speechrecorderng 3.10.13 → 3.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/fesm2022/speechrecorderng.mjs +204 -201
- package/fesm2022/speechrecorderng.mjs.map +1 -1
- package/lib/audio/ui/audio_canvas_layer_comp.d.ts +2 -2
- package/lib/spr.module.version.d.ts +1 -1
- package/lib/ui/canvas_layer_comp.d.ts +1 -1
- package/lib/ui/responsive_component.d.ts +1 -1
- package/package.json +13 -15
- package/esm2022/lib/action/action.mjs +0 -73
- package/esm2022/lib/audio/array_audio_buffer.mjs +0 -164
- package/esm2022/lib/audio/array_audio_buffer_input_stream.mjs +0 -86
- package/esm2022/lib/audio/array_audio_buffer_random_access_stream.mjs +0 -16
- package/esm2022/lib/audio/audio_data_holder.mjs +0 -264
- package/esm2022/lib/audio/audio_display.mjs +0 -118
- package/esm2022/lib/audio/audio_player.mjs +0 -238
- package/esm2022/lib/audio/capture/capture.mjs +0 -855
- package/esm2022/lib/audio/context.mjs +0 -79
- package/esm2022/lib/audio/dsp/level_measure.mjs +0 -517
- package/esm2022/lib/audio/format.mjs +0 -20
- package/esm2022/lib/audio/impl/wavformat.mjs +0 -7
- package/esm2022/lib/audio/impl/wavreader.mjs +0 -144
- package/esm2022/lib/audio/impl/wavwriter.mjs +0 -191
- package/esm2022/lib/audio/inddb_audio_buffer.mjs +0 -508
- package/esm2022/lib/audio/io/stream.mjs +0 -59
- package/esm2022/lib/audio/net_audio_buffer.mjs +0 -293
- package/esm2022/lib/audio/persistor.mjs +0 -81
- package/esm2022/lib/audio/playback/array_audio_buffer_source_node.mjs +0 -126
- package/esm2022/lib/audio/playback/audio_source_node.mjs +0 -18
- package/esm2022/lib/audio/playback/audio_source_worklet_module_loader.mjs +0 -167
- package/esm2022/lib/audio/playback/inddb_audio_buffer_source_node.mjs +0 -167
- package/esm2022/lib/audio/playback/net_audio_buffer_source_node.mjs +0 -218
- package/esm2022/lib/audio/playback/player.mjs +0 -402
- package/esm2022/lib/audio/ui/audio_canvas_layer_comp.mjs +0 -347
- package/esm2022/lib/audio/ui/audio_display_control.mjs +0 -150
- package/esm2022/lib/audio/ui/audio_display_scroll_pane.mjs +0 -146
- package/esm2022/lib/audio/ui/audiosignal.mjs +0 -533
- package/esm2022/lib/audio/ui/common.mjs +0 -19
- package/esm2022/lib/audio/ui/container.mjs +0 -414
- package/esm2022/lib/audio/ui/livelevel.mjs +0 -361
- package/esm2022/lib/audio/ui/scroll_pane_horizontal.mjs +0 -11
- package/esm2022/lib/audio/ui/sonagram.mjs +0 -900
- package/esm2022/lib/db/inddb.mjs +0 -120
- package/esm2022/lib/dsp/utils.mjs +0 -48
- package/esm2022/lib/environment/environment.defaults.mjs +0 -9
- package/esm2022/lib/io/BinaryReader.mjs +0 -93
- package/esm2022/lib/io/BinaryWriter.mjs +0 -80
- package/esm2022/lib/io/stream.mjs +0 -259
- package/esm2022/lib/math/2d/geometry.mjs +0 -28
- package/esm2022/lib/math/complex.mjs +0 -58
- package/esm2022/lib/math/dft.mjs +0 -196
- package/esm2022/lib/media/utils.mjs +0 -14
- package/esm2022/lib/net/uploader.mjs +0 -367
- package/esm2022/lib/recorder_component.mjs +0 -65
- package/esm2022/lib/speechrecorder/project/project.mjs +0 -54
- package/esm2022/lib/speechrecorder/project/project.service.mjs +0 -64
- package/esm2022/lib/speechrecorder/recording.mjs +0 -124
- package/esm2022/lib/speechrecorder/recordings/basic_recording.service.mjs +0 -221
- package/esm2022/lib/speechrecorder/recordings/recordings.service.mjs +0 -1014
- package/esm2022/lib/speechrecorder/script/script.mjs +0 -114
- package/esm2022/lib/speechrecorder/script/script.service.mjs +0 -47
- package/esm2022/lib/speechrecorder/session/audiorecorder.mjs +0 -1179
- package/esm2022/lib/speechrecorder/session/basicrecorder.mjs +0 -676
- package/esm2022/lib/speechrecorder/session/controlpanel.mjs +0 -416
- package/esm2022/lib/speechrecorder/session/item.mjs +0 -30
- package/esm2022/lib/speechrecorder/session/progress.mjs +0 -135
- package/esm2022/lib/speechrecorder/session/prompting.mjs +0 -639
- package/esm2022/lib/speechrecorder/session/recorder_combi_pane.mjs +0 -88
- package/esm2022/lib/speechrecorder/session/recording_file_cache.mjs +0 -195
- package/esm2022/lib/speechrecorder/session/recording_list.mjs +0 -188
- package/esm2022/lib/speechrecorder/session/recordingfile/recording-file-meta.component.mjs +0 -128
- package/esm2022/lib/speechrecorder/session/recordingfile/recording-file-navi.component.mjs +0 -114
- package/esm2022/lib/speechrecorder/session/recordingfile/recording-file-u-i.component.mjs +0 -146
- package/esm2022/lib/speechrecorder/session/recordingfile/recording-file-view.component.mjs +0 -424
- package/esm2022/lib/speechrecorder/session/recordingfile/recording-file.mjs +0 -68
- package/esm2022/lib/speechrecorder/session/recordingfile/recordingfile-service.mjs +0 -288
- package/esm2022/lib/speechrecorder/session/session.mjs +0 -2
- package/esm2022/lib/speechrecorder/session/session.service.mjs +0 -69
- package/esm2022/lib/speechrecorder/session/session_finished_dialog.mjs +0 -46
- package/esm2022/lib/speechrecorder/session/sessionmanager.mjs +0 -1385
- package/esm2022/lib/speechrecorder/session/warning_bar.mjs +0 -33
- package/esm2022/lib/speechrecorder/spruploader.mjs +0 -22
- package/esm2022/lib/speechrecorder/startstopsignal/startstopsignal.mjs +0 -2
- package/esm2022/lib/speechrecorder/startstopsignal/ui/simpletrafficlight.mjs +0 -57
- package/esm2022/lib/speechrecorderng.component.mjs +0 -392
- package/esm2022/lib/speechrecorderng.module.mjs +0 -97
- package/esm2022/lib/spr.config.mjs +0 -27
- package/esm2022/lib/spr.module.version.mjs +0 -2
- package/esm2022/lib/ui/canvas_layer_comp.mjs +0 -38
- package/esm2022/lib/ui/intersection-observer.directive.mjs +0 -32
- package/esm2022/lib/ui/message_dialog.mjs +0 -51
- package/esm2022/lib/ui/recordingitem_display.mjs +0 -253
- package/esm2022/lib/ui/responsive_component.mjs +0 -24
- package/esm2022/lib/utils/scrollIntoViewToBottom.mjs +0 -23
- package/esm2022/lib/utils/ua-parser.mjs +0 -190
- package/esm2022/lib/utils/utils.mjs +0 -132
- package/esm2022/lib/utils/wake_lock.mjs +0 -114
- package/esm2022/lib/utils/wake_lock_media.mjs +0 -2
- package/esm2022/public-api.mjs +0 -35
- package/esm2022/speechrecorderng.mjs +0 -5
|
@@ -1,900 +0,0 @@
|
|
|
1
|
-
import { DFTFloat32 } from '../../math/dft';
|
|
2
|
-
import { Point } from './common';
|
|
3
|
-
import { Component, ViewChild } from "@angular/core";
|
|
4
|
-
import { AudioCanvasLayerComponent } from "./audio_canvas_layer_comp";
|
|
5
|
-
import { WorkerHelper } from "../../utils/utils";
|
|
6
|
-
import { AudioBufferSource } from "../audio_data_holder";
|
|
7
|
-
import * as i0 from "@angular/core";
|
|
8
|
-
const DEFAULT_DFT_SIZE = 1024;
|
|
9
|
-
export class Sonagram extends AudioCanvasLayerComponent {
|
|
10
|
-
constructor(ref) {
|
|
11
|
-
super();
|
|
12
|
-
this.ref = ref;
|
|
13
|
-
this._playFramePosition = null;
|
|
14
|
-
this.raAsSubsc = null;
|
|
15
|
-
this.dftSize = DEFAULT_DFT_SIZE;
|
|
16
|
-
this.worker = null;
|
|
17
|
-
this._audioDataHolder = null;
|
|
18
|
-
this.markers = new Array();
|
|
19
|
-
this.dft = new DFTFloat32(this.dftSize);
|
|
20
|
-
this.workerURL = WorkerHelper.buildWorkerBlobURL(this.workerFunction);
|
|
21
|
-
this._bgColor = null;
|
|
22
|
-
this._selectColor = 'rgba(255,255,0,0.1)';
|
|
23
|
-
}
|
|
24
|
-
ngAfterViewInit() {
|
|
25
|
-
this.ce = this.ref.nativeElement;
|
|
26
|
-
this.sonagramCanvas = this.sonagramCanvasRef.nativeElement;
|
|
27
|
-
this.sonagramCanvas.style.zIndex = '1';
|
|
28
|
-
this.bgCanvas = this.bgCanvasRef.nativeElement;
|
|
29
|
-
this.bgCanvas.style.zIndex = '2';
|
|
30
|
-
this.cursorCanvas = this.cursorCanvasRef.nativeElement;
|
|
31
|
-
this.cursorCanvas.style.zIndex = '4';
|
|
32
|
-
this.markerCanvas = this.markerCanvasRef.nativeElement;
|
|
33
|
-
this.markerCanvas.style.zIndex = '3';
|
|
34
|
-
this.canvasLayers[0] = this.sonagramCanvas;
|
|
35
|
-
this.canvasLayers[1] = this.bgCanvas;
|
|
36
|
-
this.canvasLayers[2] = this.cursorCanvas;
|
|
37
|
-
this.canvasLayers[3] = this.markerCanvas;
|
|
38
|
-
}
|
|
39
|
-
get playFramePosition() {
|
|
40
|
-
return this._playFramePosition;
|
|
41
|
-
}
|
|
42
|
-
set playFramePosition(playFramePosition) {
|
|
43
|
-
this._playFramePosition = playFramePosition;
|
|
44
|
-
// this.redraw();
|
|
45
|
-
this.drawPlayPosition();
|
|
46
|
-
}
|
|
47
|
-
canvasMousePos(c, e) {
|
|
48
|
-
const cr = c.getBoundingClientRect();
|
|
49
|
-
const x = e.x - cr.left;
|
|
50
|
-
const y = e.y - cr.top;
|
|
51
|
-
return new Point(x, y);
|
|
52
|
-
}
|
|
53
|
-
drawStateText(stateText) {
|
|
54
|
-
if (stateText) {
|
|
55
|
-
const g = this.sonagramCanvas.getContext("2d");
|
|
56
|
-
const w = this.sonagramCanvas.width;
|
|
57
|
-
const h = this.sonagramCanvas.height;
|
|
58
|
-
if (g && w && h) {
|
|
59
|
-
g.strokeStyle = 'black';
|
|
60
|
-
g.fillStyle = 'black';
|
|
61
|
-
g.font = '20px sans-serif';
|
|
62
|
-
g.fillText(stateText, 10, 25);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
drawCursorPosition(e, show) {
|
|
67
|
-
if (this.cursorCanvas) {
|
|
68
|
-
const w = this.cursorCanvas.width;
|
|
69
|
-
const h = this.cursorCanvas.height;
|
|
70
|
-
const g = this.cursorCanvas.getContext('2d');
|
|
71
|
-
if (g) {
|
|
72
|
-
g.clearRect(0, 0, w, h);
|
|
73
|
-
if (show) {
|
|
74
|
-
//const pp = this.canvasMousePos(this.cursorCanvas, e);
|
|
75
|
-
let xViewPortPixelpos = e.offsetX;
|
|
76
|
-
g.fillStyle = 'yellow';
|
|
77
|
-
g.strokeStyle = 'yellow';
|
|
78
|
-
g.beginPath();
|
|
79
|
-
g.moveTo(xViewPortPixelpos, 0);
|
|
80
|
-
g.lineTo(xViewPortPixelpos, h);
|
|
81
|
-
g.closePath();
|
|
82
|
-
g.stroke();
|
|
83
|
-
if (this._audioDataHolder) {
|
|
84
|
-
let framePosRound = this.viewPortXPixelToFramePosition(xViewPortPixelpos);
|
|
85
|
-
if (framePosRound != null) {
|
|
86
|
-
g.font = '14px sans-serif';
|
|
87
|
-
g.fillStyle = 'yellow';
|
|
88
|
-
g.fillText(framePosRound.toString(), xViewPortPixelpos + 2, 50);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
drawPlayPosition() {
|
|
96
|
-
if (this.markerCanvas) {
|
|
97
|
-
const w = this.markerCanvas.width;
|
|
98
|
-
const h = this.markerCanvas.height;
|
|
99
|
-
const g = this.markerCanvas.getContext("2d");
|
|
100
|
-
if (g) {
|
|
101
|
-
g.clearRect(0, 0, w, h);
|
|
102
|
-
if (this._playFramePosition != null) {
|
|
103
|
-
let pixelPos = this.frameToViewPortXPixelPosition(this._playFramePosition);
|
|
104
|
-
if (pixelPos) {
|
|
105
|
-
g.fillStyle = 'red';
|
|
106
|
-
g.strokeStyle = 'red';
|
|
107
|
-
g.beginPath();
|
|
108
|
-
g.moveTo(pixelPos, 0);
|
|
109
|
-
g.lineTo(pixelPos, h);
|
|
110
|
-
g.closePath();
|
|
111
|
-
g.stroke();
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
/*
|
|
118
|
-
* Method used as worker code.
|
|
119
|
-
*/
|
|
120
|
-
workerFunction() {
|
|
121
|
-
// Redefine some DSP classes for worker function
|
|
122
|
-
// See e.g. audio.math.Complex
|
|
123
|
-
class Complex {
|
|
124
|
-
static fromPolarForm(magnitude, argument) {
|
|
125
|
-
const r = Math.cos(argument) * magnitude;
|
|
126
|
-
const i = Math.sin(argument) * magnitude;
|
|
127
|
-
return new Complex(r, i);
|
|
128
|
-
}
|
|
129
|
-
constructor(real, img) {
|
|
130
|
-
this.real = real;
|
|
131
|
-
this.img = img;
|
|
132
|
-
}
|
|
133
|
-
magnitude() {
|
|
134
|
-
return Math.sqrt((this.real * this.real) + (this.img * this.img));
|
|
135
|
-
}
|
|
136
|
-
argument() {
|
|
137
|
-
return Math.atan2(this.img, this.real);
|
|
138
|
-
}
|
|
139
|
-
add(addC) {
|
|
140
|
-
return new Complex(this.real + addC.real, this.img + addC.img);
|
|
141
|
-
}
|
|
142
|
-
sub(subC) {
|
|
143
|
-
return new Complex(this.real - subC.real, this.img - subC.img);
|
|
144
|
-
}
|
|
145
|
-
mult(multC) {
|
|
146
|
-
const multR = (this.real * multC.real) - (this.img * multC.img);
|
|
147
|
-
const multI = (this.real * multC.img) + (multC.real * this.img);
|
|
148
|
-
return new Complex(multR, multI);
|
|
149
|
-
}
|
|
150
|
-
multReal(multF) {
|
|
151
|
-
return new Complex(this.real * multF, this.img * multF);
|
|
152
|
-
}
|
|
153
|
-
div(divisor) {
|
|
154
|
-
const divReal = divisor.real;
|
|
155
|
-
const divImg = divisor.img;
|
|
156
|
-
const div = (divReal * divReal) + (divImg * divImg);
|
|
157
|
-
const divisionReal = ((this.real * divReal) + (this.img * divImg)) / div;
|
|
158
|
-
const divisionImg = ((divReal * this.img) - (this.real * divImg)) / div;
|
|
159
|
-
return new Complex(divisionReal, divisionImg);
|
|
160
|
-
}
|
|
161
|
-
divReal(divisor) {
|
|
162
|
-
const div = divisor * divisor;
|
|
163
|
-
const divsionReal = (this.real * divisor) / div;
|
|
164
|
-
const divsionImg = (divisor * this.img) / div;
|
|
165
|
-
return new Complex(divsionReal, divsionImg);
|
|
166
|
-
}
|
|
167
|
-
conjugate() {
|
|
168
|
-
return new Complex(this.real, -this.img);
|
|
169
|
-
}
|
|
170
|
-
equals(c) {
|
|
171
|
-
if (c === null) {
|
|
172
|
-
return false;
|
|
173
|
-
}
|
|
174
|
-
return (this.real === c.real && this.img === c.img);
|
|
175
|
-
}
|
|
176
|
-
toString() {
|
|
177
|
-
return 'Real: ' + this.real + ', Img: ' + this.img;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
class DFTFloat32 {
|
|
181
|
-
constructor(n) {
|
|
182
|
-
this.n = n;
|
|
183
|
-
this.m = Math.log(n) / Math.log(2);
|
|
184
|
-
// if(n != (1 << m))throw new RuntimeException("length N must be power of 2");
|
|
185
|
-
// lookup tables
|
|
186
|
-
this.cosLookup = new Float32Array(n / 2);
|
|
187
|
-
this.sinLookup = new Float32Array(n / 2);
|
|
188
|
-
for (let i = 0; i < n / 2; i++) {
|
|
189
|
-
const arc = (-2 * Math.PI * i) / n;
|
|
190
|
-
this.cosLookup[i] = Math.cos(arc);
|
|
191
|
-
this.sinLookup[i] = Math.sin(arc);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
processReal(srcBuf) {
|
|
195
|
-
const x = srcBuf.slice();
|
|
196
|
-
const y = new Float32Array(srcBuf.length);
|
|
197
|
-
for (let yi = 0; yi < y.length; yi++) {
|
|
198
|
-
y[yi] = 0.0;
|
|
199
|
-
}
|
|
200
|
-
this.fftCooleyTukey(x, y);
|
|
201
|
-
const rc = new Array(x.length);
|
|
202
|
-
for (let i = 0; i < x.length; i++) {
|
|
203
|
-
rc[i] = new Complex(x[i], y[i]);
|
|
204
|
-
}
|
|
205
|
-
return rc;
|
|
206
|
-
}
|
|
207
|
-
processRealMagnitude(srcBuf) {
|
|
208
|
-
const x = srcBuf.slice();
|
|
209
|
-
const y = new Float32Array(srcBuf.length);
|
|
210
|
-
for (let yi = 0; yi < y.length; yi++) {
|
|
211
|
-
y[yi] = 0.0;
|
|
212
|
-
}
|
|
213
|
-
this.fftCooleyTukey(x, y);
|
|
214
|
-
const rc = new Float32Array(x.length);
|
|
215
|
-
for (let i = 0; i < x.length; i++) {
|
|
216
|
-
const rcc = new Complex(x[i], y[i]);
|
|
217
|
-
rc[i] = rcc.magnitude();
|
|
218
|
-
}
|
|
219
|
-
return rc;
|
|
220
|
-
}
|
|
221
|
-
fftCooleyTukey(real, img) {
|
|
222
|
-
let i;
|
|
223
|
-
let j = 0;
|
|
224
|
-
let k;
|
|
225
|
-
let n1;
|
|
226
|
-
let n2 = this.n / 2;
|
|
227
|
-
let a;
|
|
228
|
-
let c;
|
|
229
|
-
let s;
|
|
230
|
-
let t1;
|
|
231
|
-
let t2;
|
|
232
|
-
for (i = 1; i < this.n - 1; i++) {
|
|
233
|
-
n1 = n2;
|
|
234
|
-
while (j >= n1) {
|
|
235
|
-
j = j - n1;
|
|
236
|
-
n1 = n1 / 2;
|
|
237
|
-
}
|
|
238
|
-
j = j + n1;
|
|
239
|
-
if (i < j) {
|
|
240
|
-
t1 = real[i];
|
|
241
|
-
real[i] = real[j];
|
|
242
|
-
real[j] = t1;
|
|
243
|
-
t1 = img[i];
|
|
244
|
-
img[i] = img[j];
|
|
245
|
-
img[j] = t1;
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
n1 = 0;
|
|
249
|
-
n2 = 1;
|
|
250
|
-
for (i = 0; i < this.m; i++) {
|
|
251
|
-
n1 = n2;
|
|
252
|
-
n2 = n2 + n2;
|
|
253
|
-
a = 0;
|
|
254
|
-
for (j = 0; j < n1; j++) {
|
|
255
|
-
c = this.cosLookup[a];
|
|
256
|
-
s = this.sinLookup[a];
|
|
257
|
-
a += (1 << (this.m - i - 1));
|
|
258
|
-
for (k = j; k < this.n; k = k + n2) {
|
|
259
|
-
t1 = c * real[k + n1] - s * img[k + n1];
|
|
260
|
-
t2 = s * real[k + n1] + c * img[k + n1];
|
|
261
|
-
real[k + n1] = real[k] - t1;
|
|
262
|
-
img[k + n1] = img[k] - t2;
|
|
263
|
-
real[k] = real[k] + t1;
|
|
264
|
-
img[k] = img[k] + t2;
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
process(t) {
|
|
270
|
-
const reals = new Float32Array(this.n);
|
|
271
|
-
const imgs = new Float32Array(this.n);
|
|
272
|
-
const trans = new Array(this.n);
|
|
273
|
-
for (let i = 0; i < this.n; i++) {
|
|
274
|
-
reals[i] = t[i].real;
|
|
275
|
-
imgs[i] = t[i].img;
|
|
276
|
-
}
|
|
277
|
-
this.fftCooleyTukey(reals, imgs);
|
|
278
|
-
for (let i = 0; i < this.n; i++) {
|
|
279
|
-
trans[i] = new Complex(reals[i], imgs[i]);
|
|
280
|
-
}
|
|
281
|
-
return trans;
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
class GaussianWindow {
|
|
285
|
-
static { this.DEFAULT_SIGMA = 0.3; }
|
|
286
|
-
constructor(size, sigma = GaussianWindow.DEFAULT_SIGMA) {
|
|
287
|
-
this.buf = new Float32Array(size);
|
|
288
|
-
const center = (size - 1) / 2;
|
|
289
|
-
for (let i = 0; i < size; i++) {
|
|
290
|
-
const quot = (i - center) / (sigma * center);
|
|
291
|
-
const exp = -0.5 * quot * quot;
|
|
292
|
-
this.buf[i] = Math.exp(exp);
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
getScale(i) {
|
|
296
|
-
return this.buf[i];
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
self.onmessage = function (msg) {
|
|
300
|
-
//console.debug("Sonagram render thread");
|
|
301
|
-
let l = msg.data.l;
|
|
302
|
-
let w = msg.data.w;
|
|
303
|
-
let h = msg.data.h;
|
|
304
|
-
let vw = msg.data.vw;
|
|
305
|
-
let chs = msg.data.chs;
|
|
306
|
-
let audioDataOffset = 0;
|
|
307
|
-
let adOffset = msg.data.audioDataOffset;
|
|
308
|
-
if (adOffset) {
|
|
309
|
-
audioDataOffset = adOffset;
|
|
310
|
-
}
|
|
311
|
-
let maxPsd = null;
|
|
312
|
-
if (msg.data.maxPsd !== undefined) {
|
|
313
|
-
maxPsd = msg.data.maxPsd;
|
|
314
|
-
}
|
|
315
|
-
let audioData = new Array(chs);
|
|
316
|
-
for (let ch = 0; ch < chs; ch++) {
|
|
317
|
-
audioData[ch] = new Float32Array(msg.data['audioData'][ch]);
|
|
318
|
-
}
|
|
319
|
-
let frameLength = msg.data.frameLength;
|
|
320
|
-
let dftSize = msg.data.dftSize;
|
|
321
|
-
let dftBands = dftSize / 2;
|
|
322
|
-
let dft = new DFTFloat32(dftSize);
|
|
323
|
-
let wf = new GaussianWindow(dftSize);
|
|
324
|
-
let arrSize = w * h * 4;
|
|
325
|
-
if (arrSize < 0) {
|
|
326
|
-
arrSize = 0;
|
|
327
|
-
}
|
|
328
|
-
let imgData = new Uint8ClampedArray(arrSize);
|
|
329
|
-
//console.log("Render method:");
|
|
330
|
-
//console.debug("Created imgData arrSize: "+arrSize+" ", w, "x", h);
|
|
331
|
-
let calcMaxPsd = -Infinity;
|
|
332
|
-
if (arrSize > 0) {
|
|
333
|
-
let chH = Math.round(h / chs);
|
|
334
|
-
let framesPerPixel = frameLength / vw;
|
|
335
|
-
//console.debug("Render: ", w, "x", h);
|
|
336
|
-
let b = new Float32Array(dftSize);
|
|
337
|
-
let sona = new Array(chs);
|
|
338
|
-
for (let ch = 0; ch < chs; ch++) {
|
|
339
|
-
let chDataLen = audioData[ch].length;
|
|
340
|
-
// initialize DFT array buffer
|
|
341
|
-
sona[ch] = new Array(w);
|
|
342
|
-
let framePos = 0;
|
|
343
|
-
for (let pii = 0; pii < w; pii++) {
|
|
344
|
-
let virtPii = l + pii;
|
|
345
|
-
// Position of sample data frame is pixel position mapped to audio frame position.
|
|
346
|
-
// Then "center" the frame by shifting left by half the DFT size (=dftBands)
|
|
347
|
-
framePos = Math.round((virtPii * framesPerPixel) - dftBands);
|
|
348
|
-
// fill DFT buffer with windowed sample values
|
|
349
|
-
for (let i = 0; i < dftSize; i++) {
|
|
350
|
-
let samplePos = framePos + i;
|
|
351
|
-
// initialize for negative sample positions and out of bounds positions
|
|
352
|
-
let chDat = 0;
|
|
353
|
-
// Set audio sample if available
|
|
354
|
-
let adp = samplePos - audioDataOffset;
|
|
355
|
-
if (adp >= 0 && adp < chDataLen) {
|
|
356
|
-
chDat = audioData[ch][adp];
|
|
357
|
-
//console.debug("Audio data: "+chDat);
|
|
358
|
-
}
|
|
359
|
-
else {
|
|
360
|
-
//console.debug("Sample buf pos oob: adp: "+adp+", chDataLen: "+chDataLen+", samplePos: "+samplePos+", i: "+i);
|
|
361
|
-
}
|
|
362
|
-
// apply Window
|
|
363
|
-
b[i] = chDat * wf.getScale(i);
|
|
364
|
-
}
|
|
365
|
-
// Calc DFT magnitudes
|
|
366
|
-
let spectr = dft.processRealMagnitude(b);
|
|
367
|
-
// Get maximum value of spectral energy
|
|
368
|
-
for (let s = 0; s < dftBands; s++) {
|
|
369
|
-
let psd = (2 * Math.pow(spectr[s], 2)) / dftBands;
|
|
370
|
-
if (psd > calcMaxPsd) {
|
|
371
|
-
calcMaxPsd = psd;
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
// Set render model data for this pixel
|
|
375
|
-
sona[ch][pii] = spectr;
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
if (!msg.data.norender) {
|
|
379
|
-
if (!maxPsd) {
|
|
380
|
-
maxPsd = calcMaxPsd;
|
|
381
|
-
}
|
|
382
|
-
for (let ch = 0; ch < chs; ch++) {
|
|
383
|
-
for (let pii = 0; pii < w; pii++) {
|
|
384
|
-
let allBlack = true;
|
|
385
|
-
for (let y = 0; y < chH; y++) {
|
|
386
|
-
let freqIdx = Math.round(y * dftBands / chH);
|
|
387
|
-
// calculate the one-sided power spectral density PSD (f, t) in Pa2/Hz
|
|
388
|
-
// PSD(f) proportional to 2|X(f)|2 / (t2 - t1)
|
|
389
|
-
let val = sona[ch][pii][freqIdx];
|
|
390
|
-
let psd = (2 * Math.pow(val, 2)) / dftBands;
|
|
391
|
-
// Calculate logarithmic value
|
|
392
|
-
//let psdLog = ips.dsp.DSPUtils.toLevelInDB(psd / maxPsd);
|
|
393
|
-
let linearLevel = psd / maxPsd;
|
|
394
|
-
let psdLog = 10 * Math.log(linearLevel) / Math.log(10);
|
|
395
|
-
// Fixed dynamic Range value of 70dB for now
|
|
396
|
-
let dynRangeInDb = 70;
|
|
397
|
-
let scaledVal = (psdLog + dynRangeInDb) / dynRangeInDb;
|
|
398
|
-
// are the following checks necessary for clamped array ?
|
|
399
|
-
if (scaledVal > 1.0)
|
|
400
|
-
scaledVal = 1;
|
|
401
|
-
if (scaledVal < 0.0) {
|
|
402
|
-
scaledVal = 0;
|
|
403
|
-
}
|
|
404
|
-
let rgbVal = Math.round(255 * scaledVal);
|
|
405
|
-
if (rgbVal < 0) {
|
|
406
|
-
// System.out.println("Neg RGB val: "+rgbVal);
|
|
407
|
-
rgbVal = 0;
|
|
408
|
-
}
|
|
409
|
-
if (rgbVal > 255) {
|
|
410
|
-
rgbVal = 255;
|
|
411
|
-
}
|
|
412
|
-
rgbVal = 255 - rgbVal;
|
|
413
|
-
if (rgbVal > 0) {
|
|
414
|
-
allBlack = false;
|
|
415
|
-
}
|
|
416
|
-
let py = chH - y;
|
|
417
|
-
let dataPos = ((((ch * chH) + py) * w) + pii) * 4;
|
|
418
|
-
imgData[dataPos + 0] = rgbVal; //R
|
|
419
|
-
imgData[dataPos + 1] = rgbVal; //G
|
|
420
|
-
imgData[dataPos + 2] = rgbVal; //B
|
|
421
|
-
imgData[dataPos + 3] = 255; //A (alpha: fully opaque)
|
|
422
|
-
//console.debug("Rendered: py: "+py+", rgbval: "+rgbVal);
|
|
423
|
-
// example 1x1, 2chs
|
|
424
|
-
// ch0x0y0R,ch0x0y0G,ch0x0y0B,ch0x0y0A,
|
|
425
|
-
// ch0x1y0R,ch0x1y0G,ch0x1y0B,ch0x1y0A,
|
|
426
|
-
// ch0x0y0R,ch0x0y0G,ch0x0y0B,ch0x0y0A,
|
|
427
|
-
// ch0x1y1R,ch0x1y1G,ch0x1y1B,ch0x1y1A,
|
|
428
|
-
// ch1x0y0R,ch1x0y0G,ch1x0y0B,ch1x0y0A,
|
|
429
|
-
// ch1x1y0R,ch1x1y0G,ch1x1y0B,ch1x1y0A,
|
|
430
|
-
// ch1x0y0R,ch1x0y0G,ch1x0y0B,ch1x0y0A,
|
|
431
|
-
// ch1x1y1R,ch1x1y1G,ch1x1y1B,ch1x1y1A
|
|
432
|
-
}
|
|
433
|
-
// if (allBlack) {
|
|
434
|
-
// console.log("Black: ", pii, " ", ch);
|
|
435
|
-
// }
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
//console.debug("Render thread post message imgData: "+imgData.length)
|
|
441
|
-
postMessage({ imgData: imgData, l: l, w: msg.data.w, h: msg.data.h, vw: vw, maxPsd: calcMaxPsd, terminate: msg.data.terminate }, [imgData.buffer]);
|
|
442
|
-
};
|
|
443
|
-
}
|
|
444
|
-
startDraw(clear = true) {
|
|
445
|
-
if (clear) {
|
|
446
|
-
if (this.bounds) {
|
|
447
|
-
this.sonagramCanvas.style.left = Math.round(this.bounds.position.left).toString() + 'px';
|
|
448
|
-
let intW = Math.round(this.bounds.dimension.width);
|
|
449
|
-
let intH = Math.round(this.bounds.dimension.height);
|
|
450
|
-
this.sonagramCanvas.width = intW;
|
|
451
|
-
this.sonagramCanvas.height = intH;
|
|
452
|
-
let g = this.sonagramCanvas.getContext("2d");
|
|
453
|
-
if (g) {
|
|
454
|
-
//g.clearRect(0, 0,w, h);
|
|
455
|
-
g.fillStyle = "white";
|
|
456
|
-
g.fillRect(0, 0, intW, intH);
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
this.startRender();
|
|
461
|
-
this.drawCursorLayer();
|
|
462
|
-
}
|
|
463
|
-
startRender() {
|
|
464
|
-
//console.debug("Sonagram start render...");
|
|
465
|
-
if (this.worker) {
|
|
466
|
-
this.worker.terminate();
|
|
467
|
-
this.worker = null;
|
|
468
|
-
}
|
|
469
|
-
if (this.raAsSubsc) {
|
|
470
|
-
this.raAsSubsc.unsubscribe();
|
|
471
|
-
}
|
|
472
|
-
if (this._audioDataHolder) {
|
|
473
|
-
this._audioDataHolder.addOnReadyListener(() => {
|
|
474
|
-
if (this._audioDataHolder && this.bounds && this.bounds.dimension) {
|
|
475
|
-
let w = Math.round(this.bounds.dimension.width);
|
|
476
|
-
let h = Math.round(this.bounds.dimension.height);
|
|
477
|
-
let vw = Math.round(this.virtualDimension.width);
|
|
478
|
-
if (w > 0 && h > 0 && vw > 0) {
|
|
479
|
-
this.worker = new Worker(this.workerURL);
|
|
480
|
-
//this.wo = new Worker('./worker/sonagram.worker', { type: `module` });
|
|
481
|
-
let chs = this._audioDataHolder.numberOfChannels;
|
|
482
|
-
let vw = Math.round(this.virtualDimension.width);
|
|
483
|
-
let frameLength = this._audioDataHolder.frameLen;
|
|
484
|
-
let framesPerPixel = Math.ceil(frameLength / vw);
|
|
485
|
-
let leftPos = Math.round(this.bounds.position.left);
|
|
486
|
-
let renderPos = leftPos;
|
|
487
|
-
let raAs = this._audioDataHolder.randomAccessAudioStream();
|
|
488
|
-
let audioBuffer = null;
|
|
489
|
-
let audioSource = this._audioDataHolder.audioSource;
|
|
490
|
-
if (audioSource instanceof AudioBufferSource) {
|
|
491
|
-
audioBuffer = audioSource.audioBuffer;
|
|
492
|
-
}
|
|
493
|
-
//let arrayAudioBuffer=this._audioDataHolder.arrayBuffer;
|
|
494
|
-
let arrAbBuf;
|
|
495
|
-
let ada = new Array(chs);
|
|
496
|
-
// for(let ch=0;ch<chs;ch++) {
|
|
497
|
-
// ada[ch] = new Float32Array(this.dftSize);
|
|
498
|
-
// }
|
|
499
|
-
let imgData;
|
|
500
|
-
let maxPsd = -Infinity;
|
|
501
|
-
let norender = true;
|
|
502
|
-
if (this.worker) {
|
|
503
|
-
this.worker.onmessage = (me) => {
|
|
504
|
-
if (true === me.data.terminate) {
|
|
505
|
-
let drawImgData;
|
|
506
|
-
if (imgData) {
|
|
507
|
-
drawImgData = imgData;
|
|
508
|
-
}
|
|
509
|
-
else {
|
|
510
|
-
drawImgData = me.data.imgData;
|
|
511
|
-
}
|
|
512
|
-
this.drawRendered(w, h, drawImgData);
|
|
513
|
-
if (this.worker) {
|
|
514
|
-
this.worker.terminate();
|
|
515
|
-
}
|
|
516
|
-
this.worker = null;
|
|
517
|
-
raAs.close();
|
|
518
|
-
}
|
|
519
|
-
else {
|
|
520
|
-
// set rendered vertical values of one pixel of timescale
|
|
521
|
-
//let dataPos = renderPos * h * 4;
|
|
522
|
-
if (norender) {
|
|
523
|
-
if (me.data.maxPsd > maxPsd) {
|
|
524
|
-
maxPsd = me.data.maxPsd;
|
|
525
|
-
//console.debug("new maxPsd: "+maxPsd);
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
else {
|
|
529
|
-
let chH = Math.round(h / chs);
|
|
530
|
-
let idp = me.data.l - leftPos;
|
|
531
|
-
for (let ch = 0; ch < chs; ch++) {
|
|
532
|
-
for (let y = 0; y < chH; y++) {
|
|
533
|
-
let py = chH - y;
|
|
534
|
-
let dataPos = ((((ch * chH) + py) * w) + idp) * 4;
|
|
535
|
-
let mePos = ((ch * chH) + py) * 4;
|
|
536
|
-
//let lastPos = dataPos + me.data.imgData.length;
|
|
537
|
-
//if (lastPos < imgData.length) {
|
|
538
|
-
// set one pixel
|
|
539
|
-
imgData[dataPos] = me.data.imgData[mePos];
|
|
540
|
-
imgData[dataPos + 1] = me.data.imgData[mePos + 1];
|
|
541
|
-
imgData[dataPos + 2] = me.data.imgData[mePos + 2];
|
|
542
|
-
imgData[dataPos + 3] = me.data.imgData[mePos + 3];
|
|
543
|
-
//} else {
|
|
544
|
-
//console.error("Out of range: " + dataPos + "+" + me.data.imgData.length + ">=" + imgData.length);
|
|
545
|
-
// }
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
if (this._audioDataHolder && arrAbBuf && this.worker) {
|
|
550
|
-
// proceed with next pixel
|
|
551
|
-
renderPos++;
|
|
552
|
-
//console.debug("Render pos: "+renderPos);
|
|
553
|
-
let terminate = false;
|
|
554
|
-
let windowEnd = renderPos >= leftPos + w;
|
|
555
|
-
if (windowEnd) {
|
|
556
|
-
if (norender) {
|
|
557
|
-
// phase two: rendering
|
|
558
|
-
norender = false;
|
|
559
|
-
// start from beginning
|
|
560
|
-
renderPos = leftPos;
|
|
561
|
-
//console.debug("now rendering: maxPsd: "+maxPsd);
|
|
562
|
-
}
|
|
563
|
-
else {
|
|
564
|
-
// terminate render phase
|
|
565
|
-
terminate = true;
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
let leftFramePos = Math.floor(frameLength * renderPos / vw) - this.dftSize / 2;
|
|
569
|
-
if (leftFramePos < 0) {
|
|
570
|
-
leftFramePos = 0;
|
|
571
|
-
}
|
|
572
|
-
//let ada = new Array<ArrayBuffer>(chs);
|
|
573
|
-
//console.debug("Render pos: "+renderPos+" leftFramePos: "+leftFramePos);
|
|
574
|
-
if (!terminate) {
|
|
575
|
-
if (this._audioDataHolder) {
|
|
576
|
-
//let read = this._audioDataHolder.frames(leftFramePos, this.dftSize, arrAbBuf);
|
|
577
|
-
this.raAsSubsc = raAs.framesObs(leftFramePos, this.dftSize, arrAbBuf).subscribe({
|
|
578
|
-
next: (read) => {
|
|
579
|
-
if (arrAbBuf && this.worker) {
|
|
580
|
-
if (read < this.dftSize) {
|
|
581
|
-
// zero padding
|
|
582
|
-
for (let ch = 0; ch < chs; ch++) {
|
|
583
|
-
for (let zp = read; zp < this.dftSize; zp++) {
|
|
584
|
-
arrAbBuf[ch][zp] = 0;
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
for (let ch = 0; ch < chs; ch++) {
|
|
589
|
-
// Need a copy here for the worker, otherwise this.audioData is not accessible after posting to the worker
|
|
590
|
-
//ada[ch] = arrAbBuf[ch].buffer.slice(0);
|
|
591
|
-
const arrAbBufCh = arrAbBuf[ch];
|
|
592
|
-
const adLen = arrAbBufCh.buffer.byteLength;
|
|
593
|
-
if (!ada[ch] || ada[ch].byteLength !== adLen) {
|
|
594
|
-
ada[ch] = new ArrayBuffer(adLen);
|
|
595
|
-
}
|
|
596
|
-
let fAdaCh = new Float32Array(ada[ch]);
|
|
597
|
-
fAdaCh.set(arrAbBuf[ch]);
|
|
598
|
-
}
|
|
599
|
-
this.worker.postMessage({
|
|
600
|
-
audioData: ada,
|
|
601
|
-
audioDataOffset: leftFramePos,
|
|
602
|
-
l: renderPos,
|
|
603
|
-
w: me.data.w,
|
|
604
|
-
h: h,
|
|
605
|
-
vw: vw,
|
|
606
|
-
chs: chs,
|
|
607
|
-
frameLength: frameLength,
|
|
608
|
-
dftSize: this.dftSize,
|
|
609
|
-
maxPsd: maxPsd,
|
|
610
|
-
norender: norender,
|
|
611
|
-
terminate: terminate
|
|
612
|
-
}, ada);
|
|
613
|
-
}
|
|
614
|
-
},
|
|
615
|
-
error: (err) => {
|
|
616
|
-
console.error("Sonagram: Error reading audio data: " + err);
|
|
617
|
-
}
|
|
618
|
-
});
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
else {
|
|
622
|
-
for (let ch = 0; ch < chs; ch++) {
|
|
623
|
-
ada[ch] = new ArrayBuffer(0);
|
|
624
|
-
}
|
|
625
|
-
this.worker.postMessage({
|
|
626
|
-
audioData: ada,
|
|
627
|
-
audioDataOffset: leftFramePos,
|
|
628
|
-
l: renderPos,
|
|
629
|
-
w: me.data.w,
|
|
630
|
-
h: h,
|
|
631
|
-
vw: vw,
|
|
632
|
-
chs: chs,
|
|
633
|
-
frameLength: frameLength,
|
|
634
|
-
dftSize: this.dftSize,
|
|
635
|
-
maxPsd: maxPsd,
|
|
636
|
-
norender: norender,
|
|
637
|
-
terminate: terminate
|
|
638
|
-
}, ada);
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
}
|
|
642
|
-
};
|
|
643
|
-
}
|
|
644
|
-
if (audioBuffer && audioBuffer.length * audioBuffer.numberOfChannels < AudioCanvasLayerComponent.ENABLE_STREAMING_NUMBER_OF_SAMPLES_THRESHOLD) {
|
|
645
|
-
let ada = new Array(chs);
|
|
646
|
-
for (let ch = 0; ch < chs; ch++) {
|
|
647
|
-
// Need a copy here for the worker, otherwise this.audioData is not accessible after posting to the worker
|
|
648
|
-
ada[ch] = audioBuffer.getChannelData(ch).buffer.slice(0);
|
|
649
|
-
}
|
|
650
|
-
//let start = Date.now();
|
|
651
|
-
if (this.markerCanvas) {
|
|
652
|
-
let g = this.markerCanvas.getContext("2d");
|
|
653
|
-
if (g) {
|
|
654
|
-
g.fillText("Rendering...", 10, 20);
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
this.worker.postMessage({
|
|
658
|
-
audioData: ada,
|
|
659
|
-
l: leftPos,
|
|
660
|
-
w: w,
|
|
661
|
-
h: h,
|
|
662
|
-
vw: Math.round(this.virtualDimension.width),
|
|
663
|
-
chs: chs,
|
|
664
|
-
frameLength: frameLength,
|
|
665
|
-
dftSize: this.dftSize,
|
|
666
|
-
terminate: true
|
|
667
|
-
}, ada);
|
|
668
|
-
}
|
|
669
|
-
else {
|
|
670
|
-
if (w > 0) {
|
|
671
|
-
if (framesPerPixel > 0) {
|
|
672
|
-
let arrSize = w * h * 4;
|
|
673
|
-
if (arrSize < 0) {
|
|
674
|
-
arrSize = 0;
|
|
675
|
-
}
|
|
676
|
-
imgData = new Uint8ClampedArray(arrSize);
|
|
677
|
-
let rw = 1;
|
|
678
|
-
arrAbBuf = new Array(chs);
|
|
679
|
-
for (let ch = 0; ch < chs; ch++) {
|
|
680
|
-
arrAbBuf[ch] = new Float32Array(this.dftSize);
|
|
681
|
-
}
|
|
682
|
-
let leftFramePos = Math.floor(frameLength * renderPos / vw) - this.dftSize / 2;
|
|
683
|
-
let framesToRead = this.dftSize;
|
|
684
|
-
if (leftFramePos < 0) {
|
|
685
|
-
leftFramePos = 0;
|
|
686
|
-
}
|
|
687
|
-
this.drawStateText('Loading/Rendering...');
|
|
688
|
-
this.raAsSubsc = raAs.framesObs(leftFramePos, framesToRead, arrAbBuf).subscribe({
|
|
689
|
-
next: (read) => {
|
|
690
|
-
if (arrAbBuf && this.worker) {
|
|
691
|
-
if (read < this.dftSize) {
|
|
692
|
-
// zero padding
|
|
693
|
-
for (let ch = 0; ch < chs; ch++) {
|
|
694
|
-
for (let zp = read; zp < this.dftSize; zp++) {
|
|
695
|
-
arrAbBuf[ch][zp] = 0;
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
for (let ch = 0; ch < chs; ch++) {
|
|
700
|
-
const arrAbBufCh = arrAbBuf[ch];
|
|
701
|
-
const adLen = arrAbBufCh.buffer.byteLength;
|
|
702
|
-
if (!ada[ch] || ada[ch].byteLength !== adLen) {
|
|
703
|
-
ada[ch] = new ArrayBuffer(adLen);
|
|
704
|
-
}
|
|
705
|
-
let fAdaCh = new Float32Array(ada[ch]);
|
|
706
|
-
fAdaCh.set(arrAbBuf[ch]);
|
|
707
|
-
}
|
|
708
|
-
this.worker.postMessage({
|
|
709
|
-
l: renderPos,
|
|
710
|
-
w: rw,
|
|
711
|
-
h: h,
|
|
712
|
-
vw: vw,
|
|
713
|
-
chs: chs,
|
|
714
|
-
frameLength: frameLength,
|
|
715
|
-
audioData: ada,
|
|
716
|
-
audioDataOffset: leftFramePos,
|
|
717
|
-
dftSize: this.dftSize,
|
|
718
|
-
norender: norender,
|
|
719
|
-
terminate: false
|
|
720
|
-
}, ada);
|
|
721
|
-
}
|
|
722
|
-
},
|
|
723
|
-
error: (err) => {
|
|
724
|
-
console.error("Sonagram: Error reading audio data: " + err);
|
|
725
|
-
}
|
|
726
|
-
});
|
|
727
|
-
}
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
});
|
|
733
|
-
}
|
|
734
|
-
else {
|
|
735
|
-
if (this.bounds && this.bounds.dimension) {
|
|
736
|
-
let w = Math.round(this.bounds.dimension.width);
|
|
737
|
-
let h = Math.round(this.bounds.dimension.height);
|
|
738
|
-
let g = this.sonagramCanvas.getContext("2d");
|
|
739
|
-
if (g) {
|
|
740
|
-
g.clearRect(0, 0, w, h);
|
|
741
|
-
}
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
|
-
drawRendered(w, h, imgData) {
|
|
746
|
-
if (this.sonagramCanvas) {
|
|
747
|
-
this.sonagramCanvas.width = w;
|
|
748
|
-
this.sonagramCanvas.height = h;
|
|
749
|
-
let g = this.sonagramCanvas.getContext("2d");
|
|
750
|
-
if (g) {
|
|
751
|
-
if (w > 0 && h > 0) {
|
|
752
|
-
let gImgData = g.createImageData(w, h);
|
|
753
|
-
gImgData.data.set(imgData);
|
|
754
|
-
g.putImageData(gImgData, 0, 0);
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
}
|
|
758
|
-
this.drawBg();
|
|
759
|
-
this.drawPlayPosition();
|
|
760
|
-
}
|
|
761
|
-
// // synchronous draw (not used anymore)
|
|
762
|
-
// redraw() {
|
|
763
|
-
//
|
|
764
|
-
// let g = this.sonagramCanvas.getContext("2d");
|
|
765
|
-
//
|
|
766
|
-
// let w = this.sonagramCanvas.width;
|
|
767
|
-
// let h = this.sonagramCanvas.height;
|
|
768
|
-
// if (g) {
|
|
769
|
-
// g.clearRect(0, 0, w, h);
|
|
770
|
-
// g.fillStyle = "white";
|
|
771
|
-
// g.fillRect(0, 0, w, h);
|
|
772
|
-
// if (this._audioDataHolder) {
|
|
773
|
-
// let spectSize = Math.floor(this.dftSize / 2)
|
|
774
|
-
// let chs = this._audioDataHolder.numberOfChannels;
|
|
775
|
-
// let chH = h / chs;
|
|
776
|
-
//
|
|
777
|
-
// let frameLength = this._audioDataHolder.frameLen;
|
|
778
|
-
//
|
|
779
|
-
// let framesPerPixel = frameLength / w;
|
|
780
|
-
// let y = 0;
|
|
781
|
-
// let audioBuffer:AudioBuffer|null=null;
|
|
782
|
-
// let audioSource=this._audioDataHolder.audioSource;
|
|
783
|
-
// if(audioSource instanceof AudioBufferSource){
|
|
784
|
-
// audioBuffer=audioSource.audioBuffer;
|
|
785
|
-
// }
|
|
786
|
-
//
|
|
787
|
-
// if(audioBuffer) {
|
|
788
|
-
// let b = new Float32Array(this.dftSize)
|
|
789
|
-
//
|
|
790
|
-
// let sona = new Array<Array<Float32Array>>(chs);
|
|
791
|
-
// let max = 0;
|
|
792
|
-
// let maxPsd = -Infinity;
|
|
793
|
-
// for (let ch = 0; ch < chs; ch++) {
|
|
794
|
-
// let x = 0;
|
|
795
|
-
// sona[ch] = new Array<Float32Array>(w);
|
|
796
|
-
//
|
|
797
|
-
// let chData = audioBuffer.getChannelData(ch);
|
|
798
|
-
// // TODO center buffer
|
|
799
|
-
//
|
|
800
|
-
// let framePos = 0;
|
|
801
|
-
// for (let pii = 0; pii < w; pii++) {
|
|
802
|
-
// framePos = Math.round(pii * framesPerPixel);
|
|
803
|
-
// // calculate DFT at pixel position
|
|
804
|
-
// for (let i = 0; i < this.dftSize; i++) {
|
|
805
|
-
// let chDat = chData[framePos + i];
|
|
806
|
-
// b[i] = chDat;
|
|
807
|
-
// }
|
|
808
|
-
// let spectr = this.dft.processRealMagnitude(b);
|
|
809
|
-
// sona[ch][pii] = spectr;
|
|
810
|
-
// // @ts-ignore
|
|
811
|
-
// let pMax = Math.max.apply(null, spectr);
|
|
812
|
-
// if (pMax > max) {
|
|
813
|
-
// max = pMax;
|
|
814
|
-
// }
|
|
815
|
-
//
|
|
816
|
-
// for (let s = 0; s < spectSize; s++) {
|
|
817
|
-
// let psd = (2 * Math.pow(spectr[s], 2)) / spectSize;
|
|
818
|
-
// if (psd > maxPsd) {
|
|
819
|
-
// maxPsd = psd;
|
|
820
|
-
// }
|
|
821
|
-
// }
|
|
822
|
-
// }
|
|
823
|
-
// }
|
|
824
|
-
// //console.log("max: ", max);
|
|
825
|
-
// maxPsd = (2 * Math.pow(max, 2)) / spectSize;
|
|
826
|
-
// for (let ch = 0; ch < chs; ch++) {
|
|
827
|
-
//
|
|
828
|
-
// let framePos = 0;
|
|
829
|
-
// for (let pii = 0; pii < w; pii++) {
|
|
830
|
-
// framePos = pii * framesPerPixel;
|
|
831
|
-
//
|
|
832
|
-
// for (let y = 0; y < h; y++) {
|
|
833
|
-
// let freqIdx = Math.round(y * spectSize / h);
|
|
834
|
-
//
|
|
835
|
-
// // calculate the one sided power spectral density PSD (f, t) in Pa2/Hz
|
|
836
|
-
// // PSD(f) proportional to 2|X(f)|2 / (t2 - t1)
|
|
837
|
-
// let val = sona[ch][pii][freqIdx];
|
|
838
|
-
// let psd = (2 * Math.pow(val, 2)) / spectSize;
|
|
839
|
-
//
|
|
840
|
-
// // Calculate logarithmic
|
|
841
|
-
// let psdLog = DSPUtils.toLevelInDB(psd / maxPsd);
|
|
842
|
-
// let dynRangeInDb = 70;
|
|
843
|
-
// let scaledVal = (psdLog + dynRangeInDb) / dynRangeInDb;
|
|
844
|
-
//
|
|
845
|
-
// if (scaledVal > 1)
|
|
846
|
-
// scaledVal = 1;
|
|
847
|
-
// if (scaledVal < 0) {
|
|
848
|
-
// scaledVal = 0;
|
|
849
|
-
// }
|
|
850
|
-
// let rgbVal = (255 * scaledVal);
|
|
851
|
-
// if (rgbVal < 0) {
|
|
852
|
-
// // System.out.println("Neg RGB val: "+rgbVal);
|
|
853
|
-
// rgbVal = 0;
|
|
854
|
-
// }
|
|
855
|
-
// if (rgbVal > 255) {
|
|
856
|
-
// rgbVal = 255;
|
|
857
|
-
// }
|
|
858
|
-
// rgbVal = 255 - rgbVal;
|
|
859
|
-
// let colorStr = CSSUtils.toColorString(rgbVal, rgbVal, rgbVal);
|
|
860
|
-
// g.fillStyle = colorStr;
|
|
861
|
-
// g.fillRect(pii, chH - y, 1, 1);
|
|
862
|
-
// }
|
|
863
|
-
// }
|
|
864
|
-
// }
|
|
865
|
-
// this.drawPlayPosition();
|
|
866
|
-
// }else{
|
|
867
|
-
// throw Error("Redraw only supported with audio buffer.")
|
|
868
|
-
// }
|
|
869
|
-
// }
|
|
870
|
-
// }
|
|
871
|
-
// }
|
|
872
|
-
//
|
|
873
|
-
setData(audioData) {
|
|
874
|
-
this._audioDataHolder = audioData;
|
|
875
|
-
this.playFramePosition = 0;
|
|
876
|
-
}
|
|
877
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: Sonagram, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
878
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.12", type: Sonagram, selector: "audio-sonagram", viewQueries: [{ propertyName: "sonagramCanvasRef", first: true, predicate: ["sonagram"], descendants: true, static: true }, { propertyName: "markerCanvasRef", first: true, predicate: ["marker"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: `
|
|
879
|
-
<canvas #sonagram height="10"></canvas>
|
|
880
|
-
<canvas #bg height="10"></canvas>
|
|
881
|
-
<canvas #cursor height="10" (mousedown)="selectionStart($event)" (mouseover)="updateCursorCanvas($event)" (mousemove)="updateCursorCanvas($event)"
|
|
882
|
-
(mouseleave)="updateCursorCanvas($event, false)"></canvas>
|
|
883
|
-
<canvas #marker height="10"></canvas>`, isInline: true, styles: [":host{min-height:0px}\n", "canvas{top:0;left:0;width:0;height:0;min-height:0px;position:absolute}\n"] }); }
|
|
884
|
-
}
|
|
885
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: Sonagram, decorators: [{
|
|
886
|
-
type: Component,
|
|
887
|
-
args: [{ selector: 'audio-sonagram', template: `
|
|
888
|
-
<canvas #sonagram height="10"></canvas>
|
|
889
|
-
<canvas #bg height="10"></canvas>
|
|
890
|
-
<canvas #cursor height="10" (mousedown)="selectionStart($event)" (mouseover)="updateCursorCanvas($event)" (mousemove)="updateCursorCanvas($event)"
|
|
891
|
-
(mouseleave)="updateCursorCanvas($event, false)"></canvas>
|
|
892
|
-
<canvas #marker height="10"></canvas>`, styles: [":host{min-height:0px}\n", "canvas{top:0;left:0;width:0;height:0;min-height:0px;position:absolute}\n"] }]
|
|
893
|
-
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { sonagramCanvasRef: [{
|
|
894
|
-
type: ViewChild,
|
|
895
|
-
args: ['sonagram', { static: true }]
|
|
896
|
-
}], markerCanvasRef: [{
|
|
897
|
-
type: ViewChild,
|
|
898
|
-
args: ['marker', { static: true }]
|
|
899
|
-
}] } });
|
|
900
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic29uYWdyYW0uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9zcGVlY2hyZWNvcmRlcm5nL3NyYy9saWIvYXVkaW8vdWkvc29uYWdyYW0udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLFVBQVUsRUFBQyxNQUFNLGdCQUFnQixDQUFDO0FBQzFDLE9BQU8sRUFBUyxLQUFLLEVBQUMsTUFBTSxVQUFVLENBQUM7QUFDdkMsT0FBTyxFQUFDLFNBQVMsRUFBYyxTQUFTLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFDL0QsT0FBTyxFQUFDLHlCQUF5QixFQUFDLE1BQU0sMkJBQTJCLENBQUM7QUFDcEUsT0FBTyxFQUFDLFlBQVksRUFBQyxNQUFNLG1CQUFtQixDQUFDO0FBQy9DLE9BQU8sRUFBQyxpQkFBaUIsRUFBa0IsTUFBTSxzQkFBc0IsQ0FBQzs7QUFLeEUsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLENBQUM7QUF3QjlCLE1BQU0sT0FBTyxRQUFTLFNBQVEseUJBQXlCO0lBb0JuRCxZQUFvQixHQUFlO1FBQy9CLEtBQUssRUFBRSxDQUFDO1FBRFEsUUFBRyxHQUFILEdBQUcsQ0FBWTtRQVIzQix1QkFBa0IsR0FBYyxJQUFJLENBQUM7UUFJckMsY0FBUyxHQUFtQixJQUFJLENBQUM7UUFFakMsWUFBTyxHQUFHLGdCQUFnQixDQUFDO1FBSS9CLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDO1FBQ25CLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxJQUFJLENBQUM7UUFDN0IsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLEtBQUssRUFBVSxDQUFDO1FBQ25DLElBQUksQ0FBQyxHQUFHLEdBQUcsSUFBSSxVQUFVLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRXhDLElBQUksQ0FBQyxTQUFTLEdBQUcsWUFBWSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FB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Ozs4Q0FLZ0M7K0VBc0JELGlCQUFpQjtzQkFBekQsU0FBUzt1QkFBQyxVQUFVLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQUVBLGVBQWU7c0JBQXJELFNBQVM7dUJBQUMsUUFBUSxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7REZURmxvYXQzMn0gZnJvbSAnLi4vLi4vbWF0aC9kZnQnO1xyXG5pbXBvcnQge01hcmtlciwgUG9pbnR9IGZyb20gJy4vY29tbW9uJztcclxuaW1wb3J0IHtDb21wb25lbnQsIEVsZW1lbnRSZWYsIFZpZXdDaGlsZH0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcclxuaW1wb3J0IHtBdWRpb0NhbnZhc0xheWVyQ29tcG9uZW50fSBmcm9tIFwiLi9hdWRpb19jYW52YXNfbGF5ZXJfY29tcFwiO1xyXG5pbXBvcnQge1dvcmtlckhlbHBlcn0gZnJvbSBcIi4uLy4uL3V0aWxzL3V0aWxzXCI7XHJcbmltcG9ydCB7QXVkaW9CdWZmZXJTb3VyY2UsIEF1ZGlvRGF0YUhvbGRlcn0gZnJvbSBcIi4uL2F1ZGlvX2RhdGFfaG9sZGVyXCI7XHJcbmltcG9ydCB7U3Vic2NyaXB0aW9ufSBmcm9tIFwicnhqc1wiO1xyXG5cclxuZGVjbGFyZSBmdW5jdGlvbiBwb3N0TWVzc2FnZShtZXNzYWdlOiBhbnksIHRyYW5zZmVyOiBBcnJheTxhbnk+KTogdm9pZDtcclxuXHJcbmNvbnN0IERFRkFVTFRfREZUX1NJWkUgPSAxMDI0O1xyXG5cclxuQENvbXBvbmVudCh7XHJcblxyXG4gICAgc2VsZWN0b3I6ICdhdWRpby1zb25hZ3JhbScsXHJcbiAgICB0ZW1wbGF0ZTogYFxyXG4gICAgICAgIDxjYW52YXMgI3NvbmFncmFtIGhlaWdodD1cIjEwXCI+PC9jYW52YXM+XHJcbiAgICAgICAgPGNhbnZhcyAjYmcgaGVpZ2h0PVwiMTBcIj48L2NhbnZhcz5cclxuICAgICAgICA8Y2FudmFzICNjdXJzb3IgaGVpZ2h0PVwiMTBcIiAobW91c2Vkb3duKT1cInNlbGVjdGlvblN0YXJ0KCRldmVudClcIiAobW91c2VvdmVyKT1cInVwZGF0ZUN1cnNvckNhbnZhcygkZXZlbnQpXCIgKG1vdXNlbW92ZSk9XCJ1cGRhdGVDdXJzb3JDYW52YXMoJGV2ZW50KVwiXHJcbiAgICAgICAgICAgICAgICAobW91c2VsZWF2ZSk9XCJ1cGRhdGVDdXJzb3JDYW52YXMoJGV2ZW50LCBmYWxzZSlcIj48L2NhbnZhcz5cclxuICAgICAgICA8Y2FudmFzICNtYXJrZXIgaGVpZ2h0PVwiMTBcIj48L2NhbnZhcz5gLFxyXG5cclxuICAgIHN0eWxlczogW2A6aG9zdHtcclxuICAgICAgbWluLWhlaWdodDogMHB4O1xyXG4gICAgfWAsYGNhbnZhcyB7XHJcbiAgICAgICAgdG9wOiAwO1xyXG4gICAgICAgIGxlZnQ6IDA7XHJcbiAgICAgICAgd2lkdGg6IDA7XHJcbiAgICAgICAgaGVpZ2h0OiAwO1xyXG4gICAgICBtaW4taGVpZ2h0OiAwcHg7XHJcbiAgICAgICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgfWBdXHJcblxyXG59KVxyXG5leHBvcnQgY2xhc3MgU29uYWdyYW0gZXh0ZW5kcyBBdWRpb0NhbnZhc0xheWVyQ29tcG9uZW50IHtcclxuXHJcbiAgICBkZnQ6IERGVEZsb2F0MzI7XHJcbiAgICBuOiBhbnk7XHJcbiAgICBjZSE6IEhUTUxEaXZFbGVtZW50O1xyXG4gICAgc29uYWdyYW1DYW52YXMhOiBIVE1MQ2FudmFzRWxlbWVudDtcclxuICAgIC8vY3Vyc29yQ2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudDtcclxuICAgIG1hcmtlckNhbnZhcyE6IEhUTUxDYW52YXNFbGVtZW50O1xyXG4gICAgQFZpZXdDaGlsZCgnc29uYWdyYW0nLCB7IHN0YXRpYzogdHJ1ZSB9KSBzb25hZ3JhbUNhbnZhc1JlZiE6IEVsZW1lbnRSZWY7XHJcblxyXG4gICAgQFZpZXdDaGlsZCgnbWFya2VyJywgeyBzdGF0aWM6IHRydWUgfSkgbWFya2VyQ2FudmFzUmVmITogRWxlbWVudFJlZjtcclxuICAgIG1hcmtlcnM6IEFycmF5PE1hcmtlcj47XHJcbiAgICBwcml2YXRlIF9wbGF5RnJhbWVQb3NpdGlvbjogbnVtYmVyfG51bGw9bnVsbDtcclxuXHJcbiAgICBwcml2YXRlIHdvcmtlcjogV29ya2VyIHwgbnVsbDtcclxuICAgIHByaXZhdGUgcmVhZG9ubHkgd29ya2VyVVJMOiBzdHJpbmc7XHJcbiAgICBwcml2YXRlIHJhQXNTdWJzYzpTdWJzY3JpcHRpb258bnVsbD1udWxsO1xyXG5cclxuICAgIHByaXZhdGUgZGZ0U2l6ZSA9IERFRkFVTFRfREZUX1NJWkU7XHJcblxyXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSByZWY6IEVsZW1lbnRSZWYpIHtcclxuICAgICAgICBzdXBlcigpO1xyXG4gICAgICAgIHRoaXMud29ya2VyID0gbnVsbDtcclxuICAgICAgICB0aGlzLl9hdWRpb0RhdGFIb2xkZXIgPSBudWxsO1xyXG4gICAgICAgIHRoaXMubWFya2VycyA9IG5ldyBBcnJheTxNYXJrZXI+KCk7XHJcbiAgICAgICAgdGhpcy5kZnQgPSBuZXcgREZURmxvYXQzMih0aGlzLmRmdFNpemUpO1xyXG5cclxuICAgICAgICB0aGlzLndvcmtlclVSTCA9IFdvcmtlckhlbHBlci5idWlsZFdvcmtlckJsb2JVUkwodGhpcy53b3JrZXJGdW5jdGlvbilcclxuICAgICAgIHRoaXMuX2JnQ29sb3I9bnVsbDtcclxuICAgICAgIHRoaXMuX3NlbGVjdENvbG9yPSdyZ2JhKDI1NSwyNTUsMCwwLjEpJ1xyXG4gICAgfVxyXG5cclxuICAgIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcclxuXHJcbiAgICAgICAgdGhpcy5jZSA9IHRoaXMucmVmLm5hdGl2ZUVsZW1lbnQ7XHJcbiAgICAgICAgdGhpcy5zb25hZ3JhbUNhbnZhcyA9IHRoaXMuc29uYWdyYW1DYW52YXNSZWYubmF0aXZlRWxlbWVudDtcclxuICAgICAgICB0aGlzLnNvbmFncmFtQ2FudmFzLnN0eWxlLnpJbmRleCA9ICcxJztcclxuICAgICAgdGhpcy5iZ0NhbnZhcyA9IHRoaXMuYmdDYW52YXNSZWYubmF0aXZlRWxlbWVudDtcclxuICAgICAgdGhpcy5iZ0NhbnZhcy5zdHlsZS56SW5kZXggPSAnMic7XHJcbiAgICAgICAgdGhpcy5jdXJzb3JDYW52YXMgPSB0aGlzLmN1cnNvckNhbnZhc1JlZi5uYXRpdmVFbGVtZW50O1xyXG4gICAgICAgIHRoaXMuY3Vyc29yQ2FudmFzLnN0eWxlLnpJbmRleCA9ICc0JztcclxuICAgICAgICB0aGlzLm1hcmtlckNhbnZhcyA9IHRoaXMubWFya2VyQ2FudmFzUmVmLm5hdGl2ZUVsZW1lbnQ7XHJcbiAgICAgICAgdGhpcy5tYXJrZXJDYW52YXMuc3R5bGUuekluZGV4ID0gJzMnO1xyXG5cclxuICAgICAgICB0aGlzLmNhbnZhc0xheWVyc1swXSA9IHRoaXMuc29uYWdyYW1DYW52YXM7XHJcbiAgICAgIHRoaXMuY2FudmFzTGF5ZXJzWzFdID0gdGhpcy5iZ0NhbnZhcztcclxuICAgICAgdGhpcy5jYW52YXNMYXllcnNbMl0gPSB0aGlzLmN1cnNvckNhbnZhcztcclxuICAgICAgICB0aGlzLmNhbnZhc0xheWVyc1szXSA9IHRoaXMubWFya2VyQ2FudmFzO1xyXG5cclxuICAgIH1cclxuXHJcbiAgICBnZXQgcGxheUZyYW1lUG9zaXRpb24oKTogbnVtYmVyfG51bGwge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl9wbGF5RnJhbWVQb3NpdGlvbjtcclxuICAgIH1cclxuXHJcbiAgICBzZXQgcGxheUZyYW1lUG9zaXRpb24ocGxheUZyYW1lUG9zaXRpb246IG51bWJlcnxudWxsKSB7XHJcbiAgICAgICAgdGhpcy5fcGxheUZyYW1lUG9zaXRpb24gPSBwbGF5RnJhbWVQb3NpdGlvbjtcclxuICAgICAgICAvLyB0aGlzLnJlZHJhdygpO1xyXG4gICAgICAgIHRoaXMuZHJhd1BsYXlQb3NpdGlvbigpO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgY2FudmFzTW91c2VQb3MoYzogSFRNTENhbnZhc0VsZW1lbnQsIGU6IE1vdXNlRXZlbnQpOiBQb2ludCB7XHJcbiAgICAgICAgY29uc3QgY3IgPSBjLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xyXG5cclxuICAgICAgICBjb25zdCB4ID0gZS54IC0gY3IubGVmdDtcclxuICAgICAgICBjb25zdCB5ID0gZS55IC0gY3IudG9wO1xyXG4gICAgICAgIHJldHVybiBuZXcgUG9pbnQoeCx5KTtcclxuICAgIH1cclxuXHJcbiAgZHJhd1N0YXRlVGV4dChzdGF0ZVRleHQ6c3RyaW5nKSB7XHJcbiAgICAgICAgaWYoc3RhdGVUZXh0KSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGcgPSB0aGlzLnNvbmFncmFtQ2FudmFzLmdldENvbnRleHQoXCIyZFwiKTtcclxuICAgICAgICAgICAgY29uc3QgdyA9IHRoaXMuc29uYWdyYW1DYW52YXMud2lkdGg7XHJcbiAgICAgICAgICAgIGNvbnN0IGggPSB0aGlzLnNvbmFncmFtQ2FudmFzLmhlaWdodDtcclxuICAgICAgICAgICAgaWYgKGcgJiYgdyAmJiBoKSB7XHJcbiAgICAgICAgICAgICAgICBnLnN0cm9rZVN0eWxlID0gJ2JsYWNrJztcclxuICAgICAgICAgICAgICAgIGcuZmlsbFN0eWxlID0gJ2JsYWNrJztcclxuICAgICAgICAgICAgICAgIGcuZm9udCA9ICcyMHB4IHNhbnMtc2VyaWYnO1xyXG4gICAgICAgICAgICAgICAgZy5maWxsVGV4dChzdGF0ZVRleHQsIDEwLCAyNSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgfVxyXG5cclxuICBkcmF3Q3Vyc29yUG9zaXRpb24oZTogTW91c2VFdmVudCwgc2hvdzogYm9vbGVhbikge1xyXG5cclxuICAgIGlmICh0aGlzLmN1cnNvckNhbnZhcykge1xyXG4gICAgICBjb25zdCB3ID0gdGhpcy5jdXJzb3JDYW52YXMud2lkdGg7XHJcbiAgICAgIGNvbnN0IGggPSB0aGlzLmN1cnNvckNhbnZhcy5oZWlnaHQ7XHJcbiAgICAgIGNvbnN0IGcgPSB0aGlzLmN1cnNvckNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xyXG4gICAgICBpZiAoZykge1xyXG4gICAgICAgIGcuY2xlYXJSZWN0KDAsIDAsIHcsIGgpO1xyXG4gICAgICAgIGlmIChzaG93KSB7XHJcbiAgICAgICAgICAvL2NvbnN0IHBwID0gdGhpcy5jYW52YXNNb3VzZVBvcyh0aGlzLmN1cnNvckNhbnZhcywgZSk7XHJcbiAgICAgICAgICBsZXQgeFZpZXdQb3J0UGl4ZWxwb3MgPSBlLm9mZnNldFg7XHJcblxyXG4gICAgICAgICAgZy5maWxsU3R5bGUgPSAneWVsbG93JztcclxuICAgICAgICAgIGcuc3Ryb2tlU3R5bGUgPSAneWVsbG93JztcclxuICAgICAgICAgIGcuYmVnaW5QYXRoKCk7XHJcbiAgICAgICAgICBnLm1vdmVUbyh4Vmlld1BvcnRQaXhlbHBvcywgMCk7XHJcbiAgICAgICAgICBnLmxpbmVUbyh4Vmlld1BvcnRQaXhlbHBvcywgaCk7XHJcbiAgICAgICAgICBnLmNsb3NlUGF0aCgpO1xyXG5cclxuICAgICAgICAgIGcuc3Ryb2tlKCk7XHJcblxyXG4gICAgICAgICAgaWYgKHRoaXMuX2F1ZGlvRGF0YUhvbGRlcikge1xyXG5cclxuICAgICAgICAgICAgbGV0IGZyYW1lUG9zUm91bmQgPSB0aGlzLnZpZXdQb3J0WFBpeGVsVG9GcmFtZVBvc2l0aW9uKHhWaWV3UG9ydFBpeGVscG9zKTtcclxuICAgICAgICAgICAgaWYoZnJhbWVQb3NSb3VuZCE9bnVsbCkge1xyXG4gICAgICAgICAgICAgIGcuZm9udCA9ICcxNHB4IHNhbnMtc2VyaWYnO1xyXG4gICAgICAgICAgICAgIGcuZmlsbFN0eWxlID0gJ3llbGxvdyc7XHJcbiAgICAgICAgICAgICAgZy5maWxsVGV4dChmcmFtZVBvc1JvdW5kLnRvU3RyaW5nKCksIHhWaWV3UG9ydFBpeGVscG9zICsgMiwgNTApO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAgIGRyYXdQbGF5UG9zaXRpb24oKSB7XHJcbiAgICAgICAgaWYgKHRoaXMubWFya2VyQ2FudmFzKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IHcgPSB0aGlzLm1hcmtlckNhbnZhcy53aWR0aDtcclxuICAgICAgICAgICAgY29uc3QgaCA9IHRoaXMubWFya2VyQ2FudmFzLmhlaWdodDtcclxuICAgICAgICAgICAgY29uc3QgZyA9IHRoaXMubWFya2VyQ2FudmFzLmdldENvbnRleHQoXCIyZFwiKTtcclxuICAgICAgICAgICAgaWYgKGcpIHtcclxuICAgICAgICAgICAgICAgIGcuY2xlYXJSZWN0KDAsIDAsIHcsIGgpO1xyXG4gICAgICAgICAgICAgICAgaWYodGhpcy5fcGxheUZyYW1lUG9zaXRpb24hPW51bGwpIHtcclxuICAgICAgICAgICAgICAgICAgICBsZXQgcGl4ZWxQb3MgPSB0aGlzLmZyYW1lVG9WaWV3UG9ydFhQaXhlbFBvc2l0aW9uKHRoaXMuX3BsYXlGcmFtZVBvc2l0aW9uKTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAocGl4ZWxQb3MpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZy5maWxsU3R5bGUgPSAncmVkJztcclxuICAgICAgICAgICAgICAgICAgICAgICAgZy5zdHJva2VTdHlsZSA9ICdyZWQnO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBnLmJlZ2luUGF0aCgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBnLm1vdmVUbyhwaXhlbFBvcywgMCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGcubGluZVRvKHBpeGVsUG9zLCBoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZy5jbG9zZVBhdGgoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZy5zdHJva2UoKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLypcclxuICAgICAqICBNZXRob2QgdXNlZCBhcyB3b3JrZXIgY29kZS5cclxuICAgICAqL1xyXG4gICAgd29ya2VyRnVuY3Rpb24oKSB7XHJcblxyXG4gICAgICAgIC8vIFJlZGVmaW5lIHNvbWUgRFNQIGNsYXNzZXMgZm9yIHdvcmtlciBmdW5jdGlvblxyXG4gICAgICAgIC8vIFNlZSBlLmcuIGF1ZGlvLm1hdGguQ29tcGxleFxyXG4gICAgICAgIGNsYXNzIENvbXBsZXgge1xyXG5cclxuICAgICAgICAgICAgcmVhbDogbnVtYmVyO1xyXG4gICAgICAgICAgICBpbWc6IG51bWJlcjtcclxuXHJcbiAgICAgICAgICAgIHB1YmxpYyBzdGF0aWMgZnJvbVBvbGFyRm9ybShtYWduaXR1ZGU6IG51bWJlciwgYXJndW1lbnQ6IG51bWJlcik6IENvbXBsZXgge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgciA9IE1hdGguY29zKGFyZ3VtZW50KSAqIG1hZ25pdHVkZTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGkgPSBNYXRoLnNpbihhcmd1bWVudCkgKiBtYWduaXR1ZGU7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IENvbXBsZXgociwgaSk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGNvbnN0cnVjdG9yKHJlYWw6IG51bWJlciwgaW1nOiBudW1iZXIpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMucmVhbCA9IHJlYWw7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmltZyA9IGltZztcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgcHVibGljIG1hZ25pdHVkZSgpOiBudW1iZXIge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIE1hdGguc3FydCgodGhpcy5yZWFsICogdGhpcy5yZWFsKSArICh0aGlzLmltZyAqIHRoaXMuaW1nKSk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHB1YmxpYyBhcmd1bWVudCgpOiBudW1iZXIge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIE1hdGguYXRhbjIodGhpcy5pbWcsIHRoaXMucmVhbCk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHB1YmxpYyBhZGQoYWRkQzogQ29tcGxleCk6IENvbXBsZXgge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBDb21wbGV4KHRoaXMucmVhbCArIGFkZEMucmVhbCwgdGhpcy5pbWcgKyBhZGRDLmltZyk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHB1YmxpYyBzdWIoc3ViQzogQ29tcGxleCk6IENvbXBsZXgge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBDb21wbGV4KHRoaXMucmVhbCAtIHN1YkMucmVhbCwgdGhpcy5pbWcgLSBzdWJDLmltZyk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHB1YmxpYyBtdWx0KG11bHRDOiBDb21wbGV4KTogQ29tcGxleCB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBtdWx0UiA9ICh0aGlzLnJlYWwgKiBtdWx0Qy5yZWFsKSAtICh0aGlzLmltZyAqIG11bHRDLmltZyk7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBtdWx0SSA9ICh0aGlzLnJlYWwgKiBtdWx0Qy5pbWcpICsgKG11bHRDLnJlYWwgKiB0aGlzLmltZyk7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IENvbXBsZXgobXVsdFIsIG11bHRJKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgcHVibGljIG11bHRSZWFsKG11bHRGOiBudW1iZXIpOiBDb21wbGV4IHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgQ29tcGxleCh0aGlzLnJlYWwgKiBtdWx0RiwgdGhpcy5pbWcgKiBtdWx0Rik7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHB1YmxpYyBkaXYoZGl2aXNvcjogQ29tcGxleCk6IENvbXBsZXgge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgZGl2UmVhbCA9IGRpdmlzb3IucmVhbDtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGRpdkltZyA9IGRpdmlzb3IuaW1nO1xyXG4gICAgICAgICAgICAgICAgY29uc3QgZGl2ID0gKGRpdlJlYWwgKiBkaXZSZWFsKSArIChkaXZJbWcgKiBkaXZJbWcpO1xyXG4gICAgICAgICAgICAgICAgY29uc3QgZGl2aXNpb25SZWFsID0gKCh0aGlzLnJlYWwgKiBkaXZSZWFsKSArICh0aGlzLmltZyAqIGRpdkltZykpIC8gZGl2O1xyXG4gICAgICAgICAgICAgICAgY29uc3QgZGl2aXNpb25JbWcgPSAoKGRpdlJlYWwgKiB0aGlzLmltZykgLSAodGhpcy5yZWFsICogZGl2SW1nKSkgLyBkaXY7XHJcblxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBDb21wbGV4KGRpdmlzaW9uUmVhbCwgZGl2aXNpb25JbWcpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBwdWJsaWMgZGl2UmVhbChkaXZpc29yOiBudW1iZXIpOiBDb21wbGV4IHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGRpdiA9IGRpdmlzb3IgKiBkaXZpc29yO1xyXG4gICAgICAgICAgICAgICAgY29uc3QgZGl2c2lvblJlYWwgPSAodGhpcy5yZWFsICogZGl2aXNvcikgLyBkaXY7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBkaXZzaW9uSW1nID0gKGRpdmlzb3IgKiB0aGlzLmltZykgLyBkaXY7XHJcblxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBDb21wbGV4KGRpdnNpb25SZWFsLCBkaXZzaW9uSW1nKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgcHVibGljIGNvbmp1Z2F0ZSgpOiBDb21wbGV4IHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgQ29tcGxleCh0aGlzLnJlYWwsIC10aGlzLmltZyk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHB1YmxpYyBlcXVhbHMoYzogQ29tcGxleCk6IGJvb2xlYW4ge1xyXG4gICAgICAgICAgICAgICAgaWYgKGMgPT09IG51bGwpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gKHRoaXMucmVhbCA9PT0gYy5yZWFsICYmIHRoaXMuaW1nID09PSBjLmltZyk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHB1YmxpYyB0b1N0cmluZygpOiBzdHJpbmcge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuICdSZWFsOiAnICsgdGhpcy5yZWFsICsgJywgSW1nOiAnICsgdGhpcy5pbWc7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNsYXNzIERGVEZsb2F0MzIge1xyXG5cclxuICAgICAgICAgICAgcHJpdmF0ZSByZWFkb25seSBuOiBudW1iZXI7XHJcbiAgICAgICAgICAgIHByaXZhdGUgcmVhZG9ubHkgbTogbnVtYmVyO1xyXG5cclxuICAgICAgICAgICAgcHJpdmF0ZSByZWFkb25seSBjb3NMb29rdXA6IEZsb2F0MzJBcnJheTtcclxuICAgICAgICAgICAgcHJpdmF0ZSByZWFkb25seSBzaW5Mb29rdXA6IEZsb2F0MzJBcnJheTtcclxuXHJcbiAgICAgICAgICAgIGNvbnN0cnVjdG9yKG46IG51bWJlcikge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5uID0gbjtcclxuICAgICAgICAgICAgICAgIHRoaXMubSA9IE1hdGgubG9nKG4pIC8gTWF0aC5sb2coMik7XHJcblxyXG4gICAgICAgICAgICAgICAgLy8gaWYobiAhPSAoMSA8PCBtKSl0aHJvdyBuZXcgUnVudGltZUV4Y2VwdGlvbihcImxlbmd0aCBOIG11c3QgYmUgcG93ZXIgb2YgMlwiKTtcclxuXHJcbiAgICAgICAgICAgICAgICAvLyBsb29rdXAgdGFibGVzXHJcbiAgICAgICAgICAgICAgICB0aGlzLmNvc0xvb2t1cCA9IG5ldyBGbG9hdDMyQXJyYXkobiAvIDIpO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5zaW5Mb29rdXAgPSBuZXcgRmxvYXQzMkFycmF5KG4gLyAyKTtcclxuXHJcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG4gLyAyOyBpKyspIHtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBhcmMgPSAoLTIgKiBNYXRoLlBJICogaSkgLyBuO1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29zTG9va3VwW2ldID0gTWF0aC5jb3MoYXJjKTtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLnNpbkxvb2t1cFtpXSA9IE1hdGguc2luKGFyYyk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHB1YmxpYyBwcm9jZXNzUmVhbChzcmNCdWY6IEZsb2F0MzJBcnJheSk6IEFycmF5PENvbXBsZXg+IHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHggPSBzcmNCdWYuc2xpY2UoKTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHkgPSBuZXcgRmxvYXQzMkFycmF5KHNyY0J1Zi5sZW5ndGgpO1xyXG4gICAgICAgICAgICAgICAgZm9yIChsZXQgeWkgPSAwOyB5aSA8IHkubGVuZ3RoOyB5aSsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgeVt5aV0gPSAwLjA7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB0aGlzLmZmdENvb2xleVR1a2V5KHgsIHkpO1xyXG4gICAgICAgICAgICAgICAgY29uc3QgcmMgPSBuZXcgQXJyYXk8Q29tcGxleD4oeC5sZW5ndGgpO1xyXG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB4Lmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmNbaV0gPSBuZXcgQ29tcGxleCh4W2ldLCB5W2ldKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIHJldHVybiByYztcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgcHVibGljIHByb2Nlc3NSZWFsTWFnbml0dWRlKHNyY0J1ZjogRmxvYXQzMkFycmF5KTogRmxvYXQzMkFycmF5IHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHggPSBzcmNCdWYuc2xpY2UoKTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHkgPSBuZXcgRmxvYXQzMkFycmF5KHNyY0J1Zi5sZW5ndGgpO1xyXG4gICAgICAgICAgICAgICAgZm9yIChsZXQgeWkgPSAwOyB5aSA8IHkubGVuZ3RoOyB5aSsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgeVt5aV0gPSAwLjA7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB0aGlzLmZmdENvb2xleVR1a2V5KHgsIHkpO1xyXG4gICAgICAgICAgICAgICAgY29uc3QgcmMgPSBuZXcgRmxvYXQzMkFycmF5KHgubGVuZ3RoKTtcclxuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgeC5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJjYyA9IG5ldyBDb21wbGV4KHhbaV0sIHlbaV0pO1xyXG4gICAgICAgICAgICAgICAgICAgIHJjW2ldID0gcmNjLm1hZ25pdHVkZSgpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJjO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBwdWJsaWMgZmZ0Q29vbGV5VHVrZXkocmVhbDogRmxvYXQzMkFycmF5LCBpbWc6IEZsb2F0MzJBcnJheSk6IHZvaWQge1xyXG4gICAgICAgICAgICAgICAgbGV0IGk6IG51bWJlcjtcclxuICAgICAgICAgICAgICAgIGxldCBqID0gMDtcclxuICAgICAgICAgICAgICAgIGxldCBrOiBudW1iZXI7XHJcbiAgICAgICAgICAgICAgICBsZXQgbjE6IG51bWJlcjtcclxuICAgICAgICAgICAgICAgIGxldCBuMjogbnVtYmVyID0gdGhpcy5uIC8gMjtcclxuICAgICAgICAgICAgICAgIGxldCBhOiBudW1iZXI7XHJcbiAgICAgICAgICAgICAgICBsZXQgYzogbnVtYmVyO1xyXG4gICAgICAgICAgICAgICAgbGV0IHM6IG51bWJlcjtcclxuICAgICAgICAgICAgICAgIGxldCB0MTogbnVtYmVyO1xyXG4gICAgICAgICAgICAgICAgbGV0IHQyOiBudW1iZXI7XHJcblxyXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMTsgaSA8IHRoaXMubiAtIDE7IGkrKykge1xyXG4gICAgICAgICAgICAgICAgICAgIG4xID0gbjI7XHJcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKGogPj0gbjEpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaiA9IGogLSBuMTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbjEgPSBuMSAvIDI7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIGogPSBqICsgbjE7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChpIDwgaikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0MSA9IHJlYWxbaV07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlYWxbaV0gPSByZWFsW2pdO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZWFsW2pdID0gdDE7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHQxID0gaW1nW2ldO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpbWdbaV0gPSBpbWdbal07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGltZ1tqXSA9IHQxO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBuMSA9IDA7XHJcbiAgICAgICAgICAgICAgICBuMiA9IDE7XHJcbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5tOyBpKyspIHtcclxuICAgICAgICAgICAgICAgICAgICBuMSA9IG4yO1xyXG4gICAgICAgICAgICAgICAgICAgIG4yID0gbjIgKyBuMjtcclxuICAgICAgICAgICAgICAgICAgICBhID0gMDtcclxuICAgICAgICAgICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgbjE7IGorKykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjID0gdGhpcy5jb3NMb29rdXBbYV07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHMgPSB0aGlzLnNpbkxvb2t1cFthXTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgYSArPSAoMSA8PCAodGhpcy5tIC0gaSAtIDEpKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoayA9IGo7IGsgPCB0aGlzLm47IGsgPSBrICsgbjIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHQxID0gYyAqIHJlYWxbayArIG4xXSAtIHMgKiBpbWdbayArIG4xXTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHQyID0gcyAqIHJlYWxbayArIG4xXSArIGMgKiBpbWdbayArIG4xXTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlYWxbayArIG4xXSA9IHJlYWxba10gLSB0MTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGltZ1trICsgbjFdID0gaW1nW2tdIC0gdDI7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWFsW2tdID0gcmVhbFtrXSArIHQxO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW1nW2tdID0gaW1nW2tdICsgdDI7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcblxyXG4gICAgICAgICAgICBwdWJsaWMgcHJvY2Vzcyh0OiBBcnJheTxDb21wbGV4Pik6IEFycmF5PENvbXBsZXg+IHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHJlYWxzOiBGbG9hdDMyQXJyYXkgPSBuZXcgRmxvYXQzMkFycmF5KHRoaXMubik7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBpbWdzOiBGbG9hdDMyQXJyYXkgPSBuZXcgRmxvYXQzMkFycmF5KHRoaXMubik7XHJcbiAgICAgICAgICAgICAgICBjb25zdCB0cmFuczogQXJyYXk8Q29tcGxleD4gPSBuZXcgQXJyYXk8Q29tcGxleD4odGhpcy5uKTtcclxuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5uOyBpKyspIHtcclxuICAgICAgICAgICAgICAgICAgICByZWFsc1tpXSA9IHRbaV0ucmVhbDtcclxuICAgICAgICAgICAgICAgICAgICBpbWdzW2ldID0gdFtpXS5pbWc7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB0aGlzLmZmdENvb2xleVR1a2V5KHJlYWxzLCBpbWdzKTtcclxuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5uOyBpKyspIHtcclxuICAgICAgICAgICAgICAgICAgICB0cmFuc1tpXSA9IG5ldyBDb21wbGV4KHJlYWxzW2ldLCBpbWdzW2ldKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIHJldHVybiB0cmFucztcclxuXHJcblxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaW50ZXJmYWNlIFdpbmRvd0Z1bmN0aW9uIHtcclxuICAgICAgICAgICAgZ2V0U2NhbGUoaTogbnVtYmVyKTogbnVtYmVyO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY2xhc3MgR2F1c3NpYW5XaW5kb3cgaW1wbGVtZW50cyBXaW5kb3dGdW5jdGlvbiB7XHJcblxyXG4gICAgICAgICAgICBwdWJsaWMgc3RhdGljIERFRkFVTFRfU0lHTUEgPSAwLjM7XHJcbiAgICAgICAgICAgIC8vIEdhdXNzaWFuIHdpbmRvdyBmdW5jdGlvbixcclxuICAgICAgICAgICAgLy8gaHR0cDovL3JlZmVyZW5jZS53b2xmcmFtLmNvbS9sYW5ndWFnZS9yZWYvR2F1c3NpYW5XaW5kb3cuaHRtbFxyXG4gICAgICAgICAgICAvLyB2YWw9ZXhwKC01MCp4KngvOSkgPT4gc2lnbWE9MC4zXHJcblxyXG4gICAgICAgICAgICBwcml2YXRlIHJlYWRvbmx5IGJ1ZjogRmxvYXQzMkFycmF5O1xyXG5cclxuICAgICAgICAgICAgY29uc3RydWN0b3Ioc2l6ZTogbnVtYmVyLCBzaWdtYTogbnVtYmVyID0gR2F1c3NpYW5XaW5kb3cuREVGQVVMVF9TSUdNQSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5idWYgPSBuZXcgRmxvYXQzMkFycmF5KHNpemUpO1xyXG4gICAgICAgICAgICAgICAgY29uc3QgY2VudGVyID0gKHNpemUgLSAxKSAvIDI7XHJcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNpemU7IGkrKykge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHF1b3QgPSAoaSAtIGNlbnRlcikgLyAoc2lnbWEgKiBjZW50ZXIpO1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGV4cCA9IC0wLjUgKiBxdW90ICogcXVvdDtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmJ1ZltpXSA9IE1hdGguZXhwKGV4cCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGdldFNjYWxlKGk6IG51bWJlcik6IG51bWJlciB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5idWZbaV07XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBzZWxmLm9ubWVzc2FnZSA9IGZ1bmN0aW9uIChtc2c6TWVzc2FnZUV2ZW50KSB7XHJcbiAgICAgICAgICAgIC8vY29uc29sZS5kZWJ1ZyhcIlNvbmFncmFtIHJlbmRlciB0aHJlYWRcIik7XHJcbiAgICAgICAgICAgIGxldCBsID0gbXNnLmRhdGEubDtcclxuICAgICAgICAgICAgbGV0IHcgPSBtc2cuZGF0YS53O1xyXG4gICAgICAgICAgICBsZXQgaCA9IG1zZy5kYXRhLmg7XHJcbiAgICAgICAgICAgIGxldCB2dyA9IG1zZy5kYXRhLnZ3O1xyXG4gICAgICAgICAgICBsZXQgY2hzID0gbXNnLmRhdGEuY2hzO1xyXG4gICAgICAgICAgICBsZXQgYXVkaW9EYXRhT2Zmc2V0PTA7XHJcbiAgICAgICAgICAgIGxldCBhZE9mZnNldD1tc2cuZGF0YS5hdWRpb0RhdGFPZmZzZXQ7XHJcbiAgICAgICAgICAgIGlmKGFkT2Zmc2V0KXtcclxuICAgICAgICAgICAgICBhdWRpb0RhdGFPZmZzZXQ9YWRPZmZzZXQ7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICBsZXQgbWF4UHNkID0gbnVsbDtcclxuICAgICAgICAgICAgaWYobXNnLmRhdGEubWF4UHNkIT09dW5kZWZpbmVkKXtcclxuICAgICAgICAgICAgICBtYXhQc2Q9bXNnLmRhdGEubWF4UHNkO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBsZXQgYXVkaW9EYXRhID0gbmV3IEFycmF5KGNocyk7XHJcbiAgICAgICAgICAgIGZvciAobGV0IGNoID0gMDsgY2ggPCBjaHM7IGNoKyspIHtcclxuICAgICAgICAgICAgICAgIGF1ZGlvRGF0YVtjaF0gPSBuZXcgRmxvYXQzMkFycmF5KG1zZy5kYXRhWydhdWRpb0RhdGEnXVtjaF0pO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBsZXQgZnJhbWVMZW5ndGggPSBtc2cuZGF0YS5mcmFtZUxlbmd0aDtcclxuICAgICAgICAgICAgbGV0IGRmdFNpemUgPSBtc2cuZGF0YS5kZnRTaXplO1xyXG5cclxuICAgICAgICAgICAgbGV0IGRmdEJhbmRzID0gZGZ0U2l6ZSAvIDI7XHJcbiAgICAgICAgICAgIGxldCBkZnQgPSBuZXcgREZURmxvYXQzMihkZnRTaXplKTtcclxuICAgICAgICAgICAgbGV0IHdmID0gbmV3IEdhdXNzaWFuV2luZG93KGRmdFNpemUpO1xyXG5cclxuICAgICAgICAgICAgbGV0IGFyclNpemU9dypoKjQ7XHJcbiAgICAgICAgICAgIGlmKGFyclNpemU8MCl7XHJcbiAgICAgICAgICAgICAgICBhcnJTaXplPTBcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBsZXQgaW1nRGF0YSA9IG5ldyBVaW50OENsYW1wZWRBcnJheShhcnJTaXplKTtcclxuICAgICAgICAgICAgLy9jb25zb2xlLmxvZyhcIlJlbmRlciBtZXRob2Q6XCIpO1xyXG4gICAgICAgICAgLy9jb25zb2xlLmRlYnVnKFwiQ3JlYXRlZCBpbWdEYXRhIGFyclNpemU6IFwiK2FyclNpemUrXCIgXCIsIHcsIFwieFwiLCBoKTtcclxuICAgICAgICAgIGxldCBjYWxjTWF4UHNkPS1JbmZpbml0eTtcclxuICAgICAgICAgICAgaWYgKGFyclNpemU+MCkge1xyXG5cclxuICAgICAgICAgICAgICAgIGxldCBjaEggPSBNYXRoLnJvdW5kKGggLyBjaHMpO1xyXG4gICAgICAgICAgICAgICAgbGV0IGZyYW1lc1BlclBpeGVsID0gZnJhbWVMZW5ndGggLyB2dztcclxuICAgICAgICAgICAgICAgIC8vY29uc29sZS5kZWJ1ZyhcIlJlbmRlcjogXCIsIHcsIFwieFwiLCBoKTtcclxuXHJcbiAgICAgICAgICAgICAgICBsZXQgYiA9IG5ldyBGbG9hdDMyQXJyYXkoZGZ0U2l6ZSk7XHJcbiAgICAgICAgICAgICAgICBsZXQgc29uYSA9IG5ldyBBcnJheShjaHMpO1xyXG5cclxuICAgICAgICAgICAgICAgIGZvciAobGV0IGNoID0gMDsgY2ggPCBjaHM7IGNoKyspIHtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IGNoRGF0YUxlbj1hdWRpb0RhdGFbY2hdLmxlbmd0aDtcclxuICAgICAgICAgICAgICAgICAgICAvLyBpbml0aWFsaXplIERGVCBhcnJheSBidWZmZXJcclxuICAgICAgICAgICAgICAgICAgICBzb25hW2NoXSA9IG5ldyBBcnJheSh3KTtcclxuICAgICAgICAgICAgICAgICAgICBsZXQgZnJhbWVQb3MgPSAwO1xyXG4gICAgICAgICAgICAgICAgICAgIGZvciAobGV0IHBpaSA9IDA7IHBpaSA8IHc7IHBpaSsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCB2aXJ0UGlpID0gbCArIHBpaTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gUG9zaXRpb24gb2Ygc2FtcGxlIGRhdGEgZnJhbWUgaXMgcGl4ZWwgcG9zaXRpb24gbWFwcGVkIHRvIGF1ZGlvIGZyYW1lIHBvc2l0aW9uLlxyXG4gICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZW4gXCJjZW50ZXJcIiB0aGUgZnJhbWUgYnkgc2hpZnRpbmcgbGVmdCBieSBoYWxmIHRoZSBERlQgc2l6ZSAoPWRmdEJhbmRzKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBmcmFtZVBvcyA9IE1hdGgucm91bmQoKHZpcnRQaWkgKiBmcmFtZXNQZXJQaXhlbCktZGZ0QmFuZHMpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBmaWxsIERGVCBidWZmZXIgd2l0aCB3aW5kb3dlZCBzYW1wbGUgdmFsdWVzXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZGZ0U2l6ZTsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgc2FtcGxlUG9zPWZyYW1lUG9zICsgaTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluaXRpYWxpemUgZm9yIG5lZ2F0aXZlIHNhbXBsZSBwb3NpdGlvbnMgYW5kIG91dCBvZiBib3VuZHMgcG9zaXRpb25zXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgY2hEYXQ9MDtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTZXQgYXVkaW8gc2FtcGxlIGlmIGF2YWlsYWJsZVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGFkcD1zYW1wbGVQb3MtYXVkaW9EYXRhT2Zmc2V0O1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYoYWRwPj0wICYmIGFkcCA8IGNoRGF0YUxlbikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaERhdCA9IGF1ZGlvRGF0YVtjaF1bYWRwXTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy9jb25zb2xlLmRlYnVnKFwiQXVkaW8gZGF0YTogXCIrY2hEYXQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfWVsc2V7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vY29uc29sZS5kZWJ1ZyhcIlNhbXBsZSBidWYgcG9zIG9vYjogYWRwOiBcIithZHArXCIsIGNoRGF0YUxlbjogXCIrY2hEYXRhTGVuK1wiLCBzYW1wbGVQb3M6IFwiK3NhbXBsZVBvcytcIiwgaTogXCIraSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXBwbHkgV2luZG93XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiW2ldID0gY2hEYXQgKiB3Zi5nZXRTY2FsZShpKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBDYWxjIERGVCBtYWduaXR1ZGVzXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBzcGVjdHIgPSBkZnQucHJvY2Vzc1JlYWxNYWduaXR1ZGUoYik7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBHZXQgbWF4aW11bSB2YWx1ZSBvZiBzcGVjdHJhbCBlbmVyZ3lcclxuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgcyA9IDA7IHMgPCBkZnRCYW5kczsgcysrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgcHNkID0gKDIgKiBNYXRoLnBvdyhzcGVjdHJbc10sIDIpKSAvIGRmdEJhbmRzO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBzZCA+IGNhbGNNYXhQc2QpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYWxjTWF4UHNkID0gcHNkO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNldCByZW5kZXIgbW9kZWwgZGF0YSBmb3IgdGhpcyBwaXhlbFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBzb25hW2NoXVtwaWldID0gc3BlY3RyO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBpZighbXNnLmRhdGEubm9yZW5kZXIpIHtcclxuICAgICAgICAgICAgICAgICAgaWYoIW1heFBzZCl7XHJcbiAgICAgICAgICAgICAgICAgICAgbWF4UHNkPWNhbGNNYXhQc2Q7XHJcbiAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGZvciAobGV0IGNoID0gMDsgY2ggPCBjaHM7IGNoKyspIHtcclxuXHJcbiAgICAgICAgICAgICAgICAgIGZvciAobGV0IHBpaSA9IDA7IHBpaSA8IHc7IHBpaSsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IGFsbEJsYWNrID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCB5ID0gMDsgeSA8IGNoSDsgeSsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICBsZXQgZnJlcUlkeCA9IE1hdGgucm91bmQoeSAqIGRmdEJhbmRzIC8gY2hIKTtcclxuICAgICAgICAgICAgICAgICAgICAgIC8vIGNhbGN1bGF0ZSB0aGUgb25lLXNpZGVkIHBvd2VyIHNwZWN0cmFsIGRlbnNpdHkgUFNEIChmLCB0KSBpbiBQYTIvSHpcclxuICAgICAgICAgICAgICAgICAgICAgIC8vIFBTRChmKSBwcm9wb3J0aW9uYWwgdG8gMnxYKGYpfDIgLyAodDIgLSB0MSlcclxuICAgICAgICAgICAgICAgICAgICAgIGxldCB2YWwgPSBzb25hW2NoXVtwaWldW2ZyZXFJZHhdO1xyXG4gICAgICAgICAgICAgICAgICAgICAgbGV0IHBzZCA9ICgyICogTWF0aC5wb3codmFsLCAyKSkgLyBkZnRCYW5kcztcclxuICAgICAgICAgICAgICAgICAgICAgIC8vIENhbGN1bGF0ZSBsb2dhcml0aG1pYyB2YWx1ZVxyXG4gICAgICAgICAgICAgICAgICAgICAgLy9sZXQgcHNkTG9nID0gaXBzLmRzcC5EU1BVdGlscy50b0xldmVsSW5EQihwc2QgLyBtYXhQc2QpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgbGV0IGxpbmVhckxldmVsID0gcHNkIC8gbWF4UHNkO1xyXG4gICAgICAgICAgICAgICAgICAgICAgbGV0IHBzZExvZyA9IDEwICogTWF0aC5sb2cobGluZWFyTGV2ZWwpIC8gTWF0aC5sb2coMTApO1xyXG4gICAgICAgICAgICAgICAgICAgICAgLy8gRml4ZWQgZHluYW1pYyBSYW5nZSB2YWx1ZSBvZiA3MGRCIGZvciBub3dcclxuICAgICAgICAgICAgICAgICAgICAgIGxldCBkeW5SYW5nZUluRGIgPSA3MDtcclxuICAgICAgICAgICAgICAgICAgICAgIGxldCBzY2FsZWRWYWwgPSAocHNkTG9nICsgZHluUmFuZ2VJbkRiKSAvIGR5blJhbmdlSW5EYjtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAvLyBhcmUgdGhlIGZvbGxvd2luZyBjaGVja3MgbmVjZXNzYXJ5IGZvciBjbGFtcGVkIGFycmF5ID9cclxuICAgICAgICAgICAgICAgICAgICAgIGlmIChzY2FsZWRWYWwgPiAxLjApXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlZFZhbCA9IDE7XHJcbiAgICAgICAgICAgICAgICAgICAgICBpZiAoc2NhbGVkVmFsIDwgMC4wKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlZFZhbCA9IDA7XHJcbiAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICBsZXQgcmdiVmFsID0gTWF0aC5yb3VuZCgyNTUgKiBzY2FsZWRWYWwpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgaWYgKHJnYlZhbCA8IDApIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy9cdFx0XHRcdFx0XHRcdFN5c3RlbS5vdXQucHJpbnRsbihcIk5lZyBSR0IgdmFsOiBcIityZ2JWYWwpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZ2JWYWwgPSAwO1xyXG4gICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgaWYgKHJnYlZhbCA+IDI1NSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZ2JWYWwgPSAyNTU7XHJcbiAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICByZ2JWYWwgPSAyNTUgLSByZ2JWYWw7XHJcbiAgICAgICAgICAgICAgICAgICAgICBpZiAocmdiVmFsID4gMCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBhbGxCbGFjayA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgbGV0IHB5ID0gY2hIIC0geTtcclxuICAgICAgICAgICAgICAgICAgICAgIGxldCBkYXRhUG9zID0gKCgoKGNoICogY2hIKSArIHB5KSAqIHcpICsgcGlpKSAqIDQ7XHJcbiAgICAgICAgICAgICAgICAgICAgICBpbWdEYXRhW2RhdGFQb3MgKyAwXSA9IHJnYlZhbDsgLy9SXHJcbiAgICAgICAgICAgICAgICAgICAgICBpbWdEYXRhW2RhdGFQb3MgKyAxXSA9IHJnYlZhbDsgLy9HXHJcbiAgICAgICAgICAgICAgICAgICAgICBpbWdEYXRhW2RhdGFQb3MgKyAyXSA9IHJnYlZhbDsgLy9CXHJcbiAgICAgICAgICAgICAgICAgICAgICBpbWdEYXRhW2RhdGFQb3MgKyAzXSA9IDI1NTsgLy9BIChhbHBoYTogZnVsbHkgb3BhcXVlKVxyXG4gICAgICAgICAgICAgICAgICAgICAgLy9jb25zb2xlLmRlYnVnKFwiUmVuZGVyZWQ6IHB5OiBcIitweStcIiwgcmdidmFsOiBcIityZ2JWYWwpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgLy8gZXhhbXBsZSAxeDEsIDJjaHNcclxuICAgICAgICAgICAgICAgICAgICAgIC8vICBjaDB4MHkwUixjaDB4MHkwRyxjaDB4MHkwQixjaDB4MHkwQSxcclxuICAgICAgICAgICAgICAgICAgICAgIC8vICBjaDB4MXkwUixjaDB4MXkwRyxjaDB4MXkwQixjaDB4MXkwQSxcclxuICAgICAgICAgICAgICAgICAgICAgIC8vICBjaDB4MHkwUixjaDB4MHkwRyxjaDB4MHkwQixjaDB4MHkwQSxcclxuICAgICAgICAgICAgICAgICAgICAgIC8vICBjaDB4MXkxUixjaDB4MXkxRyxjaDB4MXkxQixjaDB4MXkxQSxcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAvLyAgY2gxeDB5MFIsY2gxeDB5MEcsY2gxeDB5MEIsY2gxeDB5MEEsXHJcbiAgICAgICAgICAgICAgICAgICAgICAvLyAgY2gxeDF5MFIsY2gxeDF5MEcsY2gxeDF5MEIsY2gxeDF5MEEsXHJcbiAgICAgICAgICAgICAgICAgICAgICAvLyAgY2gxeDB5MFIsY2gxeDB5MEcsY2gxeDB5MEIsY2gxeDB5MEEsXHJcbiAgICAgICAgICAgICAgICAgICAgICAvLyAgY2gxeDF5MVIsY2gxeDF5MUcsY2gxeDF5MUIsY2gxeDF5MUFcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gaWYgKGFsbEJsYWNrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gICBjb25zb2xlLmxvZyhcIkJsYWNrOiBcIiwgcGlpLCBcIiBcIiwgY2gpO1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIH1cclxuICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIC8vY29uc29sZS5kZWJ1ZyhcIlJlbmRlciB0aHJlYWQgcG9zdCBtZXNzYWdlIGltZ0RhdGE6IFwiK2ltZ0RhdGEubGVuZ3RoKVxyXG4gICAgICAgICAgICBwb3N0TWVzc2FnZSh7aW1nRGF0YTogaW1nRGF0YSwgbDogbCwgdzogbXNnLmRhdGEudywgaDogbXNnLmRhdGEuaCwgdnc6IHZ3LG1heFBzZDpjYWxjTWF4UHNkLHRlcm1pbmF0ZTptc2cuZGF0YS50ZXJtaW5hdGV9LCBbaW1nRGF0YS5idWZmZXJdKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgc3RhcnREcmF3KGNsZWFyID0gdHJ1ZSkge1xyXG4gICAgICAgIGlmIChjbGVhcikge1xyXG4gICAgICAgICAgICBpZih0aGlzLmJvdW5kcykge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5zb25hZ3JhbUNhbnZhcy5zdHlsZS5sZWZ0ID0gTWF0aC5yb3VuZCh0aGlzLmJvdW5kcy5wb3NpdGlvbi5sZWZ0KS50b1N0cmluZygpICsgJ3B4JztcclxuICAgICAgICAgICAgICAgIGxldCBpbnRXID0gTWF0aC5yb3VuZCh0aGlzLmJvdW5kcy5kaW1lbnNpb24ud2lkdGgpXHJcbiAgICAgICAgICAgICAgICBsZXQgaW50SCA9IE1hdGgucm91bmQodGhpcy5ib3VuZHMuZGltZW5zaW9uLmhlaWdodClcclxuICAgICAgICAgICAgICAgIHRoaXMuc29uYWdyYW1DYW52YXMud2lkdGggPSBpbnRXO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5zb25hZ3JhbUNhbnZhcy5oZWlnaHQgPSBpbnRIO1xyXG5cclxuICAgICAgICAgICAgICAgIGxldCBnID0gdGhpcy5zb25hZ3JhbUNhbnZhcy5nZXRDb250ZXh0KFwiMmRcIik7XHJcbiAgICAgICAgICAgICAgICBpZiAoZykge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vZy5jbGVhclJlY3QoMCwgMCx3LCBoKTtcclxuICAgICAgICAgICAgICAgICAgICBnLmZpbGxTdHlsZSA9IFwid2hpdGVcIjtcclxuICAgICAgICAgICAgICAgICAgICBnLmZpbGxSZWN0KDAsIDAsIGludFcsIGludEgpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMuc3RhcnRSZW5kZXIoKTtcclxuICAgICAgICB0aGlzLmRyYXdDdXJzb3JMYXllcigpXHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBzdGFydFJlbmRlcigpIHtcclxuICAgICAgLy9jb25zb2xlLmRlYnVnKFwiU29uYWdyYW0gc3RhcnQgcmVuZGVyLi4uXCIpO1xyXG4gICAgICAgIGlmICh0aGlzLndvcmtlcikge1xyXG4gICAgICAgICAgICB0aGlzLndvcmtlci50ZXJtaW5hdGUoKTtcclxuICAgICAgICAgICAgdGhpcy53b3JrZXIgPSBudWxsO1xyXG4gICAgICAgIH1cclxuICAgICAgaWYodGhpcy5yYUFzU3Vic2Mpe1xyXG4gICAgICAgIHRoaXMucmFBc1N1YnNjLnVuc3Vic2NyaWJlKCk7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKHRoaXMuX2F1ZGlvRGF0YUhvbGRlcikge1xyXG4gICAgICAgIHRoaXMuX2F1ZGlvRGF0YUhvbGRlci5hZGRPblJlYWR5TGlzdGVuZXIoKCk9PiB7XHJcbiAgICAgICAgICBpZiAodGhpcy5fYXVkaW9EYXRhSG9sZGVyICYmIHRoaXMuYm91bmRzICYmIHRoaXMuYm91bmRzLmRpbWVuc2lvbikge1xyXG4gICAgICAgICAgICBsZXQgdyA9IE1hdGgucm91bmQodGhpcy5ib3VuZHMuZGltZW5zaW9uLndpZHRoKTtcclxuICAgICAgICAgICAgbGV0IGggPSBNYXRoLnJvdW5kKHRoaXMuYm91bmRzLmRpbWVuc2lvbi5oZWlnaHQpO1xyXG4gICAgICAgICAgICBsZXQgdncgPSBNYXRoLnJvdW5kKHRoaXMudmlydHVhbERpbWVuc2lvbi53aWR0aCk7XHJcblxyXG4gICAgICAgICAgICBpZiAodyA+IDAgJiYgaCA+IDAgJiYgdncgPiAwKSB7XHJcblxyXG4gICAgICAgICAgICAgIHRoaXMud29ya2VyID0gbmV3IFdvcmtlcih0aGlzLndvcmtlclVSTCk7XHJcbiAgICAgICAgICAgICAgLy90aGlzLndvID0gbmV3IFdvcmtlcignLi93b3JrZXIvc29uYWdyYW0ud29ya2VyJywgeyB0eXBlOiBgbW9kdWxlYCB9KTtcclxuXHJcbiAgICAgICAgICAgICAgbGV0IGNocyA9IHRoaXMuX2F1ZGlvRGF0YUhvbGRlci5udW1iZXJPZkNoYW5uZWxzO1xyXG4gICAgICAgICAgICAgIGxldCB2dyA9IE1hdGgucm91bmQodGhpcy52aXJ0dWFsRGltZW5zaW9uLndpZHRoKTtcclxuXHJcbiAgICAgICAgICAgICAgbGV0IGZyYW1lTGVuZ3RoID0gdGhpcy5fYXVkaW9EYXRhSG9sZGVyLmZyYW1lTGVuO1xyXG4gICAgICAgICAgICAgIGxldCBmcmFtZXNQZXJQaXhlbCA9IE1hdGguY2VpbChmcmFtZUxlbmd0aCAvIHZ3KTtcclxuICAgICAgICAgICAgICBsZXQgbGVmdFBvcyA9IE1hdGgucm91bmQodGhpcy5ib3VuZHMucG9zaXRpb24ubGVmdCk7XHJcbiAgICAgICAgICAgICAgbGV0IHJlbmRlclBvcyA9IGxlZnRQb3M7XHJcbiAgICAgICAgICAgICAgbGV0IHJhQXMgPSB0aGlzLl9hdWRpb0RhdGFIb2xkZXIucmFuZG9tQWNjZXNzQXVkaW9TdHJlYW0oKTtcclxuXHJcbiAgICAgICAgICAgICAgbGV0IGF1ZGlvQnVmZmVyOiBBdWRpb0J1ZmZlciB8IG51bGwgPSBudWxsO1xyXG4gICAgICAgICAgICAgIGxldCBhdWRpb1NvdXJjZSA9IHRoaXMuX2F1ZGlvRGF0YUhvbGRlci5hdWRpb1NvdXJjZTtcclxuICAgICAgICAgICAgICBpZiAoYXVkaW9Tb3VyY2UgaW5zdGFuY2VvZiBBdWRpb0J1ZmZlclNvdXJjZSkge1xyXG4gICAgICAgICAgICAgICAgYXVkaW9CdWZmZXIgPSBhdWRpb1NvdXJjZS5hdWRpb0J1ZmZlcjtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgLy9sZXQgYXJyYXlBdWRpb0J1ZmZlcj10aGlzLl9hdWRpb0RhdGFIb2xkZXIuYXJyYXlCdWZmZXI7XHJcbiAgICAgICAgICAgICAgbGV0IGFyckFiQnVmOiBGbG9hdDMyQXJyYXlbXSB8IG51bGw7XHJcbiAgICAgICAgICAgICAgbGV0IGFkYSA9IG5ldyBBcnJheTxBcnJheUJ1ZmZlcj4oY2hzKTtcclxuICAgICAgICAgICAgICAvLyBmb3IobGV0IGNoPTA7Y2g8Y2hzO2NoKyspIHtcclxuICAgICAgICAgICAgICAvLyAgIGFkYVtjaF0gPSBuZXcgRmxvYXQzMkFycmF5KHRoaXMuZGZ0U2l6ZSk7XHJcbiAgICAgICAgICAgICAgLy8gfVxyXG4gICAgICAgICAgICAgIGxldCBpbWdEYXRhOiBVaW50OENsYW1wZWRBcnJheTtcclxuICAgICAgICAgICAgICBsZXQgbWF4UHNkID0gLUluZmluaXR5O1xyXG4gICAgICAgICAgICAgIGxldCBub3JlbmRlciA9IHRydWU7XHJcblxyXG4gICAgICAgICAgICAgIGlmICh0aGlzLndvcmtlcikge1xyXG4gICAgICAgICAgICAgICAgdGhpcy53b3JrZXIub25tZXNzYWdlID0gKG1lKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgIGlmICh0cnVlID09PSBtZS5kYXRhLnRlcm1pbmF0ZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCBkcmF3SW1nRGF0YTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoaW1nRGF0YSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgZHJhd0ltZ0RhdGEgPSBpbWdEYXRhO1xyXG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICBkcmF3SW1nRGF0YSA9IG1lLmRhdGEuaW1nRGF0YTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kcmF3UmVuZGVyZWQodywgaCwgZHJhd0ltZ0RhdGEpO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLndvcmtlcikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgdGhpcy53b3JrZXIudGVybWluYXRlKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMud29ya2VyID0gbnVsbDtcclxuICAgICAgICAgICAgICAgICAgICByYUFzLmNsb3NlKCk7XHJcbiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIC8vIHNldCByZW5kZXJlZCB2ZXJ0aWNhbCB2YWx1ZXMgb2Ygb25lIHBpeGVsIG9mIHRpbWVzY2FsZVxyXG4gICAgICAgICAgICAgICAgICAgIC8vbGV0IGRhdGFQb3MgPSByZW5kZXJQb3MgKiBoICogNDtcclxuICAgICAgICAgICAgICAgICAgICBpZiAobm9yZW5kZXIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgIGlmIChtZS5kYXRhLm1heFBzZCA+IG1heFBzZCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXhQc2QgPSBtZS5kYXRhLm1heFBzZDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy9jb25zb2xlLmRlYnVnKFwibmV3IG1heFBzZDogXCIrbWF4UHNkKTtcclxuICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgbGV0IGNoSCA9IE1hdGgucm91bmQoaCAvIGNocyk7XHJcbiAgICAgICAgICAgICAgICAgICAgICBsZXQgaWRwID0gbWUuZGF0YS5sIC0gbGVmdFBvcztcclxuICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGNoID0gMDsgY2ggPCBjaHM7IGNoKyspIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgeSA9IDA7IHkgPCBjaEg7IHkrKykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBweSA9IGNoSCAtIHk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGRhdGFQb3MgPSAoKCgoY2ggKiBjaEgpICsgcHkpICogdykgKyBpZHApICogNDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgbWVQb3MgPSAoKGNoICogY2hIKSArIHB5KSAqIDQ7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy9sZXQgbGFzdFBvcyA9IGRhdGFQb3MgKyBtZS5kYXRhLmltZ0RhdGEubGVuZ3RoO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vaWYgKGxhc3RQb3MgPCBpbWdEYXRhLmxlbmd0aCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNldCBvbmUgcGl4ZWxcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaW1nRGF0YVtkYXRhUG9zXSA9IG1lLmRhdGEuaW1nRGF0YVttZVBvc107XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaW1nRGF0YVtkYXRhUG9zICsgMV0gPSBtZS5kYXRhLmltZ0RhdGFbbWVQb3MgKyAxXTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICBpbWdEYXRhW2RhdGFQb3MgKyAyXSA9IG1lLmRhdGEuaW1nRGF0YVttZVBvcyArIDJdO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGltZ0RhdGFbZGF0YVBvcyArIDNdID0gbWUuZGF0YS5pbWdEYXRhW21lUG9zICsgM107XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy99IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vY29uc29sZS5lcnJvcihcIk91dCBvZiByYW5nZTogXCIgKyBkYXRhUG9zICsgXCIrXCIgKyBtZS5kYXRhLmltZ0RhdGEubGVuZ3RoICsgXCI+PVwiICsgaW1nRGF0YS5sZW5ndGgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5fYXVkaW9EYXRhSG9sZGVyICYmIGFyckFiQnVmICYmIHRoaXMud29ya2VyKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAvLyBwcm9jZWVkIHdpdGggbmV4dCBwaXhlbFxyXG4gICAgICAgICAgICAgICAgICAgICAgcmVuZGVyUG9zKys7XHJcbiAgICAgICAgICAgICAgICAgICAgICAvL2NvbnNvbGUuZGVidWcoXCJSZW5kZXIgcG9zOiBcIityZW5kZXJQb3MpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgIGxldCB0ZXJtaW5hdGUgPSBmYWxzZTtcclxuICAgICAgICAgICAgICAgICAgICAgIGxldCB3aW5kb3dFbmQgPSByZW5kZXJQb3MgPj0gbGVmdFBvcyArIHc7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgaWYgKHdpbmRvd0VuZCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobm9yZW5kZXIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBwaGFzZSB0d286IHJlbmRlcmluZ1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIG5vcmVuZGVyID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gc3RhcnQgZnJvbSBiZWdpbm5pbmdcclxuICAgICAgICAgICAgICAgICAgICAgICAgICByZW5kZXJQb3MgPSBsZWZ0UG9zO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vY29uc29sZS5kZWJ1ZyhcIm5vdyByZW5kZXJpbmc6IG1heFBzZDogXCIrbWF4UHNkKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0ZXJtaW5hdGUgcmVuZGVyIHBoYXNlXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgdGVybWluYXRlID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgIGxldCBsZWZ0RnJhbWVQb3MgPSBNYXRoLmZsb29yKGZyYW1lTGVuZ3RoICogcmVuZGVyUG9zIC8gdncpIC0gdGhpcy5kZnRTaXplIC8gMjtcclxuICAgICAgICAgICAgICAgICAgICAgIGlmIChsZWZ0RnJhbWVQb3MgPCAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxlZnRGcmFtZVBvcyA9IDA7XHJcbiAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAvL2xldCBhZGEgPSBuZXcgQXJyYXk8QXJyYXlCdWZmZXI+KGNocyk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgLy9jb25zb2xlLmRlYnVnKFwiUmVuZGVyIHBvczogXCIrcmVuZGVyUG9zK1wiIGxlZnRGcmFtZVBvczogXCIrbGVmdEZyYW1lUG9zKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRlcm1pbmF0ZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5fYXVkaW9EYXRhSG9sZGVyKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy9sZXQgcmVhZCA9IHRoaXMuX2F1ZGlvRGF0YUhvbGRlci5mcmFtZXMobGVmdEZyYW1lUG9zLCB0aGlzLmRmdFNpemUsIGFyckFiQnVmKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJhQXNTdWJzYyA9IHJhQXMuZnJhbWVzT2JzKGxlZnRGcmFtZVBvcywgdGhpcy5kZnRTaXplLCBhcnJBYkJ1Zikuc3Vic2NyaWJlKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXh0OiAocmVhZCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhcnJBYkJ1ZiAmJiB0aGlzLndvcmtlcikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlYWQgPCB0aGlzLmRmdFNpemUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gemVybyBwYWRkaW5nXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGNoID0gMDsgY2ggPCBjaHM7IGNoKyspIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCB6cCA9IHJlYWQ7IHpwIDwgdGhpcy5kZnRTaXplOyB6cCsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcnJBYkJ1ZltjaF1benBdID0gMDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGNoID0gMDsgY2ggPCBjaHM7IGNoKyspIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTmVlZCBhIGNvcHkgaGVyZSBmb3IgdGhlIHdvcmtlciwgb3RoZXJ3aXNlIHRoaXMuYXVkaW9EYXRhIGlzIG5vdCBhY2Nlc3NpYmxlIGFmdGVyIHBvc3RpbmcgdG8gdGhlIHdvcmtlclxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvL2FkYVtjaF0gPSBhcnJBYkJ1ZltjaF0uYnVmZmVyLnNsaWNlKDApO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBhcnJBYkJ1ZkNoID0gYXJyQWJCdWZbY2hdO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBhZExlbiA9IGFyckFiQnVmQ2guYnVmZmVyLmJ5dGVMZW5ndGg7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghYWRhW2NoXSB8fCBhZGFbY2hdLmJ5dGVMZW5ndGggIT09IGFkTGVuKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWRhW2NoXSA9IG5ldyBBcnJheUJ1ZmZlcihhZExlbik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGZBZGFDaCA9IG5ldyBGbG9hdDMyQXJyYXkoYWRhW2NoXSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZBZGFDaC5zZXQoYXJyQWJCdWZbY2hdKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLndvcmtlci5wb3N0TWVzc2FnZSh7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1ZGlvRGF0YTogYWRhLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdWRpb0RhdGFPZmZzZXQ6IGxlZnRGcmFtZVBvcyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbDogcmVuZGVyUG9zLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3OiBtZS5kYXRhLncsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGg6IGgsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZ3OiB2dyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hzOiBjaHMsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZyYW1lTGVuZ3RoOiBmcmFtZUxlbmd0aCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGZ0U2l6ZTogdGhpcy5kZnRTaXplLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhQc2Q6IG1heFBzZCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9yZW5kZXI6IG5vcmVuZGVyLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXJtaW5hdGU6IHRlcm1pbmF0ZVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwgYWRhKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yOiAoZXJyKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIlNvbmFncmFtOiBFcnJvciByZWFkaW5nIGF1ZGlvIGRhdGE6IFwiICsgZXJyKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIClcclxuXHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBjaCA9IDA7IGNoIDwgY2hzOyBjaCsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgYWRhW2NoXSA9IG5ldyBBcnJheUJ1ZmZlcigwKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLndvcmtlci5wb3N0TWVzc2FnZSh7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgYXVkaW9EYXRhOiBhZGEsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgYXVkaW9EYXRhT2Zmc2V0OiBsZWZ0RnJhbWVQb3MsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgbDogcmVuZGVyUG9zLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHc6IG1lLmRhdGEudyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICBoOiBoLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHZ3OiB2dyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICBjaHM6IGNocyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICBmcmFtZUxlbmd0aDogZnJhbWVMZW5ndGgsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZGZ0U2l6ZTogdGhpcy5kZnRTaXplLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIG1heFBzZDogbWF4UHNkLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIG5vcmVuZGVyOiBub3JlbmRlcixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXJtaW5hdGU6IHRlcm1pbmF0ZVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9LCBhZGEpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICBpZiAoYXVkaW9CdWZmZXIgJiYgYXVkaW9CdWZmZXIubGVuZ3RoICogYXVkaW9CdWZmZXIubnVtYmVyT2ZDaGFubmVscyA8IEF1ZGlvQ2FudmFzTGF5ZXJDb21wb25lbnQuRU5BQkxFX1NUUkVBTUlOR19OVU1CRVJfT0ZfU0FNUExFU19USFJFU0hPTEQpIHtcclxuICAgICAgICAgICAgICAgIGxldCBhZGEgPSBuZXcgQXJyYXk8QXJyYXlCdWZmZXI+KGNocyk7XHJcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBjaCA9IDA7IGNoIDwgY2hzOyBjaCsrKSB7XHJcbiAgICAgICAgICAgICAgICAgIC8vIE5lZWQgYSBjb3B5IGhlcmUgZm9yIHRoZSB3b3JrZXIsIG90aGVyd2lzZSB0aGlzLmF1ZGlvRGF0YSBpcyBub3QgYWNjZXNzaWJsZSBhZnRlciBwb3N0aW5nIHRvIHRoZSB3b3JrZXJcclxuICAgICAgICAgICAgICAgICAgYWRhW2NoXSA9IGF1ZGlvQnVmZmVyLmdldENoYW5uZWxEYXRhKGNoKS5idWZmZXIuc2xpY2UoMCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAvL2xldCBzdGFydCA9IERhdGUubm93KCk7XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMubWFya2VyQ2FudmFzKSB7XHJcbiAgICAgICAgICAgICAgICAgIGxldCBnID0gdGhpcy5tYXJrZXJDYW52YXMuZ2V0Q29udGV4dChcIjJkXCIpO1xyXG4gICAgICAgICAgICAgICAgICBpZiAoZykge1xyXG4gICAgICAgICAgICAgICAgICAgIGcuZmlsbFRleHQoXCJSZW5kZXJpbmcuLi5cIiwgMTAsIDIwKTtcclxuICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIHRoaXMud29ya2VyLnBvc3RNZXNzYWdlKHtcclxuICAgICAgICAgICAgICAgICAgYXVkaW9EYXRhOiBhZGEsXHJcbiAgICAgICAgICAgICAgICAgIGw6IGxlZnRQb3MsXHJcbiAgICAgICAgICAgICAgICAgIHc6IHcsXHJcbiAgICAgICAgICAgICAgICAgIGg6IGgsXHJcbiAgICAgICAgICAgICAgICAgIHZ3OiBNYXRoLnJvdW5kKHRoaXMudmlydHVhbERpbWVuc2lvbi53aWR0aCksXHJcbiAgICAgICAgICAgICAgICAgIGNoczogY2hzLFxyXG4gICAgICAgICAgICAgICAgICBmcmFtZUxlbmd0aDogZnJhbWVMZW5ndGgsXHJcbiAgICAgICAgICAgICAgICAgIGRmdFNpemU6IHRoaXMuZGZ0U2l6ZSxcclxuICAgICAgICAgICAgICAgICAgdGVybWluYXRlOiB0cnVlXHJcbiAgICAgICAgICAgICAgICB9LCBhZGEpO1xyXG4gICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBpZiAodyA+IDApIHtcclxuXHJcbiAgICAgICAgICAgICAgICAgIGlmIChmcmFtZXNQZXJQaXhlbCA+IDApIHtcclxuICAgICAgICAgICAgICAgICAgICBsZXQgYXJyU2l6ZSA9IHcgKiBoICogNDtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoYXJyU2l6ZSA8IDApIHtcclxuICAgICAgICAgICAgICAgICAgICAgIGFyclNpemUgPSAwXHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIGltZ0RhdGEgPSBuZXcgVWludDhDbGFtcGVkQXJyYXkoYXJyU2l6ZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IHJ3ID0gMTtcclxuICAgICAgICAgICAgICAgICAgICBhcnJBYkJ1ZiA9IG5ldyBBcnJheTxGbG9hdDMyQXJyYXk+KGNocyk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGNoID0gMDsgY2ggPCBjaHM7IGNoKyspIHtcclxuICAgICAgICAgICAgICAgICAgICAgIGFyckFiQnVmW2NoXSA9IG5ldyBGbG9hdDMyQXJyYXkodGhpcy5kZnRTaXplKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGxldCBsZWZ0RnJhbWVQb3MgPSBNYXRoLmZsb29yKGZyYW1lTGVuZ3RoICogcmVuZGVyUG9zIC8gdncpIC0gdGhpcy5kZnRTaXplIC8gMjtcclxuICAgICAgICAgICAgICAgICAgICBsZXQgZnJhbWVzVG9SZWFkID0gdGhpcy5kZnRTaXplO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChsZWZ0RnJhbWVQb3MgPCAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICBsZWZ0RnJhbWVQb3MgPSAwO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmRyYXdTdGF0ZVRleHQoJ0xvYWRpbmcvUmVuZGVyaW5nLi4uJyk7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yYUFzU3Vic2MgPSByYUFzLmZyYW1lc09icyhsZWZ0RnJhbWVQb3MsIGZyYW1lc1RvUmVhZCwgYXJyQWJCdWYpLnN1YnNjcmliZShcclxuICAgICAgICAgICAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbmV4dDogKHJlYWQpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXJyQWJCdWYgJiYgdGhpcy53b3JrZXIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZWFkIDwgdGhpcy5kZnRTaXplKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHplcm8gcGFkZGluZ1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBjaCA9IDA7IGNoIDwgY2hzOyBjaCsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgenAgPSByZWFkOyB6cCA8IHRoaXMuZGZ0U2l6ZTsgenArKykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJyQWJCdWZbY2hdW3pwXSA9IDA7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBjaCA9IDA7IGNoIDwgY2hzOyBjaCsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGFyckFiQnVmQ2ggPSBhcnJBYkJ1ZltjaF07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGFkTGVuID0gYXJyQWJCdWZDaC5idWZmZXIuYnl0ZUxlbmd0aDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFhZGFbY2hdIHx8IGFkYVtjaF0uYnl0ZUxlbmd0aCAhPT0gYWRMZW4pIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZGFbY2hdID0gbmV3IEFycmF5QnVmZmVyKGFkTGVuKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgZkFkYUNoID0gbmV3IEZsb2F0MzJBcnJheShhZGFbY2hdKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZkFkYUNoLnNldChhcnJBYkJ1ZltjaF0pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMud29ya2VyLnBvc3RNZXNzYWdlKHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbDogcmVuZGVyUG9zLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3OiBydyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaDogaCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdnc6IHZ3LFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaHM6IGNocyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnJhbWVMZW5ndGg6IGZyYW1lTGVuZ3RoLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdWRpb0RhdGE6IGFkYSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXVkaW9EYXRhT2Zmc2V0OiBsZWZ0RnJhbWVQb3MsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRmdFNpemU6IHRoaXMuZGZ0U2l6ZSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9yZW5kZXI6IG5vcmVuZGVyLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXJtaW5hdGU6IGZhbHNlXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LCBhZGEpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3I6IChlcnIpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiU29uYWdyYW06IEVycm9yIHJlYWRpbmcgYXVkaW8gZGF0YTogXCIgKyBlcnIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgIGlmICh0aGlzLmJvdW5kcyAmJiB0aGlzLmJvdW5kcy5kaW1lbnNpb24pIHtcclxuICAgICAgICAgIGxldCB3ID0gTWF0aC5yb3VuZCh0aGlzLmJvdW5kcy5kaW1lbnNpb24ud2lkdGgpO1xyXG4gICAgICAgICAgbGV0IGggPSBNYXRoLnJvdW5kKHRoaXMuYm91bmRzLmRpbWVuc2lvbi5oZWlnaHQpO1xyXG4gICAgICAgICAgbGV0IGcgPSB0aGlzLnNvbmFncmFtQ2FudmFzLmdldENvbnRleHQoXCIyZFwiKTtcclxuICAgICAgICAgIGlmIChnKSB7XHJcbiAgICAgICAgICAgIGcuY2xlYXJSZWN0KDAsIDAsIHcsIGgpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGRyYXdSZW5kZXJlZCh3Om51bWJlcixoOm51bWJlcixpbWdEYXRhOlVpbnQ4Q2xhbXBlZEFycmF5KSB7XHJcbiAgICAgICAgaWYgKHRoaXMuc29uYWdyYW1DYW52YXMpIHtcclxuICAgICAgICAgICAgdGhpcy5zb25hZ3JhbUNhbnZhcy53aWR0aCA9IHc7XHJcbiAgICAgICAgICAgIHRoaXMuc29uYWdyYW1DYW52YXMuaGVpZ2h0ID0gaDtcclxuICAgICAgICAgICAgbGV0IGcgPSB0aGlzLnNvbmFncmFtQ2FudmFzLmdldENvbnRleHQoXCIyZFwiKTtcclxuICAgICAgICAgICAgaWYgKGcpIHtcclxuICAgICAgICAgICAgICAgIGlmICh3ID4gMCAmJiBoID4gMCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCBnSW1nRGF0YSA9IGcuY3JlYXRlSW1hZ2VEYXRhKHcsIGgpO1xyXG4gICAgICAgICAgICAgICAgICAgIGdJbWdEYXRhLmRhdGEuc2V0KGltZ0RhdGEpO1xyXG4gICAgICAgICAgICAgICAgICAgIGcucHV0SW1hZ2VEYXRhKGdJbWdEYXRhLCAwLCAwKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLmRyYXdCZygpO1xyXG4gICAgICAgIHRoaXMuZHJhd1BsYXlQb3NpdGlvbigpO1xyXG4gICAgfVxyXG5cclxuLy8gICAgIC8vIHN5bmNocm9ub3VzIGRyYXcgKG5vdCB1c2VkIGFueW1vcmUpXHJcbi8vICAgcmVkcmF3KCkge1xyXG4vL1xyXG4vLyAgICAgbGV0IGcgPSB0aGlzLnNvbmFncmFtQ2FudmFzLmdldENvbnRleHQoXCIyZFwiKTtcclxuLy9cclxuLy8gICAgIGxldCB3ID0gdGhpcy5zb25hZ3JhbUNhbnZhcy53aWR0aDtcclxuLy8gICAgIGxldCBoID0gdGhpcy5zb25hZ3JhbUNhbnZhcy5oZWlnaHQ7XHJcbi8vICAgICBpZiAoZykge1xyXG4vLyAgICAgICBnLmNsZWFyUmVjdCgwLCAwLCB3LCBoKTtcclxuLy8gICAgICAgZy5maWxsU3R5bGUgPSBcIndoaXRlXCI7XHJcbi8vICAgICAgIGcuZmlsbFJlY3QoMCwgMCwgdywgaCk7XHJcbi8vICAgICAgIGlmICh0aGlzLl9hdWRpb0RhdGFIb2xkZXIpIHtcclxuLy8gICAgICAgICBsZXQgc3BlY3RTaXplID0gTWF0aC5mbG9vcih0aGlzLmRmdFNpemUgLyAyKVxyXG4vLyAgICAgICAgIGxldCBjaHMgPSB0aGlzLl9hdWRpb0RhdGFIb2xkZXIubnVtYmVyT2ZDaGFubmVscztcclxuLy8gICAgICAgICBsZXQgY2hIID0gaCAvIGNocztcclxuLy9cclxuLy8gICAgICAgICBsZXQgZnJhbWVMZW5ndGggPSB0aGlzLl9hdWRpb0RhdGFIb2xkZXIuZnJhbWVMZW47XHJcbi8vXHJcbi8vICAgICAgICAgbGV0IGZyYW1lc1BlclBpeGVsID0gZnJhbWVMZW5ndGggLyB3O1xyXG4vLyAgICAgICAgIGxldCB5ID0gMDtcclxuLy8gICAgICAgICBsZXQgYXVkaW9CdWZmZXI6QXVkaW9CdWZmZXJ8bnVsbD1udWxsO1xyXG4vLyAgICAgICAgIGxldCBhdWRpb1NvdXJjZT10aGlzLl9hdWRpb0RhdGFIb2xkZXIuYXVkaW9Tb3VyY2U7XHJcbi8vICAgICAgICAgaWYoYXVkaW9Tb3VyY2UgaW5zdGFuY2VvZiBBdWRpb0J1ZmZlclNvdXJjZSl7XHJcbi8vICAgICAgICAgICBhdWRpb0J1ZmZlcj1hdWRpb1NvdXJjZS5hdWRpb0J1ZmZlcjtcclxuLy8gICAgICAgICB9XHJcbi8vXHJcbi8vICAgICAgICAgaWYoYXVkaW9CdWZmZXIpIHtcclxuLy8gICAgICAgICAgIGxldCBiID0gbmV3IEZsb2F0MzJBcnJheSh0aGlzLmRmdFNpemUpXHJcbi8vXHJcbi8vICAgICAgICAgICBsZXQgc29uYSA9IG5ldyBBcnJheTxBcnJheTxGbG9hdDMyQXJyYXk+PihjaHMpO1xyXG4vLyAgICAgICAgICAgbGV0IG1heCA9IDA7XHJcbi8vICAgICAgICAgICBsZXQgbWF4UHNkID0gLUluZmluaXR5O1xyXG4vLyAgICAgICAgICAgZm9yIChsZXQgY2ggPSAwOyBjaCA8IGNoczsgY2grKykge1xyXG4vLyAgICAgICAgICAgICBsZXQgeCA9IDA7XHJcbi8vICAgICAgICAgICAgIHNvbmFbY2hdID0gbmV3IEFycmF5PEZsb2F0MzJBcnJheT4odyk7XHJcbi8vXHJcbi8vICAgICAgICAgICAgIGxldCBjaERhdGEgPSBhdWRpb0J1ZmZlci5nZXRDaGFubmVsRGF0YShjaCk7XHJcbi8vICAgICAgICAgICAgIC8vIFRPRE8gY2VudGVyIGJ1ZmZlclxyXG4vL1xyXG4vLyAgICAgICAgICAgICBsZXQgZnJhbWVQb3MgPSAwO1xyXG4vLyAgICAgICAgICAgICBmb3IgKGxldCBwaWkgPSAwOyBwaWkgPCB3OyBwaWkrKykge1xyXG4vLyAgICAgICAgICAgICAgIGZyYW1lUG9zID0gTWF0aC5yb3VuZChwaWkgKiBmcmFtZXNQZXJQaXhlbCk7XHJcbi8vICAgICAgICAgICAgICAgLy8gY2FsY3VsYXRlIERGVCBhdCBwaXhlbCBwb3NpdGlvblxyXG4vLyAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5kZnRTaXplOyBpKyspIHtcclxuLy8gICAgICAgICAgICAgICAgIGxldCBjaERhdCA9IGNoRGF0YVtmcmFtZVBvcyArIGldO1xyXG4vLyAgICAgICAgICAgICAgICAgYltpXSA9IGNoRGF0O1xyXG4vLyAgICAgICAgICAgICAgIH1cclxuLy8gICAgICAgICAgICAgICBsZXQgc3BlY3RyID0gdGhpcy5kZnQucHJvY2Vzc1JlYWxNYWduaXR1ZGUoYik7XHJcbi8vICAgICAgICAgICAgICAgc29uYVtjaF1bcGlpXSA9IHNwZWN0cjtcclxuLy8gICAgICAgICAgICAgICAvLyBAdHMtaWdub3JlXHJcbi8vICAgICAgICAgICAgICAgbGV0IHBNYXggPSBNYXRoLm1heC5hcHBseShudWxsLCBzcGVjdHIpO1xyXG4vLyAgICAgICAgICAgICAgIGlmIChwTWF4ID4gbWF4KSB7XHJcbi8vICAgICAgICAgICAgICAgICBtYXggPSBwTWF4O1xyXG4vLyAgICAgICAgICAgICAgIH1cclxuLy9cclxuLy8gICAgICAgICAgICAgICBmb3IgKGxldCBzID0gMDsgcyA8IHNwZWN0U2l6ZTsgcysrKSB7XHJcbi8vICAgICAgICAgICAgICAgICBsZXQgcHNkID0gKDIgKiBNYXRoLnBvdyhzcGVjdHJbc10sIDIpKSAvIHNwZWN0U2l6ZTtcclxuLy8gICAgICAgICAgICAgICAgIGlmIChwc2QgPiBtYXhQc2QpIHtcclxuLy8gICAgICAgICAgICAgICAgICAgbWF4UHNkID0gcHNkO1xyXG4vLyAgICAgICAgICAgICAgICAgfVxyXG4vLyAgICAgICAgICAgICAgIH1cclxuLy8gICAgICAgICAgICAgfVxyXG4vLyAgICAgICAgICAgfVxyXG4vLyAgICAgICAgICAgLy9jb25zb2xlLmxvZyhcIm1heDogXCIsIG1heCk7XHJcbi8vICAgICAgICAgICBtYXhQc2QgPSAoMiAqIE1hdGgucG93KG1heCwgMikpIC8gc3BlY3RTaXplO1xyXG4vLyAgICAgICAgICAgZm9yIChsZXQgY2ggPSAwOyBjaCA8IGNoczsgY2grKykge1xyXG4vL1xyXG4vLyAgICAgICAgICAgICBsZXQgZnJhbWVQb3MgPSAwO1xyXG4vLyAgICAgICAgICAgICBmb3IgKGxldCBwaWkgPSAwOyBwaWkgPCB3OyBwaWkrKykge1xyXG4vLyAgICAgICAgICAgICAgIGZyYW1lUG9zID0gcGlpICogZnJhbWVzUGVyUGl4ZWw7XHJcbi8vXHJcbi8vICAgICAgICAgICAgICAgZm9yIChsZXQgeSA9IDA7IHkgPCBoOyB5KyspIHtcclxuLy8gICAgICAgICAgICAgICAgIGxldCBmcmVxSWR4ID0gTWF0aC5yb3VuZCh5ICogc3BlY3RTaXplIC8gaCk7XHJcbi8vXHJcbi8vICAgICAgICAgICAgICAgICAvLyBjYWxjdWxhdGUgdGhlIG9uZSBzaWRlZCBwb3dlciBzcGVjdHJhbCBkZW5zaXR5IFBTRCAoZiwgdCkgaW4gUGEyL0h6XHJcbi8vICAgICAgICAgICAgICAgICAvLyBQU0QoZikgcHJvcG9ydGlvbmFsIHRvIDJ8WChmKXwyIC8gKHQyIC0gdDEpXHJcbi8vICAgICAgICAgICAgICAgICBsZXQgdmFsID0gc29uYVtjaF1bcGlpXVtmcmVxSWR4XTtcclxuLy8gICAgICAgICAgICAgICAgIGxldCBwc2QgPSAoMiAqIE1hdGgucG93KHZhbCwgMikpIC8gc3BlY3RTaXplO1xyXG4vL1xyXG4vLyAgICAgICAgICAgICAgICAgLy8gQ2FsY3VsYXRlIGxvZ2FyaXRobWljXHJcbi8vICAgICAgICAgICAgICAgICBsZXQgcHNkTG9nID0gRFNQVXRpbHMudG9MZXZlbEluREIocHNkIC8gbWF4UHNkKTtcclxuLy8gICAgICAgICAgICAgICAgIGxldCBkeW5SYW5nZUluRGIgPSA3MDtcclxuLy8gICAgICAgICAgICAgICAgIGxldCBzY2FsZWRWYWwgPSAocHNkTG9nICsgZHluUmFuZ2VJbkRiKSAvIGR5blJhbmdlSW5EYjtcclxuLy9cclxuLy8gICAgICAgICAgICAgICAgIGlmIChzY2FsZWRWYWwgPiAxKVxyXG4vLyAgICAgICAgICAgICAgICAgICBzY2FsZWRWYWwgPSAxO1xyXG4vLyAgICAgICAgICAgICAgICAgaWYgKHNjYWxlZFZhbCA8IDApIHtcclxuLy8gICAgICAgICAgICAgICAgICAgc2NhbGVkVmFsID0gMDtcclxuLy8gICAgICAgICAgICAgICAgIH1cclxuLy8gICAgICAgICAgICAgICAgIGxldCByZ2JWYWwgPSAoMjU1ICogc2NhbGVkVmFsKTtcclxuLy8gICAgICAgICAgICAgICAgIGlmIChyZ2JWYWwgPCAwKSB7XHJcbi8vIC8vXHRcdFx0XHRcdFx0XHRTeXN0ZW0ub3V0LnByaW50bG4oXCJOZWcgUkdCIHZhbDogXCIrcmdiVmFsKTtcclxuLy8gICAgICAgICAgICAgICAgICAgcmdiVmFsID0gMDtcclxuLy8gICAgICAgICAgICAgICAgIH1cclxuLy8gICAgICAgICAgICAgICAgIGlmIChyZ2JWYWwgPiAyNTUpIHtcclxuLy8gICAgICAgICAgICAgICAgICAgcmdiVmFsID0gMjU1O1xyXG4vLyAgICAgICAgICAgICAgICAgfVxyXG4vLyAgICAgICAgICAgICAgICAgcmdiVmFsID0gMjU1IC0gcmdiVmFsO1xyXG4vLyAgICAgICAgICAgICAgICAgbGV0IGNvbG9yU3RyID0gQ1NTVXRpbHMudG9Db2xvclN0cmluZyhyZ2JWYWwsIHJnYlZhbCwgcmdiVmFsKTtcclxuLy8gICAgICAgICAgICAgICAgIGcuZmlsbFN0eWxlID0gY29sb3JTdHI7XHJcbi8vICAgICAgICAgICAgICAgICBnLmZpbGxSZWN0KHBpaSwgY2hIIC0geSwgMSwgMSk7XHJcbi8vICAgICAgICAgICAgICAgfVxyXG4vLyAgICAgICAgICAgICB9XHJcbi8vICAgICAgICAgICB9XHJcbi8vICAgICAgICAgICB0aGlzLmRyYXdQbGF5UG9zaXRpb24oKTtcclxuLy8gICAgICAgICB9ZWxzZXtcclxuLy8gICAgICAgICAgIHRocm93IEVycm9yKFwiUmVkcmF3IG9ubHkgc3VwcG9ydGVkIHdpdGggYXVkaW8gYnVmZmVyLlwiKVxyXG4vLyAgICAgICAgIH1cclxuLy8gICAgICAgfVxyXG4vLyAgICAgfVxyXG4vLyAgIH1cclxuLy9cclxuXHJcbiAgICBzZXREYXRhKGF1ZGlvRGF0YTogQXVkaW9EYXRhSG9sZGVyIHwgbnVsbCkge1xyXG4gICAgICAgIHRoaXMuX2F1ZGlvRGF0YUhvbGRlciA9IGF1ZGlvRGF0YTtcclxuICAgICAgICB0aGlzLnBsYXlGcmFtZVBvc2l0aW9uID0gMDtcclxuICAgIH1cclxuXHJcbn1cclxuXHJcbiJdfQ==
|