@jax-data-science/sci-image-visualizer 0.1.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 (311) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +404 -0
  3. package/esm2022/index.mjs +52 -0
  4. package/esm2022/jax-data-science-sci-image-visualizer.mjs +5 -0
  5. package/esm2022/lib/channel-histogram/channel-histogram.component.mjs +398 -0
  6. package/esm2022/lib/contracts/capabilities.contract.mjs +32 -0
  7. package/esm2022/lib/contracts/cell-segmenter.contract.mjs +12 -0
  8. package/esm2022/lib/contracts/channel-histogram-api.contract.mjs +14 -0
  9. package/esm2022/lib/contracts/colormap-lut.mjs +95 -0
  10. package/esm2022/lib/contracts/coordinate-transform.contract.mjs +2 -0
  11. package/esm2022/lib/contracts/display-types.mjs +8 -0
  12. package/esm2022/lib/contracts/image.contract.mjs +11 -0
  13. package/esm2022/lib/contracts/intensity.mjs +28 -0
  14. package/esm2022/lib/contracts/plot-type.mjs +112 -0
  15. package/esm2022/lib/contracts/ports/image-state.port.mjs +3 -0
  16. package/esm2022/lib/contracts/ports/preferences.port.mjs +3 -0
  17. package/esm2022/lib/contracts/ports/region-io.port.mjs +3 -0
  18. package/esm2022/lib/contracts/ports/tile-access.port.mjs +3 -0
  19. package/esm2022/lib/contracts/region-editor-api.contract.mjs +4 -0
  20. package/esm2022/lib/contracts/region-overlay.contract.mjs +2 -0
  21. package/esm2022/lib/contracts/region-store.contract.mjs +2 -0
  22. package/esm2022/lib/contracts/sam.contract.mjs +12 -0
  23. package/esm2022/lib/contracts/toolbar-config.mjs +8 -0
  24. package/esm2022/lib/contracts/visualizer.contract.mjs +10 -0
  25. package/esm2022/lib/contracts/viz-config.mjs +3 -0
  26. package/esm2022/lib/hex-color-picker/hex-color-picker.component.mjs +260 -0
  27. package/esm2022/lib/implementations/base-store-visualizer.mjs +76 -0
  28. package/esm2022/lib/implementations/napari-js/napari-axes-labels.mjs +106 -0
  29. package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +847 -0
  30. package/esm2022/lib/implementations/napari-js/napari-scale-bar.mjs +92 -0
  31. package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +2283 -0
  32. package/esm2022/lib/implementations/napari-js/napari-volume-z-handle.mjs +126 -0
  33. package/esm2022/lib/implementations/osd/display-pipeline.mjs +143 -0
  34. package/esm2022/lib/implementations/osd/histogram-sampler.mjs +217 -0
  35. package/esm2022/lib/implementations/osd/openseadragon-visualizer.service.mjs +1780 -0
  36. package/esm2022/lib/implementations/osd/osd-coordinate-transform.mjs +25 -0
  37. package/esm2022/lib/implementations/osd/osd-coords.mjs +53 -0
  38. package/esm2022/lib/implementations/osd/osd-lib.mjs +20 -0
  39. package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +1237 -0
  40. package/esm2022/lib/implementations/osd/osd-scale-bar.mjs +88 -0
  41. package/esm2022/lib/implementations/osd/slice-cache.mjs +488 -0
  42. package/esm2022/lib/implementations/osd/tile-client.mjs +29 -0
  43. package/esm2022/lib/implementations/plotly/plotly-coordinate-transform.mjs +37 -0
  44. package/esm2022/lib/implementations/plotly/plotly-region-overlay.mjs +31 -0
  45. package/esm2022/lib/implementations/plotly/plotly-trace-builders.mjs +183 -0
  46. package/esm2022/lib/implementations/plotly/plotly.service.mjs +2137 -0
  47. package/esm2022/lib/implementations/simple-slice-access.service.mjs +99 -0
  48. package/esm2022/lib/models/bezier.mjs +120 -0
  49. package/esm2022/lib/models/class-preset.mjs +46 -0
  50. package/esm2022/lib/models/geometry.mjs +198 -0
  51. package/esm2022/lib/models/region.mjs +166 -0
  52. package/esm2022/lib/models/shape.mjs +53 -0
  53. package/esm2022/lib/plot.utilities.mjs +693 -0
  54. package/esm2022/lib/processing/image-converter.service.mjs +90 -0
  55. package/esm2022/lib/processing/image-crop.mjs +62 -0
  56. package/esm2022/lib/processing/processing-image.mjs +50 -0
  57. package/esm2022/lib/provide-visualization.mjs +63 -0
  58. package/esm2022/lib/region-editor/mask-raster.mjs +95 -0
  59. package/esm2022/lib/region-editor/mask-worker.mjs +10 -0
  60. package/esm2022/lib/region-editor/region-editor.component.mjs +1190 -0
  61. package/esm2022/lib/region-ops.service.mjs +301 -0
  62. package/esm2022/lib/render-orchestrator.mjs +87 -0
  63. package/esm2022/lib/routing-visualizer.service.mjs +533 -0
  64. package/esm2022/lib/store/class-color.util.mjs +52 -0
  65. package/esm2022/lib/store/region-store.service.mjs +1029 -0
  66. package/esm2022/lib/store/visualizer-store.service.mjs +352 -0
  67. package/esm2022/lib/toolbar/brush/brush-tool.service.mjs +546 -0
  68. package/esm2022/lib/toolbar/crop/slide-crop.mjs +57 -0
  69. package/esm2022/lib/toolbar/segmentation/cell-segment-tool.service.mjs +115 -0
  70. package/esm2022/lib/toolbar/segmentation/cellpose-segmenter.service.mjs +84 -0
  71. package/esm2022/lib/toolbar/segmentation/onnx-sam-session.mjs +133 -0
  72. package/esm2022/lib/toolbar/segmentation/ort-runtime-config.mjs +31 -0
  73. package/esm2022/lib/toolbar/segmentation/sam-model-registry.mjs +108 -0
  74. package/esm2022/lib/toolbar/segmentation/sam-onnx-core.mjs +159 -0
  75. package/esm2022/lib/toolbar/segmentation/sam-point-tool.service.mjs +255 -0
  76. package/esm2022/lib/toolbar/segmentation/sam-prompt.mjs +94 -0
  77. package/esm2022/lib/toolbar/segmentation/sam-tool.service.mjs +188 -0
  78. package/esm2022/lib/toolbar/toolbar.component.mjs +311 -0
  79. package/esm2022/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.mjs +234 -0
  80. package/esm2022/lib/toolbar/wand/wand-tool.service.mjs +499 -0
  81. package/esm2022/lib/toolbar/wand/wand.service.mjs +921 -0
  82. package/esm2022/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.mjs +157 -0
  83. package/esm2022/lib/visualization.module.mjs +162 -0
  84. package/esm2022/lib/visualizer.component.mjs +1597 -0
  85. package/fesm2022/jax-data-science-sci-image-visualizer-mask-worker-uhepXUhM.mjs +12 -0
  86. package/fesm2022/jax-data-science-sci-image-visualizer-mask-worker-uhepXUhM.mjs.map +1 -0
  87. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-ci1q0xnJ.mjs +327 -0
  88. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-ci1q0xnJ.mjs.map +1 -0
  89. package/fesm2022/jax-data-science-sci-image-visualizer.mjs +21314 -0
  90. package/fesm2022/jax-data-science-sci-image-visualizer.mjs.map +1 -0
  91. package/fesm2022/mask.worker.js +989 -0
  92. package/fesm2022/onnx-sam.worker.js +202 -0
  93. package/index.d.ts +39 -0
  94. package/lib/channel-histogram/channel-histogram.component.d.ts +112 -0
  95. package/lib/contracts/capabilities.contract.d.ts +30 -0
  96. package/lib/contracts/cell-segmenter.contract.d.ts +40 -0
  97. package/lib/contracts/channel-histogram-api.contract.d.ts +98 -0
  98. package/lib/contracts/colormap-lut.d.ts +21 -0
  99. package/lib/contracts/coordinate-transform.contract.d.ts +43 -0
  100. package/lib/contracts/display-types.d.ts +41 -0
  101. package/lib/contracts/image.contract.d.ts +72 -0
  102. package/lib/contracts/intensity.d.ts +18 -0
  103. package/lib/contracts/plot-type.d.ts +108 -0
  104. package/lib/contracts/ports/image-state.port.d.ts +29 -0
  105. package/lib/contracts/ports/preferences.port.d.ts +19 -0
  106. package/lib/contracts/ports/region-io.port.d.ts +29 -0
  107. package/lib/contracts/ports/tile-access.port.d.ts +27 -0
  108. package/lib/contracts/region-editor-api.contract.d.ts +83 -0
  109. package/lib/contracts/region-overlay.contract.d.ts +47 -0
  110. package/lib/contracts/region-store.contract.d.ts +74 -0
  111. package/lib/contracts/sam.contract.d.ts +98 -0
  112. package/lib/contracts/toolbar-config.d.ts +24 -0
  113. package/lib/contracts/visualizer.contract.d.ts +346 -0
  114. package/lib/contracts/viz-config.d.ts +25 -0
  115. package/lib/hex-color-picker/hex-color-picker.component.d.ts +47 -0
  116. package/lib/implementations/base-store-visualizer.d.ts +71 -0
  117. package/lib/implementations/napari-js/napari-axes-labels.d.ts +47 -0
  118. package/lib/implementations/napari-js/napari-region-overlay.d.ts +115 -0
  119. package/lib/implementations/napari-js/napari-scale-bar.d.ts +31 -0
  120. package/lib/implementations/napari-js/napari-visualizer.service.d.ts +455 -0
  121. package/lib/implementations/napari-js/napari-volume-z-handle.d.ts +46 -0
  122. package/lib/implementations/osd/display-pipeline.d.ts +47 -0
  123. package/lib/implementations/osd/histogram-sampler.d.ts +85 -0
  124. package/lib/implementations/osd/openseadragon-visualizer.service.d.ts +476 -0
  125. package/lib/implementations/osd/osd-coordinate-transform.d.ts +17 -0
  126. package/lib/implementations/osd/osd-coords.d.ts +16 -0
  127. package/lib/implementations/osd/osd-lib.d.ts +19 -0
  128. package/lib/implementations/osd/osd-region-overlay.d.ts +191 -0
  129. package/lib/implementations/osd/osd-scale-bar.d.ts +17 -0
  130. package/lib/implementations/osd/slice-cache.d.ts +161 -0
  131. package/lib/implementations/osd/tile-client.d.ts +32 -0
  132. package/lib/implementations/plotly/plotly-coordinate-transform.d.ts +19 -0
  133. package/lib/implementations/plotly/plotly-region-overlay.d.ts +23 -0
  134. package/lib/implementations/plotly/plotly-trace-builders.d.ts +60 -0
  135. package/lib/implementations/plotly/plotly.service.d.ts +594 -0
  136. package/lib/implementations/simple-slice-access.service.d.ts +64 -0
  137. package/lib/models/bezier.d.ts +59 -0
  138. package/lib/models/class-preset.d.ts +39 -0
  139. package/lib/models/geometry.d.ts +66 -0
  140. package/lib/models/region.d.ts +132 -0
  141. package/lib/models/shape.d.ts +44 -0
  142. package/lib/plot.utilities.d.ts +107 -0
  143. package/lib/processing/image-converter.service.d.ts +28 -0
  144. package/lib/processing/image-crop.d.ts +18 -0
  145. package/lib/processing/processing-image.d.ts +17 -0
  146. package/lib/provide-visualization.d.ts +34 -0
  147. package/lib/region-editor/mask-raster.d.ts +61 -0
  148. package/lib/region-editor/mask-worker.d.ts +7 -0
  149. package/lib/region-editor/region-editor.component.d.ts +305 -0
  150. package/lib/region-ops.service.d.ts +92 -0
  151. package/lib/render-orchestrator.d.ts +59 -0
  152. package/lib/routing-visualizer.service.d.ts +227 -0
  153. package/lib/store/class-color.util.d.ts +26 -0
  154. package/lib/store/region-store.service.d.ts +315 -0
  155. package/lib/store/visualizer-store.service.d.ts +123 -0
  156. package/lib/toolbar/brush/brush-tool.service.d.ts +143 -0
  157. package/lib/toolbar/crop/slide-crop.d.ts +30 -0
  158. package/lib/toolbar/segmentation/cell-segment-tool.service.d.ts +32 -0
  159. package/lib/toolbar/segmentation/cellpose-segmenter.service.d.ts +39 -0
  160. package/lib/toolbar/segmentation/onnx-sam-session.d.ts +25 -0
  161. package/lib/toolbar/segmentation/ort-runtime-config.d.ts +4 -0
  162. package/lib/toolbar/segmentation/sam-model-registry.d.ts +36 -0
  163. package/lib/toolbar/segmentation/sam-onnx-core.d.ts +48 -0
  164. package/lib/toolbar/segmentation/sam-point-tool.service.d.ts +59 -0
  165. package/lib/toolbar/segmentation/sam-prompt.d.ts +34 -0
  166. package/lib/toolbar/segmentation/sam-tool.service.d.ts +50 -0
  167. package/lib/toolbar/toolbar.component.d.ts +167 -0
  168. package/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.d.ts +64 -0
  169. package/lib/toolbar/wand/wand-tool.service.d.ts +149 -0
  170. package/lib/toolbar/wand/wand.service.d.ts +133 -0
  171. package/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.d.ts +49 -0
  172. package/lib/visualization.module.d.ts +45 -0
  173. package/lib/visualizer.component.d.ts +378 -0
  174. package/package.json +73 -0
  175. package/src/lib/assets/3d-coordinates.svg +49 -0
  176. package/src/lib/assets/cells.svg +1 -0
  177. package/src/lib/assets/click.svg +1 -0
  178. package/src/lib/assets/colormap-luts.json +1 -0
  179. package/src/lib/assets/contour.svg +48 -0
  180. package/src/lib/assets/cube-3d.svg +1 -0
  181. package/src/lib/assets/edit-selection-white.svg +47 -0
  182. package/src/lib/assets/heatmap.svg +1 -0
  183. package/src/lib/assets/icons/colormap-Pastel1.png +0 -0
  184. package/src/lib/assets/icons/colormap-accent.png +0 -0
  185. package/src/lib/assets/icons/colormap-afmhot.png +0 -0
  186. package/src/lib/assets/icons/colormap-autumn.png +0 -0
  187. package/src/lib/assets/icons/colormap-berlin.png +0 -0
  188. package/src/lib/assets/icons/colormap-binary.png +0 -0
  189. package/src/lib/assets/icons/colormap-blackbody.png +0 -0
  190. package/src/lib/assets/icons/colormap-bluered.png +0 -0
  191. package/src/lib/assets/icons/colormap-blues.png +0 -0
  192. package/src/lib/assets/icons/colormap-bone.png +0 -0
  193. package/src/lib/assets/icons/colormap-brbg.png +0 -0
  194. package/src/lib/assets/icons/colormap-brg.png +0 -0
  195. package/src/lib/assets/icons/colormap-bugn.png +0 -0
  196. package/src/lib/assets/icons/colormap-bupu.png +0 -0
  197. package/src/lib/assets/icons/colormap-bwr.png +0 -0
  198. package/src/lib/assets/icons/colormap-cividis.png +0 -0
  199. package/src/lib/assets/icons/colormap-cmrmap.png +0 -0
  200. package/src/lib/assets/icons/colormap-cool.png +0 -0
  201. package/src/lib/assets/icons/colormap-coolwarm.png +0 -0
  202. package/src/lib/assets/icons/colormap-copper.png +0 -0
  203. package/src/lib/assets/icons/colormap-cubehelix.png +0 -0
  204. package/src/lib/assets/icons/colormap-dark2.png +0 -0
  205. package/src/lib/assets/icons/colormap-earth.png +0 -0
  206. package/src/lib/assets/icons/colormap-electric.png +0 -0
  207. package/src/lib/assets/icons/colormap-flag.png +0 -0
  208. package/src/lib/assets/icons/colormap-gist_earth.png +0 -0
  209. package/src/lib/assets/icons/colormap-gist_gray.png +0 -0
  210. package/src/lib/assets/icons/colormap-gist_heat.png +0 -0
  211. package/src/lib/assets/icons/colormap-gist_ncar.png +0 -0
  212. package/src/lib/assets/icons/colormap-gist_rainbow.png +0 -0
  213. package/src/lib/assets/icons/colormap-gist_stern.png +0 -0
  214. package/src/lib/assets/icons/colormap-gist_yarg.png +0 -0
  215. package/src/lib/assets/icons/colormap-gnbu.png +0 -0
  216. package/src/lib/assets/icons/colormap-gnuplot.png +0 -0
  217. package/src/lib/assets/icons/colormap-gnuplot2.png +0 -0
  218. package/src/lib/assets/icons/colormap-gray.png +0 -0
  219. package/src/lib/assets/icons/colormap-greens-inv.png +0 -0
  220. package/src/lib/assets/icons/colormap-greens.png +0 -0
  221. package/src/lib/assets/icons/colormap-greys-inv.png +0 -0
  222. package/src/lib/assets/icons/colormap-greys.png +0 -0
  223. package/src/lib/assets/icons/colormap-hot.png +0 -0
  224. package/src/lib/assets/icons/colormap-hsv.png +0 -0
  225. package/src/lib/assets/icons/colormap-inferno.png +0 -0
  226. package/src/lib/assets/icons/colormap-jet.png +0 -0
  227. package/src/lib/assets/icons/colormap-magma.png +0 -0
  228. package/src/lib/assets/icons/colormap-managua.png +0 -0
  229. package/src/lib/assets/icons/colormap-nipy_spectral.png +0 -0
  230. package/src/lib/assets/icons/colormap-ocean.png +0 -0
  231. package/src/lib/assets/icons/colormap-oranges.png +0 -0
  232. package/src/lib/assets/icons/colormap-orrd.png +0 -0
  233. package/src/lib/assets/icons/colormap-pastel2.png +0 -0
  234. package/src/lib/assets/icons/colormap-picnic.png +0 -0
  235. package/src/lib/assets/icons/colormap-pink.png +0 -0
  236. package/src/lib/assets/icons/colormap-piyg.png +0 -0
  237. package/src/lib/assets/icons/colormap-placeholder.png +0 -0
  238. package/src/lib/assets/icons/colormap-plasma.png +0 -0
  239. package/src/lib/assets/icons/colormap-portland.png +0 -0
  240. package/src/lib/assets/icons/colormap-prgn.png +0 -0
  241. package/src/lib/assets/icons/colormap-prism.png +0 -0
  242. package/src/lib/assets/icons/colormap-pubu.png +0 -0
  243. package/src/lib/assets/icons/colormap-pubugn.png +0 -0
  244. package/src/lib/assets/icons/colormap-puor.png +0 -0
  245. package/src/lib/assets/icons/colormap-purd.png +0 -0
  246. package/src/lib/assets/icons/colormap-purples.png +0 -0
  247. package/src/lib/assets/icons/colormap-rainbow.png +0 -0
  248. package/src/lib/assets/icons/colormap-rdbu.png +0 -0
  249. package/src/lib/assets/icons/colormap-rdgy.png +0 -0
  250. package/src/lib/assets/icons/colormap-rdpu.png +0 -0
  251. package/src/lib/assets/icons/colormap-rdylbu.png +0 -0
  252. package/src/lib/assets/icons/colormap-rdylgn.png +0 -0
  253. package/src/lib/assets/icons/colormap-reds.png +0 -0
  254. package/src/lib/assets/icons/colormap-seismic.png +0 -0
  255. package/src/lib/assets/icons/colormap-set1.png +0 -0
  256. package/src/lib/assets/icons/colormap-set2.png +0 -0
  257. package/src/lib/assets/icons/colormap-set3.png +0 -0
  258. package/src/lib/assets/icons/colormap-spectral.png +0 -0
  259. package/src/lib/assets/icons/colormap-spring.png +0 -0
  260. package/src/lib/assets/icons/colormap-summer.png +0 -0
  261. package/src/lib/assets/icons/colormap-tab10.png +0 -0
  262. package/src/lib/assets/icons/colormap-tab20.png +0 -0
  263. package/src/lib/assets/icons/colormap-tab20b.png +0 -0
  264. package/src/lib/assets/icons/colormap-tab20c.png +0 -0
  265. package/src/lib/assets/icons/colormap-terrain.png +0 -0
  266. package/src/lib/assets/icons/colormap-turbo.png +0 -0
  267. package/src/lib/assets/icons/colormap-twilight.png +0 -0
  268. package/src/lib/assets/icons/colormap-twilight_shifted.png +0 -0
  269. package/src/lib/assets/icons/colormap-vanimo.png +0 -0
  270. package/src/lib/assets/icons/colormap-viridis.png +0 -0
  271. package/src/lib/assets/icons/colormap-winter.png +0 -0
  272. package/src/lib/assets/icons/colormap-wistia.png +0 -0
  273. package/src/lib/assets/icons/colormap-ylgn.png +0 -0
  274. package/src/lib/assets/icons/colormap-ylgnbu-inv.png +0 -0
  275. package/src/lib/assets/icons/colormap-ylgnbu.png +0 -0
  276. package/src/lib/assets/icons/colormap-ylorbr.png +0 -0
  277. package/src/lib/assets/icons/colormap-ylorrd-inv.png +0 -0
  278. package/src/lib/assets/icons/colormap-ylorrd.png +0 -0
  279. package/src/lib/assets/interactive-segmentation-cursor.svg +1 -0
  280. package/src/lib/assets/invert.svg +1 -0
  281. package/src/lib/assets/isosurface.svg +7 -0
  282. package/src/lib/assets/mask.svg +1 -0
  283. package/src/lib/assets/paintbrush.svg +1 -0
  284. package/src/lib/assets/picture-segmentation.svg +43 -0
  285. package/src/lib/assets/polygon-vertices.svg +13 -0
  286. package/src/lib/assets/polyline.svg +3 -0
  287. package/src/lib/assets/redo.svg +39 -0
  288. package/src/lib/assets/region-editor.svg +37 -0
  289. package/src/lib/assets/region-move.svg +7 -0
  290. package/src/lib/assets/smooth.svg +56 -0
  291. package/src/lib/assets/spline-chart.svg +7 -0
  292. package/src/lib/assets/surface.svg +37 -0
  293. package/src/lib/assets/test/download-379.svg +1 -0
  294. package/src/lib/assets/test/download-98.svg +1 -0
  295. package/src/lib/assets/test/json-1.svg +1 -0
  296. package/src/lib/assets/test/load-53.svg +1 -0
  297. package/src/lib/assets/test/mask-44.svg +1 -0
  298. package/src/lib/assets/test/mask-download-44.svg +15 -0
  299. package/src/lib/assets/test/mask-save-44.svg +11 -0
  300. package/src/lib/assets/test/overlay-1.svg +1 -0
  301. package/src/lib/assets/test/overlay-4.svg +1 -0
  302. package/src/lib/assets/test/region-26.svg +1 -0
  303. package/src/lib/assets/test/save-56.svg +1 -0
  304. package/src/lib/assets/test/upload-43.svg +1 -0
  305. package/src/lib/assets/to-bezier.svg +15 -0
  306. package/src/lib/assets/to-polygon.svg +11 -0
  307. package/src/lib/assets/undo.svg +38 -0
  308. package/src/lib/assets/vertex-add.svg +12 -0
  309. package/src/lib/assets/vertex-delete.svg +12 -0
  310. package/src/lib/assets/wand.svg +54 -0
  311. package/src/lib/assets/zoom-box.svg +10 -0
