cdk-nextjs 0.6.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (266) hide show
  1. package/.jsii +2467 -2714
  2. package/.jsii.tabl.json +1 -1
  3. package/API.md +1725 -1909
  4. package/CLAUDE.md +2 -1
  5. package/README.md +429 -130
  6. package/assets/lambdas/post-deploy/post-deploy.lambda/index.js +152 -170
  7. package/assets/lambdas/redeploy-stage/redeploy-stage.lambda/index.js +875 -0
  8. package/docs/adapter-runtime.md +185 -0
  9. package/docs/breaking-changes.md +687 -4
  10. package/docs/caching-guide.md +156 -112
  11. package/docs/cdk-nextjs-cfn-exec-policy.json +2 -1
  12. package/docs/development-guide.md +1 -1
  13. package/docs/harness-coverage.md +598 -0
  14. package/docs/init-cache-deployment.md +32 -1
  15. package/docs/next-build-output-guide.md +30 -20
  16. package/examples/README.md +5 -1
  17. package/lib/adapter/__fixtures__/app-playground-base-path.json +4926 -0
  18. package/lib/adapter/__fixtures__/app-playground.json +4917 -0
  19. package/lib/adapter/__fixtures__/pages-i18n.json +1728 -0
  20. package/lib/adapter/adapter.mjs +1548 -185
  21. package/lib/adapter/adapter.test.js +106 -0
  22. package/lib/adapter/aws-cache-store.d.ts +489 -0
  23. package/lib/adapter/aws-cache-store.js +1004 -0
  24. package/lib/adapter/aws-cache-store.test.d.ts +1 -0
  25. package/lib/adapter/aws-cache-store.test.js +361 -0
  26. package/lib/adapter/build-outputs.d.ts +80 -0
  27. package/lib/adapter/build-outputs.js +852 -0
  28. package/lib/adapter/build-outputs.test.d.ts +1 -0
  29. package/lib/adapter/build-outputs.test.js +861 -0
  30. package/lib/adapter/cache-handler.d.ts +9 -2
  31. package/lib/adapter/cache-handler.js +72 -96
  32. package/lib/adapter/cache-handler.mjs +18956 -17774
  33. package/lib/adapter/cache-handler.test.js +263 -31
  34. package/lib/adapter/cache-kinds.d.ts +32 -0
  35. package/lib/adapter/cache-kinds.js +35 -0
  36. package/lib/adapter/cache-kinds.test.d.ts +1 -0
  37. package/lib/adapter/cache-kinds.test.js +69 -0
  38. package/lib/adapter/cache-utils.d.ts +90 -0
  39. package/lib/adapter/cache-utils.js +199 -4
  40. package/lib/adapter/cache-utils.test.d.ts +1 -0
  41. package/lib/adapter/cache-utils.test.js +179 -0
  42. package/lib/adapter/function-groups.d.ts +215 -0
  43. package/lib/adapter/function-groups.js +1099 -0
  44. package/lib/adapter/function-groups.test.d.ts +1 -0
  45. package/lib/adapter/function-groups.test.js +743 -0
  46. package/lib/adapter/init-cache.d.ts +6 -0
  47. package/lib/adapter/init-cache.js +245 -0
  48. package/lib/adapter/init-cache.test.d.ts +1 -0
  49. package/lib/adapter/init-cache.test.js +137 -0
  50. package/lib/adapter/local-file-cache-handler.d.ts +23 -0
  51. package/lib/adapter/local-file-cache-handler.js +52 -1
  52. package/lib/adapter/memory-cache-handler.d.ts +26 -17
  53. package/lib/adapter/memory-cache-handler.js +32 -50
  54. package/lib/adapter/memory-cache-handler.test.js +105 -85
  55. package/lib/adapter/s3-cache-handler.d.ts +179 -40
  56. package/lib/adapter/s3-cache-handler.js +807 -277
  57. package/lib/adapter/s3-cache-handler.test.js +1186 -31
  58. package/lib/adapter/use-cache-common.d.ts +90 -0
  59. package/lib/adapter/use-cache-common.js +250 -0
  60. package/lib/adapter/use-cache-common.test.d.ts +1 -0
  61. package/lib/adapter/use-cache-common.test.js +646 -0
  62. package/lib/adapter/use-cache-default-handler.d.ts +24 -0
  63. package/lib/adapter/use-cache-default-handler.js +90 -0
  64. package/lib/adapter/use-cache-default-handler.mjs +38645 -0
  65. package/lib/adapter/use-cache-handlers.test.d.ts +1 -0
  66. package/lib/adapter/use-cache-handlers.test.js +349 -0
  67. package/lib/adapter/use-cache-remote-handler.d.ts +26 -0
  68. package/lib/adapter/use-cache-remote-handler.js +186 -0
  69. package/lib/{image-optimization/handler.mjs → adapter/use-cache-remote-handler.mjs} +33572 -38798
  70. package/lib/generated-structs/OptionalNextjsApiProps.d.ts +59 -0
  71. package/lib/generated-structs/OptionalNextjsApiProps.js +3 -0
  72. package/lib/generated-structs/OptionalNextjsCacheProps.d.ts +15 -6
  73. package/lib/generated-structs/OptionalNextjsCacheProps.js +1 -1
  74. package/lib/generated-structs/OptionalNextjsContainersProps.d.ts +25 -11
  75. package/lib/generated-structs/OptionalNextjsContainersProps.js +1 -1
  76. package/lib/generated-structs/OptionalNextjsDistributionProps.d.ts +31 -9
  77. package/lib/generated-structs/OptionalNextjsDistributionProps.js +1 -1
  78. package/lib/generated-structs/OptionalNextjsPostDeployProps.d.ts +13 -0
  79. package/lib/generated-structs/OptionalNextjsPostDeployProps.js +1 -1
  80. package/lib/generated-structs/OptionalPostDeployCustomResourceProperties.d.ts +11 -2
  81. package/lib/generated-structs/OptionalPostDeployCustomResourceProperties.js +1 -1
  82. package/lib/index.d.ts +6 -7
  83. package/lib/index.js +2 -4
  84. package/lib/lambdas/post-deploy/post-deploy.lambda.js +3 -2
  85. package/lib/lambdas/post-deploy/prune-cache-bucket.d.ts +7 -3
  86. package/lib/lambdas/post-deploy/prune-cache-bucket.js +57 -71
  87. package/lib/lambdas/post-deploy/prune-cache-bucket.test.d.ts +1 -0
  88. package/lib/lambdas/post-deploy/prune-cache-bucket.test.js +114 -0
  89. package/lib/lambdas/post-deploy/prune-revalidation-table.d.ts +1 -0
  90. package/lib/lambdas/post-deploy/prune-revalidation-table.js +23 -31
  91. package/lib/lambdas/post-deploy/prune-revalidation-table.test.d.ts +1 -0
  92. package/lib/lambdas/post-deploy/prune-revalidation-table.test.js +71 -0
  93. package/lib/lambdas/post-deploy/prune-s3.d.ts +19 -3
  94. package/lib/lambdas/post-deploy/prune-s3.js +54 -15
  95. package/lib/lambdas/post-deploy/prune-s3.test.d.ts +1 -0
  96. package/lib/lambdas/post-deploy/prune-s3.test.js +255 -0
  97. package/lib/lambdas/redeploy-stage/redeploy-stage-function.d.ts +13 -0
  98. package/lib/lambdas/redeploy-stage/redeploy-stage-function.js +55 -0
  99. package/lib/lambdas/redeploy-stage/redeploy-stage.d.ts +24 -0
  100. package/lib/lambdas/redeploy-stage/redeploy-stage.js +68 -0
  101. package/lib/lambdas/redeploy-stage/redeploy-stage.lambda.d.ts +20 -0
  102. package/lib/lambdas/redeploy-stage/redeploy-stage.lambda.js +24 -0
  103. package/lib/lambdas/redeploy-stage/redeploy-stage.test.d.ts +1 -0
  104. package/lib/lambdas/redeploy-stage/redeploy-stage.test.js +93 -0
  105. package/lib/nextjs-api.d.ts +107 -18
  106. package/lib/nextjs-api.js +349 -39
  107. package/lib/nextjs-api.test.js +582 -1
  108. package/lib/nextjs-build/global-containers.Dockerfile +15 -10
  109. package/lib/nextjs-build/nextjs-build.d.ts +339 -63
  110. package/lib/nextjs-build/nextjs-build.js +684 -327
  111. package/lib/nextjs-build/nextjs-build.test.d.ts +1 -0
  112. package/lib/nextjs-build/nextjs-build.test.js +412 -0
  113. package/lib/nextjs-build/patch-fetch.js +1 -1
  114. package/lib/nextjs-build/patch-fetch.test.js +166 -11
  115. package/lib/nextjs-build/regional-containers.Dockerfile +17 -10
  116. package/lib/nextjs-cache.d.ts +82 -4
  117. package/lib/nextjs-cache.js +186 -10
  118. package/lib/nextjs-cache.test.js +176 -1
  119. package/lib/nextjs-compute/nextjs-compute-base-props.d.ts +21 -8
  120. package/lib/nextjs-compute/nextjs-compute-base-props.js +41 -1
  121. package/lib/nextjs-compute/nextjs-compute-base-props.test.d.ts +1 -0
  122. package/lib/nextjs-compute/nextjs-compute-base-props.test.js +44 -0
  123. package/lib/nextjs-compute/nextjs-containers.d.ts +19 -0
  124. package/lib/nextjs-compute/nextjs-containers.js +57 -20
  125. package/lib/nextjs-compute/nextjs-functions.d.ts +122 -7
  126. package/lib/nextjs-compute/nextjs-functions.js +113 -67
  127. package/lib/nextjs-compute/nextjs-functions.test.d.ts +1 -0
  128. package/lib/nextjs-compute/nextjs-functions.test.js +99 -0
  129. package/lib/nextjs-distribution.d.ts +194 -23
  130. package/lib/nextjs-distribution.js +535 -62
  131. package/lib/nextjs-distribution.test.d.ts +1 -0
  132. package/lib/nextjs-distribution.test.js +697 -0
  133. package/lib/nextjs-post-deploy.d.ts +23 -3
  134. package/lib/nextjs-post-deploy.js +14 -10
  135. package/lib/nextjs-post-deploy.test.d.ts +1 -0
  136. package/lib/nextjs-post-deploy.test.js +34 -0
  137. package/lib/nextjs-static-assets.d.ts +23 -4
  138. package/lib/nextjs-static-assets.js +29 -6
  139. package/lib/nextjs-static-assets.test.js +20 -1
  140. package/lib/root-constructs/nextjs-base-construct.d.ts +105 -45
  141. package/lib/root-constructs/nextjs-base-construct.js +144 -34
  142. package/lib/root-constructs/nextjs-global-containers.d.ts +18 -20
  143. package/lib/root-constructs/nextjs-global-containers.js +20 -70
  144. package/lib/root-constructs/nextjs-global-functions.d.ts +26 -28
  145. package/lib/root-constructs/nextjs-global-functions.js +52 -69
  146. package/lib/root-constructs/nextjs-regional-containers.d.ts +25 -5
  147. package/lib/root-constructs/nextjs-regional-containers.js +17 -15
  148. package/lib/root-constructs/nextjs-regional-functions.d.ts +22 -18
  149. package/lib/root-constructs/nextjs-regional-functions.js +8 -25
  150. package/lib/runtime/api-gateway-path.d.ts +34 -0
  151. package/lib/runtime/api-gateway-path.js +71 -0
  152. package/lib/runtime/api-gateway-path.test.d.ts +1 -0
  153. package/lib/runtime/api-gateway-path.test.js +65 -0
  154. package/lib/runtime/case-redirect.d.ts +22 -0
  155. package/lib/runtime/case-redirect.js +63 -0
  156. package/lib/runtime/case-redirect.test.d.ts +1 -0
  157. package/lib/runtime/case-redirect.test.js +32 -0
  158. package/lib/runtime/core.d.ts +234 -0
  159. package/lib/runtime/core.js +1213 -0
  160. package/lib/runtime/core.test.d.ts +1 -0
  161. package/lib/runtime/core.test.js +1678 -0
  162. package/lib/runtime/deployment-root.d.ts +13 -0
  163. package/lib/runtime/deployment-root.js +29 -0
  164. package/lib/runtime/dispatch.d.ts +331 -0
  165. package/lib/runtime/dispatch.js +751 -0
  166. package/lib/runtime/dispatch.test.d.ts +1 -0
  167. package/lib/runtime/dispatch.test.js +853 -0
  168. package/lib/runtime/entrypoints.d.ts +57 -0
  169. package/lib/runtime/entrypoints.js +115 -0
  170. package/lib/runtime/http/abort-signal.d.ts +6 -0
  171. package/lib/runtime/http/abort-signal.js +19 -0
  172. package/lib/runtime/http/abort-signal.test.d.ts +1 -0
  173. package/lib/runtime/http/abort-signal.test.js +49 -0
  174. package/lib/runtime/http/node-server.d.ts +38 -0
  175. package/lib/runtime/http/node-server.js +99 -0
  176. package/lib/runtime/http/node-server.test.d.ts +1 -0
  177. package/lib/runtime/http/node-server.test.js +96 -0
  178. package/lib/runtime/http/node-sink.d.ts +16 -0
  179. package/lib/runtime/http/node-sink.js +48 -0
  180. package/lib/runtime/http/node-sink.test.d.ts +1 -0
  181. package/lib/runtime/http/node-sink.test.js +66 -0
  182. package/lib/runtime/http/request.d.ts +62 -0
  183. package/lib/runtime/http/request.js +134 -0
  184. package/lib/runtime/http/request.test.d.ts +1 -0
  185. package/lib/runtime/http/request.test.js +103 -0
  186. package/lib/runtime/http/response.d.ts +77 -0
  187. package/lib/runtime/http/response.js +229 -0
  188. package/lib/runtime/http/response.test.d.ts +1 -0
  189. package/lib/runtime/http/response.test.js +178 -0
  190. package/lib/runtime/http/sink.d.ts +73 -0
  191. package/lib/runtime/http/sink.js +188 -0
  192. package/lib/runtime/http/sink.test.d.ts +1 -0
  193. package/lib/runtime/http/sink.test.js +257 -0
  194. package/lib/runtime/image-utils.d.ts +78 -0
  195. package/lib/runtime/image-utils.js +129 -0
  196. package/lib/runtime/image-utils.test.d.ts +1 -0
  197. package/lib/runtime/image-utils.test.js +237 -0
  198. package/lib/runtime/image.d.ts +76 -0
  199. package/lib/runtime/image.js +296 -0
  200. package/lib/runtime/image.test.d.ts +1 -0
  201. package/lib/runtime/image.test.js +405 -0
  202. package/lib/runtime/lambda-event.d.ts +4 -0
  203. package/lib/runtime/lambda-event.js +113 -0
  204. package/lib/runtime/lambda-event.test.d.ts +1 -0
  205. package/lib/runtime/lambda-event.test.js +119 -0
  206. package/lib/runtime/lambda.mjs +41595 -0
  207. package/lib/runtime/load-module.d.ts +8 -0
  208. package/lib/runtime/load-module.js +35 -0
  209. package/lib/runtime/manifest.d.ts +215 -0
  210. package/lib/runtime/manifest.js +118 -0
  211. package/lib/runtime/middleware.d.ts +43 -0
  212. package/lib/runtime/middleware.js +113 -0
  213. package/lib/runtime/middleware.test.d.ts +1 -0
  214. package/lib/runtime/middleware.test.js +259 -0
  215. package/lib/runtime/next-modules.d.ts +55 -0
  216. package/lib/runtime/next-modules.js +124 -0
  217. package/lib/runtime/next-modules.test.d.ts +1 -0
  218. package/lib/runtime/next-modules.test.js +34 -0
  219. package/lib/runtime/public-files.d.ts +32 -0
  220. package/lib/runtime/public-files.js +117 -0
  221. package/lib/runtime/public-files.test.d.ts +1 -0
  222. package/lib/runtime/public-files.test.js +97 -0
  223. package/lib/runtime/server.mjs +41588 -0
  224. package/lib/runtime/static-files.d.ts +50 -0
  225. package/lib/runtime/static-files.js +266 -0
  226. package/lib/runtime/static-files.test.d.ts +1 -0
  227. package/lib/runtime/static-files.test.js +118 -0
  228. package/lib/runtime/util.d.ts +28 -0
  229. package/lib/runtime/util.js +79 -0
  230. package/lib/utils/base-path.d.ts +123 -11
  231. package/lib/utils/base-path.js +276 -39
  232. package/lib/utils/base-path.test.js +275 -50
  233. package/lib/utils/get-architecture.d.ts +7 -8
  234. package/lib/utils/get-architecture.js +12 -13
  235. package/lib/utils/zip-directory.d.ts +14 -0
  236. package/lib/utils/zip-directory.js +121 -0
  237. package/lib/utils/zip-directory.test.d.ts +1 -0
  238. package/lib/utils/zip-directory.test.js +99 -0
  239. package/package.json +22 -3
  240. package/scripts/capture-adapter-fixture.mjs +325 -0
  241. package/scripts/e2e-deploy.sh +398 -0
  242. package/scripts/e2e-harness/README.md +707 -0
  243. package/scripts/e2e-harness/app.js +370 -0
  244. package/scripts/e2e-harness/common.sh +249 -0
  245. package/scripts/e2e-harness/screen.mjs +302 -0
  246. package/scripts/e2e-harness/stage-proxy.mjs +145 -0
  247. package/scripts/e2e-harness/type-filters.mjs +47 -0
  248. package/scripts/e2e-logs.sh +75 -0
  249. package/scripts/e2e-offline.sh +91 -0
  250. package/scripts/e2e-sweep.sh +370 -0
  251. package/scripts/e2e-warm.sh +114 -0
  252. package/scripts/zero-config-build.mjs +418 -0
  253. package/docs/1k-concurrent-users-executions.png +0 -0
  254. package/docs/plans/adapter-runtime-release.md +0 -362
  255. package/docs/plans/phase-0-image-function-opt-in.md +0 -295
  256. package/lib/generated-structs/OptionalDockerImageFunctionProps.d.ts +0 -425
  257. package/lib/generated-structs/OptionalDockerImageFunctionProps.js +0 -3
  258. package/lib/image-optimization/handler-utils.d.ts +0 -34
  259. package/lib/image-optimization/handler-utils.js +0 -83
  260. package/lib/image-optimization/handler-utils.test.js +0 -178
  261. package/lib/nextjs-build/functions.Dockerfile +0 -31
  262. package/lib/nextjs-compute/nextjs-image-function.d.ts +0 -53
  263. package/lib/nextjs-compute/nextjs-image-function.js +0 -59
  264. package/lib/utils/experimental-flags.d.ts +0 -24
  265. package/lib/utils/experimental-flags.js +0 -30
  266. /package/lib/{image-optimization/handler-utils.test.d.ts → adapter/adapter.test.d.ts} +0 -0
