@jax-data-science/sci-image-visualizer 0.8.3 → 0.10.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.
- package/README.md +201 -460
- package/esm2022/index.mjs +34 -15
- package/esm2022/lib/channel-histogram/channel-histogram.component.mjs +163 -91
- package/esm2022/lib/contracts/capabilities.contract.mjs +4 -3
- package/esm2022/lib/contracts/cell-segmenter.contract.mjs +1 -1
- package/esm2022/lib/contracts/channel-histogram-api.contract.mjs +5 -1
- package/esm2022/lib/contracts/color.mjs +60 -0
- package/esm2022/lib/contracts/colormap-lut.mjs +213 -57
- package/esm2022/lib/contracts/coordinate-transform.contract.mjs +1 -1
- package/esm2022/lib/contracts/display-types.mjs +11 -1
- package/esm2022/lib/contracts/image.contract.mjs +1 -1
- package/esm2022/lib/contracts/instance-segmenter.contract.mjs +1 -1
- package/esm2022/lib/contracts/intensity.mjs +48 -5
- package/esm2022/lib/contracts/plot-type-contribution.contract.mjs +1 -1
- package/esm2022/lib/contracts/plot-type.mjs +134 -17
- package/esm2022/lib/contracts/ports/image-state.port.mjs +4 -1
- package/esm2022/lib/contracts/ports/preferences.port.mjs +5 -1
- package/esm2022/lib/contracts/ports/region-io.port.mjs +2 -1
- package/esm2022/lib/contracts/ports/spatial-data.port.mjs +5 -1
- package/esm2022/lib/contracts/ports/tile-access.port.mjs +2 -1
- package/esm2022/lib/contracts/region-editor-api.contract.mjs +1 -1
- package/esm2022/lib/contracts/region-overlay.contract.mjs +1 -1
- package/esm2022/lib/contracts/region-store.contract.mjs +1 -1
- package/esm2022/lib/contracts/sam.contract.mjs +1 -1
- package/esm2022/lib/contracts/section-view.contract.mjs +2 -0
- package/esm2022/lib/contracts/semantic-segmenter.contract.mjs +1 -1
- package/esm2022/lib/contracts/spatial-dataset.contract.mjs +3 -1
- package/esm2022/lib/contracts/toolbar-tool.contract.mjs +6 -4
- package/esm2022/lib/contracts/visualizer.contract.mjs +1 -1
- package/esm2022/lib/contracts/viz-config.mjs +2 -1
- package/esm2022/lib/geometry/contour.mjs +63 -0
- package/esm2022/lib/geometry/loft.mjs +128 -0
- package/esm2022/lib/geometry/polylabel.mjs +156 -0
- package/esm2022/lib/geometry/raster.mjs +98 -0
- package/esm2022/lib/geometry/reconstruct.mjs +315 -0
- package/esm2022/lib/geometry/reslice-image.mjs +57 -0
- package/esm2022/lib/geometry/ring.mjs +201 -0
- package/esm2022/lib/geometry/section.mjs +215 -0
- package/esm2022/lib/hex-color-picker/hex-color-picker.component.mjs +202 -102
- package/esm2022/lib/implementations/base-store-visualizer.mjs +201 -48
- package/esm2022/lib/implementations/napari-js/napari-axes-gizmo.mjs +65 -0
- package/esm2022/lib/implementations/napari-js/napari-display-state.mjs +136 -0
- package/esm2022/lib/implementations/napari-js/napari-helpers.mjs +199 -0
- package/esm2022/lib/implementations/napari-js/napari-image-2d-scene.mjs +602 -0
- package/esm2022/lib/implementations/napari-js/napari-loading-badge.mjs +12 -9
- package/esm2022/lib/implementations/napari-js/napari-loading-state.mjs +83 -0
- package/esm2022/lib/implementations/napari-js/napari-region-mesh-pointer.mjs +100 -0
- package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +180 -591
- package/esm2022/lib/implementations/napari-js/napari-scene.mjs +2 -0
- package/esm2022/lib/implementations/napari-js/napari-spatial-2d-scene.mjs +614 -0
- package/esm2022/lib/implementations/napari-js/napari-spatial-3d-scene.mjs +769 -0
- package/esm2022/lib/implementations/napari-js/napari-spatial-encoding.mjs +199 -0
- package/esm2022/lib/implementations/napari-js/napari-spatial-hover.mjs +270 -0
- package/esm2022/lib/implementations/napari-js/napari-spatial-scene.mjs +159 -0
- package/esm2022/lib/implementations/napari-js/napari-spatial-tiles.mjs +106 -1408
- package/esm2022/lib/implementations/napari-js/napari-spatial-tooltip.mjs +2 -2
- package/esm2022/lib/implementations/napari-js/napari-surface-scene.mjs +271 -0
- package/esm2022/lib/implementations/napari-js/napari-tile-client.mjs +562 -0
- package/esm2022/lib/implementations/napari-js/napari-tool-bridge.mjs +347 -0
- package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +427 -4207
- package/esm2022/lib/implementations/napari-js/napari-volume-region-meshes.mjs +129 -0
- package/esm2022/lib/implementations/napari-js/napari-volume-scene.mjs +550 -0
- package/esm2022/lib/implementations/napari-js/napari-volume-slice-planes.mjs +103 -0
- package/esm2022/lib/implementations/napari-js/napari-volume-z-handle.mjs +6 -6
- package/esm2022/lib/implementations/napari-js/region-overlay/overlay-projection.mjs +96 -0
- package/esm2022/lib/implementations/napari-js/region-overlay/region-edit.mjs +35 -0
- package/esm2022/lib/implementations/napari-js/region-overlay/region-svg-renderer.mjs +194 -0
- package/esm2022/lib/implementations/napari-js/spatial-tiles/categorical-lookup.mjs +30 -0
- package/esm2022/lib/implementations/napari-js/spatial-tiles/cell-layers.mjs +274 -0
- package/esm2022/lib/implementations/napari-js/spatial-tiles/density-layer.mjs +144 -0
- package/esm2022/lib/implementations/napari-js/spatial-tiles/layer-groups.mjs +165 -0
- package/esm2022/lib/implementations/napari-js/spatial-tiles/plan-context.mjs +78 -0
- package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-hover.mjs +182 -0
- package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-jobs.mjs +369 -0
- package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-layers.mjs +306 -0
- package/esm2022/lib/implementations/osd/display-pipeline.mjs +102 -40
- package/esm2022/lib/implementations/osd/histogram-sampler.mjs +56 -31
- package/esm2022/lib/implementations/osd/openseadragon-viewer-options.mjs +128 -0
- package/esm2022/lib/implementations/osd/openseadragon-visualizer.service.mjs +333 -1685
- package/esm2022/lib/implementations/osd/osd-coordinate-transform.mjs +1 -1
- package/esm2022/lib/implementations/osd/osd-coords.mjs +5 -6
- package/esm2022/lib/implementations/osd/osd-export.mjs +122 -0
- package/esm2022/lib/implementations/osd/osd-lib.mjs +15 -1
- package/esm2022/lib/implementations/osd/osd-navigator-chrome.mjs +205 -0
- package/esm2022/lib/implementations/osd/osd-pixel-readback.mjs +68 -0
- package/esm2022/lib/implementations/osd/osd-region-overlay-draw.mjs +164 -0
- package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +213 -716
- package/esm2022/lib/implementations/osd/osd-scale-bar.mjs +52 -60
- package/esm2022/lib/implementations/osd/osd-tile-source.mjs +105 -0
- package/esm2022/lib/implementations/osd/osd-viewer-like.mjs +2 -0
- package/esm2022/lib/implementations/osd/osd-viewer-mount.mjs +44 -0
- package/esm2022/lib/implementations/osd/osd-viewport.mjs +184 -0
- package/esm2022/lib/implementations/osd/osd-zoom.mjs +7 -1
- package/esm2022/lib/implementations/osd/simple-source.mjs +395 -0
- package/esm2022/lib/implementations/osd/slice-cache.mjs +53 -48
- package/esm2022/lib/implementations/osd/tile-client.mjs +32 -11
- package/esm2022/lib/implementations/osd/tile-recolor.mjs +330 -0
- package/esm2022/lib/implementations/plotly/omics-trace-builders.mjs +161 -73
- package/esm2022/lib/implementations/plotly/plotly-coordinate-transform.mjs +1 -1
- package/esm2022/lib/implementations/plotly/plotly-image-loader.mjs +112 -0
- package/esm2022/lib/implementations/plotly/plotly-image-recolor.mjs +178 -0
- package/esm2022/lib/implementations/plotly/plotly-intensity-inset.mjs +33 -0
- package/esm2022/lib/implementations/plotly/plotly-isosurface-controls.mjs +83 -0
- package/esm2022/lib/implementations/plotly/plotly-layouts.mjs +121 -0
- package/esm2022/lib/implementations/plotly/plotly-readback.mjs +117 -0
- package/esm2022/lib/implementations/plotly/plotly-region-overlay.mjs +19 -10
- package/esm2022/lib/implementations/plotly/plotly-shape-projection.mjs +223 -0
- package/esm2022/lib/implementations/plotly/plotly-trace-builders.mjs +79 -19
- package/esm2022/lib/implementations/plotly/plotly-zoom-controller.mjs +223 -0
- package/esm2022/lib/implementations/plotly/plotly.service.mjs +439 -1655
- package/esm2022/lib/implementations/region-centroids.mjs +47 -0
- package/esm2022/lib/implementations/simple-slice-access.service.mjs +22 -12
- package/esm2022/lib/implementations/spatial-data-http/spatial-data-http.service.mjs +172 -92
- package/esm2022/lib/implementations/spatial-data-http/spatial-wire.mjs +103 -22
- package/esm2022/lib/implementations/tile-server/index.mjs +6 -0
- package/esm2022/lib/implementations/tile-server/native-histogram.mjs +30 -0
- package/esm2022/lib/implementations/tile-server/poll-descriptor.mjs +65 -0
- package/esm2022/lib/implementations/tile-server/tile-protocol.mjs +42 -0
- package/esm2022/lib/implementations/tile-server/transport.mjs +135 -0
- package/esm2022/lib/intensity/intensity-profile.mjs +107 -0
- package/esm2022/lib/intensity/intensity-profile.service.mjs +223 -0
- package/esm2022/lib/intensity-inset/intensity-inset.component.mjs +133 -0
- package/esm2022/lib/models/bezier.mjs +1 -11
- package/esm2022/lib/models/class-preset.mjs +41 -3
- package/esm2022/lib/models/geometry.mjs +27 -164
- package/esm2022/lib/models/polygon-edit.mjs +254 -0
- package/esm2022/lib/models/polygon-factory.mjs +134 -0
- package/esm2022/lib/models/region-clone.mjs +68 -0
- package/esm2022/lib/models/region-geojson.mjs +411 -0
- package/esm2022/lib/models/region.mjs +34 -33
- package/esm2022/lib/models/shape.mjs +18 -16
- package/esm2022/lib/plot-mode/contribution-host.mjs +297 -0
- package/esm2022/lib/plot-mode/plot-mode-controller.mjs +9 -6
- package/esm2022/lib/plot-mode/plot-type-menu.mjs +85 -0
- package/esm2022/lib/plot-mode/tool-params-model.mjs +87 -0
- package/esm2022/lib/plot.utilities.mjs +296 -473
- package/esm2022/lib/processing/image-crop.mjs +1 -1
- package/esm2022/lib/processing/processing-image.mjs +28 -15
- package/esm2022/lib/provide-visualization.mjs +40 -14
- package/esm2022/lib/region-editor/class-tree/class-tree.component.mjs +156 -0
- package/esm2022/lib/region-editor/class-tree/class-tree.mjs +108 -0
- package/esm2022/lib/region-editor/classes-panel/classes-panel.component.mjs +163 -0
- package/esm2022/lib/region-editor/file-stem.mjs +13 -0
- package/esm2022/lib/region-editor/manage-classes-dialog/manage-classes-dialog.component.mjs +118 -0
- package/esm2022/lib/region-editor/mask-export.service.mjs +98 -0
- package/esm2022/lib/region-editor/mask-raster.mjs +11 -5
- package/esm2022/lib/region-editor/region-color-dialog/region-color-dialog.component.mjs +56 -0
- package/esm2022/lib/region-editor/region-editor-help/region-editor-help.component.mjs +28 -0
- package/esm2022/lib/region-editor/region-editor.component.mjs +896 -660
- package/esm2022/lib/region-editor/region-metrics.mjs +86 -0
- package/esm2022/lib/region-editor/region-persistence.service.mjs +160 -0
- package/esm2022/lib/region-editor/region-table/region-table.component.mjs +169 -0
- package/esm2022/lib/region-editor/save-mask-dialog/save-mask-dialog.component.mjs +91 -0
- package/esm2022/lib/region-editor/save-regions-dialog/save-regions-dialog.component.mjs +92 -0
- package/esm2022/lib/region-ops.service.mjs +28 -70
- package/esm2022/lib/region-overlay/region-geometry.mjs +360 -0
- package/esm2022/lib/region-overlay/region-hit-test.mjs +103 -0
- package/esm2022/lib/region-overlay/region-source-layer.mjs +378 -0
- package/esm2022/lib/region-overlay/region-style.mjs +97 -0
- package/esm2022/lib/region-overlay/svg-region-renderer.mjs +228 -0
- package/esm2022/lib/region-source/http-region-source.mjs +104 -0
- package/esm2022/lib/region-source/region-source-ops.mjs +53 -0
- package/esm2022/lib/region-source/region-source-worker.mjs +10 -0
- package/esm2022/lib/region-source/region-source.mjs +67 -0
- package/esm2022/lib/region-source/region-tiles.mjs +708 -0
- package/esm2022/lib/region-source/worker-region-source.mjs +229 -0
- package/esm2022/lib/render-orchestrator.mjs +14 -11
- package/esm2022/lib/render-session.mjs +207 -0
- package/esm2022/lib/routing-visualizer.service.mjs +858 -414
- package/esm2022/lib/section-pane/section-pane.component.mjs +299 -0
- package/esm2022/lib/spatial/density-raster.mjs +14 -0
- package/esm2022/lib/spatial/embedding-compute-coordinator.mjs +239 -0
- package/esm2022/lib/spatial/embedding-compute.mjs +43 -10
- package/esm2022/lib/spatial/gene-search.mjs +1 -1
- package/esm2022/lib/spatial/glyphs.mjs +97 -0
- package/esm2022/lib/spatial/lod.mjs +187 -0
- package/esm2022/lib/spatial/spatial-controls.facade.mjs +200 -0
- package/esm2022/lib/spatial/spatial-density.mjs +25 -16
- package/esm2022/lib/spatial/spatial-encoding.mjs +26 -82
- package/esm2022/lib/spatial/spatial-expression.mjs +43 -42
- package/esm2022/lib/spatial/spatial-framing.mjs +1 -1
- package/esm2022/lib/spatial/spatial-heatmap.mjs +6 -3
- package/esm2022/lib/spatial/spatial-hover.mjs +5 -33
- package/esm2022/lib/spatial/spatial-panel-model.mjs +282 -0
- package/esm2022/lib/spatial/spatial-sections.mjs +1 -1
- package/esm2022/lib/spatial/spatial-selection.mjs +33 -46
- package/esm2022/lib/spatial/spatial-tile-merge.mjs +219 -0
- package/esm2022/lib/spatial/spatial-tiles.mjs +12 -648
- package/esm2022/lib/spatial/spatial-volume-image.mjs +2 -4
- package/esm2022/lib/spatial/stats.mjs +71 -0
- package/esm2022/lib/spatial/transcript-grouping.mjs +307 -0
- package/esm2022/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.mjs +150 -0
- package/esm2022/lib/spatial-controls/spatial-charts/chart-data-model.mjs +309 -0
- package/esm2022/lib/spatial-controls/spatial-charts/chart-help.mjs +145 -0
- package/esm2022/lib/spatial-controls/spatial-charts/plotly-chart-host.mjs +158 -0
- package/esm2022/lib/spatial-controls/spatial-charts/spatial-chart-window/spatial-chart-window.component.mjs +47 -0
- package/esm2022/lib/spatial-controls/spatial-charts/spatial-charts.component.mjs +297 -802
- package/esm2022/lib/spatial-controls/spatial-charts/spatial-embedding-controls/spatial-embedding-controls.component.mjs +89 -0
- package/esm2022/lib/spatial-controls/spatial-charts/spatial-heatmap-controls/spatial-heatmap-controls.component.mjs +52 -0
- package/esm2022/lib/spatial-controls/spatial-controls.component.mjs +143 -1238
- package/esm2022/lib/spatial-controls/spatial-gene-picker.mjs +153 -0
- package/esm2022/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.mjs +241 -0
- package/esm2022/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.mjs +193 -0
- package/esm2022/lib/spatial-controls/spatial-key/spatial-key.component.mjs +132 -0
- package/esm2022/lib/spatial-controls/spatial-key/spatial-key.model.mjs +67 -0
- package/esm2022/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.mjs +147 -0
- package/esm2022/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.mjs +300 -0
- package/esm2022/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.mjs +370 -0
- package/esm2022/lib/store/class-color.util.mjs +53 -5
- package/esm2022/lib/store/class-signatures.mjs +63 -0
- package/esm2022/lib/store/region-history.mjs +146 -0
- package/esm2022/lib/store/region-scope-cache.mjs +144 -0
- package/esm2022/lib/store/region-selection.mjs +82 -0
- package/esm2022/lib/store/region-source-scope.mjs +171 -0
- package/esm2022/lib/store/region-store.service.mjs +986 -670
- package/esm2022/lib/store/spatial-selection.service.mjs +2 -2
- package/esm2022/lib/store/visualizer-store.service.mjs +81 -76
- package/esm2022/lib/toast-outlets.mjs +5 -4
- package/esm2022/lib/toolbar/brush/brush-tool.service.mjs +92 -434
- package/esm2022/lib/toolbar/canvas-tools.mjs +20 -0
- package/esm2022/lib/toolbar/crop/slide-crop.mjs +26 -42
- package/esm2022/lib/toolbar/plot-type-selector/plot-type-selector.component.mjs +85 -0
- package/esm2022/lib/toolbar/region-tools/region-tool-buttons.mjs +74 -0
- package/esm2022/lib/toolbar/region-tools/region-tools.component.mjs +120 -0
- package/esm2022/lib/toolbar/segmentation/cell-segment-tool.service.mjs +74 -78
- package/esm2022/lib/toolbar/segmentation/cellpose-segmenter.service.mjs +50 -8
- package/esm2022/lib/toolbar/segmentation/onnx-sam-session.mjs +61 -42
- package/esm2022/lib/toolbar/segmentation/pending-calls.mjs +47 -0
- package/esm2022/lib/toolbar/segmentation/sam-model-registry.mjs +12 -4
- package/esm2022/lib/toolbar/segmentation/sam-onnx-core.mjs +70 -14
- package/esm2022/lib/toolbar/segmentation/sam-point-tool.service.mjs +135 -172
- package/esm2022/lib/toolbar/segmentation/sam-prompt.mjs +9 -90
- package/esm2022/lib/toolbar/segmentation/sam-session.service.mjs +183 -0
- package/esm2022/lib/toolbar/segmentation/sam-tool.service.mjs +95 -150
- package/esm2022/lib/toolbar/segmentation/segmentation-commit.mjs +12 -0
- package/esm2022/lib/toolbar/segmentation/segmentation-runner.mjs +108 -0
- package/esm2022/lib/toolbar/segmentation-tools/segmentation-tools.component.mjs +155 -0
- package/esm2022/lib/toolbar/stack-controls/stack-controls.component.mjs +121 -0
- package/esm2022/lib/toolbar/tool-kit/async-tool-status.mjs +37 -0
- package/esm2022/lib/toolbar/tool-kit/canvas-tool-manager.mjs +63 -0
- package/esm2022/lib/toolbar/tool-kit/canvas-tool.mjs +2 -0
- package/esm2022/lib/toolbar/tool-kit/frame-pixels.mjs +108 -0
- package/esm2022/lib/toolbar/tool-kit/mask-stroke-editor.mjs +306 -0
- package/esm2022/lib/toolbar/tool-kit/matrix-frame.mjs +61 -0
- package/esm2022/lib/toolbar/tool-kit/tool-overlay.mjs +140 -0
- package/esm2022/lib/toolbar/tool-kit/undo-gesture.mjs +24 -0
- package/esm2022/lib/toolbar/tool-slider/tool-slider.component.mjs +63 -0
- package/esm2022/lib/toolbar/toolbar-help-dialog/toolbar-help-dialog.component.mjs +50 -0
- package/esm2022/lib/toolbar/toolbar.component.mjs +84 -119
- package/esm2022/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.mjs +93 -115
- package/esm2022/lib/toolbar/view-controls/view-controls.component.mjs +107 -0
- package/esm2022/lib/toolbar/wand/wand-region-grow.mjs +321 -0
- package/esm2022/lib/toolbar/wand/wand-tool.service.mjs +121 -416
- package/esm2022/lib/toolbar/wand/wand.service.mjs +30 -894
- package/esm2022/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.mjs +48 -90
- package/esm2022/lib/util/mark-for-check.mjs +17 -0
- package/esm2022/lib/util/supersede.mjs +56 -0
- package/esm2022/lib/visualization.module.mjs +39 -141
- package/esm2022/lib/visualizer/floating-drag.directive.mjs +58 -0
- package/esm2022/lib/visualizer/region-actions.mjs +149 -0
- package/esm2022/lib/visualizer/region-load.mjs +123 -0
- package/esm2022/lib/visualizer/spatial-dataset-binder.mjs +163 -0
- package/esm2022/lib/visualizer/tool-modes.mjs +113 -0
- package/esm2022/lib/visualizer/viewer-shortcuts.mjs +167 -0
- package/esm2022/lib/visualizer/visualizer-context-menu.mjs +119 -0
- package/esm2022/lib/visualizer/volume-sections.mjs +175 -0
- package/esm2022/lib/visualizer.component.mjs +602 -1902
- package/esm2022/lib/workers/spatial-math-ops.mjs +43 -0
- package/esm2022/lib/workers/spatial-math-worker.mjs +10 -0
- package/esm2022/lib/workers/spatial-math.mjs +190 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-BKQhpbHv.mjs +47169 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-BKQhpbHv.mjs.map +1 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-z1IN-F7w.mjs +238 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-z1IN-F7w.mjs.map +1 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-region-source-worker-CAqBjM5L.mjs +12 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-region-source-worker-CAqBjM5L.mjs.map +1 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-spatial-math-worker-BzVFFqGS.mjs +12 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-spatial-math-worker-BzVFFqGS.mjs.map +1 -0
- package/fesm2022/jax-data-science-sci-image-visualizer.mjs +41 -34467
- package/fesm2022/jax-data-science-sci-image-visualizer.mjs.map +1 -1
- package/fesm2022/mask.worker.js +36 -917
- package/fesm2022/onnx-sam.worker.js +52 -16
- package/fesm2022/region-source.worker.js +1067 -0
- package/fesm2022/spatial-math.worker.js +471 -0
- package/fesm2022/tsne.worker.js +32 -15
- package/index.d.ts +19 -10
- package/lib/channel-histogram/channel-histogram.component.d.ts +53 -43
- package/lib/contracts/capabilities.contract.d.ts +4 -2
- package/lib/contracts/cell-segmenter.contract.d.ts +1 -0
- package/lib/contracts/channel-histogram-api.contract.d.ts +4 -0
- package/lib/contracts/color.d.ts +27 -0
- package/lib/contracts/colormap-lut.d.ts +19 -4
- package/lib/contracts/coordinate-transform.contract.d.ts +3 -3
- package/lib/contracts/display-types.d.ts +21 -0
- package/lib/contracts/image.contract.d.ts +4 -0
- package/lib/contracts/instance-segmenter.contract.d.ts +5 -0
- package/lib/contracts/intensity.d.ts +13 -2
- package/lib/contracts/plot-type.d.ts +3 -1
- package/lib/contracts/ports/image-state.port.d.ts +6 -2
- package/lib/contracts/ports/preferences.port.d.ts +4 -0
- package/lib/contracts/ports/region-io.port.d.ts +1 -0
- package/lib/contracts/ports/spatial-data.port.d.ts +4 -10
- package/lib/contracts/ports/tile-access.port.d.ts +1 -0
- package/lib/contracts/region-editor-api.contract.d.ts +85 -1
- package/lib/contracts/region-overlay.contract.d.ts +5 -0
- package/lib/contracts/region-store.contract.d.ts +22 -0
- package/lib/contracts/sam.contract.d.ts +7 -0
- package/lib/contracts/section-view.contract.d.ts +44 -0
- package/lib/contracts/semantic-segmenter.contract.d.ts +6 -0
- package/lib/contracts/spatial-dataset.contract.d.ts +19 -6
- package/lib/contracts/toolbar-tool.contract.d.ts +1 -0
- package/lib/contracts/visualizer.contract.d.ts +231 -54
- package/lib/contracts/viz-config.d.ts +9 -0
- package/lib/geometry/contour.d.ts +24 -0
- package/lib/geometry/loft.d.ts +22 -0
- package/lib/geometry/polylabel.d.ts +23 -0
- package/lib/geometry/raster.d.ts +42 -0
- package/lib/geometry/reconstruct.d.ts +54 -0
- package/lib/geometry/reslice-image.d.ts +33 -0
- package/lib/geometry/ring.d.ts +67 -0
- package/lib/geometry/section.d.ts +52 -0
- package/lib/hex-color-picker/hex-color-picker.component.d.ts +61 -27
- package/lib/implementations/base-store-visualizer.d.ts +61 -15
- package/lib/implementations/napari-js/napari-axes-gizmo.d.ts +36 -0
- package/lib/implementations/napari-js/napari-display-state.d.ts +76 -0
- package/lib/implementations/napari-js/napari-helpers.d.ts +129 -0
- package/lib/implementations/napari-js/napari-image-2d-scene.d.ts +162 -0
- package/lib/implementations/napari-js/napari-loading-badge.d.ts +4 -3
- package/lib/implementations/napari-js/napari-loading-state.d.ts +37 -0
- package/lib/implementations/napari-js/napari-region-mesh-pointer.d.ts +32 -0
- package/lib/implementations/napari-js/napari-region-overlay.d.ts +68 -71
- package/lib/implementations/napari-js/napari-scene.d.ts +126 -0
- package/lib/implementations/napari-js/napari-spatial-2d-scene.d.ts +163 -0
- package/lib/implementations/napari-js/napari-spatial-3d-scene.d.ts +212 -0
- package/lib/implementations/napari-js/napari-spatial-encoding.d.ts +114 -0
- package/lib/implementations/napari-js/napari-spatial-hover.d.ts +91 -0
- package/lib/implementations/napari-js/napari-spatial-scene.d.ts +118 -0
- package/lib/implementations/napari-js/napari-spatial-tiles.d.ts +56 -263
- package/lib/implementations/napari-js/napari-spatial-tooltip.d.ts +1 -1
- package/lib/implementations/napari-js/napari-surface-scene.d.ts +76 -0
- package/lib/implementations/napari-js/napari-tile-client.d.ts +214 -0
- package/lib/implementations/napari-js/napari-tool-bridge.d.ts +179 -0
- package/lib/implementations/napari-js/napari-visualizer.service.d.ts +169 -883
- package/lib/implementations/napari-js/napari-volume-region-meshes.d.ts +66 -0
- package/lib/implementations/napari-js/napari-volume-scene.d.ts +148 -0
- package/lib/implementations/napari-js/napari-volume-slice-planes.d.ts +43 -0
- package/lib/implementations/napari-js/napari-volume-z-handle.d.ts +8 -12
- package/lib/implementations/napari-js/region-overlay/overlay-projection.d.ts +59 -0
- package/lib/implementations/napari-js/region-overlay/region-edit.d.ts +15 -0
- package/lib/implementations/napari-js/region-overlay/region-svg-renderer.d.ts +54 -0
- package/lib/implementations/napari-js/spatial-tiles/categorical-lookup.d.ts +26 -0
- package/lib/implementations/napari-js/spatial-tiles/cell-layers.d.ts +70 -0
- package/lib/implementations/napari-js/spatial-tiles/density-layer.d.ts +61 -0
- package/lib/implementations/napari-js/spatial-tiles/layer-groups.d.ts +67 -0
- package/lib/implementations/napari-js/spatial-tiles/plan-context.d.ts +38 -0
- package/lib/implementations/napari-js/spatial-tiles/transcript-hover.d.ts +71 -0
- package/lib/implementations/napari-js/spatial-tiles/transcript-jobs.d.ts +105 -0
- package/lib/implementations/napari-js/spatial-tiles/transcript-layers.d.ts +56 -0
- package/lib/implementations/osd/display-pipeline.d.ts +38 -9
- package/lib/implementations/osd/histogram-sampler.d.ts +22 -12
- package/lib/implementations/osd/openseadragon-viewer-options.d.ts +35 -0
- package/lib/implementations/osd/openseadragon-visualizer.service.d.ts +78 -354
- package/lib/implementations/osd/osd-coordinate-transform.d.ts +2 -1
- package/lib/implementations/osd/osd-coords.d.ts +6 -4
- package/lib/implementations/osd/osd-export.d.ts +36 -0
- package/lib/implementations/osd/osd-lib.d.ts +7 -0
- package/lib/implementations/osd/osd-navigator-chrome.d.ts +69 -0
- package/lib/implementations/osd/osd-pixel-readback.d.ts +22 -0
- package/lib/implementations/osd/osd-region-overlay-draw.d.ts +38 -0
- package/lib/implementations/osd/osd-region-overlay.d.ts +46 -51
- package/lib/implementations/osd/osd-scale-bar.d.ts +8 -6
- package/lib/implementations/osd/osd-tile-source.d.ts +49 -0
- package/lib/implementations/osd/osd-viewer-like.d.ts +100 -0
- package/lib/implementations/osd/osd-viewer-mount.d.ts +14 -0
- package/lib/implementations/osd/osd-viewport.d.ts +77 -0
- package/lib/implementations/osd/osd-zoom.d.ts +6 -0
- package/lib/implementations/osd/simple-source.d.ts +161 -0
- package/lib/implementations/osd/slice-cache.d.ts +12 -3
- package/lib/implementations/osd/tile-client.d.ts +11 -14
- package/lib/implementations/osd/tile-recolor.d.ts +141 -0
- package/lib/implementations/plotly/omics-trace-builders.d.ts +32 -20
- package/lib/implementations/plotly/plotly-image-loader.d.ts +49 -0
- package/lib/implementations/plotly/plotly-image-recolor.d.ts +75 -0
- package/lib/implementations/plotly/plotly-intensity-inset.d.ts +8 -0
- package/lib/implementations/plotly/plotly-isosurface-controls.d.ts +38 -0
- package/lib/implementations/plotly/plotly-layouts.d.ts +188 -0
- package/lib/implementations/plotly/plotly-readback.d.ts +41 -0
- package/lib/implementations/plotly/plotly-region-overlay.d.ts +2 -2
- package/lib/implementations/plotly/plotly-shape-projection.d.ts +92 -0
- package/lib/implementations/plotly/plotly-trace-builders.d.ts +23 -12
- package/lib/implementations/plotly/plotly-zoom-controller.d.ts +86 -0
- package/lib/implementations/plotly/plotly.service.d.ts +136 -401
- package/lib/implementations/region-centroids.d.ts +14 -0
- package/lib/implementations/simple-slice-access.service.d.ts +7 -4
- package/lib/implementations/spatial-data-http/spatial-data-http.service.d.ts +42 -18
- package/lib/implementations/spatial-data-http/spatial-wire.d.ts +34 -9
- package/lib/implementations/tile-server/index.d.ts +5 -0
- package/lib/implementations/tile-server/native-histogram.d.ts +25 -0
- package/lib/implementations/tile-server/poll-descriptor.d.ts +39 -0
- package/lib/implementations/tile-server/tile-protocol.d.ts +83 -0
- package/lib/implementations/tile-server/transport.d.ts +62 -0
- package/lib/intensity/intensity-profile.d.ts +66 -0
- package/lib/intensity/intensity-profile.service.d.ts +108 -0
- package/lib/intensity-inset/intensity-inset.component.d.ts +58 -0
- package/lib/models/bezier.d.ts +0 -5
- package/lib/models/class-preset.d.ts +25 -0
- package/lib/models/geometry.d.ts +14 -48
- package/lib/models/polygon-edit.d.ts +72 -0
- package/lib/models/polygon-factory.d.ts +45 -0
- package/lib/models/region-clone.d.ts +20 -0
- package/lib/models/region-geojson.d.ts +57 -0
- package/lib/models/region.d.ts +59 -4
- package/lib/models/shape.d.ts +8 -0
- package/lib/plot-mode/contribution-host.d.ts +125 -0
- package/lib/plot-mode/plot-type-menu.d.ts +60 -0
- package/lib/plot-mode/tool-params-model.d.ts +49 -0
- package/lib/plot.utilities.d.ts +19 -30
- package/lib/processing/processing-image.d.ts +5 -2
- package/lib/provide-visualization.d.ts +19 -2
- package/lib/region-editor/class-tree/class-tree.component.d.ts +78 -0
- package/lib/region-editor/class-tree/class-tree.d.ts +31 -0
- package/lib/region-editor/classes-panel/classes-panel.component.d.ts +86 -0
- package/lib/region-editor/file-stem.d.ts +7 -0
- package/lib/region-editor/manage-classes-dialog/manage-classes-dialog.component.d.ts +45 -0
- package/lib/region-editor/mask-export.service.d.ts +54 -0
- package/lib/region-editor/mask-raster.d.ts +2 -8
- package/lib/region-editor/region-color-dialog/region-color-dialog.component.d.ts +29 -0
- package/lib/region-editor/region-editor-help/region-editor-help.component.d.ts +11 -0
- package/lib/region-editor/region-editor.component.d.ts +283 -200
- package/lib/region-editor/region-metrics.d.ts +34 -0
- package/lib/region-editor/region-persistence.service.d.ts +77 -0
- package/lib/region-editor/region-table/region-table.component.d.ts +89 -0
- package/lib/region-editor/save-mask-dialog/save-mask-dialog.component.d.ts +36 -0
- package/lib/region-editor/save-regions-dialog/save-regions-dialog.component.d.ts +37 -0
- package/lib/region-ops.service.d.ts +1 -7
- package/lib/region-overlay/region-geometry.d.ts +158 -0
- package/lib/region-overlay/region-hit-test.d.ts +38 -0
- package/lib/region-overlay/region-source-layer.d.ts +96 -0
- package/lib/region-overlay/region-style.d.ts +52 -0
- package/lib/region-overlay/svg-region-renderer.d.ts +110 -0
- package/lib/region-source/http-region-source.d.ts +45 -0
- package/lib/region-source/region-source-ops.d.ts +89 -0
- package/lib/region-source/region-source-worker.d.ts +7 -0
- package/lib/region-source/region-source.d.ts +82 -0
- package/lib/region-source/region-tiles.d.ts +289 -0
- package/lib/region-source/worker-region-source.d.ts +65 -0
- package/lib/render-orchestrator.d.ts +6 -2
- package/lib/render-session.d.ts +75 -0
- package/lib/routing-visualizer.service.d.ts +248 -59
- package/lib/section-pane/section-pane.component.d.ts +47 -0
- package/lib/spatial/density-raster.d.ts +6 -0
- package/lib/spatial/embedding-compute-coordinator.d.ts +123 -0
- package/lib/spatial/embedding-compute.d.ts +21 -2
- package/lib/spatial/glyphs.d.ts +16 -0
- package/lib/spatial/lod.d.ts +94 -0
- package/lib/spatial/spatial-controls.facade.d.ts +64 -0
- package/lib/spatial/spatial-density.d.ts +15 -5
- package/lib/spatial/spatial-encoding.d.ts +11 -44
- package/lib/spatial/spatial-expression.d.ts +40 -22
- package/lib/spatial/spatial-framing.d.ts +1 -0
- package/lib/spatial/spatial-heatmap.d.ts +2 -0
- package/lib/spatial/spatial-hover.d.ts +4 -16
- package/lib/spatial/spatial-panel-model.d.ts +135 -0
- package/lib/spatial/spatial-selection.d.ts +21 -26
- package/lib/spatial/spatial-tile-merge.d.ts +41 -0
- package/lib/spatial/spatial-tiles.d.ts +9 -256
- package/lib/spatial/stats.d.ts +38 -0
- package/lib/spatial/transcript-grouping.d.ts +119 -0
- package/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.d.ts +64 -0
- package/lib/spatial-controls/spatial-charts/chart-data-model.d.ts +153 -0
- package/lib/spatial-controls/spatial-charts/chart-help.d.ts +69 -0
- package/lib/spatial-controls/spatial-charts/plotly-chart-host.d.ts +98 -0
- package/lib/spatial-controls/spatial-charts/spatial-chart-window/spatial-chart-window.component.d.ts +26 -0
- package/lib/spatial-controls/spatial-charts/spatial-charts.component.d.ts +101 -260
- package/lib/spatial-controls/spatial-charts/spatial-embedding-controls/spatial-embedding-controls.component.d.ts +43 -0
- package/lib/spatial-controls/spatial-charts/spatial-heatmap-controls/spatial-heatmap-controls.component.d.ts +27 -0
- package/lib/spatial-controls/spatial-controls.component.d.ts +68 -448
- package/lib/spatial-controls/spatial-gene-picker.d.ts +86 -0
- package/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.d.ts +102 -0
- package/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.d.ts +72 -0
- package/lib/spatial-controls/spatial-key/spatial-key.component.d.ts +66 -0
- package/lib/spatial-controls/spatial-key/spatial-key.model.d.ts +33 -0
- package/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.d.ts +64 -0
- package/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.d.ts +117 -0
- package/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.d.ts +142 -0
- package/lib/store/class-color.util.d.ts +39 -2
- package/lib/store/class-signatures.d.ts +11 -0
- package/lib/store/region-history.d.ts +66 -0
- package/lib/store/region-scope-cache.d.ts +65 -0
- package/lib/store/region-selection.d.ts +36 -0
- package/lib/store/region-source-scope.d.ts +68 -0
- package/lib/store/region-store.service.d.ts +312 -116
- package/lib/store/visualizer-store.service.d.ts +32 -33
- package/lib/toast-outlets.d.ts +4 -3
- package/lib/toolbar/brush/brush-tool.service.d.ts +31 -98
- package/lib/toolbar/canvas-tools.d.ts +20 -0
- package/lib/toolbar/crop/slide-crop.d.ts +10 -4
- package/lib/toolbar/plot-type-selector/plot-type-selector.component.d.ts +38 -0
- package/lib/toolbar/region-tools/region-tool-buttons.d.ts +21 -0
- package/lib/toolbar/region-tools/region-tools.component.d.ts +62 -0
- package/lib/toolbar/segmentation/cell-segment-tool.service.d.ts +10 -14
- package/lib/toolbar/segmentation/cellpose-segmenter.service.d.ts +12 -2
- package/lib/toolbar/segmentation/onnx-sam-session.d.ts +22 -3
- package/lib/toolbar/segmentation/pending-calls.d.ts +31 -0
- package/lib/toolbar/segmentation/sam-model-registry.d.ts +9 -3
- package/lib/toolbar/segmentation/sam-onnx-core.d.ts +18 -5
- package/lib/toolbar/segmentation/sam-point-tool.service.d.ts +46 -32
- package/lib/toolbar/segmentation/sam-prompt.d.ts +7 -31
- package/lib/toolbar/segmentation/sam-session.service.d.ts +74 -0
- package/lib/toolbar/segmentation/sam-tool.service.d.ts +23 -30
- package/lib/toolbar/segmentation/segmentation-commit.d.ts +8 -0
- package/lib/toolbar/segmentation/segmentation-runner.d.ts +52 -0
- package/lib/toolbar/segmentation-tools/segmentation-tools.component.d.ts +87 -0
- package/lib/toolbar/stack-controls/stack-controls.component.d.ts +51 -0
- package/lib/toolbar/tool-kit/async-tool-status.d.ts +21 -0
- package/lib/toolbar/tool-kit/canvas-tool-manager.d.ts +36 -0
- package/lib/toolbar/tool-kit/canvas-tool.d.ts +86 -0
- package/lib/toolbar/tool-kit/frame-pixels.d.ts +45 -0
- package/lib/toolbar/tool-kit/mask-stroke-editor.d.ts +125 -0
- package/lib/toolbar/tool-kit/matrix-frame.d.ts +40 -0
- package/lib/toolbar/tool-kit/tool-overlay.d.ts +60 -0
- package/lib/toolbar/tool-kit/undo-gesture.d.ts +17 -0
- package/lib/toolbar/tool-slider/tool-slider.component.d.ts +33 -0
- package/lib/toolbar/toolbar-help-dialog/toolbar-help-dialog.component.d.ts +24 -0
- package/lib/toolbar/toolbar.component.d.ts +55 -84
- package/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.d.ts +33 -40
- package/lib/toolbar/view-controls/view-controls.component.d.ts +54 -0
- package/lib/toolbar/wand/wand-region-grow.d.ts +49 -0
- package/lib/toolbar/wand/wand-tool.service.d.ts +39 -124
- package/lib/toolbar/wand/wand.service.d.ts +22 -116
- package/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.d.ts +17 -37
- package/lib/util/mark-for-check.d.ts +11 -0
- package/lib/util/supersede.d.ts +53 -0
- package/lib/visualization.module.d.ts +18 -39
- package/lib/visualizer/floating-drag.directive.d.ts +30 -0
- package/lib/visualizer/region-actions.d.ts +54 -0
- package/lib/visualizer/region-load.d.ts +46 -0
- package/lib/visualizer/spatial-dataset-binder.d.ts +74 -0
- package/lib/visualizer/tool-modes.d.ts +49 -0
- package/lib/visualizer/viewer-shortcuts.d.ts +71 -0
- package/lib/visualizer/visualizer-context-menu.d.ts +55 -0
- package/lib/visualizer/volume-sections.d.ts +64 -0
- package/lib/visualizer.component.d.ts +232 -447
- package/lib/workers/spatial-math-ops.d.ts +65 -0
- package/lib/workers/spatial-math-worker.d.ts +7 -0
- package/lib/workers/spatial-math.d.ts +74 -0
- package/package.json +12 -3
- package/src/lib/assets/slice.svg +23 -0
- package/src/lib/styles/_viz-icons-rules.scss +73 -0
- package/src/lib/styles/viz-icons.scss +14 -0
- package/esm2022/lib/implementations/napari-js/napari-axes-labels.mjs +0 -97
- package/esm2022/lib/implementations/napari-js/napari-navigator.mjs +0 -195
- package/esm2022/lib/implementations/napari-js/napari-scale-bar.mjs +0 -92
- package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-BwP-A11m.mjs +0 -329
- package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-BwP-A11m.mjs.map +0 -1
- package/lib/implementations/napari-js/napari-axes-labels.d.ts +0 -49
- package/lib/implementations/napari-js/napari-navigator.d.ts +0 -72
- package/lib/implementations/napari-js/napari-scale-bar.d.ts +0 -35
- package/src/lib/assets/cell-detection.svg +0 -37
- package/src/lib/assets/click.svg +0 -1
- package/src/lib/assets/colormap-luts.json +0 -1
- package/src/lib/assets/edit-selection-white.svg +0 -47
- package/src/lib/assets/icons/colormap-earth.png +0 -0
- package/src/lib/assets/icons/colormap-placeholder.png +0 -0
- package/src/lib/assets/icons/colormap-pubu.png +0 -0
- package/src/lib/assets/interactive-segmentation-cursor.svg +0 -1
- package/src/lib/assets/picture-segmentation.svg +0 -43
- package/src/lib/assets/test/download-379.svg +0 -1
- package/src/lib/assets/test/download-98.svg +0 -1
- package/src/lib/assets/test/json-1.svg +0 -1
- package/src/lib/assets/test/load-53.svg +0 -1
- package/src/lib/assets/test/mask-44.svg +0 -1
- package/src/lib/assets/test/mask-download-44.svg +0 -15
- package/src/lib/assets/test/mask-save-44.svg +0 -11
- package/src/lib/assets/test/overlay-1.svg +0 -1
- package/src/lib/assets/test/overlay-4.svg +0 -1
- package/src/lib/assets/test/region-26.svg +0 -1
- package/src/lib/assets/test/save-56.svg +0 -1
- package/src/lib/assets/test/upload-43.svg +0 -1
|
@@ -1,12 +1,74 @@
|
|
|
1
1
|
import { Injectable } from '@angular/core';
|
|
2
2
|
import { BehaviorSubject, Subject } from 'rxjs';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { Rectangle, Polygon, hydrateBounds } from '../models/region';
|
|
4
|
+
import { downloadGeoJson, featureFromRegion, regionFromGeoJsonFeature, regionsFromGeoJson, regionsToGeoJson, } from '../models/region-geojson';
|
|
5
5
|
import { VisualizerStore } from './visualizer-store.service';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import { applyPresetColors, colorForLabel, presetKey } from './class-color.util';
|
|
7
|
+
import { cloneBounds, makePolygon, rectToRing, regionPolygons, regionPolylines, replaceBounds, } from '../models/polygon-factory';
|
|
8
|
+
import { outlinesArea } from '../geometry/reconstruct';
|
|
9
|
+
import { reconstructInWorker } from '../region-source/worker-region-source';
|
|
10
|
+
import * as edit from '../models/polygon-edit';
|
|
11
|
+
import { regionsEqual, withRegionPatch, withRegionZ } from '../models/region-clone';
|
|
12
|
+
import { RegionHistory } from './region-history';
|
|
13
|
+
import { RegionSelection } from './region-selection';
|
|
14
|
+
import { RegionScopeCache } from './region-scope-cache';
|
|
15
|
+
import { RegionSourceScope } from './region-source-scope';
|
|
16
|
+
import { DEFAULT_REGION_STYLE } from '../region-overlay/region-style';
|
|
8
17
|
import * as i0 from "@angular/core";
|
|
9
18
|
import * as i1 from "./visualizer-store.service";
|
|
19
|
+
/** Selecting classes takes at most this many region-source features into the regions. */
|
|
20
|
+
export const SELECT_CLASSES_LIMIT = 5000;
|
|
21
|
+
/** Class sets whose region-source outlines are kept for rebuilding their surfaces. */
|
|
22
|
+
const SOURCE_OUTLINE_CACHE_SIZE = 8;
|
|
23
|
+
/** Classes whose region-source part of the volume is kept (see RegionStore.classVolumes). */
|
|
24
|
+
const SOURCE_VOLUME_CACHE_SIZE = 64;
|
|
25
|
+
/**
|
|
26
|
+
* Feature ids unique across outlines read from several places: each call gives one part's
|
|
27
|
+
* renumbering of its own ids (a part without them is one feature).
|
|
28
|
+
*/
|
|
29
|
+
function featureIds() {
|
|
30
|
+
let next = 0;
|
|
31
|
+
return () => {
|
|
32
|
+
const ids = new Map();
|
|
33
|
+
return (own) => {
|
|
34
|
+
let id = ids.get(own);
|
|
35
|
+
if (id === undefined)
|
|
36
|
+
ids.set(own, (id = next++));
|
|
37
|
+
return id;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/** A slice's parts as outlines. */
|
|
42
|
+
function sliceOutlines(z, s) {
|
|
43
|
+
return {
|
|
44
|
+
z,
|
|
45
|
+
rings: s.rings,
|
|
46
|
+
...(s.rings.length ? { ringGroups: s.ringGroups } : {}),
|
|
47
|
+
...(s.lines.length ? { lines: s.lines } : {}),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Outlines by slice merged into one entry per slice (rings, then lines), in slice order, each
|
|
52
|
+
* part's features apart from the others' (they fill as their union).
|
|
53
|
+
*/
|
|
54
|
+
function mergeOutlines(parts) {
|
|
55
|
+
const byZ = new Map();
|
|
56
|
+
const nextPart = featureIds();
|
|
57
|
+
for (const part of parts) {
|
|
58
|
+
if (!part.rings.length && !part.lines?.length)
|
|
59
|
+
continue;
|
|
60
|
+
let slice = byZ.get(part.z);
|
|
61
|
+
if (!slice)
|
|
62
|
+
byZ.set(part.z, (slice = { rings: [], ringGroups: [], lines: [] }));
|
|
63
|
+
const id = nextPart();
|
|
64
|
+
part.rings.forEach((r, i) => {
|
|
65
|
+
slice.rings.push(r);
|
|
66
|
+
slice.ringGroups.push(id(part.ringGroups?.[i]));
|
|
67
|
+
});
|
|
68
|
+
slice.lines.push(...(part.lines ?? []));
|
|
69
|
+
}
|
|
70
|
+
return Array.from(byZ, ([z, s]) => sliceOutlines(z, s)).sort((a, b) => a.z - b.z);
|
|
71
|
+
}
|
|
10
72
|
/**
|
|
11
73
|
* Backend-neutral region store — the single source of truth for region state.
|
|
12
74
|
*
|
|
@@ -23,45 +85,34 @@ import * as i1 from "./visualizer-store.service";
|
|
|
23
85
|
* - {@link IRegionEditApi} — Region-native geometry edits (move/resize, and
|
|
24
86
|
* add/delete/move vertex) the OSD overlay drives.
|
|
25
87
|
*
|
|
88
|
+
* Copy-on-write (review RT-13): no operation changes a stored {@link Region}
|
|
89
|
+
* (or the regions array) in place. An edit builds a replacement — the geometry
|
|
90
|
+
* through the pure `models/polygon-edit` functions — and swaps it in, so the
|
|
91
|
+
* undo history ({@link RegionHistory}) can keep shallow snapshots that share
|
|
92
|
+
* every untouched region instead of deep-cloning the whole set per step.
|
|
93
|
+
* Callers must follow the same rule with the instances {@link getRegions}
|
|
94
|
+
* returns: treat them as read-only, and commit a changed copy.
|
|
95
|
+
*
|
|
26
96
|
* Classification colours live in {@link VisualizerStore} (shared by both
|
|
27
|
-
* backends); GeoJSON import/export
|
|
28
|
-
*
|
|
97
|
+
* backends); GeoJSON import/export is `models/region-geojson`. All coordinates
|
|
98
|
+
* are image pixels.
|
|
29
99
|
*/
|
|
30
100
|
export class RegionStore {
|
|
31
101
|
static { this.UNDO_LIMIT = 10; }
|
|
32
102
|
static { this.UNDO_COALESCE_MS = 250; }
|
|
33
103
|
constructor(store) {
|
|
34
104
|
this.store = store;
|
|
35
|
-
/** Per-image region cache. `regions` is always a snapshot of the entry for
|
|
36
|
-
* `currentImageKey`. */
|
|
37
|
-
this.regionsByImageKey = new Map();
|
|
38
105
|
/** The current image's regions — the live, edited array. */
|
|
39
106
|
this.regions = [];
|
|
40
|
-
/** Last saved snapshot, restorable via plotPreviousShapes(). */
|
|
41
|
-
this.previousRegions = [];
|
|
42
107
|
/**
|
|
43
108
|
* Undo/redo history (jit-ui#85): up to {@link UNDO_LIMIT} snapshots of the
|
|
44
|
-
* region set, each
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* A continuous gesture (a wand/brush/vertex drag commits to the store many
|
|
51
|
-
* times) is coalesced into a single entry: the first commit of a burst
|
|
52
|
-
* captures the pre-burst state and every commit within
|
|
53
|
-
* {@link UNDO_COALESCE_MS} of the previous one is folded into it. History
|
|
54
|
-
* never crosses an image load/switch — {@link resetUndoHistory} clears it.
|
|
109
|
+
* region set, each taken just *before* a region-editing action; continuous
|
|
110
|
+
* gestures and rapid commits coalesce (see {@link RegionHistory}). Snapshots
|
|
111
|
+
* are shallow — the regions array as it was — which is safe because nothing
|
|
112
|
+
* here mutates a region or an array in place (RT-13). History never crosses an
|
|
113
|
+
* image load/switch — {@link resetUndoHistory} clears it.
|
|
55
114
|
*/
|
|
56
|
-
this.
|
|
57
|
-
this.redoStack = [];
|
|
58
|
-
/** True while a coalescing burst is open (further commits fold into it). */
|
|
59
|
-
this.undoBurstOpen = false;
|
|
60
|
-
this.undoBurstTimer = null;
|
|
61
|
-
/** True while restoring a snapshot, so the restore records no new history. */
|
|
62
|
-
this.restoringUndo = false;
|
|
63
|
-
this.canUndo$ = new BehaviorSubject(false);
|
|
64
|
-
this.canRedo$ = new BehaviorSubject(false);
|
|
115
|
+
this.history = new RegionHistory(RegionStore.UNDO_LIMIT, RegionStore.UNDO_COALESCE_MS);
|
|
65
116
|
/** Monotonic id source — ids never repeat within the service lifetime, so
|
|
66
117
|
* selection stays correct across delete/add cycles even when names collide. */
|
|
67
118
|
this.nextId = 1;
|
|
@@ -70,39 +121,61 @@ export class RegionStore {
|
|
|
70
121
|
this.fillColor = '#ff00ff';
|
|
71
122
|
this.isRegionSavedOn = true;
|
|
72
123
|
/**
|
|
73
|
-
* Per-
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
* zero-based {@link Region.z}) for save/export. Off by default (stackMode
|
|
81
|
-
* false, z 0), so single-plane images are completely unaffected.
|
|
124
|
+
* Per-image cache and, for z-stacks, per-slice regions (jit-ui#93). In stack
|
|
125
|
+
* mode the live `regions` array holds ONE slice — the display slice — so the
|
|
126
|
+
* overlays, the selection projection and the Regions table work unchanged
|
|
127
|
+
* (they all read {@link getRegions}); {@link setDisplaySlice} swaps the live
|
|
128
|
+
* set on scrub and {@link getSliceRegions} flattens every slice (each tagged
|
|
129
|
+
* with its zero-based {@link Region.z}) for save/export. Off by default, so
|
|
130
|
+
* single-plane images are unaffected.
|
|
82
131
|
*/
|
|
83
|
-
this.
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
* z-indexed geojson (single-file z-stack, QuPath schema); `per-slice-file`
|
|
88
|
-
* writes one geojson per slice-file (a folder of numbered images). */
|
|
89
|
-
this.stackSaveLayout = 'combined';
|
|
90
|
-
/** Slices that were loaded with regions (jit-ui#93). A per-slice-file save
|
|
91
|
-
* re-writes these even when now empty, so clearing a slice's regions and
|
|
92
|
-
* saving removes its previously-saved geojson (writes an empty one). */
|
|
93
|
-
this.stackInitialNonEmpty = new Set();
|
|
94
|
-
/** Selection is tracked by region *id* internally (stable across edits) and
|
|
95
|
-
* projected to array indices on the IRegionStore boundary. */
|
|
96
|
-
this.selectedIds = [];
|
|
97
|
-
this.selectedIndices$ = new BehaviorSubject([]);
|
|
132
|
+
this.scope = new RegionScopeCache();
|
|
133
|
+
/** Selection by region *id* (stable across edits), projected to array
|
|
134
|
+
* indices on the IRegionStore boundary. */
|
|
135
|
+
this.selection = new RegionSelection();
|
|
98
136
|
this.regionUpdate$ = new Subject();
|
|
99
137
|
/** Non-coalesced sibling of regionUpdate$: fires on every change even during a
|
|
100
138
|
* batched drag, so live consumers (intensity inset) update per frame. */
|
|
101
139
|
this.regionLiveEdit$ = new Subject();
|
|
140
|
+
/** See {@link getRegionSetReplaced$}. */
|
|
141
|
+
this.regionSetReplaced$ = new Subject();
|
|
102
142
|
/** Emit coalescing for live drags (see IRegionEditApi.beginBatch). */
|
|
103
143
|
this.batchDepth = 0;
|
|
104
144
|
this.pendingEmit = false;
|
|
105
|
-
|
|
145
|
+
/**
|
|
146
|
+
* Large region sets held as tiled region sources rather than as regions (see
|
|
147
|
+
* {@link attachRegionSource}): per image and slice, with the ids taken out of each.
|
|
148
|
+
*/
|
|
149
|
+
this.sources = new RegionSourceScope();
|
|
150
|
+
this.sourceView$ = new BehaviorSubject(null);
|
|
151
|
+
/** The region look the user chose (overrides the source's hint), field by field. */
|
|
152
|
+
this.userStyle = {};
|
|
153
|
+
this.regionStyle$ = new BehaviorSubject(DEFAULT_REGION_STYLE);
|
|
154
|
+
/** Bumped on every change of the slice's source, so a late open is dropped. */
|
|
155
|
+
this.sourceGeneration = 0;
|
|
156
|
+
/** The source last published as the view: a source shown again does not turn the labels back on. */
|
|
157
|
+
this.shownSource = null;
|
|
158
|
+
/** Bumped when a region source is attached or dropped: what is read from the sources is stale. */
|
|
159
|
+
this.sourcesVersion = 0;
|
|
160
|
+
/**
|
|
161
|
+
* The region sources' part of {@link classVolumes}, by class and what the sources hold (see
|
|
162
|
+
* {@link sourceStateKey}): an edit of the regions leaves it, so the volumes of a slice being drawn
|
|
163
|
+
* on cost no source reads.
|
|
164
|
+
*/
|
|
165
|
+
this.sourceVolumeCache = new Map();
|
|
166
|
+
/** The region sources' outlines of the class sets reconstructed last (see {@link sourceOutlines}). */
|
|
167
|
+
this.sourceOutlineCache = new Map();
|
|
168
|
+
/** The classes hidden from view (names as given); every class is shown at first. */
|
|
169
|
+
this.hiddenClasses$ = new BehaviorSubject(new Set());
|
|
170
|
+
/** {@link hiddenClasses$} by {@link presetKey}, as a region's label is matched. */
|
|
171
|
+
this.hiddenKeys = new Set();
|
|
172
|
+
this.coveredFor = null;
|
|
173
|
+
// A class colour change recolours the source's features as it recolours regions.
|
|
174
|
+
this.store.getPresetSet$().subscribe(() => {
|
|
175
|
+
const view = this.sourceView$.value;
|
|
176
|
+
if (view)
|
|
177
|
+
this.sourceView$.next({ ...view });
|
|
178
|
+
});
|
|
106
179
|
}
|
|
107
180
|
// ── IRegionStore: CRUD ─────────────────────────────────────────────────
|
|
108
181
|
/**
|
|
@@ -118,26 +191,19 @@ export class RegionStore {
|
|
|
118
191
|
isRegionSaveOn = this.isRegionSavedOn;
|
|
119
192
|
if (fillColor === undefined)
|
|
120
193
|
fillColor = this.fillColor;
|
|
121
|
-
|
|
122
|
-
if (region.id == null)
|
|
123
|
-
region.id = this.nextId++;
|
|
124
|
-
if (region.name == null)
|
|
125
|
-
region.name = `shape${region.id}`;
|
|
126
|
-
// JSON in, class instances out — everything downstream (the overlays'
|
|
127
|
-
// rendering, geometry de-dup, moveRegion, GeoJSON export) discriminates
|
|
128
|
-
// the bounds with `instanceof` (jit-ui#124).
|
|
129
|
-
region.bounds = hydrateBounds(region.bounds);
|
|
130
|
-
}
|
|
131
|
-
this.applyClassificationColors(regions);
|
|
194
|
+
regions = this.admit(regions);
|
|
132
195
|
this.isRegionSavedOn = isRegionSaveOn;
|
|
133
196
|
if (isRegionSaveOn) {
|
|
134
197
|
this.recordUndoSnapshot();
|
|
135
|
-
this.showShapeLabel
|
|
198
|
+
if (this.showShapeLabel !== showRegionLabel) {
|
|
199
|
+
this.showShapeLabel = showRegionLabel;
|
|
200
|
+
this.republishView();
|
|
201
|
+
}
|
|
136
202
|
this.fillColor = fillColor;
|
|
137
203
|
if (append) {
|
|
138
204
|
// Reject by id collision (already tracked) or geometry equality (same
|
|
139
205
|
// coordinates) — the find button can push the same region repeatedly.
|
|
140
|
-
const added = regions.filter(r => !this.regions.some(existing => existing.id === r.id ||
|
|
206
|
+
const added = regions.filter((r) => !this.regions.some((existing) => existing.id === r.id || regionsEqual(existing, r)));
|
|
141
207
|
this.regions = this.regions.concat(added);
|
|
142
208
|
}
|
|
143
209
|
else {
|
|
@@ -152,19 +218,32 @@ export class RegionStore {
|
|
|
152
218
|
this.regionUpdate$.next(regions.slice());
|
|
153
219
|
}
|
|
154
220
|
}
|
|
155
|
-
/**
|
|
221
|
+
/**
|
|
222
|
+
* The canonical accessor: the current image's regions. A fresh array, but the
|
|
223
|
+
* instances are the stored ones, shared with the undo history: treat them as
|
|
224
|
+
* read-only and change a region through the store's operations (or by
|
|
225
|
+
* committing a copy). Typed `Region[]` rather than
|
|
226
|
+
* `ReadonlyArray<Readonly<Region>>` because the IRegionStore contract and the
|
|
227
|
+
* backends still take a mutable array.
|
|
228
|
+
*/
|
|
156
229
|
getRegions() {
|
|
157
230
|
return this.regions.slice();
|
|
158
231
|
}
|
|
159
232
|
// ── Per-slice regions for z-stacks (jit-ui#93) ─────────────────────────
|
|
160
233
|
/** True while a z-stack is loaded and the store holds regions per slice. */
|
|
161
|
-
isStackMode() {
|
|
234
|
+
isStackMode() {
|
|
235
|
+
return this.scope.stackMode;
|
|
236
|
+
}
|
|
162
237
|
/** The current display slice (zero-based). */
|
|
163
|
-
getDisplaySlice() {
|
|
238
|
+
getDisplaySlice() {
|
|
239
|
+
return this.scope.displaySlice;
|
|
240
|
+
}
|
|
164
241
|
/** How the current stack persists to disk (jit-ui#93): `combined` = one
|
|
165
242
|
* z-indexed geojson (single-file z-stack); `per-slice-file` = one geojson per
|
|
166
243
|
* slice-file (folder stack). Meaningless outside stack mode. */
|
|
167
|
-
getStackSaveLayout() {
|
|
244
|
+
getStackSaveLayout() {
|
|
245
|
+
return this.scope.saveLayout;
|
|
246
|
+
}
|
|
168
247
|
/**
|
|
169
248
|
* Enter per-slice stack mode. `slices` maps each zero-based slice index to
|
|
170
249
|
* the regions imported for that slice; the store makes `initialZ`'s slice the
|
|
@@ -175,33 +254,34 @@ export class RegionStore {
|
|
|
175
254
|
* exactly as {@link setRegions} does.
|
|
176
255
|
*/
|
|
177
256
|
enterStackMode(slices, initialZ = 0, saveLayout = 'combined') {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
this.
|
|
182
|
-
this.
|
|
183
|
-
for (const [z, regs] of slices) {
|
|
184
|
-
const normalized = this.normalizeSlice(regs || [], z);
|
|
185
|
-
this.regionsBySlice.set(z, normalized);
|
|
186
|
-
if (normalized.length)
|
|
187
|
-
this.stackInitialNonEmpty.add(z);
|
|
188
|
-
}
|
|
189
|
-
this.regions = (this.regionsBySlice.get(this.currentSliceZ) ?? []).slice();
|
|
190
|
-
this.previousRegions = this.regions.slice();
|
|
191
|
-
this.selectedIds = [];
|
|
257
|
+
const admitted = new Map();
|
|
258
|
+
for (const [z, regs] of slices)
|
|
259
|
+
admitted.set(z, this.normalizeSlice(regs || [], z));
|
|
260
|
+
this.regions = this.scope.enterStack(admitted, initialZ, saveLayout);
|
|
261
|
+
this.selection.replace([]);
|
|
192
262
|
this.syncCache();
|
|
193
263
|
this.resetUndoHistory();
|
|
194
264
|
this.emitSelection();
|
|
195
265
|
this.emit();
|
|
266
|
+
this.refreshSourceView();
|
|
196
267
|
}
|
|
197
268
|
/** Leave stack mode (single-plane image, or the stack was closed). */
|
|
198
269
|
exitStackMode() {
|
|
199
|
-
|
|
270
|
+
this.scope.exitStack();
|
|
271
|
+
this.refreshSourceView();
|
|
272
|
+
}
|
|
273
|
+
/** The live-set swap of {@link setDisplaySlice}. */
|
|
274
|
+
showSlice(z) {
|
|
275
|
+
const next = this.scope.showSlice(z, this.regions);
|
|
276
|
+
if (!next)
|
|
200
277
|
return;
|
|
201
|
-
this.
|
|
202
|
-
this.
|
|
203
|
-
this.
|
|
204
|
-
this.
|
|
278
|
+
this.regions = next;
|
|
279
|
+
this.selection.replace([]);
|
|
280
|
+
this.syncCache();
|
|
281
|
+
this.resetUndoHistory();
|
|
282
|
+
this.emitSelection();
|
|
283
|
+
this.emit();
|
|
284
|
+
this.refreshSourceView();
|
|
205
285
|
}
|
|
206
286
|
/**
|
|
207
287
|
* Show a different slice: capture the current slice's (possibly edited)
|
|
@@ -210,24 +290,12 @@ export class RegionStore {
|
|
|
210
290
|
* this only records the requested slice index (a no-op otherwise: single-plane
|
|
211
291
|
* regions stay on the default plane — addRegion tags Region.z only in stack
|
|
212
292
|
* mode, so the recorded index is unused until a stack is entered). (jit-ui#93)
|
|
293
|
+
* Either way {@link getRegionSetReplaced$} emits: the slice on screen changed
|
|
294
|
+
* under any in-progress tool work.
|
|
213
295
|
*/
|
|
214
296
|
setDisplaySlice(z) {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
this.currentSliceZ = next;
|
|
218
|
-
return;
|
|
219
|
-
}
|
|
220
|
-
if (this.currentSliceZ === next)
|
|
221
|
-
return;
|
|
222
|
-
this.regionsBySlice.set(this.currentSliceZ, this.regions.slice());
|
|
223
|
-
this.currentSliceZ = next;
|
|
224
|
-
this.regions = (this.regionsBySlice.get(next) ?? []).slice();
|
|
225
|
-
this.previousRegions = this.regions.slice();
|
|
226
|
-
this.selectedIds = [];
|
|
227
|
-
this.syncCache();
|
|
228
|
-
this.resetUndoHistory();
|
|
229
|
-
this.emitSelection();
|
|
230
|
-
this.emit();
|
|
297
|
+
this.showSlice(z);
|
|
298
|
+
this.regionSetReplaced$.next();
|
|
231
299
|
}
|
|
232
300
|
/**
|
|
233
301
|
* Every slice's regions for save/export, each tagged with its zero-based
|
|
@@ -235,18 +303,7 @@ export class RegionStore {
|
|
|
235
303
|
* first. Returns the flat single-plane set when not in stack mode. (jit-ui#93)
|
|
236
304
|
*/
|
|
237
305
|
getSliceRegions() {
|
|
238
|
-
|
|
239
|
-
return this.regions.slice();
|
|
240
|
-
this.regionsBySlice.set(this.currentSliceZ, this.regions.slice());
|
|
241
|
-
const out = [];
|
|
242
|
-
const zs = Array.from(this.regionsBySlice.keys()).sort((a, b) => a - b);
|
|
243
|
-
for (const z of zs) {
|
|
244
|
-
for (const r of this.regionsBySlice.get(z)) {
|
|
245
|
-
r.z = z;
|
|
246
|
-
out.push(r);
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
return out;
|
|
306
|
+
return this.scope.sliceRegions(this.regions);
|
|
250
307
|
}
|
|
251
308
|
/**
|
|
252
309
|
* Slices to write on a per-slice-file save (folder stack, jit-ui#93): every
|
|
@@ -256,48 +313,57 @@ export class RegionStore {
|
|
|
256
313
|
* the current live slice is captured first. Empty outside stack mode.
|
|
257
314
|
*/
|
|
258
315
|
getStackSaveSlices() {
|
|
259
|
-
const
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
for (const
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
for (const z of Array.from(zs).sort((a, b) => a - b)) {
|
|
268
|
-
const regs = (this.regionsBySlice.get(z) ?? []).map((r) => { r.z = z; return r; });
|
|
269
|
-
out.set(z, regs);
|
|
270
|
-
}
|
|
271
|
-
return out;
|
|
316
|
+
const slices = this.scope.stackSaveSlices(this.regions);
|
|
317
|
+
// A slice whose region source lost features (taken, deleted) is re-written too.
|
|
318
|
+
const changed = this.sources.slicesWithTaken(this.scope.activeImage).filter((z) => !slices.has(z));
|
|
319
|
+
if (!changed.length)
|
|
320
|
+
return slices;
|
|
321
|
+
for (const z of changed)
|
|
322
|
+
slices.set(z, []);
|
|
323
|
+
return new Map(Array.from(slices).sort((a, b) => a[0] - b[0]));
|
|
272
324
|
}
|
|
273
325
|
/** Mint ids/names + apply classification colours + tag the slice index, as
|
|
274
326
|
* {@link setRegions} does, for regions entering the per-slice store. */
|
|
275
327
|
normalizeSlice(regions, z) {
|
|
276
|
-
|
|
277
|
-
|
|
328
|
+
// A fresh (imported) region is tagged in place; a stored one is copied.
|
|
329
|
+
return this.admit(regions.map((r) => (r.id == null ? Object.assign(r, { z }) : withRegionZ(r, z))));
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Regions entering the store: mint ids and default names, hydrate JSON bounds
|
|
333
|
+
* into class instances — everything downstream (rendering, geometry de-dup,
|
|
334
|
+
* moveRegion, GeoJSON export) discriminates them with `instanceof`
|
|
335
|
+
* (jit-ui#124) — and apply classification colours. A region that is new to
|
|
336
|
+
* the store (no id yet) is completed in place; one that already has an id may
|
|
337
|
+
* be a stored instance shared with the undo history, so it is copied if it
|
|
338
|
+
* changes.
|
|
339
|
+
*/
|
|
340
|
+
admit(regions) {
|
|
341
|
+
const fresh = new Set();
|
|
342
|
+
const admitted = regions.map((region) => {
|
|
343
|
+
if (region.id == null) {
|
|
278
344
|
region.id = this.nextId++;
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
345
|
+
if (region.name == null)
|
|
346
|
+
region.name = `shape${region.id}`;
|
|
347
|
+
region.bounds = hydrateBounds(region.bounds);
|
|
348
|
+
fresh.add(region);
|
|
349
|
+
return region;
|
|
350
|
+
}
|
|
351
|
+
const bounds = hydrateBounds(region.bounds);
|
|
352
|
+
return region.name == null || bounds !== region.bounds
|
|
353
|
+
? withRegionPatch(region, { name: region.name ?? `shape${region.id}`, bounds })
|
|
354
|
+
: region;
|
|
355
|
+
});
|
|
356
|
+
return this.withClassificationColors(admitted, (r) => fresh.has(r));
|
|
286
357
|
}
|
|
287
358
|
/**
|
|
288
359
|
* Closed polygons projected for image-processing consumers (segmentation,
|
|
289
|
-
* trace builders)
|
|
290
|
-
*
|
|
360
|
+
* crop requests, trace builders), straight from each region's bounds: a
|
|
361
|
+
* rectangle's corners, a polygon with its holes (a bézier as its curve), one
|
|
362
|
+
* polygon per part of a multi-polygon. Open polylines are annotation-only and
|
|
363
|
+
* excluded. Coordinates are rounded to whole pixels.
|
|
291
364
|
*/
|
|
292
365
|
getRegionPolygons() {
|
|
293
|
-
|
|
294
|
-
for (const region of this.regions) {
|
|
295
|
-
const poly = this.plotUtilities.getPolygon({ ...region.getShape(this.showShapeLabel) });
|
|
296
|
-
if (poly == null || poly.closed === false)
|
|
297
|
-
continue;
|
|
298
|
-
ret.push(poly);
|
|
299
|
-
}
|
|
300
|
-
return ret;
|
|
366
|
+
return this.regions.flatMap((region) => regionPolygons(region));
|
|
301
367
|
}
|
|
302
368
|
getRegionUpdateEvent() {
|
|
303
369
|
return this.regionUpdate$.asObservable();
|
|
@@ -307,23 +373,21 @@ export class RegionStore {
|
|
|
307
373
|
getRegionLiveEdit$() {
|
|
308
374
|
return this.regionLiveEdit$.asObservable();
|
|
309
375
|
}
|
|
376
|
+
/**
|
|
377
|
+
* Emits after every {@link undo}, {@link redo} and {@link setDisplaySlice} call
|
|
378
|
+
* (even one that changed nothing): the region set was replaced under whatever
|
|
379
|
+
* a canvas tool was building on (a brush stroke, a SAM point prompt), so the
|
|
380
|
+
* backends reset their canvas tools on it. Not emitted for ordinary edits —
|
|
381
|
+
* a tool's own commit must not reset it.
|
|
382
|
+
*/
|
|
383
|
+
getRegionSetReplaced$() {
|
|
384
|
+
return this.regionSetReplaced$.asObservable();
|
|
385
|
+
}
|
|
310
386
|
// ── IRegionStore: selection ────────────────────────────────────────────
|
|
311
387
|
/** Select regions by array index (or [] to clear). Stored internally by id
|
|
312
388
|
* so the selection survives subsequent edits/reorders. */
|
|
313
389
|
setSelectedShapeIndices(indices) {
|
|
314
|
-
|
|
315
|
-
const seen = new Set();
|
|
316
|
-
for (const i of indices || []) {
|
|
317
|
-
if (!Number.isFinite(i) || i < 0 || i >= this.regions.length)
|
|
318
|
-
continue;
|
|
319
|
-
const id = this.regions[i].id;
|
|
320
|
-
if (!seen.has(id)) {
|
|
321
|
-
seen.add(id);
|
|
322
|
-
ids.push(id);
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
this.selectedIds = ids;
|
|
326
|
-
this.emitSelection();
|
|
390
|
+
this.selection.selectIndices(indices, this.regions);
|
|
327
391
|
}
|
|
328
392
|
/** Select a single region by identity (id). Backends call this from their
|
|
329
393
|
* `selectRegion()`; the OSD overlay + region editor highlight off the
|
|
@@ -331,66 +395,71 @@ export class RegionStore {
|
|
|
331
395
|
selectRegion(region) {
|
|
332
396
|
if (region?.id == null || this.indexOfId(region.id) < 0)
|
|
333
397
|
return;
|
|
334
|
-
this.
|
|
398
|
+
this.selection.replace([region.id]);
|
|
335
399
|
this.emitSelection();
|
|
336
400
|
}
|
|
337
401
|
getSelectedShapeIndices$() {
|
|
338
|
-
return this.
|
|
402
|
+
return this.selection.indices$;
|
|
339
403
|
}
|
|
340
404
|
/** Synchronous current selection (array indices) — for callers that need to
|
|
341
405
|
* read the selection without subscribing. */
|
|
342
406
|
getSelectedShapeIndices() {
|
|
343
|
-
return this.
|
|
407
|
+
return this.selection.indices;
|
|
344
408
|
}
|
|
345
409
|
/** Delete the currently selected regions and clear the selection. */
|
|
346
410
|
deleteActiveShape() {
|
|
347
|
-
if (this.
|
|
411
|
+
if (this.selection.ids.length === 0)
|
|
348
412
|
return;
|
|
349
413
|
this.recordUndoSnapshot();
|
|
350
|
-
const ids = new Set(this.
|
|
351
|
-
this.regions = this.regions.filter(r => !ids.has(r.id));
|
|
352
|
-
this.
|
|
414
|
+
const ids = new Set(this.selection.ids);
|
|
415
|
+
this.regions = this.regions.filter((r) => !ids.has(r.id));
|
|
416
|
+
this.selection.replace([]);
|
|
353
417
|
this.syncCache();
|
|
354
418
|
this.emitSelection();
|
|
355
419
|
this.emit();
|
|
356
420
|
}
|
|
357
421
|
// ── IRegionStore: colours / labels ─────────────────────────────────────
|
|
358
|
-
getShowShapeLabel() {
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
this.
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
422
|
+
getShowShapeLabel() {
|
|
423
|
+
return this.showShapeLabel;
|
|
424
|
+
}
|
|
425
|
+
getShapeColor() {
|
|
426
|
+
return this.shapeColor;
|
|
427
|
+
}
|
|
428
|
+
getFillColor() {
|
|
429
|
+
return this.fillColor;
|
|
430
|
+
}
|
|
431
|
+
/** Show or hide region labels (not on the contract; specs drive it directly).
|
|
432
|
+
* @deprecated Nothing in the library calls it; will be removed next minor. */
|
|
433
|
+
setShowShapeLabel(show) {
|
|
434
|
+
this.showShapeLabel = show;
|
|
435
|
+
this.republishView();
|
|
436
|
+
}
|
|
437
|
+
getClassificationColors() {
|
|
438
|
+
return this.store.getClassificationColors();
|
|
439
|
+
}
|
|
440
|
+
setClassificationColor(label, color) {
|
|
441
|
+
this.store.setClassificationColor(label, color);
|
|
442
|
+
}
|
|
374
443
|
// ── IRegionStore: undo / redo (jit-ui#85) ──────────────────────────────
|
|
375
444
|
/** Emits whether an undo step is currently available — drives the toolbar
|
|
376
445
|
* Undo button's enabled state (greyed out when false). */
|
|
377
446
|
getCanUndo$() {
|
|
378
|
-
return this.canUndo
|
|
447
|
+
return this.history.canUndo$;
|
|
379
448
|
}
|
|
380
449
|
/** Emits whether a redo step is currently available — drives the toolbar
|
|
381
450
|
* Redo button's enabled state. */
|
|
382
451
|
getCanRedo$() {
|
|
383
|
-
return this.canRedo
|
|
452
|
+
return this.history.canRedo$;
|
|
384
453
|
}
|
|
385
454
|
/** Synchronous read of {@link getCanUndo$} — true when at least one region
|
|
386
455
|
* action can be undone. */
|
|
387
456
|
canUndo() {
|
|
388
|
-
return this.
|
|
457
|
+
return this.history.canUndo();
|
|
389
458
|
}
|
|
390
459
|
/** Synchronous read of {@link getCanRedo$} — true when an undone action can
|
|
391
460
|
* be re-applied. */
|
|
392
461
|
canRedo() {
|
|
393
|
-
return this.
|
|
462
|
+
return this.history.canRedo();
|
|
394
463
|
}
|
|
395
464
|
/**
|
|
396
465
|
* Undo the most recent region action, restoring the region set to its state
|
|
@@ -400,14 +469,10 @@ export class RegionStore {
|
|
|
400
469
|
* nothing is left to undo.
|
|
401
470
|
*/
|
|
402
471
|
undo() {
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
this.redoStack.push(this.cloneRegions(this.regions));
|
|
408
|
-
if (this.redoStack.length > RegionStore.UNDO_LIMIT)
|
|
409
|
-
this.redoStack.shift();
|
|
410
|
-
this.restoreSnapshot(snapshot);
|
|
472
|
+
const snapshot = this.history.undo(this.snapshot());
|
|
473
|
+
if (snapshot)
|
|
474
|
+
this.restoreSnapshot(snapshot);
|
|
475
|
+
this.regionSetReplaced$.next();
|
|
411
476
|
}
|
|
412
477
|
/**
|
|
413
478
|
* Redo the action most recently undone, restoring the region set to the state
|
|
@@ -416,40 +481,26 @@ export class RegionStore {
|
|
|
416
481
|
* fresh region action).
|
|
417
482
|
*/
|
|
418
483
|
redo() {
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
this.
|
|
423
|
-
if (this.undoStack.length > RegionStore.UNDO_LIMIT)
|
|
424
|
-
this.undoStack.shift();
|
|
425
|
-
this.restoreSnapshot(snapshot);
|
|
484
|
+
const snapshot = this.history.redo(this.snapshot());
|
|
485
|
+
if (snapshot)
|
|
486
|
+
this.restoreSnapshot(snapshot);
|
|
487
|
+
this.regionSetReplaced$.next();
|
|
426
488
|
}
|
|
427
489
|
/** Discard the undo/redo history (e.g. on image load/switch — history never
|
|
428
490
|
* crosses images). */
|
|
429
491
|
resetUndoHistory() {
|
|
430
|
-
this.
|
|
431
|
-
this.redoStack = [];
|
|
432
|
-
this.closeUndoBurst();
|
|
433
|
-
if (this.canUndo$.value)
|
|
434
|
-
this.canUndo$.next(false);
|
|
435
|
-
if (this.canRedo$.value)
|
|
436
|
-
this.canRedo$.next(false);
|
|
492
|
+
this.history.reset();
|
|
437
493
|
}
|
|
438
494
|
/** Make `snapshot` the live region set and notify both backends. Shared by
|
|
439
|
-
* {@link undo} and {@link redo};
|
|
440
|
-
* clone, so it becomes the live array directly. */
|
|
495
|
+
* {@link undo} and {@link redo}; nothing records history while it runs. */
|
|
441
496
|
restoreSnapshot(snapshot) {
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
this.syncCache();
|
|
450
|
-
this.emitSelection();
|
|
451
|
-
this.restoringUndo = false;
|
|
452
|
-
this.emitUndoState();
|
|
497
|
+
this.history.restore(() => {
|
|
498
|
+
this.regions = snapshot.regions.slice();
|
|
499
|
+
this.setTaken(snapshot.taken);
|
|
500
|
+
this.syncCache();
|
|
501
|
+
// Drops any selected ids the restored set no longer contains.
|
|
502
|
+
this.emitSelection();
|
|
503
|
+
});
|
|
453
504
|
// Notify the live + coalesced streams so whichever backend is on screen
|
|
454
505
|
// re-renders from the restored store state.
|
|
455
506
|
this.regionLiveEdit$.next(this.regions.slice());
|
|
@@ -457,72 +508,38 @@ export class RegionStore {
|
|
|
457
508
|
}
|
|
458
509
|
/**
|
|
459
510
|
* Capture the pre-action region set into the bounded undo history. Called at
|
|
460
|
-
* the top of every mutating operation, *before* it changes `regions
|
|
461
|
-
* snapshot is the
|
|
462
|
-
*
|
|
463
|
-
* any redo future.
|
|
511
|
+
* the top of every mutating operation, *before* it changes `regions`. The
|
|
512
|
+
* snapshot is the array itself: every operation replaces `regions` (and any
|
|
513
|
+
* region it edits) rather than changing them, so it never changes after this.
|
|
464
514
|
*/
|
|
465
515
|
recordUndoSnapshot() {
|
|
466
|
-
|
|
467
|
-
return;
|
|
468
|
-
const startsBurst = !this.undoBurstOpen;
|
|
469
|
-
this.armUndoBurst();
|
|
470
|
-
if (!startsBurst)
|
|
471
|
-
return; // mid-burst — keep first snapshot
|
|
472
|
-
this.undoStack.push(this.cloneRegions(this.regions));
|
|
473
|
-
if (this.undoStack.length > RegionStore.UNDO_LIMIT)
|
|
474
|
-
this.undoStack.shift();
|
|
475
|
-
this.redoStack = []; // a new edit invalidates redo
|
|
476
|
-
this.emitUndoState();
|
|
477
|
-
}
|
|
478
|
-
/** Push the current can-undo / can-redo availability to subscribers. */
|
|
479
|
-
emitUndoState() {
|
|
480
|
-
const canUndo = this.undoStack.length > 0;
|
|
481
|
-
const canRedo = this.redoStack.length > 0;
|
|
482
|
-
if (this.canUndo$.value !== canUndo)
|
|
483
|
-
this.canUndo$.next(canUndo);
|
|
484
|
-
if (this.canRedo$.value !== canRedo)
|
|
485
|
-
this.canRedo$.next(canRedo);
|
|
486
|
-
}
|
|
487
|
-
/** (Re)arm the idle timer that closes the current coalescing burst. */
|
|
488
|
-
armUndoBurst() {
|
|
489
|
-
this.undoBurstOpen = true;
|
|
490
|
-
if (this.undoBurstTimer)
|
|
491
|
-
clearTimeout(this.undoBurstTimer);
|
|
492
|
-
this.undoBurstTimer = setTimeout(() => {
|
|
493
|
-
this.undoBurstOpen = false;
|
|
494
|
-
this.undoBurstTimer = null;
|
|
495
|
-
}, RegionStore.UNDO_COALESCE_MS);
|
|
496
|
-
}
|
|
497
|
-
closeUndoBurst() {
|
|
498
|
-
this.undoBurstOpen = false;
|
|
499
|
-
if (this.undoBurstTimer) {
|
|
500
|
-
clearTimeout(this.undoBurstTimer);
|
|
501
|
-
this.undoBurstTimer = null;
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
cloneRegions(regions) {
|
|
505
|
-
return regions.map(r => this.cloneRegion(r));
|
|
516
|
+
this.history.record(this.snapshot());
|
|
506
517
|
}
|
|
507
|
-
/**
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
const c = new Region();
|
|
511
|
-
Object.assign(c, r);
|
|
512
|
-
c.bounds = r.bounds ? this.cloneBounds(r.bounds) : r.bounds;
|
|
513
|
-
if (Array.isArray(r.tileCoordinates))
|
|
514
|
-
c.tileCoordinates = r.tileCoordinates.slice();
|
|
515
|
-
return c;
|
|
518
|
+
/** The state an undo step restores. */
|
|
519
|
+
snapshot() {
|
|
520
|
+
return { regions: this.regions, taken: this.currentTaken() };
|
|
516
521
|
}
|
|
517
|
-
// ── IRegionStore: GeoJSON I/O (
|
|
522
|
+
// ── IRegionStore: GeoJSON I/O (models/region-geojson) ──────────────────
|
|
523
|
+
/** Parse GeoJSON into regions, remembering the class colours the file carries so they are
|
|
524
|
+
* kept for classes with no preset (see VisualizerStore.rememberImportedClassColors). */
|
|
518
525
|
importRegions(geoJsonStr) {
|
|
519
|
-
|
|
526
|
+
const regions = regionsFromGeoJson(geoJsonStr);
|
|
527
|
+
const colors = new Map();
|
|
528
|
+
for (const r of regions) {
|
|
529
|
+
if (r.label && r.color && !colors.has(r.label))
|
|
530
|
+
colors.set(r.label, r.color);
|
|
531
|
+
}
|
|
532
|
+
if (colors.size)
|
|
533
|
+
this.store.rememberImportedClassColors(colors);
|
|
534
|
+
return regions;
|
|
520
535
|
}
|
|
521
|
-
|
|
522
|
-
|
|
536
|
+
/** Download `regions` as GeoJSON, named after `fileName` (extension
|
|
537
|
+
* replaced by `.geojson`) or `rois.geojson` without one. */
|
|
538
|
+
exportRegions(regions, fileName) {
|
|
539
|
+
downloadGeoJson(regionsToGeoJson(regions), fileName);
|
|
523
540
|
}
|
|
524
541
|
getGeoJsonString(regions) {
|
|
525
|
-
return
|
|
542
|
+
return regionsToGeoJson(regions);
|
|
526
543
|
}
|
|
527
544
|
// ── IRegionEditApi: structural edits ───────────────────────────────────
|
|
528
545
|
addRegion(region) {
|
|
@@ -534,24 +551,34 @@ export class RegionStore {
|
|
|
534
551
|
region.bounds = hydrateBounds(region.bounds); // jit-ui#124
|
|
535
552
|
// A region drawn on a stack belongs to the slice currently displayed, so
|
|
536
553
|
// it saves/reloads on that slice (jit-ui#93). No-op for single-plane images
|
|
537
|
-
// (
|
|
538
|
-
if (this.stackMode)
|
|
539
|
-
region.z = this.
|
|
540
|
-
|
|
541
|
-
this.
|
|
542
|
-
this.
|
|
554
|
+
// (the display slice stays 0).
|
|
555
|
+
if (this.scope.stackMode)
|
|
556
|
+
region.z = this.scope.displaySlice;
|
|
557
|
+
// The caller's instance becomes the stored one (completed in place).
|
|
558
|
+
const [stored] = this.withClassificationColors([region], () => true);
|
|
559
|
+
this.regions = [...this.regions, stored];
|
|
560
|
+
this.selection.replace([stored.id]);
|
|
543
561
|
this.syncCache();
|
|
544
562
|
this.emitSelection();
|
|
545
563
|
this.emit();
|
|
546
|
-
return
|
|
564
|
+
return stored.id;
|
|
547
565
|
}
|
|
548
566
|
removeRegion(id) {
|
|
549
|
-
|
|
550
|
-
|
|
567
|
+
this.removeRegions([id]);
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* Remove the regions with these ids, if present. With `{ recordUndo: false }`
|
|
571
|
+
* no undo step is taken — for clearing transient shapes that were never the
|
|
572
|
+
* user's work (the 3D view's screen-space lassos on an orbit, NAPARI-SVC-11).
|
|
573
|
+
*/
|
|
574
|
+
removeRegions(ids, opts = {}) {
|
|
575
|
+
const drop = new Set(ids);
|
|
576
|
+
if (!this.regions.some((r) => drop.has(r.id)))
|
|
551
577
|
return;
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
this.
|
|
578
|
+
if (opts.recordUndo !== false)
|
|
579
|
+
this.recordUndoSnapshot();
|
|
580
|
+
this.regions = this.regions.filter((r) => !drop.has(r.id));
|
|
581
|
+
this.selection.retain((s) => !drop.has(s));
|
|
555
582
|
this.syncCache();
|
|
556
583
|
this.emitSelection();
|
|
557
584
|
this.emit();
|
|
@@ -561,469 +588,758 @@ export class RegionStore {
|
|
|
561
588
|
if (!r)
|
|
562
589
|
return;
|
|
563
590
|
this.recordUndoSnapshot();
|
|
564
|
-
|
|
565
|
-
this.
|
|
566
|
-
this.emit();
|
|
591
|
+
// A copy, so the caller can keep using (and changing) the bounds it passed.
|
|
592
|
+
this.replaceRegion(replaceBounds(r, cloneBounds(bounds)));
|
|
567
593
|
}
|
|
568
594
|
moveRegion(id, dx, dy) {
|
|
569
595
|
const r = this.findById(id);
|
|
570
596
|
if (!r || !r.bounds)
|
|
571
597
|
return;
|
|
572
598
|
this.recordUndoSnapshot();
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
b.x += dx;
|
|
576
|
-
b.y += dy;
|
|
577
|
-
}
|
|
578
|
-
else if (b instanceof Polygon) {
|
|
579
|
-
this.translatePolygon(b, dx, dy);
|
|
580
|
-
}
|
|
581
|
-
else if (b instanceof MultiPolygon) {
|
|
582
|
-
// Translate every part (and its holes) together (jit-ui#85).
|
|
583
|
-
for (const part of b.polygons)
|
|
584
|
-
this.translatePolygon(part, dx, dy);
|
|
585
|
-
}
|
|
586
|
-
this.syncCache();
|
|
587
|
-
this.emit();
|
|
588
|
-
}
|
|
589
|
-
/** Translate a polygon's vertices and any holes in place by (dx, dy). */
|
|
590
|
-
translatePolygon(p, dx, dy) {
|
|
591
|
-
p.xpoints = p.xpoints.map(x => x + dx);
|
|
592
|
-
p.ypoints = p.ypoints.map(y => y + dy);
|
|
593
|
-
p.coordinates = p.xpoints.map((x, i) => [x, p.ypoints[i]]);
|
|
594
|
-
if (p.holes)
|
|
595
|
-
p.holes = p.holes.map(ring => ring.map(([x, y]) => [x + dx, y + dy]));
|
|
599
|
+
// Every part (and its holes) moves together (jit-ui#85).
|
|
600
|
+
this.replaceRegion(replaceBounds(r, edit.translateBounds(r.bounds, dx, dy)));
|
|
596
601
|
}
|
|
597
602
|
// ── IRegionEditApi: vertex edits (polygons only) ───────────────────────
|
|
603
|
+
// Each one is a pure copy-on-write edit from models/polygon-edit; a null
|
|
604
|
+
// result (out of range, would degenerate) records nothing and emits nothing.
|
|
598
605
|
moveVertex(id, index, x, y) {
|
|
599
|
-
|
|
600
|
-
if (!poly || index < 0 || index >= poly.xpoints.length)
|
|
601
|
-
return;
|
|
602
|
-
this.recordUndoSnapshot();
|
|
603
|
-
poly.xpoints[index] = x;
|
|
604
|
-
poly.ypoints[index] = y;
|
|
605
|
-
poly.coordinates[index] = [x, y];
|
|
606
|
-
this.syncCache();
|
|
607
|
-
this.emit();
|
|
606
|
+
this.editPolygon(id, (p) => edit.moveVertex(p, index, x, y));
|
|
608
607
|
}
|
|
609
608
|
/** Move a vertex on a polygon's interior ring (hole) — jit-ui#85. */
|
|
610
609
|
moveHoleVertex(id, holeIndex, index, x, y) {
|
|
611
|
-
|
|
612
|
-
if (!poly || !poly.holes || holeIndex < 0 || holeIndex >= poly.holes.length)
|
|
613
|
-
return;
|
|
614
|
-
const ring = poly.holes[holeIndex];
|
|
615
|
-
if (index < 0 || index >= ring.length)
|
|
616
|
-
return;
|
|
617
|
-
this.recordUndoSnapshot();
|
|
618
|
-
ring[index] = [x, y];
|
|
619
|
-
this.syncCache();
|
|
620
|
-
this.emit();
|
|
610
|
+
this.editPolygon(id, (p) => edit.moveHoleVertex(p, holeIndex, index, x, y));
|
|
621
611
|
}
|
|
622
612
|
/** Insert a vertex on a polygon's interior ring (hole), after `segIndex`
|
|
623
613
|
* (the edge's start vertex). No-op for an out-of-range hole — jit-ui#85. */
|
|
624
614
|
addHoleVertex(id, holeIndex, segIndex, x, y) {
|
|
625
|
-
|
|
626
|
-
if (!poly || !poly.holes || holeIndex < 0 || holeIndex >= poly.holes.length)
|
|
627
|
-
return;
|
|
628
|
-
const ring = poly.holes[holeIndex];
|
|
629
|
-
this.recordUndoSnapshot();
|
|
630
|
-
const at = Math.max(0, Math.min(segIndex + 1, ring.length));
|
|
631
|
-
ring.splice(at, 0, [x, y]);
|
|
632
|
-
if (poly.bezier)
|
|
633
|
-
this.seedHoleHandles(poly); // keep hole handles aligned to the ring
|
|
634
|
-
this.syncCache();
|
|
635
|
-
this.emit();
|
|
615
|
+
this.editPolygon(id, (p) => edit.addHoleVertex(p, holeIndex, segIndex, x, y));
|
|
636
616
|
}
|
|
637
617
|
/** Delete the vertex at `index` on a polygon's interior ring (hole). Removing
|
|
638
618
|
* it below 3 vertices drops the whole hole (a ring with < 3 points bounds no
|
|
639
619
|
* area) — jit-ui#85. */
|
|
640
620
|
deleteHoleVertex(id, holeIndex, index) {
|
|
641
|
-
|
|
642
|
-
if (!poly || !poly.holes || holeIndex < 0 || holeIndex >= poly.holes.length)
|
|
643
|
-
return;
|
|
644
|
-
const ring = poly.holes[holeIndex];
|
|
645
|
-
if (index < 0 || index >= ring.length)
|
|
646
|
-
return;
|
|
647
|
-
this.recordUndoSnapshot();
|
|
648
|
-
if (ring.length <= 3) {
|
|
649
|
-
poly.holes.splice(holeIndex, 1);
|
|
650
|
-
if (poly.holes.length === 0)
|
|
651
|
-
poly.holes = undefined;
|
|
652
|
-
}
|
|
653
|
-
else {
|
|
654
|
-
ring.splice(index, 1);
|
|
655
|
-
}
|
|
656
|
-
if (poly.bezier)
|
|
657
|
-
this.seedHoleHandles(poly); // keep hole handles aligned to the ring(s)
|
|
658
|
-
this.syncCache();
|
|
659
|
-
this.emit();
|
|
621
|
+
this.editPolygon(id, (p) => edit.deleteHoleVertex(p, holeIndex, index));
|
|
660
622
|
}
|
|
661
623
|
addVertex(id, segIndex, x, y) {
|
|
662
|
-
|
|
663
|
-
if (!poly)
|
|
664
|
-
return;
|
|
665
|
-
this.recordUndoSnapshot();
|
|
666
|
-
// Insert after segIndex (the start vertex of the edge). Clamp to range.
|
|
667
|
-
const at = Math.max(0, Math.min(segIndex + 1, poly.xpoints.length));
|
|
668
|
-
poly.xpoints.splice(at, 0, x);
|
|
669
|
-
poly.ypoints.splice(at, 0, y);
|
|
670
|
-
poly.coordinates = poly.xpoints.map((xx, i) => [xx, poly.ypoints[i]]);
|
|
671
|
-
poly.npoints = poly.xpoints.length;
|
|
672
|
-
// Give the new vertex smooth handles from its neighbours; keep the others'
|
|
673
|
-
// (possibly hand-edited) handles intact.
|
|
674
|
-
if (poly.bezier && poly.handlesIn && poly.handlesOut) {
|
|
675
|
-
const n = poly.xpoints.length;
|
|
676
|
-
const closed = poly.closed !== false;
|
|
677
|
-
const prev = closed ? (at - 1 + n) % n : Math.max(0, at - 1);
|
|
678
|
-
const next = closed ? (at + 1) % n : Math.min(n - 1, at + 1);
|
|
679
|
-
const tx = (poly.xpoints[next] - poly.xpoints[prev]) / 6;
|
|
680
|
-
const ty = (poly.ypoints[next] - poly.ypoints[prev]) / 6;
|
|
681
|
-
poly.handlesIn.splice(at, 0, [-tx, -ty]);
|
|
682
|
-
poly.handlesOut.splice(at, 0, [tx, ty]);
|
|
683
|
-
}
|
|
684
|
-
this.syncCache();
|
|
685
|
-
this.emit();
|
|
624
|
+
this.editPolygon(id, (p) => edit.addVertex(p, segIndex, x, y));
|
|
686
625
|
}
|
|
687
626
|
deleteVertex(id, index) {
|
|
688
|
-
|
|
689
|
-
if (!poly || index < 0 || index >= poly.xpoints.length)
|
|
690
|
-
return;
|
|
691
|
-
const min = poly.closed === false ? 2 : 3;
|
|
692
|
-
if (poly.xpoints.length <= min)
|
|
693
|
-
return; // refuse to degenerate the polygon
|
|
694
|
-
this.recordUndoSnapshot();
|
|
695
|
-
poly.xpoints.splice(index, 1);
|
|
696
|
-
poly.ypoints.splice(index, 1);
|
|
697
|
-
poly.coordinates = poly.xpoints.map((xx, i) => [xx, poly.ypoints[i]]);
|
|
698
|
-
poly.npoints = poly.xpoints.length;
|
|
699
|
-
if (poly.bezier && poly.handlesIn && poly.handlesOut) {
|
|
700
|
-
poly.handlesIn.splice(index, 1);
|
|
701
|
-
poly.handlesOut.splice(index, 1);
|
|
702
|
-
}
|
|
703
|
-
this.syncCache();
|
|
704
|
-
this.emit();
|
|
627
|
+
this.editPolygon(id, (p) => edit.deleteVertex(p, index));
|
|
705
628
|
}
|
|
706
629
|
setBezier(id, bezier) {
|
|
707
630
|
const r = this.findById(id);
|
|
708
631
|
if (!r || !r.bounds)
|
|
709
632
|
return;
|
|
633
|
+
let next = null;
|
|
710
634
|
if (r.bounds instanceof Polygon) {
|
|
711
|
-
|
|
712
|
-
return;
|
|
713
|
-
this.recordUndoSnapshot();
|
|
714
|
-
this.applyBezier(r.bounds, bezier);
|
|
635
|
+
next = edit.setBezier(r.bounds, bezier);
|
|
715
636
|
}
|
|
716
637
|
else if (r.bounds instanceof Rectangle && bezier) {
|
|
717
|
-
this.recordUndoSnapshot();
|
|
718
638
|
// Smoothing a rectangle: convert it to a 4-anchor closed polygon first.
|
|
719
|
-
const
|
|
720
|
-
|
|
721
|
-
const ys = [b.y, b.y, b.y + b.height, b.y + b.height];
|
|
722
|
-
const poly = new Polygon();
|
|
723
|
-
poly.npoints = 4;
|
|
724
|
-
poly.xpoints = xs;
|
|
725
|
-
poly.ypoints = ys;
|
|
726
|
-
poly.coordinates = xs.map((x, i) => [x, ys[i]]);
|
|
727
|
-
poly.closed = true;
|
|
728
|
-
this.applyBezier(poly, true);
|
|
729
|
-
r.bounds = poly;
|
|
639
|
+
const ring = rectToRing(r.bounds);
|
|
640
|
+
next = edit.setBezier(makePolygon(ring.xs, ring.ys), true);
|
|
730
641
|
}
|
|
731
|
-
|
|
732
|
-
return; // bezier=false on a rectangle
|
|
733
|
-
|
|
734
|
-
this.
|
|
735
|
-
this.emit();
|
|
736
|
-
}
|
|
737
|
-
/** Turn bezier on (and seed editable handles from the smooth default) or off
|
|
738
|
-
* (and drop the handles). */
|
|
739
|
-
applyBezier(poly, bezier) {
|
|
740
|
-
poly.bezier = bezier;
|
|
741
|
-
if (bezier) {
|
|
742
|
-
const off = defaultHandleOffsets(poly.xpoints, poly.ypoints, poly.closed !== false);
|
|
743
|
-
poly.handlesIn = off.in;
|
|
744
|
-
poly.handlesOut = off.out;
|
|
745
|
-
this.seedHoleHandles(poly); // smooth the holes too (donut → bezier curves the holes)
|
|
746
|
-
}
|
|
747
|
-
else {
|
|
748
|
-
poly.handlesIn = undefined;
|
|
749
|
-
poly.handlesOut = undefined;
|
|
750
|
-
poly.holeHandlesIn = undefined;
|
|
751
|
-
poly.holeHandlesOut = undefined;
|
|
752
|
-
}
|
|
753
|
-
}
|
|
754
|
-
/** (Re)seed per-hole bezier handles from the Catmull-Rom default, parallel to `poly.holes`. */
|
|
755
|
-
seedHoleHandles(poly) {
|
|
756
|
-
if (!poly.holes || !poly.holes.length) {
|
|
757
|
-
poly.holeHandlesIn = undefined;
|
|
758
|
-
poly.holeHandlesOut = undefined;
|
|
759
|
-
return;
|
|
760
|
-
}
|
|
761
|
-
const ins = [];
|
|
762
|
-
const outs = [];
|
|
763
|
-
for (const ring of poly.holes) {
|
|
764
|
-
const off = defaultHandleOffsets(ring.map((p) => p[0]), ring.map((p) => p[1]), true);
|
|
765
|
-
ins.push(off.in);
|
|
766
|
-
outs.push(off.out);
|
|
767
|
-
}
|
|
768
|
-
poly.holeHandlesIn = ins;
|
|
769
|
-
poly.holeHandlesOut = outs;
|
|
642
|
+
if (!next)
|
|
643
|
+
return; // already in that state, or bezier=false on a rectangle
|
|
644
|
+
this.recordUndoSnapshot();
|
|
645
|
+
this.replaceRegion(replaceBounds(r, next));
|
|
770
646
|
}
|
|
771
647
|
/** Drag a bezier control point on a hole ring vertex (donut bezier editing). */
|
|
772
648
|
moveHoleBezierHandle(id, holeIndex, index, side, x, y) {
|
|
773
|
-
|
|
774
|
-
if (!poly || !poly.bezier || !poly.holes || holeIndex < 0 || holeIndex >= poly.holes.length) {
|
|
775
|
-
return;
|
|
776
|
-
}
|
|
777
|
-
const ring = poly.holes[holeIndex];
|
|
778
|
-
if (index < 0 || index >= ring.length)
|
|
779
|
-
return;
|
|
780
|
-
this.recordUndoSnapshot();
|
|
781
|
-
if (!poly.holeHandlesIn || !poly.holeHandlesOut)
|
|
782
|
-
this.seedHoleHandles(poly);
|
|
783
|
-
const offset = [x - ring[index][0], y - ring[index][1]];
|
|
784
|
-
if (side === 'in')
|
|
785
|
-
poly.holeHandlesIn[holeIndex][index] = offset;
|
|
786
|
-
else
|
|
787
|
-
poly.holeHandlesOut[holeIndex][index] = offset;
|
|
788
|
-
this.syncCache();
|
|
789
|
-
this.emit();
|
|
649
|
+
this.editPolygon(id, (p) => edit.moveHoleBezierHandle(p, holeIndex, index, side, x, y));
|
|
790
650
|
}
|
|
791
651
|
moveBezierHandle(id, index, side, x, y) {
|
|
792
|
-
|
|
793
|
-
|
|
652
|
+
this.editPolygon(id, (p) => edit.moveBezierHandle(p, index, side, x, y));
|
|
653
|
+
}
|
|
654
|
+
/** Apply a copy-on-write polygon edit to region `id`: record, swap in, emit. */
|
|
655
|
+
editPolygon(id, apply) {
|
|
656
|
+
const r = this.findById(id);
|
|
657
|
+
if (!r || !(r.bounds instanceof Polygon))
|
|
658
|
+
return;
|
|
659
|
+
const next = apply(r.bounds);
|
|
660
|
+
if (!next)
|
|
794
661
|
return;
|
|
795
662
|
this.recordUndoSnapshot();
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
const offset = [x - poly.xpoints[index], y - poly.ypoints[index]];
|
|
802
|
-
if (side === 'in')
|
|
803
|
-
poly.handlesIn[index] = offset;
|
|
804
|
-
else
|
|
805
|
-
poly.handlesOut[index] = offset;
|
|
663
|
+
this.replaceRegion(replaceBounds(r, next));
|
|
664
|
+
}
|
|
665
|
+
/** Swap `next` in for the stored region with its id (a new array), then sync and emit. */
|
|
666
|
+
replaceRegion(next) {
|
|
667
|
+
this.regions = this.regions.map((r) => (r.id === next.id ? next : r));
|
|
806
668
|
this.syncCache();
|
|
807
669
|
this.emit();
|
|
808
670
|
}
|
|
809
|
-
|
|
671
|
+
/** Coalesce `regionUpdate$` until the matching {@link endBatch} (live drags);
|
|
672
|
+
* the batch is also one undo gesture ({@link beginGesture}). */
|
|
673
|
+
beginBatch() {
|
|
674
|
+
this.batchDepth++;
|
|
675
|
+
this.beginGesture();
|
|
676
|
+
}
|
|
810
677
|
endBatch() {
|
|
811
678
|
if (this.batchDepth > 0)
|
|
812
679
|
this.batchDepth--;
|
|
680
|
+
this.endGesture();
|
|
813
681
|
if (this.batchDepth === 0 && this.pendingEmit) {
|
|
814
682
|
this.pendingEmit = false;
|
|
815
683
|
this.regionUpdate$.next(this.getRegions());
|
|
816
684
|
}
|
|
817
685
|
}
|
|
818
|
-
// ── per-image lifecycle ────────────────────────────────────────────────
|
|
819
686
|
/**
|
|
820
|
-
*
|
|
821
|
-
*
|
|
822
|
-
*
|
|
687
|
+
* Mark the start of one user gesture (e.g. a wand/brush mousedown): every
|
|
688
|
+
* commit until the matching {@link endGesture} becomes a single undo step,
|
|
689
|
+
* without delaying `regionUpdate$` (tools render through it while dragging).
|
|
690
|
+
* Calls nest. A gesture never folds into an earlier timed burst.
|
|
823
691
|
*/
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
692
|
+
beginGesture() {
|
|
693
|
+
this.history.beginGesture();
|
|
694
|
+
}
|
|
695
|
+
/** End the gesture opened by {@link beginGesture}; the next commit starts a new step. */
|
|
696
|
+
endGesture() {
|
|
697
|
+
this.history.endGesture();
|
|
698
|
+
}
|
|
699
|
+
// ── Region sources: large region sets, tiled by level of detail ─────────
|
|
700
|
+
/**
|
|
701
|
+
* Hold a large region set as a tiled region source instead of as regions: the backends that
|
|
702
|
+
* draw sources (OpenSeadragon, napari) draw its features at the detail the zoom shows, from
|
|
703
|
+
* the tiles in view, and a feature joins the regions — exactly, as an ordinary editable
|
|
704
|
+
* {@link Region} with its {@link Region.sourceId} — only when it is selected or edited
|
|
705
|
+
* ({@link takeSourceFeatures}). Until then {@link getRegions} does not include it.
|
|
706
|
+
*
|
|
707
|
+
* `source` may be an opener, called the first time its slice is shown (and again if the
|
|
708
|
+
* source was closed to save memory). `slices` says which slice of the current image it
|
|
709
|
+
* serves: one (default: the slice shown; plane 0 of the source), or `'planes'`, every slice z
|
|
710
|
+
* from plane z of a z-indexed source. Replaces the source those slices had.
|
|
711
|
+
*/
|
|
712
|
+
attachRegionSource(source, slices = { slice: this.sourceSlice }) {
|
|
713
|
+
const image = this.scope.activeImage;
|
|
714
|
+
if (!image)
|
|
715
|
+
return;
|
|
716
|
+
const open = typeof source === 'function' ? source : () => Promise.resolve(source);
|
|
717
|
+
this.sources.attach(image, open, slices);
|
|
718
|
+
this.sourcesVersion++;
|
|
719
|
+
this.refreshSourceView();
|
|
720
|
+
}
|
|
721
|
+
/** Drop the current image's region sources (closing them) and what was taken from them. */
|
|
722
|
+
detachRegionSources() {
|
|
723
|
+
const image = this.scope.activeImage;
|
|
724
|
+
if (!image)
|
|
725
|
+
return;
|
|
726
|
+
this.sources.detachImage(image);
|
|
727
|
+
this.sourcesVersion++;
|
|
728
|
+
this.refreshSourceView();
|
|
729
|
+
}
|
|
730
|
+
/**
|
|
731
|
+
* Drop the slice's region source, for regions imported in place of the slice's (a small file
|
|
732
|
+
* replacing a large one): a source of the slice's own is detached; a z-indexed source over every
|
|
733
|
+
* slice has this slice's features taken out (as deleted). The other slices keep theirs.
|
|
734
|
+
*/
|
|
735
|
+
async dropSliceRegionSource() {
|
|
736
|
+
const image = this.scope.activeImage;
|
|
737
|
+
const slice = this.sourceSlice;
|
|
738
|
+
if (!image || !this.sources.has(image, slice))
|
|
739
|
+
return;
|
|
740
|
+
if (this.sources.hasOwnSource(image, slice)) {
|
|
741
|
+
this.sources.detachSlice(image, slice);
|
|
742
|
+
this.sourcesVersion++;
|
|
743
|
+
this.refreshSourceView();
|
|
827
744
|
return;
|
|
828
|
-
// Switching images ends any per-slice stack session (jit-ui#93); the loader
|
|
829
|
-
// re-enters stack mode afterwards if the new image is itself a z-stack.
|
|
830
|
-
this.exitStackMode();
|
|
831
|
-
if (this.currentImageKey) {
|
|
832
|
-
this.regionsByImageKey.set(this.currentImageKey, this.regions.slice());
|
|
833
745
|
}
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
this.
|
|
843
|
-
|
|
746
|
+
const generation = this.sourceGeneration;
|
|
747
|
+
const binding = await this.sources.binding(image, slice);
|
|
748
|
+
if (!binding || generation !== this.sourceGeneration)
|
|
749
|
+
return;
|
|
750
|
+
const all = await binding.source.getIndex(binding.plane, {
|
|
751
|
+
offset: 0,
|
|
752
|
+
limit: binding.source.info.featureCount,
|
|
753
|
+
});
|
|
754
|
+
if (generation !== this.sourceGeneration)
|
|
755
|
+
return;
|
|
756
|
+
this.setTaken(new Set([...this.currentTaken(), ...all.rows.map((r) => r.id)]));
|
|
844
757
|
}
|
|
845
|
-
/**
|
|
846
|
-
|
|
847
|
-
this.
|
|
848
|
-
this.currentImageKey = undefined;
|
|
849
|
-
this.regions = [];
|
|
850
|
-
this.selectedIds = [];
|
|
851
|
-
this.resetUndoHistory();
|
|
758
|
+
/** Whether the slice shown has a region source. */
|
|
759
|
+
hasRegionSource() {
|
|
760
|
+
return this.sources.has(this.scope.activeImage, this.sourceSlice);
|
|
852
761
|
}
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
762
|
+
/** The slice's region source as a source layer draws it; null without one (or until it opens). */
|
|
763
|
+
getRegionSourceView() {
|
|
764
|
+
return this.sourceView$.value;
|
|
765
|
+
}
|
|
766
|
+
/** {@link getRegionSourceView} and every change of it (slice, taken ids, class colours). */
|
|
767
|
+
getRegionSourceView$() {
|
|
768
|
+
return this.sourceView$.asObservable();
|
|
769
|
+
}
|
|
770
|
+
/**
|
|
771
|
+
* Take source features into the working set for editing: their exact geometry becomes
|
|
772
|
+
* ordinary regions (minted, coloured and slice-tagged as any region entering the store) and
|
|
773
|
+
* the source stops drawing them. Not an undo step of its own — undoing past it puts the
|
|
774
|
+
* features back in the source. Resolves the region ids, in the order asked (a feature already
|
|
775
|
+
* taken resolves to its region); [] when the slice changed meanwhile.
|
|
776
|
+
*/
|
|
777
|
+
async takeSourceFeatures(ids) {
|
|
778
|
+
const view = this.sourceView$.value;
|
|
779
|
+
if (!view || !ids.length)
|
|
780
|
+
return [];
|
|
781
|
+
const generation = this.sourceGeneration;
|
|
782
|
+
const wanted = ids.filter((id) => !view.taken.has(id));
|
|
783
|
+
const features = wanted.length ? await view.source.getFeatures(wanted) : [];
|
|
784
|
+
if (generation !== this.sourceGeneration)
|
|
785
|
+
return [];
|
|
786
|
+
const taken = this.currentTaken();
|
|
787
|
+
const fresh = features.filter((f) => !taken.has(f.id));
|
|
788
|
+
if (fresh.length) {
|
|
789
|
+
const regions = fresh.map((f) => {
|
|
790
|
+
const region = regionFromGeoJsonFeature(f.feature, 0, f.id);
|
|
791
|
+
if (this.scope.stackMode)
|
|
792
|
+
region.z = this.scope.displaySlice;
|
|
793
|
+
return region;
|
|
794
|
+
});
|
|
795
|
+
const admitted = this.admit(regions);
|
|
796
|
+
// Fresh instances, completed in place: named after their new id like a drawn region.
|
|
797
|
+
for (const r of admitted)
|
|
798
|
+
r.name = `shape${r.id}`;
|
|
799
|
+
this.regions = this.regions.concat(admitted);
|
|
800
|
+
this.setTaken(new Set([...taken, ...fresh.map((f) => f.id)]));
|
|
801
|
+
this.syncCache();
|
|
802
|
+
this.emitSelection();
|
|
803
|
+
this.emit();
|
|
859
804
|
}
|
|
860
|
-
|
|
805
|
+
const bySource = new Map(this.regions.filter((r) => r.sourceId !== undefined).map((r) => [r.sourceId, r.id]));
|
|
806
|
+
return ids.map((id) => bySource.get(id)).filter((id) => id !== undefined);
|
|
807
|
+
}
|
|
808
|
+
/** {@link takeSourceFeatures}, then select them (added to the selection with `additive`). */
|
|
809
|
+
async selectSourceFeatures(ids, additive = false) {
|
|
810
|
+
const taken = await this.takeSourceFeatures(ids);
|
|
811
|
+
if (!taken.length)
|
|
812
|
+
return taken;
|
|
813
|
+
this.selection.replace(additive ? [...new Set([...this.selection.ids, ...taken])] : taken);
|
|
814
|
+
this.emitSelection();
|
|
815
|
+
return taken;
|
|
861
816
|
}
|
|
862
817
|
/**
|
|
863
|
-
*
|
|
864
|
-
*
|
|
865
|
-
* embedded in the GeoJSON** (which the YOLO worker writes today). A matching
|
|
866
|
-
* preset gives the class colour; an unknown class gets a deterministic fallback
|
|
867
|
-
* colour (and, only when `autoPromote` is on, is added to the editable list).
|
|
868
|
-
* Regions the user explicitly recoloured (`colorOverridden`) are left untouched.
|
|
818
|
+
* Features per class still in the slice's region source (not taken); {} without one. With
|
|
819
|
+
* `stack`, a z-stack's over every slice: its source's planes, or each slice's source added up.
|
|
869
820
|
*/
|
|
870
|
-
|
|
871
|
-
const
|
|
872
|
-
const
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
const
|
|
878
|
-
if (
|
|
879
|
-
|
|
880
|
-
|
|
821
|
+
async getRegionSourceClassCounts(stack = false) {
|
|
822
|
+
const view = this.sourceView$.value;
|
|
823
|
+
const image = this.scope.activeImage;
|
|
824
|
+
if (!stack || !this.scope.stackMode) {
|
|
825
|
+
return view ? view.source.getClassCounts(view.plane, Array.from(view.taken)) : {};
|
|
826
|
+
}
|
|
827
|
+
if (this.sources.hasPlanesSource(image)) {
|
|
828
|
+
const binding = await this.sources.binding(image, this.sourceSlice);
|
|
829
|
+
if (!binding)
|
|
830
|
+
return {};
|
|
831
|
+
try {
|
|
832
|
+
return await binding.source.getClassCounts(null, this.sources.allTaken(image));
|
|
881
833
|
}
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
// In normalized mode, trim the promoted name so leading/trailing
|
|
887
|
-
// whitespace doesn't create invisible duplicates or odd display names.
|
|
888
|
-
const name = set.matchMode === 'normalized' ? region.label.trim() : region.label;
|
|
889
|
-
this.store.upsertClass({ name, color, source: 'auto' });
|
|
834
|
+
catch (err) {
|
|
835
|
+
// A tile server that predates counting every plane: the slice's counts.
|
|
836
|
+
console.warn('[regions] could not count the classes of every slice', err);
|
|
837
|
+
return view ? view.source.getClassCounts(view.plane, Array.from(view.taken)) : {};
|
|
890
838
|
}
|
|
891
839
|
}
|
|
840
|
+
const counts = {};
|
|
841
|
+
for (const slice of this.sources.slicesWithSource(image)) {
|
|
842
|
+
const binding = await this.sources.binding(image, slice);
|
|
843
|
+
if (!binding)
|
|
844
|
+
continue;
|
|
845
|
+
const own = await binding.source.getClassCounts(binding.plane, Array.from(this.sources.taken(image, slice)));
|
|
846
|
+
for (const [label, n] of Object.entries(own))
|
|
847
|
+
counts[label] = (counts[label] ?? 0) + n;
|
|
848
|
+
}
|
|
849
|
+
return counts;
|
|
892
850
|
}
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
851
|
+
/**
|
|
852
|
+
* Select every region of these classes on the slice — the regions', and the region source's,
|
|
853
|
+
* which are taken into the regions (at most {@link SELECT_CLASSES_LIMIT} of them). Added to the
|
|
854
|
+
* selection with `additive`. Resolves the selected region ids.
|
|
855
|
+
*/
|
|
856
|
+
async selectClasses(classes, additive = false) {
|
|
857
|
+
const wanted = new Set(classes);
|
|
858
|
+
const view = this.sourceView$.value;
|
|
859
|
+
if (view && classes.length) {
|
|
860
|
+
const page = await view.source.getIndex(view.plane, {
|
|
861
|
+
offset: 0,
|
|
862
|
+
limit: SELECT_CLASSES_LIMIT,
|
|
863
|
+
classes,
|
|
864
|
+
exclude: Array.from(view.taken),
|
|
865
|
+
});
|
|
866
|
+
if (page.rows.length)
|
|
867
|
+
await this.takeSourceFeatures(page.rows.map((r) => r.id));
|
|
896
868
|
}
|
|
869
|
+
const ids = this.regions.filter((r) => !r.isProfile?.() && r.label && wanted.has(r.label)).map((r) => r.id);
|
|
870
|
+
this.selection.replace(additive ? [...new Set([...this.selection.ids, ...ids])] : ids);
|
|
871
|
+
this.emitSelection();
|
|
872
|
+
return ids;
|
|
897
873
|
}
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
874
|
+
/**
|
|
875
|
+
* The 3D reconstruction of each group of classes over every slice of the stack (an atlas
|
|
876
|
+
* structure with its substructures, say): the outlines of the regions of those classes on every
|
|
877
|
+
* slice — the region sources' and those drawn or taken — stacked and meshed in a worker. Meshes
|
|
878
|
+
* are in image px (x, y) and slice indices (z). `pixelStep` is the in-plane voxel size (image
|
|
879
|
+
* px); the outlines are read at the matching level of detail. A group with no outline gets an
|
|
880
|
+
* empty mesh.
|
|
881
|
+
*/
|
|
882
|
+
async reconstructClasses(groups, pixelStep = 1) {
|
|
883
|
+
const level = Math.max(0, Math.floor(Math.log2(Math.max(1, pixelStep))));
|
|
884
|
+
const out = [];
|
|
885
|
+
for (const group of groups) {
|
|
886
|
+
const slices = await this.classOutlines(group.classes, level);
|
|
887
|
+
out.push({ key: group.key, mesh: await reconstructInWorker(slices, { pixelStep }) });
|
|
907
888
|
}
|
|
908
|
-
|
|
889
|
+
return out;
|
|
909
890
|
}
|
|
910
|
-
/**
|
|
911
|
-
*
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
891
|
+
/**
|
|
892
|
+
* Each class's volume over the whole stack, in px² × slices: its outlines' area on every slice
|
|
893
|
+
* (its features' union, see `outlinesArea`), one slice thick (Cavalieri's estimator), from the
|
|
894
|
+
* exact outlines. Where a feature is, a region source's or a drawn or taken region, does not
|
|
895
|
+
* change it: taking one leaves the volume as it was. The region sources' part is cached until
|
|
896
|
+
* what they hold changes (a feature taken or deleted, another source); only the slices with
|
|
897
|
+
* drawn or taken regions of the class are measured again.
|
|
898
|
+
*/
|
|
899
|
+
async classVolumes(classes) {
|
|
900
|
+
const state = this.sourceStateKey();
|
|
901
|
+
const out = new Map();
|
|
902
|
+
await Promise.all([...new Set(classes)].map(async (name) => {
|
|
903
|
+
const source = await this.sourceVolume(state, name);
|
|
904
|
+
let volume = source.total;
|
|
905
|
+
for (const regions of mergeOutlines(this.regionOutlines([name]))) {
|
|
906
|
+
const under = source.slices.get(regions.z);
|
|
907
|
+
const [both] = under ? mergeOutlines([under.outlines, regions]) : [regions];
|
|
908
|
+
volume += outlinesArea(both.rings, both.ringGroups) - (under?.area ?? 0);
|
|
920
909
|
}
|
|
910
|
+
out.set(name, volume);
|
|
911
|
+
}));
|
|
912
|
+
return out;
|
|
913
|
+
}
|
|
914
|
+
/** The region sources' part of a class's volume, cached by what they hold (see classVolumes). */
|
|
915
|
+
sourceVolume(state, name) {
|
|
916
|
+
const key = `${state}\n${name}`;
|
|
917
|
+
let source = this.sourceVolumeCache.get(key);
|
|
918
|
+
if (source) {
|
|
919
|
+
// Most recently used last.
|
|
920
|
+
this.sourceVolumeCache.delete(key);
|
|
921
|
+
this.sourceVolumeCache.set(key, source);
|
|
922
|
+
return source;
|
|
921
923
|
}
|
|
922
|
-
this.
|
|
923
|
-
|
|
924
|
-
|
|
924
|
+
source = this.sourceOutlines([name], 0).then((parts) => {
|
|
925
|
+
const slices = new Map();
|
|
926
|
+
let total = 0;
|
|
927
|
+
for (const outlines of mergeOutlines(parts)) {
|
|
928
|
+
const area = outlinesArea(outlines.rings, outlines.ringGroups);
|
|
929
|
+
slices.set(outlines.z, { area, outlines });
|
|
930
|
+
total += area;
|
|
931
|
+
}
|
|
932
|
+
return { total, slices };
|
|
933
|
+
});
|
|
934
|
+
this.sourceVolumeCache.set(key, source);
|
|
935
|
+
source.catch(() => this.sourceVolumeCache.delete(key));
|
|
936
|
+
while (this.sourceVolumeCache.size > SOURCE_VOLUME_CACHE_SIZE) {
|
|
937
|
+
this.sourceVolumeCache.delete(this.sourceVolumeCache.keys().next().value);
|
|
925
938
|
}
|
|
939
|
+
return source;
|
|
926
940
|
}
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
return true;
|
|
934
|
-
}
|
|
935
|
-
findById(id) {
|
|
936
|
-
return this.regions.find(r => r.id === id);
|
|
941
|
+
/**
|
|
942
|
+
* Every slice's outlines of these classes, the region sources' then the regions': closed shapes'
|
|
943
|
+
* rings, and open polylines as `lines`.
|
|
944
|
+
*/
|
|
945
|
+
async classOutlines(classes, level) {
|
|
946
|
+
return mergeOutlines([...(await this.sourceOutlines(classes, level)), ...this.regionOutlines(classes)]);
|
|
937
947
|
}
|
|
938
|
-
|
|
939
|
-
|
|
948
|
+
/**
|
|
949
|
+
* The region sources' outlines of these classes on every slice, without the features taken or
|
|
950
|
+
* deleted. The last few class sets are kept until what the sources hold changes: rebuilding a
|
|
951
|
+
* surface after an edit reads nothing again.
|
|
952
|
+
*/
|
|
953
|
+
sourceOutlines(classes, level) {
|
|
954
|
+
const key = `${this.sourceStateKey()}\n${level}\n${classes ? classes.join('\n') : '*'}`;
|
|
955
|
+
const cached = this.sourceOutlineCache.get(key);
|
|
956
|
+
if (cached) {
|
|
957
|
+
// Most recently used last.
|
|
958
|
+
this.sourceOutlineCache.delete(key);
|
|
959
|
+
this.sourceOutlineCache.set(key, cached);
|
|
960
|
+
return cached;
|
|
961
|
+
}
|
|
962
|
+
const read = this.readSourceOutlines(classes, level);
|
|
963
|
+
this.sourceOutlineCache.set(key, read);
|
|
964
|
+
read.catch(() => this.sourceOutlineCache.delete(key));
|
|
965
|
+
while (this.sourceOutlineCache.size > SOURCE_OUTLINE_CACHE_SIZE) {
|
|
966
|
+
this.sourceOutlineCache.delete(this.sourceOutlineCache.keys().next().value);
|
|
967
|
+
}
|
|
968
|
+
return read;
|
|
940
969
|
}
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
const
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
poly.npoints = p.npoints;
|
|
949
|
-
poly.xpoints = p.xpoints.slice();
|
|
950
|
-
poly.ypoints = p.ypoints.slice();
|
|
951
|
-
poly.coordinates = p.coordinates.map(c => c.slice());
|
|
952
|
-
poly.closed = p.closed;
|
|
953
|
-
poly.bezier = p.bezier;
|
|
954
|
-
if (p.handlesIn)
|
|
955
|
-
poly.handlesIn = p.handlesIn.map(o => o.slice());
|
|
956
|
-
if (p.handlesOut)
|
|
957
|
-
poly.handlesOut = p.handlesOut.map(o => o.slice());
|
|
958
|
-
if (p.holes)
|
|
959
|
-
poly.holes = p.holes.map(ring => ring.map(pt => pt.slice()));
|
|
960
|
-
if (p.holeHandlesIn)
|
|
961
|
-
poly.holeHandlesIn = p.holeHandlesIn.map(r => r.map(o => o.slice()));
|
|
962
|
-
if (p.holeHandlesOut)
|
|
963
|
-
poly.holeHandlesOut = p.holeHandlesOut.map(r => r.map(o => o.slice()));
|
|
964
|
-
return poly;
|
|
965
|
-
}
|
|
966
|
-
cloneBounds(bounds) {
|
|
967
|
-
if (bounds instanceof Rectangle) {
|
|
968
|
-
const rect = new Rectangle();
|
|
969
|
-
rect.x = bounds.x;
|
|
970
|
-
rect.y = bounds.y;
|
|
971
|
-
rect.width = bounds.width;
|
|
972
|
-
rect.height = bounds.height;
|
|
973
|
-
return rect;
|
|
970
|
+
async readSourceOutlines(classes, level) {
|
|
971
|
+
const out = [];
|
|
972
|
+
const image = this.scope.activeImage;
|
|
973
|
+
if (this.sources.hasPlanesSource(image)) {
|
|
974
|
+
const binding = await this.sources.binding(image, this.sourceSlice);
|
|
975
|
+
const outlines = await binding?.source.getClassOutlines(classes, level, this.sources.allTaken(image));
|
|
976
|
+
out.push(...(outlines ?? []));
|
|
974
977
|
}
|
|
975
|
-
|
|
976
|
-
const
|
|
977
|
-
|
|
978
|
-
|
|
978
|
+
for (const z of this.sources.slicesWithSource(image)) {
|
|
979
|
+
const binding = await this.sources.binding(image, z);
|
|
980
|
+
if (!binding)
|
|
981
|
+
continue;
|
|
982
|
+
const outlines = await binding.source.getClassOutlines(classes, level, Array.from(this.sources.taken(image, z)));
|
|
983
|
+
for (const s of outlines)
|
|
984
|
+
if (s.z === binding.plane)
|
|
985
|
+
out.push({ ...s, z });
|
|
979
986
|
}
|
|
980
|
-
return
|
|
987
|
+
return out;
|
|
981
988
|
}
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
989
|
+
/**
|
|
990
|
+
* Every class's outlines on every slice, by class: the region sources' (one read for all, kept
|
|
991
|
+
* like {@link sourceOutlines}) and the drawn and taken regions'. What a section through the
|
|
992
|
+
* stack cuts (see `geometry/section`).
|
|
993
|
+
*/
|
|
994
|
+
async outlinesByClass(level) {
|
|
995
|
+
const byClass = new Map();
|
|
996
|
+
const slot = (label, z) => {
|
|
997
|
+
let slices = byClass.get(label);
|
|
998
|
+
if (!slices)
|
|
999
|
+
byClass.set(label, (slices = new Map()));
|
|
1000
|
+
let slice = slices.get(z);
|
|
1001
|
+
if (!slice)
|
|
1002
|
+
slices.set(z, (slice = { rings: [], ringGroups: [], lines: [] }));
|
|
1003
|
+
return slice;
|
|
1004
|
+
};
|
|
1005
|
+
const nextPart = featureIds();
|
|
1006
|
+
for (const s of await this.sourceOutlines(null, level)) {
|
|
1007
|
+
const id = nextPart();
|
|
1008
|
+
s.rings.forEach((r, i) => {
|
|
1009
|
+
const label = s.ringLabels?.[i];
|
|
1010
|
+
if (!label)
|
|
1011
|
+
return;
|
|
1012
|
+
const slice = slot(label, s.z);
|
|
1013
|
+
slice.rings.push(r);
|
|
1014
|
+
slice.ringGroups.push(id(s.ringGroups?.[i]));
|
|
1015
|
+
});
|
|
1016
|
+
(s.lines ?? []).forEach((l, i) => {
|
|
1017
|
+
const label = s.lineLabels?.[i];
|
|
1018
|
+
if (label)
|
|
1019
|
+
slot(label, s.z).lines.push(l);
|
|
1020
|
+
});
|
|
986
1021
|
}
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
1022
|
+
for (const { label, outlines } of this.labelledRegionOutlines(null)) {
|
|
1023
|
+
// A region is one feature.
|
|
1024
|
+
const id = nextPart()(undefined);
|
|
1025
|
+
const slice = slot(label, outlines.z);
|
|
1026
|
+
slice.rings.push(...outlines.rings);
|
|
1027
|
+
slice.ringGroups.push(...outlines.rings.map(() => id));
|
|
1028
|
+
slice.lines.push(...(outlines.lines ?? []));
|
|
1029
|
+
}
|
|
1030
|
+
return new Map(Array.from(byClass, ([label, slices]) => [label, Array.from(slices, ([z, s]) => sliceOutlines(z, s))]));
|
|
1031
|
+
}
|
|
1032
|
+
/** The drawn and taken regions' outlines of these classes, by slice. */
|
|
1033
|
+
regionOutlines(classes) {
|
|
1034
|
+
return this.labelledRegionOutlines(new Set(classes)).map((o) => o.outlines);
|
|
1035
|
+
}
|
|
1036
|
+
/** Each drawn or taken region's outlines (of the `wanted` classes; null: every class) with its class. */
|
|
1037
|
+
labelledRegionOutlines(wanted) {
|
|
1038
|
+
const out = [];
|
|
1039
|
+
for (const r of this.scope.stackMode ? this.getSliceRegions() : this.regions) {
|
|
1040
|
+
if (r.isProfile?.() || !r.label || (wanted && !wanted.has(r.label)))
|
|
1041
|
+
continue;
|
|
1042
|
+
const rings = [];
|
|
1043
|
+
for (const p of regionPolygons(r)) {
|
|
1044
|
+
rings.push(Float64Array.from(p.xpoints.flatMap((x, i) => [x, p.ypoints[i]])));
|
|
1045
|
+
for (const hole of p.holes ?? [])
|
|
1046
|
+
rings.push(Float64Array.from(hole.flat()));
|
|
993
1047
|
}
|
|
994
|
-
|
|
1048
|
+
const lines = regionPolylines(r);
|
|
1049
|
+
out.push({ label: r.label, outlines: { z: r.z ?? 0, rings, ...(lines.length ? { lines } : {}) } });
|
|
995
1050
|
}
|
|
996
|
-
|
|
997
|
-
|
|
1051
|
+
return out;
|
|
1052
|
+
}
|
|
1053
|
+
/** What the region sources of the image hold (see {@link sourceStateKey}): it changes when a
|
|
1054
|
+
* feature is taken or deleted, or that is undone. */
|
|
1055
|
+
getSourceStateKey() {
|
|
1056
|
+
return this.sourceStateKey();
|
|
1057
|
+
}
|
|
1058
|
+
/**
|
|
1059
|
+
* What the region sources of the image hold: the image, its sources (one attached or dropped
|
|
1060
|
+
* bumps the version) and the features taken from them. A key for what is read from them.
|
|
1061
|
+
*/
|
|
1062
|
+
sourceStateKey() {
|
|
1063
|
+
const image = this.scope.activeImage;
|
|
1064
|
+
let taken = 2166136261;
|
|
1065
|
+
for (const z of this.sources.slicesWithTaken(image)) {
|
|
1066
|
+
for (const id of [...this.sources.taken(image, z)].sort()) {
|
|
1067
|
+
const s = `${z}:${id};`;
|
|
1068
|
+
for (let i = 0; i < s.length; i++)
|
|
1069
|
+
taken = Math.imul(taken ^ s.charCodeAt(i), 16777619) >>> 0;
|
|
1070
|
+
}
|
|
998
1071
|
}
|
|
999
|
-
return
|
|
1072
|
+
return `${image}\n${this.sourcesVersion}\n${taken}`;
|
|
1000
1073
|
}
|
|
1001
|
-
|
|
1002
|
-
|
|
1074
|
+
/** Delete source features without taking them (one undo step). */
|
|
1075
|
+
deleteSourceFeatures(ids) {
|
|
1076
|
+
const taken = this.currentTaken();
|
|
1077
|
+
const drop = ids.filter((id) => !taken.has(id));
|
|
1078
|
+
if (!drop.length || !this.sourceView$.value)
|
|
1079
|
+
return;
|
|
1080
|
+
this.recordUndoSnapshot();
|
|
1081
|
+
this.setTaken(new Set([...taken, ...drop]));
|
|
1082
|
+
this.emit();
|
|
1083
|
+
}
|
|
1084
|
+
/**
|
|
1085
|
+
* A page of the slice source's features not taken from it (file order), e.g. for the Region
|
|
1086
|
+
* Editor's list; an empty page without a source.
|
|
1087
|
+
*/
|
|
1088
|
+
async getRegionSourceIndex(query) {
|
|
1089
|
+
const view = this.sourceView$.value;
|
|
1090
|
+
if (!view)
|
|
1091
|
+
return { total: 0, rows: [] };
|
|
1092
|
+
return view.source.getIndex(view.plane, { ...query, exclude: Array.from(view.taken) });
|
|
1093
|
+
}
|
|
1094
|
+
/**
|
|
1095
|
+
* `regions` as a GeoJSON FeatureCollection string merged with the region source behind them:
|
|
1096
|
+
* the source's features that were not taken (or deleted), then `regions`. Without a source,
|
|
1097
|
+
* {@link getGeoJsonString}. `slice` names a folder stack's slice (default the one shown);
|
|
1098
|
+
* on a z-indexed stack's source (`'planes'`) the export spans every slice.
|
|
1099
|
+
*/
|
|
1100
|
+
async getGeoJsonWithSource(regions, slice = this.sourceSlice) {
|
|
1101
|
+
const image = this.scope.activeImage;
|
|
1102
|
+
const planes = this.scope.stackMode && this.sources.hasPlanesSource(image);
|
|
1103
|
+
const binding = await this.sources.binding(image, slice);
|
|
1104
|
+
if (!binding)
|
|
1105
|
+
return regionsToGeoJson(regions);
|
|
1106
|
+
const features = regions
|
|
1107
|
+
.filter((r) => !r.isProfile?.())
|
|
1108
|
+
.map((r) => featureFromRegion(r))
|
|
1109
|
+
.filter((f) => !!f);
|
|
1110
|
+
const exclude = planes ? this.sources.allTaken(image) : Array.from(this.sources.taken(image, slice));
|
|
1111
|
+
return binding.source.exportGeoJson(exclude, features);
|
|
1112
|
+
}
|
|
1113
|
+
// ── Region look ────────────────────────────────────────────────────────
|
|
1114
|
+
/**
|
|
1115
|
+
* Whether a region of class `label` goes unlabelled because a subclass of it (by the region
|
|
1116
|
+
* source's class hierarchy) is among the regions too — an atlas's "Isocortex" under its areas.
|
|
1117
|
+
* False without a hierarchy.
|
|
1118
|
+
*/
|
|
1119
|
+
isLabelCovered(label) {
|
|
1120
|
+
if (!label)
|
|
1003
1121
|
return false;
|
|
1004
|
-
|
|
1122
|
+
const hierarchy = this.sourceView$.value?.source.info.hierarchy;
|
|
1123
|
+
if (!hierarchy)
|
|
1005
1124
|
return false;
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1125
|
+
if (this.coveredFor?.regions !== this.regions || this.coveredFor.hierarchy !== hierarchy) {
|
|
1126
|
+
const parent = new Map(hierarchy.filter((n) => n.parent).map((n) => [n.name, n.parent]));
|
|
1127
|
+
const covered = new Set();
|
|
1128
|
+
for (const r of this.regions) {
|
|
1129
|
+
let p = r.label ? parent.get(r.label) : undefined;
|
|
1130
|
+
while (p && !covered.has(p)) {
|
|
1131
|
+
covered.add(p);
|
|
1132
|
+
p = parent.get(p);
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
this.coveredFor = { regions: this.regions, hierarchy, covered };
|
|
1009
1136
|
}
|
|
1010
|
-
return this.
|
|
1137
|
+
return this.coveredFor.covered.has(label);
|
|
1011
1138
|
}
|
|
1012
|
-
/**
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1139
|
+
/** The classes hidden from view (see {@link setClassesHidden}). */
|
|
1140
|
+
getHiddenClasses() {
|
|
1141
|
+
return this.hiddenClasses$.value;
|
|
1142
|
+
}
|
|
1143
|
+
/** {@link getHiddenClasses} and every change of it. */
|
|
1144
|
+
getHiddenClasses$() {
|
|
1145
|
+
return this.hiddenClasses$.asObservable();
|
|
1146
|
+
}
|
|
1147
|
+
/**
|
|
1148
|
+
* Hide (or show again) these classes' regions: the overlays and the region source's layer stop
|
|
1149
|
+
* drawing them, and a hidden region can be neither picked nor kept selected. The regions stay in
|
|
1150
|
+
* the set (the table lists them; a save keeps them).
|
|
1151
|
+
*/
|
|
1152
|
+
setClassesHidden(classes, hidden) {
|
|
1153
|
+
const cur = this.hiddenClasses$.value;
|
|
1154
|
+
const next = new Set(cur);
|
|
1155
|
+
for (const c of classes) {
|
|
1156
|
+
if (hidden)
|
|
1157
|
+
next.add(c);
|
|
1158
|
+
else
|
|
1159
|
+
next.delete(c);
|
|
1160
|
+
}
|
|
1161
|
+
if (next.size === cur.size && [...next].every((c) => cur.has(c)))
|
|
1162
|
+
return;
|
|
1163
|
+
const set = this.store.getPresetSet();
|
|
1164
|
+
this.hiddenKeys = new Set([...next].map((c) => presetKey(set, c)));
|
|
1165
|
+
this.hiddenClasses$.next(next);
|
|
1166
|
+
if (hidden) {
|
|
1167
|
+
const shown = this.selection.indices.filter((i) => !this.isClassHidden(this.regions[i]?.label));
|
|
1168
|
+
if (shown.length !== this.selection.indices.length)
|
|
1169
|
+
this.setSelectedShapeIndices(shown);
|
|
1170
|
+
}
|
|
1171
|
+
this.republishView();
|
|
1172
|
+
this.regionUpdate$.next(this.getRegions());
|
|
1173
|
+
}
|
|
1174
|
+
/** Whether regions labelled `label` are hidden (an unlabelled region never is). */
|
|
1175
|
+
isClassHidden(label) {
|
|
1176
|
+
return !!label && this.hiddenKeys.size > 0 && this.hiddenKeys.has(presetKey(this.store.getPresetSet(), label));
|
|
1177
|
+
}
|
|
1178
|
+
/** The region look: outlines, or filled (an atlas's look); see `region-style`. */
|
|
1179
|
+
getRegionStyle() {
|
|
1180
|
+
return this.regionStyle$.value;
|
|
1181
|
+
}
|
|
1182
|
+
/** {@link getRegionStyle} and every change of it. */
|
|
1183
|
+
getRegionStyle$() {
|
|
1184
|
+
return this.regionStyle$.asObservable();
|
|
1185
|
+
}
|
|
1186
|
+
/**
|
|
1187
|
+
* Choose the region look, field by field; it overrides a region source's hint for the session.
|
|
1188
|
+
* The overlays redraw.
|
|
1189
|
+
*/
|
|
1190
|
+
setRegionStyle(patch) {
|
|
1191
|
+
this.userStyle = { ...this.userStyle, ...patch };
|
|
1192
|
+
this.restyle();
|
|
1193
|
+
}
|
|
1194
|
+
/** The look now: the user's choice, else the source's hint, else outlines. */
|
|
1195
|
+
effectiveStyle() {
|
|
1196
|
+
const hint = this.hintStyle ?? {};
|
|
1197
|
+
return {
|
|
1198
|
+
fillOpacity: this.userStyle.fillOpacity ?? hint.fillOpacity ?? DEFAULT_REGION_STYLE.fillOpacity,
|
|
1199
|
+
stroke: this.userStyle.stroke !== undefined ? this.userStyle.stroke : (hint.stroke ?? null),
|
|
1200
|
+
strokeWidth: this.userStyle.strokeWidth !== undefined ? this.userStyle.strokeWidth : (hint.strokeWidth ?? null),
|
|
1201
|
+
highlight: this.userStyle.highlight !== undefined ? this.userStyle.highlight : (hint.highlight ?? null),
|
|
1202
|
+
};
|
|
1203
|
+
}
|
|
1204
|
+
/** Publish the look when it changed: the overlays redraw the regions, the source layer its features. */
|
|
1205
|
+
restyle(redraw = false) {
|
|
1206
|
+
const next = this.effectiveStyle();
|
|
1207
|
+
const cur = this.regionStyle$.value;
|
|
1208
|
+
const same = Object.keys(next).every((k) => next[k] === cur[k]);
|
|
1209
|
+
if (!same)
|
|
1210
|
+
this.regionStyle$.next(next);
|
|
1211
|
+
const view = this.sourceView$.value;
|
|
1212
|
+
if (redraw || !same || (view && view.labels !== this.showShapeLabel)) {
|
|
1213
|
+
this.republishView();
|
|
1214
|
+
this.regionUpdate$.next(this.getRegions());
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
/** Re-emit the source view with the current look and label setting. */
|
|
1218
|
+
republishView() {
|
|
1219
|
+
const view = this.sourceView$.value;
|
|
1220
|
+
if (view)
|
|
1221
|
+
this.sourceView$.next({ ...view, style: this.regionStyle$.value, labels: this.showShapeLabel });
|
|
1222
|
+
}
|
|
1223
|
+
/** The slice a region source is keyed by: the display slice in stack mode, else 0. */
|
|
1224
|
+
get sourceSlice() {
|
|
1225
|
+
return this.scope.stackMode ? this.scope.displaySlice : 0;
|
|
1226
|
+
}
|
|
1227
|
+
currentTaken() {
|
|
1228
|
+
return this.sources.taken(this.scope.activeImage, this.sourceSlice);
|
|
1229
|
+
}
|
|
1230
|
+
/** Replace the slice's taken ids and tell the source layers. */
|
|
1231
|
+
setTaken(taken) {
|
|
1232
|
+
if (taken === this.currentTaken())
|
|
1233
|
+
return;
|
|
1234
|
+
this.sources.setTaken(this.scope.activeImage, this.sourceSlice, taken);
|
|
1235
|
+
const view = this.sourceView$.value;
|
|
1236
|
+
if (view)
|
|
1237
|
+
this.sourceView$.next({ ...view, taken });
|
|
1238
|
+
}
|
|
1239
|
+
/**
|
|
1240
|
+
* Look up (opening it if needed) the slice's source and publish it as the source view. The view
|
|
1241
|
+
* is withdrawn at once: until the incoming source opens, nothing reads, takes or deletes from the
|
|
1242
|
+
* outgoing one into the slice now shown.
|
|
1243
|
+
*/
|
|
1244
|
+
refreshSourceView() {
|
|
1245
|
+
const generation = ++this.sourceGeneration;
|
|
1246
|
+
const image = this.scope.activeImage;
|
|
1247
|
+
const slice = this.sourceSlice;
|
|
1248
|
+
if (this.sourceView$.value)
|
|
1249
|
+
this.sourceView$.next(null);
|
|
1250
|
+
this.sources.show(image, slice);
|
|
1251
|
+
if (!this.sources.has(image, slice)) {
|
|
1252
|
+
this.hintStyle = undefined;
|
|
1253
|
+
this.restyle();
|
|
1254
|
+
return;
|
|
1255
|
+
}
|
|
1256
|
+
this.sources.binding(image, slice).then((binding) => {
|
|
1257
|
+
if (generation !== this.sourceGeneration)
|
|
1258
|
+
return;
|
|
1259
|
+
if (!binding) {
|
|
1260
|
+
this.sourceView$.next(null);
|
|
1261
|
+
return;
|
|
1024
1262
|
}
|
|
1263
|
+
const info = binding.source.info;
|
|
1264
|
+
const classColors = Object.entries(info.classColors);
|
|
1265
|
+
if (classColors.length)
|
|
1266
|
+
this.store.rememberImportedClassColors(new Map(classColors));
|
|
1267
|
+
// A source that asks for labels gets them when it opens (the toggle still turns them off).
|
|
1268
|
+
const labelsOn = !!info.style?.labels && !this.showShapeLabel && this.shownSource !== binding.source;
|
|
1269
|
+
if (labelsOn)
|
|
1270
|
+
this.showShapeLabel = true;
|
|
1271
|
+
this.shownSource = binding.source;
|
|
1272
|
+
this.hintStyle = info.style;
|
|
1273
|
+
this.sourceView$.next({
|
|
1274
|
+
source: binding.source,
|
|
1275
|
+
plane: binding.plane,
|
|
1276
|
+
taken: this.sources.taken(image, slice),
|
|
1277
|
+
colorOf: (f) => f.label ? colorForLabel(f.label, this.store.getPresetSet()) : f.color || this.shapeColor,
|
|
1278
|
+
style: this.regionStyle$.value,
|
|
1279
|
+
labels: this.showShapeLabel,
|
|
1280
|
+
isHidden: (label) => this.isClassHidden(label),
|
|
1281
|
+
});
|
|
1282
|
+
this.restyle(labelsOn);
|
|
1283
|
+
}, (err) => {
|
|
1284
|
+
if (generation !== this.sourceGeneration)
|
|
1285
|
+
return;
|
|
1286
|
+
console.warn('[regions] could not open the region source', err);
|
|
1287
|
+
this.sourceView$.next(null);
|
|
1288
|
+
});
|
|
1289
|
+
}
|
|
1290
|
+
// ── per-image lifecycle ────────────────────────────────────────────────
|
|
1291
|
+
/**
|
|
1292
|
+
* Switch the active image: snapshot the outgoing regions, restore the
|
|
1293
|
+
* incoming image's (or [] if none), clear selection, and notify. Idempotent
|
|
1294
|
+
* for the same image (so repeated replots of one image keep its regions).
|
|
1295
|
+
*/
|
|
1296
|
+
setActiveImage(imageInfo) {
|
|
1297
|
+
// Switching images also ends any per-slice stack session (jit-ui#93).
|
|
1298
|
+
const incoming = this.scope.switchImage(RegionScopeCache.imageKey(imageInfo), this.regions);
|
|
1299
|
+
if (!incoming)
|
|
1300
|
+
return;
|
|
1301
|
+
this.regions = incoming;
|
|
1302
|
+
this.selection.replace([]);
|
|
1303
|
+
// Undo never crosses an image switch.
|
|
1304
|
+
this.resetUndoHistory();
|
|
1305
|
+
this.emitSelection();
|
|
1306
|
+
this.regionUpdate$.next(this.getRegions());
|
|
1307
|
+
this.refreshSourceView();
|
|
1308
|
+
}
|
|
1309
|
+
// ── internals ──────────────────────────────────────────────────────────
|
|
1310
|
+
/** Apply the preset set's class colours (see {@link applyPresetColors}),
|
|
1311
|
+
* promoting unknown classes into the shared store when the set asks for it. */
|
|
1312
|
+
withClassificationColors(regions, inPlace) {
|
|
1313
|
+
return applyPresetColors(regions, this.store.getPresetSet(), {
|
|
1314
|
+
inPlace,
|
|
1315
|
+
onPromote: (preset) => this.store.upsertClass(preset),
|
|
1316
|
+
});
|
|
1317
|
+
}
|
|
1318
|
+
syncCache() {
|
|
1319
|
+
this.scope.sync(this.regions);
|
|
1320
|
+
}
|
|
1321
|
+
emit() {
|
|
1322
|
+
// Live-edit listeners (e.g. the intensity-profile inset) react on EVERY
|
|
1323
|
+
// change — including per-frame during a batched drag — so they track the
|
|
1324
|
+
// region live. The main regionUpdate$ stays coalesced during a batch (fires
|
|
1325
|
+
// once on endBatch) to keep heavier consumers (Regions tab) calm.
|
|
1326
|
+
this.regionLiveEdit$.next(this.regions.slice());
|
|
1327
|
+
if (this.batchDepth > 0) {
|
|
1328
|
+
this.pendingEmit = true;
|
|
1329
|
+
return;
|
|
1025
1330
|
}
|
|
1026
|
-
|
|
1331
|
+
this.regionUpdate$.next(this.getRegions());
|
|
1332
|
+
}
|
|
1333
|
+
/** Project the selected ids onto the current regions (pruning gone ones);
|
|
1334
|
+
* emits only if the index set changed. */
|
|
1335
|
+
emitSelection() {
|
|
1336
|
+
this.selection.sync(this.regions);
|
|
1337
|
+
}
|
|
1338
|
+
findById(id) {
|
|
1339
|
+
return this.regions.find((r) => r.id === id);
|
|
1340
|
+
}
|
|
1341
|
+
indexOfId(id) {
|
|
1342
|
+
return this.regions.findIndex((r) => r.id === id);
|
|
1027
1343
|
}
|
|
1028
1344
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: RegionStore, deps: [{ token: i1.VisualizerStore }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1029
1345
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: RegionStore, providedIn: 'root' }); }
|
|
@@ -1032,4 +1348,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImpor
|
|
|
1032
1348
|
type: Injectable,
|
|
1033
1349
|
args: [{ providedIn: 'root' }]
|
|
1034
1350
|
}], ctorParameters: () => [{ type: i1.VisualizerStore }] });
|
|
1035
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVnaW9uLXN0b3JlLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3N0b3JlL3JlZ2lvbi1zdG9yZS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUFFLGVBQWUsRUFBYyxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFHNUQsT0FBTyxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLFlBQVksRUFBRSxhQUFhLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUMzRixPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDbEQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQzdELE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBR3hELE9BQU8sRUFBRSxVQUFVLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQzs7O0FBRWxFOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBbUJHO0FBRUgsTUFBTSxPQUFPLFdBQVc7YUFFRSxlQUFVLEdBQUcsRUFBRSxBQUFMLENBQU07YUFDaEIscUJBQWdCLEdBQUcsR0FBRyxBQUFOLENBQU87SUFrRi9DLFlBQW9CLEtBQXNCO1FBQXRCLFVBQUssR0FBTCxLQUFLLENBQWlCO1FBaEYxQztpQ0FDeUI7UUFDakIsc0JBQWlCLEdBQUcsSUFBSSxHQUFHLEVBQW9CLENBQUM7UUFFeEQsNERBQTREO1FBQ3BELFlBQU8sR0FBYSxFQUFFLENBQUM7UUFDL0IsZ0VBQWdFO1FBQ3hELG9CQUFlLEdBQWEsRUFBRSxDQUFDO1FBRXZDOzs7Ozs7Ozs7Ozs7O1dBYUc7UUFDSyxjQUFTLEdBQWUsRUFBRSxDQUFDO1FBQzNCLGNBQVMsR0FBZSxFQUFFLENBQUM7UUFDbkMsNEVBQTRFO1FBQ3BFLGtCQUFh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LEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEJlaGF2aW9yU3ViamVjdCwgT2JzZXJ2YWJsZSwgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuXG5pbXBvcnQgeyBJSW1hZ2VJbmZvIH0gZnJvbSAnLi4vY29udHJhY3RzL2ltYWdlLmNvbnRyYWN0JztcbmltcG9ydCB7IFJlZ2lvbiwgUmVjdGFuZ2xlLCBQb2x5Z29uLCBNdWx0aVBvbHlnb24sIGh5ZHJhdGVCb3VuZHMgfSBmcm9tICcuLi9tb2RlbHMvcmVnaW9uJztcbmltcG9ydCB7IFBsb3RVdGlsaXRpZXMgfSBmcm9tICcuLi9wbG90LnV0aWxpdGllcyc7XG5pbXBvcnQgeyBWaXN1YWxpemVyU3RvcmUgfSBmcm9tICcuL3Zpc3VhbGl6ZXItc3RvcmUuc2VydmljZSc7XG5pbXBvcnQgeyBkZWZhdWx0SGFuZGxlT2Zmc2V0cyB9IGZyb20gJy4uL21vZGVscy9iZXppZXInO1xuaW1wb3J0IHsgSVJlZ2lvblN0b3JlIH0gZnJvbSAnLi4vY29udHJhY3RzL3Zpc3VhbGl6ZXIuY29udHJhY3QnO1xuaW1wb3J0IHsgSVJlZ2lvbkVkaXRBcGkgfSBmcm9tICcuLi9jb250cmFjdHMvcmVnaW9uLXN0b3JlLmNvbnRyYWN0JztcbmltcG9ydCB7IGZpbmRQcmVzZXQsIGZhbGxiYWNrQ29sb3JGb3IgfSBmcm9tICcuL2NsYXNzLWNvbG9yLnV0aWwnO1xuXG4vKipcbiAqIEJhY2tlbmQtbmV1dHJhbCByZWdpb24gc3RvcmUg4oCUIHRoZSBzaW5nbGUgc291cmNlIG9mIHRydXRoIGZvciByZWdpb24gc3RhdGUuXG4gKlxuICogSG9sZHMgdGhlIG5ldXRyYWwge0BsaW5rIFJlZ2lvbn0gbW9kZWwgKG5ldmVyIGEgYmFja2VuZCdzIG93biBzaGFwZVxuICogcmVwcmVzZW50YXRpb24pLCBrZXllZCBwZXIgaW1hZ2Ugc28gcmVnaW9ucyBwZXJzaXN0IGFzIHRoZSB1c2VyIHN3aXRjaGVzXG4gKiBmaWxlcyBhbmQgc3Vydml2ZSBhIFBsb3RseeKHhE9wZW5TZWFkcmFnb24gYmFja2VuZCBzd2l0Y2ggKGJvdGggYmFja2VuZHMgcmVhZFxuICogYW5kIHdyaXRlICp0aGlzKiBzdG9yZSwgc28gbm8gbWlncmF0aW9uIGlzIG5lZWRlZCkuIEJhY2tlbmRzIG93biAqcmVuZGVyaW5nKlxuICogYW5kIHJlYWN0IHRvIHtAbGluayBnZXRSZWdpb25VcGRhdGVFdmVudH07IHRoaXMgc2VydmljZSBvd25zICpzdGF0ZSogYW5kIHRoZVxuICogZWRpdGluZyBvcGVyYXRpb25zLlxuICpcbiAqIEltcGxlbWVudHM6XG4gKiAgLSB7QGxpbmsgSVJlZ2lvblN0b3JlfSDigJQgdGhlIGNyb3NzLWJhY2tlbmQgQ1JVRC9zZWxlY3Rpb24vY29sb3VyIGNvbnRyYWN0XG4gKiAgICBldmVyeSBjb25zdW1lciAoUmVnaW9uIEVkaXRvciwgc2VnbWVudGF0aW9uLCBldGMuKSBhbHJlYWR5IHVzZXMuXG4gKiAgLSB7QGxpbmsgSVJlZ2lvbkVkaXRBcGl9IOKAlCBSZWdpb24tbmF0aXZlIGdlb21ldHJ5IGVkaXRzIChtb3ZlL3Jlc2l6ZSwgYW5kXG4gKiAgICBhZGQvZGVsZXRlL21vdmUgdmVydGV4KSB0aGUgT1NEIG92ZXJsYXkgZHJpdmVzLlxuICpcbiAqIENsYXNzaWZpY2F0aW9uIGNvbG91cnMgbGl2ZSBpbiB7QGxpbmsgVmlzdWFsaXplclN0b3JlfSAoc2hhcmVkIGJ5IGJvdGhcbiAqIGJhY2tlbmRzKTsgR2VvSlNPTiBpbXBvcnQvZXhwb3J0IGFuZCB0aGUgY2xvc2VkLXBvbHlnb24gcHJvamVjdGlvbiByZXVzZSB0aGVcbiAqIG5ldXRyYWwge0BsaW5rIFBsb3RVdGlsaXRpZXN9IGhlbHBlcnMuIEFsbCBjb29yZGluYXRlcyBhcmUgaW1hZ2UgcGl4ZWxzLlxuICovXG5ASW5qZWN0YWJsZSh7IHByb3ZpZGVkSW46ICdyb290JyB9KVxuZXhwb3J0IGNsYXNzIFJlZ2lvblN0b3JlIGltcGxlbWVudHMgSVJlZ2lvblN0b3JlLCBJUmVnaW9uRWRpdEFwaSB7XG5cbiAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgVU5ET19MSU1JVCA9IDEwO1xuICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBVTkRPX0NPQUxFU0NFX01TID0gMjUwO1xuXG4gIC8qKiBQZXItaW1hZ2UgcmVnaW9uIGNhY2hlLiBgcmVnaW9uc2AgaXMgYWx3YXlzIGEgc25hcHNob3Qgb2YgdGhlIGVudHJ5IGZvclxuICAgKiAgYGN1cnJlbnRJbWFnZUtleWAuICovXG4gIHByaXZhdGUgcmVnaW9uc0J5SW1hZ2VLZXkgPSBuZXcgTWFwPHN0cmluZywgUmVnaW9uW10+KCk7XG4gIHByaXZhdGUgY3VycmVudEltYWdlS2V5OiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gIC8qKiBUaGUgY3VycmVudCBpbWFnZSdzIHJlZ2lvbnMg4oCUIHRoZSBsaXZlLCBlZGl0ZWQgYXJyYXkuICovXG4gIHByaXZhdGUgcmVnaW9uczogUmVnaW9uW10gPSBbXTtcbiAgLyoqIExhc3Qgc2F2ZWQgc25hcHNob3QsIHJlc3RvcmFibGUgdmlhIHBsb3RQcmV2aW91c1NoYXBlcygpLiAqL1xuICBwcml2YXRlIHByZXZpb3VzUmVnaW9uczogUmVnaW9uW10gPSBbXTtcblxuICAvKipcbiAgICogVW5kby9yZWRvIGhpc3RvcnkgKGppdC11aSM4NSk6IHVwIHRvIHtAbGluayBVTkRPX0xJTUlUfSBzbmFwc2hvdHMgb2YgdGhlXG4gICAqIHJlZ2lvbiBzZXQsIGVhY2ggYSBkZWVwIGNsb25lIGNhcHR1cmVkIGltbWVkaWF0ZWx5ICpiZWZvcmUqIGFcbiAgICogcmVnaW9uLWVkaXRpbmcgYWN0aW9uLiB7QGxpbmsgdW5kb30gcG9wcyB0aGUgbmV3ZXN0IG9mZiBgdW5kb1N0YWNrYCwgcHVzaGVzXG4gICAqIHRoZSBjdXJyZW50IHN0YXRlIG9udG8gYHJlZG9TdGFja2AsIGFuZCByZXN0b3JlcyBpdCDigJQgc28gaXQgY2FuIGJlIGludm9rZWRcbiAgICogdXAgdG8ge0BsaW5rIFVORE9fTElNSVR9IHRpbWVzIGluIGEgcm93LiB7QGxpbmsgcmVkb30gaXMgdGhlIG1pcnJvci4gQW55IG5ld1xuICAgKiByZWdpb24gYWN0aW9uIGNsZWFycyBgcmVkb1N0YWNrYCAodGhlIHJlZG8gZnV0dXJlIGlzIG5vIGxvbmdlciByZWFjaGFibGUpLlxuICAgKlxuICAgKiBBIGNvbnRpbnVvdXMgZ2VzdHVyZSAoYSB3YW5kL2JydXNoL3ZlcnRleCBkcmFnIGNvbW1pdHMgdG8gdGhlIHN0b3JlIG1hbnlcbiAgICogdGltZXMpIGlzIGNvYWxlc2NlZCBpbnRvIGEgc2luZ2xlIGVudHJ5OiB0aGUgZmlyc3QgY29tbWl0IG9mIGEgYnVyc3RcbiAgICogY2FwdHVyZXMgdGhlIHByZS1idXJzdCBzdGF0ZSBhbmQgZXZlcnkgY29tbWl0IHdpdGhpblxuICAgKiB7QGxpbmsgVU5ET19DT0FMRVNDRV9NU30gb2YgdGhlIHByZXZpb3VzIG9uZSBpcyBmb2xkZWQgaW50byBpdC4gSGlzdG9yeVxuICAgKiBuZXZlciBjcm9zc2VzIGFuIGltYWdlIGxvYWQvc3dpdGNoIOKAlCB7QGxpbmsgcmVzZXRVbmRvSGlzdG9yeX0gY2xlYXJzIGl0LlxuICAgKi9cbiAgcHJpdmF0ZSB1bmRvU3RhY2s6IFJlZ2lvbltdW10gPSBbXTtcbiAgcHJpdmF0ZSByZWRvU3RhY2s6IFJlZ2lvbltdW10gPSBbXTtcbiAgLyoqIFRydWUgd2hpbGUgYSBjb2FsZXNjaW5nIGJ1cnN0IGlzIG9wZW4gKGZ1cnRoZXIgY29tbWl0cyBmb2xkIGludG8gaXQpLiAqL1xuICBwcml2YXRlIHVuZG9CdXJzdE9wZW4gPSBmYWxzZTtcbiAgcHJpdmF0ZSB1bmRvQnVyc3RUaW1lcjogUmV0dXJuVHlwZTx0eXBlb2Ygc2V0VGltZW91dD4gfCBudWxsID0gbnVsbDtcbiAgLyoqIFRydWUgd2hpbGUgcmVzdG9yaW5nIGEgc25hcHNob3QsIHNvIHRoZSByZXN0b3JlIHJlY29yZHMgbm8gbmV3IGhpc3RvcnkuICovXG4gIHByaXZhdGUgcmVzdG9yaW5nVW5kbyA9IGZhbHNlO1xuICBwcml2YXRlIHJlYWRvbmx5IGNhblVuZG8kID0gbmV3IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPihmYWxzZSk7XG4gIHByaXZhdGUgcmVhZG9ubHkgY2FuUmVkbyQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+KGZhbHNlKTtcblxuICAvKiogTW9ub3RvbmljIGlkIHNvdXJjZSDigJQgaWRzIG5ldmVyIHJlcGVhdCB3aXRoaW4gdGhlIHNlcnZpY2UgbGlmZXRpbWUsIHNvXG4gICAqICBzZWxlY3Rpb24gc3RheXMgY29ycmVjdCBhY3Jvc3MgZGVsZXRlL2FkZCBjeWNsZXMgZXZlbiB3aGVuIG5hbWVzIGNvbGxpZGUuICovXG4gIHByaXZhdGUgbmV4dElkID0gMTtcblxuICBwcml2YXRlIHNob3dTaGFwZUxhYmVsID0gZmFsc2U7XG4gIHByaXZhdGUgc2hhcGVDb2xvciA9ICcjMDBGRkZGJztcbiAgcHJpdmF0ZSBmaWxsQ29sb3IgPSAnI2ZmMDBmZic7XG4gIHByaXZhdGUgaXNSZWdpb25TYXZlZE9uID0gdHJ1ZTtcblxuICAvKipcbiAgICogUGVyLXNsaWNlIHJlZ2lvbiBzdXBwb3J0IGZvciB6LXN0YWNrcyAoaml0LXVpIzkzKS4gV2hpbGUge0BsaW5rIHN0YWNrTW9kZX1cbiAgICogaXMgb24gKGEgei1zdGFjayBpcyBsb2FkZWQpLCB0aGUgbGl2ZSBgcmVnaW9uc2AgYXJyYXkgYWx3YXlzIGhvbGRzIE9ORVxuICAgKiBzbGljZSDigJQgdGhlIHtAbGluayBjdXJyZW50U2xpY2VafSBzbGljZSDigJQgc28gdGhlIG9uLWNhbnZhcyBvdmVybGF5cywgdGhlXG4gICAqIHNlbGVjdGlvbiBwcm9qZWN0aW9uLCBhbmQgdGhlIFJlZ2lvbnMgdGFibGUga2VlcCB3b3JraW5nIHVuY2hhbmdlZFxuICAgKiAodGhleSBhbGwgcmVhZCB7QGxpbmsgZ2V0UmVnaW9uc30pLiBUaGUgb3RoZXIgc2xpY2VzIGxpdmUgaW5cbiAgICoge0BsaW5rIHJlZ2lvbnNCeVNsaWNlfTsge0BsaW5rIHNldERpc3BsYXlTbGljZX0gc3dhcHMgdGhlIGxpdmUgc2V0IG9uIHNjcnViXG4gICAqIGFuZCB7QGxpbmsgZ2V0U2xpY2VSZWdpb25zfSBmbGF0dGVucyBldmVyeSBzbGljZSAoZWFjaCB0YWdnZWQgd2l0aCBpdHNcbiAgICogemVyby1iYXNlZCB7QGxpbmsgUmVnaW9uLnp9KSBmb3Igc2F2ZS9leHBvcnQuIE9mZiBieSBkZWZhdWx0IChzdGFja01vZGVcbiAgICogZmFsc2UsIHogMCksIHNvIHNpbmdsZS1wbGFuZSBpbWFnZXMgYXJlIGNvbXBsZXRlbHkgdW5hZmZlY3RlZC5cbiAgICovXG4gIHByaXZhdGUgcmVnaW9uc0J5U2xpY2UgPSBuZXcgTWFwPG51bWJlciwgUmVnaW9uW10+KCk7XG4gIHByaXZhdGUgc3RhY2tNb2RlID0gZmFsc2U7XG4gIHByaXZhdGUgY3VycmVudFNsaWNlWiA9IDA7XG4gIC8qKiBIb3cgYSBzdGFjaydzIHJlZ2lvbnMgcm91bmQtdHJpcCB0byBkaXNrIChqaXQtdWkjOTMpOiBgY29tYmluZWRgIHdyaXRlcyBvbmVcbiAgICogIHotaW5kZXhlZCBnZW9qc29uIChzaW5nbGUtZmlsZSB6LXN0YWNrLCBRdVBhdGggc2NoZW1hKTsgYHBlci1zbGljZS1maWxlYFxuICAgKiAgd3JpdGVzIG9uZSBnZW9qc29uIHBlciBzbGljZS1maWxlIChhIGZvbGRlciBvZiBudW1iZXJlZCBpbWFnZXMpLiAqL1xuICBwcml2YXRlIHN0YWNrU2F2ZUxheW91dDogJ2NvbWJpbmVkJyB8ICdwZXItc2xpY2UtZmlsZScgPSAnY29tYmluZWQnO1xuICAvKiogU2xpY2VzIHRoYXQgd2VyZSBsb2FkZWQgd2l0aCByZWdpb25zIChqaXQtdWkjOTMpLiBBIHBlci1zbGljZS1maWxlIHNhdmVcbiAgICogIHJlLXdyaXRlcyB0aGVzZSBldmVuIHdoZW4gbm93IGVtcHR5LCBzbyBjbGVhcmluZyBhIHNsaWNlJ3MgcmVnaW9ucyBhbmRcbiAgICogIHNhdmluZyByZW1vdmVzIGl0cyBwcmV2aW91c2x5LXNhdmVkIGdlb2pzb24gKHdyaXRlcyBhbiBlbXB0eSBvbmUpLiAqL1xuICBwcml2YXRlIHN0YWNrSW5pdGlhbE5vbkVtcHR5ID0gbmV3IFNldDxudW1iZXI+KCk7XG5cbiAgLyoqIFNlbGVjdGlvbiBpcyB0cmFja2VkIGJ5IHJlZ2lvbiAqaWQqIGludGVybmFsbHkgKHN0YWJsZSBhY3Jvc3MgZWRpdHMpIGFuZFxuICAgKiAgcHJvamVjdGVkIHRvIGFycmF5IGluZGljZXMgb24gdGhlIElSZWdpb25TdG9yZSBib3VuZGFyeS4gKi9cbiAgcHJpdmF0ZSBzZWxlY3RlZElkczogbnVtYmVyW10gPSBbXTtcbiAgcHJpdmF0ZSByZWFkb25seSBzZWxlY3RlZEluZGljZXMkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxudW1iZXJbXT4oW10pO1xuICBwcml2YXRlIHJlYWRvbmx5IHJlZ2lvblVwZGF0ZSQgPSBuZXcgU3ViamVjdDxSZWdpb25bXT4oKTtcbiAgLyoqIE5vbi1jb2FsZXNjZWQgc2libGluZyBvZiByZWdpb25VcGRhdGUkOiBmaXJlcyBvbiBldmVyeSBjaGFuZ2UgZXZlbiBkdXJpbmcgYVxuICAgKiAgYmF0Y2hlZCBkcmFnLCBzbyBsaXZlIGNvbnN1bWVycyAoaW50ZW5zaXR5IGluc2V0KSB1cGRhdGUgcGVyIGZyYW1lLiAqL1xuICBwcml2YXRlIHJlYWRvbmx5IHJlZ2lvbkxpdmVFZGl0JCA9IG5ldyBTdWJqZWN0PFJlZ2lvbltdPigpO1xuXG4gIC8qKiBFbWl0IGNvYWxlc2NpbmcgZm9yIGxpdmUgZHJhZ3MgKHNlZSBJUmVnaW9uRWRpdEFwaS5iZWdpbkJhdGNoKS4gKi9cbiAgcHJpdmF0ZSBiYXRjaERlcHRoID0gMDtcbiAgcHJpdmF0ZSBwZW5kaW5nRW1pdCA9IGZhbHNlO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgcGxvdFV0aWxpdGllcyA9IG5ldyBQbG90VXRpbGl0aWVzKCk7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBzdG9yZTogVmlzdWFsaXplclN0b3JlKSB7fVxuXG4gIC8vIOKUgOKUgCBJUmVnaW9uU3RvcmU6IENSVUQg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgLyoqXG4gICAqIFJlcGxhY2UgKG9yLCB3aXRoIGBhcHBlbmRgLCBhZGQgdG8pIHRoZSBjdXJyZW50IGltYWdlJ3MgcmVnaW9ucy4gTWludHMgaWRzXG4gICAqIGFuZCBkZWZhdWx0IG5hbWVzLCBhcHBsaWVzIHN0b3JlZCBjbGFzc2lmaWNhdGlvbiBjb2xvdXJzLCBhbmQgZW1pdHMuIFdoZW5cbiAgICogYGlzUmVnaW9uU2F2ZU9uYCBpcyBmYWxzZSB0aGUgcmVnaW9ucyBhcmUgc2hvd24gdHJhbnNpZW50bHkgKGVtaXR0ZWQpIGJ1dFxuICAgKiBub3Qgc3RvcmVkIOKAlCBtaXJyb3JzIHRoZSBwcmV2aW91cyBQbG90bHkgYmVoYXZpb3VyLlxuICAgKi9cbiAgc2V0UmVnaW9ucyhyZWdpb25zOiBSZWdpb25bXSwgc2hvd1JlZ2lvbkxhYmVsPzogYm9vbGVhbiwgaXNSZWdpb25TYXZlT24/OiBib29sZWFuLFxuICAgICAgICAgICAgIGZpbGxDb2xvcj86IHN0cmluZywgYXBwZW5kOiBib29sZWFuID0gZmFsc2UpOiB2b2lkIHtcbiAgICBpZiAoc2hvd1JlZ2lvbkxhYmVsID09PSB1bmRlZmluZWQpIHNob3dSZWdpb25MYWJlbCA9IHRoaXMuc2hvd1NoYXBlTGFiZWw7XG4gICAgaWYgKGlzUmVnaW9uU2F2ZU9uID09PSB1bmRlZmluZWQpIGlzUmVnaW9uU2F2ZU9uID0gdGhpcy5pc1JlZ2lvblNhdmVkT247XG4gICAgaWYgKGZpbGxDb2xvciA9PT0gdW5kZWZpbmVkKSBmaWxsQ29sb3IgPSB0aGlzLmZpbGxDb2xvcjtcblxuICAgIGZvciAoY29uc3QgcmVnaW9uIG9mIHJlZ2lvbnMpIHtcbiAgICAgIGlmIChyZWdpb24uaWQgPT0gbnVsbCkgcmVnaW9uLmlkID0gdGhpcy5uZXh0SWQrKztcbiAgICAgIGlmIChyZWdpb24ubmFtZSA9PSBudWxsKSByZWdpb24ubmFtZSA9IGBzaGFwZSR7cmVnaW9uLmlkfWA7XG4gICAgICAvLyBKU09OIGluLCBjbGFzcyBpbnN0YW5jZXMgb3V0IOKAlCBldmVyeXRoaW5nIGRvd25zdHJlYW0gKHRoZSBvdmVybGF5cydcbiAgICAgIC8vIHJlbmRlcmluZywgZ2VvbWV0cnkgZGUtZHVwLCBtb3ZlUmVnaW9uLCBHZW9KU09OIGV4cG9ydCkgZGlzY3JpbWluYXRlc1xuICAgICAgLy8gdGhlIGJvdW5kcyB3aXRoIGBpbnN0YW5jZW9mYCAoaml0LXVpIzEyNCkuXG4gICAgICByZWdpb24uYm91bmRzID0gaHlkcmF0ZUJvdW5kcyhyZWdpb24uYm91bmRzKTtcbiAgICB9XG4gICAgdGhpcy5hcHBseUNsYXNzaWZpY2F0aW9uQ29sb3JzKHJlZ2lvbnMpO1xuXG4gICAgdGhpcy5pc1JlZ2lvblNhdmVkT24gPSBpc1JlZ2lvblNhdmVPbjtcbiAgICBpZiAoaXNSZWdpb25TYXZlT24pIHtcbiAgICAgIHRoaXMucmVjb3JkVW5kb1NuYXBzaG90KCk7XG4gICAgICB0aGlzLnNob3dTaGFwZUxhYmVsID0gc2hvd1JlZ2lvbkxhYmVsO1xuICAgICAgdGhpcy5maWxsQ29sb3IgPSBmaWxsQ29sb3I7XG4gICAgICBpZiAoYXBwZW5kKSB7XG4gICAgICAgIC8vIFJlamVjdCBieSBpZCBjb2xsaXNpb24gKGFscmVhZHkgdHJhY2tlZCkgb3IgZ2VvbWV0cnkgZXF1YWxpdHkgKHNhbWVcbiAgICAgICAgLy8gY29vcmRpbmF0ZXMpIOKAlCB0aGUgZmluZCBidXR0b24gY2FuIHB1c2ggdGhlIHNhbWUgcmVnaW9uIHJlcGVhdGVkbHkuXG4gICAgICAgIGNvbnN0IGFkZGVkID0gcmVnaW9ucy5maWx0ZXIociA9PlxuICAgICAgICAgICF0aGlzLnJlZ2lvbnMuc29tZShleGlzdGluZyA9PiBleGlzdGluZy5pZCA9PT0gci5pZCB8fCB0aGlzLnJlZ2lvbnNFcXVhbChleGlzdGluZywgcikpKTtcbiAgICAgICAgdGhpcy5yZWdpb25zID0gdGhpcy5yZWdpb25zLmNvbmNhdChhZGRlZCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnJlZ2lvbnMgPSByZWdpb25zLnNsaWNlKCk7XG4gICAgICB9XG4gICAgICB0aGlzLnN5bmNDYWNoZSgpO1xuICAgICAgdGhpcy5lbWl0U2VsZWN0aW9uKCk7XG4gICAgICB0aGlzLmVtaXQoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gVHJhbnNpZW50IGRpc3BsYXkgb25seSDigJQgZG9uJ3QgdG91Y2ggc3RvcmVkIHN0YXRlLlxuICAgICAgdGhpcy5yZWdpb25VcGRhdGUkLm5leHQocmVnaW9ucy5zbGljZSgpKTtcbiAgICB9XG4gIH1cblxuICAvKiogVGhlIGNhbm9uaWNhbCBhY2Nlc3NvcjogY3VycmVudCBpbWFnZSdzIHJlZ2lvbnMgKGxpdmUgaW5zdGFuY2VzKS4gKi9cbiAgZ2V0UmVnaW9ucygpOiBSZWdpb25bXSB7XG4gICAgcmV0dXJuIHRoaXMucmVnaW9ucy5zbGljZSgpO1xuICB9XG5cbiAgLy8g4pSA4pSAIFBlci1zbGljZSByZWdpb25zIGZvciB6LXN0YWNrcyAoaml0LXVpIzkzKSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICAvKiogVHJ1ZSB3aGlsZSBhIHotc3RhY2sgaXMgbG9hZGVkIGFuZCB0aGUgc3RvcmUgaG9sZHMgcmVnaW9ucyBwZXIgc2xpY2UuICovXG4gIGlzU3RhY2tNb2RlKCk6IGJvb2xlYW4geyByZXR1cm4gdGhpcy5zdGFja01vZGU7IH1cblxuICAvKiogVGhlIGN1cnJlbnQgZGlzcGxheSBzbGljZSAoemVyby1iYXNlZCkuICovXG4gIGdldERpc3BsYXlTbGljZSgpOiBudW1iZXIgeyByZXR1cm4gdGhpcy5jdXJyZW50U2xpY2VaOyB9XG5cbiAgLyoqIEhvdyB0aGUgY3VycmVudCBzdGFjayBwZXJzaXN0cyB0byBkaXNrIChqaXQtdWkjOTMpOiBgY29tYmluZWRgID0gb25lXG4gICAqICB6LWluZGV4ZWQgZ2VvanNvbiAoc2luZ2xlLWZpbGUgei1zdGFjayk7IGBwZXItc2xpY2UtZmlsZWAgPSBvbmUgZ2VvanNvbiBwZXJcbiAgICogIHNsaWNlLWZpbGUgKGZvbGRlciBzdGFjaykuIE1lYW5pbmdsZXNzIG91dHNpZGUgc3RhY2sgbW9kZS4gKi9cbiAgZ2V0U3RhY2tTYXZlTGF5b3V0KCk6ICdjb21iaW5lZCcgfCAncGVyLXNsaWNlLWZpbGUnIHsgcmV0dXJuIHRoaXMuc3RhY2tTYXZlTGF5b3V0OyB9XG5cbiAgLyoqXG4gICAqIEVudGVyIHBlci1zbGljZSBzdGFjayBtb2RlLiBgc2xpY2VzYCBtYXBzIGVhY2ggemVyby1iYXNlZCBzbGljZSBpbmRleCB0b1xuICAgKiB0aGUgcmVnaW9ucyBpbXBvcnRlZCBmb3IgdGhhdCBzbGljZTsgdGhlIHN0b3JlIG1ha2VzIGBpbml0aWFsWmAncyBzbGljZSB0aGVcbiAgICogbGl2ZSBzZXQsIHNvIHRoZSBvdmVybGF5cyAvIHNlbGVjdGlvbiAvIFJlZ2lvbnMgdGFibGUgYXJlIHVuY2hhbmdlZCAodGhleVxuICAgKiBzdGlsbCByZWFkIHtAbGluayBnZXRSZWdpb25zfSkuIEZyZXNobHktY3JlYXRlZCByZWdpb25zIGFyZSB0YWdnZWQgd2l0aCB0aGVcbiAgICogY3VycmVudCBzbGljZSBzbyB0aGV5IHBlcnNpc3Qgb24gaXQsIGFuZCB7QGxpbmsgZ2V0U2xpY2VSZWdpb25zfSByZXR1cm5zXG4gICAqIGV2ZXJ5IHNsaWNlIGZvciBzYXZlL2V4cG9ydC4gSWRzL25hbWVzL2NsYXNzaWZpY2F0aW9uIGNvbG91cnMgYXJlIG1pbnRlZFxuICAgKiBleGFjdGx5IGFzIHtAbGluayBzZXRSZWdpb25zfSBkb2VzLlxuICAgKi9cbiAgZW50ZXJTdGFja01vZGUoc2xpY2VzOiBNYXA8bnVtYmVyLCBSZWdpb25bXT4sIGluaXRpYWxaID0gMCxcbiAgICAgICAgICAgICAgICAgc2F2ZUxheW91dDogJ2NvbWJpbmVkJyB8ICdwZXItc2xpY2UtZmlsZScgPSAnY29tYmluZWQnKTogdm9pZCB7XG4gICAgdGhpcy5zdGFja01vZGUgPSB0cnVlO1xuICAgIHRoaXMuc3RhY2tTYXZlTGF5b3V0ID0gc2F2ZUxheW91dDtcbiAgICB0aGlzLmN1cnJlbnRTbGljZVogPSBpbml0aWFsWiB8fCAwO1xuICAgIHRoaXMucmVnaW9uc0J5U2xpY2UgPSBuZXcgTWFwPG51bWJlciwgUmVnaW9uW10+KCk7XG4gICAgdGhpcy5zdGFja0luaXRpYWxOb25FbXB0eSA9IG5ldyBTZXQ8bnVtYmVyPigpO1xuICAgIGZvciAoY29uc3QgW3osIHJlZ3NdIG9mIHNsaWNlcykge1xuICAgICAgY29uc3Qgbm9ybWFsaXplZCA9IHRoaXMubm9ybWFsaXplU2xpY2UocmVncyB8fCBbXSwgeik7XG4gICAgICB0aGlzLnJlZ2lvbnNCeVNsaWNlLnNldCh6LCBub3JtYWxpemVkKTtcbiAgICAgIGlmIChub3JtYWxpemVkLmxlbmd0aCkgdGhpcy5zdGFja0luaXRpYWxOb25FbXB0eS5hZGQoeik7XG4gICAgfVxuICAgIHRoaXMucmVnaW9ucyA9ICh0aGlzLnJlZ2lvbnNCeVNsaWNlLmdldCh0aGlzLmN1cnJlbnRTbGljZVopID8/IFtdKS5zbGljZSgpO1xuICAgIHRoaXMucHJldmlvdXNSZWdpb25zID0gdGhpcy5yZWdpb25zLnNsaWNlKCk7XG4gICAgdGhpcy5zZWxlY3RlZElkcyA9IFtdO1xuICAgIHRoaXMuc3luY0NhY2hlKCk7XG4gICAgdGhpcy5yZXNldFVuZG9IaXN0b3J5KCk7XG4gICAgdGhpcy5lbWl0U2VsZWN0aW9uKCk7XG4gICAgdGhpcy5lbWl0KCk7XG4gIH1cblxuICAvKiogTGVhdmUgc3RhY2sgbW9kZSAoc2luZ2xlLXBsYW5lIGltYWdlLCBvciB0aGUgc3RhY2sgd2FzIGNsb3NlZCkuICovXG4gIGV4aXRTdGFja01vZGUoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLnN0YWNrTW9kZSkgcmV0dXJuO1xuICAgIHRoaXMuc3RhY2tNb2RlID0gZmFsc2U7XG4gICAgdGhpcy5jdXJyZW50U2xpY2VaID0gMDtcbiAgICB0aGlzLnJlZ2lvbnNCeVNsaWNlID0gbmV3IE1hcDxudW1iZXIsIFJlZ2lvbltdPigpO1xuICAgIHRoaXMuc3RhY2tJbml0aWFsTm9uRW1wdHkgPSBuZXcgU2V0PG51bWJlcj4oKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTaG93IGEgZGlmZmVyZW50IHNsaWNlOiBjYXB0dXJlIHRoZSBjdXJyZW50IHNsaWNlJ3MgKHBvc3NpYmx5IGVkaXRlZClcbiAgICogcmVnaW9ucyBiYWNrIGludG8gdGhlIHBlci1zbGljZSBzdG9yZSwgdGhlbiBsb2FkIHRoZSB0YXJnZXQgc2xpY2UncyByZWdpb25zXG4gICAqIGFzIHRoZSBsaXZlIHNldCBhbmQgZW1pdC4gVW5kbyBuZXZlciBjcm9zc2VzIGEgc2xpY2UuIE91dHNpZGUgc3RhY2sgbW9kZVxuICAgKiB0aGlzIG9ubHkgcmVjb3JkcyB0aGUgcmVxdWVzdGVkIHNsaWNlIGluZGV4IChhIG5vLW9wIG90aGVyd2lzZTogc2luZ2xlLXBsYW5lXG4gICAqIHJlZ2lvbnMgc3RheSBvbiB0aGUgZGVmYXVsdCBwbGFuZSDigJQgYWRkUmVnaW9uIHRhZ3MgUmVnaW9uLnogb25seSBpbiBzdGFja1xuICAgKiBtb2RlLCBzbyB0aGUgcmVjb3JkZWQgaW5kZXggaXMgdW51c2VkIHVudGlsIGEgc3RhY2sgaXMgZW50ZXJlZCkuIChqaXQtdWkjOTMpXG4gICAqL1xuICBzZXREaXNwbGF5U2xpY2UoejogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3QgbmV4dCA9IHogfHwgMDtcbiAgICBpZiAoIXRoaXMuc3RhY2tNb2RlKSB7IHRoaXMuY3VycmVudFNsaWNlWiA9IG5leHQ7IHJldHVybjsgfVxuICAgIGlmICh0aGlzLmN1cnJlbnRTbGljZVogPT09IG5leHQpIHJldHVybjtcbiAgICB0aGlzLnJlZ2lvbnNCeVNsaWNlLnNldCh0aGlzLmN1cnJlbnRTbGljZVosIHRoaXMucmVnaW9ucy5zbGljZSgpKTtcbiAgICB0aGlzLmN1cnJlbnRTbGljZVogPSBuZXh0O1xuICAgIHRoaXMucmVnaW9ucyA9ICh0aGlzLnJlZ2lvbnNCeVNsaWNlLmdldChuZXh0KSA/PyBbXSkuc2xpY2UoKTtcbiAgICB0aGlzLnByZXZpb3VzUmVnaW9ucyA9IHRoaXMucmVnaW9ucy5zbGljZSgpO1xuICAgIHRoaXMuc2VsZWN0ZWRJZHMgPSBbXTtcbiAgICB0aGlzLnN5bmNDYWNoZSgpO1xuICAgIHRoaXMucmVzZXRVbmRvSGlzdG9yeSgpO1xuICAgIHRoaXMuZW1pdFNlbGVjdGlvbigpO1xuICAgIHRoaXMuZW1pdCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEV2ZXJ5IHNsaWNlJ3MgcmVnaW9ucyBmb3Igc2F2ZS9leHBvcnQsIGVhY2ggdGFnZ2VkIHdpdGggaXRzIHplcm8tYmFzZWRcbiAgICogc2xpY2UgaW5kZXggaW4ge0BsaW5rIFJlZ2lvbi56fS4gQ2FwdHVyZXMgdGhlIGN1cnJlbnQgc2xpY2UncyBsaXZlIGVkaXRzXG4gICAqIGZpcnN0LiBSZXR1cm5zIHRoZSBmbGF0IHNpbmdsZS1wbGFuZSBzZXQgd2hlbiBub3QgaW4gc3RhY2sgbW9kZS4gKGppdC11aSM5MylcbiAgICovXG4gIGdldFNsaWNlUmVnaW9ucygpOiBSZWdpb25bXSB7XG4gICAgaWYgKCF0aGlzLnN0YWNrTW9kZSkgcmV0dXJuIHRoaXMucmVnaW9ucy5zbGljZSgpO1xuICAgIHRoaXMucmVnaW9uc0J5U2xpY2Uuc2V0KHRoaXMuY3VycmVudFNsaWNlWiwgdGhpcy5yZWdpb25zLnNsaWNlKCkpO1xuICAgIGNvbnN0IG91dDogUmVnaW9uW10gPSBbXTtcbiAgICBjb25zdCB6cyA9IEFycmF5LmZyb20odGhpcy5yZWdpb25zQnlTbGljZS5rZXlzKCkpLnNvcnQoKGEsIGIpID0+IGEgLSBiKTtcbiAgICBmb3IgKGNvbnN0IHogb2YgenMpIHtcbiAgICAgIGZvciAoY29uc3QgciBvZiB0aGlzLnJlZ2lvbnNCeVNsaWNlLmdldCh6KSBhcyBSZWdpb25bXSkge1xuICAgICAgICByLnogPSB6O1xuICAgICAgICBvdXQucHVzaChyKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG91dDtcbiAgfVxuXG4gIC8qKlxuICAgKiBTbGljZXMgdG8gd3JpdGUgb24gYSBwZXItc2xpY2UtZmlsZSBzYXZlIChmb2xkZXIgc3RhY2ssIGppdC11aSM5Myk6IGV2ZXJ5XG4gICAqIHNsaWNlIHRoYXQgY3VycmVudGx5IGhhcyByZWdpb25zLCBQTFVTIHNsaWNlcyB0aGF0IHdlcmUgbG9hZGVkIG5vbi1lbXB0eSBidXRcbiAgICogYXJlIG5vdyBlbXB0eSAoc28gdGhlaXIgZmlsZSBpcyByZS13cml0dGVuIGVtcHR5LCBjbGVhcmluZyBhIHNsaWNlIHdob3NlXG4gICAqIHJlZ2lvbnMgdGhlIHVzZXIgZGVsZXRlZCkuIEVhY2ggcmV0dXJuZWQgcmVnaW9uIGlzIHRhZ2dlZCB3aXRoIGl0cyB6LCBhbmRcbiAgICogdGhlIGN1cnJlbnQgbGl2ZSBzbGljZSBpcyBjYXB0dXJlZCBmaXJzdC4gRW1wdHkgb3V0c2lkZSBzdGFjayBtb2RlLlxuICAgKi9cbiAgZ2V0U3RhY2tTYXZlU2xpY2VzKCk6IE1hcDxudW1iZXIsIFJlZ2lvbltdPiB7XG4gICAgY29uc3Qgb3V0ID0gbmV3IE1hcDxudW1iZXIsIFJlZ2lvbltdPigpO1xuICAgIGlmICghdGhpcy5zdGFja01vZGUpIHJldHVybiBvdXQ7XG4gICAgdGhpcy5yZWdpb25zQnlTbGljZS5zZXQodGhpcy5jdXJyZW50U2xpY2VaLCB0aGlzLnJlZ2lvbnMuc2xpY2UoKSk7XG4gICAgY29uc3QgenMgPSBuZXcgU2V0PG51bWJlcj4odGhpcy5zdGFja0luaXRpYWxOb25FbXB0eSk7XG4gICAgZm9yIChjb25zdCBbeiwgcmVnc10gb2YgdGhpcy5yZWdpb25zQnlTbGljZSkgaWYgKHJlZ3MubGVuZ3RoKSB6cy5hZGQoeik7XG4gICAgZm9yIChjb25zdCB6IG9mIEFycmF5LmZyb20oenMpLnNvcnQoKGEsIGIpID0+IGEgLSBiKSkge1xuICAgICAgY29uc3QgcmVncyA9ICh0aGlzLnJlZ2lvbnNCeVNsaWNlLmdldCh6KSA/PyBbXSkubWFwKChyKSA9PiB7IHIueiA9IHo7IHJldHVybiByOyB9KTtcbiAgICAgIG91dC5zZXQoeiwgcmVncyk7XG4gICAgfVxuICAgIHJldHVybiBvdXQ7XG4gIH1cblxuICAvKiogTWludCBpZHMvbmFtZXMgKyBhcHBseSBjbGFzc2lmaWNhdGlvbiBjb2xvdXJzICsgdGFnIHRoZSBzbGljZSBpbmRleCwgYXNcbiAgICogIHtAbGluayBzZXRSZWdpb25zfSBkb2VzLCBmb3IgcmVnaW9ucyBlbnRlcmluZyB0aGUgcGVyLXNsaWNlIHN0b3JlLiAqL1xuICBwcml2YXRlIG5vcm1hbGl6ZVNsaWNlKHJlZ2lvbnM6IFJlZ2lvbltdLCB6OiBudW1iZXIpOiBSZWdpb25bXSB7XG4gICAgZm9yIChjb25zdCByZWdpb24gb2YgcmVnaW9ucykge1xuICAgICAgaWYgKHJlZ2lvbi5pZCA9PSBudWxsKSByZWdpb24uaWQgPSB0aGlzLm5leHRJZCsrO1xuICAgICAgaWYgKHJlZ2lvbi5uYW1lID09IG51bGwpIHJlZ2lvbi5uYW1lID0gYHNoYXBlJHtyZWdpb24uaWR9YDtcbiAgICAgIHJlZ2lvbi56ID0gejtcbiAgICAgIHJlZ2lvbi5ib3VuZHMgPSBoeWRyYXRlQm91bmRzKHJlZ2lvbi5ib3VuZHMpOyAgIC8vIGppdC11aSMxMjRcbiAgICB9XG4gICAgdGhpcy5hcHBseUNsYXNzaWZpY2F0aW9uQ29sb3JzKHJlZ2lvbnMpO1xuICAgIHJldHVybiByZWdpb25zLnNsaWNlKCk7XG4gIH1cblxuICAvKipcbiAgICogQ2xvc2VkIHBvbHlnb25zIHByb2plY3RlZCBmb3IgaW1hZ2UtcHJvY2Vzc2luZyBjb25zdW1lcnMgKHNlZ21lbnRhdGlvbixcbiAgICogdHJhY2UgYnVpbGRlcnMpLiBPcGVuIHBvbHlsaW5lcyBhcmUgYW5ub3RhdGlvbi1vbmx5IGFuZCBleGNsdWRlZC4gUmV1c2VzXG4gICAqIHRoZSBuZXV0cmFsIFBsb3RVdGlsaXRpZXMgcHJvamVjdGlvbiBzbyBvdXRwdXQgbWF0Y2hlcyB0aGUgcHJldmlvdXMgcGF0aC5cbiAgICovXG4gIGdldFJlZ2lvblBvbHlnb25zKCk6IGFueVtdIHtcbiAgICBjb25zdCByZXQ6IGFueVtdID0gW107XG4gICAgZm9yIChjb25zdCByZWdpb24gb2YgdGhpcy5yZWdpb25zKSB7XG4gICAgICBjb25zdCBwb2x5OiBhbnkgPSB0aGlzLnBsb3RVdGlsaXRpZXMuZ2V0UG9seWdvbih7IC4uLnJlZ2lvbi5nZXRTaGFwZSh0aGlzLnNob3dTaGFwZUxhYmVsKSB9KTtcbiAgICAgIGlmIChwb2x5ID09IG51bGwgfHwgcG9seS5jbG9zZWQgPT09IGZhbHNlKSBjb250aW51ZTtcbiAgICAgIHJldC5wdXNoKHBvbHkpO1xuICAgIH1cbiAgICByZXR1cm4gcmV0O1xuICB9XG5cbiAgZ2V0UmVnaW9uVXBkYXRlRXZlbnQoKTogT2JzZXJ2YWJsZTxhbnlbXT4ge1xuICAgIHJldHVybiB0aGlzLnJlZ2lvblVwZGF0ZSQuYXNPYnNlcnZhYmxlKCk7XG4gIH1cblxuICAvKiogTGl2ZSAobm9uLWNvYWxlc2NlZCkgcmVnaW9uLWNoYW5nZSBzdHJlYW0g4oCUIGZpcmVzIHBlciBmcmFtZSBkdXJpbmcgYSBkcmFnLlxuICAgKiAgVXNlZCBieSB0aGUgaW50ZW5zaXR5LXByb2ZpbGUgaW5zZXQgc28gaXQgdHJhY2tzIGxpbmUgUk9JcyBsaXZlLiAqL1xuICBnZXRSZWdpb25MaXZlRWRpdCQoKTogT2JzZXJ2YWJsZTxSZWdpb25bXT4ge1xuICAgIHJldHVybiB0aGlzLnJlZ2lvbkxpdmVFZGl0JC5hc09ic2VydmFibGUoKTtcbiAgfVxuXG4gIC8vIOKUgOKUgCBJUmVnaW9uU3RvcmU6IHNlbGVjdGlvbiDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICAvKiogU2VsZWN0IHJlZ2lvbnMgYnkgYXJyYXkgaW5kZXggKG9yIFtdIHRvIGNsZWFyKS4gU3RvcmVkIGludGVybmFsbHkgYnkgaWRcbiAgICogIHNvIHRoZSBzZWxlY3Rpb24gc3Vydml2ZXMgc3Vic2VxdWVudCBlZGl0cy9yZW9yZGVycy4gKi9cbiAgc2V0U2VsZWN0ZWRTaGFwZUluZGljZXMoaW5kaWNlczogbnVtYmVyW10pOiB2b2lkIHtcbiAgICBjb25zdCBpZHM6IG51bWJlcltdID0gW107XG4gICAgY29uc3Qgc2VlbiA9IG5ldyBTZXQ8bnVtYmVyPigpO1xuICAgIGZvciAoY29uc3QgaSBvZiBpbmRpY2VzIHx8IFtdKSB7XG4gICAgICBpZiAoIU51bWJlci5pc0Zpbml0ZShpKSB8fCBpIDwgMCB8fCBpID49IHRoaXMucmVnaW9ucy5sZW5ndGgpIGNvbnRpbnVlO1xuICAgICAgY29uc3QgaWQgPSB0aGlzLnJlZ2lvbnNbaV0uaWQ7XG4gICAgICBpZiAoIXNlZW4uaGFzKGlkKSkgeyBzZWVuLmFkZChpZCk7IGlkcy5wdXNoKGlkKTsgfVxuICAgIH1cbiAgICB0aGlzLnNlbGVjdGVkSWRzID0gaWRzO1xuICAgIHRoaXMuZW1pdFNlbGVjdGlvbigpO1xuICB9XG5cbiAgLyoqIFNlbGVjdCBhIHNpbmdsZSByZWdpb24gYnkgaWRlbnRpdHkgKGlkKS4gQmFja2VuZHMgY2FsbCB0aGlzIGZyb20gdGhlaXJcbiAgICogIGBzZWxlY3RSZWdpb24oKWA7IHRoZSBPU0Qgb3ZlcmxheSArIHJlZ2lvbiBlZGl0b3IgaGlnaGxpZ2h0IG9mZiB0aGVcbiAgICogIHJlc3VsdGluZyBzZWxlY3Rpb24gZW1pdC4gTm8tb3AgaWYgdGhlIHJlZ2lvbiBpc24ndCBpbiB0aGUgc3RvcmUuICovXG4gIHNlbGVjdFJlZ2lvbihyZWdpb246IFJlZ2lvbik6IHZvaWQge1xuICAgIGlmIChyZWdpb24/LmlkID09IG51bGwgfHwgdGhpcy5pbmRleE9mSWQocmVnaW9uLmlkKSA8IDApIHJldHVybjtcbiAgICB0aGlzLnNlbGVjdGVkSWRzID0gW3JlZ2lvbi5pZF07XG4gICAgdGhpcy5lbWl0U2VsZWN0aW9uKCk7XG4gIH1cblxuICBnZXRTZWxlY3RlZFNoYXBlSW5kaWNlcyQoKTogT2JzZXJ2YWJsZTxudW1iZXJbXT4ge1xuICAgIHJldHVybiB0aGlzLnNlbGVjdGVkSW5kaWNlcyQuYXNPYnNlcnZhYmxlKCk7XG4gIH1cblxuICAvKiogU3luY2hyb25vdXMgY3VycmVudCBzZWxlY3Rpb24gKGFycmF5IGluZGljZXMpIOKAlCBmb3IgY2FsbGVycyB0aGF0IG5lZWQgdG9cbiAgICogIHJlYWQgdGhlIHNlbGVjdGlvbiB3aXRob3V0IHN1YnNjcmliaW5nLiAqL1xuICBnZXRTZWxlY3RlZFNoYXBlSW5kaWNlcygpOiBudW1iZXJbXSB7XG4gICAgcmV0dXJuIHRoaXMuc2VsZWN0ZWRJbmRpY2VzJC52YWx1ZTtcbiAgfVxuXG4gIC8qKiBEZWxldGUgdGhlIGN1cnJlbnRseSBzZWxlY3RlZCByZWdpb25zIGFuZCBjbGVhciB0aGUgc2VsZWN0aW9uLiAqL1xuICBkZWxldGVBY3RpdmVTaGFwZSgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5zZWxlY3RlZElkcy5sZW5ndGggPT09IDApIHJldHVybjtcbiAgICB0aGlzLnJlY29yZFVuZG9TbmFwc2hvdCgpO1xuICAgIGNvbnN0IGlkcyA9IG5ldyBTZXQodGhpcy5zZWxlY3RlZElkcyk7XG4gICAgdGhpcy5yZWdpb25zID0gdGhpcy5yZWdpb25zLmZpbHRlcihyID0+ICFpZHMuaGFzKHIuaWQpKTtcbiAgICB0aGlzLnNlbGVjdGVkSWRzID0gW107XG4gICAgdGhpcy5zeW5jQ2FjaGUoKTtcbiAgICB0aGlzLmVtaXRTZWxlY3Rpb24oKTtcbiAgICB0aGlzLmVtaXQoKTtcbiAgfVxuXG4gIC8vIOKUgOKUgCBJUmVnaW9uU3RvcmU6IGNvbG91cnMgLyBsYWJlbHMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgZ2V0U2hvd1NoYXBlTGFiZWwoKTogYm9vbGVhbiB7IHJldHVybiB0aGlzLnNob3dTaGFwZUxhYmVsOyB9XG4gIGdldFNoYXBlQ29sb3IoKTogc3RyaW5nIHsgcmV0dXJuIHRoaXMuc2hhcGVDb2xvcjsgfVxuICBnZXRGaWxsQ29sb3IoKTogc3RyaW5nIHsgcmV0dXJuIHRoaXMuZmlsbENvbG9yOyB9XG5cbiAgLyoqIENvbnZlbmllbmNlIHNldHRlcnMgKG5vdCBvbiB0aGUgY29udHJhY3QpIGZvciB0b29sYmFyIHdpcmluZy4gKi9cbiAgc2V0U2hvd1NoYXBlTGFiZWwoc2hvdzogYm9vbGVhbik6IHZvaWQgeyB0aGlzLnNob3dTaGFwZUxhYmVsID0gc2hvdzsgfVxuICBzZXRTaGFwZUNvbG9yKGNvbG9yOiBzdHJpbmcpOiB2b2lkIHsgdGhpcy5zaGFwZUNvbG9yID0gY29sb3I7IH1cbiAgc2V0RmlsbENvbG9yKGNvbG9yOiBzdHJpbmcpOiB2b2lkIHsgdGhpcy5maWxsQ29sb3IgPSBjb2xvcjsgfVxuXG4gIGdldENsYXNzaWZpY2F0aW9uQ29sb3JzKCk6IE1hcDxzdHJpbmcsIHN0cmluZz4geyByZXR1cm4gdGhpcy5zdG9yZS5nZXRDbGFzc2lmaWNhdGlvbkNvbG9ycygpOyB9XG4gIHNldENsYXNzaWZpY2F0aW9uQ29sb3IobGFiZWw6IHN0cmluZywgY29sb3I6IHN0cmluZyk6IHZvaWQgeyB0aGlzLnN0b3JlLnNldENsYXNzaWZpY2F0aW9uQ29sb3IobGFiZWwsIGNvbG9yKTsgfVxuXG4gIC8vIOKUgOKUgCBJUmVnaW9uU3RvcmU6IHByZXZpb3VzLXNoYXBlcyBidWZmZXIg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgLyoqIFJlLXNob3cgdGhlIGxhc3Qgc2F2ZWQgc25hcHNob3QgKHRyYW5zaWVudCDigJQgZG9lcyBub3QgYWx0ZXIgc3RvcmVkIHN0YXRlKS4gKi9cbiAgcGxvdFByZXZpb3VzU2hhcGVzKCk6IHZvaWQge1xuICAgIHRoaXMucmVnaW9uVXBkYXRlJC5uZXh0KHRoaXMucHJldmlvdXNSZWdpb25zLnNsaWNlKCkpO1xuICB9XG4gIHNldFByZXZpb3VzU2hhcGVzKHNoYXBlczogYW55W10pOiB2b2lkIHsgdGhpcy5wcmV2aW91c1JlZ2lvbnMgPSAoc2hhcGVzIGFzIFJlZ2lvbltdKS5zbGljZSgpOyB9XG4gIGdldFByZXZpb3VzU2hhcGVzKCk6IGFueVtdIHsgcmV0dXJuIHRoaXMucHJldmlvdXNSZWdpb25zLnNsaWNlKCk7IH1cblxuICAvLyDilIDilIAgSVJlZ2lvblN0b3JlOiB1bmRvIC8gcmVkbyAoaml0LXVpIzg1KSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICAvKiogRW1pdHMgd2hldGhlciBhbiB1bmRvIHN0ZXAgaXMgY3VycmVudGx5IGF2YWlsYWJsZSDigJQgZHJpdmVzIHRoZSB0b29sYmFyXG4gICAqICBVbmRvIGJ1dHRvbidzIGVuYWJsZWQgc3RhdGUgKGdyZXllZCBvdXQgd2hlbiBmYWxzZSkuICovXG4gIGdldENhblVuZG8kKCk6IE9ic2VydmFibGU8Ym9vbGVhbj4ge1xuICAgIHJldHVybiB0aGlzLmNhblVuZG8kLmFzT2JzZXJ2YWJsZSgpO1xuICB9XG5cbiAgLyoqIEVtaXRzIHdoZXRoZXIgYSByZWRvIHN0ZXAgaXMgY3VycmVudGx5IGF2YWlsYWJsZSDigJQgZHJpdmVzIHRoZSB0b29sYmFyXG4gICAqICBSZWRvIGJ1dHRvbidzIGVuYWJsZWQgc3RhdGUuICovXG4gIGdldENhblJlZG8kKCk6IE9ic2VydmFibGU8Ym9vbGVhbj4ge1xuICAgIHJldHVybiB0aGlzLmNhblJlZG8kLmFzT2JzZXJ2YWJsZSgpO1xuICB9XG5cbiAgLyoqIFN5bmNocm9ub3VzIHJlYWQgb2Yge0BsaW5rIGdldENhblVuZG8kfSDigJQgdHJ1ZSB3aGVuIGF0IGxlYXN0IG9uZSByZWdpb25cbiAgICogIGFjdGlvbiBjYW4gYmUgdW5kb25lLiAqL1xuICBjYW5VbmRvKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnVuZG9TdGFjay5sZW5ndGggPiAwO1xuICB9XG5cbiAgLyoqIFN5bmNocm9ub3VzIHJlYWQgb2Yge0BsaW5rIGdldENhblJlZG8kfSDigJQgdHJ1ZSB3aGVuIGFuIHVuZG9uZSBhY3Rpb24gY2FuXG4gICAqICBiZSByZS1hcHBsaWVkLiAqL1xuICBjYW5SZWRvKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnJlZG9TdGFjay5sZW5ndGggPiAwO1xuICB9XG5cbiAgLyoqXG4gICAqIFVuZG8gdGhlIG1vc3QgcmVjZW50IHJlZ2lvbiBhY3Rpb24sIHJlc3RvcmluZyB0aGUgcmVnaW9uIHNldCB0byBpdHMgc3RhdGVcbiAgICoganVzdCBiZWZvcmUgdGhhdCBhY3Rpb24gYW5kIHB1c2hpbmcgdGhlIGN1cnJlbnQgc3RhdGUgb250byB0aGUgcmVkbyBzdGFjay5cbiAgICogVXAgdG8ge0BsaW5rIFVORE9fTElNSVR9IHN0ZXBzIGFyZSByZXRhaW5lZCwgc28gdGhpcyBjYW4gYmUgY2FsbGVkIHVwIHRvXG4gICAqIHtAbGluayBVTkRPX0xJTUlUfSB0aW1lcyBpbiBhIHJvdyBiZWZvcmUgdGhlIGhpc3RvcnkgZW1wdGllcy4gTm8tb3Agd2hlblxuICAgKiBub3RoaW5nIGlzIGxlZnQgdG8gdW5kby5cbiAgICovXG4gIHVuZG8oKTogdm9pZCB7XG4gICAgaWYgKHRoaXMudW5kb1N0YWNrLmxlbmd0aCA9PT0gMCkgcmV0dXJuO1xuICAgIGNvbnN0IHNuYXBzaG90ID0gdGhpcy51bmRvU3RhY2sucG9wKCkgYXMgUmVnaW9uW107XG4gICAgLy8gU3Rhc2ggdGhlIGN1cnJlbnQgKHBvc3QtYWN0aW9uKSBzdGF0ZSBzbyByZWRvIGNhbiByZS1hcHBseSBpdC5cbiAgICB0aGlzLnJlZG9TdGFjay5wdXNoKHRoaXMuY2xvbmVSZWdpb25zKHRoaXMucmVnaW9ucykpO1xuICAgIGlmICh0aGlzLnJlZG9TdGFjay5sZW5ndGggPiBSZWdpb25TdG9yZS5VTkRPX0xJTUlUKSB0aGlzLnJlZG9TdGFjay5zaGlmdCgpO1xuICAgIHRoaXMucmVzdG9yZVNuYXBzaG90KHNuYXBzaG90KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWRvIHRoZSBhY3Rpb24gbW9zdCByZWNlbnRseSB1bmRvbmUsIHJlc3RvcmluZyB0aGUgcmVnaW9uIHNldCB0byB0aGUgc3RhdGVcbiAgICogaXQgaGFkIGJlZm9yZSB0aGF0IHVuZG8gYW5kIHB1c2hpbmcgdGhlIGN1cnJlbnQgc3RhdGUgYmFjayBvbnRvIHRoZSB1bmRvXG4gICAqIHN0YWNrLiBOby1vcCB3aGVuIHRoZXJlJ3Mgbm90aGluZyB0byByZWRvICh0aGUgcmVkbyBzdGFjayBpcyBjbGVhcmVkIGJ5IGFueVxuICAgKiBmcmVzaCByZWdpb24gYWN0aW9uKS5cbiAgICovXG4gIHJlZG8oKTogdm9pZCB7XG4gICAgaWYgKHRoaXMucmVkb1N0YWNrLmxlbmd0aCA9PT0gMCkgcmV0dXJuO1xuICAgIGNvbnN0IHNuYXBzaG90ID0gdGhpcy5yZWRvU3RhY2sucG9wKCkgYXMgUmVnaW9uW107XG4gICAgdGhpcy51bmRvU3RhY2sucHVzaCh0aGlzLmNsb25lUmVnaW9ucyh0aGlzLnJlZ2lvbnMpKTtcbiAgICBpZiAodGhpcy51bmRvU3RhY2subGVuZ3RoID4gUmVnaW9uU3RvcmUuVU5ET19MSU1JVCkgdGhpcy51bmRvU3RhY2suc2hpZnQoKTtcbiAgICB0aGlzLnJlc3RvcmVTbmFwc2hvdChzbmFwc2hvdCk7XG4gIH1cblxuICAvKiogRGlzY2FyZCB0aGUgdW5kby9yZWRvIGhpc3RvcnkgKGUuZy4gb24gaW1hZ2UgbG9hZC9zd2l0Y2gg4oCUIGhpc3RvcnkgbmV2ZXJcbiAgICogIGNyb3NzZXMgaW1hZ2VzKS4gKi9cbiAgcmVzZXRVbmRvSGlzdG9yeSgpOiB2b2lkIHtcbiAgICB0aGlzLnVuZG9TdGFjayA9IFtdO1xuICAgIHRoaXMucmVkb1N0YWNrID0gW107XG4gICAgdGhpcy5jbG9zZVVuZG9CdXJzdCgpO1xuICAgIGlmICh0aGlzLmNhblVuZG8kLnZhbHVlKSB0aGlzLmNhblVuZG8kLm5leHQoZmFsc2UpO1xuICAgIGlmICh0aGlzLmNhblJlZG8kLnZhbHVlKSB0aGlzLmNhblJlZG8kLm5leHQoZmFsc2UpO1xuICB9XG5cbiAgLyoqIE1ha2UgYHNuYXBzaG90YCB0aGUgbGl2ZSByZWdpb24gc2V0IGFuZCBub3RpZnkgYm90aCBiYWNrZW5kcy4gU2hhcmVkIGJ5XG4gICAqICB7QGxpbmsgdW5kb30gYW5kIHtAbGluayByZWRvfTsgdGhlIHNuYXBzaG90IGlzIGFscmVhZHkgYSBkZXRhY2hlZCBkZWVwXG4gICAqICBjbG9uZSwgc28gaXQgYmVjb21lcyB0aGUgbGl2ZSBhcnJheSBkaXJlY3RseS4gKi9cbiAgcHJpdmF0ZSByZXN0b3JlU25hcHNob3Qoc25hcHNob3Q6IFJlZ2lvbltdKTogdm9pZCB7XG4gICAgLy8gQ2xvc2UgYW55IG9wZW4gY29hbGVzY2luZyBidXJzdCBzbyB0aGUgbmV4dCBlZGl0IHN0YXJ0cyBhIGZyZXNoIGVudHJ5LFxuICAgIC8vIGFuZCBmbGFnIHRoZSByZXN0b3JlIHNvIGl0IGRvZXNuJ3QgcmVjb3JkIGl0c2VsZiBiYWNrIGludG8gdGhlIGhpc3RvcnkuXG4gICAgdGhpcy5jbG9zZVVuZG9CdXJzdCgpO1xuICAgIHRoaXMucmVzdG9yaW5nVW5kbyA9IHRydWU7XG4gICAgdGhpcy5yZWdpb25zID0gc25hcHNob3Q7XG4gICAgLy8gRHJvcCBhbnkgc2VsZWN0ZWQgaWRzIHRoZSByZXN0b3JlZCBzZXQgbm8gbG9uZ2VyIGNvbnRhaW5zLlxuICAgIHRoaXMuc2VsZWN0ZWRJZHMgPSB0aGlzLnNlbGVjdGVkSWRzLmZpbHRlcihpZCA9PiB0aGlzLmluZGV4T2ZJZChpZCkgPj0gMCk7XG4gICAgdGhpcy5zeW5jQ2FjaGUoKTtcbiAgICB0aGlzLmVtaXRTZWxlY3Rpb24oKTtcbiAgICB0aGlzLnJlc3RvcmluZ1VuZG8gPSBmYWxzZTtcbiAgICB0aGlzLmVtaXRVbmRvU3RhdGUoKTtcbiAgICAvLyBOb3RpZnkgdGhlIGxpdmUgKyBjb2FsZXNjZWQgc3RyZWFtcyBzbyB3aGljaGV2ZXIgYmFja2VuZCBpcyBvbiBzY3JlZW5cbiAgICAvLyByZS1yZW5kZXJzIGZyb20gdGhlIHJlc3RvcmVkIHN0b3JlIHN0YXRlLlxuICAgIHRoaXMucmVnaW9uTGl2ZUVkaXQkLm5leHQodGhpcy5yZWdpb25zLnNsaWNlKCkpO1xuICAgIHRoaXMucmVnaW9uVXBkYXRlJC5uZXh0KHRoaXMuZ2V0UmVnaW9ucygpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYXB0dXJlIHRoZSBwcmUtYWN0aW9uIHJlZ2lvbiBzZXQgaW50byB0aGUgYm91bmRlZCB1bmRvIGhpc3RvcnkuIENhbGxlZCBhdFxuICAgKiB0aGUgdG9wIG9mIGV2ZXJ5IG11dGF0aW5nIG9wZXJhdGlvbiwgKmJlZm9yZSogaXQgY2hhbmdlcyBgcmVnaW9uc2AsIHNvIHRoZVxuICAgKiBzbmFwc2hvdCBpcyB0aGUgc3RhdGUgdG8gcmV0dXJuIHRvLiBSYXBpZCBjb21taXRzIGZyb20gb25lIGdlc3R1cmUgY29hbGVzY2VcbiAgICogaW50byBhIHNpbmdsZSBlbnRyeSAoc2VlIHtAbGluayB1bmRvU3RhY2t9KS4gQSBmcmVzaCBhY3Rpb24gYWxzbyBhYmFuZG9uc1xuICAgKiBhbnkgcmVkbyBmdXR1cmUuXG4gICAqL1xuICBwcml2YXRlIHJlY29yZFVuZG9TbmFwc2hvdCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5yZXN0b3JpbmdVbmRvKSByZXR1cm47XG4gICAgY29uc3Qgc3RhcnRzQnVyc3QgPSAhdGhpcy51bmRvQnVyc3RPcGVuO1xuICAgIHRoaXMuYXJtVW5kb0J1cnN0KCk7XG4gICAgaWYgKCFzdGFydHNCdXJzdCkgcmV0dXJuOyAgICAgICAgICAgICAgICAgICAgICAvLyBtaWQtYnVyc3Qg4oCUIGtlZXAgZmlyc3Qgc25hcHNob3RcbiAgICB0aGlzLnVuZG9TdGFjay5wdXNoKHRoaXMuY2xvbmVSZWdpb25zKHRoaXMucmVnaW9ucykpO1xuICAgIGlmICh0aGlzLnVuZG9TdGFjay5sZW5ndGggPiBSZWdpb25TdG9yZS5VTkRPX0xJTUlUKSB0aGlzLnVuZG9TdGFjay5zaGlmdCgpO1xuICAgIHRoaXMucmVkb1N0YWNrID0gW107ICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYSBuZXcgZWRpdCBpbnZhbGlkYXRlcyByZWRvXG4gICAgdGhpcy5lbWl0VW5kb1N0YXRlKCk7XG4gIH1cblxuICAvKiogUHVzaCB0aGUgY3VycmVudCBjYW4tdW5kbyAvIGNhbi1yZWRvIGF2YWlsYWJpbGl0eSB0byBzdWJzY3JpYmVycy4gKi9cbiAgcHJpdmF0ZSBlbWl0VW5kb1N0YXRlKCk6IHZvaWQge1xuICAgIGNvbnN0IGNhblVuZG8gPSB0aGlzLnVuZG9TdGFjay5sZW5ndGggPiAwO1xuICAgIGNvbnN0IGNhblJlZG8gPSB0aGlzLnJlZG9TdGFjay5sZW5ndGggPiAwO1xuICAgIGlmICh0aGlzLmNhblVuZG8kLnZhbHVlICE9PSBjYW5VbmRvKSB0aGlzLmNhblVuZG8kLm5leHQoY2FuVW5kbyk7XG4gICAgaWYgKHRoaXMuY2FuUmVkbyQudmFsdWUgIT09IGNhblJlZG8pIHRoaXMuY2FuUmVkbyQubmV4dChjYW5SZWRvKTtcbiAgfVxuXG4gIC8qKiAoUmUpYXJtIHRoZSBpZGxlIHRpbWVyIHRoYXQgY2xvc2VzIHRoZSBjdXJyZW50IGNvYWxlc2NpbmcgYnVyc3QuICovXG4gIHByaXZhdGUgYXJtVW5kb0J1cnN0KCk6IHZvaWQge1xuICAgIHRoaXMudW5kb0J1cnN0T3BlbiA9IHRydWU7XG4gICAgaWYgKHRoaXMudW5kb0J1cnN0VGltZXIpIGNsZWFyVGltZW91dCh0aGlzLnVuZG9CdXJzdFRpbWVyKTtcbiAgICB0aGlzLnVuZG9CdXJzdFRpbWVyID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICB0aGlzLnVuZG9CdXJzdE9wZW4gPSBmYWxzZTtcbiAgICAgIHRoaXMudW5kb0J1cnN0VGltZXIgPSBudWxsO1xuICAgIH0sIFJlZ2lvblN0b3JlLlVORE9fQ09BTEVTQ0VfTVMpO1xuICB9XG5cbiAgcHJpdmF0ZSBjbG9zZVVuZG9CdXJzdCgpOiB2b2lkIHtcbiAgICB0aGlzLnVuZG9CdXJzdE9wZW4gPSBmYWxzZTtcbiAgICBpZiAodGhpcy51bmRvQnVyc3RUaW1lcikgeyBjbGVhclRpbWVvdXQodGhpcy51bmRvQnVyc3RUaW1lcik7IHRoaXMudW5kb0J1cnN0VGltZXIgPSBudWxsOyB9XG4gIH1cblxuICBwcml2YXRlIGNsb25lUmVnaW9ucyhyZWdpb25zOiBSZWdpb25bXSk6IFJlZ2lvbltdIHtcbiAgICByZXR1cm4gcmVnaW9ucy5tYXAociA9PiB0aGlzLmNsb25lUmVnaW9uKHIpKTtcbiAgfVxuXG4gIC8qKiBEZWVwIGNsb25lIGEgcmVnaW9uIHNvIGFuIGluLXBsYWNlIGdlb21ldHJ5IGVkaXQgY2FuJ3QgbXV0YXRlIGEgc3RvcmVkXG4gICAqICBoaXN0b3J5IHNuYXBzaG90IChib3VuZHMgYXJlIGNsb25lZCB2aWEge0BsaW5rIGNsb25lQm91bmRzfSkuICovXG4gIHByaXZhdGUgY2xvbmVSZWdpb24ocjogUmVnaW9uKTogUmVnaW9uIHtcbiAgICBjb25zdCBjID0gbmV3IFJlZ2lvbigpO1xuICAgIE9iamVjdC5hc3NpZ24oYywgcik7XG4gICAgYy5ib3VuZHMgPSByLmJvdW5kcyA/IHRoaXMuY2xvbmVCb3VuZHMoci5ib3VuZHMpIDogci5ib3VuZHM7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoci50aWxlQ29vcmRpbmF0ZXMpKSBjLnRpbGVDb29yZGluYXRlcyA9IHIudGlsZUNvb3JkaW5hdGVzLnNsaWNlKCk7XG4gICAgcmV0dXJuIGM7XG4gIH1cblxuICAvLyDilIDilIAgSVJlZ2lvblN0b3JlOiBHZW9KU09OIEkvTyAobmV1dHJhbCBoZWxwZXJzKSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBpbXBvcnRSZWdpb25zKGdlb0pzb25TdHI6IHN0cmluZyk6IFJlZ2lvbltdIHtcbiAgICByZXR1cm4gdGhpcy5wbG90VXRpbGl0aWVzLmltcG9ydFJPSXNGcm9tR2VvSnNvbihnZW9Kc29uU3RyKTtcbiAgfVxuICBleHBvcnRSZWdpb25zKHJlZ2lvbnM6IFJlZ2lvbltdKTogdm9pZCB7XG4gICAgdGhpcy5wbG90VXRpbGl0aWVzLnNhdmVUb0ZpbGUodGhpcy5wbG90VXRpbGl0aWVzLmV4cG9ydFJPSXNUb0dlb0pzb24ocmVnaW9ucykpO1xuICB9XG4gIGdldEdlb0pzb25TdHJpbmcocmVnaW9uczogUmVnaW9uW10pOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLnBsb3RVdGlsaXRpZXMuZXhwb3J0Uk9Jc1RvR2VvSnNvbihyZWdpb25zKTtcbiAgfVxuXG4gIC8vIOKUgOKUgCBJUmVnaW9uRWRpdEFwaTogc3RydWN0dXJhbCBlZGl0cyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBhZGRSZWdpb24ocmVnaW9uOiBSZWdpb24pOiBudW1iZXIge1xuICAgIHRoaXMucmVjb3JkVW5kb1NuYXBzaG90KCk7XG4gICAgaWYgKHJlZ2lvbi5pZCA9PSBudWxsKSByZWdpb24uaWQgPSB0aGlzLm5leHRJZCsrO1xuICAgIGlmIChyZWdpb24ubmFtZSA9PSBudWxsKSByZWdpb24ubmFtZSA9IGBzaGFwZSR7cmVnaW9uLmlkfWA7XG4gICAgcmVnaW9uLmJvdW5kcyA9IGh5ZHJhdGVCb3VuZHMocmVnaW9uLmJvdW5kcyk7ICAgLy8gaml0LXVpIzEyNFxuICAgIC8vIEEgcmVnaW9uIGRyYXduIG9uIGEgc3RhY2sgYmVsb25ncyB0byB0aGUgc2xpY2UgY3VycmVudGx5IGRpc3BsYXllZCwgc29cbiAgICAvLyBpdCBzYXZlcy9yZWxvYWRzIG9uIHRoYXQgc2xpY2UgKGppdC11aSM5MykuIE5vLW9wIGZvciBzaW5nbGUtcGxhbmUgaW1hZ2VzXG4gICAgLy8gKGN1cnJlbnRTbGljZVogc3RheXMgMCkuXG4gICAgaWYgKHRoaXMuc3RhY2tNb2RlKSByZWdpb24ueiA9IHRoaXMuY3VycmVudFNsaWNlWjtcbiAgICB0aGlzLmFwcGx5Q2xhc3NpZmljYXRpb25Db2xvcnMoW3JlZ2lvbl0pO1xuICAgIHRoaXMucmVnaW9ucy5wdXNoKHJlZ2lvbik7XG4gICAgdGhpcy5zZWxlY3RlZElkcyA9IFtyZWdpb24uaWRdO1xuICAgIHRoaXMuc3luY0NhY2hlKCk7XG4gICAgdGhpcy5lbWl0U2VsZWN0aW9uKCk7XG4gICAgdGhpcy5lbWl0KCk7XG4gICAgcmV0dXJuIHJlZ2lvbi5pZDtcbiAgfVxuXG4gIHJlbW92ZVJlZ2lvbihpZDogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3QgaWR4ID0gdGhpcy5pbmRleE9mSWQoaWQpO1xuICAgIGlmIChpZHggPCAwKSByZXR1cm47XG4gICAgdGhpcy5yZWNvcmRVbmRvU25hcHNob3QoKTtcbiAgICB0aGlzLnJlZ2lvbnMuc3BsaWNlKGlkeCwgMSk7XG4gICAgdGhpcy5zZWxlY3RlZElkcyA9IHRoaXMuc2VsZWN0ZWRJZHMuZmlsdGVyKHMgPT4gcyAhPT0gaWQpO1xuICAgIHRoaXMuc3luY0NhY2hlKCk7XG4gICAgdGhpcy5lbWl0U2VsZWN0aW9uKCk7XG4gICAgdGhpcy5lbWl0KCk7XG4gIH1cblxuICB1cGRhdGVCb3VuZHMoaWQ6IG51bWJlciwgYm91bmRzOiBSZWN0YW5nbGUgfCBQb2x5Z29uIHwgTXVsdGlQb2x5Z29uKTogdm9pZCB7XG4gICAgY29uc3QgciA9IHRoaXMuZmluZEJ5SWQoaWQpO1xuICAgIGlmICghcikgcmV0dXJuO1xuICAgIHRoaXMucmVjb3JkVW5kb1NuYXBzaG90KCk7XG4gICAgci5ib3VuZHMgPSB0aGlzLmNsb25lQm91bmRzKGJvdW5kcyk7XG4gICAgdGhpcy5zeW5jQ2FjaGUoKTtcbiAgICB0aGlzLmVtaXQoKTtcbiAgfVxuXG4gIG1vdmVSZWdpb24oaWQ6IG51bWJlciwgZHg6IG51bWJlciwgZHk6IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnN0IHIgPSB0aGlzLmZpbmRCeUlkKGlkKTtcbiAgICBpZiAoIXIgfHwgIXIuYm91bmRzKSByZXR1cm47XG4gICAgdGhpcy5yZWNvcmRVbmRvU25hcHNob3QoKTtcbiAgICBjb25zdCBiID0gci5ib3VuZHM7XG4gICAgaWYgKGIgaW5zdGFuY2VvZiBSZWN0YW5nbGUpIHtcbiAgICAgIGIueCArPSBkeDtcbiAgICAgIGIueSArPSBkeTtcbiAgICB9IGVsc2UgaWYgKGIgaW5zdGFuY2VvZiBQb2x5Z29uKSB7XG4gICAgICB0aGlzLnRyYW5zbGF0ZVBvbHlnb24oYiwgZHgsIGR5KTtcbiAgICB9IGVsc2UgaWYgKGIgaW5zdGFuY2VvZiBNdWx0aVBvbHlnb24pIHtcbiAgICAgIC8vIFRyYW5zbGF0ZSBldmVyeSBwYXJ0IChhbmQgaXRzIGhvbGVzKSB0b2dldGhlciAoaml0LXVpIzg1KS5cbiAgICAgIGZvciAoY29uc3QgcGFydCBvZiBiLnBvbHlnb25zKSB0aGlzLnRyYW5zbGF0ZVBvbHlnb24ocGFydCwgZHgsIGR5KTtcbiAgICB9XG4gICAgdGhpcy5zeW5jQ2FjaGUoKTtcbiAgICB0aGlzLmVtaXQoKTtcbiAgfVxuXG4gIC8qKiBUcmFuc2xhdGUgYSBwb2x5Z29uJ3MgdmVydGljZXMgYW5kIGFueSBob2xlcyBpbiBwbGFjZSBieSAoZHgsIGR5KS4gKi9cbiAgcHJpdmF0ZSB0cmFuc2xhdGVQb2x5Z29uKHA6IFBvbHlnb24sIGR4OiBudW1iZXIsIGR5OiBudW1iZXIpOiB2b2lkIHtcbiAgICBwLnhwb2ludHMgPSBwLnhwb2ludHMubWFwKHggPT4geCArIGR4KTtcbiAgICBwLnlwb2ludHMgPSBwLnlwb2ludHMubWFwKHkgPT4geSArIGR5KTtcbiAgICBwLmNvb3JkaW5hdGVzID0gcC54cG9pbnRzLm1hcCgoeCwgaSkgPT4gW3gsIHAueXBvaW50c1tpXV0pO1xuICAgIGlmIChwLmhvbGVzKSBwLmhvbGVzID0gcC5ob2xlcy5tYXAocmluZyA9PiByaW5nLm1hcCgoW3gsIHldKSA9PiBbeCArIGR4LCB5ICsgZHldKSk7XG4gIH1cblxuICAvLyDilIDilIAgSVJlZ2lvbkVkaXRBcGk6IHZlcnRleCBlZGl0cyAocG9seWdvbnMgb25seSkg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgbW92ZVZlcnRleChpZDogbnVtYmVyLCBpbmRleDogbnVtYmVyLCB4OiBudW1iZXIsIHk6IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnN0IHBvbHkgPSB0aGlzLnBvbHlnb25PZihpZCk7XG4gICAgaWYgKCFwb2x5IHx8IGluZGV4IDwgMCB8fCBpbmRleCA+PSBwb2x5Lnhwb2ludHMubGVuZ3RoKSByZXR1cm47XG4gICAgdGhpcy5yZWNvcmRVbmRvU25hcHNob3QoKTtcbiAgICBwb2x5Lnhwb2ludHNbaW5kZXhdID0geDtcbiAgICBwb2x5Lnlwb2ludHNbaW5kZXhdID0geTtcbiAgICBwb2x5LmNvb3JkaW5hdGVzW2luZGV4XSA9IFt4LCB5XTtcbiAgICB0aGlzLnN5bmNDYWNoZSgpO1xuICAgIHRoaXMuZW1pdCgpO1xuICB9XG5cbiAgLyoqIE1vdmUgYSB2ZXJ0ZXggb24gYSBwb2x5Z29uJ3MgaW50ZXJpb3IgcmluZyAoaG9sZSkg4oCUIGppdC11aSM4NS4gKi9cbiAgbW92ZUhvbGVWZXJ0ZXgoaWQ6IG51bWJlciwgaG9sZUluZGV4OiBudW1iZXIsIGluZGV4OiBudW1iZXIsIHg6IG51bWJlciwgeTogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3QgcG9seSA9IHRoaXMucG9seWdvbk9mKGlkKTtcbiAgICBpZiAoIXBvbHkgfHwgIXBvbHkuaG9sZXMgfHwgaG9sZUluZGV4IDwgMCB8fCBob2xlSW5kZXggPj0gcG9seS5ob2xlcy5sZW5ndGgpIHJldHVybjtcbiAgICBjb25zdCByaW5nID0gcG9seS5ob2xlc1tob2xlSW5kZXhdO1xuICAgIGlmIChpbmRleCA8IDAgfHwgaW5kZXggPj0gcmluZy5sZW5ndGgpIHJldHVybjtcbiAgICB0aGlzLnJlY29yZFVuZG9TbmFwc2hvdCgpO1xuICAgIHJpbmdbaW5kZXhdID0gW3gsIHldO1xuICAgIHRoaXMuc3luY0NhY2hlKCk7XG4gICAgdGhpcy5lbWl0KCk7XG4gIH1cblxuICAvKiogSW5zZXJ0IGEgdmVydGV4IG9uIGEgcG9seWdvbidzIGludGVyaW9yIHJpbmcgKGhvbGUpLCBhZnRlciBgc2VnSW5kZXhgXG4gICAqICAodGhlIGVkZ2UncyBzdGFydCB2ZXJ0ZXgpLiBOby1vcCBmb3IgYW4gb3V0LW9mLXJhbmdlIGhvbGUg4oCUIGppdC11aSM4NS4gKi9cbiAgYWRkSG9sZVZlcnRleChpZDogbnVtYmVyLCBob2xlSW5kZXg6IG51bWJlciwgc2VnSW5kZXg6IG51bWJlciwgeDogbnVtYmVyLCB5OiBudW1iZXIpOiB2b2lkIHtcbiAgICBjb25zdCBwb2x5ID0gdGhpcy5wb2x5Z29uT2YoaWQpO1xuICAgIGlmICghcG9seSB8fCAhcG9seS5ob2xlcyB8fCBob2xlSW5kZXggPCAwIHx8IGhvbGVJbmRleCA+PSBwb2x5LmhvbGVzLmxlbmd0aCkgcmV0dXJuO1xuICAgIGNvbnN0IHJpbmcgPSBwb2x5LmhvbGVzW2hvbGVJbmRleF07XG4gICAgdGhpcy5yZWNvcmRVbmRvU25hcHNob3QoKTtcbiAgICBjb25zdCBhdCA9IE1hdGgubWF4KDAsIE1hdGgubWluKHNlZ0luZGV4ICsgMSwgcmluZy5sZW5ndGgpKTtcbiAgICByaW5nLnNwbGljZShhdCwgMCwgW3gsIHldKTtcbiAgICBpZiAocG9seS5iZXppZXIpIHRoaXMuc2VlZEhvbGVIYW5kbGVzKHBvbHkpOyAvLyBrZWVwIGhvbGUgaGFuZGxlcyBhbGlnbmVkIHRvIHRoZSByaW5nXG4gICAgdGhpcy5zeW5jQ2FjaGUoKTtcbiAgICB0aGlzLmVtaXQoKTtcbiAgfVxuXG4gIC8qKiBEZWxldGUgdGhlIHZlcnRleCBhdCBgaW5kZXhgIG9uIGEgcG9seWdvbidzIGludGVyaW9yIHJpbmcgKGhvbGUpLiBSZW1vdmluZ1xuICAgKiAgaXQgYmVsb3cgMyB2ZXJ0aWNlcyBkcm9wcyB0aGUgd2hvbGUgaG9sZSAoYSByaW5nIHdpdGggPCAzIHBvaW50cyBib3VuZHMgbm9cbiAgICogIGFyZWEpIOKAlCBqaXQtdWkjODUuICovXG4gIGRlbGV0ZUhvbGVWZXJ0ZXgoaWQ6IG51bWJlciwgaG9sZUluZGV4OiBudW1iZXIsIGluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICBjb25zdCBwb2x5ID0gdGhpcy5wb2x5Z29uT2YoaWQpO1xuICAgIGlmICghcG9seSB8fCAhcG9seS5ob2xlcyB8fCBob2xlSW5kZXggPCAwIHx8IGhvbGVJbmRleCA+PSBwb2x5LmhvbGVzLmxlbmd0aCkgcmV0dXJuO1xuICAgIGNvbnN0IHJpbmcgPSBwb2x5LmhvbGVzW2hvbGVJbmRleF07XG4gICAgaWYgKGluZGV4IDwgMCB8fCBpbmRleCA+PSByaW5nLmxlbmd0aCkgcmV0dXJuO1xuICAgIHRoaXMucmVjb3JkVW5kb1NuYXBzaG90KCk7XG4gICAgaWYgKHJpbmcubGVuZ3RoIDw9IDMpIHtcbiAgICAgIHBvbHkuaG9sZXMuc3BsaWNlKGhvbGVJbmRleCwgMSk7XG4gICAgICBpZiAocG9seS5ob2xlcy5sZW5ndGggPT09IDApIHBvbHkuaG9sZXMgPSB1bmRlZmluZWQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJpbmcuc3BsaWNlKGluZGV4LCAxKTtcbiAgICB9XG4gICAgaWYgKHBvbHkuYmV6aWVyKSB0aGlzLnNlZWRIb2xlSGFuZGxlcyhwb2x5KTsgLy8ga2VlcCBob2xlIGhhbmRsZXMgYWxpZ25lZCB0byB0aGUgcmluZyhzKVxuICAgIHRoaXMuc3luY0NhY2hlKCk7XG4gICAgdGhpcy5lbWl0KCk7XG4gIH1cblxuICBhZGRWZXJ0ZXgoaWQ6IG51bWJlciwgc2VnSW5kZXg6IG51bWJlciwgeDogbnVtYmVyLCB5OiBudW1iZXIpOiB2b2lkIHtcbiAgICBjb25zdCBwb2x5ID0gdGhpcy5wb2x5Z29uT2YoaWQpO1xuICAgIGlmICghcG9seSkgcmV0dXJuO1xuICAgIHRoaXMucmVjb3JkVW5kb1NuYXBzaG90KCk7XG4gICAgLy8gSW5zZXJ0IGFmdGVyIHNlZ0luZGV4ICh0aGUgc3RhcnQgdmVydGV4IG9mIHRoZSBlZGdlKS4gQ2xhbXAgdG8gcmFuZ2UuXG4gICAgY29uc3QgYXQgPSBNYXRoLm1heCgwLCBNYXRoLm1pbihzZWdJbmRleCArIDEsIHBvbHkueHBvaW50cy5sZW5ndGgpKTtcbiAgICBwb2x5Lnhwb2ludHMuc3BsaWNlKGF0LCAwLCB4KTtcbiAgICBwb2x5Lnlwb2ludHMuc3BsaWNlKGF0LCAwLCB5KTtcbiAgICBwb2x5LmNvb3JkaW5hdGVzID0gcG9seS54cG9pbnRzLm1hcCgoeHgsIGkpID0+IFt4eCwgcG9seS55cG9pbnRzW2ldXSk7XG4gICAgcG9seS5ucG9pbnRzID0gcG9seS54cG9pbnRzLmxlbmd0aDtcbiAgICAvLyBHaXZlIHRoZSBuZXcgdmVydGV4IHNtb290aCBoYW5kbGVzIGZyb20gaXRzIG5laWdoYm91cnM7IGtlZXAgdGhlIG90aGVycydcbiAgICAvLyAocG9zc2libHkgaGFuZC1lZGl0ZWQpIGhhbmRsZXMgaW50YWN0LlxuICAgIGlmIChwb2x5LmJlemllciAmJiBwb2x5LmhhbmRsZXNJbiAmJiBwb2x5LmhhbmRsZXNPdXQpIHtcbiAgICAgIGNvbnN0IG4gPSBwb2x5Lnhwb2ludHMubGVuZ3RoO1xuICAgICAgY29uc3QgY2xvc2VkID0gcG9seS5jbG9zZWQgIT09IGZhbHNlO1xuICAgICAgY29uc3QgcHJldiA9IGNsb3NlZCA/IChhdCAtIDEgKyBuKSAlIG4gOiBNYXRoLm1heCgwLCBhdCAtIDEpO1xuICAgICAgY29uc3QgbmV4dCA9IGNsb3NlZCA/IChhdCArIDEpICUgbiA6IE1hdGgubWluKG4gLSAxLCBhdCArIDEpO1xuICAgICAgY29uc3QgdHggPSAocG9seS54cG9pbnRzW25leHRdIC0gcG9seS54cG9pbnRzW3ByZXZdKSAvIDY7XG4gICAgICBjb25zdCB0eSA9IChwb2x5Lnlwb2ludHNbbmV4dF0gLSBwb2x5Lnlwb2ludHNbcHJldl0pIC8gNjtcbiAgICAgIHBvbHkuaGFuZGxlc0luLnNwbGljZShhdCwgMCwgWy10eCwgLXR5XSk7XG4gICAgICBwb2x5LmhhbmRsZXNPdXQuc3BsaWNlKGF0LCAwLCBbdHgsIHR5XSk7XG4gICAgfVxuICAgIHRoaXMuc3luY0NhY2hlKCk7XG4gICAgdGhpcy5lbWl0KCk7XG4gIH1cblxuICBkZWxldGVWZXJ0ZXgoaWQ6IG51bWJlciwgaW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnN0IHBvbHkgPSB0aGlzLnBvbHlnb25PZihpZCk7XG4gICAgaWYgKCFwb2x5IHx8IGluZGV4IDwgMCB8fCBpbmRleCA+PSBwb2x5Lnhwb2ludHMubGVuZ3RoKSByZXR1cm47XG4gICAgY29uc3QgbWluID0gcG9seS5jbG9zZWQgPT09IGZhbHNlID8gMiA6IDM7XG4gICAgaWYgKHBvbHkueHBvaW50cy5sZW5ndGggPD0gbWluKSByZXR1cm47IC8vIHJlZnVzZSB0byBkZWdlbmVyYXRlIHRoZSBwb2x5Z29uXG4gICAgdGhpcy5yZWNvcmRVbmRvU25hcHNob3QoKTtcbiAgICBwb2x5Lnhwb2ludHMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICBwb2x5Lnlwb2ludHMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICBwb2x5LmNvb3JkaW5hdGVzID0gcG9seS54cG9pbnRzLm1hcCgoeHgsIGkpID0+IFt4eCwgcG9seS55cG9pbnRzW2ldXSk7XG4gICAgcG9seS5ucG9pbnRzID0gcG9seS54cG9pbnRzLmxlbmd0aDtcbiAgICBpZiAocG9seS5iZXppZXIgJiYgcG9seS5oYW5kbGVzSW4gJiYgcG9seS5oYW5kbGVzT3V0KSB7XG4gICAgICBwb2x5LmhhbmRsZXNJbi5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgcG9seS5oYW5kbGVzT3V0LnNwbGljZShpbmRleCwgMSk7XG4gICAgfVxuICAgIHRoaXMuc3luY0NhY2hlKCk7XG4gICAgdGhpcy5lbWl0KCk7XG4gIH1cblxuICBzZXRCZXppZXIoaWQ6IG51bWJlciwgYmV6aWVyOiBib29sZWFuKTogdm9pZCB7XG4gICAgY29uc3QgciA9IHRoaXMuZmluZEJ5SWQoaWQpO1xuICAgIGlmICghciB8fCAhci5ib3VuZHMpIHJldHVybjtcbiAgICBpZiAoci5ib3VuZHMgaW5zdGFuY2VvZiBQb2x5Z29uKSB7XG4gICAgICBpZiAoci5ib3VuZHMuYmV6aWVyID09PSBiZXppZXIpIHJldHVybjtcbiAgICAgIHRoaXMucmVjb3JkVW5kb1NuYXBzaG90KCk7XG4gICAgICB0aGlzLmFwcGx5QmV6aWVyKHIuYm91bmRzLCBiZXppZXIpO1xuICAgIH0gZWxzZSBpZiAoci5ib3VuZHMgaW5zdGFuY2VvZiBSZWN0YW5nbGUgJiYgYmV6aWVyKSB7XG4gICAgICB0aGlzLnJlY29yZFVuZG9TbmFwc2hvdCgpO1xuICAgICAgLy8gU21vb3RoaW5nIGEgcmVjdGFuZ2xlOiBjb252ZXJ0IGl0IHRvIGEgNC1hbmNob3IgY2xvc2VkIHBvbHlnb24gZmlyc3QuXG4gICAgICBjb25zdCBiID0gci5ib3VuZHM7XG4gICAgICBjb25zdCB4cyA9IFtiLngsIGIueCArIGIud2lkdGgsIGIueCArIGIud2lkdGgsIGIueF07XG4gICAgICBjb25zdCB5cyA9IFtiLnksIGIueSwgYi55ICsgYi5oZWlnaHQsIGIueSArIGIuaGVpZ2h0XTtcbiAgICAgIGNvbnN0IHBvbHkgPSBuZXcgUG9seWdvbigpO1xuICAgICAgcG9seS5ucG9pbnRzID0gNDtcbiAgICAgIHBvbHkueHBvaW50cyA9IHhzO1xuICAgICAgcG9seS55cG9pbnRzID0geXM7XG4gICAgICBwb2x5LmNvb3JkaW5hdGVzID0geHMubWFwKCh4LCBpKSA9PiBbeCwgeXNbaV1dKTtcbiAgICAgIHBvbHkuY2xvc2VkID0gdHJ1ZTtcbiAgICAgIHRoaXMuYXBwbHlCZXppZXIocG9seSwgdHJ1ZSk7XG4gICAgICByLmJvdW5kcyA9IHBvbHk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybjsgLy8gYmV6aWVyPWZhbHNlIG9uIGEgcmVjdGFuZ2xlOiBub3RoaW5nIHRvIGRvXG4gICAgfVxuICAgIHRoaXMuc3luY0NhY2hlKCk7XG4gICAgdGhpcy5lbWl0KCk7XG4gIH1cblxuICAvKiogVHVybiBiZXppZXIgb24gKGFuZCBzZWVkIGVkaXRhYmxlIGhhbmRsZXMgZnJvbSB0aGUgc21vb3RoIGRlZmF1bHQpIG9yIG9mZlxuICAgKiAgKGFuZCBkcm9wIHRoZSBoYW5kbGVzKS4gKi9cbiAgcHJpdmF0ZSBhcHBseUJlemllcihwb2x5OiBQb2x5Z29uLCBiZXppZXI6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICBwb2x5LmJlemllciA9IGJlemllcjtcbiAgICBpZiAoYmV6aWVyKSB7XG4gICAgICBjb25zdCBvZmYgPSBkZWZhdWx0SGFuZGxlT2Zmc2V0cyhwb2x5Lnhwb2ludHMsIHBvbHkueXBvaW50cywgcG9seS5jbG9zZWQgIT09IGZhbHNlKTtcbiAgICAgIHBvbHkuaGFuZGxlc0luID0gb2ZmLmluO1xuICAgICAgcG9seS5oYW5kbGVzT3V0ID0gb2ZmLm91dDtcbiAgICAgIHRoaXMuc2VlZEhvbGVIYW5kbGVzKHBvbHkpOyAvLyBzbW9vdGggdGhlIGhvbGVzIHRvbyAoZG9udXQg4oaSIGJlemllciBjdXJ2ZXMgdGhlIGhvbGVzKVxuICAgIH0gZWxzZSB7XG4gICAgICBwb2x5LmhhbmRsZXNJbiA9IHVuZGVmaW5lZDtcbiAgICAgIHBvbHkuaGFuZGxlc091dCA9IHVuZGVmaW5lZDtcbiAgICAgIHBvbHkuaG9sZUhhbmRsZXNJbiA9IHVuZGVmaW5lZDtcbiAgICAgIHBvbHkuaG9sZUhhbmRsZXNPdXQgPSB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG5cbiAgLyoqIChSZSlzZWVkIHBlci1ob2xlIGJlemllciBoYW5kbGVzIGZyb20gdGhlIENhdG11bGwtUm9tIGRlZmF1bHQsIHBhcmFsbGVsIHRvIGBwb2x5LmhvbGVzYC4gKi9cbiAgcHJpdmF0ZSBzZWVkSG9sZUhhbmRsZXMocG9seTogUG9seWdvbik6IHZvaWQge1xuICAgIGlmICghcG9seS5ob2xlcyB8fCAhcG9seS5ob2xlcy5sZW5ndGgpIHtcbiAgICAgIHBvbHkuaG9sZUhhbmRsZXNJbiA9IHVuZGVmaW5lZDtcbiAgICAgIHBvbHkuaG9sZUhhbmRsZXNPdXQgPSB1bmRlZmluZWQ7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGluczogbnVtYmVyW11bXVtdID0gW107XG4gICAgY29uc3Qgb3V0czogbnVtYmVyW11bXVtdID0gW107XG4gICAgZm9yIChjb25zdCByaW5nIG9mIHBvbHkuaG9sZXMpIHtcbiAgICAgIGNvbnN0IG9mZiA9IGRlZmF1bHRIYW5kbGVPZmZzZXRzKFxuICAgICAgICByaW5nLm1hcCgocCkgPT4gcFswXSksXG4gICAgICAgIHJpbmcubWFwKChwKSA9PiBwWzFdKSxcbiAgICAgICAgdHJ1ZSxcbiAgICAgICk7XG4gICAgICBpbnMucHVzaChvZmYuaW4pO1xuICAgICAgb3V0cy5wdXNoKG9mZi5vdXQpO1xuICAgIH1cbiAgICBwb2x5LmhvbGVIYW5kbGVzSW4gPSBpbnM7XG4gICAgcG9seS5ob2xlSGFuZGxlc091dCA9IG91dHM7XG4gIH1cblxuICAvKiogRHJhZyBhIGJlemllciBjb250cm9sIHBvaW50IG9uIGEgaG9sZSByaW5nIHZlcnRleCAoZG9udXQgYmV6aWVyIGVkaXRpbmcpLiAqL1xuICBtb3ZlSG9sZUJlemllckhhbmRsZShcbiAgICBpZDogbnVtYmVyLFxuICAgIGhvbGVJbmRleDogbnVtYmVyLFxuICAgIGluZGV4OiBudW1iZXIsXG4gICAgc2lkZTogJ2luJyB8ICdvdXQnLFxuICAgIHg6IG51bWJlcixcbiAgICB5OiBudW1iZXIsXG4gICk6IHZvaWQge1xuICAgIGNvbnN0IHBvbHkgPSB0aGlzLnBvbHlnb25PZihpZCk7XG4gICAgaWYgKCFwb2x5IHx8ICFwb2x5LmJlemllciB8fCAhcG9seS5ob2xlcyB8fCBob2xlSW5kZXggPCAwIHx8IGhvbGVJbmRleCA+PSBwb2x5LmhvbGVzLmxlbmd0aCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCByaW5nID0gcG9seS5ob2xlc1tob2xlSW5kZXhdO1xuICAgIGlmIChpbmRleCA8IDAgfHwgaW5kZXggPj0gcmluZy5sZW5ndGgpIHJldHVybjtcbiAgICB0aGlzLnJlY29yZFVuZG9TbmFwc2hvdCgpO1xuICAgIGlmICghcG9seS5ob2xlSGFuZGxlc0luIHx8ICFwb2x5LmhvbGVIYW5kbGVzT3V0KSB0aGlzLnNlZWRIb2xlSGFuZGxlcyhwb2x5KTtcbiAgICBjb25zdCBvZmZzZXQgPSBbeCAtIHJpbmdbaW5kZXhdWzBdLCB5IC0gcmluZ1tpbmRleF1bMV1dO1xuICAgIGlmIChzaWRlID09PSAnaW4nKSBwb2x5LmhvbGVIYW5kbGVzSW4hW2hvbGVJbmRleF1baW5kZXhdID0gb2Zmc2V0O1xuICAgIGVsc2UgcG9seS5ob2xlSGFuZGxlc091dCFbaG9sZUluZGV4XVtpbmRleF0gPSBvZmZzZXQ7XG4gICAgdGhpcy5zeW5jQ2FjaGUoKTtcbiAgICB0aGlzLmVtaXQoKTtcbiAgfVxuXG4gIG1vdmVCZXppZXJIYW5kbGUoaWQ6IG51bWJlciwgaW5kZXg6IG51bWJlciwgc2lkZTogJ2luJyB8ICdvdXQnLCB4OiBudW1iZXIsIHk6IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnN0IHBvbHkgPSB0aGlzLnBvbHlnb25PZihpZCk7XG4gICAgaWYgKCFwb2x5IHx8ICFwb2x5LmJlemllciB8fCBpbmRleCA8IDAgfHwgaW5kZXggPj0gcG9seS54cG9pbnRzLmxlbmd0aCkgcmV0dXJuO1xuICAgIHRoaXMucmVjb3JkVW5kb1NuYXBzaG90KCk7XG4gICAgaWYgKCFwb2x5LmhhbmRsZXNJbiB8fCAhcG9seS5oYW5kbGVzT3V0KSB7XG4gICAgICBjb25zdCBvZmYgPSBkZWZhdWx0SGFuZGxlT2Zmc2V0cyhwb2x5Lnhwb2ludHMsIHBvbHkueXBvaW50cywgcG9seS5jbG9zZWQgIT09IGZhbHNlKTtcbiAgICAgIHBvbHkuaGFuZGxlc0luID0gb2ZmLmluO1xuICAgICAgcG9seS5oYW5kbGVzT3V0ID0gb2ZmLm91dDtcbiAgICB9XG4gICAgY29uc3Qgb2Zmc2V0ID0gW3ggLSBwb2x5Lnhwb2ludHNbaW5kZXhdLCB5IC0gcG9seS55cG9pbnRzW2luZGV4XV07XG4gICAgaWYgKHNpZGUgPT09ICdpbicpIHBvbHkuaGFuZGxlc0luW2luZGV4XSA9IG9mZnNldDtcbiAgICBlbHNlIHBvbHkuaGFuZGxlc091dFtpbmRleF0gPSBvZmZzZXQ7XG4gICAgdGhpcy5zeW5jQ2FjaGUoKTtcbiAgICB0aGlzLmVtaXQoKTtcbiAgfVxuXG4gIGJlZ2luQmF0Y2goKTogdm9pZCB7IHRoaXMuYmF0Y2hEZXB0aCsrOyB9XG4gIGVuZEJhdGNoKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmJhdGNoRGVwdGggPiAwKSB0aGlzLmJhdGNoRGVwdGgtLTtcbiAgICBpZiAodGhpcy5iYXRjaERlcHRoID09PSAwICYmIHRoaXMucGVuZGluZ0VtaXQpIHtcbiAgICAgIHRoaXMucGVuZGluZ0VtaXQgPSBmYWxzZTtcbiAgICAgIHRoaXMucmVnaW9uVXBkYXRlJC5uZXh0KHRoaXMuZ2V0UmVnaW9ucygpKTtcbiAgICB9XG4gIH1cblxuICAvLyDilIDilIAgcGVyLWltYWdlIGxpZmVjeWNsZSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICAvKipcbiAgICogU3dpdGNoIHRoZSBhY3RpdmUgaW1hZ2U6IHNuYXBzaG90IHRoZSBvdXRnb2luZyByZWdpb25zLCByZXN0b3JlIHRoZVxuICAgKiBpbmNvbWluZyBpbWFnZSdzIChvciBbXSBpZiBub25lKSwgY2xlYXIgc2VsZWN0aW9uLCBhbmQgbm90aWZ5LiBJZGVtcG90ZW50XG4gICAqIGZvciB0aGUgc2FtZSBpbWFnZSAoc28gcmVwZWF0ZWQgcmVwbG90cyBvZiBvbmUgaW1hZ2Uga2VlcCBpdHMgcmVnaW9ucykuXG4gICAqL1xuICBzZXRBY3RpdmVJbWFnZShpbWFnZUluZm86IElJbWFnZUluZm8pOiB2b2lkIHtcbiAgICBjb25zdCBuZXdLZXkgPSB0aGlzLmRlcml2ZUltYWdlS2V5KGltYWdlSW5mbyk7XG4gICAgaWYgKHRoaXMuY3VycmVudEltYWdlS2V5ID09PSBuZXdLZXkpIHJldHVybjtcbiAgICAvLyBTd2l0Y2hpbmcgaW1hZ2VzIGVuZHMgYW55IHBlci1zbGljZSBzdGFjayBzZXNzaW9uIChqaXQtdWkjOTMpOyB0aGUgbG9hZGVyXG4gICAgLy8gcmUtZW50ZXJzIHN0YWNrIG1vZGUgYWZ0ZXJ3YXJkcyBpZiB0aGUgbmV3IGltYWdlIGlzIGl0c2VsZiBhIHotc3RhY2suXG4gICAgdGhpcy5leGl0U3RhY2tNb2RlKCk7XG4gICAgaWYgKHRoaXMuY3VycmVudEltYWdlS2V5KSB7XG4gICAgICB0aGlzLnJlZ2lvbnNCeUltYWdlS2V5LnNldCh0aGlzLmN1cnJlbnRJbWFnZUtleSwgdGhpcy5yZWdpb25zLnNsaWNlKCkpO1xuICAgIH1cbiAgICB0aGlzLmN1cnJlbnRJbWFnZUtleSA9IG5ld0tleTtcbiAgICB0aGlzLnJlZ2lvbnMgPSAobmV3S2V5ICYmIHRoaXMucmVnaW9uc0J5SW1hZ2VLZXkuZ2V0KG5ld0tleSkpXG4gICAgICA/ICh0aGlzLnJlZ2lvbnNCeUltYWdlS2V5LmdldChuZXdLZXkpIGFzIFJlZ2lvbltdKS5zbGljZSgpXG4gICAgICA6IFtdO1xuICAgIHRoaXMucHJldmlvdXNSZWdpb25zID0gdGhpcy5yZWdpb25zLnNsaWNlKCk7XG4gICAgdGhpcy5zZWxlY3RlZElkcyA9IFtdO1xuICAgIC8vIFVuZG8gbmV2ZXIgY3Jvc3NlcyBhbiBpbWFnZSBzd2l0Y2guXG4gICAgdGhpcy5yZXNldFVuZG9IaXN0b3J5KCk7XG4gICAgdGhpcy5lbWl0U2VsZWN0aW9uKCk7XG4gICAgdGhpcy5yZWdpb25VcGRhdGUkLm5leHQodGhpcy5nZXRSZWdpb25zKCkpO1xuICB9XG5cbiAgLyoqIERyb3AgdGhlIGVudGlyZSBwZXItaW1hZ2UgY2FjaGUgKGxvZ291dCAvIHByb2plY3Qgc3dpdGNoKS4gKi9cbiAgY2xlYXJSZWdpb25zQnlJbWFnZUtleSgpOiB2b2lkIHtcbiAgICB0aGlzLnJlZ2lvbnNCeUltYWdlS2V5LmNsZWFyKCk7XG4gICAgdGhpcy5jdXJyZW50SW1hZ2VLZXkgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5yZWdpb25zID0gW107XG4gICAgdGhpcy5zZWxlY3RlZElkcyA9IFtdO1xuICAgIHRoaXMucmVzZXRVbmRvSGlzdG9yeSgpO1xuICB9XG5cbiAgLy8g4pSA4pSAIGludGVybmFscyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBwcml2YXRlIGRlcml2ZUltYWdlS2V5KGltYWdlSW5mbzogSUltYWdlSW5mbyB8IHVuZGVmaW5lZCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKCFpbWFnZUluZm8pIHJldHVybiB1bmRlZmluZWQ7XG4gICAgaWYgKGltYWdlSW5mby51cmxzICYmIGltYWdlSW5mby51cmxzLmxlbmd0aCA+IDAgJiYgaW1hZ2VJbmZvLnVybHNbMF0pIHtcbiAgICAgIHJldHVybiBpbWFnZUluZm8udXJsc1swXTtcbiAgICB9XG4gICAgcmV0dXJuIGltYWdlSW5mby5maWxlTmFtZSB8fCB1bmRlZmluZWQ7XG4gIH1cblxuICAvKipcbiAgICogUmVzb2x2ZSBlYWNoIHJlZ2lvbidzIGNvbG91ciBmcm9tIHRoZSBhbm5vdGF0aW9uLWNsYXNzIHByZXNldCBzZXQgKGppdC11aSM3MCkuXG4gICAqIFRoZSBwcmVzZXRzIGFyZSB0aGUgc291cmNlIG9mIHRydXRoIGZvciBjb2xvdXIg4oCUIHRoaXMgKipvdmVycmlkZXMgYW55IGNvbG91clxuICAgKiBlbWJlZGRlZCBpbiB0aGUgR2VvSlNPTioqICh3aGljaCB0aGUgWU9MTyB3b3JrZXIgd3JpdGVzIHRvZGF5KS4gQSBtYXRjaGluZ1xuICAgKiBwcmVzZXQgZ2l2ZXMgdGhlIGNsYXNzIGNvbG91cjsgYW4gdW5rbm93biBjbGFzcyBnZXRzIGEgZGV0ZXJtaW5pc3RpYyBmYWxsYmFja1xuICAgKiBjb2xvdXIgKGFuZCwgb25seSB3aGVuIGBhdXRvUHJvbW90ZWAgaXMgb24sIGlzIGFkZGVkIHRvIHRoZSBlZGl0YWJsZSBsaXN0KS5cbiAgICogUmVnaW9ucyB0aGUgdXNlciBleHBsaWNpdGx5IHJlY29sb3VyZWQgKGBjb2xvck92ZXJyaWRkZW5gKSBhcmUgbGVmdCB1bnRvdWNoZWQuXG4gICAqL1xuICBwcml2YXRlIGFwcGx5Q2xhc3NpZmljYXRpb25Db2xvcnMocmVnaW9uczogUmVnaW9uW10pOiB2b2lkIHtcbiAgICBjb25zdCBzZXQgPSB0aGlzLnN0b3JlLmdldFByZXNldFNldCgpO1xuICAgIGNvbnN0IGtleU9mID0gKGxhYmVsOiBzdHJpbmcpID0+XG4gICAgICBzZXQubWF0Y2hNb2RlID09PSAnbm9ybWFsaXplZCcgPyBsYWJlbC50cmltKCkudG9Mb3dlckNhc2UoKSA6IGxhYmVsO1xuICAgIGNvbnN0IGtub3duID0gbmV3IFNldChzZXQuY2xhc3Nlcy5tYXAoKGMpID0+IGtleU9mKGMubmFtZSkpKTtcbiAgICBmb3IgKGNvbnN0IHJlZ2lvbiBvZiByZWdpb25zKSB7XG4gICAgICBpZiAoIXJlZ2lvbi5sYWJlbCB8fCByZWdpb24uY29sb3JPdmVycmlkZGVuKSBjb250aW51ZTtcbiAgICAgIGNvbnN0IHByZXNldCA9IGZpbmRQcmVzZXQocmVnaW9uLmxhYmVsLCBzZXQpO1xuICAgICAgaWYgKHByZXNldCkge1xuICAgICAgICByZWdpb24uY29sb3IgPSBwcmVzZXQuY29sb3I7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgY29uc3QgY29sb3IgPSBmYWxsYmFja0NvbG9yRm9yKHJlZ2lvbi5sYWJlbCwgc2V0LmZhbGxiYWNrUGFsZXR0ZSk7XG4gICAgICByZWdpb24uY29sb3IgPSBjb2xvcjtcbiAgICAgIGlmIChzZXQuYXV0b1Byb21vdGUgJiYgIWtub3duLmhhcyhrZXlPZihyZWdpb24ubGFiZWwpKSkge1xuICAgICAgICBrbm93bi5hZGQoa2V5T2YocmVnaW9uLmxhYmVsKSk7XG4gICAgICAgIC8vIEluIG5vcm1hbGl6ZWQgbW9kZSwgdHJpbSB0aGUgcHJvbW90ZWQgbmFtZSBzbyBsZWFkaW5nL3RyYWlsaW5nXG4gICAgICAgIC8vIHdoaXRlc3BhY2UgZG9lc24ndCBjcmVhdGUgaW52aXNpYmxlIGR1cGxpY2F0ZXMgb3Igb2RkIGRpc3BsYXkgbmFtZXMuXG4gICAgICAgIGNvbnN0IG5hbWUgPSBzZXQubWF0Y2hNb2RlID09PSAnbm9ybWFsaXplZCcgPyByZWdpb24ubGFiZWwudHJpbSgpIDogcmVnaW9uLmxhYmVsO1xuICAgICAgICB0aGlzLnN0b3JlLnVwc2VydENsYXNzKHsgbmFtZSwgY29sb3IsIHNvdXJjZTogJ2F1dG8nIH0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgc3luY0NhY2hlKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmN1cnJlbnRJbWFnZUtleSkge1xuICAgICAgdGhpcy5yZWdpb25zQnlJbWFnZUtleS5zZXQodGhpcy5jdXJyZW50SW1hZ2VLZXksIHRoaXMucmVnaW9ucy5zbGljZSgpKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGVtaXQoKTogdm9pZCB7XG4gICAgLy8gTGl2ZS1lZGl0IGxpc3RlbmVycyAoZS5nLiB0aGUgaW50ZW5zaXR5LXByb2ZpbGUgaW5zZXQpIHJlYWN0IG9uIEVWRVJZXG4gICAgLy8gY2hhbmdlIOKAlCBpbmNsdWRpbmcgcGVyLWZyYW1lIGR1cmluZyBhIGJhdGNoZWQgZHJhZyDigJQgc28gdGhleSB0cmFjayB0aGVcbiAgICAvLyByZWdpb24gbGl2ZS4gVGhlIG1haW4gcmVnaW9uVXBkYXRlJCBzdGF5cyBjb2FsZXNjZWQgZHVyaW5nIGEgYmF0Y2ggKGZpcmVzXG4gICAgLy8gb25jZSBvbiBlbmRCYXRjaCkgdG8ga2VlcCBoZWF2aWVyIGNvbnN1bWVycyAoUmVnaW9ucyB0YWIpIGNhbG0uXG4gICAgdGhpcy5yZWdpb25MaXZlRWRpdCQubmV4dCh0aGlzLnJlZ2lvbnMuc2xpY2UoKSk7XG4gICAgaWYgKHRoaXMuYmF0Y2hEZXB0aCA+IDApIHsgdGhpcy5wZW5kaW5nRW1pdCA9IHRydWU7IHJldHVybjsgfVxuICAgIHRoaXMucmVnaW9uVXBkYXRlJC5uZXh0KHRoaXMuZ2V0UmVnaW9ucygpKTtcbiAgfVxuXG4gIC8qKiBQcm9qZWN0IHNlbGVjdGVkIGlkcyB0byBjdXJyZW50IGFycmF5IGluZGljZXMsIHBydW5pbmcgaWRzIHRoYXQgbm8gbG9uZ2VyXG4gICAqICBleGlzdCwgYW5kIGVtaXQgaWYgdGhlIGluZGV4IHNldCBjaGFuZ2VkLiAqL1xuICBwcml2YXRlIGVtaXRTZWxlY3Rpb24oKTogdm9pZCB7XG4gICAgY29uc3QgaW5kaWNlczogbnVtYmVyW10gPSBbXTtcbiAgICBjb25zdCBsaXZlSWRzOiBudW1iZXJbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgaWQgb2YgdGhpcy5zZWxlY3RlZElkcykge1xuICAgICAgY29uc3QgaWR4ID0gdGhpcy5pbmRleE9mSWQoaWQpO1xuICAgICAgaWYgKGlkeCA+PSAwKSB7IGluZGljZXMucHVzaChpZHgpOyBsaXZlSWRzLnB1c2goaWQpOyB9XG4gICAgfVxuICAgIHRoaXMuc2VsZWN0ZWRJZHMgPSBsaXZlSWRzO1xuICAgIGlmICghdGhpcy5pbmRpY2VzRXF1YWwodGhpcy5zZWxlY3RlZEluZGljZXMkLnZhbHVlLCBpbmRpY2VzKSkge1xuICAgICAgdGhpcy5zZWxlY3RlZEluZGljZXMkLm5leHQoaW5kaWNlcyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBpbmRpY2VzRXF1YWwoYTogbnVtYmVyW10sIGI6IG51bWJlcltdKTogYm9vbGVhbiB7XG4gICAgaWYgKGEubGVuZ3RoICE9PSBiLmxlbmd0aCkgcmV0dXJuIGZhbHNlO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYS5sZW5ndGg7IGkrKykgaWYgKGFbaV0gIT09IGJbaV0pIHJldHVybiBmYWxzZTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHByaXZhdGUgZmluZEJ5SWQoaWQ6IG51bWJlcik6IFJlZ2lvbiB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMucmVnaW9ucy5maW5kKHIgPT4gci5pZCA9PT0gaWQpO1xuICB9XG5cbiAgcHJpdmF0ZSBpbmRleE9mSWQoaWQ6IG51bWJlcik6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMucmVnaW9ucy5maW5kSW5kZXgociA9PiByLmlkID09PSBpZCk7XG4gIH1cblxuICAvKiogVGhlIHJlZ2lvbidzIGJvdW5kcyBhcyBhIFBvbHlnb24sIG9yIHVuZGVmaW5lZCBpZiBpdCBpc24ndCBhIHBvbHlnb24uICovXG4gIHByaXZhdGUgcG9seWdvbk9mKGlkOiBudW1iZXIpOiBQb2x5Z29uIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCByID0gdGhpcy5maW5kQnlJZChpZCk7XG4gICAgcmV0dXJuIHIgJiYgci5ib3VuZHMgaW5zdGFuY2VvZiBQb2x5Z29uID8gci5ib3VuZHMgOiB1bmRlZmluZWQ7XG4gIH1cblxuICBwcml2YXRlIGNsb25lUG9seWdvbihwOiBQb2x5Z29uKTogUG9seWdvbiB7XG4gICAgY29uc3QgcG9seSA9IG5ldyBQb2x5Z29uKCk7XG4gICAgcG9seS5ucG9pbnRzID0gcC5ucG9pbnRzO1xuICAgIHBvbHkueHBvaW50cyA9IHAueHBvaW50cy5zbGljZSgpO1xuICAgIHBvbHkueXBvaW50cyA9IHAueXBvaW50cy5zbGljZSgpO1xuICAgIHBvbHkuY29vcmRpbmF0ZXMgPSBwLmNvb3JkaW5hdGVzLm1hcChjID0+IGMuc2xpY2UoKSk7XG4gICAgcG9seS5jbG9zZWQgPSBwLmNsb3NlZDtcbiAgICBwb2x5LmJlemllciA9IHAuYmV6aWVyO1xuICAgIGlmIChwLmhhbmRsZXNJbikgcG9seS5oYW5kbGVzSW4gPSBwLmhhbmRsZXNJbi5tYXAobyA9PiBvLnNsaWNlKCkpO1xuICAgIGlmIChwLmhhbmRsZXNPdXQpIHBvbHkuaGFuZGxlc091dCA9IHAuaGFuZGxlc091dC5tYXAobyA9PiBvLnNsaWNlKCkpO1xuICAgIGlmIChwLmhvbGVzKSBwb2x5LmhvbGVzID0gcC5ob2xlcy5tYXAocmluZyA9PiByaW5nLm1hcChwdCA9PiBwdC5zbGljZSgpKSk7XG4gICAgaWYgKHAuaG9sZUhhbmRsZXNJbikgcG9seS5ob2xlSGFuZGxlc0luID0gcC5ob2xlSGFuZGxlc0luLm1hcChyID0+IHIubWFwKG8gPT4gby5zbGljZSgpKSk7XG4gICAgaWYgKHAuaG9sZUhhbmRsZXNPdXQpIHBvbHkuaG9sZUhhbmRsZXNPdXQgPSBwLmhvbGVIYW5kbGVzT3V0Lm1hcChyID0+IHIubWFwKG8gPT4gby5zbGljZSgpKSk7XG4gICAgcmV0dXJuIHBvbHk7XG4gIH1cblxuICBwcml2YXRlIGNsb25lQm91bmRzKGJvdW5kczogUmVjdGFuZ2xlIHwgUG9seWdvbiB8IE11bHRpUG9seWdvbik6IFJlY3RhbmdsZSB8IFBvbHlnb24gfCBNdWx0aVBvbHlnb24ge1xuICAgIGlmIChib3VuZHMgaW5zdGFuY2VvZiBSZWN0YW5nbGUpIHtcbiAgICAgIGNvbnN0IHJlY3QgPSBuZXcgUmVjdGFuZ2xlKCk7XG4gICAgICByZWN0LnggPSBib3VuZHMueDsgcmVjdC55ID0gYm91bmRzLnk7IHJlY3Qud2lkdGggPSBib3VuZHMud2lkdGg7IHJlY3QuaGVpZ2h0ID0gYm91bmRzLmhlaWdodDtcbiAgICAgIHJldHVybiByZWN0O1xuICAgIH1cbiAgICBpZiAoYm91bmRzIGluc3RhbmNlb2YgTXVsdGlQb2x5Z29uKSB7XG4gICAgICBjb25zdCBtcCA9IG5ldyBNdWx0aVBvbHlnb24oKTtcbiAgICAgIG1wLnBvbHlnb25zID0gYm91bmRzLnBvbHlnb25zLm1hcChwID0+IHRoaXMuY2xvbmVQb2x5Z29uKHApKTtcbiAgICAgIHJldHVybiBtcDtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuY2xvbmVQb2x5Z29uKGJvdW5kcyk7XG4gIH1cblxuICBwcml2YXRlIHJlZ2lvbnNFcXVhbChhOiBSZWdpb24sIGI6IFJlZ2lvbik6IGJvb2xlYW4ge1xuICAgIGNvbnN0IGJhID0gYS5ib3VuZHMsIGJiID0gYi5ib3VuZHM7XG4gICAgaWYgKGJhIGluc3RhbmNlb2YgUmVjdGFuZ2xlICYmIGJiIGluc3RhbmNlb2YgUmVjdGFuZ2xlKSB7XG4gICAgICByZXR1cm4gYmEueCA9PT0gYmIueCAmJiBiYS55ID09PSBiYi55ICYmIGJhLndpZHRoID09PSBiYi53aWR0aCAmJiBiYS5oZWlnaHQgPT09IGJiLmhlaWdodDtcbiAgICB9XG4gICAgaWYgKGJhIGluc3RhbmNlb2YgTXVsdGlQb2x5Z29uICYmIGJiIGluc3RhbmNlb2YgTXVsdGlQb2x5Z29uKSB7XG4gICAgICBpZiAoYmEucG9seWdvbnMubGVuZ3RoICE9PSBiYi5wb2x5Z29ucy5sZW5ndGgpIHJldHVybiBmYWxzZTtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYmEucG9seWdvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYgKCF0aGlzLnBvbHlnb25zRXF1YWwoYmEucG9seWdvbnNbaV0sIGJiLnBvbHlnb25zW2ldKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGlmIChiYSBpbnN0YW5jZW9mIFBvbHlnb24gJiYgYmIgaW5zdGFuY2VvZiBQb2x5Z29uKSB7XG4gICAgICByZXR1cm4gdGhpcy5wb2x5Z29uc0VxdWFsKGJhLCBiYik7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHByaXZhdGUgcG9seWdvbnNFcXVhbChwYTogUG9seWdvbiwgcGI6IFBvbHlnb24pOiBib29sZWFuIHtcbiAgICBpZiAoKHBhLmNsb3NlZCAhPT0gZmFsc2UpICE9PSAocGIuY2xvc2VkICE9PSBmYWxzZSkpIHJldHVybiBmYWxzZTtcbiAgICBpZiAocGEueHBvaW50cy5sZW5ndGggIT09IHBiLnhwb2ludHMubGVuZ3RoKSByZXR1cm4gZmFsc2U7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwYS54cG9pbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAocGEueHBvaW50c1tpXSAhPT0gcGIueHBvaW50c1tpXSB8fCBwYS55cG9pbnRzW2ldICE9PSBwYi55cG9pbnRzW2ldKSByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmhvbGVzRXF1YWwocGEuaG9sZXMsIHBiLmhvbGVzKTtcbiAgfVxuXG4gIC8qKiBDb21wYXJlIHR3byBwb2x5Z29ucycgaW50ZXJpb3ItcmluZyAoaG9sZSkgc2V0cyBmb3IgdGhlIGRlZHVwZSBwYXRoLiAqL1xuICBwcml2YXRlIGhvbGVzRXF1YWwoYTogbnVtYmVyW11bXVtdIHwgdW5kZWZpbmVkLCBiOiBudW1iZXJbXVtdW10gfCB1bmRlZmluZWQpOiBib29sZWFuIHtcbiAgICBjb25zdCBuYSA9IGE/Lmxlbmd0aCA/PyAwLCBuYiA9IGI/Lmxlbmd0aCA/PyAwO1xuICAgIGlmIChuYSAhPT0gbmIpIHJldHVybiBmYWxzZTtcbiAgICBmb3IgKGxldCBoID0gMDsgaCA8IG5hOyBoKyspIHtcbiAgICAgIGNvbnN0IHJhID0gKGEgYXMgbnVtYmVyW11bXVtdKVtoXSwgcmIgPSAoYiBhcyBudW1iZXJbXVtdW10pW2hdO1xuICAgICAgaWYgKHJhLmxlbmd0aCAhPT0gcmIubGVuZ3RoKSByZXR1cm4gZmFsc2U7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmIChyYVtpXVswXSAhPT0gcmJbaV1bMF0gfHwgcmFbaV1bMV0gIT09IHJiW2ldWzFdKSByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG59XG4iXX0=
|
|
1351
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVnaW9uLXN0b3JlLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3N0b3JlL3JlZ2lvbi1zdG9yZS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUFFLGVBQWUsRUFBYyxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFHNUQsT0FBTyxFQUFVLFNBQVMsRUFBRSxPQUFPLEVBQWdCLGFBQWEsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQzNGLE9BQU8sRUFFTCxlQUFlLEVBQ2YsaUJBQWlCLEVBQ2pCLHdCQUF3QixFQUN4QixrQkFBa0IsRUFDbEIsZ0JBQWdCLEdBQ2pCLE1BQU0sMEJBQTBCLENBQUM7QUFDbEMsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBRzdELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxhQUFhLEVBQUUsU0FBUyxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDakYsT0FBTyxFQUNMLFdBQVcsRUFDWCxXQUFXLEVBQ1gsVUFBVSxFQUNWLGNBQWMsRUFDZCxlQUFlLEVBQ2YsYUFBYSxHQUNkLE1BQU0sMkJBQTJCLENBQUM7QUFFbkMsT0FBTyxFQUFpQixZQUFZLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN0RSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSx1Q0FBdUMsQ0FBQztBQUM1RSxPQUFPLEtBQUssSUFBSSxNQUFNLHdCQUF3QixDQUFDO0FBQy9DLE9BQU8sRUFBRSxZQUFZLEVBQUUsZUFBZSxFQUFFLFdBQVcsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3BGLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNqRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDckQsT0FBTyxFQUFFLGdCQUFnQixF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LENBQUM7WUFDeEIsT0FBTztRQUNULENBQUM7UUFDRCxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQztJQUM3QyxDQUFDO0lBRUQ7K0NBQzJDO0lBQ25DLGFBQWE7UUFDbkIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3BDLENBQUM7SUFFTyxRQUFRLENBQUMsRUFBVTtRQUN6QixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO0lBQy9DLENBQUM7SUFFTyxTQUFTLENBQUMsRUFBVTtRQUMxQixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO0lBQ3BELENBQUM7OEdBdnpDVSxXQUFXO2tIQUFYLFdBQVcsY0FERSxNQUFNOzsyRkFDbkIsV0FBVztrQkFEdkIsVUFBVTttQkFBQyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIE9ic2VydmFibGUsIFN1YmplY3QgfSBmcm9tICdyeGpzJztcblxuaW1wb3J0IHsgSUltYWdlSW5mbyB9IGZyb20gJy4uL2NvbnRyYWN0cy9pbWFnZS5jb250cmFjdCc7XG5pbXBvcnQgeyBSZWdpb24sIFJlY3RhbmdsZSwgUG9seWdvbiwgTXVsdGlQb2x5Z29uLCBoeWRyYXRlQm91bmRzIH0gZnJvbSAnLi4vbW9kZWxzL3JlZ2lvbic7XG5pbXBvcnQge1xuICBHZW9Kc29uRmVhdHVyZSxcbiAgZG93bmxvYWRHZW9Kc29uLFxuICBmZWF0dXJlRnJvbVJlZ2lvbixcbiAgcmVnaW9uRnJvbUdlb0pzb25GZWF0dXJlLFxuICByZWdpb25zRnJvbUdlb0pzb24sXG4gIHJlZ2lvbnNUb0dlb0pzb24sXG59IGZyb20gJy4uL21vZGVscy9yZWdpb24tZ2VvanNvbic7XG5pbXBvcnQgeyBWaXN1YWxpemVyU3RvcmUgfSBmcm9tICcuL3Zpc3VhbGl6ZXItc3RvcmUuc2VydmljZSc7XG5pbXBvcnQgeyBJUmVnaW9uU3RvcmUgfSBmcm9tICcuLi9jb250cmFjdHMvdmlzdWFsaXplci5jb250cmFjdCc7XG5pbXBvcnQgeyBJUmVnaW9uRWRpdEFwaSwgSVJlZ2lvblNvdXJjZUFwaSB9IGZyb20gJy4uL2NvbnRyYWN0cy9yZWdpb24tc3RvcmUuY29udHJhY3QnO1xuaW1wb3J0IHsgYXBwbHlQcmVzZXRDb2xvcnMsIGNvbG9yRm9yTGFiZWwsIHByZXNldEtleSB9IGZyb20gJy4vY2xhc3MtY29sb3IudXRpbCc7XG5pbXBvcnQge1xuICBjbG9uZUJvdW5kcyxcbiAgbWFrZVBvbHlnb24sXG4gIHJlY3RUb1JpbmcsXG4gIHJlZ2lvblBvbHlnb25zLFxuICByZWdpb25Qb2x5bGluZXMsXG4gIHJlcGxhY2VCb3VuZHMsXG59IGZyb20gJy4uL21vZGVscy9wb2x5Z29uLWZhY3RvcnknO1xuaW1wb3J0IHR5cGUgeyBNZXNoIH0gZnJvbSAnbmFwYXJpLWpzL2dlb21ldHJ5JztcbmltcG9ydCB7IFNsaWNlT3V0bGluZXMsIG91dGxpbmVzQXJlYSB9IGZyb20gJy4uL2dlb21ldHJ5L3JlY29uc3RydWN0JztcbmltcG9ydCB7IHJlY29uc3RydWN0SW5Xb3JrZXIgfSBmcm9tICcuLi9yZWdpb24tc291cmNlL3dvcmtlci1yZWdpb24tc291cmNlJztcbmltcG9ydCAqIGFzIGVkaXQgZnJvbSAnLi4vbW9kZWxzL3BvbHlnb24tZWRpdCc7XG5pbXBvcnQgeyByZWdpb25zRXF1YWwsIHdpdGhSZWdpb25QYXRjaCwgd2l0aFJlZ2lvblogfSBmcm9tICcuLi9tb2RlbHMvcmVnaW9uLWNsb25lJztcbmltcG9ydCB7IFJlZ2lvbkhpc3RvcnkgfSBmcm9tICcuL3JlZ2lvbi1oaXN0b3J5JztcbmltcG9ydCB7IFJlZ2lvblNlbGVjdGlvbiB9IGZyb20gJy4vcmVnaW9uLXNlbGVjdGlvbic7XG5pbXBvcnQgeyBSZWdpb25TY29wZUNhY2hlLCBTdGFja1NhdmVMYXlvdXQgfSBmcm9tICcuL3JlZ2lvbi1zY29wZS1jYWNoZSc7XG5pbXBvcnQgeyBSZWdpb25Tb3VyY2VPcGVuZXIsIFJlZ2lvblNvdXJjZVNjb3BlLCBSZWdpb25Tb3VyY2VTbGljZXMgfSBmcm9tICcuL3JlZ2lvbi1zb3VyY2Utc2NvcGUnO1xuaW1wb3J0IHR5cGUgeyBSZWdpb25Tb3VyY2UsIFJlZ2lvblNvdXJjZVZpZXcgfSBmcm9tICcuLi9yZWdpb24tc291cmNlL3JlZ2lvbi1zb3VyY2UnO1xuaW1wb3J0IHR5cGUgeyBSZWdpb25JbmRleFBhZ2UsIFJlZ2lvbkluZGV4UXVlcnksIFJlZ2lvblNvdXJjZVN0eWxlIH0gZnJvbSAnLi4vcmVnaW9uLXNvdXJjZS9yZWdpb24tdGlsZXMnO1xuaW1wb3J0IHsgREVGQVVMVF9SRUdJT05fU1RZTEUsIFJlZ2lvblN0eWxlIH0gZnJvbSAnLi4vcmVnaW9uLW92ZXJsYXkvcmVnaW9uLXN0eWxlJztcblxuLyoqIFNlbGVjdGluZyBjbGFzc2VzIHRha2VzIGF0IG1vc3QgdGhpcyBtYW55IHJlZ2lvbi1zb3VyY2UgZmVhdHVyZXMgaW50byB0aGUgcmVnaW9ucy4gKi9cbmV4cG9ydCBjb25zdCBTRUxFQ1RfQ0xBU1NFU19MSU1JVCA9IDUwMDA7XG4vKiogQSByZWdpb24gc291cmNlJ3Mgb3V0bGluZXMgb24gYSBzbGljZSwgZWFjaCByaW5nJ3MgYW5kIGxpbmUncyBjbGFzcyB3aXRoIGl0IHdoZW4gcmVhZCBmb3IgYWxsLiAqL1xudHlwZSBMYWJlbGxlZE91dGxpbmVzID0gU2xpY2VPdXRsaW5lcyAmIHsgcmluZ0xhYmVscz86IHN0cmluZ1tdOyBsaW5lTGFiZWxzPzogc3RyaW5nW10gfTtcblxuLyoqIENsYXNzIHNldHMgd2hvc2UgcmVnaW9uLXNvdXJjZSBvdXRsaW5lcyBhcmUga2VwdCBmb3IgcmVidWlsZGluZyB0aGVpciBzdXJmYWNlcy4gKi9cbmNvbnN0IFNPVVJDRV9PVVRMSU5FX0NBQ0hFX1NJWkUgPSA4O1xuLyoqIENsYXNzZXMgd2hvc2UgcmVnaW9uLXNvdXJjZSBwYXJ0IG9mIHRoZSB2b2x1bWUgaXMga2VwdCAoc2VlIFJlZ2lvblN0b3JlLmNsYXNzVm9sdW1lcykuICovXG5jb25zdCBTT1VSQ0VfVk9MVU1FX0NBQ0hFX1NJWkUgPSA2NDtcblxuLyoqIEEgc2xpY2UncyByaW5ncywgZWFjaCB3aXRoIGl0cyBmZWF0dXJlIChzZWUgU2xpY2VPdXRsaW5lcy5yaW5nR3JvdXBzKSwgYW5kIGl0cyBsaW5lcy4gKi9cbmludGVyZmFjZSBTbGljZVBhcnRzIHtcbiAgcmluZ3M6IEFycmF5TGlrZTxudW1iZXI+W107XG4gIHJpbmdHcm91cHM6IG51bWJlcltdO1xuICBsaW5lczogQXJyYXlMaWtlPG51bWJlcj5bXTtcbn1cblxuLyoqXG4gKiBGZWF0dXJlIGlkcyB1bmlxdWUgYWNyb3NzIG91dGxpbmVzIHJlYWQgZnJvbSBzZXZlcmFsIHBsYWNlczogZWFjaCBjYWxsIGdpdmVzIG9uZSBwYXJ0J3NcbiAqIHJlbnVtYmVyaW5nIG9mIGl0cyBvd24gaWRzIChhIHBhcnQgd2l0aG91dCB0aGVtIGlzIG9uZSBmZWF0dXJlKS5cbiAqL1xuZnVuY3Rpb24gZmVhdHVyZUlkcygpOiAoKSA9PiAob3duOiBudW1iZXIgfCB1bmRlZmluZWQpID0+IG51bWJlciB7XG4gIGxldCBuZXh0ID0gMDtcbiAgcmV0dXJuICgpID0+IHtcbiAgICBjb25zdCBpZHMgPSBuZXcgTWFwPG51bWJlciB8IHVuZGVmaW5lZCwgbnVtYmVyPigpO1xuICAgIHJldHVybiAob3duKSA9PiB7XG4gICAgICBsZXQgaWQgPSBpZHMuZ2V0KG93bik7XG4gICAgICBpZiAoaWQgPT09IHVuZGVmaW5lZCkgaWRzLnNldChvd24sIChpZCA9IG5leHQrKykpO1xuICAgICAgcmV0dXJuIGlkO1xuICAgIH07XG4gIH07XG59XG5cbi8qKiBBIHNsaWNlJ3MgcGFydHMgYXMgb3V0bGluZXMuICovXG5mdW5jdGlvbiBzbGljZU91dGxpbmVzKHo6IG51bWJlciwgczogU2xpY2VQYXJ0cyk6IFNsaWNlT3V0bGluZXMge1xuICByZXR1cm4ge1xuICAgIHosXG4gICAgcmluZ3M6IHMucmluZ3MsXG4gICAgLi4uKHMucmluZ3MubGVuZ3RoID8geyByaW5nR3JvdXBzOiBzLnJpbmdHcm91cHMgfSA6IHt9KSxcbiAgICAuLi4ocy5saW5lcy5sZW5ndGggPyB7IGxpbmVzOiBzLmxpbmVzIH0gOiB7fSksXG4gIH07XG59XG5cbi8qKlxuICogT3V0bGluZXMgYnkgc2xpY2UgbWVyZ2VkIGludG8gb25lIGVudHJ5IHBlciBzbGljZSAocmluZ3MsIHRoZW4gbGluZXMpLCBpbiBzbGljZSBvcmRlciwgZWFjaFxuICogcGFydCdzIGZlYXR1cmVzIGFwYXJ0IGZyb20gdGhlIG90aGVycycgKHRoZXkgZmlsbCBhcyB0aGVpciB1bmlvbikuXG4gKi9cbmZ1bmN0aW9uIG1lcmdlT3V0bGluZXMocGFydHM6IHJlYWRvbmx5IFNsaWNlT3V0bGluZXNbXSk6IFNsaWNlT3V0bGluZXNbXSB7XG4gIGNvbnN0IGJ5WiA9IG5ldyBNYXA8bnVtYmVyLCBTbGljZVBhcnRzPigpO1xuICBjb25zdCBuZXh0UGFydCA9IGZlYXR1cmVJZHMoKTtcbiAgZm9yIChjb25zdCBwYXJ0IG9mIHBhcnRzKSB7XG4gICAgaWYgKCFwYXJ0LnJpbmdzLmxlbmd0aCAmJiAhcGFydC5saW5lcz8ubGVuZ3RoKSBjb250aW51ZTtcbiAgICBsZXQgc2xpY2UgPSBieVouZ2V0KHBhcnQueik7XG4gICAgaWYgKCFzbGljZSkgYnlaLnNldChwYXJ0LnosIChzbGljZSA9IHsgcmluZ3M6IFtdLCByaW5nR3JvdXBzOiBbXSwgbGluZXM6IFtdIH0pKTtcbiAgICBjb25zdCBpZCA9IG5leHRQYXJ0KCk7XG4gICAgcGFydC5yaW5ncy5mb3JFYWNoKChyLCBpKSA9PiB7XG4gICAgICBzbGljZS5yaW5ncy5wdXNoKHIpO1xuICAgICAgc2xpY2UucmluZ0dyb3Vwcy5wdXNoKGlkKHBhcnQucmluZ0dyb3Vwcz8uW2ldKSk7XG4gICAgfSk7XG4gICAgc2xpY2UubGluZXMucHVzaCguLi4ocGFydC5saW5lcyA/PyBbXSkpO1xuICB9XG4gIHJldHVybiBBcnJheS5mcm9tKGJ5WiwgKFt6LCBzXSkgPT4gc2xpY2VPdXRsaW5lcyh6LCBzKSkuc29ydCgoYSwgYikgPT4gYS56IC0gYi56KTtcbn1cblxuLyoqIFRoZSByZWdpb24gc291cmNlcycgcGFydCBvZiBhIGNsYXNzJ3Mgdm9sdW1lOiBpdHMgYXJlYSBvbiBlYWNoIHNsaWNlLCB3aXRoIHRoZSBvdXRsaW5lcy4gKi9cbmludGVyZmFjZSBTb3VyY2VWb2x1bWUge1xuICB0b3RhbDogbnVtYmVyO1xuICBzbGljZXM6IFJlYWRvbmx5TWFwPG51bWJlciwgeyBhcmVhOiBudW1iZXI7IG91dGxpbmVzOiBTbGljZU91dGxpbmVzIH0+O1xufVxuXG4vKiogT25lIHVuZG8gc3RlcDogdGhlIHJlZ2lvbiBzZXQgYW5kLCBmb3IgYSBzbGljZSB3aXRoIGEgcmVnaW9uIHNvdXJjZSwgd2hhdCB3YXMgdGFrZW4gZnJvbSBpdC4gKi9cbmludGVyZmFjZSBSZWdpb25TbmFwc2hvdCB7XG4gIHJlZ2lvbnM6IFJlZ2lvbltdO1xuICB0YWtlbjogUmVhZG9ubHlTZXQ8c3RyaW5nPjtcbn1cblxuLyoqXG4gKiBCYWNrZW5kLW5ldXRyYWwgcmVnaW9uIHN0b3JlIOKAlCB0aGUgc2luZ2xlIHNvdXJjZSBvZiB0cnV0aCBmb3IgcmVnaW9uIHN0YXRlLlxuICpcbiAqIEhvbGRzIHRoZSBuZXV0cmFsIHtAbGluayBSZWdpb259IG1vZGVsIChuZXZlciBhIGJhY2tlbmQncyBvd24gc2hhcGVcbiAqIHJlcHJlc2VudGF0aW9uKSwga2V5ZWQgcGVyIGltYWdlIHNvIHJlZ2lvbnMgcGVyc2lzdCBhcyB0aGUgdXNlciBzd2l0Y2hlc1xuICogZmlsZXMgYW5kIHN1cnZpdmUgYSBQbG90bHnih4RPcGVuU2VhZHJhZ29uIGJhY2tlbmQgc3dpdGNoIChib3RoIGJhY2tlbmRzIHJlYWRcbiAqIGFuZCB3cml0ZSAqdGhpcyogc3RvcmUsIHNvIG5vIG1pZ3JhdGlvbiBpcyBuZWVkZWQpLiBCYWNrZW5kcyBvd24gKnJlbmRlcmluZypcbiAqIGFuZCByZWFjdCB0byB7QGxpbmsgZ2V0UmVnaW9uVXBkYXRlRXZlbnR9OyB0aGlzIHNlcnZpY2Ugb3ducyAqc3RhdGUqIGFuZCB0aGVcbiAqIGVkaXRpbmcgb3BlcmF0aW9ucy5cbiAqXG4gKiBJbXBsZW1lbnRzOlxuICogIC0ge0BsaW5rIElSZWdpb25TdG9yZX0g4oCUIHRoZSBjcm9zcy1iYWNrZW5kIENSVUQvc2VsZWN0aW9uL2NvbG91ciBjb250cmFjdFxuICogICAgZXZlcnkgY29uc3VtZXIgKFJlZ2lvbiBFZGl0b3IsIHNlZ21lbnRhdGlvbiwgZXRjLikgYWxyZWFkeSB1c2VzLlxuICogIC0ge0BsaW5rIElSZWdpb25FZGl0QXBpfSDigJQgUmVnaW9uLW5hdGl2ZSBnZW9tZXRyeSBlZGl0cyAobW92ZS9yZXNpemUsIGFuZFxuICogICAgYWRkL2RlbGV0ZS9tb3ZlIHZlcnRleCkgdGhlIE9TRCBvdmVybGF5IGRyaXZlcy5cbiAqXG4gKiBDb3B5LW9uLXdyaXRlIChyZXZpZXcgUlQtMTMpOiBubyBvcGVyYXRpb24gY2hhbmdlcyBhIHN0b3JlZCB7QGxpbmsgUmVnaW9ufVxuICogKG9yIHRoZSByZWdpb25zIGFycmF5KSBpbiBwbGFjZS4gQW4gZWRpdCBidWlsZHMgYSByZXBsYWNlbWVudCDigJQgdGhlIGdlb21ldHJ5XG4gKiB0aHJvdWdoIHRoZSBwdXJlIGBtb2RlbHMvcG9seWdvbi1lZGl0YCBmdW5jdGlvbnMg4oCUIGFuZCBzd2FwcyBpdCBpbiwgc28gdGhlXG4gKiB1bmRvIGhpc3RvcnkgKHtAbGluayBSZWdpb25IaXN0b3J5fSkgY2FuIGtlZXAgc2hhbGxvdyBzbmFwc2hvdHMgdGhhdCBzaGFyZVxuICogZXZlcnkgdW50b3VjaGVkIHJlZ2lvbiBpbnN0ZWFkIG9mIGRlZXAtY2xvbmluZyB0aGUgd2hvbGUgc2V0IHBlciBzdGVwLlxuICogQ2FsbGVycyBtdXN0IGZvbGxvdyB0aGUgc2FtZSBydWxlIHdpdGggdGhlIGluc3RhbmNlcyB7QGxpbmsgZ2V0UmVnaW9uc31cbiAqIHJldHVybnM6IHRyZWF0IHRoZW0gYXMgcmVhZC1vbmx5LCBhbmQgY29tbWl0IGEgY2hhbmdlZCBjb3B5LlxuICpcbiAqIENsYXNzaWZpY2F0aW9uIGNvbG91cnMgbGl2ZSBpbiB7QGxpbmsgVmlzdWFsaXplclN0b3JlfSAoc2hhcmVkIGJ5IGJvdGhcbiAqIGJhY2tlbmRzKTsgR2VvSlNPTiBpbXBvcnQvZXhwb3J0IGlzIGBtb2RlbHMvcmVnaW9uLWdlb2pzb25gLiBBbGwgY29vcmRpbmF0ZXNcbiAqIGFyZSBpbWFnZSBwaXhlbHMuXG4gKi9cbkBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogJ3Jvb3QnIH0pXG5leHBvcnQgY2xhc3MgUmVnaW9uU3RvcmUgaW1wbGVtZW50cyBJUmVnaW9uU3RvcmUsIElSZWdpb25FZGl0QXBpLCBJUmVnaW9uU291cmNlQXBpIHtcbiAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgVU5ET19MSU1JVCA9IDEwO1xuICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBVTkRPX0NPQUxFU0NFX01TID0gMjUwO1xuXG4gIC8qKiBUaGUgY3VycmVudCBpbWFnZSdzIHJlZ2lvbnMg4oCUIHRoZSBsaXZlLCBlZGl0ZWQgYXJyYXkuICovXG4gIHByaXZhdGUgcmVnaW9uczogUmVnaW9uW10gPSBbXTtcblxuICAvKipcbiAgICogVW5kby9yZWRvIGhpc3RvcnkgKGppdC11aSM4NSk6IHVwIHRvIHtAbGluayBVTkRPX0xJTUlUfSBzbmFwc2hvdHMgb2YgdGhlXG4gICAqIHJlZ2lvbiBzZXQsIGVhY2ggdGFrZW4ganVzdCAqYmVmb3JlKiBhIHJlZ2lvbi1lZGl0aW5nIGFjdGlvbjsgY29udGludW91c1xuICAgKiBnZXN0dXJlcyBhbmQgcmFwaWQgY29tbWl0cyBjb2FsZXNjZSAoc2VlIHtAbGluayBSZWdpb25IaXN0b3J5fSkuIFNuYXBzaG90c1xuICAgKiBhcmUgc2hhbGxvdyDigJQgdGhlIHJlZ2lvbnMgYXJyYXkgYXMgaXQgd2FzIOKAlCB3aGljaCBpcyBzYWZlIGJlY2F1c2Ugbm90aGluZ1xuICAgKiBoZXJlIG11dGF0ZXMgYSByZWdpb24gb3IgYW4gYXJyYXkgaW4gcGxhY2UgKFJULTEzKS4gSGlzdG9yeSBuZXZlciBjcm9zc2VzIGFuXG4gICAqIGltYWdlIGxvYWQvc3dpdGNoIOKAlCB7QGxpbmsgcmVzZXRVbmRvSGlzdG9yeX0gY2xlYXJzIGl0LlxuICAgKi9cbiAgcHJpdmF0ZSByZWFkb25seSBoaXN0b3J5ID0gbmV3IFJlZ2lvbkhpc3Rvcnk8UmVnaW9uU25hcHNob3Q+KFxuICAgIFJlZ2lvblN0b3JlLlVORE9fTElNSVQsXG4gICAgUmVnaW9uU3RvcmUuVU5ET19DT0FMRVNDRV9NUyxcbiAgKTtcblxuICAvKiogTW9ub3RvbmljIGlkIHNvdXJjZSDigJQgaWRzIG5ldmVyIHJlcGVhdCB3aXRoaW4gdGhlIHNlcnZpY2UgbGlmZXRpbWUsIHNvXG4gICAqICBzZWxlY3Rpb24gc3RheXMgY29ycmVjdCBhY3Jvc3MgZGVsZXRlL2FkZCBjeWNsZXMgZXZlbiB3aGVuIG5hbWVzIGNvbGxpZGUuICovXG4gIHByaXZhdGUgbmV4dElkID0gMTtcblxuICBwcml2YXRlIHNob3dTaGFwZUxhYmVsID0gZmFsc2U7XG4gIHByaXZhdGUgc2hhcGVDb2xvciA9ICcjMDBGRkZGJztcbiAgcHJpdmF0ZSBmaWxsQ29sb3IgPSAnI2ZmMDBmZic7XG4gIHByaXZhdGUgaXNSZWdpb25TYXZlZE9uID0gdHJ1ZTtcblxuICAvKipcbiAgICogUGVyLWltYWdlIGNhY2hlIGFuZCwgZm9yIHotc3RhY2tzLCBwZXItc2xpY2UgcmVnaW9ucyAoaml0LXVpIzkzKS4gSW4gc3RhY2tcbiAgICogbW9kZSB0aGUgbGl2ZSBgcmVnaW9uc2AgYXJyYXkgaG9sZHMgT05FIHNsaWNlIOKAlCB0aGUgZGlzcGxheSBzbGljZSDigJQgc28gdGhlXG4gICAqIG92ZXJsYXlzLCB0aGUgc2VsZWN0aW9uIHByb2plY3Rpb24gYW5kIHRoZSBSZWdpb25zIHRhYmxlIHdvcmsgdW5jaGFuZ2VkXG4gICAqICh0aGV5IGFsbCByZWFkIHtAbGluayBnZXRSZWdpb25zfSk7IHtAbGluayBzZXREaXNwbGF5U2xpY2V9IHN3YXBzIHRoZSBsaXZlXG4gICAqIHNldCBvbiBzY3J1YiBhbmQge0BsaW5rIGdldFNsaWNlUmVnaW9uc30gZmxhdHRlbnMgZXZlcnkgc2xpY2UgKGVhY2ggdGFnZ2VkXG4gICAqIHdpdGggaXRzIHplcm8tYmFzZWQge0BsaW5rIFJlZ2lvbi56fSkgZm9yIHNhdmUvZXhwb3J0LiBPZmYgYnkgZGVmYXVsdCwgc29cbiAgICogc2luZ2xlLXBsYW5lIGltYWdlcyBhcmUgdW5hZmZlY3RlZC5cbiAgICovXG4gIHByaXZhdGUgcmVhZG9ubHkgc2NvcGUgPSBuZXcgUmVnaW9uU2NvcGVDYWNoZSgpO1xuXG4gIC8qKiBTZWxlY3Rpb24gYnkgcmVnaW9uICppZCogKHN0YWJsZSBhY3Jvc3MgZWRpdHMpLCBwcm9qZWN0ZWQgdG8gYXJyYXlcbiAgICogIGluZGljZXMgb24gdGhlIElSZWdpb25TdG9yZSBib3VuZGFyeS4gKi9cbiAgcHJpdmF0ZSByZWFkb25seSBzZWxlY3Rpb24gPSBuZXcgUmVnaW9uU2VsZWN0aW9uKCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgcmVnaW9uVXBkYXRlJCA9IG5ldyBTdWJqZWN0PFJlZ2lvbltdPigpO1xuICAvKiogTm9uLWNvYWxlc2NlZCBzaWJsaW5nIG9mIHJlZ2lvblVwZGF0ZSQ6IGZpcmVzIG9uIGV2ZXJ5IGNoYW5nZSBldmVuIGR1cmluZyBhXG4gICAqICBiYXRjaGVkIGRyYWcsIHNvIGxpdmUgY29uc3VtZXJzIChpbnRlbnNpdHkgaW5zZXQpIHVwZGF0ZSBwZXIgZnJhbWUuICovXG4gIHByaXZhdGUgcmVhZG9ubHkgcmVnaW9uTGl2ZUVkaXQkID0gbmV3IFN1YmplY3Q8UmVnaW9uW10+KCk7XG4gIC8qKiBTZWUge0BsaW5rIGdldFJlZ2lvblNldFJlcGxhY2VkJH0uICovXG4gIHByaXZhdGUgcmVhZG9ubHkgcmVnaW9uU2V0UmVwbGFjZWQkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICAvKiogRW1pdCBjb2FsZXNjaW5nIGZvciBsaXZlIGRyYWdzIChzZWUgSVJlZ2lvbkVkaXRBcGkuYmVnaW5CYXRjaCkuICovXG4gIHByaXZhdGUgYmF0Y2hEZXB0aCA9IDA7XG4gIHByaXZhdGUgcGVuZGluZ0VtaXQgPSBmYWxzZTtcblxuICAvKipcbiAgICogTGFyZ2UgcmVnaW9uIHNldHMgaGVsZCBhcyB0aWxlZCByZWdpb24gc291cmNlcyByYXRoZXIgdGhhbiBhcyByZWdpb25zIChzZWVcbiAgICoge0BsaW5rIGF0dGFjaFJlZ2lvblNvdXJjZX0pOiBwZXIgaW1hZ2UgYW5kIHNsaWNlLCB3aXRoIHRoZSBpZHMgdGFrZW4gb3V0IG9mIGVhY2guXG4gICAqL1xuICBwcml2YXRlIHJlYWRvbmx5IHNvdXJjZXMgPSBuZXcgUmVnaW9uU291cmNlU2NvcGUoKTtcbiAgcHJpdmF0ZSByZWFkb25seSBzb3VyY2VWaWV3JCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8UmVnaW9uU291cmNlVmlldyB8IG51bGw+KG51bGwpO1xuICAvKiogVGhlIHJlZ2lvbiBsb29rIHRoZSB1c2VyIGNob3NlIChvdmVycmlkZXMgdGhlIHNvdXJjZSdzIGhpbnQpLCBmaWVsZCBieSBmaWVsZC4gKi9cbiAgcHJpdmF0ZSB1c2VyU3R5bGU6IFBhcnRpYWw8UmVnaW9uU3R5bGU+ID0ge307XG4gIC8qKiBUaGUgY3VycmVudCBzb3VyY2UncyBzdHlsZSBoaW50LiAqL1xuICBwcml2YXRlIGhpbnRTdHlsZTogUmVnaW9uU291cmNlU3R5bGUgfCB1bmRlZmluZWQ7XG4gIHByaXZhdGUgcmVhZG9ubHkgcmVnaW9uU3R5bGUkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxSZWdpb25TdHlsZT4oREVGQVVMVF9SRUdJT05fU1RZTEUpO1xuICAvKiogQnVtcGVkIG9uIGV2ZXJ5IGNoYW5nZSBvZiB0aGUgc2xpY2UncyBzb3VyY2UsIHNvIGEgbGF0ZSBvcGVuIGlzIGRyb3BwZWQuICovXG4gIHByaXZhdGUgc291cmNlR2VuZXJhdGlvbiA9IDA7XG4gIC8qKiBUaGUgc291cmNlIGxhc3QgcHVibGlzaGVkIGFzIHRoZSB2aWV3OiBhIHNvdXJjZSBzaG93biBhZ2FpbiBkb2VzIG5vdCB0dXJuIHRoZSBsYWJlbHMgYmFjayBvbi4gKi9cbiAgcHJpdmF0ZSBzaG93blNvdXJjZTogUmVnaW9uU291cmNlIHwgbnVsbCA9IG51bGw7XG4gIC8qKiBCdW1wZWQgd2hlbiBhIHJlZ2lvbiBzb3VyY2UgaXMgYXR0YWNoZWQgb3IgZHJvcHBlZDogd2hhdCBpcyByZWFkIGZyb20gdGhlIHNvdXJjZXMgaXMgc3RhbGUuICovXG4gIHByaXZhdGUgc291cmNlc1ZlcnNpb24gPSAwO1xuXG4gIC8qKlxuICAgKiBUaGUgcmVnaW9uIHNvdXJjZXMnIHBhcnQgb2Yge0BsaW5rIGNsYXNzVm9sdW1lc30sIGJ5IGNsYXNzIGFuZCB3aGF0IHRoZSBzb3VyY2VzIGhvbGQgKHNlZVxuICAgKiB7QGxpbmsgc291cmNlU3RhdGVLZXl9KTogYW4gZWRpdCBvZiB0aGUgcmVnaW9ucyBsZWF2ZXMgaXQsIHNvIHRoZSB2b2x1bWVzIG9mIGEgc2xpY2UgYmVpbmcgZHJhd25cbiAgICogb24gY29zdCBubyBzb3VyY2UgcmVhZHMuXG4gICAqL1xuICBwcml2YXRlIHJlYWRvbmx5IHNvdXJjZVZvbHVtZUNhY2hlID0gbmV3IE1hcDxzdHJpbmcsIFByb21pc2U8U291cmNlVm9sdW1lPj4oKTtcbiAgLyoqIFRoZSByZWdpb24gc291cmNlcycgb3V0bGluZXMgb2YgdGhlIGNsYXNzIHNldHMgcmVjb25zdHJ1Y3RlZCBsYXN0IChzZWUge0BsaW5rIHNvdXJjZU91dGxpbmVzfSkuICovXG4gIHByaXZhdGUgcmVhZG9ubHkgc291cmNlT3V0bGluZUNhY2hlID0gbmV3IE1hcDxzdHJpbmcsIFByb21pc2U8TGFiZWxsZWRPdXRsaW5lc1tdPj4oKTtcblxuICAvKiogVGhlIGNsYXNzZXMgaGlkZGVuIGZyb20gdmlldyAobmFtZXMgYXMgZ2l2ZW4pOyBldmVyeSBjbGFzcyBpcyBzaG93biBhdCBmaXJzdC4gKi9cbiAgcHJpdmF0ZSByZWFkb25seSBoaWRkZW5DbGFzc2VzJCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8UmVhZG9ubHlTZXQ8c3RyaW5nPj4obmV3IFNldCgpKTtcbiAgLyoqIHtAbGluayBoaWRkZW5DbGFzc2VzJH0gYnkge0BsaW5rIHByZXNldEtleX0sIGFzIGEgcmVnaW9uJ3MgbGFiZWwgaXMgbWF0Y2hlZC4gKi9cbiAgcHJpdmF0ZSBoaWRkZW5LZXlzOiBSZWFkb25seVNldDxzdHJpbmc+ID0gbmV3IFNldCgpO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgc3RvcmU6IFZpc3VhbGl6ZXJTdG9yZSkge1xuICAgIC8vIEEgY2xhc3MgY29sb3VyIGNoYW5nZSByZWNvbG91cnMgdGhlIHNvdXJjZSdzIGZlYXR1cmVzIGFzIGl0IHJlY29sb3VycyByZWdpb25zLlxuICAgIHRoaXMuc3RvcmUuZ2V0UHJlc2V0U2V0JCgpLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICBjb25zdCB2aWV3ID0gdGhpcy5zb3VyY2VWaWV3JC52YWx1ZTtcbiAgICAgIGlmICh2aWV3KSB0aGlzLnNvdXJjZVZpZXckLm5leHQoeyAuLi52aWV3IH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLy8g4pSA4pSAIElSZWdpb25TdG9yZTogQ1JVRCDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICAvKipcbiAgICogUmVwbGFjZSAob3IsIHdpdGggYGFwcGVuZGAsIGFkZCB0bykgdGhlIGN1cnJlbnQgaW1hZ2UncyByZWdpb25zLiBNaW50cyBpZHNcbiAgICogYW5kIGRlZmF1bHQgbmFtZXMsIGFwcGxpZXMgc3RvcmVkIGNsYXNzaWZpY2F0aW9uIGNvbG91cnMsIGFuZCBlbWl0cy4gV2hlblxuICAgKiBgaXNSZWdpb25TYXZlT25gIGlzIGZhbHNlIHRoZSByZWdpb25zIGFyZSBzaG93biB0cmFuc2llbnRseSAoZW1pdHRlZCkgYnV0XG4gICAqIG5vdCBzdG9yZWQg4oCUIG1pcnJvcnMgdGhlIHByZXZpb3VzIFBsb3RseSBiZWhhdmlvdXIuXG4gICAqL1xuICBzZXRSZWdpb25zKFxuICAgIHJlZ2lvbnM6IFJlZ2lvbltdLFxuICAgIHNob3dSZWdpb25MYWJlbD86IGJvb2xlYW4sXG4gICAgaXNSZWdpb25TYXZlT24/OiBib29sZWFuLFxuICAgIGZpbGxDb2xvcj86IHN0cmluZyxcbiAgICBhcHBlbmQ6IGJvb2xlYW4gPSBmYWxzZSxcbiAgKTogdm9pZCB7XG4gICAgaWYgKHNob3dSZWdpb25MYWJlbCA9PT0gdW5kZWZpbmVkKSBzaG93UmVnaW9uTGFiZWwgPSB0aGlzLnNob3dTaGFwZUxhYmVsO1xuICAgIGlmIChpc1JlZ2lvblNhdmVPbiA9PT0gdW5kZWZpbmVkKSBpc1JlZ2lvblNhdmVPbiA9IHRoaXMuaXNSZWdpb25TYXZlZE9uO1xuICAgIGlmIChmaWxsQ29sb3IgPT09IHVuZGVmaW5lZCkgZmlsbENvbG9yID0gdGhpcy5maWxsQ29sb3I7XG5cbiAgICByZWdpb25zID0gdGhpcy5hZG1pdChyZWdpb25zKTtcblxuICAgIHRoaXMuaXNSZWdpb25TYXZlZE9uID0gaXNSZWdpb25TYXZlT247XG4gICAgaWYgKGlzUmVnaW9uU2F2ZU9uKSB7XG4gICAgICB0aGlzLnJlY29yZFVuZG9TbmFwc2hvdCgpO1xuICAgICAgaWYgKHRoaXMuc2hvd1NoYXBlTGFiZWwgIT09IHNob3dSZWdpb25MYWJlbCkge1xuICAgICAgICB0aGlzLnNob3dTaGFwZUxhYmVsID0gc2hvd1JlZ2lvbkxhYmVsO1xuICAgICAgICB0aGlzLnJlcHVibGlzaFZpZXcoKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuZmlsbENvbG9yID0gZmlsbENvbG9yO1xuICAgICAgaWYgKGFwcGVuZCkge1xuICAgICAgICAvLyBSZWplY3QgYnkgaWQgY29sbGlzaW9uIChhbHJlYWR5IHRyYWNrZWQpIG9yIGdlb21ldHJ5IGVxdWFsaXR5IChzYW1lXG4gICAgICAgIC8vIGNvb3JkaW5hdGVzKSDigJQgdGhlIGZpbmQgYnV0dG9uIGNhbiBwdXNoIHRoZSBzYW1lIHJlZ2lvbiByZXBlYXRlZGx5LlxuICAgICAgICBjb25zdCBhZGRlZCA9IHJlZ2lvbnMuZmlsdGVyKFxuICAgICAgICAgIChyKSA9PiAhdGhpcy5yZWdpb25zLnNvbWUoKGV4aXN0aW5nKSA9PiBleGlzdGluZy5pZCA9PT0gci5pZCB8fCByZWdpb25zRXF1YWwoZXhpc3RpbmcsIHIpKSxcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5yZWdpb25zID0gdGhpcy5yZWdpb25zLmNvbmNhdChhZGRlZCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnJlZ2lvbnMgPSByZWdpb25zLnNsaWNlKCk7XG4gICAgICB9XG4gICAgICB0aGlzLnN5bmNDYWNoZSgpO1xuICAgICAgdGhpcy5lbWl0U2VsZWN0aW9uKCk7XG4gICAgICB0aGlzLmVtaXQoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gVHJhbnNpZW50IGRpc3BsYXkgb25seSDigJQgZG9uJ3QgdG91Y2ggc3RvcmVkIHN0YXRlLlxuICAgICAgdGhpcy5yZWdpb25VcGRhdGUkLm5leHQocmVnaW9ucy5zbGljZSgpKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVGhlIGNhbm9uaWNhbCBhY2Nlc3NvcjogdGhlIGN1cnJlbnQgaW1hZ2UncyByZWdpb25zLiBBIGZyZXNoIGFycmF5LCBidXQgdGhlXG4gICAqIGluc3RhbmNlcyBhcmUgdGhlIHN0b3JlZCBvbmVzLCBzaGFyZWQgd2l0aCB0aGUgdW5kbyBoaXN0b3J5OiB0cmVhdCB0aGVtIGFzXG4gICAqIHJlYWQtb25seSBhbmQgY2hhbmdlIGEgcmVnaW9uIHRocm91Z2ggdGhlIHN0b3JlJ3Mgb3BlcmF0aW9ucyAob3IgYnlcbiAgICogY29tbWl0dGluZyBhIGNvcHkpLiBUeXBlZCBgUmVnaW9uW11gIHJhdGhlciB0aGFuXG4gICAqIGBSZWFkb25seUFycmF5PFJlYWRvbmx5PFJlZ2lvbj4+YCBiZWNhdXNlIHRoZSBJUmVnaW9uU3RvcmUgY29udHJhY3QgYW5kIHRoZVxuICAgKiBiYWNrZW5kcyBzdGlsbCB0YWtlIGEgbXV0YWJsZSBhcnJheS5cbiAgICovXG4gIGdldFJlZ2lvbnMoKTogUmVnaW9uW10ge1xuICAgIHJldHVybiB0aGlzLnJlZ2lvbnMuc2xpY2UoKTtcbiAgfVxuXG4gIC8vIOKUgOKUgCBQZXItc2xpY2UgcmVnaW9ucyBmb3Igei1zdGFja3MgKGppdC11aSM5Mykg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgLyoqIFRydWUgd2hpbGUgYSB6LXN0YWNrIGlzIGxvYWRlZCBhbmQgdGhlIHN0b3JlIGhvbGRzIHJlZ2lvbnMgcGVyIHNsaWNlLiAqL1xuICBpc1N0YWNrTW9kZSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5zY29wZS5zdGFja01vZGU7XG4gIH1cblxuICAvKiogVGhlIGN1cnJlbnQgZGlzcGxheSBzbGljZSAoemVyby1iYXNlZCkuICovXG4gIGdldERpc3BsYXlTbGljZSgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLnNjb3BlLmRpc3BsYXlTbGljZTtcbiAgfVxuXG4gIC8qKiBIb3cgdGhlIGN1cnJlbnQgc3RhY2sgcGVyc2lzdHMgdG8gZGlzayAoaml0LXVpIzkzKTogYGNvbWJpbmVkYCA9IG9uZVxuICAgKiAgei1pbmRleGVkIGdlb2pzb24gKHNpbmdsZS1maWxlIHotc3RhY2spOyBgcGVyLXNsaWNlLWZpbGVgID0gb25lIGdlb2pzb24gcGVyXG4gICAqICBzbGljZS1maWxlIChmb2xkZXIgc3RhY2spLiBNZWFuaW5nbGVzcyBvdXRzaWRlIHN0YWNrIG1vZGUuICovXG4gIGdldFN0YWNrU2F2ZUxheW91dCgpOiBTdGFja1NhdmVMYXlvdXQge1xuICAgIHJldHVybiB0aGlzLnNjb3BlLnNhdmVMYXlvdXQ7XG4gIH1cblxuICAvKipcbiAgICogRW50ZXIgcGVyLXNsaWNlIHN0YWNrIG1vZGUuIGBzbGljZXNgIG1hcHMgZWFjaCB6ZXJvLWJhc2VkIHNsaWNlIGluZGV4IHRvXG4gICAqIHRoZSByZWdpb25zIGltcG9ydGVkIGZvciB0aGF0IHNsaWNlOyB0aGUgc3RvcmUgbWFrZXMgYGluaXRpYWxaYCdzIHNsaWNlIHRoZVxuICAgKiBsaXZlIHNldCwgc28gdGhlIG92ZXJsYXlzIC8gc2VsZWN0aW9uIC8gUmVnaW9ucyB0YWJsZSBhcmUgdW5jaGFuZ2VkICh0aGV5XG4gICAqIHN0aWxsIHJlYWQge0BsaW5rIGdldFJlZ2lvbnN9KS4gRnJlc2hseS1jcmVhdGVkIHJlZ2lvbnMgYXJlIHRhZ2dlZCB3aXRoIHRoZVxuICAgKiBjdXJyZW50IHNsaWNlIHNvIHRoZXkgcGVyc2lzdCBvbiBpdCwgYW5kIHtAbGluayBnZXRTbGljZVJlZ2lvbnN9IHJldHVybnNcbiAgICogZXZlcnkgc2xpY2UgZm9yIHNhdmUvZXhwb3J0LiBJZHMvbmFtZXMvY2xhc3NpZmljYXRpb24gY29sb3VycyBhcmUgbWludGVkXG4gICAqIGV4YWN0bHkgYXMge0BsaW5rIHNldFJlZ2lvbnN9IGRvZXMuXG4gICAqL1xuICBlbnRlclN0YWNrTW9kZShzbGljZXM6IE1hcDxudW1iZXIsIFJlZ2lvbltdPiwgaW5pdGlhbFogPSAwLCBzYXZlTGF5b3V0OiBTdGFja1NhdmVMYXlvdXQgPSAnY29tYmluZWQnKTogdm9pZCB7XG4gICAgY29uc3QgYWRtaXR0ZWQgPSBuZXcgTWFwPG51bWJlciwgUmVnaW9uW10+KCk7XG4gICAgZm9yIChjb25zdCBbeiwgcmVnc10gb2Ygc2xpY2VzKSBhZG1pdHRlZC5zZXQoeiwgdGhpcy5ub3JtYWxpemVTbGljZShyZWdzIHx8IFtdLCB6KSk7XG4gICAgdGhpcy5yZWdpb25zID0gdGhpcy5zY29wZS5lbnRlclN0YWNrKGFkbWl0dGVkLCBpbml0aWFsWiwgc2F2ZUxheW91dCk7XG4gICAgdGhpcy5zZWxlY3Rpb24ucmVwbGFjZShbXSk7XG4gICAgdGhpcy5zeW5jQ2FjaGUoKTtcbiAgICB0aGlzLnJlc2V0VW5kb0hpc3RvcnkoKTtcbiAgICB0aGlzLmVtaXRTZWxlY3Rpb24oKTtcbiAgICB0aGlzLmVtaXQoKTtcbiAgICB0aGlzLnJlZnJlc2hTb3VyY2VWaWV3KCk7XG4gIH1cblxuICAvKiogTGVhdmUgc3RhY2sgbW9kZSAoc2luZ2xlLXBsYW5lIGltYWdlLCBvciB0aGUgc3RhY2sgd2FzIGNsb3NlZCkuICovXG4gIGV4aXRTdGFja01vZGUoKTogdm9pZCB7XG4gICAgdGhpcy5zY29wZS5leGl0U3RhY2soKTtcbiAgICB0aGlzLnJlZnJlc2hTb3VyY2VWaWV3KCk7XG4gIH1cblxuICAvKiogVGhlIGxpdmUtc2V0IHN3YXAgb2Yge0BsaW5rIHNldERpc3BsYXlTbGljZX0uICovXG4gIHByaXZhdGUgc2hvd1NsaWNlKHo6IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnN0IG5leHQgPSB0aGlzLnNjb3BlLnNob3dTbGljZSh6LCB0aGlzLnJlZ2lvbnMpO1xuICAgIGlmICghbmV4dCkgcmV0dXJuO1xuICAgIHRoaXMucmVnaW9ucyA9IG5leHQ7XG4gICAgdGhpcy5zZWxlY3Rpb24ucmVwbGFjZShbXSk7XG4gICAgdGhpcy5zeW5jQ2FjaGUoKTtcbiAgICB0aGlzLnJlc2V0VW5kb0hpc3RvcnkoKTtcbiAgICB0aGlzLmVtaXRTZWxlY3Rpb24oKTtcbiAgICB0aGlzLmVtaXQoKTtcbiAgICB0aGlzLnJlZnJlc2hTb3VyY2VWaWV3KCk7XG4gIH1cblxuICAvKipcbiAgICogU2hvdyBhIGRpZmZlcmVudCBzbGljZTogY2FwdHVyZSB0aGUgY3VycmVudCBzbGljZSdzIChwb3NzaWJseSBlZGl0ZWQpXG4gICAqIHJlZ2lvbnMgYmFjayBpbnRvIHRoZSBwZXItc2xpY2Ugc3RvcmUsIHRoZW4gbG9hZCB0aGUgdGFyZ2V0IHNsaWNlJ3MgcmVnaW9uc1xuICAgKiBhcyB0aGUgbGl2ZSBzZXQgYW5kIGVtaXQuIFVuZG8gbmV2ZXIgY3Jvc3NlcyBhIHNsaWNlLiBPdXRzaWRlIHN0YWNrIG1vZGVcbiAgICogdGhpcyBvbmx5IHJlY29yZHMgdGhlIHJlcXVlc3RlZCBzbGljZSBpbmRleCAoYSBuby1vcCBvdGhlcndpc2U6IHNpbmdsZS1wbGFuZVxuICAgKiByZWdpb25zIHN0YXkgb24gdGhlIGRlZmF1bHQgcGxhbmUg4oCUIGFkZFJlZ2lvbiB0YWdzIFJlZ2lvbi56IG9ubHkgaW4gc3RhY2tcbiAgICogbW9kZSwgc28gdGhlIHJlY29yZGVkIGluZGV4IGlzIHVudXNlZCB1bnRpbCBhIHN0YWNrIGlzIGVudGVyZWQpLiAoaml0LXVpIzkzKVxuICAgKiBFaXRoZXIgd2F5IHtAbGluayBnZXRSZWdpb25TZXRSZXBsYWNlZCR9IGVtaXRzOiB0aGUgc2xpY2Ugb24gc2NyZWVuIGNoYW5nZWRcbiAgICogdW5kZXIgYW55IGluLXByb2dyZXNzIHRvb2wgd29yay5cbiAgICovXG4gIHNldERpc3BsYXlTbGljZSh6OiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLnNob3dTbGljZSh6KTtcbiAgICB0aGlzLnJlZ2lvblNldFJlcGxhY2VkJC5uZXh0KCk7XG4gIH1cblxuICAvKipcbiAgICogRXZlcnkgc2xpY2UncyByZWdpb25zIGZvciBzYXZlL2V4cG9ydCwgZWFjaCB0YWdnZWQgd2l0aCBpdHMgemVyby1iYXNlZFxuICAgKiBzbGljZSBpbmRleCBpbiB7QGxpbmsgUmVnaW9uLnp9LiBDYXB0dXJlcyB0aGUgY3VycmVudCBzbGljZSdzIGxpdmUgZWRpdHNcbiAgICogZmlyc3QuIFJldHVybnMgdGhlIGZsYXQgc2luZ2xlLXBsYW5lIHNldCB3aGVuIG5vdCBpbiBzdGFjayBtb2RlLiAoaml0LXVpIzkzKVxuICAgKi9cbiAgZ2V0U2xpY2VSZWdpb25zKCk6IFJlZ2lvbltdIHtcbiAgICByZXR1cm4gdGhpcy5zY29wZS5zbGljZVJlZ2lvbnModGhpcy5yZWdpb25zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTbGljZXMgdG8gd3JpdGUgb24gYSBwZXItc2xpY2UtZmlsZSBzYXZlIChmb2xkZXIgc3RhY2ssIGppdC11aSM5Myk6IGV2ZXJ5XG4gICAqIHNsaWNlIHRoYXQgY3VycmVudGx5IGhhcyByZWdpb25zLCBQTFVTIHNsaWNlcyB0aGF0IHdlcmUgbG9hZGVkIG5vbi1lbXB0eSBidXRcbiAgICogYXJlIG5vdyBlbXB0eSAoc28gdGhlaXIgZmlsZSBpcyByZS13cml0dGVuIGVtcHR5LCBjbGVhcmluZyBhIHNsaWNlIHdob3NlXG4gICAqIHJlZ2lvbnMgdGhlIHVzZXIgZGVsZXRlZCkuIEVhY2ggcmV0dXJuZWQgcmVnaW9uIGlzIHRhZ2dlZCB3aXRoIGl0cyB6LCBhbmRcbiAgICogdGhlIGN1cnJlbnQgbGl2ZSBzbGljZSBpcyBjYXB0dXJlZCBmaXJzdC4gRW1wdHkgb3V0c2lkZSBzdGFjayBtb2RlLlxuICAgKi9cbiAgZ2V0U3RhY2tTYXZlU2xpY2VzKCk6IE1hcDxudW1iZXIsIFJlZ2lvbltdPiB7XG4gICAgY29uc3Qgc2xpY2VzID0gdGhpcy5zY29wZS5zdGFja1NhdmVTbGljZXModGhpcy5yZWdpb25zKTtcbiAgICAvLyBBIHNsaWNlIHdob3NlIHJlZ2lvbiBzb3VyY2UgbG9zdCBmZWF0dXJlcyAodGFrZW4sIGRlbGV0ZWQpIGlzIHJlLXdyaXR0ZW4gdG9vLlxuICAgIGNvbnN0IGNoYW5nZWQgPSB0aGlzLnNvdXJjZXMuc2xpY2VzV2l0aFRha2VuKHRoaXMuc2NvcGUuYWN0aXZlSW1hZ2UpLmZpbHRlcigoeikgPT4gIXNsaWNlcy5oYXMoeikpO1xuICAgIGlmICghY2hhbmdlZC5sZW5ndGgpIHJldHVybiBzbGljZXM7XG4gICAgZm9yIChjb25zdCB6IG9mIGNoYW5nZWQpIHNsaWNlcy5zZXQoeiwgW10pO1xuICAgIHJldHVybiBuZXcgTWFwKEFycmF5LmZyb20oc2xpY2VzKS5zb3J0KChhLCBiKSA9PiBhWzBdIC0gYlswXSkpO1xuICB9XG5cbiAgLyoqIE1pbnQgaWRzL25hbWVzICsgYXBwbHkgY2xhc3NpZmljYXRpb24gY29sb3VycyArIHRhZyB0aGUgc2xpY2UgaW5kZXgsIGFzXG4gICAqICB7QGxpbmsgc2V0UmVnaW9uc30gZG9lcywgZm9yIHJlZ2lvbnMgZW50ZXJpbmcgdGhlIHBlci1zbGljZSBzdG9yZS4gKi9cbiAgcHJpdmF0ZSBub3JtYWxpemVTbGljZShyZWdpb25zOiBSZWdpb25bXSwgejogbnVtYmVyKTogUmVnaW9uW10ge1xuICAgIC8vIEEgZnJlc2ggKGltcG9ydGVkKSByZWdpb24gaXMgdGFnZ2VkIGluIHBsYWNlOyBhIHN0b3JlZCBvbmUgaXMgY29waWVkLlxuICAgIHJldHVybiB0aGlzLmFkbWl0KHJlZ2lvbnMubWFwKChyKSA9PiAoci5pZCA9PSBudWxsID8gT2JqZWN0LmFzc2lnbihyLCB7IHogfSkgOiB3aXRoUmVnaW9uWihyLCB6KSkpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpb25zIGVudGVyaW5nIHRoZSBzdG9yZTogbWludCBpZHMgYW5kIGRlZmF1bHQgbmFtZXMsIGh5ZHJhdGUgSlNPTiBib3VuZHNcbiAgICogaW50byBjbGFzcyBpbnN0YW5jZXMg4oCUIGV2ZXJ5dGhpbmcgZG93bnN0cmVhbSAocmVuZGVyaW5nLCBnZW9tZXRyeSBkZS1kdXAsXG4gICAqIG1vdmVSZWdpb24sIEdlb0pTT04gZXhwb3J0KSBkaXNjcmltaW5hdGVzIHRoZW0gd2l0aCBgaW5zdGFuY2VvZmBcbiAgICogKGppdC11aSMxMjQpIOKAlCBhbmQgYXBwbHkgY2xhc3NpZmljYXRpb24gY29sb3Vycy4gQSByZWdpb24gdGhhdCBpcyBuZXcgdG9cbiAgICogdGhlIHN0b3JlIChubyBpZCB5ZXQpIGlzIGNvbXBsZXRlZCBpbiBwbGFjZTsgb25lIHRoYXQgYWxyZWFkeSBoYXMgYW4gaWQgbWF5XG4gICAqIGJlIGEgc3RvcmVkIGluc3RhbmNlIHNoYXJlZCB3aXRoIHRoZSB1bmRvIGhpc3RvcnksIHNvIGl0IGlzIGNvcGllZCBpZiBpdFxuICAgKiBjaGFuZ2VzLlxuICAgKi9cbiAgcHJpdmF0ZSBhZG1pdChyZWdpb25zOiBSZWdpb25bXSk6IFJlZ2lvbltdIHtcbiAgICBjb25zdCBmcmVzaCA9IG5ldyBTZXQ8UmVnaW9uPigpO1xuICAgIGNvbnN0IGFkbWl0dGVkID0gcmVnaW9ucy5tYXAoKHJlZ2lvbikgPT4ge1xuICAgICAgaWYgKHJlZ2lvbi5pZCA9PSBudWxsKSB7XG4gICAgICAgIHJlZ2lvbi5pZCA9IHRoaXMubmV4dElkKys7XG4gICAgICAgIGlmIChyZWdpb24ubmFtZSA9PSBudWxsKSByZWdpb24ubmFtZSA9IGBzaGFwZSR7cmVnaW9uLmlkfWA7XG4gICAgICAgIHJlZ2lvbi5ib3VuZHMgPSBoeWRyYXRlQm91bmRzKHJlZ2lvbi5ib3VuZHMpO1xuICAgICAgICBmcmVzaC5hZGQocmVnaW9uKTtcbiAgICAgICAgcmV0dXJuIHJlZ2lvbjtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGJvdW5kcyA9IGh5ZHJhdGVCb3VuZHMocmVnaW9uLmJvdW5kcyk7XG4gICAgICByZXR1cm4gcmVnaW9uLm5hbWUgPT0gbnVsbCB8fCBib3VuZHMgIT09IHJlZ2lvbi5ib3VuZHNcbiAgICAgICAgPyB3aXRoUmVnaW9uUGF0Y2gocmVnaW9uLCB7IG5hbWU6IHJlZ2lvbi5uYW1lID8/IGBzaGFwZSR7cmVnaW9uLmlkfWAsIGJvdW5kcyB9KVxuICAgICAgICA6IHJlZ2lvbjtcbiAgICB9KTtcbiAgICByZXR1cm4gdGhpcy53aXRoQ2xhc3NpZmljYXRpb25Db2xvcnMoYWRtaXR0ZWQsIChyKSA9PiBmcmVzaC5oYXMocikpO1xuICB9XG5cbiAgLyoqXG4gICAqIENsb3NlZCBwb2x5Z29ucyBwcm9qZWN0ZWQgZm9yIGltYWdlLXByb2Nlc3NpbmcgY29uc3VtZXJzIChzZWdtZW50YXRpb24sXG4gICAqIGNyb3AgcmVxdWVzdHMsIHRyYWNlIGJ1aWxkZXJzKSwgc3RyYWlnaHQgZnJvbSBlYWNoIHJlZ2lvbidzIGJvdW5kczogYVxuICAgKiByZWN0YW5nbGUncyBjb3JuZXJzLCBhIHBvbHlnb24gd2l0aCBpdHMgaG9sZXMgKGEgYsOpemllciBhcyBpdHMgY3VydmUpLCBvbmVcbiAgICogcG9seWdvbiBwZXIgcGFydCBvZiBhIG11bHRpLXBvbHlnb24uIE9wZW4gcG9seWxpbmVzIGFyZSBhbm5vdGF0aW9uLW9ubHkgYW5kXG4gICAqIGV4Y2x1ZGVkLiBDb29yZGluYXRlcyBhcmUgcm91bmRlZCB0byB3aG9sZSBwaXhlbHMuXG4gICAqL1xuICBnZXRSZWdpb25Qb2x5Z29ucygpOiBQb2x5Z29uW10ge1xuICAgIHJldHVybiB0aGlzLnJlZ2lvbnMuZmxhdE1hcCgocmVnaW9uKSA9PiByZWdpb25Qb2x5Z29ucyhyZWdpb24pKTtcbiAgfVxuXG4gIGdldFJlZ2lvblVwZGF0ZUV2ZW50KCk6IE9ic2VydmFibGU8YW55W10+IHtcbiAgICByZXR1cm4gdGhpcy5yZWdpb25VcGRhdGUkLmFzT2JzZXJ2YWJsZSgpO1xuICB9XG5cbiAgLyoqIExpdmUgKG5vbi1jb2FsZXNjZWQpIHJlZ2lvbi1jaGFuZ2Ugc3RyZWFtIOKAlCBmaXJlcyBwZXIgZnJhbWUgZHVyaW5nIGEgZHJhZy5cbiAgICogIFVzZWQgYnkgdGhlIGludGVuc2l0eS1wcm9maWxlIGluc2V0IHNvIGl0IHRyYWNrcyBsaW5lIFJPSXMgbGl2ZS4gKi9cbiAgZ2V0UmVnaW9uTGl2ZUVkaXQkKCk6IE9ic2VydmFibGU8UmVnaW9uW10+IHtcbiAgICByZXR1cm4gdGhpcy5yZWdpb25MaXZlRWRpdCQuYXNPYnNlcnZhYmxlKCk7XG4gIH1cblxuICAvKipcbiAgICogRW1pdHMgYWZ0ZXIgZXZlcnkge0BsaW5rIHVuZG99LCB7QGxpbmsgcmVkb30gYW5kIHtAbGluayBzZXREaXNwbGF5U2xpY2V9IGNhbGxcbiAgICogKGV2ZW4gb25lIHRoYXQgY2hhbmdlZCBub3RoaW5nKTogdGhlIHJlZ2lvbiBzZXQgd2FzIHJlcGxhY2VkIHVuZGVyIHdoYXRldmVyXG4gICAqIGEgY2FudmFzIHRvb2wgd2FzIGJ1aWxkaW5nIG9uIChhIGJydXNoIHN0cm9rZSwgYSBTQU0gcG9pbnQgcHJvbXB0KSwgc28gdGhlXG4gICAqIGJhY2tlbmRzIHJlc2V0IHRoZWlyIGNhbnZhcyB0b29scyBvbiBpdC4gTm90IGVtaXR0ZWQgZm9yIG9yZGluYXJ5IGVkaXRzIOKAlFxuICAgKiBhIHRvb2wncyBvd24gY29tbWl0IG11c3Qgbm90IHJlc2V0IGl0LlxuICAgKi9cbiAgZ2V0UmVnaW9uU2V0UmVwbGFjZWQkKCk6IE9ic2VydmFibGU8dm9pZD4ge1xuICAgIHJldHVybiB0aGlzLnJlZ2lvblNldFJlcGxhY2VkJC5hc09ic2VydmFibGUoKTtcbiAgfVxuXG4gIC8vIOKUgOKUgCBJUmVnaW9uU3RvcmU6IHNlbGVjdGlvbiDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICAvKiogU2VsZWN0IHJlZ2lvbnMgYnkgYXJyYXkgaW5kZXggKG9yIFtdIHRvIGNsZWFyKS4gU3RvcmVkIGludGVybmFsbHkgYnkgaWRcbiAgICogIHNvIHRoZSBzZWxlY3Rpb24gc3Vydml2ZXMgc3Vic2VxdWVudCBlZGl0cy9yZW9yZGVycy4gKi9cbiAgc2V0U2VsZWN0ZWRTaGFwZUluZGljZXMoaW5kaWNlczogbnVtYmVyW10pOiB2b2lkIHtcbiAgICB0aGlzLnNlbGVjdGlvbi5zZWxlY3RJbmRpY2VzKGluZGljZXMsIHRoaXMucmVnaW9ucyk7XG4gIH1cblxuICAvKiogU2VsZWN0IGEgc2luZ2xlIHJlZ2lvbiBieSBpZGVudGl0eSAoaWQpLiBCYWNrZW5kcyBjYWxsIHRoaXMgZnJvbSB0aGVpclxuICAgKiAgYHNlbGVjdFJlZ2lvbigpYDsgdGhlIE9TRCBvdmVybGF5ICsgcmVnaW9uIGVkaXRvciBoaWdobGlnaHQgb2ZmIHRoZVxuICAgKiAgcmVzdWx0aW5nIHNlbGVjdGlvbiBlbWl0LiBOby1vcCBpZiB0aGUgcmVnaW9uIGlzbid0IGluIHRoZSBzdG9yZS4gKi9cbiAgc2VsZWN0UmVnaW9uKHJlZ2lvbjogUmVnaW9uKTogdm9pZCB7XG4gICAgaWYgKHJlZ2lvbj8uaWQgPT0gbnVsbCB8fCB0aGlzLmluZGV4T2ZJZChyZWdpb24uaWQpIDwgMCkgcmV0dXJuO1xuICAgIHRoaXMuc2VsZWN0aW9uLnJlcGxhY2UoW3JlZ2lvbi5pZF0pO1xuICAgIHRoaXMuZW1pdFNlbGVjdGlvbigpO1xuICB9XG5cbiAgZ2V0U2VsZWN0ZWRTaGFwZUluZGljZXMkKCk6IE9ic2VydmFibGU8bnVtYmVyW10+IHtcbiAgICByZXR1cm4gdGhpcy5zZWxlY3Rpb24uaW5kaWNlcyQ7XG4gIH1cblxuICAvKiogU3luY2hyb25vdXMgY3VycmVudCBzZWxlY3Rpb24gKGFycmF5IGluZGljZXMpIOKAlCBmb3IgY2FsbGVycyB0aGF0IG5lZWQgdG9cbiAgICogIHJlYWQgdGhlIHNlbGVjdGlvbiB3aXRob3V0IHN1YnNjcmliaW5nLiAqL1xuICBnZXRTZWxlY3RlZFNoYXBlSW5kaWNlcygpOiBudW1iZXJbXSB7XG4gICAgcmV0dXJuIHRoaXMuc2VsZWN0aW9uLmluZGljZXM7XG4gIH1cblxuICAvKiogRGVsZXRlIHRoZSBjdXJyZW50bHkgc2VsZWN0ZWQgcmVnaW9ucyBhbmQgY2xlYXIgdGhlIHNlbGVjdGlvbi4gKi9cbiAgZGVsZXRlQWN0aXZlU2hhcGUoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuc2VsZWN0aW9uLmlkcy5sZW5ndGggPT09IDApIHJldHVybjtcbiAgICB0aGlzLnJlY29yZFVuZG9TbmFwc2hvdCgpO1xuICAgIGNvbnN0IGlkcyA9IG5ldyBTZXQodGhpcy5zZWxlY3Rpb24uaWRzKTtcbiAgICB0aGlzLnJlZ2lvbnMgPSB0aGlzLnJlZ2lvbnMuZmlsdGVyKChyKSA9PiAhaWRzLmhhcyhyLmlkKSk7XG4gICAgdGhpcy5zZWxlY3Rpb24ucmVwbGFjZShbXSk7XG4gICAgdGhpcy5zeW5jQ2FjaGUoKTtcbiAgICB0aGlzLmVtaXRTZWxlY3Rpb24oKTtcbiAgICB0aGlzLmVtaXQoKTtcbiAgfVxuXG4gIC8vIOKUgOKUgCBJUmVnaW9uU3RvcmU6IGNvbG91cnMgLyBsYWJlbHMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgZ2V0U2hvd1NoYXBlTGFiZWwoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuc2hvd1NoYXBlTGFiZWw7XG4gIH1cbiAgZ2V0U2hhcGVDb2xvcigpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLnNoYXBlQ29sb3I7XG4gIH1cbiAgZ2V0RmlsbENvbG9yKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuZmlsbENvbG9yO1xuICB9XG5cbiAgLyoqIFNob3cgb3IgaGlkZSByZWdpb24gbGFiZWxzIChub3Qgb24gdGhlIGNvbnRyYWN0OyBzcGVjcyBkcml2ZSBpdCBkaXJlY3RseSkuXG4gICAqICBAZGVwcmVjYXRlZCBOb3RoaW5nIGluIHRoZSBsaWJyYXJ5IGNhbGxzIGl0OyB3aWxsIGJlIHJlbW92ZWQgbmV4dCBtaW5vci4gKi9cbiAgc2V0U2hvd1NoYXBlTGFiZWwoc2hvdzogYm9vbGVhbik6IHZvaWQge1xuICAgIHRoaXMuc2hvd1NoYXBlTGFiZWwgPSBzaG93O1xuICAgIHRoaXMucmVwdWJsaXNoVmlldygpO1xuICB9XG5cbiAgZ2V0Q2xhc3NpZmljYXRpb25Db2xvcnMoKTogTWFwPHN0cmluZywgc3RyaW5nPiB7XG4gICAgcmV0dXJuIHRoaXMuc3RvcmUuZ2V0Q2xhc3NpZmljYXRpb25Db2xvcnMoKTtcbiAgfVxuICBzZXRDbGFzc2lmaWNhdGlvbkNvbG9yKGxhYmVsOiBzdHJpbmcsIGNvbG9yOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLnN0b3JlLnNldENsYXNzaWZpY2F0aW9uQ29sb3IobGFiZWwsIGNvbG9yKTtcbiAgfVxuXG4gIC8vIOKUgOKUgCBJUmVnaW9uU3RvcmU6IHVuZG8gLyByZWRvIChqaXQtdWkjODUpIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gIC8qKiBFbWl0cyB3aGV0aGVyIGFuIHVuZG8gc3RlcCBpcyBjdXJyZW50bHkgYXZhaWxhYmxlIOKAlCBkcml2ZXMgdGhlIHRvb2xiYXJcbiAgICogIFVuZG8gYnV0dG9uJ3MgZW5hYmxlZCBzdGF0ZSAoZ3JleWVkIG91dCB3aGVuIGZhbHNlKS4gKi9cbiAgZ2V0Q2FuVW5kbyQoKTogT2JzZXJ2YWJsZTxib29sZWFuPiB7XG4gICAgcmV0dXJuIHRoaXMuaGlzdG9yeS5jYW5VbmRvJDtcbiAgfVxuXG4gIC8qKiBFbWl0cyB3aGV0aGVyIGEgcmVkbyBzdGVwIGlzIGN1cnJlbnRseSBhdmFpbGFibGUg4oCUIGRyaXZlcyB0aGUgdG9vbGJhclxuICAgKiAgUmVkbyBidXR0b24ncyBlbmFibGVkIHN0YXRlLiAqL1xuICBnZXRDYW5SZWRvJCgpOiBPYnNlcnZhYmxlPGJvb2xlYW4+IHtcbiAgICByZXR1cm4gdGhpcy5oaXN0b3J5LmNhblJlZG8kO1xuICB9XG5cbiAgLyoqIFN5bmNocm9ub3VzIHJlYWQgb2Yge0BsaW5rIGdldENhblVuZG8kfSDigJQgdHJ1ZSB3aGVuIGF0IGxlYXN0IG9uZSByZWdpb25cbiAgICogIGFjdGlvbiBjYW4gYmUgdW5kb25lLiAqL1xuICBjYW5VbmRvKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmhpc3RvcnkuY2FuVW5kbygpO1xuICB9XG5cbiAgLyoqIFN5bmNocm9ub3VzIHJlYWQgb2Yge0BsaW5rIGdldENhblJlZG8kfSDigJQgdHJ1ZSB3aGVuIGFuIHVuZG9uZSBhY3Rpb24gY2FuXG4gICAqICBiZSByZS1hcHBsaWVkLiAqL1xuICBjYW5SZWRvKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmhpc3RvcnkuY2FuUmVkbygpO1xuICB9XG5cbiAgLyoqXG4gICAqIFVuZG8gdGhlIG1vc3QgcmVjZW50IHJlZ2lvbiBhY3Rpb24sIHJlc3RvcmluZyB0aGUgcmVnaW9uIHNldCB0byBpdHMgc3RhdGVcbiAgICoganVzdCBiZWZvcmUgdGhhdCBhY3Rpb24gYW5kIHB1c2hpbmcgdGhlIGN1cnJlbnQgc3RhdGUgb250byB0aGUgcmVkbyBzdGFjay5cbiAgICogVXAgdG8ge0BsaW5rIFVORE9fTElNSVR9IHN0ZXBzIGFyZSByZXRhaW5lZCwgc28gdGhpcyBjYW4gYmUgY2FsbGVkIHVwIHRvXG4gICAqIHtAbGluayBVTkRPX0xJTUlUfSB0aW1lcyBpbiBhIHJvdyBiZWZvcmUgdGhlIGhpc3RvcnkgZW1wdGllcy4gTm8tb3Agd2hlblxuICAgKiBub3RoaW5nIGlzIGxlZnQgdG8gdW5kby5cbiAgICovXG4gIHVuZG8oKTogdm9pZCB7XG4gICAgY29uc3Qgc25hcHNob3QgPSB0aGlzLmhpc3RvcnkudW5kbyh0aGlzLnNuYXBzaG90KCkpO1xuICAgIGlmIChzbmFwc2hvdCkgdGhpcy5yZXN0b3JlU25hcHNob3Qoc25hcHNob3QpO1xuICAgIHRoaXMucmVnaW9uU2V0UmVwbGFjZWQkLm5leHQoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWRvIHRoZSBhY3Rpb24gbW9zdCByZWNlbnRseSB1bmRvbmUsIHJlc3RvcmluZyB0aGUgcmVnaW9uIHNldCB0byB0aGUgc3RhdGVcbiAgICogaXQgaGFkIGJlZm9yZSB0aGF0IHVuZG8gYW5kIHB1c2hpbmcgdGhlIGN1cnJlbnQgc3RhdGUgYmFjayBvbnRvIHRoZSB1bmRvXG4gICAqIHN0YWNrLiBOby1vcCB3aGVuIHRoZXJlJ3Mgbm90aGluZyB0byByZWRvICh0aGUgcmVkbyBzdGFjayBpcyBjbGVhcmVkIGJ5IGFueVxuICAgKiBmcmVzaCByZWdpb24gYWN0aW9uKS5cbiAgICovXG4gIHJlZG8oKTogdm9pZCB7XG4gICAgY29uc3Qgc25hcHNob3QgPSB0aGlzLmhpc3RvcnkucmVkbyh0aGlzLnNuYXBzaG90KCkpO1xuICAgIGlmIChzbmFwc2hvdCkgdGhpcy5yZXN0b3JlU25hcHNob3Qoc25hcHNob3QpO1xuICAgIHRoaXMucmVnaW9uU2V0UmVwbGFjZWQkLm5leHQoKTtcbiAgfVxuXG4gIC8qKiBEaXNjYXJkIHRoZSB1bmRvL3JlZG8gaGlzdG9yeSAoZS5nLiBvbiBpbWFnZSBsb2FkL3N3aXRjaCDigJQgaGlzdG9yeSBuZXZlclxuICAgKiAgY3Jvc3NlcyBpbWFnZXMpLiAqL1xuICByZXNldFVuZG9IaXN0b3J5KCk6IHZvaWQge1xuICAgIHRoaXMuaGlzdG9yeS5yZXNldCgpO1xuICB9XG5cbiAgLyoqIE1ha2UgYHNuYXBzaG90YCB0aGUgbGl2ZSByZWdpb24gc2V0IGFuZCBub3RpZnkgYm90aCBiYWNrZW5kcy4gU2hhcmVkIGJ5XG4gICAqICB7QGxpbmsgdW5kb30gYW5kIHtAbGluayByZWRvfTsgbm90aGluZyByZWNvcmRzIGhpc3Rvcnkgd2hpbGUgaXQgcnVucy4gKi9cbiAgcHJpdmF0ZSByZXN0b3JlU25hcHNob3Qoc25hcHNob3Q6IFJlZ2lvblNuYXBzaG90KTogdm9pZCB7XG4gICAgdGhpcy5oaXN0b3J5LnJlc3RvcmUoKCkgPT4ge1xuICAgICAgdGhpcy5yZWdpb25zID0gc25hcHNob3QucmVnaW9ucy5zbGljZSgpO1xuICAgICAgdGhpcy5zZXRUYWtlbihzbmFwc2hvdC50YWtlbik7XG4gICAgICB0aGlzLnN5bmNDYWNoZSgpO1xuICAgICAgLy8gRHJvcHMgYW55IHNlbGVjdGVkIGlkcyB0aGUgcmVzdG9yZWQgc2V0IG5vIGxvbmdlciBjb250YWlucy5cbiAgICAgIHRoaXMuZW1pdFNlbGVjdGlvbigpO1xuICAgIH0pO1xuICAgIC8vIE5vdGlmeSB0aGUgbGl2ZSArIGNvYWxlc2NlZCBzdHJlYW1zIHNvIHdoaWNoZXZlciBiYWNrZW5kIGlzIG9uIHNjcmVlblxuICAgIC8vIHJlLXJlbmRlcnMgZnJvbSB0aGUgcmVzdG9yZWQgc3RvcmUgc3RhdGUuXG4gICAgdGhpcy5yZWdpb25MaXZlRWRpdCQubmV4dCh0aGlzLnJlZ2lvbnMuc2xpY2UoKSk7XG4gICAgdGhpcy5yZWdpb25VcGRhdGUkLm5leHQodGhpcy5nZXRSZWdpb25zKCkpO1xuICB9XG5cbiAgLyoqXG4gICAqIENhcHR1cmUgdGhlIHByZS1hY3Rpb24gcmVnaW9uIHNldCBpbnRvIHRoZSBib3VuZGVkIHVuZG8gaGlzdG9yeS4gQ2FsbGVkIGF0XG4gICAqIHRoZSB0b3Agb2YgZXZlcnkgbXV0YXRpbmcgb3BlcmF0aW9uLCAqYmVmb3JlKiBpdCBjaGFuZ2VzIGByZWdpb25zYC4gVGhlXG4gICAqIHNuYXBzaG90IGlzIHRoZSBhcnJheSBpdHNlbGY6IGV2ZXJ5IG9wZXJhdGlvbiByZXBsYWNlcyBgcmVnaW9uc2AgKGFuZCBhbnlcbiAgICogcmVnaW9uIGl0IGVkaXRzKSByYXRoZXIgdGhhbiBjaGFuZ2luZyB0aGVtLCBzbyBpdCBuZXZlciBjaGFuZ2VzIGFmdGVyIHRoaXMuXG4gICAqL1xuICBwcml2YXRlIHJlY29yZFVuZG9TbmFwc2hvdCgpOiB2b2lkIHtcbiAgICB0aGlzLmhpc3RvcnkucmVjb3JkKHRoaXMuc25hcHNob3QoKSk7XG4gIH1cblxuICAvKiogVGhlIHN0YXRlIGFuIHVuZG8gc3RlcCByZXN0b3Jlcy4gKi9cbiAgcHJpdmF0ZSBzbmFwc2hvdCgpOiBSZWdpb25TbmFwc2hvdCB7XG4gICAgcmV0dXJuIHsgcmVnaW9uczogdGhpcy5yZWdpb25zLCB0YWtlbjogdGhpcy5jdXJyZW50VGFrZW4oKSB9O1xuICB9XG5cbiAgLy8g4pSA4pSAIElSZWdpb25TdG9yZTogR2VvSlNPTiBJL08gKG1vZGVscy9yZWdpb24tZ2VvanNvbikg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgLyoqIFBhcnNlIEdlb0pTT04gaW50byByZWdpb25zLCByZW1lbWJlcmluZyB0aGUgY2xhc3MgY29sb3VycyB0aGUgZmlsZSBjYXJyaWVzIHNvIHRoZXkgYXJlXG4gICAqICBrZXB0IGZvciBjbGFzc2VzIHdpdGggbm8gcHJlc2V0IChzZWUgVmlzdWFsaXplclN0b3JlLnJlbWVtYmVySW1wb3J0ZWRDbGFzc0NvbG9ycykuICovXG4gIGltcG9ydFJlZ2lvbnMoZ2VvSnNvblN0cjogc3RyaW5nKTogUmVnaW9uW10ge1xuICAgIGNvbnN0IHJlZ2lvbnMgPSByZWdpb25zRnJvbUdlb0pzb24oZ2VvSnNvblN0cik7XG4gICAgY29uc3QgY29sb3JzID0gbmV3IE1hcDxzdHJpbmcsIHN0cmluZz4oKTtcbiAgICBmb3IgKGNvbnN0IHIgb2YgcmVnaW9ucykge1xuICAgICAgaWYgKHIubGFiZWwgJiYgci5jb2xvciAmJiAhY29sb3JzLmhhcyhyLmxhYmVsKSkgY29sb3JzLnNldChyLmxhYmVsLCByLmNvbG9yKTtcbiAgICB9XG4gICAgaWYgKGNvbG9ycy5zaXplKSB0aGlzLnN0b3JlLnJlbWVtYmVySW1wb3J0ZWRDbGFzc0NvbG9ycyhjb2xvcnMpO1xuICAgIHJldHVybiByZWdpb25zO1xuICB9XG4gIC8qKiBEb3dubG9hZCBgcmVnaW9uc2AgYXMgR2VvSlNPTiwgbmFtZWQgYWZ0ZXIgYGZpbGVOYW1lYCAoZXh0ZW5zaW9uXG4gICAqICByZXBsYWNlZCBieSBgLmdlb2pzb25gKSBvciBgcm9pcy5nZW9qc29uYCB3aXRob3V0IG9uZS4gKi9cbiAgZXhwb3J0UmVnaW9ucyhyZWdpb25zOiBSZWdpb25bXSwgZmlsZU5hbWU/OiBzdHJpbmcpOiB2b2lkIHtcbiAgICBkb3dubG9hZEdlb0pzb24ocmVnaW9uc1RvR2VvSnNvbihyZWdpb25zKSwgZmlsZU5hbWUpO1xuICB9XG4gIGdldEdlb0pzb25TdHJpbmcocmVnaW9uczogUmVnaW9uW10pOiBzdHJpbmcge1xuICAgIHJldHVybiByZWdpb25zVG9HZW9Kc29uKHJlZ2lvbnMpO1xuICB9XG5cbiAgLy8g4pSA4pSAIElSZWdpb25FZGl0QXBpOiBzdHJ1Y3R1cmFsIGVkaXRzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gIGFkZFJlZ2lvbihyZWdpb246IFJlZ2lvbik6IG51bWJlciB7XG4gICAgdGhpcy5yZWNvcmRVbmRvU25hcHNob3QoKTtcbiAgICBpZiAocmVnaW9uLmlkID09IG51bGwpIHJlZ2lvbi5pZCA9IHRoaXMubmV4dElkKys7XG4gICAgaWYgKHJlZ2lvbi5uYW1lID09IG51bGwpIHJlZ2lvbi5uYW1lID0gYHNoYXBlJHtyZWdpb24uaWR9YDtcbiAgICByZWdpb24uYm91bmRzID0gaHlkcmF0ZUJvdW5kcyhyZWdpb24uYm91bmRzKTsgLy8gaml0LXVpIzEyNFxuICAgIC8vIEEgcmVnaW9uIGRyYXduIG9uIGEgc3RhY2sgYmVsb25ncyB0byB0aGUgc2xpY2UgY3VycmVudGx5IGRpc3BsYXllZCwgc29cbiAgICAvLyBpdCBzYXZlcy9yZWxvYWRzIG9uIHRoYXQgc2xpY2UgKGppdC11aSM5MykuIE5vLW9wIGZvciBzaW5nbGUtcGxhbmUgaW1hZ2VzXG4gICAgLy8gKHRoZSBkaXNwbGF5IHNsaWNlIHN0YXlzIDApLlxuICAgIGlmICh0aGlzLnNjb3BlLnN0YWNrTW9kZSkgcmVnaW9uLnogPSB0aGlzLnNjb3BlLmRpc3BsYXlTbGljZTtcbiAgICAvLyBUaGUgY2FsbGVyJ3MgaW5zdGFuY2UgYmVjb21lcyB0aGUgc3RvcmVkIG9uZSAoY29tcGxldGVkIGluIHBsYWNlKS5cbiAgICBjb25zdCBbc3RvcmVkXSA9IHRoaXMud2l0aENsYXNzaWZpY2F0aW9uQ29sb3JzKFtyZWdpb25dLCAoKSA9PiB0cnVlKTtcbiAgICB0aGlzLnJlZ2lvbnMgPSBbLi4udGhpcy5yZWdpb25zLCBzdG9yZWRdO1xuICAgIHRoaXMuc2VsZWN0aW9uLnJlcGxhY2UoW3N0b3JlZC5pZF0pO1xuICAgIHRoaXMuc3luY0NhY2hlKCk7XG4gICAgdGhpcy5lbWl0U2VsZWN0aW9uKCk7XG4gICAgdGhpcy5lbWl0KCk7XG4gICAgcmV0dXJuIHN0b3JlZC5pZDtcbiAgfVxuXG4gIHJlbW92ZVJlZ2lvbihpZDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5yZW1vdmVSZWdpb25zKFtpZF0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZSB0aGUgcmVnaW9ucyB3aXRoIHRoZXNlIGlkcywgaWYgcHJlc2VudC4gV2l0aCBgeyByZWNvcmRVbmRvOiBmYWxzZSB9YFxuICAgKiBubyB1bmRvIHN0ZXAgaXMgdGFrZW4g4oCUIGZvciBjbGVhcmluZyB0cmFuc2llbnQgc2hhcGVzIHRoYXQgd2VyZSBuZXZlciB0aGVcbiAgICogdXNlcidzIHdvcmsgKHRoZSAzRCB2aWV3J3Mgc2NyZWVuLXNwYWNlIGxhc3NvcyBvbiBhbiBvcmJpdCwgTkFQQVJJLVNWQy0xMSkuXG4gICAqL1xuICByZW1vdmVSZWdpb25zKGlkczogSXRlcmFibGU8bnVtYmVyPiwgb3B0czogeyByZWNvcmRVbmRvPzogYm9vbGVhbiB9ID0ge30pOiB2b2lkIHtcbiAgICBjb25zdCBkcm9wID0gbmV3IFNldChpZHMpO1xuICAgIGlmICghdGhpcy5yZWdpb25zLnNvbWUoKHIpID0+IGRyb3AuaGFzKHIuaWQpKSkgcmV0dXJuO1xuICAgIGlmIChvcHRzLnJlY29yZFVuZG8gIT09IGZhbHNlKSB0aGlzLnJlY29yZFVuZG9TbmFwc2hvdCgpO1xuICAgIHRoaXMucmVnaW9ucyA9IHRoaXMucmVnaW9ucy5maWx0ZXIoKHIpID0+ICFkcm9wLmhhcyhyLmlkKSk7XG4gICAgdGhpcy5zZWxlY3Rpb24ucmV0YWluKChzKSA9PiAhZHJvcC5oYXMocykpO1xuICAgIHRoaXMuc3luY0NhY2hlKCk7XG4gICAgdGhpcy5lbWl0U2VsZWN0aW9uKCk7XG4gICAgdGhpcy5lbWl0KCk7XG4gIH1cblxuICB1cGRhdGVCb3VuZHMoaWQ6IG51bWJlciwgYm91bmRzOiBSZWN0YW5nbGUgfCBQb2x5Z29uIHwgTXVsdGlQb2x5Z29uKTogdm9pZCB7XG4gICAgY29uc3QgciA9IHRoaXMuZmluZEJ5SWQoaWQpO1xuICAgIGlmICghcikgcmV0dXJuO1xuICAgIHRoaXMucmVjb3JkVW5kb1NuYXBzaG90KCk7XG4gICAgLy8gQSBjb3B5LCBzbyB0aGUgY2FsbGVyIGNhbiBrZWVwIHVzaW5nIChhbmQgY2hhbmdpbmcpIHRoZSBib3VuZHMgaXQgcGFzc2VkLlxuICAgIHRoaXMucmVwbGFjZVJlZ2lvbihyZXBsYWNlQm91bmRzKHIsIGNsb25lQm91bmRzKGJvdW5kcykpKTtcbiAgfVxuXG4gIG1vdmVSZWdpb24oaWQ6IG51bWJlciwgZHg6IG51bWJlciwgZHk6IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnN0IHIgPSB0aGlzLmZpbmRCeUlkKGlkKTtcbiAgICBpZiAoIXIgfHwgIXIuYm91bmRzKSByZXR1cm47XG4gICAgdGhpcy5yZWNvcmRVbmRvU25hcHNob3QoKTtcbiAgICAvLyBFdmVyeSBwYXJ0IChhbmQgaXRzIGhvbGVzKSBtb3ZlcyB0b2dldGhlciAoaml0LXVpIzg1KS5cbiAgICB0aGlzLnJlcGxhY2VSZWdpb24ocmVwbGFjZUJvdW5kcyhyLCBlZGl0LnRyYW5zbGF0ZUJvdW5kcyhyLmJvdW5kcywgZHgsIGR5KSkpO1xuICB9XG5cbiAgLy8g4pSA4pSAIElSZWdpb25FZGl0QXBpOiB2ZXJ0ZXggZWRpdHMgKHBvbHlnb25zIG9ubHkpIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuICAvLyBFYWNoIG9uZSBpcyBhIHB1cmUgY29weS1vbi13cml0ZSBlZGl0IGZyb20gbW9kZWxzL3BvbHlnb24tZWRpdDsgYSBudWxsXG4gIC8vIHJlc3VsdCAob3V0IG9mIHJhbmdlLCB3b3VsZCBkZWdlbmVyYXRlKSByZWNvcmRzIG5vdGhpbmcgYW5kIGVtaXRzIG5vdGhpbmcuXG5cbiAgbW92ZVZlcnRleChpZDogbnVtYmVyLCBpbmRleDogbnVtYmVyLCB4OiBudW1iZXIsIHk6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMuZWRpdFBvbHlnb24oaWQsIChwKSA9PiBlZGl0Lm1vdmVWZXJ0ZXgocCwgaW5kZXgsIHgsIHkpKTtcbiAgfVxuXG4gIC8qKiBNb3ZlIGEgdmVydGV4IG9uIGEgcG9seWdvbidzIGludGVyaW9yIHJpbmcgKGhvbGUpIOKAlCBqaXQtdWkjODUuICovXG4gIG1vdmVIb2xlVmVydGV4KGlkOiBudW1iZXIsIGhvbGVJbmRleDogbnVtYmVyLCBpbmRleDogbnVtYmVyLCB4OiBudW1iZXIsIHk6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMuZWRpdFBvbHlnb24oaWQsIChwKSA9PiBlZGl0Lm1vdmVIb2xlVmVydGV4KHAsIGhvbGVJbmRleCwgaW5kZXgsIHgsIHkpKTtcbiAgfVxuXG4gIC8qKiBJbnNlcnQgYSB2ZXJ0ZXggb24gYSBwb2x5Z29uJ3MgaW50ZXJpb3IgcmluZyAoaG9sZSksIGFmdGVyIGBzZWdJbmRleGBcbiAgICogICh0aGUgZWRnZSdzIHN0YXJ0IHZlcnRleCkuIE5vLW9wIGZvciBhbiBvdXQtb2YtcmFuZ2UgaG9sZSDigJQgaml0LXVpIzg1LiAqL1xuICBhZGRIb2xlVmVydGV4KGlkOiBudW1iZXIsIGhvbGVJbmRleDogbnVtYmVyLCBzZWdJbmRleDogbnVtYmVyLCB4OiBudW1iZXIsIHk6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMuZWRpdFBvbHlnb24oaWQsIChwKSA9PiBlZGl0LmFkZEhvbGVWZXJ0ZXgocCwgaG9sZUluZGV4LCBzZWdJbmRleCwgeCwgeSkpO1xuICB9XG5cbiAgLyoqIERlbGV0ZSB0aGUgdmVydGV4IGF0IGBpbmRleGAgb24gYSBwb2x5Z29uJ3MgaW50ZXJpb3IgcmluZyAoaG9sZSkuIFJlbW92aW5nXG4gICAqICBpdCBiZWxvdyAzIHZlcnRpY2VzIGRyb3BzIHRoZSB3aG9sZSBob2xlIChhIHJpbmcgd2l0aCA8IDMgcG9pbnRzIGJvdW5kcyBub1xuICAgKiAgYXJlYSkg4oCUIGppdC11aSM4NS4gKi9cbiAgZGVsZXRlSG9sZVZlcnRleChpZDogbnVtYmVyLCBob2xlSW5kZXg6IG51bWJlciwgaW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMuZWRpdFBvbHlnb24oaWQsIChwKSA9PiBlZGl0LmRlbGV0ZUhvbGVWZXJ0ZXgocCwgaG9sZUluZGV4LCBpbmRleCkpO1xuICB9XG5cbiAgYWRkVmVydGV4KGlkOiBudW1iZXIsIHNlZ0luZGV4OiBudW1iZXIsIHg6IG51bWJlciwgeTogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5lZGl0UG9seWdvbihpZCwgKHApID0+IGVkaXQuYWRkVmVydGV4KHAsIHNlZ0luZGV4LCB4LCB5KSk7XG4gIH1cblxuICBkZWxldGVWZXJ0ZXgoaWQ6IG51bWJlciwgaW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMuZWRpdFBvbHlnb24oaWQsIChwKSA9PiBlZGl0LmRlbGV0ZVZlcnRleChwLCBpbmRleCkpO1xuICB9XG5cbiAgc2V0QmV6aWVyKGlkOiBudW1iZXIsIGJlemllcjogYm9vbGVhbik6IHZvaWQge1xuICAgIGNvbnN0IHIgPSB0aGlzLmZpbmRCeUlkKGlkKTtcbiAgICBpZiAoIXIgfHwgIXIuYm91bmRzKSByZXR1cm47XG4gICAgbGV0IG5leHQ6IFBvbHlnb24gfCBudWxsID0gbnVsbDtcbiAgICBpZiAoci5ib3VuZHMgaW5zdGFuY2VvZiBQb2x5Z29uKSB7XG4gICAgICBuZXh0ID0gZWRpdC5zZXRCZXppZXIoci5ib3VuZHMsIGJlemllcik7XG4gICAgfSBlbHNlIGlmIChyLmJvdW5kcyBpbnN0YW5jZW9mIFJlY3RhbmdsZSAmJiBiZXppZXIpIHtcbiAgICAgIC8vIFNtb290aGluZyBhIHJlY3RhbmdsZTogY29udmVydCBpdCB0byBhIDQtYW5jaG9yIGNsb3NlZCBwb2x5Z29uIGZpcnN0LlxuICAgICAgY29uc3QgcmluZyA9IHJlY3RUb1Jpbmcoci5ib3VuZHMpO1xuICAgICAgbmV4dCA9IGVkaXQuc2V0QmV6aWVyKG1ha2VQb2x5Z29uKHJpbmcueHMsIHJpbmcueXMpLCB0cnVlKTtcbiAgICB9XG4gICAgaWYgKCFuZXh0KSByZXR1cm47IC8vIGFscmVhZHkgaW4gdGhhdCBzdGF0ZSwgb3IgYmV6aWVyPWZhbHNlIG9uIGEgcmVjdGFuZ2xlXG4gICAgdGhpcy5yZWNvcmRVbmRvU25hcHNob3QoKTtcbiAgICB0aGlzLnJlcGxhY2VSZWdpb24ocmVwbGFjZUJvdW5kcyhyLCBuZXh0KSk7XG4gIH1cblxuICAvKiogRHJhZyBhIGJlemllciBjb250cm9sIHBvaW50IG9uIGEgaG9sZSByaW5nIHZlcnRleCAoZG9udXQgYmV6aWVyIGVkaXRpbmcpLiAqL1xuICBtb3ZlSG9sZUJlemllckhhbmRsZShcbiAgICBpZDogbnVtYmVyLFxuICAgIGhvbGVJbmRleDogbnVtYmVyLFxuICAgIGluZGV4OiBudW1iZXIsXG4gICAgc2lkZTogJ2luJyB8ICdvdXQnLFxuICAgIHg6IG51bWJlcixcbiAgICB5OiBudW1iZXIsXG4gICk6IHZvaWQge1xuICAgIHRoaXMuZWRpdFBvbHlnb24oaWQsIChwKSA9PiBlZGl0Lm1vdmVIb2xlQmV6aWVySGFuZGxlKHAsIGhvbGVJbmRleCwgaW5kZXgsIHNpZGUsIHgsIHkpKTtcbiAgfVxuXG4gIG1vdmVCZXppZXJIYW5kbGUoaWQ6IG51bWJlciwgaW5kZXg6IG51bWJlciwgc2lkZTogJ2luJyB8ICdvdXQnLCB4OiBudW1iZXIsIHk6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMuZWRpdFBvbHlnb24oaWQsIChwKSA9PiBlZGl0Lm1vdmVCZXppZXJIYW5kbGUocCwgaW5kZXgsIHNpZGUsIHgsIHkpKTtcbiAgfVxuXG4gIC8qKiBBcHBseSBhIGNvcHktb24td3JpdGUgcG9seWdvbiBlZGl0IHRvIHJlZ2lvbiBgaWRgOiByZWNvcmQsIHN3YXAgaW4sIGVtaXQuICovXG4gIHByaXZhdGUgZWRpdFBvbHlnb24oaWQ6IG51bWJlciwgYXBwbHk6IChwOiBQb2x5Z29uKSA9PiBQb2x5Z29uIHwgbnVsbCk6IHZvaWQge1xuICAgIGNvbnN0IHIgPSB0aGlzLmZpbmRCeUlkKGlkKTtcbiAgICBpZiAoIXIgfHwgIShyLmJvdW5kcyBpbnN0YW5jZW9mIFBvbHlnb24pKSByZXR1cm47XG4gICAgY29uc3QgbmV4dCA9IGFwcGx5KHIuYm91bmRzKTtcbiAgICBpZiAoIW5leHQpIHJldHVybjtcbiAgICB0aGlzLnJlY29yZFVuZG9TbmFwc2hvdCgpO1xuICAgIHRoaXMucmVwbGFjZVJlZ2lvbihyZXBsYWNlQm91bmRzKHIsIG5leHQpKTtcbiAgfVxuXG4gIC8qKiBTd2FwIGBuZXh0YCBpbiBmb3IgdGhlIHN0b3JlZCByZWdpb24gd2l0aCBpdHMgaWQgKGEgbmV3IGFycmF5KSwgdGhlbiBzeW5jIGFuZCBlbWl0LiAqL1xuICBwcml2YXRlIHJlcGxhY2VSZWdpb24obmV4dDogUmVnaW9uKTogdm9pZCB7XG4gICAgdGhpcy5yZWdpb25zID0gdGhpcy5yZWdpb25zLm1hcCgocikgPT4gKHIuaWQgPT09IG5leHQuaWQgPyBuZXh0IDogcikpO1xuICAgIHRoaXMuc3luY0NhY2hlKCk7XG4gICAgdGhpcy5lbWl0KCk7XG4gIH1cblxuICAvKiogQ29hbGVzY2UgYHJlZ2lvblVwZGF0ZSRgIHVudGlsIHRoZSBtYXRjaGluZyB7QGxpbmsgZW5kQmF0Y2h9IChsaXZlIGRyYWdzKTtcbiAgICogIHRoZSBiYXRjaCBpcyBhbHNvIG9uZSB1bmRvIGdlc3R1cmUgKHtAbGluayBiZWdpbkdlc3R1cmV9KS4gKi9cbiAgYmVnaW5CYXRjaCgpOiB2b2lkIHtcbiAgICB0aGlzLmJhdGNoRGVwdGgrKztcbiAgICB0aGlzLmJlZ2luR2VzdHVyZSgpO1xuICB9XG4gIGVuZEJhdGNoKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmJhdGNoRGVwdGggPiAwKSB0aGlzLmJhdGNoRGVwdGgtLTtcbiAgICB0aGlzLmVuZEdlc3R1cmUoKTtcbiAgICBpZiAodGhpcy5iYXRjaERlcHRoID09PSAwICYmIHRoaXMucGVuZGluZ0VtaXQpIHtcbiAgICAgIHRoaXMucGVuZGluZ0VtaXQgPSBmYWxzZTtcbiAgICAgIHRoaXMucmVnaW9uVXBkYXRlJC5uZXh0KHRoaXMuZ2V0UmVnaW9ucygpKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTWFyayB0aGUgc3RhcnQgb2Ygb25lIHVzZXIgZ2VzdHVyZSAoZS5nLiBhIHdhbmQvYnJ1c2ggbW91c2Vkb3duKTogZXZlcnlcbiAgICogY29tbWl0IHVudGlsIHRoZSBtYXRjaGluZyB7QGxpbmsgZW5kR2VzdHVyZX0gYmVjb21lcyBhIHNpbmdsZSB1bmRvIHN0ZXAsXG4gICAqIHdpdGhvdXQgZGVsYXlpbmcgYHJlZ2lvblVwZGF0ZSRgICh0b29scyByZW5kZXIgdGhyb3VnaCBpdCB3aGlsZSBkcmFnZ2luZykuXG4gICAqIENhbGxzIG5lc3QuIEEgZ2VzdHVyZSBuZXZlciBmb2xkcyBpbnRvIGFuIGVhcmxpZXIgdGltZWQgYnVyc3QuXG4gICAqL1xuICBiZWdpbkdlc3R1cmUoKTogdm9pZCB7XG4gICAgdGhpcy5oaXN0b3J5LmJlZ2luR2VzdHVyZSgpO1xuICB9XG5cbiAgLyoqIEVuZCB0aGUgZ2VzdHVyZSBvcGVuZWQgYnkge0BsaW5rIGJlZ2luR2VzdHVyZX07IHRoZSBuZXh0IGNvbW1pdCBzdGFydHMgYSBuZXcgc3RlcC4gKi9cbiAgZW5kR2VzdHVyZSgpOiB2b2lkIHtcbiAgICB0aGlzLmhpc3RvcnkuZW5kR2VzdHVyZSgpO1xuICB9XG5cbiAgLy8g4pSA4pSAIFJlZ2lvbiBzb3VyY2VzOiBsYXJnZSByZWdpb24gc2V0cywgdGlsZWQgYnkgbGV2ZWwgb2YgZGV0YWlsIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gIC8qKlxuICAgKiBIb2xkIGEgbGFyZ2UgcmVnaW9uIHNldCBhcyBhIHRpbGVkIHJlZ2lvbiBzb3VyY2UgaW5zdGVhZCBvZiBhcyByZWdpb25zOiB0aGUgYmFja2VuZHMgdGhhdFxuICAgKiBkcmF3IHNvdXJjZXMgKE9wZW5TZWFkcmFnb24sIG5hcGFyaSkgZHJhdyBpdHMgZmVhdHVyZXMgYXQgdGhlIGRldGFpbCB0aGUgem9vbSBzaG93cywgZnJvbVxuICAgKiB0aGUgdGlsZXMgaW4gdmlldywgYW5kIGEgZmVhdHVyZSBqb2lucyB0aGUgcmVnaW9ucyDigJQgZXhhY3RseSwgYXMgYW4gb3JkaW5hcnkgZWRpdGFibGVcbiAgICoge0BsaW5rIFJlZ2lvbn0gd2l0aCBpdHMge0BsaW5rIFJlZ2lvbi5zb3VyY2VJZH0g4oCUIG9ubHkgd2hlbiBpdCBpcyBzZWxlY3RlZCBvciBlZGl0ZWRcbiAgICogKHtAbGluayB0YWtlU291cmNlRmVhdHVyZXN9KS4gVW50aWwgdGhlbiB7QGxpbmsgZ2V0UmVnaW9uc30gZG9lcyBub3QgaW5jbHVkZSBpdC5cbiAgICpcbiAgICogYHNvdXJjZWAgbWF5IGJlIGFuIG9wZW5lciwgY2FsbGVkIHRoZSBmaXJzdCB0aW1lIGl0cyBzbGljZSBpcyBzaG93biAoYW5kIGFnYWluIGlmIHRoZVxuICAgKiBzb3VyY2Ugd2FzIGNsb3NlZCB0byBzYXZlIG1lbW9yeSkuIGBzbGljZXNgIHNheXMgd2hpY2ggc2xpY2Ugb2YgdGhlIGN1cnJlbnQgaW1hZ2UgaXRcbiAgICogc2VydmVzOiBvbmUgKGRlZmF1bHQ6IHRoZSBzbGljZSBzaG93bjsgcGxhbmUgMCBvZiB0aGUgc291cmNlKSwgb3IgYCdwbGFuZXMnYCwgZXZlcnkgc2xpY2UgelxuICAgKiBmcm9tIHBsYW5lIHogb2YgYSB6LWluZGV4ZWQgc291cmNlLiBSZXBsYWNlcyB0aGUgc291cmNlIHRob3NlIHNsaWNlcyBoYWQuXG4gICAqL1xuICBhdHRhY2hSZWdpb25Tb3VyY2UoXG4gICAgc291cmNlOiBSZWdpb25Tb3VyY2UgfCBSZWdpb25Tb3VyY2VPcGVuZXIsXG4gICAgc2xpY2VzOiBSZWdpb25Tb3VyY2VTbGljZXMgPSB7IHNsaWNlOiB0aGlzLnNvdXJjZVNsaWNlIH0sXG4gICk6IHZvaWQge1xuICAgIGNvbnN0IGltYWdlID0gdGhpcy5zY29wZS5hY3RpdmVJbWFnZTtcbiAgICBpZiAoIWltYWdlKSByZXR1cm47XG4gICAgY29uc3Qgb3BlbjogUmVnaW9uU291cmNlT3BlbmVyID0gdHlwZW9mIHNvdXJjZSA9PT0gJ2Z1bmN0aW9uJyA/IHNvdXJjZSA6ICgpID0+IFByb21pc2UucmVzb2x2ZShzb3VyY2UpO1xuICAgIHRoaXMuc291cmNlcy5hdHRhY2goaW1hZ2UsIG9wZW4sIHNsaWNlcyk7XG4gICAgdGhpcy5zb3VyY2VzVmVyc2lvbisrO1xuICAgIHRoaXMucmVmcmVzaFNvdXJjZVZpZXcoKTtcbiAgfVxuXG4gIC8qKiBEcm9wIHRoZSBjdXJyZW50IGltYWdlJ3MgcmVnaW9uIHNvdXJjZXMgKGNsb3NpbmcgdGhlbSkgYW5kIHdoYXQgd2FzIHRha2VuIGZyb20gdGhlbS4gKi9cbiAgZGV0YWNoUmVnaW9uU291cmNlcygpOiB2b2lkIHtcbiAgICBjb25zdCBpbWFnZSA9IHRoaXMuc2NvcGUuYWN0aXZlSW1hZ2U7XG4gICAgaWYgKCFpbWFnZSkgcmV0dXJuO1xuICAgIHRoaXMuc291cmNlcy5kZXRhY2hJbWFnZShpbWFnZSk7XG4gICAgdGhpcy5zb3VyY2VzVmVyc2lvbisrO1xuICAgIHRoaXMucmVmcmVzaFNvdXJjZVZpZXcoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEcm9wIHRoZSBzbGljZSdzIHJlZ2lvbiBzb3VyY2UsIGZvciByZWdpb25zIGltcG9ydGVkIGluIHBsYWNlIG9mIHRoZSBzbGljZSdzIChhIHNtYWxsIGZpbGVcbiAgICogcmVwbGFjaW5nIGEgbGFyZ2Ugb25lKTogYSBzb3VyY2Ugb2YgdGhlIHNsaWNlJ3Mgb3duIGlzIGRldGFjaGVkOyBhIHotaW5kZXhlZCBzb3VyY2Ugb3ZlciBldmVyeVxuICAgKiBzbGljZSBoYXMgdGhpcyBzbGljZSdzIGZlYXR1cmVzIHRha2VuIG91dCAoYXMgZGVsZXRlZCkuIFRoZSBvdGhlciBzbGljZXMga2VlcCB0aGVpcnMuXG4gICAqL1xuICBhc3luYyBkcm9wU2xpY2VSZWdpb25Tb3VyY2UoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgaW1hZ2UgPSB0aGlzLnNjb3BlLmFjdGl2ZUltYWdlO1xuICAgIGNvbnN0IHNsaWNlID0gdGhpcy5zb3VyY2VTbGljZTtcbiAgICBpZiAoIWltYWdlIHx8ICF0aGlzLnNvdXJjZXMuaGFzKGltYWdlLCBzbGljZSkpIHJldHVybjtcbiAgICBpZiAodGhpcy5zb3VyY2VzLmhhc093blNvdXJjZShpbWFnZSwgc2xpY2UpKSB7XG4gICAgICB0aGlzLnNvdXJjZXMuZGV0YWNoU2xpY2UoaW1hZ2UsIHNsaWNlKTtcbiAgICAgIHRoaXMuc291cmNlc1ZlcnNpb24rKztcbiAgICAgIHRoaXMucmVmcmVzaFNvdXJjZVZpZXcoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgZ2VuZXJhdGlvbiA9IHRoaXMuc291cmNlR2VuZXJhdGlvbjtcbiAgICBjb25zdCBiaW5kaW5nID0gYXdhaXQgdGhpcy5zb3VyY2VzLmJpbmRpbmcoaW1hZ2UsIHNsaWNlKTtcbiAgICBpZiAoIWJpbmRpbmcgfHwgZ2VuZXJhdGlvbiAhPT0gdGhpcy5zb3VyY2VHZW5lcmF0aW9uKSByZXR1cm47XG4gICAgY29uc3QgYWxsID0gYXdhaXQgYmluZGluZy5zb3VyY2UuZ2V0SW5kZXgoYmluZGluZy5wbGFuZSwge1xuICAgICAgb2Zmc2V0OiAwLFxuICAgICAgbGltaXQ6IGJpbmRpbmcuc291cmNlLmluZm8uZmVhdHVyZUNvdW50LFxuICAgIH0pO1xuICAgIGlmIChnZW5lcmF0aW9uICE9PSB0aGlzLnNvdXJjZUdlbmVyYXRpb24pIHJldHVybjtcbiAgICB0aGlzLnNldFRha2VuKG5ldyBTZXQoWy4uLnRoaXMuY3VycmVudFRha2VuKCksIC4uLmFsbC5yb3dzLm1hcCgocikgPT4gci5pZCldKSk7XG4gIH1cblxuICAvKiogV2hldGhlciB0aGUgc2xpY2Ugc2hvd24gaGFzIGEgcmVnaW9uIHNvdXJjZS4gKi9cbiAgaGFzUmVnaW9uU291cmNlKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnNvdXJjZXMuaGFzKHRoaXMuc2NvcGUuYWN0aXZlSW1hZ2UsIHRoaXMuc291cmNlU2xpY2UpO1xuICB9XG5cbiAgLyoqIFRoZSBzbGljZSdzIHJlZ2lvbiBzb3VyY2UgYXMgYSBzb3VyY2UgbGF5ZXIgZHJhd3MgaXQ7IG51bGwgd2l0aG91dCBvbmUgKG9yIHVudGlsIGl0IG9wZW5zKS4gKi9cbiAgZ2V0UmVnaW9uU291cmNlVmlldygpOiBSZWdpb25Tb3VyY2VWaWV3IHwgbnVsbCB7XG4gICAgcmV0dXJuIHRoaXMuc291cmNlVmlldyQudmFsdWU7XG4gIH1cblxuICAvKioge0BsaW5rIGdldFJlZ2lvblNvdXJjZVZpZXd9IGFuZCBldmVyeSBjaGFuZ2Ugb2YgaXQgKHNsaWNlLCB0YWtlbiBpZHMsIGNsYXNzIGNvbG91cnMpLiAqL1xuICBnZXRSZWdpb25Tb3VyY2VWaWV3JCgpOiBPYnNlcnZhYmxlPFJlZ2lvblNvdXJjZVZpZXcgfCBudWxsPiB7XG4gICAgcmV0dXJuIHRoaXMuc291cmNlVmlldyQuYXNPYnNlcnZhYmxlKCk7XG4gIH1cblxuICAvKipcbiAgICogVGFrZSBzb3VyY2UgZmVhdHVyZXMgaW50byB0aGUgd29ya2luZyBzZXQgZm9yIGVkaXRpbmc6IHRoZWlyIGV4YWN0IGdlb21ldHJ5IGJlY29tZXNcbiAgICogb3JkaW5hcnkgcmVnaW9ucyAobWludGVkLCBjb2xvdXJlZCBhbmQgc2xpY2UtdGFnZ2VkIGFzIGFueSByZWdpb24gZW50ZXJpbmcgdGhlIHN0b3JlKSBhbmRcbiAgICogdGhlIHNvdXJjZSBzdG9wcyBkcmF3aW5nIHRoZW0uIE5vdCBhbiB1bmRvIHN0ZXAgb2YgaXRzIG93biDigJQgdW5kb2luZyBwYXN0IGl0IHB1dHMgdGhlXG4gICAqIGZlYXR1cmVzIGJhY2sgaW4gdGhlIHNvdXJjZS4gUmVzb2x2ZXMgdGhlIHJlZ2lvbiBpZHMsIGluIHRoZSBvcmRlciBhc2tlZCAoYSBmZWF0dXJlIGFscmVhZHlcbiAgICogdGFrZW4gcmVzb2x2ZXMgdG8gaXRzIHJlZ2lvbik7IFtdIHdoZW4gdGhlIHNsaWNlIGNoYW5nZWQgbWVhbndoaWxlLlxuICAgKi9cbiAgYXN5bmMgdGFrZVNvdXJjZUZlYXR1cmVzKGlkczogcmVhZG9ubHkgc3RyaW5nW10pOiBQcm9taXNlPG51bWJlcltdPiB7XG4gICAgY29uc3QgdmlldyA9IHRoaXMuc291cmNlVmlldyQudmFsdWU7XG4gICAgaWYgKCF2aWV3IHx8ICFpZHMubGVuZ3RoKSByZXR1cm4gW107XG4gICAgY29uc3QgZ2VuZXJhdGlvbiA9IHRoaXMuc291cmNlR2VuZXJhdGlvbjtcbiAgICBjb25zdCB3YW50ZWQgPSBpZHMuZmlsdGVyKChpZCkgPT4gIXZpZXcudGFrZW4uaGFzKGlkKSk7XG4gICAgY29uc3QgZmVhdHVyZXMgPSB3YW50ZWQubGVuZ3RoID8gYXdhaXQgdmlldy5zb3VyY2UuZ2V0RmVhdHVyZXMod2FudGVkKSA6IFtdO1xuICAgIGlmIChnZW5lcmF0aW9uICE9PSB0aGlzLnNvdXJjZUdlbmVyYXRpb24pIHJldHVybiBbXTtcbiAgICBjb25zdCB0YWtlbiA9IHRoaXMuY3VycmVudFRha2VuKCk7XG4gICAgY29uc3QgZnJlc2ggPSBmZWF0dXJlcy5maWx0ZXIoKGYpID0+ICF0YWtlbi5oYXMoZi5pZCkpO1xuICAgIGlmIChmcmVzaC5sZW5ndGgpIHtcbiAgICAgIGNvbnN0IHJlZ2lvbnMgPSBmcmVzaC5tYXAoKGYpID0+IHtcbiAgICAgICAgY29uc3QgcmVnaW9uID0gcmVnaW9uRnJvbUdlb0pzb25GZWF0dXJlKGYuZmVhdHVyZSBhcyBHZW9Kc29uRmVhdHVyZSwgMCwgZi5pZCk7XG4gICAgICAgIGlmICh0aGlzLnNjb3BlLnN0YWNrTW9kZSkgcmVnaW9uLnogPSB0aGlzLnNjb3BlLmRpc3BsYXlTbGljZTtcbiAgICAgICAgcmV0dXJuIHJlZ2lvbjtcbiAgICAgIH0pO1xuICAgICAgY29uc3QgYWRtaXR0ZWQgPSB0aGlzLmFkbWl0KHJlZ2lvbnMpO1xuICAgICAgLy8gRnJlc2ggaW5zdGFuY2VzLCBjb21wbGV0ZWQgaW4gcGxhY2U6IG5hbWVkIGFmdGVyIHRoZWlyIG5ldyBpZCBsaWtlIGEgZHJhd24gcmVnaW9uLlxuICAgICAgZm9yIChjb25zdCByIG9mIGFkbWl0dGVkKSByLm5hbWUgPSBgc2hhcGUke3IuaWR9YDtcbiAgICAgIHRoaXMucmVnaW9ucyA9IHRoaXMucmVnaW9ucy5jb25jYXQoYWRtaXR0ZWQpO1xuICAgICAgdGhpcy5zZXRUYWtlbihuZXcgU2V0KFsuLi50YWtlbiwgLi4uZnJlc2gubWFwKChmKSA9PiBmLmlkKV0pKTtcbiAgICAgIHRoaXMuc3luY0NhY2hlKCk7XG4gICAgICB0aGlzLmVtaXRTZWxlY3Rpb24oKTtcbiAgICAgIHRoaXMuZW1pdCgpO1xuICAgIH1cbiAgICBjb25zdCBieVNvdXJjZSA9IG5ldyBNYXAodGhpcy5yZWdpb25zLmZpbHRlcigocikgPT4gci5zb3VyY2VJZCAhPT0gdW5kZWZpbmVkKS5tYXAoKHIpID0+IFtyLnNvdXJjZUlkLCByLmlkXSkpO1xuICAgIHJldHVybiBpZHMubWFwKChpZCkgPT4gYnlTb3VyY2UuZ2V0KGlkKSkuZmlsdGVyKChpZCk6IGlkIGlzIG51bWJlciA9PiBpZCAhPT0gdW5kZWZpbmVkKTtcbiAgfVxuXG4gIC8qKiB7QGxpbmsgdGFrZVNvdXJjZUZlYXR1cmVzfSwgdGhlbiBzZWxlY3QgdGhlbSAoYWRkZWQgdG8gdGhlIHNlbGVjdGlvbiB3aXRoIGBhZGRpdGl2ZWApLiAqL1xuICBhc3luYyBzZWxlY3RTb3VyY2VGZWF0dXJlcyhpZHM6IHJlYWRvbmx5IHN0cmluZ1tdLCBhZGRpdGl2ZSA9IGZhbHNlKTogUHJvbWlzZTxudW1iZXJbXT4ge1xuICAgIGNvbnN0IHRha2VuID0gYXdhaXQgdGhpcy50YWtlU291cmNlRmVhdHVyZXMoaWRzKTtcbiAgICBpZiAoIXRha2VuLmxlbmd0aCkgcmV0dXJuIHRha2VuO1xuICAgIHRoaXMuc2VsZWN0aW9uLnJlcGxhY2UoYWRkaXRpdmUgPyBbLi4ubmV3IFNldChbLi4udGhpcy5zZWxlY3Rpb24uaWRzLCAuLi50YWtlbl0pXSA6IHRha2VuKTtcbiAgICB0aGlzLmVtaXRTZWxlY3Rpb24oKTtcbiAgICByZXR1cm4gdGFrZW47XG4gIH1cblxuICAvKipcbiAgICogRmVhdHVyZXMgcGVyIGNsYXNzIHN0aWxsIGluIHRoZSBzbGljZSdzIHJlZ2lvbiBzb3VyY2UgKG5vdCB0YWtlbik7IHt9IHdpdGhvdXQgb25lLiBXaXRoXG4gICAqIGBzdGFja2AsIGEgei1zdGFjaydzIG92ZXIgZXZlcnkgc2xpY2U6IGl0cyBzb3VyY2UncyBwbGFuZXMsIG9yIGVhY2ggc2xpY2UncyBzb3VyY2UgYWRkZWQgdXAuXG4gICAqL1xuICBhc3luYyBnZXRSZWdpb25Tb3VyY2VDbGFzc0NvdW50cyhzdGFjayA9IGZhbHNlKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBudW1iZXI+PiB7XG4gICAgY29uc3QgdmlldyA9IHRoaXMuc291cmNlVmlldyQudmFsdWU7XG4gICAgY29uc3QgaW1hZ2UgPSB0aGlzLnNjb3BlLmFjdGl2ZUltYWdlO1xuICAgIGlmICghc3RhY2sgfHwgIXRoaXMuc2NvcGUuc3RhY2tNb2RlKSB7XG4gICAgICByZXR1cm4gdmlldyA/IHZpZXcuc291cmNlLmdldENsYXNzQ291bnRzKHZpZXcucGxhbmUsIEFycmF5LmZyb20odmlldy50YWtlbikpIDoge307XG4gICAgfVxuICAgIGlmICh0aGlzLnNvdXJjZXMuaGFzUGxhbmVzU291cmNlKGltYWdlKSkge1xuICAgICAgY29uc3QgYmluZGluZyA9IGF3YWl0IHRoaXMuc291cmNlcy5iaW5kaW5nKGltYWdlLCB0aGlzLnNvdXJjZVNsaWNlKTtcbiAgICAgIGlmICghYmluZGluZykgcmV0dXJuIHt9O1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IGJpbmRpbmcuc291cmNlLmdldENsYXNzQ291bnRzKG51bGwsIHRoaXMuc291cmNlcy5hbGxUYWtlbihpbWFnZSkpO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIC8vIEEgdGlsZSBzZXJ2ZXIgdGhhdCBwcmVkYXRlcyBjb3VudGluZyBldmVyeSBwbGFuZTogdGhlIHNsaWNlJ3MgY291bnRzLlxuICAgICAgICBjb25zb2xlLndhcm4oJ1tyZWdpb25zXSBjb3VsZCBub3QgY291bnQgdGhlIGNsYXNzZXMgb2YgZXZlcnkgc2xpY2UnLCBlcnIpO1xuICAgICAgICByZXR1cm4gdmlldyA/IHZpZXcuc291cmNlLmdldENsYXNzQ291bnRzKHZpZXcucGxhbmUsIEFycmF5LmZyb20odmlldy50YWtlbikpIDoge307XG4gICAgICB9XG4gICAgfVxuICAgIGNvbnN0IGNvdW50czogUmVjb3JkPHN0cmluZywgbnVtYmVyPiA9IHt9O1xuICAgIGZvciAoY29uc3Qgc2xpY2Ugb2YgdGhpcy5zb3VyY2VzLnNsaWNlc1dpdGhTb3VyY2UoaW1hZ2UpKSB7XG4gICAgICBjb25zdCBiaW5kaW5nID0gYXdhaXQgdGhpcy5zb3VyY2VzLmJpbmRpbmcoaW1hZ2UsIHNsaWNlKTtcbiAgICAgIGlmICghYmluZGluZykgY29udGludWU7XG4gICAgICBjb25zdCBvd24gPSBhd2FpdCBiaW5kaW5nLnNvdXJjZS5nZXRDbGFzc0NvdW50cyhiaW5kaW5nLnBsYW5lLCBBcnJheS5mcm9tKHRoaXMuc291cmNlcy50YWtlbihpbWFnZSwgc2xpY2UpKSk7XG4gICAgICBmb3IgKGNvbnN0IFtsYWJlbCwgbl0gb2YgT2JqZWN0LmVudHJpZXMob3duKSkgY291bnRzW2xhYmVsXSA9IChjb3VudHNbbGFiZWxdID8/IDApICsgbjtcbiAgICB9XG4gICAgcmV0dXJuIGNvdW50cztcbiAgfVxuXG4gIC8qKlxuICAgKiBTZWxlY3QgZXZlcnkgcmVnaW9uIG9mIHRoZXNlIGNsYXNzZXMgb24gdGhlIHNsaWNlIOKAlCB0aGUgcmVnaW9ucycsIGFuZCB0aGUgcmVnaW9uIHNvdXJjZSdzLFxuICAgKiB3aGljaCBhcmUgdGFrZW4gaW50byB0aGUgcmVnaW9ucyAoYXQgbW9zdCB7QGxpbmsgU0VMRUNUX0NMQVNTRVNfTElNSVR9IG9mIHRoZW0pLiBBZGRlZCB0byB0aGVcbiAgICogc2VsZWN0aW9uIHdpdGggYGFkZGl0aXZlYC4gUmVzb2x2ZXMgdGhlIHNlbGVjdGVkIHJlZ2lvbiBpZHMuXG4gICAqL1xuICBhc3luYyBzZWxlY3RDbGFzc2VzKGNsYXNzZXM6IHJlYWRvbmx5IHN0cmluZ1tdLCBhZGRpdGl2ZSA9IGZhbHNlKTogUHJvbWlzZTxudW1iZXJbXT4ge1xuICAgIGNvbnN0IHdhbnRlZCA9IG5ldyBTZXQoY2xhc3Nlcyk7XG4gICAgY29uc3QgdmlldyA9IHRoaXMuc291cmNlVmlldyQudmFsdWU7XG4gICAgaWYgKHZpZXcgJiYgY2xhc3Nlcy5sZW5ndGgpIHtcbiAgICAgIGNvbnN0IHBhZ2UgPSBhd2FpdCB2aWV3LnNvdXJjZS5nZXRJbmRleCh2aWV3LnBsYW5lLCB7XG4gICAgICAgIG9mZnNldDogMCxcbiAgICAgICAgbGltaXQ6IFNFTEVDVF9DTEFTU0VTX0xJTUlULFxuICAgICAgICBjbGFzc2VzLFxuICAgICAgICBleGNsdWRlOiBBcnJheS5mcm9tKHZpZXcudGFrZW4pLFxuICAgICAgfSk7XG4gICAgICBpZiAocGFnZS5yb3dzLmxlbmd0aCkgYXdhaXQgdGhpcy50YWtlU291cmNlRmVhdHVyZXMocGFnZS5yb3dzLm1hcCgocikgPT4gci5pZCkpO1xuICAgIH1cbiAgICBjb25zdCBpZHMgPSB0aGlzLnJlZ2lvbnMuZmlsdGVyKChyKSA9PiAhci5pc1Byb2ZpbGU/LigpICYmIHIubGFiZWwgJiYgd2FudGVkLmhhcyhyLmxhYmVsKSkubWFwKChyKSA9PiByLmlkKTtcbiAgICB0aGlzLnNlbGVjdGlvbi5yZXBsYWNlKGFkZGl0aXZlID8gWy4uLm5ldyBTZXQoWy4uLnRoaXMuc2VsZWN0aW9uLmlkcywgLi4uaWRzXSldIDogaWRzKTtcbiAgICB0aGlzLmVtaXRTZWxlY3Rpb24oKTtcbiAgICByZXR1cm4gaWRzO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSAzRCByZWNvbnN0cnVjdGlvbiBvZiBlYWNoIGdyb3VwIG9mIGNsYXNzZXMgb3ZlciBldmVyeSBzbGljZSBvZiB0aGUgc3RhY2sgKGFuIGF0bGFzXG4gICAqIHN0cnVjdHVyZSB3aXRoIGl0cyBzdWJzdHJ1Y3R1cmVzLCBzYXkpOiB0aGUgb3V0bGluZXMgb2YgdGhlIHJlZ2lvbnMgb2YgdGhvc2UgY2xhc3NlcyBvbiBldmVyeVxuICAgKiBzbGljZSDigJQgdGhlIHJlZ2lvbiBzb3VyY2VzJyBhbmQgdGhvc2UgZHJhd24gb3IgdGFrZW4g4oCUIHN0YWNrZWQgYW5kIG1lc2hlZCBpbiBhIHdvcmtlci4gTWVzaGVzXG4gICAqIGFyZSBpbiBpbWFnZSBweCAoeCwgeSkgYW5kIHNsaWNlIGluZGljZXMgKHopLiBgcGl4ZWxTdGVwYCBpcyB0aGUgaW4tcGxhbmUgdm94ZWwgc2l6ZSAoaW1hZ2VcbiAgICogcHgpOyB0aGUgb3V0bGluZXMgYXJlIHJlYWQgYXQgdGhlIG1hdGNoaW5nIGxldmVsIG9mIGRldGFpbC4gQSBncm91cCB3aXRoIG5vIG91dGxpbmUgZ2V0cyBhblxuICAgKiBlbXB0eSBtZXNoLlxuICAgKi9cbiAgYXN5bmMgcmVjb25zdHJ1Y3RDbGFzc2VzKFxuICAgIGdyb3VwczogUmVhZG9ubHlBcnJheTx7IGtleTogc3RyaW5nOyBjbGFzc2VzOiByZWFkb25seSBzdHJpbmdbXSB9PixcbiAgICBwaXhlbFN0ZXAgPSAxLFxuICApOiBQcm9taXNlPEFycmF5PHsga2V5OiBzdHJpbmc7IG1lc2g6IE1lc2ggfT4+IHtcbiAgICBjb25zdCBsZXZlbCA9IE1hdGgubWF4KDAsIE1hdGguZmxvb3IoTWF0aC5sb2cyKE1hdGgubWF4KDEsIHBpeGVsU3RlcCkpKSk7XG4gICAgY29uc3Qgb3V0OiBBcnJheTx7IGtleTogc3RyaW5nOyBtZXNoOiBNZXNoIH0+ID0gW107XG4gICAgZm9yIChjb25zdCBncm91cCBvZiBncm91cHMpIHtcbiAgICAgIGNvbnN0IHNsaWNlcyA9IGF3YWl0IHRoaXMuY2xhc3NPdXRsaW5lcyhncm91cC5jbGFzc2VzLCBsZXZlbCk7XG4gICAgICBvdXQucHVzaCh7IGtleTogZ3JvdXAua2V5LCBtZXNoOiBhd2FpdCByZWNvbnN0cnVjdEluV29ya2VyKHNsaWNlcywgeyBwaXhlbFN0ZXAgfSkgfSk7XG4gICAgfVxuICAgIHJldHVybiBvdXQ7XG4gIH1cblxuICAvKipcbiAgICogRWFjaCBjbGFzcydzIHZvbHVtZSBvdmVyIHRoZSB3aG9sZSBzdGFjaywgaW4gcHjCsiDDlyBzbGljZXM6IGl0cyBvdXRsaW5lcycgYXJlYSBvbiBldmVyeSBzbGljZVxuICAgKiAoaXRzIGZlYXR1cmVzJyB1bmlvbiwgc2VlIGBvdXRsaW5lc0FyZWFgKSwgb25lIHNsaWNlIHRoaWNrIChDYXZhbGllcmkncyBlc3RpbWF0b3IpLCBmcm9tIHRoZVxuICAgKiBleGFjdCBvdXRsaW5lcy4gV2hlcmUgYSBmZWF0dXJlIGlzLCBhIHJlZ2lvbiBzb3VyY2UncyBvciBhIGRyYXduIG9yIHRha2VuIHJlZ2lvbiwgZG9lcyBub3RcbiAgICogY2hhbmdlIGl0OiB0YWtpbmcgb25lIGxlYXZlcyB0aGUgdm9sdW1lIGFzIGl0IHdhcy4gVGhlIHJlZ2lvbiBzb3VyY2VzJyBwYXJ0IGlzIGNhY2hlZCB1bnRpbFxuICAgKiB3aGF0IHRoZXkgaG9sZCBjaGFuZ2VzIChhIGZlYXR1cmUgdGFrZW4gb3IgZGVsZXRlZCwgYW5vdGhlciBzb3VyY2UpOyBvbmx5IHRoZSBzbGljZXMgd2l0aFxuICAgKiBkcmF3biBvciB0YWtlbiByZWdpb25zIG9mIHRoZSBjbGFzcyBhcmUgbWVhc3VyZWQgYWdhaW4uXG4gICAqL1xuICBhc3luYyBjbGFzc1ZvbHVtZXMoY2xhc3NlczogcmVhZG9ubHkgc3RyaW5nW10pOiBQcm9taXNlPE1hcDxzdHJpbmcsIG51bWJlcj4+IHtcbiAgICBjb25zdCBzdGF0ZSA9IHRoaXMuc291cmNlU3RhdGVLZXkoKTtcbiAgICBjb25zdCBvdXQgPSBuZXcgTWFwPHN0cmluZywgbnVtYmVyPigpO1xuICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgWy4uLm5ldyBTZXQoY2xhc3NlcyldLm1hcChhc3luYyAobmFtZSkgPT4ge1xuICAgICAgICBjb25zdCBzb3VyY2UgPSBhd2FpdCB0aGlzLnNvdXJjZVZvbHVtZShzdGF0ZSwgbmFtZSk7XG4gICAgICAgIGxldCB2b2x1bWUgPSBzb3VyY2UudG90YWw7XG4gICAgICAgIGZvciAoY29uc3QgcmVnaW9ucyBvZiBtZXJnZU91dGxpbmVzKHRoaXMucmVnaW9uT3V0bGluZXMoW25hbWVdKSkpIHtcbiAgICAgICAgICBjb25zdCB1bmRlciA9IHNvdXJjZS5zbGljZXMuZ2V0KHJlZ2lvbnMueik7XG4gICAgICAgICAgY29uc3QgW2JvdGhdID0gdW5kZXIgPyBtZXJnZU91dGxpbmVzKFt1bmRlci5vdXRsaW5lcywgcmVnaW9uc10pIDogW3JlZ2lvbnNdO1xuICAgICAgICAgIHZvbHVtZSArPSBvdXRsaW5lc0FyZWEoYm90aC5yaW5ncywgYm90aC5yaW5nR3JvdXBzKSAtICh1bmRlcj8uYXJlYSA/PyAwKTtcbiAgICAgICAgfVxuICAgICAgICBvdXQuc2V0KG5hbWUsIHZvbHVtZSk7XG4gICAgICB9KSxcbiAgICApO1xuICAgIHJldHVybiBvdXQ7XG4gIH1cblxuICAvKiogVGhlIHJlZ2lvbiBzb3VyY2VzJyBwYXJ0IG9mIGEgY2xhc3MncyB2b2x1bWUsIGNhY2hlZCBieSB3aGF0IHRoZXkgaG9sZCAoc2VlIGNsYXNzVm9sdW1lcykuICovXG4gIHByaXZhdGUgc291cmNlVm9sdW1lKHN0YXRlOiBzdHJpbmcsIG5hbWU6IHN0cmluZyk6IFByb21pc2U8U291cmNlVm9sdW1lPiB7XG4gICAgY29uc3Qga2V5ID0gYCR7c3RhdGV9XFxuJHtuYW1lfWA7XG4gICAgbGV0IHNvdXJjZSA9IHRoaXMuc291cmNlVm9sdW1lQ2FjaGUuZ2V0KGtleSk7XG4gICAgaWYgKHNvdXJjZSkge1xuICAgICAgLy8gTW9zdCByZWNlbnRseSB1c2VkIGxhc3QuXG4gICAgICB0aGlzLnNvdXJjZVZvbHVtZUNhY2hlLmRlbGV0ZShrZXkpO1xuICAgICAgdGhpcy5zb3VyY2VWb2x1bWVDYWNoZS5zZXQoa2V5LCBzb3VyY2UpO1xuICAgICAgcmV0dXJuIHNvdXJjZTtcbiAgICB9XG4gICAgc291cmNlID0gdGhpcy5zb3VyY2VPdXRsaW5lcyhbbmFtZV0sIDApLnRoZW4oKHBhcnRzKSA9PiB7XG4gICAgICBjb25zdCBzbGljZXMgPSBuZXcgTWFwPG51bWJlciwgeyBhcmVhOiBudW1iZXI7IG91dGxpbmVzOiBTbGljZU91dGxpbmVzIH0+KCk7XG4gICAgICBsZXQgdG90YWwgPSAwO1xuICAgICAgZm9yIChjb25zdCBvdXRsaW5lcyBvZiBtZXJnZU91dGxpbmVzKHBhcnRzKSkge1xuICAgICAgICBjb25zdCBhcmVhID0gb3V0bGluZXNBcmVhKG91dGxpbmVzLnJpbmdzLCBvdXRsaW5lcy5yaW5nR3JvdXBzKTtcbiAgICAgICAgc2xpY2VzLnNldChvdXRsaW5lcy56LCB7IGFyZWEsIG91dGxpbmVzIH0pO1xuICAgICAgICB0b3RhbCArPSBhcmVhO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHsgdG90YWwsIHNsaWNlcyB9O1xuICAgIH0pO1xuICAgIHRoaXMuc291cmNlVm9sdW1lQ2FjaGUuc2V0KGtleSwgc291cmNlKTtcbiAgICBzb3VyY2UuY2F0Y2goKCkgPT4gdGhpcy5zb3VyY2VWb2x1bWVDYWNoZS5kZWxldGUoa2V5KSk7XG4gICAgd2hpbGUgKHRoaXMuc291cmNlVm9sdW1lQ2FjaGUuc2l6ZSA+IFNPVVJDRV9WT0xVTUVfQ0FDSEVfU0laRSkge1xuICAgICAgdGhpcy5zb3VyY2VWb2x1bWVDYWNoZS5kZWxldGUodGhpcy5zb3VyY2VWb2x1bWVDYWNoZS5rZXlzKCkubmV4dCgpLnZhbHVlIGFzIHN0cmluZyk7XG4gICAgfVxuICAgIHJldHVybiBzb3VyY2U7XG4gIH1cblxuICAvKipcbiAgICogRXZlcnkgc2xpY2UncyBvdXRsaW5lcyBvZiB0aGVzZSBjbGFzc2VzLCB0aGUgcmVnaW9uIHNvdXJjZXMnIHRoZW4gdGhlIHJlZ2lvbnMnOiBjbG9zZWQgc2hhcGVzJ1xuICAgKiByaW5ncywgYW5kIG9wZW4gcG9seWxpbmVzIGFzIGBsaW5lc2AuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGNsYXNzT3V0bGluZXMoY2xhc3NlczogcmVhZG9ubHkgc3RyaW5nW10sIGxldmVsOiBudW1iZXIpOiBQcm9taXNlPFNsaWNlT3V0bGluZXNbXT4ge1xuICAgIHJldHVybiBtZXJnZU91dGxpbmVzKFsuLi4oYXdhaXQgdGhpcy5zb3VyY2VPdXRsaW5lcyhjbGFzc2VzLCBsZXZlbCkpLCAuLi50aGlzLnJlZ2lvbk91dGxpbmVzKGNsYXNzZXMpXSk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIHJlZ2lvbiBzb3VyY2VzJyBvdXRsaW5lcyBvZiB0aGVzZSBjbGFzc2VzIG9uIGV2ZXJ5IHNsaWNlLCB3aXRob3V0IHRoZSBmZWF0dXJlcyB0YWtlbiBvclxuICAgKiBkZWxldGVkLiBUaGUgbGFzdCBmZXcgY2xhc3Mgc2V0cyBhcmUga2VwdCB1bnRpbCB3aGF0IHRoZSBzb3VyY2VzIGhvbGQgY2hhbmdlczogcmVidWlsZGluZyBhXG4gICAqIHN1cmZhY2UgYWZ0ZXIgYW4gZWRpdCByZWFkcyBub3RoaW5nIGFnYWluLlxuICAgKi9cbiAgcHJpdmF0ZSBzb3VyY2VPdXRsaW5lcyhjbGFzc2VzOiByZWFkb25seSBzdHJpbmdbXSB8IG51bGwsIGxldmVsOiBudW1iZXIpOiBQcm9taXNlPExhYmVsbGVkT3V0bGluZXNbXT4ge1xuICAgIGNvbnN0IGtleSA9IGAke3RoaXMuc291cmNlU3RhdGVLZXkoKX1cXG4ke2xldmVsfVxcbiR7Y2xhc3NlcyA/IGNsYXNzZXMuam9pbignXFxuJykgOiAnKid9YDtcbiAgICBjb25zdCBjYWNoZWQgPSB0aGlzLnNvdXJjZU91dGxpbmVDYWNoZS5nZXQoa2V5KTtcbiAgICBpZiAoY2FjaGVkKSB7XG4gICAgICAvLyBNb3N0IHJlY2VudGx5IHVzZWQgbGFzdC5cbiAgICAgIHRoaXMuc291cmNlT3V0bGluZUNhY2hlLmRlbGV0ZShrZXkpO1xuICAgICAgdGhpcy5zb3VyY2VPdXRsaW5lQ2FjaGUuc2V0KGtleSwgY2FjaGVkKTtcbiAgICAgIHJldHVybiBjYWNoZWQ7XG4gICAgfVxuICAgIGNvbnN0IHJlYWQgPSB0aGlzLnJlYWRTb3VyY2VPdXRsaW5lcyhjbGFzc2VzLCBsZXZlbCk7XG4gICAgdGhpcy5zb3VyY2VPdXRsaW5lQ2FjaGUuc2V0KGtleSwgcmVhZCk7XG4gICAgcmVhZC5jYXRjaCgoKSA9PiB0aGlzLnNvdXJjZU91dGxpbmVDYWNoZS5kZWxldGUoa2V5KSk7XG4gICAgd2hpbGUgKHRoaXMuc291cmNlT3V0bGluZUNhY2hlLnNpemUgPiBTT1VSQ0VfT1VUTElORV9DQUNIRV9TSVpFKSB7XG4gICAgICB0aGlzLnNvdXJjZU91dGxpbmVDYWNoZS5kZWxldGUodGhpcy5zb3VyY2VPdXRsaW5lQ2FjaGUua2V5cygpLm5leHQoKS52YWx1ZSBhcyBzdHJpbmcpO1xuICAgIH1cbiAgICByZXR1cm4gcmVhZDtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgcmVhZFNvdXJjZU91dGxpbmVzKGNsYXNzZXM6IHJlYWRvbmx5IHN0cmluZ1tdIHwgbnVsbCwgbGV2ZWw6IG51bWJlcik6IFByb21pc2U8TGFiZWxsZWRPdXRsaW5lc1tdPiB7XG4gICAgY29uc3Qgb3V0OiBMYWJlbGxlZE91dGxpbmVzW10gPSBbXTtcbiAgICBjb25zdCBpbWFnZSA9IHRoaXMuc2NvcGUuYWN0aXZlSW1hZ2U7XG4gICAgaWYgKHRoaXMuc291cmNlcy5oYXNQbGFuZXNTb3VyY2UoaW1hZ2UpKSB7XG4gICAgICBjb25zdCBiaW5kaW5nID0gYXdhaXQgdGhpcy5zb3VyY2VzLmJpbmRpbmcoaW1hZ2UsIHRoaXMuc291cmNlU2xpY2UpO1xuICAgICAgY29uc3Qgb3V0bGluZXMgPSBhd2FpdCBiaW5kaW5nPy5zb3VyY2UuZ2V0Q2xhc3NPdXRsaW5lcyhjbGFzc2VzLCBsZXZlbCwgdGhpcy5zb3VyY2VzLmFsbFRha2VuKGltYWdlKSk7XG4gICAgICBvdXQucHVzaCguLi4ob3V0bGluZXMgPz8gW10pKTtcbiAgICB9XG4gICAgZm9yIChjb25zdCB6IG9mIHRoaXMuc291cmNlcy5zbGljZXNXaXRoU291cmNlKGltYWdlKSkge1xuICAgICAgY29uc3QgYmluZGluZyA9IGF3YWl0IHRoaXMuc291cmNlcy5iaW5kaW5nKGltYWdlLCB6KTtcbiAgICAgIGlmICghYmluZGluZykgY29udGludWU7XG4gICAgICBjb25zdCBvdXRsaW5lcyA9IGF3YWl0IGJpbmRpbmcuc291cmNlLmdldENsYXNzT3V0bGluZXMoXG4gICAgICAgIGNsYXNzZXMsXG4gICAgICAgIGxldmVsLFxuICAgICAgICBBcnJheS5mcm9tKHRoaXMuc291cmNlcy50YWtlbihpbWFnZSwgeikpLFxuICAgICAgKTtcbiAgICAgIGZvciAoY29uc3QgcyBvZiBvdXRsaW5lcykgaWYgKHMueiA9PT0gYmluZGluZy5wbGFuZSkgb3V0LnB1c2goeyAuLi5zLCB6IH0pO1xuICAgIH1cbiAgICByZXR1cm4gb3V0O1xuICB9XG5cbiAgLyoqXG4gICAqIEV2ZXJ5IGNsYXNzJ3Mgb3V0bGluZXMgb24gZXZlcnkgc2xpY2UsIGJ5IGNsYXNzOiB0aGUgcmVnaW9uIHNvdXJjZXMnIChvbmUgcmVhZCBmb3IgYWxsLCBrZXB0XG4gICAqIGxpa2Uge0BsaW5rIHNvdXJjZU91dGxpbmVzfSkgYW5kIHRoZSBkcmF3biBhbmQgdGFrZW4gcmVnaW9ucycuIFdoYXQgYSBzZWN0aW9uIHRocm91Z2ggdGhlXG4gICAqIHN0YWNrIGN1dHMgKHNlZSBgZ2VvbWV0cnkvc2VjdGlvbmApLlxuICAgKi9cbiAgYXN5bmMgb3V0bGluZXNCeUNsYXNzKGxldmVsOiBudW1iZXIpOiBQcm9taXNlPE1hcDxzdHJpbmcsIFNsaWNlT3V0bGluZXNbXT4+IHtcbiAgICBjb25zdCBieUNsYXNzID0gbmV3IE1hcDxzdHJpbmcsIE1hcDxudW1iZXIsIFNsaWNlUGFydHM+PigpO1xuICAgIGNvbnN0IHNsb3QgPSAobGFiZWw6IHN0cmluZywgejogbnVtYmVyKSA9PiB7XG4gICAgICBsZXQgc2xpY2VzID0gYnlDbGFzcy5nZXQobGFiZWwpO1xuICAgICAgaWYgKCFzbGljZXMpIGJ5Q2xhc3Muc2V0KGxhYmVsLCAoc2xpY2VzID0gbmV3IE1hcCgpKSk7XG4gICAgICBsZXQgc2xpY2UgPSBzbGljZXMuZ2V0KHopO1xuICAgICAgaWYgKCFzbGljZSkgc2xpY2VzLnNldCh6LCAoc2xpY2UgPSB7IHJpbmdzOiBbXSwgcmluZ0dyb3VwczogW10sIGxpbmVzOiBbXSB9KSk7XG4gICAgICByZXR1cm4gc2xpY2U7XG4gICAgfTtcbiAgICBjb25zdCBuZXh0UGFydCA9IGZlYXR1cmVJZHMoKTtcbiAgICBmb3IgKGNvbnN0IHMgb2YgYXdhaXQgdGhpcy5zb3VyY2VPdXRsaW5lcyhudWxsLCBsZXZlbCkpIHtcbiAgICAgIGNvbnN0IGlkID0gbmV4dFBhcnQoKTtcbiAgICAgIHMucmluZ3MuZm9yRWFjaCgociwgaSkgPT4ge1xuICAgICAgICBjb25zdCBsYWJlbCA9IHMucmluZ0xhYmVscz8uW2ldO1xuICAgICAgICBpZiAoIWxhYmVsKSByZXR1cm47XG4gICAgICAgIGNvbnN0IHNsaWNlID0gc2xvdChsYWJlbCwgcy56KTtcbiAgICAgICAgc2xpY2UucmluZ3MucHVzaChyKTtcbiAgICAgICAgc2xpY2UucmluZ0dyb3Vwcy5wdXNoKGlkKHMucmluZ0dyb3Vwcz8uW2ldKSk7XG4gICAgICB9KTtcbiAgICAgIChzLmxpbmVzID8/IFtdKS5mb3JFYWNoKChsLCBpKSA9PiB7XG4gICAgICAgIGNvbnN0IGxhYmVsID0gcy5saW5lTGFiZWxzPy5baV07XG4gICAgICAgIGlmIChsYWJlbCkgc2xvdChsYWJlbCwgcy56KS5saW5lcy5wdXNoKGwpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIGZvciAoY29uc3QgeyBsYWJlbCwgb3V0bGluZXMgfSBvZiB0aGlzLmxhYmVsbGVkUmVnaW9uT3V0bGluZXMobnVsbCkpIHtcbiAgICAgIC8vIEEgcmVnaW9uIGlzIG9uZSBmZWF0dXJlLlxuICAgICAgY29uc3QgaWQgPSBuZXh0UGFydCgpKHVuZGVmaW5lZCk7XG4gICAgICBjb25zdCBzbGljZSA9IHNsb3QobGFiZWwsIG91dGxpbmVzLnopO1xuICAgICAgc2xpY2UucmluZ3MucHVzaCguLi5vdXRsaW5lcy5yaW5ncyk7XG4gICAgICBzbGljZS5yaW5nR3JvdXBzLnB1c2goLi4ub3V0bGluZXMucmluZ3MubWFwKCgpID0+IGlkKSk7XG4gICAgICBzbGljZS5saW5lcy5wdXNoKC4uLihvdXRsaW5lcy5saW5lcyA/PyBbXSkpO1xuICAgIH1cbiAgICByZXR1cm4gbmV3IE1hcChcbiAgICAgIEFycmF5LmZyb20oYnlDbGFzcywgKFtsYWJlbCwgc2xpY2VzXSkgPT4gW2xhYmVsLCBBcnJheS5mcm9tKHNsaWNlcywgKFt6LCBzXSkgPT4gc2xpY2VPdXRsaW5lcyh6LCBzKSldKSxcbiAgICApO1xuICB9XG5cbiAgLyoqIFRoZSBkcmF3biBhbmQgdGFrZW4gcmVnaW9ucycgb3V0bGluZXMgb2YgdGhlc2UgY2xhc3NlcywgYnkgc2xpY2UuICovXG4gIHByaXZhdGUgcmVnaW9uT3V0bGluZXMoY2xhc3NlczogcmVhZG9ubHkgc3RyaW5nW10pOiBTbGljZU91dGxpbmVzW10ge1xuICAgIHJldHVybiB0aGlzLmxhYmVsbGVkUmVnaW9uT3V0bGluZXMobmV3IFNldChjbGFzc2VzKSkubWFwKChvKSA9PiBvLm91dGxpbmVzKTtcbiAgfVxuXG4gIC8qKiBFYWNoIGRyYXduIG9yIHRha2VuIHJlZ2lvbidzIG91dGxpbmVzIChvZiB0aGUgYHdhbnRlZGAgY2xhc3NlczsgbnVsbDogZXZlcnkgY2xhc3MpIHdpdGggaXRzIGNsYXNzLiAqL1xuICBwcml2YXRlIGxhYmVsbGVkUmVnaW9uT3V0bGluZXMoXG4gICAgd2FudGVkOiBSZWFkb25seVNldDxzdHJpbmc+IHwgbnVsbCxcbiAgKTogQXJyYXk8eyBsYWJlbDogc3RyaW5nOyBvdXRsaW5lczogU2xpY2VPdXRsaW5lcyB9PiB7XG4gICAgY29uc3Qgb3V0OiBBcnJheTx7IGxhYmVsOiBzdHJpbmc7IG91dGxpbmVzOiBTbGljZU91dGxpbmVzIH0+ID0gW107XG4gICAgZm9yIChjb25zdCByIG9mIHRoaXMuc2NvcGUuc3RhY2tNb2RlID8gdGhpcy5nZXRTbGljZVJlZ2lvbnMoKSA6IHRoaXMucmVnaW9ucykge1xuICAgICAgaWYgKHIuaXNQcm9maWxlPy4oKSB8fCAhci5sYWJlbCB8fCAod2FudGVkICYmICF3YW50ZWQuaGFzKHIubGFiZWwpKSkgY29udGludWU7XG4gICAgICBjb25zdCByaW5nczogRmxvYXQ2NEFycmF5W10gPSBbXTtcbiAgICAgIGZvciAoY29uc3QgcCBvZiByZWdpb25Qb2x5Z29ucyhyKSkge1xuICAgICAgICByaW5ncy5wdXNoKEZsb2F0NjRBcnJheS5mcm9tKHAueHBvaW50cy5mbGF0TWFwKCh4LCBpKSA9PiBbeCwgcC55cG9pbnRzW2ldXSkpKTtcbiAgICAgICAgZm9yIChjb25zdCBob2xlIG9mIHAuaG9sZXMgPz8gW10pIHJpbmdzLnB1c2goRmxvYXQ2NEFycmF5LmZyb20oaG9sZS5mbGF0KCkpKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGxpbmVzID0gcmVnaW9uUG9seWxpbmVzKHIpO1xuICAgICAgb3V0LnB1c2goeyBsYWJlbDogci5sYWJlbCwgb3V0bGluZXM6IHsgejogci56ID8/IDAsIHJpbmdzLCAuLi4obGluZXMubGVuZ3RoID8geyBsaW5lcyB9IDoge30pIH0gfSk7XG4gICAgfVxuICAgIHJldHVybiBvdXQ7XG4gIH1cblxuICAvKiogV2hhdCB0aGUgcmVnaW9uIHNvdXJjZXMgb2YgdGhlIGltYWdlIGhvbGQgKHNlZSB7QGxpbmsgc291cmNlU3RhdGVLZXl9KTogaXQgY2hhbmdlcyB3aGVuIGFcbiAgICogIGZlYXR1cmUgaXMgdGFrZW4gb3IgZGVsZXRlZCwgb3IgdGhhdCBpcyB1bmRvbmUuICovXG4gIGdldFNvdXJjZVN0YXRlS2V5KCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuc291cmNlU3RhdGVLZXkoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBXaGF0IHRoZSByZWdpb24gc291cmNlcyBvZiB0aGUgaW1hZ2UgaG9sZDogdGhlIGltYWdlLCBpdHMgc291cmNlcyAob25lIGF0dGFjaGVkIG9yIGRyb3BwZWRcbiAgICogYnVtcHMgdGhlIHZlcnNpb24pIGFuZCB0aGUgZmVhdHVyZXMgdGFrZW4gZnJvbSB0aGVtLiBBIGtleSBmb3Igd2hhdCBpcyByZWFkIGZyb20gdGhlbS5cbiAgICovXG4gIHByaXZhdGUgc291cmNlU3RhdGVLZXkoKTogc3RyaW5nIHtcbiAgICBjb25zdCBpbWFnZSA9IHRoaXMuc2NvcGUuYWN0aXZlSW1hZ2U7XG4gICAgbGV0IHRha2VuID0gMjE2NjEzNjI2MTtcbiAgICBmb3IgKGNvbnN0IHogb2YgdGhpcy5zb3VyY2VzLnNsaWNlc1dpdGhUYWtlbihpbWFnZSkpIHtcbiAgICAgIGZvciAoY29uc3QgaWQgb2YgWy4uLnRoaXMuc291cmNlcy50YWtlbihpbWFnZSwgeildLnNvcnQoKSkge1xuICAgICAgICBjb25zdCBzID0gYCR7en06JHtpZH07YDtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzLmxlbmd0aDsgaSsrKSB0YWtlbiA9IE1hdGguaW11bCh0YWtlbiBeIHMuY2hhckNvZGVBdChpKSwgMTY3Nzc2MTkpID4+PiAwO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYCR7aW1hZ2V9XFxuJHt0aGlzLnNvdXJjZXNWZXJzaW9ufVxcbiR7dGFrZW59YDtcbiAgfVxuXG4gIC8qKiBEZWxldGUgc291cmNlIGZlYXR1cmVzIHdpdGhvdXQgdGFraW5nIHRoZW0gKG9uZSB1bmRvIHN0ZXApLiAqL1xuICBkZWxldGVTb3VyY2VGZWF0dXJlcyhpZHM6IHJlYWRvbmx5IHN0cmluZ1tdKTogdm9pZCB7XG4gICAgY29uc3QgdGFrZW4gPSB0aGlzLmN1cnJlbnRUYWtlbigpO1xuICAgIGNvbnN0IGRyb3AgPSBpZHMuZmlsdGVyKChpZCkgPT4gIXRha2VuLmhhcyhpZCkpO1xuICAgIGlmICghZHJvcC5sZW5ndGggfHwgIXRoaXMuc291cmNlVmlldyQudmFsdWUpIHJldHVybjtcbiAgICB0aGlzLnJlY29yZFVuZG9TbmFwc2hvdCgpO1xuICAgIHRoaXMuc2V0VGFrZW4obmV3IFNldChbLi4udGFrZW4sIC4uLmRyb3BdKSk7XG4gICAgdGhpcy5lbWl0KCk7XG4gIH1cblxuICAvKipcbiAgICogQSBwYWdlIG9mIHRoZSBzbGljZSBzb3VyY2UncyBmZWF0dXJlcyBub3QgdGFrZW4gZnJvbSBpdCAoZmlsZSBvcmRlciksIGUuZy4gZm9yIHRoZSBSZWdpb25cbiAgICogRWRpdG9yJ3MgbGlzdDsgYW4gZW1wdHkgcGFnZSB3aXRob3V0IGEgc291cmNlLlxuICAgKi9cbiAgYXN5bmMgZ2V0UmVnaW9uU291cmNlSW5kZXgocXVlcnk6IE9taXQ8UmVnaW9uSW5kZXhRdWVyeSwgJ2V4Y2x1ZGUnPik6IFByb21pc2U8UmVnaW9uSW5kZXhQYWdlPiB7XG4gICAgY29uc3QgdmlldyA9IHRoaXMuc291cmNlVmlldyQudmFsdWU7XG4gICAgaWYgKCF2aWV3KSByZXR1cm4geyB0b3RhbDogMCwgcm93czogW10gfTtcbiAgICByZXR1cm4gdmlldy5zb3VyY2UuZ2V0SW5kZXgodmlldy5wbGFuZSwgeyAuLi5xdWVyeSwgZXhjbHVkZTogQXJyYXkuZnJvbSh2aWV3LnRha2VuKSB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBgcmVnaW9uc2AgYXMgYSBHZW9KU09OIEZlYXR1cmVDb2xsZWN0aW9uIHN0cmluZyBtZXJnZWQgd2l0aCB0aGUgcmVnaW9uIHNvdXJjZSBiZWhpbmQgdGhlbTpcbiAgICogdGhlIHNvdXJjZSdzIGZlYXR1cmVzIHRoYXQgd2VyZSBub3QgdGFrZW4gKG9yIGRlbGV0ZWQpLCB0aGVuIGByZWdpb25zYC4gV2l0aG91dCBhIHNvdXJjZSxcbiAgICoge0BsaW5rIGdldEdlb0pzb25TdHJpbmd9LiBgc2xpY2VgIG5hbWVzIGEgZm9sZGVyIHN0YWNrJ3Mgc2xpY2UgKGRlZmF1bHQgdGhlIG9uZSBzaG93bik7XG4gICAqIG9uIGEgei1pbmRleGVkIHN0YWNrJ3Mgc291cmNlIChgJ3BsYW5lcydgKSB0aGUgZXhwb3J0IHNwYW5zIGV2ZXJ5IHNsaWNlLlxuICAgKi9cbiAgYXN5bmMgZ2V0R2VvSnNvbldpdGhTb3VyY2UocmVnaW9uczogUmVnaW9uW10sIHNsaWNlID0gdGhpcy5zb3VyY2VTbGljZSk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgaW1hZ2UgPSB0aGlzLnNjb3BlLmFjdGl2ZUltYWdlO1xuICAgIGNvbnN0IHBsYW5lcyA9IHRoaXMuc2NvcGUuc3RhY2tNb2RlICYmIHRoaXMuc291cmNlcy5oYXNQbGFuZXNTb3VyY2UoaW1hZ2UpO1xuICAgIGNvbnN0IGJpbmRpbmcgPSBhd2FpdCB0aGlzLnNvdXJjZXMuYmluZGluZyhpbWFnZSwgc2xpY2UpO1xuICAgIGlmICghYmluZGluZykgcmV0dXJuIHJlZ2lvbnNUb0dlb0pzb24ocmVnaW9ucyk7XG4gICAgY29uc3QgZmVhdHVyZXMgPSByZWdpb25zXG4gICAgICAuZmlsdGVyKChyKSA9PiAhci5pc1Byb2ZpbGU/LigpKVxuICAgICAgLm1hcCgocikgPT4gZmVhdHVyZUZyb21SZWdpb24ocikpXG4gICAgICAuZmlsdGVyKChmKTogZiBpcyBvYmplY3QgPT4gISFmKTtcbiAgICBjb25zdCBleGNsdWRlID0gcGxhbmVzID8gdGhpcy5zb3VyY2VzLmFsbFRha2VuKGltYWdlKSA6IEFycmF5LmZyb20odGhpcy5zb3VyY2VzLnRha2VuKGltYWdlLCBzbGljZSkpO1xuICAgIHJldHVybiBiaW5kaW5nLnNvdXJjZS5leHBvcnRHZW9Kc29uKGV4Y2x1ZGUsIGZlYXR1cmVzKTtcbiAgfVxuXG4gIC8vIOKUgOKUgCBSZWdpb24gbG9vayDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICAvKipcbiAgICogV2hldGhlciBhIHJlZ2lvbiBvZiBjbGFzcyBgbGFiZWxgIGdvZXMgdW5sYWJlbGxlZCBiZWNhdXNlIGEgc3ViY2xhc3Mgb2YgaXQgKGJ5IHRoZSByZWdpb25cbiAgICogc291cmNlJ3MgY2xhc3MgaGllcmFyY2h5KSBpcyBhbW9uZyB0aGUgcmVnaW9ucyB0b28g4oCUIGFuIGF0bGFzJ3MgXCJJc29jb3J0ZXhcIiB1bmRlciBpdHMgYXJlYXMuXG4gICAqIEZhbHNlIHdpdGhvdXQgYSBoaWVyYXJjaHkuXG4gICAqL1xuICBpc0xhYmVsQ292ZXJlZChsYWJlbDogc3RyaW5nIHwgdW5kZWZpbmVkKTogYm9vbGVhbiB7XG4gICAgaWYgKCFsYWJlbCkgcmV0dXJuIGZhbHNlO1xuICAgIGNvbnN0IGhpZXJhcmNoeSA9IHRoaXMuc291cmNlVmlldyQudmFsdWU/LnNvdXJjZS5pbmZvLmhpZXJhcmNoeTtcbiAgICBpZiAoIWhpZXJhcmNoeSkgcmV0dXJuIGZhbHNlO1xuICAgIGlmICh0aGlzLmNvdmVyZWRGb3I/LnJlZ2lvbnMgIT09IHRoaXMucmVnaW9ucyB8fCB0aGlzLmNvdmVyZWRGb3IuaGllcmFyY2h5ICE9PSBoaWVyYXJjaHkpIHtcbiAgICAgIGNvbnN0IHBhcmVudCA9IG5ldyBNYXAoaGllcmFyY2h5LmZpbHRlcigobikgPT4gbi5wYXJlbnQpLm1hcCgobikgPT4gW24ubmFtZSwgbi5wYXJlbnQgYXMgc3RyaW5nXSkpO1xuICAgICAgY29uc3QgY292ZXJlZCA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgICAgZm9yIChjb25zdCByIG9mIHRoaXMucmVnaW9ucykge1xuICAgICAgICBsZXQgcCA9IHIubGFiZWwgPyBwYXJlbnQuZ2V0KHIubGFiZWwpIDogdW5kZWZpbmVkO1xuICAgICAgICB3aGlsZSAocCAmJiAhY292ZXJlZC5oYXMocCkpIHtcbiAgICAgICAgICBjb3ZlcmVkLmFkZChwKTtcbiAgICAgICAgICBwID0gcGFyZW50LmdldChwKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdGhpcy5jb3ZlcmVkRm9yID0geyByZWdpb25zOiB0aGlzLnJlZ2lvbnMsIGhpZXJhcmNoeSwgY292ZXJlZCB9O1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5jb3ZlcmVkRm9yLmNvdmVyZWQuaGFzKGxhYmVsKTtcbiAgfVxuICBwcml2YXRlIGNvdmVyZWRGb3I6IHsgcmVnaW9uczogUmVnaW9uW107IGhpZXJhcmNoeTogcmVhZG9ubHkgb2JqZWN0W107IGNvdmVyZWQ6IFNldDxzdHJpbmc+IH0gfCBudWxsID0gbnVsbDtcblxuICAvKiogVGhlIGNsYXNzZXMgaGlkZGVuIGZyb20gdmlldyAoc2VlIHtAbGluayBzZXRDbGFzc2VzSGlkZGVufSkuICovXG4gIGdldEhpZGRlbkNsYXNzZXMoKTogUmVhZG9ubHlTZXQ8c3RyaW5nPiB7XG4gICAgcmV0dXJuIHRoaXMuaGlkZGVuQ2xhc3NlcyQudmFsdWU7XG4gIH1cblxuICAvKioge0BsaW5rIGdldEhpZGRlbkNsYXNzZXN9IGFuZCBldmVyeSBjaGFuZ2Ugb2YgaXQuICovXG4gIGdldEhpZGRlbkNsYXNzZXMkKCk6IE9ic2VydmFibGU8UmVhZG9ubHlTZXQ8c3RyaW5nPj4ge1xuICAgIHJldHVybiB0aGlzLmhpZGRlbkNsYXNzZXMkLmFzT2JzZXJ2YWJsZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEhpZGUgKG9yIHNob3cgYWdhaW4pIHRoZXNlIGNsYXNzZXMnIHJlZ2lvbnM6IHRoZSBvdmVybGF5cyBhbmQgdGhlIHJlZ2lvbiBzb3VyY2UncyBsYXllciBzdG9wXG4gICAqIGRyYXdpbmcgdGhlbSwgYW5kIGEgaGlkZGVuIHJlZ2lvbiBjYW4gYmUgbmVpdGhlciBwaWNrZWQgbm9yIGtlcHQgc2VsZWN0ZWQuIFRoZSByZWdpb25zIHN0YXkgaW5cbiAgICogdGhlIHNldCAodGhlIHRhYmxlIGxpc3RzIHRoZW07IGEgc2F2ZSBrZWVwcyB0aGVtKS5cbiAgICovXG4gIHNldENsYXNzZXNIaWRkZW4oY2xhc3NlczogcmVhZG9ubHkgc3RyaW5nW10sIGhpZGRlbjogYm9vbGVhbik6IHZvaWQge1xuICAgIGNvbnN0IGN1ciA9IHRoaXMuaGlkZGVuQ2xhc3NlcyQudmFsdWU7XG4gICAgY29uc3QgbmV4dCA9IG5ldyBTZXQoY3VyKTtcbiAgICBmb3IgKGNvbnN0IGMgb2YgY2xhc3Nlcykge1xuICAgICAgaWYgKGhpZGRlbikgbmV4dC5hZGQoYyk7XG4gICAgICBlbHNlIG5leHQuZGVsZXRlKGMpO1xuICAgIH1cbiAgICBpZiAobmV4dC5zaXplID09PSBjdXIuc2l6ZSAmJiBbLi4ubmV4dF0uZXZlcnkoKGMpID0+IGN1ci5oYXMoYykpKSByZXR1cm47XG4gICAgY29uc3Qgc2V0ID0gdGhpcy5zdG9yZS5nZXRQcmVzZXRTZXQoKTtcbiAgICB0aGlzLmhpZGRlbktleXMgPSBuZXcgU2V0KFsuLi5uZXh0XS5tYXAoKGMpID0+IHByZXNldEtleShzZXQsIGMpKSk7XG4gICAgdGhpcy5oaWRkZW5DbGFzc2VzJC5uZXh0KG5leHQpO1xuICAgIGlmIChoaWRkZW4pIHtcbiAgICAgIGNvbnN0IHNob3duID0gdGhpcy5zZWxlY3Rpb24uaW5kaWNlcy5maWx0ZXIoKGkpID0+ICF0aGlzLmlzQ2xhc3NIaWRkZW4odGhpcy5yZWdpb25zW2ldPy5sYWJlbCkpO1xuICAgICAgaWYgKHNob3duLmxlbmd0aCAhPT0gdGhpcy5zZWxlY3Rpb24uaW5kaWNlcy5sZW5ndGgpIHRoaXMuc2V0U2VsZWN0ZWRTaGFwZUluZGljZXMoc2hvd24pO1xuICAgIH1cbiAgICB0aGlzLnJlcHVibGlzaFZpZXcoKTtcbiAgICB0aGlzLnJlZ2lvblVwZGF0ZSQubmV4dCh0aGlzLmdldFJlZ2lvbnMoKSk7XG4gIH1cblxuICAvKiogV2hldGhlciByZWdpb25zIGxhYmVsbGVkIGBsYWJlbGAgYXJlIGhpZGRlbiAoYW4gdW5sYWJlbGxlZCByZWdpb24gbmV2ZXIgaXMpLiAqL1xuICBpc0NsYXNzSGlkZGVuKGxhYmVsOiBzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICEhbGFiZWwgJiYgdGhpcy5oaWRkZW5LZXlzLnNpemUgPiAwICYmIHRoaXMuaGlkZGVuS2V5cy5oYXMocHJlc2V0S2V5KHRoaXMuc3RvcmUuZ2V0UHJlc2V0U2V0KCksIGxhYmVsKSk7XG4gIH1cblxuICAvKiogVGhlIHJlZ2lvbiBsb29rOiBvdXRsaW5lcywgb3IgZmlsbGVkIChhbiBhdGxhcydzIGxvb2spOyBzZWUgYHJlZ2lvbi1zdHlsZWAuICovXG4gIGdldFJlZ2lvblN0eWxlKCk6IFJlZ2lvblN0eWxlIHtcbiAgICByZXR1cm4gdGhpcy5yZWdpb25TdHlsZSQudmFsdWU7XG4gIH1cblxuICAvKioge0BsaW5rIGdldFJlZ2lvblN0eWxlfSBhbmQgZXZlcnkgY2hhbmdlIG9mIGl0LiAqL1xuICBnZXRSZWdpb25TdHlsZSQoKTogT2JzZXJ2YWJsZTxSZWdpb25TdHlsZT4ge1xuICAgIHJldHVybiB0aGlzLnJlZ2lvblN0eWxlJC5hc09ic2VydmFibGUoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaG9vc2UgdGhlIHJlZ2lvbiBsb29rLCBmaWVsZCBieSBmaWVsZDsgaXQgb3ZlcnJpZGVzIGEgcmVnaW9uIHNvdXJjZSdzIGhpbnQgZm9yIHRoZSBzZXNzaW9uLlxuICAgKiBUaGUgb3ZlcmxheXMgcmVkcmF3LlxuICAgKi9cbiAgc2V0UmVnaW9uU3R5bGUocGF0Y2g6IFBhcnRpYWw8UmVnaW9uU3R5bGU+KTogdm9pZCB7XG4gICAgdGhpcy51c2VyU3R5bGUgPSB7IC4uLnRoaXMudXNlclN0eWxlLCAuLi5wYXRjaCB9O1xuICAgIHRoaXMucmVzdHlsZSgpO1xuICB9XG5cbiAgLyoqIFRoZSBsb29rIG5vdzogdGhlIHVzZXIncyBjaG9pY2UsIGVsc2UgdGhlIHNvdXJjZSdzIGhpbnQsIGVsc2Ugb3V0bGluZXMuICovXG4gIHByaXZhdGUgZWZmZWN0aXZlU3R5bGUoKTogUmVnaW9uU3R5bGUge1xuICAgIGNvbnN0IGhpbnQgPSB0aGlzLmhpbnRTdHlsZSA/PyB7fTtcbiAgICByZXR1cm4ge1xuICAgICAgZmlsbE9wYWNpdHk6IHRoaXMudXNlclN0eWxlLmZpbGxPcGFjaXR5ID8/IGhpbnQuZmlsbE9wYWNpdHkgPz8gREVGQVVMVF9SRUdJT05fU1RZTEUuZmlsbE9wYWNpdHksXG4gICAgICBzdHJva2U6IHRoaXMudXNlclN0eWxlLnN0cm9rZSAhPT0gdW5kZWZpbmVkID8gdGhpcy51c2VyU3R5bGUuc3Ryb2tlIDogKGhpbnQuc3Ryb2tlID8/IG51bGwpLFxuICAgICAgc3Ryb2tlV2lkdGg6XG4gICAgICAgIHRoaXMudXNlclN0eWxlLnN0cm9rZVdpZHRoICE9PSB1bmRlZmluZWQgPyB0aGlzLnVzZXJTdHlsZS5zdHJva2VXaWR0aCA6IChoaW50LnN0cm9rZVdpZHRoID8/IG51bGwpLFxuICAgICAgaGlnaGxpZ2h0OiB0aGlzLnVzZXJTdHlsZS5oaWdobGlnaHQgIT09IHVuZGVmaW5lZCA/IHRoaXMudXNlclN0eWxlLmhpZ2hsaWdodCA6IChoaW50LmhpZ2hsaWdodCA/PyBudWxsKSxcbiAgICB9O1xuICB9XG5cbiAgLyoqIFB1Ymxpc2ggdGhlIGxvb2sgd2hlbiBpdCBjaGFuZ2VkOiB0aGUgb3ZlcmxheXMgcmVkcmF3IHRoZSByZWdpb25zLCB0aGUgc291cmNlIGxheWVyIGl0cyBmZWF0dXJlcy4gKi9cbiAgcHJpdmF0ZSByZXN0eWxlKHJlZHJhdyA9IGZhbHNlKTogdm9pZCB7XG4gICAgY29uc3QgbmV4dCA9IHRoaXMuZWZmZWN0aXZlU3R5bGUoKTtcbiAgICBjb25zdCBjdXIgPSB0aGlzLnJlZ2lvblN0eWxlJC52YWx1ZTtcbiAgICBjb25zdCBzYW1lID0gKE9iamVjdC5rZXlzKG5leHQpIGFzIEFycmF5PGtleW9mIFJlZ2lvblN0eWxlPikuZXZlcnkoKGspID0+IG5leHRba10gPT09IGN1cltrXSk7XG4gICAgaWYgKCFzYW1lKSB0aGlzLnJlZ2lvblN0eWxlJC5uZXh0KG5leHQpO1xuICAgIGNvbnN0IHZpZXcgPSB0aGlzLnNvdXJjZVZpZXckLnZhbHVlO1xuICAgIGlmIChyZWRyYXcgfHwgIXNhbWUgfHwgKHZpZXcgJiYgdmlldy5sYWJlbHMgIT09IHRoaXMuc2hvd1NoYXBlTGFiZWwpKSB7XG4gICAgICB0aGlzLnJlcHVibGlzaFZpZXcoKTtcbiAgICAgIHRoaXMucmVnaW9uVXBkYXRlJC5uZXh0KHRoaXMuZ2V0UmVnaW9ucygpKTtcbiAgICB9XG4gIH1cblxuICAvKiogUmUtZW1pdCB0aGUgc291cmNlIHZpZXcgd2l0aCB0aGUgY3VycmVudCBsb29rIGFuZCBsYWJlbCBzZXR0aW5nLiAqL1xuICBwcml2YXRlIHJlcHVibGlzaFZpZXcoKTogdm9pZCB7XG4gICAgY29uc3QgdmlldyA9IHRoaXMuc291cmNlVmlldyQudmFsdWU7XG4gICAgaWYgKHZpZXcpIHRoaXMuc291cmNlVmlldyQubmV4dCh7IC4uLnZpZXcsIHN0eWxlOiB0aGlzLnJlZ2lvblN0eWxlJC52YWx1ZSwgbGFiZWxzOiB0aGlzLnNob3dTaGFwZUxhYmVsIH0pO1xuICB9XG5cbiAgLyoqIFRoZSBzbGljZSBhIHJlZ2lvbiBzb3VyY2UgaXMga2V5ZWQgYnk6IHRoZSBkaXNwbGF5IHNsaWNlIGluIHN0YWNrIG1vZGUsIGVsc2UgMC4gKi9cbiAgcHJpdmF0ZSBnZXQgc291cmNlU2xpY2UoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5zY29wZS5zdGFja01vZGUgPyB0aGlzLnNjb3BlLmRpc3BsYXlTbGljZSA6IDA7XG4gIH1cblxuICBwcml2YXRlIGN1cnJlbnRUYWtlbigpOiBSZWFkb25seVNldDxzdHJpbmc+IHtcbiAgICByZXR1cm4gdGhpcy5zb3VyY2VzLnRha2VuKHRoaXMuc2NvcGUuYWN0aXZlSW1hZ2UsIHRoaXMuc291cmNlU2xpY2UpO1xuICB9XG5cbiAgLyoqIFJlcGxhY2UgdGhlIHNsaWNlJ3MgdGFrZW4gaWRzIGFuZCB0ZWxsIHRoZSBzb3VyY2UgbGF5ZXJzLiAqL1xuICBwcml2YXRlIHNldFRha2VuKHRha2VuOiBSZWFkb25seVNldDxzdHJpbmc+KTogdm9pZCB7XG4gICAgaWYgKHRha2VuID09PSB0aGlzLmN1cnJlbnRUYWtlbigpKSByZXR1cm47XG4gICAgdGhpcy5zb3VyY2VzLnNldFRha2VuKHRoaXMuc2NvcGUuYWN0aXZlSW1hZ2UsIHRoaXMuc291cmNlU2xpY2UsIHRha2VuKTtcbiAgICBjb25zdCB2aWV3ID0gdGhpcy5zb3VyY2VWaWV3JC52YWx1ZTtcbiAgICBpZiAodmlldykgdGhpcy5zb3VyY2VWaWV3JC5uZXh0KHsgLi4udmlldywgdGFrZW4gfSk7XG4gIH1cblxuICAvKipcbiAgICogTG9vayB1cCAob3BlbmluZyBpdCBpZiBuZWVkZWQpIHRoZSBzbGljZSdzIHNvdXJjZSBhbmQgcHVibGlzaCBpdCBhcyB0aGUgc291cmNlIHZpZXcuIFRoZSB2aWV3XG4gICAqIGlzIHdpdGhkcmF3biBhdCBvbmNlOiB1bnRpbCB0aGUgaW5jb21pbmcgc291cmNlIG9wZW5zLCBub3RoaW5nIHJlYWRzLCB0YWtlcyBvciBkZWxldGVzIGZyb20gdGhlXG4gICAqIG91dGdvaW5nIG9uZSBpbnRvIHRoZSBzbGljZSBub3cgc2hvd24uXG4gICAqL1xuICBwcml2YXRlIHJlZnJlc2hTb3VyY2VWaWV3KCk6IHZvaWQge1xuICAgIGNvbnN0IGdlbmVyYXRpb24gPSArK3RoaXMuc291cmNlR2VuZXJhdGlvbjtcbiAgICBjb25zdCBpbWFnZSA9IHRoaXMuc2NvcGUuYWN0aXZlSW1hZ2U7XG4gICAgY29uc3Qgc2xpY2UgPSB0aGlzLnNvdXJjZVNsaWNlO1xuICAgIGlmICh0aGlzLnNvdXJjZVZpZXckLnZhbHVlKSB0aGlzLnNvdXJjZVZpZXckLm5leHQobnVsbCk7XG4gICAgdGhpcy5zb3VyY2VzLnNob3coaW1hZ2UsIHNsaWNlKTtcbiAgICBpZiAoIXRoaXMuc291cmNlcy5oYXMoaW1hZ2UsIHNsaWNlKSkge1xuICAgICAgdGhpcy5oaW50U3R5bGUgPSB1bmRlZmluZWQ7XG4gICAgICB0aGlzLnJlc3R5bGUoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5zb3VyY2VzLmJpbmRpbmcoaW1hZ2UsIHNsaWNlKS50aGVuKFxuICAgICAgKGJpbmRpbmcpID0+IHtcbiAgICAgICAgaWYgKGdlbmVyYXRpb24gIT09IHRoaXMuc291cmNlR2VuZXJhdGlvbikgcmV0dXJuO1xuICAgICAgICBpZiAoIWJpbmRpbmcpIHtcbiAgICAgICAgICB0aGlzLnNvdXJjZVZpZXckLm5leHQobnVsbCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGluZm8gPSBiaW5kaW5nLnNvdXJjZS5pbmZvO1xuICAgICAgICBjb25zdCBjbGFzc0NvbG9ycyA9IE9iamVjdC5lbnRyaWVzKGluZm8uY2xhc3NDb2xvcnMpO1xuICAgICAgICBpZiAoY2xhc3NDb2xvcnMubGVuZ3RoKSB0aGlzLnN0b3JlLnJlbWVtYmVySW1wb3J0ZWRDbGFzc0NvbG9ycyhuZXcgTWFwKGNsYXNzQ29sb3JzKSk7XG4gICAgICAgIC8vIEEgc291cmNlIHRoYXQgYXNrcyBmb3IgbGFiZWxzIGdldHMgdGhlbSB3aGVuIGl0IG9wZW5zICh0aGUgdG9nZ2xlIHN0aWxsIHR1cm5zIHRoZW0gb2ZmKS5cbiAgICAgICAgY29uc3QgbGFiZWxzT24gPSAhIWluZm8uc3R5bGU/LmxhYmVscyAmJiAhdGhpcy5zaG93U2hhcGVMYWJlbCAmJiB0aGlzLnNob3duU291cmNlICE9PSBiaW5kaW5nLnNvdXJjZTtcbiAgICAgICAgaWYgKGxhYmVsc09uKSB0aGlzLnNob3dTaGFwZUxhYmVsID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5zaG93blNvdXJjZSA9IGJpbmRpbmcuc291cmNlO1xuICAgICAgICB0aGlzLmhpbnRTdHlsZSA9IGluZm8uc3R5bGU7XG4gICAgICAgIHRoaXMuc291cmNlVmlldyQubmV4dCh7XG4gICAgICAgICAgc291cmNlOiBiaW5kaW5nLnNvdXJjZSxcbiAgICAgICAgICBwbGFuZTogYmluZGluZy5wbGFuZSxcbiAgICAgICAgICB0YWtlbjogdGhpcy5zb3VyY2VzLnRha2VuKGltYWdlLCBzbGljZSksXG4gICAgICAgICAgY29sb3JPZjogKGYpID0+XG4gICAgICAgICAgICBmLmxhYmVsID8gY29sb3JGb3JMYWJlbChmLmxhYmVsLCB0aGlzLnN0b3JlLmdldFByZXNldFNldCgpKSA6IGYuY29sb3IgfHwgdGhpcy5zaGFwZUNvbG9yLFxuICAgICAgICAgIHN0eWxlOiB0aGlzLnJlZ2lvblN0eWxlJC52YWx1ZSxcbiAgICAgICAgICBsYWJlbHM6IHRoaXMuc2hvd1NoYXBlTGFiZWwsXG4gICAgICAgICAgaXNIaWRkZW46IChsYWJlbCkgPT4gdGhpcy5pc0NsYXNzSGlkZGVuKGxhYmVsKSxcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMucmVzdHlsZShsYWJlbHNPbik7XG4gICAgICB9LFxuICAgICAgKGVycikgPT4ge1xuICAgICAgICBpZiAoZ2VuZXJhdGlvbiAhPT0gdGhpcy5zb3VyY2VHZW5lcmF0aW9uKSByZXR1cm47XG4gICAgICAgIGNvbnNvbGUud2FybignW3JlZ2lvbnNdIGNvdWxkIG5vdCBvcGVuIHRoZSByZWdpb24gc291cmNlJywgZXJyKTtcbiAgICAgICAgdGhpcy5zb3VyY2VWaWV3JC5uZXh0KG51bGwpO1xuICAgICAgfSxcbiAgICApO1xuICB9XG5cbiAgLy8g4pSA4pSAIHBlci1pbWFnZSBsaWZlY3ljbGUg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgLyoqXG4gICAqIFN3aXRjaCB0aGUgYWN0aXZlIGltYWdlOiBzbmFwc2hvdCB0aGUgb3V0Z29pbmcgcmVnaW9ucywgcmVzdG9yZSB0aGVcbiAgICogaW5jb21pbmcgaW1hZ2UncyAob3IgW10gaWYgbm9uZSksIGNsZWFyIHNlbGVjdGlvbiwgYW5kIG5vdGlmeS4gSWRlbXBvdGVudFxuICAgKiBmb3IgdGhlIHNhbWUgaW1hZ2UgKHNvIHJlcGVhdGVkIHJlcGxvdHMgb2Ygb25lIGltYWdlIGtlZXAgaXRzIHJlZ2lvbnMpLlxuICAgKi9cbiAgc2V0QWN0aXZlSW1hZ2UoaW1hZ2VJbmZvOiBJSW1hZ2VJbmZvKTogdm9pZCB7XG4gICAgLy8gU3dpdGNoaW5nIGltYWdlcyBhbHNvIGVuZHMgYW55IHBlci1zbGljZSBzdGFjayBzZXNzaW9uIChqaXQtdWkjOTMpLlxuICAgIGNvbnN0IGluY29taW5nID0gdGhpcy5zY29wZS5zd2l0Y2hJbWFnZShSZWdpb25TY29wZUNhY2hlLmltYWdlS2V5KGltYWdlSW5mbyksIHRoaXMucmVnaW9ucyk7XG4gICAgaWYgKCFpbmNvbWluZykgcmV0dXJuO1xuICAgIHRoaXMucmVnaW9ucyA9IGluY29taW5nO1xuICAgIHRoaXMuc2VsZWN0aW9uLnJlcGxhY2UoW10pO1xuICAgIC8vIFVuZG8gbmV2ZXIgY3Jvc3NlcyBhbiBpbWFnZSBzd2l0Y2guXG4gICAgdGhpcy5yZXNldFVuZG9IaXN0b3J5KCk7XG4gICAgdGhpcy5lbWl0U2VsZWN0aW9uKCk7XG4gICAgdGhpcy5yZWdpb25VcGRhdGUkLm5leHQodGhpcy5nZXRSZWdpb25zKCkpO1xuICAgIHRoaXMucmVmcmVzaFNvdXJjZVZpZXcoKTtcbiAgfVxuXG4gIC8vIOKUgOKUgCBpbnRlcm5hbHMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgLyoqIEFwcGx5IHRoZSBwcmVzZXQgc2V0J3MgY2xhc3MgY29sb3VycyAoc2VlIHtAbGluayBhcHBseVByZXNldENvbG9yc30pLFxuICAgKiAgcHJvbW90aW5nIHVua25vd24gY2xhc3NlcyBpbnRvIHRoZSBzaGFyZWQgc3RvcmUgd2hlbiB0aGUgc2V0IGFza3MgZm9yIGl0LiAqL1xuICBwcml2YXRlIHdpdGhDbGFzc2lmaWNhdGlvbkNvbG9ycyhyZWdpb25zOiBSZWdpb25bXSwgaW5QbGFjZTogKHI6IFJlZ2lvbikgPT4gYm9vbGVhbik6IFJlZ2lvbltdIHtcbiAgICByZXR1cm4gYXBwbHlQcmVzZXRDb2xvcnMocmVnaW9ucywgdGhpcy5zdG9yZS5nZXRQcmVzZXRTZXQoKSwge1xuICAgICAgaW5QbGFjZSxcbiAgICAgIG9uUHJvbW90ZTogKHByZXNldCkgPT4gdGhpcy5zdG9yZS51cHNlcnRDbGFzcyhwcmVzZXQpLFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBzeW5jQ2FjaGUoKTogdm9pZCB7XG4gICAgdGhpcy5zY29wZS5zeW5jKHRoaXMucmVnaW9ucyk7XG4gIH1cblxuICBwcml2YXRlIGVtaXQoKTogdm9pZCB7XG4gICAgLy8gTGl2ZS1lZGl0IGxpc3RlbmVycyAoZS5nLiB0aGUgaW50ZW5zaXR5LXByb2ZpbGUgaW5zZXQpIHJlYWN0IG9uIEVWRVJZXG4gICAgLy8gY2hhbmdlIOKAlCBpbmNsdWRpbmcgcGVyLWZyYW1lIGR1cmluZyBhIGJhdGNoZWQgZHJhZyDigJQgc28gdGhleSB0cmFjayB0aGVcbiAgICAvLyByZWdpb24gbGl2ZS4gVGhlIG1haW4gcmVnaW9uVXBkYXRlJCBzdGF5cyBjb2FsZXNjZWQgZHVyaW5nIGEgYmF0Y2ggKGZpcmVzXG4gICAgLy8gb25jZSBvbiBlbmRCYXRjaCkgdG8ga2VlcCBoZWF2aWVyIGNvbnN1bWVycyAoUmVnaW9ucyB0YWIpIGNhbG0uXG4gICAgdGhpcy5yZWdpb25MaXZlRWRpdCQubmV4dCh0aGlzLnJlZ2lvbnMuc2xpY2UoKSk7XG4gICAgaWYgKHRoaXMuYmF0Y2hEZXB0aCA+IDApIHtcbiAgICAgIHRoaXMucGVuZGluZ0VtaXQgPSB0cnVlO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLnJlZ2lvblVwZGF0ZSQubmV4dCh0aGlzLmdldFJlZ2lvbnMoKSk7XG4gIH1cblxuICAvKiogUHJvamVjdCB0aGUgc2VsZWN0ZWQgaWRzIG9udG8gdGhlIGN1cnJlbnQgcmVnaW9ucyAocHJ1bmluZyBnb25lIG9uZXMpO1xuICAgKiAgZW1pdHMgb25seSBpZiB0aGUgaW5kZXggc2V0IGNoYW5nZWQuICovXG4gIHByaXZhdGUgZW1pdFNlbGVjdGlvbigpOiB2b2lkIHtcbiAgICB0aGlzLnNlbGVjdGlvbi5zeW5jKHRoaXMucmVnaW9ucyk7XG4gIH1cblxuICBwcml2YXRlIGZpbmRCeUlkKGlkOiBudW1iZXIpOiBSZWdpb24gfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLnJlZ2lvbnMuZmluZCgocikgPT4gci5pZCA9PT0gaWQpO1xuICB9XG5cbiAgcHJpdmF0ZSBpbmRleE9mSWQoaWQ6IG51bWJlcik6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMucmVnaW9ucy5maW5kSW5kZXgoKHIpID0+IHIuaWQgPT09IGlkKTtcbiAgfVxufVxuIl19
|