@jax-data-science/sci-image-visualizer 0.8.3 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (525) hide show
  1. package/README.md +201 -460
  2. package/esm2022/index.mjs +28 -15
  3. package/esm2022/lib/channel-histogram/channel-histogram.component.mjs +163 -91
  4. package/esm2022/lib/contracts/capabilities.contract.mjs +4 -3
  5. package/esm2022/lib/contracts/cell-segmenter.contract.mjs +1 -1
  6. package/esm2022/lib/contracts/channel-histogram-api.contract.mjs +5 -1
  7. package/esm2022/lib/contracts/color.mjs +60 -0
  8. package/esm2022/lib/contracts/colormap-lut.mjs +213 -57
  9. package/esm2022/lib/contracts/coordinate-transform.contract.mjs +1 -1
  10. package/esm2022/lib/contracts/display-types.mjs +11 -1
  11. package/esm2022/lib/contracts/instance-segmenter.contract.mjs +1 -1
  12. package/esm2022/lib/contracts/intensity.mjs +48 -5
  13. package/esm2022/lib/contracts/plot-type-contribution.contract.mjs +1 -1
  14. package/esm2022/lib/contracts/plot-type.mjs +134 -17
  15. package/esm2022/lib/contracts/ports/image-state.port.mjs +4 -1
  16. package/esm2022/lib/contracts/ports/preferences.port.mjs +5 -1
  17. package/esm2022/lib/contracts/ports/region-io.port.mjs +2 -1
  18. package/esm2022/lib/contracts/ports/spatial-data.port.mjs +5 -1
  19. package/esm2022/lib/contracts/ports/tile-access.port.mjs +2 -1
  20. package/esm2022/lib/contracts/region-editor-api.contract.mjs +1 -1
  21. package/esm2022/lib/contracts/region-overlay.contract.mjs +1 -1
  22. package/esm2022/lib/contracts/sam.contract.mjs +1 -1
  23. package/esm2022/lib/contracts/semantic-segmenter.contract.mjs +1 -1
  24. package/esm2022/lib/contracts/spatial-dataset.contract.mjs +3 -1
  25. package/esm2022/lib/contracts/toolbar-tool.contract.mjs +6 -4
  26. package/esm2022/lib/contracts/visualizer.contract.mjs +1 -1
  27. package/esm2022/lib/contracts/viz-config.mjs +2 -1
  28. package/esm2022/lib/geometry/contour.mjs +63 -0
  29. package/esm2022/lib/geometry/raster.mjs +98 -0
  30. package/esm2022/lib/geometry/ring.mjs +201 -0
  31. package/esm2022/lib/hex-color-picker/hex-color-picker.component.mjs +202 -102
  32. package/esm2022/lib/implementations/base-store-visualizer.mjs +201 -48
  33. package/esm2022/lib/implementations/napari-js/napari-axes-gizmo.mjs +65 -0
  34. package/esm2022/lib/implementations/napari-js/napari-display-state.mjs +136 -0
  35. package/esm2022/lib/implementations/napari-js/napari-helpers.mjs +199 -0
  36. package/esm2022/lib/implementations/napari-js/napari-image-2d-scene.mjs +602 -0
  37. package/esm2022/lib/implementations/napari-js/napari-loading-badge.mjs +3 -4
  38. package/esm2022/lib/implementations/napari-js/napari-loading-state.mjs +66 -0
  39. package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +157 -591
  40. package/esm2022/lib/implementations/napari-js/napari-scene.mjs +2 -0
  41. package/esm2022/lib/implementations/napari-js/napari-spatial-2d-scene.mjs +614 -0
  42. package/esm2022/lib/implementations/napari-js/napari-spatial-3d-scene.mjs +769 -0
  43. package/esm2022/lib/implementations/napari-js/napari-spatial-encoding.mjs +199 -0
  44. package/esm2022/lib/implementations/napari-js/napari-spatial-hover.mjs +263 -0
  45. package/esm2022/lib/implementations/napari-js/napari-spatial-scene.mjs +159 -0
  46. package/esm2022/lib/implementations/napari-js/napari-spatial-tiles.mjs +106 -1408
  47. package/esm2022/lib/implementations/napari-js/napari-spatial-tooltip.mjs +2 -2
  48. package/esm2022/lib/implementations/napari-js/napari-surface-scene.mjs +271 -0
  49. package/esm2022/lib/implementations/napari-js/napari-tile-client.mjs +562 -0
  50. package/esm2022/lib/implementations/napari-js/napari-tool-bridge.mjs +344 -0
  51. package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +358 -4218
  52. package/esm2022/lib/implementations/napari-js/napari-volume-scene.mjs +439 -0
  53. package/esm2022/lib/implementations/napari-js/napari-volume-z-handle.mjs +6 -6
  54. package/esm2022/lib/implementations/napari-js/region-overlay/overlay-projection.mjs +96 -0
  55. package/esm2022/lib/implementations/napari-js/region-overlay/region-edit.mjs +35 -0
  56. package/esm2022/lib/implementations/napari-js/region-overlay/region-svg-renderer.mjs +182 -0
  57. package/esm2022/lib/implementations/napari-js/spatial-tiles/categorical-lookup.mjs +30 -0
  58. package/esm2022/lib/implementations/napari-js/spatial-tiles/cell-layers.mjs +274 -0
  59. package/esm2022/lib/implementations/napari-js/spatial-tiles/density-layer.mjs +144 -0
  60. package/esm2022/lib/implementations/napari-js/spatial-tiles/layer-groups.mjs +165 -0
  61. package/esm2022/lib/implementations/napari-js/spatial-tiles/plan-context.mjs +78 -0
  62. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-hover.mjs +182 -0
  63. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-jobs.mjs +369 -0
  64. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-layers.mjs +306 -0
  65. package/esm2022/lib/implementations/osd/display-pipeline.mjs +102 -40
  66. package/esm2022/lib/implementations/osd/histogram-sampler.mjs +56 -31
  67. package/esm2022/lib/implementations/osd/openseadragon-viewer-options.mjs +128 -0
  68. package/esm2022/lib/implementations/osd/openseadragon-visualizer.service.mjs +333 -1685
  69. package/esm2022/lib/implementations/osd/osd-coordinate-transform.mjs +1 -1
  70. package/esm2022/lib/implementations/osd/osd-coords.mjs +5 -6
  71. package/esm2022/lib/implementations/osd/osd-export.mjs +122 -0
  72. package/esm2022/lib/implementations/osd/osd-lib.mjs +15 -1
  73. package/esm2022/lib/implementations/osd/osd-navigator-chrome.mjs +205 -0
  74. package/esm2022/lib/implementations/osd/osd-pixel-readback.mjs +68 -0
  75. package/esm2022/lib/implementations/osd/osd-region-overlay-draw.mjs +153 -0
  76. package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +185 -718
  77. package/esm2022/lib/implementations/osd/osd-scale-bar.mjs +52 -60
  78. package/esm2022/lib/implementations/osd/osd-tile-source.mjs +105 -0
  79. package/esm2022/lib/implementations/osd/osd-viewer-like.mjs +2 -0
  80. package/esm2022/lib/implementations/osd/osd-viewer-mount.mjs +44 -0
  81. package/esm2022/lib/implementations/osd/osd-viewport.mjs +184 -0
  82. package/esm2022/lib/implementations/osd/osd-zoom.mjs +7 -1
  83. package/esm2022/lib/implementations/osd/simple-source.mjs +395 -0
  84. package/esm2022/lib/implementations/osd/slice-cache.mjs +53 -48
  85. package/esm2022/lib/implementations/osd/tile-client.mjs +32 -11
  86. package/esm2022/lib/implementations/osd/tile-recolor.mjs +330 -0
  87. package/esm2022/lib/implementations/plotly/omics-trace-builders.mjs +161 -73
  88. package/esm2022/lib/implementations/plotly/plotly-coordinate-transform.mjs +1 -1
  89. package/esm2022/lib/implementations/plotly/plotly-image-loader.mjs +112 -0
  90. package/esm2022/lib/implementations/plotly/plotly-image-recolor.mjs +178 -0
  91. package/esm2022/lib/implementations/plotly/plotly-intensity-inset.mjs +33 -0
  92. package/esm2022/lib/implementations/plotly/plotly-isosurface-controls.mjs +83 -0
  93. package/esm2022/lib/implementations/plotly/plotly-layouts.mjs +121 -0
  94. package/esm2022/lib/implementations/plotly/plotly-readback.mjs +117 -0
  95. package/esm2022/lib/implementations/plotly/plotly-region-overlay.mjs +19 -10
  96. package/esm2022/lib/implementations/plotly/plotly-shape-projection.mjs +223 -0
  97. package/esm2022/lib/implementations/plotly/plotly-trace-builders.mjs +79 -19
  98. package/esm2022/lib/implementations/plotly/plotly-zoom-controller.mjs +223 -0
  99. package/esm2022/lib/implementations/plotly/plotly.service.mjs +439 -1655
  100. package/esm2022/lib/implementations/region-centroids.mjs +47 -0
  101. package/esm2022/lib/implementations/simple-slice-access.service.mjs +22 -12
  102. package/esm2022/lib/implementations/spatial-data-http/spatial-data-http.service.mjs +172 -92
  103. package/esm2022/lib/implementations/spatial-data-http/spatial-wire.mjs +103 -22
  104. package/esm2022/lib/implementations/tile-server/index.mjs +6 -0
  105. package/esm2022/lib/implementations/tile-server/native-histogram.mjs +30 -0
  106. package/esm2022/lib/implementations/tile-server/poll-descriptor.mjs +65 -0
  107. package/esm2022/lib/implementations/tile-server/tile-protocol.mjs +42 -0
  108. package/esm2022/lib/implementations/tile-server/transport.mjs +135 -0
  109. package/esm2022/lib/intensity/intensity-profile.mjs +107 -0
  110. package/esm2022/lib/intensity/intensity-profile.service.mjs +223 -0
  111. package/esm2022/lib/intensity-inset/intensity-inset.component.mjs +133 -0
  112. package/esm2022/lib/models/bezier.mjs +1 -11
  113. package/esm2022/lib/models/class-preset.mjs +41 -3
  114. package/esm2022/lib/models/geometry.mjs +27 -164
  115. package/esm2022/lib/models/polygon-edit.mjs +254 -0
  116. package/esm2022/lib/models/polygon-factory.mjs +118 -0
  117. package/esm2022/lib/models/region-clone.mjs +68 -0
  118. package/esm2022/lib/models/region-geojson.mjs +373 -0
  119. package/esm2022/lib/models/region.mjs +34 -33
  120. package/esm2022/lib/models/shape.mjs +18 -16
  121. package/esm2022/lib/plot-mode/contribution-host.mjs +297 -0
  122. package/esm2022/lib/plot-mode/plot-mode-controller.mjs +9 -6
  123. package/esm2022/lib/plot-mode/plot-type-menu.mjs +85 -0
  124. package/esm2022/lib/plot-mode/tool-params-model.mjs +87 -0
  125. package/esm2022/lib/plot.utilities.mjs +296 -473
  126. package/esm2022/lib/processing/image-crop.mjs +1 -1
  127. package/esm2022/lib/processing/processing-image.mjs +28 -15
  128. package/esm2022/lib/provide-visualization.mjs +40 -14
  129. package/esm2022/lib/region-editor/classes-panel/classes-panel.component.mjs +99 -0
  130. package/esm2022/lib/region-editor/file-stem.mjs +13 -0
  131. package/esm2022/lib/region-editor/manage-classes-dialog/manage-classes-dialog.component.mjs +118 -0
  132. package/esm2022/lib/region-editor/mask-export.service.mjs +98 -0
  133. package/esm2022/lib/region-editor/mask-raster.mjs +11 -5
  134. package/esm2022/lib/region-editor/region-color-dialog/region-color-dialog.component.mjs +56 -0
  135. package/esm2022/lib/region-editor/region-editor-help/region-editor-help.component.mjs +28 -0
  136. package/esm2022/lib/region-editor/region-editor.component.mjs +402 -651
  137. package/esm2022/lib/region-editor/region-metrics.mjs +68 -0
  138. package/esm2022/lib/region-editor/region-persistence.service.mjs +134 -0
  139. package/esm2022/lib/region-editor/region-table/region-table.component.mjs +153 -0
  140. package/esm2022/lib/region-editor/save-mask-dialog/save-mask-dialog.component.mjs +91 -0
  141. package/esm2022/lib/region-editor/save-regions-dialog/save-regions-dialog.component.mjs +92 -0
  142. package/esm2022/lib/region-ops.service.mjs +28 -70
  143. package/esm2022/lib/region-overlay/region-geometry.mjs +360 -0
  144. package/esm2022/lib/region-overlay/region-hit-test.mjs +103 -0
  145. package/esm2022/lib/region-overlay/svg-region-renderer.mjs +228 -0
  146. package/esm2022/lib/render-orchestrator.mjs +14 -11
  147. package/esm2022/lib/render-session.mjs +207 -0
  148. package/esm2022/lib/routing-visualizer.service.mjs +459 -411
  149. package/esm2022/lib/spatial/density-raster.mjs +14 -0
  150. package/esm2022/lib/spatial/embedding-compute-coordinator.mjs +239 -0
  151. package/esm2022/lib/spatial/embedding-compute.mjs +43 -10
  152. package/esm2022/lib/spatial/gene-search.mjs +1 -1
  153. package/esm2022/lib/spatial/glyphs.mjs +97 -0
  154. package/esm2022/lib/spatial/lod.mjs +187 -0
  155. package/esm2022/lib/spatial/spatial-controls.facade.mjs +200 -0
  156. package/esm2022/lib/spatial/spatial-density.mjs +25 -16
  157. package/esm2022/lib/spatial/spatial-encoding.mjs +26 -82
  158. package/esm2022/lib/spatial/spatial-expression.mjs +43 -42
  159. package/esm2022/lib/spatial/spatial-framing.mjs +1 -1
  160. package/esm2022/lib/spatial/spatial-heatmap.mjs +6 -3
  161. package/esm2022/lib/spatial/spatial-hover.mjs +5 -33
  162. package/esm2022/lib/spatial/spatial-panel-model.mjs +282 -0
  163. package/esm2022/lib/spatial/spatial-sections.mjs +1 -1
  164. package/esm2022/lib/spatial/spatial-selection.mjs +33 -46
  165. package/esm2022/lib/spatial/spatial-tile-merge.mjs +219 -0
  166. package/esm2022/lib/spatial/spatial-tiles.mjs +12 -648
  167. package/esm2022/lib/spatial/spatial-volume-image.mjs +2 -4
  168. package/esm2022/lib/spatial/stats.mjs +71 -0
  169. package/esm2022/lib/spatial/transcript-grouping.mjs +307 -0
  170. package/esm2022/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.mjs +150 -0
  171. package/esm2022/lib/spatial-controls/spatial-charts/chart-data-model.mjs +309 -0
  172. package/esm2022/lib/spatial-controls/spatial-charts/chart-help.mjs +145 -0
  173. package/esm2022/lib/spatial-controls/spatial-charts/plotly-chart-host.mjs +158 -0
  174. package/esm2022/lib/spatial-controls/spatial-charts/spatial-chart-window/spatial-chart-window.component.mjs +47 -0
  175. package/esm2022/lib/spatial-controls/spatial-charts/spatial-charts.component.mjs +297 -802
  176. package/esm2022/lib/spatial-controls/spatial-charts/spatial-embedding-controls/spatial-embedding-controls.component.mjs +89 -0
  177. package/esm2022/lib/spatial-controls/spatial-charts/spatial-heatmap-controls/spatial-heatmap-controls.component.mjs +52 -0
  178. package/esm2022/lib/spatial-controls/spatial-controls.component.mjs +143 -1238
  179. package/esm2022/lib/spatial-controls/spatial-gene-picker.mjs +153 -0
  180. package/esm2022/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.mjs +241 -0
  181. package/esm2022/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.mjs +193 -0
  182. package/esm2022/lib/spatial-controls/spatial-key/spatial-key.component.mjs +132 -0
  183. package/esm2022/lib/spatial-controls/spatial-key/spatial-key.model.mjs +67 -0
  184. package/esm2022/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.mjs +147 -0
  185. package/esm2022/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.mjs +300 -0
  186. package/esm2022/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.mjs +370 -0
  187. package/esm2022/lib/store/class-color.util.mjs +46 -3
  188. package/esm2022/lib/store/region-history.mjs +146 -0
  189. package/esm2022/lib/store/region-scope-cache.mjs +140 -0
  190. package/esm2022/lib/store/region-selection.mjs +82 -0
  191. package/esm2022/lib/store/region-store.service.mjs +279 -675
  192. package/esm2022/lib/store/spatial-selection.service.mjs +2 -2
  193. package/esm2022/lib/store/visualizer-store.service.mjs +49 -71
  194. package/esm2022/lib/toast-outlets.mjs +5 -4
  195. package/esm2022/lib/toolbar/brush/brush-tool.service.mjs +92 -434
  196. package/esm2022/lib/toolbar/canvas-tools.mjs +20 -0
  197. package/esm2022/lib/toolbar/crop/slide-crop.mjs +26 -42
  198. package/esm2022/lib/toolbar/plot-type-selector/plot-type-selector.component.mjs +85 -0
  199. package/esm2022/lib/toolbar/region-tools/region-tool-buttons.mjs +74 -0
  200. package/esm2022/lib/toolbar/region-tools/region-tools.component.mjs +114 -0
  201. package/esm2022/lib/toolbar/segmentation/cell-segment-tool.service.mjs +74 -78
  202. package/esm2022/lib/toolbar/segmentation/cellpose-segmenter.service.mjs +50 -8
  203. package/esm2022/lib/toolbar/segmentation/onnx-sam-session.mjs +61 -42
  204. package/esm2022/lib/toolbar/segmentation/pending-calls.mjs +47 -0
  205. package/esm2022/lib/toolbar/segmentation/sam-model-registry.mjs +12 -4
  206. package/esm2022/lib/toolbar/segmentation/sam-onnx-core.mjs +70 -14
  207. package/esm2022/lib/toolbar/segmentation/sam-point-tool.service.mjs +135 -172
  208. package/esm2022/lib/toolbar/segmentation/sam-prompt.mjs +9 -90
  209. package/esm2022/lib/toolbar/segmentation/sam-session.service.mjs +183 -0
  210. package/esm2022/lib/toolbar/segmentation/sam-tool.service.mjs +95 -150
  211. package/esm2022/lib/toolbar/segmentation/segmentation-commit.mjs +12 -0
  212. package/esm2022/lib/toolbar/segmentation/segmentation-runner.mjs +108 -0
  213. package/esm2022/lib/toolbar/segmentation-tools/segmentation-tools.component.mjs +155 -0
  214. package/esm2022/lib/toolbar/stack-controls/stack-controls.component.mjs +81 -0
  215. package/esm2022/lib/toolbar/tool-kit/async-tool-status.mjs +37 -0
  216. package/esm2022/lib/toolbar/tool-kit/canvas-tool-manager.mjs +63 -0
  217. package/esm2022/lib/toolbar/tool-kit/canvas-tool.mjs +2 -0
  218. package/esm2022/lib/toolbar/tool-kit/frame-pixels.mjs +108 -0
  219. package/esm2022/lib/toolbar/tool-kit/mask-stroke-editor.mjs +306 -0
  220. package/esm2022/lib/toolbar/tool-kit/matrix-frame.mjs +61 -0
  221. package/esm2022/lib/toolbar/tool-kit/tool-overlay.mjs +140 -0
  222. package/esm2022/lib/toolbar/tool-kit/undo-gesture.mjs +24 -0
  223. package/esm2022/lib/toolbar/tool-slider/tool-slider.component.mjs +63 -0
  224. package/esm2022/lib/toolbar/toolbar-help-dialog/toolbar-help-dialog.component.mjs +50 -0
  225. package/esm2022/lib/toolbar/toolbar.component.mjs +68 -117
  226. package/esm2022/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.mjs +93 -115
  227. package/esm2022/lib/toolbar/view-controls/view-controls.component.mjs +107 -0
  228. package/esm2022/lib/toolbar/wand/wand-region-grow.mjs +321 -0
  229. package/esm2022/lib/toolbar/wand/wand-tool.service.mjs +121 -416
  230. package/esm2022/lib/toolbar/wand/wand.service.mjs +30 -894
  231. package/esm2022/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.mjs +48 -90
  232. package/esm2022/lib/util/mark-for-check.mjs +17 -0
  233. package/esm2022/lib/util/supersede.mjs +56 -0
  234. package/esm2022/lib/visualization.module.mjs +39 -141
  235. package/esm2022/lib/visualizer/floating-drag.directive.mjs +58 -0
  236. package/esm2022/lib/visualizer/region-actions.mjs +149 -0
  237. package/esm2022/lib/visualizer/region-load.mjs +60 -0
  238. package/esm2022/lib/visualizer/spatial-dataset-binder.mjs +163 -0
  239. package/esm2022/lib/visualizer/tool-modes.mjs +113 -0
  240. package/esm2022/lib/visualizer/viewer-shortcuts.mjs +167 -0
  241. package/esm2022/lib/visualizer/visualizer-context-menu.mjs +119 -0
  242. package/esm2022/lib/visualizer.component.mjs +480 -1902
  243. package/esm2022/lib/workers/spatial-math-ops.mjs +43 -0
  244. package/esm2022/lib/workers/spatial-math-worker.mjs +10 -0
  245. package/esm2022/lib/workers/spatial-math.mjs +190 -0
  246. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-Csxlnq7I.mjs +41083 -0
  247. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-Csxlnq7I.mjs.map +1 -0
  248. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-Bkujqg7m.mjs +238 -0
  249. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-Bkujqg7m.mjs.map +1 -0
  250. package/fesm2022/jax-data-science-sci-image-visualizer-spatial-math-worker-BzVFFqGS.mjs +12 -0
  251. package/fesm2022/jax-data-science-sci-image-visualizer-spatial-math-worker-BzVFFqGS.mjs.map +1 -0
  252. package/fesm2022/jax-data-science-sci-image-visualizer.mjs +41 -34467
  253. package/fesm2022/jax-data-science-sci-image-visualizer.mjs.map +1 -1
  254. package/fesm2022/mask.worker.js +36 -917
  255. package/fesm2022/onnx-sam.worker.js +52 -16
  256. package/fesm2022/spatial-math.worker.js +471 -0
  257. package/fesm2022/tsne.worker.js +32 -15
  258. package/index.d.ts +13 -10
  259. package/lib/channel-histogram/channel-histogram.component.d.ts +53 -43
  260. package/lib/contracts/capabilities.contract.d.ts +4 -2
  261. package/lib/contracts/cell-segmenter.contract.d.ts +1 -0
  262. package/lib/contracts/channel-histogram-api.contract.d.ts +4 -0
  263. package/lib/contracts/color.d.ts +27 -0
  264. package/lib/contracts/colormap-lut.d.ts +19 -4
  265. package/lib/contracts/coordinate-transform.contract.d.ts +3 -3
  266. package/lib/contracts/display-types.d.ts +21 -0
  267. package/lib/contracts/instance-segmenter.contract.d.ts +5 -0
  268. package/lib/contracts/intensity.d.ts +13 -2
  269. package/lib/contracts/plot-type.d.ts +3 -1
  270. package/lib/contracts/ports/image-state.port.d.ts +6 -2
  271. package/lib/contracts/ports/preferences.port.d.ts +4 -0
  272. package/lib/contracts/ports/region-io.port.d.ts +1 -0
  273. package/lib/contracts/ports/spatial-data.port.d.ts +4 -10
  274. package/lib/contracts/ports/tile-access.port.d.ts +1 -0
  275. package/lib/contracts/region-editor-api.contract.d.ts +1 -1
  276. package/lib/contracts/region-overlay.contract.d.ts +5 -0
  277. package/lib/contracts/sam.contract.d.ts +7 -0
  278. package/lib/contracts/semantic-segmenter.contract.d.ts +6 -0
  279. package/lib/contracts/spatial-dataset.contract.d.ts +19 -6
  280. package/lib/contracts/toolbar-tool.contract.d.ts +1 -0
  281. package/lib/contracts/visualizer.contract.d.ts +221 -54
  282. package/lib/contracts/viz-config.d.ts +1 -0
  283. package/lib/geometry/contour.d.ts +24 -0
  284. package/lib/geometry/raster.d.ts +42 -0
  285. package/lib/geometry/ring.d.ts +67 -0
  286. package/lib/hex-color-picker/hex-color-picker.component.d.ts +61 -27
  287. package/lib/implementations/base-store-visualizer.d.ts +61 -15
  288. package/lib/implementations/napari-js/napari-axes-gizmo.d.ts +36 -0
  289. package/lib/implementations/napari-js/napari-display-state.d.ts +76 -0
  290. package/lib/implementations/napari-js/napari-helpers.d.ts +129 -0
  291. package/lib/implementations/napari-js/napari-image-2d-scene.d.ts +162 -0
  292. package/lib/implementations/napari-js/napari-loading-badge.d.ts +0 -1
  293. package/lib/implementations/napari-js/napari-loading-state.d.ts +30 -0
  294. package/lib/implementations/napari-js/napari-region-overlay.d.ts +62 -70
  295. package/lib/implementations/napari-js/napari-scene.d.ts +93 -0
  296. package/lib/implementations/napari-js/napari-spatial-2d-scene.d.ts +163 -0
  297. package/lib/implementations/napari-js/napari-spatial-3d-scene.d.ts +212 -0
  298. package/lib/implementations/napari-js/napari-spatial-encoding.d.ts +114 -0
  299. package/lib/implementations/napari-js/napari-spatial-hover.d.ts +89 -0
  300. package/lib/implementations/napari-js/napari-spatial-scene.d.ts +118 -0
  301. package/lib/implementations/napari-js/napari-spatial-tiles.d.ts +56 -263
  302. package/lib/implementations/napari-js/napari-spatial-tooltip.d.ts +1 -1
  303. package/lib/implementations/napari-js/napari-surface-scene.d.ts +76 -0
  304. package/lib/implementations/napari-js/napari-tile-client.d.ts +214 -0
  305. package/lib/implementations/napari-js/napari-tool-bridge.d.ts +179 -0
  306. package/lib/implementations/napari-js/napari-visualizer.service.d.ts +121 -883
  307. package/lib/implementations/napari-js/napari-volume-scene.d.ts +104 -0
  308. package/lib/implementations/napari-js/napari-volume-z-handle.d.ts +8 -12
  309. package/lib/implementations/napari-js/region-overlay/overlay-projection.d.ts +59 -0
  310. package/lib/implementations/napari-js/region-overlay/region-edit.d.ts +15 -0
  311. package/lib/implementations/napari-js/region-overlay/region-svg-renderer.d.ts +54 -0
  312. package/lib/implementations/napari-js/spatial-tiles/categorical-lookup.d.ts +26 -0
  313. package/lib/implementations/napari-js/spatial-tiles/cell-layers.d.ts +70 -0
  314. package/lib/implementations/napari-js/spatial-tiles/density-layer.d.ts +61 -0
  315. package/lib/implementations/napari-js/spatial-tiles/layer-groups.d.ts +67 -0
  316. package/lib/implementations/napari-js/spatial-tiles/plan-context.d.ts +38 -0
  317. package/lib/implementations/napari-js/spatial-tiles/transcript-hover.d.ts +71 -0
  318. package/lib/implementations/napari-js/spatial-tiles/transcript-jobs.d.ts +105 -0
  319. package/lib/implementations/napari-js/spatial-tiles/transcript-layers.d.ts +56 -0
  320. package/lib/implementations/osd/display-pipeline.d.ts +38 -9
  321. package/lib/implementations/osd/histogram-sampler.d.ts +22 -12
  322. package/lib/implementations/osd/openseadragon-viewer-options.d.ts +35 -0
  323. package/lib/implementations/osd/openseadragon-visualizer.service.d.ts +78 -354
  324. package/lib/implementations/osd/osd-coordinate-transform.d.ts +2 -1
  325. package/lib/implementations/osd/osd-coords.d.ts +6 -4
  326. package/lib/implementations/osd/osd-export.d.ts +36 -0
  327. package/lib/implementations/osd/osd-lib.d.ts +7 -0
  328. package/lib/implementations/osd/osd-navigator-chrome.d.ts +69 -0
  329. package/lib/implementations/osd/osd-pixel-readback.d.ts +22 -0
  330. package/lib/implementations/osd/osd-region-overlay-draw.d.ts +37 -0
  331. package/lib/implementations/osd/osd-region-overlay.d.ts +36 -48
  332. package/lib/implementations/osd/osd-scale-bar.d.ts +8 -6
  333. package/lib/implementations/osd/osd-tile-source.d.ts +49 -0
  334. package/lib/implementations/osd/osd-viewer-like.d.ts +100 -0
  335. package/lib/implementations/osd/osd-viewer-mount.d.ts +14 -0
  336. package/lib/implementations/osd/osd-viewport.d.ts +77 -0
  337. package/lib/implementations/osd/osd-zoom.d.ts +6 -0
  338. package/lib/implementations/osd/simple-source.d.ts +161 -0
  339. package/lib/implementations/osd/slice-cache.d.ts +12 -3
  340. package/lib/implementations/osd/tile-client.d.ts +11 -14
  341. package/lib/implementations/osd/tile-recolor.d.ts +141 -0
  342. package/lib/implementations/plotly/omics-trace-builders.d.ts +32 -20
  343. package/lib/implementations/plotly/plotly-image-loader.d.ts +49 -0
  344. package/lib/implementations/plotly/plotly-image-recolor.d.ts +75 -0
  345. package/lib/implementations/plotly/plotly-intensity-inset.d.ts +8 -0
  346. package/lib/implementations/plotly/plotly-isosurface-controls.d.ts +38 -0
  347. package/lib/implementations/plotly/plotly-layouts.d.ts +188 -0
  348. package/lib/implementations/plotly/plotly-readback.d.ts +41 -0
  349. package/lib/implementations/plotly/plotly-region-overlay.d.ts +2 -2
  350. package/lib/implementations/plotly/plotly-shape-projection.d.ts +92 -0
  351. package/lib/implementations/plotly/plotly-trace-builders.d.ts +23 -12
  352. package/lib/implementations/plotly/plotly-zoom-controller.d.ts +86 -0
  353. package/lib/implementations/plotly/plotly.service.d.ts +136 -401
  354. package/lib/implementations/region-centroids.d.ts +14 -0
  355. package/lib/implementations/simple-slice-access.service.d.ts +7 -4
  356. package/lib/implementations/spatial-data-http/spatial-data-http.service.d.ts +42 -18
  357. package/lib/implementations/spatial-data-http/spatial-wire.d.ts +34 -9
  358. package/lib/implementations/tile-server/index.d.ts +5 -0
  359. package/lib/implementations/tile-server/native-histogram.d.ts +25 -0
  360. package/lib/implementations/tile-server/poll-descriptor.d.ts +39 -0
  361. package/lib/implementations/tile-server/tile-protocol.d.ts +80 -0
  362. package/lib/implementations/tile-server/transport.d.ts +62 -0
  363. package/lib/intensity/intensity-profile.d.ts +66 -0
  364. package/lib/intensity/intensity-profile.service.d.ts +108 -0
  365. package/lib/intensity-inset/intensity-inset.component.d.ts +58 -0
  366. package/lib/models/bezier.d.ts +0 -5
  367. package/lib/models/class-preset.d.ts +18 -0
  368. package/lib/models/geometry.d.ts +14 -48
  369. package/lib/models/polygon-edit.d.ts +72 -0
  370. package/lib/models/polygon-factory.d.ts +40 -0
  371. package/lib/models/region-clone.d.ts +20 -0
  372. package/lib/models/region-geojson.d.ts +17 -0
  373. package/lib/models/region.d.ts +40 -4
  374. package/lib/models/shape.d.ts +8 -0
  375. package/lib/plot-mode/contribution-host.d.ts +125 -0
  376. package/lib/plot-mode/plot-type-menu.d.ts +60 -0
  377. package/lib/plot-mode/tool-params-model.d.ts +49 -0
  378. package/lib/plot.utilities.d.ts +19 -30
  379. package/lib/processing/processing-image.d.ts +5 -2
  380. package/lib/provide-visualization.d.ts +19 -2
  381. package/lib/region-editor/classes-panel/classes-panel.component.d.ts +56 -0
  382. package/lib/region-editor/file-stem.d.ts +7 -0
  383. package/lib/region-editor/manage-classes-dialog/manage-classes-dialog.component.d.ts +45 -0
  384. package/lib/region-editor/mask-export.service.d.ts +54 -0
  385. package/lib/region-editor/mask-raster.d.ts +2 -8
  386. package/lib/region-editor/region-color-dialog/region-color-dialog.component.d.ts +29 -0
  387. package/lib/region-editor/region-editor-help/region-editor-help.component.d.ts +11 -0
  388. package/lib/region-editor/region-editor.component.d.ts +166 -199
  389. package/lib/region-editor/region-metrics.d.ts +26 -0
  390. package/lib/region-editor/region-persistence.service.d.ts +69 -0
  391. package/lib/region-editor/region-table/region-table.component.d.ts +83 -0
  392. package/lib/region-editor/save-mask-dialog/save-mask-dialog.component.d.ts +36 -0
  393. package/lib/region-editor/save-regions-dialog/save-regions-dialog.component.d.ts +37 -0
  394. package/lib/region-ops.service.d.ts +1 -7
  395. package/lib/region-overlay/region-geometry.d.ts +157 -0
  396. package/lib/region-overlay/region-hit-test.d.ts +38 -0
  397. package/lib/region-overlay/svg-region-renderer.d.ts +110 -0
  398. package/lib/render-orchestrator.d.ts +6 -2
  399. package/lib/render-session.d.ts +75 -0
  400. package/lib/routing-visualizer.service.d.ts +110 -58
  401. package/lib/spatial/density-raster.d.ts +6 -0
  402. package/lib/spatial/embedding-compute-coordinator.d.ts +123 -0
  403. package/lib/spatial/embedding-compute.d.ts +21 -2
  404. package/lib/spatial/glyphs.d.ts +16 -0
  405. package/lib/spatial/lod.d.ts +94 -0
  406. package/lib/spatial/spatial-controls.facade.d.ts +64 -0
  407. package/lib/spatial/spatial-density.d.ts +15 -5
  408. package/lib/spatial/spatial-encoding.d.ts +11 -44
  409. package/lib/spatial/spatial-expression.d.ts +40 -22
  410. package/lib/spatial/spatial-framing.d.ts +1 -0
  411. package/lib/spatial/spatial-heatmap.d.ts +2 -0
  412. package/lib/spatial/spatial-hover.d.ts +4 -16
  413. package/lib/spatial/spatial-panel-model.d.ts +135 -0
  414. package/lib/spatial/spatial-selection.d.ts +21 -26
  415. package/lib/spatial/spatial-tile-merge.d.ts +41 -0
  416. package/lib/spatial/spatial-tiles.d.ts +9 -256
  417. package/lib/spatial/stats.d.ts +38 -0
  418. package/lib/spatial/transcript-grouping.d.ts +119 -0
  419. package/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.d.ts +64 -0
  420. package/lib/spatial-controls/spatial-charts/chart-data-model.d.ts +153 -0
  421. package/lib/spatial-controls/spatial-charts/chart-help.d.ts +69 -0
  422. package/lib/spatial-controls/spatial-charts/plotly-chart-host.d.ts +98 -0
  423. package/lib/spatial-controls/spatial-charts/spatial-chart-window/spatial-chart-window.component.d.ts +26 -0
  424. package/lib/spatial-controls/spatial-charts/spatial-charts.component.d.ts +101 -260
  425. package/lib/spatial-controls/spatial-charts/spatial-embedding-controls/spatial-embedding-controls.component.d.ts +43 -0
  426. package/lib/spatial-controls/spatial-charts/spatial-heatmap-controls/spatial-heatmap-controls.component.d.ts +27 -0
  427. package/lib/spatial-controls/spatial-controls.component.d.ts +68 -448
  428. package/lib/spatial-controls/spatial-gene-picker.d.ts +86 -0
  429. package/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.d.ts +102 -0
  430. package/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.d.ts +72 -0
  431. package/lib/spatial-controls/spatial-key/spatial-key.component.d.ts +66 -0
  432. package/lib/spatial-controls/spatial-key/spatial-key.model.d.ts +33 -0
  433. package/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.d.ts +64 -0
  434. package/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.d.ts +117 -0
  435. package/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.d.ts +142 -0
  436. package/lib/store/class-color.util.d.ts +35 -1
  437. package/lib/store/region-history.d.ts +66 -0
  438. package/lib/store/region-scope-cache.d.ts +63 -0
  439. package/lib/store/region-selection.d.ts +36 -0
  440. package/lib/store/region-store.service.d.ts +104 -112
  441. package/lib/store/visualizer-store.service.d.ts +22 -33
  442. package/lib/toast-outlets.d.ts +4 -3
  443. package/lib/toolbar/brush/brush-tool.service.d.ts +31 -98
  444. package/lib/toolbar/canvas-tools.d.ts +20 -0
  445. package/lib/toolbar/crop/slide-crop.d.ts +10 -4
  446. package/lib/toolbar/plot-type-selector/plot-type-selector.component.d.ts +38 -0
  447. package/lib/toolbar/region-tools/region-tool-buttons.d.ts +21 -0
  448. package/lib/toolbar/region-tools/region-tools.component.d.ts +60 -0
  449. package/lib/toolbar/segmentation/cell-segment-tool.service.d.ts +10 -14
  450. package/lib/toolbar/segmentation/cellpose-segmenter.service.d.ts +12 -2
  451. package/lib/toolbar/segmentation/onnx-sam-session.d.ts +22 -3
  452. package/lib/toolbar/segmentation/pending-calls.d.ts +31 -0
  453. package/lib/toolbar/segmentation/sam-model-registry.d.ts +9 -3
  454. package/lib/toolbar/segmentation/sam-onnx-core.d.ts +18 -5
  455. package/lib/toolbar/segmentation/sam-point-tool.service.d.ts +46 -32
  456. package/lib/toolbar/segmentation/sam-prompt.d.ts +7 -31
  457. package/lib/toolbar/segmentation/sam-session.service.d.ts +74 -0
  458. package/lib/toolbar/segmentation/sam-tool.service.d.ts +23 -30
  459. package/lib/toolbar/segmentation/segmentation-commit.d.ts +8 -0
  460. package/lib/toolbar/segmentation/segmentation-runner.d.ts +52 -0
  461. package/lib/toolbar/segmentation-tools/segmentation-tools.component.d.ts +87 -0
  462. package/lib/toolbar/stack-controls/stack-controls.component.d.ts +40 -0
  463. package/lib/toolbar/tool-kit/async-tool-status.d.ts +21 -0
  464. package/lib/toolbar/tool-kit/canvas-tool-manager.d.ts +36 -0
  465. package/lib/toolbar/tool-kit/canvas-tool.d.ts +86 -0
  466. package/lib/toolbar/tool-kit/frame-pixels.d.ts +45 -0
  467. package/lib/toolbar/tool-kit/mask-stroke-editor.d.ts +125 -0
  468. package/lib/toolbar/tool-kit/matrix-frame.d.ts +40 -0
  469. package/lib/toolbar/tool-kit/tool-overlay.d.ts +60 -0
  470. package/lib/toolbar/tool-kit/undo-gesture.d.ts +17 -0
  471. package/lib/toolbar/tool-slider/tool-slider.component.d.ts +33 -0
  472. package/lib/toolbar/toolbar-help-dialog/toolbar-help-dialog.component.d.ts +24 -0
  473. package/lib/toolbar/toolbar.component.d.ts +47 -83
  474. package/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.d.ts +33 -40
  475. package/lib/toolbar/view-controls/view-controls.component.d.ts +54 -0
  476. package/lib/toolbar/wand/wand-region-grow.d.ts +49 -0
  477. package/lib/toolbar/wand/wand-tool.service.d.ts +39 -124
  478. package/lib/toolbar/wand/wand.service.d.ts +22 -116
  479. package/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.d.ts +17 -37
  480. package/lib/util/mark-for-check.d.ts +11 -0
  481. package/lib/util/supersede.d.ts +53 -0
  482. package/lib/visualization.module.d.ts +18 -39
  483. package/lib/visualizer/floating-drag.directive.d.ts +30 -0
  484. package/lib/visualizer/region-actions.d.ts +54 -0
  485. package/lib/visualizer/region-load.d.ts +27 -0
  486. package/lib/visualizer/spatial-dataset-binder.d.ts +74 -0
  487. package/lib/visualizer/tool-modes.d.ts +49 -0
  488. package/lib/visualizer/viewer-shortcuts.d.ts +71 -0
  489. package/lib/visualizer/visualizer-context-menu.d.ts +55 -0
  490. package/lib/visualizer.component.d.ts +201 -447
  491. package/lib/workers/spatial-math-ops.d.ts +65 -0
  492. package/lib/workers/spatial-math-worker.d.ts +7 -0
  493. package/lib/workers/spatial-math.d.ts +74 -0
  494. package/package.json +12 -3
  495. package/src/lib/styles/_viz-icons-rules.scss +73 -0
  496. package/src/lib/styles/viz-icons.scss +14 -0
  497. package/esm2022/lib/implementations/napari-js/napari-axes-labels.mjs +0 -97
  498. package/esm2022/lib/implementations/napari-js/napari-navigator.mjs +0 -195
  499. package/esm2022/lib/implementations/napari-js/napari-scale-bar.mjs +0 -92
  500. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-BwP-A11m.mjs +0 -329
  501. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-BwP-A11m.mjs.map +0 -1
  502. package/lib/implementations/napari-js/napari-axes-labels.d.ts +0 -49
  503. package/lib/implementations/napari-js/napari-navigator.d.ts +0 -72
  504. package/lib/implementations/napari-js/napari-scale-bar.d.ts +0 -35
  505. package/src/lib/assets/cell-detection.svg +0 -37
  506. package/src/lib/assets/click.svg +0 -1
  507. package/src/lib/assets/colormap-luts.json +0 -1
  508. package/src/lib/assets/edit-selection-white.svg +0 -47
  509. package/src/lib/assets/icons/colormap-earth.png +0 -0
  510. package/src/lib/assets/icons/colormap-placeholder.png +0 -0
  511. package/src/lib/assets/icons/colormap-pubu.png +0 -0
  512. package/src/lib/assets/interactive-segmentation-cursor.svg +0 -1
  513. package/src/lib/assets/picture-segmentation.svg +0 -43
  514. package/src/lib/assets/test/download-379.svg +0 -1
  515. package/src/lib/assets/test/download-98.svg +0 -1
  516. package/src/lib/assets/test/json-1.svg +0 -1
  517. package/src/lib/assets/test/load-53.svg +0 -1
  518. package/src/lib/assets/test/mask-44.svg +0 -1
  519. package/src/lib/assets/test/mask-download-44.svg +0 -15
  520. package/src/lib/assets/test/mask-save-44.svg +0 -11
  521. package/src/lib/assets/test/overlay-1.svg +0 -1
  522. package/src/lib/assets/test/overlay-4.svg +0 -1
  523. package/src/lib/assets/test/region-26.svg +0 -1
  524. package/src/lib/assets/test/save-56.svg +0 -1
  525. package/src/lib/assets/test/upload-43.svg +0 -1
