@workflow/core 5.0.0-beta.4 → 5.0.0-beta.41

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 (322) hide show
  1. package/dist/attribute-changes.d.ts +7 -0
  2. package/dist/attribute-changes.d.ts.map +1 -0
  3. package/dist/attribute-changes.js +25 -0
  4. package/dist/capabilities.d.ts +33 -1
  5. package/dist/capabilities.d.ts.map +1 -1
  6. package/dist/capabilities.js +71 -4
  7. package/dist/capture-stack.d.ts +16 -0
  8. package/dist/capture-stack.d.ts.map +1 -0
  9. package/dist/capture-stack.js +21 -0
  10. package/dist/class-serialization.d.ts +32 -0
  11. package/dist/class-serialization.d.ts.map +1 -1
  12. package/dist/class-serialization.js +37 -1
  13. package/dist/classify-error.d.ts +26 -3
  14. package/dist/classify-error.d.ts.map +1 -1
  15. package/dist/classify-error.js +109 -6
  16. package/dist/context-errors.d.ts +27 -0
  17. package/dist/context-errors.d.ts.map +1 -0
  18. package/dist/context-errors.js +101 -0
  19. package/dist/context-violation-error.d.ts +97 -0
  20. package/dist/context-violation-error.d.ts.map +1 -0
  21. package/dist/context-violation-error.js +149 -0
  22. package/dist/create-hook.d.ts +62 -4
  23. package/dist/create-hook.d.ts.map +1 -1
  24. package/dist/create-hook.js +4 -3
  25. package/dist/define-hook.d.ts.map +1 -1
  26. package/dist/define-hook.js +20 -5
  27. package/dist/describe-error.d.ts +70 -0
  28. package/dist/describe-error.d.ts.map +1 -0
  29. package/dist/describe-error.js +189 -0
  30. package/dist/encryption.d.ts +37 -3
  31. package/dist/encryption.d.ts.map +1 -1
  32. package/dist/encryption.js +97 -31
  33. package/dist/events-consumer.d.ts +147 -1
  34. package/dist/events-consumer.d.ts.map +1 -1
  35. package/dist/events-consumer.js +444 -43
  36. package/dist/flushable-stream.d.ts +65 -10
  37. package/dist/flushable-stream.d.ts.map +1 -1
  38. package/dist/flushable-stream.js +131 -18
  39. package/dist/global.d.ts +37 -1
  40. package/dist/global.d.ts.map +1 -1
  41. package/dist/global.js +21 -3
  42. package/dist/index.d.ts +1 -0
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +2 -1
  45. package/dist/log-format.d.ts +25 -0
  46. package/dist/log-format.d.ts.map +1 -0
  47. package/dist/log-format.js +250 -0
  48. package/dist/logger.d.ts +29 -30
  49. package/dist/logger.d.ts.map +1 -1
  50. package/dist/logger.js +82 -32
  51. package/dist/private.d.ts +246 -8
  52. package/dist/private.d.ts.map +1 -1
  53. package/dist/private.js +345 -9
  54. package/dist/replay-payload-cache.d.ts +68 -0
  55. package/dist/replay-payload-cache.d.ts.map +1 -0
  56. package/dist/replay-payload-cache.js +160 -0
  57. package/dist/runtime/compute-instance.d.ts +12 -0
  58. package/dist/runtime/compute-instance.d.ts.map +1 -0
  59. package/dist/runtime/compute-instance.js +13 -0
  60. package/dist/runtime/constants.d.ts +251 -0
  61. package/dist/runtime/constants.d.ts.map +1 -1
  62. package/dist/runtime/constants.js +425 -16
  63. package/dist/runtime/count-step-started-events.d.ts +52 -0
  64. package/dist/runtime/count-step-started-events.d.ts.map +1 -0
  65. package/dist/runtime/count-step-started-events.js +72 -0
  66. package/dist/runtime/deployment-guard.d.ts +99 -0
  67. package/dist/runtime/deployment-guard.d.ts.map +1 -0
  68. package/dist/runtime/deployment-guard.js +154 -0
  69. package/dist/runtime/get-port-lazy.d.ts +25 -0
  70. package/dist/runtime/get-port-lazy.d.ts.map +1 -0
  71. package/dist/runtime/get-port-lazy.js +92 -0
  72. package/dist/runtime/get-world-lazy.d.ts +23 -0
  73. package/dist/runtime/get-world-lazy.d.ts.map +1 -0
  74. package/dist/runtime/get-world-lazy.js +46 -0
  75. package/dist/runtime/helpers.d.ts +327 -10
  76. package/dist/runtime/helpers.d.ts.map +1 -1
  77. package/dist/runtime/helpers.js +586 -40
  78. package/dist/runtime/quickjs-assets.generated.d.ts +14 -0
  79. package/dist/runtime/quickjs-assets.generated.d.ts.map +1 -0
  80. package/dist/runtime/quickjs-assets.generated.js +30 -0
  81. package/dist/runtime/quickjs-entrypoint.d.ts +124 -0
  82. package/dist/runtime/quickjs-entrypoint.d.ts.map +1 -0
  83. package/dist/runtime/quickjs-entrypoint.js +1437 -0
  84. package/dist/runtime/quickjs-runtime.d.ts +228 -0
  85. package/dist/runtime/quickjs-runtime.d.ts.map +1 -0
  86. package/dist/runtime/quickjs-runtime.js +2372 -0
  87. package/dist/runtime/quickjs-serde.d.ts +107 -0
  88. package/dist/runtime/quickjs-serde.d.ts.map +1 -0
  89. package/dist/runtime/quickjs-serde.js +2098 -0
  90. package/dist/runtime/replay-budget.d.ts +89 -0
  91. package/dist/runtime/replay-budget.d.ts.map +1 -0
  92. package/dist/runtime/replay-budget.js +139 -0
  93. package/dist/runtime/replay-recovery-reporter.d.ts +36 -0
  94. package/dist/runtime/replay-recovery-reporter.d.ts.map +1 -0
  95. package/dist/runtime/replay-recovery-reporter.js +64 -0
  96. package/dist/runtime/resume-hook.d.ts +27 -4
  97. package/dist/runtime/resume-hook.d.ts.map +1 -1
  98. package/dist/runtime/resume-hook.js +452 -76
  99. package/dist/runtime/run-id-time.d.ts +19 -0
  100. package/dist/runtime/run-id-time.d.ts.map +1 -0
  101. package/dist/runtime/run-id-time.js +42 -0
  102. package/dist/runtime/run.d.ts +8 -2
  103. package/dist/runtime/run.d.ts.map +1 -1
  104. package/dist/runtime/run.js +62 -15
  105. package/dist/runtime/runs.d.ts +54 -3
  106. package/dist/runtime/runs.d.ts.map +1 -1
  107. package/dist/runtime/runs.js +119 -13
  108. package/dist/runtime/start.d.ts +70 -1
  109. package/dist/runtime/start.d.ts.map +1 -1
  110. package/dist/runtime/start.js +313 -60
  111. package/dist/runtime/step-executor.d.ts +177 -0
  112. package/dist/runtime/step-executor.d.ts.map +1 -0
  113. package/dist/runtime/step-executor.js +946 -0
  114. package/dist/runtime/step-latency.d.ts +197 -0
  115. package/dist/runtime/step-latency.d.ts.map +1 -0
  116. package/dist/runtime/step-latency.js +207 -0
  117. package/dist/runtime/step-ownership.d.ts +72 -0
  118. package/dist/runtime/step-ownership.d.ts.map +1 -0
  119. package/dist/runtime/step-ownership.js +114 -0
  120. package/dist/runtime/step-single-flight.d.ts +12 -0
  121. package/dist/runtime/step-single-flight.d.ts.map +1 -0
  122. package/dist/runtime/step-single-flight.js +69 -0
  123. package/dist/runtime/suspension-handler.d.ts +109 -7
  124. package/dist/runtime/suspension-handler.d.ts.map +1 -1
  125. package/dist/runtime/suspension-handler.js +486 -140
  126. package/dist/runtime/vm-mode.d.ts +44 -0
  127. package/dist/runtime/vm-mode.d.ts.map +1 -0
  128. package/dist/runtime/vm-mode.js +62 -0
  129. package/dist/runtime/vm-serde-bundle.generated.d.ts +14 -0
  130. package/dist/runtime/vm-serde-bundle.generated.d.ts.map +1 -0
  131. package/dist/runtime/vm-serde-bundle.generated.js +16 -0
  132. package/dist/runtime/wait-continuation.d.ts +84 -0
  133. package/dist/runtime/wait-continuation.d.ts.map +1 -0
  134. package/dist/runtime/wait-continuation.js +105 -0
  135. package/dist/runtime/wait-until.d.ts +18 -0
  136. package/dist/runtime/wait-until.d.ts.map +1 -0
  137. package/dist/runtime/wait-until.js +42 -0
  138. package/dist/runtime/world-compatibility.d.ts +20 -0
  139. package/dist/runtime/world-compatibility.d.ts.map +1 -0
  140. package/dist/runtime/world-compatibility.js +32 -0
  141. package/dist/runtime/world-init.d.ts +50 -0
  142. package/dist/runtime/world-init.d.ts.map +1 -0
  143. package/dist/runtime/world-init.js +50 -0
  144. package/dist/runtime/world.d.ts +14 -2
  145. package/dist/runtime/world.d.ts.map +1 -1
  146. package/dist/runtime/world.js +101 -26
  147. package/dist/runtime.d.ts +17 -12
  148. package/dist/runtime.d.ts.map +1 -1
  149. package/dist/runtime.js +3135 -328
  150. package/dist/schemas.d.ts +1 -1
  151. package/dist/schemas.d.ts.map +1 -1
  152. package/dist/schemas.js +1 -1
  153. package/dist/sealed-box.d.ts +167 -0
  154. package/dist/sealed-box.d.ts.map +1 -0
  155. package/dist/sealed-box.js +571 -0
  156. package/dist/serialization/client.d.ts +17 -0
  157. package/dist/serialization/client.d.ts.map +1 -0
  158. package/dist/serialization/client.js +48 -0
  159. package/dist/serialization/codec-devalue-vm.d.ts +16 -0
  160. package/dist/serialization/codec-devalue-vm.d.ts.map +1 -0
  161. package/dist/serialization/codec-devalue-vm.js +148 -0
  162. package/dist/serialization/codec-devalue.d.ts +14 -0
  163. package/dist/serialization/codec-devalue.d.ts.map +1 -0
  164. package/dist/serialization/codec-devalue.js +105 -0
  165. package/dist/serialization/codec.d.ts +125 -0
  166. package/dist/serialization/codec.d.ts.map +1 -0
  167. package/dist/serialization/codec.js +17 -0
  168. package/dist/serialization/compression.d.ts +104 -0
  169. package/dist/serialization/compression.d.ts.map +1 -0
  170. package/dist/serialization/compression.js +260 -0
  171. package/dist/serialization/encryption.d.ts +134 -0
  172. package/dist/serialization/encryption.d.ts.map +1 -0
  173. package/dist/serialization/encryption.js +186 -0
  174. package/dist/serialization/errors.d.ts +34 -0
  175. package/dist/serialization/errors.d.ts.map +1 -0
  176. package/dist/serialization/errors.js +59 -0
  177. package/dist/serialization/format.d.ts +60 -0
  178. package/dist/serialization/format.d.ts.map +1 -0
  179. package/dist/serialization/format.js +97 -0
  180. package/dist/serialization/hardened.d.ts +155 -0
  181. package/dist/serialization/hardened.d.ts.map +1 -0
  182. package/dist/serialization/hardened.js +523 -0
  183. package/dist/serialization/index.d.ts +20 -0
  184. package/dist/serialization/index.d.ts.map +1 -0
  185. package/dist/serialization/index.js +22 -0
  186. package/dist/serialization/reducers/class-vm.d.ts +20 -0
  187. package/dist/serialization/reducers/class-vm.d.ts.map +1 -0
  188. package/dist/serialization/reducers/class-vm.js +77 -0
  189. package/dist/serialization/reducers/class.d.ts +11 -0
  190. package/dist/serialization/reducers/class.d.ts.map +1 -0
  191. package/dist/serialization/reducers/class.js +73 -0
  192. package/dist/serialization/reducers/common-vm.d.ts +15 -0
  193. package/dist/serialization/reducers/common-vm.d.ts.map +1 -0
  194. package/dist/serialization/reducers/common-vm.js +579 -0
  195. package/dist/serialization/reducers/common.d.ts +16 -0
  196. package/dist/serialization/reducers/common.d.ts.map +1 -0
  197. package/dist/serialization/reducers/common.js +478 -0
  198. package/dist/serialization/reducers/step-function-vm.d.ts +44 -0
  199. package/dist/serialization/reducers/step-function-vm.d.ts.map +1 -0
  200. package/dist/serialization/reducers/step-function-vm.js +97 -0
  201. package/dist/serialization/reducers/step-function.d.ts +35 -0
  202. package/dist/serialization/reducers/step-function.d.ts.map +1 -0
  203. package/dist/serialization/reducers/step-function.js +104 -0
  204. package/dist/serialization/step.d.ts +17 -0
  205. package/dist/serialization/step.d.ts.map +1 -0
  206. package/dist/serialization/step.js +48 -0
  207. package/dist/serialization/types.d.ts +273 -0
  208. package/dist/serialization/types.d.ts.map +1 -0
  209. package/dist/serialization/types.js +35 -0
  210. package/dist/serialization/workflow-vm.d.ts +29 -0
  211. package/dist/serialization/workflow-vm.d.ts.map +1 -0
  212. package/dist/serialization/workflow-vm.js +71 -0
  213. package/dist/serialization/workflow.d.ts +29 -0
  214. package/dist/serialization/workflow.d.ts.map +1 -0
  215. package/dist/serialization/workflow.js +54 -0
  216. package/dist/serialization-format.d.ts +60 -4
  217. package/dist/serialization-format.d.ts.map +1 -1
  218. package/dist/serialization-format.js +276 -56
  219. package/dist/serialization.d.ts +374 -221
  220. package/dist/serialization.d.ts.map +1 -1
  221. package/dist/serialization.js +2300 -783
  222. package/dist/set-attributes.d.ts +13 -0
  223. package/dist/set-attributes.d.ts.map +1 -0
  224. package/dist/set-attributes.js +60 -0
  225. package/dist/sleep.d.ts.map +1 -1
  226. package/dist/sleep.js +3 -2
  227. package/dist/source-map.d.ts +25 -0
  228. package/dist/source-map.d.ts.map +1 -1
  229. package/dist/source-map.js +148 -10
  230. package/dist/step/context-storage.d.ts +61 -2
  231. package/dist/step/context-storage.d.ts.map +1 -1
  232. package/dist/step/context-storage.js +7 -5
  233. package/dist/step/get-closure-vars.d.ts.map +1 -1
  234. package/dist/step/get-closure-vars.js +3 -2
  235. package/dist/step/get-step-metadata.d.ts.map +1 -1
  236. package/dist/step/get-step-metadata.js +3 -2
  237. package/dist/step/get-workflow-metadata.d.ts.map +1 -1
  238. package/dist/step/get-workflow-metadata.js +3 -2
  239. package/dist/step/writable-stream.d.ts.map +1 -1
  240. package/dist/step/writable-stream.js +71 -7
  241. package/dist/step.d.ts.map +1 -1
  242. package/dist/step.js +225 -29
  243. package/dist/symbols.d.ts +54 -0
  244. package/dist/symbols.d.ts.map +1 -1
  245. package/dist/symbols.js +55 -1
  246. package/dist/telemetry/semantic-conventions.d.ts +265 -2
  247. package/dist/telemetry/semantic-conventions.d.ts.map +1 -1
  248. package/dist/telemetry/semantic-conventions.js +190 -1
  249. package/dist/telemetry.d.ts +73 -0
  250. package/dist/telemetry.d.ts.map +1 -1
  251. package/dist/telemetry.js +153 -16
  252. package/dist/types.d.ts +6 -0
  253. package/dist/types.d.ts.map +1 -1
  254. package/dist/types.js +23 -1
  255. package/dist/util.d.ts +16 -6
  256. package/dist/util.d.ts.map +1 -1
  257. package/dist/util.js +25 -16
  258. package/dist/version.d.ts +1 -1
  259. package/dist/version.d.ts.map +1 -1
  260. package/dist/version.js +2 -2
  261. package/dist/vm/index.d.ts.map +1 -1
  262. package/dist/vm/index.js +85 -14
  263. package/dist/vm/script-cache.d.ts +28 -0
  264. package/dist/vm/script-cache.d.ts.map +1 -0
  265. package/dist/vm/script-cache.js +140 -0
  266. package/dist/workflow/abort-controller.d.ts +65 -0
  267. package/dist/workflow/abort-controller.d.ts.map +1 -0
  268. package/dist/workflow/abort-controller.js +312 -0
  269. package/dist/workflow/attribute-dispatcher.d.ts +6 -0
  270. package/dist/workflow/attribute-dispatcher.d.ts.map +1 -0
  271. package/dist/workflow/attribute-dispatcher.js +48 -0
  272. package/dist/workflow/create-hook.d.ts.map +1 -1
  273. package/dist/workflow/create-hook.js +25 -3
  274. package/dist/workflow/define-hook.d.ts +1 -1
  275. package/dist/workflow/define-hook.d.ts.map +1 -1
  276. package/dist/workflow/define-hook.js +8 -4
  277. package/dist/workflow/get-workflow-metadata.d.ts.map +1 -1
  278. package/dist/workflow/get-workflow-metadata.js +14 -3
  279. package/dist/workflow/hook.d.ts.map +1 -1
  280. package/dist/workflow/hook.js +302 -36
  281. package/dist/workflow/index.d.ts +1 -0
  282. package/dist/workflow/index.d.ts.map +1 -1
  283. package/dist/workflow/index.js +5 -3
  284. package/dist/workflow/set-attributes.d.ts +68 -0
  285. package/dist/workflow/set-attributes.d.ts.map +1 -0
  286. package/dist/workflow/set-attributes.js +60 -0
  287. package/dist/workflow/sleep.d.ts.map +1 -1
  288. package/dist/workflow/sleep.js +57 -8
  289. package/dist/workflow/world-init-stub.d.ts +15 -0
  290. package/dist/workflow/world-init-stub.d.ts.map +1 -0
  291. package/dist/workflow/world-init-stub.js +15 -0
  292. package/dist/workflow.d.ts +79 -3
  293. package/dist/workflow.d.ts.map +1 -1
  294. package/dist/workflow.js +831 -553
  295. package/docs/api-reference/create-hook.mdx +79 -0
  296. package/docs/api-reference/create-webhook.mdx +1 -0
  297. package/docs/api-reference/define-hook.mdx +26 -24
  298. package/docs/api-reference/fatal-error.mdx +29 -7
  299. package/docs/api-reference/fetch.mdx +8 -4
  300. package/docs/api-reference/index.mdx +3 -0
  301. package/docs/api-reference/set-attributes.mdx +61 -0
  302. package/docs/api-reference/sleep.mdx +1 -1
  303. package/docs/foundations/cancellation.mdx +459 -0
  304. package/docs/foundations/errors-and-retries.mdx +7 -3
  305. package/docs/foundations/hooks.mdx +29 -0
  306. package/docs/foundations/idempotency.mdx +243 -11
  307. package/docs/foundations/index.mdx +1 -23
  308. package/docs/foundations/meta.json +3 -1
  309. package/docs/foundations/serialization.mdx +77 -41
  310. package/docs/foundations/starting-workflows.mdx +79 -2
  311. package/docs/foundations/streaming.mdx +14 -23
  312. package/docs/foundations/versioning.mdx +263 -0
  313. package/docs/how-it-works/cancellation.mdx +287 -0
  314. package/docs/how-it-works/code-transform.mdx +21 -17
  315. package/docs/how-it-works/encryption.mdx +5 -5
  316. package/docs/how-it-works/event-sourcing.mdx +17 -9
  317. package/docs/how-it-works/framework-integrations.mdx +96 -337
  318. package/docs/how-it-works/meta.json +2 -1
  319. package/package.json +31 -13
  320. package/dist/runtime/step-handler.d.ts +0 -2
  321. package/dist/runtime/step-handler.d.ts.map +0 -1
  322. package/dist/runtime/step-handler.js +0 -678
package/dist/runtime.js CHANGED
@@ -1,69 +1,418 @@
1
- import { EntityConflictError, RUN_ERROR_CODES, RunExpiredError, WorkflowRuntimeError, } from '@workflow/errors';
2
- import { parseWorkflowName } from '@workflow/utils/parse-name';
3
- import { SPEC_VERSION_CURRENT, WorkflowInvokePayloadSchema, } from '@workflow/world';
4
- import { classifyRunError } from './classify-error.js';
5
- import { importKey } from './encryption.js';
1
+ import assert from 'node:assert/strict';
2
+ import { types } from 'node:util';
3
+ import { CorruptedEventLogError, EntityConflictError, FatalError, HookNotFoundError, MaxEventsExceededError, PreconditionFailedError, ReplayDivergenceError, RUN_ERROR_CODES, RunExpiredError, WorkflowRuntimeError, } from '@workflow/errors';
4
+ import { once, setWorkflowBasePath } from '@workflow/utils';
5
+ import { parseWorkflowName, workflowDisplayName, } from '@workflow/utils/parse-name';
6
+ import { getQueueTopicPrefix, isLegacySpecVersion, isTerminalRunEventType, ROOT_RUN_ID_ATTRIBUTE, resolveQueueNamespace, SPEC_VERSION_CURRENT, SPEC_VERSION_SUPPORTS_COMPRESSION, WorkflowInvokePayloadSchema, } from '@workflow/world';
7
+ import ms from 'ms';
8
+ import { decodeTime } from 'ulid';
9
+ import { classifyRunError, isRetryableWorldError, isWorldContractError, } from './classify-error.js';
10
+ import { describeError } from './describe-error.js';
6
11
  import { WorkflowSuspension } from './global.js';
7
12
  import { runtimeLogger } from './logger.js';
8
- import { MAX_QUEUE_DELIVERIES, REPLAY_TIMEOUT_MAX_RETRIES, REPLAY_TIMEOUT_MS, } from './runtime/constants.js';
9
- import { getAllWorkflowRunEvents, getQueueOverhead, handleHealthCheckMessage, parseHealthCheckPayload, withHealthCheck, } from './runtime/helpers.js';
13
+ import { getStepFunction } from './private.js';
14
+ import { ReplayPayloadCache } from './replay-payload-cache.js';
15
+ import { COMPUTE_INSTANCE_ID } from './runtime/compute-instance.js';
16
+ import { getMaxEventsOverride, getMaxQueueDeliveries, getPreconditionMaxInProcessRestarts, getPreconditionMaxReinvocations, getPreconditionReinvokeDelaySeconds, getReplayDivergenceMaxRetries, isInlineOwnershipEnabled, isTurboEnabled, isVmRetentionEnabled, } from './runtime/constants.js';
17
+ import { countStepStartedEvents } from './runtime/count-step-started-events.js';
18
+ import { guardDeploymentAffinity, } from './runtime/deployment-guard.js';
19
+ import { appendUniqueEvents, getQueueOverhead, getWorkflowQueueName, handleHealthCheckMessage, insertEventByEventId, isPreconditionGuardEnabled, isSlotGapCheckEnabled, loadWorkflowRunEvents, memoizeEncryptionKey, mergeReportedEvents, parseHealthCheckPayload, preconditionEventDelta, preconditionSnapshotParams, queueMessage, settleEventSlotGap, withHealthCheck, } from './runtime/helpers.js';
20
+ import { handleReplayBudgetExhausted, ReplayBudget, } from './runtime/replay-budget.js';
21
+ import { ReplayRecoveryReporter } from './runtime/replay-recovery-reporter.js';
22
+ import { runIdCreatedAt } from './runtime/run-id-time.js';
23
+ import { DEFAULT_STEP_MAX_RETRIES, executeStep, } from './runtime/step-executor.js';
24
+ import { computeStepLatencyTracking } from './runtime/step-latency.js';
25
+ import { backstopIdempotencyKey, hasPendingStepOwnedByMessage, isStepOwnershipActive, stepLeaseRemainingSeconds, } from './runtime/step-ownership.js';
26
+ import { runStepSingleFlight } from './runtime/step-single-flight.js';
10
27
  import { handleSuspension } from './runtime/suspension-handler.js';
28
+ import { useQuickJSVm } from './runtime/vm-mode.js';
29
+ import { getWaitContinuationDispatch } from './runtime/wait-continuation.js';
11
30
  import { getWorld, getWorldHandlers, } from './runtime/world.js';
31
+ import { dehydrateRunError } from './serialization.js';
12
32
  import { remapErrorStack } from './source-map.js';
13
33
  import * as Attribute from './telemetry/semantic-conventions.js';
14
- import { linkToCurrentContext, trace, withTraceContext, withWorkflowBaggage, } from './telemetry.js';
34
+ import { buildInvocationSpanLinks, getNextTraceCarrier, getSpanKind, getWorkflowTraceMode, isUsableTraceCarrier, trace, withTraceContext, withWorkflowBaggage, } from './telemetry.js';
15
35
  import { getErrorName, getErrorStack, normalizeUnknownError } from './types.js';
16
36
  import { buildWorkflowSuspensionMessage } from './util.js';
17
- import { runWorkflow } from './workflow.js';
37
+ import { replayWorkflow, resumeWorkflow, } from './workflow.js';
18
38
  export { WorkflowSuspension } from './global.js';
19
39
  export { healthCheck, } from './runtime/helpers.js';
20
40
  export { getHookByToken, resumeHook, resumeWebhook, } from './runtime/resume-hook.js';
21
41
  export { getRun, Run, } from './runtime/run.js';
22
- export { cancelRun, listStreams, readStream, recreateRunFromExisting, reenqueueRun, wakeUpRun, } from './runtime/runs.js';
42
+ export { cancelRun, cancelRuns, listStreams, readStream, recreateRunFromExisting, reenqueueRun, wakeUpRun, } from './runtime/runs.js';
23
43
  export { start, } from './runtime/start.js';
24
- export { stepEntrypoint } from './runtime/step-handler.js';
25
- export { createWorld, getWorld, getWorldHandlers, setWorld, } from './runtime/world.js';
44
+ export { createWorld, createWorldFromModule, getWorld, getWorldHandlers, setWorld, } from './runtime/world.js';
26
45
  /**
27
- * Function that creates a single route which handles any workflow execution
28
- * request and routes to the appropriate workflow function.
46
+ * Apply the optional client-side event-limit override.
47
+ * `WORKFLOW_MAX_EVENTS_OVERRIDE`, when set to a positive integer, clamps the
48
+ * server-supplied per-run event ceiling to a smaller value so enforcement can
49
+ * be exercised without a server-side change. Clamp-down only: it never raises
50
+ * the server's limit, and it takes effect even when the server returns none.
51
+ * Unset ⇒ server value passes through unchanged.
52
+ */
53
+ function clampMaxEvents(serverValue) {
54
+ const override = getMaxEventsOverride();
55
+ if (override === undefined)
56
+ return serverValue;
57
+ return serverValue === undefined ? override : Math.min(serverValue, override);
58
+ }
59
+ /**
60
+ * Refuse a queue delivery whose run was created in a different environment than
61
+ * this deployment runs in.
62
+ *
63
+ * `start()` performs two writes that must land in the same tenant: the
64
+ * `run_created` event, attributed to whatever environment the *caller*
65
+ * authenticates as, and the queue message, pinned to a *deployment*. A
66
+ * misconfigured caller can split them — writing the run to one environment
67
+ * while addressing the message to a deployment in another. The consumer then
68
+ * finds no run under its own tenant and the backend's resilient start
69
+ * (`run_started` creates the run when `run_created` was never seen) mints a
70
+ * SECOND copy of the same run id in this environment. Both copies are real: the
71
+ * creator's sits pending forever, this one executes, and every subsequent
72
+ * cross-tenant queue ack fails to find its message.
73
+ *
74
+ * Nothing external is needed to catch this: the creator's environment rides the
75
+ * message in `runInput.environment` and this process already knows its own. So
76
+ * compare them and stop BEFORE `run_started` — the write that would create the
77
+ * fork. Refusing after it would be too late.
78
+ *
79
+ * Returns `true` when the caller must abandon the delivery. Skipped whenever
80
+ * either side is unknown, which keeps every existing setup on its current
81
+ * behavior: worlds with no environment dimension (`world-local`,
82
+ * `world-postgres`) don't implement `getEnvironment`, and runs started by an
83
+ * older SDK carry no `environment` field.
84
+ */
85
+ function refuseCrossEnvironmentDelivery({ world, runInput, runId, runLogger, }) {
86
+ const creatorEnvironment = runInput?.environment;
87
+ if (!creatorEnvironment)
88
+ return false;
89
+ const currentEnvironment = world.getEnvironment?.();
90
+ if (!currentEnvironment || currentEnvironment === creatorEnvironment) {
91
+ return false;
92
+ }
93
+ runLogger.error(`Refusing to run this workflow: it was created in the "${creatorEnvironment}" ` +
94
+ `environment but this deployment runs in "${currentEnvironment}". ` +
95
+ 'Executing it here would create a second copy of the same run id in ' +
96
+ 'both environments — one pending forever, one running — so the queue ' +
97
+ 'message is being discarded without executing and without retrying. ' +
98
+ 'The client that called start() wrote the run to its own environment ' +
99
+ 'but addressed the queue message to a deployment in another one. Check ' +
100
+ 'that the environment that client authenticates as (WORKFLOW_VERCEL_ENV ' +
101
+ "for CLI and CI clients, or the OIDC token's environment inside a " +
102
+ 'deployment) matches the environment of the deployment it targets. The ' +
103
+ `run it created is still pending in "${creatorEnvironment}" and will ` +
104
+ 'not run.', {
105
+ workflowRunId: runId,
106
+ creatorEnvironment,
107
+ currentEnvironment,
108
+ pinnedDeploymentId: runInput?.deploymentId,
109
+ });
110
+ return true;
111
+ }
112
+ /**
113
+ * Log when a `start()`-enqueued message pinned to one deployment is delivered
114
+ * to a different one.
115
+ *
116
+ * A first-delivery message carries `runInput.deploymentId` — the deployment
117
+ * `start()` addressed it to — so comparing that against this handler's own
118
+ * deployment detects mis-delivery directly. This is a DIAGNOSTIC, not a gate:
119
+ * it warns and lets the invocation proceed, deliberately.
29
120
  *
30
- * @param workflowCode - The workflow bundle code containing all the workflow
31
- * functions at the top level.
32
- * @returns A function that can be used as a Vercel API route.
121
+ * Why this one only warns while its environment sibling above refuses: a
122
+ * differing deployment id is not by itself evidence of the fork we care about.
123
+ * The environment pair is exact two named environments that disagree — and it
124
+ * is the dimension the run's tenant is keyed on. Deployment ids disagree for
125
+ * benign reasons too: `world-local` derives its id from the installed package
126
+ * version (`dpl_local@<version>`), so upgrading the SDK mid-run changes it with
127
+ * nothing wrong. Refusing on that signal would strand correct runs, and
128
+ * refusing before `run_started` leaves no server-side record to explain why.
129
+ * Anyone tempted to promote this to a hard failure has to handle that first.
130
+ *
131
+ * Skipped unless BOTH ids are known — `getDeploymentId()` throws in worlds that
132
+ * require a deployment and have none, and a re-enqueued message carries no
133
+ * `runInput` at all.
33
134
  */
34
- export function workflowEntrypoint(workflowCode) {
35
- const handler = (worldHandlers) => worldHandlers.createQueueHandler('__wkf_workflow_', async (message_, metadata) => {
135
+ async function warnOnDeploymentPinningMismatch({ world, runInput, runId, runLogger, }) {
136
+ const pinnedDeploymentId = runInput?.deploymentId;
137
+ if (!pinnedDeploymentId)
138
+ return;
139
+ let currentDeploymentId;
140
+ try {
141
+ currentDeploymentId = await world.getDeploymentId();
142
+ }
143
+ catch {
144
+ // Worlds that require a deployment id throw when there isn't one. That is
145
+ // not a mismatch — there is simply nothing to compare against.
146
+ return;
147
+ }
148
+ if (!currentDeploymentId || currentDeploymentId === pinnedDeploymentId) {
149
+ return;
150
+ }
151
+ runLogger.error('Queue message was delivered to a deployment it was not pinned to. ' +
152
+ 'The run was created targeting a different deployment, so this ' +
153
+ 'invocation may be replaying against code the run was not started on. ' +
154
+ 'Continuing — this is expected if the Workflow SDK version changed ' +
155
+ 'mid-run in local development, where the deployment id is derived from ' +
156
+ 'that version.', {
157
+ workflowRunId: runId,
158
+ pinnedDeploymentId,
159
+ currentDeploymentId,
160
+ });
161
+ }
162
+ function getWorkflowSetupErrorCode(err) {
163
+ if (WorkflowRuntimeError.is(err)) {
164
+ return RUN_ERROR_CODES.RUNTIME_ERROR;
165
+ }
166
+ if (isWorldContractError(err)) {
167
+ return RUN_ERROR_CODES.WORLD_CONTRACT_ERROR;
168
+ }
169
+ return null;
170
+ }
171
+ async function recordFatalRunError({ world, workflowRun, runId, requestId, err, errorCode, logMessage, }) {
172
+ runtimeLogger.error(logMessage, {
173
+ workflowRunId: runId,
174
+ errorCode,
175
+ error: err instanceof Error ? err.message : String(err),
176
+ });
177
+ try {
178
+ const getEncryptionKey = memoizeEncryptionKey(world, workflowRun ?? runId);
179
+ await world.events.create(runId, {
180
+ eventType: 'run_failed',
181
+ specVersion: SPEC_VERSION_CURRENT,
182
+ eventData: {
183
+ error: await dehydrateRunError(err, runId, await getEncryptionKey(), globalThis, (workflowRun?.specVersion ?? 0) >= SPEC_VERSION_SUPPORTS_COMPRESSION),
184
+ errorCode,
185
+ },
186
+ }, { requestId });
187
+ }
188
+ catch (failErr) {
189
+ if (EntityConflictError.is(failErr) || RunExpiredError.is(failErr)) {
190
+ return;
191
+ }
192
+ if (isWorldContractError(failErr)) {
193
+ runtimeLogger.error('Fatal world contract error while recording workflow failure', {
194
+ workflowRunId: runId,
195
+ errorCode: RUN_ERROR_CODES.WORLD_CONTRACT_ERROR,
196
+ error: failErr instanceof Error ? failErr.message : String(failErr),
197
+ });
198
+ return;
199
+ }
200
+ throw failErr;
201
+ }
202
+ }
203
+ function hasRecordedTerminalRunEvent(events, runId) {
204
+ // Terminal run events are always last by construction (no event creation
205
+ // succeeds against a terminal run), but scan the full array for
206
+ // defense-in-depth: a World/backend ordering bug shouldn't make us miss an
207
+ // actual termination signal.
208
+ const terminalRunEvent = events.find((e) => e.runId === runId &&
209
+ (e.eventType === 'run_completed' ||
210
+ e.eventType === 'run_failed' ||
211
+ e.eventType === 'run_cancelled'));
212
+ if (!terminalRunEvent) {
213
+ return false;
214
+ }
215
+ runtimeLogger.debug('Run reached terminal event, exiting', {
216
+ workflowRunId: runId,
217
+ eventType: terminalRunEvent.eventType,
218
+ eventId: terminalRunEvent.eventId,
219
+ });
220
+ return true;
221
+ }
222
+ /** How many of `ids` are absent from `present`. */
223
+ function countMissingIds(ids, present) {
224
+ let missing = 0;
225
+ for (const id of ids) {
226
+ if (!present.has(id))
227
+ missing++;
228
+ }
229
+ return missing;
230
+ }
231
+ /**
232
+ * The lineage root of a loaded run: its `$rootRunId` attribute, or its own id
233
+ * when it is itself a root.
234
+ */
235
+ function rootRunIdFrom(attributes, runId) {
236
+ return attributes?.[ROOT_RUN_ID_ATTRIBUTE] ?? runId;
237
+ }
238
+ /**
239
+ * Whether the run has a hook and/or wait that an out-of-band writer could
240
+ * append an event for between an inline step's `step_completed` write and
241
+ * the next replay — namely an open hook (a `hook_created` not yet
242
+ * `hook_disposed`, which a webhook receiver can resolve with
243
+ * `hook_received`) or an open wait (a `wait_created` not yet
244
+ * `wait_completed`, which the wait timer can resolve with
245
+ * `wait_completed`).
246
+ *
247
+ * This gates VM retention, the inline-delta fast path, and turbo's forced
248
+ * optimistic start. A terminal-step delta can omit an event appended
249
+ * concurrently after that write. With no open hook or wait, only cancellation
250
+ * can do so, and observing it one replay late is safe because the next entity
251
+ * write is rejected.
252
+ *
253
+ * Step-body `attr_set` writes are NOT a concern: they land before the
254
+ * step's terminal write and are therefore already inside the returned
255
+ * delta.
256
+ */
257
+ function openHookAndWaitState(events) {
258
+ const hooks = new Set();
259
+ const waits = new Set();
260
+ for (const event of events) {
261
+ switch (event.eventType) {
262
+ case 'hook_created':
263
+ hooks.add(event.correlationId);
264
+ break;
265
+ case 'hook_disposed':
266
+ hooks.delete(event.correlationId);
267
+ break;
268
+ case 'wait_created':
269
+ waits.add(event.correlationId);
270
+ break;
271
+ case 'wait_completed':
272
+ waits.delete(event.correlationId);
273
+ break;
274
+ }
275
+ }
276
+ return { openHook: hooks.size > 0, openWait: waits.size > 0 };
277
+ }
278
+ function nextEventLogLoad(log) {
279
+ if (log.cursor === null) {
280
+ return { type: 'loadAll' };
281
+ }
282
+ return {
283
+ type: 'loadAfter',
284
+ events: log.events,
285
+ cursor: log.cursor,
286
+ };
287
+ }
288
+ function appendEventLog(log, appended) {
289
+ appendUniqueEvents(log.events, appended.events);
290
+ log.cursor = appended.cursor ?? log.cursor;
291
+ }
292
+ /**
293
+ * The whole retention predicate: keep the session only for a pure step
294
+ * boundary (every suspension item is a step — any other item type, present
295
+ * or future, is unretainable by default) whose new step inputs serialized
296
+ * without executing workflow code, with no out-of-band continuation source:
297
+ * attributes require replay; hooks and waits can wake another invocation.
298
+ * `WORKFLOW_RETAINED_VM=0` disables retention entirely.
299
+ *
300
+ * The open hook/wait scan is O(events), so it is taken through a lazy getter
301
+ * and consulted last, after every cheap check has passed.
302
+ *
303
+ * INVARIANT this predicate leans on: every suspension signaler that does NOT
304
+ * carry the step-consumer generation guard (sleep, hook, attribute — see
305
+ * `suspensionGeneration` in private.ts) must be unretainable here, either via
306
+ * a non-step queue item or the open hook/wait scan. A new signaler that
307
+ * satisfies neither would let a stale signal be accepted as a fresh
308
+ * suspension on a resumed session.
309
+ *
310
+ * Quiescence assumes workflow code stays inside the sandbox's determinism
311
+ * contract. Escaping to the host realm (e.g. recovering the host `Function`
312
+ * constructor from an exposed host class to schedule real timers) makes a
313
+ * workflow nondeterministic under ordinary replay too, and is not defended
314
+ * here.
315
+ */
316
+ function canRetainWorkflowSession(suspension, stepInputsSafe, openHookWait) {
317
+ if (!isVmRetentionEnabled() ||
318
+ !stepInputsSafe ||
319
+ suspension.steps.length === 0 ||
320
+ !suspension.steps.every((item) => item.type === 'step')) {
321
+ return false;
322
+ }
323
+ const { openHook, openWait } = openHookWait.value;
324
+ return !openHook && !openWait;
325
+ }
326
+ /**
327
+ * Maximum inline-execution duration for a single handler invocation.
328
+ *
329
+ * Order of precedence:
330
+ * 1. `WORKFLOW_V2_TIMEOUT_MS` env var
331
+ * 2. Tiered budget derived from `world.getRuntimeDeadline()`
332
+ * 3. Default of 2 minutes
333
+ */
334
+ async function getMaxInlineDurationMs(world, invocationStartTime) {
335
+ const rawEnvOverride = process.env.WORKFLOW_V2_TIMEOUT_MS;
336
+ if (rawEnvOverride !== undefined && rawEnvOverride !== '') {
337
+ const parsed = Number(rawEnvOverride);
338
+ if (Number.isFinite(parsed) && parsed > 0) {
339
+ return parsed;
340
+ }
341
+ }
342
+ const runtimeDeadline = await world.getRuntimeDeadline?.();
343
+ if (runtimeDeadline !== undefined) {
344
+ const deadlineMs = runtimeDeadline.getTime();
345
+ if (!Number.isNaN(deadlineMs)) {
346
+ const maxDurationMs = Math.floor(deadlineMs - invocationStartTime);
347
+ if (maxDurationMs >= ms('25m')) {
348
+ return ms('10m');
349
+ }
350
+ if (maxDurationMs >= ms('10m')) {
351
+ return ms('5m');
352
+ }
353
+ }
354
+ }
355
+ return ms('2m');
356
+ }
357
+ /**
358
+ * Creates a single route which handles workflow execution requests,
359
+ * executing steps inline when possible to reduce function invocations
360
+ * and queue overhead.
361
+ *
362
+ * The handler loops: replay workflow → execute step inline → replay → ...
363
+ * until the workflow completes, times out, or encounters non-step suspensions.
364
+ *
365
+ * @param workflowCode - The workflow bundle code containing all workflow functions
366
+ * @returns A function that can be used as a Vercel API route
367
+ */
368
+ export function workflowEntrypoint(workflowCode, options) {
369
+ setWorkflowBasePath(options?.basePath);
370
+ const namespace = resolveQueueNamespace(options?.namespace);
371
+ const workflowPrefix = getQueueTopicPrefix('workflow', namespace);
372
+ const handler = (worldHandlers) => worldHandlers.createQueueHandler(workflowPrefix, async (message_, metadata) => {
36
373
  // Check if this is a health check message
37
374
  // NOTE: Health check messages are intentionally unauthenticated for monitoring purposes.
38
375
  // They only write a simple status response to a stream and do not expose sensitive data.
39
376
  // The stream name includes a unique correlationId that must be known by the caller.
40
377
  const healthCheck = parseHealthCheckPayload(message_);
41
378
  if (healthCheck) {
42
- await handleHealthCheckMessage(healthCheck, 'workflow', worldHandlers.specVersion);
379
+ await handleHealthCheckMessage(healthCheck, worldHandlers.specVersion);
43
380
  return;
44
381
  }
45
- const { runId, traceCarrier: traceContext, requestedAt, runInput, } = WorkflowInvokePayloadSchema.parse(message_);
382
+ const { runId, traceCarrier: incomingTraceCarrier, requestedAt, stepId: incomingStepId, stepName: incomingStepName, replayDivergence, preconditionReinvocations, deploymentMismatchRetryCount, runInput, hookInput, } = WorkflowInvokePayloadSchema.parse(message_);
383
+ // `start()` always attaches a trace carrier, but
384
+ // serializeTraceCarrier() returns `{}` when no OTEL SDK is registered
385
+ // or no span is active — treat an empty carrier the same as an
386
+ // absent one so linked mode falls back to a fresh origin instead of
387
+ // forwarding a useless `{}` forever.
388
+ const traceContext = isUsableTraceCarrier(incomingTraceCarrier)
389
+ ? incomingTraceCarrier
390
+ : undefined;
46
391
  const { requestId } = metadata;
47
- // Extract the workflow name from the topic name
48
- const workflowName = metadata.queueName.slice('__wkf_workflow_'.length);
392
+ const workflowName = metadata.queueName.slice(workflowPrefix.length);
49
393
  // --- Max delivery check ---
50
394
  // Enforce max delivery limit before any infrastructure calls.
51
395
  // This prevents runaway workflows from consuming infinite queue deliveries.
52
- // At this point, we want to do the minimal amount of work (no fetching
53
- // of the workflow events, etc. We simply attempt to mark the run as failed
54
- // and if that fails, the message is still consumed but with adequate logging
55
- // that an error occurred preventing us from failing the run.
56
- if (metadata.attempt > MAX_QUEUE_DELIVERIES) {
57
- runtimeLogger.error(`Workflow handler exceeded max deliveries (${metadata.attempt}/${MAX_QUEUE_DELIVERIES})`, { workflowRunId: runId, workflowName, attempt: metadata.attempt });
396
+ // Scoped logger for this run attaches runId/workflowName to every
397
+ // log line and child loggers below, so callers don't repeat it.
398
+ const runLogger = runtimeLogger.forRun(runId, workflowName);
399
+ const maxQueueDeliveries = getMaxQueueDeliveries();
400
+ if (metadata.attempt > maxQueueDeliveries) {
401
+ const maxDeliveriesDescription = describeError(undefined, RUN_ERROR_CODES.MAX_DELIVERIES_EXCEEDED);
402
+ runLogger.error(`Workflow handler exceeded max deliveries (${metadata.attempt}/${maxQueueDeliveries})`, {
403
+ attempt: metadata.attempt,
404
+ errorCode: maxDeliveriesDescription.errorCode,
405
+ errorAttribution: maxDeliveriesDescription.attribution,
406
+ });
58
407
  try {
59
408
  const world = await getWorld();
409
+ const getEncryptionKey = memoizeEncryptionKey(world, runId);
410
+ const err = new FatalError(`Workflow exceeded maximum queue deliveries (${metadata.attempt}/${maxQueueDeliveries})`);
60
411
  await world.events.create(runId, {
61
412
  eventType: 'run_failed',
62
413
  specVersion: SPEC_VERSION_CURRENT,
63
414
  eventData: {
64
- error: {
65
- message: `Workflow exceeded maximum queue deliveries (${metadata.attempt}/${MAX_QUEUE_DELIVERIES})`,
66
- },
415
+ error: await dehydrateRunError(err, runId, await getEncryptionKey()),
67
416
  errorCode: RUN_ERROR_CODES.MAX_DELIVERIES_EXCEEDED,
68
417
  },
69
418
  }, { requestId });
@@ -73,97 +422,974 @@ export function workflowEntrypoint(workflowCode) {
73
422
  // Run already finished, consume the message silently
74
423
  return;
75
424
  }
76
- runtimeLogger.error(`Failed to mark run as failed after ${metadata.attempt} delivery attempts. ` +
425
+ runLogger.error(`Failed to mark run as failed after ${metadata.attempt} delivery attempts. ` +
77
426
  `A persistent error is preventing the run from being terminated. ` +
78
427
  `The run will remain in its current state until manually resolved. ` +
79
428
  `This is most likely due to a persistent outage of the workflow backend ` +
80
429
  `or a bug in the workflow runtime and should be reported to the Workflow team.`, {
81
- workflowRunId: runId,
82
- error: err instanceof Error ? err.message : String(err),
83
430
  attempt: metadata.attempt,
431
+ errorName: err instanceof Error ? err.name : 'UnknownError',
432
+ errorMessage: err instanceof Error ? err.message : String(err),
433
+ errorStack: err instanceof Error ? err.stack : undefined,
84
434
  });
85
435
  }
86
436
  return;
87
437
  }
88
- const spanLinks = await linkToCurrentContext();
89
- // --- Replay timeout guard ---
90
- // If the replay takes longer than the timeout, fail the run and exit.
91
- // This must be lower than the function's maxDuration to ensure
92
- // the failure is recorded before the platform kills the function.
93
- let replayTimeout;
94
- if (process.env.VERCEL_URL !== undefined) {
95
- replayTimeout = setTimeout(async () => {
96
- runtimeLogger.error('Workflow replay exceeded timeout', {
97
- workflowRunId: runId,
98
- timeoutMs: REPLAY_TIMEOUT_MS,
99
- attempt: metadata.attempt,
100
- maxRetries: REPLAY_TIMEOUT_MAX_RETRIES,
101
- });
102
- // Allow a few retries before permanently failing the run.
103
- // On early attempts, just exit so the queue retries the message.
104
- if (metadata.attempt <= REPLAY_TIMEOUT_MAX_RETRIES) {
105
- process.exit(1);
106
- }
107
- try {
108
- const world = await getWorld();
109
- await world.events.create(runId, {
110
- eventType: 'run_failed',
111
- specVersion: SPEC_VERSION_CURRENT,
112
- eventData: {
113
- error: {
114
- message: `Workflow replay exceeded maximum duration (${REPLAY_TIMEOUT_MS / 1000}s) after ${metadata.attempt} attempts`,
115
- },
116
- errorCode: RUN_ERROR_CODES.REPLAY_TIMEOUT,
117
- },
118
- }, { requestId });
119
- }
120
- catch {
121
- // Best effort — process exits regardless
122
- }
123
- // Note that this also prevents the runtime from acking the queue message,
124
- // so the queue will call back once, after which a 410 will get it to exit early.
125
- process.exit(1);
126
- }, REPLAY_TIMEOUT_MS);
127
- replayTimeout.unref();
128
- }
129
- // Invoke user workflow within the propagated trace context and baggage
130
- return await withTraceContext(traceContext, async () => {
131
- // Set workflow context as baggage for automatic propagation
438
+ // --- Trace correlation mode ---
439
+ // 'linked' (default): the workflow.execute span below stays a CHILD
440
+ // of the local delivery (flow-route) context, so one invocation
441
+ // route handler, workflow replay, inline steps, event writes is a
442
+ // single bounded trace. The run-origin context travels as a span
443
+ // LINK (not a parent), and re-enqueues forward the original carrier
444
+ // unchanged, so a (potentially hours-long) run is never stitched
445
+ // into one giant trace across invocations.
446
+ // 'continuous': legacy behavior the restored run-origin context
447
+ // becomes the parent of this invocation's spans.
448
+ const traceMode = getWorkflowTraceMode();
449
+ // Trace carrier to attach to messages this invocation enqueues —
450
+ // see getNextTraceCarrier for the linked/continuous semantics.
451
+ const nextTraceCarrier = () => getNextTraceCarrier(traceMode, traceContext);
452
+ // Span links to the incoming delivery context and (in linked mode)
453
+ // the run-origin context from the trace carrier.
454
+ const spanLinks = await buildInvocationSpanLinks(traceMode, traceContext);
455
+ // The replay budget covers orchestration work between steps, not inline
456
+ // step bodies. It is checked between loop iterations; step bodies use
457
+ // the platform timeout and NO_INLINE_REPLAY_AFTER_MS guard instead.
458
+ const replayBudget = new ReplayBudget();
459
+ // In linked mode the run-origin context is NOT restored as the
460
+ // active (parent) context — passing `undefined` makes
461
+ // withTraceContext a passthrough, so the workflow.execute span below
462
+ // stays a child of the local delivery (flow-route) context and the
463
+ // run-origin travels as a span link instead.
464
+ const parentTraceCarrier = traceMode === 'continuous' ? traceContext : undefined;
465
+ // Queue-delivered invocation: CONSUMER kind, matching the
466
+ // queue-delivered step.execute span.
467
+ const spanKind = await getSpanKind('CONSUMER');
468
+ return await withTraceContext(parentTraceCarrier, async () => {
132
469
  return await withWorkflowBaggage({ workflowRunId: runId, workflowName }, async () => {
133
- const world = await getWorld();
134
- return trace(`WORKFLOW ${workflowName}`, { links: spanLinks }, async (span) => {
470
+ const world = await trace('workflow.route.get_world', async () => getWorld());
471
+ // Both checks below look at `runInput`, so both are no-ops on a
472
+ // re-enqueued message (which carries none) — they only ever run on
473
+ // a first delivery, the one that could create the run.
474
+ //
475
+ // Returning acks the message. That is deliberate: the mismatch is
476
+ // baked into this message, so every redelivery would reach the
477
+ // same verdict, and throwing would just hot-loop the handler until
478
+ // MAX_QUEUE_DELIVERIES with the same error each time. It matches
479
+ // how the run_started path already discards deliveries whose
480
+ // verdict cannot change (EntityConflictError, RunExpiredError).
481
+ if (refuseCrossEnvironmentDelivery({
482
+ world,
483
+ runInput,
484
+ runId,
485
+ runLogger,
486
+ })) {
487
+ return;
488
+ }
489
+ // Diagnostic only — see the helper for why this warns instead of
490
+ // refusing the invocation.
491
+ await warnOnDeploymentPinningMismatch({
492
+ world,
493
+ runInput,
494
+ runId,
495
+ runLogger,
496
+ });
497
+ return trace(`workflow.execute ${workflowDisplayName(workflowName)}`, { kind: spanKind, links: spanLinks }, async (span) => {
135
498
  span?.setAttributes({
136
499
  ...Attribute.WorkflowName(workflowName),
137
- ...Attribute.WorkflowOperation('execute'),
138
- // Standard OTEL messaging conventions
500
+ ...Attribute.WorkflowOperation('execute_v2'),
139
501
  ...Attribute.MessagingSystem('vercel-queue'),
140
502
  ...Attribute.MessagingDestinationName(metadata.queueName),
141
503
  ...Attribute.MessagingMessageId(metadata.messageId),
142
504
  ...Attribute.MessagingOperationType('process'),
143
505
  ...getQueueOverhead({ requestedAt }),
144
- });
145
- // TODO: validate `workflowName` exists before consuming message?
146
- span?.setAttributes({
147
506
  ...Attribute.WorkflowRunId(runId),
148
507
  ...Attribute.WorkflowTracePropagated(!!traceContext),
508
+ ...Attribute.WorkflowTraceMode(traceMode),
149
509
  });
150
- let workflowStartedAt = -1;
510
+ const invocationStartTime = Date.now();
511
+ const noInlineReplayAfterMs = await getMaxInlineDurationMs(world, invocationStartTime);
512
+ let loopIteration = 0;
513
+ const replayRecoveryReporter = replayDivergence
514
+ ? new ReplayRecoveryReporter(replayDivergence.count)
515
+ : ReplayRecoveryReporter.inert();
516
+ // Every write this loop makes carries the cursor of the log
517
+ // it was computed against, and folds a complete returned
518
+ // delta into that log.
519
+ const createEvent = async (data, params) => {
520
+ const sinceCursor = deltaRequestCursor(data, params);
521
+ const result = await replayRecoveryReporter.withEventCreate(sinceCursor === undefined
522
+ ? params
523
+ : { ...params, sinceCursor }, (p) => world.events.create(runId, data, p));
524
+ if (sinceCursor !== undefined) {
525
+ absorbCreateDelta(sinceCursor, result);
526
+ }
527
+ return result;
528
+ };
529
+ /**
530
+ * The cursor to ask for an inline delta against, or
531
+ * undefined to not ask.
532
+ *
533
+ * Turbo is excluded on purpose: it exists to make the first
534
+ * invocation's writes as cheap as possible, and it has no
535
+ * loaded log to extend. Run-terminal writes are excluded
536
+ * because nothing reads the log afterwards, so the delta
537
+ * would be work the World does for no one. A caller that
538
+ * set its own `sinceCursor` (or asked for the `run_started`
539
+ * / `hook_received` preload, which owns the same response
540
+ * fields) keeps what it asked for.
541
+ */
542
+ const deltaRequestCursor = (data, params) => {
543
+ if (turbo ||
544
+ eventLog.type !== 'ready' ||
545
+ params?.sinceCursor !== undefined ||
546
+ params?.preloadEvents === true ||
547
+ isTerminalRunEventType(data.eventType)) {
548
+ return undefined;
549
+ }
550
+ return eventLog.cursor ?? undefined;
551
+ };
552
+ /**
553
+ * Fold an inline delta returned by `events.create` into the
554
+ * in-memory event log.
555
+ *
556
+ * The delta is what `events.list({ cursor: sentCursor })`
557
+ * would have returned right after the write, so it carries
558
+ * back both our own event and anything another writer
559
+ * appended in band. Absorbing it here means the next reader
560
+ * already has the log and the loop's incremental
561
+ * `events.list` finds nothing left to fetch.
562
+ *
563
+ * Declining is always safe — an unabsorbed delta is a delta
564
+ * the next `events.list` returns — so the guards are free to
565
+ * be strict:
566
+ *
567
+ * - `hasMore` means the World truncated the page. Taking it
568
+ * while advancing the cursor to the page end would be
569
+ * fine, but taking it and NOT advancing would duplicate,
570
+ * and the truncated case is rare enough not to special-case.
571
+ * - The cursor must be exactly where it was when the request
572
+ * went out. Concurrent writes each diff against the cursor
573
+ * they saw, and `appendUniqueEvents` deliberately does not
574
+ * re-sort, so absorbing a second delta computed from an
575
+ * older cursor could append events behind ones already
576
+ * taken. First response back wins; the rest are dropped.
577
+ */
578
+ const absorbCreateDelta = (sentCursor, result) => {
579
+ if (eventLog.type !== 'ready' ||
580
+ eventLog.cursor !== sentCursor ||
581
+ result.events === undefined ||
582
+ result.hasMore === true) {
583
+ return;
584
+ }
585
+ appendEventLog(eventLog, {
586
+ events: result.events,
587
+ cursor: result.cursor,
588
+ });
589
+ };
590
+ // `ready` can replay once without a read. The other states
591
+ // describe the next load exactly.
592
+ let eventLog = { type: 'loadAll' };
593
+ // Shared state: set by either the background step path
594
+ // or the run_started setup below.
151
595
  let workflowRun;
152
- // Pre-loaded events from the run_started response.
153
- // When present, we skip the events.list call to reduce TTFB.
154
- let preloadedEvents;
596
+ // Server-supplied per-run event ceiling from the run_started
597
+ // response. Undefined no enforcement (older servers, turbo).
598
+ let maxEventsLimit;
599
+ let workflowStartedAt = -1;
600
+ // Latency telemetry (TTFS) state — see runtime/step-latency.ts.
601
+ // Whether this invocation's FIRST event snapshot contained
602
+ // nothing beyond run_created/run_started: anything else was
603
+ // written by an earlier invocation, whose contribution to
604
+ // time-to-first-step (including the queue hop back here)
605
+ // cannot be measured wall-clock, so TTFS is not reported.
606
+ // Set once, on the first iteration's loaded snapshot.
607
+ let invocationStartedClean;
608
+ // Epoch ms the `run_started` response was received/parsed
609
+ // by the SDK — anchors RSFS (run_started → first step's
610
+ // start POST). Set once, in the run_started setup below.
611
+ // Under turbo, run_started is backgrounded rather than
612
+ // awaited, so this is stamped at the point the run is
613
+ // synthesized locally instead of the real response — see
614
+ // StepLatencyTracking.rsfsAnchorMs.
615
+ let runStartedReceivedAtMs;
616
+ // Wall-clock ms spent committing hook_created events before
617
+ // the first step ran, accumulated across suspension passes
618
+ // and subtracted from TTFS. Accumulators here survive an
619
+ // in-process replay restart (a stale-snapshot rejection, or
620
+ // the attribute-event restart below), so a restarted
621
+ // invocation over-counts by the abandoned pass's hook time —
622
+ // the same slight over-count either restart has always had.
623
+ let preStepBlockingMs = 0;
624
+ // Snapshot of the accumulator as of the suspension that
625
+ // wrote the run's first attr_set (whose hook phase ran
626
+ // before its attr writes). When a pre-step setAttributes
627
+ // ends the TTFS measurement at the attr write, only hook
628
+ // time from BEFORE that point may be subtracted — later
629
+ // hook writes fall outside the measured window.
630
+ let preStepBlockingBeforeAttrMs;
631
+ // Turbo mode fast-paths the very first delivery of the very
632
+ // first invocation, where it is provably safe to: background
633
+ // `run_started`, skip the initial event-log load (nothing has
634
+ // been written yet), and force optimistic inline start (no
635
+ // concurrent peer handler exists to race the create-claim).
636
+ // `runInput` is only present on the start()-enqueued message,
637
+ // and `attempt === 1` (1-based) means this is the first
638
+ // delivery; `incomingStepId` would mark a background-step
639
+ // invocation and `replayDivergence` a recovery replay — both
640
+ // ineligible. The single-handler guarantee that makes forced
641
+ // optimistic start safe ends once a hook or wait is created
642
+ // (they introduce resume invocations), so turbo exits at that
643
+ // point (see `forceOptimisticStart`). Workflow attribute
644
+ // writes introduce no such invocation source — they resolve
645
+ // via an in-process replay and don't end turbo.
646
+ // NOTE: `metadata.attempt === 1` is also load-bearing for
647
+ // inline step ownership: owned-recovery steps (a step
648
+ // stamped by a PREVIOUS delivery of this message) can only
649
+ // exist on attempt ≥ 2, so turbo and owned recovery are
650
+ // mutually exclusive. The turbo `reinvoke()` paths (hook
651
+ // conflict, throttle backoff) ack this message and continue
652
+ // under a NEW message id — safe only because no
653
+ // non-terminal step can be inline-owned by the acked id
654
+ // when turbo is on. If turbo ever engages on redeliveries,
655
+ // those paths must first check for owned pending steps and
656
+ // fall back to `{ timeoutSeconds }` redelivery.
657
+ const turbo = isTurboEnabled() &&
658
+ runInput !== undefined &&
659
+ metadata.attempt === 1 &&
660
+ incomingStepId === undefined &&
661
+ !replayDivergence;
662
+ span?.setAttributes(Attribute.WorkflowTurbo(turbo));
663
+ // Turbo mode only: resolves once the backgrounded
664
+ // `run_started` has landed (or rejects if it failed). Threaded
665
+ // into handleSuspension and executeStep so no step/hook/wait
666
+ // write races ahead of the run's creation. Undefined outside
667
+ // turbo, where `run_started` is awaited up front.
668
+ let runReadyBarrier;
669
+ // Order a terminal run write (run_completed / run_failed) after
670
+ // the backgrounded run_started in turbo mode — a no-step
671
+ // workflow can otherwise reach run_completed before the run
672
+ // exists. Best-effort: a barrier rejection is swallowed for
673
+ // ordering only; if run_started truly failed the terminal write
674
+ // surfaces the real error (run not found / gone) and the message
675
+ // redelivers. No-op outside turbo.
676
+ const awaitRunReady = async () => {
677
+ if (runReadyBarrier) {
678
+ try {
679
+ await runReadyBarrier;
680
+ }
681
+ catch {
682
+ // intentional: ordering barrier only — see above.
683
+ }
684
+ }
685
+ };
686
+ // Re-invoke the orchestrator. Outside turbo this returns
687
+ // `{ timeoutSeconds }`, which makes the queue reschedule the
688
+ // CURRENT delivery's message. In turbo that is a trap: the
689
+ // current message carries `runInput`, and on async queues
690
+ // (e.g. graphile-worker) a reschedule comes back as delivery
691
+ // attempt 1 — so turbo re-engages, skips the event-log load
692
+ // again, replays against an empty log, never observes the
693
+ // hook event this invocation just wrote, and re-suspends
694
+ // forever (the run wedges). Under turbo we instead enqueue an
695
+ // explicit continuation that carries NO `runInput`, so the
696
+ // next delivery is a normal (non-turbo) load-and-replay that
697
+ // observes the committed events and makes progress; we then
698
+ // return `undefined` so the queue treats this delivery as done
699
+ // rather than also rescheduling it.
700
+ // Inline-ownership invariant guard: correlation IDs of
701
+ // steps whose bodies this invocation is executing under an
702
+ // ownership stamp (lazy inline + owned recovery), while the
703
+ // body is in flight. Crash recovery depends on the owning
704
+ // message NOT being acked while such a step is non-terminal
705
+ // (ack = handler return or reinvoke, which acks + enqueues
706
+ // under a NEW message id — the redelivery of the old id is
707
+ // what re-executes an orphaned owned step). All executeStep
708
+ // calls are awaited before any ack path runs, so this set
709
+ // is empty at every ack by construction; the check exists
710
+ // to catch future refactors that break that ordering.
711
+ const inFlightOwnedSteps = new Set();
712
+ const assertNoInFlightOwnedSteps = (ackPath) => {
713
+ if (inFlightOwnedSteps.size > 0) {
714
+ runtimeLogger.error('Invariant violation: acking the workflow message while owned inline steps are still executing — crash recovery for these steps is broken', {
715
+ workflowRunId: runId,
716
+ ackPath,
717
+ stepIds: [...inFlightOwnedSteps],
718
+ });
719
+ }
720
+ };
721
+ // A plain orchestrator-replay message. Omits `runInput` (it
722
+ // re-engages turbo on the next delivery and wedges the run —
723
+ // see `reinvoke` below) and `replayDivergence` /
724
+ // `serverErrorRetryCount` (this delivery chain's budgets).
725
+ const replayMessage = async () => ({
726
+ runId,
727
+ traceCarrier: await nextTraceCarrier(),
728
+ requestedAt: new Date(),
729
+ });
730
+ const reinvoke = async (delaySeconds,
731
+ /**
732
+ * Extra fields to carry on the new message. Only reaches the
733
+ * next invocation on the turbo path: without turbo no
734
+ * message is enqueued at all — the handler returns a
735
+ * visibility timeout and the queue redelivers the CURRENT
736
+ * message, whose body (and therefore any counter on it)
737
+ * cannot be changed.
738
+ */
739
+ extraPayload) => {
740
+ assertNoInFlightOwnedSteps('reinvoke');
741
+ if (!turbo)
742
+ return { timeoutSeconds: delaySeconds };
743
+ await queueMessage(world, getWorkflowQueueName(workflowName, namespace), { ...(await replayMessage()), ...extraPayload }, delaySeconds > 0 ? { delaySeconds } : undefined);
744
+ return undefined;
745
+ };
746
+ // Precondition (412) recovery: how many times this invocation
747
+ // has thrown away its replay and started over in-process.
748
+ let preconditionRestarts = 0;
749
+ /**
750
+ * Event ids the discarded replay held, kept until the next
751
+ * load resolves so a restart can report what its reload
752
+ * actually found. Without this a 412 only ever tells you that
753
+ * a restart happened, which conflates two very different
754
+ * situations: a log that grew (expected — the fence did its
755
+ * job) and a log that came back identical, which means client
756
+ * and backend disagree about the count for the same set of
757
+ * events and the restart will re-derive the same snapshot and
758
+ * be rejected again.
759
+ */
760
+ let preconditionRestartBaseline = null;
761
+ /**
762
+ * Report what a stale-snapshot restart's reload found, once
763
+ * the log this replay will actually consume is in hand.
764
+ *
765
+ * `grew` is the expected case and gives 412 volume a
766
+ * denominator. `unchanged` means the reload disagreed with
767
+ * the rejection, so this replay re-derives the same snapshot
768
+ * and is rejected again until the budget is spent. `shrank`
769
+ * should be impossible: every load path only adds to a run's
770
+ * log.
771
+ */
772
+ const reportPreconditionRestartReload = (events) => {
773
+ const baseline = preconditionRestartBaseline;
774
+ if (!baseline)
775
+ return;
776
+ preconditionRestartBaseline = null;
777
+ const reloadedIds = new Set(events.map((event) => event.eventId));
778
+ const added = countMissingIds(reloadedIds, baseline.ids);
779
+ const dropped = countMissingIds(baseline.ids, reloadedIds);
780
+ const outcome = dropped > 0 ? 'shrank' : added > 0 ? 'grew' : 'unchanged';
781
+ runtimeLogger.warn('Restarted replay reloaded its event log after a stale-snapshot rejection', {
782
+ workflowRunId: runId,
783
+ outcome,
784
+ added,
785
+ dropped,
786
+ eventsBefore: baseline.ids.size,
787
+ eventsAfter: reloadedIds.size,
788
+ preconditionRestarts: baseline.restart,
789
+ reason: baseline.reason,
790
+ source: baseline.source,
791
+ loopIteration,
792
+ });
793
+ };
794
+ /**
795
+ * Recover from a stale-snapshot rejection by restarting the
796
+ * replay inside this invocation, returning false when the
797
+ * per-invocation budget is spent (the caller then falls back
798
+ * to a fresh invocation).
799
+ *
800
+ * A 412 means the log this replay derived its events from was
801
+ * missing an event the backend had already recorded. The
802
+ * rejected write cannot simply be retried: correlation ids
803
+ * are positional ordinals of one seeded sequence, so a replay
804
+ * over the corrected log mints a different id for the same
805
+ * logical event, and re-posting this one would persist an
806
+ * event no correct replay ever produces. The whole replay has
807
+ * to be re-derived — which the loop does by discarding its
808
+ * cached log, since `runWorkflow` then builds a fresh VM,
809
+ * seed and correlation-id sequence from the reloaded events.
810
+ */
811
+ const restartReplayInProcess = (reason, error,
812
+ /**
813
+ * Set false when writes this invocation made concurrently
814
+ * with the rejected one may be missing from the 412's
815
+ * delta: the World computed that delta against the
816
+ * rejected request's snapshot, so it cannot contain an
817
+ * event a sibling committed afterwards, and merging it
818
+ * would restart the replay on a log that is still
819
+ * incomplete. Only a full reload is authoritative then.
820
+ */
821
+ { allowDelta = true } = {}) => {
822
+ if (preconditionRestarts >=
823
+ getPreconditionMaxInProcessRestarts()) {
824
+ return false;
825
+ }
826
+ preconditionRestarts++;
827
+ // Every stale-snapshot restart invalidates the parked VM:
828
+ // the log it consumed was missing events, so only a fresh
829
+ // replay over the corrected log is authoritative. This
830
+ // also covers the suspension-create 412, which fires
831
+ // before the retention decision (kill switch + step-input
832
+ // gate) ever ran, and the run_completed 412, where a
833
+ // completed session must not be resumed again.
834
+ retainedSession = null;
835
+ // A World MAY return the events we were missing on the 412.
836
+ // Trust it only on the FIRST restart: its completeness proof
837
+ // leans on the backend's own bookkeeping, so if that
838
+ // under-counts, a "complete" delta can still leave a hole.
839
+ // Bounding it to one attempt caps that at a single wasted
840
+ // restart; every later restart does the authoritative load.
841
+ const delta = allowDelta && preconditionRestarts === 1
842
+ ? preconditionEventDelta(error, runId)
843
+ : null;
844
+ // A delta is only usable if there is a loaded log to merge
845
+ // it into; without one the restart must load everything.
846
+ const usedDelta = delta !== null && eventLog.type !== 'loadAll';
847
+ // Snapshot the set being discarded while it is still in
848
+ // hand; the comparison happens once the next load resolves.
849
+ preconditionRestartBaseline =
850
+ eventLog.type !== 'loadAll'
851
+ ? {
852
+ ids: new Set(eventLog.events.map((event) => event.eventId)),
853
+ restart: preconditionRestarts,
854
+ reason,
855
+ source: usedDelta ? 'inline-delta' : 'full-reload',
856
+ }
857
+ : null;
858
+ if (delta && eventLog.type !== 'loadAll') {
859
+ appendEventLog(eventLog, delta);
860
+ eventLog = { ...eventLog, type: 'ready' };
861
+ }
862
+ else {
863
+ // MUST be a full, cursor-less reload. The cursor filters
864
+ // by lexicographic event id while a hole is defined by
865
+ // ULID *time*: an event in the same millisecond sorts
866
+ // either side of the cursor depending on its random
867
+ // component, and an event minted in an earlier
868
+ // millisecond but committed later always sorts below it.
869
+ // An incremental load therefore heals the hole only by
870
+ // luck.
871
+ eventLog = { type: 'loadAll' };
872
+ // The corrected log inserts the missing events BELOW the
873
+ // length already scanned for payload prewarming, shifting
874
+ // every later position. Only a full rescan sees them.
875
+ replayPayloadCache.resetScan();
876
+ }
877
+ runtimeLogger.warn('Event creation rejected as stale; restarting replay in-process', {
878
+ workflowRunId: runId,
879
+ reason,
880
+ loopIteration,
881
+ preconditionRestarts,
882
+ source: usedDelta ? 'inline-delta' : 'full-reload',
883
+ });
884
+ span?.setAttributes({
885
+ 'workflow.precondition_restarts': preconditionRestarts,
886
+ });
887
+ return true;
888
+ };
889
+ /**
890
+ * Escalate a stale-snapshot rejection that survived the
891
+ * in-process restart budget to a fresh invocation, or give up
892
+ * on the run when the per-run budget is also spent.
893
+ *
894
+ * The in-process budget is a closure variable and the queue's
895
+ * delivery count restarts at 1 whenever a new message is
896
+ * enqueued, so a run that is permanently unable to catch up
897
+ * with its own event log would otherwise cycle restarts →
898
+ * re-invoke → restarts with no run-level bound. The chain is
899
+ * therefore counted on the message itself, in the same way
900
+ * replay divergences are, and fails the run once exhausted.
901
+ *
902
+ * The counter only advances on hops that enqueue a new message
903
+ * (see `reinvoke`). A redelivery-based hop keeps the same body
904
+ * and so the same count, but it also keeps advancing
905
+ * `metadata.attempt`, which the max-delivery check at the top
906
+ * of the handler already bounds — and the delay below is what
907
+ * makes that budget span real time rather than being burned in
908
+ * a tight loop.
909
+ */
910
+ const reinvokeAfterStaleRejection = async (reason, error) => {
911
+ const attempt = (preconditionReinvocations ?? 0) + 1;
912
+ const maxReinvocations = getPreconditionMaxReinvocations();
913
+ if (attempt > maxReinvocations) {
914
+ return {
915
+ reinvoked: false,
916
+ error: new WorkflowRuntimeError(`Event creation was rejected as stale after ${maxReinvocations} re-invocations of ${getPreconditionMaxInProcessRestarts()} in-process replay restarts each: this run cannot observe its own event log completely enough to make progress. Last rejection (${reason}): ${error instanceof Error ? error.message : String(error)}`, { cause: error }),
917
+ };
918
+ }
919
+ runtimeLogger.warn('Event creation rejected as stale after in-process restarts; re-invoking run for a fresh replay', {
920
+ workflowRunId: runId,
921
+ reason,
922
+ loopIteration,
923
+ preconditionReinvocations: attempt,
924
+ maxReinvocations,
925
+ });
926
+ span?.setAttributes({
927
+ 'workflow.precondition_reinvocations': attempt,
928
+ });
929
+ // Delayed, unlike the other reinvoke() callers: the
930
+ // in-process restarts already reloaded the log several times
931
+ // without catching up, so the writers this replay is racing
932
+ // are still active. Retrying instantly just burns the
933
+ // per-run budget at full speed.
934
+ return {
935
+ reinvoked: true,
936
+ result: await reinvoke(getPreconditionReinvokeDelaySeconds(), { preconditionReinvocations: attempt }),
937
+ };
938
+ };
939
+ // Deployment-affinity guard, shared by the two paths that
940
+ // execute a run: queued step executions and flow replays.
941
+ const guardDeployment = async (run, reenqueuePayload, beforeStop) => {
942
+ const { outcome, spanAttributes } = await guardDeploymentAffinity({
943
+ world,
944
+ run,
945
+ requestId,
946
+ retryCount: deploymentMismatchRetryCount,
947
+ beforeStop,
948
+ isDeploymentUnavailableError: world.isDeploymentUnavailableError,
949
+ reenqueue: async ({ deploymentId, specVersion, deploymentMismatchRetryCount: retryCount, delaySeconds, }) => {
950
+ await queueMessage(world, getWorkflowQueueName(workflowName, namespace), {
951
+ ...(await reenqueuePayload()),
952
+ deploymentMismatchRetryCount: retryCount,
953
+ }, { deploymentId, specVersion, delaySeconds });
954
+ },
955
+ });
956
+ if (spanAttributes)
957
+ span?.setAttributes(spanAttributes);
958
+ return outcome;
959
+ };
960
+ // If incoming message has a stepId, this is a background step
961
+ // execution. Execute the step, then check if all parallel steps
962
+ // from the batch are done. If so, replay inline (saving a queue
963
+ // roundtrip). If not, return — the last handler to complete
964
+ // will pick up the replay.
965
+ if (incomingStepId && incomingStepName) {
966
+ try {
967
+ const bgRun = await world.runs.get(runId, {
968
+ resolveData: 'none',
969
+ });
970
+ if (bgRun.status !== 'running') {
971
+ runtimeLogger.debug('Run already finished, skipping background step', { workflowRunId: runId, status: bgRun.status });
972
+ return;
973
+ }
974
+ // Covers every queued step execution — first dispatch and
975
+ // redeliveries/retries alike.
976
+ if ((await guardDeployment(bgRun, async () => ({
977
+ ...(await replayMessage()),
978
+ stepId: incomingStepId,
979
+ stepName: incomingStepName,
980
+ }))) !== 'continue') {
981
+ return;
982
+ }
983
+ const bgStartedAt = bgRun.startedAt
984
+ ? +bgRun.startedAt
985
+ : Date.now();
986
+ // Retry ceiling for a backgrounded step. `metadata.attempt`
987
+ // (the queue delivery count) is a cheap upper bound, but it
988
+ // over-counts: a ThrottleError / TooEarlyError — or any
989
+ // redelivery that never ran the body — still advances it, so
990
+ // trusting it directly could fail a step as "exceeded max
991
+ // retries" before the body ever ran (a user-visible
992
+ // regression under transient backend pressure). Use it only
993
+ // as a fast gate: while it is at or under the ceiling the
994
+ // step cannot be exhausted, so proceed without touching the
995
+ // log. Only once it crosses the ceiling do we load the full
996
+ // event log and derive the authoritative attempt from the
997
+ // recorded `step_started` count — scoped to the lifecycle
998
+ // attempt total (bare starts plus the largest single
999
+ // owner's starts): throttle/too-early redeliveries write
1000
+ // no start at all, racing invocations' one-off stamped
1001
+ // duplicates don't accumulate (counting them falsely
1002
+ // exhausted healthy steps — see countStepStartedEvents),
1003
+ // and attempts burned under a prior inline-ownership
1004
+ // phase still count, so a step that times out under
1005
+ // owned recovery and then transitions to queued/bare
1006
+ // retries trips the combined ceiling. This still bounds
1007
+ // timeouts, which write no error for the post-body guard
1008
+ // to catch.
1009
+ let bgAuthoritativeAttempt = metadata.attempt;
1010
+ const bgMaxRetries = getStepFunction(incomingStepName)?.maxRetries ??
1011
+ DEFAULT_STEP_MAX_RETRIES;
1012
+ if (metadata.attempt > bgMaxRetries + 1) {
1013
+ const loaded = await loadWorkflowRunEvents(runId);
1014
+ bgAuthoritativeAttempt =
1015
+ countStepStartedEvents(loaded.events, incomingStepId, { type: 'totalAttempts' }) + 1;
1016
+ }
1017
+ // Pause the replay budget while the step body runs —
1018
+ // step duration is bounded by the platform's function
1019
+ // maxDuration, not by the replay timeout. See the
1020
+ // ReplayBudget docs for the contract.
1021
+ replayBudget.pause();
1022
+ let stepResult;
1023
+ try {
1024
+ // Single-flight: a delayed backstop (or retry) message
1025
+ // can arrive while another execution of this same step
1026
+ // is mid-body in this process — most importantly on
1027
+ // worlds with no invocation kill bound (world-local),
1028
+ // where the ownership lease is not a death proof. The
1029
+ // loser awaits the winner's settlement, then acks
1030
+ // without executing. No ownerMessageId here: the bare
1031
+ // step_started of a queue-driven execution
1032
+ // intentionally clears inline ownership (the step is
1033
+ // queue-owned from this point).
1034
+ stepResult = await runStepSingleFlight(runId, incomingStepId, () => executeStep({
1035
+ world,
1036
+ workflowRunId: runId,
1037
+ workflowDeploymentId: bgRun.deploymentId,
1038
+ workflowName,
1039
+ workflowStartedAt: bgStartedAt,
1040
+ rootRunId: rootRunIdFrom(bgRun.attributes, runId),
1041
+ stepId: incomingStepId,
1042
+ stepName: incomingStepName,
1043
+ runSpecVersion: bgRun.specVersion,
1044
+ // Retry ceiling: the queue delivery count as a fast
1045
+ // gate, verified against the recorded step_started
1046
+ // count once it crosses the ceiling (see above).
1047
+ authoritativeAttempt: bgAuthoritativeAttempt,
1048
+ }));
1049
+ }
1050
+ finally {
1051
+ replayBudget.resume();
1052
+ }
1053
+ if (stepResult.type === 'retry') {
1054
+ return { timeoutSeconds: stepResult.timeoutSeconds };
1055
+ }
1056
+ if (stepResult.type === 'throttled') {
1057
+ return { timeoutSeconds: stepResult.timeoutSeconds };
1058
+ }
1059
+ // If step had pending ops (stream writes), break and let
1060
+ // waitUntil flush them — can't continue inline.
1061
+ if (stepResult.type === 'completed' &&
1062
+ stepResult.hasPendingOps) {
1063
+ await queueMessage(world, getWorkflowQueueName(workflowName, namespace), {
1064
+ runId,
1065
+ traceCarrier: await nextTraceCarrier(),
1066
+ requestedAt: new Date(),
1067
+ });
1068
+ return;
1069
+ }
1070
+ if (stepResult.type === 'completed' ||
1071
+ stepResult.type === 'failed' ||
1072
+ stepResult.type === 'skipped') {
1073
+ // Load events to check if all parallel steps are done.
1074
+ // Use cursor-based loading so the main loop can continue
1075
+ // incrementally from here.
1076
+ const loaded = await loadWorkflowRunEvents(runId);
1077
+ eventLog = nextEventLogLoad(loaded);
1078
+ // Check for pending steps: any step_created without
1079
+ // a matching step_completed or step_failed.
1080
+ const stepCreatedIds = new Set();
1081
+ const stepTerminalIds = new Set();
1082
+ for (const e of loaded.events) {
1083
+ if (e.eventType === 'step_created') {
1084
+ stepCreatedIds.add(e.correlationId);
1085
+ }
1086
+ else if (e.eventType === 'step_completed' ||
1087
+ e.eventType === 'step_failed') {
1088
+ stepTerminalIds.add(e.correlationId);
1089
+ }
1090
+ }
1091
+ const pendingStepIds = new Set();
1092
+ for (const id of stepCreatedIds) {
1093
+ if (!stepTerminalIds.has(id)) {
1094
+ pendingStepIds.add(id);
1095
+ }
1096
+ }
1097
+ if (pendingStepIds.size > 0) {
1098
+ // A pending step that THIS message inline-owns (a
1099
+ // previous delivery of this message stamped its
1100
+ // step_started and then crashed mid-body) must be
1101
+ // recovered here: only the owning message may
1102
+ // re-execute it before the ownership lease expires,
1103
+ // and wake replays merely ensure a delayed
1104
+ // backstop. Fall through to the main loop, whose
1105
+ // dispatch table routes it to owned recovery.
1106
+ if (isInlineOwnershipEnabled() &&
1107
+ hasPendingStepOwnedByMessage(loaded.events, pendingStepIds, metadata.messageId)) {
1108
+ runtimeLogger.debug('Background step done; falling through to recover an inline step owned by this message', { workflowRunId: runId });
1109
+ }
1110
+ else {
1111
+ // Other steps still in progress. Return without
1112
+ // queuing — the last handler to complete will see
1113
+ // all steps done and replay inline.
1114
+ runtimeLogger.debug('Background step done but other steps pending, returning', { workflowRunId: runId });
1115
+ return;
1116
+ }
1117
+ }
1118
+ // All steps done — fall through to the main replay loop.
1119
+ // Set up shared state so the loop can continue.
1120
+ runtimeLogger.debug('All parallel steps done, replaying inline after background step', { workflowRunId: runId });
1121
+ const runCreatedEvent = loaded.events.find((event) => event.eventType === 'run_created');
1122
+ let replayInput;
1123
+ if (runCreatedEvent) {
1124
+ replayInput = runCreatedEvent.eventData.input;
1125
+ }
1126
+ else {
1127
+ if (!isLegacySpecVersion(bgRun.specVersion)) {
1128
+ throw new WorkflowRuntimeError(`Workflow run "${runId}" has no "run_created" event`);
1129
+ }
1130
+ // Legacy runs predate the event-sourced run_created
1131
+ // invariant, so retain the resolved GET only for them.
1132
+ const legacyRun = await world.runs.get(runId, {
1133
+ resolveData: 'all',
1134
+ });
1135
+ if (legacyRun.status !== 'running') {
1136
+ return;
1137
+ }
1138
+ replayInput = legacyRun.input;
1139
+ }
1140
+ workflowRun = {
1141
+ ...bgRun,
1142
+ input: replayInput,
1143
+ status: 'running',
1144
+ output: undefined,
1145
+ error: undefined,
1146
+ completedAt: undefined,
1147
+ };
1148
+ workflowStartedAt = bgStartedAt;
1149
+ }
1150
+ else {
1151
+ return;
1152
+ }
1153
+ }
1154
+ catch (err) {
1155
+ const errorCode = getWorkflowSetupErrorCode(err);
1156
+ if (!errorCode) {
1157
+ throw err;
1158
+ }
1159
+ await recordFatalRunError({
1160
+ world,
1161
+ workflowRun,
1162
+ runId,
1163
+ requestId,
1164
+ err,
1165
+ errorCode,
1166
+ logMessage: 'Fatal error while preparing background workflow step',
1167
+ });
1168
+ return;
1169
+ }
1170
+ }
1171
+ // Deployment-affinity pre-check for the lazy hook fast
1172
+ // path below. New lazy-resume messages carry the run's
1173
+ // pinned deployment (`hookInput.deploymentId`), so a
1174
+ // misrouted delivery is detectable with a cheap ambient
1175
+ // deployment-id comparison BEFORE the fast path's
1176
+ // hook_received write — the correctly-routed common case
1177
+ // pays no run fetch and no latency. Only a detected
1178
+ // mismatch fetches the authoritative run and hands it to
1179
+ // the existing guard (which owns re-route/fail policy);
1180
+ // the re-routed message keeps the complete `hookInput`,
1181
+ // since it may hold the only copy of the resume payload.
1182
+ // When the pinned or ambient id is unavailable (older
1183
+ // producer message, a world without deployment affinity,
1184
+ // or a getDeploymentId failure), behavior is unchanged:
1185
+ // the authoritative guard after run setup — which remains
1186
+ // the protection before replay and step execution — still
1187
+ // covers the delivery; the fast path's write is idempotent
1188
+ // per (runId, resumeId), so a pre-guard write from an
1189
+ // older message stays convergent.
1190
+ if (!workflowRun &&
1191
+ hookInput?.deploymentId !== undefined &&
1192
+ // Same eligibility as guardDeploymentAffinity: without
1193
+ // atomic, immutable deployments the ids legitimately
1194
+ // differ (e.g. dpl_local@<version>) and comparing them
1195
+ // would trigger spurious run fetches.
1196
+ world.capabilities?.deploymentAffinity === true) {
1197
+ const pinnedDeploymentId = hookInput.deploymentId;
1198
+ let currentDeploymentId;
1199
+ try {
1200
+ currentDeploymentId = await world.getDeploymentId();
1201
+ }
1202
+ catch {
1203
+ currentDeploymentId = undefined;
1204
+ }
1205
+ if (currentDeploymentId !== undefined &&
1206
+ currentDeploymentId !== pinnedDeploymentId) {
1207
+ const run = await world.runs.get(runId, {
1208
+ resolveData: 'none',
1209
+ });
1210
+ if ((await guardDeployment(run, async () => ({
1211
+ ...(await replayMessage()),
1212
+ hookInput,
1213
+ }), awaitRunReady)) !== 'continue') {
1214
+ return;
1215
+ }
1216
+ }
1217
+ }
1218
+ // --- Lazy hook resume fast path ---
1219
+ // A lazy hook delivery (resumeId + digest on the queue
1220
+ // message) hoists the consumer's idempotent hook_received
1221
+ // re-ensure above run_started and asks the World to return
1222
+ // the current replay log with the write (preloadEvents). A
1223
+ // supporting World answers with the reconstructed run, the
1224
+ // complete replay log, and the run's event ceiling —
1225
+ // everything the generic setup below would spend a
1226
+ // run_started POST and an events.list on. Any other result
1227
+ // (older server, a World that ignores the param, or a
1228
+ // preload that fails validation, including a bounded
1229
+ // hasMore page) falls back to that generic setup; the
1230
+ // hook_received write itself has still succeeded either
1231
+ // way, so the re-ensure block below is skipped via
1232
+ // `hookEnsured`. Never taken on turbo (turbo deliveries
1233
+ // carry runInput, not hookInput) or after the background
1234
+ // step path already loaded the run.
1235
+ let hookEnsured = false;
1236
+ if (!workflowRun &&
1237
+ hookInput &&
1238
+ hookInput.resumeId !== undefined &&
1239
+ hookInput.payloadDigest !== undefined) {
1240
+ const hookResumeInput = hookInput;
1241
+ // Date the materialized event to when the resume actually
1242
+ // occurred — same derivation as the re-ensure below (the
1243
+ // resumeId is a ULID minted by resumeHook() at resume
1244
+ // time).
1245
+ let occurredAt;
1246
+ try {
1247
+ occurredAt = new Date(decodeTime(hookResumeInput.resumeId));
1248
+ }
1249
+ catch {
1250
+ occurredAt = undefined;
1251
+ }
1252
+ try {
1253
+ span?.addEvent('workflow.hook_received.create.start', {
1254
+ 'workflow.hook_received.preload_events': true,
1255
+ });
1256
+ const result = await createEvent({
1257
+ eventType: 'hook_received',
1258
+ specVersion: SPEC_VERSION_CURRENT,
1259
+ correlationId: hookResumeInput.hookId,
1260
+ eventData: {
1261
+ token: hookResumeInput.token,
1262
+ payload: hookResumeInput.payload,
1263
+ },
1264
+ }, {
1265
+ requestId,
1266
+ occurredAt,
1267
+ resumeId: hookResumeInput.resumeId,
1268
+ resumePayloadDigest: hookResumeInput.payloadDigest,
1269
+ preloadEvents: true,
1270
+ });
1271
+ hookEnsured = true;
1272
+ // Note: unlike the re-ensure below, this hoisted write
1273
+ // does NOT set HookResilientResumeMaterialized — it
1274
+ // runs on every fast-path resume, including the common
1275
+ // case where the producer's direct write already landed
1276
+ // and this call merely converged on it, so it carries
1277
+ // no recovery signal. workflow.resume_setup_source
1278
+ // (below) describes this path instead.
1279
+ // The preload is usable as replay input only when it is
1280
+ // demonstrably the complete picture: a reconstructed
1281
+ // run with a start time, a non-empty COMPLETE log
1282
+ // (hasMore false — this path has no cursor-continuation
1283
+ // machinery, so a bounded page must not be trusted),
1284
+ // the server's event ceiling (this response plays
1285
+ // run_started's role, so a missing ceiling would leave
1286
+ // event-limit enforcement disabled for the run),
1287
+ // both run lifecycle events, the canonical event this
1288
+ // write converged on, and the hook_received matching
1289
+ // THIS resume (so we never replay against a log that is
1290
+ // missing the very event that triggered this delivery).
1291
+ const usableReplayPreload = result.run !== undefined &&
1292
+ result.run.startedAt !== undefined &&
1293
+ result.event !== undefined &&
1294
+ result.events !== undefined &&
1295
+ result.events.length > 0 &&
1296
+ result.cursor != null &&
1297
+ result.hasMore === false &&
1298
+ typeof result.maxEvents === 'number' &&
1299
+ result.events.some((e) => e.eventType === 'run_created') &&
1300
+ result.events.some((e) => e.eventType === 'run_started') &&
1301
+ result.events.some((e) => e.eventType === 'hook_received' &&
1302
+ e.resumeId === hookResumeInput.resumeId);
1303
+ if (usableReplayPreload &&
1304
+ result.run?.startedAt &&
1305
+ result.events) {
1306
+ // The reconstructed run always reads 'running', but a
1307
+ // terminal event committed concurrently rides in the
1308
+ // log itself. The node replay loop would catch it, but
1309
+ // QuickJS dispatches before that check — so consume
1310
+ // the delivery here, before any engine runs. Same
1311
+ // outcome as the run_started path's non-running
1312
+ // status check.
1313
+ const terminalEvent = result.events.find((e) => e.runId === runId &&
1314
+ (e.eventType === 'run_completed' ||
1315
+ e.eventType === 'run_failed' ||
1316
+ e.eventType === 'run_cancelled'));
1317
+ if (terminalEvent) {
1318
+ // The preload still initialized this delivery (it
1319
+ // is how the terminal state was observed), so the
1320
+ // setup-source and the run's actual terminal
1321
+ // status are recorded before consuming.
1322
+ span?.setAttributes({
1323
+ ...Attribute.WorkflowRunStatus(terminalEvent.eventType === 'run_completed'
1324
+ ? 'completed'
1325
+ : terminalEvent.eventType === 'run_failed'
1326
+ ? 'failed'
1327
+ : 'cancelled'),
1328
+ ...Attribute.HookResumeSetupSource('hook_received_stream'),
1329
+ });
1330
+ runtimeLogger.info('Run already finished during lazy hook setup, skipping', {
1331
+ workflowRunId: runId,
1332
+ eventType: terminalEvent.eventType,
1333
+ });
1334
+ return;
1335
+ }
1336
+ workflowRun = result.run;
1337
+ maxEventsLimit = clampMaxEvents(result.maxEvents);
1338
+ // Anchors RSFS — see the declaration above. This
1339
+ // response plays run_started's role on this path.
1340
+ runStartedReceivedAtMs = Date.now();
1341
+ eventLog = {
1342
+ type: 'ready',
1343
+ events: result.events,
1344
+ cursor: result.cursor,
1345
+ };
1346
+ workflowStartedAt = +result.run.startedAt;
1347
+ span?.setAttributes({
1348
+ ...Attribute.WorkflowRunStatus(result.run.status),
1349
+ ...Attribute.WorkflowStartedAt(workflowStartedAt),
1350
+ ...Attribute.HookResumeSetupSource('hook_received_stream'),
1351
+ });
1352
+ }
1353
+ else {
1354
+ // Successful write, no usable preload (CBOR response
1355
+ // from an older server, a World that ignored the
1356
+ // opt-in, a bounded hasMore page, or a preload that
1357
+ // failed validation): take the generic run_started
1358
+ // setup below. Its preload is loaded after this write
1359
+ // committed, so the canonical hook_received is part
1360
+ // of whatever log that setup reads — no splice
1361
+ // needed.
1362
+ span?.setAttributes(Attribute.HookResumeSetupSource('hook_received_fallback'));
1363
+ }
1364
+ }
1365
+ catch (err) {
1366
+ // Same classification as the re-ensure below:
1367
+ // - HookNotFound / RunExpired: the run went terminal;
1368
+ // nothing left to resume, consume the message.
1369
+ // - anything else (EntityConflict, a truncated preload
1370
+ // stream, transport failures): transient — rethrow so
1371
+ // the queue redelivers and the idempotent
1372
+ // (runId, resumeId) claim converges on retry.
1373
+ if (HookNotFoundError.is(err) ||
1374
+ RunExpiredError.is(err)) {
1375
+ runtimeLogger.info('Run already finished during lazy hook setup, skipping', { workflowRunId: runId, message: err.message });
1376
+ return;
1377
+ }
1378
+ throw err;
1379
+ }
1380
+ }
155
1381
  // --- Infrastructure: prepare the run state ---
156
- // Always call run_started directly this both transitions
157
- // the run to 'running' AND returns the run entity, saving
158
- // a separate runs.get round-trip.
159
- // Contract: events.create('run_started') must be idempotent
160
- // for runs already in 'running' status (return the run
161
- // without error), not just for pending running transitions.
162
- // Network/server errors propagate to the queue handler for retry.
163
- // WorkflowRuntimeError (data integrity issues) are fatal and
164
- // produce run_failed since retrying won't fix them.
165
- try {
166
- const result = await world.events.create(runId, {
1382
+ // Skip if workflowRun was already set by the background
1383
+ // step path (inline replay after all parallel steps done)
1384
+ // or by the lazy hook fast path above.
1385
+ if (!workflowRun) {
1386
+ // Always call run_started directly this both transitions
1387
+ // the run to 'running' AND returns the run entity, saving
1388
+ // a separate runs.get round-trip.
1389
+ // Contract: events.create('run_started') must be idempotent
1390
+ // for runs already in 'running' status (return the run
1391
+ // without error), not just for pending → running transitions.
1392
+ const runStartedEvent = {
167
1393
  eventType: 'run_started',
168
1394
  // Use the spec version from the original start() call
169
1395
  // when available, so the resilient start path creates
@@ -180,208 +1406,1805 @@ export function workflowEntrypoint(workflowCode) {
180
1406
  deploymentId: runInput.deploymentId,
181
1407
  workflowName: runInput.workflowName,
182
1408
  executionContext: runInput.executionContext,
1409
+ attributes: runInput.attributes,
1410
+ allowReservedAttributes: runInput.allowReservedAttributes,
183
1411
  },
184
1412
  }
185
1413
  : {}),
186
- }, { requestId });
187
- if (!result.run) {
188
- throw new WorkflowRuntimeError(`Event creation for 'run_started' did not return the run entity for run "${runId}"`);
189
- }
190
- workflowRun = result.run;
191
- // If the response includes events, use them to skip
192
- // the initial events.list call and reduce TTFB.
193
- if (result.events && result.events.length > 0) {
194
- preloadedEvents = result.events;
195
- }
196
- if (!workflowRun.startedAt) {
197
- throw new WorkflowRuntimeError(`Workflow run "${runId}" has no "startedAt" timestamp`);
1414
+ };
1415
+ if (turbo && runInput) {
1416
+ // Turbo: background `run_started` and synthesize the run
1417
+ // entity locally so replay can begin without waiting for
1418
+ // the round-trip. Safe here because this is the first
1419
+ // delivery of the first invocation start() created the
1420
+ // run moments ago and no events have been written yet. The
1421
+ // barrier is consumed by every downstream write (suspension
1422
+ // handler, optimistic step_started, terminal run writes) so
1423
+ // nothing is written before the run exists.
1424
+ span?.addEvent('workflow.run_started.create.start', {
1425
+ 'workflow.run_started.skip_preload': true,
1426
+ });
1427
+ const startedPromise = createEvent(runStartedEvent,
1428
+ // We background this purely as a write barrier and
1429
+ // never read its preloaded events, so skip the
1430
+ // run_started event-log preload. That trims the
1431
+ // run_started request the chained first step_started
1432
+ // waits on — shortening time-to-second-step — and the
1433
+ // wasted list+resolve it would otherwise compute.
1434
+ { requestId, skipPreload: true });
1435
+ runReadyBarrier = startedPromise;
1436
+ // Turbo backgrounds run_started, so the non-turbo assignment
1437
+ // below never runs — thread the per-run event ceiling off the
1438
+ // backgrounded response here instead. The guard re-checks
1439
+ // maxEventsLimit every loop iteration, so a value that lands
1440
+ // shortly after start still enforces well before a runaway
1441
+ // log approaches the ceiling.
1442
+ void startedPromise
1443
+ .then((r) => {
1444
+ const limit = clampMaxEvents(r.maxEvents);
1445
+ if (limit !== undefined)
1446
+ maxEventsLimit = limit;
1447
+ })
1448
+ // Prevent an early failure from surfacing as an
1449
+ // unhandledRejection; runReadyBarrier still observes it.
1450
+ .catch(() => { });
1451
+ // Skip the initial events.list: nothing has been written to
1452
+ // the log yet on a first delivery (run_started is still in
1453
+ // flight). An empty preload routes iteration 1 through
1454
+ // the no-load preloaded branch; iteration 2 then takes the
1455
+ // existing post-preloaded full reload to pick up a cursor
1456
+ // without a spurious "cursor missing" warning.
1457
+ eventLog = {
1458
+ type: 'ready',
1459
+ events: [],
1460
+ cursor: null,
1461
+ };
1462
+ const now = new Date();
1463
+ workflowRun = {
1464
+ runId,
1465
+ status: 'running',
1466
+ deploymentId: runInput.deploymentId,
1467
+ workflowName: runInput.workflowName,
1468
+ specVersion: runInput.specVersion,
1469
+ executionContext: runInput.executionContext,
1470
+ input: runInput.input,
1471
+ // Seed attributes from start() ride along in `runInput`
1472
+ // (they live in `run_created`'s eventData, not separate
1473
+ // `attr_set` events), so the synthesized snapshot carries
1474
+ // them even though we skip the initial events.list. This
1475
+ // is correct ONLY while attributes are write-only:
1476
+ // there is no in-workflow read API today (see workflow.ts
1477
+ // "structural until a read API is introduced"), so the
1478
+ // empty preloaded log can't diverge on a read. If a read
1479
+ // API is ever added it MUST read from this snapshot, not
1480
+ // by replaying run_created/attr_set events — otherwise
1481
+ // turbo's empty initial log would surface seed attributes
1482
+ // as `{}` on the first delivery only.
1483
+ attributes: runInput.attributes ?? {},
1484
+ startedAt: now,
1485
+ createdAt: now,
1486
+ updatedAt: now,
1487
+ };
1488
+ workflowStartedAt = +now;
1489
+ // See the `runStartedReceivedAtMs` declaration above:
1490
+ // turbo synthesizes the run before the real
1491
+ // `run_started` response lands, so anchor RSFS here
1492
+ // rather than at an actual response instant.
1493
+ runStartedReceivedAtMs = +now;
1494
+ span?.setAttributes({
1495
+ ...Attribute.WorkflowRunStatus('running'),
1496
+ ...Attribute.WorkflowStartedAt(workflowStartedAt),
1497
+ });
198
1498
  }
1499
+ else {
1500
+ try {
1501
+ span?.addEvent('workflow.run_started.create.start', {
1502
+ 'workflow.run_started.skip_preload': false,
1503
+ });
1504
+ const result = await createEvent(runStartedEvent, {
1505
+ requestId,
1506
+ });
1507
+ workflowRun = result.run;
1508
+ maxEventsLimit = clampMaxEvents(result.maxEvents);
1509
+ // Anchors RSFS — see the declaration above.
1510
+ runStartedReceivedAtMs = Date.now();
1511
+ if (result.events?.length) {
1512
+ const loaded = {
1513
+ events: [...result.events],
1514
+ cursor: result.cursor ?? null,
1515
+ };
1516
+ eventLog = result.hasMore
1517
+ ? nextEventLogLoad(loaded)
1518
+ : { ...loaded, type: 'ready' };
1519
+ }
1520
+ workflowStartedAt = +result.run.startedAt;
1521
+ span?.setAttributes({
1522
+ ...Attribute.WorkflowRunStatus(result.run.status),
1523
+ ...Attribute.WorkflowStartedAt(workflowStartedAt),
1524
+ });
1525
+ if (result.run.status !== 'running') {
1526
+ runtimeLogger.info('Workflow already completed or failed, skipping', {
1527
+ workflowRunId: runId,
1528
+ status: result.run.status,
1529
+ });
1530
+ // TODO: for `cancel`, we actually want to propagate a WorkflowCancelled event
1531
+ // inside the workflow context so the user can gracefully exit. this is SIGTERM
1532
+ // TODO: furthermore, there should be a timeout or a way to force cancel SIGKILL
1533
+ // so that we actually exit here without replaying the workflow at all, in the case
1534
+ // the replaying the workflow is itself failing.
1535
+ return;
1536
+ }
1537
+ }
1538
+ catch (err) {
1539
+ // Run was concurrently completed/failed/cancelled
1540
+ if (EntityConflictError.is(err) ||
1541
+ RunExpiredError.is(err)) {
1542
+ // EntityConflictError: run was concurrently
1543
+ // completed/failed/cancelled during setup.
1544
+ // RunExpiredError: run already in terminal state.
1545
+ // In both cases, skip processing this message.
1546
+ runtimeLogger.info('Run already finished during setup, skipping', { workflowRunId: runId, message: err.message });
1547
+ return;
1548
+ }
1549
+ else {
1550
+ const errorCode = getWorkflowSetupErrorCode(err);
1551
+ if (!errorCode) {
1552
+ throw err;
1553
+ }
1554
+ await recordFatalRunError({
1555
+ world,
1556
+ workflowRun,
1557
+ runId,
1558
+ requestId,
1559
+ err,
1560
+ errorCode,
1561
+ logMessage: 'Fatal runtime error during workflow setup',
1562
+ });
1563
+ return;
1564
+ }
1565
+ }
1566
+ } // end else (non-turbo run_started)
1567
+ } // end if (!workflowRun)
1568
+ assert(workflowRun, 'Workflow run must be loaded before replay');
1569
+ // Covers every flow replay — initial start, step completions,
1570
+ // hook resumptions, wait completions — and stops before any
1571
+ // workflow code or inline step executes when the run is not
1572
+ // pinned here (see `guardDeploymentAffinity`). This remains
1573
+ // the AUTHORITATIVE protection before replay and step
1574
+ // execution. `awaitRunReady` orders turbo's `run_started`
1575
+ // before either stopping action.
1576
+ //
1577
+ // Lazy hook resumes are additionally pre-checked above the
1578
+ // fast path: a new message's `hookInput.deploymentId` is
1579
+ // compared against the ambient deployment id for free, and
1580
+ // only a detected mismatch fetches the authoritative run —
1581
+ // so a misrouted modern resume re-routes with zero event
1582
+ // writes. Older messages (no `hookInput.deploymentId`) reach
1583
+ // the fast path's idempotent hook_received write before this
1584
+ // guard; that write converges per (runId, resumeId) on the
1585
+ // pinned deployment, so it is safe, just not free. Either
1586
+ // way the re-routed message must carry `hookInput`, or a
1587
+ // resume whose producer write had not yet landed would be
1588
+ // lost.
1589
+ if ((await guardDeployment(workflowRun, async () => ({
1590
+ ...(await replayMessage()),
1591
+ ...(hookInput ? { hookInput } : {}),
1592
+ }), awaitRunReady)) !== 'continue') {
1593
+ return;
199
1594
  }
200
- catch (err) {
201
- // Run was concurrently completed/failed/cancelled
202
- if (EntityConflictError.is(err) ||
203
- RunExpiredError.is(err)) {
204
- // EntityConflictError: run was concurrently
205
- // completed/failed/cancelled during setup.
206
- // RunExpiredError: run already in terminal state.
207
- // In both cases, skip processing this message.
208
- runtimeLogger.info('Run already finished during setup, skipping', { workflowRunId: runId, message: err.message });
209
- return;
1595
+ // Lazy hook resume: the producer (resumeHook fast path)
1596
+ // parallelized the `hook_received` write with this queue
1597
+ // publish, so the event may not be persisted yet. Idempotently
1598
+ // ensure it before replay — keyed by `resumeId` so a
1599
+ // concurrent producer write converges on exactly one event
1600
+ // (the server resolves a matching claim as success, not an
1601
+ // error). `hookInput` never rides a turbo first-delivery
1602
+ // (that path carries `runInput`, not `hookInput`), so this
1603
+ // only runs on the normal load-and-replay path. Skipped
1604
+ // entirely when the fast path above already ensured the
1605
+ // event (`hookEnsured`) — successfully or via its fallback,
1606
+ // whose run_started preload was loaded after the write and
1607
+ // therefore already contains the canonical event.
1608
+ if (hookInput && !hookEnsured) {
1609
+ // Perf (Option A): if the producer's concurrent direct
1610
+ // write already landed in the run_started preload, the
1611
+ // canonical event is in the log and the re-ensure round trip
1612
+ // is pure overhead. Skip it when the preload already carries
1613
+ // a `hook_received` with this resume's persisted `resumeId`
1614
+ // (unique per resume, so we never skip on an unrelated
1615
+ // hook_received). Best-effort: the win lands only when the
1616
+ // producer's write beat this consumer's load; otherwise we
1617
+ // fall through to the idempotent re-ensure below.
1618
+ //
1619
+ // Intentionally unreachable for atomic lazy resumes
1620
+ // (resumeId + digest): those set `hookEnsured` in the
1621
+ // hoisted fast path above — on success AND on its
1622
+ // fallback — so this block (and the skip check) now only
1623
+ // serves hookInput shapes without the full idempotency
1624
+ // pair.
1625
+ const alreadyPreloaded = hookInput.resumeId !== undefined &&
1626
+ eventLog.type !== 'loadAll' &&
1627
+ eventLog.events.some((e) => e.eventType === 'hook_received' &&
1628
+ e.resumeId === hookInput.resumeId);
1629
+ if (alreadyPreloaded) {
1630
+ // Event already visible in the preloaded log — nothing to
1631
+ // ensure or splice.
210
1632
  }
211
- else if (err instanceof WorkflowRuntimeError) {
212
- runtimeLogger.error('Fatal runtime error during workflow setup', { workflowRunId: runId, error: err.message });
1633
+ else {
1634
+ // Date the materialized event to when the resume actually
1635
+ // occurred, not when this queue delivery ran. `resumeId`
1636
+ // is the ULID minted by `resumeHook()` at resume time, so
1637
+ // its embedded timestamp is the honest `occurredAt` and
1638
+ // keeps latency attribution off the queue round trip. A
1639
+ // non-ULID resumeId (legacy / test) simply leaves it
1640
+ // undefined, so the World falls back to `createdAt`.
1641
+ let occurredAt;
1642
+ try {
1643
+ occurredAt =
1644
+ hookInput.resumeId !== undefined
1645
+ ? new Date(decodeTime(hookInput.resumeId))
1646
+ : undefined;
1647
+ }
1648
+ catch {
1649
+ occurredAt = undefined;
1650
+ }
1651
+ let ensuredEvent;
213
1652
  try {
214
- await world.events.create(runId, {
215
- eventType: 'run_failed',
1653
+ const ensured = await world.events.create(runId, {
1654
+ eventType: 'hook_received',
216
1655
  specVersion: SPEC_VERSION_CURRENT,
1656
+ correlationId: hookInput.hookId,
217
1657
  eventData: {
218
- error: {
219
- message: err.message,
220
- stack: err.stack,
221
- },
222
- errorCode: RUN_ERROR_CODES.RUNTIME_ERROR,
1658
+ token: hookInput.token,
1659
+ payload: hookInput.payload,
223
1660
  },
224
- }, { requestId });
1661
+ }, {
1662
+ requestId,
1663
+ occurredAt,
1664
+ resumeId: hookInput.resumeId,
1665
+ resumePayloadDigest: hookInput.payloadDigest,
1666
+ });
1667
+ // Consumer-side completion of the recovery path: this
1668
+ // replay materialized the event because the producer's
1669
+ // direct write had not landed in the preload.
1670
+ span?.setAttributes(Attribute.HookResilientResumeMaterialized(true));
1671
+ // The canonical event — whether this call committed it or
1672
+ // converged on the producer's concurrent write — so we can
1673
+ // splice it into the preloaded log instead of discarding
1674
+ // the preload (see below).
1675
+ //
1676
+ // Reconstruct `eventData` from `hookInput` rather than
1677
+ // trusting the POST response's payload: world-vercel posts
1678
+ // hook_received with `remoteRefBehavior: 'lazy'`, so the
1679
+ // returned event's payload is a RemoteRef *descriptor*, not
1680
+ // the serialized bytes replay needs. `hookInput` carries
1681
+ // the real token + payload bytes (they rode the queue
1682
+ // message), so splice those onto the returned event's
1683
+ // stable eventId/metadata.
1684
+ // The re-ensure always returns a `hook_received` event, so
1685
+ // the splice is safe. The cast is needed because spreading
1686
+ // the raw `Event` union and overriding `eventData` collapses
1687
+ // to a non-`hook_received` member (whose `eventData` is a
1688
+ // different shape); the object is a genuine `hook_received`
1689
+ // event by construction.
1690
+ const base = ensured.event;
1691
+ ensuredEvent = base
1692
+ ? {
1693
+ ...base,
1694
+ eventData: {
1695
+ token: hookInput.token,
1696
+ payload: hookInput.payload,
1697
+ },
1698
+ }
1699
+ : undefined;
225
1700
  }
226
- catch (failErr) {
227
- if (EntityConflictError.is(failErr) ||
228
- RunExpiredError.is(failErr)) {
1701
+ catch (err) {
1702
+ // A matching concurrent claim (same resumeId + digest) is
1703
+ // resolved as success server-side and never throws, so
1704
+ // anything caught here is a genuine terminal or transient
1705
+ // condition:
1706
+ //
1707
+ // - HookNotFound / RunExpired: the producer's direct write
1708
+ // already ended this resume's eligibility (the run went
1709
+ // terminal). There is nothing left to resume, so consume
1710
+ // the message and stop. Continuing to replay would be
1711
+ // wasted work — and, worse, would ack a delivery that may
1712
+ // carry the only copy of the payload.
1713
+ if (HookNotFoundError.is(err) ||
1714
+ RunExpiredError.is(err)) {
229
1715
  return;
230
1716
  }
231
- throw failErr;
1717
+ // - EntityConflict (and any other unexpected error): the
1718
+ // resumeId constraint exists but the matching event is
1719
+ // not yet observable — the producer's parallel write is
1720
+ // still in flight, or a redrive raced the claim. This is
1721
+ // transient: rethrow so the queue redelivers and a later
1722
+ // attempt converges on the committed event instead of
1723
+ // replaying (and acking) without the payload.
1724
+ throw err;
232
1725
  }
233
- return;
234
- }
235
- else {
236
- throw err;
237
- }
238
- }
239
- workflowStartedAt = +workflowRun.startedAt;
240
- span?.setAttributes({
241
- ...Attribute.WorkflowRunStatus(workflowRun.status),
242
- ...Attribute.WorkflowStartedAt(workflowStartedAt),
243
- });
244
- if (workflowRun.status !== 'running') {
245
- // Workflow has already completed or failed, so we can skip it
246
- runtimeLogger.info('Workflow already completed or failed, skipping', {
247
- workflowRunId: runId,
248
- status: workflowRun.status,
249
- });
250
- // TODO: for `cancel`, we actually want to propagate a WorkflowCancelled event
251
- // inside the workflow context so the user can gracefully exit. this is SIGTERM
252
- // TODO: furthermore, there should be a timeout or a way to force cancel SIGKILL
253
- // so that we actually exit here without replaying the workflow at all, in the case
254
- // the replaying the workflow is itself failing.
255
- return;
1726
+ // The run_started response preloaded the log BEFORE this
1727
+ // ensure, so it cannot include the hook_received. Rather
1728
+ // than discard the preload (which would cost a fresh
1729
+ // events.list round trip on the first replay iteration),
1730
+ // splice in the canonical event reconstructed above. It
1731
+ // carries a stable eventId, so `insertEventByEventId` keeps
1732
+ // it in ascending eventId order and is idempotent if a later
1733
+ // list re-observes it. Only when the World returns no event
1734
+ // do we fall back to reloading the complete log.
1735
+ if (eventLog.type !== 'loadAll' && ensuredEvent) {
1736
+ insertEventByEventId(eventLog.events, ensuredEvent);
1737
+ }
1738
+ else {
1739
+ eventLog = { type: 'loadAll' };
1740
+ }
1741
+ } // end else (re-ensure needed)
256
1742
  }
257
- // Load all events into memory before running.
258
- // If we got pre-loaded events from the run_started response,
259
- // skip the events.list round-trip to reduce TTFB.
260
- const events = preloadedEvents ??
261
- (await getAllWorkflowRunEvents(workflowRun.runId));
262
- // Check for any elapsed waits and create wait_completed events
263
- const now = Date.now();
264
- // Pre-compute completed correlation IDs for O(n) lookup instead of O(n²)
265
- const completedWaitIds = new Set(events
266
- .filter((e) => e.eventType === 'wait_completed')
267
- .map((e) => e.correlationId));
268
- // Collect all waits that need completion
269
- const waitsToComplete = events
270
- .filter((e) => e.eventType === 'wait_created' &&
271
- e.correlationId !== undefined &&
272
- !completedWaitIds.has(e.correlationId) &&
273
- now >= e.eventData.resumeAt.getTime())
274
- .map((e) => ({
275
- eventType: 'wait_completed',
276
- specVersion: SPEC_VERSION_CURRENT,
277
- correlationId: e.correlationId,
278
- }));
279
- // Create all wait_completed events
280
- for (const waitEvent of waitsToComplete) {
281
- try {
282
- const result = await world.events.create(runId, waitEvent, {
1743
+ // Resolve the encryption key for this run's deployment.
1744
+ // Used eagerly here since both workflow execution (input
1745
+ // hydration / hook payload decryption) and the run_failed
1746
+ // dehydrate path below need it. Memoized accessor: first
1747
+ // call triggers the actual fetch / HKDF derivation,
1748
+ // subsequent calls await the cached promise.
1749
+ const getEncryptionKey = memoizeEncryptionKey(world, workflowRun);
1750
+ const encryptionKey = await getEncryptionKey();
1751
+ // Invocation-scoped cache of VM-independent prepared payloads
1752
+ // and immutable final values. It survives the fresh workflow
1753
+ // VM created by each inline replay, but never crosses runs or
1754
+ // queue deliveries.
1755
+ const replayPayloadCache = new ReplayPayloadCache(encryptionKey);
1756
+ // The live VM parked at the previous boundary, when the
1757
+ // retention decision kept it. null this iteration cold-
1758
+ // replays. Invocation-scoped: dies with this delivery.
1759
+ let retainedSession = null;
1760
+ // Main replay loop
1761
+ // biome-ignore lint/correctness/noConstantCondition: intentional loop
1762
+ while (true) {
1763
+ loopIteration++;
1764
+ // Replay-budget check: bail out (retry or fail) if
1765
+ // non-step time within this invocation has exceeded
1766
+ // the configured budget. Step bodies are excluded
1767
+ // because replayBudget.pause()/resume() bracket every
1768
+ // `executeStep` call.
1769
+ if (replayBudget.isExhausted()) {
1770
+ await handleReplayBudgetExhausted({
1771
+ runId,
1772
+ workflowName,
283
1773
  requestId,
1774
+ attempt: metadata.attempt,
1775
+ limitMs: replayBudget.configuredLimitMs,
284
1776
  });
285
- // Add the event to the events array so the workflow can see it
286
- events.push(result.event);
287
- }
288
- catch (err) {
289
- if (EntityConflictError.is(err)) {
290
- runtimeLogger.info('Wait already completed, skipping', {
291
- workflowRunId: runId,
292
- correlationId: waitEvent.correlationId,
293
- });
294
- continue;
295
- }
296
- throw err;
1777
+ // Only the terminal attempt returns, after run_failed is
1778
+ // durable. Earlier attempts reject for queue redelivery.
1779
+ return;
297
1780
  }
298
- }
299
- // Resolve the encryption key for this run's deployment
300
- const rawKey = await world.getEncryptionKeyForRun?.(workflowRun);
301
- const encryptionKey = rawKey
302
- ? await importKey(rawKey)
303
- : undefined;
304
- // --- User code execution ---
305
- // Only errors from runWorkflow() (user workflow code) should
306
- // produce run_failed. Infrastructure errors (network, server)
307
- // must propagate to the queue handler for automatic retry.
308
- let workflowResult;
309
- try {
310
- workflowResult = await trace('workflow.replay', {}, async (replaySpan) => {
311
- replaySpan?.setAttributes({
312
- ...Attribute.WorkflowEventsCount(events.length),
1781
+ // Check timeout before replay
1782
+ if (Date.now() - invocationStartTime >=
1783
+ noInlineReplayAfterMs) {
1784
+ runtimeLogger.info('V2 timeout reached, re-scheduling workflow', {
1785
+ workflowRunId: runId,
1786
+ loopIteration,
1787
+ elapsedMs: Date.now() - invocationStartTime,
313
1788
  });
314
- return await runWorkflow(workflowCode, workflowRun, events, encryptionKey);
315
- });
316
- }
317
- catch (err) {
318
- // WorkflowSuspension is normal control flow — not an error
319
- if (WorkflowSuspension.is(err)) {
320
- const suspensionMessage = buildWorkflowSuspensionMessage(runId, err.stepCount, err.hookCount, err.waitCount);
321
- if (suspensionMessage) {
322
- runtimeLogger.debug(suspensionMessage);
323
- }
324
- const result = await handleSuspension({
325
- suspension: err,
326
- world,
327
- run: workflowRun,
328
- span,
329
- requestId,
1789
+ await queueMessage(world, getWorkflowQueueName(workflowName, namespace), {
1790
+ runId,
1791
+ traceCarrier: await nextTraceCarrier(),
1792
+ requestedAt: new Date(),
330
1793
  });
331
- if (result.timeoutSeconds !== undefined) {
332
- return { timeoutSeconds: result.timeoutSeconds };
333
- }
334
- // Suspension handled, no further work needed
335
1794
  return;
336
1795
  }
337
- // This is a user code error or a WorkflowRuntimeError
338
- // (e.g., corrupted event log). Fail the workflow run.
339
- // Record exception for OTEL error tracking
340
- if (err instanceof Error) {
341
- span?.recordException?.(err);
342
- }
343
- const normalizedError = await normalizeUnknownError(err);
344
- const errorName = normalizedError.name || getErrorName(err);
345
- const errorMessage = normalizedError.message;
346
- let errorStack = normalizedError.stack || getErrorStack(err);
347
- // Remap error stack using source maps to show original source locations
348
- if (errorStack) {
349
- const parsedName = parseWorkflowName(workflowName);
350
- const filename = parsedName?.moduleSpecifier || workflowName;
351
- errorStack = remapErrorStack(errorStack, filename, workflowCode);
352
- }
353
- // Classify the error: WorkflowRuntimeError indicates an
354
- // internal issue (corrupted event log, missing data);
355
- // everything else is a user code error.
356
- const errorCode = classifyRunError(err);
357
- runtimeLogger.error('Error while running workflow', {
358
- workflowRunId: runId,
359
- errorCode,
360
- errorName,
361
- errorStack,
362
- });
363
- // Fail the workflow run via event (event-sourced architecture)
1796
+ let replayStart = 0;
364
1797
  try {
365
- await world.events.create(runId, {
366
- eventType: 'run_failed',
1798
+ // --- QuickJS VM engine dispatch ---
1799
+ // The QuickJS engine (opt-in via WORKFLOW_VM=quickjs
1800
+ // or executionContext.workflowVm) is a self-contained
1801
+ // alternative to the node:vm inline-replay logic
1802
+ // below. It performs the same full event replay, but
1803
+ // runs the workflow code in a QuickJS WASM VM, queues
1804
+ // steps via the same combined route (so they hit
1805
+ // executeStep below on re-entry), and manages its own
1806
+ // run_completed / run_failed lifecycle for workflow
1807
+ // outcomes. When the QuickJS engine is in effect,
1808
+ // return immediately after dispatch.
1809
+ //
1810
+ // Deliberately INSIDE this try: engine failures that
1811
+ // escape the entrypoint (MaxEventsExceededError, a
1812
+ // WASM OOM at the memory ceiling, a bundle-eval
1813
+ // failure) must reach this loop's catch so they are
1814
+ // classified and recorded as run_failed — outside the
1815
+ // try they would nack the message and burn all queue
1816
+ // redeliveries before dying as
1817
+ // MAX_DELIVERIES_EXCEEDED. Transient world errors
1818
+ // still rethrow out of the catch for redelivery, same
1819
+ // as node-engine replay failures.
1820
+ if (useQuickJSVm(workflowRun)) {
1821
+ runtimeLogger.debug('Using QuickJS VM engine', {
1822
+ workflowRunId: runId,
1823
+ loopIteration,
1824
+ });
1825
+ // Under turbo, run_started is backgrounded. The
1826
+ // QuickJS entrypoint fetches the event log and
1827
+ // writes events directly, so wait for the run to be
1828
+ // durably started first — it does not thread the
1829
+ // turbo runReadyBarrier the way handleSuspension
1830
+ // does.
1831
+ await awaitRunReady();
1832
+ if (eventLog.type === 'loadAfter') {
1833
+ appendEventLog(eventLog, await loadWorkflowRunEvents(runId, eventLog.cursor));
1834
+ eventLog = { ...eventLog, type: 'ready' };
1835
+ }
1836
+ // Lazy import: the QuickJS entrypoint's import chain
1837
+ // embeds the base64 WASM binary + extensions
1838
+ // (~1.3 MB decoded at module scope). Loading it here
1839
+ // keeps that out of node-engine deployments entirely
1840
+ // — only the opt-in path pays, on first dispatch.
1841
+ const { runWorkflowWithQuickJS } = await import('./runtime/quickjs-entrypoint.js');
1842
+ const quickjsResult = await runWorkflowWithQuickJS({
1843
+ workflowCode,
1844
+ workflowName,
1845
+ workflowRun,
1846
+ preloadedEvents: eventLog.type === 'ready'
1847
+ ? eventLog.events
1848
+ : undefined,
1849
+ preloadedEventsComplete: eventLog.type === 'ready',
1850
+ runInput,
1851
+ parentSpan: span,
1852
+ maxEventsLimit,
1853
+ namespace,
1854
+ nextTraceCarrier,
1855
+ // Inline-step ownership plumbing: redeliveries of
1856
+ // this message drive crash recovery for steps an
1857
+ // earlier invocation claimed inline (see the
1858
+ // backstop pass in the entrypoint's loop), and
1859
+ // the message id is stamped as `ownerMessageId`
1860
+ // on inline lazy step claims so wake replays
1861
+ // defer to the in-flight body instead of
1862
+ // requeueing the step.
1863
+ deliveryAttempt: metadata.attempt,
1864
+ ownerMessageId: metadata.messageId,
1865
+ });
1866
+ if (quickjsResult?.timeoutSeconds !== undefined) {
1867
+ // Use `reinvoke` rather than returning
1868
+ // `{ timeoutSeconds }` directly: under turbo the
1869
+ // current message carries `runInput` and a
1870
+ // reschedule would re-engage turbo on redelivery
1871
+ // (replaying against a stale preloaded log and
1872
+ // wedging the run — see the reinvoke() docs
1873
+ // above). reinvoke enqueues an explicit
1874
+ // continuation without `runInput` in that case.
1875
+ return await reinvoke(quickjsResult.timeoutSeconds);
1876
+ }
1877
+ return;
1878
+ }
1879
+ if (eventLog.type !== 'ready') {
1880
+ const page = await loadWorkflowRunEvents(runId, eventLog.type === 'loadAfter'
1881
+ ? eventLog.cursor
1882
+ : undefined);
1883
+ if (eventLog.type === 'loadAfter') {
1884
+ appendEventLog(eventLog, page);
1885
+ eventLog = { ...eventLog, type: 'ready' };
1886
+ }
1887
+ else {
1888
+ eventLog = { ...page, type: 'ready' };
1889
+ }
1890
+ }
1891
+ assert(eventLog.type === 'ready');
1892
+ reportPreconditionRestartReload(eventLog.events);
1893
+ // Detect concurrent completion via the event log: if
1894
+ // any other handler wrote a terminal run event, exit
1895
+ // before doing replay work. The run entity's status is
1896
+ // derived from these events, so checking the log here
1897
+ // gives us the same signal as a runs.get() round-trip
1898
+ // without the extra request per loop iteration.
1899
+ if (hasRecordedTerminalRunEvent(eventLog.events, runId)) {
1900
+ return;
1901
+ }
1902
+ // Complete elapsed waits
1903
+ const now = Date.now();
1904
+ const completedWaitIds = new Set(eventLog.events
1905
+ .filter((e) => e.eventType === 'wait_completed')
1906
+ .map((e) => e.correlationId));
1907
+ const waitsToComplete = eventLog.events
1908
+ .filter((e) => e.eventType === 'wait_created' &&
1909
+ e.correlationId !== undefined &&
1910
+ !completedWaitIds.has(e.correlationId) &&
1911
+ now >= e.eventData.resumeAt.getTime())
1912
+ .map((e) => ({
1913
+ eventType: 'wait_completed',
367
1914
  specVersion: SPEC_VERSION_CURRENT,
1915
+ correlationId: e.correlationId,
368
1916
  eventData: {
369
- error: {
370
- message: errorMessage,
371
- stack: errorStack,
372
- },
373
- errorCode,
1917
+ resumeAt: e.eventData.resumeAt,
374
1918
  },
375
- }, { requestId });
1919
+ }));
1920
+ for (const waitEvent of waitsToComplete) {
1921
+ try {
1922
+ const created = await createEvent(waitEvent, {
1923
+ requestId,
1924
+ ...preconditionSnapshotParams(eventLog.events, eventLog.cursor),
1925
+ });
1926
+ // Bump-and-report: fold what this write skipped over
1927
+ // into the snapshot the remaining waits are guarded
1928
+ // against, so each asks for a slot above it.
1929
+ //
1930
+ // Only a complete answer. `hasMore` means the World
1931
+ // returned part of what it was asked for, and the
1932
+ // missing-completion check below is what decides
1933
+ // whether this handler still has to fetch. Folding in
1934
+ // a partial page would make the log look like it
1935
+ // holds the completion when the rest of the page is
1936
+ // still unread, so the fetch would be skipped on a
1937
+ // snapshot that is short of the World's.
1938
+ if (created.events?.length &&
1939
+ created.hasMore !== true) {
1940
+ mergeReportedEvents(eventLog.events, created.events);
1941
+ }
1942
+ }
1943
+ catch (err) {
1944
+ if (EntityConflictError.is(err)) {
1945
+ runtimeLogger.info('Wait already completed, skipping', {
1946
+ workflowRunId: runId,
1947
+ correlationId: waitEvent.correlationId,
1948
+ });
1949
+ continue;
1950
+ }
1951
+ throw err;
1952
+ }
1953
+ }
1954
+ assert(eventLog.type === 'ready');
1955
+ // The event list above may be stale by the time an
1956
+ // elapsed wait is committed, and this replay has to see
1957
+ // its own wait_completed before it can advance past the
1958
+ // sleep. Each write asked the World for the delta since
1959
+ // our cursor and folded it in (see createEvent), so a
1960
+ // supporting World has already handed those events back
1961
+ // and there is nothing left to do. Only fetch for the
1962
+ // completions still missing locally: a World that
1963
+ // ignores `sinceCursor`, a truncated delta, a concurrent
1964
+ // absorb that lost the cursor race, or an
1965
+ // EntityConflictError, whose rejection carries no delta.
1966
+ const completedWaitIdsAfterWrites = new Set(eventLog.events
1967
+ .filter((e) => e.eventType === 'wait_completed')
1968
+ .map((e) => e.correlationId));
1969
+ const missingWaitCompletions = waitsToComplete.filter((waitEvent) => !completedWaitIdsAfterWrites.has(waitEvent.correlationId));
1970
+ if (missingWaitCompletions.length > 0) {
1971
+ // Load only events after the original snapshot cursor
1972
+ // so concurrent durable events, such as hook_received,
1973
+ // keep their ordering relative to wait_completed. Fall
1974
+ // back to a full reload for older worlds that cannot
1975
+ // give us a stable cursor, or if the cursor delta does
1976
+ // not include the wait completion this handler just
1977
+ // attempted.
1978
+ if (eventLog.cursor) {
1979
+ const page = await loadWorkflowRunEvents(runId, eventLog.cursor);
1980
+ const completedWaitIdsAfterCursor = new Set(page.events
1981
+ .filter((e) => e.eventType === 'wait_completed')
1982
+ .map((e) => e.correlationId));
1983
+ const sawAllWaitCompletions = missingWaitCompletions.every((waitEvent) => completedWaitIdsAfterCursor.has(waitEvent.correlationId));
1984
+ if (sawAllWaitCompletions) {
1985
+ appendEventLog(eventLog, page);
1986
+ }
1987
+ else {
1988
+ eventLog = {
1989
+ ...(await loadWorkflowRunEvents(runId)),
1990
+ type: 'ready',
1991
+ };
1992
+ }
1993
+ }
1994
+ else {
1995
+ eventLog = {
1996
+ ...(await loadWorkflowRunEvents(runId)),
1997
+ type: 'ready',
1998
+ };
1999
+ }
2000
+ }
2001
+ // A replay reads the log as the complete record of what
2002
+ // has happened, so a position nothing occupies is
2003
+ // indistinguishable from an event that never occurred and
2004
+ // the branch it would have decided gets decided the other
2005
+ // way. Failing here is the difference between a run that
2006
+ // reports its own corruption and one that silently
2007
+ // returns the wrong answer.
2008
+ //
2009
+ // A hole that is merely a write mid-commit fills in on
2010
+ // its own, so settleEventSlotGap re-reads before
2011
+ // concluding, and adopts whichever log it settled on.
2012
+ if (isSlotGapCheckEnabled()) {
2013
+ const settled = await settleEventSlotGap(runId, {
2014
+ events: eventLog.events,
2015
+ cursor: eventLog.cursor,
2016
+ });
2017
+ eventLog = { ...settled.log, type: 'ready' };
2018
+ if (settled.gap !== undefined) {
2019
+ throw new CorruptedEventLogError(`Event log for run ${runId} has a hole at slot ${settled.gap.firstMissingSlot}: ${settled.gap.missingCount} of the ${settled.gap.maxSlot} slots up to the log's maximum hold no event.`);
2020
+ }
2021
+ }
2022
+ // Completing elapsed waits refreshes the event snapshot.
2023
+ // A concurrent handler may have written the terminal run
2024
+ // event after the initial snapshot but before this
2025
+ // replay. Once the event log records that outcome, this
2026
+ // delivery is done.
2027
+ if (hasRecordedTerminalRunEvent(eventLog.events, runId)) {
2028
+ return;
2029
+ }
2030
+ // Event-limit guard: fail a runaway run once its log
2031
+ // reaches the server-supplied ceiling (undefined ⇒ no
2032
+ // enforcement). The throw is caught below and written as
2033
+ // run_failed / MAX_EVENTS_EXCEEDED.
2034
+ if (maxEventsLimit !== undefined &&
2035
+ eventLog.events.length >= maxEventsLimit) {
2036
+ throw new MaxEventsExceededError(eventLog.events.length, maxEventsLimit);
2037
+ }
2038
+ // Latency telemetry: judge TTFS eligibility against the
2039
+ // invocation's first snapshot. Waits completed above
2040
+ // would already disqualify via the event-type check, so
2041
+ // evaluating after the wait pass is equivalent.
2042
+ // attr_set is permitted: a redelivery can land after a
2043
+ // committed pre-step attr_set, and the detour it marks
2044
+ // is subtracted via preStepAttrStartMs regardless of
2045
+ // which invocation wrote it (see runtime/step-latency.ts).
2046
+ invocationStartedClean ??= eventLog.events.every((e) => e.eventType === 'run_created' ||
2047
+ e.eventType === 'run_started' ||
2048
+ e.eventType === 'attr_set');
2049
+ runtimeLogger.debug('Starting workflow execution', {
2050
+ workflowRunId: runId,
2051
+ loopIteration,
2052
+ eventCount: eventLog.events.length,
2053
+ executionMode: retainedSession ? 'retained' : 'replay',
2054
+ });
2055
+ replayStart = Date.now();
2056
+ // Start every missing decrypt/decompress operation up
2057
+ // front (already-prepared payloads are skipped). Web
2058
+ // Crypto work overlaps VM setup on the replay path and
2059
+ // the appended events' consumption on the resume path;
2060
+ // consumers still deserialize and resolve in event order.
2061
+ const payloadPrewarm = replayPayloadCache.prewarm(workflowRun, eventLog.events);
2062
+ let workflowResult = retainedSession
2063
+ ? await resumeWorkflow(retainedSession, eventLog.events)
2064
+ : { type: 'replay' };
2065
+ if (workflowResult.type === 'replay') {
2066
+ retainedSession = null;
2067
+ workflowResult = await replayWorkflow({
2068
+ workflowCode,
2069
+ workflowRun,
2070
+ events: eventLog.events,
2071
+ encryptionKey,
2072
+ replayPayloadCache,
2073
+ // Turbo: the end-of-run drain inside workflow
2074
+ // execution commits fire-and-forget `*_created`
2075
+ // events before the terminal `awaitRunReady()` below.
2076
+ runReadyBarrier,
2077
+ worldCapabilities: world.capabilities,
2078
+ });
2079
+ }
2080
+ await payloadPrewarm;
2081
+ if (workflowResult.type === 'suspended') {
2082
+ // Park the live session; the suspension catch below
2083
+ // makes the one retention decision — keep it for the
2084
+ // next iteration or discard it for a fresh replay.
2085
+ retainedSession = workflowResult.session;
2086
+ throw workflowResult.suspension;
2087
+ }
2088
+ const result = workflowResult.output;
2089
+ runtimeLogger.debug('Workflow execution completed', {
2090
+ workflowRunId: runId,
2091
+ loopIteration,
2092
+ replayMs: Date.now() - replayStart,
2093
+ executionMode: retainedSession ? 'retained' : 'replay',
2094
+ });
2095
+ replayRecoveryReporter.activate();
2096
+ // Workflow completed. Send the snapshot but do NOT
2097
+ // reload-and-retry the create in place: `result` was
2098
+ // computed by this replay, so a stale (412) rejection must
2099
+ // force a *fresh replay* (which may observe the new event
2100
+ // and produce a different result), not re-commit the stale
2101
+ // result. The catch below restarts the replay in-process.
2102
+ try {
2103
+ // Turbo: a workflow that finishes with no steps reaches
2104
+ // here before the backgrounded run_started; order the
2105
+ // terminal write after it so the run exists.
2106
+ await awaitRunReady();
2107
+ await createEvent({
2108
+ eventType: 'run_completed',
2109
+ specVersion: SPEC_VERSION_CURRENT,
2110
+ eventData: { output: result },
2111
+ }, {
2112
+ requestId,
2113
+ ...preconditionSnapshotParams(eventLog.events, eventLog.cursor),
2114
+ });
2115
+ }
2116
+ catch (err) {
2117
+ if (EntityConflictError.is(err) ||
2118
+ RunExpiredError.is(err)) {
2119
+ runtimeLogger.info('Tried completing workflow run, but run has already finished.', { workflowRunId: runId, message: err.message });
2120
+ return;
2121
+ }
2122
+ throw err;
2123
+ }
2124
+ span?.setAttributes({
2125
+ ...Attribute.WorkflowRunStatus('completed'),
2126
+ });
2127
+ return;
376
2128
  }
377
- catch (failErr) {
378
- if (EntityConflictError.is(failErr) ||
379
- RunExpiredError.is(failErr)) {
380
- runtimeLogger.info('Tried failing workflow run, but run has already finished.', {
2129
+ catch (err) {
2130
+ if (WorkflowSuspension.is(err)) {
2131
+ replayRecoveryReporter.activate();
2132
+ // Synchronous workflow-execution duration for THIS
2133
+ // suspension only — anchors the `finalSchedulingReplay`
2134
+ // telemetry field below (see
2135
+ // StepLatencyTracking.replayMs). This is the FINAL
2136
+ // replay pass, the one that reached and scheduled the
2137
+ // first step: valid rsfs paths can replay more than
2138
+ // once before the first step (e.g. a workflow-body
2139
+ // `setAttributes()` detour replays twice), and a
2140
+ // redelivery omits earlier invocations' replay work
2141
+ // entirely. This value is NOT accumulated across
2142
+ // those earlier passes, so it must not be read as
2143
+ // "the replay portion of rsfs" — rsfs covers the
2144
+ // whole run_started-to-first-step window;
2145
+ // finalSchedulingReplay covers only this last pass.
2146
+ // Captured here, before `handleSuspension`'s awaited
2147
+ // I/O, so it excludes that I/O.
2148
+ //
2149
+ // This duplicates what OTEL already captures on the
2150
+ // run/invocation span, but is collected as client
2151
+ // telemetry so the server can emit it as an
2152
+ // UNSAMPLED, full-population metric: workflow-server's
2153
+ // server spans are heavily sampled in production
2154
+ // (~7%), and client spans can't be filtered by SDK
2155
+ // version, so neither can serve as the dashboard's
2156
+ // exact TTFS decomposition. On a retained-VM
2157
+ // resume this measures the resume (typically ~0ms),
2158
+ // not a replay, so the field's distribution is
2159
+ // bimodal once retention is active.
2160
+ const replayDurationMs = Date.now() - replayStart;
2161
+ runtimeLogger.debug('Workflow suspended', {
381
2162
  workflowRunId: runId,
382
- message: failErr.message,
2163
+ loopIteration,
2164
+ replayMs: replayDurationMs,
2165
+ steps: err.stepCount,
2166
+ hooks: err.hookCount,
2167
+ waits: err.waitCount,
2168
+ });
2169
+ const suspensionMessage = buildWorkflowSuspensionMessage(err.stepCount, err.hookCount, err.waitCount);
2170
+ if (suspensionMessage) {
2171
+ runtimeLogger.debug(suspensionMessage);
2172
+ }
2173
+ // V2: handle suspension without queuing steps.
2174
+ // Each event creation inside handleSuspension carries the
2175
+ // precondition snapshot of the loaded event log, so a
2176
+ // backend holding an event this replay never saw rejects
2177
+ // the write (412) instead of accepting a divergent one.
2178
+ // The rejection is handled here, by restarting the
2179
+ // replay — never by re-posting the same event.
2180
+ const suspensionStart = Date.now();
2181
+ assert(eventLog.type === 'ready', 'Workflow suspended before its event log was loaded');
2182
+ let suspensionResult;
2183
+ try {
2184
+ suspensionResult = await handleSuspension({
2185
+ suspension: err,
2186
+ world,
2187
+ run: workflowRun,
2188
+ span,
2189
+ requestId,
2190
+ eventLog,
2191
+ runReadyBarrier,
2192
+ replayRecoveryReporter,
2193
+ });
2194
+ }
2195
+ catch (suspensionError) {
2196
+ // A suspension create was rejected as stale: re-derive
2197
+ // the replay from a corrected log in this invocation.
2198
+ // Once the in-process budget is spent, fall back to an
2199
+ // explicit immediate re-invocation (a rethrow relies
2200
+ // on redelivery of a message the turbo path already
2201
+ // acked — the run would stall for the queue's ~300s
2202
+ // default visibility timeout).
2203
+ if (PreconditionFailedError.is(suspensionError)) {
2204
+ if (restartReplayInProcess('suspension-create', suspensionError)) {
2205
+ continue;
2206
+ }
2207
+ const escalation = await reinvokeAfterStaleRejection('suspension-create', suspensionError);
2208
+ if (escalation.reinvoked)
2209
+ return escalation.result;
2210
+ // Per-run budget spent: fail the run rather than
2211
+ // hand it back to the queue to spin again.
2212
+ throw escalation.error;
2213
+ }
2214
+ if (!FatalError.is(suspensionError)) {
2215
+ // Transient failures propagate to the queue
2216
+ // handler so the message is redelivered.
2217
+ throw suspensionError;
2218
+ }
2219
+ // Non-retryable failure while committing the
2220
+ // suspension's events — e.g. an attribute write
2221
+ // the World rejected as invalid (the cumulative
2222
+ // per-run cap can only be checked World-side).
2223
+ // Redelivery would replay the workflow into the
2224
+ // same write and the same rejection, so fail the
2225
+ // run with the error instead of wedging the
2226
+ // message in redelivery.
2227
+ const errorCode = classifyRunError(suspensionError);
2228
+ runtimeLogger.error('Non-retryable error while committing workflow suspension; failing run', {
2229
+ workflowRunId: runId,
2230
+ errorCode,
2231
+ errorName: suspensionError.name,
2232
+ errorMessage: suspensionError.message,
2233
+ });
2234
+ try {
2235
+ // Turbo: order the terminal write after the
2236
+ // backgrounded run_started so the run exists.
2237
+ await awaitRunReady();
2238
+ await createEvent({
2239
+ eventType: 'run_failed',
2240
+ specVersion: SPEC_VERSION_CURRENT,
2241
+ eventData: {
2242
+ error: await dehydrateRunError(suspensionError, runId, encryptionKey, globalThis, (workflowRun?.specVersion ?? 0) >=
2243
+ SPEC_VERSION_SUPPORTS_COMPRESSION),
2244
+ errorCode,
2245
+ },
2246
+ }, { requestId });
2247
+ }
2248
+ catch (failErr) {
2249
+ if (EntityConflictError.is(failErr) ||
2250
+ RunExpiredError.is(failErr)) {
2251
+ runtimeLogger.info('Tried failing workflow run, but run has already finished.', {
2252
+ workflowRunId: runId,
2253
+ message: failErr.message,
2254
+ });
2255
+ return;
2256
+ }
2257
+ throw failErr;
2258
+ }
2259
+ span?.setAttributes({
2260
+ ...Attribute.WorkflowRunStatus('failed'),
2261
+ ...Attribute.WorkflowErrorCode(errorCode),
2262
+ ...Attribute.WorkflowErrorName(suspensionError.name),
2263
+ ...Attribute.WorkflowErrorMessage(suspensionError.message),
2264
+ ...Attribute.ErrorType(suspensionError.name),
2265
+ });
2266
+ return;
2267
+ }
2268
+ if (suspensionResult.reportedEventCount > 0) {
2269
+ // Bump-and-report merged events BELOW the tail and
2270
+ // re-sorted the array to slot order, shifting every
2271
+ // position the prewarm scan had already recorded.
2272
+ // The cursor is deliberately left alone: the report
2273
+ // is a lower bound on what was skipped, so the next
2274
+ // incremental read still has to cover the same range.
2275
+ replayPayloadCache.resetScan();
2276
+ }
2277
+ // Open hooks/waits in the log as loaded for this
2278
+ // replay. This suspension's own hook/wait writes are
2279
+ // NOT in it — they never reach retention anyway,
2280
+ // because a suspension containing a non-step item
2281
+ // fails canRetainWorkflowSession's type check before
2282
+ // the scan is consulted. Computed
2283
+ // lazily, at most once, and shared between the
2284
+ // retention decision here and the delta/turbo gates
2285
+ // below — the attr-detour and hook-conflict paths
2286
+ // return/continue before the gates and usually
2287
+ // short-circuit before ever scanning the log.
2288
+ const openHookWait = once(() => {
2289
+ assert(eventLog.type === 'ready');
2290
+ return openHookAndWaitState(eventLog.events);
383
2291
  });
2292
+ // The single retention decision: keep the parked
2293
+ // session only across a pure step boundary with no
2294
+ // out-of-band continuation source and provably
2295
+ // passive step inputs.
2296
+ if (retainedSession &&
2297
+ !canRetainWorkflowSession(err, suspensionResult.retainedStepInputsSafe, openHookWait)) {
2298
+ retainedSession = null;
2299
+ }
2300
+ preStepBlockingMs += suspensionResult.hookCreationMs;
2301
+ if (suspensionResult.hasAttributeEvents &&
2302
+ preStepBlockingBeforeAttrMs === undefined) {
2303
+ preStepBlockingBeforeAttrMs = preStepBlockingMs;
2304
+ }
2305
+ runtimeLogger.debug('Suspension handled', {
2306
+ workflowRunId: runId,
2307
+ suspensionMs: Date.now() - suspensionStart,
2308
+ pendingSteps: suspensionResult.pendingSteps.length,
2309
+ timeoutSeconds: suspensionResult.waitTimeout?.seconds,
2310
+ hasHookConflict: suspensionResult.hasHookConflict,
2311
+ hasAwaitedHookCreation: suspensionResult.hasAwaitedHookCreation,
2312
+ hasAttributeEvents: suspensionResult.hasAttributeEvents,
2313
+ });
2314
+ // Hook conflict: break loop, re-invoke via queue
2315
+ if (suspensionResult.hasHookConflict) {
2316
+ return await reinvoke(0);
2317
+ }
2318
+ // Native workflow attribute events are resolved
2319
+ // through replay: the next loop iteration reloads the
2320
+ // log (now holding the just-committed attr_set) and
2321
+ // replays, resolving the setAttributes promise. Skip
2322
+ // step processing for this pass so that replay decides
2323
+ // races first — in Promise.race([setAttributes(),
2324
+ // step()]), the durable attribute event must be able
2325
+ // to win without executing the losing step. The replay
2326
+ // happens in-process rather than via a queue
2327
+ // re-invocation: unlike hooks and waits, an attr_set
2328
+ // introduces no out-of-band invocation source that the
2329
+ // handler would need to yield the message for, so
2330
+ // paying a delivery round-trip here would only add
2331
+ // latency before the workflow's next step.
2332
+ if (suspensionResult.hasAttributeEvents) {
2333
+ eventLog = nextEventLogLoad(eventLog);
2334
+ continue;
2335
+ }
2336
+ const pendingSteps = suspensionResult.pendingSteps;
2337
+ // Inline execution is gated on ownership. The
2338
+ // suspension handler deferred the step_created write for
2339
+ // up to `getMaxInlineSteps()` steps (`lazyInlineSteps`)
2340
+ // so we can run them inline — in parallel — via lazy
2341
+ // `step_started` events that create each step on the fly,
2342
+ // saving one world round-trip per inline step. Ownership
2343
+ // is still atomic and exactly-one per step: the world's
2344
+ // create-claim inside each step_started returns
2345
+ // `EntityConflictError` (→ executeStep `skipped`) to any
2346
+ // concurrent loser, so only one handler ever runs a given
2347
+ // body. Every other pending step keeps its eager
2348
+ // step_created (in `createdStepCorrelationIds`) and is
2349
+ // queued below.
2350
+ //
2351
+ // The suspension handler only designates
2352
+ // `lazyInlineSteps` when no `hook.getConflict()` awaiter
2353
+ // is present. That awaiter case must execute nothing
2354
+ // inline: an inline `await executeStep(...)` blocks this
2355
+ // handler for the full step duration, so the awaiter's
2356
+ // continuation (which only advances on the next replay)
2357
+ // would be serialized behind the step — defeating work
2358
+ // the workflow expressed as parallel (e.g.
2359
+ // `hook.getConflict().then(() => stepB())` racing `await
2360
+ // stepA()`). In that case `lazyInlineSteps` is empty and
2361
+ // every step is queued for re-invocation, which replays
2362
+ // over the just-committed hook_created and resolves the
2363
+ // awaiter while queued steps run in parallel invocations.
2364
+ const lazyInlineSteps = suspensionResult.lazyInlineSteps;
2365
+ const inlineCorrelationIds = new Set(lazyInlineSteps.map((s) => s.correlationId));
2366
+ // Unified queue dispatch for everything we are NOT
2367
+ // inline-executing. Steps are queued with stepId so
2368
+ // the receiver runs them; the wait timer is queued
2369
+ // as a generic continuation that fires after the
2370
+ // wait elapses and lets the next replay observe the
2371
+ // elapsed wait via the "complete elapsed waits"
2372
+ // pass.
2373
+ //
2374
+ // Step dispatch decision table (per pending step not
2375
+ // designated lazy-inline):
2376
+ //
2377
+ // - Inline-owned, owner === this message →
2378
+ // execute in THIS invocation (owned recovery: a
2379
+ // redelivery of the owning message re-executes
2380
+ // the step it crashed on, via a payload-less
2381
+ // step_started re-stamped with its
2382
+ // ownerMessageId — not a bare start).
2383
+ // - Inline-owned, owner !== this message →
2384
+ // ensure a DELAYED backstop wake exists
2385
+ // (delaySeconds = ownership lease remaining)
2386
+ // instead of enqueueing the step. The owning
2387
+ // invocation is (likely) still running the body;
2388
+ // an immediate step message would bare-start the
2389
+ // running step and execute it a second time
2390
+ // (workflow#2780). The backstop is a plain run
2391
+ // continuation, NOT a step message: when it
2392
+ // fires, this same decision table handles
2393
+ // whatever state the step is in by then
2394
+ // (terminal → nothing pending; queue-owned after
2395
+ // step_retrying → normal keyed dispatch; owner
2396
+ // dead with lease expired → immediate dispatch,
2397
+ // preserving step-level failure semantics for
2398
+ // poison steps; lease refreshed by owner
2399
+ // recovery → re-arm). The backstop's
2400
+ // idempotencyKey is scoped to the ownership
2401
+ // EPOCH (latest step_started timestamp), NOT
2402
+ // just the correlation ID, and must never be
2403
+ // the step message's own key — see
2404
+ // backstopIdempotencyKey for both invariants
2405
+ // (fixed keys either absorb the retry handoff
2406
+ // or dedupe the refreshed-lease re-arm against
2407
+ // the in-flight backstop itself).
2408
+ // - Not owned (never stamped / eager / ownership
2409
+ // lapsed at step_retrying / lease expired /
2410
+ // kill-switched) → immediate enqueue, exactly as
2411
+ // before. This covers crash recovery: if a prior
2412
+ // handler wrote step_created but crashed before
2413
+ // queueing, a later handler queues it;
2414
+ // idempotencyKey on correlationId dedupes
2415
+ // redundant queues across concurrent handlers.
2416
+ //
2417
+ // The wait continuation is what makes
2418
+ // `Promise.race(step, sleep)` behave correctly with
2419
+ // inline step execution: even if the inline step
2420
+ // blocks this handler for the full step duration,
2421
+ // the wait timer fires in a separate function
2422
+ // invocation. If the sleep wins, that parallel
2423
+ // invocation completes the run; if the step wins,
2424
+ // the wait continuation fires later and no-ops on
2425
+ // the terminal run.
2426
+ //
2427
+ // The continuation's delay is clamped to the
2428
+ // maximum queue delay (long waits chain across
2429
+ // multiple hops) and its idempotency key dedupes
2430
+ // re-observations of the same pending wait across
2431
+ // suspension passes — see
2432
+ // runtime/wait-continuation.ts for the full
2433
+ // delay/key selection rationale.
2434
+ const traceCarrier = await nextTraceCarrier();
2435
+ const dispatches = [];
2436
+ const inlineOwnership = isInlineOwnershipEnabled();
2437
+ const dispatchNowMs = Date.now();
2438
+ const ownedRecoverySteps = [];
2439
+ let backstopWakesArmed = 0;
2440
+ for (const step of pendingSteps) {
2441
+ if (inlineCorrelationIds.has(step.correlationId)) {
2442
+ continue;
2443
+ }
2444
+ const ownershipActive = inlineOwnership && isStepOwnershipActive(step);
2445
+ if (ownershipActive &&
2446
+ step.ownerMessageId === metadata.messageId) {
2447
+ // Owned recovery: this delivery IS the owning
2448
+ // message; re-execute the step in this
2449
+ // invocation instead of queueing it.
2450
+ ownedRecoverySteps.push(step);
2451
+ continue;
2452
+ }
2453
+ // Delayed backstop wake while another invocation's
2454
+ // ownership lease is live; immediate step enqueue
2455
+ // otherwise (lease expired ⇒ remaining 0 ⇒ same as
2456
+ // today, which is also the degraded mode for
2457
+ // worlds with unstable message IDs — the owner
2458
+ // check above never matches there).
2459
+ const backstopDelaySeconds = ownershipActive
2460
+ ? stepLeaseRemainingSeconds(step, dispatchNowMs)
2461
+ : 0;
2462
+ if (backstopDelaySeconds > 0) {
2463
+ backstopWakesArmed++;
2464
+ runtimeLogger.debug('Pending step is inline-owned by a live invocation; ensuring delayed backstop wake instead of immediate requeue', {
2465
+ workflowRunId: runId,
2466
+ stepId: step.correlationId,
2467
+ ownerMessageId: step.ownerMessageId,
2468
+ backstopDelaySeconds,
2469
+ });
2470
+ dispatches.push(queueMessage(world, getWorkflowQueueName(workflowName, namespace), {
2471
+ runId,
2472
+ traceCarrier,
2473
+ requestedAt: new Date(),
2474
+ }, {
2475
+ delaySeconds: backstopDelaySeconds,
2476
+ idempotencyKey: backstopIdempotencyKey(step),
2477
+ }));
2478
+ continue;
2479
+ }
2480
+ dispatches.push(queueMessage(world, getWorkflowQueueName(workflowName, namespace), {
2481
+ runId,
2482
+ stepId: step.correlationId,
2483
+ stepName: step.stepName,
2484
+ traceCarrier,
2485
+ requestedAt: new Date(),
2486
+ }, {
2487
+ idempotencyKey: step.correlationId,
2488
+ }));
2489
+ }
2490
+ if (suspensionResult.waitTimeout) {
2491
+ dispatches.push(queueMessage(world, getWorkflowQueueName(workflowName, namespace), {
2492
+ runId,
2493
+ traceCarrier,
2494
+ requestedAt: new Date(),
2495
+ }, getWaitContinuationDispatch(suspensionResult.waitTimeout.seconds, suspensionResult.waitTimeout.correlationId)));
2496
+ }
2497
+ await Promise.all(dispatches);
2498
+ // The set of steps THIS invocation executes: the
2499
+ // deferred lazy-inline batch plus any owned-recovery
2500
+ // steps (this message's redelivery re-executing a
2501
+ // step it crashed on — no lazyStepInput; the input
2502
+ // hydrates from the step entity like the background
2503
+ // path, and the payload-less step_started re-stamps
2504
+ // ownership — unlike the background path's start it
2505
+ // is NOT bare: it carries this message's
2506
+ // ownerMessageId, which is also what the
2507
+ // owned-recovery retry ceiling counts).
2508
+ const inlineExecutions = [
2509
+ ...lazyInlineSteps.map((s) => ({
2510
+ correlationId: s.correlationId,
2511
+ stepName: s.stepName,
2512
+ lazyStepInput: s.dehydratedInput,
2513
+ })),
2514
+ ...ownedRecoverySteps.map((s) => ({
2515
+ correlationId: s.correlationId,
2516
+ stepName: s.stepName,
2517
+ })),
2518
+ ];
2519
+ // Ownership telemetry (design doc Phase 7): span
2520
+ // attributes so production traces show when crash
2521
+ // recovery ran or a wake was converted into a
2522
+ // backstop, and a warn (always printed, unlike
2523
+ // debug/info) for owned recovery — it means a prior
2524
+ // delivery of this message died mid-step-body.
2525
+ if (backstopWakesArmed > 0 ||
2526
+ ownedRecoverySteps.length > 0) {
2527
+ span?.setAttributes({
2528
+ ...(ownedRecoverySteps.length > 0
2529
+ ? Attribute.WorkflowOwnedRecoverySteps(ownedRecoverySteps.length)
2530
+ : {}),
2531
+ ...(backstopWakesArmed > 0
2532
+ ? Attribute.WorkflowBackstopWakesArmed(backstopWakesArmed)
2533
+ : {}),
2534
+ });
2535
+ }
2536
+ if (ownedRecoverySteps.length > 0) {
2537
+ runtimeLogger.warn('Re-executing inline steps owned by this queue message — a previous delivery crashed mid-body and this redelivery is recovering them', {
2538
+ workflowRunId: runId,
2539
+ stepIds: ownedRecoverySteps.map((s) => s.correlationId),
2540
+ });
2541
+ }
2542
+ // Nothing to execute inline — everything has been
2543
+ // queued (or no work needs scheduling). Exit and let
2544
+ // the queue drive subsequent replays.
2545
+ if (inlineExecutions.length === 0) {
2546
+ // A `hook.getConflict()` awaiter needs an immediate
2547
+ // re-invocation: the replay consumes the
2548
+ // just-committed hook_created and resolves the
2549
+ // awaiter. Without it (no inline step, all work
2550
+ // queued or none pending) the run would sit idle
2551
+ // until some unrelated message woke it.
2552
+ if (suspensionResult.hasAwaitedHookCreation) {
2553
+ return await reinvoke(0);
2554
+ }
2555
+ return;
2556
+ }
2557
+ // Open hooks/waits are consulted by all three gates
2558
+ // below; resolve the memoized scan once here.
2559
+ const openHookWaitState = openHookWait.value;
2560
+ // Inline-delta fast path gate. We request the delta —
2561
+ // and on the next iteration consume it in place of the
2562
+ // events.list — only when ALL hold:
2563
+ //
2564
+ // - We have a real prior cursor to diff against (a
2565
+ // World may return none on the initial load).
2566
+ // - This is the clean single-step sequential case:
2567
+ // this suspension produced exactly one step and no
2568
+ // waits (`err.{step,wait}Count`), that one step is
2569
+ // the lone pending step (`pendingSteps.length === 1`)
2570
+ // and the lone inline step
2571
+ // (`lazyInlineSteps.length === 1` — no parallel
2572
+ // siblings queued to background handlers, and no other
2573
+ // inline step writing its own events out of band).
2574
+ // - No pending wait timer from THIS suspension, and no
2575
+ // open wait in the cumulative log: a concurrent
2576
+ // `wait_completed` landing after the delta snapshot
2577
+ // does not bump the outside-event marker, so nothing
2578
+ // fences a replay from the stale delta.
2579
+ // - No open (or this-suspension-created) hook — UNLESS
2580
+ // the precondition guard is enabled AND the World
2581
+ // declares it actually enforces the guard
2582
+ // (`capabilities.preconditionGuard`; the env flag
2583
+ // alone only makes the runtime SEND snapshots, which
2584
+ // an unsupporting backend ignores — no fence). The
2585
+ // delta snapshots the log at the step_completed
2586
+ // write but is consumed on the next replay, so an
2587
+ // out-of-band `hook_received` landing in that window
2588
+ // is absent from the delta and observed one
2589
+ // iteration later than a real fetch would observe
2590
+ // it. That staleness is qualitatively the same
2591
+ // read-to-write race the fetch path already has (an
2592
+ // event can land right after `events.list` returns
2593
+ // and before the suspension's writes); with an
2594
+ // enforced guard it is also fenced: `hook_received`
2595
+ // bumps the per-run outside-event marker, so every
2596
+ // durable write the stale replay attempts is
2597
+ // rejected with 412 — its guarded suspension creates
2598
+ // (retried over the reloaded log, or exhausted into
2599
+ // a queue re-invocation), AND the lazy step_started
2600
+ // claim of its next inline step, which carries the
2601
+ // snapshot too (threaded below via
2602
+ // `stateUpdatedAt`; on rejection the batch is
2603
+ // abandoned and re-invoked for a fresh replay, so a
2604
+ // stale view can never commit a step). Hooks created
2605
+ // by THIS suspension are inside the delta (their
2606
+ // `hook_created` lands before the step-terminal
2607
+ // write), so only their `hook_received` responses
2608
+ // are subject to the same fenced window. Without an
2609
+ // enforced guard there is no fence, so keep the
2610
+ // conservative gate.
2611
+ // - With no hook or wait open at all, the only
2612
+ // out-of-band writer is cancellation, which is safe
2613
+ // to observe one iteration late. See
2614
+ // openHookAndWaitState.
2615
+ //
2616
+ // When more than one step runs inline, each writes its
2617
+ // own events and the per-write delta would be partial, so
2618
+ // the delta is not requested (the gate below is false for
2619
+ // multi-step) and the next iteration does a normal fetch.
2620
+ // Whether the precondition guard is actually in force:
2621
+ // enabled by env AND enforced by the World. The env
2622
+ // flag alone only makes the runtime send snapshots,
2623
+ // which an unsupporting backend ignores (no fence).
2624
+ const guardEnforced = isPreconditionGuardEnabled() &&
2625
+ world.capabilities?.preconditionGuard === true;
2626
+ const requestInlineDelta = typeof eventLog.cursor === 'string' &&
2627
+ err.stepCount === 1 &&
2628
+ err.waitCount === 0 &&
2629
+ pendingSteps.length === 1 &&
2630
+ lazyInlineSteps.length === 1 &&
2631
+ ownedRecoverySteps.length === 0 &&
2632
+ !suspensionResult.waitTimeout &&
2633
+ !openHookWaitState.openWait &&
2634
+ (guardEnforced ||
2635
+ (err.hookCount === 0 &&
2636
+ !openHookWaitState.openHook));
2637
+ // Stale-sensitive batch: a hook is open in the run (or
2638
+ // was created by this suspension, so its hook_received
2639
+ // can land any moment) — an out-of-band event can make
2640
+ // the view this batch was scheduled from stale. With
2641
+ // the guard in force, the fence rejects a stale
2642
+ // claim's durable writes — but it cannot un-run a step
2643
+ // BODY that optimistic start began before the claim
2644
+ // settled. Suppress optimistic start for these batches
2645
+ // (take await-then-run) so a 412-fenced step never
2646
+ // executes user code at all: the fence then covers
2647
+ // side effects, not just the event log. Costs one
2648
+ // claim round-trip per step while a hook is open, only
2649
+ // on guard-enforcing deployments. Without the guard
2650
+ // nothing 412s, so suppression would buy nothing —
2651
+ // stale-view exposure there is the pre-existing
2652
+ // optimistic-start contract (idempotent side effects).
2653
+ const suppressOptimisticStart = guardEnforced &&
2654
+ (openHookWaitState.openHook ||
2655
+ err.hookCount > 0 ||
2656
+ suspensionResult.hasHookEvents);
2657
+ // Turbo mode forces optimistic inline start for this
2658
+ // batch — but only while the run is still "clean" (a pure
2659
+ // step suspension). The moment a hook or wait is
2660
+ // created, later resume/parallel invocations become
2661
+ // possible, so the single-handler guarantee that makes
2662
+ // forced optimistic start safe no longer holds — turbo
2663
+ // exits and the steps take the normal (env-gated)
2664
+ // await-then-run path. The hook-conflict case already
2665
+ // returned early above, the attr case continued into a
2666
+ // fresh replay (so a batch-scheduling suspension never
2667
+ // carries attr events), and the awaited-hook case
2668
+ // emptied lazyInlineSteps; the checks below are
2669
+ // defensive.
2670
+ //
2671
+ // The `suspensionResult.*` flags only reflect what THIS
2672
+ // batch created, so they do not catch a hook/wait opened
2673
+ // in an earlier iteration of the same delivery (e.g. a
2674
+ // fire-and-forget `createHook(...)` that doesn't block the
2675
+ // workflow, letting the replay loop continue to later pure
2676
+ // step suspensions). Once any hook or wait is open in the
2677
+ // cumulative log, resume/parallel invocations are possible
2678
+ // for the rest of the run, so turbo must latch off
2679
+ // permanently — checked here via `openHookAndWaitState`
2680
+ // over the cumulative event log.
2681
+ //
2682
+ // NOTE: `WORKFLOW_SEQUENTIAL_REPLAYS=1` (per-run flow
2683
+ // topics consumed with `maxConcurrency: 1`) would in
2684
+ // principle waive this latch — serialized orchestrator
2685
+ // invocations restore the single-handler guarantee for
2686
+ // the whole delivery. The waiver is intentionally NOT
2687
+ // taken: the env var is a runtime-process setting that
2688
+ // cannot prove the BUILT flow trigger actually carries
2689
+ // `maxConcurrency: 1` (it must be set at build time
2690
+ // too, and some integrations write their own trigger
2691
+ // config), and `capabilities.maxConcurrency` only
2692
+ // declares queue support, not deployed configuration.
2693
+ // Until the build emits a verifiable signal that the
2694
+ // deployed trigger is serialized, the conservative
2695
+ // latch stays.
2696
+ const forceOptimisticStart = turbo &&
2697
+ !suspensionResult.hasAttributeEvents &&
2698
+ !suspensionResult.waitTimeout &&
2699
+ !suspensionResult.hasHookEvents &&
2700
+ !suspensionResult.hasAwaitedHookCreation &&
2701
+ !openHookWaitState.openHook &&
2702
+ !openHookWaitState.openWait;
2703
+ // Execute the inline steps in parallel. The replay
2704
+ // budget is paused for the whole batch — step duration is
2705
+ // bounded by the platform's function maxDuration, not the
2706
+ // replay timeout — so the budget check at the top of the
2707
+ // next loop iteration doesn't charge the step bodies.
2708
+ // Latency telemetry: decide whether this batch's first
2709
+ // step qualifies for TTFS/STSO measurement. Only the
2710
+ // batch's first step carries the tracking so a
2711
+ // parallel batch emits one sample per scheduling gap,
2712
+ // not one per sibling. Turbo's synthesized run
2713
+ // snapshot has a local-clock createdAt, so under
2714
+ // turbo only the run-id ULID timestamp is trusted.
2715
+ const latencyTracking = computeStepLatencyTracking({
2716
+ events: eventLog.events,
2717
+ invocationStartedClean: invocationStartedClean === true,
2718
+ runCreatedAtMs: runIdCreatedAt(runId) ??
2719
+ (turbo ? undefined : +workflowRun.createdAt),
2720
+ runStartedReceivedAtMs,
2721
+ replayMs: replayDurationMs,
2722
+ preStepBlockingMs,
2723
+ preStepBlockingBeforeAttrMs,
2724
+ // This suspension's own hook/wait writes are not in
2725
+ // the loaded event log yet, so report them explicitly.
2726
+ suspensionHasWaits: err.waitCount > 0 ||
2727
+ suspensionResult.waitTimeout !== undefined,
2728
+ suspensionCreatedHooks: err.hookCount > 0 || suspensionResult.hasHookEvents,
2729
+ turbo,
2730
+ });
2731
+ // Precondition-guard snapshot for the inline
2732
+ // step_started claims: the lazy claim is the first
2733
+ // durable write of a hot-path step (its step_created
2734
+ // is deferred), so without a snapshot it would bypass
2735
+ // the guard entirely and a stale replay could claim —
2736
+ // and commit — a step scheduled off a view that misses
2737
+ // an event it never loaded.
2738
+ // `preconditionSnapshotParams` returns an empty object
2739
+ // when the guard env flag is off, so this is a no-op
2740
+ // outside guarded deployments; Worlds that don't
2741
+ // enforce the guard ignore it.
2742
+ const inlineClaimSnapshot = preconditionSnapshotParams(eventLog.events, eventLog.cursor);
2743
+ replayBudget.pause();
2744
+ let stepResults;
2745
+ const stepExecutionPromises = inlineExecutions.map((s, stepIndex) => {
2746
+ const run = () => {
2747
+ assert(eventLog.type === 'ready');
2748
+ return executeStep({
2749
+ world,
2750
+ workflowRunId: runId,
2751
+ workflowDeploymentId: workflowRun.deploymentId,
2752
+ workflowName,
2753
+ workflowStartedAt,
2754
+ rootRunId: rootRunIdFrom(workflowRun.attributes, runId),
2755
+ stepId: s.correlationId,
2756
+ stepName: s.stepName,
2757
+ runSpecVersion: workflowRun.specVersion,
2758
+ // Attempt number = prior step_started count + 1
2759
+ // (this execution's start), counting only THIS
2760
+ // message's own starts: the owned-recovery
2761
+ // ceiling bounds how many times this owning
2762
+ // message re-runs a step it crashed/timed out
2763
+ // on, and each of those (re)starts stamps
2764
+ // metadata.messageId. Starts written by racing
2765
+ // invocations (stale/wake replays, a step
2766
+ // message dispatched off a lost create-claim)
2767
+ // carry other IDs — or none — and must not
2768
+ // count, or the ceiling falsely exhausts a
2769
+ // healthy step (see countStepStartedEvents).
2770
+ // A lazy step is brand-new by construction (it
2771
+ // enters the batch only when it has no
2772
+ // step_created yet), so it has zero prior
2773
+ // starts and is always attempt 1 — skip the
2774
+ // log scan entirely. Only an owned-recovery
2775
+ // re-run can have prior starts, and that path
2776
+ // is uncommon, so reserve the O(n) scan for it
2777
+ // rather than walking the growing log for
2778
+ // every inline step (which would be O(n²)
2779
+ // across a long sequential workflow).
2780
+ authoritativeAttempt: s.lazyStepInput !== undefined
2781
+ ? 1
2782
+ : countStepStartedEvents(eventLog.events, s.correlationId, {
2783
+ type: 'ownedBy',
2784
+ messageId: metadata.messageId,
2785
+ }) + 1,
2786
+ // Lazy inline start: send the deferred step's
2787
+ // input on step_started so the world creates
2788
+ // the step on the fly. Absent for
2789
+ // owned-recovery steps, whose input hydrates
2790
+ // from the existing step entity.
2791
+ lazyStepInput: s.lazyStepInput,
2792
+ // Inline ownership: stamp (or re-stamp) this
2793
+ // invocation's queue message ID on the
2794
+ // step_started, so wake replays see the body
2795
+ // as in flight here and suppress the
2796
+ // immediate requeue (workflow#2780).
2797
+ ownerMessageId: metadata.messageId,
2798
+ // Turbo: force optimistic start and hold the
2799
+ // lazy step_started until the backgrounded
2800
+ // run_started lands (the body still runs
2801
+ // immediately). Both are undefined/false
2802
+ // outside turbo.
2803
+ forceOptimisticStart,
2804
+ // Guard-enforced batches with an open hook
2805
+ // await the claim before running the body, so
2806
+ // a 412-fenced step never executes user code —
2807
+ // see suppressOptimisticStart above.
2808
+ suppressOptimisticStart,
2809
+ runReadyBarrier,
2810
+ preconditionSnapshot: inlineClaimSnapshot,
2811
+ ...(stepIndex === 0 &&
2812
+ s.lazyStepInput !== undefined &&
2813
+ latencyTracking
2814
+ ? { latencyTracking }
2815
+ : {}),
2816
+ ...(requestInlineDelta && eventLog.cursor
2817
+ ? {
2818
+ inlineDeltaSinceCursor: eventLog.cursor,
2819
+ }
2820
+ : {}),
2821
+ replayRecoveryReporter,
2822
+ });
2823
+ };
2824
+ // Invariant bookkeeping: this invocation owns
2825
+ // these bodies until they settle — see
2826
+ // assertNoInFlightOwnedSteps.
2827
+ inFlightOwnedSteps.add(s.correlationId);
2828
+ // Lazy steps are brand-new (their create-claim
2829
+ // is the exactly-once gate), but an
2830
+ // owned-recovery step already exists and its
2831
+ // delayed backstop message may fire mid-body
2832
+ // in this same process — route those through
2833
+ // the in-process single-flight.
2834
+ const executed = s.lazyStepInput === undefined
2835
+ ? runStepSingleFlight(runId, s.correlationId, run)
2836
+ : run();
2837
+ return executed.finally(() => inFlightOwnedSteps.delete(s.correlationId));
2838
+ });
2839
+ try {
2840
+ stepResults = await Promise.all(stepExecutionPromises);
2841
+ }
2842
+ catch (stepErr) {
2843
+ // A stale (412) rejection of an inline step_started
2844
+ // claim: the loaded view this batch was scheduled
2845
+ // from is missing an event the backend already has,
2846
+ // so the claim was fenced by the guard and no step
2847
+ // events were written. Abandon the batch — any
2848
+ // optimistic body result is discarded by executeStep's
2849
+ // reconciliation — and restart the replay so it
2850
+ // observes the missing event. Wait for the sibling
2851
+ // executions to settle first so no owned body is in
2852
+ // flight when the restart (or the ack path) runs.
2853
+ if (PreconditionFailedError.is(stepErr)) {
2854
+ const settled = await Promise.allSettled(stepExecutionPromises);
2855
+ // A sibling whose claim was accepted wrote step
2856
+ // events of its own, possibly after the World built
2857
+ // this 412's delta — so that delta can no longer be
2858
+ // assumed to complete the log, and the restart has
2859
+ // to reload it in full. `skipped` (the step already
2860
+ // existed), `gone` and `throttled` (claim rejected)
2861
+ // wrote nothing.
2862
+ const siblingWrote = settled.some((outcome) => outcome.status === 'fulfilled' &&
2863
+ (outcome.value.type === 'completed' ||
2864
+ outcome.value.type === 'failed' ||
2865
+ outcome.value.type === 'retry'));
2866
+ if (restartReplayInProcess('inline-claim', stepErr, {
2867
+ allowDelta: !siblingWrote,
2868
+ })) {
2869
+ // The finally below resumes the replay budget
2870
+ // before the next iteration starts.
2871
+ continue;
2872
+ }
2873
+ // The finally below resumes the replay budget
2874
+ // before this return (or throw) completes.
2875
+ const escalation = await reinvokeAfterStaleRejection('inline-claim', stepErr);
2876
+ if (escalation.reinvoked)
2877
+ return escalation.result;
2878
+ throw escalation.error;
2879
+ }
2880
+ throw stepErr;
2881
+ }
2882
+ finally {
2883
+ replayBudget.resume();
2884
+ }
2885
+ // Aggregate the batch results. `retry` steps (which
2886
+ // already exist — their `step_started` succeeded) are
2887
+ // re-queued per-step as background steps with their own
2888
+ // delay; `throttled` steps (rejected on the create-claim,
2889
+ // so never created) instead defer redelivery of this
2890
+ // orchestrator message so they re-run inline with input
2891
+ // on replay; completed/failed steps already wrote their
2892
+ // terminal events. We only loop back to replay when every
2893
+ // inline step reached a terminal state — otherwise the
2894
+ // still-pending steps will be re-run by their queued retry
2895
+ // messages and the background-step path replays once
2896
+ // all steps are done.
2897
+ const toRetry = [];
2898
+ let anyPendingOps = false;
2899
+ // A throttled inline step delays redelivery of THIS
2900
+ // orchestrator message rather than being re-queued as a
2901
+ // background step. Crucially, a `throttled` result means
2902
+ // the lazy `step_started` was rejected on the atomic
2903
+ // create-claim — so the step was NEVER created (no
2904
+ // `step_created`, no step entity). Re-queuing it as a
2905
+ // background step would send a bare `step_started` (no
2906
+ // input), which the world rejects with `Step "<id>" not
2907
+ // found` because it cannot lazily create the step without
2908
+ // its input; that error isn't translatable, so the
2909
+ // message redelivers until MAX_QUEUE_DELIVERIES and the
2910
+ // step (and run) fail. Deferring redelivery of the
2911
+ // orchestrator instead re-attempts the throttled step
2912
+ // inline WITH its input on replay. We track the longest
2913
+ // backoff so a batch with multiple throttles waits the
2914
+ // max. Note: `retry` results are safe to re-queue as
2915
+ // background steps because a retry implies `step_started`
2916
+ // already succeeded and the step exists.
2917
+ let throttleTimeout;
2918
+ for (let i = 0; i < inlineExecutions.length; i++) {
2919
+ const r = stepResults[i];
2920
+ const s = inlineExecutions[i];
2921
+ if (r.type === 'retry') {
2922
+ toRetry.push({
2923
+ step: s,
2924
+ delaySeconds: r.timeoutSeconds,
2925
+ });
2926
+ }
2927
+ else if (r.type === 'throttled') {
2928
+ throttleTimeout = Math.max(throttleTimeout ?? 0, r.timeoutSeconds);
2929
+ }
2930
+ else if (r.type === 'completed' &&
2931
+ r.hasPendingOps) {
2932
+ anyPendingOps = true;
2933
+ }
2934
+ }
2935
+ if (throttleTimeout !== undefined) {
2936
+ // Defer redelivery of the orchestrator after the
2937
+ // throttle backoff. On replay every non-terminal step
2938
+ // is re-dispatched by the suspension handler: the
2939
+ // still-throttled steps run inline again WITH their
2940
+ // input (their `step_created` is deferred anew), and
2941
+ // any `retry` steps in this batch are queued as
2942
+ // background steps with their own retryAfter honored.
2943
+ // Terminal steps (completed/failed/skipped/gone) are
2944
+ // observed from their events and not re-run. Because
2945
+ // the replay drives all remaining work, we must NOT
2946
+ // also re-queue `toRetry` here — that would
2947
+ // double-dispatch those steps.
2948
+ //
2949
+ // This returns BEFORE the `anyPendingOps` branch
2950
+ // below, so a batch that mixes a throttle with a
2951
+ // completed step that left unflushed ops does not
2952
+ // queue the explicit flush continuation. That is safe
2953
+ // because the throttle backoff (>= 1s) always exceeds
2954
+ // the in-invocation flush window (<= 500ms + waitUntil),
2955
+ // so ops settle before the post-backoff redelivery
2956
+ // replays and reads them.
2957
+ return await reinvoke(throttleTimeout);
2958
+ }
2959
+ if (toRetry.length > 0) {
2960
+ const retryTraceCarrier = await nextTraceCarrier();
2961
+ await Promise.all(toRetry.map(({ step, delaySeconds }) => queueMessage(world, getWorkflowQueueName(workflowName, namespace), {
2962
+ runId,
2963
+ stepId: step.correlationId,
2964
+ stepName: step.stepName,
2965
+ traceCarrier: retryTraceCarrier,
2966
+ requestedAt: new Date(),
2967
+ }, {
2968
+ delaySeconds,
2969
+ // Key the delayed retry on the step's
2970
+ // correlationId so it dedupes against the
2971
+ // keyed re-dispatch the suspension handler
2972
+ // performs on replay (it also uses
2973
+ // `idempotencyKey: step.correlationId`).
2974
+ //
2975
+ // Without this, a mixed batch where one step
2976
+ // `completed` with unflushed background ops
2977
+ // (`anyPendingOps`) and another step is
2978
+ // retrying would double-dispatch the retry:
2979
+ // the `anyPendingOps` branch below queues an
2980
+ // immediate plain continuation, whose replay
2981
+ // sees the still-`retrying` step as pending
2982
+ // and re-dispatches it *immediately* and
2983
+ // *with* a key. Since this delayed retry had
2984
+ // no key, the two messages wouldn't dedupe —
2985
+ // the step would run twice, the configured
2986
+ // retry backoff would be ignored (plain
2987
+ // `Error` retries persist no `retryAfter`, so
2988
+ // the world has no `TooEarly` guard), and the
2989
+ // retry body could run early/concurrently.
2990
+ // Sharing the key lets the earlier delayed
2991
+ // message win, honoring the backoff.
2992
+ idempotencyKey: step.correlationId,
2993
+ })));
2994
+ }
2995
+ // Let pending background operations flush before the next
2996
+ // replay reads their results.
2997
+ if (anyPendingOps) {
2998
+ runtimeLogger.debug('Breaking loop: inline step has pending ops', { workflowRunId: runId, loopIteration });
2999
+ await queueMessage(world, getWorkflowQueueName(workflowName, namespace), {
3000
+ runId,
3001
+ traceCarrier: await nextTraceCarrier(),
3002
+ requestedAt: new Date(),
3003
+ });
3004
+ return;
3005
+ }
3006
+ if (toRetry.length > 0) {
3007
+ // Some inline steps will be re-run via their queued
3008
+ // retry messages; the background-step path replays
3009
+ // once all steps are terminal. Don't loop here — the
3010
+ // retrying steps have no terminal event to observe yet.
3011
+ return;
3012
+ }
3013
+ // All inline steps reached a terminal state
3014
+ // (completed/failed/skipped/gone) — loop back to replay
3015
+ // (the workflow observes the terminal events on replay).
3016
+ //
3017
+ // Reuse any inline delta. If it is partial, continue
3018
+ // from its cursor instead of reading the page again.
3019
+ if (inlineExecutions.length === 1) {
3020
+ const only = stepResults[0];
3021
+ if (only.type === 'completed' && only.inlineDelta) {
3022
+ appendEventLog(eventLog, only.inlineDelta);
3023
+ eventLog = only.inlineDelta.hasMore
3024
+ ? nextEventLogLoad(eventLog)
3025
+ : { ...eventLog, type: 'ready' };
3026
+ continue;
3027
+ }
3028
+ }
3029
+ eventLog = nextEventLogLoad(eventLog);
3030
+ }
3031
+ else {
3032
+ // Stale-snapshot rejection of a guarded write made
3033
+ // directly by the replay loop — the result-bearing
3034
+ // `run_completed`, or the `wait_completed` of the wait
3035
+ // pass. Both reach this one catch and the rejection
3036
+ // does not say which, hence the neutral label.
3037
+ // Neither may be re-posted in place: the correlation id
3038
+ // and (for run_completed) the result itself came from
3039
+ // this replay, and a corrected log may produce
3040
+ // different ones. Don't fail the run — restart the
3041
+ // replay in this invocation, and only once that budget
3042
+ // is spent schedule an explicit re-invocation.
3043
+ // Rethrowing instead would rely on redelivery of the
3044
+ // CURRENT message, which the turbo path has already
3045
+ // acked — empirically the run then stalls for the
3046
+ // queue's ~300s default visibility timeout before
3047
+ // completing.
3048
+ let terminalError = err;
3049
+ if (PreconditionFailedError.is(err)) {
3050
+ if (restartReplayInProcess('replay-write', err)) {
3051
+ continue;
3052
+ }
3053
+ const escalation = await reinvokeAfterStaleRejection('replay-write', err);
3054
+ if (escalation.reinvoked)
3055
+ return escalation.result;
3056
+ // Per-run budget spent. Fall through to the terminal
3057
+ // path below instead of rethrowing: this catch owns
3058
+ // failing the run, and a rethrow would escape to the
3059
+ // queue handler and be redelivered.
3060
+ terminalError = escalation.error;
3061
+ }
3062
+ // Transient infrastructure failures talking to the
3063
+ // world (workflow-server) — an exhausted RetryAgent
3064
+ // (UND_ERR_REQ_RETRY from a sustained 429/503 storm),
3065
+ // a dropped socket, a connect/DNS failure, or a client
3066
+ // timeout — must NOT fail the run. Rethrow so the queue
3067
+ // redelivers and a fresh invocation retries the replay
3068
+ // once the backend recovers. The @vercel/queue handler
3069
+ // applies a fast (1s→60s) backoff by delivery count,
3070
+ // avoiding the ~5min default visibility-timeout redrive
3071
+ // (and never killing the process via run_failed).
3072
+ if (isRetryableWorldError(err)) {
3073
+ runLogger.warn('Transient world error during replay; redelivering via queue instead of failing the run', {
3074
+ errorName: err instanceof Error
3075
+ ? err.name
3076
+ : 'UnknownError',
3077
+ errorMessage: err instanceof Error
3078
+ ? err.message
3079
+ : String(err),
3080
+ deliveryAttempt: metadata.attempt,
3081
+ });
3082
+ throw err;
3083
+ }
3084
+ let replayDivergenceCountForFailure;
3085
+ if (ReplayDivergenceError.is(err)) {
3086
+ const divergenceCount = (replayDivergence?.count ?? 0) + 1;
3087
+ const maxRecoveryReplays = getReplayDivergenceMaxRetries();
3088
+ if (divergenceCount <= maxRecoveryReplays) {
3089
+ runLogger.warn('Workflow replay diverged; queueing a recovery replay before declaring the event log corrupted', {
3090
+ errorCode: RUN_ERROR_CODES.REPLAY_DIVERGENCE,
3091
+ divergenceEventId: err.eventId,
3092
+ priorDivergenceEventId: replayDivergence?.eventId,
3093
+ divergenceCount,
3094
+ deliveryAttempt: metadata.attempt,
3095
+ maxRecoveryReplays,
3096
+ errorMessage: err.message,
3097
+ });
3098
+ await queueMessage(world, getWorkflowQueueName(workflowName, namespace), {
3099
+ runId,
3100
+ traceCarrier: await nextTraceCarrier(),
3101
+ requestedAt: new Date(),
3102
+ replayDivergence: {
3103
+ eventId: err.eventId,
3104
+ count: divergenceCount,
3105
+ },
3106
+ });
3107
+ return;
3108
+ }
3109
+ replayDivergenceCountForFailure = divergenceCount;
3110
+ terminalError = new CorruptedEventLogError(`Workflow replay diverged ${divergenceCount} times after ${maxRecoveryReplays} recovery replays; latest divergent event was ${err.eventId}. Last divergence: ${err.message}`, { cause: err });
3111
+ }
3112
+ else if (replayStart > 0) {
3113
+ replayRecoveryReporter.activate();
3114
+ }
3115
+ // User code errors and terminal runtime errors fail the run.
3116
+ if (terminalError instanceof Error) {
3117
+ span?.recordException?.(terminalError);
3118
+ }
3119
+ const normalizedError = await normalizeUnknownError(terminalError);
3120
+ const errorName = normalizedError.name || getErrorName(terminalError);
3121
+ const errorMessage = normalizedError.message;
3122
+ let errorStack = normalizedError.stack || getErrorStack(terminalError);
3123
+ if (errorStack) {
3124
+ const parsedName = parseWorkflowName(workflowName);
3125
+ const filename = parsedName?.moduleSpecifier || workflowName;
3126
+ errorStack = remapErrorStack(errorStack, filename, workflowCode);
3127
+ }
3128
+ // Classify the error: WorkflowRuntimeError indicates
3129
+ // an SDK/runtime issue, and selected subclasses use
3130
+ // more specific codes for backend tracking.
3131
+ const errorCode = classifyRunError(terminalError);
3132
+ runtimeLogger.error('Error while running workflow', {
3133
+ workflowRunId: runId,
3134
+ errorCode,
3135
+ errorName,
3136
+ errorStack,
3137
+ });
3138
+ // Apply the source-map-remapped stack to the thrown
3139
+ // value so that the serialized error preserves it
3140
+ // for consumers. `types.isNativeError()` is used
3141
+ // instead of `err instanceof Error` because the
3142
+ // workflow runs in a separate VM realm — its Error
3143
+ // class is distinct from the host's, so `instanceof
3144
+ // Error` is `false` for VM-thrown errors. The V8
3145
+ // type tag works across realms.
3146
+ if (types.isNativeError(terminalError) && errorStack) {
3147
+ terminalError.stack = errorStack;
3148
+ }
3149
+ // Fail the workflow run via event (event-sourced).
3150
+ // Serialize the original thrown value so its full
3151
+ // type identity and custom properties round-trip
3152
+ // through the event log.
3153
+ //
3154
+ // Precondition-guard asymmetry: unlike `run_completed`,
3155
+ // this terminal `run_failed` sends no `stateUpdatedAt`
3156
+ // snapshot, so it is never 412-rejected even if a hook
3157
+ // landed mid-replay and could have changed the path that
3158
+ // threw. This is intentional and fail-open: a spurious
3159
+ // failure is recoverable (the run can be re-run from the
3160
+ // dashboard), whereas a spurious *completion* commits a
3161
+ // wrong result. Guarding this write symmetrically would
3162
+ // also need the loaded event log, which is scoped to the
3163
+ // replay `try` above and not available in this catch.
3164
+ try {
3165
+ // Turbo: order the terminal write after the
3166
+ // backgrounded run_started so the run exists.
3167
+ await awaitRunReady();
3168
+ await createEvent({
3169
+ eventType: 'run_failed',
3170
+ specVersion: SPEC_VERSION_CURRENT,
3171
+ eventData: {
3172
+ error: await dehydrateRunError(terminalError, runId, encryptionKey, globalThis, (workflowRun?.specVersion ?? 0) >=
3173
+ SPEC_VERSION_SUPPORTS_COMPRESSION),
3174
+ errorCode,
3175
+ },
3176
+ }, {
3177
+ requestId,
3178
+ ...(replayDivergenceCountForFailure !== undefined
3179
+ ? {
3180
+ replayDivergenceCount: replayDivergenceCountForFailure,
3181
+ }
3182
+ : {}),
3183
+ });
3184
+ }
3185
+ catch (failErr) {
3186
+ if (EntityConflictError.is(failErr) ||
3187
+ RunExpiredError.is(failErr)) {
3188
+ runtimeLogger.info('Tried failing workflow run, but run has already finished.', {
3189
+ workflowRunId: runId,
3190
+ message: failErr.message,
3191
+ });
3192
+ return;
3193
+ }
3194
+ if (isWorldContractError(failErr)) {
3195
+ runtimeLogger.error('Fatal world contract error while recording workflow failure', {
3196
+ workflowRunId: runId,
3197
+ errorCode: RUN_ERROR_CODES.WORLD_CONTRACT_ERROR,
3198
+ error: failErr instanceof Error
3199
+ ? failErr.message
3200
+ : String(failErr),
3201
+ });
3202
+ return;
3203
+ }
3204
+ throw failErr;
3205
+ }
384
3206
  span?.setAttributes({
3207
+ ...Attribute.WorkflowRunStatus('failed'),
385
3208
  ...Attribute.WorkflowErrorCode(errorCode),
386
3209
  ...Attribute.WorkflowErrorName(errorName),
387
3210
  ...Attribute.WorkflowErrorMessage(errorMessage),
@@ -389,65 +3212,49 @@ export function workflowEntrypoint(workflowCode) {
389
3212
  });
390
3213
  return;
391
3214
  }
392
- else {
393
- throw failErr;
394
- }
395
3215
  }
396
- span?.setAttributes({
397
- ...Attribute.WorkflowRunStatus('failed'),
398
- ...Attribute.WorkflowErrorCode(errorCode),
399
- ...Attribute.WorkflowErrorName(errorName),
400
- ...Attribute.WorkflowErrorMessage(errorMessage),
401
- ...Attribute.ErrorType(errorName),
402
- });
403
- return;
404
3216
  }
405
- // --- Infrastructure: complete the run ---
406
- // This is outside the user-code try/catch so that failures
407
- // here (e.g., network errors) propagate to the queue handler.
408
- try {
409
- await world.events.create(runId, {
410
- eventType: 'run_completed',
411
- specVersion: SPEC_VERSION_CURRENT,
412
- eventData: {
413
- output: workflowResult,
414
- },
415
- }, { requestId });
416
- }
417
- catch (err) {
418
- if (EntityConflictError.is(err) ||
419
- RunExpiredError.is(err)) {
420
- runtimeLogger.info('Tried completing workflow run, but run has already finished.', {
421
- workflowRunId: runId,
422
- message: err.message,
423
- });
424
- return;
425
- }
426
- else {
427
- throw err;
428
- }
429
- }
430
- span?.setAttributes({
431
- ...Attribute.WorkflowRunStatus('completed'),
432
- ...Attribute.WorkflowEventsCount(events.length),
433
- });
434
- }); // End trace
435
- }); // End withWorkflowBaggage
436
- }).finally(() => {
437
- if (replayTimeout) {
438
- clearTimeout(replayTimeout);
439
- }
440
- }); // End withTraceContext
3217
+ });
3218
+ });
3219
+ });
441
3220
  });
442
3221
  let cachedHandler;
3222
+ let invocationCount = 0;
3223
+ const entrypointCreatedAt = Date.now();
3224
+ const routeModuleBodyInitMs = typeof options?.routeModuleBodyStartedAt === 'number'
3225
+ ? entrypointCreatedAt - options.routeModuleBodyStartedAt
3226
+ : undefined;
443
3227
  return withHealthCheck(async (req) => {
444
- if (!cachedHandler) {
445
- cachedHandler = handler(await getWorldHandlers());
446
- }
447
- return cachedHandler(req);
3228
+ invocationCount += 1;
3229
+ const handlerCached = cachedHandler !== undefined;
3230
+ const spanKind = await getSpanKind('SERVER');
3231
+ return trace('workflow.route.flow', {
3232
+ kind: spanKind,
3233
+ attributes: {
3234
+ ...Attribute.WorkflowRouteType('flow'),
3235
+ ...Attribute.FaasInstance(COMPUTE_INSTANCE_ID),
3236
+ ...Attribute.WorkflowRouteHandlerCached(handlerCached),
3237
+ ...Attribute.WorkflowRouteInvocationCount(invocationCount),
3238
+ ...Attribute.WorkflowRouteEntrypointAgeMs(Date.now() - entrypointCreatedAt),
3239
+ ...(routeModuleBodyInitMs === undefined
3240
+ ? {}
3241
+ : Attribute.WorkflowRouteModuleBodyInitMs(routeModuleBodyInitMs)),
3242
+ ...Attribute.HttpRequestMethod(req.method),
3243
+ ...Attribute.HttpRoute('/.well-known/workflow/v1/flow'),
3244
+ },
3245
+ }, async (span) => {
3246
+ if (!cachedHandler) {
3247
+ cachedHandler = await trace('workflow.route.init', async () => {
3248
+ const worldHandlers = await trace('workflow.route.get_world_handlers', async () => getWorldHandlers());
3249
+ return handler(worldHandlers);
3250
+ });
3251
+ }
3252
+ const response = await cachedHandler(req);
3253
+ if (response instanceof Response) {
3254
+ span?.setAttributes(Attribute.HttpResponseStatusCode(response.status));
3255
+ }
3256
+ return response;
3257
+ });
448
3258
  });
449
3259
  }
450
- // this is a no-op placeholder as the client is
451
- // expecting this to be present but we aren't actually using it
452
- export function runStep() { }
453
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVudGltZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9ydW50aW1lLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxtQkFBbUIsRUFDbkIsZUFBZSxFQUNmLGVBQWUsRUFDZixvQkFBb0IsR0FDckIsTUFBTSxrQkFBa0IsQ0FBQztBQUMxQixPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUMvRCxPQUFPLEVBRUwsb0JBQW9CLEVBQ3BCLDJCQUEyQixHQUU1QixNQUFNLGlCQUFpQixDQUFDO0FBQ3pCLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUM1QyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDakQsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUM1QyxPQUFPLEVBQ0wsb0JBQW9CLEVBQ3BCLDBCQUEwQixFQUMxQixpQkFBaUIsR0FDbEIsTUFBTSx3QkFBd0IsQ0FBQztBQUNoQyxPQUFPLEVBQ0wsdUJBQXVCLEVBQ3ZCLGdCQUFnQixFQUNoQix3QkFBd0IsRUFDeEIsdUJBQXVCLEVBQ3ZCLGVBQWUsR0FDaEIsTUFBTSxzQkFBc0IsQ0FBQztBQUM5QixPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNuRSxPQUFPLEVBQ0wsUUFBUSxFQUNSLGdCQUFnQixHQUVqQixNQUFNLG9CQUFvQixDQUFDO0FBQzVCLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNsRCxPQUFPLEtBQUssU0FBUyxNQUFNLHFDQUFxQyxDQUFDO0FBQ2pFLE9BQU8sRUFDTCxvQkFBb0IsRUFDcEIsS0FBSyxFQUNMLGdCQUFnQixFQUNoQixtQkFBbUIsR0FDcEIsTUFBTSxnQkFBZ0IsQ0FBQztBQUN4QixPQUFP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Q0FBQyxpQkFBaUIsQ0FBQyxXQUFXLENBQUM7d0JBQzNDLEdBQUcsU0FBUyxDQUFDLG1CQUFtQixDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUM7cUJBQ2hELENBQUMsQ0FBQztnQkFDTCxDQUFDLENBQ0YsQ0FBQyxDQUFDLFlBQVk7WUFDakIsQ0FBQyxDQUNGLENBQUMsQ0FBQywwQkFBMEI7UUFDL0IsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRTtZQUNkLElBQUksYUFBYSxFQUFFLENBQUM7Z0JBQ2xCLFlBQVksQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUM5QixDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUMsQ0FBQyx1QkFBdUI7SUFDN0IsQ0FBQyxDQUNGLENBQUM7SUFFSixJQUFJLGFBQWdFLENBQUM7SUFDckUsT0FBTyxlQUFlLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxFQUFFO1FBQ25DLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUNuQixhQUFhLEdBQUcsT0FBTyxDQUFDLE1BQU0sZ0JBQWdCLEVBQUUsQ0FBQyxDQUFDO1FBQ3BELENBQUM7UUFDRCxPQUFPLGFBQWEsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUM1QixDQUFDLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRCwrQ0FBK0M7QUFDL0MsK0RBQStEO0FBQy9ELE1BQU0sVUFBVSxPQUFPLEtBQUksQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEVudGl0eUNvbmZsaWN0RXJyb3IsXG4gIFJVTl9FUlJPUl9DT0RFUyxcbiAgUnVuRXhwaXJlZEVycm9yLFxuICBXb3JrZmxvd1J1bnRpbWVFcnJvcixcbn0gZnJvbSAnQHdvcmtmbG93L2Vycm9ycyc7XG5pbXBvcnQgeyBwYXJzZVdvcmtmbG93TmFtZSB9IGZyb20gJ0B3b3JrZmxvdy91dGlscy9wYXJzZS1uYW1lJztcbmltcG9ydCB7XG4gIHR5cGUgRXZlbnQsXG4gIFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICBXb3JrZmxvd0ludm9rZVBheWxvYWRTY2hlbWEsXG4gIHR5cGUgV29ya2Zsb3dSdW4sXG59IGZyb20gJ0B3b3JrZmxvdy93b3JsZCc7XG5pbXBvcnQgeyBjbGFzc2lmeVJ1bkVycm9yIH0gZnJvbSAnLi9jbGFzc2lmeS1lcnJvci5qcyc7XG5pbXBvcnQgeyBpbXBvcnRLZXkgfSBmcm9tICcuL2VuY3J5cHRpb24uanMnO1xuaW1wb3J0IHsgV29ya2Zsb3dTdXNwZW5zaW9uIH0gZnJvbSAnLi9nbG9iYWwuanMnO1xuaW1wb3J0IHsgcnVudGltZUxvZ2dlciB9IGZyb20gJy4vbG9nZ2VyLmpzJztcbmltcG9ydCB7XG4gIE1BWF9RVUVVRV9ERUxJVkVSSUVTLFxuICBSRVBMQVlfVElNRU9VVF9NQVhfUkVUUklFUyxcbiAgUkVQTEFZX1RJTUVPVVRfTVMsXG59IGZyb20gJy4vcnVudGltZS9jb25zdGFudHMuanMnO1xuaW1wb3J0IHtcbiAgZ2V0QWxsV29ya2Zsb3dSdW5FdmVudHMsXG4gIGdldFF1ZXVlT3ZlcmhlYWQsXG4gIGhhbmRsZUhlYWx0aENoZWNrTWVzc2FnZSxcbiAgcGFyc2VIZWFsdGhDaGVja1BheWxvYWQsXG4gIHdpdGhIZWFsdGhDaGVjayxcbn0gZnJvbSAnLi9ydW50aW1lL2hlbHBlcnMuanMnO1xuaW1wb3J0IHsgaGFuZGxlU3VzcGVuc2lvbiB9IGZyb20gJy4vcnVudGltZS9zdXNwZW5zaW9uLWhhbmRsZXIuanMnO1xuaW1wb3J0IHtcbiAgZ2V0V29ybGQsXG4gIGdldFdvcmxkSGFuZGxlcnMsXG4gIHR5cGUgV29ybGRIYW5kbGVycyxcbn0gZnJvbSAnLi9ydW50aW1lL3dvcmxkLmpzJztcbmltcG9ydCB7IHJlbWFwRXJyb3JTdGFjayB9IGZyb20gJy4vc291cmNlLW1hcC5qcyc7XG5pbXBvcnQgKiBhcyBBdHRyaWJ1dGUgZnJvbSAnLi90ZWxlbWV0cnkvc2VtYW50aWMtY29udmVudGlvbnMuanMnO1xuaW1wb3J0IHtcbiAgbGlua1RvQ3VycmVudENvbnRleHQsXG4gIHRyYWNlLFxuICB3aXRoVHJhY2VDb250ZXh0LFxuICB3aXRoV29ya2Zsb3dCYWdnYWdlLFxufSBmcm9tICcuL3RlbGVtZXRyeS5qcyc7XG5pbXBvcnQgeyBnZXRFcnJvck5hbWUsIGdldEVycm9yU3RhY2ssIG5vcm1hbGl6ZVVua25vd25FcnJvciB9IGZyb20gJy4vdHlwZXMuanMnO1xuaW1wb3J0IHsgYnVpbGRXb3JrZmxvd1N1c3BlbnNpb25NZXNzYWdlIH0gZnJvbSAnLi91dGlsLmpzJztcbmltcG9ydCB7IHJ1bldvcmtmbG93IH0gZnJvbSAnLi93b3JrZmxvdy5qcyc7XG5cbmV4cG9ydCB0eXBlIHsgRXZlbnQsIFdvcmtmbG93UnVuIH07XG5leHBvcnQgeyBXb3JrZmxvd1N1c3BlbnNpb24gfSBmcm9tICcuL2dsb2JhbC5qcyc7XG5leHBvcnQge1xuICB0eXBlIEhlYWx0aENoZWNrRW5kcG9pbnQsXG4gIHR5cGUgSGVhbHRoQ2hlY2tPcHRpb25zLFxuICB0eXBlIEhlYWx0aENoZWNrUmVzdWx0LFxuICBoZWFsdGhDaGVjayxcbn0gZnJvbSAnLi9ydW50aW1lL2hlbHBlcnMuanMnO1xuZXhwb3J0IHtcbiAgZ2V0SG9va0J5VG9rZW4sXG4gIHJlc3VtZUhvb2ssXG4gIHJlc3VtZVdlYmhvb2ssXG59IGZyb20gJy4vcnVudGltZS9yZXN1bWUtaG9vay5qcyc7XG5leHBvcnQge1xuICBnZXRSdW4sXG4gIFJ1bixcbiAgdHlwZSBXb3JrZmxvd1JlYWRhYmxlU3RyZWFtLFxuICB0eXBlIFdvcmtmbG93UmVhZGFibGVTdHJlYW1PcHRpb25zLFxufSBmcm9tICcuL3J1bnRpbWUvcnVuLmpzJztcbmV4cG9ydCB7XG4gIGNhbmNlbFJ1bixcbiAgbGlzdFN0cmVhbXMsXG4gIHR5cGUgUmVhZFN0cmVhbU9wdGlvbnMsXG4gIHR5cGUgUmVjcmVhdGVSdW5PcHRpb25zLFxuICByZWFkU3RyZWFtLFxuICByZWNyZWF0ZVJ1bkZyb21FeGlzdGluZyxcbiAgcmVlbnF1ZXVlUnVuLFxuICB0eXBlIFN0b3BTbGVlcE9wdGlvbnMsXG4gIHR5cGUgU3RvcFNsZWVwUmVzdWx0LFxuICB3YWtlVXBSdW4sXG59IGZyb20gJy4vcnVudGltZS9ydW5zLmpzJztcbmV4cG9ydCB7XG4gIHR5cGUgU3RhcnRPcHRpb25zLFxuICB0eXBlIFN0YXJ0T3B0aW9uc0Jhc2UsXG4gIHR5cGUgU3RhcnRPcHRpb25zV2l0aERlcGxveW1lbnRJZCxcbiAgdHlwZSBTdGFydE9wdGlvbnNXaXRob3V0RGVwbG95bWVudElkLFxuICBzdGFydCxcbn0gZnJvbSAnLi9ydW50aW1lL3N0YXJ0LmpzJztcbmV4cG9ydCB7IHN0ZXBFbnRyeXBvaW50IH0gZnJvbSAnLi9ydW50aW1lL3N0ZXAtaGFuZGxlci5qcyc7XG5leHBvcnQge1xuICBjcmVhdGVXb3JsZCxcbiAgZ2V0V29ybGQsXG4gIGdldFdvcmxkSGFuZGxlcnMsXG4gIHNldFdvcmxkLFxufSBmcm9tICcuL3J1bnRpbWUvd29ybGQuanMnO1xuXG4vKipcbiAqIEZ1bmN0aW9uIHRoYXQgY3JlYXRlcyBhIHNpbmdsZSByb3V0ZSB3aGljaCBoYW5kbGVzIGFueSB3b3JrZmxvdyBleGVjdXRpb25cbiAqIHJlcXVlc3QgYW5kIHJvdXRlcyB0byB0aGUgYXBwcm9wcmlhdGUgd29ya2Zsb3cgZnVuY3Rpb24uXG4gKlxuICogQHBhcmFtIHdvcmtmbG93Q29kZSAtIFRoZSB3b3JrZmxvdyBidW5kbGUgY29kZSBjb250YWluaW5nIGFsbCB0aGUgd29ya2Zsb3dcbiAqIGZ1bmN0aW9ucyBhdCB0aGUgdG9wIGxldmVsLlxuICogQHJldHVybnMgQSBmdW5jdGlvbiB0aGF0IGNhbiBiZSB1c2VkIGFzIGEgVmVyY2VsIEFQSSByb3V0ZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHdvcmtmbG93RW50cnlwb2ludChcbiAgd29ya2Zsb3dDb2RlOiBzdHJpbmdcbik6IChyZXE6IFJlcXVlc3QpID0+IFByb21pc2U8UmVzcG9uc2U+IHtcbiAgY29uc3QgaGFuZGxlciA9ICh3b3JsZEhhbmRsZXJzOiBXb3JsZEhhbmRsZXJzKSA9PlxuICAgIHdvcmxkSGFuZGxlcnMuY3JlYXRlUXVldWVIYW5kbGVyKFxuICAgICAgJ19fd2tmX3dvcmtmbG93XycsXG4gICAgICBhc3luYyAobWVzc2FnZV8sIG1ldGFkYXRhKSA9PiB7XG4gICAgICAgIC8vIENoZWNrIGlmIHRoaXMgaXMgYSBoZWFsdGggY2hlY2sgbWVzc2FnZVxuICAgICAgICAvLyBOT1RFOiBIZWFsdGggY2hlY2sgbWVzc2FnZXMgYXJlIGludGVudGlvbmFsbHkgdW5hdXRoZW50aWNhdGVkIGZvciBtb25pdG9yaW5nIHB1cnBvc2VzLlxuICAgICAgICAvLyBUaGV5IG9ubHkgd3JpdGUgYSBzaW1wbGUgc3RhdHVzIHJlc3BvbnNlIHRvIGEgc3RyZWFtIGFuZCBkbyBub3QgZXhwb3NlIHNlbnNpdGl2ZSBkYXRhLlxuICAgICAgICAvLyBUaGUgc3RyZWFtIG5hbWUgaW5jbHVkZXMgYSB1bmlxdWUgY29ycmVsYXRpb25JZCB0aGF0IG11c3QgYmUga25vd24gYnkgdGhlIGNhbGxlci5cbiAgICAgICAgY29uc3QgaGVhbHRoQ2hlY2sgPSBwYXJzZUhlYWx0aENoZWNrUGF5bG9hZChtZXNzYWdlXyk7XG4gICAgICAgIGlmIChoZWFsdGhDaGVjaykge1xuICAgICAgICAgIGF3YWl0IGhhbmRsZUhlYWx0aENoZWNrTWVzc2FnZShcbiAgICAgICAgICAgIGhlYWx0aENoZWNrLFxuICAgICAgICAgICAgJ3dvcmtmbG93JyxcbiAgICAgICAgICAgIHdvcmxkSGFuZGxlcnMuc3BlY1ZlcnNpb25cbiAgICAgICAgICApO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICBydW5JZCxcbiAgICAgICAgICB0cmFjZUNhcnJpZXI6IHRyYWNlQ29udGV4dCxcbiAgICAgICAgICByZXF1ZXN0ZWRBdCxcbiAgICAgICAgICBydW5JbnB1dCxcbiAgICAgICAgfSA9IFdvcmtmbG93SW52b2tlUGF5bG9hZFNjaGVtYS5wYXJzZShtZXNzYWdlXyk7XG4gICAgICAgIGNvbnN0IHsgcmVxdWVzdElkIH0gPSBtZXRhZGF0YTtcbiAgICAgICAgLy8gRXh0cmFjdCB0aGUgd29ya2Zsb3cgbmFtZSBmcm9tIHRoZSB0b3BpYyBuYW1lXG4gICAgICAgIGNvbnN0IHdvcmtmbG93TmFtZSA9IG1ldGFkYXRhLnF1ZXVlTmFtZS5zbGljZSgnX193a2Zfd29ya2Zsb3dfJy5sZW5ndGgpO1xuXG4gICAgICAgIC8vIC0tLSBNYXggZGVsaXZlcnkgY2hlY2sgLS0tXG4gICAgICAgIC8vIEVuZm9yY2UgbWF4IGRlbGl2ZXJ5IGxpbWl0IGJlZm9yZSBhbnkgaW5mcmFzdHJ1Y3R1cmUgY2FsbHMuXG4gICAgICAgIC8vIFRoaXMgcHJldmVudHMgcnVuYXdheSB3b3JrZmxvd3MgZnJvbSBjb25zdW1pbmcgaW5maW5pdGUgcXVldWUgZGVsaXZlcmllcy5cbiAgICAgICAgLy8gQXQgdGhpcyBwb2ludCwgd2Ugd2FudCB0byBkbyB0aGUgbWluaW1hbCBhbW91bnQgb2Ygd29yayAobm8gZmV0Y2hpbmdcbiAgICAgICAgLy8gb2YgdGhlIHdvcmtmbG93IGV2ZW50cywgZXRjLiBXZSBzaW1wbHkgYXR0ZW1wdCB0byBtYXJrIHRoZSBydW4gYXMgZmFpbGVkXG4gICAgICAgIC8vIGFuZCBpZiB0aGF0IGZhaWxzLCB0aGUgbWVzc2FnZSBpcyBzdGlsbCBjb25zdW1lZCBidXQgd2l0aCBhZGVxdWF0ZSBsb2dnaW5nXG4gICAgICAgIC8vIHRoYXQgYW4gZXJyb3Igb2NjdXJyZWQgcHJldmVudGluZyB1cyBmcm9tIGZhaWxpbmcgdGhlIHJ1bi5cbiAgICAgICAgaWYgKG1ldGFkYXRhLmF0dGVtcHQgPiBNQVhfUVVFVUVfREVMSVZFUklFUykge1xuICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuZXJyb3IoXG4gICAgICAgICAgICBgV29ya2Zsb3cgaGFuZGxlciBleGNlZWRlZCBtYXggZGVsaXZlcmllcyAoJHttZXRhZGF0YS5hdHRlbXB0fS8ke01BWF9RVUVVRV9ERUxJVkVSSUVTfSlgLFxuICAgICAgICAgICAgeyB3b3JrZmxvd1J1bklkOiBydW5JZCwgd29ya2Zsb3dOYW1lLCBhdHRlbXB0OiBtZXRhZGF0YS5hdHRlbXB0IH1cbiAgICAgICAgICApO1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCB3b3JsZCA9IGF3YWl0IGdldFdvcmxkKCk7XG4gICAgICAgICAgICBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKFxuICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGV2ZW50VHlwZTogJ3J1bl9mYWlsZWQnLFxuICAgICAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgICAgICAgIGVycm9yOiB7XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGBXb3JrZmxvdyBleGNlZWRlZCBtYXhpbXVtIHF1ZXVlIGRlbGl2ZXJpZXMgKCR7bWV0YWRhdGEuYXR0ZW1wdH0vJHtNQVhfUVVFVUVfREVMSVZFUklFU30pYCxcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICBlcnJvckNvZGU6IFJVTl9FUlJPUl9DT0RFUy5NQVhfREVMSVZFUklFU19FWENFRURFRCxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB7IHJlcXVlc3RJZCB9XG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZXJyKSB8fCBSdW5FeHBpcmVkRXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAgICAgICAvLyBSdW4gYWxyZWFkeSBmaW5pc2hlZCwgY29uc3VtZSB0aGUgbWVzc2FnZSBzaWxlbnRseVxuICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBydW50aW1lTG9nZ2VyLmVycm9yKFxuICAgICAgICAgICAgICBgRmFpbGVkIHRvIG1hcmsgcnVuIGFzIGZhaWxlZCBhZnRlciAke21ldGFkYXRhLmF0dGVtcHR9IGRlbGl2ZXJ5IGF0dGVtcHRzLiBgICtcbiAgICAgICAgICAgICAgICBgQSBwZXJzaXN0ZW50IGVycm9yIGlzIHByZXZlbnRpbmcgdGhlIHJ1biBmcm9tIGJlaW5nIHRlcm1pbmF0ZWQuIGAgK1xuICAgICAgICAgICAgICAgIGBUaGUgcnVuIHdpbGwgcmVtYWluIGluIGl0cyBjdXJyZW50IHN0YXRlIHVudGlsIG1hbnVhbGx5IHJlc29sdmVkLiBgICtcbiAgICAgICAgICAgICAgICBgVGhpcyBpcyBtb3N0IGxpa2VseSBkdWUgdG8gYSBwZXJzaXN0ZW50IG91dGFnZSBvZiB0aGUgd29ya2Zsb3cgYmFja2VuZCBgICtcbiAgICAgICAgICAgICAgICBgb3IgYSBidWcgaW4gdGhlIHdvcmtmbG93IHJ1bnRpbWUgYW5kIHNob3VsZCBiZSByZXBvcnRlZCB0byB0aGUgV29ya2Zsb3cgdGVhbS5gLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgZXJyb3I6IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKSxcbiAgICAgICAgICAgICAgICBhdHRlbXB0OiBtZXRhZGF0YS5hdHRlbXB0LFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBzcGFuTGlua3MgPSBhd2FpdCBsaW5rVG9DdXJyZW50Q29udGV4dCgpO1xuXG4gICAgICAgIC8vIC0tLSBSZXBsYXkgdGltZW91dCBndWFyZCAtLS1cbiAgICAgICAgLy8gSWYgdGhlIHJlcGxheSB0YWtlcyBsb25nZXIgdGhhbiB0aGUgdGltZW91dCwgZmFpbCB0aGUgcnVuIGFuZCBleGl0LlxuICAgICAgICAvLyBUaGlzIG11c3QgYmUgbG93ZXIgdGhhbiB0aGUgZnVuY3Rpb24ncyBtYXhEdXJhdGlvbiB0byBlbnN1cmVcbiAgICAgICAgLy8gdGhlIGZhaWx1cmUgaXMgcmVjb3JkZWQgYmVmb3JlIHRoZSBwbGF0Zm9ybSBraWxscyB0aGUgZnVuY3Rpb24uXG4gICAgICAgIGxldCByZXBsYXlUaW1lb3V0OiBOb2RlSlMuVGltZW91dCB8IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKHByb2Nlc3MuZW52LlZFUkNFTF9VUkwgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHJlcGxheVRpbWVvdXQgPSBzZXRUaW1lb3V0KGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuZXJyb3IoJ1dvcmtmbG93IHJlcGxheSBleGNlZWRlZCB0aW1lb3V0Jywge1xuICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgdGltZW91dE1zOiBSRVBMQVlfVElNRU9VVF9NUyxcbiAgICAgICAgICAgICAgYXR0ZW1wdDogbWV0YWRhdGEuYXR0ZW1wdCxcbiAgICAgICAgICAgICAgbWF4UmV0cmllczogUkVQTEFZX1RJTUVPVVRfTUFYX1JFVFJJRVMsXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgLy8gQWxsb3cgYSBmZXcgcmV0cmllcyBiZWZvcmUgcGVybWFuZW50bHkgZmFpbGluZyB0aGUgcnVuLlxuICAgICAgICAgICAgLy8gT24gZWFybHkgYXR0ZW1wdHMsIGp1c3QgZXhpdCBzbyB0aGUgcXVldWUgcmV0cmllcyB0aGUgbWVzc2FnZS5cbiAgICAgICAgICAgIGlmIChtZXRhZGF0YS5hdHRlbXB0IDw9IFJFUExBWV9USU1FT1VUX01BWF9SRVRSSUVTKSB7XG4gICAgICAgICAgICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgY29uc3Qgd29ybGQgPSBhd2FpdCBnZXRXb3JsZCgpO1xuICAgICAgICAgICAgICBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKFxuICAgICAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIGV2ZW50VHlwZTogJ3J1bl9mYWlsZWQnLFxuICAgICAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yOiB7XG4gICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogYFdvcmtmbG93IHJlcGxheSBleGNlZWRlZCBtYXhpbXVtIGR1cmF0aW9uICgke1JFUExBWV9USU1FT1VUX01TIC8gMTAwMH1zKSBhZnRlciAke21ldGFkYXRhLmF0dGVtcHR9IGF0dGVtcHRzYCxcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JDb2RlOiBSVU5fRVJST1JfQ09ERVMuUkVQTEFZX1RJTUVPVVQsXG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgeyByZXF1ZXN0SWQgfVxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICAgIC8vIEJlc3QgZWZmb3J0IOKAlCBwcm9jZXNzIGV4aXRzIHJlZ2FyZGxlc3NcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIE5vdGUgdGhhdCB0aGlzIGFsc28gcHJldmVudHMgdGhlIHJ1bnRpbWUgZnJvbSBhY2tpbmcgdGhlIHF1ZXVlIG1lc3NhZ2UsXG4gICAgICAgICAgICAvLyBzbyB0aGUgcXVldWUgd2lsbCBjYWxsIGJhY2sgb25jZSwgYWZ0ZXIgd2hpY2ggYSA0MTAgd2lsbCBnZXQgaXQgdG8gZXhpdCBlYXJseS5cbiAgICAgICAgICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgICAgICAgICB9LCBSRVBMQVlfVElNRU9VVF9NUyk7XG4gICAgICAgICAgcmVwbGF5VGltZW91dC51bnJlZigpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSW52b2tlIHVzZXIgd29ya2Zsb3cgd2l0aGluIHRoZSBwcm9wYWdhdGVkIHRyYWNlIGNvbnRleHQgYW5kIGJhZ2dhZ2VcbiAgICAgICAgcmV0dXJuIGF3YWl0IHdpdGhUcmFjZUNvbnRleHQodHJhY2VDb250ZXh0LCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgLy8gU2V0IHdvcmtmbG93IGNvbnRleHQgYXMgYmFnZ2FnZSBmb3IgYXV0b21hdGljIHByb3BhZ2F0aW9uXG4gICAgICAgICAgcmV0dXJuIGF3YWl0IHdpdGhXb3JrZmxvd0JhZ2dhZ2UoXG4gICAgICAgICAgICB7IHdvcmtmbG93UnVuSWQ6IHJ1bklkLCB3b3JrZmxvd05hbWUgfSxcbiAgICAgICAgICAgIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgICAgY29uc3Qgd29ybGQgPSBhd2FpdCBnZXRXb3JsZCgpO1xuICAgICAgICAgICAgICByZXR1cm4gdHJhY2UoXG4gICAgICAgICAgICAgICAgYFdPUktGTE9XICR7d29ya2Zsb3dOYW1lfWAsXG4gICAgICAgICAgICAgICAgeyBsaW5rczogc3BhbkxpbmtzIH0sXG4gICAgICAgICAgICAgICAgYXN5bmMgKHNwYW4pID0+IHtcbiAgICAgICAgICAgICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dOYW1lKHdvcmtmbG93TmFtZSksXG4gICAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd09wZXJhdGlvbignZXhlY3V0ZScpLFxuICAgICAgICAgICAgICAgICAgICAvLyBTdGFuZGFyZCBPVEVMIG1lc3NhZ2luZyBjb252ZW50aW9uc1xuICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuTWVzc2FnaW5nU3lzdGVtKCd2ZXJjZWwtcXVldWUnKSxcbiAgICAgICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLk1lc3NhZ2luZ0Rlc3RpbmF0aW9uTmFtZShtZXRhZGF0YS5xdWV1ZU5hbWUpLFxuICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuTWVzc2FnaW5nTWVzc2FnZUlkKG1ldGFkYXRhLm1lc3NhZ2VJZCksXG4gICAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5NZXNzYWdpbmdPcGVyYXRpb25UeXBlKCdwcm9jZXNzJyksXG4gICAgICAgICAgICAgICAgICAgIC4uLmdldFF1ZXVlT3ZlcmhlYWQoeyByZXF1ZXN0ZWRBdCB9KSxcbiAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAvLyBUT0RPOiB2YWxpZGF0ZSBgd29ya2Zsb3dOYW1lYCBleGlzdHMgYmVmb3JlIGNvbnN1bWluZyBtZXNzYWdlP1xuXG4gICAgICAgICAgICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLldvcmtmbG93UnVuSWQocnVuSWQpLFxuICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dUcmFjZVByb3BhZ2F0ZWQoISF0cmFjZUNvbnRleHQpLFxuICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgIGxldCB3b3JrZmxvd1N0YXJ0ZWRBdCA9IC0xO1xuICAgICAgICAgICAgICAgICAgbGV0IHdvcmtmbG93UnVuOiBXb3JrZmxvd1J1biB8IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgIC8vIFByZS1sb2FkZWQgZXZlbnRzIGZyb20gdGhlIHJ1bl9zdGFydGVkIHJlc3BvbnNlLlxuICAgICAgICAgICAgICAgICAgLy8gV2hlbiBwcmVzZW50LCB3ZSBza2lwIHRoZSBldmVudHMubGlzdCBjYWxsIHRvIHJlZHVjZSBUVEZCLlxuICAgICAgICAgICAgICAgICAgbGV0IHByZWxvYWRlZEV2ZW50czogRXZlbnRbXSB8IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgICAgLy8gLS0tIEluZnJhc3RydWN0dXJlOiBwcmVwYXJlIHRoZSBydW4gc3RhdGUgLS0tXG4gICAgICAgICAgICAgICAgICAvLyBBbHdheXMgY2FsbCBydW5fc3RhcnRlZCBkaXJlY3RseSDigJQgdGhpcyBib3RoIHRyYW5zaXRpb25zXG4gICAgICAgICAgICAgICAgICAvLyB0aGUgcnVuIHRvICdydW5uaW5nJyBBTkQgcmV0dXJucyB0aGUgcnVuIGVudGl0eSwgc2F2aW5nXG4gICAgICAgICAgICAgICAgICAvLyBhIHNlcGFyYXRlIHJ1bnMuZ2V0IHJvdW5kLXRyaXAuXG4gICAgICAgICAgICAgICAgICAvLyBDb250cmFjdDogZXZlbnRzLmNyZWF0ZSgncnVuX3N0YXJ0ZWQnKSBtdXN0IGJlIGlkZW1wb3RlbnRcbiAgICAgICAgICAgICAgICAgIC8vIGZvciBydW5zIGFscmVhZHkgaW4gJ3J1bm5pbmcnIHN0YXR1cyAocmV0dXJuIHRoZSBydW5cbiAgICAgICAgICAgICAgICAgIC8vIHdpdGhvdXQgZXJyb3IpLCBub3QganVzdCBmb3IgcGVuZGluZyDihpIgcnVubmluZyB0cmFuc2l0aW9ucy5cbiAgICAgICAgICAgICAgICAgIC8vIE5ldHdvcmsvc2VydmVyIGVycm9ycyBwcm9wYWdhdGUgdG8gdGhlIHF1ZXVlIGhhbmRsZXIgZm9yIHJldHJ5LlxuICAgICAgICAgICAgICAgICAgLy8gV29ya2Zsb3dSdW50aW1lRXJyb3IgKGRhdGEgaW50ZWdyaXR5IGlzc3VlcykgYXJlIGZhdGFsIGFuZFxuICAgICAgICAgICAgICAgICAgLy8gcHJvZHVjZSBydW5fZmFpbGVkIHNpbmNlIHJldHJ5aW5nIHdvbid0IGZpeCB0aGVtLlxuICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgd29ybGQuZXZlbnRzLmNyZWF0ZShcbiAgICAgICAgICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudFR5cGU6ICdydW5fc3RhcnRlZCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBVc2UgdGhlIHNwZWMgdmVyc2lvbiBmcm9tIHRoZSBvcmlnaW5hbCBzdGFydCgpIGNhbGxcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHdoZW4gYXZhaWxhYmxlLCBzbyB0aGUgcmVzaWxpZW50IHN0YXJ0IHBhdGggY3JlYXRlc1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIHJ1biB3aXRoIHRoZSBjb3JyZWN0IHZlcnNpb24gKG5vdCBhbHdheXMgY3VycmVudCkuXG4gICAgICAgICAgICAgICAgICAgICAgICBzcGVjVmVyc2lvbjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcnVuSW5wdXQ/LnNwZWNWZXJzaW9uID8/IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gUGFzcyBydW4gaW5wdXQgZnJvbSBxdWV1ZSBzbyB0aGUgc2VydmVyIGNhblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gY3JlYXRlIHRoZSBydW4gaWYgcnVuX2NyZWF0ZWQgd2FzIG1pc3NlZC5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFVpbnQ4QXJyYXkgdmFsdWVzIHN1cnZpdmUgdGhlIHF1ZXVlIG5hdGl2ZWx5XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAoQ0JPUiBvbiB3b3JsZC12ZXJjZWwsIEpTT04gcmV2aXZlciBvbiB3b3JsZC1sb2NhbCkuXG4gICAgICAgICAgICAgICAgICAgICAgICAuLi4ocnVuSW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgPyB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXQ6IHJ1bklucHV0LmlucHV0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXBsb3ltZW50SWQ6IHJ1bklucHV0LmRlcGxveW1lbnRJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dOYW1lOiBydW5JbnB1dC53b3JrZmxvd05hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4ZWN1dGlvbkNvbnRleHQ6IHJ1bklucHV0LmV4ZWN1dGlvbkNvbnRleHQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgOiB7fSksXG4gICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICB7IHJlcXVlc3RJZCB9XG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIGlmICghcmVzdWx0LnJ1bikge1xuICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBXb3JrZmxvd1J1bnRpbWVFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgICAgIGBFdmVudCBjcmVhdGlvbiBmb3IgJ3J1bl9zdGFydGVkJyBkaWQgbm90IHJldHVybiB0aGUgcnVuIGVudGl0eSBmb3IgcnVuIFwiJHtydW5JZH1cImBcbiAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuID0gcmVzdWx0LnJ1bjtcblxuICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgcmVzcG9uc2UgaW5jbHVkZXMgZXZlbnRzLCB1c2UgdGhlbSB0byBza2lwXG4gICAgICAgICAgICAgICAgICAgIC8vIHRoZSBpbml0aWFsIGV2ZW50cy5saXN0IGNhbGwgYW5kIHJlZHVjZSBUVEZCLlxuICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0LmV2ZW50cyAmJiByZXN1bHQuZXZlbnRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICBwcmVsb2FkZWRFdmVudHMgPSByZXN1bHQuZXZlbnRzO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCF3b3JrZmxvd1J1bi5zdGFydGVkQXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgV29ya2Zsb3dSdW50aW1lRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgICBgV29ya2Zsb3cgcnVuIFwiJHtydW5JZH1cIiBoYXMgbm8gXCJzdGFydGVkQXRcIiB0aW1lc3RhbXBgXG4gICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJ1biB3YXMgY29uY3VycmVudGx5IGNvbXBsZXRlZC9mYWlsZWQvY2FuY2VsbGVkXG4gICAgICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgICBFbnRpdHlDb25mbGljdEVycm9yLmlzKGVycikgfHxcbiAgICAgICAgICAgICAgICAgICAgICBSdW5FeHBpcmVkRXJyb3IuaXMoZXJyKVxuICAgICAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgICAvLyBFbnRpdHlDb25mbGljdEVycm9yOiBydW4gd2FzIGNvbmN1cnJlbnRseVxuICAgICAgICAgICAgICAgICAgICAgIC8vIGNvbXBsZXRlZC9mYWlsZWQvY2FuY2VsbGVkIGR1cmluZyBzZXR1cC5cbiAgICAgICAgICAgICAgICAgICAgICAvLyBSdW5FeHBpcmVkRXJyb3I6IHJ1biBhbHJlYWR5IGluIHRlcm1pbmFsIHN0YXRlLlxuICAgICAgICAgICAgICAgICAgICAgIC8vIEluIGJvdGggY2FzZXMsIHNraXAgcHJvY2Vzc2luZyB0aGlzIG1lc3NhZ2UuXG4gICAgICAgICAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAgICAgICAgICAgJ1J1biBhbHJlYWR5IGZpbmlzaGVkIGR1cmluZyBzZXR1cCwgc2tpcHBpbmcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgeyB3b3JrZmxvd1J1bklkOiBydW5JZCwgbWVzc2FnZTogZXJyLm1lc3NhZ2UgfVxuICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGVyciBpbnN0YW5jZW9mIFdvcmtmbG93UnVudGltZUVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5lcnJvcihcbiAgICAgICAgICAgICAgICAgICAgICAgICdGYXRhbCBydW50aW1lIGVycm9yIGR1cmluZyB3b3JrZmxvdyBzZXR1cCcsXG4gICAgICAgICAgICAgICAgICAgICAgICB7IHdvcmtmbG93UnVuSWQ6IHJ1bklkLCBlcnJvcjogZXJyLm1lc3NhZ2UgfVxuICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGUoXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRUeXBlOiAncnVuX2ZhaWxlZCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3I6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YWNrOiBlcnIuc3RhY2ssXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDb2RlOiBSVU5fRVJST1JfQ09ERVMuUlVOVElNRV9FUlJPUixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICB7IHJlcXVlc3RJZCB9XG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGZhaWxFcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgRW50aXR5Q29uZmxpY3RFcnJvci5pcyhmYWlsRXJyKSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICBSdW5FeHBpcmVkRXJyb3IuaXMoZmFpbEVycilcbiAgICAgICAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBmYWlsRXJyO1xuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgIHdvcmtmbG93U3RhcnRlZEF0ID0gK3dvcmtmbG93UnVuLnN0YXJ0ZWRBdDtcblxuICAgICAgICAgICAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd1J1blN0YXR1cyh3b3JrZmxvd1J1bi5zdGF0dXMpLFxuICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dTdGFydGVkQXQod29ya2Zsb3dTdGFydGVkQXQpLFxuICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgIGlmICh3b3JrZmxvd1J1bi5zdGF0dXMgIT09ICdydW5uaW5nJykge1xuICAgICAgICAgICAgICAgICAgICAvLyBXb3JrZmxvdyBoYXMgYWxyZWFkeSBjb21wbGV0ZWQgb3IgZmFpbGVkLCBzbyB3ZSBjYW4gc2tpcCBpdFxuICAgICAgICAgICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICAgICAgICAgJ1dvcmtmbG93IGFscmVhZHkgY29tcGxldGVkIG9yIGZhaWxlZCwgc2tpcHBpbmcnLFxuICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgc3RhdHVzOiB3b3JrZmxvd1J1bi5zdGF0dXMsXG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIFRPRE86IGZvciBgY2FuY2VsYCwgd2UgYWN0dWFsbHkgd2FudCB0byBwcm9wYWdhdGUgYSBXb3JrZmxvd0NhbmNlbGxlZCBldmVudFxuICAgICAgICAgICAgICAgICAgICAvLyBpbnNpZGUgdGhlIHdvcmtmbG93IGNvbnRleHQgc28gdGhlIHVzZXIgY2FuIGdyYWNlZnVsbHkgZXhpdC4gdGhpcyBpcyBTSUdURVJNXG4gICAgICAgICAgICAgICAgICAgIC8vIFRPRE86IGZ1cnRoZXJtb3JlLCB0aGVyZSBzaG91bGQgYmUgYSB0aW1lb3V0IG9yIGEgd2F5IHRvIGZvcmNlIGNhbmNlbCBTSUdLSUxMXG4gICAgICAgICAgICAgICAgICAgIC8vIHNvIHRoYXQgd2UgYWN0dWFsbHkgZXhpdCBoZXJlIHdpdGhvdXQgcmVwbGF5aW5nIHRoZSB3b3JrZmxvdyBhdCBhbGwsIGluIHRoZSBjYXNlXG4gICAgICAgICAgICAgICAgICAgIC8vIHRoZSByZXBsYXlpbmcgdGhlIHdvcmtmbG93IGlzIGl0c2VsZiBmYWlsaW5nLlxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgLy8gTG9hZCBhbGwgZXZlbnRzIGludG8gbWVtb3J5IGJlZm9yZSBydW5uaW5nLlxuICAgICAgICAgICAgICAgICAgLy8gSWYgd2UgZ290IHByZS1sb2FkZWQgZXZlbnRzIGZyb20gdGhlIHJ1bl9zdGFydGVkIHJlc3BvbnNlLFxuICAgICAgICAgICAgICAgICAgLy8gc2tpcCB0aGUgZXZlbnRzLmxpc3Qgcm91bmQtdHJpcCB0byByZWR1Y2UgVFRGQi5cbiAgICAgICAgICAgICAgICAgIGNvbnN0IGV2ZW50cyA9XG4gICAgICAgICAgICAgICAgICAgIHByZWxvYWRlZEV2ZW50cyA/P1xuICAgICAgICAgICAgICAgICAgICAoYXdhaXQgZ2V0QWxsV29ya2Zsb3dSdW5FdmVudHMod29ya2Zsb3dSdW4ucnVuSWQpKTtcblxuICAgICAgICAgICAgICAgICAgLy8gQ2hlY2sgZm9yIGFueSBlbGFwc2VkIHdhaXRzIGFuZCBjcmVhdGUgd2FpdF9jb21wbGV0ZWQgZXZlbnRzXG4gICAgICAgICAgICAgICAgICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuXG4gICAgICAgICAgICAgICAgICAvLyBQcmUtY29tcHV0ZSBjb21wbGV0ZWQgY29ycmVsYXRpb24gSURzIGZvciBPKG4pIGxvb2t1cCBpbnN0ZWFkIG9mIE8obsKyKVxuICAgICAgICAgICAgICAgICAgY29uc3QgY29tcGxldGVkV2FpdElkcyA9IG5ldyBTZXQoXG4gICAgICAgICAgICAgICAgICAgIGV2ZW50c1xuICAgICAgICAgICAgICAgICAgICAgIC5maWx0ZXIoKGUpID0+IGUuZXZlbnRUeXBlID09PSAnd2FpdF9jb21wbGV0ZWQnKVxuICAgICAgICAgICAgICAgICAgICAgIC5tYXAoKGUpID0+IGUuY29ycmVsYXRpb25JZClcbiAgICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICAgIC8vIENvbGxlY3QgYWxsIHdhaXRzIHRoYXQgbmVlZCBjb21wbGV0aW9uXG4gICAgICAgICAgICAgICAgICBjb25zdCB3YWl0c1RvQ29tcGxldGUgPSBldmVudHNcbiAgICAgICAgICAgICAgICAgICAgLmZpbHRlcihcbiAgICAgICAgICAgICAgICAgICAgICAoZSk6IGUgaXMgdHlwZW9mIGUgJiB7IGNvcnJlbGF0aW9uSWQ6IHN0cmluZyB9ID0+XG4gICAgICAgICAgICAgICAgICAgICAgICBlLmV2ZW50VHlwZSA9PT0gJ3dhaXRfY3JlYXRlZCcgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIGUuY29ycmVsYXRpb25JZCAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAhY29tcGxldGVkV2FpdElkcy5oYXMoZS5jb3JyZWxhdGlvbklkKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgbm93ID49IChlLmV2ZW50RGF0YS5yZXN1bWVBdCBhcyBEYXRlKS5nZXRUaW1lKClcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAubWFwKChlKSA9PiAoe1xuICAgICAgICAgICAgICAgICAgICAgIGV2ZW50VHlwZTogJ3dhaXRfY29tcGxldGVkJyBhcyBjb25zdCxcbiAgICAgICAgICAgICAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogZS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgICAgICB9KSk7XG5cbiAgICAgICAgICAgICAgICAgIC8vIENyZWF0ZSBhbGwgd2FpdF9jb21wbGV0ZWQgZXZlbnRzXG4gICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHdhaXRFdmVudCBvZiB3YWl0c1RvQ29tcGxldGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKFxuICAgICAgICAgICAgICAgICAgICAgICAgcnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICB3YWl0RXZlbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJlcXVlc3RJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCB0aGUgZXZlbnQgdG8gdGhlIGV2ZW50cyBhcnJheSBzbyB0aGUgd29ya2Zsb3cgY2FuIHNlZSBpdFxuICAgICAgICAgICAgICAgICAgICAgIGV2ZW50cy5wdXNoKHJlc3VsdC5ldmVudCEpO1xuICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oJ1dhaXQgYWxyZWFkeSBjb21wbGV0ZWQsIHNraXBwaW5nJywge1xuICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogd2FpdEV2ZW50LmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgLy8gUmVzb2x2ZSB0aGUgZW5jcnlwdGlvbiBrZXkgZm9yIHRoaXMgcnVuJ3MgZGVwbG95bWVudFxuICAgICAgICAgICAgICAgICAgY29uc3QgcmF3S2V5ID1cbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgd29ybGQuZ2V0RW5jcnlwdGlvbktleUZvclJ1bj8uKHdvcmtmbG93UnVuKTtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IGVuY3J5cHRpb25LZXkgPSByYXdLZXlcbiAgICAgICAgICAgICAgICAgICAgPyBhd2FpdCBpbXBvcnRLZXkocmF3S2V5KVxuICAgICAgICAgICAgICAgICAgICA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgICAgLy8gLS0tIFVzZXIgY29kZSBleGVjdXRpb24gLS0tXG4gICAgICAgICAgICAgICAgICAvLyBPbmx5IGVycm9ycyBmcm9tIHJ1bldvcmtmbG93KCkgKHVzZXIgd29ya2Zsb3cgY29kZSkgc2hvdWxkXG4gICAgICAgICAgICAgICAgICAvLyBwcm9kdWNlIHJ1bl9mYWlsZWQuIEluZnJhc3RydWN0dXJlIGVycm9ycyAobmV0d29yaywgc2VydmVyKVxuICAgICAgICAgICAgICAgICAgLy8gbXVzdCBwcm9wYWdhdGUgdG8gdGhlIHF1ZXVlIGhhbmRsZXIgZm9yIGF1dG9tYXRpYyByZXRyeS5cbiAgICAgICAgICAgICAgICAgIGxldCB3b3JrZmxvd1Jlc3VsdDogdW5rbm93bjtcbiAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UmVzdWx0ID0gYXdhaXQgdHJhY2UoXG4gICAgICAgICAgICAgICAgICAgICAgJ3dvcmtmbG93LnJlcGxheScsXG4gICAgICAgICAgICAgICAgICAgICAge30sXG4gICAgICAgICAgICAgICAgICAgICAgYXN5bmMgKHJlcGxheVNwYW4pID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlcGxheVNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dFdmVudHNDb3VudChldmVudHMubGVuZ3RoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHJ1bldvcmtmbG93KFxuICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd0NvZGUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGVuY3J5cHRpb25LZXlcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFdvcmtmbG93U3VzcGVuc2lvbiBpcyBub3JtYWwgY29udHJvbCBmbG93IOKAlCBub3QgYW4gZXJyb3JcbiAgICAgICAgICAgICAgICAgICAgaWYgKFdvcmtmbG93U3VzcGVuc2lvbi5pcyhlcnIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3VzcGVuc2lvbk1lc3NhZ2UgPSBidWlsZFdvcmtmbG93U3VzcGVuc2lvbk1lc3NhZ2UoXG4gICAgICAgICAgICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGVyci5zdGVwQ291bnQsXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnIuaG9va0NvdW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyLndhaXRDb3VudFxuICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgaWYgKHN1c3BlbnNpb25NZXNzYWdlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBydW50aW1lTG9nZ2VyLmRlYnVnKHN1c3BlbnNpb25NZXNzYWdlKTtcbiAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBoYW5kbGVTdXNwZW5zaW9uKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN1c3BlbnNpb246IGVycixcbiAgICAgICAgICAgICAgICAgICAgICAgIHdvcmxkLFxuICAgICAgICAgICAgICAgICAgICAgICAgcnVuOiB3b3JrZmxvd1J1bixcbiAgICAgICAgICAgICAgICAgICAgICAgIHNwYW4sXG4gICAgICAgICAgICAgICAgICAgICAgICByZXF1ZXN0SWQsXG4gICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0LnRpbWVvdXRTZWNvbmRzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7IHRpbWVvdXRTZWNvbmRzOiByZXN1bHQudGltZW91dFNlY29uZHMgfTtcbiAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAvLyBTdXNwZW5zaW9uIGhhbmRsZWQsIG5vIGZ1cnRoZXIgd29yayBuZWVkZWRcbiAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIGlzIGEgdXNlciBjb2RlIGVycm9yIG9yIGEgV29ya2Zsb3dSdW50aW1lRXJyb3JcbiAgICAgICAgICAgICAgICAgICAgLy8gKGUuZy4sIGNvcnJ1cHRlZCBldmVudCBsb2cpLiBGYWlsIHRoZSB3b3JrZmxvdyBydW4uXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gUmVjb3JkIGV4Y2VwdGlvbiBmb3IgT1RFTCBlcnJvciB0cmFja2luZ1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICBzcGFuPy5yZWNvcmRFeGNlcHRpb24/LihlcnIpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgbm9ybWFsaXplZEVycm9yID0gYXdhaXQgbm9ybWFsaXplVW5rbm93bkVycm9yKGVycik7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yTmFtZSA9IG5vcm1hbGl6ZWRFcnJvci5uYW1lIHx8IGdldEVycm9yTmFtZShlcnIpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSBub3JtYWxpemVkRXJyb3IubWVzc2FnZTtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yU3RhY2sgPVxuICAgICAgICAgICAgICAgICAgICAgIG5vcm1hbGl6ZWRFcnJvci5zdGFjayB8fCBnZXRFcnJvclN0YWNrKGVycik7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gUmVtYXAgZXJyb3Igc3RhY2sgdXNpbmcgc291cmNlIG1hcHMgdG8gc2hvdyBvcmlnaW5hbCBzb3VyY2UgbG9jYXRpb25zXG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvclN0YWNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgcGFyc2VkTmFtZSA9IHBhcnNlV29ya2Zsb3dOYW1lKHdvcmtmbG93TmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgZmlsZW5hbWUgPVxuICAgICAgICAgICAgICAgICAgICAgICAgcGFyc2VkTmFtZT8ubW9kdWxlU3BlY2lmaWVyIHx8IHdvcmtmbG93TmFtZTtcbiAgICAgICAgICAgICAgICAgICAgICBlcnJvclN0YWNrID0gcmVtYXBFcnJvclN0YWNrKFxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JTdGFjayxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGVuYW1lLFxuICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dDb2RlXG4gICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIENsYXNzaWZ5IHRoZSBlcnJvcjogV29ya2Zsb3dSdW50aW1lRXJyb3IgaW5kaWNhdGVzIGFuXG4gICAgICAgICAgICAgICAgICAgIC8vIGludGVybmFsIGlzc3VlIChjb3JydXB0ZWQgZXZlbnQgbG9nLCBtaXNzaW5nIGRhdGEpO1xuICAgICAgICAgICAgICAgICAgICAvLyBldmVyeXRoaW5nIGVsc2UgaXMgYSB1c2VyIGNvZGUgZXJyb3IuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yQ29kZSA9IGNsYXNzaWZ5UnVuRXJyb3IoZXJyKTtcblxuICAgICAgICAgICAgICAgICAgICBydW50aW1lTG9nZ2VyLmVycm9yKCdFcnJvciB3aGlsZSBydW5uaW5nIHdvcmtmbG93Jywge1xuICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ29kZSxcbiAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgZXJyb3JTdGFjayxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gRmFpbCB0aGUgd29ya2Zsb3cgcnVuIHZpYSBldmVudCAoZXZlbnQtc291cmNlZCBhcmNoaXRlY3R1cmUpXG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgYXdhaXQgd29ybGQuZXZlbnRzLmNyZWF0ZShcbiAgICAgICAgICAgICAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudFR5cGU6ICdydW5fZmFpbGVkJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvcjoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyb3JNZXNzYWdlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhY2s6IGVycm9yU3RhY2ssXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNvZGUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgeyByZXF1ZXN0SWQgfVxuICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGZhaWxFcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgICAgICBFbnRpdHlDb25mbGljdEVycm9yLmlzKGZhaWxFcnIpIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICBSdW5FeHBpcmVkRXJyb3IuaXMoZmFpbEVycilcbiAgICAgICAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbyhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgJ1RyaWVkIGZhaWxpbmcgd29ya2Zsb3cgcnVuLCBidXQgcnVuIGhhcyBhbHJlYWR5IGZpbmlzaGVkLicsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBmYWlsRXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLldvcmtmbG93RXJyb3JDb2RlKGVycm9yQ29kZSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd0Vycm9yTmFtZShlcnJvck5hbWUpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dFcnJvck1lc3NhZ2UoZXJyb3JNZXNzYWdlKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLkVycm9yVHlwZShlcnJvck5hbWUpLFxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IGZhaWxFcnI7XG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLldvcmtmbG93UnVuU3RhdHVzKCdmYWlsZWQnKSxcbiAgICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dFcnJvckNvZGUoZXJyb3JDb2RlKSxcbiAgICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dFcnJvck5hbWUoZXJyb3JOYW1lKSxcbiAgICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dFcnJvck1lc3NhZ2UoZXJyb3JNZXNzYWdlKSxcbiAgICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuRXJyb3JUeXBlKGVycm9yTmFtZSksXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgIC8vIC0tLSBJbmZyYXN0cnVjdHVyZTogY29tcGxldGUgdGhlIHJ1biAtLS1cbiAgICAgICAgICAgICAgICAgIC8vIFRoaXMgaXMgb3V0c2lkZSB0aGUgdXNlci1jb2RlIHRyeS9jYXRjaCBzbyB0aGF0IGZhaWx1cmVzXG4gICAgICAgICAgICAgICAgICAvLyBoZXJlIChlLmcuLCBuZXR3b3JrIGVycm9ycykgcHJvcGFnYXRlIHRvIHRoZSBxdWV1ZSBoYW5kbGVyLlxuICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgd29ybGQuZXZlbnRzLmNyZWF0ZShcbiAgICAgICAgICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudFR5cGU6ICdydW5fY29tcGxldGVkJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQ6IHdvcmtmbG93UmVzdWx0LFxuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgIHsgcmVxdWVzdElkIH1cbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgICAgRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpIHx8XG4gICAgICAgICAgICAgICAgICAgICAgUnVuRXhwaXJlZEVycm9yLmlzKGVycilcbiAgICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAgICAgICAgICAgJ1RyaWVkIGNvbXBsZXRpbmcgd29ya2Zsb3cgcnVuLCBidXQgcnVuIGhhcyBhbHJlYWR5IGZpbmlzaGVkLicsXG4gICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd1J1blN0YXR1cygnY29tcGxldGVkJyksXG4gICAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd0V2ZW50c0NvdW50KGV2ZW50cy5sZW5ndGgpLFxuICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICApOyAvLyBFbmQgdHJhY2VcbiAgICAgICAgICAgIH1cbiAgICAgICAgICApOyAvLyBFbmQgd2l0aFdvcmtmbG93QmFnZ2FnZVxuICAgICAgICB9KS5maW5hbGx5KCgpID0+IHtcbiAgICAgICAgICBpZiAocmVwbGF5VGltZW91dCkge1xuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHJlcGxheVRpbWVvdXQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7IC8vIEVuZCB3aXRoVHJhY2VDb250ZXh0XG4gICAgICB9XG4gICAgKTtcblxuICBsZXQgY2FjaGVkSGFuZGxlcjogKChyZXE6IFJlcXVlc3QpID0+IFByb21pc2U8UmVzcG9uc2U+KSB8IHVuZGVmaW5lZDtcbiAgcmV0dXJuIHdpdGhIZWFsdGhDaGVjayhhc3luYyAocmVxKSA9PiB7XG4gICAgaWYgKCFjYWNoZWRIYW5kbGVyKSB7XG4gICAgICBjYWNoZWRIYW5kbGVyID0gaGFuZGxlcihhd2FpdCBnZXRXb3JsZEhhbmRsZXJzKCkpO1xuICAgIH1cbiAgICByZXR1cm4gY2FjaGVkSGFuZGxlcihyZXEpO1xuICB9KTtcbn1cblxuLy8gdGhpcyBpcyBhIG5vLW9wIHBsYWNlaG9sZGVyIGFzIHRoZSBjbGllbnQgaXNcbi8vIGV4cGVjdGluZyB0aGlzIHRvIGJlIHByZXNlbnQgYnV0IHdlIGFyZW4ndCBhY3R1YWxseSB1c2luZyBpdFxuZXhwb3J0IGZ1bmN0aW9uIHJ1blN0ZXAoKSB7fVxuIl19
3260
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVudGltZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9ydW50aW1lLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sTUFBTSxNQUFNLG9CQUFvQixDQUFDO0FBQ3hDLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDbEMsT0FBTyxFQUNMLHNCQUFzQixFQUN0QixtQkFBbUIsRUFDbkIsVUFBVSxFQUNWLGlCQUFpQixFQUNqQixzQkFBc0IsRUFDdEIsdUJBQXVCLEVBQ3ZCLHFCQUFxQixFQUNyQixlQUFlLEVBRWYsZUFBZSxFQUNmLG9CQUFvQixHQUNyQixNQUFNLGtCQUFrQixDQUFDO0FBQzFCLE9BQU8sRUFBRSxJQUFJLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUM1RCxPQUFPLEVBQ0wsaUJBQWlCLEVBQ2pCLG1CQUFtQixHQUNwQixNQUFNLDRCQUE0QixDQUFDO0FBQ3BDLE9BQU8sRUFLTCxtQkFBbUIsRUFDbkIsbUJBQW1CLEVBQ25CLHNCQUFzQixFQUN0QixxQkFBcUIsRUFFckIscUJBQXFCLEVBQ3JCLG9CQUFvQixFQUNwQixpQ0FBaUMsRUFFakMsMkJBQTJCLEdBRzVCLE1BQU0saUJBQWlCLENBQUM7QUFDekIsT0FBTyxFQUFFLE1BQU0sSUFBSSxDQUFDO0FBQ3BCLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDbEMsT0FBTyxFQUNMLGdCQUFnQixFQUNoQixxQkFBcUIsRUFDckIsb0JBQW9CLEdBQ3JCLE1BQU0scUJBQXFCLENBQUM7QUFDN0IsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3BELE9BQU8sRUFBZ0Msa0JBQWtCLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDL0UsT0FBTyxFQUFlLGFBQWEsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUN6RCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQy9DLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQy9ELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ3BFLE9BQU8sRUFDTCxvQkFBb0IsRUFDcEIscUJBQXFCLEVBQ3JCLG1DQUFtQyxFQUNuQywrQkFBK0IsRUFDL0IsbUNBQW1DLEVBQ25DLDZCQUE2QixFQUM3Qix3QkFBd0IsRUFDeEIsY0FBYyxFQUNkLG9CQUFvQixHQUNyQixNQUFNLHdCQUF3QixDQUFDO0FBQ2hDLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLHdDQUF3QyxDQUFDO0FBQ2hGLE9BQU8sRUFFTCx1QkFBdUIsR0FFeEIsTUFBTSwrQkFBK0IsQ0FBQztBQUN2QyxPQUFPLEVBQ0wsa0JBQWtCLEVBQ2xCLGdCQUFnQixFQUNoQixvQkFBb0IsRUFDcEIsd0JBQXdCLEVBQ3hCLG9CQUFvQixFQUNwQiwwQkFBMEIsRUFDMUIscUJBQXFCLEVBRXJCLHFCQUFxQixFQUNyQixvQkFBb0IsRUFDcEIsbUJBQW1CLEVBQ25CLHVCQUF1QixFQUN2QixzQkFBc0IsRUFDdEIsMEJBQTBCLEVBQzFCLFlBQVksRUFDWixrQkFBa0IsRUFDbEIsZUFBZSxHQUNoQixNQUFNLHNCQUFzQixDQUFDO0FBQzlCLE9BQU8sRUFDTCwyQkFBMkIsRUFDM0IsWUFBWSxHQUNiLE1BQU0sNEJBQTRCLENBQUM7QUFDcEMsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sdUNBQXVDLENBQUM7QUFDL0UsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQzFELE9BQU8sRUFDTCx3QkFBd0IsRUFDeEIsV0FBVyxHQUNaLE1BQU0sNEJBQTRCLENBQUM7QUFDcEMsT0FBTyxFQUFFLDBCQUEwQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDdkUsT0FBTyxFQUNMLHNCQUFzQixFQUN0Qiw0QkFBNEIsRUFDNUIscUJBQXFCLEVBQ3JCLHlCQUF5QixHQUMxQixNQUFNLDZCQUE2QixDQUFDO0FBQ3JDLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ3RFLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ25FLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUNwRCxPQUFPLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUM3RSxPQUFPLEVBQ0wsUUFBUSxFQUNSLGdCQUFnQixHQUVqQixNQUFNLG9CQUFvQixDQUFDO0FBQzVCLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNsRCxPQUFPLEtBQUssU0FBUyxNQUFNLHFDQUFxQyxDQUFDO0FBQ2pFLE9BQU8sRUFDTCx3QkFBd0IsRUFDeEIsbUJBQW1CLEVBQ25CLFdBQVcsRUFDWCxvQkFBb0IsRUFDcEIsb0JBQW9CLEVBQ3BCLEtBQUssRUFDTCxnQkFBZ0IsRUFDaEIsbUJBQW1CLEdBQ3BCLE1BQU0sZ0JBQWdCLENBQUM7QUFDeEIsT0FBTyxFQUFFLFlBQVksRUFBRSxhQUFhLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDaEYsT0FBTyxFQUFFLDhCQUE4QixFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQzNELE9BQU8sRUFDTCxjQUFjLEVBQ2QsY0FBYyxHQUdmLE1BQU0sZUFBZSxDQUFDO0FBR3ZCLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNqRCxPQUFPLEVBR0wsV0FBVyxHQUNaLE1BQU0sc0JBQXNCLENBQUM7QUFDOUIsT0FBTyxFQUNMLGNBQWMsRUFFZCxVQUFVLEVBQ1YsYUFBYSxHQUNkLE1BQU0sMEJBQTBCLENBQUM7QUFDbEMsT0FBTyxFQUNMLE1BQU0sRUFDTixHQUFHLEdBR0osTUFBTSxrQkFBa0IsQ0FBQztBQUMxQixPQUFPLEVBRUwsU0FBUyxFQUNULFVBQVUsRUFDVixXQUFXLEVBSVgsVUFBVSxFQUNWLHVCQUF1QixFQUN2QixZQUFZLEVBR1osU0FBUyxHQUNWLE1BQU0sbUJBQW1CLENBQUM7QUFDM0IsT0FBTyxFQUtMLEtBQUssR0FDTixNQUFNLG9CQUFvQixDQUFDO0FBQzVCLE9BQU8sRUFDTCxXQUFXLEVBQ1gscUJBQXFCLEVBQ3JCLFFBQVEsRUFDUixnQkFBZ0IsRUFDaEIsUUFBUSxHQUVULE1BQU0sb0JBQW9CLENBQUM7QUFFNUI7Ozs7Ozs7R0FPRztBQUNILFNBQVMsY0FBYyxDQUFDLFdBQStCO0lBQ3JELE1BQU0sUUFBUSxHQUFHLG9CQUFvQixFQUFFLENBQUM7SUFDeEMsSUFBSSxRQUFRLEtBQUssU0FBUztRQUFFLE9BQU8sV0FBVyxDQUFDO0lBQy9DLE9BQU8sV0FBVyxLQUFLLFNBQVMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxRQUFRLENBQUMsQ0FBQztBQUNoRixDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F5Qkc7QUFDSCxTQUFTLDhCQUE4QixDQUFDLEVBQ3RDLEtBQUssRUFDTCxRQUFRLEVBQ1IsS0FBSyxFQUNMLFNBQVMsR0FNVjtJQUNDLE1BQU0sa0JBQWtCLEdBQUcsUUFBUSxFQUFFLFdBQVcsQ0FBQztJQUNqRCxJQUFJLENBQUMsa0JBQWtCO1FBQUUsT0FBTyxLQUFLLENBQUM7SUFFdEMsTUFBTSxrQkFBa0IsR0FBRyxLQUFLLENBQUMsY0FBYyxFQUFFLEVBQUUsQ0FBQztJQUNwRCxJQUFJLENBQUMsa0JBQWtCLElBQUksa0JBQWtCLEtBQUssa0JBQWtCLEVBQUUsQ0FBQztRQUNyRSxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFFRCxTQUFTLENBQUMsS0FBSyxDQUNiLHlEQUF5RCxrQkFBa0IsSUFBSTtRQUM3RSw0Q0FBNEMsa0JBQWtCLEtBQUs7UUFDbkUscUVBQXFFO1FBQ3JFLHNFQUFzRTtRQUN0RSxxRUFBcUU7UUFDckUsc0VBQXNFO1FBQ3RFLHdFQUF3RTtRQUN4RSx5RUFBeUU7UUFDekUsbUVBQW1FO1FBQ25FLHdFQUF3RTtRQUN4RSx1Q0FBdUMsa0JBQWtCLGFBQWE7UUFDdEUsVUFBVSxFQUNaO1FBQ0UsYUFBYSxFQUFFLEtBQUs7UUFDcEIsa0JBQWtCO1FBQ2xCLGtCQUFrQjtRQUNsQixrQkFBa0IsRUFBRSxRQUFRLEVBQUUsWUFBWTtLQUMzQyxDQUNGLENBQUM7SUFDRixPQUFPLElBQUksQ0FBQztBQUNkLENBQUM7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXNCRztBQUNILEtBQUssVUFBVSwrQkFBK0IsQ0FBQyxFQUM3QyxLQUFLLEVBQ0wsUUFBUSxFQUNSLEtBQUssRUFDTCxTQUFTLEdBTVY7SUFDQyxNQUFNLGtCQUFrQixHQUFHLFFBQVEsRUFBRSxZQUFZLENBQUM7SUFDbEQsSUFBSSxDQUFDLGtCQUFrQjtRQUFFLE9BQU87SUFFaEMsSUFBSSxtQkFBdUMsQ0FBQztJQUM1QyxJQUFJLENBQUM7UUFDSCxtQkFBbUIsR0FBRyxNQUFNLEtBQUssQ0FBQyxlQUFlLEVBQUUsQ0FBQztJQUN0RCxDQUFDO0lBQUMsTUFBTSxDQUFDO1FBQ1AsMEVBQTBFO1FBQzFFLCtEQUErRDtRQUMvRCxPQUFPO0lBQ1QsQ0FBQztJQUNELElBQUksQ0FBQyxtQkFBbUIsSUFBSSxtQkFBbUIsS0FBSyxrQkFBa0IsRUFBRSxDQUFDO1FBQ3ZFLE9BQU87SUFDVCxDQUFDO0lBRUQsU0FBUyxDQUFDLEtBQUssQ0FDYixvRUFBb0U7UUFDbEUsZ0VBQWdFO1FBQ2hFLHVFQUF1RTtRQUN2RSxvRUFBb0U7UUFDcEUsd0VBQXdFO1FBQ3hFLGVBQWUsRUFDakI7UUFDRSxhQUFhLEVBQUUsS0FBSztRQUNwQixrQkFBa0I7UUFDbEIsbUJBQW1CO0tBQ3BCLENBQ0YsQ0FBQztBQUNKLENBQUM7QUFFRCxTQUFTLHlCQUF5QixDQUFDLEdBQVk7SUFDN0MsSUFBSSxvQkFBb0IsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUNqQyxPQUFPLGVBQWUsQ0FBQyxhQUFhLENBQUM7SUFDdkMsQ0FBQztJQUVELElBQUksb0JBQW9CLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUM5QixPQUFPLGVBQWUsQ0FBQyxvQkFBb0IsQ0FBQztJQUM5QyxDQUFDO0lBRUQsT0FBTyxJQUFJLENBQUM7QUFDZCxDQUFDO0FBRUQsS0FBSyxVQUFVLG1CQUFtQixDQUFDLEVBQ2pDLEtBQUssRUFDTCxXQUFXLEVBQ1gsS0FBSyxFQUNMLFNBQVMsRUFDVCxHQUFHLEVBQ0gsU0FBUyxFQUNULFVBQVUsR0FTWDtJQUNDLGFBQWEsQ0FBQyxLQUFLLENBQUMsVUFBVSxFQUFFO1FBQzlCLGFBQWEsRUFBRSxLQUFLO1FBQ3BCLFNBQVM7UUFDVCxLQUFLLEVBQUUsR0FBRyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQztLQUN4RCxDQUFDLENBQUM7SUFFSCxJQUFJLENBQUM7UUFDSCxNQUFNLGdCQUFnQixHQUFHLG9CQUFvQixDQUFDLEtBQUssRUFBRSxXQUFXLElBQUksS0FBSyxDQUFDLENBQUM7UUFDM0UsTUFBTSxLQUFLLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FDdkIsS0FBSyxFQUNMO1lBQ0UsU0FBUyxFQUFFLFlBQVk7WUFDdkIsV0FBVyxFQUFFLG9CQUFvQjtZQUNqQyxTQUFTLEVBQUU7Z0JBQ1QsS0FBSyxFQUFFLE1BQU0saUJBQWlCLENBQzVCLEdBQUcsRUFDSCxLQUFLLEVBQ0wsTUFBTSxnQkFBZ0IsRUFBRSxFQUN4QixVQUFVLEVBQ1YsQ0FBQyxXQUFXLEVBQUUsV0FBVyxJQUFJLENBQUMsQ0FBQyxJQUFJLGlDQUFpQyxDQUNyRTtnQkFDRCxTQUFTO2FBQ1Y7U0FDRixFQUNELEVBQUUsU0FBUyxFQUFFLENBQ2QsQ0FBQztJQUNKLENBQUM7SUFBQyxPQUFPLE9BQU8sRUFBRSxDQUFDO1FBQ2pCLElBQUksbUJBQW1CLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLGVBQWUsQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUNuRSxPQUFPO1FBQ1QsQ0FBQztRQUNELElBQUksb0JBQW9CLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUNsQyxhQUFhLENBQUMsS0FBSyxDQUNqQiw2REFBNkQsRUFDN0Q7Z0JBQ0UsYUFBYSxFQUFFLEtBQUs7Z0JBQ3BCLFNBQVMsRUFBRSxlQUFlLENBQUMsb0JBQW9CO2dCQUMvQyxLQUFLLEVBQUUsT0FBTyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQzthQUNwRSxDQUNGLENBQUM7WUFDRixPQUFPO1FBQ1QsQ0FBQztRQUNELE1BQU0sT0FBTyxDQUFDO0lBQ2hCLENBQUM7QUFDSCxDQUFDO0FBRUQsU0FBUywyQkFBMkIsQ0FBQyxNQUFlLEVBQUUsS0FBYTtJQUNqRSx5RUFBeUU7SUFDekUsZ0VBQWdFO0lBQ2hFLDJFQUEyRTtJQUMzRSw2QkFBNkI7SUFDN0IsTUFBTSxnQkFBZ0IsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUNsQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQ0osQ0FBQyxDQUFDLEtBQUssS0FBSyxLQUFLO1FBQ2pCLENBQUMsQ0FBQyxDQUFDLFNBQVMsS0FBSyxlQUFlO1lBQzlCLENBQUMsQ0FBQyxTQUFTLEtBQUssWUFBWTtZQUM1QixDQUFDLENBQUMsU0FBUyxLQUFLLGVBQWUsQ0FBQyxDQUNyQyxDQUFDO0lBRUYsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7UUFDdEIsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRUQsYUFBYSxDQUFDLEtBQUssQ0FBQyxxQ0FBcUMsRUFBRTtRQUN6RCxhQUFhLEVBQUUsS0FBSztRQUNwQixTQUFTLEVBQUUsZ0JBQWdCLENBQUMsU0FBUztRQUNyQyxPQUFPLEVBQUUsZ0JBQWdCLENBQUMsT0FBTztLQUNsQyxDQUFDLENBQUM7SUFDSCxPQUFPLElBQUksQ0FBQztBQUNkLENBQUM7QUFFRCxtREFBbUQ7QUFDbkQsU0FBUyxlQUFlLENBQUMsR0FBcUIsRUFBRSxPQUFvQjtJQUNsRSxJQUFJLE9BQU8sR0FBRyxDQUFDLENBQUM7SUFDaEIsS0FBSyxNQUFNLEVBQUUsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUNyQixJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFBRSxPQUFPLEVBQUUsQ0FBQztJQUNsQyxDQUFDO0lBQ0QsT0FBTyxPQUFPLENBQUM7QUFDakIsQ0FBQztBQUVEOzs7R0FHRztBQUNILFNBQVMsYUFBYSxDQUNwQixVQUE4QyxFQUM5QyxLQUFhO0lBRWIsT0FBTyxVQUFVLEVBQUUsQ0FBQyxxQkFBcUIsQ0FBQyxJQUFJLEtBQUssQ0FBQztBQUN0RCxDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQWtCRztBQUNILFNBQVMsb0JBQW9CLENBQUMsTUFBZTtJQUkzQyxNQUFNLEtBQUssR0FBRyxJQUFJLEdBQUcsRUFBVSxDQUFDO0lBQ2hDLE1BQU0sS0FBSyxHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7SUFDaEMsS0FBSyxNQUFNLEtBQUssSUFBSSxNQUFNLEVBQUUsQ0FBQztRQUMzQixRQUFRLEtBQUssQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUN4QixLQUFLLGNBQWM7Z0JBQ2pCLEtBQUssQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxDQUFDO2dCQUMvQixNQUFNO1lBQ1IsS0FBSyxlQUFlO2dCQUNsQixLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsQ0FBQztnQkFDbEMsTUFBTTtZQUNSLEtBQUssY0FBYztnQkFDakIsS0FBSyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLENBQUM7Z0JBQy9CLE1BQU07WUFDUixLQUFLLGdCQUFnQjtnQkFDbkIsS0FBSyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLENBQUM7Z0JBQ2xDLE1BQU07UUFDVixDQUFDO0lBQ0gsQ0FBQztJQUNELE9BQU8sRUFBRSxRQUFRLEVBQUUsS0FBSyxDQUFDLElBQUksR0FBRyxDQUFDLEVBQUUsUUFBUSxFQUFFLEtBQUssQ0FBQyxJQUFJLEdBQUcsQ0FBQyxFQUFFLENBQUM7QUFDaEUsQ0FBQztBQU9ELFNBQVMsZ0JBQWdCLENBQUMsR0FBbUI7SUFDM0MsSUFBSSxHQUFHLENBQUMsTUFBTSxLQUFLLElBQUksRUFBRSxDQUFDO1FBQ3hCLE9BQU8sRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLENBQUM7SUFDN0IsQ0FBQztJQUNELE9BQU87UUFDTCxJQUFJLEVBQUUsV0FBVztRQUNqQixNQUFNLEVBQUUsR0FBRyxDQUFDLE1BQU07UUFDbEIsTUFBTSxFQUFFLEdBQUcsQ0FBQyxNQUFNO0tBQ25CLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxjQUFjLENBQUMsR0FBbUIsRUFBRSxRQUF3QjtJQUNuRSxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNoRCxHQUFHLENBQUMsTUFBTSxHQUFHLFFBQVEsQ0FBQyxNQUFNLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQztBQUM3QyxDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBdUJHO0FBQ0gsU0FBUyx3QkFBd0IsQ0FDL0IsVUFBOEIsRUFDOUIsY0FBdUIsRUFDdkIsWUFBZ0U7SUFFaEUsSUFDRSxDQUFDLG9CQUFvQixFQUFFO1FBQ3ZCLENBQUMsY0FBYztRQUNmLFVBQVUsQ0FBQyxLQUFLLENBQUMsTUFBTSxLQUFLLENBQUM7UUFDN0IsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksS0FBSyxNQUFNLENBQUMsRUFDdkQsQ0FBQztRQUNELE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUNELE1BQU0sRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLEdBQUcsWUFBWSxDQUFDLEtBQUssQ0FBQztJQUNsRCxPQUFPLENBQUMsUUFBUSxJQUFJLENBQUMsUUFBUSxDQUFDO0FBQ2hDLENBQUM7QUFFRDs7Ozs7OztHQU9HO0FBQ0gsS0FBSyxVQUFVLHNCQUFzQixDQUNuQyxLQUFZLEVBQ1osbUJBQTJCO0lBRTNCLE1BQU0sY0FBYyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsc0JBQXNCLENBQUM7SUFDMUQsSUFBSSxjQUFjLEtBQUssU0FBUyxJQUFJLGNBQWMsS0FBSyxFQUFFLEVBQUUsQ0FBQztRQUMxRCxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDdEMsSUFBSSxNQUFNLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxJQUFJLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUMxQyxPQUFPLE1BQU0sQ0FBQztRQUNoQixDQUFDO0lBQ0gsQ0FBQztJQUVELE1BQU0sZUFBZSxHQUFHLE1BQU0sS0FBSyxDQUFDLGtCQUFrQixFQUFFLEVBQUUsQ0FBQztJQUMzRCxJQUFJLGVBQWUsS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUNsQyxNQUFNLFVBQVUsR0FBRyxlQUFlLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDN0MsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQztZQUM5QixNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsR0FBRyxtQkFBbUIsQ0FBQyxDQUFDO1lBQ25FLElBQUksYUFBYSxJQUFJLEVBQUUsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO2dCQUMvQixPQUFPLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNuQixDQUFDO1lBRUQsSUFBSSxhQUFhLElBQUksRUFBRSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7Z0JBQy9CLE9BQU8sRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ2xCLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVELE9BQU8sRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQ2xCLENBQUM7QUFFRDs7Ozs7Ozs7OztHQVVHO0FBQ0gsTUFBTSxVQUFVLGtCQUFrQixDQUNoQyxZQUFvQixFQUNwQixPQUlDO0lBRUQsbUJBQW1CLENBQUMsT0FBTyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBRXZDLE1BQU0sU0FBUyxHQUFHLHFCQUFxQixDQUFDLE9BQU8sRUFBRSxTQUFTLENBQUMsQ0FBQztJQUM1RCxNQUFNLGNBQWMsR0FBRyxtQkFBbUIsQ0FBQyxVQUFVLEVBQUUsU0FBUyxDQUFDLENBQUM7SUFFbEUsTUFBTSxPQUFPLEdBQUcsQ0FBQyxhQUE0QixFQUFFLEVBQUUsQ0FDL0MsYUFBYSxDQUFDLGtCQUFrQixDQUM5QixjQUFjLEVBQ2QsS0FBSyxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsRUFBRTtRQUMzQiwwQ0FBMEM7UUFDMUMseUZBQXlGO1FBQ3pGLHlGQUF5RjtRQUN6RixvRkFBb0Y7UUFDcEYsTUFBTSxXQUFXLEdBQUcsdUJBQXVCLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDdEQsSUFBSSxXQUFXLEVBQUUsQ0FBQztZQUNoQixNQUFNLHdCQUF3QixDQUM1QixXQUFXLEVBQ1gsYUFBYSxDQUFDLFdBQVcsQ0FDMUIsQ0FBQztZQUNGLE9BQU87UUFDVCxDQUFDO1FBRUQsTUFBTSxFQUNKLEtBQUssRUFDTCxZQUFZLEVBQUUsb0JBQW9CLEVBQ2xDLFdBQVcsRUFDWCxNQUFNLEVBQUUsY0FBYyxFQUN0QixRQUFRLEVBQUUsZ0JBQWdCLEVBQzFCLGdCQUFnQixFQUNoQix5QkFBeUIsRUFDekIsNEJBQTRCLEVBQzVCLFFBQVEsRUFDUixTQUFTLEdBQ1YsR0FBRywyQkFBMkIsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDaEQsaURBQWlEO1FBQ2pELHNFQUFzRTtRQUN0RSwrREFBK0Q7UUFDL0Qsb0VBQW9FO1FBQ3BFLHFDQUFxQztRQUNyQyxNQUFNLFlBQVksR0FBRyxvQkFBb0IsQ0FBQyxvQkFBb0IsQ0FBQztZQUM3RCxDQUFDLENBQUMsb0JBQW9CO1lBQ3RCLENBQUMsQ0FBQyxTQUFTLENBQUM7UUFDZCxNQUFNLEVBQUUsU0FBUyxFQUFFLEdBQUcsUUFBUSxDQUFDO1FBQy9CLE1BQU0sWUFBWSxHQUFHLFFBQVEsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUVyRSw2QkFBNkI7UUFDN0IsOERBQThEO1FBQzlELDRFQUE0RTtRQUM1RSxvRUFBb0U7UUFDcEUsZ0VBQWdFO1FBQ2hFLE1BQU0sU0FBUyxHQUFHLGFBQWEsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBRTVELE1BQU0sa0JBQWtCLEdBQUcscUJBQXFCLEVBQUUsQ0FBQztRQUNuRCxJQUFJLFFBQVEsQ0FBQyxPQUFPLEdBQUcsa0JBQWtCLEVBQUUsQ0FBQztZQUMxQyxNQUFNLHdCQUF3QixHQUFHLGFBQWEsQ0FDNUMsU0FBUyxFQUNULGVBQWUsQ0FBQyx1QkFBdUIsQ0FDeEMsQ0FBQztZQUNGLFNBQVMsQ0FBQyxLQUFLLENBQ2IsNkNBQTZDLFFBQVEsQ0FBQyxPQUFPLElBQUksa0JBQWtCLEdBQUcsRUFDdEY7Z0JBQ0UsT0FBTyxFQUFFLFFBQVEsQ0FBQyxPQUFPO2dCQUN6QixTQUFTLEVBQUUsd0JBQXdCLENBQUMsU0FBUztnQkFDN0MsZ0JBQWdCLEVBQUUsd0JBQXdCLENBQUMsV0FBVzthQUN2RCxDQUNGLENBQUM7WUFDRixJQUFJLENBQUM7Z0JBQ0gsTUFBTSxLQUFLLEdBQUcsTUFBTSxRQUFRLEVBQUUsQ0FBQztnQkFDL0IsTUFBTSxnQkFBZ0IsR0FBRyxvQkFBb0IsQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUM7Z0JBQzVELE1BQU0sR0FBRyxHQUFHLElBQUksVUFBVSxDQUN4QiwrQ0FBK0MsUUFBUSxDQUFDLE9BQU8sSUFBSSxrQkFBa0IsR0FBRyxDQUN6RixDQUFDO2dCQUNGLE1BQU0sS0FBSyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQ3ZCLEtBQUssRUFDTDtvQkFDRSxTQUFTLEVBQUUsWUFBWTtvQkFDdkIsV0FBVyxFQUFFLG9CQUFvQjtvQkFDakMsU0FBUyxFQUFFO3dCQUNULEtBQUssRUFBRSxNQUFNLGlCQUFpQixDQUM1QixHQUFHLEVBQ0gsS0FBSyxFQUNMLE1BQU0sZ0JBQWdCLEVBQUUsQ0FDekI7d0JBQ0QsU0FBUyxFQUFFLGVBQWUsQ0FBQyx1QkFBdUI7cUJBQ25EO2lCQUNGLEVBQ0QsRUFBRSxTQUFTLEVBQUUsQ0FDZCxDQUFDO1lBQ0osQ0FBQztZQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7Z0JBQ2IsSUFBSSxtQkFBbUIsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksZUFBZSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO29CQUMzRCxxREFBcUQ7b0JBQ3JELE9BQU87Z0JBQ1QsQ0FBQztnQkFDRCxTQUFTLENBQUMsS0FBSyxDQUNiLHNDQUFzQyxRQUFRLENBQUMsT0FBTyxzQkFBc0I7b0JBQzFFLGtFQUFrRTtvQkFDbEUsb0VBQW9FO29CQUNwRSx5RUFBeUU7b0JBQ3pFLCtFQUErRSxFQUNqRjtvQkFDRSxPQUFPLEVBQUUsUUFBUSxDQUFDLE9BQU87b0JBQ3pCLFNBQVMsRUFBRSxHQUFHLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxjQUFjO29CQUMzRCxZQUFZLEVBQUUsR0FBRyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQztvQkFDOUQsVUFBVSxFQUFFLEdBQUcsWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLFNBQVM7aUJBQ3pELENBQ0YsQ0FBQztZQUNKLENBQUM7WUFDRCxPQUFPO1FBQ1QsQ0FBQztRQUVELGlDQUFpQztRQUNqQyxvRUFBb0U7UUFDcEUsa0VBQWtFO1FBQ2xFLG9FQUFvRTtRQUNwRSxpRUFBaUU7UUFDakUsb0VBQW9FO1FBQ3BFLGlFQUFpRTtRQUNqRSwyQ0FBMkM7UUFDM0Msa0VBQWtFO1FBQ2xFLGlEQUFpRDtRQUNqRCxNQUFNLFNBQVMsR0FBRyxvQkFBb0IsRUFBRSxDQUFDO1FBRXpDLGlFQUFpRTtRQUNqRSwrREFBK0Q7UUFDL0QsTUFBTSxnQkFBZ0IsR0FBRyxHQUFvQyxFQUFFLENBQzdELG1CQUFtQixDQUFDLFNBQVMsRUFBRSxZQUFZLENBQUMsQ0FBQztRQUUvQyxtRUFBbUU7UUFDbkUsaURBQWlEO1FBQ2pELE1BQU0sU0FBUyxHQUFHLE1BQU0sd0JBQXdCLENBQzlDLFNBQVMsRUFDVCxZQUFZLENBQ2IsQ0FBQztRQUVGLHdFQUF3RTtRQUN4RSxzRUFBc0U7UUFDdEUsb0VBQW9FO1FBQ3BFLE1BQU0sWUFBWSxHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7UUFFeEMsK0RBQStEO1FBQy9ELHNEQUFzRDtRQUN0RCxxRUFBcUU7UUFDckUsbUVBQW1FO1FBQ25FLDZDQUE2QztRQUM3QyxNQUFNLGtCQUFrQixHQUN0QixTQUFTLEtBQUssWUFBWSxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztRQUN4RCwwREFBMEQ7UUFDMUQscUNBQXFDO1FBQ3JDLE1BQU0sUUFBUSxHQUFHLE1BQU0sV0FBVyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQy9DLE9BQU8sTUFBTSxnQkFBZ0IsQ0FBQyxrQkFBa0IsRUFBRSxLQUFLLElBQUksRUFBRTtZQUMzRCxPQUFPLE1BQU0sbUJBQW1CLENBQzlCLEVBQUUsYUFBYSxFQUFFLEtBQUssRUFBRSxZQUFZLEVBQUUsRUFDdEMsS0FBSyxJQUFJLEVBQUU7Z0JBQ1QsTUFBTSxLQUFLLEdBQUcsTUFBTSxLQUFLLENBQUMsMEJBQTBCLEVBQUUsS0FBSyxJQUFJLEVBQUUsQ0FDL0QsUUFBUSxFQUFFLENBQ1gsQ0FBQztnQkFDRixnRUFBZ0U7Z0JBQ2hFLG1FQUFtRTtnQkFDbkUsdURBQXVEO2dCQUN2RCxFQUFFO2dCQUNGLGtFQUFrRTtnQkFDbEUsK0RBQStEO2dCQUMvRCxtRUFBbUU7Z0JBQ25FLGlFQUFpRTtnQkFDakUsNkRBQTZEO2dCQUM3RCxnRUFBZ0U7Z0JBQ2hFLElBQ0UsOEJBQThCLENBQUM7b0JBQzdCLEtBQUs7b0JBQ0wsUUFBUTtvQkFDUixLQUFLO29CQUNMLFNBQVM7aUJBQ1YsQ0FBQyxFQUNGLENBQUM7b0JBQ0QsT0FBTztnQkFDVCxDQUFDO2dCQUNELGlFQUFpRTtnQkFDakUsMkJBQTJCO2dCQUMzQixNQUFNLCtCQUErQixDQUFDO29CQUNwQyxLQUFLO29CQUNMLFFBQVE7b0JBQ1IsS0FBSztvQkFDTCxTQUFTO2lCQUNWLENBQUMsQ0FBQztnQkFDSCxPQUFPLEtBQUssQ0FDVixvQkFBb0IsbUJBQW1CLENBQUMsWUFBWSxDQUFDLEVBQUUsRUFDdkQsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsRUFDcEMsS0FBSyxFQUFFLElBQUksRUFBRSxFQUFFO29CQUNiLElBQUksRUFBRSxhQUFhLENBQUM7d0JBQ2xCLEdBQUcsU0FBUyxDQUFDLFlBQVksQ0FBQyxZQUFZLENBQUM7d0JBQ3ZDLEdBQUcsU0FBUyxDQUFDLGlCQUFpQixDQUFDLFlBQVksQ0FBQzt3QkFDNUMsR0FBRyxTQUFTLENBQUMsZUFBZSxDQUFDLGNBQWMsQ0FBQzt3QkFDNUMsR0FBRyxTQUFTLENBQUMsd0JBQXdCLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQzt3QkFDekQsR0FBRyxTQUFTLENBQUMsa0JBQWtCLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQzt3QkFDbkQsR0FBRyxTQUFTLENBQUMsc0JBQXNCLENBQUMsU0FBUyxDQUFDO3dCQUM5QyxHQUFHLGdCQUFnQixDQUFDLEVBQUUsV0FBVyxFQUFFLENBQUM7d0JBQ3BDLEdBQUcsU0FBUyxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUM7d0JBQ2pDLEdBQUcsU0FBUyxDQUFDLHVCQUF1QixDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUM7d0JBQ3BELEdBQUcsU0FBUyxDQUFDLGlCQUFpQixDQUFDLFNBQVMsQ0FBQztxQkFDMUMsQ0FBQyxDQUFDO29CQUVILE1BQU0sbUJBQW1CLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO29CQUN2QyxNQUFNLHFCQUFxQixHQUFHLE1BQU0sc0JBQXNCLENBQ3hELEtBQUssRUFDTCxtQkFBbUIsQ0FDcEIsQ0FBQztvQkFDRixJQUFJLGFBQWEsR0FBRyxDQUFDLENBQUM7b0JBQ3RCLE1BQU0sc0JBQXNCLEdBQUcsZ0JBQWdCO3dCQUM3QyxDQUFDLENBQUMsSUFBSSxzQkFBc0IsQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUM7d0JBQ3BELENBQUMsQ0FBQyxzQkFBc0IsQ0FBQyxLQUFLLEVBQUUsQ0FBQztvQkFDbkMsNERBQTREO29CQUM1RCx5REFBeUQ7b0JBQ3pELHVCQUF1QjtvQkFDdkIsTUFBTSxXQUFXLEdBQUcsS0FBSyxFQUN2QixJQUFPLEVBQ1AsTUFBMEIsRUFDMUIsRUFBRTt3QkFDRixNQUFNLFdBQVcsR0FBRyxrQkFBa0IsQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUM7d0JBQ3JELE1BQU0sTUFBTSxHQUFHLE1BQU0sc0JBQXNCLENBQUMsZUFBZSxDQUN6RCxXQUFXLEtBQUssU0FBUzs0QkFDdkIsQ0FBQyxDQUFDLE1BQU07NEJBQ1IsQ0FBQyxDQUFDLEVBQUUsR0FBRyxNQUFNLEVBQUUsV0FBVyxFQUFFLEVBQzlCLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUMzQyxDQUFDO3dCQUNGLElBQUksV0FBVyxLQUFLLFNBQVMsRUFBRSxDQUFDOzRCQUM5QixpQkFBaUIsQ0FBQyxXQUFXLEVBQUUsTUFBTSxDQUFDLENBQUM7d0JBQ3pDLENBQUM7d0JBQ0QsT0FBTyxNQUFNLENBQUM7b0JBQ2hCLENBQUMsQ0FBQztvQkFFRjs7Ozs7Ozs7Ozs7O3VCQVlHO29CQUNILE1BQU0sa0JBQWtCLEdBQUcsQ0FDekIsSUFBd0IsRUFDeEIsTUFBcUMsRUFDakIsRUFBRTt3QkFDdEIsSUFDRSxLQUFLOzRCQUNMLFFBQVEsQ0FBQyxJQUFJLEtBQUssT0FBTzs0QkFDekIsTUFBTSxFQUFFLFdBQVcsS0FBSyxTQUFTOzRCQUNqQyxNQUFNLEVBQUUsYUFBYSxLQUFLLElBQUk7NEJBQzlCLHNCQUFzQixDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFDdEMsQ0FBQzs0QkFDRCxPQUFPLFNBQVMsQ0FBQzt3QkFDbkIsQ0FBQzt3QkFDRCxPQUFPLFFBQVEsQ0FBQyxNQUFNLElBQUksU0FBUyxDQUFDO29CQUN0QyxDQUFDLENBQUM7b0JBRUY7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7dUJBeUJHO29CQUNILE1BQU0saUJBQWlCLEdBQUcsQ0FDeEIsVUFBa0IsRUFDbEIsTUFBbUIsRUFDYixFQUFFO3dCQUNSLElBQ0UsUUFBUSxDQUFDLElBQUksS0FBSyxPQUFPOzRCQUN6QixRQUFRLENBQUMsTUFBTSxLQUFLLFVBQVU7NEJBQzlCLE1BQU0sQ0FBQyxNQUFNLEtBQUssU0FBUzs0QkFDM0IsTUFBTSxDQUFDLE9BQU8sS0FBSyxJQUFJLEVBQ3ZCLENBQUM7NEJBQ0QsT0FBTzt3QkFDVCxDQUFDO3dCQUNELGNBQWMsQ0FBQyxRQUFRLEVBQUU7NEJBQ3ZCLE1BQU0sRUFBRSxNQUFNLENBQUMsTUFBTTs0QkFDckIsTUFBTSxFQUFFLE1BQU0sQ0FBQyxNQUFNO3lCQUN0QixDQUFDLENBQUM7b0JBQ0wsQ0FBQyxDQUFDO29CQUVGLDJEQUEyRDtvQkFDM0Qsa0NBQWtDO29CQUNsQyxJQUFJLFFBQVEsR0FBbUIsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLENBQUM7b0JBRW5ELHVEQUF1RDtvQkFDdkQsa0NBQWtDO29CQUNsQyxJQUFJLFdBQW9DLENBQUM7b0JBQ3pDLDZEQUE2RDtvQkFDN0QsK0RBQStEO29CQUMvRCxJQUFJLGNBQWtDLENBQUM7b0JBQ3ZDLElBQUksaUJBQWlCLEdBQUcsQ0FBQyxDQUFDLENBQUM7b0JBRTNCLGdFQUFnRTtvQkFDaEUsMkRBQTJEO29CQUMzRCw0REFBNEQ7b0JBQzVELDBEQUEwRDtvQkFDMUQseURBQXlEO29CQUN6RCwwREFBMEQ7b0JBQzFELHNEQUFzRDtvQkFDdEQsSUFBSSxzQkFBMkMsQ0FBQztvQkFDaEQsMERBQTBEO29CQUMxRCx3REFBd0Q7b0JBQ3hELHlEQUF5RDtvQkFDekQsdURBQXVEO29CQUN2RCxzREFBc0Q7b0JBQ3RELHlEQUF5RDtvQkFDekQsb0NBQW9DO29CQUNwQyxJQUFJLHNCQUEwQyxDQUFDO29CQUMvQyw0REFBNEQ7b0JBQzVELDJEQUEyRDtvQkFDM0QseURBQXlEO29CQUN6RCw0REFBNEQ7b0JBQzVELHFEQUFxRDtvQkFDckQsNkRBQTZEO29CQUM3RCw0REFBNEQ7b0JBQzVELElBQUksaUJBQWlCLEdBQUcsQ0FBQyxDQUFDO29CQUMxQix3REFBd0Q7b0JBQ3hELHVEQUF1RDtvQkFDdkQseURBQXlEO29CQUN6RCx5REFBeUQ7b0JBQ3pELHdEQUF3RDtvQkFDeEQsZ0RBQWdEO29CQUNoRCxJQUFJLDJCQUErQyxDQUFDO29CQUVwRCw0REFBNEQ7b0JBQzVELDZEQUE2RDtvQkFDN0QsOERBQThEO29CQUM5RCwyREFBMkQ7b0JBQzNELDREQUE0RDtvQkFDNUQsOERBQThEO29CQUM5RCx3REFBd0Q7b0JBQ3hELDBEQUEwRDtvQkFDMUQsNkRBQTZEO29CQUM3RCw2REFBNkQ7b0JBQzdELDREQUE0RDtvQkFDNUQsOERBQThEO29CQUM5RCx5REFBeUQ7b0JBQ3pELDREQUE0RDtvQkFDNUQsZ0RBQWdEO29CQUNoRCwwREFBMEQ7b0JBQzFELHNEQUFzRDtvQkFDdEQsMkRBQTJEO29CQUMzRCx3REFBd0Q7b0JBQ3hELHlEQUF5RDtvQkFDekQsNERBQTREO29CQUM1RCxnREFBZ0Q7b0JBQ2hELHdEQUF3RDtvQkFDeEQsMkRBQTJEO29CQUMzRCwyREFBMkQ7b0JBQzNELGdEQUFnRDtvQkFDaEQsTUFBTSxLQUFLLEdBQ1QsY0FBYyxFQUFFO3dCQUNoQixRQUFRLEtBQUssU0FBUzt3QkFDdEIsUUFBUSxDQUFDLE9BQU8sS0FBSyxDQUFDO3dCQUN0QixjQUFjLEtBQUssU0FBUzt3QkFDNUIsQ0FBQyxnQkFBZ0IsQ0FBQztvQkFDcEIsSUFBSSxFQUFFLGFBQWEsQ0FBQyxTQUFTLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7b0JBRXBELGtEQUFrRDtvQkFDbEQsK0RBQStEO29CQUMvRCw2REFBNkQ7b0JBQzdELDZEQUE2RDtvQkFDN0Qsa0RBQWtEO29CQUNsRCxJQUFJLGVBQTZDLENBQUM7b0JBRWxELGdFQUFnRTtvQkFDaEUseURBQXlEO29CQUN6RCw0REFBNEQ7b0JBQzVELDREQUE0RDtvQkFDNUQsZ0VBQWdFO29CQUNoRSxpRUFBaUU7b0JBQ2pFLG1DQUFtQztvQkFDbkMsTUFBTSxhQUFhLEdBQUcsS0FBSyxJQUFtQixFQUFFO3dCQUM5QyxJQUFJLGVBQWUsRUFBRSxDQUFDOzRCQUNwQixJQUFJLENBQUM7Z0NBQ0gsTUFBTSxlQUFlLENBQUM7NEJBQ3hCLENBQUM7NEJBQUMsTUFBTSxDQUFDO2dDQUNQLGtEQUFrRDs0QkFDcEQsQ0FBQzt3QkFDSCxDQUFDO29CQUNILENBQUMsQ0FBQztvQkFFRix5REFBeUQ7b0JBQ3pELDZEQUE2RDtvQkFDN0QsMkRBQTJEO29CQUMzRCwwREFBMEQ7b0JBQzFELDZEQUE2RDtvQkFDN0QsNERBQTREO29CQUM1RCwwREFBMEQ7b0JBQzFELHlEQUF5RDtvQkFDekQsOERBQThEO29CQUM5RCwyREFBMkQ7b0JBQzNELDZEQUE2RDtvQkFDN0QsNERBQTREO29CQUM1RCwrREFBK0Q7b0JBQy9ELG9DQUFvQztvQkFDcEMsdURBQXVEO29CQUN2RCwyREFBMkQ7b0JBQzNELDREQUE0RDtvQkFDNUQsMERBQTBEO29CQUMxRCw0REFBNEQ7b0JBQzVELDJEQUEyRDtvQkFDM0QsMkRBQTJEO29CQUMzRCw0REFBNEQ7b0JBQzVELDBEQUEwRDtvQkFDMUQsMERBQTBEO29CQUMxRCxzREFBc0Q7b0JBQ3RELE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztvQkFDN0MsTUFBTSwwQkFBMEIsR0FBRyxDQUNqQyxPQUFlLEVBQ1QsRUFBRTt3QkFDUixJQUFJLGtCQUFrQixDQUFDLElBQUksR0FBRyxDQUFDLEVBQUUsQ0FBQzs0QkFDaEMsYUFBYSxDQUFDLEtBQUssQ0FDakIsMElBQTBJLEVBQzFJO2dDQUNFLGFBQWEsRUFBRSxLQUFLO2dDQUNwQixPQUFPO2dDQUNQLE9BQU8sRUFBRSxDQUFDLEdBQUcsa0JBQWtCLENBQUM7NkJBQ2pDLENBQ0YsQ0FBQzt3QkFDSixDQUFDO29CQUNILENBQUMsQ0FBQztvQkFFRiw0REFBNEQ7b0JBQzVELDZEQUE2RDtvQkFDN0QsaURBQWlEO29CQUNqRCwyREFBMkQ7b0JBQzNELE1BQU0sYUFBYSxHQUNqQixLQUFLLElBQW9DLEVBQUUsQ0FBQyxDQUFDO3dCQUMzQyxLQUFLO3dCQUNMLFlBQVksRUFBRSxNQUFNLGdCQUFnQixFQUFFO3dCQUN0QyxXQUFXLEVBQUUsSUFBSSxJQUFJLEVBQUU7cUJBQ3hCLENBQUMsQ0FBQztvQkFFTCxNQUFNLFFBQVEsR0FBRyxLQUFLLEVBQ3BCLFlBQW9CO29CQUNwQjs7Ozs7Ozt1QkFPRztvQkFDSCxZQUE2QyxFQUNJLEVBQUU7d0JBQ25ELDBCQUEwQixDQUFDLFVBQVUsQ0FBQyxDQUFDO3dCQUN2QyxJQUFJLENBQUMsS0FBSzs0QkFBRSxPQUFPLEVBQUUsY0FBYyxFQUFFLFlBQVksRUFBRSxDQUFDO3dCQUNwRCxNQUFNLFlBQVksQ0FDaEIsS0FBSyxFQUNMLG9CQUFvQixDQUFDLFlBQVksRUFBRSxTQUFTLENBQUMsRUFDN0MsRUFBRSxHQUFHLENBQUMsTUFBTSxhQUFhLEVBQUUsQ0FBQyxFQUFFLEdBQUcsWUFBWSxFQUFFLEVBQy9DLFlBQVksR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsWUFBWSxFQUFFLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FDaEQsQ0FBQzt3QkFDRixPQUFPLFNBQVMsQ0FBQztvQkFDbkIsQ0FBQyxDQUFDO29CQUVGLDhEQUE4RDtvQkFDOUQsMERBQTBEO29CQUMxRCxJQUFJLG9CQUFvQixHQUFHLENBQUMsQ0FBQztvQkFDN0I7Ozs7Ozs7Ozs7dUJBVUc7b0JBQ0gsSUFBSSwyQkFBMkIsR0FLcEIsSUFBSSxDQUFDO29CQUNoQjs7Ozs7Ozs7Ozt1QkFVRztvQkFDSCxNQUFNLCtCQUErQixHQUFHLENBQ3RDLE1BQWUsRUFDVCxFQUFFO3dCQUNSLE1BQU0sUUFBUSxHQUFHLDJCQUEyQixDQUFDO3dCQUM3QyxJQUFJLENBQUMsUUFBUTs0QkFBRSxPQUFPO3dCQUN0QiwyQkFBMkIsR0FBRyxJQUFJLENBQUM7d0JBRW5DLE1BQU0sV0FBVyxHQUFHLElBQUksR0FBRyxDQUN6QixNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQ3JDLENBQUM7d0JBQ0YsTUFBTSxLQUFLLEdBQUcsZUFBZSxDQUFDLFdBQVcsRUFBRSxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUM7d0JBQ3pELE1BQU0sT0FBTyxHQUFHLGVBQWUsQ0FBQyxRQUFRLENBQUMsR0FBRyxFQUFFLFdBQVcsQ0FBQyxDQUFDO3dCQUMzRCxNQUFNLE9BQU8sR0FDWCxPQUFPLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEtBQUssR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDO3dCQUU1RCxhQUFhLENBQUMsSUFBSSxDQUNoQiwwRUFBMEUsRUFDMUU7NEJBQ0UsYUFBYSxFQUFFLEtBQUs7NEJBQ3BCLE9BQU87NEJBQ1AsS0FBSzs0QkFDTCxPQUFPOzRCQUNQLFlBQVksRUFBRSxRQUFRLENBQUMsR0FBRyxDQUFDLElBQUk7NEJBQy9CLFdBQVcsRUFBRSxXQUFXLENBQUMsSUFBSTs0QkFDN0Isb0JBQW9CLEVBQUUsUUFBUSxDQUFDLE9BQU87NEJBQ3RDLE1BQU0sRUFBRSxRQUFRLENBQUMsTUFBTTs0QkFDdkIsTUFBTSxFQUFFLFFBQVEsQ0FBQyxNQUFNOzRCQUN2QixhQUFhO3lCQUNkLENBQ0YsQ0FBQztvQkFDSixDQUFDLENBQUM7b0JBQ0Y7Ozs7Ozs7Ozs7Ozs7Ozs7dUJBZ0JHO29CQUNILE1BQU0sc0JBQXNCLEdBQUcsQ0FDN0IsTUFBYyxFQUNkLEtBQWU7b0JBQ2Y7Ozs7Ozs7O3VCQVFHO29CQUNILEVBQUUsVUFBVSxHQUFHLElBQUksS0FBK0IsRUFBRSxFQUMzQyxFQUFFO3dCQUNYLElBQ0Usb0JBQW9COzRCQUNwQixtQ0FBbUMsRUFBRSxFQUNyQyxDQUFDOzRCQUNELE9BQU8sS0FBSyxDQUFDO3dCQUNmLENBQUM7d0JBQ0Qsb0JBQW9CLEVBQUUsQ0FBQzt3QkFDdkIsMERBQTBEO3dCQUMxRCwwREFBMEQ7d0JBQzFELHVEQUF1RDt3QkFDdkQscURBQXFEO3dCQUNyRCwwREFBMEQ7d0JBQzFELHFEQUFxRDt3QkFDckQsK0NBQStDO3dCQUMvQyxlQUFlLEdBQUcsSUFBSSxDQUFDO3dCQUN2Qiw0REFBNEQ7d0JBQzVELDZEQUE2RDt3QkFDN0QscURBQXFEO3dCQUNyRCwyREFBMkQ7d0JBQzNELDBEQUEwRDt3QkFDMUQsNERBQTREO3dCQUM1RCxNQUFNLEtBQUssR0FDVCxVQUFVLElBQUksb0JBQW9CLEtBQUssQ0FBQzs0QkFDdEMsQ0FBQyxDQUFDLHNCQUFzQixDQUFDLEtBQUssRUFBRSxLQUFLLENBQUM7NEJBQ3RDLENBQUMsQ0FBQyxJQUFJLENBQUM7d0JBQ1gsMkRBQTJEO3dCQUMzRCx5REFBeUQ7d0JBQ3pELE1BQU0sU0FBUyxHQUNiLEtBQUssS0FBSyxJQUFJLElBQUksUUFBUSxDQUFDLElBQUksS0FBSyxTQUFTLENBQUM7d0JBQ2hELHdEQUF3RDt3QkFDeEQsNERBQTREO3dCQUM1RCwyQkFBMkI7NEJBQ3pCLFFBQVEsQ0FBQyxJQUFJLEtBQUssU0FBUztnQ0FDekIsQ0FBQyxDQUFDO29DQUNFLEdBQUcsRUFBRSxJQUFJLEdBQUcsQ0FDVixRQUFRLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUM5QztvQ0FDRCxPQUFPLEVBQUUsb0JBQW9CO29DQUM3QixNQUFNO29DQUNOLE1BQU0sRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsYUFBYTtpQ0FDbkQ7Z0NBQ0gsQ0FBQyxDQUFDLElBQUksQ0FBQzt3QkFDWCxJQUFJLEtBQUssSUFBSSxRQUFRLENBQUMsSUFBSSxLQUFLLFNBQVMsRUFBRSxDQUFDOzRCQUN6QyxjQUFjLENBQUMsUUFBUSxFQUFFLEtBQUssQ0FBQyxDQUFDOzRCQUNoQyxRQUFRLEdBQUcsRUFBRSxHQUFHLFFBQVEsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLENBQUM7d0JBQzVDLENBQUM7NkJBQU0sQ0FBQzs0QkFDTix5REFBeUQ7NEJBQ3pELHVEQUF1RDs0QkFDdkQsc0RBQXNEOzRCQUN0RCxvREFBb0Q7NEJBQ3BELCtDQUErQzs0QkFDL0MseURBQXlEOzRCQUN6RCx1REFBdUQ7NEJBQ3ZELFFBQVE7NEJBQ1IsUUFBUSxHQUFHLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxDQUFDOzRCQUMvQix5REFBeUQ7NEJBQ3pELDBEQUEwRDs0QkFDMUQsc0RBQXNEOzRCQUN0RCxrQkFBa0IsQ0FBQyxTQUFTLEVBQUUsQ0FBQzt3QkFDakMsQ0FBQzt3QkFDRCxhQUFhLENBQUMsSUFBSSxDQUNoQixnRUFBZ0UsRUFDaEU7NEJBQ0UsYUFBYSxFQUFFLEtBQUs7NEJBQ3BCLE1BQU07NEJBQ04sYUFBYTs0QkFDYixvQkFBb0I7NEJBQ3BCLE1BQU0sRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsYUFBYTt5QkFDbkQsQ0FDRixDQUFDO3dCQUNGLElBQUksRUFBRSxhQUFhLENBQUM7NEJBQ2xCLGdDQUFnQyxFQUFFLG9CQUFvQjt5QkFDdkQsQ0FBQyxDQUFDO3dCQUNILE9BQU8sSUFBSSxDQUFDO29CQUNkLENBQUMsQ0FBQztvQkFFRjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7dUJBb0JHO29CQUNILE1BQU0sMkJBQTJCLEdBQUcsS0FBSyxFQUN2QyxNQUFjLEVBQ2QsS0FBYyxFQU9kLEVBQUU7d0JBQ0YsTUFBTSxPQUFPLEdBQUcsQ0FBQyx5QkFBeUIsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7d0JBQ3JELE1BQU0sZ0JBQWdCLEdBQUcsK0JBQStCLEVBQUUsQ0FBQzt3QkFDM0QsSUFBSSxPQUFPLEdBQUcsZ0JBQWdCLEVBQUUsQ0FBQzs0QkFDL0IsT0FBTztnQ0FDTCxTQUFTLEVBQUUsS0FBSztnQ0FDaEIsS0FBSyxFQUFFLElBQUksb0JBQW9CLENBQzdCLDhDQUE4QyxnQkFBZ0Isc0JBQXNCLG1DQUFtQyxFQUFFLG1JQUFtSSxNQUFNLE1BQU0sS0FBSyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLEVBQ2hVLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxDQUNqQjs2QkFDRixDQUFDO3dCQUNKLENBQUM7d0JBQ0QsYUFBYSxDQUFDLElBQUksQ0FDaEIsZ0dBQWdHLEVBQ2hHOzRCQUNFLGFBQWEsRUFBRSxLQUFLOzRCQUNwQixNQUFNOzRCQUNOLGFBQWE7NEJBQ2IseUJBQXlCLEVBQUUsT0FBTzs0QkFDbEMsZ0JBQWdCO3lCQUNqQixDQUNGLENBQUM7d0JBQ0YsSUFBSSxFQUFFLGFBQWEsQ0FBQzs0QkFDbEIscUNBQXFDLEVBQUUsT0FBTzt5QkFDL0MsQ0FBQyxDQUFDO3dCQUNILG9EQUFvRDt3QkFDcEQsNkRBQTZEO3dCQUM3RCw0REFBNEQ7d0JBQzVELHNEQUFzRDt3QkFDdEQsZ0NBQWdDO3dCQUNoQyxPQUFPOzRCQUNMLFNBQVMsRUFBRSxJQUFJOzRCQUNmLE1BQU0sRUFBRSxNQUFNLFFBQVEsQ0FDcEIsbUNBQW1DLEVBQUUsRUFDckMsRUFBRSx5QkFBeUIsRUFBRSxPQUFPLEVBQUUsQ0FDdkM7eUJBQ0YsQ0FBQztvQkFDSixDQUFDLENBQUM7b0JBRUYsMERBQTBEO29CQUMxRCwwREFBMEQ7b0JBQzFELE1BQU0sZUFBZSxHQUFHLEtBQUssRUFDM0IsR0FHQyxFQUNELGdCQUFzRCxFQUN0RCxVQUFnQyxFQUNJLEVBQUU7d0JBQ3RDLE1BQU0sRUFBRSxPQUFPLEVBQUUsY0FBYyxFQUFFLEdBQy9CLE1BQU0sdUJBQXVCLENBQUM7NEJBQzVCLEtBQUs7NEJBQ0wsR0FBRzs0QkFDSCxTQUFTOzRCQUNULFVBQVUsRUFBRSw0QkFBNEI7NEJBQ3hDLFVBQVU7NEJBQ1YsNEJBQTRCLEVBQzFCLEtBQUssQ0FBQyw0QkFBNEI7NEJBQ3BDLFNBQVMsRUFBRSxLQUFLLEVBQUUsRUFDaEIsWUFBWSxFQUNaLFdBQVcsRUFDWCw0QkFBNEIsRUFBRSxVQUFVLEVBQ3hDLFlBQVksR0FDRSxFQUFFLEVBQUU7Z0NBQ2xCLE1BQU0sWUFBWSxDQUNoQixLQUFLLEVBQ0wsb0JBQW9CLENBQUMsWUFBWSxFQUFFLFNBQVMsQ0FBQyxFQUM3QztvQ0FDRSxHQUFHLENBQUMsTUFBTSxnQkFBZ0IsRUFBRSxDQUFDO29DQUM3Qiw0QkFBNEIsRUFBRSxVQUFVO2lDQUN6QyxFQUNELEVBQUUsWUFBWSxFQUFFLFdBQVcsRUFBRSxZQUFZLEVBQUUsQ0FDNUMsQ0FBQzs0QkFDSixDQUFDO3lCQUNGLENBQUMsQ0FBQzt3QkFDTCxJQUFJLGNBQWM7NEJBQUUsSUFBSSxFQUFFLGFBQWEsQ0FBQyxjQUFjLENBQUMsQ0FBQzt3QkFDeEQsT0FBTyxPQUFPLENBQUM7b0JBQ2pCLENBQUMsQ0FBQztvQkFFRiw4REFBOEQ7b0JBQzlELGdFQUFnRTtvQkFDaEUsZ0VBQWdFO29CQUNoRSw0REFBNEQ7b0JBQzVELDJCQUEyQjtvQkFDM0IsSUFBSSxjQUFjLElBQUksZ0JBQWdCLEVBQUUsQ0FBQzt3QkFDdkMsSUFBSSxDQUFDOzRCQUNILE1BQU0sS0FBSyxHQUFHLE1BQU0sS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFO2dDQUN4QyxXQUFXLEVBQUUsTUFBTTs2QkFDcEIsQ0FBQyxDQUFDOzRCQUNILElBQUksS0FBSyxDQUFDLE1BQU0sS0FBSyxTQUFTLEVBQUUsQ0FBQztnQ0FDL0IsYUFBYSxDQUFDLEtBQUssQ0FDakIsZ0RBQWdELEVBQ2hELEVBQUUsYUFBYSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUMvQyxDQUFDO2dDQUNGLE9BQU87NEJBQ1QsQ0FBQzs0QkFDRCwwREFBMEQ7NEJBQzFELDhCQUE4Qjs0QkFDOUIsSUFDRSxDQUFDLE1BQU0sZUFBZSxDQUFDLEtBQUssRUFBRSxLQUFLLElBQUksRUFBRSxDQUFDLENBQUM7Z0NBQ3pDLEdBQUcsQ0FBQyxNQUFNLGFBQWEsRUFBRSxDQUFDO2dDQUMxQixNQUFNLEVBQUUsY0FBYztnQ0FDdEIsUUFBUSxFQUFFLGdCQUFnQjs2QkFDM0IsQ0FBQyxDQUFDLENBQUMsS0FBSyxVQUFVLEVBQ25CLENBQUM7Z0NBQ0QsT0FBTzs0QkFDVCxDQUFDOzRCQUNELE1BQU0sV0FBVyxHQUFHLEtBQUssQ0FBQyxTQUFTO2dDQUNqQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsU0FBUztnQ0FDbEIsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQzs0QkFFZiw0REFBNEQ7NEJBQzVELDREQUE0RDs0QkFDNUQsd0RBQXdEOzRCQUN4RCw2REFBNkQ7NEJBQzdELDBEQUEwRDs0QkFDMUQsb0RBQW9EOzRCQUNwRCw0REFBNEQ7NEJBQzVELDBEQUEwRDs0QkFDMUQsNERBQTREOzRCQUM1RCw0REFBNEQ7NEJBQzVELDBEQUEwRDs0QkFDMUQsMERBQTBEOzRCQUMxRCxxREFBcUQ7NEJBQ3JELHlEQUF5RDs0QkFDekQsdURBQXVEOzRCQUN2RCxxREFBcUQ7NEJBQ3JELHlEQUF5RDs0QkFDekQscURBQXFEOzRCQUNyRCxvREFBb0Q7NEJBQ3BELHFEQUFxRDs0QkFDckQsd0RBQXdEOzRCQUN4RCx5REFBeUQ7NEJBQ3pELFlBQVk7NEJBQ1osSUFBSSxzQkFBc0IsR0FBRyxRQUFRLENBQUMsT0FBTyxDQUFDOzRCQUM5QyxNQUFNLFlBQVksR0FDaEIsZUFBZSxDQUFDLGdCQUFnQixDQUFDLEVBQUUsVUFBVTtnQ0FDN0Msd0JBQXdCLENBQUM7NEJBQzNCLElBQUksUUFBUSxDQUFDLE9BQU8sR0FBRyxZQUFZLEdBQUcsQ0FBQyxFQUFFLENBQUM7Z0NBQ3hDLE1BQU0sTUFBTSxHQUFHLE1BQU0scUJBQXFCLENBQUMsS0FBSyxDQUFDLENBQUM7Z0NBQ2xELHNCQUFzQjtvQ0FDcEIsc0JBQXNCLENBQ3BCLE1BQU0sQ0FBQyxNQUFNLEVBQ2IsY0FBYyxFQUNkLEVBQUUsSUFBSSxFQUFFLGVBQWUsRUFBRSxDQUMxQixHQUFHLENBQUMsQ0FBQzs0QkFDVixDQUFDOzRCQUVELHFEQUFxRDs0QkFDckQsc0RBQXNEOzRCQUN0RCxrREFBa0Q7NEJBQ2xELHNDQUFzQzs0QkFDdEMsWUFBWSxDQUFDLEtBQUssRUFBRSxDQUFDOzRCQUNyQixJQUFJLFVBQW1ELENBQUM7NEJBQ3hELElBQUksQ0FBQztnQ0FDSCx1REFBdUQ7Z0NBQ3ZELHVEQUF1RDtnQ0FDdkQsb0RBQW9EO2dDQUNwRCxzREFBc0Q7Z0NBQ3RELHNEQUFzRDtnQ0FDdEQsa0RBQWtEO2dDQUNsRCxzREFBc0Q7Z0NBQ3RELDJDQUEyQztnQ0FDM0MscURBQXFEO2dDQUNyRCxnQ0FBZ0M7Z0NBQ2hDLFVBQVUsR0FBRyxNQUFNLG1CQUFtQixDQUNwQyxLQUFLLEVBQ0wsY0FBYyxFQUNkLEdBQUcsRUFBRSxDQUNILFdBQVcsQ0FBQztvQ0FDVixLQUFLO29DQUNMLGFBQWEsRUFBRSxLQUFLO29DQUNwQixvQkFBb0IsRUFBRSxLQUFLLENBQUMsWUFBWTtvQ0FDeEMsWUFBWTtvQ0FDWixpQkFBaUIsRUFBRSxXQUFXO29DQUM5QixTQUFTLEVBQUUsYUFBYSxDQUFDLEtBQUssQ0FBQyxVQUFVLEVBQUUsS0FBSyxDQUFDO29DQUNqRCxNQUFNLEVBQUUsY0FBYztvQ0FDdEIsUUFBUSxFQUFFLGdCQUFnQjtvQ0FDMUIsY0FBYyxFQUFFLEtBQUssQ0FBQyxXQUFXO29DQUNqQyxvREFBb0Q7b0NBQ3BELG1EQUFtRDtvQ0FDbkQsaURBQWlEO29DQUNqRCxvQkFBb0IsRUFBRSxzQkFBc0I7aUNBQzdDLENBQUMsQ0FDTCxDQUFDOzRCQUNKLENBQUM7b0NBQVMsQ0FBQztnQ0FDVCxZQUFZLENBQUMsTUFBTSxFQUFFLENBQUM7NEJBQ3hCLENBQUM7NEJBQ0QsSUFBSSxVQUFVLENBQUMsSUFBSSxLQUFLLE9BQU8sRUFBRSxDQUFDO2dDQUNoQyxPQUFPLEVBQUUsY0FBYyxFQUFFLFVBQVUsQ0FBQyxjQUFjLEVBQUUsQ0FBQzs0QkFDdkQsQ0FBQzs0QkFDRCxJQUFJLFVBQVUsQ0FBQyxJQUFJLEtBQUssV0FBVyxFQUFFLENBQUM7Z0NBQ3BDLE9BQU8sRUFBRSxjQUFjLEVBQUUsVUFBVSxDQUFDLGNBQWMsRUFBRSxDQUFDOzRCQUN2RCxDQUFDOzRCQUVELHlEQUF5RDs0QkFDekQsZ0RBQWdEOzRCQUNoRCxJQUNFLFVBQVUsQ0FBQyxJQUFJLEtBQUssV0FBVztnQ0FDL0IsVUFBVSxDQUFDLGFBQWEsRUFDeEIsQ0FBQztnQ0FDRCxNQUFNLFlBQVksQ0FDaEIsS0FBSyxFQUNMLG9CQUFvQixDQUFDLFlBQVksRUFBRSxTQUFTLENBQUMsRUFDN0M7b0NBQ0UsS0FBSztvQ0FDTCxZQUFZLEVBQUUsTUFBTSxnQkFBZ0IsRUFBRTtvQ0FDdEMsV0FBVyxFQUFFLElBQUksSUFBSSxFQUFFO2lDQUN4QixDQUNGLENBQUM7Z0NBQ0YsT0FBTzs0QkFDVCxDQUFDOzRCQUVELElBQ0UsVUFBVSxDQUFDLElBQUksS0FBSyxXQUFXO2dDQUMvQixVQUFVLENBQUMsSUFBSSxLQUFLLFFBQVE7Z0NBQzVCLFVBQVUsQ0FBQyxJQUFJLEtBQUssU0FBUyxFQUM3QixDQUFDO2dDQUNELHVEQUF1RDtnQ0FDdkQseURBQXlEO2dDQUN6RCwyQkFBMkI7Z0NBQzNCLE1BQU0sTUFBTSxHQUFHLE1BQU0scUJBQXFCLENBQUMsS0FBSyxDQUFDLENBQUM7Z0NBQ2xELFFBQVEsR0FBRyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsQ0FBQztnQ0FFcEMsb0RBQW9EO2dDQUNwRCw0Q0FBNEM7Z0NBQzVDLE1BQU0sY0FBYyxHQUFHLElBQUksR0FBRyxFQUFzQixDQUFDO2dDQUNyRCxNQUFNLGVBQWUsR0FBRyxJQUFJLEdBQUcsRUFBc0IsQ0FBQztnQ0FDdEQsS0FBSyxNQUFNLENBQUMsSUFBSSxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUM7b0NBQzlCLElBQUksQ0FBQyxDQUFDLFNBQVMsS0FBSyxjQUFjLEVBQUUsQ0FBQzt3Q0FDbkMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLENBQUM7b0NBQ3RDLENBQUM7eUNBQU0sSUFDTCxDQUFDLENBQUMsU0FBUyxLQUFLLGdCQUFnQjt3Q0FDaEMsQ0FBQyxDQUFDLFNBQVMsS0FBSyxhQUFhLEVBQzdCLENBQUM7d0NBQ0QsZUFBZSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLENBQUM7b0NBQ3ZDLENBQUM7Z0NBQ0gsQ0FBQztnQ0FDRCxNQUFNLGNBQWMsR0FBRyxJQUFJLEdBQUcsRUFBc0IsQ0FBQztnQ0FDckQsS0FBSyxNQUFNLEVBQUUsSUFBSSxjQUFjLEVBQUUsQ0FBQztvQ0FDaEMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQzt3Q0FDN0IsY0FBYyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztvQ0FDekIsQ0FBQztnQ0FDSCxDQUFDO2dDQUVELElBQUksY0FBYyxDQUFDLElBQUksR0FBRyxDQUFDLEVBQUUsQ0FBQztvQ0FDNUIsa0RBQWtEO29DQUNsRCxnREFBZ0Q7b0NBQ2hELGtEQUFrRDtvQ0FDbEQsOENBQThDO29DQUM5QyxvREFBb0Q7b0NBQ3BELDJDQUEyQztvQ0FDM0MsaURBQWlEO29DQUNqRCw4Q0FBOEM7b0NBQzlDLElBQ0Usd0JBQXdCLEVBQUU7d0NBQzFCLDRCQUE0QixDQUMxQixNQUFNLENBQUMsTUFBTSxFQUNiLGNBQWMsRUFDZCxRQUFRLENBQUMsU0FBUyxDQUNuQixFQUNELENBQUM7d0NBQ0QsYUFBYSxDQUFDLEtBQUssQ0FDakIsdUZBQXVGLEVBQ3ZGLEVBQUUsYUFBYSxFQUFFLEtBQUssRUFBRSxDQUN6QixDQUFDO29DQUNKLENBQUM7eUNBQU0sQ0FBQzt3Q0FDTixnREFBZ0Q7d0NBQ2hELGtEQUFrRDt3Q0FDbEQsb0NBQW9DO3dDQUNwQyxhQUFhLENBQUMsS0FBSyxDQUNqQix5REFBeUQsRUFDekQsRUFBRSxhQUFhLEVBQUUsS0FBSyxFQUFFLENBQ3pCLENBQUM7d0NBQ0YsT0FBTztvQ0FDVCxDQUFDO2dDQUNILENBQUM7Z0NBRUQseURBQXlEO2dDQUN6RCxnREFBZ0Q7Z0NBQ2hELGFBQWEsQ0FBQyxLQUFLLENBQ2pCLGlFQUFpRSxFQUNqRSxFQUFFLGFBQWEsRUFBRSxLQUFLLEVBQUUsQ0FDekIsQ0FBQztnQ0FDRixNQUFNLGVBQWUsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FDeEMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxTQUFTLEtBQUssYUFBYSxDQUM3QyxDQUFDO2dDQUNGLElBQUksV0FBb0IsQ0FBQztnQ0FDekIsSUFBSSxlQUFlLEVBQUUsQ0FBQztvQ0FDcEIsV0FBVyxHQUFHLGVBQWUsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDO2dDQUNoRCxDQUFDO3FDQUFNLENBQUM7b0NBQ04sSUFBSSxDQUFDLG1CQUFtQixDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDO3dDQUM1QyxNQUFNLElBQUksb0JBQW9CLENBQzVCLGlCQUFpQixLQUFLLDhCQUE4QixDQUNyRCxDQUFDO29DQUNKLENBQUM7b0NBQ0Qsb0RBQW9EO29DQUNwRCx1REFBdUQ7b0NBQ3ZELE1BQU0sU0FBUyxHQUFHLE1BQU0sS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFO3dDQUM1QyxXQUFXLEVBQUUsS0FBSztxQ0FDbkIsQ0FBQyxDQUFDO29DQUNILElBQUksU0FBUyxDQUFDLE1BQU0sS0FBSyxTQUFTLEVBQUUsQ0FBQzt3Q0FDbkMsT0FBTztvQ0FDVCxDQUFDO29DQUNELFdBQVcsR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDO2dDQUNoQyxDQUFDO2dDQUNELFdBQVcsR0FBRztvQ0FDWixHQUFHLEtBQUs7b0NBQ1IsS0FBSyxFQUFFLFdBQVc7b0NBQ2xCLE1BQU0sRUFBRSxTQUFTO29DQUNqQixNQUFNLEVBQUUsU0FBUztvQ0FDakIsS0FBSyxFQUFFLFNBQVM7b0NBQ2hCLFdBQVcsRUFBRSxTQUFTO2lDQUN2QixDQUFDO2dDQUNGLGlCQUFpQixHQUFHLFdBQVcsQ0FBQzs0QkFDbEMsQ0FBQztpQ0FBTSxDQUFDO2dDQUNOLE9BQU87NEJBQ1QsQ0FBQzt3QkFDSCxDQUFDO3dCQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7NEJBQ2IsTUFBTSxTQUFTLEdBQUcseUJBQXlCLENBQUMsR0FBRyxDQUFDLENBQUM7NEJBQ2pELElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztnQ0FDZixNQUFNLEdBQUcsQ0FBQzs0QkFDWixDQUFDOzRCQUNELE1BQU0sbUJBQW1CLENBQUM7Z0NBQ3hCLEtBQUs7Z0NBQ0wsV0FBVztnQ0FDWCxLQUFLO2dDQUNMLFNBQVM7Z0NBQ1QsR0FBRztnQ0FDSCxTQUFTO2dDQUNULFVBQVUsRUFDUixzREFBc0Q7NkJBQ3pELENBQUMsQ0FBQzs0QkFDSCxPQUFPO3dCQUNULENBQUM7b0JBQ0gsQ0FBQztvQkFFRCx1REFBdUQ7b0JBQ3ZELHVEQUF1RDtvQkFDdkQscURBQXFEO29CQUNyRCx3REFBd0Q7b0JBQ3hELGtEQUFrRDtvQkFDbEQseURBQXlEO29CQUN6RCxvREFBb0Q7b0JBQ3BELHlEQUF5RDtvQkFDekQsd0RBQXdEO29CQUN4RCx3REFBd0Q7b0JBQ3hELHlEQUF5RDtvQkFDekQsc0RBQXNEO29CQUN0RCx5REFBeUQ7b0JBQ3pELHdEQUF3RDtvQkFDeEQsMERBQTBEO29CQUMxRCwwREFBMEQ7b0JBQzFELDJEQUEyRDtvQkFDM0Qsc0RBQXNEO29CQUN0RCxrQ0FBa0M7b0JBQ2xDLElBQ0UsQ0FBQyxXQUFXO3dCQUNaLFNBQVMsRUFBRSxZQUFZLEtBQUssU0FBUzt3QkFDckMsdURBQXVEO3dCQUN2RCxxREFBcUQ7d0JBQ3JELHVEQUF1RDt3QkFDdkQsc0NBQXNDO3dCQUN0QyxLQUFLLENBQUMsWUFBWSxFQUFFLGtCQUFrQixLQUFLLElBQUksRUFDL0MsQ0FBQzt3QkFDRCxNQUFNLGtCQUFrQixHQUFHLFNBQVMsQ0FBQyxZQUFZLENBQUM7d0JBQ2xELElBQUksbUJBQXVDLENBQUM7d0JBQzVDLElBQUksQ0FBQzs0QkFDSCxtQkFBbUIsR0FBRyxNQUFNLEtBQUssQ0FBQyxlQUFlLEVBQUUsQ0FBQzt3QkFDdEQsQ0FBQzt3QkFBQyxNQUFNLENBQUM7NEJBQ1AsbUJBQW1CLEdBQUcsU0FBUyxDQUFDO3dCQUNsQyxDQUFDO3dCQUNELElBQ0UsbUJBQW1CLEtBQUssU0FBUzs0QkFDakMsbUJBQW1CLEtBQUssa0JBQWtCLEVBQzFDLENBQUM7NEJBQ0QsTUFBTSxHQUFHLEdBQUcsTUFBTSxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUU7Z0NBQ3RDLFdBQVcsRUFBRSxNQUFNOzZCQUNwQixDQUFDLENBQUM7NEJBQ0gsSUFDRSxDQUFDLE1BQU0sZUFBZSxDQUNwQixHQUFHLEVBQ0gsS0FBSyxJQUFJLEVBQUUsQ0FBQyxDQUFDO2dDQUNYLEdBQUcsQ0FBQyxNQUFNLGFBQWEsRUFBRSxDQUFDO2dDQUMxQixTQUFTOzZCQUNWLENBQUMsRUFDRixhQUFhLENBQ2QsQ0FBQyxLQUFLLFVBQVUsRUFDakIsQ0FBQztnQ0FDRCxPQUFPOzRCQUNULENBQUM7d0JBQ0gsQ0FBQztvQkFDSCxDQUFDO29CQUVELHFDQUFxQztvQkFDckMsdURBQXVEO29CQUN2RCwwREFBMEQ7b0JBQzFELDJEQUEyRDtvQkFDM0QsMkRBQTJEO29CQUMzRCwyREFBMkQ7b0JBQzNELHFEQUFxRDtvQkFDckQsbURBQW1EO29CQUNuRCwyREFBMkQ7b0JBQzNELHNEQUFzRDtvQkFDdEQscURBQXFEO29CQUNyRCxzREFBc0Q7b0JBQ3RELHdEQUF3RDtvQkFDeEQsbURBQW1EO29CQUNuRCx3REFBd0Q7b0JBQ3hELHlEQUF5RDtvQkFDekQsb0NBQW9DO29CQUNwQyxJQUFJLFdBQVcsR0FBRyxLQUFLLENBQUM7b0JBQ3hCLElBQ0UsQ0FBQyxXQUFXO3dCQUNaLFNBQVM7d0JBQ1QsU0FBUyxDQUFDLFFBQVEsS0FBSyxTQUFTO3dCQUNoQyxTQUFTLENBQUMsYUFBYSxLQUFLLFNBQVMsRUFDckMsQ0FBQzt3QkFDRCxNQUFNLGVBQWUsR0FBRyxTQUFTLENBQUM7d0JBQ2xDLDBEQUEwRDt3QkFDMUQseURBQXlEO3dCQUN6RCxzREFBc0Q7d0JBQ3RELFNBQVM7d0JBQ1QsSUFBSSxVQUE0QixDQUFDO3dCQUNqQyxJQUFJLENBQUM7NEJBQ0gsVUFBVSxHQUFHLElBQUksSUFBSSxDQUNuQixVQUFVLENBQUMsZUFBZSxDQUFDLFFBQVEsQ0FBQyxDQUNyQyxDQUFDO3dCQUNKLENBQUM7d0JBQUMsTUFBTSxDQUFDOzRCQUNQLFVBQVUsR0FBRyxTQUFTLENBQUM7d0JBQ3pCLENBQUM7d0JBQ0QsSUFBSSxDQUFDOzRCQUNILElBQUksRUFBRSxRQUFRLENBQUMscUNBQXFDLEVBQUU7Z0NBQ3BELHVDQUF1QyxFQUFFLElBQUk7NkJBQzlDLENBQUMsQ0FBQzs0QkFDSCxNQUFNLE1BQU0sR0FBRyxNQUFNLFdBQVcsQ0FDOUI7Z0NBQ0UsU0FBUyxFQUFFLGVBQWU7Z0NBQzFCLFdBQVcsRUFBRSxvQkFBb0I7Z0NBQ2pDLGFBQWEsRUFBRSxlQUFlLENBQUMsTUFBTTtnQ0FDckMsU0FBUyxFQUFFO29DQUNULEtBQUssRUFBRSxlQUFlLENBQUMsS0FBSztvQ0FDNUIsT0FBTyxFQUFFLGVBQWUsQ0FBQyxPQUFPO2lDQUNqQzs2QkFDRixFQUNEO2dDQUNFLFNBQVM7Z0NBQ1QsVUFBVTtnQ0FDVixRQUFRLEVBQUUsZUFBZSxDQUFDLFFBQVE7Z0NBQ2xDLG1CQUFtQixFQUFFLGVBQWUsQ0FBQyxhQUFhO2dDQUNsRCxhQUFhLEVBQUUsSUFBSTs2QkFDcEIsQ0FDRixDQUFDOzRCQUNGLFdBQVcsR0FBRyxJQUFJLENBQUM7NEJBQ25CLHVEQUF1RDs0QkFDdkQsb0RBQW9EOzRCQUNwRCx1REFBdUQ7NEJBQ3ZELHdEQUF3RDs0QkFDeEQsc0RBQXNEOzRCQUN0RCxtREFBbUQ7NEJBQ25ELHVDQUF1Qzs0QkFFdkMsd0RBQXdEOzRCQUN4RCxxREFBcUQ7NEJBQ3JELGtEQUFrRDs0QkFDbEQsd0RBQXdEOzRCQUN4RCxxREFBcUQ7NEJBQ3JELGtEQUFrRDs0QkFDbEQsdURBQXVEOzRCQUN2RCxpREFBaUQ7NEJBQ2pELHNEQUFzRDs0QkFDdEQscURBQXFEOzRCQUNyRCx3REFBd0Q7NEJBQ3hELHdEQUF3RDs0QkFDeEQsTUFBTSxtQkFBbUIsR0FDdkIsTUFBTSxDQUFDLEdBQUcsS0FBSyxTQUFTO2dDQUN4QixNQUFNLENBQUMsR0FBRyxDQUFDLFNBQVMsS0FBSyxTQUFTO2dDQUNsQyxNQUFNLENBQUMsS0FBSyxLQUFLLFNBQVM7Z0NBQzFCLE1BQU0sQ0FBQyxNQUFNLEtBQUssU0FBUztnQ0FDM0IsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQztnQ0FDeEIsTUFBTSxDQUFDLE1BQU0sSUFBSSxJQUFJO2dDQUNyQixNQUFNLENBQUMsT0FBTyxLQUFLLEtBQUs7Z0NBQ3hCLE9BQU8sTUFBTSxDQUFDLFNBQVMsS0FBSyxRQUFRO2dDQUNwQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FDaEIsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxTQUFTLEtBQUssYUFBYSxDQUNyQztnQ0FDRCxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FDaEIsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxTQUFTLEtBQUssYUFBYSxDQUNyQztnQ0FDRCxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FDaEIsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUNKLENBQUMsQ0FBQyxTQUFTLEtBQUssZUFBZTtvQ0FDL0IsQ0FBQyxDQUFDLFFBQVEsS0FBSyxlQUFlLENBQUMsUUFBUSxDQUMxQyxDQUFDOzRCQUVKLElBQ0UsbUJBQW1CO2dDQUNuQixNQUFNLENBQUMsR0FBRyxFQUFFLFNBQVM7Z0NBQ3JCLE1BQU0sQ0FBQyxNQUFNLEVBQ2IsQ0FBQztnQ0FDRCxzREFBc0Q7Z0NBQ3RELHFEQUFxRDtnQ0FDckQsdURBQXVEO2dDQUN2RCxvREFBb0Q7Z0NBQ3BELGtEQUFrRDtnQ0FDbEQsZ0RBQWdEO2dDQUNoRCxnQkFBZ0I7Z0NBQ2hCLE1BQU0sYUFBYSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUN0QyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQ0osQ0FBQyxDQUFDLEtBQUssS0FBSyxLQUFLO29DQUNqQixDQUFDLENBQUMsQ0FBQyxTQUFTLEtBQUssZUFBZTt3Q0FDOUIsQ0FBQyxDQUFDLFNBQVMsS0FBSyxZQUFZO3dDQUM1QixDQUFDLENBQUMsU0FBUyxLQUFLLGVBQWUsQ0FBQyxDQUNyQyxDQUFDO2dDQUNGLElBQUksYUFBYSxFQUFFLENBQUM7b0NBQ2xCLGtEQUFrRDtvQ0FDbEQsa0RBQWtEO29DQUNsRCw2Q0FBNkM7b0NBQzdDLHdDQUF3QztvQ0FDeEMsSUFBSSxFQUFFLGFBQWEsQ0FBQzt3Q0FDbEIsR0FBRyxTQUFTLENBQUMsaUJBQWlCLENBQzVCLGFBQWEsQ0FBQyxTQUFTLEtBQUssZUFBZTs0Q0FDekMsQ0FBQyxDQUFDLFdBQVc7NENBQ2IsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxTQUFTLEtBQUssWUFBWTtnREFDeEMsQ0FBQyxDQUFDLFFBQVE7Z0RBQ1YsQ0FBQyxDQUFDLFdBQVcsQ0FDbEI7d0NBQ0QsR0FBRyxTQUFTLENBQUMscUJBQXFCLENBQ2hDLHNCQUFzQixDQUN2QjtxQ0FDRixDQUFDLENBQUM7b0NBQ0gsYUFBYSxDQUFDLElBQUksQ0FDaEIsdURBQXVELEVBQ3ZEO3dDQUNFLGFBQWEsRUFBRSxLQUFLO3dDQUNwQixTQUFTLEVBQUUsYUFBYSxDQUFDLFNBQVM7cUNBQ25DLENBQ0YsQ0FBQztvQ0FDRixPQUFPO2dDQUNULENBQUM7Z0NBQ0QsV0FBVyxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUM7Z0NBQ3pCLGNBQWMsR0FBRyxjQUFjLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO2dDQUNsRCxpREFBaUQ7Z0NBQ2pELGtEQUFrRDtnQ0FDbEQsc0JBQXNCLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO2dDQUNwQyxRQUFRLEdBQUc7b0NBQ1QsSUFBSSxFQUFFLE9BQU87b0NBQ2IsTUFBTSxFQUFFLE1BQU0sQ0FBQyxNQUFNO29DQUNyQixNQUFNLEVBQUUsTUFBTSxDQUFDLE1BQU07aUNBQ3RCLENBQUM7Z0NBQ0YsaUJBQWlCLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQztnQ0FDMUMsSUFBSSxFQUFFLGFBQWEsQ0FBQztvQ0FDbEIsR0FBRyxTQUFTLENBQUMsaUJBQWlCLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUM7b0NBQ2pELEdBQUcsU0FBUyxDQUFDLGlCQUFpQixDQUFDLGlCQUFpQixDQUFDO29DQUNqRCxHQUFHLFNBQVMsQ0FBQyxxQkFBcUIsQ0FDaEMsc0JBQXNCLENBQ3ZCO2lDQUNGLENBQUMsQ0FBQzs0QkFDTCxDQUFDO2lDQUFNLENBQUM7Z0NBQ04scURBQXFEO2dDQUNyRCxpREFBaUQ7Z0NBQ2pELG9EQUFvRDtnQ0FDcEQsbURBQW1EO2dDQUNuRCxzREFBc0Q7Z0NBQ3RELG9EQUFvRDtnQ0FDcEQsK0NBQStDO2dDQUMvQyxVQUFVO2dDQUNWLElBQUksRUFBRSxhQUFhLENBQ2pCLFNBQVMsQ0FBQyxxQkFBcUIsQ0FDN0Isd0JBQXdCLENBQ3pCLENBQ0YsQ0FBQzs0QkFDSixDQUFDO3dCQUNILENBQUM7d0JBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQzs0QkFDYiw4Q0FBOEM7NEJBQzlDLHNEQUFzRDs0QkFDdEQsaURBQWlEOzRCQUNqRCx1REFBdUQ7NEJBQ3ZELHdEQUF3RDs0QkFDeEQsNENBQTRDOzRCQUM1QyxnREFBZ0Q7NEJBQ2hELElBQ0UsaUJBQWlCLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQztnQ0FDekIsZUFBZSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFDdkIsQ0FBQztnQ0FDRCxhQUFhLENBQUMsSUFBSSxDQUNoQix1REFBdUQsRUFDdkQsRUFBRSxhQUFhLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxHQUFHLENBQUMsT0FBTyxFQUFFLENBQy9DLENBQUM7Z0NBQ0YsT0FBTzs0QkFDVCxDQUFDOzRCQUNELE1BQU0sR0FBRyxDQUFDO3dCQUNaLENBQUM7b0JBQ0gsQ0FBQztvQkFFRCxnREFBZ0Q7b0JBQ2hELHdEQUF3RDtvQkFDeEQsMERBQTBEO29CQUMxRCx1Q0FBdUM7b0JBQ3ZDLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQzt3QkFDakIsMkRBQTJEO3dCQUMzRCwwREFBMEQ7d0JBQzFELGtDQUFrQzt3QkFDbEMsNERBQTREO3dCQUM1RCx1REFBdUQ7d0JBQ3ZELDhEQUE4RDt3QkFDOUQsTUFBTSxlQUFlLEdBQUc7NEJBQ3RCLFNBQVMsRUFBRSxhQUFzQjs0QkFDakMsc0RBQXNEOzRCQUN0RCxzREFBc0Q7NEJBQ3RELHlEQUF5RDs0QkFDekQsV0FBVyxFQUNULFFBQVEsRUFBRSxXQUFXLElBQUksb0JBQW9COzRCQUMvQyw4Q0FBOEM7NEJBQzlDLDRDQUE0Qzs0QkFDNUMsK0NBQStDOzRCQUMvQyx1REFBdUQ7NEJBQ3ZELEdBQUcsQ0FBQyxRQUFRO2dDQUNWLENBQUMsQ0FBQztvQ0FDRSxTQUFTLEVBQUU7d0NBQ1QsS0FBSyxFQUFFLFFBQVEsQ0FBQyxLQUFLO3dDQUNyQixZQUFZLEVBQUUsUUFBUSxDQUFDLFlBQVk7d0NBQ25DLFlBQVksRUFBRSxRQUFRLENBQUMsWUFBWTt3Q0FDbkMsZ0JBQWdCLEVBQUUsUUFBUSxDQUFDLGdCQUFnQjt3Q0FDM0MsVUFBVSxFQUFFLFFBQVEsQ0FBQyxVQUFVO3dDQUMvQix1QkFBdUIsRUFDckIsUUFBUSxDQUFDLHVCQUF1QjtxQ0FDbkM7aUNBQ0Y7Z0NBQ0gsQ0FBQyxDQUFDLEVBQUUsQ0FBQzt5QkFDUixDQUFDO3dCQUNGLElBQUksS0FBSyxJQUFJLFFBQVEsRUFBRSxDQUFDOzRCQUN0Qix5REFBeUQ7NEJBQ3pELHlEQUF5RDs0QkFDekQsc0RBQXNEOzRCQUN0RCx5REFBeUQ7NEJBQ3pELDJEQUEyRDs0QkFDM0QsNERBQTREOzRCQUM1RCw0REFBNEQ7NEJBQzVELDRDQUE0Qzs0QkFDNUMsSUFBSSxFQUFFLFFBQVEsQ0FBQyxtQ0FBbUMsRUFBRTtnQ0FDbEQsbUNBQW1DLEVBQUUsSUFBSTs2QkFDMUMsQ0FBQyxDQUFDOzRCQUNILE1BQU0sY0FBYyxHQUFHLFdBQVcsQ0FDaEMsZUFBZTs0QkFDZixtREFBbUQ7NEJBQ25ELCtDQUErQzs0QkFDL0MsZ0RBQWdEOzRCQUNoRCxxREFBcUQ7NEJBQ3JELHNEQUFzRDs0QkFDdEQsa0RBQWtEOzRCQUNsRCxFQUFFLFNBQVMsRUFBRSxXQUFXLEVBQUUsSUFBSSxFQUFFLENBQ2pDLENBQUM7NEJBQ0YsZUFBZSxHQUFHLGNBQWMsQ0FBQzs0QkFDakMsNkRBQTZEOzRCQUM3RCw4REFBOEQ7NEJBQzlELDBEQUEwRDs0QkFDMUQsNkRBQTZEOzRCQUM3RCwyREFBMkQ7NEJBQzNELDhCQUE4Qjs0QkFDOUIsS0FBSyxjQUFjO2lDQUNoQixJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtnQ0FDVixNQUFNLEtBQUssR0FBRyxjQUFjLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDO2dDQUMxQyxJQUFJLEtBQUssS0FBSyxTQUFTO29DQUFFLGNBQWMsR0FBRyxLQUFLLENBQUM7NEJBQ2xELENBQUMsQ0FBQztnQ0FDRixnREFBZ0Q7Z0NBQ2hELHlEQUF5RDtpQ0FDeEQsS0FBSyxDQUFDLEdBQUcsRUFBRSxHQUFFLENBQUMsQ0FBQyxDQUFDOzRCQUNuQiw0REFBNEQ7NEJBQzVELDJEQUEyRDs0QkFDM0QsdURBQXVEOzRCQUN2RCwyREFBMkQ7NEJBQzNELDBEQUEwRDs0QkFDMUQsK0NBQStDOzRCQUMvQyxRQUFRLEdBQUc7Z0NBQ1QsSUFBSSxFQUFFLE9BQU87Z0NBQ2IsTUFBTSxFQUFFLEVBQUU7Z0NBQ1YsTUFBTSxFQUFFLElBQUk7NkJBQ2IsQ0FBQzs0QkFDRixNQUFNLEdBQUcsR0FBRyxJQUFJLElBQUksRUFBRSxDQUFDOzRCQUN2QixXQUFXLEdBQUc7Z0NBQ1osS0FBSztnQ0FDTCxNQUFNLEVBQUUsU0FBUztnQ0FDakIsWUFBWSxFQUFFLFFBQVEsQ0FBQyxZQUFZO2dDQUNuQyxZQUFZLEVBQUUsUUFBUSxDQUFDLFlBQVk7Z0NBQ25DLFdBQVcsRUFBRSxRQUFRLENBQUMsV0FBVztnQ0FDakMsZ0JBQWdCLEVBQUUsUUFBUSxDQUFDLGdCQUFnQjtnQ0FDM0MsS0FBSyxFQUFFLFFBQVEsQ0FBQyxLQUFLO2dDQUNyQix3REFBd0Q7Z0NBQ3hELHdEQUF3RDtnQ0FDeEQsMERBQTBEO2dDQUMxRCx5REFBeUQ7Z0NBQ3pELG1EQUFtRDtnQ0FDbkQsMERBQTBEO2dDQUMxRCx1REFBdUQ7Z0NBQ3ZELHlEQUF5RDtnQ0FDekQseURBQXlEO2dDQUN6RCx1REFBdUQ7Z0NBQ3ZELDBEQUEwRDtnQ0FDMUQsc0NBQXNDO2dDQUN0QyxVQUFVLEVBQUUsUUFBUSxDQUFDLFVBQVUsSUFBSSxFQUFFO2dDQUNyQyxTQUFTLEVBQUUsR0FBRztnQ0FDZCxTQUFTLEVBQUUsR0FBRztnQ0FDZCxTQUFTLEVBQUUsR0FBRzs2QkFDZixDQUFDOzRCQUNGLGlCQUFpQixHQUFHLENBQUMsR0FBRyxDQUFDOzRCQUN6QixzREFBc0Q7NEJBQ3RELDRDQUE0Qzs0QkFDNUMsb0RBQW9EOzRCQUNwRCw2Q0FBNkM7NEJBQzdDLHNCQUFzQixHQUFHLENBQUMsR0FBRyxDQUFDOzRCQUM5QixJQUFJLEVBQUUsYUFBYSxDQUFDO2dDQUNsQixHQUFHLFNBQVMsQ0FBQyxpQkFBaUIsQ0FBQyxTQUFTLENBQUM7Z0NBQ3pDLEdBQUcsU0FBUyxDQUFDLGlCQUFpQixDQUFDLGlCQUFpQixDQUFDOzZCQUNsRCxDQUFDLENBQUM7d0JBQ0wsQ0FBQzs2QkFBTSxDQUFDOzRCQUNOLElBQUksQ0FBQztnQ0FDSCxJQUFJLEVBQUUsUUFBUSxDQUFDLG1DQUFtQyxFQUFFO29DQUNsRCxtQ0FBbUMsRUFBRSxLQUFLO2lDQUMzQyxDQUFDLENBQUM7Z0NBQ0gsTUFBTSxNQUFNLEdBQUcsTUFBTSxXQUFXLENBQUMsZUFBZSxFQUFFO29DQUNoRCxTQUFTO2lDQUNWLENBQUMsQ0FBQztnQ0FDSCxXQUFXLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQztnQ0FDekIsY0FBYyxHQUFHLGNBQWMsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUM7Z0NBQ2xELDRDQUE0QztnQ0FDNUMsc0JBQXNCLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO2dDQUVwQyxJQUFJLE1BQU0sQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLENBQUM7b0NBQzFCLE1BQU0sTUFBTSxHQUFHO3dDQUNiLE1BQU0sRUFBRSxDQUFDLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQzt3Q0FDMUIsTUFBTSxFQUFFLE1BQU0sQ0FBQyxNQUFNLElBQUksSUFBSTtxQ0FDOUIsQ0FBQztvQ0FDRixRQUFRLEdBQUcsTUFBTSxDQUFDLE9BQU87d0NBQ3ZCLENBQUMsQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUM7d0NBQzFCLENBQUMsQ0FBQyxFQUFFLEdBQUcsTUFBTSxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsQ0FBQztnQ0FDbkMsQ0FBQztnQ0FDRCxpQkFBaUIsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDO2dDQUMxQyxJQUFJLEVBQUUsYUFBYSxDQUFDO29DQUNsQixHQUFHLFNBQVMsQ0FBQyxpQkFBaUIsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQztvQ0FDakQsR0FBRyxTQUFTLENBQUMsaUJBQWlCLENBQUMsaUJBQWlCLENBQUM7aUNBQ2xELENBQUMsQ0FBQztnQ0FFSCxJQUFJLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxLQUFLLFNBQVMsRUFBRSxDQUFDO29DQUNwQyxhQUFhLENBQUMsSUFBSSxDQUNoQixnREFBZ0QsRUFDaEQ7d0NBQ0UsYUFBYSxFQUFFLEtBQUs7d0NBQ3BCLE1BQU0sRUFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU07cUNBQzFCLENBQ0YsQ0FBQztvQ0FFRiw4RUFBOEU7b0NBQzlFLCtFQUErRTtvQ0FDL0UsZ0ZBQWdGO29DQUNoRixtRkFBbUY7b0NBQ25GLGdEQUFnRDtvQ0FFaEQsT0FBTztnQ0FDVCxDQUFDOzRCQUNILENBQUM7NEJBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztnQ0FDYixrREFBa0Q7Z0NBQ2xELElBQ0UsbUJBQW1CLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQztvQ0FDM0IsZUFBZSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFDdkIsQ0FBQztvQ0FDRCw0Q0FBNEM7b0NBQzVDLDJDQUEyQztvQ0FDM0Msa0RBQWtEO29DQUNsRCwrQ0FBK0M7b0NBQy9DLGFBQWEsQ0FBQyxJQUFJLENBQ2hCLDZDQUE2QyxFQUM3QyxFQUFFLGFBQWEsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLEdBQUcsQ0FBQyxPQUFPLEVBQUUsQ0FDL0MsQ0FBQztvQ0FDRixPQUFPO2dDQUNULENBQUM7cUNBQU0sQ0FBQztvQ0FDTixNQUFNLFNBQVMsR0FBRyx5QkFBeUIsQ0FBQyxHQUFHLENBQUMsQ0FBQztvQ0FDakQsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO3dDQUNmLE1BQU0sR0FBRyxDQUFDO29DQUNaLENBQUM7b0NBQ0QsTUFBTSxtQkFBbUIsQ0FBQzt3Q0FDeEIsS0FBSzt3Q0FDTCxXQUFXO3dDQUNYLEtBQUs7d0NBQ0wsU0FBUzt3Q0FDVCxHQUFHO3dDQUNILFNBQVM7d0NBQ1QsVUFBVSxFQUNSLDJDQUEyQztxQ0FDOUMsQ0FBQyxDQUFDO29DQUNILE9BQU87Z0NBQ1QsQ0FBQzs0QkFDSCxDQUFDO3dCQUNILENBQUMsQ0FBQyxtQ0FBbUM7b0JBQ3ZDLENBQUMsQ0FBQyx3QkFBd0I7b0JBQzFCLE1BQU0sQ0FDSixXQUFXLEVBQ1gsMkNBQTJDLENBQzVDLENBQUM7b0JBRUYsOERBQThEO29CQUM5RCw0REFBNEQ7b0JBQzVELDREQUE0RDtvQkFDNUQsNERBQTREO29CQUM1RCxzREFBc0Q7b0JBQ3RELDBEQUEwRDtvQkFDMUQsaUNBQWlDO29CQUNqQyxFQUFFO29CQUNGLDJEQUEyRDtvQkFDM0QseURBQXlEO29CQUN6RCwyREFBMkQ7b0JBQzNELDJEQUEyRDtvQkFDM0QseURBQXlEO29CQUN6RCw2REFBNkQ7b0JBQzdELDZEQUE2RDtvQkFDN0QsMkRBQTJEO29CQUMzRCwwREFBMEQ7b0JBQzFELHlEQUF5RDtvQkFDekQsMERBQTBEO29CQUMxRCxRQUFRO29CQUNSLElBQ0UsQ0FBQyxNQUFNLGVBQWUsQ0FDcEIsV0FBVyxFQUNYLEtBQUssSUFBSSxFQUFFLENBQUMsQ0FBQzt3QkFDWCxHQUFHLENBQUMsTUFBTSxhQUFhLEVBQUUsQ0FBQzt3QkFDMUIsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO3FCQUNwQyxDQUFDLEVBQ0YsYUFBYSxDQUNkLENBQUMsS0FBSyxVQUFVLEVBQ2pCLENBQUM7d0JBQ0QsT0FBTztvQkFDVCxDQUFDO29CQUVELHdEQUF3RDtvQkFDeEQseURBQXlEO29CQUN6RCwrREFBK0Q7b0JBQy9ELHFEQUFxRDtvQkFDckQsMkRBQTJEO29CQUMzRCwyREFBMkQ7b0JBQzNELHlEQUF5RDtvQkFDekQsMkRBQTJEO29CQUMzRCx3REFBd0Q7b0JBQ3hELHdEQUF3RDtvQkFDeEQsNERBQTREO29CQUM1RCwyREFBMkQ7b0JBQzNELGtEQUFrRDtvQkFDbEQsSUFBSSxTQUFTLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQzt3QkFDOUIsdURBQXVEO3dCQUN2RCx1REFBdUQ7d0JBQ3ZELDZEQUE2RDt3QkFDN0QsNkRBQTZEO3dCQUM3RCw0REFBNEQ7d0JBQzVELHVEQUF1RDt3QkFDdkQsMkRBQTJEO3dCQUMzRCwyREFBMkQ7d0JBQzNELGtEQUFrRDt3QkFDbEQsRUFBRTt3QkFDRixvREFBb0Q7d0JBQ3BELHNEQUFzRDt3QkFDdEQsa0RBQWtEO3dCQUNsRCx5REFBeUQ7d0JBQ3pELHVEQUF1RDt3QkFDdkQsUUFBUTt3QkFDUixNQUFNLGdCQUFnQixHQUNwQixTQUFTLENBQUMsUUFBUSxLQUFLLFNBQVM7NEJBQ2hDLFFBQVEsQ0FBQyxJQUFJLEtBQUssU0FBUzs0QkFDM0IsUUFBUSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQ2xCLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FDSixDQUFDLENBQUMsU0FBUyxLQUFLLGVBQWU7Z0NBQy9CLENBQUMsQ0FBQyxRQUFRLEtBQUssU0FBUyxDQUFDLFFBQVEsQ0FDcEMsQ0FBQzt3QkFDSixJQUFJLGdCQUFnQixFQUFFLENBQUM7NEJBQ3JCLDBEQUEwRDs0QkFDMUQsb0JBQW9CO3dCQUN0QixDQUFDOzZCQUFNLENBQUM7NEJBQ04sMERBQTBEOzRCQUMxRCx5REFBeUQ7NEJBQ3pELDBEQUEwRDs0QkFDMUQsd0RBQXdEOzRCQUN4RCx3REFBd0Q7NEJBQ3hELHFEQUFxRDs0QkFDckQscURBQXFEOzRCQUNyRCxJQUFJLFVBQTRCLENBQUM7NEJBQ2pDLElBQUksQ0FBQztnQ0FDSCxVQUFVO29DQUNSLFNBQVMsQ0FBQyxRQUFRLEtBQUssU0FBUzt3Q0FDOUIsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLENBQUM7d0NBQzFDLENBQUMsQ0FBQyxTQUFTLENBQUM7NEJBQ2xCLENBQUM7NEJBQUMsTUFBTSxDQUFDO2dDQUNQLFVBQVUsR0FBRyxTQUFTLENBQUM7NEJBQ3pCLENBQUM7NEJBQ0QsSUFBSSxZQUErQixDQUFDOzRCQUNwQyxJQUFJLENBQUM7Z0NBQ0gsTUFBTSxPQUFPLEdBQUcsTUFBTSxLQUFLLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FDdkMsS0FBSyxFQUNMO29DQUNFLFNBQVMsRUFBRSxlQUFlO29DQUMxQixXQUFXLEVBQUUsb0JBQW9CO29DQUNqQyxhQUFhLEVBQUUsU0FBUyxDQUFDLE1BQU07b0NBQy9CLFNBQVMsRUFBRTt3Q0FDVCxLQUFLLEVBQUUsU0FBUyxDQUFDLEtBQUs7d0NBQ3RCLE9BQU8sRUFBRSxTQUFTLENBQUMsT0FBTztxQ0FDM0I7aUNBQ0YsRUFDRDtvQ0FDRSxTQUFTO29DQUNULFVBQVU7b0NBQ1YsUUFBUSxFQUFFLFNBQVMsQ0FBQyxRQUFRO29DQUM1QixtQkFBbUIsRUFBRSxTQUFTLENBQUMsYUFBYTtpQ0FDN0MsQ0FDRixDQUFDO2dDQUNGLHNEQUFzRDtnQ0FDdEQsdURBQXVEO2dDQUN2RCw4Q0FBOEM7Z0NBQzlDLElBQUksRUFBRSxhQUFhLENBQ2pCLFNBQVMsQ0FBQywrQkFBK0IsQ0FBQyxJQUFJLENBQUMsQ0FDaEQsQ0FBQztnQ0FDRiwwREFBMEQ7Z0NBQzFELDJEQUEyRDtnQ0FDM0QseURBQXlEO2dDQUN6RCwyQkFBMkI7Z0NBQzNCLEVBQUU7Z0NBQ0YsdURBQXVEO2dDQUN2RCwyREFBMkQ7Z0NBQzNELHlEQUF5RDtnQ0FDekQsNERBQTREO2dDQUM1RCx5REFBeUQ7Z0NBQ3pELHNEQUFzRDtnQ0FDdEQsc0RBQXNEO2dDQUN0RCwyQkFBMkI7Z0NBQzNCLDJEQUEyRDtnQ0FDM0QsMkRBQTJEO2dDQUMzRCw2REFBNkQ7Z0NBQzdELDBEQUEwRDtnQ0FDMUQsNERBQTREO2dDQUM1RCx5QkFBeUI7Z0NBQ3pCLE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUM7Z0NBQzNCLFlBQVksR0FBRyxJQUFJO29DQUNqQixDQUFDLENBQUU7d0NBQ0MsR0FBRyxJQUFJO3dDQUNQLFNBQVMsRUFBRTs0Q0FDVCxLQUFLLEVBQUUsU0FBUyxDQUFDLEtBQUs7NENBQ3RCLE9BQU8sRUFBRSxTQUFTLENBQUMsT0FBTzt5Q0FDM0I7cUNBQ1E7b0NBQ2IsQ0FBQyxDQUFDLFNBQVMsQ0FBQzs0QkFDaEIsQ0FBQzs0QkFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO2dDQUNiLDBEQUEwRDtnQ0FDMUQsdURBQXVEO2dDQUN2RCwwREFBMEQ7Z0NBQzFELGFBQWE7Z0NBQ2IsRUFBRTtnQ0FDRiwyREFBMkQ7Z0NBQzNELDBEQUEwRDtnQ0FDMUQsMkRBQTJEO2dDQUMzRCx3REFBd0Q7Z0NBQ3hELDREQUE0RDtnQ0FDNUQsd0NBQXdDO2dDQUN4QyxJQUNFLGlCQUFpQixDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUM7b0NBQ3pCLGVBQWUsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQ3ZCLENBQUM7b0NBQ0QsT0FBTztnQ0FDVCxDQUFDO2dDQUNELHlEQUF5RDtnQ0FDekQseURBQXlEO2dDQUN6RCwwREFBMEQ7Z0NBQzFELDJEQUEyRDtnQ0FDM0QsMkRBQTJEO2dDQUMzRCx3REFBd0Q7Z0NBQ3hELGdEQUFnRDtnQ0FDaEQsTUFBTSxHQUFHLENBQUM7NEJBQ1osQ0FBQzs0QkFDRCx5REFBeUQ7NEJBQ3pELHlEQUF5RDs0QkFDekQscURBQXFEOzRCQUNyRCx5REFBeUQ7NEJBQ3pELHdEQUF3RDs0QkFDeEQsNERBQTREOzRCQUM1RCw2REFBNkQ7NEJBQzdELDREQUE0RDs0QkFDNUQsaURBQWlEOzRCQUNqRCxJQUFJLFFBQVEsQ0FBQyxJQUFJLEtBQUssU0FBUyxJQUFJLFlBQVksRUFBRSxDQUFDO2dDQUNoRCxvQkFBb0IsQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLFlBQVksQ0FBQyxDQUFDOzRCQUN0RCxDQUFDO2lDQUFNLENBQUM7Z0NBQ04sUUFBUSxHQUFHLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxDQUFDOzRCQUNqQyxDQUFDO3dCQUNILENBQUMsQ0FBQyw4QkFBOEI7b0JBQ2xDLENBQUM7b0JBRUQsd0RBQXdEO29CQUN4RCx5REFBeUQ7b0JBQ3pELDBEQUEwRDtvQkFDMUQseURBQXlEO29CQUN6RCxvREFBb0Q7b0JBQ3BELDZDQUE2QztvQkFDN0MsTUFBTSxnQkFBZ0IsR0FBRyxvQkFBb0IsQ0FDM0MsS0FBSyxFQUNMLFdBQVcsQ0FDWixDQUFDO29CQUNGLE1BQU0sYUFBYSxHQUFHLE1BQU0sZ0JBQWdCLEVBQUUsQ0FBQztvQkFFL0MsOERBQThEO29CQUM5RCw2REFBNkQ7b0JBQzdELDhEQUE4RDtvQkFDOUQsb0JBQW9CO29CQUNwQixNQUFNLGtCQUFrQixHQUFHLElBQUksa0JBQWtCLENBQy9DLGFBQWEsQ0FDZCxDQUFDO29CQUVGLHdEQUF3RDtvQkFDeEQsMERBQTBEO29CQUMxRCx1REFBdUQ7b0JBQ3ZELElBQUksZUFBZSxHQUEyQixJQUFJLENBQUM7b0JBRW5ELG1CQUFtQjtvQkFDbkIsc0VBQXNFO29CQUN0RSxPQUFPLElBQUksRUFBRSxDQUFDO3dCQUNaLGFBQWEsRUFBRSxDQUFDO3dCQUVoQixtREFBbUQ7d0JBQ25ELG9EQUFvRDt3QkFDcEQsa0RBQWtEO3dCQUNsRCxzREFBc0Q7d0JBQ3RELHNCQUFzQjt3QkFDdEIsSUFBSSxZQUFZLENBQUMsV0FBVyxFQUFFLEVBQUUsQ0FBQzs0QkFDL0IsTUFBTSwyQkFBMkIsQ0FBQztnQ0FDaEMsS0FBSztnQ0FDTCxZQUFZO2dDQUNaLFNBQVM7Z0NBQ1QsT0FBTyxFQUFFLFFBQVEsQ0FBQyxPQUFPO2dDQUN6QixPQUFPLEVBQUUsWUFBWSxDQUFDLGlCQUFpQjs2QkFDeEMsQ0FBQyxDQUFDOzRCQUNILHlEQUF5RDs0QkFDekQseURBQXlEOzRCQUN6RCxPQUFPO3dCQUNULENBQUM7d0JBRUQsOEJBQThCO3dCQUM5QixJQUNFLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxtQkFBbUI7NEJBQ2hDLHFCQUFxQixFQUNyQixDQUFDOzRCQUNELGFBQWEsQ0FBQyxJQUFJLENBQ2hCLDRDQUE0QyxFQUM1QztnQ0FDRSxhQUFhLEVBQUUsS0FBSztnQ0FDcEIsYUFBYTtnQ0FDYixTQUFTLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLG1CQUFtQjs2QkFDNUMsQ0FDRixDQUFDOzRCQUNGLE1BQU0sWUFBWSxDQUNoQixLQUFLLEVBQ0wsb0JBQW9CLENBQUMsWUFBWSxFQUFFLFNBQVMsQ0FBQyxFQUM3QztnQ0FDRSxLQUFLO2dDQUNMLFlBQVksRUFBRSxNQUFNLGdCQUFnQixFQUFFO2dDQUN0QyxXQUFXLEVBQUUsSUFBSSxJQUFJLEVBQUU7NkJBQ3hCLENBQ0YsQ0FBQzs0QkFDRixPQUFPO3dCQUNULENBQUM7d0JBRUQsSUFBSSxXQUFXLEdBQUcsQ0FBQyxDQUFDO3dCQUNwQixJQUFJLENBQUM7NEJBQ0gscUNBQXFDOzRCQUNyQyxxREFBcUQ7NEJBQ3JELHNEQUFzRDs0QkFDdEQsaURBQWlEOzRCQUNqRCxxREFBcUQ7NEJBQ3JELHNEQUFzRDs0QkFDdEQsaURBQWlEOzRCQUNqRCxzREFBc0Q7NEJBQ3RELG9EQUFvRDs0QkFDcEQsa0RBQWtEOzRCQUNsRCxxQ0FBcUM7NEJBQ3JDLEVBQUU7NEJBQ0YscURBQXFEOzRCQUNyRCxtREFBbUQ7NEJBQ25ELGdEQUFnRDs0QkFDaEQsb0RBQW9EOzRCQUNwRCxzREFBc0Q7NEJBQ3RELHFEQUFxRDs0QkFDckQsK0JBQStCOzRCQUMvQixrREFBa0Q7NEJBQ2xELHNEQUFzRDs0QkFDdEQsa0NBQWtDOzRCQUNsQyxJQUFJLFlBQVksQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDO2dDQUM5QixhQUFhLENBQUMsS0FBSyxDQUFDLHlCQUF5QixFQUFFO29DQUM3QyxhQUFhLEVBQUUsS0FBSztvQ0FDcEIsYUFBYTtpQ0FDZCxDQUFDLENBQUM7Z0NBQ0gsZ0RBQWdEO2dDQUNoRCwrQ0FBK0M7Z0NBQy9DLG9EQUFvRDtnQ0FDcEQsaURBQWlEO2dDQUNqRCxpREFBaUQ7Z0NBQ2pELFFBQVE7Z0NBQ1IsTUFBTSxhQUFhLEVBQUUsQ0FBQztnQ0FDdEIsSUFBSSxRQUFRLENBQUMsSUFBSSxLQUFLLFdBQVcsRUFBRSxDQUFDO29DQUNsQyxjQUFjLENBQ1osUUFBUSxFQUNSLE1BQU0scUJBQXFCLENBQUMsS0FBSyxFQUFFLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FDcEQsQ0FBQztvQ0FDRixRQUFRLEdBQUcsRUFBRSxHQUFHLFFBQVEsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLENBQUM7Z0NBQzVDLENBQUM7Z0NBQ0QscURBQXFEO2dDQUNyRCw2Q0FBNkM7Z0NBQzdDLHFEQUFxRDtnQ0FDckQscURBQXFEO2dDQUNyRCxrREFBa0Q7Z0NBQ2xELE1BQU0sRUFBRSxzQkFBc0IsRUFBRSxHQUFHLE1BQU0sTUFBTSxDQUM3QyxpQ0FBaUMsQ0FDbEMsQ0FBQztnQ0FDRixNQUFNLGFBQWEsR0FBRyxNQUFNLHNCQUFzQixDQUFDO29DQUNqRCxZQUFZO29DQUNaLFlBQVk7b0NBQ1osV0FBVztvQ0FDWCxlQUFlLEVBQ2IsUUFBUSxDQUFDLElBQUksS0FBSyxPQUFPO3dDQUN2QixDQUFDLENBQUMsUUFBUSxDQUFDLE1BQU07d0NBQ2pCLENBQUMsQ0FBQyxTQUFTO29DQUNmLHVCQUF1QixFQUFFLFFBQVEsQ0FBQyxJQUFJLEtBQUssT0FBTztvQ0FDbEQsUUFBUTtvQ0FDUixVQUFVLEVBQUUsSUFBSTtvQ0FDaEIsY0FBYztvQ0FDZCxTQUFTO29DQUNULGdCQUFnQjtvQ0FDaEIsa0RBQWtEO29DQUNsRCxpREFBaUQ7b0NBQ2pELDZDQUE2QztvQ0FDN0MsK0NBQStDO29DQUMvQyxnREFBZ0Q7b0NBQ2hELDZDQUE2QztvQ0FDN0MseUNBQXlDO29DQUN6Qyx1QkFBdUI7b0NBQ3ZCLGVBQWUsRUFBRSxRQUFRLENBQUMsT0FBTztvQ0FDakMsY0FBYyxFQUFFLFFBQVEsQ0FBQyxTQUFTO2lDQUNuQyxDQUFDLENBQUM7Z0NBQ0gsSUFBSSxhQUFhLEVBQUUsY0FBYyxLQUFLLFNBQVMsRUFBRSxDQUFDO29DQUNoRCx1Q0FBdUM7b0NBQ3ZDLGlEQUFpRDtvQ0FDakQsMkNBQTJDO29DQUMzQyxpREFBaUQ7b0NBQ2pELCtDQUErQztvQ0FDL0MsNENBQTRDO29DQUM1Qyx3Q0FBd0M7b0NBQ3hDLGdEQUFnRDtvQ0FDaEQsT0FBTyxNQUFNLFFBQVEsQ0FBQyxhQUFhLENBQUMsY0FBYyxDQUFDLENBQUM7Z0NBQ3RELENBQUM7Z0NBQ0QsT0FBTzs0QkFDVCxDQUFDOzRCQUVELElBQUksUUFBUSxDQUFDLElBQUksS0FBSyxPQUFPLEVBQUUsQ0FBQztnQ0FDOUIsTUFBTSxJQUFJLEdBQUcsTUFBTSxxQkFBcUIsQ0FDdEMsS0FBSyxFQUNMLFFBQVEsQ0FBQyxJQUFJLEtBQUssV0FBVztvQ0FDM0IsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxNQUFNO29DQUNqQixDQUFDLENBQUMsU0FBUyxDQUNkLENBQUM7Z0NBQ0YsSUFBSSxRQUFRLENBQUMsSUFBSSxLQUFLLFdBQVcsRUFBRSxDQUFDO29DQUNsQyxjQUFjLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxDQUFDO29DQUMvQixRQUFRLEdBQUcsRUFBRSxHQUFHLFFBQVEsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLENBQUM7Z0NBQzVDLENBQUM7cUNBQU0sQ0FBQztvQ0FDTixRQUFRLEdBQUcsRUFBRSxHQUFHLElBQUksRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLENBQUM7Z0NBQ3hDLENBQUM7NEJBQ0gsQ0FBQzs0QkFDRCxNQUFNLENBQUMsUUFBUSxDQUFDLElBQUksS0FBSyxPQUFPLENBQUMsQ0FBQzs0QkFFbEMsK0JBQStCLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDOzRCQUVqRCxxREFBcUQ7NEJBQ3JELHFEQUFxRDs0QkFDckQsdURBQXVEOzRCQUN2RCxzREFBc0Q7NEJBQ3RELHNEQUFzRDs0QkFDdEQsZ0RBQWdEOzRCQUNoRCxJQUFJLDJCQUEyQixDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQztnQ0FDeEQsT0FBTzs0QkFDVCxDQUFDOzRCQUVELHlCQUF5Qjs0QkFDekIsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDOzRCQUN2QixNQUFNLGdCQUFnQixHQUFHLElBQUksR0FBRyxDQUM5QixRQUFRLENBQUMsTUFBTTtpQ0FDWixNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxTQUFTLEtBQUssZ0JBQWdCLENBQUM7aUNBQy9DLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxDQUMvQixDQUFDOzRCQUNGLE1BQU0sZUFBZSxHQUFHLFFBQVEsQ0FBQyxNQUFNO2lDQUNwQyxNQUFNLENBQ0wsQ0FDRSxDQUFDLEVBSTJCLEVBQUUsQ0FDOUIsQ0FBQyxDQUFDLFNBQVMsS0FBSyxjQUFjO2dDQUM5QixDQUFDLENBQUMsYUFBYSxLQUFLLFNBQVM7Z0NBQzdCLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUM7Z0NBQ3RDLEdBQUcsSUFBSyxDQUFDLENBQUMsU0FBUyxDQUFDLFFBQWlCLENBQUMsT0FBTyxFQUFFLENBQ2xEO2lDQUNBLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztnQ0FDWCxTQUFTLEVBQUUsZ0JBQXlCO2dDQUNwQyxXQUFXLEVBQUUsb0JBQW9CO2dDQUNqQyxhQUFhLEVBQUUsQ0FBQyxDQUFDLGFBQWE7Z0NBQzlCLFNBQVMsRUFBRTtvQ0FDVCxRQUFRLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxRQUFRO2lDQUMvQjs2QkFDRixDQUFDLENBQUMsQ0FBQzs0QkFFTixLQUFLLE1BQU0sU0FBUyxJQUFJLGVBQWUsRUFBRSxDQUFDO2dDQUN4QyxJQUFJLENBQUM7b0NBQ0gsTUFBTSxPQUFPLEdBQUcsTUFBTSxXQUFXLENBQUMsU0FBUyxFQUFFO3dDQUMzQyxTQUFTO3dDQUNULEdBQUcsMEJBQTBCLENBQzNCLFFBQVEsQ0FBQyxNQUFNLEVBQ2YsUUFBUSxDQUFDLE1BQU0sQ0FDaEI7cUNBQ0YsQ0FBQyxDQUFDO29DQUNILHFEQUFxRDtvQ0FDckQsb0RBQW9EO29DQUNwRCw2Q0FBNkM7b0NBQzdDLEVBQUU7b0NBQ0Ysb0RBQW9EO29DQUNwRCxrREFBa0Q7b0NBQ2xELGlEQUFpRDtvQ0FDakQsc0RBQXNEO29DQUN0RCxpREFBaUQ7b0NBQ2pELG9EQUFvRDtvQ0FDcEQsbURBQW1EO29DQUNuRCx5Q0FBeUM7b0NBQ3pDLElBQ0UsT0FBTyxDQUFDLE1BQU0sRUFBRSxNQUFNO3dDQUN0QixPQUFPLENBQUMsT0FBTyxLQUFLLElBQUksRUFDeEIsQ0FBQzt3Q0FDRCxtQkFBbUIsQ0FDakIsUUFBUSxDQUFDLE1BQU0sRUFDZixPQUFPLENBQUMsTUFBTSxDQUNmLENBQUM7b0NBQ0osQ0FBQztnQ0FDSCxDQUFDO2dDQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7b0NBQ2IsSUFBSSxtQkFBbUIsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQzt3Q0FDaEMsYUFBYSxDQUFDLElBQUksQ0FDaEIsa0NBQWtDLEVBQ2xDOzRDQUNFLGFBQWEsRUFBRSxLQUFLOzRDQUNwQixhQUFhLEVBQUUsU0FBUyxDQUFDLGFBQWE7eUNBQ3ZDLENBQ0YsQ0FBQzt3Q0FDRixTQUFTO29DQUNYLENBQUM7b0NBQ0QsTUFBTSxHQUFHLENBQUM7Z0NBQ1osQ0FBQzs0QkFDSCxDQUFDOzRCQUNELE1BQU0sQ0FBQyxRQUFRLENBQUMsSUFBSSxLQUFLLE9BQU8sQ0FBQyxDQUFDOzRCQUVsQyxtREFBbUQ7NEJBQ25ELHdEQUF3RDs0QkFDeEQsd0RBQXdEOzRCQUN4RCx3REFBd0Q7NEJBQ3hELHNEQUFzRDs0QkFDdEQsd0RBQXdEOzRCQUN4RCxzREFBc0Q7NEJBQ3RELGtEQUFrRDs0QkFDbEQseURBQXlEOzRCQUN6RCwwQ0FBMEM7NEJBQzFDLHlEQUF5RDs0QkFDekQsTUFBTSwyQkFBMkIsR0FBRyxJQUFJLEdBQUcsQ0FDekMsUUFBUSxDQUFDLE1BQU07aUNBQ1osTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsU0FBUyxLQUFLLGdCQUFnQixDQUFDO2lDQUMvQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsQ0FDL0IsQ0FBQzs0QkFDRixNQUFNLHNCQUFzQixHQUFHLGVBQWUsQ0FBQyxNQUFNLENBQ25ELENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FDWixDQUFDLDJCQUEyQixDQUFDLEdBQUcsQ0FDOUIsU0FBUyxDQUFDLGFBQWEsQ0FDeEIsQ0FDSixDQUFDOzRCQUVGLElBQUksc0JBQXNCLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO2dDQUN0QyxzREFBc0Q7Z0NBQ3RELHVEQUF1RDtnQ0FDdkQsdURBQXVEO2dDQUN2RCxxREFBcUQ7Z0NBQ3JELHVEQUF1RDtnQ0FDdkQsb0RBQW9EO2dDQUNwRCxhQUFhO2dDQUNiLElBQUksUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDO29DQUNwQixNQUFNLElBQUksR0FBRyxNQUFNLHFCQUFxQixDQUN0QyxLQUFLLEVBQ0wsUUFBUSxDQUFDLE1BQU0sQ0FDaEIsQ0FBQztvQ0FDRixNQUFNLDJCQUEyQixHQUFHLElBQUksR0FBRyxDQUN6QyxJQUFJLENBQUMsTUFBTTt5Q0FDUixNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxTQUFTLEtBQUssZ0JBQWdCLENBQUM7eUNBQy9DLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxDQUMvQixDQUFDO29DQUNGLE1BQU0scUJBQXFCLEdBQ3pCLHNCQUFzQixDQUFDLEtBQUssQ0FBQyxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQ3pDLDJCQUEyQixDQUFDLEdBQUcsQ0FDN0IsU0FBUyxDQUFDLGFBQWEsQ0FDeEIsQ0FDRixDQUFDO29DQUVKLElBQUkscUJBQXFCLEVBQUUsQ0FBQzt3Q0FDMUIsY0FBYyxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsQ0FBQztvQ0FDakMsQ0FBQzt5Q0FBTSxDQUFDO3dDQUNOLFFBQVEsR0FBRzs0Q0FDVCxHQUFHLENBQUMsTUFBTSxxQkFBcUIsQ0FBQyxLQUFLLENBQUMsQ0FBQzs0Q0FDdkMsSUFBSSxFQUFFLE9BQU87eUNBQ2QsQ0FBQztvQ0FDSixDQUFDO2dDQUNILENBQUM7cUNBQU0sQ0FBQztvQ0FDTixRQUFRLEdBQUc7d0NBQ1QsR0FBRyxDQUFDLE1BQU0scUJBQXFCLENBQUMsS0FBSyxDQUFDLENBQUM7d0NBQ3ZDLElBQUksRUFBRSxPQUFPO3FDQUNkLENBQUM7Z0NBQ0osQ0FBQzs0QkFDSCxDQUFDOzRCQUVELHdEQUF3RDs0QkFDeEQsa0RBQWtEOzRCQUNsRCwwREFBMEQ7NEJBQzFELDBEQUEwRDs0QkFDMUQseURBQXlEOzRCQUN6RCxtREFBbUQ7NEJBQ25ELDRCQUE0Qjs0QkFDNUIsRUFBRTs0QkFDRix1REFBdUQ7NEJBQ3ZELGlEQUFpRDs0QkFDakQsc0RBQXNEOzRCQUN0RCxJQUFJLHFCQUFxQixFQUFFLEVBQUUsQ0FBQztnQ0FDNUIsTUFBTSxPQUFPLEdBQUcsTUFBTSxrQkFBa0IsQ0FBQyxLQUFLLEVBQUU7b0NBQzlDLE1BQU0sRUFBRSxRQUFRLENBQUMsTUFBTTtvQ0FDdkIsTUFBTSxFQUFFLFFBQVEsQ0FBQyxNQUFNO2lDQUN4QixDQUFDLENBQUM7Z0NBQ0gsUUFBUSxHQUFHLEVBQUUsR0FBRyxPQUFPLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsQ0FBQztnQ0FDN0MsSUFBSSxPQUFPLENBQUMsR0FBRyxLQUFLLFNBQVMsRUFBRSxDQUFDO29DQUM5QixNQUFNLElBQUksc0JBQXNCLENBQzlCLHFCQUFxQixLQUFLLHVCQUF1QixPQUFPLENBQUMsR0FBRyxDQUFDLGdCQUFnQixLQUFLLE9BQU8sQ0FBQyxHQUFHLENBQUMsWUFBWSxXQUFXLE9BQU8sQ0FBQyxHQUFHLENBQUMsT0FBTywrQ0FBK0MsQ0FDeEwsQ0FBQztnQ0FDSixDQUFDOzRCQUNILENBQUM7NEJBRUQseURBQXlEOzRCQUN6RCx5REFBeUQ7NEJBQ3pELG1EQUFtRDs0QkFDbkQsd0RBQXdEOzRCQUN4RCxvQkFBb0I7NEJBQ3BCLElBQUksMkJBQTJCLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDO2dDQUN4RCxPQUFPOzRCQUNULENBQUM7NEJBRUQscURBQXFEOzRCQUNyRCxzREFBc0Q7NEJBQ3RELHlEQUF5RDs0QkFDekQsb0NBQW9DOzRCQUNwQyxJQUNFLGNBQWMsS0FBSyxTQUFTO2dDQUM1QixRQUFRLENBQUMsTUFBTSxDQUFDLE1BQU0sSUFBSSxjQUFjLEVBQ3hDLENBQUM7Z0NBQ0QsTUFBTSxJQUFJLHNCQUFzQixDQUM5QixRQUFRLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFDdEIsY0FBYyxDQUNmLENBQUM7NEJBQ0osQ0FBQzs0QkFFRCx3REFBd0Q7NEJBQ3hELHFEQUFxRDs0QkFDckQsd0RBQXdEOzRCQUN4RCxnREFBZ0Q7NEJBQ2hELHVEQUF1RDs0QkFDdkQsdURBQXVEOzRCQUN2RCxxREFBcUQ7NEJBQ3JELDJEQUEyRDs0QkFDM0Qsc0JBQXNCLEtBQUssUUFBUSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQzlDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FDSixDQUFDLENBQUMsU0FBUyxLQUFLLGFBQWE7Z0NBQzdCLENBQUMsQ0FBQyxTQUFTLEtBQUssYUFBYTtnQ0FDN0IsQ0FBQyxDQUFDLFNBQVMsS0FBSyxVQUFVLENBQzdCLENBQUM7NEJBRUYsYUFBYSxDQUFDLEtBQUssQ0FBQyw2QkFBNkIsRUFBRTtnQ0FDakQsYUFBYSxFQUFFLEtBQUs7Z0NBQ3BCLGFBQWE7Z0NBQ2IsVUFBVSxFQUFFLFFBQVEsQ0FBQyxNQUFNLENBQUMsTUFBTTtnQ0FDbEMsYUFBYSxFQUFFLGVBQWUsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxRQUFROzZCQUN2RCxDQUFDLENBQUM7NEJBQ0gsV0FBVyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQzs0QkFDekIsc0RBQXNEOzRCQUN0RCxxREFBcUQ7NEJBQ3JELHVEQUF1RDs0QkFDdkQsdURBQXVEOzRCQUN2RCwwREFBMEQ7NEJBQzFELE1BQU0sY0FBYyxHQUFHLGtCQUFrQixDQUFDLE9BQU8sQ0FDL0MsV0FBVyxFQUNYLFFBQVEsQ0FBQyxNQUFNLENBQ2hCLENBQUM7NEJBQ0YsSUFBSSxjQUFjLEdBQXlCLGVBQWU7Z0NBQ3hELENBQUMsQ0FBQyxNQUFNLGNBQWMsQ0FBQyxlQUFlLEVBQUUsUUFBUSxDQUFDLE1BQU0sQ0FBQztnQ0FDeEQsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxDQUFDOzRCQUV2QixJQUFJLGNBQWMsQ0FBQyxJQUFJLEtBQUssUUFBUSxFQUFFLENBQUM7Z0NBQ3JDLGVBQWUsR0FBRyxJQUFJLENBQUM7Z0NBQ3ZCLGNBQWMsR0FBRyxNQUFNLGNBQWMsQ0FBQztvQ0FDcEMsWUFBWTtvQ0FDWixXQUFXO29DQUNYLE1BQU0sRUFBRSxRQUFRLENBQUMsTUFBTTtvQ0FDdkIsYUFBYTtvQ0FDYixrQkFBa0I7b0NBQ2xCLDhDQUE4QztvQ0FDOUMsZ0RBQWdEO29DQUNoRCxzREFBc0Q7b0NBQ3RELGVBQWU7b0NBQ2YsaUJBQWlCLEVBQUUsS0FBSyxDQUFDLFlBQVk7aUNBQ3RDLENBQUMsQ0FBQzs0QkFDTCxDQUFDOzRCQUNELE1BQU0sY0FBYyxDQUFDOzRCQUVyQixJQUFJLGNBQWMsQ0FBQyxJQUFJLEtBQUssV0FBVyxFQUFFLENBQUM7Z0NBQ3hDLG9EQUFvRDtnQ0FDcEQscURBQXFEO2dDQUNyRCxtREFBbUQ7Z0NBQ25ELGVBQWUsR0FBRyxjQUFjLENBQUMsT0FBTyxDQUFDO2dDQUN6QyxNQUFNLGNBQWMsQ0FBQyxVQUFVLENBQUM7NEJBQ2xDLENBQUM7NEJBRUQsTUFBTSxNQUFNLEdBQUcsY0FBYyxDQUFDLE1BQU0sQ0FBQzs0QkFDckMsYUFBYSxDQUFDLEtBQUssQ0FBQyw4QkFBOEIsRUFBRTtnQ0FDbEQsYUFBYSxFQUFFLEtBQUs7Z0NBQ3BCLGFBQWE7Z0NBQ2IsUUFBUSxFQUFFLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxXQUFXO2dDQUNsQyxhQUFhLEVBQUUsZUFBZSxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLFFBQVE7NkJBQ3ZELENBQUMsQ0FBQzs0QkFDSCxzQkFBc0IsQ0FBQyxRQUFRLEVBQUUsQ0FBQzs0QkFFbEMsbURBQW1EOzRCQUNuRCxxREFBcUQ7NEJBQ3JELDJEQUEyRDs0QkFDM0QsMERBQTBEOzRCQUMxRCwyREFBMkQ7NEJBQzNELDBEQUEwRDs0QkFDMUQsSUFBSSxDQUFDO2dDQUNILHdEQUF3RDtnQ0FDeEQsc0RBQXNEO2dDQUN0RCw2Q0FBNkM7Z0NBQzdDLE1BQU0sYUFBYSxFQUFFLENBQUM7Z0NBQ3RCLE1BQU0sV0FBVyxDQUNmO29DQUNFLFNBQVMsRUFBRSxlQUFlO29DQUMxQixXQUFXLEVBQUUsb0JBQW9CO29DQUNqQyxTQUFTLEVBQUUsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFO2lDQUM5QixFQUNEO29DQUNFLFNBQVM7b0NBQ1QsR0FBRywwQkFBMEIsQ0FDM0IsUUFBUSxDQUFDLE1BQU0sRUFDZixRQUFRLENBQUMsTUFBTSxDQUNoQjtpQ0FDRixDQUNGLENBQUM7NEJBQ0osQ0FBQzs0QkFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO2dDQUNiLElBQ0UsbUJBQW1CLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQztvQ0FDM0IsZUFBZSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFDdkIsQ0FBQztvQ0FDRCxhQUFhLENBQUMsSUFBSSxDQUNoQiw4REFBOEQsRUFDOUQsRUFBRSxhQUFhLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxHQUFHLENBQUMsT0FBTyxFQUFFLENBQy9DLENBQUM7b0NBQ0YsT0FBTztnQ0FDVCxDQUFDO2dDQUNELE1BQU0sR0FBRyxDQUFDOzRCQUNaLENBQUM7NEJBRUQsSUFBSSxFQUFFLGFBQWEsQ0FBQztnQ0FDbEIsR0FBRyxTQUFTLENBQUMsaUJBQWlCLENBQUMsV0FBVyxDQUFDOzZCQUM1QyxDQUFDLENBQUM7NEJBQ0gsT0FBTzt3QkFDVCxDQUFDO3dCQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7NEJBQ2IsSUFBSSxrQkFBa0IsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztnQ0FDL0Isc0JBQXNCLENBQUMsUUFBUSxFQUFFLENBQUM7Z0NBQ2xDLG1EQUFtRDtnQ0FDbkQsd0RBQXdEO2dDQUN4RCw2QkFBNkI7Z0NBQzdCLG1EQUFtRDtnQ0FDbkQsc0RBQXNEO2dDQUN0RCxvREFBb0Q7Z0NBQ3BELG1EQUFtRDtnQ0FDbkQsaURBQWlEO2dDQUNqRCxvREFBb0Q7Z0NBQ3BELGlEQUFpRDtnQ0FDakQsa0RBQWtEO2dDQUNsRCxpREFBaUQ7Z0NBQ2pELDBDQUEwQztnQ0FDMUMsb0RBQW9EO2dDQUNwRCxxREFBcUQ7Z0NBQ3JELGdDQUFnQztnQ0FDaEMsRUFBRTtnQ0FDRixvREFBb0Q7Z0NBQ3BELGtEQUFrRDtnQ0FDbEQsNENBQTRDO2dDQUM1Qyx1REFBdUQ7Z0NBQ3ZELGlEQUFpRDtnQ0FDakQsbURBQW1EO2dDQUNuRCxtREFBbUQ7Z0NBQ25ELDZDQUE2QztnQ0FDN0Msb0RBQW9EO2dDQUNwRCwrQ0FBK0M7Z0NBQy9DLG9DQUFvQztnQ0FDcEMsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsV0FBVyxDQUFDO2dDQUNsRCxhQUFhLENBQUMsS0FBSyxDQUFDLG9CQUFvQixFQUFFO29DQUN4QyxhQUFhLEVBQUUsS0FBSztvQ0FDcEIsYUFBYTtvQ0FDYixRQUFRLEVBQUUsZ0JBQWdCO29DQUMxQixLQUFLLEVBQUUsR0FBRyxDQUFDLFNBQVM7b0NBQ3BCLEtBQUssRUFBRSxHQUFHLENBQUMsU0FBUztvQ0FDcEIsS0FBSyxFQUFFLEdBQUcsQ0FBQyxTQUFTO2lDQUNyQixDQUFDLENBQUM7Z0NBQ0gsTUFBTSxpQkFBaUIsR0FDckIsOEJBQThCLENBQzVCLEdBQUcsQ0FBQyxTQUFTLEVBQ2IsR0FBRyxDQUFDLFNBQVMsRUFDYixHQUFHLENBQUMsU0FBUyxDQUNkLENBQUM7Z0NBQ0osSUFBSSxpQkFBaUIsRUFBRSxDQUFDO29DQUN0QixhQUFhLENBQUMsS0FBSyxDQUFDLGlCQUFpQixDQUFDLENBQUM7Z0NBQ3pDLENBQUM7Z0NBRUQsK0NBQStDO2dDQUMvQywwREFBMEQ7Z0NBQzFELHNEQUFzRDtnQ0FDdEQseURBQXlEO2dDQUN6RCx3REFBd0Q7Z0NBQ3hELG1EQUFtRDtnQ0FDbkQsK0NBQStDO2dDQUMvQyxNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7Z0NBQ25DLE1BQU0sQ0FDSixRQUFRLENBQUMsSUFBSSxLQUFLLE9BQU8sRUFDekIsb0RBQW9ELENBQ3JELENBQUM7Z0NBQ0YsSUFBSSxnQkFFSCxDQUFDO2dDQUNGLElBQUksQ0FBQztvQ0FDSCxnQkFBZ0IsR0FBRyxNQUFNLGdCQUFnQixDQUFDO3dDQUN4QyxVQUFVLEVBQUUsR0FBRzt3Q0FDZixLQUFLO3dDQUNMLEdBQUcsRUFBRSxXQUFXO3dDQUNoQixJQUFJO3dDQUNKLFNBQVM7d0NBQ1QsUUFBUTt3Q0FDUixlQUFlO3dDQUNmLHNCQUFzQjtxQ0FDdkIsQ0FBQyxDQUFDO2dDQUNMLENBQUM7Z0NBQUMsT0FBTyxlQUFlLEVBQUUsQ0FBQztvQ0FDekIsdURBQXVEO29DQUN2RCxzREFBc0Q7b0NBQ3RELHVEQUF1RDtvQ0FDdkQscURBQXFEO29DQUNyRCxvREFBb0Q7b0NBQ3BELG9EQUFvRDtvQ0FDcEQsK0JBQStCO29DQUMvQixJQUFJLHVCQUF1QixDQUFDLEVBQUUsQ0FBQyxlQUFlLENBQUMsRUFBRSxDQUFDO3dDQUNoRCxJQUNFLHNCQUFzQixDQUNwQixtQkFBbUIsRUFDbkIsZUFBZSxDQUNoQixFQUNELENBQUM7NENBQ0QsU0FBUzt3Q0FDWCxDQUFDO3dDQUNELE1BQU0sVUFBVSxHQUNkLE1BQU0sMkJBQTJCLENBQy9CLG1CQUFtQixFQUNuQixlQUFlLENBQ2hCLENBQUM7d0NBQ0osSUFBSSxVQUFVLENBQUMsU0FBUzs0Q0FBRSxPQUFPLFVBQVUsQ0FBQyxNQUFNLENBQUM7d0NBQ25ELGlEQUFpRDt3Q0FDakQsMkNBQTJDO3dDQUMzQyxNQUFNLFVBQVUsQ0FBQyxLQUFLLENBQUM7b0NBQ3pCLENBQUM7b0NBQ0QsSUFBSSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsZUFBZSxDQUFDLEVBQUUsQ0FBQzt3Q0FDcEMsNENBQTRDO3dDQUM1Qyx5Q0FBeUM7d0NBQ3pDLE1BQU0sZUFBZSxDQUFDO29DQUN4QixDQUFDO29DQUNELDZDQUE2QztvQ0FDN0MsZ0RBQWdEO29DQUNoRCxnREFBZ0Q7b0NBQ2hELCtDQUErQztvQ0FDL0MsZ0RBQWdEO29DQUNoRCxpREFBaUQ7b0NBQ2pELDRDQUE0QztvQ0FDNUMseUJBQXlCO29DQUN6QixNQUFNLFNBQVMsR0FBRyxnQkFBZ0IsQ0FBQyxlQUFlLENBQUMsQ0FBQztvQ0FDcEQsYUFBYSxDQUFDLEtBQUssQ0FDakIsdUVBQXVFLEVBQ3ZFO3dDQUNFLGFBQWEsRUFBRSxLQUFLO3dDQUNwQixTQUFTO3dDQUNULFNBQVMsRUFBRSxlQUFlLENBQUMsSUFBSTt3Q0FDL0IsWUFBWSxFQUFFLGVBQWUsQ0FBQyxPQUFPO3FDQUN0QyxDQUNGLENBQUM7b0NBQ0YsSUFBSSxDQUFDO3dDQUNILDRDQUE0Qzt3Q0FDNUMsOENBQThDO3dDQUM5QyxNQUFNLGFBQWEsRUFBRSxDQUFDO3dDQUN0QixNQUFNLFdBQVcsQ0FDZjs0Q0FDRSxTQUFTLEVBQUUsWUFBWTs0Q0FDdkIsV0FBVyxFQUFFLG9CQUFvQjs0Q0FDakMsU0FBUyxFQUFFO2dEQUNULEtBQUssRUFBRSxNQUFNLGlCQUFpQixDQUM1QixlQUFlLEVBQ2YsS0FBSyxFQUNMLGFBQWEsRUFDYixVQUFVLEVBQ1YsQ0FBQyxXQUFXLEVBQUUsV0FBVyxJQUFJLENBQUMsQ0FBQztvREFDN0IsaUNBQWlDLENBQ3BDO2dEQUNELFNBQVM7NkNBQ1Y7eUNBQ0YsRUFDRCxFQUFFLFNBQVMsRUFBRSxDQUNkLENBQUM7b0NBQ0osQ0FBQztvQ0FBQyxPQUFPLE9BQU8sRUFBRSxDQUFDO3dDQUNqQixJQUNFLG1CQUFtQixDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUM7NENBQy9CLGVBQWUsQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLEVBQzNCLENBQUM7NENBQ0QsYUFBYSxDQUFDLElBQUksQ0FDaEIsMkRBQTJELEVBQzNEO2dEQUNFLGFBQWEsRUFBRSxLQUFLO2dEQUNwQixPQUFPLEVBQUUsT0FBTyxDQUFDLE9BQU87NkNBQ3pCLENBQ0YsQ0FBQzs0Q0FDRixPQUFPO3dDQUNULENBQUM7d0NBQ0QsTUFBTSxPQUFPLENBQUM7b0NBQ2hCLENBQUM7b0NBQ0QsSUFBSSxFQUFFLGFBQWEsQ0FBQzt3Q0FDbEIsR0FBRyxTQUFTLENBQUMsaUJBQWlCLENBQUMsUUFBUSxDQUFDO3dDQUN4QyxHQUFHLFNBQVMsQ0FBQyxpQkFBaUIsQ0FBQyxTQUFTLENBQUM7d0NBQ3pDLEdBQUcsU0FBUyxDQUFDLGlCQUFpQixDQUM1QixlQUFlLENBQUMsSUFBSSxDQUNyQjt3Q0FDRCxHQUFHLFNBQVMsQ0FBQyxvQkFBb0IsQ0FDL0IsZUFBZSxDQUFDLE9BQU8sQ0FDeEI7d0NBQ0QsR0FBRyxTQUFTLENBQUMsU0FBUyxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUM7cUNBQzdDLENBQUMsQ0FBQztvQ0FDSCxPQUFPO2dDQUNULENBQUM7Z0NBQ0QsSUFBSSxnQkFBZ0IsQ0FBQyxrQkFBa0IsR0FBRyxDQUFDLEVBQUUsQ0FBQztvQ0FDNUMsbURBQW1EO29DQUNuRCxvREFBb0Q7b0NBQ3BELGtEQUFrRDtvQ0FDbEQsb0RBQW9EO29DQUNwRCxvREFBb0Q7b0NBQ3BELHNEQUFzRDtvQ0FDdEQsa0JBQWtCLENBQUMsU0FBUyxFQUFFLENBQUM7Z0NBQ2pDLENBQUM7Z0NBRUQsaURBQWlEO2dDQUNqRCxxREFBcUQ7Z0NBQ3JELGlEQUFpRDtnQ0FDakQsa0RBQWtEO2dDQUNsRCxxREFBcUQ7Z0NBQ3JELGtDQUFrQztnQ0FDbEMsK0NBQStDO2dDQUMvQyxvREFBb0Q7Z0NBQ3BELGtEQUFrRDtnQ0FDbEQsK0NBQStDO2dDQUMvQyw4Q0FBOEM7Z0NBQzlDLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUU7b0NBQzdCLE1BQU0sQ0FBQyxRQUFRLENBQUMsSUFBSSxLQUFLLE9BQU8sQ0FBQyxDQUFDO29DQUNsQyxPQUFPLG9CQUFvQixDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQztnQ0FDL0MsQ0FBQyxDQUFDLENBQUM7Z0NBRUgsaURBQWlEO2dDQUNqRCxtREFBbUQ7Z0NBQ25ELCtDQUErQztnQ0FDL0MsdUJBQXVCO2dDQUN2QixJQUNFLGVBQWU7b0NBQ2YsQ0FBQyx3QkFBd0IsQ0FDdkIsR0FBRyxFQUNILGdCQUFnQixDQUFDLHNCQUFzQixFQUN2QyxZQUFZLENBQ2IsRUFDRCxDQUFDO29DQUNELGVBQWUsR0FBRyxJQUFJLENBQUM7Z0NBQ3pCLENBQUM7Z0NBQ0QsaUJBQWlCLElBQUksZ0JBQWdCLENBQUMsY0FBYyxDQUFDO2dDQUNyRCxJQUNFLGdCQUFnQixDQUFDLGtCQUFrQjtvQ0FDbkMsMkJBQTJCLEtBQUssU0FBUyxFQUN6QyxDQUFDO29DQUNELDJCQUEyQixHQUFHLGlCQUFpQixDQUFDO2dDQUNsRCxDQUFDO2dDQUNELGFBQWEsQ0FBQyxLQUFLLENBQUMsb0JBQW9CLEVBQUU7b0NBQ3hDLGFBQWEsRUFBRSxLQUFLO29DQUNwQixZQUFZLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLGVBQWU7b0NBQzFDLFlBQVksRUFBRSxnQkFBZ0IsQ0FBQyxZQUFZLENBQUMsTUFBTTtvQ0FDbEQsY0FBYyxFQUFFLGdCQUFnQixDQUFDLFdBQVcsRUFBRSxPQUFPO29DQUNyRCxlQUFlLEVBQUUsZ0JBQWdCLENBQUMsZUFBZTtvQ0FDakQsc0JBQXNCLEVBQ3BCLGdCQUFnQixDQUFDLHNCQUFzQjtvQ0FDekMsa0JBQWtCLEVBQ2hCLGdCQUFnQixDQUFDLGtCQUFrQjtpQ0FDdEMsQ0FBQyxDQUFDO2dDQUVILGlEQUFpRDtnQ0FDakQsSUFBSSxnQkFBZ0IsQ0FBQyxlQUFlLEVBQUUsQ0FBQztvQ0FDckMsT0FBTyxNQUFNLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQ0FDM0IsQ0FBQztnQ0FFRCxnREFBZ0Q7Z0NBQ2hELHNEQUFzRDtnQ0FDdEQsb0RBQW9EO2dDQUNwRCxxREFBcUQ7Z0NBQ3JELHVEQUF1RDtnQ0FDdkQsa0RBQWtEO2dDQUNsRCxxREFBcUQ7Z0NBQ3JELHVEQUF1RDtnQ0FDdkQsNkNBQTZDO2dDQUM3QyxxREFBcUQ7Z0NBQ3JELHVEQUF1RDtnQ0FDdkQsa0RBQWtEO2dDQUNsRCxtREFBbUQ7Z0NBQ25ELDJDQUEyQztnQ0FDM0MsSUFBSSxnQkFBZ0IsQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO29DQUN4QyxRQUFRLEdBQUcsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLENBQUM7b0NBQ3RDLFNBQVM7Z0NBQ1gsQ0FBQztnQ0FFRCxNQUFNLFlBQVksR0FBRyxnQkFBZ0IsQ0FBQyxZQUFZLENBQUM7Z0NBRW5ELDhDQUE4QztnQ0FDOUMseURBQXlEO2dDQUN6RCx3REFBd0Q7Z0NBQ3hELHFEQUFxRDtnQ0FDckQsMERBQTBEO2dDQUMxRCx5REFBeUQ7Z0NBQ3pELHdEQUF3RDtnQ0FDeEQsZ0RBQWdEO2dDQUNoRCx5REFBeUQ7Z0NBQ3pELDBEQUEwRDtnQ0FDMUQsaURBQWlEO2dDQUNqRCx1REFBdUQ7Z0NBQ3ZELGdCQUFnQjtnQ0FDaEIsRUFBRTtnQ0FDRix5Q0FBeUM7Z0NBQ3pDLHlEQUF5RDtnQ0FDekQscURBQXFEO2dDQUNyRCx5REFBeUQ7Z0NBQ3pELHVEQUF1RDtnQ0FDdkQsd0RBQXdEO2dDQUN4RCx1REFBdUQ7Z0NBQ3ZELDJDQUEyQztnQ0FDM0MseURBQXlEO2dDQUN6RCx5REFBeUQ7Z0NBQ3pELHdEQUF3RDtnQ0FDeEQsd0RBQXdEO2dDQUN4RCwwREFBMEQ7Z0NBQzFELE1BQU0sZUFBZSxHQUNuQixnQkFBZ0IsQ0FBQyxlQUFlLENBQUM7Z0NBQ25DLE1BQU0sb0JBQW9CLEdBQUcsSUFBSSxHQUFHLENBQ2xDLGVBQWUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsQ0FDNUMsQ0FBQztnQ0FFRixtREFBbUQ7Z0NBQ25ELG9EQUFvRDtnQ0FDcEQsbURBQW1EO2dDQUNuRCxpREFBaUQ7Z0NBQ2pELG9EQUFvRDtnQ0FDcEQsZ0RBQWdEO2dDQUNoRCxRQUFRO2dDQUNSLEVBQUU7Z0NBQ0YscURBQXFEO2dDQUNyRCwyQkFBMkI7Z0NBQzNCLEVBQUU7Z0NBQ0YsOENBQThDO2dDQUM5QyxvREFBb0Q7Z0NBQ3BELG1EQUFtRDtnQ0FDbkQsaURBQWlEO2dDQUNqRCx1Q0FBdUM7Z0NBQ3ZDLDBDQUEwQztnQ0FDMUMsOENBQThDO2dDQUM5Qyw0Q0FBNEM7Z0NBQzVDLGlEQUFpRDtnQ0FDakQsaURBQWlEO2dDQUNqRCxxREFBcUQ7Z0NBQ3JELHFEQUFxRDtnQ0FDckQsZ0RBQWdEO2dDQUNoRCxtREFBbUQ7Z0NBQ25ELGdEQUFnRDtnQ0FDaEQsOENBQThDO2dDQUM5Qyw0Q0FBNEM7Z0NBQzVDLHFEQUFxRDtnQ0FDckQsbURBQW1EO2dDQUNuRCxvREFBb0Q7Z0NBQ3BELGtEQUFrRDtnQ0FDbEQsNkNBQTZDO2dDQUM3Qyx5Q0FBeUM7Z0NBQ3pDLGdEQUFnRDtnQ0FDaEQsaURBQWlEO2dDQUNqRCxpREFBaUQ7Z0NBQ2pELHVDQUF1QztnQ0FDdkMsaURBQWlEO2dDQUNqRCxrREFBa0Q7Z0NBQ2xELG1EQUFtRDtnQ0FDbkQsc0NBQXNDO2dDQUN0QyxtREFBbUQ7Z0NBQ25ELGdEQUFnRDtnQ0FDaEQscURBQXFEO2dDQUNyRCxxREFBcUQ7Z0NBQ3JELG9EQUFvRDtnQ0FDcEQsMkNBQTJDO2dDQUMzQyw4Q0FBOEM7Z0NBQzlDLG1EQUFtRDtnQ0FDbkQsRUFBRTtnQ0FDRixzQ0FBc0M7Z0NBQ3RDLG9EQUFvRDtnQ0FDcEQsaURBQWlEO2dDQUNqRCxrREFBa0Q7Z0NBQ2xELDhDQUE4QztnQ0FDOUMsK0NBQStDO2dDQUMvQyxrREFBa0Q7Z0NBQ2xELGtEQUFrRDtnQ0FDbEQsb0JBQW9CO2dDQUNwQixFQUFFO2dDQUNGLDZDQUE2QztnQ0FDN0MsK0NBQStDO2dDQUMvQyxpREFBaUQ7Z0NBQ2pELGtEQUFrRDtnQ0FDbEQsMEJBQTBCO2dDQUMxQiw0Q0FBNEM7Z0NBQzVDLGlDQUFpQztnQ0FDakMsTUFBTSxZQUFZLEdBQUcsTUFBTSxnQkFBZ0IsRUFBRSxDQUFDO2dDQUM5QyxNQUFNLFVBQVUsR0FBdUIsRUFBRSxDQUFDO2dDQUMxQyxNQUFNLGVBQWUsR0FBRyx3QkFBd0IsRUFBRSxDQUFDO2dDQUNuRCxNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7Z0NBQ2pDLE1BQU0sa0JBQWtCLEdBQ3RCLEVBQUUsQ0FBQztnQ0FDTCxJQUFJLGtCQUFrQixHQUFHLENBQUMsQ0FBQztnQ0FDM0IsS0FBSyxNQUFNLElBQUksSUFBSSxZQUFZLEVBQUUsQ0FBQztvQ0FDaEMsSUFBSSxvQkFBb0IsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxFQUFFLENBQUM7d0NBQ2pELFNBQVM7b0NBQ1gsQ0FBQztvQ0FDRCxNQUFNLGVBQWUsR0FDbkIsZUFBZSxJQUFJLHFCQUFxQixDQUFDLElBQUksQ0FBQyxDQUFDO29DQUNqRCxJQUNFLGVBQWU7d0NBQ2YsSUFBSSxDQUFDLGNBQWMsS0FBSyxRQUFRLENBQUMsU0FBUyxFQUMxQyxDQUFDO3dDQUNELDhDQUE4Qzt3Q0FDOUMsdUNBQXVDO3dDQUN2QyxxQ0FBcUM7d0NBQ3JDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQzt3Q0FDOUIsU0FBUztvQ0FDWCxDQUFDO29DQUNELG1EQUFtRDtvQ0FDbkQsa0RBQWtEO29DQUNsRCxtREFBbUQ7b0NBQ25ELDZDQUE2QztvQ0FDN0MsK0NBQStDO29DQUMvQyxvQ0FBb0M7b0NBQ3BDLE1BQU0sb0JBQW9CLEdBQUcsZUFBZTt3Q0FDMUMsQ0FBQyxDQUFDLHlCQUF5QixDQUFDLElBQUksRUFBRSxhQUFhLENBQUM7d0NBQ2hELENBQUMsQ0FBQyxDQUFDLENBQUM7b0NBQ04sSUFBSSxvQkFBb0IsR0FBRyxDQUFDLEVBQUUsQ0FBQzt3Q0FDN0Isa0JBQWtCLEVBQUUsQ0FBQzt3Q0FDckIsYUFBYSxDQUFDLEtBQUssQ0FDakIsZ0hBQWdILEVBQ2hIOzRDQUNFLGFBQWEsRUFBRSxLQUFLOzRDQUNwQixNQUFNLEVBQUUsSUFBSSxDQUFDLGFBQWE7NENBQzFCLGNBQWMsRUFBRSxJQUFJLENBQUMsY0FBYzs0Q0FDbkMsb0JBQW9CO3lDQUNyQixDQUNGLENBQUM7d0NBQ0YsVUFBVSxDQUFDLElBQUksQ0FDYixZQUFZLENBQ1YsS0FBSyxFQUNMLG9CQUFvQixDQUFDLFlBQVksRUFBRSxTQUFTLENBQUMsRUFDN0M7NENBQ0UsS0FBSzs0Q0FDTCxZQUFZOzRDQUNaLFdBQVcsRUFBRSxJQUFJLElBQUksRUFBRTt5Q0FDeEIsRUFDRDs0Q0FDRSxZQUFZLEVBQUUsb0JBQW9COzRDQUNsQyxjQUFjLEVBQUUsc0JBQXNCLENBQUMsSUFBSSxDQUFDO3lDQUM3QyxDQUNGLENBQ0YsQ0FBQzt3Q0FDRixTQUFTO29DQUNYLENBQUM7b0NBQ0QsVUFBVSxDQUFDLElBQUksQ0FDYixZQUFZLENBQ1YsS0FBSyxFQUNMLG9CQUFvQixDQUFDLFlBQVksRUFBRSxTQUFTLENBQUMsRUFDN0M7d0NBQ0UsS0FBSzt3Q0FDTCxNQUFNLEVBQUUsSUFBSSxDQUFDLGFBQWE7d0NBQzFCLFFBQVEsRUFBRSxJQUFJLENBQUMsUUFBUTt3Q0FDdkIsWUFBWTt3Q0FDWixXQUFXLEVBQUUsSUFBSSxJQUFJLEVBQUU7cUNBQ3hCLEVBQ0Q7d0NBQ0UsY0FBYyxFQUFFLElBQUksQ0FBQyxhQUFhO3FDQUNuQyxDQUNGLENBQ0YsQ0FBQztnQ0FDSixDQUFDO2dDQUNELElBQUksZ0JBQWdCLENBQUMsV0FBVyxFQUFFLENBQUM7b0NBQ2pDLFVBQVUsQ0FBQyxJQUFJLENBQ2IsWUFBWSxDQUNWLEtBQUssRUFDTCxvQkFBb0IsQ0FBQyxZQUFZLEVBQUUsU0FBUyxDQUFDLEVBQzdDO3dDQUNFLEtBQUs7d0NBQ0wsWUFBWTt3Q0FDWixXQUFXLEVBQUUsSUFBSSxJQUFJLEVBQUU7cUNBQ3hCLEVBQ0QsMkJBQTJCLENBQ3pCLGdCQUFnQixDQUFDLFdBQVcsQ0FBQyxPQUFPLEVBQ3BDLGdCQUFnQixDQUFDLFdBQVcsQ0FBQyxhQUFhLENBQzNDLENBQ0YsQ0FDRixDQUFDO2dDQUNKLENBQUM7Z0NBQ0QsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDO2dDQUU5QixpREFBaUQ7Z0NBQ2pELHFEQUFxRDtnQ0FDckQsa0RBQWtEO2dDQUNsRCxtREFBbUQ7Z0NBQ25ELG9EQUFvRDtnQ0FDcEQsb0RBQW9EO2dDQUNwRCxvREFBb0Q7Z0NBQ3BELHlDQUF5QztnQ0FDekMseUNBQXlDO2dDQUN6Qyx3Q0FBd0M7Z0NBQ3hDLE1BQU0sZ0JBQWdCLEdBSWpCO29DQUNILEdBQUcsZUFBZSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQzt3Q0FDN0IsYUFBYSxFQUFFLENBQUMsQ0FBQyxhQUFhO3dDQUM5QixRQUFRLEVBQUUsQ0FBQyxDQUFDLFFBQVE7d0NBQ3BCLGFBQWEsRUFBRSxDQUFDLENBQUMsZUFBZTtxQ0FDakMsQ0FBQyxDQUFDO29DQUNILEdBQUcsa0JBQWtCLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO3dDQUNoQyxhQUFhLEVBQUUsQ0FBQyxDQUFDLGFBQWE7d0NBQzlCLFFBQVEsRUFBRSxDQUFDLENBQUMsUUFBUTtxQ0FDckIsQ0FBQyxDQUFDO2lDQUNKLENBQUM7Z0NBQ0YsaURBQWlEO2dDQUNqRCxrREFBa0Q7Z0NBQ2xELDhDQUE4QztnQ0FDOUMsK0NBQStDO2dDQUMvQyxvREFBb0Q7Z0NBQ3BELCtDQUErQztnQ0FDL0MsSUFDRSxrQkFBa0IsR0FBRyxDQUFDO29DQUN0QixrQkFBa0IsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUM3QixDQUFDO29DQUNELElBQUksRUFBRSxhQUFhLENBQUM7d0NBQ2xCLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLEdBQUcsQ0FBQzs0Q0FDL0IsQ0FBQyxDQUFDLFNBQVMsQ0FBQywwQkFBMEIsQ0FDbEMsa0JBQWtCLENBQUMsTUFBTSxDQUMxQjs0Q0FDSCxDQUFDLENBQUMsRUFBRSxDQUFDO3dDQUNQLEdBQUcsQ0FBQyxrQkFBa0IsR0FBRyxDQUFDOzRDQUN4QixDQUFDLENBQUMsU0FBUyxDQUFDLDBCQUEwQixDQUNsQyxrQkFBa0IsQ0FDbkI7NENBQ0gsQ0FBQyxDQUFDLEVBQUUsQ0FBQztxQ0FDUixDQUFDLENBQUM7Z0NBQ0wsQ0FBQztnQ0FDRCxJQUFJLGtCQUFrQixDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztvQ0FDbEMsYUFBYSxDQUFDLElBQUksQ0FDaEIscUlBQXFJLEVBQ3JJO3dDQUNFLGFBQWEsRUFBRSxLQUFLO3dDQUNwQixPQUFPLEVBQUUsa0JBQWtCLENBQUMsR0FBRyxDQUM3QixDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FDdkI7cUNBQ0YsQ0FDRixDQUFDO2dDQUNKLENBQUM7Z0NBRUQsa0RBQWtEO2dDQUNsRCxxREFBcUQ7Z0NBQ3JELHNDQUFzQztnQ0FDdEMsSUFBSSxnQkFBZ0IsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7b0NBQ2xDLG9EQUFvRDtvQ0FDcEQseUNBQXlDO29DQUN6QywrQ0FBK0M7b0NBQy9DLGdEQUFnRDtvQ0FDaEQsaURBQWlEO29DQUNqRCx3Q0FBd0M7b0NBQ3hDLElBQUksZ0JBQWdCLENBQUMsc0JBQXNCLEVBQUUsQ0FBQzt3Q0FDNUMsT0FBTyxNQUFNLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztvQ0FDM0IsQ0FBQztvQ0FDRCxPQUFPO2dDQUNULENBQUM7Z0NBRUQsb0RBQW9EO2dDQUNwRCw4Q0FBOEM7Z0NBQzlDLE1BQU0saUJBQWlCLEdBQUcsWUFBWSxDQUFDLEtBQUssQ0FBQztnQ0FFN0Msc0RBQXNEO2dDQUN0RCx1REFBdUQ7Z0NBQ3ZELG9DQUFvQztnQ0FDcEMsRUFBRTtnQ0FDRixvREFBb0Q7Z0NBQ3BELGlEQUFpRDtnQ0FDakQsb0RBQW9EO2dDQUNwRCxzREFBc0Q7Z0NBQ3RELHNEQUFzRDtnQ0FDdEQseURBQXlEO2dDQUN6RCw4QkFBOEI7Z0NBQzlCLG1EQUFtRDtnQ0FDbkQsMERBQTBEO2dDQUMxRCxzREFBc0Q7Z0NBQ3RELHdEQUF3RDtnQ0FDeEQsbURBQW1EO2dDQUNuRCx1REFBdUQ7Z0NBQ3ZELHdEQUF3RDtnQ0FDeEQsMkNBQTJDO2dDQUMzQyx3REFBd0Q7Z0NBQ3hELHFEQUFxRDtnQ0FDckQsNkNBQTZDO2dDQUM3QyxxREFBcUQ7Z0NBQ3JELHdEQUF3RDtnQ0FDeEQsc0RBQXNEO2dDQUN0RCxtREFBbUQ7Z0NBQ25ELHFEQUFxRDtnQ0FDckQsd0RBQXdEO2dDQUN4RCwrQ0FBK0M7Z0NBQy9DLHFEQUFxRDtnQ0FDckQsa0RBQWtEO2dDQUNsRCx1REFBdUQ7Z0NBQ3ZELHNEQUFzRDtnQ0FDdEQsa0RBQWtEO2dDQUNsRCx1REFBdUQ7Z0NBQ3ZELHNEQUFzRDtnQ0FDdEQsZ0RBQWdEO2dDQUNoRCx3REFBd0Q7Z0NBQ3hELHVEQUF1RDtnQ0FDdkQsdURBQXVEO2dDQUN2RCxzREFBc0Q7Z0NBQ3RELHNDQUFzQztnQ0FDdEMsaURBQWlEO2dDQUNqRCx1REFBdUQ7Z0NBQ3ZELHdEQUF3RDtnQ0FDeEQsb0RBQW9EO2dDQUNwRCxtREFBbUQ7Z0NBQ25ELHFEQUFxRDtnQ0FDckQsdURBQXVEO2dDQUN2RCxtREFBbUQ7Z0NBQ25ELHdCQUF3QjtnQ0FDeEIsZ0RBQWdEO2dDQUNoRCx1REFBdUQ7Z0NBQ3ZELHdDQUF3QztnQ0FDeEMsMkJBQTJCO2dDQUMzQixFQUFFO2dDQUNGLHVEQUF1RDtnQ0FDdkQsMERBQTBEO2dDQUMxRCwwREFBMEQ7Z0NBQzFELDBEQUEwRDtnQ0FDMUQsdURBQXVEO2dDQUN2RCxvREFBb0Q7Z0NBQ3BELG9EQUFvRDtnQ0FDcEQsb0RBQW9EO2dDQUNwRCxNQUFNLGFBQWEsR0FDakIsMEJBQTBCLEVBQUU7b0NBQzVCLEtBQUssQ0FBQyxZQUFZLEVBQUUsaUJBQWlCLEtBQUssSUFBSSxDQUFDO2dDQUVqRCxNQUFNLGtCQUFrQixHQUN0QixPQUFPLFFBQVEsQ0FBQyxNQUFNLEtBQUssUUFBUTtvQ0FDbkMsR0FBRyxDQUFDLFNBQVMsS0FBSyxDQUFDO29DQUNuQixHQUFHLENBQUMsU0FBUyxLQUFLLENBQUM7b0NBQ25CLFlBQVksQ0FBQyxNQUFNLEtBQUssQ0FBQztvQ0FDekIsZUFBZSxDQUFDLE1BQU0sS0FBSyxDQUFDO29DQUM1QixrQkFBa0IsQ0FBQyxNQUFNLEtBQUssQ0FBQztvQ0FDL0IsQ0FBQyxnQkFBZ0IsQ0FBQyxXQUFXO29DQUM3QixDQUFDLGlCQUFpQixDQUFDLFFBQVE7b0NBQzNCLENBQUMsYUFBYTt3Q0FDWixDQUFDLEdBQUcsQ0FBQyxTQUFTLEtBQUssQ0FBQzs0Q0FDbEIsQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO2dDQUVwQyx1REFBdUQ7Z0NBQ3ZELHVEQUF1RDtnQ0FDdkQsdURBQXVEO2dDQUN2RCxxREFBcUQ7Z0NBQ3JELGdEQUFnRDtnQ0FDaEQsdURBQXVEO2dDQUN2RCxvREFBb0Q7Z0NBQ3BELHVEQUF1RDtnQ0FDdkQsbURBQW1EO2dDQUNuRCxtREFBbUQ7Z0NBQ25ELGtEQUFrRDtnQ0FDbEQsdURBQXVEO2dDQUN2RCxvREFBb0Q7Z0NBQ3BELG1EQUFtRDtnQ0FDbkQsZ0RBQWdEO2dDQUNoRCx1REFBdUQ7Z0NBQ3ZELE1BQU0sdUJBQXVCLEdBQzNCLGFBQWE7b0NBQ2IsQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRO3dDQUN6QixHQUFHLENBQUMsU0FBUyxHQUFHLENBQUM7d0NBQ2pCLGdCQUFnQixDQUFDLGFBQWEsQ0FBQyxDQUFDO2dDQUVwQyxxREFBcUQ7Z0NBQ3JELDBEQUEwRDtnQ0FDMUQsaURBQWlEO2dDQUNqRCxvREFBb0Q7Z0NBQ3BELHVEQUF1RDtnQ0FDdkQsdURBQXVEO2dDQUN2RCxrREFBa0Q7Z0NBQ2xELHNEQUFzRDtnQ0FDdEQsdURBQXVEO2dDQUN2RCx1REFBdUQ7Z0NBQ3ZELGtEQUFrRDtnQ0FDbEQsZ0RBQWdEO2dDQUNoRCxhQUFhO2dDQUNiLEVBQUU7Z0NBQ0Ysd0RBQXdEO2dDQUN4RCx5REFBeUQ7Z0NBQ3pELHVEQUF1RDtnQ0FDdkQsMkRBQTJEO2dDQUMzRCwyREFBMkQ7Z0NBQzNELDBEQUEwRDtnQ0FDMUQsMkRBQTJEO2dDQUMzRCxtREFBbUQ7Z0NBQ25ELHdEQUF3RDtnQ0FDeEQsaUNBQWlDO2dDQUNqQyxFQUFFO2dDQUNGLHNEQUFzRDtnQ0FDdEQscURBQXFEO2dDQUNyRCx1REFBdUQ7Z0NBQ3ZELHVEQUF1RDtnQ0FDdkQsc0RBQXNEO2dDQUN0RCx1REFBdUQ7Z0NBQ3ZELHVEQUF1RDtnQ0FDdkQsb0RBQW9EO2dDQUNwRCxxREFBcUQ7Z0NBQ3JELGtEQUFrRDtnQ0FDbEQsc0RBQXNEO2dDQUN0RCxxREFBcUQ7Z0NBQ3JELG1EQUFtRDtnQ0FDbkQsZUFBZTtnQ0FDZixNQUFNLG9CQUFvQixHQUN4QixLQUFLO29DQUNMLENBQUMsZ0JBQWdCLENBQUMsa0JBQWtCO29DQUNwQyxDQUFDLGdCQUFnQixDQUFDLFdBQVc7b0NBQzdCLENBQUMsZ0JBQWdCLENBQUMsYUFBYTtvQ0FDL0IsQ0FBQyxnQkFBZ0IsQ0FBQyxzQkFBc0I7b0NBQ3hDLENBQUMsaUJBQWlCLENBQUMsUUFBUTtvQ0FDM0IsQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRLENBQUM7Z0NBRTlCLG1EQUFtRDtnQ0FDbkQsMERBQTBEO2dDQUMxRCwwREFBMEQ7Z0NBQzFELHlEQUF5RDtnQ0FDekQsc0RBQXNEO2dDQUN0RCx1REFBdUQ7Z0NBQ3ZELHFEQUFxRDtnQ0FDckQsK0NBQStDO2dDQUMvQyxzREFBc0Q7Z0NBQ3RELCtDQUErQztnQ0FDL0MsaURBQWlEO2dDQUNqRCxtREFBbUQ7Z0NBQ25ELE1BQU0sZUFBZSxHQUFHLDBCQUEwQixDQUFDO29DQUNqRCxNQUFNLEVBQUUsUUFBUSxDQUFDLE1BQU07b0NBQ3ZCLHNCQUFzQixFQUNwQixzQkFBc0IsS0FBSyxJQUFJO29DQUNqQyxjQUFjLEVBQ1osY0FBYyxDQUFDLEtBQUssQ0FBQzt3Q0FDckIsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsU0FBUyxDQUFDO29DQUM5QyxzQkFBc0I7b0NBQ3RCLFFBQVEsRUFBRSxnQkFBZ0I7b0NBQzFCLGlCQUFpQjtvQ0FDakIsMkJBQTJCO29DQUMzQixvREFBb0Q7b0NBQ3BELHVEQUF1RDtvQ0FDdkQsa0JBQWtCLEVBQ2hCLEdBQUcsQ0FBQyxTQUFTLEdBQUcsQ0FBQzt3Q0FDakIsZ0JBQWdCLENBQUMsV0FBVyxLQUFLLFNBQVM7b0NBQzVDLHNCQUFzQixFQUNwQixHQUFHLENBQUMsU0FBUyxHQUFHLENBQUMsSUFBSSxnQkFBZ0IsQ0FBQyxhQUFhO29DQUNyRCxLQUFLO2lDQUNOLENBQUMsQ0FBQztnQ0FFSCw2Q0FBNkM7Z0NBQzdDLG1EQUFtRDtnQ0FDbkQscURBQXFEO2dDQUNyRCxzREFBc0Q7Z0NBQ3RELHNEQUFzRDtnQ0FDdEQsdURBQXVEO2dDQUN2RCw0QkFBNEI7Z0NBQzVCLHVEQUF1RDtnQ0FDdkQscURBQXFEO2dDQUNyRCxpREFBaUQ7Z0NBQ2pELCtCQUErQjtnQ0FDL0IsTUFBTSxtQkFBbUIsR0FBRywwQkFBMEIsQ0FDcEQsUUFBUSxDQUFDLE1BQU0sRUFDZixRQUFRLENBQUMsTUFBTSxDQUNoQixDQUFDO2dDQUVGLFlBQVksQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQ0FDckIsSUFBSSxXQUVELENBQUM7Z0NBQ0osTUFBTSxxQkFBcUIsR0FBRyxnQkFBZ0IsQ0FBQyxHQUFHLENBQ2hELENBQUMsQ0FBQyxFQUFFLFNBQVMsRUFBRSxFQUFFO29DQUNmLE1BQU0sR0FBRyxHQUFHLEdBQUcsRUFBRTt3Q0FDZixNQUFNLENBQUMsUUFBUSxDQUFDLElBQUksS0FBSyxPQUFPLENBQUMsQ0FBQzt3Q0FDbEMsT0FBTyxXQUFXLENBQUM7NENBQ2pCLEtBQUs7NENBQ0wsYUFBYSxFQUFFLEtBQUs7NENBQ3BCLG9CQUFvQixFQUFFLFdBQVcsQ0FBQyxZQUFZOzRDQUM5QyxZQUFZOzRDQUNaLGlCQUFpQjs0Q0FDakIsU0FBUyxFQUFFLGFBQWEsQ0FDdEIsV0FBVyxDQUFDLFVBQVUsRUFDdEIsS0FBSyxDQUNOOzRDQUNELE1BQU0sRUFBRSxDQUFDLENBQUMsYUFBYTs0Q0FDdkIsUUFBUSxFQUFFLENBQUMsQ0FBQyxRQUFROzRDQUNwQixjQUFjLEVBQUUsV0FBVyxDQUFDLFdBQVc7NENBQ3ZDLGdEQUFnRDs0Q0FDaEQsK0NBQStDOzRDQUMvQywyQ0FBMkM7NENBQzNDLDRDQUE0Qzs0Q0FDNUMsOENBQThDOzRDQUM5QywwQ0FBMEM7NENBQzFDLCtDQUErQzs0Q0FDL0MsMENBQTBDOzRDQUMxQyw4Q0FBOEM7NENBQzlDLDJDQUEyQzs0Q0FDM0MsMkNBQTJDOzRDQUMzQyw2Q0FBNkM7NENBQzdDLCtDQUErQzs0Q0FDL0MsdUNBQXVDOzRDQUN2QywwQ0FBMEM7NENBQzFDLDRDQUE0Qzs0Q0FDNUMsNENBQTRDOzRDQUM1Qyw4Q0FBOEM7NENBQzlDLCtDQUErQzs0Q0FDL0MsMENBQTBDOzRDQUMxQywwQ0FBMEM7NENBQzFDLHNDQUFzQzs0Q0FDdEMsb0JBQW9CLEVBQ2xCLENBQUMsQ0FBQyxhQUFhLEtBQUssU0FBUztnREFDM0IsQ0FBQyxDQUFDLENBQUM7Z0RBQ0gsQ0FBQyxDQUFDLHNCQUFzQixDQUNwQixRQUFRLENBQUMsTUFBTSxFQUNmLENBQUMsQ0FBQyxhQUFhLEVBQ2Y7b0RBQ0UsSUFBSSxFQUFFLFNBQVM7b0RBQ2YsU0FBUyxFQUFFLFFBQVEsQ0FBQyxTQUFTO2lEQUM5QixDQUNGLEdBQUcsQ0FBQzs0Q0FDWCw4Q0FBOEM7NENBQzlDLDZDQUE2Qzs0Q0FDN0Msa0NBQWtDOzRDQUNsQyw2Q0FBNkM7NENBQzdDLGlDQUFpQzs0Q0FDakMsYUFBYSxFQUFFLENBQUMsQ0FBQyxhQUFhOzRDQUM5Qiw2Q0FBNkM7NENBQzdDLHVDQUF1Qzs0Q0FDdkMsNkNBQTZDOzRDQUM3QyxxQ0FBcUM7NENBQ3JDLHFDQUFxQzs0Q0FDckMsY0FBYyxFQUFFLFFBQVEsQ0FBQyxTQUFTOzRDQUNsQyw2Q0FBNkM7NENBQzdDLDJDQUEyQzs0Q0FDM0MseUNBQXlDOzRDQUN6Qyx5Q0FBeUM7NENBQ3pDLGlCQUFpQjs0Q0FDakIsb0JBQW9COzRDQUNwQiwyQ0FBMkM7NENBQzNDLDhDQUE4Qzs0Q0FDOUMsK0NBQStDOzRDQUMvQyxxQ0FBcUM7NENBQ3JDLHVCQUF1Qjs0Q0FDdkIsZUFBZTs0Q0FDZixvQkFBb0IsRUFBRSxtQkFBbUI7NENBQ3pDLEdBQUcsQ0FBQyxTQUFTLEtBQUssQ0FBQztnREFDbkIsQ0FBQyxDQUFDLGFBQWEsS0FBSyxTQUFTO2dEQUM3QixlQUFlO2dEQUNiLENBQUMsQ0FBQyxFQUFFLGVBQWUsRUFBRTtnREFDckIsQ0FBQyxDQUFDLEVBQUUsQ0FBQzs0Q0FDUCxHQUFHLENBQUMsa0JBQWtCLElBQUksUUFBUSxDQUFDLE1BQU07Z0RBQ3ZDLENBQUMsQ0FBQztvREFDRSxzQkFBc0IsRUFBRSxRQUFRLENBQUMsTUFBTTtpREFDeEM7Z0RBQ0gsQ0FBQyxDQUFDLEVBQUUsQ0FBQzs0Q0FDUCxzQkFBc0I7eUNBQ3ZCLENBQUMsQ0FBQztvQ0FDTCxDQUFDLENBQUM7b0NBQ0YsOENBQThDO29DQUM5Qyx1Q0FBdUM7b0NBQ3ZDLDhCQUE4QjtvQ0FDOUIsa0JBQWtCLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsQ0FBQztvQ0FDeEMsK0NBQStDO29DQUMvQyxvQ0FBb0M7b0NBQ3BDLDZDQUE2QztvQ0FDN0MsNkNBQTZDO29DQUM3Qyw2Q0FBNkM7b0NBQzdDLGdDQUFnQztvQ0FDaEMsTUFBTSxRQUFRLEdBQ1osQ0FBQyxDQUFDLGFBQWEsS0FBSyxTQUFTO3dDQUMzQixDQUFDLENBQUMsbUJBQW1CLENBQ2pCLEtBQUssRUFDTCxDQUFDLENBQUMsYUFBYSxFQUNmLEdBQUcsQ0FDSjt3Q0FDSCxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUM7b0NBQ1osT0FBTyxRQUFRLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUMzQixrQkFBa0IsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxDQUMzQyxDQUFDO2dDQUNKLENBQUMsQ0FDRixDQUFDO2dDQUNGLElBQUksQ0FBQztvQ0FDSCxXQUFXLEdBQUcsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUM3QixxQkFBcUIsQ0FDdEIsQ0FBQztnQ0FDSixDQUFDO2dDQUFDLE9BQU8sT0FBTyxFQUFFLENBQUM7b0NBQ2pCLG9EQUFvRDtvQ0FDcEQsa0RBQWtEO29DQUNsRCxvREFBb0Q7b0NBQ3BELG1EQUFtRDtvQ0FDbkQsK0NBQStDO29DQUMvQyx1REFBdUQ7b0NBQ3ZELGdEQUFnRDtvQ0FDaEQsbURBQW1EO29DQUNuRCxvREFBb0Q7b0NBQ3BELGtEQUFrRDtvQ0FDbEQsSUFBSSx1QkFBdUIsQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQzt3Q0FDeEMsTUFBTSxPQUFPLEdBQUcsTUFBTSxPQUFPLENBQUMsVUFBVSxDQUN0QyxxQkFBcUIsQ0FDdEIsQ0FBQzt3Q0FDRixnREFBZ0Q7d0NBQ2hELG9EQUFvRDt3Q0FDcEQsb0RBQW9EO3dDQUNwRCxtREFBbUQ7d0NBQ25ELG9EQUFvRDt3Q0FDcEQsb0RBQW9EO3dDQUNwRCxpQkFBaUI7d0NBQ2pCLE1BQU0sWUFBWSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQy9CLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FDVixPQUFPLENBQUMsTUFBTSxLQUFLLFdBQVc7NENBQzlCLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxJQUFJLEtBQUssV0FBVztnREFDakMsT0FBTyxDQUFDLEtBQUssQ0FBQyxJQUFJLEtBQUssUUFBUTtnREFDL0IsT0FBTyxDQUFDLEtBQUssQ0FBQyxJQUFJLEtBQUssT0FBTyxDQUFDLENBQ3BDLENBQUM7d0NBQ0YsSUFDRSxzQkFBc0IsQ0FBQyxjQUFjLEVBQUUsT0FBTyxFQUFFOzRDQUM5QyxVQUFVLEVBQUUsQ0FBQyxZQUFZO3lDQUMxQixDQUFDLEVBQ0YsQ0FBQzs0Q0FDRCw4Q0FBOEM7NENBQzlDLG9DQUFvQzs0Q0FDcEMsU0FBUzt3Q0FDWCxDQUFDO3dDQUNELDhDQUE4Qzt3Q0FDOUMsMkNBQTJDO3dDQUMzQyxNQUFNLFVBQVUsR0FDZCxNQUFNLDJCQUEyQixDQUMvQixjQUFjLEVBQ2QsT0FBTyxDQUNSLENBQUM7d0NBQ0osSUFBSSxVQUFVLENBQUMsU0FBUzs0Q0FBRSxPQUFPLFVBQVUsQ0FBQyxNQUFNLENBQUM7d0NBQ25ELE1BQU0sVUFBVSxDQUFDLEtBQUssQ0FBQztvQ0FDekIsQ0FBQztvQ0FDRCxNQUFNLE9BQU8sQ0FBQztnQ0FDaEIsQ0FBQzt3Q0FBUyxDQUFDO29DQUNULFlBQVksQ0FBQyxNQUFNLEVBQUUsQ0FBQztnQ0FDeEIsQ0FBQztnQ0FFRCxvREFBb0Q7Z0NBQ3BELHNEQUFzRDtnQ0FDdEQsd0RBQXdEO2dDQUN4RCwwREFBMEQ7Z0NBQzFELHFEQUFxRDtnQ0FDckQsd0RBQXdEO2dDQUN4RCx3REFBd0Q7Z0NBQ3hELDBEQUEwRDtnQ0FDMUQsdURBQXVEO2dDQUN2RCwyREFBMkQ7Z0NBQzNELHFEQUFxRDtnQ0FDckQsc0JBQXNCO2dDQUN0QixNQUFNLE9BQU8sR0FHUCxFQUFFLENBQUM7Z0NBQ1QsSUFBSSxhQUFhLEdBQUcsS0FBSyxDQUFDO2dDQUMxQixvREFBb0Q7Z0NBQ3BELHdEQUF3RDtnQ0FDeEQseURBQXlEO2dDQUN6RCxxREFBcUQ7Z0NBQ3JELG1EQUFtRDtnQ0FDbkQsc0RBQXNEO2dDQUN0RCx1REFBdUQ7Z0NBQ3ZELHdEQUF3RDtnQ0FDeEQsMERBQTBEO2dDQUMxRCxtREFBbUQ7Z0NBQ25ELHdEQUF3RDtnQ0FDeEQsbURBQW1EO2dDQUNuRCxzREFBc0Q7Z0NBQ3RELHdEQUF3RDtnQ0FDeEQsdURBQXVEO2dDQUN2RCxxREFBcUQ7Z0NBQ3JELDBEQUEwRDtnQ0FDMUQseUNBQXlDO2dDQUN6QyxJQUFJLGVBQW1DLENBQUM7Z0NBQ3hDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxnQkFBZ0IsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztvQ0FDakQsTUFBTSxDQUFDLEdBQUcsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDO29DQUN6QixNQUFNLENBQUMsR0FBRyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsQ0FBQztvQ0FDOUIsSUFBSSxDQUFDLENBQUMsSUFBSSxLQUFLLE9BQU8sRUFBRSxDQUFDO3dDQUN2QixPQUFPLENBQUMsSUFBSSxDQUFDOzRDQUNYLElBQUksRUFBRSxDQUFDOzRDQUNQLFlBQVksRUFBRSxDQUFDLENBQUMsY0FBYzt5Q0FDL0IsQ0FBQyxDQUFDO29DQUNMLENBQUM7eUNBQU0sSUFBSSxDQUFDLENBQUMsSUFBSSxLQUFLLFdBQVcsRUFBRSxDQUFDO3dDQUNsQyxlQUFlLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FDeEIsZUFBZSxJQUFJLENBQUMsRUFDcEIsQ0FBQyxDQUFDLGNBQWMsQ0FDakIsQ0FBQztvQ0FDSixDQUFDO3lDQUFNLElBQ0wsQ0FBQyxDQUFDLElBQUksS0FBSyxXQUFXO3dDQUN0QixDQUFDLENBQUMsYUFBYSxFQUNmLENBQUM7d0NBQ0QsYUFBYSxHQUFHLElBQUksQ0FBQztvQ0FDdkIsQ0FBQztnQ0FDSCxDQUFDO2dDQUVELElBQUksZUFBZSxLQUFLLFNBQVMsRUFBRSxDQUFDO29DQUNsQyxpREFBaUQ7b0NBQ2pELHNEQUFzRDtvQ0FDdEQsa0RBQWtEO29DQUNsRCxvREFBb0Q7b0NBQ3BELHFEQUFxRDtvQ0FDckQsZ0RBQWdEO29DQUNoRCxzREFBc0Q7b0NBQ3RELHFEQUFxRDtvQ0FDckQscURBQXFEO29DQUNyRCxvREFBb0Q7b0NBQ3BELDRDQUE0QztvQ0FDNUMsK0JBQStCO29DQUMvQixFQUFFO29DQUNGLGlEQUFpRDtvQ0FDakQsaURBQWlEO29DQUNqRCxrREFBa0Q7b0NBQ2xELHNEQUFzRDtvQ0FDdEQsc0RBQXNEO29DQUN0RCx5REFBeUQ7b0NBQ3pELG1EQUFtRDtvQ0FDbkQsMEJBQTBCO29DQUMxQixPQUFPLE1BQU0sUUFBUSxDQUFDLGVBQWUsQ0FBQyxDQUFDO2dDQUN6QyxDQUFDO2dDQUVELElBQUksT0FBTyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztvQ0FDdkIsTUFBTSxpQkFBaUIsR0FBRyxNQUFNLGdCQUFnQixFQUFFLENBQUM7b0NBQ25ELE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FDZixPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLEVBQUUsRUFBRSxDQUNyQyxZQUFZLENBQ1YsS0FBSyxFQUNMLG9CQUFvQixDQUFDLFlBQVksRUFBRSxTQUFTLENBQUMsRUFDN0M7d0NBQ0UsS0FBSzt3Q0FDTCxNQUFNLEVBQUUsSUFBSSxDQUFDLGFBQWE7d0NBQzFCLFFBQVEsRUFBRSxJQUFJLENBQUMsUUFBUTt3Q0FDdkIsWUFBWSxFQUFFLGlCQUFpQjt3Q0FDL0IsV0FBVyxFQUFFLElBQUksSUFBSSxFQUFFO3FDQUN4QixFQUNEO3dDQUNFLFlBQVk7d0NBQ1osc0NBQXNDO3dDQUN0QywwQ0FBMEM7d0NBQzFDLDJDQUEyQzt3Q0FDM0MsbUNBQW1DO3dDQUNuQyx5Q0FBeUM7d0NBQ3pDLEVBQUU7d0NBQ0YsNkNBQTZDO3dDQUM3Qyw0Q0FBNEM7d0NBQzVDLHdDQUF3Qzt3Q0FDeEMsNENBQTRDO3dDQUM1Qyw2Q0FBNkM7d0NBQzdDLDZDQUE2Qzt3Q0FDN0MsNENBQTRDO3dDQUM1Qyx5Q0FBeUM7d0NBQ3pDLDZDQUE2Qzt3Q0FDN0MsNkNBQTZDO3dDQUM3QywyQ0FBMkM7d0NBQzNDLHdDQUF3Qzt3Q0FDeEMsOENBQThDO3dDQUM5Qyw4Q0FBOEM7d0NBQzlDLDJDQUEyQzt3Q0FDM0MsMkNBQTJDO3dDQUMzQyxxQ0FBcUM7d0NBQ3JDLGNBQWMsRUFBRSxJQUFJLENBQUMsYUFBYTtxQ0FDbkMsQ0FDRixDQUNGLENBQ0YsQ0FBQztnQ0FDSixDQUFDO2dDQUVELDBEQUEwRDtnQ0FDMUQsOEJBQThCO2dDQUM5QixJQUFJLGFBQWEsRUFBRSxDQUFDO29DQUNsQixhQUFhLENBQUMsS0FBSyxDQUNqQiw0Q0FBNEMsRUFDNUMsRUFBRSxhQUFhLEVBQUUsS0FBSyxFQUFFLGFBQWEsRUFBRSxDQUN4QyxDQUFDO29DQUNGLE1BQU0sWUFBWSxDQUNoQixLQUFLLEVBQ0wsb0JBQW9CLENBQUMsWUFBWSxFQUFFLFNBQVMsQ0FBQyxFQUM3Qzt3Q0FDRSxLQUFLO3dDQUNMLFlBQVksRUFBRSxNQUFNLGdCQUFnQixFQUFFO3dDQUN0QyxXQUFXLEVBQUUsSUFBSSxJQUFJLEVBQUU7cUNBQ3hCLENBQ0YsQ0FBQztvQ0FDRixPQUFPO2dDQUNULENBQUM7Z0NBRUQsSUFBSSxPQUFPLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO29DQUN2QixvREFBb0Q7b0NBQ3BELG1EQUFtRDtvQ0FDbkQscURBQXFEO29DQUNyRCx3REFBd0Q7b0NBQ3hELE9BQU87Z0NBQ1QsQ0FBQztnQ0FFRCw0Q0FBNEM7Z0NBQzVDLHdEQUF3RDtnQ0FDeEQseURBQXlEO2dDQUN6RCxFQUFFO2dDQUNGLHFEQUFxRDtnQ0FDckQscURBQXFEO2dDQUNyRCxJQUFJLGdCQUFnQixDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztvQ0FDbEMsTUFBTSxJQUFJLEdBQUcsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDO29DQUM1QixJQUFJLElBQUksQ0FBQyxJQUFJLEtBQUssV0FBVyxJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQzt3Q0FDbEQsY0FBYyxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7d0NBQzNDLFFBQVEsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLE9BQU87NENBQ2pDLENBQUMsQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUM7NENBQzVCLENBQUMsQ0FBQyxFQUFFLEdBQUcsUUFBUSxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsQ0FBQzt3Q0FDbkMsU0FBUztvQ0FDWCxDQUFDO2dDQUNILENBQUM7Z0NBQ0QsUUFBUSxHQUFHLGdCQUFnQixDQUFDLFFBQVEsQ0FBQyxDQUFDOzRCQUN4QyxDQUFDO2lDQUFNLENBQUM7Z0NBQ04sbURBQW1EO2dDQUNuRCxtREFBbUQ7Z0NBQ25ELHVEQUF1RDtnQ0FDdkQsb0RBQW9EO2dDQUNwRCwrQ0FBK0M7Z0NBQy9DLHdEQUF3RDtnQ0FDeEQsc0RBQXNEO2dDQUN0RCwrQ0FBK0M7Z0NBQy9DLG1EQUFtRDtnQ0FDbkQsdURBQXVEO2dDQUN2RCwrQ0FBK0M7Z0NBQy9DLHFEQUFxRDtnQ0FDckQsb0RBQW9EO2dDQUNwRCxrREFBa0Q7Z0NBQ2xELGtEQUFrRDtnQ0FDbEQsY0FBYztnQ0FDZCxJQUFJLGFBQWEsR0FBRyxHQUFHLENBQUM7Z0NBQ3hCLElBQUksdUJBQXVCLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7b0NBQ3BDLElBQUksc0JBQXNCLENBQUMsY0FBYyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUM7d0NBQ2hELFNBQVM7b0NBQ1gsQ0FBQztvQ0FDRCxNQUFNLFVBQVUsR0FBRyxNQUFNLDJCQUEyQixDQUNsRCxjQUFjLEVBQ2QsR0FBRyxDQUNKLENBQUM7b0NBQ0YsSUFBSSxVQUFVLENBQUMsU0FBUzt3Q0FBRSxPQUFPLFVBQVUsQ0FBQyxNQUFNLENBQUM7b0NBQ25ELHFEQUFxRDtvQ0FDckQsb0RBQW9EO29DQUNwRCxxREFBcUQ7b0NBQ3JELG9DQUFvQztvQ0FDcEMsYUFBYSxHQUFHLFVBQVUsQ0FBQyxLQUFLLENBQUM7Z0NBQ25DLENBQUM7Z0NBRUQsbURBQW1EO2dDQUNuRCxvREFBb0Q7Z0NBQ3BELHNEQUFzRDtnQ0FDdEQsdURBQXVEO2dDQUN2RCx3REFBd0Q7Z0NBQ3hELHVEQUF1RDtnQ0FDdkQsdURBQXVEO2dDQUN2RCxxREFBcUQ7Z0NBQ3JELHdEQUF3RDtnQ0FDeEQsa0RBQWtEO2dDQUNsRCxJQUFJLHFCQUFxQixDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7b0NBQy9CLFNBQVMsQ0FBQyxJQUFJLENBQ1osd0ZBQXdGLEVBQ3hGO3dDQUNFLFNBQVMsRUFDUCxHQUFHLFlBQVksS0FBSzs0Q0FDbEIsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJOzRDQUNWLENBQUMsQ0FBQyxjQUFjO3dDQUNwQixZQUFZLEVBQ1YsR0FBRyxZQUFZLEtBQUs7NENBQ2xCLENBQUMsQ0FBQyxHQUFHLENBQUMsT0FBTzs0Q0FDYixDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQzt3Q0FDakIsZUFBZSxFQUFFLFFBQVEsQ0FBQyxPQUFPO3FDQUNsQyxDQUNGLENBQUM7b0NBQ0YsTUFBTSxHQUFHLENBQUM7Z0NBQ1osQ0FBQztnQ0FFRCxJQUFJLCtCQUFtRCxDQUFDO2dDQUN4RCxJQUFJLHFCQUFxQixDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO29DQUNsQyxNQUFNLGVBQWUsR0FDbkIsQ0FBQyxnQkFBZ0IsRUFBRSxLQUFLLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO29DQUNyQyxNQUFNLGtCQUFrQixHQUN0Qiw2QkFBNkIsRUFBRSxDQUFDO29DQUVsQyxJQUFJLGVBQWUsSUFBSSxrQkFBa0IsRUFBRSxDQUFDO3dDQUMxQyxTQUFTLENBQUMsSUFBSSxDQUNaLCtGQUErRixFQUMvRjs0Q0FDRSxTQUFTLEVBQUUsZUFBZSxDQUFDLGlCQUFpQjs0Q0FDNUMsaUJBQWlCLEVBQUUsR0FBRyxDQUFDLE9BQU87NENBQzlCLHNCQUFzQixFQUNwQixnQkFBZ0IsRUFBRSxPQUFPOzRDQUMzQixlQUFlOzRDQUNmLGVBQWUsRUFBRSxRQUFRLENBQUMsT0FBTzs0Q0FDakMsa0JBQWtCOzRDQUNsQixZQUFZLEVBQUUsR0FBRyxDQUFDLE9BQU87eUNBQzFCLENBQ0YsQ0FBQzt3Q0FDRixNQUFNLFlBQVksQ0FDaEIsS0FBSyxFQUNMLG9CQUFvQixDQUFDLFlBQVksRUFBRSxTQUFTLENBQUMsRUFDN0M7NENBQ0UsS0FBSzs0Q0FDTCxZQUFZLEVBQUUsTUFBTSxnQkFBZ0IsRUFBRTs0Q0FDdEMsV0FBVyxFQUFFLElBQUksSUFBSSxFQUFFOzRDQUN2QixnQkFBZ0IsRUFBRTtnREFDaEIsT0FBTyxFQUFFLEdBQUcsQ0FBQyxPQUFPO2dEQUNwQixLQUFLLEVBQUUsZUFBZTs2Q0FDdkI7eUNBQ0YsQ0FDRixDQUFDO3dDQUNGLE9BQU87b0NBQ1QsQ0FBQztvQ0FFRCwrQkFBK0IsR0FBRyxlQUFlLENBQUM7b0NBQ2xELGFBQWEsR0FBRyxJQUFJLHNCQUFzQixDQUN4Qyw0QkFBNEIsZUFBZSxnQkFBZ0Isa0JBQWtCLGlEQUFpRCxHQUFHLENBQUMsT0FBTyxzQkFBc0IsR0FBRyxDQUFDLE9BQU8sRUFBRSxFQUM1SyxFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUUsQ0FDZixDQUFDO2dDQUNKLENBQUM7cUNBQU0sSUFBSSxXQUFXLEdBQUcsQ0FBQyxFQUFFLENBQUM7b0NBQzNCLHNCQUFzQixDQUFDLFFBQVEsRUFBRSxDQUFDO2dDQUNwQyxDQUFDO2dDQUVELDZEQUE2RDtnQ0FDN0QsSUFBSSxhQUFhLFlBQVksS0FBSyxFQUFFLENBQUM7b0NBQ25DLElBQUksRUFBRSxlQUFlLEVBQUUsQ0FBQyxhQUFhLENBQUMsQ0FBQztnQ0FDekMsQ0FBQztnQ0FFRCxNQUFNLGVBQWUsR0FDbkIsTUFBTSxxQkFBcUIsQ0FBQyxhQUFhLENBQUMsQ0FBQztnQ0FDN0MsTUFBTSxTQUFTLEdBQ2IsZUFBZSxDQUFDLElBQUksSUFBSSxZQUFZLENBQUMsYUFBYSxDQUFDLENBQUM7Z0NBQ3RELE1BQU0sWUFBWSxHQUFHLGVBQWUsQ0FBQyxPQUFPLENBQUM7Z0NBQzdDLElBQUksVUFBVSxHQUNaLGVBQWUsQ0FBQyxLQUFLLElBQUksYUFBYSxDQUFDLGFBQWEsQ0FBQyxDQUFDO2dDQUV4RCxJQUFJLFVBQVUsRUFBRSxDQUFDO29DQUNmLE1BQU0sVUFBVSxHQUFHLGlCQUFpQixDQUFDLFlBQVksQ0FBQyxDQUFDO29DQUNuRCxNQUFNLFFBQVEsR0FDWixVQUFVLEVBQUUsZUFBZSxJQUFJLFlBQVksQ0FBQztvQ0FDOUMsVUFBVSxHQUFHLGVBQWUsQ0FDMUIsVUFBVSxFQUNWLFFBQVEsRUFDUixZQUFZLENBQ2IsQ0FBQztnQ0FDSixDQUFDO2dDQUVELHFEQUFxRDtnQ0FDckQsb0RBQW9EO2dDQUNwRCw0Q0FBNEM7Z0NBQzVDLE1BQU0sU0FBUyxHQUFHLGdCQUFnQixDQUFDLGFBQWEsQ0FBQyxDQUFDO2dDQUVsRCxhQUFhLENBQUMsS0FBSyxDQUFDLDhCQUE4QixFQUFFO29DQUNsRCxhQUFhLEVBQUUsS0FBSztvQ0FDcEIsU0FBUztvQ0FDVCxTQUFTO29DQUNULFVBQVU7aUNBQ1gsQ0FBQyxDQUFDO2dDQUVILG9EQUFvRDtnQ0FDcEQsa0RBQWtEO2dDQUNsRCxpREFBaUQ7Z0NBQ2pELGdEQUFnRDtnQ0FDaEQsbURBQW1EO2dDQUNuRCxvREFBb0Q7Z0NBQ3BELGlEQUFpRDtnQ0FDakQsZ0NBQWdDO2dDQUNoQyxJQUFJLEtBQUssQ0FBQyxhQUFhLENBQUMsYUFBYSxDQUFDLElBQUksVUFBVSxFQUFFLENBQUM7b0NBQ3BELGFBQXVCLENBQUMsS0FBSyxHQUFHLFVBQVUsQ0FBQztnQ0FDOUMsQ0FBQztnQ0FFRCxtREFBbUQ7Z0NBQ25ELGtEQUFrRDtnQ0FDbEQsaURBQWlEO2dDQUNqRCx5QkFBeUI7Z0NBQ3pCLEVBQUU7Z0NBQ0Ysd0RBQXdEO2dDQUN4RCx1REFBdUQ7Z0NBQ3ZELHVEQUF1RDtnQ0FDdkQseURBQXlEO2dDQUN6RCx1REFBdUQ7Z0NBQ3ZELHlEQUF5RDtnQ0FDekQsd0RBQXdEO2dDQUN4RCx3REFBd0Q7Z0NBQ3hELHlEQUF5RDtnQ0FDekQsc0RBQXNEO2dDQUN0RCxJQUFJLENBQUM7b0NBQ0gsNENBQTRDO29DQUM1Qyw4Q0FBOEM7b0NBQzlDLE1BQU0sYUFBYSxFQUFFLENBQUM7b0NBQ3RCLE1BQU0sV0FBVyxDQUNmO3dDQUNFLFNBQVMsRUFBRSxZQUFZO3dDQUN2QixXQUFXLEVBQUUsb0JBQW9CO3dDQUNqQyxTQUFTLEVBQUU7NENBQ1QsS0FBSyxFQUFFLE1BQU0saUJBQWlCLENBQzVCLGFBQWEsRUFDYixLQUFLLEVBQ0wsYUFBYSxFQUNiLFVBQVUsRUFDVixDQUFDLFdBQVcsRUFBRSxXQUFXLElBQUksQ0FBQyxDQUFDO2dEQUM3QixpQ0FBaUMsQ0FDcEM7NENBQ0QsU0FBUzt5Q0FDVjtxQ0FDRixFQUNEO3dDQUNFLFNBQVM7d0NBQ1QsR0FBRyxDQUFDLCtCQUErQixLQUFLLFNBQVM7NENBQy9DLENBQUMsQ0FBQztnREFDRSxxQkFBcUIsRUFDbkIsK0JBQStCOzZDQUNsQzs0Q0FDSCxDQUFDLENBQUMsRUFBRSxDQUFDO3FDQUNSLENBQ0YsQ0FBQztnQ0FDSixDQUFDO2dDQUFDLE9BQU8sT0FBTyxFQUFFLENBQUM7b0NBQ2pCLElBQ0UsbUJBQW1CLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQzt3Q0FDL0IsZUFBZSxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsRUFDM0IsQ0FBQzt3Q0FDRCxhQUFhLENBQUMsSUFBSSxDQUNoQiwyREFBMkQsRUFDM0Q7NENBQ0UsYUFBYSxFQUFFLEtBQUs7NENBQ3BCLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTzt5Q0FDekIsQ0FDRixDQUFDO3dDQUNGLE9BQU87b0NBQ1QsQ0FBQztvQ0FDRCxJQUFJLG9CQUFvQixDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7d0NBQ2xDLGFBQWEsQ0FBQyxLQUFLLENBQ2pCLDZEQUE2RCxFQUM3RDs0Q0FDRSxhQUFhLEVBQUUsS0FBSzs0Q0FDcEIsU0FBUyxFQUFFLGVBQWUsQ0FBQyxvQkFBb0I7NENBQy9DLEtBQUssRUFDSCxPQUFPLFlBQVksS0FBSztnREFDdEIsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxPQUFPO2dEQUNqQixDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQzt5Q0FDdEIsQ0FDRixDQUFDO3dDQUNGLE9BQU87b0NBQ1QsQ0FBQztvQ0FDRCxNQUFNLE9BQU8sQ0FBQztnQ0FDaEIsQ0FBQztnQ0FFRCxJQUFJLEVBQUUsYUFBYSxDQUFDO29DQUNsQixHQUFHLFNBQVMsQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRLENBQUM7b0NBQ3hDLEdBQUcsU0FBUyxDQUFDLGlCQUFpQixDQUFDLFNBQVMsQ0FBQztvQ0FDekMsR0FBRyxTQUFTLENBQUMsaUJBQWlCLENBQUMsU0FBUyxDQUFDO29DQUN6QyxHQUFHLFNBQVMsQ0FBQyxvQkFBb0IsQ0FBQyxZQUFZLENBQUM7b0NBQy9DLEdBQUcsU0FBUyxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUM7aUNBQ2xDLENBQUMsQ0FBQztnQ0FDSCxPQUFPOzRCQUNULENBQUM7d0JBQ0gsQ0FBQztvQkFDSCxDQUFDO2dCQUNILENBQUMsQ0FDRixDQUFDO1lBQ0osQ0FBQyxDQUNGLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FDRixDQUFDO0lBRUosSUFBSSxhQUFnRSxDQUFDO0lBQ3JFLElBQUksZUFBZSxHQUFHLENBQUMsQ0FBQztJQUN4QixNQUFNLG1CQUFtQixHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUN2QyxNQUFNLHFCQUFxQixHQUN6QixPQUFPLE9BQU8sRUFBRSx3QkFBd0IsS0FBSyxRQUFRO1FBQ25ELENBQUMsQ0FBQyxtQkFBbUIsR0FBRyxPQUFPLENBQUMsd0JBQXdCO1FBQ3hELENBQUMsQ0FBQyxTQUFTLENBQUM7SUFFaEIsT0FBTyxlQUFlLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxFQUFFO1FBQ25DLGVBQWUsSUFBSSxDQUFDLENBQUM7UUFDckIsTUFBTSxhQUFhLEdBQUcsYUFBYSxLQUFLLFNBQVMsQ0FBQztRQUNsRCxNQUFNLFFBQVEsR0FBRyxNQUFNLFdBQVcsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUU3QyxPQUFPLEtBQUssQ0FDVixxQkFBcUIsRUFDckI7WUFDRSxJQUFJLEVBQUUsUUFBUTtZQUNkLFVBQVUsRUFBRTtnQkFDVixHQUFHLFNBQVMsQ0FBQyxpQkFBaUIsQ0FBQyxNQUFNLENBQUM7Z0JBQ3RDLEdBQUcsU0FBUyxDQUFDLFlBQVksQ0FBQyxtQkFBbUIsQ0FBQztnQkFDOUMsR0FBRyxTQUFTLENBQUMsMEJBQTBCLENBQUMsYUFBYSxDQUFDO2dCQUN0RCxHQUFHLFNBQVMsQ0FBQyw0QkFBNEIsQ0FBQyxlQUFlLENBQUM7Z0JBQzFELEdBQUcsU0FBUyxDQUFDLDRCQUE0QixDQUN2QyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsbUJBQW1CLENBQ2pDO2dCQUNELEdBQUcsQ0FBQyxxQkFBcUIsS0FBSyxTQUFTO29CQUNyQyxDQUFDLENBQUMsRUFBRTtvQkFDSixDQUFDLENBQUMsU0FBUyxDQUFDLDZCQUE2QixDQUFDLHFCQUFxQixDQUFDLENBQUM7Z0JBQ25FLEdBQUcsU0FBUyxDQUFDLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUM7Z0JBQzFDLEdBQUcsU0FBUyxDQUFDLFNBQVMsQ0FBQywrQkFBK0IsQ0FBQzthQUN4RDtTQUNGLEVBQ0QsS0FBSyxFQUFFLElBQUksRUFBRSxFQUFFO1lBQ2IsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO2dCQUNuQixhQUFhLEdBQUcsTUFBTSxLQUFLLENBQUMscUJBQXFCLEVBQUUsS0FBSyxJQUFJLEVBQUU7b0JBQzVELE1BQU0sYUFBYSxHQUFHLE1BQU0sS0FBSyxDQUMvQixtQ0FBbUMsRUFDbkMsS0FBSyxJQUFJLEVBQUUsQ0FBQyxnQkFBZ0IsRUFBRSxDQUMvQixDQUFDO29CQUNGLE9BQU8sT0FBTyxDQUFDLGFBQWEsQ0FBQyxDQUFDO2dCQUNoQyxDQUFDLENBQUMsQ0FBQztZQUNMLENBQUM7WUFFRCxNQUFNLFFBQVEsR0FBRyxNQUFNLGFBQWEsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUMxQyxJQUFJLFFBQVEsWUFBWSxRQUFRLEVBQUUsQ0FBQztnQkFDakMsSUFBSSxFQUFFLGFBQWEsQ0FDakIsU0FBUyxDQUFDLHNCQUFzQixDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FDbEQsQ0FBQztZQUNKLENBQUM7WUFDRCxPQUFPLFFBQVEsQ0FBQztRQUNsQixDQUFDLENBQ0YsQ0FBQztJQUNKLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBhc3NlcnQgZnJvbSAnbm9kZTphc3NlcnQvc3RyaWN0JztcbmltcG9ydCB7IHR5cGVzIH0gZnJvbSAnbm9kZTp1dGlsJztcbmltcG9ydCB7XG4gIENvcnJ1cHRlZEV2ZW50TG9nRXJyb3IsXG4gIEVudGl0eUNvbmZsaWN0RXJyb3IsXG4gIEZhdGFsRXJyb3IsXG4gIEhvb2tOb3RGb3VuZEVycm9yLFxuICBNYXhFdmVudHNFeGNlZWRlZEVycm9yLFxuICBQcmVjb25kaXRpb25GYWlsZWRFcnJvcixcbiAgUmVwbGF5RGl2ZXJnZW5jZUVycm9yLFxuICBSVU5fRVJST1JfQ09ERVMsXG4gIHR5cGUgUnVuRXJyb3JDb2RlLFxuICBSdW5FeHBpcmVkRXJyb3IsXG4gIFdvcmtmbG93UnVudGltZUVycm9yLFxufSBmcm9tICdAd29ya2Zsb3cvZXJyb3JzJztcbmltcG9ydCB7IG9uY2UsIHNldFdvcmtmbG93QmFzZVBhdGggfSBmcm9tICdAd29ya2Zsb3cvdXRpbHMnO1xuaW1wb3J0IHtcbiAgcGFyc2VXb3JrZmxvd05hbWUsXG4gIHdvcmtmbG93RGlzcGxheU5hbWUsXG59IGZyb20gJ0B3b3JrZmxvdy91dGlscy9wYXJzZS1uYW1lJztcbmltcG9ydCB7XG4gIHR5cGUgQ3JlYXRlRXZlbnRQYXJhbXMsXG4gIHR5cGUgQ3JlYXRlRXZlbnRSZXF1ZXN0LFxuICB0eXBlIEV2ZW50LFxuICB0eXBlIEV2ZW50UmVzdWx0LFxuICBnZXRRdWV1ZVRvcGljUHJlZml4LFxuICBpc0xlZ2FjeVNwZWNWZXJzaW9uLFxuICBpc1Rlcm1pbmFsUnVuRXZlbnRUeXBlLFxuICBST09UX1JVTl9JRF9BVFRSSUJVVEUsXG4gIHR5cGUgUnVuSW5wdXQsXG4gIHJlc29sdmVRdWV1ZU5hbWVzcGFjZSxcbiAgU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gIFNQRUNfVkVSU0lPTl9TVVBQT1JUU19DT01QUkVTU0lPTixcbiAgdHlwZSBXb3JrZmxvd0ludm9rZVBheWxvYWQsXG4gIFdvcmtmbG93SW52b2tlUGF5bG9hZFNjaGVtYSxcbiAgdHlwZSBXb3JrZmxvd1J1bixcbiAgdHlwZSBXb3JsZCxcbn0gZnJvbSAnQHdvcmtmbG93L3dvcmxkJztcbmltcG9ydCBtcyBmcm9tICdtcyc7XG5pbXBvcnQgeyBkZWNvZGVUaW1lIH0gZnJvbSAndWxpZCc7XG5pbXBvcnQge1xuICBjbGFzc2lmeVJ1bkVycm9yLFxuICBpc1JldHJ5YWJsZVdvcmxkRXJyb3IsXG4gIGlzV29ybGRDb250cmFjdEVycm9yLFxufSBmcm9tICcuL2NsYXNzaWZ5LWVycm9yLmpzJztcbmltcG9ydCB7IGRlc2NyaWJlRXJyb3IgfSBmcm9tICcuL2Rlc2NyaWJlLWVycm9yLmpzJztcbmltcG9ydCB7IHR5cGUgU3RlcEludm9jYXRpb25RdWV1ZUl0ZW0sIFdvcmtmbG93U3VzcGVuc2lvbiB9IGZyb20gJy4vZ2xvYmFsLmpzJztcbmltcG9ydCB7IHR5cGUgTG9nZ2VyLCBydW50aW1lTG9nZ2VyIH0gZnJvbSAnLi9sb2dnZXIuanMnO1xuaW1wb3J0IHsgZ2V0U3RlcEZ1bmN0aW9uIH0gZnJvbSAnLi9wcml2YXRlLmpzJztcbmltcG9ydCB7IFJlcGxheVBheWxvYWRDYWNoZSB9IGZyb20gJy4vcmVwbGF5LXBheWxvYWQtY2FjaGUuanMnO1xuaW1wb3J0IHsgQ09NUFVURV9JTlNUQU5DRV9JRCB9IGZyb20gJy4vcnVudGltZS9jb21wdXRlLWluc3RhbmNlLmpzJztcbmltcG9ydCB7XG4gIGdldE1heEV2ZW50c092ZXJyaWRlLFxuICBnZXRNYXhRdWV1ZURlbGl2ZXJpZXMsXG4gIGdldFByZWNvbmRpdGlvbk1heEluUHJvY2Vzc1Jlc3RhcnRzLFxuICBnZXRQcmVjb25kaXRpb25NYXhSZWludm9jYXRpb25zLFxuICBnZXRQcmVjb25kaXRpb25SZWludm9rZURlbGF5U2Vjb25kcyxcbiAgZ2V0UmVwbGF5RGl2ZXJnZW5jZU1heFJldHJpZXMsXG4gIGlzSW5saW5lT3duZXJzaGlwRW5hYmxlZCxcbiAgaXNUdXJib0VuYWJsZWQsXG4gIGlzVm1SZXRlbnRpb25FbmFibGVkLFxufSBmcm9tICcuL3J1bnRpbWUvY29uc3RhbnRzLmpzJztcbmltcG9ydCB7IGNvdW50U3RlcFN0YXJ0ZWRFdmVudHMgfSBmcm9tICcuL3J1bnRpbWUvY291bnQtc3RlcC1zdGFydGVkLWV2ZW50cy5qcyc7XG5pbXBvcnQge1xuICB0eXBlIERlcGxveW1lbnRBZmZpbml0eU91dGNvbWUsXG4gIGd1YXJkRGVwbG95bWVudEFmZmluaXR5LFxuICB0eXBlIFJlZW5xdWV1ZUFyZ3MsXG59IGZyb20gJy4vcnVudGltZS9kZXBsb3ltZW50LWd1YXJkLmpzJztcbmltcG9ydCB7XG4gIGFwcGVuZFVuaXF1ZUV2ZW50cyxcbiAgZ2V0UXVldWVPdmVyaGVhZCxcbiAgZ2V0V29ya2Zsb3dRdWV1ZU5hbWUsXG4gIGhhbmRsZUhlYWx0aENoZWNrTWVzc2FnZSxcbiAgaW5zZXJ0RXZlbnRCeUV2ZW50SWQsXG4gIGlzUHJlY29uZGl0aW9uR3VhcmRFbmFibGVkLFxuICBpc1Nsb3RHYXBDaGVja0VuYWJsZWQsXG4gIHR5cGUgTG9hZGVkRXZlbnRMb2csXG4gIGxvYWRXb3JrZmxvd1J1bkV2ZW50cyxcbiAgbWVtb2l6ZUVuY3J5cHRpb25LZXksXG4gIG1lcmdlUmVwb3J0ZWRFdmVudHMsXG4gIHBhcnNlSGVhbHRoQ2hlY2tQYXlsb2FkLFxuICBwcmVjb25kaXRpb25FdmVudERlbHRhLFxuICBwcmVjb25kaXRpb25TbmFwc2hvdFBhcmFtcyxcbiAgcXVldWVNZXNzYWdlLFxuICBzZXR0bGVFdmVudFNsb3RHYXAsXG4gIHdpdGhIZWFsdGhDaGVjayxcbn0gZnJvbSAnLi9ydW50aW1lL2hlbHBlcnMuanMnO1xuaW1wb3J0IHtcbiAgaGFuZGxlUmVwbGF5QnVkZ2V0RXhoYXVzdGVkLFxuICBSZXBsYXlCdWRnZXQsXG59IGZyb20gJy4vcnVudGltZS9yZXBsYXktYnVkZ2V0LmpzJztcbmltcG9ydCB7IFJlcGxheVJlY292ZXJ5UmVwb3J0ZXIgfSBmcm9tICcuL3J1bnRpbWUvcmVwbGF5LXJlY292ZXJ5LXJlcG9ydGVyLmpzJztcbmltcG9ydCB7IHJ1bklkQ3JlYXRlZEF0IH0gZnJvbSAnLi9ydW50aW1lL3J1bi1pZC10aW1lLmpzJztcbmltcG9ydCB7XG4gIERFRkFVTFRfU1RFUF9NQVhfUkVUUklFUyxcbiAgZXhlY3V0ZVN0ZXAsXG59IGZyb20gJy4vcnVudGltZS9zdGVwLWV4ZWN1dG9yLmpzJztcbmltcG9ydCB7IGNvbXB1dGVTdGVwTGF0ZW5jeVRyYWNraW5nIH0gZnJvbSAnLi9ydW50aW1lL3N0ZXAtbGF0ZW5jeS5qcyc7XG5pbXBvcnQge1xuICBiYWNrc3RvcElkZW1wb3RlbmN5S2V5LFxuICBoYXNQZW5kaW5nU3RlcE93bmVkQnlNZXNzYWdlLFxuICBpc1N0ZXBPd25lcnNoaXBBY3RpdmUsXG4gIHN0ZXBMZWFzZVJlbWFpbmluZ1NlY29uZHMsXG59IGZyb20gJy4vcnVudGltZS9zdGVwLW93bmVyc2hpcC5qcyc7XG5pbXBvcnQgeyBydW5TdGVwU2luZ2xlRmxpZ2h0IH0gZnJvbSAnLi9ydW50aW1lL3N0ZXAtc2luZ2xlLWZsaWdodC5qcyc7XG5pbXBvcnQgeyBoYW5kbGVTdXNwZW5zaW9uIH0gZnJvbSAnLi9ydW50aW1lL3N1c3BlbnNpb24taGFuZGxlci5qcyc7XG5pbXBvcnQgeyB1c2VRdWlja0pTVm0gfSBmcm9tICcuL3J1bnRpbWUvdm0tbW9kZS5qcyc7XG5pbXBvcnQgeyBnZXRXYWl0Q29udGludWF0aW9uRGlzcGF0Y2ggfSBmcm9tICcuL3J1bnRpbWUvd2FpdC1jb250aW51YXRpb24uanMnO1xuaW1wb3J0IHtcbiAgZ2V0V29ybGQsXG4gIGdldFdvcmxkSGFuZGxlcnMsXG4gIHR5cGUgV29ybGRIYW5kbGVycyxcbn0gZnJvbSAnLi9ydW50aW1lL3dvcmxkLmpzJztcbmltcG9ydCB7IGRlaHlkcmF0ZVJ1bkVycm9yIH0gZnJvbSAnLi9zZXJpYWxpemF0aW9uLmpzJztcbmltcG9ydCB7IHJlbWFwRXJyb3JTdGFjayB9IGZyb20gJy4vc291cmNlLW1hcC5qcyc7XG5pbXBvcnQgKiBhcyBBdHRyaWJ1dGUgZnJvbSAnLi90ZWxlbWV0cnkvc2VtYW50aWMtY29udmVudGlvbnMuanMnO1xuaW1wb3J0IHtcbiAgYnVpbGRJbnZvY2F0aW9uU3BhbkxpbmtzLFxuICBnZXROZXh0VHJhY2VDYXJyaWVyLFxuICBnZXRTcGFuS2luZCxcbiAgZ2V0V29ya2Zsb3dUcmFjZU1vZGUsXG4gIGlzVXNhYmxlVHJhY2VDYXJyaWVyLFxuICB0cmFjZSxcbiAgd2l0aFRyYWNlQ29udGV4dCxcbiAgd2l0aFdvcmtmbG93QmFnZ2FnZSxcbn0gZnJvbSAnLi90ZWxlbWV0cnkuanMnO1xuaW1wb3J0IHsgZ2V0RXJyb3JOYW1lLCBnZXRFcnJvclN0YWNrLCBub3JtYWxpemVVbmtub3duRXJyb3IgfSBmcm9tICcuL3R5cGVzLmpzJztcbmltcG9ydCB7IGJ1aWxkV29ya2Zsb3dTdXNwZW5zaW9uTWVzc2FnZSB9IGZyb20gJy4vdXRpbC5qcyc7XG5pbXBvcnQge1xuICByZXBsYXlXb3JrZmxvdyxcbiAgcmVzdW1lV29ya2Zsb3csXG4gIHR5cGUgV29ya2Zsb3dSZXN1bWVSZXN1bHQsXG4gIHR5cGUgV29ya2Zsb3dTZXNzaW9uLFxufSBmcm9tICcuL3dvcmtmbG93LmpzJztcblxuZXhwb3J0IHR5cGUgeyBFdmVudCwgV29ya2Zsb3dSdW4gfTtcbmV4cG9ydCB7IFdvcmtmbG93U3VzcGVuc2lvbiB9IGZyb20gJy4vZ2xvYmFsLmpzJztcbmV4cG9ydCB7XG4gIHR5cGUgSGVhbHRoQ2hlY2tPcHRpb25zLFxuICB0eXBlIEhlYWx0aENoZWNrUmVzdWx0LFxuICBoZWFsdGhDaGVjayxcbn0gZnJvbSAnLi9ydW50aW1lL2hlbHBlcnMuanMnO1xuZXhwb3J0IHtcbiAgZ2V0SG9va0J5VG9rZW4sXG4gIHR5cGUgUmVzdW1lZEhvb2ssXG4gIHJlc3VtZUhvb2ssXG4gIHJlc3VtZVdlYmhvb2ssXG59IGZyb20gJy4vcnVudGltZS9yZXN1bWUtaG9vay5qcyc7XG5leHBvcnQge1xuICBnZXRSdW4sXG4gIFJ1bixcbiAgdHlwZSBXb3JrZmxvd1JlYWRhYmxlU3RyZWFtLFxuICB0eXBlIFdvcmtmbG93UmVhZGFibGVTdHJlYW1PcHRpb25zLFxufSBmcm9tICcuL3J1bnRpbWUvcnVuLmpzJztcbmV4cG9ydCB7XG4gIHR5cGUgQ2FuY2VsUnVuT3B0aW9ucyxcbiAgY2FuY2VsUnVuLFxuICBjYW5jZWxSdW5zLFxuICBsaXN0U3RyZWFtcyxcbiAgdHlwZSBSZWFkU3RyZWFtT3B0aW9ucyxcbiAgdHlwZSBSZWNyZWF0ZVJ1bk9wdGlvbnMsXG4gIHR5cGUgUmVlbnF1ZXVlUnVuT3B0aW9ucyxcbiAgcmVhZFN0cmVhbSxcbiAgcmVjcmVhdGVSdW5Gcm9tRXhpc3RpbmcsXG4gIHJlZW5xdWV1ZVJ1bixcbiAgdHlwZSBTdG9wU2xlZXBPcHRpb25zLFxuICB0eXBlIFN0b3BTbGVlcFJlc3VsdCxcbiAgd2FrZVVwUnVuLFxufSBmcm9tICcuL3J1bnRpbWUvcnVucy5qcyc7XG5leHBvcnQge1xuICB0eXBlIFN0YXJ0T3B0aW9ucyxcbiAgdHlwZSBTdGFydE9wdGlvbnNCYXNlLFxuICB0eXBlIFN0YXJ0T3B0aW9uc1dpdGhEZXBsb3ltZW50SWQsXG4gIHR5cGUgU3RhcnRPcHRpb25zV2l0aG91dERlcGxveW1lbnRJZCxcbiAgc3RhcnQsXG59IGZyb20gJy4vcnVudGltZS9zdGFydC5qcyc7XG5leHBvcnQge1xuICBjcmVhdGVXb3JsZCxcbiAgY3JlYXRlV29ybGRGcm9tTW9kdWxlLFxuICBnZXRXb3JsZCxcbiAgZ2V0V29ybGRIYW5kbGVycyxcbiAgc2V0V29ybGQsXG4gIHR5cGUgV29ybGRGYWN0b3J5TW9kdWxlLFxufSBmcm9tICcuL3J1bnRpbWUvd29ybGQuanMnO1xuXG4vKipcbiAqIEFwcGx5IHRoZSBvcHRpb25hbCBjbGllbnQtc2lkZSBldmVudC1saW1pdCBvdmVycmlkZS5cbiAqIGBXT1JLRkxPV19NQVhfRVZFTlRTX09WRVJSSURFYCwgd2hlbiBzZXQgdG8gYSBwb3NpdGl2ZSBpbnRlZ2VyLCBjbGFtcHMgdGhlXG4gKiBzZXJ2ZXItc3VwcGxpZWQgcGVyLXJ1biBldmVudCBjZWlsaW5nIHRvIGEgc21hbGxlciB2YWx1ZSBzbyBlbmZvcmNlbWVudCBjYW5cbiAqIGJlIGV4ZXJjaXNlZCB3aXRob3V0IGEgc2VydmVyLXNpZGUgY2hhbmdlLiBDbGFtcC1kb3duIG9ubHk6IGl0IG5ldmVyIHJhaXNlc1xuICogdGhlIHNlcnZlcidzIGxpbWl0LCBhbmQgaXQgdGFrZXMgZWZmZWN0IGV2ZW4gd2hlbiB0aGUgc2VydmVyIHJldHVybnMgbm9uZS5cbiAqIFVuc2V0IOKHkiBzZXJ2ZXIgdmFsdWUgcGFzc2VzIHRocm91Z2ggdW5jaGFuZ2VkLlxuICovXG5mdW5jdGlvbiBjbGFtcE1heEV2ZW50cyhzZXJ2ZXJWYWx1ZTogbnVtYmVyIHwgdW5kZWZpbmVkKTogbnVtYmVyIHwgdW5kZWZpbmVkIHtcbiAgY29uc3Qgb3ZlcnJpZGUgPSBnZXRNYXhFdmVudHNPdmVycmlkZSgpO1xuICBpZiAob3ZlcnJpZGUgPT09IHVuZGVmaW5lZCkgcmV0dXJuIHNlcnZlclZhbHVlO1xuICByZXR1cm4gc2VydmVyVmFsdWUgPT09IHVuZGVmaW5lZCA/IG92ZXJyaWRlIDogTWF0aC5taW4oc2VydmVyVmFsdWUsIG92ZXJyaWRlKTtcbn1cblxuLyoqXG4gKiBSZWZ1c2UgYSBxdWV1ZSBkZWxpdmVyeSB3aG9zZSBydW4gd2FzIGNyZWF0ZWQgaW4gYSBkaWZmZXJlbnQgZW52aXJvbm1lbnQgdGhhblxuICogdGhpcyBkZXBsb3ltZW50IHJ1bnMgaW4uXG4gKlxuICogYHN0YXJ0KClgIHBlcmZvcm1zIHR3byB3cml0ZXMgdGhhdCBtdXN0IGxhbmQgaW4gdGhlIHNhbWUgdGVuYW50OiB0aGVcbiAqIGBydW5fY3JlYXRlZGAgZXZlbnQsIGF0dHJpYnV0ZWQgdG8gd2hhdGV2ZXIgZW52aXJvbm1lbnQgdGhlICpjYWxsZXIqXG4gKiBhdXRoZW50aWNhdGVzIGFzLCBhbmQgdGhlIHF1ZXVlIG1lc3NhZ2UsIHBpbm5lZCB0byBhICpkZXBsb3ltZW50Ki4gQVxuICogbWlzY29uZmlndXJlZCBjYWxsZXIgY2FuIHNwbGl0IHRoZW0g4oCUIHdyaXRpbmcgdGhlIHJ1biB0byBvbmUgZW52aXJvbm1lbnRcbiAqIHdoaWxlIGFkZHJlc3NpbmcgdGhlIG1lc3NhZ2UgdG8gYSBkZXBsb3ltZW50IGluIGFub3RoZXIuIFRoZSBjb25zdW1lciB0aGVuXG4gKiBmaW5kcyBubyBydW4gdW5kZXIgaXRzIG93biB0ZW5hbnQgYW5kIHRoZSBiYWNrZW5kJ3MgcmVzaWxpZW50IHN0YXJ0XG4gKiAoYHJ1bl9zdGFydGVkYCBjcmVhdGVzIHRoZSBydW4gd2hlbiBgcnVuX2NyZWF0ZWRgIHdhcyBuZXZlciBzZWVuKSBtaW50cyBhXG4gKiBTRUNPTkQgY29weSBvZiB0aGUgc2FtZSBydW4gaWQgaW4gdGhpcyBlbnZpcm9ubWVudC4gQm90aCBjb3BpZXMgYXJlIHJlYWw6IHRoZVxuICogY3JlYXRvcidzIHNpdHMgcGVuZGluZyBmb3JldmVyLCB0aGlzIG9uZSBleGVjdXRlcywgYW5kIGV2ZXJ5IHN1YnNlcXVlbnRcbiAqIGNyb3NzLXRlbmFudCBxdWV1ZSBhY2sgZmFpbHMgdG8gZmluZCBpdHMgbWVzc2FnZS5cbiAqXG4gKiBOb3RoaW5nIGV4dGVybmFsIGlzIG5lZWRlZCB0byBjYXRjaCB0aGlzOiB0aGUgY3JlYXRvcidzIGVudmlyb25tZW50IHJpZGVzIHRoZVxuICogbWVzc2FnZSBpbiBgcnVuSW5wdXQuZW52aXJvbm1lbnRgIGFuZCB0aGlzIHByb2Nlc3MgYWxyZWFkeSBrbm93cyBpdHMgb3duLiBTb1xuICogY29tcGFyZSB0aGVtIGFuZCBzdG9wIEJFRk9SRSBgcnVuX3N0YXJ0ZWRgIOKAlCB0aGUgd3JpdGUgdGhhdCB3b3VsZCBjcmVhdGUgdGhlXG4gKiBmb3JrLiBSZWZ1c2luZyBhZnRlciBpdCB3b3VsZCBiZSB0b28gbGF0ZS5cbiAqXG4gKiBSZXR1cm5zIGB0cnVlYCB3aGVuIHRoZSBjYWxsZXIgbXVzdCBhYmFuZG9uIHRoZSBkZWxpdmVyeS4gU2tpcHBlZCB3aGVuZXZlclxuICogZWl0aGVyIHNpZGUgaXMgdW5rbm93biwgd2hpY2gga2VlcHMgZXZlcnkgZXhpc3Rpbmcgc2V0dXAgb24gaXRzIGN1cnJlbnRcbiAqIGJlaGF2aW9yOiB3b3JsZHMgd2l0aCBubyBlbnZpcm9ubWVudCBkaW1lbnNpb24gKGB3b3JsZC1sb2NhbGAsXG4gKiBgd29ybGQtcG9zdGdyZXNgKSBkb24ndCBpbXBsZW1lbnQgYGdldEVudmlyb25tZW50YCwgYW5kIHJ1bnMgc3RhcnRlZCBieSBhblxuICogb2xkZXIgU0RLIGNhcnJ5IG5vIGBlbnZpcm9ubWVudGAgZmllbGQuXG4gKi9cbmZ1bmN0aW9uIHJlZnVzZUNyb3NzRW52aXJvbm1lbnREZWxpdmVyeSh7XG4gIHdvcmxkLFxuICBydW5JbnB1dCxcbiAgcnVuSWQsXG4gIHJ1bkxvZ2dlcixcbn06IHtcbiAgd29ybGQ6IFdvcmxkO1xuICBydW5JbnB1dDogUnVuSW5wdXQgfCB1bmRlZmluZWQ7XG4gIHJ1bklkOiBzdHJpbmc7XG4gIHJ1bkxvZ2dlcjogTG9nZ2VyO1xufSk6IGJvb2xlYW4ge1xuICBjb25zdCBjcmVhdG9yRW52aXJvbm1lbnQgPSBydW5JbnB1dD8uZW52aXJvbm1lbnQ7XG4gIGlmICghY3JlYXRvckVudmlyb25tZW50KSByZXR1cm4gZmFsc2U7XG5cbiAgY29uc3QgY3VycmVudEVudmlyb25tZW50ID0gd29ybGQuZ2V0RW52aXJvbm1lbnQ/LigpO1xuICBpZiAoIWN1cnJlbnRFbnZpcm9ubWVudCB8fCBjdXJyZW50RW52aXJvbm1lbnQgPT09IGNyZWF0b3JFbnZpcm9ubWVudCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHJ1bkxvZ2dlci5lcnJvcihcbiAgICBgUmVmdXNpbmcgdG8gcnVuIHRoaXMgd29ya2Zsb3c6IGl0IHdhcyBjcmVhdGVkIGluIHRoZSBcIiR7Y3JlYXRvckVudmlyb25tZW50fVwiIGAgK1xuICAgICAgYGVudmlyb25tZW50IGJ1dCB0aGlzIGRlcGxveW1lbnQgcnVucyBpbiBcIiR7Y3VycmVudEVudmlyb25tZW50fVwiLiBgICtcbiAgICAgICdFeGVjdXRpbmcgaXQgaGVyZSB3b3VsZCBjcmVhdGUgYSBzZWNvbmQgY29weSBvZiB0aGUgc2FtZSBydW4gaWQgaW4gJyArXG4gICAgICAnYm90aCBlbnZpcm9ubWVudHMg4oCUIG9uZSBwZW5kaW5nIGZvcmV2ZXIsIG9uZSBydW5uaW5nIOKAlCBzbyB0aGUgcXVldWUgJyArXG4gICAgICAnbWVzc2FnZSBpcyBiZWluZyBkaXNjYXJkZWQgd2l0aG91dCBleGVjdXRpbmcgYW5kIHdpdGhvdXQgcmV0cnlpbmcuICcgK1xuICAgICAgJ1RoZSBjbGllbnQgdGhhdCBjYWxsZWQgc3RhcnQoKSB3cm90ZSB0aGUgcnVuIHRvIGl0cyBvd24gZW52aXJvbm1lbnQgJyArXG4gICAgICAnYnV0IGFkZHJlc3NlZCB0aGUgcXVldWUgbWVzc2FnZSB0byBhIGRlcGxveW1lbnQgaW4gYW5vdGhlciBvbmUuIENoZWNrICcgK1xuICAgICAgJ3RoYXQgdGhlIGVudmlyb25tZW50IHRoYXQgY2xpZW50IGF1dGhlbnRpY2F0ZXMgYXMgKFdPUktGTE9XX1ZFUkNFTF9FTlYgJyArXG4gICAgICBcImZvciBDTEkgYW5kIENJIGNsaWVudHMsIG9yIHRoZSBPSURDIHRva2VuJ3MgZW52aXJvbm1lbnQgaW5zaWRlIGEgXCIgK1xuICAgICAgJ2RlcGxveW1lbnQpIG1hdGNoZXMgdGhlIGVudmlyb25tZW50IG9mIHRoZSBkZXBsb3ltZW50IGl0IHRhcmdldHMuIFRoZSAnICtcbiAgICAgIGBydW4gaXQgY3JlYXRlZCBpcyBzdGlsbCBwZW5kaW5nIGluIFwiJHtjcmVhdG9yRW52aXJvbm1lbnR9XCIgYW5kIHdpbGwgYCArXG4gICAgICAnbm90IHJ1bi4nLFxuICAgIHtcbiAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgY3JlYXRvckVudmlyb25tZW50LFxuICAgICAgY3VycmVudEVudmlyb25tZW50LFxuICAgICAgcGlubmVkRGVwbG95bWVudElkOiBydW5JbnB1dD8uZGVwbG95bWVudElkLFxuICAgIH1cbiAgKTtcbiAgcmV0dXJuIHRydWU7XG59XG5cbi8qKlxuICogTG9nIHdoZW4gYSBgc3RhcnQoKWAtZW5xdWV1ZWQgbWVzc2FnZSBwaW5uZWQgdG8gb25lIGRlcGxveW1lbnQgaXMgZGVsaXZlcmVkXG4gKiB0byBhIGRpZmZlcmVudCBvbmUuXG4gKlxuICogQSBmaXJzdC1kZWxpdmVyeSBtZXNzYWdlIGNhcnJpZXMgYHJ1bklucHV0LmRlcGxveW1lbnRJZGAg4oCUIHRoZSBkZXBsb3ltZW50XG4gKiBgc3RhcnQoKWAgYWRkcmVzc2VkIGl0IHRvIOKAlCBzbyBjb21wYXJpbmcgdGhhdCBhZ2FpbnN0IHRoaXMgaGFuZGxlcidzIG93blxuICogZGVwbG95bWVudCBkZXRlY3RzIG1pcy1kZWxpdmVyeSBkaXJlY3RseS4gVGhpcyBpcyBhIERJQUdOT1NUSUMsIG5vdCBhIGdhdGU6XG4gKiBpdCB3YXJucyBhbmQgbGV0cyB0aGUgaW52b2NhdGlvbiBwcm9jZWVkLCBkZWxpYmVyYXRlbHkuXG4gKlxuICogV2h5IHRoaXMgb25lIG9ubHkgd2FybnMgd2hpbGUgaXRzIGVudmlyb25tZW50IHNpYmxpbmcgYWJvdmUgcmVmdXNlczogYVxuICogZGlmZmVyaW5nIGRlcGxveW1lbnQgaWQgaXMgbm90IGJ5IGl0c2VsZiBldmlkZW5jZSBvZiB0aGUgZm9yayB3ZSBjYXJlIGFib3V0LlxuICogVGhlIGVudmlyb25tZW50IHBhaXIgaXMgZXhhY3Qg4oCUIHR3byBuYW1lZCBlbnZpcm9ubWVudHMgdGhhdCBkaXNhZ3JlZSDigJQgYW5kIGl0XG4gKiBpcyB0aGUgZGltZW5zaW9uIHRoZSBydW4ncyB0ZW5hbnQgaXMga2V5ZWQgb24uIERlcGxveW1lbnQgaWRzIGRpc2FncmVlIGZvclxuICogYmVuaWduIHJlYXNvbnMgdG9vOiBgd29ybGQtbG9jYWxgIGRlcml2ZXMgaXRzIGlkIGZyb20gdGhlIGluc3RhbGxlZCBwYWNrYWdlXG4gKiB2ZXJzaW9uIChgZHBsX2xvY2FsQDx2ZXJzaW9uPmApLCBzbyB1cGdyYWRpbmcgdGhlIFNESyBtaWQtcnVuIGNoYW5nZXMgaXQgd2l0aFxuICogbm90aGluZyB3cm9uZy4gUmVmdXNpbmcgb24gdGhhdCBzaWduYWwgd291bGQgc3RyYW5kIGNvcnJlY3QgcnVucywgYW5kXG4gKiByZWZ1c2luZyBiZWZvcmUgYHJ1bl9zdGFydGVkYCBsZWF2ZXMgbm8gc2VydmVyLXNpZGUgcmVjb3JkIHRvIGV4cGxhaW4gd2h5LlxuICogQW55b25lIHRlbXB0ZWQgdG8gcHJvbW90ZSB0aGlzIHRvIGEgaGFyZCBmYWlsdXJlIGhhcyB0byBoYW5kbGUgdGhhdCBmaXJzdC5cbiAqXG4gKiBTa2lwcGVkIHVubGVzcyBCT1RIIGlkcyBhcmUga25vd24g4oCUIGBnZXREZXBsb3ltZW50SWQoKWAgdGhyb3dzIGluIHdvcmxkcyB0aGF0XG4gKiByZXF1aXJlIGEgZGVwbG95bWVudCBhbmQgaGF2ZSBub25lLCBhbmQgYSByZS1lbnF1ZXVlZCBtZXNzYWdlIGNhcnJpZXMgbm9cbiAqIGBydW5JbnB1dGAgYXQgYWxsLlxuICovXG5hc3luYyBmdW5jdGlvbiB3YXJuT25EZXBsb3ltZW50UGlubmluZ01pc21hdGNoKHtcbiAgd29ybGQsXG4gIHJ1bklucHV0LFxuICBydW5JZCxcbiAgcnVuTG9nZ2VyLFxufToge1xuICB3b3JsZDogV29ybGQ7XG4gIHJ1bklucHV0OiBSdW5JbnB1dCB8IHVuZGVmaW5lZDtcbiAgcnVuSWQ6IHN0cmluZztcbiAgcnVuTG9nZ2VyOiBMb2dnZXI7XG59KTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHBpbm5lZERlcGxveW1lbnRJZCA9IHJ1bklucHV0Py5kZXBsb3ltZW50SWQ7XG4gIGlmICghcGlubmVkRGVwbG95bWVudElkKSByZXR1cm47XG5cbiAgbGV0IGN1cnJlbnREZXBsb3ltZW50SWQ6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgdHJ5IHtcbiAgICBjdXJyZW50RGVwbG95bWVudElkID0gYXdhaXQgd29ybGQuZ2V0RGVwbG95bWVudElkKCk7XG4gIH0gY2F0Y2gge1xuICAgIC8vIFdvcmxkcyB0aGF0IHJlcXVpcmUgYSBkZXBsb3ltZW50IGlkIHRocm93IHdoZW4gdGhlcmUgaXNuJ3Qgb25lLiBUaGF0IGlzXG4gICAgLy8gbm90IGEgbWlzbWF0Y2gg4oCUIHRoZXJlIGlzIHNpbXBseSBub3RoaW5nIHRvIGNvbXBhcmUgYWdhaW5zdC5cbiAgICByZXR1cm47XG4gIH1cbiAgaWYgKCFjdXJyZW50RGVwbG95bWVudElkIHx8IGN1cnJlbnREZXBsb3ltZW50SWQgPT09IHBpbm5lZERlcGxveW1lbnRJZCkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHJ1bkxvZ2dlci5lcnJvcihcbiAgICAnUXVldWUgbWVzc2FnZSB3YXMgZGVsaXZlcmVkIHRvIGEgZGVwbG95bWVudCBpdCB3YXMgbm90IHBpbm5lZCB0by4gJyArXG4gICAgICAnVGhlIHJ1biB3YXMgY3JlYXRlZCB0YXJnZXRpbmcgYSBkaWZmZXJlbnQgZGVwbG95bWVudCwgc28gdGhpcyAnICtcbiAgICAgICdpbnZvY2F0aW9uIG1heSBiZSByZXBsYXlpbmcgYWdhaW5zdCBjb2RlIHRoZSBydW4gd2FzIG5vdCBzdGFydGVkIG9uLiAnICtcbiAgICAgICdDb250aW51aW5nIOKAlCB0aGlzIGlzIGV4cGVjdGVkIGlmIHRoZSBXb3JrZmxvdyBTREsgdmVyc2lvbiBjaGFuZ2VkICcgK1xuICAgICAgJ21pZC1ydW4gaW4gbG9jYWwgZGV2ZWxvcG1lbnQsIHdoZXJlIHRoZSBkZXBsb3ltZW50IGlkIGlzIGRlcml2ZWQgZnJvbSAnICtcbiAgICAgICd0aGF0IHZlcnNpb24uJyxcbiAgICB7XG4gICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgIHBpbm5lZERlcGxveW1lbnRJZCxcbiAgICAgIGN1cnJlbnREZXBsb3ltZW50SWQsXG4gICAgfVxuICApO1xufVxuXG5mdW5jdGlvbiBnZXRXb3JrZmxvd1NldHVwRXJyb3JDb2RlKGVycjogdW5rbm93bik6IFJ1bkVycm9yQ29kZSB8IG51bGwge1xuICBpZiAoV29ya2Zsb3dSdW50aW1lRXJyb3IuaXMoZXJyKSkge1xuICAgIHJldHVybiBSVU5fRVJST1JfQ09ERVMuUlVOVElNRV9FUlJPUjtcbiAgfVxuXG4gIGlmIChpc1dvcmxkQ29udHJhY3RFcnJvcihlcnIpKSB7XG4gICAgcmV0dXJuIFJVTl9FUlJPUl9DT0RFUy5XT1JMRF9DT05UUkFDVF9FUlJPUjtcbiAgfVxuXG4gIHJldHVybiBudWxsO1xufVxuXG5hc3luYyBmdW5jdGlvbiByZWNvcmRGYXRhbFJ1bkVycm9yKHtcbiAgd29ybGQsXG4gIHdvcmtmbG93UnVuLFxuICBydW5JZCxcbiAgcmVxdWVzdElkLFxuICBlcnIsXG4gIGVycm9yQ29kZSxcbiAgbG9nTWVzc2FnZSxcbn06IHtcbiAgd29ybGQ6IFdvcmxkO1xuICB3b3JrZmxvd1J1bjogV29ya2Zsb3dSdW4gfCB1bmRlZmluZWQ7XG4gIHJ1bklkOiBzdHJpbmc7XG4gIHJlcXVlc3RJZDogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICBlcnI6IHVua25vd247XG4gIGVycm9yQ29kZTogUnVuRXJyb3JDb2RlO1xuICBsb2dNZXNzYWdlOiBzdHJpbmc7XG59KSB7XG4gIHJ1bnRpbWVMb2dnZXIuZXJyb3IobG9nTWVzc2FnZSwge1xuICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgIGVycm9yQ29kZSxcbiAgICBlcnJvcjogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpLFxuICB9KTtcblxuICB0cnkge1xuICAgIGNvbnN0IGdldEVuY3J5cHRpb25LZXkgPSBtZW1vaXplRW5jcnlwdGlvbktleSh3b3JsZCwgd29ya2Zsb3dSdW4gPz8gcnVuSWQpO1xuICAgIGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGUoXG4gICAgICBydW5JZCxcbiAgICAgIHtcbiAgICAgICAgZXZlbnRUeXBlOiAncnVuX2ZhaWxlZCcsXG4gICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgZXJyb3I6IGF3YWl0IGRlaHlkcmF0ZVJ1bkVycm9yKFxuICAgICAgICAgICAgZXJyLFxuICAgICAgICAgICAgcnVuSWQsXG4gICAgICAgICAgICBhd2FpdCBnZXRFbmNyeXB0aW9uS2V5KCksXG4gICAgICAgICAgICBnbG9iYWxUaGlzLFxuICAgICAgICAgICAgKHdvcmtmbG93UnVuPy5zcGVjVmVyc2lvbiA/PyAwKSA+PSBTUEVDX1ZFUlNJT05fU1VQUE9SVFNfQ09NUFJFU1NJT05cbiAgICAgICAgICApLFxuICAgICAgICAgIGVycm9yQ29kZSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICB7IHJlcXVlc3RJZCB9XG4gICAgKTtcbiAgfSBjYXRjaCAoZmFpbEVycikge1xuICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKGZhaWxFcnIpIHx8IFJ1bkV4cGlyZWRFcnJvci5pcyhmYWlsRXJyKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoaXNXb3JsZENvbnRyYWN0RXJyb3IoZmFpbEVycikpIHtcbiAgICAgIHJ1bnRpbWVMb2dnZXIuZXJyb3IoXG4gICAgICAgICdGYXRhbCB3b3JsZCBjb250cmFjdCBlcnJvciB3aGlsZSByZWNvcmRpbmcgd29ya2Zsb3cgZmFpbHVyZScsXG4gICAgICAgIHtcbiAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICBlcnJvckNvZGU6IFJVTl9FUlJPUl9DT0RFUy5XT1JMRF9DT05UUkFDVF9FUlJPUixcbiAgICAgICAgICBlcnJvcjogZmFpbEVyciBpbnN0YW5jZW9mIEVycm9yID8gZmFpbEVyci5tZXNzYWdlIDogU3RyaW5nKGZhaWxFcnIpLFxuICAgICAgICB9XG4gICAgICApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aHJvdyBmYWlsRXJyO1xuICB9XG59XG5cbmZ1bmN0aW9uIGhhc1JlY29yZGVkVGVybWluYWxSdW5FdmVudChldmVudHM6IEV2ZW50W10sIHJ1bklkOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgLy8gVGVybWluYWwgcnVuIGV2ZW50cyBhcmUgYWx3YXlzIGxhc3QgYnkgY29uc3RydWN0aW9uIChubyBldmVudCBjcmVhdGlvblxuICAvLyBzdWNjZWVkcyBhZ2FpbnN0IGEgdGVybWluYWwgcnVuKSwgYnV0IHNjYW4gdGhlIGZ1bGwgYXJyYXkgZm9yXG4gIC8vIGRlZmVuc2UtaW4tZGVwdGg6IGEgV29ybGQvYmFja2VuZCBvcmRlcmluZyBidWcgc2hvdWxkbid0IG1ha2UgdXMgbWlzcyBhblxuICAvLyBhY3R1YWwgdGVybWluYXRpb24gc2lnbmFsLlxuICBjb25zdCB0ZXJtaW5hbFJ1bkV2ZW50ID0gZXZlbnRzLmZpbmQoXG4gICAgKGUpID0+XG4gICAgICBlLnJ1bklkID09PSBydW5JZCAmJlxuICAgICAgKGUuZXZlbnRUeXBlID09PSAncnVuX2NvbXBsZXRlZCcgfHxcbiAgICAgICAgZS5ldmVudFR5cGUgPT09ICdydW5fZmFpbGVkJyB8fFxuICAgICAgICBlLmV2ZW50VHlwZSA9PT0gJ3J1bl9jYW5jZWxsZWQnKVxuICApO1xuXG4gIGlmICghdGVybWluYWxSdW5FdmVudCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHJ1bnRpbWVMb2dnZXIuZGVidWcoJ1J1biByZWFjaGVkIHRlcm1pbmFsIGV2ZW50LCBleGl0aW5nJywge1xuICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgIGV2ZW50VHlwZTogdGVybWluYWxSdW5FdmVudC5ldmVudFR5cGUsXG4gICAgZXZlbnRJZDogdGVybWluYWxSdW5FdmVudC5ldmVudElkLFxuICB9KTtcbiAgcmV0dXJuIHRydWU7XG59XG5cbi8qKiBIb3cgbWFueSBvZiBgaWRzYCBhcmUgYWJzZW50IGZyb20gYHByZXNlbnRgLiAqL1xuZnVuY3Rpb24gY291bnRNaXNzaW5nSWRzKGlkczogSXRlcmFibGU8c3RyaW5nPiwgcHJlc2VudDogU2V0PHN0cmluZz4pOiBudW1iZXIge1xuICBsZXQgbWlzc2luZyA9IDA7XG4gIGZvciAoY29uc3QgaWQgb2YgaWRzKSB7XG4gICAgaWYgKCFwcmVzZW50LmhhcyhpZCkpIG1pc3NpbmcrKztcbiAgfVxuICByZXR1cm4gbWlzc2luZztcbn1cblxuLyoqXG4gKiBUaGUgbGluZWFnZSByb290IG9mIGEgbG9hZGVkIHJ1bjogaXRzIGAkcm9vdFJ1bklkYCBhdHRyaWJ1dGUsIG9yIGl0cyBvd24gaWRcbiAqIHdoZW4gaXQgaXMgaXRzZWxmIGEgcm9vdC5cbiAqL1xuZnVuY3Rpb24gcm9vdFJ1bklkRnJvbShcbiAgYXR0cmlidXRlczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB8IHVuZGVmaW5lZCxcbiAgcnVuSWQ6IHN0cmluZ1xuKTogc3RyaW5nIHtcbiAgcmV0dXJuIGF0dHJpYnV0ZXM/LltST09UX1JVTl9JRF9BVFRSSUJVVEVdID8/IHJ1bklkO1xufVxuXG4vKipcbiAqIFdoZXRoZXIgdGhlIHJ1biBoYXMgYSBob29rIGFuZC9vciB3YWl0IHRoYXQgYW4gb3V0LW9mLWJhbmQgd3JpdGVyIGNvdWxkXG4gKiBhcHBlbmQgYW4gZXZlbnQgZm9yIGJldHdlZW4gYW4gaW5saW5lIHN0ZXAncyBgc3RlcF9jb21wbGV0ZWRgIHdyaXRlIGFuZFxuICogdGhlIG5leHQgcmVwbGF5IOKAlCBuYW1lbHkgYW4gb3BlbiBob29rIChhIGBob29rX2NyZWF0ZWRgIG5vdCB5ZXRcbiAqIGBob29rX2Rpc3Bvc2VkYCwgd2hpY2ggYSB3ZWJob29rIHJlY2VpdmVyIGNhbiByZXNvbHZlIHdpdGhcbiAqIGBob29rX3JlY2VpdmVkYCkgb3IgYW4gb3BlbiB3YWl0IChhIGB3YWl0X2NyZWF0ZWRgIG5vdCB5ZXRcbiAqIGB3YWl0X2NvbXBsZXRlZGAsIHdoaWNoIHRoZSB3YWl0IHRpbWVyIGNhbiByZXNvbHZlIHdpdGhcbiAqIGB3YWl0X2NvbXBsZXRlZGApLlxuICpcbiAqIFRoaXMgZ2F0ZXMgVk0gcmV0ZW50aW9uLCB0aGUgaW5saW5lLWRlbHRhIGZhc3QgcGF0aCwgYW5kIHR1cmJvJ3MgZm9yY2VkXG4gKiBvcHRpbWlzdGljIHN0YXJ0LiBBIHRlcm1pbmFsLXN0ZXAgZGVsdGEgY2FuIG9taXQgYW4gZXZlbnQgYXBwZW5kZWRcbiAqIGNvbmN1cnJlbnRseSBhZnRlciB0aGF0IHdyaXRlLiBXaXRoIG5vIG9wZW4gaG9vayBvciB3YWl0LCBvbmx5IGNhbmNlbGxhdGlvblxuICogY2FuIGRvIHNvLCBhbmQgb2JzZXJ2aW5nIGl0IG9uZSByZXBsYXkgbGF0ZSBpcyBzYWZlIGJlY2F1c2UgdGhlIG5leHQgZW50aXR5XG4gKiB3cml0ZSBpcyByZWplY3RlZC5cbiAqXG4gKiBTdGVwLWJvZHkgYGF0dHJfc2V0YCB3cml0ZXMgYXJlIE5PVCBhIGNvbmNlcm46IHRoZXkgbGFuZCBiZWZvcmUgdGhlXG4gKiBzdGVwJ3MgdGVybWluYWwgd3JpdGUgYW5kIGFyZSB0aGVyZWZvcmUgYWxyZWFkeSBpbnNpZGUgdGhlIHJldHVybmVkXG4gKiBkZWx0YS5cbiAqL1xuZnVuY3Rpb24gb3Blbkhvb2tBbmRXYWl0U3RhdGUoZXZlbnRzOiBFdmVudFtdKToge1xuICBvcGVuSG9vazogYm9vbGVhbjtcbiAgb3BlbldhaXQ6IGJvb2xlYW47XG59IHtcbiAgY29uc3QgaG9va3MgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgY29uc3Qgd2FpdHMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgZm9yIChjb25zdCBldmVudCBvZiBldmVudHMpIHtcbiAgICBzd2l0Y2ggKGV2ZW50LmV2ZW50VHlwZSkge1xuICAgICAgY2FzZSAnaG9va19jcmVhdGVkJzpcbiAgICAgICAgaG9va3MuYWRkKGV2ZW50LmNvcnJlbGF0aW9uSWQpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2hvb2tfZGlzcG9zZWQnOlxuICAgICAgICBob29rcy5kZWxldGUoZXZlbnQuY29ycmVsYXRpb25JZCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnd2FpdF9jcmVhdGVkJzpcbiAgICAgICAgd2FpdHMuYWRkKGV2ZW50LmNvcnJlbGF0aW9uSWQpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3dhaXRfY29tcGxldGVkJzpcbiAgICAgICAgd2FpdHMuZGVsZXRlKGV2ZW50LmNvcnJlbGF0aW9uSWQpO1xuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHsgb3Blbkhvb2s6IGhvb2tzLnNpemUgPiAwLCBvcGVuV2FpdDogd2FpdHMuc2l6ZSA+IDAgfTtcbn1cblxudHlwZSBSZXBsYXlFdmVudExvZyA9XG4gIHwgeyB0eXBlOiAnbG9hZEFsbCcgfVxuICB8ICh7IHR5cGU6ICdyZWFkeScgfSAmIExvYWRlZEV2ZW50TG9nKVxuICB8ICh7IHR5cGU6ICdsb2FkQWZ0ZXInOyBjdXJzb3I6IHN0cmluZyB9ICYgTG9hZGVkRXZlbnRMb2cpO1xuXG5mdW5jdGlvbiBuZXh0RXZlbnRMb2dMb2FkKGxvZzogTG9hZGVkRXZlbnRMb2cpOiBSZXBsYXlFdmVudExvZyB7XG4gIGlmIChsb2cuY3Vyc29yID09PSBudWxsKSB7XG4gICAgcmV0dXJuIHsgdHlwZTogJ2xvYWRBbGwnIH07XG4gIH1cbiAgcmV0dXJuIHtcbiAgICB0eXBlOiAnbG9hZEFmdGVyJyxcbiAgICBldmVudHM6IGxvZy5ldmVudHMsXG4gICAgY3Vyc29yOiBsb2cuY3Vyc29yLFxuICB9O1xufVxuXG5mdW5jdGlvbiBhcHBlbmRFdmVudExvZyhsb2c6IExvYWRlZEV2ZW50TG9nLCBhcHBlbmRlZDogTG9hZGVkRXZlbnRMb2cpOiB2b2lkIHtcbiAgYXBwZW5kVW5pcXVlRXZlbnRzKGxvZy5ldmVudHMsIGFwcGVuZGVkLmV2ZW50cyk7XG4gIGxvZy5jdXJzb3IgPSBhcHBlbmRlZC5jdXJzb3IgPz8gbG9nLmN1cnNvcjtcbn1cblxuLyoqXG4gKiBUaGUgd2hvbGUgcmV0ZW50aW9uIHByZWRpY2F0ZToga2VlcCB0aGUgc2Vzc2lvbiBvbmx5IGZvciBhIHB1cmUgc3RlcFxuICogYm91bmRhcnkgKGV2ZXJ5IHN1c3BlbnNpb24gaXRlbSBpcyBhIHN0ZXAg4oCUIGFueSBvdGhlciBpdGVtIHR5cGUsIHByZXNlbnRcbiAqIG9yIGZ1dHVyZSwgaXMgdW5yZXRhaW5hYmxlIGJ5IGRlZmF1bHQpIHdob3NlIG5ldyBzdGVwIGlucHV0cyBzZXJpYWxpemVkXG4gKiB3aXRob3V0IGV4ZWN1dGluZyB3b3JrZmxvdyBjb2RlLCB3aXRoIG5vIG91dC1vZi1iYW5kIGNvbnRpbnVhdGlvbiBzb3VyY2U6XG4gKiBhdHRyaWJ1dGVzIHJlcXVpcmUgcmVwbGF5OyBob29rcyBhbmQgd2FpdHMgY2FuIHdha2UgYW5vdGhlciBpbnZvY2F0aW9uLlxuICogYFdPUktGTE9XX1JFVEFJTkVEX1ZNPTBgIGRpc2FibGVzIHJldGVudGlvbiBlbnRpcmVseS5cbiAqXG4gKiBUaGUgb3BlbiBob29rL3dhaXQgc2NhbiBpcyBPKGV2ZW50cyksIHNvIGl0IGlzIHRha2VuIHRocm91Z2ggYSBsYXp5IGdldHRlclxuICogYW5kIGNvbnN1bHRlZCBsYXN0LCBhZnRlciBldmVyeSBjaGVhcCBjaGVjayBoYXMgcGFzc2VkLlxuICpcbiAqIElOVkFSSUFOVCB0aGlzIHByZWRpY2F0ZSBsZWFucyBvbjogZXZlcnkgc3VzcGVuc2lvbiBzaWduYWxlciB0aGF0IGRvZXMgTk9UXG4gKiBjYXJyeSB0aGUgc3RlcC1jb25zdW1lciBnZW5lcmF0aW9uIGd1YXJkIChzbGVlcCwgaG9vaywgYXR0cmlidXRlIOKAlCBzZWVcbiAqIGBzdXNwZW5zaW9uR2VuZXJhdGlvbmAgaW4gcHJpdmF0ZS50cykgbXVzdCBiZSB1bnJldGFpbmFibGUgaGVyZSwgZWl0aGVyIHZpYVxuICogYSBub24tc3RlcCBxdWV1ZSBpdGVtIG9yIHRoZSBvcGVuIGhvb2svd2FpdCBzY2FuLiBBIG5ldyBzaWduYWxlciB0aGF0XG4gKiBzYXRpc2ZpZXMgbmVpdGhlciB3b3VsZCBsZXQgYSBzdGFsZSBzaWduYWwgYmUgYWNjZXB0ZWQgYXMgYSBmcmVzaFxuICogc3VzcGVuc2lvbiBvbiBhIHJlc3VtZWQgc2Vzc2lvbi5cbiAqXG4gKiBRdWllc2NlbmNlIGFzc3VtZXMgd29ya2Zsb3cgY29kZSBzdGF5cyBpbnNpZGUgdGhlIHNhbmRib3gncyBkZXRlcm1pbmlzbVxuICogY29udHJhY3QuIEVzY2FwaW5nIHRvIHRoZSBob3N0IHJlYWxtIChlLmcuIHJlY292ZXJpbmcgdGhlIGhvc3QgYEZ1bmN0aW9uYFxuICogY29uc3RydWN0b3IgZnJvbSBhbiBleHBvc2VkIGhvc3QgY2xhc3MgdG8gc2NoZWR1bGUgcmVhbCB0aW1lcnMpIG1ha2VzIGFcbiAqIHdvcmtmbG93IG5vbmRldGVybWluaXN0aWMgdW5kZXIgb3JkaW5hcnkgcmVwbGF5IHRvbywgYW5kIGlzIG5vdCBkZWZlbmRlZFxuICogaGVyZS5cbiAqL1xuZnVuY3Rpb24gY2FuUmV0YWluV29ya2Zsb3dTZXNzaW9uKFxuICBzdXNwZW5zaW9uOiBXb3JrZmxvd1N1c3BlbnNpb24sXG4gIHN0ZXBJbnB1dHNTYWZlOiBib29sZWFuLFxuICBvcGVuSG9va1dhaXQ6IHsgdmFsdWU6IFJldHVyblR5cGU8dHlwZW9mIG9wZW5Ib29rQW5kV2FpdFN0YXRlPiB9XG4pOiBib29sZWFuIHtcbiAgaWYgKFxuICAgICFpc1ZtUmV0ZW50aW9uRW5hYmxlZCgpIHx8XG4gICAgIXN0ZXBJbnB1dHNTYWZlIHx8XG4gICAgc3VzcGVuc2lvbi5zdGVwcy5sZW5ndGggPT09IDAgfHxcbiAgICAhc3VzcGVuc2lvbi5zdGVwcy5ldmVyeSgoaXRlbSkgPT4gaXRlbS50eXBlID09PSAnc3RlcCcpXG4gICkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBjb25zdCB7IG9wZW5Ib29rLCBvcGVuV2FpdCB9ID0gb3Blbkhvb2tXYWl0LnZhbHVlO1xuICByZXR1cm4gIW9wZW5Ib29rICYmICFvcGVuV2FpdDtcbn1cblxuLyoqXG4gKiBNYXhpbXVtIGlubGluZS1leGVjdXRpb24gZHVyYXRpb24gZm9yIGEgc2luZ2xlIGhhbmRsZXIgaW52b2NhdGlvbi5cbiAqXG4gKiBPcmRlciBvZiBwcmVjZWRlbmNlOlxuICogMS4gYFdPUktGTE9XX1YyX1RJTUVPVVRfTVNgIGVudiB2YXJcbiAqIDIuIFRpZXJlZCBidWRnZXQgZGVyaXZlZCBmcm9tIGB3b3JsZC5nZXRSdW50aW1lRGVhZGxpbmUoKWBcbiAqIDMuIERlZmF1bHQgb2YgMiBtaW51dGVzXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGdldE1heElubGluZUR1cmF0aW9uTXMoXG4gIHdvcmxkOiBXb3JsZCxcbiAgaW52b2NhdGlvblN0YXJ0VGltZTogbnVtYmVyXG4pOiBQcm9taXNlPG51bWJlcj4ge1xuICBjb25zdCByYXdFbnZPdmVycmlkZSA9IHByb2Nlc3MuZW52LldPUktGTE9XX1YyX1RJTUVPVVRfTVM7XG4gIGlmIChyYXdFbnZPdmVycmlkZSAhPT0gdW5kZWZpbmVkICYmIHJhd0Vudk92ZXJyaWRlICE9PSAnJykge1xuICAgIGNvbnN0IHBhcnNlZCA9IE51bWJlcihyYXdFbnZPdmVycmlkZSk7XG4gICAgaWYgKE51bWJlci5pc0Zpbml0ZShwYXJzZWQpICYmIHBhcnNlZCA+IDApIHtcbiAgICAgIHJldHVybiBwYXJzZWQ7XG4gICAgfVxuICB9XG5cbiAgY29uc3QgcnVudGltZURlYWRsaW5lID0gYXdhaXQgd29ybGQuZ2V0UnVudGltZURlYWRsaW5lPy4oKTtcbiAgaWYgKHJ1bnRpbWVEZWFkbGluZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgY29uc3QgZGVhZGxpbmVNcyA9IHJ1bnRpbWVEZWFkbGluZS5nZXRUaW1lKCk7XG4gICAgaWYgKCFOdW1iZXIuaXNOYU4oZGVhZGxpbmVNcykpIHtcbiAgICAgIGNvbnN0IG1heER1cmF0aW9uTXMgPSBNYXRoLmZsb29yKGRlYWRsaW5lTXMgLSBpbnZvY2F0aW9uU3RhcnRUaW1lKTtcbiAgICAgIGlmIChtYXhEdXJhdGlvbk1zID49IG1zKCcyNW0nKSkge1xuICAgICAgICByZXR1cm4gbXMoJzEwbScpO1xuICAgICAgfVxuXG4gICAgICBpZiAobWF4RHVyYXRpb25NcyA+PSBtcygnMTBtJykpIHtcbiAgICAgICAgcmV0dXJuIG1zKCc1bScpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBtcygnMm0nKTtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgc2luZ2xlIHJvdXRlIHdoaWNoIGhhbmRsZXMgd29ya2Zsb3cgZXhlY3V0aW9uIHJlcXVlc3RzLFxuICogZXhlY3V0aW5nIHN0ZXBzIGlubGluZSB3aGVuIHBvc3NpYmxlIHRvIHJlZHVjZSBmdW5jdGlvbiBpbnZvY2F0aW9uc1xuICogYW5kIHF1ZXVlIG92ZXJoZWFkLlxuICpcbiAqIFRoZSBoYW5kbGVyIGxvb3BzOiByZXBsYXkgd29ya2Zsb3cg4oaSIGV4ZWN1dGUgc3RlcCBpbmxpbmUg4oaSIHJlcGxheSDihpIgLi4uXG4gKiB1bnRpbCB0aGUgd29ya2Zsb3cgY29tcGxldGVzLCB0aW1lcyBvdXQsIG9yIGVuY291bnRlcnMgbm9uLXN0ZXAgc3VzcGVuc2lvbnMuXG4gKlxuICogQHBhcmFtIHdvcmtmbG93Q29kZSAtIFRoZSB3b3JrZmxvdyBidW5kbGUgY29kZSBjb250YWluaW5nIGFsbCB3b3JrZmxvdyBmdW5jdGlvbnNcbiAqIEByZXR1cm5zIEEgZnVuY3Rpb24gdGhhdCBjYW4gYmUgdXNlZCBhcyBhIFZlcmNlbCBBUEkgcm91dGVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHdvcmtmbG93RW50cnlwb2ludChcbiAgd29ya2Zsb3dDb2RlOiBzdHJpbmcsXG4gIG9wdGlvbnM/OiB7XG4gICAgbmFtZXNwYWNlPzogc3RyaW5nO1xuICAgIHJvdXRlTW9kdWxlQm9keVN0YXJ0ZWRBdD86IG51bWJlcjtcbiAgICBiYXNlUGF0aD86IHN0cmluZztcbiAgfVxuKTogKHJlcTogUmVxdWVzdCkgPT4gUHJvbWlzZTxSZXNwb25zZT4ge1xuICBzZXRXb3JrZmxvd0Jhc2VQYXRoKG9wdGlvbnM/LmJhc2VQYXRoKTtcblxuICBjb25zdCBuYW1lc3BhY2UgPSByZXNvbHZlUXVldWVOYW1lc3BhY2Uob3B0aW9ucz8ubmFtZXNwYWNlKTtcbiAgY29uc3Qgd29ya2Zsb3dQcmVmaXggPSBnZXRRdWV1ZVRvcGljUHJlZml4KCd3b3JrZmxvdycsIG5hbWVzcGFjZSk7XG5cbiAgY29uc3QgaGFuZGxlciA9ICh3b3JsZEhhbmRsZXJzOiBXb3JsZEhhbmRsZXJzKSA9PlxuICAgIHdvcmxkSGFuZGxlcnMuY3JlYXRlUXVldWVIYW5kbGVyKFxuICAgICAgd29ya2Zsb3dQcmVmaXgsXG4gICAgICBhc3luYyAobWVzc2FnZV8sIG1ldGFkYXRhKSA9PiB7XG4gICAgICAgIC8vIENoZWNrIGlmIHRoaXMgaXMgYSBoZWFsdGggY2hlY2sgbWVzc2FnZVxuICAgICAgICAvLyBOT1RFOiBIZWFsdGggY2hlY2sgbWVzc2FnZXMgYXJlIGludGVudGlvbmFsbHkgdW5hdXRoZW50aWNhdGVkIGZvciBtb25pdG9yaW5nIHB1cnBvc2VzLlxuICAgICAgICAvLyBUaGV5IG9ubHkgd3JpdGUgYSBzaW1wbGUgc3RhdHVzIHJlc3BvbnNlIHRvIGEgc3RyZWFtIGFuZCBkbyBub3QgZXhwb3NlIHNlbnNpdGl2ZSBkYXRhLlxuICAgICAgICAvLyBUaGUgc3RyZWFtIG5hbWUgaW5jbHVkZXMgYSB1bmlxdWUgY29ycmVsYXRpb25JZCB0aGF0IG11c3QgYmUga25vd24gYnkgdGhlIGNhbGxlci5cbiAgICAgICAgY29uc3QgaGVhbHRoQ2hlY2sgPSBwYXJzZUhlYWx0aENoZWNrUGF5bG9hZChtZXNzYWdlXyk7XG4gICAgICAgIGlmIChoZWFsdGhDaGVjaykge1xuICAgICAgICAgIGF3YWl0IGhhbmRsZUhlYWx0aENoZWNrTWVzc2FnZShcbiAgICAgICAgICAgIGhlYWx0aENoZWNrLFxuICAgICAgICAgICAgd29ybGRIYW5kbGVycy5zcGVjVmVyc2lvblxuICAgICAgICAgICk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgIHRyYWNlQ2FycmllcjogaW5jb21pbmdUcmFjZUNhcnJpZXIsXG4gICAgICAgICAgcmVxdWVzdGVkQXQsXG4gICAgICAgICAgc3RlcElkOiBpbmNvbWluZ1N0ZXBJZCxcbiAgICAgICAgICBzdGVwTmFtZTogaW5jb21pbmdTdGVwTmFtZSxcbiAgICAgICAgICByZXBsYXlEaXZlcmdlbmNlLFxuICAgICAgICAgIHByZWNvbmRpdGlvblJlaW52b2NhdGlvbnMsXG4gICAgICAgICAgZGVwbG95bWVudE1pc21hdGNoUmV0cnlDb3VudCxcbiAgICAgICAgICBydW5JbnB1dCxcbiAgICAgICAgICBob29rSW5wdXQsXG4gICAgICAgIH0gPSBXb3JrZmxvd0ludm9rZVBheWxvYWRTY2hlbWEucGFyc2UobWVzc2FnZV8pO1xuICAgICAgICAvLyBgc3RhcnQoKWAgYWx3YXlzIGF0dGFjaGVzIGEgdHJhY2UgY2FycmllciwgYnV0XG4gICAgICAgIC8vIHNlcmlhbGl6ZVRyYWNlQ2FycmllcigpIHJldHVybnMgYHt9YCB3aGVuIG5vIE9URUwgU0RLIGlzIHJlZ2lzdGVyZWRcbiAgICAgICAgLy8gb3Igbm8gc3BhbiBpcyBhY3RpdmUg4oCUIHRyZWF0IGFuIGVtcHR5IGNhcnJpZXIgdGhlIHNhbWUgYXMgYW5cbiAgICAgICAgLy8gYWJzZW50IG9uZSBzbyBsaW5rZWQgbW9kZSBmYWxscyBiYWNrIHRvIGEgZnJlc2ggb3JpZ2luIGluc3RlYWQgb2ZcbiAgICAgICAgLy8gZm9yd2FyZGluZyBhIHVzZWxlc3MgYHt9YCBmb3JldmVyLlxuICAgICAgICBjb25zdCB0cmFjZUNvbnRleHQgPSBpc1VzYWJsZVRyYWNlQ2FycmllcihpbmNvbWluZ1RyYWNlQ2FycmllcilcbiAgICAgICAgICA/IGluY29taW5nVHJhY2VDYXJyaWVyXG4gICAgICAgICAgOiB1bmRlZmluZWQ7XG4gICAgICAgIGNvbnN0IHsgcmVxdWVzdElkIH0gPSBtZXRhZGF0YTtcbiAgICAgICAgY29uc3Qgd29ya2Zsb3dOYW1lID0gbWV0YWRhdGEucXVldWVOYW1lLnNsaWNlKHdvcmtmbG93UHJlZml4Lmxlbmd0aCk7XG5cbiAgICAgICAgLy8gLS0tIE1heCBkZWxpdmVyeSBjaGVjayAtLS1cbiAgICAgICAgLy8gRW5mb3JjZSBtYXggZGVsaXZlcnkgbGltaXQgYmVmb3JlIGFueSBpbmZyYXN0cnVjdHVyZSBjYWxscy5cbiAgICAgICAgLy8gVGhpcyBwcmV2ZW50cyBydW5hd2F5IHdvcmtmbG93cyBmcm9tIGNvbnN1bWluZyBpbmZpbml0ZSBxdWV1ZSBkZWxpdmVyaWVzLlxuICAgICAgICAvLyBTY29wZWQgbG9nZ2VyIGZvciB0aGlzIHJ1biDigJQgYXR0YWNoZXMgcnVuSWQvd29ya2Zsb3dOYW1lIHRvIGV2ZXJ5XG4gICAgICAgIC8vIGxvZyBsaW5lIGFuZCBjaGlsZCBsb2dnZXJzIGJlbG93LCBzbyBjYWxsZXJzIGRvbid0IHJlcGVhdCBpdC5cbiAgICAgICAgY29uc3QgcnVuTG9nZ2VyID0gcnVudGltZUxvZ2dlci5mb3JSdW4ocnVuSWQsIHdvcmtmbG93TmFtZSk7XG5cbiAgICAgICAgY29uc3QgbWF4UXVldWVEZWxpdmVyaWVzID0gZ2V0TWF4UXVldWVEZWxpdmVyaWVzKCk7XG4gICAgICAgIGlmIChtZXRhZGF0YS5hdHRlbXB0ID4gbWF4UXVldWVEZWxpdmVyaWVzKSB7XG4gICAgICAgICAgY29uc3QgbWF4RGVsaXZlcmllc0Rlc2NyaXB0aW9uID0gZGVzY3JpYmVFcnJvcihcbiAgICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICAgIFJVTl9FUlJPUl9DT0RFUy5NQVhfREVMSVZFUklFU19FWENFRURFRFxuICAgICAgICAgICk7XG4gICAgICAgICAgcnVuTG9nZ2VyLmVycm9yKFxuICAgICAgICAgICAgYFdvcmtmbG93IGhhbmRsZXIgZXhjZWVkZWQgbWF4IGRlbGl2ZXJpZXMgKCR7bWV0YWRhdGEuYXR0ZW1wdH0vJHttYXhRdWV1ZURlbGl2ZXJpZXN9KWAsXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGF0dGVtcHQ6IG1ldGFkYXRhLmF0dGVtcHQsXG4gICAgICAgICAgICAgIGVycm9yQ29kZTogbWF4RGVsaXZlcmllc0Rlc2NyaXB0aW9uLmVycm9yQ29kZSxcbiAgICAgICAgICAgICAgZXJyb3JBdHRyaWJ1dGlvbjogbWF4RGVsaXZlcmllc0Rlc2NyaXB0aW9uLmF0dHJpYnV0aW9uLFxuICAgICAgICAgICAgfVxuICAgICAgICAgICk7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHdvcmxkID0gYXdhaXQgZ2V0V29ybGQoKTtcbiAgICAgICAgICAgIGNvbnN0IGdldEVuY3J5cHRpb25LZXkgPSBtZW1vaXplRW5jcnlwdGlvbktleSh3b3JsZCwgcnVuSWQpO1xuICAgICAgICAgICAgY29uc3QgZXJyID0gbmV3IEZhdGFsRXJyb3IoXG4gICAgICAgICAgICAgIGBXb3JrZmxvdyBleGNlZWRlZCBtYXhpbXVtIHF1ZXVlIGRlbGl2ZXJpZXMgKCR7bWV0YWRhdGEuYXR0ZW1wdH0vJHttYXhRdWV1ZURlbGl2ZXJpZXN9KWBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKFxuICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGV2ZW50VHlwZTogJ3J1bl9mYWlsZWQnLFxuICAgICAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgICAgICAgIGVycm9yOiBhd2FpdCBkZWh5ZHJhdGVSdW5FcnJvcihcbiAgICAgICAgICAgICAgICAgICAgZXJyLFxuICAgICAgICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgZ2V0RW5jcnlwdGlvbktleSgpXG4gICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgZXJyb3JDb2RlOiBSVU5fRVJST1JfQ09ERVMuTUFYX0RFTElWRVJJRVNfRVhDRUVERUQsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgeyByZXF1ZXN0SWQgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKGVycikgfHwgUnVuRXhwaXJlZEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgICAgLy8gUnVuIGFscmVhZHkgZmluaXNoZWQsIGNvbnN1bWUgdGhlIG1lc3NhZ2Ugc2lsZW50bHlcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcnVuTG9nZ2VyLmVycm9yKFxuICAgICAgICAgICAgICBgRmFpbGVkIHRvIG1hcmsgcnVuIGFzIGZhaWxlZCBhZnRlciAke21ldGFkYXRhLmF0dGVtcHR9IGRlbGl2ZXJ5IGF0dGVtcHRzLiBgICtcbiAgICAgICAgICAgICAgICBgQSBwZXJzaXN0ZW50IGVycm9yIGlzIHByZXZlbnRpbmcgdGhlIHJ1biBmcm9tIGJlaW5nIHRlcm1pbmF0ZWQuIGAgK1xuICAgICAgICAgICAgICAgIGBUaGUgcnVuIHdpbGwgcmVtYWluIGluIGl0cyBjdXJyZW50IHN0YXRlIHVudGlsIG1hbnVhbGx5IHJlc29sdmVkLiBgICtcbiAgICAgICAgICAgICAgICBgVGhpcyBpcyBtb3N0IGxpa2VseSBkdWUgdG8gYSBwZXJzaXN0ZW50IG91dGFnZSBvZiB0aGUgd29ya2Zsb3cgYmFja2VuZCBgICtcbiAgICAgICAgICAgICAgICBgb3IgYSBidWcgaW4gdGhlIHdvcmtmbG93IHJ1bnRpbWUgYW5kIHNob3VsZCBiZSByZXBvcnRlZCB0byB0aGUgV29ya2Zsb3cgdGVhbS5gLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgYXR0ZW1wdDogbWV0YWRhdGEuYXR0ZW1wdCxcbiAgICAgICAgICAgICAgICBlcnJvck5hbWU6IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm5hbWUgOiAnVW5rbm93bkVycm9yJyxcbiAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2U6IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKSxcbiAgICAgICAgICAgICAgICBlcnJvclN0YWNrOiBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5zdGFjayA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gLS0tIFRyYWNlIGNvcnJlbGF0aW9uIG1vZGUgLS0tXG4gICAgICAgIC8vICdsaW5rZWQnIChkZWZhdWx0KTogdGhlIHdvcmtmbG93LmV4ZWN1dGUgc3BhbiBiZWxvdyBzdGF5cyBhIENISUxEXG4gICAgICAgIC8vIG9mIHRoZSBsb2NhbCBkZWxpdmVyeSAoZmxvdy1yb3V0ZSkgY29udGV4dCwgc28gb25lIGludm9jYXRpb24g4oCUXG4gICAgICAgIC8vIHJvdXRlIGhhbmRsZXIsIHdvcmtmbG93IHJlcGxheSwgaW5saW5lIHN0ZXBzLCBldmVudCB3cml0ZXMg4oCUIGlzIGFcbiAgICAgICAgLy8gc2luZ2xlIGJvdW5kZWQgdHJhY2UuIFRoZSBydW4tb3JpZ2luIGNvbnRleHQgdHJhdmVscyBhcyBhIHNwYW5cbiAgICAgICAgLy8gTElOSyAobm90IGEgcGFyZW50KSwgYW5kIHJlLWVucXVldWVzIGZvcndhcmQgdGhlIG9yaWdpbmFsIGNhcnJpZXJcbiAgICAgICAgLy8gdW5jaGFuZ2VkLCBzbyBhIChwb3RlbnRpYWxseSBob3Vycy1sb25nKSBydW4gaXMgbmV2ZXIgc3RpdGNoZWRcbiAgICAgICAgLy8gaW50byBvbmUgZ2lhbnQgdHJhY2UgYWNyb3NzIGludm9jYXRpb25zLlxuICAgICAgICAvLyAnY29udGludW91cyc6IGxlZ2FjeSBiZWhhdmlvciDigJQgdGhlIHJlc3RvcmVkIHJ1bi1vcmlnaW4gY29udGV4dFxuICAgICAgICAvLyBiZWNvbWVzIHRoZSBwYXJlbnQgb2YgdGhpcyBpbnZvY2F0aW9uJ3Mgc3BhbnMuXG4gICAgICAgIGNvbnN0IHRyYWNlTW9kZSA9IGdldFdvcmtmbG93VHJhY2VNb2RlKCk7XG5cbiAgICAgICAgLy8gVHJhY2UgY2FycmllciB0byBhdHRhY2ggdG8gbWVzc2FnZXMgdGhpcyBpbnZvY2F0aW9uIGVucXVldWVzIOKAlFxuICAgICAgICAvLyBzZWUgZ2V0TmV4dFRyYWNlQ2FycmllciBmb3IgdGhlIGxpbmtlZC9jb250aW51b3VzIHNlbWFudGljcy5cbiAgICAgICAgY29uc3QgbmV4dFRyYWNlQ2FycmllciA9ICgpOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIHN0cmluZz4+ID0+XG4gICAgICAgICAgZ2V0TmV4dFRyYWNlQ2Fycmllcih0cmFjZU1vZGUsIHRyYWNlQ29udGV4dCk7XG5cbiAgICAgICAgLy8gU3BhbiBsaW5rcyB0byB0aGUgaW5jb21pbmcgZGVsaXZlcnkgY29udGV4dCBhbmQgKGluIGxpbmtlZCBtb2RlKVxuICAgICAgICAvLyB0aGUgcnVuLW9yaWdpbiBjb250ZXh0IGZyb20gdGhlIHRyYWNlIGNhcnJpZXIuXG4gICAgICAgIGNvbnN0IHNwYW5MaW5rcyA9IGF3YWl0IGJ1aWxkSW52b2NhdGlvblNwYW5MaW5rcyhcbiAgICAgICAgICB0cmFjZU1vZGUsXG4gICAgICAgICAgdHJhY2VDb250ZXh0XG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gVGhlIHJlcGxheSBidWRnZXQgY292ZXJzIG9yY2hlc3RyYXRpb24gd29yayBiZXR3ZWVuIHN0ZXBzLCBub3QgaW5saW5lXG4gICAgICAgIC8vIHN0ZXAgYm9kaWVzLiBJdCBpcyBjaGVja2VkIGJldHdlZW4gbG9vcCBpdGVyYXRpb25zOyBzdGVwIGJvZGllcyB1c2VcbiAgICAgICAgLy8gdGhlIHBsYXRmb3JtIHRpbWVvdXQgYW5kIE5PX0lOTElORV9SRVBMQVlfQUZURVJfTVMgZ3VhcmQgaW5zdGVhZC5cbiAgICAgICAgY29uc3QgcmVwbGF5QnVkZ2V0ID0gbmV3IFJlcGxheUJ1ZGdldCgpO1xuXG4gICAgICAgIC8vIEluIGxpbmtlZCBtb2RlIHRoZSBydW4tb3JpZ2luIGNvbnRleHQgaXMgTk9UIHJlc3RvcmVkIGFzIHRoZVxuICAgICAgICAvLyBhY3RpdmUgKHBhcmVudCkgY29udGV4dCDigJQgcGFzc2luZyBgdW5kZWZpbmVkYCBtYWtlc1xuICAgICAgICAvLyB3aXRoVHJhY2VDb250ZXh0IGEgcGFzc3Rocm91Z2gsIHNvIHRoZSB3b3JrZmxvdy5leGVjdXRlIHNwYW4gYmVsb3dcbiAgICAgICAgLy8gc3RheXMgYSBjaGlsZCBvZiB0aGUgbG9jYWwgZGVsaXZlcnkgKGZsb3ctcm91dGUpIGNvbnRleHQgYW5kIHRoZVxuICAgICAgICAvLyBydW4tb3JpZ2luIHRyYXZlbHMgYXMgYSBzcGFuIGxpbmsgaW5zdGVhZC5cbiAgICAgICAgY29uc3QgcGFyZW50VHJhY2VDYXJyaWVyID1cbiAgICAgICAgICB0cmFjZU1vZGUgPT09ICdjb250aW51b3VzJyA/IHRyYWNlQ29udGV4dCA6IHVuZGVmaW5lZDtcbiAgICAgICAgLy8gUXVldWUtZGVsaXZlcmVkIGludm9jYXRpb246IENPTlNVTUVSIGtpbmQsIG1hdGNoaW5nIHRoZVxuICAgICAgICAvLyBxdWV1ZS1kZWxpdmVyZWQgc3RlcC5leGVjdXRlIHNwYW4uXG4gICAgICAgIGNvbnN0IHNwYW5LaW5kID0gYXdhaXQgZ2V0U3BhbktpbmQoJ0NPTlNVTUVSJyk7XG4gICAgICAgIHJldHVybiBhd2FpdCB3aXRoVHJhY2VDb250ZXh0KHBhcmVudFRyYWNlQ2FycmllciwgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIHJldHVybiBhd2FpdCB3aXRoV29ya2Zsb3dCYWdnYWdlKFxuICAgICAgICAgICAgeyB3b3JrZmxvd1J1bklkOiBydW5JZCwgd29ya2Zsb3dOYW1lIH0sXG4gICAgICAgICAgICBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgIGNvbnN0IHdvcmxkID0gYXdhaXQgdHJhY2UoJ3dvcmtmbG93LnJvdXRlLmdldF93b3JsZCcsIGFzeW5jICgpID0+XG4gICAgICAgICAgICAgICAgZ2V0V29ybGQoKVxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAvLyBCb3RoIGNoZWNrcyBiZWxvdyBsb29rIGF0IGBydW5JbnB1dGAsIHNvIGJvdGggYXJlIG5vLW9wcyBvbiBhXG4gICAgICAgICAgICAgIC8vIHJlLWVucXVldWVkIG1lc3NhZ2UgKHdoaWNoIGNhcnJpZXMgbm9uZSkg4oCUIHRoZXkgb25seSBldmVyIHJ1biBvblxuICAgICAgICAgICAgICAvLyBhIGZpcnN0IGRlbGl2ZXJ5LCB0aGUgb25lIHRoYXQgY291bGQgY3JlYXRlIHRoZSBydW4uXG4gICAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAgIC8vIFJldHVybmluZyBhY2tzIHRoZSBtZXNzYWdlLiBUaGF0IGlzIGRlbGliZXJhdGU6IHRoZSBtaXNtYXRjaCBpc1xuICAgICAgICAgICAgICAvLyBiYWtlZCBpbnRvIHRoaXMgbWVzc2FnZSwgc28gZXZlcnkgcmVkZWxpdmVyeSB3b3VsZCByZWFjaCB0aGVcbiAgICAgICAgICAgICAgLy8gc2FtZSB2ZXJkaWN0LCBhbmQgdGhyb3dpbmcgd291bGQganVzdCBob3QtbG9vcCB0aGUgaGFuZGxlciB1bnRpbFxuICAgICAgICAgICAgICAvLyBNQVhfUVVFVUVfREVMSVZFUklFUyB3aXRoIHRoZSBzYW1lIGVycm9yIGVhY2ggdGltZS4gSXQgbWF0Y2hlc1xuICAgICAgICAgICAgICAvLyBob3cgdGhlIHJ1bl9zdGFydGVkIHBhdGggYWxyZWFkeSBkaXNjYXJkcyBkZWxpdmVyaWVzIHdob3NlXG4gICAgICAgICAgICAgIC8vIHZlcmRpY3QgY2Fubm90IGNoYW5nZSAoRW50aXR5Q29uZmxpY3RFcnJvciwgUnVuRXhwaXJlZEVycm9yKS5cbiAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgIHJlZnVzZUNyb3NzRW52aXJvbm1lbnREZWxpdmVyeSh7XG4gICAgICAgICAgICAgICAgICB3b3JsZCxcbiAgICAgICAgICAgICAgICAgIHJ1bklucHV0LFxuICAgICAgICAgICAgICAgICAgcnVuSWQsXG4gICAgICAgICAgICAgICAgICBydW5Mb2dnZXIsXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIC8vIERpYWdub3N0aWMgb25seSDigJQgc2VlIHRoZSBoZWxwZXIgZm9yIHdoeSB0aGlzIHdhcm5zIGluc3RlYWQgb2ZcbiAgICAgICAgICAgICAgLy8gcmVmdXNpbmcgdGhlIGludm9jYXRpb24uXG4gICAgICAgICAgICAgIGF3YWl0IHdhcm5PbkRlcGxveW1lbnRQaW5uaW5nTWlzbWF0Y2goe1xuICAgICAgICAgICAgICAgIHdvcmxkLFxuICAgICAgICAgICAgICAgIHJ1bklucHV0LFxuICAgICAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgICAgIHJ1bkxvZ2dlcixcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIHJldHVybiB0cmFjZShcbiAgICAgICAgICAgICAgICBgd29ya2Zsb3cuZXhlY3V0ZSAke3dvcmtmbG93RGlzcGxheU5hbWUod29ya2Zsb3dOYW1lKX1gLFxuICAgICAgICAgICAgICAgIHsga2luZDogc3BhbktpbmQsIGxpbmtzOiBzcGFuTGlua3MgfSxcbiAgICAgICAgICAgICAgICBhc3luYyAoc3BhbikgPT4ge1xuICAgICAgICAgICAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd05hbWUod29ya2Zsb3dOYW1lKSxcbiAgICAgICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLldvcmtmbG93T3BlcmF0aW9uKCdleGVjdXRlX3YyJyksXG4gICAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5NZXNzYWdpbmdTeXN0ZW0oJ3ZlcmNlbC1xdWV1ZScpLFxuICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuTWVzc2FnaW5nRGVzdGluYXRpb25OYW1lKG1ldGFkYXRhLnF1ZXVlTmFtZSksXG4gICAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5NZXNzYWdpbmdNZXNzYWdlSWQobWV0YWRhdGEubWVzc2FnZUlkKSxcbiAgICAgICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLk1lc3NhZ2luZ09wZXJhdGlvblR5cGUoJ3Byb2Nlc3MnKSxcbiAgICAgICAgICAgICAgICAgICAgLi4uZ2V0UXVldWVPdmVyaGVhZCh7IHJlcXVlc3RlZEF0IH0pLFxuICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dSdW5JZChydW5JZCksXG4gICAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd1RyYWNlUHJvcGFnYXRlZCghIXRyYWNlQ29udGV4dCksXG4gICAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd1RyYWNlTW9kZSh0cmFjZU1vZGUpLFxuICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgIGNvbnN0IGludm9jYXRpb25TdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgICAgICAgICAgICAgY29uc3Qgbm9JbmxpbmVSZXBsYXlBZnRlck1zID0gYXdhaXQgZ2V0TWF4SW5saW5lRHVyYXRpb25NcyhcbiAgICAgICAgICAgICAgICAgICAgd29ybGQsXG4gICAgICAgICAgICAgICAgICAgIGludm9jYXRpb25TdGFydFRpbWVcbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICBsZXQgbG9vcEl0ZXJhdGlvbiA9IDA7XG4gICAgICAgICAgICAgICAgICBjb25zdCByZXBsYXlSZWNvdmVyeVJlcG9ydGVyID0gcmVwbGF5RGl2ZXJnZW5jZVxuICAgICAgICAgICAgICAgICAgICA/IG5ldyBSZXBsYXlSZWNvdmVyeVJlcG9ydGVyKHJlcGxheURpdmVyZ2VuY2UuY291bnQpXG4gICAgICAgICAgICAgICAgICAgIDogUmVwbGF5UmVjb3ZlcnlSZXBvcnRlci5pbmVydCgpO1xuICAgICAgICAgICAgICAgICAgLy8gRXZlcnkgd3JpdGUgdGhpcyBsb29wIG1ha2VzIGNhcnJpZXMgdGhlIGN1cnNvciBvZiB0aGUgbG9nXG4gICAgICAgICAgICAgICAgICAvLyBpdCB3YXMgY29tcHV0ZWQgYWdhaW5zdCwgYW5kIGZvbGRzIGEgY29tcGxldGUgcmV0dXJuZWRcbiAgICAgICAgICAgICAgICAgIC8vIGRlbHRhIGludG8gdGhhdCBsb2cuXG4gICAgICAgICAgICAgICAgICBjb25zdCBjcmVhdGVFdmVudCA9IGFzeW5jIDxUIGV4dGVuZHMgQ3JlYXRlRXZlbnRSZXF1ZXN0PihcbiAgICAgICAgICAgICAgICAgICAgZGF0YTogVCxcbiAgICAgICAgICAgICAgICAgICAgcGFyYW1zPzogQ3JlYXRlRXZlbnRQYXJhbXNcbiAgICAgICAgICAgICAgICAgICkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzaW5jZUN1cnNvciA9IGRlbHRhUmVxdWVzdEN1cnNvcihkYXRhLCBwYXJhbXMpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCByZXBsYXlSZWNvdmVyeVJlcG9ydGVyLndpdGhFdmVudENyZWF0ZShcbiAgICAgICAgICAgICAgICAgICAgICBzaW5jZUN1cnNvciA9PT0gdW5kZWZpbmVkXG4gICAgICAgICAgICAgICAgICAgICAgICA/IHBhcmFtc1xuICAgICAgICAgICAgICAgICAgICAgICAgOiB7IC4uLnBhcmFtcywgc2luY2VDdXJzb3IgfSxcbiAgICAgICAgICAgICAgICAgICAgICAocCkgPT4gd29ybGQuZXZlbnRzLmNyZWF0ZShydW5JZCwgZGF0YSwgcClcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNpbmNlQ3Vyc29yICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICBhYnNvcmJDcmVhdGVEZWx0YShzaW5jZUN1cnNvciwgcmVzdWx0KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgICAgICAgKiBUaGUgY3Vyc29yIHRvIGFzayBmb3IgYW4gaW5saW5lIGRlbHRhIGFnYWluc3QsIG9yXG4gICAgICAgICAgICAgICAgICAgKiB1bmRlZmluZWQgdG8gbm90IGFzay5cbiAgICAgICAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgICAgICAgKiBUdXJibyBpcyBleGNsdWRlZCBvbiBwdXJwb3NlOiBpdCBleGlzdHMgdG8gbWFrZSB0aGUgZmlyc3RcbiAgICAgICAgICAgICAgICAgICAqIGludm9jYXRpb24ncyB3cml0ZXMgYXMgY2hlYXAgYXMgcG9zc2libGUsIGFuZCBpdCBoYXMgbm9cbiAgICAgICAgICAgICAgICAgICAqIGxvYWRlZCBsb2cgdG8gZXh0ZW5kLiBSdW4tdGVybWluYWwgd3JpdGVzIGFyZSBleGNsdWRlZFxuICAgICAgICAgICAgICAgICAgICogYmVjYXVzZSBub3RoaW5nIHJlYWRzIHRoZSBsb2cgYWZ0ZXJ3YXJkcywgc28gdGhlIGRlbHRhXG4gICAgICAgICAgICAgICAgICAgKiB3b3VsZCBiZSB3b3JrIHRoZSBXb3JsZCBkb2VzIGZvciBubyBvbmUuIEEgY2FsbGVyIHRoYXRcbiAgICAgICAgICAgICAgICAgICAqIHNldCBpdHMgb3duIGBzaW5jZUN1cnNvcmAgKG9yIGFza2VkIGZvciB0aGUgYHJ1bl9zdGFydGVkYFxuICAgICAgICAgICAgICAgICAgICogLyBgaG9va19yZWNlaXZlZGAgcHJlbG9hZCwgd2hpY2ggb3ducyB0aGUgc2FtZSByZXNwb25zZVxuICAgICAgICAgICAgICAgICAgICogZmllbGRzKSBrZWVwcyB3aGF0IGl0IGFza2VkIGZvci5cbiAgICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgICAgY29uc3QgZGVsdGFSZXF1ZXN0Q3Vyc29yID0gKFxuICAgICAgICAgICAgICAgICAgICBkYXRhOiBDcmVhdGVFdmVudFJlcXVlc3QsXG4gICAgICAgICAgICAgICAgICAgIHBhcmFtczogQ3JlYXRlRXZlbnRQYXJhbXMgfCB1bmRlZmluZWRcbiAgICAgICAgICAgICAgICAgICk6IHN0cmluZyB8IHVuZGVmaW5lZCA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgICB0dXJibyB8fFxuICAgICAgICAgICAgICAgICAgICAgIGV2ZW50TG9nLnR5cGUgIT09ICdyZWFkeScgfHxcbiAgICAgICAgICAgICAgICAgICAgICBwYXJhbXM/LnNpbmNlQ3Vyc29yICE9PSB1bmRlZmluZWQgfHxcbiAgICAgICAgICAgICAgICAgICAgICBwYXJhbXM/LnByZWxvYWRFdmVudHMgPT09IHRydWUgfHxcbiAgICAgICAgICAgICAgICAgICAgICBpc1Rlcm1pbmFsUnVuRXZlbnRUeXBlKGRhdGEuZXZlbnRUeXBlKVxuICAgICAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBldmVudExvZy5jdXJzb3IgPz8gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgICAgICAgKiBGb2xkIGFuIGlubGluZSBkZWx0YSByZXR1cm5lZCBieSBgZXZlbnRzLmNyZWF0ZWAgaW50byB0aGVcbiAgICAgICAgICAgICAgICAgICAqIGluLW1lbW9yeSBldmVudCBsb2cuXG4gICAgICAgICAgICAgICAgICAgKlxuICAgICAgICAgICAgICAgICAgICogVGhlIGRlbHRhIGlzIHdoYXQgYGV2ZW50cy5saXN0KHsgY3Vyc29yOiBzZW50Q3Vyc29yIH0pYFxuICAgICAgICAgICAgICAgICAgICogd291bGQgaGF2ZSByZXR1cm5lZCByaWdodCBhZnRlciB0aGUgd3JpdGUsIHNvIGl0IGNhcnJpZXNcbiAgICAgICAgICAgICAgICAgICAqIGJhY2sgYm90aCBvdXIgb3duIGV2ZW50IGFuZCBhbnl0aGluZyBhbm90aGVyIHdyaXRlclxuICAgICAgICAgICAgICAgICAgICogYXBwZW5kZWQgaW4gYmFuZC4gQWJzb3JiaW5nIGl0IGhlcmUgbWVhbnMgdGhlIG5leHQgcmVhZGVyXG4gICAgICAgICAgICAgICAgICAgKiBhbHJlYWR5IGhhcyB0aGUgbG9nIGFuZCB0aGUgbG9vcCdzIGluY3JlbWVudGFsXG4gICAgICAgICAgICAgICAgICAgKiBgZXZlbnRzLmxpc3RgIGZpbmRzIG5vdGhpbmcgbGVmdCB0byBmZXRjaC5cbiAgICAgICAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgICAgICAgKiBEZWNsaW5pbmcgaXMgYWx3YXlzIHNhZmUg4oCUIGFuIHVuYWJzb3JiZWQgZGVsdGEgaXMgYSBkZWx0YVxuICAgICAgICAgICAgICAgICAgICogdGhlIG5leHQgYGV2ZW50cy5saXN0YCByZXR1cm5zIOKAlCBzbyB0aGUgZ3VhcmRzIGFyZSBmcmVlIHRvXG4gICAgICAgICAgICAgICAgICAgKiBiZSBzdHJpY3Q6XG4gICAgICAgICAgICAgICAgICAgKlxuICAgICAgICAgICAgICAgICAgICogLSBgaGFzTW9yZWAgbWVhbnMgdGhlIFdvcmxkIHRydW5jYXRlZCB0aGUgcGFnZS4gVGFraW5nIGl0XG4gICAgICAgICAgICAgICAgICAgKiAgIHdoaWxlIGFkdmFuY2luZyB0aGUgY3Vyc29yIHRvIHRoZSBwYWdlIGVuZCB3b3VsZCBiZVxuICAgICAgICAgICAgICAgICAgICogICBmaW5lLCBidXQgdGFraW5nIGl0IGFuZCBOT1QgYWR2YW5jaW5nIHdvdWxkIGR1cGxpY2F0ZSxcbiAgICAgICAgICAgICAgICAgICAqICAgYW5kIHRoZSB0cnVuY2F0ZWQgY2FzZSBpcyByYXJlIGVub3VnaCBub3QgdG8gc3BlY2lhbC1jYXNlLlxuICAgICAgICAgICAgICAgICAgICogLSBUaGUgY3Vyc29yIG11c3QgYmUgZXhhY3RseSB3aGVyZSBpdCB3YXMgd2hlbiB0aGUgcmVxdWVzdFxuICAgICAgICAgICAgICAgICAgICogICB3ZW50IG91dC4gQ29uY3VycmVudCB3cml0ZXMgZWFjaCBkaWZmIGFnYWluc3QgdGhlIGN1cnNvclxuICAgICAgICAgICAgICAgICAgICogICB0aGV5IHNhdywgYW5kIGBhcHBlbmRVbmlxdWVFdmVudHNgIGRlbGliZXJhdGVseSBkb2VzIG5vdFxuICAgICAgICAgICAgICAgICAgICogICByZS1zb3J0LCBzbyBhYnNvcmJpbmcgYSBzZWNvbmQgZGVsdGEgY29tcHV0ZWQgZnJvbSBhblxuICAgICAgICAgICAgICAgICAgICogICBvbGRlciBjdXJzb3IgY291bGQgYXBwZW5kIGV2ZW50cyBiZWhpbmQgb25lcyBhbHJlYWR5XG4gICAgICAgICAgICAgICAgICAgKiAgIHRha2VuLiBGaXJzdCByZXNwb25zZSBiYWNrIHdpbnM7IHRoZSByZXN0IGFyZSBkcm9wcGVkLlxuICAgICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgICBjb25zdCBhYnNvcmJDcmVhdGVEZWx0YSA9IChcbiAgICAgICAgICAgICAgICAgICAgc2VudEN1cnNvcjogc3RyaW5nLFxuICAgICAgICAgICAgICAgICAgICByZXN1bHQ6IEV2ZW50UmVzdWx0XG4gICAgICAgICAgICAgICAgICApOiB2b2lkID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICAgIGV2ZW50TG9nLnR5cGUgIT09ICdyZWFkeScgfHxcbiAgICAgICAgICAgICAgICAgICAgICBldmVudExvZy5jdXJzb3IgIT09IHNlbnRDdXJzb3IgfHxcbiAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuZXZlbnRzID09PSB1bmRlZmluZWQgfHxcbiAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuaGFzTW9yZSA9PT0gdHJ1ZVxuICAgICAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYXBwZW5kRXZlbnRMb2coZXZlbnRMb2csIHtcbiAgICAgICAgICAgICAgICAgICAgICBldmVudHM6IHJlc3VsdC5ldmVudHMsXG4gICAgICAgICAgICAgICAgICAgICAgY3Vyc29yOiByZXN1bHQuY3Vyc29yLFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICAgIC8vIGByZWFkeWAgY2FuIHJlcGxheSBvbmNlIHdpdGhvdXQgYSByZWFkLiBUaGUgb3RoZXIgc3RhdGVzXG4gICAgICAgICAgICAgICAgICAvLyBkZXNjcmliZSB0aGUgbmV4dCBsb2FkIGV4YWN0bHkuXG4gICAgICAgICAgICAgICAgICBsZXQgZXZlbnRMb2c6IFJlcGxheUV2ZW50TG9nID0geyB0eXBlOiAnbG9hZEFsbCcgfTtcblxuICAgICAgICAgICAgICAgICAgLy8gU2hhcmVkIHN0YXRlOiBzZXQgYnkgZWl0aGVyIHRoZSBiYWNrZ3JvdW5kIHN0ZXAgcGF0aFxuICAgICAgICAgICAgICAgICAgLy8gb3IgdGhlIHJ1bl9zdGFydGVkIHNldHVwIGJlbG93LlxuICAgICAgICAgICAgICAgICAgbGV0IHdvcmtmbG93UnVuOiBXb3JrZmxvd1J1biB8IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgIC8vIFNlcnZlci1zdXBwbGllZCBwZXItcnVuIGV2ZW50IGNlaWxpbmcgZnJvbSB0aGUgcnVuX3N0YXJ0ZWRcbiAgICAgICAgICAgICAgICAgIC8vIHJlc3BvbnNlLiBVbmRlZmluZWQg4oeSIG5vIGVuZm9yY2VtZW50IChvbGRlciBzZXJ2ZXJzLCB0dXJibykuXG4gICAgICAgICAgICAgICAgICBsZXQgbWF4RXZlbnRzTGltaXQ6IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgIGxldCB3b3JrZmxvd1N0YXJ0ZWRBdCA9IC0xO1xuXG4gICAgICAgICAgICAgICAgICAvLyBMYXRlbmN5IHRlbGVtZXRyeSAoVFRGUykgc3RhdGUg4oCUIHNlZSBydW50aW1lL3N0ZXAtbGF0ZW5jeS50cy5cbiAgICAgICAgICAgICAgICAgIC8vIFdoZXRoZXIgdGhpcyBpbnZvY2F0aW9uJ3MgRklSU1QgZXZlbnQgc25hcHNob3QgY29udGFpbmVkXG4gICAgICAgICAgICAgICAgICAvLyBub3RoaW5nIGJleW9uZCBydW5fY3JlYXRlZC9ydW5fc3RhcnRlZDogYW55dGhpbmcgZWxzZSB3YXNcbiAgICAgICAgICAgICAgICAgIC8vIHdyaXR0ZW4gYnkgYW4gZWFybGllciBpbnZvY2F0aW9uLCB3aG9zZSBjb250cmlidXRpb24gdG9cbiAgICAgICAgICAgICAgICAgIC8vIHRpbWUtdG8tZmlyc3Qtc3RlcCAoaW5jbHVkaW5nIHRoZSBxdWV1ZSBob3AgYmFjayBoZXJlKVxuICAgICAgICAgICAgICAgICAgLy8gY2Fubm90IGJlIG1lYXN1cmVkIHdhbGwtY2xvY2ssIHNvIFRURlMgaXMgbm90IHJlcG9ydGVkLlxuICAgICAgICAgICAgICAgICAgLy8gU2V0IG9uY2UsIG9uIHRoZSBmaXJzdCBpdGVyYXRpb24ncyBsb2FkZWQgc25hcHNob3QuXG4gICAgICAgICAgICAgICAgICBsZXQgaW52b2NhdGlvblN0YXJ0ZWRDbGVhbjogYm9vbGVhbiB8IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgIC8vIEVwb2NoIG1zIHRoZSBgcnVuX3N0YXJ0ZWRgIHJlc3BvbnNlIHdhcyByZWNlaXZlZC9wYXJzZWRcbiAgICAgICAgICAgICAgICAgIC8vIGJ5IHRoZSBTREsg4oCUIGFuY2hvcnMgUlNGUyAocnVuX3N0YXJ0ZWQg4oaSIGZpcnN0IHN0ZXAnc1xuICAgICAgICAgICAgICAgICAgLy8gc3RhcnQgUE9TVCkuIFNldCBvbmNlLCBpbiB0aGUgcnVuX3N0YXJ0ZWQgc2V0dXAgYmVsb3cuXG4gICAgICAgICAgICAgICAgICAvLyBVbmRlciB0dXJibywgcnVuX3N0YXJ0ZWQgaXMgYmFja2dyb3VuZGVkIHJhdGhlciB0aGFuXG4gICAgICAgICAgICAgICAgICAvLyBhd2FpdGVkLCBzbyB0aGlzIGlzIHN0YW1wZWQgYXQgdGhlIHBvaW50IHRoZSBydW4gaXNcbiAgICAgICAgICAgICAgICAgIC8vIHN5bnRoZXNpemVkIGxvY2FsbHkgaW5zdGVhZCBvZiB0aGUgcmVhbCByZXNwb25zZSDigJQgc2VlXG4gICAgICAgICAgICAgICAgICAvLyBTdGVwTGF0ZW5jeVRyYWNraW5nLnJzZnNBbmNob3JNcy5cbiAgICAgICAgICAgICAgICAgIGxldCBydW5TdGFydGVkUmVjZWl2ZWRBdE1zOiBudW1iZXIgfCB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAvLyBXYWxsLWNsb2NrIG1zIHNwZW50IGNvbW1pdHRpbmcgaG9va19jcmVhdGVkIGV2ZW50cyBiZWZvcmVcbiAgICAgICAgICAgICAgICAgIC8vIHRoZSBmaXJzdCBzdGVwIHJhbiwgYWNjdW11bGF0ZWQgYWNyb3NzIHN1c3BlbnNpb24gcGFzc2VzXG4gICAgICAgICAgICAgICAgICAvLyBhbmQgc3VidHJhY3RlZCBmcm9tIFRURlMuIEFjY3VtdWxhdG9ycyBoZXJlIHN1cnZpdmUgYW5cbiAgICAgICAgICAgICAgICAgIC8vIGluLXByb2Nlc3MgcmVwbGF5IHJlc3RhcnQgKGEgc3RhbGUtc25hcHNob3QgcmVqZWN0aW9uLCBvclxuICAgICAgICAgICAgICAgICAgLy8gdGhlIGF0dHJpYnV0ZS1ldmVudCByZXN0YXJ0IGJlbG93KSwgc28gYSByZXN0YXJ0ZWRcbiAgICAgICAgICAgICAgICAgIC8vIGludm9jYXRpb24gb3Zlci1jb3VudHMgYnkgdGhlIGFiYW5kb25lZCBwYXNzJ3MgaG9vayB0aW1lIOKAlFxuICAgICAgICAgICAgICAgICAgLy8gdGhlIHNhbWUgc2xpZ2h0IG92ZXItY291bnQgZWl0aGVyIHJlc3RhcnQgaGFzIGFsd2F5cyBoYWQuXG4gICAgICAgICAgICAgICAgICBsZXQgcHJlU3RlcEJsb2NraW5nTXMgPSAwO1xuICAgICAgICAgICAgICAgICAgLy8gU25hcHNob3Qgb2YgdGhlIGFjY3VtdWxhdG9yIGFzIG9mIHRoZSBzdXNwZW5zaW9uIHRoYXRcbiAgICAgICAgICAgICAgICAgIC8vIHdyb3RlIHRoZSBydW4ncyBmaXJzdCBhdHRyX3NldCAod2hvc2UgaG9vayBwaGFzZSByYW5cbiAgICAgICAgICAgICAgICAgIC8vIGJlZm9yZSBpdHMgYXR0ciB3cml0ZXMpLiBXaGVuIGEgcHJlLXN0ZXAgc2V0QXR0cmlidXRlc1xuICAgICAgICAgICAgICAgICAgLy8gZW5kcyB0aGUgVFRGUyBtZWFzdXJlbWVudCBhdCB0aGUgYXR0ciB3cml0ZSwgb25seSBob29rXG4gICAgICAgICAgICAgICAgICAvLyB0aW1lIGZyb20gQkVGT1JFIHRoYXQgcG9pbnQgbWF5IGJlIHN1YnRyYWN0ZWQg4oCUIGxhdGVyXG4gICAgICAgICAgICAgICAgICAvLyBob29rIHdyaXRlcyBmYWxsIG91dHNpZGUgdGhlIG1lYXN1cmVkIHdpbmRvdy5cbiAgICAgICAgICAgICAgICAgIGxldCBwcmVTdGVwQmxvY2tpbmdCZWZvcmVBdHRyTXM6IG51bWJlciB8IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgICAgLy8gVHVyYm8gbW9kZSBmYXN0LXBhdGhzIHRoZSB2ZXJ5IGZpcnN0IGRlbGl2ZXJ5IG9mIHRoZSB2ZXJ5XG4gICAgICAgICAgICAgICAgICAvLyBmaXJzdCBpbnZvY2F0aW9uLCB3aGVyZSBpdCBpcyBwcm92YWJseSBzYWZlIHRvOiBiYWNrZ3JvdW5kXG4gICAgICAgICAgICAgICAgICAvLyBgcnVuX3N0YXJ0ZWRgLCBza2lwIHRoZSBpbml0aWFsIGV2ZW50LWxvZyBsb2FkIChub3RoaW5nIGhhc1xuICAgICAgICAgICAgICAgICAgLy8gYmVlbiB3cml0dGVuIHlldCksIGFuZCBmb3JjZSBvcHRpbWlzdGljIGlubGluZSBzdGFydCAobm9cbiAgICAgICAgICAgICAgICAgIC8vIGNvbmN1cnJlbnQgcGVlciBoYW5kbGVyIGV4aXN0cyB0byByYWNlIHRoZSBjcmVhdGUtY2xhaW0pLlxuICAgICAgICAgICAgICAgICAgLy8gYHJ1bklucHV0YCBpcyBvbmx5IHByZXNlbnQgb24gdGhlIHN0YXJ0KCktZW5xdWV1ZWQgbWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgIC8vIGFuZCBgYXR0ZW1wdCA9PT0gMWAgKDEtYmFzZWQpIG1lYW5zIHRoaXMgaXMgdGhlIGZpcnN0XG4gICAgICAgICAgICAgICAgICAvLyBkZWxpdmVyeTsgYGluY29taW5nU3RlcElkYCB3b3VsZCBtYXJrIGEgYmFja2dyb3VuZC1zdGVwXG4gICAgICAgICAgICAgICAgICAvLyBpbnZvY2F0aW9uIGFuZCBgcmVwbGF5RGl2ZXJnZW5jZWAgYSByZWNvdmVyeSByZXBsYXkg4oCUIGJvdGhcbiAgICAgICAgICAgICAgICAgIC8vIGluZWxpZ2libGUuIFRoZSBzaW5nbGUtaGFuZGxlciBndWFyYW50ZWUgdGhhdCBtYWtlcyBmb3JjZWRcbiAgICAgICAgICAgICAgICAgIC8vIG9wdGltaXN0aWMgc3RhcnQgc2FmZSBlbmRzIG9uY2UgYSBob29rIG9yIHdhaXQgaXMgY3JlYXRlZFxuICAgICAgICAgICAgICAgICAgLy8gKHRoZXkgaW50cm9kdWNlIHJlc3VtZSBpbnZvY2F0aW9ucyksIHNvIHR1cmJvIGV4aXRzIGF0IHRoYXRcbiAgICAgICAgICAgICAgICAgIC8vIHBvaW50IChzZWUgYGZvcmNlT3B0aW1pc3RpY1N0YXJ0YCkuIFdvcmtmbG93IGF0dHJpYnV0ZVxuICAgICAgICAgICAgICAgICAgLy8gd3JpdGVzIGludHJvZHVjZSBubyBzdWNoIGludm9jYXRpb24gc291cmNlIOKAlCB0aGV5IHJlc29sdmVcbiAgICAgICAgICAgICAgICAgIC8vIHZpYSBhbiBpbi1wcm9jZXNzIHJlcGxheSBhbmQgZG9uJ3QgZW5kIHR1cmJvLlxuICAgICAgICAgICAgICAgICAgLy8gTk9URTogYG1ldGFkYXRhLmF0dGVtcHQgPT09IDFgIGlzIGFsc28gbG9hZC1iZWFyaW5nIGZvclxuICAgICAgICAgICAgICAgICAgLy8gaW5saW5lIHN0ZXAgb3duZXJzaGlwOiBvd25lZC1yZWNvdmVyeSBzdGVwcyAoYSBzdGVwXG4gICAgICAgICAgICAgICAgICAvLyBzdGFtcGVkIGJ5IGEgUFJFVklPVVMgZGVsaXZlcnkgb2YgdGhpcyBtZXNzYWdlKSBjYW4gb25seVxuICAgICAgICAgICAgICAgICAgLy8gZXhpc3Qgb24gYXR0ZW1wdCDiiaUgMiwgc28gdHVyYm8gYW5kIG93bmVkIHJlY292ZXJ5IGFyZVxuICAgICAgICAgICAgICAgICAgLy8gbXV0dWFsbHkgZXhjbHVzaXZlLiBUaGUgdHVyYm8gYHJlaW52b2tlKClgIHBhdGhzIChob29rXG4gICAgICAgICAgICAgICAgICAvLyBjb25mbGljdCwgdGhyb3R0bGUgYmFja29mZikgYWNrIHRoaXMgbWVzc2FnZSBhbmQgY29udGludWVcbiAgICAgICAgICAgICAgICAgIC8vIHVuZGVyIGEgTkVXIG1lc3NhZ2UgaWQg4oCUIHNhZmUgb25seSBiZWNhdXNlIG5vXG4gICAgICAgICAgICAgICAgICAvLyBub24tdGVybWluYWwgc3RlcCBjYW4gYmUgaW5saW5lLW93bmVkIGJ5IHRoZSBhY2tlZCBpZFxuICAgICAgICAgICAgICAgICAgLy8gd2hlbiB0dXJibyBpcyBvbi4gSWYgdHVyYm8gZXZlciBlbmdhZ2VzIG9uIHJlZGVsaXZlcmllcyxcbiAgICAgICAgICAgICAgICAgIC8vIHRob3NlIHBhdGhzIG11c3QgZmlyc3QgY2hlY2sgZm9yIG93bmVkIHBlbmRpbmcgc3RlcHMgYW5kXG4gICAgICAgICAgICAgICAgICAvLyBmYWxsIGJhY2sgdG8gYHsgdGltZW91dFNlY29uZHMgfWAgcmVkZWxpdmVyeS5cbiAgICAgICAgICAgICAgICAgIGNvbnN0IHR1cmJvID1cbiAgICAgICAgICAgICAgICAgICAgaXNUdXJib0VuYWJsZWQoKSAmJlxuICAgICAgICAgICAgICAgICAgICBydW5JbnB1dCAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhLmF0dGVtcHQgPT09IDEgJiZcbiAgICAgICAgICAgICAgICAgICAgaW5jb21pbmdTdGVwSWQgPT09IHVuZGVmaW5lZCAmJlxuICAgICAgICAgICAgICAgICAgICAhcmVwbGF5RGl2ZXJnZW5jZTtcbiAgICAgICAgICAgICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoQXR0cmlidXRlLldvcmtmbG93VHVyYm8odHVyYm8pKTtcblxuICAgICAgICAgICAgICAgICAgLy8gVHVyYm8gbW9kZSBvbmx5OiByZXNvbHZlcyBvbmNlIHRoZSBiYWNrZ3JvdW5kZWRcbiAgICAgICAgICAgICAgICAgIC8vIGBydW5fc3RhcnRlZGAgaGFzIGxhbmRlZCAob3IgcmVqZWN0cyBpZiBpdCBmYWlsZWQpLiBUaHJlYWRlZFxuICAgICAgICAgICAgICAgICAgLy8gaW50byBoYW5kbGVTdXNwZW5zaW9uIGFuZCBleGVjdXRlU3RlcCBzbyBubyBzdGVwL2hvb2svd2FpdFxuICAgICAgICAgICAgICAgICAgLy8gd3JpdGUgcmFjZXMgYWhlYWQgb2YgdGhlIHJ1bidzIGNyZWF0aW9uLiBVbmRlZmluZWQgb3V0c2lkZVxuICAgICAgICAgICAgICAgICAgLy8gdHVyYm8sIHdoZXJlIGBydW5fc3RhcnRlZGAgaXMgYXdhaXRlZCB1cCBmcm9udC5cbiAgICAgICAgICAgICAgICAgIGxldCBydW5SZWFkeUJhcnJpZXI6IFByb21pc2U8dW5rbm93bj4gfCB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICAgIC8vIE9yZGVyIGEgdGVybWluYWwgcnVuIHdyaXRlIChydW5fY29tcGxldGVkIC8gcnVuX2ZhaWxlZCkgYWZ0ZXJcbiAgICAgICAgICAgICAgICAgIC8vIHRoZSBiYWNrZ3JvdW5kZWQgcnVuX3N0YXJ0ZWQgaW4gdHVyYm8gbW9kZSDigJQgYSBuby1zdGVwXG4gICAgICAgICAgICAgICAgICAvLyB3b3JrZmxvdyBjYW4gb3RoZXJ3aXNlIHJlYWNoIHJ1bl9jb21wbGV0ZWQgYmVmb3JlIHRoZSBydW5cbiAgICAgICAgICAgICAgICAgIC8vIGV4aXN0cy4gQmVzdC1lZmZvcnQ6IGEgYmFycmllciByZWplY3Rpb24gaXMgc3dhbGxvd2VkIGZvclxuICAgICAgICAgICAgICAgICAgLy8gb3JkZXJpbmcgb25seTsgaWYgcnVuX3N0YXJ0ZWQgdHJ1bHkgZmFpbGVkIHRoZSB0ZXJtaW5hbCB3cml0ZVxuICAgICAgICAgICAgICAgICAgLy8gc3VyZmFjZXMgdGhlIHJlYWwgZXJyb3IgKHJ1biBub3QgZm91bmQgLyBnb25lKSBhbmQgdGhlIG1lc3NhZ2VcbiAgICAgICAgICAgICAgICAgIC8vIHJlZGVsaXZlcnMuIE5vLW9wIG91dHNpZGUgdHVyYm8uXG4gICAgICAgICAgICAgICAgICBjb25zdCBhd2FpdFJ1blJlYWR5ID0gYXN5bmMgKCk6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAocnVuUmVhZHlCYXJyaWVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHJ1blJlYWR5QmFycmllcjtcbiAgICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGludGVudGlvbmFsOiBvcmRlcmluZyBiYXJyaWVyIG9ubHkg4oCUIHNlZSBhYm92ZS5cbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICAgIC8vIFJlLWludm9rZSB0aGUgb3JjaGVzdHJhdG9yLiBPdXRzaWRlIHR1cmJvIHRoaXMgcmV0dXJuc1xuICAgICAgICAgICAgICAgICAgLy8gYHsgdGltZW91dFNlY29uZHMgfWAsIHdoaWNoIG1ha2VzIHRoZSBxdWV1ZSByZXNjaGVkdWxlIHRoZVxuICAgICAgICAgICAgICAgICAgLy8gQ1VSUkVOVCBkZWxpdmVyeSdzIG1lc3NhZ2UuIEluIHR1cmJvIHRoYXQgaXMgYSB0cmFwOiB0aGVcbiAgICAgICAgICAgICAgICAgIC8vIGN1cnJlbnQgbWVzc2FnZSBjYXJyaWVzIGBydW5JbnB1dGAsIGFuZCBvbiBhc3luYyBxdWV1ZXNcbiAgICAgICAgICAgICAgICAgIC8vIChlLmcuIGdyYXBoaWxlLXdvcmtlcikgYSByZXNjaGVkdWxlIGNvbWVzIGJhY2sgYXMgZGVsaXZlcnlcbiAgICAgICAgICAgICAgICAgIC8vIGF0dGVtcHQgMSDigJQgc28gdHVyYm8gcmUtZW5nYWdlcywgc2tpcHMgdGhlIGV2ZW50LWxvZyBsb2FkXG4gICAgICAgICAgICAgICAgICAvLyBhZ2FpbiwgcmVwbGF5cyBhZ2FpbnN0IGFuIGVtcHR5IGxvZywgbmV2ZXIgb2JzZXJ2ZXMgdGhlXG4gICAgICAgICAgICAgICAgICAvLyBob29rIGV2ZW50IHRoaXMgaW52b2NhdGlvbiBqdXN0IHdyb3RlLCBhbmQgcmUtc3VzcGVuZHNcbiAgICAgICAgICAgICAgICAgIC8vIGZvcmV2ZXIgKHRoZSBydW4gd2VkZ2VzKS4gVW5kZXIgdHVyYm8gd2UgaW5zdGVhZCBlbnF1ZXVlIGFuXG4gICAgICAgICAgICAgICAgICAvLyBleHBsaWNpdCBjb250aW51YXRpb24gdGhhdCBjYXJyaWVzIE5PIGBydW5JbnB1dGAsIHNvIHRoZVxuICAgICAgICAgICAgICAgICAgLy8gbmV4dCBkZWxpdmVyeSBpcyBhIG5vcm1hbCAobm9uLXR1cmJvKSBsb2FkLWFuZC1yZXBsYXkgdGhhdFxuICAgICAgICAgICAgICAgICAgLy8gb2JzZXJ2ZXMgdGhlIGNvbW1pdHRlZCBldmVudHMgYW5kIG1ha2VzIHByb2dyZXNzOyB3ZSB0aGVuXG4gICAgICAgICAgICAgICAgICAvLyByZXR1cm4gYHVuZGVmaW5lZGAgc28gdGhlIHF1ZXVlIHRyZWF0cyB0aGlzIGRlbGl2ZXJ5IGFzIGRvbmVcbiAgICAgICAgICAgICAgICAgIC8vIHJhdGhlciB0aGFuIGFsc28gcmVzY2hlZHVsaW5nIGl0LlxuICAgICAgICAgICAgICAgICAgLy8gSW5saW5lLW93bmVyc2hpcCBpbnZhcmlhbnQgZ3VhcmQ6IGNvcnJlbGF0aW9uIElEcyBvZlxuICAgICAgICAgICAgICAgICAgLy8gc3RlcHMgd2hvc2UgYm9kaWVzIHRoaXMgaW52b2NhdGlvbiBpcyBleGVjdXRpbmcgdW5kZXIgYW5cbiAgICAgICAgICAgICAgICAgIC8vIG93bmVyc2hpcCBzdGFtcCAobGF6eSBpbmxpbmUgKyBvd25lZCByZWNvdmVyeSksIHdoaWxlIHRoZVxuICAgICAgICAgICAgICAgICAgLy8gYm9keSBpcyBpbiBmbGlnaHQuIENyYXNoIHJlY292ZXJ5IGRlcGVuZHMgb24gdGhlIG93bmluZ1xuICAgICAgICAgICAgICAgICAgLy8gbWVzc2FnZSBOT1QgYmVpbmcgYWNrZWQgd2hpbGUgc3VjaCBhIHN0ZXAgaXMgbm9uLXRlcm1pbmFsXG4gICAgICAgICAgICAgICAgICAvLyAoYWNrID0gaGFuZGxlciByZXR1cm4gb3IgcmVpbnZva2UsIHdoaWNoIGFja3MgKyBlbnF1ZXVlc1xuICAgICAgICAgICAgICAgICAgLy8gdW5kZXIgYSBORVcgbWVzc2FnZSBpZCDigJQgdGhlIHJlZGVsaXZlcnkgb2YgdGhlIG9sZCBpZCBpc1xuICAgICAgICAgICAgICAgICAgLy8gd2hhdCByZS1leGVjdXRlcyBhbiBvcnBoYW5lZCBvd25lZCBzdGVwKS4gQWxsIGV4ZWN1dGVTdGVwXG4gICAgICAgICAgICAgICAgICAvLyBjYWxscyBhcmUgYXdhaXRlZCBiZWZvcmUgYW55IGFjayBwYXRoIHJ1bnMsIHNvIHRoaXMgc2V0XG4gICAgICAgICAgICAgICAgICAvLyBpcyBlbXB0eSBhdCBldmVyeSBhY2sgYnkgY29uc3RydWN0aW9uOyB0aGUgY2hlY2sgZXhpc3RzXG4gICAgICAgICAgICAgICAgICAvLyB0byBjYXRjaCBmdXR1cmUgcmVmYWN0b3JzIHRoYXQgYnJlYWsgdGhhdCBvcmRlcmluZy5cbiAgICAgICAgICAgICAgICAgIGNvbnN0IGluRmxpZ2h0T3duZWRTdGVwcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgICAgICAgICAgICAgICAgY29uc3QgYXNzZXJ0Tm9JbkZsaWdodE93bmVkU3RlcHMgPSAoXG4gICAgICAgICAgICAgICAgICAgIGFja1BhdGg6IHN0cmluZ1xuICAgICAgICAgICAgICAgICAgKTogdm9pZCA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbkZsaWdodE93bmVkU3RlcHMuc2l6ZSA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICBydW50aW1lTG9nZ2VyLmVycm9yKFxuICAgICAgICAgICAgICAgICAgICAgICAgJ0ludmFyaWFudCB2aW9sYXRpb246IGFja2luZyB0aGUgd29ya2Zsb3cgbWVzc2FnZSB3aGlsZSBvd25lZCBpbmxpbmUgc3RlcHMgYXJlIHN0aWxsIGV4ZWN1dGluZyDigJQgY3Jhc2ggcmVjb3ZlcnkgZm9yIHRoZXNlIHN0ZXBzIGlzIGJyb2tlbicsXG4gICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBhY2tQYXRoLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBzdGVwSWRzOiBbLi4uaW5GbGlnaHRPd25lZFN0ZXBzXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgICAvLyBBIHBsYWluIG9yY2hlc3RyYXRvci1yZXBsYXkgbWVzc2FnZS4gT21pdHMgYHJ1bklucHV0YCAoaXRcbiAgICAgICAgICAgICAgICAgIC8vIHJlLWVuZ2FnZXMgdHVyYm8gb24gdGhlIG5leHQgZGVsaXZlcnkgYW5kIHdlZGdlcyB0aGUgcnVuIOKAlFxuICAgICAgICAgICAgICAgICAgLy8gc2VlIGByZWludm9rZWAgYmVsb3cpIGFuZCBgcmVwbGF5RGl2ZXJnZW5jZWAgL1xuICAgICAgICAgICAgICAgICAgLy8gYHNlcnZlckVycm9yUmV0cnlDb3VudGAgKHRoaXMgZGVsaXZlcnkgY2hhaW4ncyBidWRnZXRzKS5cbiAgICAgICAgICAgICAgICAgIGNvbnN0IHJlcGxheU1lc3NhZ2UgPVxuICAgICAgICAgICAgICAgICAgICBhc3luYyAoKTogUHJvbWlzZTxXb3JrZmxvd0ludm9rZVBheWxvYWQ+ID0+ICh7XG4gICAgICAgICAgICAgICAgICAgICAgcnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgdHJhY2VDYXJyaWVyOiBhd2FpdCBuZXh0VHJhY2VDYXJyaWVyKCksXG4gICAgICAgICAgICAgICAgICAgICAgcmVxdWVzdGVkQXQ6IG5ldyBEYXRlKCksXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICBjb25zdCByZWludm9rZSA9IGFzeW5jIChcbiAgICAgICAgICAgICAgICAgICAgZGVsYXlTZWNvbmRzOiBudW1iZXIsXG4gICAgICAgICAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICAgICAgICAgKiBFeHRyYSBmaWVsZHMgdG8gY2Fycnkgb24gdGhlIG5ldyBtZXNzYWdlLiBPbmx5IHJlYWNoZXMgdGhlXG4gICAgICAgICAgICAgICAgICAgICAqIG5leHQgaW52b2NhdGlvbiBvbiB0aGUgdHVyYm8gcGF0aDogd2l0aG91dCB0dXJibyBub1xuICAgICAgICAgICAgICAgICAgICAgKiBtZXNzYWdlIGlzIGVucXVldWVkIGF0IGFsbCDigJQgdGhlIGhhbmRsZXIgcmV0dXJucyBhXG4gICAgICAgICAgICAgICAgICAgICAqIHZpc2liaWxpdHkgdGltZW91dCBhbmQgdGhlIHF1ZXVlIHJlZGVsaXZlcnMgdGhlIENVUlJFTlRcbiAgICAgICAgICAgICAgICAgICAgICogbWVzc2FnZSwgd2hvc2UgYm9keSAoYW5kIHRoZXJlZm9yZSBhbnkgY291bnRlciBvbiBpdClcbiAgICAgICAgICAgICAgICAgICAgICogY2Fubm90IGJlIGNoYW5nZWQuXG4gICAgICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgICAgICBleHRyYVBheWxvYWQ/OiBQYXJ0aWFsPFdvcmtmbG93SW52b2tlUGF5bG9hZD5cbiAgICAgICAgICAgICAgICAgICk6IFByb21pc2U8eyB0aW1lb3V0U2Vjb25kczogbnVtYmVyIH0gfCB1bmRlZmluZWQ+ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0Tm9JbkZsaWdodE93bmVkU3RlcHMoJ3JlaW52b2tlJyk7XG4gICAgICAgICAgICAgICAgICAgIGlmICghdHVyYm8pIHJldHVybiB7IHRpbWVvdXRTZWNvbmRzOiBkZWxheVNlY29uZHMgfTtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgcXVldWVNZXNzYWdlKFxuICAgICAgICAgICAgICAgICAgICAgIHdvcmxkLFxuICAgICAgICAgICAgICAgICAgICAgIGdldFdvcmtmbG93UXVldWVOYW1lKHdvcmtmbG93TmFtZSwgbmFtZXNwYWNlKSxcbiAgICAgICAgICAgICAgICAgICAgICB7IC4uLihhd2FpdCByZXBsYXlNZXNzYWdlKCkpLCAuLi5leHRyYVBheWxvYWQgfSxcbiAgICAgICAgICAgICAgICAgICAgICBkZWxheVNlY29uZHMgPiAwID8geyBkZWxheVNlY29uZHMgfSA6IHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgLy8gUHJlY29uZGl0aW9uICg0MTIpIHJlY292ZXJ5OiBob3cgbWFueSB0aW1lcyB0aGlzIGludm9jYXRpb25cbiAgICAgICAgICAgICAgICAgIC8vIGhhcyB0aHJvd24gYXdheSBpdHMgcmVwbGF5IGFuZCBzdGFydGVkIG92ZXIgaW4tcHJvY2Vzcy5cbiAgICAgICAgICAgICAgICAgIGxldCBwcmVjb25kaXRpb25SZXN0YXJ0cyA9IDA7XG4gICAgICAgICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAgICAgICAqIEV2ZW50IGlkcyB0aGUgZGlzY2FyZGVkIHJlcGxheSBoZWxkLCBrZXB0IHVudGlsIHRoZSBuZXh0XG4gICAgICAgICAgICAgICAgICAgKiBsb2FkIHJlc29sdmVzIHNvIGEgcmVzdGFydCBjYW4gcmVwb3J0IHdoYXQgaXRzIHJlbG9hZFxuICAgICAgICAgICAgICAgICAgICogYWN0dWFsbHkgZm91bmQuIFdpdGhvdXQgdGhpcyBhIDQxMiBvbmx5IGV2ZXIgdGVsbHMgeW91IHRoYXRcbiAgICAgICAgICAgICAgICAgICAqIGEgcmVzdGFydCBoYXBwZW5lZCwgd2hpY2ggY29uZmxhdGVzIHR3byB2ZXJ5IGRpZmZlcmVudFxuICAgICAgICAgICAgICAgICAgICogc2l0dWF0aW9uczogYSBsb2cgdGhhdCBncmV3IChleHBlY3RlZCDigJQgdGhlIGZlbmNlIGRpZCBpdHNcbiAgICAgICAgICAgICAgICAgICAqIGpvYikgYW5kIGEgbG9nIHRoYXQgY2FtZSBiYWNrIGlkZW50aWNhbCwgd2hpY2ggbWVhbnMgY2xpZW50XG4gICAgICAgICAgICAgICAgICAgKiBhbmQgYmFja2VuZCBkaXNhZ3JlZSBhYm91dCB0aGUgY291bnQgZm9yIHRoZSBzYW1lIHNldCBvZlxuICAgICAgICAgICAgICAgICAgICogZXZlbnRzIGFuZCB0aGUgcmVzdGFydCB3aWxsIHJlLWRlcml2ZSB0aGUgc2FtZSBzbmFwc2hvdCBhbmRcbiAgICAgICAgICAgICAgICAgICAqIGJlIHJlamVjdGVkIGFnYWluLlxuICAgICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgICBsZXQgcHJlY29uZGl0aW9uUmVzdGFydEJhc2VsaW5lOiB7XG4gICAgICAgICAgICAgICAgICAgIGlkczogU2V0PHN0cmluZz47XG4gICAgICAgICAgICAgICAgICAgIHJlc3RhcnQ6IG51bWJlcjtcbiAgICAgICAgICAgICAgICAgICAgcmVhc29uOiBzdHJpbmc7XG4gICAgICAgICAgICAgICAgICAgIHNvdXJjZTogJ2lubGluZS1kZWx0YScgfCAnZnVsbC1yZWxvYWQnO1xuICAgICAgICAgICAgICAgICAgfSB8IG51bGwgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgICAgICAgKiBSZXBvcnQgd2hhdCBhIHN0YWxlLXNuYXBzaG90IHJlc3RhcnQncyByZWxvYWQgZm91bmQsIG9uY2VcbiAgICAgICAgICAgICAgICAgICAqIHRoZSBsb2cgdGhpcyByZXBsYXkgd2lsbCBhY3R1YWxseSBjb25zdW1lIGlzIGluIGhhbmQuXG4gICAgICAgICAgICAgICAgICAgKlxuICAgICAgICAgICAgICAgICAgICogYGdyZXdgIGlzIHRoZSBleHBlY3RlZCBjYXNlIGFuZCBnaXZlcyA0MTIgdm9sdW1lIGFcbiAgICAgICAgICAgICAgICAgICAqIGRlbm9taW5hdG9yLiBgdW5jaGFuZ2VkYCBtZWFucyB0aGUgcmVsb2FkIGRpc2FncmVlZCB3aXRoXG4gICAgICAgICAgICAgICAgICAgKiB0aGUgcmVqZWN0aW9uLCBzbyB0aGlzIHJlcGxheSByZS1kZXJpdmVzIHRoZSBzYW1lIHNuYXBzaG90XG4gICAgICAgICAgICAgICAgICAgKiBhbmQgaXMgcmVqZWN0ZWQgYWdhaW4gdW50aWwgdGhlIGJ1ZGdldCBpcyBzcGVudC4gYHNocmFua2BcbiAgICAgICAgICAgICAgICAgICAqIHNob3VsZCBiZSBpbXBvc3NpYmxlOiBldmVyeSBsb2FkIHBhdGggb25seSBhZGRzIHRvIGEgcnVuJ3NcbiAgICAgICAgICAgICAgICAgICAqIGxvZy5cbiAgICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgICAgY29uc3QgcmVwb3J0UHJlY29uZGl0aW9uUmVzdGFydFJlbG9hZCA9IChcbiAgICAgICAgICAgICAgICAgICAgZXZlbnRzOiBFdmVudFtdXG4gICAgICAgICAgICAgICAgICApOiB2b2lkID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgYmFzZWxpbmUgPSBwcmVjb25kaXRpb25SZXN0YXJ0QmFzZWxpbmU7XG4gICAgICAgICAgICAgICAgICAgIGlmICghYmFzZWxpbmUpIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgcHJlY29uZGl0aW9uUmVzdGFydEJhc2VsaW5lID0gbnVsbDtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCByZWxvYWRlZElkcyA9IG5ldyBTZXQoXG4gICAgICAgICAgICAgICAgICAgICAgZXZlbnRzLm1hcCgoZXZlbnQpID0+IGV2ZW50LmV2ZW50SWQpXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGFkZGVkID0gY291bnRNaXNzaW5nSWRzKHJlbG9hZGVkSWRzLCBiYXNlbGluZS5pZHMpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBkcm9wcGVkID0gY291bnRNaXNzaW5nSWRzKGJhc2VsaW5lLmlkcywgcmVsb2FkZWRJZHMpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBvdXRjb21lID1cbiAgICAgICAgICAgICAgICAgICAgICBkcm9wcGVkID4gMCA/ICdzaHJhbmsnIDogYWRkZWQgPiAwID8gJ2dyZXcnIDogJ3VuY2hhbmdlZCc7XG5cbiAgICAgICAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci53YXJuKFxuICAgICAgICAgICAgICAgICAgICAgICdSZXN0YXJ0ZWQgcmVwbGF5IHJlbG9hZGVkIGl0cyBldmVudCBsb2cgYWZ0ZXIgYSBzdGFsZS1zbmFwc2hvdCByZWplY3Rpb24nLFxuICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZGVkLFxuICAgICAgICAgICAgICAgICAgICAgICAgZHJvcHBlZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50c0JlZm9yZTogYmFzZWxpbmUuaWRzLnNpemUsXG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudHNBZnRlcjogcmVsb2FkZWRJZHMuc2l6ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZWNvbmRpdGlvblJlc3RhcnRzOiBiYXNlbGluZS5yZXN0YXJ0LFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVhc29uOiBiYXNlbGluZS5yZWFzb24sXG4gICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2U6IGJhc2VsaW5lLnNvdXJjZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvb3BJdGVyYXRpb24sXG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICAgICAgICogUmVjb3ZlciBmcm9tIGEgc3RhbGUtc25hcHNob3QgcmVqZWN0aW9uIGJ5IHJlc3RhcnRpbmcgdGhlXG4gICAgICAgICAgICAgICAgICAgKiByZXBsYXkgaW5zaWRlIHRoaXMgaW52b2NhdGlvbiwgcmV0dXJuaW5nIGZhbHNlIHdoZW4gdGhlXG4gICAgICAgICAgICAgICAgICAgKiBwZXItaW52b2NhdGlvbiBidWRnZXQgaXMgc3BlbnQgKHRoZSBjYWxsZXIgdGhlbiBmYWxscyBiYWNrXG4gICAgICAgICAgICAgICAgICAgKiB0byBhIGZyZXNoIGludm9jYXRpb24pLlxuICAgICAgICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAgICAgICAqIEEgNDEyIG1lYW5zIHRoZSBsb2cgdGhpcyByZXBsYXkgZGVyaXZlZCBpdHMgZXZlbnRzIGZyb20gd2FzXG4gICAgICAgICAgICAgICAgICAgKiBtaXNzaW5nIGFuIGV2ZW50IHRoZSBiYWNrZW5kIGhhZCBhbHJlYWR5IHJlY29yZGVkLiBUaGVcbiAgICAgICAgICAgICAgICAgICAqIHJlamVjdGVkIHdyaXRlIGNhbm5vdCBzaW1wbHkgYmUgcmV0cmllZDogY29ycmVsYXRpb24gaWRzXG4gICAgICAgICAgICAgICAgICAgKiBhcmUgcG9zaXRpb25hbCBvcmRpbmFscyBvZiBvbmUgc2VlZGVkIHNlcXVlbmNlLCBzbyBhIHJlcGxheVxuICAgICAgICAgICAgICAgICAgICogb3ZlciB0aGUgY29ycmVjdGVkIGxvZyBtaW50cyBhIGRpZmZlcmVudCBpZCBmb3IgdGhlIHNhbWVcbiAgICAgICAgICAgICAgICAgICAqIGxvZ2ljYWwgZXZlbnQsIGFuZCByZS1wb3N0aW5nIHRoaXMgb25lIHdvdWxkIHBlcnNpc3QgYW5cbiAgICAgICAgICAgICAgICAgICAqIGV2ZW50IG5vIGNvcnJlY3QgcmVwbGF5IGV2ZXIgcHJvZHVjZXMuIFRoZSB3aG9sZSByZXBsYXkgaGFzXG4gICAgICAgICAgICAgICAgICAgKiB0byBiZSByZS1kZXJpdmVkIOKAlCB3aGljaCB0aGUgbG9vcCBkb2VzIGJ5IGRpc2NhcmRpbmcgaXRzXG4gICAgICAgICAgICAgICAgICAgKiBjYWNoZWQgbG9nLCBzaW5jZSBgcnVuV29ya2Zsb3dgIHRoZW4gYnVpbGRzIGEgZnJlc2ggVk0sXG4gICAgICAgICAgICAgICAgICAgKiBzZWVkIGFuZCBjb3JyZWxhdGlvbi1pZCBzZXF1ZW5jZSBmcm9tIHRoZSByZWxvYWRlZCBldmVudHMuXG4gICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgIGNvbnN0IHJlc3RhcnRSZXBsYXlJblByb2Nlc3MgPSAoXG4gICAgICAgICAgICAgICAgICAgIHJlYXNvbjogc3RyaW5nLFxuICAgICAgICAgICAgICAgICAgICBlcnJvcj86IHVua25vd24sXG4gICAgICAgICAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICAgICAgICAgKiBTZXQgZmFsc2Ugd2hlbiB3cml0ZXMgdGhpcyBpbnZvY2F0aW9uIG1hZGUgY29uY3VycmVudGx5XG4gICAgICAgICAgICAgICAgICAgICAqIHdpdGggdGhlIHJlamVjdGVkIG9uZSBtYXkgYmUgbWlzc2luZyBmcm9tIHRoZSA0MTInc1xuICAgICAgICAgICAgICAgICAgICAgKiBkZWx0YTogdGhlIFdvcmxkIGNvbXB1dGVkIHRoYXQgZGVsdGEgYWdhaW5zdCB0aGVcbiAgICAgICAgICAgICAgICAgICAgICogcmVqZWN0ZWQgcmVxdWVzdCdzIHNuYXBzaG90LCBzbyBpdCBjYW5ub3QgY29udGFpbiBhblxuICAgICAgICAgICAgICAgICAgICAgKiBldmVudCBhIHNpYmxpbmcgY29tbWl0dGVkIGFmdGVyd2FyZHMsIGFuZCBtZXJnaW5nIGl0XG4gICAgICAgICAgICAgICAgICAgICAqIHdvdWxkIHJlc3RhcnQgdGhlIHJlcGxheSBvbiBhIGxvZyB0aGF0IGlzIHN0aWxsXG4gICAgICAgICAgICAgICAgICAgICAqIGluY29tcGxldGUuIE9ubHkgYSBmdWxsIHJlbG9hZCBpcyBhdXRob3JpdGF0aXZlIHRoZW4uXG4gICAgICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgICAgICB7IGFsbG93RGVsdGEgPSB0cnVlIH06IHsgYWxsb3dEZWx0YT86IGJvb2xlYW4gfSA9IHt9XG4gICAgICAgICAgICAgICAgICApOiBib29sZWFuID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICAgIHByZWNvbmRpdGlvblJlc3RhcnRzID49XG4gICAgICAgICAgICAgICAgICAgICAgZ2V0UHJlY29uZGl0aW9uTWF4SW5Qcm9jZXNzUmVzdGFydHMoKVxuICAgICAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcHJlY29uZGl0aW9uUmVzdGFydHMrKztcbiAgICAgICAgICAgICAgICAgICAgLy8gRXZlcnkgc3RhbGUtc25hcHNob3QgcmVzdGFydCBpbnZhbGlkYXRlcyB0aGUgcGFya2VkIFZNOlxuICAgICAgICAgICAgICAgICAgICAvLyB0aGUgbG9nIGl0IGNvbnN1bWVkIHdhcyBtaXNzaW5nIGV2ZW50cywgc28gb25seSBhIGZyZXNoXG4gICAgICAgICAgICAgICAgICAgIC8vIHJlcGxheSBvdmVyIHRoZSBjb3JyZWN0ZWQgbG9nIGlzIGF1dGhvcml0YXRpdmUuIFRoaXNcbiAgICAgICAgICAgICAgICAgICAgLy8gYWxzbyBjb3ZlcnMgdGhlIHN1c3BlbnNpb24tY3JlYXRlIDQxMiwgd2hpY2ggZmlyZXNcbiAgICAgICAgICAgICAgICAgICAgLy8gYmVmb3JlIHRoZSByZXRlbnRpb24gZGVjaXNpb24gKGtpbGwgc3dpdGNoICsgc3RlcC1pbnB1dFxuICAgICAgICAgICAgICAgICAgICAvLyBnYXRlKSBldmVyIHJhbiwgYW5kIHRoZSBydW5fY29tcGxldGVkIDQxMiwgd2hlcmUgYVxuICAgICAgICAgICAgICAgICAgICAvLyBjb21wbGV0ZWQgc2Vzc2lvbiBtdXN0IG5vdCBiZSByZXN1bWVkIGFnYWluLlxuICAgICAgICAgICAgICAgICAgICByZXRhaW5lZFNlc3Npb24gPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICAvLyBBIFdvcmxkIE1BWSByZXR1cm4gdGhlIGV2ZW50cyB3ZSB3ZXJlIG1pc3Npbmcgb24gdGhlIDQxMi5cbiAgICAgICAgICAgICAgICAgICAgLy8gVHJ1c3QgaXQgb25seSBvbiB0aGUgRklSU1QgcmVzdGFydDogaXRzIGNvbXBsZXRlbmVzcyBwcm9vZlxuICAgICAgICAgICAgICAgICAgICAvLyBsZWFucyBvbiB0aGUgYmFja2VuZCdzIG93biBib29ra2VlcGluZywgc28gaWYgdGhhdFxuICAgICAgICAgICAgICAgICAgICAvLyB1bmRlci1jb3VudHMsIGEgXCJjb21wbGV0ZVwiIGRlbHRhIGNhbiBzdGlsbCBsZWF2ZSBhIGhvbGUuXG4gICAgICAgICAgICAgICAgICAgIC8vIEJvdW5kaW5nIGl0IHRvIG9uZSBhdHRlbXB0IGNhcHMgdGhhdCBhdCBhIHNpbmdsZSB3YXN0ZWRcbiAgICAgICAgICAgICAgICAgICAgLy8gcmVzdGFydDsgZXZlcnkgbGF0ZXIgcmVzdGFydCBkb2VzIHRoZSBhdXRob3JpdGF0aXZlIGxvYWQuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGRlbHRhID1cbiAgICAgICAgICAgICAgICAgICAgICBhbGxvd0RlbHRhICYmIHByZWNvbmRpdGlvblJlc3RhcnRzID09PSAxXG4gICAgICAgICAgICAgICAgICAgICAgICA/IHByZWNvbmRpdGlvbkV2ZW50RGVsdGEoZXJyb3IsIHJ1bklkKVxuICAgICAgICAgICAgICAgICAgICAgICAgOiBudWxsO1xuICAgICAgICAgICAgICAgICAgICAvLyBBIGRlbHRhIGlzIG9ubHkgdXNhYmxlIGlmIHRoZXJlIGlzIGEgbG9hZGVkIGxvZyB0byBtZXJnZVxuICAgICAgICAgICAgICAgICAgICAvLyBpdCBpbnRvOyB3aXRob3V0IG9uZSB0aGUgcmVzdGFydCBtdXN0IGxvYWQgZXZlcnl0aGluZy5cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdXNlZERlbHRhID1cbiAgICAgICAgICAgICAgICAgICAgICBkZWx0YSAhPT0gbnVsbCAmJiBldmVudExvZy50eXBlICE9PSAnbG9hZEFsbCc7XG4gICAgICAgICAgICAgICAgICAgIC8vIFNuYXBzaG90IHRoZSBzZXQgYmVpbmcgZGlzY2FyZGVkIHdoaWxlIGl0IGlzIHN0aWxsIGluXG4gICAgICAgICAgICAgICAgICAgIC8vIGhhbmQ7IHRoZSBjb21wYXJpc29uIGhhcHBlbnMgb25jZSB0aGUgbmV4dCBsb2FkIHJlc29sdmVzLlxuICAgICAgICAgICAgICAgICAgICBwcmVjb25kaXRpb25SZXN0YXJ0QmFzZWxpbmUgPVxuICAgICAgICAgICAgICAgICAgICAgIGV2ZW50TG9nLnR5cGUgIT09ICdsb2FkQWxsJ1xuICAgICAgICAgICAgICAgICAgICAgICAgPyB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWRzOiBuZXcgU2V0KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRMb2cuZXZlbnRzLm1hcCgoZXZlbnQpID0+IGV2ZW50LmV2ZW50SWQpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN0YXJ0OiBwcmVjb25kaXRpb25SZXN0YXJ0cyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWFzb24sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlOiB1c2VkRGVsdGEgPyAnaW5saW5lLWRlbHRhJyA6ICdmdWxsLXJlbG9hZCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIDogbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGRlbHRhICYmIGV2ZW50TG9nLnR5cGUgIT09ICdsb2FkQWxsJykge1xuICAgICAgICAgICAgICAgICAgICAgIGFwcGVuZEV2ZW50TG9nKGV2ZW50TG9nLCBkZWx0YSk7XG4gICAgICAgICAgICAgICAgICAgICAgZXZlbnRMb2cgPSB7IC4uLmV2ZW50TG9nLCB0eXBlOiAncmVhZHknIH07XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgLy8gTVVTVCBiZSBhIGZ1bGwsIGN1cnNvci1sZXNzIHJlbG9hZC4gVGhlIGN1cnNvciBmaWx0ZXJzXG4gICAgICAgICAgICAgICAgICAgICAgLy8gYnkgbGV4aWNvZ3JhcGhpYyBldmVudCBpZCB3aGlsZSBhIGhvbGUgaXMgZGVmaW5lZCBieVxuICAgICAgICAgICAgICAgICAgICAgIC8vIFVMSUQgKnRpbWUqOiBhbiBldmVudCBpbiB0aGUgc2FtZSBtaWxsaXNlY29uZCBzb3J0c1xuICAgICAgICAgICAgICAgICAgICAgIC8vIGVpdGhlciBzaWRlIG9mIHRoZSBjdXJzb3IgZGVwZW5kaW5nIG9uIGl0cyByYW5kb21cbiAgICAgICAgICAgICAgICAgICAgICAvLyBjb21wb25lbnQsIGFuZCBhbiBldmVudCBtaW50ZWQgaW4gYW4gZWFybGllclxuICAgICAgICAgICAgICAgICAgICAgIC8vIG1pbGxpc2Vjb25kIGJ1dCBjb21taXR0ZWQgbGF0ZXIgYWx3YXlzIHNvcnRzIGJlbG93IGl0LlxuICAgICAgICAgICAgICAgICAgICAgIC8vIEFuIGluY3JlbWVudGFsIGxvYWQgdGhlcmVmb3JlIGhlYWxzIHRoZSBob2xlIG9ubHkgYnlcbiAgICAgICAgICAgICAgICAgICAgICAvLyBsdWNrLlxuICAgICAgICAgICAgICAgICAgICAgIGV2ZW50TG9nID0geyB0eXBlOiAnbG9hZEFsbCcgfTtcbiAgICAgICAgICAgICAgICAgICAgICAvLyBUaGUgY29ycmVjdGVkIGxvZyBpbnNlcnRzIHRoZSBtaXNzaW5nIGV2ZW50cyBCRUxPVyB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAvLyBsZW5ndGggYWxyZWFkeSBzY2FubmVkIGZvciBwYXlsb2FkIHByZXdhcm1pbmcsIHNoaWZ0aW5nXG4gICAgICAgICAgICAgICAgICAgICAgLy8gZXZlcnkgbGF0ZXIgcG9zaXRpb24uIE9ubHkgYSBmdWxsIHJlc2NhbiBzZWVzIHRoZW0uXG4gICAgICAgICAgICAgICAgICAgICAgcmVwbGF5UGF5bG9hZENhY2hlLnJlc2V0U2NhbigpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIud2FybihcbiAgICAgICAgICAgICAgICAgICAgICAnRXZlbnQgY3JlYXRpb24gcmVqZWN0ZWQgYXMgc3RhbGU7IHJlc3RhcnRpbmcgcmVwbGF5IGluLXByb2Nlc3MnLFxuICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVhc29uLFxuICAgICAgICAgICAgICAgICAgICAgICAgbG9vcEl0ZXJhdGlvbixcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZWNvbmRpdGlvblJlc3RhcnRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlOiB1c2VkRGVsdGEgPyAnaW5saW5lLWRlbHRhJyA6ICdmdWxsLXJlbG9hZCcsXG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAgICAgICAgICAgICAnd29ya2Zsb3cucHJlY29uZGl0aW9uX3Jlc3RhcnRzJzogcHJlY29uZGl0aW9uUmVzdGFydHMsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICAgICAgICogRXNjYWxhdGUgYSBzdGFsZS1zbmFwc2hvdCByZWplY3Rpb24gdGhhdCBzdXJ2aXZlZCB0aGVcbiAgICAgICAgICAgICAgICAgICAqIGluLXByb2Nlc3MgcmVzdGFydCBidWRnZXQgdG8gYSBmcmVzaCBpbnZvY2F0aW9uLCBvciBnaXZlIHVwXG4gICAgICAgICAgICAgICAgICAgKiBvbiB0aGUgcnVuIHdoZW4gdGhlIHBlci1ydW4gYnVkZ2V0IGlzIGFsc28gc3BlbnQuXG4gICAgICAgICAgICAgICAgICAgKlxuICAgICAgICAgICAgICAgICAgICogVGhlIGluLXByb2Nlc3MgYnVkZ2V0IGlzIGEgY2xvc3VyZSB2YXJpYWJsZSBhbmQgdGhlIHF1ZXVlJ3NcbiAgICAgICAgICAgICAgICAgICAqIGRlbGl2ZXJ5IGNvdW50IHJlc3RhcnRzIGF0IDEgd2hlbmV2ZXIgYSBuZXcgbWVzc2FnZSBpc1xuICAgICAgICAgICAgICAgICAgICogZW5xdWV1ZWQsIHNvIGEgcnVuIHRoYXQgaXMgcGVybWFuZW50bHkgdW5hYmxlIHRvIGNhdGNoIHVwXG4gICAgICAgICAgICAgICAgICAgKiB3aXRoIGl0cyBvd24gZXZlbnQgbG9nIHdvdWxkIG90aGVyd2lzZSBjeWNsZSByZXN0YXJ0cyDihpJcbiAgICAgICAgICAgICAgICAgICAqIHJlLWludm9rZSDihpIgcmVzdGFydHMgd2l0aCBubyBydW4tbGV2ZWwgYm91bmQuIFRoZSBjaGFpbiBpc1xuICAgICAgICAgICAgICAgICAgICogdGhlcmVmb3JlIGNvdW50ZWQgb24gdGhlIG1lc3NhZ2UgaXRzZWxmLCBpbiB0aGUgc2FtZSB3YXlcbiAgICAgICAgICAgICAgICAgICAqIHJlcGxheSBkaXZlcmdlbmNlcyBhcmUsIGFuZCBmYWlscyB0aGUgcnVuIG9uY2UgZXhoYXVzdGVkLlxuICAgICAgICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAgICAgICAqIFRoZSBjb3VudGVyIG9ubHkgYWR2YW5jZXMgb24gaG9wcyB0aGF0IGVucXVldWUgYSBuZXcgbWVzc2FnZVxuICAgICAgICAgICAgICAgICAgICogKHNlZSBgcmVpbnZva2VgKS4gQSByZWRlbGl2ZXJ5LWJhc2VkIGhvcCBrZWVwcyB0aGUgc2FtZSBib2R5XG4gICAgICAgICAgICAgICAgICAgKiBhbmQgc28gdGhlIHNhbWUgY291bnQsIGJ1dCBpdCBhbHNvIGtlZXBzIGFkdmFuY2luZ1xuICAgICAgICAgICAgICAgICAgICogYG1ldGFkYXRhLmF0dGVtcHRgLCB3aGljaCB0aGUgbWF4LWRlbGl2ZXJ5IGNoZWNrIGF0IHRoZSB0b3BcbiAgICAgICAgICAgICAgICAgICAqIG9mIHRoZSBoYW5kbGVyIGFscmVhZHkgYm91bmRzIOKAlCBhbmQgdGhlIGRlbGF5IGJlbG93IGlzIHdoYXRcbiAgICAgICAgICAgICAgICAgICAqIG1ha2VzIHRoYXQgYnVkZ2V0IHNwYW4gcmVhbCB0aW1lIHJhdGhlciB0aGFuIGJlaW5nIGJ1cm5lZCBpblxuICAgICAgICAgICAgICAgICAgICogYSB0aWdodCBsb29wLlxuICAgICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgICBjb25zdCByZWludm9rZUFmdGVyU3RhbGVSZWplY3Rpb24gPSBhc3luYyAoXG4gICAgICAgICAgICAgICAgICAgIHJlYXNvbjogc3RyaW5nLFxuICAgICAgICAgICAgICAgICAgICBlcnJvcjogdW5rbm93blxuICAgICAgICAgICAgICAgICAgKTogUHJvbWlzZTxcbiAgICAgICAgICAgICAgICAgICAgfCB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWludm9rZWQ6IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQ6IHsgdGltZW91dFNlY29uZHM6IG51bWJlciB9IHwgdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfCB7IHJlaW52b2tlZDogZmFsc2U7IGVycm9yOiBFcnJvciB9XG4gICAgICAgICAgICAgICAgICA+ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgYXR0ZW1wdCA9IChwcmVjb25kaXRpb25SZWludm9jYXRpb25zID8/IDApICsgMTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbWF4UmVpbnZvY2F0aW9ucyA9IGdldFByZWNvbmRpdGlvbk1heFJlaW52b2NhdGlvbnMoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGF0dGVtcHQgPiBtYXhSZWludm9jYXRpb25zKSB7XG4gICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlaW52b2tlZDogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvcjogbmV3IFdvcmtmbG93UnVudGltZUVycm9yKFxuICAgICAgICAgICAgICAgICAgICAgICAgICBgRXZlbnQgY3JlYXRpb24gd2FzIHJlamVjdGVkIGFzIHN0YWxlIGFmdGVyICR7bWF4UmVpbnZvY2F0aW9uc30gcmUtaW52b2NhdGlvbnMgb2YgJHtnZXRQcmVjb25kaXRpb25NYXhJblByb2Nlc3NSZXN0YXJ0cygpfSBpbi1wcm9jZXNzIHJlcGxheSByZXN0YXJ0cyBlYWNoOiB0aGlzIHJ1biBjYW5ub3Qgb2JzZXJ2ZSBpdHMgb3duIGV2ZW50IGxvZyBjb21wbGV0ZWx5IGVub3VnaCB0byBtYWtlIHByb2dyZXNzLiBMYXN0IHJlamVjdGlvbiAoJHtyZWFzb259KTogJHtlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvcil9YCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgeyBjYXVzZTogZXJyb3IgfVxuICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIud2FybihcbiAgICAgICAgICAgICAgICAgICAgICAnRXZlbnQgY3JlYXRpb24gcmVqZWN0ZWQgYXMgc3RhbGUgYWZ0ZXIgaW4tcHJvY2VzcyByZXN0YXJ0czsgcmUtaW52b2tpbmcgcnVuIGZvciBhIGZyZXNoIHJlcGxheScsXG4gICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICByZWFzb24sXG4gICAgICAgICAgICAgICAgICAgICAgICBsb29wSXRlcmF0aW9uLFxuICAgICAgICAgICAgICAgICAgICAgICAgcHJlY29uZGl0aW9uUmVpbnZvY2F0aW9uczogYXR0ZW1wdCxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1heFJlaW52b2NhdGlvbnMsXG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAgICAgICAgICAgICAnd29ya2Zsb3cucHJlY29uZGl0aW9uX3JlaW52b2NhdGlvbnMnOiBhdHRlbXB0LFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgLy8gRGVsYXllZCwgdW5saWtlIHRoZSBvdGhlciByZWludm9rZSgpIGNhbGxlcnM6IHRoZVxuICAgICAgICAgICAgICAgICAgICAvLyBpbi1wcm9jZXNzIHJlc3RhcnRzIGFscmVhZHkgcmVsb2FkZWQgdGhlIGxvZyBzZXZlcmFsIHRpbWVzXG4gICAgICAgICAgICAgICAgICAgIC8vIHdpdGhvdXQgY2F0Y2hpbmcgdXAsIHNvIHRoZSB3cml0ZXJzIHRoaXMgcmVwbGF5IGlzIHJhY2luZ1xuICAgICAgICAgICAgICAgICAgICAvLyBhcmUgc3RpbGwgYWN0aXZlLiBSZXRyeWluZyBpbnN0YW50bHkganVzdCBidXJucyB0aGVcbiAgICAgICAgICAgICAgICAgICAgLy8gcGVyLXJ1biBidWRnZXQgYXQgZnVsbCBzcGVlZC5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICByZWludm9rZWQ6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgcmVzdWx0OiBhd2FpdCByZWludm9rZShcbiAgICAgICAgICAgICAgICAgICAgICAgIGdldFByZWNvbmRpdGlvblJlaW52b2tlRGVsYXlTZWNvbmRzKCksXG4gICAgICAgICAgICAgICAgICAgICAgICB7IHByZWNvbmRpdGlvblJlaW52b2NhdGlvbnM6IGF0dGVtcHQgfVxuICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgICAvLyBEZXBsb3ltZW50LWFmZmluaXR5IGd1YXJkLCBzaGFyZWQgYnkgdGhlIHR3byBwYXRocyB0aGF0XG4gICAgICAgICAgICAgICAgICAvLyBleGVjdXRlIGEgcnVuOiBxdWV1ZWQgc3RlcCBleGVjdXRpb25zIGFuZCBmbG93IHJlcGxheXMuXG4gICAgICAgICAgICAgICAgICBjb25zdCBndWFyZERlcGxveW1lbnQgPSBhc3luYyAoXG4gICAgICAgICAgICAgICAgICAgIHJ1bjogUGljazxcbiAgICAgICAgICAgICAgICAgICAgICBXb3JrZmxvd1J1bixcbiAgICAgICAgICAgICAgICAgICAgICAncnVuSWQnIHwgJ2RlcGxveW1lbnRJZCcgfCAnc3BlY1ZlcnNpb24nXG4gICAgICAgICAgICAgICAgICAgID4sXG4gICAgICAgICAgICAgICAgICAgIHJlZW5xdWV1ZVBheWxvYWQ6ICgpID0+IFByb21pc2U8V29ya2Zsb3dJbnZva2VQYXlsb2FkPixcbiAgICAgICAgICAgICAgICAgICAgYmVmb3JlU3RvcD86ICgpID0+IFByb21pc2U8dm9pZD5cbiAgICAgICAgICAgICAgICAgICk6IFByb21pc2U8RGVwbG95bWVudEFmZmluaXR5T3V0Y29tZT4gPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB7IG91dGNvbWUsIHNwYW5BdHRyaWJ1dGVzIH0gPVxuICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IGd1YXJkRGVwbG95bWVudEFmZmluaXR5KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdvcmxkLFxuICAgICAgICAgICAgICAgICAgICAgICAgcnVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWVzdElkLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0cnlDb3VudDogZGVwbG95bWVudE1pc21hdGNoUmV0cnlDb3VudCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGJlZm9yZVN0b3AsXG4gICAgICAgICAgICAgICAgICAgICAgICBpc0RlcGxveW1lbnRVbmF2YWlsYWJsZUVycm9yOlxuICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JsZC5pc0RlcGxveW1lbnRVbmF2YWlsYWJsZUVycm9yLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVlbnF1ZXVlOiBhc3luYyAoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICBkZXBsb3ltZW50SWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHNwZWNWZXJzaW9uLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBkZXBsb3ltZW50TWlzbWF0Y2hSZXRyeUNvdW50OiByZXRyeUNvdW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICBkZWxheVNlY29uZHMsXG4gICAgICAgICAgICAgICAgICAgICAgICB9OiBSZWVucXVldWVBcmdzKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHF1ZXVlTWVzc2FnZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JsZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRXb3JrZmxvd1F1ZXVlTmFtZSh3b3JrZmxvd05hbWUsIG5hbWVzcGFjZSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uKGF3YWl0IHJlZW5xdWV1ZVBheWxvYWQoKSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXBsb3ltZW50TWlzbWF0Y2hSZXRyeUNvdW50OiByZXRyeUNvdW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgeyBkZXBsb3ltZW50SWQsIHNwZWNWZXJzaW9uLCBkZWxheVNlY29uZHMgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNwYW5BdHRyaWJ1dGVzKSBzcGFuPy5zZXRBdHRyaWJ1dGVzKHNwYW5BdHRyaWJ1dGVzKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG91dGNvbWU7XG4gICAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgICAvLyBJZiBpbmNvbWluZyBtZXNzYWdlIGhhcyBhIHN0ZXBJZCwgdGhpcyBpcyBhIGJhY2tncm91bmQgc3RlcFxuICAgICAgICAgICAgICAgICAgLy8gZXhlY3V0aW9uLiBFeGVjdXRlIHRoZSBzdGVwLCB0aGVuIGNoZWNrIGlmIGFsbCBwYXJhbGxlbCBzdGVwc1xuICAgICAgICAgICAgICAgICAgLy8gZnJvbSB0aGUgYmF0Y2ggYXJlIGRvbmUuIElmIHNvLCByZXBsYXkgaW5saW5lIChzYXZpbmcgYSBxdWV1ZVxuICAgICAgICAgICAgICAgICAgLy8gcm91bmR0cmlwKS4gSWYgbm90LCByZXR1cm4g4oCUIHRoZSBsYXN0IGhhbmRsZXIgdG8gY29tcGxldGVcbiAgICAgICAgICAgICAgICAgIC8vIHdpbGwgcGljayB1cCB0aGUgcmVwbGF5LlxuICAgICAgICAgICAgICAgICAgaWYgKGluY29taW5nU3RlcElkICYmIGluY29taW5nU3RlcE5hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBiZ1J1biA9IGF3YWl0IHdvcmxkLnJ1bnMuZ2V0KHJ1bklkLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlRGF0YTogJ25vbmUnLFxuICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgIGlmIChiZ1J1bi5zdGF0dXMgIT09ICdydW5uaW5nJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5kZWJ1ZyhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgJ1J1biBhbHJlYWR5IGZpbmlzaGVkLCBza2lwcGluZyBiYWNrZ3JvdW5kIHN0ZXAnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICB7IHdvcmtmbG93UnVuSWQ6IHJ1bklkLCBzdGF0dXM6IGJnUnVuLnN0YXR1cyB9XG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAvLyBDb3ZlcnMgZXZlcnkgcXVldWVkIHN0ZXAgZXhlY3V0aW9uIOKAlCBmaXJzdCBkaXNwYXRjaCBhbmRcbiAgICAgICAgICAgICAgICAgICAgICAvLyByZWRlbGl2ZXJpZXMvcmV0cmllcyBhbGlrZS5cbiAgICAgICAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAoYXdhaXQgZ3VhcmREZXBsb3ltZW50KGJnUnVuLCBhc3luYyAoKSA9PiAoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAuLi4oYXdhaXQgcmVwbGF5TWVzc2FnZSgpKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgc3RlcElkOiBpbmNvbWluZ1N0ZXBJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgc3RlcE5hbWU6IGluY29taW5nU3RlcE5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICB9KSkpICE9PSAnY29udGludWUnXG4gICAgICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGJnU3RhcnRlZEF0ID0gYmdSdW4uc3RhcnRlZEF0XG4gICAgICAgICAgICAgICAgICAgICAgICA/ICtiZ1J1bi5zdGFydGVkQXRcbiAgICAgICAgICAgICAgICAgICAgICAgIDogRGF0ZS5ub3coKTtcblxuICAgICAgICAgICAgICAgICAgICAgIC8vIFJldHJ5IGNlaWxpbmcgZm9yIGEgYmFja2dyb3VuZGVkIHN0ZXAuIGBtZXRhZGF0YS5hdHRlbXB0YFxuICAgICAgICAgICAgICAgICAgICAgIC8vICh0aGUgcXVldWUgZGVsaXZlcnkgY291bnQpIGlzIGEgY2hlYXAgdXBwZXIgYm91bmQsIGJ1dCBpdFxuICAgICAgICAgICAgICAgICAgICAgIC8vIG92ZXItY291bnRzOiBhIFRocm90dGxlRXJyb3IgLyBUb29FYXJseUVycm9yIOKAlCBvciBhbnlcbiAgICAgICAgICAgICAgICAgICAgICAvLyByZWRlbGl2ZXJ5IHRoYXQgbmV2ZXIgcmFuIHRoZSBib2R5IOKAlCBzdGlsbCBhZHZhbmNlcyBpdCwgc29cbiAgICAgICAgICAgICAgICAgICAgICAvLyB0cnVzdGluZyBpdCBkaXJlY3RseSBjb3VsZCBmYWlsIGEgc3RlcCBhcyBcImV4Y2VlZGVkIG1heFxuICAgICAgICAgICAgICAgICAgICAgIC8vIHJldHJpZXNcIiBiZWZvcmUgdGhlIGJvZHkgZXZlciByYW4gKGEgdXNlci12aXNpYmxlXG4gICAgICAgICAgICAgICAgICAgICAgLy8gcmVncmVzc2lvbiB1bmRlciB0cmFuc2llbnQgYmFja2VuZCBwcmVzc3VyZSkuIFVzZSBpdCBvbmx5XG4gICAgICAgICAgICAgICAgICAgICAgLy8gYXMgYSBmYXN0IGdhdGU6IHdoaWxlIGl0IGlzIGF0IG9yIHVuZGVyIHRoZSBjZWlsaW5nIHRoZVxuICAgICAgICAgICAgICAgICAgICAgIC8vIHN0ZXAgY2Fubm90IGJlIGV4aGF1c3RlZCwgc28gcHJvY2VlZCB3aXRob3V0IHRvdWNoaW5nIHRoZVxuICAgICAgICAgICAgICAgICAgICAgIC8vIGxvZy4gT25seSBvbmNlIGl0IGNyb3NzZXMgdGhlIGNlaWxpbmcgZG8gd2UgbG9hZCB0aGUgZnVsbFxuICAgICAgICAgICAgICAgICAgICAgIC8vIGV2ZW50IGxvZyBhbmQgZGVyaXZlIHRoZSBhdXRob3JpdGF0aXZlIGF0dGVtcHQgZnJvbSB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAvLyByZWNvcmRlZCBgc3RlcF9zdGFydGVkYCBjb3VudCDigJQgc2NvcGVkIHRvIHRoZSBsaWZlY3ljbGVcbiAgICAgICAgICAgICAgICAgICAgICAvLyBhdHRlbXB0IHRvdGFsIChiYXJlIHN0YXJ0cyBwbHVzIHRoZSBsYXJnZXN0IHNpbmdsZVxuICAgICAgICAgICAgICAgICAgICAgIC8vIG93bmVyJ3Mgc3RhcnRzKTogdGhyb3R0bGUvdG9vLWVhcmx5IHJlZGVsaXZlcmllcyB3cml0ZVxuICAgICAgICAgICAgICAgICAgICAgIC8vIG5vIHN0YXJ0IGF0IGFsbCwgcmFjaW5nIGludm9jYXRpb25zJyBvbmUtb2ZmIHN0YW1wZWRcbiAgICAgICAgICAgICAgICAgICAgICAvLyBkdXBsaWNhdGVzIGRvbid0IGFjY3VtdWxhdGUgKGNvdW50aW5nIHRoZW0gZmFsc2VseVxuICAgICAgICAgICAgICAgICAgICAgIC8vIGV4aGF1c3RlZCBoZWFsdGh5IHN0ZXBzIOKAlCBzZWUgY291bnRTdGVwU3RhcnRlZEV2ZW50cyksXG4gICAgICAgICAgICAgICAgICAgICAgLy8gYW5kIGF0dGVtcHRzIGJ1cm5lZCB1bmRlciBhIHByaW9yIGlubGluZS1vd25lcnNoaXBcbiAgICAgICAgICAgICAgICAgICAgICAvLyBwaGFzZSBzdGlsbCBjb3VudCwgc28gYSBzdGVwIHRoYXQgdGltZXMgb3V0IHVuZGVyXG4gICAgICAgICAgICAgICAgICAgICAgLy8gb3duZWQgcmVjb3ZlcnkgYW5kIHRoZW4gdHJhbnNpdGlvbnMgdG8gcXVldWVkL2JhcmVcbiAgICAgICAgICAgICAgICAgICAgICAvLyByZXRyaWVzIHRyaXBzIHRoZSBjb21iaW5lZCBjZWlsaW5nLiBUaGlzIHN0aWxsIGJvdW5kc1xuICAgICAgICAgICAgICAgICAgICAgIC8vIHRpbWVvdXRzLCB3aGljaCB3cml0ZSBubyBlcnJvciBmb3IgdGhlIHBvc3QtYm9keSBndWFyZFxuICAgICAgICAgICAgICAgICAgICAgIC8vIHRvIGNhdGNoLlxuICAgICAgICAgICAgICAgICAgICAgIGxldCBiZ0F1dGhvcml0YXRpdmVBdHRlbXB0ID0gbWV0YWRhdGEuYXR0ZW1wdDtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBiZ01heFJldHJpZXMgPVxuICAgICAgICAgICAgICAgICAgICAgICAgZ2V0U3RlcEZ1bmN0aW9uKGluY29taW5nU3RlcE5hbWUpPy5tYXhSZXRyaWVzID8/XG4gICAgICAgICAgICAgICAgICAgICAgICBERUZBVUxUX1NURVBfTUFYX1JFVFJJRVM7XG4gICAgICAgICAgICAgICAgICAgICAgaWYgKG1ldGFkYXRhLmF0dGVtcHQgPiBiZ01heFJldHJpZXMgKyAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBsb2FkZWQgPSBhd2FpdCBsb2FkV29ya2Zsb3dSdW5FdmVudHMocnVuSWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYmdBdXRob3JpdGF0aXZlQXR0ZW1wdCA9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50U3RlcFN0YXJ0ZWRFdmVudHMoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9hZGVkLmV2ZW50cyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmNvbWluZ1N0ZXBJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7IHR5cGU6ICd0b3RhbEF0dGVtcHRzJyB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICkgKyAxO1xuICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgIC8vIFBhdXNlIHRoZSByZXBsYXkgYnVkZ2V0IHdoaWxlIHRoZSBzdGVwIGJvZHkgcnVucyDigJRcbiAgICAgICAgICAgICAgICAgICAgICAvLyBzdGVwIGR1cmF0aW9uIGlzIGJvdW5kZWQgYnkgdGhlIHBsYXRmb3JtJ3MgZnVuY3Rpb25cbiAgICAgICAgICAgICAgICAgICAgICAvLyBtYXhEdXJhdGlvbiwgbm90IGJ5IHRoZSByZXBsYXkgdGltZW91dC4gU2VlIHRoZVxuICAgICAgICAgICAgICAgICAgICAgIC8vIFJlcGxheUJ1ZGdldCBkb2NzIGZvciB0aGUgY29udHJhY3QuXG4gICAgICAgICAgICAgICAgICAgICAgcmVwbGF5QnVkZ2V0LnBhdXNlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgbGV0IHN0ZXBSZXN1bHQ6IEF3YWl0ZWQ8UmV0dXJuVHlwZTx0eXBlb2YgZXhlY3V0ZVN0ZXA+PjtcbiAgICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2luZ2xlLWZsaWdodDogYSBkZWxheWVkIGJhY2tzdG9wIChvciByZXRyeSkgbWVzc2FnZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gY2FuIGFycml2ZSB3aGlsZSBhbm90aGVyIGV4ZWN1dGlvbiBvZiB0aGlzIHNhbWUgc3RlcFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXMgbWlkLWJvZHkgaW4gdGhpcyBwcm9jZXNzIOKAlCBtb3N0IGltcG9ydGFudGx5IG9uXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB3b3JsZHMgd2l0aCBubyBpbnZvY2F0aW9uIGtpbGwgYm91bmQgKHdvcmxkLWxvY2FsKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHdoZXJlIHRoZSBvd25lcnNoaXAgbGVhc2UgaXMgbm90IGEgZGVhdGggcHJvb2YuIFRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbG9zZXIgYXdhaXRzIHRoZSB3aW5uZXIncyBzZXR0bGVtZW50LCB0aGVuIGFja3NcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHdpdGhvdXQgZXhlY3V0aW5nLiBObyBvd25lck1lc3NhZ2VJZCBoZXJlOiB0aGUgYmFyZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gc3RlcF9zdGFydGVkIG9mIGEgcXVldWUtZHJpdmVuIGV4ZWN1dGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW50ZW50aW9uYWxseSBjbGVhcnMgaW5saW5lIG93bmVyc2hpcCAodGhlIHN0ZXAgaXNcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHF1ZXVlLW93bmVkIGZyb20gdGhpcyBwb2ludCkuXG4gICAgICAgICAgICAgICAgICAgICAgICBzdGVwUmVzdWx0ID0gYXdhaXQgcnVuU3RlcFNpbmdsZUZsaWdodChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGluY29taW5nU3RlcElkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAoKSA9PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4ZWN1dGVTdGVwKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmxkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd0RlcGxveW1lbnRJZDogYmdSdW4uZGVwbG95bWVudElkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dTdGFydGVkQXQ6IGJnU3RhcnRlZEF0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdFJ1bklkOiByb290UnVuSWRGcm9tKGJnUnVuLmF0dHJpYnV0ZXMsIHJ1bklkKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXBJZDogaW5jb21pbmdTdGVwSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGVwTmFtZTogaW5jb21pbmdTdGVwTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJ1blNwZWNWZXJzaW9uOiBiZ1J1bi5zcGVjVmVyc2lvbixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJldHJ5IGNlaWxpbmc6IHRoZSBxdWV1ZSBkZWxpdmVyeSBjb3VudCBhcyBhIGZhc3RcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGdhdGUsIHZlcmlmaWVkIGFnYWluc3QgdGhlIHJlY29yZGVkIHN0ZXBfc3RhcnRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gY291bnQgb25jZSBpdCBjcm9zc2VzIHRoZSBjZWlsaW5nIChzZWUgYWJvdmUpLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXV0aG9yaXRhdGl2ZUF0dGVtcHQ6IGJnQXV0aG9yaXRhdGl2ZUF0dGVtcHQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlcGxheUJ1ZGdldC5yZXN1bWUoKTtcbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgaWYgKHN0ZXBSZXN1bHQudHlwZSA9PT0gJ3JldHJ5Jykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHsgdGltZW91dFNlY29uZHM6IHN0ZXBSZXN1bHQudGltZW91dFNlY29uZHMgfTtcbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgaWYgKHN0ZXBSZXN1bHQudHlwZSA9PT0gJ3Rocm90dGxlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7IHRpbWVvdXRTZWNvbmRzOiBzdGVwUmVzdWx0LnRpbWVvdXRTZWNvbmRzIH07XG4gICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgLy8gSWYgc3RlcCBoYWQgcGVuZGluZyBvcHMgKHN0cmVhbSB3cml0ZXMpLCBicmVhayBhbmQgbGV0XG4gICAgICAgICAgICAgICAgICAgICAgLy8gd2FpdFVudGlsIGZsdXNoIHRoZW0g4oCUIGNhbid0IGNvbnRpbnVlIGlubGluZS5cbiAgICAgICAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgICAgICBzdGVwUmVzdWx0LnR5cGUgPT09ICdjb21wbGV0ZWQnICYmXG4gICAgICAgICAgICAgICAgICAgICAgICBzdGVwUmVzdWx0Lmhhc1BlbmRpbmdPcHNcbiAgICAgICAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHF1ZXVlTWVzc2FnZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgd29ybGQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGdldFdvcmtmbG93UXVldWVOYW1lKHdvcmtmbG93TmFtZSwgbmFtZXNwYWNlKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNlQ2FycmllcjogYXdhaXQgbmV4dFRyYWNlQ2FycmllcigpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcXVlc3RlZEF0OiBuZXcgRGF0ZSgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXBSZXN1bHQudHlwZSA9PT0gJ2NvbXBsZXRlZCcgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXBSZXN1bHQudHlwZSA9PT0gJ2ZhaWxlZCcgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXBSZXN1bHQudHlwZSA9PT0gJ3NraXBwZWQnXG4gICAgICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBMb2FkIGV2ZW50cyB0byBjaGVjayBpZiBhbGwgcGFyYWxsZWwgc3RlcHMgYXJlIGRvbmUuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBVc2UgY3Vyc29yLWJhc2VkIGxvYWRpbmcgc28gdGhlIG1haW4gbG9vcCBjYW4gY29udGludWVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluY3JlbWVudGFsbHkgZnJvbSBoZXJlLlxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbG9hZGVkID0gYXdhaXQgbG9hZFdvcmtmbG93UnVuRXZlbnRzKHJ1bklkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50TG9nID0gbmV4dEV2ZW50TG9nTG9hZChsb2FkZWQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBDaGVjayBmb3IgcGVuZGluZyBzdGVwczogYW55IHN0ZXBfY3JlYXRlZCB3aXRob3V0XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhIG1hdGNoaW5nIHN0ZXBfY29tcGxldGVkIG9yIHN0ZXBfZmFpbGVkLlxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RlcENyZWF0ZWRJZHMgPSBuZXcgU2V0PHN0cmluZyB8IHVuZGVmaW5lZD4oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0ZXBUZXJtaW5hbElkcyA9IG5ldyBTZXQ8c3RyaW5nIHwgdW5kZWZpbmVkPigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBlIG9mIGxvYWRlZC5ldmVudHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGUuZXZlbnRUeXBlID09PSAnc3RlcF9jcmVhdGVkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXBDcmVhdGVkSWRzLmFkZChlLmNvcnJlbGF0aW9uSWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGUuZXZlbnRUeXBlID09PSAnc3RlcF9jb21wbGV0ZWQnIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZS5ldmVudFR5cGUgPT09ICdzdGVwX2ZhaWxlZCdcbiAgICAgICAgICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RlcFRlcm1pbmFsSWRzLmFkZChlLmNvcnJlbGF0aW9uSWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwZW5kaW5nU3RlcElkcyA9IG5ldyBTZXQ8c3RyaW5nIHwgdW5kZWZpbmVkPigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBpZCBvZiBzdGVwQ3JlYXRlZElkcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXN0ZXBUZXJtaW5hbElkcy5oYXMoaWQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGVuZGluZ1N0ZXBJZHMuYWRkKGlkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocGVuZGluZ1N0ZXBJZHMuc2l6ZSA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQSBwZW5kaW5nIHN0ZXAgdGhhdCBUSElTIG1lc3NhZ2UgaW5saW5lLW93bnMgKGFcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gcHJldmlvdXMgZGVsaXZlcnkgb2YgdGhpcyBtZXNzYWdlIHN0YW1wZWQgaXRzXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHN0ZXBfc3RhcnRlZCBhbmQgdGhlbiBjcmFzaGVkIG1pZC1ib2R5KSBtdXN0IGJlXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHJlY292ZXJlZCBoZXJlOiBvbmx5IHRoZSBvd25pbmcgbWVzc2FnZSBtYXlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gcmUtZXhlY3V0ZSBpdCBiZWZvcmUgdGhlIG93bmVyc2hpcCBsZWFzZSBleHBpcmVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhbmQgd2FrZSByZXBsYXlzIG1lcmVseSBlbnN1cmUgYSBkZWxheWVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGJhY2tzdG9wLiBGYWxsIHRocm91Z2ggdG8gdGhlIG1haW4gbG9vcCwgd2hvc2VcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gZGlzcGF0Y2ggdGFibGUgcm91dGVzIGl0IHRvIG93bmVkIHJlY292ZXJ5LlxuICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNJbmxpbmVPd25lcnNoaXBFbmFibGVkKCkgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNQZW5kaW5nU3RlcE93bmVkQnlNZXNzYWdlKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9hZGVkLmV2ZW50cyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBlbmRpbmdTdGVwSWRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGEubWVzc2FnZUlkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBydW50aW1lTG9nZ2VyLmRlYnVnKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0JhY2tncm91bmQgc3RlcCBkb25lOyBmYWxsaW5nIHRocm91Z2ggdG8gcmVjb3ZlciBhbiBpbmxpbmUgc3RlcCBvd25lZCBieSB0aGlzIG1lc3NhZ2UnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeyB3b3JrZmxvd1J1bklkOiBydW5JZCB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPdGhlciBzdGVwcyBzdGlsbCBpbiBwcm9ncmVzcy4gUmV0dXJuIHdpdGhvdXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBxdWV1aW5nIOKAlCB0aGUgbGFzdCBoYW5kbGVyIHRvIGNvbXBsZXRlIHdpbGwgc2VlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWxsIHN0ZXBzIGRvbmUgYW5kIHJlcGxheSBpbmxpbmUuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5kZWJ1ZyhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdCYWNrZ3JvdW5kIHN0ZXAgZG9uZSBidXQgb3RoZXIgc3RlcHMgcGVuZGluZywgcmV0dXJuaW5nJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsgd29ya2Zsb3dSdW5JZDogcnVuSWQgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFsbCBzdGVwcyBkb25lIOKAlCBmYWxsIHRocm91Z2ggdG8gdGhlIG1haW4gcmVwbGF5IGxvb3AuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBTZXQgdXAgc2hhcmVkIHN0YXRlIHNvIHRoZSBsb29wIGNhbiBjb250aW51ZS5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuZGVidWcoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICdBbGwgcGFyYWxsZWwgc3RlcHMgZG9uZSwgcmVwbGF5aW5nIGlubGluZSBhZnRlciBiYWNrZ3JvdW5kIHN0ZXAnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICB7IHdvcmtmbG93UnVuSWQ6IHJ1bklkIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBydW5DcmVhdGVkRXZlbnQgPSBsb2FkZWQuZXZlbnRzLmZpbmQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgIChldmVudCkgPT4gZXZlbnQuZXZlbnRUeXBlID09PSAncnVuX2NyZWF0ZWQnXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHJlcGxheUlucHV0OiB1bmtub3duO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJ1bkNyZWF0ZWRFdmVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICByZXBsYXlJbnB1dCA9IHJ1bkNyZWF0ZWRFdmVudC5ldmVudERhdGEuaW5wdXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWlzTGVnYWN5U3BlY1ZlcnNpb24oYmdSdW4uc3BlY1ZlcnNpb24pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFdvcmtmbG93UnVudGltZUVycm9yKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYFdvcmtmbG93IHJ1biBcIiR7cnVuSWR9XCIgaGFzIG5vIFwicnVuX2NyZWF0ZWRcIiBldmVudGBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIExlZ2FjeSBydW5zIHByZWRhdGUgdGhlIGV2ZW50LXNvdXJjZWQgcnVuX2NyZWF0ZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW52YXJpYW50LCBzbyByZXRhaW4gdGhlIHJlc29sdmVkIEdFVCBvbmx5IGZvciB0aGVtLlxuICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBsZWdhY3lSdW4gPSBhd2FpdCB3b3JsZC5ydW5zLmdldChydW5JZCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmVEYXRhOiAnYWxsJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsZWdhY3lSdW4uc3RhdHVzICE9PSAncnVubmluZycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwbGF5SW5wdXQgPSBsZWdhY3lSdW4uaW5wdXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1biA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uYmdSdW4sXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0OiByZXBsYXlJbnB1dCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdHVzOiAncnVubmluZycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvcjogdW5kZWZpbmVkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBjb21wbGV0ZWRBdDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93U3RhcnRlZEF0ID0gYmdTdGFydGVkQXQ7XG4gICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yQ29kZSA9IGdldFdvcmtmbG93U2V0dXBFcnJvckNvZGUoZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgICBpZiAoIWVycm9yQ29kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICBhd2FpdCByZWNvcmRGYXRhbFJ1bkVycm9yKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdvcmxkLFxuICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlcXVlc3RJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycixcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ29kZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvZ01lc3NhZ2U6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICdGYXRhbCBlcnJvciB3aGlsZSBwcmVwYXJpbmcgYmFja2dyb3VuZCB3b3JrZmxvdyBzdGVwJyxcbiAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgLy8gRGVwbG95bWVudC1hZmZpbml0eSBwcmUtY2hlY2sgZm9yIHRoZSBsYXp5IGhvb2sgZmFzdFxuICAgICAgICAgICAgICAgICAgLy8gcGF0aCBiZWxvdy4gTmV3IGxhenktcmVzdW1lIG1lc3NhZ2VzIGNhcnJ5IHRoZSBydW4nc1xuICAgICAgICAgICAgICAgICAgLy8gcGlubmVkIGRlcGxveW1lbnQgKGBob29rSW5wdXQuZGVwbG95bWVudElkYCksIHNvIGFcbiAgICAgICAgICAgICAgICAgIC8vIG1pc3JvdXRlZCBkZWxpdmVyeSBpcyBkZXRlY3RhYmxlIHdpdGggYSBjaGVhcCBhbWJpZW50XG4gICAgICAgICAgICAgICAgICAvLyBkZXBsb3ltZW50LWlkIGNvbXBhcmlzb24gQkVGT1JFIHRoZSBmYXN0IHBhdGgnc1xuICAgICAgICAgICAgICAgICAgLy8gaG9va19yZWNlaXZlZCB3cml0ZSDigJQgdGhlIGNvcnJlY3RseS1yb3V0ZWQgY29tbW9uIGNhc2VcbiAgICAgICAgICAgICAgICAgIC8vIHBheXMgbm8gcnVuIGZldGNoIGFuZCBubyBsYXRlbmN5LiBPbmx5IGEgZGV0ZWN0ZWRcbiAgICAgICAgICAgICAgICAgIC8vIG1pc21hdGNoIGZldGNoZXMgdGhlIGF1dGhvcml0YXRpdmUgcnVuIGFuZCBoYW5kcyBpdCB0b1xuICAgICAgICAgICAgICAgICAgLy8gdGhlIGV4aXN0aW5nIGd1YXJkICh3aGljaCBvd25zIHJlLXJvdXRlL2ZhaWwgcG9saWN5KTtcbiAgICAgICAgICAgICAgICAgIC8vIHRoZSByZS1yb3V0ZWQgbWVzc2FnZSBrZWVwcyB0aGUgY29tcGxldGUgYGhvb2tJbnB1dGAsXG4gICAgICAgICAgICAgICAgICAvLyBzaW5jZSBpdCBtYXkgaG9sZCB0aGUgb25seSBjb3B5IG9mIHRoZSByZXN1bWUgcGF5bG9hZC5cbiAgICAgICAgICAgICAgICAgIC8vIFdoZW4gdGhlIHBpbm5lZCBvciBhbWJpZW50IGlkIGlzIHVuYXZhaWxhYmxlIChvbGRlclxuICAgICAgICAgICAgICAgICAgLy8gcHJvZHVjZXIgbWVzc2FnZSwgYSB3b3JsZCB3aXRob3V0IGRlcGxveW1lbnQgYWZmaW5pdHksXG4gICAgICAgICAgICAgICAgICAvLyBvciBhIGdldERlcGxveW1lbnRJZCBmYWlsdXJlKSwgYmVoYXZpb3IgaXMgdW5jaGFuZ2VkOlxuICAgICAgICAgICAgICAgICAgLy8gdGhlIGF1dGhvcml0YXRpdmUgZ3VhcmQgYWZ0ZXIgcnVuIHNldHVwIOKAlCB3aGljaCByZW1haW5zXG4gICAgICAgICAgICAgICAgICAvLyB0aGUgcHJvdGVjdGlvbiBiZWZvcmUgcmVwbGF5IGFuZCBzdGVwIGV4ZWN1dGlvbiDigJQgc3RpbGxcbiAgICAgICAgICAgICAgICAgIC8vIGNvdmVycyB0aGUgZGVsaXZlcnk7IHRoZSBmYXN0IHBhdGgncyB3cml0ZSBpcyBpZGVtcG90ZW50XG4gICAgICAgICAgICAgICAgICAvLyBwZXIgKHJ1bklkLCByZXN1bWVJZCksIHNvIGEgcHJlLWd1YXJkIHdyaXRlIGZyb20gYW5cbiAgICAgICAgICAgICAgICAgIC8vIG9sZGVyIG1lc3NhZ2Ugc3RheXMgY29udmVyZ2VudC5cbiAgICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgIXdvcmtmbG93UnVuICYmXG4gICAgICAgICAgICAgICAgICAgIGhvb2tJbnB1dD8uZGVwbG95bWVudElkICE9PSB1bmRlZmluZWQgJiZcbiAgICAgICAgICAgICAgICAgICAgLy8gU2FtZSBlbGlnaWJpbGl0eSBhcyBndWFyZERlcGxveW1lbnRBZmZpbml0eTogd2l0aG91dFxuICAgICAgICAgICAgICAgICAgICAvLyBhdG9taWMsIGltbXV0YWJsZSBkZXBsb3ltZW50cyB0aGUgaWRzIGxlZ2l0aW1hdGVseVxuICAgICAgICAgICAgICAgICAgICAvLyBkaWZmZXIgKGUuZy4gZHBsX2xvY2FsQDx2ZXJzaW9uPikgYW5kIGNvbXBhcmluZyB0aGVtXG4gICAgICAgICAgICAgICAgICAgIC8vIHdvdWxkIHRyaWdnZXIgc3B1cmlvdXMgcnVuIGZldGNoZXMuXG4gICAgICAgICAgICAgICAgICAgIHdvcmxkLmNhcGFiaWxpdGllcz8uZGVwbG95bWVudEFmZmluaXR5ID09PSB0cnVlXG4gICAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGlubmVkRGVwbG95bWVudElkID0gaG9va0lucHV0LmRlcGxveW1lbnRJZDtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGN1cnJlbnREZXBsb3ltZW50SWQ6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50RGVwbG95bWVudElkID0gYXdhaXQgd29ybGQuZ2V0RGVwbG95bWVudElkKCk7XG4gICAgICAgICAgICAgICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnREZXBsb3ltZW50SWQgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnREZXBsb3ltZW50SWQgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnREZXBsb3ltZW50SWQgIT09IHBpbm5lZERlcGxveW1lbnRJZFxuICAgICAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBydW4gPSBhd2FpdCB3b3JsZC5ydW5zLmdldChydW5JZCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZURhdGE6ICdub25lJyxcbiAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAoYXdhaXQgZ3VhcmREZXBsb3ltZW50KFxuICAgICAgICAgICAgICAgICAgICAgICAgICBydW4sXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGFzeW5jICgpID0+ICh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uKGF3YWl0IHJlcGxheU1lc3NhZ2UoKSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9va0lucHV0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXRSdW5SZWFkeVxuICAgICAgICAgICAgICAgICAgICAgICAgKSkgIT09ICdjb250aW51ZSdcbiAgICAgICAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgLy8gLS0tIExhenkgaG9vayByZXN1bWUgZmFzdCBwYXRoIC0tLVxuICAgICAgICAgICAgICAgICAgLy8gQSBsYXp5IGhvb2sgZGVsaXZlcnkgKHJlc3VtZUlkICsgZGlnZXN0IG9uIHRoZSBxdWV1ZVxuICAgICAgICAgICAgICAgICAgLy8gbWVzc2FnZSkgaG9pc3RzIHRoZSBjb25zdW1lcidzIGlkZW1wb3RlbnQgaG9va19yZWNlaXZlZFxuICAgICAgICAgICAgICAgICAgLy8gcmUtZW5zdXJlIGFib3ZlIHJ1bl9zdGFydGVkIGFuZCBhc2tzIHRoZSBXb3JsZCB0byByZXR1cm5cbiAgICAgICAgICAgICAgICAgIC8vIHRoZSBjdXJyZW50IHJlcGxheSBsb2cgd2l0aCB0aGUgd3JpdGUgKHByZWxvYWRFdmVudHMpLiBBXG4gICAgICAgICAgICAgICAgICAvLyBzdXBwb3J0aW5nIFdvcmxkIGFuc3dlcnMgd2l0aCB0aGUgcmVjb25zdHJ1Y3RlZCBydW4sIHRoZVxuICAgICAgICAgICAgICAgICAgLy8gY29tcGxldGUgcmVwbGF5IGxvZywgYW5kIHRoZSBydW4ncyBldmVudCBjZWlsaW5nIOKAlFxuICAgICAgICAgICAgICAgICAgLy8gZXZlcnl0aGluZyB0aGUgZ2VuZXJpYyBzZXR1cCBiZWxvdyB3b3VsZCBzcGVuZCBhXG4gICAgICAgICAgICAgICAgICAvLyBydW5fc3RhcnRlZCBQT1NUIGFuZCBhbiBldmVudHMubGlzdCBvbi4gQW55IG90aGVyIHJlc3VsdFxuICAgICAgICAgICAgICAgICAgLy8gKG9sZGVyIHNlcnZlciwgYSBXb3JsZCB0aGF0IGlnbm9yZXMgdGhlIHBhcmFtLCBvciBhXG4gICAgICAgICAgICAgICAgICAvLyBwcmVsb2FkIHRoYXQgZmFpbHMgdmFsaWRhdGlvbiwgaW5jbHVkaW5nIGEgYm91bmRlZFxuICAgICAgICAgICAgICAgICAgLy8gaGFzTW9yZSBwYWdlKSBmYWxscyBiYWNrIHRvIHRoYXQgZ2VuZXJpYyBzZXR1cDsgdGhlXG4gICAgICAgICAgICAgICAgICAvLyBob29rX3JlY2VpdmVkIHdyaXRlIGl0c2VsZiBoYXMgc3RpbGwgc3VjY2VlZGVkIGVpdGhlclxuICAgICAgICAgICAgICAgICAgLy8gd2F5LCBzbyB0aGUgcmUtZW5zdXJlIGJsb2NrIGJlbG93IGlzIHNraXBwZWQgdmlhXG4gICAgICAgICAgICAgICAgICAvLyBgaG9va0Vuc3VyZWRgLiBOZXZlciB0YWtlbiBvbiB0dXJibyAodHVyYm8gZGVsaXZlcmllc1xuICAgICAgICAgICAgICAgICAgLy8gY2FycnkgcnVuSW5wdXQsIG5vdCBob29rSW5wdXQpIG9yIGFmdGVyIHRoZSBiYWNrZ3JvdW5kXG4gICAgICAgICAgICAgICAgICAvLyBzdGVwIHBhdGggYWxyZWFkeSBsb2FkZWQgdGhlIHJ1bi5cbiAgICAgICAgICAgICAgICAgIGxldCBob29rRW5zdXJlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICAhd29ya2Zsb3dSdW4gJiZcbiAgICAgICAgICAgICAgICAgICAgaG9va0lucHV0ICYmXG4gICAgICAgICAgICAgICAgICAgIGhvb2tJbnB1dC5yZXN1bWVJZCAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAgICAgICAgICAgICAgIGhvb2tJbnB1dC5wYXlsb2FkRGlnZXN0ICE9PSB1bmRlZmluZWRcbiAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBob29rUmVzdW1lSW5wdXQgPSBob29rSW5wdXQ7XG4gICAgICAgICAgICAgICAgICAgIC8vIERhdGUgdGhlIG1hdGVyaWFsaXplZCBldmVudCB0byB3aGVuIHRoZSByZXN1bWUgYWN0dWFsbHlcbiAgICAgICAgICAgICAgICAgICAgLy8gb2NjdXJyZWQg4oCUIHNhbWUgZGVyaXZhdGlvbiBhcyB0aGUgcmUtZW5zdXJlIGJlbG93ICh0aGVcbiAgICAgICAgICAgICAgICAgICAgLy8gcmVzdW1lSWQgaXMgYSBVTElEIG1pbnRlZCBieSByZXN1bWVIb29rKCkgYXQgcmVzdW1lXG4gICAgICAgICAgICAgICAgICAgIC8vIHRpbWUpLlxuICAgICAgICAgICAgICAgICAgICBsZXQgb2NjdXJyZWRBdDogRGF0ZSB8IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICBvY2N1cnJlZEF0ID0gbmV3IERhdGUoXG4gICAgICAgICAgICAgICAgICAgICAgICBkZWNvZGVUaW1lKGhvb2tSZXN1bWVJbnB1dC5yZXN1bWVJZClcbiAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgICAgICAgICAgICBvY2N1cnJlZEF0ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgc3Bhbj8uYWRkRXZlbnQoJ3dvcmtmbG93Lmhvb2tfcmVjZWl2ZWQuY3JlYXRlLnN0YXJ0Jywge1xuICAgICAgICAgICAgICAgICAgICAgICAgJ3dvcmtmbG93Lmhvb2tfcmVjZWl2ZWQucHJlbG9hZF9ldmVudHMnOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNyZWF0ZUV2ZW50KFxuICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudFR5cGU6ICdob29rX3JlY2VpdmVkJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBob29rUmVzdW1lSW5wdXQuaG9va0lkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b2tlbjogaG9va1Jlc3VtZUlucHV0LnRva2VuLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBheWxvYWQ6IGhvb2tSZXN1bWVJbnB1dC5wYXlsb2FkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWVzdElkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBvY2N1cnJlZEF0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bWVJZDogaG9va1Jlc3VtZUlucHV0LnJlc3VtZUlkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bWVQYXlsb2FkRGlnZXN0OiBob29rUmVzdW1lSW5wdXQucGF5bG9hZERpZ2VzdCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlbG9hZEV2ZW50czogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgIGhvb2tFbnN1cmVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAvLyBOb3RlOiB1bmxpa2UgdGhlIHJlLWVuc3VyZSBiZWxvdywgdGhpcyBob2lzdGVkIHdyaXRlXG4gICAgICAgICAgICAgICAgICAgICAgLy8gZG9lcyBOT1Qgc2V0IEhvb2tSZXNpbGllbnRSZXN1bWVNYXRlcmlhbGl6ZWQg4oCUIGl0XG4gICAgICAgICAgICAgICAgICAgICAgLy8gcnVucyBvbiBldmVyeSBmYXN0LXBhdGggcmVzdW1lLCBpbmNsdWRpbmcgdGhlIGNvbW1vblxuICAgICAgICAgICAgICAgICAgICAgIC8vIGNhc2Ugd2hlcmUgdGhlIHByb2R1Y2VyJ3MgZGlyZWN0IHdyaXRlIGFscmVhZHkgbGFuZGVkXG4gICAgICAgICAgICAgICAgICAgICAgLy8gYW5kIHRoaXMgY2FsbCBtZXJlbHkgY29udmVyZ2VkIG9uIGl0LCBzbyBpdCBjYXJyaWVzXG4gICAgICAgICAgICAgICAgICAgICAgLy8gbm8gcmVjb3Zlcnkgc2lnbmFsLiB3b3JrZmxvdy5yZXN1bWVfc2V0dXBfc291cmNlXG4gICAgICAgICAgICAgICAgICAgICAgLy8gKGJlbG93KSBkZXNjcmliZXMgdGhpcyBwYXRoIGluc3RlYWQuXG5cbiAgICAgICAgICAgICAgICAgICAgICAvLyBUaGUgcHJlbG9hZCBpcyB1c2FibGUgYXMgcmVwbGF5IGlucHV0IG9ubHkgd2hlbiBpdCBpc1xuICAgICAgICAgICAgICAgICAgICAgIC8vIGRlbW9uc3RyYWJseSB0aGUgY29tcGxldGUgcGljdHVyZTogYSByZWNvbnN0cnVjdGVkXG4gICAgICAgICAgICAgICAgICAgICAgLy8gcnVuIHdpdGggYSBzdGFydCB0aW1lLCBhIG5vbi1lbXB0eSBDT01QTEVURSBsb2dcbiAgICAgICAgICAgICAgICAgICAgICAvLyAoaGFzTW9yZSBmYWxzZSDigJQgdGhpcyBwYXRoIGhhcyBubyBjdXJzb3ItY29udGludWF0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgLy8gbWFjaGluZXJ5LCBzbyBhIGJvdW5kZWQgcGFnZSBtdXN0IG5vdCBiZSB0cnVzdGVkKSxcbiAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgc2VydmVyJ3MgZXZlbnQgY2VpbGluZyAodGhpcyByZXNwb25zZSBwbGF5c1xuICAgICAgICAgICAgICAgICAgICAgIC8vIHJ1bl9zdGFydGVkJ3Mgcm9sZSwgc28gYSBtaXNzaW5nIGNlaWxpbmcgd291bGQgbGVhdmVcbiAgICAgICAgICAgICAgICAgICAgICAvLyBldmVudC1saW1pdCBlbmZvcmNlbWVudCBkaXNhYmxlZCBmb3IgdGhlIHJ1biksXG4gICAgICAgICAgICAgICAgICAgICAgLy8gYm90aCBydW4gbGlmZWN5Y2xlIGV2ZW50cywgdGhlIGNhbm9uaWNhbCBldmVudCB0aGlzXG4gICAgICAgICAgICAgICAgICAgICAgLy8gd3JpdGUgY29udmVyZ2VkIG9uLCBhbmQgdGhlIGhvb2tfcmVjZWl2ZWQgbWF0Y2hpbmdcbiAgICAgICAgICAgICAgICAgICAgICAvLyBUSElTIHJlc3VtZSAoc28gd2UgbmV2ZXIgcmVwbGF5IGFnYWluc3QgYSBsb2cgdGhhdCBpc1xuICAgICAgICAgICAgICAgICAgICAgIC8vIG1pc3NpbmcgdGhlIHZlcnkgZXZlbnQgdGhhdCB0cmlnZ2VyZWQgdGhpcyBkZWxpdmVyeSkuXG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgdXNhYmxlUmVwbGF5UHJlbG9hZCA9XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQucnVuICE9PSB1bmRlZmluZWQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5ydW4uc3RhcnRlZEF0ICE9PSB1bmRlZmluZWQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5ldmVudCAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuZXZlbnRzICE9PSB1bmRlZmluZWQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5ldmVudHMubGVuZ3RoID4gMCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmN1cnNvciAhPSBudWxsICYmXG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuaGFzTW9yZSA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGVvZiByZXN1bHQubWF4RXZlbnRzID09PSAnbnVtYmVyJyAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmV2ZW50cy5zb21lKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAoZSkgPT4gZS5ldmVudFR5cGUgPT09ICdydW5fY3JlYXRlZCdcbiAgICAgICAgICAgICAgICAgICAgICAgICkgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5ldmVudHMuc29tZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgKGUpID0+IGUuZXZlbnRUeXBlID09PSAncnVuX3N0YXJ0ZWQnXG4gICAgICAgICAgICAgICAgICAgICAgICApICYmXG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuZXZlbnRzLnNvbWUoXG4gICAgICAgICAgICAgICAgICAgICAgICAgIChlKSA9PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGUuZXZlbnRUeXBlID09PSAnaG9va19yZWNlaXZlZCcgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlLnJlc3VtZUlkID09PSBob29rUmVzdW1lSW5wdXQucmVzdW1lSWRcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgICAgICB1c2FibGVSZXBsYXlQcmVsb2FkICYmXG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQucnVuPy5zdGFydGVkQXQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5ldmVudHNcbiAgICAgICAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZSByZWNvbnN0cnVjdGVkIHJ1biBhbHdheXMgcmVhZHMgJ3J1bm5pbmcnLCBidXQgYVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGVybWluYWwgZXZlbnQgY29tbWl0dGVkIGNvbmN1cnJlbnRseSByaWRlcyBpbiB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGxvZyBpdHNlbGYuIFRoZSBub2RlIHJlcGxheSBsb29wIHdvdWxkIGNhdGNoIGl0LCBidXRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFF1aWNrSlMgZGlzcGF0Y2hlcyBiZWZvcmUgdGhhdCBjaGVjayDigJQgc28gY29uc3VtZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIGRlbGl2ZXJ5IGhlcmUsIGJlZm9yZSBhbnkgZW5naW5lIHJ1bnMuIFNhbWVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG91dGNvbWUgYXMgdGhlIHJ1bl9zdGFydGVkIHBhdGgncyBub24tcnVubmluZ1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gc3RhdHVzIGNoZWNrLlxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdGVybWluYWxFdmVudCA9IHJlc3VsdC5ldmVudHMuZmluZChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgKGUpID0+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZS5ydW5JZCA9PT0gcnVuSWQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZS5ldmVudFR5cGUgPT09ICdydW5fY29tcGxldGVkJyB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZS5ldmVudFR5cGUgPT09ICdydW5fZmFpbGVkJyB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZS5ldmVudFR5cGUgPT09ICdydW5fY2FuY2VsbGVkJylcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGVybWluYWxFdmVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGUgcHJlbG9hZCBzdGlsbCBpbml0aWFsaXplZCB0aGlzIGRlbGl2ZXJ5IChpdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpcyBob3cgdGhlIHRlcm1pbmFsIHN0YXRlIHdhcyBvYnNlcnZlZCksIHNvIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBzZXR1cC1zb3VyY2UgYW5kIHRoZSBydW4ncyBhY3R1YWwgdGVybWluYWxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gc3RhdHVzIGFyZSByZWNvcmRlZCBiZWZvcmUgY29uc3VtaW5nLlxuICAgICAgICAgICAgICAgICAgICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dSdW5TdGF0dXMoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXJtaW5hbEV2ZW50LmV2ZW50VHlwZSA9PT0gJ3J1bl9jb21wbGV0ZWQnXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gJ2NvbXBsZXRlZCdcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiB0ZXJtaW5hbEV2ZW50LmV2ZW50VHlwZSA9PT0gJ3J1bl9mYWlsZWQnXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPyAnZmFpbGVkJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogJ2NhbmNlbGxlZCdcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Ib29rUmVzdW1lU2V0dXBTb3VyY2UoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnaG9va19yZWNlaXZlZF9zdHJlYW0nXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbyhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnUnVuIGFscmVhZHkgZmluaXNoZWQgZHVyaW5nIGxhenkgaG9vayBzZXR1cCwgc2tpcHBpbmcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRUeXBlOiB0ZXJtaW5hbEV2ZW50LmV2ZW50VHlwZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuID0gcmVzdWx0LnJ1bjtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1heEV2ZW50c0xpbWl0ID0gY2xhbXBNYXhFdmVudHMocmVzdWx0Lm1heEV2ZW50cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBBbmNob3JzIFJTRlMg4oCUIHNlZSB0aGUgZGVjbGFyYXRpb24gYWJvdmUuIFRoaXNcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHJlc3BvbnNlIHBsYXlzIHJ1bl9zdGFydGVkJ3Mgcm9sZSBvbiB0aGlzIHBhdGguXG4gICAgICAgICAgICAgICAgICAgICAgICBydW5TdGFydGVkUmVjZWl2ZWRBdE1zID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50TG9nID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAncmVhZHknLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHM6IHJlc3VsdC5ldmVudHMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnNvcjogcmVzdWx0LmN1cnNvcixcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1N0YXJ0ZWRBdCA9ICtyZXN1bHQucnVuLnN0YXJ0ZWRBdDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dSdW5TdGF0dXMocmVzdWx0LnJ1bi5zdGF0dXMpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dTdGFydGVkQXQod29ya2Zsb3dTdGFydGVkQXQpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuSG9va1Jlc3VtZVNldHVwU291cmNlKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdob29rX3JlY2VpdmVkX3N0cmVhbSdcbiAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBTdWNjZXNzZnVsIHdyaXRlLCBubyB1c2FibGUgcHJlbG9hZCAoQ0JPUiByZXNwb25zZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZnJvbSBhbiBvbGRlciBzZXJ2ZXIsIGEgV29ybGQgdGhhdCBpZ25vcmVkIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gb3B0LWluLCBhIGJvdW5kZWQgaGFzTW9yZSBwYWdlLCBvciBhIHByZWxvYWQgdGhhdFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZmFpbGVkIHZhbGlkYXRpb24pOiB0YWtlIHRoZSBnZW5lcmljIHJ1bl9zdGFydGVkXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBzZXR1cCBiZWxvdy4gSXRzIHByZWxvYWQgaXMgbG9hZGVkIGFmdGVyIHRoaXMgd3JpdGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNvbW1pdHRlZCwgc28gdGhlIGNhbm9uaWNhbCBob29rX3JlY2VpdmVkIGlzIHBhcnRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG9mIHdoYXRldmVyIGxvZyB0aGF0IHNldHVwIHJlYWRzIOKAlCBubyBzcGxpY2VcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG5lZWRlZC5cbiAgICAgICAgICAgICAgICAgICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoXG4gICAgICAgICAgICAgICAgICAgICAgICAgIEF0dHJpYnV0ZS5Ib29rUmVzdW1lU2V0dXBTb3VyY2UoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2hvb2tfcmVjZWl2ZWRfZmFsbGJhY2snXG4gICAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAvLyBTYW1lIGNsYXNzaWZpY2F0aW9uIGFzIHRoZSByZS1lbnN1cmUgYmVsb3c6XG4gICAgICAgICAgICAgICAgICAgICAgLy8gLSBIb29rTm90Rm91bmQgLyBSdW5FeHBpcmVkOiB0aGUgcnVuIHdlbnQgdGVybWluYWw7XG4gICAgICAgICAgICAgICAgICAgICAgLy8gICBub3RoaW5nIGxlZnQgdG8gcmVzdW1lLCBjb25zdW1lIHRoZSBtZXNzYWdlLlxuICAgICAgICAgICAgICAgICAgICAgIC8vIC0gYW55dGhpbmcgZWxzZSAoRW50aXR5Q29uZmxpY3QsIGEgdHJ1bmNhdGVkIHByZWxvYWRcbiAgICAgICAgICAgICAgICAgICAgICAvLyAgIHN0cmVhbSwgdHJhbnNwb3J0IGZhaWx1cmVzKTogdHJhbnNpZW50IOKAlCByZXRocm93IHNvXG4gICAgICAgICAgICAgICAgICAgICAgLy8gICB0aGUgcXVldWUgcmVkZWxpdmVycyBhbmQgdGhlIGlkZW1wb3RlbnRcbiAgICAgICAgICAgICAgICAgICAgICAvLyAgIChydW5JZCwgcmVzdW1lSWQpIGNsYWltIGNvbnZlcmdlcyBvbiByZXRyeS5cbiAgICAgICAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgICAgICBIb29rTm90Rm91bmRFcnJvci5pcyhlcnIpIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICBSdW5FeHBpcmVkRXJyb3IuaXMoZXJyKVxuICAgICAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAnUnVuIGFscmVhZHkgZmluaXNoZWQgZHVyaW5nIGxhenkgaG9vayBzZXR1cCwgc2tpcHBpbmcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICB7IHdvcmtmbG93UnVuSWQ6IHJ1bklkLCBtZXNzYWdlOiBlcnIubWVzc2FnZSB9XG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgLy8gLS0tIEluZnJhc3RydWN0dXJlOiBwcmVwYXJlIHRoZSBydW4gc3RhdGUgLS0tXG4gICAgICAgICAgICAgICAgICAvLyBTa2lwIGlmIHdvcmtmbG93UnVuIHdhcyBhbHJlYWR5IHNldCBieSB0aGUgYmFja2dyb3VuZFxuICAgICAgICAgICAgICAgICAgLy8gc3RlcCBwYXRoIChpbmxpbmUgcmVwbGF5IGFmdGVyIGFsbCBwYXJhbGxlbCBzdGVwcyBkb25lKVxuICAgICAgICAgICAgICAgICAgLy8gb3IgYnkgdGhlIGxhenkgaG9vayBmYXN0IHBhdGggYWJvdmUuXG4gICAgICAgICAgICAgICAgICBpZiAoIXdvcmtmbG93UnVuKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEFsd2F5cyBjYWxsIHJ1bl9zdGFydGVkIGRpcmVjdGx5IOKAlCB0aGlzIGJvdGggdHJhbnNpdGlvbnNcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhlIHJ1biB0byAncnVubmluZycgQU5EIHJldHVybnMgdGhlIHJ1biBlbnRpdHksIHNhdmluZ1xuICAgICAgICAgICAgICAgICAgICAvLyBhIHNlcGFyYXRlIHJ1bnMuZ2V0IHJvdW5kLXRyaXAuXG4gICAgICAgICAgICAgICAgICAgIC8vIENvbnRyYWN0OiBldmVudHMuY3JlYXRlKCdydW5fc3RhcnRlZCcpIG11c3QgYmUgaWRlbXBvdGVudFxuICAgICAgICAgICAgICAgICAgICAvLyBmb3IgcnVucyBhbHJlYWR5IGluICdydW5uaW5nJyBzdGF0dXMgKHJldHVybiB0aGUgcnVuXG4gICAgICAgICAgICAgICAgICAgIC8vIHdpdGhvdXQgZXJyb3IpLCBub3QganVzdCBmb3IgcGVuZGluZyDihpIgcnVubmluZyB0cmFuc2l0aW9ucy5cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcnVuU3RhcnRlZEV2ZW50ID0ge1xuICAgICAgICAgICAgICAgICAgICAgIGV2ZW50VHlwZTogJ3J1bl9zdGFydGVkJyBhcyBjb25zdCxcbiAgICAgICAgICAgICAgICAgICAgICAvLyBVc2UgdGhlIHNwZWMgdmVyc2lvbiBmcm9tIHRoZSBvcmlnaW5hbCBzdGFydCgpIGNhbGxcbiAgICAgICAgICAgICAgICAgICAgICAvLyB3aGVuIGF2YWlsYWJsZSwgc28gdGhlIHJlc2lsaWVudCBzdGFydCBwYXRoIGNyZWF0ZXNcbiAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgcnVuIHdpdGggdGhlIGNvcnJlY3QgdmVyc2lvbiAobm90IGFsd2F5cyBjdXJyZW50KS5cbiAgICAgICAgICAgICAgICAgICAgICBzcGVjVmVyc2lvbjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJ1bklucHV0Py5zcGVjVmVyc2lvbiA/PyBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgICAgICAgICAgICAvLyBQYXNzIHJ1biBpbnB1dCBmcm9tIHF1ZXVlIHNvIHRoZSBzZXJ2ZXIgY2FuXG4gICAgICAgICAgICAgICAgICAgICAgLy8gY3JlYXRlIHRoZSBydW4gaWYgcnVuX2NyZWF0ZWQgd2FzIG1pc3NlZC5cbiAgICAgICAgICAgICAgICAgICAgICAvLyBVaW50OEFycmF5IHZhbHVlcyBzdXJ2aXZlIHRoZSBxdWV1ZSBuYXRpdmVseVxuICAgICAgICAgICAgICAgICAgICAgIC8vIChDQk9SIG9uIHdvcmxkLXZlcmNlbCwgSlNPTiByZXZpdmVyIG9uIHdvcmxkLWxvY2FsKS5cbiAgICAgICAgICAgICAgICAgICAgICAuLi4ocnVuSW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICAgID8ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXQ6IHJ1bklucHV0LmlucHV0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVwbG95bWVudElkOiBydW5JbnB1dC5kZXBsb3ltZW50SWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd05hbWU6IHJ1bklucHV0LndvcmtmbG93TmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4ZWN1dGlvbkNvbnRleHQ6IHJ1bklucHV0LmV4ZWN1dGlvbkNvbnRleHQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdHRyaWJ1dGVzOiBydW5JbnB1dC5hdHRyaWJ1dGVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxsb3dSZXNlcnZlZEF0dHJpYnV0ZXM6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJ1bklucHV0LmFsbG93UmVzZXJ2ZWRBdHRyaWJ1dGVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIDoge30pLFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICBpZiAodHVyYm8gJiYgcnVuSW5wdXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAvLyBUdXJibzogYmFja2dyb3VuZCBgcnVuX3N0YXJ0ZWRgIGFuZCBzeW50aGVzaXplIHRoZSBydW5cbiAgICAgICAgICAgICAgICAgICAgICAvLyBlbnRpdHkgbG9jYWxseSBzbyByZXBsYXkgY2FuIGJlZ2luIHdpdGhvdXQgd2FpdGluZyBmb3JcbiAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgcm91bmQtdHJpcC4gU2FmZSBoZXJlIGJlY2F1c2UgdGhpcyBpcyB0aGUgZmlyc3RcbiAgICAgICAgICAgICAgICAgICAgICAvLyBkZWxpdmVyeSBvZiB0aGUgZmlyc3QgaW52b2NhdGlvbiDigJQgc3RhcnQoKSBjcmVhdGVkIHRoZVxuICAgICAgICAgICAgICAgICAgICAgIC8vIHJ1biBtb21lbnRzIGFnbyBhbmQgbm8gZXZlbnRzIGhhdmUgYmVlbiB3cml0dGVuIHlldC4gVGhlXG4gICAgICAgICAgICAgICAgICAgICAgLy8gYmFycmllciBpcyBjb25zdW1lZCBieSBldmVyeSBkb3duc3RyZWFtIHdyaXRlIChzdXNwZW5zaW9uXG4gICAgICAgICAgICAgICAgICAgICAgLy8gaGFuZGxlciwgb3B0aW1pc3RpYyBzdGVwX3N0YXJ0ZWQsIHRlcm1pbmFsIHJ1biB3cml0ZXMpIHNvXG4gICAgICAgICAgICAgICAgICAgICAgLy8gbm90aGluZyBpcyB3cml0dGVuIGJlZm9yZSB0aGUgcnVuIGV4aXN0cy5cbiAgICAgICAgICAgICAgICAgICAgICBzcGFuPy5hZGRFdmVudCgnd29ya2Zsb3cucnVuX3N0YXJ0ZWQuY3JlYXRlLnN0YXJ0Jywge1xuICAgICAgICAgICAgICAgICAgICAgICAgJ3dvcmtmbG93LnJ1bl9zdGFydGVkLnNraXBfcHJlbG9hZCc6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RhcnRlZFByb21pc2UgPSBjcmVhdGVFdmVudChcbiAgICAgICAgICAgICAgICAgICAgICAgIHJ1blN0YXJ0ZWRFdmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdlIGJhY2tncm91bmQgdGhpcyBwdXJlbHkgYXMgYSB3cml0ZSBiYXJyaWVyIGFuZFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbmV2ZXIgcmVhZCBpdHMgcHJlbG9hZGVkIGV2ZW50cywgc28gc2tpcCB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHJ1bl9zdGFydGVkIGV2ZW50LWxvZyBwcmVsb2FkLiBUaGF0IHRyaW1zIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gcnVuX3N0YXJ0ZWQgcmVxdWVzdCB0aGUgY2hhaW5lZCBmaXJzdCBzdGVwX3N0YXJ0ZWRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHdhaXRzIG9uIOKAlCBzaG9ydGVuaW5nIHRpbWUtdG8tc2Vjb25kLXN0ZXAg4oCUIGFuZCB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHdhc3RlZCBsaXN0K3Jlc29sdmUgaXQgd291bGQgb3RoZXJ3aXNlIGNvbXB1dGUuXG4gICAgICAgICAgICAgICAgICAgICAgICB7IHJlcXVlc3RJZCwgc2tpcFByZWxvYWQ6IHRydWUgfVxuICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgcnVuUmVhZHlCYXJyaWVyID0gc3RhcnRlZFByb21pc2U7XG4gICAgICAgICAgICAgICAgICAgICAgLy8gVHVyYm8gYmFja2dyb3VuZHMgcnVuX3N0YXJ0ZWQsIHNvIHRoZSBub24tdHVyYm8gYXNzaWdubWVudFxuICAgICAgICAgICAgICAgICAgICAgIC8vIGJlbG93IG5ldmVyIHJ1bnMg4oCUIHRocmVhZCB0aGUgcGVyLXJ1biBldmVudCBjZWlsaW5nIG9mZiB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAvLyBiYWNrZ3JvdW5kZWQgcmVzcG9uc2UgaGVyZSBpbnN0ZWFkLiBUaGUgZ3VhcmQgcmUtY2hlY2tzXG4gICAgICAgICAgICAgICAgICAgICAgLy8gbWF4RXZlbnRzTGltaXQgZXZlcnkgbG9vcCBpdGVyYXRpb24sIHNvIGEgdmFsdWUgdGhhdCBsYW5kc1xuICAgICAgICAgICAgICAgICAgICAgIC8vIHNob3J0bHkgYWZ0ZXIgc3RhcnQgc3RpbGwgZW5mb3JjZXMgd2VsbCBiZWZvcmUgYSBydW5hd2F5XG4gICAgICAgICAgICAgICAgICAgICAgLy8gbG9nIGFwcHJvYWNoZXMgdGhlIGNlaWxpbmcuXG4gICAgICAgICAgICAgICAgICAgICAgdm9pZCBzdGFydGVkUHJvbWlzZVxuICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKHIpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbGltaXQgPSBjbGFtcE1heEV2ZW50cyhyLm1heEV2ZW50cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsaW1pdCAhPT0gdW5kZWZpbmVkKSBtYXhFdmVudHNMaW1pdCA9IGxpbWl0O1xuICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFByZXZlbnQgYW4gZWFybHkgZmFpbHVyZSBmcm9tIHN1cmZhY2luZyBhcyBhblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdW5oYW5kbGVkUmVqZWN0aW9uOyBydW5SZWFkeUJhcnJpZXIgc3RpbGwgb2JzZXJ2ZXMgaXQuXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goKCkgPT4ge30pO1xuICAgICAgICAgICAgICAgICAgICAgIC8vIFNraXAgdGhlIGluaXRpYWwgZXZlbnRzLmxpc3Q6IG5vdGhpbmcgaGFzIGJlZW4gd3JpdHRlbiB0b1xuICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBsb2cgeWV0IG9uIGEgZmlyc3QgZGVsaXZlcnkgKHJ1bl9zdGFydGVkIGlzIHN0aWxsIGluXG4gICAgICAgICAgICAgICAgICAgICAgLy8gZmxpZ2h0KS4gQW4gZW1wdHkgcHJlbG9hZCByb3V0ZXMgaXRlcmF0aW9uIDEgdGhyb3VnaFxuICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBuby1sb2FkIHByZWxvYWRlZCBicmFuY2g7IGl0ZXJhdGlvbiAyIHRoZW4gdGFrZXMgdGhlXG4gICAgICAgICAgICAgICAgICAgICAgLy8gZXhpc3RpbmcgcG9zdC1wcmVsb2FkZWQgZnVsbCByZWxvYWQgdG8gcGljayB1cCBhIGN1cnNvclxuICAgICAgICAgICAgICAgICAgICAgIC8vIHdpdGhvdXQgYSBzcHVyaW91cyBcImN1cnNvciBtaXNzaW5nXCIgd2FybmluZy5cbiAgICAgICAgICAgICAgICAgICAgICBldmVudExvZyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdyZWFkeScsXG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudHM6IFtdLFxuICAgICAgICAgICAgICAgICAgICAgICAgY3Vyc29yOiBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3Qgbm93ID0gbmV3IERhdGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1biA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgc3RhdHVzOiAncnVubmluZycsXG4gICAgICAgICAgICAgICAgICAgICAgICBkZXBsb3ltZW50SWQ6IHJ1bklucHV0LmRlcGxveW1lbnRJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93TmFtZTogcnVuSW5wdXQud29ya2Zsb3dOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IHJ1bklucHV0LnNwZWNWZXJzaW9uLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXhlY3V0aW9uQ29udGV4dDogcnVuSW5wdXQuZXhlY3V0aW9uQ29udGV4dCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0OiBydW5JbnB1dC5pbnB1dCxcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNlZWQgYXR0cmlidXRlcyBmcm9tIHN0YXJ0KCkgcmlkZSBhbG9uZyBpbiBgcnVuSW5wdXRgXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAodGhleSBsaXZlIGluIGBydW5fY3JlYXRlZGAncyBldmVudERhdGEsIG5vdCBzZXBhcmF0ZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYGF0dHJfc2V0YCBldmVudHMpLCBzbyB0aGUgc3ludGhlc2l6ZWQgc25hcHNob3QgY2Fycmllc1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlbSBldmVuIHRob3VnaCB3ZSBza2lwIHRoZSBpbml0aWFsIGV2ZW50cy5saXN0LiBUaGlzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpcyBjb3JyZWN0IE9OTFkgd2hpbGUgYXR0cmlidXRlcyBhcmUgd3JpdGUtb25seTpcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZXJlIGlzIG5vIGluLXdvcmtmbG93IHJlYWQgQVBJIHRvZGF5IChzZWUgd29ya2Zsb3cudHNcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFwic3RydWN0dXJhbCB1bnRpbCBhIHJlYWQgQVBJIGlzIGludHJvZHVjZWRcIiksIHNvIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZW1wdHkgcHJlbG9hZGVkIGxvZyBjYW4ndCBkaXZlcmdlIG9uIGEgcmVhZC4gSWYgYSByZWFkXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBBUEkgaXMgZXZlciBhZGRlZCBpdCBNVVNUIHJlYWQgZnJvbSB0aGlzIHNuYXBzaG90LCBub3RcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGJ5IHJlcGxheWluZyBydW5fY3JlYXRlZC9hdHRyX3NldCBldmVudHMg4oCUIG90aGVyd2lzZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdHVyYm8ncyBlbXB0eSBpbml0aWFsIGxvZyB3b3VsZCBzdXJmYWNlIHNlZWQgYXR0cmlidXRlc1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXMgYHt9YCBvbiB0aGUgZmlyc3QgZGVsaXZlcnkgb25seS5cbiAgICAgICAgICAgICAgICAgICAgICAgIGF0dHJpYnV0ZXM6IHJ1bklucHV0LmF0dHJpYnV0ZXMgPz8ge30sXG4gICAgICAgICAgICAgICAgICAgICAgICBzdGFydGVkQXQ6IG5vdyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNyZWF0ZWRBdDogbm93LFxuICAgICAgICAgICAgICAgICAgICAgICAgdXBkYXRlZEF0OiBub3csXG4gICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1N0YXJ0ZWRBdCA9ICtub3c7XG4gICAgICAgICAgICAgICAgICAgICAgLy8gU2VlIHRoZSBgcnVuU3RhcnRlZFJlY2VpdmVkQXRNc2AgZGVjbGFyYXRpb24gYWJvdmU6XG4gICAgICAgICAgICAgICAgICAgICAgLy8gdHVyYm8gc3ludGhlc2l6ZXMgdGhlIHJ1biBiZWZvcmUgdGhlIHJlYWxcbiAgICAgICAgICAgICAgICAgICAgICAvLyBgcnVuX3N0YXJ0ZWRgIHJlc3BvbnNlIGxhbmRzLCBzbyBhbmNob3IgUlNGUyBoZXJlXG4gICAgICAgICAgICAgICAgICAgICAgLy8gcmF0aGVyIHRoYW4gYXQgYW4gYWN0dWFsIHJlc3BvbnNlIGluc3RhbnQuXG4gICAgICAgICAgICAgICAgICAgICAgcnVuU3RhcnRlZFJlY2VpdmVkQXRNcyA9ICtub3c7XG4gICAgICAgICAgICAgICAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dSdW5TdGF0dXMoJ3J1bm5pbmcnKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd1N0YXJ0ZWRBdCh3b3JrZmxvd1N0YXJ0ZWRBdCksXG4gICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNwYW4/LmFkZEV2ZW50KCd3b3JrZmxvdy5ydW5fc3RhcnRlZC5jcmVhdGUuc3RhcnQnLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICd3b3JrZmxvdy5ydW5fc3RhcnRlZC5za2lwX3ByZWxvYWQnOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY3JlYXRlRXZlbnQocnVuU3RhcnRlZEV2ZW50LCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJlcXVlc3RJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW4gPSByZXN1bHQucnVuO1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4RXZlbnRzTGltaXQgPSBjbGFtcE1heEV2ZW50cyhyZXN1bHQubWF4RXZlbnRzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFuY2hvcnMgUlNGUyDigJQgc2VlIHRoZSBkZWNsYXJhdGlvbiBhYm92ZS5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJ1blN0YXJ0ZWRSZWNlaXZlZEF0TXMgPSBEYXRlLm5vdygpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0LmV2ZW50cz8ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGxvYWRlZCA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHM6IFsuLi5yZXN1bHQuZXZlbnRzXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJzb3I6IHJlc3VsdC5jdXJzb3IgPz8gbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRMb2cgPSByZXN1bHQuaGFzTW9yZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gbmV4dEV2ZW50TG9nTG9hZChsb2FkZWQpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgOiB7IC4uLmxvYWRlZCwgdHlwZTogJ3JlYWR5JyB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dTdGFydGVkQXQgPSArcmVzdWx0LnJ1bi5zdGFydGVkQXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLldvcmtmbG93UnVuU3RhdHVzKHJlc3VsdC5ydW4uc3RhdHVzKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLldvcmtmbG93U3RhcnRlZEF0KHdvcmtmbG93U3RhcnRlZEF0KSxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0LnJ1bi5zdGF0dXMgIT09ICdydW5uaW5nJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ1dvcmtmbG93IGFscmVhZHkgY29tcGxldGVkIG9yIGZhaWxlZCwgc2tpcHBpbmcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdHVzOiByZXN1bHQucnVuLnN0YXR1cyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVE9ETzogZm9yIGBjYW5jZWxgLCB3ZSBhY3R1YWxseSB3YW50IHRvIHByb3BhZ2F0ZSBhIFdvcmtmbG93Q2FuY2VsbGVkIGV2ZW50XG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluc2lkZSB0aGUgd29ya2Zsb3cgY29udGV4dCBzbyB0aGUgdXNlciBjYW4gZ3JhY2VmdWxseSBleGl0LiB0aGlzIGlzIFNJR1RFUk1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVE9ETzogZnVydGhlcm1vcmUsIHRoZXJlIHNob3VsZCBiZSBhIHRpbWVvdXQgb3IgYSB3YXkgdG8gZm9yY2UgY2FuY2VsIFNJR0tJTExcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gc28gdGhhdCB3ZSBhY3R1YWxseSBleGl0IGhlcmUgd2l0aG91dCByZXBsYXlpbmcgdGhlIHdvcmtmbG93IGF0IGFsbCwgaW4gdGhlIGNhc2VcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIHJlcGxheWluZyB0aGUgd29ya2Zsb3cgaXMgaXRzZWxmIGZhaWxpbmcuXG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gUnVuIHdhcyBjb25jdXJyZW50bHkgY29tcGxldGVkL2ZhaWxlZC9jYW5jZWxsZWRcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgIFJ1bkV4cGlyZWRFcnJvci5pcyhlcnIpXG4gICAgICAgICAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRW50aXR5Q29uZmxpY3RFcnJvcjogcnVuIHdhcyBjb25jdXJyZW50bHlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gY29tcGxldGVkL2ZhaWxlZC9jYW5jZWxsZWQgZHVyaW5nIHNldHVwLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSdW5FeHBpcmVkRXJyb3I6IHJ1biBhbHJlYWR5IGluIHRlcm1pbmFsIHN0YXRlLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJbiBib3RoIGNhc2VzLCBza2lwIHByb2Nlc3NpbmcgdGhpcyBtZXNzYWdlLlxuICAgICAgICAgICAgICAgICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ1J1biBhbHJlYWR5IGZpbmlzaGVkIGR1cmluZyBzZXR1cCwgc2tpcHBpbmcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsgd29ya2Zsb3dSdW5JZDogcnVuSWQsIG1lc3NhZ2U6IGVyci5tZXNzYWdlIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3JDb2RlID0gZ2V0V29ya2Zsb3dTZXR1cEVycm9yQ29kZShlcnIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWVycm9yQ29kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCByZWNvcmRGYXRhbFJ1bkVycm9yKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JsZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXF1ZXN0SWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ29kZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2dNZXNzYWdlOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0ZhdGFsIHJ1bnRpbWUgZXJyb3IgZHVyaW5nIHdvcmtmbG93IHNldHVwJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gLy8gZW5kIGVsc2UgKG5vbi10dXJibyBydW5fc3RhcnRlZClcbiAgICAgICAgICAgICAgICAgIH0gLy8gZW5kIGlmICghd29ya2Zsb3dSdW4pXG4gICAgICAgICAgICAgICAgICBhc3NlcnQoXG4gICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuLFxuICAgICAgICAgICAgICAgICAgICAnV29ya2Zsb3cgcnVuIG11c3QgYmUgbG9hZGVkIGJlZm9yZSByZXBsYXknXG4gICAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgICAvLyBDb3ZlcnMgZXZlcnkgZmxvdyByZXBsYXkg4oCUIGluaXRpYWwgc3RhcnQsIHN0ZXAgY29tcGxldGlvbnMsXG4gICAgICAgICAgICAgICAgICAvLyBob29rIHJlc3VtcHRpb25zLCB3YWl0IGNvbXBsZXRpb25zIOKAlCBhbmQgc3RvcHMgYmVmb3JlIGFueVxuICAgICAgICAgICAgICAgICAgLy8gd29ya2Zsb3cgY29kZSBvciBpbmxpbmUgc3RlcCBleGVjdXRlcyB3aGVuIHRoZSBydW4gaXMgbm90XG4gICAgICAgICAgICAgICAgICAvLyBwaW5uZWQgaGVyZSAoc2VlIGBndWFyZERlcGxveW1lbnRBZmZpbml0eWApLiBUaGlzIHJlbWFpbnNcbiAgICAgICAgICAgICAgICAgIC8vIHRoZSBBVVRIT1JJVEFUSVZFIHByb3RlY3Rpb24gYmVmb3JlIHJlcGxheSBhbmQgc3RlcFxuICAgICAgICAgICAgICAgICAgLy8gZXhlY3V0aW9uLiBgYXdhaXRSdW5SZWFkeWAgb3JkZXJzIHR1cmJvJ3MgYHJ1bl9zdGFydGVkYFxuICAgICAgICAgICAgICAgICAgLy8gYmVmb3JlIGVpdGhlciBzdG9wcGluZyBhY3Rpb24uXG4gICAgICAgICAgICAgICAgICAvL1xuICAgICAgICAgICAgICAgICAgLy8gTGF6eSBob29rIHJlc3VtZXMgYXJlIGFkZGl0aW9uYWxseSBwcmUtY2hlY2tlZCBhYm92ZSB0aGVcbiAgICAgICAgICAgICAgICAgIC8vIGZhc3QgcGF0aDogYSBuZXcgbWVzc2FnZSdzIGBob29rSW5wdXQuZGVwbG95bWVudElkYCBpc1xuICAgICAgICAgICAgICAgICAgLy8gY29tcGFyZWQgYWdhaW5zdCB0aGUgYW1iaWVudCBkZXBsb3ltZW50IGlkIGZvciBmcmVlLCBhbmRcbiAgICAgICAgICAgICAgICAgIC8vIG9ubHkgYSBkZXRlY3RlZCBtaXNtYXRjaCBmZXRjaGVzIHRoZSBhdXRob3JpdGF0aXZlIHJ1biDigJRcbiAgICAgICAgICAgICAgICAgIC8vIHNvIGEgbWlzcm91dGVkIG1vZGVybiByZXN1bWUgcmUtcm91dGVzIHdpdGggemVybyBldmVudFxuICAgICAgICAgICAgICAgICAgLy8gd3JpdGVzLiBPbGRlciBtZXNzYWdlcyAobm8gYGhvb2tJbnB1dC5kZXBsb3ltZW50SWRgKSByZWFjaFxuICAgICAgICAgICAgICAgICAgLy8gdGhlIGZhc3QgcGF0aCdzIGlkZW1wb3RlbnQgaG9va19yZWNlaXZlZCB3cml0ZSBiZWZvcmUgdGhpc1xuICAgICAgICAgICAgICAgICAgLy8gZ3VhcmQ7IHRoYXQgd3JpdGUgY29udmVyZ2VzIHBlciAocnVuSWQsIHJlc3VtZUlkKSBvbiB0aGVcbiAgICAgICAgICAgICAgICAgIC8vIHBpbm5lZCBkZXBsb3ltZW50LCBzbyBpdCBpcyBzYWZlLCBqdXN0IG5vdCBmcmVlLiBFaXRoZXJcbiAgICAgICAgICAgICAgICAgIC8vIHdheSB0aGUgcmUtcm91dGVkIG1lc3NhZ2UgbXVzdCBjYXJyeSBgaG9va0lucHV0YCwgb3IgYVxuICAgICAgICAgICAgICAgICAgLy8gcmVzdW1lIHdob3NlIHByb2R1Y2VyIHdyaXRlIGhhZCBub3QgeWV0IGxhbmRlZCB3b3VsZCBiZVxuICAgICAgICAgICAgICAgICAgLy8gbG9zdC5cbiAgICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgKGF3YWl0IGd1YXJkRGVwbG95bWVudChcbiAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bixcbiAgICAgICAgICAgICAgICAgICAgICBhc3luYyAoKSA9PiAoe1xuICAgICAgICAgICAgICAgICAgICAgICAgLi4uKGF3YWl0IHJlcGxheU1lc3NhZ2UoKSksXG4gICAgICAgICAgICAgICAgICAgICAgICAuLi4oaG9va0lucHV0ID8geyBob29rSW5wdXQgfSA6IHt9KSxcbiAgICAgICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICAgICAgICBhd2FpdFJ1blJlYWR5XG4gICAgICAgICAgICAgICAgICAgICkpICE9PSAnY29udGludWUnXG4gICAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAvLyBMYXp5IGhvb2sgcmVzdW1lOiB0aGUgcHJvZHVjZXIgKHJlc3VtZUhvb2sgZmFzdCBwYXRoKVxuICAgICAgICAgICAgICAgICAgLy8gcGFyYWxsZWxpemVkIHRoZSBgaG9va19yZWNlaXZlZGAgd3JpdGUgd2l0aCB0aGlzIHF1ZXVlXG4gICAgICAgICAgICAgICAgICAvLyBwdWJsaXNoLCBzbyB0aGUgZXZlbnQgbWF5IG5vdCBiZSBwZXJzaXN0ZWQgeWV0LiBJZGVtcG90ZW50bHlcbiAgICAgICAgICAgICAgICAgIC8vIGVuc3VyZSBpdCBiZWZvcmUgcmVwbGF5IOKAlCBrZXllZCBieSBgcmVzdW1lSWRgIHNvIGFcbiAgICAgICAgICAgICAgICAgIC8vIGNvbmN1cnJlbnQgcHJvZHVjZXIgd3JpdGUgY29udmVyZ2VzIG9uIGV4YWN0bHkgb25lIGV2ZW50XG4gICAgICAgICAgICAgICAgICAvLyAodGhlIHNlcnZlciByZXNvbHZlcyBhIG1hdGNoaW5nIGNsYWltIGFzIHN1Y2Nlc3MsIG5vdCBhblxuICAgICAgICAgICAgICAgICAgLy8gZXJyb3IpLiBgaG9va0lucHV0YCBuZXZlciByaWRlcyBhIHR1cmJvIGZpcnN0LWRlbGl2ZXJ5XG4gICAgICAgICAgICAgICAgICAvLyAodGhhdCBwYXRoIGNhcnJpZXMgYHJ1bklucHV0YCwgbm90IGBob29rSW5wdXRgKSwgc28gdGhpc1xuICAgICAgICAgICAgICAgICAgLy8gb25seSBydW5zIG9uIHRoZSBub3JtYWwgbG9hZC1hbmQtcmVwbGF5IHBhdGguIFNraXBwZWRcbiAgICAgICAgICAgICAgICAgIC8vIGVudGlyZWx5IHdoZW4gdGhlIGZhc3QgcGF0aCBhYm92ZSBhbHJlYWR5IGVuc3VyZWQgdGhlXG4gICAgICAgICAgICAgICAgICAvLyBldmVudCAoYGhvb2tFbnN1cmVkYCkg4oCUIHN1Y2Nlc3NmdWxseSBvciB2aWEgaXRzIGZhbGxiYWNrLFxuICAgICAgICAgICAgICAgICAgLy8gd2hvc2UgcnVuX3N0YXJ0ZWQgcHJlbG9hZCB3YXMgbG9hZGVkIGFmdGVyIHRoZSB3cml0ZSBhbmRcbiAgICAgICAgICAgICAgICAgIC8vIHRoZXJlZm9yZSBhbHJlYWR5IGNvbnRhaW5zIHRoZSBjYW5vbmljYWwgZXZlbnQuXG4gICAgICAgICAgICAgICAgICBpZiAoaG9va0lucHV0ICYmICFob29rRW5zdXJlZCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBQZXJmIChPcHRpb24gQSk6IGlmIHRoZSBwcm9kdWNlcidzIGNvbmN1cnJlbnQgZGlyZWN0XG4gICAgICAgICAgICAgICAgICAgIC8vIHdyaXRlIGFscmVhZHkgbGFuZGVkIGluIHRoZSBydW5fc3RhcnRlZCBwcmVsb2FkLCB0aGVcbiAgICAgICAgICAgICAgICAgICAgLy8gY2Fub25pY2FsIGV2ZW50IGlzIGluIHRoZSBsb2cgYW5kIHRoZSByZS1lbnN1cmUgcm91bmQgdHJpcFxuICAgICAgICAgICAgICAgICAgICAvLyBpcyBwdXJlIG92ZXJoZWFkLiBTa2lwIGl0IHdoZW4gdGhlIHByZWxvYWQgYWxyZWFkeSBjYXJyaWVzXG4gICAgICAgICAgICAgICAgICAgIC8vIGEgYGhvb2tfcmVjZWl2ZWRgIHdpdGggdGhpcyByZXN1bWUncyBwZXJzaXN0ZWQgYHJlc3VtZUlkYFxuICAgICAgICAgICAgICAgICAgICAvLyAodW5pcXVlIHBlciByZXN1bWUsIHNvIHdlIG5ldmVyIHNraXAgb24gYW4gdW5yZWxhdGVkXG4gICAgICAgICAgICAgICAgICAgIC8vIGhvb2tfcmVjZWl2ZWQpLiBCZXN0LWVmZm9ydDogdGhlIHdpbiBsYW5kcyBvbmx5IHdoZW4gdGhlXG4gICAgICAgICAgICAgICAgICAgIC8vIHByb2R1Y2VyJ3Mgd3JpdGUgYmVhdCB0aGlzIGNvbnN1bWVyJ3MgbG9hZDsgb3RoZXJ3aXNlIHdlXG4gICAgICAgICAgICAgICAgICAgIC8vIGZhbGwgdGhyb3VnaCB0byB0aGUgaWRlbXBvdGVudCByZS1lbnN1cmUgYmVsb3cuXG4gICAgICAgICAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAgICAgICAgIC8vIEludGVudGlvbmFsbHkgdW5yZWFjaGFibGUgZm9yIGF0b21pYyBsYXp5IHJlc3VtZXNcbiAgICAgICAgICAgICAgICAgICAgLy8gKHJlc3VtZUlkICsgZGlnZXN0KTogdGhvc2Ugc2V0IGBob29rRW5zdXJlZGAgaW4gdGhlXG4gICAgICAgICAgICAgICAgICAgIC8vIGhvaXN0ZWQgZmFzdCBwYXRoIGFib3ZlIOKAlCBvbiBzdWNjZXNzIEFORCBvbiBpdHNcbiAgICAgICAgICAgICAgICAgICAgLy8gZmFsbGJhY2sg4oCUIHNvIHRoaXMgYmxvY2sgKGFuZCB0aGUgc2tpcCBjaGVjaykgbm93IG9ubHlcbiAgICAgICAgICAgICAgICAgICAgLy8gc2VydmVzIGhvb2tJbnB1dCBzaGFwZXMgd2l0aG91dCB0aGUgZnVsbCBpZGVtcG90ZW5jeVxuICAgICAgICAgICAgICAgICAgICAvLyBwYWlyLlxuICAgICAgICAgICAgICAgICAgICBjb25zdCBhbHJlYWR5UHJlbG9hZGVkID1cbiAgICAgICAgICAgICAgICAgICAgICBob29rSW5wdXQucmVzdW1lSWQgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICAgICAgICAgICAgICAgIGV2ZW50TG9nLnR5cGUgIT09ICdsb2FkQWxsJyAmJlxuICAgICAgICAgICAgICAgICAgICAgIGV2ZW50TG9nLmV2ZW50cy5zb21lKFxuICAgICAgICAgICAgICAgICAgICAgICAgKGUpID0+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGUuZXZlbnRUeXBlID09PSAnaG9va19yZWNlaXZlZCcgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZS5yZXN1bWVJZCA9PT0gaG9va0lucHV0LnJlc3VtZUlkXG4gICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGFscmVhZHlQcmVsb2FkZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAvLyBFdmVudCBhbHJlYWR5IHZpc2libGUgaW4gdGhlIHByZWxvYWRlZCBsb2cg4oCUIG5vdGhpbmcgdG9cbiAgICAgICAgICAgICAgICAgICAgICAvLyBlbnN1cmUgb3Igc3BsaWNlLlxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgIC8vIERhdGUgdGhlIG1hdGVyaWFsaXplZCBldmVudCB0byB3aGVuIHRoZSByZXN1bWUgYWN0dWFsbHlcbiAgICAgICAgICAgICAgICAgICAgICAvLyBvY2N1cnJlZCwgbm90IHdoZW4gdGhpcyBxdWV1ZSBkZWxpdmVyeSByYW4uIGByZXN1bWVJZGBcbiAgICAgICAgICAgICAgICAgICAgICAvLyBpcyB0aGUgVUxJRCBtaW50ZWQgYnkgYHJlc3VtZUhvb2soKWAgYXQgcmVzdW1lIHRpbWUsIHNvXG4gICAgICAgICAgICAgICAgICAgICAgLy8gaXRzIGVtYmVkZGVkIHRpbWVzdGFtcCBpcyB0aGUgaG9uZXN0IGBvY2N1cnJlZEF0YCBhbmRcbiAgICAgICAgICAgICAgICAgICAgICAvLyBrZWVwcyBsYXRlbmN5IGF0dHJpYnV0aW9uIG9mZiB0aGUgcXVldWUgcm91bmQgdHJpcC4gQVxuICAgICAgICAgICAgICAgICAgICAgIC8vIG5vbi1VTElEIHJlc3VtZUlkIChsZWdhY3kgLyB0ZXN0KSBzaW1wbHkgbGVhdmVzIGl0XG4gICAgICAgICAgICAgICAgICAgICAgLy8gdW5kZWZpbmVkLCBzbyB0aGUgV29ybGQgZmFsbHMgYmFjayB0byBgY3JlYXRlZEF0YC5cbiAgICAgICAgICAgICAgICAgICAgICBsZXQgb2NjdXJyZWRBdDogRGF0ZSB8IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb2NjdXJyZWRBdCA9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tJbnB1dC5yZXN1bWVJZCAhPT0gdW5kZWZpbmVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPyBuZXcgRGF0ZShkZWNvZGVUaW1lKGhvb2tJbnB1dC5yZXN1bWVJZCkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvY2N1cnJlZEF0ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICBsZXQgZW5zdXJlZEV2ZW50OiBFdmVudCB8IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZW5zdXJlZCA9IGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGUoXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRUeXBlOiAnaG9va19yZWNlaXZlZCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IGhvb2tJbnB1dC5ob29rSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b2tlbjogaG9va0lucHV0LnRva2VuLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF5bG9hZDogaG9va0lucHV0LnBheWxvYWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcXVlc3RJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvY2N1cnJlZEF0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VtZUlkOiBob29rSW5wdXQucmVzdW1lSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdW1lUGF5bG9hZERpZ2VzdDogaG9va0lucHV0LnBheWxvYWREaWdlc3QsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBDb25zdW1lci1zaWRlIGNvbXBsZXRpb24gb2YgdGhlIHJlY292ZXJ5IHBhdGg6IHRoaXNcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHJlcGxheSBtYXRlcmlhbGl6ZWQgdGhlIGV2ZW50IGJlY2F1c2UgdGhlIHByb2R1Y2VyJ3NcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGRpcmVjdCB3cml0ZSBoYWQgbm90IGxhbmRlZCBpbiB0aGUgcHJlbG9hZC5cbiAgICAgICAgICAgICAgICAgICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoXG4gICAgICAgICAgICAgICAgICAgICAgICAgIEF0dHJpYnV0ZS5Ib29rUmVzaWxpZW50UmVzdW1lTWF0ZXJpYWxpemVkKHRydWUpXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhlIGNhbm9uaWNhbCBldmVudCDigJQgd2hldGhlciB0aGlzIGNhbGwgY29tbWl0dGVkIGl0IG9yXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBjb252ZXJnZWQgb24gdGhlIHByb2R1Y2VyJ3MgY29uY3VycmVudCB3cml0ZSDigJQgc28gd2UgY2FuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBzcGxpY2UgaXQgaW50byB0aGUgcHJlbG9hZGVkIGxvZyBpbnN0ZWFkIG9mIGRpc2NhcmRpbmdcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBwcmVsb2FkIChzZWUgYmVsb3cpLlxuICAgICAgICAgICAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJlY29uc3RydWN0IGBldmVudERhdGFgIGZyb20gYGhvb2tJbnB1dGAgcmF0aGVyIHRoYW5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRydXN0aW5nIHRoZSBQT1NUIHJlc3BvbnNlJ3MgcGF5bG9hZDogd29ybGQtdmVyY2VsIHBvc3RzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBob29rX3JlY2VpdmVkIHdpdGggYHJlbW90ZVJlZkJlaGF2aW9yOiAnbGF6eSdgLCBzbyB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHJldHVybmVkIGV2ZW50J3MgcGF5bG9hZCBpcyBhIFJlbW90ZVJlZiAqZGVzY3JpcHRvciosIG5vdFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIHNlcmlhbGl6ZWQgYnl0ZXMgcmVwbGF5IG5lZWRzLiBgaG9va0lucHV0YCBjYXJyaWVzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgcmVhbCB0b2tlbiArIHBheWxvYWQgYnl0ZXMgKHRoZXkgcm9kZSB0aGUgcXVldWVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG1lc3NhZ2UpLCBzbyBzcGxpY2UgdGhvc2Ugb250byB0aGUgcmV0dXJuZWQgZXZlbnQnc1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gc3RhYmxlIGV2ZW50SWQvbWV0YWRhdGEuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGUgcmUtZW5zdXJlIGFsd2F5cyByZXR1cm5zIGEgYGhvb2tfcmVjZWl2ZWRgIGV2ZW50LCBzb1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIHNwbGljZSBpcyBzYWZlLiBUaGUgY2FzdCBpcyBuZWVkZWQgYmVjYXVzZSBzcHJlYWRpbmdcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSByYXcgYEV2ZW50YCB1bmlvbiBhbmQgb3ZlcnJpZGluZyBgZXZlbnREYXRhYCBjb2xsYXBzZXNcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRvIGEgbm9uLWBob29rX3JlY2VpdmVkYCBtZW1iZXIgKHdob3NlIGBldmVudERhdGFgIGlzIGFcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGRpZmZlcmVudCBzaGFwZSk7IHRoZSBvYmplY3QgaXMgYSBnZW51aW5lIGBob29rX3JlY2VpdmVkYFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZXZlbnQgYnkgY29uc3RydWN0aW9uLlxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYmFzZSA9IGVuc3VyZWQuZXZlbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbnN1cmVkRXZlbnQgPSBiYXNlXG4gICAgICAgICAgICAgICAgICAgICAgICAgID8gKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLmJhc2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9rZW46IGhvb2tJbnB1dC50b2tlbixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF5bG9hZDogaG9va0lucHV0LnBheWxvYWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gYXMgRXZlbnQpXG4gICAgICAgICAgICAgICAgICAgICAgICAgIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQSBtYXRjaGluZyBjb25jdXJyZW50IGNsYWltIChzYW1lIHJlc3VtZUlkICsgZGlnZXN0KSBpc1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gcmVzb2x2ZWQgYXMgc3VjY2VzcyBzZXJ2ZXItc2lkZSBhbmQgbmV2ZXIgdGhyb3dzLCBzb1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYW55dGhpbmcgY2F1Z2h0IGhlcmUgaXMgYSBnZW51aW5lIHRlcm1pbmFsIG9yIHRyYW5zaWVudFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gY29uZGl0aW9uOlxuICAgICAgICAgICAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIC0gSG9va05vdEZvdW5kIC8gUnVuRXhwaXJlZDogdGhlIHByb2R1Y2VyJ3MgZGlyZWN0IHdyaXRlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgIGFscmVhZHkgZW5kZWQgdGhpcyByZXN1bWUncyBlbGlnaWJpbGl0eSAodGhlIHJ1biB3ZW50XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgIHRlcm1pbmFsKS4gVGhlcmUgaXMgbm90aGluZyBsZWZ0IHRvIHJlc3VtZSwgc28gY29uc3VtZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICB0aGUgbWVzc2FnZSBhbmQgc3RvcC4gQ29udGludWluZyB0byByZXBsYXkgd291bGQgYmVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgd2FzdGVkIHdvcmsg4oCUIGFuZCwgd29yc2UsIHdvdWxkIGFjayBhIGRlbGl2ZXJ5IHRoYXQgbWF5XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgIGNhcnJ5IHRoZSBvbmx5IGNvcHkgb2YgdGhlIHBheWxvYWQuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgIEhvb2tOb3RGb3VuZEVycm9yLmlzKGVycikgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgUnVuRXhwaXJlZEVycm9yLmlzKGVycilcbiAgICAgICAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAtIEVudGl0eUNvbmZsaWN0IChhbmQgYW55IG90aGVyIHVuZXhwZWN0ZWQgZXJyb3IpOiB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgcmVzdW1lSWQgY29uc3RyYWludCBleGlzdHMgYnV0IHRoZSBtYXRjaGluZyBldmVudCBpc1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICBub3QgeWV0IG9ic2VydmFibGUg4oCUIHRoZSBwcm9kdWNlcidzIHBhcmFsbGVsIHdyaXRlIGlzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgIHN0aWxsIGluIGZsaWdodCwgb3IgYSByZWRyaXZlIHJhY2VkIHRoZSBjbGFpbS4gVGhpcyBpc1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICB0cmFuc2llbnQ6IHJldGhyb3cgc28gdGhlIHF1ZXVlIHJlZGVsaXZlcnMgYW5kIGEgbGF0ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgYXR0ZW1wdCBjb252ZXJnZXMgb24gdGhlIGNvbW1pdHRlZCBldmVudCBpbnN0ZWFkIG9mXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgIHJlcGxheWluZyAoYW5kIGFja2luZykgd2l0aG91dCB0aGUgcGF5bG9hZC5cbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgLy8gVGhlIHJ1bl9zdGFydGVkIHJlc3BvbnNlIHByZWxvYWRlZCB0aGUgbG9nIEJFRk9SRSB0aGlzXG4gICAgICAgICAgICAgICAgICAgICAgLy8gZW5zdXJlLCBzbyBpdCBjYW5ub3QgaW5jbHVkZSB0aGUgaG9va19yZWNlaXZlZC4gUmF0aGVyXG4gICAgICAgICAgICAgICAgICAgICAgLy8gdGhhbiBkaXNjYXJkIHRoZSBwcmVsb2FkICh3aGljaCB3b3VsZCBjb3N0IGEgZnJlc2hcbiAgICAgICAgICAgICAgICAgICAgICAvLyBldmVudHMubGlzdCByb3VuZCB0cmlwIG9uIHRoZSBmaXJzdCByZXBsYXkgaXRlcmF0aW9uKSxcbiAgICAgICAgICAgICAgICAgICAgICAvLyBzcGxpY2UgaW4gdGhlIGNhbm9uaWNhbCBldmVudCByZWNvbnN0cnVjdGVkIGFib3ZlLiBJdFxuICAgICAgICAgICAgICAgICAgICAgIC8vIGNhcnJpZXMgYSBzdGFibGUgZXZlbnRJZCwgc28gYGluc2VydEV2ZW50QnlFdmVudElkYCBrZWVwc1xuICAgICAgICAgICAgICAgICAgICAgIC8vIGl0IGluIGFzY2VuZGluZyBldmVudElkIG9yZGVyIGFuZCBpcyBpZGVtcG90ZW50IGlmIGEgbGF0ZXJcbiAgICAgICAgICAgICAgICAgICAgICAvLyBsaXN0IHJlLW9ic2VydmVzIGl0LiBPbmx5IHdoZW4gdGhlIFdvcmxkIHJldHVybnMgbm8gZXZlbnRcbiAgICAgICAgICAgICAgICAgICAgICAvLyBkbyB3ZSBmYWxsIGJhY2sgdG8gcmVsb2FkaW5nIHRoZSBjb21wbGV0ZSBsb2cuXG4gICAgICAgICAgICAgICAgICAgICAgaWYgKGV2ZW50TG9nLnR5cGUgIT09ICdsb2FkQWxsJyAmJiBlbnN1cmVkRXZlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydEV2ZW50QnlFdmVudElkKGV2ZW50TG9nLmV2ZW50cywgZW5zdXJlZEV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRMb2cgPSB7IHR5cGU6ICdsb2FkQWxsJyB9O1xuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSAvLyBlbmQgZWxzZSAocmUtZW5zdXJlIG5lZWRlZClcbiAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgLy8gUmVzb2x2ZSB0aGUgZW5jcnlwdGlvbiBrZXkgZm9yIHRoaXMgcnVuJ3MgZGVwbG95bWVudC5cbiAgICAgICAgICAgICAgICAgIC8vIFVzZWQgZWFnZXJseSBoZXJlIHNpbmNlIGJvdGggd29ya2Zsb3cgZXhlY3V0aW9uIChpbnB1dFxuICAgICAgICAgICAgICAgICAgLy8gaHlkcmF0aW9uIC8gaG9vayBwYXlsb2FkIGRlY3J5cHRpb24pIGFuZCB0aGUgcnVuX2ZhaWxlZFxuICAgICAgICAgICAgICAgICAgLy8gZGVoeWRyYXRlIHBhdGggYmVsb3cgbmVlZCBpdC4gTWVtb2l6ZWQgYWNjZXNzb3I6IGZpcnN0XG4gICAgICAgICAgICAgICAgICAvLyBjYWxsIHRyaWdnZXJzIHRoZSBhY3R1YWwgZmV0Y2ggLyBIS0RGIGRlcml2YXRpb24sXG4gICAgICAgICAgICAgICAgICAvLyBzdWJzZXF1ZW50IGNhbGxzIGF3YWl0IHRoZSBjYWNoZWQgcHJvbWlzZS5cbiAgICAgICAgICAgICAgICAgIGNvbnN0IGdldEVuY3J5cHRpb25LZXkgPSBtZW1vaXplRW5jcnlwdGlvbktleShcbiAgICAgICAgICAgICAgICAgICAgd29ybGQsXG4gICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuXG4gICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgY29uc3QgZW5jcnlwdGlvbktleSA9IGF3YWl0IGdldEVuY3J5cHRpb25LZXkoKTtcblxuICAgICAgICAgICAgICAgICAgLy8gSW52b2NhdGlvbi1zY29wZWQgY2FjaGUgb2YgVk0taW5kZXBlbmRlbnQgcHJlcGFyZWQgcGF5bG9hZHNcbiAgICAgICAgICAgICAgICAgIC8vIGFuZCBpbW11dGFibGUgZmluYWwgdmFsdWVzLiBJdCBzdXJ2aXZlcyB0aGUgZnJlc2ggd29ya2Zsb3dcbiAgICAgICAgICAgICAgICAgIC8vIFZNIGNyZWF0ZWQgYnkgZWFjaCBpbmxpbmUgcmVwbGF5LCBidXQgbmV2ZXIgY3Jvc3NlcyBydW5zIG9yXG4gICAgICAgICAgICAgICAgICAvLyBxdWV1ZSBkZWxpdmVyaWVzLlxuICAgICAgICAgICAgICAgICAgY29uc3QgcmVwbGF5UGF5bG9hZENhY2hlID0gbmV3IFJlcGxheVBheWxvYWRDYWNoZShcbiAgICAgICAgICAgICAgICAgICAgZW5jcnlwdGlvbktleVxuICAgICAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgICAgICAgLy8gVGhlIGxpdmUgVk0gcGFya2VkIGF0IHRoZSBwcmV2aW91cyBib3VuZGFyeSwgd2hlbiB0aGVcbiAgICAgICAgICAgICAgICAgIC8vIHJldGVudGlvbiBkZWNpc2lvbiBrZXB0IGl0LiBudWxsIOKGkiB0aGlzIGl0ZXJhdGlvbiBjb2xkLVxuICAgICAgICAgICAgICAgICAgLy8gcmVwbGF5cy4gSW52b2NhdGlvbi1zY29wZWQ6IGRpZXMgd2l0aCB0aGlzIGRlbGl2ZXJ5LlxuICAgICAgICAgICAgICAgICAgbGV0IHJldGFpbmVkU2Vzc2lvbjogV29ya2Zsb3dTZXNzaW9uIHwgbnVsbCA9IG51bGw7XG5cbiAgICAgICAgICAgICAgICAgIC8vIE1haW4gcmVwbGF5IGxvb3BcbiAgICAgICAgICAgICAgICAgIC8vIGJpb21lLWlnbm9yZSBsaW50L2NvcnJlY3RuZXNzL25vQ29uc3RhbnRDb25kaXRpb246IGludGVudGlvbmFsIGxvb3BcbiAgICAgICAgICAgICAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGxvb3BJdGVyYXRpb24rKztcblxuICAgICAgICAgICAgICAgICAgICAvLyBSZXBsYXktYnVkZ2V0IGNoZWNrOiBiYWlsIG91dCAocmV0cnkgb3IgZmFpbCkgaWZcbiAgICAgICAgICAgICAgICAgICAgLy8gbm9uLXN0ZXAgdGltZSB3aXRoaW4gdGhpcyBpbnZvY2F0aW9uIGhhcyBleGNlZWRlZFxuICAgICAgICAgICAgICAgICAgICAvLyB0aGUgY29uZmlndXJlZCBidWRnZXQuIFN0ZXAgYm9kaWVzIGFyZSBleGNsdWRlZFxuICAgICAgICAgICAgICAgICAgICAvLyBiZWNhdXNlIHJlcGxheUJ1ZGdldC5wYXVzZSgpL3Jlc3VtZSgpIGJyYWNrZXQgZXZlcnlcbiAgICAgICAgICAgICAgICAgICAgLy8gYGV4ZWN1dGVTdGVwYCBjYWxsLlxuICAgICAgICAgICAgICAgICAgICBpZiAocmVwbGF5QnVkZ2V0LmlzRXhoYXVzdGVkKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBoYW5kbGVSZXBsYXlCdWRnZXRFeGhhdXN0ZWQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgcnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd05hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICByZXF1ZXN0SWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBhdHRlbXB0OiBtZXRhZGF0YS5hdHRlbXB0LFxuICAgICAgICAgICAgICAgICAgICAgICAgbGltaXRNczogcmVwbGF5QnVkZ2V0LmNvbmZpZ3VyZWRMaW1pdE1zLFxuICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgIC8vIE9ubHkgdGhlIHRlcm1pbmFsIGF0dGVtcHQgcmV0dXJucywgYWZ0ZXIgcnVuX2ZhaWxlZCBpc1xuICAgICAgICAgICAgICAgICAgICAgIC8vIGR1cmFibGUuIEVhcmxpZXIgYXR0ZW1wdHMgcmVqZWN0IGZvciBxdWV1ZSByZWRlbGl2ZXJ5LlxuICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIENoZWNrIHRpbWVvdXQgYmVmb3JlIHJlcGxheVxuICAgICAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgICAgRGF0ZS5ub3coKSAtIGludm9jYXRpb25TdGFydFRpbWUgPj1cbiAgICAgICAgICAgICAgICAgICAgICBub0lubGluZVJlcGxheUFmdGVyTXNcbiAgICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAgICAgICAgICAgJ1YyIHRpbWVvdXQgcmVhY2hlZCwgcmUtc2NoZWR1bGluZyB3b3JrZmxvdycsXG4gICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBsb29wSXRlcmF0aW9uLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBlbGFwc2VkTXM6IERhdGUubm93KCkgLSBpbnZvY2F0aW9uU3RhcnRUaW1lLFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgYXdhaXQgcXVldWVNZXNzYWdlKFxuICAgICAgICAgICAgICAgICAgICAgICAgd29ybGQsXG4gICAgICAgICAgICAgICAgICAgICAgICBnZXRXb3JrZmxvd1F1ZXVlTmFtZSh3b3JrZmxvd05hbWUsIG5hbWVzcGFjZSksXG4gICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjZUNhcnJpZXI6IGF3YWl0IG5leHRUcmFjZUNhcnJpZXIoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWVzdGVkQXQ6IG5ldyBEYXRlKCksXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBsZXQgcmVwbGF5U3RhcnQgPSAwO1xuICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgIC8vIC0tLSBRdWlja0pTIFZNIGVuZ2luZSBkaXNwYXRjaCAtLS1cbiAgICAgICAgICAgICAgICAgICAgICAvLyBUaGUgUXVpY2tKUyBlbmdpbmUgKG9wdC1pbiB2aWEgV09SS0ZMT1dfVk09cXVpY2tqc1xuICAgICAgICAgICAgICAgICAgICAgIC8vIG9yIGV4ZWN1dGlvbkNvbnRleHQud29ya2Zsb3dWbSkgaXMgYSBzZWxmLWNvbnRhaW5lZFxuICAgICAgICAgICAgICAgICAgICAgIC8vIGFsdGVybmF0aXZlIHRvIHRoZSBub2RlOnZtIGlubGluZS1yZXBsYXkgbG9naWNcbiAgICAgICAgICAgICAgICAgICAgICAvLyBiZWxvdy4gSXQgcGVyZm9ybXMgdGhlIHNhbWUgZnVsbCBldmVudCByZXBsYXksIGJ1dFxuICAgICAgICAgICAgICAgICAgICAgIC8vIHJ1bnMgdGhlIHdvcmtmbG93IGNvZGUgaW4gYSBRdWlja0pTIFdBU00gVk0sIHF1ZXVlc1xuICAgICAgICAgICAgICAgICAgICAgIC8vIHN0ZXBzIHZpYSB0aGUgc2FtZSBjb21iaW5lZCByb3V0ZSAoc28gdGhleSBoaXRcbiAgICAgICAgICAgICAgICAgICAgICAvLyBleGVjdXRlU3RlcCBiZWxvdyBvbiByZS1lbnRyeSksIGFuZCBtYW5hZ2VzIGl0cyBvd25cbiAgICAgICAgICAgICAgICAgICAgICAvLyBydW5fY29tcGxldGVkIC8gcnVuX2ZhaWxlZCBsaWZlY3ljbGUgZm9yIHdvcmtmbG93XG4gICAgICAgICAgICAgICAgICAgICAgLy8gb3V0Y29tZXMuIFdoZW4gdGhlIFF1aWNrSlMgZW5naW5lIGlzIGluIGVmZmVjdCxcbiAgICAgICAgICAgICAgICAgICAgICAvLyByZXR1cm4gaW1tZWRpYXRlbHkgYWZ0ZXIgZGlzcGF0Y2guXG4gICAgICAgICAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgICAgICAgICAvLyBEZWxpYmVyYXRlbHkgSU5TSURFIHRoaXMgdHJ5OiBlbmdpbmUgZmFpbHVyZXMgdGhhdFxuICAgICAgICAgICAgICAgICAgICAgIC8vIGVzY2FwZSB0aGUgZW50cnlwb2ludCAoTWF4RXZlbnRzRXhjZWVkZWRFcnJvciwgYVxuICAgICAgICAgICAgICAgICAgICAgIC8vIFdBU00gT09NIGF0IHRoZSBtZW1vcnkgY2VpbGluZywgYSBidW5kbGUtZXZhbFxuICAgICAgICAgICAgICAgICAgICAgIC8vIGZhaWx1cmUpIG11c3QgcmVhY2ggdGhpcyBsb29wJ3MgY2F0Y2ggc28gdGhleSBhcmVcbiAgICAgICAgICAgICAgICAgICAgICAvLyBjbGFzc2lmaWVkIGFuZCByZWNvcmRlZCBhcyBydW5fZmFpbGVkIOKAlCBvdXRzaWRlIHRoZVxuICAgICAgICAgICAgICAgICAgICAgIC8vIHRyeSB0aGV5IHdvdWxkIG5hY2sgdGhlIG1lc3NhZ2UgYW5kIGJ1cm4gYWxsIHF1ZXVlXG4gICAgICAgICAgICAgICAgICAgICAgLy8gcmVkZWxpdmVyaWVzIGJlZm9yZSBkeWluZyBhc1xuICAgICAgICAgICAgICAgICAgICAgIC8vIE1BWF9ERUxJVkVSSUVTX0VYQ0VFREVELiBUcmFuc2llbnQgd29ybGQgZXJyb3JzXG4gICAgICAgICAgICAgICAgICAgICAgLy8gc3RpbGwgcmV0aHJvdyBvdXQgb2YgdGhlIGNhdGNoIGZvciByZWRlbGl2ZXJ5LCBzYW1lXG4gICAgICAgICAgICAgICAgICAgICAgLy8gYXMgbm9kZS1lbmdpbmUgcmVwbGF5IGZhaWx1cmVzLlxuICAgICAgICAgICAgICAgICAgICAgIGlmICh1c2VRdWlja0pTVm0od29ya2Zsb3dSdW4pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBydW50aW1lTG9nZ2VyLmRlYnVnKCdVc2luZyBRdWlja0pTIFZNIGVuZ2luZScsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGxvb3BJdGVyYXRpb24sXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFVuZGVyIHR1cmJvLCBydW5fc3RhcnRlZCBpcyBiYWNrZ3JvdW5kZWQuIFRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gUXVpY2tKUyBlbnRyeXBvaW50IGZldGNoZXMgdGhlIGV2ZW50IGxvZyBhbmRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHdyaXRlcyBldmVudHMgZGlyZWN0bHksIHNvIHdhaXQgZm9yIHRoZSBydW4gdG8gYmVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGR1cmFibHkgc3RhcnRlZCBmaXJzdCDigJQgaXQgZG9lcyBub3QgdGhyZWFkIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdHVyYm8gcnVuUmVhZHlCYXJyaWVyIHRoZSB3YXkgaGFuZGxlU3VzcGVuc2lvblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZG9lcy5cbiAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IGF3YWl0UnVuUmVhZHkoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChldmVudExvZy50eXBlID09PSAnbG9hZEFmdGVyJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBlbmRFdmVudExvZyhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudExvZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBsb2FkV29ya2Zsb3dSdW5FdmVudHMocnVuSWQsIGV2ZW50TG9nLmN1cnNvcilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRMb2cgPSB7IC4uLmV2ZW50TG9nLCB0eXBlOiAncmVhZHknIH07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBMYXp5IGltcG9ydDogdGhlIFF1aWNrSlMgZW50cnlwb2ludCdzIGltcG9ydCBjaGFpblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZW1iZWRzIHRoZSBiYXNlNjQgV0FTTSBiaW5hcnkgKyBleHRlbnNpb25zXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAofjEuMyBNQiBkZWNvZGVkIGF0IG1vZHVsZSBzY29wZSkuIExvYWRpbmcgaXQgaGVyZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8ga2VlcHMgdGhhdCBvdXQgb2Ygbm9kZS1lbmdpbmUgZGVwbG95bWVudHMgZW50aXJlbHlcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIOKAlCBvbmx5IHRoZSBvcHQtaW4gcGF0aCBwYXlzLCBvbiBmaXJzdCBkaXNwYXRjaC5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHsgcnVuV29ya2Zsb3dXaXRoUXVpY2tKUyB9ID0gYXdhaXQgaW1wb3J0KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAnLi9ydW50aW1lL3F1aWNranMtZW50cnlwb2ludC5qcydcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBxdWlja2pzUmVzdWx0ID0gYXdhaXQgcnVuV29ya2Zsb3dXaXRoUXVpY2tKUyh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93Q29kZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlbG9hZGVkRXZlbnRzOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50TG9nLnR5cGUgPT09ICdyZWFkeSdcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gZXZlbnRMb2cuZXZlbnRzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlbG9hZGVkRXZlbnRzQ29tcGxldGU6IGV2ZW50TG9nLnR5cGUgPT09ICdyZWFkeScsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJ1bklucHV0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRTcGFuOiBzcGFuLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhFdmVudHNMaW1pdCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZXNwYWNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBuZXh0VHJhY2VDYXJyaWVyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJbmxpbmUtc3RlcCBvd25lcnNoaXAgcGx1bWJpbmc6IHJlZGVsaXZlcmllcyBvZlxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGlzIG1lc3NhZ2UgZHJpdmUgY3Jhc2ggcmVjb3ZlcnkgZm9yIHN0ZXBzIGFuXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGVhcmxpZXIgaW52b2NhdGlvbiBjbGFpbWVkIGlubGluZSAoc2VlIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBiYWNrc3RvcCBwYXNzIGluIHRoZSBlbnRyeXBvaW50J3MgbG9vcCksIGFuZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgbWVzc2FnZSBpZCBpcyBzdGFtcGVkIGFzIGBvd25lck1lc3NhZ2VJZGBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gb24gaW5saW5lIGxhenkgc3RlcCBjbGFpbXMgc28gd2FrZSByZXBsYXlzXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGRlZmVyIHRvIHRoZSBpbi1mbGlnaHQgYm9keSBpbnN0ZWFkIG9mXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHJlcXVldWVpbmcgdGhlIHN0ZXAuXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGl2ZXJ5QXR0ZW1wdDogbWV0YWRhdGEuYXR0ZW1wdCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgb3duZXJNZXNzYWdlSWQ6IG1ldGFkYXRhLm1lc3NhZ2VJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHF1aWNranNSZXN1bHQ/LnRpbWVvdXRTZWNvbmRzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVXNlIGByZWludm9rZWAgcmF0aGVyIHRoYW4gcmV0dXJuaW5nXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGB7IHRpbWVvdXRTZWNvbmRzIH1gIGRpcmVjdGx5OiB1bmRlciB0dXJibyB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gY3VycmVudCBtZXNzYWdlIGNhcnJpZXMgYHJ1bklucHV0YCBhbmQgYVxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyByZXNjaGVkdWxlIHdvdWxkIHJlLWVuZ2FnZSB0dXJibyBvbiByZWRlbGl2ZXJ5XG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIChyZXBsYXlpbmcgYWdhaW5zdCBhIHN0YWxlIHByZWxvYWRlZCBsb2cgYW5kXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHdlZGdpbmcgdGhlIHJ1biDigJQgc2VlIHRoZSByZWludm9rZSgpIGRvY3NcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWJvdmUpLiByZWludm9rZSBlbnF1ZXVlcyBhbiBleHBsaWNpdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBjb250aW51YXRpb24gd2l0aG91dCBgcnVuSW5wdXRgIGluIHRoYXQgY2FzZS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHJlaW52b2tlKHF1aWNranNSZXN1bHQudGltZW91dFNlY29uZHMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgIGlmIChldmVudExvZy50eXBlICE9PSAncmVhZHknKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwYWdlID0gYXdhaXQgbG9hZFdvcmtmbG93UnVuRXZlbnRzKFxuICAgICAgICAgICAgICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRMb2cudHlwZSA9PT0gJ2xvYWRBZnRlcidcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IGV2ZW50TG9nLmN1cnNvclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogdW5kZWZpbmVkXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGV2ZW50TG9nLnR5cGUgPT09ICdsb2FkQWZ0ZXInKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGVuZEV2ZW50TG9nKGV2ZW50TG9nLCBwYWdlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRMb2cgPSB7IC4uLmV2ZW50TG9nLCB0eXBlOiAncmVhZHknIH07XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudExvZyA9IHsgLi4ucGFnZSwgdHlwZTogJ3JlYWR5JyB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICBhc3NlcnQoZXZlbnRMb2cudHlwZSA9PT0gJ3JlYWR5Jyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICByZXBvcnRQcmVjb25kaXRpb25SZXN0YXJ0UmVsb2FkKGV2ZW50TG9nLmV2ZW50cyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAvLyBEZXRlY3QgY29uY3VycmVudCBjb21wbGV0aW9uIHZpYSB0aGUgZXZlbnQgbG9nOiBpZlxuICAgICAgICAgICAgICAgICAgICAgIC8vIGFueSBvdGhlciBoYW5kbGVyIHdyb3RlIGEgdGVybWluYWwgcnVuIGV2ZW50LCBleGl0XG4gICAgICAgICAgICAgICAgICAgICAgLy8gYmVmb3JlIGRvaW5nIHJlcGxheSB3b3JrLiBUaGUgcnVuIGVudGl0eSdzIHN0YXR1cyBpc1xuICAgICAgICAgICAgICAgICAgICAgIC8vIGRlcml2ZWQgZnJvbSB0aGVzZSBldmVudHMsIHNvIGNoZWNraW5nIHRoZSBsb2cgaGVyZVxuICAgICAgICAgICAgICAgICAgICAgIC8vIGdpdmVzIHVzIHRoZSBzYW1lIHNpZ25hbCBhcyBhIHJ1bnMuZ2V0KCkgcm91bmQtdHJpcFxuICAgICAgICAgICAgICAgICAgICAgIC8vIHdpdGhvdXQgdGhlIGV4dHJhIHJlcXVlc3QgcGVyIGxvb3AgaXRlcmF0aW9uLlxuICAgICAgICAgICAgICAgICAgICAgIGlmIChoYXNSZWNvcmRlZFRlcm1pbmFsUnVuRXZlbnQoZXZlbnRMb2cuZXZlbnRzLCBydW5JZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAvLyBDb21wbGV0ZSBlbGFwc2VkIHdhaXRzXG4gICAgICAgICAgICAgICAgICAgICAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjb21wbGV0ZWRXYWl0SWRzID0gbmV3IFNldChcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50TG9nLmV2ZW50c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAuZmlsdGVyKChlKSA9PiBlLmV2ZW50VHlwZSA9PT0gJ3dhaXRfY29tcGxldGVkJylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLm1hcCgoZSkgPT4gZS5jb3JyZWxhdGlvbklkKVxuICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3Qgd2FpdHNUb0NvbXBsZXRlID0gZXZlbnRMb2cuZXZlbnRzXG4gICAgICAgICAgICAgICAgICAgICAgICAuZmlsdGVyKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZVxuICAgICAgICAgICAgICAgICAgICAgICAgICApOiBlIGlzIEV4dHJhY3Q8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgeyBldmVudFR5cGU6ICd3YWl0X2NyZWF0ZWQnIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPiAmIHsgY29ycmVsYXRpb25JZDogc3RyaW5nIH0gPT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlLmV2ZW50VHlwZSA9PT0gJ3dhaXRfY3JlYXRlZCcgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlLmNvcnJlbGF0aW9uSWQgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICFjb21wbGV0ZWRXYWl0SWRzLmhhcyhlLmNvcnJlbGF0aW9uSWQpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm93ID49IChlLmV2ZW50RGF0YS5yZXN1bWVBdCBhcyBEYXRlKS5nZXRUaW1lKClcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICAgIC5tYXAoKGUpID0+ICh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50VHlwZTogJ3dhaXRfY29tcGxldGVkJyBhcyBjb25zdCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBlLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VtZUF0OiBlLmV2ZW50RGF0YS5yZXN1bWVBdCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pKTtcblxuICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3Qgd2FpdEV2ZW50IG9mIHdhaXRzVG9Db21wbGV0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY3JlYXRlZCA9IGF3YWl0IGNyZWF0ZUV2ZW50KHdhaXRFdmVudCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcXVlc3RJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5wcmVjb25kaXRpb25TbmFwc2hvdFBhcmFtcyhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50TG9nLmV2ZW50cyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50TG9nLmN1cnNvclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBCdW1wLWFuZC1yZXBvcnQ6IGZvbGQgd2hhdCB0aGlzIHdyaXRlIHNraXBwZWQgb3ZlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpbnRvIHRoZSBzbmFwc2hvdCB0aGUgcmVtYWluaW5nIHdhaXRzIGFyZSBndWFyZGVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFnYWluc3QsIHNvIGVhY2ggYXNrcyBmb3IgYSBzbG90IGFib3ZlIGl0LlxuICAgICAgICAgICAgICAgICAgICAgICAgICAvL1xuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPbmx5IGEgY29tcGxldGUgYW5zd2VyLiBgaGFzTW9yZWAgbWVhbnMgdGhlIFdvcmxkXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHJldHVybmVkIHBhcnQgb2Ygd2hhdCBpdCB3YXMgYXNrZWQgZm9yLCBhbmQgdGhlXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG1pc3NpbmctY29tcGxldGlvbiBjaGVjayBiZWxvdyBpcyB3aGF0IGRlY2lkZXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gd2hldGhlciB0aGlzIGhhbmRsZXIgc3RpbGwgaGFzIHRvIGZldGNoLiBGb2xkaW5nIGluXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGEgcGFydGlhbCBwYWdlIHdvdWxkIG1ha2UgdGhlIGxvZyBsb29rIGxpa2UgaXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaG9sZHMgdGhlIGNvbXBsZXRpb24gd2hlbiB0aGUgcmVzdCBvZiB0aGUgcGFnZSBpc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBzdGlsbCB1bnJlYWQsIHNvIHRoZSBmZXRjaCB3b3VsZCBiZSBza2lwcGVkIG9uIGFcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gc25hcHNob3QgdGhhdCBpcyBzaG9ydCBvZiB0aGUgV29ybGQncy5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNyZWF0ZWQuZXZlbnRzPy5sZW5ndGggJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjcmVhdGVkLmhhc01vcmUgIT09IHRydWVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVyZ2VSZXBvcnRlZEV2ZW50cyhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50TG9nLmV2ZW50cyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNyZWF0ZWQuZXZlbnRzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnV2FpdCBhbHJlYWR5IGNvbXBsZXRlZCwgc2tpcHBpbmcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogd2FpdEV2ZW50LmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgIGFzc2VydChldmVudExvZy50eXBlID09PSAncmVhZHknKTtcblxuICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZSBldmVudCBsaXN0IGFib3ZlIG1heSBiZSBzdGFsZSBieSB0aGUgdGltZSBhblxuICAgICAgICAgICAgICAgICAgICAgIC8vIGVsYXBzZWQgd2FpdCBpcyBjb21taXR0ZWQsIGFuZCB0aGlzIHJlcGxheSBoYXMgdG8gc2VlXG4gICAgICAgICAgICAgICAgICAgICAgLy8gaXRzIG93biB3YWl0X2NvbXBsZXRlZCBiZWZvcmUgaXQgY2FuIGFkdmFuY2UgcGFzdCB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAvLyBzbGVlcC4gRWFjaCB3cml0ZSBhc2tlZCB0aGUgV29ybGQgZm9yIHRoZSBkZWx0YSBzaW5jZVxuICAgICAgICAgICAgICAgICAgICAgIC8vIG91ciBjdXJzb3IgYW5kIGZvbGRlZCBpdCBpbiAoc2VlIGNyZWF0ZUV2ZW50KSwgc28gYVxuICAgICAgICAgICAgICAgICAgICAgIC8vIHN1cHBvcnRpbmcgV29ybGQgaGFzIGFscmVhZHkgaGFuZGVkIHRob3NlIGV2ZW50cyBiYWNrXG4gICAgICAgICAgICAgICAgICAgICAgLy8gYW5kIHRoZXJlIGlzIG5vdGhpbmcgbGVmdCB0byBkby4gT25seSBmZXRjaCBmb3IgdGhlXG4gICAgICAgICAgICAgICAgICAgICAgLy8gY29tcGxldGlvbnMgc3RpbGwgbWlzc2luZyBsb2NhbGx5OiBhIFdvcmxkIHRoYXRcbiAgICAgICAgICAgICAgICAgICAgICAvLyBpZ25vcmVzIGBzaW5jZUN1cnNvcmAsIGEgdHJ1bmNhdGVkIGRlbHRhLCBhIGNvbmN1cnJlbnRcbiAgICAgICAgICAgICAgICAgICAgICAvLyBhYnNvcmIgdGhhdCBsb3N0IHRoZSBjdXJzb3IgcmFjZSwgb3IgYW5cbiAgICAgICAgICAgICAgICAgICAgICAvLyBFbnRpdHlDb25mbGljdEVycm9yLCB3aG9zZSByZWplY3Rpb24gY2FycmllcyBubyBkZWx0YS5cbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjb21wbGV0ZWRXYWl0SWRzQWZ0ZXJXcml0ZXMgPSBuZXcgU2V0KFxuICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRMb2cuZXZlbnRzXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC5maWx0ZXIoKGUpID0+IGUuZXZlbnRUeXBlID09PSAnd2FpdF9jb21wbGV0ZWQnKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAubWFwKChlKSA9PiBlLmNvcnJlbGF0aW9uSWQpXG4gICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtaXNzaW5nV2FpdENvbXBsZXRpb25zID0gd2FpdHNUb0NvbXBsZXRlLmZpbHRlcihcbiAgICAgICAgICAgICAgICAgICAgICAgICh3YWl0RXZlbnQpID0+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICFjb21wbGV0ZWRXYWl0SWRzQWZ0ZXJXcml0ZXMuaGFzKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhaXRFdmVudC5jb3JyZWxhdGlvbklkXG4gICAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgICAgICAgaWYgKG1pc3NpbmdXYWl0Q29tcGxldGlvbnMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gTG9hZCBvbmx5IGV2ZW50cyBhZnRlciB0aGUgb3JpZ2luYWwgc25hcHNob3QgY3Vyc29yXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBzbyBjb25jdXJyZW50IGR1cmFibGUgZXZlbnRzLCBzdWNoIGFzIGhvb2tfcmVjZWl2ZWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBrZWVwIHRoZWlyIG9yZGVyaW5nIHJlbGF0aXZlIHRvIHdhaXRfY29tcGxldGVkLiBGYWxsXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBiYWNrIHRvIGEgZnVsbCByZWxvYWQgZm9yIG9sZGVyIHdvcmxkcyB0aGF0IGNhbm5vdFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZ2l2ZSB1cyBhIHN0YWJsZSBjdXJzb3IsIG9yIGlmIHRoZSBjdXJzb3IgZGVsdGEgZG9lc1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbm90IGluY2x1ZGUgdGhlIHdhaXQgY29tcGxldGlvbiB0aGlzIGhhbmRsZXIganVzdFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXR0ZW1wdGVkLlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGV2ZW50TG9nLmN1cnNvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwYWdlID0gYXdhaXQgbG9hZFdvcmtmbG93UnVuRXZlbnRzKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50TG9nLmN1cnNvclxuICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjb21wbGV0ZWRXYWl0SWRzQWZ0ZXJDdXJzb3IgPSBuZXcgU2V0KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2UuZXZlbnRzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuZmlsdGVyKChlKSA9PiBlLmV2ZW50VHlwZSA9PT0gJ3dhaXRfY29tcGxldGVkJylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5tYXAoKGUpID0+IGUuY29ycmVsYXRpb25JZClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2F3QWxsV2FpdENvbXBsZXRpb25zID1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaXNzaW5nV2FpdENvbXBsZXRpb25zLmV2ZXJ5KCh3YWl0RXZlbnQpID0+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21wbGV0ZWRXYWl0SWRzQWZ0ZXJDdXJzb3IuaGFzKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3YWl0RXZlbnQuY29ycmVsYXRpb25JZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNhd0FsbFdhaXRDb21wbGV0aW9ucykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGVuZEV2ZW50TG9nKGV2ZW50TG9nLCBwYWdlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudExvZyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLihhd2FpdCBsb2FkV29ya2Zsb3dSdW5FdmVudHMocnVuSWQpKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdyZWFkeScsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRMb2cgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uKGF3YWl0IGxvYWRXb3JrZmxvd1J1bkV2ZW50cyhydW5JZCkpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdyZWFkeScsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgLy8gQSByZXBsYXkgcmVhZHMgdGhlIGxvZyBhcyB0aGUgY29tcGxldGUgcmVjb3JkIG9mIHdoYXRcbiAgICAgICAgICAgICAgICAgICAgICAvLyBoYXMgaGFwcGVuZWQsIHNvIGEgcG9zaXRpb24gbm90aGluZyBvY2N1cGllcyBpc1xuICAgICAgICAgICAgICAgICAgICAgIC8vIGluZGlzdGluZ3Vpc2hhYmxlIGZyb20gYW4gZXZlbnQgdGhhdCBuZXZlciBvY2N1cnJlZCBhbmRcbiAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgYnJhbmNoIGl0IHdvdWxkIGhhdmUgZGVjaWRlZCBnZXRzIGRlY2lkZWQgdGhlIG90aGVyXG4gICAgICAgICAgICAgICAgICAgICAgLy8gd2F5LiBGYWlsaW5nIGhlcmUgaXMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBhIHJ1biB0aGF0XG4gICAgICAgICAgICAgICAgICAgICAgLy8gcmVwb3J0cyBpdHMgb3duIGNvcnJ1cHRpb24gYW5kIG9uZSB0aGF0IHNpbGVudGx5XG4gICAgICAgICAgICAgICAgICAgICAgLy8gcmV0dXJucyB0aGUgd3JvbmcgYW5zd2VyLlxuICAgICAgICAgICAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAgICAgICAgICAgLy8gQSBob2xlIHRoYXQgaXMgbWVyZWx5IGEgd3JpdGUgbWlkLWNvbW1pdCBmaWxscyBpbiBvblxuICAgICAgICAgICAgICAgICAgICAgIC8vIGl0cyBvd24sIHNvIHNldHRsZUV2ZW50U2xvdEdhcCByZS1yZWFkcyBiZWZvcmVcbiAgICAgICAgICAgICAgICAgICAgICAvLyBjb25jbHVkaW5nLCBhbmQgYWRvcHRzIHdoaWNoZXZlciBsb2cgaXQgc2V0dGxlZCBvbi5cbiAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNTbG90R2FwQ2hlY2tFbmFibGVkKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHNldHRsZWQgPSBhd2FpdCBzZXR0bGVFdmVudFNsb3RHYXAocnVuSWQsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzOiBldmVudExvZy5ldmVudHMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnNvcjogZXZlbnRMb2cuY3Vyc29yLFxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudExvZyA9IHsgLi4uc2V0dGxlZC5sb2csIHR5cGU6ICdyZWFkeScgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZXR0bGVkLmdhcCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBDb3JydXB0ZWRFdmVudExvZ0Vycm9yKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBFdmVudCBsb2cgZm9yIHJ1biAke3J1bklkfSBoYXMgYSBob2xlIGF0IHNsb3QgJHtzZXR0bGVkLmdhcC5maXJzdE1pc3NpbmdTbG90fTogJHtzZXR0bGVkLmdhcC5taXNzaW5nQ291bnR9IG9mIHRoZSAke3NldHRsZWQuZ2FwLm1heFNsb3R9IHNsb3RzIHVwIHRvIHRoZSBsb2cncyBtYXhpbXVtIGhvbGQgbm8gZXZlbnQuYFxuICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgIC8vIENvbXBsZXRpbmcgZWxhcHNlZCB3YWl0cyByZWZyZXNoZXMgdGhlIGV2ZW50IHNuYXBzaG90LlxuICAgICAgICAgICAgICAgICAgICAgIC8vIEEgY29uY3VycmVudCBoYW5kbGVyIG1heSBoYXZlIHdyaXR0ZW4gdGhlIHRlcm1pbmFsIHJ1blxuICAgICAgICAgICAgICAgICAgICAgIC8vIGV2ZW50IGFmdGVyIHRoZSBpbml0aWFsIHNuYXBzaG90IGJ1dCBiZWZvcmUgdGhpc1xuICAgICAgICAgICAgICAgICAgICAgIC8vIHJlcGxheS4gT25jZSB0aGUgZXZlbnQgbG9nIHJlY29yZHMgdGhhdCBvdXRjb21lLCB0aGlzXG4gICAgICAgICAgICAgICAgICAgICAgLy8gZGVsaXZlcnkgaXMgZG9uZS5cbiAgICAgICAgICAgICAgICAgICAgICBpZiAoaGFzUmVjb3JkZWRUZXJtaW5hbFJ1bkV2ZW50KGV2ZW50TG9nLmV2ZW50cywgcnVuSWQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgLy8gRXZlbnQtbGltaXQgZ3VhcmQ6IGZhaWwgYSBydW5hd2F5IHJ1biBvbmNlIGl0cyBsb2dcbiAgICAgICAgICAgICAgICAgICAgICAvLyByZWFjaGVzIHRoZSBzZXJ2ZXItc3VwcGxpZWQgY2VpbGluZyAodW5kZWZpbmVkIOKHkiBub1xuICAgICAgICAgICAgICAgICAgICAgIC8vIGVuZm9yY2VtZW50KS4gVGhlIHRocm93IGlzIGNhdWdodCBiZWxvdyBhbmQgd3JpdHRlbiBhc1xuICAgICAgICAgICAgICAgICAgICAgIC8vIHJ1bl9mYWlsZWQgLyBNQVhfRVZFTlRTX0VYQ0VFREVELlxuICAgICAgICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgICAgIG1heEV2ZW50c0xpbWl0ICE9PSB1bmRlZmluZWQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50TG9nLmV2ZW50cy5sZW5ndGggPj0gbWF4RXZlbnRzTGltaXRcbiAgICAgICAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBNYXhFdmVudHNFeGNlZWRlZEVycm9yKFxuICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudExvZy5ldmVudHMubGVuZ3RoLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhFdmVudHNMaW1pdFxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAvLyBMYXRlbmN5IHRlbGVtZXRyeToganVkZ2UgVFRGUyBlbGlnaWJpbGl0eSBhZ2FpbnN0IHRoZVxuICAgICAgICAgICAgICAgICAgICAgIC8vIGludm9jYXRpb24ncyBmaXJzdCBzbmFwc2hvdC4gV2FpdHMgY29tcGxldGVkIGFib3ZlXG4gICAgICAgICAgICAgICAgICAgICAgLy8gd291bGQgYWxyZWFkeSBkaXNxdWFsaWZ5IHZpYSB0aGUgZXZlbnQtdHlwZSBjaGVjaywgc29cbiAgICAgICAgICAgICAgICAgICAgICAvLyBldmFsdWF0aW5nIGFmdGVyIHRoZSB3YWl0IHBhc3MgaXMgZXF1aXZhbGVudC5cbiAgICAgICAgICAgICAgICAgICAgICAvLyBhdHRyX3NldCBpcyBwZXJtaXR0ZWQ6IGEgcmVkZWxpdmVyeSBjYW4gbGFuZCBhZnRlciBhXG4gICAgICAgICAgICAgICAgICAgICAgLy8gY29tbWl0dGVkIHByZS1zdGVwIGF0dHJfc2V0LCBhbmQgdGhlIGRldG91ciBpdCBtYXJrc1xuICAgICAgICAgICAgICAgICAgICAgIC8vIGlzIHN1YnRyYWN0ZWQgdmlhIHByZVN0ZXBBdHRyU3RhcnRNcyByZWdhcmRsZXNzIG9mXG4gICAgICAgICAgICAgICAgICAgICAgLy8gd2hpY2ggaW52b2NhdGlvbiB3cm90ZSBpdCAoc2VlIHJ1bnRpbWUvc3RlcC1sYXRlbmN5LnRzKS5cbiAgICAgICAgICAgICAgICAgICAgICBpbnZvY2F0aW9uU3RhcnRlZENsZWFuID8/PSBldmVudExvZy5ldmVudHMuZXZlcnkoXG4gICAgICAgICAgICAgICAgICAgICAgICAoZSkgPT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgZS5ldmVudFR5cGUgPT09ICdydW5fY3JlYXRlZCcgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZS5ldmVudFR5cGUgPT09ICdydW5fc3RhcnRlZCcgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZS5ldmVudFR5cGUgPT09ICdhdHRyX3NldCdcbiAgICAgICAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5kZWJ1ZygnU3RhcnRpbmcgd29ya2Zsb3cgZXhlY3V0aW9uJywge1xuICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBsb29wSXRlcmF0aW9uLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRDb3VudDogZXZlbnRMb2cuZXZlbnRzLmxlbmd0aCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGV4ZWN1dGlvbk1vZGU6IHJldGFpbmVkU2Vzc2lvbiA/ICdyZXRhaW5lZCcgOiAncmVwbGF5JyxcbiAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICByZXBsYXlTdGFydCA9IERhdGUubm93KCk7XG4gICAgICAgICAgICAgICAgICAgICAgLy8gU3RhcnQgZXZlcnkgbWlzc2luZyBkZWNyeXB0L2RlY29tcHJlc3Mgb3BlcmF0aW9uIHVwXG4gICAgICAgICAgICAgICAgICAgICAgLy8gZnJvbnQgKGFscmVhZHktcHJlcGFyZWQgcGF5bG9hZHMgYXJlIHNraXBwZWQpLiBXZWJcbiAgICAgICAgICAgICAgICAgICAgICAvLyBDcnlwdG8gd29yayBvdmVybGFwcyBWTSBzZXR1cCBvbiB0aGUgcmVwbGF5IHBhdGggYW5kXG4gICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIGFwcGVuZGVkIGV2ZW50cycgY29uc3VtcHRpb24gb24gdGhlIHJlc3VtZSBwYXRoO1xuICAgICAgICAgICAgICAgICAgICAgIC8vIGNvbnN1bWVycyBzdGlsbCBkZXNlcmlhbGl6ZSBhbmQgcmVzb2x2ZSBpbiBldmVudCBvcmRlci5cbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwYXlsb2FkUHJld2FybSA9IHJlcGxheVBheWxvYWRDYWNoZS5wcmV3YXJtKFxuICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudExvZy5ldmVudHNcbiAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgIGxldCB3b3JrZmxvd1Jlc3VsdDogV29ya2Zsb3dSZXN1bWVSZXN1bHQgPSByZXRhaW5lZFNlc3Npb25cbiAgICAgICAgICAgICAgICAgICAgICAgID8gYXdhaXQgcmVzdW1lV29ya2Zsb3cocmV0YWluZWRTZXNzaW9uLCBldmVudExvZy5ldmVudHMpXG4gICAgICAgICAgICAgICAgICAgICAgICA6IHsgdHlwZTogJ3JlcGxheScgfTtcblxuICAgICAgICAgICAgICAgICAgICAgIGlmICh3b3JrZmxvd1Jlc3VsdC50eXBlID09PSAncmVwbGF5Jykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0YWluZWRTZXNzaW9uID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UmVzdWx0ID0gYXdhaXQgcmVwbGF5V29ya2Zsb3coe1xuICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd0NvZGUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHM6IGV2ZW50TG9nLmV2ZW50cyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZW5jcnlwdGlvbktleSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwbGF5UGF5bG9hZENhY2hlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUdXJibzogdGhlIGVuZC1vZi1ydW4gZHJhaW4gaW5zaWRlIHdvcmtmbG93XG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGV4ZWN1dGlvbiBjb21taXRzIGZpcmUtYW5kLWZvcmdldCBgKl9jcmVhdGVkYFxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBldmVudHMgYmVmb3JlIHRoZSB0ZXJtaW5hbCBgYXdhaXRSdW5SZWFkeSgpYCBiZWxvdy5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgcnVuUmVhZHlCYXJyaWVyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JsZENhcGFiaWxpdGllczogd29ybGQuY2FwYWJpbGl0aWVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHBheWxvYWRQcmV3YXJtO1xuXG4gICAgICAgICAgICAgICAgICAgICAgaWYgKHdvcmtmbG93UmVzdWx0LnR5cGUgPT09ICdzdXNwZW5kZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBQYXJrIHRoZSBsaXZlIHNlc3Npb247IHRoZSBzdXNwZW5zaW9uIGNhdGNoIGJlbG93XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBtYWtlcyB0aGUgb25lIHJldGVudGlvbiBkZWNpc2lvbiDigJQga2VlcCBpdCBmb3IgdGhlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBuZXh0IGl0ZXJhdGlvbiBvciBkaXNjYXJkIGl0IGZvciBhIGZyZXNoIHJlcGxheS5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldGFpbmVkU2Vzc2lvbiA9IHdvcmtmbG93UmVzdWx0LnNlc3Npb247XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyB3b3JrZmxvd1Jlc3VsdC5zdXNwZW5zaW9uO1xuICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IHdvcmtmbG93UmVzdWx0Lm91dHB1dDtcbiAgICAgICAgICAgICAgICAgICAgICBydW50aW1lTG9nZ2VyLmRlYnVnKCdXb3JrZmxvdyBleGVjdXRpb24gY29tcGxldGVkJywge1xuICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBsb29wSXRlcmF0aW9uLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVwbGF5TXM6IERhdGUubm93KCkgLSByZXBsYXlTdGFydCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGV4ZWN1dGlvbk1vZGU6IHJldGFpbmVkU2Vzc2lvbiA/ICdyZXRhaW5lZCcgOiAncmVwbGF5JyxcbiAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICByZXBsYXlSZWNvdmVyeVJlcG9ydGVyLmFjdGl2YXRlKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAvLyBXb3JrZmxvdyBjb21wbGV0ZWQuIFNlbmQgdGhlIHNuYXBzaG90IGJ1dCBkbyBOT1RcbiAgICAgICAgICAgICAgICAgICAgICAvLyByZWxvYWQtYW5kLXJldHJ5IHRoZSBjcmVhdGUgaW4gcGxhY2U6IGByZXN1bHRgIHdhc1xuICAgICAgICAgICAgICAgICAgICAgIC8vIGNvbXB1dGVkIGJ5IHRoaXMgcmVwbGF5LCBzbyBhIHN0YWxlICg0MTIpIHJlamVjdGlvbiBtdXN0XG4gICAgICAgICAgICAgICAgICAgICAgLy8gZm9yY2UgYSAqZnJlc2ggcmVwbGF5KiAod2hpY2ggbWF5IG9ic2VydmUgdGhlIG5ldyBldmVudFxuICAgICAgICAgICAgICAgICAgICAgIC8vIGFuZCBwcm9kdWNlIGEgZGlmZmVyZW50IHJlc3VsdCksIG5vdCByZS1jb21taXQgdGhlIHN0YWxlXG4gICAgICAgICAgICAgICAgICAgICAgLy8gcmVzdWx0LiBUaGUgY2F0Y2ggYmVsb3cgcmVzdGFydHMgdGhlIHJlcGxheSBpbi1wcm9jZXNzLlxuICAgICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBUdXJibzogYSB3b3JrZmxvdyB0aGF0IGZpbmlzaGVzIHdpdGggbm8gc3RlcHMgcmVhY2hlc1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaGVyZSBiZWZvcmUgdGhlIGJhY2tncm91bmRlZCBydW5fc3RhcnRlZDsgb3JkZXIgdGhlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB0ZXJtaW5hbCB3cml0ZSBhZnRlciBpdCBzbyB0aGUgcnVuIGV4aXN0cy5cbiAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IGF3YWl0UnVuUmVhZHkoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IGNyZWF0ZUV2ZW50KFxuICAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRUeXBlOiAncnVuX2NvbXBsZXRlZCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50RGF0YTogeyBvdXRwdXQ6IHJlc3VsdCB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWVzdElkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLnByZWNvbmRpdGlvblNuYXBzaG90UGFyYW1zKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRMb2cuZXZlbnRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRMb2cuY3Vyc29yXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgIFJ1bkV4cGlyZWRFcnJvci5pcyhlcnIpXG4gICAgICAgICAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdUcmllZCBjb21wbGV0aW5nIHdvcmtmbG93IHJ1biwgYnV0IHJ1biBoYXMgYWxyZWFkeSBmaW5pc2hlZC4nLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsgd29ya2Zsb3dSdW5JZDogcnVuSWQsIG1lc3NhZ2U6IGVyci5tZXNzYWdlIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLldvcmtmbG93UnVuU3RhdHVzKCdjb21wbGV0ZWQnKSxcbiAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgICAgICAgIGlmIChXb3JrZmxvd1N1c3BlbnNpb24uaXMoZXJyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVwbGF5UmVjb3ZlcnlSZXBvcnRlci5hY3RpdmF0ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gU3luY2hyb25vdXMgd29ya2Zsb3ctZXhlY3V0aW9uIGR1cmF0aW9uIGZvciBUSElTXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBzdXNwZW5zaW9uIG9ubHkg4oCUIGFuY2hvcnMgdGhlIGBmaW5hbFNjaGVkdWxpbmdSZXBsYXlgXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB0ZWxlbWV0cnkgZmllbGQgYmVsb3cgKHNlZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gU3RlcExhdGVuY3lUcmFja2luZy5yZXBsYXlNcykuIFRoaXMgaXMgdGhlIEZJTkFMXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyByZXBsYXkgcGFzcywgdGhlIG9uZSB0aGF0IHJlYWNoZWQgYW5kIHNjaGVkdWxlZCB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGZpcnN0IHN0ZXA6IHZhbGlkIHJzZnMgcGF0aHMgY2FuIHJlcGxheSBtb3JlIHRoYW5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG9uY2UgYmVmb3JlIHRoZSBmaXJzdCBzdGVwIChlLmcuIGEgd29ya2Zsb3ctYm9keVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYHNldEF0dHJpYnV0ZXMoKWAgZGV0b3VyIHJlcGxheXMgdHdpY2UpLCBhbmQgYVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gcmVkZWxpdmVyeSBvbWl0cyBlYXJsaWVyIGludm9jYXRpb25zJyByZXBsYXkgd29ya1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZW50aXJlbHkuIFRoaXMgdmFsdWUgaXMgTk9UIGFjY3VtdWxhdGVkIGFjcm9zc1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhvc2UgZWFybGllciBwYXNzZXMsIHNvIGl0IG11c3Qgbm90IGJlIHJlYWQgYXNcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFwidGhlIHJlcGxheSBwb3J0aW9uIG9mIHJzZnNcIiDigJQgcnNmcyBjb3ZlcnMgdGhlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB3aG9sZSBydW5fc3RhcnRlZC10by1maXJzdC1zdGVwIHdpbmRvdztcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGZpbmFsU2NoZWR1bGluZ1JlcGxheSBjb3ZlcnMgb25seSB0aGlzIGxhc3QgcGFzcy5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIENhcHR1cmVkIGhlcmUsIGJlZm9yZSBgaGFuZGxlU3VzcGVuc2lvbmAncyBhd2FpdGVkXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBJL08sIHNvIGl0IGV4Y2x1ZGVzIHRoYXQgSS9PLlxuICAgICAgICAgICAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgZHVwbGljYXRlcyB3aGF0IE9URUwgYWxyZWFkeSBjYXB0dXJlcyBvbiB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHJ1bi9pbnZvY2F0aW9uIHNwYW4sIGJ1dCBpcyBjb2xsZWN0ZWQgYXMgY2xpZW50XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB0ZWxlbWV0cnkgc28gdGhlIHNlcnZlciBjYW4gZW1pdCBpdCBhcyBhblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVU5TQU1QTEVELCBmdWxsLXBvcHVsYXRpb24gbWV0cmljOiB3b3JrZmxvdy1zZXJ2ZXInc1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gc2VydmVyIHNwYW5zIGFyZSBoZWF2aWx5IHNhbXBsZWQgaW4gcHJvZHVjdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gKH43JSksIGFuZCBjbGllbnQgc3BhbnMgY2FuJ3QgYmUgZmlsdGVyZWQgYnkgU0RLXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB2ZXJzaW9uLCBzbyBuZWl0aGVyIGNhbiBzZXJ2ZSBhcyB0aGUgZGFzaGJvYXJkJ3NcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGV4YWN0IFRURlMgZGVjb21wb3NpdGlvbi4gT24gYSByZXRhaW5lZC1WTVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gcmVzdW1lIHRoaXMgbWVhc3VyZXMgdGhlIHJlc3VtZSAodHlwaWNhbGx5IH4wbXMpLFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbm90IGEgcmVwbGF5LCBzbyB0aGUgZmllbGQncyBkaXN0cmlidXRpb24gaXNcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGJpbW9kYWwgb25jZSByZXRlbnRpb24gaXMgYWN0aXZlLlxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVwbGF5RHVyYXRpb25NcyA9IERhdGUubm93KCkgLSByZXBsYXlTdGFydDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuZGVidWcoJ1dvcmtmbG93IHN1c3BlbmRlZCcsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGxvb3BJdGVyYXRpb24sXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJlcGxheU1zOiByZXBsYXlEdXJhdGlvbk1zLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBzdGVwczogZXJyLnN0ZXBDb3VudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaG9va3M6IGVyci5ob29rQ291bnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHdhaXRzOiBlcnIud2FpdENvdW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdXNwZW5zaW9uTWVzc2FnZSA9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGJ1aWxkV29ya2Zsb3dTdXNwZW5zaW9uTWVzc2FnZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnIuc3RlcENvdW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVyci5ob29rQ291bnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyLndhaXRDb3VudFxuICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN1c3BlbnNpb25NZXNzYWdlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuZGVidWcoc3VzcGVuc2lvbk1lc3NhZ2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBWMjogaGFuZGxlIHN1c3BlbnNpb24gd2l0aG91dCBxdWV1aW5nIHN0ZXBzLlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRWFjaCBldmVudCBjcmVhdGlvbiBpbnNpZGUgaGFuZGxlU3VzcGVuc2lvbiBjYXJyaWVzIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gcHJlY29uZGl0aW9uIHNuYXBzaG90IG9mIHRoZSBsb2FkZWQgZXZlbnQgbG9nLCBzbyBhXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBiYWNrZW5kIGhvbGRpbmcgYW4gZXZlbnQgdGhpcyByZXBsYXkgbmV2ZXIgc2F3IHJlamVjdHNcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSB3cml0ZSAoNDEyKSBpbnN0ZWFkIG9mIGFjY2VwdGluZyBhIGRpdmVyZ2VudCBvbmUuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGUgcmVqZWN0aW9uIGlzIGhhbmRsZWQgaGVyZSwgYnkgcmVzdGFydGluZyB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHJlcGxheSDigJQgbmV2ZXIgYnkgcmUtcG9zdGluZyB0aGUgc2FtZSBldmVudC5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN1c3BlbnNpb25TdGFydCA9IERhdGUubm93KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhc3NlcnQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50TG9nLnR5cGUgPT09ICdyZWFkeScsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICdXb3JrZmxvdyBzdXNwZW5kZWQgYmVmb3JlIGl0cyBldmVudCBsb2cgd2FzIGxvYWRlZCdcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgc3VzcGVuc2lvblJlc3VsdDogQXdhaXRlZDxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgUmV0dXJuVHlwZTx0eXBlb2YgaGFuZGxlU3VzcGVuc2lvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgID47XG4gICAgICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBzdXNwZW5zaW9uUmVzdWx0ID0gYXdhaXQgaGFuZGxlU3VzcGVuc2lvbih7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VzcGVuc2lvbjogZXJyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmxkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJ1bjogd29ya2Zsb3dSdW4sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BhbixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXF1ZXN0SWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRMb2csXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcnVuUmVhZHlCYXJyaWVyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcGxheVJlY292ZXJ5UmVwb3J0ZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoc3VzcGVuc2lvbkVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEEgc3VzcGVuc2lvbiBjcmVhdGUgd2FzIHJlamVjdGVkIGFzIHN0YWxlOiByZS1kZXJpdmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIHJlcGxheSBmcm9tIGEgY29ycmVjdGVkIGxvZyBpbiB0aGlzIGludm9jYXRpb24uXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9uY2UgdGhlIGluLXByb2Nlc3MgYnVkZ2V0IGlzIHNwZW50LCBmYWxsIGJhY2sgdG8gYW5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gZXhwbGljaXQgaW1tZWRpYXRlIHJlLWludm9jYXRpb24gKGEgcmV0aHJvdyByZWxpZXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gb24gcmVkZWxpdmVyeSBvZiBhIG1lc3NhZ2UgdGhlIHR1cmJvIHBhdGggYWxyZWFkeVxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhY2tlZCDigJQgdGhlIHJ1biB3b3VsZCBzdGFsbCBmb3IgdGhlIHF1ZXVlJ3MgfjMwMHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gZGVmYXVsdCB2aXNpYmlsaXR5IHRpbWVvdXQpLlxuICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoUHJlY29uZGl0aW9uRmFpbGVkRXJyb3IuaXMoc3VzcGVuc2lvbkVycm9yKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3RhcnRSZXBsYXlJblByb2Nlc3MoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdXNwZW5zaW9uLWNyZWF0ZScsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1c3BlbnNpb25FcnJvclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVzY2FsYXRpb24gPVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgcmVpbnZva2VBZnRlclN0YWxlUmVqZWN0aW9uKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3VzcGVuc2lvbi1jcmVhdGUnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdXNwZW5zaW9uRXJyb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVzY2FsYXRpb24ucmVpbnZva2VkKSByZXR1cm4gZXNjYWxhdGlvbi5yZXN1bHQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUGVyLXJ1biBidWRnZXQgc3BlbnQ6IGZhaWwgdGhlIHJ1biByYXRoZXIgdGhhblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGhhbmQgaXQgYmFjayB0byB0aGUgcXVldWUgdG8gc3BpbiBhZ2Fpbi5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBlc2NhbGF0aW9uLmVycm9yO1xuICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghRmF0YWxFcnJvci5pcyhzdXNwZW5zaW9uRXJyb3IpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVHJhbnNpZW50IGZhaWx1cmVzIHByb3BhZ2F0ZSB0byB0aGUgcXVldWVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBoYW5kbGVyIHNvIHRoZSBtZXNzYWdlIGlzIHJlZGVsaXZlcmVkLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IHN1c3BlbnNpb25FcnJvcjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBOb24tcmV0cnlhYmxlIGZhaWx1cmUgd2hpbGUgY29tbWl0dGluZyB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gc3VzcGVuc2lvbidzIGV2ZW50cyDigJQgZS5nLiBhbiBhdHRyaWJ1dGUgd3JpdGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIFdvcmxkIHJlamVjdGVkIGFzIGludmFsaWQgKHRoZSBjdW11bGF0aXZlXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHBlci1ydW4gY2FwIGNhbiBvbmx5IGJlIGNoZWNrZWQgV29ybGQtc2lkZSkuXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJlZGVsaXZlcnkgd291bGQgcmVwbGF5IHRoZSB3b3JrZmxvdyBpbnRvIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBzYW1lIHdyaXRlIGFuZCB0aGUgc2FtZSByZWplY3Rpb24sIHNvIGZhaWwgdGhlXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHJ1biB3aXRoIHRoZSBlcnJvciBpbnN0ZWFkIG9mIHdlZGdpbmcgdGhlXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG1lc3NhZ2UgaW4gcmVkZWxpdmVyeS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3JDb2RlID0gY2xhc3NpZnlSdW5FcnJvcihzdXNwZW5zaW9uRXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBydW50aW1lTG9nZ2VyLmVycm9yKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdOb24tcmV0cnlhYmxlIGVycm9yIHdoaWxlIGNvbW1pdHRpbmcgd29ya2Zsb3cgc3VzcGVuc2lvbjsgZmFpbGluZyBydW4nLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDb2RlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lOiBzdXNwZW5zaW9uRXJyb3IubmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZTogc3VzcGVuc2lvbkVycm9yLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFR1cmJvOiBvcmRlciB0aGUgdGVybWluYWwgd3JpdGUgYWZ0ZXIgdGhlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYmFja2dyb3VuZGVkIHJ1bl9zdGFydGVkIHNvIHRoZSBydW4gZXhpc3RzLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IGF3YWl0UnVuUmVhZHkoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBjcmVhdGVFdmVudChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRUeXBlOiAncnVuX2ZhaWxlZCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3I6IGF3YWl0IGRlaHlkcmF0ZVJ1bkVycm9yKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VzcGVuc2lvbkVycm9yLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmNyeXB0aW9uS2V5LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2xvYmFsVGhpcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh3b3JrZmxvd1J1bj8uc3BlY1ZlcnNpb24gPz8gMCkgPj1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU1BFQ19WRVJTSU9OX1NVUFBPUlRTX0NPTVBSRVNTSU9OXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNvZGUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeyByZXF1ZXN0SWQgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGZhaWxFcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFbnRpdHlDb25mbGljdEVycm9yLmlzKGZhaWxFcnIpIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSdW5FeHBpcmVkRXJyb3IuaXMoZmFpbEVycilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbyhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ1RyaWVkIGZhaWxpbmcgd29ya2Zsb3cgcnVuLCBidXQgcnVuIGhhcyBhbHJlYWR5IGZpbmlzaGVkLicsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBmYWlsRXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IGZhaWxFcnI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLldvcmtmbG93UnVuU3RhdHVzKCdmYWlsZWQnKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dFcnJvckNvZGUoZXJyb3JDb2RlKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dFcnJvck5hbWUoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdXNwZW5zaW9uRXJyb3IubmFtZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLldvcmtmbG93RXJyb3JNZXNzYWdlKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VzcGVuc2lvbkVycm9yLm1lc3NhZ2VcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5FcnJvclR5cGUoc3VzcGVuc2lvbkVycm9yLm5hbWUpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN1c3BlbnNpb25SZXN1bHQucmVwb3J0ZWRFdmVudENvdW50ID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBCdW1wLWFuZC1yZXBvcnQgbWVyZ2VkIGV2ZW50cyBCRUxPVyB0aGUgdGFpbCBhbmRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gcmUtc29ydGVkIHRoZSBhcnJheSB0byBzbG90IG9yZGVyLCBzaGlmdGluZyBldmVyeVxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBwb3NpdGlvbiB0aGUgcHJld2FybSBzY2FuIGhhZCBhbHJlYWR5IHJlY29yZGVkLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGUgY3Vyc29yIGlzIGRlbGliZXJhdGVseSBsZWZ0IGFsb25lOiB0aGUgcmVwb3J0XG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlzIGEgbG93ZXIgYm91bmQgb24gd2hhdCB3YXMgc2tpcHBlZCwgc28gdGhlIG5leHRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW5jcmVtZW50YWwgcmVhZCBzdGlsbCBoYXMgdG8gY292ZXIgdGhlIHNhbWUgcmFuZ2UuXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJlcGxheVBheWxvYWRDYWNoZS5yZXNldFNjYW4oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3BlbiBob29rcy93YWl0cyBpbiB0aGUgbG9nIGFzIGxvYWRlZCBmb3IgdGhpc1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gcmVwbGF5LiBUaGlzIHN1c3BlbnNpb24ncyBvd24gaG9vay93YWl0IHdyaXRlcyBhcmVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE5PVCBpbiBpdCDigJQgdGhleSBuZXZlciByZWFjaCByZXRlbnRpb24gYW55d2F5LFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYmVjYXVzZSBhIHN1c3BlbnNpb24gY29udGFpbmluZyBhIG5vbi1zdGVwIGl0ZW1cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGZhaWxzIGNhblJldGFpbldvcmtmbG93U2Vzc2lvbidzIHR5cGUgY2hlY2sgYmVmb3JlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgc2NhbiBpcyBjb25zdWx0ZWQuIENvbXB1dGVkXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBsYXppbHksIGF0IG1vc3Qgb25jZSwgYW5kIHNoYXJlZCBiZXR3ZWVuIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gcmV0ZW50aW9uIGRlY2lzaW9uIGhlcmUgYW5kIHRoZSBkZWx0YS90dXJibyBnYXRlc1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYmVsb3cg4oCUIHRoZSBhdHRyLWRldG91ciBhbmQgaG9vay1jb25mbGljdCBwYXRoc1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gcmV0dXJuL2NvbnRpbnVlIGJlZm9yZSB0aGUgZ2F0ZXMgYW5kIHVzdWFsbHlcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNob3J0LWNpcmN1aXQgYmVmb3JlIGV2ZXIgc2Nhbm5pbmcgdGhlIGxvZy5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG9wZW5Ib29rV2FpdCA9IG9uY2UoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBhc3NlcnQoZXZlbnRMb2cudHlwZSA9PT0gJ3JlYWR5Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBvcGVuSG9va0FuZFdhaXRTdGF0ZShldmVudExvZy5ldmVudHMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZSBzaW5nbGUgcmV0ZW50aW9uIGRlY2lzaW9uOiBrZWVwIHRoZSBwYXJrZWRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNlc3Npb24gb25seSBhY3Jvc3MgYSBwdXJlIHN0ZXAgYm91bmRhcnkgd2l0aCBub1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gb3V0LW9mLWJhbmQgY29udGludWF0aW9uIHNvdXJjZSBhbmQgcHJvdmFibHlcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHBhc3NpdmUgc3RlcCBpbnB1dHMuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJldGFpbmVkU2Vzc2lvbiAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAhY2FuUmV0YWluV29ya2Zsb3dTZXNzaW9uKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdXNwZW5zaW9uUmVzdWx0LnJldGFpbmVkU3RlcElucHV0c1NhZmUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3Blbkhvb2tXYWl0XG4gICAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICByZXRhaW5lZFNlc3Npb24gPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgcHJlU3RlcEJsb2NraW5nTXMgKz0gc3VzcGVuc2lvblJlc3VsdC5ob29rQ3JlYXRpb25NcztcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgc3VzcGVuc2lvblJlc3VsdC5oYXNBdHRyaWJ1dGVFdmVudHMgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlU3RlcEJsb2NraW5nQmVmb3JlQXR0ck1zID09PSB1bmRlZmluZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBwcmVTdGVwQmxvY2tpbmdCZWZvcmVBdHRyTXMgPSBwcmVTdGVwQmxvY2tpbmdNcztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuZGVidWcoJ1N1c3BlbnNpb24gaGFuZGxlZCcsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHN1c3BlbnNpb25NczogRGF0ZS5ub3coKSAtIHN1c3BlbnNpb25TdGFydCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcGVuZGluZ1N0ZXBzOiBzdXNwZW5zaW9uUmVzdWx0LnBlbmRpbmdTdGVwcy5sZW5ndGgsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHRpbWVvdXRTZWNvbmRzOiBzdXNwZW5zaW9uUmVzdWx0LndhaXRUaW1lb3V0Py5zZWNvbmRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNIb29rQ29uZmxpY3Q6IHN1c3BlbnNpb25SZXN1bHQuaGFzSG9va0NvbmZsaWN0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNBd2FpdGVkSG9va0NyZWF0aW9uOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1c3BlbnNpb25SZXN1bHQuaGFzQXdhaXRlZEhvb2tDcmVhdGlvbixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzQXR0cmlidXRlRXZlbnRzOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1c3BlbnNpb25SZXN1bHQuaGFzQXR0cmlidXRlRXZlbnRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEhvb2sgY29uZmxpY3Q6IGJyZWFrIGxvb3AsIHJlLWludm9rZSB2aWEgcXVldWVcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdXNwZW5zaW9uUmVzdWx0Lmhhc0hvb2tDb25mbGljdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYXdhaXQgcmVpbnZva2UoMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE5hdGl2ZSB3b3JrZmxvdyBhdHRyaWJ1dGUgZXZlbnRzIGFyZSByZXNvbHZlZFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhyb3VnaCByZXBsYXk6IHRoZSBuZXh0IGxvb3AgaXRlcmF0aW9uIHJlbG9hZHMgdGhlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBsb2cgKG5vdyBob2xkaW5nIHRoZSBqdXN0LWNvbW1pdHRlZCBhdHRyX3NldCkgYW5kXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyByZXBsYXlzLCByZXNvbHZpbmcgdGhlIHNldEF0dHJpYnV0ZXMgcHJvbWlzZS4gU2tpcFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gc3RlcCBwcm9jZXNzaW5nIGZvciB0aGlzIHBhc3Mgc28gdGhhdCByZXBsYXkgZGVjaWRlc1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gcmFjZXMgZmlyc3Qg4oCUIGluIFByb21pc2UucmFjZShbc2V0QXR0cmlidXRlcygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gc3RlcCgpXSksIHRoZSBkdXJhYmxlIGF0dHJpYnV0ZSBldmVudCBtdXN0IGJlIGFibGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRvIHdpbiB3aXRob3V0IGV4ZWN1dGluZyB0aGUgbG9zaW5nIHN0ZXAuIFRoZSByZXBsYXlcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGhhcHBlbnMgaW4tcHJvY2VzcyByYXRoZXIgdGhhbiB2aWEgYSBxdWV1ZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gcmUtaW52b2NhdGlvbjogdW5saWtlIGhvb2tzIGFuZCB3YWl0cywgYW4gYXR0cl9zZXRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGludHJvZHVjZXMgbm8gb3V0LW9mLWJhbmQgaW52b2NhdGlvbiBzb3VyY2UgdGhhdCB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGhhbmRsZXIgd291bGQgbmVlZCB0byB5aWVsZCB0aGUgbWVzc2FnZSBmb3IsIHNvXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBwYXlpbmcgYSBkZWxpdmVyeSByb3VuZC10cmlwIGhlcmUgd291bGQgb25seSBhZGRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGxhdGVuY3kgYmVmb3JlIHRoZSB3b3JrZmxvdydzIG5leHQgc3RlcC5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdXNwZW5zaW9uUmVzdWx0Lmhhc0F0dHJpYnV0ZUV2ZW50cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudExvZyA9IG5leHRFdmVudExvZ0xvYWQoZXZlbnRMb2cpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcGVuZGluZ1N0ZXBzID0gc3VzcGVuc2lvblJlc3VsdC5wZW5kaW5nU3RlcHM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIElubGluZSBleGVjdXRpb24gaXMgZ2F0ZWQgb24gb3duZXJzaGlwLiBUaGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHN1c3BlbnNpb24gaGFuZGxlciBkZWZlcnJlZCB0aGUgc3RlcF9jcmVhdGVkIHdyaXRlIGZvclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdXAgdG8gYGdldE1heElubGluZVN0ZXBzKClgIHN0ZXBzIChgbGF6eUlubGluZVN0ZXBzYClcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNvIHdlIGNhbiBydW4gdGhlbSBpbmxpbmUg4oCUIGluIHBhcmFsbGVsIOKAlCB2aWEgbGF6eVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYHN0ZXBfc3RhcnRlZGAgZXZlbnRzIHRoYXQgY3JlYXRlIGVhY2ggc3RlcCBvbiB0aGUgZmx5LFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gc2F2aW5nIG9uZSB3b3JsZCByb3VuZC10cmlwIHBlciBpbmxpbmUgc3RlcC4gT3duZXJzaGlwXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpcyBzdGlsbCBhdG9taWMgYW5kIGV4YWN0bHktb25lIHBlciBzdGVwOiB0aGUgd29ybGQnc1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gY3JlYXRlLWNsYWltIGluc2lkZSBlYWNoIHN0ZXBfc3RhcnRlZCByZXR1cm5zXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBgRW50aXR5Q29uZmxpY3RFcnJvcmAgKOKGkiBleGVjdXRlU3RlcCBgc2tpcHBlZGApIHRvIGFueVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gY29uY3VycmVudCBsb3Nlciwgc28gb25seSBvbmUgaGFuZGxlciBldmVyIHJ1bnMgYSBnaXZlblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYm9keS4gRXZlcnkgb3RoZXIgcGVuZGluZyBzdGVwIGtlZXBzIGl0cyBlYWdlclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gc3RlcF9jcmVhdGVkIChpbiBgY3JlYXRlZFN0ZXBDb3JyZWxhdGlvbklkc2ApIGFuZCBpc1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gcXVldWVkIGJlbG93LlxuICAgICAgICAgICAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZSBzdXNwZW5zaW9uIGhhbmRsZXIgb25seSBkZXNpZ25hdGVzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBgbGF6eUlubGluZVN0ZXBzYCB3aGVuIG5vIGBob29rLmdldENvbmZsaWN0KClgIGF3YWl0ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlzIHByZXNlbnQuIFRoYXQgYXdhaXRlciBjYXNlIG11c3QgZXhlY3V0ZSBub3RoaW5nXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpbmxpbmU6IGFuIGlubGluZSBgYXdhaXQgZXhlY3V0ZVN0ZXAoLi4uKWAgYmxvY2tzIHRoaXNcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGhhbmRsZXIgZm9yIHRoZSBmdWxsIHN0ZXAgZHVyYXRpb24sIHNvIHRoZSBhd2FpdGVyJ3NcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNvbnRpbnVhdGlvbiAod2hpY2ggb25seSBhZHZhbmNlcyBvbiB0aGUgbmV4dCByZXBsYXkpXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB3b3VsZCBiZSBzZXJpYWxpemVkIGJlaGluZCB0aGUgc3RlcCDigJQgZGVmZWF0aW5nIHdvcmtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSB3b3JrZmxvdyBleHByZXNzZWQgYXMgcGFyYWxsZWwgKGUuZy5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGBob29rLmdldENvbmZsaWN0KCkudGhlbigoKSA9PiBzdGVwQigpKWAgcmFjaW5nIGBhd2FpdFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gc3RlcEEoKWApLiBJbiB0aGF0IGNhc2UgYGxhenlJbmxpbmVTdGVwc2AgaXMgZW1wdHkgYW5kXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBldmVyeSBzdGVwIGlzIHF1ZXVlZCBmb3IgcmUtaW52b2NhdGlvbiwgd2hpY2ggcmVwbGF5c1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gb3ZlciB0aGUganVzdC1jb21taXR0ZWQgaG9va19jcmVhdGVkIGFuZCByZXNvbHZlcyB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGF3YWl0ZXIgd2hpbGUgcXVldWVkIHN0ZXBzIHJ1biBpbiBwYXJhbGxlbCBpbnZvY2F0aW9ucy5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGxhenlJbmxpbmVTdGVwcyA9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHN1c3BlbnNpb25SZXN1bHQubGF6eUlubGluZVN0ZXBzO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaW5saW5lQ29ycmVsYXRpb25JZHMgPSBuZXcgU2V0KFxuICAgICAgICAgICAgICAgICAgICAgICAgICBsYXp5SW5saW5lU3RlcHMubWFwKChzKSA9PiBzLmNvcnJlbGF0aW9uSWQpXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBVbmlmaWVkIHF1ZXVlIGRpc3BhdGNoIGZvciBldmVyeXRoaW5nIHdlIGFyZSBOT1RcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlubGluZS1leGVjdXRpbmcuIFN0ZXBzIGFyZSBxdWV1ZWQgd2l0aCBzdGVwSWQgc29cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSByZWNlaXZlciBydW5zIHRoZW07IHRoZSB3YWl0IHRpbWVyIGlzIHF1ZXVlZFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXMgYSBnZW5lcmljIGNvbnRpbnVhdGlvbiB0aGF0IGZpcmVzIGFmdGVyIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gd2FpdCBlbGFwc2VzIGFuZCBsZXRzIHRoZSBuZXh0IHJlcGxheSBvYnNlcnZlIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZWxhcHNlZCB3YWl0IHZpYSB0aGUgXCJjb21wbGV0ZSBlbGFwc2VkIHdhaXRzXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHBhc3MuXG4gICAgICAgICAgICAgICAgICAgICAgICAvL1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gU3RlcCBkaXNwYXRjaCBkZWNpc2lvbiB0YWJsZSAocGVyIHBlbmRpbmcgc3RlcCBub3RcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGRlc2lnbmF0ZWQgbGF6eS1pbmxpbmUpOlxuICAgICAgICAgICAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgLSBJbmxpbmUtb3duZWQsIG93bmVyID09PSB0aGlzIG1lc3NhZ2UgIOKGklxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgIGV4ZWN1dGUgaW4gVEhJUyBpbnZvY2F0aW9uIChvd25lZCByZWNvdmVyeTogYVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgIHJlZGVsaXZlcnkgb2YgdGhlIG93bmluZyBtZXNzYWdlIHJlLWV4ZWN1dGVzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAgdGhlIHN0ZXAgaXQgY3Jhc2hlZCBvbiwgdmlhIGEgcGF5bG9hZC1sZXNzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAgc3RlcF9zdGFydGVkIHJlLXN0YW1wZWQgd2l0aCBpdHNcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgICBvd25lck1lc3NhZ2VJZCDigJQgbm90IGEgYmFyZSBzdGFydCkuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgIC0gSW5saW5lLW93bmVkLCBvd25lciAhPT0gdGhpcyBtZXNzYWdlICDihpJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgICBlbnN1cmUgYSBERUxBWUVEIGJhY2tzdG9wIHdha2UgZXhpc3RzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAgKGRlbGF5U2Vjb25kcyA9IG93bmVyc2hpcCBsZWFzZSByZW1haW5pbmcpXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAgaW5zdGVhZCBvZiBlbnF1ZXVlaW5nIHRoZSBzdGVwLiBUaGUgb3duaW5nXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAgaW52b2NhdGlvbiBpcyAobGlrZWx5KSBzdGlsbCBydW5uaW5nIHRoZSBib2R5O1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgIGFuIGltbWVkaWF0ZSBzdGVwIG1lc3NhZ2Ugd291bGQgYmFyZS1zdGFydCB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgICBydW5uaW5nIHN0ZXAgYW5kIGV4ZWN1dGUgaXQgYSBzZWNvbmQgdGltZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgICh3b3JrZmxvdyMyNzgwKS4gVGhlIGJhY2tzdG9wIGlzIGEgcGxhaW4gcnVuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAgY29udGludWF0aW9uLCBOT1QgYSBzdGVwIG1lc3NhZ2U6IHdoZW4gaXRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgICBmaXJlcywgdGhpcyBzYW1lIGRlY2lzaW9uIHRhYmxlIGhhbmRsZXNcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgICB3aGF0ZXZlciBzdGF0ZSB0aGUgc3RlcCBpcyBpbiBieSB0aGVuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAgKHRlcm1pbmFsIOKGkiBub3RoaW5nIHBlbmRpbmc7IHF1ZXVlLW93bmVkIGFmdGVyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAgc3RlcF9yZXRyeWluZyDihpIgbm9ybWFsIGtleWVkIGRpc3BhdGNoOyBvd25lclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgIGRlYWQgd2l0aCBsZWFzZSBleHBpcmVkIOKGkiBpbW1lZGlhdGUgZGlzcGF0Y2gsXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAgcHJlc2VydmluZyBzdGVwLWxldmVsIGZhaWx1cmUgc2VtYW50aWNzIGZvclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgIHBvaXNvbiBzdGVwczsgbGVhc2UgcmVmcmVzaGVkIGJ5IG93bmVyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAgcmVjb3Zlcnkg4oaSIHJlLWFybSkuIFRoZSBiYWNrc3RvcCdzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAgaWRlbXBvdGVuY3lLZXkgaXMgc2NvcGVkIHRvIHRoZSBvd25lcnNoaXBcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgICBFUE9DSCAobGF0ZXN0IHN0ZXBfc3RhcnRlZCB0aW1lc3RhbXApLCBOT1RcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgICBqdXN0IHRoZSBjb3JyZWxhdGlvbiBJRCwgYW5kIG11c3QgbmV2ZXIgYmVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgICB0aGUgc3RlcCBtZXNzYWdlJ3Mgb3duIGtleSDigJQgc2VlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAgYmFja3N0b3BJZGVtcG90ZW5jeUtleSBmb3IgYm90aCBpbnZhcmlhbnRzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAgKGZpeGVkIGtleXMgZWl0aGVyIGFic29yYiB0aGUgcmV0cnkgaGFuZG9mZlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgIG9yIGRlZHVwZSB0aGUgcmVmcmVzaGVkLWxlYXNlIHJlLWFybSBhZ2FpbnN0XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAgdGhlIGluLWZsaWdodCBiYWNrc3RvcCBpdHNlbGYpLlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAtIE5vdCBvd25lZCAobmV2ZXIgc3RhbXBlZCAvIGVhZ2VyIC8gb3duZXJzaGlwXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAgbGFwc2VkIGF0IHN0ZXBfcmV0cnlpbmcgLyBsZWFzZSBleHBpcmVkIC9cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgICBraWxsLXN3aXRjaGVkKSDihpIgaW1tZWRpYXRlIGVucXVldWUsIGV4YWN0bHkgYXNcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgICBiZWZvcmUuIFRoaXMgY292ZXJzIGNyYXNoIHJlY292ZXJ5OiBpZiBhIHByaW9yXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAgaGFuZGxlciB3cm90ZSBzdGVwX2NyZWF0ZWQgYnV0IGNyYXNoZWQgYmVmb3JlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAgcXVldWVpbmcsIGEgbGF0ZXIgaGFuZGxlciBxdWV1ZXMgaXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAgaWRlbXBvdGVuY3lLZXkgb24gY29ycmVsYXRpb25JZCBkZWR1cGVzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAgcmVkdW5kYW50IHF1ZXVlcyBhY3Jvc3MgY29uY3VycmVudCBoYW5kbGVycy5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGUgd2FpdCBjb250aW51YXRpb24gaXMgd2hhdCBtYWtlc1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYFByb21pc2UucmFjZShzdGVwLCBzbGVlcClgIGJlaGF2ZSBjb3JyZWN0bHkgd2l0aFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW5saW5lIHN0ZXAgZXhlY3V0aW9uOiBldmVuIGlmIHRoZSBpbmxpbmUgc3RlcFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYmxvY2tzIHRoaXMgaGFuZGxlciBmb3IgdGhlIGZ1bGwgc3RlcCBkdXJhdGlvbixcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSB3YWl0IHRpbWVyIGZpcmVzIGluIGEgc2VwYXJhdGUgZnVuY3Rpb25cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGludm9jYXRpb24uIElmIHRoZSBzbGVlcCB3aW5zLCB0aGF0IHBhcmFsbGVsXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpbnZvY2F0aW9uIGNvbXBsZXRlcyB0aGUgcnVuOyBpZiB0aGUgc3RlcCB3aW5zLFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIHdhaXQgY29udGludWF0aW9uIGZpcmVzIGxhdGVyIGFuZCBuby1vcHMgb25cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSB0ZXJtaW5hbCBydW4uXG4gICAgICAgICAgICAgICAgICAgICAgICAvL1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhlIGNvbnRpbnVhdGlvbidzIGRlbGF5IGlzIGNsYW1wZWQgdG8gdGhlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBtYXhpbXVtIHF1ZXVlIGRlbGF5IChsb25nIHdhaXRzIGNoYWluIGFjcm9zc1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbXVsdGlwbGUgaG9wcykgYW5kIGl0cyBpZGVtcG90ZW5jeSBrZXkgZGVkdXBlc1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gcmUtb2JzZXJ2YXRpb25zIG9mIHRoZSBzYW1lIHBlbmRpbmcgd2FpdCBhY3Jvc3NcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHN1c3BlbnNpb24gcGFzc2VzIOKAlCBzZWVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHJ1bnRpbWUvd2FpdC1jb250aW51YXRpb24udHMgZm9yIHRoZSBmdWxsXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBkZWxheS9rZXkgc2VsZWN0aW9uIHJhdGlvbmFsZS5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRyYWNlQ2FycmllciA9IGF3YWl0IG5leHRUcmFjZUNhcnJpZXIoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRpc3BhdGNoZXM6IFByb21pc2U8dW5rbm93bj5bXSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaW5saW5lT3duZXJzaGlwID0gaXNJbmxpbmVPd25lcnNoaXBFbmFibGVkKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkaXNwYXRjaE5vd01zID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG93bmVkUmVjb3ZlcnlTdGVwczogU3RlcEludm9jYXRpb25RdWV1ZUl0ZW1bXSA9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGJhY2tzdG9wV2FrZXNBcm1lZCA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHN0ZXAgb2YgcGVuZGluZ1N0ZXBzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbmxpbmVDb3JyZWxhdGlvbklkcy5oYXMoc3RlcC5jb3JyZWxhdGlvbklkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG93bmVyc2hpcEFjdGl2ZSA9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5saW5lT3duZXJzaGlwICYmIGlzU3RlcE93bmVyc2hpcEFjdGl2ZShzdGVwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG93bmVyc2hpcEFjdGl2ZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXAub3duZXJNZXNzYWdlSWQgPT09IG1ldGFkYXRhLm1lc3NhZ2VJZFxuICAgICAgICAgICAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPd25lZCByZWNvdmVyeTogdGhpcyBkZWxpdmVyeSBJUyB0aGUgb3duaW5nXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbWVzc2FnZTsgcmUtZXhlY3V0ZSB0aGUgc3RlcCBpbiB0aGlzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW52b2NhdGlvbiBpbnN0ZWFkIG9mIHF1ZXVlaW5nIGl0LlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG93bmVkUmVjb3ZlcnlTdGVwcy5wdXNoKHN0ZXApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIERlbGF5ZWQgYmFja3N0b3Agd2FrZSB3aGlsZSBhbm90aGVyIGludm9jYXRpb24nc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBvd25lcnNoaXAgbGVhc2UgaXMgbGl2ZTsgaW1tZWRpYXRlIHN0ZXAgZW5xdWV1ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBvdGhlcndpc2UgKGxlYXNlIGV4cGlyZWQg4oeSIHJlbWFpbmluZyAwIOKHkiBzYW1lIGFzXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRvZGF5LCB3aGljaCBpcyBhbHNvIHRoZSBkZWdyYWRlZCBtb2RlIGZvclxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB3b3JsZHMgd2l0aCB1bnN0YWJsZSBtZXNzYWdlIElEcyDigJQgdGhlIG93bmVyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNoZWNrIGFib3ZlIG5ldmVyIG1hdGNoZXMgdGhlcmUpLlxuICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBiYWNrc3RvcERlbGF5U2Vjb25kcyA9IG93bmVyc2hpcEFjdGl2ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gc3RlcExlYXNlUmVtYWluaW5nU2Vjb25kcyhzdGVwLCBkaXNwYXRjaE5vd01zKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJhY2tzdG9wRGVsYXlTZWNvbmRzID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhY2tzdG9wV2FrZXNBcm1lZCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuZGVidWcoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnUGVuZGluZyBzdGVwIGlzIGlubGluZS1vd25lZCBieSBhIGxpdmUgaW52b2NhdGlvbjsgZW5zdXJpbmcgZGVsYXllZCBiYWNrc3RvcCB3YWtlIGluc3RlYWQgb2YgaW1tZWRpYXRlIHJlcXVldWUnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RlcElkOiBzdGVwLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG93bmVyTWVzc2FnZUlkOiBzdGVwLm93bmVyTWVzc2FnZUlkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiYWNrc3RvcERlbGF5U2Vjb25kcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3BhdGNoZXMucHVzaChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHF1ZXVlTWVzc2FnZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd29ybGQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldFdvcmtmbG93UXVldWVOYW1lKHdvcmtmbG93TmFtZSwgbmFtZXNwYWNlKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNlQ2FycmllcixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXF1ZXN0ZWRBdDogbmV3IERhdGUoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGF5U2Vjb25kczogYmFja3N0b3BEZWxheVNlY29uZHMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWRlbXBvdGVuY3lLZXk6IGJhY2tzdG9wSWRlbXBvdGVuY3lLZXkoc3RlcCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3BhdGNoZXMucHVzaChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBxdWV1ZU1lc3NhZ2UoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JsZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldFdvcmtmbG93UXVldWVOYW1lKHdvcmtmbG93TmFtZSwgbmFtZXNwYWNlKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXBJZDogc3RlcC5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGVwTmFtZTogc3RlcC5zdGVwTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhY2VDYXJyaWVyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXF1ZXN0ZWRBdDogbmV3IERhdGUoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkZW1wb3RlbmN5S2V5OiBzdGVwLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN1c3BlbnNpb25SZXN1bHQud2FpdFRpbWVvdXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzcGF0Y2hlcy5wdXNoKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHF1ZXVlTWVzc2FnZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmxkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0V29ya2Zsb3dRdWV1ZU5hbWUod29ya2Zsb3dOYW1lLCBuYW1lc3BhY2UpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhY2VDYXJyaWVyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXF1ZXN0ZWRBdDogbmV3IERhdGUoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRXYWl0Q29udGludWF0aW9uRGlzcGF0Y2goXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1c3BlbnNpb25SZXN1bHQud2FpdFRpbWVvdXQuc2Vjb25kcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VzcGVuc2lvblJlc3VsdC53YWl0VGltZW91dC5jb3JyZWxhdGlvbklkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoZGlzcGF0Y2hlcyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZSBzZXQgb2Ygc3RlcHMgVEhJUyBpbnZvY2F0aW9uIGV4ZWN1dGVzOiB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGRlZmVycmVkIGxhenktaW5saW5lIGJhdGNoIHBsdXMgYW55IG93bmVkLXJlY292ZXJ5XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBzdGVwcyAodGhpcyBtZXNzYWdlJ3MgcmVkZWxpdmVyeSByZS1leGVjdXRpbmcgYVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gc3RlcCBpdCBjcmFzaGVkIG9uIOKAlCBubyBsYXp5U3RlcElucHV0OyB0aGUgaW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGh5ZHJhdGVzIGZyb20gdGhlIHN0ZXAgZW50aXR5IGxpa2UgdGhlIGJhY2tncm91bmRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHBhdGgsIGFuZCB0aGUgcGF5bG9hZC1sZXNzIHN0ZXBfc3RhcnRlZCByZS1zdGFtcHNcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG93bmVyc2hpcCDigJQgdW5saWtlIHRoZSBiYWNrZ3JvdW5kIHBhdGgncyBzdGFydCBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXMgTk9UIGJhcmU6IGl0IGNhcnJpZXMgdGhpcyBtZXNzYWdlJ3NcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG93bmVyTWVzc2FnZUlkLCB3aGljaCBpcyBhbHNvIHdoYXQgdGhlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBvd25lZC1yZWNvdmVyeSByZXRyeSBjZWlsaW5nIGNvdW50cykuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBpbmxpbmVFeGVjdXRpb25zOiBBcnJheTx7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHN0cmluZztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgc3RlcE5hbWU6IHN0cmluZztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgbGF6eVN0ZXBJbnB1dD86ICh0eXBlb2YgbGF6eUlubGluZVN0ZXBzKVtudW1iZXJdWydkZWh5ZHJhdGVkSW5wdXQnXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0+ID0gW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5sYXp5SW5saW5lU3RlcHMubWFwKChzKSA9PiAoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHMuY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGVwTmFtZTogcy5zdGVwTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXp5U3RlcElucHV0OiBzLmRlaHlkcmF0ZWRJbnB1dCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfSkpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5vd25lZFJlY292ZXJ5U3RlcHMubWFwKChzKSA9PiAoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHMuY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGVwTmFtZTogcy5zdGVwTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfSkpLFxuICAgICAgICAgICAgICAgICAgICAgICAgXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE93bmVyc2hpcCB0ZWxlbWV0cnkgKGRlc2lnbiBkb2MgUGhhc2UgNyk6IHNwYW5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGF0dHJpYnV0ZXMgc28gcHJvZHVjdGlvbiB0cmFjZXMgc2hvdyB3aGVuIGNyYXNoXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyByZWNvdmVyeSByYW4gb3IgYSB3YWtlIHdhcyBjb252ZXJ0ZWQgaW50byBhXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBiYWNrc3RvcCwgYW5kIGEgd2FybiAoYWx3YXlzIHByaW50ZWQsIHVubGlrZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZGVidWcvaW5mbykgZm9yIG93bmVkIHJlY292ZXJ5IOKAlCBpdCBtZWFucyBhIHByaW9yXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBkZWxpdmVyeSBvZiB0aGlzIG1lc3NhZ2UgZGllZCBtaWQtc3RlcC1ib2R5LlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICBiYWNrc3RvcFdha2VzQXJtZWQgPiAwIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgIG93bmVkUmVjb3ZlcnlTdGVwcy5sZW5ndGggPiAwXG4gICAgICAgICAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uKG93bmVkUmVjb3ZlcnlTdGVwcy5sZW5ndGggPiAwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IEF0dHJpYnV0ZS5Xb3JrZmxvd093bmVkUmVjb3ZlcnlTdGVwcyhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvd25lZFJlY292ZXJ5U3RlcHMubGVuZ3RoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDoge30pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLihiYWNrc3RvcFdha2VzQXJtZWQgPiAwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IEF0dHJpYnV0ZS5Xb3JrZmxvd0JhY2tzdG9wV2FrZXNBcm1lZChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiYWNrc3RvcFdha2VzQXJtZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiB7fSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG93bmVkUmVjb3ZlcnlTdGVwcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIud2FybihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnUmUtZXhlY3V0aW5nIGlubGluZSBzdGVwcyBvd25lZCBieSB0aGlzIHF1ZXVlIG1lc3NhZ2Ug4oCUIGEgcHJldmlvdXMgZGVsaXZlcnkgY3Jhc2hlZCBtaWQtYm9keSBhbmQgdGhpcyByZWRlbGl2ZXJ5IGlzIHJlY292ZXJpbmcgdGhlbScsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGVwSWRzOiBvd25lZFJlY292ZXJ5U3RlcHMubWFwKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAocykgPT4gcy5jb3JyZWxhdGlvbklkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gTm90aGluZyB0byBleGVjdXRlIGlubGluZSDigJQgZXZlcnl0aGluZyBoYXMgYmVlblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gcXVldWVkIChvciBubyB3b3JrIG5lZWRzIHNjaGVkdWxpbmcpLiBFeGl0IGFuZCBsZXRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBxdWV1ZSBkcml2ZSBzdWJzZXF1ZW50IHJlcGxheXMuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW5saW5lRXhlY3V0aW9ucy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQSBgaG9vay5nZXRDb25mbGljdCgpYCBhd2FpdGVyIG5lZWRzIGFuIGltbWVkaWF0ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyByZS1pbnZvY2F0aW9uOiB0aGUgcmVwbGF5IGNvbnN1bWVzIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBqdXN0LWNvbW1pdHRlZCBob29rX2NyZWF0ZWQgYW5kIHJlc29sdmVzIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhd2FpdGVyLiBXaXRob3V0IGl0IChubyBpbmxpbmUgc3RlcCwgYWxsIHdvcmtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gcXVldWVkIG9yIG5vbmUgcGVuZGluZykgdGhlIHJ1biB3b3VsZCBzaXQgaWRsZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB1bnRpbCBzb21lIHVucmVsYXRlZCBtZXNzYWdlIHdva2UgaXQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdXNwZW5zaW9uUmVzdWx0Lmhhc0F3YWl0ZWRIb29rQ3JlYXRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYXdhaXQgcmVpbnZva2UoMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBPcGVuIGhvb2tzL3dhaXRzIGFyZSBjb25zdWx0ZWQgYnkgYWxsIHRocmVlIGdhdGVzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBiZWxvdzsgcmVzb2x2ZSB0aGUgbWVtb2l6ZWQgc2NhbiBvbmNlIGhlcmUuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBvcGVuSG9va1dhaXRTdGF0ZSA9IG9wZW5Ib29rV2FpdC52YWx1ZTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSW5saW5lLWRlbHRhIGZhc3QgcGF0aCBnYXRlLiBXZSByZXF1ZXN0IHRoZSBkZWx0YSDigJRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFuZCBvbiB0aGUgbmV4dCBpdGVyYXRpb24gY29uc3VtZSBpdCBpbiBwbGFjZSBvZiB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGV2ZW50cy5saXN0IOKAlCBvbmx5IHdoZW4gQUxMIGhvbGQ6XG4gICAgICAgICAgICAgICAgICAgICAgICAvL1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gIC0gV2UgaGF2ZSBhIHJlYWwgcHJpb3IgY3Vyc29yIHRvIGRpZmYgYWdhaW5zdCAoYVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgV29ybGQgbWF5IHJldHVybiBub25lIG9uIHRoZSBpbml0aWFsIGxvYWQpLlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gIC0gVGhpcyBpcyB0aGUgY2xlYW4gc2luZ2xlLXN0ZXAgc2VxdWVudGlhbCBjYXNlOlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgdGhpcyBzdXNwZW5zaW9uIHByb2R1Y2VkIGV4YWN0bHkgb25lIHN0ZXAgYW5kIG5vXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICB3YWl0cyAoYGVyci57c3RlcCx3YWl0fUNvdW50YCksIHRoYXQgb25lIHN0ZXAgaXNcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgIHRoZSBsb25lIHBlbmRpbmcgc3RlcCAoYHBlbmRpbmdTdGVwcy5sZW5ndGggPT09IDFgKVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgYW5kIHRoZSBsb25lIGlubGluZSBzdGVwXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAoYGxhenlJbmxpbmVTdGVwcy5sZW5ndGggPT09IDFgIOKAlCBubyBwYXJhbGxlbFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgc2libGluZ3MgcXVldWVkIHRvIGJhY2tncm91bmQgaGFuZGxlcnMsIGFuZCBubyBvdGhlclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgaW5saW5lIHN0ZXAgd3JpdGluZyBpdHMgb3duIGV2ZW50cyBvdXQgb2YgYmFuZCkuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgLSBObyBwZW5kaW5nIHdhaXQgdGltZXIgZnJvbSBUSElTIHN1c3BlbnNpb24sIGFuZCBub1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgb3BlbiB3YWl0IGluIHRoZSBjdW11bGF0aXZlIGxvZzogYSBjb25jdXJyZW50XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICBgd2FpdF9jb21wbGV0ZWRgIGxhbmRpbmcgYWZ0ZXIgdGhlIGRlbHRhIHNuYXBzaG90XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICBkb2VzIG5vdCBidW1wIHRoZSBvdXRzaWRlLWV2ZW50IG1hcmtlciwgc28gbm90aGluZ1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgZmVuY2VzIGEgcmVwbGF5IGZyb20gdGhlIHN0YWxlIGRlbHRhLlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gIC0gTm8gb3BlbiAob3IgdGhpcy1zdXNwZW5zaW9uLWNyZWF0ZWQpIGhvb2sg4oCUIFVOTEVTU1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgdGhlIHByZWNvbmRpdGlvbiBndWFyZCBpcyBlbmFibGVkIEFORCB0aGUgV29ybGRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgIGRlY2xhcmVzIGl0IGFjdHVhbGx5IGVuZm9yY2VzIHRoZSBndWFyZFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgKGBjYXBhYmlsaXRpZXMucHJlY29uZGl0aW9uR3VhcmRgOyB0aGUgZW52IGZsYWdcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgIGFsb25lIG9ubHkgbWFrZXMgdGhlIHJ1bnRpbWUgU0VORCBzbmFwc2hvdHMsIHdoaWNoXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICBhbiB1bnN1cHBvcnRpbmcgYmFja2VuZCBpZ25vcmVzIOKAlCBubyBmZW5jZSkuIFRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgZGVsdGEgc25hcHNob3RzIHRoZSBsb2cgYXQgdGhlIHN0ZXBfY29tcGxldGVkXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICB3cml0ZSBidXQgaXMgY29uc3VtZWQgb24gdGhlIG5leHQgcmVwbGF5LCBzbyBhblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgb3V0LW9mLWJhbmQgYGhvb2tfcmVjZWl2ZWRgIGxhbmRpbmcgaW4gdGhhdCB3aW5kb3dcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgIGlzIGFic2VudCBmcm9tIHRoZSBkZWx0YSBhbmQgb2JzZXJ2ZWQgb25lXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICBpdGVyYXRpb24gbGF0ZXIgdGhhbiBhIHJlYWwgZmV0Y2ggd291bGQgb2JzZXJ2ZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgaXQuIFRoYXQgc3RhbGVuZXNzIGlzIHF1YWxpdGF0aXZlbHkgdGhlIHNhbWVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgIHJlYWQtdG8td3JpdGUgcmFjZSB0aGUgZmV0Y2ggcGF0aCBhbHJlYWR5IGhhcyAoYW5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgIGV2ZW50IGNhbiBsYW5kIHJpZ2h0IGFmdGVyIGBldmVudHMubGlzdGAgcmV0dXJuc1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgYW5kIGJlZm9yZSB0aGUgc3VzcGVuc2lvbidzIHdyaXRlcyk7IHdpdGggYW5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgIGVuZm9yY2VkIGd1YXJkIGl0IGlzIGFsc28gZmVuY2VkOiBgaG9va19yZWNlaXZlZGBcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgIGJ1bXBzIHRoZSBwZXItcnVuIG91dHNpZGUtZXZlbnQgbWFya2VyLCBzbyBldmVyeVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgZHVyYWJsZSB3cml0ZSB0aGUgc3RhbGUgcmVwbGF5IGF0dGVtcHRzIGlzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICByZWplY3RlZCB3aXRoIDQxMiDigJQgaXRzIGd1YXJkZWQgc3VzcGVuc2lvbiBjcmVhdGVzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAocmV0cmllZCBvdmVyIHRoZSByZWxvYWRlZCBsb2csIG9yIGV4aGF1c3RlZCBpbnRvXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICBhIHF1ZXVlIHJlLWludm9jYXRpb24pLCBBTkQgdGhlIGxhenkgc3RlcF9zdGFydGVkXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICBjbGFpbSBvZiBpdHMgbmV4dCBpbmxpbmUgc3RlcCwgd2hpY2ggY2FycmllcyB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgIHNuYXBzaG90IHRvbyAodGhyZWFkZWQgYmVsb3cgdmlhXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICBgc3RhdGVVcGRhdGVkQXRgOyBvbiByZWplY3Rpb24gdGhlIGJhdGNoIGlzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICBhYmFuZG9uZWQgYW5kIHJlLWludm9rZWQgZm9yIGEgZnJlc2ggcmVwbGF5LCBzbyBhXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICBzdGFsZSB2aWV3IGNhbiBuZXZlciBjb21taXQgYSBzdGVwKS4gSG9va3MgY3JlYXRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgYnkgVEhJUyBzdXNwZW5zaW9uIGFyZSBpbnNpZGUgdGhlIGRlbHRhICh0aGVpclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgYGhvb2tfY3JlYXRlZGAgbGFuZHMgYmVmb3JlIHRoZSBzdGVwLXRlcm1pbmFsXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICB3cml0ZSksIHNvIG9ubHkgdGhlaXIgYGhvb2tfcmVjZWl2ZWRgIHJlc3BvbnNlc1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgYXJlIHN1YmplY3QgdG8gdGhlIHNhbWUgZmVuY2VkIHdpbmRvdy4gV2l0aG91dCBhblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgZW5mb3JjZWQgZ3VhcmQgdGhlcmUgaXMgbm8gZmVuY2UsIHNvIGtlZXAgdGhlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICBjb25zZXJ2YXRpdmUgZ2F0ZS5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICAtIFdpdGggbm8gaG9vayBvciB3YWl0IG9wZW4gYXQgYWxsLCB0aGUgb25seVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgb3V0LW9mLWJhbmQgd3JpdGVyIGlzIGNhbmNlbGxhdGlvbiwgd2hpY2ggaXMgc2FmZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgdG8gb2JzZXJ2ZSBvbmUgaXRlcmF0aW9uIGxhdGUuIFNlZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgb3Blbkhvb2tBbmRXYWl0U3RhdGUuXG4gICAgICAgICAgICAgICAgICAgICAgICAvL1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2hlbiBtb3JlIHRoYW4gb25lIHN0ZXAgcnVucyBpbmxpbmUsIGVhY2ggd3JpdGVzIGl0c1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gb3duIGV2ZW50cyBhbmQgdGhlIHBlci13cml0ZSBkZWx0YSB3b3VsZCBiZSBwYXJ0aWFsLCBzb1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIGRlbHRhIGlzIG5vdCByZXF1ZXN0ZWQgKHRoZSBnYXRlIGJlbG93IGlzIGZhbHNlIGZvclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbXVsdGktc3RlcCkgYW5kIHRoZSBuZXh0IGl0ZXJhdGlvbiBkb2VzIGEgbm9ybWFsIGZldGNoLlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2hldGhlciB0aGUgcHJlY29uZGl0aW9uIGd1YXJkIGlzIGFjdHVhbGx5IGluIGZvcmNlOlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZW5hYmxlZCBieSBlbnYgQU5EIGVuZm9yY2VkIGJ5IHRoZSBXb3JsZC4gVGhlIGVudlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZmxhZyBhbG9uZSBvbmx5IG1ha2VzIHRoZSBydW50aW1lIHNlbmQgc25hcHNob3RzLFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gd2hpY2ggYW4gdW5zdXBwb3J0aW5nIGJhY2tlbmQgaWdub3JlcyAobm8gZmVuY2UpLlxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZ3VhcmRFbmZvcmNlZCA9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGlzUHJlY29uZGl0aW9uR3VhcmRFbmFibGVkKCkgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgd29ybGQuY2FwYWJpbGl0aWVzPy5wcmVjb25kaXRpb25HdWFyZCA9PT0gdHJ1ZTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVxdWVzdElubGluZURlbHRhID1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZW9mIGV2ZW50TG9nLmN1cnNvciA9PT0gJ3N0cmluZycgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyLnN0ZXBDb3VudCA9PT0gMSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICBlcnIud2FpdENvdW50ID09PSAwICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHBlbmRpbmdTdGVwcy5sZW5ndGggPT09IDEgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgbGF6eUlubGluZVN0ZXBzLmxlbmd0aCA9PT0gMSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICBvd25lZFJlY292ZXJ5U3RlcHMubGVuZ3RoID09PSAwICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICFzdXNwZW5zaW9uUmVzdWx0LndhaXRUaW1lb3V0ICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICFvcGVuSG9va1dhaXRTdGF0ZS5vcGVuV2FpdCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAoZ3VhcmRFbmZvcmNlZCB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChlcnIuaG9va0NvdW50ID09PSAwICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAhb3Blbkhvb2tXYWl0U3RhdGUub3Blbkhvb2spKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gU3RhbGUtc2Vuc2l0aXZlIGJhdGNoOiBhIGhvb2sgaXMgb3BlbiBpbiB0aGUgcnVuIChvclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gd2FzIGNyZWF0ZWQgYnkgdGhpcyBzdXNwZW5zaW9uLCBzbyBpdHMgaG9va19yZWNlaXZlZFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gY2FuIGxhbmQgYW55IG1vbWVudCkg4oCUIGFuIG91dC1vZi1iYW5kIGV2ZW50IGNhbiBtYWtlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgdmlldyB0aGlzIGJhdGNoIHdhcyBzY2hlZHVsZWQgZnJvbSBzdGFsZS4gV2l0aFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIGd1YXJkIGluIGZvcmNlLCB0aGUgZmVuY2UgcmVqZWN0cyBhIHN0YWxlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBjbGFpbSdzIGR1cmFibGUgd3JpdGVzIOKAlCBidXQgaXQgY2Fubm90IHVuLXJ1biBhIHN0ZXBcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJPRFkgdGhhdCBvcHRpbWlzdGljIHN0YXJ0IGJlZ2FuIGJlZm9yZSB0aGUgY2xhaW1cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNldHRsZWQuIFN1cHByZXNzIG9wdGltaXN0aWMgc3RhcnQgZm9yIHRoZXNlIGJhdGNoZXNcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICh0YWtlIGF3YWl0LXRoZW4tcnVuKSBzbyBhIDQxMi1mZW5jZWQgc3RlcCBuZXZlclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZXhlY3V0ZXMgdXNlciBjb2RlIGF0IGFsbDogdGhlIGZlbmNlIHRoZW4gY292ZXJzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBzaWRlIGVmZmVjdHMsIG5vdCBqdXN0IHRoZSBldmVudCBsb2cuIENvc3RzIG9uZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gY2xhaW0gcm91bmQtdHJpcCBwZXIgc3RlcCB3aGlsZSBhIGhvb2sgaXMgb3Blbiwgb25seVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gb24gZ3VhcmQtZW5mb3JjaW5nIGRlcGxveW1lbnRzLiBXaXRob3V0IHRoZSBndWFyZFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbm90aGluZyA0MTJzLCBzbyBzdXBwcmVzc2lvbiB3b3VsZCBidXkgbm90aGluZyDigJRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHN0YWxlLXZpZXcgZXhwb3N1cmUgdGhlcmUgaXMgdGhlIHByZS1leGlzdGluZ1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gb3B0aW1pc3RpYy1zdGFydCBjb250cmFjdCAoaWRlbXBvdGVudCBzaWRlIGVmZmVjdHMpLlxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3VwcHJlc3NPcHRpbWlzdGljU3RhcnQgPVxuICAgICAgICAgICAgICAgICAgICAgICAgICBndWFyZEVuZm9yY2VkICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgIChvcGVuSG9va1dhaXRTdGF0ZS5vcGVuSG9vayB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVyci5ob29rQ291bnQgPiAwIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VzcGVuc2lvblJlc3VsdC5oYXNIb29rRXZlbnRzKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVHVyYm8gbW9kZSBmb3JjZXMgb3B0aW1pc3RpYyBpbmxpbmUgc3RhcnQgZm9yIHRoaXNcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGJhdGNoIOKAlCBidXQgb25seSB3aGlsZSB0aGUgcnVuIGlzIHN0aWxsIFwiY2xlYW5cIiAoYSBwdXJlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBzdGVwIHN1c3BlbnNpb24pLiBUaGUgbW9tZW50IGEgaG9vayBvciB3YWl0IGlzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBjcmVhdGVkLCBsYXRlciByZXN1bWUvcGFyYWxsZWwgaW52b2NhdGlvbnMgYmVjb21lXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBwb3NzaWJsZSwgc28gdGhlIHNpbmdsZS1oYW5kbGVyIGd1YXJhbnRlZSB0aGF0IG1ha2VzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBmb3JjZWQgb3B0aW1pc3RpYyBzdGFydCBzYWZlIG5vIGxvbmdlciBob2xkcyDigJQgdHVyYm9cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGV4aXRzIGFuZCB0aGUgc3RlcHMgdGFrZSB0aGUgbm9ybWFsIChlbnYtZ2F0ZWQpXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhd2FpdC10aGVuLXJ1biBwYXRoLiBUaGUgaG9vay1jb25mbGljdCBjYXNlIGFscmVhZHlcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHJldHVybmVkIGVhcmx5IGFib3ZlLCB0aGUgYXR0ciBjYXNlIGNvbnRpbnVlZCBpbnRvIGFcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGZyZXNoIHJlcGxheSAoc28gYSBiYXRjaC1zY2hlZHVsaW5nIHN1c3BlbnNpb24gbmV2ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNhcnJpZXMgYXR0ciBldmVudHMpLCBhbmQgdGhlIGF3YWl0ZWQtaG9vayBjYXNlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBlbXB0aWVkIGxhenlJbmxpbmVTdGVwczsgdGhlIGNoZWNrcyBiZWxvdyBhcmVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGRlZmVuc2l2ZS5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGUgYHN1c3BlbnNpb25SZXN1bHQuKmAgZmxhZ3Mgb25seSByZWZsZWN0IHdoYXQgVEhJU1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYmF0Y2ggY3JlYXRlZCwgc28gdGhleSBkbyBub3QgY2F0Y2ggYSBob29rL3dhaXQgb3BlbmVkXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpbiBhbiBlYXJsaWVyIGl0ZXJhdGlvbiBvZiB0aGUgc2FtZSBkZWxpdmVyeSAoZS5nLiBhXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBmaXJlLWFuZC1mb3JnZXQgYGNyZWF0ZUhvb2soLi4uKWAgdGhhdCBkb2Vzbid0IGJsb2NrIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gd29ya2Zsb3csIGxldHRpbmcgdGhlIHJlcGxheSBsb29wIGNvbnRpbnVlIHRvIGxhdGVyIHB1cmVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHN0ZXAgc3VzcGVuc2lvbnMpLiBPbmNlIGFueSBob29rIG9yIHdhaXQgaXMgb3BlbiBpbiB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGN1bXVsYXRpdmUgbG9nLCByZXN1bWUvcGFyYWxsZWwgaW52b2NhdGlvbnMgYXJlIHBvc3NpYmxlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBmb3IgdGhlIHJlc3Qgb2YgdGhlIHJ1biwgc28gdHVyYm8gbXVzdCBsYXRjaCBvZmZcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHBlcm1hbmVudGx5IOKAlCBjaGVja2VkIGhlcmUgdmlhIGBvcGVuSG9va0FuZFdhaXRTdGF0ZWBcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG92ZXIgdGhlIGN1bXVsYXRpdmUgZXZlbnQgbG9nLlxuICAgICAgICAgICAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE5PVEU6IGBXT1JLRkxPV19TRVFVRU5USUFMX1JFUExBWVM9MWAgKHBlci1ydW4gZmxvd1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdG9waWNzIGNvbnN1bWVkIHdpdGggYG1heENvbmN1cnJlbmN5OiAxYCkgd291bGQgaW5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHByaW5jaXBsZSB3YWl2ZSB0aGlzIGxhdGNoIOKAlCBzZXJpYWxpemVkIG9yY2hlc3RyYXRvclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW52b2NhdGlvbnMgcmVzdG9yZSB0aGUgc2luZ2xlLWhhbmRsZXIgZ3VhcmFudGVlIGZvclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIHdob2xlIGRlbGl2ZXJ5LiBUaGUgd2FpdmVyIGlzIGludGVudGlvbmFsbHkgTk9UXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB0YWtlbjogdGhlIGVudiB2YXIgaXMgYSBydW50aW1lLXByb2Nlc3Mgc2V0dGluZyB0aGF0XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBjYW5ub3QgcHJvdmUgdGhlIEJVSUxUIGZsb3cgdHJpZ2dlciBhY3R1YWxseSBjYXJyaWVzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBgbWF4Q29uY3VycmVuY3k6IDFgIChpdCBtdXN0IGJlIHNldCBhdCBidWlsZCB0aW1lXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB0b28sIGFuZCBzb21lIGludGVncmF0aW9ucyB3cml0ZSB0aGVpciBvd24gdHJpZ2dlclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gY29uZmlnKSwgYW5kIGBjYXBhYmlsaXRpZXMubWF4Q29uY3VycmVuY3lgIG9ubHlcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGRlY2xhcmVzIHF1ZXVlIHN1cHBvcnQsIG5vdCBkZXBsb3llZCBjb25maWd1cmF0aW9uLlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVW50aWwgdGhlIGJ1aWxkIGVtaXRzIGEgdmVyaWZpYWJsZSBzaWduYWwgdGhhdCB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGRlcGxveWVkIHRyaWdnZXIgaXMgc2VyaWFsaXplZCwgdGhlIGNvbnNlcnZhdGl2ZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbGF0Y2ggc3RheXMuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmb3JjZU9wdGltaXN0aWNTdGFydCA9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHR1cmJvICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICFzdXNwZW5zaW9uUmVzdWx0Lmhhc0F0dHJpYnV0ZUV2ZW50cyAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAhc3VzcGVuc2lvblJlc3VsdC53YWl0VGltZW91dCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAhc3VzcGVuc2lvblJlc3VsdC5oYXNIb29rRXZlbnRzICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICFzdXNwZW5zaW9uUmVzdWx0Lmhhc0F3YWl0ZWRIb29rQ3JlYXRpb24gJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIW9wZW5Ib29rV2FpdFN0YXRlLm9wZW5Ib29rICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICFvcGVuSG9va1dhaXRTdGF0ZS5vcGVuV2FpdDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRXhlY3V0ZSB0aGUgaW5saW5lIHN0ZXBzIGluIHBhcmFsbGVsLiBUaGUgcmVwbGF5XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBidWRnZXQgaXMgcGF1c2VkIGZvciB0aGUgd2hvbGUgYmF0Y2gg4oCUIHN0ZXAgZHVyYXRpb24gaXNcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGJvdW5kZWQgYnkgdGhlIHBsYXRmb3JtJ3MgZnVuY3Rpb24gbWF4RHVyYXRpb24sIG5vdCB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHJlcGxheSB0aW1lb3V0IOKAlCBzbyB0aGUgYnVkZ2V0IGNoZWNrIGF0IHRoZSB0b3Agb2YgdGhlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBuZXh0IGxvb3AgaXRlcmF0aW9uIGRvZXNuJ3QgY2hhcmdlIHRoZSBzdGVwIGJvZGllcy5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIExhdGVuY3kgdGVsZW1ldHJ5OiBkZWNpZGUgd2hldGhlciB0aGlzIGJhdGNoJ3MgZmlyc3RcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHN0ZXAgcXVhbGlmaWVzIGZvciBUVEZTL1NUU08gbWVhc3VyZW1lbnQuIE9ubHkgdGhlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBiYXRjaCdzIGZpcnN0IHN0ZXAgY2FycmllcyB0aGUgdHJhY2tpbmcgc28gYVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gcGFyYWxsZWwgYmF0Y2ggZW1pdHMgb25lIHNhbXBsZSBwZXIgc2NoZWR1bGluZyBnYXAsXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBub3Qgb25lIHBlciBzaWJsaW5nLiBUdXJibydzIHN5bnRoZXNpemVkIHJ1blxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gc25hcHNob3QgaGFzIGEgbG9jYWwtY2xvY2sgY3JlYXRlZEF0LCBzbyB1bmRlclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdHVyYm8gb25seSB0aGUgcnVuLWlkIFVMSUQgdGltZXN0YW1wIGlzIHRydXN0ZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBsYXRlbmN5VHJhY2tpbmcgPSBjb21wdXRlU3RlcExhdGVuY3lUcmFja2luZyh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50czogZXZlbnRMb2cuZXZlbnRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBpbnZvY2F0aW9uU3RhcnRlZENsZWFuOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludm9jYXRpb25TdGFydGVkQ2xlYW4gPT09IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJ1bkNyZWF0ZWRBdE1zOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJ1bklkQ3JlYXRlZEF0KHJ1bklkKSA/P1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICh0dXJibyA/IHVuZGVmaW5lZCA6ICt3b3JrZmxvd1J1bi5jcmVhdGVkQXQpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBydW5TdGFydGVkUmVjZWl2ZWRBdE1zLFxuICAgICAgICAgICAgICAgICAgICAgICAgICByZXBsYXlNczogcmVwbGF5RHVyYXRpb25NcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlU3RlcEJsb2NraW5nTXMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHByZVN0ZXBCbG9ja2luZ0JlZm9yZUF0dHJNcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyBzdXNwZW5zaW9uJ3Mgb3duIGhvb2svd2FpdCB3cml0ZXMgYXJlIG5vdCBpblxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgbG9hZGVkIGV2ZW50IGxvZyB5ZXQsIHNvIHJlcG9ydCB0aGVtIGV4cGxpY2l0bHkuXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHN1c3BlbnNpb25IYXNXYWl0czpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnIud2FpdENvdW50ID4gMCB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1c3BlbnNpb25SZXN1bHQud2FpdFRpbWVvdXQgIT09IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgc3VzcGVuc2lvbkNyZWF0ZWRIb29rczpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnIuaG9va0NvdW50ID4gMCB8fCBzdXNwZW5zaW9uUmVzdWx0Lmhhc0hvb2tFdmVudHMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHR1cmJvLFxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFByZWNvbmRpdGlvbi1ndWFyZCBzbmFwc2hvdCBmb3IgdGhlIGlubGluZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gc3RlcF9zdGFydGVkIGNsYWltczogdGhlIGxhenkgY2xhaW0gaXMgdGhlIGZpcnN0XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBkdXJhYmxlIHdyaXRlIG9mIGEgaG90LXBhdGggc3RlcCAoaXRzIHN0ZXBfY3JlYXRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXMgZGVmZXJyZWQpLCBzbyB3aXRob3V0IGEgc25hcHNob3QgaXQgd291bGQgYnlwYXNzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgZ3VhcmQgZW50aXJlbHkgYW5kIGEgc3RhbGUgcmVwbGF5IGNvdWxkIGNsYWltIOKAlFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYW5kIGNvbW1pdCDigJQgYSBzdGVwIHNjaGVkdWxlZCBvZmYgYSB2aWV3IHRoYXQgbWlzc2VzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhbiBldmVudCBpdCBuZXZlciBsb2FkZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBgcHJlY29uZGl0aW9uU25hcHNob3RQYXJhbXNgIHJldHVybnMgYW4gZW1wdHkgb2JqZWN0XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB3aGVuIHRoZSBndWFyZCBlbnYgZmxhZyBpcyBvZmYsIHNvIHRoaXMgaXMgYSBuby1vcFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gb3V0c2lkZSBndWFyZGVkIGRlcGxveW1lbnRzOyBXb3JsZHMgdGhhdCBkb24ndFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZW5mb3JjZSB0aGUgZ3VhcmQgaWdub3JlIGl0LlxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaW5saW5lQ2xhaW1TbmFwc2hvdCA9IHByZWNvbmRpdGlvblNuYXBzaG90UGFyYW1zKFxuICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudExvZy5ldmVudHMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50TG9nLmN1cnNvclxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgcmVwbGF5QnVkZ2V0LnBhdXNlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgc3RlcFJlc3VsdHM6IEF3YWl0ZWQ8XG4gICAgICAgICAgICAgICAgICAgICAgICAgIFJldHVyblR5cGU8dHlwZW9mIGV4ZWN1dGVTdGVwPlxuICAgICAgICAgICAgICAgICAgICAgICAgPltdO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RlcEV4ZWN1dGlvblByb21pc2VzID0gaW5saW5lRXhlY3V0aW9ucy5tYXAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgIChzLCBzdGVwSW5kZXgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBydW4gPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3NlcnQoZXZlbnRMb2cudHlwZSA9PT0gJ3JlYWR5Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZXhlY3V0ZVN0ZXAoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JsZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93RGVwbG95bWVudElkOiB3b3JrZmxvd1J1bi5kZXBsb3ltZW50SWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93TmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dTdGFydGVkQXQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3RSdW5JZDogcm9vdFJ1bklkRnJvbShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bi5hdHRyaWJ1dGVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJ1bklkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXBJZDogcy5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGVwTmFtZTogcy5zdGVwTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcnVuU3BlY1ZlcnNpb246IHdvcmtmbG93UnVuLnNwZWNWZXJzaW9uLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBdHRlbXB0IG51bWJlciA9IHByaW9yIHN0ZXBfc3RhcnRlZCBjb3VudCArIDFcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gKHRoaXMgZXhlY3V0aW9uJ3Mgc3RhcnQpLCBjb3VudGluZyBvbmx5IFRISVNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbWVzc2FnZSdzIG93biBzdGFydHM6IHRoZSBvd25lZC1yZWNvdmVyeVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBjZWlsaW5nIGJvdW5kcyBob3cgbWFueSB0aW1lcyB0aGlzIG93bmluZ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBtZXNzYWdlIHJlLXJ1bnMgYSBzdGVwIGl0IGNyYXNoZWQvdGltZWQgb3V0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG9uLCBhbmQgZWFjaCBvZiB0aG9zZSAocmUpc3RhcnRzIHN0YW1wc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBtZXRhZGF0YS5tZXNzYWdlSWQuIFN0YXJ0cyB3cml0dGVuIGJ5IHJhY2luZ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpbnZvY2F0aW9ucyAoc3RhbGUvd2FrZSByZXBsYXlzLCBhIHN0ZXBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbWVzc2FnZSBkaXNwYXRjaGVkIG9mZiBhIGxvc3QgY3JlYXRlLWNsYWltKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBjYXJyeSBvdGhlciBJRHMg4oCUIG9yIG5vbmUg4oCUIGFuZCBtdXN0IG5vdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBjb3VudCwgb3IgdGhlIGNlaWxpbmcgZmFsc2VseSBleGhhdXN0cyBhXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGhlYWx0aHkgc3RlcCAoc2VlIGNvdW50U3RlcFN0YXJ0ZWRFdmVudHMpLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBIGxhenkgc3RlcCBpcyBicmFuZC1uZXcgYnkgY29uc3RydWN0aW9uIChpdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBlbnRlcnMgdGhlIGJhdGNoIG9ubHkgd2hlbiBpdCBoYXMgbm9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gc3RlcF9jcmVhdGVkIHlldCksIHNvIGl0IGhhcyB6ZXJvIHByaW9yXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHN0YXJ0cyBhbmQgaXMgYWx3YXlzIGF0dGVtcHQgMSDigJQgc2tpcCB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbG9nIHNjYW4gZW50aXJlbHkuIE9ubHkgYW4gb3duZWQtcmVjb3ZlcnlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gcmUtcnVuIGNhbiBoYXZlIHByaW9yIHN0YXJ0cywgYW5kIHRoYXQgcGF0aFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpcyB1bmNvbW1vbiwgc28gcmVzZXJ2ZSB0aGUgTyhuKSBzY2FuIGZvciBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyByYXRoZXIgdGhhbiB3YWxraW5nIHRoZSBncm93aW5nIGxvZyBmb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gZXZlcnkgaW5saW5lIHN0ZXAgKHdoaWNoIHdvdWxkIGJlIE8obsKyKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhY3Jvc3MgYSBsb25nIHNlcXVlbnRpYWwgd29ya2Zsb3cpLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdXRob3JpdGF0aXZlQXR0ZW1wdDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzLmxhenlTdGVwSW5wdXQgIT09IHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPyAxXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IGNvdW50U3RlcFN0YXJ0ZWRFdmVudHMoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRMb2cuZXZlbnRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHMuY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnb3duZWRCeScsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlSWQ6IG1ldGFkYXRhLm1lc3NhZ2VJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgKyAxLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBMYXp5IGlubGluZSBzdGFydDogc2VuZCB0aGUgZGVmZXJyZWQgc3RlcCdzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlucHV0IG9uIHN0ZXBfc3RhcnRlZCBzbyB0aGUgd29ybGQgY3JlYXRlc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgc3RlcCBvbiB0aGUgZmx5LiBBYnNlbnQgZm9yXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG93bmVkLXJlY292ZXJ5IHN0ZXBzLCB3aG9zZSBpbnB1dCBoeWRyYXRlc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBmcm9tIHRoZSBleGlzdGluZyBzdGVwIGVudGl0eS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGF6eVN0ZXBJbnB1dDogcy5sYXp5U3RlcElucHV0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJbmxpbmUgb3duZXJzaGlwOiBzdGFtcCAob3IgcmUtc3RhbXApIHRoaXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW52b2NhdGlvbidzIHF1ZXVlIG1lc3NhZ2UgSUQgb24gdGhlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHN0ZXBfc3RhcnRlZCwgc28gd2FrZSByZXBsYXlzIHNlZSB0aGUgYm9keVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhcyBpbiBmbGlnaHQgaGVyZSBhbmQgc3VwcHJlc3MgdGhlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGltbWVkaWF0ZSByZXF1ZXVlICh3b3JrZmxvdyMyNzgwKS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3duZXJNZXNzYWdlSWQ6IG1ldGFkYXRhLm1lc3NhZ2VJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVHVyYm86IGZvcmNlIG9wdGltaXN0aWMgc3RhcnQgYW5kIGhvbGQgdGhlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGxhenkgc3RlcF9zdGFydGVkIHVudGlsIHRoZSBiYWNrZ3JvdW5kZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gcnVuX3N0YXJ0ZWQgbGFuZHMgKHRoZSBib2R5IHN0aWxsIHJ1bnNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW1tZWRpYXRlbHkpLiBCb3RoIGFyZSB1bmRlZmluZWQvZmFsc2VcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gb3V0c2lkZSB0dXJiby5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yY2VPcHRpbWlzdGljU3RhcnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEd1YXJkLWVuZm9yY2VkIGJhdGNoZXMgd2l0aCBhbiBvcGVuIGhvb2tcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXdhaXQgdGhlIGNsYWltIGJlZm9yZSBydW5uaW5nIHRoZSBib2R5LCBzb1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhIDQxMi1mZW5jZWQgc3RlcCBuZXZlciBleGVjdXRlcyB1c2VyIGNvZGUg4oCUXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNlZSBzdXBwcmVzc09wdGltaXN0aWNTdGFydCBhYm92ZS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VwcHJlc3NPcHRpbWlzdGljU3RhcnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJ1blJlYWR5QmFycmllcixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlY29uZGl0aW9uU25hcHNob3Q6IGlubGluZUNsYWltU25hcHNob3QsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLihzdGVwSW5kZXggPT09IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcy5sYXp5U3RlcElucHV0ICE9PSB1bmRlZmluZWQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGF0ZW5jeVRyYWNraW5nXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPyB7IGxhdGVuY3lUcmFja2luZyB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiB7fSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLihyZXF1ZXN0SW5saW5lRGVsdGEgJiYgZXZlbnRMb2cuY3Vyc29yXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPyB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlubGluZURlbHRhU2luY2VDdXJzb3I6IGV2ZW50TG9nLmN1cnNvcixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IHt9KSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwbGF5UmVjb3ZlcnlSZXBvcnRlcixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSW52YXJpYW50IGJvb2trZWVwaW5nOiB0aGlzIGludm9jYXRpb24gb3duc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZXNlIGJvZGllcyB1bnRpbCB0aGV5IHNldHRsZSDigJQgc2VlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXNzZXJ0Tm9JbkZsaWdodE93bmVkU3RlcHMuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5GbGlnaHRPd25lZFN0ZXBzLmFkZChzLmNvcnJlbGF0aW9uSWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIExhenkgc3RlcHMgYXJlIGJyYW5kLW5ldyAodGhlaXIgY3JlYXRlLWNsYWltXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXMgdGhlIGV4YWN0bHktb25jZSBnYXRlKSwgYnV0IGFuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gb3duZWQtcmVjb3Zlcnkgc3RlcCBhbHJlYWR5IGV4aXN0cyBhbmQgaXRzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gZGVsYXllZCBiYWNrc3RvcCBtZXNzYWdlIG1heSBmaXJlIG1pZC1ib2R5XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW4gdGhpcyBzYW1lIHByb2Nlc3Mg4oCUIHJvdXRlIHRob3NlIHRocm91Z2hcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgaW4tcHJvY2VzcyBzaW5nbGUtZmxpZ2h0LlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGV4ZWN1dGVkID1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHMubGF6eVN0ZXBJbnB1dCA9PT0gdW5kZWZpbmVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gcnVuU3RlcFNpbmdsZUZsaWdodChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcy5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcnVuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IHJ1bigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBleGVjdXRlZC5maW5hbGx5KCgpID0+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbkZsaWdodE93bmVkU3RlcHMuZGVsZXRlKHMuY29ycmVsYXRpb25JZClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgc3RlcFJlc3VsdHMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGVwRXhlY3V0aW9uUHJvbWlzZXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKHN0ZXBFcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQSBzdGFsZSAoNDEyKSByZWplY3Rpb24gb2YgYW4gaW5saW5lIHN0ZXBfc3RhcnRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBjbGFpbTogdGhlIGxvYWRlZCB2aWV3IHRoaXMgYmF0Y2ggd2FzIHNjaGVkdWxlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBmcm9tIGlzIG1pc3NpbmcgYW4gZXZlbnQgdGhlIGJhY2tlbmQgYWxyZWFkeSBoYXMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNvIHRoZSBjbGFpbSB3YXMgZmVuY2VkIGJ5IHRoZSBndWFyZCBhbmQgbm8gc3RlcFxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBldmVudHMgd2VyZSB3cml0dGVuLiBBYmFuZG9uIHRoZSBiYXRjaCDigJQgYW55XG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG9wdGltaXN0aWMgYm9keSByZXN1bHQgaXMgZGlzY2FyZGVkIGJ5IGV4ZWN1dGVTdGVwJ3NcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gcmVjb25jaWxpYXRpb24g4oCUIGFuZCByZXN0YXJ0IHRoZSByZXBsYXkgc28gaXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gb2JzZXJ2ZXMgdGhlIG1pc3NpbmcgZXZlbnQuIFdhaXQgZm9yIHRoZSBzaWJsaW5nXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGV4ZWN1dGlvbnMgdG8gc2V0dGxlIGZpcnN0IHNvIG5vIG93bmVkIGJvZHkgaXMgaW5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gZmxpZ2h0IHdoZW4gdGhlIHJlc3RhcnQgKG9yIHRoZSBhY2sgcGF0aCkgcnVucy5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFByZWNvbmRpdGlvbkZhaWxlZEVycm9yLmlzKHN0ZXBFcnIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2V0dGxlZCA9IGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXBFeGVjdXRpb25Qcm9taXNlc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQSBzaWJsaW5nIHdob3NlIGNsYWltIHdhcyBhY2NlcHRlZCB3cm90ZSBzdGVwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gZXZlbnRzIG9mIGl0cyBvd24sIHBvc3NpYmx5IGFmdGVyIHRoZSBXb3JsZCBidWlsdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoaXMgNDEyJ3MgZGVsdGEg4oCUIHNvIHRoYXQgZGVsdGEgY2FuIG5vIGxvbmdlciBiZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFzc3VtZWQgdG8gY29tcGxldGUgdGhlIGxvZywgYW5kIHRoZSByZXN0YXJ0IGhhc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRvIHJlbG9hZCBpdCBpbiBmdWxsLiBgc2tpcHBlZGAgKHRoZSBzdGVwIGFscmVhZHlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBleGlzdGVkKSwgYGdvbmVgIGFuZCBgdGhyb3R0bGVkYCAoY2xhaW0gcmVqZWN0ZWQpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gd3JvdGUgbm90aGluZy5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzaWJsaW5nV3JvdGUgPSBzZXR0bGVkLnNvbWUoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAob3V0Y29tZSkgPT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZS5zdGF0dXMgPT09ICdmdWxmaWxsZWQnICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChvdXRjb21lLnZhbHVlLnR5cGUgPT09ICdjb21wbGV0ZWQnIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZS52YWx1ZS50eXBlID09PSAnZmFpbGVkJyB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWUudmFsdWUudHlwZSA9PT0gJ3JldHJ5JylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3RhcnRSZXBsYXlJblByb2Nlc3MoJ2lubGluZS1jbGFpbScsIHN0ZXBFcnIsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxsb3dEZWx0YTogIXNpYmxpbmdXcm90ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGUgZmluYWxseSBiZWxvdyByZXN1bWVzIHRoZSByZXBsYXkgYnVkZ2V0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBiZWZvcmUgdGhlIG5leHQgaXRlcmF0aW9uIHN0YXJ0cy5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGUgZmluYWxseSBiZWxvdyByZXN1bWVzIHRoZSByZXBsYXkgYnVkZ2V0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYmVmb3JlIHRoaXMgcmV0dXJuIChvciB0aHJvdykgY29tcGxldGVzLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVzY2FsYXRpb24gPVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgcmVpbnZva2VBZnRlclN0YWxlUmVqZWN0aW9uKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnaW5saW5lLWNsYWltJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RlcEVyclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXNjYWxhdGlvbi5yZWludm9rZWQpIHJldHVybiBlc2NhbGF0aW9uLnJlc3VsdDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBlc2NhbGF0aW9uLmVycm9yO1xuICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IHN0ZXBFcnI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICByZXBsYXlCdWRnZXQucmVzdW1lKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFnZ3JlZ2F0ZSB0aGUgYmF0Y2ggcmVzdWx0cy4gYHJldHJ5YCBzdGVwcyAod2hpY2hcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFscmVhZHkgZXhpc3Qg4oCUIHRoZWlyIGBzdGVwX3N0YXJ0ZWRgIHN1Y2NlZWRlZCkgYXJlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyByZS1xdWV1ZWQgcGVyLXN0ZXAgYXMgYmFja2dyb3VuZCBzdGVwcyB3aXRoIHRoZWlyIG93blxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZGVsYXk7IGB0aHJvdHRsZWRgIHN0ZXBzIChyZWplY3RlZCBvbiB0aGUgY3JlYXRlLWNsYWltLFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gc28gbmV2ZXIgY3JlYXRlZCkgaW5zdGVhZCBkZWZlciByZWRlbGl2ZXJ5IG9mIHRoaXNcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG9yY2hlc3RyYXRvciBtZXNzYWdlIHNvIHRoZXkgcmUtcnVuIGlubGluZSB3aXRoIGlucHV0XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBvbiByZXBsYXk7IGNvbXBsZXRlZC9mYWlsZWQgc3RlcHMgYWxyZWFkeSB3cm90ZSB0aGVpclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGVybWluYWwgZXZlbnRzLiBXZSBvbmx5IGxvb3AgYmFjayB0byByZXBsYXkgd2hlbiBldmVyeVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW5saW5lIHN0ZXAgcmVhY2hlZCBhIHRlcm1pbmFsIHN0YXRlIOKAlCBvdGhlcndpc2UgdGhlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBzdGlsbC1wZW5kaW5nIHN0ZXBzIHdpbGwgYmUgcmUtcnVuIGJ5IHRoZWlyIHF1ZXVlZCByZXRyeVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbWVzc2FnZXMgYW5kIHRoZSBiYWNrZ3JvdW5kLXN0ZXAgcGF0aCByZXBsYXlzIG9uY2VcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFsbCBzdGVwcyBhcmUgZG9uZS5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRvUmV0cnk6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgc3RlcDogKHR5cGVvZiBpbmxpbmVFeGVjdXRpb25zKVtudW1iZXJdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBkZWxheVNlY29uZHM6IG51bWJlcjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1bXSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGFueVBlbmRpbmdPcHMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEEgdGhyb3R0bGVkIGlubGluZSBzdGVwIGRlbGF5cyByZWRlbGl2ZXJ5IG9mIFRISVNcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG9yY2hlc3RyYXRvciBtZXNzYWdlIHJhdGhlciB0aGFuIGJlaW5nIHJlLXF1ZXVlZCBhcyBhXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBiYWNrZ3JvdW5kIHN0ZXAuIENydWNpYWxseSwgYSBgdGhyb3R0bGVkYCByZXN1bHQgbWVhbnNcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBsYXp5IGBzdGVwX3N0YXJ0ZWRgIHdhcyByZWplY3RlZCBvbiB0aGUgYXRvbWljXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBjcmVhdGUtY2xhaW0g4oCUIHNvIHRoZSBzdGVwIHdhcyBORVZFUiBjcmVhdGVkIChub1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYHN0ZXBfY3JlYXRlZGAsIG5vIHN0ZXAgZW50aXR5KS4gUmUtcXVldWluZyBpdCBhcyBhXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBiYWNrZ3JvdW5kIHN0ZXAgd291bGQgc2VuZCBhIGJhcmUgYHN0ZXBfc3RhcnRlZGAgKG5vXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpbnB1dCksIHdoaWNoIHRoZSB3b3JsZCByZWplY3RzIHdpdGggYFN0ZXAgXCI8aWQ+XCIgbm90XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBmb3VuZGAgYmVjYXVzZSBpdCBjYW5ub3QgbGF6aWx5IGNyZWF0ZSB0aGUgc3RlcCB3aXRob3V0XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpdHMgaW5wdXQ7IHRoYXQgZXJyb3IgaXNuJ3QgdHJhbnNsYXRhYmxlLCBzbyB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG1lc3NhZ2UgcmVkZWxpdmVycyB1bnRpbCBNQVhfUVVFVUVfREVMSVZFUklFUyBhbmQgdGhlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBzdGVwIChhbmQgcnVuKSBmYWlsLiBEZWZlcnJpbmcgcmVkZWxpdmVyeSBvZiB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG9yY2hlc3RyYXRvciBpbnN0ZWFkIHJlLWF0dGVtcHRzIHRoZSB0aHJvdHRsZWQgc3RlcFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW5saW5lIFdJVEggaXRzIGlucHV0IG9uIHJlcGxheS4gV2UgdHJhY2sgdGhlIGxvbmdlc3RcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGJhY2tvZmYgc28gYSBiYXRjaCB3aXRoIG11bHRpcGxlIHRocm90dGxlcyB3YWl0cyB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG1heC4gTm90ZTogYHJldHJ5YCByZXN1bHRzIGFyZSBzYWZlIHRvIHJlLXF1ZXVlIGFzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBiYWNrZ3JvdW5kIHN0ZXBzIGJlY2F1c2UgYSByZXRyeSBpbXBsaWVzIGBzdGVwX3N0YXJ0ZWRgXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhbHJlYWR5IHN1Y2NlZWRlZCBhbmQgdGhlIHN0ZXAgZXhpc3RzLlxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHRocm90dGxlVGltZW91dDogbnVtYmVyIHwgdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbmxpbmVFeGVjdXRpb25zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHIgPSBzdGVwUmVzdWx0c1tpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcyA9IGlubGluZUV4ZWN1dGlvbnNbaV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyLnR5cGUgPT09ICdyZXRyeScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b1JldHJ5LnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RlcDogcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGF5U2Vjb25kczogci50aW1lb3V0U2Vjb25kcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChyLnR5cGUgPT09ICd0aHJvdHRsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3R0bGVUaW1lb3V0ID0gTWF0aC5tYXgoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdHRsZVRpbWVvdXQgPz8gMCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHIudGltZW91dFNlY29uZHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHIudHlwZSA9PT0gJ2NvbXBsZXRlZCcgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByLmhhc1BlbmRpbmdPcHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYW55UGVuZGluZ09wcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRocm90dGxlVGltZW91dCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIERlZmVyIHJlZGVsaXZlcnkgb2YgdGhlIG9yY2hlc3RyYXRvciBhZnRlciB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhyb3R0bGUgYmFja29mZi4gT24gcmVwbGF5IGV2ZXJ5IG5vbi10ZXJtaW5hbCBzdGVwXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlzIHJlLWRpc3BhdGNoZWQgYnkgdGhlIHN1c3BlbnNpb24gaGFuZGxlcjogdGhlXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHN0aWxsLXRocm90dGxlZCBzdGVwcyBydW4gaW5saW5lIGFnYWluIFdJVEggdGhlaXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW5wdXQgKHRoZWlyIGBzdGVwX2NyZWF0ZWRgIGlzIGRlZmVycmVkIGFuZXcpLCBhbmRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYW55IGByZXRyeWAgc3RlcHMgaW4gdGhpcyBiYXRjaCBhcmUgcXVldWVkIGFzXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGJhY2tncm91bmQgc3RlcHMgd2l0aCB0aGVpciBvd24gcmV0cnlBZnRlciBob25vcmVkLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUZXJtaW5hbCBzdGVwcyAoY29tcGxldGVkL2ZhaWxlZC9za2lwcGVkL2dvbmUpIGFyZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBvYnNlcnZlZCBmcm9tIHRoZWlyIGV2ZW50cyBhbmQgbm90IHJlLXJ1bi4gQmVjYXVzZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgcmVwbGF5IGRyaXZlcyBhbGwgcmVtYWluaW5nIHdvcmssIHdlIG11c3QgTk9UXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFsc28gcmUtcXVldWUgYHRvUmV0cnlgIGhlcmUg4oCUIHRoYXQgd291bGRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gZG91YmxlLWRpc3BhdGNoIHRob3NlIHN0ZXBzLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAvL1xuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHJldHVybnMgQkVGT1JFIHRoZSBgYW55UGVuZGluZ09wc2AgYnJhbmNoXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGJlbG93LCBzbyBhIGJhdGNoIHRoYXQgbWl4ZXMgYSB0aHJvdHRsZSB3aXRoIGFcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gY29tcGxldGVkIHN0ZXAgdGhhdCBsZWZ0IHVuZmx1c2hlZCBvcHMgZG9lcyBub3RcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gcXVldWUgdGhlIGV4cGxpY2l0IGZsdXNoIGNvbnRpbnVhdGlvbi4gVGhhdCBpcyBzYWZlXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGJlY2F1c2UgdGhlIHRocm90dGxlIGJhY2tvZmYgKD49IDFzKSBhbHdheXMgZXhjZWVkc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgaW4taW52b2NhdGlvbiBmbHVzaCB3aW5kb3cgKDw9IDUwMG1zICsgd2FpdFVudGlsKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gc28gb3BzIHNldHRsZSBiZWZvcmUgdGhlIHBvc3QtYmFja29mZiByZWRlbGl2ZXJ5XG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHJlcGxheXMgYW5kIHJlYWRzIHRoZW0uXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhd2FpdCByZWludm9rZSh0aHJvdHRsZVRpbWVvdXQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodG9SZXRyeS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJldHJ5VHJhY2VDYXJyaWVyID0gYXdhaXQgbmV4dFRyYWNlQ2FycmllcigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b1JldHJ5Lm1hcCgoeyBzdGVwLCBkZWxheVNlY29uZHMgfSkgPT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHF1ZXVlTWVzc2FnZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd29ybGQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldFdvcmtmbG93UXVldWVOYW1lKHdvcmtmbG93TmFtZSwgbmFtZXNwYWNlKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXBJZDogc3RlcC5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXBOYW1lOiBzdGVwLnN0ZXBOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNlQ2FycmllcjogcmV0cnlUcmFjZUNhcnJpZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWVzdGVkQXQ6IG5ldyBEYXRlKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWxheVNlY29uZHMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gS2V5IHRoZSBkZWxheWVkIHJldHJ5IG9uIHRoZSBzdGVwJ3NcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBjb3JyZWxhdGlvbklkIHNvIGl0IGRlZHVwZXMgYWdhaW5zdCB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBrZXllZCByZS1kaXNwYXRjaCB0aGUgc3VzcGVuc2lvbiBoYW5kbGVyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gcGVyZm9ybXMgb24gcmVwbGF5IChpdCBhbHNvIHVzZXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBgaWRlbXBvdGVuY3lLZXk6IHN0ZXAuY29ycmVsYXRpb25JZGApLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2l0aG91dCB0aGlzLCBhIG1peGVkIGJhdGNoIHdoZXJlIG9uZSBzdGVwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYGNvbXBsZXRlZGAgd2l0aCB1bmZsdXNoZWQgYmFja2dyb3VuZCBvcHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAoYGFueVBlbmRpbmdPcHNgKSBhbmQgYW5vdGhlciBzdGVwIGlzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gcmV0cnlpbmcgd291bGQgZG91YmxlLWRpc3BhdGNoIHRoZSByZXRyeTpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgYGFueVBlbmRpbmdPcHNgIGJyYW5jaCBiZWxvdyBxdWV1ZXMgYW5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpbW1lZGlhdGUgcGxhaW4gY29udGludWF0aW9uLCB3aG9zZSByZXBsYXlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBzZWVzIHRoZSBzdGlsbC1gcmV0cnlpbmdgIHN0ZXAgYXMgcGVuZGluZ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFuZCByZS1kaXNwYXRjaGVzIGl0ICppbW1lZGlhdGVseSogYW5kXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gKndpdGgqIGEga2V5LiBTaW5jZSB0aGlzIGRlbGF5ZWQgcmV0cnkgaGFkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbm8ga2V5LCB0aGUgdHdvIG1lc3NhZ2VzIHdvdWxkbid0IGRlZHVwZSDigJRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgc3RlcCB3b3VsZCBydW4gdHdpY2UsIHRoZSBjb25maWd1cmVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gcmV0cnkgYmFja29mZiB3b3VsZCBiZSBpZ25vcmVkIChwbGFpblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGBFcnJvcmAgcmV0cmllcyBwZXJzaXN0IG5vIGByZXRyeUFmdGVyYCwgc29cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgd29ybGQgaGFzIG5vIGBUb29FYXJseWAgZ3VhcmQpLCBhbmQgdGhlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gcmV0cnkgYm9keSBjb3VsZCBydW4gZWFybHkvY29uY3VycmVudGx5LlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNoYXJpbmcgdGhlIGtleSBsZXRzIHRoZSBlYXJsaWVyIGRlbGF5ZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBtZXNzYWdlIHdpbiwgaG9ub3JpbmcgdGhlIGJhY2tvZmYuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWRlbXBvdGVuY3lLZXk6IHN0ZXAuY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gTGV0IHBlbmRpbmcgYmFja2dyb3VuZCBvcGVyYXRpb25zIGZsdXNoIGJlZm9yZSB0aGUgbmV4dFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gcmVwbGF5IHJlYWRzIHRoZWlyIHJlc3VsdHMuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYW55UGVuZGluZ09wcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBydW50aW1lTG9nZ2VyLmRlYnVnKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdCcmVha2luZyBsb29wOiBpbmxpbmUgc3RlcCBoYXMgcGVuZGluZyBvcHMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsgd29ya2Zsb3dSdW5JZDogcnVuSWQsIGxvb3BJdGVyYXRpb24gfVxuICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBxdWV1ZU1lc3NhZ2UoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd29ybGQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0V29ya2Zsb3dRdWV1ZU5hbWUod29ya2Zsb3dOYW1lLCBuYW1lc3BhY2UpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhY2VDYXJyaWVyOiBhd2FpdCBuZXh0VHJhY2VDYXJyaWVyKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXF1ZXN0ZWRBdDogbmV3IERhdGUoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRvUmV0cnkubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTb21lIGlubGluZSBzdGVwcyB3aWxsIGJlIHJlLXJ1biB2aWEgdGhlaXIgcXVldWVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHJldHJ5IG1lc3NhZ2VzOyB0aGUgYmFja2dyb3VuZC1zdGVwIHBhdGggcmVwbGF5c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBvbmNlIGFsbCBzdGVwcyBhcmUgdGVybWluYWwuIERvbid0IGxvb3AgaGVyZSDigJQgdGhlXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHJldHJ5aW5nIHN0ZXBzIGhhdmUgbm8gdGVybWluYWwgZXZlbnQgdG8gb2JzZXJ2ZSB5ZXQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWxsIGlubGluZSBzdGVwcyByZWFjaGVkIGEgdGVybWluYWwgc3RhdGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIChjb21wbGV0ZWQvZmFpbGVkL3NraXBwZWQvZ29uZSkg4oCUIGxvb3AgYmFjayB0byByZXBsYXlcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICh0aGUgd29ya2Zsb3cgb2JzZXJ2ZXMgdGhlIHRlcm1pbmFsIGV2ZW50cyBvbiByZXBsYXkpLlxuICAgICAgICAgICAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJldXNlIGFueSBpbmxpbmUgZGVsdGEuIElmIGl0IGlzIHBhcnRpYWwsIGNvbnRpbnVlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBmcm9tIGl0cyBjdXJzb3IgaW5zdGVhZCBvZiByZWFkaW5nIHRoZSBwYWdlIGFnYWluLlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlubGluZUV4ZWN1dGlvbnMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG9ubHkgPSBzdGVwUmVzdWx0c1swXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9ubHkudHlwZSA9PT0gJ2NvbXBsZXRlZCcgJiYgb25seS5pbmxpbmVEZWx0YSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGVuZEV2ZW50TG9nKGV2ZW50TG9nLCBvbmx5LmlubGluZURlbHRhKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudExvZyA9IG9ubHkuaW5saW5lRGVsdGEuaGFzTW9yZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPyBuZXh0RXZlbnRMb2dMb2FkKGV2ZW50TG9nKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiB7IC4uLmV2ZW50TG9nLCB0eXBlOiAncmVhZHknIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50TG9nID0gbmV4dEV2ZW50TG9nTG9hZChldmVudExvZyk7XG4gICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFN0YWxlLXNuYXBzaG90IHJlamVjdGlvbiBvZiBhIGd1YXJkZWQgd3JpdGUgbWFkZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZGlyZWN0bHkgYnkgdGhlIHJlcGxheSBsb29wIOKAlCB0aGUgcmVzdWx0LWJlYXJpbmdcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGBydW5fY29tcGxldGVkYCwgb3IgdGhlIGB3YWl0X2NvbXBsZXRlZGAgb2YgdGhlIHdhaXRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHBhc3MuIEJvdGggcmVhY2ggdGhpcyBvbmUgY2F0Y2ggYW5kIHRoZSByZWplY3Rpb25cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGRvZXMgbm90IHNheSB3aGljaCwgaGVuY2UgdGhlIG5ldXRyYWwgbGFiZWwuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBOZWl0aGVyIG1heSBiZSByZS1wb3N0ZWQgaW4gcGxhY2U6IHRoZSBjb3JyZWxhdGlvbiBpZFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYW5kIChmb3IgcnVuX2NvbXBsZXRlZCkgdGhlIHJlc3VsdCBpdHNlbGYgY2FtZSBmcm9tXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGlzIHJlcGxheSwgYW5kIGEgY29ycmVjdGVkIGxvZyBtYXkgcHJvZHVjZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZGlmZmVyZW50IG9uZXMuIERvbid0IGZhaWwgdGhlIHJ1biDigJQgcmVzdGFydCB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHJlcGxheSBpbiB0aGlzIGludm9jYXRpb24sIGFuZCBvbmx5IG9uY2UgdGhhdCBidWRnZXRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlzIHNwZW50IHNjaGVkdWxlIGFuIGV4cGxpY2l0IHJlLWludm9jYXRpb24uXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBSZXRocm93aW5nIGluc3RlYWQgd291bGQgcmVseSBvbiByZWRlbGl2ZXJ5IG9mIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ1VSUkVOVCBtZXNzYWdlLCB3aGljaCB0aGUgdHVyYm8gcGF0aCBoYXMgYWxyZWFkeVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWNrZWQg4oCUIGVtcGlyaWNhbGx5IHRoZSBydW4gdGhlbiBzdGFsbHMgZm9yIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gcXVldWUncyB+MzAwcyBkZWZhdWx0IHZpc2liaWxpdHkgdGltZW91dCBiZWZvcmVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNvbXBsZXRpbmcuXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgdGVybWluYWxFcnJvciA9IGVycjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChQcmVjb25kaXRpb25GYWlsZWRFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXN0YXJ0UmVwbGF5SW5Qcm9jZXNzKCdyZXBsYXktd3JpdGUnLCBlcnIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXNjYWxhdGlvbiA9IGF3YWl0IHJlaW52b2tlQWZ0ZXJTdGFsZVJlamVjdGlvbihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAncmVwbGF5LXdyaXRlJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVzY2FsYXRpb24ucmVpbnZva2VkKSByZXR1cm4gZXNjYWxhdGlvbi5yZXN1bHQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFBlci1ydW4gYnVkZ2V0IHNwZW50LiBGYWxsIHRocm91Z2ggdG8gdGhlIHRlcm1pbmFsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHBhdGggYmVsb3cgaW5zdGVhZCBvZiByZXRocm93aW5nOiB0aGlzIGNhdGNoIG93bnNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gZmFpbGluZyB0aGUgcnVuLCBhbmQgYSByZXRocm93IHdvdWxkIGVzY2FwZSB0byB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gcXVldWUgaGFuZGxlciBhbmQgYmUgcmVkZWxpdmVyZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHRlcm1pbmFsRXJyb3IgPSBlc2NhbGF0aW9uLmVycm9yO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBUcmFuc2llbnQgaW5mcmFzdHJ1Y3R1cmUgZmFpbHVyZXMgdGFsa2luZyB0byB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHdvcmxkICh3b3JrZmxvdy1zZXJ2ZXIpIOKAlCBhbiBleGhhdXN0ZWQgUmV0cnlBZ2VudFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gKFVORF9FUlJfUkVRX1JFVFJZIGZyb20gYSBzdXN0YWluZWQgNDI5LzUwMyBzdG9ybSksXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhIGRyb3BwZWQgc29ja2V0LCBhIGNvbm5lY3QvRE5TIGZhaWx1cmUsIG9yIGEgY2xpZW50XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB0aW1lb3V0IOKAlCBtdXN0IE5PVCBmYWlsIHRoZSBydW4uIFJldGhyb3cgc28gdGhlIHF1ZXVlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyByZWRlbGl2ZXJzIGFuZCBhIGZyZXNoIGludm9jYXRpb24gcmV0cmllcyB0aGUgcmVwbGF5XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBvbmNlIHRoZSBiYWNrZW5kIHJlY292ZXJzLiBUaGUgQHZlcmNlbC9xdWV1ZSBoYW5kbGVyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhcHBsaWVzIGEgZmFzdCAoMXPihpI2MHMpIGJhY2tvZmYgYnkgZGVsaXZlcnkgY291bnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhdm9pZGluZyB0aGUgfjVtaW4gZGVmYXVsdCB2aXNpYmlsaXR5LXRpbWVvdXQgcmVkcml2ZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gKGFuZCBuZXZlciBraWxsaW5nIHRoZSBwcm9jZXNzIHZpYSBydW5fZmFpbGVkKS5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1JldHJ5YWJsZVdvcmxkRXJyb3IoZXJyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBydW5Mb2dnZXIud2FybihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnVHJhbnNpZW50IHdvcmxkIGVycm9yIGR1cmluZyByZXBsYXk7IHJlZGVsaXZlcmluZyB2aWEgcXVldWUgaW5zdGVhZCBvZiBmYWlsaW5nIHRoZSBydW4nLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZTpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyIGluc3RhbmNlb2YgRXJyb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IGVyci5uYW1lXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiAnVW5rbm93bkVycm9yJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZTpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyIGluc3RhbmNlb2YgRXJyb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IGVyci5tZXNzYWdlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiBTdHJpbmcoZXJyKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGl2ZXJ5QXR0ZW1wdDogbWV0YWRhdGEuYXR0ZW1wdCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHJlcGxheURpdmVyZ2VuY2VDb3VudEZvckZhaWx1cmU6IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChSZXBsYXlEaXZlcmdlbmNlRXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkaXZlcmdlbmNlQ291bnQgPVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChyZXBsYXlEaXZlcmdlbmNlPy5jb3VudCA/PyAwKSArIDE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1heFJlY292ZXJ5UmVwbGF5cyA9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0UmVwbGF5RGl2ZXJnZW5jZU1heFJldHJpZXMoKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGl2ZXJnZW5jZUNvdW50IDw9IG1heFJlY292ZXJ5UmVwbGF5cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJ1bkxvZ2dlci53YXJuKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ1dvcmtmbG93IHJlcGxheSBkaXZlcmdlZDsgcXVldWVpbmcgYSByZWNvdmVyeSByZXBsYXkgYmVmb3JlIGRlY2xhcmluZyB0aGUgZXZlbnQgbG9nIGNvcnJ1cHRlZCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ29kZTogUlVOX0VSUk9SX0NPREVTLlJFUExBWV9ESVZFUkdFTkNFLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXZlcmdlbmNlRXZlbnRJZDogZXJyLmV2ZW50SWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW9yRGl2ZXJnZW5jZUV2ZW50SWQ6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwbGF5RGl2ZXJnZW5jZT8uZXZlbnRJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGl2ZXJnZW5jZUNvdW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWxpdmVyeUF0dGVtcHQ6IG1ldGFkYXRhLmF0dGVtcHQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heFJlY292ZXJ5UmVwbGF5cyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHF1ZXVlTWVzc2FnZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmxkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0V29ya2Zsb3dRdWV1ZU5hbWUod29ya2Zsb3dOYW1lLCBuYW1lc3BhY2UpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhY2VDYXJyaWVyOiBhd2FpdCBuZXh0VHJhY2VDYXJyaWVyKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcXVlc3RlZEF0OiBuZXcgRGF0ZSgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXBsYXlEaXZlcmdlbmNlOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRJZDogZXJyLmV2ZW50SWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY291bnQ6IGRpdmVyZ2VuY2VDb3VudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJlcGxheURpdmVyZ2VuY2VDb3VudEZvckZhaWx1cmUgPSBkaXZlcmdlbmNlQ291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHRlcm1pbmFsRXJyb3IgPSBuZXcgQ29ycnVwdGVkRXZlbnRMb2dFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBgV29ya2Zsb3cgcmVwbGF5IGRpdmVyZ2VkICR7ZGl2ZXJnZW5jZUNvdW50fSB0aW1lcyBhZnRlciAke21heFJlY292ZXJ5UmVwbGF5c30gcmVjb3ZlcnkgcmVwbGF5czsgbGF0ZXN0IGRpdmVyZ2VudCBldmVudCB3YXMgJHtlcnIuZXZlbnRJZH0uIExhc3QgZGl2ZXJnZW5jZTogJHtlcnIubWVzc2FnZX1gLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsgY2F1c2U6IGVyciB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHJlcGxheVN0YXJ0ID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICByZXBsYXlSZWNvdmVyeVJlcG9ydGVyLmFjdGl2YXRlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFVzZXIgY29kZSBlcnJvcnMgYW5kIHRlcm1pbmFsIHJ1bnRpbWUgZXJyb3JzIGZhaWwgdGhlIHJ1bi5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0ZXJtaW5hbEVycm9yIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgc3Bhbj8ucmVjb3JkRXhjZXB0aW9uPy4odGVybWluYWxFcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG5vcm1hbGl6ZWRFcnJvciA9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IG5vcm1hbGl6ZVVua25vd25FcnJvcih0ZXJtaW5hbEVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yTmFtZSA9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIG5vcm1hbGl6ZWRFcnJvci5uYW1lIHx8IGdldEVycm9yTmFtZSh0ZXJtaW5hbEVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IG5vcm1hbGl6ZWRFcnJvci5tZXNzYWdlO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yU3RhY2sgPVxuICAgICAgICAgICAgICAgICAgICAgICAgICBub3JtYWxpemVkRXJyb3Iuc3RhY2sgfHwgZ2V0RXJyb3JTdGFjayh0ZXJtaW5hbEVycm9yKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yU3RhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcGFyc2VkTmFtZSA9IHBhcnNlV29ya2Zsb3dOYW1lKHdvcmtmbG93TmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZpbGVuYW1lID1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXJzZWROYW1lPy5tb2R1bGVTcGVjaWZpZXIgfHwgd29ya2Zsb3dOYW1lO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvclN0YWNrID0gcmVtYXBFcnJvclN0YWNrKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yU3RhY2ssXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZW5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dDb2RlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIENsYXNzaWZ5IHRoZSBlcnJvcjogV29ya2Zsb3dSdW50aW1lRXJyb3IgaW5kaWNhdGVzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhbiBTREsvcnVudGltZSBpc3N1ZSwgYW5kIHNlbGVjdGVkIHN1YmNsYXNzZXMgdXNlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBtb3JlIHNwZWNpZmljIGNvZGVzIGZvciBiYWNrZW5kIHRyYWNraW5nLlxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3JDb2RlID0gY2xhc3NpZnlSdW5FcnJvcih0ZXJtaW5hbEVycm9yKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5lcnJvcignRXJyb3Igd2hpbGUgcnVubmluZyB3b3JrZmxvdycsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ29kZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvclN0YWNrLFxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFwcGx5IHRoZSBzb3VyY2UtbWFwLXJlbWFwcGVkIHN0YWNrIHRvIHRoZSB0aHJvd25cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHZhbHVlIHNvIHRoYXQgdGhlIHNlcmlhbGl6ZWQgZXJyb3IgcHJlc2VydmVzIGl0XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBmb3IgY29uc3VtZXJzLiBgdHlwZXMuaXNOYXRpdmVFcnJvcigpYCBpcyB1c2VkXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpbnN0ZWFkIG9mIGBlcnIgaW5zdGFuY2VvZiBFcnJvcmAgYmVjYXVzZSB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHdvcmtmbG93IHJ1bnMgaW4gYSBzZXBhcmF0ZSBWTSByZWFsbSDigJQgaXRzIEVycm9yXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBjbGFzcyBpcyBkaXN0aW5jdCBmcm9tIHRoZSBob3N0J3MsIHNvIGBpbnN0YW5jZW9mXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBFcnJvcmAgaXMgYGZhbHNlYCBmb3IgVk0tdGhyb3duIGVycm9ycy4gVGhlIFY4XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB0eXBlIHRhZyB3b3JrcyBhY3Jvc3MgcmVhbG1zLlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVzLmlzTmF0aXZlRXJyb3IodGVybWluYWxFcnJvcikgJiYgZXJyb3JTdGFjaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAodGVybWluYWxFcnJvciBhcyBFcnJvcikuc3RhY2sgPSBlcnJvclN0YWNrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBGYWlsIHRoZSB3b3JrZmxvdyBydW4gdmlhIGV2ZW50IChldmVudC1zb3VyY2VkKS5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNlcmlhbGl6ZSB0aGUgb3JpZ2luYWwgdGhyb3duIHZhbHVlIHNvIGl0cyBmdWxsXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB0eXBlIGlkZW50aXR5IGFuZCBjdXN0b20gcHJvcGVydGllcyByb3VuZC10cmlwXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB0aHJvdWdoIHRoZSBldmVudCBsb2cuXG4gICAgICAgICAgICAgICAgICAgICAgICAvL1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gUHJlY29uZGl0aW9uLWd1YXJkIGFzeW1tZXRyeTogdW5saWtlIGBydW5fY29tcGxldGVkYCxcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoaXMgdGVybWluYWwgYHJ1bl9mYWlsZWRgIHNlbmRzIG5vIGBzdGF0ZVVwZGF0ZWRBdGBcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNuYXBzaG90LCBzbyBpdCBpcyBuZXZlciA0MTItcmVqZWN0ZWQgZXZlbiBpZiBhIGhvb2tcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGxhbmRlZCBtaWQtcmVwbGF5IGFuZCBjb3VsZCBoYXZlIGNoYW5nZWQgdGhlIHBhdGggdGhhdFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhyZXcuIFRoaXMgaXMgaW50ZW50aW9uYWwgYW5kIGZhaWwtb3BlbjogYSBzcHVyaW91c1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZmFpbHVyZSBpcyByZWNvdmVyYWJsZSAodGhlIHJ1biBjYW4gYmUgcmUtcnVuIGZyb20gdGhlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBkYXNoYm9hcmQpLCB3aGVyZWFzIGEgc3B1cmlvdXMgKmNvbXBsZXRpb24qIGNvbW1pdHMgYVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gd3JvbmcgcmVzdWx0LiBHdWFyZGluZyB0aGlzIHdyaXRlIHN5bW1ldHJpY2FsbHkgd291bGRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFsc28gbmVlZCB0aGUgbG9hZGVkIGV2ZW50IGxvZywgd2hpY2ggaXMgc2NvcGVkIHRvIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gcmVwbGF5IGB0cnlgIGFib3ZlIGFuZCBub3QgYXZhaWxhYmxlIGluIHRoaXMgY2F0Y2guXG4gICAgICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUdXJibzogb3JkZXIgdGhlIHRlcm1pbmFsIHdyaXRlIGFmdGVyIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBiYWNrZ3JvdW5kZWQgcnVuX3N0YXJ0ZWQgc28gdGhlIHJ1biBleGlzdHMuXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IGF3YWl0UnVuUmVhZHkoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgY3JlYXRlRXZlbnQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRUeXBlOiAncnVuX2ZhaWxlZCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3I6IGF3YWl0IGRlaHlkcmF0ZVJ1bkVycm9yKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRlcm1pbmFsRXJyb3IsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5jcnlwdGlvbktleSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnbG9iYWxUaGlzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh3b3JrZmxvd1J1bj8uc3BlY1ZlcnNpb24gPz8gMCkgPj1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNQRUNfVkVSU0lPTl9TVVBQT1JUU19DT01QUkVTU0lPTlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNvZGUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWVzdElkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uKHJlcGxheURpdmVyZ2VuY2VDb3VudEZvckZhaWx1cmUgIT09IHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcGxheURpdmVyZ2VuY2VDb3VudDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwbGF5RGl2ZXJnZW5jZUNvdW50Rm9yRmFpbHVyZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDoge30pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGZhaWxFcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZmFpbEVycikgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBSdW5FeHBpcmVkRXJyb3IuaXMoZmFpbEVycilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ1RyaWVkIGZhaWxpbmcgd29ya2Zsb3cgcnVuLCBidXQgcnVuIGhhcyBhbHJlYWR5IGZpbmlzaGVkLicsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBmYWlsRXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzV29ybGRDb250cmFjdEVycm9yKGZhaWxFcnIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5lcnJvcihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdGYXRhbCB3b3JsZCBjb250cmFjdCBlcnJvciB3aGlsZSByZWNvcmRpbmcgd29ya2Zsb3cgZmFpbHVyZScsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNvZGU6IFJVTl9FUlJPUl9DT0RFUy5XT1JMRF9DT05UUkFDVF9FUlJPUixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3I6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFpbEVyciBpbnN0YW5jZW9mIEVycm9yXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IGZhaWxFcnIubWVzc2FnZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiBTdHJpbmcoZmFpbEVyciksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgZmFpbEVycjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd1J1blN0YXR1cygnZmFpbGVkJyksXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd0Vycm9yQ29kZShlcnJvckNvZGUpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dFcnJvck5hbWUoZXJyb3JOYW1lKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLldvcmtmbG93RXJyb3JNZXNzYWdlKGVycm9yTWVzc2FnZSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5FcnJvclR5cGUoZXJyb3JOYW1lKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICApO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICApO1xuXG4gIGxldCBjYWNoZWRIYW5kbGVyOiAoKHJlcTogUmVxdWVzdCkgPT4gUHJvbWlzZTxSZXNwb25zZT4pIHwgdW5kZWZpbmVkO1xuICBsZXQgaW52b2NhdGlvbkNvdW50ID0gMDtcbiAgY29uc3QgZW50cnlwb2ludENyZWF0ZWRBdCA9IERhdGUubm93KCk7XG4gIGNvbnN0IHJvdXRlTW9kdWxlQm9keUluaXRNcyA9XG4gICAgdHlwZW9mIG9wdGlvbnM/LnJvdXRlTW9kdWxlQm9keVN0YXJ0ZWRBdCA9PT0gJ251bWJlcidcbiAgICAgID8gZW50cnlwb2ludENyZWF0ZWRBdCAtIG9wdGlvbnMucm91dGVNb2R1bGVCb2R5U3RhcnRlZEF0XG4gICAgICA6IHVuZGVmaW5lZDtcblxuICByZXR1cm4gd2l0aEhlYWx0aENoZWNrKGFzeW5jIChyZXEpID0+IHtcbiAgICBpbnZvY2F0aW9uQ291bnQgKz0gMTtcbiAgICBjb25zdCBoYW5kbGVyQ2FjaGVkID0gY2FjaGVkSGFuZGxlciAhPT0gdW5kZWZpbmVkO1xuICAgIGNvbnN0IHNwYW5LaW5kID0gYXdhaXQgZ2V0U3BhbktpbmQoJ1NFUlZFUicpO1xuXG4gICAgcmV0dXJuIHRyYWNlKFxuICAgICAgJ3dvcmtmbG93LnJvdXRlLmZsb3cnLFxuICAgICAge1xuICAgICAgICBraW5kOiBzcGFuS2luZCxcbiAgICAgICAgYXR0cmlidXRlczoge1xuICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd1JvdXRlVHlwZSgnZmxvdycpLFxuICAgICAgICAgIC4uLkF0dHJpYnV0ZS5GYWFzSW5zdGFuY2UoQ09NUFVURV9JTlNUQU5DRV9JRCksXG4gICAgICAgICAgLi4uQXR0cmlidXRlLldvcmtmbG93Um91dGVIYW5kbGVyQ2FjaGVkKGhhbmRsZXJDYWNoZWQpLFxuICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd1JvdXRlSW52b2NhdGlvbkNvdW50KGludm9jYXRpb25Db3VudCksXG4gICAgICAgICAgLi4uQXR0cmlidXRlLldvcmtmbG93Um91dGVFbnRyeXBvaW50QWdlTXMoXG4gICAgICAgICAgICBEYXRlLm5vdygpIC0gZW50cnlwb2ludENyZWF0ZWRBdFxuICAgICAgICAgICksXG4gICAgICAgICAgLi4uKHJvdXRlTW9kdWxlQm9keUluaXRNcyA9PT0gdW5kZWZpbmVkXG4gICAgICAgICAgICA/IHt9XG4gICAgICAgICAgICA6IEF0dHJpYnV0ZS5Xb3JrZmxvd1JvdXRlTW9kdWxlQm9keUluaXRNcyhyb3V0ZU1vZHVsZUJvZHlJbml0TXMpKSxcbiAgICAgICAgICAuLi5BdHRyaWJ1dGUuSHR0cFJlcXVlc3RNZXRob2QocmVxLm1ldGhvZCksXG4gICAgICAgICAgLi4uQXR0cmlidXRlLkh0dHBSb3V0ZSgnLy53ZWxsLWtub3duL3dvcmtmbG93L3YxL2Zsb3cnKSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICBhc3luYyAoc3BhbikgPT4ge1xuICAgICAgICBpZiAoIWNhY2hlZEhhbmRsZXIpIHtcbiAgICAgICAgICBjYWNoZWRIYW5kbGVyID0gYXdhaXQgdHJhY2UoJ3dvcmtmbG93LnJvdXRlLmluaXQnLCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCB3b3JsZEhhbmRsZXJzID0gYXdhaXQgdHJhY2UoXG4gICAgICAgICAgICAgICd3b3JrZmxvdy5yb3V0ZS5nZXRfd29ybGRfaGFuZGxlcnMnLFxuICAgICAgICAgICAgICBhc3luYyAoKSA9PiBnZXRXb3JsZEhhbmRsZXJzKClcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm4gaGFuZGxlcih3b3JsZEhhbmRsZXJzKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgY2FjaGVkSGFuZGxlcihyZXEpO1xuICAgICAgICBpZiAocmVzcG9uc2UgaW5zdGFuY2VvZiBSZXNwb25zZSkge1xuICAgICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoXG4gICAgICAgICAgICBBdHRyaWJ1dGUuSHR0cFJlc3BvbnNlU3RhdHVzQ29kZShyZXNwb25zZS5zdGF0dXMpXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzcG9uc2U7XG4gICAgICB9XG4gICAgKTtcbiAgfSk7XG59XG4iXX0=