@jax-data-science/sci-image-visualizer 0.9.0 → 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.
Files changed (131) hide show
  1. package/esm2022/index.mjs +7 -1
  2. package/esm2022/lib/contracts/image.contract.mjs +1 -1
  3. package/esm2022/lib/contracts/region-editor-api.contract.mjs +1 -1
  4. package/esm2022/lib/contracts/region-store.contract.mjs +1 -1
  5. package/esm2022/lib/contracts/section-view.contract.mjs +2 -0
  6. package/esm2022/lib/contracts/visualizer.contract.mjs +1 -1
  7. package/esm2022/lib/contracts/viz-config.mjs +1 -1
  8. package/esm2022/lib/geometry/loft.mjs +128 -0
  9. package/esm2022/lib/geometry/polylabel.mjs +156 -0
  10. package/esm2022/lib/geometry/reconstruct.mjs +315 -0
  11. package/esm2022/lib/geometry/reslice-image.mjs +57 -0
  12. package/esm2022/lib/geometry/section.mjs +215 -0
  13. package/esm2022/lib/implementations/napari-js/napari-loading-badge.mjs +11 -7
  14. package/esm2022/lib/implementations/napari-js/napari-loading-state.mjs +20 -3
  15. package/esm2022/lib/implementations/napari-js/napari-region-mesh-pointer.mjs +100 -0
  16. package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +28 -5
  17. package/esm2022/lib/implementations/napari-js/napari-scene.mjs +1 -1
  18. package/esm2022/lib/implementations/napari-js/napari-spatial-hover.mjs +9 -2
  19. package/esm2022/lib/implementations/napari-js/napari-tool-bridge.mjs +5 -2
  20. package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +81 -1
  21. package/esm2022/lib/implementations/napari-js/napari-volume-region-meshes.mjs +129 -0
  22. package/esm2022/lib/implementations/napari-js/napari-volume-scene.mjs +115 -4
  23. package/esm2022/lib/implementations/napari-js/napari-volume-slice-planes.mjs +103 -0
  24. package/esm2022/lib/implementations/napari-js/region-overlay/region-svg-renderer.mjs +15 -3
  25. package/esm2022/lib/implementations/osd/osd-region-overlay-draw.mjs +18 -7
  26. package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +38 -8
  27. package/esm2022/lib/implementations/tile-server/tile-protocol.mjs +1 -1
  28. package/esm2022/lib/models/class-preset.mjs +1 -1
  29. package/esm2022/lib/models/polygon-factory.mjs +17 -1
  30. package/esm2022/lib/models/region-geojson.mjs +44 -6
  31. package/esm2022/lib/models/region.mjs +1 -1
  32. package/esm2022/lib/region-editor/class-tree/class-tree.component.mjs +156 -0
  33. package/esm2022/lib/region-editor/class-tree/class-tree.mjs +108 -0
  34. package/esm2022/lib/region-editor/classes-panel/classes-panel.component.mjs +77 -13
  35. package/esm2022/lib/region-editor/region-editor.component.mjs +527 -42
  36. package/esm2022/lib/region-editor/region-metrics.mjs +20 -2
  37. package/esm2022/lib/region-editor/region-persistence.service.mjs +36 -10
  38. package/esm2022/lib/region-editor/region-table/region-table.component.mjs +24 -8
  39. package/esm2022/lib/region-overlay/region-geometry.mjs +3 -3
  40. package/esm2022/lib/region-overlay/region-source-layer.mjs +378 -0
  41. package/esm2022/lib/region-overlay/region-style.mjs +97 -0
  42. package/esm2022/lib/region-source/http-region-source.mjs +104 -0
  43. package/esm2022/lib/region-source/region-source-ops.mjs +53 -0
  44. package/esm2022/lib/region-source/region-source-worker.mjs +10 -0
  45. package/esm2022/lib/region-source/region-source.mjs +67 -0
  46. package/esm2022/lib/region-source/region-tiles.mjs +708 -0
  47. package/esm2022/lib/region-source/worker-region-source.mjs +229 -0
  48. package/esm2022/lib/routing-visualizer.service.mjs +418 -22
  49. package/esm2022/lib/section-pane/section-pane.component.mjs +299 -0
  50. package/esm2022/lib/store/class-color.util.mjs +10 -5
  51. package/esm2022/lib/store/class-signatures.mjs +63 -0
  52. package/esm2022/lib/store/region-scope-cache.mjs +5 -1
  53. package/esm2022/lib/store/region-source-scope.mjs +171 -0
  54. package/esm2022/lib/store/region-store.service.mjs +724 -12
  55. package/esm2022/lib/store/visualizer-store.service.mjs +33 -6
  56. package/esm2022/lib/toolbar/region-tools/region-tools.component.mjs +8 -2
  57. package/esm2022/lib/toolbar/stack-controls/stack-controls.component.mjs +55 -15
  58. package/esm2022/lib/toolbar/toolbar.component.mjs +19 -5
  59. package/esm2022/lib/visualizer/region-load.mjs +67 -4
  60. package/esm2022/lib/visualizer/volume-sections.mjs +175 -0
  61. package/esm2022/lib/visualizer.component.mjs +128 -6
  62. package/fesm2022/{jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-Csxlnq7I.mjs → jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-BKQhpbHv.mjs} +7239 -1153
  63. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-BKQhpbHv.mjs.map +1 -0
  64. package/fesm2022/{jax-data-science-sci-image-visualizer-onnx-sam-session-Bkujqg7m.mjs → jax-data-science-sci-image-visualizer-onnx-sam-session-z1IN-F7w.mjs} +4 -4
  65. package/fesm2022/{jax-data-science-sci-image-visualizer-onnx-sam-session-Bkujqg7m.mjs.map → jax-data-science-sci-image-visualizer-onnx-sam-session-z1IN-F7w.mjs.map} +1 -1
  66. package/fesm2022/jax-data-science-sci-image-visualizer-region-source-worker-CAqBjM5L.mjs +12 -0
  67. package/fesm2022/jax-data-science-sci-image-visualizer-region-source-worker-CAqBjM5L.mjs.map +1 -0
  68. package/fesm2022/jax-data-science-sci-image-visualizer.mjs +3 -3
  69. package/fesm2022/region-source.worker.js +1067 -0
  70. package/index.d.ts +6 -0
  71. package/lib/contracts/image.contract.d.ts +4 -0
  72. package/lib/contracts/region-editor-api.contract.d.ts +84 -0
  73. package/lib/contracts/region-store.contract.d.ts +22 -0
  74. package/lib/contracts/section-view.contract.d.ts +44 -0
  75. package/lib/contracts/visualizer.contract.d.ts +10 -0
  76. package/lib/contracts/viz-config.d.ts +8 -0
  77. package/lib/geometry/loft.d.ts +22 -0
  78. package/lib/geometry/polylabel.d.ts +23 -0
  79. package/lib/geometry/reconstruct.d.ts +54 -0
  80. package/lib/geometry/reslice-image.d.ts +33 -0
  81. package/lib/geometry/section.d.ts +52 -0
  82. package/lib/implementations/napari-js/napari-loading-badge.d.ts +4 -2
  83. package/lib/implementations/napari-js/napari-loading-state.d.ts +8 -1
  84. package/lib/implementations/napari-js/napari-region-mesh-pointer.d.ts +32 -0
  85. package/lib/implementations/napari-js/napari-region-overlay.d.ts +6 -1
  86. package/lib/implementations/napari-js/napari-scene.d.ts +33 -0
  87. package/lib/implementations/napari-js/napari-spatial-hover.d.ts +3 -1
  88. package/lib/implementations/napari-js/napari-visualizer.service.d.ts +48 -0
  89. package/lib/implementations/napari-js/napari-volume-region-meshes.d.ts +66 -0
  90. package/lib/implementations/napari-js/napari-volume-scene.d.ts +45 -1
  91. package/lib/implementations/napari-js/napari-volume-slice-planes.d.ts +43 -0
  92. package/lib/implementations/osd/osd-region-overlay-draw.d.ts +4 -3
  93. package/lib/implementations/osd/osd-region-overlay.d.ts +10 -3
  94. package/lib/implementations/tile-server/tile-protocol.d.ts +3 -0
  95. package/lib/models/class-preset.d.ts +7 -0
  96. package/lib/models/polygon-factory.d.ts +5 -0
  97. package/lib/models/region-geojson.d.ts +40 -0
  98. package/lib/models/region.d.ts +19 -0
  99. package/lib/region-editor/class-tree/class-tree.component.d.ts +78 -0
  100. package/lib/region-editor/class-tree/class-tree.d.ts +31 -0
  101. package/lib/region-editor/classes-panel/classes-panel.component.d.ts +36 -6
  102. package/lib/region-editor/region-editor.component.d.ts +133 -17
  103. package/lib/region-editor/region-metrics.d.ts +8 -0
  104. package/lib/region-editor/region-persistence.service.d.ts +12 -4
  105. package/lib/region-editor/region-table/region-table.component.d.ts +10 -4
  106. package/lib/region-overlay/region-geometry.d.ts +4 -3
  107. package/lib/region-overlay/region-source-layer.d.ts +96 -0
  108. package/lib/region-overlay/region-style.d.ts +52 -0
  109. package/lib/region-source/http-region-source.d.ts +45 -0
  110. package/lib/region-source/region-source-ops.d.ts +89 -0
  111. package/lib/region-source/region-source-worker.d.ts +7 -0
  112. package/lib/region-source/region-source.d.ts +82 -0
  113. package/lib/region-source/region-tiles.d.ts +289 -0
  114. package/lib/region-source/worker-region-source.d.ts +65 -0
  115. package/lib/routing-visualizer.service.d.ts +138 -1
  116. package/lib/section-pane/section-pane.component.d.ts +47 -0
  117. package/lib/store/class-color.util.d.ts +6 -3
  118. package/lib/store/class-signatures.d.ts +11 -0
  119. package/lib/store/region-scope-cache.d.ts +2 -0
  120. package/lib/store/region-source-scope.d.ts +68 -0
  121. package/lib/store/region-store.service.d.ts +206 -2
  122. package/lib/store/visualizer-store.service.d.ts +10 -0
  123. package/lib/toolbar/region-tools/region-tools.component.d.ts +3 -1
  124. package/lib/toolbar/stack-controls/stack-controls.component.d.ts +20 -9
  125. package/lib/toolbar/toolbar.component.d.ts +9 -2
  126. package/lib/visualizer/region-load.d.ts +23 -4
  127. package/lib/visualizer/volume-sections.d.ts +64 -0
  128. package/lib/visualizer.component.d.ts +31 -0
  129. package/package.json +2 -2
  130. package/src/lib/assets/slice.svg +23 -0
  131. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-Csxlnq7I.mjs.map +0 -1
@@ -1,22 +1,30 @@
1
- import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
1
+ import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, Input, Output, } from '@angular/core';
2
2
  import { CommonModule } from '@angular/common';
3
+ import { FormsModule } from '@angular/forms';
4
+ import { InputTextModule } from 'primeng/inputtext';
3
5
  import { ButtonModule } from 'primeng/button';
4
6
  import { TooltipModule } from 'primeng/tooltip';
5
7
  import { presetKey } from '../../store/class-color.util';
6
8
  import { HexColorPickerComponent } from '../../hex-color-picker/hex-color-picker.component';
9
+ import { scrollToPicked } from '../class-tree/class-tree.component';
7
10
  import * as i0 from "@angular/core";
8
11
  import * as i1 from "@angular/common";
9
- import * as i2 from "primeng/button";
10
- import * as i3 from "primeng/tooltip";
12
+ import * as i2 from "@angular/forms";
13
+ import * as i3 from "primeng/button";
14
+ import * as i4 from "primeng/inputtext";
15
+ import * as i5 from "primeng/tooltip";
11
16
  /**
12
17
  * The Region Editor's docked "Classes" panel (jit-ui#70): every annotation
13
18
  * class with its colour swatch and region count. A row click picks the active
14
19
  * class (and re-classifies a selection), the swatch recolours the class, the
15
- * trash removes it, Manage opens the full editor. Presentational: the editor
16
- * applies every action.
20
+ * trash removes it, Manage opens the full editor; the search box filters the
21
+ * rows by name; the eye hides a class's regions. For a class hierarchy the editor projects a class tree in,
22
+ * shown in place of the list while {@link treeView} is on. Presentational: the
23
+ * editor applies every action.
17
24
  */