@@ -1,11 +1,43 @@
1
1
  import { HttpClient } from '@angular/common/http';
2
+ import { LruCache } from 'napari-js';
2
3
  import { Injectable } from '@angular/core';
3
4
  import { BehaviorSubject, firstValueFrom } from 'rxjs';
4
5
  import { timeout } from 'rxjs/operators';
6
+ import { ALL_GENES } from '../../contracts/ports/spatial-data.port';
5
7
  import { findColumnMeta, } from '../../contracts/spatial-dataset.contract';
6
8
  import { assertManifestVersion, datasetFromManifest, decodeColumn, decodeCoords, decodeDensity, decodeEmbedding, decodeFeatureVector, decodePolygonTile, decodePolygons, decodeRadius, decodeTranscriptTile, } from './spatial-wire';
9
+ import { searchGeneNames } from '../../spatial/gene-search';
10
+ import { Supersede } from '../../util/supersede';
7
11
  import * as i0 from "@angular/core";
8
12
  import * as i1 from "@angular/common/http";
13
+ /**
14
+ * A dataset selection that a newer selection (or a `clear`) overtook.
15
+ *
16
+ * Thrown rather than resolved so a caller cannot mistake it for "this dataset is
17
+ * now loaded": nothing was published, on purpose.
18
+ */
19
+ export class SupersededError extends Error {
20
+ constructor(id) {
21
+ super(`[spatial] selection of "${id}" was superseded by a newer one`);
22
+ this.name = 'SupersededError';
23
+ }
24
+ }
25
+ /**
26
+ * Bytes a decoded payload holds: its own typed-array views, one level deep — every
27
+ * payload here is a typed array or a flat record of them.
28
+ */
29
+ function payloadBytes(value) {
30
+ if (ArrayBuffer.isView(value))
31
+ return value.byteLength;
32
+ let bytes = 0;
33
+ if (value && typeof value === 'object') {
34
+ for (const v of Object.values(value))
35
+ if (ArrayBuffer.isView(v))
36
+ bytes += v.byteLength;
37
+ }
38
+ return bytes;
39
+ }
40
+ const MiB = 1024 * 1024;
9
41
  /**
10
42
  * Reference {@link SpatialDataPort} adapter for the wire format the bundled
11
43
  * example server speaks (see `spatial-wire.ts` and
@@ -29,18 +61,6 @@ import * as i1 from "@angular/common/http";
29
61
  * Requests go through Angular's `HttpClient` (not `fetch`) so the host's
30
62
  * interceptors — auth headers above all — apply, matching `tile-client.ts`.
31
63
  */
