@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,1237 @@
1
+ import { OSD } from './osd-lib';
2
+ import { Subscription } from 'rxjs';
3
+ import { Region, Rectangle, Polygon, MultiPolygon } from '../../models/region';
4
+ import { resolveHandles } from '../../models/bezier';
5
+ import { elementToImage, imageToElement } from './osd-coords';
6
+ const SVGNS = 'http://www.w3.org/2000/svg';
7
+ const ZONE_CURSOR = {
8
+ move: 'move', n: 'ns-resize', s: 'ns-resize', e: 'ew-resize', w: 'ew-resize',
9
+ ne: 'nesw-resize', sw: 'nesw-resize', nw: 'nwse-resize', se: 'nwse-resize',
10
+ };
11
+ /** Screen-pixel tolerance for grabbing an edge/corner handle. */
12
+ const EDIT_TOL = 8;
13
+ /** Wheel zoom step per scroll tick — mirrors the viewer's `zoomPerScroll`. */
14
+ const ZOOM_PER_SCROLL = 1.1;
15
+ /**
16
+ * OpenSeadragon implementation of {@link IRegionOverlay}.
17
+ *
18
+ * - Renders the store's regions (rect/polygon) in image-pixel space, kept
19
+ * aligned on every pan/zoom via the OSD viewport API.
20
+ * - Draws new rectangle and polygon regions (committed to the shared store).
21
+ * - Click-to-select in 'select' mode.
22
+ *
23
+ * Reads/writes the shared {@link IRegionStore}, so regions stay in sync with the
24
+ * Region Editor and the Plotly backend. The wand, vertex-eraser and zoom-to-box
25
+ * tools are NOT handled here — they're owned by OpenSeadragonVisualizerService
26
+ * (which binds them to OSD via the shared coordinate transform + viewport pixel
27
+ * readback), the same singleton tool services the Plotly backend uses.
28
+ */
29
+ export class OsdRegionOverlay {
30
+ constructor(viewer, store) {
31
+ this.viewer = viewer;
32
+ this.store = store;
33
+ this.subs = new Subscription();
34
+ this.osd = OSD;
35
+ this.selected = [];
36
+ this.mode = 'none';
37
+ this.rectStart = null; // image coords
38
+ this.rectCurrent = null;
39
+ this.polyPoints = []; // image coords
40
+ /** True while dragging a freehand path (freeform / polyline). */
41
+ this.freehandDragging = false;
42
+ /** True while placing a click-to-add polygon ('drawpolygon' mode). */
43
+ this.drawingPolygon = false;
44
+ /** Last element-pixel point appended, to thin the freehand path. */
45
+ this.lastFreehandPx = null;
46
+ /**
47
+ * In-progress edit of the selected region:
48
+ * - kind 'bounds' — rectangle resize/move or whole-region move (uses `zone`);
49
+ * - kind 'vertex' — dragging a single polygon vertex (uses `vertexIndex`).
50
+ */
51
+ this.edit = null;
52
+ this.editDragged = false;
53
+ /** Rubber-band (marquee) multi-select in 'select' mode: press on empty space
54
+ * and drag to select every region the band intersects. Image coords. */
55
+ this.bandStart = null;
56
+ this.bandCurrent = null;
57
+ this.bandDragged = false;
58
+ this.redrawHandler = () => this.redraw();
59
+ /** Drive OSD zoom from the wheel while any tool owns the pointer.
60
+ *
61
+ * OSD's native scroll-zoom is part of mouse-nav, so `setMouseNavEnabled(false)`
62
+ * (used by every region tool and by the wand/brush/eraser/SAM tools) disables
63
+ * it. The covering-canvas tools also sit above the OSD canvas and swallow the
64
+ * wheel outright. This listener is bound once to the viewer element — an
65
+ * ancestor of both the OSD canvas and the tool overlays — and forwards the
66
+ * wheel to a cursor-centred zoom whenever mouse-nav is off. When nav is on (no
67
+ * tool active) it does nothing and OSD zooms natively. (jit-ui#94) */
68
+ this.wheelZoomHandler = (e) => {
69
+ const vp = this.viewer?.viewport;
70
+ const el = this.viewer?.element;
71
+ // Nav on → no tool active → let OSD handle scroll-zoom natively.
72
+ if (!vp || !el || e.deltaY === 0 || this.viewer.isMouseNavEnabled())
73
+ return;
74
+ e.preventDefault();
75
+ const rect = el.getBoundingClientRect();
76
+ const refPoint = vp.pointFromPixel(new this.osd.Point(e.clientX - rect.left, e.clientY - rect.top));
77
+ vp.zoomBy(e.deltaY < 0 ? ZOOM_PER_SCROLL : 1 / ZOOM_PER_SCROLL, refPoint);
78
+ vp.applyConstraints();
79
+ };
80
+ this.svg = document.createElementNS(SVGNS, 'svg');
81
+ Object.assign(this.svg.style, {
82
+ position: 'absolute', left: '0', top: '0', width: '100%', height: '100%',
83
+ pointerEvents: 'none', // OSD handles navigation unless we're drawing
84
+ });
85
+ this.viewer.canvas.appendChild(this.svg);
86
+ this.viewer.addHandler('update-viewport', this.redrawHandler);
87
+ this.viewer.addHandler('animation', this.redrawHandler);
88
+ this.viewer.addHandler('resize', this.redrawHandler);
89
+ this.viewer.addHandler('rotate', this.redrawHandler);
90
+ // Keep wheel-zoom alive while a tool has mouse-nav disabled (see handler).
91
+ this.viewer.element
92
+ ?.addEventListener('wheel', this.wheelZoomHandler, { passive: false });
93
+ this.tracker = new this.osd.MouseTracker({
94
+ element: this.viewer.canvas,
95
+ pressHandler: (e) => this.onPress(e),
96
+ dragHandler: (e) => this.onDrag(e),
97
+ releaseHandler: (e) => this.onRelease(e),
98
+ clickHandler: (e) => this.onClick(e),
99
+ moveHandler: (e) => this.onMove(e),
100
+ });
101
+ this.tracker.setTracking(false);
102
+ this.subs.add(this.store.getRegionUpdateEvent().subscribe(this.redrawHandler));
103
+ this.subs.add(this.store.getSelectedShapeIndices$().subscribe(idx => {
104
+ this.selected = idx || [];
105
+ this.redraw();
106
+ }));
107
+ this.redraw();
108
+ }
109
+ /** Switch drawing/selection mode; toggles OSD navigation accordingly. */
110
+ setMode(mode) {
111
+ this.mode = mode;
112
+ this.resetInProgress();
113
+ // Any active region tool takes over the pointer — OSD pan/zoom is disabled
114
+ // so dragging draws (and clicks select) instead of panning. With no tool,
115
+ // OSD navigates normally.
116
+ this.viewer.setMouseNavEnabled(mode === 'none');
117
+ this.tracker.setTracking(mode !== 'none');
118
+ this.updateCursor(false);
119
+ this.redraw();
120
+ }
121
+ /** Cursor feedback per mode (crosshair while drawing; pointer over a region
122
+ * in select mode). */
123
+ updateCursor(overRegion) {
124
+ const canvas = this.viewer.canvas;
125
+ if (this.mode === 'drawrect' || this.mode === 'drawclosedpath' || this.mode === 'drawopenpath'
126
+ || this.mode === 'drawpolygon' || this.mode === 'addpoint' || this.mode === 'deletepoint') {
127
+ canvas.style.cursor = 'crosshair';
128
+ }
129
+ else if (this.mode === 'move') {
130
+ canvas.style.cursor = 'move';
131
+ }
132
+ else if (this.mode === 'select') {
133
+ canvas.style.cursor = overRegion ? 'pointer' : 'default';
134
+ }
135
+ else {
136
+ canvas.style.cursor = ''; // OSD default (grab)
137
+ }
138
+ }
139
+ /** Whether the selected region's vertices/handles should be drawn. Shown
140
+ * whenever a region is selected — including `none` (display) mode and while
141
+ * another tool (wand, brush, SAM…) is active — so a selection always reveals
142
+ * its vertices. Suppressed only while actively drawing a brand-new shape,
143
+ * where stray handles would be noise. */
144
+ get showsSelectedVertices() {
145
+ return this.mode !== 'drawrect' && this.mode !== 'drawpolygon'
146
+ && this.mode !== 'drawclosedpath' && this.mode !== 'drawopenpath';
147
+ }
148
+ destroy() {
149
+ this.subs.unsubscribe();
150
+ this.viewer.element
151
+ ?.removeEventListener('wheel', this.wheelZoomHandler);
152
+ this.viewer.removeHandler('update-viewport', this.redrawHandler);
153
+ this.viewer.removeHandler('animation', this.redrawHandler);
154
+ this.viewer.removeHandler('resize', this.redrawHandler);
155
+ this.viewer.removeHandler('rotate', this.redrawHandler);
156
+ if (this.tracker)
157
+ this.tracker.destroy();
158
+ if (this.svg.parentNode)
159
+ this.svg.parentNode.removeChild(this.svg);
160
+ }
161
+ // ── coordinate helpers ───────────────────────────────────────────────
162
+ /** Image-pixel point -> element pixel point. */
163
+ toPx(imgX, imgY) {
164
+ return imageToElement(this.viewer, imgX, imgY);
165
+ }
166
+ /** Element pixel point (from a MouseTracker event) -> image-pixel point. */
167
+ toImage(pos) {
168
+ const p = elementToImage(this.viewer, pos.x, pos.y);
169
+ return { x: Math.round(p.x), y: Math.round(p.y) };
170
+ }
171
+ // ── rendering ────────────────────────────────────────────────────────
172
+ redraw() {
173
+ while (this.svg.firstChild)
174
+ this.svg.removeChild(this.svg.firstChild);
175
+ const regions = this.store.getRegions();
176
+ regions.forEach((r, i) => {
177
+ const el = this.buildRegionEl(r, this.selected.includes(i));
178
+ if (el)
179
+ this.svg.appendChild(el);
180
+ });
181
+ // Handles on the selected polygon, so the user can grab/insert/delete
182
+ // vertices. Bezier regions also get their cubic
183
+ // control handles (tangent lines + control points), mirroring paper.js's
184
+ // fullySelected rendering.
185
+ if (this.showsSelectedVertices) {
186
+ const sel = this.selectedRegionInfo();
187
+ const b = sel?.region.bounds;
188
+ // Handles/vertices take the region's own colour (not the global shape
189
+ // colour) so they match the shape they belong to.
190
+ const color = sel ? sel.region.color || this.store.getShapeColor() : '';
191
+ if (b instanceof Polygon) {
192
+ if (b.bezier) {
193
+ this.drawBezierHandles(b, color);
194
+ }
195
+ else {
196
+ for (let i = 0; i < b.xpoints.length; i++) {
197
+ const q = this.toPx(b.xpoints[i], b.ypoints[i]);
198
+ this.svg.appendChild(this.vertexMarker(q.x, q.y, false, color));
199
+ }
200
+ // Interior-ring (hole) vertices too, so a donut's inner outline shows
201
+ // its vertices when selected (jit-ui#85).
202
+ if (b.holes) {
203
+ for (const ring of b.holes) {
204
+ for (const [hx, hy] of ring) {
205
+ const q = this.toPx(hx, hy);
206
+ this.svg.appendChild(this.vertexMarker(q.x, q.y, false, color));
207
+ }
208
+ }
209
+ }
210
+ }
211
+ }
212
+ else if (b instanceof Rectangle) {
213
+ // The four corners as grab/resize handles.
214
+ const corners = [
215
+ [b.x, b.y], [b.x + b.width, b.y],
216
+ [b.x + b.width, b.y + b.height], [b.x, b.y + b.height],
217
+ ];
218
+ for (const [cx, cy] of corners) {
219
+ const q = this.toPx(cx, cy);
220
+ this.svg.appendChild(this.vertexMarker(q.x, q.y, false, color));
221
+ }
222
+ }
223
+ }
224
+ // Rubber-band (marquee) selection preview.
225
+ if (this.mode === 'select' && this.bandStart && this.bandCurrent) {
226
+ this.svg.appendChild(this.selectionBand(this.bandStart, this.bandCurrent));
227
+ }
228
+ // In-progress drawing preview.
229
+ if (this.mode === 'drawrect' && this.rectStart && this.rectCurrent) {
230
+ this.svg.appendChild(this.rectPreview(this.rectStart, this.rectCurrent));
231
+ }
232
+ if ((this.mode === 'drawclosedpath' || this.mode === 'drawopenpath') && this.polyPoints.length) {
233
+ this.svg.appendChild(this.polyPreview(this.polyPoints));
234
+ }
235
+ // Click-to-place polygon preview: the polyline so far + a marker on the
236
+ // first vertex (click it to close).
237
+ if (this.mode === 'drawpolygon' && this.polyPoints.length) {
238
+ this.svg.appendChild(this.polyPreview(this.polyPoints));
239
+ const f = this.toPx(this.polyPoints[0].x, this.polyPoints[0].y);
240
+ this.svg.appendChild(this.vertexMarker(f.x, f.y, true));
241
+ }
242
+ }
243
+ /** A small vertex handle (filled for an emphasised marker, hollow otherwise).
244
+ * Colour defaults to the global shape colour (used by the in-progress draw
245
+ * preview); selected-region handles pass the region's own colour. */
246
+ vertexMarker(x, y, emphasised, color = this.store.getShapeColor()) {
247
+ const c = document.createElementNS(SVGNS, 'circle');
248
+ c.setAttribute('cx', `${x}`);
249
+ c.setAttribute('cy', `${y}`);
250
+ c.setAttribute('r', emphasised ? '5' : '4');
251
+ c.setAttribute('fill', emphasised ? color : '#ffffff');
252
+ c.setAttribute('stroke', color);
253
+ c.setAttribute('stroke-width', '2');
254
+ return c;
255
+ }
256
+ buildRegionEl(region, selected) {
257
+ const color = region.color || this.store.getShapeColor();
258
+ const bounds = region.bounds;
259
+ let pts = null;
260
+ let closed = true;
261
+ let el = null;
262
+ if (bounds instanceof MultiPolygon) {
263
+ // Multi-part region (jit-ui#85): one even-odd <path> with every part's
264
+ // exterior plus its holes. All parts' vertices drive the label bbox.
265
+ const parts = bounds.polygons.filter((p) => (p.xpoints?.length ?? 0) >= 3);
266
+ if (parts.length === 0)
267
+ return null;
268
+ pts = [];
269
+ let d = '';
270
+ for (const part of parts) {
271
+ const ext = part.xpoints.map((x, i) => ({ x, y: part.ypoints[i] }));
272
+ pts.push(...ext);
273
+ d += (d ? ' ' : '') + this.straightPathD(ext, true);
274
+ if (part.holes) {
275
+ for (const ring of part.holes) {
276
+ d += ' ' + this.straightPathD(ring.map(([x, y]) => ({ x, y })), true);
277
+ }
278
+ }
279
+ }
280
+ el = document.createElementNS(SVGNS, 'path');
281
+ el.setAttribute('d', d);
282
+ el.setAttribute('fill-rule', 'evenodd');
283
+ }
284
+ else if (bounds instanceof Rectangle) {
285
+ pts = [
286
+ { x: bounds.x, y: bounds.y },
287
+ { x: bounds.x + bounds.width, y: bounds.y },
288
+ { x: bounds.x + bounds.width, y: bounds.y + bounds.height },
289
+ { x: bounds.x, y: bounds.y + bounds.height },
290
+ ];
291
+ }
292
+ else if (bounds instanceof Polygon) {
293
+ closed = bounds.closed !== false;
294
+ // The anchors drive the label bbox and (for non-bezier) the rendered shape.
295
+ pts = bounds.xpoints.map((x, i) => ({ x, y: bounds.ypoints[i] }));
296
+ }
297
+ if (!pts || pts.length === 0)
298
+ return null;
299
+ if (!el) {
300
+ // Bezier regions render as a true cubic-bezier path through the anchors
301
+ // (paper.js-equivalent smooth curve); everything else as a straight
302
+ // polygon/polyline.
303
+ const isBezier = bounds instanceof Polygon && bounds.bezier && pts.length >= 2;
304
+ // Interior rings (holes) — punch through with even-odd fill (jit-ui#85).
305
+ const holes = (closed && bounds instanceof Polygon && bounds.holes?.length)
306
+ ? bounds.holes : null;
307
+ if (isBezier || holes) {
308
+ el = document.createElementNS(SVGNS, 'path');
309
+ // Exterior subpath (smooth for bezier, straight otherwise) followed by a
310
+ // straight subpath per hole.
311
+ let d = isBezier ? this.bezierPathD(bounds) : this.straightPathD(pts, closed);
312
+ if (holes) {
313
+ const poly = bounds;
314
+ holes.forEach((ring, hi) => {
315
+ const xs = ring.map((p) => p[0]);
316
+ const ys = ring.map((p) => p[1]);
317
+ // When the donut is a bezier, smooth its holes too (jit-ui#102) — using stored hole
318
+ // handles when present, else the Catmull-Rom default (via resolveHandles).
319
+ d +=
320
+ ' ' +
321
+ (isBezier
322
+ ? this.ringBezierPathD(xs, ys, poly.holeHandlesIn?.[hi], poly.holeHandlesOut?.[hi], true)
323
+ : this.straightPathD(ring.map(([x, y]) => ({ x, y })), true));
324
+ });
325
+ el.setAttribute('fill-rule', 'evenodd');
326
+ }
327
+ el.setAttribute('d', d);
328
+ }
329
+ else {
330
+ el = document.createElementNS(SVGNS, closed ? 'polygon' : 'polyline');
331
+ el.setAttribute('points', pts.map(p => { const q = this.toPx(p.x, p.y); return `${q.x},${q.y}`; }).join(' '));
332
+ }
333
+ }
334
+ el.setAttribute('fill', selected ? this.rgba(color, 0.35) : 'none');
335
+ el.setAttribute('stroke', color);
336
+ el.setAttribute('stroke-width', selected ? '4' : '2');
337
+ // The class label (legend), shown when the Region Editor's "show labels" is
338
+ // on — mirrors Plotly's per-shape label (top-left, drawn in the region's
339
+ // colour). Without this OSD showed regions with no label even though Plotly
340
+ // did. region.label is restored from the shape's legend in getRegion().
341
+ const label = region.label;
342
+ if (this.store.getShowShapeLabel() && label != null && `${label}`.length > 0) {
343
+ const g = document.createElementNS(SVGNS, 'g');
344
+ g.appendChild(el);
345
+ const minX = Math.min(...pts.map(p => p.x));
346
+ const minY = Math.min(...pts.map(p => p.y));
347
+ const q = this.toPx(minX, minY);
348
+ const text = document.createElementNS(SVGNS, 'text');
349
+ text.setAttribute('x', `${q.x}`);
350
+ text.setAttribute('y', `${q.y - 4}`); // just above the top-left corner
351
+ text.setAttribute('fill', color);
352
+ text.setAttribute('font-size', '13');
353
+ text.setAttribute('font-family', 'sans-serif');
354
+ // Dark halo so the label stays legible over both bright and dark tiles.
355
+ text.setAttribute('paint-order', 'stroke');
356
+ text.setAttribute('stroke', 'rgba(0,0,0,0.65)');
357
+ text.setAttribute('stroke-width', '2');
358
+ text.textContent = `${label}`;
359
+ g.appendChild(text);
360
+ return g;
361
+ }
362
+ return el;
363
+ }
364
+ /** Marquee rectangle for rubber-band multi-select (dashed outline + faint fill). */
365
+ selectionBand(a, b) {
366
+ const corners = [
367
+ { x: a.x, y: a.y }, { x: b.x, y: a.y }, { x: b.x, y: b.y }, { x: a.x, y: b.y },
368
+ ];
369
+ const el = document.createElementNS(SVGNS, 'polygon');
370
+ el.setAttribute('points', corners.map(p => { const q = this.toPx(p.x, p.y); return `${q.x},${q.y}`; }).join(' '));
371
+ el.setAttribute('fill', 'rgba(120,170,255,0.15)');
372
+ el.setAttribute('stroke', '#4a90e2');
373
+ el.setAttribute('stroke-dasharray', '4 3');
374
+ el.setAttribute('stroke-width', '1');
375
+ return el;
376
+ }
377
+ rectPreview(a, b) {
378
+ const corners = [
379
+ { x: a.x, y: a.y }, { x: b.x, y: a.y }, { x: b.x, y: b.y }, { x: a.x, y: b.y },
380
+ ];
381
+ const el = document.createElementNS(SVGNS, 'polygon');
382
+ el.setAttribute('points', corners.map(p => { const q = this.toPx(p.x, p.y); return `${q.x},${q.y}`; }).join(' '));
383
+ el.setAttribute('fill', 'none');
384
+ el.setAttribute('stroke', this.store.getShapeColor());
385
+ el.setAttribute('stroke-dasharray', '4 3');
386
+ el.setAttribute('stroke-width', '2');
387
+ return el;
388
+ }
389
+ polyPreview(pts) {
390
+ const el = document.createElementNS(SVGNS, 'polyline');
391
+ el.setAttribute('points', pts.map(p => { const q = this.toPx(p.x, p.y); return `${q.x},${q.y}`; }).join(' '));
392
+ el.setAttribute('fill', 'none');
393
+ el.setAttribute('stroke', this.store.getShapeColor());
394
+ el.setAttribute('stroke-dasharray', '4 3');
395
+ el.setAttribute('stroke-width', '2');
396
+ return el;
397
+ }
398
+ /** SVG path `d` (element-pixel coords) for a straight-edged ring/polyline. */
399
+ straightPathD(pts, closed) {
400
+ if (pts.length < 2)
401
+ return '';
402
+ let d = '';
403
+ pts.forEach((p, i) => {
404
+ const q = this.toPx(p.x, p.y);
405
+ d += (i === 0 ? 'M ' : ' L ') + `${q.x},${q.y}`;
406
+ });
407
+ if (closed)
408
+ d += ' Z';
409
+ return d;
410
+ }
411
+ /** SVG path `d` (element-pixel coords) for the smooth cubic bezier through a
412
+ * polygon's anchors — the paper.js-equivalent curve. */
413
+ bezierPathD(poly) {
414
+ const closed = poly.closed !== false;
415
+ return this.ringBezierPathD(poly.xpoints, poly.ypoints, poly.handlesIn, poly.handlesOut, closed);
416
+ }
417
+ /** SVG cubic-bezier path `d` (element px) for any ring (exterior or hole). Uses the stored
418
+ * per-vertex handle offsets when present, else the Catmull-Rom default (resolveHandles). */
419
+ ringBezierPathD(xs, ys, inOff, outOff, closed) {
420
+ const n = Math.min(xs.length, ys.length);
421
+ if (n < 2)
422
+ return '';
423
+ const h = resolveHandles(xs, ys, closed, inOff, outOff);
424
+ const px = (x, y) => { const q = this.toPx(x, y); return `${q.x},${q.y}`; };
425
+ let d = `M ${px(xs[0], ys[0])}`;
426
+ const segs = closed ? n : n - 1;
427
+ for (let i = 0; i < segs; i++) {
428
+ const j = (i + 1) % n;
429
+ const c1 = h[i].out;
430
+ const c2 = h[j].in;
431
+ d += ` C ${px(c1[0], c1[1])} ${px(c2[0], c2[1])} ${px(xs[j], ys[j])}`;
432
+ }
433
+ if (closed)
434
+ d += ' Z';
435
+ return d;
436
+ }
437
+ /**
438
+ * Draw the bezier editing handles for the selected region, paper.js-style:
439
+ * each anchor as a small square, with tangent lines out to its two control
440
+ * points (drawn as small circles).
441
+ */
442
+ drawBezierHandles(poly, color) {
443
+ const xs = poly.xpoints;
444
+ const ys = poly.ypoints;
445
+ const drawRing = (rxs, rys, inOff, outOff, closed) => {
446
+ const h = resolveHandles(rxs, rys, closed, inOff, outOff);
447
+ for (let i = 0; i < rxs.length; i++) {
448
+ const a = this.toPx(rxs[i], rys[i]);
449
+ if (h[i].hasIn)
450
+ this.drawHandle(a, this.toPx(h[i].in[0], h[i].in[1]), color);
451
+ if (h[i].hasOut)
452
+ this.drawHandle(a, this.toPx(h[i].out[0], h[i].out[1]), color);
453
+ this.svg.appendChild(this.anchorSquare(a.x, a.y, color));
454
+ }
455
+ };
456
+ drawRing(xs, ys, poly.handlesIn, poly.handlesOut, poly.closed !== false);
457
+ // Donut hole rings get their own editable bezier handles (jit-ui#102).
458
+ if (poly.holes && poly.holeHandlesIn && poly.holeHandlesOut) {
459
+ poly.holes.forEach((ring, hi) => {
460
+ const inOff = poly.holeHandlesIn[hi];
461
+ const outOff = poly.holeHandlesOut[hi];
462
+ if (inOff && outOff)
463
+ drawRing(ring.map((p) => p[0]), ring.map((p) => p[1]), inOff, outOff, true);
464
+ });
465
+ }
466
+ }
467
+ /** A tangent line from an anchor to a control point, with a circle at the end. */
468
+ drawHandle(anchor, ctrl, color) {
469
+ const line = document.createElementNS(SVGNS, 'line');
470
+ line.setAttribute('x1', `${anchor.x}`);
471
+ line.setAttribute('y1', `${anchor.y}`);
472
+ line.setAttribute('x2', `${ctrl.x}`);
473
+ line.setAttribute('y2', `${ctrl.y}`);
474
+ line.setAttribute('stroke', color);
475
+ line.setAttribute('stroke-width', '1');
476
+ this.svg.appendChild(line);
477
+ const c = document.createElementNS(SVGNS, 'circle');
478
+ c.setAttribute('cx', `${ctrl.x}`);
479
+ c.setAttribute('cy', `${ctrl.y}`);
480
+ c.setAttribute('r', '3');
481
+ c.setAttribute('fill', color);
482
+ this.svg.appendChild(c);
483
+ }
484
+ /** A filled-white anchor square (the editable vertex). */
485
+ anchorSquare(x, y, color) {
486
+ const r = 3.5;
487
+ const rect = document.createElementNS(SVGNS, 'rect');
488
+ rect.setAttribute('x', `${x - r}`);
489
+ rect.setAttribute('y', `${y - r}`);
490
+ rect.setAttribute('width', `${2 * r}`);
491
+ rect.setAttribute('height', `${2 * r}`);
492
+ rect.setAttribute('fill', '#ffffff');
493
+ rect.setAttribute('stroke', color);
494
+ rect.setAttribute('stroke-width', '2');
495
+ return rect;
496
+ }
497
+ rgba(color, alpha) {
498
+ // Accept #rrggbb; fall back to the color as-is for named/rgb values.
499
+ if (/^#([0-9a-f]{6})$/i.test(color)) {
500
+ const r = parseInt(color.slice(1, 3), 16);
501
+ const g = parseInt(color.slice(3, 5), 16);
502
+ const b = parseInt(color.slice(5, 7), 16);
503
+ return `rgba(${r},${g},${b},${alpha})`;
504
+ }
505
+ return color;
506
+ }
507
+ // ── interaction ──────────────────────────────────────────────────────
508
+ get isFreehand() {
509
+ return this.mode === 'drawclosedpath' || this.mode === 'drawopenpath';
510
+ }
511
+ onPress(e) {
512
+ if (this.mode === 'drawrect') {
513
+ this.rectStart = this.toImage(e.position);
514
+ this.rectCurrent = this.rectStart;
515
+ return;
516
+ }
517
+ if (this.isFreehand) {
518
+ // Freehand draw (matches Plotly drawclosedpath/drawopenpath): press to
519
+ // start, drag to trace, release to commit.
520
+ this.freehandDragging = true;
521
+ this.polyPoints = [this.toImage(e.position)];
522
+ this.lastFreehandPx = { x: e.position.x, y: e.position.y };
523
+ return;
524
+ }
525
+ if (this.mode === 'move') {
526
+ // Whole-region drag ('move' mode): press inside the selected region
527
+ // to translate it, ignoring vertices/edges.
528
+ const sel = this.selectedRegionInfo();
529
+ if (sel && this.containsPoint(sel.region, this.toImage(e.position))) {
530
+ this.startEdit('bounds', 'move', -1, sel.region, this.toImage(e.position));
531
+ }
532
+ return;
533
+ }
534
+ if (this.mode === 'select') {
535
+ // A bezier control handle takes top priority (it sits off the anchor).
536
+ const hh = this.hitBezierHandle(e.position);
537
+ if (hh) {
538
+ const region = this.store.getRegions()[this.selected[this.selected.length - 1]];
539
+ this.startEdit('handle', 'move', hh.index, region, this.toImage(e.position), hh.side, hh.ring);
540
+ return;
541
+ }
542
+ // Then dragging a single polygon vertex (over body-move/resize) —
543
+ // 'select' grabs the nearest segment first.
544
+ const vh = this.hitVertex(e.position);
545
+ if (vh) {
546
+ const region = this.store.getRegions()[this.selected[this.selected.length - 1]];
547
+ this.startEdit('vertex', 'move', vh.index, region, this.toImage(e.position), 'out', vh.ring);
548
+ return;
549
+ }
550
+ // Otherwise start a move/resize when pressing the selected region's
551
+ // body/handles.
552
+ const ez = this.editZoneAt(e.position);
553
+ if (ez) {
554
+ this.startEdit('bounds', ez.zone, -1, this.store.getRegions()[ez.index], this.toImage(e.position));
555
+ return;
556
+ }
557
+ // Press on empty space / a non-selected region: begin a rubber-band
558
+ // multi-select. A plain click (no drag) falls through to onClick, which
559
+ // single-selects or clears.
560
+ this.bandStart = this.toImage(e.position);
561
+ this.bandCurrent = this.bandStart;
562
+ this.bandDragged = false;
563
+ }
564
+ }
565
+ /** Begin an edit gesture (move/resize or single-vertex drag) and open a store
566
+ * batch so the live drag emits once on release. */
567
+ startEdit(kind, zone, vertexIndex, region, startImg, handleSide = 'out', ring = -1) {
568
+ this.edit = {
569
+ kind, zone, vertexIndex, ring, handleSide, id: region.id,
570
+ startImg, orig: kind === 'bounds' ? this.snapshot(region) : null,
571
+ };
572
+ this.editDragged = false;
573
+ this.store.beginBatch();
574
+ }
575
+ onDrag(e) {
576
+ if (this.mode === 'drawrect' && this.rectStart) {
577
+ this.rectCurrent = this.toImage(e.position);
578
+ this.redraw();
579
+ return;
580
+ }
581
+ if (this.freehandDragging && this.isFreehand) {
582
+ // Thin the path: only sample once the cursor has moved a few screen px.
583
+ const last = this.lastFreehandPx;
584
+ if (!last || Math.hypot(e.position.x - last.x, e.position.y - last.y) >= 4) {
585
+ this.polyPoints.push(this.toImage(e.position));
586
+ this.lastFreehandPx = { x: e.position.x, y: e.position.y };
587
+ this.redraw();
588
+ }
589
+ return;
590
+ }
591
+ if (this.edit) {
592
+ this.editDragged = true;
593
+ this.applyEdit(this.toImage(e.position));
594
+ return;
595
+ }
596
+ if (this.bandStart) {
597
+ this.bandCurrent = this.toImage(e.position);
598
+ this.bandDragged = true;
599
+ this.redraw();
600
+ }
601
+ }
602
+ onRelease(e) {
603
+ if (this.mode === 'drawrect' && this.rectStart) {
604
+ const end = this.toImage(e.position);
605
+ const x = Math.min(this.rectStart.x, end.x);
606
+ const y = Math.min(this.rectStart.y, end.y);
607
+ const w = Math.abs(end.x - this.rectStart.x);
608
+ const h = Math.abs(end.y - this.rectStart.y);
609
+ this.rectStart = this.rectCurrent = null;
610
+ if (w > 2 && h > 2)
611
+ this.commitRectangle(x, y, w, h);
612
+ return;
613
+ }
614
+ if (this.freehandDragging) {
615
+ this.freehandDragging = false;
616
+ this.lastFreehandPx = null;
617
+ // Closed = freeform (drawclosedpath); open = polyline (drawopenpath).
618
+ this.commitPolygon(this.mode === 'drawclosedpath');
619
+ return;
620
+ }
621
+ // Move/resize already applied live; flush the coalesced edits + end the
622
+ // gesture (keep selection).
623
+ if (this.edit) {
624
+ this.store.endBatch();
625
+ this.edit = null;
626
+ return;
627
+ }
628
+ // Finish a rubber-band selection: select every region the band intersects.
629
+ if (this.bandStart) {
630
+ const start = this.bandStart;
631
+ const end = this.bandCurrent ?? start;
632
+ this.bandStart = this.bandCurrent = null;
633
+ const x0 = Math.min(start.x, end.x), y0 = Math.min(start.y, end.y);
634
+ const x1 = Math.max(start.x, end.x), y1 = Math.max(start.y, end.y);
635
+ // Only a real drag selects; a click-sized band falls through to onClick.
636
+ if (this.bandDragged && (x1 - x0 > 2 || y1 - y0 > 2)) {
637
+ this.store.setSelectedShapeIndices(this.regionsInRect(x0, y0, x1, y1));
638
+ }
639
+ this.redraw();
640
+ }
641
+ }
642
+ onClick(e) {
643
+ if (this.mode === 'select') {
644
+ // A move/resize/vertex drag or a rubber-band drag also ends with a click
645
+ // event — don't treat it as a re-selection.
646
+ if (this.editDragged) {
647
+ this.editDragged = false;
648
+ return;
649
+ }
650
+ if (this.bandDragged) {
651
+ this.bandDragged = false;
652
+ return;
653
+ }
654
+ // Shift (or Cmd/Ctrl) toggles the clicked region in/out of the current
655
+ // selection; a plain click replaces it.
656
+ const oe = e.originalEvent;
657
+ const additive = !!oe && (oe.shiftKey || oe.metaKey || oe.ctrlKey);
658
+ this.selectAt(this.toImage(e.position), additive);
659
+ return;
660
+ }
661
+ if (this.mode === 'drawpolygon') {
662
+ this.onDrawPolygonClick(e);
663
+ return;
664
+ }
665
+ if (this.mode === 'addpoint') {
666
+ // Insert a vertex on the clicked edge — exterior or an interior ring.
667
+ const sel = this.selectedRegionInfo();
668
+ const edge = sel ? this.hitEdge(e.position, sel.region) : null;
669
+ if (sel && edge) {
670
+ if (edge.ring < 0)
671
+ this.store.addVertex(sel.region.id, edge.segIndex, edge.x, edge.y);
672
+ else
673
+ this.store.addHoleVertex(sel.region.id, edge.ring, edge.segIndex, edge.x, edge.y);
674
+ }
675
+ return;
676
+ }
677
+ if (this.mode === 'deletepoint') {
678
+ // Remove the clicked vertex — exterior or an interior ring (jit-ui#85).
679
+ const vh = this.hitVertex(e.position);
680
+ if (vh) {
681
+ if (vh.ring < 0)
682
+ this.store.deleteVertex(vh.id, vh.index);
683
+ else
684
+ this.store.deleteHoleVertex(vh.id, vh.ring, vh.index);
685
+ }
686
+ return;
687
+ }
688
+ }
689
+ /**
690
+ * Click-to-place polygon ('drawpolygon'): the first click starts the
691
+ * polygon, each subsequent click adds a vertex, and clicking near the first
692
+ * vertex (with at least 3 placed) closes and commits it.
693
+ */
694
+ onDrawPolygonClick(e) {
695
+ const pt = this.toImage(e.position);
696
+ if (!this.drawingPolygon) {
697
+ this.polyPoints = [pt];
698
+ this.drawingPolygon = true;
699
+ this.redraw();
700
+ return;
701
+ }
702
+ const first = this.toPx(this.polyPoints[0].x, this.polyPoints[0].y);
703
+ const onFirst = Math.hypot(e.position.x - first.x, e.position.y - first.y) <= EDIT_TOL;
704
+ if (onFirst && this.polyPoints.length >= 3) {
705
+ this.commitPolygon(true); // closes + resets in-progress (incl. drawingPolygon)
706
+ return;
707
+ }
708
+ this.polyPoints.push(pt);
709
+ this.redraw();
710
+ }
711
+ /**
712
+ * Hover feedback in select mode: move/resize cursors over the selected
713
+ * region's body/edges/corners, a pointer over any other region.
714
+ */
715
+ onMove(e) {
716
+ if (this.mode !== 'select')
717
+ return;
718
+ // A grabbable bezier control handle or vertex of the selected polygon takes
719
+ // priority.
720
+ if (this.hitBezierHandle(e.position) || this.hitVertex(e.position)) {
721
+ this.viewer.canvas.style.cursor = 'pointer';
722
+ return;
723
+ }
724
+ const ez = this.editZoneAt(e.position);
725
+ if (ez) {
726
+ this.viewer.canvas.style.cursor = ZONE_CURSOR[ez.zone];
727
+ return;
728
+ }
729
+ this.updateCursor(this.regionIndexAt(this.toImage(e.position)) >= 0);
730
+ }
731
+ /**
732
+ * The move/resize zone under the cursor for the currently-selected region
733
+ * (rectangles get edge/corner handles + body; polygons get body-move only),
734
+ * or null if the cursor isn't over the selected region.
735
+ */
736
+ editZoneAt(position) {
737
+ if (this.selected.length === 0)
738
+ return null;
739
+ const index = this.selected[this.selected.length - 1];
740
+ const region = this.store.getRegions()[index];
741
+ if (!region)
742
+ return null;
743
+ const b = region.bounds;
744
+ if (b instanceof Rectangle) {
745
+ const a = this.toPx(b.x, b.y);
746
+ const c = this.toPx(b.x + b.width, b.y + b.height);
747
+ const zone = this.rectZone(position.x, position.y, Math.min(a.x, c.x), Math.min(a.y, c.y), Math.max(a.x, c.x), Math.max(a.y, c.y));
748
+ return zone ? { zone, index } : null;
749
+ }
750
+ if (b instanceof Polygon || b instanceof MultiPolygon) {
751
+ // Polygons + multi-part regions support whole-region move (no resize zones).
752
+ return this.containsPoint(region, this.toImage(position)) ? { zone: 'move', index } : null;
753
+ }
754
+ return null;
755
+ }
756
+ /** The currently-selected region (the last one selected), or null. */
757
+ selectedRegionInfo() {
758
+ if (this.selected.length === 0)
759
+ return null;
760
+ const index = this.selected[this.selected.length - 1];
761
+ const region = this.store.getRegions()[index];
762
+ return region ? { region, index } : null;
763
+ }
764
+ /** The vertex of the selected polygon under the cursor (screen-pixel
765
+ * tolerance), or null. Rectangles have no editable vertices. */
766
+ hitVertex(position) {
767
+ const sel = this.selectedRegionInfo();
768
+ if (!sel || !(sel.region.bounds instanceof Polygon))
769
+ return null;
770
+ const b = sel.region.bounds;
771
+ for (let i = 0; i < b.xpoints.length; i++) {
772
+ const q = this.toPx(b.xpoints[i], b.ypoints[i]);
773
+ if (Math.hypot(position.x - q.x, position.y - q.y) <= EDIT_TOL) {
774
+ return { id: sel.region.id, ring: -1, index: i };
775
+ }
776
+ }
777
+ // Interior-ring (hole) vertices are draggable too (jit-ui#85).
778
+ if (b.holes) {
779
+ for (let h = 0; h < b.holes.length; h++) {
780
+ const ring = b.holes[h];
781
+ for (let i = 0; i < ring.length; i++) {
782
+ const q = this.toPx(ring[i][0], ring[i][1]);
783
+ if (Math.hypot(position.x - q.x, position.y - q.y) <= EDIT_TOL) {
784
+ return { id: sel.region.id, ring: h, index: i };
785
+ }
786
+ }
787
+ }
788
+ }
789
+ return null;
790
+ }
791
+ /** The bezier control handle of the selected region under the cursor (which
792
+ * anchor, and whether the in- or out-handle), or null. */
793
+ hitBezierHandle(position) {
794
+ const sel = this.selectedRegionInfo();
795
+ if (!sel || !(sel.region.bounds instanceof Polygon) || !sel.region.bounds.bezier)
796
+ return null;
797
+ const b = sel.region.bounds;
798
+ // Test one ring's control handles; returns the matched vertex/side or null.
799
+ const testRing = (xs, ys, inOff, outOff, closed, ring) => {
800
+ const h = resolveHandles(xs, ys, closed, inOff, outOff);
801
+ for (let i = 0; i < h.length; i++) {
802
+ if (h[i].hasOut) {
803
+ const q = this.toPx(h[i].out[0], h[i].out[1]);
804
+ if (Math.hypot(position.x - q.x, position.y - q.y) <= EDIT_TOL) {
805
+ return { id: sel.region.id, index: i, side: 'out', ring };
806
+ }
807
+ }
808
+ if (h[i].hasIn) {
809
+ const q = this.toPx(h[i].in[0], h[i].in[1]);
810
+ if (Math.hypot(position.x - q.x, position.y - q.y) <= EDIT_TOL) {
811
+ return { id: sel.region.id, index: i, side: 'in', ring };
812
+ }
813
+ }
814
+ }
815
+ return null;
816
+ };
817
+ const ext = testRing(b.xpoints, b.ypoints, b.handlesIn, b.handlesOut, b.closed !== false, -1);
818
+ if (ext)
819
+ return ext;
820
+ // Donut hole rings (jit-ui#102): their own bezier control handles.
821
+ if (b.holes && b.holeHandlesIn && b.holeHandlesOut) {
822
+ for (let hi = 0; hi < b.holes.length; hi++) {
823
+ const ring = b.holes[hi];
824
+ const hit = testRing(ring.map((p) => p[0]), ring.map((p) => p[1]), b.holeHandlesIn[hi], b.holeHandlesOut[hi], true, hi);
825
+ if (hit)
826
+ return hit;
827
+ }
828
+ }
829
+ return null;
830
+ }
831
+ /** The edge of `region`'s polygon nearest the cursor (within tolerance), with
832
+ * the clicked point in image coords as the insertion position, or null. */
833
+ hitEdge(position, region) {
834
+ if (!(region.bounds instanceof Polygon))
835
+ return null;
836
+ const b = region.bounds;
837
+ let best = -1, bestRing = -1, bestDist = Infinity;
838
+ // Nearest edge across the exterior (ring -1) and every interior ring (hole).
839
+ const scan = (xs, ys, ring, closed) => {
840
+ const n = xs.length;
841
+ const segCount = closed ? n : n - 1; // closed wraps the last->first edge
842
+ for (let i = 0; i < segCount; i++) {
843
+ const j = (i + 1) % n;
844
+ const a = this.toPx(xs[i], ys[i]);
845
+ const c = this.toPx(xs[j], ys[j]);
846
+ const d = this.distToSegmentPx(position, a, c);
847
+ if (d < bestDist) {
848
+ bestDist = d;
849
+ best = i;
850
+ bestRing = ring;
851
+ }
852
+ }
853
+ };
854
+ scan(b.xpoints, b.ypoints, -1, b.closed !== false);
855
+ if (b.holes) {
856
+ b.holes.forEach((r, h) => scan(r.map(p => p[0]), r.map(p => p[1]), h, true));
857
+ }
858
+ if (best < 0 || bestDist > EDIT_TOL)
859
+ return null;
860
+ const img = this.toImage(position);
861
+ return { ring: bestRing, segIndex: best, x: img.x, y: img.y };
862
+ }
863
+ /** Classify a screen point against a screen-space rectangle into a zone. */
864
+ rectZone(px, py, x0, y0, x1, y1) {
865
+ const t = EDIT_TOL;
866
+ if (px < x0 - t || px > x1 + t || py < y0 - t || py > y1 + t)
867
+ return null;
868
+ const left = Math.abs(px - x0) <= t, right = Math.abs(px - x1) <= t;
869
+ const top = Math.abs(py - y0) <= t, bottom = Math.abs(py - y1) <= t;
870
+ if (top && left)
871
+ return 'nw';
872
+ if (top && right)
873
+ return 'ne';
874
+ if (bottom && left)
875
+ return 'sw';
876
+ if (bottom && right)
877
+ return 'se';
878
+ if (left)
879
+ return 'w';
880
+ if (right)
881
+ return 'e';
882
+ if (top)
883
+ return 'n';
884
+ if (bottom)
885
+ return 's';
886
+ if (px > x0 && px < x1 && py > y0 && py < y1)
887
+ return 'move';
888
+ return null;
889
+ }
890
+ /** Snapshot the selected region's geometry at the start of an edit. */
891
+ snapshot(region) {
892
+ const b = region.bounds;
893
+ if (b instanceof Rectangle)
894
+ return { kind: 'rect', x: b.x, y: b.y, w: b.width, h: b.height };
895
+ if (b instanceof Polygon) {
896
+ return {
897
+ kind: 'poly', xs: b.xpoints.slice(), ys: b.ypoints.slice(), closed: b.closed !== false,
898
+ bezier: b.bezier,
899
+ inOff: b.handlesIn?.map(o => o.slice()),
900
+ outOff: b.handlesOut?.map(o => o.slice()),
901
+ holes: b.holes?.map(ring => ring.map(pt => pt.slice())),
902
+ };
903
+ }
904
+ if (b instanceof MultiPolygon) {
905
+ return {
906
+ kind: 'multi',
907
+ polygons: b.polygons.map((p) => ({
908
+ xs: p.xpoints.slice(), ys: p.ypoints.slice(), closed: p.closed !== false,
909
+ holes: p.holes?.map(ring => ring.map(pt => pt.slice())),
910
+ })),
911
+ };
912
+ }
913
+ return { kind: 'rect', x: 0, y: 0, w: 0, h: 0 };
914
+ }
915
+ /**
916
+ * Apply the in-progress move/resize to the region, live, through the
917
+ * Region-native edit API. Recomputed absolutely from the gesture-start
918
+ * snapshot (`orig`) + the total delta, so each frame is idempotent.
919
+ */
920
+ applyEdit(curImg) {
921
+ if (!this.edit)
922
+ return;
923
+ if (this.edit.kind === 'vertex') {
924
+ // Drag a single vertex to the cursor (absolute — idempotent). Route to the
925
+ // exterior or the matching interior ring (hole) — jit-ui#85.
926
+ if (this.edit.ring < 0) {
927
+ this.store.moveVertex(this.edit.id, this.edit.vertexIndex, curImg.x, curImg.y);
928
+ }
929
+ else {
930
+ this.store.moveHoleVertex(this.edit.id, this.edit.ring, this.edit.vertexIndex, curImg.x, curImg.y);
931
+ }
932
+ this.redraw();
933
+ return;
934
+ }
935
+ if (this.edit.kind === 'handle') {
936
+ // Drag a bezier control handle to the cursor — exterior (ring -1) or a donut hole ring.
937
+ if (this.edit.ring < 0) {
938
+ this.store.moveBezierHandle(this.edit.id, this.edit.vertexIndex, this.edit.handleSide, curImg.x, curImg.y);
939
+ }
940
+ else {
941
+ this.store.moveHoleBezierHandle(this.edit.id, this.edit.ring, this.edit.vertexIndex, this.edit.handleSide, curImg.x, curImg.y);
942
+ }
943
+ this.redraw();
944
+ return;
945
+ }
946
+ const dx = curImg.x - this.edit.startImg.x;
947
+ const dy = curImg.y - this.edit.startImg.y;
948
+ const o = this.edit.orig;
949
+ if (o.kind === 'rect') {
950
+ let x0 = o.x, y0 = o.y, x1 = o.x + o.w, y1 = o.y + o.h;
951
+ switch (this.edit.zone) {
952
+ case 'move':
953
+ x0 += dx;
954
+ x1 += dx;
955
+ y0 += dy;
956
+ y1 += dy;
957
+ break;
958
+ case 'w':
959
+ x0 += dx;
960
+ break;
961
+ case 'e':
962
+ x1 += dx;
963
+ break;
964
+ case 'n':
965
+ y0 += dy;
966
+ break;
967
+ case 's':
968
+ y1 += dy;
969
+ break;
970
+ case 'nw':
971
+ x0 += dx;
972
+ y0 += dy;
973
+ break;
974
+ case 'ne':
975
+ x1 += dx;
976
+ y0 += dy;
977
+ break;
978
+ case 'sw':
979
+ x0 += dx;
980
+ y1 += dy;
981
+ break;
982
+ case 'se':
983
+ x1 += dx;
984
+ y1 += dy;
985
+ break;
986
+ }
987
+ const rect = new Rectangle();
988
+ rect.x = Math.round(Math.min(x0, x1));
989
+ rect.y = Math.round(Math.min(y0, y1));
990
+ rect.width = Math.round(Math.abs(x1 - x0));
991
+ rect.height = Math.round(Math.abs(y1 - y0));
992
+ this.store.updateBounds(this.edit.id, rect);
993
+ }
994
+ else if (o.kind === 'multi') {
995
+ // Multi-part region: translate every part (and its holes) by the delta.
996
+ const mp = new MultiPolygon();
997
+ mp.polygons = o.polygons.map((pp) => {
998
+ const xs = pp.xs.map((x) => Math.round(x + dx));
999
+ const ys = pp.ys.map((y) => Math.round(y + dy));
1000
+ const poly = new Polygon();
1001
+ poly.npoints = xs.length;
1002
+ poly.xpoints = xs;
1003
+ poly.ypoints = ys;
1004
+ poly.coordinates = xs.map((x, i) => [x, ys[i]]);
1005
+ poly.closed = pp.closed;
1006
+ if (pp.holes) {
1007
+ poly.holes = pp.holes.map((ring) => ring.map(([x, y]) => [Math.round(x + dx), Math.round(y + dy)]));
1008
+ }
1009
+ return poly;
1010
+ });
1011
+ this.store.updateBounds(this.edit.id, mp);
1012
+ }
1013
+ else {
1014
+ // Polygon: translate every vertex (the only polygon edit zone is 'move').
1015
+ // Bezier flag + handle offsets are relative, so they carry over unchanged.
1016
+ const xs = o.xs.map((x) => Math.round(x + dx));
1017
+ const ys = o.ys.map((y) => Math.round(y + dy));
1018
+ const poly = new Polygon();
1019
+ poly.npoints = xs.length;
1020
+ poly.xpoints = xs;
1021
+ poly.ypoints = ys;
1022
+ poly.coordinates = xs.map((x, i) => [x, ys[i]]);
1023
+ poly.closed = o.closed;
1024
+ poly.bezier = o.bezier;
1025
+ if (o.inOff)
1026
+ poly.handlesIn = o.inOff.map((off) => off.slice());
1027
+ if (o.outOff)
1028
+ poly.handlesOut = o.outOff.map((off) => off.slice());
1029
+ // Translate interior rings (holes) with the exterior (jit-ui#85).
1030
+ if (o.holes) {
1031
+ poly.holes = o.holes.map((ring) => ring.map(([x, y]) => [Math.round(x + dx), Math.round(y + dy)]));
1032
+ }
1033
+ this.store.updateBounds(this.edit.id, poly);
1034
+ }
1035
+ this.redraw();
1036
+ }
1037
+ selectAt(pt, additive = false) {
1038
+ const idx = this.regionIndexAt(pt);
1039
+ if (additive) {
1040
+ // Shift-click on empty space keeps the current selection.
1041
+ if (idx < 0)
1042
+ return;
1043
+ // `this.selected` mirrors the store's current selection (kept in sync via
1044
+ // the subscription), so it's the source of truth without a sync getter.
1045
+ const cur = this.selected.slice();
1046
+ const at = cur.indexOf(idx);
1047
+ if (at >= 0)
1048
+ cur.splice(at, 1); // toggle off
1049
+ else
1050
+ cur.push(idx); // toggle on
1051
+ this.store.setSelectedShapeIndices(cur);
1052
+ return;
1053
+ }
1054
+ this.store.setSelectedShapeIndices(idx >= 0 ? [idx] : []);
1055
+ }
1056
+ /** Indices of every region whose bounding box intersects the image-space
1057
+ * rectangle [x0,y0]–[x1,y1] (rubber-band multi-select). */
1058
+ regionsInRect(x0, y0, x1, y1) {
1059
+ const out = [];
1060
+ this.store.getRegions().forEach((r, i) => {
1061
+ const bb = this.regionBBox(r);
1062
+ if (bb && bb.x0 <= x1 && bb.x1 >= x0 && bb.y0 <= y1 && bb.y1 >= y0)
1063
+ out.push(i);
1064
+ });
1065
+ return out;
1066
+ }
1067
+ /** Axis-aligned bounding box of a region in image coords, or null if empty. */
1068
+ regionBBox(r) {
1069
+ const b = r.bounds;
1070
+ if (b instanceof Rectangle) {
1071
+ return { x0: b.x, y0: b.y, x1: b.x + b.width, y1: b.y + b.height };
1072
+ }
1073
+ if (b instanceof Polygon && b.xpoints.length) {
1074
+ return {
1075
+ x0: Math.min(...b.xpoints), y0: Math.min(...b.ypoints),
1076
+ x1: Math.max(...b.xpoints), y1: Math.max(...b.ypoints),
1077
+ };
1078
+ }
1079
+ if (b instanceof MultiPolygon) {
1080
+ let x0 = Infinity, y0 = Infinity, x1 = -Infinity, y1 = -Infinity;
1081
+ for (const p of b.polygons) {
1082
+ for (let i = 0; i < p.xpoints.length; i++) {
1083
+ if (p.xpoints[i] < x0)
1084
+ x0 = p.xpoints[i];
1085
+ if (p.xpoints[i] > x1)
1086
+ x1 = p.xpoints[i];
1087
+ if (p.ypoints[i] < y0)
1088
+ y0 = p.ypoints[i];
1089
+ if (p.ypoints[i] > y1)
1090
+ y1 = p.ypoints[i];
1091
+ }
1092
+ }
1093
+ return x1 >= x0 ? { x0, y0, x1, y1 } : null;
1094
+ }
1095
+ return null;
1096
+ }
1097
+ /** Index of the topmost region under a point, or -1. */
1098
+ regionIndexAt(pt) {
1099
+ const regions = this.store.getRegions();
1100
+ for (let i = regions.length - 1; i >= 0; i--) {
1101
+ if (this.containsPoint(regions[i], pt))
1102
+ return i;
1103
+ }
1104
+ return -1;
1105
+ }
1106
+ containsPoint(region, pt) {
1107
+ const b = region.bounds;
1108
+ if (b instanceof Rectangle) {
1109
+ return pt.x >= b.x && pt.x <= b.x + b.width && pt.y >= b.y && pt.y <= b.y + b.height;
1110
+ }
1111
+ // Multi-part region: inside any part (exterior minus that part's holes).
1112
+ if (b instanceof MultiPolygon) {
1113
+ return b.polygons.some((p) => this.closedPolygonContains(p, pt));
1114
+ }
1115
+ if (b instanceof Polygon) {
1116
+ if (b.closed !== false)
1117
+ return this.closedPolygonContains(b, pt);
1118
+ // Open polyline: no interior — select when the click lands near the line.
1119
+ // Tolerance is in screen pixels so it stays clickable at any zoom.
1120
+ const xs = b.xpoints, ys = b.ypoints, n = xs.length, tolPx = 6;
1121
+ const here = this.toPx(pt.x, pt.y);
1122
+ for (let i = 0; i + 1 < n; i++) {
1123
+ const a = this.toPx(xs[i], ys[i]);
1124
+ const c = this.toPx(xs[i + 1], ys[i + 1]);
1125
+ if (this.distToSegmentPx(here, a, c) <= tolPx)
1126
+ return true;
1127
+ }
1128
+ return false;
1129
+ }
1130
+ return false;
1131
+ }
1132
+ /** Point-in-closed-polygon (image coords) honouring interior rings (holes):
1133
+ * inside the exterior AND outside every hole (even-odd). */
1134
+ closedPolygonContains(b, pt) {
1135
+ const inRing = (rxs, rys) => {
1136
+ let hit = false;
1137
+ for (let i = 0, j = rxs.length - 1; i < rxs.length; j = i++) {
1138
+ const intersect = ((rys[i] > pt.y) !== (rys[j] > pt.y))
1139
+ && (pt.x < ((rxs[j] - rxs[i]) * (pt.y - rys[i])) / (rys[j] - rys[i]) + rxs[i]);
1140
+ if (intersect)
1141
+ hit = !hit;
1142
+ }
1143
+ return hit;
1144
+ };
1145
+ if (!inRing(b.xpoints, b.ypoints))
1146
+ return false;
1147
+ if (b.holes) {
1148
+ for (const ring of b.holes) {
1149
+ if (inRing(ring.map(p => p[0]), ring.map(p => p[1])))
1150
+ return false;
1151
+ }
1152
+ }
1153
+ return true;
1154
+ }
1155
+ /** Shortest distance from point p to segment a–b, all in screen pixels. */
1156
+ distToSegmentPx(p, a, b) {
1157
+ const dx = b.x - a.x, dy = b.y - a.y;
1158
+ const len2 = dx * dx + dy * dy;
1159
+ if (len2 === 0)
1160
+ return Math.hypot(p.x - a.x, p.y - a.y);
1161
+ let t = ((p.x - a.x) * dx + (p.y - a.y) * dy) / len2;
1162
+ t = Math.max(0, Math.min(1, t));
1163
+ return Math.hypot(p.x - (a.x + t * dx), p.y - (a.y + t * dy));
1164
+ }
1165
+ resetInProgress() {
1166
+ this.rectStart = this.rectCurrent = null;
1167
+ this.polyPoints = [];
1168
+ this.freehandDragging = false;
1169
+ this.drawingPolygon = false;
1170
+ this.lastFreehandPx = null;
1171
+ // Close any open edit batch (e.g. a mode switch mid-drag) so the store's
1172
+ // emit coalescing doesn't get stuck.
1173
+ if (this.edit) {
1174
+ this.store.endBatch();
1175
+ this.edit = null;
1176
+ }
1177
+ }
1178
+ // ── commit to the store ──────────────────────────────────────────────
1179
+ commitRectangle(x, y, w, h) {
1180
+ const region = new Region();
1181
+ const rect = new Rectangle();
1182
+ rect.x = x;
1183
+ rect.y = y;
1184
+ rect.width = w;
1185
+ rect.height = h;
1186
+ region.bounds = rect;
1187
+ region.color = this.store.getShapeColor();
1188
+ this.commitRegion(region);
1189
+ }
1190
+ commitPolygon(closed) {
1191
+ if (this.polyPoints.length < (closed ? 3 : 2)) {
1192
+ this.resetInProgress();
1193
+ return;
1194
+ }
1195
+ const region = new Region();
1196
+ const poly = new Polygon();
1197
+ poly.npoints = this.polyPoints.length;
1198
+ poly.xpoints = this.polyPoints.map(p => p.x);
1199
+ poly.ypoints = this.polyPoints.map(p => p.y);
1200
+ poly.coordinates = this.polyPoints.map(p => [p.x, p.y]);
1201
+ poly.closed = closed;
1202
+ region.bounds = poly;
1203
+ region.color = this.store.getShapeColor();
1204
+ this.resetInProgress();
1205
+ this.commitRegion(region);
1206
+ }
1207
+ /**
1208
+ * Add a freshly-drawn region to the shared store and redraw immediately. The
1209
+ * store mints the id, selects the new region (so it renders solid/highlighted
1210
+ * rather than as a dashed in-progress shape) and emits the full region list to
1211
+ * the Region Editor — we still redraw locally rather than relying solely on
1212
+ * the store's update event, which can be swallowed when Plotly isn't active.
1213
+ */
1214
+ commitRegion(region) {
1215
+ // Default class/annotation name, matching the Plotly backend and the Region
1216
+ // Editor's "Add" actions so a freshly drawn region isn't unlabeled.
1217
+ if (region.label == null)
1218
+ region.label = 'Region';
1219
+ this.store.addRegion(region);
1220
+ this.redraw();
1221
+ }
1222
+ /**
1223
+ * Convert the selected region(s) to/from a bezier curve (toBezier = true /
1224
+ * toPolygon = false). One-shot; the anchors are unchanged,
1225
+ * only the smooth-curve rendering is toggled.
1226
+ */
1227
+ setSelectedBezier(bezier) {
1228
+ const regions = this.store.getRegions();
1229
+ for (const idx of this.selected) {
1230
+ const region = regions[idx];
1231
+ if (region)
1232
+ this.store.setBezier(region.id, bezier);
1233
+ }
1234
+ this.redraw();
1235
+ }
1236
+ }
1237
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3NkLXJlZ2lvbi1vdmVybGF5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9pbXBsZW1lbnRhdGlvbnMvb3NkL29zZC1yZWdpb24tb3ZlcmxheS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ2hDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFFcEMsT0FBTyxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQy9FLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUlyRCxPQUFPLEVBQUUsY0FBYyxFQUFFLGNBQWMsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQVk5RCxNQUFNLEtBQUssR0FBRyw0QkFBNEIsQ0FBQztBQUkzQyxNQUFNLFdBQVcsR0FBNkI7SUFDNUMsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDLEVBQUUsV0FBVyxFQUFFLENBQUMsRUFBRSxXQUFXLEVBQUUsQ0FBQyxFQUFFLFdBQVcsRUFBRSxDQUFDLEVBQUUsV0FBVztJQUM1RSxFQUFFLEVBQUUsYUFBYSxFQUFFLEVBQUUsRUFBRSxhQUFhLEVBQUUsRUFBRSxFQUFFLGFBQWEsRUFBRSxFQUFFLEVBQUUsYUFBYTtDQUMzRSxDQUFDO0FBQ0YsaUVBQWlFO0FBQ2pFLE1BQU0sUUFBUSxHQUFHLENBQUMsQ0FBQztBQUNuQiw4RUFBOEU7QUFDOUUsTUFBTSxlQUFlLEdBQUcsR0FBRyxDQUFDO0FBRTVCOzs7Ozs7Ozs7Ozs7O0dBYUc7QUFDSCxNQUFNLE9BQU8sZ0JBQWdCO0lBNkMzQixZQUFvQixNQUFXLEVBQVUsS0FBc0I7UUFBM0MsV0FBTSxHQUFOLE1BQU0sQ0FBSztRQUFVLFVBQUssR0FBTCxLQUFLLENBQWlCO1FBMUM5QyxTQUFJLEdBQUcsSUFBSSxZQUFZLEVB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LEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUNsSCxFQUFFLENBQUMsWUFBWSxDQUFDLE1BQU0sRUFBRSx3QkFBd0IsQ0FBQyxDQUFDO1FBQ2xELEVBQUUsQ0FBQyxZQUFZLENBQUMsUUFBUSxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBQ3JDLEVBQUUsQ0FBQyxZQUFZLENBQUMsa0JBQWtCLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDM0MsRUFBRSxDQUFDLFlBQVksQ0FBQyxjQUFjLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDckMsT0FBTyxFQUFFLENBQUM7SUFDWixDQUFDO0lBRU8sV0FBVyxDQUFDLENBQTJCLEVBQUUsQ0FBMkI7UUFDMUUsTUFBTSxPQUFPLEdBQUc7WUFDZCxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFO1NBQy9FLENBQUM7UUFDRixNQUFNLEVBQUUsR0FBRyxRQUFRLENBQUMsZUFBZSxDQUFDLEtBQUssRUFBRSxTQUFTLENBQUMsQ0FBQztRQUN0RCxFQUFFLENBQUMsWUFBWSxDQUFDLFFBQVEsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsTUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMs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QUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDbkcsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDO0lBQ0gsQ0FBQztJQUVELGtGQUFrRjtJQUMxRSxVQUFVLENBQUMsTUFBZ0MsRUFBRSxJQUE4QixFQUFFLEtBQWE7UUFDaEcsTUFBTSxJQUFJLEdBQUcsUUFBUSxDQUFDLGVBQWUsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDckQsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLEVBQUUsR0FBRyxNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxFQUFFLEdBQUcsTUFBTSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDL0UsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDM0UsSUFBSSxDQUFDLFlBQVksQ0FBQyxRQUFRLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDbkMsSUFBSSxDQUFDLFlBQVksQ0FBQyxjQUFjLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDdkMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDM0IsTUFBTSxDQUFDLEdBQUcsUUFBUSxDQUFDLGVBQWUsQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDcEQsQ0FBQyxDQUFDLFlBQVksQ0FBQyxJQUFJLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsSUFBSSxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7UUFD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S0FBSyxHQUFHO29CQUFFLEVBQUUsSUFBSSxFQUFFLENBQUM7b0JBQUMsTUFBTTtnQkFDMUIsS0FBSyxHQUFHO29CQUFFLEVBQUUsSUFBSSxFQUFFLENBQUM7b0JBQUMsTUFBTTtnQkFDMUIsS0FBSyxHQUFHO29CQUFFLEVBQUUsSUFBSSxFQUFFLENBQUM7b0JBQUMsTUFBTTtnQkFDMUIsS0FBSyxJQUFJO29CQUFFLEVBQUUsSUFBSSxFQUFFLENBQUM7b0JBQUMsRUFBRSxJQUFJLEVBQUUsQ0FBQztvQkFBQyxNQUFNO2dCQUNyQyxLQUFLLElBQUk7b0JBQUUsRUFBRSxJQUFJLEVBQUUsQ0FBQztvQkFBQyxFQUFFLElBQUksRUFBRSxDQUFDO29CQUFDLE1BQU07Z0JBQ3JDLEtBQUssSUFBSTtvQkFBRSxFQUFFLElBQUksRUFBRSxDQUFDO29CQUFDLEVBQUUsSUFBSSxFQUFFLENBQUM7b0JBQUMsTUFBTTtnQkFDckMsS0FBSyxJQUFJO29CQUFFLEVBQUUsSUFBSSxFQUFFLENBQUM7b0JBQUMsRUFBRSxJQUFJLEVBQUUsQ0FBQztvQkFBQyxNQUFNO1lBQ3ZDLENBQUM7WUFDRCxNQUFNLElBQUksR0FBRyxJQUFJLFNBQVMsRUFBRSxDQUFDO1lBQzdCLElBQUksQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ3RDLElBQUksQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ3RDLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQzNDLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMs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QUMsTUFBTSxFQUFFLENBQUM7SUFDaEIsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxpQkFBaUIsQ0FBQyxNQUFlO1FBQy9CLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDeEMsS0FBSyxNQUFNLEdBQUcsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDaEMsTUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQzVCLElBQUksTUFBTTtnQkFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ3RELENBQUM7UUFDRCxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7SUFDaEIsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgT1NEIH0gZnJvbSAnLi9vc2QtbGliJztcbmltcG9ydCB7IFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuXG5pbXBvcnQgeyBSZWdpb24sIFJlY3RhbmdsZSwgUG9seWdvbiwgTXVsdGlQb2x5Z29uIH0gZnJvbSAnLi4vLi4vbW9kZWxzL3JlZ2lvbic7XG5pbXBvcnQgeyByZXNvbHZlSGFuZGxlcyB9IGZyb20gJy4uLy4uL21vZGVscy9iZXppZXInO1xuaW1wb3J0IHsgSVJlZ2lvblN0b3JlIH0gZnJvbSAnLi4vLi4vY29udHJhY3RzL3Zpc3VhbGl6ZXIuY29udHJhY3QnO1xuaW1wb3J0IHsgSVJlZ2lvbkVkaXRBcGkgfSBmcm9tICcuLi8uLi9jb250cmFjdHMvcmVnaW9uLXN0b3JlLmNvbnRyYWN0JztcbmltcG9ydCB7IElSZWdpb25PdmVybGF5LCBSZWdpb25Ub29sTW9kZSB9IGZyb20gJy4uLy4uL2NvbnRyYWN0cy9yZWdpb24tb3ZlcmxheS5jb250cmFjdCc7XG5pbXBvcnQgeyBlbGVtZW50VG9JbWFnZSwgaW1hZ2VUb0VsZW1lbnQgfSBmcm9tICcuL29zZC1jb29yZHMnO1xuXG4vKipcbiAqIFRoZSBzaGFyZWQgcmVnaW9uIHN0b3JlIGFzIHRoZSBvdmVybGF5IG5lZWRzIGl0OiB0aGUgY3Jvc3MtYmFja2VuZFxuICoge0BsaW5rIElSZWdpb25TdG9yZX0gKHJlYWQgcmVnaW9ucywgc2VsZWN0aW9uLCBjb2xvdXJzKSBwbHVzIHRoZSBSZWdpb24tbmF0aXZlXG4gKiB7QGxpbmsgSVJlZ2lvbkVkaXRBcGl9IChhZGQvbW92ZS9yZXNpemUvdmVydGV4IGVkaXRzKS4gVGhlIHNoYXJlZCBSZWdpb25TdG9yZVxuICogc2F0aXNmaWVzIGJvdGguIFRoZSBvdmVybGF5IGVkaXRzIHRocm91Z2ggdGhlc2UgdHlwZWQgb3BlcmF0aW9ucyBvbiB0aGVcbiAqIG5ldXRyYWwgUmVnaW9uIG1vZGVsIOKAlCBpdCBuZXZlciB0b3VjaGVzIGEgYmFja2VuZCdzIG93biBzaGFwZSByZXByZXNlbnRhdGlvblxuICogKGUuZy4gUGxvdGx5J3MgYHgwL3kwL3gxL3kxYCAvIGBN4oCmTOKAplpgIGRpY3RzKS5cbiAqL1xuZXhwb3J0IHR5cGUgUmVnaW9uRWRpdFN0b3JlID0gSVJlZ2lvblN0b3JlICYgSVJlZ2lvbkVkaXRBcGk7XG5cbmNvbnN0IFNWR05TID0gJ2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJztcblxuLyoqIE1vdmUvcmVzaXplIHpvbmVzIG9uIHRoZSBzZWxlY3RlZCByZWN0YW5nbGUuICovXG50eXBlIEVkaXRab25lID0gJ21vdmUnIHwgJ24nIHwgJ3MnIHwgJ2UnIHwgJ3cnIHwgJ25lJyB8ICdudycgfCAnc2UnIHwgJ3N3JztcbmNvbnN0IFpPTkVfQ1VSU09SOiBSZWNvcmQ8RWRpdFpvbmUsIHN0cmluZz4gPSB7XG4gIG1vdmU6ICdtb3ZlJywgbjogJ25zLXJlc2l6ZScsIHM6ICducy1yZXNpemUnLCBlOiAnZXctcmVzaXplJywgdzogJ2V3LXJlc2l6ZScsXG4gIG5lOiAnbmVzdy1yZXNpemUnLCBzdzogJ25lc3ctcmVzaXplJywgbnc6ICdud3NlLXJlc2l6ZScsIHNlOiAnbndzZS1yZXNpemUnLFxufTtcbi8qKiBTY3JlZW4tcGl4ZWwgdG9sZXJhbmNlIGZvciBncmFiYmluZyBhbiBlZGdlL2Nvcm5lciBoYW5kbGUuICovXG5jb25zdCBFRElUX1RPTCA9IDg7XG4vKiogV2hlZWwgem9vbSBzdGVwIHBlciBzY3JvbGwgdGljayDigJQgbWlycm9ycyB0aGUgdmlld2VyJ3MgYHpvb21QZXJTY3JvbGxgLiAqL1xuY29uc3QgWk9PTV9QRVJfU0NST0xMID0gMS4xO1xuXG4vKipcbiAqIE9wZW5TZWFkcmFnb24gaW1wbGVtZW50YXRpb24gb2Yge0BsaW5rIElSZWdpb25PdmVybGF5fS5cbiAqXG4gKiAtIFJlbmRlcnMgdGhlIHN0b3JlJ3MgcmVnaW9ucyAocmVjdC9wb2x5Z29uKSBpbiBpbWFnZS1waXhlbCBzcGFjZSwga2VwdFxuICogICBhbGlnbmVkIG9uIGV2ZXJ5IHBhbi96b29tIHZpYSB0aGUgT1NEIHZpZXdwb3J0IEFQSS5cbiAqIC0gRHJhd3MgbmV3IHJlY3RhbmdsZSBhbmQgcG9seWdvbiByZWdpb25zIChjb21taXR0ZWQgdG8gdGhlIHNoYXJlZCBzdG9yZSkuXG4gKiAtIENsaWNrLXRvLXNlbGVjdCBpbiAnc2VsZWN0JyBtb2RlLlxuICpcbiAqIFJlYWRzL3dyaXRlcyB0aGUgc2hhcmVkIHtAbGluayBJUmVnaW9uU3RvcmV9LCBzbyByZWdpb25zIHN0YXkgaW4gc3luYyB3aXRoIHRoZVxuICogUmVnaW9uIEVkaXRvciBhbmQgdGhlIFBsb3RseSBiYWNrZW5kLiBUaGUgd2FuZCwgdmVydGV4LWVyYXNlciBhbmQgem9vbS10by1ib3hcbiAqIHRvb2xzIGFyZSBOT1QgaGFuZGxlZCBoZXJlIOKAlCB0aGV5J3JlIG93bmVkIGJ5IE9wZW5TZWFkcmFnb25WaXN1YWxpemVyU2VydmljZVxuICogKHdoaWNoIGJpbmRzIHRoZW0gdG8gT1NEIHZpYSB0aGUgc2hhcmVkIGNvb3JkaW5hdGUgdHJhbnNmb3JtICsgdmlld3BvcnQgcGl4ZWxcbiAqIHJlYWRiYWNrKSwgdGhlIHNhbWUgc2luZ2xldG9uIHRvb2wgc2VydmljZXMgdGhlIFBsb3RseSBiYWNrZW5kIHVzZXMuXG4gKi9cbmV4cG9ydCBjbGFzcyBPc2RSZWdpb25PdmVybGF5IGltcGxlbWVudHMgSVJlZ2lvbk92ZXJsYXkge1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgc3ZnOiBTVkdTVkdFbGVtZW50O1xuICBwcml2YXRlIHJlYWRvbmx5IHN1YnMgPSBuZXcgU3Vic2NyaXB0aW9uKCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgb3NkOiBhbnkgPSBPU0Q7XG5cbiAgcHJpdmF0ZSBzZWxlY3RlZDogbnVtYmVyW10gPSBbXTtcbiAgcHJpdmF0ZSBtb2RlOiBSZWdpb25Ub29sTW9kZSA9ICdub25lJztcblxuICBwcml2YXRlIHRyYWNrZXI6IGFueTtcbiAgcHJpdmF0ZSByZWN0U3RhcnQ6IHsgeDogbnVtYmVyOyB5OiBudW1iZXIgfSB8IG51bGwgPSBudWxsOyAvLyBpbWFnZSBjb29yZHNcbiAgcHJpdmF0ZSByZWN0Q3VycmVudDogeyB4OiBudW1iZXI7IHk6IG51bWJlciB9IHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgcG9seVBvaW50czogeyB4OiBudW1iZXI7IHk6IG51bWJlciB9W10gPSBbXTsgICAgICAgIC8vIGltYWdlIGNvb3Jkc1xuICAvKiogVHJ1ZSB3aGlsZSBkcmFnZ2luZyBhIGZyZWVoYW5kIHBhdGggKGZyZWVmb3JtIC8gcG9seWxpbmUpLiAqL1xuICBwcml2YXRlIGZyZWVoYW5kRHJhZ2dpbmcgPSBmYWxzZTtcbiAgLyoqIFRydWUgd2hpbGUgcGxhY2luZyBhIGNsaWNrLXRvLWFkZCBwb2x5Z29uICgnZHJhd3BvbHlnb24nIG1vZGUpLiAqL1xuICBwcml2YXRlIGRyYXdpbmdQb2x5Z29uID0gZmFsc2U7XG4gIC8qKiBMYXN0IGVsZW1lbnQtcGl4ZWwgcG9pbnQgYXBwZW5kZWQsIHRvIHRoaW4gdGhlIGZyZWVoYW5kIHBhdGguICovXG4gIHByaXZhdGUgbGFzdEZyZWVoYW5kUHg6IHsgeDogbnVtYmVyOyB5OiBudW1iZXIgfSB8IG51bGwgPSBudWxsO1xuICAvKipcbiAgICogSW4tcHJvZ3Jlc3MgZWRpdCBvZiB0aGUgc2VsZWN0ZWQgcmVnaW9uOlxuICAgKiAgLSBraW5kICdib3VuZHMnIOKAlCByZWN0YW5nbGUgcmVzaXplL21vdmUgb3Igd2hvbGUtcmVnaW9uIG1vdmUgKHVzZXMgYHpvbmVgKTtcbiAgICogIC0ga2luZCAndmVydGV4JyDigJQgZHJhZ2dpbmcgYSBzaW5nbGUgcG9seWdvbiB2ZXJ0ZXggKHVzZXMgYHZlcnRleEluZGV4YCkuXG4gICAqL1xuICBwcml2YXRlIGVkaXQ6IHtcbiAgICBraW5kOiAnYm91bmRzJyB8ICd2ZXJ0ZXgnIHwgJ2hhbmRsZSc7XG4gICAgem9uZTogRWRpdFpvbmU7XG4gICAgdmVydGV4SW5kZXg6IG51bWJlcjtcbiAgICAvKiogV2hpY2ggcmluZyB0aGUgZHJhZ2dlZCB2ZXJ0ZXggYmVsb25ncyB0bzogLTEgPSBleHRlcmlvciwgZWxzZSBhIGhvbGVcbiAgICAgKiAgaW5kZXggaW50byBgUG9seWdvbi5ob2xlc2AgKGppdC11aSM4NSkuICovXG4gICAgcmluZzogbnVtYmVyO1xuICAgIGhhbmRsZVNpZGU6ICdpbicgfCAnb3V0JztcbiAgICBpZDogbnVtYmVyO1xuICAgIHN0YXJ0SW1nOiB7IHg6IG51bWJlcjsgeTogbnVtYmVyIH07XG4gICAgb3JpZzogYW55O1xuICB9IHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgZWRpdERyYWdnZWQgPSBmYWxzZTtcbiAgLyoqIFJ1YmJlci1iYW5kIChtYXJxdWVlKSBtdWx0aS1zZWxlY3QgaW4gJ3NlbGVjdCcgbW9kZTogcHJlc3Mgb24gZW1wdHkgc3BhY2VcbiAgICogIGFuZCBkcmFnIHRvIHNlbGVjdCBldmVyeSByZWdpb24gdGhlIGJhbmQgaW50ZXJzZWN0cy4gSW1hZ2UgY29vcmRzLiAqL1xuICBwcml2YXRlIGJhbmRTdGFydDogeyB4OiBudW1iZXI7IHk6IG51bWJlciB9IHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgYmFuZEN1cnJlbnQ6IHsgeDogbnVtYmVyOyB5OiBudW1iZXIgfSB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIGJhbmREcmFnZ2VkID0gZmFsc2U7XG5cbiAgcHJpdmF0ZSByZWFkb25seSByZWRyYXdIYW5kbGVyID0gKCkgPT4gdGhpcy5yZWRyYXcoKTtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHZpZXdlcjogYW55LCBwcml2YXRlIHN0b3JlOiBSZWdpb25FZGl0U3RvcmUpIHtcbiAgICB0aGlzLnN2ZyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhTVkdOUywgJ3N2ZycpIGFzIFNWR1NWR0VsZW1lbnQ7XG4gICAgT2JqZWN0LmFzc2lnbih0aGlzLnN2Zy5zdHlsZSwge1xuICAgICAgcG9zaXRpb246ICdhYnNvbHV0ZScsIGxlZnQ6ICcwJywgdG9wOiAnMCcsIHdpZHRoOiAnMTAwJScsIGhlaWdodDogJzEwMCUnLFxuICAgICAgcG9pbnRlckV2ZW50czogJ25vbmUnLCAvLyBPU0QgaGFuZGxlcyBuYXZpZ2F0aW9uIHVubGVzcyB3ZSdyZSBkcmF3aW5nXG4gICAgfSk7XG4gICAgdGhpcy52aWV3ZXIuY2FudmFzLmFwcGVuZENoaWxkKHRoaXMuc3ZnKTtcblxuICAgIHRoaXMudmlld2VyLmFkZEhhbmRsZXIoJ3VwZGF0ZS12aWV3cG9ydCcsIHRoaXMucmVkcmF3SGFuZGxlcik7XG4gICAgdGhpcy52aWV3ZXIuYWRkSGFuZGxlcignYW5pbWF0aW9uJywgdGhpcy5yZWRyYXdIYW5kbGVyKTtcbiAgICB0aGlzLnZpZXdlci5hZGRIYW5kbGVyKCdyZXNpemUnLCB0aGlzLnJlZHJhd0hhbmRsZXIpO1xuICAgIHRoaXMudmlld2VyLmFkZEhhbmRsZXIoJ3JvdGF0ZScsIHRoaXMucmVkcmF3SGFuZGxlcik7XG4gICAgLy8gS2VlcCB3aGVlbC16b29tIGFsaXZlIHdoaWxlIGEgdG9vbCBoYXMgbW91c2UtbmF2IGRpc2FibGVkIChzZWUgaGFuZGxlcikuXG4gICAgKHRoaXMudmlld2VyLmVsZW1lbnQgYXMgSFRNTEVsZW1lbnQgfCB1bmRlZmluZWQpXG4gICAgICA/LmFkZEV2ZW50TGlzdGVuZXIoJ3doZWVsJywgdGhpcy53aGVlbFpvb21IYW5kbGVyLCB7IHBhc3NpdmU6IGZhbHNlIH0pO1xuXG4gICAgdGhpcy50cmFja2VyID0gbmV3IHRoaXMub3NkLk1vdXNlVHJhY2tlcih7XG4gICAgICBlbGVtZW50OiB0aGlzLnZpZXdlci5jYW52YXMsXG4gICAgICBwcmVzc0hhbmRsZXI6IChlOiBhbnkpID0+IHRoaXMub25QcmVzcyhlKSxcbiAgICAgIGRyYWdIYW5kbGVyOiAoZTogYW55KSA9PiB0aGlzLm9uRHJhZyhlKSxcbiAgICAgIHJlbGVhc2VIYW5kbGVyOiAoZTogYW55KSA9PiB0aGlzLm9uUmVsZWFzZShlKSxcbiAgICAgIGNsaWNrSGFuZGxlcjogKGU6IGFueSkgPT4gdGhpcy5vbkNsaWNrKGUpLFxuICAgICAgbW92ZUhhbmRsZXI6IChlOiBhbnkpID0+IHRoaXMub25Nb3ZlKGUpLFxuICAgIH0pO1xuICAgIHRoaXMudHJhY2tlci5zZXRUcmFja2luZyhmYWxzZSk7XG5cbiAgICB0aGlzLnN1YnMuYWRkKHRoaXMuc3RvcmUuZ2V0UmVnaW9uVXBkYXRlRXZlbnQoKS5zdWJzY3JpYmUodGhpcy5yZWRyYXdIYW5kbGVyKSk7XG4gICAgdGhpcy5zdWJzLmFkZCh0aGlzLnN0b3JlLmdldFNlbGVjdGVkU2hhcGVJbmRpY2VzJCgpLnN1YnNjcmliZShpZHggPT4ge1xuICAgICAgdGhpcy5zZWxlY3RlZCA9IGlkeCB8fCBbXTtcbiAgICAgIHRoaXMucmVkcmF3KCk7XG4gICAgfSkpO1xuXG4gICAgdGhpcy5yZWRyYXcoKTtcbiAgfVxuXG4gIC8qKiBTd2l0Y2ggZHJhd2luZy9zZWxlY3Rpb24gbW9kZTsgdG9nZ2xlcyBPU0QgbmF2aWdhdGlvbiBhY2NvcmRpbmdseS4gKi9cbiAgc2V0TW9kZShtb2RlOiBSZWdpb25Ub29sTW9kZSk6IHZvaWQge1xuICAgIHRoaXMubW9kZSA9IG1vZGU7XG4gICAgdGhpcy5yZXNldEluUHJvZ3Jlc3MoKTtcbiAgICAvLyBBbnkgYWN0aXZlIHJlZ2lvbiB0b29sIHRha2VzIG92ZXIgdGhlIHBvaW50ZXIg4oCUIE9TRCBwYW4vem9vbSBpcyBkaXNhYmxlZFxuICAgIC8vIHNvIGRyYWdnaW5nIGRyYXdzIChhbmQgY2xpY2tzIHNlbGVjdCkgaW5zdGVhZCBvZiBwYW5uaW5nLiBXaXRoIG5vIHRvb2wsXG4gICAgLy8gT1NEIG5hdmlnYXRlcyBub3JtYWxseS5cbiAgICB0aGlzLnZpZXdlci5zZXRNb3VzZU5hdkVuYWJsZWQobW9kZSA9PT0gJ25vbmUnKTtcbiAgICB0aGlzLnRyYWNrZXIuc2V0VHJhY2tpbmcobW9kZSAhPT0gJ25vbmUnKTtcbiAgICB0aGlzLnVwZGF0ZUN1cnNvcihmYWxzZSk7XG4gICAgdGhpcy5yZWRyYXcoKTtcbiAgfVxuXG4gIC8qKiBEcml2ZSBPU0Qgem9vbSBmcm9tIHRoZSB3aGVlbCB3aGlsZSBhbnkgdG9vbCBvd25zIHRoZSBwb2ludGVyLlxuICAgKlxuICAgKiBPU0QncyBuYXRpdmUgc2Nyb2xsLXpvb20gaXMgcGFydCBvZiBtb3VzZS1uYXYsIHNvIGBzZXRNb3VzZU5hdkVuYWJsZWQoZmFsc2UpYFxuICAgKiAodXNlZCBieSBldmVyeSByZWdpb24gdG9vbCBhbmQgYnkgdGhlIHdhbmQvYnJ1c2gvZXJhc2VyL1NBTSB0b29scykgZGlzYWJsZXNcbiAgICogaXQuIFRoZSBjb3ZlcmluZy1jYW52YXMgdG9vbHMgYWxzbyBzaXQgYWJvdmUgdGhlIE9TRCBjYW52YXMgYW5kIHN3YWxsb3cgdGhlXG4gICAqIHdoZWVsIG91dHJpZ2h0LiBUaGlzIGxpc3RlbmVyIGlzIGJvdW5kIG9uY2UgdG8gdGhlIHZpZXdlciBlbGVtZW50IOKAlCBhblxuICAgKiBhbmNlc3RvciBvZiBib3RoIHRoZSBPU0QgY2FudmFzIGFuZCB0aGUgdG9vbCBvdmVybGF5cyDigJQgYW5kIGZvcndhcmRzIHRoZVxuICAgKiB3aGVlbCB0byBhIGN1cnNvci1jZW50cmVkIHpvb20gd2hlbmV2ZXIgbW91c2UtbmF2IGlzIG9mZi4gV2hlbiBuYXYgaXMgb24gKG5vXG4gICAqIHRvb2wgYWN0aXZlKSBpdCBkb2VzIG5vdGhpbmcgYW5kIE9TRCB6b29tcyBuYXRpdmVseS4gKGppdC11aSM5NCkgKi9cbiAgcHJpdmF0ZSByZWFkb25seSB3aGVlbFpvb21IYW5kbGVyID0gKGU6IFdoZWVsRXZlbnQpID0+IHtcbiAgICBjb25zdCB2cCA9IHRoaXMudmlld2VyPy52aWV3cG9ydDtcbiAgICBjb25zdCBlbCA9IHRoaXMudmlld2VyPy5lbGVtZW50IGFzIEhUTUxFbGVtZW50IHwgdW5kZWZpbmVkO1xuICAgIC8vIE5hdiBvbiDihpIgbm8gdG9vbCBhY3RpdmUg4oaSIGxldCBPU0QgaGFuZGxlIHNjcm9sbC16b29tIG5hdGl2ZWx5LlxuICAgIGlmICghdnAgfHwgIWVsIHx8IGUuZGVsdGFZID09PSAwIHx8IHRoaXMudmlld2VyLmlzTW91c2VOYXZFbmFibGVkKCkpIHJldHVybjtcbiAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgY29uc3QgcmVjdCA9IGVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIGNvbnN0IHJlZlBvaW50ID0gdnAucG9pbnRGcm9tUGl4ZWwobmV3IHRoaXMub3NkLlBvaW50KGUuY2xpZW50WCAtIHJlY3QubGVmdCwgZS5jbGllbnRZIC0gcmVjdC50b3ApKTtcbiAgICB2cC56b29tQnkoZS5kZWx0YVkgPCAwID8gWk9PTV9QRVJfU0NST0xMIDogMSAvIFpPT01fUEVSX1NDUk9MTCwgcmVmUG9pbnQpO1xuICAgIHZwLmFwcGx5Q29uc3RyYWludHMoKTtcbiAgfTtcblxuICAvKiogQ3Vyc29yIGZlZWRiYWNrIHBlciBtb2RlIChjcm9zc2hhaXIgd2hpbGUgZHJhd2luZzsgcG9pbnRlciBvdmVyIGEgcmVnaW9uXG4gICAqICBpbiBzZWxlY3QgbW9kZSkuICovXG4gIHByaXZhdGUgdXBkYXRlQ3Vyc29yKG92ZXJSZWdpb246IGJvb2xlYW4pOiB2b2lkIHtcbiAgICBjb25zdCBjYW52YXMgPSB0aGlzLnZpZXdlci5jYW52YXMgYXMgSFRNTEVsZW1lbnQ7XG4gICAgaWYgKHRoaXMubW9kZSA9PT0gJ2RyYXdyZWN0JyB8fCB0aGlzLm1vZGUgPT09ICdkcmF3Y2xvc2VkcGF0aCcgfHwgdGhpcy5tb2RlID09PSAnZHJhd29wZW5wYXRoJ1xuICAgICAgICB8fCB0aGlzLm1vZGUgPT09ICdkcmF3cG9seWdvbicgfHwgdGhpcy5tb2RlID09PSAnYWRkcG9pbnQnIHx8IHRoaXMubW9kZSA9PT0gJ2RlbGV0ZXBvaW50Jykge1xuICAgICAgY2FudmFzLnN0eWxlLmN1cnNvciA9ICdjcm9zc2hhaXInO1xuICAgIH0gZWxzZSBpZiAodGhpcy5tb2RlID09PSAnbW92ZScpIHtcbiAgICAgIGNhbnZhcy5zdHlsZS5jdXJzb3IgPSAnbW92ZSc7XG4gICAgfSBlbHNlIGlmICh0aGlzLm1vZGUgPT09ICdzZWxlY3QnKSB7XG4gICAgICBjYW52YXMuc3R5bGUuY3Vyc29yID0gb3ZlclJlZ2lvbiA/ICdwb2ludGVyJyA6ICdkZWZhdWx0JztcbiAgICB9IGVsc2Uge1xuICAgICAgY2FudmFzLnN0eWxlLmN1cnNvciA9ICcnOyAvLyBPU0QgZGVmYXVsdCAoZ3JhYilcbiAgICB9XG4gIH1cblxuICAvKiogV2hldGhlciB0aGUgc2VsZWN0ZWQgcmVnaW9uJ3MgdmVydGljZXMvaGFuZGxlcyBzaG91bGQgYmUgZHJhd24uIFNob3duXG4gICAqICB3aGVuZXZlciBhIHJlZ2lvbiBpcyBzZWxlY3RlZCDigJQgaW5jbHVkaW5nIGBub25lYCAoZGlzcGxheSkgbW9kZSBhbmQgd2hpbGVcbiAgICogIGFub3RoZXIgdG9vbCAod2FuZCwgYnJ1c2gsIFNBTeKApikgaXMgYWN0aXZlIOKAlCBzbyBhIHNlbGVjdGlvbiBhbHdheXMgcmV2ZWFsc1xuICAgKiAgaXRzIHZlcnRpY2VzLiBTdXBwcmVzc2VkIG9ubHkgd2hpbGUgYWN0aXZlbHkgZHJhd2luZyBhIGJyYW5kLW5ldyBzaGFwZSxcbiAgICogIHdoZXJlIHN0cmF5IGhhbmRsZXMgd291bGQgYmUgbm9pc2UuICovXG4gIHByaXZhdGUgZ2V0IHNob3dzU2VsZWN0ZWRWZXJ0aWNlcygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5tb2RlICE9PSAnZHJhd3JlY3QnICYmIHRoaXMubW9kZSAhPT0gJ2RyYXdwb2x5Z29uJ1xuICAgICAgJiYgdGhpcy5tb2RlICE9PSAnZHJhd2Nsb3NlZHBhdGgnICYmIHRoaXMubW9kZSAhPT0gJ2RyYXdvcGVucGF0aCc7XG4gIH1cblxuICBkZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMuc3Vicy51bnN1YnNjcmliZSgpO1xuICAgICh0aGlzLnZpZXdlci5lbGVtZW50IGFzIEhUTUxFbGVtZW50IHwgdW5kZWZpbmVkKVxuICAgICAgPy5yZW1vdmVFdmVudExpc3RlbmVyKCd3aGVlbCcsIHRoaXMud2hlZWxab29tSGFuZGxlcik7XG4gICAgdGhpcy52aWV3ZXIucmVtb3ZlSGFuZGxlcigndXBkYXRlLXZpZXdwb3J0JywgdGhpcy5yZWRyYXdIYW5kbGVyKTtcbiAgICB0aGlzLnZpZXdlci5yZW1vdmVIYW5kbGVyKCdhbmltYXRpb24nLCB0aGlzLnJlZHJhd0hhbmRsZXIpO1xuICAgIHRoaXMudmlld2VyLnJlbW92ZUhhbmRsZXIoJ3Jlc2l6ZScsIHRoaXMucmVkcmF3SGFuZGxlcik7XG4gICAgdGhpcy52aWV3ZXIucmVtb3ZlSGFuZGxlcigncm90YXRlJywgdGhpcy5yZWRyYXdIYW5kbGVyKTtcbiAgICBpZiAodGhpcy50cmFja2VyKSB0aGlzLnRyYWNrZXIuZGVzdHJveSgpO1xuICAgIGlmICh0aGlzLnN2Zy5wYXJlbnROb2RlKSB0aGlzLnN2Zy5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKHRoaXMuc3ZnKTtcbiAgfVxuXG4gIC8vIOKUgOKUgCBjb29yZGluYXRlIGhlbHBlcnMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG4gIC8qKiBJbWFnZS1waXhlbCBwb2ludCAtPiBlbGVtZW50IHBpeGVsIHBvaW50LiAqL1xuICBwcml2YXRlIHRvUHgoaW1nWDogbnVtYmVyLCBpbWdZOiBudW1iZXIpOiB7IHg6IG51bWJlcjsgeTogbnVtYmVyIH0ge1xuICAgIHJldHVybiBpbWFnZVRvRWxlbWVudCh0aGlzLnZpZXdlciwgaW1nWCwgaW1nWSk7XG4gIH1cbiAgLyoqIEVsZW1lbnQgcGl4ZWwgcG9pbnQgKGZyb20gYSBNb3VzZVRyYWNrZXIgZXZlbnQpIC0+IGltYWdlLXBpeGVsIHBvaW50LiAqL1xuICBwcml2YXRlIHRvSW1hZ2UocG9zOiBhbnkpOiB7IHg6IG51bWJlcjsgeTogbnVtYmVyIH0ge1xuICAgIGNvbnN0IHAgPSBlbGVtZW50VG9JbWFnZSh0aGlzLnZpZXdlciwgcG9zLngsIHBvcy55KTtcbiAgICByZXR1cm4geyB4OiBNYXRoLnJvdW5kKHAueCksIHk6IE1hdGgucm91bmQocC55KSB9O1xuICB9XG5cbiAgLy8g4pSA4pSAIHJlbmRlcmluZyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcbiAgcmVkcmF3KCk6IHZvaWQge1xuICAgIHdoaWxlICh0aGlzLnN2Zy5maXJzdENoaWxkKSB0aGlzLnN2Zy5yZW1vdmVDaGlsZCh0aGlzLnN2Zy5maXJzdENoaWxkKTtcblxuICAgIGNvbnN0IHJlZ2lvbnMgPSB0aGlzLnN0b3JlLmdldFJlZ2lvbnMoKTtcbiAgICByZWdpb25zLmZvckVhY2goKHIsIGkpID0+IHtcbiAgICAgIGNvbnN0IGVsID0gdGhpcy5idWlsZFJlZ2lvbkVsKHIsIHRoaXMuc2VsZWN0ZWQuaW5jbHVkZXMoaSkpO1xuICAgICAgaWYgKGVsKSB0aGlzLnN2Zy5hcHBlbmRDaGlsZChlbCk7XG4gICAgfSk7XG5cbiAgICAvLyBIYW5kbGVzIG9uIHRoZSBzZWxlY3RlZCBwb2x5Z29uLCBzbyB0aGUgdXNlciBjYW4gZ3JhYi9pbnNlcnQvZGVsZXRlXG4gICAgLy8gdmVydGljZXMuIEJlemllciByZWdpb25zIGFsc28gZ2V0IHRoZWlyIGN1YmljXG4gICAgLy8gY29udHJvbCBoYW5kbGVzICh0YW5nZW50IGxpbmVzICsgY29udHJvbCBwb2ludHMpLCBtaXJyb3JpbmcgcGFwZXIuanMnc1xuICAgIC8vIGZ1bGx5U2VsZWN0ZWQgcmVuZGVyaW5nLlxuICAgIGlmICh0aGlzLnNob3dzU2VsZWN0ZWRWZXJ0aWNlcykge1xuICAgICAgY29uc3Qgc2VsID0gdGhpcy5zZWxlY3RlZFJlZ2lvbkluZm8oKTtcbiAgICAgIGNvbnN0IGIgPSBzZWw/LnJlZ2lvbi5ib3VuZHM7XG4gICAgICAvLyBIYW5kbGVzL3ZlcnRpY2VzIHRha2UgdGhlIHJlZ2lvbidzIG93biBjb2xvdXIgKG5vdCB0aGUgZ2xvYmFsIHNoYXBlXG4gICAgICAvLyBjb2xvdXIpIHNvIHRoZXkgbWF0Y2ggdGhlIHNoYXBlIHRoZXkgYmVsb25nIHRvLlxuICAgICAgY29uc3QgY29sb3IgPSBzZWwgPyBzZWwucmVnaW9uLmNvbG9yIHx8IHRoaXMuc3RvcmUuZ2V0U2hhcGVDb2xvcigpIDogJyc7XG4gICAgICBpZiAoYiBpbnN0YW5jZW9mIFBvbHlnb24pIHtcbiAgICAgICAgaWYgKGIuYmV6aWVyKSB7XG4gICAgICAgICAgdGhpcy5kcmF3QmV6aWVySGFuZGxlcyhiLCBjb2xvcik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBiLnhwb2ludHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IHEgPSB0aGlzLnRvUHgoYi54cG9pbnRzW2ldLCBiLnlwb2ludHNbaV0pO1xuICAgICAgICAgICAgdGhpcy5zdmcuYXBwZW5kQ2hpbGQodGhpcy52ZXJ0ZXhNYXJrZXIocS54LCBxLnksIGZhbHNlLCBjb2xvcikpO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBJbnRlcmlvci1yaW5nIChob2xlKSB2ZXJ0aWNlcyB0b28sIHNvIGEgZG9udXQncyBpbm5lciBvdXRsaW5lIHNob3dzXG4gICAgICAgICAgLy8gaXRzIHZlcnRpY2VzIHdoZW4gc2VsZWN0ZWQgKGppdC11aSM4NSkuXG4gICAgICAgICAgaWYgKGIuaG9sZXMpIHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgcmluZyBvZiBiLmhvbGVzKSB7XG4gICAgICAgICAgICAgIGZvciAoY29uc3QgW2h4LCBoeV0gb2YgcmluZykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHEgPSB0aGlzLnRvUHgoaHgsIGh5KTtcbiAgICAgICAgICAgICAgICB0aGlzLnN2Zy5hcHBlbmRDaGlsZCh0aGlzLnZlcnRleE1hcmtlcihxLngsIHEueSwgZmFsc2UsIGNvbG9yKSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoYiBpbnN0YW5jZW9mIFJlY3RhbmdsZSkge1xuICAgICAgICAvLyBUaGUgZm91ciBjb3JuZXJzIGFzIGdyYWIvcmVzaXplIGhhbmRsZXMuXG4gICAgICAgIGNvbnN0IGNvcm5lcnM6IFtudW1iZXIsIG51bWJlcl1bXSA9IFtcbiAgICAgICAgICBbYi54LCBiLnldLCBbYi54ICsgYi53aWR0aCwgYi55XSxcbiAgICAgICAgICBbYi54ICsgYi53aWR0aCwgYi55ICsgYi5oZWlnaHRdLCBbYi54LCBiLnkgKyBiLmhlaWdodF0sXG4gICAgICAgIF07XG4gICAgICAgIGZvciAoY29uc3QgW2N4LCBjeV0gb2YgY29ybmVycykge1xuICAgICAgICAgIGNvbnN0IHEgPSB0aGlzLnRvUHgoY3gsIGN5KTtcbiAgICAgICAgICB0aGlzLnN2Zy5hcHBlbmRDaGlsZCh0aGlzLnZlcnRleE1hcmtlcihxLngsIHEueSwgZmFsc2UsIGNvbG9yKSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBSdWJiZXItYmFuZCAobWFycXVlZSkgc2VsZWN0aW9uIHByZXZpZXcuXG4gICAgaWYgKHRoaXMubW9kZSA9PT0gJ3NlbGVjdCcgJiYgdGhpcy5iYW5kU3RhcnQgJiYgdGhpcy5iYW5kQ3VycmVudCkge1xuICAgICAgdGhpcy5zdmcuYXBwZW5kQ2hpbGQodGhpcy5zZWxlY3Rpb25CYW5kKHRoaXMuYmFuZFN0YXJ0LCB0aGlzLmJhbmRDdXJyZW50KSk7XG4gICAgfVxuXG4gICAgLy8gSW4tcHJvZ3Jlc3MgZHJhd2luZyBwcmV2aWV3LlxuICAgIGlmICh0aGlzLm1vZGUgPT09ICdkcmF3cmVjdCcgJiYgdGhpcy5yZWN0U3RhcnQgJiYgdGhpcy5yZWN0Q3VycmVudCkge1xuICAgICAgdGhpcy5zdmcuYXBwZW5kQ2hpbGQodGhpcy5yZWN0UHJldmlldyh0aGlzLnJlY3RTdGFydCwgdGhpcy5yZWN0Q3VycmVudCkpO1xuICAgIH1cbiAgICBpZiAoKHRoaXMubW9kZSA9PT0gJ2RyYXdjbG9zZWRwYXRoJyB8fCB0aGlzLm1vZGUgPT09ICdkcmF3b3BlbnBhdGgnKSAmJiB0aGlzLnBvbHlQb2ludHMubGVuZ3RoKSB7XG4gICAgICB0aGlzLnN2Zy5hcHBlbmRDaGlsZCh0aGlzLnBvbHlQcmV2aWV3KHRoaXMucG9seVBvaW50cykpO1xuICAgIH1cbiAgICAvLyBDbGljay10by1wbGFjZSBwb2x5Z29uIHByZXZpZXc6IHRoZSBwb2x5bGluZSBzbyBmYXIgKyBhIG1hcmtlciBvbiB0aGVcbiAgICAvLyBmaXJzdCB2ZXJ0ZXggKGNsaWNrIGl0IHRvIGNsb3NlKS5cbiAgICBpZiAodGhpcy5tb2RlID09PSAnZHJhd3BvbHlnb24nICYmIHRoaXMucG9seVBvaW50cy5sZW5ndGgpIHtcbiAgICAgIHRoaXMuc3ZnLmFwcGVuZENoaWxkKHRoaXMucG9seVByZXZpZXcodGhpcy5wb2x5UG9pbnRzKSk7XG4gICAgICBjb25zdCBmID0gdGhpcy50b1B4KHRoaXMucG9seVBvaW50c1swXS54LCB0aGlzLnBvbHlQb2ludHNbMF0ueSk7XG4gICAgICB0aGlzLnN2Zy5hcHBlbmRDaGlsZCh0aGlzLnZlcnRleE1hcmtlcihmLngsIGYueSwgdHJ1ZSkpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBBIHNtYWxsIHZlcnRleCBoYW5kbGUgKGZpbGxlZCBmb3IgYW4gZW1waGFzaXNlZCBtYXJrZXIsIGhvbGxvdyBvdGhlcndpc2UpLlxuICAgKiAgQ29sb3VyIGRlZmF1bHRzIHRvIHRoZSBnbG9iYWwgc2hhcGUgY29sb3VyICh1c2VkIGJ5IHRoZSBpbi1wcm9ncmVzcyBkcmF3XG4gICAqICBwcmV2aWV3KTsgc2VsZWN0ZWQtcmVnaW9uIGhhbmRsZXMgcGFzcyB0aGUgcmVnaW9uJ3Mgb3duIGNvbG91ci4gKi9cbiAgcHJpdmF0ZSB2ZXJ0ZXhNYXJrZXIoeDogbnVtYmVyLCB5OiBudW1iZXIsIGVtcGhhc2lzZWQ6IGJvb2xlYW4sXG4gICAgICAgICAgICAgICAgICAgICAgIGNvbG9yOiBzdHJpbmcgPSB0aGlzLnN0b3JlLmdldFNoYXBlQ29sb3IoKSk6IFNWR0VsZW1lbnQge1xuICAgIGNvbnN0IGMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoU1ZHTlMsICdjaXJjbGUnKTtcbiAgICBjLnNldEF0dHJpYnV0ZSgnY3gnLCBgJHt4fWApO1xuICAgIGMuc2V0QXR0cmlidXRlKCdjeScsIGAke3l9YCk7XG4gICAgYy5zZXRBdHRyaWJ1dGUoJ3InLCBlbXBoYXNpc2VkID8gJzUnIDogJzQnKTtcbiAgICBjLnNldEF0dHJpYnV0ZSgnZmlsbCcsIGVtcGhhc2lzZWQgPyBjb2xvciA6ICcjZmZmZmZmJyk7XG4gICAgYy5zZXRBdHRyaWJ1dGUoJ3N0cm9rZScsIGNvbG9yKTtcbiAgICBjLnNldEF0dHJpYnV0ZSgnc3Ryb2tlLXdpZHRoJywgJzInKTtcbiAgICByZXR1cm4gYztcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRSZWdpb25FbChyZWdpb246IFJlZ2lvbiwgc2VsZWN0ZWQ6IGJvb2xlYW4pOiBTVkdFbGVtZW50IHwgbnVsbCB7XG4gICAgY29uc3QgY29sb3IgPSByZWdpb24uY29sb3IgfHwgdGhpcy5zdG9yZS5nZXRTaGFwZUNvbG9yKCk7XG4gICAgY29uc3QgYm91bmRzID0gcmVnaW9uLmJvdW5kcztcbiAgICBsZXQgcHRzOiB7IHg6IG51bWJlcjsgeTogbnVtYmVyIH1bXSB8IG51bGwgPSBudWxsO1xuICAgIGxldCBjbG9zZWQgPSB0cnVlO1xuICAgIGxldCBlbDogU1ZHRWxlbWVudCB8IG51bGwgPSBudWxsO1xuXG4gICAgaWYgKGJvdW5kcyBpbnN0YW5jZW9mIE11bHRpUG9seWdvbikge1xuICAgICAgLy8gTXVsdGktcGFydCByZWdpb24gKGppdC11aSM4NSk6IG9uZSBldmVuLW9kZCA8cGF0aD4gd2l0aCBldmVyeSBwYXJ0J3NcbiAgICAgIC8vIGV4dGVyaW9yIHBsdXMgaXRzIGhvbGVzLiBBbGwgcGFydHMnIHZlcnRpY2VzIGRyaXZlIHRoZSBsYWJlbCBiYm94LlxuICAgICAgY29uc3QgcGFydHMgPSBib3VuZHMucG9seWdvbnMuZmlsdGVyKChwKSA9PiAocC54cG9pbnRzPy5sZW5ndGggPz8gMCkgPj0gMyk7XG4gICAgICBpZiAocGFydHMubGVuZ3RoID09PSAwKSByZXR1cm4gbnVsbDtcbiAgICAgIHB0cyA9IFtdO1xuICAgICAgbGV0IGQgPSAnJztcbiAgICAgIGZvciAoY29uc3QgcGFydCBvZiBwYXJ0cykge1xuICAgICAgICBjb25zdCBleHQgPSBwYXJ0Lnhwb2ludHMubWFwKCh4LCBpKSA9PiAoeyB4LCB5OiBwYXJ0Lnlwb2ludHNbaV0gfSkpO1xuICAgICAgICBwdHMucHVzaCguLi5leHQpO1xuICAgICAgICBkICs9IChkID8gJyAnIDogJycpICsgdGhpcy5zdHJhaWdodFBhdGhEKGV4dCwgdHJ1ZSk7XG4gICAgICAgIGlmIChwYXJ0LmhvbGVzKSB7XG4gICAgICAgICAgZm9yIChjb25zdCByaW5nIG9mIHBhcnQuaG9sZXMpIHtcbiAgICAgICAgICAgIGQgKz0gJyAnICsgdGhpcy5zdHJhaWdodFBhdGhEKHJpbmcubWFwKChbeCwgeV0pID0+ICh7IHgsIHkgfSkpLCB0cnVlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKFNWR05TLCAncGF0aCcpO1xuICAgICAgZWwuc2V0QXR0cmlidXRlKCdkJywgZCk7XG4gICAgICBlbC5zZXRBdHRyaWJ1dGUoJ2ZpbGwtcnVsZScsICdldmVub2RkJyk7XG4gICAgfSBlbHNlIGlmIChib3VuZHMgaW5zdGFuY2VvZiBSZWN0YW5nbGUpIHtcbiAgICAgIHB0cyA9IFtcbiAgICAgICAgeyB4OiBib3VuZHMueCwgeTogYm91bmRzLnkgfSxcbiAgICAgICAgeyB4OiBib3VuZHMueCArIGJvdW5kcy53aWR0aCwgeTogYm91bmRzLnkgfSxcbiAgICAgICAgeyB4OiBib3VuZHMueCArIGJvdW5kcy53aWR0aCwgeTogYm91bmRzLnkgKyBib3VuZHMuaGVpZ2h0IH0sXG4gICAgICAgIHsgeDogYm91bmRzLngsIHk6IGJvdW5kcy55ICsgYm91bmRzLmhlaWdodCB9LFxuICAgICAgXTtcbiAgICB9IGVsc2UgaWYgKGJvdW5kcyBpbnN0YW5jZW9mIFBvbHlnb24pIHtcbiAgICAgIGNsb3NlZCA9IGJvdW5kcy5jbG9zZWQgIT09IGZhbHNlO1xuICAgICAgLy8gVGhlIGFuY2hvcnMgZHJpdmUgdGhlIGxhYmVsIGJib3ggYW5kIChmb3Igbm9uLWJlemllcikgdGhlIHJlbmRlcmVkIHNoYXBlLlxuICAgICAgcHRzID0gYm91bmRzLnhwb2ludHMubWFwKCh4LCBpKSA9PiAoeyB4LCB5OiBib3VuZHMueXBvaW50c1tpXSB9KSk7XG4gICAgfVxuICAgIGlmICghcHRzIHx8IHB0cy5sZW5ndGggPT09IDApIHJldHVybiBudWxsO1xuXG4gICAgaWYgKCFlbCkge1xuICAgICAgLy8gQmV6aWVyIHJlZ2lvbnMgcmVuZGVyIGFzIGEgdHJ1ZSBjdWJpYy1iZXppZXIgcGF0aCB0aHJvdWdoIHRoZSBhbmNob3JzXG4gICAgICAvLyAocGFwZXIuanMtZXF1aXZhbGVudCBzbW9vdGggY3VydmUpOyBldmVyeXRoaW5nIGVsc2UgYXMgYSBzdHJhaWdodFxuICAgICAgLy8gcG9seWdvbi9wb2x5bGluZS5cbiAgICAgIGNvbnN0IGlzQmV6aWVyID0gYm91bmRzIGluc3RhbmNlb2YgUG9seWdvbiAmJiBib3VuZHMuYmV6aWVyICYmIHB0cy5sZW5ndGggPj0gMjtcbiAgICAgIC8vIEludGVyaW9yIHJpbmdzIChob2xlcykg4oCUIHB1bmNoIHRocm91Z2ggd2l0aCBldmVuLW9kZCBmaWxsIChqaXQtdWkjODUpLlxuICAgICAgY29uc3QgaG9sZXMgPSAoY2xvc2VkICYmIGJvdW5kcyBpbnN0YW5jZW9mIFBvbHlnb24gJiYgYm91bmRzLmhvbGVzPy5sZW5ndGgpXG4gICAgICAgID8gYm91bmRzLmhvbGVzIDogbnVsbDtcbiAgICAgIGlmIChpc0JlemllciB8fCBob2xlcykge1xuICAgICAgICBlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhTVkdOUywgJ3BhdGgnKTtcbiAgICAgICAgLy8gRXh0ZXJpb3Igc3VicGF0aCAoc21vb3RoIGZvciBiZXppZXIsIHN0cmFpZ2h0IG90aGVyd2lzZSkgZm9sbG93ZWQgYnkgYVxuICAgICAgICAvLyBzdHJhaWdodCBzdWJwYXRoIHBlciBob2xlLlxuICAgICAgICBsZXQgZCA9IGlzQmV6aWVyID8gdGhpcy5iZXppZXJQYXRoRChib3VuZHMgYXMgUG9seWdvbikgOiB0aGlzLnN0cmFpZ2h0UGF0aEQocHRzLCBjbG9zZWQpO1xuICAgICAgICBpZiAoaG9sZXMpIHtcbiAgICAgICAgICBjb25zdCBwb2x5ID0gYm91bmRzIGFzIFBvbHlnb247XG4gICAgICAgICAgaG9sZXMuZm9yRWFjaCgocmluZywgaGkpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHhzID0gcmluZy5tYXAoKHApID0+IHBbMF0pO1xuICAgICAgICAgICAgY29uc3QgeXMgPSByaW5nLm1hcCgocCkgPT4gcFsxXSk7XG4gICAgICAgICAgICAvLyBXaGVuIHRoZSBkb251dCBpcyBhIGJlemllciwgc21vb3RoIGl0cyBob2xlcyB0b28gKGppdC11aSMxMDIpIOKAlCB1c2luZyBzdG9yZWQgaG9sZVxuICAgICAgICAgICAgLy8gaGFuZGxlcyB3aGVuIHByZXNlbnQsIGVsc2UgdGhlIENhdG11bGwtUm9tIGRlZmF1bHQgKHZpYSByZXNvbHZlSGFuZGxlcykuXG4gICAgICAgICAgICBkICs9XG4gICAgICAgICAgICAgICcgJyArXG4gICAgICAgICAgICAgIChpc0JlemllclxuICAgICAgICAgICAgICAgID8gdGhpcy5yaW5nQmV6aWVyUGF0aEQoeHMsIHlzLCBwb2x5LmhvbGVIYW5kbGVzSW4/LltoaV0sIHBvbHkuaG9sZUhhbmRsZXNPdXQ/LltoaV0sIHRydWUpXG4gICAgICAgICAgICAgICAgOiB0aGlzLnN0cmFpZ2h0UGF0aEQocmluZy5tYXAoKFt4LCB5XSkgPT4gKHsgeCwgeSB9KSksIHRydWUpKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBlbC5zZXRBdHRyaWJ1dGUoJ2ZpbGwtcnVsZScsICdldmVub2RkJyk7XG4gICAgICAgIH1cbiAgICAgICAgZWwuc2V0QXR0cmlidXRlKCdkJywgZCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhTVkdOUywgY2xvc2VkID8gJ3BvbHlnb24nIDogJ3BvbHlsaW5lJyk7XG4gICAgICAgIGVsLnNldEF0dHJpYnV0ZSgncG9pbnRzJywgcHRzLm1hcChwID0+IHsgY29uc3QgcSA9IHRoaXMudG9QeChwLngsIHAueSk7IHJldHVybiBgJHtxLnh9LCR7cS55fWA7IH0pLmpvaW4oJyAnKSk7XG4gICAgICB9XG4gICAgfVxuICAgIGVsLnNldEF0dHJpYnV0ZSgnZmlsbCcsIHNlbGVjdGVkID8gdGhpcy5yZ2JhKGNvbG9yLCAwLjM1KSA6ICdub25lJyk7XG4gICAgZWwuc2V0QXR0cmlidXRlKCdzdHJva2UnLCBjb2xvcik7XG4gICAgZWwuc2V0QXR0cmlidXRlKCdzdHJva2Utd2lkdGgnLCBzZWxlY3RlZCA/ICc0JyA6ICcyJyk7XG5cbiAgICAvLyBUaGUgY2xhc3MgbGFiZWwgKGxlZ2VuZCksIHNob3duIHdoZW4gdGhlIFJlZ2lvbiBFZGl0b3IncyBcInNob3cgbGFiZWxzXCIgaXNcbiAgICAvLyBvbiDigJQgbWlycm9ycyBQbG90bHkncyBwZXItc2hhcGUgbGFiZWwgKHRvcC1sZWZ0LCBkcmF3biBpbiB0aGUgcmVnaW9uJ3NcbiAgICAvLyBjb2xvdXIpLiBXaXRob3V0IHRoaXMgT1NEIHNob3dlZCByZWdpb25zIHdpdGggbm8gbGFiZWwgZXZlbiB0aG91Z2ggUGxvdGx5XG4gICAgLy8gZGlkLiByZWdpb24ubGFiZWwgaXMgcmVzdG9yZWQgZnJvbSB0aGUgc2hhcGUncyBsZWdlbmQgaW4gZ2V0UmVnaW9uKCkuXG4gICAgY29uc3QgbGFiZWwgPSByZWdpb24ubGFiZWw7XG4gICAgaWYgKHRoaXMuc3RvcmUuZ2V0U2hvd1NoYXBlTGFiZWwoKSAmJiBsYWJlbCAhPSBudWxsICYmIGAke2xhYmVsfWAubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3QgZyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhTVkdOUywgJ2cnKTtcbiAgICAgIGcuYXBwZW5kQ2hpbGQoZWwpO1xuICAgICAgY29uc3QgbWluWCA9IE1hdGgubWluKC4uLnB0cy5tYXAocCA9PiBwLngpKTtcbiAgICAgIGNvbnN0IG1pblkgPSBNYXRoLm1pbiguLi5wdHMubWFwKHAgPT4gcC55KSk7XG4gICAgICBjb25zdCBxID0gdGhpcy50b1B4KG1pblgsIG1pblkpO1xuICAgICAgY29uc3QgdGV4dCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhTVkdOUywgJ3RleHQnKTtcbiAgICAgIHRleHQuc2V0QXR0cmlidXRlKCd4JywgYCR7cS54fWApO1xuICAgICAgdGV4dC5zZXRBdHRyaWJ1dGUoJ3knLCBgJHtxLnkgLSA0fWApOyAvLyBqdXN0IGFib3ZlIHRoZSB0b3AtbGVmdCBjb3JuZXJcbiAgICAgIHRleHQuc2V0QXR0cmlidXRlKCdmaWxsJywgY29sb3IpO1xuICAgICAgdGV4dC5zZXRBdHRyaWJ1dGUoJ2ZvbnQtc2l6ZScsICcxMycpO1xuICAgICAgdGV4dC5zZXRBdHRyaWJ1dGUoJ2ZvbnQtZmFtaWx5JywgJ3NhbnMtc2VyaWYnKTtcbiAgICAgIC8vIERhcmsgaGFsbyBzbyB0aGUgbGFiZWwgc3RheXMgbGVnaWJsZSBvdmVyIGJvdGggYnJpZ2h0IGFuZCBkYXJrIHRpbGVzLlxuICAgICAgdGV4dC5zZXRBdHRyaWJ1dGUoJ3BhaW50LW9yZGVyJywgJ3N0cm9rZScpO1xuICAgICAgdGV4dC5zZXRBdHRyaWJ1dGUoJ3N0cm9rZScsICdyZ2JhKDAsMCwwLDAuNjUpJyk7XG4gICAgICB0ZXh0LnNldEF0dHJpYnV0ZSgnc3Ryb2tlLXdpZHRoJywgJzInKTtcbiAgICAgIHRleHQudGV4dENvbnRlbnQgPSBgJHtsYWJlbH1gO1xuICAgICAgZy5hcHBlbmRDaGlsZCh0ZXh0KTtcbiAgICAgIHJldHVybiBnO1xuICAgIH1cbiAgICByZXR1cm4gZWw7XG4gIH1cblxuICAvKiogTWFycXVlZSByZWN0YW5nbGUgZm9yIHJ1YmJlci1iYW5kIG11bHRpLXNlbGVjdCAoZGFzaGVkIG91dGxpbmUgKyBmYWludCBmaWxsKS4gKi9cbiAgcHJpdmF0ZSBzZWxlY3Rpb25CYW5kKGE6IHsgeDogbnVtYmVyOyB5OiBudW1iZXIgfSwgYjogeyB4OiBudW1iZXI7IHk6IG51bWJlciB9KTogU1ZHRWxlbWVudCB7XG4gICAgY29uc3QgY29ybmVycyA9IFtcbiAgICAgIHsgeDogYS54LCB5OiBhLnkgfSwgeyB4OiBiLngsIHk6IGEueSB9LCB7IHg6IGIueCwgeTogYi55IH0sIHsgeDogYS54LCB5OiBiLnkgfSxcbiAgICBdO1xuICAgIGNvbnN0IGVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKFNWR05TLCAncG9seWdvbicpO1xuICAgIGVsLnNldEF0dHJpYnV0ZSgncG9pbnRzJywgY29ybmVycy5tYXAocCA9PiB7IGNvbnN0IHEgPSB0aGlzLnRvUHgocC54LCBwLnkpOyByZXR1cm4gYCR7cS54fSwke3EueX1gOyB9KS5qb2luKCcgJykpO1xuICAgIGVsLnNldEF0dHJpYnV0ZSgnZmlsbCcsICdyZ2JhKDEyMCwxNzAsMjU1LDAuMTUpJyk7XG4gICAgZWwuc2V0QXR0cmlidXRlKCdzdHJva2UnLCAnIzRhOTBlMicpO1xuICAgIGVsLnNldEF0dHJpYnV0ZSgnc3Ryb2tlLWRhc2hhcnJheScsICc0IDMnKTtcbiAgICBlbC5zZXRBdHRyaWJ1dGUoJ3N0cm9rZS13aWR0aCcsICcxJyk7XG4gICAgcmV0dXJuIGVsO1xuICB9XG5cbiAgcHJpdmF0ZSByZWN0UHJldmlldyhhOiB7IHg6IG51bWJlcjsgeTogbnVtYmVyIH0sIGI6IHsgeDogbnVtYmVyOyB5OiBudW1iZXIgfSk6IFNWR0VsZW1lbnQge1xuICAgIGNvbnN0IGNvcm5lcnMgPSBbXG4gICAgICB7IHg6IGEueCwgeTogYS55IH0sIHsgeDogYi54LCB5OiBhLnkgfSwgeyB4OiBiLngsIHk6IGIueSB9LCB7IHg6IGEueCwgeTogYi55IH0sXG4gICAgXTtcbiAgICBjb25zdCBlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhTVkdOUywgJ3BvbHlnb24nKTtcbiAgICBlbC5zZXRBdHRyaWJ1dGUoJ3BvaW50cycsIGNvcm5lcnMubWFwKHAgPT4geyBjb25zdCBxID0gdGhpcy50b1B4KHAueCwgcC55KTsgcmV0dXJuIGAke3EueH0sJHtxLnl9YDsgfSkuam9pbignICcpKTtcbiAgICBlbC5zZXRBdHRyaWJ1dGUoJ2ZpbGwnLCAnbm9uZScpO1xuICAgIGVsLnNldEF0dHJpYnV0ZSgnc3Ryb2tlJywgdGhpcy5zdG9yZS5nZXRTaGFwZUNvbG9yKCkpO1xuICAgIGVsLnNldEF0dHJpYnV0ZSgnc3Ryb2tlLWRhc2hhcnJheScsICc0IDMnKTtcbiAgICBlbC5zZXRBdHRyaWJ1dGUoJ3N0cm9rZS13aWR0aCcsICcyJyk7XG4gICAgcmV0dXJuIGVsO1xuICB9XG5cbiAgcHJpdmF0ZSBwb2x5UHJldmlldyhwdHM6IHsgeDogbnVtYmVyOyB5OiBudW1iZXIgfVtdKTogU1ZHRWxlbWVudCB7XG4gICAgY29uc3QgZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoU1ZHTlMsICdwb2x5bGluZScpO1xuICAgIGVsLnNldEF0dHJpYnV0ZSgncG9pbnRzJywgcHRzLm1hcChwID0+IHsgY29uc3QgcSA9IHRoaXMudG9QeChwLngsIHAueSk7IHJldHVybiBgJHtxLnh9LCR7cS55fWA7IH0pLmpvaW4oJyAnKSk7XG4gICAgZWwuc2V0QXR0cmlidXRlKCdmaWxsJywgJ25vbmUnKTtcbiAgICBlbC5zZXRBdHRyaWJ1dGUoJ3N0cm9rZScsIHRoaXMuc3RvcmUuZ2V0U2hhcGVDb2xvcigpKTtcbiAgICBlbC5zZXRBdHRyaWJ1dGUoJ3N0cm9rZS1kYXNoYXJyYXknLCAnNCAzJyk7XG4gICAgZWwuc2V0QXR0cmlidXRlKCdzdHJva2Utd2lkdGgnLCAnMicpO1xuICAgIHJldHVybiBlbDtcbiAgfVxuXG4gIC8qKiBTVkcgcGF0aCBgZGAgKGVsZW1lbnQtcGl4ZWwgY29vcmRzKSBmb3IgYSBzdHJhaWdodC1lZGdlZCByaW5nL3BvbHlsaW5lLiAqL1xuICBwcml2YXRlIHN0cmFpZ2h0UGF0aEQocHRzOiB7IHg6IG51bWJlcjsgeTogbnVtYmVyIH1bXSwgY2xvc2VkOiBib29sZWFuKTogc3RyaW5nIHtcbiAgICBpZiAocHRzLmxlbmd0aCA8IDIpIHJldHVybiAnJztcbiAgICBsZXQgZCA9ICcnO1xuICAgIHB0cy5mb3JFYWNoKChwLCBpKSA9PiB7XG4gICAgICBjb25zdCBxID0gdGhpcy50b1B4KHAueCwgcC55KTtcbiAgICAgIGQgKz0gKGkgPT09IDAgPyAnTSAnIDogJyBMICcpICsgYCR7cS54fSwke3EueX1gO1xuICAgIH0pO1xuICAgIGlmIChjbG9zZWQpIGQgKz0gJyBaJztcbiAgICByZXR1cm4gZDtcbiAgfVxuXG4gIC8qKiBTVkcgcGF0aCBgZGAgKGVsZW1lbnQtcGl4ZWwgY29vcmRzKSBmb3IgdGhlIHNtb290aCBjdWJpYyBiZXppZXIgdGhyb3VnaCBhXG4gICAqICBwb2x5Z29uJ3MgYW5jaG9ycyDigJQgdGhlIHBhcGVyLmpzLWVxdWl2YWxlbnQgY3VydmUuICovXG4gIHByaXZhdGUgYmV6aWVyUGF0aEQocG9seTogUG9seWdvbik6IHN0cmluZyB7XG4gICAgY29uc3QgY2xvc2VkID0gcG9seS5jbG9zZWQgIT09IGZhbHNlO1xuICAgIHJldHVybiB0aGlzLnJpbmdCZXppZXJQYXRoRChwb2x5Lnhwb2ludHMsIHBvbHkueXBvaW50cywgcG9seS5oYW5kbGVzSW4sIHBvbHkuaGFuZGxlc091dCwgY2xvc2VkKTtcbiAgfVxuXG4gIC8qKiBTVkcgY3ViaWMtYmV6aWVyIHBhdGggYGRgIChlbGVtZW50IHB4KSBmb3IgYW55IHJpbmcgKGV4dGVyaW9yIG9yIGhvbGUpLiBVc2VzIHRoZSBzdG9yZWRcbiAgICogIHBlci12ZXJ0ZXggaGFuZGxlIG9mZnNldHMgd2hlbiBwcmVzZW50LCBlbHNlIHRoZSBDYXRtdWxsLVJvbSBkZWZhdWx0IChyZXNvbHZlSGFuZGxlcykuICovXG4gIHByaXZhdGUgcmluZ0JlemllclBhdGhEKFxuICAgIHhzOiBudW1iZXJbXSwgeXM6IG51bWJlcltdLCBpbk9mZjogbnVtYmVyW11bXSB8IHVuZGVmaW5lZCwgb3V0T2ZmOiBudW1iZXJbXVtdIHwgdW5kZWZpbmVkLCBjbG9zZWQ6IGJvb2xlYW4sXG4gICk6IHN0cmluZyB7XG4gICAgY29uc3QgbiA9IE1hdGgubWluKHhzLmxlbmd0aCwgeXMubGVuZ3RoKTtcbiAgICBpZiAobiA8IDIpIHJldHVybiAnJztcbiAgICBjb25zdCBoID0gcmVzb2x2ZUhhbmRsZXMoeHMsIHlzLCBjbG9zZWQsIGluT2ZmLCBvdXRPZmYpO1xuICAgIGNvbnN0IHB4ID0gKHg6IG51bWJlciwgeTogbnVtYmVyKSA9PiB7IGNvbnN0IHEgPSB0aGlzLnRvUHgoeCwgeSk7IHJldHVybiBgJHtxLnh9LCR7cS55fWA7IH07XG4gICAgbGV0IGQgPSBgTSAke3B4KHhzWzBdLCB5c1swXSl9YDtcbiAgICBjb25zdCBzZWdzID0gY2xvc2VkID8gbiA6IG4gLSAxO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2VnczsgaSsrKSB7XG4gICAgICBjb25zdCBqID0gKGkgKyAxKSAlIG47XG4gICAgICBjb25zdCBjMSA9IGhbaV0ub3V0O1xuICAgICAgY29uc3QgYzIgPSBoW2pdLmluO1xuICAgICAgZCArPSBgIEMgJHtweChjMVswXSwgYzFbMV0pfSAke3B4KGMyWzBdLCBjMlsxXSl9ICR7cHgoeHNbal0sIHlzW2pdKX1gO1xuICAgIH1cbiAgICBpZiAoY2xvc2VkKSBkICs9ICcgWic7XG4gICAgcmV0dXJuIGQ7XG4gIH1cblxuICAvKipcbiAgICogRHJhdyB0aGUgYmV6aWVyIGVkaXRpbmcgaGFuZGxlcyBmb3IgdGhlIHNlbGVjdGVkIHJlZ2lvbiwgcGFwZXIuanMtc3R5bGU6XG4gICAqIGVhY2ggYW5jaG9yIGFzIGEgc21hbGwgc3F1YXJlLCB3aXRoIHRhbmdlbnQgbGluZXMgb3V0IHRvIGl0cyB0d28gY29udHJvbFxuICAgKiBwb2ludHMgKGRyYXduIGFzIHNtYWxsIGNpcmNsZXMpLlxuICAgKi9cbiAgcHJpdmF0ZSBkcmF3QmV6aWVySGFuZGxlcyhwb2x5OiBQb2x5Z29uLCBjb2xvcjogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgeHMgPSBwb2x5Lnhwb2ludHM7XG4gICAgY29uc3QgeXMgPSBwb2x5Lnlwb2ludHM7XG4gICAgY29uc3QgZHJhd1JpbmcgPSAocnhzOiBudW1iZXJbXSwgcnlzOiBudW1iZXJbXSwgaW5PZmY6IG51bWJlcltdW10gfCB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgICAgICAgb3V0T2ZmOiBudW1iZXJbXVtdIHwgdW5kZWZpbmVkLCBjbG9zZWQ6IGJvb2xlYW4pOiB2b2lkID0+IHtcbiAgICAgIGNvbnN0IGggPSByZXNvbHZlSGFuZGxlcyhyeHMsIHJ5cywgY2xvc2VkLCBpbk9mZiwgb3V0T2ZmKTtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcnhzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGEgPSB0aGlzLnRvUHgocnhzW2ldLCByeXNbaV0pO1xuICAgICAgICBpZiAoaFtpXS5oYXNJbikgdGhpcy5kcmF3SGFuZGxlKGEsIHRoaXMudG9QeChoW2ldLmluWzBdLCBoW2ldLmluWzFdKSwgY29sb3IpO1xuICAgICAgICBpZiAoaFtpXS5oYXNPdXQpIHRoaXMuZHJhd0hhbmRsZShhLCB0aGlzLnRvUHgoaFtpXS5vdXRbMF0sIGhbaV0ub3V0WzFdKSwgY29sb3IpO1xuICAgICAgICB0aGlzLnN2Zy5hcHBlbmRDaGlsZCh0aGlzLmFuY2hvclNxdWFyZShhLngsIGEueSwgY29sb3IpKTtcbiAgICAgIH1cbiAgICB9O1xuICAgIGRyYXdSaW5nKHhzLCB5cywgcG9seS5oYW5kbGVzSW4sIHBvbHkuaGFuZGxlc091dCwgcG9seS5jbG9zZWQgIT09IGZhbHNlKTtcbiAgICAvLyBEb251dCBob2xlIHJpbmdzIGdldCB0aGVpciBvd24gZWRpdGFibGUgYmV6aWVyIGhhbmRsZXMgKGppdC11aSMxMDIpLlxuICAgIGlmIChwb2x5LmhvbGVzICYmIHBvbHkuaG9sZUhhbmRsZXNJbiAmJiBwb2x5LmhvbGVIYW5kbGVzT3V0KSB7XG4gICAgICBwb2x5LmhvbGVzLmZvckVhY2goKHJpbmcsIGhpKSA9PiB7XG4gICAgICAgIGNvbnN0IGluT2ZmID0gcG9seS5ob2xlSGFuZGxlc0luIVtoaV07XG4gICAgICAgIGNvbnN0IG91dE9mZiA9IHBvbHkuaG9sZUhhbmRsZXNPdXQhW2hpXTtcbiAgICAgICAgaWYgKGluT2ZmICYmIG91dE9mZikgZHJhd1JpbmcocmluZy5tYXAoKHApID0+IHBbMF0pLCByaW5nLm1hcCgocCkgPT4gcFsxXSksIGluT2ZmLCBvdXRPZmYsIHRydWUpO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgLyoqIEEgdGFuZ2VudCBsaW5lIGZyb20gYW4gYW5jaG9yIHRvIGEgY29udHJvbCBwb2ludCwgd2l0aCBhIGNpcmNsZSBhdCB0aGUgZW5kLiAqL1xuICBwcml2YXRlIGRyYXdIYW5kbGUoYW5jaG9yOiB7IHg6IG51bWJlcjsgeTogbnVtYmVyIH0sIGN0cmw6IHsgeDogbnVtYmVyOyB5OiBudW1iZXIgfSwgY29sb3I6IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IGxpbmUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoU1ZHTlMsICdsaW5lJyk7XG4gICAgbGluZS5zZXRBdHRyaWJ1dGUoJ3gxJywgYCR7YW5jaG9yLnh9YCk7IGxpbmUuc2V0QXR0cmlidXRlKCd5MScsIGAke2FuY2hvci55fWApO1xuICAgIGxpbmUuc2V0QXR0cmlidXRlKCd4MicsIGAke2N0cmwueH1gKTsgbGluZS5zZXRBdHRyaWJ1dGUoJ3kyJywgYCR7Y3RybC55fWApO1xuICAgIGxpbmUuc2V0QXR0cmlidXRlKCdzdHJva2UnLCBjb2xvcik7XG4gICAgbGluZS5zZXRBdHRyaWJ1dGUoJ3N0cm9rZS13aWR0aCcsICcxJyk7XG4gICAgdGhpcy5zdmcuYXBwZW5kQ2hpbGQobGluZSk7XG4gICAgY29uc3QgYyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhTVkdOUywgJ2NpcmNsZScpO1xuICAgIGMuc2V0QXR0cmlidXRlKCdjeCcsIGAke2N0cmwueH1gKTsgYy5zZXRBdHRyaWJ1dGUoJ2N5JywgYCR7Y3RybC55fWApO1xuICAgIGMuc2V0QXR0cmlidXRlKCdyJywgJzMnKTtcbiAgICBjLnNldEF0dHJpYnV0ZSgnZmlsbCcsIGNvbG9yKTtcbiAgICB0aGlzLnN2Zy5hcHBlbmRDaGlsZChjKTtcbiAgfVxuXG4gIC8qKiBBIGZpbGxlZC13aGl0ZSBhbmNob3Igc3F1YXJlICh0aGUgZWRpdGFibGUgdmVydGV4KS4gKi9cbiAgcHJpdmF0ZSBhbmNob3JTcXVhcmUoeDogbnVtYmVyLCB5OiBudW1iZXIsIGNvbG9yOiBzdHJpbmcpOiBTVkdFbGVtZW50IHtcbiAgICBjb25zdCByID0gMy41O1xuICAgIGNvbnN0IHJlY3QgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoU1ZHTlMsICdyZWN0Jyk7XG4gICAgcmVjdC5zZXRBdHRyaWJ1dGUoJ3gnLCBgJHt4IC0gcn1gKTsgcmVjdC5zZXRBdHRyaWJ1dGUoJ3knLCBgJHt5IC0gcn1gKTtcbiAgICByZWN0LnNldEF0dHJpYnV0ZSgnd2lkdGgnLCBgJHsyICogcn1gKTsgcmVjdC5zZXRBdHRyaWJ1dGUoJ2hlaWdodCcsIGAkezIgKiByfWApO1xuICAgIHJlY3Quc2V0QXR0cmlidXRlKCdmaWxsJywgJyNmZmZmZmYnKTtcbiAgICByZWN0LnNldEF0dHJpYnV0ZSgnc3Ryb2tlJywgY29sb3IpO1xuICAgIHJlY3Quc2V0QXR0cmlidXRlKCdzdHJva2Utd2lkdGgnLCAnMicpO1xuICAgIHJldHVybiByZWN0O1xuICB9XG5cbiAgcHJpdmF0ZSByZ2JhKGNvbG9yOiBzdHJpbmcsIGFscGhhOiBudW1iZXIpOiBzdHJpbmcge1xuICAgIC8vIEFjY2VwdCAjcnJnZ2JiOyBmYWxsIGJhY2sgdG8gdGhlIGNvbG9yIGFzLWlzIGZvciBuYW1lZC9yZ2IgdmFsdWVzLlxuICAgIGlmICgvXiMoWzAtOWEtZl17Nn0pJC9pLnRlc3QoY29sb3IpKSB7XG4gICAgICBjb25zdCByID0gcGFyc2VJbnQoY29sb3Iuc2xpY2UoMSwgMyksIDE2KTtcbiAgICAgIGNvbnN0IGcgPSBwYXJzZUludChjb2xvci5zbGljZSgzLCA1KSwgMTYpO1xuICAgICAgY29uc3QgYiA9IHBhcnNlSW50KGNvbG9yLnNsaWNlKDUsIDcpLCAxNik7XG4gICAgICByZXR1cm4gYHJnYmEoJHtyfSwke2d9LCR7Yn0sJHthbHBoYX0pYDtcbiAgICB9XG4gICAgcmV0dXJuIGNvbG9yO1xuICB9XG5cbiAgLy8g4pSA4pSAIGludGVyYWN0aW9uIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuICBwcml2YXRlIGdldCBpc0ZyZWVoYW5kKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLm1vZGUgPT09ICdkcmF3Y2xvc2VkcGF0aCcgfHwgdGhpcy5tb2RlID09PSAnZHJhd29wZW5wYXRoJztcbiAgfVxuXG4gIHByaXZhdGUgb25QcmVzcyhlOiBhbnkpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5tb2RlID09PSAnZHJhd3JlY3QnKSB7XG4gICAgICB0aGlzLnJlY3RTdGFydCA9IHRoaXMudG9JbWFnZShlLnBvc2l0aW9uKTtcbiAgICAgIHRoaXMucmVjdEN1cnJlbnQgPSB0aGlzLnJlY3RTdGFydDtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHRoaXMuaXNGcmVlaGFuZCkge1xuICAgICAgLy8gRnJlZWhhbmQgZHJhdyAobWF0Y2hlcyBQbG90bHkgZHJhd2Nsb3NlZHBhdGgvZHJhd29wZW5wYXRoKTogcHJlc3MgdG9cbiAgICAgIC8vIHN0YXJ0LCBkcmFnIHRvIHRyYWNlLCByZWxlYXNlIHRvIGNvbW1pdC5cbiAgICAgIHRoaXMuZnJlZWhhbmREcmFnZ2luZyA9IHRydWU7XG4gICAgICB0aGlzLnBvbHlQb2ludHMgPSBbdGhpcy50b0ltYWdlKGUucG9zaXRpb24pXTtcbiAgICAgIHRoaXMubGFzdEZyZWVoYW5kUHggPSB7IHg6IGUucG9zaXRpb24ueCwgeTogZS5wb3NpdGlvbi55IH07XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICh0aGlzLm1vZGUgPT09ICdtb3ZlJykge1xuICAgICAgLy8gV2hvbGUtcmVnaW9uIGRyYWcgKCdtb3ZlJyBtb2RlKTogcHJlc3MgaW5zaWRlIHRoZSBzZWxlY3RlZCByZWdpb25cbiAgICAgIC8vIHRvIHRyYW5zbGF0ZSBpdCwgaWdub3JpbmcgdmVydGljZXMvZWRnZXMuXG4gICAgICBjb25zdCBzZWwgPSB0aGlzLnNlbGVjdGVkUmVnaW9uSW5mbygpO1xuICAgICAgaWYgKHNlbCAmJiB0aGlzLmNvbnRhaW5zUG9pbnQoc2VsLnJlZ2lvbiwgdGhpcy50b0ltYWdlKGUucG9zaXRpb24pKSkge1xuICAgICAgICB0aGlzLnN0YXJ0RWRpdCgnYm91bmRzJywgJ21vdmUnLCAtMSwgc2VsLnJlZ2lvbiwgdGhpcy50b0ltYWdlKGUucG9zaXRpb24pKTtcbiAgICAgIH1cbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHRoaXMubW9kZSA9PT0gJ3NlbGVjdCcpIHtcbiAgICAgIC8vIEEgYmV6aWVyIGNvbnRyb2wgaGFuZGxlIHRha2VzIHRvcCBwcmlvcml0eSAoaXQgc2l0cyBvZmYgdGhlIGFuY2hvcikuXG4gICAgICBjb25zdCBoaCA9IHRoaXMuaGl0QmV6aWVySGFuZGxlKGUucG9zaXRpb24pO1xuICAgICAgaWYgKGhoKSB7XG4gICAgICAgIGNvbnN0IHJlZ2lvbiA9IHRoaXMuc3RvcmUuZ2V0UmVnaW9ucygpW3RoaXMuc2VsZWN0ZWRbdGhpcy5zZWxlY3RlZC5sZW5ndGggLSAxXV07XG4gICAgICAgIHRoaXMuc3RhcnRFZGl0KCdoYW5kbGUnLCAnbW92ZScsIGhoLmluZGV4LCByZWdpb24sIHRoaXMudG9JbWFnZShlLnBvc2l0aW9uKSwgaGguc2lkZSwgaGgucmluZyk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIC8vIFRoZW4gZHJhZ2dpbmcgYSBzaW5nbGUgcG9seWdvbiB2ZXJ0ZXggKG92ZXIgYm9keS1tb3ZlL3Jlc2l6ZSkg4oCUXG4gICAgICAvLyAnc2VsZWN0JyBncmFicyB0aGUgbmVhcmVzdCBzZWdtZW50IGZpcnN0LlxuICAgICAgY29uc3QgdmggPSB0aGlzLmhpdFZlcnRleChlLnBvc2l0aW9uKTtcbiAgICAgIGlmICh2aCkge1xuICAgICAgICBjb25zdCByZWdpb24gPSB0aGlzLnN0b3JlLmdldFJlZ2lvbnMoKVt0aGlzLnNlbGVjdGVkW3RoaXMuc2VsZWN0ZWQubGVuZ3RoIC0gMV1dO1xuICAgICAgICB0aGlzLnN0YXJ0RWRpdCgndmVydGV4JywgJ21vdmUnLCB2aC5pbmRleCwgcmVnaW9uLCB0aGlzLnRvSW1hZ2UoZS5wb3NpdGlvbiksICdvdXQnLCB2aC5yaW5nKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgLy8gT3RoZXJ3aXNlIHN0YXJ0IGEgbW92ZS9yZXNpemUgd2hlbiBwcmVzc2luZyB0aGUgc2VsZWN0ZWQgcmVnaW9uJ3NcbiAgICAgIC8vIGJvZHkvaGFuZGxlcy5cbiAgICAgIGNvbnN0IGV6ID0gdGhpcy5lZGl0Wm9uZUF0KGUucG9zaXRpb24pO1xuICAgICAgaWYgKGV6KSB7XG4gICAgICAgIHRoaXMuc3RhcnRFZGl0KCdib3VuZHMnLCBlei56b25lLCAtMSwgdGhpcy5zdG9yZS5nZXRSZWdpb25zKClbZXouaW5kZXhdLCB0aGlzLnRvSW1hZ2UoZS5wb3NpdGlvbikpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICAvLyBQcmVzcyBvbiBlbXB0eSBzcGFjZSAvIGEgbm9uLXNlbGVjdGVkIHJlZ2lvbjogYmVnaW4gYSBydWJiZXItYmFuZFxuICAgICAgLy8gbXVsdGktc2VsZWN0LiBBIHBsYWluIGNsaWNrIChubyBkcmFnKSBmYWxscyB0aHJvdWdoIHRvIG9uQ2xpY2ssIHdoaWNoXG4gICAgICAvLyBzaW5nbGUtc2VsZWN0cyBvciBjbGVhcnMuXG4gICAgICB0aGlzLmJhbmRTdGFydCA9IHRoaXMudG9JbWFnZShlLnBvc2l0aW9uKTtcbiAgICAgIHRoaXMuYmFuZEN1cnJlbnQgPSB0aGlzLmJhbmRTdGFydDtcbiAgICAgIHRoaXMuYmFuZERyYWdnZWQgPSBmYWxzZTtcbiAgICB9XG4gIH1cblxuICAvKiogQmVnaW4gYW4gZWRpdCBnZXN0dXJlIChtb3ZlL3Jlc2l6ZSBvciBzaW5nbGUtdmVydGV4IGRyYWcpIGFuZCBvcGVuIGEgc3RvcmVcbiAgICogIGJhdGNoIHNvIHRoZSBsaXZlIGRyYWcgZW1pdHMgb25jZSBvbiByZWxlYXNlLiAqL1xuICBwcml2YXRlIHN0YXJ0RWRpdChraW5kOiAnYm91bmRzJyB8ICd2ZXJ0ZXgnIHwgJ2hhbmRsZScsIHpvbmU6IEVkaXRab25lLCB2ZXJ0ZXhJbmRleDogbnVtYmVyLFxuICAgICAgICAgICAgICAgICAgICByZWdpb246IFJlZ2lvbiwgc3RhcnRJbWc6IHsgeDogbnVtYmVyOyB5OiBudW1iZXIgfSxcbiAgICAgICAgICAgICAgICAgICAgaGFuZGxlU2lkZTogJ2luJyB8ICdvdXQnID0gJ291dCcsIHJpbmcgPSAtMSk6IHZvaWQge1xuICAgIHRoaXMuZWRpdCA9IHtcbiAgICAgIGtpbmQsIHpvbmUsIHZlcnRleEluZGV4LCByaW5nLCBoYW5kbGVTaWRlLCBpZDogcmVnaW9uLmlkLFxuICAgICAgc3RhcnRJbWcsIG9yaWc6IGtpbmQgPT09ICdib3VuZHMnID8gdGhpcy5zbmFwc2hvdChyZWdpb24pIDogbnVsbCxcbiAgICB9O1xuICAgIHRoaXMuZWRpdERyYWdnZWQgPSBmYWxzZTtcbiAgICB0aGlzLnN0b3JlLmJlZ2luQmF0Y2goKTtcbiAgfVxuXG4gIHByaXZhdGUgb25EcmFnKGU6IGFueSk6IHZvaWQge1xuICAgIGlmICh0aGlzLm1vZGUgPT09ICdkcmF3cmVjdCcgJiYgdGhpcy5yZWN0U3RhcnQpIHtcbiAgICAgIHRoaXMucmVjdEN1cnJlbnQgPSB0aGlzLnRvSW1hZ2UoZS5wb3NpdGlvbik7XG4gICAgICB0aGlzLnJlZHJhdygpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAodGhpcy5mcmVlaGFuZERyYWdnaW5nICYmIHRoaXMuaXNGcmVlaGFuZCkge1xuICAgICAgLy8gVGhpbiB0aGUgcGF0aDogb25seSBzYW1wbGUgb25jZSB0aGUgY3Vyc29yIGhhcyBtb3ZlZCBhIGZldyBzY3JlZW4gcHguXG4gICAgICBjb25zdCBsYXN0ID0gdGhpcy5sYXN0RnJlZWhhbmRQeDtcbiAgICAgIGlmICghbGFzdCB8fCBNYXRoLmh5cG90KGUucG9zaXRpb24ueCAtIGxhc3QueCwgZS5wb3NpdGlvbi55IC0gbGFzdC55KSA+PSA0KSB7XG4gICAgICAgIHRoaXMucG9seVBvaW50cy5wdXNoKHRoaXMudG9JbWFnZShlLnBvc2l0aW9uKSk7XG4gICAgICAgIHRoaXMubGFzdEZyZWVoYW5kUHggPSB7IHg6IGUucG9zaXRpb24ueCwgeTogZS5wb3NpdGlvbi55IH07XG4gICAgICAgIHRoaXMucmVkcmF3KCk7XG4gICAgICB9XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICh0aGlzLmVkaXQpIHtcbiAgICAgIHRoaXMuZWRpdERyYWdnZWQgPSB0cnVlO1xuICAgICAgdGhpcy5hcHBseUVkaXQodGhpcy50b0ltYWdlKGUucG9zaXRpb24pKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHRoaXMuYmFuZFN0YXJ0KSB7XG4gICAgICB0aGlzLmJhbmRDdXJyZW50ID0gdGhpcy50b0ltYWdlKGUucG9zaXRpb24pO1xuICAgICAgdGhpcy5iYW5kRHJhZ2dlZCA9IHRydWU7XG4gICAgICB0aGlzLnJlZHJhdygpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgb25SZWxlYXNlKGU6IGFueSk6IHZvaWQge1xuICAgIGlmICh0aGlzLm1vZGUgPT09ICdkcmF3cmVjdCcgJiYgdGhpcy5yZWN0U3RhcnQpIHtcbiAgICAgIGNvbnN0IGVuZCA9IHRoaXMudG9JbWFnZShlLnBvc2l0aW9uKTtcbiAgICAgIGNvbnN0IHggPSBNYXRoLm1pbih0aGlzLnJlY3RTdGFydC54LCBlbmQueCk7XG4gICAgICBjb25zdCB5ID0gTWF0aC5taW4odGhpcy5yZWN0U3RhcnQueSwgZW5kLnkpO1xuICAgICAgY29uc3QgdyA9IE1hdGguYWJzKGVuZC54IC0gdGhpcy5yZWN0U3RhcnQueCk7XG4gICAgICBjb25zdCBoID0gTWF0aC5hYnMoZW5kLnkgLSB0aGlzLnJlY3RTdGFydC55KTtcbiAgICAgIHRoaXMucmVjdFN0YXJ0ID0gdGhpcy5yZWN0Q3VycmVudCA9IG51bGw7XG4gICAgICBpZiAodyA+IDIgJiYgaCA+IDIpIHRoaXMuY29tbWl0UmVjdGFuZ2xlKHgsIHksIHcsIGgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAodGhpcy5mcmVlaGFuZERyYWdnaW5nKSB7XG4gICAgICB0aGlzLmZyZWVoYW5kRHJhZ2dpbmcgPSBmYWxzZTtcbiAgICAgIHRoaXMubGFzdEZyZWVoYW5kUHggPSBudWxsO1xuICAgICAgLy8gQ2xvc2VkID0gZnJlZWZvcm0gKGRyYXdjbG9zZWRwYXRoKTsgb3BlbiA9IHBvbHlsaW5lIChkcmF3b3BlbnBhdGgpLlxuICAgICAgdGhpcy5jb21taXRQb2x5Z29uKHRoaXMubW9kZSA9PT0gJ2RyYXdjbG9zZWRwYXRoJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIC8vIE1vdmUvcmVzaXplIGFscmVhZHkgYXBwbGllZCBsaXZlOyBmbHVzaCB0aGUgY29hbGVzY2VkIGVkaXRzICsgZW5kIHRoZVxuICAgIC8vIGdlc3R1cmUgKGtlZXAgc2VsZWN0aW9uKS5cbiAgICBpZiAodGhpcy5lZGl0KSB7XG4gICAgICB0aGlzLnN0b3JlLmVuZEJhdGNoKCk7XG4gICAgICB0aGlzLmVkaXQgPSBudWxsO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyBGaW5pc2ggYSBydWJiZXItYmFuZCBzZWxlY3Rpb246IHNlbGVjdCBldmVyeSByZWdpb24gdGhlIGJhbmQgaW50ZXJzZWN0cy5cbiAgICBpZiAodGhpcy5iYW5kU3RhcnQpIHtcbiAgICAgIGNvbnN0IHN0YXJ0ID0gdGhpcy5iYW5kU3RhcnQ7XG4gICAgICBjb25zdCBlbmQgPSB0aGlzLmJhbmRDdXJyZW50ID8/IHN0YXJ0O1xuICAgICAgdGhpcy5iYW5kU3RhcnQgPSB0aGlzLmJhbmRDdXJyZW50ID0gbnVsbDtcbiAgICAgIGNvbnN0IHgwID0gTWF0aC5taW4oc3RhcnQueCwgZW5kLngpLCB5MCA9IE1hdGgubWluKHN0YXJ0LnksIGVuZC55KTtcbiAgICAgIGNvbnN0IHgxID0gTWF0aC5tYXgoc3RhcnQueCwgZW5kLngpLCB5MSA9IE1hdGgubWF4KHN0YXJ0LnksIGVuZC55KTtcbiAgICAgIC8vIE9ubHkgYSByZWFsIGRyYWcgc2VsZWN0czsgYSBjbGljay1zaXplZCBiYW5kIGZhbGxzIHRocm91Z2ggdG8gb25DbGljay5cbiAgICAgIGlmICh0aGlzLmJhbmREcmFnZ2VkICYmICh4MSAtIHgwID4gMiB8fCB5MSAtIHkwID4gMikpIHtcbiAgICAgICAgdGhpcy5zdG9yZS5zZXRTZWxlY3RlZFNoYXBlSW5kaWNlcyh0aGlzLnJlZ2lvbnNJblJlY3QoeDAsIHkwLCB4MSwgeTEpKTtcbiAgICAgIH1cbiAgICAgIHRoaXMucmVkcmF3KCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBvbkNsaWNrKGU6IGFueSk6IHZvaWQge1xuICAgIGlmICh0aGlzLm1vZGUgPT09ICdzZWxlY3QnKSB7XG4gICAgICAvLyBBIG1vdmUvcmVzaXplL3ZlcnRleCBkcmFnIG9yIGEgcnViYmVyLWJhbmQgZHJhZyBhbHNvIGVuZHMgd2l0aCBhIGNsaWNrXG4gICAgICAvLyBldmVudCDigJQgZG9uJ3QgdHJlYXQgaXQgYXMgYSByZS1zZWxlY3Rpb24uXG4gICAgICBpZiAodGhpcy5lZGl0RHJhZ2dlZCkgeyB0aGlzLmVkaXREcmFnZ2VkID0gZmFsc2U7IHJldHVybjsgfVxuICAgICAgaWYgKHRoaXMuYmFuZERyYWdnZWQpIHsgdGhpcy5iYW5kRHJhZ2dlZCA9IGZhbHNlOyByZXR1cm47IH1cbiAgICAgIC8vIFNoaWZ0IChvciBDbWQvQ3RybCkgdG9nZ2xlcyB0aGUgY2xpY2tlZCByZWdpb24gaW4vb3V0IG9mIHRoZSBjdXJyZW50XG4gICAgICAvLyBzZWxlY3Rpb247IGEgcGxhaW4gY2xpY2sgcmVwbGFjZXMgaXQuXG4gICAgICBjb25zdCBvZSA9IGUub3JpZ2luYWxFdmVudDtcbiAgICAgIGNvbnN0IGFkZGl0aXZlID0gISFvZSAmJiAob2Uuc2hpZnRLZXkgfHwgb2UubWV0YUtleSB8fCBvZS5jdHJsS2V5KTtcbiAgICAgIHRoaXMuc2VsZWN0QXQodGhpcy50b0ltYWdlKGUucG9zaXRpb24pLCBhZGRpdGl2ZSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICh0aGlzLm1vZGUgPT09ICdkcmF3cG9seWdvbicpIHtcbiAgICAgIHRoaXMub25EcmF3UG9seWdvbkNsaWNrKGUpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAodGhpcy5tb2RlID09PSAnYWRkcG9pbnQnKSB7XG4gICAgICAvLyBJbnNlcnQgYSB2ZXJ0ZXggb24gdGhlIGNsaWNrZWQgZWRnZSDigJQgZXh0ZXJpb3Igb3IgYW4gaW50ZXJpb3IgcmluZy5cbiAgICAgIGNvbnN0IHNlbCA9IHRoaXMuc2VsZWN0ZWRSZWdpb25JbmZvKCk7XG4gICAgICBjb25zdCBlZGdlID0gc2VsID8gdGhpcy5oaXRFZGdlKGUucG9zaXRpb24sIHNlbC5yZWdpb24pIDogbnVsbDtcbiAgICAgIGlmIChzZWwgJiYgZWRnZSkge1xuICAgICAgICBpZiAoZWRnZS5yaW5nIDwgMCkgdGhpcy5zdG9yZS5hZGRWZXJ0ZXgoc2VsLnJlZ2lvbi5pZCwgZWRnZS5zZWdJbmRleCwgZWRnZS54LCBlZGdlLnkpO1xuICAgICAgICBlbHNlIHRoaXMuc3RvcmUuYWRkSG9sZVZlcnRleChzZWwucmVnaW9uLmlkLCBlZGdlLnJpbmcsIGVkZ2Uuc2VnSW5kZXgsIGVkZ2UueCwgZWRnZS55KTtcbiAgICAgIH1cbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHRoaXMubW9kZSA9PT0gJ2RlbGV0ZXBvaW50Jykge1xuICAgICAgLy8gUmVtb3ZlIHRoZSBjbGlja2VkIHZlcnRleCDigJQgZXh0ZXJpb3Igb3IgYW4gaW50ZXJpb3IgcmluZyAoaml0LXVpIzg1KS5cbiAgICAgIGNvbnN0IHZoID0gdGhpcy5oaXRWZXJ0ZXgoZS5wb3NpdGlvbik7XG4gICAgICBpZiAodmgpIHtcbiAgICAgICAgaWYgKHZoLnJpbmcgPCAwKSB0aGlzLnN0b3JlLmRlbGV0ZVZlcnRleCh2aC5pZCwgdmguaW5kZXgpO1xuICAgICAgICBlbHNlIHRoaXMuc3RvcmUuZGVsZXRlSG9sZVZlcnRleCh2aC5pZCwgdmgucmluZywgdmguaW5kZXgpO1xuICAgICAgfVxuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDbGljay10by1wbGFjZSBwb2x5Z29uICgnZHJhd3BvbHlnb24nKTogdGhlIGZpcnN0IGNsaWNrIHN0YXJ0cyB0aGVcbiAgICogcG9seWdvbiwgZWFjaCBzdWJzZXF1ZW50IGNsaWNrIGFkZHMgYSB2ZXJ0ZXgsIGFuZCBjbGlja2luZyBuZWFyIHRoZSBmaXJzdFxuICAgKiB2ZXJ0ZXggKHdpdGggYXQgbGVhc3QgMyBwbGFjZWQpIGNsb3NlcyBhbmQgY29tbWl0cyBpdC5cbiAgICovXG4gIHByaXZhdGUgb25EcmF3UG9seWdvbkNsaWNrKGU6IGFueSk6IHZvaWQge1xuICAgIGNvbnN0IHB0ID0gdGhpcy50b0ltYWdlKGUucG9zaXRpb24pO1xuICAgIGlmICghdGhpcy5kcmF3aW5nUG9seWdvbikge1xuICAgICAgdGhpcy5wb2x5UG9pbnRzID0gW3B0XTtcbiAgICAgIHRoaXMuZHJhd2luZ1BvbHlnb24gPSB0cnVlO1xuICAgICAgdGhpcy5yZWRyYXcoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgZmlyc3QgPSB0aGlzLnRvUHgodGhpcy5wb2x5UG9pbnRzWzBdLngsIHRoaXMucG9seVBvaW50c1swXS55KTtcbiAgICBjb25zdCBvbkZpcnN0ID0gTWF0aC5oeXBvdChlLnBvc2l0aW9uLnggLSBmaXJzdC54LCBlLnBvc2l0aW9uLnkgLSBmaXJzdC55KSA8PSBFRElUX1RPTDtcbiAgICBpZiAob25GaXJzdCAmJiB0aGlzLnBvbHlQb2ludHMubGVuZ3RoID49IDMpIHtcbiAgICAgIHRoaXMuY29tbWl0UG9seWdvbih0cnVlKTsgLy8gY2xvc2VzICsgcmVzZXRzIGluLXByb2dyZXNzIChpbmNsLiBkcmF3aW5nUG9seWdvbilcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5wb2x5UG9pbnRzLnB1c2gocHQpO1xuICAgIHRoaXMucmVkcmF3KCk7XG4gIH1cblxuICAvKipcbiAgICogSG92ZXIgZmVlZGJhY2sgaW4gc2VsZWN0IG1vZGU6IG1vdmUvcmVzaXplIGN1cnNvcnMgb3ZlciB0aGUgc2VsZWN0ZWRcbiAgICogcmVnaW9uJ3MgYm9keS9lZGdlcy9jb3JuZXJzLCBhIHBvaW50ZXIgb3ZlciBhbnkgb3RoZXIgcmVnaW9uLlxuICAgKi9cbiAgcHJpdmF0ZSBvbk1vdmUoZTogYW55KTogdm9pZCB7XG4gICAgaWYgKHRoaXMubW9kZSAhPT0gJ3NlbGVjdCcpIHJldHVybjtcbiAgICAvLyBBIGdyYWJiYWJsZSBiZXppZXIgY29udHJvbCBoYW5kbGUgb3IgdmVydGV4IG9mIHRoZSBzZWxlY3RlZCBwb2x5Z29uIHRha2VzXG4gICAgLy8gcHJpb3JpdHkuXG4gICAgaWYgKHRoaXMuaGl0QmV6aWVySGFuZGxlKGUucG9zaXRpb24pIHx8IHRoaXMuaGl0VmVydGV4KGUucG9zaXRpb24pKSB7XG4gICAgICAodGhpcy52aWV3ZXIuY2FudmFzIGFzIEhUTUxFbGVtZW50KS5zdHlsZS5jdXJzb3IgPSAncG9pbnRlcic7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGV6ID0gdGhpcy5lZGl0Wm9uZUF0KGUucG9zaXRpb24pO1xuICAgIGlmIChleikge1xuICAgICAgKHRoaXMudmlld2VyLmNhbnZhcyBhcyBIVE1MRWxlbWVudCkuc3R5bGUuY3Vyc29yID0gWk9ORV9DVVJTT1JbZXouem9uZV07XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMudXBkYXRlQ3Vyc29yKHRoaXMucmVnaW9uSW5kZXhBdCh0aGlzLnRvSW1hZ2UoZS5wb3NpdGlvbikpID49IDApO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBtb3ZlL3Jlc2l6ZSB6b25lIHVuZGVyIHRoZSBjdXJzb3IgZm9yIHRoZSBjdXJyZW50bHktc2VsZWN0ZWQgcmVnaW9uXG4gICAqIChyZWN0YW5nbGVzIGdldCBlZGdlL2Nvcm5lciBoYW5kbGVzICsgYm9keTsgcG9seWdvbnMgZ2V0IGJvZHktbW92ZSBvbmx5KSxcbiAgICogb3IgbnVsbCBpZiB0aGUgY3Vyc29yIGlzbid0IG92ZXIgdGhlIHNlbGVjdGVkIHJlZ2lvbi5cbiAgICovXG4gIHByaXZhdGUgZWRpdFpvbmVBdChwb3NpdGlvbjogeyB4OiBudW1iZXI7IHk6IG51bWJlciB9KTogeyB6b25lOiBFZGl0Wm9uZTsgaW5kZXg6IG51bWJlciB9IHwgbnVsbCB7XG4gICAgaWYgKHRoaXMuc2VsZWN0ZWQubGVuZ3RoID09PSAwKSByZXR1cm4gbnVsbDtcbiAgICBjb25zdCBpbmRleCA9IHRoaXMuc2VsZWN0ZWRbdGhpcy5zZWxlY3RlZC5sZW5ndGggLSAxXTtcbiAgICBjb25zdCByZWdpb24gPSB0aGlzLnN0b3JlLmdldFJlZ2lvbnMoKVtpbmRleF07XG4gICAgaWYgKCFyZWdpb24pIHJldHVybiBudWxsO1xuICAgIGNvbnN0IGIgPSByZWdpb24uYm91bmRzO1xuICAgIGlmIChiIGluc3RhbmNlb2YgUmVjdGFuZ2xlKSB7XG4gICAgICBjb25zdCBhID0gdGhpcy50b1B4KGIueCwgYi55KTtcbiAgICAgIGNvbnN0IGMgPSB0aGlzLnRvUHgoYi54ICsgYi53aWR0aCwgYi55ICsgYi5oZWlnaHQpO1xuICAgICAgY29uc3Qgem9uZSA9IHRoaXMucmVjdFpvbmUocG9zaXRpb24ueCwgcG9zaXRpb24ueSxcbiAgICAgICAgTWF0aC5taW4oYS54LCBjLngpLCBNYXRoLm1pbihhLnksIGMueSksIE1hdGgubWF4KGEueCwgYy54KSwgTWF0aC5tYXgoYS55LCBjLnkpKTtcbiAgICAgIHJldHVybiB6b25lID8geyB6b25lLCBpbmRleCB9IDogbnVsbDtcbiAgICB9XG4gICAgaWYgKGIgaW5zdGFuY2VvZiBQb2x5Z29uIHx8IGIgaW5zdGFuY2VvZiBNdWx0aVBvbHlnb24pIHtcbiAgICAgIC8vIFBvbHlnb25zICsgbXVsdGktcGFydCByZWdpb25zIHN1cHBvcnQgd2hvbGUtcmVnaW9uIG1vdmUgKG5vIHJlc2l6ZSB6b25lcykuXG4gICAgICByZXR1cm4gdGhpcy5jb250YWluc1BvaW50KHJlZ2lvbiwgdGhpcy50b0ltYWdlKHBvc2l0aW9uKSkgPyB7IHpvbmU6ICdtb3ZlJywgaW5kZXggfSA6IG51bGw7XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLyoqIFRoZSBjdXJyZW50bHktc2VsZWN0ZWQgcmVnaW9uICh0aGUgbGFzdCBvbmUgc2VsZWN0ZWQpLCBvciBudWxsLiAqL1xuICBwcml2YXRlIHNlbGVjdGVkUmVnaW9uSW5mbygpOiB7IHJlZ2lvbjogUmVnaW9uOyBpbmRleDogbnVtYmVyIH0gfCBudWxsIHtcbiAgICBpZiAodGhpcy5zZWxlY3RlZC5sZW5ndGggPT09IDApIHJldHVybiBudWxsO1xuICAgIGNvbnN0IGluZGV4ID0gdGhpcy5zZWxlY3RlZFt0aGlzLnNlbGVjdGVkLmxlbmd0aCAtIDFdO1xuICAgIGNvbnN0IHJlZ2lvbiA9IHRoaXMuc3RvcmUuZ2V0UmVnaW9ucygpW2luZGV4XTtcbiAgICByZXR1cm4gcmVnaW9uID8geyByZWdpb24sIGluZGV4IH0gOiBudWxsO1xuICB9XG5cbiAgLyoqIFRoZSB2ZXJ0ZXggb2YgdGhlIHNlbGVjdGVkIHBvbHlnb24gdW5kZXIgdGhlIGN1cnNvciAoc2NyZWVuLXBpeGVsXG4gICAqICB0b2xlcmFuY2UpLCBvciBudWxsLiBSZWN0YW5nbGVzIGhhdmUgbm8gZWRpdGFibGUgdmVydGljZXMuICovXG4gIHByaXZhdGUgaGl0VmVydGV4KHBvc2l0aW9uOiB7IHg6IG51bWJlcjsgeTogbnVtYmVyIH0pOiB7IGlkOiBudW1iZXI7IHJpbmc6IG51bWJlcjsgaW5kZXg6IG51bWJlciB9IHwgbnVsbCB7XG4gICAgY29uc3Qgc2VsID0gdGhpcy5zZWxlY3RlZFJlZ2lvbkluZm8oKTtcbiAgICBpZiAoIXNlbCB8fCAhKHNlbC5yZWdpb24uYm91bmRzIGluc3RhbmNlb2YgUG9seWdvbikpIHJldHVybiBudWxsO1xuICAgIGNvbnN0IGIgPSBzZWwucmVnaW9uLmJvdW5kcztcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGIueHBvaW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgcSA9IHRoaXMudG9QeChiLnhwb2ludHNbaV0sIGIueXBvaW50c1tpXSk7XG4gICAgICBpZiAoTWF0aC5oeXBvdChwb3NpdGlvbi54IC0gcS54LCBwb3NpdGlvbi55IC0gcS55KSA8PSBFRElUX1RPTCkge1xuICAgICAgICByZXR1cm4geyBpZDogc2VsLnJlZ2lvbi5pZCwgcmluZzogLTEsIGluZGV4OiBpIH07XG4gICAgICB9XG4gICAgfVxuICAgIC8vIEludGVyaW9yLXJpbmcgKGhvbGUpIHZlcnRpY2VzIGFyZSBkcmFnZ2FibGUgdG9vIChqaXQtdWkjODUpLlxuICAgIGlmIChiLmhvbGVzKSB7XG4gICAgICBmb3IgKGxldCBoID0gMDsgaCA8IGIuaG9sZXMubGVuZ3RoOyBoKyspIHtcbiAgICAgICAgY29uc3QgcmluZyA9IGIuaG9sZXNbaF07XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmluZy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGNvbnN0IHEgPSB0aGlzLnRvUHgocmluZ1tpXVswXSwgcmluZ1tpXVsxXSk7XG4gICAgICAgICAgaWYgKE1hdGguaHlwb3QocG9zaXRpb24ueCAtIHEueCwgcG9zaXRpb24ueSAtIHEueSkgPD0gRURJVF9UT0wpIHtcbiAgICAgICAgICAgIHJldHVybiB7IGlkOiBzZWwucmVnaW9uLmlkLCByaW5nOiBoLCBpbmRleDogaSB9O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIC8qKiBUaGUgYmV6aWVyIGNvbnRyb2wgaGFuZGxlIG9mIHRoZSBzZWxlY3RlZCByZWdpb24gdW5kZXIgdGhlIGN1cnNvciAod2hpY2hcbiAgICogIGFuY2hvciwgYW5kIHdoZXRoZXIgdGhlIGluLSBvciBvdXQtaGFuZGxlKSwgb3IgbnVsbC4gKi9cbiAgcHJpdmF0ZSBoaXRCZXppZXJIYW5kbGUoXG4gICAgcG9zaXRpb246IHsgeDogbnVtYmVyOyB5OiBudW1iZXIgfSxcbiAgKTogeyBpZDogbnVtYmVyOyBpbmRleDogbnVtYmVyOyBzaWRlOiAnaW4nIHwgJ291dCc7IHJpbmc6IG51bWJlciB9IHwgbnVsbCB7XG4gICAgY29uc3Qgc2VsID0gdGhpcy5zZWxlY3RlZFJlZ2lvbkluZm8oKTtcbiAgICBpZiAoIXNlbCB8fCAhKHNlbC5yZWdpb24uYm91bmRzIGluc3RhbmNlb2YgUG9seWdvbikgfHwgIXNlbC5yZWdpb24uYm91bmRzLmJlemllcikgcmV0dXJuIG51bGw7XG4gICAgY29uc3QgYiA9IHNlbC5yZWdpb24uYm91bmRzO1xuICAgIC8vIFRlc3Qgb25lIHJpbmcncyBjb250cm9sIGhhbmRsZXM7IHJldHVybnMgdGhlIG1hdGNoZWQgdmVydGV4L3NpZGUgb3IgbnVsbC5cbiAgICBjb25zdCB0ZXN0UmluZyA9IChcbiAgICAgIHhzOiBudW1iZXJbXSwgeXM6IG51bWJlcltdLCBpbk9mZjogbnVtYmVyW11bXSB8IHVuZGVmaW5lZCwgb3V0T2ZmOiBudW1iZXJbXVtdIHwgdW5kZWZpbmVkLFxuICAgICAgY2xvc2VkOiBib29sZWFuLCByaW5nOiBudW1iZXIsXG4gICAgKTogeyBpZDogbnVtYmVyOyBpbmRleDogbnVtYmVyOyBzaWRlOiAnaW4nIHwgJ291dCc7IHJpbmc6IG51bWJlciB9IHwgbnVsbCA9PiB7XG4gICAgICBjb25zdCBoID0gcmVzb2x2ZUhhbmRsZXMoeHMsIHlzLCBjbG9zZWQsIGluT2ZmLCBvdXRPZmYpO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBoLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmIChoW2ldLmhhc091dCkge1xuICAgICAgICAgIGNvbnN0IHEgPSB0aGlzLnRvUHgoaFtpXS5vdXRbMF0sIGhbaV0ub3V0WzFdKTtcbiAgICAgICAgICBpZiAoTWF0aC5oeXBvdChwb3NpdGlvbi54IC0gcS54LCBwb3NpdGlvbi55IC0gcS55KSA8PSBFRElUX1RPTCkge1xuICAgICAgICAgICAgcmV0dXJuIHsgaWQ6IHNlbC5yZWdpb24uaWQsIGluZGV4OiBpLCBzaWRlOiAnb3V0JywgcmluZyB9O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoaFtpXS5oYXNJbikge1xuICAgICAgICAgIGNvbnN0IHEgPSB0aGlzLnRvUHgoaFtpXS5pblswXSwgaFtpXS5pblsxXSk7XG4gICAgICAgICAgaWYgKE1hdGguaHlwb3QocG9zaXRpb24ueCAtIHEueCwgcG9zaXRpb24ueSAtIHEueSkgPD0gRURJVF9UT0wpIHtcbiAgICAgICAgICAgIHJldHVybiB7IGlkOiBzZWwucmVnaW9uLmlkLCBpbmRleDogaSwgc2lkZTogJ2luJywgcmluZyB9O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfTtcbiAgICBjb25zdCBleHQgPSB0ZXN0UmluZyhiLnhwb2ludHMsIGIueXBvaW50cywgYi5oYW5kbGVzSW4sIGIuaGFuZGxlc091dCwgYi5jbG9zZWQgIT09IGZhbHNlLCAtMSk7XG4gICAgaWYgKGV4dCkgcmV0dXJuIGV4dDtcbiAgICAvLyBEb251dCBob2xlIHJpbmdzIChqaXQtdWkjMTAyKTogdGhlaXIgb3duIGJlemllciBjb250cm9sIGhhbmRsZXMuXG4gICAgaWYgKGIuaG9sZXMgJiYgYi5ob2xlSGFuZGxlc0luICYmIGIuaG9sZUhhbmRsZXNPdXQpIHtcbiAgICAgIGZvciAobGV0IGhpID0gMDsgaGkgPCBiLmhvbGVzLmxlbmd0aDsgaGkrKykge1xuICAgICAgICBjb25zdCByaW5nID0gYi5ob2xlc1toaV07XG4gICAgICAgIGNvbnN0IGhpdCA9IHRlc3RSaW5nKFxuICAgICAgICAgIHJpbmcubWFwKChwKSA9PiBwWzBdKSwgcmluZy5tYXAoKHApID0+IHBbMV0pLFxuICAgICAgICAgIGIuaG9sZUhhbmRsZXNJbltoaV0sIGIuaG9sZUhhbmRsZXNPdXRbaGldLCB0cnVlLCBoaSxcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKGhpdCkgcmV0dXJuIGhpdDtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICAvKiogVGhlIGVkZ2Ugb2YgYHJlZ2lvbmAncyBwb2x5Z29uIG5lYXJlc3QgdGhlIGN1cnNvciAod2l0aGluIHRvbGVyYW5jZSksIHdpdGhcbiAgICogIHRoZSBjbGlja2VkIHBvaW50IGluIGltYWdlIGNvb3JkcyBhcyB0aGUgaW5zZXJ0aW9uIHBvc2l0aW9uLCBvciBudWxsLiAqL1xuICBwcml2YXRlIGhpdEVkZ2UocG9zaXRpb246IHsgeDogbnVtYmVyOyB5OiBudW1iZXIgfSwgcmVnaW9uOiBSZWdpb24pOlxuICAgIHsgcmluZzogbnVtYmVyOyBzZWdJbmRleDogbnVtYmVyOyB4OiBudW1iZXI7IHk6IG51bWJlciB9IHwgbnVsbCB7XG4gICAgaWYgKCEocmVnaW9uLmJvdW5kcyBpbnN0YW5jZW9mIFBvbHlnb24pKSByZXR1cm4gbnVsbDtcbiAgICBjb25zdCBiID0gcmVnaW9uLmJvdW5kcztcbiAgICBsZXQgYmVzdCA9IC0xLCBiZXN0UmluZyA9IC0xLCBiZXN0RGlzdCA9IEluZmluaXR5O1xuICAgIC8vIE5lYXJlc3QgZWRnZSBhY3Jvc3MgdGhlIGV4dGVyaW9yIChyaW5nIC0xKSBhbmQgZXZlcnkgaW50ZXJpb3IgcmluZyAoaG9sZSkuXG4gICAgY29uc3Qgc2NhbiA9ICh4czogbnVtYmVyW10sIHlzOiBudW1iZXJbXSwgcmluZzogbnVtYmVyLCBjbG9zZWQ6IGJvb2xlYW4pID0+IHtcbiAgICAgIGNvbnN0IG4gPSB4cy5sZW5ndGg7XG4gICAgICBjb25zdCBzZWdDb3VudCA9IGNsb3NlZCA/IG4gOiBuIC0gMTsgLy8gY2xvc2VkIHdyYXBzIHRoZSBsYXN0LT5maXJzdCBlZGdlXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNlZ0NvdW50OyBpKyspIHtcbiAgICAgICAgY29uc3QgaiA9IChpICsgMSkgJSBuO1xuICAgICAgICBjb25zdCBhID0gdGhpcy50b1B4KHhzW2ldLCB5c1tpXSk7XG4gICAgICAgIGNvbnN0IGMgPSB0aGlzLnRvUHgoeHNbal0sIHlzW2pdKTtcbiAgICAgICAgY29uc3QgZCA9IHRoaXMuZGlzdFRvU2VnbWVudFB4KHBvc2l0aW9uLCBhLCBjKTtcbiAgICAgICAgaWYgKGQgPCBiZXN0RGlzdCkgeyBiZXN0RGlzdCA9IGQ7IGJlc3QgPSBpOyBiZXN0UmluZyA9IHJpbmc7IH1cbiAgICAgIH1cbiAgICB9O1xuICAgIHNjYW4oYi54cG9pbnRzLCBiLnlwb2ludHMsIC0xLCBiLmNsb3NlZCAhPT0gZmFsc2UpO1xuICAgIGlmIChiLmhvbGVzKSB7XG4gICAgICBiLmhvbGVzLmZvckVhY2goKHIsIGgpID0+IHNjYW4oci5tYXAocCA9PiBwWzBdKSwgci5tYXAocCA9PiBwWzFdKSwgaCwgdHJ1ZSkpO1xuICAgIH1cbiAgICBpZiAoYmVzdCA8IDAgfHwgYmVzdERpc3QgPiBFRElUX1RPTCkgcmV0dXJuIG51bGw7XG4gICAgY29uc3QgaW1nID0gdGhpcy50b0ltYWdlKHBvc2l0aW9uKTtcbiAgICByZXR1cm4geyByaW5nOiBiZXN0UmluZywgc2VnSW5kZXg6IGJlc3QsIHg6IGltZy54LCB5OiBpbWcueSB9O1xuICB9XG5cbiAgLyoqIENsYXNzaWZ5IGEgc2NyZWVuIHBvaW50IGFnYWluc3QgYSBzY3JlZW4tc3BhY2UgcmVjdGFuZ2xlIGludG8gYSB6b25lLiAqL1xuICBwcml2YXRlIHJlY3Rab25lKHB4OiBudW1iZXIsIHB5OiBudW1iZXIsIHgwOiBudW1iZXIsIHkwOiBudW1iZXIsIHgxOiBudW1iZXIsIHkxOiBudW1iZXIpOiBFZGl0Wm9uZSB8IG51bGwge1xuICAgIGNvbnN0IHQgPSBFRElUX1RPTDtcbiAgICBpZiAocHggPCB4MCAtIHQgfHwgcHggPiB4MSArIHQgfHwgcHkgPCB5MCAtIHQgfHwgcHkgPiB5MSArIHQpIHJldHVybiBudWxsO1xuICAgIGNvbnN0IGxlZnQgPSBNYXRoLmFicyhweCAtIHgwKSA8PSB0LCByaWdodCA9IE1hdGguYWJzKHB4IC0geDEpIDw9IHQ7XG4gICAgY29uc3QgdG9wID0gTWF0aC5hYnMocHkgLSB5MCkgPD0gdCwgYm90dG9tID0gTWF0aC5hYnMocHkgLSB5MSkgPD0gdDtcbiAgICBpZiAodG9wICYmIGxlZnQpIHJldHVybiAnbncnO1xuICAgIGlmICh0b3AgJiYgcmlnaHQpIHJldHVybiAnbmUnO1xuICAgIGlmIChib3R0b20gJiYgbGVmdCkgcmV0dXJuICdzdyc7XG4gICAgaWYgKGJvdHRvbSAmJiByaWdodCkgcmV0dXJuICdzZSc7XG4gICAgaWYgKGxlZnQpIHJldHVybiAndyc7XG4gICAgaWYgKHJpZ2h0KSByZXR1cm4gJ2UnO1xuICAgIGlmICh0b3ApIHJldHVybiAnbic7XG4gICAgaWYgKGJvdHRvbSkgcmV0dXJuICdzJztcbiAgICBpZiAocHggPiB4MCAmJiBweCA8IHgxICYmIHB5ID4geTAgJiYgcHkgPCB5MSkgcmV0dXJuICdtb3ZlJztcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIC8qKiBTbmFwc2hvdCB0aGUgc2VsZWN0ZWQgcmVnaW9uJ3MgZ2VvbWV0cnkgYXQgdGhlIHN0YXJ0IG9mIGFuIGVkaXQuICovXG4gIHByaXZhdGUgc25hcHNob3QocmVnaW9uOiBSZWdpb24pOiBhbnkge1xuICAgIGNvbnN0IGIgPSByZWdpb24uYm91bmRzO1xuICAgIGlmIChiIGluc3RhbmNlb2YgUmVjdGFuZ2xlKSByZXR1cm4geyBraW5kOiAncmVjdCcsIHg6IGIueCwgeTogYi55LCB3OiBiLndpZHRoLCBoOiBiLmhlaWdodCB9O1xuICAgIGlmIChiIGluc3RhbmNlb2YgUG9seWdvbikge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAga2luZDogJ3BvbHknLCB4czogYi54cG9pbnRzLnNsaWNlKCksIHlzOiBiLnlwb2ludHMuc2xpY2UoKSwgY2xvc2VkOiBiLmNsb3NlZCAhPT0gZmFsc2UsXG4gICAgICAgIGJlemllcjogYi5iZXppZXIsXG4gICAgICAgIGluT2ZmOiBiLmhhbmRsZXNJbj8ubWFwKG8gPT4gby5zbGljZSgpKSxcbiAgICAgICAgb3V0T2ZmOiBiLmhhbmRsZXNPdXQ/Lm1hcChvID0+IG8uc2xpY2UoKSksXG4gICAgICAgIGhvbGVzOiBiLmhvbGVzPy5tYXAocmluZyA9PiByaW5nLm1hcChwdCA9PiBwdC5zbGljZSgpKSksXG4gICAgICB9O1xuICAgIH1cbiAgICBpZiAoYiBpbnN0YW5jZW9mIE11bHRpUG9seWdvbikge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAga2luZDogJ211bHRpJyxcbiAgICAgICAgcG9seWdvbnM6IGIucG9seWdvbnMubWFwKChwKSA9PiAoe1xuICAgICAgICAgIHhzOiBwLnhwb2ludHMuc2xpY2UoKSwgeXM6IHAueXBvaW50cy5zbGljZSgpLCBjbG9zZWQ6IHAuY2xvc2VkICE9PSBmYWxzZSxcbiAgICAgICAgICBob2xlczogcC5ob2xlcz8ubWFwKHJpbmcgPT4gcmluZy5tYXAocHQgPT4gcHQuc2xpY2UoKSkpLFxuICAgICAgICB9KSksXG4gICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4geyBraW5kOiAncmVjdCcsIHg6IDAsIHk6IDAsIHc6IDAsIGg6IDAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBcHBseSB0aGUgaW4tcHJvZ3Jlc3MgbW92ZS9yZXNpemUgdG8gdGhlIHJlZ2lvbiwgbGl2ZSwgdGhyb3VnaCB0aGVcbiAgICogUmVnaW9uLW5hdGl2ZSBlZGl0IEFQSS4gUmVjb21wdXRlZCBhYnNvbHV0ZWx5IGZyb20gdGhlIGdlc3R1cmUtc3RhcnRcbiAgICogc25hcHNob3QgKGBvcmlnYCkgKyB0aGUgdG90YWwgZGVsdGEsIHNvIGVhY2ggZnJhbWUgaXMgaWRlbXBvdGVudC5cbiAgICovXG4gIHByaXZhdGUgYXBwbHlFZGl0KGN1ckltZzogeyB4OiBudW1iZXI7IHk6IG51bWJlciB9KTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmVkaXQpIHJldHVybjtcblxuICAgIGlmICh0aGlzLmVkaXQua2luZCA9PT0gJ3ZlcnRleCcpIHtcbiAgICAgIC8vIERyYWcgYSBzaW5nbGUgdmVydGV4IHRvIHRoZSBjdXJzb3IgKGFic29sdXRlIOKAlCBpZGVtcG90ZW50KS4gUm91dGUgdG8gdGhlXG4gICAgICAvLyBleHRlcmlvciBvciB0aGUgbWF0Y2hpbmcgaW50ZXJpb3IgcmluZyAoaG9sZSkg4oCUIGppdC11aSM4NS5cbiAgICAgIGlmICh0aGlzLmVkaXQucmluZyA8IDApIHtcbiAgICAgICAgdGhpcy5zdG9yZS5tb3ZlVmVydGV4KHRoaXMuZWRpdC5pZCwgdGhpcy5lZGl0LnZlcnRleEluZGV4LCBjdXJJbWcueCwgY3VySW1nLnkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5zdG9yZS5tb3ZlSG9sZVZlcnRleCh0aGlzLmVkaXQuaWQsIHRoaXMuZWRpdC5yaW5nLCB0aGlzLmVkaXQudmVydGV4SW5kZXgsIGN1ckltZy54LCBjdXJJbWcueSk7XG4gICAgICB9XG4gICAgICB0aGlzLnJlZHJhdygpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmVkaXQua2luZCA9PT0gJ2hhbmRsZScpIHtcbiAgICAgIC8vIERyYWcgYSBiZXppZXIgY29udHJvbCBoYW5kbGUgdG8gdGhlIGN1cnNvciDigJQgZXh0ZXJpb3IgKHJpbmcgLTEpIG9yIGEgZG9udXQgaG9sZSByaW5nLlxuICAgICAgaWYgKHRoaXMuZWRpdC5yaW5nIDwgMCkge1xuICAgICAgICB0aGlzLnN0b3JlLm1vdmVCZXppZXJIYW5kbGUodGhpcy5lZGl0LmlkLCB0aGlzLmVkaXQudmVydGV4SW5kZXgsIHRoaXMuZWRpdC5oYW5kbGVTaWRlLCBjdXJJbWcueCwgY3VySW1nLnkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5zdG9yZS5tb3ZlSG9sZUJlemllckhhbmRsZShcbiAgICAgICAgICB0aGlzLmVkaXQuaWQsIHRoaXMuZWRpdC5yaW5nLCB0aGlzLmVkaXQudmVydGV4SW5kZXgsIHRoaXMuZWRpdC5oYW5kbGVTaWRlLCBjdXJJbWcueCwgY3VySW1nLnksXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICB0aGlzLnJlZHJhdygpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGR4ID0gY3VySW1nLnggLSB0aGlzLmVkaXQuc3RhcnRJbWcueDtcbiAgICBjb25zdCBkeSA9IGN1ckltZy55IC0gdGhpcy5lZGl0LnN0YXJ0SW1nLnk7XG5cbiAgICBjb25zdCBvID0gdGhpcy5lZGl0Lm9yaWc7XG4gICAgaWYgKG8ua2luZCA9PT0gJ3JlY3QnKSB7XG4gICAgICBsZXQgeDAgPSBvLngsIHkwID0gby55LCB4MSA9IG8ueCArIG8udywgeTEgPSBvLnkgKyBvLmg7XG4gICAgICBzd2l0Y2ggKHRoaXMuZWRpdC56b25lKSB7XG4gICAgICAgIGNhc2UgJ21vdmUnOiB4MCArPSBkeDsgeDEgKz0gZHg7IHkwICs9IGR5OyB5MSArPSBkeTsgYnJlYWs7XG4gICAgICAgIGNhc2UgJ3cnOiB4MCArPSBkeDsgYnJlYWs7XG4gICAgICAgIGNhc2UgJ2UnOiB4MSArPSBkeDsgYnJlYWs7XG4gICAgICAgIGNhc2UgJ24nOiB5MCArPSBkeTsgYnJlYWs7XG4gICAgICAgIGNhc2UgJ3MnOiB5MSArPSBkeTsgYnJlYWs7XG4gICAgICAgIGNhc2UgJ253JzogeDAgKz0gZHg7IHkwICs9IGR5OyBicmVhaztcbiAgICAgICAgY2FzZSAnbmUnOiB4MSArPSBkeDsgeTAgKz0gZHk7IGJyZWFrO1xuICAgICAgICBjYXNlICdzdyc6IHgwICs9IGR4OyB5MSArPSBkeTsgYnJlYWs7XG4gICAgICAgIGNhc2UgJ3NlJzogeDEgKz0gZHg7IHkxICs9IGR5OyBicmVhaztcbiAgICAgIH1cbiAgICAgIGNvbnN0IHJlY3QgPSBuZXcgUmVjdGFuZ2xlKCk7XG4gICAgICByZWN0LnggPSBNYXRoLnJvdW5kKE1hdGgubWluKHgwLCB4MSkpO1xuICAgICAgcmVjdC55ID0gTWF0aC5yb3VuZChNYXRoLm1pbih5MCwgeTEpKTtcbiAgICAgIHJlY3Qud2lkdGggPSBNYXRoLnJvdW5kKE1hdGguYWJzKHgxIC0geDApKTtcbiAgICAgIHJlY3QuaGVpZ2h0ID0gTWF0aC5yb3VuZChNYXRoLmFicyh5MSAtIHkwKSk7XG4gICAgICB0aGlzLnN0b3JlLnVwZGF0ZUJvdW5kcyh0aGlzLmVkaXQuaWQsIHJlY3QpO1xuICAgIH0gZWxzZSBpZiAoby5raW5kID09PSAnbXVsdGknKSB7XG4gICAgICAvLyBNdWx0aS1wYXJ0IHJlZ2lvbjogdHJhbnNsYXRlIGV2ZXJ5IHBhcnQgKGFuZCBpdHMgaG9sZXMpIGJ5IHRoZSBkZWx0YS5cbiAgICAgIGNvbnN0IG1wID0gbmV3IE11bHRpUG9seWdvbigpO1xuICAgICAgbXAucG9seWdvbnMgPSBvLnBvbHlnb25zLm1hcCgocHA6IGFueSkgPT4ge1xuICAgICAgICBjb25zdCB4cyA9IHBwLnhzLm1hcCgoeDogbnVtYmVyKSA9PiBNYXRoLnJvdW5kKHggKyBkeCkpO1xuICAgICAgICBjb25zdCB5cyA9IHBwLnlzLm1hcCgoeTogbnVtYmVyKSA9PiBNYXRoLnJvdW5kKHkgKyBkeSkpO1xuICAgICAgICBjb25zdCBwb2x5ID0gbmV3IFBvbHlnb24oKTtcbiAgICAgICAgcG9seS5ucG9pbnRzID0geHMubGVuZ3RoO1xuICAgICAgICBwb2x5Lnhwb2ludHMgPSB4cztcbiAgICAgICAgcG9seS55cG9pbnRzID0geXM7XG4gICAgICAgIHBvbHkuY29vcmRpbmF0ZXMgPSB4cy5tYXAoKHg6IG51bWJlciwgaTogbnVtYmVyKSA9PiBbeCwgeXNbaV1dKTtcbiAgICAgICAgcG9seS5jbG9zZWQgPSBwcC5jbG9zZWQ7XG4gICAgICAgIGlmIChwcC5ob2xlcykge1xuICAgICAgICAgIHBvbHkuaG9sZXMgPSBwcC5ob2xlcy5tYXAoKHJpbmc6IG51bWJlcltdW10pID0+XG4gICAgICAgICAgICByaW5nLm1hcCgoW3gsIHldOiBudW1iZXJbXSkgPT4gW01hdGgucm91bmQoeCArIGR4KSwgTWF0aC5yb3VuZCh5ICsgZHkpXSkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBwb2x5O1xuICAgICAgfSk7XG4gICAgICB0aGlzLnN0b3JlLnVwZGF0ZUJvdW5kcyh0aGlzLmVkaXQuaWQsIG1wKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gUG9seWdvbjogdHJhbnNsYXRlIGV2ZXJ5IHZlcnRleCAodGhlIG9ubHkgcG9seWdvbiBlZGl0IHpvbmUgaXMgJ21vdmUnKS5cbiAgICAgIC8vIEJlemllciBmbGFnICsgaGFuZGxlIG9mZnNldHMgYXJlIHJlbGF0aXZlLCBzbyB0aGV5IGNhcnJ5IG92ZXIgdW5jaGFuZ2VkLlxuICAgICAgY29uc3QgeHMgPSBvLnhzLm1hcCgoeDogbnVtYmVyKSA9PiBNYXRoLnJvdW5kKHggKyBkeCkpO1xuICAgICAgY29uc3QgeXMgPSBvLnlzLm1hcCgoeTogbnVtYmVyKSA9PiBNYXRoLnJvdW5kKHkgKyBkeSkpO1xuICAgICAgY29uc3QgcG9seSA9IG5ldyBQb2x5Z29uKCk7XG4gICAgICBwb2x5Lm5wb2ludHMgPSB4cy5sZW5ndGg7XG4gICAgICBwb2x5Lnhwb2ludHMgPSB4cztcbiAgICAgIHBvbHkueXBvaW50cyA9IHlzO1xuICAgICAgcG9seS5jb29yZGluYXRlcyA9IHhzLm1hcCgoeDogbnVtYmVyLCBpOiBudW1iZXIpID0+IFt4LCB5c1tpXV0pO1xuICAgICAgcG9seS5jbG9zZWQgPSBvLmNsb3NlZDtcbiAgICAgIHBvbHkuYmV6aWVyID0gby5iZXppZXI7XG4gICAgICBpZiAoby5pbk9mZikgcG9seS5oYW5kbGVzSW4gPSBvLmluT2ZmLm1hcCgob2ZmOiBudW1iZXJbXSkgPT4gb2ZmLnNsaWNlKCkpO1xuICAgICAgaWYgKG8ub3V0T2ZmKSBwb2x5LmhhbmRsZXNPdXQgPSBvLm91dE9mZi5tYXAoKG9mZjogbnVtYmVyW10pID0+IG9mZi5zbGljZSgpKTtcbiAgICAgIC8vIFRyYW5zbGF0ZSBpbnRlcmlvciByaW5ncyAoaG9sZXMpIHdpdGggdGhlIGV4dGVyaW9yIChqaXQtdWkjODUpLlxuICAgICAgaWYgKG8uaG9sZXMpIHtcbiAgICAgICAgcG9seS5ob2xlcyA9IG8uaG9sZXMubWFwKChyaW5nOiBudW1iZXJbXVtdKSA9PlxuICAgICAgICAgIHJpbmcubWFwKChbeCwgeV06IG51bWJlcltdKSA9PiBbTWF0aC5yb3VuZCh4ICsgZHgpLCBNYXRoLnJvdW5kKHkgKyBkeSldKSk7XG4gICAgICB9XG4gICAgICB0aGlzLnN0b3JlLnVwZGF0ZUJvdW5kcyh0aGlzLmVkaXQuaWQsIHBvbHkpO1xuICAgIH1cbiAgICB0aGlzLnJlZHJhdygpO1xuICB9XG5cbiAgcHJpdmF0ZSBzZWxlY3RBdChwdDogeyB4OiBudW1iZXI7IHk6IG51bWJlciB9LCBhZGRpdGl2ZSA9IGZhbHNlKTogdm9pZCB7XG4gICAgY29uc3QgaWR4ID0gdGhpcy5yZWdpb25JbmRleEF0KHB0KTtcbiAgICBpZiAoYWRkaXRpdmUpIHtcbiAgICAgIC8vIFNoaWZ0LWNsaWNrIG9uIGVtcHR5IHNwYWNlIGtlZXBzIHRoZSBjdXJyZW50IHNlbGVjdGlvbi5cbiAgICAgIGlmIChpZHggPCAwKSByZXR1cm47XG4gICAgICAvLyBgdGhpcy5zZWxlY3RlZGAgbWlycm9ycyB0aGUgc3RvcmUncyBjdXJyZW50IHNlbGVjdGlvbiAoa2VwdCBpbiBzeW5jIHZpYVxuICAgICAgLy8gdGhlIHN1YnNjcmlwdGlvbiksIHNvIGl0J3MgdGhlIHNvdXJjZSBvZiB0cnV0aCB3aXRob3V0IGEgc3luYyBnZXR0ZXIuXG4gICAgICBjb25zdCBjdXIgPSB0aGlzLnNlbGVjdGVkLnNsaWNlKCk7XG4gICAgICBjb25zdCBhdCA9IGN1ci5pbmRleE9mKGlkeCk7XG4gICAgICBpZiAoYXQgPj0gMCkgY3VyLnNwbGljZShhdCwgMSk7IC8vIHRvZ2dsZSBvZmZcbiAgICAgIGVsc2UgY3VyLnB1c2goaWR4KTsgICAgICAgICAgICAgLy8gdG9nZ2xlIG9uXG4gICAgICB0aGlzLnN0b3JlLnNldFNlbGVjdGVkU2hhcGVJbmRpY2VzKGN1cik7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuc3RvcmUuc2V0U2VsZWN0ZWRTaGFwZUluZGljZXMoaWR4ID49IDAgPyBbaWR4XSA6IFtdKTtcbiAgfVxuXG4gIC8qKiBJbmRpY2VzIG9mIGV2ZXJ5IHJlZ2lvbiB3aG9zZSBib3VuZGluZyBib3ggaW50ZXJzZWN0cyB0aGUgaW1hZ2Utc3BhY2VcbiAgICogIHJlY3RhbmdsZSBbeDAseTBd4oCTW3gxLHkxXSAocnViYmVyLWJhbmQgbXVsdGktc2VsZWN0KS4gKi9cbiAgcHJpdmF0ZSByZWdpb25zSW5SZWN0KHgwOiBudW1iZXIsIHkwOiBudW1iZXIsIHgxOiBudW1iZXIsIHkxOiBudW1iZXIpOiBudW1iZXJbXSB7XG4gICAgY29uc3Qgb3V0OiBudW1iZXJbXSA9IFtdO1xuICAgIHRoaXMuc3RvcmUuZ2V0UmVnaW9ucygpLmZvckVhY2goKHIsIGkpID0+IHtcbiAgICAgIGNvbnN0IGJiID0gdGhpcy5yZWdpb25CQm94KHIpO1xuICAgICAgaWYgKGJiICYmIGJiLngwIDw9IHgxICYmIGJiLngxID49IHgwICYmIGJiLnkwIDw9IHkxICYmIGJiLnkxID49IHkwKSBvdXQucHVzaChpKTtcbiAgICB9KTtcbiAgICByZXR1cm4gb3V0O1xuICB9XG5cbiAgLyoqIEF4aXMtYWxpZ25lZCBib3VuZGluZyBib3ggb2YgYSByZWdpb24gaW4gaW1hZ2UgY29vcmRzLCBvciBudWxsIGlmIGVtcHR5LiAqL1xuICBwcml2YXRlIHJlZ2lvbkJCb3gocjogUmVnaW9uKTogeyB4MDogbnVtYmVyOyB5MDogbnVtYmVyOyB4MTogbnVtYmVyOyB5MTogbnVtYmVyIH0gfCBudWxsIHtcbiAgICBjb25zdCBiID0gci5ib3VuZHM7XG4gICAgaWYgKGIgaW5zdGFuY2VvZiBSZWN0YW5nbGUpIHtcbiAgICAgIHJldHVybiB7IHgwOiBiLngsIHkwOiBiLnksIHgxOiBiLnggKyBiLndpZHRoLCB5MTogYi55ICsgYi5oZWlnaHQgfTtcbiAgICB9XG4gICAgaWYgKGIgaW5zdGFuY2VvZiBQb2x5Z29uICYmIGIueHBvaW50cy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHgwOiBNYXRoLm1pbiguLi5iLnhwb2ludHMpLCB5MDogTWF0aC5taW4oLi4uYi55cG9pbnRzKSxcbiAgICAgICAgeDE6IE1hdGgubWF4KC4uLmIueHBvaW50cyksIHkxOiBNYXRoLm1heCguLi5iLnlwb2ludHMpLFxuICAgICAgfTtcbiAgICB9XG4gICAgaWYgKGIgaW5zdGFuY2VvZiBNdWx0aVBvbHlnb24pIHtcbiAgICAgIGxldCB4MCA9IEluZmluaXR5LCB5MCA9IEluZmluaXR5LCB4MSA9IC1JbmZpbml0eSwgeTEgPSAtSW5maW5pdHk7XG4gICAgICBmb3IgKGNvbnN0IHAgb2YgYi5wb2x5Z29ucykge1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHAueHBvaW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGlmIChwLnhwb2ludHNbaV0gPCB4MCkgeDAgPSBwLnhwb2ludHNbaV07XG4gICAgICAgICAgaWYgKHAueHBvaW50c1tpXSA+IHgxKSB4MSA9IHAueHBvaW50c1tpXTtcbiAgICAgICAgICBpZiAocC55cG9pbnRzW2ldIDwgeTApIHkwID0gcC55cG9pbnRzW2ldO1xuICAgICAgICAgIGlmIChwLnlwb2ludHNbaV0gPiB5MSkgeTEgPSBwLnlwb2ludHNbaV07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiB4MSA+PSB4MCA/IHsgeDAsIHkwLCB4MSwgeTEgfSA6IG51bGw7XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLyoqIEluZGV4IG9mIHRoZSB0b3Btb3N0IHJlZ2lvbiB1bmRlciBhIHBvaW50LCBvciAtMS4gKi9cbiAgcHJpdmF0ZSByZWdpb25JbmRleEF0KHB0OiB7IHg6IG51bWJlcjsgeTogbnVtYmVyIH0pOiBudW1iZXIge1xuICAgIGNvbnN0IHJlZ2lvbnMgPSB0aGlzLnN0b3JlLmdldFJlZ2lvbnMoKTtcbiAgICBmb3IgKGxldCBpID0gcmVnaW9ucy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgaWYgKHRoaXMuY29udGFpbnNQb2ludChyZWdpb25zW2ldLCBwdCkpIHJldHVybiBpO1xuICAgIH1cbiAgICByZXR1cm4gLTE7XG4gIH1cblxuICBwcml2YXRlIGNvbnRhaW5zUG9pbnQocmVnaW9uOiBSZWdpb24sIHB0OiB7IHg6IG51bWJlcjsgeTogbnVtYmVyIH0pOiBib29sZWFuIHtcbiAgICBjb25zdCBiID0gcmVnaW9uLmJvdW5kcztcbiAgICBpZiAoYiBpbnN0YW5jZW9mIFJlY3RhbmdsZSkge1xuICAgICAgcmV0dXJuIHB0LnggPj0gYi54ICYmIHB0LnggPD0gYi54ICsgYi53aWR0aCAmJiBwdC55ID49IGIueSAmJiBwdC55IDw9IGIueSArIGIuaGVpZ2h0O1xuICAgIH1cbiAgICAvLyBNdWx0aS1wYXJ0IHJlZ2lvbjogaW5zaWRlIGFueSBwYXJ0IChleHRlcmlvciBtaW51cyB0aGF0IHBhcnQncyBob2xlcykuXG4gICAgaWYgKGIgaW5zdGFuY2VvZiBNdWx0aVBvbHlnb24pIHtcbiAgICAgIHJldHVybiBiLnBvbHlnb25zLnNvbWUoKHApID0+IHRoaXMuY2xvc2VkUG9seWdvbkNvbnRhaW5zKHAsIHB0KSk7XG4gICAgfVxuICAgIGlmIChiIGluc3RhbmNlb2YgUG9seWdvbikge1xuICAgICAgaWYgKGIuY2xvc2VkICE9PSBmYWxzZSkgcmV0dXJuIHRoaXMuY2xvc2VkUG9seWdvbkNvbnRhaW5zKGIsIHB0KTtcbiAgICAgIC8vIE9wZW4gcG9seWxpbmU6IG5vIGludGVyaW9yIOKAlCBzZWxlY3Qgd2hlbiB0aGUgY2xpY2sgbGFuZHMgbmVhciB0aGUgbGluZS5cbiAgICAgIC8vIFRvbGVyYW5jZSBpcyBpbiBzY3JlZW4gcGl4ZWxzIHNvIGl0IHN0YXlzIGNsaWNrYWJsZSBhdCBhbnkgem9vbS5cbiAgICAgIGNvbnN0IHhzID0gYi54cG9pbnRzLCB5cyA9IGIueXBvaW50cywgbiA9IHhzLmxlbmd0aCwgdG9sUHggPSA2O1xuICAgICAgY29uc3QgaGVyZSA9IHRoaXMudG9QeChwdC54LCBwdC55KTtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpICsgMSA8IG47IGkrKykge1xuICAgICAgICBjb25zdCBhID0gdGhpcy50b1B4KHhzW2ldLCB5c1tpXSk7XG4gICAgICAgIGNvbnN0IGMgPSB0aGlzLnRvUHgoeHNbaSArIDFdLCB5c1tpICsgMV0pO1xuICAgICAgICBpZiAodGhpcy5kaXN0VG9TZWdtZW50UHgoaGVyZSwgYSwgYykgPD0gdG9sUHgpIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvKiogUG9pbnQtaW4tY2xvc2VkLXBvbHlnb24gKGltYWdlIGNvb3JkcykgaG9ub3VyaW5nIGludGVyaW9yIHJpbmdzIChob2xlcyk6XG4gICAqICBpbnNpZGUgdGhlIGV4dGVyaW9yIEFORCBvdXRzaWRlIGV2ZXJ5IGhvbGUgKGV2ZW4tb2RkKS4gKi9cbiAgcHJpdmF0ZSBjbG9zZWRQb2x5Z29uQ29udGFpbnMoYjogUG9seWdvbiwgcHQ6IHsgeDogbnVtYmVyOyB5OiBudW1iZXIgfSk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IGluUmluZyA9IChyeHM6IG51bWJlcltdLCByeXM6IG51bWJlcltdKTogYm9vbGVhbiA9PiB7XG4gICAgICBsZXQgaGl0ID0gZmFsc2U7XG4gICAgICBmb3IgKGxldCBpID0gMCwgaiA9IHJ4cy5sZW5ndGggLSAxOyBpIDwgcnhzLmxlbmd0aDsgaiA9IGkrKykge1xuICAgICAgICBjb25zdCBpbnRlcnNlY3QgPSAoKHJ5c1tpXSA+IHB0LnkpICE9PSAocnlzW2pdID4gcHQueSkpXG4gICAgICAgICAgJiYgKHB0LnggPCAoKHJ4c1tqXSAtIHJ4c1tpXSkgKiAocHQueSAtIHJ5c1tpXSkpIC8gKHJ5c1tqXSAtIHJ5c1tpXSkgKyByeHNbaV0pO1xuICAgICAgICBpZiAoaW50ZXJzZWN0KSBoaXQgPSAhaGl0O1xuICAgICAgfVxuICAgICAgcmV0dXJuIGhpdDtcbiAgICB9O1xuICAgIGlmICghaW5SaW5nKGIueHBvaW50cywgYi55cG9pbnRzKSkgcmV0dXJuIGZhbHNlO1xuICAgIGlmIChiLmhvbGVzKSB7XG4gICAgICBmb3IgKGNvbnN0IHJpbmcgb2YgYi5ob2xlcykge1xuICAgICAgICBpZiAoaW5SaW5nKHJpbmcubWFwKHAgPT4gcFswXSksIHJpbmcubWFwKHAgPT4gcFsxXSkpKSByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLyoqIFNob3J0ZXN0IGRpc3RhbmNlIGZyb20gcG9pbnQgcCB0byBzZWdtZW50IGHigJNiLCBhbGwgaW4gc2NyZWVuIHBpeGVscy4gKi9cbiAgcHJpdmF0ZSBkaXN0VG9TZWdtZW50UHgoXG4gICAgcDogeyB4OiBudW1iZXI7IHk6IG51bWJlciB9LCBhOiB7IHg6IG51bWJlcjsgeTogbnVtYmVyIH0sIGI6IHsgeDogbnVtYmVyOyB5OiBudW1iZXIgfSxcbiAgKTogbnVtYmVyIHtcbiAgICBjb25zdCBkeCA9IGIueCAtIGEueCwgZHkgPSBiLnkgLSBhLnk7XG4gICAgY29uc3QgbGVuMiA9IGR4ICogZHggKyBkeSAqIGR5O1xuICAgIGlmIChsZW4yID09PSAwKSByZXR1cm4gTWF0aC5oeXBvdChwLnggLSBhLngsIHAueSAtIGEueSk7XG4gICAgbGV0IHQgPSAoKHAueCAtIGEueCkgKiBkeCArIChwLnkgLSBhLnkpICogZHkpIC8gbGVuMjtcbiAgICB0ID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oMSwgdCkpO1xuICAgIHJldHVybiBNYXRoLmh5cG90KHAueCAtIChhLnggKyB0ICogZHgpLCBwLnkgLSAoYS55ICsgdCAqIGR5KSk7XG4gIH1cblxuICBwcml2YXRlIHJlc2V0SW5Qcm9ncmVzcygpOiB2b2lkIHtcbiAgICB0aGlzLnJlY3RTdGFydCA9IHRoaXMucmVjdEN1cnJlbnQgPSBudWxsO1xuICAgIHRoaXMucG9seVBvaW50cyA9IFtdO1xuICAgIHRoaXMuZnJlZWhhbmREcmFnZ2luZyA9IGZhbHNlO1xuICAgIHRoaXMuZHJhd2luZ1BvbHlnb24gPSBmYWxzZTtcbiAgICB0aGlzLmxhc3RGcmVlaGFuZFB4ID0gbnVsbDtcbiAgICAvLyBDbG9zZSBhbnkgb3BlbiBlZGl0IGJhdGNoIChlLmcuIGEgbW9kZSBzd2l0Y2ggbWlkLWRyYWcpIHNvIHRoZSBzdG9yZSdzXG4gICAgLy8gZW1pdCBjb2FsZXNjaW5nIGRvZXNuJ3QgZ2V0IHN0dWNrLlxuICAgIGlmICh0aGlzLmVkaXQpIHtcbiAgICAgIHRoaXMuc3RvcmUuZW5kQmF0Y2goKTtcbiAgICAgIHRoaXMuZWRpdCA9IG51bGw7XG4gICAgfVxuICB9XG5cbiAgLy8g4pSA4pSAIGNvbW1pdCB0byB0aGUgc3RvcmUg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG4gIHByaXZhdGUgY29tbWl0UmVjdGFuZ2xlKHg6IG51bWJlciwgeTogbnVtYmVyLCB3OiBudW1iZXIsIGg6IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnN0IHJlZ2lvbiA9IG5ldyBSZWdpb24oKTtcbiAgICBjb25zdCByZWN0ID0gbmV3IFJlY3RhbmdsZSgpO1xuICAgIHJlY3QueCA9IHg7IHJlY3QueSA9IHk7IHJlY3Qud2lkdGggPSB3OyByZWN0LmhlaWdodCA9IGg7XG4gICAgcmVnaW9uLmJvdW5kcyA9IHJlY3Q7XG4gICAgcmVnaW9uLmNvbG9yID0gdGhpcy5zdG9yZS5nZXRTaGFwZUNvbG9yKCk7XG4gICAgdGhpcy5jb21taXRSZWdpb24ocmVnaW9uKTtcbiAgfVxuXG4gIHByaXZhdGUgY29tbWl0UG9seWdvbihjbG9zZWQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICBpZiAodGhpcy5wb2x5UG9pbnRzLmxlbmd0aCA8IChjbG9zZWQgPyAzIDogMikpIHsgdGhpcy5yZXNldEluUHJvZ3Jlc3MoKTsgcmV0dXJuOyB9XG4gICAgY29uc3QgcmVnaW9uID0gbmV3IFJlZ2lvbigpO1xuICAgIGNvbnN0IHBvbHkgPSBuZXcgUG9seWdvbigpO1xuICAgIHBvbHkubnBvaW50cyA9IHRoaXMucG9seVBvaW50cy5sZW5ndGg7XG4gICAgcG9seS54cG9pbnRzID0gdGhpcy5wb2x5UG9pbnRzLm1hcChwID0+IHAueCk7XG4gICAgcG9seS55cG9pbnRzID0gdGhpcy5wb2x5UG9pbnRzLm1hcChwID0+IHAueSk7XG4gICAgcG9seS5jb29yZGluYXRlcyA9IHRoaXMucG9seVBvaW50cy5tYXAocCA9PiBbcC54LCBwLnldKTtcbiAgICBwb2x5LmNsb3NlZCA9IGNsb3NlZDtcbiAgICByZWdpb24uYm91bmRzID0gcG9seTtcbiAgICByZWdpb24uY29sb3IgPSB0aGlzLnN0b3JlLmdldFNoYXBlQ29sb3IoKTtcbiAgICB0aGlzLnJlc2V0SW5Qcm9ncmVzcygpO1xuICAgIHRoaXMuY29tbWl0UmVnaW9uKHJlZ2lvbik7XG4gIH1cblxuICAvKipcbiAgICogQWRkIGEgZnJlc2hseS1kcmF3biByZWdpb24gdG8gdGhlIHNoYXJlZCBzdG9yZSBhbmQgcmVkcmF3IGltbWVkaWF0ZWx5LiBUaGVcbiAgICogc3RvcmUgbWludHMgdGhlIGlkLCBzZWxlY3RzIHRoZSBuZXcgcmVnaW9uIChzbyBpdCByZW5kZXJzIHNvbGlkL2hpZ2hsaWdodGVkXG4gICAqIHJhdGhlciB0aGFuIGFzIGEgZGFzaGVkIGluLXByb2dyZXNzIHNoYXBlKSBhbmQgZW1pdHMgdGhlIGZ1bGwgcmVnaW9uIGxpc3QgdG9cbiAgICogdGhlIFJlZ2lvbiBFZGl0b3Ig4oCUIHdlIHN0aWxsIHJlZHJhdyBsb2NhbGx5IHJhdGhlciB0aGFuIHJlbHlpbmcgc29sZWx5IG9uXG4gICAqIHRoZSBzdG9yZSdzIHVwZGF0ZSBldmVudCwgd2hpY2ggY2FuIGJlIHN3YWxsb3dlZCB3aGVuIFBsb3RseSBpc24ndCBhY3RpdmUuXG4gICAqL1xuICBwcml2YXRlIGNvbW1pdFJlZ2lvbihyZWdpb246IFJlZ2lvbik6IHZvaWQge1xuICAgIC8vIERlZmF1bHQgY2xhc3MvYW5ub3RhdGlvbiBuYW1lLCBtYXRjaGluZyB0aGUgUGxvdGx5IGJhY2tlbmQgYW5kIHRoZSBSZWdpb25cbiAgICAvLyBFZGl0b3IncyBcIkFkZFwiIGFjdGlvbnMgc28gYSBmcmVzaGx5IGRyYXduIHJlZ2lvbiBpc24ndCB1bmxhYmVsZWQuXG4gICAgaWYgKHJlZ2lvbi5sYWJlbCA9PSBudWxsKSByZWdpb24ubGFiZWwgPSAnUmVnaW9uJztcbiAgICB0aGlzLnN0b3JlLmFkZFJlZ2lvbihyZWdpb24pO1xuICAgIHRoaXMucmVkcmF3KCk7XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydCB0aGUgc2VsZWN0ZWQgcmVnaW9uKHMpIHRvL2Zyb20gYSBiZXppZXIgY3VydmUgKHRvQmV6aWVyID0gdHJ1ZSAvXG4gICAqIHRvUG9seWdvbiA9IGZhbHNlKS4gT25lLXNob3Q7IHRoZSBhbmNob3JzIGFyZSB1bmNoYW5nZWQsXG4gICAqIG9ubHkgdGhlIHNtb290aC1jdXJ2ZSByZW5kZXJpbmcgaXMgdG9nZ2xlZC5cbiAgICovXG4gIHNldFNlbGVjdGVkQmV6aWVyKGJlemllcjogYm9vbGVhbik6IHZvaWQge1xuICAgIGNvbnN0IHJlZ2lvbnMgPSB0aGlzLnN0b3JlLmdldFJlZ2lvbnMoKTtcbiAgICBmb3IgKGNvbnN0IGlkeCBvZiB0aGlzLnNlbGVjdGVkKSB7XG4gICAgICBjb25zdCByZWdpb24gPSByZWdpb25zW2lkeF07XG4gICAgICBpZiAocmVnaW9uKSB0aGlzLnN0b3JlLnNldEJlemllcihyZWdpb24uaWQsIGJlemllcik7XG4gICAgfVxuICAgIHRoaXMucmVkcmF3KCk7XG4gIH1cbn1cbiJdfQ==