@datagrok-libraries/bio 5.1.1 → 5.2.1
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/index.d.ts +5 -5
- package/index.d.ts.map +1 -1
- package/index.js +6 -6
- package/index.ts +9 -5
- package/package.json +3 -2
- package/src/viewers/{web-logo.d.ts → web-logo-viewer.d.ts} +5 -6
- package/src/viewers/web-logo-viewer.d.ts.map +1 -0
- package/src/viewers/web-logo-viewer.js +677 -0
- package/src/viewers/web-logo.d.ts.map +0 -1
- package/src/viewers/web-logo.js +0 -677
|
@@ -0,0 +1,677 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import * as grok from 'datagrok-api/grok';
|
|
11
|
+
import * as ui from 'datagrok-api/ui';
|
|
12
|
+
import * as DG from 'datagrok-api/dg';
|
|
13
|
+
import wu from 'wu';
|
|
14
|
+
import * as rxjs from 'rxjs';
|
|
15
|
+
import { UnitsHandler } from '../utils/units-handler';
|
|
16
|
+
import { getSplitter, monomerToShort, pickUpPalette, pickUpSeqCol } from '../utils/macromolecule';
|
|
17
|
+
export var PositionHeight;
|
|
18
|
+
(function (PositionHeight) {
|
|
19
|
+
PositionHeight["Entropy"] = "Entropy";
|
|
20
|
+
PositionHeight["full"] = "100%";
|
|
21
|
+
})(PositionHeight || (PositionHeight = {}));
|
|
22
|
+
/**@param {MouseEvent} event
|
|
23
|
+
* @param {number} r devicePixelRation
|
|
24
|
+
* @return {DG.Point} canvas related cursor position
|
|
25
|
+
*/
|
|
26
|
+
HTMLCanvasElement.prototype.getCursorPosition = function (event, r) {
|
|
27
|
+
const rect = this.getBoundingClientRect();
|
|
28
|
+
return new DG.Point((event.clientX - rect.left) * r, (event.clientY - rect.top) * r);
|
|
29
|
+
};
|
|
30
|
+
DG.Rect.prototype.contains = function (x, y) {
|
|
31
|
+
return this.left <= x && x <= this.right && this.top <= y && y <= this.bottom;
|
|
32
|
+
};
|
|
33
|
+
export class PositionMonomerInfo {
|
|
34
|
+
constructor(count = 0, bounds = new DG.Rect(0, 0, 0, 0)) {
|
|
35
|
+
this.count = count;
|
|
36
|
+
this.bounds = bounds;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export class PositionInfo {
|
|
40
|
+
/** freq = {}, rowCount = 0
|
|
41
|
+
* @param {string} name Name of position ('111A', '111.1', etc)
|
|
42
|
+
* @param {number} sumForHeightCalc Sum of all monomer counts for height calculation
|
|
43
|
+
* @param {number} rowCount Count of elements in column
|
|
44
|
+
* @param {string[]} freq frequency of monomers in position
|
|
45
|
+
*/
|
|
46
|
+
constructor(name, freq = {}, rowCount = 0, sumForHeightCalc = 0) {
|
|
47
|
+
this.name = name;
|
|
48
|
+
this.freq = freq;
|
|
49
|
+
this.rowCount = rowCount;
|
|
50
|
+
this.sumForHeightCalc = sumForHeightCalc;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export class WebLogoViewer extends DG.JsViewer {
|
|
54
|
+
constructor() {
|
|
55
|
+
super();
|
|
56
|
+
this.viewerId = -1;
|
|
57
|
+
this.initialized = false;
|
|
58
|
+
// private readonly colorScheme: ColorScheme = ColorSchemes[NucleotidesWebLogo.residuesSet];
|
|
59
|
+
this.cp = null;
|
|
60
|
+
this.axisHeight = 12;
|
|
61
|
+
this.seqCol = null;
|
|
62
|
+
this.splitter = null;
|
|
63
|
+
// private maxLength: number = 100;
|
|
64
|
+
this.positions = [];
|
|
65
|
+
this.rowsMasked = 0;
|
|
66
|
+
this.rowsNull = 0;
|
|
67
|
+
this.visibleSlider = false;
|
|
68
|
+
this.allowResize = true;
|
|
69
|
+
this.turnOfResizeForOneSetValue = false;
|
|
70
|
+
this.backgroundColor = 0xFFFFFFFF;
|
|
71
|
+
this.positionMargin = 0;
|
|
72
|
+
this.positionNames = [];
|
|
73
|
+
this.startPosition = -1;
|
|
74
|
+
this.endPosition = -1;
|
|
75
|
+
this.viewSubs = [];
|
|
76
|
+
this.viewerId = WebLogoViewer.viewerCount;
|
|
77
|
+
WebLogoViewer.viewerCount += 1;
|
|
78
|
+
this.textBaseline = 'top';
|
|
79
|
+
this.unitsHandler = null;
|
|
80
|
+
this.backgroundColor = this.int('backgroundColor', 0xFFFFFFFF);
|
|
81
|
+
this._positionWidth = this.positionWidth = this.float('positionWidth', 16 /*,
|
|
82
|
+
{editor: 'slider', min: 4, max: 64, postfix: 'px'}*/);
|
|
83
|
+
this.minHeight = this.float('minHeight', 50 /*,
|
|
84
|
+
{editor: 'slider', min: 25, max: 250, postfix: 'px'}*/);
|
|
85
|
+
this.maxHeight = this.float('maxHeight', 100 /*,
|
|
86
|
+
{editor: 'slider', min: 25, max: 500, postfix: 'px'}*/);
|
|
87
|
+
this.skipEmptySequences = this.bool('skipEmptySequences', true);
|
|
88
|
+
this.sequenceColumnName = this.string('sequenceColumnName', null);
|
|
89
|
+
this.startPositionName = this.string('startPositionName', null);
|
|
90
|
+
this.endPositionName = this.string('endPositionName', null);
|
|
91
|
+
this.fixWidth = this.bool('fixWidth', false);
|
|
92
|
+
this.verticalAlignment = this.string('verticalAlignment', 'middle', { choices: ['top', 'middle', 'bottom'] });
|
|
93
|
+
this.horizontalAlignment = this.string('horizontalAlignment', 'center', { choices: ['left', 'center', 'right'] });
|
|
94
|
+
this.fitArea = this.bool('fitArea', true);
|
|
95
|
+
this.shrinkEmptyTail = this.bool('shrinkEmptyTail', true);
|
|
96
|
+
this.skipEmptyPositions = this.bool('skipEmptyPositions', false);
|
|
97
|
+
this.positionMarginState = this.string('positionMarginState', 'auto', { choices: ['auto', 'enable', 'off'] });
|
|
98
|
+
let defaultValueForPositionMargin = 0;
|
|
99
|
+
if (this.positionMarginState === 'auto') {
|
|
100
|
+
defaultValueForPositionMargin = 4;
|
|
101
|
+
}
|
|
102
|
+
this.positionMargin = this.int('positionMargin', defaultValueForPositionMargin, { min: 0, max: 16 });
|
|
103
|
+
this.positionHeight = this.string('positionHeight', PositionHeight.full, { choices: [PositionHeight.full, PositionHeight.Entropy] });
|
|
104
|
+
const style = { style: 'barbell' };
|
|
105
|
+
this.slider = ui.rangeSlider(0, 100, 0, 20, false, style);
|
|
106
|
+
this.canvas = ui.canvas();
|
|
107
|
+
this.canvas.style.width = '100%';
|
|
108
|
+
}
|
|
109
|
+
/** For startPosition equals to endPosition Length is 1 */
|
|
110
|
+
get Length() {
|
|
111
|
+
if (this.skipEmptyPositions) {
|
|
112
|
+
return this.positions.length;
|
|
113
|
+
}
|
|
114
|
+
return this.startPosition <= this.endPosition ? this.endPosition - this.startPosition + 1 : 0;
|
|
115
|
+
}
|
|
116
|
+
/** Calculate new position data basic on {@link positionMarginState} and {@link positionMargin} */
|
|
117
|
+
get positionWidthWithMargin() {
|
|
118
|
+
return this._positionWidth + this.positionMarginValue;
|
|
119
|
+
}
|
|
120
|
+
get positionMarginValue() {
|
|
121
|
+
var _a;
|
|
122
|
+
if ((this.positionMarginState === 'auto') && (((_a = this.unitsHandler) === null || _a === void 0 ? void 0 : _a.getAlphabetIsMultichar()) === true)) {
|
|
123
|
+
return this.positionMargin;
|
|
124
|
+
}
|
|
125
|
+
if (this.positionMarginState === 'enable') {
|
|
126
|
+
return this.positionMargin;
|
|
127
|
+
}
|
|
128
|
+
return 0;
|
|
129
|
+
}
|
|
130
|
+
/** Count of position rendered for calculations countOfRenderPositions */
|
|
131
|
+
get countOfRenderPositions() {
|
|
132
|
+
if (this.host == null) {
|
|
133
|
+
return 0;
|
|
134
|
+
}
|
|
135
|
+
const r = window.devicePixelRatio;
|
|
136
|
+
if (r > 1) {
|
|
137
|
+
return this.canvasWidthWithRatio / this.positionWidthWithMargin;
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
return this.canvas.width / (this.positionWidthWithMargin * r);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
get canvasWidthWithRatio() {
|
|
144
|
+
return this.canvas.width * window.devicePixelRatio;
|
|
145
|
+
}
|
|
146
|
+
/** Position of start rendering */
|
|
147
|
+
get firstVisibleIndex() {
|
|
148
|
+
return (this.visibleSlider) ? Math.floor(this.slider.min) : 0;
|
|
149
|
+
}
|
|
150
|
+
init() {
|
|
151
|
+
if (this.initialized) {
|
|
152
|
+
console.error('WebLogo second initialization!');
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
this.initialized = true;
|
|
156
|
+
this.helpUrl = '/help/visualize/viewers/web-logo.md';
|
|
157
|
+
this.msgHost = ui.div('No message');
|
|
158
|
+
this.msgHost.style.display = 'none';
|
|
159
|
+
this.canvas = ui.canvas();
|
|
160
|
+
this.canvas.style.width = '100%';
|
|
161
|
+
//this.slider.setShowHandles(false);
|
|
162
|
+
this.slider.root.style.position = 'absolute';
|
|
163
|
+
this.slider.root.style.zIndex = '999';
|
|
164
|
+
this.slider.root.style.display = 'none';
|
|
165
|
+
this.slider.root.style.height = '0.7em';
|
|
166
|
+
this.visibleSlider = false;
|
|
167
|
+
this.slider.onValuesChanged.subscribe(() => {
|
|
168
|
+
if ((this.host == null)) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
/* Resize slider if we can resize do that */
|
|
172
|
+
if ((this.allowResize) && (!this.turnOfResizeForOneSetValue) &&
|
|
173
|
+
(this.visibleSlider)) {
|
|
174
|
+
const countOfPositions = Math.ceil(this.slider.max - this.slider.min);
|
|
175
|
+
const calculatedWidth = (this.canvas.width / countOfPositions) - this.positionMarginValue;
|
|
176
|
+
// saving positionWidth value global (even if slider is not visible)
|
|
177
|
+
this.positionWidth = calculatedWidth;
|
|
178
|
+
this._positionWidth = calculatedWidth;
|
|
179
|
+
}
|
|
180
|
+
this.turnOfResizeForOneSetValue = false;
|
|
181
|
+
this.render(true);
|
|
182
|
+
});
|
|
183
|
+
this.host = ui.div([this.msgHost, this.canvas]);
|
|
184
|
+
this.host.style.justifyContent = 'center';
|
|
185
|
+
this.host.style.alignItems = 'center';
|
|
186
|
+
this.host.style.position = 'relative';
|
|
187
|
+
this.host.style.setProperty('overflow', 'hidden', 'important');
|
|
188
|
+
const getMonomer = (p) => {
|
|
189
|
+
const calculatedX = p.x + this.firstVisibleIndex * this.positionWidthWithMargin;
|
|
190
|
+
const jPos = Math.floor(p.x / this.positionWidthWithMargin + this.firstVisibleIndex);
|
|
191
|
+
const position = this.positions[jPos];
|
|
192
|
+
if (position === void 0)
|
|
193
|
+
return [jPos, null, null];
|
|
194
|
+
const monomer = Object.keys(position.freq)
|
|
195
|
+
.find((m) => position.freq[m].bounds.contains(calculatedX, p.y));
|
|
196
|
+
if (monomer === undefined)
|
|
197
|
+
return [jPos, null, null];
|
|
198
|
+
return [jPos, monomer, position.freq[monomer]];
|
|
199
|
+
};
|
|
200
|
+
const correctMonomerFilter = (iRow, monomer, jPos) => {
|
|
201
|
+
const seq = this.seqCol.get(iRow);
|
|
202
|
+
const seqM = seq ? this.splitter(seq)[this.startPosition + jPos] : null;
|
|
203
|
+
return ((seqM === monomer) || (seqM === '' && monomer === '-')) && this.dataFrame.filter.get(iRow);
|
|
204
|
+
};
|
|
205
|
+
rxjs.fromEvent(this.canvas, 'mousemove').subscribe((e) => {
|
|
206
|
+
const args = e;
|
|
207
|
+
const r = window.devicePixelRatio;
|
|
208
|
+
const cursorP = this.canvas.getCursorPosition(args, r);
|
|
209
|
+
const [jPos, monomer] = getMonomer(cursorP);
|
|
210
|
+
if (this.dataFrame && this.seqCol && this.splitter && monomer) {
|
|
211
|
+
const rowCount = wu.count().take(this.dataFrame.rowCount).filter(function (iRow) {
|
|
212
|
+
return correctMonomerFilter(iRow, monomer, jPos);
|
|
213
|
+
}).reduce((count, iRow) => count + 1, 0);
|
|
214
|
+
ui.tooltip.show(ui.div([ui.div(`${monomer}`), ui.div(`${rowCount} rows`)]), args.x + 16, args.y + 16);
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
ui.tooltip.hide();
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
rxjs.fromEvent(this.canvas, 'mousedown').subscribe((e) => {
|
|
221
|
+
const args = e;
|
|
222
|
+
const r = window.devicePixelRatio;
|
|
223
|
+
const [jPos, monomer] = getMonomer(this.canvas.getCursorPosition(args, r));
|
|
224
|
+
// prevents deselect all rows if we miss monomer bounds
|
|
225
|
+
if (this.dataFrame && this.seqCol && this.splitter && monomer) {
|
|
226
|
+
this.dataFrame.selection.init(function (iRow) {
|
|
227
|
+
return correctMonomerFilter(iRow, monomer, jPos);
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
rxjs.fromEvent(this.canvas, 'wheel').subscribe((e) => {
|
|
232
|
+
if (!this.visibleSlider)
|
|
233
|
+
return;
|
|
234
|
+
const countOfScrollPositions = (e.deltaY / 100) * Math.max(Math.floor((this.countOfRenderPositions) / 2), 1);
|
|
235
|
+
this.slider.scrollBy(this.slider.min + countOfScrollPositions);
|
|
236
|
+
});
|
|
237
|
+
this.viewSubs.push(ui.onSizeChanged(this.root).subscribe(this.rootOnSizeChanged.bind(this)));
|
|
238
|
+
this.root.append(this.host);
|
|
239
|
+
this.root.append(this.slider.root);
|
|
240
|
+
this._calculate(window.devicePixelRatio);
|
|
241
|
+
this.updateSlider();
|
|
242
|
+
this.render(true);
|
|
243
|
+
}
|
|
244
|
+
/** Handler of changing size WebLogo */
|
|
245
|
+
rootOnSizeChanged() {
|
|
246
|
+
this._calculate(window.devicePixelRatio);
|
|
247
|
+
this.updateSlider();
|
|
248
|
+
this.render(true);
|
|
249
|
+
}
|
|
250
|
+
/** Assigns {@link seqCol} and {@link cp} based on {@link sequenceColumnName} and calls {@link render}().
|
|
251
|
+
*/
|
|
252
|
+
updateSeqCol() {
|
|
253
|
+
if (this.dataFrame) {
|
|
254
|
+
this.seqCol = this.sequenceColumnName ? this.dataFrame.col(this.sequenceColumnName) : null;
|
|
255
|
+
if (this.seqCol == null) {
|
|
256
|
+
this.seqCol = pickUpSeqCol(this.dataFrame);
|
|
257
|
+
this.sequenceColumnName = this.seqCol ? this.seqCol.name : null;
|
|
258
|
+
}
|
|
259
|
+
if (this.seqCol) {
|
|
260
|
+
const units = this.seqCol.getTag(DG.TAGS.UNITS);
|
|
261
|
+
const separator = this.seqCol.getTag("separator" /* TAGS.separator */);
|
|
262
|
+
this.splitter = getSplitter(units, separator);
|
|
263
|
+
this.unitsHandler = new UnitsHandler(this.seqCol);
|
|
264
|
+
this.updatePositions();
|
|
265
|
+
this.cp = pickUpPalette(this.seqCol);
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
this.splitter = null;
|
|
269
|
+
this.positionNames = [];
|
|
270
|
+
this.startPosition = -1;
|
|
271
|
+
this.endPosition = -1;
|
|
272
|
+
this.cp = null;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
this.render();
|
|
276
|
+
}
|
|
277
|
+
/** Updates {@link positionNames} and calculates {@link startPosition} and {@link endPosition}.
|
|
278
|
+
*/
|
|
279
|
+
updatePositions() {
|
|
280
|
+
if (!this.seqCol)
|
|
281
|
+
return;
|
|
282
|
+
let categories;
|
|
283
|
+
if (this.shrinkEmptyTail) {
|
|
284
|
+
const indices = this.dataFrame.filter.getSelectedIndexes();
|
|
285
|
+
categories = Array.from(new Set(Array.from(Array(indices.length).keys()).map((i) => this.seqCol.get(indices[i]))));
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
categories = this.seqCol.categories;
|
|
289
|
+
}
|
|
290
|
+
const maxLength = categories.length > 0 ? Math.max(...categories.map((s) => s !== null ? this.splitter(s).length : 0)) : 0;
|
|
291
|
+
// Get position names from data column tag 'positionNames'
|
|
292
|
+
const positionNamesTxt = this.seqCol.getTag('positionNames');
|
|
293
|
+
// Fallback if 'positionNames' tag is not provided
|
|
294
|
+
this.positionNames = positionNamesTxt ? positionNamesTxt.split(', ').map((n) => n.trim()) :
|
|
295
|
+
[...Array(maxLength).keys()].map((jPos) => `${jPos + 1}`);
|
|
296
|
+
this.startPosition = (this.startPositionName && this.positionNames &&
|
|
297
|
+
this.positionNames.includes(this.startPositionName)) ?
|
|
298
|
+
this.positionNames.indexOf(this.startPositionName) : 0;
|
|
299
|
+
this.endPosition = (this.endPositionName && this.positionNames &&
|
|
300
|
+
this.positionNames.includes(this.endPositionName)) ?
|
|
301
|
+
this.positionNames.indexOf(this.endPositionName) : (maxLength - 1);
|
|
302
|
+
}
|
|
303
|
+
get widthArea() {
|
|
304
|
+
return this.Length * this.positionWidth / window.devicePixelRatio;
|
|
305
|
+
}
|
|
306
|
+
get heightArea() {
|
|
307
|
+
return Math.min(this.maxHeight, Math.max(this.minHeight, this.root.clientHeight));
|
|
308
|
+
}
|
|
309
|
+
get xScale() {
|
|
310
|
+
return (this.root.clientWidth - this.Length * this.positionMarginValue) / this.widthArea;
|
|
311
|
+
}
|
|
312
|
+
get yScale() {
|
|
313
|
+
return this.root.clientHeight / this.heightArea;
|
|
314
|
+
}
|
|
315
|
+
checkIsHideSlider() {
|
|
316
|
+
let showSliderWithFitArea = true;
|
|
317
|
+
const minScale = Math.min(this.xScale, this.yScale);
|
|
318
|
+
if (((minScale == this.xScale) || (minScale <= 1)) && (this.fitArea)) {
|
|
319
|
+
showSliderWithFitArea = false;
|
|
320
|
+
}
|
|
321
|
+
return ((this.fixWidth || Math.ceil(this.canvas.width / this.positionWidthWithMargin) >= this.Length) || (showSliderWithFitArea));
|
|
322
|
+
}
|
|
323
|
+
setSliderVisibility(visible) {
|
|
324
|
+
if (visible) {
|
|
325
|
+
this.slider.root.style.display = 'inherit';
|
|
326
|
+
this.visibleSlider = true;
|
|
327
|
+
}
|
|
328
|
+
else {
|
|
329
|
+
this.slider.root.style.display = 'none';
|
|
330
|
+
this.visibleSlider = false;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
/** Updates {@link slider}, needed to set slider options and to update slider position. */
|
|
334
|
+
updateSlider() {
|
|
335
|
+
if (this.checkIsHideSlider()) {
|
|
336
|
+
this.setSliderVisibility(false);
|
|
337
|
+
}
|
|
338
|
+
else {
|
|
339
|
+
this.setSliderVisibility(true);
|
|
340
|
+
}
|
|
341
|
+
if ((this.slider != null) && (this.canvas != null)) {
|
|
342
|
+
let diffEndScrollAndSliderMin = Math.floor(this.slider.min + this.canvas.width / this.positionWidthWithMargin) - this.Length;
|
|
343
|
+
diffEndScrollAndSliderMin = diffEndScrollAndSliderMin > 0 ? diffEndScrollAndSliderMin : 0;
|
|
344
|
+
let newMin = Math.floor(this.slider.min - diffEndScrollAndSliderMin);
|
|
345
|
+
let newMax = Math.floor(this.slider.min - diffEndScrollAndSliderMin) + Math.floor(this.canvas.width / this.positionWidthWithMargin);
|
|
346
|
+
if (this.checkIsHideSlider()) {
|
|
347
|
+
newMin = 0;
|
|
348
|
+
newMax = this.Length - 1;
|
|
349
|
+
}
|
|
350
|
+
this.turnOfResizeForOneSetValue = true;
|
|
351
|
+
this.slider.setValues(0, this.Length, newMin, newMax);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
/** Handler of property change events. */
|
|
355
|
+
onPropertyChanged(property) {
|
|
356
|
+
super.onPropertyChanged(property);
|
|
357
|
+
switch (property.name) {
|
|
358
|
+
case 'sequenceColumnName':
|
|
359
|
+
this.updateSeqCol();
|
|
360
|
+
break;
|
|
361
|
+
case 'startPositionName':
|
|
362
|
+
this.updateSeqCol();
|
|
363
|
+
break;
|
|
364
|
+
case 'endPositionName':
|
|
365
|
+
this.updateSeqCol();
|
|
366
|
+
break;
|
|
367
|
+
case 'positionWidth':
|
|
368
|
+
this._positionWidth = this.positionWidth;
|
|
369
|
+
this.updateSlider();
|
|
370
|
+
break;
|
|
371
|
+
case 'fixWidth':
|
|
372
|
+
this.updateSlider();
|
|
373
|
+
break;
|
|
374
|
+
case 'fitArea':
|
|
375
|
+
this.updateSlider();
|
|
376
|
+
break;
|
|
377
|
+
case 'shrinkEmptyTail':
|
|
378
|
+
this.updatePositions();
|
|
379
|
+
break;
|
|
380
|
+
case 'skipEmptyPositions':
|
|
381
|
+
this.updatePositions();
|
|
382
|
+
break;
|
|
383
|
+
case 'positionMargin':
|
|
384
|
+
this.updateSlider();
|
|
385
|
+
break;
|
|
386
|
+
}
|
|
387
|
+
this.render(true);
|
|
388
|
+
}
|
|
389
|
+
/** Add filter handlers when table is a attached */
|
|
390
|
+
onTableAttached() {
|
|
391
|
+
super.onTableAttached();
|
|
392
|
+
const dataFrameTxt = this.dataFrame ? 'data' : 'null';
|
|
393
|
+
console.debug(`bio: WebLogo<${this.viewerId}>.onTableAttached( dataFrame = ${dataFrameTxt} ) start`);
|
|
394
|
+
this.updateSeqCol();
|
|
395
|
+
if (this.dataFrame !== void 0) {
|
|
396
|
+
this.subs.push(this.dataFrame.selection.onChanged.subscribe((_) => this.render()));
|
|
397
|
+
this.subs.push(this.dataFrame.filter.onChanged.subscribe((_) => {
|
|
398
|
+
this.updatePositions();
|
|
399
|
+
this.render();
|
|
400
|
+
}));
|
|
401
|
+
}
|
|
402
|
+
this.init();
|
|
403
|
+
console.debug(`bio: WebLogo<${this.viewerId}>.onTableAttached() end`);
|
|
404
|
+
}
|
|
405
|
+
/** Remove all handlers when table is a detach */
|
|
406
|
+
detach() {
|
|
407
|
+
const _super = Object.create(null, {
|
|
408
|
+
detach: { get: () => super.detach }
|
|
409
|
+
});
|
|
410
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
411
|
+
const dataFrameTxt = `${this.dataFrame ? 'data' : 'null'}`;
|
|
412
|
+
console.debug(`bio: WebLogo<${this.viewerId}>.onTableAttached( dataFrame = ${dataFrameTxt} ) start`);
|
|
413
|
+
_super.detach.call(this);
|
|
414
|
+
this.viewSubs.forEach((sub) => sub.unsubscribe());
|
|
415
|
+
this.host.remove();
|
|
416
|
+
this.msgHost = undefined;
|
|
417
|
+
this.host = undefined;
|
|
418
|
+
this.initialized = false;
|
|
419
|
+
console.debug(`bio: WebLogo<${this.viewerId}>.onTableAttached() end`);
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
/** Helper function for rendering */
|
|
423
|
+
_nullSequence(fillerResidue = 'X') {
|
|
424
|
+
if (!this.skipEmptySequences)
|
|
425
|
+
return new Array(this.Length).fill(fillerResidue).join('');
|
|
426
|
+
return '';
|
|
427
|
+
}
|
|
428
|
+
/** Helper function for remove empty positions */
|
|
429
|
+
// TODO: use this function in from core
|
|
430
|
+
removeWhere(array, predicate) {
|
|
431
|
+
let length = array.length;
|
|
432
|
+
let updateIterator = 0;
|
|
433
|
+
for (let deleteIterator = 0; deleteIterator < length; deleteIterator++) {
|
|
434
|
+
if (!predicate(array[deleteIterator])) {
|
|
435
|
+
array[updateIterator] = array[deleteIterator];
|
|
436
|
+
updateIterator++;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
array.length = updateIterator;
|
|
440
|
+
return array;
|
|
441
|
+
}
|
|
442
|
+
/** Function for removing empty positions */
|
|
443
|
+
_removeEmptyPositions() {
|
|
444
|
+
if (this.skipEmptyPositions) {
|
|
445
|
+
this.removeWhere(this.positions, item => { var _a; return ((_a = item === null || item === void 0 ? void 0 : item.freq['-']) === null || _a === void 0 ? void 0 : _a.count) === item.rowCount; });
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
_calculate(r) {
|
|
449
|
+
if (!this.host || !this.seqCol || !this.dataFrame)
|
|
450
|
+
return;
|
|
451
|
+
this.unitsHandler = new UnitsHandler(this.seqCol);
|
|
452
|
+
this.calcSize();
|
|
453
|
+
this.positions = new Array(this.startPosition <= this.endPosition ? this.endPosition - this.startPosition + 1 : 0);
|
|
454
|
+
for (let jPos = 0; jPos < this.Length; jPos++) {
|
|
455
|
+
const posName = this.positionNames[this.startPosition + jPos];
|
|
456
|
+
this.positions[jPos] = new PositionInfo(posName);
|
|
457
|
+
}
|
|
458
|
+
// 2022-05-05 askalkin instructed to show WebLogo based on filter (not selection)
|
|
459
|
+
const indices = this.dataFrame.filter.getSelectedIndexes();
|
|
460
|
+
// const indices = this.dataFrame.selection.trueCount > 0 ? this.dataFrame.selection.getSelectedIndexes() :
|
|
461
|
+
// this.dataFrame.filter.getSelectedIndexes();
|
|
462
|
+
this.rowsMasked = indices.length;
|
|
463
|
+
this.rowsNull = 0;
|
|
464
|
+
for (const i of indices) {
|
|
465
|
+
let s = (this.seqCol.get(i));
|
|
466
|
+
if (!s) {
|
|
467
|
+
s = this._nullSequence();
|
|
468
|
+
++this.rowsNull;
|
|
469
|
+
}
|
|
470
|
+
const seqM = this.splitter(s);
|
|
471
|
+
for (let jPos = 0; jPos < this.Length; jPos++) {
|
|
472
|
+
const pmInfo = this.positions[jPos].freq;
|
|
473
|
+
const m = seqM[this.startPosition + jPos] || '-';
|
|
474
|
+
if (!(m in pmInfo))
|
|
475
|
+
pmInfo[m] = new PositionMonomerInfo();
|
|
476
|
+
pmInfo[m].count++;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
//#region Polish freq counts
|
|
480
|
+
for (let jPos = 0; jPos < this.Length; jPos++) {
|
|
481
|
+
// delete this.positions[jPos].freq['-'];
|
|
482
|
+
this.positions[jPos].rowCount = 0;
|
|
483
|
+
for (const m in this.positions[jPos].freq)
|
|
484
|
+
this.positions[jPos].rowCount += this.positions[jPos].freq[m].count;
|
|
485
|
+
if (this.positionHeight == PositionHeight.Entropy) {
|
|
486
|
+
this.positions[jPos].sumForHeightCalc = 0;
|
|
487
|
+
for (const m in this.positions[jPos].freq) {
|
|
488
|
+
const pn = this.positions[jPos].freq[m].count / this.positions[jPos].rowCount;
|
|
489
|
+
this.positions[jPos].sumForHeightCalc += -pn * Math.log2(pn);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
//#endregion
|
|
494
|
+
this._removeEmptyPositions();
|
|
495
|
+
const absoluteMaxHeight = this.canvas.height - this.axisHeight * r;
|
|
496
|
+
//#region Calculate screen
|
|
497
|
+
for (let jPos = 0; jPos < this.Length; jPos++) {
|
|
498
|
+
const freq = this.positions[jPos].freq;
|
|
499
|
+
const rowCount = this.positions[jPos].rowCount;
|
|
500
|
+
const alphabetSize = this.getAlphabetSize();
|
|
501
|
+
if ((this.positionHeight == PositionHeight.Entropy) && (alphabetSize == null)) {
|
|
502
|
+
grok.shell.error('WebLogo: alphabet is undefined.');
|
|
503
|
+
}
|
|
504
|
+
const maxHeight = (this.positionHeight == PositionHeight.Entropy) ? (absoluteMaxHeight * (Math.log2(alphabetSize) - (this.positions[jPos].sumForHeightCalc)) / Math.log2(alphabetSize)) : absoluteMaxHeight;
|
|
505
|
+
let y = this.axisHeight * r + (absoluteMaxHeight - maxHeight - 1);
|
|
506
|
+
const entries = Object.entries(freq).sort((a, b) => {
|
|
507
|
+
if (a[0] !== '-' && b[0] !== '-')
|
|
508
|
+
return b[1].count - a[1].count;
|
|
509
|
+
else if (a[0] === '-' && b[0] === '-')
|
|
510
|
+
return 0;
|
|
511
|
+
else if (a[0] === '-')
|
|
512
|
+
return -1;
|
|
513
|
+
else /* (b[0] === '-') */
|
|
514
|
+
return +1;
|
|
515
|
+
});
|
|
516
|
+
for (const entry of entries) {
|
|
517
|
+
const pmInfo = entry[1];
|
|
518
|
+
// const m: string = entry[0];
|
|
519
|
+
const h = maxHeight * pmInfo.count / rowCount;
|
|
520
|
+
pmInfo.bounds = new DG.Rect(jPos * this.positionWidthWithMargin, y, this._positionWidth, h);
|
|
521
|
+
y += h;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
//#endregion
|
|
525
|
+
}
|
|
526
|
+
/** Render WebLogo sensitive to changes in params of rendering
|
|
527
|
+
*@param {boolean} recalc - indicates that need to recalculate data for rendering
|
|
528
|
+
*/
|
|
529
|
+
render(recalc = true) {
|
|
530
|
+
var _a;
|
|
531
|
+
if (this.msgHost) {
|
|
532
|
+
if (this.seqCol && !this.cp) {
|
|
533
|
+
this.msgHost.innerText = `Unknown palette (column semType: '${this.seqCol.semType}').`;
|
|
534
|
+
this.msgHost.style.display = '';
|
|
535
|
+
}
|
|
536
|
+
else {
|
|
537
|
+
this.msgHost.style.display = 'none';
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
if (!this.seqCol || !this.dataFrame || !this.cp || this.startPosition === -1 || this.endPosition === -1 || this.host == null || this.slider == null)
|
|
541
|
+
return;
|
|
542
|
+
const g = this.canvas.getContext('2d');
|
|
543
|
+
if (!g)
|
|
544
|
+
return;
|
|
545
|
+
this.slider.root.style.width = `${this.host.clientWidth}px`;
|
|
546
|
+
const r = window.devicePixelRatio;
|
|
547
|
+
if (recalc)
|
|
548
|
+
this._calculate(r);
|
|
549
|
+
g.resetTransform();
|
|
550
|
+
g.fillStyle = DG.Color.toHtml(this.backgroundColor);
|
|
551
|
+
g.fillRect(0, 0, this.canvas.width, this.canvas.height);
|
|
552
|
+
g.textBaseline = this.textBaseline;
|
|
553
|
+
const maxCountOfRowsRendered = this.countOfRenderPositions + 1;
|
|
554
|
+
const firstVisibleIndex = (this.visibleSlider) ? Math.floor(this.slider.min) : 0;
|
|
555
|
+
const lastVisibleIndex = Math.min(this.Length, firstVisibleIndex + maxCountOfRowsRendered);
|
|
556
|
+
//#region Plot positionNames
|
|
557
|
+
const positionFontSize = 10 * r;
|
|
558
|
+
g.resetTransform();
|
|
559
|
+
g.fillStyle = 'black';
|
|
560
|
+
g.textAlign = 'center';
|
|
561
|
+
g.font = `${positionFontSize.toFixed(1)}px Roboto, Roboto Local, sans-serif`;
|
|
562
|
+
const posNameMaxWidth = Math.max(...this.positions.map((pos) => g.measureText(pos.name).width));
|
|
563
|
+
const hScale = posNameMaxWidth < (this._positionWidth - 2) ? 1 : (this._positionWidth - 2) / posNameMaxWidth;
|
|
564
|
+
for (let jPos = this.firstVisibleIndex; jPos < lastVisibleIndex; jPos++) {
|
|
565
|
+
const pos = this.positions[jPos];
|
|
566
|
+
g.resetTransform();
|
|
567
|
+
g.setTransform(hScale, 0, 0, 1, jPos * this.positionWidthWithMargin + this._positionWidth / 2 - this.positionWidthWithMargin * firstVisibleIndex, 0);
|
|
568
|
+
g.fillText(pos.name, 0, 0);
|
|
569
|
+
}
|
|
570
|
+
//#endregion Plot positionNames
|
|
571
|
+
const fontStyle = '16px Roboto, Roboto Local, sans-serif';
|
|
572
|
+
// Hacks to scale uppercase characters to target rectangle
|
|
573
|
+
const uppercaseLetterAscent = 0.25;
|
|
574
|
+
const uppercaseLetterHeight = 12.2;
|
|
575
|
+
for (let jPos = this.firstVisibleIndex; jPos < lastVisibleIndex; jPos++) {
|
|
576
|
+
for (const [monomer, pmInfo] of Object.entries(this.positions[jPos].freq)) {
|
|
577
|
+
if (monomer !== '-') {
|
|
578
|
+
const monomerTxt = monomerToShort(monomer, 5);
|
|
579
|
+
const b = pmInfo.bounds;
|
|
580
|
+
const left = b.left - this.positionWidthWithMargin * this.firstVisibleIndex;
|
|
581
|
+
g.resetTransform();
|
|
582
|
+
g.strokeStyle = 'lightgray';
|
|
583
|
+
g.lineWidth = 1;
|
|
584
|
+
g.rect(left, b.top, b.width, b.height);
|
|
585
|
+
g.fillStyle = (_a = this.cp.get(monomer)) !== null && _a !== void 0 ? _a : this.cp.get('other');
|
|
586
|
+
g.textAlign = 'left';
|
|
587
|
+
g.font = fontStyle;
|
|
588
|
+
//g.fillRect(b.left, b.top, b.width, b.height);
|
|
589
|
+
const mTm = g.measureText(monomerTxt);
|
|
590
|
+
g.setTransform(b.width / mTm.width, 0, 0, b.height / uppercaseLetterHeight, left, b.top);
|
|
591
|
+
g.fillText(monomerTxt, 0, -uppercaseLetterAscent);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
/** Calculate canvas size an positionWidth and updates properties */
|
|
597
|
+
calcSize() {
|
|
598
|
+
if (!this.host)
|
|
599
|
+
return;
|
|
600
|
+
const r = window.devicePixelRatio;
|
|
601
|
+
let width = this.widthArea;
|
|
602
|
+
let height = this.heightArea;
|
|
603
|
+
if ((this.fitArea) && (!this.visibleSlider)) {
|
|
604
|
+
const scale = Math.max(1, Math.min(this.xScale, this.yScale));
|
|
605
|
+
width = width * scale;
|
|
606
|
+
height = height * scale;
|
|
607
|
+
this._positionWidth = this.positionWidth * scale;
|
|
608
|
+
}
|
|
609
|
+
width = this.Length * this.positionWidthWithMargin / r;
|
|
610
|
+
this.canvas.width = this.root.clientWidth * r;
|
|
611
|
+
this.canvas.style.width = `${this.root.clientWidth}px`;
|
|
612
|
+
// const canvasHeight: number = width > this.root.clientWidth ? height - 8 : height;
|
|
613
|
+
this.host.style.setProperty('height', `${height}px`);
|
|
614
|
+
const canvasHeight = this.host.clientHeight;
|
|
615
|
+
this.canvas.height = canvasHeight * r;
|
|
616
|
+
// Adjust host and root width
|
|
617
|
+
if (this.fixWidth) {
|
|
618
|
+
// full width for canvas host and root
|
|
619
|
+
this.root.style.width = this.host.style.width = `${width}px`;
|
|
620
|
+
this.root.style.height = `${height}px`;
|
|
621
|
+
this.root.style.overflow = 'hidden';
|
|
622
|
+
this.host.style.setProperty('overflow-y', 'hidden', 'important');
|
|
623
|
+
}
|
|
624
|
+
else {
|
|
625
|
+
// allow scroll canvas in root
|
|
626
|
+
this.root.style.width = this.host.style.width = '100%';
|
|
627
|
+
this.host.style.overflowX = 'auto!important';
|
|
628
|
+
this.host.style.setProperty('text-align', this.horizontalAlignment);
|
|
629
|
+
const sliderHeight = this.visibleSlider ? 10 : 0;
|
|
630
|
+
// vertical alignment
|
|
631
|
+
let hostTopMargin = 0;
|
|
632
|
+
switch (this.verticalAlignment) {
|
|
633
|
+
case 'top':
|
|
634
|
+
hostTopMargin = 0;
|
|
635
|
+
break;
|
|
636
|
+
case 'middle':
|
|
637
|
+
hostTopMargin = Math.max(0, (this.root.clientHeight - height) / 2);
|
|
638
|
+
break;
|
|
639
|
+
case 'bottom':
|
|
640
|
+
hostTopMargin = Math.max(0, this.root.clientHeight - height - sliderHeight);
|
|
641
|
+
break;
|
|
642
|
+
}
|
|
643
|
+
// horizontal alignment
|
|
644
|
+
let hostLeftMargin = 0;
|
|
645
|
+
switch (this.horizontalAlignment) {
|
|
646
|
+
case 'left':
|
|
647
|
+
hostLeftMargin = 0;
|
|
648
|
+
break;
|
|
649
|
+
case 'center':
|
|
650
|
+
hostLeftMargin = Math.max(0, (this.root.clientWidth - width) / 2);
|
|
651
|
+
break;
|
|
652
|
+
case 'right':
|
|
653
|
+
hostLeftMargin = Math.max(0, this.root.clientWidth - width);
|
|
654
|
+
break;
|
|
655
|
+
}
|
|
656
|
+
this.host.style.setProperty('margin-top', `${hostTopMargin}px`, 'important');
|
|
657
|
+
this.host.style.setProperty('margin-left', `${hostLeftMargin}px`, 'important');
|
|
658
|
+
if (this.slider != null) {
|
|
659
|
+
this.slider.root.style.setProperty('margin-top', `${hostTopMargin + canvasHeight}px`, 'important');
|
|
660
|
+
}
|
|
661
|
+
if (this.root.clientHeight <= height) {
|
|
662
|
+
this.host.style.setProperty('height', `${this.root.clientHeight}px`);
|
|
663
|
+
this.host.style.setProperty('overflow-y', null);
|
|
664
|
+
}
|
|
665
|
+
else {
|
|
666
|
+
this.host.style.setProperty('overflow-y', 'hidden', 'important');
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
getAlphabetSize() {
|
|
671
|
+
var _a, _b;
|
|
672
|
+
return (_b = (_a = this.unitsHandler) === null || _a === void 0 ? void 0 : _a.getAlphabetSize()) !== null && _b !== void 0 ? _b : 0;
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
WebLogoViewer.residuesSet = 'nucleotides';
|
|
676
|
+
WebLogoViewer.viewerCount = -1;
|
|
677
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2ViLWxvZ28tdmlld2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsid2ViLWxvZ28tdmlld2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUFBLE9BQU8sS0FBSyxJQUFJLE1BQU0sbUJBQW1CLENBQUM7QUFDMUMsT0FBTyxLQUFLLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUN0QyxPQUFPLEtBQUssRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRXRDLE9BQU8sRUFBRSxNQUFNLElBQUksQ0FBQztBQUNwQixPQUFPLEtBQUssSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUk3QixPQUFPLEVBQUMsWUFBWSxFQUFDLE1BQU0sd0JBQXdCLENBQUM7QUFFcEQsT0FBTyxFQUFDLFdBQVcsRUFBRSxjQUFjLEVBQUUsYUFBYSxFQUFFLFlBQVksRUFBcUIsTUFBTSx3QkFBd0IsQ0FBQztBQUVwSCxNQUFNLENBQU4sSUFBWSxjQUdYO0FBSEQsV0FBWSxjQUFjO0lBQ3hCLHFDQUFtQixDQUFBO0lBQ25CLCtCQUFhLENBQUE7QUFDZixDQUFDLEVBSFcsY0FBYyxLQUFkLGNBQWMsUUFHekI7QUFRRDs7O0dBR0c7QUFDSCxpQkFBaUIsQ0FBQyxTQUFTLENBQUMsaUJBQWlCLEdBQUcsVUFBUyxLQUFpQixFQUFFLENBQVM7SUFDbkYsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7SUFDMUMsT0FBTyxJQUFJLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztBQUN2RixDQUFDLENBQUM7QUFFRixFQUFFLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLEdBQUcsVUFBUyxDQUFTLEVBQUUsQ0FBUztJQUN4RCxP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QUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsYUFBYSxFQUFFLEdBQUcsY0FBYyxJQUFJLEVBQUUsV0FBVyxDQUFDLENBQUM7WUFDL0UsSUFBSSxJQUFJLENBQUMsTUFBTSxJQUFJLElBQUksRUFBRTtnQkFDdkIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxZQUFZLEVBQUUsR0FBRyxhQUFhLEdBQUcsWUFBWSxJQUFJLEVBQUUsV0FBVyxDQUFDLENBQUM7YUFDcEc7WUFFRCxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxJQUFJLE1BQU0sRUFBRTtnQkFDcEMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLFFBQVEsRUFBRSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxJQUFJLENBQUMsQ0FBQztnQkFDckUsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLFlBQVksRUFBRSxJQUFJLENBQUMsQ0FBQzthQUNqRDtpQkFBTTtnQkFDTCxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsWUFBWSxFQUFFLFFBQVEsRUFBRSxXQUFXLENBQUMsQ0FBQzthQUNsRTtTQUNGO0lBQ0gsQ0FBQztJQUVNLGVBQWU7O1FBQ3BCLE9BQU8sTUFBQSxNQUFBLElBQUksQ0FBQyxZQUFZLDBDQUFFLGVBQWUsRUFBRSxtQ0FBSSxDQUFDLENBQUM7SUFDbkQsQ0FBQzs7QUF4dkJhLHlCQUFXLEdBQUcsYUFBYSxDQUFDO0FBQzNCLHlCQUFXLEdBQVcsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBncm9rIGZyb20gJ2RhdGFncm9rLWFwaS9ncm9rJztcbmltcG9ydCAqIGFzIHVpIGZyb20gJ2RhdGFncm9rLWFwaS91aSc7XG5pbXBvcnQgKiBhcyBERyBmcm9tICdkYXRhZ3Jvay1hcGkvZGcnO1xuXG5pbXBvcnQgd3UgZnJvbSAnd3UnO1xuaW1wb3J0ICogYXMgcnhqcyBmcm9tICdyeGpzJztcblxuaW1wb3J0IHtTZXFQYWxldHRlfSBmcm9tICcuLi9zZXEtcGFsZXR0ZXMnO1xuaW1wb3J0IHtTdWJzY3JpcHRpb259IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtVbml0c0hhbmRsZXJ9IGZyb20gJy4uL3V0aWxzL3VuaXRzLWhhbmRsZXInO1xuaW1wb3J0IHtTbGlkZXJPcHRpb25zfSBmcm9tICdkYXRhZ3Jvay1hcGkvZGcnO1xuaW1wb3J0IHtnZXRTcGxpdHRlciwgbW9ub21lclRvU2hvcnQsIHBpY2tVcFBhbGV0dGUsIHBpY2tVcFNlcUNvbCwgU3BsaXR0ZXJGdW5jLCBUQUdTfSBmcm9tICcuLi91dGlscy9tYWNyb21vbGVjdWxlJztcblxuZXhwb3J0IGVudW0gUG9zaXRpb25IZWlnaHQge1xuICBFbnRyb3B5ID0gJ0VudHJvcHknLFxuICBmdWxsID0gJzEwMCUnLFxufVxuXG5kZWNsYXJlIGdsb2JhbCB7XG4gIGludGVyZmFjZSBIVE1MQ2FudmFzRWxlbWVudCB7XG4gICAgZ2V0Q3Vyc29yUG9zaXRpb24oZXZlbnQ6IE1vdXNlRXZlbnQsIHI6IG51bWJlcik6IERHLlBvaW50O1xuICB9XG59XG5cbi8qKkBwYXJhbSB7TW91c2VFdmVudH0gZXZlbnRcbiAqIEBwYXJhbSB7bnVtYmVyfSByIGRldmljZVBpeGVsUmF0aW9uXG4gKiBAcmV0dXJuIHtERy5Qb2ludH0gY2FudmFzIHJlbGF0ZWQgY3Vyc29yIHBvc2l0aW9uXG4gKi9cbkhUTUxDYW52YXNFbGVtZW50LnByb3RvdHlwZS5nZXRDdXJzb3JQb3NpdGlvbiA9IGZ1bmN0aW9uKGV2ZW50OiBNb3VzZUV2ZW50LCByOiBudW1iZXIpOiBERy5Qb2ludCB7XG4gIGNvbnN0IHJlY3QgPSB0aGlzLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICByZXR1cm4gbmV3IERHLlBvaW50KChldmVudC5jbGllbnRYIC0gcmVjdC5sZWZ0KSAqIHIsIChldmVudC5jbGllbnRZIC0gcmVjdC50b3ApICogcik7XG59O1xuXG5ERy5SZWN0LnByb3RvdHlwZS5jb250YWlucyA9IGZ1bmN0aW9uKHg6IG51bWJlciwgeTogbnVtYmVyKTogYm9vbGVhbiB7XG4gIHJldHVybiB0aGlzLmxlZnQgPD0geCAmJiB4IDw9IHRoaXMucmlnaHQgJiYgdGhpcy50b3AgPD0geSAmJiB5IDw9IHRoaXMuYm90dG9tO1xufTtcblxuZXhwb3J0IGNsYXNzIFBvc2l0aW9uTW9ub21lckluZm8ge1xuICAvKiogU2VxdWVuY2VzIGNvdW50IHdpdGggbW9ub21lciBpbiBwb3NpdGlvbiAqL1xuICBjb3VudDogbnVtYmVyO1xuXG4gIC8qKiBSZW1lbWJlciBzY3JlZW4gY29vcmRzIHJlY3QgKi9cbiAgYm91bmRzOiBERy5SZWN0O1xuXG4gIGNvbnN0cnVjdG9yKGNvdW50OiBudW1iZXIgPSAwLCBib3VuZHM6IERHLlJlY3QgPSBuZXcgREcuUmVjdCgwLCAwLCAwLCAwKSkge1xuICAgIHRoaXMuY291bnQgPSBjb3VudDtcbiAgICB0aGlzLmJvdW5kcyA9IGJvdW5kcztcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgUG9zaXRpb25JbmZvIHtcbiAgcHVibGljIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcbiAgZnJlcTogeyBbbTogc3RyaW5nXTogUG9zaXRpb25Nb25vbWVySW5mbyB9O1xuICByb3dDb3VudDogbnVtYmVyO1xuICBzdW1Gb3JIZWlnaHRDYWxjOiBudW1iZXI7XG5cbiAgLyoqIGZyZXEgPSB7fSwgcm93Q291bnQgPSAwXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIE5hbWUgb2YgcG9zaXRpb24gKCcxMTFBJywgJzExMS4xJywgZXRjKVxuICAgKiBAcGFyYW0ge251bWJlcn0gc3VtRm9ySGVpZ2h0Q2FsYyBTdW0gb2YgYWxsIG1vbm9tZXIgY291bnRzIGZvciBoZWlnaHQgY2FsY3VsYXRpb25cbiAgICogQHBhcmFtIHtudW1iZXJ9IHJvd0NvdW50IENvdW50IG9mIGVsZW1lbnRzIGluIGNvbHVtblxuICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBmcmVxIGZyZXF1ZW5jeSBvZiBtb25vbWVycyBpbiBwb3NpdGlvblxuICAgKi9cbiAgY29uc3RydWN0b3IobmFtZTogc3RyaW5nLCBmcmVxOiB7IFttOiBzdHJpbmddOiBQb3NpdGlvbk1vbm9tZXJJbmZvIH0gPSB7fSwgcm93Q291bnQ6IG51bWJlciA9IDAsIHN1bUZvckhlaWdodENhbGM6IG51bWJlciA9IDApIHtcbiAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgIHRoaXMuZnJlcSA9IGZyZXE7XG4gICAgdGhpcy5yb3dDb3VudCA9IHJvd0NvdW50O1xuICAgIHRoaXMuc3VtRm9ySGVpZ2h0Q2FsYyA9IHN1bUZvckhlaWdodENhbGM7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFdlYkxvZ29WaWV3ZXIgZXh0ZW5kcyBERy5Kc1ZpZXdlciB7XG4gIHB1YmxpYyBzdGF0aWMgcmVzaWR1ZXNTZXQgPSAnbnVjbGVvdGlkZXMnO1xuICBwcml2YXRlIHN0YXRpYyB2aWV3ZXJDb3VudDogbnVtYmVyID0gLTE7XG5cbiAgcHJpdmF0ZSByZWFkb25seSB2aWV3ZXJJZDogbnVtYmVyID0gLTE7XG4gIHByaXZhdGUgdW5pdHNIYW5kbGVyOiBVbml0c0hhbmRsZXIgfCBudWxsO1xuICBwcml2YXRlIGluaXRpYWxpemVkOiBib29sZWFuID0gZmFsc2U7XG5cbiAgLy8gcHJpdmF0ZSByZWFkb25seSBjb2xvclNjaGVtZTogQ29sb3JTY2hlbWUgPSBDb2xvclNjaGVtZXNbTnVjbGVvdGlkZXNXZWJMb2dvLnJlc2lkdWVzU2V0XTtcbiAgcHJvdGVjdGVkIGNwOiBTZXFQYWxldHRlIHwgbnVsbCA9IG51bGw7XG5cbiAgcHJpdmF0ZSBob3N0PzogSFRNTERpdkVsZW1lbnQ7XG4gIHByaXZhdGUgbXNnSG9zdD86IEhUTUxFbGVtZW50O1xuICBwcml2YXRlIGNhbnZhczogSFRNTENhbnZhc0VsZW1lbnQ7XG4gIHByaXZhdGUgc2xpZGVyOiBERy5SYW5nZVNsaWRlcjtcbiAgcHJpdmF0ZSByZWFkb25seSB0ZXh0QmFzZWxpbmU6IENhbnZhc1RleHRCYXNlbGluZTtcblxuICBwcml2YXRlIGF4aXNIZWlnaHQ6IG51bWJlciA9IDEyO1xuXG4gIHByaXZhdGUgc2VxQ29sOiBERy5Db2x1bW48c3RyaW5nPiB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHNwbGl0dGVyOiBTcGxpdHRlckZ1bmMgfCBudWxsID0gbnVsbDtcbiAgLy8gcHJpdmF0ZSBtYXhMZW5ndGg6IG51bWJlciA9IDEwMDtcbiAgcHJpdmF0ZSBwb3NpdGlvbnM6IFBvc2l0aW9uSW5mb1tdID0gW107XG5cbiAgcHJpdmF0ZSByb3dzTWFza2VkOiBudW1iZXIgPSAwO1xuICBwcml2YXRlIHJvd3NOdWxsOiBudW1iZXIgPSAwO1xuICBwcml2YXRlIHZpc2libGVTbGlkZXI6IGJvb2xlYW4gPSBmYWxzZTtcbiAgcHJpdmF0ZSBhbGxvd1Jlc2l6ZTogYm9vbGVhbiA9IHRydWU7XG4gIHByaXZhdGUgdHVybk9mUmVzaXplRm9yT25lU2V0VmFsdWU6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAvLyBWaWV3ZXIncyBwcm9wZXJ0aWVzIChsaWtlbHkgdGhleSBzaG91bGQgYmUgcHVibGljIHNvIHRoYXQgdGhleSBjYW4gYmUgc2V0IG91dHNpZGUpXG4gIHByaXZhdGUgX3Bvc2l0aW9uV2lkdGg6IG51bWJlcjtcbiAgcHVibGljIHBvc2l0aW9uV2lkdGg6IG51bWJlcjtcbiAgcHVibGljIG1pbkhlaWdodDogbnVtYmVyO1xuICBwdWJsaWMgYmFja2dyb3VuZENvbG9yOiBudW1iZXIgPSAweEZGRkZGRkZGO1xuICBwdWJsaWMgbWF4SGVpZ2h0OiBudW1iZXI7XG4gIHB1YmxpYyBza2lwRW1wdHlTZXF1ZW5jZXM6IGJvb2xlYW47XG4gIHB1YmxpYyBzZXF1ZW5jZUNvbHVtbk5hbWU6IHN0cmluZyB8IG51bGw7XG4gIHB1YmxpYyBwb3NpdGlvbk1hcmdpblN0YXRlOiBzdHJpbmc7XG4gIHB1YmxpYyBwb3NpdGlvbk1hcmdpbjogbnVtYmVyID0gMDtcbiAgcHVibGljIHN0YXJ0UG9zaXRpb25OYW1lOiBzdHJpbmcgfCBudWxsO1xuICBwdWJsaWMgZW5kUG9zaXRpb25OYW1lOiBzdHJpbmcgfCBudWxsO1xuICBwdWJsaWMgZml4V2lkdGg6IGJvb2xlYW47XG4gIHB1YmxpYyB2ZXJ0aWNhbEFsaWdubWVudDogc3RyaW5nIHwgbnVsbDtcbiAgcHVibGljIGhvcml6b250YWxBbGlnbm1lbnQ6IHN0cmluZyB8IG51bGw7XG4gIHB1YmxpYyBmaXRBcmVhOiBib29sZWFuO1xuICBwdWJsaWMgc2hyaW5rRW1wdHlUYWlsOiBib29sZWFuO1xuICBwdWJsaWMgc2tpcEVtcHR5UG9zaXRpb25zOiBib29sZWFuO1xuICBwdWJsaWMgcG9zaXRpb25IZWlnaHQ6IHN0cmluZztcblxuICBwcml2YXRlIHBvc2l0aW9uTmFtZXM6IHN0cmluZ1tdID0gW107XG5cbiAgcHJpdmF0ZSBzdGFydFBvc2l0aW9uOiBudW1iZXIgPSAtMTtcblxuICBwcml2YXRlIGVuZFBvc2l0aW9uOiBudW1iZXIgPSAtMTtcblxuICAvKiogRm9yIHN0YXJ0UG9zaXRpb24gZXF1YWxzIHRvIGVuZFBvc2l0aW9uIExlbmd0aCBpcyAxICovXG4gIHByaXZhdGUgZ2V0IExlbmd0aCgpOiBudW1iZXIge1xuICAgIGlmICh0aGlzLnNraXBFbXB0eVBvc2l0aW9ucykge1xuICAgICAgcmV0dXJuIHRoaXMucG9zaXRpb25zLmxlbmd0aDtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuc3RhcnRQb3NpdGlvbiA8PSB0aGlzLmVuZFBvc2l0aW9uID8gdGhpcy5lbmRQb3NpdGlvbiAtIHRoaXMuc3RhcnRQb3NpdGlvbiArIDEgOiAwO1xuICB9XG5cbiAgLyoqIENhbGN1bGF0ZSBuZXcgcG9zaXRpb24gZGF0YSBiYXNpYyBvbiB7QGxpbmsgcG9zaXRpb25NYXJnaW5TdGF0ZX0gYW5kIHtAbGluayBwb3NpdGlvbk1hcmdpbn0gKi9cbiAgcHJpdmF0ZSBnZXQgcG9zaXRpb25XaWR0aFdpdGhNYXJnaW4oKSB7XG4gICAgcmV0dXJuIHRoaXMuX3Bvc2l0aW9uV2lkdGggKyB0aGlzLnBvc2l0aW9uTWFyZ2luVmFsdWU7XG4gIH1cblxuICBwcml2YXRlIGdldCBwb3NpdGlvbk1hcmdpblZhbHVlKCkge1xuICAgIGlmICgodGhpcy5wb3NpdGlvbk1hcmdpblN0YXRlID09PSAnYXV0bycpICYmICh0aGlzLnVuaXRzSGFuZGxlcj8uZ2V0QWxwaGFiZXRJc011bHRpY2hhcigpID09PSB0cnVlKSkge1xuICAgICAgcmV0dXJuIHRoaXMucG9zaXRpb25NYXJnaW47XG4gICAgfVxuICAgIGlmICh0aGlzLnBvc2l0aW9uTWFyZ2luU3RhdGUgPT09ICdlbmFibGUnKSB7XG4gICAgICByZXR1cm4gdGhpcy5wb3NpdGlvbk1hcmdpbjtcbiAgICB9XG5cbiAgICByZXR1cm4gMDtcbiAgfVxuXG4gIC8qKiBDb3VudCBvZiBwb3NpdGlvbiByZW5kZXJlZCBmb3IgY2FsY3VsYXRpb25zIGNvdW50T2ZSZW5kZXJQb3NpdGlvbnMgKi9cbiAgcHJpdmF0ZSBnZXQgY291bnRPZlJlbmRlclBvc2l0aW9ucygpIHtcbiAgICBpZiAodGhpcy5ob3N0ID09IG51bGwpIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgICBjb25zdCByID0gd2luZG93LmRldmljZVBpeGVsUmF0aW87XG4gICAgaWYgKHIgPiAxKSB7XG4gICAgICByZXR1cm4gdGhpcy5jYW52YXNXaWR0aFdpdGhSYXRpbyAvIHRoaXMucG9zaXRpb25XaWR0aFdpdGhNYXJnaW47XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB0aGlzLmNhbnZhcy53aWR0aCAvICh0aGlzLnBvc2l0aW9uV2lkdGhXaXRoTWFyZ2luICogcik7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZXQgY2FudmFzV2lkdGhXaXRoUmF0aW8oKSB7XG4gICAgcmV0dXJuIHRoaXMuY2FudmFzLndpZHRoICogd2luZG93LmRldmljZVBpeGVsUmF0aW87XG4gIH1cblxuXG4gIC8qKiBQb3NpdGlvbiBvZiBzdGFydCByZW5kZXJpbmcgKi9cbiAgcHJpdmF0ZSBnZXQgZmlyc3RWaXNpYmxlSW5kZXgoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gKHRoaXMudmlzaWJsZVNsaWRlcikgPyBNYXRoLmZsb29yKHRoaXMuc2xpZGVyLm1pbikgOiAwO1xuICB9XG5cbiAgcHJpdmF0ZSB2aWV3U3ViczogU3Vic2NyaXB0aW9uW10gPSBbXTtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgdGhpcy52aWV3ZXJJZCA9IFdlYkxvZ29WaWV3ZXIudmlld2VyQ291bnQ7XG4gICAgV2ViTG9nb1ZpZXdlci52aWV3ZXJDb3VudCArPSAxO1xuXG4gICAgdGhpcy50ZXh0QmFzZWxpbmUgPSAndG9wJztcbiAgICB0aGlzLnVuaXRzSGFuZGxlciA9IG51bGw7XG5cbiAgICB0aGlzLmJhY2tncm91bmRDb2xvciA9IHRoaXMuaW50KCdiYWNrZ3JvdW5kQ29sb3InLCAweEZGRkZGRkZGKTtcbiAgICB0aGlzLl9wb3NpdGlvbldpZHRoID0gdGhpcy5wb3NpdGlvbldpZHRoID0gdGhpcy5mbG9hdCgncG9zaXRpb25XaWR0aCcsIDE2LyosXG4gICAgICB7ZWRpdG9yOiAnc2xpZGVyJywgbWluOiA0LCBtYXg6IDY0LCBwb3N0Zml4OiAncHgnfSovKTtcbiAgICB0aGlzLm1pbkhlaWdodCA9IHRoaXMuZmxvYXQoJ21pbkhlaWdodCcsIDUwLyosXG4gICAgICB7ZWRpdG9yOiAnc2xpZGVyJywgbWluOiAyNSwgbWF4OiAyNTAsIHBvc3RmaXg6ICdweCd9Ki8pO1xuICAgIHRoaXMubWF4SGVpZ2h0ID0gdGhpcy5mbG9hdCgnbWF4SGVpZ2h0JywgMTAwLyosXG4gICAgICB7ZWRpdG9yOiAnc2xpZGVyJywgbWluOiAyNSwgbWF4OiA1MDAsIHBvc3RmaXg6ICdweCd9Ki8pO1xuXG4gICAgdGhpcy5za2lwRW1wdHlTZXF1ZW5jZXMgPSB0aGlzLmJvb2woJ3NraXBFbXB0eVNlcXVlbmNlcycsIHRydWUpO1xuICAgIHRoaXMuc2VxdWVuY2VDb2x1bW5OYW1lID0gdGhpcy5zdHJpbmcoJ3NlcXVlbmNlQ29sdW1uTmFtZScsIG51bGwpO1xuXG4gICAgdGhpcy5zdGFydFBvc2l0aW9uTmFtZSA9IHRoaXMuc3RyaW5nKCdzdGFydFBvc2l0aW9uTmFtZScsIG51bGwpO1xuICAgIHRoaXMuZW5kUG9zaXRpb25OYW1lID0gdGhpcy5zdHJpbmcoJ2VuZFBvc2l0aW9uTmFtZScsIG51bGwpO1xuXG4gICAgdGhpcy5maXhXaWR0aCA9IHRoaXMuYm9vbCgnZml4V2lkdGgnLCBmYWxzZSk7XG5cbiAgICB0aGlzLnZlcnRpY2FsQWxpZ25tZW50ID0gdGhpcy5zdHJpbmcoJ3ZlcnRpY2FsQWxpZ25tZW50JywgJ21pZGRsZScsXG4gICAgICB7Y2hvaWNlczogWyd0b3AnLCAnbWlkZGxlJywgJ2JvdHRvbSddfSk7XG4gICAgdGhpcy5ob3Jpem9udGFsQWxpZ25tZW50ID0gdGhpcy5zdHJpbmcoJ2hvcml6b250YWxBbGlnbm1lbnQnLCAnY2VudGVyJyxcbiAgICAgIHtjaG9pY2VzOiBbJ2xlZnQnLCAnY2VudGVyJywgJ3JpZ2h0J119KTtcbiAgICB0aGlzLmZpdEFyZWEgPSB0aGlzLmJvb2woJ2ZpdEFyZWEnLCB0cnVlKTtcbiAgICB0aGlzLnNocmlua0VtcHR5VGFpbCA9IHRoaXMuYm9vbCgnc2hyaW5rRW1wdHlUYWlsJywgdHJ1ZSk7XG4gICAgdGhpcy5za2lwRW1wdHlQb3NpdGlvbnMgPSB0aGlzLmJvb2woJ3NraXBFbXB0eVBvc2l0aW9ucycsIGZhbHNlKTtcbiAgICB0aGlzLnBvc2l0aW9uTWFyZ2luU3RhdGUgPSB0aGlzLnN0cmluZygncG9zaXRpb25NYXJnaW5TdGF0ZScsICdhdXRvJyxcbiAgICAgIHtjaG9pY2VzOiBbJ2F1dG8nLCAnZW5hYmxlJywgJ29mZiddfSk7XG4gICAgbGV0IGRlZmF1bHRWYWx1ZUZvclBvc2l0aW9uTWFyZ2luID0gMDtcbiAgICBpZiAodGhpcy5wb3NpdGlvbk1hcmdpblN0YXRlID09PSAnYXV0bycpIHtcbiAgICAgIGRlZmF1bHRWYWx1ZUZvclBvc2l0aW9uTWFyZ2luID0gNDtcbiAgICB9XG4gICAgdGhpcy5wb3NpdGlvbk1hcmdpbiA9IHRoaXMuaW50KCdwb3NpdGlvbk1hcmdpbicsIGRlZmF1bHRWYWx1ZUZvclBvc2l0aW9uTWFyZ2luLCB7bWluOiAwLCBtYXg6IDE2fSk7XG4gICAgdGhpcy5wb3NpdGlvbkhlaWdodCA9IHRoaXMuc3RyaW5nKCdwb3NpdGlvbkhlaWdodCcsIFBvc2l0aW9uSGVpZ2h0LmZ1bGwsIHtjaG9pY2VzOiBbUG9zaXRpb25IZWlnaHQuZnVsbCwgUG9zaXRpb25IZWlnaHQuRW50cm9weV19KTtcblxuICAgIGNvbnN0IHN0eWxlOiBTbGlkZXJPcHRpb25zID0ge3N0eWxlOiAnYmFyYmVsbCd9O1xuICAgIHRoaXMuc2xpZGVyID0gdWkucmFuZ2VTbGlkZXIoMCwgMTAwLCAwLCAyMCwgZmFsc2UsIHN0eWxlKTtcbiAgICB0aGlzLmNhbnZhcyA9IHVpLmNhbnZhcygpO1xuICAgIHRoaXMuY2FudmFzLnN0eWxlLndpZHRoID0gJzEwMCUnO1xuICB9XG5cbiAgcHJpdmF0ZSBpbml0KCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmluaXRpYWxpemVkKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdXZWJMb2dvIHNlY29uZCBpbml0aWFsaXphdGlvbiEnKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmluaXRpYWxpemVkID0gdHJ1ZTtcbiAgICB0aGlzLmhlbHBVcmwgPSAnL2hlbHAvdmlzdWFsaXplL3ZpZXdlcnMvd2ViLWxvZ28ubWQnO1xuXG4gICAgdGhpcy5tc2dIb3N0ID0gdWkuZGl2KCdObyBtZXNzYWdlJyk7XG4gICAgdGhpcy5tc2dIb3N0LnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG5cbiAgICB0aGlzLmNhbnZhcyA9IHVpLmNhbnZhcygpO1xuICAgIHRoaXMuY2FudmFzLnN0eWxlLndpZHRoID0gJzEwMCUnO1xuXG4gICAgLy90aGlzLnNsaWRlci5zZXRTaG93SGFuZGxlcyhmYWxzZSk7XG4gICAgdGhpcy5zbGlkZXIucm9vdC5zdHlsZS5wb3NpdGlvbiA9ICdhYnNvbHV0ZSc7XG4gICAgdGhpcy5zbGlkZXIucm9vdC5zdHlsZS56SW5kZXggPSAnOTk5JztcbiAgICB0aGlzLnNsaWRlci5yb290LnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgdGhpcy5zbGlkZXIucm9vdC5zdHlsZS5oZWlnaHQgPSAnMC43ZW0nO1xuXG4gICAgdGhpcy52aXNpYmxlU2xpZGVyID0gZmFsc2U7XG5cbiAgICB0aGlzLnNsaWRlci5vblZhbHVlc0NoYW5nZWQuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgIGlmICgodGhpcy5ob3N0ID09IG51bGwpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIC8qIFJlc2l6ZSBzbGlkZXIgaWYgd2UgY2FuIHJlc2l6ZSBkbyB0aGF0ICovXG4gICAgICBpZiAoKHRoaXMuYWxsb3dSZXNpemUpICYmICghdGhpcy50dXJuT2ZSZXNpemVGb3JPbmVTZXRWYWx1ZSkgJiZcbiAgICAgICAgKHRoaXMudmlzaWJsZVNsaWRlcikpIHtcbiAgICAgICAgY29uc3QgY291bnRPZlBvc2l0aW9ucyA9IE1hdGguY2VpbCh0aGlzLnNsaWRlci5tYXggLSB0aGlzLnNsaWRlci5taW4pO1xuICAgICAgICBjb25zdCBjYWxjdWxhdGVkV2lkdGggPSAodGhpcy5jYW52YXMud2lkdGggLyBjb3VudE9mUG9zaXRpb25zKSAtIHRoaXMucG9zaXRpb25NYXJnaW5WYWx1ZTtcbiAgICAgICAgLy8gc2F2aW5nIHBvc2l0aW9uV2lkdGggdmFsdWUgZ2xvYmFsIChldmVuIGlmIHNsaWRlciBpcyBub3QgdmlzaWJsZSlcbiAgICAgICAgdGhpcy5wb3NpdGlvbldpZHRoID0gY2FsY3VsYXRlZFdpZHRoO1xuICAgICAgICB0aGlzLl9wb3NpdGlvbldpZHRoID0gY2FsY3VsYXRlZFdpZHRoO1xuICAgICAgfVxuICAgICAgdGhpcy50dXJuT2ZSZXNpemVGb3JPbmVTZXRWYWx1ZSA9IGZhbHNlO1xuICAgICAgdGhpcy5yZW5kZXIodHJ1ZSk7XG4gICAgfSk7XG5cblxuICAgIHRoaXMuaG9zdCA9IHVpLmRpdihbdGhpcy5tc2dIb3N0LCB0aGlzLmNhbnZhc10pO1xuXG4gICAgdGhpcy5ob3N0LnN0eWxlLmp1c3RpZnlDb250ZW50ID0gJ2NlbnRlcic7XG4gICAgdGhpcy5ob3N0LnN0eWxlLmFsaWduSXRlbXMgPSAnY2VudGVyJztcbiAgICB0aGlzLmhvc3Quc3R5bGUucG9zaXRpb24gPSAncmVsYXRpdmUnO1xuICAgIHRoaXMuaG9zdC5zdHlsZS5zZXRQcm9wZXJ0eSgnb3ZlcmZsb3cnLCAnaGlkZGVuJywgJ2ltcG9ydGFudCcpO1xuXG4gICAgY29uc3QgZ2V0TW9ub21lciA9IChwOiBERy5Qb2ludCk6IFtudW1iZXIsIHN0cmluZyB8IG51bGwsIFBvc2l0aW9uTW9ub21lckluZm8gfCBudWxsXSA9PiB7XG4gICAgICBjb25zdCBjYWxjdWxhdGVkWCA9IHAueCArIHRoaXMuZmlyc3RWaXNpYmxlSW5kZXggKiB0aGlzLnBvc2l0aW9uV2lkdGhXaXRoTWFyZ2luO1xuICAgICAgY29uc3QgalBvcyA9IE1hdGguZmxvb3IocC54IC8gdGhpcy5wb3NpdGlvbldpZHRoV2l0aE1hcmdpbiArIHRoaXMuZmlyc3RWaXNpYmxlSW5kZXgpO1xuICAgICAgY29uc3QgcG9zaXRpb24gPSB0aGlzLnBvc2l0aW9uc1tqUG9zXTtcblxuICAgICAgaWYgKHBvc2l0aW9uID09PSB2b2lkIDApXG4gICAgICAgIHJldHVybiBbalBvcywgbnVsbCwgbnVsbF07XG5cbiAgICAgIGNvbnN0IG1vbm9tZXI6IHN0cmluZyB8IHVuZGVmaW5lZCA9IE9iamVjdC5rZXlzKHBvc2l0aW9uLmZyZXEpXG4gICAgICAgIC5maW5kKChtKSA9PiBwb3NpdGlvbi5mcmVxW21dLmJvdW5kcy5jb250YWlucyhjYWxjdWxhdGVkWCwgcC55KSk7XG4gICAgICBpZiAobW9ub21lciA9PT0gdW5kZWZpbmVkKVxuICAgICAgICByZXR1cm4gW2pQb3MsIG51bGwsIG51bGxdO1xuXG4gICAgICByZXR1cm4gW2pQb3MsIG1vbm9tZXIsIHBvc2l0aW9uLmZyZXFbbW9ub21lcl1dO1xuICAgIH07XG5cbiAgICBjb25zdCBjb3JyZWN0TW9ub21lckZpbHRlciA9IChpUm93OiBudW1iZXIsIG1vbm9tZXI6IHN0cmluZywgalBvczogbnVtYmVyKSA9PiB7XG4gICAgICBjb25zdCBzZXEgPSB0aGlzLnNlcUNvbCEuZ2V0KGlSb3cpO1xuICAgICAgY29uc3Qgc2VxTSA9IHNlcSA/IHRoaXMuc3BsaXR0ZXIhKHNlcSlbdGhpcy5zdGFydFBvc2l0aW9uICsgalBvc10gOiBudWxsO1xuICAgICAgcmV0dXJuICgoc2VxTSA9PT0gbW9ub21lcikgfHwgKHNlcU0gPT09ICcnICYmIG1vbm9tZXIgPT09ICctJykpICYmIHRoaXMuZGF0YUZyYW1lLmZpbHRlci5nZXQoaVJvdyk7XG4gICAgfTtcblxuICAgIHJ4anMuZnJvbUV2ZW50PE1vdXNlRXZlbnQ+KHRoaXMuY2FudmFzLCAnbW91c2Vtb3ZlJykuc3Vic2NyaWJlKChlOiBNb3VzZUV2ZW50KSA9PiB7XG4gICAgICBjb25zdCBhcmdzID0gZSBhcyBNb3VzZUV2ZW50O1xuXG4gICAgICBjb25zdCByOiBudW1iZXIgPSB3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbztcbiAgICAgIGNvbnN0IGN1cnNvclA6IERHLlBvaW50ID0gdGhpcy5jYW52YXMuZ2V0Q3Vyc29yUG9zaXRpb24oYXJncywgcik7XG4gICAgICBjb25zdCBbalBvcywgbW9ub21lcl0gPSBnZXRNb25vbWVyKGN1cnNvclApO1xuICAgICAgaWYgKHRoaXMuZGF0YUZyYW1lICYmIHRoaXMuc2VxQ29sICYmIHRoaXMuc3BsaXR0ZXIgJiYgbW9ub21lcikge1xuICAgICAgICBjb25zdCByb3dDb3VudCA9IHd1LmNvdW50KCkudGFrZSh0aGlzLmRhdGFGcmFtZS5yb3dDb3VudCkuZmlsdGVyKGZ1bmN0aW9uKGlSb3cpIHtcbiAgICAgICAgICByZXR1cm4gY29ycmVjdE1vbm9tZXJGaWx0ZXIoaVJvdywgbW9ub21lciwgalBvcyk7XG4gICAgICAgIH0pLnJlZHVjZTxudW1iZXI+KChjb3VudCwgaVJvdykgPT4gY291bnQgKyAxLCAwKTtcbiAgICAgICAgdWkudG9vbHRpcC5zaG93KHVpLmRpdihbdWkuZGl2KGAke21vbm9tZXJ9YCksIHVpLmRpdihgJHtyb3dDb3VudH0gcm93c2ApXSksIGFyZ3MueCArIDE2LCBhcmdzLnkgKyAxNik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1aS50b29sdGlwLmhpZGUoKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHJ4anMuZnJvbUV2ZW50PE1vdXNlRXZlbnQ+KHRoaXMuY2FudmFzLCAnbW91c2Vkb3duJykuc3Vic2NyaWJlKChlOiBNb3VzZUV2ZW50KSA9PiB7XG4gICAgICBjb25zdCBhcmdzID0gZSBhcyBNb3VzZUV2ZW50O1xuICAgICAgY29uc3QgcjogbnVtYmVyID0gd2luZG93LmRldmljZVBpeGVsUmF0aW87XG4gICAgICBjb25zdCBbalBvcywgbW9ub21lcl0gPSBnZXRNb25vbWVyKHRoaXMuY2FudmFzLmdldEN1cnNvclBvc2l0aW9uKGFyZ3MsIHIpKTtcblxuICAgICAgLy8gcHJldmVudHMgZGVzZWxlY3QgYWxsIHJvd3MgaWYgd2UgbWlzcyBtb25vbWVyIGJvdW5kc1xuICAgICAgaWYgKHRoaXMuZGF0YUZyYW1lICYmIHRoaXMuc2VxQ29sICYmIHRoaXMuc3BsaXR0ZXIgJiYgbW9ub21lcikge1xuICAgICAgICB0aGlzLmRhdGFGcmFtZS5zZWxlY3Rpb24uaW5pdChmdW5jdGlvbihpUm93KSB7XG4gICAgICAgICAgcmV0dXJuIGNvcnJlY3RNb25vbWVyRmlsdGVyKGlSb3csIG1vbm9tZXIsIGpQb3MpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHJ4anMuZnJvbUV2ZW50PFdoZWVsRXZlbnQ+KHRoaXMuY2FudmFzLCAnd2hlZWwnKS5zdWJzY3JpYmUoKGU6IFdoZWVsRXZlbnQpID0+IHtcbiAgICAgIGlmICghdGhpcy52aXNpYmxlU2xpZGVyKVxuICAgICAgICByZXR1cm47XG4gICAgICBjb25zdCBjb3VudE9mU2Nyb2xsUG9zaXRpb25zID0gKGUuZGVsdGFZIC8gMTAwKSAqIE1hdGgubWF4KE1hdGguZmxvb3IoKHRoaXMuY291bnRPZlJlbmRlclBvc2l0aW9ucykgLyAyKSwgMSk7XG4gICAgICB0aGlzLnNsaWRlci5zY3JvbGxCeSh0aGlzLnNsaWRlci5taW4gKyBjb3VudE9mU2Nyb2xsUG9zaXRpb25zKTtcblxuICAgIH0pO1xuXG4gICAgdGhpcy52aWV3U3Vicy5wdXNoKHVpLm9uU2l6ZUNoYW5nZWQodGhpcy5yb290KS5zdWJzY3JpYmUodGhpcy5yb290T25TaXplQ2hhbmdlZC5iaW5kKHRoaXMpKSk7XG5cbiAgICB0aGlzLnJvb3QuYXBwZW5kKHRoaXMuaG9zdCk7XG4gICAgdGhpcy5yb290LmFwcGVuZCh0aGlzLnNsaWRlci5yb290KTtcblxuICAgIHRoaXMuX2NhbGN1bGF0ZSh3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbyk7XG4gICAgdGhpcy51cGRhdGVTbGlkZXIoKTtcbiAgICB0aGlzLnJlbmRlcih0cnVlKTtcbiAgfVxuXG4gIC8qKiBIYW5kbGVyIG9mIGNoYW5naW5nIHNpemUgV2ViTG9nbyAqL1xuICBwcml2YXRlIHJvb3RPblNpemVDaGFuZ2VkKCk6IHZvaWQge1xuICAgIHRoaXMuX2NhbGN1bGF0ZSh3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbyk7XG4gICAgdGhpcy51cGRhdGVTbGlkZXIoKTtcbiAgICB0aGlzLnJlbmRlcih0cnVlKTtcbiAgfVxuXG4gIC8qKiBBc3NpZ25zIHtAbGluayBzZXFDb2x9IGFuZCB7QGxpbmsgY3B9IGJhc2VkIG9uIHtAbGluayBzZXF1ZW5jZUNvbHVtbk5hbWV9IGFuZCBjYWxscyB7QGxpbmsgcmVuZGVyfSgpLlxuICAgKi9cbiAgcHJpdmF0ZSB1cGRhdGVTZXFDb2woKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZGF0YUZyYW1lKSB7XG4gICAgICB0aGlzLnNlcUNvbCA9IHRoaXMuc2VxdWVuY2VDb2x1bW5OYW1lID8gdGhpcy5kYXRhRnJhbWUuY29sKHRoaXMuc2VxdWVuY2VDb2x1bW5OYW1lKSA6IG51bGw7XG4gICAgICBpZiAodGhpcy5zZXFDb2wgPT0gbnVsbCkge1xuICAgICAgICB0aGlzLnNlcUNvbCA9IHBpY2tVcFNlcUNvbCh0aGlzLmRhdGFGcmFtZSk7XG4gICAgICAgIHRoaXMuc2VxdWVuY2VDb2x1bW5OYW1lID0gdGhpcy5zZXFDb2wgPyB0aGlzLnNlcUNvbC5uYW1lIDogbnVsbDtcbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLnNlcUNvbCkge1xuICAgICAgICBjb25zdCB1bml0czogc3RyaW5nID0gdGhpcy5zZXFDb2whLmdldFRhZyhERy5UQUdTLlVOSVRTKTtcbiAgICAgICAgY29uc3Qgc2VwYXJhdG9yOiBzdHJpbmcgPSB0aGlzLnNlcUNvbCEuZ2V0VGFnKFRBR1Muc2VwYXJhdG9yKTtcbiAgICAgICAgdGhpcy5zcGxpdHRlciA9IGdldFNwbGl0dGVyKHVuaXRzLCBzZXBhcmF0b3IpO1xuICAgICAgICB0aGlzLnVuaXRzSGFuZGxlciA9IG5ldyBVbml0c0hhbmRsZXIodGhpcy5zZXFDb2wpO1xuXG4gICAgICAgIHRoaXMudXBkYXRlUG9zaXRpb25zKCk7XG4gICAgICAgIHRoaXMuY3AgPSBwaWNrVXBQYWxldHRlKHRoaXMuc2VxQ29sKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuc3BsaXR0ZXIgPSBudWxsO1xuICAgICAgICB0aGlzLnBvc2l0aW9uTmFtZXMgPSBbXTtcbiAgICAgICAgdGhpcy5zdGFydFBvc2l0aW9uID0gLTE7XG4gICAgICAgIHRoaXMuZW5kUG9zaXRpb24gPSAtMTtcbiAgICAgICAgdGhpcy5jcCA9IG51bGw7XG4gICAgICB9XG4gICAgfVxuICAgIHRoaXMucmVuZGVyKCk7XG4gIH1cblxuICAvKiogVXBkYXRlcyB7QGxpbmsgcG9zaXRpb25OYW1lc30gYW5kIGNhbGN1bGF0ZXMge0BsaW5rIHN0YXJ0UG9zaXRpb259IGFuZCB7QGxpbmsgZW5kUG9zaXRpb259LlxuICAgKi9cbiAgcHJpdmF0ZSB1cGRhdGVQb3NpdGlvbnMoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLnNlcUNvbClcbiAgICAgIHJldHVybjtcblxuICAgIGxldCBjYXRlZ29yaWVzOiAoc3RyaW5nIHwgbnVsbCkgW107XG4gICAgaWYgKHRoaXMuc2hyaW5rRW1wdHlUYWlsKSB7XG4gICAgICBjb25zdCBpbmRpY2VzOiBJbnQzMkFycmF5ID0gdGhpcy5kYXRhRnJhbWUuZmlsdGVyLmdldFNlbGVjdGVkSW5kZXhlcygpO1xuICAgICAgY2F0ZWdvcmllcyA9IEFycmF5LmZyb20obmV3IFNldChcbiAgICAgICAgQXJyYXkuZnJvbShBcnJheShpbmRpY2VzLmxlbmd0aCkua2V5cygpKS5tYXAoKGk6IG51bWJlcikgPT4gdGhpcy5zZXFDb2whLmdldChpbmRpY2VzW2ldKSkpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY2F0ZWdvcmllcyA9IHRoaXMuc2VxQ29sLmNhdGVnb3JpZXM7XG4gICAgfVxuICAgIGNvbnN0IG1heExlbmd0aCA9IGNhdGVnb3JpZXMubGVuZ3RoID4gMCA/IE1hdGgubWF4KC4uLmNhdGVnb3JpZXMubWFwKFxuICAgICAgKHMpID0+IHMgIT09IG51bGwgPyB0aGlzLnNwbGl0dGVyIShzKS5sZW5ndGggOiAwKSkgOiAwO1xuXG4gICAgLy8gR2V0IHBvc2l0aW9uIG5hbWVzIGZyb20gZGF0YSBjb2x1bW4gdGFnICdwb3NpdGlvbk5hbWVzJ1xuICAgIGNvbnN0IHBvc2l0aW9uTmFtZXNUeHQgPSB0aGlzLnNlcUNvbC5nZXRUYWcoJ3Bvc2l0aW9uTmFtZXMnKTtcbiAgICAvLyBGYWxsYmFjayBpZiAncG9zaXRpb25OYW1lcycgdGFnIGlzIG5vdCBwcm92aWRlZFxuICAgIHRoaXMucG9zaXRpb25OYW1lcyA9IHBvc2l0aW9uTmFtZXNUeHQgPyBwb3NpdGlvbk5hbWVzVHh0LnNwbGl0KCcsICcpLm1hcCgobikgPT4gbi50cmltKCkpIDpcbiAgICAgIFsuLi5BcnJheShtYXhMZW5ndGgpLmtleXMoKV0ubWFwKChqUG9zKSA9PiBgJHtqUG9zICsgMX1gKTtcblxuICAgIHRoaXMuc3RhcnRQb3NpdGlvbiA9ICh0aGlzLnN0YXJ0UG9zaXRpb25OYW1lICYmIHRoaXMucG9zaXRpb25OYW1lcyAmJlxuICAgICAgdGhpcy5wb3NpdGlvbk5hbWVzLmluY2x1ZGVzKHRoaXMuc3RhcnRQb3NpdGlvbk5hbWUpKSA/XG4gICAgICB0aGlzLnBvc2l0aW9uTmFtZXMuaW5kZXhPZih0aGlzLnN0YXJ0UG9zaXRpb25OYW1lKSA6IDA7XG4gICAgdGhpcy5lbmRQb3NpdGlvbiA9ICh0aGlzLmVuZFBvc2l0aW9uTmFtZSAmJiB0aGlzLnBvc2l0aW9uTmFtZXMgJiZcbiAgICAgIHRoaXMucG9zaXRpb25OYW1lcy5pbmNsdWRlcyh0aGlzLmVuZFBvc2l0aW9uTmFtZSkpID9cbiAgICAgIHRoaXMucG9zaXRpb25OYW1lcy5pbmRleE9mKHRoaXMuZW5kUG9zaXRpb25OYW1lKSA6IChtYXhMZW5ndGggLSAxKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0IHdpZHRoQXJlYSgpIHtcbiAgICByZXR1cm4gdGhpcy5MZW5ndGggKiB0aGlzLnBvc2l0aW9uV2lkdGggLyB3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbztcbiAgfVxuXG4gIHByaXZhdGUgZ2V0IGhlaWdodEFyZWEoKSB7XG4gICAgcmV0dXJuIE1hdGgubWluKHRoaXMubWF4SGVpZ2h0LCBNYXRoLm1heCh0aGlzLm1pbkhlaWdodCwgdGhpcy5yb290LmNsaWVudEhlaWdodCkpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXQgeFNjYWxlKCkge1xuICAgIHJldHVybiAodGhpcy5yb290LmNsaWVudFdpZHRoIC0gdGhpcy5MZW5ndGggKiB0aGlzLnBvc2l0aW9uTWFyZ2luVmFsdWUpIC8gdGhpcy53aWR0aEFyZWE7XG4gIH1cblxuICBwcml2YXRlIGdldCB5U2NhbGUoKSB7XG4gICAgcmV0dXJuIHRoaXMucm9vdC5jbGllbnRIZWlnaHQgLyB0aGlzLmhlaWdodEFyZWE7XG4gIH1cblxuICBwcml2YXRlIGNoZWNrSXNIaWRlU2xpZGVyKCk6IGJvb2xlYW4ge1xuICAgIGxldCBzaG93U2xpZGVyV2l0aEZpdEFyZWEgPSB0cnVlO1xuICAgIGNvbnN0IG1pblNjYWxlID0gTWF0aC5taW4odGhpcy54U2NhbGUsIHRoaXMueVNjYWxlKTtcblxuICAgIGlmICgoKG1pblNjYWxlID09IHRoaXMueFNjYWxlKSB8fCAobWluU2NhbGUgPD0gMSkpICYmICh0aGlzLmZpdEFyZWEpKSB7XG4gICAgICBzaG93U2xpZGVyV2l0aEZpdEFyZWEgPSBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuICgodGhpcy5maXhXaWR0aCB8fCBNYXRoLmNlaWwodGhpcy5jYW52YXMud2lkdGggLyB0aGlzLnBvc2l0aW9uV2lkdGhXaXRoTWFyZ2luKSA+PSB0aGlzLkxlbmd0aCkgfHwgKHNob3dTbGlkZXJXaXRoRml0QXJlYSkpO1xuICB9XG5cbiAgc2V0U2xpZGVyVmlzaWJpbGl0eSh2aXNpYmxlOiBib29sZWFuKTogdm9pZCB7XG4gICAgaWYgKHZpc2libGUpIHtcbiAgICAgIHRoaXMuc2xpZGVyLnJvb3Quc3R5bGUuZGlzcGxheSA9ICdpbmhlcml0JztcbiAgICAgIHRoaXMudmlzaWJsZVNsaWRlciA9IHRydWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuc2xpZGVyLnJvb3Quc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgIHRoaXMudmlzaWJsZVNsaWRlciA9IGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBVcGRhdGVzIHtAbGluayBzbGlkZXJ9LCBuZWVkZWQgdG8gc2V0IHNsaWRlciBvcHRpb25zIGFuZCB0byB1cGRhdGUgc2xpZGVyIHBvc2l0aW9uLiAqL1xuICBwcml2YXRlIHVwZGF0ZVNsaWRlcigpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5jaGVja0lzSGlkZVNsaWRlcigpKSB7XG4gICAgICB0aGlzLnNldFNsaWRlclZpc2liaWxpdHkoZmFsc2UpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnNldFNsaWRlclZpc2liaWxpdHkodHJ1ZSk7XG4gICAgfVxuICAgIGlmICgodGhpcy5zbGlkZXIgIT0gbnVsbCkgJiYgKHRoaXMuY2FudmFzICE9IG51bGwpKSB7XG4gICAgICBsZXQgZGlmZkVuZFNjcm9sbEFuZFNsaWRlck1pbiA9IE1hdGguZmxvb3IodGhpcy5zbGlkZXIubWluICsgdGhpcy5jYW52YXMud2lkdGggLyB0aGlzLnBvc2l0aW9uV2lkdGhXaXRoTWFyZ2luKSAtIHRoaXMuTGVuZ3RoO1xuICAgICAgZGlmZkVuZFNjcm9sbEFuZFNsaWRlck1pbiA9IGRpZmZFbmRTY3JvbGxBbmRTbGlkZXJNaW4gPiAwID8gZGlmZkVuZFNjcm9sbEFuZFNsaWRlck1pbiA6IDA7XG4gICAgICBsZXQgbmV3TWluID0gTWF0aC5mbG9vcih0aGlzLnNsaWRlci5taW4gLSBkaWZmRW5kU2Nyb2xsQW5kU2xpZGVyTWluKTtcbiAgICAgIGxldCBuZXdNYXggPSBNYXRoLmZsb29yKHRoaXMuc2xpZGVyLm1pbiAtIGRpZmZFbmRTY3JvbGxBbmRTbGlkZXJNaW4pICsgTWF0aC5mbG9vcih0aGlzLmNhbnZhcy53aWR0aCAvIHRoaXMucG9zaXRpb25XaWR0aFdpdGhNYXJnaW4pO1xuICAgICAgaWYgKHRoaXMuY2hlY2tJc0hpZGVTbGlkZXIoKSkge1xuICAgICAgICBuZXdNaW4gPSAwO1xuICAgICAgICBuZXdNYXggPSB0aGlzLkxlbmd0aCAtIDE7XG4gICAgICB9XG4gICAgICB0aGlzLnR1cm5PZlJlc2l6ZUZvck9uZVNldFZhbHVlID0gdHJ1ZTtcbiAgICAgIHRoaXMuc2xpZGVyLnNldFZhbHVlcygwLCB0aGlzLkxlbmd0aCxcbiAgICAgICAgbmV3TWluLCBuZXdNYXgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBIYW5kbGVyIG9mIHByb3BlcnR5IGNoYW5nZSBldmVudHMuICovXG4gIHB1YmxpYyBvdmVycmlkZSBvblByb3BlcnR5Q2hhbmdlZChwcm9wZXJ0eTogREcuUHJvcGVydHkpOiB2b2lkIHtcbiAgICBzdXBlci5vblByb3BlcnR5Q2hhbmdlZChwcm9wZXJ0eSk7XG5cbiAgICBzd2l0Y2ggKHByb3BlcnR5Lm5hbWUpIHtcbiAgICBjYXNlICdzZXF1ZW5jZUNvbHVtbk5hbWUnOlxuICAgICAgdGhpcy51cGRhdGVTZXFDb2woKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ3N0YXJ0UG9zaXRpb25OYW1lJzpcbiAgICAgIHRoaXMudXBkYXRlU2VxQ29sKCk7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdlbmRQb3NpdGlvbk5hbWUnOlxuICAgICAgdGhpcy51cGRhdGVTZXFDb2woKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ3Bvc2l0aW9uV2lkdGgnOlxuICAgICAgdGhpcy5fcG9zaXRpb25XaWR0aCA9IHRoaXMucG9zaXRpb25XaWR0aDtcbiAgICAgIHRoaXMudXBkYXRlU2xpZGVyKCk7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdmaXhXaWR0aCc6XG4gICAgICB0aGlzLnVwZGF0ZVNsaWRlcigpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnZml0QXJlYSc6XG4gICAgICB0aGlzLnVwZGF0ZVNsaWRlcigpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnc2hyaW5rRW1wdHlUYWlsJzpcbiAgICAgIHRoaXMudXBkYXRlUG9zaXRpb25zKCk7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdza2lwRW1wdHlQb3NpdGlvbnMnOlxuICAgICAgdGhpcy51cGRhdGVQb3NpdGlvbnMoKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ3Bvc2l0aW9uTWFyZ2luJzpcbiAgICAgIHRoaXMudXBkYXRlU2xpZGVyKCk7XG4gICAgICBicmVhaztcbiAgICB9XG5cbiAgICB0aGlzLnJlbmRlcih0cnVlKTtcbiAgfVxuXG4gIC8qKiBBZGQgZmlsdGVyIGhhbmRsZXJzIHdoZW4gdGFibGUgaXMgYSBhdHRhY2hlZCAgKi9cbiAgcHVibGljIG92ZXJyaWRlIG9uVGFibGVBdHRhY2hlZCgpIHtcbiAgICBzdXBlci5vblRhYmxlQXR0YWNoZWQoKTtcblxuICAgIGNvbnN0IGRhdGFGcmFtZVR4dDogc3RyaW5nID0gdGhpcy5kYXRhRnJhbWUgPyAnZGF0YScgOiAnbnVsbCc7XG4gICAgY29uc29sZS5kZWJ1ZyhgYmlvOiBXZWJMb2dvPCR7dGhpcy52aWV3ZXJJZH0+Lm9uVGFibGVBdHRhY2hlZCggZGF0YUZyYW1lID0gJHtkYXRhRnJhbWVUeHR9ICkgc3RhcnRgKTtcblxuICAgIHRoaXMudXBkYXRlU2VxQ29sKCk7XG5cbiAgICBpZiAodGhpcy5kYXRhRnJhbWUgIT09IHZvaWQgMCkge1xuICAgICAgdGhpcy5zdWJzLnB1c2godGhpcy5kYXRhRnJhbWUuc2VsZWN0aW9uLm9uQ2hhbmdlZC5zdWJzY3JpYmUoKF8pID0+IHRoaXMucmVuZGVyKCkpKTtcbiAgICAgIHRoaXMuc3Vicy5wdXNoKHRoaXMuZGF0YUZyYW1lLmZpbHRlci5vbkNoYW5nZWQuc3Vic2NyaWJlKChfKSA9PiB7XG4gICAgICAgIHRoaXMudXBkYXRlUG9zaXRpb25zKCk7XG4gICAgICAgIHRoaXMucmVuZGVyKCk7XG4gICAgICB9KSk7XG4gICAgfVxuXG4gICAgdGhpcy5pbml0KCk7XG4gICAgY29uc29sZS5kZWJ1ZyhgYmlvOiBXZWJMb2dvPCR7dGhpcy52aWV3ZXJJZH0+Lm9uVGFibGVBdHRhY2hlZCgpIGVuZGApO1xuICB9XG5cbiAgLyoqIFJlbW92ZSBhbGwgaGFuZGxlcnMgd2hlbiB0YWJsZSBpcyBhIGRldGFjaCAgKi9cbiAgcHVibGljIG92ZXJyaWRlIGFzeW5jIGRldGFjaCgpIHtcbiAgICBjb25zdCBkYXRhRnJhbWVUeHQgPSBgJHt0aGlzLmRhdGFGcmFtZSA/ICdkYXRhJyA6ICdudWxsJ31gO1xuICAgIGNvbnNvbGUuZGVidWcoYGJpbzogV2ViTG9nbzwke3RoaXMudmlld2VySWR9Pi5vblRhYmxlQXR0YWNoZWQoIGRhdGFGcmFtZSA9ICR7ZGF0YUZyYW1lVHh0fSApIHN0YXJ0YCk7XG4gICAgc3VwZXIuZGV0YWNoKCk7XG5cbiAgICB0aGlzLnZpZXdTdWJzLmZvckVhY2goKHN1YikgPT4gc3ViLnVuc3Vic2NyaWJlKCkpO1xuICAgIHRoaXMuaG9zdCEucmVtb3ZlKCk7XG4gICAgdGhpcy5tc2dIb3N0ID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuaG9zdCA9IHVuZGVmaW5lZDtcblxuICAgIHRoaXMuaW5pdGlhbGl6ZWQgPSBmYWxzZTtcbiAgICBjb25zb2xlLmRlYnVnKGBiaW86IFdlYkxvZ288JHt0aGlzLnZpZXdlcklkfT4ub25UYWJsZUF0dGFjaGVkKCkgZW5kYCk7XG4gIH1cblxuICAvKiogSGVscGVyIGZ1bmN0aW9uIGZvciByZW5kZXJpbmcgKi9cbiAgcHJvdGVjdGVkIF9udWxsU2VxdWVuY2UoZmlsbGVyUmVzaWR1ZSA9ICdYJyk6IHN0cmluZyB7XG4gICAgaWYgKCF0aGlzLnNraXBFbXB0eVNlcXVlbmNlcylcbiAgICAgIHJldHVybiBuZXcgQXJyYXkodGhpcy5MZW5ndGgpLmZpbGwoZmlsbGVyUmVzaWR1ZSkuam9pbignJyk7XG5cbiAgICByZXR1cm4gJyc7XG4gIH1cblxuICAvKiogSGVscGVyIGZ1bmN0aW9uIGZvciByZW1vdmUgZW1wdHkgcG9zaXRpb25zICovXG4gIC8vIFRPRE86IHVzZSB0aGlzIGZ1bmN0aW9uIGluIGZyb20gY29yZVxuICBwcm90ZWN0ZWQgcmVtb3ZlV2hlcmUoYXJyYXk6IEFycmF5PGFueT4sIHByZWRpY2F0ZTogKFQ6IGFueSkgPT4gYm9vbGVhbik6IEFycmF5PGFueT4ge1xuICAgIGxldCBsZW5ndGggPSBhcnJheS5sZW5ndGg7XG4gICAgbGV0IHVwZGF0ZUl0ZXJhdG9yID0gMDtcbiAgICBmb3IgKGxldCBkZWxldGVJdGVyYXRvciA9IDA7IGRlbGV0ZUl0ZXJhdG9yIDwgbGVuZ3RoOyBkZWxldGVJdGVyYXRvcisrKSB7XG4gICAgICBpZiAoIXByZWRpY2F0ZShhcnJheVtkZWxldGVJdGVyYXRvcl0pKSB7XG4gICAgICAgIGFycmF5W3VwZGF0ZUl0ZXJhdG9yXSA9IGFycmF5W2RlbGV0ZUl0ZXJhdG9yXTtcbiAgICAgICAgdXBkYXRlSXRlcmF0b3IrKztcbiAgICAgIH1cbiAgICB9XG4gICAgYXJyYXkubGVuZ3RoID0gdXBkYXRlSXRlcmF0b3I7XG4gICAgcmV0dXJuIGFycmF5O1xuICB9XG5cblxuICAvKiogRnVuY3Rpb24gZm9yIHJlbW92aW5nIGVtcHR5IHBvc2l0aW9ucyAqL1xuICBwcm90ZWN0ZWQgX3JlbW92ZUVtcHR5UG9zaXRpb25zKCkge1xuICAgIGlmICh0aGlzLnNraXBFbXB0eVBvc2l0aW9ucykge1xuICAgICAgdGhpcy5yZW1vdmVXaGVyZSh0aGlzLnBvc2l0aW9ucywgaXRlbSA9PiBpdGVtPy5mcmVxWyctJ10/LmNvdW50ID09PSBpdGVtLnJvd0NvdW50KTtcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgX2NhbGN1bGF0ZShyOiBudW1iZXIpIHtcbiAgICBpZiAoIXRoaXMuaG9zdCB8fCAhdGhpcy5zZXFDb2wgfHwgIXRoaXMuZGF0YUZyYW1lKVxuICAgICAgcmV0dXJuO1xuICAgIHRoaXMudW5pdHNIYW5kbGVyID0gbmV3IFVuaXRzSGFuZGxlcih0aGlzLnNlcUNvbCk7XG5cbiAgICB0aGlzLmNhbGNTaXplKCk7XG5cbiAgICB0aGlzLnBvc2l0aW9ucyA9IG5ldyBBcnJheSh0aGlzLnN0YXJ0UG9zaXRpb24gPD0gdGhpcy5lbmRQb3NpdGlvbiA/IHRoaXMuZW5kUG9zaXRpb24gLSB0aGlzLnN0YXJ0UG9zaXRpb24gKyAxIDogMCk7XG4gICAgZm9yIChsZXQgalBvcyA9IDA7IGpQb3MgPCB0aGlzLkxlbmd0aDsgalBvcysrKSB7XG4gICAgICBjb25zdCBwb3NOYW1lOiBzdHJpbmcgPSB0aGlzLnBvc2l0aW9uTmFtZXNbdGhpcy5zdGFydFBvc2l0aW9uICsgalBvc107XG4gICAgICB0aGlzLnBvc2l0aW9uc1tqUG9zXSA9IG5ldyBQb3NpdGlvbkluZm8ocG9zTmFtZSk7XG4gICAgfVxuXG4gICAgLy8gMjAyMi0wNS0wNSBhc2thbGtpbiBpbnN0cnVjdGVkIHRvIHNob3cgV2ViTG9nbyBiYXNlZCBvbiBmaWx0ZXIgKG5vdCBzZWxlY3Rpb24pXG4gICAgY29uc3QgaW5kaWNlcyA9IHRoaXMuZGF0YUZyYW1lLmZpbHRlci5nZXRTZWxlY3RlZEluZGV4ZXMoKTtcbiAgICAvLyBjb25zdCBpbmRpY2VzID0gdGhpcy5kYXRhRnJhbWUuc2VsZWN0aW9uLnRydWVDb3VudCA+IDAgPyB0aGlzLmRhdGFGcmFtZS5zZWxlY3Rpb24uZ2V0U2VsZWN0ZWRJbmRleGVzKCkgOlxuICAgIC8vICAgdGhpcy5kYXRhRnJhbWUuZmlsdGVyLmdldFNlbGVjdGVkSW5kZXhlcygpO1xuXG4gICAgdGhpcy5yb3dzTWFza2VkID0gaW5kaWNlcy5sZW5ndGg7XG4gICAgdGhpcy5yb3dzTnVsbCA9IDA7XG5cbiAgICBmb3IgKGNvbnN0IGkgb2YgaW5kaWNlcykge1xuICAgICAgbGV0IHM6IHN0cmluZyA9IDxzdHJpbmc+KHRoaXMuc2VxQ29sLmdldChpKSk7XG5cbiAgICAgIGlmICghcykge1xuICAgICAgICBzID0gdGhpcy5fbnVsbFNlcXVlbmNlKCk7XG4gICAgICAgICsrdGhpcy5yb3dzTnVsbDtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc2VxTTogc3RyaW5nW10gPSB0aGlzLnNwbGl0dGVyIShzKTtcbiAgICAgIGZvciAobGV0IGpQb3MgPSAwOyBqUG9zIDwgdGhpcy5MZW5ndGg7IGpQb3MrKykge1xuICAgICAgICBjb25zdCBwbUluZm8gPSB0aGlzLnBvc2l0aW9uc1tqUG9zXS5mcmVxO1xuICAgICAgICBjb25zdCBtOiBzdHJpbmcgPSBzZXFNW3RoaXMuc3RhcnRQb3NpdGlvbiArIGpQb3NdIHx8ICctJztcbiAgICAgICAgaWYgKCEobSBpbiBwbUluZm8pKVxuICAgICAgICAgIHBtSW5mb1ttXSA9IG5ldyBQb3NpdGlvbk1vbm9tZXJJbmZvKCk7XG4gICAgICAgIHBtSW5mb1ttXS5jb3VudCsrO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vI3JlZ2lvbiBQb2xpc2ggZnJlcSBjb3VudHNcbiAgICBmb3IgKGxldCBqUG9zID0gMDsgalBvcyA8IHRoaXMuTGVuZ3RoOyBqUG9zKyspIHtcbiAgICAgIC8vIGRlbGV0ZSB0aGlzLnBvc2l0aW9uc1tqUG9zXS5mcmVxWyctJ107XG5cbiAgICAgIHRoaXMucG9zaXRpb25zW2pQb3NdLnJvd0NvdW50ID0gMDtcbiAgICAgIGZvciAoY29uc3QgbSBpbiB0aGlzLnBvc2l0aW9uc1tqUG9zXS5mcmVxKVxuICAgICAgICB0aGlzLnBvc2l0aW9uc1tqUG9zXS5yb3dDb3VudCArPSB0aGlzLnBvc2l0aW9uc1tqUG9zXS5mcmVxW21dLmNvdW50O1xuICAgICAgaWYgKHRoaXMucG9zaXRpb25IZWlnaHQgPT0gUG9zaXRpb25IZWlnaHQuRW50cm9weSkge1xuICAgICAgICB0aGlzLnBvc2l0aW9uc1tqUG9zXS5zdW1Gb3JIZWlnaHRDYWxjID0gMDtcbiAgICAgICAgZm9yIChjb25zdCBtIGluIHRoaXMucG9zaXRpb25zW2pQb3NdLmZyZXEpIHtcbiAgICAgICAgICBjb25zdCBwbiA9IHRoaXMucG9zaXRpb25zW2pQb3NdLmZyZXFbbV0uY291bnQgLyB0aGlzLnBvc2l0aW9uc1tqUG9zXS5yb3dDb3VudDtcbiAgICAgICAgICB0aGlzLnBvc2l0aW9uc1tqUG9zXS5zdW1Gb3JIZWlnaHRDYWxjICs9IC1wbiAqIE1hdGgubG9nMihwbik7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgLy8jZW5kcmVnaW9uXG4gICAgdGhpcy5fcmVtb3ZlRW1wdHlQb3NpdGlvbnMoKTtcblxuICAgIGNvbnN0IGFic29sdXRlTWF4SGVpZ2h0ID0gdGhpcy5jYW52YXMuaGVpZ2h0IC0gdGhpcy5heGlzSGVpZ2h0ICogcjtcblxuICAgIC8vI3JlZ2lvbiBDYWxjdWxhdGUgc2NyZWVuXG4gICAgZm9yIChsZXQgalBvcyA9IDA7IGpQb3MgPCB0aGlzLkxlbmd0aDsgalBvcysrKSB7XG4gICAgICBjb25zdCBmcmVxOiB7IFtjOiBzdHJpbmddOiBQb3NpdGlvbk1vbm9tZXJJbmZvIH0gPSB0aGlzLnBvc2l0aW9uc1tqUG9zXS5mcmVxO1xuICAgICAgY29uc3Qgcm93Q291bnQgPSB0aGlzLnBvc2l0aW9uc1tqUG9zXS5yb3dDb3VudDtcbiAgICAgIGNvbnN0IGFscGhhYmV0U2l6ZSA9IHRoaXMuZ2V0QWxwaGFiZXRTaXplKCk7XG4gICAgICBpZiAoKHRoaXMucG9zaXRpb25IZWlnaHQgPT0gUG9zaXRpb25IZWlnaHQuRW50cm9weSkgJiYgKGFscGhhYmV0U2l6ZSA9PSBudWxsKSkge1xuICAgICAgICBncm9rLnNoZWxsLmVycm9yKCdXZWJMb2dvOiBhbHBoYWJldCBpcyB1bmRlZmluZWQuJyk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG1heEhlaWdodCA9ICh0aGlzLnBvc2l0aW9uSGVpZ2h0ID09IFBvc2l0aW9uSGVpZ2h0LkVudHJvcHkpID8gKGFic29sdXRlTWF4SGVpZ2h0ICogKE1hdGgubG9nMihhbHBoYWJldFNpemUpIC0gKHRoaXMucG9zaXRpb25zW2pQb3NdLnN1bUZvckhlaWdodENhbGMpKSAvIE1hdGgubG9nMihhbHBoYWJldFNpemUpKSA6IGFic29sdXRlTWF4SGVpZ2h0O1xuXG4gICAgICBsZXQgeTogbnVtYmVyID0gdGhpcy5heGlzSGVpZ2h0ICogciArIChhYnNvbHV0ZU1heEhlaWdodCAtIG1heEhlaWdodCAtIDEpO1xuXG4gICAgICBjb25zdCBlbnRyaWVzID0gT2JqZWN0LmVudHJpZXMoZnJlcSkuc29ydCgoYSwgYikgPT4ge1xuICAgICAgICBpZiAoYVswXSAhPT0gJy0nICYmIGJbMF0gIT09ICctJylcbiAgICAgICAgICByZXR1cm4gYlsxXS5jb3VudCAtIGFbMV0uY291bnQ7XG4gICAgICAgIGVsc2UgaWYgKGFbMF0gPT09ICctJyAmJiBiWzBdID09PSAnLScpXG4gICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgIGVsc2UgaWYgKGFbMF0gPT09ICctJylcbiAgICAgICAgICByZXR1cm4gLTE7XG4gICAgICAgIGVsc2UgLyogKGJbMF0gPT09ICctJykgKi9cbiAgICAgICAgICByZXR1cm4gKzE7XG4gICAgICB9KTtcbiAgICAgIGZvciAoY29uc3QgZW50cnkgb2YgZW50cmllcykge1xuICAgICAgICBjb25zdCBwbUluZm86IFBvc2l0aW9uTW9ub21lckluZm8gPSBlbnRyeVsxXTtcbiAgICAgICAgLy8gY29uc3QgbTogc3RyaW5nID0gZW50cnlbMF07XG4gICAgICAgIGNvbnN0IGg6IG51bWJlciA9IG1heEhlaWdodCAqIHBtSW5mby5jb3VudCAvIHJvd0NvdW50O1xuXG4gICAgICAgIHBtSW5mby5ib3VuZHMgPSBuZXcgREcuUmVjdChqUG9zICogdGhpcy5wb3NpdGlvbldpZHRoV2l0aE1hcmdpbiwgeSwgdGhpcy5fcG9zaXRpb25XaWR0aCwgaCk7XG4gICAgICAgIHkgKz0gaDtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8jZW5kcmVnaW9uXG5cbiAgfVxuXG4gIC8qKiBSZW5kZXIgV2ViTG9nbyBzZW5zaXRpdmUgdG8gY2hhbmdlcyBpbiBwYXJhbXMgb2YgcmVuZGVyaW5nXG4gICAqQHBhcmFtIHtib29sZWFufSByZWNhbGMgLSBpbmRpY2F0ZXMgdGhhdCBuZWVkIHRvIHJlY2FsY3VsYXRlIGRhdGEgZm9yIHJlbmRlcmluZ1xuICAgKi9cbiAgcmVuZGVyKHJlY2FsYyA9IHRydWUpIHtcbiAgICBpZiAodGhpcy5tc2dIb3N0KSB7XG4gICAgICBpZiAodGhpcy5zZXFDb2wgJiYgIXRoaXMuY3ApIHtcbiAgICAgICAgdGhpcy5tc2dIb3N0IS5pbm5lclRleHQgPSBgVW5rbm93biBwYWxldHRlIChjb2x1bW4gc2VtVHlwZTogJyR7dGhpcy5zZXFDb2wuc2VtVHlwZX0nKS5gO1xuICAgICAgICB0aGlzLm1zZ0hvc3QhLnN0eWxlLmRpc3BsYXkgPSAnJztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMubXNnSG9zdCEuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuc2VxQ29sIHx8ICF0aGlzLmRhdGFGcmFtZSB8fCAhdGhpcy5jcCB8fCB0aGlzLnN0YXJ0UG9zaXRpb24gPT09IC0xIHx8IHRoaXMuZW5kUG9zaXRpb24gPT09IC0xIHx8IHRoaXMuaG9zdCA9PSBudWxsIHx8IHRoaXMuc2xpZGVyID09IG51bGwpXG4gICAgICByZXR1cm47XG5cbiAgICBjb25zdCBnID0gdGhpcy5jYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICBpZiAoIWcpIHJldHVybjtcblxuICAgIHRoaXMuc2xpZGVyLnJvb3Quc3R5bGUud2lkdGggPSBgJHt0aGlzLmhvc3QuY2xpZW50V2lkdGh9cHhgO1xuXG4gICAgY29uc3QgciA9IHdpbmRvdy5kZXZpY2VQaXhlbFJhdGlvO1xuXG4gICAgaWYgKHJlY2FsYylcbiAgICAgIHRoaXMuX2NhbGN1bGF0ZShyKTtcblxuICAgIGcucmVzZXRUcmFuc2Zvcm0oKTtcbiAgICBnLmZpbGxTdHlsZSA9IERHLkNvbG9yLnRvSHRtbCh0aGlzLmJhY2tncm91bmRDb2xvcik7XG4gICAgZy5maWxsUmVjdCgwLCAwLCB0aGlzLmNhbnZhcy53aWR0aCwgdGhpcy5jYW52YXMuaGVpZ2h0KTtcbiAgICBnLnRleHRCYXNlbGluZSA9IHRoaXMudGV4dEJhc2VsaW5lO1xuXG4gICAgY29uc3QgbWF4Q291bnRPZlJvd3NSZW5kZXJlZCA9IHRoaXMuY291bnRPZlJlbmRlclBvc2l0aW9ucyArIDE7XG4gICAgY29uc3QgZmlyc3RWaXNpYmxlSW5kZXggPSAodGhpcy52aXNpYmxlU2xpZGVyKSA/IE1hdGguZmxvb3IodGhpcy5zbGlkZXIubWluKSA6IDA7XG4gICAgY29uc3QgbGFzdFZpc2libGVJbmRleCA9IE1hdGgubWluKHRoaXMuTGVuZ3RoLCBmaXJzdFZpc2libGVJbmRleCArIG1heENvdW50T2ZSb3dzUmVuZGVyZWQpO1xuXG4gICAgLy8jcmVnaW9uIFBsb3QgcG9zaXRpb25OYW1lc1xuICAgIGNvbnN0IHBvc2l0aW9uRm9udFNpemUgPSAxMCAqIHI7XG4gICAgZy5yZXNldFRyYW5zZm9ybSgpO1xuICAgIGcuZmlsbFN0eWxlID0gJ2JsYWNrJztcbiAgICBnLnRleHRBbGlnbiA9ICdjZW50ZXInO1xuICAgIGcuZm9udCA9IGAke3Bvc2l0aW9uRm9udFNpemUudG9GaXhlZCgxKX1weCBSb2JvdG8sIFJvYm90byBMb2NhbCwgc2Fucy1zZXJpZmA7XG4gICAgY29uc3QgcG9zTmFtZU1heFdpZHRoID0gTWF0aC5tYXgoLi4udGhpcy5wb3NpdGlvbnMubWFwKChwb3MpID0+IGcubWVhc3VyZVRleHQocG9zLm5hbWUpLndpZHRoKSk7XG4gICAgY29uc3QgaFNjYWxlID0gcG9zTmFtZU1heFdpZHRoIDwgKHRoaXMuX3Bvc2l0aW9uV2lkdGggLSAyKSA/IDEgOiAodGhpcy5fcG9zaXRpb25XaWR0aCAtIDIpIC8gcG9zTmFtZU1heFdpZHRoO1xuXG4gICAgZm9yIChsZXQgalBvcyA9IHRoaXMuZmlyc3RWaXNpYmxlSW5kZXg7IGpQb3MgPCBsYXN0VmlzaWJsZUluZGV4OyBqUG9zKyspIHtcbiAgICAgIGNvbnN0IHBvczogUG9zaXRpb25JbmZvID0gdGhpcy5wb3NpdGlvbnNbalBvc107XG4gICAgICBnLnJlc2V0VHJhbnNmb3JtKCk7XG4gICAgICBnLnNldFRyYW5zZm9ybShcbiAgICAgICAgaFNjYWxlLCAwLCAwLCAxLFxuICAgICAgICBqUG9zICogdGhpcy5wb3NpdGlvbldpZHRoV2l0aE1hcmdpbiArIHRoaXMuX3Bvc2l0aW9uV2lkdGggLyAyIC0gdGhpcy5wb3NpdGlvbldpZHRoV2l0aE1hcmdpbiAqIGZpcnN0VmlzaWJsZUluZGV4LCAwKTtcbiAgICAgIGcuZmlsbFRleHQocG9zLm5hbWUsIDAsIDApO1xuICAgIH1cbiAgICAvLyNlbmRyZWdpb24gUGxvdCBwb3NpdGlvbk5hbWVzXG4gICAgY29uc3QgZm9udFN0eWxlID0gJzE2cHggUm9ib3RvLCBSb2JvdG8gTG9jYWwsIHNhbnMtc2VyaWYnO1xuICAgIC8vIEhhY2tzIHRvIHNjYWxlIHVwcGVyY2FzZSBjaGFyYWN0ZXJzIHRvIHRhcmdldCByZWN0YW5nbGVcbiAgICBjb25zdCB1cHBlcmNhc2VMZXR0ZXJBc2NlbnQgPSAwLjI1O1xuICAgIGNvbnN0IHVwcGVyY2FzZUxldHRlckhlaWdodCA9IDEyLjI7XG4gICAgZm9yIChsZXQgalBvcyA9IHRoaXMuZmlyc3RWaXNpYmxlSW5kZXg7IGpQb3MgPCBsYXN0VmlzaWJsZUluZGV4OyBqUG9zKyspIHtcbiAgICAgIGZvciAoY29uc3QgW21vbm9tZXIsIHBtSW5mb10gb2YgT2JqZWN0LmVudHJpZXModGhpcy5wb3NpdGlvbnNbalBvc10uZnJlcSkpIHtcbiAgICAgICAgaWYgKG1vbm9tZXIgIT09ICctJykge1xuICAgICAgICAgIGNvbnN0IG1vbm9tZXJUeHQgPSBtb25vbWVyVG9TaG9ydChtb25vbWVyLCA1KTtcbiAgICAgICAgICBjb25zdCBiID0gcG1JbmZvLmJvdW5kcztcbiAgICAgICAgICBjb25zdCBsZWZ0ID0gYi5sZWZ0IC0gdGhpcy5wb3NpdGlvbldpZHRoV2l0aE1hcmdpbiAqIHRoaXMuZmlyc3RWaXNpYmxlSW5kZXg7XG5cbiAgICAgICAgICBnLnJlc2V0VHJhbnNmb3JtKCk7XG4gICAgICAgICAgZy5zdHJva2VTdHlsZSA9ICdsaWdodGdyYXknO1xuICAgICAgICAgIGcubGluZVdpZHRoID0gMTtcbiAgICAgICAgICBnLnJlY3QobGVmdCwgYi50b3AsIGIud2lkdGgsIGIuaGVpZ2h0KTtcbiAgICAgICAgICBnLmZpbGxTdHlsZSA9IHRoaXMuY3AuZ2V0KG1vbm9tZXIpID8/IHRoaXMuY3AuZ2V0KCdvdGhlcicpO1xuICAgICAgICAgIGcudGV4dEFsaWduID0gJ2xlZnQnO1xuICAgICAgICAgIGcuZm9udCA9IGZvbnRTdHlsZTtcbiAgICAgICAgICAvL2cuZmlsbFJlY3QoYi5sZWZ0LCBiLnRvcCwgYi53aWR0aCwgYi5oZWlnaHQpO1xuICAgICAgICAgIGNvbnN0IG1UbTogVGV4dE1ldHJpY3MgPSBnLm1lYXN1cmVUZXh0KG1vbm9tZXJUeHQpO1xuXG4gICAgICAgICAgZy5zZXRUcmFuc2Zvcm0oXG4gICAgICAgICAgICBiLndpZHRoIC8gbVRtLndpZHRoLCAwLCAwLCBiLmhlaWdodCAvIHVwcGVyY2FzZUxldHRlckhlaWdodCxcbiAgICAgICAgICAgIGxlZnQsIGIudG9wKTtcbiAgICAgICAgICBnLmZpbGxUZXh0KG1vbm9tZXJUeHQsIDAsIC11cHBlcmNhc2VMZXR0ZXJBc2NlbnQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqIENhbGN1bGF0ZSBjYW52YXMgc2l6ZSBhbiBwb3NpdGlvbldpZHRoIGFuZCB1cGRhdGVzIHByb3BlcnRpZXMgKi9cbiAgcHJpdmF0ZSBjYWxjU2l6ZSgpIHtcbiAgICBpZiAoIXRoaXMuaG9zdClcbiAgICAgIHJldHVybjtcblxuICAgIGNvbnN0IHI6IG51bWJlciA9IHdpbmRvdy5kZXZpY2VQaXhlbFJhdGlvO1xuXG4gICAgbGV0IHdpZHRoOiBudW1iZXIgPSB0aGlzLndpZHRoQXJlYTtcbiAgICBsZXQgaGVpZ2h0ID0gdGhpcy5oZWlnaHRBcmVhO1xuXG4gICAgaWYgKCh0aGlzLmZpdEFyZWEpICYmICghdGhpcy52aXNpYmxlU2xpZGVyKSkge1xuICAgICAgY29uc3Qgc2NhbGUgPSBNYXRoLm1heCgxLCBNYXRoLm1pbih0aGlzLnhTY2FsZSwgdGhpcy55U2NhbGUpKTtcbiAgICAgIHdpZHRoID0gd2lkdGggKiBzY2FsZTtcbiAgICAgIGhlaWdodCA9IGhlaWdodCAqIHNjYWxlO1xuICAgICAgdGhpcy5fcG9zaXRpb25XaWR0aCA9IHRoaXMucG9zaXRpb25XaWR0aCAqIHNjYWxlO1xuICAgIH1cblxuICAgIHdpZHRoID0gdGhpcy5MZW5ndGggKiB0aGlzLnBvc2l0aW9uV2lkdGhXaXRoTWFyZ2luIC8gcjtcblxuICAgIHRoaXMuY2FudmFzLndpZHRoID0gdGhpcy5yb290LmNsaWVudFdpZHRoICogcjtcbiAgICB0aGlzLmNhbnZhcy5zdHlsZS53aWR0aCA9IGAke3RoaXMucm9vdC5jbGllbnRXaWR0aH1weGA7XG5cbiAgICAvLyBjb25zdCBjYW52YXNIZWlnaHQ6IG51bWJlciA9IHdpZHRoID4gdGhpcy5yb290LmNsaWVudFdpZHRoID8gaGVpZ2h0IC0gOCA6IGhlaWdodDtcbiAgICB0aGlzLmhvc3Quc3R5bGUuc2V0UHJvcGVydHkoJ2hlaWdodCcsIGAke2hlaWdodH1weGApO1xuICAgIGNvbnN0IGNhbnZhc0hlaWdodDogbnVtYmVyID0gdGhpcy5ob3N0LmNsaWVudEhlaWdodDtcbiAgICB0aGlzLmNhbnZhcy5oZWlnaHQgPSBjYW52YXNIZWlnaHQgKiByO1xuXG4gICAgLy8gQWRqdXN0IGhvc3QgYW5kIHJvb3Qgd2lkdGhcbiAgICBpZiAodGhpcy5maXhXaWR0aCkge1xuICAgICAgLy8gZnVsbCB3aWR0aCBmb3IgY2FudmFzIGhvc3QgYW5kIHJvb3RcbiAgICAgIHRoaXMucm9vdC5zdHlsZS53aWR0aCA9IHRoaXMuaG9zdC5zdHlsZS53aWR0aCA9IGAke3dpZHRofXB4YDtcbiAgICAgIHRoaXMucm9vdC5zdHlsZS5oZWlnaHQgPSBgJHtoZWlnaHR9cHhgO1xuICAgICAgdGhpcy5yb290LnN0eWxlLm92ZXJmbG93ID0gJ2hpZGRlbic7XG4gICAgICB0aGlzLmhvc3Quc3R5bGUuc2V0UHJvcGVydHkoJ292ZXJmbG93LXknLCAnaGlkZGVuJywgJ2ltcG9ydGFudCcpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBhbGxvdyBzY3JvbGwgY2FudmFzIGluIHJvb3RcbiAgICAgIHRoaXMucm9vdC5zdHlsZS53aWR0aCA9IHRoaXMuaG9zdC5zdHlsZS53aWR0aCA9ICcxMDAlJztcbiAgICAgIHRoaXMuaG9zdC5zdHlsZS5vdmVyZmxvd1ggPSAnYXV0byFpbXBvcnRhbnQnO1xuICAgICAgdGhpcy5ob3N0LnN0eWxlLnNldFByb3BlcnR5KCd0ZXh0LWFsaWduJywgdGhpcy5ob3Jpem9udGFsQWxpZ25tZW50KTtcblxuICAgICAgY29uc3Qgc2xpZGVySGVpZ2h0ID0gdGhpcy52aXNpYmxlU2xpZGVyID8gMTAgOiAwO1xuXG4gICAgICAvLyB2ZXJ0aWNhbCBhbGlnbm1lbnRcbiAgICAgIGxldCBob3N0VG9wTWFyZ2luID0gMDtcbiAgICAgIHN3aXRjaCAodGhpcy52ZXJ0aWNhbEFsaWdubWVudCkge1xuICAgICAgY2FzZSAndG9wJzpcbiAgICAgICAgaG9zdFRvcE1hcmdpbiA9IDA7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnbWlkZGxlJzpcbiAgICAgICAgaG9zdFRvcE1hcmdpbiA9IE1hdGgubWF4KDAsICh0aGlzLnJvb3QuY2xpZW50SGVpZ2h0IC0gaGVpZ2h0KSAvIDIpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2JvdHRvbSc6XG4gICAgICAgIGhvc3RUb3BNYXJnaW4gPSBNYXRoLm1heCgwLCB0aGlzLnJvb3QuY2xpZW50SGVpZ2h0IC0gaGVpZ2h0IC0gc2xpZGVySGVpZ2h0KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICAvLyBob3Jpem9udGFsIGFsaWdubWVudFxuICAgICAgbGV0IGhvc3RMZWZ0TWFyZ2luID0gMDtcbiAgICAgIHN3aXRjaCAodGhpcy5ob3Jpem9udGFsQWxpZ25tZW50KSB7XG4gICAgICBjYXNlICdsZWZ0JzpcbiAgICAgICAgaG9zdExlZnRNYXJnaW4gPSAwO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2NlbnRlcic6XG4gICAgICAgIGhvc3RMZWZ0TWFyZ2luID0gTWF0aC5tYXgoMCwgKHRoaXMucm9vdC5jbGllbnRXaWR0aCAtIHdpZHRoKSAvIDIpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3JpZ2h0JzpcbiAgICAgICAgaG9zdExlZnRNYXJnaW4gPSBNYXRoLm1heCgwLCB0aGlzLnJvb3QuY2xpZW50V2lkdGggLSB3aWR0aCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgdGhpcy5ob3N0LnN0eWxlLnNldFByb3BlcnR5KCdtYXJnaW4tdG9wJywgYCR7aG9zdFRvcE1hcmdpbn1weGAsICdpbXBvcnRhbnQnKTtcbiAgICAgIHRoaXMuaG9zdC5zdHlsZS5zZXRQcm9wZXJ0eSgnbWFyZ2luLWxlZnQnLCBgJHtob3N0TGVmdE1hcmdpbn1weGAsICdpbXBvcnRhbnQnKTtcbiAgICAgIGlmICh0aGlzLnNsaWRlciAhPSBudWxsKSB7XG4gICAgICAgIHRoaXMuc2xpZGVyLnJvb3Quc3R5bGUuc2V0UHJvcGVydHkoJ21hcmdpbi10b3AnLCBgJHtob3N0VG9wTWFyZ2luICsgY2FudmFzSGVpZ2h0fXB4YCwgJ2ltcG9ydGFudCcpO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5yb290LmNsaWVudEhlaWdodCA8PSBoZWlnaHQpIHtcbiAgICAgICAgdGhpcy5ob3N0LnN0eWxlLnNldFByb3BlcnR5KCdoZWlnaHQnLCBgJHt0aGlzLnJvb3QuY2xpZW50SGVpZ2h0fXB4YCk7XG4gICAgICAgIHRoaXMuaG9zdC5zdHlsZS5zZXRQcm9wZXJ0eSgnb3ZlcmZsb3cteScsIG51bGwpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5ob3N0LnN0eWxlLnNldFByb3BlcnR5KCdvdmVyZmxvdy15JywgJ2hpZGRlbicsICdpbXBvcnRhbnQnKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwdWJsaWMgZ2V0QWxwaGFiZXRTaXplKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMudW5pdHNIYW5kbGVyPy5nZXRBbHBoYWJldFNpemUoKSA/PyAwO1xuICB9XG59XG4iXX0=
|