@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,488 @@
1
+ import { OSD } from './osd-lib';
2
+ export class SliceCache {
3
+ constructor(host) {
4
+ this.host = host;
5
+ /** z-slice → its TiledImage in the viewer world (composite path). */
6
+ this.sliceItems = new Map();
7
+ /** Multichannel per-slice cache: z → the N channel TiledImages for that slice
8
+ * (additively composited by OSD; index = channel). Only the active slice's
9
+ * visible channels have opacity > 0. */
10
+ this.channelSliceItems = new Map();
11
+ /** Cached multichannel slices whose tiles were tinted before the latest
12
+ * display change; re-tinted lazily when next revealed by z-scrub. */
13
+ this.staleSlices = new Set();
14
+ /** Most-recently-shown z last; drives LRU eviction. */
15
+ this.sliceLru = [];
16
+ /** z-slices whose tiled image is being added (dedupe rapid scrubbing). */
17
+ this.slicesLoading = new Set();
18
+ /** Bumped whenever the loaded image changes; in-flight background slice adds
19
+ * captured under an older token are dropped (cancelled image switch). */
20
+ this.sliceLoadToken = 0;
21
+ /** The slice the background loader is currently waiting on (its tiles are
22
+ * still streaming): addTiledImage 'success' fires on add, not on tile load,
23
+ * so we gate the next slice on getFullyLoaded(). */
24
+ this.bgLoadingZ = null;
25
+ /** When bgLoadingZ started loading — a fallback so a slow/stuck slice can't
26
+ * stall the whole background pass forever. */
27
+ this.bgLoadingSince = 0;
28
+ /** Slices the background loader has already attempted (no tight retry loop). */
29
+ this.bgAttempted = new Set();
30
+ /** Max cached slice tiled images kept resident before LRU eviction. */
31
+ this.maxCachedSlices = 8;
32
+ /** Upper bound on resident slices, regardless of stack depth (memory guard). */
33
+ this.MAX_CACHED_SLICES_CAP = 64;
34
+ /** Fit-view tile budget above which background preloading is skipped: a huge
35
+ * no-pyramid stack would preload every slice at full resolution and
36
+ * flood/timeout. Normal stacks stay below it and KEEP the flicker-free
37
+ * pre-cache. */
38
+ this.MAX_PREFETCH_FIT_TILES = 256;
39
+ /** True only for stacks too large to background-preload. */
40
+ this.skipSlicePrefetch = false;
41
+ this.prefetchTimer = null;
42
+ }
43
+ // ── configuration (per image, from plot()) ────────────────────────────
44
+ /** Size the cache for the loaded image: keep the whole stack resident
45
+ * (capped) so the background loader fills every slice without evicting
46
+ * itself; skip preloading entirely when even the coarsest level's tile
47
+ * grid is too large (its slices only exist at full resolution). */
48
+ configure(stackDepth, coarseFitTiles) {
49
+ this.skipSlicePrefetch = coarseFitTiles > this.MAX_PREFETCH_FIT_TILES;
50
+ this.maxCachedSlices =
51
+ stackDepth > 1 ? Math.min(this.MAX_CACHED_SLICES_CAP, stackDepth) : 1;
52
+ }
53
+ /** Current LRU cap (the viewer sizes its tile cache from it). */
54
+ maxSlices() {
55
+ return this.maxCachedSlices;
56
+ }
57
+ /** Drop the per-channel groups (on a fresh plot). */
58
+ clearChannelGroups() {
59
+ this.channelSliceItems.clear();
60
+ }
61
+ /** Seed the cache with the just-opened composite slice (world item 0), so
62
+ * scrubbing back to it later is an instant opacity toggle, not a re-open. */
63
+ seedComposite(z, item) {
64
+ this.sliceItems.set(z, item);
65
+ this.touchSliceLru(z);
66
+ }
67
+ // ── slice display (setZIndex's cache work) ────────────────────────────
68
+ /** Show slice z: reveal it instantly when cached (re-tinting a stale
69
+ * multichannel group), otherwise add it once. The current slice stays
70
+ * visible until the new one is in — no white-flicker. */
71
+ showSlice(z) {
72
+ if (this.host.isMultiChannel()) {
73
+ const group = this.channelSliceItems.get(z);
74
+ if (group && group.length && group.some((it) => it && this.sliceInWorld(it))) {
75
+ this.revealChannelSlice(z);
76
+ // If a display change happened while this slice was cached, its tiles
77
+ // hold a stale tint — re-apply now (it's the visible slice, so the
78
+ // brief restore flash is acceptable, like a fresh load).
79
+ if (this.staleSlices.delete(z))
80
+ this.invalidateSlice(z);
81
+ this.touchSliceLru(z);
82
+ this.schedulePrefetch();
83
+ }
84
+ else if (!this.slicesLoading.has(z)) {
85
+ this.addChannelSlice(z);
86
+ }
87
+ return;
88
+ }
89
+ const cached = this.sliceItems.get(z);
90
+ if (cached && this.sliceInWorld(cached)) {
91
+ // Instant: reveal the cached slice, hide the others — no fetch/decode.
92
+ this.showOnlySlice(z);
93
+ this.touchSliceLru(z);
94
+ this.schedulePrefetch();
95
+ return;
96
+ }
97
+ if (this.slicesLoading.has(z))
98
+ return; // already being added; success reveals it
99
+ this.addSlice(z);
100
+ }
101
+ /** Add a never-seen slice as a hidden tiled image, then reveal it once loaded
102
+ * (composite path; multichannel routes to addChannelSlice). */
103
+ addSlice(z) {
104
+ if (!this.host.hasImage())
105
+ return;
106
+ if (this.host.isMultiChannel()) {
107
+ this.addChannelSlice(z);
108
+ return;
109
+ }
110
+ this.slicesLoading.add(z);
111
+ // Tag this add to the current image; if the user switches images before it
112
+ // resolves, the stale callback is dropped (the add belongs to the old stack).
113
+ const token = this.sliceLoadToken;
114
+ const ts = this.host.buildTileSource(z);
115
+ try {
116
+ // addTiledImage lives on the Viewer (it queues the add into the world).
117
+ this.host.viewer().addTiledImage({
118
+ tileSource: ts,
119
+ x: 0,
120
+ y: 0,
121
+ width: 1, // match the primary image's normalized placement
122
+ opacity: 0,
123
+ // Load tiles even though it's hidden — this is what lets the background
124
+ // loader fill every slice's cache so scrubbing gets progressively smoother.
125
+ preload: true,
126
+ success: (e) => {
127
+ const item = e?.item;
128
+ if (token !== this.sliceLoadToken) {
129
+ // Image switched while this was adding — drop the orphan so it stops
130
+ // loading instead of streaming tiles for the abandoned stack.
131
+ if (item) {
132
+ try {
133
+ this.host.viewer()?.world?.removeItem(item);
134
+ }
135
+ catch { /* gone */ }
136
+ }
137
+ return;
138
+ }
139
+ this.slicesLoading.delete(z);
140
+ if (!item)
141
+ return;
142
+ this.sliceItems.set(z, item);
143
+ this.touchSliceLru(z);
144
+ this.host.onCompositeSliceAdded(z);
145
+ // Only reveal if the user is still on this slice (fast scrubbing may
146
+ // have moved on — leave it cached/hidden for a later revisit).
147
+ if (z === this.host.currentZ()) {
148
+ this.showOnlySlice(z);
149
+ this.schedulePrefetch();
150
+ }
151
+ this.evictSliceLru();
152
+ },
153
+ error: () => {
154
+ if (token === this.sliceLoadToken)
155
+ this.slicesLoading.delete(z);
156
+ },
157
+ });
158
+ }
159
+ catch (err) {
160
+ this.slicesLoading.delete(z);
161
+ console.warn('[OSD] failed to add z-slice', err);
162
+ }
163
+ }
164
+ /**
165
+ * Add slice z's channel group: one additively-composited ('lighter' = Fiji
166
+ * "Composite") TiledImage per channel, hidden (opacity 0) until revealed.
167
+ * Each is preloaded so the background loader can pre-fill every slice.
168
+ * Cached so a revisit is an instant opacity toggle — no re-fetch, no
169
+ * white-flicker. Mirrors addSlice for the composite path.
170
+ */
171
+ addChannelSlice(z) {
172
+ if (!this.host.hasImage())
173
+ return;
174
+ if (this.channelSliceItems.has(z) || this.slicesLoading.has(z))
175
+ return;
176
+ this.slicesLoading.add(z);
177
+ const token = this.sliceLoadToken;
178
+ const n = this.host.channelCount();
179
+ const group = new Array(n);
180
+ let settled = 0;
181
+ const onSettled = () => {
182
+ if (++settled < n)
183
+ return;
184
+ if (token !== this.sliceLoadToken)
185
+ return; // image switched mid-add
186
+ this.slicesLoading.delete(z);
187
+ this.channelSliceItems.set(z, group);
188
+ this.staleSlices.delete(z); // freshly tinted at the current display state
189
+ this.touchSliceLru(z);
190
+ if (z === this.host.currentZ()) {
191
+ this.revealChannelSlice(z); // tiles may still be decoding; opacity is set now
192
+ this.schedulePrefetch();
193
+ }
194
+ this.evictSliceLru();
195
+ };
196
+ for (let c = 0; c < n; c++) {
197
+ try {
198
+ this.host.viewer().addTiledImage({
199
+ tileSource: this.host.buildTileSource(z, c),
200
+ x: 0, y: 0, width: 1,
201
+ opacity: 0, // revealed by revealChannelSlice once the group is in
202
+ compositeOperation: 'lighter',
203
+ preload: true,
204
+ success: (e) => {
205
+ const item = e?.item;
206
+ if (token !== this.sliceLoadToken) {
207
+ if (item) {
208
+ try {
209
+ this.host.viewer()?.world?.removeItem(item);
210
+ }
211
+ catch { /* gone */ }
212
+ }
213
+ return;
214
+ }
215
+ if (item)
216
+ group[c] = item;
217
+ onSettled();
218
+ },
219
+ error: () => onSettled(),
220
+ });
221
+ }
222
+ catch (err) {
223
+ console.warn('[OSD] failed to add channel slice image', z, c, err);
224
+ onSettled();
225
+ }
226
+ }
227
+ }
228
+ /** Reveal slice z's channel group (each visible channel → opacity 1) and
229
+ * hide every other cached slice's group. Instant; no fetch/decode. */
230
+ revealChannelSlice(z) {
231
+ for (const [zz, group] of this.channelSliceItems) {
232
+ const active = zz === z;
233
+ group.forEach((it, c) => {
234
+ if (!it)
235
+ return;
236
+ const visible = this.host.channelVisible(c);
237
+ try {
238
+ it.setOpacity(active && visible ? 1 : 0);
239
+ }
240
+ catch { /* gone */ }
241
+ });
242
+ }
243
+ }
244
+ /** Show the given composite slice (opacity 1) and hide all other cached slices. */
245
+ showOnlySlice(z) {
246
+ for (const [zz, item] of this.sliceItems) {
247
+ try {
248
+ item.setOpacity(zz === z ? 1 : 0);
249
+ }
250
+ catch { /* item gone */ }
251
+ }
252
+ }
253
+ // ── display invalidation (multichannel) ───────────────────────────────
254
+ /** Re-tint after a display change: invalidate ONLY the visible slice's
255
+ * channel images — invalidating the whole world would re-process every
256
+ * hidden/preloaded slice's tiles (hundreds), flooding OSD and wasting work
257
+ * on tiles that aren't on screen. The other cached slices are marked stale
258
+ * and re-tinted lazily when revealed. */
259
+ invalidateChannelDisplay(z) {
260
+ this.invalidateSlice(z);
261
+ this.staleSlices.clear();
262
+ for (const zz of this.channelSliceItems.keys()) {
263
+ if (zz !== z)
264
+ this.staleSlices.add(zz);
265
+ }
266
+ }
267
+ /** Invalidate (restore + re-recolor) just the channel images of one cached
268
+ * slice. A shared timestamp batches the per-image invalidations into one
269
+ * processing pass (OSD dedupes tiles already stamped at >= tStamp). */
270
+ invalidateSlice(z) {
271
+ const group = this.channelSliceItems.get(z) ?? [];
272
+ if (!group.length)
273
+ return;
274
+ const osd = OSD;
275
+ const tStamp = typeof osd.now === 'function' ? osd.now() : Date.now();
276
+ for (const it of group) {
277
+ if (it && typeof it.requestInvalidate === 'function') {
278
+ try {
279
+ it.requestInvalidate(true, false, tStamp);
280
+ }
281
+ catch { /* gone */ }
282
+ }
283
+ }
284
+ }
285
+ // ── background stack preloading ───────────────────────────────────────
286
+ /** Debounce so a burst of viewport/slice events coalesces, then advance the
287
+ * background stack loader by one slice. */
288
+ schedulePrefetch() {
289
+ if (this.skipSlicePrefetch)
290
+ return;
291
+ if (this.prefetchTimer)
292
+ clearTimeout(this.prefetchTimer);
293
+ this.prefetchTimer = setTimeout(() => this.loadNextBackgroundSlice(), 200);
294
+ }
295
+ /**
296
+ * Background-load the whole stack: add each not-yet-cached slice as a
297
+ * hidden, preloaded tiled image, one at a time, working outward from the
298
+ * current slice — and never blocking the visible slice (it yields while the
299
+ * current view is still streaming tiles; only one slice is in flight at a
300
+ * time so the on-screen tiles always win the connection).
301
+ */
302
+ loadNextBackgroundSlice() {
303
+ this.prefetchTimer = null;
304
+ if (!this.host.hasImage())
305
+ return;
306
+ const sliceCount = this.host.sliceCount();
307
+ if (sliceCount <= 1)
308
+ return; // not a stack — nothing to preload
309
+ // Yield to the visible slice while it's still streaming tiles.
310
+ if (this.sliceTilesLoading(this.host.currentZ())) {
311
+ this.schedulePrefetch();
312
+ return;
313
+ }
314
+ // Gate on the in-flight slice's TILES finishing — addTiledImage's success
315
+ // fires on add, not on tile load, so without this we'd add the whole stack
316
+ // at once and flood the connection. A time fallback prevents a stuck slice
317
+ // from stalling the pass.
318
+ if (this.bgLoadingZ != null) {
319
+ const adding = this.slicesLoading.has(this.bgLoadingZ);
320
+ const tilesLoading = this.sliceTilesLoading(this.bgLoadingZ);
321
+ const timedOut = Date.now() - this.bgLoadingSince > 8000;
322
+ if ((adding || tilesLoading) && !timedOut) {
323
+ this.schedulePrefetch();
324
+ return;
325
+ }
326
+ this.bgLoadingZ = null; // that slice's tiles are in (or gave up) — advance
327
+ }
328
+ const next = this.nearestUncachedSlice(sliceCount);
329
+ if (next == null)
330
+ return; // whole stack cached — done
331
+ this.bgLoadingZ = next;
332
+ this.bgLoadingSince = Date.now();
333
+ this.bgAttempted.add(next);
334
+ this.addSlice(next); // hidden + preload (added with opacity 0; not revealed)
335
+ this.schedulePrefetch(); // poll until its tiles load, then advance
336
+ }
337
+ /** The not-yet-cached slice closest to the current one (load nearest first),
338
+ * skipping any already attempted so a failed/slow one isn't retried in a loop. */
339
+ nearestUncachedSlice(sliceCount) {
340
+ const cur = this.host.currentZ();
341
+ for (let d = 0; d < sliceCount; d++) {
342
+ const candidates = d === 0 ? [cur] : [cur - d, cur + d];
343
+ for (const z of candidates) {
344
+ if (z >= 0 && z < sliceCount &&
345
+ !this.sliceCacheHas(z) && !this.slicesLoading.has(z) && !this.bgAttempted.has(z)) {
346
+ return z;
347
+ }
348
+ }
349
+ }
350
+ return null;
351
+ }
352
+ /**
353
+ * Stop background stack preloading and invalidate any in-flight slice add.
354
+ * Called when a different image is selected so the previous stack stops
355
+ * loading immediately instead of finishing in the background.
356
+ */
357
+ cancelBackgroundLoad() {
358
+ if (this.prefetchTimer) {
359
+ clearTimeout(this.prefetchTimer);
360
+ this.prefetchTimer = null;
361
+ }
362
+ this.slicesLoading.clear();
363
+ this.bgLoadingZ = null;
364
+ this.bgAttempted.clear();
365
+ this.sliceLoadToken++; // drop pending addTiledImage callbacks from the old image
366
+ // Abort in-flight background tiles immediately by dropping the hidden
367
+ // preloaded slices (removeItem cancels their pending tile loads). Keep the
368
+ // visible slice so the current view doesn't blank before the next plot.
369
+ this.dropHiddenSlices();
370
+ }
371
+ /** Remove every cached slice except the currently displayed one, aborting
372
+ * their in-flight tile requests. */
373
+ dropHiddenSlices() {
374
+ const v = this.host.viewer();
375
+ if (!v)
376
+ return;
377
+ const cur = this.host.currentZ();
378
+ for (const [z, item] of [...this.sliceItems]) {
379
+ if (z === cur)
380
+ continue;
381
+ this.sliceItems.delete(z);
382
+ try {
383
+ v.world.removeItem(item);
384
+ }
385
+ catch { /* already gone */ }
386
+ }
387
+ for (const [z, group] of [...this.channelSliceItems]) {
388
+ if (z === cur)
389
+ continue;
390
+ this.channelSliceItems.delete(z);
391
+ for (const it of group) {
392
+ if (it) {
393
+ try {
394
+ v.world.removeItem(it);
395
+ }
396
+ catch { /* gone */ }
397
+ }
398
+ }
399
+ }
400
+ this.sliceLru = this.sliceCacheHas(cur) ? [cur] : [];
401
+ }
402
+ // ── cache bookkeeping ─────────────────────────────────────────────────
403
+ /** Whether slice z is in the active cache (composite single image, or the
404
+ * multichannel per-channel group). */
405
+ sliceCacheHas(z) {
406
+ return this.host.isMultiChannel() ? this.channelSliceItems.has(z) : this.sliceItems.has(z);
407
+ }
408
+ /** The cached TiledImage(s) for slice z (0–1 for composite, N for multichannel). */
409
+ sliceGroup(z) {
410
+ if (this.host.isMultiChannel())
411
+ return this.channelSliceItems.get(z) ?? [];
412
+ const it = this.sliceItems.get(z);
413
+ return it ? [it] : [];
414
+ }
415
+ /** Whether slice z's tiles are still streaming (any cached image not fully loaded). */
416
+ sliceTilesLoading(z) {
417
+ const g = this.sliceGroup(z);
418
+ if (!g.length)
419
+ return false;
420
+ return g.some((it) => it && typeof it.getFullyLoaded === 'function' && !it.getFullyLoaded());
421
+ }
422
+ /** Remove slice z's cached image(s) from the world and the active cache. */
423
+ removeCachedSlice(z) {
424
+ const v = this.host.viewer();
425
+ if (this.host.isMultiChannel()) {
426
+ const group = this.channelSliceItems.get(z);
427
+ this.channelSliceItems.delete(z);
428
+ if (group && v)
429
+ for (const it of group) {
430
+ if (it) {
431
+ try {
432
+ v.world.removeItem(it);
433
+ }
434
+ catch { /* gone */ }
435
+ }
436
+ }
437
+ }
438
+ else {
439
+ const item = this.sliceItems.get(z);
440
+ this.sliceItems.delete(z);
441
+ if (item && v) {
442
+ try {
443
+ v.world.removeItem(item);
444
+ }
445
+ catch { /* gone */ }
446
+ }
447
+ }
448
+ }
449
+ /** Is the tiled image still in the world (not evicted)? */
450
+ sliceInWorld(item) {
451
+ try {
452
+ return this.host.viewer().world.getIndexOfItem(item) >= 0;
453
+ }
454
+ catch {
455
+ return false;
456
+ }
457
+ }
458
+ /** Mark z as most-recently-used. */
459
+ touchSliceLru(z) {
460
+ const i = this.sliceLru.indexOf(z);
461
+ if (i >= 0)
462
+ this.sliceLru.splice(i, 1);
463
+ this.sliceLru.push(z);
464
+ }
465
+ /** Drop the least-recently-used cached slices beyond the cap (never the
466
+ * current one), removing their tiled images so memory stays bounded. */
467
+ evictSliceLru() {
468
+ while (this.sliceLru.length > this.maxCachedSlices) {
469
+ const cur = this.host.currentZ();
470
+ const idx = this.sliceLru.findIndex((z) => z !== cur);
471
+ if (idx < 0)
472
+ break;
473
+ const z = this.sliceLru.splice(idx, 1)[0];
474
+ this.removeCachedSlice(z);
475
+ }
476
+ }
477
+ /** Clear the cache (on teardown / image switch). */
478
+ reset() {
479
+ this.sliceItems.clear();
480
+ this.channelSliceItems.clear();
481
+ this.staleSlices.clear();
482
+ this.sliceLru = [];
483
+ this.slicesLoading.clear();
484
+ this.bgLoadingZ = null;
485
+ this.bgAttempted.clear();
486
+ }
487
+ }
488
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2xpY2UtY2FjaGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbGliL2ltcGxlbWVudGF0aW9ucy9vc2Qvc2xpY2UtY2FjaGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQXlDaEMsTUFBTSxPQUFPLFVBQVU7SUF1Q3JCLFlBQW9CLElBQW9CO1FBQXBCLFNBQUksR0FBSixJQUFJLENBQWdCO1FBdEN4QyxxRUFBcUU7UUFDN0QsZUFBVSxHQUFHLElBQUksR0FBRyxFQUFlLENBQUM7UUFDNUM7O2lEQUV5QztRQUNqQyxzQkFBaUIsR0FBRyxJQUFJLEdBQUcsRUFBaUIsQ0FBQztRQUNyRDs4RUFDc0U7UUFDOUQsZ0JBQVcsR0FBRyxJQUFJLEdBQUcsRUFBVSxDQUFDO1FBQ3hDLHVEQUF1RDtRQUMvQyxhQUFRLEdBQWEsRUFBRSxDQUFDO1FBQ2hDLDBFQUEwRTtRQUNsRSxrQkFBYSxHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7UUFDMUM7a0ZBQzBFO1FBQ2xFLG1CQUFjLEdBQUcsQ0FBQyxDQUFDO1FBQzNCOzs2REFFcUQ7UUFDN0MsZUFBVSxHQUFrQixJQUFJLENBQUM7UUFDekM7dURBQytDO1FBQ3ZDLG1CQUFjLEdBQUcsQ0FBQyxDQUFDO1FBQzNCLGdGQUFnRjtRQUN4RSxnQkFBVyxHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7UUFDeEMsdUVBQXVFO1FBQy9ELG9CQUFlLEdBQUcsQ0FBQyxDQUFDO1FBQzVCLGdGQUFnRjtRQUMvRCwwQkFBcUIsR0FBRyxFQUFFLENBQUM7UUFDNUM7Ozt5QkFHaUI7UUFDQSwyQkFBc0IsR0FBRyxHQUFHLENBQUM7UUFDOUMsNERBQTREO1FBQ3BELHNCQUFpQixHQUFHLEtBQUssQ0FBQztRQUMxQixrQkFBYSxHQUFRLElBQUksQ0FBQztJQUVTLENBQUM7SUFFNUMseUVBQXlFO0lBRXpFOzs7d0VBR29FO0lB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Q0FBQztZQUNuRCxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ2pDLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEtBQUssR0FBRyxDQUFDLENBQUM7WUFDdEQsSUFBSSxHQUFHLEdBQUcsQ0FBQztnQkFBRSxNQUFNO1lBQ25CLE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUMxQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDNUIsQ0FBQztJQUNILENBQUM7SUFFRCxvREFBb0Q7SUFDcEQsS0FBSztRQUNILElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDeEIsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEtBQUssRUFBRSxDQUFDO1FBQy9CLElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDekIsSUFBSSxDQUFDLFFBQVEsR0FBRyxFQUFFLENBQUM7UUFDbkIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUMzQixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQztRQUN2QixJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQzNCLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE9TRCB9IGZyb20gJy4vb3NkLWxpYic7XG5cbi8qKlxuICogU3RhY2stc2xpY2UgY2FjaGUgZm9yIHRoZSBPcGVuU2VhZHJhZ29uIGJhY2tlbmQgKHJlZmFjdG9yaW5nIHBsYW4sIFN0ZXAgMyDigJRcbiAqIGEgcHVyZSBtb3ZlIG9mIHRoZSBjYWNoZSBjbHVzdGVyIG91dCBvZiB0aGUgdmlzdWFsaXplciBzZXJ2aWNlKS5cbiAqXG4gKiBTY3J1YmJpbmcgdGhlIHotc2xpZGVyIHVzZWQgdG8gdmlld2VyLm9wZW4oKSBhIGZyZXNoIHRpbGUgc291cmNlIHBlciBzbGljZSxcbiAqIHdoaWNoIGRlc3Ryb3lzIHRoZSBjdXJyZW50IHRpbGVkIGltYWdlIChhbmQgaXRzIGRlY29kZWQrcmVjb2xvcmVkIHRpbGVzKSwgc29cbiAqIHJldmlzaXRpbmcgYSBzbGljZSByZS1mZXRjaGVkIGV2ZXJ5dGhpbmcuIEluc3RlYWQgd2Uga2VlcCBlYWNoIHZpc2l0ZWQgc2xpY2VcbiAqIGFzIGl0cyBvd24gdGlsZWQgaW1hZ2UgaW4gdGhlIHdvcmxkIGFuZCBqdXN0IHRvZ2dsZSBvcGFjaXR5IOKAlCBhIHJldmlzaXRlZFxuICogc2xpY2UgaXMgaW5zdGFudCAobm8gbmV0d29yaywgbm8gcmUtZGVjb2RlLCBubyByZS1yZWNvbG9yKS4gQm91bmRlZCBieSBhblxuICogTFJVIHNvIGRlZXAgc3RhY2tzIGRvbid0IGdyb3cgd2l0aG91dCBsaW1pdC4gTXVsdGljaGFubmVsIHNsaWNlcyBjYWNoZSBvbmVcbiAqIFRpbGVkSW1hZ2UgcGVyIGNoYW5uZWwgKGFkZGl0aXZlbHkgY29tcG9zaXRlZCk7IGNvbXBvc2l0ZSBzbGljZXMgY2FjaGUgb25lLlxuICogQSBiYWNrZ3JvdW5kIGxvYWRlciBwcmUtZmlsbHMgdGhlIHJlc3Qgb2YgdGhlIHN0YWNrLCBvbmUgc2xpY2UgYXQgYSB0aW1lLFxuICogeWllbGRpbmcgdG8gdGhlIHZpc2libGUgc2xpY2Ugc28gb24tc2NyZWVuIHRpbGVzIGFsd2F5cyB3aW4gdGhlIGNvbm5lY3Rpb24uXG4gKi9cblxuLyoqIFdoYXQgdGhlIGNhY2hlIG5lZWRzIGZyb20gdGhlIHZpc3VhbGl6ZXIgc2VydmljZS4gQWxsIGFjY2Vzc29ycyBhcmUgbGl2ZVxuICogIChjYWxsZWQgYXQgdXNlIHRpbWUsIG5ldmVyIGNhcHR1cmVkKSBzbyB0aGUgY2FjaGUgYWx3YXlzIHNlZXMgdGhlIGN1cnJlbnRcbiAqICB2aWV3ZXIvZGVzY3JpcHRvci96IOKAlCBtYXRjaGluZyB0aGUgZmllbGQgcmVhZHMgaXQgcmVwbGFjZWQuICovXG5leHBvcnQgaW50ZXJmYWNlIFNsaWNlQ2FjaGVIb3N0IHtcbiAgLyoqIFRoZSBtb3VudGVkIHZpZXdlciwgb3IgbnVsbC4gKi9cbiAgdmlld2VyKCk6IGFueSB8IG51bGw7XG4gIC8qKiBUcnVlIHdoZW4gYSB2aWV3ZXIsIGRlc2NyaXB0b3IgYW5kIGluZm9CNjQgYXJlIGFsbCBwcmVzZW50LiAqL1xuICBoYXNJbWFnZSgpOiBib29sZWFuO1xuICAvKiogU3RhY2sgZGVwdGggKGRlc2NyaXB0b3IueiwgMSBmb3Igc2luZ2xlIGltYWdlcykuICovXG4gIHNsaWNlQ291bnQoKTogbnVtYmVyO1xuICAvKiogVGhlIGN1cnJlbnRseSBkaXNwbGF5ZWQgei1zbGljZS4gKi9cbiAgY3VycmVudFooKTogbnVtYmVyO1xuICAvKiogUGVyLWNoYW5uZWwgcmVuZGVyaW5nIChtdWx0aWNoYW5uZWwgZmx1b3Jlc2NlbmNlKSB2cyBjb21wb3NpdGUuICovXG4gIGlzTXVsdGlDaGFubmVsKCk6IGJvb2xlYW47XG4gIC8qKiBDaGFubmVsIGNvdW50IGZvciBhIG11bHRpY2hhbm5lbCBncm91cCBhZGQuICovXG4gIGNoYW5uZWxDb3VudCgpOiBudW1iZXI7XG4gIC8qKiBDaGFubmVsIHZpc2liaWxpdHkgKGRyaXZlcyBncm91cCByZXZlYWwgb3BhY2l0eSkuICovXG4gIGNoYW5uZWxWaXNpYmxlKGM6IG51bWJlcik6IGJvb2xlYW47XG4gIC8qKiBUaWxlIHNvdXJjZSBmb3Igc2xpY2UgeiAob3B0aW9uYWxseSBvbmUgY2hhbm5lbCkuICovXG4gIGJ1aWxkVGlsZVNvdXJjZSh6OiBudW1iZXIsIGNoYW5uZWw/OiBudW1iZXIpOiBhbnk7XG4gIC8qKiBBIGNvbXBvc2l0ZSBzbGljZSBsYW5kZWQgaW4gdGhlIHdvcmxkIOKAlCB0aGUgc2VydmljZSBzYW1wbGVzIGl0cyB3aW5kb3cuICovXG4gIG9uQ29tcG9zaXRlU2xpY2VBZGRlZCh6OiBudW1iZXIpOiB2b2lkO1xufVxuXG5leHBvcnQgY2xhc3MgU2xpY2VDYWNoZSB7XG4gIC8qKiB6LXNsaWNlIOKGkiBpdHMgVGlsZWRJbWFnZSBpbiB0aGUgdmlld2VyIHdvcmxkIChjb21wb3NpdGUgcGF0aCkuICovXG4gIHByaXZhdGUgc2xpY2VJdGVtcyA9IG5ldyBNYXA8bnVtYmVyLCBhbnk+KCk7XG4gIC8qKiBNdWx0aWNoYW5uZWwgcGVyLXNsaWNlIGNhY2hlOiB6IOKGkiB0aGUgTiBjaGFubmVsIFRpbGVkSW1hZ2VzIGZvciB0aGF0IHNsaWNlXG4gICAqICAoYWRkaXRpdmVseSBjb21wb3NpdGVkIGJ5IE9TRDsgaW5kZXggPSBjaGFubmVsKS4gT25seSB0aGUgYWN0aXZlIHNsaWNlJ3NcbiAgICogIHZpc2libGUgY2hhbm5lbHMgaGF2ZSBvcGFjaXR5ID4gMC4gKi9cbiAgcHJpdmF0ZSBjaGFubmVsU2xpY2VJdGVtcyA9IG5ldyBNYXA8bnVtYmVyLCBhbnlbXT4oKTtcbiAgLyoqIENhY2hlZCBtdWx0aWNoYW5uZWwgc2xpY2VzIHdob3NlIHRpbGVzIHdlcmUgdGludGVkIGJlZm9yZSB0aGUgbGF0ZXN0XG4gICAqICBkaXNwbGF5IGNoYW5nZTsgcmUtdGludGVkIGxhemlseSB3aGVuIG5leHQgcmV2ZWFsZWQgYnkgei1zY3J1Yi4gKi9cbiAgcHJpdmF0ZSBzdGFsZVNsaWNlcyA9IG5ldyBTZXQ8bnVtYmVyPigpO1xuICAvKiogTW9zdC1yZWNlbnRseS1zaG93biB6IGxhc3Q7IGRyaXZlcyBMUlUgZXZpY3Rpb24uICovXG4gIHByaXZhdGUgc2xpY2VMcnU6IG51bWJlcltdID0gW107XG4gIC8qKiB6LXNsaWNlcyB3aG9zZSB0aWxlZCBpbWFnZSBpcyBiZWluZyBhZGRlZCAoZGVkdXBlIHJhcGlkIHNjcnViYmluZykuICovXG4gIHByaXZhdGUgc2xpY2VzTG9hZGluZyA9IG5ldyBTZXQ8bnVtYmVyPigpO1xuICAvKiogQnVtcGVkIHdoZW5ldmVyIHRoZSBsb2FkZWQgaW1hZ2UgY2hhbmdlczsgaW4tZmxpZ2h0IGJhY2tncm91bmQgc2xpY2UgYWRkc1xuICAgKiAgY2FwdHVyZWQgdW5kZXIgYW4gb2xkZXIgdG9rZW4gYXJlIGRyb3BwZWQgKGNhbmNlbGxlZCBpbWFnZSBzd2l0Y2gpLiAqL1xuICBwcml2YXRlIHNsaWNlTG9hZFRva2VuID0gMDtcbiAgLyoqIFRoZSBzbGljZSB0aGUgYmFja2dyb3VuZCBsb2FkZXIgaXMgY3VycmVudGx5IHdhaXRpbmcgb24gKGl0cyB0aWxlcyBhcmVcbiAgICogIHN0aWxsIHN0cmVhbWluZyk6IGFkZFRpbGVkSW1hZ2UgJ3N1Y2Nlc3MnIGZpcmVzIG9uIGFkZCwgbm90IG9uIHRpbGUgbG9hZCxcbiAgICogIHNvIHdlIGdhdGUgdGhlIG5leHQgc2xpY2Ugb24gZ2V0RnVsbHlMb2FkZWQoKS4gKi9cbiAgcHJpdmF0ZSBiZ0xvYWRpbmdaOiBudW1iZXIgfCBudWxsID0gbnVsbDtcbiAgLyoqIFdoZW4gYmdMb2FkaW5nWiBzdGFydGVkIGxvYWRpbmcg4oCUIGEgZmFsbGJhY2sgc28gYSBzbG93L3N0dWNrIHNsaWNlIGNhbid0XG4gICAqICBzdGFsbCB0aGUgd2hvbGUgYmFja2dyb3VuZCBwYXNzIGZvcmV2ZXIuICovXG4gIHByaXZhdGUgYmdMb2FkaW5nU2luY2UgPSAwO1xuICAvKiogU2xpY2VzIHRoZSBiYWNrZ3JvdW5kIGxvYWRlciBoYXMgYWxyZWFkeSBhdHRlbXB0ZWQgKG5vIHRpZ2h0IHJldHJ5IGxvb3ApLiAqL1xuICBwcml2YXRlIGJnQXR0ZW1wdGVkID0gbmV3IFNldDxudW1iZXI+KCk7XG4gIC8qKiBNYXggY2FjaGVkIHNsaWNlIHRpbGVkIGltYWdlcyBrZXB0IHJlc2lkZW50IGJlZm9yZSBMUlUgZXZpY3Rpb24uICovXG4gIHByaXZhdGUgbWF4Q2FjaGVkU2xpY2VzID0gODtcbiAgLyoqIFVwcGVyIGJvdW5kIG9uIHJlc2lkZW50IHNsaWNlcywgcmVnYXJkbGVzcyBvZiBzdGFjayBkZXB0aCAobWVtb3J5IGd1YXJkKS4gKi9cbiAgcHJpdmF0ZSByZWFkb25seSBNQVhfQ0FDSEVEX1NMSUNFU19DQVAgPSA2NDtcbiAgLyoqIEZpdC12aWV3IHRpbGUgYnVkZ2V0IGFib3ZlIHdoaWNoIGJhY2tncm91bmQgcHJlbG9hZGluZyBpcyBza2lwcGVkOiBhIGh1Z2VcbiAgICogIG5vLXB5cmFtaWQgc3RhY2sgd291bGQgcHJlbG9hZCBldmVyeSBzbGljZSBhdCBmdWxsIHJlc29sdXRpb24gYW5kXG4gICAqICBmbG9vZC90aW1lb3V0LiBOb3JtYWwgc3RhY2tzIHN0YXkgYmVsb3cgaXQgYW5kIEtFRVAgdGhlIGZsaWNrZXItZnJlZVxuICAgKiAgcHJlLWNhY2hlLiAqL1xuICBwcml2YXRlIHJlYWRvbmx5IE1BWF9QUkVGRVRDSF9GSVRfVElMRVMgPSAyNTY7XG4gIC8qKiBUcnVlIG9ubHkgZm9yIHN0YWNrcyB0b28gbGFyZ2UgdG8gYmFja2dyb3VuZC1wcmVsb2FkLiAqL1xuICBwcml2YXRlIHNraXBTbGljZVByZWZldGNoID0gZmFsc2U7XG4gIHByaXZhdGUgcHJlZmV0Y2hUaW1lcjogYW55ID0gbnVsbDtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGhvc3Q6IFNsaWNlQ2FjaGVIb3N0KSB7fVxuXG4gIC8vIOKUgOKUgCBjb25maWd1cmF0aW9uIChwZXIgaW1hZ2UsIGZyb20gcGxvdCgpKSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICAvKiogU2l6ZSB0aGUgY2FjaGUgZm9yIHRoZSBsb2FkZWQgaW1hZ2U6IGtlZXAgdGhlIHdob2xlIHN0YWNrIHJlc2lkZW50XG4gICAqICAoY2FwcGVkKSBzbyB0aGUgYmFja2dyb3VuZCBsb2FkZXIgZmlsbHMgZXZlcnkgc2xpY2Ugd2l0aG91dCBldmljdGluZ1xuICAgKiAgaXRzZWxmOyBza2lwIHByZWxvYWRpbmcgZW50aXJlbHkgd2hlbiBldmVuIHRoZSBjb2Fyc2VzdCBsZXZlbCdzIHRpbGVcbiAgICogIGdyaWQgaXMgdG9vIGxhcmdlIChpdHMgc2xpY2VzIG9ubHkgZXhpc3QgYXQgZnVsbCByZXNvbHV0aW9uKS4gKi9cbiAgY29uZmlndXJlKHN0YWNrRGVwdGg6IG51bWJlciwgY29hcnNlRml0VGlsZXM6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMuc2tpcFNsaWNlUHJlZmV0Y2ggPSBjb2Fyc2VGaXRUaWxlcyA+IHRoaXMuTUFYX1BSRUZFVENIX0ZJVF9USUxFUztcbiAgICB0aGlzLm1heENhY2hlZFNsaWNlcyA9XG4gICAgICBzdGFja0RlcHRoID4gMSA/IE1hdGgubWluKHRoaXMuTUFYX0NBQ0hFRF9TTElDRVNfQ0FQLCBzdGFja0RlcHRoKSA6IDE7XG4gIH1cblxuICAvKiogQ3VycmVudCBMUlUgY2FwICh0aGUgdmlld2VyIHNpemVzIGl0cyB0aWxlIGNhY2hlIGZyb20gaXQpLiAqL1xuICBtYXhTbGljZXMoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5tYXhDYWNoZWRTbGljZXM7XG4gIH1cblxuICAvKiogRHJvcCB0aGUgcGVyLWNoYW5uZWwgZ3JvdXBzIChvbiBhIGZyZXNoIHBsb3QpLiAqL1xuICBjbGVhckNoYW5uZWxHcm91cHMoKTogdm9pZCB7XG4gICAgdGhpcy5jaGFubmVsU2xpY2VJdGVtcy5jbGVhcigpO1xuICB9XG5cbiAgLyoqIFNlZWQgdGhlIGNhY2hlIHdpdGggdGhlIGp1c3Qtb3BlbmVkIGNvbXBvc2l0ZSBzbGljZSAod29ybGQgaXRlbSAwKSwgc29cbiAgICogIHNjcnViYmluZyBiYWNrIHRvIGl0IGxhdGVyIGlzIGFuIGluc3RhbnQgb3BhY2l0eSB0b2dnbGUsIG5vdCBhIHJlLW9wZW4uICovXG4gIHNlZWRDb21wb3NpdGUoejogbnVtYmVyLCBpdGVtOiBhbnkpOiB2b2lkIHtcbiAgICB0aGlzLnNsaWNlSXRlbXMuc2V0KHosIGl0ZW0pO1xuICAgIHRoaXMudG91Y2hTbGljZUxydSh6KTtcbiAgfVxuXG4gIC8vIOKUgOKUgCBzbGljZSBkaXNwbGF5IChzZXRaSW5kZXgncyBjYWNoZSB3b3JrKSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICAvKiogU2hvdyBzbGljZSB6OiByZXZlYWwgaXQgaW5zdGFudGx5IHdoZW4gY2FjaGVkIChyZS10aW50aW5nIGEgc3RhbGVcbiAgICogIG11bHRpY2hhbm5lbCBncm91cCksIG90aGVyd2lzZSBhZGQgaXQgb25jZS4gVGhlIGN1cnJlbnQgc2xpY2Ugc3RheXNcbiAgICogIHZpc2libGUgdW50aWwgdGhlIG5ldyBvbmUgaXMgaW4g4oCUIG5vIHdoaXRlLWZsaWNrZXIuICovXG4gIHNob3dTbGljZSh6OiBudW1iZXIpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5ob3N0LmlzTXVsdGlDaGFubmVsKCkpIHtcbiAgICAgIGNvbnN0IGdyb3VwID0gdGhpcy5jaGFubmVsU2xpY2VJdGVtcy5nZXQoeik7XG4gICAgICBpZiAoZ3JvdXAgJiYgZ3JvdXAubGVuZ3RoICYmIGdyb3VwLnNvbWUoKGl0KSA9PiBpdCAmJiB0aGlzLnNsaWNlSW5Xb3JsZChpdCkpKSB7XG4gICAgICAgIHRoaXMucmV2ZWFsQ2hhbm5lbFNsaWNlKHopO1xuICAgICAgICAvLyBJZiBhIGRpc3BsYXkgY2hhbmdlIGhhcHBlbmVkIHdoaWxlIHRoaXMgc2xpY2Ugd2FzIGNhY2hlZCwgaXRzIHRpbGVzXG4gICAgICAgIC8vIGhvbGQgYSBzdGFsZSB0aW50IOKAlCByZS1hcHBseSBub3cgKGl0J3MgdGhlIHZpc2libGUgc2xpY2UsIHNvIHRoZVxuICAgICAgICAvLyBicmllZiByZXN0b3JlIGZsYXNoIGlzIGFjY2VwdGFibGUsIGxpa2UgYSBmcmVzaCBsb2FkKS5cbiAgICAgICAgaWYgKHRoaXMuc3RhbGVTbGljZXMuZGVsZXRlKHopKSB0aGlzLmludmFsaWRhdGVTbGljZSh6KTtcbiAgICAgICAgdGhpcy50b3VjaFNsaWNlTHJ1KHopO1xuICAgICAgICB0aGlzLnNjaGVkdWxlUHJlZmV0Y2goKTtcbiAgICAgIH0gZWxzZSBpZiAoIXRoaXMuc2xpY2VzTG9hZGluZy5oYXMoeikpIHtcbiAgICAgICAgdGhpcy5hZGRDaGFubmVsU2xpY2Uoeik7XG4gICAgICB9XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGNhY2hlZCA9IHRoaXMuc2xpY2VJdGVtcy5nZXQoeik7XG4gICAgaWYgKGNhY2hlZCAmJiB0aGlzLnNsaWNlSW5Xb3JsZChjYWNoZWQpKSB7XG4gICAgICAvLyBJbnN0YW50OiByZXZlYWwgdGhlIGNhY2hlZCBzbGljZSwgaGlkZSB0aGUgb3RoZXJzIOKAlCBubyBmZXRjaC9kZWNvZGUuXG4gICAgICB0aGlzLnNob3dPbmx5U2xpY2Uoeik7XG4gICAgICB0aGlzLnRvdWNoU2xpY2VMcnUoeik7XG4gICAgICB0aGlzLnNjaGVkdWxlUHJlZmV0Y2goKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHRoaXMuc2xpY2VzTG9hZGluZy5oYXMoeikpIHJldHVybjsgLy8gYWxyZWFkeSBiZWluZyBhZGRlZDsgc3VjY2VzcyByZXZlYWxzIGl0XG4gICAgdGhpcy5hZGRTbGljZSh6KTtcbiAgfVxuXG4gIC8qKiBBZGQgYSBuZXZlci1zZWVuIHNsaWNlIGFzIGEgaGlkZGVuIHRpbGVkIGltYWdlLCB0aGVuIHJldmVhbCBpdCBvbmNlIGxvYWRlZFxuICAgKiAgKGNvbXBvc2l0ZSBwYXRoOyBtdWx0aWNoYW5uZWwgcm91dGVzIHRvIGFkZENoYW5uZWxTbGljZSkuICovXG4gIHByaXZhdGUgYWRkU2xpY2UoejogbnVtYmVyKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmhvc3QuaGFzSW1hZ2UoKSkgcmV0dXJuO1xuICAgIGlmICh0aGlzLmhvc3QuaXNNdWx0aUNoYW5uZWwoKSkge1xuICAgICAgdGhpcy5hZGRDaGFubmVsU2xpY2Uoeik7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuc2xpY2VzTG9hZGluZy5hZGQoeik7XG4gICAgLy8gVGFnIHRoaXMgYWRkIHRvIHRoZSBjdXJyZW50IGltYWdlOyBpZiB0aGUgdXNlciBzd2l0Y2hlcyBpbWFnZXMgYmVmb3JlIGl0XG4gICAgLy8gcmVzb2x2ZXMsIHRoZSBzdGFsZSBjYWxsYmFjayBpcyBkcm9wcGVkICh0aGUgYWRkIGJlbG9uZ3MgdG8gdGhlIG9sZCBzdGFjaykuXG4gICAgY29uc3QgdG9rZW4gPSB0aGlzLnNsaWNlTG9hZFRva2VuO1xuICAgIGNvbnN0IHRzID0gdGhpcy5ob3N0LmJ1aWxkVGlsZVNvdXJjZSh6KTtcbiAgICB0cnkge1xuICAgICAgLy8gYWRkVGlsZWRJbWFnZSBsaXZlcyBvbiB0aGUgVmlld2VyIChpdCBxdWV1ZXMgdGhlIGFkZCBpbnRvIHRoZSB3b3JsZCkuXG4gICAgICB0aGlzLmhvc3Qudmlld2VyKCkuYWRkVGlsZWRJbWFnZSh7XG4gICAgICAgIHRpbGVTb3VyY2U6IHRzLFxuICAgICAgICB4OiAwLFxuICAgICAgICB5OiAwLFxuICAgICAgICB3aWR0aDogMSwgLy8gbWF0Y2ggdGhlIHByaW1hcnkgaW1hZ2UncyBub3JtYWxpemVkIHBsYWNlbWVudFxuICAgICAgICBvcGFjaXR5OiAwLFxuICAgICAgICAvLyBMb2FkIHRpbGVzIGV2ZW4gdGhvdWdoIGl0J3MgaGlkZGVuIOKAlCB0aGlzIGlzIHdoYXQgbGV0cyB0aGUgYmFja2dyb3VuZFxuICAgICAgICAvLyBsb2FkZXIgZmlsbCBldmVyeSBzbGljZSdzIGNhY2hlIHNvIHNjcnViYmluZyBnZXRzIHByb2dyZXNzaXZlbHkgc21vb3RoZXIuXG4gICAgICAgIHByZWxvYWQ6IHRydWUsXG4gICAgICAgIHN1Y2Nlc3M6IChlOiBhbnkpID0+IHtcbiAgICAgICAgICBjb25zdCBpdGVtID0gZT8uaXRlbTtcbiAgICAgICAgICBpZiAodG9rZW4gIT09IHRoaXMuc2xpY2VMb2FkVG9rZW4pIHtcbiAgICAgICAgICAgIC8vIEltYWdlIHN3aXRjaGVkIHdoaWxlIHRoaXMgd2FzIGFkZGluZyDigJQgZHJvcCB0aGUgb3JwaGFuIHNvIGl0IHN0b3BzXG4gICAgICAgICAgICAvLyBsb2FkaW5nIGluc3RlYWQgb2Ygc3RyZWFtaW5nIHRpbGVzIGZvciB0aGUgYWJhbmRvbmVkIHN0YWNrLlxuICAgICAgICAgICAgaWYgKGl0ZW0pIHtcbiAgICAgICAgICAgICAgdHJ5IHsgdGhpcy5ob3N0LnZpZXdlcigpPy53b3JsZD8ucmVtb3ZlSXRlbShpdGVtKTsgfSBjYXRjaCB7IC8qIGdvbmUgKi8gfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aGlzLnNsaWNlc0xvYWRpbmcuZGVsZXRlKHopO1xuICAgICAgICAgIGlmICghaXRlbSkgcmV0dXJuO1xuICAgICAgICAgIHRoaXMuc2xpY2VJdGVtcy5zZXQoeiwgaXRlbSk7XG4gICAgICAgICAgdGhpcy50b3VjaFNsaWNlTHJ1KHopO1xuICAgICAgICAgIHRoaXMuaG9zdC5vbkNvbXBvc2l0ZVNsaWNlQWRkZWQoeik7XG4gICAgICAgICAgLy8gT25seSByZXZlYWwgaWYgdGhlIHVzZXIgaXMgc3RpbGwgb24gdGhpcyBzbGljZSAoZmFzdCBzY3J1YmJpbmcgbWF5XG4gICAgICAgICAgLy8gaGF2ZSBtb3ZlZCBvbiDigJQgbGVhdmUgaXQgY2FjaGVkL2hpZGRlbiBmb3IgYSBsYXRlciByZXZpc2l0KS5cbiAgICAgICAgICBpZiAoeiA9PT0gdGhpcy5ob3N0LmN1cnJlbnRaKCkpIHtcbiAgICAgICAgICAgIHRoaXMuc2hvd09ubHlTbGljZSh6KTtcbiAgICAgICAgICAgIHRoaXMuc2NoZWR1bGVQcmVmZXRjaCgpO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aGlzLmV2aWN0U2xpY2VMcnUoKTtcbiAgICAgICAgfSxcbiAgICAgICAgZXJyb3I6ICgpID0+IHtcbiAgICAgICAgICBpZiAodG9rZW4gPT09IHRoaXMuc2xpY2VMb2FkVG9rZW4pIHRoaXMuc2xpY2VzTG9hZGluZy5kZWxldGUoeik7XG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHRoaXMuc2xpY2VzTG9hZGluZy5kZWxldGUoeik7XG4gICAgICBjb25zb2xlLndhcm4oJ1tPU0RdIGZhaWxlZCB0byBhZGQgei1zbGljZScsIGVycik7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBzbGljZSB6J3MgY2hhbm5lbCBncm91cDogb25lIGFkZGl0aXZlbHktY29tcG9zaXRlZCAoJ2xpZ2h0ZXInID0gRmlqaVxuICAgKiBcIkNvbXBvc2l0ZVwiKSBUaWxlZEltYWdlIHBlciBjaGFubmVsLCBoaWRkZW4gKG9wYWNpdHkgMCkgdW50aWwgcmV2ZWFsZWQuXG4gICAqIEVhY2ggaXMgcHJlbG9hZGVkIHNvIHRoZSBiYWNrZ3JvdW5kIGxvYWRlciBjYW4gcHJlLWZpbGwgZXZlcnkgc2xpY2UuXG4gICAqIENhY2hlZCBzbyBhIHJldmlzaXQgaXMgYW4gaW5zdGFudCBvcGFjaXR5IHRvZ2dsZSDigJQgbm8gcmUtZmV0Y2gsIG5vXG4gICAqIHdoaXRlLWZsaWNrZXIuIE1pcnJvcnMgYWRkU2xpY2UgZm9yIHRoZSBjb21wb3NpdGUgcGF0aC5cbiAgICovXG4gIGFkZENoYW5uZWxTbGljZSh6OiBudW1iZXIpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuaG9zdC5oYXNJbWFnZSgpKSByZXR1cm47XG4gICAgaWYgKHRoaXMuY2hhbm5lbFNsaWNlSXRlbXMuaGFzKHopIHx8IHRoaXMuc2xpY2VzTG9hZGluZy5oYXMoeikpIHJldHVybjtcbiAgICB0aGlzLnNsaWNlc0xvYWRpbmcuYWRkKHopO1xuICAgIGNvbnN0IHRva2VuID0gdGhpcy5zbGljZUxvYWRUb2tlbjtcbiAgICBjb25zdCBuID0gdGhpcy5ob3N0LmNoYW5uZWxDb3VudCgpO1xuICAgIGNvbnN0IGdyb3VwOiBhbnlbXSA9IG5ldyBBcnJheShuKTtcbiAgICBsZXQgc2V0dGxlZCA9IDA7XG4gICAgY29uc3Qgb25TZXR0bGVkID0gKCkgPT4ge1xuICAgICAgaWYgKCsrc2V0dGxlZCA8IG4pIHJldHVybjtcbiAgICAgIGlmICh0b2tlbiAhPT0gdGhpcy5zbGljZUxvYWRUb2tlbikgcmV0dXJuOyAvLyBpbWFnZSBzd2l0Y2hlZCBtaWQtYWRkXG4gICAgICB0aGlzLnNsaWNlc0xvYWRpbmcuZGVsZXRlKHopO1xuICAgICAgdGhpcy5jaGFubmVsU2xpY2VJdGVtcy5zZXQoeiwgZ3JvdXApO1xuICAgICAgdGhpcy5zdGFsZVNsaWNlcy5kZWxldGUoeik7IC8vIGZyZXNobHkgdGludGVkIGF0IHRoZSBjdXJyZW50IGRpc3BsYXkgc3RhdGVcbiAgICAgIHRoaXMudG91Y2hTbGljZUxydSh6KTtcbiAgICAgIGlmICh6ID09PSB0aGlzLmhvc3QuY3VycmVudFooKSkge1xuICAgICAgICB0aGlzLnJldmVhbENoYW5uZWxTbGljZSh6KTsgLy8gdGlsZXMgbWF5IHN0aWxsIGJlIGRlY29kaW5nOyBvcGFjaXR5IGlzIHNldCBub3dcbiAgICAgICAgdGhpcy5zY2hlZHVsZVByZWZldGNoKCk7XG4gICAgICB9XG4gICAgICB0aGlzLmV2aWN0U2xpY2VMcnUoKTtcbiAgICB9O1xuICAgIGZvciAobGV0IGMgPSAwOyBjIDwgbjsgYysrKSB7XG4gICAgICB0cnkge1xuICAgICAgICB0aGlzLmhvc3Qudmlld2VyKCkuYWRkVGlsZWRJbWFnZSh7XG4gICAgICAgICAgdGlsZVNvdXJjZTogdGhpcy5ob3N0LmJ1aWxkVGlsZVNvdXJjZSh6LCBjKSxcbiAgICAgICAgICB4OiAwLCB5OiAwLCB3aWR0aDogMSxcbiAgICAgICAgICBvcGFjaXR5OiAwLCAvLyByZXZlYWxlZCBieSByZXZlYWxDaGFubmVsU2xpY2Ugb25jZSB0aGUgZ3JvdXAgaXMgaW5cbiAgICAgICAgICBjb21wb3NpdGVPcGVyYXRpb246ICdsaWdodGVyJyxcbiAgICAgICAgICBwcmVsb2FkOiB0cnVlLFxuICAgICAgICAgIHN1Y2Nlc3M6IChlOiBhbnkpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGl0ZW0gPSBlPy5pdGVtO1xuICAgICAgICAgICAgaWYgKHRva2VuICE9PSB0aGlzLnNsaWNlTG9hZFRva2VuKSB7XG4gICAgICAgICAgICAgIGlmIChpdGVtKSB7IHRyeSB7IHRoaXMuaG9zdC52aWV3ZXIoKT8ud29ybGQ/LnJlbW92ZUl0ZW0oaXRlbSk7IH0gY2F0Y2ggeyAvKiBnb25lICovIH0gfVxuICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaXRlbSkgZ3JvdXBbY10gPSBpdGVtO1xuICAgICAgICAgICAgb25TZXR0bGVkKCk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICBlcnJvcjogKCkgPT4gb25TZXR0bGVkKCksXG4gICAgICAgIH0pO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignW09TRF0gZmFpbGVkIHRvIGFkZCBjaGFubmVsIHNsaWNlIGltYWdlJywgeiwgYywgZXJyKTtcbiAgICAgICAgb25TZXR0bGVkKCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqIFJldmVhbCBzbGljZSB6J3MgY2hhbm5lbCBncm91cCAoZWFjaCB2aXNpYmxlIGNoYW5uZWwg4oaSIG9wYWNpdHkgMSkgYW5kXG4gICAqICBoaWRlIGV2ZXJ5IG90aGVyIGNhY2hlZCBzbGljZSdzIGdyb3VwLiBJbnN0YW50OyBubyBmZXRjaC9kZWNvZGUuICovXG4gIHJldmVhbENoYW5uZWxTbGljZSh6OiBudW1iZXIpOiB2b2lkIHtcbiAgICBmb3IgKGNvbnN0IFt6eiwgZ3JvdXBdIG9mIHRoaXMuY2hhbm5lbFNsaWNlSXRlbXMpIHtcbiAgICAgIGNvbnN0IGFjdGl2ZSA9IHp6ID09PSB6O1xuICAgICAgZ3JvdXAuZm9yRWFjaCgoaXQsIGMpID0+IHtcbiAgICAgICAgaWYgKCFpdCkgcmV0dXJuO1xuICAgICAgICBjb25zdCB2aXNpYmxlID0gdGhpcy5ob3N0LmNoYW5uZWxWaXNpYmxlKGMpO1xuICAgICAgICB0cnkgeyBpdC5zZXRPcGFjaXR5KGFjdGl2ZSAmJiB2aXNpYmxlID8gMSA6IDApOyB9IGNhdGNoIHsgLyogZ29uZSAqLyB9XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvKiogU2hvdyB0aGUgZ2l2ZW4gY29tcG9zaXRlIHNsaWNlIChvcGFjaXR5IDEpIGFuZCBoaWRlIGFsbCBvdGhlciBjYWNoZWQgc2xpY2VzLiAqL1xuICBwcml2YXRlIHNob3dPbmx5U2xpY2UoejogbnVtYmVyKTogdm9pZCB7XG4gICAgZm9yIChjb25zdCBbenosIGl0ZW1dIG9mIHRoaXMuc2xpY2VJdGVtcykge1xuICAgICAgdHJ5IHsgaXRlbS5zZXRPcGFjaXR5KHp6ID09PSB6ID8gMSA6IDApOyB9IGNhdGNoIHsgLyogaXRlbSBnb25lICovIH1cbiAgICB9XG4gIH1cblxuICAvLyDilIDilIAgZGlzcGxheSBpbnZhbGlkYXRpb24gKG11bHRpY2hhbm5lbCkg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgLyoqIFJlLXRpbnQgYWZ0ZXIgYSBkaXNwbGF5IGNoYW5nZTogaW52YWxpZGF0ZSBPTkxZIHRoZSB2aXNpYmxlIHNsaWNlJ3NcbiAgICogIGNoYW5uZWwgaW1hZ2VzIOKAlCBpbnZhbGlkYXRpbmcgdGhlIHdob2xlIHdvcmxkIHdvdWxkIHJlLXByb2Nlc3MgZXZlcnlcbiAgICogIGhpZGRlbi9wcmVsb2FkZWQgc2xpY2UncyB0aWxlcyAoaHVuZHJlZHMpLCBmbG9vZGluZyBPU0QgYW5kIHdhc3Rpbmcgd29ya1xuICAgKiAgb24gdGlsZXMgdGhhdCBhcmVuJ3Qgb24gc2NyZWVuLiBUaGUgb3RoZXIgY2FjaGVkIHNsaWNlcyBhcmUgbWFya2VkIHN0YWxlXG4gICAqICBhbmQgcmUtdGludGVkIGxhemlseSB3aGVuIHJldmVhbGVkLiAqL1xuICBpbnZhbGlkYXRlQ2hhbm5lbERpc3BsYXkoejogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5pbnZhbGlkYXRlU2xpY2Uoeik7XG4gICAgdGhpcy5zdGFsZVNsaWNlcy5jbGVhcigpO1xuICAgIGZvciAoY29uc3Qgenogb2YgdGhpcy5jaGFubmVsU2xpY2VJdGVtcy5rZXlzKCkpIHtcbiAgICAgIGlmICh6eiAhPT0geikgdGhpcy5zdGFsZVNsaWNlcy5hZGQoenopO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBJbnZhbGlkYXRlIChyZXN0b3JlICsgcmUtcmVjb2xvcikganVzdCB0aGUgY2hhbm5lbCBpbWFnZXMgb2Ygb25lIGNhY2hlZFxuICAgKiAgc2xpY2UuIEEgc2hhcmVkIHRpbWVzdGFtcCBiYXRjaGVzIHRoZSBwZXItaW1hZ2UgaW52YWxpZGF0aW9ucyBpbnRvIG9uZVxuICAgKiAgcHJvY2Vzc2luZyBwYXNzIChPU0QgZGVkdXBlcyB0aWxlcyBhbHJlYWR5IHN0YW1wZWQgYXQgPj0gdFN0YW1wKS4gKi9cbiAgcHJpdmF0ZSBpbnZhbGlkYXRlU2xpY2UoejogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3QgZ3JvdXAgPSB0aGlzLmNoYW5uZWxTbGljZUl0ZW1zLmdldCh6KSA/PyBbXTtcbiAgICBpZiAoIWdyb3VwLmxlbmd0aCkgcmV0dXJuO1xuICAgIGNvbnN0IG9zZDogYW55ID0gT1NEO1xuICAgIGNvbnN0IHRTdGFtcCA9IHR5cGVvZiBvc2Qubm93ID09PSAnZnVuY3Rpb24nID8gb3NkLm5vdygpIDogRGF0ZS5ub3coKTtcbiAgICBmb3IgKGNvbnN0IGl0IG9mIGdyb3VwKSB7XG4gICAgICBpZiAoaXQgJiYgdHlwZW9mIGl0LnJlcXVlc3RJbnZhbGlkYXRlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRyeSB7IGl0LnJlcXVlc3RJbnZhbGlkYXRlKHRydWUsIGZhbHNlLCB0U3RhbXApOyB9IGNhdGNoIHsgLyogZ29uZSAqLyB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8g4pSA4pSAIGJhY2tncm91bmQgc3RhY2sgcHJlbG9hZGluZyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICAvKiogRGVib3VuY2Ugc28gYSBidXJzdCBvZiB2aWV3cG9ydC9zbGljZSBldmVudHMgY29hbGVzY2VzLCB0aGVuIGFkdmFuY2UgdGhlXG4gICAqICBiYWNrZ3JvdW5kIHN0YWNrIGxvYWRlciBieSBvbmUgc2xpY2UuICovXG4gIHNjaGVkdWxlUHJlZmV0Y2goKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuc2tpcFNsaWNlUHJlZmV0Y2gpIHJldHVybjtcbiAgICBpZiAodGhpcy5wcmVmZXRjaFRpbWVyKSBjbGVhclRpbWVvdXQodGhpcy5wcmVmZXRjaFRpbWVyKTtcbiAgICB0aGlzLnByZWZldGNoVGltZXIgPSBzZXRUaW1lb3V0KCgpID0+IHRoaXMubG9hZE5leHRCYWNrZ3JvdW5kU2xpY2UoKSwgMjAwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBCYWNrZ3JvdW5kLWxvYWQgdGhlIHdob2xlIHN0YWNrOiBhZGQgZWFjaCBub3QteWV0LWNhY2hlZCBzbGljZSBhcyBhXG4gICAqIGhpZGRlbiwgcHJlbG9hZGVkIHRpbGVkIGltYWdlLCBvbmUgYXQgYSB0aW1lLCB3b3JraW5nIG91dHdhcmQgZnJvbSB0aGVcbiAgICogY3VycmVudCBzbGljZSDigJQgYW5kIG5ldmVyIGJsb2NraW5nIHRoZSB2aXNpYmxlIHNsaWNlIChpdCB5aWVsZHMgd2hpbGUgdGhlXG4gICAqIGN1cnJlbnQgdmlldyBpcyBzdGlsbCBzdHJlYW1pbmcgdGlsZXM7IG9ubHkgb25lIHNsaWNlIGlzIGluIGZsaWdodCBhdCBhXG4gICAqIHRpbWUgc28gdGhlIG9uLXNjcmVlbiB0aWxlcyBhbHdheXMgd2luIHRoZSBjb25uZWN0aW9uKS5cbiAgICovXG4gIHByaXZhdGUgbG9hZE5leHRCYWNrZ3JvdW5kU2xpY2UoKTogdm9pZCB7XG4gICAgdGhpcy5wcmVmZXRjaFRpbWVyID0gbnVsbDtcbiAgICBpZiAoIXRoaXMuaG9zdC5oYXNJbWFnZSgpKSByZXR1cm47XG4gICAgY29uc3Qgc2xpY2VDb3VudCA9IHRoaXMuaG9zdC5zbGljZUNvdW50KCk7XG4gICAgaWYgKHNsaWNlQ291bnQgPD0gMSkgcmV0dXJuOyAvLyBub3QgYSBzdGFjayDigJQgbm90aGluZyB0byBwcmVsb2FkXG4gICAgLy8gWWllbGQgdG8gdGhlIHZpc2libGUgc2xpY2Ugd2hpbGUgaXQncyBzdGlsbCBzdHJlYW1pbmcgdGlsZXMuXG4gICAgaWYgKHRoaXMuc2xpY2VUaWxlc0xvYWRpbmcodGhpcy5ob3N0LmN1cnJlbnRaKCkpKSB7XG4gICAgICB0aGlzLnNjaGVkdWxlUHJlZmV0Y2goKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgLy8gR2F0ZSBvbiB0aGUgaW4tZmxpZ2h0IHNsaWNlJ3MgVElMRVMgZmluaXNoaW5nIOKAlCBhZGRUaWxlZEltYWdlJ3Mgc3VjY2Vzc1xuICAgIC8vIGZpcmVzIG9uIGFkZCwgbm90IG9uIHRpbGUgbG9hZCwgc28gd2l0aG91dCB0aGlzIHdlJ2QgYWRkIHRoZSB3aG9sZSBzdGFja1xuICAgIC8vIGF0IG9uY2UgYW5kIGZsb29kIHRoZSBjb25uZWN0aW9uLiBBIHRpbWUgZmFsbGJhY2sgcHJldmVudHMgYSBzdHVjayBzbGljZVxuICAgIC8vIGZyb20gc3RhbGxpbmcgdGhlIHBhc3MuXG4gICAgaWYgKHRoaXMuYmdMb2FkaW5nWiAhPSBudWxsKSB7XG4gICAgICBjb25zdCBhZGRpbmcgPSB0aGlzLnNsaWNlc0xvYWRpbmcuaGFzKHRoaXMuYmdMb2FkaW5nWik7XG4gICAgICBjb25zdCB0aWxlc0xvYWRpbmcgPSB0aGlzLnNsaWNlVGlsZXNMb2FkaW5nKHRoaXMuYmdMb2FkaW5nWik7XG4gICAgICBjb25zdCB0aW1lZE91dCA9IERhdGUubm93KCkgLSB0aGlzLmJnTG9hZGluZ1NpbmNlID4gODAwMDtcbiAgICAgIGlmICgoYWRkaW5nIHx8IHRpbGVzTG9hZGluZykgJiYgIXRpbWVkT3V0KSB7XG4gICAgICAgIHRoaXMuc2NoZWR1bGVQcmVmZXRjaCgpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB0aGlzLmJnTG9hZGluZ1ogPSBudWxsOyAvLyB0aGF0IHNsaWNlJ3MgdGlsZXMgYXJlIGluIChvciBnYXZlIHVwKSDigJQgYWR2YW5jZVxuICAgIH1cbiAgICBjb25zdCBuZXh0ID0gdGhpcy5uZWFyZXN0VW5jYWNoZWRTbGljZShzbGljZUNvdW50KTtcbiAgICBpZiAobmV4dCA9PSBudWxsKSByZXR1cm47IC8vIHdob2xlIHN0YWNrIGNhY2hlZCDigJQgZG9uZVxuICAgIHRoaXMuYmdMb2FkaW5nWiA9IG5leHQ7XG4gICAgdGhpcy5iZ0xvYWRpbmdTaW5jZSA9IERhdGUubm93KCk7XG4gICAgdGhpcy5iZ0F0dGVtcHRlZC5hZGQobmV4dCk7XG4gICAgdGhpcy5hZGRTbGljZShuZXh0KTsgLy8gaGlkZGVuICsgcHJlbG9hZCAoYWRkZWQgd2l0aCBvcGFjaXR5IDA7IG5vdCByZXZlYWxlZClcbiAgICB0aGlzLnNjaGVkdWxlUHJlZmV0Y2goKTsgLy8gcG9sbCB1bnRpbCBpdHMgdGlsZXMgbG9hZCwgdGhlbiBhZHZhbmNlXG4gIH1cblxuICAvKiogVGhlIG5vdC15ZXQtY2FjaGVkIHNsaWNlIGNsb3Nlc3QgdG8gdGhlIGN1cnJlbnQgb25lIChsb2FkIG5lYXJlc3QgZmlyc3QpLFxuICAgKiAgc2tpcHBpbmcgYW55IGFscmVhZHkgYXR0ZW1wdGVkIHNvIGEgZmFpbGVkL3Nsb3cgb25lIGlzbid0IHJldHJpZWQgaW4gYSBsb29wLiAqL1xuICBwcml2YXRlIG5lYXJlc3RVbmNhY2hlZFNsaWNlKHNsaWNlQ291bnQ6IG51bWJlcik6IG51bWJlciB8IG51bGwge1xuICAgIGNvbnN0IGN1ciA9IHRoaXMuaG9zdC5jdXJyZW50WigpO1xuICAgIGZvciAobGV0IGQgPSAwOyBkIDwgc2xpY2VDb3VudDsgZCsrKSB7XG4gICAgICBjb25zdCBjYW5kaWRhdGVzID0gZCA9PT0gMCA/IFtjdXJdIDogW2N1ciAtIGQsIGN1ciArIGRdO1xuICAgICAgZm9yIChjb25zdCB6IG9mIGNhbmRpZGF0ZXMpIHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIHogPj0gMCAmJiB6IDwgc2xpY2VDb3VudCAmJlxuICAgICAgICAgICF0aGlzLnNsaWNlQ2FjaGVIYXMoeikgJiYgIXRoaXMuc2xpY2VzTG9hZGluZy5oYXMoeikgJiYgIXRoaXMuYmdBdHRlbXB0ZWQuaGFzKHopXG4gICAgICAgICkge1xuICAgICAgICAgIHJldHVybiB6O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIFN0b3AgYmFja2dyb3VuZCBzdGFjayBwcmVsb2FkaW5nIGFuZCBpbnZhbGlkYXRlIGFueSBpbi1mbGlnaHQgc2xpY2UgYWRkLlxuICAgKiBDYWxsZWQgd2hlbiBhIGRpZmZlcmVudCBpbWFnZSBpcyBzZWxlY3RlZCBzbyB0aGUgcHJldmlvdXMgc3RhY2sgc3RvcHNcbiAgICogbG9hZGluZyBpbW1lZGlhdGVseSBpbnN0ZWFkIG9mIGZpbmlzaGluZyBpbiB0aGUgYmFja2dyb3VuZC5cbiAgICovXG4gIGNhbmNlbEJhY2tncm91bmRMb2FkKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLnByZWZldGNoVGltZXIpIHtcbiAgICAgIGNsZWFyVGltZW91dCh0aGlzLnByZWZldGNoVGltZXIpO1xuICAgICAgdGhpcy5wcmVmZXRjaFRpbWVyID0gbnVsbDtcbiAgICB9XG4gICAgdGhpcy5zbGljZXNMb2FkaW5nLmNsZWFyKCk7XG4gICAgdGhpcy5iZ0xvYWRpbmdaID0gbnVsbDtcbiAgICB0aGlzLmJnQXR0ZW1wdGVkLmNsZWFyKCk7XG4gICAgdGhpcy5zbGljZUxvYWRUb2tlbisrOyAvLyBkcm9wIHBlbmRpbmcgYWRkVGlsZWRJbWFnZSBjYWxsYmFja3MgZnJvbSB0aGUgb2xkIGltYWdlXG4gICAgLy8gQWJvcnQgaW4tZmxpZ2h0IGJhY2tncm91bmQgdGlsZXMgaW1tZWRpYXRlbHkgYnkgZHJvcHBpbmcgdGhlIGhpZGRlblxuICAgIC8vIHByZWxvYWRlZCBzbGljZXMgKHJlbW92ZUl0ZW0gY2FuY2VscyB0aGVpciBwZW5kaW5nIHRpbGUgbG9hZHMpLiBLZWVwIHRoZVxuICAgIC8vIHZpc2libGUgc2xpY2Ugc28gdGhlIGN1cnJlbnQgdmlldyBkb2Vzbid0IGJsYW5rIGJlZm9yZSB0aGUgbmV4dCBwbG90LlxuICAgIHRoaXMuZHJvcEhpZGRlblNsaWNlcygpO1xuICB9XG5cbiAgLyoqIFJlbW92ZSBldmVyeSBjYWNoZWQgc2xpY2UgZXhjZXB0IHRoZSBjdXJyZW50bHkgZGlzcGxheWVkIG9uZSwgYWJvcnRpbmdcbiAgICogIHRoZWlyIGluLWZsaWdodCB0aWxlIHJlcXVlc3RzLiAqL1xuICBwcml2YXRlIGRyb3BIaWRkZW5TbGljZXMoKTogdm9pZCB7XG4gICAgY29uc3QgdiA9IHRoaXMuaG9zdC52aWV3ZXIoKTtcbiAgICBpZiAoIXYpIHJldHVybjtcbiAgICBjb25zdCBjdXIgPSB0aGlzLmhvc3QuY3VycmVudFooKTtcbiAgICBmb3IgKGNvbnN0IFt6LCBpdGVtXSBvZiBbLi4udGhpcy5zbGljZUl0ZW1zXSkge1xuICAgICAgaWYgKHogPT09IGN1cikgY29udGludWU7XG4gICAgICB0aGlzLnNsaWNlSXRlbXMuZGVsZXRlKHopO1xuICAgICAgdHJ5IHsgdi53b3JsZC5yZW1vdmVJdGVtKGl0ZW0pOyB9IGNhdGNoIHsgLyogYWxyZWFkeSBnb25lICovIH1cbiAgICB9XG4gICAgZm9yIChjb25zdCBbeiwgZ3JvdXBdIG9mIFsuLi50aGlzLmNoYW5uZWxTbGljZUl0ZW1zXSkge1xuICAgICAgaWYgKHogPT09IGN1cikgY29udGludWU7XG4gICAgICB0aGlzLmNoYW5uZWxTbGljZUl0ZW1zLmRlbGV0ZSh6KTtcbiAgICAgIGZvciAoY29uc3QgaXQgb2YgZ3JvdXApIHsgaWYgKGl0KSB7IHRyeSB7IHYud29ybGQucmVtb3ZlSXRlbShpdCk7IH0gY2F0Y2ggeyAvKiBnb25lICovIH0gfSB9XG4gICAgfVxuICAgIHRoaXMuc2xpY2VMcnUgPSB0aGlzLnNsaWNlQ2FjaGVIYXMoY3VyKSA/IFtjdXJdIDogW107XG4gIH1cblxuICAvLyDilIDilIAgY2FjaGUgYm9va2tlZXBpbmcg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgLyoqIFdoZXRoZXIgc2xpY2UgeiBpcyBpbiB0aGUgYWN0aXZlIGNhY2hlIChjb21wb3NpdGUgc2luZ2xlIGltYWdlLCBvciB0aGVcbiAgICogIG11bHRpY2hhbm5lbCBwZXItY2hhbm5lbCBncm91cCkuICovXG4gIHByaXZhdGUgc2xpY2VDYWNoZUhhcyh6OiBudW1iZXIpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5ob3N0LmlzTXVsdGlDaGFubmVsKCkgPyB0aGlzLmNoYW5uZWxTbGljZUl0ZW1zLmhhcyh6KSA6IHRoaXMuc2xpY2VJdGVtcy5oYXMoeik7XG4gIH1cblxuICAvKiogVGhlIGNhY2hlZCBUaWxlZEltYWdlKHMpIGZvciBzbGljZSB6ICgw4oCTMSBmb3IgY29tcG9zaXRlLCBOIGZvciBtdWx0aWNoYW5uZWwpLiAqL1xuICBwcml2YXRlIHNsaWNlR3JvdXAoejogbnVtYmVyKTogYW55W10ge1xuICAgIGlmICh0aGlzLmhvc3QuaXNNdWx0aUNoYW5uZWwoKSkgcmV0dXJuIHRoaXMuY2hhbm5lbFNsaWNlSXRlbXMuZ2V0KHopID8/IFtdO1xuICAgIGNvbnN0IGl0ID0gdGhpcy5zbGljZUl0ZW1zLmdldCh6KTtcbiAgICByZXR1cm4gaXQgPyBbaXRdIDogW107XG4gIH1cblxuICAvKiogV2hldGhlciBzbGljZSB6J3MgdGlsZXMgYXJlIHN0aWxsIHN0cmVhbWluZyAoYW55IGNhY2hlZCBpbWFnZSBub3QgZnVsbHkgbG9hZGVkKS4gKi9cbiAgcHJpdmF0ZSBzbGljZVRpbGVzTG9hZGluZyh6OiBudW1iZXIpOiBib29sZWFuIHtcbiAgICBjb25zdCBnID0gdGhpcy5zbGljZUdyb3VwKHopO1xuICAgIGlmICghZy5sZW5ndGgpIHJldHVybiBmYWxzZTtcbiAgICByZXR1cm4gZy5zb21lKChpdCkgPT4gaXQgJiYgdHlwZW9mIGl0LmdldEZ1bGx5TG9hZGVkID09PSAnZnVuY3Rpb24nICYmICFpdC5nZXRGdWxseUxvYWRlZCgpKTtcbiAgfVxuXG4gIC8qKiBSZW1vdmUgc2xpY2UgeidzIGNhY2hlZCBpbWFnZShzKSBmcm9tIHRoZSB3b3JsZCBhbmQgdGhlIGFjdGl2ZSBjYWNoZS4gKi9cbiAgcHJpdmF0ZSByZW1vdmVDYWNoZWRTbGljZSh6OiBudW1iZXIpOiB2b2lkIHtcbiAgICBjb25zdCB2ID0gdGhpcy5ob3N0LnZpZXdlcigpO1xuICAgIGlmICh0aGlzLmhvc3QuaXNNdWx0aUNoYW5uZWwoKSkge1xuICAgICAgY29uc3QgZ3JvdXAgPSB0aGlzLmNoYW5uZWxTbGljZUl0ZW1zLmdldCh6KTtcbiAgICAgIHRoaXMuY2hhbm5lbFNsaWNlSXRlbXMuZGVsZXRlKHopO1xuICAgICAgaWYgKGdyb3VwICYmIHYpIGZvciAoY29uc3QgaXQgb2YgZ3JvdXApIHsgaWYgKGl0KSB7IHRyeSB7IHYud29ybGQucmVtb3ZlSXRlbShpdCk7IH0gY2F0Y2ggeyAvKiBnb25lICovIH0gfSB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGl0ZW0gPSB0aGlzLnNsaWNlSXRlbXMuZ2V0KHopO1xuICAgICAgdGhpcy5zbGljZUl0ZW1zLmRlbGV0ZSh6KTtcbiAgICAgIGlmIChpdGVtICYmIHYpIHsgdHJ5IHsgdi53b3JsZC5yZW1vdmVJdGVtKGl0ZW0pOyB9IGNhdGNoIHsgLyogZ29uZSAqLyB9IH1cbiAgICB9XG4gIH1cblxuICAvKiogSXMgdGhlIHRpbGVkIGltYWdlIHN0aWxsIGluIHRoZSB3b3JsZCAobm90IGV2aWN0ZWQpPyAqL1xuICBwcml2YXRlIHNsaWNlSW5Xb3JsZChpdGVtOiBhbnkpOiBib29sZWFuIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIHRoaXMuaG9zdC52aWV3ZXIoKS53b3JsZC5nZXRJbmRleE9mSXRlbShpdGVtKSA+PSAwO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBNYXJrIHogYXMgbW9zdC1yZWNlbnRseS11c2VkLiAqL1xuICBwcml2YXRlIHRvdWNoU2xpY2VMcnUoejogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3QgaSA9IHRoaXMuc2xpY2VMcnUuaW5kZXhPZih6KTtcbiAgICBpZiAoaSA+PSAwKSB0aGlzLnNsaWNlTHJ1LnNwbGljZShpLCAxKTtcbiAgICB0aGlzLnNsaWNlTHJ1LnB1c2goeik7XG4gIH1cblxuICAvKiogRHJvcCB0aGUgbGVhc3QtcmVjZW50bHktdXNlZCBjYWNoZWQgc2xpY2VzIGJleW9uZCB0aGUgY2FwIChuZXZlciB0aGVcbiAgICogIGN1cnJlbnQgb25lKSwgcmVtb3ZpbmcgdGhlaXIgdGlsZWQgaW1hZ2VzIHNvIG1lbW9yeSBzdGF5cyBib3VuZGVkLiAqL1xuICBwcml2YXRlIGV2aWN0U2xpY2VMcnUoKTogdm9pZCB7XG4gICAgd2hpbGUgKHRoaXMuc2xpY2VMcnUubGVuZ3RoID4gdGhpcy5tYXhDYWNoZWRTbGljZXMpIHtcbiAgICAgIGNvbnN0IGN1ciA9IHRoaXMuaG9zdC5jdXJyZW50WigpO1xuICAgICAgY29uc3QgaWR4ID0gdGhpcy5zbGljZUxydS5maW5kSW5kZXgoKHopID0+IHogIT09IGN1cik7XG4gICAgICBpZiAoaWR4IDwgMCkgYnJlYWs7XG4gICAgICBjb25zdCB6ID0gdGhpcy5zbGljZUxydS5zcGxpY2UoaWR4LCAxKVswXTtcbiAgICAgIHRoaXMucmVtb3ZlQ2FjaGVkU2xpY2Uoeik7XG4gICAgfVxuICB9XG5cbiAgLyoqIENsZWFyIHRoZSBjYWNoZSAob24gdGVhcmRvd24gLyBpbWFnZSBzd2l0Y2gpLiAqL1xuICByZXNldCgpOiB2b2lkIHtcbiAgICB0aGlzLnNsaWNlSXRlbXMuY2xlYXIoKTtcbiAgICB0aGlzLmNoYW5uZWxTbGljZUl0ZW1zLmNsZWFyKCk7XG4gICAgdGhpcy5zdGFsZVNsaWNlcy5jbGVhcigpO1xuICAgIHRoaXMuc2xpY2VMcnUgPSBbXTtcbiAgICB0aGlzLnNsaWNlc0xvYWRpbmcuY2xlYXIoKTtcbiAgICB0aGlzLmJnTG9hZGluZ1ogPSBudWxsO1xuICAgIHRoaXMuYmdBdHRlbXB0ZWQuY2xlYXIoKTtcbiAgfVxufVxuIl19
@@ -0,0 +1,29 @@
1
+ import { firstValueFrom } from 'rxjs';
2
+ import { timeout } from 'rxjs/operators';
3
+ /** Build the `/tile` request URL — the one place its query shape lives. */
4
+ export function buildTileUrl(api, infoB64, c) {
5
+ const ch = c.channel == null ? '' : `&channel=${c.channel}`;
6
+ return `${api}tile?info=${infoB64}&res=${c.res}&col=${c.col}&row=${c.row}&z=${c.z}&tileSize=${c.tileSize}${ch}`;
7
+ }
8
+ /** Fetch a tile PNG and decode it to an ImageBitmap. The caller owns the
9
+ * bitmap (call `close()` when done). Throws on network/decode failure. */
10
+ export async function fetchTileBitmap(http, url, timeoutMs) {
11
+ const blob = await firstValueFrom(http.get(url, { responseType: 'blob' }).pipe(timeout(timeoutMs)));
12
+ return createImageBitmap(blob);
13
+ }
14
+ /** Fetch a tile and read its pixels back as RGBA ImageData (via an offscreen
15
+ * canvas). Returns null only when a 2d context can't be created; throws on
16
+ * network/decode failure (the caller's tagged catch handles it). */
17
+ export async function fetchTileRgba(http, url, timeoutMs) {
18
+ const bmp = await fetchTileBitmap(http, url, timeoutMs);
19
+ const cv = document.createElement('canvas');
20
+ cv.width = bmp.width;
21
+ cv.height = bmp.height;
22
+ const ctx = cv.getContext('2d', { willReadFrequently: true });
23
+ if (!ctx)
24
+ return null;
25
+ ctx.drawImage(bmp, 0, 0);
26
+ bmp.close?.();
27
+ return ctx.getImageData(0, 0, cv.width, cv.height);
28
+ }
29
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGlsZS1jbGllbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbGliL2ltcGxlbWVudGF0aW9ucy9vc2QvdGlsZS1jbGllbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUN0QyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUEwQnpDLDJFQUEyRTtBQUMzRSxNQUFNLFVBQVUsWUFBWSxDQUFDLEdBQVcsRUFBRSxPQUFlLEVBQUUsQ0FBYTtJQUN0RSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsT0FBTyxJQUFJLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUM1RCxPQUFPLEdBQUcsR0FBRyxhQUFhLE9BQU8sUUFBUSxDQUFDLENBQUMsR0FBRyxRQUFRLENBQUMsQ0FBQyxHQUFHLFFBQVEsQ0FBQyxDQUFDLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsQ0FBQyxRQUFRLEdBQUcsRUFBRSxFQUFFLENBQUM7QUFDbEgsQ0FBQztBQUVEOzJFQUMyRTtBQUMzRSxNQUFNLENBQUMsS0FBSyxVQUFVLGVBQWUsQ0FBQyxJQUFnQixFQUFFLEdBQVcsRUFBRSxTQUFpQjtJQUNwRixNQUFNLElBQUksR0FBRyxNQUFNLGNBQWMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxFQUFFLFlBQVksRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BHLE9BQU8saUJBQWlCLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDakMsQ0FBQztBQUVEOztxRUFFcUU7QUFDckUsTUFBTSxDQUFDLEtBQUssVUFBVSxhQUFhLENBQ2pDLElBQWdCLEVBQUUsR0FBVyxFQUFFLFNBQWlCO0lBRWhELE1BQU0sR0FBRyxHQUFHLE1BQU0sZUFBZSxDQUFDLElBQUksRUFBRSxHQUFHLEVBQUUsU0FBUyxDQUFDLENBQUM7SUFDeEQsTUFBTSxFQUFFLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUM1QyxFQUFFLENBQUMsS0FBSyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUM7SUFDckIsRUFBRSxDQUFDLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDO0lBQ3ZCLE1BQU0sR0FBRyxHQUFHLEVBQUUsQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLEVBQUUsa0JBQWtCLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUM5RCxJQUFJLENBQUMsR0FBRztRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQ3RCLEdBQUcsQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUN6QixHQUFHLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQztJQUNkLE9BQU8sR0FBRyxDQUFDLFlBQVksQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQ3JELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBIdHRwQ2xpZW50IH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHsgZmlyc3RWYWx1ZUZyb20gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IHRpbWVvdXQgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbi8qKlxuICogU2luZ2xlIHNvdXJjZSBvZiB0cnV0aCBmb3Igaml0LXNlcnZpY2UgYC90aWxlYCBhY2Nlc3MgZnJvbSB0aGUgT1NEIGJhY2tlbmRcbiAqIChyZWZhY3RvcmluZyBwbGFuLCBTdGVwIDIpLiBCZWZvcmUgdGhpcyBtb2R1bGUgdGhlIHRpbGUgVVJMIHdhcyBzdHJpbmctYnVpbHRcbiAqIGluIGZvdXIgcGxhY2VzIGFuZCB0aGUgZmV0Y2jihpJkZWNvZGUgcGlwZWxpbmUgY29weS1wYXN0ZWQgaW4gdGhyZWUg4oCUIGV2ZXJ5XG4gKiBxdWVyeS1wYXJhbSBjaGFuZ2UgaGFkIHRvIGJlIHJlcGVhdGVkIHBlciBzaXRlLlxuICpcbiAqIEVycm9yIGhhbmRsaW5nIGlzIGRlbGliZXJhdGVseSBsZWZ0IHRvIHRoZSBDQUxMIFNJVEVTOiB0aGVzZSBoZWxwZXJzXG4gKiBwcm9wYWdhdGUgZmFpbHVyZXMgc28gZWFjaCBjYWxsZXIga2VlcHMgaXRzIG93biB0YWdnZWQgY2F0Y2hcbiAqIChgW3ZpejpoaXN0b2dyYW1dYCwgYFt2aXo6d2luZG93XWAsIGBbdml6OmV4cG9ydF1gKSBhbmQgaXRzIG93blxuICogc2tpcC9mYWxsYmFjayBzZW1hbnRpY3MuXG4gKi9cblxuLyoqIFRpbGUgY29vcmRpbmF0ZXMgZm9yIG9uZSBgL3RpbGVgIHJlcXVlc3QuIGBjaGFubmVsID09IG51bGxgIChvciBvbWl0dGVkKVxuICogIHJlcXVlc3RzIHRoZSBzZXJ2ZXItY29tcG9zaXRlZCB0aWxlOyBhbiBpbmRleCAoaW5jbHVkaW5nIDApIHJlcXVlc3RzIHRoYXRcbiAqICBzaW5nbGUgY2hhbm5lbCBhcyBncmF5c2NhbGUuICovXG5leHBvcnQgaW50ZXJmYWNlIFRpbGVDb29yZHMge1xuICByZXM6IG51bWJlcjtcbiAgY29sOiBudW1iZXI7XG4gIHJvdzogbnVtYmVyO1xuICB6OiBudW1iZXI7XG4gIHRpbGVTaXplOiBudW1iZXI7XG4gIGNoYW5uZWw/OiBudW1iZXIgfCBudWxsO1xufVxuXG4vKiogQnVpbGQgdGhlIGAvdGlsZWAgcmVxdWVzdCBVUkwg4oCUIHRoZSBvbmUgcGxhY2UgaXRzIHF1ZXJ5IHNoYXBlIGxpdmVzLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkVGlsZVVybChhcGk6IHN0cmluZywgaW5mb0I2NDogc3RyaW5nLCBjOiBUaWxlQ29vcmRzKTogc3RyaW5nIHtcbiAgY29uc3QgY2ggPSBjLmNoYW5uZWwgPT0gbnVsbCA/ICcnIDogYCZjaGFubmVsPSR7Yy5jaGFubmVsfWA7XG4gIHJldHVybiBgJHthcGl9dGlsZT9pbmZvPSR7aW5mb0I2NH0mcmVzPSR7Yy5yZXN9JmNvbD0ke2MuY29sfSZyb3c9JHtjLnJvd30mej0ke2Muen0mdGlsZVNpemU9JHtjLnRpbGVTaXplfSR7Y2h9YDtcbn1cblxuLyoqIEZldGNoIGEgdGlsZSBQTkcgYW5kIGRlY29kZSBpdCB0byBhbiBJbWFnZUJpdG1hcC4gVGhlIGNhbGxlciBvd25zIHRoZVxuICogIGJpdG1hcCAoY2FsbCBgY2xvc2UoKWAgd2hlbiBkb25lKS4gVGhyb3dzIG9uIG5ldHdvcmsvZGVjb2RlIGZhaWx1cmUuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZmV0Y2hUaWxlQml0bWFwKGh0dHA6IEh0dHBDbGllbnQsIHVybDogc3RyaW5nLCB0aW1lb3V0TXM6IG51bWJlcik6IFByb21pc2U8SW1hZ2VCaXRtYXA+IHtcbiAgY29uc3QgYmxvYiA9IGF3YWl0IGZpcnN0VmFsdWVGcm9tKGh0dHAuZ2V0KHVybCwgeyByZXNwb25zZVR5cGU6ICdibG9iJyB9KS5waXBlKHRpbWVvdXQodGltZW91dE1zKSkpO1xuICByZXR1cm4gY3JlYXRlSW1hZ2VCaXRtYXAoYmxvYik7XG59XG5cbi8qKiBGZXRjaCBhIHRpbGUgYW5kIHJlYWQgaXRzIHBpeGVscyBiYWNrIGFzIFJHQkEgSW1hZ2VEYXRhICh2aWEgYW4gb2Zmc2NyZWVuXG4gKiAgY2FudmFzKS4gUmV0dXJucyBudWxsIG9ubHkgd2hlbiBhIDJkIGNvbnRleHQgY2FuJ3QgYmUgY3JlYXRlZDsgdGhyb3dzIG9uXG4gKiAgbmV0d29yay9kZWNvZGUgZmFpbHVyZSAodGhlIGNhbGxlcidzIHRhZ2dlZCBjYXRjaCBoYW5kbGVzIGl0KS4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBmZXRjaFRpbGVSZ2JhKFxuICBodHRwOiBIdHRwQ2xpZW50LCB1cmw6IHN0cmluZywgdGltZW91dE1zOiBudW1iZXIsXG4pOiBQcm9taXNlPEltYWdlRGF0YSB8IG51bGw+IHtcbiAgY29uc3QgYm1wID0gYXdhaXQgZmV0Y2hUaWxlQml0bWFwKGh0dHAsIHVybCwgdGltZW91dE1zKTtcbiAgY29uc3QgY3YgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgY3Yud2lkdGggPSBibXAud2lkdGg7XG4gIGN2LmhlaWdodCA9IGJtcC5oZWlnaHQ7XG4gIGNvbnN0IGN0eCA9IGN2LmdldENvbnRleHQoJzJkJywgeyB3aWxsUmVhZEZyZXF1ZW50bHk6IHRydWUgfSk7XG4gIGlmICghY3R4KSByZXR1cm4gbnVsbDtcbiAgY3R4LmRyYXdJbWFnZShibXAsIDAsIDApO1xuICBibXAuY2xvc2U/LigpO1xuICByZXR1cm4gY3R4LmdldEltYWdlRGF0YSgwLCAwLCBjdi53aWR0aCwgY3YuaGVpZ2h0KTtcbn1cbiJdfQ==