32
- /**
33
- * A dataset selection that a newer selection (or a `clear`) overtook.
34
- *
35
- * Thrown rather than resolved so a caller cannot mistake it for "this dataset is
36
- * now loaded": nothing was published, on purpose.
37
- */
38
- export class SupersededError extends Error {
39
- constructor(id) {
40
- super(`[spatial] selection of "${id}" was superseded by a newer one`);
41
- this.name = 'SupersededError';
42
- }
43
- }
44
64
  export class SpatialDataHttpService {
45
65
  static { this.CACHE_LIMIT = 32; }
46
66
  static { this.TILE_CACHE_LIMIT = 384; }
@@ -53,16 +73,23 @@ export class SpatialDataHttpService {
53
73
  this.timeoutMs = 30_000;
54
74
  this.dataset$ = new BehaviorSubject(null);
55
75
  this.manifest = null;
56
- /** Bumped by every `selectDataset` and every `clear`, so a selection that
57
- * finishes after a newer intent can tell and drop what it fetched. */
58
- this.selectToken = 0;
76
+ /** Advanced by every `selectDataset` and every `clear`, so a selection that
77
+ * finishes after a newer intent can tell and drop what it fetched. Cache fills
78
+ * take a {@link Supersede.current snapshot} of it, so a vector or tile that lands
79
+ * after a switch is returned to its caller but never kept for the next dataset. */
80
+ this.selection = new Supersede();
59
81
  /**
60
82
  * Loaded vectors, keyed `column:<name>` / `feature:<name>`. Bounded LRU:
61
83
  * colouring by cluster → by a gene → back by cluster must not refetch, but an
62
- * afternoon of browsing genes must not grow without limit either (one vector
63
- * is `4·N` bytes — 2 MB at 500k cells).
84
+ * afternoon of browsing genes must not grow without limit either.
85
+ *
86
+ * Bounded by BYTES as well as entries: one vector is `4·N` bytes — 2 MB at 500k
87
+ * cells, but 14.8 MB at 3.7M, where 32 entries (an embedding is two or three
88
+ * vectors) could pin close to half a gigabyte.
64
89
  */
65
90
  this.cache = new Map();
91
+ this.cachedBytes = 0;
92
+ this.cacheBytes = 256 * MiB;
66
93
  /** In-flight requests, so double-clicking a gene issues one fetch. */
67
94
  this.inFlight = new Map();
68
95
  /**
@@ -70,24 +97,37 @@ export class SpatialDataHttpService {
70
97
  * of a zoomed-out section is dozens of them — far past the vector cache's limit.
71
98
  */
72
99
  this.tileCache = new Map();
100
+ /** Bytes of each RESOLVED tile in {@link tileCache}; a pending one counts once it lands. */
101
+ this.tileBytes = new Map();
102
+ this.tileBytesTotal = 0;
103
+ this.tileCacheBytes = 128 * MiB;
73
104
  this.volumePromise = null;
74
105
  this.polygonsPromise = null;
75
- /** Small JSON answers, keyed by URL — hovering back and forth must not refetch. */
76
- this.summaryCache = new Map();
106
+ /** Small JSON answers, keyed by URL — hovering back and forth must not refetch. Least recently
107
+ * USED goes first, so the summary under the pointer stays while others are evicted. */
108
+ this.summaryCache = new LruCache(256);
77
109
  }
78
110
  // ── configuration ───────────────────────────────────────────────────────
79
- /** Point the adapter at a server. Clears any loaded dataset. */
111
+ /**
112
+ * Point the adapter at a server. Clears any loaded dataset.
113
+ *
114
+ * `cacheBytes` / `tileCacheBytes` cap the decoded vectors (default 256 MiB) and tiles
115
+ * (default 128 MiB) kept for reuse; the most recent entry is always kept.
116
+ */
80
117
  configure(options) {
81
118
  const raw = options.baseUrl ?? '';
82
119
  this.baseUrl = raw.endsWith('/') ? raw : `${raw}/`;
83
120
  if (options.timeoutMs !== undefined)
84
121
  this.timeoutMs = options.timeoutMs;
122
+ if (options.cacheBytes !== undefined)
123
+ this.cacheBytes = options.cacheBytes;
124
+ if (options.tileCacheBytes !== undefined)
125
+ this.tileCacheBytes = options.tileCacheBytes;
85
126
  this.clear();
86
127
  }
87
128
  /** Datasets this server offers, for a host-side picker. */
88
129
  listDatasets() {
89
- return this.getJson('spatial/datasets')
90
- .then((r) => r.datasets ?? []);
130
+ return this.getJson('spatial/datasets').then((r) => r.datasets ?? []);
91
131
  }
92
132
  /**
93
133
  * One dataset's manifest, WITHOUT selecting it. Lets a host inspect what a
@@ -96,43 +136,41 @@ export class SpatialDataHttpService {
96
136
  * dataset to find out.
97
137
  */
98
138
  readManifest(id) {
99
- return this.getJson(`spatial/${encodeURIComponent(id)}/manifest`)
100
- .then((manifest) => {
139
+ return this.getJson(`spatial/${encodeURIComponent(id)}/manifest`).then((manifest) => {
101
140
  assertManifestVersion(manifest);
102
141
  return manifest;
103
142
  });
104
143
  }
105
144
  /**
106
145
  * Load a dataset and publish it on {@link getDataset$}. Fetches the manifest,
107
- * then the vectors that are always needed (coordinates, and ids/radius when
108
- * the manifest says they exist) — nothing else.
146
+ * then, in parallel, the vectors that are always needed (coordinates, and
147
+ * ids/radius when the manifest says they exist) — nothing else.
109
148
  */
110
149
  async selectDataset(id) {
111
150
  this.clear();
112
- // Selections are SEQUENCED: this is four awaits deep, so a slower earlier
151
+ // Selections are SEQUENCED: this is two awaits deep, so a slower earlier
113
152
  // call would otherwise assign `this.manifest` or publish its dataset after a
114
153
  // later one — leaving the manifest and the observations from two different
115
154
  // datasets, which is worse than either being late.
116
- const mine = ++this.selectToken;
117
- const superseded = () => mine !== this.selectToken;
155
+ const task = this.selection.next();
156
+ const superseded = () => !task.isCurrent();
118
157
  const path = `spatial/${encodeURIComponent(id)}`;
119
158
  const manifest = await this.getJson(`${path}/manifest`);
120
159
  assertManifestVersion(manifest);
121
160
  if (superseded())
122
161
  throw new SupersededError(id);
123
162
  this.manifest = manifest;
124
- const coordsBuf = await this.getBinary(`${path}/coords`);
163
+ // Independent of each other, so requested together: time to first paint is the
164
+ // slowest of them, not their sum (the ids JSON alone is tens of MB on a large dataset).
165
+ const [coordsBuf, ids, radiusBuf] = await Promise.all([
166
+ this.getBinary(`${path}/coords`),
167
+ manifest.hasIds ? this.getJson(`${path}/ids`).then((r) => r.ids) : undefined,
168
+ manifest.radius?.mode === 'per-observation' ? this.getBinary(`${path}/radius`) : undefined,
169
+ ]);
125
170
  if (superseded())
126
171
  throw new SupersededError(id);
127
172
  const coords = decodeCoords(coordsBuf, manifest.count, !!manifest.hasZ);
128
- const ids = manifest.hasIds
129
- ? (await this.getJson(`${path}/ids`)).ids
130
- : undefined;
131
- const radius = manifest.radius?.mode === 'per-observation'
132
- ? decodeRadius(await this.getBinary(`${path}/radius`), manifest.count)
133
- : undefined;
134
- if (superseded())
135
- throw new SupersededError(id);
173
+ const radius = radiusBuf ? decodeRadius(radiusBuf, manifest.count) : undefined;
136
174
  const dataset = datasetFromManifest(manifest, coords, { ids, radius });
137
175
  this.dataset$.next(dataset);
138
176
  return dataset;
@@ -141,11 +179,14 @@ export class SpatialDataHttpService {
141
179
  clear() {
142
180
  // A clear is itself the newest intent, so it supersedes any selection still
143
181
  // in flight rather than letting one land afterwards.
144
- this.selectToken++;
182
+ this.selection.cancel();
145
183
  this.manifest = null;
146
184
  this.cache.clear();
185
+ this.cachedBytes = 0;
147
186
  this.inFlight.clear();
148
187
  this.tileCache.clear();
188
+ this.tileBytes.clear();
189
+ this.tileBytesTotal = 0;
149
190
  this.summaryCache.clear();
150
191
  this.polygonsPromise = null;
151
192
  this.volumePromise = null;
@@ -165,8 +206,7 @@ export class SpatialDataHttpService {
165
206
  // as a plot that silently renders every point as "no data".
166
207
  return Promise.reject(new Error(`[spatial] unknown column "${name}". Available: ${dataset.columns.map((c) => c.name).join(', ')}`));
167
208
  }
168
- return this.fetchCached(`column:${name}`, () => this.getBinary(`spatial/${encodeURIComponent(manifest.id)}/column/${encodeURIComponent(name)}`)
169
- .then((buf) => decodeColumn(buf, meta, manifest.count)));
209
+ return this.fetchCached(`column:${name}`, () => this.getBinary(`spatial/${encodeURIComponent(manifest.id)}/column/${encodeURIComponent(name)}`).then((buf) => decodeColumn(buf, meta, manifest.count)));
170
210
  }
171
211
  getEmbedding(name) {
172
212
  const manifest = this.requireManifest();
@@ -182,20 +222,16 @@ export class SpatialDataHttpService {
182
222
  if (names && !names.includes(name)) {
183
223
  return Promise.reject(new Error(`[spatial] unknown feature "${name}"`));
184
224
  }
185
- return this.fetchCached(`feature:${name}`, () => this.getBinary(`spatial/${encodeURIComponent(manifest.id)}/feature/${encodeURIComponent(name)}`)
186
- .then((buf) => decodeFeatureVector(buf, manifest.count)));
225
+ return this.fetchCached(`feature:${name}`, () => this.getBinary(`spatial/${encodeURIComponent(manifest.id)}/feature/${encodeURIComponent(name)}`).then((buf) => decodeFeatureVector(buf, manifest.count)));
187
226
  }
188
227
  async searchFeatures(query, limit = 50) {
189
228
  const manifest = this.requireManifest();
190
229
  // A dataset that inlined its names (targeted panel) is filtered locally —
191
- // no round-trip for a keystroke.
230
+ // no round-trip for a keystroke — and ranked as the picker ranks them.
192
231
  const names = manifest.features?.names;
193
- if (names) {
194
- const q = query.toLowerCase();
195
- return names.filter((n) => n.toLowerCase().includes(q)).slice(0, limit);
196
- }
197
- const url = `spatial/${encodeURIComponent(manifest.id)}/features`
198
- + `?q=${encodeURIComponent(query)}&limit=${limit}`;
232
+ if (names)
233
+ return searchGeneNames(names, query, limit);
234
+ const url = `spatial/${encodeURIComponent(manifest.id)}/features` + `?q=${encodeURIComponent(query)}&limit=${limit}`;
199
235
  return (await this.getJson(url)).names ?? [];
200
236
  }
201
237
  getPolygons() {
@@ -205,10 +241,12 @@ export class SpatialDataHttpService {
205
241
  }
206
242
  // Geometry is one large blob rather than a per-name vector, so it gets its
207
243
  // own single-flight slot instead of a cache entry.
208
- this.polygonsPromise ??= this
209
- .getBinary(`spatial/${encodeURIComponent(manifest.id)}/polygons`)
244
+ this.polygonsPromise ??= this.getBinary(`spatial/${encodeURIComponent(manifest.id)}/polygons`)
210
245
  .then(decodePolygons)
211
- .catch((err) => { this.polygonsPromise = null; throw err; });
246
+ .catch((err) => {
247
+ this.polygonsPromise = null;
248
+ throw err;
249
+ });
212
250
  return this.polygonsPromise;
213
251
  }
214
252
  getPolygonTile(set, level, gx, gy) {
@@ -216,9 +254,9 @@ export class SpatialDataHttpService {
216
254
  if (!manifest.polygonTiles) {
217
255
  return Promise.reject(new Error('[spatial] this dataset has no tiled polygons'));
218
256
  }
219
- const path = `spatial/${encodeURIComponent(manifest.id)}/polygon-tile/`
220
- + `${encodeURIComponent(set)}/${level}/${gx}/${gy}`;
221
- return this.cachedTile(path, () => this.getBinary(path).then(decodePolygonTile));
257
+ const path = `spatial/${encodeURIComponent(manifest.id)}/polygon-tile/` +
258
+ `${encodeURIComponent(set)}/${level}/${gx}/${gy}`;
259
+ return this.cachedTile(path, () => this.getBinary(path).then((buf) => decodePolygonTile(buf, manifest.count)));
222
260
  }
223
261
  getTranscriptTile(level, gx, gy, query) {
224
262
  const manifest = this.requireManifest();
@@ -227,15 +265,28 @@ export class SpatialDataHttpService {
227
265
  }
228
266
  const genes = query.genes.map(encodeURIComponent).join(',');
229
267
  const box = query.box ? `&box=${query.box.join(',')}` : '';
230
- const path = `spatial/${encodeURIComponent(manifest.id)}/transcript-tile/${level}/${gx}/${gy}`
231
- + `?genes=${genes}&quality=${query.quality ?? 'high'}${box}`;
232
- return this.cachedTile(path, () => this.getBinary(path).then(decodeTranscriptTile));
268
+ const path = `spatial/${encodeURIComponent(manifest.id)}/transcript-tile/${level}/${gx}/${gy}` +
269
+ `?genes=${genes}&quality=${query.quality ?? 'high'}${box}`;
270
+ // The codes index the genes asked for — except for ALL_GENES, whose list the
271
+ // server owns, so only the observations can be bounded there.
272
+ const limits = {
273
+ observations: manifest.count,
274
+ ...(query.genes.includes(ALL_GENES) ? {} : { genes: query.genes.length }),
275
+ };
276
+ return this.cachedTile(path, () => this.getBinary(path).then((buf) => decodeTranscriptTile(buf, limits)));
233
277
  }
234
278
  getTranscriptGeneBins(level, tx, ty, genes) {
235
279
  const manifest = this.requireManifest();
236
- const path = `spatial/${encodeURIComponent(manifest.id)}/gene-bins/${level}/${tx}/${ty}`
237
- + `?genes=${genes.map(encodeURIComponent).join(',')}`;
238
- return this.cachedTile(path, () => this.getBinary(path).then(decodeTranscriptTile));
280
+ if (!manifest.transcriptGeneBins) {
281
+ return Promise.reject(new Error('[spatial] this dataset has no per-gene bins'));
282
+ }
283
+ const path = `spatial/${encodeURIComponent(manifest.id)}/gene-bins/${level}/${tx}/${ty}` +
284
+ `?genes=${genes.map(encodeURIComponent).join(',')}`;
285
+ const limits = {
286
+ observations: manifest.count,
287
+ ...(genes.includes(ALL_GENES) ? {} : { genes: genes.length }),
288
+ };
289
+ return this.cachedTile(path, () => this.getBinary(path).then((buf) => decodeTranscriptTile(buf, limits)));
239
290
  }
240
291
  getTranscriptBins(level, tx, ty) {
241
292
  const manifest = this.requireManifest();
@@ -243,7 +294,7 @@ export class SpatialDataHttpService {
243
294
  return Promise.reject(new Error('[spatial] this dataset has no transcript pyramid'));
244
295
  }
245
296
  const path = `spatial/${encodeURIComponent(manifest.id)}/transcript-bins/${level}/${tx}/${ty}`;
246
- return this.cachedTile(path, () => this.getBinary(path).then(decodeTranscriptTile));
297
+ return this.cachedTile(path, () => this.getBinary(path).then((buf) => decodeTranscriptTile(buf, { observations: manifest.count })));
247
298
  }
248
299
  getTranscriptSummary(query) {
249
300
  const manifest = this.requireManifest();
@@ -260,8 +311,6 @@ export class SpatialDataHttpService {
260
311
  hit = this.getJson(url);
261
312
  hit.catch(() => this.summaryCache.delete(url));
262
313
  this.summaryCache.set(url, hit);
263
- if (this.summaryCache.size > 256)
264
- this.summaryCache.delete(this.summaryCache.keys().next().value);
265
314
  }
266
315
  return hit;
267
316
  }
@@ -280,9 +329,11 @@ export class SpatialDataHttpService {
280
329
  // upload as they do to every read, or a protected server refuses it.
281
330
  let body;
282
331
  try {
283
- body = await firstValueFrom(this.http.post(url, table, {
332
+ body = await firstValueFrom(this.http
333
+ .post(url, table, {
284
334
  headers: { 'Content-Type': 'text/csv' },
285
- }).pipe(timeout(this.timeoutMs)));
335
+ })
336
+ .pipe(timeout(this.timeoutMs)));
286
337
  }
287
338
  catch (err) {
288
339
  const e = err;
@@ -294,7 +345,7 @@ export class SpatialDataHttpService {
294
345
  if (current && this.manifest?.id === manifest.id) {
295
346
  const columns = current.columns.filter((c) => c.name !== column.name).concat(column);
296
347
  this.manifest = { ...this.manifest, columns };
297
- this.cache.delete(`column:${column.name}`);
348
+ this.uncache(`column:${column.name}`);
298
349
  this.dataset$.next({ ...current, columns });
299
350
  }
300
351
  return { column, matched: body.matched };
@@ -316,20 +367,39 @@ export class SpatialDataHttpService {
316
367
  this.tileCache.set(key, hit);
317
368
  return hit;
318
369
  }
319
- const mine = this.selectToken;
320
- const promise = load().catch((err) => {
370
+ const generation = this.selection.current();
371
+ const promise = load().then((tile) => {
372
+ // Sized once it lands, and only while it is still the entry under its key.
373
+ if (this.tileCache.get(key) === promise && !this.tileBytes.has(key)) {
374
+ const bytes = payloadBytes(tile);
375
+ this.tileBytes.set(key, bytes);
376
+ this.tileBytesTotal += bytes;
377
+ this.evictTiles();
378
+ }
379
+ return tile;
380
+ }, (err) => {
321
381
  if (this.tileCache.get(key) === promise)
322
- this.tileCache.delete(key);
382
+ this.dropTile(key);
323
383
  throw err;
324
384
  });
325
- if (mine === this.selectToken) {
385
+ if (generation.isCurrent()) {
326
386
  this.tileCache.set(key, promise);
327
- while (this.tileCache.size > SpatialDataHttpService.TILE_CACHE_LIMIT) {
328
- this.tileCache.delete(this.tileCache.keys().next().value);
329
- }
387
+ this.evictTiles();
330
388
  }
331
389
  return promise;
332
390
  }
391
+ /** Oldest first, past the entry cap or the byte budget, keeping the newest. */
392
+ evictTiles() {
393
+ while (this.tileCache.size > 1 &&
394
+ (this.tileCache.size > SpatialDataHttpService.TILE_CACHE_LIMIT || this.tileBytesTotal > this.tileCacheBytes)) {
395
+ this.dropTile(this.tileCache.keys().next().value);
396
+ }
397
+ }
398
+ dropTile(key) {
399
+ this.tileCache.delete(key);
400
+ this.tileBytesTotal -= this.tileBytes.get(key) ?? 0;
401
+ this.tileBytes.delete(key);
402
+ }
333
403
  /**
334
404
  * The reference volume's voxels, single-flighted like the polygons.
335
405
  *
@@ -344,17 +414,19 @@ export class SpatialDataHttpService {
344
414
  if (!meta) {
345
415
  return Promise.reject(new Error('[spatial] this dataset has no reference volume'));
346
416
  }
347
- this.volumePromise ??= this
348
- .getBinary(`spatial/${encodeURIComponent(manifest.id)}/volume`)
417
+ this.volumePromise ??= this.getBinary(`spatial/${encodeURIComponent(manifest.id)}/volume`)
349
418
  .then((buf) => {
350
419
  const want = meta.width * meta.height * meta.depth;
351
420
  if (buf.byteLength !== want) {
352
- throw new Error(`[spatial] volume is ${buf.byteLength} bytes, expected ${want} `
353
- + `(${meta.width}x${meta.height}x${meta.depth})`);
421
+ throw new Error(`[spatial] volume is ${buf.byteLength} bytes, expected ${want} ` +
422
+ `(${meta.width}x${meta.height}x${meta.depth})`);
354
423
  }
355
424
  return new Uint8Array(buf);
356
425
  })
357
- .catch((err) => { this.volumePromise = null; throw err; });
426
+ .catch((err) => {
427
+ this.volumePromise = null;
428
+ throw err;
429
+ });
358
430
  return this.volumePromise;
359
431
  }
360
432
  // ── internals ───────────────────────────────────────────────────────────
@@ -385,19 +457,22 @@ export class SpatialDataHttpService {
385
457
  // Re-insert to mark most-recently-used (Map preserves insertion order).
386
458
  this.cache.delete(key);
387
459
  this.cache.set(key, hit);
388
- return Promise.resolve(hit);
460
+ return Promise.resolve(hit.value);
389
461
  }
390
462
  const pending = this.inFlight.get(key);
391
463
  if (pending)
392
464
  return pending;
393
- const mine = this.selectToken;
465
+ const generation = this.selection.current();
394
466
  const promise = load()
395
467
  .then((value) => {
396
468
  // Still returned to the caller that asked: it may well be a component that is
397
469
  // itself being torn down, and rejecting here would surface a switch as an error.
398
470
  // What must not happen is the value being kept for whoever comes next.
399
- if (mine === this.selectToken) {
400
- this.cache.set(key, value);
471
+ if (generation.isCurrent()) {
472
+ this.uncache(key);
473
+ const bytes = payloadBytes(value);
474
+ this.cache.set(key, { value, bytes });
475
+ this.cachedBytes += bytes;
401
476
  this.evict();
402
477
  }
403
478
  return value;
@@ -409,20 +484,25 @@ export class SpatialDataHttpService {
409
484
  this.inFlight.set(key, promise);
410
485
  return promise;
411
486
  }
487
+ /** Oldest first, past the entry cap or the byte budget, keeping the newest. */
412
488
  evict() {
413
- while (this.cache.size > SpatialDataHttpService.CACHE_LIMIT) {
414
- const oldest = this.cache.keys().next().value;
415
- if (oldest === undefined)
416
- break;
417
- this.cache.delete(oldest);
489
+ while (this.cache.size > 1 &&
490
+ (this.cache.size > SpatialDataHttpService.CACHE_LIMIT || this.cachedBytes > this.cacheBytes)) {
491
+ this.uncache(this.cache.keys().next().value);
418
492
  }
419
493
  }
494
+ uncache(key) {
495
+ const entry = this.cache.get(key);
496
+ if (!entry)
497
+ return;
498
+ this.cache.delete(key);
499
+ this.cachedBytes -= entry.bytes;
500
+ }
420
501
  getJson(path) {
421
502
  return firstValueFrom(this.http.get(`${this.baseUrl}${path}`).pipe(timeout(this.timeoutMs)));
422
503
  }
423
504
  getBinary(path) {
424
- return firstValueFrom(this.http.get(`${this.baseUrl}${path}`, { responseType: 'arraybuffer' })
425
- .pipe(timeout(this.timeoutMs)));
505
+ return firstValueFrom(this.http.get(`${this.baseUrl}${path}`, { responseType: 'arraybuffer' }).pipe(timeout(this.timeoutMs)));
426
506
  }
427
507
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: SpatialDataHttpService, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
428
508
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: SpatialDataHttpService }); }
@@ -430,4 +510,4 @@ export class SpatialDataHttpService {
430
510
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: SpatialDataHttpService, decorators: [{
431
511
  type: Injectable
432
512
  }], ctorParameters: () => [{ type: i1.HttpClient }] });
433
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3BhdGlhbC1kYXRhLWh0dHAuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvaW1wbGVtZW50YXRpb25zL3NwYXRpYWwtZGF0YS1odHRwL3NwYXRpYWwtZGF0YS1odHRwLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBcUIsTUFBTSxzQkFBc0IsQ0FBQztBQUNyRSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNDLE9BQU8sRUFBRSxlQUFlLEVBQWMsY0FBYyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ25FLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUd6QyxPQUFPLEVBV0wsY0FBYyxHQUNmLE1BQU0sMENBQTBDLENBQUM7QUFDbEQsT0FBTyxFQUdMLHFCQUFxQixFQUNyQixtQkFBbUIsRUFDbkIsWUFBWSxFQUNaLFlBQVksRUFDWixhQUFhLEVBQ2IsZUFBZSxFQUNmLG1CQUFtQixFQUNuQixpQkFBaUIsRUFDakIsY0FBYyxFQUNkLFlBQVksRUFDWixvQkFBb0IsR0FDckIsTUFBTSxnQkFBZ0IsQ0FBQzs7O0FBRXhCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBc0JHO0FBQ0g7Ozs7O0dBS0c7QUFDSCxNQUFNLE9BQU8sZUFBZ0IsU0FBUSxLQUFLO0lBQ3hDLFlBQVksRUFBVTtRQUNwQixLQUFLLENBQUMsMkJBQTJCLEVBQUUsaUNBQWlDLENBQUMsQ0FBQztRQUN0RSxJQUFJLENBQUMsSUFBSSxHQUFHLGlCQUFpQixDQUFDO0lBQ2hDLENBQUM7Q0FDRjtBQVNELE1BQU0sT0FBTyxzQkFBc0I7YUFvQlQsZ0JBQVcsR0FBRyxFQUFFLEFBQUwsQ0FBTTthQVVqQixxQkFBZ0IsR0FBRyxHQUFHLEFBQU4sQ0FBTztJQUsvQyxZQUFvQixJQUFnQjtRQUFoQixTQUFJLEdBQUosSUFBSSxDQUFZO1FBbENw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QUUsT0FBTyxDQUFDLENBQUM7UUFDaEMsT0FBTyxPQUFPLENBQUM7SUFDakIsQ0FBQztJQUVPLEtBQUs7UUFDWCxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxHQUFHLHNCQUFzQixDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQzVELE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsSUFBSSxFQUFFLENBQUMsS0FBMkIsQ0FBQztZQUNwRSxJQUFJLE1BQU0sS0FBSyxTQUFTO2dCQUFFLE1BQU07WUFDaEMsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDNUIsQ0FBQztJQUNILENBQUM7SUFFTyxPQUFPLENBQUksSUFBWTtRQUM3QixPQUFPLGNBQWMsQ0FDbkIsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUksR0FBRyxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FDekUsQ0FBQztJQUNKLENBQUM7SUFFTyxTQUFTLENBQUMsSUFBWTtRQUM1QixPQUFPLGNBQWMsQ0FDbkIsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksRUFBRSxFQUFFLEVBQUUsWUFBWSxFQUFFLGFBQWEsRUFBRSxDQUFDO2FBQ3JFLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQ2pDLENBQUM7SUFDSixDQUFDOzhHQS9iVSxzQkFBc0I7a0hBQXRCLHNCQUFzQjs7MkZBQXRCLHNCQUFzQjtrQkFEbEMsVUFBVSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEh0dHBDbGllbnQsIEh0dHBFcnJvclJlc3BvbnNlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0LCBPYnNlcnZhYmxlLCBmaXJzdFZhbHVlRnJvbSB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgdGltZW91dCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuaW1wb3J0IHsgU3BhdGlhbERhdGFQb3J0LCBUcmFuc2NyaXB0VGlsZVF1ZXJ5IH0gZnJvbSAnLi4vLi4vY29udHJhY3RzL3BvcnRzL3NwYXRpYWwtZGF0YS5wb3J0JztcbmltcG9ydCB7XG4gIFNwYXRpYWxDb2x1bW4sXG4gIFNwYXRpYWxEYXRhc2V0LFxuICBTcGF0aWFsRGVuc2l0eVJhc3RlcixcbiAgU3BhdGlhbEVtYmVkZGluZyxcbiAgU3BhdGlhbFBvbHlnb25UaWxlLFxuICBTcGF0aWFsUG9seWdvbnMsXG4gIENhdGVnb3JpY2FsQ29sdW1uTWV0YSxcbiAgU3BhdGlhbE1hcmtlckdlbmVzLCBTcGF0aWFsVHJhbnNjcmlwdENvdW50cyxcbiAgU3BhdGlhbFRyYW5zY3JpcHRTdW1tYXJ5LFxuICBTcGF0aWFsVHJhbnNjcmlwdFRpbGUsXG4gIGZpbmRDb2x1bW5NZXRhLFxufSBmcm9tICcuLi8uLi9jb250cmFjdHMvc3BhdGlhbC1kYXRhc2V0LmNvbnRyYWN0JztcbmltcG9ydCB7XG4gIFNwYXRpYWxEYXRhc2V0U3VtbWFyeSxcbiAgU3BhdGlhbE1hbmlmZXN0LFxuICBhc3NlcnRNYW5pZmVzdFZlcnNpb24sXG4gIGRhdGFzZXRGcm9tTWFuaWZlc3QsXG4gIGRlY29kZUNvbHVtbixcbiAgZGVjb2RlQ29vcmRzLFxuICBkZWNvZGVEZW5zaXR5LFxuICBkZWNvZGVFbWJlZGRpbmcsXG4gIGRlY29kZUZlYXR1cmVWZWN0b3IsXG4gIGRlY29kZVBvbHlnb25UaWxlLFxuICBkZWNvZGVQb2x5Z29ucyxcbiAgZGVjb2RlUmFkaXVzLFxuICBkZWNvZGVUcmFuc2NyaXB0VGlsZSxcbn0gZnJvbSAnLi9zcGF0aWFsLXdpcmUnO1xuXG4vKipcbiAqIFJlZmVyZW5jZSB7QGxpbmsgU3BhdGlhbERhdGFQb3J0fSBhZGFwdGVyIGZvciB0aGUgd2lyZSBmb3JtYXQgdGhlIGJ1bmRsZWRcbiAqIGV4YW1wbGUgc2VydmVyIHNwZWFrcyAoc2VlIGBzcGF0aWFsLXdpcmUudHNgIGFuZFxuICogYGV4YW1wbGVzL3RpbGUtc2VydmVyL2xpYi9zcGF0aWFsLm1qc2ApLlxuICpcbiAqIE9QVElPTkFMIEFORCBVTkJPVU5EIEJZIERFRkFVTFQg4oCUIHRoaXMgc2VydmljZSBpcyBgQEluamVjdGFibGUoKWAgd2l0aG91dFxuICogYHByb3ZpZGVkSW5gLCBzbyBub3RoaW5nIGdldHMgaXQgdW5sZXNzIGEgaG9zdCBleHBsaWNpdGx5IHByb3ZpZGVzIGl0OlxuICpcbiAqIGBgYHRzXG4gKiBwcm92aWRlcnM6IFtcbiAqICAgU3BhdGlhbERhdGFIdHRwU2VydmljZSxcbiAqICAgeyBwcm92aWRlOiBTUEFUSUFMX0RBVEFfUE9SVCwgdXNlRXhpc3Rpbmc6IFNwYXRpYWxEYXRhSHR0cFNlcnZpY2UgfSxcbiAqIF1cbiAqIGBgYFxuICpcbiAqIFRoYXQgbWlycm9ycyBgQ2VsbHBvc2VTZWdtZW50ZXJTZXJ2aWNlYDogYSBjb25jcmV0ZSBpbXBsZW1lbnRhdGlvbiB0aGVcbiAqIGxpYnJhcnkgc2hpcHMgZm9yIGNvbnZlbmllbmNlLCBub3QgYSBkZWZhdWx0IHRoZSBwb3J0IGludmVyc2lvbiBpcyBxdWlldGx5XG4gKiBnaXZpbmcgdXAgb24uIEEgaG9zdCB3aXRoIGl0cyBvd24gYmFja2VuZCBpbXBsZW1lbnRzIGBTcGF0aWFsRGF0YVBvcnRgXG4gKiBkaXJlY3RseSBhbmQgbmV2ZXIgdG91Y2hlcyB0aGlzIGNsYXNzLlxuICpcbiAqIFJlcXVlc3RzIGdvIHRocm91Z2ggQW5ndWxhcidzIGBIdHRwQ2xpZW50YCAobm90IGBmZXRjaGApIHNvIHRoZSBob3N0J3NcbiAqIGludGVyY2VwdG9ycyDigJQgYXV0aCBoZWFkZXJzIGFib3ZlIGFsbCDigJQgYXBwbHksIG1hdGNoaW5nIGB0aWxlLWNsaWVudC50c2AuXG4gKi9cbi8qKlxuICogQSBkYXRhc2V0IHNlbGVjdGlvbiB0aGF0IGEgbmV3ZXIgc2VsZWN0aW9uIChvciBhIGBjbGVhcmApIG92ZXJ0b29rLlxuICpcbiAqIFRocm93biByYXRoZXIgdGhhbiByZXNvbHZlZCBzbyBhIGNhbGxlciBjYW5ub3QgbWlzdGFrZSBpdCBmb3IgXCJ0aGlzIGRhdGFzZXQgaXNcbiAqIG5vdyBsb2FkZWRcIjogbm90aGluZyB3YXMgcHVibGlzaGVkLCBvbiBwdXJwb3NlLlxuICovXG5leHBvcnQgY2xhc3MgU3VwZXJzZWRlZEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihpZDogc3RyaW5nKSB7XG4gICAgc3VwZXIoYFtzcGF0aWFsXSBzZWxlY3Rpb24gb2YgXCIke2lkfVwiIHdhcyBzdXBlcnNlZGVkIGJ5IGEgbmV3ZXIgb25lYCk7XG4gICAgdGhpcy5uYW1lID0gJ1N1cGVyc2VkZWRFcnJvcic7XG4gIH1cbn1cblxuLyoqXG4gKiBXaGF0IHRoZSBMUlUgY2FuIGhvbGQuIE9uZSBhbGlhcyByYXRoZXIgdGhhbiBhIHVuaW9uIHJlcGVhdGVkIGF0IGVhY2ggdXNlLCBzbyBhZGRpbmcgYSBwYXlsb2FkXG4gKiBraW5kIGlzIGEgc2luZ2xlIGVkaXQgaW5zdGVhZCBvZiBmb3VyIHRoYXQgY2FuIGRyaWZ0IGFwYXJ0LlxuICovXG50eXBlIENhY2hlZFBheWxvYWQgPSBTcGF0aWFsQ29sdW1uIHwgRmxvYXQzMkFycmF5IHwgU3BhdGlhbEVtYmVkZGluZyB8IFNwYXRpYWxEZW5zaXR5UmFzdGVyO1xuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgU3BhdGlhbERhdGFIdHRwU2VydmljZSBpbXBsZW1lbnRzIFNwYXRpYWxEYXRhUG9ydCB7XG4gIC8qKiBTZXJ2ZXIgcm9vdCwgbm9ybWFsaXNlZCB0byBlbmQgd2l0aCBleGFjdGx5IG9uZSBgL2AuICovXG4gIHByaXZhdGUgYmFzZVVybCA9ICcnO1xuICAvKiogUGVyLXJlcXVlc3QgY2VpbGluZy4gVmVjdG9ycyBhcmUgc21hbGw7IGEgaHVuZyByZXF1ZXN0IHNob3VsZCBub3Qgd2VkZ2VcbiAgICogIHRoZSBwaWNrZXIuICovXG4gIHByaXZhdGUgdGltZW91dE1zID0gMzBfMDAwO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgZGF0YXNldCQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PFNwYXRpYWxEYXRhc2V0IHwgbnVsbD4obnVsbCk7XG4gIHByaXZhdGUgbWFuaWZlc3Q6IFNwYXRpYWxNYW5pZmVzdCB8IG51bGwgPSBudWxsO1xuICAvKiogQnVtcGVkIGJ5IGV2ZXJ5IGBzZWxlY3REYXRhc2V0YCBhbmQgZXZlcnkgYGNsZWFyYCwgc28gYSBzZWxlY3Rpb24gdGhhdFxuICAgKiAgZmluaXNoZXMgYWZ0ZXIgYSBuZXdlciBpbnRlbnQgY2FuIHRlbGwgYW5kIGRyb3Agd2hhdCBpdCBmZXRjaGVkLiAqL1xuICBwcml2YXRlIHNlbGVjdFRva2VuID0gMDtcblxuICAvKipcbiAgICogTG9hZGVkIHZlY3RvcnMsIGtleWVkIGBjb2x1bW46PG5hbWU+YCAvIGBmZWF0dXJlOjxuYW1lPmAuIEJvdW5kZWQgTFJVOlxuICAgKiBjb2xvdXJpbmcgYnkgY2x1c3RlciDihpIgYnkgYSBnZW5lIOKGkiBiYWNrIGJ5IGNsdXN0ZXIgbXVzdCBub3QgcmVmZXRjaCwgYnV0IGFuXG4gICAqIGFmdGVybm9vbiBvZiBicm93c2luZyBnZW5lcyBtdXN0IG5vdCBncm93IHdpdGhvdXQgbGltaXQgZWl0aGVyIChvbmUgdmVjdG9yXG4gICAqIGlzIGA0wrdOYCBieXRlcyDigJQgMiBNQiBhdCA1MDBrIGNlbGxzKS5cbiAgICovXG4gIHByaXZhdGUgcmVhZG9ubHkgY2FjaGUgPSBuZXcgTWFwPHN0cmluZywgQ2FjaGVkUGF5bG9hZD4oKTtcbiAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgQ0FDSEVfTElNSVQgPSAzMjtcblxuICAvKiogSW4tZmxpZ2h0IHJlcXVlc3RzLCBzbyBkb3VibGUtY2xpY2tpbmcgYSBnZW5lIGlzc3VlcyBvbmUgZmV0Y2guICovXG4gIHByaXZhdGUgcmVhZG9ubHkgaW5GbGlnaHQgPSBuZXcgTWFwPHN0cmluZywgUHJvbWlzZTxDYWNoZWRQYXlsb2FkPj4oKTtcblxuICAvKipcbiAgICogVGlsZXMgZ2V0IHRoZWlyIG93biwgbGFyZ2VyIGNhY2hlOiBwYW5uaW5nIHJldmlzaXRzIHRoZW0gY29uc3RhbnRseSwgYW5kIG9uZSBzY3JlZW5cbiAgICogb2YgYSB6b29tZWQtb3V0IHNlY3Rpb24gaXMgZG96ZW5zIG9mIHRoZW0g4oCUIGZhciBwYXN0IHRoZSB2ZWN0b3IgY2FjaGUncyBsaW1pdC5cbiAgICovXG4gIHByaXZhdGUgcmVhZG9ubHkgdGlsZUNhY2hlID0gbmV3IE1hcDxzdHJpbmcsIFByb21pc2U8U3BhdGlhbFBvbHlnb25UaWxlIHwgU3BhdGlhbFRyYW5zY3JpcHRUaWxlPj4oKTtcbiAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgVElMRV9DQUNIRV9MSU1JVCA9IDM4NDtcblxuICBwcml2YXRlIHZvbHVtZVByb21pc2U6IFByb21pc2U8VWludDhBcnJheT4gfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBwb2x5Z29uc1Byb21pc2U6IFByb21pc2U8U3BhdGlhbFBvbHlnb25zPiB8IG51bGwgPSBudWxsO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgaHR0cDogSHR0cENsaWVudCkge31cblxuICAvLyDilIDilIAgY29uZmlndXJhdGlvbiDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICAvKiogUG9pbnQgdGhlIGFkYXB0ZXIgYXQgYSBzZXJ2ZXIuIENsZWFycyBhbnkgbG9hZGVkIGRhdGFzZXQuICovXG4gIGNvbmZpZ3VyZShvcHRpb25zOiB7IGJhc2VVcmw6IHN0cmluZzsgdGltZW91dE1zPzogbnVtYmVyIH0pOiB2b2lkIHtcbiAgICBjb25zdCByYXcgPSBvcHRpb25zLmJhc2VVcmwgPz8gJyc7XG4gICAgdGhpcy5iYXNlVXJsID0gcmF3LmVuZHNXaXRoKCcvJykgPyByYXcgOiBgJHtyYXd9L2A7XG4gICAgaWYgKG9wdGlvbnMudGltZW91dE1zICE9PSB1bmRlZmluZWQpIHRoaXMudGltZW91dE1zID0gb3B0aW9ucy50aW1lb3V0TXM7XG4gICAgdGhpcy5jbGVhcigpO1xuICB9XG5cbiAgLyoqIERhdGFzZXRzIHRoaXMgc2VydmVyIG9mZmVycywgZm9yIGEgaG9zdC1zaWRlIHBpY2tlci4gKi9cbiAgbGlzdERhdGFzZXRzKCk6IFByb21pc2U8U3BhdGlhbERhdGFzZXRTdW1tYXJ5W10+IHtcbiAgICByZXR1cm4gdGhpcy5nZXRKc29uPHsgZGF0YXNldHM6IFNwYXRpYWxEYXRhc2V0U3VtbWFyeVtdIH0+KCdzcGF0aWFsL2RhdGFzZXRzJylcbiAgICAgIC50aGVuKChyKSA9PiByLmRhdGFzZXRzID8/IFtdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBPbmUgZGF0YXNldCdzIG1hbmlmZXN0LCBXSVRIT1VUIHNlbGVjdGluZyBpdC4gTGV0cyBhIGhvc3QgaW5zcGVjdCB3aGF0IGFcbiAgICogc2VydmVyIG9mZmVycyDigJQgY29sdW1uIGFuZCBmZWF0dXJlIG1ldGFkYXRhLCBhbmQgd2hpY2ggaW1hZ2UgYSBkYXRhc2V0XG4gICAqIHJlZ2lzdGVycyBvbnRvIOKAlCB3aGlsZSBidWlsZGluZyBhIHBpY2tlciwgcmF0aGVyIHRoYW4gaGF2aW5nIHRvIGxvYWQgZWFjaFxuICAgKiBkYXRhc2V0IHRvIGZpbmQgb3V0LlxuICAgKi9cbiAgcmVhZE1hbmlmZXN0KGlkOiBzdHJpbmcpOiBQcm9taXNlPFNwYXRpYWxNYW5pZmVzdD4ge1xuICAgIHJldHVybiB0aGlzLmdldEpzb248U3BhdGlhbE1hbmlmZXN0Pihgc3BhdGlhbC8ke2VuY29kZVVSSUNvbXBvbmVudChpZCl9L21hbmlmZXN0YClcbiAgICAgIC50aGVuKChtYW5pZmVzdCkgPT4ge1xuICAgICAgICBhc3NlcnRNYW5pZmVzdFZlcnNpb24obWFuaWZlc3QpO1xuICAgICAgICByZXR1cm4gbWFuaWZlc3Q7XG4gICAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMb2FkIGEgZGF0YXNldCBhbmQgcHVibGlzaCBpdCBvbiB7QGxpbmsgZ2V0RGF0YXNldCR9LiBGZXRjaGVzIHRoZSBtYW5pZmVzdCxcbiAgICogdGhlbiB0aGUgdmVjdG9ycyB0aGF0IGFyZSBhbHdheXMgbmVlZGVkIChjb29yZGluYXRlcywgYW5kIGlkcy9yYWRpdXMgd2hlblxuICAgKiB0aGUgbWFuaWZlc3Qgc2F5cyB0aGV5IGV4aXN0KSDigJQgbm90aGluZyBlbHNlLlxuICAgKi9cbiAgYXN5bmMgc2VsZWN0RGF0YXNldChpZDogc3RyaW5nKTogUHJvbWlzZTxTcGF0aWFsRGF0YXNldD4ge1xuICAgIHRoaXMuY2xlYXIoKTtcbiAgICAvLyBTZWxlY3Rpb25zIGFyZSBTRVFVRU5DRUQ6IHRoaXMgaXMgZm91ciBhd2FpdHMgZGVlcCwgc28gYSBzbG93ZXIgZWFybGllclxuICAgIC8vIGNhbGwgd291bGQgb3RoZXJ3aXNlIGFzc2lnbiBgdGhpcy5tYW5pZmVzdGAgb3IgcHVibGlzaCBpdHMgZGF0YXNldCBhZnRlciBhXG4gICAgLy8gbGF0ZXIgb25lIOKAlCBsZWF2aW5nIHRoZSBtYW5pZmVzdCBhbmQgdGhlIG9ic2VydmF0aW9ucyBmcm9tIHR3byBkaWZmZXJlbnRcbiAgICAvLyBkYXRhc2V0cywgd2hpY2ggaXMgd29yc2UgdGhhbiBlaXRoZXIgYmVpbmcgbGF0ZS5cbiAgICBjb25zdCBtaW5lID0gKyt0aGlzLnNlbGVjdFRva2VuO1xuICAgIGNvbnN0IHN1cGVyc2VkZWQgPSAoKSA9PiBtaW5lICE9PSB0aGlzLnNlbGVjdFRva2VuO1xuICAgIGNvbnN0IHBhdGggPSBgc3BhdGlhbC8ke2VuY29kZVVSSUNvbXBvbmVudChpZCl9YDtcblxuICAgIGNvbnN0IG1hbmlmZXN0ID0gYXdhaXQgdGhpcy5nZXRKc29uPFNwYXRpYWxNYW5pZmVzdD4oYCR7cGF0aH0vbWFuaWZlc3RgKTtcbiAgICBhc3NlcnRNYW5pZmVzdFZlcnNpb24obWFuaWZlc3QpO1xuICAgIGlmIChzdXBlcnNlZGVkKCkpIHRocm93IG5ldyBTdXBlcnNlZGVkRXJyb3IoaWQpO1xuICAgIHRoaXMubWFuaWZlc3QgPSBtYW5pZmVzdDtcblxuICAgIGNvbnN0IGNvb3Jkc0J1ZiA9IGF3YWl0IHRoaXMuZ2V0QmluYXJ5KGAke3BhdGh9L2Nvb3Jkc2ApO1xuICAgIGlmIChzdXBlcnNlZGVkKCkpIHRocm93IG5ldyBTdXBlcnNlZGVkRXJyb3IoaWQpO1xuICAgIGNvbnN0IGNvb3JkcyA9IGRlY29kZUNvb3Jkcyhjb29yZHNCdWYsIG1hbmlmZXN0LmNvdW50LCAhIW1hbmlmZXN0Lmhhc1opO1xuXG4gICAgY29uc3QgaWRzID0gbWFuaWZlc3QuaGFzSWRzXG4gICAgICA/IChhd2FpdCB0aGlzLmdldEpzb248eyBpZHM6IHN0cmluZ1tdIH0+KGAke3BhdGh9L2lkc2ApKS5pZHNcbiAgICAgIDogdW5kZWZpbmVkO1xuICAgIGNvbnN0IHJhZGl1cyA9IG1hbmlmZXN0LnJhZGl1cz8ubW9kZSA9PT0gJ3Blci1vYnNlcnZhdGlvbidcbiAgICAgID8gZGVjb2RlUmFkaXVzKGF3YWl0IHRoaXMuZ2V0QmluYXJ5KGAke3BhdGh9L3JhZGl1c2ApLCBtYW5pZmVzdC5jb3VudClcbiAgICAgIDogdW5kZWZpbmVkO1xuICAgIGlmIChzdXBlcnNlZGVkKCkpIHRocm93IG5ldyBTdXBlcnNlZGVkRXJyb3IoaWQpO1xuXG4gICAgY29uc3QgZGF0YXNldCA9IGRhdGFzZXRGcm9tTWFuaWZlc3QobWFuaWZlc3QsIGNvb3JkcywgeyBpZHMsIHJhZGl1cyB9KTtcbiAgICB0aGlzLmRhdGFzZXQkLm5leHQoZGF0YXNldCk7XG4gICAgcmV0dXJuIGRhdGFzZXQ7XG4gIH1cblxuICAvKiogRHJvcCB0aGUgbG9hZGVkIGRhdGFzZXQgYW5kIGV2ZXJ5IGNhY2hlZCB2ZWN0b3IuICovXG4gIGNsZWFyKCk6IHZvaWQge1xuICAgIC8vIEEgY2xlYXIgaXMgaXRzZWxmIHRoZSBuZXdlc3QgaW50ZW50LCBzbyBpdCBzdXBlcnNlZGVzIGFueSBzZWxlY3Rpb24gc3RpbGxcbiAgICAvLyBpbiBmbGlnaHQgcmF0aGVyIHRoYW4gbGV0dGluZyBvbmUgbGFuZCBhZnRlcndhcmRzLlxuICAgIHRoaXMuc2VsZWN0VG9rZW4rKztcbiAgICB0aGlzLm1hbmlmZXN0ID0gbnVsbDtcbiAgICB0aGlzLmNhY2hlLmNsZWFyKCk7XG4gICAgdGhpcy5pbkZsaWdodC5jbGVhcigpO1xuICAgIHRoaXMudGlsZUNhY2hlLmNsZWFyKCk7XG4gICAgdGhpcy5zdW1tYXJ5Q2FjaGUuY2xlYXIoKTtcbiAgICB0aGlzLnBvbHlnb25zUHJvbWlzZSA9IG51bGw7XG4gICAgdGhpcy52b2x1bWVQcm9taXNlID0gbnVsbDtcbiAgICBpZiAodGhpcy5kYXRhc2V0JC52YWx1ZSAhPT0gbnVsbCkgdGhpcy5kYXRhc2V0JC5uZXh0KG51bGwpO1xuICB9XG5cbiAgLy8g4pSA4pSAIFNwYXRpYWxEYXRhUG9ydCDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBnZXREYXRhc2V0JCgpOiBPYnNlcnZhYmxlPFNwYXRpYWxEYXRhc2V0IHwgbnVsbD4ge1xuICAgIHJldHVybiB0aGlzLmRhdGFzZXQkLmFzT2JzZXJ2YWJsZSgpO1xuICB9XG5cbiAgZ2V0Q29sdW1uKG5hbWU6IHN0cmluZyk6IFByb21pc2U8U3BhdGlhbENvbHVtbj4ge1xuICAgIGNvbnN0IG1hbmlmZXN0ID0gdGhpcy5yZXF1aXJlTWFuaWZlc3QoKTtcbiAgICBjb25zdCBkYXRhc2V0ID0gdGhpcy5kYXRhc2V0JC52YWx1ZSE7XG4gICAgY29uc3QgbWV0YSA9IGZpbmRDb2x1bW5NZXRhKGRhdGFzZXQsIG5hbWUpO1xuICAgIGlmICghbWV0YSkge1xuICAgICAgLy8gUmVqZWN0IHJhdGhlciB0aGFuIHJlc29sdmUgZW1wdHk6IGEgdHlwbyBtdXN0IHN1cmZhY2UgYXMgYW4gZXJyb3IsIG5vdFxuICAgICAgLy8gYXMgYSBwbG90IHRoYXQgc2lsZW50bHkgcmVuZGVycyBldmVyeSBwb2ludCBhcyBcIm5vIGRhdGFcIi5cbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoXG4gICAgICAgIGBbc3BhdGlhbF0gdW5rbm93biBjb2x1bW4gXCIke25hbWV9XCIuIEF2YWlsYWJsZTogJHtkYXRhc2V0LmNvbHVtbnMubWFwKChjKSA9PiBjLm5hbWUpLmpvaW4oJywgJyl9YCxcbiAgICAgICkpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5mZXRjaENhY2hlZChcbiAgICAgIGBjb2x1bW46JHtuYW1lfWAsXG4gICAgICAoKSA9PiB0aGlzLmdldEJpbmFyeShgc3BhdGlhbC8ke2VuY29kZVVSSUNvbXBvbmVudChtYW5pZmVzdC5pZCl9L2NvbHVtbi8ke2VuY29kZVVSSUNvbXBvbmVudChuYW1lKX1gKVxuICAgICAgICAudGhlbigoYnVmKSA9PiBkZWNvZGVDb2x1bW4oYnVmLCBtZXRhLCBtYW5pZmVzdC5jb3VudCkpLFxuICAgICkgYXMgUHJvbWlzZTxTcGF0aWFsQ29sdW1uPjtcbiAgfVxuXG4gIGdldEVtYmVkZGluZyhuYW1lOiBzdHJpbmcpOiBQcm9taXNlPFNwYXRpYWxFbWJlZGRpbmc+IHtcbiAgICBjb25zdCBtYW5pZmVzdCA9IHRoaXMucmVxdWlyZU1hbmlmZXN0KCk7XG4gICAgY29uc3QgbWV0YSA9IG1hbmlmZXN0LmVtYmVkZGluZ3M/LmZpbmQoKGUpID0+IGUubmFtZSA9PT0gbmFtZSk7XG4gICAgaWYgKCFtZXRhKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKGBbc3BhdGlhbF0gdW5rbm93biBlbWJlZGRpbmcgXCIke25hbWV9XCJgKSk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmZldGNoQ2FjaGVkKFxuICAgICAgYGVtYmVkZGluZzoke25hbWV9YCxcbiAgICAgICgpID0+IHRoaXMuZ2V0QmluYXJ5KFxuICAgICAgICBgc3BhdGlhbC8ke2VuY29kZVVSSUNvbXBvbmVudChtYW5pZmVzdC5pZCl9L2VtYmVkZGluZy8ke2VuY29kZVVSSUNvbXBvbmVudChuYW1lKX1gLFxuICAgICAgKS50aGVuKChidWYpID0+IGRlY29kZUVtYmVkZGluZyhidWYsIG1ldGEsIG1hbmlmZXN0LmNvdW50KSksXG4gICAgKSBhcyBQcm9taXNlPFNwYXRpYWxFbWJlZGRpbmc+O1xuICB9XG5cbiAgZ2V0RmVhdHVyZVZlY3RvcihuYW1lOiBzdHJpbmcpOiBQcm9taXNlPEZsb2F0MzJBcnJheT4ge1xuICAgIGNvbnN0IG1hbmlmZXN0ID0gdGhpcy5yZXF1aXJlTWFuaWZlc3QoKTtcbiAgICBjb25zdCBuYW1lcyA9IG1hbmlmZXN0LmZlYXR1cmVzPy5uYW1lcztcbiAgICBpZiAobmFtZXMgJiYgIW5hbWVzLmluY2x1ZGVzKG5hbWUpKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKGBbc3BhdGlhbF0gdW5rbm93biBmZWF0dXJlIFwiJHtuYW1lfVwiYCkpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5mZXRjaENhY2hlZChcbiAgICAgIGBmZWF0dXJlOiR7bmFtZX1gLFxuICAgICAgKCkgPT4gdGhpcy5nZXRCaW5hcnkoYHNwYXRpYWwvJHtlbmNvZGVVUklDb21wb25lbnQobWFuaWZlc3QuaWQpfS9mZWF0dXJlLyR7ZW5jb2RlVVJJQ29tcG9uZW50KG5hbWUpfWApXG4gICAgICAgIC50aGVuKChidWYpID0+IGRlY29kZUZlYXR1cmVWZWN0b3IoYnVmLCBtYW5pZmVzdC5jb3VudCkpLFxuICAgICkgYXMgUHJvbWlzZTxGbG9hdDMyQXJyYXk+O1xuICB9XG5cbiAgYXN5bmMgc2VhcmNoRmVhdHVyZXMocXVlcnk6IHN0cmluZywgbGltaXQgPSA1MCk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgICBjb25zdCBtYW5pZmVzdCA9IHRoaXMucmVxdWlyZU1hbmlmZXN0KCk7XG4gICAgLy8gQSBkYXRhc2V0IHRoYXQgaW5saW5lZCBpdHMgbmFtZXMgKHRhcmdldGVkIHBhbmVsKSBpcyBmaWx0ZXJlZCBsb2NhbGx5IOKAlFxuICAgIC8vIG5vIHJvdW5kLXRyaXAgZm9yIGEga2V5c3Ryb2tlLlxuICAgIGNvbnN0IG5hbWVzID0gbWFuaWZlc3QuZmVhdHVyZXM/Lm5hbWVzO1xuICAgIGlmIChuYW1lcykge1xuICAgICAgY29uc3QgcSA9IHF1ZXJ5LnRvTG93ZXJDYXNlKCk7XG4gICAgICByZXR1cm4gbmFtZXMuZmlsdGVyKChuKSA9PiBuLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMocSkpLnNsaWNlKDAsIGxpbWl0KTtcbiAgICB9XG4gICAgY29uc3QgdXJsID0gYHNwYXRpYWwvJHtlbmNvZGVVUklDb21wb25lbnQobWFuaWZlc3QuaWQpfS9mZWF0dXJlc2BcbiAgICAgICsgYD9xPSR7ZW5jb2RlVVJJQ29tcG9uZW50KHF1ZXJ5KX0mbGltaXQ9JHtsaW1pdH1gO1xuICAgIHJldHVybiAoYXdhaXQgdGhpcy5nZXRKc29uPHsgbmFtZXM6IHN0cmluZ1tdIH0+KHVybCkpLm5hbWVzID8/IFtdO1xuICB9XG5cbiAgZ2V0UG9seWdvbnMoKTogUHJvbWlzZTxTcGF0aWFsUG9seWdvbnM+IHtcbiAgICBjb25zdCBtYW5pZmVzdCA9IHRoaXMucmVxdWlyZU1hbmlmZXN0KCk7XG4gICAgaWYgKCFtYW5pZmVzdC5wb2x5Z29ucykge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBFcnJvcignW3NwYXRpYWxdIHRoaXMgZGF0YXNldCBoYXMgbm8gcG9seWdvbiBnZW9tZXRyeScpKTtcbiAgICB9XG4gICAgLy8gR2VvbWV0cnkgaXMgb25lIGxhcmdlIGJsb2IgcmF0aGVyIHRoYW4gYSBwZXItbmFtZSB2ZWN0b3IsIHNvIGl0IGdldHMgaXRzXG4gICAgLy8gb3duIHNpbmdsZS1mbGlnaHQgc2xvdCBpbnN0ZWFkIG9mIGEgY2FjaGUgZW50cnkuXG4gICAgdGhpcy5wb2x5Z29uc1Byb21pc2UgPz89IHRoaXNcbiAgICAgIC5nZXRCaW5hcnkoYHNwYXRpYWwvJHtlbmNvZGVVUklDb21wb25lbnQobWFuaWZlc3QuaWQpfS9wb2x5Z29uc2ApXG4gICAgICAudGhlbihkZWNvZGVQb2x5Z29ucylcbiAgICAgIC5jYXRjaCgoZXJyKSA9PiB7IHRoaXMucG9seWdvbnNQcm9taXNlID0gbnVsbDsgdGhyb3cgZXJyOyB9KTtcbiAgICByZXR1cm4gdGhpcy5wb2x5Z29uc1Byb21pc2U7XG4gIH1cblxuICBnZXRQb2x5Z29uVGlsZShzZXQ6IHN0cmluZywgbGV2ZWw6IG51bWJlciwgZ3g6IG51bWJlciwgZ3k6IG51bWJlcik6IFByb21pc2U8U3BhdGlhbFBvbHlnb25UaWxlPiB7XG4gICAgY29uc3QgbWFuaWZlc3QgPSB0aGlzLnJlcXVpcmVNYW5pZmVzdCgpO1xuICAgIGlmICghbWFuaWZlc3QucG9seWdvblRpbGVzKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKCdbc3BhdGlhbF0gdGhpcyBkYXRhc2V0IGhhcyBubyB0aWxlZCBwb2x5Z29ucycpKTtcbiAgICB9XG4gICAgY29uc3QgcGF0aCA9IGBzcGF0aWFsLyR7ZW5jb2RlVVJJQ29tcG9uZW50KG1hbmlmZXN0LmlkKX0vcG9seWdvbi10aWxlL2BcbiAgICAgICsgYCR7ZW5jb2RlVVJJQ29tcG9uZW50KHNldCl9LyR7bGV2ZWx9LyR7Z3h9LyR7Z3l9YDtcbiAgICByZXR1cm4gdGhpcy5jYWNoZWRUaWxlKHBhdGgsICgpID0+IHRoaXMuZ2V0QmluYXJ5KHBhdGgpLnRoZW4oZGVjb2RlUG9seWdvblRpbGUpKSBhc1xuICAgICAgUHJvbWlzZTxTcGF0aWFsUG9seWdvblRpbGU+O1xuICB9XG5cbiAgZ2V0VHJhbnNjcmlwdFRpbGUoXG4gICAgbGV2ZWw6IG51bWJlciwgZ3g6IG51bWJlciwgZ3k6IG51bWJlciwgcXVlcnk6IFRyYW5zY3JpcHRUaWxlUXVlcnksXG4gICk6IFByb21pc2U8U3BhdGlhbFRyYW5zY3JpcHRUaWxlPiB7XG4gICAgY29uc3QgbWFuaWZlc3QgPSB0aGlzLnJlcXVpcmVNYW5pZmVzdCgpO1xuICAgIGlmICghbWFuaWZlc3QudHJhbnNjcmlwdFRpbGVzKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKCdbc3BhdGlhbF0gdGhpcyBkYXRhc2V0IGhhcyBubyB0aWxlZCB0cmFuc2NyaXB0cycpKTtcbiAgICB9XG4gICAgY29uc3QgZ2VuZXMgPSBxdWVyeS5nZW5lcy5tYXAoZW5jb2RlVVJJQ29tcG9uZW50KS5qb2luKCcsJyk7XG4gICAgY29uc3QgYm94ID0gcXVlcnkuYm94ID8gYCZib3g9JHtxdWVyeS5ib3guam9pbignLCcpfWAgOiAnJztcbiAgICBjb25zdCBwYXRoID0gYHNwYXRpYWwvJHtlbmNvZGVVUklDb21wb25lbnQobWFuaWZlc3QuaWQpfS90cmFuc2NyaXB0LXRpbGUvJHtsZXZlbH0vJHtneH0vJHtneX1gXG4gICAgICArIGA/Z2VuZXM9JHtnZW5lc30mcXVhbGl0eT0ke3F1ZXJ5LnF1YWxpdHkgPz8gJ2hpZ2gnfSR7Ym94fWA7XG4gICAgcmV0dXJuIHRoaXMuY2FjaGVkVGlsZShwYXRoLCAoKSA9PiB0aGlzLmdldEJpbmFyeShwYXRoKS50aGVuKGRlY29kZVRyYW5zY3JpcHRUaWxlKSkgYXNcbiAgICAgIFByb21pc2U8U3BhdGlhbFRyYW5zY3JpcHRUaWxlPjtcbiAgfVxuXG4gIGdldFRyYW5zY3JpcHRHZW5lQmlucyhsZXZlbDogbnVtYmVyLCB0eDogbnVtYmVyLCB0eTogbnVtYmVyLCBnZW5lczogc3RyaW5nW10pOiBQcm9taXNlPFNwYXRpYWxUcmFuc2NyaXB0VGlsZT4ge1xuICAgIGNvbnN0IG1hbmlmZXN0ID0gdGhpcy5yZXF1aXJlTWFuaWZlc3QoKTtcbiAgICBjb25zdCBwYXRoID0gYHNwYXRpYWwvJHtlbmNvZGVVUklDb21wb25lbnQobWFuaWZlc3QuaWQpfS9nZW5lLWJpbnMvJHtsZXZlbH0vJHt0eH0vJHt0eX1gXG4gICAgICArIGA/Z2VuZXM9JHtnZW5lcy5tYXAoZW5jb2RlVVJJQ29tcG9uZW50KS5qb2luKCcsJyl9YDtcbiAgICByZXR1cm4gdGhpcy5jYWNoZWRUaWxlKHBhdGgsICgpID0+IHRoaXMuZ2V0QmluYXJ5KHBhdGgpLnRoZW4oZGVjb2RlVHJhbnNjcmlwdFRpbGUpKSBhc1xuICAgICAgUHJvbWlzZTxTcGF0aWFsVHJhbnNjcmlwdFRpbGU+O1xuICB9XG5cbiAgZ2V0VHJhbnNjcmlwdEJpbnMobGV2ZWw6IG51bWJlciwgdHg6IG51bWJlciwgdHk6IG51bWJlcik6IFByb21pc2U8U3BhdGlhbFRyYW5zY3JpcHRUaWxlPiB7XG4gICAgY29uc3QgbWFuaWZlc3QgPSB0aGlzLnJlcXVpcmVNYW5pZmVzdCgpO1xuICAgIGlmICghbWFuaWZlc3QudHJhbnNjcmlwdEJpbnMpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoJ1tzcGF0aWFsXSB0aGlzIGRhdGFzZXQgaGFzIG5vIHRyYW5zY3JpcHQgcHlyYW1pZCcpKTtcbiAgICB9XG4gICAgY29uc3QgcGF0aCA9IGBzcGF0aWFsLyR7ZW5jb2RlVVJJQ29tcG9uZW50KG1hbmlmZXN0LmlkKX0vdHJhbnNjcmlwdC1iaW5zLyR7bGV2ZWx9LyR7dHh9LyR7dHl9YDtcbiAgICByZXR1cm4gdGhpcy5jYWNoZWRUaWxlKHBhdGgsICgpID0+IHRoaXMuZ2V0QmluYXJ5KHBhdGgpLnRoZW4oZGVjb2RlVHJhbnNjcmlwdFRpbGUpKSBhc1xuICAgICAgUHJvbWlzZTxTcGF0aWFsVHJhbnNjcmlwdFRpbGU+O1xuICB9XG5cbiAgLyoqIFNtYWxsIEpTT04gYW5zd2Vycywga2V5ZWQgYnkgVVJMIOKAlCBob3ZlcmluZyBiYWNrIGFuZCBmb3J0aCBtdXN0IG5vdCByZWZldGNoLiAqL1xuICBwcml2YXRlIHJlYWRvbmx5IHN1bW1hcnlDYWNoZSA9IG5ldyBNYXA8c3RyaW5nLCBQcm9taXNlPFNwYXRpYWxUcmFuc2NyaXB0U3VtbWFyeT4+KCk7XG5cbiAgZ2V0VHJhbnNjcmlwdFN1bW1hcnkocXVlcnk6IHtcbiAgICBib3g/OiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXTsgZ2VuZXM/OiBzdHJpbmdbXTsgY2VsbHM/OiBudW1iZXJbXTtcbiAgfSk6IFByb21pc2U8U3BhdGlhbFRyYW5zY3JpcHRTdW1tYXJ5PiB7XG4gICAgY29uc3QgbWFuaWZlc3QgPSB0aGlzLnJlcXVpcmVNYW5pZmVzdCgpO1xuICAgIGNvbnN0IHBhcmFtczogc3RyaW5nW10gPSBbXTtcbiAgICBpZiAocXVlcnkuYm94KSBwYXJhbXMucHVzaChgYm94PSR7cXVlcnkuYm94Lm1hcCgodikgPT4gK3YudG9GaXhlZCgzKSkuam9pbignLCcpfWApO1xuICAgIGlmIChxdWVyeS5nZW5lcz8ubGVuZ3RoKSBwYXJhbXMucHVzaChgZ2VuZXM9JHtxdWVyeS5nZW5lcy5tYXAoZW5jb2RlVVJJQ29tcG9uZW50KS5qb2luKCcsJyl9YCk7XG4gICAgaWYgKHF1ZXJ5LmNlbGxzPy5sZW5ndGgpIHBhcmFtcy5wdXNoKGBjZWxscz0ke3F1ZXJ5LmNlbGxzLmpvaW4oJywnKX1gKTtcbiAgICBjb25zdCB1cmwgPSBgc3BhdGlhbC8ke2VuY29kZVVSSUNvbXBvbmVudChtYW5pZmVzdC5pZCl9L3RyYW5zY3JpcHQtc3VtbWFyeT8ke3BhcmFtcy5qb2luKCcmJyl9YDtcbiAgICBsZXQgaGl0ID0gdGhpcy5zdW1tYXJ5Q2FjaGUuZ2V0KHVybCk7XG4gICAgaWYgKCFoaXQpIHtcbiAgICAgIGhpdCA9IHRoaXMuZ2V0SnNvbjxTcGF0aWFsVHJhbnNjcmlwdFN1bW1hcnk+KHVybCk7XG4gICAgICBoaXQuY2F0Y2goKCkgPT4gdGhpcy5zdW1tYXJ5Q2FjaGUuZGVsZXRlKHVybCkpO1xuICAgICAgdGhpcy5zdW1tYXJ5Q2FjaGUuc2V0KHVybCwgaGl0KTtcbiAgICAgIGlmICh0aGlzLnN1bW1hcnlDYWNoZS5zaXplID4gMjU2KSB0aGlzLnN1bW1hcnlDYWNoZS5kZWxldGUodGhpcy5zdW1tYXJ5Q2FjaGUua2V5cygpLm5leHQoKS52YWx1ZSEpO1xuICAgIH1cbiAgICByZXR1cm4gaGl0O1xuICB9XG5cbiAgZ2V0RGVuc2l0eShnZW5lczogc3RyaW5nW10sIGJpblNpemU/OiBudW1iZXIpOiBQcm9taXNlPFNwYXRpYWxEZW5zaXR5UmFzdGVyPiB7XG4gICAgY29uc3QgbWFuaWZlc3QgPSB0aGlzLnJlcXVpcmVNYW5pZmVzdCgpO1xuICAgIGlmICghbWFuaWZlc3QuZGVuc2l0eSkgcmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBFcnJvcignW3NwYXRpYWxdIHRoaXMgZGF0YXNldCBoYXMgbm8gZGVuc2l0eSByYXN0ZXInKSk7XG4gICAgY29uc3QgbGlzdCA9IFsuLi5nZW5lc107XG4gICAgY29uc3QgYmluID0gYmluU2l6ZSA/IGAmYmluPSR7YmluU2l6ZX1gIDogJyc7XG4gICAgcmV0dXJuIHRoaXMuZmV0Y2hDYWNoZWQoXG4gICAgICBgZGVuc2l0eToke2xpc3Quam9pbignLCcpfToke2JpblNpemUgPz8gJyd9YCxcbiAgICAgICgpID0+IHRoaXMuZ2V0QmluYXJ5KFxuICAgICAgICBgc3BhdGlhbC8ke2VuY29kZVVSSUNvbXBvbmVudChtYW5pZmVzdC5pZCl9L2RlbnNpdHk/Z2VuZXM9JHtsaXN0Lm1hcChlbmNvZGVVUklDb21wb25lbnQpLmpvaW4oJywnKX0ke2Jpbn1gLFxuICAgICAgKS50aGVuKChidWYpID0+IGRlY29kZURlbnNpdHkoYnVmLCBsaXN0KSksXG4gICAgKSBhcyBQcm9taXNlPFNwYXRpYWxEZW5zaXR5UmFzdGVyPjtcbiAgfVxuXG4gIGFzeW5jIGltcG9ydEdyb3VwcyhsYWJlbDogc3RyaW5nLCB0YWJsZTogc3RyaW5nKTogUHJvbWlzZTx7IGNvbHVtbjogQ2F0ZWdvcmljYWxDb2x1bW5NZXRhOyBtYXRjaGVkOiBudW1iZXIgfT4ge1xuICAgIGNvbnN0IG1hbmlmZXN0ID0gdGhpcy5yZXF1aXJlTWFuaWZlc3QoKTtcbiAgICBjb25zdCB1cmwgPSBgJHt0aGlzLmJhc2VVcmx9c3BhdGlhbC8ke2VuY29kZVVSSUNvbXBvbmVudChtYW5pZmVzdC5pZCl9L2dyb3Vwcz9uYW1lPSR7ZW5jb2RlVVJJQ29tcG9uZW50KGxhYmVsKX1gO1xuICAgIC8vIEh0dHBDbGllbnQsIG5vdCBmZXRjaDogYSBob3N0J3MgaW50ZXJjZXB0b3JzIChpdHMgYXV0aCBoZWFkZXIpIG11c3QgYXBwbHkgdG8gdGhlXG4gICAgLy8gdXBsb2FkIGFzIHRoZXkgZG8gdG8gZXZlcnkgcmVhZCwgb3IgYSBwcm90ZWN0ZWQgc2VydmVyIHJlZnVzZXMgaXQuXG4gICAgbGV0IGJvZHk6IHsgY29sdW1uOiBDYXRlZ29yaWNhbENvbHVtbk1ldGE7IG1hdGNoZWQ6IG51bWJlciB9O1xuICAgIHRyeSB7XG4gICAgICBib2R5ID0gYXdhaXQgZmlyc3RWYWx1ZUZyb20oXG4gICAgICAgIHRoaXMuaHR0cC5wb3N0PHsgY29sdW1uOiBDYXRlZ29yaWNhbENvbHVtbk1ldGE7IG1hdGNoZWQ6IG51bWJlciB9Pih1cmwsIHRhYmxlLCB7XG4gICAgICAgICAgaGVhZGVyczogeyAnQ29udGVudC1UeXBlJzogJ3RleHQvY3N2JyB9LFxuICAgICAgICB9KS5waXBlKHRpbWVvdXQodGhpcy50aW1lb3V0TXMpKSxcbiAgICAgICk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBjb25zdCBlID0gZXJyIGFzIEh0dHBFcnJvclJlc3BvbnNlO1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGU/LmVycm9yPy5lcnJvciA/PyBgW3NwYXRpYWxdIGltcG9ydCBmYWlsZWQgKEhUVFAgJHtlPy5zdGF0dXMgPz8gJz8nfSlgKTtcbiAgICB9XG4gICAgY29uc3QgY29sdW1uID0gYm9keS5jb2x1bW47XG4gICAgLy8gVGhlIG5ldyBjb2x1bW4gam9pbnMgdGhlIGRhdGFzZXQ6IHJlLWVtaXQgc28gZXZlcnkgcGFuZWwgc2VlcyBpdC5cbiAgICBjb25zdCBjdXJyZW50ID0gdGhpcy5kYXRhc2V0JC52YWx1ZTtcbiAgICBpZiAoY3VycmVudCAmJiB0aGlzLm1hbmlmZXN0Py5pZCA9PT0gbWFuaWZlc3QuaWQpIHtcbiAgICAgIGNvbnN0IGNvbHVtbnMgPSBjdXJyZW50LmNvbHVtbnMuZmlsdGVyKChjKSA9PiBjLm5hbWUgIT09IGNvbHVtbi5uYW1lKS5jb25jYXQoY29sdW1uKTtcbiAgICAgIHRoaXMubWFuaWZlc3QgPSB7IC4uLnRoaXMubWFuaWZlc3QsIGNvbHVtbnMgfTtcbiAgICAgIHRoaXMuY2FjaGUuZGVsZXRlKGBjb2x1bW46JHtjb2x1bW4ubmFtZX1gKTtcbiAgICAgIHRoaXMuZGF0YXNldCQubmV4dCh7IC4uLmN1cnJlbnQsIGNvbHVtbnMgfSk7XG4gICAgfVxuICAgIHJldHVybiB7IGNvbHVtbiwgbWF0Y2hlZDogYm9keS5tYXRjaGVkIH07XG4gIH1cblxuICBnZXRNYXJrZXJHZW5lcyhjb2x1bW46IHN0cmluZywgcGVyR3JvdXAgPSA1KTogUHJvbWlzZTxTcGF0aWFsTWFya2VyR2VuZXM+IHtcbiAgICBjb25zdCBtYW5pZmVzdCA9IHRoaXMucmVxdWlyZU1hbmlmZXN0KCk7XG4gICAgLy8gTm8gcGVyLXJlcXVlc3QgdGltZW91dDogdGhlIGZpcnN0IGNvbXB1dGF0aW9uIGlzIGEgcGFzcyBvdmVyIHRoZSB3aG9sZSBtYXRyaXguXG4gICAgcmV0dXJuIGZpcnN0VmFsdWVGcm9tKHRoaXMuaHR0cC5nZXQ8U3BhdGlhbE1hcmtlckdlbmVzPihcbiAgICAgIGAke3RoaXMuYmFzZVVybH1zcGF0aWFsLyR7ZW5jb2RlVVJJQ29tcG9uZW50KG1hbmlmZXN0LmlkKX0vbWFya2Vycy8ke2VuY29kZVVSSUNvbXBvbmVudChjb2x1bW4pfT9uPSR7cGVyR3JvdXB9YCxcbiAgICApKTtcbiAgfVxuXG4gIGdldFRyYW5zY3JpcHRDb3VudHMoZ2VuZXM6IHN0cmluZ1tdKTogUHJvbWlzZTxTcGF0aWFsVHJhbnNjcmlwdENvdW50cz4ge1xuICAgIGNvbnN0IG1hbmlmZXN0ID0gdGhpcy5yZXF1aXJlTWFuaWZlc3QoKTtcbiAgICByZXR1cm4gdGhpcy5nZXRKc29uPFNwYXRpYWxUcmFuc2NyaXB0Q291bnRzPihcbiAgICAgIGBzcGF0aWFsLyR7ZW5jb2RlVVJJQ29tcG9uZW50KG1hbmlmZXN0LmlkKX0vdHJhbnNjcmlwdC1jb3VudHM/Z2VuZXM9JHtnZW5lcy5tYXAoZW5jb2RlVVJJQ29tcG9uZW50KS5qb2luKCcsJyl9YCxcbiAgICApO1xuICB9XG5cbiAgLyoqIExSVSBvdmVyIHRpbGUgcHJvbWlzZXMsIHNvIGNvbmN1cnJlbnQgYXNrcyBzaGFyZSBvbmUgcmVxdWVzdCBhbmQgYSBmYWlsdXJlIGlzIG5vdCBrZXB0LiAqL1xuICBwcml2YXRlIGNhY2hlZFRpbGU8VCBleHRlbmRzIFNwYXRpYWxQb2x5Z29uVGlsZSB8IFNwYXRpYWxUcmFuc2NyaXB0VGlsZT4oXG4gICAga2V5OiBzdHJpbmcsIGxvYWQ6ICgpID0+IFByb21pc2U8VD4sXG4gICk6IFByb21pc2U8VD4ge1xuICAgIGNvbnN0IGhpdCA9IHRoaXMudGlsZUNhY2hlLmdldChrZXkpO1xuICAgIGlmIChoaXQpIHtcbiAgICAgIHRoaXMudGlsZUNhY2hlLmRlbGV0ZShrZXkpO1xuICAgICAgdGhpcy50aWxlQ2FjaGUuc2V0KGtleSwgaGl0KTtcbiAgICAgIHJldHVybiBoaXQgYXMgUHJvbWlzZTxUPjtcbiAgICB9XG4gICAgY29uc3QgbWluZSA9IHRoaXMuc2VsZWN0VG9rZW47XG4gICAgY29uc3QgcHJvbWlzZSA9IGxvYWQoKS5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICBpZiAodGhpcy50aWxlQ2FjaGUuZ2V0KGtleSkgPT09IHByb21pc2UpIHRoaXMudGlsZUNhY2hlLmRlbGV0ZShrZXkpO1xuICAgICAgdGhyb3cgZXJyO1xuICAgIH0pO1xuICAgIGlmIChtaW5lID09PSB0aGlzLnNlbGVjdFRva2VuKSB7XG4gICAgICB0aGlzLnRpbGVDYWNoZS5zZXQoa2V5LCBwcm9taXNlKTtcbiAgICAgIHdoaWxlICh0aGlzLnRpbGVDYWNoZS5zaXplID4gU3BhdGlhbERhdGFIdHRwU2VydmljZS5USUxFX0NBQ0hFX0xJTUlUKSB7XG4gICAgICAgIHRoaXMudGlsZUNhY2hlLmRlbGV0ZSh0aGlzLnRpbGVDYWNoZS5rZXlzKCkubmV4dCgpLnZhbHVlISk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBwcm9taXNlO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSByZWZlcmVuY2Ugdm9sdW1lJ3Mgdm94ZWxzLCBzaW5nbGUtZmxpZ2h0ZWQgbGlrZSB0aGUgcG9seWdvbnMuXG4gICAqXG4gICAqIFZhbGlkYXRlZCBhZ2FpbnN0IHRoZSBtYW5pZmVzdCdzIGRlY2xhcmVkIGRpbWVuc2lvbnMgYmVmb3JlIGl0IGlzIGhhbmRlZFxuICAgKiBiYWNrOiBhIHNob3J0IG9yIGxvbmcgYnVmZmVyIHJlYWQgYXMgYSAzRCB0ZXh0dXJlIGRvZXMgbm90IGZhaWwsIGl0IHNoZWFyc1xuICAgKiB0aGUgYW5hdG9teSBpbnRvIGRpYWdvbmFsIHN0cmVha3MsIGFuZCB0aGF0IGlzIGZhciBoYXJkZXIgdG8gcmVjb2duaXNlIGFzIGFcbiAgICogdHJhbnNwb3J0IHByb2JsZW0gdGhhbiBhbiBlcnJvciBpcy5cbiAgICovXG4gIGdldFZvbHVtZSgpOiBQcm9taXNlPFVpbnQ4QXJyYXk+IHtcbiAgICBjb25zdCBtYW5pZmVzdCA9IHRoaXMucmVxdWlyZU1hbmlmZXN0KCk7XG4gICAgY29uc3QgbWV0YSA9IG1hbmlmZXN0LnZvbHVtZTtcbiAgICBpZiAoIW1ldGEpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoJ1tzcGF0aWFsXSB0aGlzIGRhdGFzZXQgaGFzIG5vIHJlZmVyZW5jZSB2b2x1bWUnKSk7XG4gICAgfVxuICAgIHRoaXMudm9sdW1lUHJvbWlzZSA/Pz0gdGhpc1xuICAgICAgLmdldEJpbmFyeShgc3BhdGlhbC8ke2VuY29kZVVSSUNvbXBvbmVudChtYW5pZmVzdC5pZCl9L3ZvbHVtZWApXG4gICAgICAudGhlbigoYnVmKSA9PiB7XG4gICAgICAgIGNvbnN0IHdhbnQgPSBtZXRhLndpZHRoICogbWV0YS5oZWlnaHQgKiBtZXRhLmRlcHRoO1xuICAgICAgICBpZiAoYnVmLmJ5dGVMZW5ndGggIT09IHdhbnQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICBgW3NwYXRpYWxdIHZvbHVtZSBpcyAke2J1Zi5ieXRlTGVuZ3RofSBieXRlcywgZXhwZWN0ZWQgJHt3YW50fSBgXG4gICAgICAgICAgICArIGAoJHttZXRhLndpZHRofXgke21ldGEuaGVpZ2h0fXgke21ldGEuZGVwdGh9KWAsXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoYnVmKTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goKGVycikgPT4geyB0aGlzLnZvbHVtZVByb21pc2UgPSBudWxsOyB0aHJvdyBlcnI7IH0pO1xuICAgIHJldHVybiB0aGlzLnZvbHVtZVByb21pc2U7XG4gIH1cblxuICAvLyDilIDilIAgaW50ZXJuYWxzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gIHByaXZhdGUgcmVxdWlyZU1hbmlmZXN0KCk6IFNwYXRpYWxNYW5pZmVzdCB7XG4gICAgaWYgKCF0aGlzLm1hbmlmZXN0IHx8ICF0aGlzLmRhdGFzZXQkLnZhbHVlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1tzcGF0aWFsXSBubyBkYXRhc2V0IHNlbGVjdGVkIOKAlCBjYWxsIHNlbGVjdERhdGFzZXQoKSBmaXJzdCcpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5tYW5pZmVzdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWNoZSArIHNpbmdsZS1mbGlnaHQgYXJvdW5kIGEgdmVjdG9yIGZldGNoLlxuICAgKlxuICAgKiBLZXlzIGFyZSBMT0dJQ0FMIOKAlCBgZmVhdHVyZTpHQVBESGAsIG5vdCBgPGRhdGFzZXQ+L2ZlYXR1cmU6R0FQREhgIOKAlCBiZWNhdXNlIGBjbGVhcigpYFxuICAgKiBlbXB0aWVzIHRoZSBtYXBzIG9uIGV2ZXJ5IHN3aXRjaCwgc28gdHdvIGRhdGFzZXRzIG5ldmVyIGhvbGQgZW50cmllcyBhdCBvbmNlLiBXaGF0XG4gICAqIHRoYXQgZG9lcyBub3QgY292ZXIgaXMgYSByZXF1ZXN0IHN0aWxsIGluIHRoZSBhaXIgd2hlbiB0aGUgc3dpdGNoIGhhcHBlbnM6IGBjbGVhcigpYFxuICAgKiBjYW5ub3QgY2FuY2VsIGFuIEhUVFAgY2FsbCwgc28gYSB2ZWN0b3IgZmV0Y2hlZCBmb3IgZGF0YXNldCBBIGNhbiByZXNvbHZlIGFmdGVyIEIgaGFzXG4gICAqIGJlZW4gc2VsZWN0ZWQgYW5kIHdyaXRlIGl0c2VsZiBpbnRvIEIncyBjYWNoZSB1bmRlciBhIGtleSBCIHdvdWxkIHJlYWQuIEJvdGggZGF0YXNldHNcbiAgICogaGF2aW5nIGEgZ2VuZSBvZiB0aGF0IG5hbWUgaXMgdGhlIGNvbW1vbiBjYXNlLCBub3QgdGhlIHVubHVja3kgb25lLCBhbmQgdGhlIHJlc3VsdCBpc1xuICAgKiBhIHBsb3Qgb2YgQSdzIGV4cHJlc3Npb24gb3ZlciBCJ3MgY2VsbHMg4oCUIHdoaWNoIGxvb2tzIGxpa2UgZGF0YSwgbm90IGxpa2UgYSBmYXVsdC5cbiAgICpcbiAgICogU28gdGhlIGdlbmVyYXRpb24gaXMgY2hlY2tlZCBhZnRlciB0aGUgYXdhaXQsIGFuZCB0aGUgaW4tZmxpZ2h0IHNsb3QgaXMgY2xlYXJlZCBvbmx5XG4gICAqIHdoZW4gdGhlIHByb21pc2Ugc3RpbGwgc2l0dGluZyBpbiBpdCBpcyB0aGlzIG9uZTogYSBsYXRlIGFycml2YWwgbXVzdCBub3QgZXZpY3QgdGhlXG4gICAqIGVudHJ5IGEgbmV3ZXIgcmVxdWVzdCBmb3IgdGhlIHNhbWUga2V5IGlzIGFscmVhZHkgc2hhcmluZy5cbiAgICovXG4gIHByaXZhdGUgZmV0Y2hDYWNoZWQoa2V5OiBzdHJpbmcsIGxvYWQ6ICgpID0+IFByb21pc2U8Q2FjaGVkUGF5bG9hZD4pOiBQcm9taXNlPENhY2hlZFBheWxvYWQ+IHtcbiAgICBjb25zdCBoaXQgPSB0aGlzLmNhY2hlLmdldChrZXkpO1xuICAgIGlmIChoaXQpIHtcbiAgICAgIC8vIFJlLWluc2VydCB0byBtYXJrIG1vc3QtcmVjZW50bHktdXNlZCAoTWFwIHByZXNlcnZlcyBpbnNlcnRpb24gb3JkZXIpLlxuICAgICAgdGhpcy5jYWNoZS5kZWxldGUoa2V5KTtcbiAgICAgIHRoaXMuY2FjaGUuc2V0KGtleSwgaGl0KTtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoaGl0KTtcbiAgICB9XG4gICAgY29uc3QgcGVuZGluZyA9IHRoaXMuaW5GbGlnaHQuZ2V0KGtleSk7XG4gICAgaWYgKHBlbmRpbmcpIHJldHVybiBwZW5kaW5nO1xuXG4gICAgY29uc3QgbWluZSA9IHRoaXMuc2VsZWN0VG9rZW47XG4gICAgY29uc3QgcHJvbWlzZTogUHJvbWlzZTxDYWNoZWRQYXlsb2FkPiA9IGxvYWQoKVxuICAgICAgLnRoZW4oKHZhbHVlKSA9PiB7XG4gICAgICAgIC8vIFN0aWxsIHJldHVybmVkIHRvIHRoZSBjYWxsZXIgdGhhdCBhc2tlZDogaXQgbWF5IHdlbGwgYmUgYSBjb21wb25lbnQgdGhhdCBpc1xuICAgICAgICAvLyBpdHNlbGYgYmVpbmcgdG9ybiBkb3duLCBhbmQgcmVqZWN0aW5nIGhlcmUgd291bGQgc3VyZmFjZSBhIHN3aXRjaCBhcyBhbiBlcnJvci5cbiAgICAgICAgLy8gV2hhdCBtdXN0IG5vdCBoYXBwZW4gaXMgdGhlIHZhbHVlIGJlaW5nIGtlcHQgZm9yIHdob2V2ZXIgY29tZXMgbmV4dC5cbiAgICAgICAgaWYgKG1pbmUgPT09IHRoaXMuc2VsZWN0VG9rZW4pIHtcbiAgICAgICAgICB0aGlzLmNhY2hlLnNldChrZXksIHZhbHVlKTtcbiAgICAgICAgICB0aGlzLmV2aWN0KCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgfSlcbiAgICAgIC5maW5hbGx5KCgpID0+IHtcbiAgICAgICAgaWYgKHRoaXMuaW5GbGlnaHQuZ2V0KGtleSkgPT09IHByb21pc2UpIHRoaXMuaW5GbGlnaHQuZGVsZXRlKGtleSk7XG4gICAgICB9KTtcbiAgICB0aGlzLmluRmxpZ2h0LnNldChrZXksIHByb21pc2UpO1xuICAgIHJldHVybiBwcm9taXNlO1xuICB9XG5cbiAgcHJpdmF0ZSBldmljdCgpOiB2b2lkIHtcbiAgICB3aGlsZSAodGhpcy5jYWNoZS5zaXplID4gU3BhdGlhbERhdGFIdHRwU2VydmljZS5DQUNIRV9MSU1JVCkge1xuICAgICAgY29uc3Qgb2xkZXN0ID0gdGhpcy5jYWNoZS5rZXlzKCkubmV4dCgpLnZhbHVlIGFzIHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICAgIGlmIChvbGRlc3QgPT09IHVuZGVmaW5lZCkgYnJlYWs7XG4gICAgICB0aGlzLmNhY2hlLmRlbGV0ZShvbGRlc3QpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZ2V0SnNvbjxUPihwYXRoOiBzdHJpbmcpOiBQcm9taXNlPFQ+IHtcbiAgICByZXR1cm4gZmlyc3RWYWx1ZUZyb20oXG4gICAgICB0aGlzLmh0dHAuZ2V0PFQ+KGAke3RoaXMuYmFzZVVybH0ke3BhdGh9YCkucGlwZSh0aW1lb3V0KHRoaXMudGltZW91dE1zKSksXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0QmluYXJ5KHBhdGg6IHN0cmluZyk6IFByb21pc2U8QXJyYXlCdWZmZXI+IHtcbiAgICByZXR1cm4gZmlyc3RWYWx1ZUZyb20oXG4gICAgICB0aGlzLmh0dHAuZ2V0KGAke3RoaXMuYmFzZVVybH0ke3BhdGh9YCwgeyByZXNwb25zZVR5cGU6ICdhcnJheWJ1ZmZlcicgfSlcbiAgICAgICAgLnBpcGUodGltZW91dCh0aGlzLnRpbWVvdXRNcykpLFxuICAgICk7XG4gIH1cbn1cbiJdfQ==
513
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3BhdGlhbC1kYXRhLWh0dHAuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvaW1wbGVtZW50YXRpb25zL3NwYXRpYWwtZGF0YS1odHRwL3NwYXRpYWwtZGF0YS1odHRwLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBcUIsTUFBTSxzQkFBc0IsQ0FBQztBQUNyRSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ3JDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUFFLGVBQWUsRUFBYyxjQUFjLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDbkUsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRXpDLE9BQU8sRUFBRSxTQUFTLEVBQXdDLE1BQU0seUNBQXlDLENBQUM7QUFDMUcsT0FBTyxFQVlMLGNBQWMsR0FDZixNQUFNLDBDQUEwQyxDQUFDO0FBQ2xELE9BQU8sRUFHTCxxQkFBcUIsRUFDckIsbUJBQW1CLEVBQ25CLFlBQVksRUFDWixZQUFZLEVBQ1osYUFBYSxFQUNiLGVBQWUsRUFDZixtQkFBbUIsRUFDbkIsaUJBQWlCLEVBQ2pCLGNBQWMsRUFDZCxZQUFZLEVBQ1osb0JBQW9CLEdBQ3JCLE1BQU0sZ0JBQWdCLENBQUM7QUFDeEIsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQzVELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQzs7O0FBRWpEOzs7OztHQUtHO0FBQ0gsTUFBTSxPQUFPLGVBQWdCLFNBQVEsS0FBSztJQUN4QyxZQUFZLEVBQVU7UUFDcEIsS0FBSyxDQUFDLDJCQUEyQixFQUFFLGlDQUFpQyxDQUFDLENBQUM7UUFDdEUsSUFBSSxDQUFDLElBQUksR0FBRyxpQkFBaUIsQ0FBQztJQUNoQyxDQUFDO0NB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cm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XG5pbXBvcnQgeyBMcnVDYWNoZSB9IGZyb20gJ25hcGFyaS1qcyc7XG5pbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIE9ic2VydmFibGUsIGZpcnN0VmFsdWVGcm9tIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyB0aW1lb3V0IH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQgeyBBTExfR0VORVMsIFNwYXRpYWxEYXRhUG9ydCwgVHJhbnNjcmlwdFRpbGVRdWVyeSB9IGZyb20gJy4uLy4uL2NvbnRyYWN0cy9wb3J0cy9zcGF0aWFsLWRhdGEucG9ydCc7XG5pbXBvcnQge1xuICBTcGF0aWFsQ29sdW1uLFxuICBTcGF0aWFsRGF0YXNldCxcbiAgU3BhdGlhbERlbnNpdHlSYXN0ZXIsXG4gIFNwYXRpYWxFbWJlZGRpbmcsXG4gIFNwYXRpYWxQb2x5Z29uVGlsZSxcbiAgU3BhdGlhbFBvbHlnb25zLFxuICBDYXRlZ29yaWNhbENvbHVtbk1ldGEsXG4gIFNwYXRpYWxNYXJrZXJHZW5lcyxcbiAgU3BhdGlhbFRyYW5zY3JpcHRDb3VudHMsXG4gIFNwYXRpYWxUcmFuc2NyaXB0U3VtbWFyeSxcbiAgU3BhdGlhbFRyYW5zY3JpcHRUaWxlLFxuICBmaW5kQ29sdW1uTWV0YSxcbn0gZnJvbSAnLi4vLi4vY29udHJhY3RzL3NwYXRpYWwtZGF0YXNldC5jb250cmFjdCc7XG5pbXBvcnQge1xuICBTcGF0aWFsRGF0YXNldFN1bW1hcnksXG4gIFNwYXRpYWxNYW5pZmVzdCxcbiAgYXNzZXJ0TWFuaWZlc3RWZXJzaW9uLFxuICBkYXRhc2V0RnJvbU1hbmlmZXN0LFxuICBkZWNvZGVDb2x1bW4sXG4gIGRlY29kZUNvb3JkcyxcbiAgZGVjb2RlRGVuc2l0eSxcbiAgZGVjb2RlRW1iZWRkaW5nLFxuICBkZWNvZGVGZWF0dXJlVmVjdG9yLFxuICBkZWNvZGVQb2x5Z29uVGlsZSxcbiAgZGVjb2RlUG9seWdvbnMsXG4gIGRlY29kZVJhZGl1cyxcbiAgZGVjb2RlVHJhbnNjcmlwdFRpbGUsXG59IGZyb20gJy4vc3BhdGlhbC13aXJlJztcbmltcG9ydCB7IHNlYXJjaEdlbmVOYW1lcyB9IGZyb20gJy4uLy4uL3NwYXRpYWwvZ2VuZS1zZWFyY2gnO1xuaW1wb3J0IHsgU3VwZXJzZWRlIH0gZnJvbSAnLi4vLi4vdXRpbC9zdXBlcnNlZGUnO1xuXG4vKipcbiAqIEEgZGF0YXNldCBzZWxlY3Rpb24gdGhhdCBhIG5ld2VyIHNlbGVjdGlvbiAob3IgYSBgY2xlYXJgKSBvdmVydG9vay5cbiAqXG4gKiBUaHJvd24gcmF0aGVyIHRoYW4gcmVzb2x2ZWQgc28gYSBjYWxsZXIgY2Fubm90IG1pc3Rha2UgaXQgZm9yIFwidGhpcyBkYXRhc2V0IGlzXG4gKiBub3cgbG9hZGVkXCI6IG5vdGhpbmcgd2FzIHB1Ymxpc2hlZCwgb24gcHVycG9zZS5cbiAqL1xuZXhwb3J0IGNsYXNzIFN1cGVyc2VkZWRFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgY29uc3RydWN0b3IoaWQ6IHN0cmluZykge1xuICAgIHN1cGVyKGBbc3BhdGlhbF0gc2VsZWN0aW9uIG9mIFwiJHtpZH1cIiB3YXMgc3VwZXJzZWRlZCBieSBhIG5ld2VyIG9uZWApO1xuICAgIHRoaXMubmFtZSA9ICdTdXBlcnNlZGVkRXJyb3InO1xuICB9XG59XG5cbi8qKlxuICogV2hhdCB0aGUgTFJVIGNhbiBob2xkLiBPbmUgYWxpYXMgcmF0aGVyIHRoYW4gYSB1bmlvbiByZXBlYXRlZCBhdCBlYWNoIHVzZSwgc28gYWRkaW5nIGEgcGF5bG9hZFxuICoga2luZCBpcyBhIHNpbmdsZSBlZGl0IGluc3RlYWQgb2YgZm91ciB0aGF0IGNhbiBkcmlmdCBhcGFydC5cbiAqL1xudHlwZSBDYWNoZWRQYXlsb2FkID0gU3BhdGlhbENvbHVtbiB8IEZsb2F0MzJBcnJheSB8IFNwYXRpYWxFbWJlZGRpbmcgfCBTcGF0aWFsRGVuc2l0eVJhc3RlcjtcblxuLyoqXG4gKiBCeXRlcyBhIGRlY29kZWQgcGF5bG9hZCBob2xkczogaXRzIG93biB0eXBlZC1hcnJheSB2aWV3cywgb25lIGxldmVsIGRlZXAg4oCUIGV2ZXJ5XG4gKiBwYXlsb2FkIGhlcmUgaXMgYSB0eXBlZCBhcnJheSBvciBhIGZsYXQgcmVjb3JkIG9mIHRoZW0uXG4gKi9cbmZ1bmN0aW9uIHBheWxvYWRCeXRlcyh2YWx1ZTogdW5rbm93bik6IG51bWJlciB7XG4gIGlmIChBcnJheUJ1ZmZlci5pc1ZpZXcodmFsdWUpKSByZXR1cm4gdmFsdWUuYnl0ZUxlbmd0aDtcbiAgbGV0IGJ5dGVzID0gMDtcbiAgaWYgKHZhbHVlICYmIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcpIHtcbiAgICBmb3IgKGNvbnN0IHYgb2YgT2JqZWN0LnZhbHVlcyh2YWx1ZSkpIGlmIChBcnJheUJ1ZmZlci5pc1ZpZXcodikpIGJ5dGVzICs9IHYuYnl0ZUxlbmd0aDtcbiAgfVxuICByZXR1cm4gYnl0ZXM7XG59XG5cbmNvbnN0IE1pQiA9IDEwMjQgKiAxMDI0O1xuXG4vKipcbiAqIFJlZmVyZW5jZSB7QGxpbmsgU3BhdGlhbERhdGFQb3J0fSBhZGFwdGVyIGZvciB0aGUgd2lyZSBmb3JtYXQgdGhlIGJ1bmRsZWRcbiAqIGV4YW1wbGUgc2VydmVyIHNwZWFrcyAoc2VlIGBzcGF0aWFsLXdpcmUudHNgIGFuZFxuICogYGV4YW1wbGVzL3RpbGUtc2VydmVyL2xpYi9zcGF0aWFsLm1qc2ApLlxuICpcbiAqIE9QVElPTkFMIEFORCBVTkJPVU5EIEJZIERFRkFVTFQg4oCUIHRoaXMgc2VydmljZSBpcyBgQEluamVjdGFibGUoKWAgd2l0aG91dFxuICogYHByb3ZpZGVkSW5gLCBzbyBub3RoaW5nIGdldHMgaXQgdW5sZXNzIGEgaG9zdCBleHBsaWNpdGx5IHByb3ZpZGVzIGl0OlxuICpcbiAqIGBgYHRzXG4gKiBwcm92aWRlcnM6IFtcbiAqICAgU3BhdGlhbERhdGFIdHRwU2VydmljZSxcbiAqICAgeyBwcm92aWRlOiBTUEFUSUFMX0RBVEFfUE9SVCwgdXNlRXhpc3Rpbmc6IFNwYXRpYWxEYXRhSHR0cFNlcnZpY2UgfSxcbiAqIF1cbiAqIGBgYFxuICpcbiAqIFRoYXQgbWlycm9ycyBgQ2VsbHBvc2VTZWdtZW50ZXJTZXJ2aWNlYDogYSBjb25jcmV0ZSBpbXBsZW1lbnRhdGlvbiB0aGVcbiAqIGxpYnJhcnkgc2hpcHMgZm9yIGNvbnZlbmllbmNlLCBub3QgYSBkZWZhdWx0IHRoZSBwb3J0IGludmVyc2lvbiBpcyBxdWlldGx5XG4gKiBnaXZpbmcgdXAgb24uIEEgaG9zdCB3aXRoIGl0cyBvd24gYmFja2VuZCBpbXBsZW1lbnRzIGBTcGF0aWFsRGF0YVBvcnRgXG4gKiBkaXJlY3RseSBhbmQgbmV2ZXIgdG91Y2hlcyB0aGlzIGNsYXNzLlxuICpcbiAqIFJlcXVlc3RzIGdvIHRocm91Z2ggQW5ndWxhcidzIGBIdHRwQ2xpZW50YCAobm90IGBmZXRjaGApIHNvIHRoZSBob3N0J3NcbiAqIGludGVyY2VwdG9ycyDigJQgYXV0aCBoZWFkZXJzIGFib3ZlIGFsbCDigJQgYXBwbHksIG1hdGNoaW5nIGB0aWxlLWNsaWVudC50c2AuXG4gKi9cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBTcGF0aWFsRGF0YUh0dHBTZXJ2aWNlIGltcGxlbWVudHMgU3BhdGlhbERhdGFQb3J0IHtcbiAgLyoqIFNlcnZlciByb290LCBub3JtYWxpc2VkIHRvIGVuZCB3aXRoIGV4YWN0bHkgb25lIGAvYC4gKi9cbiAgcHJpdmF0ZSBiYXNlVXJsID0gJyc7XG4gIC8qKiBQZXItcmVxdWVzdCBjZWlsaW5nLiBWZWN0b3JzIGFyZSBzbWFsbDsgYSBodW5nIHJlcXVlc3Qgc2hvdWxkIG5vdCB3ZWRnZVxuICAgKiAgdGhlIHBpY2tlci4gKi9cbiAgcHJpdmF0ZSB0aW1lb3V0TXMgPSAzMF8wMDA7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBkYXRhc2V0JCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8U3BhdGlhbERhdGFzZXQgfCBudWxsPihudWxsKTtcbiAgcHJpdmF0ZSBtYW5pZmVzdDogU3BhdGlhbE1hbmlmZXN0IHwgbnVsbCA9IG51bGw7XG4gIC8qKiBBZHZhbmNlZCBieSBldmVyeSBgc2VsZWN0RGF0YXNldGAgYW5kIGV2ZXJ5IGBjbGVhcmAsIHNvIGEgc2VsZWN0aW9uIHRoYXRcbiAgICogIGZpbmlzaGVzIGFmdGVyIGEgbmV3ZXIgaW50ZW50IGNhbiB0ZWxsIGFuZCBkcm9wIHdoYXQgaXQgZmV0Y2hlZC4gQ2FjaGUgZmlsbHNcbiAgICogIHRha2UgYSB7QGxpbmsgU3VwZXJzZWRlLmN1cnJlbnQgc25hcHNob3R9IG9mIGl0LCBzbyBhIHZlY3RvciBvciB0aWxlIHRoYXQgbGFuZHNcbiAgICogIGFmdGVyIGEgc3dpdGNoIGlzIHJldHVybmVkIHRvIGl0cyBjYWxsZXIgYnV0IG5ldmVyIGtlcHQgZm9yIHRoZSBuZXh0IGRhdGFzZXQuICovXG4gIHByaXZhdGUgcmVhZG9ubHkgc2VsZWN0aW9uID0gbmV3IFN1cGVyc2VkZSgpO1xuXG4gIC8qKlxuICAgKiBMb2FkZWQgdmVjdG9ycywga2V5ZWQgYGNvbHVtbjo8bmFtZT5gIC8gYGZlYXR1cmU6PG5hbWU+YC4gQm91bmRlZCBMUlU6XG4gICAqIGNvbG91cmluZyBieSBjbHVzdGVyIOKGkiBieSBhIGdlbmUg4oaSIGJhY2sgYnkgY2x1c3RlciBtdXN0IG5vdCByZWZldGNoLCBidXQgYW5cbiAgICogYWZ0ZXJub29uIG9mIGJyb3dzaW5nIGdlbmVzIG11c3Qgbm90IGdyb3cgd2l0aG91dCBsaW1pdCBlaXRoZXIuXG4gICAqXG4gICAqIEJvdW5kZWQgYnkgQllURVMgYXMgd2VsbCBhcyBlbnRyaWVzOiBvbmUgdmVjdG9yIGlzIGA0wrdOYCBieXRlcyDigJQgMiBNQiBhdCA1MDBrXG4gICAqIGNlbGxzLCBidXQgMTQuOCBNQiBhdCAzLjdNLCB3aGVyZSAzMiBlbnRyaWVzIChhbiBlbWJlZGRpbmcgaXMgdHdvIG9yIHRocmVlXG4gICAqIHZlY3RvcnMpIGNvdWxkIHBpbiBjbG9zZSB0byBoYWxmIGEgZ2lnYWJ5dGUuXG4gICAqL1xuICBwcml2YXRlIHJlYWRvbmx5IGNhY2hlID0gbmV3IE1hcDxzdHJpbmcsIHsgdmFsdWU6IENhY2hlZFBheWxvYWQ7IGJ5dGVzOiBudW1iZXIgfT4oKTtcbiAgcHJpdmF0ZSBjYWNoZWRCeXRlcyA9IDA7XG4gIHByaXZhdGUgc3RhdGljIHJlYWRvbmx5IENBQ0hFX0xJTUlUID0gMzI7XG4gIHByaXZhdGUgY2FjaGVCeXRlcyA9IDI1NiAqIE1pQjtcblxuICAvKiogSW4tZmxpZ2h0IHJlcXVlc3RzLCBzbyBkb3VibGUtY2xpY2tpbmcgYSBnZW5lIGlzc3VlcyBvbmUgZmV0Y2guICovXG4gIHByaXZhdGUgcmVhZG9ubHkgaW5GbGlnaHQgPSBuZXcgTWFwPHN0cmluZywgUHJvbWlzZTxDYWNoZWRQYXlsb2FkPj4oKTtcblxuICAvKipcbiAgICogVGlsZXMgZ2V0IHRoZWlyIG93biwgbGFyZ2VyIGNhY2hlOiBwYW5uaW5nIHJldmlzaXRzIHRoZW0gY29uc3RhbnRseSwgYW5kIG9uZSBzY3JlZW5cbiAgICogb2YgYSB6b29tZWQtb3V0IHNlY3Rpb24gaXMgZG96ZW5zIG9mIHRoZW0g4oCUIGZhciBwYXN0IHRoZSB2ZWN0b3IgY2FjaGUncyBsaW1pdC5cbiAgICovXG4gIHByaXZhdGUgcmVhZG9ubHkgdGlsZUNhY2hlID0gbmV3IE1hcDxzdHJpbmcsIFByb21pc2U8U3BhdGlhbFBvbHlnb25UaWxlIHwgU3BhdGlhbFRyYW5zY3JpcHRUaWxlPj4oKTtcbiAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgVElMRV9DQUNIRV9MSU1JVCA9IDM4NDtcbiAgLyoqIEJ5dGVzIG9mIGVhY2ggUkVTT0xWRUQgdGlsZSBpbiB7QGxpbmsgdGlsZUNhY2hlfTsgYSBwZW5kaW5nIG9uZSBjb3VudHMgb25jZSBpdCBsYW5kcy4gKi9cbiAgcHJpdmF0ZSByZWFkb25seSB0aWxlQnl0ZXMgPSBuZXcgTWFwPHN0cmluZywgbnVtYmVyPigpO1xuICBwcml2YXRlIHRpbGVCeXRlc1RvdGFsID0gMDtcbiAgcHJpdmF0ZSB0aWxlQ2FjaGVCeXRlcyA9IDEyOCAqIE1pQjtcblxuICBwcml2YXRlIHZvbHVtZVByb21pc2U6IFByb21pc2U8VWludDhBcnJheT4gfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBwb2x5Z29uc1Byb21pc2U6IFByb21pc2U8U3BhdGlhbFBvbHlnb25zPiB8IG51bGwgPSBudWxsO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgaHR0cDogSHR0cENsaWVudCkge31cblxuICAvLyDilIDilIAgY29uZmlndXJhdGlvbiDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICAvKipcbiAgICogUG9pbnQgdGhlIGFkYXB0ZXIgYXQgYSBzZXJ2ZXIuIENsZWFycyBhbnkgbG9hZGVkIGRhdGFzZXQuXG4gICAqXG4gICAqIGBjYWNoZUJ5dGVzYCAvIGB0aWxlQ2FjaGVCeXRlc2AgY2FwIHRoZSBkZWNvZGVkIHZlY3RvcnMgKGRlZmF1bHQgMjU2IE1pQikgYW5kIHRpbGVzXG4gICAqIChkZWZhdWx0IDEyOCBNaUIpIGtlcHQgZm9yIHJldXNlOyB0aGUgbW9zdCByZWNlbnQgZW50cnkgaXMgYWx3YXlzIGtlcHQuXG4gICAqL1xuICBjb25maWd1cmUob3B0aW9uczogeyBiYXNlVXJsOiBzdHJpbmc7IHRpbWVvdXRNcz86IG51bWJlcjsgY2FjaGVCeXRlcz86IG51bWJlcjsgdGlsZUNhY2hlQnl0ZXM/OiBudW1iZXIgfSk6IHZvaWQge1xuICAgIGNvbnN0IHJhdyA9IG9wdGlvbnMuYmFzZVVybCA/PyAnJztcbiAgICB0aGlzLmJhc2VVcmwgPSByYXcuZW5kc1dpdGgoJy8nKSA/IHJhdyA6IGAke3Jhd30vYDtcbiAgICBpZiAob3B0aW9ucy50aW1lb3V0TXMgIT09IHVuZGVmaW5lZCkgdGhpcy50aW1lb3V0TXMgPSBvcHRpb25zLnRpbWVvdXRNcztcbiAgICBpZiAob3B0aW9ucy5jYWNoZUJ5dGVzICE9PSB1bmRlZmluZWQpIHRoaXMuY2FjaGVCeXRlcyA9IG9wdGlvbnMuY2FjaGVCeXRlcztcbiAgICBpZiAob3B0aW9ucy50aWxlQ2FjaGVCeXRlcyAhPT0gdW5kZWZpbmVkKSB0aGlzLnRpbGVDYWNoZUJ5dGVzID0gb3B0aW9ucy50aWxlQ2FjaGVCeXRlcztcbiAgICB0aGlzLmNsZWFyKCk7XG4gIH1cblxuICAvKiogRGF0YXNldHMgdGhpcyBzZXJ2ZXIgb2ZmZXJzLCBmb3IgYSBob3N0LXNpZGUgcGlja2VyLiAqL1xuICBsaXN0RGF0YXNldHMoKTogUHJvbWlzZTxTcGF0aWFsRGF0YXNldFN1bW1hcnlbXT4ge1xuICAgIHJldHVybiB0aGlzLmdldEpzb248eyBkYXRhc2V0czogU3BhdGlhbERhdGFzZXRTdW1tYXJ5W10gfT4oJ3NwYXRpYWwvZGF0YXNldHMnKS50aGVuKChyKSA9PiByLmRhdGFzZXRzID8/IFtdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBPbmUgZGF0YXNldCdzIG1hbmlmZXN0LCBXSVRIT1VUIHNlbGVjdGluZyBpdC4gTGV0cyBhIGhvc3QgaW5zcGVjdCB3aGF0IGFcbiAgICogc2VydmVyIG9mZmVycyDigJQgY29sdW1uIGFuZCBmZWF0dXJlIG1ldGFkYXRhLCBhbmQgd2hpY2ggaW1hZ2UgYSBkYXRhc2V0XG4gICAqIHJlZ2lzdGVycyBvbnRvIOKAlCB3aGlsZSBidWlsZGluZyBhIHBpY2tlciwgcmF0aGVyIHRoYW4gaGF2aW5nIHRvIGxvYWQgZWFjaFxuICAgKiBkYXRhc2V0IHRvIGZpbmQgb3V0LlxuICAgKi9cbiAgcmVhZE1hbmlmZXN0KGlkOiBzdHJpbmcpOiBQcm9taXNlPFNwYXRpYWxNYW5pZmVzdD4ge1xuICAgIHJldHVybiB0aGlzLmdldEpzb248U3BhdGlhbE1hbmlmZXN0Pihgc3BhdGlhbC8ke2VuY29kZVVSSUNvbXBvbmVudChpZCl9L21hbmlmZXN0YCkudGhlbigobWFuaWZlc3QpID0+IHtcbiAgICAgIGFzc2VydE1hbmlmZXN0VmVyc2lvbihtYW5pZmVzdCk7XG4gICAgICByZXR1cm4gbWFuaWZlc3Q7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogTG9hZCBhIGRhdGFzZXQgYW5kIHB1Ymxpc2ggaXQgb24ge0BsaW5rIGdldERhdGFzZXQkfS4gRmV0Y2hlcyB0aGUgbWFuaWZlc3QsXG4gICAqIHRoZW4sIGluIHBhcmFsbGVsLCB0aGUgdmVjdG9ycyB0aGF0IGFyZSBhbHdheXMgbmVlZGVkIChjb29yZGluYXRlcywgYW5kXG4gICAqIGlkcy9yYWRpdXMgd2hlbiB0aGUgbWFuaWZlc3Qgc2F5cyB0aGV5IGV4aXN0KSDigJQgbm90aGluZyBlbHNlLlxuICAgKi9cbiAgYXN5bmMgc2VsZWN0RGF0YXNldChpZDogc3RyaW5nKTogUHJvbWlzZTxTcGF0aWFsRGF0YXNldD4ge1xuICAgIHRoaXMuY2xlYXIoKTtcbiAgICAvLyBTZWxlY3Rpb25zIGFyZSBTRVFVRU5DRUQ6IHRoaXMgaXMgdHdvIGF3YWl0cyBkZWVwLCBzbyBhIHNsb3dlciBlYXJsaWVyXG4gICAgLy8gY2FsbCB3b3VsZCBvdGhlcndpc2UgYXNzaWduIGB0aGlzLm1hbmlmZXN0YCBvciBwdWJsaXNoIGl0cyBkYXRhc2V0IGFmdGVyIGFcbiAgICAvLyBsYXRlciBvbmUg4oCUIGxlYXZpbmcgdGhlIG1hbmlmZXN0IGFuZCB0aGUgb2JzZXJ2YXRpb25zIGZyb20gdHdvIGRpZmZlcmVudFxuICAgIC8vIGRhdGFzZXRzLCB3aGljaCBpcyB3b3JzZSB0aGFuIGVpdGhlciBiZWluZyBsYXRlLlxuICAgIGNvbnN0IHRhc2sgPSB0aGlzLnNlbGVjdGlvbi5uZXh0KCk7XG4gICAgY29uc3Qgc3VwZXJzZWRlZCA9ICgpID0+ICF0YXNrLmlzQ3VycmVudCgpO1xuICAgIGNvbnN0IHBhdGggPSBgc3BhdGlhbC8ke2VuY29kZVVSSUNvbXBvbmVudChpZCl9YDtcblxuICAgIGNvbnN0IG1hbmlmZXN0ID0gYXdhaXQgdGhpcy5nZXRKc29uPFNwYXRpYWxNYW5pZmVzdD4oYCR7cGF0aH0vbWFuaWZlc3RgKTtcbiAgICBhc3NlcnRNYW5pZmVzdFZlcnNpb24obWFuaWZlc3QpO1xuICAgIGlmIChzdXBlcnNlZGVkKCkpIHRocm93IG5ldyBTdXBlcnNlZGVkRXJyb3IoaWQpO1xuICAgIHRoaXMubWFuaWZlc3QgPSBtYW5pZmVzdDtcblxuICAgIC8vIEluZGVwZW5kZW50IG9mIGVhY2ggb3RoZXIsIHNvIHJlcXVlc3RlZCB0b2dldGhlcjogdGltZSB0byBmaXJzdCBwYWludCBpcyB0aGVcbiAgICAvLyBzbG93ZXN0IG9mIHRoZW0sIG5vdCB0aGVpciBzdW0gKHRoZSBpZHMgSlNPTiBhbG9uZSBpcyB0ZW5zIG9mIE1CIG9uIGEgbGFyZ2UgZGF0YXNldCkuXG4gICAgY29uc3QgW2Nvb3Jkc0J1ZiwgaWRzLCByYWRpdXNCdWZdID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgdGhpcy5nZXRCaW5hcnkoYCR7cGF0aH0vY29vcmRzYCksXG4gICAgICBtYW5pZmVzdC5oYXNJZHMgPyB0aGlzLmdldEpzb248eyBpZHM6IHN0cmluZ1tdIH0+KGAke3BhdGh9L2lkc2ApLnRoZW4oKHIpID0+IHIuaWRzKSA6IHVuZGVmaW5lZCxcbiAgICAgIG1hbmlmZXN0LnJhZGl1cz8ubW9kZSA9PT0gJ3Blci1vYnNlcnZhdGlvbicgPyB0aGlzLmdldEJpbmFyeShgJHtwYXRofS9yYWRpdXNgKSA6IHVuZGVmaW5lZCxcbiAgICBdKTtcbiAgICBpZiAoc3VwZXJzZWRlZCgpKSB0aHJvdyBuZXcgU3VwZXJzZWRlZEVycm9yKGlkKTtcbiAgICBjb25zdCBjb29yZHMgPSBkZWNvZGVDb29yZHMoY29vcmRzQnVmLCBtYW5pZmVzdC5jb3VudCwgISFtYW5pZmVzdC5oYXNaKTtcbiAgICBjb25zdCByYWRpdXMgPSByYWRpdXNCdWYgPyBkZWNvZGVSYWRpdXMocmFkaXVzQnVmLCBtYW5pZmVzdC5jb3VudCkgOiB1bmRlZmluZWQ7XG5cbiAgICBjb25zdCBkYXRhc2V0ID0gZGF0YXNldEZyb21NYW5pZmVzdChtYW5pZmVzdCwgY29vcmRzLCB7IGlkcywgcmFkaXVzIH0pO1xuICAgIHRoaXMuZGF0YXNldCQubmV4dChkYXRhc2V0KTtcbiAgICByZXR1cm4gZGF0YXNldDtcbiAgfVxuXG4gIC8qKiBEcm9wIHRoZSBsb2FkZWQgZGF0YXNldCBhbmQgZXZlcnkgY2FjaGVkIHZlY3Rvci4gKi9cbiAgY2xlYXIoKTogdm9pZCB7XG4gICAgLy8gQSBjbGVhciBpcyBpdHNlbGYgdGhlIG5ld2VzdCBpbnRlbnQsIHNvIGl0IHN1cGVyc2VkZXMgYW55IHNlbGVjdGlvbiBzdGlsbFxuICAgIC8vIGluIGZsaWdodCByYXRoZXIgdGhhbiBsZXR0aW5nIG9uZSBsYW5kIGFmdGVyd2FyZHMuXG4gICAgdGhpcy5zZWxlY3Rpb24uY2FuY2VsKCk7XG4gICAgdGhpcy5tYW5pZmVzdCA9IG51bGw7XG4gICAgdGhpcy5jYWNoZS5jbGVhcigpO1xuICAgIHRoaXMuY2FjaGVkQnl0ZXMgPSAwO1xuICAgIHRoaXMuaW5GbGlnaHQuY2xlYXIoKTtcbiAgICB0aGlzLnRpbGVDYWNoZS5jbGVhcigpO1xuICAgIHRoaXMudGlsZUJ5dGVzLmNsZWFyKCk7XG4gICAgdGhpcy50aWxlQnl0ZXNUb3RhbCA9IDA7XG4gICAgdGhpcy5zdW1tYXJ5Q2FjaGUuY2xlYXIoKTtcbiAgICB0aGlzLnBvbHlnb25zUHJvbWlzZSA9IG51bGw7XG4gICAgdGhpcy52b2x1bWVQcm9taXNlID0gbnVsbDtcbiAgICBpZiAodGhpcy5kYXRhc2V0JC52YWx1ZSAhPT0gbnVsbCkgdGhpcy5kYXRhc2V0JC5uZXh0KG51bGwpO1xuICB9XG5cbiAgLy8g4pSA4pSAIFNwYXRpYWxEYXRhUG9ydCDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBnZXREYXRhc2V0JCgpOiBPYnNlcnZhYmxlPFNwYXRpYWxEYXRhc2V0IHwgbnVsbD4ge1xuICAgIHJldHVybiB0aGlzLmRhdGFzZXQkLmFzT2JzZXJ2YWJsZSgpO1xuICB9XG5cbiAgZ2V0Q29sdW1uKG5hbWU6IHN0cmluZyk6IFByb21pc2U8U3BhdGlhbENvbHVtbj4ge1xuICAgIGNvbnN0IG1hbmlmZXN0ID0gdGhpcy5yZXF1aXJlTWFuaWZlc3QoKTtcbiAgICBjb25zdCBkYXRhc2V0ID0gdGhpcy5kYXRhc2V0JC52YWx1ZSE7XG4gICAgY29uc3QgbWV0YSA9IGZpbmRDb2x1bW5NZXRhKGRhdGFzZXQsIG5hbWUpO1xuICAgIGlmICghbWV0YSkge1xuICAgICAgLy8gUmVqZWN0IHJhdGhlciB0aGFuIHJlc29sdmUgZW1wdHk6IGEgdHlwbyBtdXN0IHN1cmZhY2UgYXMgYW4gZXJyb3IsIG5vdFxuICAgICAgLy8gYXMgYSBwbG90IHRoYXQgc2lsZW50bHkgcmVuZGVycyBldmVyeSBwb2ludCBhcyBcIm5vIGRhdGFcIi5cbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChcbiAgICAgICAgbmV3IEVycm9yKFxuICAgICAgICAgIGBbc3BhdGlhbF0gdW5rbm93biBjb2x1bW4gXCIke25hbWV9XCIuIEF2YWlsYWJsZTogJHtkYXRhc2V0LmNvbHVtbnMubWFwKChjKSA9PiBjLm5hbWUpLmpvaW4oJywgJyl9YCxcbiAgICAgICAgKSxcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmZldGNoQ2FjaGVkKGBjb2x1bW46JHtuYW1lfWAsICgpID0+XG4gICAgICB0aGlzLmdldEJpbmFyeShgc3BhdGlhbC8ke2VuY29kZVVSSUNvbXBvbmVudChtYW5pZmVzdC5pZCl9L2NvbHVtbi8ke2VuY29kZVVSSUNvbXBvbmVudChuYW1lKX1gKS50aGVuKChidWYpID0+XG4gICAgICAgIGRlY29kZUNvbHVtbihidWYsIG1ldGEsIG1hbmlmZXN0LmNvdW50KSxcbiAgICAgICksXG4gICAgKSBhcyBQcm9taXNlPFNwYXRpYWxDb2x1bW4+O1xuICB9XG5cbiAgZ2V0RW1iZWRkaW5nKG5hbWU6IHN0cmluZyk6IFByb21pc2U8U3BhdGlhbEVtYmVkZGluZz4ge1xuICAgIGNvbnN0IG1hbmlmZXN0ID0gdGhpcy5yZXF1aXJlTWFuaWZlc3QoKTtcbiAgICBjb25zdCBtZXRhID0gbWFuaWZlc3QuZW1iZWRkaW5ncz8uZmluZCgoZSkgPT4gZS5uYW1lID09PSBuYW1lKTtcbiAgICBpZiAoIW1ldGEpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoYFtzcGF0aWFsXSB1bmtub3duIGVtYmVkZGluZyBcIiR7bmFtZX1cImApKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuZmV0Y2hDYWNoZWQoYGVtYmVkZGluZzoke25hbWV9YCwgKCkgPT5cbiAgICAgIHRoaXMuZ2V0QmluYXJ5KGBzcGF0aWFsLyR7ZW5jb2RlVVJJQ29tcG9uZW50KG1hbmlmZXN0LmlkKX0vZW1iZWRkaW5nLyR7ZW5jb2RlVVJJQ29tcG9uZW50KG5hbWUpfWApLnRoZW4oXG4gICAgICAgIChidWYpID0+IGRlY29kZUVtYmVkZGluZyhidWYsIG1ldGEsIG1hbmlmZXN0LmNvdW50KSxcbiAgICAgICksXG4gICAgKSBhcyBQcm9taXNlPFNwYXRpYWxFbWJlZGRpbmc+O1xuICB9XG5cbiAgZ2V0RmVhdHVyZVZlY3RvcihuYW1lOiBzdHJpbmcpOiBQcm9taXNlPEZsb2F0MzJBcnJheT4ge1xuICAgIGNvbnN0IG1hbmlmZXN0ID0gdGhpcy5yZXF1aXJlTWFuaWZlc3QoKTtcbiAgICBjb25zdCBuYW1lcyA9IG1hbmlmZXN0LmZlYXR1cmVzPy5uYW1lcztcbiAgICBpZiAobmFtZXMgJiYgIW5hbWVzLmluY2x1ZGVzKG5hbWUpKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKGBbc3BhdGlhbF0gdW5rbm93biBmZWF0dXJlIFwiJHtuYW1lfVwiYCkpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5mZXRjaENhY2hlZChgZmVhdHVyZToke25hbWV9YCwgKCkgPT5cbiAgICAgIHRoaXMuZ2V0QmluYXJ5KGBzcGF0aWFsLyR7ZW5jb2RlVVJJQ29tcG9uZW50KG1hbmlmZXN0LmlkKX0vZmVhdHVyZS8ke2VuY29kZVVSSUNvbXBvbmVudChuYW1lKX1gKS50aGVuKFxuICAgICAgICAoYnVmKSA9PiBkZWNvZGVGZWF0dXJlVmVjdG9yKGJ1ZiwgbWFuaWZlc3QuY291bnQpLFxuICAgICAgKSxcbiAgICApIGFzIFByb21pc2U8RmxvYXQzMkFycmF5PjtcbiAgfVxuXG4gIGFzeW5jIHNlYXJjaEZlYXR1cmVzKHF1ZXJ5OiBzdHJpbmcsIGxpbWl0ID0gNTApOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gICAgY29uc3QgbWFuaWZlc3QgPSB0aGlzLnJlcXVpcmVNYW5pZmVzdCgpO1xuICAgIC8vIEEgZGF0YXNldCB0aGF0IGlubGluZWQgaXRzIG5hbWVzICh0YXJnZXRlZCBwYW5lbCkgaXMgZmlsdGVyZWQgbG9jYWxseSDigJRcbiAgICAvLyBubyByb3VuZC10cmlwIGZvciBhIGtleXN0cm9rZSDigJQgYW5kIHJhbmtlZCBhcyB0aGUgcGlja2VyIHJhbmtzIHRoZW0uXG4gICAgY29uc3QgbmFtZXMgPSBtYW5pZmVzdC5mZWF0dXJlcz8ubmFtZXM7XG4gICAgaWYgKG5hbWVzKSByZXR1cm4gc2VhcmNoR2VuZU5hbWVzKG5hbWVzLCBxdWVyeSwgbGltaXQpO1xuICAgIGNvbnN0IHVybCA9XG4gICAgICBgc3BhdGlhbC8ke2VuY29kZVVSSUNvbXBvbmVudChtYW5pZmVzdC5pZCl9L2ZlYXR1cmVzYCArIGA/cT0ke2VuY29kZVVSSUNvbXBvbmVudChxdWVyeSl9JmxpbWl0PSR7bGltaXR9YDtcbiAgICByZXR1cm4gKGF3YWl0IHRoaXMuZ2V0SnNvbjx7IG5hbWVzOiBzdHJpbmdbXSB9Pih1cmwpKS5uYW1lcyA/PyBbXTtcbiAgfVxuXG4gIGdldFBvbHlnb25zKCk6IFByb21pc2U8U3BhdGlhbFBvbHlnb25zPiB7XG4gICAgY29uc3QgbWFuaWZlc3QgPSB0aGlzLnJlcXVpcmVNYW5pZmVzdCgpO1xuICAgIGlmICghbWFuaWZlc3QucG9seWdvbnMpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoJ1tzcGF0aWFsXSB0aGlzIGRhdGFzZXQgaGFzIG5vIHBvbHlnb24gZ2VvbWV0cnknKSk7XG4gICAgfVxuICAgIC8vIEdlb21ldHJ5IGlzIG9uZSBsYXJnZSBibG9iIHJhdGhlciB0aGFuIGEgcGVyLW5hbWUgdmVjdG9yLCBzbyBpdCBnZXRzIGl0c1xuICAgIC8vIG93biBzaW5nbGUtZmxpZ2h0IHNsb3QgaW5zdGVhZCBvZiBhIGNhY2hlIGVudHJ5LlxuICAgIHRoaXMucG9seWdvbnNQcm9taXNlID8/PSB0aGlzLmdldEJpbmFyeShgc3BhdGlhbC8ke2VuY29kZVVSSUNvbXBvbmVudChtYW5pZmVzdC5pZCl9L3BvbHlnb25zYClcbiAgICAgIC50aGVuKGRlY29kZVBvbHlnb25zKVxuICAgICAgLmNhdGNoKChlcnIpID0+IHtcbiAgICAgICAgdGhpcy5wb2x5Z29uc1Byb21pc2UgPSBudWxsO1xuICAgICAgICB0aHJvdyBlcnI7XG4gICAgICB9KTtcbiAgICByZXR1cm4gdGhpcy5wb2x5Z29uc1Byb21pc2U7XG4gIH1cblxuICBnZXRQb2x5Z29uVGlsZShzZXQ6IHN0cmluZywgbGV2ZWw6IG51bWJlciwgZ3g6IG51bWJlciwgZ3k6IG51bWJlcik6IFByb21pc2U8U3BhdGlhbFBvbHlnb25UaWxlPiB7XG4gICAgY29uc3QgbWFuaWZlc3QgPSB0aGlzLnJlcXVpcmVNYW5pZmVzdCgpO1xuICAgIGlmICghbWFuaWZlc3QucG9seWdvblRpbGVzKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKCdbc3BhdGlhbF0gdGhpcyBkYXRhc2V0IGhhcyBubyB0aWxlZCBwb2x5Z29ucycpKTtcbiAgICB9XG4gICAgY29uc3QgcGF0aCA9XG4gICAgICBgc3BhdGlhbC8ke2VuY29kZVVSSUNvbXBvbmVudChtYW5pZmVzdC5pZCl9L3BvbHlnb24tdGlsZS9gICtcbiAgICAgIGAke2VuY29kZVVSSUNvbXBvbmVudChzZXQpfS8ke2xldmVsfS8ke2d4fS8ke2d5fWA7XG4gICAgcmV0dXJuIHRoaXMuY2FjaGVkVGlsZShwYXRoLCAoKSA9PlxuICAgICAgdGhpcy5nZXRCaW5hcnkocGF0aCkudGhlbigoYnVmKSA9PiBkZWNvZGVQb2x5Z29uVGlsZShidWYsIG1hbmlmZXN0LmNvdW50KSksXG4gICAgKSBhcyBQcm9taXNlPFNwYXRpYWxQb2x5Z29uVGlsZT47XG4gIH1cblxuICBnZXRUcmFuc2NyaXB0VGlsZShcbiAgICBsZXZlbDogbnVtYmVyLFxuICAgIGd4OiBudW1iZXIsXG4gICAgZ3k6IG51bWJlcixcbiAgICBxdWVyeTogVHJhbnNjcmlwdFRpbGVRdWVyeSxcbiAgKTogUHJvbWlzZTxTcGF0aWFsVHJhbnNjcmlwdFRpbGU+IHtcbiAgICBjb25zdCBtYW5pZmVzdCA9IHRoaXMucmVxdWlyZU1hbmlmZXN0KCk7XG4gICAgaWYgKCFtYW5pZmVzdC50cmFuc2NyaXB0VGlsZXMpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoJ1tzcGF0aWFsXSB0aGlzIGRhdGFzZXQgaGFzIG5vIHRpbGVkIHRyYW5zY3JpcHRzJykpO1xuICAgIH1cbiAgICBjb25zdCBnZW5lcyA9IHF1ZXJ5LmdlbmVzLm1hcChlbmNvZGVVUklDb21wb25lbnQpLmpvaW4oJywnKTtcbiAgICBjb25zdCBib3ggPSBxdWVyeS5ib3ggPyBgJmJveD0ke3F1ZXJ5LmJveC5qb2luKCcsJyl9YCA6ICcnO1xuICAgIGNvbnN0IHBhdGggPVxuICAgICAgYHNwYXRpYWwvJHtlbmNvZGVVUklDb21wb25lbnQobWFuaWZlc3QuaWQpfS90cmFuc2NyaXB0LXRpbGUvJHtsZXZlbH0vJHtneH0vJHtneX1gICtcbiAgICAgIGA/Z2VuZXM9JHtnZW5lc30mcXVhbGl0eT0ke3F1ZXJ5LnF1YWxpdHkgPz8gJ2hpZ2gnfSR7Ym94fWA7XG4gICAgLy8gVGhlIGNvZGVzIGluZGV4IHRoZSBnZW5lcyBhc2tlZCBmb3Ig4oCUIGV4Y2VwdCBmb3IgQUxMX0dFTkVTLCB3aG9zZSBsaXN0IHRoZVxuICAgIC8vIHNlcnZlciBvd25zLCBzbyBvbmx5IHRoZSBvYnNlcnZhdGlvbnMgY2FuIGJlIGJvdW5kZWQgdGhlcmUuXG4gICAgY29uc3QgbGltaXRzID0ge1xuICAgICAgb2JzZXJ2YXRpb25zOiBtYW5pZmVzdC5jb3VudCxcbiAgICAgIC4uLihxdWVyeS5nZW5lcy5pbmNsdWRlcyhBTExfR0VORVMpID8ge30gOiB7IGdlbmVzOiBxdWVyeS5nZW5lcy5sZW5ndGggfSksXG4gICAgfTtcbiAgICByZXR1cm4gdGhpcy5jYWNoZWRUaWxlKHBhdGgsICgpID0+XG4gICAgICB0aGlzLmdldEJpbmFyeShwYXRoKS50aGVuKChidWYpID0+IGRlY29kZVRyYW5zY3JpcHRUaWxlKGJ1ZiwgbGltaXRzKSksXG4gICAgKSBhcyBQcm9taXNlPFNwYXRpYWxUcmFuc2NyaXB0VGlsZT47XG4gIH1cblxuICBnZXRUcmFuc2NyaXB0R2VuZUJpbnMobGV2ZWw6IG51bWJlciwgdHg6IG51bWJlciwgdHk6IG51bWJlciwgZ2VuZXM6IHN0cmluZ1tdKTogUHJvbWlzZTxTcGF0aWFsVHJhbnNjcmlwdFRpbGU+IHtcbiAgICBjb25zdCBtYW5pZmVzdCA9IHRoaXMucmVxdWlyZU1hbmlmZXN0KCk7XG4gICAgaWYgKCFtYW5pZmVzdC50cmFuc2NyaXB0R2VuZUJpbnMpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoJ1tzcGF0aWFsXSB0aGlzIGRhdGFzZXQgaGFzIG5vIHBlci1nZW5lIGJpbnMnKSk7XG4gICAgfVxuICAgIGNvbnN0IHBhdGggPVxuICAgICAgYHNwYXRpYWwvJHtlbmNvZGVVUklDb21wb25lbnQobWFuaWZlc3QuaWQpfS9nZW5lLWJpbnMvJHtsZXZlbH0vJHt0eH0vJHt0eX1gICtcbiAgICAgIGA/Z2VuZXM9JHtnZW5lcy5tYXAoZW5jb2RlVVJJQ29tcG9uZW50KS5qb2luKCcsJyl9YDtcbiAgICBjb25zdCBsaW1pdHMgPSB7XG4gICAgICBvYnNlcnZhdGlvbnM6IG1hbmlmZXN0LmNvdW50LFxuICAgICAgLi4uKGdlbmVzLmluY2x1ZGVzKEFMTF9HRU5FUykgPyB7fSA6IHsgZ2VuZXM6IGdlbmVzLmxlbmd0aCB9KSxcbiAgICB9O1xuICAgIHJldHVybiB0aGlzLmNhY2hlZFRpbGUocGF0aCwgKCkgPT5cbiAgICAgIHRoaXMuZ2V0QmluYXJ5KHBhdGgpLnRoZW4oKGJ1ZikgPT4gZGVjb2RlVHJhbnNjcmlwdFRpbGUoYnVmLCBsaW1pdHMpKSxcbiAgICApIGFzIFByb21pc2U8U3BhdGlhbFRyYW5zY3JpcHRUaWxlPjtcbiAgfVxuXG4gIGdldFRyYW5zY3JpcHRCaW5zKGxldmVsOiBudW1iZXIsIHR4OiBudW1iZXIsIHR5OiBudW1iZXIpOiBQcm9taXNlPFNwYXRpYWxUcmFuc2NyaXB0VGlsZT4ge1xuICAgIGNvbnN0IG1hbmlmZXN0ID0gdGhpcy5yZXF1aXJlTWFuaWZlc3QoKTtcbiAgICBpZiAoIW1hbmlmZXN0LnRyYW5zY3JpcHRCaW5zKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKCdbc3BhdGlhbF0gdGhpcyBkYXRhc2V0IGhhcyBubyB0cmFuc2NyaXB0IHB5cmFtaWQnKSk7XG4gICAgfVxuICAgIGNvbnN0IHBhdGggPSBgc3BhdGlhbC8ke2VuY29kZVVSSUNvbXBvbmVudChtYW5pZmVzdC5pZCl9L3RyYW5zY3JpcHQtYmlucy8ke2xldmVsfS8ke3R4fS8ke3R5fWA7XG4gICAgcmV0dXJuIHRoaXMuY2FjaGVkVGlsZShwYXRoLCAoKSA9PlxuICAgICAgdGhpcy5nZXRCaW5hcnkocGF0aCkudGhlbigoYnVmKSA9PiBkZWNvZGVUcmFuc2NyaXB0VGlsZShidWYsIHsgb2JzZXJ2YXRpb25zOiBtYW5pZmVzdC5jb3VudCB9KSksXG4gICAgKSBhcyBQcm9taXNlPFNwYXRpYWxUcmFuc2NyaXB0VGlsZT47XG4gIH1cblxuICAvKiogU21hbGwgSlNPTiBhbnN3ZXJzLCBrZXllZCBieSBVUkwg4oCUIGhvdmVyaW5nIGJhY2sgYW5kIGZvcnRoIG11c3Qgbm90IHJlZmV0Y2guIExlYXN0IHJlY2VudGx5XG4gICAqICBVU0VEIGdvZXMgZmlyc3QsIHNvIHRoZSBzdW1tYXJ5IHVuZGVyIHRoZSBwb2ludGVyIHN0YXlzIHdoaWxlIG90aGVycyBhcmUgZXZpY3RlZC4gKi9cbiAgcHJpdmF0ZSByZWFkb25seSBzdW1tYXJ5Q2FjaGUgPSBuZXcgTHJ1Q2FjaGU8UHJvbWlzZTxTcGF0aWFsVHJhbnNjcmlwdFN1bW1hcnk+PigyNTYpO1xuXG4gIGdldFRyYW5zY3JpcHRTdW1tYXJ5KHF1ZXJ5OiB7XG4gICAgYm94PzogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl07XG4gICAgZ2VuZXM/OiBzdHJpbmdbXTtcbiAgICBjZWxscz86IG51bWJlcltdO1xuICB9KTogUHJvbWlzZTxTcGF0aWFsVHJhbnNjcmlwdFN1bW1hcnk+IHtcbiAgICBjb25zdCBtYW5pZmVzdCA9IHRoaXMucmVxdWlyZU1hbmlmZXN0KCk7XG4gICAgY29uc3QgcGFyYW1zOiBzdHJpbmdbXSA9IFtdO1xuICAgIGlmIChxdWVyeS5ib3gpIHBhcmFtcy5wdXNoKGBib3g9JHtxdWVyeS5ib3gubWFwKCh2KSA9PiArdi50b0ZpeGVkKDMpKS5qb2luKCcsJyl9YCk7XG4gICAgaWYgKHF1ZXJ5LmdlbmVzPy5sZW5ndGgpIHBhcmFtcy5wdXNoKGBnZW5lcz0ke3F1ZXJ5LmdlbmVzLm1hcChlbmNvZGVVUklDb21wb25lbnQpLmpvaW4oJywnKX1gKTtcbiAgICBpZiAocXVlcnkuY2VsbHM/Lmxlbmd0aCkgcGFyYW1zLnB1c2goYGNlbGxzPSR7cXVlcnkuY2VsbHMuam9pbignLCcpfWApO1xuICAgIGNvbnN0IHVybCA9IGBzcGF0aWFsLyR7ZW5jb2RlVVJJQ29tcG9uZW50KG1hbmlmZXN0LmlkKX0vdHJhbnNjcmlwdC1zdW1tYXJ5PyR7cGFyYW1zLmpvaW4oJyYnKX1gO1xuICAgIGxldCBoaXQgPSB0aGlzLnN1bW1hcnlDYWNoZS5nZXQodXJsKTtcbiAgICBpZiAoIWhpdCkge1xuICAgICAgaGl0ID0gdGhpcy5nZXRKc29uPFNwYXRpYWxUcmFuc2NyaXB0U3VtbWFyeT4odXJsKTtcbiAgICAgIGhpdC5jYXRjaCgoKSA9PiB0aGlzLnN1bW1hcnlDYWNoZS5kZWxldGUodXJsKSk7XG4gICAgICB0aGlzLnN1bW1hcnlDYWNoZS5zZXQodXJsLCBoaXQpO1xuICAgIH1cbiAgICByZXR1cm4gaGl0O1xuICB9XG5cbiAgZ2V0RGVuc2l0eShnZW5lczogc3RyaW5nW10sIGJpblNpemU/OiBudW1iZXIpOiBQcm9taXNlPFNwYXRpYWxEZW5zaXR5UmFzdGVyPiB7XG4gICAgY29uc3QgbWFuaWZlc3QgPSB0aGlzLnJlcXVpcmVNYW5pZmVzdCgpO1xuICAgIGlmICghbWFuaWZlc3QuZGVuc2l0eSkgcmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBFcnJvcignW3NwYXRpYWxdIHRoaXMgZGF0YXNldCBoYXMgbm8gZGVuc2l0eSByYXN0ZXInKSk7XG4gICAgY29uc3QgbGlzdCA9IFsuLi5nZW5lc107XG4gICAgY29uc3QgYmluID0gYmluU2l6ZSA/IGAmYmluPSR7YmluU2l6ZX1gIDogJyc7XG4gICAgcmV0dXJuIHRoaXMuZmV0Y2hDYWNoZWQoYGRlbnNpdHk6JHtsaXN0LmpvaW4oJywnKX06JHtiaW5TaXplID8/ICcnfWAsICgpID0+XG4gICAgICB0aGlzLmdldEJpbmFyeShcbiAgICAgICAgYHNwYXRpYWwvJHtlbmNvZGVVUklDb21wb25lbnQobWFuaWZlc3QuaWQpfS9kZW5zaXR5P2dlbmVzPSR7bGlzdC5tYXAoZW5jb2RlVVJJQ29tcG9uZW50KS5qb2luKCcsJyl9JHtiaW59YCxcbiAgICAgICkudGhlbigoYnVmKSA9PiBkZWNvZGVEZW5zaXR5KGJ1ZiwgbGlzdCkpLFxuICAgICkgYXMgUHJvbWlzZTxTcGF0aWFsRGVuc2l0eVJhc3Rlcj47XG4gIH1cblxuICBhc3luYyBpbXBvcnRHcm91cHMobGFiZWw6IHN0cmluZywgdGFibGU6IHN0cmluZyk6IFByb21pc2U8eyBjb2x1bW46IENhdGVnb3JpY2FsQ29sdW1uTWV0YTsgbWF0Y2hlZDogbnVtYmVyIH0+IHtcbiAgICBjb25zdCBtYW5pZmVzdCA9IHRoaXMucmVxdWlyZU1hbmlmZXN0KCk7XG4gICAgY29uc3QgdXJsID0gYCR7dGhpcy5iYXNlVXJsfXNwYXRpYWwvJHtlbmNvZGVVUklDb21wb25lbnQobWFuaWZlc3QuaWQpfS9ncm91cHM/bmFtZT0ke2VuY29kZVVSSUNvbXBvbmVudChsYWJlbCl9YDtcbiAgICAvLyBIdHRwQ2xpZW50LCBub3QgZmV0Y2g6IGEgaG9zdCdzIGludGVyY2VwdG9ycyAoaXRzIGF1dGggaGVhZGVyKSBtdXN0IGFwcGx5IHRvIHRoZVxuICAgIC8vIHVwbG9hZCBhcyB0aGV5IGRvIHRvIGV2ZXJ5IHJlYWQsIG9yIGEgcHJvdGVjdGVkIHNlcnZlciByZWZ1c2VzIGl0LlxuICAgIGxldCBib2R5OiB7IGNvbHVtbjogQ2F0ZWdvcmljYWxDb2x1bW5NZXRhOyBtYXRjaGVkOiBudW1iZXIgfTtcbiAgICB0cnkge1xuICAgICAgYm9keSA9IGF3YWl0IGZpcnN0VmFsdWVGcm9tKFxuICAgICAgICB0aGlzLmh0dHBcbiAgICAgICAgICAucG9zdDx7IGNvbHVtbjogQ2F0ZWdvcmljYWxDb2x1bW5NZXRhOyBtYXRjaGVkOiBudW1iZXIgfT4odXJsLCB0YWJsZSwge1xuICAgICAgICAgICAgaGVhZGVyczogeyAnQ29udGVudC1UeXBlJzogJ3RleHQvY3N2JyB9LFxuICAgICAgICAgIH0pXG4gICAgICAgICAgLnBpcGUodGltZW91dCh0aGlzLnRpbWVvdXRNcykpLFxuICAgICAgKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGNvbnN0IGUgPSBlcnIgYXMgSHR0cEVycm9yUmVzcG9uc2U7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoZT8uZXJyb3I/LmVycm9yID8/IGBbc3BhdGlhbF0gaW1wb3J0IGZhaWxlZCAoSFRUUCAke2U/LnN0YXR1cyA/PyAnPyd9KWApO1xuICAgIH1cbiAgICBjb25zdCBjb2x1bW4gPSBib2R5LmNvbHVtbjtcbiAgICAvLyBUaGUgbmV3IGNvbHVtbiBqb2lucyB0aGUgZGF0YXNldDogcmUtZW1pdCBzbyBldmVyeSBwYW5lbCBzZWVzIGl0LlxuICAgIGNvbnN0IGN1cnJlbnQgPSB0aGlzLmRhdGFzZXQkLnZhbHVlO1xuICAgIGlmIChjdXJyZW50ICYmIHRoaXMubWFuaWZlc3Q/LmlkID09PSBtYW5pZmVzdC5pZCkge1xuICAgICAgY29uc3QgY29sdW1ucyA9IGN1cnJlbnQuY29sdW1ucy5maWx0ZXIoKGMpID0+IGMubmFtZSAhPT0gY29sdW1uLm5hbWUpLmNvbmNhdChjb2x1bW4pO1xuICAgICAgdGhpcy5tYW5pZmVzdCA9IHsgLi4udGhpcy5tYW5pZmVzdCwgY29sdW1ucyB9O1xuICAgICAgdGhpcy51bmNhY2hlKGBjb2x1bW46JHtjb2x1bW4ubmFtZX1gKTtcbiAgICAgIHRoaXMuZGF0YXNldCQubmV4dCh7IC4uLmN1cnJlbnQsIGNvbHVtbnMgfSk7XG4gICAgfVxuICAgIHJldHVybiB7IGNvbHVtbiwgbWF0Y2hlZDogYm9keS5tYXRjaGVkIH07XG4gIH1cblxuICBnZXRNYXJrZXJHZW5lcyhjb2x1bW46IHN0cmluZywgcGVyR3JvdXAgPSA1KTogUHJvbWlzZTxTcGF0aWFsTWFya2VyR2VuZXM+IHtcbiAgICBjb25zdCBtYW5pZmVzdCA9IHRoaXMucmVxdWlyZU1hbmlmZXN0KCk7XG4gICAgLy8gTm8gcGVyLXJlcXVlc3QgdGltZW91dDogdGhlIGZpcnN0IGNvbXB1dGF0aW9uIGlzIGEgcGFzcyBvdmVyIHRoZSB3aG9sZSBtYXRyaXguXG4gICAgcmV0dXJuIGZpcnN0VmFsdWVGcm9tKFxuICAgICAgdGhpcy5odHRwLmdldDxTcGF0aWFsTWFya2VyR2VuZXM+KFxuICAgICAgICBgJHt0aGlzLmJhc2VVcmx9c3BhdGlhbC8ke2VuY29kZVVSSUNvbXBvbmVudChtYW5pZmVzdC5pZCl9L21hcmtlcnMvJHtlbmNvZGVVUklDb21wb25lbnQoY29sdW1uKX0/bj0ke3Blckdyb3VwfWAsXG4gICAgICApLFxuICAgICk7XG4gIH1cblxuICBnZXRUcmFuc2NyaXB0Q291bnRzKGdlbmVzOiBzdHJpbmdbXSk6IFByb21pc2U8U3BhdGlhbFRyYW5zY3JpcHRDb3VudHM+IHtcbiAgICBjb25zdCBtYW5pZmVzdCA9IHRoaXMucmVxdWlyZU1hbmlmZXN0KCk7XG4gICAgcmV0dXJuIHRoaXMuZ2V0SnNvbjxTcGF0aWFsVHJhbnNjcmlwdENvdW50cz4oXG4gICAgICBgc3BhdGlhbC8ke2VuY29kZVVSSUNvbXBvbmVudChtYW5pZmVzdC5pZCl9L3RyYW5zY3JpcHQtY291bnRzP2dlbmVzPSR7Z2VuZXMubWFwKGVuY29kZVVSSUNvbXBvbmVudCkuam9pbignLCcpfWAsXG4gICAgKTtcbiAgfVxuXG4gIC8qKiBMUlUgb3ZlciB0aWxlIHByb21pc2VzLCBzbyBjb25jdXJyZW50IGFza3Mgc2hhcmUgb25lIHJlcXVlc3QgYW5kIGEgZmFpbHVyZSBpcyBub3Qga2VwdC4gKi9cbiAgcHJpdmF0ZSBjYWNoZWRUaWxlPFQgZXh0ZW5kcyBTcGF0aWFsUG9seWdvblRpbGUgfCBTcGF0aWFsVHJhbnNjcmlwdFRpbGU+KFxuICAgIGtleTogc3RyaW5nLFxuICAgIGxvYWQ6ICgpID0+IFByb21pc2U8VD4sXG4gICk6IFByb21pc2U8VD4ge1xuICAgIGNvbnN0IGhpdCA9IHRoaXMudGlsZUNhY2hlLmdldChrZXkpO1xuICAgIGlmIChoaXQpIHtcbiAgICAgIHRoaXMudGlsZUNhY2hlLmRlbGV0ZShrZXkpO1xuICAgICAgdGhpcy50aWxlQ2FjaGUuc2V0KGtleSwgaGl0KTtcbiAgICAgIHJldHVybiBoaXQgYXMgUHJvbWlzZTxUPjtcbiAgICB9XG4gICAgY29uc3QgZ2VuZXJhdGlvbiA9IHRoaXMuc2VsZWN0aW9uLmN1cnJlbnQoKTtcbiAgICBjb25zdCBwcm9taXNlOiBQcm9taXNlPFQ+ID0gbG9hZCgpLnRoZW4oXG4gICAgICAodGlsZSkgPT4ge1xuICAgICAgICAvLyBTaXplZCBvbmNlIGl0IGxhbmRzLCBhbmQgb25seSB3aGlsZSBpdCBpcyBzdGlsbCB0aGUgZW50cnkgdW5kZXIgaXRzIGtleS5cbiAgICAgICAgaWYgKHRoaXMudGlsZUNhY2hlLmdldChrZXkpID09PSBwcm9taXNlICYmICF0aGlzLnRpbGVCeXRlcy5oYXMoa2V5KSkge1xuICAgICAgICAgIGNvbnN0IGJ5dGVzID0gcGF5bG9hZEJ5dGVzKHRpbGUpO1xuICAgICAgICAgIHRoaXMudGlsZUJ5dGVzLnNldChrZXksIGJ5dGVzKTtcbiAgICAgICAgICB0aGlzLnRpbGVCeXRlc1RvdGFsICs9IGJ5dGVzO1xuICAgICAgICAgIHRoaXMuZXZpY3RUaWxlcygpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aWxlO1xuICAgICAgfSxcbiAgICAgIChlcnIpID0+IHtcbiAgICAgICAgaWYgKHRoaXMudGlsZUNhY2hlLmdldChrZXkpID09PSBwcm9taXNlKSB0aGlzLmRyb3BUaWxlKGtleSk7XG4gICAgICAgIHRocm93IGVycjtcbiAgICAgIH0sXG4gICAgKTtcbiAgICBpZiAoZ2VuZXJhdGlvbi5pc0N1cnJlbnQoKSkge1xuICAgICAgdGhpcy50aWxlQ2FjaGUuc2V0KGtleSwgcHJvbWlzZSk7XG4gICAgICB0aGlzLmV2aWN0VGlsZXMoKTtcbiAgICB9XG4gICAgcmV0dXJuIHByb21pc2U7XG4gIH1cblxuICAvKiogT2xkZXN0IGZpcnN0LCBwYXN0IHRoZSBlbnRyeSBjYXAgb3IgdGhlIGJ5dGUgYnVkZ2V0LCBrZWVwaW5nIHRoZSBuZXdlc3QuICovXG4gIHByaXZhdGUgZXZpY3RUaWxlcygpOiB2b2lkIHtcbiAgICB3aGlsZSAoXG4gICAgICB0aGlzLnRpbGVDYWNoZS5zaXplID4gMSAmJlxuICAgICAgKHRoaXMudGlsZUNhY2hlLnNpemUgPiBTcGF0aWFsRGF0YUh0dHBTZXJ2aWNlLlRJTEVfQ0FDSEVfTElNSVQgfHwgdGhpcy50aWxlQnl0ZXNUb3RhbCA+IHRoaXMudGlsZUNhY2hlQnl0ZXMpXG4gICAgKSB7XG4gICAgICB0aGlzLmRyb3BUaWxlKHRoaXMudGlsZUNhY2hlLmtleXMoKS5uZXh0KCkudmFsdWUhKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGRyb3BUaWxlKGtleTogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy50aWxlQ2FjaGUuZGVsZXRlKGtleSk7XG4gICAgdGhpcy50aWxlQnl0ZXNUb3RhbCAtPSB0aGlzLnRpbGVCeXRlcy5nZXQoa2V5KSA/PyAwO1xuICAgIHRoaXMudGlsZUJ5dGVzLmRlbGV0ZShrZXkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSByZWZlcmVuY2Ugdm9sdW1lJ3Mgdm94ZWxzLCBzaW5nbGUtZmxpZ2h0ZWQgbGlrZSB0aGUgcG9seWdvbnMuXG4gICAqXG4gICAqIFZhbGlkYXRlZCBhZ2FpbnN0IHRoZSBtYW5pZmVzdCdzIGRlY2xhcmVkIGRpbWVuc2lvbnMgYmVmb3JlIGl0IGlzIGhhbmRlZFxuICAgKiBiYWNrOiBhIHNob3J0IG9yIGxvbmcgYnVmZmVyIHJlYWQgYXMgYSAzRCB0ZXh0dXJlIGRvZXMgbm90IGZhaWwsIGl0IHNoZWFyc1xuICAgKiB0aGUgYW5hdG9teSBpbnRvIGRpYWdvbmFsIHN0cmVha3MsIGFuZCB0aGF0IGlzIGZhciBoYXJkZXIgdG8gcmVjb2duaXNlIGFzIGFcbiAgICogdHJhbnNwb3J0IHByb2JsZW0gdGhhbiBhbiBlcnJvciBpcy5cbiAgICovXG4gIGdldFZvbHVtZSgpOiBQcm9taXNlPFVpbnQ4QXJyYXk+IHtcbiAgICBjb25zdCBtYW5pZmVzdCA9IHRoaXMucmVxdWlyZU1hbmlmZXN0KCk7XG4gICAgY29uc3QgbWV0YSA9IG1hbmlmZXN0LnZvbHVtZTtcbiAgICBpZiAoIW1ldGEpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoJ1tzcGF0aWFsXSB0aGlzIGRhdGFzZXQgaGFzIG5vIHJlZmVyZW5jZSB2b2x1bWUnKSk7XG4gICAgfVxuICAgIHRoaXMudm9sdW1lUHJvbWlzZSA/Pz0gdGhpcy5nZXRCaW5hcnkoYHNwYXRpYWwvJHtlbmNvZGVVUklDb21wb25lbnQobWFuaWZlc3QuaWQpfS92b2x1bWVgKVxuICAgICAgLnRoZW4oKGJ1ZikgPT4ge1xuICAgICAgICBjb25zdCB3YW50ID0gbWV0YS53aWR0aCAqIG1ldGEuaGVpZ2h0ICogbWV0YS5kZXB0aDtcbiAgICAgICAgaWYgKGJ1Zi5ieXRlTGVuZ3RoICE9PSB3YW50KSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgYFtzcGF0aWFsXSB2b2x1bWUgaXMgJHtidWYuYnl0ZUxlbmd0aH0gYnl0ZXMsIGV4cGVjdGVkICR7d2FudH0gYCArXG4gICAgICAgICAgICAgIGAoJHttZXRhLndpZHRofXgke21ldGEuaGVpZ2h0fXgke21ldGEuZGVwdGh9KWAsXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoYnVmKTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goKGVycikgPT4ge1xuICAgICAgICB0aGlzLnZvbHVtZVByb21pc2UgPSBudWxsO1xuICAgICAgICB0aHJvdyBlcnI7XG4gICAgICB9KTtcbiAgICByZXR1cm4gdGhpcy52b2x1bWVQcm9taXNlO1xuICB9XG5cbiAgLy8g4pSA4pSAIGludGVybmFscyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBwcml2YXRlIHJlcXVpcmVNYW5pZmVzdCgpOiBTcGF0aWFsTWFuaWZlc3Qge1xuICAgIGlmICghdGhpcy5tYW5pZmVzdCB8fCAhdGhpcy5kYXRhc2V0JC52YWx1ZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdbc3BhdGlhbF0gbm8gZGF0YXNldCBzZWxlY3RlZCDigJQgY2FsbCBzZWxlY3REYXRhc2V0KCkgZmlyc3QnKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMubWFuaWZlc3Q7XG4gIH1cblxuICAvKipcbiAgICogQ2FjaGUgKyBzaW5nbGUtZmxpZ2h0IGFyb3VuZCBhIHZlY3RvciBmZXRjaC5cbiAgICpcbiAgICogS2V5cyBhcmUgTE9HSUNBTCDigJQgYGZlYXR1cmU6R0FQREhgLCBub3QgYDxkYXRhc2V0Pi9mZWF0dXJlOkdBUERIYCDigJQgYmVjYXVzZSBgY2xlYXIoKWBcbiAgICogZW1wdGllcyB0aGUgbWFwcyBvbiBldmVyeSBzd2l0Y2gsIHNvIHR3byBkYXRhc2V0cyBuZXZlciBob2xkIGVudHJpZXMgYXQgb25jZS4gV2hhdFxuICAgKiB0aGF0IGRvZXMgbm90IGNvdmVyIGlzIGEgcmVxdWVzdCBzdGlsbCBpbiB0aGUgYWlyIHdoZW4gdGhlIHN3aXRjaCBoYXBwZW5zOiBgY2xlYXIoKWBcbiAgICogY2Fubm90IGNhbmNlbCBhbiBIVFRQIGNhbGwsIHNvIGEgdmVjdG9yIGZldGNoZWQgZm9yIGRhdGFzZXQgQSBjYW4gcmVzb2x2ZSBhZnRlciBCIGhhc1xuICAgKiBiZWVuIHNlbGVjdGVkIGFuZCB3cml0ZSBpdHNlbGYgaW50byBCJ3MgY2FjaGUgdW5kZXIgYSBrZXkgQiB3b3VsZCByZWFkLiBCb3RoIGRhdGFzZXRzXG4gICAqIGhhdmluZyBhIGdlbmUgb2YgdGhhdCBuYW1lIGlzIHRoZSBjb21tb24gY2FzZSwgbm90IHRoZSB1bmx1Y2t5IG9uZSwgYW5kIHRoZSByZXN1bHQgaXNcbiAgICogYSBwbG90IG9mIEEncyBleHByZXNzaW9uIG92ZXIgQidzIGNlbGxzIOKAlCB3aGljaCBsb29rcyBsaWtlIGRhdGEsIG5vdCBsaWtlIGEgZmF1bHQuXG4gICAqXG4gICAqIFNvIHRoZSBnZW5lcmF0aW9uIGlzIGNoZWNrZWQgYWZ0ZXIgdGhlIGF3YWl0LCBhbmQgdGhlIGluLWZsaWdodCBzbG90IGlzIGNsZWFyZWQgb25seVxuICAgKiB3aGVuIHRoZSBwcm9taXNlIHN0aWxsIHNpdHRpbmcgaW4gaXQgaXMgdGhpcyBvbmU6IGEgbGF0ZSBhcnJpdmFsIG11c3Qgbm90IGV2aWN0IHRoZVxuICAgKiBlbnRyeSBhIG5ld2VyIHJlcXVlc3QgZm9yIHRoZSBzYW1lIGtleSBpcyBhbHJlYWR5IHNoYXJpbmcuXG4gICAqL1xuICBwcml2YXRlIGZldGNoQ2FjaGVkKGtleTogc3RyaW5nLCBsb2FkOiAoKSA9PiBQcm9taXNlPENhY2hlZFBheWxvYWQ+KTogUHJvbWlzZTxDYWNoZWRQYXlsb2FkPiB7XG4gICAgY29uc3QgaGl0ID0gdGhpcy5jYWNoZS5nZXQoa2V5KTtcbiAgICBpZiAoaGl0KSB7XG4gICAgICAvLyBSZS1pbnNlcnQgdG8gbWFyayBtb3N0LXJlY2VudGx5LXVzZWQgKE1hcCBwcmVzZXJ2ZXMgaW5zZXJ0aW9uIG9yZGVyKS5cbiAgICAgIHRoaXMuY2FjaGUuZGVsZXRlKGtleSk7XG4gICAgICB0aGlzLmNhY2hlLnNldChrZXksIGhpdCk7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGhpdC52YWx1ZSk7XG4gICAgfVxuICAgIGNvbnN0IHBlbmRpbmcgPSB0aGlzLmluRmxpZ2h0LmdldChrZXkpO1xuICAgIGlmIChwZW5kaW5nKSByZXR1cm4gcGVuZGluZztcblxuICAgIGNvbnN0IGdlbmVyYXRpb24gPSB0aGlzLnNlbGVjdGlvbi5jdXJyZW50KCk7XG4gICAgY29uc3QgcHJvbWlzZTogUHJvbWlzZTxDYWNoZWRQYXlsb2FkPiA9IGxvYWQoKVxuICAgICAgLnRoZW4oKHZhbHVlKSA9PiB7XG4gICAgICAgIC8vIFN0aWxsIHJldHVybmVkIHRvIHRoZSBjYWxsZXIgdGhhdCBhc2tlZDogaXQgbWF5IHdlbGwgYmUgYSBjb21wb25lbnQgdGhhdCBpc1xuICAgICAgICAvLyBpdHNlbGYgYmVpbmcgdG9ybiBkb3duLCBhbmQgcmVqZWN0aW5nIGhlcmUgd291bGQgc3VyZmFjZSBhIHN3aXRjaCBhcyBhbiBlcnJvci5cbiAgICAgICAgLy8gV2hhdCBtdXN0IG5vdCBoYXBwZW4gaXMgdGhlIHZhbHVlIGJlaW5nIGtlcHQgZm9yIHdob2V2ZXIgY29tZXMgbmV4dC5cbiAgICAgICAgaWYgKGdlbmVyYXRpb24uaXNDdXJyZW50KCkpIHtcbiAgICAgICAgICB0aGlzLnVuY2FjaGUoa2V5KTtcbiAgICAgICAgICBjb25zdCBieXRlcyA9IHBheWxvYWRCeXRlcyh2YWx1ZSk7XG4gICAgICAgICAgdGhpcy5jYWNoZS5zZXQoa2V5LCB7IHZhbHVlLCBieXRlcyB9KTtcbiAgICAgICAgICB0aGlzLmNhY2hlZEJ5dGVzICs9IGJ5dGVzO1xuICAgICAgICAgIHRoaXMuZXZpY3QoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICB9KVxuICAgICAgLmZpbmFsbHkoKCkgPT4ge1xuICAgICAgICBpZiAodGhpcy5pbkZsaWdodC5nZXQoa2V5KSA9PT0gcHJvbWlzZSkgdGhpcy5pbkZsaWdodC5kZWxldGUoa2V5KTtcbiAgICAgIH0pO1xuICAgIHRoaXMuaW5GbGlnaHQuc2V0KGtleSwgcHJvbWlzZSk7XG4gICAgcmV0dXJuIHByb21pc2U7XG4gIH1cblxuICAvKiogT2xkZXN0IGZpcnN0LCBwYXN0IHRoZSBlbnRyeSBjYXAgb3IgdGhlIGJ5dGUgYnVkZ2V0LCBrZWVwaW5nIHRoZSBuZXdlc3QuICovXG4gIHByaXZhdGUgZXZpY3QoKTogdm9pZCB7XG4gICAgd2hpbGUgKFxuICAgICAgdGhpcy5jYWNoZS5zaXplID4gMSAmJlxuICAgICAgKHRoaXMuY2FjaGUuc2l6ZSA+IFNwYXRpYWxEYXRhSHR0cFNlcnZpY2UuQ0FDSEVfTElNSVQgfHwgdGhpcy5jYWNoZWRCeXRlcyA+IHRoaXMuY2FjaGVCeXRlcylcbiAgICApIHtcbiAgICAgIHRoaXMudW5jYWNoZSh0aGlzLmNhY2hlLmtleXMoKS5uZXh0KCkudmFsdWUhKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHVuY2FjaGUoa2V5OiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBlbnRyeSA9IHRoaXMuY2FjaGUuZ2V0KGtleSk7XG4gICAgaWYgKCFlbnRyeSkgcmV0dXJuO1xuICAgIHRoaXMuY2FjaGUuZGVsZXRlKGtleSk7XG4gICAgdGhpcy5jYWNoZWRCeXRlcyAtPSBlbnRyeS5ieXRlcztcbiAgfVxuXG4gIHByaXZhdGUgZ2V0SnNvbjxUPihwYXRoOiBzdHJpbmcpOiBQcm9taXNlPFQ+IHtcbiAgICByZXR1cm4gZmlyc3RWYWx1ZUZyb20odGhpcy5odHRwLmdldDxUPihgJHt0aGlzLmJhc2VVcmx9JHtwYXRofWApLnBpcGUodGltZW91dCh0aGlzLnRpbWVvdXRNcykpKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0QmluYXJ5KHBhdGg6IHN0cmluZyk6IFByb21pc2U8QXJyYXlCdWZmZXI+IHtcbiAgICByZXR1cm4gZmlyc3RWYWx1ZUZyb20oXG4gICAgICB0aGlzLmh0dHAuZ2V0KGAke3RoaXMuYmFzZVVybH0ke3BhdGh9YCwgeyByZXNwb25zZVR5cGU6ICdhcnJheWJ1ZmZlcicgfSkucGlwZSh0aW1lb3V0KHRoaXMudGltZW91dE1zKSksXG4gICAgKTtcbiAgfVxufVxuIl19