@jax-data-science/sci-image-visualizer 0.12.1 → 0.14.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/esm2022/lib/contracts/channel-histogram-api.contract.mjs +19 -1
- package/esm2022/lib/contracts/display-types.mjs +7 -1
- package/esm2022/lib/contracts/image.contract.mjs +1 -1
- package/esm2022/lib/contracts/region-editor-api.contract.mjs +1 -1
- package/esm2022/lib/contracts/spatial-dataset.contract.mjs +1 -1
- package/esm2022/lib/contracts/visualizer.contract.mjs +1 -1
- package/esm2022/lib/geometry/reconstruct.mjs +11 -1
- package/esm2022/lib/implementations/napari-js/napari-image-2d-scene.mjs +17 -2
- package/esm2022/lib/implementations/napari-js/napari-spatial-2d-scene.mjs +88 -10
- package/esm2022/lib/implementations/napari-js/napari-spatial-3d-scene.mjs +62 -13
- package/esm2022/lib/implementations/napari-js/napari-spatial-encoding.mjs +21 -1
- package/esm2022/lib/implementations/napari-js/napari-spatial-scene.mjs +5 -1
- package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +9 -1
- package/esm2022/lib/implementations/napari-js/spatial-tiles/categorical-lookup.mjs +26 -3
- package/esm2022/lib/implementations/napari-js/spatial-tiles/cell-layers.mjs +3 -2
- package/esm2022/lib/implementations/napari-js/spatial-tiles/density-layer.mjs +20 -4
- package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-hover.mjs +4 -2
- package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-jobs.mjs +4 -2
- package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-layers.mjs +42 -15
- package/esm2022/lib/implementations/osd/openseadragon-visualizer.service.mjs +3 -1
- package/esm2022/lib/region-editor/region-editor.component.mjs +13 -1
- package/esm2022/lib/routing-visualizer.service.mjs +4 -1
- package/esm2022/lib/spatial/lod.mjs +6 -3
- package/esm2022/lib/spatial/spatial-controls.facade.mjs +78 -23
- package/esm2022/lib/spatial/spatial-gene-filter.mjs +138 -0
- package/esm2022/lib/spatial/spatial-selection.mjs +70 -1
- package/esm2022/lib/spatial/spatial-tile-merge.mjs +42 -1
- package/esm2022/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.mjs +3 -3
- package/esm2022/lib/spatial-controls/spatial-controls.component.mjs +54 -11
- package/esm2022/lib/spatial-controls/spatial-gene-style/spatial-gene-style.component.mjs +66 -0
- package/esm2022/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.mjs +106 -26
- package/esm2022/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.mjs +3 -3
- package/esm2022/lib/spatial-controls/spatial-key/spatial-key.component.mjs +3 -3
- package/esm2022/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.mjs +3 -3
- package/esm2022/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.mjs +110 -8
- package/esm2022/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.mjs +41 -9
- package/esm2022/lib/store/region-selection.mjs +21 -4
- package/esm2022/lib/store/region-store.service.mjs +22 -3
- package/esm2022/lib/store/spatial-selection.service.mjs +13 -1
- package/esm2022/lib/store/visualizer-store.service.mjs +50 -1
- package/esm2022/lib/toolbar/toolbar-help-dialog/toolbar-help-dialog.component.mjs +3 -3
- package/fesm2022/{jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-DnPlIP2F.mjs → jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-DvFp1jNH.mjs} +1777 -793
- package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-DvFp1jNH.mjs.map +1 -0
- package/fesm2022/{jax-data-science-sci-image-visualizer-onnx-sam-session-Bs987_-E.mjs → jax-data-science-sci-image-visualizer-onnx-sam-session-D7lSUAM1.mjs} +2 -2
- package/fesm2022/{jax-data-science-sci-image-visualizer-onnx-sam-session-Bs987_-E.mjs.map → jax-data-science-sci-image-visualizer-onnx-sam-session-D7lSUAM1.mjs.map} +1 -1
- package/fesm2022/jax-data-science-sci-image-visualizer.mjs +2 -2
- package/lib/contracts/channel-histogram-api.contract.d.ts +14 -0
- package/lib/contracts/display-types.d.ts +27 -0
- package/lib/contracts/image.contract.d.ts +2 -0
- package/lib/contracts/region-editor-api.contract.d.ts +3 -0
- package/lib/contracts/spatial-dataset.contract.d.ts +7 -0
- package/lib/contracts/visualizer.contract.d.ts +28 -2
- package/lib/geometry/reconstruct.d.ts +6 -0
- package/lib/implementations/napari-js/napari-image-2d-scene.d.ts +7 -0
- package/lib/implementations/napari-js/napari-spatial-2d-scene.d.ts +13 -2
- package/lib/implementations/napari-js/napari-spatial-encoding.d.ts +5 -0
- package/lib/implementations/napari-js/napari-spatial-scene.d.ts +4 -0
- package/lib/implementations/napari-js/napari-visualizer.service.d.ts +5 -0
- package/lib/implementations/napari-js/spatial-tiles/categorical-lookup.d.ts +6 -1
- package/lib/implementations/napari-js/spatial-tiles/transcript-hover.d.ts +4 -0
- package/lib/implementations/napari-js/spatial-tiles/transcript-layers.d.ts +3 -1
- package/lib/routing-visualizer.service.d.ts +1 -0
- package/lib/spatial/lod.d.ts +3 -1
- package/lib/spatial/spatial-controls.facade.d.ts +19 -2
- package/lib/spatial/spatial-gene-filter.d.ts +44 -0
- package/lib/spatial/spatial-selection.d.ts +16 -1
- package/lib/spatial/spatial-tile-merge.d.ts +17 -0
- package/lib/spatial-controls/spatial-controls.component.d.ts +14 -3
- package/lib/spatial-controls/spatial-gene-style/spatial-gene-style.component.d.ts +30 -0
- package/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.d.ts +39 -7
- package/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.d.ts +33 -1
- package/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.d.ts +13 -1
- package/lib/store/region-selection.d.ts +14 -3
- package/lib/store/region-store.service.d.ts +14 -1
- package/lib/store/spatial-selection.service.d.ts +8 -0
- package/lib/store/visualizer-store.service.d.ts +13 -0
- package/package.json +1 -1
- package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-DnPlIP2F.mjs.map +0 -1
|
@@ -13,10 +13,13 @@ import { TooltipModule } from 'primeng/tooltip';
|
|
|
13
13
|
import { TreeSelectModule } from 'primeng/treeselect';
|
|
14
14
|
import { DEFAULT_SPATIAL_VIEW, } from '../../contracts/display-types';
|
|
15
15
|
import { defaultGlyphFor } from '../../spatial/spatial-tiles';
|
|
16
|
+
import { cellTypeColumnFor } from '../../spatial/lod';
|
|
17
|
+
import { everyGeneOff } from '../../spatial/spatial-tile-merge';
|
|
16
18
|
import { GLYPH_OPTIONS, allGenesPreparingNote, densityColorBarCss, importGeneGroupsPatch, markerColumnOptions, parseGeneGroups, tileOptions, } from '../../spatial/spatial-panel-model';
|
|
17
19
|
import { colormapNodeFor } from '../spatial-key/spatial-key.component';
|
|
18
20
|
import { SpatialGeneTreeComponent } from '../spatial-gene-tree/spatial-gene-tree.component';
|
|
19
21
|
import { SpatialMarkerGenesFormComponent } from '../spatial-marker-genes-form/spatial-marker-genes-form.component';
|
|
22
|
+
import { hasGeneFilter } from '../../spatial/spatial-gene-filter';
|
|
20
23
|
import * as i0 from "@angular/core";
|
|
21
24
|
import * as i1 from "@angular/common";
|
|
22
25
|
import * as i2 from "@angular/forms";
|
|
@@ -66,11 +69,13 @@ export class SpatialTranscriptsPanelComponent {
|
|
|
66
69
|
this.openChange = new EventEmitter();
|
|
67
70
|
/** Virtual-scrolled only past this many options (see the cells panel's gene dropdown). */
|
|
68
71
|
this.geneVirtualScrollFrom = 200;
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
];
|
|
72
|
+
/**
|
|
73
|
+
* Colourings on offer: "Cell type" only for a dataset with cell types. Rebuilt only when that
|
|
74
|
+
* changes, for the same reason as {@link transcriptModeOptions}.
|
|
75
|
+
*/
|
|
76
|
+
this.transcriptColorOptions = [];
|
|
77
|
+
/** Whether the dataset has a column naming each cell's type (see `cellTypeColumnFor`). */
|
|
78
|
+
this.hasCellTypes = false;
|
|
74
79
|
this.glyphOptions = GLYPH_OPTIONS;
|
|
75
80
|
this.budgetOptions = [25_000, 50_000, 100_000, 200_000, 400_000].map((n) => ({
|
|
76
81
|
label: n.toLocaleString(),
|
|
@@ -114,6 +119,17 @@ export class SpatialTranscriptsPanelComponent {
|
|
|
114
119
|
}
|
|
115
120
|
if (changes['view'] || changes['dataset'] || changes['controls'])
|
|
116
121
|
this.geneMenu = this.buildGeneMenu();
|
|
122
|
+
if (changes['view'] || changes['dataset']) {
|
|
123
|
+
const hasCellTypes = !!this.dataset && cellTypeColumnFor(this.dataset, this.view) !== null;
|
|
124
|
+
if (hasCellTypes !== this.hasCellTypes || !this.transcriptColorOptions.length) {
|
|
125
|
+
this.hasCellTypes = hasCellTypes;
|
|
126
|
+
this.transcriptColorOptions = [
|
|
127
|
+
{ label: 'Cluster', value: 'cluster' },
|
|
128
|
+
...(hasCellTypes ? [{ label: 'Cell type', value: 'cellType' }] : []),
|
|
129
|
+
{ label: 'Gene', value: 'gene' },
|
|
130
|
+
];
|
|
131
|
+
}
|
|
132
|
+
}
|
|
117
133
|
if (changes['view'] || changes['colormapOptions']) {
|
|
118
134
|
this.selectedDensityColormapNode = colormapNodeFor(this.colormapOptions, this.view.densityColormap);
|
|
119
135
|
}
|
|
@@ -160,7 +176,10 @@ export class SpatialTranscriptsPanelComponent {
|
|
|
160
176
|
return this.canShowAllGenes && this.view.transcriptAllGenes && this.view.transcriptMode !== 'density';
|
|
161
177
|
}
|
|
162
178
|
onTranscriptAllGenes(on) {
|
|
163
|
-
|
|
179
|
+
// "All genes" switched off whole with the tree's root eye stays a property of that one visit;
|
|
180
|
+
// genes hidden one by one are kept for the next.
|
|
181
|
+
const wholeOff = everyGeneOff(this.view.transcriptAllGenesHidden);
|
|
182
|
+
this.controls?.setViewState({ transcriptAllGenes: on, ...(wholeOff ? { transcriptAllGenesHidden: [] } : {}) });
|
|
164
183
|
}
|
|
165
184
|
/** '±': every gene, or back to the chosen list. */
|
|
166
185
|
onToggleAllGenes() {
|
|
@@ -210,12 +229,25 @@ export class SpatialTranscriptsPanelComponent {
|
|
|
210
229
|
const e = this.estimate;
|
|
211
230
|
return e && e.max > 0 ? Math.min(100, (100 * e.points) / e.max) : 0;
|
|
212
231
|
}
|
|
232
|
+
/** Whether the Observations gene filter is on, which limits the transcripts drawn. */
|
|
233
|
+
get observationsFiltered() {
|
|
234
|
+
return hasGeneFilter(this.view);
|
|
235
|
+
}
|
|
213
236
|
get estimateOverMax() {
|
|
214
237
|
return !!this.estimate && this.estimate.points > this.estimate.max;
|
|
215
238
|
}
|
|
216
239
|
onTranscriptBudget(n) {
|
|
217
240
|
this.controls?.setViewState({ transcriptBudget: n });
|
|
218
241
|
}
|
|
242
|
+
/** The colouring in use: "Cell type" without cell types colours by gene (as the markers do). */
|
|
243
|
+
get transcriptColorShown() {
|
|
244
|
+
return this.view.transcriptColorBy === 'cellType' && !this.hasCellTypes ? 'gene' : this.view.transcriptColorBy;
|
|
245
|
+
}
|
|
246
|
+
/** Genes of "All genes" hidden one by one (not the whole set switched off). */
|
|
247
|
+
get allGenesSomeHidden() {
|
|
248
|
+
const off = this.view.transcriptAllGenesHidden;
|
|
249
|
+
return this.view.transcriptAllGenes && off.length > 0 && !everyGeneOff(off);
|
|
250
|
+
}
|
|
219
251
|
onTranscriptColorBy(by) {
|
|
220
252
|
this.controls?.setViewState({ transcriptColorBy: by });
|
|
221
253
|
}
|
|
@@ -323,7 +355,7 @@ export class SpatialTranscriptsPanelComponent {
|
|
|
323
355
|
];
|
|
324
356
|
}
|
|
325
357
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: SpatialTranscriptsPanelComponent, deps: [{ token: i0.NgZone }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
326
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.9", type: SpatialTranscriptsPanelComponent, isStandalone: true, selector: "spatial-transcripts-panel", inputs: { controls: "controls", dataset: "dataset", view: "view", genes: "genes", estimate: "estimate", densityStats: "densityStats", geneCounts: "geneCounts", colormapOptions: "colormapOptions", open: "open" }, outputs: { openChange: "openChange" }, viewQueries: [{ propertyName: "geneGroupFileRef", first: true, predicate: ["geneGroupFile"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"sc-panel\" [class.open]=\"open\">\n <div class=\"sc-panel-head\" (click)=\"openChange.emit(!open)\">\n <p-checkbox\n [binary]=\"true\"\n [ngModel]=\"view.transcriptMode !== 'off'\"\n (click)=\"$event.stopPropagation()\"\n (onChange)=\"onTranscriptsOn($event.checked)\"\n ></p-checkbox>\n <span class=\"sc-panel-title\">Transcripts</span>\n <i class=\"pi\" [class.pi-chevron-down]=\"open\" [class.pi-chevron-right]=\"!open\"></i>\n </div>\n <div class=\"sc-panel-body\" *ngIf=\"open\">\n <div class=\"sc-row sc-row-picker\">\n <ng-container *ngIf=\"genes?.state$ | async as gene\">\n <p-multiSelect\n inputId=\"sc-tx-genes\"\n [options]=\"gene.options\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [ngModel]=\"view.transcriptGenes\"\n (onChange)=\"onTranscriptGenes($event.value)\"\n [filter]=\"true\"\n filterBy=\"label\"\n [resetFilterOnHide]=\"true\"\n (onFilter)=\"genes?.onFilter($event.filter)\"\n (onPanelShow)=\"genes?.ensureList()\"\n [virtualScroll]=\"gene.options.length > geneVirtualScrollFrom\"\n [virtualScrollItemSize]=\"30\"\n [showToggleAll]=\"false\"\n [emptyFilterMessage]=\"gene.remote ? 'No match \u2014 keep typing' : 'No match'\"\n [emptyMessage]=\"gene.remote ? 'Type to search genes' : 'No genes'\"\n appendTo=\"body\"\n placeholder=\"Search for genes to visualize\u2026\"\n [selectedItemsLabel]=\"'{0} genes selected'\"\n [maxSelectedLabels]=\"0\"\n styleClass=\"sc-full\"\n ></p-multiSelect>\n </ng-container>\n <button\n type=\"button\"\n class=\"sc-icon-btn\"\n *ngIf=\"canShowAllGenes\"\n (click)=\"onToggleAllGenes()\"\n [class.active]=\"view.transcriptAllGenes\"\n [title]=\"view.transcriptAllGenes ? 'Back to the selected genes' : 'Select all genes'\"\n >\n \u00B1\n </button>\n <button type=\"button\" class=\"sc-icon-btn\" (click)=\"geneMenuRef.toggle($event)\" title=\"More\">\n <i class=\"pi pi-ellipsis-v\"></i>\n </button>\n <p-menu #geneMenuRef [model]=\"geneMenu\" [popup]=\"true\" appendTo=\"body\"></p-menu>\n <input\n #geneGroupFile\n type=\"file\"\n accept=\".csv,.tsv,.txt\"\n hidden\n (change)=\"onImportGeneGroups(geneGroupFile)\"\n />\n </div>\n <small class=\"sc-hint sc-error\" *ngIf=\"geneGroupError\">{{ geneGroupError }}</small>\n <small class=\"sc-hint\" *ngIf=\"allGenesPreparing\">{{ allGenesPreparing }}</small>\n\n <spatial-marker-genes-form\n [controls]=\"controls\"\n [dataset]=\"dataset\"\n [view]=\"view\"\n [open]=\"markersOpen\"\n (openChange)=\"markersOpen = $event\"\n ></spatial-marker-genes-form>\n\n <spatial-gene-tree\n [controls]=\"controls\"\n [dataset]=\"dataset\"\n [view]=\"view\"\n [geneCounts]=\"geneCounts\"\n [geneTotal]=\"geneTotal\"\n ></spatial-gene-tree>\n\n <div class=\"sc-subhead\">Transcript controls</div>\n <span class=\"sc-lbl\">View transcripts as</span>\n <p-selectButton\n [options]=\"transcriptModeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [ngModel]=\"view.transcriptMode === 'off' ? null : view.transcriptMode\"\n (ngModelChange)=\"onTranscriptMode($event)\"\n [allowEmpty]=\"false\"\n styleClass=\"sc-buttons\"\n ></p-selectButton>\n\n <ng-container *ngIf=\"estimate\">\n <div class=\"sc-row\">\n <span\n class=\"sc-lbl\"\n pTooltip=\"Transcripts of the visible genes estimated to be in view, against the most markers drawn at once\"\n tooltipPosition=\"top\"\n >Estimated Transcript Points</span\n >\n <button type=\"button\" class=\"sc-small-btn\" (click)=\"editingMax = !editingMax\">Edit Max</button>\n </div>\n <div class=\"sc-meter\">\n <div class=\"sc-meter-fill\" [class.over]=\"estimateOverMax\" [style.width.%]=\"estimatePercent\"></div>\n </div>\n <div class=\"sc-meter-ends\">\n <span>{{ estimate.points | number }} points</span>\n <span>{{ estimate.max | number }} max{{ estimateOverMax ? ' reached' : '' }}</span>\n </div>\n <div class=\"sc-row\" *ngIf=\"editingMax\">\n <span class=\"sc-lbl\">Max markers</span>\n <p-dropdown\n [options]=\"budgetOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [ngModel]=\"view.transcriptBudget\"\n (ngModelChange)=\"onTranscriptBudget($event)\"\n appendTo=\"body\"\n ></p-dropdown>\n </div>\n <small class=\"sc-hint\" *ngIf=\"estimateOverMax && view.transcriptMode !== 'density'\">\n Max points reached: transcripts are grouped by area, circles sized by how many they hold. Zoom in or select\n fewer genes to see individual points.\n </small>\n </ng-container>\n\n <ng-container *ngIf=\"view.transcriptMode === 'circles' || view.transcriptMode === 'glyphs'\">\n <div class=\"sc-row\">\n <span class=\"sc-lbl\">Colour by</span>\n <p-selectButton\n [options]=\"transcriptColorOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [ngModel]=\"view.transcriptColorBy\"\n (ngModelChange)=\"onTranscriptColorBy($event)\"\n [allowEmpty]=\"false\"\n styleClass=\"sc-buttons\"\n ></p-selectButton>\n </div>\n <small\n class=\"sc-hint\"\n *ngIf=\"view.transcriptAllGenes && view.transcriptColorBy === 'gene' && estimateOverMax\"\n >\n Grouped markers mix genes, so they are coloured by cell type until you zoom in to individual transcripts.\n </small>\n <div class=\"sc-row\" *ngIf=\"view.transcriptAllGenes && view.transcriptMode === 'glyphs'\">\n <span class=\"sc-lbl\">Icon</span>\n <p-dropdown\n [options]=\"glyphOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [ngModel]=\"glyphOf('*', 0)\"\n (ngModelChange)=\"onGlyph('*', $event)\"\n appendTo=\"body\"\n styleClass=\"sc-glyph-pick\"\n >\n <ng-template let-opt pTemplate=\"item\">\n <span class=\"sc-glyph-option\">\n <svg viewBox=\"-1.2 -1.2 2.4 2.4\" class=\"sc-glyph-svg\">\n <polygon [attr.points]=\"opt.points\"></polygon>\n </svg>\n {{ opt.label }}\n </span>\n </ng-template>\n <ng-template let-opt pTemplate=\"selectedItem\">\n <span class=\"sc-glyph-option\">\n <svg viewBox=\"-1.2 -1.2 2.4 2.4\" class=\"sc-glyph-svg\">\n <polygon [attr.points]=\"opt?.points\"></polygon>\n </svg>\n </span>\n </ng-template>\n </p-dropdown>\n </div>\n <div class=\"sc-row\">\n <span class=\"sc-lbl\">Size</span>\n <p-slider\n [ngModel]=\"view.transcriptScale\"\n [min]=\"0.5\"\n [max]=\"3\"\n [step]=\"0.25\"\n (onChange)=\"onTranscriptScale($event.value)\"\n ></p-slider>\n <span class=\"sc-val\">{{ view.transcriptScale }}\u00D7</span>\n </div>\n <div class=\"sc-row\">\n <span class=\"sc-lbl\">Opacity</span>\n <p-slider\n [ngModel]=\"view.transcriptOpacity\"\n [min]=\"0.1\"\n [max]=\"1\"\n [step]=\"0.05\"\n (onChange)=\"onTranscriptOpacity($event.value)\"\n ></p-slider>\n <span class=\"sc-val\">{{ view.transcriptOpacity }}</span>\n </div>\n <div class=\"sc-row\" *ngIf=\"!showingAllGenes\">\n <p-checkbox\n [binary]=\"true\"\n [ngModel]=\"view.transcriptQuality === 'all'\"\n inputId=\"sc-tx-lowq\"\n (onChange)=\"onTranscriptQuality($event.checked)\"\n ></p-checkbox>\n <label class=\"sc-lbl\" for=\"sc-tx-lowq\">Include low-quality calls</label>\n </div>\n </ng-container>\n\n <ng-container *ngIf=\"view.transcriptMode === 'density'\">\n <span class=\"sc-lbl\">Density map opacity</span>\n <div class=\"sc-row sc-row-number\">\n <p-slider\n [ngModel]=\"view.densityOpacity\"\n [min]=\"0.05\"\n [max]=\"1\"\n [step]=\"0.05\"\n (onChange)=\"onDensityOpacity($event.value)\"\n ></p-slider>\n <p-inputNumber\n [ngModel]=\"densityOpacityPercent\"\n (ngModelChange)=\"onDensityOpacityPercent($event)\"\n [min]=\"5\"\n [max]=\"100\"\n inputStyleClass=\"sc-num\"\n ></p-inputNumber>\n </div>\n <span class=\"sc-lbl\" pTooltip=\"Edge of each density bin\" tooltipPosition=\"top\">Density map bin size</span>\n <p-slider\n [ngModel]=\"densityBinIndex\"\n [min]=\"0\"\n [max]=\"3\"\n [step]=\"1\"\n (onChange)=\"onDensityBinIndex($event.value)\"\n styleClass=\"sc-bin-slider\"\n ></p-slider>\n <div class=\"sc-ticks\">\n <span *ngFor=\"let b of densityBins\">{{ b }}\u00D7{{ b }}\u00B5m</span>\n </div>\n <span\n class=\"sc-lbl\"\n pTooltip=\"Transcripts per \u00B5m\u00B2 at which the colour scale starts and saturates\"\n tooltipPosition=\"top\"\n >Density map scale threshold</span\n >\n <div class=\"sc-row sc-row-range\">\n <p-inputNumber\n [ngModel]=\"densityWindow[0]\"\n (ngModelChange)=\"onDensityRangeEnd(0, $event)\"\n mode=\"decimal\"\n [minFractionDigits]=\"3\"\n [maxFractionDigits]=\"3\"\n inputStyleClass=\"sc-num\"\n ></p-inputNumber>\n <p-slider\n [ngModel]=\"densityWindow\"\n [range]=\"true\"\n [min]=\"0\"\n [max]=\"densitySliderMax\"\n [step]=\"densityStep\"\n (onChange)=\"onDensityRange($event.values)\"\n ></p-slider>\n <p-inputNumber\n [ngModel]=\"densityWindow[1]\"\n (ngModelChange)=\"onDensityRangeEnd(1, $event)\"\n mode=\"decimal\"\n [minFractionDigits]=\"3\"\n [maxFractionDigits]=\"3\"\n inputStyleClass=\"sc-num\"\n ></p-inputNumber>\n </div>\n <div class=\"sc-row\">\n <small class=\"sc-hint\">{{ view.densityRange ? 'Set by hand.' : 'Derived from the data.' }}</small>\n <button type=\"button\" class=\"sc-small-btn\" *ngIf=\"view.densityRange\" (click)=\"onDensityAuto()\">\n Auto\n </button>\n </div>\n <span class=\"sc-lbl\">Density map bin coloring</span>\n <div class=\"sc-row sc-row-picker\">\n <div class=\"sc-colorbar sc-full\" [style.background]=\"densityColorBarCss\"></div>\n <p-treeSelect\n [options]=\"colormapOptions\"\n [ngModel]=\"selectedDensityColormapNode\"\n selectionMode=\"single\"\n [showClear]=\"true\"\n placeholder=\"Inferno\"\n [scrollHeight]=\"'260px'\"\n appendTo=\"body\"\n styleClass=\"sc-palette\"\n (onNodeSelect)=\"onDensityColormap($event.node)\"\n (onClear)=\"onDensityColormap(null)\"\n >\n <ng-template let-node pTemplate=\"default\">\n <span class=\"sc-cmap-option\">\n <img *ngIf=\"!node.children && node.data?.src\" [src]=\"node.data.src\" class=\"sc-cmap-swatch\" alt=\"\" />\n <span>{{ node.label }}</span>\n </span>\n </ng-template>\n </p-treeSelect>\n </div>\n <div class=\"sc-colorbar-ends\">\n <span>{{ densityWindow[0] | number: '1.0-3' }}</span\n ><span>{{ densityWindow[1] | number: '1.0-3' }}</span>\n </div>\n </ng-container>\n </div>\n</div>\n", styles: [".sc-hint{font-size:.75rem;color:var(--text-color-secondary, #6c757d)}.sc-error{color:var(--red-600, #c62828)}.sc-section{display:flex;flex-direction:column;gap:.35rem}.sc-lbl{font-size:.78rem;color:var(--text-color-secondary, #6c757d);white-space:nowrap}.sc-row{display:flex;align-items:center;gap:.6rem}.sc-row p-slider,.sc-row p-dropdown,.sc-row p-treeSelect{flex:1 1 0;min-width:0}:host ::ng-deep .sc-row p-slider .p-slider{width:100%}:host ::ng-deep .sc-row p-dropdown .p-dropdown,:host ::ng-deep .sc-row p-treeSelect .p-treeselect{width:100%}.sc-row .sc-lbl{flex:0 0 calc(50% - .6rem);min-width:0;overflow:hidden;text-overflow:ellipsis}.sc-cmap-option{display:inline-flex;align-items:center;gap:.4rem}.sc-cmap-swatch{width:3.5rem;height:.7rem;border-radius:2px;display:block}.sc-val{flex:0 0 4rem;text-align:right;font-size:.78rem;font-variant-numeric:tabular-nums;white-space:nowrap}:host ::ng-deep .sc-full,:host ::ng-deep .sc-full .p-dropdown,:host ::ng-deep .sc-full .p-autocomplete,:host ::ng-deep .sc-full input{width:100%}.sc-colorbar{height:.75rem;border-radius:2px;border:1px solid rgba(0,0,0,.2)}.sc-colorbar-ends{display:flex;justify-content:space-between;font-size:.7rem;color:var(--text-color-secondary, #6c757d);margin-top:.2rem}.sc-panel{border:1px solid var(--surface-border, #dee2e6);border-radius:6px;margin-bottom:.5rem;overflow:hidden}.sc-panel-head{display:flex;align-items:center;gap:.6rem;padding:.5rem .7rem;cursor:pointer;-webkit-user-select:none;user-select:none;background:var(--surface-100, #f5f6f7)}.sc-panel-head .sc-panel-title{flex:1;font-weight:600}.sc-panel.open>.sc-panel-head{background:var(--primary-color, #2196f3);color:var(--primary-color-text, #fff)}.sc-panel-body{display:flex;flex-direction:column;gap:.45rem;padding:.6rem .75rem .75rem}.sc-subhead{display:flex;align-items:center;gap:.5rem;margin-top:.4rem;font-size:.72rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--text-color-secondary, #6c757d)}.sc-subhead:after{content:\"\";flex:1;border-top:1px solid var(--surface-border, #dee2e6)}:host ::ng-deep .sc-buttons .p-button{padding:.35rem .75rem;font-size:.85rem}.sc-row-picker p-dropdown,.sc-row-picker p-multiSelect,.sc-row-picker p-treeSelect{flex:1 1 0;min-width:0}:host ::ng-deep .sc-row-picker .sc-variant{width:6.5rem}:host ::ng-deep .sc-row-picker p-multiselect .p-multiselect{width:100%}:host ::ng-deep .sc-row-picker p-dropdown:has(.sc-variant){flex:0 0 6.5rem}:host ::ng-deep .sc-row-picker p-treeselect:has(.sc-palette){flex:0 0 3rem}:host ::ng-deep .sc-palette .p-treeselect-label{width:0;padding:0}.sc-icon-btn{flex:0 0 auto;border:0;background:transparent;cursor:pointer;padding:.25rem .35rem;font:inherit;font-size:1.05rem;color:var(--text-color, #333);border-radius:4px}.sc-icon-btn:hover{background:var(--surface-200, #e9ecef)}.sc-icon-btn.active{color:var(--primary-color, #2196f3);font-weight:700}.sc-icon-btn:disabled{opacity:.5;cursor:default}.sc-small-btn{margin-left:auto;border:1px solid var(--surface-border, #ced4da);background:var(--surface-0, #fff);border-radius:4px;padding:.2rem .6rem;font:inherit;font-size:.8rem;cursor:pointer}:host ::ng-deep .sc-group-heading{font-size:.7rem;font-weight:700;letter-spacing:.05em;text-transform:uppercase;opacity:.7}.sc-group-list,.sc-gene-tree{max-height:16rem;overflow-y:auto;border:1px solid var(--surface-border, #dee2e6);border-radius:4px;padding:.25rem .4rem}.sc-group-row,.sc-gene-row{display:flex;align-items:center;gap:.45rem;padding:.15rem 0;font-size:.88rem}.sc-group-row .sc-group-label,.sc-gene-row .sc-group-label{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sc-group-all,.sc-gene-root,.sc-gene-group{font-weight:600}.sc-group-all .sc-icon-btn,.sc-gene-root .sc-icon-btn,.sc-gene-group .sc-icon-btn{margin-left:auto;font-size:.85rem}.sc-count{flex:0 0 auto;font-size:.78rem;color:var(--text-color-secondary, #6c757d)}.sc-glyph-option{display:inline-flex;align-items:center;gap:.4rem}.sc-glyph-svg{width:1rem;height:1rem;fill:currentColor}:host ::ng-deep .sc-glyph-pick .p-dropdown-label{padding:.2rem .4rem}.sc-color-input{width:2.5rem;height:1.8rem;border:1px solid var(--surface-border, #ced4da);border-radius:4px;padding:0;background:none}.sc-row-number p-slider,.sc-row-range p-slider{flex:1 1 0;min-width:0}:host ::ng-deep .sc-num{width:4.5rem;padding:.3rem .4rem;text-align:center}:host ::ng-deep .sc-row-number p-inputnumber,:host ::ng-deep .sc-row-range p-inputnumber{flex:0 0 auto}:host{display:contents}.sc-meter{height:.45rem;border-radius:3px;background:var(--surface-200, #e9ecef);overflow:hidden}.sc-meter-fill{height:100%;background:var(--primary-color, #2196f3)}.sc-meter-fill.over{background:var(--orange-500, #f59e0b)}.sc-meter-ends,.sc-ticks{display:flex;justify-content:space-between;font-size:.72rem;font-weight:600;color:var(--text-color-secondary, #6c757d)}\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: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1.DecimalPipe, name: "number" }, { kind: "ngmodule", type: FormsModule }, { 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: SharedModule }, { kind: "directive", type: i3.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: CheckboxModule }, { kind: "component", type: i4.Checkbox, selector: "p-checkbox", inputs: ["value", "name", "disabled", "binary", "label", "ariaLabelledBy", "ariaLabel", "tabindex", "inputId", "style", "styleClass", "labelStyleClass", "formControl", "checkboxIcon", "readonly", "required", "autofocus", "trueValue", "falseValue", "variant"], outputs: ["onChange", "onFocus", "onBlur"] }, { kind: "ngmodule", type: DropdownModule }, { kind: "component", type: i5.Dropdown, selector: "p-dropdown", inputs: ["id", "scrollHeight", "filter", "name", "style", "panelStyle", "styleClass", "panelStyleClass", "readonly", "required", "editable", "appendTo", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "variant", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "autoDisplayFirst", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "maxlength", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "autoShowPanelOnPrintableCharacterKeyDown", "disabled", "itemSize", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "filterValue", "options"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: InputNumberModule }, { kind: "component", type: i6.InputNumber, selector: "p-inputNumber", inputs: ["showButtons", "format", "buttonLayout", "inputId", "styleClass", "style", "placeholder", "size", "maxlength", "tabindex", "title", "ariaLabelledBy", "ariaLabel", "ariaRequired", "name", "required", "autocomplete", "min", "max", "incrementButtonClass", "decrementButtonClass", "incrementButtonIcon", "decrementButtonIcon", "readonly", "step", "allowEmpty", "locale", "localeMatcher", "mode", "currency", "currencyDisplay", "useGrouping", "variant", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "inputStyle", "inputStyleClass", "showClear", "autofocus", "disabled"], outputs: ["onInput", "onFocus", "onBlur", "onKeyDown", "onClear"] }, { kind: "ngmodule", type: MenuModule }, { kind: "component", type: i7.Menu, selector: "p-menu", inputs: ["model", "popup", "style", "styleClass", "appendTo", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "ariaLabel", "ariaLabelledBy", "id", "tabindex"], outputs: ["onShow", "onHide", "onBlur", "onFocus"] }, { kind: "directive", type: i8.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "ngmodule", type: MultiSelectModule }, { kind: "component", type: i9.MultiSelect, selector: "p-multiSelect", inputs: ["id", "ariaLabel", "style", "styleClass", "panelStyle", "panelStyleClass", "inputId", "disabled", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "variant", "appendTo", "dataKey", "name", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "showClear", "autofocus", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "defaultLabel", "placeholder", "options", "filterValue", "itemSize", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { kind: "ngmodule", type: SelectButtonModule }, { kind: "component", type: i10.SelectButton, selector: "p-selectButton", inputs: ["options", "optionLabel", "optionValue", "optionDisabled", "unselectable", "tabindex", "multiple", "allowEmpty", "style", "styleClass", "ariaLabelledBy", "disabled", "dataKey", "autofocus"], outputs: ["onOptionClick", "onChange"] }, { kind: "ngmodule", type: SliderModule }, { kind: "component", type: i11.Slider, selector: "p-slider", inputs: ["animate", "disabled", "min", "max", "orientation", "step", "range", "style", "styleClass", "ariaLabel", "ariaLabelledBy", "tabindex", "autofocus"], outputs: ["onChange", "onSlideEnd"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "ngmodule", type: TreeSelectModule }, { kind: "component", type: i12.TreeSelect, selector: "p-treeSelect", inputs: ["inputId", "scrollHeight", "disabled", "metaKeySelection", "variant", "display", "selectionMode", "tabindex", "ariaLabel", "ariaLabelledBy", "placeholder", "panelClass", "panelStyle", "panelStyleClass", "containerStyle", "containerStyleClass", "labelStyle", "labelStyleClass", "overlayOptions", "emptyMessage", "appendTo", "filter", "filterBy", "filterMode", "filterPlaceholder", "filterLocale", "filterInputAutoFocus", "propagateSelectionDown", "propagateSelectionUp", "showClear", "resetFilterOnHide", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "autofocus", "options", "showTransitionOptions", "hideTransitionOptions", "loading"], outputs: ["onNodeExpand", "onNodeCollapse", "onShow", "onHide", "onClear", "onFilter", "onFocus", "onBlur", "onNodeUnselect", "onNodeSelect"] }, { kind: "component", type: SpatialGeneTreeComponent, selector: "spatial-gene-tree", inputs: ["controls", "dataset", "view", "geneCounts", "geneTotal"] }, { kind: "component", type: SpatialMarkerGenesFormComponent, selector: "spatial-marker-genes-form", inputs: ["controls", "dataset", "view", "open"], outputs: ["openChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
358
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.9", type: SpatialTranscriptsPanelComponent, isStandalone: true, selector: "spatial-transcripts-panel", inputs: { controls: "controls", dataset: "dataset", view: "view", genes: "genes", estimate: "estimate", densityStats: "densityStats", geneCounts: "geneCounts", colormapOptions: "colormapOptions", open: "open" }, outputs: { openChange: "openChange" }, viewQueries: [{ propertyName: "geneGroupFileRef", first: true, predicate: ["geneGroupFile"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"sc-panel\" [class.open]=\"open\">\n <div class=\"sc-panel-head\" (click)=\"openChange.emit(!open)\">\n <p-checkbox\n [binary]=\"true\"\n [ngModel]=\"view.transcriptMode !== 'off'\"\n (click)=\"$event.stopPropagation()\"\n (onChange)=\"onTranscriptsOn($event.checked)\"\n ></p-checkbox>\n <span class=\"sc-panel-title\">Transcripts</span>\n <i class=\"pi\" [class.pi-chevron-down]=\"open\" [class.pi-chevron-right]=\"!open\"></i>\n </div>\n <div class=\"sc-panel-body\" *ngIf=\"open\">\n <div class=\"sc-row sc-row-picker\">\n <ng-container *ngIf=\"genes?.state$ | async as gene\">\n <p-multiSelect\n inputId=\"sc-tx-genes\"\n [options]=\"gene.options\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [ngModel]=\"view.transcriptGenes\"\n (onChange)=\"onTranscriptGenes($event.value)\"\n [filter]=\"true\"\n filterBy=\"label\"\n [resetFilterOnHide]=\"true\"\n (onFilter)=\"genes?.onFilter($event.filter)\"\n (onPanelShow)=\"genes?.ensureList()\"\n [virtualScroll]=\"gene.options.length > geneVirtualScrollFrom\"\n [virtualScrollItemSize]=\"30\"\n [showToggleAll]=\"false\"\n [emptyFilterMessage]=\"gene.remote ? 'No match \u2014 keep typing' : 'No match'\"\n [emptyMessage]=\"gene.remote ? 'Type to search genes' : 'No genes'\"\n appendTo=\"body\"\n placeholder=\"Search for genes to visualize\u2026\"\n [selectedItemsLabel]=\"'{0} genes selected'\"\n [maxSelectedLabels]=\"0\"\n styleClass=\"sc-full\"\n ></p-multiSelect>\n </ng-container>\n <button\n type=\"button\"\n class=\"sc-icon-btn\"\n *ngIf=\"canShowAllGenes\"\n (click)=\"onToggleAllGenes()\"\n [class.active]=\"view.transcriptAllGenes\"\n [title]=\"view.transcriptAllGenes ? 'Back to the selected genes' : 'Select all genes'\"\n >\n \u00B1\n </button>\n <button type=\"button\" class=\"sc-icon-btn\" (click)=\"geneMenuRef.toggle($event)\" title=\"More\">\n <i class=\"pi pi-ellipsis-v\"></i>\n </button>\n <p-menu #geneMenuRef [model]=\"geneMenu\" [popup]=\"true\" appendTo=\"body\"></p-menu>\n <input\n #geneGroupFile\n type=\"file\"\n accept=\".csv,.tsv,.txt\"\n hidden\n (change)=\"onImportGeneGroups(geneGroupFile)\"\n />\n </div>\n <small class=\"sc-hint sc-error\" *ngIf=\"geneGroupError\">{{ geneGroupError }}</small>\n <small class=\"sc-hint\" *ngIf=\"allGenesPreparing\">{{ allGenesPreparing }}</small>\n\n <spatial-marker-genes-form\n [controls]=\"controls\"\n [dataset]=\"dataset\"\n [view]=\"view\"\n [open]=\"markersOpen\"\n (openChange)=\"markersOpen = $event\"\n ></spatial-marker-genes-form>\n\n <spatial-gene-tree\n [controls]=\"controls\"\n [dataset]=\"dataset\"\n [view]=\"view\"\n [geneCounts]=\"geneCounts\"\n [geneTotal]=\"geneTotal\"\n ></spatial-gene-tree>\n\n <div class=\"sc-subhead\">Transcript controls</div>\n <span class=\"sc-lbl\">View transcripts as</span>\n <p-selectButton\n [options]=\"transcriptModeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [ngModel]=\"view.transcriptMode === 'off' ? null : view.transcriptMode\"\n (ngModelChange)=\"onTranscriptMode($event)\"\n [allowEmpty]=\"false\"\n styleClass=\"sc-buttons\"\n ></p-selectButton>\n\n <ng-container *ngIf=\"estimate\">\n <div class=\"sc-row\">\n <span\n class=\"sc-lbl\"\n pTooltip=\"Transcripts of the visible genes estimated to be in view, against the most markers drawn at once\"\n tooltipPosition=\"top\"\n >Estimated Transcript Points</span\n >\n <button type=\"button\" class=\"sc-small-btn\" (click)=\"editingMax = !editingMax\">Edit Max</button>\n </div>\n <div class=\"sc-meter\">\n <div class=\"sc-meter-fill\" [class.over]=\"estimateOverMax\" [style.width.%]=\"estimatePercent\"></div>\n </div>\n <div class=\"sc-meter-ends\">\n <span>{{ estimate.points | number }} points</span>\n <span>{{ estimate.max | number }} max{{ estimateOverMax ? ' reached' : '' }}</span>\n </div>\n <div class=\"sc-row\" *ngIf=\"editingMax\">\n <span class=\"sc-lbl\">Max markers</span>\n <p-dropdown\n [options]=\"budgetOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [ngModel]=\"view.transcriptBudget\"\n (ngModelChange)=\"onTranscriptBudget($event)\"\n appendTo=\"body\"\n ></p-dropdown>\n </div>\n <small class=\"sc-hint\" *ngIf=\"estimateOverMax && view.transcriptMode !== 'density'\">\n Max points reached: transcripts are grouped by area, circles sized by how many they hold. Zoom in or select\n fewer genes to see individual points.\n </small>\n </ng-container>\n\n <!-- The density raster and the grouped markers drawn from it carry no cells, so they\n cannot follow the Observations gene filter: they are not drawn while it is on. -->\n <small class=\"sc-hint\" *ngIf=\"observationsFiltered && view.transcriptMode === 'density'\">\n Observations are filtered by gene, and the density map sums every cell's transcripts, so it is hidden. Use\n Circles or Icons to see the transcripts of the observations shown.\n </small>\n <small\n class=\"sc-hint\"\n *ngIf=\"observationsFiltered && (view.transcriptMode === 'circles' || view.transcriptMode === 'glyphs')\"\n >\n Observations are filtered by gene: only the transcripts of the observations shown are drawn. Transcripts\n grouped by area when zoomed out carry no cells, so they are hidden; zoom in to see them.\n </small>\n\n <ng-container *ngIf=\"view.transcriptMode === 'circles' || view.transcriptMode === 'glyphs'\">\n <div class=\"sc-row\">\n <span class=\"sc-lbl\">Colour by</span>\n <p-selectButton\n [options]=\"transcriptColorOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [ngModel]=\"transcriptColorShown\"\n (ngModelChange)=\"onTranscriptColorBy($event)\"\n [allowEmpty]=\"false\"\n styleClass=\"sc-buttons\"\n ></p-selectButton>\n </div>\n <ng-container *ngIf=\"view.transcriptAllGenes && estimateOverMax\">\n <small class=\"sc-hint\" *ngIf=\"hasCellTypes && transcriptColorShown !== 'cellType'\">\n Grouped markers mix genes, so they are coloured by cell type until you zoom in to individual transcripts.\n </small>\n <small class=\"sc-hint\" *ngIf=\"!hasCellTypes\">\n Grouped markers mix genes and this dataset has no cell types, so they are drawn in one colour until you\n zoom in to individual transcripts.\n </small>\n <small class=\"sc-hint\" *ngIf=\"allGenesSomeHidden\">\n Grouped markers hold every gene: hidden genes are left out once you zoom in to individual transcripts.\n </small>\n </ng-container>\n <div class=\"sc-row\" *ngIf=\"view.transcriptAllGenes && view.transcriptMode === 'glyphs'\">\n <span class=\"sc-lbl\">Icon</span>\n <p-dropdown\n [options]=\"glyphOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [ngModel]=\"glyphOf('*', 0)\"\n (ngModelChange)=\"onGlyph('*', $event)\"\n appendTo=\"body\"\n styleClass=\"sc-glyph-pick\"\n >\n <ng-template let-opt pTemplate=\"item\">\n <span class=\"sc-glyph-option\">\n <svg viewBox=\"-1.2 -1.2 2.4 2.4\" class=\"sc-glyph-svg\">\n <polygon [attr.points]=\"opt.points\"></polygon>\n </svg>\n {{ opt.label }}\n </span>\n </ng-template>\n <ng-template let-opt pTemplate=\"selectedItem\">\n <span class=\"sc-glyph-option\">\n <svg viewBox=\"-1.2 -1.2 2.4 2.4\" class=\"sc-glyph-svg\">\n <polygon [attr.points]=\"opt?.points\"></polygon>\n </svg>\n </span>\n </ng-template>\n </p-dropdown>\n </div>\n <div class=\"sc-row\">\n <span class=\"sc-lbl\">Size</span>\n <p-slider\n [ngModel]=\"view.transcriptScale\"\n [min]=\"0.5\"\n [max]=\"3\"\n [step]=\"0.25\"\n (onChange)=\"onTranscriptScale($event.value)\"\n ></p-slider>\n <span class=\"sc-val\">{{ view.transcriptScale }}\u00D7</span>\n </div>\n <div class=\"sc-row\">\n <span class=\"sc-lbl\">Opacity</span>\n <p-slider\n [ngModel]=\"view.transcriptOpacity\"\n [min]=\"0.1\"\n [max]=\"1\"\n [step]=\"0.05\"\n (onChange)=\"onTranscriptOpacity($event.value)\"\n ></p-slider>\n <span class=\"sc-val\">{{ view.transcriptOpacity }}</span>\n </div>\n <div class=\"sc-row\" *ngIf=\"!showingAllGenes\">\n <p-checkbox\n [binary]=\"true\"\n [ngModel]=\"view.transcriptQuality === 'all'\"\n inputId=\"sc-tx-lowq\"\n (onChange)=\"onTranscriptQuality($event.checked)\"\n ></p-checkbox>\n <label class=\"sc-lbl\" for=\"sc-tx-lowq\">Include low-quality calls</label>\n </div>\n </ng-container>\n\n <ng-container *ngIf=\"view.transcriptMode === 'density'\">\n <span class=\"sc-lbl\">Density map opacity</span>\n <div class=\"sc-row sc-row-number\">\n <p-slider\n [ngModel]=\"view.densityOpacity\"\n [min]=\"0.05\"\n [max]=\"1\"\n [step]=\"0.05\"\n (onChange)=\"onDensityOpacity($event.value)\"\n ></p-slider>\n <p-inputNumber\n [ngModel]=\"densityOpacityPercent\"\n (ngModelChange)=\"onDensityOpacityPercent($event)\"\n [min]=\"5\"\n [max]=\"100\"\n inputStyleClass=\"sc-num\"\n ></p-inputNumber>\n </div>\n <span class=\"sc-lbl\" pTooltip=\"Edge of each density bin\" tooltipPosition=\"top\">Density map bin size</span>\n <p-slider\n [ngModel]=\"densityBinIndex\"\n [min]=\"0\"\n [max]=\"3\"\n [step]=\"1\"\n (onChange)=\"onDensityBinIndex($event.value)\"\n styleClass=\"sc-bin-slider\"\n ></p-slider>\n <div class=\"sc-ticks\">\n <span *ngFor=\"let b of densityBins\">{{ b }}\u00D7{{ b }}\u00B5m</span>\n </div>\n <span\n class=\"sc-lbl\"\n pTooltip=\"Transcripts per \u00B5m\u00B2 at which the colour scale starts and saturates\"\n tooltipPosition=\"top\"\n >Density map scale threshold</span\n >\n <div class=\"sc-row sc-row-range\">\n <p-inputNumber\n [ngModel]=\"densityWindow[0]\"\n (ngModelChange)=\"onDensityRangeEnd(0, $event)\"\n mode=\"decimal\"\n [minFractionDigits]=\"3\"\n [maxFractionDigits]=\"3\"\n inputStyleClass=\"sc-num\"\n ></p-inputNumber>\n <p-slider\n [ngModel]=\"densityWindow\"\n [range]=\"true\"\n [min]=\"0\"\n [max]=\"densitySliderMax\"\n [step]=\"densityStep\"\n (onChange)=\"onDensityRange($event.values)\"\n ></p-slider>\n <p-inputNumber\n [ngModel]=\"densityWindow[1]\"\n (ngModelChange)=\"onDensityRangeEnd(1, $event)\"\n mode=\"decimal\"\n [minFractionDigits]=\"3\"\n [maxFractionDigits]=\"3\"\n inputStyleClass=\"sc-num\"\n ></p-inputNumber>\n </div>\n <div class=\"sc-row\">\n <small class=\"sc-hint\">{{ view.densityRange ? 'Set by hand.' : 'Derived from the data.' }}</small>\n <button type=\"button\" class=\"sc-small-btn\" *ngIf=\"view.densityRange\" (click)=\"onDensityAuto()\">\n Auto\n </button>\n </div>\n <span class=\"sc-lbl\">Density map bin coloring</span>\n <div class=\"sc-row sc-row-picker\">\n <div class=\"sc-colorbar sc-full\" [style.background]=\"densityColorBarCss\"></div>\n <p-treeSelect\n [options]=\"colormapOptions\"\n [ngModel]=\"selectedDensityColormapNode\"\n selectionMode=\"single\"\n [showClear]=\"true\"\n placeholder=\"Inferno\"\n [scrollHeight]=\"'260px'\"\n appendTo=\"body\"\n styleClass=\"sc-palette\"\n (onNodeSelect)=\"onDensityColormap($event.node)\"\n (onClear)=\"onDensityColormap(null)\"\n >\n <ng-template let-node pTemplate=\"default\">\n <span class=\"sc-cmap-option\">\n <img *ngIf=\"!node.children && node.data?.src\" [src]=\"node.data.src\" class=\"sc-cmap-swatch\" alt=\"\" />\n <span>{{ node.label }}</span>\n </span>\n </ng-template>\n </p-treeSelect>\n </div>\n <div class=\"sc-colorbar-ends\">\n <span>{{ densityWindow[0] | number: '1.0-3' }}</span\n ><span>{{ densityWindow[1] | number: '1.0-3' }}</span>\n </div>\n </ng-container>\n </div>\n</div>\n", styles: [".sc-hint{font-size:.75rem;color:var(--text-color-secondary, #6c757d)}.sc-error{color:var(--red-600, #c62828)}.sc-section{display:flex;flex-direction:column;gap:.35rem}.sc-lbl{font-size:.78rem;color:var(--text-color-secondary, #6c757d);white-space:nowrap}.sc-row{display:flex;align-items:center;gap:.6rem}.sc-row p-slider,.sc-row p-dropdown,.sc-row p-treeSelect{flex:1 1 0;min-width:0}:host ::ng-deep .sc-row p-slider .p-slider{width:100%}:host ::ng-deep .sc-row p-dropdown .p-dropdown,:host ::ng-deep .sc-row p-treeSelect .p-treeselect{width:100%}.sc-row .sc-lbl{flex:0 0 calc(50% - .6rem);min-width:0;overflow:hidden;text-overflow:ellipsis}.sc-cmap-option{display:inline-flex;align-items:center;gap:.4rem}.sc-cmap-swatch{width:3.5rem;height:.7rem;border-radius:2px;display:block}.sc-val{flex:0 0 4rem;text-align:right;font-size:.78rem;font-variant-numeric:tabular-nums;white-space:nowrap}:host ::ng-deep .sc-full,:host ::ng-deep .sc-full .p-dropdown,:host ::ng-deep .sc-full .p-autocomplete,:host ::ng-deep .sc-full input{width:100%}.sc-colorbar{height:.75rem;border-radius:2px;border:1px solid rgba(0,0,0,.2)}.sc-colorbar-ends{display:flex;justify-content:space-between;font-size:.7rem;color:var(--text-color-secondary, #6c757d);margin-top:.2rem}.sc-panel{border:1px solid var(--surface-border, #dee2e6);border-radius:6px;margin-bottom:.5rem;overflow:hidden}.sc-panel-head{display:flex;align-items:center;gap:.6rem;padding:.5rem .7rem;cursor:pointer;-webkit-user-select:none;user-select:none;background:var(--surface-100, #f5f6f7)}.sc-panel-head .sc-panel-title{flex:1;font-weight:600}.sc-panel.open>.sc-panel-head{background:var(--primary-color, #2196f3);color:var(--primary-color-text, #fff)}.sc-panel-body{display:flex;flex-direction:column;gap:.45rem;padding:.6rem .75rem .75rem}.sc-subhead{display:flex;align-items:center;gap:.5rem;margin-top:.4rem;font-size:.72rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--text-color-secondary, #6c757d)}.sc-subhead:after{content:\"\";flex:1;border-top:1px solid var(--surface-border, #dee2e6)}:host ::ng-deep .sc-buttons .p-button{padding:.35rem .75rem;font-size:.85rem}.sc-row-picker p-dropdown,.sc-row-picker p-multiSelect,.sc-row-picker p-treeSelect{flex:1 1 0;min-width:0}:host ::ng-deep .sc-row-picker .sc-variant{width:6.5rem}:host ::ng-deep .sc-row-picker p-multiselect .p-multiselect{width:100%}:host ::ng-deep .sc-row-picker p-dropdown:has(.sc-variant){flex:0 0 6.5rem}:host ::ng-deep .sc-row-picker p-treeselect:has(.sc-palette){flex:0 0 3rem}:host ::ng-deep .sc-palette .p-treeselect-label{width:0;padding:0}.sc-icon-btn{flex:0 0 auto;border:0;background:transparent;cursor:pointer;padding:.25rem .35rem;font:inherit;font-size:1.05rem;color:var(--text-color, #333);border-radius:4px}.sc-icon-btn:hover{background:var(--surface-200, #e9ecef)}.sc-icon-btn.active{color:var(--primary-color, #2196f3);font-weight:700}.sc-icon-btn:disabled{opacity:.5;cursor:default}.sc-small-btn{margin-left:auto;border:1px solid var(--surface-border, #ced4da);background:var(--surface-0, #fff);border-radius:4px;padding:.2rem .6rem;font:inherit;font-size:.8rem;cursor:pointer}:host ::ng-deep .sc-group-heading{font-size:.7rem;font-weight:700;letter-spacing:.05em;text-transform:uppercase;opacity:.7}.sc-group-list,.sc-gene-tree{max-height:16rem;overflow-y:auto;border:1px solid var(--surface-border, #dee2e6);border-radius:4px;padding:.25rem .4rem}.sc-group-row,.sc-gene-row{display:flex;align-items:center;gap:.45rem;padding:.15rem 0;font-size:.88rem}.sc-group-row .sc-group-label,.sc-gene-row .sc-group-label{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sc-group-all,.sc-gene-root,.sc-gene-group{font-weight:600}.sc-group-all .sc-icon-btn,.sc-gene-root .sc-icon-btn,.sc-gene-group .sc-icon-btn{margin-left:auto;font-size:.85rem}.sc-count{flex:0 0 auto;font-size:.78rem;color:var(--text-color-secondary, #6c757d)}.sc-glyph-option{display:inline-flex;align-items:center;gap:.4rem}.sc-glyph-svg{width:1rem;height:1rem;fill:currentColor}:host ::ng-deep .sc-glyph-pick .p-dropdown-label{padding:.2rem .4rem}.sc-color-input{width:2.5rem;height:1.8rem;border:1px solid var(--surface-border, #ced4da);border-radius:4px;padding:0;background:none}.sc-row-number p-slider,.sc-row-range p-slider{flex:1 1 0;min-width:0}:host ::ng-deep .sc-num{width:4.5rem;padding:.3rem .4rem;text-align:center}:host ::ng-deep .sc-row-number p-inputnumber,:host ::ng-deep .sc-row-range p-inputnumber{flex:0 0 auto}.sc-gene-icon{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:1.4rem;height:1.4rem;padding:0;border:1px solid transparent;border-radius:4px;background:transparent;cursor:pointer}.sc-gene-icon:hover,.sc-gene-icon:focus-visible{border-color:var(--surface-border, rgba(0, 0, 0, .2))}:host{display:contents}.sc-meter{height:.45rem;border-radius:3px;background:var(--surface-200, #e9ecef);overflow:hidden}.sc-meter-fill{height:100%;background:var(--primary-color, #2196f3)}.sc-meter-fill.over{background:var(--orange-500, #f59e0b)}.sc-meter-ends,.sc-ticks{display:flex;justify-content:space-between;font-size:.72rem;font-weight:600;color:var(--text-color-secondary, #6c757d)}\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: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1.DecimalPipe, name: "number" }, { kind: "ngmodule", type: FormsModule }, { 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: SharedModule }, { kind: "directive", type: i3.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: CheckboxModule }, { kind: "component", type: i4.Checkbox, selector: "p-checkbox", inputs: ["value", "name", "disabled", "binary", "label", "ariaLabelledBy", "ariaLabel", "tabindex", "inputId", "style", "styleClass", "labelStyleClass", "formControl", "checkboxIcon", "readonly", "required", "autofocus", "trueValue", "falseValue", "variant"], outputs: ["onChange", "onFocus", "onBlur"] }, { kind: "ngmodule", type: DropdownModule }, { kind: "component", type: i5.Dropdown, selector: "p-dropdown", inputs: ["id", "scrollHeight", "filter", "name", "style", "panelStyle", "styleClass", "panelStyleClass", "readonly", "required", "editable", "appendTo", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "variant", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "autoDisplayFirst", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "maxlength", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "autoShowPanelOnPrintableCharacterKeyDown", "disabled", "itemSize", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "filterValue", "options"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: InputNumberModule }, { kind: "component", type: i6.InputNumber, selector: "p-inputNumber", inputs: ["showButtons", "format", "buttonLayout", "inputId", "styleClass", "style", "placeholder", "size", "maxlength", "tabindex", "title", "ariaLabelledBy", "ariaLabel", "ariaRequired", "name", "required", "autocomplete", "min", "max", "incrementButtonClass", "decrementButtonClass", "incrementButtonIcon", "decrementButtonIcon", "readonly", "step", "allowEmpty", "locale", "localeMatcher", "mode", "currency", "currencyDisplay", "useGrouping", "variant", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "inputStyle", "inputStyleClass", "showClear", "autofocus", "disabled"], outputs: ["onInput", "onFocus", "onBlur", "onKeyDown", "onClear"] }, { kind: "ngmodule", type: MenuModule }, { kind: "component", type: i7.Menu, selector: "p-menu", inputs: ["model", "popup", "style", "styleClass", "appendTo", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "ariaLabel", "ariaLabelledBy", "id", "tabindex"], outputs: ["onShow", "onHide", "onBlur", "onFocus"] }, { kind: "directive", type: i8.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "ngmodule", type: MultiSelectModule }, { kind: "component", type: i9.MultiSelect, selector: "p-multiSelect", inputs: ["id", "ariaLabel", "style", "styleClass", "panelStyle", "panelStyleClass", "inputId", "disabled", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "variant", "appendTo", "dataKey", "name", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "showClear", "autofocus", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "defaultLabel", "placeholder", "options", "filterValue", "itemSize", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { kind: "ngmodule", type: SelectButtonModule }, { kind: "component", type: i10.SelectButton, selector: "p-selectButton", inputs: ["options", "optionLabel", "optionValue", "optionDisabled", "unselectable", "tabindex", "multiple", "allowEmpty", "style", "styleClass", "ariaLabelledBy", "disabled", "dataKey", "autofocus"], outputs: ["onOptionClick", "onChange"] }, { kind: "ngmodule", type: SliderModule }, { kind: "component", type: i11.Slider, selector: "p-slider", inputs: ["animate", "disabled", "min", "max", "orientation", "step", "range", "style", "styleClass", "ariaLabel", "ariaLabelledBy", "tabindex", "autofocus"], outputs: ["onChange", "onSlideEnd"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "ngmodule", type: TreeSelectModule }, { kind: "component", type: i12.TreeSelect, selector: "p-treeSelect", inputs: ["inputId", "scrollHeight", "disabled", "metaKeySelection", "variant", "display", "selectionMode", "tabindex", "ariaLabel", "ariaLabelledBy", "placeholder", "panelClass", "panelStyle", "panelStyleClass", "containerStyle", "containerStyleClass", "labelStyle", "labelStyleClass", "overlayOptions", "emptyMessage", "appendTo", "filter", "filterBy", "filterMode", "filterPlaceholder", "filterLocale", "filterInputAutoFocus", "propagateSelectionDown", "propagateSelectionUp", "showClear", "resetFilterOnHide", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "autofocus", "options", "showTransitionOptions", "hideTransitionOptions", "loading"], outputs: ["onNodeExpand", "onNodeCollapse", "onShow", "onHide", "onClear", "onFilter", "onFocus", "onBlur", "onNodeUnselect", "onNodeSelect"] }, { kind: "component", type: SpatialGeneTreeComponent, selector: "spatial-gene-tree", inputs: ["controls", "dataset", "view", "geneCounts", "geneTotal"] }, { kind: "component", type: SpatialMarkerGenesFormComponent, selector: "spatial-marker-genes-form", inputs: ["controls", "dataset", "view", "open"], outputs: ["openChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
327
359
|
}
|
|
328
360
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: SpatialTranscriptsPanelComponent, decorators: [{
|
|
329
361
|
type: Component,
|
|
@@ -342,7 +374,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImpor
|
|
|
342
374
|
TreeSelectModule,
|
|
343
375
|
SpatialGeneTreeComponent,
|
|
344
376
|
SpatialMarkerGenesFormComponent,
|
|
345
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sc-panel\" [class.open]=\"open\">\n <div class=\"sc-panel-head\" (click)=\"openChange.emit(!open)\">\n <p-checkbox\n [binary]=\"true\"\n [ngModel]=\"view.transcriptMode !== 'off'\"\n (click)=\"$event.stopPropagation()\"\n (onChange)=\"onTranscriptsOn($event.checked)\"\n ></p-checkbox>\n <span class=\"sc-panel-title\">Transcripts</span>\n <i class=\"pi\" [class.pi-chevron-down]=\"open\" [class.pi-chevron-right]=\"!open\"></i>\n </div>\n <div class=\"sc-panel-body\" *ngIf=\"open\">\n <div class=\"sc-row sc-row-picker\">\n <ng-container *ngIf=\"genes?.state$ | async as gene\">\n <p-multiSelect\n inputId=\"sc-tx-genes\"\n [options]=\"gene.options\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [ngModel]=\"view.transcriptGenes\"\n (onChange)=\"onTranscriptGenes($event.value)\"\n [filter]=\"true\"\n filterBy=\"label\"\n [resetFilterOnHide]=\"true\"\n (onFilter)=\"genes?.onFilter($event.filter)\"\n (onPanelShow)=\"genes?.ensureList()\"\n [virtualScroll]=\"gene.options.length > geneVirtualScrollFrom\"\n [virtualScrollItemSize]=\"30\"\n [showToggleAll]=\"false\"\n [emptyFilterMessage]=\"gene.remote ? 'No match \u2014 keep typing' : 'No match'\"\n [emptyMessage]=\"gene.remote ? 'Type to search genes' : 'No genes'\"\n appendTo=\"body\"\n placeholder=\"Search for genes to visualize\u2026\"\n [selectedItemsLabel]=\"'{0} genes selected'\"\n [maxSelectedLabels]=\"0\"\n styleClass=\"sc-full\"\n ></p-multiSelect>\n </ng-container>\n <button\n type=\"button\"\n class=\"sc-icon-btn\"\n *ngIf=\"canShowAllGenes\"\n (click)=\"onToggleAllGenes()\"\n [class.active]=\"view.transcriptAllGenes\"\n [title]=\"view.transcriptAllGenes ? 'Back to the selected genes' : 'Select all genes'\"\n >\n \u00B1\n </button>\n <button type=\"button\" class=\"sc-icon-btn\" (click)=\"geneMenuRef.toggle($event)\" title=\"More\">\n <i class=\"pi pi-ellipsis-v\"></i>\n </button>\n <p-menu #geneMenuRef [model]=\"geneMenu\" [popup]=\"true\" appendTo=\"body\"></p-menu>\n <input\n #geneGroupFile\n type=\"file\"\n accept=\".csv,.tsv,.txt\"\n hidden\n (change)=\"onImportGeneGroups(geneGroupFile)\"\n />\n </div>\n <small class=\"sc-hint sc-error\" *ngIf=\"geneGroupError\">{{ geneGroupError }}</small>\n <small class=\"sc-hint\" *ngIf=\"allGenesPreparing\">{{ allGenesPreparing }}</small>\n\n <spatial-marker-genes-form\n [controls]=\"controls\"\n [dataset]=\"dataset\"\n [view]=\"view\"\n [open]=\"markersOpen\"\n (openChange)=\"markersOpen = $event\"\n ></spatial-marker-genes-form>\n\n <spatial-gene-tree\n [controls]=\"controls\"\n [dataset]=\"dataset\"\n [view]=\"view\"\n [geneCounts]=\"geneCounts\"\n [geneTotal]=\"geneTotal\"\n ></spatial-gene-tree>\n\n <div class=\"sc-subhead\">Transcript controls</div>\n <span class=\"sc-lbl\">View transcripts as</span>\n <p-selectButton\n [options]=\"transcriptModeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [ngModel]=\"view.transcriptMode === 'off' ? null : view.transcriptMode\"\n (ngModelChange)=\"onTranscriptMode($event)\"\n [allowEmpty]=\"false\"\n styleClass=\"sc-buttons\"\n ></p-selectButton>\n\n <ng-container *ngIf=\"estimate\">\n <div class=\"sc-row\">\n <span\n class=\"sc-lbl\"\n pTooltip=\"Transcripts of the visible genes estimated to be in view, against the most markers drawn at once\"\n tooltipPosition=\"top\"\n >Estimated Transcript Points</span\n >\n <button type=\"button\" class=\"sc-small-btn\" (click)=\"editingMax = !editingMax\">Edit Max</button>\n </div>\n <div class=\"sc-meter\">\n <div class=\"sc-meter-fill\" [class.over]=\"estimateOverMax\" [style.width.%]=\"estimatePercent\"></div>\n </div>\n <div class=\"sc-meter-ends\">\n <span>{{ estimate.points | number }} points</span>\n <span>{{ estimate.max | number }} max{{ estimateOverMax ? ' reached' : '' }}</span>\n </div>\n <div class=\"sc-row\" *ngIf=\"editingMax\">\n <span class=\"sc-lbl\">Max markers</span>\n <p-dropdown\n [options]=\"budgetOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [ngModel]=\"view.transcriptBudget\"\n (ngModelChange)=\"onTranscriptBudget($event)\"\n appendTo=\"body\"\n ></p-dropdown>\n </div>\n <small class=\"sc-hint\" *ngIf=\"estimateOverMax && view.transcriptMode !== 'density'\">\n Max points reached: transcripts are grouped by area, circles sized by how many they hold. Zoom in or select\n fewer genes to see individual points.\n </small>\n </ng-container>\n\n <ng-container *ngIf=\"view.transcriptMode === 'circles' || view.transcriptMode === 'glyphs'\">\n <div class=\"sc-row\">\n <span class=\"sc-lbl\">Colour by</span>\n <p-selectButton\n [options]=\"transcriptColorOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [ngModel]=\"view.transcriptColorBy\"\n (ngModelChange)=\"onTranscriptColorBy($event)\"\n [allowEmpty]=\"false\"\n styleClass=\"sc-buttons\"\n ></p-selectButton>\n </div>\n <small\n class=\"sc-hint\"\n *ngIf=\"view.transcriptAllGenes && view.transcriptColorBy === 'gene' && estimateOverMax\"\n >\n Grouped markers mix genes, so they are coloured by cell type until you zoom in to individual transcripts.\n </small>\n <div class=\"sc-row\" *ngIf=\"view.transcriptAllGenes && view.transcriptMode === 'glyphs'\">\n <span class=\"sc-lbl\">Icon</span>\n <p-dropdown\n [options]=\"glyphOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [ngModel]=\"glyphOf('*', 0)\"\n (ngModelChange)=\"onGlyph('*', $event)\"\n appendTo=\"body\"\n styleClass=\"sc-glyph-pick\"\n >\n <ng-template let-opt pTemplate=\"item\">\n <span class=\"sc-glyph-option\">\n <svg viewBox=\"-1.2 -1.2 2.4 2.4\" class=\"sc-glyph-svg\">\n <polygon [attr.points]=\"opt.points\"></polygon>\n </svg>\n {{ opt.label }}\n </span>\n </ng-template>\n <ng-template let-opt pTemplate=\"selectedItem\">\n <span class=\"sc-glyph-option\">\n <svg viewBox=\"-1.2 -1.2 2.4 2.4\" class=\"sc-glyph-svg\">\n <polygon [attr.points]=\"opt?.points\"></polygon>\n </svg>\n </span>\n </ng-template>\n </p-dropdown>\n </div>\n <div class=\"sc-row\">\n <span class=\"sc-lbl\">Size</span>\n <p-slider\n [ngModel]=\"view.transcriptScale\"\n [min]=\"0.5\"\n [max]=\"3\"\n [step]=\"0.25\"\n (onChange)=\"onTranscriptScale($event.value)\"\n ></p-slider>\n <span class=\"sc-val\">{{ view.transcriptScale }}\u00D7</span>\n </div>\n <div class=\"sc-row\">\n <span class=\"sc-lbl\">Opacity</span>\n <p-slider\n [ngModel]=\"view.transcriptOpacity\"\n [min]=\"0.1\"\n [max]=\"1\"\n [step]=\"0.05\"\n (onChange)=\"onTranscriptOpacity($event.value)\"\n ></p-slider>\n <span class=\"sc-val\">{{ view.transcriptOpacity }}</span>\n </div>\n <div class=\"sc-row\" *ngIf=\"!showingAllGenes\">\n <p-checkbox\n [binary]=\"true\"\n [ngModel]=\"view.transcriptQuality === 'all'\"\n inputId=\"sc-tx-lowq\"\n (onChange)=\"onTranscriptQuality($event.checked)\"\n ></p-checkbox>\n <label class=\"sc-lbl\" for=\"sc-tx-lowq\">Include low-quality calls</label>\n </div>\n </ng-container>\n\n <ng-container *ngIf=\"view.transcriptMode === 'density'\">\n <span class=\"sc-lbl\">Density map opacity</span>\n <div class=\"sc-row sc-row-number\">\n <p-slider\n [ngModel]=\"view.densityOpacity\"\n [min]=\"0.05\"\n [max]=\"1\"\n [step]=\"0.05\"\n (onChange)=\"onDensityOpacity($event.value)\"\n ></p-slider>\n <p-inputNumber\n [ngModel]=\"densityOpacityPercent\"\n (ngModelChange)=\"onDensityOpacityPercent($event)\"\n [min]=\"5\"\n [max]=\"100\"\n inputStyleClass=\"sc-num\"\n ></p-inputNumber>\n </div>\n <span class=\"sc-lbl\" pTooltip=\"Edge of each density bin\" tooltipPosition=\"top\">Density map bin size</span>\n <p-slider\n [ngModel]=\"densityBinIndex\"\n [min]=\"0\"\n [max]=\"3\"\n [step]=\"1\"\n (onChange)=\"onDensityBinIndex($event.value)\"\n styleClass=\"sc-bin-slider\"\n ></p-slider>\n <div class=\"sc-ticks\">\n <span *ngFor=\"let b of densityBins\">{{ b }}\u00D7{{ b }}\u00B5m</span>\n </div>\n <span\n class=\"sc-lbl\"\n pTooltip=\"Transcripts per \u00B5m\u00B2 at which the colour scale starts and saturates\"\n tooltipPosition=\"top\"\n >Density map scale threshold</span\n >\n <div class=\"sc-row sc-row-range\">\n <p-inputNumber\n [ngModel]=\"densityWindow[0]\"\n (ngModelChange)=\"onDensityRangeEnd(0, $event)\"\n mode=\"decimal\"\n [minFractionDigits]=\"3\"\n [maxFractionDigits]=\"3\"\n inputStyleClass=\"sc-num\"\n ></p-inputNumber>\n <p-slider\n [ngModel]=\"densityWindow\"\n [range]=\"true\"\n [min]=\"0\"\n [max]=\"densitySliderMax\"\n [step]=\"densityStep\"\n (onChange)=\"onDensityRange($event.values)\"\n ></p-slider>\n <p-inputNumber\n [ngModel]=\"densityWindow[1]\"\n (ngModelChange)=\"onDensityRangeEnd(1, $event)\"\n mode=\"decimal\"\n [minFractionDigits]=\"3\"\n [maxFractionDigits]=\"3\"\n inputStyleClass=\"sc-num\"\n ></p-inputNumber>\n </div>\n <div class=\"sc-row\">\n <small class=\"sc-hint\">{{ view.densityRange ? 'Set by hand.' : 'Derived from the data.' }}</small>\n <button type=\"button\" class=\"sc-small-btn\" *ngIf=\"view.densityRange\" (click)=\"onDensityAuto()\">\n Auto\n </button>\n </div>\n <span class=\"sc-lbl\">Density map bin coloring</span>\n <div class=\"sc-row sc-row-picker\">\n <div class=\"sc-colorbar sc-full\" [style.background]=\"densityColorBarCss\"></div>\n <p-treeSelect\n [options]=\"colormapOptions\"\n [ngModel]=\"selectedDensityColormapNode\"\n selectionMode=\"single\"\n [showClear]=\"true\"\n placeholder=\"Inferno\"\n [scrollHeight]=\"'260px'\"\n appendTo=\"body\"\n styleClass=\"sc-palette\"\n (onNodeSelect)=\"onDensityColormap($event.node)\"\n (onClear)=\"onDensityColormap(null)\"\n >\n <ng-template let-node pTemplate=\"default\">\n <span class=\"sc-cmap-option\">\n <img *ngIf=\"!node.children && node.data?.src\" [src]=\"node.data.src\" class=\"sc-cmap-swatch\" alt=\"\" />\n <span>{{ node.label }}</span>\n </span>\n </ng-template>\n </p-treeSelect>\n </div>\n <div class=\"sc-colorbar-ends\">\n <span>{{ densityWindow[0] | number: '1.0-3' }}</span\n ><span>{{ densityWindow[1] | number: '1.0-3' }}</span>\n </div>\n </ng-container>\n </div>\n</div>\n", styles: [".sc-hint{font-size:.75rem;color:var(--text-color-secondary, #6c757d)}.sc-error{color:var(--red-600, #c62828)}.sc-section{display:flex;flex-direction:column;gap:.35rem}.sc-lbl{font-size:.78rem;color:var(--text-color-secondary, #6c757d);white-space:nowrap}.sc-row{display:flex;align-items:center;gap:.6rem}.sc-row p-slider,.sc-row p-dropdown,.sc-row p-treeSelect{flex:1 1 0;min-width:0}:host ::ng-deep .sc-row p-slider .p-slider{width:100%}:host ::ng-deep .sc-row p-dropdown .p-dropdown,:host ::ng-deep .sc-row p-treeSelect .p-treeselect{width:100%}.sc-row .sc-lbl{flex:0 0 calc(50% - .6rem);min-width:0;overflow:hidden;text-overflow:ellipsis}.sc-cmap-option{display:inline-flex;align-items:center;gap:.4rem}.sc-cmap-swatch{width:3.5rem;height:.7rem;border-radius:2px;display:block}.sc-val{flex:0 0 4rem;text-align:right;font-size:.78rem;font-variant-numeric:tabular-nums;white-space:nowrap}:host ::ng-deep .sc-full,:host ::ng-deep .sc-full .p-dropdown,:host ::ng-deep .sc-full .p-autocomplete,:host ::ng-deep .sc-full input{width:100%}.sc-colorbar{height:.75rem;border-radius:2px;border:1px solid rgba(0,0,0,.2)}.sc-colorbar-ends{display:flex;justify-content:space-between;font-size:.7rem;color:var(--text-color-secondary, #6c757d);margin-top:.2rem}.sc-panel{border:1px solid var(--surface-border, #dee2e6);border-radius:6px;margin-bottom:.5rem;overflow:hidden}.sc-panel-head{display:flex;align-items:center;gap:.6rem;padding:.5rem .7rem;cursor:pointer;-webkit-user-select:none;user-select:none;background:var(--surface-100, #f5f6f7)}.sc-panel-head .sc-panel-title{flex:1;font-weight:600}.sc-panel.open>.sc-panel-head{background:var(--primary-color, #2196f3);color:var(--primary-color-text, #fff)}.sc-panel-body{display:flex;flex-direction:column;gap:.45rem;padding:.6rem .75rem .75rem}.sc-subhead{display:flex;align-items:center;gap:.5rem;margin-top:.4rem;font-size:.72rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--text-color-secondary, #6c757d)}.sc-subhead:after{content:\"\";flex:1;border-top:1px solid var(--surface-border, #dee2e6)}:host ::ng-deep .sc-buttons .p-button{padding:.35rem .75rem;font-size:.85rem}.sc-row-picker p-dropdown,.sc-row-picker p-multiSelect,.sc-row-picker p-treeSelect{flex:1 1 0;min-width:0}:host ::ng-deep .sc-row-picker .sc-variant{width:6.5rem}:host ::ng-deep .sc-row-picker p-multiselect .p-multiselect{width:100%}:host ::ng-deep .sc-row-picker p-dropdown:has(.sc-variant){flex:0 0 6.5rem}:host ::ng-deep .sc-row-picker p-treeselect:has(.sc-palette){flex:0 0 3rem}:host ::ng-deep .sc-palette .p-treeselect-label{width:0;padding:0}.sc-icon-btn{flex:0 0 auto;border:0;background:transparent;cursor:pointer;padding:.25rem .35rem;font:inherit;font-size:1.05rem;color:var(--text-color, #333);border-radius:4px}.sc-icon-btn:hover{background:var(--surface-200, #e9ecef)}.sc-icon-btn.active{color:var(--primary-color, #2196f3);font-weight:700}.sc-icon-btn:disabled{opacity:.5;cursor:default}.sc-small-btn{margin-left:auto;border:1px solid var(--surface-border, #ced4da);background:var(--surface-0, #fff);border-radius:4px;padding:.2rem .6rem;font:inherit;font-size:.8rem;cursor:pointer}:host ::ng-deep .sc-group-heading{font-size:.7rem;font-weight:700;letter-spacing:.05em;text-transform:uppercase;opacity:.7}.sc-group-list,.sc-gene-tree{max-height:16rem;overflow-y:auto;border:1px solid var(--surface-border, #dee2e6);border-radius:4px;padding:.25rem .4rem}.sc-group-row,.sc-gene-row{display:flex;align-items:center;gap:.45rem;padding:.15rem 0;font-size:.88rem}.sc-group-row .sc-group-label,.sc-gene-row .sc-group-label{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sc-group-all,.sc-gene-root,.sc-gene-group{font-weight:600}.sc-group-all .sc-icon-btn,.sc-gene-root .sc-icon-btn,.sc-gene-group .sc-icon-btn{margin-left:auto;font-size:.85rem}.sc-count{flex:0 0 auto;font-size:.78rem;color:var(--text-color-secondary, #6c757d)}.sc-glyph-option{display:inline-flex;align-items:center;gap:.4rem}.sc-glyph-svg{width:1rem;height:1rem;fill:currentColor}:host ::ng-deep .sc-glyph-pick .p-dropdown-label{padding:.2rem .4rem}.sc-color-input{width:2.5rem;height:1.8rem;border:1px solid var(--surface-border, #ced4da);border-radius:4px;padding:0;background:none}.sc-row-number p-slider,.sc-row-range p-slider{flex:1 1 0;min-width:0}:host ::ng-deep .sc-num{width:4.5rem;padding:.3rem .4rem;text-align:center}:host ::ng-deep .sc-row-number p-inputnumber,:host ::ng-deep .sc-row-range p-inputnumber{flex:0 0 auto}:host{display:contents}.sc-meter{height:.45rem;border-radius:3px;background:var(--surface-200, #e9ecef);overflow:hidden}.sc-meter-fill{height:100%;background:var(--primary-color, #2196f3)}.sc-meter-fill.over{background:var(--orange-500, #f59e0b)}.sc-meter-ends,.sc-ticks{display:flex;justify-content:space-between;font-size:.72rem;font-weight:600;color:var(--text-color-secondary, #6c757d)}\n"] }]
|
|
377
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sc-panel\" [class.open]=\"open\">\n <div class=\"sc-panel-head\" (click)=\"openChange.emit(!open)\">\n <p-checkbox\n [binary]=\"true\"\n [ngModel]=\"view.transcriptMode !== 'off'\"\n (click)=\"$event.stopPropagation()\"\n (onChange)=\"onTranscriptsOn($event.checked)\"\n ></p-checkbox>\n <span class=\"sc-panel-title\">Transcripts</span>\n <i class=\"pi\" [class.pi-chevron-down]=\"open\" [class.pi-chevron-right]=\"!open\"></i>\n </div>\n <div class=\"sc-panel-body\" *ngIf=\"open\">\n <div class=\"sc-row sc-row-picker\">\n <ng-container *ngIf=\"genes?.state$ | async as gene\">\n <p-multiSelect\n inputId=\"sc-tx-genes\"\n [options]=\"gene.options\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [ngModel]=\"view.transcriptGenes\"\n (onChange)=\"onTranscriptGenes($event.value)\"\n [filter]=\"true\"\n filterBy=\"label\"\n [resetFilterOnHide]=\"true\"\n (onFilter)=\"genes?.onFilter($event.filter)\"\n (onPanelShow)=\"genes?.ensureList()\"\n [virtualScroll]=\"gene.options.length > geneVirtualScrollFrom\"\n [virtualScrollItemSize]=\"30\"\n [showToggleAll]=\"false\"\n [emptyFilterMessage]=\"gene.remote ? 'No match \u2014 keep typing' : 'No match'\"\n [emptyMessage]=\"gene.remote ? 'Type to search genes' : 'No genes'\"\n appendTo=\"body\"\n placeholder=\"Search for genes to visualize\u2026\"\n [selectedItemsLabel]=\"'{0} genes selected'\"\n [maxSelectedLabels]=\"0\"\n styleClass=\"sc-full\"\n ></p-multiSelect>\n </ng-container>\n <button\n type=\"button\"\n class=\"sc-icon-btn\"\n *ngIf=\"canShowAllGenes\"\n (click)=\"onToggleAllGenes()\"\n [class.active]=\"view.transcriptAllGenes\"\n [title]=\"view.transcriptAllGenes ? 'Back to the selected genes' : 'Select all genes'\"\n >\n \u00B1\n </button>\n <button type=\"button\" class=\"sc-icon-btn\" (click)=\"geneMenuRef.toggle($event)\" title=\"More\">\n <i class=\"pi pi-ellipsis-v\"></i>\n </button>\n <p-menu #geneMenuRef [model]=\"geneMenu\" [popup]=\"true\" appendTo=\"body\"></p-menu>\n <input\n #geneGroupFile\n type=\"file\"\n accept=\".csv,.tsv,.txt\"\n hidden\n (change)=\"onImportGeneGroups(geneGroupFile)\"\n />\n </div>\n <small class=\"sc-hint sc-error\" *ngIf=\"geneGroupError\">{{ geneGroupError }}</small>\n <small class=\"sc-hint\" *ngIf=\"allGenesPreparing\">{{ allGenesPreparing }}</small>\n\n <spatial-marker-genes-form\n [controls]=\"controls\"\n [dataset]=\"dataset\"\n [view]=\"view\"\n [open]=\"markersOpen\"\n (openChange)=\"markersOpen = $event\"\n ></spatial-marker-genes-form>\n\n <spatial-gene-tree\n [controls]=\"controls\"\n [dataset]=\"dataset\"\n [view]=\"view\"\n [geneCounts]=\"geneCounts\"\n [geneTotal]=\"geneTotal\"\n ></spatial-gene-tree>\n\n <div class=\"sc-subhead\">Transcript controls</div>\n <span class=\"sc-lbl\">View transcripts as</span>\n <p-selectButton\n [options]=\"transcriptModeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [ngModel]=\"view.transcriptMode === 'off' ? null : view.transcriptMode\"\n (ngModelChange)=\"onTranscriptMode($event)\"\n [allowEmpty]=\"false\"\n styleClass=\"sc-buttons\"\n ></p-selectButton>\n\n <ng-container *ngIf=\"estimate\">\n <div class=\"sc-row\">\n <span\n class=\"sc-lbl\"\n pTooltip=\"Transcripts of the visible genes estimated to be in view, against the most markers drawn at once\"\n tooltipPosition=\"top\"\n >Estimated Transcript Points</span\n >\n <button type=\"button\" class=\"sc-small-btn\" (click)=\"editingMax = !editingMax\">Edit Max</button>\n </div>\n <div class=\"sc-meter\">\n <div class=\"sc-meter-fill\" [class.over]=\"estimateOverMax\" [style.width.%]=\"estimatePercent\"></div>\n </div>\n <div class=\"sc-meter-ends\">\n <span>{{ estimate.points | number }} points</span>\n <span>{{ estimate.max | number }} max{{ estimateOverMax ? ' reached' : '' }}</span>\n </div>\n <div class=\"sc-row\" *ngIf=\"editingMax\">\n <span class=\"sc-lbl\">Max markers</span>\n <p-dropdown\n [options]=\"budgetOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [ngModel]=\"view.transcriptBudget\"\n (ngModelChange)=\"onTranscriptBudget($event)\"\n appendTo=\"body\"\n ></p-dropdown>\n </div>\n <small class=\"sc-hint\" *ngIf=\"estimateOverMax && view.transcriptMode !== 'density'\">\n Max points reached: transcripts are grouped by area, circles sized by how many they hold. Zoom in or select\n fewer genes to see individual points.\n </small>\n </ng-container>\n\n <!-- The density raster and the grouped markers drawn from it carry no cells, so they\n cannot follow the Observations gene filter: they are not drawn while it is on. -->\n <small class=\"sc-hint\" *ngIf=\"observationsFiltered && view.transcriptMode === 'density'\">\n Observations are filtered by gene, and the density map sums every cell's transcripts, so it is hidden. Use\n Circles or Icons to see the transcripts of the observations shown.\n </small>\n <small\n class=\"sc-hint\"\n *ngIf=\"observationsFiltered && (view.transcriptMode === 'circles' || view.transcriptMode === 'glyphs')\"\n >\n Observations are filtered by gene: only the transcripts of the observations shown are drawn. Transcripts\n grouped by area when zoomed out carry no cells, so they are hidden; zoom in to see them.\n </small>\n\n <ng-container *ngIf=\"view.transcriptMode === 'circles' || view.transcriptMode === 'glyphs'\">\n <div class=\"sc-row\">\n <span class=\"sc-lbl\">Colour by</span>\n <p-selectButton\n [options]=\"transcriptColorOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [ngModel]=\"transcriptColorShown\"\n (ngModelChange)=\"onTranscriptColorBy($event)\"\n [allowEmpty]=\"false\"\n styleClass=\"sc-buttons\"\n ></p-selectButton>\n </div>\n <ng-container *ngIf=\"view.transcriptAllGenes && estimateOverMax\">\n <small class=\"sc-hint\" *ngIf=\"hasCellTypes && transcriptColorShown !== 'cellType'\">\n Grouped markers mix genes, so they are coloured by cell type until you zoom in to individual transcripts.\n </small>\n <small class=\"sc-hint\" *ngIf=\"!hasCellTypes\">\n Grouped markers mix genes and this dataset has no cell types, so they are drawn in one colour until you\n zoom in to individual transcripts.\n </small>\n <small class=\"sc-hint\" *ngIf=\"allGenesSomeHidden\">\n Grouped markers hold every gene: hidden genes are left out once you zoom in to individual transcripts.\n </small>\n </ng-container>\n <div class=\"sc-row\" *ngIf=\"view.transcriptAllGenes && view.transcriptMode === 'glyphs'\">\n <span class=\"sc-lbl\">Icon</span>\n <p-dropdown\n [options]=\"glyphOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [ngModel]=\"glyphOf('*', 0)\"\n (ngModelChange)=\"onGlyph('*', $event)\"\n appendTo=\"body\"\n styleClass=\"sc-glyph-pick\"\n >\n <ng-template let-opt pTemplate=\"item\">\n <span class=\"sc-glyph-option\">\n <svg viewBox=\"-1.2 -1.2 2.4 2.4\" class=\"sc-glyph-svg\">\n <polygon [attr.points]=\"opt.points\"></polygon>\n </svg>\n {{ opt.label }}\n </span>\n </ng-template>\n <ng-template let-opt pTemplate=\"selectedItem\">\n <span class=\"sc-glyph-option\">\n <svg viewBox=\"-1.2 -1.2 2.4 2.4\" class=\"sc-glyph-svg\">\n <polygon [attr.points]=\"opt?.points\"></polygon>\n </svg>\n </span>\n </ng-template>\n </p-dropdown>\n </div>\n <div class=\"sc-row\">\n <span class=\"sc-lbl\">Size</span>\n <p-slider\n [ngModel]=\"view.transcriptScale\"\n [min]=\"0.5\"\n [max]=\"3\"\n [step]=\"0.25\"\n (onChange)=\"onTranscriptScale($event.value)\"\n ></p-slider>\n <span class=\"sc-val\">{{ view.transcriptScale }}\u00D7</span>\n </div>\n <div class=\"sc-row\">\n <span class=\"sc-lbl\">Opacity</span>\n <p-slider\n [ngModel]=\"view.transcriptOpacity\"\n [min]=\"0.1\"\n [max]=\"1\"\n [step]=\"0.05\"\n (onChange)=\"onTranscriptOpacity($event.value)\"\n ></p-slider>\n <span class=\"sc-val\">{{ view.transcriptOpacity }}</span>\n </div>\n <div class=\"sc-row\" *ngIf=\"!showingAllGenes\">\n <p-checkbox\n [binary]=\"true\"\n [ngModel]=\"view.transcriptQuality === 'all'\"\n inputId=\"sc-tx-lowq\"\n (onChange)=\"onTranscriptQuality($event.checked)\"\n ></p-checkbox>\n <label class=\"sc-lbl\" for=\"sc-tx-lowq\">Include low-quality calls</label>\n </div>\n </ng-container>\n\n <ng-container *ngIf=\"view.transcriptMode === 'density'\">\n <span class=\"sc-lbl\">Density map opacity</span>\n <div class=\"sc-row sc-row-number\">\n <p-slider\n [ngModel]=\"view.densityOpacity\"\n [min]=\"0.05\"\n [max]=\"1\"\n [step]=\"0.05\"\n (onChange)=\"onDensityOpacity($event.value)\"\n ></p-slider>\n <p-inputNumber\n [ngModel]=\"densityOpacityPercent\"\n (ngModelChange)=\"onDensityOpacityPercent($event)\"\n [min]=\"5\"\n [max]=\"100\"\n inputStyleClass=\"sc-num\"\n ></p-inputNumber>\n </div>\n <span class=\"sc-lbl\" pTooltip=\"Edge of each density bin\" tooltipPosition=\"top\">Density map bin size</span>\n <p-slider\n [ngModel]=\"densityBinIndex\"\n [min]=\"0\"\n [max]=\"3\"\n [step]=\"1\"\n (onChange)=\"onDensityBinIndex($event.value)\"\n styleClass=\"sc-bin-slider\"\n ></p-slider>\n <div class=\"sc-ticks\">\n <span *ngFor=\"let b of densityBins\">{{ b }}\u00D7{{ b }}\u00B5m</span>\n </div>\n <span\n class=\"sc-lbl\"\n pTooltip=\"Transcripts per \u00B5m\u00B2 at which the colour scale starts and saturates\"\n tooltipPosition=\"top\"\n >Density map scale threshold</span\n >\n <div class=\"sc-row sc-row-range\">\n <p-inputNumber\n [ngModel]=\"densityWindow[0]\"\n (ngModelChange)=\"onDensityRangeEnd(0, $event)\"\n mode=\"decimal\"\n [minFractionDigits]=\"3\"\n [maxFractionDigits]=\"3\"\n inputStyleClass=\"sc-num\"\n ></p-inputNumber>\n <p-slider\n [ngModel]=\"densityWindow\"\n [range]=\"true\"\n [min]=\"0\"\n [max]=\"densitySliderMax\"\n [step]=\"densityStep\"\n (onChange)=\"onDensityRange($event.values)\"\n ></p-slider>\n <p-inputNumber\n [ngModel]=\"densityWindow[1]\"\n (ngModelChange)=\"onDensityRangeEnd(1, $event)\"\n mode=\"decimal\"\n [minFractionDigits]=\"3\"\n [maxFractionDigits]=\"3\"\n inputStyleClass=\"sc-num\"\n ></p-inputNumber>\n </div>\n <div class=\"sc-row\">\n <small class=\"sc-hint\">{{ view.densityRange ? 'Set by hand.' : 'Derived from the data.' }}</small>\n <button type=\"button\" class=\"sc-small-btn\" *ngIf=\"view.densityRange\" (click)=\"onDensityAuto()\">\n Auto\n </button>\n </div>\n <span class=\"sc-lbl\">Density map bin coloring</span>\n <div class=\"sc-row sc-row-picker\">\n <div class=\"sc-colorbar sc-full\" [style.background]=\"densityColorBarCss\"></div>\n <p-treeSelect\n [options]=\"colormapOptions\"\n [ngModel]=\"selectedDensityColormapNode\"\n selectionMode=\"single\"\n [showClear]=\"true\"\n placeholder=\"Inferno\"\n [scrollHeight]=\"'260px'\"\n appendTo=\"body\"\n styleClass=\"sc-palette\"\n (onNodeSelect)=\"onDensityColormap($event.node)\"\n (onClear)=\"onDensityColormap(null)\"\n >\n <ng-template let-node pTemplate=\"default\">\n <span class=\"sc-cmap-option\">\n <img *ngIf=\"!node.children && node.data?.src\" [src]=\"node.data.src\" class=\"sc-cmap-swatch\" alt=\"\" />\n <span>{{ node.label }}</span>\n </span>\n </ng-template>\n </p-treeSelect>\n </div>\n <div class=\"sc-colorbar-ends\">\n <span>{{ densityWindow[0] | number: '1.0-3' }}</span\n ><span>{{ densityWindow[1] | number: '1.0-3' }}</span>\n </div>\n </ng-container>\n </div>\n</div>\n", styles: [".sc-hint{font-size:.75rem;color:var(--text-color-secondary, #6c757d)}.sc-error{color:var(--red-600, #c62828)}.sc-section{display:flex;flex-direction:column;gap:.35rem}.sc-lbl{font-size:.78rem;color:var(--text-color-secondary, #6c757d);white-space:nowrap}.sc-row{display:flex;align-items:center;gap:.6rem}.sc-row p-slider,.sc-row p-dropdown,.sc-row p-treeSelect{flex:1 1 0;min-width:0}:host ::ng-deep .sc-row p-slider .p-slider{width:100%}:host ::ng-deep .sc-row p-dropdown .p-dropdown,:host ::ng-deep .sc-row p-treeSelect .p-treeselect{width:100%}.sc-row .sc-lbl{flex:0 0 calc(50% - .6rem);min-width:0;overflow:hidden;text-overflow:ellipsis}.sc-cmap-option{display:inline-flex;align-items:center;gap:.4rem}.sc-cmap-swatch{width:3.5rem;height:.7rem;border-radius:2px;display:block}.sc-val{flex:0 0 4rem;text-align:right;font-size:.78rem;font-variant-numeric:tabular-nums;white-space:nowrap}:host ::ng-deep .sc-full,:host ::ng-deep .sc-full .p-dropdown,:host ::ng-deep .sc-full .p-autocomplete,:host ::ng-deep .sc-full input{width:100%}.sc-colorbar{height:.75rem;border-radius:2px;border:1px solid rgba(0,0,0,.2)}.sc-colorbar-ends{display:flex;justify-content:space-between;font-size:.7rem;color:var(--text-color-secondary, #6c757d);margin-top:.2rem}.sc-panel{border:1px solid var(--surface-border, #dee2e6);border-radius:6px;margin-bottom:.5rem;overflow:hidden}.sc-panel-head{display:flex;align-items:center;gap:.6rem;padding:.5rem .7rem;cursor:pointer;-webkit-user-select:none;user-select:none;background:var(--surface-100, #f5f6f7)}.sc-panel-head .sc-panel-title{flex:1;font-weight:600}.sc-panel.open>.sc-panel-head{background:var(--primary-color, #2196f3);color:var(--primary-color-text, #fff)}.sc-panel-body{display:flex;flex-direction:column;gap:.45rem;padding:.6rem .75rem .75rem}.sc-subhead{display:flex;align-items:center;gap:.5rem;margin-top:.4rem;font-size:.72rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--text-color-secondary, #6c757d)}.sc-subhead:after{content:\"\";flex:1;border-top:1px solid var(--surface-border, #dee2e6)}:host ::ng-deep .sc-buttons .p-button{padding:.35rem .75rem;font-size:.85rem}.sc-row-picker p-dropdown,.sc-row-picker p-multiSelect,.sc-row-picker p-treeSelect{flex:1 1 0;min-width:0}:host ::ng-deep .sc-row-picker .sc-variant{width:6.5rem}:host ::ng-deep .sc-row-picker p-multiselect .p-multiselect{width:100%}:host ::ng-deep .sc-row-picker p-dropdown:has(.sc-variant){flex:0 0 6.5rem}:host ::ng-deep .sc-row-picker p-treeselect:has(.sc-palette){flex:0 0 3rem}:host ::ng-deep .sc-palette .p-treeselect-label{width:0;padding:0}.sc-icon-btn{flex:0 0 auto;border:0;background:transparent;cursor:pointer;padding:.25rem .35rem;font:inherit;font-size:1.05rem;color:var(--text-color, #333);border-radius:4px}.sc-icon-btn:hover{background:var(--surface-200, #e9ecef)}.sc-icon-btn.active{color:var(--primary-color, #2196f3);font-weight:700}.sc-icon-btn:disabled{opacity:.5;cursor:default}.sc-small-btn{margin-left:auto;border:1px solid var(--surface-border, #ced4da);background:var(--surface-0, #fff);border-radius:4px;padding:.2rem .6rem;font:inherit;font-size:.8rem;cursor:pointer}:host ::ng-deep .sc-group-heading{font-size:.7rem;font-weight:700;letter-spacing:.05em;text-transform:uppercase;opacity:.7}.sc-group-list,.sc-gene-tree{max-height:16rem;overflow-y:auto;border:1px solid var(--surface-border, #dee2e6);border-radius:4px;padding:.25rem .4rem}.sc-group-row,.sc-gene-row{display:flex;align-items:center;gap:.45rem;padding:.15rem 0;font-size:.88rem}.sc-group-row .sc-group-label,.sc-gene-row .sc-group-label{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sc-group-all,.sc-gene-root,.sc-gene-group{font-weight:600}.sc-group-all .sc-icon-btn,.sc-gene-root .sc-icon-btn,.sc-gene-group .sc-icon-btn{margin-left:auto;font-size:.85rem}.sc-count{flex:0 0 auto;font-size:.78rem;color:var(--text-color-secondary, #6c757d)}.sc-glyph-option{display:inline-flex;align-items:center;gap:.4rem}.sc-glyph-svg{width:1rem;height:1rem;fill:currentColor}:host ::ng-deep .sc-glyph-pick .p-dropdown-label{padding:.2rem .4rem}.sc-color-input{width:2.5rem;height:1.8rem;border:1px solid var(--surface-border, #ced4da);border-radius:4px;padding:0;background:none}.sc-row-number p-slider,.sc-row-range p-slider{flex:1 1 0;min-width:0}:host ::ng-deep .sc-num{width:4.5rem;padding:.3rem .4rem;text-align:center}:host ::ng-deep .sc-row-number p-inputnumber,:host ::ng-deep .sc-row-range p-inputnumber{flex:0 0 auto}.sc-gene-icon{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:1.4rem;height:1.4rem;padding:0;border:1px solid transparent;border-radius:4px;background:transparent;cursor:pointer}.sc-gene-icon:hover,.sc-gene-icon:focus-visible{border-color:var(--surface-border, rgba(0, 0, 0, .2))}:host{display:contents}.sc-meter{height:.45rem;border-radius:3px;background:var(--surface-200, #e9ecef);overflow:hidden}.sc-meter-fill{height:100%;background:var(--primary-color, #2196f3)}.sc-meter-fill.over{background:var(--orange-500, #f59e0b)}.sc-meter-ends,.sc-ticks{display:flex;justify-content:space-between;font-size:.72rem;font-weight:600;color:var(--text-color-secondary, #6c757d)}\n"] }]
|
|
346
378
|
}], ctorParameters: () => [{ type: i0.NgZone }, { type: i0.ChangeDetectorRef }], propDecorators: { controls: [{
|
|
347
379
|
type: Input
|
|
348
380
|
}], dataset: [{
|
|
@@ -367,4 +399,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImpor
|
|
|
367
399
|
type: ViewChild,
|
|
368
400
|
args: ['geneGroupFile']
|
|
369
401
|
}] } });
|
|
370
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3BhdGlhbC10cmFuc2NyaXB0cy1wYW5lbC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbGliL3NwYXRpYWwtY29udHJvbHMvc3BhdGlhbC10cmFuc2NyaXB0cy1wYW5lbC9zcGF0aWFsLXRyYW5zY3JpcHRzLXBhbmVsLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvc3BhdGlhbC1jb250cm9scy9zcGF0aWFsLXRyYW5zY3JpcHRzLXBhbmVsL3NwYXRpYWwtdHJhbnNjcmlwdHMtcGFuZWwuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLHVCQUF1QixFQUN2QixpQkFBaUIsRUFDakIsU0FBUyxFQUNULFVBQVUsRUFDVixZQUFZLEVBQ1osS0FBSyxFQUNMLE1BQU0sRUFFTixNQUFNLEVBRU4sU0FBUyxHQUNWLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUMzQyxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDbEQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3hELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDMUMsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDeEQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDMUQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzlDLE9BQU8sRUFB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LE1BQU07MkdBSXRDLFFBQVE7c0JBQWhCLEtBQUs7Z0JBRUcsT0FBTztzQkFBZixLQUFLO2dCQUVHLElBQUk7c0JBQVosS0FBSztnQkFFRyxLQUFLO3NCQUFiLEtBQUs7Z0JBRUcsUUFBUTtzQkFBaEIsS0FBSztnQkFFRyxZQUFZO3NCQUFwQixLQUFLO2dCQUVHLFVBQVU7c0JBQWxCLEtBQUs7Z0JBRUcsZUFBZTtzQkFBdkIsS0FBSztnQkFFRyxJQUFJO3NCQUFaLEtBQUs7Z0JBRWEsVUFBVTtzQkFBNUIsTUFBTTtnQkFpRDZCLGdCQUFnQjtzQkFBbkQsU0FBUzt1QkFBQyxlQUFlIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENoYW5nZURldGVjdG9yUmVmLFxuICBDb21wb25lbnQsXG4gIEVsZW1lbnRSZWYsXG4gIEV2ZW50RW1pdHRlcixcbiAgSW5wdXQsXG4gIE5nWm9uZSxcbiAgT25DaGFuZ2VzLFxuICBPdXRwdXQsXG4gIFNpbXBsZUNoYW5nZXMsXG4gIFZpZXdDaGlsZCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgRm9ybXNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBTaGFyZWRNb2R1bGUgfSBmcm9tICdwcmltZW5nL2FwaSc7XG5pbXBvcnQgeyBDaGVja2JveE1vZHVsZSB9IGZyb20gJ3ByaW1lbmcvY2hlY2tib3gnO1xuaW1wb3J0IHsgRHJvcGRvd25Nb2R1bGUgfSBmcm9tICdwcmltZW5nL2Ryb3Bkb3duJztcbmltcG9ydCB7IElucHV0TnVtYmVyTW9kdWxlIH0gZnJvbSAncHJpbWVuZy9pbnB1dG51bWJlcic7XG5pbXBvcnQgeyBNZW51TW9kdWxlIH0gZnJvbSAncHJpbWVuZy9tZW51JztcbmltcG9ydCB7IE11bHRpU2VsZWN0TW9kdWxlIH0gZnJvbSAncHJpbWVuZy9tdWx0aXNlbGVjdCc7XG5pbXBvcnQgeyBTZWxlY3RCdXR0b25Nb2R1bGUgfSBmcm9tICdwcmltZW5nL3NlbGVjdGJ1dHRvbic7XG5pbXBvcnQgeyBTbGlkZXJNb2R1bGUgfSBmcm9tICdwcmltZW5nL3NsaWRlcic7XG5pbXBvcnQgeyBUb29sdGlwTW9kdWxlIH0gZnJvbSAncHJpbWVuZy90b29sdGlwJztcbmltcG9ydCB7IFRyZWVTZWxlY3RNb2R1bGUgfSBmcm9tICdwcmltZW5nL3RyZWVzZWxlY3QnO1xuXG5pbXBvcnQgdHlwZSB7IElTcGF0aWFsQ29udHJvbHMgfSBmcm9tICcuLi8uLi9jb250cmFjdHMvdmlzdWFsaXplci5jb250cmFjdCc7XG5pbXBvcnQgdHlwZSB7IFNwYXRpYWxEYXRhc2V0IH0gZnJvbSAnLi4vLi4vY29udHJhY3RzL3NwYXRpYWwtZGF0YXNldC5jb250cmFjdCc7XG5pbXBvcnQge1xuICBDb2xvcm1hcE5vZGUsXG4gIERFRkFVTFRfU1BBVElBTF9WSUVXLFxuICBTcGF0aWFsVmlld1N0YXRlLFxuICBUcmFuc2NyaXB0R2x5cGhOYW1lLFxufSBmcm9tICcuLi8uLi9jb250cmFjdHMvZGlzcGxheS10eXBlcyc7XG5pbXBvcnQgeyBkZWZhdWx0R2x5cGhGb3IgfSBmcm9tICcuLi8uLi9zcGF0aWFsL3NwYXRpYWwtdGlsZXMnO1xuaW1wb3J0IHtcbiAgR0xZUEhfT1BUSU9OUyxcbiAgUGFuZWxPcHRpb24sXG4gIGFsbEdlbmVzUHJlcGFyaW5nTm90ZSxcbiAgZGVuc2l0eUNvbG9yQmFyQ3NzLFxuICBpbXBvcnRHZW5lR3JvdXBzUGF0Y2gsXG4gIG1hcmtlckNvbHVtbk9wdGlvbnMsXG4gIHBhcnNlR2VuZUdyb3VwcyxcbiAgdGlsZU9wdGlvbnMsXG59IGZyb20gJy4uLy4uL3NwYXRpYWwvc3BhdGlhbC1wYW5lbC1tb2RlbCc7XG5pbXBvcnQgdHlwZSB7IEdlbmVQaWNrZXJNb2RlbCB9IGZyb20gJy4uL3NwYXRpYWwtZ2VuZS1waWNrZXInO1xuaW1wb3J0IHsgY29sb3JtYXBOb2RlRm9yIH0gZnJvbSAnLi4vc3BhdGlhbC1rZXkvc3BhdGlhbC1rZXkuY29tcG9uZW50JztcbmltcG9ydCB7IFNwYXRpYWxHZW5lVHJlZUNvbXBvbmVudCB9IGZyb20gJy4uL3NwYXRpYWwtZ2VuZS10cmVlL3NwYXRpYWwtZ2VuZS10cmVlLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBTcGF0aWFsTWFya2VyR2VuZXNGb3JtQ29tcG9uZW50IH0gZnJvbSAnLi4vc3BhdGlhbC1tYXJrZXItZ2VuZXMtZm9ybS9zcGF0aWFsLW1hcmtlci1nZW5lcy1mb3JtLmNvbXBvbmVudCc7XG5cbi8qKiBPbmUgaXRlbSBvZiB0aGUgZ2VuZSBsaXN0J3MgJ+KLricgbWVudS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgR2VuZU1lbnVJdGVtIHtcbiAgbGFiZWw6IHN0cmluZztcbiAgaWNvbjogc3RyaW5nO1xuICBjb21tYW5kOiAoKSA9PiB2b2lkO1xuICBkaXNhYmxlZD86IGJvb2xlYW47XG59XG5cbi8qKlxuICogVGhlIFRyYW5zY3JpcHRzIHNlY3Rpb24sIGFzIFhlbml1bSBFeHBsb3JlcidzOiB0aGUgb24vb2ZmIHN3aXRjaCwgdGhlIHRyYW5zY3JpcHQgZ2VuZXNcbiAqICh3aXRoIFwiQWxsIGdlbmVzXCIsIHRoZSAn4ouuJyBtZW51IGFuZCBnZW5lLWdyb3VwIGltcG9ydCksIHRoZVxuICoge0BsaW5rIFNwYXRpYWxNYXJrZXJHZW5lc0Zvcm1Db21wb25lbnQgbWFya2VyLWdlbmVzIGZvcm19LCB0aGVcbiAqIHtAbGluayBTcGF0aWFsR2VuZVRyZWVDb21wb25lbnQgZ2VuZSB0cmVlfSwgaG93IHRyYW5zY3JpcHRzIGFyZSBkcmF3biDigJQgdGhlIHBvaW50c1xuICogZXN0aW1hdGUgYWdhaW5zdCBpdHMgYnVkZ2V0LCBjb2xvdXJpbmcsIGljb24sIHNpemUsIG9wYWNpdHkgYW5kIHF1YWxpdHkg4oCUIGFuZCB0aGVcbiAqIGRlbnNpdHkgbWFwJ3Mgb3BhY2l0eSwgYmluIHNpemUsIHRocmVzaG9sZCB3aW5kb3cgYW5kIGNvbG9ybWFwLlxuICpcbiAqIFdyaXRlcyBvbmx5IHRocm91Z2ggYGNvbnRyb2xzLnNldFZpZXdTdGF0ZWAuXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3NwYXRpYWwtdHJhbnNjcmlwdHMtcGFuZWwnLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbXG4gICAgQ29tbW9uTW9kdWxlLFxuICAgIEZvcm1zTW9kdWxlLFxuICAgIFNoYXJlZE1vZHVsZSxcbiAgICBDaGVja2JveE1vZHVsZSxcbiAgICBEcm9wZG93bk1vZHVsZSxcbiAgICBJbnB1dE51bWJlck1vZHVsZSxcbiAgICBNZW51TW9kdWxlLFxuICAgIE11bHRpU2VsZWN0TW9kdWxlLFxuICAgIFNlbGVjdEJ1dHRvbk1vZHVsZSxcbiAgICBTbGlkZXJNb2R1bGUsXG4gICAgVG9vbHRpcE1vZHVsZSxcbiAgICBUcmVlU2VsZWN0TW9kdWxlLFxuICAgIFNwYXRpYWxHZW5lVHJlZUNvbXBvbmVudCxcbiAgICBTcGF0aWFsTWFya2VyR2VuZXNGb3JtQ29tcG9uZW50LFxuICBdLFxuICB0ZW1wbGF0ZVVybDogJy4vc3BhdGlhbC10cmFuc2NyaXB0cy1wYW5lbC5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL3NwYXRpYWwtdHJhbnNjcmlwdHMtcGFuZWwuY29tcG9uZW50LnNjc3MnXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG59KVxuZXhwb3J0IGNsYXNzIFNwYXRpYWxUcmFuc2NyaXB0c1BhbmVsQ29tcG9uZW50IGltcGxlbWVudHMgT25DaGFuZ2VzIHtcbiAgLyoqIFRoZSBzcGF0aWFsIGNvbnRyb2xzIHRoaXMgcGFuZWwgcmVhZHMgYW5kIHdyaXRlcyB0aHJvdWdoOyBudWxsIHdpdGhvdXQgYSBgU1BBVElBTF9EQVRBX1BPUlRgLiAqL1xuICBASW5wdXQoKSBjb250cm9sczogSVNwYXRpYWxDb250cm9scyB8IG51bGwgPSBudWxsO1xuICAvKiogVGhlIGRhdGFzZXQgb24gb2ZmZXIsIG9yIG51bGwuICovXG4gIEBJbnB1dCgpIGRhdGFzZXQ6IFNwYXRpYWxEYXRhc2V0IHwgbnVsbCA9IG51bGw7XG4gIC8qKiBUaGUgY3VycmVudCBzcGF0aWFsIHZpZXcgc3RhdGU6IHdoYXQgaXMgZHJhd24sIGFuZCBob3cuICovXG4gIEBJbnB1dCgpIHZpZXc6IFNwYXRpYWxWaWV3U3RhdGUgPSBERUZBVUxUX1NQQVRJQUxfVklFVztcbiAgLyoqIFRoZSBnZW5lIGxpc3QgdGhlIHRyYW5zY3JpcHQgZ2VuZXMgYXJlIHBpY2tlZCBmcm9tLCBzaGFyZWQgd2l0aCB0aGUgb3RoZXIgZ2VuZSBkcm9wZG93bnMuICovXG4gIEBJbnB1dCgpIGdlbmVzOiBHZW5lUGlja2VyTW9kZWwgfCBudWxsID0gbnVsbDtcbiAgLyoqIEVzdGltYXRlZCB0cmFuc2NyaXB0cyBpbiB2aWV3LCBhZ2FpbnN0IHRoZSBidWRnZXQg4oCUIEV4cGxvcmVyJ3MgcG9pbnRzIGJhci4gKi9cbiAgQElucHV0KCkgZXN0aW1hdGU6IHsgcG9pbnRzOiBudW1iZXI7IG1heDogbnVtYmVyIH0gfCBudWxsID0gbnVsbDtcbiAgLyoqIFRoZSBkZW5zaXR5IHdpbmRvdyBpbiB1c2UgYW5kIGl0cyBkZW5zZXN0IGJpbiwgZm9yIHRoZSB0aHJlc2hvbGQgY29udHJvbC4gKi9cbiAgQElucHV0KCkgZGVuc2l0eVN0YXRzOiB7IGxvOiBudW1iZXI7IGhpOiBudW1iZXI7IG1heDogbnVtYmVyIH0gfCBudWxsID0gbnVsbDtcbiAgLyoqIFRyYW5zY3JpcHRzIG9mIGVhY2ggc2VsZWN0ZWQgZ2VuZSBpbiB0aGUgY3VycmVudCB2aWV3LCBmcm9tIHRoZSByZW5kZXJlci4gKi9cbiAgQElucHV0KCkgZ2VuZUNvdW50czogUmVjb3JkPHN0cmluZywgbnVtYmVyPiB8IG51bGwgPSBudWxsO1xuICAvKiogQ29sb3JtYXAgdHJlZSBmb3IgdGhlIGRlbnNpdHkgbWFwJ3MgY29sb3VyaW5nLiAqL1xuICBASW5wdXQoKSBjb2xvcm1hcE9wdGlvbnM6IENvbG9ybWFwTm9kZVtdID0gW107XG4gIC8qKiBXaGV0aGVyIHRoZSBzZWN0aW9uIGlzIGV4cGFuZGVkLiAqL1xuICBASW5wdXQoKSBvcGVuID0gZmFsc2U7XG4gIC8qKiBBc2tzIHRvIG9wZW4gb3IgY2xvc2UgaXQ7IHR3by13YXkgd2l0aCBgb3BlbmAuICovXG4gIEBPdXRwdXQoKSByZWFkb25seSBvcGVuQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxib29sZWFuPigpO1xuXG4gIC8qKiBWaXJ0dWFsLXNjcm9sbGVkIG9ubHkgcGFzdCB0aGlzIG1hbnkgb3B0aW9ucyAoc2VlIHRoZSBjZWxscyBwYW5lbCdzIGdlbmUgZHJvcGRvd24pLiAqL1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgZ2VuZVZpcnR1YWxTY3JvbGxGcm9tID0gMjAwO1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgdHJhbnNjcmlwdENvbG9yT3B0aW9uczogUGFuZWxPcHRpb248U3BhdGlhbFZpZXdTdGF0ZVsndHJhbnNjcmlwdENvbG9yQnknXT5bXSA9IFtcbiAgICB7IGxhYmVsOiAnQ2x1c3RlcicsIHZhbHVlOiAnY2x1c3RlcicgfSxcbiAgICB7IGxhYmVsOiAnQ2VsbCB0eXBlJywgdmFsdWU6ICdjZWxsVHlwZScgfSxcbiAgICB7IGxhYmVsOiAnR2VuZScsIHZhbHVlOiAnZ2VuZScgfSxcbiAgXTtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGdseXBoT3B0aW9ucyA9IEdMWVBIX09QVElPTlM7XG4gIHByb3RlY3RlZCByZWFkb25seSBidWRnZXRPcHRpb25zID0gWzI1XzAwMCwgNTBfMDAwLCAxMDBfMDAwLCAyMDBfMDAwLCA0MDBfMDAwXS5tYXAoKG4pID0+ICh7XG4gICAgbGFiZWw6IG4udG9Mb2NhbGVTdHJpbmcoKSxcbiAgICB2YWx1ZTogbixcbiAgfSkpO1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgZGVuc2l0eUJpbnMgPSBbMTAsIDIwLCA0MCwgODBdO1xuXG4gIC8qKlxuICAgKiBUcmFuc2NyaXB0IG1vZGVzIG9uIG9mZmVyLiBCdWlsdCBvbmNlIHBlciBkYXRhc2V0IHJhdGhlciB0aGFuIGluIGEgZ2V0dGVyOiBhIGdldHRlclxuICAgKiByZXR1cm5zIGEgZnJlc2ggYXJyYXkgb24gZXZlcnkgY2hhbmdlLWRldGVjdGlvbiBwYXNzLCBhbmQgUHJpbWVORyByZS1yZW5kZXJzIGl0c1xuICAgKiBidXR0b25zIHdoZW5ldmVyIHRoZSBhcnJheSBpZGVudGl0eSBjaGFuZ2VzIOKAlCB3aGljaCBtYWRlIHRoZW0gaW1wb3NzaWJsZSB0byBjbGljay5cbiAgICovXG4gIHByb3RlY3RlZCB0cmFuc2NyaXB0TW9kZU9wdGlvbnM6IFBhbmVsT3B0aW9uPFNwYXRpYWxWaWV3U3RhdGVbJ3RyYW5zY3JpcHRNb2RlJ10+W10gPSBbXTtcbiAgLyoqIFRoZSAn4ouuJyBtZW51LCByZWJ1aWx0IHdoZW4gd2hhdCBlbmFibGVzIGl0cyBpdGVtcyBjaGFuZ2VzLiAqL1xuICBwcm90ZWN0ZWQgZ2VuZU1lbnU6IEdlbmVNZW51SXRlbVtdID0gW107XG4gIHByb3RlY3RlZCBlZGl0aW5nTWF4ID0gZmFsc2U7XG4gIC8qKiBXaGV0aGVyIHRoZSBtYXJrZXItZ2VuZXMgZm9ybSBpcyBzaG93bi4gKi9cbiAgcHJvdGVjdGVkIG1hcmtlcnNPcGVuID0gZmFsc2U7XG4gIHByb3RlY3RlZCBnZW5lR3JvdXBFcnJvcjogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG5cbiAgLyoqXG4gICAqIFRoZSB0aHJlc2hvbGQgd2luZG93IHNob3duOiB0aGUgb25lIHNldCwgZWxzZSB0aGUgb25lIGRlcml2ZWQuIEEgc3RvcmVkIGFycmF5LCBub3QgYVxuICAgKiBnZXR0ZXI6IGEgcmFuZ2Ugc2xpZGVyJ3MgYG5nTW9kZWxgIGdpdmVuIGEgZnJlc2ggYXJyYXkgZXZlcnkgY2hhbmdlLWRldGVjdGlvbiBwYXNzXG4gICAqIHNjaGVkdWxlcyBhbm90aGVyIHBhc3MsIGZvcmV2ZXIg4oCUIHdoaWNoIGh1bmcgdGhlIHBhZ2UgdGhlIG1vbWVudCB0aGUgZGVuc2l0eVxuICAgKiBjb250cm9scyBhcHBlYXJlZC5cbiAgICovXG4gIHByb3RlY3RlZCBkZW5zaXR5V2luZG93OiBbbnVtYmVyLCBudW1iZXJdID0gWzAsIDFdO1xuICBwcm90ZWN0ZWQgZGVuc2l0eVNsaWRlck1heCA9IDE7XG4gIHByb3RlY3RlZCBkZW5zaXR5U3RlcCA9IDAuMDA1O1xuICBwcm90ZWN0ZWQgc2VsZWN0ZWREZW5zaXR5Q29sb3JtYXBOb2RlOiBDb2xvcm1hcE5vZGUgfCBudWxsID0gbnVsbDtcbiAgLyoqIEJ1aWx0IG9uY2UgcGVyIGRlbnNpdHkgY29sb3JtYXA6IGEgMjU2LWVudHJ5IExVVCBwZXIgY2hhbmdlLWRldGVjdGlvbiBwYXNzIGlzIHdhc3RlLiAqL1xuICBwcm90ZWN0ZWQgZGVuc2l0eUNvbG9yQmFyQ3NzID0gJyc7XG4gIHByaXZhdGUgZGVuc2l0eUJhckZvcjogU3BhdGlhbFZpZXdTdGF0ZVsnZGVuc2l0eUNvbG9ybWFwJ10gfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG5cbiAgLyoqIFRoZSBtb2RlIHRoZSBzZWN0aW9uIGhlYWRlcidzIHN3aXRjaCB0dXJucyBiYWNrIG9uLiAqL1xuICBwcml2YXRlIGxhc3RUcmFuc2NyaXB0TW9kZTogRXhjbHVkZTxTcGF0aWFsVmlld1N0YXRlWyd0cmFuc2NyaXB0TW9kZSddLCAnb2ZmJz4gPSAnY2lyY2xlcyc7XG4gIC8qKiBXaGV0aGVyIGFueSBjb2x1bW4gY2FuIHN1cHBseSBtYXJrZXIgZ2VuZXMnIGNsdXN0ZXJzLiAqL1xuICBwcml2YXRlIGhhc01hcmtlckNvbHVtbnMgPSBmYWxzZTtcblxuICAvKiogVGhlIGhpZGRlbiBmaWxlIGlucHV0IHRoZSBtZW51J3MgaW1wb3J0IG9wZW5zLiAqL1xuICBAVmlld0NoaWxkKCdnZW5lR3JvdXBGaWxlJykgcHJpdmF0ZSBnZW5lR3JvdXBGaWxlUmVmPzogRWxlbWVudFJlZjxIVE1MSW5wdXRFbGVtZW50PjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IHpvbmU6IE5nWm9uZSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGNkcjogQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICkge31cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgaWYgKGNoYW5nZXNbJ2RhdGFzZXQnXSkge1xuICAgICAgdGhpcy50cmFuc2NyaXB0TW9kZU9wdGlvbnMgPSB0aWxlT3B0aW9ucyh0aGlzLmRhdGFzZXQpLnRyYW5zY3JpcHRNb2RlT3B0aW9ucztcbiAgICAgIHRoaXMuaGFzTWFya2VyQ29sdW1ucyA9IG1hcmtlckNvbHVtbk9wdGlvbnModGhpcy5kYXRhc2V0Py5jb2x1bW5zKS5sZW5ndGggPiAwO1xuICAgIH1cbiAgICBpZiAoY2hhbmdlc1sndmlldyddIHx8IGNoYW5nZXNbJ2RhdGFzZXQnXSB8fCBjaGFuZ2VzWydjb250cm9scyddKSB0aGlzLmdlbmVNZW51ID0gdGhpcy5idWlsZEdlbmVNZW51KCk7XG4gICAgaWYgKGNoYW5nZXNbJ3ZpZXcnXSB8fCBjaGFuZ2VzWydjb2xvcm1hcE9wdGlvbnMnXSkge1xuICAgICAgdGhpcy5zZWxlY3RlZERlbnNpdHlDb2xvcm1hcE5vZGUgPSBjb2xvcm1hcE5vZGVGb3IodGhpcy5jb2xvcm1hcE9wdGlvbnMsIHRoaXMudmlldy5kZW5zaXR5Q29sb3JtYXApO1xuICAgIH1cbiAgICBpZiAodGhpcy5kZW5zaXR5QmFyRm9yICE9PSB0aGlzLnZpZXcuZGVuc2l0eUNvbG9ybWFwIHx8ICF0aGlzLmRlbnNpdHlDb2xvckJhckNzcykge1xuICAgICAgdGhpcy5kZW5zaXR5QmFyRm9yID0gdGhpcy52aWV3LmRlbnNpdHlDb2xvcm1hcDtcbiAgICAgIHRoaXMuZGVuc2l0eUNvbG9yQmFyQ3NzID0gZGVuc2l0eUNvbG9yQmFyQ3NzKHRoaXMudmlldy5kZW5zaXR5Q29sb3JtYXApO1xuICAgIH1cbiAgICB0aGlzLnJlZnJlc2hEZW5zaXR5V2luZG93KCk7XG4gIH1cblxuICAvLyDilIDilIAgdGhlIHNlY3Rpb24gc3dpdGNoIGFuZCB0aGUgZ2VuZXMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgcHJvdGVjdGVkIG9uVHJhbnNjcmlwdHNPbihvbjogYm9vbGVhbik6IHZvaWQge1xuICAgIGlmICghb24pIHtcbiAgICAgIGlmICh0aGlzLnZpZXcudHJhbnNjcmlwdE1vZGUgIT09ICdvZmYnKSB0aGlzLmxhc3RUcmFuc2NyaXB0TW9kZSA9IHRoaXMudmlldy50cmFuc2NyaXB0TW9kZTtcbiAgICAgIHRoaXMuY29udHJvbHM/LnNldFZpZXdTdGF0ZSh7IHRyYW5zY3JpcHRNb2RlOiAnb2ZmJyB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgbW9kZSA9IHRoaXMuZGF0YXNldD8udHJhbnNjcmlwdFRpbGVzID8gdGhpcy5sYXN0VHJhbnNjcmlwdE1vZGUgOiAnZGVuc2l0eSc7XG4gICAgdGhpcy5vblRyYW5zY3JpcHRNb2RlKG1vZGUpO1xuICAgIHRoaXMub3BlbkNoYW5nZS5lbWl0KHRydWUpO1xuICB9XG5cbiAgcHJvdGVjdGVkIG9uVHJhbnNjcmlwdE1vZGUobW9kZTogU3BhdGlhbFZpZXdTdGF0ZVsndHJhbnNjcmlwdE1vZGUnXSk6IHZvaWQge1xuICAgIC8vIFNlZWQgdGhlIGdlbmUgbGlzdCBmcm9tIHRoZSBnZW5lIGJlaW5nIGNvbG91cmVkIGJ5LCBzbyBzd2l0Y2hpbmcgdHJhbnNjcmlwdHMgb25cbiAgICAvLyBzaG93cyBzb21ldGhpbmcgc3RyYWlnaHQgYXdheS5cbiAgICBjb25zdCBzZWVkID1cbiAgICAgICF0aGlzLnZpZXcudHJhbnNjcmlwdEdlbmVzLmxlbmd0aCAmJiB0aGlzLnZpZXcuY29sb3JCeT8ua2luZCA9PT0gJ2ZlYXR1cmUnID8gW3RoaXMudmlldy5jb2xvckJ5Lm5hbWVdIDogbnVsbDtcbiAgICB0aGlzLmNvbnRyb2xzPy5zZXRWaWV3U3RhdGUoeyB0cmFuc2NyaXB0TW9kZTogbW9kZSwgLi4uKHNlZWQgPyB7IHRyYW5zY3JpcHRHZW5lczogc2VlZCB9IDoge30pIH0pO1xuICB9XG5cbiAgcHJvdGVjdGVkIG9uVHJhbnNjcmlwdEdlbmVzKGdlbmVzOiBzdHJpbmdbXSB8IG51bGwpOiB2b2lkIHtcbiAgICB0aGlzLmNvbnRyb2xzPy5zZXRWaWV3U3RhdGUoeyB0cmFuc2NyaXB0R2VuZXM6IFsuLi4oZ2VuZXMgPz8gW10pXSB9KTtcbiAgfVxuXG4gIC8qKiBSZWFsIGdlbmVzIGluIHRoZSBwYW5lbCDigJQgdGhlIHRyZWUncyBkZW5vbWluYXRvci4gKi9cbiAgcHJvdGVjdGVkIGdldCBnZW5lVG90YWwoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gKFxuICAgICAgdGhpcy5kYXRhc2V0Py50cmFuc2NyaXB0VGlsZXM/LmdlbmVDb3VudCA/PyB0aGlzLmRhdGFzZXQ/LmZlYXR1cmVzPy5jb3VudCA/PyB0aGlzLmdlbmVzPy5yZXNpZGVudENvdW50ID8/IDBcbiAgICApO1xuICB9XG5cbiAgLyoqIFwiQWxsIGdlbmVzXCIgbmVlZHMgdGhlIGdyb3VwaW5nIHB5cmFtaWQsIG9yIGF0IGxlYXN0IHRpbGVzIHRvIGRyYXcgaW5kaXZpZHVhbGx5LiAqL1xuICBwcm90ZWN0ZWQgZ2V0IGNhblNob3dBbGxHZW5lcygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gISF0aGlzLmRhdGFzZXQ/LnRyYW5zY3JpcHRCaW5zO1xuICB9XG5cbiAgLyoqIFdoeSBcIkFsbCBnZW5lc1wiIGlzIG5vdCBvZmZlcmVkIHlldCwgd2hpbGUgdGhlIHNlcnZlciBidWlsZHMgaXRzIHB5cmFtaWQuICovXG4gIHByb3RlY3RlZCBnZXQgYWxsR2VuZXNQcmVwYXJpbmcoKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgcmV0dXJuIGFsbEdlbmVzUHJlcGFyaW5nTm90ZSh0aGlzLmRhdGFzZXQpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGdldCBzaG93aW5nQWxsR2VuZXMoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuY2FuU2hvd0FsbEdlbmVzICYmIHRoaXMudmlldy50cmFuc2NyaXB0QWxsR2VuZXMgJiYgdGhpcy52aWV3LnRyYW5zY3JpcHRNb2RlICE9PSAnZGVuc2l0eSc7XG4gIH1cblxuICBvblRyYW5zY3JpcHRBbGxHZW5lcyhvbjogYm9vbGVhbik6IHZvaWQge1xuICAgIHRoaXMuY29udHJvbHM/LnNldFZpZXdTdGF0ZSh7IHRyYW5zY3JpcHRBbGxHZW5lczogb24gfSk7XG4gIH1cblxuICAvKiogJ8KxJzogZXZlcnkgZ2VuZSwgb3IgYmFjayB0byB0aGUgY2hvc2VuIGxpc3QuICovXG4gIHByb3RlY3RlZCBvblRvZ2dsZUFsbEdlbmVzKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5jYW5TaG93QWxsR2VuZXMpIHJldHVybjtcbiAgICB0aGlzLm9uVHJhbnNjcmlwdEFsbEdlbmVzKCF0aGlzLnZpZXcudHJhbnNjcmlwdEFsbEdlbmVzKTtcbiAgfVxuXG4gIGdldCBjYW5BZGRNYXJrZXJzKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAhIXRoaXMuY29udHJvbHM/Lm1hcmtlckdlbmVzICYmIHRoaXMuaGFzTWFya2VyQ29sdW1ucztcbiAgfVxuXG4gIC8qKiBPcGVuIHRoZSBtYXJrZXItZ2VuZXMgZm9ybSAoZnJvbSB0aGUgJ+KLricgbWVudSkuICovXG4gIG9wZW5NYXJrZXJzKCk6IHZvaWQge1xuICAgIHRoaXMubWFya2Vyc09wZW4gPSB0cnVlO1xuICAgIHRoaXMub3BlbkNoYW5nZS5lbWl0KHRydWUpO1xuICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgb25OZXdHZW5lR3JvdXAoKTogdm9pZCB7XG4gICAgY29uc3QgbmFtZSA9IChnbG9iYWxUaGlzLnByb21wdD8uKCdOYW1lIGZvciB0aGlzIGdlbmUgZ3JvdXAnLCAnR2VuZSBncm91cCcpID8/ICcnKS50cmltKCk7XG4gICAgaWYgKCFuYW1lKSByZXR1cm47XG4gICAgY29uc3QgZ3JvdXBzID0gdGhpcy52aWV3LnRyYW5zY3JpcHRHZW5lR3JvdXBzLmZpbHRlcigoZykgPT4gZy5uYW1lICE9PSBuYW1lKTtcbiAgICB0aGlzLmNvbnRyb2xzPy5zZXRWaWV3U3RhdGUoe1xuICAgICAgdHJhbnNjcmlwdEdlbmVHcm91cHM6IFsuLi5ncm91cHMsIHsgbmFtZSwgZ2VuZXM6IFsuLi50aGlzLnZpZXcudHJhbnNjcmlwdEdlbmVzXSB9XSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbXBvcnQgZ2VuZSBncm91cHM6IENTVi9UU1Ygd2l0aCBhIGdyb3VwIGFuZCBhIGdlbmUgY29sdW1uIChoZWFkZXIgb3B0aW9uYWwpLCBlLmcuXG4gICAqIG1hcmtlciBnZW5lcyBwZXIgY2VsbCB0eXBlLiBUaGUgZ2VuZXMgYXJlIGFkZGVkIHRvIHRoZSBzZWxlY3Rpb24uXG4gICAqL1xuICBwcm90ZWN0ZWQgYXN5bmMgb25JbXBvcnRHZW5lR3JvdXBzKGlucHV0OiBIVE1MSW5wdXRFbGVtZW50KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgZmlsZSA9IGlucHV0LmZpbGVzPy5bMF07XG4gICAgaW5wdXQudmFsdWUgPSAnJztcbiAgICBpZiAoIWZpbGUpIHJldHVybjtcbiAgICB0aGlzLmdlbmVHcm91cEVycm9yID0gbnVsbDtcbiAgICBjb25zdCBncm91cHMgPSBwYXJzZUdlbmVHcm91cHMoYXdhaXQgZmlsZS50ZXh0KCkpO1xuICAgIHRoaXMuem9uZS5ydW4oKCkgPT4ge1xuICAgICAgaWYgKCFncm91cHMubGVuZ3RoKSB0aGlzLmdlbmVHcm91cEVycm9yID0gJ05vIFwiZ3JvdXAsZ2VuZVwiIHJvd3MgZm91bmQgaW4gdGhhdCBmaWxlLic7XG4gICAgICBlbHNlIHRoaXMuY29udHJvbHM/LnNldFZpZXdTdGF0ZShpbXBvcnRHZW5lR3JvdXBzUGF0Y2godGhpcy52aWV3LCBncm91cHMpKTtcbiAgICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICAgIH0pO1xuICB9XG5cbiAgLy8g4pSA4pSAIGhvdyB0cmFuc2NyaXB0cyBhcmUgZHJhd24g4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgcHJvdGVjdGVkIGdldCBlc3RpbWF0ZVBlcmNlbnQoKTogbnVtYmVyIHtcbiAgICBjb25zdCBlID0gdGhpcy5lc3RpbWF0ZTtcbiAgICByZXR1cm4gZSAmJiBlLm1heCA+IDAgPyBNYXRoLm1pbigxMDAsICgxMDAgKiBlLnBvaW50cykgLyBlLm1heCkgOiAwO1xuICB9XG5cbiAgcHJvdGVjdGVkIGdldCBlc3RpbWF0ZU92ZXJNYXgoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICEhdGhpcy5lc3RpbWF0ZSAmJiB0aGlzLmVzdGltYXRlLnBvaW50cyA+IHRoaXMuZXN0aW1hdGUubWF4O1xuICB9XG5cbiAgcHJvdGVjdGVkIG9uVHJhbnNjcmlwdEJ1ZGdldChuOiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLmNvbnRyb2xzPy5zZXRWaWV3U3RhdGUoeyB0cmFuc2NyaXB0QnVkZ2V0OiBuIH0pO1xuICB9XG5cbiAgcHJvdGVjdGVkIG9uVHJhbnNjcmlwdENvbG9yQnkoYnk6IFNwYXRpYWxWaWV3U3RhdGVbJ3RyYW5zY3JpcHRDb2xvckJ5J10pOiB2b2lkIHtcbiAgICB0aGlzLmNvbnRyb2xzPy5zZXRWaWV3U3RhdGUoeyB0cmFuc2NyaXB0Q29sb3JCeTogYnkgfSk7XG4gIH1cblxuICAvLyBQcmltZU5HJ3Mgc2xpZGVyIHJlcG9ydHMgYG51bWJlciB8IHVuZGVmaW5lZGA7IGlnbm9yZSB0aGUgZW1wdHkgY2FzZSByYXRoZXIgdGhhblxuICAvLyB3cml0aW5nIGB1bmRlZmluZWRgIGludG8gdGhlIHN0b3JlLlxuICBwcm90ZWN0ZWQgb25UcmFuc2NyaXB0U2NhbGUodmFsdWU6IG51bWJlciB8IHVuZGVmaW5lZCk6IHZvaWQge1xuICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSByZXR1cm47XG4gICAgdGhpcy5jb250cm9scz8uc2V0Vmlld1N0YXRlKHsgdHJhbnNjcmlwdFNjYWxlOiB2YWx1ZSB9KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvblRyYW5zY3JpcHRPcGFjaXR5KHZhbHVlOiBudW1iZXIgfCB1bmRlZmluZWQpOiB2b2lkIHtcbiAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuICAgIHRoaXMuY29udHJvbHM/LnNldFZpZXdTdGF0ZSh7IHRyYW5zY3JpcHRPcGFjaXR5OiB2YWx1ZSB9KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvblRyYW5zY3JpcHRRdWFsaXR5KGluY2x1ZGVMb3c6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0aGlzLmNvbnRyb2xzPy5zZXRWaWV3U3RhdGUoeyB0cmFuc2NyaXB0UXVhbGl0eTogaW5jbHVkZUxvdyA/ICdhbGwnIDogJ2hpZ2gnIH0pO1xuICB9XG5cbiAgcHJvdGVjdGVkIGdseXBoT2YoZ2VuZTogc3RyaW5nLCBzbG90OiBudW1iZXIpOiBUcmFuc2NyaXB0R2x5cGhOYW1lIHtcbiAgICByZXR1cm4gdGhpcy52aWV3LnRyYW5zY3JpcHRHbHlwaHNbZ2VuZV0gPz8gZGVmYXVsdEdseXBoRm9yKHNsb3QpO1xuICB9XG5cbiAgcHJvdGVjdGVkIG9uR2x5cGgoZ2VuZTogc3RyaW5nLCBnbHlwaDogVHJhbnNjcmlwdEdseXBoTmFtZSk6IHZvaWQge1xuICAgIHRoaXMuY29udHJvbHM/LnNldFZpZXdTdGF0ZSh7IHRyYW5zY3JpcHRHbHlwaHM6IHsgLi4udGhpcy52aWV3LnRyYW5zY3JpcHRHbHlwaHMsIFtnZW5lXTogZ2x5cGggfSB9KTtcbiAgfVxuXG4gIC8vIOKUgOKUgCBkZW5zaXR5IG1hcCDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBwcm90ZWN0ZWQgZ2V0IGRlbnNpdHlPcGFjaXR5UGVyY2VudCgpOiBudW1iZXIge1xuICAgIHJldHVybiBNYXRoLnJvdW5kKHRoaXMudmlldy5kZW5zaXR5T3BhY2l0eSAqIDEwMCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgb25EZW5zaXR5T3BhY2l0eSh2YWx1ZTogbnVtYmVyIHwgdW5kZWZpbmVkKTogdm9pZCB7XG4gICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHJldHVybjtcbiAgICB0aGlzLmNvbnRyb2xzPy5zZXRWaWV3U3RhdGUoeyBkZW5zaXR5T3BhY2l0eTogdmFsdWUgfSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgb25EZW5zaXR5T3BhY2l0eVBlcmNlbnQodjogbnVtYmVyIHwgbnVsbCk6IHZvaWQge1xuICAgIGlmICh2ID09PSBudWxsIHx8ICFOdW1iZXIuaXNGaW5pdGUodikpIHJldHVybjtcbiAgICB0aGlzLmNvbnRyb2xzPy5zZXRWaWV3U3RhdGUoeyBkZW5zaXR5T3BhY2l0eTogTWF0aC5taW4oMSwgTWF0aC5tYXgoMC4wNSwgdiAvIDEwMCkpIH0pO1xuICB9XG5cbiAgcHJvdGVjdGVkIGdldCBkZW5zaXR5QmluSW5kZXgoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gTWF0aC5tYXgoMCwgdGhpcy5kZW5zaXR5Qmlucy5pbmRleE9mKHRoaXMudmlldy5kZW5zaXR5QmluKSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgb25EZW5zaXR5QmluSW5kZXgoaTogbnVtYmVyIHwgdW5kZWZpbmVkKTogdm9pZCB7XG4gICAgaWYgKGkgPT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuICAgIHRoaXMuY29udHJvbHM/LnNldFZpZXdTdGF0ZSh7IGRlbnNpdHlCaW46IHRoaXMuZGVuc2l0eUJpbnNbaV0gPz8gMTAgfSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgb25EZW5zaXR5UmFuZ2UocmFuZ2U6IFtudW1iZXIsIG51bWJlcl0gfCBudW1iZXJbXSB8IHVuZGVmaW5lZCk6IHZvaWQge1xuICAgIGlmICghcmFuZ2UgfHwgcmFuZ2UubGVuZ3RoICE9PSAyKSByZXR1cm47XG4gICAgdGhpcy5jb250cm9scz8uc2V0Vmlld1N0YXRlKHsgZGVuc2l0eVJhbmdlOiBbTWF0aC5taW4ocmFuZ2VbMF0sIHJhbmdlWzFdKSwgTWF0aC5tYXgocmFuZ2VbMF0sIHJhbmdlWzFdKV0gfSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgb25EZW5zaXR5UmFuZ2VFbmQod2hpY2g6IDAgfCAxLCB2OiBudW1iZXIgfCBudWxsKTogdm9pZCB7XG4gICAgaWYgKHYgPT09IG51bGwgfHwgIU51bWJlci5pc0Zpbml0ZSh2KSkgcmV0dXJuO1xuICAgIGNvbnN0IG5leHQ6IFtudW1iZXIsIG51bWJlcl0gPSBbLi4udGhpcy5kZW5zaXR5V2luZG93XTtcbiAgICBuZXh0W3doaWNoXSA9IHY7XG4gICAgdGhpcy5vbkRlbnNpdHlSYW5nZShuZXh0KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvbkRlbnNpdHlBdXRvKCk6IHZvaWQge1xuICAgIHRoaXMuY29udHJvbHM/LnNldFZpZXdTdGF0ZSh7IGRlbnNpdHlSYW5nZTogbnVsbCB9KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvbkRlbnNpdHlDb2xvcm1hcChub2RlOiBDb2xvcm1hcE5vZGUgfCBudWxsKTogdm9pZCB7XG4gICAgdGhpcy5zZWxlY3RlZERlbnNpdHlDb2xvcm1hcE5vZGUgPSBub2RlO1xuICAgIHRoaXMuY29udHJvbHM/LnNldFZpZXdTdGF0ZSh7IGRlbnNpdHlDb2xvcm1hcDogbm9kZT8uZGF0YT8udmFsdWUgPz8gbnVsbCB9KTtcbiAgfVxuXG4gIHByaXZhdGUgcmVmcmVzaERlbnNpdHlXaW5kb3coKTogdm9pZCB7XG4gICAgY29uc3QgbmV4dDogW251bWJlciwgbnVtYmVyXSA9XG4gICAgICB0aGlzLnZpZXcuZGVuc2l0eVJhbmdlID8/ICh0aGlzLmRlbnNpdHlTdGF0cyA/IFt0aGlzLmRlbnNpdHlTdGF0cy5sbywgdGhpcy5kZW5zaXR5U3RhdHMuaGldIDogWzAsIDFdKTtcbiAgICBpZiAobmV4dFswXSAhPT0gdGhpcy5kZW5zaXR5V2luZG93WzBdIHx8IG5leHRbMV0gIT09IHRoaXMuZGVuc2l0eVdpbmRvd1sxXSkgdGhpcy5kZW5zaXR5V2luZG93ID0gbmV4dDtcbiAgICB0aGlzLmRlbnNpdHlTbGlkZXJNYXggPSBNYXRoLm1heCh0aGlzLmRlbnNpdHlTdGF0cz8ubWF4ID8/IDEsIHRoaXMuZGVuc2l0eVdpbmRvd1sxXSk7XG4gICAgdGhpcy5kZW5zaXR5U3RlcCA9IHRoaXMuZGVuc2l0eVNsaWRlck1heCAvIDIwMDtcbiAgfVxuXG4gIC8qKiAn4ouuJyBtZW51LiAqL1xuICBwcml2YXRlIGJ1aWxkR2VuZU1lbnUoKTogR2VuZU1lbnVJdGVtW10ge1xuICAgIHJldHVybiBbXG4gICAgICB7XG4gICAgICAgIGxhYmVsOiAnQWRkIG1hcmtlciBnZW5lcyBvZiBjbHVzdGVyc+KApicsXG4gICAgICAgIGljb246ICdwaSBwaS1zaXRlbWFwJyxcbiAgICAgICAgZGlzYWJsZWQ6ICF0aGlzLmNhbkFkZE1hcmtlcnMsXG4gICAgICAgIGNvbW1hbmQ6ICgpID0+IHRoaXMub3Blbk1hcmtlcnMoKSxcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIGxhYmVsOiAnTmV3IGdyb3VwIGZyb20gc2VsZWN0ZWQgZ2VuZXMnLFxuICAgICAgICBpY29uOiAncGkgcGktZm9sZGVyLXBsdXMnLFxuICAgICAgICBkaXNhYmxlZDogIXRoaXMudmlldy50cmFuc2NyaXB0R2VuZXMubGVuZ3RoLFxuICAgICAgICBjb21tYW5kOiAoKSA9PiB0aGlzLm9uTmV3R2VuZUdyb3VwKCksXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBsYWJlbDogJ0ltcG9ydCBnZW5lIGdyb3VwcyAoQ1NWKeKApicsXG4gICAgICAgIGljb246ICdwaSBwaS11cGxvYWQnLFxuICAgICAgICBjb21tYW5kOiAoKSA9PiB0aGlzLmdlbmVHcm91cEZpbGVSZWY/Lm5hdGl2ZUVsZW1lbnQuY2xpY2soKSxcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIGxhYmVsOiAnUmVtb3ZlIGdlbmUgZ3JvdXBzJyxcbiAgICAgICAgaWNvbjogJ3BpIHBpLXRpbWVzJyxcbiAgICAgICAgZGlzYWJsZWQ6ICF0aGlzLnZpZXcudHJhbnNjcmlwdEdlbmVHcm91cHMubGVuZ3RoLFxuICAgICAgICBjb21tYW5kOiAoKSA9PiB0aGlzLmNvbnRyb2xzPy5zZXRWaWV3U3RhdGUoeyB0cmFuc2NyaXB0R2VuZUdyb3VwczogW10gfSksXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBsYWJlbDogJ0NsZWFyIHNlbGVjdGlvbicsXG4gICAgICAgIGljb246ICdwaSBwaS1iYW4nLFxuICAgICAgICBkaXNhYmxlZDogIXRoaXMudmlldy50cmFuc2NyaXB0R2VuZXMubGVuZ3RoLFxuICAgICAgICBjb21tYW5kOiAoKSA9PiB0aGlzLmNvbnRyb2xzPy5zZXRWaWV3U3RhdGUoeyB0cmFuc2NyaXB0R2VuZXM6IFtdLCB0cmFuc2NyaXB0SGlkZGVuR2VuZXM6IFtdIH0pLFxuICAgICAgfSxcbiAgICBdO1xuICB9XG59XG4iLCI8ZGl2IGNsYXNzPVwic2MtcGFuZWxcIiBbY2xhc3Mub3Blbl09XCJvcGVuXCI+XG4gIDxkaXYgY2xhc3M9XCJzYy1wYW5lbC1oZWFkXCIgKGNsaWNrKT1cIm9wZW5DaGFuZ2UuZW1pdCghb3BlbilcIj5cbiAgICA8cC1jaGVja2JveFxuICAgICAgW2JpbmFyeV09XCJ0cnVlXCJcbiAgICAgIFtuZ01vZGVsXT1cInZpZXcudHJhbnNjcmlwdE1vZGUgIT09ICdvZmYnXCJcbiAgICAgIChjbGljayk9XCIkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcIlxuICAgICAgKG9uQ2hhbmdlKT1cIm9uVHJhbnNjcmlwdHNPbigkZXZlbnQuY2hlY2tlZClcIlxuICAgID48L3AtY2hlY2tib3g+XG4gICAgPHNwYW4gY2xhc3M9XCJzYy1wYW5lbC10aXRsZVwiPlRyYW5zY3JpcHRzPC9zcGFuPlxuICAgIDxpIGNsYXNzPVwicGlcIiBbY2xhc3MucGktY2hldnJvbi1kb3duXT1cIm9wZW5cIiBbY2xhc3MucGktY2hldnJvbi1yaWdodF09XCIhb3BlblwiPjwvaT5cbiAgPC9kaXY+XG4gIDxkaXYgY2xhc3M9XCJzYy1wYW5lbC1ib2R5XCIgKm5nSWY9XCJvcGVuXCI+XG4gICAgPGRpdiBjbGFzcz1cInNjLXJvdyBzYy1yb3ctcGlja2VyXCI+XG4gICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiZ2VuZXM/LnN0YXRlJCB8IGFzeW5jIGFzIGdlbmVcIj5cbiAgICAgICAgPHAtbXVsdGlTZWxlY3RcbiAgICAgICAgICBpbnB1dElkPVwic2MtdHgtZ2VuZXNcIlxuICAgICAgICAgIFtvcHRpb25zXT1cImdlbmUub3B0aW9uc1wiXG4gICAgICAgICAgb3B0aW9uTGFiZWw9XCJsYWJlbFwiXG4gICAgICAgICAgb3B0aW9uVmFsdWU9XCJ2YWx1ZVwiXG4gICAgICAgICAgW25nTW9kZWxdPVwidmlldy50cmFuc2NyaXB0R2VuZXNcIlxuICAgICAgICAgIChvbkNoYW5nZSk9XCJvblRyYW5zY3JpcHRHZW5lcygkZXZlbnQudmFsdWUpXCJcbiAgICAgICAgICBbZmlsdGVyXT1cInRydWVcIlxuICAgICAgICAgIGZpbHRlckJ5PVwibGFiZWxcIlxuICAgICAgICAgIFtyZXNldEZpbHRlck9uSGlkZV09XCJ0cnVlXCJcbiAgICAgICAgICAob25GaWx0ZXIpPVwiZ2VuZXM/Lm9uRmlsdGVyKCRldmVudC5maWx0ZXIpXCJcbiAgICAgICAgICAob25QYW5lbFNob3cpPVwiZ2VuZXM/LmVuc3VyZUxpc3QoKVwiXG4gICAgICAgICAgW3ZpcnR1YWxTY3JvbGxdPVwiZ2VuZS5vcHRpb25zLmxlbmd0aCA+IGdlbmVWaXJ0dWFsU2Nyb2xsRnJvbVwiXG4gICAgICAgICAgW3ZpcnR1YWxTY3JvbGxJdGVtU2l6ZV09XCIzMFwiXG4gICAgICAgICAgW3Nob3dUb2dnbGVBbGxdPVwiZmFsc2VcIlxuICAgICAgICAgIFtlbXB0eUZpbHRlck1lc3NhZ2VdPVwiZ2VuZS5yZW1vdGUgPyAnTm8gbWF0Y2gg4oCUIGtlZXAgdHlwaW5nJyA6ICdObyBtYXRjaCdcIlxuICAgICAgICAgIFtlbXB0eU1lc3NhZ2VdPVwiZ2VuZS5yZW1vdGUgPyAnVHlwZSB0byBzZWFyY2ggZ2VuZXMnIDogJ05vIGdlbmVzJ1wiXG4gICAgICAgICAgYXBwZW5kVG89XCJib2R5XCJcbiAgICAgICAgICBwbGFjZWhvbGRlcj1cIlNlYXJjaCBmb3IgZ2VuZXMgdG8gdmlzdWFsaXpl4oCmXCJcbiAgICAgICAgICBbc2VsZWN0ZWRJdGVtc0xhYmVsXT1cIid7MH0gZ2VuZXMgc2VsZWN0ZWQnXCJcbiAgICAgICAgICBbbWF4U2VsZWN0ZWRMYWJlbHNdPVwiMFwiXG4gICAgICAgICAgc3R5bGVDbGFzcz1cInNjLWZ1bGxcIlxuICAgICAgICA+PC9wLW11bHRpU2VsZWN0PlxuICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICA8YnV0dG9uXG4gICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICBjbGFzcz1cInNjLWljb24tYnRuXCJcbiAgICAgICAgKm5nSWY9XCJjYW5TaG93QWxsR2VuZXNcIlxuICAgICAgICAoY2xpY2spPVwib25Ub2dnbGVBbGxHZW5lcygpXCJcbiAgICAgICAgW2NsYXNzLmFjdGl2ZV09XCJ2aWV3LnRyYW5zY3JpcHRBbGxHZW5lc1wiXG4gICAgICAgIFt0aXRsZV09XCJ2aWV3LnRyYW5zY3JpcHRBbGxHZW5lcyA/ICdCYWNrIHRvIHRoZSBzZWxlY3RlZCBnZW5lcycgOiAnU2VsZWN0IGFsbCBnZW5lcydcIlxuICAgICAgPlxuICAgICAgICDCsVxuICAgICAgPC9idXR0b24+XG4gICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cInNjLWljb24tYnRuXCIgKGNsaWNrKT1cImdlbmVNZW51UmVmLnRvZ2dsZSgkZXZlbnQpXCIgdGl0bGU9XCJNb3JlXCI+XG4gICAgICAgIDxpIGNsYXNzPVwicGkgcGktZWxsaXBzaXMtdlwiPjwvaT5cbiAgICAgIDwvYnV0dG9uPlxuICAgICAgPHAtbWVudSAjZ2VuZU1lbnVSZWYgW21vZGVsXT1cImdlbmVNZW51XCIgW3BvcHVwXT1cInRydWVcIiBhcHBlbmRUbz1cImJvZHlcIj48L3AtbWVudT5cbiAgICAgIDxpbnB1dFxuICAgICAgICAjZ2VuZUdyb3VwRmlsZVxuICAgICAgICB0eXBlPVwiZmlsZVwiXG4gICAgICAgIGFjY2VwdD1cIi5jc3YsLnRzdiwudHh0XCJcbiAgICAgICAgaGlkZGVuXG4gICAgICAgIChjaGFuZ2UpPVwib25JbXBvcnRHZW5lR3JvdXBzKGdlbmVHcm91cEZpbGUpXCJcbiAgICAgIC8+XG4gICAgPC9kaXY+XG4gICAgPHNtYWxsIGNsYXNzPVwic2MtaGludCBzYy1lcnJvclwiICpuZ0lmPVwiZ2VuZUdyb3VwRXJyb3JcIj57eyBnZW5lR3JvdXBFcnJvciB9fTwvc21hbGw+XG4gICAgPHNtYWxsIGNsYXNzPVwic2MtaGludFwiICpuZ0lmPVwiYWxsR2VuZXNQcmVwYXJpbmdcIj57eyBhbGxHZW5lc1ByZXBhcmluZyB9fTwvc21hbGw+XG5cbiAgICA8c3BhdGlhbC1tYXJrZXItZ2VuZXMtZm9ybVxuICAgICAgW2NvbnRyb2xzXT1cImNvbnRyb2xzXCJcbiAgICAgIFtkYXRhc2V0XT1cImRhdGFzZXRcIlxuICAgICAgW3ZpZXddPVwidmlld1wiXG4gICAgICBbb3Blbl09XCJtYXJrZXJzT3BlblwiXG4gICAgICAob3BlbkNoYW5nZSk9XCJtYXJrZXJzT3BlbiA9ICRldmVudFwiXG4gICAgPjwvc3BhdGlhbC1tYXJrZXItZ2VuZXMtZm9ybT5cblxuICAgIDxzcGF0aWFsLWdlbmUtdHJlZVxuICAgICAgW2NvbnRyb2xzXT1cImNvbnRyb2xzXCJcbiAgICAgIFtkYXRhc2V0XT1cImRhdGFzZXRcIlxuICAgICAgW3ZpZXddPVwidmlld1wiXG4gICAgICBbZ2VuZUNvdW50c109XCJnZW5lQ291bnRzXCJcbiAgICAgIFtnZW5lVG90YWxdPVwiZ2VuZVRvdGFsXCJcbiAgICA+PC9zcGF0aWFsLWdlbmUtdHJlZT5cblxuICAgIDxkaXYgY2xhc3M9XCJzYy1zdWJoZWFkXCI+VHJhbnNjcmlwdCBjb250cm9sczwvZGl2PlxuICAgIDxzcGFuIGNsYXNzPVwic2MtbGJsXCI+VmlldyB0cmFuc2NyaXB0cyBhczwvc3Bhbj5cbiAgICA8cC1zZWxlY3RCdXR0b25cbiAgICAgIFtvcHRpb25zXT1cInRyYW5zY3JpcHRNb2RlT3B0aW9uc1wiXG4gICAgICBvcHRpb25MYWJlbD1cImxhYmVsXCJcbiAgICAgIG9wdGlvblZhbHVlPVwidmFsdWVcIlxuICAgICAgW25nTW9kZWxdPVwidmlldy50cmFuc2NyaXB0TW9kZSA9PT0gJ29mZicgPyBudWxsIDogdmlldy50cmFuc2NyaXB0TW9kZVwiXG4gICAgICAobmdNb2RlbENoYW5nZSk9XCJvblRyYW5zY3JpcHRNb2RlKCRldmVudClcIlxuICAgICAgW2FsbG93RW1wdHldPVwiZmFsc2VcIlxuICAgICAgc3R5bGVDbGFzcz1cInNjLWJ1dHRvbnNcIlxuICAgID48L3Atc2VsZWN0QnV0dG9uPlxuXG4gICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImVzdGltYXRlXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwic2Mtcm93XCI+XG4gICAgICAgIDxzcGFuXG4gICAgICAgICAgY2xhc3M9XCJzYy1sYmxcIlxuICAgICAgICAgIHBUb29sdGlwPVwiVHJhbnNjcmlwdHMgb2YgdGhlIHZpc2libGUgZ2VuZXMgZXN0aW1hdGVkIHRvIGJlIGluIHZpZXcsIGFnYWluc3QgdGhlIG1vc3QgbWFya2VycyBkcmF3biBhdCBvbmNlXCJcbiAgICAgICAgICB0b29sdGlwUG9zaXRpb249XCJ0b3BcIlxuICAgICAgICAgID5Fc3RpbWF0ZWQgVHJhbnNjcmlwdCBQb2ludHM8L3NwYW5cbiAgICAgICAgPlxuICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cInNjLXNtYWxsLWJ0blwiIChjbGljayk9XCJlZGl0aW5nTWF4ID0gIWVkaXRpbmdNYXhcIj5FZGl0IE1heDwvYnV0dG9uPlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwic2MtbWV0ZXJcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cInNjLW1ldGVyLWZpbGxcIiBbY2xhc3Mub3Zlcl09XCJlc3RpbWF0ZU92ZXJNYXhcIiBbc3R5bGUud2lkdGguJV09XCJlc3RpbWF0ZVBlcmNlbnRcIj48L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cInNjLW1ldGVyLWVuZHNcIj5cbiAgICAgICAgPHNwYW4+e3sgZXN0aW1hdGUucG9pbnRzIHwgbnVtYmVyIH19IHBvaW50czwvc3Bhbj5cbiAgICAgICAgPHNwYW4+e3sgZXN0aW1hdGUubWF4IHwgbnVtYmVyIH19IG1heHt7IGVzdGltYXRlT3Zlck1heCA/ICcgcmVhY2hlZCcgOiAnJyB9fTwvc3Bhbj5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cInNjLXJvd1wiICpuZ0lmPVwiZWRpdGluZ01heFwiPlxuICAgICAgICA8c3BhbiBjbGFzcz1cInNjLWxibFwiPk1heCBtYXJrZXJzPC9zcGFuPlxuICAgICAgICA8cC1kcm9wZG93blxuICAgICAgICAgIFtvcHRpb25zXT1cImJ1ZGdldE9wdGlvbnNcIlxuICAgICAgICAgIG9wdGlvbkxhYmVsPVwibGFiZWxcIlxuICAgICAgICAgIG9wdGlvblZhbHVlPVwidmFsdWVcIlxuICAgICAgICAgIFtuZ01vZGVsXT1cInZpZXcudHJhbnNjcmlwdEJ1ZGdldFwiXG4gICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwib25UcmFuc2NyaXB0QnVkZ2V0KCRldmVudClcIlxuICAgICAgICAgIGFwcGVuZFRvPVwiYm9keVwiXG4gICAgICAgID48L3AtZHJvcGRvd24+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxzbWFsbCBjbGFzcz1cInNjLWhpbnRcIiAqbmdJZj1cImVzdGltYXRlT3Zlck1heCAmJiB2aWV3LnRyYW5zY3JpcHRNb2RlICE9PSAnZGVuc2l0eSdcIj5cbiAgICAgICAgTWF4IHBvaW50cyByZWFjaGVkOiB0cmFuc2NyaXB0cyBhcmUgZ3JvdXBlZCBieSBhcmVhLCBjaXJjbGVzIHNpemVkIGJ5IGhvdyBtYW55IHRoZXkgaG9sZC4gWm9vbSBpbiBvciBzZWxlY3RcbiAgICAgICAgZmV3ZXIgZ2VuZXMgdG8gc2VlIGluZGl2aWR1YWwgcG9pbnRzLlxuICAgICAgPC9zbWFsbD5cbiAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJ2aWV3LnRyYW5zY3JpcHRNb2RlID09PSAnY2lyY2xlcycgfHwgdmlldy50cmFuc2NyaXB0TW9kZSA9PT0gJ2dseXBocydcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJzYy1yb3dcIj5cbiAgICAgICAgPHNwYW4gY2xhc3M9XCJzYy1sYmxcIj5Db2xvdXIgYnk8L3NwYW4+XG4gICAgICAgIDxwLXNlbGVjdEJ1dHRvblxuICAgICAgICAgIFtvcHRpb25zXT1cInRyYW5zY3JpcHRDb2xvck9wdGlvbnNcIlxuICAgICAgICAgIG9wdGlvbkxhYmVsPVwibGFiZWxcIlxuICAgICAgICAgIG9wdGlvblZhbHVlPVwidmFsdWVcIlxuICAgICAgICAgIFtuZ01vZGVsXT1cInZpZXcudHJhbnNjcmlwdENvbG9yQnlcIlxuICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cIm9uVHJhbnNjcmlwdENvbG9yQnkoJGV2ZW50KVwiXG4gICAgICAgICAgW2FsbG93RW1wdHldPVwiZmFsc2VcIlxuICAgICAgICAgIHN0eWxlQ2xhc3M9XCJzYy1idXR0b25zXCJcbiAgICAgICAgPjwvcC1zZWxlY3RCdXR0b24+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxzbWFsbFxuICAgICAgICBjbGFzcz1cInNjLWhpbnRcIlxuICAgICAgICAqbmdJZj1cInZpZXcudHJhbnNjcmlwdEFsbEdlbmVzICYmIHZpZXcudHJhbnNjcmlwdENvbG9yQnkgPT09ICdnZW5lJyAmJiBlc3RpbWF0ZU92ZXJNYXhcIlxuICAgICAgPlxuICAgICAgICBHcm91cGVkIG1hcmtlcnMgbWl4IGdlbmVzLCBzbyB0aGV5IGFyZSBjb2xvdXJlZCBieSBjZWxsIHR5cGUgdW50aWwgeW91IHpvb20gaW4gdG8gaW5kaXZpZHVhbCB0cmFuc2NyaXB0cy5cbiAgICAgIDwvc21hbGw+XG4gICAgICA8ZGl2IGNsYXNzPVwic2Mtcm93XCIgKm5nSWY9XCJ2aWV3LnRyYW5zY3JpcHRBbGxHZW5lcyAmJiB2aWV3LnRyYW5zY3JpcHRNb2RlID09PSAnZ2x5cGhzJ1wiPlxuICAgICAgICA8c3BhbiBjbGFzcz1cInNjLWxibFwiPkljb248L3NwYW4+XG4gICAgICAgIDxwLWRyb3Bkb3duXG4gICAgICAgICAgW29wdGlvbnNdPVwiZ2x5cGhPcHRpb25zXCJcbiAgICAgICAgICBvcHRpb25MYWJlbD1cImxhYmVsXCJcbiAgICAgICAgICBvcHRpb25WYWx1ZT1cInZhbHVlXCJcbiAgICAgICAgICBbbmdNb2RlbF09XCJnbHlwaE9mKCcqJywgMClcIlxuICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cIm9uR2x5cGgoJyonLCAkZXZlbnQpXCJcbiAgICAgICAgICBhcHBlbmRUbz1cImJvZHlcIlxuICAgICAgICAgIHN0eWxlQ2xhc3M9XCJzYy1nbHlwaC1waWNrXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxuZy10ZW1wbGF0ZSBsZXQtb3B0IHBUZW1wbGF0ZT1cIml0ZW1cIj5cbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwic2MtZ2x5cGgtb3B0aW9uXCI+XG4gICAgICAgICAgICAgIDxzdmcgdmlld0JveD1cIi0xLjIgLTEuMiAyLjQgMi40XCIgY2xhc3M9XCJzYy1nbHlwaC1zdmdcIj5cbiAgICAgICAgICAgICAgICA8cG9seWdvbiBbYXR0ci5wb2ludHNdPVwib3B0LnBvaW50c1wiPjwvcG9seWdvbj5cbiAgICAgICAgICAgICAgPC9zdmc+XG4gICAgICAgICAgICAgIHt7IG9wdC5sYWJlbCB9fVxuICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgPG5nLXRlbXBsYXRlIGxldC1vcHQgcFRlbXBsYXRlPVwic2VsZWN0ZWRJdGVtXCI+XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cInNjLWdseXBoLW9wdGlvblwiPlxuICAgICAgICAgICAgICA8c3ZnIHZpZXdCb3g9XCItMS4yIC0xLjIgMi40IDIuNFwiIGNsYXNzPVwic2MtZ2x5cGgtc3ZnXCI+XG4gICAgICAgICAgICAgICAgPHBvbHlnb24gW2F0dHIucG9pbnRzXT1cIm9wdD8ucG9pbnRzXCI+PC9wb2x5Z29uPlxuICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICA8L3AtZHJvcGRvd24+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJzYy1yb3dcIj5cbiAgICAgICAgPHNwYW4gY2xhc3M9XCJzYy1sYmxcIj5TaXplPC9zcGFuPlxuICAgICAgICA8cC1zbGlkZXJcbiAgICAgICAgICBbbmdNb2RlbF09XCJ2aWV3LnRyYW5zY3JpcHRTY2FsZVwiXG4gICAgICAgICAgW21pbl09XCIwLjVcIlxuICAgICAgICAgIFttYXhdPVwiM1wiXG4gICAgICAgICAgW3N0ZXBdPVwiMC4yNVwiXG4gICAgICAgICAgKG9uQ2hhbmdlKT1cIm9uVHJhbnNjcmlwdFNjYWxlKCRldmVudC52YWx1ZSlcIlxuICAgICAgICA+PC9wLXNsaWRlcj5cbiAgICAgICAgPHNwYW4gY2xhc3M9XCJzYy12YWxcIj57eyB2aWV3LnRyYW5zY3JpcHRTY2FsZSB9fcOXPC9zcGFuPlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwic2Mtcm93XCI+XG4gICAgICAgIDxzcGFuIGNsYXNzPVwic2MtbGJsXCI+T3BhY2l0eTwvc3Bhbj5cbiAgICAgICAgPHAtc2xpZGVyXG4gICAgICAgICAgW25nTW9kZWxdPVwidmlldy50cmFuc2NyaXB0T3BhY2l0eVwiXG4gICAgICAgICAgW21pbl09XCIwLjFcIlxuICAgICAgICAgIFttYXhdPVwiMVwiXG4gICAgICAgICAgW3N0ZXBdPVwiMC4wNVwiXG4gICAgICAgICAgKG9uQ2hhbmdlKT1cIm9uVHJhbnNjcmlwdE9wYWNpdHkoJGV2ZW50LnZhbHVlKVwiXG4gICAgICAgID48L3Atc2xpZGVyPlxuICAgICAgICA8c3BhbiBjbGFzcz1cInNjLXZhbFwiPnt7IHZpZXcudHJhbnNjcmlwdE9wYWNpdHkgfX08L3NwYW4+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJzYy1yb3dcIiAqbmdJZj1cIiFzaG93aW5nQWxsR2VuZXNcIj5cbiAgICAgICAgPHAtY2hlY2tib3hcbiAgICAgICAgICBbYmluYXJ5XT1cInRydWVcIlxuICAgICAgICAgIFtuZ01vZGVsXT1cInZpZXcudHJhbnNjcmlwdFF1YWxpdHkgPT09ICdhbGwnXCJcbiAgICAgICAgICBpbnB1dElkPVwic2MtdHgtbG93cVwiXG4gICAgICAgICAgKG9uQ2hhbmdlKT1cIm9uVHJhbnNjcmlwdFF1YWxpdHkoJGV2ZW50LmNoZWNrZWQpXCJcbiAgICAgICAgPjwvcC1jaGVja2JveD5cbiAgICAgICAgPGxhYmVsIGNsYXNzPVwic2MtbGJsXCIgZm9yPVwic2MtdHgtbG93cVwiPkluY2x1ZGUgbG93LXF1YWxpdHkgY2FsbHM8L2xhYmVsPlxuICAgICAgPC9kaXY+XG4gICAgPC9uZy1jb250YWluZXI+XG5cbiAgICA8bmctY29udGFpbmVyICpuZ0lmPVwidmlldy50cmFuc2NyaXB0TW9kZSA9PT0gJ2RlbnNpdHknXCI+XG4gICAgICA8c3BhbiBjbGFzcz1cInNjLWxibFwiPkRlbnNpdHkgbWFwIG9wYWNpdHk8L3NwYW4+XG4gICAgICA8ZGl2IGNsYXNzPVwic2Mtcm93IHNjLXJvdy1udW1iZXJcIj5cbiAgICAgICAgPHAtc2xpZGVyXG4gICAgICAgICAgW25nTW9kZWxdPVwidmlldy5kZW5zaXR5T3BhY2l0eVwiXG4gICAgICAgICAgW21pbl09XCIwLjA1XCJcbiAgICAgICAgICBbbWF4XT1cIjFcIlxuICAgICAgICAgIFtzdGVwXT1cIjAuMDVcIlxuICAgICAgICAgIChvbkNoYW5nZSk9XCJvbkRlbnNpdHlPcGFjaXR5KCRldmVudC52YWx1ZSlcIlxuICAgICAgICA+PC9wLXNsaWRlcj5cbiAgICAgICAgPHAtaW5wdXROdW1iZXJcbiAgICAgICAgICBbbmdNb2RlbF09XCJkZW5zaXR5T3BhY2l0eVBlcmNlbnRcIlxuICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cIm9uRGVuc2l0eU9wYWNpdHlQZXJjZW50KCRldmVudClcIlxuICAgICAgICAgIFttaW5dPVwiNVwiXG4gICAgICAgICAgW21heF09XCIxMDBcIlxuICAgICAgICAgIGlucHV0U3R5bGVDbGFzcz1cInNjLW51bVwiXG4gICAgICAgID48L3AtaW5wdXROdW1iZXI+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxzcGFuIGNsYXNzPVwic2MtbGJsXCIgcFRvb2x0aXA9XCJFZGdlIG9mIGVhY2ggZGVuc2l0eSBiaW5cIiB0b29sdGlwUG9zaXRpb249XCJ0b3BcIj5EZW5zaXR5IG1hcCBiaW4gc2l6ZTwvc3Bhbj5cbiAgICAgIDxwLXNsaWRlclxuICAgICAgICBbbmdNb2RlbF09XCJkZW5zaXR5QmluSW5kZXhcIlxuICAgICAgICBbbWluXT1cIjBcIlxuICAgICAgICBbbWF4XT1cIjNcIlxuICAgICAgICBbc3RlcF09XCIxXCJcbiAgICAgICAgKG9uQ2hhbmdlKT1cIm9uRGVuc2l0eUJpbkluZGV4KCRldmVudC52YWx1ZSlcIlxuICAgICAgICBzdHlsZUNsYXNzPVwic2MtYmluLXNsaWRlclwiXG4gICAgICA+PC9wLXNsaWRlcj5cbiAgICAgIDxkaXYgY2xhc3M9XCJzYy10aWNrc1wiPlxuICAgICAgICA8c3BhbiAqbmdGb3I9XCJsZXQgYiBvZiBkZW5zaXR5Qmluc1wiPnt7IGIgfX3Dl3t7IGIgfX3CtW08L3NwYW4+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxzcGFuXG4gICAgICAgIGNsYXNzPVwic2MtbGJsXCJcbiAgICAgICAgcFRvb2x0aXA9XCJUcmFuc2NyaXB0cyBwZXIgwrVtwrIgYXQgd2hpY2ggdGhlIGNvbG91ciBzY2FsZSBzdGFydHMgYW5kIHNhdHVyYXRlc1wiXG4gICAgICAgIHRvb2x0aXBQb3NpdGlvbj1cInRvcFwiXG4gICAgICAgID5EZW5zaXR5IG1hcCBzY2FsZSB0aHJlc2hvbGQ8L3NwYW5cbiAgICAgID5cbiAgICAgIDxkaXYgY2xhc3M9XCJzYy1yb3cgc2Mtcm93LXJhbmdlXCI+XG4gICAgICAgIDxwLWlucHV0TnVtYmVyXG4gICAgICAgICAgW25nTW9kZWxdPVwiZGVuc2l0eVdpbmRvd1swXVwiXG4gICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwib25EZW5zaXR5UmFuZ2VFbmQoMCwgJGV2ZW50KVwiXG4gICAgICAgICAgbW9kZT1cImRlY2ltYWxcIlxuICAgICAgICAgIFttaW5GcmFjdGlvbkRpZ2l0c109XCIzXCJcbiAgICAgICAgICBbbWF4RnJhY3Rpb25EaWdpdHNdPVwiM1wiXG4gICAgICAgICAgaW5wdXRTdHlsZUNsYXNzPVwic2MtbnVtXCJcbiAgICAgICAgPjwvcC1pbnB1dE51bWJlcj5cbiAgICAgICAgPHAtc2xpZGVyXG4gICAgICAgICAgW25nTW9kZWxdPVwiZGVuc2l0eVdpbmRvd1wiXG4gICAgICAgICAgW3JhbmdlXT1cInRydWVcIlxuICAgICAgICAgIFttaW5dPVwiMFwiXG4gICAgICAgICAgW21heF09XCJkZW5zaXR5U2xpZGVyTWF4XCJcbiAgICAgICAgICBbc3RlcF09XCJkZW5zaXR5U3RlcFwiXG4gICAgICAgICAgKG9uQ2hhbmdlKT1cIm9uRGVuc2l0eVJhbmdlKCRldmVudC52YWx1ZXMpXCJcbiAgICAgICAgPjwvcC1zbGlkZXI+XG4gICAgICAgIDxwLWlucHV0TnVtYmVyXG4gICAgICAgICAgW25nTW9kZWxdPVwiZGVuc2l0eVdpbmRvd1sxXVwiXG4gICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwib25EZW5zaXR5UmFuZ2VFbmQoMSwgJGV2ZW50KVwiXG4gICAgICAgICAgbW9kZT1cImRlY2ltYWxcIlxuICAgICAgICAgIFttaW5GcmFjdGlvbkRpZ2l0c109XCIzXCJcbiAgICAgICAgICBbbWF4RnJhY3Rpb25EaWdpdHNdPVwiM1wiXG4gICAgICAgICAgaW5wdXRTdHlsZUNsYXNzPVwic2MtbnVtXCJcbiAgICAgICAgPjwvcC1pbnB1dE51bWJlcj5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cInNjLXJvd1wiPlxuICAgICAgICA8c21hbGwgY2xhc3M9XCJzYy1oaW50XCI+e3sgdmlldy5kZW5zaXR5UmFuZ2UgPyAnU2V0IGJ5IGhhbmQuJyA6ICdEZXJpdmVkIGZyb20gdGhlIGRhdGEuJyB9fTwvc21hbGw+XG4gICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwic2Mtc21hbGwtYnRuXCIgKm5nSWY9XCJ2aWV3LmRlbnNpdHlSYW5nZVwiIChjbGljayk9XCJvbkRlbnNpdHlBdXRvKClcIj5cbiAgICAgICAgICBBdXRvXG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9kaXY+XG4gICAgICA8c3BhbiBjbGFzcz1cInNjLWxibFwiPkRlbnNpdHkgbWFwIGJpbiBjb2xvcmluZzwvc3Bhbj5cbiAgICAgIDxkaXYgY2xhc3M9XCJzYy1yb3cgc2Mtcm93LXBpY2tlclwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwic2MtY29sb3JiYXIgc2MtZnVsbFwiIFtzdHlsZS5iYWNrZ3JvdW5kXT1cImRlbnNpdHlDb2xvckJhckNzc1wiPjwvZGl2PlxuICAgICAgICA8cC10cmVlU2VsZWN0XG4gICAgICAgICAgW29wdGlvbnNdPVwiY29sb3JtYXBPcHRpb25zXCJcbiAgICAgICAgICBbbmdNb2RlbF09XCJzZWxlY3RlZERlbnNpdHlDb2xvcm1hcE5vZGVcIlxuICAgICAgICAgIHNlbGVjdGlvbk1vZGU9XCJzaW5nbGVcIlxuICAgICAgICAgIFtzaG93Q2xlYXJdPVwidHJ1ZVwiXG4gICAgICAgICAgcGxhY2Vob2xkZXI9XCJJbmZlcm5vXCJcbiAgICAgICAgICBbc2Nyb2xsSGVpZ2h0XT1cIicyNjBweCdcIlxuICAgICAgICAgIGFwcGVuZFRvPVwiYm9keVwiXG4gICAgICAgICAgc3R5bGVDbGFzcz1cInNjLXBhbGV0dGVcIlxuICAgICAgICAgIChvbk5vZGVTZWxlY3QpPVwib25EZW5zaXR5Q29sb3JtYXAoJGV2ZW50Lm5vZGUpXCJcbiAgICAgICAgICAob25DbGVhcik9XCJvbkRlbnNpdHlDb2xvcm1hcChudWxsKVwiXG4gICAgICAgID5cbiAgICAgICAgICA8bmctdGVtcGxhdGUgbGV0LW5vZGUgcFRlbXBsYXRlPVwiZGVmYXVsdFwiPlxuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJzYy1jbWFwLW9wdGlvblwiPlxuICAgICAgICAgICAgICA8aW1nICpuZ0lmPVwiIW5vZGUuY2hpbGRyZW4gJiYgbm9kZS5kYXRhPy5zcmNcIiBbc3JjXT1cIm5vZGUuZGF0YS5zcmNcIiBjbGFzcz1cInNjLWNtYXAtc3dhdGNoXCIgYWx0PVwiXCIgLz5cbiAgICAgICAgICAgICAgPHNwYW4+e3sgbm9kZS5sYWJlbCB9fTwvc3Bhbj5cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICA8L3AtdHJlZVNlbGVjdD5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cInNjLWNvbG9yYmFyLWVuZHNcIj5cbiAgICAgICAgPHNwYW4+e3sgZGVuc2l0eVdpbmRvd1swXSB8IG51bWJlcjogJzEuMC0zJyB9fTwvc3BhblxuICAgICAgICA+PHNwYW4+e3sgZGVuc2l0eVdpbmRvd1sxXSB8IG51bWJlcjogJzEuMC0zJyB9fTwvc3Bhbj5cbiAgICAgIDwvZGl2PlxuICAgIDwvbmctY29udGFpbmVyPlxuICA8L2Rpdj5cbjwvZGl2PlxuIl19
|
|
402
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3BhdGlhbC10cmFuc2NyaXB0cy1wYW5lbC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbGliL3NwYXRpYWwtY29udHJvbHMvc3BhdGlhbC10cmFuc2NyaXB0cy1wYW5lbC9zcGF0aWFsLXRyYW5zY3JpcHRzLXBhbmVsLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvc3BhdGlhbC1jb250cm9scy9zcGF0aWFsLXRyYW5zY3JpcHRzLXBhbmVsL3NwYXRpYWwtdHJhbnNjcmlwdHMtcGFuZWwuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLHVCQUF1QixFQUN2QixpQkFBaUIsRUFDakIsU0FBUyxFQUNULFVBQVUsRUFDVixZQUFZLEVBQ1osS0FBSyxFQUNMLE1BQU0sRUFFTixNQUFNLEVBRU4sU0FBUyxHQUNWLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUMzQyxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDbEQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3hELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDMUMsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDeEQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDMUQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzlDLE9BQU8sRUFB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eXZCQUNqQixVQUFVLGlxQkFDVixpQkFBaUIsbzFDQUNqQixrQkFBa0IseVZBQ2xCLFlBQVksZ1NBQ1osYUFBYSw4QkFDYixnQkFBZ0IsODRCQUNoQix3QkFBd0Isa0lBQ3hCLCtCQUErQjs7MkZBTXRCLGdDQUFnQztrQkF2QjVDLFNBQVM7K0JBQ0UsMkJBQTJCLGNBQ3pCLElBQUksV0FDUDt3QkFDUCxZQUFZO3dCQUNaLFdBQVc7d0JBQ1gsWUFBWTt3QkFDWixjQUFjO3dCQUNkLGNBQWM7d0JBQ2QsaUJBQWlCO3dCQUNqQixVQUFVO3dCQUNWLGlCQUFpQjt3QkFDakIsa0JBQWtCO3dCQUNsQixZQUFZO3dCQUNaLGFBQWE7d0JBQ2IsZ0JBQWdCO3dCQUNoQix3QkFBd0I7d0JBQ3hCLCtCQUErQjtxQkFDaEMsbUJBR2dCLHVCQUF1QixDQUFDLE1BQU07MkdBSXRDLFFBQVE7c0JBQWhCLEtBQUs7Z0JBRUcsT0FBTztzQkFBZixLQUFLO2dCQUVHLElBQUk7c0JBQVosS0FBSztnQkFFRyxLQUFLO3NCQUFiLEtBQUs7Z0JBRUcsUUFBUTtzQkFBaEIsS0FBSztnQkFFRyxZQUFZO3NCQUFwQixLQUFLO2dCQUVHLFVBQVU7c0JBQWxCLEtBQUs7Z0JBRUcsZUFBZTtzQkFBdkIsS0FBSztnQkFFRyxJQUFJO3NCQUFaLEtBQUs7Z0JBRWEsVUFBVTtzQkFBNUIsTUFBTTtnQkFtRDZCLGdCQUFnQjtzQkFBbkQsU0FBUzt1QkFBQyxlQUFlIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENoYW5nZURldGVjdG9yUmVmLFxuICBDb21wb25lbnQsXG4gIEVsZW1lbnRSZWYsXG4gIEV2ZW50RW1pdHRlcixcbiAgSW5wdXQsXG4gIE5nWm9uZSxcbiAgT25DaGFuZ2VzLFxuICBPdXRwdXQsXG4gIFNpbXBsZUNoYW5nZXMsXG4gIFZpZXdDaGlsZCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgRm9ybXNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBTaGFyZWRNb2R1bGUgfSBmcm9tICdwcmltZW5nL2FwaSc7XG5pbXBvcnQgeyBDaGVja2JveE1vZHVsZSB9IGZyb20gJ3ByaW1lbmcvY2hlY2tib3gnO1xuaW1wb3J0IHsgRHJvcGRvd25Nb2R1bGUgfSBmcm9tICdwcmltZW5nL2Ryb3Bkb3duJztcbmltcG9ydCB7IElucHV0TnVtYmVyTW9kdWxlIH0gZnJvbSAncHJpbWVuZy9pbnB1dG51bWJlcic7XG5pbXBvcnQgeyBNZW51TW9kdWxlIH0gZnJvbSAncHJpbWVuZy9tZW51JztcbmltcG9ydCB7IE11bHRpU2VsZWN0TW9kdWxlIH0gZnJvbSAncHJpbWVuZy9tdWx0aXNlbGVjdCc7XG5pbXBvcnQgeyBTZWxlY3RCdXR0b25Nb2R1bGUgfSBmcm9tICdwcmltZW5nL3NlbGVjdGJ1dHRvbic7XG5pbXBvcnQgeyBTbGlkZXJNb2R1bGUgfSBmcm9tICdwcmltZW5nL3NsaWRlcic7XG5pbXBvcnQgeyBUb29sdGlwTW9kdWxlIH0gZnJvbSAncHJpbWVuZy90b29sdGlwJztcbmltcG9ydCB7IFRyZWVTZWxlY3RNb2R1bGUgfSBmcm9tICdwcmltZW5nL3RyZWVzZWxlY3QnO1xuXG5pbXBvcnQgdHlwZSB7IElTcGF0aWFsQ29udHJvbHMgfSBmcm9tICcuLi8uLi9jb250cmFjdHMvdmlzdWFsaXplci5jb250cmFjdCc7XG5pbXBvcnQgdHlwZSB7IFNwYXRpYWxEYXRhc2V0IH0gZnJvbSAnLi4vLi4vY29udHJhY3RzL3NwYXRpYWwtZGF0YXNldC5jb250cmFjdCc7XG5pbXBvcnQge1xuICBDb2xvcm1hcE5vZGUsXG4gIERFRkFVTFRfU1BBVElBTF9WSUVXLFxuICBTcGF0aWFsVmlld1N0YXRlLFxuICBUcmFuc2NyaXB0R2x5cGhOYW1lLFxufSBmcm9tICcuLi8uLi9jb250cmFjdHMvZGlzcGxheS10eXBlcyc7XG5pbXBvcnQgeyBkZWZhdWx0R2x5cGhGb3IgfSBmcm9tICcuLi8uLi9zcGF0aWFsL3NwYXRpYWwtdGlsZXMnO1xuaW1wb3J0IHsgY2VsbFR5cGVDb2x1bW5Gb3IgfSBmcm9tICcuLi8uLi9zcGF0aWFsL2xvZCc7XG5pbXBvcnQgeyBldmVyeUdlbmVPZmYgfSBmcm9tICcuLi8uLi9zcGF0aWFsL3NwYXRpYWwtdGlsZS1tZXJnZSc7XG5pbXBvcnQge1xuICBHTFlQSF9PUFRJT05TLFxuICBQYW5lbE9wdGlvbixcbiAgYWxsR2VuZXNQcmVwYXJpbmdOb3RlLFxuICBkZW5zaXR5Q29sb3JCYXJDc3MsXG4gIGltcG9ydEdlbmVHcm91cHNQYXRjaCxcbiAgbWFya2VyQ29sdW1uT3B0aW9ucyxcbiAgcGFyc2VHZW5lR3JvdXBzLFxuICB0aWxlT3B0aW9ucyxcbn0gZnJvbSAnLi4vLi4vc3BhdGlhbC9zcGF0aWFsLXBhbmVsLW1vZGVsJztcbmltcG9ydCB0eXBlIHsgR2VuZVBpY2tlck1vZGVsIH0gZnJvbSAnLi4vc3BhdGlhbC1nZW5lLXBpY2tlcic7XG5pbXBvcnQgeyBjb2xvcm1hcE5vZGVGb3IgfSBmcm9tICcuLi9zcGF0aWFsLWtleS9zcGF0aWFsLWtleS5jb21wb25lbnQnO1xuaW1wb3J0IHsgU3BhdGlhbEdlbmVUcmVlQ29tcG9uZW50IH0gZnJvbSAnLi4vc3BhdGlhbC1nZW5lLXRyZWUvc3BhdGlhbC1nZW5lLXRyZWUuY29tcG9uZW50JztcbmltcG9ydCB7IFNwYXRpYWxNYXJrZXJHZW5lc0Zvcm1Db21wb25lbnQgfSBmcm9tICcuLi9zcGF0aWFsLW1hcmtlci1nZW5lcy1mb3JtL3NwYXRpYWwtbWFya2VyLWdlbmVzLWZvcm0uY29tcG9uZW50JztcbmltcG9ydCB7IGhhc0dlbmVGaWx0ZXIgfSBmcm9tICcuLi8uLi9zcGF0aWFsL3NwYXRpYWwtZ2VuZS1maWx0ZXInO1xuXG4vKiogT25lIGl0ZW0gb2YgdGhlIGdlbmUgbGlzdCdzICfii64nIG1lbnUuICovXG5leHBvcnQgaW50ZXJmYWNlIEdlbmVNZW51SXRlbSB7XG4gIGxhYmVsOiBzdHJpbmc7XG4gIGljb246IHN0cmluZztcbiAgY29tbWFuZDogKCkgPT4gdm9pZDtcbiAgZGlzYWJsZWQ/OiBib29sZWFuO1xufVxuXG4vKipcbiAqIFRoZSBUcmFuc2NyaXB0cyBzZWN0aW9uLCBhcyBYZW5pdW0gRXhwbG9yZXInczogdGhlIG9uL29mZiBzd2l0Y2gsIHRoZSB0cmFuc2NyaXB0IGdlbmVzXG4gKiAod2l0aCBcIkFsbCBnZW5lc1wiLCB0aGUgJ+KLricgbWVudSBhbmQgZ2VuZS1ncm91cCBpbXBvcnQpLCB0aGVcbiAqIHtAbGluayBTcGF0aWFsTWFya2VyR2VuZXNGb3JtQ29tcG9uZW50IG1hcmtlci1nZW5lcyBmb3JtfSwgdGhlXG4gKiB7QGxpbmsgU3BhdGlhbEdlbmVUcmVlQ29tcG9uZW50IGdlbmUgdHJlZX0sIGhvdyB0cmFuc2NyaXB0cyBhcmUgZHJhd24g4oCUIHRoZSBwb2ludHNcbiAqIGVzdGltYXRlIGFnYWluc3QgaXRzIGJ1ZGdldCwgY29sb3VyaW5nLCBpY29uLCBzaXplLCBvcGFjaXR5IGFuZCBxdWFsaXR5IOKAlCBhbmQgdGhlXG4gKiBkZW5zaXR5IG1hcCdzIG9wYWNpdHksIGJpbiBzaXplLCB0aHJlc2hvbGQgd2luZG93IGFuZCBjb2xvcm1hcC5cbiAqXG4gKiBXcml0ZXMgb25seSB0aHJvdWdoIGBjb250cm9scy5zZXRWaWV3U3RhdGVgLlxuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdzcGF0aWFsLXRyYW5zY3JpcHRzLXBhbmVsJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW1xuICAgIENvbW1vbk1vZHVsZSxcbiAgICBGb3Jtc01vZHVsZSxcbiAgICBTaGFyZWRNb2R1bGUsXG4gICAgQ2hlY2tib3hNb2R1bGUsXG4gICAgRHJvcGRvd25Nb2R1bGUsXG4gICAgSW5wdXROdW1iZXJNb2R1bGUsXG4gICAgTWVudU1vZHVsZSxcbiAgICBNdWx0aVNlbGVjdE1vZHVsZSxcbiAgICBTZWxlY3RCdXR0b25Nb2R1bGUsXG4gICAgU2xpZGVyTW9kdWxlLFxuICAgIFRvb2x0aXBNb2R1bGUsXG4gICAgVHJlZVNlbGVjdE1vZHVsZSxcbiAgICBTcGF0aWFsR2VuZVRyZWVDb21wb25lbnQsXG4gICAgU3BhdGlhbE1hcmtlckdlbmVzRm9ybUNvbXBvbmVudCxcbiAgXSxcbiAgdGVtcGxhdGVVcmw6ICcuL3NwYXRpYWwtdHJhbnNjcmlwdHMtcGFuZWwuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9zcGF0aWFsLXRyYW5zY3JpcHRzLXBhbmVsLmNvbXBvbmVudC5zY3NzJ10sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxufSlcbmV4cG9ydCBjbGFzcyBTcGF0aWFsVHJhbnNjcmlwdHNQYW5lbENvbXBvbmVudCBpbXBsZW1lbnRzIE9uQ2hhbmdlcyB7XG4gIC8qKiBUaGUgc3BhdGlhbCBjb250cm9scyB0aGlzIHBhbmVsIHJlYWRzIGFuZCB3cml0ZXMgdGhyb3VnaDsgbnVsbCB3aXRob3V0IGEgYFNQQVRJQUxfREFUQV9QT1JUYC4gKi9cbiAgQElucHV0KCkgY29udHJvbHM6IElTcGF0aWFsQ29udHJvbHMgfCBudWxsID0gbnVsbDtcbiAgLyoqIFRoZSBkYXRhc2V0IG9uIG9mZmVyLCBvciBudWxsLiAqL1xuICBASW5wdXQoKSBkYXRhc2V0OiBTcGF0aWFsRGF0YXNldCB8IG51bGwgPSBudWxsO1xuICAvKiogVGhlIGN1cnJlbnQgc3BhdGlhbCB2aWV3IHN0YXRlOiB3aGF0IGlzIGRyYXduLCBhbmQgaG93LiAqL1xuICBASW5wdXQoKSB2aWV3OiBTcGF0aWFsVmlld1N0YXRlID0gREVGQVVMVF9TUEFUSUFMX1ZJRVc7XG4gIC8qKiBUaGUgZ2VuZSBsaXN0IHRoZSB0cmFuc2NyaXB0IGdlbmVzIGFyZSBwaWNrZWQgZnJvbSwgc2hhcmVkIHdpdGggdGhlIG90aGVyIGdlbmUgZHJvcGRvd25zLiAqL1xuICBASW5wdXQoKSBnZW5lczogR2VuZVBpY2tlck1vZGVsIHwgbnVsbCA9IG51bGw7XG4gIC8qKiBFc3RpbWF0ZWQgdHJhbnNjcmlwdHMgaW4gdmlldywgYWdhaW5zdCB0aGUgYnVkZ2V0IOKAlCBFeHBsb3JlcidzIHBvaW50cyBiYXIuICovXG4gIEBJbnB1dCgpIGVzdGltYXRlOiB7IHBvaW50czogbnVtYmVyOyBtYXg6IG51bWJlciB9IHwgbnVsbCA9IG51bGw7XG4gIC8qKiBUaGUgZGVuc2l0eSB3aW5kb3cgaW4gdXNlIGFuZCBpdHMgZGVuc2VzdCBiaW4sIGZvciB0aGUgdGhyZXNob2xkIGNvbnRyb2wuICovXG4gIEBJbnB1dCgpIGRlbnNpdHlTdGF0czogeyBsbzogbnVtYmVyOyBoaTogbnVtYmVyOyBtYXg6IG51bWJlciB9IHwgbnVsbCA9IG51bGw7XG4gIC8qKiBUcmFuc2NyaXB0cyBvZiBlYWNoIHNlbGVjdGVkIGdlbmUgaW4gdGhlIGN1cnJlbnQgdmlldywgZnJvbSB0aGUgcmVuZGVyZXIuICovXG4gIEBJbnB1dCgpIGdlbmVDb3VudHM6IFJlY29yZDxzdHJpbmcsIG51bWJlcj4gfCBudWxsID0gbnVsbDtcbiAgLyoqIENvbG9ybWFwIHRyZWUgZm9yIHRoZSBkZW5zaXR5IG1hcCdzIGNvbG91cmluZy4gKi9cbiAgQElucHV0KCkgY29sb3JtYXBPcHRpb25zOiBDb2xvcm1hcE5vZGVbXSA9IFtdO1xuICAvKiogV2hldGhlciB0aGUgc2VjdGlvbiBpcyBleHBhbmRlZC4gKi9cbiAgQElucHV0KCkgb3BlbiA9IGZhbHNlO1xuICAvKiogQXNrcyB0byBvcGVuIG9yIGNsb3NlIGl0OyB0d28td2F5IHdpdGggYG9wZW5gLiAqL1xuICBAT3V0cHV0KCkgcmVhZG9ubHkgb3BlbkNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4oKTtcblxuICAvKiogVmlydHVhbC1zY3JvbGxlZCBvbmx5IHBhc3QgdGhpcyBtYW55IG9wdGlvbnMgKHNlZSB0aGUgY2VsbHMgcGFuZWwncyBnZW5lIGRyb3Bkb3duKS4gKi9cbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGdlbmVWaXJ0dWFsU2Nyb2xsRnJvbSA9IDIwMDtcbiAgLyoqXG4gICAqIENvbG91cmluZ3Mgb24gb2ZmZXI6IFwiQ2VsbCB0eXBlXCIgb25seSBmb3IgYSBkYXRhc2V0IHdpdGggY2VsbCB0eXBlcy4gUmVidWlsdCBvbmx5IHdoZW4gdGhhdFxuICAgKiBjaGFuZ2VzLCBmb3IgdGhlIHNhbWUgcmVhc29uIGFzIHtAbGluayB0cmFuc2NyaXB0TW9kZU9wdGlvbnN9LlxuICAgKi9cbiAgcHJvdGVjdGVkIHRyYW5zY3JpcHRDb2xvck9wdGlvbnM6IFBhbmVsT3B0aW9uPFNwYXRpYWxWaWV3U3RhdGVbJ3RyYW5zY3JpcHRDb2xvckJ5J10+W10gPSBbXTtcbiAgLyoqIFdoZXRoZXIgdGhlIGRhdGFzZXQgaGFzIGEgY29sdW1uIG5hbWluZyBlYWNoIGNlbGwncyB0eXBlIChzZWUgYGNlbGxUeXBlQ29sdW1uRm9yYCkuICovXG4gIHByb3RlY3RlZCBoYXNDZWxsVHlwZXMgPSBmYWxzZTtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGdseXBoT3B0aW9ucyA9IEdMWVBIX09QVElPTlM7XG4gIHByb3RlY3RlZCByZWFkb25seSBidWRnZXRPcHRpb25zID0gWzI1XzAwMCwgNTBfMDAwLCAxMDBfMDAwLCAyMDBfMDAwLCA0MDBfMDAwXS5tYXAoKG4pID0+ICh7XG4gICAgbGFiZWw6IG4udG9Mb2NhbGVTdHJpbmcoKSxcbiAgICB2YWx1ZTogbixcbiAgfSkpO1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgZGVuc2l0eUJpbnMgPSBbMTAsIDIwLCA0MCwgODBdO1xuXG4gIC8qKlxuICAgKiBUcmFuc2NyaXB0IG1vZGVzIG9uIG9mZmVyLiBCdWlsdCBvbmNlIHBlciBkYXRhc2V0IHJhdGhlciB0aGFuIGluIGEgZ2V0dGVyOiBhIGdldHRlclxuICAgKiByZXR1cm5zIGEgZnJlc2ggYXJyYXkgb24gZXZlcnkgY2hhbmdlLWRldGVjdGlvbiBwYXNzLCBhbmQgUHJpbWVORyByZS1yZW5kZXJzIGl0c1xuICAgKiBidXR0b25zIHdoZW5ldmVyIHRoZSBhcnJheSBpZGVudGl0eSBjaGFuZ2VzIOKAlCB3aGljaCBtYWRlIHRoZW0gaW1wb3NzaWJsZSB0byBjbGljay5cbiAgICovXG4gIHByb3RlY3RlZCB0cmFuc2NyaXB0TW9kZU9wdGlvbnM6IFBhbmVsT3B0aW9uPFNwYXRpYWxWaWV3U3RhdGVbJ3RyYW5zY3JpcHRNb2RlJ10+W10gPSBbXTtcbiAgLyoqIFRoZSAn4ouuJyBtZW51LCByZWJ1aWx0IHdoZW4gd2hhdCBlbmFibGVzIGl0cyBpdGVtcyBjaGFuZ2VzLiAqL1xuICBwcm90ZWN0ZWQgZ2VuZU1lbnU6IEdlbmVNZW51SXRlbVtdID0gW107XG4gIHByb3RlY3RlZCBlZGl0aW5nTWF4ID0gZmFsc2U7XG4gIC8qKiBXaGV0aGVyIHRoZSBtYXJrZXItZ2VuZXMgZm9ybSBpcyBzaG93bi4gKi9cbiAgcHJvdGVjdGVkIG1hcmtlcnNPcGVuID0gZmFsc2U7XG4gIHByb3RlY3RlZCBnZW5lR3JvdXBFcnJvcjogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG5cbiAgLyoqXG4gICAqIFRoZSB0aHJlc2hvbGQgd2luZG93IHNob3duOiB0aGUgb25lIHNldCwgZWxzZSB0aGUgb25lIGRlcml2ZWQuIEEgc3RvcmVkIGFycmF5LCBub3QgYVxuICAgKiBnZXR0ZXI6IGEgcmFuZ2Ugc2xpZGVyJ3MgYG5nTW9kZWxgIGdpdmVuIGEgZnJlc2ggYXJyYXkgZXZlcnkgY2hhbmdlLWRldGVjdGlvbiBwYXNzXG4gICAqIHNjaGVkdWxlcyBhbm90aGVyIHBhc3MsIGZvcmV2ZXIg4oCUIHdoaWNoIGh1bmcgdGhlIHBhZ2UgdGhlIG1vbWVudCB0aGUgZGVuc2l0eVxuICAgKiBjb250cm9scyBhcHBlYXJlZC5cbiAgICovXG4gIHByb3RlY3RlZCBkZW5zaXR5V2luZG93OiBbbnVtYmVyLCBudW1iZXJdID0gWzAsIDFdO1xuICBwcm90ZWN0ZWQgZGVuc2l0eVNsaWRlck1heCA9IDE7XG4gIHByb3RlY3RlZCBkZW5zaXR5U3RlcCA9IDAuMDA1O1xuICBwcm90ZWN0ZWQgc2VsZWN0ZWREZW5zaXR5Q29sb3JtYXBOb2RlOiBDb2xvcm1hcE5vZGUgfCBudWxsID0gbnVsbDtcbiAgLyoqIEJ1aWx0IG9uY2UgcGVyIGRlbnNpdHkgY29sb3JtYXA6IGEgMjU2LWVudHJ5IExVVCBwZXIgY2hhbmdlLWRldGVjdGlvbiBwYXNzIGlzIHdhc3RlLiAqL1xuICBwcm90ZWN0ZWQgZGVuc2l0eUNvbG9yQmFyQ3NzID0gJyc7XG4gIHByaXZhdGUgZGVuc2l0eUJhckZvcjogU3BhdGlhbFZpZXdTdGF0ZVsnZGVuc2l0eUNvbG9ybWFwJ10gfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG5cbiAgLyoqIFRoZSBtb2RlIHRoZSBzZWN0aW9uIGhlYWRlcidzIHN3aXRjaCB0dXJucyBiYWNrIG9uLiAqL1xuICBwcml2YXRlIGxhc3RUcmFuc2NyaXB0TW9kZTogRXhjbHVkZTxTcGF0aWFsVmlld1N0YXRlWyd0cmFuc2NyaXB0TW9kZSddLCAnb2ZmJz4gPSAnY2lyY2xlcyc7XG4gIC8qKiBXaGV0aGVyIGFueSBjb2x1bW4gY2FuIHN1cHBseSBtYXJrZXIgZ2VuZXMnIGNsdXN0ZXJzLiAqL1xuICBwcml2YXRlIGhhc01hcmtlckNvbHVtbnMgPSBmYWxzZTtcblxuICAvKiogVGhlIGhpZGRlbiBmaWxlIGlucHV0IHRoZSBtZW51J3MgaW1wb3J0IG9wZW5zLiAqL1xuICBAVmlld0NoaWxkKCdnZW5lR3JvdXBGaWxlJykgcHJpdmF0ZSBnZW5lR3JvdXBGaWxlUmVmPzogRWxlbWVudFJlZjxIVE1MSW5wdXRFbGVtZW50PjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IHpvbmU6IE5nWm9uZSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGNkcjogQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICkge31cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgaWYgKGNoYW5nZXNbJ2RhdGFzZXQnXSkge1xuICAgICAgdGhpcy50cmFuc2NyaXB0TW9kZU9wdGlvbnMgPSB0aWxlT3B0aW9ucyh0aGlzLmRhdGFzZXQpLnRyYW5zY3JpcHRNb2RlT3B0aW9ucztcbiAgICAgIHRoaXMuaGFzTWFya2VyQ29sdW1ucyA9IG1hcmtlckNvbHVtbk9wdGlvbnModGhpcy5kYXRhc2V0Py5jb2x1bW5zKS5sZW5ndGggPiAwO1xuICAgIH1cbiAgICBpZiAoY2hhbmdlc1sndmlldyddIHx8IGNoYW5nZXNbJ2RhdGFzZXQnXSB8fCBjaGFuZ2VzWydjb250cm9scyddKSB0aGlzLmdlbmVNZW51ID0gdGhpcy5idWlsZEdlbmVNZW51KCk7XG4gICAgaWYgKGNoYW5nZXNbJ3ZpZXcnXSB8fCBjaGFuZ2VzWydkYXRhc2V0J10pIHtcbiAgICAgIGNvbnN0IGhhc0NlbGxUeXBlcyA9ICEhdGhpcy5kYXRhc2V0ICYmIGNlbGxUeXBlQ29sdW1uRm9yKHRoaXMuZGF0YXNldCwgdGhpcy52aWV3KSAhPT0gbnVsbDtcbiAgICAgIGlmIChoYXNDZWxsVHlwZXMgIT09IHRoaXMuaGFzQ2VsbFR5cGVzIHx8ICF0aGlzLnRyYW5zY3JpcHRDb2xvck9wdGlvbnMubGVuZ3RoKSB7XG4gICAgICAgIHRoaXMuaGFzQ2VsbFR5cGVzID0gaGFzQ2VsbFR5cGVzO1xuICAgICAgICB0aGlzLnRyYW5zY3JpcHRDb2xvck9wdGlvbnMgPSBbXG4gICAgICAgICAgeyBsYWJlbDogJ0NsdXN0ZXInLCB2YWx1ZTogJ2NsdXN0ZXInIH0sXG4gICAgICAgICAgLi4uKGhhc0NlbGxUeXBlcyA/IFt7IGxhYmVsOiAnQ2VsbCB0eXBlJywgdmFsdWU6ICdjZWxsVHlwZScgYXMgY29uc3QgfV0gOiBbXSksXG4gICAgICAgICAgeyBsYWJlbDogJ0dlbmUnLCB2YWx1ZTogJ2dlbmUnIH0sXG4gICAgICAgIF07XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChjaGFuZ2VzWyd2aWV3J10gfHwgY2hhbmdlc1snY29sb3JtYXBPcHRpb25zJ10pIHtcbiAgICAgIHRoaXMuc2VsZWN0ZWREZW5zaXR5Q29sb3JtYXBOb2RlID0gY29sb3JtYXBOb2RlRm9yKHRoaXMuY29sb3JtYXBPcHRpb25zLCB0aGlzLnZpZXcuZGVuc2l0eUNvbG9ybWFwKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuZGVuc2l0eUJhckZvciAhPT0gdGhpcy52aWV3LmRlbnNpdHlDb2xvcm1hcCB8fCAhdGhpcy5kZW5zaXR5Q29sb3JCYXJDc3MpIHtcbiAgICAgIHRoaXMuZGVuc2l0eUJhckZvciA9IHRoaXMudmlldy5kZW5zaXR5Q29sb3JtYXA7XG4gICAgICB0aGlzLmRlbnNpdHlDb2xvckJhckNzcyA9IGRlbnNpdHlDb2xvckJhckNzcyh0aGlzLnZpZXcuZGVuc2l0eUNvbG9ybWFwKTtcbiAgICB9XG4gICAgdGhpcy5yZWZyZXNoRGVuc2l0eVdpbmRvdygpO1xuICB9XG5cbiAgLy8g4pSA4pSAIHRoZSBzZWN0aW9uIHN3aXRjaCBhbmQgdGhlIGdlbmVzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gIHByb3RlY3RlZCBvblRyYW5zY3JpcHRzT24ob246IGJvb2xlYW4pOiB2b2lkIHtcbiAgICBpZiAoIW9uKSB7XG4gICAgICBpZiAodGhpcy52aWV3LnRyYW5zY3JpcHRNb2RlICE9PSAnb2ZmJykgdGhpcy5sYXN0VHJhbnNjcmlwdE1vZGUgPSB0aGlzLnZpZXcudHJhbnNjcmlwdE1vZGU7XG4gICAgICB0aGlzLmNvbnRyb2xzPy5zZXRWaWV3U3RhdGUoeyB0cmFuc2NyaXB0TW9kZTogJ29mZicgfSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IG1vZGUgPSB0aGlzLmRhdGFzZXQ/LnRyYW5zY3JpcHRUaWxlcyA/IHRoaXMubGFzdFRyYW5zY3JpcHRNb2RlIDogJ2RlbnNpdHknO1xuICAgIHRoaXMub25UcmFuc2NyaXB0TW9kZShtb2RlKTtcbiAgICB0aGlzLm9wZW5DaGFuZ2UuZW1pdCh0cnVlKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvblRyYW5zY3JpcHRNb2RlKG1vZGU6IFNwYXRpYWxWaWV3U3RhdGVbJ3RyYW5zY3JpcHRNb2RlJ10pOiB2b2lkIHtcbiAgICAvLyBTZWVkIHRoZSBnZW5lIGxpc3QgZnJvbSB0aGUgZ2VuZSBiZWluZyBjb2xvdXJlZCBieSwgc28gc3dpdGNoaW5nIHRyYW5zY3JpcHRzIG9uXG4gICAgLy8gc2hvd3Mgc29tZXRoaW5nIHN0cmFpZ2h0IGF3YXkuXG4gICAgY29uc3Qgc2VlZCA9XG4gICAgICAhdGhpcy52aWV3LnRyYW5zY3JpcHRHZW5lcy5sZW5ndGggJiYgdGhpcy52aWV3LmNvbG9yQnk/LmtpbmQgPT09ICdmZWF0dXJlJyA/IFt0aGlzLnZpZXcuY29sb3JCeS5uYW1lXSA6IG51bGw7XG4gICAgdGhpcy5jb250cm9scz8uc2V0Vmlld1N0YXRlKHsgdHJhbnNjcmlwdE1vZGU6IG1vZGUsIC4uLihzZWVkID8geyB0cmFuc2NyaXB0R2VuZXM6IHNlZWQgfSA6IHt9KSB9KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvblRyYW5zY3JpcHRHZW5lcyhnZW5lczogc3RyaW5nW10gfCBudWxsKTogdm9pZCB7XG4gICAgdGhpcy5jb250cm9scz8uc2V0Vmlld1N0YXRlKHsgdHJhbnNjcmlwdEdlbmVzOiBbLi4uKGdlbmVzID8/IFtdKV0gfSk7XG4gIH1cblxuICAvKiogUmVhbCBnZW5lcyBpbiB0aGUgcGFuZWwg4oCUIHRoZSB0cmVlJ3MgZGVub21pbmF0b3IuICovXG4gIHByb3RlY3RlZCBnZXQgZ2VuZVRvdGFsKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIChcbiAgICAgIHRoaXMuZGF0YXNldD8udHJhbnNjcmlwdFRpbGVzPy5nZW5lQ291bnQgPz8gdGhpcy5kYXRhc2V0Py5mZWF0dXJlcz8uY291bnQgPz8gdGhpcy5nZW5lcz8ucmVzaWRlbnRDb3VudCA/PyAwXG4gICAgKTtcbiAgfVxuXG4gIC8qKiBcIkFsbCBnZW5lc1wiIG5lZWRzIHRoZSBncm91cGluZyBweXJhbWlkLCBvciBhdCBsZWFzdCB0aWxlcyB0byBkcmF3IGluZGl2aWR1YWxseS4gKi9cbiAgcHJvdGVjdGVkIGdldCBjYW5TaG93QWxsR2VuZXMoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICEhdGhpcy5kYXRhc2V0Py50cmFuc2NyaXB0QmlucztcbiAgfVxuXG4gIC8qKiBXaHkgXCJBbGwgZ2VuZXNcIiBpcyBub3Qgb2ZmZXJlZCB5ZXQsIHdoaWxlIHRoZSBzZXJ2ZXIgYnVpbGRzIGl0cyBweXJhbWlkLiAqL1xuICBwcm90ZWN0ZWQgZ2V0IGFsbEdlbmVzUHJlcGFyaW5nKCk6IHN0cmluZyB8IG51bGwge1xuICAgIHJldHVybiBhbGxHZW5lc1ByZXBhcmluZ05vdGUodGhpcy5kYXRhc2V0KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBnZXQgc2hvd2luZ0FsbEdlbmVzKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmNhblNob3dBbGxHZW5lcyAmJiB0aGlzLnZpZXcudHJhbnNjcmlwdEFsbEdlbmVzICYmIHRoaXMudmlldy50cmFuc2NyaXB0TW9kZSAhPT0gJ2RlbnNpdHknO1xuICB9XG5cbiAgb25UcmFuc2NyaXB0QWxsR2VuZXMob246IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAvLyBcIkFsbCBnZW5lc1wiIHN3aXRjaGVkIG9mZiB3aG9sZSB3aXRoIHRoZSB0cmVlJ3Mgcm9vdCBleWUgc3RheXMgYSBwcm9wZXJ0eSBvZiB0aGF0IG9uZSB2aXNpdDtcbiAgICAvLyBnZW5lcyBoaWRkZW4gb25lIGJ5IG9uZSBhcmUga2VwdCBmb3IgdGhlIG5leHQuXG4gICAgY29uc3Qgd2hvbGVPZmYgPSBldmVyeUdlbmVPZmYodGhpcy52aWV3LnRyYW5zY3JpcHRBbGxHZW5lc0hpZGRlbik7XG4gICAgdGhpcy5jb250cm9scz8uc2V0Vmlld1N0YXRlKHsgdHJhbnNjcmlwdEFsbEdlbmVzOiBvbiwgLi4uKHdob2xlT2ZmID8geyB0cmFuc2NyaXB0QWxsR2VuZXNIaWRkZW46IFtdIH0gOiB7fSkgfSk7XG4gIH1cblxuICAvKiogJ8KxJzogZXZlcnkgZ2VuZSwgb3IgYmFjayB0byB0aGUgY2hvc2VuIGxpc3QuICovXG4gIHByb3RlY3RlZCBvblRvZ2dsZUFsbEdlbmVzKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5jYW5TaG93QWxsR2VuZXMpIHJldHVybjtcbiAgICB0aGlzLm9uVHJhbnNjcmlwdEFsbEdlbmVzKCF0aGlzLnZpZXcudHJhbnNjcmlwdEFsbEdlbmVzKTtcbiAgfVxuXG4gIGdldCBjYW5BZGRNYXJrZXJzKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAhIXRoaXMuY29udHJvbHM/Lm1hcmtlckdlbmVzICYmIHRoaXMuaGFzTWFya2VyQ29sdW1ucztcbiAgfVxuXG4gIC8qKiBPcGVuIHRoZSBtYXJrZXItZ2VuZXMgZm9ybSAoZnJvbSB0aGUgJ+KLricgbWVudSkuICovXG4gIG9wZW5NYXJrZXJzKCk6IHZvaWQge1xuICAgIHRoaXMubWFya2Vyc09wZW4gPSB0cnVlO1xuICAgIHRoaXMub3BlbkNoYW5nZS5lbWl0KHRydWUpO1xuICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgb25OZXdHZW5lR3JvdXAoKTogdm9pZCB7XG4gICAgY29uc3QgbmFtZSA9IChnbG9iYWxUaGlzLnByb21wdD8uKCdOYW1lIGZvciB0aGlzIGdlbmUgZ3JvdXAnLCAnR2VuZSBncm91cCcpID8/ICcnKS50cmltKCk7XG4gICAgaWYgKCFuYW1lKSByZXR1cm47XG4gICAgY29uc3QgZ3JvdXBzID0gdGhpcy52aWV3LnRyYW5zY3JpcHRHZW5lR3JvdXBzLmZpbHRlcigoZykgPT4gZy5uYW1lICE9PSBuYW1lKTtcbiAgICB0aGlzLmNvbnRyb2xzPy5zZXRWaWV3U3RhdGUoe1xuICAgICAgdHJhbnNjcmlwdEdlbmVHcm91cHM6IFsuLi5ncm91cHMsIHsgbmFtZSwgZ2VuZXM6IFsuLi50aGlzLnZpZXcudHJhbnNjcmlwdEdlbmVzXSB9XSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbXBvcnQgZ2VuZSBncm91cHM6IENTVi9UU1Ygd2l0aCBhIGdyb3VwIGFuZCBhIGdlbmUgY29sdW1uIChoZWFkZXIgb3B0aW9uYWwpLCBlLmcuXG4gICAqIG1hcmtlciBnZW5lcyBwZXIgY2VsbCB0eXBlLiBUaGUgZ2VuZXMgYXJlIGFkZGVkIHRvIHRoZSBzZWxlY3Rpb24uXG4gICAqL1xuICBwcm90ZWN0ZWQgYXN5bmMgb25JbXBvcnRHZW5lR3JvdXBzKGlucHV0OiBIVE1MSW5wdXRFbGVtZW50KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgZmlsZSA9IGlucHV0LmZpbGVzPy5bMF07XG4gICAgaW5wdXQudmFsdWUgPSAnJztcbiAgICBpZiAoIWZpbGUpIHJldHVybjtcbiAgICB0aGlzLmdlbmVHcm91cEVycm9yID0gbnVsbDtcbiAgICBjb25zdCBncm91cHMgPSBwYXJzZUdlbmVHcm91cHMoYXdhaXQgZmlsZS50ZXh0KCkpO1xuICAgIHRoaXMuem9uZS5ydW4oKCkgPT4ge1xuICAgICAgaWYgKCFncm91cHMubGVuZ3RoKSB0aGlzLmdlbmVHcm91cEVycm9yID0gJ05vIFwiZ3JvdXAsZ2VuZVwiIHJvd3MgZm91bmQgaW4gdGhhdCBmaWxlLic7XG4gICAgICBlbHNlIHRoaXMuY29udHJvbHM/LnNldFZpZXdTdGF0ZShpbXBvcnRHZW5lR3JvdXBzUGF0Y2godGhpcy52aWV3LCBncm91cHMpKTtcbiAgICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICAgIH0pO1xuICB9XG5cbiAgLy8g4pSA4pSAIGhvdyB0cmFuc2NyaXB0cyBhcmUgZHJhd24g4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgcHJvdGVjdGVkIGdldCBlc3RpbWF0ZVBlcmNlbnQoKTogbnVtYmVyIHtcbiAgICBjb25zdCBlID0gdGhpcy5lc3RpbWF0ZTtcbiAgICByZXR1cm4gZSAmJiBlLm1heCA+IDAgPyBNYXRoLm1pbigxMDAsICgxMDAgKiBlLnBvaW50cykgLyBlLm1heCkgOiAwO1xuICB9XG5cbiAgLyoqIFdoZXRoZXIgdGhlIE9ic2VydmF0aW9ucyBnZW5lIGZpbHRlciBpcyBvbiwgd2hpY2ggbGltaXRzIHRoZSB0cmFuc2NyaXB0cyBkcmF3bi4gKi9cbiAgcHJvdGVjdGVkIGdldCBvYnNlcnZhdGlvbnNGaWx0ZXJlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gaGFzR2VuZUZpbHRlcih0aGlzLnZpZXcpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGdldCBlc3RpbWF0ZU92ZXJNYXgoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICEhdGhpcy5lc3RpbWF0ZSAmJiB0aGlzLmVzdGltYXRlLnBvaW50cyA+IHRoaXMuZXN0aW1hdGUubWF4O1xuICB9XG5cbiAgcHJvdGVjdGVkIG9uVHJhbnNjcmlwdEJ1ZGdldChuOiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLmNvbnRyb2xzPy5zZXRWaWV3U3RhdGUoeyB0cmFuc2NyaXB0QnVkZ2V0OiBuIH0pO1xuICB9XG5cbiAgLyoqIFRoZSBjb2xvdXJpbmcgaW4gdXNlOiBcIkNlbGwgdHlwZVwiIHdpdGhvdXQgY2VsbCB0eXBlcyBjb2xvdXJzIGJ5IGdlbmUgKGFzIHRoZSBtYXJrZXJzIGRvKS4gKi9cbiAgcHJvdGVjdGVkIGdldCB0cmFuc2NyaXB0Q29sb3JTaG93bigpOiBTcGF0aWFsVmlld1N0YXRlWyd0cmFuc2NyaXB0Q29sb3JCeSddIHtcbiAgICByZXR1cm4gdGhpcy52aWV3LnRyYW5zY3JpcHRDb2xvckJ5ID09PSAnY2VsbFR5cGUnICYmICF0aGlzLmhhc0NlbGxUeXBlcyA/ICdnZW5lJyA6IHRoaXMudmlldy50cmFuc2NyaXB0Q29sb3JCeTtcbiAgfVxuXG4gIC8qKiBHZW5lcyBvZiBcIkFsbCBnZW5lc1wiIGhpZGRlbiBvbmUgYnkgb25lIChub3QgdGhlIHdob2xlIHNldCBzd2l0Y2hlZCBvZmYpLiAqL1xuICBwcm90ZWN0ZWQgZ2V0IGFsbEdlbmVzU29tZUhpZGRlbigpOiBib29sZWFuIHtcbiAgICBjb25zdCBvZmYgPSB0aGlzLnZpZXcudHJhbnNjcmlwdEFsbEdlbmVzSGlkZGVuO1xuICAgIHJldHVybiB0aGlzLnZpZXcudHJhbnNjcmlwdEFsbEdlbmVzICYmIG9mZi5sZW5ndGggPiAwICYmICFldmVyeUdlbmVPZmYob2ZmKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvblRyYW5zY3JpcHRDb2xvckJ5KGJ5OiBTcGF0aWFsVmlld1N0YXRlWyd0cmFuc2NyaXB0Q29sb3JCeSddKTogdm9pZCB7XG4gICAgdGhpcy5jb250cm9scz8uc2V0Vmlld1N0YXRlKHsgdHJhbnNjcmlwdENvbG9yQnk6IGJ5IH0pO1xuICB9XG5cbiAgLy8gUHJpbWVORydzIHNsaWRlciByZXBvcnRzIGBudW1iZXIgfCB1bmRlZmluZWRgOyBpZ25vcmUgdGhlIGVtcHR5IGNhc2UgcmF0aGVyIHRoYW5cbiAgLy8gd3JpdGluZyBgdW5kZWZpbmVkYCBpbnRvIHRoZSBzdG9yZS5cbiAgcHJvdGVjdGVkIG9uVHJhbnNjcmlwdFNjYWxlKHZhbHVlOiBudW1iZXIgfCB1bmRlZmluZWQpOiB2b2lkIHtcbiAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuICAgIHRoaXMuY29udHJvbHM/LnNldFZpZXdTdGF0ZSh7IHRyYW5zY3JpcHRTY2FsZTogdmFsdWUgfSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgb25UcmFuc2NyaXB0T3BhY2l0eSh2YWx1ZTogbnVtYmVyIHwgdW5kZWZpbmVkKTogdm9pZCB7XG4gICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHJldHVybjtcbiAgICB0aGlzLmNvbnRyb2xzPy5zZXRWaWV3U3RhdGUoeyB0cmFuc2NyaXB0T3BhY2l0eTogdmFsdWUgfSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgb25UcmFuc2NyaXB0UXVhbGl0eShpbmNsdWRlTG93OiBib29sZWFuKTogdm9pZCB7XG4gICAgdGhpcy5jb250cm9scz8uc2V0Vmlld1N0YXRlKHsgdHJhbnNjcmlwdFF1YWxpdHk6IGluY2x1ZGVMb3cgPyAnYWxsJyA6ICdoaWdoJyB9KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBnbHlwaE9mKGdlbmU6IHN0cmluZywgc2xvdDogbnVtYmVyKTogVHJhbnNjcmlwdEdseXBoTmFtZSB7XG4gICAgcmV0dXJuIHRoaXMudmlldy50cmFuc2NyaXB0R2x5cGhzW2dlbmVdID8/IGRlZmF1bHRHbHlwaEZvcihzbG90KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvbkdseXBoKGdlbmU6IHN0cmluZywgZ2x5cGg6IFRyYW5zY3JpcHRHbHlwaE5hbWUpOiB2b2lkIHtcbiAgICB0aGlzLmNvbnRyb2xzPy5zZXRWaWV3U3RhdGUoeyB0cmFuc2NyaXB0R2x5cGhzOiB7IC4uLnRoaXMudmlldy50cmFuc2NyaXB0R2x5cGhzLCBbZ2VuZV06IGdseXBoIH0gfSk7XG4gIH1cblxuICAvLyDilIDilIAgZGVuc2l0eSBtYXAg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgcHJvdGVjdGVkIGdldCBkZW5zaXR5T3BhY2l0eVBlcmNlbnQoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gTWF0aC5yb3VuZCh0aGlzLnZpZXcuZGVuc2l0eU9wYWNpdHkgKiAxMDApO1xuICB9XG5cbiAgcHJvdGVjdGVkIG9uRGVuc2l0eU9wYWNpdHkodmFsdWU6IG51bWJlciB8IHVuZGVmaW5lZCk6IHZvaWQge1xuICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSByZXR1cm47XG4gICAgdGhpcy5jb250cm9scz8uc2V0Vmlld1N0YXRlKHsgZGVuc2l0eU9wYWNpdHk6IHZhbHVlIH0pO1xuICB9XG5cbiAgcHJvdGVjdGVkIG9uRGVuc2l0eU9wYWNpdHlQZXJjZW50KHY6IG51bWJlciB8IG51bGwpOiB2b2lkIHtcbiAgICBpZiAodiA9PT0gbnVsbCB8fCAhTnVtYmVyLmlzRmluaXRlKHYpKSByZXR1cm47XG4gICAgdGhpcy5jb250cm9scz8uc2V0Vmlld1N0YXRlKHsgZGVuc2l0eU9wYWNpdHk6IE1hdGgubWluKDEsIE1hdGgubWF4KDAuMDUsIHYgLyAxMDApKSB9KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBnZXQgZGVuc2l0eUJpbkluZGV4KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIE1hdGgubWF4KDAsIHRoaXMuZGVuc2l0eUJpbnMuaW5kZXhPZih0aGlzLnZpZXcuZGVuc2l0eUJpbikpO1xuICB9XG5cbiAgcHJvdGVjdGVkIG9uRGVuc2l0eUJpbkluZGV4KGk6IG51bWJlciB8IHVuZGVmaW5lZCk6IHZvaWQge1xuICAgIGlmIChpID09PSB1bmRlZmluZWQpIHJldHVybjtcbiAgICB0aGlzLmNvbnRyb2xzPy5zZXRWaWV3U3RhdGUoeyBkZW5zaXR5QmluOiB0aGlzLmRlbnNpdHlCaW5zW2ldID8/IDEwIH0pO1xuICB9XG5cbiAgcHJvdGVjdGVkIG9uRGVuc2l0eVJhbmdlKHJhbmdlOiBbbnVtYmVyLCBudW1iZXJdIHwgbnVtYmVyW10gfCB1bmRlZmluZWQpOiB2b2lkIHtcbiAgICBpZiAoIXJhbmdlIHx8IHJhbmdlLmxlbmd0aCAhPT0gMikgcmV0dXJuO1xuICAgIHRoaXMuY29udHJvbHM/LnNldFZpZXdTdGF0ZSh7IGRlbnNpdHlSYW5nZTogW01hdGgubWluKHJhbmdlWzBdLCByYW5nZVsxXSksIE1hdGgubWF4KHJhbmdlWzBdLCByYW5nZVsxXSldIH0pO1xuICB9XG5cbiAgcHJvdGVjdGVkIG9uRGVuc2l0eVJhbmdlRW5kKHdoaWNoOiAwIHwgMSwgdjogbnVtYmVyIHwgbnVsbCk6IHZvaWQge1xuICAgIGlmICh2ID09PSBudWxsIHx8ICFOdW1iZXIuaXNGaW5pdGUodikpIHJldHVybjtcbiAgICBjb25zdCBuZXh0OiBbbnVtYmVyLCBudW1iZXJdID0gWy4uLnRoaXMuZGVuc2l0eVdpbmRvd107XG4gICAgbmV4dFt3aGljaF0gPSB2O1xuICAgIHRoaXMub25EZW5zaXR5UmFuZ2UobmV4dCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgb25EZW5zaXR5QXV0bygpOiB2b2lkIHtcbiAgICB0aGlzLmNvbnRyb2xzPy5zZXRWaWV3U3RhdGUoeyBkZW5zaXR5UmFuZ2U6IG51bGwgfSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgb25EZW5zaXR5Q29sb3JtYXAobm9kZTogQ29sb3JtYXBOb2RlIHwgbnVsbCk6IHZvaWQge1xuICAgIHRoaXMuc2VsZWN0ZWREZW5zaXR5Q29sb3JtYXBOb2RlID0gbm9kZTtcbiAgICB0aGlzLmNvbnRyb2xzPy5zZXRWaWV3U3RhdGUoeyBkZW5zaXR5Q29sb3JtYXA6IG5vZGU/LmRhdGE/LnZhbHVlID8/IG51bGwgfSk7XG4gIH1cblxuICBwcml2YXRlIHJlZnJlc2hEZW5zaXR5V2luZG93KCk6IHZvaWQge1xuICAgIGNvbnN0IG5leHQ6IFtudW1iZXIsIG51bWJlcl0gPVxuICAgICAgdGhpcy52aWV3LmRlbnNpdHlSYW5nZSA/PyAodGhpcy5kZW5zaXR5U3RhdHMgPyBbdGhpcy5kZW5zaXR5U3RhdHMubG8sIHRoaXMuZGVuc2l0eVN0YXRzLmhpXSA6IFswLCAxXSk7XG4gICAgaWYgKG5leHRbMF0gIT09IHRoaXMuZGVuc2l0eVdpbmRvd1swXSB8fCBuZXh0WzFdICE9PSB0aGlzLmRlbnNpdHlXaW5kb3dbMV0pIHRoaXMuZGVuc2l0eVdpbmRvdyA9IG5leHQ7XG4gICAgdGhpcy5kZW5zaXR5U2xpZGVyTWF4ID0gTWF0aC5tYXgodGhpcy5kZW5zaXR5U3RhdHM/Lm1heCA/PyAxLCB0aGlzLmRlbnNpdHlXaW5kb3dbMV0pO1xuICAgIHRoaXMuZGVuc2l0eVN0ZXAgPSB0aGlzLmRlbnNpdHlTbGlkZXJNYXggLyAyMDA7XG4gIH1cblxuICAvKiogJ+KLricgbWVudS4gKi9cbiAgcHJpdmF0ZSBidWlsZEdlbmVNZW51KCk6IEdlbmVNZW51SXRlbVtdIHtcbiAgICByZXR1cm4gW1xuICAgICAge1xuICAgICAgICBsYWJlbDogJ0FkZCBtYXJrZXIgZ2VuZXMgb2YgY2x1c3RlcnPigKYnLFxuICAgICAgICBpY29uOiAncGkgcGktc2l0ZW1hcCcsXG4gICAgICAgIGRpc2FibGVkOiAhdGhpcy5jYW5BZGRNYXJrZXJzLFxuICAgICAgICBjb21tYW5kOiAoKSA9PiB0aGlzLm9wZW5NYXJrZXJzKCksXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBsYWJlbDogJ05ldyBncm91cCBmcm9tIHNlbGVjdGVkIGdlbmVzJyxcbiAgICAgICAgaWNvbjogJ3BpIHBpLWZvbGRlci1wbHVzJyxcbiAgICAgICAgZGlzYWJsZWQ6ICF0aGlzLnZpZXcudHJhbnNjcmlwdEdlbmVzLmxlbmd0aCxcbiAgICAgICAgY29tbWFuZDogKCkgPT4gdGhpcy5vbk5ld0dlbmVHcm91cCgpLFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgbGFiZWw6ICdJbXBvcnQgZ2VuZSBncm91cHMgKENTVinigKYnLFxuICAgICAgICBpY29uOiAncGkgcGktdXBsb2FkJyxcbiAgICAgICAgY29tbWFuZDogKCkgPT4gdGhpcy5nZW5lR3JvdXBGaWxlUmVmPy5uYXRpdmVFbGVtZW50LmNsaWNrKCksXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBsYWJlbDogJ1JlbW92ZSBnZW5lIGdyb3VwcycsXG4gICAgICAgIGljb246ICdwaSBwaS10aW1lcycsXG4gICAgICAgIGRpc2FibGVkOiAhdGhpcy52aWV3LnRyYW5zY3JpcHRHZW5lR3JvdXBzLmxlbmd0aCxcbiAgICAgICAgY29tbWFuZDogKCkgPT4gdGhpcy5jb250cm9scz8uc2V0Vmlld1N0YXRlKHsgdHJhbnNjcmlwdEdlbmVHcm91cHM6IFtdIH0pLFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgbGFiZWw6ICdDbGVhciBzZWxlY3Rpb24nLFxuICAgICAgICBpY29uOiAncGkgcGktYmFuJyxcbiAgICAgICAgZGlzYWJsZWQ6ICF0aGlzLnZpZXcudHJhbnNjcmlwdEdlbmVzLmxlbmd0aCxcbiAgICAgICAgY29tbWFuZDogKCkgPT4gdGhpcy5jb250cm9scz8uc2V0Vmlld1N0YXRlKHsgdHJhbnNjcmlwdEdlbmVzOiBbXSwgdHJhbnNjcmlwdEhpZGRlbkdlbmVzOiBbXSB9KSxcbiAgICAgIH0sXG4gICAgXTtcbiAgfVxufVxuIiwiPGRpdiBjbGFzcz1cInNjLXBhbmVsXCIgW2NsYXNzLm9wZW5dPVwib3BlblwiPlxuICA8ZGl2IGNsYXNzPVwic2MtcGFuZWwtaGVhZFwiIChjbGljayk9XCJvcGVuQ2hhbmdlLmVtaXQoIW9wZW4pXCI+XG4gICAgPHAtY2hlY2tib3hcbiAgICAgIFtiaW5hcnldPVwidHJ1ZVwiXG4gICAgICBbbmdNb2RlbF09XCJ2aWV3LnRyYW5zY3JpcHRNb2RlICE9PSAnb2ZmJ1wiXG4gICAgICAoY2xpY2spPVwiJGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpXCJcbiAgICAgIChvbkNoYW5nZSk9XCJvblRyYW5zY3JpcHRzT24oJGV2ZW50LmNoZWNrZWQpXCJcbiAgICA+PC9wLWNoZWNrYm94PlxuICAgIDxzcGFuIGNsYXNzPVwic2MtcGFuZWwtdGl0bGVcIj5UcmFuc2NyaXB0czwvc3Bhbj5cbiAgICA8aSBjbGFzcz1cInBpXCIgW2NsYXNzLnBpLWNoZXZyb24tZG93bl09XCJvcGVuXCIgW2NsYXNzLnBpLWNoZXZyb24tcmlnaHRdPVwiIW9wZW5cIj48L2k+XG4gIDwvZGl2PlxuICA8ZGl2IGNsYXNzPVwic2MtcGFuZWwtYm9keVwiICpuZ0lmPVwib3BlblwiPlxuICAgIDxkaXYgY2xhc3M9XCJzYy1yb3cgc2Mtcm93LXBpY2tlclwiPlxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImdlbmVzPy5zdGF0ZSQgfCBhc3luYyBhcyBnZW5lXCI+XG4gICAgICAgIDxwLW11bHRpU2VsZWN0XG4gICAgICAgICAgaW5wdXRJZD1cInNjLXR4LWdlbmVzXCJcbiAgICAgICAgICBbb3B0aW9uc109XCJnZW5lLm9wdGlvbnNcIlxuICAgICAgICAgIG9wdGlvbkxhYmVsPVwibGFiZWxcIlxuICAgICAgICAgIG9wdGlvblZhbHVlPVwidmFsdWVcIlxuICAgICAgICAgIFtuZ01vZGVsXT1cInZpZXcudHJhbnNjcmlwdEdlbmVzXCJcbiAgICAgICAgICAob25DaGFuZ2UpPVwib25UcmFuc2NyaXB0R2VuZXMoJGV2ZW50LnZhbHVlKVwiXG4gICAgICAgICAgW2ZpbHRlcl09XCJ0cnVlXCJcbiAgICAgICAgICBmaWx0ZXJCeT1cImxhYmVsXCJcbiAgICAgICAgICBbcmVzZXRGaWx0ZXJPbkhpZGVdPVwidHJ1ZVwiXG4gICAgICAgICAgKG9uRmlsdGVyKT1cImdlbmVzPy5vbkZpbHRlcigkZXZlbnQuZmlsdGVyKVwiXG4gICAgICAgICAgKG9uUGFuZWxTaG93KT1cImdlbmVzPy5lbnN1cmVMaXN0KClcIlxuICAgICAgICAgIFt2aXJ0dWFsU2Nyb2xsXT1cImdlbmUub3B0aW9ucy5sZW5ndGggPiBnZW5lVmlydHVhbFNjcm9sbEZyb21cIlxuICAgICAgICAgIFt2aXJ0dWFsU2Nyb2xsSXRlbVNpemVdPVwiMzBcIlxuICAgICAgICAgIFtzaG93VG9nZ2xlQWxsXT1cImZhbHNlXCJcbiAgICAgICAgICBbZW1wdHlGaWx0ZXJNZXNzYWdlXT1cImdlbmUucmVtb3RlID8gJ05vIG1hdGNoIOKAlCBrZWVwIHR5cGluZycgOiAnTm8gbWF0Y2gnXCJcbiAgICAgICAgICBbZW1wdHlNZXNzYWdlXT1cImdlbmUucmVtb3RlID8gJ1R5cGUgdG8gc2VhcmNoIGdlbmVzJyA6ICdObyBnZW5lcydcIlxuICAgICAgICAgIGFwcGVuZFRvPVwiYm9keVwiXG4gICAgICAgICAgcGxhY2Vob2xkZXI9XCJTZWFyY2ggZm9yIGdlbmVzIHRvIHZpc3VhbGl6ZeKAplwiXG4gICAgICAgICAgW3NlbGVjdGVkSXRlbXNMYWJlbF09XCInezB9IGdlbmVzIHNlbGVjdGVkJ1wiXG4gICAgICAgICAgW21heFNlbGVjdGVkTGFiZWxzXT1cIjBcIlxuICAgICAgICAgIHN0eWxlQ2xhc3M9XCJzYy1mdWxsXCJcbiAgICAgICAgPjwvcC1tdWx0aVNlbGVjdD5cbiAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgPGJ1dHRvblxuICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgY2xhc3M9XCJzYy1pY29uLWJ0blwiXG4gICAgICAgICpuZ0lmPVwiY2FuU2hvd0FsbEdlbmVzXCJcbiAgICAgICAgKGNsaWNrKT1cIm9uVG9nZ2xlQWxsR2VuZXMoKVwiXG4gICAgICAgIFtjbGFzcy5hY3RpdmVdPVwidmlldy50cmFuc2NyaXB0QWxsR2VuZXNcIlxuICAgICAgICBbdGl0bGVdPVwidmlldy50cmFuc2NyaXB0QWxsR2VuZXMgPyAnQmFjayB0byB0aGUgc2VsZWN0ZWQgZ2VuZXMnIDogJ1NlbGVjdCBhbGwgZ2VuZXMnXCJcbiAgICAgID5cbiAgICAgICAgwrFcbiAgICAgIDwvYnV0dG9uPlxuICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJzYy1pY29uLWJ0blwiIChjbGljayk9XCJnZW5lTWVudVJlZi50b2dnbGUoJGV2ZW50KVwiIHRpdGxlPVwiTW9yZVwiPlxuICAgICAgICA8aSBjbGFzcz1cInBpIHBpLWVsbGlwc2lzLXZcIj48L2k+XG4gICAgICA8L2J1dHRvbj5cbiAgICAgIDxwLW1lbnUgI2dlbmVNZW51UmVmIFttb2RlbF09XCJnZW5lTWVudVwiIFtwb3B1cF09XCJ0cnVlXCIgYXBwZW5kVG89XCJib2R5XCI+PC9wLW1lbnU+XG4gICAgICA8aW5wdXRcbiAgICAgICAgI2dlbmVHcm91cEZpbGVcbiAgICAgICAgdHlwZT1cImZpbGVcIlxuICAgICAgICBhY2NlcHQ9XCIuY3N2LC50c3YsLnR4dFwiXG4gICAgICAgIGhpZGRlblxuICAgICAgICAoY2hhbmdlKT1cIm9uSW1wb3J0R2VuZUdyb3VwcyhnZW5lR3JvdXBGaWxlKVwiXG4gICAgICAvPlxuICAgIDwvZGl2PlxuICAgIDxzbWFsbCBjbGFzcz1cInNjLWhpbnQgc2MtZXJyb3JcIiAqbmdJZj1cImdlbmVHcm91cEVycm9yXCI+e3sgZ2VuZUdyb3VwRXJyb3IgfX08L3NtYWxsPlxuICAgIDxzbWFsbCBjbGFzcz1cInNjLWhpbnRcIiAqbmdJZj1cImFsbEdlbmVzUHJlcGFyaW5nXCI+e3sgYWxsR2VuZXNQcmVwYXJpbmcgfX08L3NtYWxsPlxuXG4gICAgPHNwYXRpYWwtbWFya2VyLWdlbmVzLWZvcm1cbiAgICAgIFtjb250cm9sc109XCJjb250cm9sc1wiXG4gICAgICBbZGF0YXNldF09XCJkYXRhc2V0XCJcbiAgICAgIFt2aWV3XT1cInZpZXdcIlxuICAgICAgW29wZW5dPVwibWFya2Vyc09wZW5cIlxuICAgICAgKG9wZW5DaGFuZ2UpPVwibWFya2Vyc09wZW4gPSAkZXZlbnRcIlxuICAgID48L3NwYXRpYWwtbWFya2VyLWdlbmVzLWZvcm0+XG5cbiAgICA8c3BhdGlhbC1nZW5lLXRyZWVcbiAgICAgIFtjb250cm9sc109XCJjb250cm9sc1wiXG4gICAgICBbZGF0YXNldF09XCJkYXRhc2V0XCJcbiAgICAgIFt2aWV3XT1cInZpZXdcIlxuICAgICAgW2dlbmVDb3VudHNdPVwiZ2VuZUNvdW50c1wiXG4gICAgICBbZ2VuZVRvdGFsXT1cImdlbmVUb3RhbFwiXG4gICAgPjwvc3BhdGlhbC1nZW5lLXRyZWU+XG5cbiAgICA8ZGl2IGNsYXNzPVwic2Mtc3ViaGVhZFwiPlRyYW5zY3JpcHQgY29udHJvbHM8L2Rpdj5cbiAgICA8c3BhbiBjbGFzcz1cInNjLWxibFwiPlZpZXcgdHJhbnNjcmlwdHMgYXM8L3NwYW4+XG4gICAgPHAtc2VsZWN0QnV0dG9uXG4gICAgICBbb3B0aW9uc109XCJ0cmFuc2NyaXB0TW9kZU9wdGlvbnNcIlxuICAgICAgb3B0aW9uTGFiZWw9XCJsYWJlbFwiXG4gICAgICBvcHRpb25WYWx1ZT1cInZhbHVlXCJcbiAgICAgIFtuZ01vZGVsXT1cInZpZXcudHJhbnNjcmlwdE1vZGUgPT09ICdvZmYnID8gbnVsbCA6IHZpZXcudHJhbnNjcmlwdE1vZGVcIlxuICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwib25UcmFuc2NyaXB0TW9kZSgkZXZlbnQpXCJcbiAgICAgIFthbGxvd0VtcHR5XT1cImZhbHNlXCJcbiAgICAgIHN0eWxlQ2xhc3M9XCJzYy1idXR0b25zXCJcbiAgICA+PC9wLXNlbGVjdEJ1dHRvbj5cblxuICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJlc3RpbWF0ZVwiPlxuICAgICAgPGRpdiBjbGFzcz1cInNjLXJvd1wiPlxuICAgICAgICA8c3BhblxuICAgICAgICAgIGNsYXNzPVwic2MtbGJsXCJcbiAgICAgICAgICBwVG9vbHRpcD1cIlRyYW5zY3JpcHRzIG9mIHRoZSB2aXNpYmxlIGdlbmVzIGVzdGltYXRlZCB0byBiZSBpbiB2aWV3LCBhZ2FpbnN0IHRoZSBtb3N0IG1hcmtlcnMgZHJhd24gYXQgb25jZVwiXG4gICAgICAgICAgdG9vbHRpcFBvc2l0aW9uPVwidG9wXCJcbiAgICAgICAgICA+RXN0aW1hdGVkIFRyYW5zY3JpcHQgUG9pbnRzPC9zcGFuXG4gICAgICAgID5cbiAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJzYy1zbWFsbC1idG5cIiAoY2xpY2spPVwiZWRpdGluZ01heCA9ICFlZGl0aW5nTWF4XCI+RWRpdCBNYXg8L2J1dHRvbj5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cInNjLW1ldGVyXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJzYy1tZXRlci1maWxsXCIgW2NsYXNzLm92ZXJdPVwiZXN0aW1hdGVPdmVyTWF4XCIgW3N0eWxlLndpZHRoLiVdPVwiZXN0aW1hdGVQZXJjZW50XCI+PC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJzYy1tZXRlci1lbmRzXCI+XG4gICAgICAgIDxzcGFuPnt7IGVzdGltYXRlLnBvaW50cyB8IG51bWJlciB9fSBwb2ludHM8L3NwYW4+XG4gICAgICAgIDxzcGFuPnt7IGVzdGltYXRlLm1heCB8IG51bWJlciB9fSBtYXh7eyBlc3RpbWF0ZU92ZXJNYXggPyAnIHJlYWNoZWQnIDogJycgfX08L3NwYW4+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJzYy1yb3dcIiAqbmdJZj1cImVkaXRpbmdNYXhcIj5cbiAgICAgICAgPHNwYW4gY2xhc3M9XCJzYy1sYmxcIj5NYXggbWFya2Vyczwvc3Bhbj5cbiAgICAgICAgPHAtZHJvcGRvd25cbiAgICAgICAgICBbb3B0aW9uc109XCJidWRnZXRPcHRpb25zXCJcbiAgICAgICAgICBvcHRpb25MYWJlbD1cImxhYmVsXCJcbiAgICAgICAgICBvcHRpb25WYWx1ZT1cInZhbHVlXCJcbiAgICAgICAgICBbbmdNb2RlbF09XCJ2aWV3LnRyYW5zY3JpcHRCdWRnZXRcIlxuICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cIm9uVHJhbnNjcmlwdEJ1ZGdldCgkZXZlbnQpXCJcbiAgICAgICAgICBhcHBlbmRUbz1cImJvZHlcIlxuICAgICAgICA+PC9wLWRyb3Bkb3duPlxuICAgICAgPC9kaXY+XG4gICAgICA8c21hbGwgY2xhc3M9XCJzYy1oaW50XCIgKm5nSWY9XCJlc3RpbWF0ZU92ZXJNYXggJiYgdmlldy50cmFuc2NyaXB0TW9kZSAhPT0gJ2RlbnNpdHknXCI+XG4gICAgICAgIE1heCBwb2ludHMgcmVhY2hlZDogdHJhbnNjcmlwdHMgYXJlIGdyb3VwZWQgYnkgYXJlYSwgY2lyY2xlcyBzaXplZCBieSBob3cgbWFueSB0aGV5IGhvbGQuIFpvb20gaW4gb3Igc2VsZWN0XG4gICAgICAgIGZld2VyIGdlbmVzIHRvIHNlZSBpbmRpdmlkdWFsIHBvaW50cy5cbiAgICAgIDwvc21hbGw+XG4gICAgPC9uZy1jb250YWluZXI+XG5cbiAgICA8IS0tIFRoZSBkZW5zaXR5IHJhc3RlciBhbmQgdGhlIGdyb3VwZWQgbWFya2VycyBkcmF3biBmcm9tIGl0IGNhcnJ5IG5vIGNlbGxzLCBzbyB0aGV5XG4gICAgICAgICBjYW5ub3QgZm9sbG93IHRoZSBPYnNlcnZhdGlvbnMgZ2VuZSBmaWx0ZXI6IHRoZXkgYXJlIG5vdCBkcmF3biB3aGlsZSBpdCBpcyBvbi4gLS0+XG4gICAgPHNtYWxsIGNsYXNzPVwic2MtaGludFwiICpuZ0lmPVwib2JzZXJ2YXRpb25zRmlsdGVyZWQgJiYgdmlldy50cmFuc2NyaXB0TW9kZSA9PT0gJ2RlbnNpdHknXCI+XG4gICAgICBPYnNlcnZhdGlvbnMgYXJlIGZpbHRlcmVkIGJ5IGdlbmUsIGFuZCB0aGUgZGVuc2l0eSBtYXAgc3VtcyBldmVyeSBjZWxsJ3MgdHJhbnNjcmlwdHMsIHNvIGl0IGlzIGhpZGRlbi4gVXNlXG4gICAgICBDaXJjbGVzIG9yIEljb25zIHRvIHNlZSB0aGUgdHJhbnNjcmlwdHMgb2YgdGhlIG9ic2VydmF0aW9ucyBzaG93bi5cbiAgICA8L3NtYWxsPlxuICAgIDxzbWFsbFxuICAgICAgY2xhc3M9XCJzYy1oaW50XCJcbiAgICAgICpuZ0lmPVwib2JzZXJ2YXRpb25zRmlsdGVyZWQgJiYgKHZpZXcudHJhbnNjcmlwdE1vZGUgPT09ICdjaXJjbGVzJyB8fCB2aWV3LnRyYW5zY3JpcHRNb2RlID09PSAnZ2x5cGhzJylcIlxuICAgID5cbiAgICAgIE9ic2VydmF0aW9ucyBhcmUgZmlsdGVyZWQgYnkgZ2VuZTogb25seSB0aGUgdHJhbnNjcmlwdHMgb2YgdGhlIG9ic2VydmF0aW9ucyBzaG93biBhcmUgZHJhd24uIFRyYW5zY3JpcHRzXG4gICAgICBncm91cGVkIGJ5IGFyZWEgd2hlbiB6b29tZWQgb3V0IGNhcnJ5IG5vIGNlbGxzLCBzbyB0aGV5IGFyZSBoaWRkZW47IHpvb20gaW4gdG8gc2VlIHRoZW0uXG4gICAgPC9zbWFsbD5cblxuICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJ2aWV3LnRyYW5zY3JpcHRNb2RlID09PSAnY2lyY2xlcycgfHwgdmlldy50cmFuc2NyaXB0TW9kZSA9PT0gJ2dseXBocydcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJzYy1yb3dcIj5cbiAgICAgICAgPHNwYW4gY2xhc3M9XCJzYy1sYmxcIj5Db2xvdXIgYnk8L3NwYW4+XG4gICAgICAgIDxwLXNlbGVjdEJ1dHRvblxuICAgICAgICAgIFtvcHRpb25zXT1cInRyYW5zY3JpcHRDb2xvck9wdGlvbnNcIlxuICAgICAgICAgIG9wdGlvbkxhYmVsPVwibGFiZWxcIlxuICAgICAgICAgIG9wdGlvblZhbHVlPVwidmFsdWVcIlxuICAgICAgICAgIFtuZ01vZGVsXT1cInRyYW5zY3JpcHRDb2xvclNob3duXCJcbiAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJvblRyYW5zY3JpcHRDb2xvckJ5KCRldmVudClcIlxuICAgICAgICAgIFthbGxvd0VtcHR5XT1cImZhbHNlXCJcbiAgICAgICAgICBzdHlsZUNsYXNzPVwic2MtYnV0dG9uc1wiXG4gICAgICAgID48L3Atc2VsZWN0QnV0dG9uPlxuICAgICAgPC9kaXY+XG4gICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwidmlldy50cmFuc2NyaXB0QWxsR2VuZXMgJiYgZXN0aW1hdGVPdmVyTWF4XCI+XG4gICAgICAgIDxzbWFsbCBjbGFzcz1cInNjLWhpbnRcIiAqbmdJZj1cImhhc0NlbGxUeXBlcyAmJiB0cmFuc2NyaXB0Q29sb3JTaG93biAhPT0gJ2NlbGxUeXBlJ1wiPlxuICAgICAgICAgIEdyb3VwZWQgbWFya2VycyBtaXggZ2VuZXMsIHNvIHRoZXkgYXJlIGNvbG91cmVkIGJ5IGNlbGwgdHlwZSB1bnRpbCB5b3Ugem9vbSBpbiB0byBpbmRpdmlkdWFsIHRyYW5zY3JpcHRzLlxuICAgICAgICA8L3NtYWxsPlxuICAgICAgICA8c21hbGwgY2xhc3M9XCJzYy1oaW50XCIgKm5nSWY9XCIhaGFzQ2VsbFR5cGVzXCI+XG4gICAgICAgICAgR3JvdXBlZCBtYXJrZXJzIG1peCBnZW5lcyBhbmQgdGhpcyBkYXRhc2V0IGhhcyBubyBjZWxsIHR5cGVzLCBzbyB0aGV5IGFyZSBkcmF3biBpbiBvbmUgY29sb3VyIHVudGlsIHlvdVxuICAgICAgICAgIHpvb20gaW4gdG8gaW5kaXZpZHVhbCB0cmFuc2NyaXB0cy5cbiAgICAgICAgPC9zbWFsbD5cbiAgICAgICAgPHNtYWxsIGNsYXNzPVwic2MtaGludFwiICpuZ0lmPVwiYWxsR2VuZXNTb21lSGlkZGVuXCI+XG4gICAgICAgICAgR3JvdXBlZCBtYXJrZXJzIGhvbGQgZXZlcnkgZ2VuZTogaGlkZGVuIGdlbmVzIGFyZSBsZWZ0IG91dCBvbmNlIHlvdSB6b29tIGluIHRvIGluZGl2aWR1YWwgdHJhbnNjcmlwdHMuXG4gICAgICAgIDwvc21hbGw+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgIDxkaXYgY2xhc3M9XCJzYy1yb3dcIiAqbmdJZj1cInZpZXcudHJhbnNjcmlwdEFsbEdlbmVzICYmIHZpZXcudHJhbnNjcmlwdE1vZGUgPT09ICdnbHlwaHMnXCI+XG4gICAgICAgIDxzcGFuIGNsYXNzPVwic2MtbGJsXCI+SWNvbjwvc3Bhbj5cbiAgICAgICAgPHAtZHJvcGRvd25cbiAgICAgICAgICBbb3B0aW9uc109XCJnbHlwaE9wdGlvbnNcIlxuICAgICAgICAgIG9wdGlvbkxhYmVsPVwibGFiZWxcIlxuICAgICAgICAgIG9wdGlvblZhbHVlPVwidmFsdWVcIlxuICAgICAgICAgIFtuZ01vZGVsXT1cImdseXBoT2YoJyonLCAwKVwiXG4gICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwib25HbHlwaCgnKicsICRldmVudClcIlxuICAgICAgICAgIGFwcGVuZFRvPVwiYm9keVwiXG4gICAgICAgICAgc3R5bGVDbGFzcz1cInNjLWdseXBoLXBpY2tcIlxuICAgICAgICA+XG4gICAgICAgICAgPG5nLXRlbXBsYXRlIGxldC1vcHQgcFRlbXBsYXRlPVwiaXRlbVwiPlxuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJzYy1nbHlwaC1vcHRpb25cIj5cbiAgICAgICAgICAgICAgPHN2ZyB2aWV3Qm94PVwiLTEuMiAtMS4yIDIuNCAyLjRcIiBjbGFzcz1cInNjLWdseXBoLXN2Z1wiPlxuICAgICAgICAgICAgICAgIDxwb2x5Z29uIFthdHRyLnBvaW50c109XCJvcHQucG9pbnRzXCI+PC9wb2x5Z29uPlxuICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgICAge3sgb3B0LmxhYmVsIH19XG4gICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICA8bmctdGVtcGxhdGUgbGV0LW9wdCBwVGVtcGxhdGU9XCJzZWxlY3RlZEl0ZW1cIj5cbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwic2MtZ2x5cGgtb3B0aW9uXCI+XG4gICAgICAgICAgICAgIDxzdmcgdmlld0JveD1cIi0xLjIgLTEuMiAyLjQgMi40XCIgY2xhc3M9XCJzYy1nbHlwaC1zdmdcIj5cbiAgICAgICAgICAgICAgICA8cG9seWdvbiBbYXR0ci5wb2ludHNdPVwib3B0Py5wb2ludHNcIj48L3BvbHlnb24+XG4gICAgICAgICAgICAgIDwvc3ZnPlxuICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgIDwvcC1kcm9wZG93bj5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cInNjLXJvd1wiPlxuICAgICAgICA8c3BhbiBjbGFzcz1cInNjLWxibFwiPlNpemU8L3NwYW4+XG4gICAgICAgIDxwLXNsaWRlclxuICAgICAgICAgIFtuZ01vZGVsXT1cInZpZXcudHJhbnNjcmlwdFNjYWxlXCJcbiAgICAgICAgICBbbWluXT1cIjAuNVwiXG4gICAgICAgICAgW21heF09XCIzXCJcbiAgICAgICAgICBbc3RlcF09XCIwLjI1XCJcbiAgICAgICAgICAob25DaGFuZ2UpPVwib25UcmFuc2NyaXB0U2NhbGUoJGV2ZW50LnZhbHVlKVwiXG4gICAgICAgID48L3Atc2xpZGVyPlxuICAgICAgICA8c3BhbiBjbGFzcz1cInNjLXZhbFwiPnt7IHZpZXcudHJhbnNjcmlwdFNjYWxlIH19w5c8L3NwYW4+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJzYy1yb3dcIj5cbiAgICAgICAgPHNwYW4gY2xhc3M9XCJzYy1sYmxcIj5PcGFjaXR5PC9zcGFuPlxuICAgICAgICA8cC1zbGlkZXJcbiAgICAgICAgICBbbmdNb2RlbF09XCJ2aWV3LnRyYW5zY3JpcHRPcGFjaXR5XCJcbiAgICAgICAgICBbbWluXT1cIjAuMVwiXG4gICAgICAgICAgW21heF09XCIxXCJcbiAgICAgICAgICBbc3RlcF09XCIwLjA1XCJcbiAgICAgICAgICAob25DaGFuZ2UpPVwib25UcmFuc2NyaXB0T3BhY2l0eSgkZXZlbnQudmFsdWUpXCJcbiAgICAgICAgPjwvcC1zbGlkZXI+XG4gICAgICAgIDxzcGFuIGNsYXNzPVwic2MtdmFsXCI+e3sgdmlldy50cmFuc2NyaXB0T3BhY2l0eSB9fTwvc3Bhbj5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cInNjLXJvd1wiICpuZ0lmPVwiIXNob3dpbmdBbGxHZW5lc1wiPlxuICAgICAgICA8cC1jaGVja2JveFxuICAgICAgICAgIFtiaW5hcnldPVwidHJ1ZVwiXG4gICAgICAgICAgW25nTW9kZWxdPVwidmlldy50cmFuc2NyaXB0UXVhbGl0eSA9PT0gJ2FsbCdcIlxuICAgICAgICAgIGlucHV0SWQ9XCJzYy10eC1sb3dxXCJcbiAgICAgICAgICAob25DaGFuZ2UpPVwib25UcmFuc2NyaXB0UXVhbGl0eSgkZXZlbnQuY2hlY2tlZClcIlxuICAgICAgICA+PC9wLWNoZWNrYm94PlxuICAgICAgICA8bGFiZWwgY2xhc3M9XCJzYy1sYmxcIiBmb3I9XCJzYy10eC1sb3dxXCI+SW5jbHVkZSBsb3ctcXVhbGl0eSBjYWxsczwvbGFiZWw+XG4gICAgICA8L2Rpdj5cbiAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJ2aWV3LnRyYW5zY3JpcHRNb2RlID09PSAnZGVuc2l0eSdcIj5cbiAgICAgIDxzcGFuIGNsYXNzPVwic2MtbGJsXCI+RGVuc2l0eSBtYXAgb3BhY2l0eTwvc3Bhbj5cbiAgICAgIDxkaXYgY2xhc3M9XCJzYy1yb3cgc2Mtcm93LW51bWJlclwiPlxuICAgICAgICA8cC1zbGlkZXJcbiAgICAgICAgICBbbmdNb2RlbF09XCJ2aWV3LmRlbnNpdHlPcGFjaXR5XCJcbiAgICAgICAgICBbbWluXT1cIjAuMDVcIlxuICAgICAgICAgIFttYXhdPVwiMVwiXG4gICAgICAgICAgW3N0ZXBdPVwiMC4wNVwiXG4gICAgICAgICAgKG9uQ2hhbmdlKT1cIm9uRGVuc2l0eU9wYWNpdHkoJGV2ZW50LnZhbHVlKVwiXG4gICAgICAgID48L3Atc2xpZGVyPlxuICAgICAgICA8cC1pbnB1dE51bWJlclxuICAgICAgICAgIFtuZ01vZGVsXT1cImRlbnNpdHlPcGFjaXR5UGVyY2VudFwiXG4gICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwib25EZW5zaXR5T3BhY2l0eVBlcmNlbnQoJGV2ZW50KVwiXG4gICAgICAgICAgW21pbl09XCI1XCJcbiAgICAgICAgICBbbWF4XT1cIjEwMFwiXG4gICAgICAgICAgaW5wdXRTdHlsZUNsYXNzPVwic2MtbnVtXCJcbiAgICAgICAgPjwvcC1pbnB1dE51bWJlcj5cbiAgICAgIDwvZGl2PlxuICAgICAgPHNwYW4gY2xhc3M9XCJzYy1sYmxcIiBwVG9vbHRpcD1cIkVkZ2Ugb2YgZWFjaCBkZW5zaXR5IGJpblwiIHRvb2x0aXBQb3NpdGlvbj1cInRvcFwiPkRlbnNpdHkgbWFwIGJpbiBzaXplPC9zcGFuPlxuICAgICAgPHAtc2xpZGVyXG4gICAgICAgIFtuZ01vZGVsXT1cImRlbnNpdHlCaW5JbmRleFwiXG4gICAgICAgIFttaW5dPVwiMFwiXG4gICAgICAgIFttYXhdPVwiM1wiXG4gICAgICAgIFtzdGVwXT1cIjFcIlxuICAgICAgICAob25DaGFuZ2UpPVwib25EZW5zaXR5QmluSW5kZXgoJGV2ZW50LnZhbHVlKVwiXG4gICAgICAgIHN0eWxlQ2xhc3M9XCJzYy1iaW4tc2xpZGVyXCJcbiAgICAgID48L3Atc2xpZGVyPlxuICAgICAgPGRpdiBjbGFzcz1cInNjLXRpY2tzXCI+XG4gICAgICAgIDxzcGFuICpuZ0Zvcj1cImxldCBiIG9mIGRlbnNpdHlCaW5zXCI+e3sgYiB9fcOXe3sgYiB9fcK1bTwvc3Bhbj5cbiAgICAgIDwvZGl2PlxuICAgICAgPHNwYW5cbiAgICAgICAgY2xhc3M9XCJzYy1sYmxcIlxuICAgICAgICBwVG9vbHRpcD1cIlRyYW5zY3JpcHRzIHBlciDCtW3CsiBhdCB3aGljaCB0aGUgY29sb3VyIHNjYWxlIHN0YXJ0cyBhbmQgc2F0dXJhdGVzXCJcbiAgICAgICAgdG9vbHRpcFBvc2l0aW9uPVwidG9wXCJcbiAgICAgICAgPkRlbnNpdHkgbWFwIHNjYWxlIHRocmVzaG9sZDwvc3BhblxuICAgICAgPlxuICAgICAgPGRpdiBjbGFzcz1cInNjLXJvdyBzYy1yb3ctcmFuZ2VcIj5cbiAgICAgICAgPHAtaW5wdXROdW1iZXJcbiAgICAgICAgICBbbmdNb2RlbF09XCJkZW5zaXR5V2luZG93WzBdXCJcbiAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJvbkRlbnNpdHlSYW5nZUVuZCgwLCAkZXZlbnQpXCJcbiAgICAgICAgICBtb2RlPVwiZGVjaW1hbFwiXG4gICAgICAgICAgW21pbkZyYWN0aW9uRGlnaXRzXT1cIjNcIlxuICAgICAgICAgIFttYXhGcmFjdGlvbkRpZ2l0c109XCIzXCJcbiAgICAgICAgICBpbnB1dFN0eWxlQ2xhc3M9XCJzYy1udW1cIlxuICAgICAgICA+PC9wLWlucHV0TnVtYmVyPlxuICAgICAgICA8cC1zbGlkZXJcbiAgICAgICAgICBbbmdNb2RlbF09XCJkZW5zaXR5V2luZG93XCJcbiAgICAgICAgICBbcmFuZ2VdPVwidHJ1ZVwiXG4gICAgICAgICAgW21pbl09XCIwXCJcbiAgICAgICAgICBbbWF4XT1cImRlbnNpdHlTbGlkZXJNYXhcIlxuICAgICAgICAgIFtzdGVwXT1cImRlbnNpdHlTdGVwXCJcbiAgICAgICAgICAob25DaGFuZ2UpPVwib25EZW5zaXR5UmFuZ2UoJGV2ZW50LnZhbHVlcylcIlxuICAgICAgICA+PC9wLXNsaWRlcj5cbiAgICAgICAgPHAtaW5wdXROdW1iZXJcbiAgICAgICAgICBbbmdNb2RlbF09XCJkZW5zaXR5V2luZG93WzFdXCJcbiAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJvbkRlbnNpdHlSYW5nZUVuZCgxLCAkZXZlbnQpXCJcbiAgICAgICAgICBtb2RlPVwiZGVjaW1hbFwiXG4gICAgICAgICAgW21pbkZyYWN0aW9uRGlnaXRzXT1cIjNcIlxuICAgICAgICAgIFttYXhGcmFjdGlvbkRpZ2l0c109XCIzXCJcbiAgICAgICAgICBpbnB1dFN0eWxlQ2xhc3M9XCJzYy1udW1cIlxuICAgICAgICA+PC9wLWlucHV0TnVtYmVyPlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwic2Mtcm93XCI+XG4gICAgICAgIDxzbWFsbCBjbGFzcz1cInNjLWhpbnRcIj57eyB2aWV3LmRlbnNpdHlSYW5nZSA/ICdTZXQgYnkgaGFuZC4nIDogJ0Rlcml2ZWQgZnJvbSB0aGUgZGF0YS4nIH19PC9zbWFsbD5cbiAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJzYy1zbWFsbC1idG5cIiAqbmdJZj1cInZpZXcuZGVuc2l0eVJhbmdlXCIgKGNsaWNrKT1cIm9uRGVuc2l0eUF1dG8oKVwiPlxuICAgICAgICAgIEF1dG9cbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxzcGFuIGNsYXNzPVwic2MtbGJsXCI+RGVuc2l0eSBtYXAgYmluIGNvbG9yaW5nPC9zcGFuPlxuICAgICAgPGRpdiBjbGFzcz1cInNjLXJvdyBzYy1yb3ctcGlja2VyXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJzYy1jb2xvcmJhciBzYy1mdWxsXCIgW3N0eWxlLmJhY2tncm91bmRdPVwiZGVuc2l0eUNvbG9yQmFyQ3NzXCI+PC9kaXY+XG4gICAgICAgIDxwLXRyZWVTZWxlY3RcbiAgICAgICAgICBbb3B0aW9uc109XCJjb2xvcm1hcE9wdGlvbnNcIlxuICAgICAgICAgIFtuZ01vZGVsXT1cInNlbGVjdGVkRGVuc2l0eUNvbG9ybWFwTm9kZVwiXG4gICAgICAgICAgc2VsZWN0aW9uTW9kZT1cInNpbmdsZVwiXG4gICAgICAgICAgW3Nob3dDbGVhcl09XCJ0cnVlXCJcbiAgICAgICAgICBwbGFjZWhvbGRlcj1cIkluZmVybm9cIlxuICAgICAgICAgIFtzY3JvbGxIZWlnaHRdPVwiJzI2MHB4J1wiXG4gICAgICAgICAgYXBwZW5kVG89XCJib2R5XCJcbiAgICAgICAgICBzdHlsZUNsYXNzPVwic2MtcGFsZXR0ZVwiXG4gICAgICAgICAgKG9uTm9kZVNlbGVjdCk9XCJvbkRlbnNpdHlDb2xvcm1hcCgkZXZlbnQubm9kZSlcIlxuICAgICAgICAgIChvbkNsZWFyKT1cIm9uRGVuc2l0eUNvbG9ybWFwKG51bGwpXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxuZy10ZW1wbGF0ZSBsZXQtbm9kZSBwVGVtcGxhdGU9XCJkZWZhdWx0XCI+XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cInNjLWNtYXAtb3B0aW9uXCI+XG4gICAgICAgICAgICAgIDxpbWcgKm5nSWY9XCIhbm9kZS5jaGlsZHJlbiAmJiBub2RlLmRhdGE/LnNyY1wiIFtzcmNdPVwibm9kZS5kYXRhLnNyY1wiIGNsYXNzPVwic2MtY21hcC1zd2F0Y2hcIiBhbHQ9XCJcIiAvPlxuICAgICAgICAgICAgICA8c3Bhbj57eyBub2RlLmxhYmVsIH19PC9zcGFuPlxuICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgIDwvcC10cmVlU2VsZWN0PlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwic2MtY29sb3JiYXItZW5kc1wiPlxuICAgICAgICA8c3Bhbj57eyBkZW5zaXR5V2luZG93WzBdIHwgbnVtYmVyOiAnMS4wLTMnIH19PC9zcGFuXG4gICAgICAgID48c3Bhbj57eyBkZW5zaXR5V2luZG93WzFdIHwgbnVtYmVyOiAnMS4wLTMnIH19PC9zcGFuPlxuICAgICAgPC9kaXY+XG4gICAgPC9uZy1jb250YWluZXI+XG4gIDwvZGl2PlxuPC9kaXY+XG4iXX0=
|