@@ -0,0 +1,693 @@
1
+ import { Polygon, Rectangle, Region, MultiPolygon } from './models/region';
2
+ import { resolveHandles, bezierCurveFromHandles } from './models/bezier';
3
+ import { saveAs } from 'file-saver';
4
+ export const COLORMAP_OPTIONS = [
5
+ {
6
+ label: 'Sequential',
7
+ data: null,
8
+ children: [
9
+ { label: 'Greys', data: { value: 'GREYS_LUT', src: 'assets/plotting/icons/colormap-greys.png' } },
10
+ { label: 'Purples', data: { value: 'PURPLES_LUT', src: 'assets/plotting/icons/colormap-purples.png' } },
11
+ { label: 'Blues', data: { value: 'BLUES_LUT', src: 'assets/plotting/icons/colormap-blues.png' } },
12
+ { label: 'Greens', data: { value: 'GREENS_LUT', src: 'assets/plotting/icons/colormap-greens.png' } },
13
+ { label: 'Oranges', data: { value: 'ORANGES_LUT', src: 'assets/plotting/icons/colormap-oranges.png' } },
14
+ { label: 'Reds', data: { value: 'Reds', src: 'assets/plotting/icons/colormap-reds.png' } },
15
+ { label: 'YlOrBr', data: { value: 'YLORBR_LUT', src: 'assets/plotting/icons/colormap-ylorbr.png' } },
16
+ { label: 'YlOrRd', data: { value: 'YLORRD_LUT', src: 'assets/plotting/icons/colormap-ylorrd.png' } },
17
+ { label: 'OrRd', data: { value: 'ORRD_LUT', src: 'assets/plotting/icons/colormap-orrd.png' } },
18
+ { label: 'PuRd', data: { value: 'PURD_LUT', src: 'assets/plotting/icons/colormap-purd.png' } },
19
+ { label: 'RdPu', data: { value: 'RDPU_LUT', src: 'assets/plotting/icons/colormap-rdpu.png' } },
20
+ { label: 'BuPu', data: { value: 'BUPU_LUT', src: 'assets/plotting/icons/colormap-bupu.png' } },
21
+ { label: 'GnBu', data: { value: 'GNBU_LUT', src: 'assets/plotting/icons/colormap-gnbu.png' } },
22
+ { label: 'YlGnBu', data: { value: 'YLGNBU_LUT', src: 'assets/plotting/icons/colormap-ylgnbu.png' } },
23
+ { label: 'PuBuGn', data: { value: 'PUBUGN_LUT', src: 'assets/plotting/icons/colormap-pubugn.png' } },
24
+ { label: 'BuGn', data: { value: 'BUGN_LUT', src: 'assets/plotting/icons/colormap-bugn.png' } },
25
+ { label: 'YlGn', data: { value: 'YLGN_LUT', src: 'assets/plotting/icons/colormap-ylgn.png' } },
26
+ { label: 'Greys Inv', data: { value: 'Greys', src: 'assets/plotting/icons/colormap-greys-inv.png' } },
27
+ { label: 'Greens Inv', data: { value: 'Greens', src: 'assets/plotting/icons/colormap-greens-inv.png' } },
28
+ { label: 'YlOrRd Inv', data: { value: 'YlOrRd', src: 'assets/plotting/icons/colormap-ylorrd-inv.png' } },
29
+ { label: 'YlGnBu Inv', data: { value: 'YlGnBu', src: 'assets/plotting/icons/colormap-ylgnbu-inv.png' } },
30
+ ]
31
+ },
32
+ {
33
+ label: 'Sequential (2)',
34
+ data: null,
35
+ children: [
36
+ { label: 'binary', data: { value: 'BINARY_LUT', src: 'assets/plotting/icons/colormap-binary.png' } },
37
+ { label: 'gist_yarg', data: { value: 'GIST_YARG_LUT', src: 'assets/plotting/icons/colormap-gist_yarg.png' } },
38
+ { label: 'gist_gray', data: { value: 'GIST_GRAY_LUT', src: 'assets/plotting/icons/colormap-gist_gray.png' } },
39
+ { label: 'gray', data: { value: 'GRAY_LUT', src: 'assets/plotting/icons/colormap-gray.png' } },
40
+ { label: 'bone', data: { value: 'BONE_LUT', src: 'assets/plotting/icons/colormap-bone.png' } },
41
+ { label: 'pink', data: { value: 'PINK_LUT', src: 'assets/plotting/icons/colormap-pink.png' } },
42
+ { label: 'spring', data: { value: 'SPRING_LUT', src: 'assets/plotting/icons/colormap-spring.png' } },
43
+ { label: 'summer', data: { value: 'SUMMER_LUT', src: 'assets/plotting/icons/colormap-summer.png' } },
44
+ { label: 'autumn', data: { value: 'AUTUMN_LUT', src: 'assets/plotting/icons/colormap-autumn.png' } },
45
+ { label: 'winter', data: { value: 'WINTER_LUT', src: 'assets/plotting/icons/colormap-winter.png' } },
46
+ { label: 'cool', data: { value: 'COOL_LUT', src: 'assets/plotting/icons/colormap-cool.png' } },
47
+ { label: 'Wistia', data: { value: 'WISTIA_LUT', src: 'assets/plotting/icons/colormap-wistia.png' } },
48
+ { label: 'hot', data: { value: 'HOT_LUT', src: 'assets/plotting/icons/colormap-hot.png' } },
49
+ { label: 'afmhot', data: { value: 'AFMHOT_LUT', src: 'assets/plotting/icons/colormap-afmhot.png' } },
50
+ { label: 'gist_heat', data: { value: 'GIST_HEAT_LUT', src: 'assets/plotting/icons/colormap-gist_heat.png' } },
51
+ { label: 'copper', data: { value: 'COPPER_LUT', src: 'assets/plotting/icons/colormap-copper.png' } },
52
+ { label: 'Bluered', data: { value: 'Bluered', src: 'assets/plotting/icons/colormap-bluered.png' } },
53
+ ]
54
+ },
55
+ {
56
+ label: 'Perceptually Uniform Sequential',
57
+ data: null,
58
+ children: [
59
+ { label: 'Viridis', data: { value: 'Viridis', src: 'assets/plotting/icons/colormap-viridis.png' } },
60
+ { label: 'Magma', data: { value: 'MAGMA_LUT', src: 'assets/plotting/icons/colormap-magma.png' } },
61
+ { label: 'Inferno', data: { value: 'INFERNO_LUT', src: 'assets/plotting/icons/colormap-inferno.png' } },
62
+ { label: 'Cividis', data: { value: 'Cividis', src: 'assets/plotting/icons/colormap-cividis.png' } },
63
+ { label: 'Electric', data: { value: 'Electric', src: 'assets/plotting/icons/colormap-electric.png' } },
64
+ { label: 'Plasma', data: { value: 'PLASMA_LUT', src: 'assets/plotting/icons/colormap-plasma.png' } },
65
+ ]
66
+ },
67
+ {
68
+ label: 'Diverging',
69
+ data: null,
70
+ children: [
71
+ { label: 'PiYG', data: { value: 'PIYG_LUT', src: 'assets/plotting/icons/colormap-piyg.png' } },
72
+ { label: 'PRGn', data: { value: 'PRGN_LUT', src: 'assets/plotting/icons/colormap-prgn.png' } },
73
+ { label: 'BrBG', data: { value: 'BRBG_LUT', src: 'assets/plotting/icons/colormap-brbg.png' } },
74
+ { label: 'PuOr', data: { value: 'PUOR_LUT', src: 'assets/plotting/icons/colormap-puor.png' } },
75
+ { label: 'RdGy', data: { value: 'RDGY_LUT', src: 'assets/plotting/icons/colormap-rdgy.png' } },
76
+ { label: 'RdBu', data: { value: 'RDBU_LUT', src: 'assets/plotting/icons/colormap-rdbu.png' } },
77
+ { label: 'RdYlBu', data: { value: 'RDYLBU_LUT', src: 'assets/plotting/icons/colormap-rdylbu.png' } },
78
+ { label: 'RdYlGn', data: { value: 'RDYLGN_LUT', src: 'assets/plotting/icons/colormap-rdylgn.png' } },
79
+ { label: 'Spectral', data: { value: 'SPECTRAL_LUT', src: 'assets/plotting/icons/colormap-spectral.png' } },
80
+ { label: 'coolwarm', data: { value: 'COOLWARM_LUT', src: 'assets/plotting/icons/colormap-coolwarm.png' } },
81
+ { label: 'bwr', data: { value: 'BWR_LUT', src: 'assets/plotting/icons/colormap-bwr.png' } },
82
+ { label: 'seismic', data: { value: 'SEISMIC_LUT', src: 'assets/plotting/icons/colormap-seismic.png' } },
83
+ { label: 'berlin', data: { value: 'BERLIN_LUT', src: 'assets/plotting/icons/colormap-berlin.png' } },
84
+ { label: 'managua', data: { value: 'MANAGUA_LUT', src: 'assets/plotting/icons/colormap-managua.png' } },
85
+ { label: 'vanimo', data: { value: 'VANIMO_LUT', src: 'assets/plotting/icons/colormap-vanimo.png' } },
86
+ { label: 'Picnic', data: { value: 'Picnic', src: 'assets/plotting/icons/colormap-picnic.png' } },
87
+ { label: 'Portland', data: { value: 'Portland', src: 'assets/plotting/icons/colormap-portland.png' } },
88
+ ]
89
+ },
90
+ {
91
+ label: 'Cyclic',
92
+ data: null,
93
+ children: [
94
+ { label: 'twilight', data: { value: 'TWILIGHT_LUT', src: 'assets/plotting/icons/colormap-twilight.png' } },
95
+ { label: 'twilight_shifted', data: { value: 'TWILIGHT_SHIFTED_LUT', src: 'assets/plotting/icons/colormap-twilight_shifted.png' } },
96
+ { label: 'hsv', data: { value: 'HSV_LUT', src: 'assets/plotting/icons/colormap-hsv.png' } },
97
+ ]
98
+ },
99
+ {
100
+ label: 'Qualitative',
101
+ data: null,
102
+ children: [
103
+ { label: 'Pastel1', data: { value: 'PASTEL1_LUT', src: 'assets/plotting/icons/colormap-Pastel1.png' } },
104
+ { label: 'Pastel2', data: { value: 'PASTEL2_LUT', src: 'assets/plotting/icons/colormap-pastel2.png' } },
105
+ { label: 'Accent', data: { value: 'ACCENT_LUT', src: 'assets/plotting/icons/colormap-accent.png' } },
106
+ { label: 'Dark2', data: { value: 'DARK2_LUT', src: 'assets/plotting/icons/colormap-dark2.png' } },
107
+ { label: 'Set1', data: { value: 'SET1_LUT', src: 'assets/plotting/icons/colormap-set1.png' } },
108
+ { label: 'Set2', data: { value: 'SET2_LUT', src: 'assets/plotting/icons/colormap-set2.png' } },
109
+ { label: 'Set3', data: { value: 'SET3_LUT', src: 'assets/plotting/icons/colormap-set3.png' } },
110
+ { label: 'tab10', data: { value: 'TAB10_LUT', src: 'assets/plotting/icons/colormap-tab10.png' } },
111
+ { label: 'tab20', data: { value: 'TAB20_LUT', src: 'assets/plotting/icons/colormap-tab20.png' } },
112
+ { label: 'tab20b', data: { value: 'TAB20B_LUT', src: 'assets/plotting/icons/colormap-tab20b.png' } },
113
+ { label: 'tab20c', data: { value: 'TAB20C_LUT', src: 'assets/plotting/icons/colormap-tab20c.png' } }
114
+ ]
115
+ },
116
+ {
117
+ label: 'Miscellaneous',
118
+ data: null,
119
+ children: [
120
+ { label: 'flag', data: { value: 'FLAG_LUT', src: 'assets/plotting/icons/colormap-flag.png' } },
121
+ { label: 'prism', data: { value: 'PRISM_LUT', src: 'assets/plotting/icons/colormap-prism.png' } },
122
+ { label: 'ocean', data: { value: 'OCEAN_LUT', src: 'assets/plotting/icons/colormap-ocean.png' } },
123
+ { label: 'gist_earth', data: { value: 'GIST_EARTH_LUT', src: 'assets/plotting/icons/colormap-gist_earth.png' } },
124
+ { label: 'terrain', data: { value: 'TERRAIN_LUT', src: 'assets/plotting/icons/colormap-terrain.png' } },
125
+ { label: 'gist_stern', data: { value: 'GIST_STERN_LUT', src: 'assets/plotting/icons/colormap-gist_stern.png' } },
126
+ { label: 'gnuplot', data: { value: 'GNUPLOT_LUT', src: 'assets/plotting/icons/colormap-gnuplot.png' } },
127
+ { label: 'gnuplot2', data: { value: 'GNUPLOT2_LUT', src: 'assets/plotting/icons/colormap-gnuplot2.png' } },
128
+ { label: 'CMRmap', data: { value: 'CMRMAP_LUT', src: 'assets/plotting/icons/colormap-cmrmap.png' } },
129
+ { label: 'cubehelix', data: { value: 'CUBEHELIX_LUT', src: 'assets/plotting/icons/colormap-cubehelix.png' } },
130
+ { label: 'brg', data: { value: 'BRG_LUT', src: 'assets/plotting/icons/colormap-brg.png' } },
131
+ { label: 'gist_rainbow', data: { value: 'GIST_RAINBOW_LUT', src: 'assets/plotting/icons/colormap-gist_rainbow.png' } },
132
+ { label: 'rainbow', data: { value: 'RAINBOW_LUT', src: 'assets/plotting/icons/colormap-rainbow.png' } },
133
+ { label: 'jet', data: { value: 'JET_LUT', src: 'assets/plotting/icons/colormap-jet.png' } },
134
+ { label: 'turbo', data: { value: 'TURBO_LUT', src: 'assets/plotting/icons/colormap-turbo.png' } },
135
+ { label: 'nipy_spectral', data: { value: 'NIPY_SPECTRAL_LUT', src: 'assets/plotting/icons/colormap-nipy_spectral.png' } },
136
+ { label: 'gist_ncar', data: { value: 'GIST_NCAR_LUT', src: 'assets/plotting/icons/colormap-gist_ncar.png' } },
137
+ { label: 'Blackbody', data: { value: 'Blackbody', src: 'assets/plotting/icons/colormap-blackbody.png' } },
138
+ ]
139
+ }
140
+ ];
141
+ export const CONFIG = {
142
+ displaylogo: false, // Hide the plotly logo
143
+ responsive: true, // Make the plot responsive
144
+ displayModeBar: false,
145
+ scrollZoom: false, // disable mouse scroll zoom
146
+ };
147
+ export const CONFIG_SURFACE = {
148
+ displaylogo: false, // Hide the plotly logo
149
+ responsive: true, // Make the plot responsive
150
+ displayModeBar: false,
151
+ scrollZoom: true, // 3D scenes orbit/zoom natively on scroll
152
+ };
153
+ export class PlotUtilities {
154
+ /**
155
+ * Rounds all the point coordinates of a path ('M13.54,54.566L35.44,33.3L36.22,89.6Z')
156
+ * becomes 'M14,55L35,33L36,90Z'
157
+ * @param path
158
+ */
159
+ roundPathCoordinates(path) {
160
+ const isClosed = path.endsWith('Z');
161
+ const inner = isClosed ? path.substring(1, path.length - 1) : path.substring(1);
162
+ let roundedPath = 'M';
163
+ const strArray = inner.split('L');
164
+ for (let i = 0; i < strArray.length; i++) {
165
+ const xy = strArray[i].split(',');
166
+ if (i < strArray.length - 1) {
167
+ roundedPath = `${roundedPath}${Math.round(+xy[0])},${Math.round(+xy[1])}L`;
168
+ }
169
+ else {
170
+ roundedPath = `${roundedPath}${Math.round(+xy[0])},${Math.round(+xy[1])}`;
171
+ }
172
+ }
173
+ return isClosed ? roundedPath + 'Z' : roundedPath;
174
+ }
175
+ /**
176
+ * Transform a 1d array into a matrix given a given width
177
+ * @param array Uint8Array
178
+ * @param elementsPerSubArray
179
+ */
180
+ arrayToMatrix(array, elementsPerSubArray) {
181
+ const matrix = [];
182
+ let i, k;
183
+ for (i = 0, k = -1; i < array.length; i++) {
184
+ if (i % elementsPerSubArray === 0) {
185
+ k++;
186
+ matrix[k] = [];
187
+ }
188
+ matrix[k].push(array[i]);
189
+ }
190
+ return matrix;
191
+ }
192
+ /**
193
+ * coordinates are of the bottom left and upper right corners of the rectangle, The coordinates
194
+ * are taken given a yAxis that is up side down (as for all images). If Zoom is out of the image boundary,
195
+ * it will return the image size coordinates for the new rectangle.
196
+ * @param coordinates plotly coordinates ([Xaxis.range[0], xAxis.range[1], yAxis.range[0], yaxis.range[1]])
197
+ * @param trueImageSize true image size [0, x, 0, y]
198
+ */
199
+ getRectangle(coordinates, trueImageSize) {
200
+ const rect = new Rectangle();
201
+ // check if new image size is bigger than original image size
202
+ if (coordinates[3] < 0) {
203
+ coordinates[3] = 0;
204
+ }
205
+ if (coordinates[1] > trueImageSize[1]) {
206
+ coordinates[1] = trueImageSize[1];
207
+ }
208
+ if (coordinates[2] > trueImageSize[3]) {
209
+ coordinates[2] = trueImageSize[3];
210
+ }
211
+ if (coordinates[0] < 0) {
212
+ coordinates[0] = 0;
213
+ }
214
+ // if coordinates outside of image left/right/top/bottom
215
+ // we set the coordinates to the original image size.
216
+ if (coordinates[1] < 0 || coordinates[0] > trueImageSize[1]
217
+ || coordinates[2] < 0 || coordinates[3] > trueImageSize[3]) {
218
+ coordinates[0] = 0;
219
+ coordinates[1] = trueImageSize[1];
220
+ coordinates[2] = trueImageSize[3];
221
+ coordinates[3] = 0;
222
+ }
223
+ rect.x = Math.floor(coordinates[0]);
224
+ rect.y = Math.floor(coordinates[3]);
225
+ rect.width = Math.floor(coordinates[1] - coordinates[0]);
226
+ rect.height = Math.floor(coordinates[2] - coordinates[3]);
227
+ return rect;
228
+ }
229
+ /**
230
+ * given a dom object (found by id), return a Rectangle of the bounding element.
231
+ * @param div
232
+ */
233
+ getDomRectangle(div) {
234
+ const domRect = new Rectangle();
235
+ const appDiv = document.getElementById(div);
236
+ if (appDiv && appDiv.parentNode && appDiv.parentNode.parentElement) {
237
+ const rect = appDiv.parentNode.parentElement.getBoundingClientRect();
238
+ domRect.x = Math.round(rect.x);
239
+ domRect.y = Math.round(rect.y);
240
+ domRect.width = Math.round(rect.width);
241
+ domRect.height = Math.round(rect.height);
242
+ }
243
+ return domRect;
244
+ }
245
+ /**
246
+ * snap region to closest pixel in the coordinate (round the coordinates of the region)
247
+ * @param shape
248
+ * @private
249
+ */
250
+ snapRegion(shape) {
251
+ // if region is a polygon
252
+ if (shape.path) {
253
+ shape.path = this.roundPathCoordinates(shape.path);
254
+ }
255
+ else if (shape.x0 && shape.x1 && shape.y0 && shape.y1) {
256
+ // if region is a rectangle
257
+ if (typeof shape.x0 === 'number') {
258
+ shape.x0 = Math.round(shape.x0);
259
+ }
260
+ if (typeof shape.x1 === 'number') {
261
+ shape.x1 = Math.round(shape.x1);
262
+ }
263
+ if (typeof shape.y0 === 'number') {
264
+ shape.y0 = Math.round(shape.y0);
265
+ }
266
+ if (typeof shape.y1 === 'number') {
267
+ shape.y1 = Math.round(shape.y1);
268
+ }
269
+ }
270
+ return shape;
271
+ }
272
+ /**
273
+ * Given a figure (path or rectangle), returns a polygon
274
+ * @param fig
275
+ */
276
+ getPolygon(fig) {
277
+ const poly = new Polygon();
278
+ if (fig.type === 'path') {
279
+ const tempPath = fig.path;
280
+ const isClosed = tempPath.endsWith('Z');
281
+ const path = isClosed ? tempPath.substring(1, tempPath.length - 1) : tempPath.substring(1);
282
+ const verts = path.split('L');
283
+ poly.npoints = verts.length;
284
+ poly.xpoints = [];
285
+ poly.ypoints = [];
286
+ poly.closed = isClosed;
287
+ verts.forEach((pnt) => {
288
+ const point = pnt.split(',');
289
+ poly.xpoints.push(Math.round(point[0]));
290
+ poly.ypoints.push(Math.round(point[1]));
291
+ });
292
+ }
293
+ else if (fig.type === 'rect') {
294
+ poly.npoints = 4;
295
+ poly.xpoints = this.round([fig.x0, fig.x1, fig.x1, fig.x0]);
296
+ poly.ypoints = this.round([fig.y1, fig.y1, fig.y0, fig.y0]);
297
+ }
298
+ else {
299
+ console.log('Ignoring unrecognised shape in diagram');
300
+ return null;
301
+ }
302
+ return poly;
303
+ }
304
+ /**
305
+ * TESTED
306
+ * Rounds a list of numbers
307
+ * @param a
308
+ */
309
+ round(a) {
310
+ const b = [];
311
+ a.forEach((d) => b.push(Math.round(d)));
312
+ return b;
313
+ }
314
+ /**
315
+ * TESTED
316
+ * Returns true of zoom is the same as image size
317
+ * @param rect Rectangle area
318
+ * @param trueImgSize
319
+ * @return true if rect is out of image size boundary
320
+ */
321
+ isZoomSameAsImgSize(rect, trueImgSize) {
322
+ return rect.x === trueImgSize[0] && rect.y === trueImgSize[2]
323
+ && rect.width === trueImgSize[1] && rect.height === trueImgSize[3];
324
+ }
325
+ /**
326
+ * Save the json string to a file
327
+ * @param jsonString
328
+ */
329
+ saveToFile(jsonString, baseName) {
330
+ const blob = new Blob([jsonString], { type: 'application/json' });
331
+ const stem = (baseName ?? '').replace(/\.[^/.]+$/, '').trim() || 'rois';
332
+ saveAs(blob, `${stem}.geojson`);
333
+ }
334
+ /**
335
+ * Function that imports ROIs from a geojson object
336
+ * @param geoJsonStr
337
+ * @return Region[]
338
+ */
339
+ importROIsFromGeoJson(geoJsonStr) {
340
+ const regions = [];
341
+ let geoJson;
342
+ try {
343
+ geoJson = JSON.parse(geoJsonStr);
344
+ }
345
+ catch (error) {
346
+ throw new Error('Error parsing json string: ' + error);
347
+ }
348
+ if (!geoJson.features) {
349
+ throw new Error('Invalid GeoJson file: must contain the \'features\' key.');
350
+ }
351
+ let idx = 0;
352
+ for (const feature of geoJson.features) {
353
+ const region = new Region();
354
+ region.name = `shape${idx}`;
355
+ idx++;
356
+ // QuPath stores the image plane INSIDE the geometry (a sibling of
357
+ // type/coordinates), not in properties: `geometry.plane = {c,z,t}`, all
358
+ // zero-based, and the key is omitted for the default plane (z=0,t=0). A
359
+ // missing plane therefore reads back as z=0 (jit-ui#93).
360
+ region.z = feature.geometry?.plane?.z ?? 0;
361
+ if (!feature.properties || !feature.properties.classification) {
362
+ // No classification metadata — use a default label and color.
363
+ region.label = 'Cell';
364
+ }
365
+ else if (!feature.properties.classification.name) {
366
+ // assume classification is a string
367
+ region.label = feature.properties.classification;
368
+ }
369
+ else {
370
+ // if classification is an object with a name / check color as well
371
+ region.label = feature.properties.classification.name;
372
+ if (feature.properties.classification.color) {
373
+ region.color = this.rgbToHex(feature.properties.classification.color[0], feature.properties.classification.color[1], feature.properties.classification.color[2]);
374
+ }
375
+ }
376
+ // JIT bezier region: the editable anchors + flag travel in properties
377
+ // (the geometry holds the flattened curve for viewers without bezier
378
+ // support). Reconstruct the editable bezier from the anchors.
379
+ if (feature.properties && feature.properties.isBezier && feature.properties.bezierAnchors) {
380
+ const anchors = feature.properties.bezierAnchors;
381
+ const polygon = new Polygon();
382
+ polygon.bezier = true;
383
+ polygon.closed = feature.geometry?.type !== 'LineString';
384
+ polygon.npoints = anchors.length;
385
+ polygon.xpoints = anchors.map(a => a[0]);
386
+ polygon.ypoints = anchors.map(a => a[1]);
387
+ polygon.coordinates = anchors.map(a => [a[0], a[1]]);
388
+ // Restore the edited control handles when present (else they'll fall back
389
+ // to the smooth Catmull-Rom default at render time).
390
+ if (feature.properties.bezierHandlesIn)
391
+ polygon.handlesIn = feature.properties.bezierHandlesIn;
392
+ if (feature.properties.bezierHandlesOut)
393
+ polygon.handlesOut = feature.properties.bezierHandlesOut;
394
+ // Restore donut holes + their editable bezier handles (jit-ui#102).
395
+ if (feature.properties.holes)
396
+ polygon.holes = feature.properties.holes;
397
+ if (feature.properties.holeHandlesIn)
398
+ polygon.holeHandlesIn = feature.properties.holeHandlesIn;
399
+ if (feature.properties.holeHandlesOut)
400
+ polygon.holeHandlesOut = feature.properties.holeHandlesOut;
401
+ region.bounds = polygon;
402
+ regions.push(region);
403
+ continue;
404
+ }
405
+ const coordinates = feature.geometry.coordinates;
406
+ if (!coordinates) {
407
+ throw new Error('Invalid GeoJson file: must contain the \'coordinates\' key.');
408
+ }
409
+ // Multi-part region: GeoJSON MultiPolygon → one Polygon per part, each
410
+ // with its own holes (jit-ui#85).
411
+ if (feature.geometry.type === 'MultiPolygon') {
412
+ const mp = new MultiPolygon();
413
+ mp.polygons = coordinates
414
+ .map(rings => this.polygonFromRings(rings))
415
+ .filter(p => p.xpoints.length >= 3);
416
+ region.bounds = mp;
417
+ regions.push(region);
418
+ continue;
419
+ }
420
+ // Open polyline: LineString geometry
421
+ if (feature.geometry.type === 'LineString') {
422
+ const polygon = new Polygon();
423
+ polygon.closed = false;
424
+ polygon.npoints = coordinates.length;
425
+ polygon.xpoints = [];
426
+ polygon.ypoints = [];
427
+ polygon.coordinates = [];
428
+ for (let i = 0; i < coordinates.length; i++) {
429
+ polygon.xpoints.push(coordinates[i][0]);
430
+ polygon.ypoints.push(coordinates[i][1]);
431
+ polygon.coordinates.push([coordinates[i][0], coordinates[i][1]]);
432
+ }
433
+ region.bounds = polygon;
434
+ // Polygon: check if it encodes a rectangle (single ring only — a polygon
435
+ // with holes must never be collapsed to a rectangle).
436
+ }
437
+ else if (coordinates.length === 1
438
+ && coordinates[0].length === 5
439
+ && JSON.stringify(coordinates[0][0]) === JSON.stringify(coordinates[0][4])
440
+ && coordinates[0][0][0] === coordinates[0][3][0]
441
+ && coordinates[0][0][1] === coordinates[0][1][1]
442
+ && coordinates[0][1][0] === coordinates[0][2][0]
443
+ && coordinates[0][2][1] === coordinates[0][3][1]) {
444
+ const rectangle = new Rectangle();
445
+ rectangle.x = coordinates[0][0][0];
446
+ rectangle.y = coordinates[0][0][1];
447
+ rectangle.width = coordinates[0][2][0] - coordinates[0][0][0];
448
+ rectangle.height = coordinates[0][2][1] - coordinates[0][0][1];
449
+ region.bounds = rectangle;
450
+ }
451
+ else { // polygon is a freeform closed polygon
452
+ const polygon = new Polygon();
453
+ polygon.npoints = coordinates[0].length - 1;
454
+ polygon.xpoints = [];
455
+ polygon.ypoints = [];
456
+ polygon.coordinates = [];
457
+ for (let i = 0; i < coordinates[0].length - 1; i++) {
458
+ polygon.xpoints.push(coordinates[0][i][0]);
459
+ polygon.ypoints.push(coordinates[0][i][1]);
460
+ polygon.coordinates.push([coordinates[0][i][0], coordinates[0][i][1]]);
461
+ }
462
+ // Extra rings are interior holes (GeoJSON Polygon convention) — jit-ui#85.
463
+ const holes = this.ringsToHoles(coordinates.slice(1));
464
+ if (holes.length)
465
+ polygon.holes = holes;
466
+ region.bounds = polygon;
467
+ }
468
+ regions.push(region);
469
+ }
470
+ return regions;
471
+ }
472
+ /**
473
+ * Function that returns a geojson object from a Plotly ROI
474
+ * @param rois
475
+ * @return FeatureCollection<Geometry, GeoJsonProperties>
476
+ */
477
+ exportROIsToGeoJson(rois) {
478
+ console.log('Exporting ROIs to GeoJson');
479
+ console.log(rois);
480
+ const features = [];
481
+ for (const roi of rois.filter(r => r.kind !== 'profile')) {
482
+ // QuPath places the image plane inside the geometry (sibling of
483
+ // type/coordinates), zero-based, and omits it for the default plane
484
+ // (z=0,t=0). Emit `plane: {c,z,t}` only for a non-default slice so a
485
+ // single-plane image round-trips byte-identically to QuPath (jit-ui#93).
486
+ const planeProp = (roi.z ?? 0) !== 0 ? { plane: { c: -1, z: roi.z, t: 0 } } : {};
487
+ if (roi.bounds instanceof Rectangle) {
488
+ const rectangle = {
489
+ type: 'Feature',
490
+ properties: {
491
+ classification: {
492
+ name: roi.label ? roi.label : roi.name,
493
+ color: [
494
+ this.hexToRgb(roi?.color)[0],
495
+ this.hexToRgb(roi?.color)[1],
496
+ this.hexToRgb(roi?.color)[2]
497
+ ]
498
+ },
499
+ },
500
+ geometry: {
501
+ type: 'Polygon',
502
+ coordinates: [[
503
+ [roi.bounds.x, roi.bounds.y],
504
+ [roi.bounds.x + roi.bounds.width, roi.bounds.y],
505
+ [roi.bounds.x + roi.bounds.width, roi.bounds.y + roi.bounds.height],
506
+ [roi.bounds.x, roi.bounds.y + roi.bounds.height],
507
+ [roi.bounds.x, roi.bounds.y]
508
+ ]],
509
+ ...planeProp
510
+ }
511
+ };
512
+ features.push(rectangle);
513
+ }
514
+ else if (roi.bounds instanceof Polygon) {
515
+ const colorRgb = [
516
+ this.hexToRgb(roi?.color)[0],
517
+ this.hexToRgb(roi?.color)[1],
518
+ this.hexToRgb(roi?.color)[2]
519
+ ];
520
+ const closed = roi.bounds.closed !== false;
521
+ const isBezier = roi.bounds.bezier === true;
522
+ // For a bezier region the geometry is the flattened smooth curve,
523
+ // so a viewer without bezier support (QuPath) still renders the curve;
524
+ // the editable anchors + flag ride along in properties for JIT.
525
+ const geomCoords = isBezier
526
+ ? (() => {
527
+ const handles = resolveHandles(roi.bounds.xpoints, roi.bounds.ypoints, closed, roi.bounds.handlesIn, roi.bounds.handlesOut);
528
+ const c = bezierCurveFromHandles(roi.bounds.xpoints, roi.bounds.ypoints, handles, closed);
529
+ return c.xs.map((x, i) => [x, c.ys[i]]);
530
+ })()
531
+ : roi.bounds.coordinates;
532
+ const properties = {
533
+ classification: {
534
+ name: roi.label ? roi.label : roi.name,
535
+ color: colorRgb
536
+ },
537
+ };
538
+ if (isBezier) {
539
+ properties.isBezier = true;
540
+ properties.bezierAnchors = roi.bounds.coordinates;
541
+ // The editable control handles (relative offsets) travel along so JIT
542
+ // round-trips a hand-edited curve, not just the smooth default.
543
+ if (roi.bounds.handlesIn)
544
+ properties.bezierHandlesIn = roi.bounds.handlesIn;
545
+ if (roi.bounds.handlesOut)
546
+ properties.bezierHandlesOut = roi.bounds.handlesOut;
547
+ // Donut bezier: the hole anchors + their editable handles round-trip too (jit-ui#102).
548
+ if (roi.bounds.holes)
549
+ properties.holes = roi.bounds.holes;
550
+ if (roi.bounds.holeHandlesIn)
551
+ properties.holeHandlesIn = roi.bounds.holeHandlesIn;
552
+ if (roi.bounds.holeHandlesOut)
553
+ properties.holeHandlesOut = roi.bounds.holeHandlesOut;
554
+ }
555
+ if (closed) {
556
+ // Close the ring. The flattened bezier curve already returns to its
557
+ // start, so only the straight-polygon path needs the first point
558
+ // repeated.
559
+ const ring = isBezier ? geomCoords : [...geomCoords, geomCoords[0]];
560
+ // Interior rings (holes) follow the exterior as extra GeoJSON rings —
561
+ // standard Polygon-with-holes, which QuPath round-trips (jit-ui#85). For a bezier donut,
562
+ // the hole geometry is the flattened smooth curve too (jit-ui#102).
563
+ const rings = [ring];
564
+ if (roi.bounds.holes) {
565
+ roi.bounds.holes.forEach((hole, hi) => {
566
+ if (hole.length < 3)
567
+ return;
568
+ if (isBezier) {
569
+ const hxs = hole.map((p) => p[0]);
570
+ const hys = hole.map((p) => p[1]);
571
+ const hh = resolveHandles(hxs, hys, true, roi.bounds.holeHandlesIn?.[hi], roi.bounds.holeHandlesOut?.[hi]);
572
+ const c = bezierCurveFromHandles(hxs, hys, hh, true);
573
+ rings.push(c.xs.map((x, i) => [x, c.ys[i]]));
574
+ }
575
+ else {
576
+ rings.push([...hole, hole[0]]);
577
+ }
578
+ });
579
+ }
580
+ features.push({
581
+ type: 'Feature',
582
+ properties,
583
+ geometry: { type: 'Polygon', coordinates: rings, ...planeProp }
584
+ });
585
+ }
586
+ else {
587
+ features.push({
588
+ type: 'Feature',
589
+ properties,
590
+ geometry: { type: 'LineString', coordinates: geomCoords, ...planeProp }
591
+ });
592
+ }
593
+ }
594
+ else if (roi.bounds instanceof MultiPolygon) {
595
+ // Multi-part region → GeoJSON MultiPolygon: one ring-set per part
596
+ // (exterior + holes), each ring closed (jit-ui#85).
597
+ const colorRgb = [
598
+ this.hexToRgb(roi?.color)[0],
599
+ this.hexToRgb(roi?.color)[1],
600
+ this.hexToRgb(roi?.color)[2]
601
+ ];
602
+ const coordinates = roi.bounds.polygons
603
+ .filter(part => part.xpoints.length >= 3)
604
+ .map(part => {
605
+ const ext = part.xpoints.map((x, i) => [x, part.ypoints[i]]);
606
+ const rings = [[...ext, ext[0]]];
607
+ if (part.holes) {
608
+ for (const hole of part.holes) {
609
+ if (hole.length >= 3)
610
+ rings.push([...hole, hole[0]]);
611
+ }
612
+ }
613
+ return rings;
614
+ });
615
+ features.push({
616
+ type: 'Feature',
617
+ properties: { classification: { name: roi.label ? roi.label : roi.name, color: colorRgb } },
618
+ geometry: { type: 'MultiPolygon', coordinates, ...planeProp }
619
+ });
620
+ }
621
+ }
622
+ const geoJsonData = {
623
+ features: features,
624
+ type: 'FeatureCollection'
625
+ };
626
+ return JSON.stringify(geoJsonData);
627
+ }
628
+ /**
629
+ * Convert GeoJSON interior rings into the neutral hole representation
630
+ * (`number[][]` per ring, no repeated closing point). Degenerate rings (< 3
631
+ * distinct points) are dropped. jit-ui#85.
632
+ */
633
+ /**
634
+ * Build a closed {@link Polygon} from a GeoJSON ring set: `rings[0]` is the
635
+ * exterior (closing point dropped), `rings[1..]` are interior holes. jit-ui#85.
636
+ */
637
+ polygonFromRings(rings) {
638
+ const poly = new Polygon();
639
+ const ext = rings?.[0] ?? [];
640
+ const last = ext.length - 1;
641
+ const closed = ext.length > 1 && ext[0][0] === ext[last][0] && ext[0][1] === ext[last][1];
642
+ const n = closed ? last : ext.length;
643
+ poly.xpoints = [];
644
+ poly.ypoints = [];
645
+ poly.coordinates = [];
646
+ for (let i = 0; i < n; i++) {
647
+ poly.xpoints.push(ext[i][0]);
648
+ poly.ypoints.push(ext[i][1]);
649
+ poly.coordinates.push([ext[i][0], ext[i][1]]);
650
+ }
651
+ poly.npoints = poly.xpoints.length;
652
+ poly.closed = true;
653
+ const holes = this.ringsToHoles(rings.slice(1));
654
+ if (holes.length)
655
+ poly.holes = holes;
656
+ return poly;
657
+ }
658
+ ringsToHoles(rings) {
659
+ const holes = [];
660
+ for (const ringIn of rings || []) {
661
+ if (!ringIn || ringIn.length < 3)
662
+ continue;
663
+ const last = ringIn.length - 1;
664
+ const closed = ringIn[0][0] === ringIn[last][0] && ringIn[0][1] === ringIn[last][1];
665
+ const n = closed ? last : ringIn.length;
666
+ const ring = [];
667
+ for (let i = 0; i < n; i++)
668
+ ring.push([ringIn[i][0], ringIn[i][1]]);
669
+ if (ring.length >= 3)
670
+ holes.push(ring);
671
+ }
672
+ return holes;
673
+ }
674
+ rgbToHex(r, g, b) {
675
+ return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
676
+ }
677
+ hexToRgb(hex) {
678
+ let r, g, b;
679
+ if (hex) {
680
+ const bigint = parseInt(hex.slice(1), 16);
681
+ r = (bigint >> 16) & 255;
682
+ g = (bigint >> 8) & 255;
683
+ b = bigint & 255;
684
+ }
685
+ else {
686
+ r = 0;
687
+ g = 0;
688
+ b = 0;
689
+ }
690
+ return [r, g, b];
691
+ }
692
+ }
693
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGxvdC51dGlsaXRpZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3Bsb3QudXRpbGl0aWVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUUzRSxPQUFPLEVBQUUsY0FBYyxFQUFFLHNCQUFzQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDekUsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLFlBQVksQ0FBQztBQUVwQyxNQUFNLENBQUMsTUFBTSxnQkFBZ0IsR0FBRztJQUM5QjtRQUNFLEtBQUssRUFBRSxZQUFZO1FBQ25CLElBQUksRUFBRSxJQUFJO1FBQ1YsUUFBUSxFQUFFO1lBQ1IsRUFBRSxLQUFLLEVBQUMsT0FBTyxFQUFFLElBQUksRUFBRSxFQUFFLEtBQUssRUFBRSxXQUFXLEVBQUUsR0FBRyxFQUFDLDBDQUEwQyxFQUFFLEVBQUU7WUFDL0YsRUFBRSxLQUFLLEVBQUMsU0FBUyxFQUFFLElBQUksRUFBRSxFQUFFLEtBQUssRUFBRSxhQUFhLEVBQUUsR0FBRyxFQUFDLDRDQUE0QyxFQUFFLEVBQUU7WUFDckcsRUFBRSxLQUFLLEVBQUMsT0FBTyxFQUFFLElBQUksRUFBRSxFQUFFLEtBQUssRUFBRSxXQUFXLEVBQUUsR0FBRyxFQUFDLDBDQUEwQyxFQUFFLEVBQUU7WUFDL0YsRUFBRSxLQUFLLEVBQUMsUUFBUSxFQUFFLElBQUksRUFBRSxFQUFFLEtBQUssRUFBRSxZQUFZLEVBQUUsR0FBRyxFQUFDLDJDQUEyQyxFQUFFLEVBQUU7WUFDbEcsRUFBRSxLQUFLLEVBQUMsU0FBUyxFQUFFLElBQUksRUFBRSxFQUFFLEtBQUssRUFBRSxhQUFhLEVBQUUsR0FBRyxFQUFDLDRDQUE0QyxFQUFFLEVBQUU7WUFDckcsRUFBRSxLQUFLLEVBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFDLHlDQUF5QyxFQUFFLEVBQUU7WUFDeEYsRUFBRSxLQUFLLEVBQUMsUUFBUSxFQUFFLElBQUksRUFBRSxFQUFFLEtBQUssRUFBRSxZQUFZLEVBQUUsR0FBRyxFQUFDLDJDQUEyQyxFQUFFLEVBQUU7WUFDbEcsRUFBRSxLQUFLLEVBQUMsUUFBUSxFQUFFLElBQUksRUFBRSxFQUFFLEtBQUssRUFBRSxZQUFZLEVBQUUsR0FBRyxFQUFDLDJDQUEyQyxFQUFFLEVBQUU7WUFDbEcsRUFBRSxLQUFLLEVBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUUsR0FBRyxFQUFDLHlDQUF5QyxFQUFFLEVBQUU7WUFDNUYsRUFBRSxLQUFLLEVBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUUsR0FBRyxFQUFDLHlDQUF5QyxFQUFFLEVBQUU7WUFDNUYsRUFBRSxLQUFLLEVBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUUsR0FBRyxFQUFDLHlDQUF5QyxFQUFFLEVBQUU7WUFDNUYsRUFBRSxLQUFLLEVBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUUsR0FBRyxFQUFDLHlDQUF5QyxFQUFFLEVBQUU7WUFDNUYsRUFBRSxLQUFLLEVBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUUsR0FBRyxFQUFDLHlDQUF5QyxFQUFFLEVBQUU7WUFDNUYsRUFBRSxLQUFLLEVBQUMsUUFBUSxFQUFFLElBQUksRUFBRSxFQUFFLEtBQUssRUFBRSxZQUFZLEVBQUUsR0FBRyxFQUFDLDJDQUEyQyxFQUFFLEVBQUU7WUFDbEcsRUFBRSxLQUFLLEVBQUMsUUFBUSxFQUFFLElBQUksRUFBRSxFQUFFLEtBQUssRUFBRSxZQUFZLEVBQUUsR0FBRyxFQUFDLDJDQUEyQyxFQUFFLEVBQUU7WUFDbEcsRUFBRSxLQUFLLEVBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUUsR0FBRyxFQUFDLHlDQUF5QyxFQUFFLEVBQUU7WUFDNUYsRUFBRSxLQUFLLEVBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUUsR0FBRyxFQUFDLHlDQUF5QyxFQUFFLEVBQUU7WUFDNUYsRUFBRSxLQUFLLEVBQUMsV0FBVyxFQUFFLElBQUksRUFBRSxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFDLDhDQUE4QyxFQUFFLEVBQUU7WUFDbkcsRUFBRSxLQUFLLEVBQUMsWUFBWSxFQUFFLElBQUksRUFBRSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsR0FBRyxFQUFDLCtDQUErQyxFQUFFLEVBQUU7WUFDdEcsRUFBRSxLQUFLLEVBQUMsWUFBWSxFQUFFLElBQUksRUFBRSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsR0FBRyxFQUFDLCtDQUErQyxFQUFFLEVBQUU7WUFDdEcsRUFBRSxLQUFLLEVBQUMsWUFBWSxFQUFFLElBQUksRUFBRSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsR0FBRyxFQUFDLCtDQUErQyxFQUFFLEVBQUU7U0FDdkc7S0FDRjtJQUNEO1FBQ0UsS0FBSyxFQUFFLGdCQUFnQjtRQUN2QixJQUFJLEVBQUUsSUFBSTtRQUNWLFFBQVEsRUFBRTtZQUNSLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLEdBQUcsRUFBRSwyQ0FBMkMsRUFBRSxFQUFFO1lBQ3BHLEVBQUUsS0FBSyxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsZUFBZSxFQUFFLEdBQUcsRUFBRSw4Q0FBOEMsRUFBRSxFQUFFO1lBQzdHLEVBQUUsS0FBSyxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsZUFBZSxFQUFFLEdBQUcsRUFBRSw4Q0FBOEMsRUFBRSxFQUFFO1lBQzdHLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSx5Q0FBeUMsRUFBRSxFQUFFO1lBQzlGLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSx5Q0FBeUMsRUFBRSxFQUFFO1lBQzlGLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSx5Q0FBeUMsRUFBRSxFQUFFO1lBQzlGLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLEdBQUcsRUFBRSwyQ0FBMkMsRUFBRSxFQUFFO1lBQ3BHLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLEdBQUcsRUFBRSwyQ0FBMkMsRUFBRSxFQUFFO1lBQ3BHLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLEdBQUcsRUFBRSwyQ0FBMkMsRUFBRSxFQUFFO1lBQ3BHLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLEdBQUcsRUFBRSwyQ0FBMkMsRUFBRSxFQUFFO1lBQ3BHLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSx5Q0FBeUMsRUFBRSxFQUFFO1lBQzlGLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLEdBQUcsRUFBRSwyQ0FBMkMsRUFBRSxFQUFFO1lBQ3BHLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSx3Q0FBd0MsRUFBRSxFQUFFO1lBQzNGLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLEdBQUcsRUFBRSwyQ0FBMkMsRUFBRSxFQUFFO1lBQ3BHLEVBQUUsS0FBSyxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsZUFBZSxFQUFFLEdBQUcsRUFBRSw4Q0FBOEMsRUFBRSxFQUFFO1lBQzdHLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLEdBQUcsRUFBRSwyQ0FBMkMsRUFBRSxFQUFFO1lBQ3BHLEVBQUUsS0FBSyxFQUFDLFNBQVMsRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBQyw0Q0FBNEMsRUFBRSxFQUFFO1NBRWxHO0tBQ0Y7SUFDRDtRQUNFLEtBQUssRUFBRSxpQ0FBaUM7UUFDeEMsSUFBSSxFQUFFLElBQUk7UUFDVixRQUFRLEVBQUU7WUFDUixFQUFFLEtBQUssRUFBQyxTQUFTLEVBQUUsSUFBSSxFQUFFLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxHQUFHLEVBQUMsNENBQTRDLEVBQUUsRUFBRTtZQUNqRyxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLEVBQUUsS0FBSyxFQUFFLFdBQVcsRUFBRSxHQUFHLEVBQUMsMENBQTBDLEVBQUUsRUFBRTtZQUNoRyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLEVBQUUsS0FBSyxFQUFFLGFBQWEsRUFBRSxHQUFHLEVBQUMsNENBQTRDLEVBQUUsRUFBRTtZQUN0RyxFQUFFLEtBQUssRUFBQyxTQUFTLEVBQUUsSUFBSSxFQUFFLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxHQUFHLEVBQUMsNENBQTRDLEVBQUUsRUFBRTtZQUNqRyxFQUFFLEtBQUssRUFBQyxVQUFVLEVBQUUsSUFBSSxFQUFFLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRSxHQUFHLEVBQUUsNkNBQTZDLEVBQUUsRUFBRTtZQUNyRyxFQUFFLEtBQUssRUFBQyxRQUFRLEVBQUUsSUFBSSxFQUFFLEVBQUUsS0FBSyxFQUFFLFlBQVksRUFBRSxHQUFHLEVBQUMsMkNBQTJDLEVBQUUsRUFBRTtTQUNuRztLQUNGO0lBQ0Q7UUFDRSxLQUFLLEVBQUUsV0FBVztRQUNsQixJQUFJLEVBQUUsSUFBSTtRQUNWLFFBQVEsRUFBRTtZQUNSLEVBQUUsS0FBSyxFQUFDLE1BQU0sRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBQyx5Q0FBeUMsRUFBRSxFQUFFO1lBQzVGLEVBQUUsS0FBSyxFQUFDLE1BQU0sRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBQyx5Q0FBeUMsRUFBRSxFQUFFO1lBQzVGLEVBQUUsS0FBSyxFQUFDLE1BQU0sRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBQyx5Q0FBeUMsRUFBRSxFQUFFO1lBQzVGLEVBQUUsS0FBSyxFQUFDLE1BQU0sRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBQyx5Q0FBeUMsRUFBRSxFQUFFO1lBQzVGLEVBQUUsS0FBSyxFQUFDLE1BQU0sRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBQyx5Q0FBeUMsRUFBRSxFQUFFO1lBQzVGLEVBQUUsS0FBSyxFQUFDLE1BQU0sRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBQyx5Q0FBeUMsRUFBRSxFQUFFO1lBQzVGLEVBQUUsS0FBSyxFQUFDLFFBQVEsRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLEdBQUcsRUFBQywyQ0FBMkMsRUFBRSxFQUFFO1lBQ2xHLEVBQUUsS0FBSyxFQUFDLFFBQVEsRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLEdBQUcsRUFBQywyQ0FBMkMsRUFBRSxFQUFFO1lBQ2xHLEVBQUUsS0FBSyxFQUFDLFVBQVUsRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsY0FBYyxFQUFFLEdBQUcsRUFBQyw2Q0FBNkMsRUFBRSxFQUFFO1lBQ3hHLEVBQUUsS0FBSyxFQUFDLFVBQVUsRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsY0FBYyxFQUFFLEdBQUcsRUFBQyw2Q0FBNkMsRUFBRSxFQUFFO1lBQ3hHLEVBQUUsS0FBSyxFQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBQyx3Q0FBd0MsRUFBRSxFQUFFO1lBQ3pGLEVBQUUsS0FBSyxFQUFDLFNBQVMsRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsYUFBYSxFQUFFLEdBQUcsRUFBQyw0Q0FBNEMsRUFBRSxFQUFFO1lBQ3JHLEVBQUUsS0FBSyxFQUFDLFFBQVEsRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLEdBQUcsRUFBQywyQ0FBMkMsRUFBRSxFQUFFO1lBQ2xHLEVBQUUsS0FBSyxFQUFDLFNBQVMsRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsYUFBYSxFQUFFLEdBQUcsRUFBQyw0Q0FBNEMsRUFBRSxFQUFFO1lBQ3JHLEVBQUUsS0FBSyxFQUFDLFFBQVEsRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLEdBQUcsRUFBQywyQ0FBMkMsRUFBRSxFQUFFO1lBQ2xHLEVBQUUsS0FBSyxFQUFDLFFBQVEsRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLEdBQUcsRUFBQywyQ0FBMkMsRUFBRSxFQUFFO1lBQzlGLEVBQUUsS0FBSyxFQUFDLFVBQVUsRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBQyw2Q0FBNkMsRUFBRSxFQUFFO1NBRXJHO0tBQ0Y7SUFDRDtRQUNF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RSxDQUFDO1FBQzNCLE1BQU0sR0FBRyxHQUFHLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUM3QixNQUFNLElBQUksR0FBRyxHQUFHLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztRQUM1QixNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxHQUFHLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDMUYsTUFBTSxDQUFDLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUM7UUFDckMsSUFBSSxDQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7UUFBQyxJQUFJLENBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztRQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsRUFBRSxDQUFDO1FBQzVELEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUMzQixJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUM3QixJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUM3QixJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2hELENBQUM7UUFD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dXJjZXNDb250ZW50IjpbImltcG9ydCB7IFBvbHlnb24sIFJlY3RhbmdsZSwgUmVnaW9uLCBNdWx0aVBvbHlnb24gfSBmcm9tICcuL21vZGVscy9yZWdpb24nO1xuaW1wb3J0IHsgU2hhcGVTZWxlY3Rpb24gfSBmcm9tICcuL21vZGVscy9zaGFwZSc7XG5pbXBvcnQgeyByZXNvbHZlSGFuZGxlcywgYmV6aWVyQ3VydmVGcm9tSGFuZGxlcyB9IGZyb20gJy4vbW9kZWxzL2Jlemllcic7XG5pbXBvcnQgeyBzYXZlQXMgfSBmcm9tICdmaWxlLXNhdmVyJztcblxuZXhwb3J0IGNvbnN0IENPTE9STUFQX09QVElPTlMgPSBbXG4gIHtcbiAgICBsYWJlbDogJ1NlcXVlbnRpYWwnLFxuICAgIGRhdGE6IG51bGwsXG4gICAgY2hpbGRyZW46IFtcbiAgICAgIHsgbGFiZWw6J0dyZXlzJywgZGF0YTogeyB2YWx1ZTogJ0dSRVlTX0xVVCcsIHNyYzonYXNzZXRzL3Bsb3R0aW5nL2ljb25zL2NvbG9ybWFwLWdyZXlzLnBuZycgfSB9LFxuICAgICAgeyBsYWJlbDonUHVycGxlcycsIGRhdGE6IHsgdmFsdWU6ICdQVVJQTEVTX0xVVCcsIHNyYzonYXNzZXRzL3Bsb3R0aW5nL2ljb25zL2NvbG9ybWFwLXB1cnBsZXMucG5nJyB9IH0sXG4gICAgICB7IGxhYmVsOidCbHVlcycsIGRhdGE6IHsgdmFsdWU6ICdCTFVFU19MVVQnLCBzcmM6J2Fzc2V0cy9wbG90dGluZy9pY29ucy9jb2xvcm1hcC1ibHVlcy5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6J0dyZWVucycsIGRhdGE6IHsgdmFsdWU6ICdHUkVFTlNfTFVUJywgc3JjOidhc3NldHMvcGxvdHRpbmcvaWNvbnMvY29sb3JtYXAtZ3JlZW5zLnBuZycgfSB9LFxuICAgICAgeyBsYWJlbDonT3JhbmdlcycsIGRhdGE6IHsgdmFsdWU6ICdPUkFOR0VTX0xVVCcsIHNyYzonYXNzZXRzL3Bsb3R0aW5nL2ljb25zL2NvbG9ybWFwLW9yYW5nZXMucG5nJyB9IH0sXG4gICAgICB7IGxhYmVsOidSZWRzJywgZGF0YTogeyB2YWx1ZTogJ1JlZHMnLCBzcmM6J2Fzc2V0cy9wbG90dGluZy9pY29ucy9jb2xvcm1hcC1yZWRzLnBuZycgfSB9LFxuICAgICAgeyBsYWJlbDonWWxPckJyJywgZGF0YTogeyB2YWx1ZTogJ1lMT1JCUl9MVVQnLCBzcmM6J2Fzc2V0cy9wbG90dGluZy9pY29ucy9jb2xvcm1hcC15bG9yYnIucG5nJyB9IH0sXG4gICAgICB7IGxhYmVsOidZbE9yUmQnLCBkYXRhOiB7IHZhbHVlOiAnWUxPUlJEX0xVVCcsIHNyYzonYXNzZXRzL3Bsb3R0aW5nL2ljb25zL2NvbG9ybWFwLXlsb3JyZC5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6J09yUmQnLCBkYXRhOiB7IHZhbHVlOiAnT1JSRF9MVVQnLCBzcmM6J2Fzc2V0cy9wbG90dGluZy9pY29ucy9jb2xvcm1hcC1vcnJkLnBuZycgfSB9LFxuICAgICAgeyBsYWJlbDonUHVSZCcsIGRhdGE6IHsgdmFsdWU6ICdQVVJEX0xVVCcsIHNyYzonYXNzZXRzL3Bsb3R0aW5nL2ljb25zL2NvbG9ybWFwLXB1cmQucG5nJyB9IH0sXG4gICAgICB7IGxhYmVsOidSZFB1JywgZGF0YTogeyB2YWx1ZTogJ1JEUFVfTFVUJywgc3JjOidhc3NldHMvcGxvdHRpbmcvaWNvbnMvY29sb3JtYXAtcmRwdS5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6J0J1UHUnLCBkYXRhOiB7IHZhbHVlOiAnQlVQVV9MVVQnLCBzcmM6J2Fzc2V0cy9wbG90dGluZy9pY29ucy9jb2xvcm1hcC1idXB1LnBuZycgfSB9LFxuICAgICAgeyBsYWJlbDonR25CdScsIGRhdGE6IHsgdmFsdWU6ICdHTkJVX0xVVCcsIHNyYzonYXNzZXRzL3Bsb3R0aW5nL2ljb25zL2NvbG9ybWFwLWduYnUucG5nJyB9IH0sXG4gICAgICB7IGxhYmVsOidZbEduQnUnLCBkYXRhOiB7IHZhbHVlOiAnWUxHTkJVX0xVVCcsIHNyYzonYXNzZXRzL3Bsb3R0aW5nL2ljb25zL2NvbG9ybWFwLXlsZ25idS5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6J1B1QnVHbicsIGRhdGE6IHsgdmFsdWU6ICdQVUJVR05fTFVUJywgc3JjOidhc3NldHMvcGxvdHRpbmcvaWNvbnMvY29sb3JtYXAtcHVidWduLnBuZycgfSB9LFxuICAgICAgeyBsYWJlbDonQnVHbicsIGRhdGE6IHsgdmFsdWU6ICdCVUdOX0xVVCcsIHNyYzonYXNzZXRzL3Bsb3R0aW5nL2ljb25zL2NvbG9ybWFwLWJ1Z24ucG5nJyB9IH0sXG4gICAgICB7IGxhYmVsOidZbEduJywgZGF0YTogeyB2YWx1ZTogJ1lMR05fTFVUJywgc3JjOidhc3NldHMvcGxvdHRpbmcvaWNvbnMvY29sb3JtYXAteWxnbi5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6J0dyZXlzIEludicsIGRhdGE6IHsgdmFsdWU6ICdHcmV5cycsIHNyYzonYXNzZXRzL3Bsb3R0aW5nL2ljb25zL2NvbG9ybWFwLWdyZXlzLWludi5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6J0dyZWVucyBJbnYnLCBkYXRhOiB7IHZhbHVlOiAnR3JlZW5zJywgc3JjOidhc3NldHMvcGxvdHRpbmcvaWNvbnMvY29sb3JtYXAtZ3JlZW5zLWludi5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6J1lsT3JSZCBJbnYnLCBkYXRhOiB7IHZhbHVlOiAnWWxPclJkJywgc3JjOidhc3NldHMvcGxvdHRpbmcvaWNvbnMvY29sb3JtYXAteWxvcnJkLWludi5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6J1lsR25CdSBJbnYnLCBkYXRhOiB7IHZhbHVlOiAnWWxHbkJ1Jywgc3JjOidhc3NldHMvcGxvdHRpbmcvaWNvbnMvY29sb3JtYXAteWxnbmJ1LWludi5wbmcnIH0gfSxcbiAgICBdXG4gIH0sXG4gIHtcbiAgICBsYWJlbDogJ1NlcXVlbnRpYWwgKDIpJyxcbiAgICBkYXRhOiBudWxsLFxuICAgIGNoaWxkcmVuOiBbXG4gICAgICB7IGxhYmVsOiAnYmluYXJ5JywgZGF0YTogeyB2YWx1ZTogJ0JJTkFSWV9MVVQnLCBzcmM6ICdhc3NldHMvcGxvdHRpbmcvaWNvbnMvY29sb3JtYXAtYmluYXJ5LnBuZycgfSB9LFxuICAgICAgeyBsYWJlbDogJ2dpc3RfeWFyZycsIGRhdGE6IHsgdmFsdWU6ICdHSVNUX1lBUkdfTFVUJywgc3JjOiAnYXNzZXRzL3Bsb3R0aW5nL2ljb25zL2NvbG9ybWFwLWdpc3RfeWFyZy5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6ICdnaXN0X2dyYXknLCBkYXRhOiB7IHZhbHVlOiAnR0lTVF9HUkFZX0xVVCcsIHNyYzogJ2Fzc2V0cy9wbG90dGluZy9pY29ucy9jb2xvcm1hcC1naXN0X2dyYXkucG5nJyB9IH0sXG4gICAgICB7IGxhYmVsOiAnZ3JheScsIGRhdGE6IHsgdmFsdWU6ICdHUkFZX0xVVCcsIHNyYzogJ2Fzc2V0cy9wbG90dGluZy9pY29ucy9jb2xvcm1hcC1ncmF5LnBuZycgfSB9LFxuICAgICAgeyBsYWJlbDogJ2JvbmUnLCBkYXRhOiB7IHZhbHVlOiAnQk9ORV9MVVQnLCBzcmM6ICdhc3NldHMvcGxvdHRpbmcvaWNvbnMvY29sb3JtYXAtYm9uZS5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6ICdwaW5rJywgZGF0YTogeyB2YWx1ZTogJ1BJTktfTFVUJywgc3JjOiAnYXNzZXRzL3Bsb3R0aW5nL2ljb25zL2NvbG9ybWFwLXBpbmsucG5nJyB9IH0sXG4gICAgICB7IGxhYmVsOiAnc3ByaW5nJywgZGF0YTogeyB2YWx1ZTogJ1NQUklOR19MVVQnLCBzcmM6ICdhc3NldHMvcGxvdHRpbmcvaWNvbnMvY29sb3JtYXAtc3ByaW5nLnBuZycgfSB9LFxuICAgICAgeyBsYWJlbDogJ3N1bW1lcicsIGRhdGE6IHsgdmFsdWU6ICdTVU1NRVJfTFVUJywgc3JjOiAnYXNzZXRzL3Bsb3R0aW5nL2ljb25zL2NvbG9ybWFwLXN1bW1lci5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6ICdhdXR1bW4nLCBkYXRhOiB7IHZhbHVlOiAnQVVUVU1OX0xVVCcsIHNyYzogJ2Fzc2V0cy9wbG90dGluZy9pY29ucy9jb2xvcm1hcC1hdXR1bW4ucG5nJyB9IH0sXG4gICAgICB7IGxhYmVsOiAnd2ludGVyJywgZGF0YTogeyB2YWx1ZTogJ1dJTlRFUl9MVVQnLCBzcmM6ICdhc3NldHMvcGxvdHRpbmcvaWNvbnMvY29sb3JtYXAtd2ludGVyLnBuZycgfSB9LFxuICAgICAgeyBsYWJlbDogJ2Nvb2wnLCBkYXRhOiB7IHZhbHVlOiAnQ09PTF9MVVQnLCBzcmM6ICdhc3NldHMvcGxvdHRpbmcvaWNvbnMvY29sb3JtYXAtY29vbC5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6ICdXaXN0aWEnLCBkYXRhOiB7IHZhbHVlOiAnV0lTVElBX0xVVCcsIHNyYzogJ2Fzc2V0cy9wbG90dGluZy9pY29ucy9jb2xvcm1hcC13aXN0aWEucG5nJyB9IH0sXG4gICAgICB7IGxhYmVsOiAnaG90JywgZGF0YTogeyB2YWx1ZTogJ0hPVF9MVVQnLCBzcmM6ICdhc3NldHMvcGxvdHRpbmcvaWNvbnMvY29sb3JtYXAtaG90LnBuZycgfSB9LFxuICAgICAgeyBsYWJlbDogJ2FmbWhvdCcsIGRhdGE6IHsgdmFsdWU6ICdBRk1IT1RfTFVUJywgc3JjOiAnYXNzZXRzL3Bsb3R0aW5nL2ljb25zL2NvbG9ybWFwLWFmbWhvdC5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6ICdnaXN0X2hlYXQnLCBkYXRhOiB7IHZhbHVlOiAnR0lTVF9IRUFUX0xVVCcsIHNyYzogJ2Fzc2V0cy9wbG90dGluZy9pY29ucy9jb2xvcm1hcC1naXN0X2hlYXQucG5nJyB9IH0sXG4gICAgICB7IGxhYmVsOiAnY29wcGVyJywgZGF0YTogeyB2YWx1ZTogJ0NPUFBFUl9MVVQnLCBzcmM6ICdhc3NldHMvcGxvdHRpbmcvaWNvbnMvY29sb3JtYXAtY29wcGVyLnBuZycgfSB9LFxuICAgICAgeyBsYWJlbDonQmx1ZXJlZCcsIGRhdGE6IHsgdmFsdWU6ICdCbHVlcmVkJywgc3JjOidhc3NldHMvcGxvdHRpbmcvaWNvbnMvY29sb3JtYXAtYmx1ZXJlZC5wbmcnIH0gfSxcblxuICAgIF1cbiAgfSxcbiAge1xuICAgIGxhYmVsOiAnUGVyY2VwdHVhbGx5IFVuaWZvcm0gU2VxdWVudGlhbCcsXG4gICAgZGF0YTogbnVsbCxcbiAgICBjaGlsZHJlbjogW1xuICAgICAgeyBsYWJlbDonVmlyaWRpcycsIGRhdGE6IHsgdmFsdWU6ICdWaXJpZGlzJywgc3JjOidhc3NldHMvcGxvdHRpbmcvaWNvbnMvY29sb3JtYXAtdmlyaWRpcy5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6ICdNYWdtYScsIGRhdGE6IHsgdmFsdWU6ICdNQUdNQV9MVVQnLCBzcmM6J2Fzc2V0cy9wbG90dGluZy9pY29ucy9jb2xvcm1hcC1tYWdtYS5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6ICdJbmZlcm5vJywgZGF0YTogeyB2YWx1ZTogJ0lORkVSTk9fTFVUJywgc3JjOidhc3NldHMvcGxvdHRpbmcvaWNvbnMvY29sb3JtYXAtaW5mZXJuby5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6J0NpdmlkaXMnLCBkYXRhOiB7IHZhbHVlOiAnQ2l2aWRpcycsIHNyYzonYXNzZXRzL3Bsb3R0aW5nL2ljb25zL2NvbG9ybWFwLWNpdmlkaXMucG5nJyB9IH0sXG4gICAgICB7IGxhYmVsOidFbGVjdHJpYycsIGRhdGE6IHsgdmFsdWU6ICdFbGVjdHJpYycsIHNyYzogJ2Fzc2V0cy9wbG90dGluZy9pY29ucy9jb2xvcm1hcC1lbGVjdHJpYy5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6J1BsYXNtYScsIGRhdGE6IHsgdmFsdWU6ICdQTEFTTUFfTFVUJywgc3JjOidhc3NldHMvcGxvdHRpbmcvaWNvbnMvY29sb3JtYXAtcGxhc21hLnBuZycgfSB9LFxuICAgIF1cbiAgfSxcbiAge1xuICAgIGxhYmVsOiAnRGl2ZXJnaW5nJyxcbiAgICBkYXRhOiBudWxsLFxuICAgIGNoaWxkcmVuOiBbXG4gICAgICB7IGxhYmVsOidQaVlHJywgZGF0YTogeyB2YWx1ZTogJ1BJWUdfTFVUJywgc3JjOidhc3NldHMvcGxvdHRpbmcvaWNvbnMvY29sb3JtYXAtcGl5Zy5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6J1BSR24nLCBkYXRhOiB7IHZhbHVlOiAnUFJHTl9MVVQnLCBzcmM6J2Fzc2V0cy9wbG90dGluZy9pY29ucy9jb2xvcm1hcC1wcmduLnBuZycgfSB9LFxuICAgICAgeyBsYWJlbDonQnJCRycsIGRhdGE6IHsgdmFsdWU6ICdCUkJHX0xVVCcsIHNyYzonYXNzZXRzL3Bsb3R0aW5nL2ljb25zL2NvbG9ybWFwLWJyYmcucG5nJyB9IH0sXG4gICAgICB7IGxhYmVsOidQdU9yJywgZGF0YTogeyB2YWx1ZTogJ1BVT1JfTFVUJywgc3JjOidhc3NldHMvcGxvdHRpbmcvaWNvbnMvY29sb3JtYXAtcHVvci5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6J1JkR3knLCBkYXRhOiB7IHZhbHVlOiAnUkRHWV9MVVQnLCBzcmM6J2Fzc2V0cy9wbG90dGluZy9pY29ucy9jb2xvcm1hcC1yZGd5LnBuZycgfSB9LFxuICAgICAgeyBsYWJlbDonUmRCdScsIGRhdGE6IHsgdmFsdWU6ICdSREJVX0xVVCcsIHNyYzonYXNzZXRzL3Bsb3R0aW5nL2ljb25zL2NvbG9ybWFwLXJkYnUucG5nJyB9IH0sXG4gICAgICB7IGxhYmVsOidSZFlsQnUnLCBkYXRhOiB7IHZhbHVlOiAnUkRZTEJVX0xVVCcsIHNyYzonYXNzZXRzL3Bsb3R0aW5nL2ljb25zL2NvbG9ybWFwLXJkeWxidS5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6J1JkWWxHbicsIGRhdGE6IHsgdmFsdWU6ICdSRFlMR05fTFVUJywgc3JjOidhc3NldHMvcGxvdHRpbmcvaWNvbnMvY29sb3JtYXAtcmR5bGduLnBuZycgfSB9LFxuICAgICAgeyBsYWJlbDonU3BlY3RyYWwnLCBkYXRhOiB7IHZhbHVlOiAnU1BFQ1RSQUxfTFVUJywgc3JjOidhc3NldHMvcGxvdHRpbmcvaWNvbnMvY29sb3JtYXAtc3BlY3RyYWwucG5nJyB9IH0sXG4gICAgICB7IGxhYmVsOidjb29sd2FybScsIGRhdGE6IHsgdmFsdWU6ICdDT09MV0FSTV9MVVQnLCBzcmM6J2Fzc2V0cy9wbG90dGluZy9pY29ucy9jb2xvcm1hcC1jb29sd2FybS5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6J2J3cicsIGRhdGE6IHsgdmFsdWU6ICdCV1JfTFVUJywgc3JjOidhc3NldHMvcGxvdHRpbmcvaWNvbnMvY29sb3JtYXAtYndyLnBuZycgfSB9LFxuICAgICAgeyBsYWJlbDonc2Vpc21pYycsIGRhdGE6IHsgdmFsdWU6ICdTRUlTTUlDX0xVVCcsIHNyYzonYXNzZXRzL3Bsb3R0aW5nL2ljb25zL2NvbG9ybWFwLXNlaXNtaWMucG5nJyB9IH0sXG4gICAgICB7IGxhYmVsOidiZXJsaW4nLCBkYXRhOiB7IHZhbHVlOiAnQkVSTElOX0xVVCcsIHNyYzonYXNzZXRzL3Bsb3R0aW5nL2ljb25zL2NvbG9ybWFwLWJlcmxpbi5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6J21hbmFndWEnLCBkYXRhOiB7IHZhbHVlOiAnTUFOQUdVQV9MVVQnLCBzcmM6J2Fzc2V0cy9wbG90dGluZy9pY29ucy9jb2xvcm1hcC1tYW5hZ3VhLnBuZycgfSB9LFxuICAgICAgeyBsYWJlbDondmFuaW1vJywgZGF0YTogeyB2YWx1ZTogJ1ZBTklNT19MVVQnLCBzcmM6J2Fzc2V0cy9wbG90dGluZy9pY29ucy9jb2xvcm1hcC12YW5pbW8ucG5nJyB9IH0sXG4gICAgICB7IGxhYmVsOidQaWNuaWMnLCBkYXRhOiB7IHZhbHVlOiAnUGljbmljJywgc3JjOidhc3NldHMvcGxvdHRpbmcvaWNvbnMvY29sb3JtYXAtcGljbmljLnBuZycgfSB9LFxuICAgICAgeyBsYWJlbDonUG9ydGxhbmQnLCBkYXRhOiB7IHZhbHVlOiAnUG9ydGxhbmQnLCBzcmM6J2Fzc2V0cy9wbG90dGluZy9pY29ucy9jb2xvcm1hcC1wb3J0bGFuZC5wbmcnIH0gfSxcblxuICAgIF1cbiAgfSxcbiAge1xuICAgIGxhYmVsOiAnQ3ljbGljJyxcbiAgICBkYXRhOiBudWxsLFxuICAgIGNoaWxkcmVuOiBbXG4gICAgICB7IGxhYmVsOid0d2lsaWdodCcsIGRhdGE6IHsgdmFsdWU6ICdUV0lMSUdIVF9MVVQnLCBzcmM6J2Fzc2V0cy9wbG90dGluZy9pY29ucy9jb2xvcm1hcC10d2lsaWdodC5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6J3R3aWxpZ2h0X3NoaWZ0ZWQnLCBkYXRhOiB7IHZhbHVlOiAnVFdJTElHSFRfU0hJRlRFRF9MVVQnLCBzcmM6J2Fzc2V0cy9wbG90dGluZy9pY29ucy9jb2xvcm1hcC10d2lsaWdodF9zaGlmdGVkLnBuZycgfSB9LFxuICAgICAgeyBsYWJlbDogJ2hzdicsIGRhdGE6IHsgdmFsdWU6ICdIU1ZfTFVUJywgc3JjOiAnYXNzZXRzL3Bsb3R0aW5nL2ljb25zL2NvbG9ybWFwLWhzdi5wbmcnIH0gfSxcbiAgICBdXG4gIH0sXG4gIHtcbiAgICBsYWJlbDogJ1F1YWxpdGF0aXZlJyxcbiAgICBkYXRhOiBudWxsLFxuICAgIGNoaWxkcmVuOiBbXG4gICAgICB7IGxhYmVsOidQYXN0ZWwxJywgZGF0YTogeyB2YWx1ZTogJ1BBU1RFTDFfTFVUJywgc3JjOidhc3NldHMvcGxvdHRpbmcvaWNvbnMvY29sb3JtYXAtUGFzdGVsMS5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6J1Bhc3RlbDInLCBkYXRhOiB7IHZhbHVlOiAnUEFTVEVMMl9MVVQnLCBzcmM6J2Fzc2V0cy9wbG90dGluZy9pY29ucy9jb2xvcm1hcC1wYXN0ZWwyLnBuZycgfSB9LFxuICAgICAgeyBsYWJlbDonQWNjZW50JywgZGF0YTogeyB2YWx1ZTogJ0FDQ0VOVF9MVVQnLCBzcmM6J2Fzc2V0cy9wbG90dGluZy9pY29ucy9jb2xvcm1hcC1hY2NlbnQucG5nJyB9IH0sXG4gICAgICB7IGxhYmVsOidEYXJrMicsIGRhdGE6IHsgdmFsdWU6ICdEQVJLMl9MVVQnLCBzcmM6J2Fzc2V0cy9wbG90dGluZy9pY29ucy9jb2xvcm1hcC1kYXJrMi5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6J1NldDEnLCBkYXRhOiB7IHZhbHVlOiAnU0VUMV9MVVQnLCBzcmM6J2Fzc2V0cy9wbG90dGluZy9pY29ucy9jb2xvcm1hcC1zZXQxLnBuZycgfSB9LFxuICAgICAgeyBsYWJlbDonU2V0MicsIGRhdGE6IHsgdmFsdWU6ICdTRVQyX0xVVCcsIHNyYzonYXNzZXRzL3Bsb3R0aW5nL2ljb25zL2NvbG9ybWFwLXNldDIucG5nJyB9IH0sXG4gICAgICB7IGxhYmVsOidTZXQzJywgZGF0YTogeyB2YWx1ZTogJ1NFVDNfTFVUJywgc3JjOiAnYXNzZXRzL3Bsb3R0aW5nL2ljb25zL2NvbG9ybWFwLXNldDMucG5nJyB9IH0sXG4gICAgICB7IGxhYmVsOid0YWIxMCcsIGRhdGE6IHsgdmFsdWU6ICdUQUIxMF9MVVQnLCBzcmM6J2Fzc2V0cy9wbG90dGluZy9pY29ucy9jb2xvcm1hcC10YWIxMC5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6J3RhYjIwJywgZGF0YTogeyB2YWx1ZTogJ1RBQjIwX0xVVCcsIHNyYzonYXNzZXRzL3Bsb3R0aW5nL2ljb25zL2NvbG9ybWFwLXRhYjIwLnBuZycgfSB9LFxuICAgICAgeyBsYWJlbDondGFiMjBiJywgZGF0YTogeyB2YWx1ZTogJ1RBQjIwQl9MVVQnLCBzcmM6J2Fzc2V0cy9wbG90dGluZy9pY29ucy9jb2xvcm1hcC10YWIyMGIucG5nJyB9IH0sXG4gICAgICB7IGxhYmVsOid0YWIyMGMnLCBkYXRhOiB7IHZhbHVlOiAnVEFCMjBDX0xVVCcsIHNyYzogJ2Fzc2V0cy9wbG90dGluZy9pY29ucy9jb2xvcm1hcC10YWIyMGMucG5nJyB9IH1cbiAgICBdXG4gIH0sXG4gIHtcbiAgICBsYWJlbDogJ01pc2NlbGxhbmVvdXMnLFxuICAgIGRhdGE6IG51bGwsXG4gICAgY2hpbGRyZW46IFtcbiAgICAgIHsgbGFiZWw6J2ZsYWcnLCBkYXRhOiB7IHZhbHVlOiAnRkxBR19MVVQnLCBzcmM6ICdhc3NldHMvcGxvdHRpbmcvaWNvbnMvY29sb3JtYXAtZmxhZy5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6J3ByaXNtJywgZGF0YTogeyB2YWx1ZTogJ1BSSVNNX0xVVCcsIHNyYzogJ2Fzc2V0cy9wbG90dGluZy9pY29ucy9jb2xvcm1hcC1wcmlzbS5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6J29jZWFuJywgZGF0YTogeyB2YWx1ZTogJ09DRUFOX0xVVCcsIHNyYzogJ2Fzc2V0cy9wbG90dGluZy9pY29ucy9jb2xvcm1hcC1vY2Vhbi5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6J2dpc3RfZWFydGgnLCBkYXRhOiB7IHZhbHVlOiAnR0lTVF9FQVJUSF9MVVQnLCBzcmM6ICdhc3NldHMvcGxvdHRpbmcvaWNvbnMvY29sb3JtYXAtZ2lzdF9lYXJ0aC5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6J3RlcnJhaW4nLCBkYXRhOiB7IHZhbHVlOiAnVEVSUkFJTl9MVVQnLCBzcmM6ICdhc3NldHMvcGxvdHRpbmcvaWNvbnMvY29sb3JtYXAtdGVycmFpbi5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6J2dpc3Rfc3Rlcm4nLCBkYXRhOiB7IHZhbHVlOiAnR0lTVF9TVEVSTl9MVVQnLCBzcmM6ICdhc3NldHMvcGxvdHRpbmcvaWNvbnMvY29sb3JtYXAtZ2lzdF9zdGVybi5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6J2dudXBsb3QnLCBkYXRhOiB7IHZhbHVlOiAnR05VUExPVF9MVVQnLCBzcmM6ICdhc3NldHMvcGxvdHRpbmcvaWNvbnMvY29sb3JtYXAtZ251cGxvdC5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6J2dudXBsb3QyJywgZGF0YTogeyB2YWx1ZTogJ0dOVVBMT1QyX0xVVCcsIHNyYzogJ2Fzc2V0cy9wbG90dGluZy9pY29ucy9jb2xvcm1hcC1nbnVwbG90Mi5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6J0NNUm1hcCcsIGRhdGE6IHsgdmFsdWU6ICdDTVJNQVBfTFVUJywgc3JjOiAnYXNzZXRzL3Bsb3R0aW5nL2ljb25zL2NvbG9ybWFwLWNtcm1hcC5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6J2N1YmVoZWxpeCcsIGRhdGE6IHsgdmFsdWU6ICdDVUJFSEVMSVhfTFVUJywgc3JjOiAnYXNzZXRzL3Bsb3R0aW5nL2ljb25zL2NvbG9ybWFwLWN1YmVoZWxpeC5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6J2JyZycsIGRhdGE6IHsgdmFsdWU6ICdCUkdfTFVUJywgc3JjOiAnYXNzZXRzL3Bsb3R0aW5nL2ljb25zL2NvbG9ybWFwLWJyZy5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6J2dpc3RfcmFpbmJvdycsIGRhdGE6IHsgdmFsdWU6ICdHSVNUX1JBSU5CT1dfTFVUJywgc3JjOiAnYXNzZXRzL3Bsb3R0aW5nL2ljb25zL2NvbG9ybWFwLWdpc3RfcmFpbmJvdy5wbmcnIH0gfSxcbiAgICAgIHsgbGFiZWw6J3JhaW5ib3cnLCBkYXRhOiB7IHZhbHVlOiAnUkFJTkJPV19MVVQnLCBzcmM6J2Fzc2V0cy9wbG90dGluZy9pY29ucy9jb2xvcm1hcC1yYWluYm93LnBuZycgfSB9LFxuICAgICAgeyBsYWJlbDonamV0JywgZGF0YTogeyB2YWx1ZTogJ0pFVF9MVVQnLCBzcmM6J2Fzc2V0cy9wbG90dGluZy9pY29ucy9jb2xvcm1hcC1qZXQucG5nJyB9IH0sXG4gICAgICB7IGxhYmVsOid0dXJibycsIGRhdGE6IHsgdmFsdWU6ICdUVVJCT19MVVQnLCBzcmM6ICdhc3NldHMvcGxvdHRpbmcvaWNvbnMvY29sb3JtYXAtdHVyYm8ucG5nJyB9IH0sXG4gICAgICB7IGxhYmVsOiduaXB5X3NwZWN0cmFsJywgZGF0YTogeyB2YWx1ZTogJ05JUFlfU1BFQ1RSQUxfTFVUJywgc3JjOiAnYXNzZXRzL3Bsb3R0aW5nL2ljb25zL2NvbG9ybWFwLW5pcHlfc3BlY3RyYWwucG5nJyB9IH0sXG4gICAgICB7IGxhYmVsOidnaXN0X25jYXInLCBkYXRhOiB7IHZhbHVlOiAnR0lTVF9OQ0FSX0xVVCcsIHNyYzogJ2Fzc2V0cy9wbG90dGluZy9pY29ucy9jb2xvcm1hcC1naXN0X25jYXIucG5nJyB9IH0sXG4gICAgICB7IGxhYmVsOidCbGFja2JvZHknLCBkYXRhOiB7IHZhbHVlOiAnQmxhY2tib2R5Jywgc3JjOidhc3NldHMvcGxvdHRpbmcvaWNvbnMvY29sb3JtYXAtYmxhY2tib2R5LnBuZycgfSB9LFxuICAgIF1cbiAgfVxuXTtcblxuZXhwb3J0IGNvbnN0IENPTkZJRyA9IHtcbiAgZGlzcGxheWxvZ286IGZhbHNlLCAvLyBIaWRlIHRoZSBwbG90bHkgbG9nb1xuICByZXNwb25zaXZlOiB0cnVlLCAvLyBNYWtlIHRoZSBwbG90IHJlc3BvbnNpdmVcbiAgZGlzcGxheU1vZGVCYXI6IGZhbHNlLFxuICBzY3JvbGxab29tOiBmYWxzZSwgLy8gZGlzYWJsZSBtb3VzZSBzY3JvbGwgem9vbVxufTtcbmV4cG9ydCBjb25zdCBDT05GSUdfU1VSRkFDRSA9IHtcbiAgZGlzcGxheWxvZ286IGZhbHNlLCAvLyBIaWRlIHRoZSBwbG90bHkgbG9nb1xuICByZXNwb25zaXZlOiB0cnVlLCAvLyBNYWtlIHRoZSBwbG90IHJlc3BvbnNpdmVcbiAgZGlzcGxheU1vZGVCYXI6IGZhbHNlLFxuICBzY3JvbGxab29tOiB0cnVlLCAvLyAzRCBzY2VuZXMgb3JiaXQvem9vbSBuYXRpdmVseSBvbiBzY3JvbGxcbn07XG5leHBvcnQgY2xhc3MgUGxvdFV0aWxpdGllcyB7XG5cbiAgLyoqXG4gICAqIFJvdW5kcyBhbGwgdGhlIHBvaW50IGNvb3JkaW5hdGVzIG9mIGEgcGF0aCAoJ00xMy41NCw1NC41NjZMMzUuNDQsMzMuM0wzNi4yMiw4OS42WicpXG4gICAqIGJlY29tZXMgJ00xNCw1NUwzNSwzM0wzNiw5MFonXG4gICAqIEBwYXJhbSBwYXRoXG4gICAqL1xuICBwdWJsaWMgcm91bmRQYXRoQ29vcmRpbmF0ZXMocGF0aDogc3RyaW5nKSB7XG4gICAgY29uc3QgaXNDbG9zZWQgPSBwYXRoLmVuZHNXaXRoKCdaJyk7XG4gICAgY29uc3QgaW5uZXIgPSBpc0Nsb3NlZCA/IHBhdGguc3Vic3RyaW5nKDEsIHBhdGgubGVuZ3RoIC0gMSkgOiBwYXRoLnN1YnN0cmluZygxKTtcbiAgICBsZXQgcm91bmRlZFBhdGggPSAnTSc7XG4gICAgY29uc3Qgc3RyQXJyYXkgPSBpbm5lci5zcGxpdCgnTCcpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc3RyQXJyYXkubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IHh5ID0gc3RyQXJyYXlbaV0uc3BsaXQoJywnKTtcbiAgICAgIGlmIChpIDwgc3RyQXJyYXkubGVuZ3RoIC0gMSkge1xuICAgICAgICByb3VuZGVkUGF0aCA9IGAke3JvdW5kZWRQYXRofSR7TWF0aC5yb3VuZCgreHlbMF0pfSwke01hdGgucm91bmQoK3h5WzFdKX1MYDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJvdW5kZWRQYXRoID0gYCR7cm91bmRlZFBhdGh9JHtNYXRoLnJvdW5kKCt4eVswXSl9LCR7TWF0aC5yb3VuZCgreHlbMV0pfWA7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBpc0Nsb3NlZCA/IHJvdW5kZWRQYXRoICsgJ1onIDogcm91bmRlZFBhdGg7XG4gIH1cblxuICAvKipcbiAgICogVHJhbnNmb3JtIGEgMWQgYXJyYXkgaW50byBhIG1hdHJpeCBnaXZlbiBhIGdpdmVuIHdpZHRoXG4gICAqIEBwYXJhbSBhcnJheSBVaW50OEFycmF5XG4gICAqIEBwYXJhbSBlbGVtZW50c1BlclN1YkFycmF5XG4gICAqL1xuICBwdWJsaWMgYXJyYXlUb01hdHJpeChhcnJheTogYW55W10gfCBVaW50OEFycmF5LCBlbGVtZW50c1BlclN1YkFycmF5OiBudW1iZXIpIHtcbiAgICBjb25zdCBtYXRyaXg6IGFueVtdID0gW107XG4gICAgbGV0IGksIGs7XG4gICAgZm9yIChpID0gMCwgayA9IC0xOyBpIDwgYXJyYXkubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmIChpICUgZWxlbWVudHNQZXJTdWJBcnJheSA9PT0gMCkge1xuICAgICAgICBrKys7XG4gICAgICAgIG1hdHJpeFtrXSA9IFtdO1xuICAgICAgfVxuICAgICAgbWF0cml4W2tdLnB1c2goYXJyYXlbaV0pO1xuICAgIH1cbiAgICByZXR1cm4gbWF0cml4O1xuICB9XG5cbiAgLyoqXG4gICAqIGNvb3JkaW5hdGVzIGFyZSBvZiB0aGUgYm90dG9tIGxlZnQgYW5kIHVwcGVyIHJpZ2h0IGNvcm5lcnMgb2YgdGhlIHJlY3RhbmdsZSwgVGhlIGNvb3JkaW5hdGVzXG4gICAqIGFyZSB0YWtlbiBnaXZlbiBhIHlBeGlzIHRoYXQgaXMgdXAgc2lkZSBkb3duIChhcyBmb3IgYWxsIGltYWdlcykuIElmIFpvb20gaXMgb3V0IG9mIHRoZSBpbWFnZSBib3VuZGFyeSxcbiAgICogaXQgd2lsbCByZXR1cm4gdGhlIGltYWdlIHNpemUgY29vcmRpbmF0ZXMgZm9yIHRoZSBuZXcgcmVjdGFuZ2xlLlxuICAgKiBAcGFyYW0gY29vcmRpbmF0ZXMgcGxvdGx5IGNvb3JkaW5hdGVzIChbWGF4aXMucmFuZ2VbMF0sIHhBeGlzLnJhbmdlWzFdLCB5QXhpcy5yYW5nZVswXSwgeWF4aXMucmFuZ2VbMV1dKVxuICAgKiBAcGFyYW0gdHJ1ZUltYWdlU2l6ZSB0cnVlIGltYWdlIHNpemUgWzAsIHgsIDAsIHldXG4gICAqL1xuICBwdWJsaWMgZ2V0UmVjdGFuZ2xlKGNvb3JkaW5hdGVzOiBudW1iZXJbXSwgdHJ1ZUltYWdlU2l6ZTogbnVtYmVyW10pIHtcbiAgICBjb25zdCByZWN0ID0gbmV3IFJlY3RhbmdsZSgpO1xuICAgIC8vIGNoZWNrIGlmIG5ldyBpbWFnZSBzaXplIGlzIGJpZ2dlciB0aGFuIG9yaWdpbmFsIGltYWdlIHNpemVcbiAgICBpZiAoY29vcmRpbmF0ZXNbM10gPCAwKSB7XG4gICAgICBjb29yZGluYXRlc1szXSA9IDA7XG4gICAgfVxuICAgIGlmIChjb29yZGluYXRlc1sxXSA+IHRydWVJbWFnZVNpemVbMV0pIHtcbiAgICAgIGNvb3JkaW5hdGVzWzFdID0gdHJ1ZUltYWdlU2l6ZVsxXTtcbiAgICB9XG4gICAgaWYgKGNvb3JkaW5hdGVzWzJdID4gdHJ1ZUltYWdlU2l6ZVszXSkge1xuICAgICAgY29vcmRpbmF0ZXNbMl0gPSB0cnVlSW1hZ2VTaXplWzNdO1xuICAgIH1cbiAgICBpZiAoY29vcmRpbmF0ZXNbMF0gPCAwKSB7XG4gICAgICBjb29yZGluYXRlc1swXSA9IDA7XG4gICAgfVxuICAgIC8vIGlmIGNvb3JkaW5hdGVzIG91dHNpZGUgb2YgaW1hZ2UgbGVmdC9yaWdodC90b3AvYm90dG9tXG4gICAgLy8gd2Ugc2V0IHRoZSBjb29yZGluYXRlcyB0byB0aGUgb3JpZ2luYWwgaW1hZ2Ugc2l6ZS5cbiAgICBpZiAoY29vcmRpbmF0ZXNbMV0gPCAwIHx8IGNvb3JkaW5hdGVzWzBdID4gdHJ1ZUltYWdlU2l6ZVsxXVxuICAgICAgfHwgY29vcmRpbmF0ZXNbMl0gPCAwIHx8IGNvb3JkaW5hdGVzWzNdID4gdHJ1ZUltYWdlU2l6ZVszXSkge1xuICAgICAgY29vcmRpbmF0ZXNbMF0gPSAwO1xuICAgICAgY29vcmRpbmF0ZXNbMV0gPSB0cnVlSW1hZ2VTaXplWzFdO1xuICAgICAgY29vcmRpbmF0ZXNbMl0gPSB0cnVlSW1hZ2VTaXplWzNdO1xuICAgICAgY29vcmRpbmF0ZXNbM10gPSAwO1xuICAgIH1cbiAgICByZWN0LnggPSBNYXRoLmZsb29yKGNvb3JkaW5hdGVzWzBdKTtcbiAgICByZWN0LnkgPSBNYXRoLmZsb29yKGNvb3JkaW5hdGVzWzNdKTtcbiAgICByZWN0LndpZHRoID0gTWF0aC5mbG9vcihjb29yZGluYXRlc1sxXSAtIGNvb3JkaW5hdGVzWzBdKTtcbiAgICByZWN0LmhlaWdodCA9IE1hdGguZmxvb3IoY29vcmRpbmF0ZXNbMl0gLSBjb29yZGluYXRlc1szXSk7XG4gICAgcmV0dXJuIHJlY3Q7XG4gIH1cblxuICAvKipcbiAgICogZ2l2ZW4gYSBkb20gb2JqZWN0IChmb3VuZCBieSBpZCksIHJldHVybiBhIFJlY3RhbmdsZSBvZiB0aGUgYm91bmRpbmcgZWxlbWVudC5cbiAgICogQHBhcmFtIGRpdlxuICAgKi9cbiAgcHVibGljIGdldERvbVJlY3RhbmdsZShkaXY6IHN0cmluZykge1xuICAgIGNvbnN0IGRvbVJlY3QgPSBuZXcgUmVjdGFuZ2xlKCk7XG4gICAgY29uc3QgYXBwRGl2OiBIVE1MRWxlbWVudCB8IG51bGwgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChkaXYpO1xuICAgIGlmIChhcHBEaXYgJiYgYXBwRGl2LnBhcmVudE5vZGUgJiYgYXBwRGl2LnBhcmVudE5vZGUucGFyZW50RWxlbWVudCkge1xuICAgICAgY29uc3QgcmVjdCA9IGFwcERpdi5wYXJlbnROb2RlLnBhcmVudEVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICBkb21SZWN0LnggPSBNYXRoLnJvdW5kKHJlY3QueCk7XG4gICAgICBkb21SZWN0LnkgPSBNYXRoLnJvdW5kKHJlY3QueSk7XG4gICAgICBkb21SZWN0LndpZHRoID0gTWF0aC5yb3VuZChyZWN0LndpZHRoKTtcbiAgICAgIGRvbVJlY3QuaGVpZ2h0ID0gTWF0aC5yb3VuZChyZWN0LmhlaWdodCk7XG4gICAgfVxuICAgIHJldHVybiBkb21SZWN0O1xuICB9XG5cbiAgLyoqXG4gICAqIHNuYXAgcmVnaW9uICB0byBjbG9zZXN0IHBpeGVsIGluIHRoZSBjb29yZGluYXRlIChyb3VuZCB0aGUgY29vcmRpbmF0ZXMgb2YgdGhlIHJlZ2lvbilcbiAgICogQHBhcmFtIHNoYXBlXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBwdWJsaWMgc25hcFJlZ2lvbihzaGFwZTogU2hhcGVTZWxlY3Rpb24pIHtcbiAgICAvLyBpZiByZWdpb24gaXMgYSBwb2x5Z29uXG4gICAgaWYgKHNoYXBlLnBhdGgpIHtcbiAgICAgIHNoYXBlLnBhdGggPSB0aGlzLnJvdW5kUGF0aENvb3JkaW5hdGVzKHNoYXBlLnBhdGgpO1xuICAgIH0gZWxzZSBpZiAoc2hhcGUueDAgJiYgc2hhcGUueDEgJiYgc2hhcGUueTAgJiYgc2hhcGUueTEpIHtcbiAgICAgIC8vIGlmIHJlZ2lvbiBpcyBhIHJlY3RhbmdsZVxuICAgICAgaWYgKHR5cGVvZiBzaGFwZS54MCA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgc2hhcGUueDAgPSBNYXRoLnJvdW5kKHNoYXBlLngwKTtcbiAgICAgIH1cbiAgICAgIGlmICh0eXBlb2Ygc2hhcGUueDEgPT09ICdudW1iZXInKSB7XG4gICAgICAgIHNoYXBlLngxID0gTWF0aC5yb3VuZChzaGFwZS54MSk7XG4gICAgICB9XG4gICAgICBpZiAodHlwZW9mIHNoYXBlLnkwID09PSAnbnVtYmVyJykge1xuICAgICAgICBzaGFwZS55MCA9IE1hdGgucm91bmQoc2hhcGUueTApO1xuICAgICAgfVxuICAgICAgaWYgKHR5cGVvZiBzaGFwZS55MSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgc2hhcGUueTEgPSBNYXRoLnJvdW5kKHNoYXBlLnkxKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHNoYXBlO1xuICB9XG5cbiAgLyoqXG4gICAqIEdpdmVuIGEgZmlndXJlIChwYXRoIG9yIHJlY3RhbmdsZSksIHJldHVybnMgYSBwb2x5Z29uXG4gICAqIEBwYXJhbSBmaWdcbiAgICovXG4gIHB1YmxpYyBnZXRQb2x5Z29uKGZpZzogYW55KTogYW55IHtcbiAgICBjb25zdCBwb2x5OiBhbnkgPSBuZXcgUG9seWdvbigpO1xuICAgIGlmIChmaWcudHlwZSA9PT0gJ3BhdGgnKSB7XG4gICAgICBjb25zdCB0ZW1wUGF0aCA9IGZpZy5wYXRoIGFzIHN0cmluZztcbiAgICAgIGNvbnN0IGlzQ2xvc2VkID0gdGVtcFBhdGguZW5kc1dpdGgoJ1onKTtcbiAgICAgIGNvbnN0IHBhdGggPSBpc0Nsb3NlZCA/IHRlbXBQYXRoLnN1YnN0cmluZygxLCB0ZW1wUGF0aC5sZW5ndGggLSAxKSA6IHRlbXBQYXRoLnN1YnN0cmluZygxKTtcbiAgICAgIGNvbnN0IHZlcnRzOiBzdHJpbmdbXSA9IHBhdGguc3BsaXQoJ0wnKTtcbiAgICAgIHBvbHkubnBvaW50cyA9IHZlcnRzLmxlbmd0aDtcbiAgICAgIHBvbHkueHBvaW50cyA9IFtdO1xuICAgICAgcG9seS55cG9pbnRzID0gW107XG4gICAgICBwb2x5LmNsb3NlZCA9IGlzQ2xvc2VkO1xuICAgICAgdmVydHMuZm9yRWFjaCgocG50OiBhbnkpID0+IHtcbiAgICAgICAgY29uc3QgcG9pbnQgPSBwbnQuc3BsaXQoJywnKTtcbiAgICAgICAgcG9seS54cG9pbnRzLnB1c2goTWF0aC5yb3VuZChwb2ludFswXSkpO1xuICAgICAgICBwb2x5Lnlwb2ludHMucHVzaChNYXRoLnJvdW5kKHBvaW50WzFdKSk7XG4gICAgICB9KTtcbiAgICB9IGVsc2UgaWYgKGZpZy50eXBlID09PSAncmVjdCcpIHtcbiAgICAgIHBvbHkubnBvaW50cyA9IDQ7XG4gICAgICBwb2x5Lnhwb2ludHMgPSB0aGlzLnJvdW5kKFtmaWcueDAsIGZpZy54MSwgZmlnLngxLCBmaWcueDBdKTtcbiAgICAgIHBvbHkueXBvaW50cyA9IHRoaXMucm91bmQoW2ZpZy55MSwgZmlnLnkxLCBmaWcueTAsIGZpZy55MF0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zb2xlLmxvZygnSWdub3JpbmcgdW5yZWNvZ25pc2VkIHNoYXBlIGluIGRpYWdyYW0nKTtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICByZXR1cm4gcG9seTtcbiAgfVxuXG4gIC8qKlxuICAgKiBURVNURURcbiAgICogUm91bmRzIGEgbGlzdCBvZiBudW1iZXJzXG4gICAqIEBwYXJhbSBhXG4gICAqL1xuICBwdWJsaWMgcm91bmQoYTogbnVtYmVyW10pOiBudW1iZXJbXSB7XG4gICAgY29uc3QgYjogbnVtYmVyW10gPSBbXTtcbiAgICBhLmZvckVhY2goKGQ6IG51bWJlcikgPT4gYi5wdXNoKE1hdGgucm91bmQoZCkpKTtcbiAgICByZXR1cm4gYjtcbiAgfVxuXG4gIC8qKlxuICAgKiBURVNURURcbiAgICogUmV0dXJucyB0cnVlIG9mIHpvb20gaXMgdGhlIHNhbWUgYXMgaW1hZ2Ugc2l6ZVxuICAgKiBAcGFyYW0gcmVjdCBSZWN0YW5nbGUgYXJlYVxuICAgKiBAcGFyYW0gdHJ1ZUltZ1NpemVcbiAgICogQHJldHVybiB0cnVlIGlmIHJlY3QgaXMgb3V0IG9mIGltYWdlIHNpemUgYm91bmRhcnlcbiAgICovXG4gIHB1YmxpYyBpc1pvb21TYW1lQXNJbWdTaXplKHJlY3Q6IFJlY3RhbmdsZSwgdHJ1ZUltZ1NpemU6IG51bWJlcltdKSB7XG4gICAgcmV0dXJuIHJlY3QueCA9PT0gdHJ1ZUltZ1NpemVbMF0gJiYgcmVjdC55ID09PSB0cnVlSW1nU2l6ZVsyXVxuICAgICAgJiYgcmVjdC53aWR0aCA9PT0gdHJ1ZUltZ1NpemVbMV0gJiYgcmVjdC5oZWlnaHQgPT09IHRydWVJbWdTaXplWzNdO1xuICB9XG5cbiAgLyoqXG4gICAqIFNhdmUgdGhlIGpzb24gc3RyaW5nIHRvIGEgZmlsZVxuICAgKiBAcGFyYW0ganNvblN0cmluZ1xuICAgKi9cbiAgcHVibGljIHNhdmVUb0ZpbGUoanNvblN0cmluZzogYW55LCBiYXNlTmFtZT86IHN0cmluZykge1xuICAgIGNvbnN0IGJsb2IgPSBuZXcgQmxvYihbanNvblN0cmluZ10sIHsgdHlwZTogJ2FwcGxpY2F0aW9uL2pzb24nIH0pO1xuICAgIGNvbnN0IHN0ZW0gPSAoYmFzZU5hbWUgPz8gJycpLnJlcGxhY2UoL1xcLlteLy5dKyQvLCAnJykudHJpbSgpIHx8ICdyb2lzJztcbiAgICBzYXZlQXMoYmxvYiwgYCR7c3RlbX0uZ2VvanNvbmApO1xuICB9XG5cbiAgLyoqXG4gICAqIEZ1bmN0aW9uIHRoYXQgaW1wb3J0cyBST0lzIGZyb20gYSBnZW9qc29uIG9iamVjdFxuICAgKiBAcGFyYW0gZ2VvSnNvblN0clxuICAgKiBAcmV0dXJuIFJlZ2lvbltdXG4gICAqL1xuICBwdWJsaWMgaW1wb3J0Uk9Jc0Zyb21HZW9Kc29uKGdlb0pzb25TdHI6IHN0cmluZyk6IFJlZ2lvbltdIHtcbiAgICBjb25zdCByZWdpb25zOiBSZWdpb25bXSA9IFtdO1xuICAgIGxldCBnZW9Kc29uOiBhbnk7XG4gICAgdHJ5IHtcbiAgICAgIGdlb0pzb24gPSBKU09OLnBhcnNlKGdlb0pzb25TdHIpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Vycm9yIHBhcnNpbmcganNvbiBzdHJpbmc6ICcgKyBlcnJvcik7XG4gICAgfVxuICAgIGlmICghZ2VvSnNvbi5mZWF0dXJlcykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIEdlb0pzb24gZmlsZTogbXVzdCBjb250YWluIHRoZSBcXCdmZWF0dXJlc1xcJyBrZXkuJyk7XG4gICAgfVxuICAgIGxldCBpZHggPSAwO1xuICAgIGZvciAoY29uc3QgZmVhdHVyZSBvZiBnZW9Kc29uLmZlYXR1cmVzKSB7XG4gICAgICBjb25zdCByZWdpb24gPSBuZXcgUmVnaW9uKCk7XG4gICAgICByZWdpb24ubmFtZSA9IGBzaGFwZSR7aWR4fWA7XG4gICAgICBpZHgrKztcbiAgICAgIC8vIFF1UGF0aCBzdG9yZXMgdGhlIGltYWdlIHBsYW5lIElOU0lERSB0aGUgZ2VvbWV0cnkgKGEgc2libGluZyBvZlxuICAgICAgLy8gdHlwZS9jb29yZGluYXRlcyksIG5vdCBpbiBwcm9wZXJ0aWVzOiBgZ2VvbWV0cnkucGxhbmUgPSB7Yyx6LHR9YCwgYWxsXG4gICAgICAvLyB6ZXJvLWJhc2VkLCBhbmQgdGhlIGtleSBpcyBvbWl0dGVkIGZvciB0aGUgZGVmYXVsdCBwbGFuZSAoej0wLHQ9MCkuIEFcbiAgICAgIC8vIG1pc3NpbmcgcGxhbmUgdGhlcmVmb3JlIHJlYWRzIGJhY2sgYXMgej0wIChqaXQtdWkjOTMpLlxuICAgICAgcmVnaW9uLnogPSBmZWF0dXJlLmdlb21ldHJ5Py5wbGFuZT8ueiA/PyAwO1xuICAgICAgaWYgKCFmZWF0dXJlLnByb3BlcnRpZXMgfHwgIWZlYXR1cmUucHJvcGVydGllcy5jbGFzc2lmaWNhdGlvbikge1xuICAgICAgICAvLyBObyBjbGFzc2lmaWNhdGlvbiBtZXRhZGF0YSDigJQgdXNlIGEgZGVmYXVsdCBsYWJlbCBhbmQgY29sb3IuXG4gICAgICAgIHJlZ2lvbi5sYWJlbCA9ICdDZWxsJztcbiAgICAgIH0gZWxzZSBpZiAoIWZlYXR1cmUucHJvcGVydGllcy5jbGFzc2lmaWNhdGlvbi5uYW1lKSB7XG4gICAgICAgIC8vIGFzc3VtZSBjbGFzc2lmaWNhdGlvbiBpcyBhIHN0cmluZ1xuICAgICAgICByZWdpb24ubGFiZWwgPSBmZWF0dXJlLnByb3BlcnRpZXMuY2xhc3NpZmljYXRpb247XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBpZiBjbGFzc2lmaWNhdGlvbiBpcyBhbiBvYmplY3Qgd2l0aCBhIG5hbWUgLyBjaGVjayBjb2xvciBhcyB3ZWxsXG4gICAgICAgIHJlZ2lvbi5sYWJlbCA9IGZlYXR1cmUucHJvcGVydGllcy5jbGFzc2lmaWNhdGlvbi5uYW1lO1xuICAgICAgICBpZiAoZmVhdHVyZS5wcm9wZXJ0aWVzLmNsYXNzaWZpY2F0aW9uLmNvbG9yKSB7XG4gICAgICAgICAgcmVnaW9uLmNvbG9yID0gdGhpcy5yZ2JUb0hleChcbiAgICAgICAgICAgIGZlYXR1cmUucHJvcGVydGllcy5jbGFzc2lmaWNhdGlvbi5jb2xvclswXSxcbiAgICAgICAgICAgIGZlYXR1cmUucHJvcGVydGllcy5jbGFzc2lmaWNhdGlvbi5jb2xvclsxXSxcbiAgICAgICAgICAgIGZlYXR1cmUucHJvcGVydGllcy5jbGFzc2lmaWNhdGlvbi5jb2xvclsyXVxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gSklUIGJlemllciByZWdpb246IHRoZSBlZGl0YWJsZSBhbmNob3JzICsgZmxhZyB0cmF2ZWwgaW4gcHJvcGVydGllc1xuICAgICAgLy8gKHRoZSBnZW9tZXRyeSBob2xkcyB0aGUgZmxhdHRlbmVkIGN1cnZlIGZvciB2aWV3ZXJzIHdpdGhvdXQgYmV6aWVyXG4gICAgICAvLyBzdXBwb3J0KS4gUmVjb25zdHJ1Y3QgdGhlIGVkaXRhYmxlIGJlemllciBmcm9tIHRoZSBhbmNob3JzLlxuICAgICAgaWYgKGZlYXR1cmUucHJvcGVydGllcyAmJiBmZWF0dXJlLnByb3BlcnRpZXMuaXNCZXppZXIgJiYgZmVhdHVyZS5wcm9wZXJ0aWVzLmJlemllckFuY2hvcnMpIHtcbiAgICAgICAgY29uc3QgYW5jaG9yczogbnVtYmVyW11bXSA9IGZlYXR1cmUucHJvcGVydGllcy5iZXppZXJBbmNob3JzO1xuICAgICAgICBjb25zdCBwb2x5Z29uID0gbmV3IFBvbHlnb24oKTtcbiAgICAgICAgcG9seWdvbi5iZXppZXIgPSB0cnVlO1xuICAgICAgICBwb2x5Z29uLmNsb3NlZCA9IGZlYXR1cmUuZ2VvbWV0cnk/LnR5cGUgIT09ICdMaW5lU3RyaW5nJztcbiAgICAgICAgcG9seWdvbi5ucG9pbnRzID0gYW5jaG9ycy5sZW5ndGg7XG4gICAgICAgIHBvbHlnb24ueHBvaW50cyA9IGFuY2hvcnMubWFwKGEgPT4gYVswXSk7XG4gICAgICAgIHBvbHlnb24ueXBvaW50cyA9IGFuY2hvcnMubWFwKGEgPT4gYVsxXSk7XG4gICAgICAgIHBvbHlnb24uY29vcmRpbmF0ZXMgPSBhbmNob3JzLm1hcChhID0+IFthWzBdLCBhWzFdXSk7XG4gICAgICAgIC8vIFJlc3RvcmUgdGhlIGVkaXRlZCBjb250cm9sIGhhbmRsZXMgd2hlbiBwcmVzZW50IChlbHNlIHRoZXknbGwgZmFsbCBiYWNrXG4gICAgICAgIC8vIHRvIHRoZSBzbW9vdGggQ2F0bXVsbC1Sb20gZGVmYXVsdCBhdCByZW5kZXIgdGltZSkuXG4gICAgICAgIGlmIChmZWF0dXJlLnByb3BlcnRpZXMuYmV6aWVySGFuZGxlc0luKSBwb2x5Z29uLmhhbmRsZXNJbiA9IGZlYXR1cmUucHJvcGVydGllcy5iZXppZXJIYW5kbGVzSW47XG4gICAgICAgIGlmIChmZWF0dXJlLnByb3BlcnRpZXMuYmV6aWVySGFuZGxlc091dCkgcG9seWdvbi5oYW5kbGVzT3V0ID0gZmVhdHVyZS5wcm9wZXJ0aWVzLmJlemllckhhbmRsZXNPdXQ7XG4gICAgICAgIC8vIFJlc3RvcmUgZG9udXQgaG9sZXMgKyB0aGVpciBlZGl0YWJsZSBiZXppZXIgaGFuZGxlcyAoaml0LXVpIzEwMikuXG4gICAgICAgIGlmIChmZWF0dXJlLnByb3BlcnRpZXMuaG9sZXMpIHBvbHlnb24uaG9sZXMgPSBmZWF0dXJlLnByb3BlcnRpZXMuaG9sZXM7XG4gICAgICAgIGlmIChmZWF0dXJlLnByb3BlcnRpZXMuaG9sZUhhbmRsZXNJbikgcG9seWdvbi5ob2xlSGFuZGxlc0luID0gZmVhdHVyZS5wcm9wZXJ0aWVzLmhvbGVIYW5kbGVzSW47XG4gICAgICAgIGlmIChmZWF0dXJlLnByb3BlcnRpZXMuaG9sZUhhbmRsZXNPdXQpIHBvbHlnb24uaG9sZUhhbmRsZXNPdXQgPSBmZWF0dXJlLnByb3BlcnRpZXMuaG9sZUhhbmRsZXNPdXQ7XG4gICAgICAgIHJlZ2lvbi5ib3VuZHMgPSBwb2x5Z29uO1xuICAgICAgICByZWdpb25zLnB1c2gocmVnaW9uKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGNvb3JkaW5hdGVzID0gZmVhdHVyZS5nZW9tZXRyeS5jb29yZGluYXRlcztcbiAgICAgIGlmICghY29vcmRpbmF0ZXMpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIEdlb0pzb24gZmlsZTogbXVzdCBjb250YWluIHRoZSBcXCdjb29yZGluYXRlc1xcJyBrZXkuJyk7XG4gICAgICB9XG4gICAgICAvLyBNdWx0aS1wYXJ0IHJlZ2lvbjogR2VvSlNPTiBNdWx0aVBvbHlnb24g4oaSIG9uZSBQb2x5Z29uIHBlciBwYXJ0LCBlYWNoXG4gICAgICAvLyB3aXRoIGl0cyBvd24gaG9sZXMgKGppdC11aSM4NSkuXG4gICAgICBpZiAoZmVhdHVyZS5nZW9tZXRyeS50eXBlID09PSAnTXVsdGlQb2x5Z29uJykge1xuICAgICAgICBjb25zdCBtcCA9IG5ldyBNdWx0aVBvbHlnb24oKTtcbiAgICAgICAgbXAucG9seWdvbnMgPSAoY29vcmRpbmF0ZXMgYXMgbnVtYmVyW11bXVtdW10pXG4gICAgICAgICAgLm1hcChyaW5ncyA9PiB0aGlzLnBvbHlnb25Gcm9tUmluZ3MocmluZ3MpKVxuICAgICAgICAgIC5maWx0ZXIocCA9PiBwLnhwb2ludHMubGVuZ3RoID49IDMpO1xuICAgICAgICByZWdpb24uYm91bmRzID0gbXA7XG4gICAgICAgIHJlZ2lvbnMucHVzaChyZWdpb24pO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIC8vIE9wZW4gcG9seWxpbmU6IExpbmVTdHJpbmcgZ2VvbWV0cnlcbiAgICAgIGlmIChmZWF0dXJlLmdlb21ldHJ5LnR5cGUgPT09ICdMaW5lU3RyaW5nJykge1xuICAgICAgICBjb25zdCBwb2x5Z29uID0gbmV3IFBvbHlnb24oKTtcbiAgICAgICAgcG9seWdvbi5jbG9zZWQgPSBmYWxzZTtcbiAgICAgICAgcG9seWdvbi5ucG9pbnRzID0gY29vcmRpbmF0ZXMubGVuZ3RoO1xuICAgICAgICBwb2x5Z29uLnhwb2ludHMgPSBbXTtcbiAgICAgICAgcG9seWdvbi55cG9pbnRzID0gW107XG4gICAgICAgIHBvbHlnb24uY29vcmRpbmF0ZXMgPSBbXTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb29yZGluYXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIHBvbHlnb24ueHBvaW50cy5wdXNoKGNvb3JkaW5hdGVzW2ldWzBdKTtcbiAgICAgICAgICBwb2x5Z29uLnlwb2ludHMucHVzaChjb29yZGluYXRlc1tpXVsxXSk7XG4gICAgICAgICAgcG9seWdvbi5jb29yZGluYXRlcy5wdXNoKFtjb29yZGluYXRlc1tpXVswXSwgY29vcmRpbmF0ZXNbaV1bMV1dKTtcbiAgICAgICAgfVxuICAgICAgICByZWdpb24uYm91bmRzID0gcG9seWdvbjtcbiAgICAgIC8vIFBvbHlnb246IGNoZWNrIGlmIGl0IGVuY29kZXMgYSByZWN0YW5nbGUgKHNpbmdsZSByaW5nIG9ubHkg4oCUIGEgcG9seWdvblxuICAgICAgLy8gd2l0aCBob2xlcyBtdXN0IG5ldmVyIGJlIGNvbGxhcHNlZCB0byBhIHJlY3RhbmdsZSkuXG4gICAgICB9IGVsc2UgaWYgKGNvb3JkaW5hdGVzLmxlbmd0aCA9PT0gMVxuICAgICAgICAmJiBjb29yZGluYXRlc1swXS5sZW5ndGggPT09IDVcbiAgICAgICAgJiYgSlNPTi5zdHJpbmdpZnkoY29vcmRpbmF0ZXNbMF1bMF0pID09PSBKU09OLnN0cmluZ2lmeShjb29yZGluYXRlc1swXVs0XSlcbiAgICAgICAgJiYgY29vcmRpbmF0ZXNbMF1bMF1bMF0gPT09IGNvb3JkaW5hdGVzWzBdWzNdWzBdXG4gICAgICAgICYmIGNvb3JkaW5hdGVzWzBdWzBdWzFdID09PSBjb29yZGluYXRlc1swXVsxXVsxXVxuICAgICAgICAmJiBjb29yZGluYXRlc1swXVsxXVswXSA9PT0gY29vcmRpbmF0ZXNbMF1bMl1bMF1cbiAgICAgICAgJiYgY29vcmRpbmF0ZXNbMF1bMl1bMV0gPT09IGNvb3JkaW5hdGVzWzBdWzNdWzFdKSB7XG4gICAgICAgIGNvbnN0IHJlY3RhbmdsZSA9IG5ldyBSZWN0YW5nbGUoKTtcbiAgICAgICAgcmVjdGFuZ2xlLnggPSBjb29yZGluYXRlc1swXVswXVswXTtcbiAgICAgICAgcmVjdGFuZ2xlLnkgPSBjb29yZGluYXRlc1swXVswXVsxXTtcbiAgICAgICAgcmVjdGFuZ2xlLndpZHRoID0gY29vcmRpbmF0ZXNbMF1bMl1bMF0gLSBjb29yZGluYXRlc1swXVswXVswXTtcbiAgICAgICAgcmVjdGFuZ2xlLmhlaWdodCA9IGNvb3JkaW5hdGVzWzBdWzJdWzFdIC0gY29vcmRpbmF0ZXNbMF1bMF1bMV07XG4gICAgICAgIHJlZ2lvbi5ib3VuZHMgPSByZWN0YW5nbGU7XG5cbiAgICAgIH0gZWxzZSB7IC8vIHBvbHlnb24gaXMgYSBmcmVlZm9ybSBjbG9zZWQgcG9seWdvblxuICAgICAgICBjb25zdCBwb2x5Z29uID0gbmV3IFBvbHlnb24oKTtcbiAgICAgICAgcG9seWdvbi5ucG9pbnRzID0gY29vcmRpbmF0ZXNbMF0ubGVuZ3RoIC0gMTtcbiAgICAgICAgcG9seWdvbi54cG9pbnRzID0gW107XG4gICAgICAgIHBvbHlnb24ueXBvaW50cyA9IFtdO1xuICAgICAgICBwb2x5Z29uLmNvb3JkaW5hdGVzID0gW107XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY29vcmRpbmF0ZXNbMF0ubGVuZ3RoIC0gMTsgaSsrKSB7XG4gICAgICAgICAgcG9seWdvbi54cG9pbnRzLnB1c2goY29vcmRpbmF0ZXNbMF1baV1bMF0pO1xuICAgICAgICAgIHBvbHlnb24ueXBvaW50cy5wdXNoKGNvb3JkaW5hdGVzWzBdW2ldWzFdKTtcbiAgICAgICAgICBwb2x5Z29uLmNvb3JkaW5hdGVzLnB1c2goW2Nvb3JkaW5hdGVzWzBdW2ldWzBdLCBjb29yZGluYXRlc1swXVtpXVsxXV0pO1xuICAgICAgICB9XG4gICAgICAgIC8vIEV4dHJhIHJpbmdzIGFyZSBpbnRlcmlvciBob2xlcyAoR2VvSlNPTiBQb2x5Z29uIGNvbnZlbnRpb24pIOKAlCBqaXQtdWkjODUuXG4gICAgICAgIGNvbnN0IGhvbGVzID0gdGhpcy5yaW5nc1RvSG9sZXMoY29vcmRpbmF0ZXMuc2xpY2UoMSkpO1xuICAgICAgICBpZiAoaG9sZXMubGVuZ3RoKSBwb2x5Z29uLmhvbGVzID0gaG9sZXM7XG4gICAgICAgIHJlZ2lvbi5ib3VuZHMgPSBwb2x5Z29uO1xuICAgICAgfVxuICAgICAgcmVnaW9ucy5wdXNoKHJlZ2lvbik7XG4gICAgfVxuICAgIHJldHVybiByZWdpb25zO1xuICB9XG5cbiAgLyoqXG4gICAqIEZ1bmN0aW9uIHRoYXQgcmV0dXJucyBhIGdlb2pzb24gb2JqZWN0IGZyb20gYSBQbG90bHkgUk9JXG4gICAqIEBwYXJhbSByb2lzXG4gICAqIEByZXR1cm4gRmVhdHVyZUNvbGxlY3Rpb248R2VvbWV0cnksIEdlb0pzb25Qcm9wZXJ0aWVzPlxuICAgKi9cbiAgcHVibGljIGV4cG9ydFJPSXNUb0dlb0pzb24ocm9pczogUmVnaW9uW10pOiBzdHJpbmcge1xuICAgIGNvbnNvbGUubG9nKCdFeHBvcnRpbmcgUk9JcyB0byBHZW9Kc29uJyk7XG4gICAgY29uc29sZS5sb2cocm9pcyk7XG4gICAgY29uc3QgZmVhdHVyZXM6IGFueVtdID0gW107XG4gICAgZm9yIChjb25zdCByb2kgb2Ygcm9pcy5maWx0ZXIociA9PiAociBhcyBhbnkpLmtpbmQgIT09ICdwcm9maWxlJykpIHtcbiAgICAgIC8vIFF1UGF0aCBwbGFjZXMgdGhlIGltYWdlIHBsYW5lIGluc2lkZSB0aGUgZ2VvbWV0cnkgKHNpYmxpbmcgb2ZcbiAgICAgIC8vIHR5cGUvY29vcmRpbmF0ZXMpLCB6ZXJvLWJhc2VkLCBhbmQgb21pdHMgaXQgZm9yIHRoZSBkZWZhdWx0IHBsYW5lXG4gICAgICAvLyAoej0wLHQ9MCkuIEVtaXQgYHBsYW5lOiB7Yyx6LHR9YCBvbmx5IGZvciBhIG5vbi1kZWZhdWx0IHNsaWNlIHNvIGFcbiAgICAgIC8vIHNpbmdsZS1wbGFuZSBpbWFnZSByb3VuZC10cmlwcyBieXRlLWlkZW50aWNhbGx5IHRvIFF1UGF0aCAoaml0LXVpIzkzKS5cbiAgICAgIGNvbnN0IHBsYW5lUHJvcCA9IChyb2kueiA/PyAwKSAhPT0gMCA/IHsgcGxhbmU6IHsgYzogLTEsIHo6IHJvaS56LCB0OiAwIH0gfSA6IHt9O1xuICAgICAgaWYgKHJvaS5ib3VuZHMgaW5zdGFuY2VvZiBSZWN0YW5nbGUpIHtcbiAgICAgICAgY29uc3QgcmVjdGFuZ2xlID0ge1xuICAgICAgICAgIHR5cGU6ICdGZWF0dXJlJyxcbiAgICAgICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgICBjbGFzc2lmaWNhdGlvbjoge1xuICAgICAgICAgICAgICBuYW1lOiByb2kubGFiZWwgPyByb2kubGFiZWwgOiByb2kubmFtZSxcbiAgICAgICAgICAgICAgY29sb3I6IFtcbiAgICAgICAgICAgICAgICB0aGlzLmhleFRvUmdiKHJvaT8uY29sb3IpWzBdLFxuICAgICAgICAgICAgICAgIHRoaXMuaGV4VG9SZ2Iocm9pPy5jb2xvcilbMV0sXG4gICAgICAgICAgICAgICAgdGhpcy5oZXhUb1JnYihyb2k/LmNvbG9yKVsyXVxuICAgICAgICAgICAgICBdXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAgZ2VvbWV0cnk6IHtcbiAgICAgICAgICAgIHR5cGU6ICdQb2x5Z29uJyxcbiAgICAgICAgICAgIGNvb3JkaW5hdGVzOiBbW1xuICAgICAgICAgICAgICBbcm9pLmJvdW5kcy54LCByb2kuYm91bmRzLnldLFxuICAgICAgICAgICAgICBbcm9pLmJvdW5kcy54ICsgcm9pLmJvdW5kcy53aWR0aCwgcm9pLmJvdW5kcy55XSxcbiAgICAgICAgICAgICAgW3JvaS5ib3VuZHMueCArIHJvaS5ib3VuZHMud2lkdGgsIHJvaS5ib3VuZHMueSArIHJvaS5ib3VuZHMuaGVpZ2h0XSxcbiAgICAgICAgICAgICAgW3JvaS5ib3VuZHMueCwgcm9pLmJvdW5kcy55ICsgcm9pLmJvdW5kcy5oZWlnaHRdLFxuICAgICAgICAgICAgICBbcm9pLmJvdW5kcy54LCByb2kuYm91bmRzLnldXG4gICAgICAgICAgICBdXSxcbiAgICAgICAgICAgIC4uLnBsYW5lUHJvcFxuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgZmVhdHVyZXMucHVzaChyZWN0YW5nbGUpO1xuICAgICAgfSBlbHNlIGlmIChyb2kuYm91bmRzIGluc3RhbmNlb2YgUG9seWdvbikge1xuICAgICAgICBjb25zdCBjb2xvclJnYiA9IFtcbiAgICAgICAgICB0aGlzLmhleFRvUmdiKHJvaT8uY29sb3IpWzBdLFxuICAgICAgICAgIHRoaXMuaGV4VG9SZ2Iocm9pPy5jb2xvcilbMV0sXG4gICAgICAgICAgdGhpcy5oZXhUb1JnYihyb2k/LmNvbG9yKVsyXVxuICAgICAgICBdO1xuICAgICAgICBjb25zdCBjbG9zZWQgPSByb2kuYm91bmRzLmNsb3NlZCAhPT0gZmFsc2U7XG4gICAgICAgIGNvbnN0IGlzQmV6aWVyID0gcm9pLmJvdW5kcy5iZXppZXIgPT09IHRydWU7XG4gICAgICAgIC8vIEZvciBhIGJlemllciByZWdpb24gdGhlIGdlb21ldHJ5IGlzIHRoZSBmbGF0dGVuZWQgc21vb3RoIGN1cnZlLFxuICAgICAgICAvLyBzbyBhIHZpZXdlciB3aXRob3V0IGJlemllciBzdXBwb3J0IChRdVBhdGgpIHN0aWxsIHJlbmRlcnMgdGhlIGN1cnZlO1xuICAgICAgICAvLyB0aGUgZWRpdGFibGUgYW5jaG9ycyArIGZsYWcgcmlkZSBhbG9uZyBpbiBwcm9wZXJ0aWVzIGZvciBKSVQuXG4gICAgICAgIGNvbnN0IGdlb21Db29yZHMgPSBpc0JlemllclxuICAgICAgICAgID8gKCgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGhhbmRsZXMgPSByZXNvbHZlSGFuZGxlcyhyb2kuYm91bmRzLnhwb2ludHMsIHJvaS5ib3VuZHMueXBvaW50cywgY2xvc2VkLFxuICAgICAgICAgICAgICByb2kuYm91bmRzLmhhbmRsZXNJbiwgcm9pLmJvdW5kcy5oYW5kbGVzT3V0KTtcbiAgICAgICAgICAgIGNvbnN0IGMgPSBiZXppZXJDdXJ2ZUZyb21IYW5kbGVzKHJvaS5ib3VuZHMueHBvaW50cywgcm9pLmJvdW5kcy55cG9pbnRzLCBoYW5kbGVzLCBjbG9zZWQpO1xuICAgICAgICAgICAgcmV0dXJuIGMueHMubWFwKCh4LCBpKSA9PiBbeCwgYy55c1tpXV0pO1xuICAgICAgICAgIH0pKClcbiAgICAgICAgICA6IHJvaS5ib3VuZHMuY29vcmRpbmF0ZXM7XG4gICAgICAgIGNvbnN0IHByb3BlcnRpZXM6IGFueSA9IHtcbiAgICAgICAgICBjbGFzc2lmaWNhdGlvbjoge1xuICAgICAgICAgICAgbmFtZTogcm9pLmxhYmVsID8gcm9pLmxhYmVsIDogcm9pLm5hbWUsXG4gICAgICAgICAgICBjb2xvcjogY29sb3JSZ2JcbiAgICAgICAgICB9LFxuICAgICAgICB9O1xuICAgICAgICBpZiAoaXNCZXppZXIpIHtcbiAgICAgICAgICBwcm9wZXJ0aWVzLmlzQmV6aWVyID0gdHJ1ZTtcbiAgICAgICAgICBwcm9wZXJ0aWVzLmJlemllckFuY2hvcnMgPSByb2kuYm91bmRzLmNvb3JkaW5hdGVzO1xuICAgICAgICAgIC8vIFRoZSBlZGl0YWJsZSBjb250cm9sIGhhbmRsZXMgKHJlbGF0aXZlIG9mZnNldHMpIHRyYXZlbCBhbG9uZyBzbyBKSVRcbiAgICAgICAgICAvLyByb3VuZC10cmlwcyBhIGhhbmQtZWRpdGVkIGN1cnZlLCBub3QganVzdCB0aGUgc21vb3RoIGRlZmF1bHQuXG4gICAgICAgICAgaWYgKHJvaS5ib3VuZHMuaGFuZGxlc0luKSBwcm9wZXJ0aWVzLmJlemllckhhbmRsZXNJbiA9IHJvaS5ib3VuZHMuaGFuZGxlc0luO1xuICAgICAgICAgIGlmIChyb2kuYm91bmRzLmhhbmRsZXNPdXQpIHByb3BlcnRpZXMuYmV6aWVySGFuZGxlc091dCA9IHJvaS5ib3VuZHMuaGFuZGxlc091dDtcbiAgICAgICAgICAvLyBEb251dCBiZXppZXI6IHRoZSBob2xlIGFuY2hvcnMgKyB0aGVpciBlZGl0YWJsZSBoYW5kbGVzIHJvdW5kLXRyaXAgdG9vIChqaXQtdWkjMTAyKS5cbiAgICAgICAgICBpZiAocm9pLmJvdW5kcy5ob2xlcykgcHJvcGVydGllcy5ob2xlcyA9IHJvaS5ib3VuZHMuaG9sZXM7XG4gICAgICAgICAgaWYgKHJvaS5ib3VuZHMuaG9sZUhhbmRsZXNJbikgcHJvcGVydGllcy5ob2xlSGFuZGxlc0luID0gcm9pLmJvdW5kcy5ob2xlSGFuZGxlc0luO1xuICAgICAgICAgIGlmIChyb2kuYm91bmRzLmhvbGVIYW5kbGVzT3V0KSBwcm9wZXJ0aWVzLmhvbGVIYW5kbGVzT3V0ID0gcm9pLmJvdW5kcy5ob2xlSGFuZGxlc091dDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY2xvc2VkKSB7XG4gICAgICAgICAgLy8gQ2xvc2UgdGhlIHJpbmcuIFRoZSBmbGF0dGVuZWQgYmV6aWVyIGN1cnZlIGFscmVhZHkgcmV0dXJucyB0byBpdHNcbiAgICAgICAgICAvLyBzdGFydCwgc28gb25seSB0aGUgc3RyYWlnaHQtcG9seWdvbiBwYXRoIG5lZWRzIHRoZSBmaXJzdCBwb2ludFxuICAgICAgICAgIC8vIHJlcGVhdGVkLlxuICAgICAgICAgIGNvbnN0IHJpbmcgPSBpc0JlemllciA/IGdlb21Db29yZHMgOiBbLi4uZ2VvbUNvb3JkcywgZ2VvbUNvb3Jkc1swXV07XG4gICAgICAgICAgLy8gSW50ZXJpb3IgcmluZ3MgKGhvbGVzKSBmb2xsb3cgdGhlIGV4dGVyaW9yIGFzIGV4dHJhIEdlb0pTT04gcmluZ3Mg4oCUXG4gICAgICAgICAgLy8gc3RhbmRhcmQgUG9seWdvbi13aXRoLWhvbGVzLCB3aGljaCBRdVBhdGggcm91bmQtdHJpcHMgKGppdC11aSM4NSkuIEZvciBhIGJlemllciBkb251dCxcbiAgICAgICAgICAvLyB0aGUgaG9sZSBnZW9tZXRyeSBpcyB0aGUgZmxhdHRlbmVkIHNtb290aCBjdXJ2ZSB0b28gKGppdC11aSMxMDIpLlxuICAgICAgICAgIGNvbnN0IHJpbmdzOiBudW1iZXJbXVtdW10gPSBbcmluZ107XG4gICAgICAgICAgaWYgKHJvaS5ib3VuZHMuaG9sZXMpIHtcbiAgICAgICAgICAgIHJvaS5ib3VuZHMuaG9sZXMuZm9yRWFjaCgoaG9sZSwgaGkpID0+IHtcbiAgICAgICAgICAgICAgaWYgKGhvbGUubGVuZ3RoIDwgMykgcmV0dXJuO1xuICAgICAgICAgICAgICBpZiAoaXNCZXppZXIpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBoeHMgPSBob2xlLm1hcCgocCkgPT4gcFswXSk7XG4gICAgICAgICAgICAgICAgY29uc3QgaHlzID0gaG9sZS5tYXAoKHApID0+IHBbMV0pO1xuICAgICAgICAgICAgICAgIGNvbnN0IGhoID0gcmVzb2x2ZUhhbmRsZXMoXG4gICAgICAgICAgICAgICAgICBoeHMsIGh5cywgdHJ1ZSxcbiAgICAgICAgICAgICAgICAgIChyb2kuYm91bmRzIGFzIFBvbHlnb24pLmhvbGVIYW5kbGVzSW4/LltoaV0sXG4gICAgICAgICAgICAgICAgICAocm9pLmJvdW5kcyBhcyBQb2x5Z29uKS5ob2xlSGFuZGxlc091dD8uW2hpXSxcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIGNvbnN0IGMgPSBiZXppZXJDdXJ2ZUZyb21IYW5kbGVzKGh4cywgaHlzLCBoaCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgcmluZ3MucHVzaChjLnhzLm1hcCgoeCwgaSkgPT4gW3gsIGMueXNbaV1dKSk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmluZ3MucHVzaChbLi4uaG9sZSwgaG9sZVswXV0pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZmVhdHVyZXMucHVzaCh7XG4gICAgICAgICAgICB0eXBlOiAnRmVhdHVyZScsXG4gICAgICAgICAgICBwcm9wZXJ0aWVzLFxuICAgICAgICAgICAgZ2VvbWV0cnk6IHsgdHlwZTogJ1BvbHlnb24nLCBjb29yZGluYXRlczogcmluZ3MsIC4uLnBsYW5lUHJvcCB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZmVhdHVyZXMucHVzaCh7XG4gICAgICAgICAgICB0eXBlOiAnRmVhdHVyZScsXG4gICAgICAgICAgICBwcm9wZXJ0aWVzLFxuICAgICAgICAgICAgZ2VvbWV0cnk6IHsgdHlwZTogJ0xpbmVTdHJpbmcnLCBjb29yZGluYXRlczogZ2VvbUNvb3JkcywgLi4ucGxhbmVQcm9wIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChyb2kuYm91bmRzIGluc3RhbmNlb2YgTXVsdGlQb2x5Z29uKSB7XG4gICAgICAgIC8vIE11bHRpLXBhcnQgcmVnaW9uIOKGkiBHZW9KU09OIE11bHRpUG9seWdvbjogb25lIHJpbmctc2V0IHBlciBwYXJ0XG4gICAgICAgIC8vIChleHRlcmlvciArIGhvbGVzKSwgZWFjaCByaW5nIGNsb3NlZCAoaml0LXVpIzg1KS5cbiAgICAgICAgY29uc3QgY29sb3JSZ2IgPSBbXG4gICAgICAgICAgdGhpcy5oZXhUb1JnYihyb2k/LmNvbG9yKVswXSxcbiAgICAgICAgICB0aGlzLmhleFRvUmdiKHJvaT8uY29sb3IpWzFdLFxuICAgICAgICAgIHRoaXMuaGV4VG9SZ2Iocm9pPy5jb2xvcilbMl1cbiAgICAgICAgXTtcbiAgICAgICAgY29uc3QgY29vcmRpbmF0ZXMgPSByb2kuYm91bmRzLnBvbHlnb25zXG4gICAgICAgICAgLmZpbHRlcihwYXJ0ID0+IHBhcnQueHBvaW50cy5sZW5ndGggPj0gMylcbiAgICAgICAgICAubWFwKHBhcnQgPT4ge1xuICAgICAgICAgICAgY29uc3QgZXh0ID0gcGFydC54cG9pbnRzLm1hcCgoeCwgaSkgPT4gW3gsIHBhcnQueXBvaW50c1tpXV0pO1xuICAgICAgICAgICAgY29uc3QgcmluZ3M6IG51bWJlcltdW11bXSA9IFtbLi4uZXh0LCBleHRbMF1dXTtcbiAgICAgICAgICAgIGlmIChwYXJ0LmhvbGVzKSB7XG4gICAgICAgICAgICAgIGZvciAoY29uc3QgaG9sZSBvZiBwYXJ0LmhvbGVzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGhvbGUubGVuZ3RoID49IDMpIHJpbmdzLnB1c2goWy4uLmhvbGUsIGhvbGVbMF1dKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJpbmdzO1xuICAgICAgICAgIH0pO1xuICAgICAgICBmZWF0dXJlcy5wdXNoKHtcbiAgICAgICAgICB0eXBlOiAnRmVhdHVyZScsXG4gICAgICAgICAgcHJvcGVydGllczogeyBjbGFzc2lmaWNhdGlvbjogeyBuYW1lOiByb2kubGFiZWwgPyByb2kubGFiZWwgOiByb2kubmFtZSwgY29sb3I6IGNvbG9yUmdiIH0gfSxcbiAgICAgICAgICBnZW9tZXRyeTogeyB0eXBlOiAnTXVsdGlQb2x5Z29uJywgY29vcmRpbmF0ZXMsIC4uLnBsYW5lUHJvcCB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgICBjb25zdCBnZW9Kc29uRGF0YSA9IHtcbiAgICAgIGZlYXR1cmVzOiBmZWF0dXJlcyxcbiAgICAgIHR5cGU6ICdGZWF0dXJlQ29sbGVjdGlvbidcbiAgICB9O1xuXG4gICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KGdlb0pzb25EYXRhKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0IEdlb0pTT04gaW50ZXJpb3IgcmluZ3MgaW50byB0aGUgbmV1dHJhbCBob2xlIHJlcHJlc2VudGF0aW9uXG4gICAqIChgbnVtYmVyW11bXWAgcGVyIHJpbmcsIG5vIHJlcGVhdGVkIGNsb3NpbmcgcG9pbnQpLiBEZWdlbmVyYXRlIHJpbmdzICg8IDNcbiAgICogZGlzdGluY3QgcG9pbnRzKSBhcmUgZHJvcHBlZC4gaml0LXVpIzg1LlxuICAgKi9cbiAgLyoqXG4gICAqIEJ1aWxkIGEgY2xvc2VkIHtAbGluayBQb2x5Z29ufSBmcm9tIGEgR2VvSlNPTiByaW5nIHNldDogYHJpbmdzWzBdYCBpcyB0aGVcbiAgICogZXh0ZXJpb3IgKGNsb3NpbmcgcG9pbnQgZHJvcHBlZCksIGByaW5nc1sxLi5dYCBhcmUgaW50ZXJpb3IgaG9sZXMuIGppdC11aSM4NS5cbiAgICovXG4gIHByaXZhdGUgcG9seWdvbkZyb21SaW5ncyhyaW5nczogbnVtYmVyW11bXVtdKTogUG9seWdvbiB7XG4gICAgY29uc3QgcG9seSA9IG5ldyBQb2x5Z29uKCk7XG4gICAgY29uc3QgZXh0ID0gcmluZ3M/LlswXSA/PyBbXTtcbiAgICBjb25zdCBsYXN0ID0gZXh0Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgY2xvc2VkID0gZXh0Lmxlbmd0aCA+IDEgJiYgZXh0WzBdWzBdID09PSBleHRbbGFzdF1bMF0gJiYgZXh0WzBdWzFdID09PSBleHRbbGFzdF1bMV07XG4gICAgY29uc3QgbiA9IGNsb3NlZCA/IGxhc3QgOiBleHQubGVuZ3RoO1xuICAgIHBvbHkueHBvaW50cyA9IFtdOyBwb2x5Lnlwb2ludHMgPSBbXTsgcG9seS5jb29yZGluYXRlcyA9IFtdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgICBwb2x5Lnhwb2ludHMucHVzaChleHRbaV1bMF0pO1xuICAgICAgcG9seS55cG9pbnRzLnB1c2goZXh0W2ldWzFdKTtcbiAgICAgIHBvbHkuY29vcmRpbmF0ZXMucHVzaChbZXh0W2ldWzBdLCBleHRbaV1bMV1dKTtcbiAgICB9XG4gICAgcG9seS5ucG9pbnRzID0gcG9seS54cG9pbnRzLmxlbmd0aDtcbiAgICBwb2x5LmNsb3NlZCA9IHRydWU7XG4gICAgY29uc3QgaG9sZXMgPSB0aGlzLnJpbmdzVG9Ib2xlcyhyaW5ncy5zbGljZSgxKSk7XG4gICAgaWYgKGhvbGVzLmxlbmd0aCkgcG9seS5ob2xlcyA9IGhvbGVzO1xuICAgIHJldHVybiBwb2x5O1xuICB9XG5cbiAgcHJpdmF0ZSByaW5nc1RvSG9sZXMocmluZ3M6IG51bWJlcltdW11bXSk6IG51bWJlcltdW11bXSB7XG4gICAgY29uc3QgaG9sZXM6IG51bWJlcltdW11bXSA9IFtdO1xuICAgIGZvciAoY29uc3QgcmluZ0luIG9mIHJpbmdzIHx8IFtdKSB7XG4gICAgICBpZiAoIXJpbmdJbiB8fCByaW5nSW4ubGVuZ3RoIDwgMykgY29udGludWU7XG4gICAgICBjb25zdCBsYXN0ID0gcmluZ0luLmxlbmd0aCAtIDE7XG4gICAgICBjb25zdCBjbG9zZWQgPSByaW5nSW5bMF1bMF0gPT09IHJpbmdJbltsYXN0XVswXSAmJiByaW5nSW5bMF1bMV0gPT09IHJpbmdJbltsYXN0XVsxXTtcbiAgICAgIGNvbnN0IG4gPSBjbG9zZWQgPyBsYXN0IDogcmluZ0luLmxlbmd0aDtcbiAgICAgIGNvbnN0IHJpbmc6IG51bWJlcltdW10gPSBbXTtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbjsgaSsrKSByaW5nLnB1c2goW3JpbmdJbltpXVswXSwgcmluZ0luW2ldWzFdXSk7XG4gICAgICBpZiAocmluZy5sZW5ndGggPj0gMykgaG9sZXMucHVzaChyaW5nKTtcbiAgICB9XG4gICAgcmV0dXJuIGhvbGVzO1xuICB9XG5cbiAgcHVibGljIHJnYlRvSGV4KHI6IG51bWJlciwgZzogbnVtYmVyLCBiOiBudW1iZXIpOiBzdHJpbmcge1xuICAgIHJldHVybiAnIycgKyAoKDEgPDwgMjQpICsgKHIgPDwgMTYpICsgKGcgPDwgOCkgKyBiKS50b1N0cmluZygxNikuc2xpY2UoMSk7XG4gIH1cblxuICBwdWJsaWMgaGV4VG9SZ2IoaGV4OiBzdHJpbmcgfCB1bmRlZmluZWQpOiBudW1iZXJbXSB7XG4gICAgbGV0IHI6IG51bWJlciwgZzogbnVtYmVyLCBiOiBudW1iZXI7XG4gICAgaWYgKGhleCkge1xuICAgICAgY29uc3QgYmlnaW50ID0gcGFyc2VJbnQoaGV4LnNsaWNlKDEpLCAxNik7XG4gICAgICByID0gKGJpZ2ludCA+PiAxNikgJiAyNTU7XG4gICAgICBnID0gKGJpZ2ludCA+PiA4KSAmIDI1NTtcbiAgICAgIGIgPSBiaWdpbnQgJiAyNTU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHIgPSAwO1xuICAgICAgZyA9IDA7XG4gICAgICBiID0gMDtcbiAgICB9XG4gICAgcmV0dXJuIFtyLCBnLCBiXTtcbiAgfVxuXG59XG4iXX0=