18
25
  export class ClassesPanelComponent {
19
- constructor() {
26
+ constructor(el) {
27
+ this.el = el;
20
28
  /** The classes in display order. */
21
29
  this.classes = [];
22
30
  /** Region count per class, keyed by {@link presetKey} under `matchMode`. */
@@ -25,10 +33,28 @@ export class ClassesPanelComponent {
25
33
  this.matchMode = 'exact';
26
34
  /** The active class (highlighted), or null. */
27
35
  this.activeClass = null;
36
+ /** The class picked last (in the class tree, or a surface in 3D): highlighted, scrolled into view. */
37
+ this.picked = null;
38
+ /** Classes with a selected region (marked). */
39
+ this.marked = new Set();
28
40
  /** Number of selected regions (changes what a row click does). */
29
41
  this.selectedCount = 0;
30
42
  /** The class regions revert to; it can't be removed while in use. */
31
43
  this.defaultClassName = 'Region';
44
+ /** Whether a volume view is on screen: each class can then be shown in 3D. */
45
+ this.volume = false;
46
+ /** The classes shown in 3D. */
47
+ this.shown3d = new Set();
48
+ /** The classes hidden from view. */
49
+ this.hidden = new Set();
50
+ /** A class's eye (its name): hide it, or show it again. */
51
+ this.toggleHidden = new EventEmitter();
52
+ /** A class's 3D toggle (its name). */
53
+ this.toggle3d = new EventEmitter();
54
+ /** Whether the projected class tree is shown instead of the list; null: there is no tree. */
55
+ this.treeView = null;
56
+ /** The list / tree switch. */
57
+ this.treeViewChange = new EventEmitter();
32
58
  /** A row was clicked: make the class active / apply it to the selection. */
33
59
  this.pick = new EventEmitter();
34
60
  /** A class's swatch picked a new colour. */
@@ -39,10 +65,14 @@ export class ClassesPanelComponent {
39
65
  this.manage = new EventEmitter();
40
66
  /** trackBy for the class rows so re-sorting doesn't re-create the pickers. */
41
67
  this.trackByName = (_, c) => c.name;
42
- /** The rows drawn, rebuilt when an input changes rather than per check. */
68
+ /** Every class's row, rebuilt when an input changes rather than per check. */
43
69
  this.rows = [];
70
+ /** The rows matching {@link query}. */
71
+ this.shownRows = [];
72
+ /** The search box's text. */
73
+ this.query = '';
44
74
  }
45
- ngOnChanges() {
75
+ ngOnChanges(changes = {}) {
46
76
  this.rows = this.classes.map((c) => ({
47
77
  name: c.name,
48
78
  color: c.color,
@@ -51,6 +81,22 @@ export class ClassesPanelComponent {
51
81
  rowTooltip: this.rowTooltip(c.name),
52
82
  removeTooltip: this.removeTooltip(c.name),
53
83
  }));
84
+ this.filter();
85
+ if (changes['picked'] && this.picked)
86
+ setTimeout(() => scrollToPicked(this.el.nativeElement, '.class-row.picked'));
87
+ }
88
+ onQuery(value) {
89
+ this.query = value;
90
+ this.filter();
91
+ }
92
+ /** Enter in the search box picks the first match. */
93
+ pickFirstMatch() {
94
+ if (this.query.trim() && this.shownRows.length)
95
+ this.pick.emit(this.shownRows[0].name);
96
+ }
97
+ filter() {
98
+ const q = this.query.trim().toLowerCase();
99
+ this.shownRows = q ? this.rows.filter((r) => r.name.toLowerCase().includes(q)) : this.rows;
54
100
  }
55
101
  count(name) {
56
102
  return this.counts.get(presetKey({ matchMode: this.matchMode }, name)) ?? 0;
@@ -69,13 +115,13 @@ export class ClassesPanelComponent {
69
115
  return 'The default class cannot be removed while in use';
70
116
  return inUse ? `Remove class — its regions revert to ${this.defaultClassName}` : 'Remove class';
71
117
  }
72
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: ClassesPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
73
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.9", type: ClassesPanelComponent, isStandalone: true, selector: "region-classes-panel", inputs: { classes: "classes", counts: "counts", matchMode: "matchMode", activeClass: "activeClass", selectedCount: "selectedCount", defaultClassName: "defaultClassName" }, outputs: { pick: "pick", recolor: "recolor", remove: "remove", manage: "manage" }, usesOnChanges: true, ngImport: i0, template: "<!-- Docked \"Classes\" panel (jit-ui#70): the always-visible list of annotation\n classes above the regions table. Click a row to make it the active class\n (new regions inherit it; with rows selected it re-classifies them); recolour\n via the swatch; the badge shows how many regions use the class. \"Manage\"\n opens the full editor (fallback palette, auto-add, matching, import/export). -->\n<div class=\"classes-panel\">\n <div class=\"classes-panel-header\">\n <span class=\"classes-panel-title\">Classes</span>\n <button\n pButton\n type=\"button\"\n icon=\"pi pi-cog\"\n label=\"Manage\"\n class=\"p-button-sm p-button-text\"\n pTooltip=\"Manage classes \u2014 add / remove, palette, matching, import/export\"\n tooltipPosition=\"bottom\"\n (click)=\"manage.emit()\"\n ></button>\n </div>\n <div class=\"classes-panel-body\">\n <div\n *ngFor=\"let c of rows; trackBy: trackByName\"\n class=\"class-row\"\n [class.active]=\"activeClass === c.name\"\n (click)=\"pick.emit(c.name)\"\n [pTooltip]=\"c.rowTooltip\"\n tooltipPosition=\"bottom\"\n >\n <span class=\"row-swatch\" (click)=\"$event.stopPropagation()\">\n <hex-color-picker [color]=\"c.color\" (colorChange)=\"recolor.emit({ name: c.name, color: $event })\">\n </hex-color-picker>\n </span>\n <span class=\"row-name\">{{ c.name }}</span>\n <span class=\"row-count\" [class.zero]=\"c.count === 0\">{{ c.count }}</span>\n <button\n pButton\n type=\"button\"\n icon=\"pi pi-trash\"\n class=\"p-button-sm p-button-text p-button-warning row-del\"\n [disabled]=\"!c.canRemove\"\n [pTooltip]=\"c.removeTooltip\"\n tooltipPosition=\"bottom\"\n [attr.aria-label]=\"'Remove class ' + c.name\"\n (click)=\"$event.stopPropagation(); remove.emit(c.name)\"\n ></button>\n </div>\n <div *ngIf=\"!classes.length\" class=\"classes-empty\">No classes yet \u2014 add one from Manage.</div>\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:block;flex:0 0 auto}.classes-panel{display:flex;flex-direction:column;flex:0 0 auto;border-bottom:1px solid var(--surface-border)}.classes-panel-header{display:flex;align-items:center;gap:.35rem;padding:.35rem .5rem;border-bottom:1px solid var(--surface-border)}.classes-panel-title{font-size:.75rem;font-weight:600;letter-spacing:.03em;text-transform:uppercase;color:var(--text-color-secondary);margin-right:auto}.classes-panel-body{height:7rem;min-height:2.5rem;max-height:60vh;overflow-x:hidden;overflow-y:auto;resize:vertical}::ng-deep region-classes-panel .classes-panel-body .hex-picker-swatch{width:1.25rem;height:1.25rem;border-width:1px}.class-row{display:flex;align-items:center;gap:.5rem;padding:.1rem .5rem;cursor:pointer;border-left:3px solid transparent}.class-row:hover{background:var(--surface-hover, rgba(0, 0, 0, .04))}.class-row.active{background:var(--highlight-bg, rgba(51, 153, 255, .12));border-left-color:var(--primary-color)}.class-row .row-swatch{flex:0 0 auto;display:inline-flex}.class-row .row-name{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.85rem}.class-row.active .row-name{color:var(--primary-color);font-weight:600}.class-row .row-count{flex:0 0 auto;min-width:1.5rem;text-align:center;font-size:.72rem;font-variant-numeric:tabular-nums;color:var(--text-color-secondary);background:var(--surface-200, rgba(0, 0, 0, .06));border-radius:10px;padding:0 .4rem}.class-row .row-count.zero{opacity:.5}.class-row .row-del{flex:0 0 auto}.classes-empty{font-size:.8rem;color:var(--text-color-secondary);padding:.5rem}::ng-deep region-classes-panel .classes-panel-body .class-row .p-button.p-button-icon-only{width:1.75rem;height:1.75rem;padding:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i2.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "label", "icon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i3.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "component", type: HexColorPickerComponent, selector: "hex-color-picker", inputs: ["color"], outputs: ["colorChange", "colorInput"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
118
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: ClassesPanelComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
119
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.9", type: ClassesPanelComponent, isStandalone: true, selector: "region-classes-panel", inputs: { classes: "classes", counts: "counts", matchMode: "matchMode", activeClass: "activeClass", picked: "picked", marked: "marked", selectedCount: "selectedCount", defaultClassName: "defaultClassName", volume: "volume", shown3d: "shown3d", hidden: "hidden", treeView: "treeView" }, outputs: { toggleHidden: "toggleHidden", toggle3d: "toggle3d", treeViewChange: "treeViewChange", pick: "pick", recolor: "recolor", remove: "remove", manage: "manage" }, usesOnChanges: true, ngImport: i0, template: "<!-- Docked \"Classes\" panel (jit-ui#70): the always-visible list of annotation\n classes above the regions table. Click a row to make it the active class\n (new regions inherit it; with rows selected it re-classifies them); recolour\n via the swatch; the badge shows how many regions use the class. \"Manage\"\n opens the full editor (fallback palette, auto-add, matching, import/export).\n A region set with a class hierarchy (an atlas ontology) can show its classes\n as a tree instead (projected in by the editor); the header switches views. -->\n<div class=\"classes-panel\">\n <div class=\"classes-panel-header\">\n <span class=\"classes-panel-title\">Classes</span>\n <button\n *ngIf=\"treeView !== null\"\n pButton\n type=\"button\"\n [icon]=\"treeView ? 'pi pi-list' : 'pi pi-sitemap'\"\n class=\"p-button-sm p-button-text\"\n [pTooltip]=\"treeView ? 'Show the classes as a list' : 'Show the classes as a tree'\"\n tooltipPosition=\"bottom\"\n [attr.aria-label]=\"treeView ? 'Show the classes as a list' : 'Show the classes as a tree'\"\n (click)=\"treeViewChange.emit(!treeView)\"\n ></button>\n <button\n pButton\n type=\"button\"\n icon=\"pi pi-cog\"\n label=\"Manage\"\n class=\"p-button-sm p-button-text\"\n pTooltip=\"Manage classes \u2014 add / remove, palette, matching, import/export\"\n tooltipPosition=\"bottom\"\n (click)=\"manage.emit()\"\n ></button>\n </div>\n <ng-container *ngIf=\"treeView; else list\"><ng-content></ng-content></ng-container>\n <ng-template #list>\n <input\n *ngIf=\"classes.length\"\n type=\"text\"\n pInputText\n class=\"p-inputtext-sm classes-search\"\n placeholder=\"Search by name\"\n aria-label=\"Search the classes\"\n [ngModel]=\"query\"\n (ngModelChange)=\"onQuery($event)\"\n (keydown.enter)=\"pickFirstMatch()\"\n />\n <div class=\"classes-panel-body\">\n <div\n *ngFor=\"let c of shownRows; trackBy: trackByName\"\n class=\"class-row\"\n [class.active]=\"activeClass === c.name\"\n [class.picked]=\"picked === c.name\"\n [class.marked]=\"marked.has(c.name)\"\n [class.hidden-class]=\"hidden.has(c.name)\"\n (click)=\"pick.emit(c.name)\"\n [pTooltip]=\"c.rowTooltip\"\n tooltipPosition=\"bottom\"\n >\n <i\n class=\"pi row-eye\"\n [ngClass]=\"hidden.has(c.name) ? 'pi-eye-slash' : 'pi-eye'\"\n role=\"button\"\n [attr.aria-pressed]=\"!hidden.has(c.name)\"\n [attr.aria-label]=\"(hidden.has(c.name) ? 'Show ' : 'Hide ') + c.name\"\n [pTooltip]=\"hidden.has(c.name) ? 'Show this class' : 'Hide this class'\"\n tooltipPosition=\"bottom\"\n (click)=\"$event.stopPropagation(); toggleHidden.emit(c.name)\"\n ></i>\n <span class=\"row-swatch\" (click)=\"$event.stopPropagation()\">\n <hex-color-picker [color]=\"c.color\" (colorChange)=\"recolor.emit({ name: c.name, color: $event })\">\n </hex-color-picker>\n </span>\n <span class=\"row-name\">{{ c.name }}</span>\n <span class=\"row-count\" [class.zero]=\"c.count === 0\">{{ c.count }}</span>\n <i\n *ngIf=\"volume\"\n class=\"pi pi-box row-3d\"\n [class.on]=\"shown3d.has(c.name)\"\n role=\"button\"\n [attr.aria-pressed]=\"shown3d.has(c.name)\"\n [attr.aria-label]=\"'Show ' + c.name + ' in 3D'\"\n pTooltip=\"Show in the volume, in 3D\"\n tooltipPosition=\"bottom\"\n (click)=\"$event.stopPropagation(); toggle3d.emit(c.name)\"\n ></i>\n <button\n pButton\n type=\"button\"\n icon=\"pi pi-trash\"\n class=\"p-button-sm p-button-text p-button-warning row-del\"\n [disabled]=\"!c.canRemove\"\n [pTooltip]=\"c.removeTooltip\"\n tooltipPosition=\"bottom\"\n [attr.aria-label]=\"'Remove class ' + c.name\"\n (click)=\"$event.stopPropagation(); remove.emit(c.name)\"\n ></button>\n </div>\n <div *ngIf=\"!classes.length\" class=\"classes-empty\">No classes yet \u2014 add one from Manage.</div>\n <div *ngIf=\"classes.length && !shownRows.length\" class=\"classes-empty\">No class matches.</div>\n </div>\n </ng-template>\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:block;flex:0 0 auto}.classes-panel{display:flex;flex-direction:column;flex:0 0 auto;border-bottom:1px solid var(--surface-border)}.classes-panel-header{display:flex;align-items:center;gap:.35rem;padding:.35rem .5rem;border-bottom:1px solid var(--surface-border)}.classes-panel-title{font-size:.75rem;font-weight:600;letter-spacing:.03em;text-transform:uppercase;color:var(--text-color-secondary);margin-right:auto}.classes-search{margin:.25rem .5rem}.classes-panel-body{height:7rem;min-height:2.5rem;max-height:60vh;overflow-x:hidden;overflow-y:auto;resize:vertical}::ng-deep region-classes-panel .classes-panel-body .hex-picker-swatch{width:1.25rem;height:1.25rem;border-width:1px}.class-row{display:flex;align-items:center;gap:.5rem;padding:.1rem .5rem;cursor:pointer;border-left:3px solid transparent}.class-row:hover{background:var(--surface-hover, rgba(0, 0, 0, .04))}.class-row.picked{background:var(--highlight-bg, rgba(51, 153, 255, .12))}.class-row.marked{box-shadow:inset 3px 0 0 var(--primary-color)}.class-row.active{background:var(--highlight-bg, rgba(51, 153, 255, .12));border-left-color:var(--primary-color)}.class-row .row-swatch{flex:0 0 auto;display:inline-flex}.class-row .row-name{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.85rem}.class-row.active .row-name{color:var(--primary-color);font-weight:600}.class-row .row-count{flex:0 0 auto;min-width:1.5rem;text-align:center;font-size:.72rem;font-variant-numeric:tabular-nums;color:var(--text-color-secondary);background:var(--surface-200, rgba(0, 0, 0, .06));border-radius:10px;padding:0 .4rem}.class-row .row-count.zero{opacity:.5}.class-row .row-del{flex:0 0 auto}.classes-empty{font-size:.8rem;color:var(--text-color-secondary);padding:.5rem}::ng-deep region-classes-panel .classes-panel-body .class-row .p-button.p-button-icon-only{width:1.75rem;height:1.75rem;padding:0}.class-row .row-3d{flex:0 0 auto;font-size:.8rem;opacity:.35;cursor:pointer}.class-row .row-3d:hover{opacity:.8}.class-row .row-3d.on{opacity:1;color:var(--primary-color)}.class-row .row-eye{flex:0 0 auto;font-size:.8rem;opacity:.4;cursor:pointer}.class-row .row-eye:hover{opacity:.9}.class-row.hidden-class .row-eye{opacity:1}.class-row.hidden-class .row-swatch,.class-row.hidden-class .row-name,.class-row.hidden-class .row-count{opacity:.45}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i3.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "label", "icon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i4.InputText, selector: "[pInputText]", inputs: ["variant"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i5.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "component", type: HexColorPickerComponent, selector: "hex-color-picker", inputs: ["color"], outputs: ["colorChange", "colorInput"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
74
120
  }
75
121
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: ClassesPanelComponent, decorators: [{
76
122
  type: Component,
77
- args: [{ selector: 'region-classes-panel', standalone: true, imports: [CommonModule, ButtonModule, TooltipModule, HexColorPickerComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Docked \"Classes\" panel (jit-ui#70): the always-visible list of annotation\n classes above the regions table. Click a row to make it the active class\n (new regions inherit it; with rows selected it re-classifies them); recolour\n via the swatch; the badge shows how many regions use the class. \"Manage\"\n opens the full editor (fallback palette, auto-add, matching, import/export). -->\n<div class=\"classes-panel\">\n <div class=\"classes-panel-header\">\n <span class=\"classes-panel-title\">Classes</span>\n <button\n pButton\n type=\"button\"\n icon=\"pi pi-cog\"\n label=\"Manage\"\n class=\"p-button-sm p-button-text\"\n pTooltip=\"Manage classes \u2014 add / remove, palette, matching, import/export\"\n tooltipPosition=\"bottom\"\n (click)=\"manage.emit()\"\n ></button>\n </div>\n <div class=\"classes-panel-body\">\n <div\n *ngFor=\"let c of rows; trackBy: trackByName\"\n class=\"class-row\"\n [class.active]=\"activeClass === c.name\"\n (click)=\"pick.emit(c.name)\"\n [pTooltip]=\"c.rowTooltip\"\n tooltipPosition=\"bottom\"\n >\n <span class=\"row-swatch\" (click)=\"$event.stopPropagation()\">\n <hex-color-picker [color]=\"c.color\" (colorChange)=\"recolor.emit({ name: c.name, color: $event })\">\n </hex-color-picker>\n </span>\n <span class=\"row-name\">{{ c.name }}</span>\n <span class=\"row-count\" [class.zero]=\"c.count === 0\">{{ c.count }}</span>\n <button\n pButton\n type=\"button\"\n icon=\"pi pi-trash\"\n class=\"p-button-sm p-button-text p-button-warning row-del\"\n [disabled]=\"!c.canRemove\"\n [pTooltip]=\"c.removeTooltip\"\n tooltipPosition=\"bottom\"\n [attr.aria-label]=\"'Remove class ' + c.name\"\n (click)=\"$event.stopPropagation(); remove.emit(c.name)\"\n ></button>\n </div>\n <div *ngIf=\"!classes.length\" class=\"classes-empty\">No classes yet \u2014 add one from Manage.</div>\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:block;flex:0 0 auto}.classes-panel{display:flex;flex-direction:column;flex:0 0 auto;border-bottom:1px solid var(--surface-border)}.classes-panel-header{display:flex;align-items:center;gap:.35rem;padding:.35rem .5rem;border-bottom:1px solid var(--surface-border)}.classes-panel-title{font-size:.75rem;font-weight:600;letter-spacing:.03em;text-transform:uppercase;color:var(--text-color-secondary);margin-right:auto}.classes-panel-body{height:7rem;min-height:2.5rem;max-height:60vh;overflow-x:hidden;overflow-y:auto;resize:vertical}::ng-deep region-classes-panel .classes-panel-body .hex-picker-swatch{width:1.25rem;height:1.25rem;border-width:1px}.class-row{display:flex;align-items:center;gap:.5rem;padding:.1rem .5rem;cursor:pointer;border-left:3px solid transparent}.class-row:hover{background:var(--surface-hover, rgba(0, 0, 0, .04))}.class-row.active{background:var(--highlight-bg, rgba(51, 153, 255, .12));border-left-color:var(--primary-color)}.class-row .row-swatch{flex:0 0 auto;display:inline-flex}.class-row .row-name{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.85rem}.class-row.active .row-name{color:var(--primary-color);font-weight:600}.class-row .row-count{flex:0 0 auto;min-width:1.5rem;text-align:center;font-size:.72rem;font-variant-numeric:tabular-nums;color:var(--text-color-secondary);background:var(--surface-200, rgba(0, 0, 0, .06));border-radius:10px;padding:0 .4rem}.class-row .row-count.zero{opacity:.5}.class-row .row-del{flex:0 0 auto}.classes-empty{font-size:.8rem;color:var(--text-color-secondary);padding:.5rem}::ng-deep region-classes-panel .classes-panel-body .class-row .p-button.p-button-icon-only{width:1.75rem;height:1.75rem;padding:0}\n"] }]
78
- }], propDecorators: { classes: [{
123
+ args: [{ selector: 'region-classes-panel', standalone: true, imports: [CommonModule, FormsModule, ButtonModule, InputTextModule, TooltipModule, HexColorPickerComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Docked \"Classes\" panel (jit-ui#70): the always-visible list of annotation\n classes above the regions table. Click a row to make it the active class\n (new regions inherit it; with rows selected it re-classifies them); recolour\n via the swatch; the badge shows how many regions use the class. \"Manage\"\n opens the full editor (fallback palette, auto-add, matching, import/export).\n A region set with a class hierarchy (an atlas ontology) can show its classes\n as a tree instead (projected in by the editor); the header switches views. -->\n<div class=\"classes-panel\">\n <div class=\"classes-panel-header\">\n <span class=\"classes-panel-title\">Classes</span>\n <button\n *ngIf=\"treeView !== null\"\n pButton\n type=\"button\"\n [icon]=\"treeView ? 'pi pi-list' : 'pi pi-sitemap'\"\n class=\"p-button-sm p-button-text\"\n [pTooltip]=\"treeView ? 'Show the classes as a list' : 'Show the classes as a tree'\"\n tooltipPosition=\"bottom\"\n [attr.aria-label]=\"treeView ? 'Show the classes as a list' : 'Show the classes as a tree'\"\n (click)=\"treeViewChange.emit(!treeView)\"\n ></button>\n <button\n pButton\n type=\"button\"\n icon=\"pi pi-cog\"\n label=\"Manage\"\n class=\"p-button-sm p-button-text\"\n pTooltip=\"Manage classes \u2014 add / remove, palette, matching, import/export\"\n tooltipPosition=\"bottom\"\n (click)=\"manage.emit()\"\n ></button>\n </div>\n <ng-container *ngIf=\"treeView; else list\"><ng-content></ng-content></ng-container>\n <ng-template #list>\n <input\n *ngIf=\"classes.length\"\n type=\"text\"\n pInputText\n class=\"p-inputtext-sm classes-search\"\n placeholder=\"Search by name\"\n aria-label=\"Search the classes\"\n [ngModel]=\"query\"\n (ngModelChange)=\"onQuery($event)\"\n (keydown.enter)=\"pickFirstMatch()\"\n />\n <div class=\"classes-panel-body\">\n <div\n *ngFor=\"let c of shownRows; trackBy: trackByName\"\n class=\"class-row\"\n [class.active]=\"activeClass === c.name\"\n [class.picked]=\"picked === c.name\"\n [class.marked]=\"marked.has(c.name)\"\n [class.hidden-class]=\"hidden.has(c.name)\"\n (click)=\"pick.emit(c.name)\"\n [pTooltip]=\"c.rowTooltip\"\n tooltipPosition=\"bottom\"\n >\n <i\n class=\"pi row-eye\"\n [ngClass]=\"hidden.has(c.name) ? 'pi-eye-slash' : 'pi-eye'\"\n role=\"button\"\n [attr.aria-pressed]=\"!hidden.has(c.name)\"\n [attr.aria-label]=\"(hidden.has(c.name) ? 'Show ' : 'Hide ') + c.name\"\n [pTooltip]=\"hidden.has(c.name) ? 'Show this class' : 'Hide this class'\"\n tooltipPosition=\"bottom\"\n (click)=\"$event.stopPropagation(); toggleHidden.emit(c.name)\"\n ></i>\n <span class=\"row-swatch\" (click)=\"$event.stopPropagation()\">\n <hex-color-picker [color]=\"c.color\" (colorChange)=\"recolor.emit({ name: c.name, color: $event })\">\n </hex-color-picker>\n </span>\n <span class=\"row-name\">{{ c.name }}</span>\n <span class=\"row-count\" [class.zero]=\"c.count === 0\">{{ c.count }}</span>\n <i\n *ngIf=\"volume\"\n class=\"pi pi-box row-3d\"\n [class.on]=\"shown3d.has(c.name)\"\n role=\"button\"\n [attr.aria-pressed]=\"shown3d.has(c.name)\"\n [attr.aria-label]=\"'Show ' + c.name + ' in 3D'\"\n pTooltip=\"Show in the volume, in 3D\"\n tooltipPosition=\"bottom\"\n (click)=\"$event.stopPropagation(); toggle3d.emit(c.name)\"\n ></i>\n <button\n pButton\n type=\"button\"\n icon=\"pi pi-trash\"\n class=\"p-button-sm p-button-text p-button-warning row-del\"\n [disabled]=\"!c.canRemove\"\n [pTooltip]=\"c.removeTooltip\"\n tooltipPosition=\"bottom\"\n [attr.aria-label]=\"'Remove class ' + c.name\"\n (click)=\"$event.stopPropagation(); remove.emit(c.name)\"\n ></button>\n </div>\n <div *ngIf=\"!classes.length\" class=\"classes-empty\">No classes yet \u2014 add one from Manage.</div>\n <div *ngIf=\"classes.length && !shownRows.length\" class=\"classes-empty\">No class matches.</div>\n </div>\n </ng-template>\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:block;flex:0 0 auto}.classes-panel{display:flex;flex-direction:column;flex:0 0 auto;border-bottom:1px solid var(--surface-border)}.classes-panel-header{display:flex;align-items:center;gap:.35rem;padding:.35rem .5rem;border-bottom:1px solid var(--surface-border)}.classes-panel-title{font-size:.75rem;font-weight:600;letter-spacing:.03em;text-transform:uppercase;color:var(--text-color-secondary);margin-right:auto}.classes-search{margin:.25rem .5rem}.classes-panel-body{height:7rem;min-height:2.5rem;max-height:60vh;overflow-x:hidden;overflow-y:auto;resize:vertical}::ng-deep region-classes-panel .classes-panel-body .hex-picker-swatch{width:1.25rem;height:1.25rem;border-width:1px}.class-row{display:flex;align-items:center;gap:.5rem;padding:.1rem .5rem;cursor:pointer;border-left:3px solid transparent}.class-row:hover{background:var(--surface-hover, rgba(0, 0, 0, .04))}.class-row.picked{background:var(--highlight-bg, rgba(51, 153, 255, .12))}.class-row.marked{box-shadow:inset 3px 0 0 var(--primary-color)}.class-row.active{background:var(--highlight-bg, rgba(51, 153, 255, .12));border-left-color:var(--primary-color)}.class-row .row-swatch{flex:0 0 auto;display:inline-flex}.class-row .row-name{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.85rem}.class-row.active .row-name{color:var(--primary-color);font-weight:600}.class-row .row-count{flex:0 0 auto;min-width:1.5rem;text-align:center;font-size:.72rem;font-variant-numeric:tabular-nums;color:var(--text-color-secondary);background:var(--surface-200, rgba(0, 0, 0, .06));border-radius:10px;padding:0 .4rem}.class-row .row-count.zero{opacity:.5}.class-row .row-del{flex:0 0 auto}.classes-empty{font-size:.8rem;color:var(--text-color-secondary);padding:.5rem}::ng-deep region-classes-panel .classes-panel-body .class-row .p-button.p-button-icon-only{width:1.75rem;height:1.75rem;padding:0}.class-row .row-3d{flex:0 0 auto;font-size:.8rem;opacity:.35;cursor:pointer}.class-row .row-3d:hover{opacity:.8}.class-row .row-3d.on{opacity:1;color:var(--primary-color)}.class-row .row-eye{flex:0 0 auto;font-size:.8rem;opacity:.4;cursor:pointer}.class-row .row-eye:hover{opacity:.9}.class-row.hidden-class .row-eye{opacity:1}.class-row.hidden-class .row-swatch,.class-row.hidden-class .row-name,.class-row.hidden-class .row-count{opacity:.45}\n"] }]
124
+ }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { classes: [{
79
125
  type: Input
80
126
  }], counts: [{
81
127
  type: Input
@@ -83,10 +129,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImpor
83
129
  type: Input
84
130
  }], activeClass: [{
85
131
  type: Input
132
+ }], picked: [{
133
+ type: Input
134
+ }], marked: [{
135
+ type: Input
86
136
  }], selectedCount: [{
87
137
  type: Input
88
138
  }], defaultClassName: [{
89
139
  type: Input
140
+ }], volume: [{
141
+ type: Input
142
+ }], shown3d: [{
143
+ type: Input
144
+ }], hidden: [{
145
+ type: Input
146
+ }], toggleHidden: [{
147
+ type: Output
148
+ }], toggle3d: [{
149
+ type: Output
150
+ }], treeView: [{
151
+ type: Input
152
+ }], treeViewChange: [{
153
+ type: Output
90
154
  }], pick: [{
91
155
  type: Output
92
156
  }], recolor: [{
@@ -96,4 +160,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImpor
96
160
  }], manage: [{
97
161
  type: Output
98
162
  }] } });
99
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy1wYW5lbC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbGliL3JlZ2lvbi1lZGl0b3IvY2xhc3Nlcy1wYW5lbC9jbGFzc2VzLXBhbmVsLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvcmVnaW9uLWVkaXRvci9jbGFzc2VzLXBhbmVsL2NsYXNzZXMtcGFuZWwuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLHVCQUF1QixFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFhLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzRyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzlDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUdoRCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDekQsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sbURBQW1ELENBQUM7Ozs7O0FBWTVGOzs7Ozs7R0FNRztBQVNILE1BQU0sT0FBTyxxQkFBcUI7SUFSbEM7UUFTRSxvQ0FBb0M7UUFDM0IsWUFBTyxHQUFrQixFQUFFLENBQUM7UUFDckMsNEVBQTRFO1FBQ25FLFdBQU0sR0FBRyxJQUFJLEdBQUcsRUFBa0IsQ0FBQztRQUM1QywrREFBK0Q7UUFDdEQsY0FBUyxHQUFjLE9BQU8sQ0FBQztRQUN4QywrQ0FBK0M7UUFDdEMsZ0JBQVcsR0FBa0IsSUFBSSxDQUFDO1FBQzNDLGtFQUFrRTtRQUN6RCxrQkFBYSxHQUFHLENBQUMsQ0FBQztRQUMzQixxRUFBcUU7UUFDNUQscUJBQWdCLEdBQUcsUUFBUSxDQUFDO1FBRXJDLDRFQUE0RTtRQUNsRSxTQUFJLEdBQUcsSUFBSSxZQUFZLEVB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QkFBZixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENvbXBvbmVudCwgRXZlbnRFbWl0dGVyLCBJbnB1dCwgT25DaGFuZ2VzLCBPdXRwdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBCdXR0b25Nb2R1bGUgfSBmcm9tICdwcmltZW5nL2J1dHRvbic7XG5pbXBvcnQgeyBUb29sdGlwTW9kdWxlIH0gZnJvbSAncHJpbWVuZy90b29sdGlwJztcblxuaW1wb3J0IHsgQ2xhc3NQcmVzZXQsIE1hdGNoTW9kZSB9IGZyb20gJy4uLy4uL21vZGVscy9jbGFzcy1wcmVzZXQnO1xuaW1wb3J0IHsgcHJlc2V0S2V5IH0gZnJvbSAnLi4vLi4vc3RvcmUvY2xhc3MtY29sb3IudXRpbCc7XG5pbXBvcnQgeyBIZXhDb2xvclBpY2tlckNvbXBvbmVudCB9IGZyb20gJy4uLy4uL2hleC1jb2xvci1waWNrZXIvaGV4LWNvbG9yLXBpY2tlci5jb21wb25lbnQnO1xuXG4vKiogT25lIGNsYXNzIHJvdyBhcyB0aGUgdGVtcGxhdGUgZHJhd3MgaXQsIGRlcml2ZWQgb25jZSBwZXIgaW5wdXQgY2hhbmdlLiAqL1xuaW50ZXJmYWNlIENsYXNzUm93IHtcbiAgbmFtZTogc3RyaW5nO1xuICBjb2xvcjogc3RyaW5nO1xuICBjb3VudDogbnVtYmVyO1xuICBjYW5SZW1vdmU6IGJvb2xlYW47XG4gIHJvd1Rvb2x0aXA6IHN0cmluZztcbiAgcmVtb3ZlVG9vbHRpcDogc3RyaW5nO1xufVxuXG4vKipcbiAqIFRoZSBSZWdpb24gRWRpdG9yJ3MgZG9ja2VkIFwiQ2xhc3Nlc1wiIHBhbmVsIChqaXQtdWkjNzApOiBldmVyeSBhbm5vdGF0aW9uXG4gKiBjbGFzcyB3aXRoIGl0cyBjb2xvdXIgc3dhdGNoIGFuZCByZWdpb24gY291bnQuIEEgcm93IGNsaWNrIHBpY2tzIHRoZSBhY3RpdmVcbiAqIGNsYXNzIChhbmQgcmUtY2xhc3NpZmllcyBhIHNlbGVjdGlvbiksIHRoZSBzd2F0Y2ggcmVjb2xvdXJzIHRoZSBjbGFzcywgdGhlXG4gKiB0cmFzaCByZW1vdmVzIGl0LCBNYW5hZ2Ugb3BlbnMgdGhlIGZ1bGwgZWRpdG9yLiBQcmVzZW50YXRpb25hbDogdGhlIGVkaXRvclxuICogYXBwbGllcyBldmVyeSBhY3Rpb24uXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3JlZ2lvbi1jbGFzc2VzLXBhbmVsJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZSwgQnV0dG9uTW9kdWxlLCBUb29sdGlwTW9kdWxlLCBIZXhDb2xvclBpY2tlckNvbXBvbmVudF0sXG4gIHRlbXBsYXRlVXJsOiAnLi9jbGFzc2VzLXBhbmVsLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vY2xhc3Nlcy1wYW5lbC5jb21wb25lbnQuc2NzcyddLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbn0pXG5leHBvcnQgY2xhc3MgQ2xhc3Nlc1BhbmVsQ29tcG9uZW50IGltcGxlbWVudHMgT25DaGFuZ2VzIHtcbiAgLyoqIFRoZSBjbGFzc2VzIGluIGRpc3BsYXkgb3JkZXIuICovXG4gIEBJbnB1dCgpIGNsYXNzZXM6IENsYXNzUHJlc2V0W10gPSBbXTtcbiAgLyoqIFJlZ2lvbiBjb3VudCBwZXIgY2xhc3MsIGtleWVkIGJ5IHtAbGluayBwcmVzZXRLZXl9IHVuZGVyIGBtYXRjaE1vZGVgLiAqL1xuICBASW5wdXQoKSBjb3VudHMgPSBuZXcgTWFwPHN0cmluZywgbnVtYmVyPigpO1xuICAvKiogSG93IGxhYmVscyBhcmUgbWF0Y2hlZCB0byBjbGFzc2VzIChrZXlzIHtAbGluayBjb3VudHN9KS4gKi9cbiAgQElucHV0KCkgbWF0Y2hNb2RlOiBNYXRjaE1vZGUgPSAnZXhhY3QnO1xuICAvKiogVGhlIGFjdGl2ZSBjbGFzcyAoaGlnaGxpZ2h0ZWQpLCBvciBudWxsLiAqL1xuICBASW5wdXQoKSBhY3RpdmVDbGFzczogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIC8qKiBOdW1iZXIgb2Ygc2VsZWN0ZWQgcmVnaW9ucyAoY2hhbmdlcyB3aGF0IGEgcm93IGNsaWNrIGRvZXMpLiAqL1xuICBASW5wdXQoKSBzZWxlY3RlZENvdW50ID0gMDtcbiAgLyoqIFRoZSBjbGFzcyByZWdpb25zIHJldmVydCB0bzsgaXQgY2FuJ3QgYmUgcmVtb3ZlZCB3aGlsZSBpbiB1c2UuICovXG4gIEBJbnB1dCgpIGRlZmF1bHRDbGFzc05hbWUgPSAnUmVnaW9uJztcblxuICAvKiogQSByb3cgd2FzIGNsaWNrZWQ6IG1ha2UgdGhlIGNsYXNzIGFjdGl2ZSAvIGFwcGx5IGl0IHRvIHRoZSBzZWxlY3Rpb24uICovXG4gIEBPdXRwdXQoKSBwaWNrID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmc+KCk7XG4gIC8qKiBBIGNsYXNzJ3Mgc3dhdGNoIHBpY2tlZCBhIG5ldyBjb2xvdXIuICovXG4gIEBPdXRwdXQoKSByZWNvbG9yID0gbmV3IEV2ZW50RW1pdHRlcjx7IG5hbWU6IHN0cmluZzsgY29sb3I6IHN0cmluZyB9PigpO1xuICAvKiogQSBjbGFzcydzIHRyYXNoIGJ1dHRvbiAoaXRzIG5hbWUpLiAqL1xuICBAT3V0cHV0KCkgcmVtb3ZlID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmc+KCk7XG4gIC8qKiBNYW5hZ2UgY2xpY2tlZC4gKi9cbiAgQE91dHB1dCgpIG1hbmFnZSA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcblxuICAvKiogdHJhY2tCeSBmb3IgdGhlIGNsYXNzIHJvd3Mgc28gcmUtc29ydGluZyBkb2Vzbid0IHJlLWNyZWF0ZSB0aGUgcGlja2Vycy4gKi9cbiAgcHJvdGVjdGVkIHJlYWRvbmx5IHRyYWNrQnlOYW1lID0gKF86IG51bWJlciwgYzogQ2xhc3NSb3cpOiBzdHJpbmcgPT4gYy5uYW1lO1xuXG4gIC8qKiBUaGUgcm93cyBkcmF3biwgcmVidWlsdCB3aGVuIGFuIGlucHV0IGNoYW5nZXMgcmF0aGVyIHRoYW4gcGVyIGNoZWNrLiAqL1xuICBwcm90ZWN0ZWQgcm93czogQ2xhc3NSb3dbXSA9IFtdO1xuXG4gIG5nT25DaGFuZ2VzKCk6IHZvaWQge1xuICAgIHRoaXMucm93cyA9IHRoaXMuY2xhc3Nlcy5tYXAoKGMpID0+ICh7XG4gICAgICBuYW1lOiBjLm5hbWUsXG4gICAgICBjb2xvcjogYy5jb2xvcixcbiAgICAgIGNvdW50OiB0aGlzLmNvdW50KGMubmFtZSksXG4gICAgICBjYW5SZW1vdmU6IHRoaXMuY2FuUmVtb3ZlKGMubmFtZSksXG4gICAgICByb3dUb29sdGlwOiB0aGlzLnJvd1Rvb2x0aXAoYy5uYW1lKSxcbiAgICAgIHJlbW92ZVRvb2x0aXA6IHRoaXMucmVtb3ZlVG9vbHRpcChjLm5hbWUpLFxuICAgIH0pKTtcbiAgfVxuXG4gIHByaXZhdGUgY291bnQobmFtZTogc3RyaW5nKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5jb3VudHMuZ2V0KHByZXNldEtleSh7IG1hdGNoTW9kZTogdGhpcy5tYXRjaE1vZGUgfSwgbmFtZSkpID8/IDA7XG4gIH1cblxuICBwcml2YXRlIGNhblJlbW92ZShuYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gIShuYW1lID09PSB0aGlzLmRlZmF1bHRDbGFzc05hbWUgJiYgdGhpcy5jb3VudChuYW1lKSA+IDApO1xuICB9XG5cbiAgcHJvdGVjdGVkIHJvd1Rvb2x0aXAobmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5zZWxlY3RlZENvdW50XG4gICAgICA/IGBBcHBseSDigJwke25hbWV94oCdIHRvIHRoZSBzZWxlY3RlZCByZWdpb24ocylgXG4gICAgICA6IGBTZXQg4oCcJHtuYW1lfeKAnSBhY3RpdmUg4oCUIG5ldyByZWdpb25zIHVzZSBpdGA7XG4gIH1cblxuICBwcm90ZWN0ZWQgcmVtb3ZlVG9vbHRpcChuYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGNvbnN0IGluVXNlID0gdGhpcy5jb3VudChuYW1lKSA+IDA7XG4gICAgaWYgKG5hbWUgPT09IHRoaXMuZGVmYXVsdENsYXNzTmFtZSAmJiBpblVzZSkgcmV0dXJuICdUaGUgZGVmYXVsdCBjbGFzcyBjYW5ub3QgYmUgcmVtb3ZlZCB3aGlsZSBpbiB1c2UnO1xuICAgIHJldHVybiBpblVzZSA/IGBSZW1vdmUgY2xhc3Mg4oCUIGl0cyByZWdpb25zIHJldmVydCB0byAke3RoaXMuZGVmYXVsdENsYXNzTmFtZX1gIDogJ1JlbW92ZSBjbGFzcyc7XG4gIH1cbn1cbiIsIjwhLS0gRG9ja2VkIFwiQ2xhc3Nlc1wiIHBhbmVsIChqaXQtdWkjNzApOiB0aGUgYWx3YXlzLXZpc2libGUgbGlzdCBvZiBhbm5vdGF0aW9uXG4gICAgIGNsYXNzZXMgYWJvdmUgdGhlIHJlZ2lvbnMgdGFibGUuIENsaWNrIGEgcm93IHRvIG1ha2UgaXQgdGhlIGFjdGl2ZSBjbGFzc1xuICAgICAobmV3IHJlZ2lvbnMgaW5oZXJpdCBpdDsgd2l0aCByb3dzIHNlbGVjdGVkIGl0IHJlLWNsYXNzaWZpZXMgdGhlbSk7IHJlY29sb3VyXG4gICAgIHZpYSB0aGUgc3dhdGNoOyB0aGUgYmFkZ2Ugc2hvd3MgaG93IG1hbnkgcmVnaW9ucyB1c2UgdGhlIGNsYXNzLiBcIk1hbmFnZVwiXG4gICAgIG9wZW5zIHRoZSBmdWxsIGVkaXRvciAoZmFsbGJhY2sgcGFsZXR0ZSwgYXV0by1hZGQsIG1hdGNoaW5nLCBpbXBvcnQvZXhwb3J0KS4gLS0+XG48ZGl2IGNsYXNzPVwiY2xhc3Nlcy1wYW5lbFwiPlxuICA8ZGl2IGNsYXNzPVwiY2xhc3Nlcy1wYW5lbC1oZWFkZXJcIj5cbiAgICA8c3BhbiBjbGFzcz1cImNsYXNzZXMtcGFuZWwtdGl0bGVcIj5DbGFzc2VzPC9zcGFuPlxuICAgIDxidXR0b25cbiAgICAgIHBCdXR0b25cbiAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgaWNvbj1cInBpIHBpLWNvZ1wiXG4gICAgICBsYWJlbD1cIk1hbmFnZVwiXG4gICAgICBjbGFzcz1cInAtYnV0dG9uLXNtIHAtYnV0dG9uLXRleHRcIlxuICAgICAgcFRvb2x0aXA9XCJNYW5hZ2UgY2xhc3NlcyDigJQgYWRkIC8gcmVtb3ZlLCBwYWxldHRlLCBtYXRjaGluZywgaW1wb3J0L2V4cG9ydFwiXG4gICAgICB0b29sdGlwUG9zaXRpb249XCJib3R0b21cIlxuICAgICAgKGNsaWNrKT1cIm1hbmFnZS5lbWl0KClcIlxuICAgID48L2J1dHRvbj5cbiAgPC9kaXY+XG4gIDxkaXYgY2xhc3M9XCJjbGFzc2VzLXBhbmVsLWJvZHlcIj5cbiAgICA8ZGl2XG4gICAgICAqbmdGb3I9XCJsZXQgYyBvZiByb3dzOyB0cmFja0J5OiB0cmFja0J5TmFtZVwiXG4gICAgICBjbGFzcz1cImNsYXNzLXJvd1wiXG4gICAgICBbY2xhc3MuYWN0aXZlXT1cImFjdGl2ZUNsYXNzID09PSBjLm5hbWVcIlxuICAgICAgKGNsaWNrKT1cInBpY2suZW1pdChjLm5hbWUpXCJcbiAgICAgIFtwVG9vbHRpcF09XCJjLnJvd1Rvb2x0aXBcIlxuICAgICAgdG9vbHRpcFBvc2l0aW9uPVwiYm90dG9tXCJcbiAgICA+XG4gICAgICA8c3BhbiBjbGFzcz1cInJvdy1zd2F0Y2hcIiAoY2xpY2spPVwiJGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpXCI+XG4gICAgICAgIDxoZXgtY29sb3ItcGlja2VyIFtjb2xvcl09XCJjLmNvbG9yXCIgKGNvbG9yQ2hhbmdlKT1cInJlY29sb3IuZW1pdCh7IG5hbWU6IGMubmFtZSwgY29sb3I6ICRldmVudCB9KVwiPlxuICAgICAgICA8L2hleC1jb2xvci1waWNrZXI+XG4gICAgICA8L3NwYW4+XG4gICAgICA8c3BhbiBjbGFzcz1cInJvdy1uYW1lXCI+e3sgYy5uYW1lIH19PC9zcGFuPlxuICAgICAgPHNwYW4gY2xhc3M9XCJyb3ctY291bnRcIiBbY2xhc3MuemVyb109XCJjLmNvdW50ID09PSAwXCI+e3sgYy5jb3VudCB9fTwvc3Bhbj5cbiAgICAgIDxidXR0b25cbiAgICAgICAgcEJ1dHRvblxuICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgaWNvbj1cInBpIHBpLXRyYXNoXCJcbiAgICAgICAgY2xhc3M9XCJwLWJ1dHRvbi1zbSBwLWJ1dHRvbi10ZXh0IHAtYnV0dG9uLXdhcm5pbmcgcm93LWRlbFwiXG4gICAgICAgIFtkaXNhYmxlZF09XCIhYy5jYW5SZW1vdmVcIlxuICAgICAgICBbcFRvb2x0aXBdPVwiYy5yZW1vdmVUb29sdGlwXCJcbiAgICAgICAgdG9vbHRpcFBvc2l0aW9uPVwiYm90dG9tXCJcbiAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCInUmVtb3ZlIGNsYXNzICcgKyBjLm5hbWVcIlxuICAgICAgICAoY2xpY2spPVwiJGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpOyByZW1vdmUuZW1pdChjLm5hbWUpXCJcbiAgICAgID48L2J1dHRvbj5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2ICpuZ0lmPVwiIWNsYXNzZXMubGVuZ3RoXCIgY2xhc3M9XCJjbGFzc2VzLWVtcHR5XCI+Tm8gY2xhc3NlcyB5ZXQg4oCUIGFkZCBvbmUgZnJvbSBNYW5hZ2UuPC9kaXY+XG4gIDwvZGl2PlxuPC9kaXY+XG4iXX0=
163
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy1wYW5lbC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbGliL3JlZ2lvbi1lZGl0b3IvY2xhc3Nlcy1wYW5lbC9jbGFzc2VzLXBhbmVsLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvcmVnaW9uLWVkaXRvci9jbGFzc2VzLXBhbmVsL2NsYXNzZXMtcGFuZWwuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLHVCQUF1QixFQUN2QixTQUFTLEVBQ1QsVUFBVSxFQUNWLFlBQVksRUFDWixLQUFLLEVBRUwsTUFBTSxHQUVQLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ3BELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM5QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFHaEQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQ3pELE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLG1EQUFtRCxDQUFDO0FBQzVGLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQzs7Ozs7OztBQVlwRTs7Ozs7Ozs7R0FRRztBQVNILE1BQU0sT0FBTyxxQkFBcUI7SUFtRGhDLFlBQTZCLEVBQTJCO1FBQTNCLE9BQUUsR0FBRixFQUFFLENBQXlCO1FBbER4RCxvQ0FBb0M7UUFDM0IsWUFBTyxHQUFrQixFQUFFLENBQUM7UUFDckMsNEVBQTRFO1FBQ25FLFdBQU0sR0FBRyxJQUFJLEdBQUcsRUFBa0IsQ0FBQztRQUM1QywrREFBK0Q7UUFDdEQsY0FBUyxHQUFjLE9BQU8sQ0FBQztRQUN4QywrQ0FBK0M7UUFDdEMsZ0JBQVcsR0FBa0IsSUFBSSxDQUFDO1FBQzNDLHNHQUFzRztRQUM3RixXQUFNLEdBQWtCLElBQUksQ0FBQztRQUN0QywrQ0FBK0M7UUFDdEMsV0FBTSxHQUF3QixJQUFJLEdBQUcsRUFBRSxDQUFDO1FBQ2pELGtFQUFrRTtRQUN6RCxrQkFBYSxHQUFHLENBQUMsQ0FBQztRQUMzQixxRUFBcUU7UUFDNUQscUJBQWdCLEdBQUcsUUFBUSxDQUFDO1FBQ3JDLDhFQUE4RTtRQUNyRSxXQUFNLEdBQUcsS0FBSyxDQUFDO1FBQ3hCLCtCQUErQjtRQUN0QixZQUFPLEdBQXdCLElBQUksR0FBRyxFQUFFLENBQUM7UUFDbEQsb0NBQW9DO1FBQzNCLFdBQU0sR0FBd0IsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUNqRCwyREFBMkQ7UUFDakQsaUJBQVksR0FBRyxJQUFJLFlBQVksRUFBVSxDQUFDO1FBQ3BELHNDQUFzQztRQUM1QixhQUFRLEdBQUcsSUFBSSxZQUFZLEVBQVUsQ0FBQztRQUNoRCw2RkFBNkY7UUFDcEYsYUFBUSxHQUFtQixJQUFJLENBQUM7UUFDekMsOEJBQThCO1FBQ3BCLG1CQUFjLEdBQUcsSUFBSSxZQUFZLEVBQVcsQ0FBQztRQUV2RCw0RUFBNEU7UUFDbEUsU0FBSSxHQUFHLElBQUksWUFBWSxFQUFVLENBQUM7UUFDNUMsNENBQTRDO1FBQ2xDLFlBQU8sR0FBRyxJQUFJLFlBQVksRUFBbUMsQ0FBQztRQUN4RSx5Q0FBeUM7UUFDL0IsV0FBTSxHQUFHLElBQUksWUFBWSxFQUFVLENBQUM7UUFDOUMsc0JBQXNCO1FBQ1osV0FBTSxHQUFHLElBQUksWUFBWSxFQUFRLENBQUM7UUFFNUMsOEVBQThFO1FBQzNELGdCQUFXLEdBQUcsQ0FBQyxDQUFTLEVBQUUsQ0FBVyxFQUFVLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1FBRTVFLDhFQUE4RTtRQUNwRSxTQUFJLEdBQWUsRUFBRSxDQUFDO1FBQ2hDLHVDQUF1QztRQUM3QixjQUFTLEdBQWUsRUFBRSxDQUFDO1FBQ3JDLDZCQUE2QjtRQUNuQixVQUFLLEdBQUcsRUFBRSxDQUFDO0lBRXNDLENBQUM7SUFFNUQsV0FBVyxDQUFDLFVBQXlCLEVBQUU7UUFDckMsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUNuQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUk7WUFDWixLQUFLLEVBQUUsQ0FBQyxDQUFDLEtBQUs7WUFDZCxLQUFLLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1lBQ3pCLFNBQVMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7WUFDakMsVUFBVSxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztZQUNuQyxhQUFhLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1NBQzFDLENBQUMsQ0FBQyxDQUFDO1FBQ0osSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ2QsSUFBSSxPQUFPLENBQUMsUUFBUSxDQUFDLElBQUksSUFBSSxDQUFDLE1BQU07WUFDbEMsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLGFBQWEsRUFBRSxtQkFBbUIsQ0FBQyxDQUFDLENBQUM7SUFDakYsQ0FBQztJQUVTLE9BQU8sQ0FBQyxLQUFhO1FBQzdCLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO1FBQ25CLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztJQUNoQixDQUFDO0lBRUQscURBQXFEO0lBQzNDLGNBQWM7UUFDdEIsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxJQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTTtZQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDekYsQ0FBQztJQUVPLE1BQU07UUFDWixNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQzFDLElBQUksQ0FBQyxTQUFTLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztJQUM3RixDQUFDO0lBRU8sS0FBSyxDQUFDLElBQVk7UUFDeEIsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsRUFBRSxTQUFTLEVBQUUsSUFBSSxDQUFDLFNBQVMsRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzlFLENBQUM7SUFFTyxTQUFTLENBQUMsSUFBWTtRQUM1QixPQUFPLENBQUMsQ0FBQyxJQUFJLEtBQUssSUFBSSxDQUFDLGdCQUFnQixJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDbkUsQ0FBQztJQUVTLFVBQVUsQ0FBQyxJQUFZO1FBQy9CLE9BQU8sSUFBSSxDQUFDLGFBQWE7WUFDdkIsQ0FBQyxDQUFDLFVBQVUsSUFBSSw2QkFBNkI7WUFDN0MsQ0FBQyxDQUFDLFFBQVEsSUFBSSwrQkFBK0IsQ0FBQztJQUNsRCxDQUFDO0lBRVMsYUFBYSxDQUFDLElBQVk7UUFDbEMsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDbkMsSUFBSSxJQUFJLEtBQUssSUFBSSxDQUFDLGdCQUFnQixJQUFJLEtBQUs7WUFBRSxPQUFPLGtEQUFrRCxDQUFDO1FBQ3ZHLE9BQU8sS0FBSyxDQUFDLENBQUMsQ0FBQyx3Q0FBd0MsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUMsQ0FBQyxDQUFDLGNBQWMsQ0FBQztJQUNsRyxDQUFDOzhHQXBHVSxxQkFBcUI7a0dBQXJCLHFCQUFxQiw0aUJDaERsQyw2MElBcUdBLGc0RUQxRFksWUFBWSw2VkFBRSxXQUFXLDhtQkFBRSxZQUFZLDRPQUFFLGVBQWUsd0hBQUUsYUFBYSxzWEFBRSx1QkFBdUI7OzJGQUsvRixxQkFBcUI7a0JBUmpDLFNBQVM7K0JBQ0Usc0JBQXNCLGNBQ3BCLElBQUksV0FDUCxDQUFDLFlBQVksRUFBRSxXQUFXLEVBQUUsWUFBWSxFQUFFLGVBQWUsRUFBRSxhQUFhLEVBQUUsdUJBQXVCLENBQUMsbUJBRzFGLHVCQUF1QixDQUFDLE1BQU07K0VBSXRDLE9BQU87c0JBQWYsS0FBSztnQkFFRyxNQUFNO3NCQUFkLEtBQUs7Z0JBRUcsU0FBUztzQkFBakIsS0FBSztnQkFFRyxXQUFXO3NCQUFuQixLQUFLO2dCQUVHLE1BQU07c0JBQWQsS0FBSztnQkFFRyxNQUFNO3NCQUFkLEtBQUs7Z0JBRUcsYUFBYTtzQkFBckIsS0FBSztnQkFFRyxnQkFBZ0I7c0JBQXhCLEtBQUs7Z0JBRUcsTUFBTTtzQkFBZCxLQUFLO2dCQUVHLE9BQU87c0JBQWYsS0FBSztnQkFFRyxNQUFNO3NCQUFkLEtBQUs7Z0JBRUksWUFBWTtzQkFBckIsTUFBTTtnQkFFRyxRQUFRO3NCQUFqQixNQUFNO2dCQUVFLFFBQVE7c0JBQWhCLEtBQUs7Z0JBRUksY0FBYztzQkFBdkIsTUFBTTtnQkFHRyxJQUFJO3NCQUFiLE1BQU07Z0JBRUcsT0FBTztzQkFBaEIsTUFBTTtnQkFFRyxNQUFNO3NCQUFmLE1BQU07Z0JBRUcsTUFBTTtzQkFBZixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENvbXBvbmVudCxcbiAgRWxlbWVudFJlZixcbiAgRXZlbnRFbWl0dGVyLFxuICBJbnB1dCxcbiAgT25DaGFuZ2VzLFxuICBPdXRwdXQsXG4gIFNpbXBsZUNoYW5nZXMsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IEZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgSW5wdXRUZXh0TW9kdWxlIH0gZnJvbSAncHJpbWVuZy9pbnB1dHRleHQnO1xuaW1wb3J0IHsgQnV0dG9uTW9kdWxlIH0gZnJvbSAncHJpbWVuZy9idXR0b24nO1xuaW1wb3J0IHsgVG9vbHRpcE1vZHVsZSB9IGZyb20gJ3ByaW1lbmcvdG9vbHRpcCc7XG5cbmltcG9ydCB7IENsYXNzUHJlc2V0LCBNYXRjaE1vZGUgfSBmcm9tICcuLi8uLi9tb2RlbHMvY2xhc3MtcHJlc2V0JztcbmltcG9ydCB7IHByZXNldEtleSB9IGZyb20gJy4uLy4uL3N0b3JlL2NsYXNzLWNvbG9yLnV0aWwnO1xuaW1wb3J0IHsgSGV4Q29sb3JQaWNrZXJDb21wb25lbnQgfSBmcm9tICcuLi8uLi9oZXgtY29sb3ItcGlja2VyL2hleC1jb2xvci1waWNrZXIuY29tcG9uZW50JztcbmltcG9ydCB7IHNjcm9sbFRvUGlja2VkIH0gZnJvbSAnLi4vY2xhc3MtdHJlZS9jbGFzcy10cmVlLmNvbXBvbmVudCc7XG5cbi8qKiBPbmUgY2xhc3Mgcm93IGFzIHRoZSB0ZW1wbGF0ZSBkcmF3cyBpdCwgZGVyaXZlZCBvbmNlIHBlciBpbnB1dCBjaGFuZ2UuICovXG5pbnRlcmZhY2UgQ2xhc3NSb3cge1xuICBuYW1lOiBzdHJpbmc7XG4gIGNvbG9yOiBzdHJpbmc7XG4gIGNvdW50OiBudW1iZXI7XG4gIGNhblJlbW92ZTogYm9vbGVhbjtcbiAgcm93VG9vbHRpcDogc3RyaW5nO1xuICByZW1vdmVUb29sdGlwOiBzdHJpbmc7XG59XG5cbi8qKlxuICogVGhlIFJlZ2lvbiBFZGl0b3IncyBkb2NrZWQgXCJDbGFzc2VzXCIgcGFuZWwgKGppdC11aSM3MCk6IGV2ZXJ5IGFubm90YXRpb25cbiAqIGNsYXNzIHdpdGggaXRzIGNvbG91ciBzd2F0Y2ggYW5kIHJlZ2lvbiBjb3VudC4gQSByb3cgY2xpY2sgcGlja3MgdGhlIGFjdGl2ZVxuICogY2xhc3MgKGFuZCByZS1jbGFzc2lmaWVzIGEgc2VsZWN0aW9uKSwgdGhlIHN3YXRjaCByZWNvbG91cnMgdGhlIGNsYXNzLCB0aGVcbiAqIHRyYXNoIHJlbW92ZXMgaXQsIE1hbmFnZSBvcGVucyB0aGUgZnVsbCBlZGl0b3I7IHRoZSBzZWFyY2ggYm94IGZpbHRlcnMgdGhlXG4gKiByb3dzIGJ5IG5hbWU7IHRoZSBleWUgaGlkZXMgYSBjbGFzcydzIHJlZ2lvbnMuIEZvciBhIGNsYXNzIGhpZXJhcmNoeSB0aGUgZWRpdG9yIHByb2plY3RzIGEgY2xhc3MgdHJlZSBpbixcbiAqIHNob3duIGluIHBsYWNlIG9mIHRoZSBsaXN0IHdoaWxlIHtAbGluayB0cmVlVmlld30gaXMgb24uIFByZXNlbnRhdGlvbmFsOiB0aGVcbiAqIGVkaXRvciBhcHBsaWVzIGV2ZXJ5IGFjdGlvbi5cbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAncmVnaW9uLWNsYXNzZXMtcGFuZWwnLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlLCBGb3Jtc01vZHVsZSwgQnV0dG9uTW9kdWxlLCBJbnB1dFRleHRNb2R1bGUsIFRvb2x0aXBNb2R1bGUsIEhleENvbG9yUGlja2VyQ29tcG9uZW50XSxcbiAgdGVtcGxhdGVVcmw6ICcuL2NsYXNzZXMtcGFuZWwuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9jbGFzc2VzLXBhbmVsLmNvbXBvbmVudC5zY3NzJ10sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxufSlcbmV4cG9ydCBjbGFzcyBDbGFzc2VzUGFuZWxDb21wb25lbnQgaW1wbGVtZW50cyBPbkNoYW5nZXMge1xuICAvKiogVGhlIGNsYXNzZXMgaW4gZGlzcGxheSBvcmRlci4gKi9cbiAgQElucHV0KCkgY2xhc3NlczogQ2xhc3NQcmVzZXRbXSA9IFtdO1xuICAvKiogUmVnaW9uIGNvdW50IHBlciBjbGFzcywga2V5ZWQgYnkge0BsaW5rIHByZXNldEtleX0gdW5kZXIgYG1hdGNoTW9kZWAuICovXG4gIEBJbnB1dCgpIGNvdW50cyA9IG5ldyBNYXA8c3RyaW5nLCBudW1iZXI+KCk7XG4gIC8qKiBIb3cgbGFiZWxzIGFyZSBtYXRjaGVkIHRvIGNsYXNzZXMgKGtleXMge0BsaW5rIGNvdW50c30pLiAqL1xuICBASW5wdXQoKSBtYXRjaE1vZGU6IE1hdGNoTW9kZSA9ICdleGFjdCc7XG4gIC8qKiBUaGUgYWN0aXZlIGNsYXNzIChoaWdobGlnaHRlZCksIG9yIG51bGwuICovXG4gIEBJbnB1dCgpIGFjdGl2ZUNsYXNzOiBzdHJpbmcgfCBudWxsID0gbnVsbDtcbiAgLyoqIFRoZSBjbGFzcyBwaWNrZWQgbGFzdCAoaW4gdGhlIGNsYXNzIHRyZWUsIG9yIGEgc3VyZmFjZSBpbiAzRCk6IGhpZ2hsaWdodGVkLCBzY3JvbGxlZCBpbnRvIHZpZXcuICovXG4gIEBJbnB1dCgpIHBpY2tlZDogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIC8qKiBDbGFzc2VzIHdpdGggYSBzZWxlY3RlZCByZWdpb24gKG1hcmtlZCkuICovXG4gIEBJbnB1dCgpIG1hcmtlZDogUmVhZG9ubHlTZXQ8c3RyaW5nPiA9IG5ldyBTZXQoKTtcbiAgLyoqIE51bWJlciBvZiBzZWxlY3RlZCByZWdpb25zIChjaGFuZ2VzIHdoYXQgYSByb3cgY2xpY2sgZG9lcykuICovXG4gIEBJbnB1dCgpIHNlbGVjdGVkQ291bnQgPSAwO1xuICAvKiogVGhlIGNsYXNzIHJlZ2lvbnMgcmV2ZXJ0IHRvOyBpdCBjYW4ndCBiZSByZW1vdmVkIHdoaWxlIGluIHVzZS4gKi9cbiAgQElucHV0KCkgZGVmYXVsdENsYXNzTmFtZSA9ICdSZWdpb24nO1xuICAvKiogV2hldGhlciBhIHZvbHVtZSB2aWV3IGlzIG9uIHNjcmVlbjogZWFjaCBjbGFzcyBjYW4gdGhlbiBiZSBzaG93biBpbiAzRC4gKi9cbiAgQElucHV0KCkgdm9sdW1lID0gZmFsc2U7XG4gIC8qKiBUaGUgY2xhc3NlcyBzaG93biBpbiAzRC4gKi9cbiAgQElucHV0KCkgc2hvd24zZDogUmVhZG9ubHlTZXQ8c3RyaW5nPiA9IG5ldyBTZXQoKTtcbiAgLyoqIFRoZSBjbGFzc2VzIGhpZGRlbiBmcm9tIHZpZXcuICovXG4gIEBJbnB1dCgpIGhpZGRlbjogUmVhZG9ubHlTZXQ8c3RyaW5nPiA9IG5ldyBTZXQoKTtcbiAgLyoqIEEgY2xhc3MncyBleWUgKGl0cyBuYW1lKTogaGlkZSBpdCwgb3Igc2hvdyBpdCBhZ2Fpbi4gKi9cbiAgQE91dHB1dCgpIHRvZ2dsZUhpZGRlbiA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xuICAvKiogQSBjbGFzcydzIDNEIHRvZ2dsZSAoaXRzIG5hbWUpLiAqL1xuICBAT3V0cHV0KCkgdG9nZ2xlM2QgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcbiAgLyoqIFdoZXRoZXIgdGhlIHByb2plY3RlZCBjbGFzcyB0cmVlIGlzIHNob3duIGluc3RlYWQgb2YgdGhlIGxpc3Q7IG51bGw6IHRoZXJlIGlzIG5vIHRyZWUuICovXG4gIEBJbnB1dCgpIHRyZWVWaWV3OiBib29sZWFuIHwgbnVsbCA9IG51bGw7XG4gIC8qKiBUaGUgbGlzdCAvIHRyZWUgc3dpdGNoLiAqL1xuICBAT3V0cHV0KCkgdHJlZVZpZXdDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPGJvb2xlYW4+KCk7XG5cbiAgLyoqIEEgcm93IHdhcyBjbGlja2VkOiBtYWtlIHRoZSBjbGFzcyBhY3RpdmUgLyBhcHBseSBpdCB0byB0aGUgc2VsZWN0aW9uLiAqL1xuICBAT3V0cHV0KCkgcGljayA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xuICAvKiogQSBjbGFzcydzIHN3YXRjaCBwaWNrZWQgYSBuZXcgY29sb3VyLiAqL1xuICBAT3V0cHV0KCkgcmVjb2xvciA9IG5ldyBFdmVudEVtaXR0ZXI8eyBuYW1lOiBzdHJpbmc7IGNvbG9yOiBzdHJpbmcgfT4oKTtcbiAgLyoqIEEgY2xhc3MncyB0cmFzaCBidXR0b24gKGl0cyBuYW1lKS4gKi9cbiAgQE91dHB1dCgpIHJlbW92ZSA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xuICAvKiogTWFuYWdlIGNsaWNrZWQuICovXG4gIEBPdXRwdXQoKSBtYW5hZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG5cbiAgLyoqIHRyYWNrQnkgZm9yIHRoZSBjbGFzcyByb3dzIHNvIHJlLXNvcnRpbmcgZG9lc24ndCByZS1jcmVhdGUgdGhlIHBpY2tlcnMuICovXG4gIHByb3RlY3RlZCByZWFkb25seSB0cmFja0J5TmFtZSA9IChfOiBudW1iZXIsIGM6IENsYXNzUm93KTogc3RyaW5nID0+IGMubmFtZTtcblxuICAvKiogRXZlcnkgY2xhc3MncyByb3csIHJlYnVpbHQgd2hlbiBhbiBpbnB1dCBjaGFuZ2VzIHJhdGhlciB0aGFuIHBlciBjaGVjay4gKi9cbiAgcHJvdGVjdGVkIHJvd3M6IENsYXNzUm93W10gPSBbXTtcbiAgLyoqIFRoZSByb3dzIG1hdGNoaW5nIHtAbGluayBxdWVyeX0uICovXG4gIHByb3RlY3RlZCBzaG93blJvd3M6IENsYXNzUm93W10gPSBbXTtcbiAgLyoqIFRoZSBzZWFyY2ggYm94J3MgdGV4dC4gKi9cbiAgcHJvdGVjdGVkIHF1ZXJ5ID0gJyc7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSBlbDogRWxlbWVudFJlZjxIVE1MRWxlbWVudD4pIHt9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyA9IHt9KTogdm9pZCB7XG4gICAgdGhpcy5yb3dzID0gdGhpcy5jbGFzc2VzLm1hcCgoYykgPT4gKHtcbiAgICAgIG5hbWU6IGMubmFtZSxcbiAgICAgIGNvbG9yOiBjLmNvbG9yLFxuICAgICAgY291bnQ6IHRoaXMuY291bnQoYy5uYW1lKSxcbiAgICAgIGNhblJlbW92ZTogdGhpcy5jYW5SZW1vdmUoYy5uYW1lKSxcbiAgICAgIHJvd1Rvb2x0aXA6IHRoaXMucm93VG9vbHRpcChjLm5hbWUpLFxuICAgICAgcmVtb3ZlVG9vbHRpcDogdGhpcy5yZW1vdmVUb29sdGlwKGMubmFtZSksXG4gICAgfSkpO1xuICAgIHRoaXMuZmlsdGVyKCk7XG4gICAgaWYgKGNoYW5nZXNbJ3BpY2tlZCddICYmIHRoaXMucGlja2VkKVxuICAgICAgc2V0VGltZW91dCgoKSA9PiBzY3JvbGxUb1BpY2tlZCh0aGlzLmVsLm5hdGl2ZUVsZW1lbnQsICcuY2xhc3Mtcm93LnBpY2tlZCcpKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvblF1ZXJ5KHZhbHVlOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLnF1ZXJ5ID0gdmFsdWU7XG4gICAgdGhpcy5maWx0ZXIoKTtcbiAgfVxuXG4gIC8qKiBFbnRlciBpbiB0aGUgc2VhcmNoIGJveCBwaWNrcyB0aGUgZmlyc3QgbWF0Y2guICovXG4gIHByb3RlY3RlZCBwaWNrRmlyc3RNYXRjaCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5xdWVyeS50cmltKCkgJiYgdGhpcy5zaG93blJvd3MubGVuZ3RoKSB0aGlzLnBpY2suZW1pdCh0aGlzLnNob3duUm93c1swXS5uYW1lKTtcbiAgfVxuXG4gIHByaXZhdGUgZmlsdGVyKCk6IHZvaWQge1xuICAgIGNvbnN0IHEgPSB0aGlzLnF1ZXJ5LnRyaW0oKS50b0xvd2VyQ2FzZSgpO1xuICAgIHRoaXMuc2hvd25Sb3dzID0gcSA/IHRoaXMucm93cy5maWx0ZXIoKHIpID0+IHIubmFtZS50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHEpKSA6IHRoaXMucm93cztcbiAgfVxuXG4gIHByaXZhdGUgY291bnQobmFtZTogc3RyaW5nKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5jb3VudHMuZ2V0KHByZXNldEtleSh7IG1hdGNoTW9kZTogdGhpcy5tYXRjaE1vZGUgfSwgbmFtZSkpID8/IDA7XG4gIH1cblxuICBwcml2YXRlIGNhblJlbW92ZShuYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gIShuYW1lID09PSB0aGlzLmRlZmF1bHRDbGFzc05hbWUgJiYgdGhpcy5jb3VudChuYW1lKSA+IDApO1xuICB9XG5cbiAgcHJvdGVjdGVkIHJvd1Rvb2x0aXAobmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5zZWxlY3RlZENvdW50XG4gICAgICA/IGBBcHBseSDigJwke25hbWV94oCdIHRvIHRoZSBzZWxlY3RlZCByZWdpb24ocylgXG4gICAgICA6IGBTZXQg4oCcJHtuYW1lfeKAnSBhY3RpdmUg4oCUIG5ldyByZWdpb25zIHVzZSBpdGA7XG4gIH1cblxuICBwcm90ZWN0ZWQgcmVtb3ZlVG9vbHRpcChuYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGNvbnN0IGluVXNlID0gdGhpcy5jb3VudChuYW1lKSA+IDA7XG4gICAgaWYgKG5hbWUgPT09IHRoaXMuZGVmYXVsdENsYXNzTmFtZSAmJiBpblVzZSkgcmV0dXJuICdUaGUgZGVmYXVsdCBjbGFzcyBjYW5ub3QgYmUgcmVtb3ZlZCB3aGlsZSBpbiB1c2UnO1xuICAgIHJldHVybiBpblVzZSA/IGBSZW1vdmUgY2xhc3Mg4oCUIGl0cyByZWdpb25zIHJldmVydCB0byAke3RoaXMuZGVmYXVsdENsYXNzTmFtZX1gIDogJ1JlbW92ZSBjbGFzcyc7XG4gIH1cbn1cbiIsIjwhLS0gRG9ja2VkIFwiQ2xhc3Nlc1wiIHBhbmVsIChqaXQtdWkjNzApOiB0aGUgYWx3YXlzLXZpc2libGUgbGlzdCBvZiBhbm5vdGF0aW9uXG4gICAgIGNsYXNzZXMgYWJvdmUgdGhlIHJlZ2lvbnMgdGFibGUuIENsaWNrIGEgcm93IHRvIG1ha2UgaXQgdGhlIGFjdGl2ZSBjbGFzc1xuICAgICAobmV3IHJlZ2lvbnMgaW5oZXJpdCBpdDsgd2l0aCByb3dzIHNlbGVjdGVkIGl0IHJlLWNsYXNzaWZpZXMgdGhlbSk7IHJlY29sb3VyXG4gICAgIHZpYSB0aGUgc3dhdGNoOyB0aGUgYmFkZ2Ugc2hvd3MgaG93IG1hbnkgcmVnaW9ucyB1c2UgdGhlIGNsYXNzLiBcIk1hbmFnZVwiXG4gICAgIG9wZW5zIHRoZSBmdWxsIGVkaXRvciAoZmFsbGJhY2sgcGFsZXR0ZSwgYXV0by1hZGQsIG1hdGNoaW5nLCBpbXBvcnQvZXhwb3J0KS5cbiAgICAgQSByZWdpb24gc2V0IHdpdGggYSBjbGFzcyBoaWVyYXJjaHkgKGFuIGF0bGFzIG9udG9sb2d5KSBjYW4gc2hvdyBpdHMgY2xhc3Nlc1xuICAgICBhcyBhIHRyZWUgaW5zdGVhZCAocHJvamVjdGVkIGluIGJ5IHRoZSBlZGl0b3IpOyB0aGUgaGVhZGVyIHN3aXRjaGVzIHZpZXdzLiAtLT5cbjxkaXYgY2xhc3M9XCJjbGFzc2VzLXBhbmVsXCI+XG4gIDxkaXYgY2xhc3M9XCJjbGFzc2VzLXBhbmVsLWhlYWRlclwiPlxuICAgIDxzcGFuIGNsYXNzPVwiY2xhc3Nlcy1wYW5lbC10aXRsZVwiPkNsYXNzZXM8L3NwYW4+XG4gICAgPGJ1dHRvblxuICAgICAgKm5nSWY9XCJ0cmVlVmlldyAhPT0gbnVsbFwiXG4gICAgICBwQnV0dG9uXG4gICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgIFtpY29uXT1cInRyZWVWaWV3ID8gJ3BpIHBpLWxpc3QnIDogJ3BpIHBpLXNpdGVtYXAnXCJcbiAgICAgIGNsYXNzPVwicC1idXR0b24tc20gcC1idXR0b24tdGV4dFwiXG4gICAgICBbcFRvb2x0aXBdPVwidHJlZVZpZXcgPyAnU2hvdyB0aGUgY2xhc3NlcyBhcyBhIGxpc3QnIDogJ1Nob3cgdGhlIGNsYXNzZXMgYXMgYSB0cmVlJ1wiXG4gICAgICB0b29sdGlwUG9zaXRpb249XCJib3R0b21cIlxuICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCJ0cmVlVmlldyA/ICdTaG93IHRoZSBjbGFzc2VzIGFzIGEgbGlzdCcgOiAnU2hvdyB0aGUgY2xhc3NlcyBhcyBhIHRyZWUnXCJcbiAgICAgIChjbGljayk9XCJ0cmVlVmlld0NoYW5nZS5lbWl0KCF0cmVlVmlldylcIlxuICAgID48L2J1dHRvbj5cbiAgICA8YnV0dG9uXG4gICAgICBwQnV0dG9uXG4gICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgIGljb249XCJwaSBwaS1jb2dcIlxuICAgICAgbGFiZWw9XCJNYW5hZ2VcIlxuICAgICAgY2xhc3M9XCJwLWJ1dHRvbi1zbSBwLWJ1dHRvbi10ZXh0XCJcbiAgICAgIHBUb29sdGlwPVwiTWFuYWdlIGNsYXNzZXMg4oCUIGFkZCAvIHJlbW92ZSwgcGFsZXR0ZSwgbWF0Y2hpbmcsIGltcG9ydC9leHBvcnRcIlxuICAgICAgdG9vbHRpcFBvc2l0aW9uPVwiYm90dG9tXCJcbiAgICAgIChjbGljayk9XCJtYW5hZ2UuZW1pdCgpXCJcbiAgICA+PC9idXR0b24+XG4gIDwvZGl2PlxuICA8bmctY29udGFpbmVyICpuZ0lmPVwidHJlZVZpZXc7IGVsc2UgbGlzdFwiPjxuZy1jb250ZW50PjwvbmctY29udGVudD48L25nLWNvbnRhaW5lcj5cbiAgPG5nLXRlbXBsYXRlICNsaXN0PlxuICAgIDxpbnB1dFxuICAgICAgKm5nSWY9XCJjbGFzc2VzLmxlbmd0aFwiXG4gICAgICB0eXBlPVwidGV4dFwiXG4gICAgICBwSW5wdXRUZXh0XG4gICAgICBjbGFzcz1cInAtaW5wdXR0ZXh0LXNtIGNsYXNzZXMtc2VhcmNoXCJcbiAgICAgIHBsYWNlaG9sZGVyPVwiU2VhcmNoIGJ5IG5hbWVcIlxuICAgICAgYXJpYS1sYWJlbD1cIlNlYXJjaCB0aGUgY2xhc3Nlc1wiXG4gICAgICBbbmdNb2RlbF09XCJxdWVyeVwiXG4gICAgICAobmdNb2RlbENoYW5nZSk9XCJvblF1ZXJ5KCRldmVudClcIlxuICAgICAgKGtleWRvd24uZW50ZXIpPVwicGlja0ZpcnN0TWF0Y2goKVwiXG4gICAgLz5cbiAgICA8ZGl2IGNsYXNzPVwiY2xhc3Nlcy1wYW5lbC1ib2R5XCI+XG4gICAgICA8ZGl2XG4gICAgICAgICpuZ0Zvcj1cImxldCBjIG9mIHNob3duUm93czsgdHJhY2tCeTogdHJhY2tCeU5hbWVcIlxuICAgICAgICBjbGFzcz1cImNsYXNzLXJvd1wiXG4gICAgICAgIFtjbGFzcy5hY3RpdmVdPVwiYWN0aXZlQ2xhc3MgPT09IGMubmFtZVwiXG4gICAgICAgIFtjbGFzcy5waWNrZWRdPVwicGlja2VkID09PSBjLm5hbWVcIlxuICAgICAgICBbY2xhc3MubWFya2VkXT1cIm1hcmtlZC5oYXMoYy5uYW1lKVwiXG4gICAgICAgIFtjbGFzcy5oaWRkZW4tY2xhc3NdPVwiaGlkZGVuLmhhcyhjLm5hbWUpXCJcbiAgICAgICAgKGNsaWNrKT1cInBpY2suZW1pdChjLm5hbWUpXCJcbiAgICAgICAgW3BUb29sdGlwXT1cImMucm93VG9vbHRpcFwiXG4gICAgICAgIHRvb2x0aXBQb3NpdGlvbj1cImJvdHRvbVwiXG4gICAgICA+XG4gICAgICAgIDxpXG4gICAgICAgICAgY2xhc3M9XCJwaSByb3ctZXllXCJcbiAgICAgICAgICBbbmdDbGFzc109XCJoaWRkZW4uaGFzKGMubmFtZSkgPyAncGktZXllLXNsYXNoJyA6ICdwaS1leWUnXCJcbiAgICAgICAgICByb2xlPVwiYnV0dG9uXCJcbiAgICAgICAgICBbYXR0ci5hcmlhLXByZXNzZWRdPVwiIWhpZGRlbi5oYXMoYy5uYW1lKVwiXG4gICAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCIoaGlkZGVuLmhhcyhjLm5hbWUpID8gJ1Nob3cgJyA6ICdIaWRlICcpICsgYy5uYW1lXCJcbiAgICAgICAgICBbcFRvb2x0aXBdPVwiaGlkZGVuLmhhcyhjLm5hbWUpID8gJ1Nob3cgdGhpcyBjbGFzcycgOiAnSGlkZSB0aGlzIGNsYXNzJ1wiXG4gICAgICAgICAgdG9vbHRpcFBvc2l0aW9uPVwiYm90dG9tXCJcbiAgICAgICAgICAoY2xpY2spPVwiJGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpOyB0b2dnbGVIaWRkZW4uZW1pdChjLm5hbWUpXCJcbiAgICAgICAgPjwvaT5cbiAgICAgICAgPHNwYW4gY2xhc3M9XCJyb3ctc3dhdGNoXCIgKGNsaWNrKT1cIiRldmVudC5zdG9wUHJvcGFnYXRpb24oKVwiPlxuICAgICAgICAgIDxoZXgtY29sb3ItcGlja2VyIFtjb2xvcl09XCJjLmNvbG9yXCIgKGNvbG9yQ2hhbmdlKT1cInJlY29sb3IuZW1pdCh7IG5hbWU6IGMubmFtZSwgY29sb3I6ICRldmVudCB9KVwiPlxuICAgICAgICAgIDwvaGV4LWNvbG9yLXBpY2tlcj5cbiAgICAgICAgPC9zcGFuPlxuICAgICAgICA8c3BhbiBjbGFzcz1cInJvdy1uYW1lXCI+e3sgYy5uYW1lIH19PC9zcGFuPlxuICAgICAgICA8c3BhbiBjbGFzcz1cInJvdy1jb3VudFwiIFtjbGFzcy56ZXJvXT1cImMuY291bnQgPT09IDBcIj57eyBjLmNvdW50IH19PC9zcGFuPlxuICAgICAgICA8aVxuICAgICAgICAgICpuZ0lmPVwidm9sdW1lXCJcbiAgICAgICAgICBjbGFzcz1cInBpIHBpLWJveCByb3ctM2RcIlxuICAgICAgICAgIFtjbGFzcy5vbl09XCJzaG93bjNkLmhhcyhjLm5hbWUpXCJcbiAgICAgICAgICByb2xlPVwiYnV0dG9uXCJcbiAgICAgICAgICBbYXR0ci5hcmlhLXByZXNzZWRdPVwic2hvd24zZC5oYXMoYy5uYW1lKVwiXG4gICAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCInU2hvdyAnICsgYy5uYW1lICsgJyBpbiAzRCdcIlxuICAgICAgICAgIHBUb29sdGlwPVwiU2hvdyBpbiB0aGUgdm9sdW1lLCBpbiAzRFwiXG4gICAgICAgICAgdG9vbHRpcFBvc2l0aW9uPVwiYm90dG9tXCJcbiAgICAgICAgICAoY2xpY2spPVwiJGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpOyB0b2dnbGUzZC5lbWl0KGMubmFtZSlcIlxuICAgICAgICA+PC9pPlxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgcEJ1dHRvblxuICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgIGljb249XCJwaSBwaS10cmFzaFwiXG4gICAgICAgICAgY2xhc3M9XCJwLWJ1dHRvbi1zbSBwLWJ1dHRvbi10ZXh0IHAtYnV0dG9uLXdhcm5pbmcgcm93LWRlbFwiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cIiFjLmNhblJlbW92ZVwiXG4gICAgICAgICAgW3BUb29sdGlwXT1cImMucmVtb3ZlVG9vbHRpcFwiXG4gICAgICAgICAgdG9vbHRpcFBvc2l0aW9uPVwiYm90dG9tXCJcbiAgICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cIidSZW1vdmUgY2xhc3MgJyArIGMubmFtZVwiXG4gICAgICAgICAgKGNsaWNrKT1cIiRldmVudC5zdG9wUHJvcGFnYXRpb24oKTsgcmVtb3ZlLmVtaXQoYy5uYW1lKVwiXG4gICAgICAgID48L2J1dHRvbj5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiAqbmdJZj1cIiFjbGFzc2VzLmxlbmd0aFwiIGNsYXNzPVwiY2xhc3Nlcy1lbXB0eVwiPk5vIGNsYXNzZXMgeWV0IOKAlCBhZGQgb25lIGZyb20gTWFuYWdlLjwvZGl2PlxuICAgICAgPGRpdiAqbmdJZj1cImNsYXNzZXMubGVuZ3RoICYmICFzaG93blJvd3MubGVuZ3RoXCIgY2xhc3M9XCJjbGFzc2VzLWVtcHR5XCI+Tm8gY2xhc3MgbWF0Y2hlcy48L2Rpdj5cbiAgICA8L2Rpdj5cbiAgPC9uZy10ZW1wbGF0ZT5cbjwvZGl2PlxuIl19