@@ -0,0 +1,853 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ /* eslint-disable import/no-extraneous-dependencies */
7
+ const node_fs_1 = require("node:fs");
8
+ const node_os_1 = require("node:os");
9
+ const node_path_1 = require("node:path");
10
+ const dispatch_1 = require("./dispatch");
11
+ const public_files_1 = require("./public-files");
12
+ const app_playground_base_path_json_1 = __importDefault(require("../adapter/__fixtures__/app-playground-base-path.json"));
13
+ const app_playground_json_1 = __importDefault(require("../adapter/__fixtures__/app-playground.json"));
14
+ const pages_i18n_json_1 = __importDefault(require("../adapter/__fixtures__/pages-i18n.json"));
15
+ const build_outputs_1 = require("../adapter/build-outputs");
16
+ /**
17
+ * Dispatch is tested against the manifests that step 1 produces from real
18
+ * `onBuildComplete` captures, rather than against hand-written manifests: the
19
+ * thing most likely to break is the correspondence between how the build keys
20
+ * `entrypoints` and how `resolveRoutes` reports `resolvedPathname`, and a
21
+ * hand-written manifest would assume that correspondence instead of proving it.
22
+ */
23
+ function manifestOf(fixture) {
24
+ const warn = jest.spyOn(console, "warn").mockImplementation(() => { });
25
+ try {
26
+ const ctx = structuredClone(fixture);
27
+ // The fixtures' project dirs are synthetic `/repo/…` paths, so the build cwd
28
+ // has to be stated; see `assertBuildCwd`.
29
+ return (0, build_outputs_1.buildAdapterManifest)(ctx, { buildCwd: ctx.projectDir }).manifest;
30
+ }
31
+ finally {
32
+ warn.mockRestore();
33
+ }
34
+ }
35
+ /**
36
+ * The fixture with `app/params/optional/[[...rest]]` moved to `app/[[...rest]]`,
37
+ * a root optional catch-all: a route every request not claimed earlier falls
38
+ * into, `/_next/image` included unless dispatch puts it ahead of them. No example
39
+ * app has one, and a capture would add a whole app to cover one route, so the
40
+ * route is moved rather than captured.
41
+ */
42
+ function withRootCatchAll(fixture) {
43
+ return JSON.parse(JSON.stringify(fixture)
44
+ .split("/params/optional/[[...rest]]")
45
+ .join("/[[...rest]]")
46
+ .split("[/]?/params/optional(?:")
47
+ .join("[/]?(?:"));
48
+ }
49
+ const manifests = {
50
+ "app-playground": manifestOf(app_playground_json_1.default),
51
+ "app-playground-base-path": manifestOf(app_playground_base_path_json_1.default),
52
+ "app-playground-root-catch-all": manifestOf(withRootCatchAll(app_playground_json_1.default)),
53
+ "app-playground-base-path-root-catch-all": manifestOf(withRootCatchAll(app_playground_base_path_json_1.default)),
54
+ "pages-i18n": manifestOf(pages_i18n_json_1.default),
55
+ };
56
+ const ORIGIN = "https://example.test";
57
+ function request(url, headers = {}) {
58
+ const result = {
59
+ method: "GET",
60
+ url: new URL(url, ORIGIN),
61
+ headers: new Headers({ host: "example.test", ...headers }),
62
+ // GET/HEAD have no body, but `resolveRoutes` requires a stream.
63
+ body: new ReadableStream({
64
+ start(controller) {
65
+ controller.close();
66
+ },
67
+ }),
68
+ // Middleware that lets every request through.
69
+ invokeMiddleware: async () => ({ response: new Response() }),
70
+ };
71
+ return result;
72
+ }
73
+ /** A Dispatcher over `name`, whose middleware, if given, answers `middleware()`. */
74
+ function dispatcherFor(name, middleware) {
75
+ const dispatcher = new dispatch_1.Dispatcher({ manifest: manifests[name] });
76
+ return {
77
+ notFoundFor: dispatcher.notFoundFor,
78
+ dispatch: (req) => dispatcher.dispatch(middleware
79
+ ? {
80
+ ...req,
81
+ invokeMiddleware: async () => ({
82
+ ...(await middleware()),
83
+ response: new Response(),
84
+ }),
85
+ }
86
+ : req),
87
+ };
88
+ }
89
+ /** The 404 or 500 a request with no locale gets. */
90
+ function statusTargetOf(manifest, status) {
91
+ return (0, dispatch_1.statusTargets)(manifest, status)(undefined);
92
+ }
93
+ describe("Dispatcher entrypoint resolution", () => {
94
+ it("resolves a dynamic App Router page to its template entrypoint", async () => {
95
+ const result = await dispatcherFor("app-playground").dispatch(request("/isr/1"));
96
+ expect(result.kind).toBe("entrypoint");
97
+ if (result.kind !== "entrypoint")
98
+ return;
99
+ // `resolvedPathname` is the template; `invocationTarget` is concrete. Both
100
+ // are needed: the first picks the module, the second is what it renders.
101
+ expect(result.resolvedPathname).toBe("/isr/[id]");
102
+ expect(result.invocationTarget).toEqual({
103
+ pathname: "/isr/1",
104
+ query: { nxtPid: "1" },
105
+ });
106
+ expect(result.entrypoint.filePath).toContain("isr/[id]/page.js");
107
+ expect(result.entrypoint.type).toBe("app-page");
108
+ });
109
+ it("resolves an App Router route handler", async () => {
110
+ const result = await dispatcherFor("app-playground").dispatch(request("/api/health"));
111
+ expect(result.kind).toBe("entrypoint");
112
+ if (result.kind !== "entrypoint")
113
+ return;
114
+ expect(result.entrypoint.type).toBe("app-route");
115
+ expect(result.resolvedPathname).toBe("/api/health");
116
+ });
117
+ it("matches basePath-prefixed entrypoint keys without normalization", async () => {
118
+ // Step 1 keyed `entrypoints` by the basePath-prefixed `output.pathname` and
119
+ // left open whether `resolvedPathname` comes back prefixed. It does — this
120
+ // test is what closes that question.
121
+ const dispatcher = dispatcherFor("app-playground-base-path");
122
+ const result = await dispatcher.dispatch(request("/prod/isr/1"));
123
+ expect(result.kind).toBe("entrypoint");
124
+ if (result.kind !== "entrypoint")
125
+ return;
126
+ expect(result.resolvedPathname).toBe("/prod/isr/[id]");
127
+ expect(result.invocationTarget.pathname).toBe("/prod/isr/1");
128
+ // The same path without the prefix is not the app's.
129
+ const unprefixed = await dispatcher.dispatch(request("/isr/1"));
130
+ expect(unprefixed.kind).toBe("not-found");
131
+ });
132
+ it("resolves a Pages Router page and API route", async () => {
133
+ const dispatcher = dispatcherFor("pages-i18n");
134
+ const page = await dispatcher.dispatch(request("/en-US/ssr"));
135
+ expect(page.kind).toBe("entrypoint");
136
+ if (page.kind === "entrypoint") {
137
+ expect(page.entrypoint.type).toBe("page");
138
+ }
139
+ const api = await dispatcher.dispatch(request("/api/hello"));
140
+ expect(api.kind).toBe("entrypoint");
141
+ if (api.kind === "entrypoint") {
142
+ expect(api.entrypoint.type).toBe("page-api");
143
+ }
144
+ });
145
+ it("resolves a Pages Router ISR data URL via its prerender template", async () => {
146
+ // This only works because `buildAdapterManifest` adds dynamic *prerender*
147
+ // templates to `pathnames`/`entrypoints`: `/_next/data/…/[slug].json` is
148
+ // not a route output, so without it this URL 404s while `next start` serves
149
+ // it.
150
+ const { buildId } = manifests["pages-i18n"];
151
+ const result = await dispatcherFor("pages-i18n").dispatch(request(`/_next/data/${buildId}/fr/blog/hello.json`));
152
+ expect(result.kind).toBe("entrypoint");
153
+ if (result.kind !== "entrypoint")
154
+ return;
155
+ expect(result.resolvedPathname).toBe(`/_next/data/${buildId}/fr/blog/[slug].json`);
156
+ expect(result.entrypoint.filePath).toContain("blog/[slug]");
157
+ expect(result.invocationTarget.query).toMatchObject({ nxtPslug: "hello" });
158
+ });
159
+ it("resolves the canonical trailing-slash URL of a `trailingSlash` app", async () => {
160
+ // The build's pathnames never carry the slash, but `trailingSlash: true`
161
+ // makes `/a/` the URL Next.js's own 308 sends browsers to, and
162
+ // `@next/routing` matches pathnames by exact equality. Measured against
163
+ // next.js's `test/e2e/app-dir/trailingslash`: without this, 6 of 8 cases
164
+ // failed, including `fetch('/api/revalidate')` getting the 404 page.
165
+ const withSlash = structuredClone(app_playground_json_1.default);
166
+ withSlash.config.trailingSlash = true;
167
+ // All three captures are from apps with the default `trailingSlash: false`,
168
+ // so their `beforeMiddleware` carries the *strip*-slash 308 (`/a/` → `/a`).
169
+ // Leaving it in would make the clone incoherent — that redirect is what a
170
+ // real `trailingSlash: true` build replaces with the add-slash one — and it
171
+ // fires before any pathname is matched, so nothing below would be reached.
172
+ const routing = withSlash.routing;
173
+ routing.beforeMiddleware = routing.beforeMiddleware.filter((route) => route.status !== 308);
174
+ const dispatcher = new dispatch_1.Dispatcher({
175
+ manifest: manifestOf(withSlash),
176
+ });
177
+ const page = await dispatcher.dispatch(request("/isr/1/"));
178
+ expect(page.kind).toBe("entrypoint");
179
+ if (page.kind !== "entrypoint")
180
+ return;
181
+ // Normalized on the way out, because `entrypoints` is keyed without the
182
+ // slash and the render has to land on its prerender's cache key.
183
+ expect(page.resolvedPathname).toBe("/isr/[id]");
184
+ expect(page.invocationTarget).toEqual({
185
+ pathname: "/isr/1",
186
+ query: { nxtPid: "1" },
187
+ });
188
+ const route = await dispatcher.dispatch(request("/api/health/"));
189
+ expect(route.kind).toBe("entrypoint");
190
+ if (route.kind === "entrypoint") {
191
+ expect(route.resolvedPathname).toBe("/api/health");
192
+ }
193
+ // A static file keeps its extension-bearing pathname: Next.js compiles the
194
+ // *opposite* redirect for those, and shadowing it would serve `/x.js/`.
195
+ const asset = await dispatcher.dispatch(request("/favicon.ico"));
196
+ expect(asset.kind).toBe("static-file");
197
+ expect(await dispatcher.dispatch(request("/favicon.ico/"))).toMatchObject({
198
+ kind: "not-found",
199
+ });
200
+ });
201
+ it("gives a param whose name prefixes another param's its own value", async () => {
202
+ // `@next/routing` expands `$nxtPid2` by replacing group names in insertion
203
+ // order, so the `$nxtPid` prefix wins and leaves a literal `2`: the route is
204
+ // invoked with `nxtPid2=a2`. `repairRouteParamQuery` corrects it from
205
+ // `routeMatches`. Measured against `test/e2e/app-dir/use-params`, whose
206
+ // fixture is `app/[id]/[id2]/page.tsx`; app-playground's
207
+ // `app/params/prefix/[id]/[id2]` is the same shape.
208
+ const result = await dispatcherFor("app-playground").dispatch(request("/params/prefix/a/b"));
209
+ expect(result.kind).toBe("entrypoint");
210
+ if (result.kind !== "entrypoint")
211
+ return;
212
+ expect(result.resolvedPathname).toBe("/params/prefix/[id]/[id2]");
213
+ expect(result.invocationTarget).toEqual({
214
+ pathname: "/params/prefix/a/b",
215
+ query: { nxtPid: "a", nxtPid2: "b" },
216
+ });
217
+ expect(result.invocationTarget.query).toEqual({
218
+ nxtPid: "a",
219
+ nxtPid2: "b",
220
+ });
221
+ });
222
+ it("applies a gated beforeFiles rewrite from next.config.ts once", async () => {
223
+ // app-playground's one config rewrite: `/e2e/rewrite/:path(.*)` with
224
+ // `has: query json=true`, to `/e2e/rewrite/echo?from=/:path`. Its output
225
+ // matches it again, which is what Next.js re-applies inside the entrypoint
226
+ // - the Dispatcher's half is resolving it exactly once.
227
+ const dispatcher = dispatcherFor("app-playground");
228
+ const rewritten = await dispatcher.dispatch(request("/e2e/rewrite/some/route?json=true"));
229
+ expect(rewritten.kind).toBe("entrypoint");
230
+ if (rewritten.kind !== "entrypoint")
231
+ return;
232
+ expect(rewritten.resolvedPathname).toBe("/e2e/rewrite/echo");
233
+ expect(rewritten.invocationTarget.query).toMatchObject({
234
+ from: "/some/route",
235
+ json: "true",
236
+ });
237
+ // Without the `has` condition the rule does not fire and nothing else
238
+ // serves the path.
239
+ expect(await dispatcher.dispatch(request("/e2e/rewrite/some/route"))).toMatchObject({ kind: "not-found" });
240
+ });
241
+ });
242
+ describe("Dispatcher public/ files", () => {
243
+ /**
244
+ * A real `public/` on disk, listed by the same `readPublicFiles` the runtime
245
+ * calls at cold start, so the spellings under test are the ones the lister
246
+ * and the routing table actually produce between them.
247
+ */
248
+ function publicDir(files) {
249
+ const dir = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), "cdk-nextjs-dispatch-public-"));
250
+ for (const file of files) {
251
+ (0, node_fs_1.mkdirSync)((0, node_path_1.dirname)((0, node_path_1.join)(dir, file)), { recursive: true });
252
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(dir, file), file);
253
+ }
254
+ return (0, public_files_1.readPublicFiles)(dir);
255
+ }
256
+ function dispatcherWithPublic(name, files) {
257
+ return new dispatch_1.Dispatcher({
258
+ manifest: manifests[name],
259
+ publicFiles: publicDir(files),
260
+ });
261
+ }
262
+ it.each([
263
+ // A space is encoded by every client, so the two spellings agree.
264
+ ["static/hello e2e.png", ["/static/hello%20e2e.png"]],
265
+ // These a browser sends as written, and `encodeURIComponent` does not.
266
+ ["images/logo@2x.png", ["/images/logo@2x.png", "/images/logo%402x.png"]],
267
+ ["c++.svg", ["/c++.svg", "/c%2B%2B.svg"]],
268
+ ["icon[1].png", ["/icon[1].png", "/icon%5B1%5D.png"]],
269
+ ["Q&A.pdf", ["/Q&A.pdf", "/Q%26A.pdf"]],
270
+ // A literal `%` can only be requested escaped.
271
+ ["100%.png", ["/100%25.png"]],
272
+ ["фото/a.jpg", ["/%D1%84%D0%BE%D1%82%D0%BE/a.jpg"]],
273
+ ])("serves public/%s under every spelling a link can have", async (file, urls) => {
274
+ const dispatcher = dispatcherWithPublic("app-playground", [file]);
275
+ for (const url of urls) {
276
+ expect(await dispatcher.dispatch(request(url))).toMatchObject({
277
+ kind: "static-file",
278
+ source: "public",
279
+ filePath: `app-playground/public/${file}`,
280
+ });
281
+ }
282
+ });
283
+ it("serves public/ ahead of an app route at the same pathname", async () => {
284
+ // `app/favicon.ico` is a build output here; `next start` checks public/
285
+ // before app and page routes, so a leftover `public/favicon.ico` wins.
286
+ const result = await dispatcherWithPublic("app-playground", [
287
+ "favicon.ico",
288
+ ]).dispatch(request("/favicon.ico"));
289
+ expect(result).toMatchObject({
290
+ kind: "static-file",
291
+ filePath: "app-playground/public/favicon.ico",
292
+ });
293
+ });
294
+ it("still serves the build output when public/ has no file there", async () => {
295
+ const result = await dispatcherWithPublic("app-playground", []).dispatch(request("/favicon.ico"));
296
+ expect(result).toMatchObject({ kind: "static-file", source: "server" });
297
+ });
298
+ it("serves public/ under basePath", async () => {
299
+ const dispatcher = dispatcherWithPublic("app-playground-base-path", [
300
+ "test.txt",
301
+ ]);
302
+ expect(await dispatcher.dispatch(request("/prod/test.txt"))).toMatchObject({
303
+ kind: "static-file",
304
+ filePath: "app-playground/public/test.txt",
305
+ });
306
+ expect((await dispatcher.dispatch(request("/test.txt"))).kind).not.toBe("static-file");
307
+ });
308
+ it("serves public/ in an i18n app, bare and under a default locale only", async () => {
309
+ // `resolveRoutes` prefixes the locale before it matches, so `/test.txt` is
310
+ // looked up as `/en-US/test.txt`. `next start` strips the default locale,
311
+ // and each domain's, off a public/ request - `fr` is example.fr's - and no
312
+ // other.
313
+ const dispatcher = dispatcherWithPublic("pages-i18n", ["test.txt"]);
314
+ for (const url of ["/test.txt", "/en-US/test.txt", "/fr/test.txt"]) {
315
+ expect(await dispatcher.dispatch(request(url))).toMatchObject({
316
+ kind: "static-file",
317
+ filePath: "pages-i18n/public/test.txt",
318
+ });
319
+ }
320
+ expect((await dispatcher.dispatch(request("/nl-NL/test.txt"))).kind).not.toBe("static-file");
321
+ });
322
+ it("knows nothing of public/ when the deployment has none", async () => {
323
+ // The Lambda types: CloudFront or API Gateway answers public/ from S3, the
324
+ // package does not carry it, and a request that got through anyway takes
325
+ // the ordinary not-found path, middleware request headers and all.
326
+ expect(await dispatcherFor("app-playground").dispatch(request("/test.txt"))).toMatchObject({ kind: "not-found" });
327
+ });
328
+ });
329
+ describe("Dispatcher build-output spellings", () => {
330
+ it("serves a _next/static file whose name the HTML percent-encodes", async () => {
331
+ // webpack names an App Router chunk after its route segment, brackets and
332
+ // all, and Next.js reports the pathname unencoded; the `<script>` tag in
333
+ // the HTML asks for `%5Bid%5D`.
334
+ const base = manifests["app-playground"];
335
+ const pathname = "/_next/static/chunks/app/isr/[id]/page-0123abcd.js";
336
+ const filePath = "app-playground/.next/static/chunks/app/isr/[id]/page-0123abcd.js";
337
+ const manifest = {
338
+ ...base,
339
+ staticFiles: { ...base.staticFiles, [pathname]: filePath },
340
+ pathnames: [...base.pathnames, pathname],
341
+ };
342
+ const dispatcher = new dispatch_1.Dispatcher({
343
+ manifest,
344
+ });
345
+ for (const url of [
346
+ "/_next/static/chunks/app/isr/%5Bid%5D/page-0123abcd.js",
347
+ pathname,
348
+ ]) {
349
+ expect(await dispatcher.dispatch(request(url))).toMatchObject({
350
+ kind: "static-file",
351
+ source: "next-static",
352
+ filePath,
353
+ });
354
+ }
355
+ });
356
+ });
357
+ describe("Dispatcher non-entrypoint outcomes", () => {
358
+ it("serves a build asset as a static file with its immutable cache header", async () => {
359
+ const manifest = manifests["app-playground"];
360
+ const pathname = Object.keys(manifest.staticFiles).find((file) => file.startsWith("/_next/static/"));
361
+ const result = await dispatcherFor("app-playground").dispatch(request(pathname));
362
+ expect(result.kind).toBe("static-file");
363
+ if (result.kind !== "static-file")
364
+ return;
365
+ expect(result.pathname).toBe(pathname);
366
+ expect(result.responseHeaders.get("cache-control")).toBe("public,max-age=31536000,immutable");
367
+ });
368
+ it("routes /_next/image to the optimizer, basePath included", async () => {
369
+ const query = "?url=%2Ffoo.png&w=640&q=75";
370
+ const plain = await dispatcherFor("app-playground").dispatch(request(`/_next/image${query}`));
371
+ expect(plain.kind).toBe("image-optimization");
372
+ const prefixed = await dispatcherFor("app-playground-base-path").dispatch(request(`/prod/_next/image${query}`));
373
+ expect(prefixed.kind).toBe("image-optimization");
374
+ if (prefixed.kind !== "image-optimization")
375
+ return;
376
+ expect(prefixed.url.searchParams.get("url")).toBe("/foo.png");
377
+ });
378
+ it("routes /_next/image to the optimizer ahead of a root catch-all", async () => {
379
+ const query = "?url=%2Ffoo.png&w=640&q=75";
380
+ const catchAll = dispatcherFor("app-playground-root-catch-all");
381
+ const image = await catchAll.dispatch(request(`/_next/image${query}`));
382
+ expect(image.kind).toBe("image-optimization");
383
+ if (image.kind !== "image-optimization")
384
+ return;
385
+ expect(image.url.searchParams.get("url")).toBe("/foo.png");
386
+ // The catch-all itself still takes everything else.
387
+ const page = await catchAll.dispatch(request("/a/b"));
388
+ expect(page.kind).toBe("entrypoint");
389
+ if (page.kind !== "entrypoint")
390
+ return;
391
+ expect(page.resolvedPathname).toBe("/[[...rest]]");
392
+ const prefixedCatchAll = dispatcherFor("app-playground-base-path-root-catch-all");
393
+ const prefixed = await prefixedCatchAll.dispatch(request(`/prod/_next/image${query}`));
394
+ expect(prefixed.kind).toBe("image-optimization");
395
+ // Without which the image assertion would pass on a fixture with no
396
+ // catch-all at all.
397
+ const prefixedPage = await prefixedCatchAll.dispatch(request("/prod/a/b"));
398
+ expect(prefixedPage.kind).toBe("entrypoint");
399
+ if (prefixedPage.kind !== "entrypoint")
400
+ return;
401
+ expect(prefixedPage.resolvedPathname).toBe("/prod/[[...rest]]");
402
+ });
403
+ it("optimizes the destination of a next.config rewrite onto /_next/image", async () => {
404
+ const manifest = manifests["app-playground-root-catch-all"];
405
+ const routing = manifest.routing;
406
+ const result = await new dispatch_1.Dispatcher({
407
+ manifest: {
408
+ ...manifest,
409
+ routing: {
410
+ ...routing,
411
+ beforeFiles: [
412
+ {
413
+ source: "/avatar/:id",
414
+ sourceRegex: "^\\/avatar(?:\\/([^\\/]+?))(?:\\/)?$",
415
+ destination: "/_next/image?url=%2Favatars%2F$1.png&w=64&q=75",
416
+ },
417
+ ...routing.beforeFiles,
418
+ ],
419
+ },
420
+ },
421
+ }).dispatch(request("/avatar/42"));
422
+ expect(result.kind).toBe("image-optimization");
423
+ if (result.kind !== "image-optimization")
424
+ return;
425
+ expect(result.url.pathname).toBe("/_next/image");
426
+ expect(result.url.searchParams.get("url")).toBe("/avatars/42.png");
427
+ expect(result.url.searchParams.get("w")).toBe("64");
428
+ });
429
+ it("redirects a trailing slash", async () => {
430
+ const result = await dispatcherFor("app-playground").dispatch(request("/isr/1/"));
431
+ expect(result).toMatchObject({
432
+ kind: "redirect",
433
+ status: 308,
434
+ location: "/isr/1",
435
+ });
436
+ });
437
+ it("serves the app's root in the default locale, with no redirect at all", async () => {
438
+ // `resolveRoutes` prefixes the locale as `${basePath}/${locale}${pathname}`,
439
+ // which turns the root into `/en-US/`, and the slash-stripping 308 every
440
+ // build compiles then answered `GET /` with a redirect no `next start`
441
+ // sends. Measured against `test/e2e/i18n-support-catchall`, whose `/` is a
442
+ // 200. See `Dispatcher.withRootLocale`.
443
+ const result = await dispatcherFor("pages-i18n").dispatch(request("/"));
444
+ expect(result).toMatchObject({ kind: "static-file", pathname: "/en-US" });
445
+ });
446
+ it("redirects the root to the locale the request asked for", async () => {
447
+ const result = await dispatcherFor("pages-i18n").dispatch(request("/", { "accept-language": "nl-NL" }));
448
+ // 307 and not 308, because the next request may detect a different locale.
449
+ // Relative and without the trailing slash `resolveRoutes` puts in the
450
+ // location it builds (`https://example.test/nl-NL/`), which is what
451
+ // `next start` sends and what a test asserting `headers.location` reads.
452
+ expect(result).toMatchObject({
453
+ kind: "redirect",
454
+ status: 307,
455
+ location: "/nl-NL",
456
+ });
457
+ });
458
+ it("keeps a redirect to another locale's domain absolute", async () => {
459
+ // The fixture maps `fr` onto example.fr, and an absolute location is the
460
+ // only way to leave the origin.
461
+ const result = await dispatcherFor("pages-i18n").dispatch(request("/", { cookie: "NEXT_LOCALE=fr" }));
462
+ expect(result).toMatchObject({
463
+ kind: "redirect",
464
+ status: 307,
465
+ location: "https://example.fr/",
466
+ });
467
+ });
468
+ it("serves the root of a `trailingSlash` i18n app with no redirect", async () => {
469
+ // With `trailingSlash: true`, `next build` compiles the slash-*adding* 308
470
+ // (`load-custom-routes`' `/:notfile(...)` → `/:notfile/`, `locale: false`)
471
+ // in place of the stripping one, and prefixing the root as `/en-US` made
472
+ // that rule answer `GET /` with a 308 to `/en-US/`, where `next start`
473
+ // answers 200.
474
+ const withSlash = structuredClone(pages_i18n_json_1.default);
475
+ withSlash.config.trailingSlash = true;
476
+ const routing = withSlash.routing;
477
+ routing.beforeMiddleware = [
478
+ {
479
+ source: "/:notfile((?!\\.well-known(?:/.*)?)(?:[^/]+/)*[^/\\.]+)",
480
+ sourceRegex: "^(?:\\/((?!\\.well-known(?:\\/.*)?)(?:[^\\/]+\\/)*[^\\/\\.]+))$",
481
+ headers: { Location: "/$1/" },
482
+ status: 308,
483
+ priority: true,
484
+ },
485
+ ...routing.beforeMiddleware.filter((route) => route.status !== 308),
486
+ ];
487
+ const dispatcher = new dispatch_1.Dispatcher({ manifest: manifestOf(withSlash) });
488
+ expect(await dispatcher.dispatch(request("/"))).toMatchObject({
489
+ kind: "static-file",
490
+ pathname: "/en-US",
491
+ });
492
+ // The rule itself is live: the slashless locale root still gets it.
493
+ expect(await dispatcher.dispatch(request("/en-US"))).toMatchObject({
494
+ kind: "redirect",
495
+ status: 308,
496
+ location: "/en-US/",
497
+ });
498
+ });
499
+ it("still strips a trailing slash the request itself carried", async () => {
500
+ const result = await dispatcherFor("pages-i18n").dispatch(request("/nl-NL/"));
501
+ expect(result).toMatchObject({
502
+ kind: "redirect",
503
+ status: 308,
504
+ location: "/nl-NL",
505
+ });
506
+ });
507
+ it("returns a direct response for a route that forces a status", async () => {
508
+ const base = manifests["app-playground"];
509
+ const manifest = {
510
+ ...base,
511
+ middleware: null,
512
+ routing: {
513
+ ...base.routing,
514
+ beforeFiles: [
515
+ {
516
+ sourceRegex: "^/blocked$",
517
+ status: 403,
518
+ headers: { "x-why": "no" },
519
+ },
520
+ ],
521
+ },
522
+ };
523
+ const result = await new dispatch_1.Dispatcher({ manifest }).dispatch(request("/blocked"));
524
+ expect(result).toMatchObject({ kind: "response", status: 403 });
525
+ expect(result.responseHeaders.get("x-why")).toBe("no");
526
+ });
527
+ it("reports an unknown path as not found", async () => {
528
+ const result = await dispatcherFor("app-playground").dispatch(request("/definitely-not-a-route"));
529
+ expect(result.kind).toBe("not-found");
530
+ if (result.kind !== "not-found")
531
+ return;
532
+ expect(result.pathname).toBe("/definitely-not-a-route");
533
+ });
534
+ it("resolves the 404 target per router flavor", () => {
535
+ expect(statusTargetOf(manifests["app-playground"], 404)).toMatchObject({
536
+ kind: "entrypoint",
537
+ pathname: "/_not-found",
538
+ });
539
+ expect(statusTargetOf(manifests["app-playground-base-path"], 404)).toMatchObject({
540
+ kind: "entrypoint",
541
+ pathname: "/prod/_not-found",
542
+ });
543
+ // Pages Router has no `/_not-found`, and `next build` prerenders its 404 —
544
+ // one per locale — which `next start` serves ahead of `/_error`.
545
+ expect(statusTargetOf(manifests["pages-i18n"], 404)).toEqual({
546
+ kind: "static-file",
547
+ pathname: "/en-US/404",
548
+ filePath: manifests["pages-i18n"].staticFiles["/en-US/404"],
549
+ });
550
+ });
551
+ it("serves the prerendered 404 of the request's locale", () => {
552
+ // Every Pages build has `/_error`, so checking it first made the
553
+ // prerendered 404 — the app's `pages/404.js` — dead code; and under i18n
554
+ // the prerender is only ever keyed by locale, never as a bare `/404`.
555
+ const dispatcher = dispatcherFor("pages-i18n");
556
+ const { staticFiles } = manifests["pages-i18n"];
557
+ const at = (url) => dispatcher.notFoundFor(new URL(url, ORIGIN));
558
+ expect(at("/fr/nope")).toMatchObject({ filePath: staticFiles["/fr/404"] });
559
+ expect(at("/NL-nl/nope")).toMatchObject({
560
+ filePath: staticFiles["/nl-NL/404"],
561
+ });
562
+ expect(at("/nope")).toMatchObject({ filePath: staticFiles["/en-US/404"] });
563
+ // No locale in the path: the domain's default, as `next start` renders it.
564
+ expect(at("https://example.fr/nope")).toMatchObject({
565
+ filePath: staticFiles["/fr/404"],
566
+ });
567
+ });
568
+ it("falls back to /_error when no 404 was prerendered", () => {
569
+ // What a `pages/_app.js` with `getInitialProps` builds without a
570
+ // `pages/404.js`: `next build` then prerenders no 404 at all.
571
+ const base = manifests["pages-i18n"];
572
+ const without404 = Object.fromEntries(Object.entries(base.staticFiles).filter(([key]) => !key.endsWith("/404")));
573
+ expect(statusTargetOf({ ...base, staticFiles: without404 }, 404)).toMatchObject({ kind: "entrypoint", pathname: "/_error" });
574
+ });
575
+ it("prefers an invocable custom /404 over /_error", () => {
576
+ // What `pages/404.js` plus a `pages/_app.js` with `getInitialProps` builds:
577
+ // the 404 cannot be prerendered, so it arrives as an entrypoint beside
578
+ // `/_error`. Serving `/_error` there means the built-in "404: This page
579
+ // could not be found" replaces the app's own — `test/e2e/404-page-app`.
580
+ const base = manifests["pages-i18n"];
581
+ const withCustom404 = {
582
+ ...base,
583
+ entrypoints: {
584
+ ...base.entrypoints,
585
+ "/404": { ...base.entrypoints["/_error"], id: "/404" },
586
+ },
587
+ };
588
+ expect(statusTargetOf(withCustom404, 404)).toMatchObject({
589
+ kind: "entrypoint",
590
+ pathname: "/404",
591
+ });
592
+ // App Router still wins over both: `/_not-found` is what next looks for
593
+ // first, and an app with both routers has all three.
594
+ expect(statusTargetOf({
595
+ ...withCustom404,
596
+ entrypoints: {
597
+ ...withCustom404.entrypoints,
598
+ "/_not-found": {
599
+ ...base.entrypoints["/_error"],
600
+ id: "/_not-found",
601
+ },
602
+ },
603
+ }, 404)).toMatchObject({ kind: "entrypoint", pathname: "/_not-found" });
604
+ });
605
+ it("falls back to a prerendered 404, then to nothing", () => {
606
+ const base = manifests["app-playground"];
607
+ const withoutEntrypoints = {
608
+ ...base,
609
+ entrypoints: {},
610
+ middleware: null,
611
+ };
612
+ expect(statusTargetOf(withoutEntrypoints, 404)).toEqual({
613
+ kind: "static-file",
614
+ pathname: "/404",
615
+ filePath: base.staticFiles["/404"],
616
+ });
617
+ expect(statusTargetOf({ ...withoutEntrypoints, staticFiles: {} }, 404)).toEqual({ kind: "none" });
618
+ });
619
+ });
620
+ describe("the 500 ladder", () => {
621
+ it("prefers the prerendered /500 next emits by default", () => {
622
+ const base = manifests["app-playground"];
623
+ expect(statusTargetOf(base, 500)).toEqual({
624
+ kind: "static-file",
625
+ pathname: "/500",
626
+ filePath: base.staticFiles["/500"],
627
+ });
628
+ });
629
+ it("prefers an invocable /500 over the prerendered one", () => {
630
+ // What a `pages/500.js` that cannot be static-optimized builds.
631
+ const base = manifests["pages-i18n"];
632
+ expect(statusTargetOf({
633
+ ...base,
634
+ entrypoints: {
635
+ ...base.entrypoints,
636
+ "/500": { ...base.entrypoints["/_error"], id: "/500" },
637
+ },
638
+ }, 500)).toMatchObject({ kind: "entrypoint", pathname: "/500" });
639
+ });
640
+ it("falls back to /_error, then to nothing", () => {
641
+ // `/_error` is where a custom error page lands when it has
642
+ // `getInitialProps` — the case `test/e2e/async-modules` measures.
643
+ const base = manifests["pages-i18n"];
644
+ expect(statusTargetOf({ ...base, staticFiles: {} }, 500)).toMatchObject({
645
+ kind: "entrypoint",
646
+ pathname: "/_error",
647
+ });
648
+ expect(statusTargetOf({ ...base, staticFiles: {}, entrypoints: {} }, 500)).toEqual({ kind: "none" });
649
+ });
650
+ it("serves the prerendered 500 of the request's locale", () => {
651
+ // Under i18n the prerendered 500 is keyed only by locale, never as a bare
652
+ // `/500`, so looking up `/500` alone always fell through to `/_error`.
653
+ const base = manifests["pages-i18n"];
654
+ const errorTargetFor = (0, dispatch_1.statusTargets)(base, 500);
655
+ const at = (url) => errorTargetFor(new URL(url, ORIGIN));
656
+ expect(at("/fr/ssr")).toEqual({
657
+ kind: "static-file",
658
+ pathname: "/fr/500",
659
+ filePath: base.staticFiles["/fr/500"],
660
+ });
661
+ expect(at("/ssr")).toMatchObject({ pathname: "/en-US/500" });
662
+ // No locale in the path: the domain's default, as `next start` renders it.
663
+ expect(at("https://example.fr/ssr")).toMatchObject({
664
+ pathname: "/fr/500",
665
+ });
666
+ // A request whose URL could not be parsed gets the default locale's.
667
+ expect(errorTargetFor(undefined)).toMatchObject({
668
+ pathname: "/en-US/500",
669
+ });
670
+ expect(statusTargetOf(base, 500)).toMatchObject({ pathname: "/en-US/500" });
671
+ });
672
+ it("looks for the error page under the app's basePath", () => {
673
+ const base = manifests["app-playground-base-path"];
674
+ expect(statusTargetOf(base, 500)).toMatchObject({ pathname: "/prod/500" });
675
+ });
676
+ });
677
+ describe("toRedirect", () => {
678
+ it("prefers the documented redirect field", () => {
679
+ // `resolveRoutes` does not populate `ResolveRoutesResult.redirect` in
680
+ // next 16.3.5 — every redirect arrives as bare status + `location` — so this
681
+ // is the only coverage that branch can have until it does.
682
+ expect((0, dispatch_1.toRedirect)({ redirect: { url: new URL("https://e.test/x"), status: 301 } }, new Headers())).toEqual({ location: "https://e.test/x", status: 301 });
683
+ });
684
+ it("ignores a location header on a non-3xx status", () => {
685
+ const headers = new Headers({ location: "/x" });
686
+ expect((0, dispatch_1.toRedirect)({ status: 200 }, headers)).toBeUndefined();
687
+ expect((0, dispatch_1.toRedirect)({ status: 403 }, headers)).toBeUndefined();
688
+ expect((0, dispatch_1.toRedirect)({}, headers)).toBeUndefined();
689
+ expect((0, dispatch_1.toRedirect)({ status: 308 }, new Headers())).toBeUndefined();
690
+ });
691
+ });
692
+ describe("Dispatcher middleware handling", () => {
693
+ it("reports a middleware response without resolving a route", async () => {
694
+ const result = await dispatcherFor("app-playground", async () => ({
695
+ bodySent: true,
696
+ responseHeaders: new Headers({ "x-mw": "responded" }),
697
+ })).dispatch(request("/isr/1"));
698
+ expect(result.kind).toBe("middleware-responded");
699
+ });
700
+ it("sends next.config headers() with a response middleware wrote", async () => {
701
+ // `app-playground`'s `headers()` sets this on `/api/echo`; `next start`
702
+ // sends it with a middleware 401 there too.
703
+ const result = await dispatcherFor("app-playground", async () => ({
704
+ bodySent: true,
705
+ })).dispatch(request("/api/echo"));
706
+ expect(result.kind).toBe("middleware-responded");
707
+ expect(result.responseHeaders.get("x-e2e-config-header")).toBe("from-next-config");
708
+ const other = await dispatcherFor("app-playground", async () => ({
709
+ bodySent: true,
710
+ })).dispatch(request("/isr/1"));
711
+ expect(other.responseHeaders.has("x-e2e-config-header")).toBe(false);
712
+ });
713
+ it("normalizes a middleware redirect to a same-origin path", async () => {
714
+ const result = await dispatcherFor("app-playground", async () => ({
715
+ redirect: { url: new URL("/login", ORIGIN), status: 307 },
716
+ })).dispatch(request("/isr/1"));
717
+ expect(result).toMatchObject({
718
+ kind: "redirect",
719
+ status: 307,
720
+ // `NextResponse.redirect(new URL("/login", request.url))` is how every
721
+ // middleware spells this, and Next.js sends the path: `@next/routing`'s
722
+ // own `getRelativeURL` does it for the header it sets, and only the
723
+ // `redirect.url` field this path reads keeps the absolute form.
724
+ location: "/login",
725
+ });
726
+ });
727
+ it("follows an internal middleware rewrite to the rewritten entrypoint", async () => {
728
+ const result = await dispatcherFor("app-playground", async () => ({
729
+ rewrite: new URL("/api/health", ORIGIN),
730
+ })).dispatch(request("/isr/1"));
731
+ expect(result.kind).toBe("entrypoint");
732
+ if (result.kind !== "entrypoint")
733
+ return;
734
+ expect(result.resolvedPathname).toBe("/api/health");
735
+ });
736
+ it("routes /_next/image when middleware is what put the request on it", async () => {
737
+ // The API Gateway examples' middleware rewrites `/x` to `/<stage>/x` so the
738
+ // build's `basePath` lines up. `resolveRoutes` never reports the rewritten
739
+ // URL back, so optimizing the URL as received would lose the rewrite.
740
+ const query = "?url=%2Ffoo.png&w=640&q=75";
741
+ const result = await dispatcherFor("app-playground-base-path", async () => ({ rewrite: new URL(`/prod/_next/image${query}`, ORIGIN) })).dispatch(request(`/_next/image${query}`));
742
+ expect(result.kind).toBe("image-optimization");
743
+ if (result.kind !== "image-optimization")
744
+ return;
745
+ expect(result.url.searchParams.get("url")).toBe("/foo.png");
746
+ });
747
+ it("does not leak the internal rewrite header it consumed", async () => {
748
+ const result = await dispatcherFor("app-playground", async () => ({
749
+ rewrite: new URL("/api/health", ORIGIN),
750
+ responseHeaders: new Headers({ "x-middleware-rewrite": "/api/health" }),
751
+ })).dispatch(request("/isr/1"));
752
+ expect(result.responseHeaders.has("x-middleware-rewrite")).toBe(false);
753
+ });
754
+ it("reports an external middleware rewrite as a proxy target", async () => {
755
+ const result = await dispatcherFor("app-playground", async () => ({
756
+ rewrite: new URL("https://upstream.test/x"),
757
+ })).dispatch(request("/isr/1"));
758
+ expect(result.kind).toBe("external-rewrite");
759
+ if (result.kind !== "external-rewrite")
760
+ return;
761
+ expect(result.url.href).toBe("https://upstream.test/x");
762
+ });
763
+ it("carries middleware request headers forward and response headers back", async () => {
764
+ // `resolveRoutes` drops `MiddlewareResult.requestHeaders`: it neither
765
+ // returns them nor mutates the `headers` it was given. Dispatch captures
766
+ // them from the callback, which is what keeps
767
+ // `NextResponse.next({ request: { headers } })` working.
768
+ const result = await dispatcherFor("app-playground", async () => ({
769
+ requestHeaders: new Headers({ host: "example.test", "x-user": "42" }),
770
+ responseHeaders: new Headers({ "x-mw": "ran" }),
771
+ })).dispatch(request("/isr/1"));
772
+ expect(result.kind).toBe("entrypoint");
773
+ if (result.kind !== "entrypoint")
774
+ return;
775
+ expect(result.requestHeaders.get("x-user")).toBe("42");
776
+ expect(result.responseHeaders.get("x-mw")).toBe("ran");
777
+ });
778
+ it("passes the caller's request headers through when middleware adds none", async () => {
779
+ const result = await dispatcherFor("app-playground").dispatch(request("/isr/1", { "x-caller": "yes" }));
780
+ expect(result.kind).toBe("entrypoint");
781
+ if (result.kind !== "entrypoint")
782
+ return;
783
+ expect(result.requestHeaders.get("x-caller")).toBe("yes");
784
+ });
785
+ });
786
+ describe("repairRouteParamQuery", () => {
787
+ it("drops an optional catchall's param when the request filled none", () => {
788
+ // Measured from `resolveRoutes` for `/optional-catchall` against
789
+ // `app/optional-catchall/[[...params]]`: *both* sides carry the key with no
790
+ // value, which the `@next/routing` types do not admit. The key alone is what
791
+ // makes `prepare()` invent a param, so the key has to go.
792
+ expect((0, dispatch_1.repairRouteParamQuery)({ nxtPparams: undefined }, {
793
+ nxtPparams: undefined,
794
+ })).toEqual({});
795
+ // The same shape with "" for the value, which the expansion can also produce.
796
+ expect((0, dispatch_1.repairRouteParamQuery)({ nxtPparams: "" }, {})).toEqual({});
797
+ // A filled one is left alone, whichever source it came from.
798
+ expect((0, dispatch_1.repairRouteParamQuery)({ nxtPparams: "a/b" }, { nxtPparams: "a/b" })).toEqual({ nxtPparams: "a/b" });
799
+ // No route param can be legitimately empty - a required segment captures
800
+ // `[^/]+?`, a required catchall `.+?`, and an optional catchall that matched
801
+ // nothing has no group for `routeMatches` to report - so an empty value goes
802
+ // whether or not `routeMatches` echoes it.
803
+ expect((0, dispatch_1.repairRouteParamQuery)({ nxtPid: "" }, { nxtPid: "" })).toEqual({});
804
+ // Not a route param, so not ours to touch.
805
+ expect((0, dispatch_1.repairRouteParamQuery)({ q: "" }, {})).toEqual({ q: "" });
806
+ });
807
+ it("repairs and drops in one pass", () => {
808
+ // The prefix collision and the unset optional catchall in the same query:
809
+ // `nxtPid2` is wrong and `nxtPrest` was never requested.
810
+ expect((0, dispatch_1.repairRouteParamQuery)({ nxtPid: "a", nxtPid2: "a2", nxtPrest: "" }, { nxtPid: "a", nxtPid2: "b" })).toEqual({ nxtPid: "a", nxtPid2: "b" });
811
+ });
812
+ });
813
+ describe("outOfBandRouteParams", () => {
814
+ it("leaves a query the contract can carry alone", () => {
815
+ expect((0, dispatch_1.outOfBandRouteParams)({ nxtPrest: "a/b", q: "1" }, "/pages-cache/[...rest]")).toBeUndefined();
816
+ expect((0, dispatch_1.outOfBandRouteParams)({ nxtPid: "42" }, "/isr/[id]")).toBeUndefined();
817
+ // An encoded delimiter in something that is not a route param is not ours.
818
+ expect((0, dispatch_1.outOfBandRouteParams)({ q: "a%2Fb" }, "/pages-cache/[...rest]")).toBeUndefined();
819
+ });
820
+ it("restates a capture with an encoded delimiter as params, once decoded", () => {
821
+ // `test/e2e/incremental-cache-path-traversal`. Through the query contract
822
+ // this becomes three params and `normalizePagePath` throws on the pathname
823
+ // rebuilt from them; `next start` renders one param, which is this.
824
+ expect((0, dispatch_1.outOfBandRouteParams)({ nxtPrest: "..%2F..%2Fserver-reference-manifest" }, "/_next/data/BUILD_ID/pages-cache/[...rest].json")).toEqual({
825
+ params: { rest: ["../../server-reference-manifest"] },
826
+ query: {},
827
+ });
828
+ });
829
+ it("splits a repeat on real delimiters only, and keeps a single param whole", () => {
830
+ expect((0, dispatch_1.outOfBandRouteParams)({ nxtPrest: "a/b%2Fc/d" }, "/pages-cache/[[...rest]]")).toEqual({ params: { rest: ["a", "b/c", "d"] }, query: {} });
831
+ expect((0, dispatch_1.outOfBandRouteParams)({ nxtPid: "a%2Fb" }, "/isr/[id]")).toEqual({
832
+ params: { id: "a/b" },
833
+ query: {},
834
+ });
835
+ });
836
+ it("keeps everything that is not a route param in the query", () => {
837
+ expect((0, dispatch_1.outOfBandRouteParams)({ nxtPrest: "a%2Fb", from: "/x", page: "2" }, "/pages-cache/[...rest]")).toEqual({
838
+ params: { rest: ["a/b"] },
839
+ query: { from: "/x", page: "2" },
840
+ });
841
+ });
842
+ it("stays on the query contract when a param cannot be restated", () => {
843
+ // An optional catchall the request left unset. Half a param set is worse
844
+ // than none: `prepare` would interpolate a route with a missing segment.
845
+ expect((0, dispatch_1.outOfBandRouteParams)({ nxtPrest: "a%2Fb", nxtPoptional: "" }, "/pages-cache/[...rest]/[[...optional]]")).toBeUndefined();
846
+ });
847
+ it("tolerates a capture that is not valid percent-encoding", () => {
848
+ // `decodeQueryPathParameter` is a try/catch for the same reason: `%2F` makes
849
+ // this reachable while `%zz` makes `decodeURIComponent` throw.
850
+ expect((0, dispatch_1.outOfBandRouteParams)({ nxtPrest: "a%2F%zz" }, "/pages-cache/[...rest]")).toEqual({ params: { rest: ["a%2F%zz"] }, query: {} });
851
+ });
852
+ });
853
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGlzcGF0Y2gudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9ydW50aW1lL2Rpc3BhdGNoLnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxzREFBc0Q7QUFDdEQscUNBQWdFO0FBQ2hFLHFDQUFpQztBQUNqQyx5Q0FBMEM7QUFFMUMseUNBT29CO0FBRXBCLGlEQUFpRDtBQUNqRCwwSEFBMEY7QUFDMUYsc0dBQXdFO0FBQ3hFLDhGQUFnRTtBQUNoRSw0REFHa0M7QUFFbEM7Ozs7OztHQU1HO0FBQ0gsU0FBUyxVQUFVLENBQUMsT0FBZ0I7SUFDbEMsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUMsa0JBQWtCLENBQUMsR0FBRyxFQUFFLEdBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdEUsSUFBSSxDQUFDO1FBQ0gsTUFBTSxHQUFHLEdBQUcsZUFBZSxDQUFDLE9BQU8sQ0FBeUIsQ0FBQztRQUM3RCw2RUFBNkU7UUFDN0UsMENBQTBDO1FBQzFDLE9BQU8sSUFBQSxvQ0FBb0IsRUFBQyxHQUFHLEVBQUUsRUFBRSxRQUFRLEVBQUUsR0FBRyxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDO0lBQzFFLENBQUM7WUFBUyxDQUFDO1FBQ1QsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ3JCLENBQUM7QUFDSCxDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsU0FBUyxnQkFBZ0IsQ0FBQyxPQUFnQjtJQUN4QyxPQUFPLElBQUksQ0FBQyxLQUFLLENBQ2YsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUM7U0FDcEIsS0FBSyxDQUFDLDhCQUE4QixDQUFDO1NBQ3JDLElBQUksQ0FBQyxjQUFjLENBQUM7U0FDcEIsS0FBSyxDQUFDLHlCQUF5QixDQUFDO1NBQ2hDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FDbkIsQ0FBQztBQUNKLENBQUM7QUFFRCxNQUFNLFNBQVMsR0FBRztJQUNoQixnQkFBZ0IsRUFBRSxVQUFVLENBQUMsNkJBQWEsQ0FBQztJQUMzQywwQkFBMEIsRUFBRSxVQUFVLENBQUMsdUNBQXFCLENBQUM7SUFDN0QsK0JBQStCLEVBQUUsVUFBVSxDQUFDLGdCQUFnQixDQUFDLDZCQUFhLENBQUMsQ0FBQztJQUM1RSx5Q0FBeUMsRUFBRSxVQUFVLENBQ25ELGdCQUFnQixDQUFDLHVDQUFxQixDQUFDLENBQ3hDO0lBQ0QsWUFBWSxFQUFFLFVBQVUsQ0FBQyx5QkFBUyxDQUFDO0NBQzNCLENBQUM7QUFFWCxNQUFNLE1BQU0sR0FBRyxzQkFBc0IsQ0FBQztBQUV0QyxTQUFTLE9BQU8sQ0FBQyxHQUFXLEVBQUUsVUFBa0MsRUFBRTtJQUNoRSxNQUFNLE1BQU0sR0FBb0I7UUFDOUIsTUFBTSxFQUFFLEtBQUs7UUFDYixHQUFHLEVBQUUsSUFBSSxHQUFHLENBQUMsR0FBRyxFQUFFLE1BQU0sQ0FBQztRQUN6QixPQUFPLEVBQUUsSUFBSSxPQUFPLENBQUMsRUFBRSxJQUFJLEVBQUUsY0FBYyxFQUFFLEdBQUcsT0FBTyxFQUFFLENBQUM7UUFDMUQsZ0VBQWdFO1FBQ2hFLElBQUksRUFBRSxJQUFJLGNBQWMsQ0FBQztZQUN2QixLQUFLLENBQUMsVUFBVTtnQkFDZCxVQUFVLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDckIsQ0FBQztTQUNGLENBQUM7UUFDRiw4Q0FBOEM7UUFDOUMsZ0JBQWdCLEVBQUUsS0FBSyxJQUFJLEVBQUUsQ0FBQyxDQUFDLEVBQUUsUUFBUSxFQUFFLElBQUksUUFBUSxFQUFFLEVBQUUsQ0FBQztLQUM3RCxDQUFDO0lBQ0YsT0FBTyxNQUFNLENBQUM7QUFDaEIsQ0FBQztBQUVELG9GQUFvRjtBQUNwRixTQUFTLGFBQWEsQ0FDcEIsSUFBNEIsRUFDNUIsVUFBNEM7SUFFNUMsTUFBTSxVQUFVLEdBQUcsSUFBSSxxQkFBVSxDQUFDLEVBQUUsUUFBUSxFQUFFLFNBQVMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDakUsT0FBTztRQUNMLFdBQVcsRUFBRSxVQUFVLENBQUMsV0FBVztRQUNuQyxRQUFRLEVBQUUsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUNoQixVQUFVLENBQUMsUUFBUSxDQUNqQixVQUFVO1lBQ1IsQ0FBQyxDQUFDO2dCQUNFLEdBQUcsR0FBRztnQkFDTixnQkFBZ0IsRUFBRSxLQUFLLElBQUksRUFBRSxDQUFDLENBQUM7b0JBQzdCLEdBQUcsQ0FBQyxNQUFNLFVBQVUsRUFBRSxDQUFDO29CQUN2QixRQUFRLEVBQUUsSUFBSSxRQUFRLEVBQUU7aUJBQ3pCLENBQUM7YUFDSDtZQUNILENBQUMsQ0FBQyxHQUFHLENBQ1I7S0FDSixDQUFDO0FBQ0osQ0FBQztBQUVELG9EQUFvRDtBQUNwRCxTQUFTLGNBQWMsQ0FBQyxRQUF5QixFQUFFLE1BQWlCO0lBQ2xFLE9BQU8sSUFBQSx3QkFBYSxFQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQztBQUNwRCxDQUFDO0FBRUQsUUFBUSxDQUFDLGtDQUFrQyxFQUFFLEdBQUcsRUFBRTtJQUNoRCxFQUFFLENBQUMsK0RBQStELEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDN0UsTUFBTSxNQUFNLEdBQUcsTUFBTSxhQUFhLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxRQUFRLENBQzNELE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FDbEIsQ0FBQztRQUNGLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ3ZDLElBQUksTUFBTSxDQUFDLElBQUksS0FBSyxZQUFZO1lBQUUsT0FBTztRQUN6QywyRUFBMkU7UUFDM0UseUVBQXlFO1FBQ3pFLE1BQU0sQ0FBQyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDbEQsTUFBTSxDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQztZQUN0QyxRQUFRLEVBQUUsUUFBUTtZQUNsQixLQUFLLEVBQUUsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFO1NBQ3ZCLENBQUMsQ0FBQztRQUNILE1BQU0sQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQ2pFLE1BQU0sQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUNsRCxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyxzQ0FBc0MsRUFBRSxLQUFLLElBQUksRUFBRTtRQUNwRCxNQUFNLE1BQU0sR0FBRyxNQUFNLGFBQWEsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLFFBQVEsQ0FDM0QsT0FBTyxDQUFDLGFBQWEsQ0FBQyxDQUN2QixDQUFDO1FBQ0YsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDdkMsSUFBSSxNQUFNLENBQUMsSUFBSSxLQUFLLFlBQVk7WUFBRSxPQUFPO1FBQ3pDLE1BQU0sQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUNqRCxNQUFNLENBQUMsTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBQ3RELENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLGlFQUFpRSxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQy9FLDRFQUE0RTtRQUM1RSwyRUFBMkU7UUFDM0UscUNBQXFDO1FBQ3JDLE1BQU0sVUFBVSxHQUFHLGFBQWEsQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO1FBQzdELE1BQU0sTUFBTSxHQUFHLE1BQU0sVUFBVSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQztRQUNqRSxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUN2QyxJQUFJLE1BQU0sQ0FBQyxJQUFJLEtBQUssWUFBWTtZQUFFLE9BQU87UUFDekMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBQ3ZELE1BQU0sQ0FBQyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBRTdELHFEQUFxRDtRQUNyRCxNQUFNLFVBQVUsR0FBRyxNQUFNLFVBQVUsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7UUFDaEUsTUFBTSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDNUMsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsNENBQTRDLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDMUQsTUFBTSxVQUFVLEdBQUcsYUFBYSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQy9DLE1BQU0sSUFBSSxHQUFHLE1BQU0sVUFBVSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQztRQUM5RCxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUNyQyxJQUFJLElBQUksQ0FBQyxJQUFJLEtBQUssWUFBWSxFQUFFLENBQUM7WUFDL0IsTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzVDLENBQUM7UUFDRCxNQUFNLEdBQUcsR0FBRyxNQUFNLFVBQVUsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUM7UUFDN0QsTUFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDcEMsSUFBSSxHQUFHLENBQUMsSUFBSSxLQUFLLFlBQVksRUFBRSxDQUFDO1lBQzlCLE1BQU0sQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUMvQyxDQUFDO0lBQ0gsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsaUVBQWlFLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDL0UsMEVBQTBFO1FBQzFFLHlFQUF5RTtRQUN6RSw0RUFBNEU7UUFDNUUsTUFBTTtRQUNOLE1BQU0sRUFBRSxPQUFPLEVBQUUsR0FBRyxTQUFTLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDNUMsTUFBTSxNQUFNLEdBQUcsTUFBTSxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUMsUUFBUSxDQUN2RCxPQUFPLENBQUMsZUFBZSxPQUFPLHFCQUFxQixDQUFDLENBQ3JELENBQUM7UUFDRixNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUN2QyxJQUFJLE1BQU0sQ0FBQyxJQUFJLEtBQUssWUFBWTtZQUFFLE9BQU87UUFDekMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLElBQUksQ0FDbEMsZUFBZSxPQUFPLHNCQUFzQixDQUM3QyxDQUFDO1FBQ0YsTUFBTSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQzVELE1BQU0sQ0FBQyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLENBQUMsYUFBYSxDQUFDLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUM7SUFDN0UsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsb0VBQW9FLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDbEYseUVBQXlFO1FBQ3pFLCtEQUErRDtRQUMvRCx3RUFBd0U7UUFDeEUseUVBQXlFO1FBQ3pFLHFFQUFxRTtRQUNyRSxNQUFNLFNBQVMsR0FBRyxlQUFlLENBQy9CLDZCQUF3QixDQUNELENBQUM7UUFDekIsU0FBUyxDQUFDLE1BQXFDLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQztRQUN0RSw0RUFBNEU7UUFDNUUsNEVBQTRFO1FBQzVFLDBFQUEwRTtRQUMxRSw0RUFBNEU7UUFDNUUsMkVBQTJFO1FBQzNFLE1BQU0sT0FBTyxHQUFHLFNBQVMsQ0FBQyxPQUV6QixDQUFDO1FBQ0YsT0FBTyxDQUFDLGdCQUFnQixHQUFHLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLENBQ3hELENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsTUFBTSxLQUFLLEdBQUcsQ0FDaEMsQ0FBQztRQUNGLE1BQU0sVUFBVSxHQUFHLElBQUkscUJBQVUsQ0FBQztZQUNoQyxRQUFRLEVBQUUsVUFBVSxDQUFDLFNBQVMsQ0FBQztTQUNoQyxDQUFDLENBQUM7UUFFSCxNQUFNLElBQUksR0FBRyxNQUFNLFVBQVUsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7UUFDM0QsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDckMsSUFBSSxJQUFJLENBQUMsSUFBSSxLQUFLLFlBQVk7WUFBRSxPQUFPO1FBQ3ZDLHdFQUF3RTtRQUN4RSxpRUFBaUU7UUFDakUsTUFBTSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUNoRCxNQUFNLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUMsT0FBTyxDQUFDO1lBQ3BDLFFBQVEsRUFBRSxRQUFRO1lBQ2xCLEtBQUssRUFBRSxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUU7U0FDdkIsQ0FBQyxDQUFDO1FBRUgsTUFBTSxLQUFLLEdBQUcsTUFBTSxVQUFVLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDO1FBQ2pFLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ3RDLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxZQUFZLEVBQUUsQ0FBQztZQUNoQyxNQUFNLENBQUMsS0FBSyxDQUFDLGdCQUFnQixDQUFDLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQ3JELENBQUM7UUFFRCwyRUFBMkU7UUFDM0Usd0VBQXdFO1FBQ3hFLE1BQU0sS0FBSyxHQUFHLE1BQU0sVUFBVSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQztRQUNqRSxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUN2QyxNQUFNLENBQUMsTUFBTSxVQUFVLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDO1lBQ3hFLElBQUksRUFBRSxXQUFXO1NBQ2xCLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLGlFQUFpRSxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQy9FLDJFQUEyRTtRQUMzRSw2RUFBNkU7UUFDN0Usc0VBQXNFO1FBQ3RFLHdFQUF3RTtRQUN4RSx5REFBeUQ7UUFDekQsb0RBQW9EO1FBQ3BELE1BQU0sTUFBTSxHQUFHLE1BQU0sYUFBYSxDQUFDLGdCQUFnQixDQUFDLENBQUMsUUFBUSxDQUMzRCxPQUFPLENBQUMsb0JBQW9CLENBQUMsQ0FDOUIsQ0FBQztRQUNGLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ3ZDLElBQUksTUFBTSxDQUFDLElBQUksS0FBSyxZQUFZO1lBQUUsT0FBTztRQUN6QyxNQUFNLENBQUMsTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUMsSUFBSSxDQUFDLDJCQUEyQixDQUFDLENBQUM7UUFDbEUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQztZQUN0QyxRQUFRLEVBQUUsb0JBQW9CO1lBQzlCLEtBQUssRUFBRSxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsT0FBTyxFQUFFLEdBQUcsRUFBRTtTQUNyQyxDQUFDLENBQUM7UUFDSCxNQUFNLENBQUMsTUFBTSxDQUFDLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxDQUFDLE9BQU8sQ0FBQztZQUM1QyxNQUFNLEVBQUUsR0FBRztZQUNYLE9BQU8sRUFBRSxHQUFHO1NBQ2IsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsOERBQThELEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDNUUscUVBQXFFO1FBQ3JFLHlFQUF5RTtRQUN6RSwyRUFBMkU7UUFDM0Usd0RBQXdEO1FBQ3hELE1BQU0sVUFBVSxHQUFHLGFBQWEsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBQ25ELE1BQU0sU0FBUyxHQUFHLE1BQU0sVUFBVSxDQUFDLFFBQVEsQ0FDekMsT0FBTyxDQUFDLG1DQUFtQyxDQUFDLENBQzdDLENBQUM7UUFDRixNQUFNLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUMxQyxJQUFJLFNBQVMsQ0FBQyxJQUFJLEtBQUssWUFBWTtZQUFFLE9BQU87UUFDNUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO1FBQzdELE1BQU0sQ0FBQyxTQUFTLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLENBQUMsYUFBYSxDQUFDO1lBQ3JELElBQUksRUFBRSxhQUFhO1lBQ25CLElBQUksRUFBRSxNQUFNO1NBQ2IsQ0FBQyxDQUFDO1FBRUgsc0VBQXNFO1FBQ3RFLG1CQUFtQjtRQUNuQixNQUFNLENBQ0osTUFBTSxVQUFVLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDLENBQzlELENBQUMsYUFBYSxDQUFDLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxDQUFDLENBQUM7SUFDekMsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQztBQUVILFFBQVEsQ0FBQywwQkFBMEIsRUFBRSxHQUFHLEVBQUU7SUFDeEM7Ozs7T0FJRztJQUNILFNBQVMsU0FBUyxDQUFDLEtBQWU7UUFDaEMsTUFBTSxHQUFHLEdBQUcsSUFBQSxxQkFBVyxFQUFDLElBQUEsZ0JBQUksRUFBQyxJQUFBLGdCQUFNLEdBQUUsRUFBRSw2QkFBNkIsQ0FBQyxDQUFDLENBQUM7UUFDdkUsS0FBSyxNQUFNLElBQUksSUFBSSxLQUFLLEVBQUUsQ0FBQztZQUN6QixJQUFBLG1CQUFTLEVBQUMsSUFBQSxtQkFBTyxFQUFDLElBQUEsZ0JBQUksRUFBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUMsRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1lBQ3pELElBQUEsdUJBQWEsRUFBQyxJQUFBLGdCQUFJLEVBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ3ZDLENBQUM7UUFDRCxPQUFPLElBQUEsOEJBQWUsRUFBQyxHQUFHLENBQUMsQ0FBQztJQUM5QixDQUFDO0lBRUQsU0FBUyxvQkFBb0IsQ0FDM0IsSUFBNEIsRUFDNUIsS0FBZTtRQUVmLE9BQU8sSUFBSSxxQkFBVSxDQUFDO1lBQ3BCLFFBQVEsRUFBRSxTQUFTLENBQUMsSUFBSSxDQUFDO1lBQ3pCLFdBQVcsRUFBRSxTQUFTLENBQUMsS0FBSyxDQUFDO1NBQzlCLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxFQUFFLENBQUMsSUFBSSxDQUFDO1FBQ04sa0VBQWtFO1FBQ2xFLENBQUMsc0JBQXNCLEVBQUUsQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO1FBQ3JELHVFQUF1RTtRQUN2RSxDQUFDLG9CQUFvQixFQUFFLENBQUMscUJBQXFCLEVBQUUsdUJBQXVCLENBQUMsQ0FBQztRQUN4RSxDQUFDLFNBQVMsRUFBRSxDQUFDLFVBQVUsRUFBRSxjQUFjLENBQUMsQ0FBQztRQUN6QyxDQUFDLGFBQWEsRUFBRSxDQUFDLGNBQWMsRUFBRSxrQkFBa0IsQ0FBQyxDQUFDO1FBQ3JELENBQUMsU0FBUyxFQUFFLENBQUMsVUFBVSxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBQ3ZDLCtDQUErQztRQUMvQyxDQUFDLFVBQVUsRUFBRSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQzdCLENBQUMsWUFBWSxFQUFFLENBQUMsaUNBQWlDLENBQUMsQ0FBQztLQUNwRCxDQUFDLENBQ0EsdURBQXVELEVBQ3ZELEtBQUssRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLEVBQUU7UUFDbkIsTUFBTSxVQUFVLEdBQUcsb0JBQW9CLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQ2xFLEtBQUssTUFBTSxHQUFHLElBQUksSUFBSSxFQUFFLENBQUM7WUFDdkIsTUFBTSxDQUFDLE1BQU0sVUFBVSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQztnQkFDNUQsSUFBSSxFQUFFLGFBQWE7Z0JBQ25CLE1BQU0sRUFBRSxRQUFRO2dCQUNoQixRQUFRLEVBQUUseUJBQXlCLElBQUksRUFBRTthQUMxQyxDQUFDLENBQUM7UUFDTCxDQUFDO0lBQ0gsQ0FBQyxDQUNGLENBQUM7SUFFRixFQUFFLENBQUMsMkRBQTJELEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDekUsd0VBQXdFO1FBQ3hFLHVFQUF1RTtRQUN2RSxNQUFNLE1BQU0sR0FBRyxNQUFNLG9CQUFvQixDQUFDLGdCQUFnQixFQUFFO1lBQzFELGFBQWE7U0FDZCxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDO1FBQ3JDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxhQUFhLENBQUM7WUFDM0IsSUFBSSxFQUFFLGFBQWE7WUFDbkIsUUFBUSxFQUFFLG1DQUFtQztTQUM5QyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyw4REFBOEQsRUFBRSxLQUFLLElBQUksRUFBRTtRQUM1RSxNQUFNLE1BQU0sR0FBRyxNQUFNLG9CQUFvQixDQUFDLGdCQUFnQixFQUFFLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FDdEUsT0FBTyxDQUFDLGNBQWMsQ0FBQyxDQUN4QixDQUFDO1FBQ0YsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLGFBQWEsQ0FBQyxFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7SUFDMUUsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsK0JBQStCLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDN0MsTUFBTSxVQUFVLEdBQUcsb0JBQW9CLENBQUMsMEJBQTBCLEVBQUU7WUFDbEUsVUFBVTtTQUNYLENBQUMsQ0FBQztRQUNILE1BQU0sQ0FBQyxNQUFNLFVBQVUsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQztZQUN6RSxJQUFJLEVBQUUsYUFBYTtZQUNuQixRQUFRLEVBQUUsZ0NBQWdDO1NBQzNDLENBQUMsQ0FBQztRQUNILE1BQU0sQ0FBQyxDQUFDLE1BQU0sVUFBVSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQ3JFLGFBQWEsQ0FDZCxDQUFDO0lBQ0osQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMscUVBQXFFLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDbkYsMkVBQTJFO1FBQzNFLDBFQUEwRTtRQUMxRSwyRUFBMkU7UUFDM0UsU0FBUztRQUNULE1BQU0sVUFBVSxHQUFHLG9CQUFvQixDQUFDLFlBQVksRUFBRSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7UUFDcEUsS0FBSyxNQUFNLEdBQUcsSUFBSSxDQUFDLFdBQVcsRUFBRSxpQkFBaUIsRUFBRSxjQUFjLENBQUMsRUFBRSxDQUFDO1lBQ25FLE1BQU0sQ0FBQyxNQUFNLFVBQVUsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUM7Z0JBQzVELElBQUksRUFBRSxhQUFhO2dCQUNuQixRQUFRLEVBQUUsNEJBQTRCO2FBQ3ZDLENBQUMsQ0FBQztRQUNMLENBQUM7UUFDRCxNQUFNLENBQ0osQ0FBQyxNQUFNLFVBQVUsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FDN0QsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBQzVCLENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLHVEQUF1RCxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ3JFLDJFQUEyRTtRQUMzRSx5RUFBeUU7UUFDekUsbUVBQW1FO1FBQ25FLE1BQU0sQ0FDSixNQUFNLGFBQWEsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FDckUsQ0FBQyxhQUFhLENBQUMsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLENBQUMsQ0FBQztJQUN6QyxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDO0FBRUgsUUFBUSxDQUFDLG1DQUFtQyxFQUFFLEdBQUcsRUFBRTtJQUNqRCxFQUFFLENBQUMsZ0VBQWdFLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDOUUsMEVBQTBFO1FBQzFFLHlFQUF5RTtRQUN6RSxnQ0FBZ0M7UUFDaEMsTUFBTSxJQUFJLEdBQUcsU0FBUyxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFDekMsTUFBTSxRQUFRLEdBQUcsb0RBQW9ELENBQUM7UUFDdEUsTUFBTSxRQUFRLEdBQ1osa0VBQWtFLENBQUM7UUFDckUsTUFBTSxRQUFRLEdBQW9CO1lBQ2hDLEdBQUcsSUFBSTtZQUNQLFdBQVcsRUFBRSxFQUFFLEdBQUcsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxFQUFFLFFBQVEsRUFBRTtZQUMxRCxTQUFTLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxTQUFTLEVBQUUsUUFBUSxDQUFDO1NBQ3pDLENBQUM7UUFDRixNQUFNLFVBQVUsR0FBRyxJQUFJLHFCQUFVLENBQUM7WUFDaEMsUUFBUTtTQUNULENBQUMsQ0FBQztRQUNILEtBQUssTUFBTSxHQUFHLElBQUk7WUFDaEIsd0RBQXdEO1lBQ3hELFFBQVE7U0FDVCxFQUFFLENBQUM7WUFDRixNQUFNLENBQUMsTUFBTSxVQUFVLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDO2dCQUM1RCxJQUFJLEVBQUUsYUFBYTtnQkFDbkIsTUFBTSxFQUFFLGFBQWE7Z0JBQ3JCLFFBQVE7YUFDVCxDQUFDLENBQUM7UUFDTCxDQUFDO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQztBQUVILFFBQVEsQ0FBQyxvQ0FBb0MsRUFBRSxHQUFHLEVBQUU7SUFDbEQsRUFBRSxDQUFDLHVFQUF1RSxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ3JGLE1BQU0sUUFBUSxHQUFHLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBQzdDLE1BQU0sUUFBUSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQy9ELElBQUksQ0FBQyxVQUFVLENBQUMsZ0JBQWdCLENBQUMsQ0FDakMsQ0FBQztRQUNILE1BQU0sTUFBTSxHQUFHLE1BQU0sYUFBYSxDQUFDLGdCQUFnQixDQUFDLENBQUMsUUFBUSxDQUMzRCxPQUFPLENBQUMsUUFBUSxDQUFDLENBQ2xCLENBQUM7UUFDRixNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUN4QyxJQUFJLE1BQU0sQ0FBQyxJQUFJLEtBQUssYUFBYTtZQUFFLE9BQU87UUFDMUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDdkMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUN0RCxtQ0FBbUMsQ0FDcEMsQ0FBQztJQUNKLENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLHlEQUF5RCxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ3ZFLE1BQU0sS0FBSyxHQUFHLDRCQUE0QixDQUFDO1FBQzNDLE1BQU0sS0FBSyxHQUFHLE1BQU0sYUFBYSxDQUFDLGdCQUFnQixDQUFDLENBQUMsUUFBUSxDQUMxRCxPQUFPLENBQUMsZUFBZSxLQUFLLEVBQUUsQ0FBQyxDQUNoQyxDQUFDO1FBQ0YsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsb0JBQW9CLENBQUMsQ0FBQztRQUU5QyxNQUFNLFFBQVEsR0FBRyxNQUFNLGFBQWEsQ0FBQywwQkFBMEIsQ0FBQyxDQUFDLFFBQVEsQ0FDdkUsT0FBTyxDQUFDLG9CQUFvQixLQUFLLEVBQUUsQ0FBQyxDQUNyQyxDQUFDO1FBQ0YsTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsb0JBQW9CLENBQUMsQ0FBQztRQUNqRCxJQUFJLFFBQVEsQ0FBQyxJQUFJLEtBQUssb0JBQW9CO1lBQUUsT0FBTztRQUNuRCxNQUFNLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQ2hFLENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLGdFQUFnRSxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQzlFLE1BQU0sS0FBSyxHQUFHLDRCQUE0QixDQUFDO1FBQzNDLE1BQU0sUUFBUSxHQUFHLGFBQWEsQ0FBQywrQkFBK0IsQ0FBQyxDQUFDO1FBQ2hFLE1BQU0sS0FBSyxHQUFHLE1BQU0sUUFBUSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsZUFBZSxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDdkUsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsb0JBQW9CLENBQUMsQ0FBQztRQUM5QyxJQUFJLEtBQUssQ0FBQyxJQUFJLEtBQUssb0JBQW9CO1lBQUUsT0FBTztRQUNoRCxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBRTNELG9EQUFvRDtRQUNwRCxNQUFNLElBQUksR0FBRyxNQUFNLFFBQVEsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7UUFDdEQsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDckMsSUFBSSxJQUFJLENBQUMsSUFBSSxLQUFLLFlBQVk7WUFBRSxPQUFPO1FBQ3ZDLE1BQU0sQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUM7UUFFbkQsTUFBTSxnQkFBZ0IsR0FBRyxhQUFhLENBQ3BDLHlDQUF5QyxDQUMxQyxDQUFDO1FBQ0YsTUFBTSxRQUFRLEdBQUcsTUFBTSxnQkFBZ0IsQ0FBQyxRQUFRLENBQzlDLE9BQU8sQ0FBQyxvQkFBb0IsS0FBSyxFQUFFLENBQUMsQ0FDckMsQ0FBQztRQUNGLE1BQU0sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLG9CQUFvQixDQUFDLENBQUM7UUFDakQsb0VBQW9FO1FBQ3BFLG9CQUFvQjtRQUNwQixNQUFNLFlBQVksR0FBRyxNQUFNLGdCQUFnQixDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQztRQUMzRSxNQUFNLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUM3QyxJQUFJLFlBQVksQ0FBQyxJQUFJLEtBQUssWUFBWTtZQUFFLE9BQU87UUFDL0MsTUFBTSxDQUFDLFlBQVksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO0lBQ2xFLENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLHNFQUFzRSxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ3BGLE1BQU0sUUFBUSxHQUFHLFNBQVMsQ0FBQywrQkFBK0IsQ0FBQyxDQUFDO1FBQzVELE1BQU0sT0FBTyxHQUFHLFFBQVEsQ0FBQyxPQUFxQyxDQUFDO1FBQy9ELE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxxQkFBVSxDQUFDO1lBQ2xDLFFBQVEsRUFBRTtnQkFDUixHQUFHLFFBQVE7Z0JBQ1gsT0FBTyxFQUFFO29CQUNQLEdBQUcsT0FBTztvQkFDVixXQUFXLEVBQUU7d0JBQ1g7NEJBQ0UsTUFBTSxFQUFFLGFBQWE7NEJBQ3JCLFdBQVcsRUFBRSxzQ0FBc0M7NEJBQ25ELFdBQVcsRUFBRSxnREFBZ0Q7eUJBQzlEO3dCQUNELEdBQUcsT0FBTyxDQUFDLFdBQVc7cUJBQ3ZCO2lCQUNGO2FBQ0Y7U0FDRixDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDO1FBQ25DLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLG9CQUFvQixDQUFDLENBQUM7UUFDL0MsSUFBSSxNQUFNLENBQUMsSUFBSSxLQUFLLG9CQUFvQjtZQUFFLE9BQU87UUFDakQsTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQ2pELE1BQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztRQUNuRSxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3RELENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLDRCQUE0QixFQUFFLEtBQUssSUFBSSxFQUFFO1FBQzFDLE1BQU0sTUFBTSxHQUFHLE1BQU0sYUFBYSxDQUFDLGdCQUFnQixDQUFDLENBQUMsUUFBUSxDQUMzRCxPQUFPLENBQUMsU0FBUyxDQUFDLENBQ25CLENBQUM7UUFDRixNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsYUFBYSxDQUFDO1lBQzNCLElBQUksRUFBRSxVQUFVO1lBQ2hCLE1BQU0sRUFBRSxHQUFHO1lBQ1gsUUFBUSxFQUFFLFFBQVE7U0FDbkIsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsc0VBQXNFLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDcEYsNkVBQTZFO1FBQzdFLHlFQUF5RTtRQUN6RSx1RUFBdUU7UUFDdkUsMkVBQTJFO1FBQzNFLHdDQUF3QztRQUN4QyxNQUFNLE1BQU0sR0FBRyxNQUFNLGFBQWEsQ0FBQyxZQUFZLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDeEUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLGFBQWEsQ0FBQyxFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7SUFDNUUsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsd0RBQXdELEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDdEUsTUFBTSxNQUFNLEdBQUcsTUFBTSxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUMsUUFBUSxDQUN2RCxPQUFPLENBQUMsR0FBRyxFQUFFLEVBQUUsaUJBQWlCLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FDN0MsQ0FBQztRQUNGLDJFQUEyRTtRQUMzRSxzRUFBc0U7UUFDdEUsb0VBQW9FO1FBQ3BFLHlFQUF5RTtRQUN6RSxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsYUFBYSxDQUFDO1lBQzNCLElBQUksRUFBRSxVQUFVO1lBQ2hCLE1BQU0sRUFBRSxHQUFHO1lBQ1gsUUFBUSxFQUFFLFFBQVE7U0FDbkIsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsc0RBQXNELEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDcEUseUVBQXlFO1FBQ3pFLGdDQUFnQztRQUNoQyxNQUFNLE1BQU0sR0FBRyxNQUFNLGFBQWEsQ0FBQyxZQUFZLENBQUMsQ0FBQyxRQUFRLENBQ3ZELE9BQU8sQ0FBQyxHQUFHLEVBQUUsRUFBRSxNQUFNLEVBQUUsZ0JBQWdCLEVBQUUsQ0FBQyxDQUMzQyxDQUFDO1FBQ0YsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLGFBQWEsQ0FBQztZQUMzQixJQUFJLEVBQUUsVUFBVTtZQUNoQixNQUFNLEVBQUUsR0FBRztZQUNYLFFBQVEsRUFBRSxxQkFBcUI7U0FDaEMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsZ0VBQWdFLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDOUUsMkVBQTJFO1FBQzNFLDJFQUEyRTtRQUMzRSx5RUFBeUU7UUFDekUsdUVBQXVFO1FBQ3ZFLGVBQWU7UUFDZixNQUFNLFNBQVMsR0FBRyxlQUFlLENBQy9CLHlCQUFvQixDQUNHLENBQUM7UUFDekIsU0FBUyxDQUFDLE1BQXFDLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQztRQUN0RSxNQUFNLE9BQU8sR0FBRyxTQUFTLENBQUMsT0FFekIsQ0FBQztRQUNGLE9BQU8sQ0FBQyxnQkFBZ0IsR0FBRztZQUN6QjtnQkFDRSxNQUFNLEVBQUUseURBQXlEO2dCQUNqRSxXQUFXLEVBQ1QsaUVBQWlFO2dCQUNuRSxPQUFPLEVBQUUsRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFO2dCQUM3QixNQUFNLEVBQUUsR0FBRztnQkFDWCxRQUFRLEVBQUUsSUFBSTthQUNmO1lBQ0QsR0FBRyxPQUFPLENBQUMsZ0JBQWdCLENBQUMsTUFBTSxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsTUFBTSxLQUFLLEdBQUcsQ0FBQztTQUNwRSxDQUFDO1FBQ0YsTUFBTSxVQUFVLEdBQUcsSUFBSSxxQkFBVSxDQUFDLEVBQUUsUUFBUSxFQUFFLFVBQVUsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUM7UUFFdkUsTUFBTSxDQUFDLE1BQU0sVUFBVSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQztZQUM1RCxJQUFJLEVBQUUsYUFBYTtZQUNuQixRQUFRLEVBQUUsUUFBUTtTQUNuQixDQUFDLENBQUM7UUFDSCxvRUFBb0U7UUFDcEUsTUFBTSxDQUFDLE1BQU0sVUFBVSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQztZQUNqRSxJQUFJLEVBQUUsVUFBVTtZQUNoQixNQUFNLEVBQUUsR0FBRztZQUNYLFFBQVEsRUFBRSxTQUFTO1NBQ3BCLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLDBEQUEwRCxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ3hFLE1BQU0sTUFBTSxHQUFHLE1BQU0sYUFBYSxDQUFDLFlBQVksQ0FBQyxDQUFDLFFBQVEsQ0FDdkQsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUNuQixDQUFDO1FBQ0YsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLGFBQWEsQ0FBQztZQUMzQixJQUFJLEVBQUUsVUFBVTtZQUNoQixNQUFNLEVBQUUsR0FBRztZQUNYLFFBQVEsRUFBRSxRQUFRO1NBQ25CLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLDREQUE0RCxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQzFFLE1BQU0sSUFBSSxHQUFHLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBQ3pDLE1BQU0sUUFBUSxHQUFvQjtZQUNoQyxHQUFHLElBQUk7WUFDUCxVQUFVLEVBQUUsSUFBSTtZQUNoQixPQUFPLEVBQUU7Z0JBQ1AsR0FBSSxJQUFJLENBQUMsT0FBbUM7Z0JBQzVDLFdBQVcsRUFBRTtvQkFDWDt3QkFDRSxXQUFXLEVBQUUsWUFBWTt3QkFDekIsTUFBTSxFQUFFLEdBQUc7d0JBQ1gsT0FBTyxFQUFFLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRTtxQkFDM0I7aUJBQ0Y7YUFDRjtTQUNGLENBQUM7UUFDRixNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUkscUJBQVUsQ0FBQyxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUMsUUFBUSxDQUN4RCxPQUFPLENBQUMsVUFBVSxDQUFDLENBQ3BCLENBQUM7UUFDRixNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsYUFBYSxDQUFDLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQztRQUNoRSxNQUFNLENBQUMsTUFBTSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDekQsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsc0NBQXNDLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDcEQsTUFBTSxNQUFNLEdBQUcsTUFBTSxhQUFhLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxRQUFRLENBQzNELE9BQU8sQ0FBQyx5QkFBeUIsQ0FBQyxDQUNuQyxDQUFDO1FBQ0YsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDdEMsSUFBSSxNQUFNLENBQUMsSUFBSSxLQUFLLFdBQVc7WUFBRSxPQUFPO1FBQ3hDLE1BQU0sQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsSUFBSSxDQUFDLHlCQUF5QixDQUFDLENBQUM7SUFDMUQsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsMkNBQTJDLEVBQUUsR0FBRyxFQUFFO1FBQ25ELE1BQU0sQ0FBQyxjQUFjLENBQUMsU0FBUyxDQUFDLGdCQUFnQixDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUM7WUFDckUsSUFBSSxFQUFFLFlBQVk7WUFDbEIsUUFBUSxFQUFFLGFBQWE7U0FDeEIsQ0FBQyxDQUFDO1FBQ0gsTUFBTSxDQUNKLGNBQWMsQ0FBQyxTQUFTLENBQUMsMEJBQTBCLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FDM0QsQ0FBQyxhQUFhLENBQUM7WUFDZCxJQUFJLEVBQUUsWUFBWTtZQUNsQixRQUFRLEVBQUUsa0JBQWtCO1NBQzdCLENBQUMsQ0FBQztRQUNILDJFQUEyRTtRQUMzRSxpRUFBaUU7UUFDakUsTUFBTSxDQUFDLGNBQWMsQ0FBQyxTQUFTLENBQUMsWUFBWSxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUM7WUFDM0QsSUFBSSxFQUFFLGFBQWE7WUFDbkIsUUFBUSxFQUFFLFlBQVk7WUFDdEIsUUFBUSxFQUFFLFNBQVMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxXQUFXLENBQUMsWUFBWSxDQUFDO1NBQzVELENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLG9EQUFvRCxFQUFFLEdBQUcsRUFBRTtRQUM1RCxpRUFBaUU7UUFDakUseUVBQXlFO1FBQ3pFLHNFQUFzRTtRQUN0RSxNQUFNLFVBQVUsR0FBRyxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDL0MsTUFBTSxFQUFFLFdBQVcsRUFBRSxHQUFHLFNBQVMsQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUNoRCxNQUFNLEVBQUUsR0FBRyxDQUFDLEdBQVcsRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxHQUFHLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQztRQUV6RSxNQUFNLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLEVBQUUsUUFBUSxFQUFFLFdBQVcsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDM0UsTUFBTSxDQUFDLEVBQUUsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQztZQUN0QyxRQUFRLEVBQUUsV0FBVyxDQUFDLFlBQVksQ0FBQztTQUNwQyxDQUFDLENBQUM7UUFDSCxNQUFNLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLEVBQUUsUUFBUSxFQUFFLFdBQVcsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDM0UsMkVBQTJFO1FBQzNFLE1BQU0sQ0FBQyxFQUFFLENBQUMseUJBQXlCLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQztZQUNsRCxRQUFRLEVBQUUsV0FBVyxDQUFDLFNBQVMsQ0FBQztTQUNqQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyxtREFBbUQsRUFBRSxHQUFHLEVBQUU7UUFDM0QsaUVBQWlFO1FBQ2pFLDhEQUE4RDtRQUM5RCxNQUFNLElBQUksR0FBRyxTQUFTLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDckMsTUFBTSxVQUFVLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FDbkMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQzFFLENBQUM7UUFDRixNQUFNLENBQ0osY0FBYyxDQUFDLEVBQUUsR0FBRyxJQUFJLEVBQUUsV0FBVyxFQUFFLFVBQVUsRUFBRSxFQUFFLEdBQUcsQ0FBQyxDQUMxRCxDQUFDLGFBQWEsQ0FBQyxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsUUFBUSxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUM7SUFDL0QsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsK0NBQStDLEVBQUUsR0FBRyxFQUFFO1FBQ3ZELDRFQUE0RTtRQUM1RSx1RUFBdUU7UUFDdkUsd0VBQXdFO1FBQ3hFLHdFQUF3RTtRQUN4RSxNQUFNLElBQUksR0FBRyxTQUFTLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDckMsTUFBTSxhQUFhLEdBQW9CO1lBQ3JDLEdBQUcsSUFBSTtZQUNQLFdBQVcsRUFBRTtnQkFDWCxHQUFHLElBQUksQ0FBQyxXQUFXO2dCQUNuQixNQUFNLEVBQUUsRUFBRSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsU0FBUyxDQUFDLEVBQUUsRUFBRSxFQUFFLE1BQU0sRUFBRTthQUN2RDtTQUNGLENBQUM7UUFDRixNQUFNLENBQUMsY0FBYyxDQUFDLGFBQWEsRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQztZQUN2RCxJQUFJLEVBQUUsWUFBWTtZQUNsQixRQUFRLEVBQUUsTUFBTTtTQUNqQixDQUFDLENBQUM7UUFDSCx3RUFBd0U7UUFDeEUscURBQXFEO1FBQ3JELE1BQU0sQ0FDSixjQUFjLENBQ1o7WUFDRSxHQUFHLGFBQWE7WUFDaEIsV0FBVyxFQUFFO2dCQUNYLEdBQUcsYUFBYSxDQUFDLFdBQVc7Z0JBQzVCLGFBQWEsRUFBRTtvQkFDYixHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsU0FBUyxDQUFDO29CQUM5QixFQUFFLEVBQUUsYUFBYTtpQkFDbEI7YUFDRjtTQUNGLEVBQ0QsR0FBRyxDQUNKLENBQ0YsQ0FBQyxhQUFhLENBQUMsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSxhQUFhLEVBQUUsQ0FBQyxDQUFDO0lBQ25FLENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLGtEQUFrRCxFQUFFLEdBQUcsRUFBRTtRQUMxRCxNQUFNLElBQUksR0FBRyxTQUFTLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUN6QyxNQUFNLGtCQUFrQixHQUFvQjtZQUMxQyxHQUFHLElBQUk7WUFDUCxXQUFXLEVBQUUsRUFBRTtZQUNmLFVBQVUsRUFBRSxJQUFJO1NBQ2pCLENBQUM7UUFDRixNQUFNLENBQUMsY0FBYyxDQUFDLGtCQUFrQixFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDO1lBQ3RELElBQUksRUFBRSxhQUFhO1lBQ25CLFFBQVEsRUFBRSxNQUFNO1lBQ2hCLFFBQVEsRUFBRSxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQztTQUNuQyxDQUFDLENBQUM7UUFDSCxNQUFNLENBQ0osY0FBYyxDQUFDLEVBQUUsR0FBRyxrQkFBa0IsRUFBRSxXQUFXLEVBQUUsRUFBRSxFQUFFLEVBQUUsR0FBRyxDQUFDLENBQ2hFLENBQUMsT0FBTyxDQUFDLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUM7SUFDOUIsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQztBQUVILFFBQVEsQ0FBQyxnQkFBZ0IsRUFBRSxHQUFHLEVBQUU7SUFDOUIsRUFBRSxDQUFDLG9EQUFvRCxFQUFFLEdBQUcsRUFBRTtRQUM1RCxNQUFNLElBQUksR0FBRyxTQUFTLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUN6QyxNQUFNLENBQUMsY0FBYyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQztZQUN4QyxJQUFJLEVBQUUsYUFBYTtZQUNuQixRQUFRLEVBQUUsTUFBTTtZQUNoQixRQUFRLEVBQUUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUM7U0FDbkMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsb0RBQW9ELEVBQUUsR0FBRyxFQUFFO1FBQzVELGdFQUFnRTtRQUNoRSxNQUFNLElBQUksR0FBRyxTQUFTLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDckMsTUFBTSxDQUNKLGNBQWMsQ0FDWjtZQUNFLEdBQUcsSUFBSTtZQUNQLFdBQVcsRUFBRTtnQkFDWCxHQUFHLElBQUksQ0FBQyxXQUFXO2dCQUNuQixNQUFNLEVBQUUsRUFBRSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsU0FBUyxDQUFDLEVBQUUsRUFBRSxFQUFFLE1BQU0sRUFBRTthQUN2RDtTQUNGLEVBQ0QsR0FBRyxDQUNKLENBQ0YsQ0FBQyxhQUFhLENBQUMsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDO0lBQzVELENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLHdDQUF3QyxFQUFFLEdBQUcsRUFBRTtRQUNoRCwyREFBMkQ7UUFDM0Qsa0VBQWtFO1FBQ2xFLE1BQU0sSUFBSSxHQUFHLFNBQVMsQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUNyQyxNQUFNLENBQUMsY0FBYyxDQUFDLEVBQUUsR0FBRyxJQUFJLEVBQUUsV0FBVyxFQUFFLEVBQUUsRUFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDO1lBQ3RFLElBQUksRUFBRSxZQUFZO1lBQ2xCLFFBQVEsRUFBRSxTQUFTO1NBQ3BCLENBQUMsQ0FBQztRQUNILE1BQU0sQ0FDSixjQUFjLENBQUMsRUFBRSxHQUFHLElBQUksRUFBRSxXQUFXLEVBQUUsRUFBRSxFQUFFLFdBQVcsRUFBRSxFQUFFLEVBQUUsRUFBRSxHQUFHLENBQUMsQ0FDbkUsQ0FBQyxPQUFPLENBQUMsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQztJQUM5QixDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyxvREFBb0QsRUFBRSxHQUFHLEVBQUU7UUFDNUQsMEVBQTBFO1FBQzFFLHVFQUF1RTtRQUN2RSxNQUFNLElBQUksR0FBRyxTQUFTLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDckMsTUFBTSxjQUFjLEdBQUcsSUFBQSx3QkFBYSxFQUFDLElBQUksRUFBRSxHQUFHLENBQUMsQ0FBQztRQUNoRCxNQUFNLEVBQUUsR0FBRyxDQUFDLEdBQVcsRUFBRSxFQUFFLENBQUMsY0FBYyxDQUFDLElBQUksR0FBRyxDQUFDLEdBQUcsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO1FBRWpFLE1BQU0sQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUM7WUFDNUIsSUFBSSxFQUFFLGFBQWE7WUFDbkIsUUFBUSxFQUFFLFNBQVM7WUFDbkIsUUFBUSxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsU0FBUyxDQUFDO1NBQ3RDLENBQUMsQ0FBQztRQUNILE1BQU0sQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsRUFBRSxRQUFRLEVBQUUsWUFBWSxFQUFFLENBQUMsQ0FBQztRQUM3RCwyRUFBMkU7UUFDM0UsTUFBTSxDQUFDLEVBQUUsQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDO1lBQ2pELFFBQVEsRUFBRSxTQUFTO1NBQ3BCLENBQUMsQ0FBQztRQUNILHFFQUFxRTtRQUNyRSxNQUFNLENBQUMsY0FBYyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDO1lBQzlDLFFBQVEsRUFBRSxZQUFZO1NBQ3ZCLENBQUMsQ0FBQztRQUNILE1BQU0sQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLEVBQUUsUUFBUSxFQUFFLFlBQVksRUFBRSxDQUFDLENBQUM7SUFDOUUsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsbURBQW1ELEVBQUUsR0FBRyxFQUFFO1FBQzNELE1BQU0sSUFBSSxHQUFHLFNBQVMsQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO1FBQ25ELE1BQU0sQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLEVBQUUsUUFBUSxFQUFFLFdBQVcsRUFBRSxDQUFDLENBQUM7SUFDN0UsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQztBQUVILFFBQVEsQ0FBQyxZQUFZLEVBQUUsR0FBRyxFQUFFO0lBQzFCLEVBQUUsQ0FBQyx1Q0FBdUMsRUFBRSxHQUFHLEVBQUU7UUFDL0Msc0VBQXNFO1FBQ3RFLDZFQUE2RTtRQUM3RSwyREFBMkQ7UUFDM0QsTUFBTSxDQUNKLElBQUEscUJBQVUsRUFDUixFQUFFLFFBQVEsRUFBRSxFQUFFLEdBQUcsRUFBRSxJQUFJLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUMvRCxJQUFJLE9BQU8sRUFBRSxDQUNkLENBQ0YsQ0FBQyxPQUFPLENBQUMsRUFBRSxRQUFRLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFDM0QsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsK0NBQStDLEVBQUUsR0FBRyxFQUFFO1FBQ3ZELE1BQU0sT0FBTyxHQUFHLElBQUksT0FBTyxDQUFDLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7UUFDaEQsTUFBTSxDQUFDLElBQUEscUJBQVUsRUFBQyxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQzdELE1BQU0sQ0FBQyxJQUFBLHFCQUFVLEVBQUMsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUM3RCxNQUFNLENBQUMsSUFBQSxxQkFBVSxFQUFDLEVBQUUsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQ2hELE1BQU0sQ0FBQyxJQUFBLHFCQUFVLEVBQUMsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLEVBQUUsSUFBSSxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUMsYUFBYSxFQUFFLENBQUM7SUFDckUsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQztBQUVILFFBQVEsQ0FBQyxnQ0FBZ0MsRUFBRSxHQUFHLEVBQUU7SUFDOUMsRUFBRSxDQUFDLHlEQUF5RCxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ3ZFLE1BQU0sTUFBTSxHQUFHLE1BQU0sYUFBYSxDQUFDLGdCQUFnQixFQUFFLEtBQUssSUFBSSxFQUFFLENBQUMsQ0FBQztZQUNoRSxRQUFRLEVBQUUsSUFBSTtZQUNkLGVBQWUsRUFBRSxJQUFJLE9BQU8sQ0FBQyxFQUFFLE1BQU0sRUFBRSxXQUFXLEVBQUUsQ0FBQztTQUN0RCxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7UUFDaEMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsc0JBQXNCLENBQUMsQ0FBQztJQUNuRCxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyw4REFBOEQsRUFBRSxLQUFLLElBQUksRUFBRTtRQUM1RSx3RUFBd0U7UUFDeEUsNENBQTRDO1FBQzVDLE1BQU0sTUFBTSxHQUFHLE1BQU0sYUFBYSxDQUFDLGdCQUFnQixFQUFFLEtBQUssSUFBSSxFQUFFLENBQUMsQ0FBQztZQUNoRSxRQUFRLEVBQUUsSUFBSTtTQUNmLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQztRQUNuQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO1FBQ2pELE1BQU0sQ0FBQyxNQUFNLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUM1RCxrQkFBa0IsQ0FDbkIsQ0FBQztRQUVGLE1BQU0sS0FBSyxHQUFHLE1BQU0sYUFBYSxDQUFDLGdCQUFnQixFQUFFLEtBQUssSUFBSSxFQUFFLENBQUMsQ0FBQztZQUMvRCxRQUFRLEVBQUUsSUFBSTtTQUNmLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztRQUNoQyxNQUFNLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUN2RSxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyx3REFBd0QsRUFBRSxLQUFLLElBQUksRUFBRTtRQUN0RSxNQUFNLE1BQU0sR0FBRyxNQUFNLGFBQWEsQ0FBQyxnQkFBZ0IsRUFBRSxLQUFLLElBQUksRUFBRSxDQUFDLENBQUM7WUFDaEUsUUFBUSxFQUFFLEVBQUUsR0FBRyxFQUFFLElBQUksR0FBRyxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFO1NBQzFELENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztRQUNoQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsYUFBYSxDQUFDO1lBQzNCLElBQUksRUFBRSxVQUFVO1lBQ2hCLE1BQU0sRUFBRSxHQUFHO1lBQ1gsdUVBQXVFO1lBQ3ZFLHdFQUF3RTtZQUN4RSxvRUFBb0U7WUFDcEUsZ0VBQWdFO1lBQ2hFLFFBQVEsRUFBRSxRQUFRO1NBQ25CLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLG9FQUFvRSxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ2xGLE1BQU0sTUFBTSxHQUFHLE1BQU0sYUFBYSxDQUFDLGdCQUFnQixFQUFFLEtBQUssSUFBSSxFQUFFLENBQUMsQ0FBQztZQUNoRSxPQUFPLEVBQUUsSUFBSSxHQUFHLENBQUMsYUFBYSxFQUFFLE1BQU0sQ0FBQztTQUN4QyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7UUFDaEMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDdkMsSUFBSSxNQUFNLENBQUMsSUFBSSxLQUFLLFlBQVk7WUFBRSxPQUFPO1FBQ3pDLE1BQU0sQ0FBQyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDdEQsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsbUVBQW1FLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDakYsNEVBQTRFO1FBQzVFLDJFQUEyRTtRQUMzRSxzRUFBc0U7UUFDdEUsTUFBTSxLQUFLLEdBQUcsNEJBQTRCLENBQUM7UUFDM0MsTUFBTSxNQUFNLEdBQUcsTUFBTSxhQUFhLENBQ2hDLDBCQUEwQixFQUMxQixLQUFLLElBQUksRUFBRSxDQUFDLENBQUMsRUFBRSxPQUFPLEVBQUUsSUFBSSxHQUFHLENBQUMsb0JBQW9CLEtBQUssRUFBRSxFQUFFLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FDeEUsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLGVBQWUsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQzVDLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLG9CQUFvQixDQUFDLENBQUM7UUFDL0MsSUFBSSxNQUFNLENBQUMsSUFBSSxLQUFLLG9CQUFvQjtZQUFFLE9BQU87UUFDakQsTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUM5RCxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyx1REFBdUQsRUFBRSxLQUFLLElBQUksRUFBRTtRQUNyRSxNQUFNLE1BQU0sR0FBRyxNQUFNLGFBQWEsQ0FBQyxnQkFBZ0IsRUFBRSxLQUFLLElBQUksRUFBRSxDQUFDLENBQUM7WUFDaEUsT0FBTyxFQUFFLElBQUksR0FBRyxDQUFDLGFBQWEsRUFBRSxNQUFNLENBQUM7WUFDdkMsZUFBZSxFQUFFLElBQUksT0FBTyxDQUFDLEVBQUUsc0JBQXNCLEVBQUUsYUFBYSxFQUFFLENBQUM7U0FDeEUsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO1FBQ2hDLE1BQU0sQ0FBQyxNQUFNLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3pFLENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLDBEQUEwRCxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ3hFLE1BQU0sTUFBTSxHQUFHLE1BQU0sYUFBYSxDQUFDLGdCQUFnQixFQUFFLEtBQUssSUFBSSxFQUFFLENBQUMsQ0FBQztZQUNoRSxPQUFPLEVBQUUsSUFBSSxHQUFHLENBQUMseUJBQXlCLENBQUM7U0FDNUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO1FBQ2hDLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLENBQUM7UUFDN0MsSUFBSSxNQUFNLENBQUMsSUFBSSxLQUFLLGtCQUFrQjtZQUFFLE9BQU87UUFDL0MsTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLHlCQUF5QixDQUFDLENBQUM7SUFDMUQsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsc0VBQXNFLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDcEYsc0VBQXNFO1FBQ3RFLHlFQUF5RTtRQUN6RSw4Q0FBOEM7UUFDOUMseURBQXlEO1FBQ3pELE1BQU0sTUFBTSxHQUFHLE1BQU0sYUFBYSxDQUFDLGdCQUFnQixFQUFFLEtBQUssSUFBSSxFQUFFLENBQUMsQ0FBQztZQUNoRSxjQUFjLEVBQUUsSUFBSSxPQUFPLENBQUMsRUFBRSxJQUFJLEVBQUUsY0FBYyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsQ0FBQztZQUNyRSxlQUFlLEVBQUUsSUFBSSxPQUFPLENBQUMsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLENBQUM7U0FDaEQsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO1FBQ2hDLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ3ZDLElBQUksTUFBTSxDQUFDLElBQUksS0FBSyxZQUFZO1lBQUUsT0FBTztRQUN6QyxNQUFNLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDdkQsTUFBTSxDQUFDLE1BQU0sQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3pELENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLHVFQUF1RSxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ3JGLE1BQU0sTUFBTSxHQUFHLE1BQU0sYUFBYSxDQUFDLGdCQUFnQixDQUFDLENBQUMsUUFBUSxDQUMzRCxPQUFPLENBQUMsUUFBUSxFQUFFLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQ3pDLENBQUM7UUFDRixNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUN2QyxJQUFJLE1BQU0sQ0FBQyxJQUFJLEtBQUssWUFBWTtZQUFFLE9BQU87UUFDekMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzVELENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUM7QUFFSCxRQUFRLENBQUMsdUJBQXVCLEVBQUUsR0FBRyxFQUFFO0lBQ3JDLEVBQUUsQ0FBQyxpRUFBaUUsRUFBRSxHQUFHLEVBQUU7UUFDekUsaUVBQWlFO1FBQ2pFLDRFQUE0RTtRQUM1RSw2RUFBNkU7UUFDN0UsMERBQTBEO1FBQzFELE1BQU0sQ0FDSixJQUFBLGdDQUFxQixFQUNuQixFQUFFLFVBQVUsRUFBRSxTQUFVLEVBQUUsRUFDMUI7WUFDRSxVQUFVLEVBQUUsU0FBUztTQUN0QixDQUNGLENBQ0YsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDZCw4RUFBOEU7UUFDOUUsTUFBTSxDQUFDLElBQUEsZ0NBQXFCLEVBQUMsRUFBRSxVQUFVLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDbEUsNkRBQTZEO1FBQzdELE1BQU0sQ0FDSixJQUFBLGdDQUFxQixFQUFDLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQ3BFLENBQUMsT0FBTyxDQUFDLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDakMseUVBQXlFO1FBQ3pFLDZFQUE2RTtRQUM3RSw2RUFBNkU7UUFDN0UsMkNBQTJDO1FBQzNDLE1BQU0sQ0FBQyxJQUFBLGdDQUFxQixFQUFDLEVBQUUsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsTUFBTSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDMUUsMkNBQTJDO1FBQzNDLE1BQU0sQ0FBQyxJQUFBLGdDQUFxQixFQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDbEUsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsK0JBQStCLEVBQUUsR0FBRyxFQUFFO1FBQ3ZDLDBFQUEwRTtRQUMxRSx5REFBeUQ7UUFDekQsTUFBTSxDQUNKLElBQUEsZ0NBQXFCLEVBQ25CLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxFQUFFLEVBQUUsRUFDNUMsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxHQUFHLEVBQUUsQ0FDOUIsQ0FDRixDQUFDLE9BQU8sQ0FBQyxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsT0FBTyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFDM0MsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQztBQUVILFFBQVEsQ0FBQyxzQkFBc0IsRUFBRSxHQUFHLEVBQUU7SUFDcEMsRUFBRSxDQUFDLDZDQUE2QyxFQUFFLEdBQUcsRUFBRTtRQUNyRCxNQUFNLENBQ0osSUFBQSwrQkFBb0IsRUFDbEIsRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUUsRUFDM0Isd0JBQXdCLENBQ3pCLENBQ0YsQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUNsQixNQUFNLENBQUMsSUFBQSwrQkFBb0IsRUFBQyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsRUFBRSxXQUFXLENBQUMsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQzVFLDJFQUEyRTtRQUMzRSxNQUFNLENBQ0osSUFBQSwrQkFBb0IsRUFBQyxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsRUFBRSx3QkFBd0IsQ0FBQyxDQUMvRCxDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQ3BCLENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLHNFQUFzRSxFQUFFLEdBQUcsRUFBRTtRQUM5RSwwRUFBMEU7UUFDMUUsMkVBQTJFO1FBQzNFLG9FQUFvRTtRQUNwRSxNQUFNLENBQ0osSUFBQSwrQkFBb0IsRUFDbEIsRUFBRSxRQUFRLEVBQUUscUNBQXFDLEVBQUUsRUFDbkQsaURBQWlELENBQ2xELENBQ0YsQ0FBQyxPQUFPLENBQUM7WUFDUixNQUFNLEVBQUUsRUFBRSxJQUFJLEVBQUUsQ0FBQyxpQ0FBaUMsQ0FBQyxFQUFFO1lBQ3JELEtBQUssRUFBRSxFQUFFO1NBQ1YsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMseUVBQXlFLEVBQUUsR0FBRyxFQUFFO1FBQ2pGLE1BQU0sQ0FDSixJQUFBLCtCQUFvQixFQUNsQixFQUFFLFFBQVEsRUFBRSxXQUFXLEVBQUUsRUFDekIsMEJBQTBCLENBQzNCLENBQ0YsQ0FBQyxPQUFPLENBQUMsRUFBRSxNQUFNLEVBQUUsRUFBRSxJQUFJLEVBQUUsQ0FBQyxHQUFHLEVBQUUsS0FBSyxFQUFFLEdBQUcsQ0FBQyxFQUFFLEVBQUUsS0FBSyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDOUQsTUFBTSxDQUFDLElBQUEsK0JBQW9CLEVBQUMsRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLEVBQUUsV0FBVyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUM7WUFDckUsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEtBQUssRUFBRTtZQUNyQixLQUFLLEVBQUUsRUFBRTtTQUNWLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLHlEQUF5RCxFQUFFLEdBQUcsRUFBRTtRQUNqRSxNQUFNLENBQ0osSUFBQSwrQkFBb0IsRUFDbEIsRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxFQUM1Qyx3QkFBd0IsQ0FDekIsQ0FDRixDQUFDLE9BQU8sQ0FBQztZQUNSLE1BQU0sRUFBRSxFQUFFLElBQUksRUFBRSxDQUFDLEtBQUssQ0FBQyxFQUFFO1lBQ3pCLEtBQUssRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRTtTQUNqQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyw2REFBNkQsRUFBRSxHQUFHLEVBQUU7UUFDckUseUVBQXlFO1FBQ3pFLHlFQUF5RTtRQUN6RSxNQUFNLENBQ0osSUFBQSwrQkFBb0IsRUFDbEIsRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLFlBQVksRUFBRSxFQUFFLEVBQUUsRUFDdkMsd0NBQXdDLENBQ3pDLENBQ0YsQ0FBQyxhQUFhLEVBQUUsQ0FBQztJQUNwQixDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyx3REFBd0QsRUFBRSxHQUFHLEVBQUU7UUFDaEUsNkVBQTZFO1FBQzdFLCtEQUErRDtRQUMvRCxNQUFNLENBQ0osSUFBQSwrQkFBb0IsRUFBQyxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsRUFBRSx3QkFBd0IsQ0FBQyxDQUN4RSxDQUFDLE9BQU8sQ0FBQyxFQUFFLE1BQU0sRUFBRSxFQUFFLElBQUksRUFBRSxDQUFDLFNBQVMsQ0FBQyxFQUFFLEVBQUUsS0FBSyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDMUQsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llcyAqL1xuaW1wb3J0IHsgbWtkaXJTeW5jLCBta2R0ZW1wU3luYywgd3JpdGVGaWxlU3luYyB9IGZyb20gXCJub2RlOmZzXCI7XG5pbXBvcnQgeyB0bXBkaXIgfSBmcm9tIFwibm9kZTpvc1wiO1xuaW1wb3J0IHsgZGlybmFtZSwgam9pbiB9IGZyb20gXCJub2RlOnBhdGhcIjtcbmltcG9ydCB7IE1pZGRsZXdhcmVSZXN1bHQgfSBmcm9tIFwiQG5leHQvcm91dGluZ1wiO1xuaW1wb3J0IHtcbiAgRGlzcGF0Y2hSZXF1ZXN0LFxuICBEaXNwYXRjaGVyLFxuICBvdXRPZkJhbmRSb3V0ZVBhcmFtcyxcbiAgcmVwYWlyUm91dGVQYXJhbVF1ZXJ5LFxuICBzdGF0dXNUYXJnZXRzLFxuICB0b1JlZGlyZWN0LFxufSBmcm9tIFwiLi9kaXNwYXRjaFwiO1xuaW1wb3J0IHsgQWRhcHRlck1hbmlmZXN0IH0gZnJvbSBcIi4vbWFuaWZlc3RcIjtcbmltcG9ydCB7IHJlYWRQdWJsaWNGaWxlcyB9IGZyb20gXCIuL3B1YmxpYy1maWxlc1wiO1xuaW1wb3J0IGFwcFBsYXlncm91bmRCYXNlUGF0aCBmcm9tIFwiLi4vYWRhcHRlci9fX2ZpeHR1cmVzX18vYXBwLXBsYXlncm91bmQtYmFzZS1wYXRoLmpzb25cIjtcbmltcG9ydCBhcHBQbGF5Z3JvdW5kIGZyb20gXCIuLi9hZGFwdGVyL19fZml4dHVyZXNfXy9hcHAtcGxheWdyb3VuZC5qc29uXCI7XG5pbXBvcnQgcGFnZXNJMThuIGZyb20gXCIuLi9hZGFwdGVyL19fZml4dHVyZXNfXy9wYWdlcy1pMThuLmpzb25cIjtcbmltcG9ydCB7XG4gIEJ1aWxkQ29tcGxldGVDb250ZXh0LFxuICBidWlsZEFkYXB0ZXJNYW5pZmVzdCxcbn0gZnJvbSBcIi4uL2FkYXB0ZXIvYnVpbGQtb3V0cHV0c1wiO1xuXG4vKipcbiAqIERpc3BhdGNoIGlzIHRlc3RlZCBhZ2FpbnN0IHRoZSBtYW5pZmVzdHMgdGhhdCBzdGVwIDEgcHJvZHVjZXMgZnJvbSByZWFsXG4gKiBgb25CdWlsZENvbXBsZXRlYCBjYXB0dXJlcywgcmF0aGVyIHRoYW4gYWdhaW5zdCBoYW5kLXdyaXR0ZW4gbWFuaWZlc3RzOiB0aGVcbiAqIHRoaW5nIG1vc3QgbGlrZWx5IHRvIGJyZWFrIGlzIHRoZSBjb3JyZXNwb25kZW5jZSBiZXR3ZWVuIGhvdyB0aGUgYnVpbGQga2V5c1xuICogYGVudHJ5cG9pbnRzYCBhbmQgaG93IGByZXNvbHZlUm91dGVzYCByZXBvcnRzIGByZXNvbHZlZFBhdGhuYW1lYCwgYW5kIGFcbiAqIGhhbmQtd3JpdHRlbiBtYW5pZmVzdCB3b3VsZCBhc3N1bWUgdGhhdCBjb3JyZXNwb25kZW5jZSBpbnN0ZWFkIG9mIHByb3ZpbmcgaXQuXG4gKi9cbmZ1bmN0aW9uIG1hbmlmZXN0T2YoZml4dHVyZTogdW5rbm93bik6IEFkYXB0ZXJNYW5pZmVzdCB7XG4gIGNvbnN0IHdhcm4gPSBqZXN0LnNweU9uKGNvbnNvbGUsIFwid2FyblwiKS5tb2NrSW1wbGVtZW50YXRpb24oKCkgPT4ge30pO1xuICB0cnkge1xuICAgIGNvbnN0IGN0eCA9IHN0cnVjdHVyZWRDbG9uZShmaXh0dXJlKSBhcyBCdWlsZENvbXBsZXRlQ29udGV4dDtcbiAgICAvLyBUaGUgZml4dHVyZXMnIHByb2plY3QgZGlycyBhcmUgc3ludGhldGljIGAvcmVwby/igKZgIHBhdGhzLCBzbyB0aGUgYnVpbGQgY3dkXG4gICAgLy8gaGFzIHRvIGJlIHN0YXRlZDsgc2VlIGBhc3NlcnRCdWlsZEN3ZGAuXG4gICAgcmV0dXJuIGJ1aWxkQWRhcHRlck1hbmlmZXN0KGN0eCwgeyBidWlsZEN3ZDogY3R4LnByb2plY3REaXIgfSkubWFuaWZlc3Q7XG4gIH0gZmluYWxseSB7XG4gICAgd2Fybi5tb2NrUmVzdG9yZSgpO1xuICB9XG59XG5cbi8qKlxuICogVGhlIGZpeHR1cmUgd2l0aCBgYXBwL3BhcmFtcy9vcHRpb25hbC9bWy4uLnJlc3RdXWAgbW92ZWQgdG8gYGFwcC9bWy4uLnJlc3RdXWAsXG4gKiBhIHJvb3Qgb3B0aW9uYWwgY2F0Y2gtYWxsOiBhIHJvdXRlIGV2ZXJ5IHJlcXVlc3Qgbm90IGNsYWltZWQgZWFybGllciBmYWxsc1xuICogaW50bywgYC9fbmV4dC9pbWFnZWAgaW5jbHVkZWQgdW5sZXNzIGRpc3BhdGNoIHB1dHMgaXQgYWhlYWQgb2YgdGhlbS4gTm8gZXhhbXBsZVxuICogYXBwIGhhcyBvbmUsIGFuZCBhIGNhcHR1cmUgd291bGQgYWRkIGEgd2hvbGUgYXBwIHRvIGNvdmVyIG9uZSByb3V0ZSwgc28gdGhlXG4gKiByb3V0ZSBpcyBtb3ZlZCByYXRoZXIgdGhhbiBjYXB0dXJlZC5cbiAqL1xuZnVuY3Rpb24gd2l0aFJvb3RDYXRjaEFsbChmaXh0dXJlOiB1bmtub3duKTogdW5rbm93biB7XG4gIHJldHVybiBKU09OLnBhcnNlKFxuICAgIEpTT04uc3RyaW5naWZ5KGZpeHR1cmUpXG4gICAgICAuc3BsaXQoXCIvcGFyYW1zL29wdGlvbmFsL1tbLi4ucmVzdF1dXCIpXG4gICAgICAuam9pbihcIi9bWy4uLnJlc3RdXVwiKVxuICAgICAgLnNwbGl0KFwiWy9dPy9wYXJhbXMvb3B0aW9uYWwoPzpcIilcbiAgICAgIC5qb2luKFwiWy9dPyg/OlwiKSxcbiAgKTtcbn1cblxuY29uc3QgbWFuaWZlc3RzID0ge1xuICBcImFwcC1wbGF5Z3JvdW5kXCI6IG1hbmlmZXN0T2YoYXBwUGxheWdyb3VuZCksXG4gIFwiYXBwLXBsYXlncm91bmQtYmFzZS1wYXRoXCI6IG1hbmlmZXN0T2YoYXBwUGxheWdyb3VuZEJhc2VQYXRoKSxcbiAgXCJhcHAtcGxheWdyb3VuZC1yb290LWNhdGNoLWFsbFwiOiBtYW5pZmVzdE9mKHdpdGhSb290Q2F0Y2hBbGwoYXBwUGxheWdyb3VuZCkpLFxuICBcImFwcC1wbGF5Z3JvdW5kLWJhc2UtcGF0aC1yb290LWNhdGNoLWFsbFwiOiBtYW5pZmVzdE9mKFxuICAgIHdpdGhSb290Q2F0Y2hBbGwoYXBwUGxheWdyb3VuZEJhc2VQYXRoKSxcbiAgKSxcbiAgXCJwYWdlcy1pMThuXCI6IG1hbmlmZXN0T2YocGFnZXNJMThuKSxcbn0gYXMgY29uc3Q7XG5cbmNvbnN0IE9SSUdJTiA9IFwiaHR0cHM6Ly9leGFtcGxlLnRlc3RcIjtcblxuZnVuY3Rpb24gcmVxdWVzdCh1cmw6IHN0cmluZywgaGVhZGVyczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9KSB7XG4gIGNvbnN0IHJlc3VsdDogRGlzcGF0Y2hSZXF1ZXN0ID0ge1xuICAgIG1ldGhvZDogXCJHRVRcIixcbiAgICB1cmw6IG5ldyBVUkwodXJsLCBPUklHSU4pLFxuICAgIGhlYWRlcnM6IG5ldyBIZWFkZXJzKHsgaG9zdDogXCJleGFtcGxlLnRlc3RcIiwgLi4uaGVhZGVycyB9KSxcbiAgICAvLyBHRVQvSEVBRCBoYXZlIG5vIGJvZHksIGJ1dCBgcmVzb2x2ZVJvdXRlc2AgcmVxdWlyZXMgYSBzdHJlYW0uXG4gICAgYm9keTogbmV3IFJlYWRhYmxlU3RyZWFtKHtcbiAgICAgIHN0YXJ0KGNvbnRyb2xsZXIpIHtcbiAgICAgICAgY29udHJvbGxlci5jbG9zZSgpO1xuICAgICAgfSxcbiAgICB9KSxcbiAgICAvLyBNaWRkbGV3YXJlIHRoYXQgbGV0cyBldmVyeSByZXF1ZXN0IHRocm91Z2guXG4gICAgaW52b2tlTWlkZGxld2FyZTogYXN5bmMgKCkgPT4gKHsgcmVzcG9uc2U6IG5ldyBSZXNwb25zZSgpIH0pLFxuICB9O1xuICByZXR1cm4gcmVzdWx0O1xufVxuXG4vKiogQSBEaXNwYXRjaGVyIG92ZXIgYG5hbWVgLCB3aG9zZSBtaWRkbGV3YXJlLCBpZiBnaXZlbiwgYW5zd2VycyBgbWlkZGxld2FyZSgpYC4gKi9cbmZ1bmN0aW9uIGRpc3BhdGNoZXJGb3IoXG4gIG5hbWU6IGtleW9mIHR5cGVvZiBtYW5pZmVzdHMsXG4gIG1pZGRsZXdhcmU/OiAoKSA9PiBQcm9taXNlPE1pZGRsZXdhcmVSZXN1bHQ+LFxuKTogUGljazxEaXNwYXRjaGVyLCBcImRpc3BhdGNoXCIgfCBcIm5vdEZvdW5kRm9yXCI+IHtcbiAgY29uc3QgZGlzcGF0Y2hlciA9IG5ldyBEaXNwYXRjaGVyKHsgbWFuaWZlc3Q6IG1hbmlmZXN0c1tuYW1lXSB9KTtcbiAgcmV0dXJuIHtcbiAgICBub3RGb3VuZEZvcjogZGlzcGF0Y2hlci5ub3RGb3VuZEZvcixcbiAgICBkaXNwYXRjaDogKHJlcSkgPT5cbiAgICAgIGRpc3BhdGNoZXIuZGlzcGF0Y2goXG4gICAgICAgIG1pZGRsZXdhcmVcbiAgICAgICAgICA/IHtcbiAgICAgICAgICAgICAgLi4ucmVxLFxuICAgICAgICAgICAgICBpbnZva2VNaWRkbGV3YXJlOiBhc3luYyAoKSA9PiAoe1xuICAgICAgICAgICAgICAgIC4uLihhd2FpdCBtaWRkbGV3YXJlKCkpLFxuICAgICAgICAgICAgICAgIHJlc3BvbnNlOiBuZXcgUmVzcG9uc2UoKSxcbiAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICB9XG4gICAgICAgICAgOiByZXEsXG4gICAgICApLFxuICB9O1xufVxuXG4vKiogVGhlIDQwNCBvciA1MDAgYSByZXF1ZXN0IHdpdGggbm8gbG9jYWxlIGdldHMuICovXG5mdW5jdGlvbiBzdGF0dXNUYXJnZXRPZihtYW5pZmVzdDogQWRhcHRlck1hbmlmZXN0LCBzdGF0dXM6IDQwNCB8IDUwMCkge1xuICByZXR1cm4gc3RhdHVzVGFyZ2V0cyhtYW5pZmVzdCwgc3RhdHVzKSh1bmRlZmluZWQpO1xufVxuXG5kZXNjcmliZShcIkRpc3BhdGNoZXIgZW50cnlwb2ludCByZXNvbHV0aW9uXCIsICgpID0+IHtcbiAgaXQoXCJyZXNvbHZlcyBhIGR5bmFtaWMgQXBwIFJvdXRlciBwYWdlIHRvIGl0cyB0ZW1wbGF0ZSBlbnRyeXBvaW50XCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBkaXNwYXRjaGVyRm9yKFwiYXBwLXBsYXlncm91bmRcIikuZGlzcGF0Y2goXG4gICAgICByZXF1ZXN0KFwiL2lzci8xXCIpLFxuICAgICk7XG4gICAgZXhwZWN0KHJlc3VsdC5raW5kKS50b0JlKFwiZW50cnlwb2ludFwiKTtcbiAgICBpZiAocmVzdWx0LmtpbmQgIT09IFwiZW50cnlwb2ludFwiKSByZXR1cm47XG4gICAgLy8gYHJlc29sdmVkUGF0aG5hbWVgIGlzIHRoZSB0ZW1wbGF0ZTsgYGludm9jYXRpb25UYXJnZXRgIGlzIGNvbmNyZXRlLiBCb3RoXG4gICAgLy8gYXJlIG5lZWRlZDogdGhlIGZpcnN0IHBpY2tzIHRoZSBtb2R1bGUsIHRoZSBzZWNvbmQgaXMgd2hhdCBpdCByZW5kZXJzLlxuICAgIGV4cGVjdChyZXN1bHQucmVzb2x2ZWRQYXRobmFtZSkudG9CZShcIi9pc3IvW2lkXVwiKTtcbiAgICBleHBlY3QocmVzdWx0Lmludm9jYXRpb25UYXJnZXQpLnRvRXF1YWwoe1xuICAgICAgcGF0aG5hbWU6IFwiL2lzci8xXCIsXG4gICAgICBxdWVyeTogeyBueHRQaWQ6IFwiMVwiIH0sXG4gICAgfSk7XG4gICAgZXhwZWN0KHJlc3VsdC5lbnRyeXBvaW50LmZpbGVQYXRoKS50b0NvbnRhaW4oXCJpc3IvW2lkXS9wYWdlLmpzXCIpO1xuICAgIGV4cGVjdChyZXN1bHQuZW50cnlwb2ludC50eXBlKS50b0JlKFwiYXBwLXBhZ2VcIik7XG4gIH0pO1xuXG4gIGl0KFwicmVzb2x2ZXMgYW4gQXBwIFJvdXRlciByb3V0ZSBoYW5kbGVyXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBkaXNwYXRjaGVyRm9yKFwiYXBwLXBsYXlncm91bmRcIikuZGlzcGF0Y2goXG4gICAgICByZXF1ZXN0KFwiL2FwaS9oZWFsdGhcIiksXG4gICAgKTtcbiAgICBleHBlY3QocmVzdWx0LmtpbmQpLnRvQmUoXCJlbnRyeXBvaW50XCIpO1xuICAgIGlmIChyZXN1bHQua2luZCAhPT0gXCJlbnRyeXBvaW50XCIpIHJldHVybjtcbiAgICBleHBlY3QocmVzdWx0LmVudHJ5cG9pbnQudHlwZSkudG9CZShcImFwcC1yb3V0ZVwiKTtcbiAgICBleHBlY3QocmVzdWx0LnJlc29sdmVkUGF0aG5hbWUpLnRvQmUoXCIvYXBpL2hlYWx0aFwiKTtcbiAgfSk7XG5cbiAgaXQoXCJtYXRjaGVzIGJhc2VQYXRoLXByZWZpeGVkIGVudHJ5cG9pbnQga2V5cyB3aXRob3V0IG5vcm1hbGl6YXRpb25cIiwgYXN5bmMgKCkgPT4ge1xuICAgIC8vIFN0ZXAgMSBrZXllZCBgZW50cnlwb2ludHNgIGJ5IHRoZSBiYXNlUGF0aC1wcmVmaXhlZCBgb3V0cHV0LnBhdGhuYW1lYCBhbmRcbiAgICAvLyBsZWZ0IG9wZW4gd2hldGhlciBgcmVzb2x2ZWRQYXRobmFtZWAgY29tZXMgYmFjayBwcmVmaXhlZC4gSXQgZG9lcyDigJQgdGhpc1xuICAgIC8vIHRlc3QgaXMgd2hhdCBjbG9zZXMgdGhhdCBxdWVzdGlvbi5cbiAgICBjb25zdCBkaXNwYXRjaGVyID0gZGlzcGF0Y2hlckZvcihcImFwcC1wbGF5Z3JvdW5kLWJhc2UtcGF0aFwiKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBkaXNwYXRjaGVyLmRpc3BhdGNoKHJlcXVlc3QoXCIvcHJvZC9pc3IvMVwiKSk7XG4gICAgZXhwZWN0KHJlc3VsdC5raW5kKS50b0JlKFwiZW50cnlwb2ludFwiKTtcbiAgICBpZiAocmVzdWx0LmtpbmQgIT09IFwiZW50cnlwb2ludFwiKSByZXR1cm47XG4gICAgZXhwZWN0KHJlc3VsdC5yZXNvbHZlZFBhdGhuYW1lKS50b0JlKFwiL3Byb2QvaXNyL1tpZF1cIik7XG4gICAgZXhwZWN0KHJlc3VsdC5pbnZvY2F0aW9uVGFyZ2V0LnBhdGhuYW1lKS50b0JlKFwiL3Byb2QvaXNyLzFcIik7XG5cbiAgICAvLyBUaGUgc2FtZSBwYXRoIHdpdGhvdXQgdGhlIHByZWZpeCBpcyBub3QgdGhlIGFwcCdzLlxuICAgIGNvbnN0IHVucHJlZml4ZWQgPSBhd2FpdCBkaXNwYXRjaGVyLmRpc3BhdGNoKHJlcXVlc3QoXCIvaXNyLzFcIikpO1xuICAgIGV4cGVjdCh1bnByZWZpeGVkLmtpbmQpLnRvQmUoXCJub3QtZm91bmRcIik7XG4gIH0pO1xuXG4gIGl0KFwicmVzb2x2ZXMgYSBQYWdlcyBSb3V0ZXIgcGFnZSBhbmQgQVBJIHJvdXRlXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBkaXNwYXRjaGVyID0gZGlzcGF0Y2hlckZvcihcInBhZ2VzLWkxOG5cIik7XG4gICAgY29uc3QgcGFnZSA9IGF3YWl0IGRpc3BhdGNoZXIuZGlzcGF0Y2gocmVxdWVzdChcIi9lbi1VUy9zc3JcIikpO1xuICAgIGV4cGVjdChwYWdlLmtpbmQpLnRvQmUoXCJlbnRyeXBvaW50XCIpO1xuICAgIGlmIChwYWdlLmtpbmQgPT09IFwiZW50cnlwb2ludFwiKSB7XG4gICAgICBleHBlY3QocGFnZS5lbnRyeXBvaW50LnR5cGUpLnRvQmUoXCJwYWdlXCIpO1xuICAgIH1cbiAgICBjb25zdCBhcGkgPSBhd2FpdCBkaXNwYXRjaGVyLmRpc3BhdGNoKHJlcXVlc3QoXCIvYXBpL2hlbGxvXCIpKTtcbiAgICBleHBlY3QoYXBpLmtpbmQpLnRvQmUoXCJlbnRyeXBvaW50XCIpO1xuICAgIGlmIChhcGkua2luZCA9PT0gXCJlbnRyeXBvaW50XCIpIHtcbiAgICAgIGV4cGVjdChhcGkuZW50cnlwb2ludC50eXBlKS50b0JlKFwicGFnZS1hcGlcIik7XG4gICAgfVxuICB9KTtcblxuICBpdChcInJlc29sdmVzIGEgUGFnZXMgUm91dGVyIElTUiBkYXRhIFVSTCB2aWEgaXRzIHByZXJlbmRlciB0ZW1wbGF0ZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgLy8gVGhpcyBvbmx5IHdvcmtzIGJlY2F1c2UgYGJ1aWxkQWRhcHRlck1hbmlmZXN0YCBhZGRzIGR5bmFtaWMgKnByZXJlbmRlcipcbiAgICAvLyB0ZW1wbGF0ZXMgdG8gYHBhdGhuYW1lc2AvYGVudHJ5cG9pbnRzYDogYC9fbmV4dC9kYXRhL+KApi9bc2x1Z10uanNvbmAgaXNcbiAgICAvLyBub3QgYSByb3V0ZSBvdXRwdXQsIHNvIHdpdGhvdXQgaXQgdGhpcyBVUkwgNDA0cyB3aGlsZSBgbmV4dCBzdGFydGAgc2VydmVzXG4gICAgLy8gaXQuXG4gICAgY29uc3QgeyBidWlsZElkIH0gPSBtYW5pZmVzdHNbXCJwYWdlcy1pMThuXCJdO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGRpc3BhdGNoZXJGb3IoXCJwYWdlcy1pMThuXCIpLmRpc3BhdGNoKFxuICAgICAgcmVxdWVzdChgL19uZXh0L2RhdGEvJHtidWlsZElkfS9mci9ibG9nL2hlbGxvLmpzb25gKSxcbiAgICApO1xuICAgIGV4cGVjdChyZXN1bHQua2luZCkudG9CZShcImVudHJ5cG9pbnRcIik7XG4gICAgaWYgKHJlc3VsdC5raW5kICE9PSBcImVudHJ5cG9pbnRcIikgcmV0dXJuO1xuICAgIGV4cGVjdChyZXN1bHQucmVzb2x2ZWRQYXRobmFtZSkudG9CZShcbiAgICAgIGAvX25leHQvZGF0YS8ke2J1aWxkSWR9L2ZyL2Jsb2cvW3NsdWddLmpzb25gLFxuICAgICk7XG4gICAgZXhwZWN0KHJlc3VsdC5lbnRyeXBvaW50LmZpbGVQYXRoKS50b0NvbnRhaW4oXCJibG9nL1tzbHVnXVwiKTtcbiAgICBleHBlY3QocmVzdWx0Lmludm9jYXRpb25UYXJnZXQucXVlcnkpLnRvTWF0Y2hPYmplY3QoeyBueHRQc2x1ZzogXCJoZWxsb1wiIH0pO1xuICB9KTtcblxuICBpdChcInJlc29sdmVzIHRoZSBjYW5vbmljYWwgdHJhaWxpbmctc2xhc2ggVVJMIG9mIGEgYHRyYWlsaW5nU2xhc2hgIGFwcFwiLCBhc3luYyAoKSA9PiB7XG4gICAgLy8gVGhlIGJ1aWxkJ3MgcGF0aG5hbWVzIG5ldmVyIGNhcnJ5IHRoZSBzbGFzaCwgYnV0IGB0cmFpbGluZ1NsYXNoOiB0cnVlYFxuICAgIC8vIG1ha2VzIGAvYS9gIHRoZSBVUkwgTmV4dC5qcydzIG93biAzMDggc2VuZHMgYnJvd3NlcnMgdG8sIGFuZFxuICAgIC8vIGBAbmV4dC9yb3V0aW5nYCBtYXRjaGVzIHBhdGhuYW1lcyBieSBleGFjdCBlcXVhbGl0eS4gTWVhc3VyZWQgYWdhaW5zdFxuICAgIC8vIG5leHQuanMncyBgdGVzdC9lMmUvYXBwLWRpci90cmFpbGluZ3NsYXNoYDogd2l0aG91dCB0aGlzLCA2IG9mIDggY2FzZXNcbiAgICAvLyBmYWlsZWQsIGluY2x1ZGluZyBgZmV0Y2goJy9hcGkvcmV2YWxpZGF0ZScpYCBnZXR0aW5nIHRoZSA0MDQgcGFnZS5cbiAgICBjb25zdCB3aXRoU2xhc2ggPSBzdHJ1Y3R1cmVkQ2xvbmUoXG4gICAgICBhcHBQbGF5Z3JvdW5kIGFzIHVua25vd24sXG4gICAgKSBhcyBCdWlsZENvbXBsZXRlQ29udGV4dDtcbiAgICAod2l0aFNsYXNoLmNvbmZpZyBhcyB7IHRyYWlsaW5nU2xhc2g6IGJvb2xlYW4gfSkudHJhaWxpbmdTbGFzaCA9IHRydWU7XG4gICAgLy8gQWxsIHRocmVlIGNhcHR1cmVzIGFyZSBmcm9tIGFwcHMgd2l0aCB0aGUgZGVmYXVsdCBgdHJhaWxpbmdTbGFzaDogZmFsc2VgLFxuICAgIC8vIHNvIHRoZWlyIGBiZWZvcmVNaWRkbGV3YXJlYCBjYXJyaWVzIHRoZSAqc3RyaXAqLXNsYXNoIDMwOCAoYC9hL2Ag4oaSIGAvYWApLlxuICAgIC8vIExlYXZpbmcgaXQgaW4gd291bGQgbWFrZSB0aGUgY2xvbmUgaW5jb2hlcmVudCDigJQgdGhhdCByZWRpcmVjdCBpcyB3aGF0IGFcbiAgICAvLyByZWFsIGB0cmFpbGluZ1NsYXNoOiB0cnVlYCBidWlsZCByZXBsYWNlcyB3aXRoIHRoZSBhZGQtc2xhc2ggb25lIOKAlCBhbmQgaXRcbiAgICAvLyBmaXJlcyBiZWZvcmUgYW55IHBhdGhuYW1lIGlzIG1hdGNoZWQsIHNvIG5vdGhpbmcgYmVsb3cgd291bGQgYmUgcmVhY2hlZC5cbiAgICBjb25zdCByb3V0aW5nID0gd2l0aFNsYXNoLnJvdXRpbmcgYXMge1xuICAgICAgYmVmb3JlTWlkZGxld2FyZTogeyBzdGF0dXM/OiBudW1iZXIgfVtdO1xuICAgIH07XG4gICAgcm91dGluZy5iZWZvcmVNaWRkbGV3YXJlID0gcm91dGluZy5iZWZvcmVNaWRkbGV3YXJlLmZpbHRlcihcbiAgICAgIChyb3V0ZSkgPT4gcm91dGUuc3RhdHVzICE9PSAzMDgsXG4gICAgKTtcbiAgICBjb25zdCBkaXNwYXRjaGVyID0gbmV3IERpc3BhdGNoZXIoe1xuICAgICAgbWFuaWZlc3Q6IG1hbmlmZXN0T2Yod2l0aFNsYXNoKSxcbiAgICB9KTtcblxuICAgIGNvbnN0IHBhZ2UgPSBhd2FpdCBkaXNwYXRjaGVyLmRpc3BhdGNoKHJlcXVlc3QoXCIvaXNyLzEvXCIpKTtcbiAgICBleHBlY3QocGFnZS5raW5kKS50b0JlKFwiZW50cnlwb2ludFwiKTtcbiAgICBpZiAocGFnZS5raW5kICE9PSBcImVudHJ5cG9pbnRcIikgcmV0dXJuO1xuICAgIC8vIE5vcm1hbGl6ZWQgb24gdGhlIHdheSBvdXQsIGJlY2F1c2UgYGVudHJ5cG9pbnRzYCBpcyBrZXllZCB3aXRob3V0IHRoZVxuICAgIC8vIHNsYXNoIGFuZCB0aGUgcmVuZGVyIGhhcyB0byBsYW5kIG9uIGl0cyBwcmVyZW5kZXIncyBjYWNoZSBrZXkuXG4gICAgZXhwZWN0KHBhZ2UucmVzb2x2ZWRQYXRobmFtZSkudG9CZShcIi9pc3IvW2lkXVwiKTtcbiAgICBleHBlY3QocGFnZS5pbnZvY2F0aW9uVGFyZ2V0KS50b0VxdWFsKHtcbiAgICAgIHBhdGhuYW1lOiBcIi9pc3IvMVwiLFxuICAgICAgcXVlcnk6IHsgbnh0UGlkOiBcIjFcIiB9LFxuICAgIH0pO1xuXG4gICAgY29uc3Qgcm91dGUgPSBhd2FpdCBkaXNwYXRjaGVyLmRpc3BhdGNoKHJlcXVlc3QoXCIvYXBpL2hlYWx0aC9cIikpO1xuICAgIGV4cGVjdChyb3V0ZS5raW5kKS50b0JlKFwiZW50cnlwb2ludFwiKTtcbiAgICBpZiAocm91dGUua2luZCA9PT0gXCJlbnRyeXBvaW50XCIpIHtcbiAgICAgIGV4cGVjdChyb3V0ZS5yZXNvbHZlZFBhdGhuYW1lKS50b0JlKFwiL2FwaS9oZWFsdGhcIik7XG4gICAgfVxuXG4gICAgLy8gQSBzdGF0aWMgZmlsZSBrZWVwcyBpdHMgZXh0ZW5zaW9uLWJlYXJpbmcgcGF0aG5hbWU6IE5leHQuanMgY29tcGlsZXMgdGhlXG4gICAgLy8gKm9wcG9zaXRlKiByZWRpcmVjdCBmb3IgdGhvc2UsIGFuZCBzaGFkb3dpbmcgaXQgd291bGQgc2VydmUgYC94LmpzL2AuXG4gICAgY29uc3QgYXNzZXQgPSBhd2FpdCBkaXNwYXRjaGVyLmRpc3BhdGNoKHJlcXVlc3QoXCIvZmF2aWNvbi5pY29cIikpO1xuICAgIGV4cGVjdChhc3NldC5raW5kKS50b0JlKFwic3RhdGljLWZpbGVcIik7XG4gICAgZXhwZWN0KGF3YWl0IGRpc3BhdGNoZXIuZGlzcGF0Y2gocmVxdWVzdChcIi9mYXZpY29uLmljby9cIikpKS50b01hdGNoT2JqZWN0KHtcbiAgICAgIGtpbmQ6IFwibm90LWZvdW5kXCIsXG4gICAgfSk7XG4gIH0pO1xuXG4gIGl0KFwiZ2l2ZXMgYSBwYXJhbSB3aG9zZSBuYW1lIHByZWZpeGVzIGFub3RoZXIgcGFyYW0ncyBpdHMgb3duIHZhbHVlXCIsIGFzeW5jICgpID0+IHtcbiAgICAvLyBgQG5leHQvcm91dGluZ2AgZXhwYW5kcyBgJG54dFBpZDJgIGJ5IHJlcGxhY2luZyBncm91cCBuYW1lcyBpbiBpbnNlcnRpb25cbiAgICAvLyBvcmRlciwgc28gdGhlIGAkbnh0UGlkYCBwcmVmaXggd2lucyBhbmQgbGVhdmVzIGEgbGl0ZXJhbCBgMmA6IHRoZSByb3V0ZSBpc1xuICAgIC8vIGludm9rZWQgd2l0aCBgbnh0UGlkMj1hMmAuIGByZXBhaXJSb3V0ZVBhcmFtUXVlcnlgIGNvcnJlY3RzIGl0IGZyb21cbiAgICAvLyBgcm91dGVNYXRjaGVzYC4gTWVhc3VyZWQgYWdhaW5zdCBgdGVzdC9lMmUvYXBwLWRpci91c2UtcGFyYW1zYCwgd2hvc2VcbiAgICAvLyBmaXh0dXJlIGlzIGBhcHAvW2lkXS9baWQyXS9wYWdlLnRzeGA7IGFwcC1wbGF5Z3JvdW5kJ3NcbiAgICAvLyBgYXBwL3BhcmFtcy9wcmVmaXgvW2lkXS9baWQyXWAgaXMgdGhlIHNhbWUgc2hhcGUuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZGlzcGF0Y2hlckZvcihcImFwcC1wbGF5Z3JvdW5kXCIpLmRpc3BhdGNoKFxuICAgICAgcmVxdWVzdChcIi9wYXJhbXMvcHJlZml4L2EvYlwiKSxcbiAgICApO1xuICAgIGV4cGVjdChyZXN1bHQua2luZCkudG9CZShcImVudHJ5cG9pbnRcIik7XG4gICAgaWYgKHJlc3VsdC5raW5kICE9PSBcImVudHJ5cG9pbnRcIikgcmV0dXJuO1xuICAgIGV4cGVjdChyZXN1bHQucmVzb2x2ZWRQYXRobmFtZSkudG9CZShcIi9wYXJhbXMvcHJlZml4L1tpZF0vW2lkMl1cIik7XG4gICAgZXhwZWN0KHJlc3VsdC5pbnZvY2F0aW9uVGFyZ2V0KS50b0VxdWFsKHtcbiAgICAgIHBhdGhuYW1lOiBcIi9wYXJhbXMvcHJlZml4L2EvYlwiLFxuICAgICAgcXVlcnk6IHsgbnh0UGlkOiBcImFcIiwgbnh0UGlkMjogXCJiXCIgfSxcbiAgICB9KTtcbiAgICBleHBlY3QocmVzdWx0Lmludm9jYXRpb25UYXJnZXQucXVlcnkpLnRvRXF1YWwoe1xuICAgICAgbnh0UGlkOiBcImFcIixcbiAgICAgIG54dFBpZDI6IFwiYlwiLFxuICAgIH0pO1xuICB9KTtcblxuICBpdChcImFwcGxpZXMgYSBnYXRlZCBiZWZvcmVGaWxlcyByZXdyaXRlIGZyb20gbmV4dC5jb25maWcudHMgb25jZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgLy8gYXBwLXBsYXlncm91bmQncyBvbmUgY29uZmlnIHJld3JpdGU6IGAvZTJlL3Jld3JpdGUvOnBhdGgoLiopYCB3aXRoXG4gICAgLy8gYGhhczogcXVlcnkganNvbj10cnVlYCwgdG8gYC9lMmUvcmV3cml0ZS9lY2hvP2Zyb209LzpwYXRoYC4gSXRzIG91dHB1dFxuICAgIC8vIG1hdGNoZXMgaXQgYWdhaW4sIHdoaWNoIGlzIHdoYXQgTmV4dC5qcyByZS1hcHBsaWVzIGluc2lkZSB0aGUgZW50cnlwb2ludFxuICAgIC8vIC0gdGhlIERpc3BhdGNoZXIncyBoYWxmIGlzIHJlc29sdmluZyBpdCBleGFjdGx5IG9uY2UuXG4gICAgY29uc3QgZGlzcGF0Y2hlciA9IGRpc3BhdGNoZXJGb3IoXCJhcHAtcGxheWdyb3VuZFwiKTtcbiAgICBjb25zdCByZXdyaXR0ZW4gPSBhd2FpdCBkaXNwYXRjaGVyLmRpc3BhdGNoKFxuICAgICAgcmVxdWVzdChcIi9lMmUvcmV3cml0ZS9zb21lL3JvdXRlP2pzb249dHJ1ZVwiKSxcbiAgICApO1xuICAgIGV4cGVjdChyZXdyaXR0ZW4ua2luZCkudG9CZShcImVudHJ5cG9pbnRcIik7XG4gICAgaWYgKHJld3JpdHRlbi5raW5kICE9PSBcImVudHJ5cG9pbnRcIikgcmV0dXJuO1xuICAgIGV4cGVjdChyZXdyaXR0ZW4ucmVzb2x2ZWRQYXRobmFtZSkudG9CZShcIi9lMmUvcmV3cml0ZS9lY2hvXCIpO1xuICAgIGV4cGVjdChyZXdyaXR0ZW4uaW52b2NhdGlvblRhcmdldC5xdWVyeSkudG9NYXRjaE9iamVjdCh7XG4gICAgICBmcm9tOiBcIi9zb21lL3JvdXRlXCIsXG4gICAgICBqc29uOiBcInRydWVcIixcbiAgICB9KTtcblxuICAgIC8vIFdpdGhvdXQgdGhlIGBoYXNgIGNvbmRpdGlvbiB0aGUgcnVsZSBkb2VzIG5vdCBmaXJlIGFuZCBub3RoaW5nIGVsc2VcbiAgICAvLyBzZXJ2ZXMgdGhlIHBhdGguXG4gICAgZXhwZWN0KFxuICAgICAgYXdhaXQgZGlzcGF0Y2hlci5kaXNwYXRjaChyZXF1ZXN0KFwiL2UyZS9yZXdyaXRlL3NvbWUvcm91dGVcIikpLFxuICAgICkudG9NYXRjaE9iamVjdCh7IGtpbmQ6IFwibm90LWZvdW5kXCIgfSk7XG4gIH0pO1xufSk7XG5cbmRlc2NyaWJlKFwiRGlzcGF0Y2hlciBwdWJsaWMvIGZpbGVzXCIsICgpID0+IHtcbiAgLyoqXG4gICAqIEEgcmVhbCBgcHVibGljL2Agb24gZGlzaywgbGlzdGVkIGJ5IHRoZSBzYW1lIGByZWFkUHVibGljRmlsZXNgIHRoZSBydW50aW1lXG4gICAqIGNhbGxzIGF0IGNvbGQgc3RhcnQsIHNvIHRoZSBzcGVsbGluZ3MgdW5kZXIgdGVzdCBhcmUgdGhlIG9uZXMgdGhlIGxpc3RlclxuICAgKiBhbmQgdGhlIHJvdXRpbmcgdGFibGUgYWN0dWFsbHkgcHJvZHVjZSBiZXR3ZWVuIHRoZW0uXG4gICAqL1xuICBmdW5jdGlvbiBwdWJsaWNEaXIoZmlsZXM6IHN0cmluZ1tdKTogcmVhZG9ubHkgc3RyaW5nW10ge1xuICAgIGNvbnN0IGRpciA9IG1rZHRlbXBTeW5jKGpvaW4odG1wZGlyKCksIFwiY2RrLW5leHRqcy1kaXNwYXRjaC1wdWJsaWMtXCIpKTtcbiAgICBmb3IgKGNvbnN0IGZpbGUgb2YgZmlsZXMpIHtcbiAgICAgIG1rZGlyU3luYyhkaXJuYW1lKGpvaW4oZGlyLCBmaWxlKSksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgICAgd3JpdGVGaWxlU3luYyhqb2luKGRpciwgZmlsZSksIGZpbGUpO1xuICAgIH1cbiAgICByZXR1cm4gcmVhZFB1YmxpY0ZpbGVzKGRpcik7XG4gIH1cblxuICBmdW5jdGlvbiBkaXNwYXRjaGVyV2l0aFB1YmxpYyhcbiAgICBuYW1lOiBrZXlvZiB0eXBlb2YgbWFuaWZlc3RzLFxuICAgIGZpbGVzOiBzdHJpbmdbXSxcbiAgKTogRGlzcGF0Y2hlciB7XG4gICAgcmV0dXJuIG5ldyBEaXNwYXRjaGVyKHtcbiAgICAgIG1hbmlmZXN0OiBtYW5pZmVzdHNbbmFtZV0sXG4gICAgICBwdWJsaWNGaWxlczogcHVibGljRGlyKGZpbGVzKSxcbiAgICB9KTtcbiAgfVxuXG4gIGl0LmVhY2goW1xuICAgIC8vIEEgc3BhY2UgaXMgZW5jb2RlZCBieSBldmVyeSBjbGllbnQsIHNvIHRoZSB0d28gc3BlbGxpbmdzIGFncmVlLlxuICAgIFtcInN0YXRpYy9oZWxsbyBlMmUucG5nXCIsIFtcIi9zdGF0aWMvaGVsbG8lMjBlMmUucG5nXCJdXSxcbiAgICAvLyBUaGVzZSBhIGJyb3dzZXIgc2VuZHMgYXMgd3JpdHRlbiwgYW5kIGBlbmNvZGVVUklDb21wb25lbnRgIGRvZXMgbm90LlxuICAgIFtcImltYWdlcy9sb2dvQDJ4LnBuZ1wiLCBbXCIvaW1hZ2VzL2xvZ29AMngucG5nXCIsIFwiL2ltYWdlcy9sb2dvJTQwMngucG5nXCJdXSxcbiAgICBbXCJjKysuc3ZnXCIsIFtcIi9jKysuc3ZnXCIsIFwiL2MlMkIlMkIuc3ZnXCJdXSxcbiAgICBbXCJpY29uWzFdLnBuZ1wiLCBbXCIvaWNvblsxXS5wbmdcIiwgXCIvaWNvbiU1QjElNUQucG5nXCJdXSxcbiAgICBbXCJRJkEucGRmXCIsIFtcIi9RJkEucGRmXCIsIFwiL1ElMjZBLnBkZlwiXV0sXG4gICAgLy8gQSBsaXRlcmFsIGAlYCBjYW4gb25seSBiZSByZXF1ZXN0ZWQgZXNjYXBlZC5cbiAgICBbXCIxMDAlLnBuZ1wiLCBbXCIvMTAwJTI1LnBuZ1wiXV0sXG4gICAgW1wi0YTQvtGC0L4vYS5qcGdcIiwgW1wiLyVEMSU4NCVEMCVCRSVEMSU4MiVEMCVCRS9hLmpwZ1wiXV0sXG4gIF0pKFxuICAgIFwic2VydmVzIHB1YmxpYy8lcyB1bmRlciBldmVyeSBzcGVsbGluZyBhIGxpbmsgY2FuIGhhdmVcIixcbiAgICBhc3luYyAoZmlsZSwgdXJscykgPT4ge1xuICAgICAgY29uc3QgZGlzcGF0Y2hlciA9IGRpc3BhdGNoZXJXaXRoUHVibGljKFwiYXBwLXBsYXlncm91bmRcIiwgW2ZpbGVdKTtcbiAgICAgIGZvciAoY29uc3QgdXJsIG9mIHVybHMpIHtcbiAgICAgICAgZXhwZWN0KGF3YWl0IGRpc3BhdGNoZXIuZGlzcGF0Y2gocmVxdWVzdCh1cmwpKSkudG9NYXRjaE9iamVjdCh7XG4gICAgICAgICAga2luZDogXCJzdGF0aWMtZmlsZVwiLFxuICAgICAgICAgIHNvdXJjZTogXCJwdWJsaWNcIixcbiAgICAgICAgICBmaWxlUGF0aDogYGFwcC1wbGF5Z3JvdW5kL3B1YmxpYy8ke2ZpbGV9YCxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSxcbiAgKTtcblxuICBpdChcInNlcnZlcyBwdWJsaWMvIGFoZWFkIG9mIGFuIGFwcCByb3V0ZSBhdCB0aGUgc2FtZSBwYXRobmFtZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgLy8gYGFwcC9mYXZpY29uLmljb2AgaXMgYSBidWlsZCBvdXRwdXQgaGVyZTsgYG5leHQgc3RhcnRgIGNoZWNrcyBwdWJsaWMvXG4gICAgLy8gYmVmb3JlIGFwcCBhbmQgcGFnZSByb3V0ZXMsIHNvIGEgbGVmdG92ZXIgYHB1YmxpYy9mYXZpY29uLmljb2Agd2lucy5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBkaXNwYXRjaGVyV2l0aFB1YmxpYyhcImFwcC1wbGF5Z3JvdW5kXCIsIFtcbiAgICAgIFwiZmF2aWNvbi5pY29cIixcbiAgICBdKS5kaXNwYXRjaChyZXF1ZXN0KFwiL2Zhdmljb24uaWNvXCIpKTtcbiAgICBleHBlY3QocmVzdWx0KS50b01hdGNoT2JqZWN0KHtcbiAgICAgIGtpbmQ6IFwic3RhdGljLWZpbGVcIixcbiAgICAgIGZpbGVQYXRoOiBcImFwcC1wbGF5Z3JvdW5kL3B1YmxpYy9mYXZpY29uLmljb1wiLFxuICAgIH0pO1xuICB9KTtcblxuICBpdChcInN0aWxsIHNlcnZlcyB0aGUgYnVpbGQgb3V0cHV0IHdoZW4gcHVibGljLyBoYXMgbm8gZmlsZSB0aGVyZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZGlzcGF0Y2hlcldpdGhQdWJsaWMoXCJhcHAtcGxheWdyb3VuZFwiLCBbXSkuZGlzcGF0Y2goXG4gICAgICByZXF1ZXN0KFwiL2Zhdmljb24uaWNvXCIpLFxuICAgICk7XG4gICAgZXhwZWN0KHJlc3VsdCkudG9NYXRjaE9iamVjdCh7IGtpbmQ6IFwic3RhdGljLWZpbGVcIiwgc291cmNlOiBcInNlcnZlclwiIH0pO1xuICB9KTtcblxuICBpdChcInNlcnZlcyBwdWJsaWMvIHVuZGVyIGJhc2VQYXRoXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBkaXNwYXRjaGVyID0gZGlzcGF0Y2hlcldpdGhQdWJsaWMoXCJhcHAtcGxheWdyb3VuZC1iYXNlLXBhdGhcIiwgW1xuICAgICAgXCJ0ZXN0LnR4dFwiLFxuICAgIF0pO1xuICAgIGV4cGVjdChhd2FpdCBkaXNwYXRjaGVyLmRpc3BhdGNoKHJlcXVlc3QoXCIvcHJvZC90ZXN0LnR4dFwiKSkpLnRvTWF0Y2hPYmplY3Qoe1xuICAgICAga2luZDogXCJzdGF0aWMtZmlsZVwiLFxuICAgICAgZmlsZVBhdGg6IFwiYXBwLXBsYXlncm91bmQvcHVibGljL3Rlc3QudHh0XCIsXG4gICAgfSk7XG4gICAgZXhwZWN0KChhd2FpdCBkaXNwYXRjaGVyLmRpc3BhdGNoKHJlcXVlc3QoXCIvdGVzdC50eHRcIikpKS5raW5kKS5ub3QudG9CZShcbiAgICAgIFwic3RhdGljLWZpbGVcIixcbiAgICApO1xuICB9KTtcblxuICBpdChcInNlcnZlcyBwdWJsaWMvIGluIGFuIGkxOG4gYXBwLCBiYXJlIGFuZCB1bmRlciBhIGRlZmF1bHQgbG9jYWxlIG9ubHlcIiwgYXN5bmMgKCkgPT4ge1xuICAgIC8vIGByZXNvbHZlUm91dGVzYCBwcmVmaXhlcyB0aGUgbG9jYWxlIGJlZm9yZSBpdCBtYXRjaGVzLCBzbyBgL3Rlc3QudHh0YCBpc1xuICAgIC8vIGxvb2tlZCB1cCBhcyBgL2VuLVVTL3Rlc3QudHh0YC4gYG5leHQgc3RhcnRgIHN0cmlwcyB0aGUgZGVmYXVsdCBsb2NhbGUsXG4gICAgLy8gYW5kIGVhY2ggZG9tYWluJ3MsIG9mZiBhIHB1YmxpYy8gcmVxdWVzdCAtIGBmcmAgaXMgZXhhbXBsZS5mcidzIC0gYW5kIG5vXG4gICAgLy8gb3RoZXIuXG4gICAgY29uc3QgZGlzcGF0Y2hlciA9IGRpc3BhdGNoZXJXaXRoUHVibGljKFwicGFnZXMtaTE4blwiLCBbXCJ0ZXN0LnR4dFwiXSk7XG4gICAgZm9yIChjb25zdCB1cmwgb2YgW1wiL3Rlc3QudHh0XCIsIFwiL2VuLVVTL3Rlc3QudHh0XCIsIFwiL2ZyL3Rlc3QudHh0XCJdKSB7XG4gICAgICBleHBlY3QoYXdhaXQgZGlzcGF0Y2hlci5kaXNwYXRjaChyZXF1ZXN0KHVybCkpKS50b01hdGNoT2JqZWN0KHtcbiAgICAgICAga2luZDogXCJzdGF0aWMtZmlsZVwiLFxuICAgICAgICBmaWxlUGF0aDogXCJwYWdlcy1pMThuL3B1YmxpYy90ZXN0LnR4dFwiLFxuICAgICAgfSk7XG4gICAgfVxuICAgIGV4cGVjdChcbiAgICAgIChhd2FpdCBkaXNwYXRjaGVyLmRpc3BhdGNoKHJlcXVlc3QoXCIvbmwtTkwvdGVzdC50eHRcIikpKS5raW5kLFxuICAgICkubm90LnRvQmUoXCJzdGF0aWMtZmlsZVwiKTtcbiAgfSk7XG5cbiAgaXQoXCJrbm93cyBub3RoaW5nIG9mIHB1YmxpYy8gd2hlbiB0aGUgZGVwbG95bWVudCBoYXMgbm9uZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgLy8gVGhlIExhbWJkYSB0eXBlczogQ2xvdWRGcm9udCBvciBBUEkgR2F0ZXdheSBhbnN3ZXJzIHB1YmxpYy8gZnJvbSBTMywgdGhlXG4gICAgLy8gcGFja2FnZSBkb2VzIG5vdCBjYXJyeSBpdCwgYW5kIGEgcmVxdWVzdCB0aGF0IGdvdCB0aHJvdWdoIGFueXdheSB0YWtlc1xuICAgIC8vIHRoZSBvcmRpbmFyeSBub3QtZm91bmQgcGF0aCwgbWlkZGxld2FyZSByZXF1ZXN0IGhlYWRlcnMgYW5kIGFsbC5cbiAgICBleHBlY3QoXG4gICAgICBhd2FpdCBkaXNwYXRjaGVyRm9yKFwiYXBwLXBsYXlncm91bmRcIikuZGlzcGF0Y2gocmVxdWVzdChcIi90ZXN0LnR4dFwiKSksXG4gICAgKS50b01hdGNoT2JqZWN0KHsga2luZDogXCJub3QtZm91bmRcIiB9KTtcbiAgfSk7XG59KTtcblxuZGVzY3JpYmUoXCJEaXNwYXRjaGVyIGJ1aWxkLW91dHB1dCBzcGVsbGluZ3NcIiwgKCkgPT4ge1xuICBpdChcInNlcnZlcyBhIF9uZXh0L3N0YXRpYyBmaWxlIHdob3NlIG5hbWUgdGhlIEhUTUwgcGVyY2VudC1lbmNvZGVzXCIsIGFzeW5jICgpID0+IHtcbiAgICAvLyB3ZWJwYWNrIG5hbWVzIGFuIEFwcCBSb3V0ZXIgY2h1bmsgYWZ0ZXIgaXRzIHJvdXRlIHNlZ21lbnQsIGJyYWNrZXRzIGFuZFxuICAgIC8vIGFsbCwgYW5kIE5leHQuanMgcmVwb3J0cyB0aGUgcGF0aG5hbWUgdW5lbmNvZGVkOyB0aGUgYDxzY3JpcHQ+YCB0YWcgaW5cbiAgICAvLyB0aGUgSFRNTCBhc2tzIGZvciBgJTVCaWQlNURgLlxuICAgIGNvbnN0IGJhc2UgPSBtYW5pZmVzdHNbXCJhcHAtcGxheWdyb3VuZFwiXTtcbiAgICBjb25zdCBwYXRobmFtZSA9IFwiL19uZXh0L3N0YXRpYy9jaHVua3MvYXBwL2lzci9baWRdL3BhZ2UtMDEyM2FiY2QuanNcIjtcbiAgICBjb25zdCBmaWxlUGF0aCA9XG4gICAgICBcImFwcC1wbGF5Z3JvdW5kLy5uZXh0L3N0YXRpYy9jaHVua3MvYXBwL2lzci9baWRdL3BhZ2UtMDEyM2FiY2QuanNcIjtcbiAgICBjb25zdCBtYW5pZmVzdDogQWRhcHRlck1hbmlmZXN0ID0ge1xuICAgICAgLi4uYmFzZSxcbiAgICAgIHN0YXRpY0ZpbGVzOiB7IC4uLmJhc2Uuc3RhdGljRmlsZXMsIFtwYXRobmFtZV06IGZpbGVQYXRoIH0sXG4gICAgICBwYXRobmFtZXM6IFsuLi5iYXNlLnBhdGhuYW1lcywgcGF0aG5hbWVdLFxuICAgIH07XG4gICAgY29uc3QgZGlzcGF0Y2hlciA9IG5ldyBEaXNwYXRjaGVyKHtcbiAgICAgIG1hbmlmZXN0LFxuICAgIH0pO1xuICAgIGZvciAoY29uc3QgdXJsIG9mIFtcbiAgICAgIFwiL19uZXh0L3N0YXRpYy9jaHVua3MvYXBwL2lzci8lNUJpZCU1RC9wYWdlLTAxMjNhYmNkLmpzXCIsXG4gICAgICBwYXRobmFtZSxcbiAgICBdKSB7XG4gICAgICBleHBlY3QoYXdhaXQgZGlzcGF0Y2hlci5kaXNwYXRjaChyZXF1ZXN0KHVybCkpKS50b01hdGNoT2JqZWN0KHtcbiAgICAgICAga2luZDogXCJzdGF0aWMtZmlsZVwiLFxuICAgICAgICBzb3VyY2U6IFwibmV4dC1zdGF0aWNcIixcbiAgICAgICAgZmlsZVBhdGgsXG4gICAgICB9KTtcbiAgICB9XG4gIH0pO1xufSk7XG5cbmRlc2NyaWJlKFwiRGlzcGF0Y2hlciBub24tZW50cnlwb2ludCBvdXRjb21lc1wiLCAoKSA9PiB7XG4gIGl0KFwic2VydmVzIGEgYnVpbGQgYXNzZXQgYXMgYSBzdGF0aWMgZmlsZSB3aXRoIGl0cyBpbW11dGFibGUgY2FjaGUgaGVhZGVyXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBtYW5pZmVzdCA9IG1hbmlmZXN0c1tcImFwcC1wbGF5Z3JvdW5kXCJdO1xuICAgIGNvbnN0IHBhdGhuYW1lID0gT2JqZWN0LmtleXMobWFuaWZlc3Quc3RhdGljRmlsZXMpLmZpbmQoKGZpbGUpID0+XG4gICAgICBmaWxlLnN0YXJ0c1dpdGgoXCIvX25leHQvc3RhdGljL1wiKSxcbiAgICApITtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBkaXNwYXRjaGVyRm9yKFwiYXBwLXBsYXlncm91bmRcIikuZGlzcGF0Y2goXG4gICAgICByZXF1ZXN0KHBhdGhuYW1lKSxcbiAgICApO1xuICAgIGV4cGVjdChyZXN1bHQua2luZCkudG9CZShcInN0YXRpYy1maWxlXCIpO1xuICAgIGlmIChyZXN1bHQua2luZCAhPT0gXCJzdGF0aWMtZmlsZVwiKSByZXR1cm47XG4gICAgZXhwZWN0KHJlc3VsdC5wYXRobmFtZSkudG9CZShwYXRobmFtZSk7XG4gICAgZXhwZWN0KHJlc3VsdC5yZXNwb25zZUhlYWRlcnMuZ2V0KFwiY2FjaGUtY29udHJvbFwiKSkudG9CZShcbiAgICAgIFwicHVibGljLG1heC1hZ2U9MzE1MzYwMDAsaW1tdXRhYmxlXCIsXG4gICAgKTtcbiAgfSk7XG5cbiAgaXQoXCJyb3V0ZXMgL19uZXh0L2ltYWdlIHRvIHRoZSBvcHRpbWl6ZXIsIGJhc2VQYXRoIGluY2x1ZGVkXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBxdWVyeSA9IFwiP3VybD0lMkZmb28ucG5nJnc9NjQwJnE9NzVcIjtcbiAgICBjb25zdCBwbGFpbiA9IGF3YWl0IGRpc3BhdGNoZXJGb3IoXCJhcHAtcGxheWdyb3VuZFwiKS5kaXNwYXRjaChcbiAgICAgIHJlcXVlc3QoYC9fbmV4dC9pbWFnZSR7cXVlcnl9YCksXG4gICAgKTtcbiAgICBleHBlY3QocGxhaW4ua2luZCkudG9CZShcImltYWdlLW9wdGltaXphdGlvblwiKTtcblxuICAgIGNvbnN0IHByZWZpeGVkID0gYXdhaXQgZGlzcGF0Y2hlckZvcihcImFwcC1wbGF5Z3JvdW5kLWJhc2UtcGF0aFwiKS5kaXNwYXRjaChcbiAgICAgIHJlcXVlc3QoYC9wcm9kL19uZXh0L2ltYWdlJHtxdWVyeX1gKSxcbiAgICApO1xuICAgIGV4cGVjdChwcmVmaXhlZC5raW5kKS50b0JlKFwiaW1hZ2Utb3B0aW1pemF0aW9uXCIpO1xuICAgIGlmIChwcmVmaXhlZC5raW5kICE9PSBcImltYWdlLW9wdGltaXphdGlvblwiKSByZXR1cm47XG4gICAgZXhwZWN0KHByZWZpeGVkLnVybC5zZWFyY2hQYXJhbXMuZ2V0KFwidXJsXCIpKS50b0JlKFwiL2Zvby5wbmdcIik7XG4gIH0pO1xuXG4gIGl0KFwicm91dGVzIC9fbmV4dC9pbWFnZSB0byB0aGUgb3B0aW1pemVyIGFoZWFkIG9mIGEgcm9vdCBjYXRjaC1hbGxcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHF1ZXJ5ID0gXCI/dXJsPSUyRmZvby5wbmcmdz02NDAmcT03NVwiO1xuICAgIGNvbnN0IGNhdGNoQWxsID0gZGlzcGF0Y2hlckZvcihcImFwcC1wbGF5Z3JvdW5kLXJvb3QtY2F0Y2gtYWxsXCIpO1xuICAgIGNvbnN0IGltYWdlID0gYXdhaXQgY2F0Y2hBbGwuZGlzcGF0Y2gocmVxdWVzdChgL19uZXh0L2ltYWdlJHtxdWVyeX1gKSk7XG4gICAgZXhwZWN0KGltYWdlLmtpbmQpLnRvQmUoXCJpbWFnZS1vcHRpbWl6YXRpb25cIik7XG4gICAgaWYgKGltYWdlLmtpbmQgIT09IFwiaW1hZ2Utb3B0aW1pemF0aW9uXCIpIHJldHVybjtcbiAgICBleHBlY3QoaW1hZ2UudXJsLnNlYXJjaFBhcmFtcy5nZXQoXCJ1cmxcIikpLnRvQmUoXCIvZm9vLnBuZ1wiKTtcblxuICAgIC8vIFRoZSBjYXRjaC1hbGwgaXRzZWxmIHN0aWxsIHRha2VzIGV2ZXJ5dGhpbmcgZWxzZS5cbiAgICBjb25zdCBwYWdlID0gYXdhaXQgY2F0Y2hBbGwuZGlzcGF0Y2gocmVxdWVzdChcIi9hL2JcIikpO1xuICAgIGV4cGVjdChwYWdlLmtpbmQpLnRvQmUoXCJlbnRyeXBvaW50XCIpO1xuICAgIGlmIChwYWdlLmtpbmQgIT09IFwiZW50cnlwb2ludFwiKSByZXR1cm47XG4gICAgZXhwZWN0KHBhZ2UucmVzb2x2ZWRQYXRobmFtZSkudG9CZShcIi9bWy4uLnJlc3RdXVwiKTtcblxuICAgIGNvbnN0IHByZWZpeGVkQ2F0Y2hBbGwgPSBkaXNwYXRjaGVyRm9yKFxuICAgICAgXCJhcHAtcGxheWdyb3VuZC1iYXNlLXBhdGgtcm9vdC1jYXRjaC1hbGxcIixcbiAgICApO1xuICAgIGNvbnN0IHByZWZpeGVkID0gYXdhaXQgcHJlZml4ZWRDYXRjaEFsbC5kaXNwYXRjaChcbiAgICAgIHJlcXVlc3QoYC9wcm9kL19uZXh0L2ltYWdlJHtxdWVyeX1gKSxcbiAgICApO1xuICAgIGV4cGVjdChwcmVmaXhlZC5raW5kKS50b0JlKFwiaW1hZ2Utb3B0aW1pemF0aW9uXCIpO1xuICAgIC8vIFdpdGhvdXQgd2hpY2ggdGhlIGltYWdlIGFzc2VydGlvbiB3b3VsZCBwYXNzIG9uIGEgZml4dHVyZSB3aXRoIG5vXG4gICAgLy8gY2F0Y2gtYWxsIGF0IGFsbC5cbiAgICBjb25zdCBwcmVmaXhlZFBhZ2UgPSBhd2FpdCBwcmVmaXhlZENhdGNoQWxsLmRpc3BhdGNoKHJlcXVlc3QoXCIvcHJvZC9hL2JcIikpO1xuICAgIGV4cGVjdChwcmVmaXhlZFBhZ2Uua2luZCkudG9CZShcImVudHJ5cG9pbnRcIik7XG4gICAgaWYgKHByZWZpeGVkUGFnZS5raW5kICE9PSBcImVudHJ5cG9pbnRcIikgcmV0dXJuO1xuICAgIGV4cGVjdChwcmVmaXhlZFBhZ2UucmVzb2x2ZWRQYXRobmFtZSkudG9CZShcIi9wcm9kL1tbLi4ucmVzdF1dXCIpO1xuICB9KTtcblxuICBpdChcIm9wdGltaXplcyB0aGUgZGVzdGluYXRpb24gb2YgYSBuZXh0LmNvbmZpZyByZXdyaXRlIG9udG8gL19uZXh0L2ltYWdlXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBtYW5pZmVzdCA9IG1hbmlmZXN0c1tcImFwcC1wbGF5Z3JvdW5kLXJvb3QtY2F0Y2gtYWxsXCJdO1xuICAgIGNvbnN0IHJvdXRpbmcgPSBtYW5pZmVzdC5yb3V0aW5nIGFzIHsgYmVmb3JlRmlsZXM6IHVua25vd25bXSB9O1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IG5ldyBEaXNwYXRjaGVyKHtcbiAgICAgIG1hbmlmZXN0OiB7XG4gICAgICAgIC4uLm1hbmlmZXN0LFxuICAgICAgICByb3V0aW5nOiB7XG4gICAgICAgICAgLi4ucm91dGluZyxcbiAgICAgICAgICBiZWZvcmVGaWxlczogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBzb3VyY2U6IFwiL2F2YXRhci86aWRcIixcbiAgICAgICAgICAgICAgc291cmNlUmVnZXg6IFwiXlxcXFwvYXZhdGFyKD86XFxcXC8oW15cXFxcL10rPykpKD86XFxcXC8pPyRcIixcbiAgICAgICAgICAgICAgZGVzdGluYXRpb246IFwiL19uZXh0L2ltYWdlP3VybD0lMkZhdmF0YXJzJTJGJDEucG5nJnc9NjQmcT03NVwiLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIC4uLnJvdXRpbmcuYmVmb3JlRmlsZXMsXG4gICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSkuZGlzcGF0Y2gocmVxdWVzdChcIi9hdmF0YXIvNDJcIikpO1xuICAgIGV4cGVjdChyZXN1bHQua2luZCkudG9CZShcImltYWdlLW9wdGltaXphdGlvblwiKTtcbiAgICBpZiAocmVzdWx0LmtpbmQgIT09IFwiaW1hZ2Utb3B0aW1pemF0aW9uXCIpIHJldHVybjtcbiAgICBleHBlY3QocmVzdWx0LnVybC5wYXRobmFtZSkudG9CZShcIi9fbmV4dC9pbWFnZVwiKTtcbiAgICBleHBlY3QocmVzdWx0LnVybC5zZWFyY2hQYXJhbXMuZ2V0KFwidXJsXCIpKS50b0JlKFwiL2F2YXRhcnMvNDIucG5nXCIpO1xuICAgIGV4cGVjdChyZXN1bHQudXJsLnNlYXJjaFBhcmFtcy5nZXQoXCJ3XCIpKS50b0JlKFwiNjRcIik7XG4gIH0pO1xuXG4gIGl0KFwicmVkaXJlY3RzIGEgdHJhaWxpbmcgc2xhc2hcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGRpc3BhdGNoZXJGb3IoXCJhcHAtcGxheWdyb3VuZFwiKS5kaXNwYXRjaChcbiAgICAgIHJlcXVlc3QoXCIvaXNyLzEvXCIpLFxuICAgICk7XG4gICAgZXhwZWN0KHJlc3VsdCkudG9NYXRjaE9iamVjdCh7XG4gICAgICBraW5kOiBcInJlZGlyZWN0XCIsXG4gICAgICBzdGF0dXM6IDMwOCxcbiAgICAgIGxvY2F0aW9uOiBcIi9pc3IvMVwiLFxuICAgIH0pO1xuICB9KTtcblxuICBpdChcInNlcnZlcyB0aGUgYXBwJ3Mgcm9vdCBpbiB0aGUgZGVmYXVsdCBsb2NhbGUsIHdpdGggbm8gcmVkaXJlY3QgYXQgYWxsXCIsIGFzeW5jICgpID0+IHtcbiAgICAvLyBgcmVzb2x2ZVJvdXRlc2AgcHJlZml4ZXMgdGhlIGxvY2FsZSBhcyBgJHtiYXNlUGF0aH0vJHtsb2NhbGV9JHtwYXRobmFtZX1gLFxuICAgIC8vIHdoaWNoIHR1cm5zIHRoZSByb290IGludG8gYC9lbi1VUy9gLCBhbmQgdGhlIHNsYXNoLXN0cmlwcGluZyAzMDggZXZlcnlcbiAgICAvLyBidWlsZCBjb21waWxlcyB0aGVuIGFuc3dlcmVkIGBHRVQgL2Agd2l0aCBhIHJlZGlyZWN0IG5vIGBuZXh0IHN0YXJ0YFxuICAgIC8vIHNlbmRzLiBNZWFzdXJlZCBhZ2FpbnN0IGB0ZXN0L2UyZS9pMThuLXN1cHBvcnQtY2F0Y2hhbGxgLCB3aG9zZSBgL2AgaXMgYVxuICAgIC8vIDIwMC4gU2VlIGBEaXNwYXRjaGVyLndpdGhSb290TG9jYWxlYC5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBkaXNwYXRjaGVyRm9yKFwicGFnZXMtaTE4blwiKS5kaXNwYXRjaChyZXF1ZXN0KFwiL1wiKSk7XG4gICAgZXhwZWN0KHJlc3VsdCkudG9NYXRjaE9iamVjdCh7IGtpbmQ6IFwic3RhdGljLWZpbGVcIiwgcGF0aG5hbWU6IFwiL2VuLVVTXCIgfSk7XG4gIH0pO1xuXG4gIGl0KFwicmVkaXJlY3RzIHRoZSByb290IHRvIHRoZSBsb2NhbGUgdGhlIHJlcXVlc3QgYXNrZWQgZm9yXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBkaXNwYXRjaGVyRm9yKFwicGFnZXMtaTE4blwiKS5kaXNwYXRjaChcbiAgICAgIHJlcXVlc3QoXCIvXCIsIHsgXCJhY2NlcHQtbGFuZ3VhZ2VcIjogXCJubC1OTFwiIH0pLFxuICAgICk7XG4gICAgLy8gMzA3IGFuZCBub3QgMzA4LCBiZWNhdXNlIHRoZSBuZXh0IHJlcXVlc3QgbWF5IGRldGVjdCBhIGRpZmZlcmVudCBsb2NhbGUuXG4gICAgLy8gUmVsYXRpdmUgYW5kIHdpdGhvdXQgdGhlIHRyYWlsaW5nIHNsYXNoIGByZXNvbHZlUm91dGVzYCBwdXRzIGluIHRoZVxuICAgIC8vIGxvY2F0aW9uIGl0IGJ1aWxkcyAoYGh0dHBzOi8vZXhhbXBsZS50ZXN0L25sLU5ML2ApLCB3aGljaCBpcyB3aGF0XG4gICAgLy8gYG5leHQgc3RhcnRgIHNlbmRzIGFuZCB3aGF0IGEgdGVzdCBhc3NlcnRpbmcgYGhlYWRlcnMubG9jYXRpb25gIHJlYWRzLlxuICAgIGV4cGVjdChyZXN1bHQpLnRvTWF0Y2hPYmplY3Qoe1xuICAgICAga2luZDogXCJyZWRpcmVjdFwiLFxuICAgICAgc3RhdHVzOiAzMDcsXG4gICAgICBsb2NhdGlvbjogXCIvbmwtTkxcIixcbiAgICB9KTtcbiAgfSk7XG5cbiAgaXQoXCJrZWVwcyBhIHJlZGlyZWN0IHRvIGFub3RoZXIgbG9jYWxlJ3MgZG9tYWluIGFic29sdXRlXCIsIGFzeW5jICgpID0+IHtcbiAgICAvLyBUaGUgZml4dHVyZSBtYXBzIGBmcmAgb250byBleGFtcGxlLmZyLCBhbmQgYW4gYWJzb2x1dGUgbG9jYXRpb24gaXMgdGhlXG4gICAgLy8gb25seSB3YXkgdG8gbGVhdmUgdGhlIG9yaWdpbi5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBkaXNwYXRjaGVyRm9yKFwicGFnZXMtaTE4blwiKS5kaXNwYXRjaChcbiAgICAgIHJlcXVlc3QoXCIvXCIsIHsgY29va2llOiBcIk5FWFRfTE9DQUxFPWZyXCIgfSksXG4gICAgKTtcbiAgICBleHBlY3QocmVzdWx0KS50b01hdGNoT2JqZWN0KHtcbiAgICAgIGtpbmQ6IFwicmVkaXJlY3RcIixcbiAgICAgIHN0YXR1czogMzA3LFxuICAgICAgbG9jYXRpb246IFwiaHR0cHM6Ly9leGFtcGxlLmZyL1wiLFxuICAgIH0pO1xuICB9KTtcblxuICBpdChcInNlcnZlcyB0aGUgcm9vdCBvZiBhIGB0cmFpbGluZ1NsYXNoYCBpMThuIGFwcCB3aXRoIG5vIHJlZGlyZWN0XCIsIGFzeW5jICgpID0+IHtcbiAgICAvLyBXaXRoIGB0cmFpbGluZ1NsYXNoOiB0cnVlYCwgYG5leHQgYnVpbGRgIGNvbXBpbGVzIHRoZSBzbGFzaC0qYWRkaW5nKiAzMDhcbiAgICAvLyAoYGxvYWQtY3VzdG9tLXJvdXRlc2AnIGAvOm5vdGZpbGUoLi4uKWAg4oaSIGAvOm5vdGZpbGUvYCwgYGxvY2FsZTogZmFsc2VgKVxuICAgIC8vIGluIHBsYWNlIG9mIHRoZSBzdHJpcHBpbmcgb25lLCBhbmQgcHJlZml4aW5nIHRoZSByb290IGFzIGAvZW4tVVNgIG1hZGVcbiAgICAvLyB0aGF0IHJ1bGUgYW5zd2VyIGBHRVQgL2Agd2l0aCBhIDMwOCB0byBgL2VuLVVTL2AsIHdoZXJlIGBuZXh0IHN0YXJ0YFxuICAgIC8vIGFuc3dlcnMgMjAwLlxuICAgIGNvbnN0IHdpdGhTbGFzaCA9IHN0cnVjdHVyZWRDbG9uZShcbiAgICAgIHBhZ2VzSTE4biBhcyB1bmtub3duLFxuICAgICkgYXMgQnVpbGRDb21wbGV0ZUNvbnRleHQ7XG4gICAgKHdpdGhTbGFzaC5jb25maWcgYXMgeyB0cmFpbGluZ1NsYXNoOiBib29sZWFuIH0pLnRyYWlsaW5nU2xhc2ggPSB0cnVlO1xuICAgIGNvbnN0IHJvdXRpbmcgPSB3aXRoU2xhc2gucm91dGluZyBhcyB7XG4gICAgICBiZWZvcmVNaWRkbGV3YXJlOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPltdO1xuICAgIH07XG4gICAgcm91dGluZy5iZWZvcmVNaWRkbGV3YXJlID0gW1xuICAgICAge1xuICAgICAgICBzb3VyY2U6IFwiLzpub3RmaWxlKCg/IVxcXFwud2VsbC1rbm93big/Oi8uKik/KSg/OlteL10rLykqW14vXFxcXC5dKylcIixcbiAgICAgICAgc291cmNlUmVnZXg6XG4gICAgICAgICAgXCJeKD86XFxcXC8oKD8hXFxcXC53ZWxsLWtub3duKD86XFxcXC8uKik/KSg/OlteXFxcXC9dK1xcXFwvKSpbXlxcXFwvXFxcXC5dKykpJFwiLFxuICAgICAgICBoZWFkZXJzOiB7IExvY2F0aW9uOiBcIi8kMS9cIiB9LFxuICAgICAgICBzdGF0dXM6IDMwOCxcbiAgICAgICAgcHJpb3JpdHk6IHRydWUsXG4gICAgICB9LFxuICAgICAgLi4ucm91dGluZy5iZWZvcmVNaWRkbGV3YXJlLmZpbHRlcigocm91dGUpID0+IHJvdXRlLnN0YXR1cyAhPT0gMzA4KSxcbiAgICBdO1xuICAgIGNvbnN0IGRpc3BhdGNoZXIgPSBuZXcgRGlzcGF0Y2hlcih7IG1hbmlmZXN0OiBtYW5pZmVzdE9mKHdpdGhTbGFzaCkgfSk7XG5cbiAgICBleHBlY3QoYXdhaXQgZGlzcGF0Y2hlci5kaXNwYXRjaChyZXF1ZXN0KFwiL1wiKSkpLnRvTWF0Y2hPYmplY3Qoe1xuICAgICAga2luZDogXCJzdGF0aWMtZmlsZVwiLFxuICAgICAgcGF0aG5hbWU6IFwiL2VuLVVTXCIsXG4gICAgfSk7XG4gICAgLy8gVGhlIHJ1bGUgaXRzZWxmIGlzIGxpdmU6IHRoZSBzbGFzaGxlc3MgbG9jYWxlIHJvb3Qgc3RpbGwgZ2V0cyBpdC5cbiAgICBleHBlY3QoYXdhaXQgZGlzcGF0Y2hlci5kaXNwYXRjaChyZXF1ZXN0KFwiL2VuLVVTXCIpKSkudG9NYXRjaE9iamVjdCh7XG4gICAgICBraW5kOiBcInJlZGlyZWN0XCIsXG4gICAgICBzdGF0dXM6IDMwOCxcbiAgICAgIGxvY2F0aW9uOiBcIi9lbi1VUy9cIixcbiAgICB9KTtcbiAgfSk7XG5cbiAgaXQoXCJzdGlsbCBzdHJpcHMgYSB0cmFpbGluZyBzbGFzaCB0aGUgcmVxdWVzdCBpdHNlbGYgY2FycmllZFwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZGlzcGF0Y2hlckZvcihcInBhZ2VzLWkxOG5cIikuZGlzcGF0Y2goXG4gICAgICByZXF1ZXN0KFwiL25sLU5ML1wiKSxcbiAgICApO1xuICAgIGV4cGVjdChyZXN1bHQpLnRvTWF0Y2hPYmplY3Qoe1xuICAgICAga2luZDogXCJyZWRpcmVjdFwiLFxuICAgICAgc3RhdHVzOiAzMDgsXG4gICAgICBsb2NhdGlvbjogXCIvbmwtTkxcIixcbiAgICB9KTtcbiAgfSk7XG5cbiAgaXQoXCJyZXR1cm5zIGEgZGlyZWN0IHJlc3BvbnNlIGZvciBhIHJvdXRlIHRoYXQgZm9yY2VzIGEgc3RhdHVzXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBiYXNlID0gbWFuaWZlc3RzW1wiYXBwLXBsYXlncm91bmRcIl07XG4gICAgY29uc3QgbWFuaWZlc3Q6IEFkYXB0ZXJNYW5pZmVzdCA9IHtcbiAgICAgIC4uLmJhc2UsXG4gICAgICBtaWRkbGV3YXJlOiBudWxsLFxuICAgICAgcm91dGluZzoge1xuICAgICAgICAuLi4oYmFzZS5yb3V0aW5nIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KSxcbiAgICAgICAgYmVmb3JlRmlsZXM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBzb3VyY2VSZWdleDogXCJeL2Jsb2NrZWQkXCIsXG4gICAgICAgICAgICBzdGF0dXM6IDQwMyxcbiAgICAgICAgICAgIGhlYWRlcnM6IHsgXCJ4LXdoeVwiOiBcIm5vXCIgfSxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfSxcbiAgICB9O1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IG5ldyBEaXNwYXRjaGVyKHsgbWFuaWZlc3QgfSkuZGlzcGF0Y2goXG4gICAgICByZXF1ZXN0KFwiL2Jsb2NrZWRcIiksXG4gICAgKTtcbiAgICBleHBlY3QocmVzdWx0KS50b01hdGNoT2JqZWN0KHsga2luZDogXCJyZXNwb25zZVwiLCBzdGF0dXM6IDQwMyB9KTtcbiAgICBleHBlY3QocmVzdWx0LnJlc3BvbnNlSGVhZGVycy5nZXQoXCJ4LXdoeVwiKSkudG9CZShcIm5vXCIpO1xuICB9KTtcblxuICBpdChcInJlcG9ydHMgYW4gdW5rbm93biBwYXRoIGFzIG5vdCBmb3VuZFwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZGlzcGF0Y2hlckZvcihcImFwcC1wbGF5Z3JvdW5kXCIpLmRpc3BhdGNoKFxuICAgICAgcmVxdWVzdChcIi9kZWZpbml0ZWx5LW5vdC1hLXJvdXRlXCIpLFxuICAgICk7XG4gICAgZXhwZWN0KHJlc3VsdC5raW5kKS50b0JlKFwibm90LWZvdW5kXCIpO1xuICAgIGlmIChyZXN1bHQua2luZCAhPT0gXCJub3QtZm91bmRcIikgcmV0dXJuO1xuICAgIGV4cGVjdChyZXN1bHQucGF0aG5hbWUpLnRvQmUoXCIvZGVmaW5pdGVseS1ub3QtYS1yb3V0ZVwiKTtcbiAgfSk7XG5cbiAgaXQoXCJyZXNvbHZlcyB0aGUgNDA0IHRhcmdldCBwZXIgcm91dGVyIGZsYXZvclwiLCAoKSA9PiB7XG4gICAgZXhwZWN0KHN0YXR1c1RhcmdldE9mKG1hbmlmZXN0c1tcImFwcC1wbGF5Z3JvdW5kXCJdLCA0MDQpKS50b01hdGNoT2JqZWN0KHtcbiAgICAgIGtpbmQ6IFwiZW50cnlwb2ludFwiLFxuICAgICAgcGF0aG5hbWU6IFwiL19ub3QtZm91bmRcIixcbiAgICB9KTtcbiAgICBleHBlY3QoXG4gICAgICBzdGF0dXNUYXJnZXRPZihtYW5pZmVzdHNbXCJhcHAtcGxheWdyb3VuZC1iYXNlLXBhdGhcIl0sIDQwNCksXG4gICAgKS50b01hdGNoT2JqZWN0KHtcbiAgICAgIGtpbmQ6IFwiZW50cnlwb2ludFwiLFxuICAgICAgcGF0aG5hbWU6IFwiL3Byb2QvX25vdC1mb3VuZFwiLFxuICAgIH0pO1xuICAgIC8vIFBhZ2VzIFJvdXRlciBoYXMgbm8gYC9fbm90LWZvdW5kYCwgYW5kIGBuZXh0IGJ1aWxkYCBwcmVyZW5kZXJzIGl0cyA0MDQg4oCUXG4gICAgLy8gb25lIHBlciBsb2NhbGUg4oCUIHdoaWNoIGBuZXh0IHN0YXJ0YCBzZXJ2ZXMgYWhlYWQgb2YgYC9fZXJyb3JgLlxuICAgIGV4cGVjdChzdGF0dXNUYXJnZXRPZihtYW5pZmVzdHNbXCJwYWdlcy1pMThuXCJdLCA0MDQpKS50b0VxdWFsKHtcbiAgICAgIGtpbmQ6IFwic3RhdGljLWZpbGVcIixcbiAgICAgIHBhdGhuYW1lOiBcIi9lbi1VUy80MDRcIixcbiAgICAgIGZpbGVQYXRoOiBtYW5pZmVzdHNbXCJwYWdlcy1pMThuXCJdLnN0YXRpY0ZpbGVzW1wiL2VuLVVTLzQwNFwiXSxcbiAgICB9KTtcbiAgfSk7XG5cbiAgaXQoXCJzZXJ2ZXMgdGhlIHByZXJlbmRlcmVkIDQwNCBvZiB0aGUgcmVxdWVzdCdzIGxvY2FsZVwiLCAoKSA9PiB7XG4gICAgLy8gRXZlcnkgUGFnZXMgYnVpbGQgaGFzIGAvX2Vycm9yYCwgc28gY2hlY2tpbmcgaXQgZmlyc3QgbWFkZSB0aGVcbiAgICAvLyBwcmVyZW5kZXJlZCA0MDQg4oCUIHRoZSBhcHAncyBgcGFnZXMvNDA0LmpzYCDigJQgZGVhZCBjb2RlOyBhbmQgdW5kZXIgaTE4blxuICAgIC8vIHRoZSBwcmVyZW5kZXIgaXMgb25seSBldmVyIGtleWVkIGJ5IGxvY2FsZSwgbmV2ZXIgYXMgYSBiYXJlIGAvNDA0YC5cbiAgICBjb25zdCBkaXNwYXRjaGVyID0gZGlzcGF0Y2hlckZvcihcInBhZ2VzLWkxOG5cIik7XG4gICAgY29uc3QgeyBzdGF0aWNGaWxlcyB9ID0gbWFuaWZlc3RzW1wicGFnZXMtaTE4blwiXTtcbiAgICBjb25zdCBhdCA9ICh1cmw6IHN0cmluZykgPT4gZGlzcGF0Y2hlci5ub3RGb3VuZEZvcihuZXcgVVJMKHVybCwgT1JJR0lOKSk7XG5cbiAgICBleHBlY3QoYXQoXCIvZnIvbm9wZVwiKSkudG9NYXRjaE9iamVjdCh7IGZpbGVQYXRoOiBzdGF0aWNGaWxlc1tcIi9mci80MDRcIl0gfSk7XG4gICAgZXhwZWN0KGF0KFwiL05MLW5sL25vcGVcIikpLnRvTWF0Y2hPYmplY3Qoe1xuICAgICAgZmlsZVBhdGg6IHN0YXRpY0ZpbGVzW1wiL25sLU5MLzQwNFwiXSxcbiAgICB9KTtcbiAgICBleHBlY3QoYXQoXCIvbm9wZVwiKSkudG9NYXRjaE9iamVjdCh7IGZpbGVQYXRoOiBzdGF0aWNGaWxlc1tcIi9lbi1VUy80MDRcIl0gfSk7XG4gICAgLy8gTm8gbG9jYWxlIGluIHRoZSBwYXRoOiB0aGUgZG9tYWluJ3MgZGVmYXVsdCwgYXMgYG5leHQgc3RhcnRgIHJlbmRlcnMgaXQuXG4gICAgZXhwZWN0KGF0KFwiaHR0cHM6Ly9leGFtcGxlLmZyL25vcGVcIikpLnRvTWF0Y2hPYmplY3Qoe1xuICAgICAgZmlsZVBhdGg6IHN0YXRpY0ZpbGVzW1wiL2ZyLzQwNFwiXSxcbiAgICB9KTtcbiAgfSk7XG5cbiAgaXQoXCJmYWxscyBiYWNrIHRvIC9fZXJyb3Igd2hlbiBubyA0MDQgd2FzIHByZXJlbmRlcmVkXCIsICgpID0+IHtcbiAgICAvLyBXaGF0IGEgYHBhZ2VzL19hcHAuanNgIHdpdGggYGdldEluaXRpYWxQcm9wc2AgYnVpbGRzIHdpdGhvdXQgYVxuICAgIC8vIGBwYWdlcy80MDQuanNgOiBgbmV4dCBidWlsZGAgdGhlbiBwcmVyZW5kZXJzIG5vIDQwNCBhdCBhbGwuXG4gICAgY29uc3QgYmFzZSA9IG1hbmlmZXN0c1tcInBhZ2VzLWkxOG5cIl07XG4gICAgY29uc3Qgd2l0aG91dDQwNCA9IE9iamVjdC5mcm9tRW50cmllcyhcbiAgICAgIE9iamVjdC5lbnRyaWVzKGJhc2Uuc3RhdGljRmlsZXMpLmZpbHRlcigoW2tleV0pID0+ICFrZXkuZW5kc1dpdGgoXCIvNDA0XCIpKSxcbiAgICApO1xuICAgIGV4cGVjdChcbiAgICAgIHN0YXR1c1RhcmdldE9mKHsgLi4uYmFzZSwgc3RhdGljRmlsZXM6IHdpdGhvdXQ0MDQgfSwgNDA0KSxcbiAgICApLnRvTWF0Y2hPYmplY3QoeyBraW5kOiBcImVudHJ5cG9pbnRcIiwgcGF0aG5hbWU6IFwiL19lcnJvclwiIH0pO1xuICB9KTtcblxuICBpdChcInByZWZlcnMgYW4gaW52b2NhYmxlIGN1c3RvbSAvNDA0IG92ZXIgL19lcnJvclwiLCAoKSA9PiB7XG4gICAgLy8gV2hhdCBgcGFnZXMvNDA0LmpzYCBwbHVzIGEgYHBhZ2VzL19hcHAuanNgIHdpdGggYGdldEluaXRpYWxQcm9wc2AgYnVpbGRzOlxuICAgIC8vIHRoZSA0MDQgY2Fubm90IGJlIHByZXJlbmRlcmVkLCBzbyBpdCBhcnJpdmVzIGFzIGFuIGVudHJ5cG9pbnQgYmVzaWRlXG4gICAgLy8gYC9fZXJyb3JgLiBTZXJ2aW5nIGAvX2Vycm9yYCB0aGVyZSBtZWFucyB0aGUgYnVpbHQtaW4gXCI0MDQ6IFRoaXMgcGFnZVxuICAgIC8vIGNvdWxkIG5vdCBiZSBmb3VuZFwiIHJlcGxhY2VzIHRoZSBhcHAncyBvd24g4oCUIGB0ZXN0L2UyZS80MDQtcGFnZS1hcHBgLlxuICAgIGNvbnN0IGJhc2UgPSBtYW5pZmVzdHNbXCJwYWdlcy1pMThuXCJdO1xuICAgIGNvbnN0IHdpdGhDdXN0b200MDQ6IEFkYXB0ZXJNYW5pZmVzdCA9IHtcbiAgICAgIC4uLmJhc2UsXG4gICAgICBlbnRyeXBvaW50czoge1xuICAgICAgICAuLi5iYXNlLmVudHJ5cG9pbnRzLFxuICAgICAgICBcIi80MDRcIjogeyAuLi5iYXNlLmVudHJ5cG9pbnRzW1wiL19lcnJvclwiXSwgaWQ6IFwiLzQwNFwiIH0sXG4gICAgICB9LFxuICAgIH07XG4gICAgZXhwZWN0KHN0YXR1c1RhcmdldE9mKHdpdGhDdXN0b200MDQsIDQwNCkpLnRvTWF0Y2hPYmplY3Qoe1xuICAgICAga2luZDogXCJlbnRyeXBvaW50XCIsXG4gICAgICBwYXRobmFtZTogXCIvNDA0XCIsXG4gICAgfSk7XG4gICAgLy8gQXBwIFJvdXRlciBzdGlsbCB3aW5zIG92ZXIgYm90aDogYC9fbm90LWZvdW5kYCBpcyB3aGF0IG5leHQgbG9va3MgZm9yXG4gICAgLy8gZmlyc3QsIGFuZCBhbiBhcHAgd2l0aCBib3RoIHJvdXRlcnMgaGFzIGFsbCB0aHJlZS5cbiAgICBleHBlY3QoXG4gICAgICBzdGF0dXNUYXJnZXRPZihcbiAgICAgICAge1xuICAgICAgICAgIC4uLndpdGhDdXN0b200MDQsXG4gICAgICAgICAgZW50cnlwb2ludHM6IHtcbiAgICAgICAgICAgIC4uLndpdGhDdXN0b200MDQuZW50cnlwb2ludHMsXG4gICAgICAgICAgICBcIi9fbm90LWZvdW5kXCI6IHtcbiAgICAgICAgICAgICAgLi4uYmFzZS5lbnRyeXBvaW50c1tcIi9fZXJyb3JcIl0sXG4gICAgICAgICAgICAgIGlkOiBcIi9fbm90LWZvdW5kXCIsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIDQwNCxcbiAgICAgICksXG4gICAgKS50b01hdGNoT2JqZWN0KHsga2luZDogXCJlbnRyeXBvaW50XCIsIHBhdGhuYW1lOiBcIi9fbm90LWZvdW5kXCIgfSk7XG4gIH0pO1xuXG4gIGl0KFwiZmFsbHMgYmFjayB0byBhIHByZXJlbmRlcmVkIDQwNCwgdGhlbiB0byBub3RoaW5nXCIsICgpID0+IHtcbiAgICBjb25zdCBiYXNlID0gbWFuaWZlc3RzW1wiYXBwLXBsYXlncm91bmRcIl07XG4gICAgY29uc3Qgd2l0aG91dEVudHJ5cG9pbnRzOiBBZGFwdGVyTWFuaWZlc3QgPSB7XG4gICAgICAuLi5iYXNlLFxuICAgICAgZW50cnlwb2ludHM6IHt9LFxuICAgICAgbWlkZGxld2FyZTogbnVsbCxcbiAgICB9O1xuICAgIGV4cGVjdChzdGF0dXNUYXJnZXRPZih3aXRob3V0RW50cnlwb2ludHMsIDQwNCkpLnRvRXF1YWwoe1xuICAgICAga2luZDogXCJzdGF0aWMtZmlsZVwiLFxuICAgICAgcGF0aG5hbWU6IFwiLzQwNFwiLFxuICAgICAgZmlsZVBhdGg6IGJhc2Uuc3RhdGljRmlsZXNbXCIvNDA0XCJdLFxuICAgIH0pO1xuICAgIGV4cGVjdChcbiAgICAgIHN0YXR1c1RhcmdldE9mKHsgLi4ud2l0aG91dEVudHJ5cG9pbnRzLCBzdGF0aWNGaWxlczoge30gfSwgNDA0KSxcbiAgICApLnRvRXF1YWwoeyBraW5kOiBcIm5vbmVcIiB9KTtcbiAgfSk7XG59KTtcblxuZGVzY3JpYmUoXCJ0aGUgNTAwIGxhZGRlclwiLCAoKSA9PiB7XG4gIGl0KFwicHJlZmVycyB0aGUgcHJlcmVuZGVyZWQgLzUwMCBuZXh0IGVtaXRzIGJ5IGRlZmF1bHRcIiwgKCkgPT4ge1xuICAgIGNvbnN0IGJhc2UgPSBtYW5pZmVzdHNbXCJhcHAtcGxheWdyb3VuZFwiXTtcbiAgICBleHBlY3Qoc3RhdHVzVGFyZ2V0T2YoYmFzZSwgNTAwKSkudG9FcXVhbCh7XG4gICAgICBraW5kOiBcInN0YXRpYy1maWxlXCIsXG4gICAgICBwYXRobmFtZTogXCIvNTAwXCIsXG4gICAgICBmaWxlUGF0aDogYmFzZS5zdGF0aWNGaWxlc1tcIi81MDBcIl0sXG4gICAgfSk7XG4gIH0pO1xuXG4gIGl0KFwicHJlZmVycyBhbiBpbnZvY2FibGUgLzUwMCBvdmVyIHRoZSBwcmVyZW5kZXJlZCBvbmVcIiwgKCkgPT4ge1xuICAgIC8vIFdoYXQgYSBgcGFnZXMvNTAwLmpzYCB0aGF0IGNhbm5vdCBiZSBzdGF0aWMtb3B0aW1pemVkIGJ1aWxkcy5cbiAgICBjb25zdCBiYXNlID0gbWFuaWZlc3RzW1wicGFnZXMtaTE4blwiXTtcbiAgICBleHBlY3QoXG4gICAgICBzdGF0dXNUYXJnZXRPZihcbiAgICAgICAge1xuICAgICAgICAgIC4uLmJhc2UsXG4gICAgICAgICAgZW50cnlwb2ludHM6IHtcbiAgICAgICAgICAgIC4uLmJhc2UuZW50cnlwb2ludHMsXG4gICAgICAgICAgICBcIi81MDBcIjogeyAuLi5iYXNlLmVudHJ5cG9pbnRzW1wiL19lcnJvclwiXSwgaWQ6IFwiLzUwMFwiIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgNTAwLFxuICAgICAgKSxcbiAgICApLnRvTWF0Y2hPYmplY3QoeyBraW5kOiBcImVudHJ5cG9pbnRcIiwgcGF0aG5hbWU6IFwiLzUwMFwiIH0pO1xuICB9KTtcblxuICBpdChcImZhbGxzIGJhY2sgdG8gL19lcnJvciwgdGhlbiB0byBub3RoaW5nXCIsICgpID0+IHtcbiAgICAvLyBgL19lcnJvcmAgaXMgd2hlcmUgYSBjdXN0b20gZXJyb3IgcGFnZSBsYW5kcyB3aGVuIGl0IGhhc1xuICAgIC8vIGBnZXRJbml0aWFsUHJvcHNgIOKAlCB0aGUgY2FzZSBgdGVzdC9lMmUvYXN5bmMtbW9kdWxlc2AgbWVhc3VyZXMuXG4gICAgY29uc3QgYmFzZSA9IG1hbmlmZXN0c1tcInBhZ2VzLWkxOG5cIl07XG4gICAgZXhwZWN0KHN0YXR1c1RhcmdldE9mKHsgLi4uYmFzZSwgc3RhdGljRmlsZXM6IHt9IH0sIDUwMCkpLnRvTWF0Y2hPYmplY3Qoe1xuICAgICAga2luZDogXCJlbnRyeXBvaW50XCIsXG4gICAgICBwYXRobmFtZTogXCIvX2Vycm9yXCIsXG4gICAgfSk7XG4gICAgZXhwZWN0KFxuICAgICAgc3RhdHVzVGFyZ2V0T2YoeyAuLi5iYXNlLCBzdGF0aWNGaWxlczoge30sIGVudHJ5cG9pbnRzOiB7fSB9LCA1MDApLFxuICAgICkudG9FcXVhbCh7IGtpbmQ6IFwibm9uZVwiIH0pO1xuICB9KTtcblxuICBpdChcInNlcnZlcyB0aGUgcHJlcmVuZGVyZWQgNTAwIG9mIHRoZSByZXF1ZXN0J3MgbG9jYWxlXCIsICgpID0+IHtcbiAgICAvLyBVbmRlciBpMThuIHRoZSBwcmVyZW5kZXJlZCA1MDAgaXMga2V5ZWQgb25seSBieSBsb2NhbGUsIG5ldmVyIGFzIGEgYmFyZVxuICAgIC8vIGAvNTAwYCwgc28gbG9va2luZyB1cCBgLzUwMGAgYWxvbmUgYWx3YXlzIGZlbGwgdGhyb3VnaCB0byBgL19lcnJvcmAuXG4gICAgY29uc3QgYmFzZSA9IG1hbmlmZXN0c1tcInBhZ2VzLWkxOG5cIl07XG4gICAgY29uc3QgZXJyb3JUYXJnZXRGb3IgPSBzdGF0dXNUYXJnZXRzKGJhc2UsIDUwMCk7XG4gICAgY29uc3QgYXQgPSAodXJsOiBzdHJpbmcpID0+IGVycm9yVGFyZ2V0Rm9yKG5ldyBVUkwodXJsLCBPUklHSU4pKTtcblxuICAgIGV4cGVjdChhdChcIi9mci9zc3JcIikpLnRvRXF1YWwoe1xuICAgICAga2luZDogXCJzdGF0aWMtZmlsZVwiLFxuICAgICAgcGF0aG5hbWU6IFwiL2ZyLzUwMFwiLFxuICAgICAgZmlsZVBhdGg6IGJhc2Uuc3RhdGljRmlsZXNbXCIvZnIvNTAwXCJdLFxuICAgIH0pO1xuICAgIGV4cGVjdChhdChcIi9zc3JcIikpLnRvTWF0Y2hPYmplY3QoeyBwYXRobmFtZTogXCIvZW4tVVMvNTAwXCIgfSk7XG4gICAgLy8gTm8gbG9jYWxlIGluIHRoZSBwYXRoOiB0aGUgZG9tYWluJ3MgZGVmYXVsdCwgYXMgYG5leHQgc3RhcnRgIHJlbmRlcnMgaXQuXG4gICAgZXhwZWN0KGF0KFwiaHR0cHM6Ly9leGFtcGxlLmZyL3NzclwiKSkudG9NYXRjaE9iamVjdCh7XG4gICAgICBwYXRobmFtZTogXCIvZnIvNTAwXCIsXG4gICAgfSk7XG4gICAgLy8gQSByZXF1ZXN0IHdob3NlIFVSTCBjb3VsZCBub3QgYmUgcGFyc2VkIGdldHMgdGhlIGRlZmF1bHQgbG9jYWxlJ3MuXG4gICAgZXhwZWN0KGVycm9yVGFyZ2V0Rm9yKHVuZGVmaW5lZCkpLnRvTWF0Y2hPYmplY3Qoe1xuICAgICAgcGF0aG5hbWU6IFwiL2VuLVVTLzUwMFwiLFxuICAgIH0pO1xuICAgIGV4cGVjdChzdGF0dXNUYXJnZXRPZihiYXNlLCA1MDApKS50b01hdGNoT2JqZWN0KHsgcGF0aG5hbWU6IFwiL2VuLVVTLzUwMFwiIH0pO1xuICB9KTtcblxuICBpdChcImxvb2tzIGZvciB0aGUgZXJyb3IgcGFnZSB1bmRlciB0aGUgYXBwJ3MgYmFzZVBhdGhcIiwgKCkgPT4ge1xuICAgIGNvbnN0IGJhc2UgPSBtYW5pZmVzdHNbXCJhcHAtcGxheWdyb3VuZC1iYXNlLXBhdGhcIl07XG4gICAgZXhwZWN0KHN0YXR1c1RhcmdldE9mKGJhc2UsIDUwMCkpLnRvTWF0Y2hPYmplY3QoeyBwYXRobmFtZTogXCIvcHJvZC81MDBcIiB9KTtcbiAgfSk7XG59KTtcblxuZGVzY3JpYmUoXCJ0b1JlZGlyZWN0XCIsICgpID0+IHtcbiAgaXQoXCJwcmVmZXJzIHRoZSBkb2N1bWVudGVkIHJlZGlyZWN0IGZpZWxkXCIsICgpID0+IHtcbiAgICAvLyBgcmVzb2x2ZVJvdXRlc2AgZG9lcyBub3QgcG9wdWxhdGUgYFJlc29sdmVSb3V0ZXNSZXN1bHQucmVkaXJlY3RgIGluXG4gICAgLy8gbmV4dCAxNi4zLjUg4oCUIGV2ZXJ5IHJlZGlyZWN0IGFycml2ZXMgYXMgYmFyZSBzdGF0dXMgKyBgbG9jYXRpb25gIOKAlCBzbyB0aGlzXG4gICAgLy8gaXMgdGhlIG9ubHkgY292ZXJhZ2UgdGhhdCBicmFuY2ggY2FuIGhhdmUgdW50aWwgaXQgZG9lcy5cbiAgICBleHBlY3QoXG4gICAgICB0b1JlZGlyZWN0KFxuICAgICAgICB7IHJlZGlyZWN0OiB7IHVybDogbmV3IFVSTChcImh0dHBzOi8vZS50ZXN0L3hcIiksIHN0YXR1czogMzAxIH0gfSxcbiAgICAgICAgbmV3IEhlYWRlcnMoKSxcbiAgICAgICksXG4gICAgKS50b0VxdWFsKHsgbG9jYXRpb246IFwiaHR0cHM6Ly9lLnRlc3QveFwiLCBzdGF0dXM6IDMwMSB9KTtcbiAgfSk7XG5cbiAgaXQoXCJpZ25vcmVzIGEgbG9jYXRpb24gaGVhZGVyIG9uIGEgbm9uLTN4eCBzdGF0dXNcIiwgKCkgPT4ge1xuICAgIGNvbnN0IGhlYWRlcnMgPSBuZXcgSGVhZGVycyh7IGxvY2F0aW9uOiBcIi94XCIgfSk7XG4gICAgZXhwZWN0KHRvUmVkaXJlY3QoeyBzdGF0dXM6IDIwMCB9LCBoZWFkZXJzKSkudG9CZVVuZGVmaW5lZCgpO1xuICAgIGV4cGVjdCh0b1JlZGlyZWN0KHsgc3RhdHVzOiA0MDMgfSwgaGVhZGVycykpLnRvQmVVbmRlZmluZWQoKTtcbiAgICBleHBlY3QodG9SZWRpcmVjdCh7fSwgaGVhZGVycykpLnRvQmVVbmRlZmluZWQoKTtcbiAgICBleHBlY3QodG9SZWRpcmVjdCh7IHN0YXR1czogMzA4IH0sIG5ldyBIZWFkZXJzKCkpKS50b0JlVW5kZWZpbmVkKCk7XG4gIH0pO1xufSk7XG5cbmRlc2NyaWJlKFwiRGlzcGF0Y2hlciBtaWRkbGV3YXJlIGhhbmRsaW5nXCIsICgpID0+IHtcbiAgaXQoXCJyZXBvcnRzIGEgbWlkZGxld2FyZSByZXNwb25zZSB3aXRob3V0IHJlc29sdmluZyBhIHJvdXRlXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBkaXNwYXRjaGVyRm9yKFwiYXBwLXBsYXlncm91bmRcIiwgYXN5bmMgKCkgPT4gKHtcbiAgICAgIGJvZHlTZW50OiB0cnVlLFxuICAgICAgcmVzcG9uc2VIZWFkZXJzOiBuZXcgSGVhZGVycyh7IFwieC1td1wiOiBcInJlc3BvbmRlZFwiIH0pLFxuICAgIH0pKS5kaXNwYXRjaChyZXF1ZXN0KFwiL2lzci8xXCIpKTtcbiAgICBleHBlY3QocmVzdWx0LmtpbmQpLnRvQmUoXCJtaWRkbGV3YXJlLXJlc3BvbmRlZFwiKTtcbiAgfSk7XG5cbiAgaXQoXCJzZW5kcyBuZXh0LmNvbmZpZyBoZWFkZXJzKCkgd2l0aCBhIHJlc3BvbnNlIG1pZGRsZXdhcmUgd3JvdGVcIiwgYXN5bmMgKCkgPT4ge1xuICAgIC8vIGBhcHAtcGxheWdyb3VuZGAncyBgaGVhZGVycygpYCBzZXRzIHRoaXMgb24gYC9hcGkvZWNob2A7IGBuZXh0IHN0YXJ0YFxuICAgIC8vIHNlbmRzIGl0IHdpdGggYSBtaWRkbGV3YXJlIDQwMSB0aGVyZSB0b28uXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZGlzcGF0Y2hlckZvcihcImFwcC1wbGF5Z3JvdW5kXCIsIGFzeW5jICgpID0+ICh7XG4gICAgICBib2R5U2VudDogdHJ1ZSxcbiAgICB9KSkuZGlzcGF0Y2gocmVxdWVzdChcIi9hcGkvZWNob1wiKSk7XG4gICAgZXhwZWN0KHJlc3VsdC5raW5kKS50b0JlKFwibWlkZGxld2FyZS1yZXNwb25kZWRcIik7XG4gICAgZXhwZWN0KHJlc3VsdC5yZXNwb25zZUhlYWRlcnMuZ2V0KFwieC1lMmUtY29uZmlnLWhlYWRlclwiKSkudG9CZShcbiAgICAgIFwiZnJvbS1uZXh0LWNvbmZpZ1wiLFxuICAgICk7XG5cbiAgICBjb25zdCBvdGhlciA9IGF3YWl0IGRpc3BhdGNoZXJGb3IoXCJhcHAtcGxheWdyb3VuZFwiLCBhc3luYyAoKSA9PiAoe1xuICAgICAgYm9keVNlbnQ6IHRydWUsXG4gICAgfSkpLmRpc3BhdGNoKHJlcXVlc3QoXCIvaXNyLzFcIikpO1xuICAgIGV4cGVjdChvdGhlci5yZXNwb25zZUhlYWRlcnMuaGFzKFwieC1lMmUtY29uZmlnLWhlYWRlclwiKSkudG9CZShmYWxzZSk7XG4gIH0pO1xuXG4gIGl0KFwibm9ybWFsaXplcyBhIG1pZGRsZXdhcmUgcmVkaXJlY3QgdG8gYSBzYW1lLW9yaWdpbiBwYXRoXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBkaXNwYXRjaGVyRm9yKFwiYXBwLXBsYXlncm91bmRcIiwgYXN5bmMgKCkgPT4gKHtcbiAgICAgIHJlZGlyZWN0OiB7IHVybDogbmV3IFVSTChcIi9sb2dpblwiLCBPUklHSU4pLCBzdGF0dXM6IDMwNyB9LFxuICAgIH0pKS5kaXNwYXRjaChyZXF1ZXN0KFwiL2lzci8xXCIpKTtcbiAgICBleHBlY3QocmVzdWx0KS50b01hdGNoT2JqZWN0KHtcbiAgICAgIGtpbmQ6IFwicmVkaXJlY3RcIixcbiAgICAgIHN0YXR1czogMzA3LFxuICAgICAgLy8gYE5leHRSZXNwb25zZS5yZWRpcmVjdChuZXcgVVJMKFwiL2xvZ2luXCIsIHJlcXVlc3QudXJsKSlgIGlzIGhvdyBldmVyeVxuICAgICAgLy8gbWlkZGxld2FyZSBzcGVsbHMgdGhpcywgYW5kIE5leHQuanMgc2VuZHMgdGhlIHBhdGg6IGBAbmV4dC9yb3V0aW5nYCdzXG4gICAgICAvLyBvd24gYGdldFJlbGF0aXZlVVJMYCBkb2VzIGl0IGZvciB0aGUgaGVhZGVyIGl0IHNldHMsIGFuZCBvbmx5IHRoZVxuICAgICAgLy8gYHJlZGlyZWN0LnVybGAgZmllbGQgdGhpcyBwYXRoIHJlYWRzIGtlZXBzIHRoZSBhYnNvbHV0ZSBmb3JtLlxuICAgICAgbG9jYXRpb246IFwiL2xvZ2luXCIsXG4gICAgfSk7XG4gIH0pO1xuXG4gIGl0KFwiZm9sbG93cyBhbiBpbnRlcm5hbCBtaWRkbGV3YXJlIHJld3JpdGUgdG8gdGhlIHJld3JpdHRlbiBlbnRyeXBvaW50XCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBkaXNwYXRjaGVyRm9yKFwiYXBwLXBsYXlncm91bmRcIiwgYXN5bmMgKCkgPT4gKHtcbiAgICAgIHJld3JpdGU6IG5ldyBVUkwoXCIvYXBpL2hlYWx0aFwiLCBPUklHSU4pLFxuICAgIH0pKS5kaXNwYXRjaChyZXF1ZXN0KFwiL2lzci8xXCIpKTtcbiAgICBleHBlY3QocmVzdWx0LmtpbmQpLnRvQmUoXCJlbnRyeXBvaW50XCIpO1xuICAgIGlmIChyZXN1bHQua2luZCAhPT0gXCJlbnRyeXBvaW50XCIpIHJldHVybjtcbiAgICBleHBlY3QocmVzdWx0LnJlc29sdmVkUGF0aG5hbWUpLnRvQmUoXCIvYXBpL2hlYWx0aFwiKTtcbiAgfSk7XG5cbiAgaXQoXCJyb3V0ZXMgL19uZXh0L2ltYWdlIHdoZW4gbWlkZGxld2FyZSBpcyB3aGF0IHB1dCB0aGUgcmVxdWVzdCBvbiBpdFwiLCBhc3luYyAoKSA9PiB7XG4gICAgLy8gVGhlIEFQSSBHYXRld2F5IGV4YW1wbGVzJyBtaWRkbGV3YXJlIHJld3JpdGVzIGAveGAgdG8gYC88c3RhZ2U+L3hgIHNvIHRoZVxuICAgIC8vIGJ1aWxkJ3MgYGJhc2VQYXRoYCBsaW5lcyB1cC4gYHJlc29sdmVSb3V0ZXNgIG5ldmVyIHJlcG9ydHMgdGhlIHJld3JpdHRlblxuICAgIC8vIFVSTCBiYWNrLCBzbyBvcHRpbWl6aW5nIHRoZSBVUkwgYXMgcmVjZWl2ZWQgd291bGQgbG9zZSB0aGUgcmV3cml0ZS5cbiAgICBjb25zdCBxdWVyeSA9IFwiP3VybD0lMkZmb28ucG5nJnc9NjQwJnE9NzVcIjtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBkaXNwYXRjaGVyRm9yKFxuICAgICAgXCJhcHAtcGxheWdyb3VuZC1iYXNlLXBhdGhcIixcbiAgICAgIGFzeW5jICgpID0+ICh7IHJld3JpdGU6IG5ldyBVUkwoYC9wcm9kL19uZXh0L2ltYWdlJHtxdWVyeX1gLCBPUklHSU4pIH0pLFxuICAgICkuZGlzcGF0Y2gocmVxdWVzdChgL19uZXh0L2ltYWdlJHtxdWVyeX1gKSk7XG4gICAgZXhwZWN0KHJlc3VsdC5raW5kKS50b0JlKFwiaW1hZ2Utb3B0aW1pemF0aW9uXCIpO1xuICAgIGlmIChyZXN1bHQua2luZCAhPT0gXCJpbWFnZS1vcHRpbWl6YXRpb25cIikgcmV0dXJuO1xuICAgIGV4cGVjdChyZXN1bHQudXJsLnNlYXJjaFBhcmFtcy5nZXQoXCJ1cmxcIikpLnRvQmUoXCIvZm9vLnBuZ1wiKTtcbiAgfSk7XG5cbiAgaXQoXCJkb2VzIG5vdCBsZWFrIHRoZSBpbnRlcm5hbCByZXdyaXRlIGhlYWRlciBpdCBjb25zdW1lZFwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZGlzcGF0Y2hlckZvcihcImFwcC1wbGF5Z3JvdW5kXCIsIGFzeW5jICgpID0+ICh7XG4gICAgICByZXdyaXRlOiBuZXcgVVJMKFwiL2FwaS9oZWFsdGhcIiwgT1JJR0lOKSxcbiAgICAgIHJlc3BvbnNlSGVhZGVyczogbmV3IEhlYWRlcnMoeyBcIngtbWlkZGxld2FyZS1yZXdyaXRlXCI6IFwiL2FwaS9oZWFsdGhcIiB9KSxcbiAgICB9KSkuZGlzcGF0Y2gocmVxdWVzdChcIi9pc3IvMVwiKSk7XG4gICAgZXhwZWN0KHJlc3VsdC5yZXNwb25zZUhlYWRlcnMuaGFzKFwieC1taWRkbGV3YXJlLXJld3JpdGVcIikpLnRvQmUoZmFsc2UpO1xuICB9KTtcblxuICBpdChcInJlcG9ydHMgYW4gZXh0ZXJuYWwgbWlkZGxld2FyZSByZXdyaXRlIGFzIGEgcHJveHkgdGFyZ2V0XCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBkaXNwYXRjaGVyRm9yKFwiYXBwLXBsYXlncm91bmRcIiwgYXN5bmMgKCkgPT4gKHtcbiAgICAgIHJld3JpdGU6IG5ldyBVUkwoXCJodHRwczovL3Vwc3RyZWFtLnRlc3QveFwiKSxcbiAgICB9KSkuZGlzcGF0Y2gocmVxdWVzdChcIi9pc3IvMVwiKSk7XG4gICAgZXhwZWN0KHJlc3VsdC5raW5kKS50b0JlKFwiZXh0ZXJuYWwtcmV3cml0ZVwiKTtcbiAgICBpZiAocmVzdWx0LmtpbmQgIT09IFwiZXh0ZXJuYWwtcmV3cml0ZVwiKSByZXR1cm47XG4gICAgZXhwZWN0KHJlc3VsdC51cmwuaHJlZikudG9CZShcImh0dHBzOi8vdXBzdHJlYW0udGVzdC94XCIpO1xuICB9KTtcblxuICBpdChcImNhcnJpZXMgbWlkZGxld2FyZSByZXF1ZXN0IGhlYWRlcnMgZm9yd2FyZCBhbmQgcmVzcG9uc2UgaGVhZGVycyBiYWNrXCIsIGFzeW5jICgpID0+IHtcbiAgICAvLyBgcmVzb2x2ZVJvdXRlc2AgZHJvcHMgYE1pZGRsZXdhcmVSZXN1bHQucmVxdWVzdEhlYWRlcnNgOiBpdCBuZWl0aGVyXG4gICAgLy8gcmV0dXJucyB0aGVtIG5vciBtdXRhdGVzIHRoZSBgaGVhZGVyc2AgaXQgd2FzIGdpdmVuLiBEaXNwYXRjaCBjYXB0dXJlc1xuICAgIC8vIHRoZW0gZnJvbSB0aGUgY2FsbGJhY2ssIHdoaWNoIGlzIHdoYXQga2VlcHNcbiAgICAvLyBgTmV4dFJlc3BvbnNlLm5leHQoeyByZXF1ZXN0OiB7IGhlYWRlcnMgfSB9KWAgd29ya2luZy5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBkaXNwYXRjaGVyRm9yKFwiYXBwLXBsYXlncm91bmRcIiwgYXN5bmMgKCkgPT4gKHtcbiAgICAgIHJlcXVlc3RIZWFkZXJzOiBuZXcgSGVhZGVycyh7IGhvc3Q6IFwiZXhhbXBsZS50ZXN0XCIsIFwieC11c2VyXCI6IFwiNDJcIiB9KSxcbiAgICAgIHJlc3BvbnNlSGVhZGVyczogbmV3IEhlYWRlcnMoeyBcIngtbXdcIjogXCJyYW5cIiB9KSxcbiAgICB9KSkuZGlzcGF0Y2gocmVxdWVzdChcIi9pc3IvMVwiKSk7XG4gICAgZXhwZWN0KHJlc3VsdC5raW5kKS50b0JlKFwiZW50cnlwb2ludFwiKTtcbiAgICBpZiAocmVzdWx0LmtpbmQgIT09IFwiZW50cnlwb2ludFwiKSByZXR1cm47XG4gICAgZXhwZWN0KHJlc3VsdC5yZXF1ZXN0SGVhZGVycy5nZXQoXCJ4LXVzZXJcIikpLnRvQmUoXCI0MlwiKTtcbiAgICBleHBlY3QocmVzdWx0LnJlc3BvbnNlSGVhZGVycy5nZXQoXCJ4LW13XCIpKS50b0JlKFwicmFuXCIpO1xuICB9KTtcblxuICBpdChcInBhc3NlcyB0aGUgY2FsbGVyJ3MgcmVxdWVzdCBoZWFkZXJzIHRocm91Z2ggd2hlbiBtaWRkbGV3YXJlIGFkZHMgbm9uZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZGlzcGF0Y2hlckZvcihcImFwcC1wbGF5Z3JvdW5kXCIpLmRpc3BhdGNoKFxuICAgICAgcmVxdWVzdChcIi9pc3IvMVwiLCB7IFwieC1jYWxsZXJcIjogXCJ5ZXNcIiB9KSxcbiAgICApO1xuICAgIGV4cGVjdChyZXN1bHQua2luZCkudG9CZShcImVudHJ5cG9pbnRcIik7XG4gICAgaWYgKHJlc3VsdC5raW5kICE9PSBcImVudHJ5cG9pbnRcIikgcmV0dXJuO1xuICAgIGV4cGVjdChyZXN1bHQucmVxdWVzdEhlYWRlcnMuZ2V0KFwieC1jYWxsZXJcIikpLnRvQmUoXCJ5ZXNcIik7XG4gIH0pO1xufSk7XG5cbmRlc2NyaWJlKFwicmVwYWlyUm91dGVQYXJhbVF1ZXJ5XCIsICgpID0+IHtcbiAgaXQoXCJkcm9wcyBhbiBvcHRpb25hbCBjYXRjaGFsbCdzIHBhcmFtIHdoZW4gdGhlIHJlcXVlc3QgZmlsbGVkIG5vbmVcIiwgKCkgPT4ge1xuICAgIC8vIE1lYXN1cmVkIGZyb20gYHJlc29sdmVSb3V0ZXNgIGZvciBgL29wdGlvbmFsLWNhdGNoYWxsYCBhZ2FpbnN0XG4gICAgLy8gYGFwcC9vcHRpb25hbC1jYXRjaGFsbC9bWy4uLnBhcmFtc11dYDogKmJvdGgqIHNpZGVzIGNhcnJ5IHRoZSBrZXkgd2l0aCBub1xuICAgIC8vIHZhbHVlLCB3aGljaCB0aGUgYEBuZXh0L3JvdXRpbmdgIHR5cGVzIGRvIG5vdCBhZG1pdC4gVGhlIGtleSBhbG9uZSBpcyB3aGF0XG4gICAgLy8gbWFrZXMgYHByZXBhcmUoKWAgaW52ZW50IGEgcGFyYW0sIHNvIHRoZSBrZXkgaGFzIHRvIGdvLlxuICAgIGV4cGVjdChcbiAgICAgIHJlcGFpclJvdXRlUGFyYW1RdWVyeShcbiAgICAgICAgeyBueHRQcGFyYW1zOiB1bmRlZmluZWQhIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBueHRQcGFyYW1zOiB1bmRlZmluZWQsXG4gICAgICAgIH0sXG4gICAgICApLFxuICAgICkudG9FcXVhbCh7fSk7XG4gICAgLy8gVGhlIHNhbWUgc2hhcGUgd2l0aCBcIlwiIGZvciB0aGUgdmFsdWUsIHdoaWNoIHRoZSBleHBhbnNpb24gY2FuIGFsc28gcHJvZHVjZS5cbiAgICBleHBlY3QocmVwYWlyUm91dGVQYXJhbVF1ZXJ5KHsgbnh0UHBhcmFtczogXCJcIiB9LCB7fSkpLnRvRXF1YWwoe30pO1xuICAgIC8vIEEgZmlsbGVkIG9uZSBpcyBsZWZ0IGFsb25lLCB3aGljaGV2ZXIgc291cmNlIGl0IGNhbWUgZnJvbS5cbiAgICBleHBlY3QoXG4gICAgICByZXBhaXJSb3V0ZVBhcmFtUXVlcnkoeyBueHRQcGFyYW1zOiBcImEvYlwiIH0sIHsgbnh0UHBhcmFtczogXCJhL2JcIiB9KSxcbiAgICApLnRvRXF1YWwoeyBueHRQcGFyYW1zOiBcImEvYlwiIH0pO1xuICAgIC8vIE5vIHJvdXRlIHBhcmFtIGNhbiBiZSBsZWdpdGltYXRlbHkgZW1wdHkgLSBhIHJlcXVpcmVkIHNlZ21lbnQgY2FwdHVyZXNcbiAgICAvLyBgW14vXSs/YCwgYSByZXF1aXJlZCBjYXRjaGFsbCBgLis/YCwgYW5kIGFuIG9wdGlvbmFsIGNhdGNoYWxsIHRoYXQgbWF0Y2hlZFxuICAgIC8vIG5vdGhpbmcgaGFzIG5vIGdyb3VwIGZvciBgcm91dGVNYXRjaGVzYCB0byByZXBvcnQgLSBzbyBhbiBlbXB0eSB2YWx1ZSBnb2VzXG4gICAgLy8gd2hldGhlciBvciBub3QgYHJvdXRlTWF0Y2hlc2AgZWNob2VzIGl0LlxuICAgIGV4cGVjdChyZXBhaXJSb3V0ZVBhcmFtUXVlcnkoeyBueHRQaWQ6IFwiXCIgfSwgeyBueHRQaWQ6IFwiXCIgfSkpLnRvRXF1YWwoe30pO1xuICAgIC8vIE5vdCBhIHJvdXRlIHBhcmFtLCBzbyBub3Qgb3VycyB0byB0b3VjaC5cbiAgICBleHBlY3QocmVwYWlyUm91dGVQYXJhbVF1ZXJ5KHsgcTogXCJcIiB9LCB7fSkpLnRvRXF1YWwoeyBxOiBcIlwiIH0pO1xuICB9KTtcblxuICBpdChcInJlcGFpcnMgYW5kIGRyb3BzIGluIG9uZSBwYXNzXCIsICgpID0+IHtcbiAgICAvLyBUaGUgcHJlZml4IGNvbGxpc2lvbiBhbmQgdGhlIHVuc2V0IG9wdGlvbmFsIGNhdGNoYWxsIGluIHRoZSBzYW1lIHF1ZXJ5OlxuICAgIC8vIGBueHRQaWQyYCBpcyB3cm9uZyBhbmQgYG54dFByZXN0YCB3YXMgbmV2ZXIgcmVxdWVzdGVkLlxuICAgIGV4cGVjdChcbiAgICAgIHJlcGFpclJvdXRlUGFyYW1RdWVyeShcbiAgICAgICAgeyBueHRQaWQ6IFwiYVwiLCBueHRQaWQyOiBcImEyXCIsIG54dFByZXN0OiBcIlwiIH0sXG4gICAgICAgIHsgbnh0UGlkOiBcImFcIiwgbnh0UGlkMjogXCJiXCIgfSxcbiAgICAgICksXG4gICAgKS50b0VxdWFsKHsgbnh0UGlkOiBcImFcIiwgbnh0UGlkMjogXCJiXCIgfSk7XG4gIH0pO1xufSk7XG5cbmRlc2NyaWJlKFwib3V0T2ZCYW5kUm91dGVQYXJhbXNcIiwgKCkgPT4ge1xuICBpdChcImxlYXZlcyBhIHF1ZXJ5IHRoZSBjb250cmFjdCBjYW4gY2FycnkgYWxvbmVcIiwgKCkgPT4ge1xuICAgIGV4cGVjdChcbiAgICAgIG91dE9mQmFuZFJvdXRlUGFyYW1zKFxuICAgICAgICB7IG54dFByZXN0OiBcImEvYlwiLCBxOiBcIjFcIiB9LFxuICAgICAgICBcIi9wYWdlcy1jYWNoZS9bLi4ucmVzdF1cIixcbiAgICAgICksXG4gICAgKS50b0JlVW5kZWZpbmVkKCk7XG4gICAgZXhwZWN0KG91dE9mQmFuZFJvdXRlUGFyYW1zKHsgbnh0UGlkOiBcIjQyXCIgfSwgXCIvaXNyL1tpZF1cIikpLnRvQmVVbmRlZmluZWQoKTtcbiAgICAvLyBBbiBlbmNvZGVkIGRlbGltaXRlciBpbiBzb21ldGhpbmcgdGhhdCBpcyBub3QgYSByb3V0ZSBwYXJhbSBpcyBub3Qgb3Vycy5cbiAgICBleHBlY3QoXG4gICAgICBvdXRPZkJhbmRSb3V0ZVBhcmFtcyh7IHE6IFwiYSUyRmJcIiB9LCBcIi9wYWdlcy1jYWNoZS9bLi4ucmVzdF1cIiksXG4gICAgKS50b0JlVW5kZWZpbmVkKCk7XG4gIH0pO1xuXG4gIGl0KFwicmVzdGF0ZXMgYSBjYXB0dXJlIHdpdGggYW4gZW5jb2RlZCBkZWxpbWl0ZXIgYXMgcGFyYW1zLCBvbmNlIGRlY29kZWRcIiwgKCkgPT4ge1xuICAgIC8vIGB0ZXN0L2UyZS9pbmNyZW1lbnRhbC1jYWNoZS1wYXRoLXRyYXZlcnNhbGAuIFRocm91Z2ggdGhlIHF1ZXJ5IGNvbnRyYWN0XG4gICAgLy8gdGhpcyBiZWNvbWVzIHRocmVlIHBhcmFtcyBhbmQgYG5vcm1hbGl6ZVBhZ2VQYXRoYCB0aHJvd3Mgb24gdGhlIHBhdGhuYW1lXG4gICAgLy8gcmVidWlsdCBmcm9tIHRoZW07IGBuZXh0IHN0YXJ0YCByZW5kZXJzIG9uZSBwYXJhbSwgd2hpY2ggaXMgdGhpcy5cbiAgICBleHBlY3QoXG4gICAgICBvdXRPZkJhbmRSb3V0ZVBhcmFtcyhcbiAgICAgICAgeyBueHRQcmVzdDogXCIuLiUyRi4uJTJGc2VydmVyLXJlZmVyZW5jZS1tYW5pZmVzdFwiIH0sXG4gICAgICAgIFwiL19uZXh0L2RhdGEvQlVJTERfSUQvcGFnZXMtY2FjaGUvWy4uLnJlc3RdLmpzb25cIixcbiAgICAgICksXG4gICAgKS50b0VxdWFsKHtcbiAgICAgIHBhcmFtczogeyByZXN0OiBbXCIuLi8uLi9zZXJ2ZXItcmVmZXJlbmNlLW1hbmlmZXN0XCJdIH0sXG4gICAgICBxdWVyeToge30sXG4gICAgfSk7XG4gIH0pO1xuXG4gIGl0KFwic3BsaXRzIGEgcmVwZWF0IG9uIHJlYWwgZGVsaW1pdGVycyBvbmx5LCBhbmQga2VlcHMgYSBzaW5nbGUgcGFyYW0gd2hvbGVcIiwgKCkgPT4ge1xuICAgIGV4cGVjdChcbiAgICAgIG91dE9mQmFuZFJvdXRlUGFyYW1zKFxuICAgICAgICB7IG54dFByZXN0OiBcImEvYiUyRmMvZFwiIH0sXG4gICAgICAgIFwiL3BhZ2VzLWNhY2hlL1tbLi4ucmVzdF1dXCIsXG4gICAgICApLFxuICAgICkudG9FcXVhbCh7IHBhcmFtczogeyByZXN0OiBbXCJhXCIsIFwiYi9jXCIsIFwiZFwiXSB9LCBxdWVyeToge30gfSk7XG4gICAgZXhwZWN0KG91dE9mQmFuZFJvdXRlUGFyYW1zKHsgbnh0UGlkOiBcImElMkZiXCIgfSwgXCIvaXNyL1tpZF1cIikpLnRvRXF1YWwoe1xuICAgICAgcGFyYW1zOiB7IGlkOiBcImEvYlwiIH0sXG4gICAgICBxdWVyeToge30sXG4gICAgfSk7XG4gIH0pO1xuXG4gIGl0KFwia2VlcHMgZXZlcnl0aGluZyB0aGF0IGlzIG5vdCBhIHJvdXRlIHBhcmFtIGluIHRoZSBxdWVyeVwiLCAoKSA9PiB7XG4gICAgZXhwZWN0KFxuICAgICAgb3V0T2ZCYW5kUm91dGVQYXJhbXMoXG4gICAgICAgIHsgbnh0UHJlc3Q6IFwiYSUyRmJcIiwgZnJvbTogXCIveFwiLCBwYWdlOiBcIjJcIiB9LFxuICAgICAgICBcIi9wYWdlcy1jYWNoZS9bLi4ucmVzdF1cIixcbiAgICAgICksXG4gICAgKS50b0VxdWFsKHtcbiAgICAgIHBhcmFtczogeyByZXN0OiBbXCJhL2JcIl0gfSxcbiAgICAgIHF1ZXJ5OiB7IGZyb206IFwiL3hcIiwgcGFnZTogXCIyXCIgfSxcbiAgICB9KTtcbiAgfSk7XG5cbiAgaXQoXCJzdGF5cyBvbiB0aGUgcXVlcnkgY29udHJhY3Qgd2hlbiBhIHBhcmFtIGNhbm5vdCBiZSByZXN0YXRlZFwiLCAoKSA9PiB7XG4gICAgLy8gQW4gb3B0aW9uYWwgY2F0Y2hhbGwgdGhlIHJlcXVlc3QgbGVmdCB1bnNldC4gSGFsZiBhIHBhcmFtIHNldCBpcyB3b3JzZVxuICAgIC8vIHRoYW4gbm9uZTogYHByZXBhcmVgIHdvdWxkIGludGVycG9sYXRlIGEgcm91dGUgd2l0aCBhIG1pc3Npbmcgc2VnbWVudC5cbiAgICBleHBlY3QoXG4gICAgICBvdXRPZkJhbmRSb3V0ZVBhcmFtcyhcbiAgICAgICAgeyBueHRQcmVzdDogXCJhJTJGYlwiLCBueHRQb3B0aW9uYWw6IFwiXCIgfSxcbiAgICAgICAgXCIvcGFnZXMtY2FjaGUvWy4uLnJlc3RdL1tbLi4ub3B0aW9uYWxdXVwiLFxuICAgICAgKSxcbiAgICApLnRvQmVVbmRlZmluZWQoKTtcbiAgfSk7XG5cbiAgaXQoXCJ0b2xlcmF0ZXMgYSBjYXB0dXJlIHRoYXQgaXMgbm90IHZhbGlkIHBlcmNlbnQtZW5jb2RpbmdcIiwgKCkgPT4ge1xuICAgIC8vIGBkZWNvZGVRdWVyeVBhdGhQYXJhbWV0ZXJgIGlzIGEgdHJ5L2NhdGNoIGZvciB0aGUgc2FtZSByZWFzb246IGAlMkZgIG1ha2VzXG4gICAgLy8gdGhpcyByZWFjaGFibGUgd2hpbGUgYCV6emAgbWFrZXMgYGRlY29kZVVSSUNvbXBvbmVudGAgdGhyb3cuXG4gICAgZXhwZWN0KFxuICAgICAgb3V0T2ZCYW5kUm91dGVQYXJhbXMoeyBueHRQcmVzdDogXCJhJTJGJXp6XCIgfSwgXCIvcGFnZXMtY2FjaGUvWy4uLnJlc3RdXCIpLFxuICAgICkudG9FcXVhbCh7IHBhcmFtczogeyByZXN0OiBbXCJhJTJGJXp6XCJdIH0sIHF1ZXJ5OiB7fSB9KTtcbiAgfSk7XG59KTtcbiJdfQ==