speechrecorderng 3.6.0 → 3.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2022/lib/action/action.mjs +73 -0
- package/{esm2020 → esm2022}/lib/audio/array_audio_buffer.mjs +163 -163
- package/{esm2020 → esm2022}/lib/audio/array_audio_buffer_input_stream.mjs +85 -85
- package/{esm2020 → esm2022}/lib/audio/array_audio_buffer_random_access_stream.mjs +15 -15
- package/esm2022/lib/audio/audio_data_holder.mjs +264 -0
- package/{esm2020 → esm2022}/lib/audio/audio_display.mjs +93 -93
- package/{esm2020 → esm2022}/lib/audio/audio_player.mjs +213 -213
- package/esm2022/lib/audio/capture/capture.mjs +855 -0
- package/esm2022/lib/audio/context.mjs +79 -0
- package/{esm2020 → esm2022}/lib/audio/dsp/level_measure.mjs +515 -515
- package/{esm2020 → esm2022}/lib/audio/format.mjs +16 -16
- package/esm2022/lib/audio/impl/wavformat.mjs +6 -0
- package/{esm2020 → esm2022}/lib/audio/impl/wavreader.mjs +133 -133
- package/esm2022/lib/audio/impl/wavwriter.mjs +105 -0
- package/esm2022/lib/audio/inddb_audio_buffer.mjs +508 -0
- package/{esm2020 → esm2022}/lib/audio/io/stream.mjs +58 -58
- package/esm2022/lib/audio/net_audio_buffer.mjs +293 -0
- package/{esm2020 → esm2022}/lib/audio/persistor.mjs +80 -80
- package/{esm2020 → esm2022}/lib/audio/playback/array_audio_buffer_source_node.mjs +125 -125
- package/esm2022/lib/audio/playback/audio_source_node.mjs +18 -0
- package/esm2022/lib/audio/playback/audio_source_worklet_module_loader.mjs +167 -0
- package/{esm2020 → esm2022}/lib/audio/playback/inddb_audio_buffer_source_node.mjs +166 -166
- package/{esm2020 → esm2022}/lib/audio/playback/net_audio_buffer_source_node.mjs +217 -217
- package/esm2022/lib/audio/playback/player.mjs +402 -0
- package/esm2022/lib/audio/ui/audio_canvas_layer_comp.mjs +347 -0
- package/{esm2020 → esm2022}/lib/audio/ui/audio_display_control.mjs +65 -65
- package/{esm2020 → esm2022}/lib/audio/ui/audio_display_scroll_pane.mjs +139 -139
- package/{esm2020 → esm2022}/lib/audio/ui/audiosignal.mjs +524 -524
- package/{esm2020 → esm2022}/lib/audio/ui/common.mjs +18 -18
- package/esm2022/lib/audio/ui/container.mjs +414 -0
- package/{esm2020 → esm2022}/lib/audio/ui/livelevel.mjs +352 -352
- package/esm2022/lib/audio/ui/scroll_pane_horizontal.mjs +11 -0
- package/esm2022/lib/audio/ui/sonagram.mjs +900 -0
- package/esm2022/lib/db/inddb.mjs +120 -0
- package/esm2022/lib/dsp/utils.mjs +48 -0
- package/{esm2020 → esm2022}/lib/io/BinaryReader.mjs +84 -84
- package/esm2022/lib/io/BinaryWriter.mjs +74 -0
- package/{esm2020 → esm2022}/lib/io/stream.mjs +258 -258
- package/{esm2020 → esm2022}/lib/math/2d/geometry.mjs +27 -27
- package/esm2022/lib/math/complex.mjs +58 -0
- package/{esm2020 → esm2022}/lib/math/dft.mjs +195 -195
- package/{esm2020 → esm2022}/lib/media/utils.mjs +13 -13
- package/esm2022/lib/net/uploader.mjs +367 -0
- package/{esm2020 → esm2022}/lib/recorder_component.mjs +64 -64
- package/esm2022/lib/speechrecorder/project/project.mjs +49 -0
- package/esm2022/lib/speechrecorder/project/project.service.mjs +64 -0
- package/{esm2020 → esm2022}/lib/speechrecorder/recording.mjs +123 -123
- package/esm2022/lib/speechrecorder/recordings/basic_recording.service.mjs +218 -0
- package/esm2022/lib/speechrecorder/recordings/recordings.service.mjs +1014 -0
- package/{esm2020 → esm2022}/lib/speechrecorder/script/script.mjs +114 -114
- package/{esm2020 → esm2022}/lib/speechrecorder/script/script.service.mjs +47 -47
- package/esm2022/lib/speechrecorder/session/audiorecorder.mjs +1179 -0
- package/esm2022/lib/speechrecorder/session/basicrecorder.mjs +668 -0
- package/esm2022/lib/speechrecorder/session/controlpanel.mjs +416 -0
- package/{esm2020 → esm2022}/lib/speechrecorder/session/item.mjs +29 -29
- package/{esm2020 → esm2022}/lib/speechrecorder/session/progress.mjs +69 -69
- package/{esm2020 → esm2022}/lib/speechrecorder/session/prompting.mjs +571 -571
- package/{esm2020 → esm2022}/lib/speechrecorder/session/recorder_combi_pane.mjs +65 -65
- package/esm2022/lib/speechrecorder/session/recording_file_cache.mjs +195 -0
- package/{esm2020 → esm2022}/lib/speechrecorder/session/recording_list.mjs +103 -103
- package/{esm2020 → esm2022}/lib/speechrecorder/session/recordingfile/recording-file-meta.component.mjs +63 -63
- package/{esm2020 → esm2022}/lib/speechrecorder/session/recordingfile/recording-file-navi.component.mjs +51 -51
- package/{esm2020 → esm2022}/lib/speechrecorder/session/recordingfile/recording-file-u-i.component.mjs +104 -104
- package/{esm2020 → esm2022}/lib/speechrecorder/session/recordingfile/recording-file-view.component.mjs +381 -381
- package/{esm2020 → esm2022}/lib/speechrecorder/session/recordingfile/recording-file.mjs +67 -67
- package/esm2022/lib/speechrecorder/session/recordingfile/recordingfile-service.mjs +288 -0
- package/{esm2020 → esm2022}/lib/speechrecorder/session/session.mjs +1 -1
- package/esm2022/lib/speechrecorder/session/session.service.mjs +69 -0
- package/{esm2020 → esm2022}/lib/speechrecorder/session/session_finished_dialog.mjs +29 -29
- package/esm2022/lib/speechrecorder/session/sessionmanager.mjs +1386 -0
- package/{esm2020 → esm2022}/lib/speechrecorder/session/warning_bar.mjs +28 -28
- package/{esm2020 → esm2022}/lib/speechrecorder/spruploader.mjs +22 -22
- package/{esm2020 → esm2022}/lib/speechrecorder/startstopsignal/startstopsignal.mjs +1 -1
- package/esm2022/lib/speechrecorder/startstopsignal/ui/simpletrafficlight.mjs +57 -0
- package/{esm2020 → esm2022}/lib/speechrecorderng.component.mjs +388 -388
- package/{esm2020 → esm2022}/lib/speechrecorderng.module.mjs +100 -100
- package/{esm2020 → esm2022}/lib/spr.config.mjs +26 -26
- package/{esm2020 → esm2022}/lib/spr.module.version.mjs +2 -2
- package/{esm2020 → esm2022}/lib/ui/canvas_layer_comp.mjs +38 -38
- package/{esm2020 → esm2022}/lib/ui/message_dialog.mjs +30 -30
- package/esm2022/lib/ui/recordingitem_display.mjs +253 -0
- package/{esm2020 → esm2022}/lib/ui/responsive_component.mjs +24 -24
- package/{esm2020 → esm2022}/lib/utils/scrollIntoViewToBottom.mjs +23 -23
- package/esm2022/lib/utils/ua-parser.mjs +190 -0
- package/esm2022/lib/utils/utils.mjs +105 -0
- package/esm2022/lib/utils/wake_lock.mjs +114 -0
- package/{esm2020 → esm2022}/lib/utils/wake_lock_media.mjs +1 -1
- package/{esm2020 → esm2022}/public-api.mjs +33 -33
- package/{esm2020 → esm2022}/speechrecorderng.mjs +4 -4
- package/{fesm2020 → fesm2022}/speechrecorderng.mjs +16518 -16454
- package/fesm2022/speechrecorderng.mjs.map +1 -0
- package/index.d.ts +5 -5
- package/lib/action/action.d.ts +27 -27
- package/lib/audio/array_audio_buffer.d.ts +31 -31
- package/lib/audio/array_audio_buffer_input_stream.d.ts +14 -14
- package/lib/audio/array_audio_buffer_random_access_stream.d.ts +9 -9
- package/lib/audio/audio_data_holder.d.ts +84 -84
- package/lib/audio/audio_display.d.ts +36 -36
- package/lib/audio/audio_player.d.ts +47 -47
- package/lib/audio/capture/capture.d.ts +67 -67
- package/lib/audio/context.d.ts +6 -6
- package/lib/audio/dsp/level_measure.d.ts +60 -60
- package/lib/audio/format.d.ts +11 -11
- package/lib/audio/impl/wavformat.d.ts +5 -5
- package/lib/audio/impl/wavreader.d.ts +16 -16
- package/lib/audio/impl/wavwriter.d.ts +13 -13
- package/lib/audio/inddb_audio_buffer.d.ts +68 -68
- package/lib/audio/io/stream.d.ts +28 -28
- package/lib/audio/net_audio_buffer.d.ts +57 -57
- package/lib/audio/persistor.d.ts +29 -29
- package/lib/audio/playback/array_audio_buffer_source_node.d.ts +18 -18
- package/lib/audio/playback/audio_source_node.d.ts +10 -10
- package/lib/audio/playback/audio_source_worklet_module_loader.d.ts +4 -4
- package/lib/audio/playback/inddb_audio_buffer_source_node.d.ts +21 -21
- package/lib/audio/playback/net_audio_buffer_source_node.d.ts +27 -27
- package/lib/audio/playback/player.d.ts +65 -65
- package/lib/audio/ui/audio_canvas_layer_comp.d.ts +68 -68
- package/lib/audio/ui/audio_display_control.d.ts +25 -25
- package/lib/audio/ui/audio_display_scroll_pane.d.ts +26 -26
- package/lib/audio/ui/audiosignal.d.ts +30 -30
- package/lib/audio/ui/common.d.ts +11 -11
- package/lib/audio/ui/container.d.ts +63 -63
- package/lib/audio/ui/livelevel.d.ts +60 -60
- package/lib/audio/ui/scroll_pane_horizontal.d.ts +5 -5
- package/lib/audio/ui/sonagram.d.ts +37 -37
- package/lib/db/inddb.d.ts +21 -21
- package/lib/dsp/utils.d.ts +19 -19
- package/lib/io/BinaryReader.d.ts +18 -18
- package/lib/io/BinaryWriter.d.ts +15 -15
- package/lib/io/stream.d.ts +59 -59
- package/lib/math/2d/geometry.d.ts +18 -18
- package/lib/math/complex.d.ts +17 -17
- package/lib/math/dft.d.ts +22 -22
- package/lib/media/utils.d.ts +3 -3
- package/lib/net/uploader.d.ts +81 -81
- package/lib/recorder_component.d.ts +16 -16
- package/lib/speechrecorder/project/project.d.ts +59 -59
- package/lib/speechrecorder/project/project.service.d.ts +21 -21
- package/lib/speechrecorder/recording.d.ts +51 -51
- package/lib/speechrecorder/recordings/basic_recording.service.d.ts +27 -27
- package/lib/speechrecorder/recordings/recordings.service.d.ts +48 -48
- package/lib/speechrecorder/script/script.d.ts +80 -79
- package/lib/speechrecorder/script/script.service.d.ts +16 -16
- package/lib/speechrecorder/session/audiorecorder.d.ts +122 -122
- package/lib/speechrecorder/session/basicrecorder.d.ts +139 -139
- package/lib/speechrecorder/session/controlpanel.d.ts +109 -107
- package/lib/speechrecorder/session/item.d.ts +12 -12
- package/lib/speechrecorder/session/progress.d.ts +17 -17
- package/lib/speechrecorder/session/prompting.d.ts +121 -121
- package/lib/speechrecorder/session/recorder_combi_pane.d.ts +32 -32
- package/lib/speechrecorder/session/recording_file_cache.d.ts +33 -33
- package/lib/speechrecorder/session/recording_list.d.ts +24 -24
- package/lib/speechrecorder/session/recordingfile/recording-file-meta.component.d.ts +15 -15
- package/lib/speechrecorder/session/recordingfile/recording-file-navi.component.d.ts +20 -20
- package/lib/speechrecorder/session/recordingfile/recording-file-u-i.component.d.ts +31 -31
- package/lib/speechrecorder/session/recordingfile/recording-file-view.component.d.ts +55 -55
- package/lib/speechrecorder/session/recordingfile/recording-file.d.ts +7 -7
- package/lib/speechrecorder/session/recordingfile/recordingfile-service.d.ts +24 -24
- package/lib/speechrecorder/session/session.d.ts +15 -15
- package/lib/speechrecorder/session/session.service.d.ts +20 -20
- package/lib/speechrecorder/session/session_finished_dialog.d.ts +10 -10
- package/lib/speechrecorder/session/sessionmanager.d.ts +129 -123
- package/lib/speechrecorder/session/warning_bar.d.ts +8 -8
- package/lib/speechrecorder/spruploader.d.ts +11 -11
- package/lib/speechrecorder/startstopsignal/startstopsignal.d.ts +10 -10
- package/lib/speechrecorder/startstopsignal/ui/simpletrafficlight.d.ts +11 -11
- package/lib/speechrecorderng.component.d.ts +61 -61
- package/lib/speechrecorderng.module.d.ts +56 -56
- package/lib/spr.config.d.ts +17 -17
- package/lib/spr.module.version.d.ts +1 -1
- package/lib/ui/canvas_layer_comp.d.ts +13 -13
- package/lib/ui/message_dialog.d.ts +10 -10
- package/lib/ui/recordingitem_display.d.ts +84 -84
- package/lib/ui/responsive_component.d.ts +9 -9
- package/lib/utils/scrollIntoViewToBottom.d.ts +9 -9
- package/lib/utils/ua-parser.d.ts +43 -43
- package/lib/utils/utils.d.ts +19 -19
- package/lib/utils/wake_lock.d.ts +23 -23
- package/lib/utils/wake_lock_media.d.ts +1 -1
- package/package.json +17 -23
- package/public-api.d.ts +33 -33
- package/esm2020/lib/action/action.mjs +0 -73
- package/esm2020/lib/audio/audio_data_holder.mjs +0 -264
- package/esm2020/lib/audio/capture/capture.mjs +0 -855
- package/esm2020/lib/audio/context.mjs +0 -79
- package/esm2020/lib/audio/impl/wavformat.mjs +0 -6
- package/esm2020/lib/audio/impl/wavwriter.mjs +0 -105
- package/esm2020/lib/audio/inddb_audio_buffer.mjs +0 -508
- package/esm2020/lib/audio/net_audio_buffer.mjs +0 -293
- package/esm2020/lib/audio/playback/audio_source_node.mjs +0 -18
- package/esm2020/lib/audio/playback/audio_source_worklet_module_loader.mjs +0 -167
- package/esm2020/lib/audio/playback/player.mjs +0 -402
- package/esm2020/lib/audio/ui/audio_canvas_layer_comp.mjs +0 -347
- package/esm2020/lib/audio/ui/container.mjs +0 -414
- package/esm2020/lib/audio/ui/scroll_pane_horizontal.mjs +0 -11
- package/esm2020/lib/audio/ui/sonagram.mjs +0 -900
- package/esm2020/lib/db/inddb.mjs +0 -120
- package/esm2020/lib/dsp/utils.mjs +0 -48
- package/esm2020/lib/io/BinaryWriter.mjs +0 -74
- package/esm2020/lib/math/complex.mjs +0 -58
- package/esm2020/lib/net/uploader.mjs +0 -367
- package/esm2020/lib/speechrecorder/project/project.mjs +0 -49
- package/esm2020/lib/speechrecorder/project/project.service.mjs +0 -64
- package/esm2020/lib/speechrecorder/recordings/basic_recording.service.mjs +0 -216
- package/esm2020/lib/speechrecorder/recordings/recordings.service.mjs +0 -1014
- package/esm2020/lib/speechrecorder/session/audiorecorder.mjs +0 -1179
- package/esm2020/lib/speechrecorder/session/basicrecorder.mjs +0 -666
- package/esm2020/lib/speechrecorder/session/controlpanel.mjs +0 -409
- package/esm2020/lib/speechrecorder/session/recording_file_cache.mjs +0 -195
- package/esm2020/lib/speechrecorder/session/recordingfile/recordingfile-service.mjs +0 -288
- package/esm2020/lib/speechrecorder/session/session.service.mjs +0 -69
- package/esm2020/lib/speechrecorder/session/sessionmanager.mjs +0 -1333
- package/esm2020/lib/speechrecorder/startstopsignal/ui/simpletrafficlight.mjs +0 -57
- package/esm2020/lib/ui/recordingitem_display.mjs +0 -253
- package/esm2020/lib/utils/ua-parser.mjs +0 -190
- package/esm2020/lib/utils/utils.mjs +0 -105
- package/esm2020/lib/utils/wake_lock.mjs +0 -114
- package/fesm2015/speechrecorderng.mjs +0 -17708
- package/fesm2015/speechrecorderng.mjs.map +0 -1
- package/fesm2020/speechrecorderng.mjs.map +0 -1
|
@@ -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
|
-
constructor(real, img) {
|
|
125
|
-
this.real = real;
|
|
126
|
-
this.img = img;
|
|
127
|
-
}
|
|
128
|
-
static fromPolarForm(magnitude, argument) {
|
|
129
|
-
const r = Math.cos(argument) * magnitude;
|
|
130
|
-
const i = Math.sin(argument) * magnitude;
|
|
131
|
-
return new Complex(r, i);
|
|
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
|
-
constructor(size, sigma = GaussianWindow.DEFAULT_SIGMA) {
|
|
286
|
-
this.buf = new Float32Array(size);
|
|
287
|
-
const center = (size - 1) / 2;
|
|
288
|
-
for (let i = 0; i < size; i++) {
|
|
289
|
-
const quot = (i - center) / (sigma * center);
|
|
290
|
-
const exp = -0.5 * quot * quot;
|
|
291
|
-
this.buf[i] = Math.exp(exp);
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
getScale(i) {
|
|
295
|
-
return this.buf[i];
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
GaussianWindow.DEFAULT_SIGMA = 0.3;
|
|
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
|
-
}
|
|
878
|
-
Sonagram.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: Sonagram, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
879
|
-
Sonagram.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.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: `
|
|
880
|
-
<canvas #sonagram height="10"></canvas>
|
|
881
|
-
<canvas #bg height="10"></canvas>
|
|
882
|
-
<canvas #cursor height="10" (mousedown)="selectionStart($event)" (mouseover)="updateCursorCanvas($event)" (mousemove)="updateCursorCanvas($event)"
|
|
883
|
-
(mouseleave)="updateCursorCanvas($event, false)"></canvas>
|
|
884
|
-
<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"] });
|
|
885
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.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: function () { return [{ 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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RUFBRSxDQUFDO29CQUNiLENBQUMsR0FBRyxDQUFDLENBQUM7b0JBQ04sS0FBSyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUU7d0JBQ3JCLENBQUMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDO3dCQUN0QixDQUFDLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQzt3QkFDdEIsQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQzt3QkFFN0IsS0FBSyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxFQUFFOzRCQUNoQyxFQUFFLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7NEJBQ3hDLEVBQUUsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQzs0QkFDeEMsSUFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDOzRCQUM1QixHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUM7NEJBQzFCLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDOzRCQUN2QixHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQzt5QkFDeEI7cUJBQ0o7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Y2VzQ29udGVudCI6WyJpbXBvcnQge0RGVEZsb2F0MzJ9IGZyb20gJy4uLy4uL21hdGgvZGZ0JztcclxuaW1wb3J0IHtNYXJrZXIsIFBvaW50fSBmcm9tICcuL2NvbW1vbic7XHJcbmltcG9ydCB7Q29tcG9uZW50LCBFbGVtZW50UmVmLCBWaWV3Q2hpbGR9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XHJcbmltcG9ydCB7QXVkaW9DYW52YXNMYXllckNvbXBvbmVudH0gZnJvbSBcIi4vYXVkaW9fY2FudmFzX2xheWVyX2NvbXBcIjtcclxuaW1wb3J0IHtXb3JrZXJIZWxwZXJ9IGZyb20gXCIuLi8uLi91dGlscy91dGlsc1wiO1xyXG5pbXBvcnQge0F1ZGlvQnVmZmVyU291cmNlLCBBdWRpb0RhdGFIb2xkZXJ9IGZyb20gXCIuLi9hdWRpb19kYXRhX2hvbGRlclwiO1xyXG5pbXBvcnQge1N1YnNjcmlwdGlvbn0gZnJvbSBcInJ4anNcIjtcclxuXHJcbmRlY2xhcmUgZnVuY3Rpb24gcG9zdE1lc3NhZ2UobWVzc2FnZTogYW55LCB0cmFuc2ZlcjogQXJyYXk8YW55Pik6IHZvaWQ7XHJcblxyXG5jb25zdCBERUZBVUxUX0RGVF9TSVpFID0gMTAyNDtcclxuXHJcbkBDb21wb25lbnQoe1xyXG5cclxuICAgIHNlbGVjdG9yOiAnYXVkaW8tc29uYWdyYW0nLFxyXG4gICAgdGVtcGxhdGU6IGBcclxuICAgICAgICA8Y2FudmFzICNzb25hZ3JhbSBoZWlnaHQ9XCIxMFwiPjwvY2FudmFzPlxyXG4gICAgICAgIDxjYW52YXMgI2JnIGhlaWdodD1cIjEwXCI+PC9jYW52YXM+XHJcbiAgICAgICAgPGNhbnZhcyAjY3Vyc29yIGhlaWdodD1cIjEwXCIgKG1vdXNlZG93bik9XCJzZWxlY3Rpb25TdGFydCgkZXZlbnQpXCIgKG1vdXNlb3Zlcik9XCJ1cGRhdGVDdXJzb3JDYW52YXMoJGV2ZW50KVwiIChtb3VzZW1vdmUpPVwidXBkYXRlQ3Vyc29yQ2FudmFzKCRldmVudClcIlxyXG4gICAgICAgICAgICAgICAgKG1vdXNlbGVhdmUpPVwidXBkYXRlQ3Vyc29yQ2FudmFzKCRldmVudCwgZmFsc2UpXCI+PC9jYW52YXM+XHJcbiAgICAgICAgPGNhbnZhcyAjbWFya2VyIGhlaWdodD1cIjEwXCI+PC9jYW52YXM+YCxcclxuXHJcbiAgICBzdHlsZXM6IFtgOmhvc3R7XHJcbiAgICAgIG1pbi1oZWlnaHQ6IDBweDtcclxuICAgIH1gLGBjYW52YXMge1xyXG4gICAgICAgIHRvcDogMDtcclxuICAgICAgICBsZWZ0OiAwO1xyXG4gICAgICAgIHdpZHRoOiAwO1xyXG4gICAgICAgIGhlaWdodDogMDtcclxuICAgICAgbWluLWhlaWdodDogMHB4O1xyXG4gICAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgIH1gXVxyXG5cclxufSlcclxuZXhwb3J0IGNsYXNzIFNvbmFncmFtIGV4dGVuZHMgQXVkaW9DYW52YXNMYXllckNvbXBvbmVudCB7XHJcblxyXG4gICAgZGZ0OiBERlRGbG9hdDMyO1xyXG4gICAgbjogYW55O1xyXG4gICAgY2UhOiBIVE1MRGl2RWxlbWVudDtcclxuICAgIHNvbmFncmFtQ2FudmFzITogSFRNTENhbnZhc0VsZW1lbnQ7XHJcbiAgICAvL2N1cnNvckNhbnZhczogSFRNTENhbnZhc0VsZW1lbnQ7XHJcbiAgICBtYXJrZXJDYW52YXMhOiBIVE1MQ2FudmFzRWxlbWVudDtcclxuICAgIEBWaWV3Q2hpbGQoJ3NvbmFncmFtJywgeyBzdGF0aWM6IHRydWUgfSkgc29uYWdyYW1DYW52YXNSZWYhOiBFbGVtZW50UmVmO1xyXG5cclxuICAgIEBWaWV3Q2hpbGQoJ21hcmtlcicsIHsgc3RhdGljOiB0cnVlIH0pIG1hcmtlckNhbnZhc1JlZiE6IEVsZW1lbnRSZWY7XHJcbiAgICBtYXJrZXJzOiBBcnJheTxNYXJrZXI+O1xyXG4gICAgcHJpdmF0ZSBfcGxheUZyYW1lUG9zaXRpb246IG51bWJlcnxudWxsPW51bGw7XHJcblxyXG4gICAgcHJpdmF0ZSB3b3JrZXI6IFdvcmtlciB8IG51bGw7XHJcbiAgICBwcml2YXRlIHJlYWRvbmx5IHdvcmtlclVSTDogc3RyaW5nO1xyXG4gICAgcHJpdmF0ZSByYUFzU3Vic2M6U3Vic2NyaXB0aW9ufG51bGw9bnVsbDtcclxuXHJcbiAgICBwcml2YXRlIGRmdFNpemUgPSBERUZBVUxUX0RGVF9TSVpFO1xyXG5cclxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVmOiBFbGVtZW50UmVmKSB7XHJcbiAgICAgICAgc3VwZXIoKTtcclxuICAgICAgICB0aGlzLndvcmtlciA9IG51bGw7XHJcbiAgICAgICAgdGhpcy5fYXVkaW9EYXRhSG9sZGVyID0gbnVsbDtcclxuICAgICAgICB0aGlzLm1hcmtlcnMgPSBuZXcgQXJyYXk8TWFya2VyPigpO1xyXG4gICAgICAgIHRoaXMuZGZ0ID0gbmV3IERGVEZsb2F0MzIodGhpcy5kZnRTaXplKTtcclxuXHJcbiAgICAgICAgdGhpcy53b3JrZXJVUkwgPSBXb3JrZXJIZWxwZXIuYnVpbGRXb3JrZXJCbG9iVVJMKHRoaXMud29ya2VyRnVuY3Rpb24pXHJcbiAgICAgICB0aGlzLl9iZ0NvbG9yPW51bGw7XHJcbiAgICAgICB0aGlzLl9zZWxlY3RDb2xvcj0ncmdiYSgyNTUsMjU1LDAsMC4xKSdcclxuICAgIH1cclxuXHJcbiAgICBuZ0FmdGVyVmlld0luaXQoKSB7XHJcblxyXG4gICAgICAgIHRoaXMuY2UgPSB0aGlzLnJlZi5uYXRpdmVFbGVtZW50O1xyXG4gICAgICAgIHRoaXMuc29uYWdyYW1DYW52YXMgPSB0aGlzLnNvbmFncmFtQ2FudmFzUmVmLm5hdGl2ZUVsZW1lbnQ7XHJcbiAgICAgICAgdGhpcy5zb25hZ3JhbUNhbnZhcy5zdHlsZS56SW5kZXggPSAnMSc7XHJcbiAgICAgIHRoaXMuYmdDYW52YXMgPSB0aGlzLmJnQ2FudmFzUmVmLm5hdGl2ZUVsZW1lbnQ7XHJcbiAgICAgIHRoaXMuYmdDYW52YXMuc3R5bGUuekluZGV4ID0gJzInO1xyXG4gICAgICAgIHRoaXMuY3Vyc29yQ2FudmFzID0gdGhpcy5jdXJzb3JDYW52YXNSZWYubmF0aXZlRWxlbWVudDtcclxuICAgICAgICB0aGlzLmN1cnNvckNhbnZhcy5zdHlsZS56SW5kZXggPSAnNCc7XHJcbiAgICAgICAgdGhpcy5tYXJrZXJDYW52YXMgPSB0aGlzLm1hcmtlckNhbnZhc1JlZi5uYXRpdmVFbGVtZW50O1xyXG4gICAgICAgIHRoaXMubWFya2VyQ2FudmFzLnN0eWxlLnpJbmRleCA9ICczJztcclxuXHJcbiAgICAgICAgdGhpcy5jYW52YXNMYXllcnNbMF0gPSB0aGlzLnNvbmFncmFtQ2FudmFzO1xyXG4gICAgICB0aGlzLmNhbnZhc0xheWVyc1sxXSA9IHRoaXMuYmdDYW52YXM7XHJcbiAgICAgIHRoaXMuY2FudmFzTGF5ZXJzWzJdID0gdGhpcy5jdXJzb3JDYW52YXM7XHJcbiAgICAgICAgdGhpcy5jYW52YXNMYXllcnNbM10gPSB0aGlzLm1hcmtlckNhbnZhcztcclxuXHJcbiAgICB9XHJcblxyXG4gICAgZ2V0IHBsYXlGcmFtZVBvc2l0aW9uKCk6IG51bWJlcnxudWxsIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5fcGxheUZyYW1lUG9zaXRpb247XHJcbiAgICB9XHJcblxyXG4gICAgc2V0IHBsYXlGcmFtZVBvc2l0aW9uKHBsYXlGcmFtZVBvc2l0aW9uOiBudW1iZXJ8bnVsbCkge1xyXG4gICAgICAgIHRoaXMuX3BsYXlGcmFtZVBvc2l0aW9uID0gcGxheUZyYW1lUG9zaXRpb247XHJcbiAgICAgICAgLy8gdGhpcy5yZWRyYXcoKTtcclxuICAgICAgICB0aGlzLmRyYXdQbGF5UG9zaXRpb24oKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIGNhbnZhc01vdXNlUG9zKGM6IEhUTUxDYW52YXNFbGVtZW50LCBlOiBNb3VzZUV2ZW50KTogUG9pbnQge1xyXG4gICAgICAgIGNvbnN0IGNyID0gYy5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcclxuXHJcbiAgICAgICAgY29uc3QgeCA9IGUueCAtIGNyLmxlZnQ7XHJcbiAgICAgICAgY29uc3QgeSA9IGUueSAtIGNyLnRvcDtcclxuICAgICAgICByZXR1cm4gbmV3IFBvaW50KHgseSk7XHJcbiAgICB9XHJcblxyXG4gIGRyYXdTdGF0ZVRleHQoc3RhdGVUZXh0OnN0cmluZykge1xyXG4gICAgICAgIGlmKHN0YXRlVGV4dCkge1xyXG4gICAgICAgICAgICBjb25zdCBnID0gdGhpcy5zb25hZ3JhbUNhbnZhcy5nZXRDb250ZXh0KFwiMmRcIik7XHJcbiAgICAgICAgICAgIGNvbnN0IHcgPSB0aGlzLnNvbmFncmFtQ2FudmFzLndpZHRoO1xyXG4gICAgICAgICAgICBjb25zdCBoID0gdGhpcy5zb25hZ3JhbUNhbnZhcy5oZWlnaHQ7XHJcbiAgICAgICAgICAgIGlmIChnICYmIHcgJiYgaCkge1xyXG4gICAgICAgICAgICAgICAgZy5zdHJva2VTdHlsZSA9ICdibGFjayc7XHJcbiAgICAgICAgICAgICAgICBnLmZpbGxTdHlsZSA9ICdibGFjayc7XHJcbiAgICAgICAgICAgICAgICBnLmZvbnQgPSAnMjBweCBzYW5zLXNlcmlmJztcclxuICAgICAgICAgICAgICAgIGcuZmlsbFRleHQoc3RhdGVUZXh0LCAxMCwgMjUpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gIH1cclxuXHJcbiAgZHJhd0N1cnNvclBvc2l0aW9uKGU6IE1vdXNlRXZlbnQsIHNob3c6IGJvb2xlYW4pIHtcclxuXHJcbiAgICBpZiAodGhpcy5jdXJzb3JDYW52YXMpIHtcclxuICAgICAgY29uc3QgdyA9IHRoaXMuY3Vyc29yQ2FudmFzLndpZHRoO1xyXG4gICAgICBjb25zdCBoID0gdGhpcy5jdXJzb3JDYW52YXMuaGVpZ2h0O1xyXG4gICAgICBjb25zdCBnID0gdGhpcy5jdXJzb3JDYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcclxuICAgICAgaWYgKGcpIHtcclxuICAgICAgICBnLmNsZWFyUmVjdCgwLCAwLCB3LCBoKTtcclxuICAgICAgICBpZiAoc2hvdykge1xyXG4gICAgICAgICAgLy9jb25zdCBwcCA9IHRoaXMuY2FudmFzTW91c2VQb3ModGhpcy5jdXJzb3JDYW52YXMsIGUpO1xyXG4gICAgICAgICAgbGV0IHhWaWV3UG9ydFBpeGVscG9zID0gZS5vZmZzZXRYO1xyXG5cclxuICAgICAgICAgIGcuZmlsbFN0eWxlID0gJ3llbGxvdyc7XHJcbiAgICAgICAgICBnLnN0cm9rZVN0eWxlID0gJ3llbGxvdyc7XHJcbiAgICAgICAgICBnLmJlZ2luUGF0aCgpO1xyXG4gICAgICAgICAgZy5tb3ZlVG8oeFZpZXdQb3J0UGl4ZWxwb3MsIDApO1xyXG4gICAgICAgICAgZy5saW5lVG8oeFZpZXdQb3J0UGl4ZWxwb3MsIGgpO1xyXG4gICAgICAgICAgZy5jbG9zZVBhdGgoKTtcclxuXHJcbiAgICAgICAgICBnLnN0cm9rZSgpO1xyXG5cclxuICAgICAgICAgIGlmICh0aGlzLl9hdWRpb0RhdGFIb2xkZXIpIHtcclxuXHJcbiAgICAgICAgICAgIGxldCBmcmFtZVBvc1JvdW5kID0gdGhpcy52aWV3UG9ydFhQaXhlbFRvRnJhbWVQb3NpdGlvbih4Vmlld1BvcnRQaXhlbHBvcyk7XHJcbiAgICAgICAgICAgIGlmKGZyYW1lUG9zUm91bmQhPW51bGwpIHtcclxuICAgICAgICAgICAgICBnLmZvbnQgPSAnMTRweCBzYW5zLXNlcmlmJztcclxuICAgICAgICAgICAgICBnLmZpbGxTdHlsZSA9ICd5ZWxsb3cnO1xyXG4gICAgICAgICAgICAgIGcuZmlsbFRleHQoZnJhbWVQb3NSb3VuZC50b1N0cmluZygpLCB4Vmlld1BvcnRQaXhlbHBvcyArIDIsIDUwKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgICBkcmF3UGxheVBvc2l0aW9uKCkge1xyXG4gICAgICAgIGlmICh0aGlzLm1hcmtlckNhbnZhcykge1xyXG4gICAgICAgICAgICBjb25zdCB3ID0gdGhpcy5tYXJrZXJDYW52YXMud2lkdGg7XHJcbiAgICAgICAgICAgIGNvbnN0IGggPSB0aGlzLm1hcmtlckNhbnZhcy5oZWlnaHQ7XHJcbiAgICAgICAgICAgIGNvbnN0IGcgPSB0aGlzLm1hcmtlckNhbnZhcy5nZXRDb250ZXh0KFwiMmRcIik7XHJcbiAgICAgICAgICAgIGlmIChnKSB7XHJcbiAgICAgICAgICAgICAgICBnLmNsZWFyUmVjdCgwLCAwLCB3LCBoKTtcclxuICAgICAgICAgICAgICAgIGlmKHRoaXMuX3BsYXlGcmFtZVBvc2l0aW9uIT1udWxsKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IHBpeGVsUG9zID0gdGhpcy5mcmFtZVRvVmlld1BvcnRYUGl4ZWxQb3NpdGlvbih0aGlzLl9wbGF5RnJhbWVQb3NpdGlvbik7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBpeGVsUG9zKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGcuZmlsbFN0eWxlID0gJ3JlZCc7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGcuc3Ryb2tlU3R5bGUgPSAncmVkJztcclxuICAgICAgICAgICAgICAgICAgICAgICAgZy5iZWdpblBhdGgoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZy5tb3ZlVG8ocGl4ZWxQb3MsIDApO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBnLmxpbmVUbyhwaXhlbFBvcywgaCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGcuY2xvc2VQYXRoKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGcuc3Ryb2tlKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qXHJcbiAgICAgKiAgTWV0aG9kIHVzZWQgYXMgd29ya2VyIGNvZGUuXHJcbiAgICAgKi9cclxuICAgIHdvcmtlckZ1bmN0aW9uKCkge1xyXG5cclxuICAgICAgICAvLyBSZWRlZmluZSBzb21lIERTUCBjbGFzc2VzIGZvciB3b3JrZXIgZnVuY3Rpb25cclxuICAgICAgICAvLyBTZWUgZS5nLiBhdWRpby5tYXRoLkNvbXBsZXhcclxuICAgICAgICBjbGFzcyBDb21wbGV4IHtcclxuXHJcbiAgICAgICAgICAgIHJlYWw6IG51bWJlcjtcclxuICAgICAgICAgICAgaW1nOiBudW1iZXI7XHJcblxyXG4gICAgICAgICAgICBwdWJsaWMgc3RhdGljIGZyb21Qb2xhckZvcm0obWFnbml0dWRlOiBudW1iZXIsIGFyZ3VtZW50OiBudW1iZXIpOiBDb21wbGV4IHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHIgPSBNYXRoLmNvcyhhcmd1bWVudCkgKiBtYWduaXR1ZGU7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBpID0gTWF0aC5zaW4oYXJndW1lbnQpICogbWFnbml0dWRlO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBDb21wbGV4KHIsIGkpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBjb25zdHJ1Y3RvcihyZWFsOiBudW1iZXIsIGltZzogbnVtYmVyKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnJlYWwgPSByZWFsO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5pbWcgPSBpbWc7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHB1YmxpYyBtYWduaXR1ZGUoKTogbnVtYmVyIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBNYXRoLnNxcnQoKHRoaXMucmVhbCAqIHRoaXMucmVhbCkgKyAodGhpcy5pbWcgKiB0aGlzLmltZykpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBwdWJsaWMgYXJndW1lbnQoKTogbnVtYmVyIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBNYXRoLmF0YW4yKHRoaXMuaW1nLCB0aGlzLnJlYWwpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBwdWJsaWMgYWRkKGFkZEM6IENvbXBsZXgpOiBDb21wbGV4IHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgQ29tcGxleCh0aGlzLnJlYWwgKyBhZGRDLnJlYWwsIHRoaXMuaW1nICsgYWRkQy5pbWcpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBwdWJsaWMgc3ViKHN1YkM6IENvbXBsZXgpOiBDb21wbGV4IHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgQ29tcGxleCh0aGlzLnJlYWwgLSBzdWJDLnJlYWwsIHRoaXMuaW1nIC0gc3ViQy5pbWcpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBwdWJsaWMgbXVsdChtdWx0QzogQ29tcGxleCk6IENvbXBsZXgge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgbXVsdFIgPSAodGhpcy5yZWFsICogbXVsdEMucmVhbCkgLSAodGhpcy5pbWcgKiBtdWx0Qy5pbWcpO1xyXG4gICAgICAgICAgICAgICAgY29uc3QgbXVsdEkgPSAodGhpcy5yZWFsICogbXVsdEMuaW1nKSArIChtdWx0Qy5yZWFsICogdGhpcy5pbWcpO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBDb21wbGV4KG11bHRSLCBtdWx0SSk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHB1YmxpYyBtdWx0UmVhbChtdWx0RjogbnVtYmVyKTogQ29tcGxleCB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IENvbXBsZXgodGhpcy5yZWFsICogbXVsdEYsIHRoaXMuaW1nICogbXVsdEYpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBwdWJsaWMgZGl2KGRpdmlzb3I6IENvbXBsZXgpOiBDb21wbGV4IHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGRpdlJlYWwgPSBkaXZpc29yLnJlYWw7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBkaXZJbWcgPSBkaXZpc29yLmltZztcclxuICAgICAgICAgICAgICAgIGNvbnN0IGRpdiA9IChkaXZSZWFsICogZGl2UmVhbCkgKyAoZGl2SW1nICogZGl2SW1nKTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGRpdmlzaW9uUmVhbCA9ICgodGhpcy5yZWFsICogZGl2UmVhbCkgKyAodGhpcy5pbWcgKiBkaXZJbWcpKSAvIGRpdjtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGRpdmlzaW9uSW1nID0gKChkaXZSZWFsICogdGhpcy5pbWcpIC0gKHRoaXMucmVhbCAqIGRpdkltZykpIC8gZGl2O1xyXG5cclxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgQ29tcGxleChkaXZpc2lvblJlYWwsIGRpdmlzaW9uSW1nKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgcHVibGljIGRpdlJlYWwoZGl2aXNvcjogbnVtYmVyKTogQ29tcGxleCB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBkaXYgPSBkaXZpc29yICogZGl2aXNvcjtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGRpdnNpb25SZWFsID0gKHRoaXMucmVhbCAqIGRpdmlzb3IpIC8gZGl2O1xyXG4gICAgICAgICAgICAgICAgY29uc3QgZGl2c2lvbkltZyA9IChkaXZpc29yICogdGhpcy5pbWcpIC8gZGl2O1xyXG5cclxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgQ29tcGxleChkaXZzaW9uUmVhbCwgZGl2c2lvbkltZyk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHB1YmxpYyBjb25qdWdhdGUoKTogQ29tcGxleCB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IENvbXBsZXgodGhpcy5yZWFsLCAtdGhpcy5pbWcpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBwdWJsaWMgZXF1YWxzKGM6IENvbXBsZXgpOiBib29sZWFuIHtcclxuICAgICAgICAgICAgICAgIGlmIChjID09PSBudWxsKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuICh0aGlzLnJlYWwgPT09IGMucmVhbCAmJiB0aGlzLmltZyA9PT0gYy5pbWcpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBwdWJsaWMgdG9TdHJpbmcoKTogc3RyaW5nIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiAnUmVhbDogJyArIHRoaXMucmVhbCArICcsIEltZzogJyArIHRoaXMuaW1nO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjbGFzcyBERlRGbG9hdDMyIHtcclxuXHJcbiAgICAgICAgICAgIHByaXZhdGUgcmVhZG9ubHkgbjogbnVtYmVyO1xyXG4gICAgICAgICAgICBwcml2YXRlIHJlYWRvbmx5IG06IG51bWJlcjtcclxuXHJcbiAgICAgICAgICAgIHByaXZhdGUgcmVhZG9ubHkgY29zTG9va3VwOiBGbG9hdDMyQXJyYXk7XHJcbiAgICAgICAgICAgIHByaXZhdGUgcmVhZG9ubHkgc2luTG9va3VwOiBGbG9hdDMyQXJyYXk7XHJcblxyXG4gICAgICAgICAgICBjb25zdHJ1Y3RvcihuOiBudW1iZXIpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMubiA9IG47XHJcbiAgICAgICAgICAgICAgICB0aGlzLm0gPSBNYXRoLmxvZyhuKSAvIE1hdGgubG9nKDIpO1xyXG5cclxuICAgICAgICAgICAgICAgIC8vIGlmKG4gIT0gKDEgPDwgbSkpdGhyb3cgbmV3IFJ1bnRpbWVFeGNlcHRpb24oXCJsZW5ndGggTiBtdXN0IGJlIHBvd2VyIG9mIDJcIik7XHJcblxyXG4gICAgICAgICAgICAgICAgLy8gbG9va3VwIHRhYmxlc1xyXG4gICAgICAgICAgICAgICAgdGhpcy5jb3NMb29rdXAgPSBuZXcgRmxvYXQzMkFycmF5KG4gLyAyKTtcclxuICAgICAgICAgICAgICAgIHRoaXMuc2luTG9va3VwID0gbmV3IEZsb2F0MzJBcnJheShuIC8gMik7XHJcblxyXG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBuIC8gMjsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgYXJjID0gKC0yICogTWF0aC5QSSAqIGkpIC8gbjtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvc0xvb2t1cFtpXSA9IE1hdGguY29zKGFyYyk7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zaW5Mb29rdXBbaV0gPSBNYXRoLnNpbihhcmMpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBwdWJsaWMgcHJvY2Vzc1JlYWwoc3JjQnVmOiBGbG9hdDMyQXJyYXkpOiBBcnJheTxDb21wbGV4PiB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCB4ID0gc3JjQnVmLnNsaWNlKCk7XHJcbiAgICAgICAgICAgICAgICBjb25zdCB5ID0gbmV3IEZsb2F0MzJBcnJheShzcmNCdWYubGVuZ3RoKTtcclxuICAgICAgICAgICAgICAgIGZvciAobGV0IHlpID0gMDsgeWkgPCB5Lmxlbmd0aDsgeWkrKykge1xyXG4gICAgICAgICAgICAgICAgICAgIHlbeWldID0gMC4wO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgdGhpcy5mZnRDb29sZXlUdWtleSh4LCB5KTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHJjID0gbmV3IEFycmF5PENvbXBsZXg+KHgubGVuZ3RoKTtcclxuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgeC5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICAgICAgICAgIHJjW2ldID0gbmV3IENvbXBsZXgoeFtpXSwgeVtpXSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gcmM7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHB1YmxpYyBwcm9jZXNzUmVhbE1hZ25pdHVkZShzcmNCdWY6IEZsb2F0MzJBcnJheSk6IEZsb2F0MzJBcnJheSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCB4ID0gc3JjQnVmLnNsaWNlKCk7XHJcbiAgICAgICAgICAgICAgICBjb25zdCB5ID0gbmV3IEZsb2F0MzJBcnJheShzcmNCdWYubGVuZ3RoKTtcclxuICAgICAgICAgICAgICAgIGZvciAobGV0IHlpID0gMDsgeWkgPCB5Lmxlbmd0aDsgeWkrKykge1xyXG4gICAgICAgICAgICAgICAgICAgIHlbeWldID0gMC4wO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgdGhpcy5mZnRDb29sZXlUdWtleSh4LCB5KTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHJjID0gbmV3IEZsb2F0MzJBcnJheSh4Lmxlbmd0aCk7XHJcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHgubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCByY2MgPSBuZXcgQ29tcGxleCh4W2ldLCB5W2ldKTtcclxuICAgICAgICAgICAgICAgICAgICByY1tpXSA9IHJjYy5tYWduaXR1ZGUoKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIHJldHVybiByYztcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgcHVibGljIGZmdENvb2xleVR1a2V5KHJlYWw6IEZsb2F0MzJBcnJheSwgaW1nOiBGbG9hdDMyQXJyYXkpOiB2b2lkIHtcclxuICAgICAgICAgICAgICAgIGxldCBpOiBudW1iZXI7XHJcbiAgICAgICAgICAgICAgICBsZXQgaiA9IDA7XHJcbiAgICAgICAgICAgICAgICBsZXQgazogbnVtYmVyO1xyXG4gICAgICAgICAgICAgICAgbGV0IG4xOiBudW1iZXI7XHJcbiAgICAgICAgICAgICAgICBsZXQgbjI6IG51bWJlciA9IHRoaXMubiAvIDI7XHJcbiAgICAgICAgICAgICAgICBsZXQgYTogbnVtYmVyO1xyXG4gICAgICAgICAgICAgICAgbGV0IGM6IG51bWJlcjtcclxuICAgICAgICAgICAgICAgIGxldCBzOiBudW1iZXI7XHJcbiAgICAgICAgICAgICAgICBsZXQgdDE6IG51bWJlcjtcclxuICAgICAgICAgICAgICAgIGxldCB0MjogbnVtYmVyO1xyXG5cclxuICAgICAgICAgICAgICAgIGZvciAoaSA9IDE7IGkgPCB0aGlzLm4gLSAxOyBpKyspIHtcclxuICAgICAgICAgICAgICAgICAgICBuMSA9IG4yO1xyXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChqID49IG4xKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGogPSBqIC0gbjE7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG4xID0gbjEgLyAyO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBqID0gaiArIG4xO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBpZiAoaSA8IGopIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdDEgPSByZWFsW2ldO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZWFsW2ldID0gcmVhbFtqXTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmVhbFtqXSA9IHQxO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0MSA9IGltZ1tpXTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaW1nW2ldID0gaW1nW2pdO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpbWdbal0gPSB0MTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgbjEgPSAwO1xyXG4gICAgICAgICAgICAgICAgbjIgPSAxO1xyXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHRoaXMubTsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbjEgPSBuMjtcclxuICAgICAgICAgICAgICAgICAgICBuMiA9IG4yICsgbjI7XHJcbiAgICAgICAgICAgICAgICAgICAgYSA9IDA7XHJcbiAgICAgICAgICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IG4xOyBqKyspIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgYyA9IHRoaXMuY29zTG9va3VwW2FdO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBzID0gdGhpcy5zaW5Mb29rdXBbYV07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGEgKz0gKDEgPDwgKHRoaXMubSAtIGkgLSAxKSk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGsgPSBqOyBrIDwgdGhpcy5uOyBrID0gayArIG4yKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0MSA9IGMgKiByZWFsW2sgKyBuMV0gLSBzICogaW1nW2sgKyBuMV07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0MiA9IHMgKiByZWFsW2sgKyBuMV0gKyBjICogaW1nW2sgKyBuMV07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWFsW2sgKyBuMV0gPSByZWFsW2tdIC0gdDE7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbWdbayArIG4xXSA9IGltZ1trXSAtIHQyO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVhbFtrXSA9IHJlYWxba10gKyB0MTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGltZ1trXSA9IGltZ1trXSArIHQyO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcblxyXG5cclxuICAgICAgICAgICAgcHVibGljIHByb2Nlc3ModDogQXJyYXk8Q29tcGxleD4pOiBBcnJheTxDb21wbGV4PiB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCByZWFsczogRmxvYXQzMkFycmF5ID0gbmV3IEZsb2F0MzJBcnJheSh0aGlzLm4pO1xyXG4gICAgICAgICAgICAgICAgY29uc3QgaW1nczogRmxvYXQzMkFycmF5ID0gbmV3IEZsb2F0MzJBcnJheSh0aGlzLm4pO1xyXG4gICAgICAgICAgICAgICAgY29uc3QgdHJhbnM6IEFycmF5PENvbXBsZXg+ID0gbmV3IEFycmF5PENvbXBsZXg+KHRoaXMubik7XHJcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubjsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmVhbHNbaV0gPSB0W2ldLnJlYWw7XHJcbiAgICAgICAgICAgICAgICAgICAgaW1nc1tpXSA9IHRbaV0uaW1nO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgdGhpcy5mZnRDb29sZXlUdWtleShyZWFscywgaW1ncyk7XHJcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubjsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdHJhbnNbaV0gPSBuZXcgQ29tcGxleChyZWFsc1tpXSwgaW1nc1tpXSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJhbnM7XHJcblxyXG5cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGludGVyZmFjZSBXaW5kb3dGdW5jdGlvbiB7XHJcbiAgICAgICAgICAgIGdldFNjYWxlKGk6IG51bWJlcik6IG51bWJlcjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNsYXNzIEdhdXNzaWFuV2luZG93IGltcGxlbWVudHMgV2luZG93RnVuY3Rpb24ge1xyXG5cclxuICAgICAgICAgICAgcHVibGljIHN0YXRpYyBERUZBVUxUX1NJR01BID0gMC4zO1xyXG4gICAgICAgICAgICAvLyBHYXVzc2lhbiB3aW5kb3cgZnVuY3Rpb24sXHJcbiAgICAgICAgICAgIC8vIGh0dHA6Ly9yZWZlcmVuY2Uud29sZnJhbS5jb20vbGFuZ3VhZ2UvcmVmL0dhdXNzaWFuV2luZG93Lmh0bWxcclxuICAgICAgICAgICAgLy8gdmFsPWV4cCgtNTAqeCp4LzkpID0+IHNpZ21hPTAuM1xyXG5cclxuICAgICAgICAgICAgcHJpdmF0ZSByZWFkb25seSBidWY6IEZsb2F0MzJBcnJheTtcclxuXHJcbiAgICAgICAgICAgIGNvbnN0cnVjdG9yKHNpemU6IG51bWJlciwgc2lnbWE6IG51bWJlciA9IEdhdXNzaWFuV2luZG93LkRFRkFVTFRfU0lHTUEpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuYnVmID0gbmV3IEZsb2F0MzJBcnJheShzaXplKTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGNlbnRlciA9IChzaXplIC0gMSkgLyAyO1xyXG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBxdW90ID0gKGkgLSBjZW50ZXIpIC8gKHNpZ21hICogY2VudGVyKTtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBleHAgPSAtMC41ICogcXVvdCAqIHF1b3Q7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5idWZbaV0gPSBNYXRoLmV4cChleHApO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBnZXRTY2FsZShpOiBudW1iZXIpOiBudW1iZXIge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYnVmW2ldO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgc2VsZi5vbm1lc3NhZ2UgPSBmdW5jdGlvbiAobXNnOk1lc3NhZ2VFdmVudCkge1xyXG4gICAgICAgICAgICAvL2NvbnNvbGUuZGVidWcoXCJTb25hZ3JhbSByZW5kZXIgdGhyZWFkXCIpO1xyXG4gICAgICAgICAgICBsZXQgbCA9IG1zZy5kYXRhLmw7XHJcbiAgICAgICAgICAgIGxldCB3ID0gbXNnLmRhdGEudztcclxuICAgICAgICAgICAgbGV0IGggPSBtc2cuZGF0YS5oO1xyXG4gICAgICAgICAgICBsZXQgdncgPSBtc2cuZGF0YS52dztcclxuICAgICAgICAgICAgbGV0IGNocyA9IG1zZy5kYXRhLmNocztcclxuICAgICAgICAgICAgbGV0IGF1ZGlvRGF0YU9mZnNldD0wO1xyXG4gICAgICAgICAgICBsZXQgYWRPZmZzZXQ9bXNnLmRhdGEuYXVkaW9EYXRhT2Zmc2V0O1xyXG4gICAgICAgICAgICBpZihhZE9mZnNldCl7XHJcbiAgICAgICAgICAgICAgYXVkaW9EYXRhT2Zmc2V0PWFkT2Zmc2V0O1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgbGV0IG1heFBzZCA9IG51bGw7XHJcbiAgICAgICAgICAgIGlmKG1zZy5kYXRhLm1heFBzZCE9PXVuZGVmaW5lZCl7XHJcbiAgICAgICAgICAgICAgbWF4UHNkPW1zZy5kYXRhLm1heFBzZDtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgbGV0IGF1ZGlvRGF0YSA9IG5ldyBBcnJheShjaHMpO1xyXG4gICAgICAgICAgICBmb3IgKGxldCBjaCA9IDA7IGNoIDwgY2hzOyBjaCsrKSB7XHJcbiAgICAgICAgICAgICAgICBhdWRpb0RhdGFbY2hdID0gbmV3IEZsb2F0MzJBcnJheShtc2cuZGF0YVsnYXVkaW9EYXRhJ11bY2hdKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgbGV0IGZyYW1lTGVuZ3RoID0gbXNnLmRhdGEuZnJhbWVMZW5ndGg7XHJcbiAgICAgICAgICAgIGxldCBkZnRTaXplID0gbXNnLmRhdGEuZGZ0U2l6ZTtcclxuXHJcbiAgICAgICAgICAgIGxldCBkZnRCYW5kcyA9IGRmdFNpemUgLyAyO1xyXG4gICAgICAgICAgICBsZXQgZGZ0ID0gbmV3IERGVEZsb2F0MzIoZGZ0U2l6ZSk7XHJcbiAgICAgICAgICAgIGxldCB3ZiA9IG5ldyBHYXVzc2lhbldpbmRvdyhkZnRTaXplKTtcclxuXHJcbiAgICAgICAgICAgIGxldCBhcnJTaXplPXcqaCo0O1xyXG4gICAgICAgICAgICBpZihhcnJTaXplPDApe1xyXG4gICAgICAgICAgICAgICAgYXJyU2l6ZT0wXHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgbGV0IGltZ0RhdGEgPSBuZXcgVWludDhDbGFtcGVkQXJyYXkoYXJyU2l6ZSk7XHJcbiAgICAgICAgICAgIC8vY29uc29sZS5sb2coXCJSZW5kZXIgbWV0aG9kOlwiKTtcclxuICAgICAgICAgIC8vY29uc29sZS5kZWJ1ZyhcIkNyZWF0ZWQgaW1nRGF0YSBhcnJTaXplOiBcIithcnJTaXplK1wiIFwiLCB3LCBcInhcIiwgaCk7XHJcbiAgICAgICAgICBsZXQgY2FsY01heFBzZD0tSW5maW5pdHk7XHJcbiAgICAgICAgICAgIGlmIChhcnJTaXplPjApIHtcclxuXHJcbiAgICAgICAgICAgICAgICBsZXQgY2hIID0gTWF0aC5yb3VuZChoIC8gY2hzKTtcclxuICAgICAgICAgICAgICAgIGxldCBmcmFtZXNQZXJQaXhlbCA9IGZyYW1lTGVuZ3RoIC8gdnc7XHJcbiAgICAgICAgICAgICAgICAvL2NvbnNvbGUuZGVidWcoXCJSZW5kZXI6IFwiLCB3LCBcInhcIiwgaCk7XHJcblxyXG4gICAgICAgICAgICAgICAgbGV0IGIgPSBuZXcgRmxvYXQzMkFycmF5KGRmdFNpemUpO1xyXG4gICAgICAgICAgICAgICAgbGV0IHNvbmEgPSBuZXcgQXJyYXkoY2hzKTtcclxuXHJcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBjaCA9IDA7IGNoIDwgY2hzOyBjaCsrKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGxldCBjaERhdGFMZW49YXVkaW9EYXRhW2NoXS5sZW5ndGg7XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gaW5pdGlhbGl6ZSBERlQgYXJyYXkgYnVmZmVyXHJcbiAgICAgICAgICAgICAgICAgICAgc29uYVtjaF0gPSBuZXcgQXJyYXkodyk7XHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IGZyYW1lUG9zID0gMDtcclxuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBwaWkgPSAwOyBwaWkgPCB3OyBwaWkrKykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgdmlydFBpaSA9IGwgKyBwaWk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFBvc2l0aW9uIG9mIHNhbXBsZSBkYXRhIGZyYW1lIGlzIHBpeGVsIHBvc2l0aW9uIG1hcHBlZCB0byBhdWRpbyBmcmFtZSBwb3NpdGlvbi5cclxuICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGVuIFwiY2VudGVyXCIgdGhlIGZyYW1lIGJ5IHNoaWZ0aW5nIGxlZnQgYnkgaGFsZiB0aGUgREZUIHNpemUgKD1kZnRCYW5kcylcclxuICAgICAgICAgICAgICAgICAgICAgICAgZnJhbWVQb3MgPSBNYXRoLnJvdW5kKCh2aXJ0UGlpICogZnJhbWVzUGVyUGl4ZWwpLWRmdEJhbmRzKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZmlsbCBERlQgYnVmZmVyIHdpdGggd2luZG93ZWQgc2FtcGxlIHZhbHVlc1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGRmdFNpemU7IGkrKykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHNhbXBsZVBvcz1mcmFtZVBvcyArIGk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpbml0aWFsaXplIGZvciBuZWdhdGl2ZSBzYW1wbGUgcG9zaXRpb25zIGFuZCBvdXQgb2YgYm91bmRzIHBvc2l0aW9uc1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGNoRGF0PTA7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2V0IGF1ZGlvIHNhbXBsZSBpZiBhdmFpbGFibGVcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBhZHA9c2FtcGxlUG9zLWF1ZGlvRGF0YU9mZnNldDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmKGFkcD49MCAmJiBhZHAgPCBjaERhdGFMZW4pIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hEYXQgPSBhdWRpb0RhdGFbY2hdW2FkcF07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vY29uc29sZS5kZWJ1ZyhcIkF1ZGlvIGRhdGE6IFwiK2NoRGF0KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1lbHNle1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvL2NvbnNvbGUuZGVidWcoXCJTYW1wbGUgYnVmIHBvcyBvb2I6IGFkcDogXCIrYWRwK1wiLCBjaERhdGFMZW46IFwiK2NoRGF0YUxlbitcIiwgc2FtcGxlUG9zOiBcIitzYW1wbGVQb3MrXCIsIGk6IFwiK2kpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFwcGx5IFdpbmRvd1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYltpXSA9IGNoRGF0ICogd2YuZ2V0U2NhbGUoaSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ2FsYyBERlQgbWFnbml0dWRlc1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgc3BlY3RyID0gZGZ0LnByb2Nlc3NSZWFsTWFnbml0dWRlKGIpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gR2V0IG1heGltdW0gdmFsdWUgb2Ygc3BlY3RyYWwgZW5lcmd5XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IHMgPSAwOyBzIDwgZGZ0QmFuZHM7IHMrKykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHBzZCA9ICgyICogTWF0aC5wb3coc3BlY3RyW3NdLCAyKSkgLyBkZnRCYW5kcztcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwc2QgPiBjYWxjTWF4UHNkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FsY01heFBzZCA9IHBzZDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBTZXQgcmVuZGVyIG1vZGVsIGRhdGEgZm9yIHRoaXMgcGl4ZWxcclxuICAgICAgICAgICAgICAgICAgICAgICAgc29uYVtjaF1bcGlpXSA9IHNwZWN0cjtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgaWYoIW1zZy5kYXRhLm5vcmVuZGVyKSB7XHJcbiAgICAgICAgICAgICAgICAgIGlmKCFtYXhQc2Qpe1xyXG4gICAgICAgICAgICAgICAgICAgIG1heFBzZD1jYWxjTWF4UHNkO1xyXG4gICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBjaCA9IDA7IGNoIDwgY2hzOyBjaCsrKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgICBmb3IgKGxldCBwaWkgPSAwOyBwaWkgPCB3OyBwaWkrKykge1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCBhbGxCbGFjayA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgeSA9IDA7IHkgPCBjaEg7IHkrKykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgbGV0IGZyZXFJZHggPSBNYXRoLnJvdW5kKHkgKiBkZnRCYW5kcyAvIGNoSCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAvLyBjYWxjdWxhdGUgdGhlIG9uZS1zaWRlZCBwb3dlciBzcGVjdHJhbCBkZW5zaXR5IFBTRCAoZiwgdCkgaW4gUGEyL0h6XHJcbiAgICAgICAgICAgICAgICAgICAgICAvLyBQU0QoZikgcHJvcG9ydGlvbmFsIHRvIDJ8WChmKXwyIC8gKHQyIC0gdDEpXHJcbiAgICAgICAgICAgICAgICAgICAgICBsZXQgdmFsID0gc29uYVtjaF1bcGlpXVtmcmVxSWR4XTtcclxuICAgICAgICAgICAgICAgICAgICAgIGxldCBwc2QgPSAoMiAqIE1hdGgucG93KHZhbCwgMikpIC8gZGZ0QmFuZHM7XHJcbiAgICAgICAgICAgICAgICAgICAgICAvLyBDYWxjdWxhdGUgbG9nYXJpdGhtaWMgdmFsdWVcclxuICAgICAgICAgICAgICAgICAgICAgIC8vbGV0IHBzZExvZyA9IGlwcy5kc3AuRFNQVXRpbHMudG9MZXZlbEluREIocHNkIC8gbWF4UHNkKTtcclxuICAgICAgICAgICAgICAgICAgICAgIGxldCBsaW5lYXJMZXZlbCA9IHBzZCAvIG1heFBzZDtcclxuICAgICAgICAgICAgICAgICAgICAgIGxldCBwc2RMb2cgPSAxMCAqIE1hdGgubG9nKGxpbmVhckxldmVsKSAvIE1hdGgubG9nKDEwKTtcclxuICAgICAgICAgICAgICAgICAgICAgIC8vIEZpeGVkIGR5bmFtaWMgUmFuZ2UgdmFsdWUgb2YgNzBkQiBmb3Igbm93XHJcbiAgICAgICAgICAgICAgICAgICAgICBsZXQgZHluUmFuZ2VJbkRiID0gNzA7XHJcbiAgICAgICAgICAgICAgICAgICAgICBsZXQgc2NhbGVkVmFsID0gKHBzZExvZyArIGR5blJhbmdlSW5EYikgLyBkeW5SYW5nZUluRGI7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgLy8gYXJlIHRoZSBmb2xsb3dpbmcgY2hlY2tzIG5lY2Vzc2FyeSBmb3IgY2xhbXBlZCBhcnJheSA/XHJcbiAgICAgICAgICAgICAgICAgICAgICBpZiAoc2NhbGVkVmFsID4gMS4wKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBzY2FsZWRWYWwgPSAxO1xyXG4gICAgICAgICAgICAgICAgICAgICAgaWYgKHNjYWxlZFZhbCA8IDAuMCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBzY2FsZWRWYWwgPSAwO1xyXG4gICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgbGV0IHJnYlZhbCA9IE1hdGgucm91bmQoMjU1ICogc2NhbGVkVmFsKTtcclxuICAgICAgICAgICAgICAgICAgICAgIGlmIChyZ2JWYWwgPCAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vXHRcdFx0XHRcdFx0XHRTeXN0ZW0ub3V0LnByaW50bG4oXCJOZWcgUkdCIHZhbDogXCIrcmdiVmFsKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmdiVmFsID0gMDtcclxuICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgIGlmIChyZ2JWYWwgPiAyNTUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmdiVmFsID0gMjU1O1xyXG4gICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgcmdiVmFsID0gMjU1IC0gcmdiVmFsO1xyXG4gICAgICAgICAgICAgICAgICAgICAgaWYgKHJnYlZhbCA+IDApIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgYWxsQmxhY2sgPSBmYWxzZTtcclxuICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgIGxldCBweSA9IGNoSCAtIHk7XHJcbiAgICAgICAgICAgICAgICAgICAgICBsZXQgZGF0YVBvcyA9ICgoKChjaCAqIGNoSCkgKyBweSkgKiB3KSArIHBpaSkgKiA0O1xyXG4gICAgICAgICAgICAgICAgICAgICAgaW1nRGF0YVtkYXRhUG9zICsgMF0gPSByZ2JWYWw7IC8vUlxyXG4gICAgICAgICAgICAgICAgICAgICAgaW1nRGF0YVtkYXRhUG9zICsgMV0gPSByZ2JWYWw7IC8vR1xyXG4gICAgICAgICAgICAgICAgICAgICAgaW1nRGF0YVtkYXRhUG9zICsgMl0gPSByZ2JWYWw7IC8vQlxyXG4gICAgICAgICAgICAgICAgICAgICAgaW1nRGF0YVtkYXRhUG9zICsgM10gPSAyNTU7IC8vQSAoYWxwaGE6IGZ1bGx5IG9wYXF1ZSlcclxuICAgICAgICAgICAgICAgICAgICAgIC8vY29uc29sZS5kZWJ1ZyhcIlJlbmRlcmVkOiBweTogXCIrcHkrXCIsIHJnYnZhbDogXCIrcmdiVmFsKTtcclxuICAgICAgICAgICAgICAgICAgICAgIC8vIGV4YW1wbGUgMXgxLCAyY2hzXHJcbiAgICAgICAgICAgICAgICAgICAgICAvLyAgY2gweDB5MFIsY2gweDB5MEcsY2gweDB5MEIsY2gweDB5MEEsXHJcbiAgICAgICAgICAgICAgICAgICAgICAvLyAgY2gweDF5MFIsY2gweDF5MEcsY2gweDF5MEIsY2gweDF5MEEsXHJcbiAgICAgICAgICAgICAgICAgICAgICAvLyAgY2gweDB5MFIsY2gweDB5MEcsY2gweDB5MEIsY2gweDB5MEEsXHJcbiAgICAgICAgICAgICAgICAgICAgICAvLyAgY2gweDF5MVIsY2gweDF5MUcsY2gweDF5MUIsY2gweDF5MUEsXHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgLy8gIGNoMXgweTBSLGNoMXgweTBHLGNoMXgweTBCLGNoMXgweTBBLFxyXG4gICAgICAgICAgICAgICAgICAgICAgLy8gIGNoMXgxeTBSLGNoMXgxeTBHLGNoMXgxeTBCLGNoMXgxeTBBLFxyXG4gICAgICAgICAgICAgICAgICAgICAgLy8gIGNoMXgweTBSLGNoMXgweTBHLGNoMXgweTBCLGNoMXgweTBBLFxyXG4gICAgICAgICAgICAgICAgICAgICAgLy8gIGNoMXgxeTFSLGNoMXgxeTFHLGNoMXgxeTFCLGNoMXgxeTFBXHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIC8vIGlmIChhbGxCbGFjaykge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vICAgY29uc29sZS5sb2coXCJCbGFjazogXCIsIHBpaSwgXCIgXCIsIGNoKTtcclxuICAgICAgICAgICAgICAgICAgICAvLyB9XHJcbiAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAvL2NvbnNvbGUuZGVidWcoXCJSZW5kZXIgdGhyZWFkIHBvc3QgbWVzc2FnZSBpbWdEYXRhOiBcIitpbWdEYXRhLmxlbmd0aClcclxuICAgICAgICAgICAgcG9zdE1lc3NhZ2Uoe2ltZ0RhdGE6IGltZ0RhdGEsIGw6IGwsIHc6IG1zZy5kYXRhLncsIGg6IG1zZy5kYXRhLmgsIHZ3OiB2dyxtYXhQc2Q6Y2FsY01heFBzZCx0ZXJtaW5hdGU6bXNnLmRhdGEudGVybWluYXRlfSwgW2ltZ0RhdGEuYnVmZmVyXSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHN0YXJ0RHJhdyhjbGVhciA9IHRydWUpIHtcclxuICAgICAgICBpZiAoY2xlYXIpIHtcclxuICAgICAgICAgICAgaWYodGhpcy5ib3VuZHMpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuc29uYWdyYW1DYW52YXMuc3R5bGUubGVmdCA9IE1hdGgucm91bmQodGhpcy5ib3VuZHMucG9zaXRpb24ubGVmdCkudG9TdHJpbmcoKSArICdweCc7XHJcbiAgICAgICAgICAgICAgICBsZXQgaW50VyA9IE1hdGgucm91bmQodGhpcy5ib3VuZHMuZGltZW5zaW9uLndpZHRoKVxyXG4gICAgICAgICAgICAgICAgbGV0IGludEggPSBNYXRoLnJvdW5kKHRoaXMuYm91bmRzLmRpbWVuc2lvbi5oZWlnaHQpXHJcbiAgICAgICAgICAgICAgICB0aGlzLnNvbmFncmFtQ2FudmFzLndpZHRoID0gaW50VztcclxuICAgICAgICAgICAgICAgIHRoaXMuc29uYWdyYW1DYW52YXMuaGVpZ2h0ID0gaW50SDtcclxuXHJcbiAgICAgICAgICAgICAgICBsZXQgZyA9IHRoaXMuc29uYWdyYW1DYW52YXMuZ2V0Q29udGV4dChcIjJkXCIpO1xyXG4gICAgICAgICAgICAgICAgaWYgKGcpIHtcclxuICAgICAgICAgICAgICAgICAgICAvL2cuY2xlYXJSZWN0KDAsIDAsdywgaCk7XHJcbiAgICAgICAgICAgICAgICAgICAgZy5maWxsU3R5bGUgPSBcIndoaXRlXCI7XHJcbiAgICAgICAgICAgICAgICAgICAgZy5maWxsUmVjdCgwLCAwLCBpbnRXLCBpbnRIKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLnN0YXJ0UmVuZGVyKCk7XHJcbiAgICAgICAgdGhpcy5kcmF3Q3Vyc29yTGF5ZXIoKVxyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgc3RhcnRSZW5kZXIoKSB7XHJcbiAgICAgIC8vY29uc29sZS5kZWJ1ZyhcIlNvbmFncmFtIHN0YXJ0IHJlbmRlci4uLlwiKTtcclxuICAgICAgICBpZiAodGhpcy53b3JrZXIpIHtcclxuICAgICAgICAgICAgdGhpcy53b3JrZXIudGVybWluYXRlKCk7XHJcbiAgICAgICAgICAgIHRoaXMud29ya2VyID0gbnVsbDtcclxuICAgICAgICB9XHJcbiAgICAgIGlmKHRoaXMucmFBc1N1YnNjKXtcclxuICAgICAgICB0aGlzLnJhQXNTdWJzYy51bnN1YnNjcmliZSgpO1xyXG4gICAgICB9XHJcbiAgICAgIGlmICh0aGlzLl9hdWRpb0RhdGFIb2xkZXIpIHtcclxuICAgICAgICB0aGlzLl9hdWRpb0RhdGFIb2xkZXIuYWRkT25SZWFkeUxpc3RlbmVyKCgpPT4ge1xyXG4gICAgICAgICAgaWYgKHRoaXMuX2F1ZGlvRGF0YUhvbGRlciAmJiB0aGlzLmJvdW5kcyAmJiB0aGlzLmJvdW5kcy5kaW1lbnNpb24pIHtcclxuICAgICAgICAgICAgbGV0IHcgPSBNYXRoLnJvdW5kKHRoaXMuYm91bmRzLmRpbWVuc2lvbi53aWR0aCk7XHJcbiAgICAgICAgICAgIGxldCBoID0gTWF0aC5yb3VuZCh0aGlzLmJvdW5kcy5kaW1lbnNpb24uaGVpZ2h0KTtcclxuICAgICAgICAgICAgbGV0IHZ3ID0gTWF0aC5yb3VuZCh0aGlzLnZpcnR1YWxEaW1lbnNpb24ud2lkdGgpO1xyXG5cclxuICAgICAgICAgICAgaWYgKHcgPiAwICYmIGggPiAwICYmIHZ3ID4gMCkge1xyXG5cclxuICAgICAgICAgICAgICB0aGlzLndvcmtlciA9IG5ldyBXb3JrZXIodGhpcy53b3JrZXJVUkwpO1xyXG4gICAgICAgICAgICAgIC8vdGhpcy53byA9IG5ldyBXb3JrZXIoJy4vd29ya2VyL3NvbmFncmFtLndvcmtlcicsIHsgdHlwZTogYG1vZHVsZWAgfSk7XHJcblxyXG4gICAgICAgICAgICAgIGxldCBjaHMgPSB0aGlzLl9hdWRpb0RhdGFIb2xkZXIubnVtYmVyT2ZDaGFubmVscztcclxuICAgICAgICAgICAgICBsZXQgdncgPSBNYXRoLnJvdW5kKHRoaXMudmlydHVhbERpbWVuc2lvbi53aWR0aCk7XHJcblxyXG4gICAgICAgICAgICAgIGxldCBmcmFtZUxlbmd0aCA9IHRoaXMuX2F1ZGlvRGF0YUhvbGRlci5mcmFtZUxlbjtcclxuICAgICAgICAgICAgICBsZXQgZnJhbWVzUGVyUGl4ZWwgPSBNYXRoLmNlaWwoZnJhbWVMZW5ndGggLyB2dyk7XHJcbiAgICAgICAgICAgICAgbGV0IGxlZnRQb3MgPSBNYXRoLnJvdW5kKHRoaXMuYm91bmRzLnBvc2l0aW9uLmxlZnQpO1xyXG4gICAgICAgICAgICAgIGxldCByZW5kZXJQb3MgPSBsZWZ0UG9zO1xyXG4gICAgICAgICAgICAgIGxldCByYUFzID0gdGhpcy5fYXVkaW9EYXRhSG9sZGVyLnJhbmRvbUFjY2Vzc0F1ZGlvU3RyZWFtKCk7XHJcblxyXG4gICAgICAgICAgICAgIGxldCBhdWRpb0J1ZmZlcjogQXVkaW9CdWZmZXIgfCBudWxsID0gbnVsbDtcclxuICAgICAgICAgICAgICBsZXQgYXVkaW9Tb3VyY2UgPSB0aGlzLl9hdWRpb0RhdGFIb2xkZXIuYXVkaW9Tb3VyY2U7XHJcbiAgICAgICAgICAgICAgaWYgKGF1ZGlvU291cmNlIGluc3RhbmNlb2YgQXVkaW9CdWZmZXJTb3VyY2UpIHtcclxuICAgICAgICAgICAgICAgIGF1ZGlvQnVmZmVyID0gYXVkaW9Tb3VyY2UuYXVkaW9CdWZmZXI7XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIC8vbGV0IGFycmF5QXVkaW9CdWZmZXI9dGhpcy5fYXVkaW9EYXRhSG9sZGVyLmFycmF5QnVmZmVyO1xyXG4gICAgICAgICAgICAgIGxldCBhcnJBYkJ1ZjogRmxvYXQzMkFycmF5W10gfCBudWxsO1xyXG4gICAgICAgICAgICAgIGxldCBhZGEgPSBuZXcgQXJyYXk8QXJyYXlCdWZmZXI+KGNocyk7XHJcbiAgICAgICAgICAgICAgLy8gZm9yKGxldCBjaD0wO2NoPGNocztjaCsrKSB7XHJcbiAgICAgICAgICAgICAgLy8gICBhZGFbY2hdID0gbmV3IEZsb2F0MzJBcnJheSh0aGlzLmRmdFNpemUpO1xyXG4gICAgICAgICAgICAgIC8vIH1cclxuICAgICAgICAgICAgICBsZXQgaW1nRGF0YTogVWludDhDbGFtcGVkQXJyYXk7XHJcbiAgICAgICAgICAgICAgbGV0IG1heFBzZCA9IC1JbmZpbml0eTtcclxuICAgICAgICAgICAgICBsZXQgbm9yZW5kZXIgPSB0cnVlO1xyXG5cclxuICAgICAgICAgICAgICBpZiAodGhpcy53b3JrZXIpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMud29ya2VyLm9ubWVzc2FnZSA9IChtZSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICBpZiAodHJ1ZSA9PT0gbWUuZGF0YS50ZXJtaW5hdGUpIHtcclxuICAgICAgICAgICAgICAgICAgICBsZXQgZHJhd0ltZ0RhdGE7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGltZ0RhdGEpIHtcclxuICAgICAgICAgICAgICAgICAgICAgIGRyYXdJbWdEYXRhID0gaW1nRGF0YTtcclxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgZHJhd0ltZ0RhdGEgPSBtZS5kYXRhLmltZ0RhdGE7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZHJhd1JlbmRlcmVkKHcsIGgsIGRyYXdJbWdEYXRhKTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy53b3JrZXIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgIHRoaXMud29ya2VyLnRlcm1pbmF0ZSgpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB0aGlzLndvcmtlciA9IG51bGw7XHJcbiAgICAgICAgICAgICAgICAgICAgcmFBcy5jbG9zZSgpO1xyXG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAvLyBzZXQgcmVuZGVyZWQgdmVydGljYWwgdmFsdWVzIG9mIG9uZSBwaXhlbCBvZiB0aW1lc2NhbGVcclxuICAgICAgICAgICAgICAgICAgICAvL2xldCBkYXRhUG9zID0gcmVuZGVyUG9zICogaCAqIDQ7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5vcmVuZGVyKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICBpZiAobWUuZGF0YS5tYXhQc2QgPiBtYXhQc2QpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbWF4UHNkID0gbWUuZGF0YS5tYXhQc2Q7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vY29uc29sZS5kZWJ1ZyhcIm5ldyBtYXhQc2Q6IFwiK21heFBzZCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgIGxldCBjaEggPSBNYXRoLnJvdW5kKGggLyBjaHMpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgbGV0IGlkcCA9IG1lLmRhdGEubCAtIGxlZnRQb3M7XHJcbiAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBjaCA9IDA7IGNoIDwgY2hzOyBjaCsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IHkgPSAwOyB5IDwgY2hIOyB5KyspIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgcHkgPSBjaEggLSB5O1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBkYXRhUG9zID0gKCgoKGNoICogY2hIKSArIHB5KSAqIHcpICsgaWRwKSAqIDQ7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IG1lUG9zID0gKChjaCAqIGNoSCkgKyBweSkgKiA0O1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vbGV0IGxhc3RQb3MgPSBkYXRhUG9zICsgbWUuZGF0YS5pbWdEYXRhLmxlbmd0aDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAvL2lmIChsYXN0UG9zIDwgaW1nRGF0YS5sZW5ndGgpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBzZXQgb25lIHBpeGVsXHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGltZ0RhdGFbZGF0YVBvc10gPSBtZS5kYXRhLmltZ0RhdGFbbWVQb3NdO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGltZ0RhdGFbZGF0YVBvcyArIDFdID0gbWUuZGF0YS5pbWdEYXRhW21lUG9zICsgMV07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaW1nRGF0YVtkYXRhUG9zICsgMl0gPSBtZS5kYXRhLmltZ0RhdGFbbWVQb3MgKyAyXTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICBpbWdEYXRhW2RhdGFQb3MgKyAzXSA9IG1lLmRhdGEuaW1nRGF0YVttZVBvcyArIDNdO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAvL2NvbnNvbGUuZXJyb3IoXCJPdXQgb2YgcmFuZ2U6IFwiICsgZGF0YVBvcyArIFwiK1wiICsgbWUuZGF0YS5pbWdEYXRhLmxlbmd0aCArIFwiPj1cIiArIGltZ0RhdGEubGVuZ3RoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX2F1ZGlvRGF0YUhvbGRlciAmJiBhcnJBYkJ1ZiAmJiB0aGlzLndvcmtlcikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgLy8gcHJvY2VlZCB3aXRoIG5leHQgcGl4ZWxcclxuICAgICAgICAgICAgICAgICAgICAgIHJlbmRlclBvcysrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgLy9jb25zb2xlLmRlYnVnKFwiUmVuZGVyIHBvczogXCIrcmVuZGVyUG9zKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICBsZXQgdGVybWluYXRlID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICAgICAgICBsZXQgd2luZG93RW5kID0gcmVuZGVyUG9zID49IGxlZnRQb3MgKyB3O1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgIGlmICh3aW5kb3dFbmQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG5vcmVuZGVyKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gcGhhc2UgdHdvOiByZW5kZXJpbmdcclxuICAgICAgICAgICAgICAgICAgICAgICAgICBub3JlbmRlciA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHN0YXJ0IGZyb20gYmVnaW5uaW5nXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcmVuZGVyUG9zID0gbGVmdFBvcztcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAvL2NvbnNvbGUuZGVidWcoXCJub3cgcmVuZGVyaW5nOiBtYXhQc2Q6IFwiK21heFBzZCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGVybWluYXRlIHJlbmRlciBwaGFzZVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHRlcm1pbmF0ZSA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICBsZXQgbGVmdEZyYW1lUG9zID0gTWF0aC5mbG9vcihmcmFtZUxlbmd0aCAqIHJlbmRlclBvcyAvIHZ3KSAtIHRoaXMuZGZ0U2l6ZSAvIDI7XHJcbiAgICAgICAgICAgICAgICAgICAgICBpZiAobGVmdEZyYW1lUG9zIDwgMCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZWZ0RnJhbWVQb3MgPSAwO1xyXG4gICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgLy9sZXQgYWRhID0gbmV3IEFycmF5PEFycmF5QnVmZmVyPihjaHMpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgIC8vY29uc29sZS5kZWJ1ZyhcIlJlbmRlciBwb3M6IFwiK3JlbmRlclBvcytcIiBsZWZ0RnJhbWVQb3M6IFwiK2xlZnRGcmFtZVBvcyk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgaWYgKCF0ZXJtaW5hdGUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX2F1ZGlvRGF0YUhvbGRlcikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vbGV0IHJlYWQgPSB0aGlzLl9hdWRpb0RhdGFIb2xkZXIuZnJhbWVzKGxlZnRGcmFtZVBvcywgdGhpcy5kZnRTaXplLCBhcnJBYkJ1Zik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yYUFzU3Vic2MgPSByYUFzLmZyYW1lc09icyhsZWZ0RnJhbWVQb3MsIHRoaXMuZGZ0U2l6ZSwgYXJyQWJCdWYpLnN1YnNjcmliZShcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV4dDogKHJlYWQpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXJyQWJCdWYgJiYgdGhpcy53b3JrZXIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZWFkIDwgdGhpcy5kZnRTaXplKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHplcm8gcGFkZGluZ1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBjaCA9IDA7IGNoIDwgY2hzOyBjaCsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgenAgPSByZWFkOyB6cCA8IHRoaXMuZGZ0U2l6ZTsgenArKykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJyQWJCdWZbY2hdW3pwXSA9IDA7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBjaCA9IDA7IGNoIDwgY2hzOyBjaCsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE5lZWQgYSBjb3B5IGhlcmUgZm9yIHRoZSB3b3JrZXIsIG90aGVyd2lzZSB0aGlzLmF1ZGlvRGF0YSBpcyBub3QgYWNjZXNzaWJsZSBhZnRlciBwb3N0aW5nIHRvIHRoZSB3b3JrZXJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy9hZGFbY2hdID0gYXJyQWJCdWZbY2hdLmJ1ZmZlci5zbGljZSgwKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYXJyQWJCdWZDaCA9IGFyckFiQnVmW2NoXTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYWRMZW4gPSBhcnJBYkJ1ZkNoLmJ1ZmZlci5ieXRlTGVuZ3RoO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWFkYVtjaF0gfHwgYWRhW2NoXS5ieXRlTGVuZ3RoICE9PSBhZExlbikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFkYVtjaF0gPSBuZXcgQXJyYXlCdWZmZXIoYWRMZW4pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBmQWRhQ2ggPSBuZXcgRmxvYXQzMkFycmF5KGFkYVtjaF0pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmQWRhQ2guc2V0KGFyckFiQnVmW2NoXSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy53b3JrZXIucG9zdE1lc3NhZ2Uoe1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdWRpb0RhdGE6IGFkYSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXVkaW9EYXRhT2Zmc2V0OiBsZWZ0RnJhbWVQb3MsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGw6IHJlbmRlclBvcyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdzogbWUuZGF0YS53LFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoOiBoLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2dzogdncsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoczogY2hzLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmcmFtZUxlbmd0aDogZnJhbWVMZW5ndGgsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRmdFNpemU6IHRoaXMuZGZ0U2l6ZSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4UHNkOiBtYXhQc2QsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vcmVuZGVyOiBub3JlbmRlcixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGVybWluYXRlOiB0ZXJtaW5hdGVcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIGFkYSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvcjogKGVycikgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJTb25hZ3JhbTogRXJyb3IgcmVhZGluZyBhdWRpbyBkYXRhOiBcIiArIGVycik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICApXHJcblxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgY2ggPSAwOyBjaCA8IGNoczsgY2grKykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGFkYVtjaF0gPSBuZXcgQXJyYXlCdWZmZXIoMCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy53b3JrZXIucG9zdE1lc3NhZ2Uoe1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGF1ZGlvRGF0YTogYWRhLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGF1ZGlvRGF0YU9mZnNldDogbGVmdEZyYW1lUG9zLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGw6IHJlbmRlclBvcyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICB3OiBtZS5kYXRhLncsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaDogaCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICB2dzogdncsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY2hzOiBjaHMsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZnJhbWVMZW5ndGg6IGZyYW1lTGVuZ3RoLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGRmdFNpemU6IHRoaXMuZGZ0U2l6ZSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhQc2Q6IG1heFBzZCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICBub3JlbmRlcjogbm9yZW5kZXIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgdGVybWluYXRlOiB0ZXJtaW5hdGVcclxuICAgICAgICAgICAgICAgICAgICAgICAgfSwgYWRhKTtcclxuICAgICAgICAgICAgICAgICAgICAgIH1cclxuXHJcblxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgaWYgKGF1ZGlvQnVmZmVyICYmIGF1ZGlvQnVmZmVyLmxlbmd0aCAqIGF1ZGlvQnVmZmVyLm51bWJlck9mQ2hhbm5lbHMgPCBBdWRpb0NhbnZhc0xheWVyQ29tcG9uZW50LkVOQUJMRV9TVFJFQU1JTkdfTlVNQkVSX09GX1NBTVBMRVNfVEhSRVNIT0xEKSB7XHJcbiAgICAgICAgICAgICAgICBsZXQgYWRhID0gbmV3IEFycmF5PEFycmF5QnVmZmVyPihjaHMpO1xyXG4gICAgICAgICAgICAgICAgZm9yIChsZXQgY2ggPSAwOyBjaCA8IGNoczsgY2grKykge1xyXG4gICAgICAgICAgICAgICAgICAvLyBOZWVkIGEgY29weSBoZXJlIGZvciB0aGUgd29ya2VyLCBvdGhlcndpc2UgdGhpcy5hdWRpb0RhdGEgaXMgbm90IGFjY2Vzc2libGUgYWZ0ZXIgcG9zdGluZyB0byB0aGUgd29ya2VyXHJcbiAgICAgICAgICAgICAgICAgIGFkYVtjaF0gPSBhdWRpb0J1ZmZlci5nZXRDaGFubmVsRGF0YShjaCkuYnVmZmVyLnNsaWNlKDApO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgLy9sZXQgc3RhcnQgPSBEYXRlLm5vdygpO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLm1hcmtlckNhbnZhcykge1xyXG4gICAgICAgICAgICAgICAgICBsZXQgZyA9IHRoaXMubWFya2VyQ2FudmFzLmdldENvbnRleHQoXCIyZFwiKTtcclxuICAgICAgICAgICAgICAgICAgaWYgKGcpIHtcclxuICAgICAgICAgICAgICAgICAgICBnLmZpbGxUZXh0KFwiUmVuZGVyaW5nLi4uXCIsIDEwLCAyMCk7XHJcbiAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB0aGlzLndvcmtlci5wb3N0TWVzc2FnZSh7XHJcbiAgICAgICAgICAgICAgICAgIGF1ZGlvRGF0YTogYWRhLFxyXG4gICAgICAgICAgICAgICAgICBsOiBsZWZ0UG9zLFxyXG4gICAgICAgICAgICAgICAgICB3OiB3LFxyXG4gICAgICAgICAgICAgICAgICBoOiBoLFxyXG4gICAgICAgICAgICAgICAgICB2dzogTWF0aC5yb3VuZCh0aGlzLnZpcnR1YWxEaW1lbnNpb24ud2lkdGgpLFxyXG4gICAgICAgICAgICAgICAgICBjaHM6IGNocyxcclxuICAgICAgICAgICAgICAgICAgZnJhbWVMZW5ndGg6IGZyYW1lTGVuZ3RoLFxyXG4gICAgICAgICAgICAgICAgICBkZnRTaXplOiB0aGlzLmRmdFNpemUsXHJcbiAgICAgICAgICAgICAgICAgIHRlcm1pbmF0ZTogdHJ1ZVxyXG4gICAgICAgICAgICAgICAgfSwgYWRhKTtcclxuICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgaWYgKHcgPiAwKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgICBpZiAoZnJhbWVzUGVyUGl4ZWwgPiAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IGFyclNpemUgPSB3ICogaCAqIDQ7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGFyclNpemUgPCAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICBhcnJTaXplID0gMFxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBpbWdEYXRhID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KGFyclNpemUpO1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCBydyA9IDE7XHJcbiAgICAgICAgICAgICAgICAgICAgYXJyQWJCdWYgPSBuZXcgQXJyYXk8RmxvYXQzMkFycmF5PihjaHMpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBjaCA9IDA7IGNoIDwgY2hzOyBjaCsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICBhcnJBYkJ1ZltjaF0gPSBuZXcgRmxvYXQzMkFycmF5KHRoaXMuZGZ0U2l6ZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICBsZXQgbGVmdEZyYW1lUG9zID0gTWF0aC5mbG9vcihmcmFtZUxlbmd0aCAqIHJlbmRlclBvcyAvIHZ3KSAtIHRoaXMuZGZ0U2l6ZSAvIDI7XHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IGZyYW1lc1RvUmVhZCA9IHRoaXMuZGZ0U2l6ZTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAobGVmdEZyYW1lUG9zIDwgMCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgbGVmdEZyYW1lUG9zID0gMDtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kcmF3U3RhdGVUZXh0KCdMb2FkaW5nL1JlbmRlcmluZy4uLicpO1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmFBc1N1YnNjID0gcmFBcy5mcmFtZXNPYnMobGVmdEZyYW1lUG9zLCBmcmFtZXNUb1JlYWQsIGFyckFiQnVmKS5zdWJzY3JpYmUoXHJcbiAgICAgICAgICAgICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG5leHQ6IChyZWFkKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFyckFiQnVmICYmIHRoaXMud29ya2VyKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVhZCA8IHRoaXMuZGZ0U2l6ZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB6ZXJvIHBhZGRpbmdcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgY2ggPSAwOyBjaCA8IGNoczsgY2grKykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IHpwID0gcmVhZDsgenAgPCB0aGlzLmRmdFNpemU7IHpwKyspIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyckFiQnVmW2NoXVt6cF0gPSAwO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgY2ggPSAwOyBjaCA8IGNoczsgY2grKykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBhcnJBYkJ1ZkNoID0gYXJyQWJCdWZbY2hdO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBhZExlbiA9IGFyckFiQnVmQ2guYnVmZmVyLmJ5dGVMZW5ndGg7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghYWRhW2NoXSB8fCBhZGFbY2hdLmJ5dGVMZW5ndGggIT09IGFkTGVuKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWRhW2NoXSA9IG5ldyBBcnJheUJ1ZmZlcihhZExlbik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGZBZGFDaCA9IG5ldyBGbG9hdDMyQXJyYXkoYWRhW2NoXSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZBZGFDaC5zZXQoYXJyQWJCdWZbY2hdKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLndvcmtlci5wb3N0TWVzc2FnZSh7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGw6IHJlbmRlclBvcyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdzogcncsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGg6IGgsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZ3OiB2dyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hzOiBjaHMsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZyYW1lTGVuZ3RoOiBmcmFtZUxlbmd0aCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXVkaW9EYXRhOiBhZGEsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1ZGlvRGF0YU9mZnNldDogbGVmdEZyYW1lUG9zLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZnRTaXplOiB0aGlzLmRmdFNpemUsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vcmVuZGVyOiBub3JlbmRlcixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGVybWluYXRlOiBmYWxzZVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwgYWRhKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yOiAoZXJyKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIlNvbmFncmFtOiBFcnJvciByZWFkaW5nIGF1ZGlvIGRhdGE6IFwiICsgZXJyKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICBpZiAodGhpcy5ib3VuZHMgJiYgdGhpcy5ib3VuZHMuZGltZW5zaW9uKSB7XHJcbiAgICAgICAgICBsZXQgdyA9IE1hdGgucm91bmQodGhpcy5ib3VuZHMuZGltZW5zaW9uLndpZHRoKTtcclxuICAgICAgICAgIGxldCBoID0gTWF0aC5yb3VuZCh0aGlzLmJvdW5kcy5kaW1lbnNpb24uaGVpZ2h0KTtcclxuICAgICAgICAgIGxldCBnID0gdGhpcy5zb25hZ3JhbUNhbnZhcy5nZXRDb250ZXh0KFwiMmRcIik7XHJcbiAgICAgICAgICBpZiAoZykge1xyXG4gICAgICAgICAgICBnLmNsZWFyUmVjdCgwLCAwLCB3LCBoKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBkcmF3UmVuZGVyZWQodzpudW1iZXIsaDpudW1iZXIsaW1nRGF0YTpVaW50OENsYW1wZWRBcnJheSkge1xyXG4gICAgICAgIGlmICh0aGlzLnNvbmFncmFtQ2FudmFzKSB7XHJcbiAgICAgICAgICAgIHRoaXMuc29uYWdyYW1DYW52YXMud2lkdGggPSB3O1xyXG4gICAgICAgICAgICB0aGlzLnNvbmFncmFtQ2FudmFzLmhlaWdodCA9IGg7XHJcbiAgICAgICAgICAgIGxldCBnID0gdGhpcy5zb25hZ3JhbUNhbnZhcy5nZXRDb250ZXh0KFwiMmRcIik7XHJcbiAgICAgICAgICAgIGlmIChnKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAodyA+IDAgJiYgaCA+IDApIHtcclxuICAgICAgICAgICAgICAgICAgICBsZXQgZ0ltZ0RhdGEgPSBnLmNyZWF0ZUltYWdlRGF0YSh3LCBoKTtcclxuICAgICAgICAgICAgICAgICAgICBnSW1nRGF0YS5kYXRhLnNldChpbWdEYXRhKTtcclxuICAgICAgICAgICAgICAgICAgICBnLnB1dEltYWdlRGF0YShnSW1nRGF0YSwgMCwgMCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5kcmF3QmcoKTtcclxuICAgICAgICB0aGlzLmRyYXdQbGF5UG9zaXRpb24oKTtcclxuICAgIH1cclxuXHJcbi8vICAgICAvLyBzeW5jaHJvbm91cyBkcmF3IChub3QgdXNlZCBhbnltb3JlKVxyXG4vLyAgIHJlZHJhdygpIHtcclxuLy9cclxuLy8gICAgIGxldCBnID0gdGhpcy5zb25hZ3JhbUNhbnZhcy5nZXRDb250ZXh0KFwiMmRcIik7XHJcbi8vXHJcbi8vICAgICBsZXQgdyA9IHRoaXMuc29uYWdyYW1DYW52YXMud2lkdGg7XHJcbi8vICAgICBsZXQgaCA9IHRoaXMuc29uYWdyYW1DYW52YXMuaGVpZ2h0O1xyXG4vLyAgICAgaWYgKGcpIHtcclxuLy8gICAgICAgZy5jbGVhclJlY3QoMCwgMCwgdywgaCk7XHJcbi8vICAgICAgIGcuZmlsbFN0eWxlID0gXCJ3aGl0ZVwiO1xyXG4vLyAgICAgICBnLmZpbGxSZWN0KDAsIDAsIHcsIGgpO1xyXG4vLyAgICAgICBpZiAodGhpcy5fYXVkaW9EYXRhSG9sZGVyKSB7XHJcbi8vICAgICAgICAgbGV0IHNwZWN0U2l6ZSA9IE1hdGguZmxvb3IodGhpcy5kZnRTaXplIC8gMilcclxuLy8gICAgICAgICBsZXQgY2hzID0gdGhpcy5fYXVkaW9EYXRhSG9sZGVyLm51bWJlck9mQ2hhbm5lbHM7XHJcbi8vICAgICAgICAgbGV0IGNoSCA9IGggLyBjaHM7XHJcbi8vXHJcbi8vICAgICAgICAgbGV0IGZyYW1lTGVuZ3RoID0gdGhpcy5fYXVkaW9EYXRhSG9sZGVyLmZyYW1lTGVuO1xyXG4vL1xyXG4vLyAgICAgICAgIGxldCBmcmFtZXNQZXJQaXhlbCA9IGZyYW1lTGVuZ3RoIC8gdztcclxuLy8gICAgICAgICBsZXQgeSA9IDA7XHJcbi8vICAgICAgICAgbGV0IGF1ZGlvQnVmZmVyOkF1ZGlvQnVmZmVyfG51bGw9bnVsbDtcclxuLy8gICAgICAgICBsZXQgYXVkaW9Tb3VyY2U9dGhpcy5fYXVkaW9EYXRhSG9sZGVyLmF1ZGlvU291cmNlO1xyXG4vLyAgICAgICAgIGlmKGF1ZGlvU291cmNlIGluc3RhbmNlb2YgQXVkaW9CdWZmZXJTb3VyY2Upe1xyXG4vLyAgICAgICAgICAgYXVkaW9CdWZmZXI9YXVkaW9Tb3VyY2UuYXVkaW9CdWZmZXI7XHJcbi8vICAgICAgICAgfVxyXG4vL1xyXG4vLyAgICAgICAgIGlmKGF1ZGlvQnVmZmVyKSB7XHJcbi8vICAgICAgICAgICBsZXQgYiA9IG5ldyBGbG9hdDMyQXJyYXkodGhpcy5kZnRTaXplKVxyXG4vL1xyXG4vLyAgICAgICAgICAgbGV0IHNvbmEgPSBuZXcgQXJyYXk8QXJyYXk8RmxvYXQzMkFycmF5Pj4oY2hzKTtcclxuLy8gICAgICAgICAgIGxldCBtYXggPSAwO1xyXG4vLyAgICAgICAgICAgbGV0IG1heFBzZCA9IC1JbmZpbml0eTtcclxuLy8gICAgICAgICAgIGZvciAobGV0IGNoID0gMDsgY2ggPCBjaHM7IGNoKyspIHtcclxuLy8gICAgICAgICAgICAgbGV0IHggPSAwO1xyXG4vLyAgICAgICAgICAgICBzb25hW2NoXSA9IG5ldyBBcnJheTxGbG9hdDMyQXJyYXk+KHcpO1xyXG4vL1xyXG4vLyAgICAgICAgICAgICBsZXQgY2hEYXRhID0gYXVkaW9CdWZmZXIuZ2V0Q2hhbm5lbERhdGEoY2gpO1xyXG4vLyAgICAgICAgICAgICAvLyBUT0RPIGNlbnRlciBidWZmZXJcclxuLy9cclxuLy8gICAgICAgICAgICAgbGV0IGZyYW1lUG9zID0gMDtcclxuLy8gICAgICAgICAgICAgZm9yIChsZXQgcGlpID0gMDsgcGlpIDwgdzsgcGlpKyspIHtcclxuLy8gICAgICAgICAgICAgICBmcmFtZVBvcyA9IE1hdGgucm91bmQocGlpICogZnJhbWVzUGVyUGl4ZWwpO1xyXG4vLyAgICAgICAgICAgICAgIC8vIGNhbGN1bGF0ZSBERlQgYXQgcGl4ZWwgcG9zaXRpb25cclxuLy8gICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuZGZ0U2l6ZTsgaSsrKSB7XHJcbi8vICAgICAgICAgICAgICAgICBsZXQgY2hEYXQgPSBjaERhdGFbZnJhbWVQb3MgKyBpXTtcclxuLy8gICAgICAgICAgICAgICAgIGJbaV0gPSBjaERhdDtcclxuLy8gICAgICAgICAgICAgICB9XHJcbi8vICAgICAgICAgICAgICAgbGV0IHNwZWN0ciA9IHRoaXMuZGZ0LnByb2Nlc3NSZWFsTWFnbml0dWRlKGIpO1xyXG4vLyAgICAgICAgICAgICAgIHNvbmFbY2hdW3BpaV0gPSBzcGVjdHI7XHJcbi8vICAgICAgICAgICAgICAgLy8gQHRzLWlnbm9yZVxyXG4vLyAgICAgICAgICAgICAgIGxldCBwTWF4ID0gTWF0aC5tYXguYXBwbHkobnVsbCwgc3BlY3RyKTtcclxuLy8gICAgICAgICAgICAgICBpZiAocE1heCA+IG1heCkge1xyXG4vLyAgICAgICAgICAgICAgICAgbWF4ID0gcE1heDtcclxuLy8gICAgICAgICAgICAgICB9XHJcbi8vXHJcbi8vICAgICAgICAgICAgICAgZm9yIChsZXQgcyA9IDA7IHMgPCBzcGVjdFNpemU7IHMrKykge1xyXG4vLyAgICAgICAgICAgICAgICAgbGV0IHBzZCA9ICgyICogTWF0aC5wb3coc3BlY3RyW3NdLCAyKSkgLyBzcGVjdFNpemU7XHJcbi8vICAgICAgICAgICAgICAgICBpZiAocHNkID4gbWF4UHNkKSB7XHJcbi8vICAgICAgICAgICAgICAgICAgIG1heFBzZCA9IHBzZDtcclxuLy8gICAgICAgICAgICAgICAgIH1cclxuLy8gICAgICAgICAgICAgICB9XHJcbi8vICAgICAgICAgICAgIH1cclxuLy8gICAgICAgICAgIH1cclxuLy8gICAgICAgICAgIC8vY29uc29sZS5sb2coXCJtYXg6IFwiLCBtYXgpO1xyXG4vLyAgICAgICAgICAgbWF4UHNkID0gKDIgKiBNYXRoLnBvdyhtYXgsIDIpKSAvIHNwZWN0U2l6ZTtcclxuLy8gICAgICAgICAgIGZvciAobGV0IGNoID0gMDsgY2ggPCBjaHM7IGNoKyspIHtcclxuLy9cclxuLy8gICAgICAgICAgICAgbGV0IGZyYW1lUG9zID0gMDtcclxuLy8gICAgICAgICAgICAgZm9yIChsZXQgcGlpID0gMDsgcGlpIDwgdzsgcGlpKyspIHtcclxuLy8gICAgICAgICAgICAgICBmcmFtZVBvcyA9IHBpaSAqIGZyYW1lc1BlclBpeGVsO1xyXG4vL1xyXG4vLyAgICAgICAgICAgICAgIGZvciAobGV0IHkgPSAwOyB5IDwgaDsgeSsrKSB7XHJcbi8vICAgICAgICAgICAgICAgICBsZXQgZnJlcUlkeCA9IE1hdGgucm91bmQoeSAqIHNwZWN0U2l6ZSAvIGgpO1xyXG4vL1xyXG4vLyAgICAgICAgICAgICAgICAgLy8gY2FsY3VsYXRlIHRoZSBvbmUgc2lkZWQgcG93ZXIgc3BlY3RyYWwgZGVuc2l0eSBQU0QgKGYsIHQpIGluIFBhMi9IelxyXG4vLyAgICAgICAgICAgICAgICAgLy8gUFNEKGYpIHByb3BvcnRpb25hbCB0byAyfFgoZil8MiAvICh0MiAtIHQxKVxyXG4vLyAgICAgICAgICAgICAgICAgbGV0IHZhbCA9IHNvbmFbY2hdW3BpaV1bZnJlcUlkeF07XHJcbi8vICAgICAgICAgICAgICAgICBsZXQgcHNkID0gKDIgKiBNYXRoLnBvdyh2YWwsIDIpKSAvIHNwZWN0U2l6ZTtcclxuLy9cclxuLy8gICAgICAgICAgICAgICAgIC8vIENhbGN1bGF0ZSBsb2dhcml0aG1pY1xyXG4vLyAgICAgICAgICAgICAgICAgbGV0IHBzZExvZyA9IERTUFV0aWxzLnRvTGV2ZWxJbkRCKHBzZCAvIG1heFBzZCk7XHJcbi8vICAgICAgICAgICAgICAgICBsZXQgZHluUmFuZ2VJbkRiID0gNzA7XHJcbi8vICAgICAgICAgICAgICAgICBsZXQgc2NhbGVkVmFsID0gKHBzZExvZyArIGR5blJhbmdlSW5EYikgLyBkeW5SYW5nZUluRGI7XHJcbi8vXHJcbi8vICAgICAgICAgICAgICAgICBpZiAoc2NhbGVkVmFsID4gMSlcclxuLy8gICAgICAgICAgICAgICAgICAgc2NhbGVkVmFsID0gMTtcclxuLy8gICAgICAgICAgICAgICAgIGlmIChzY2FsZWRWYWwgPCAwKSB7XHJcbi8vICAgICAgICAgICAgICAgICAgIHNjYWxlZFZhbCA9IDA7XHJcbi8vICAgICAgICAgICAgICAgICB9XHJcbi8vICAgICAgICAgICAgICAgICBsZXQgcmdiVmFsID0gKDI1NSAqIHNjYWxlZFZhbCk7XHJcbi8vICAgICAgICAgICAgICAgICBpZiAocmdiVmFsIDwgMCkge1xyXG4vLyAvL1x0XHRcdFx0XHRcdFx0U3lzdGVtLm91dC5wcmludGxuKFwiTmVnIFJHQiB2YWw6IFwiK3JnYlZhbCk7XHJcbi8vICAgICAgICAgICAgICAgICAgIHJnYlZhbCA9IDA7XHJcbi8vICAgICAgICAgICAgICAgICB9XHJcbi8vICAgICAgICAgICAgICAgICBpZiAocmdiVmFsID4gMjU1KSB7XHJcbi8vICAgICAgICAgICAgICAgICAgIHJnYlZhbCA9IDI1NTtcclxuLy8gICAgICAgICAgICAgICAgIH1cclxuLy8gICAgICAgICAgICAgICAgIHJnYlZhbCA9IDI1NSAtIHJnYlZhbDtcclxuLy8gICAgICAgICAgICAgICAgIGxldCBjb2xvclN0ciA9IENTU1V0aWxzLnRvQ29sb3JTdHJpbmcocmdiVmFsLCByZ2JWYWwsIHJnYlZhbCk7XHJcbi8vICAgICAgICAgICAgICAgICBnLmZpbGxTdHlsZSA9IGNvbG9yU3RyO1xyXG4vLyAgICAgICAgICAgICAgICAgZy5maWxsUmVjdChwaWksIGNoSCAtIHksIDEsIDEpO1xyXG4vLyAgICAgICAgICAgICAgIH1cclxuLy8gICAgICAgICAgICAgfVxyXG4vLyAgICAgICAgICAgfVxyXG4vLyAgICAgICAgICAgdGhpcy5kcmF3UGxheVBvc2l0aW9uKCk7XHJcbi8vICAgICAgICAgfWVsc2V7XHJcbi8vICAgICAgICAgICB0aHJvdyBFcnJvcihcIlJlZHJhdyBvbmx5IHN1cHBvcnRlZCB3aXRoIGF1ZGlvIGJ1ZmZlci5cIilcclxuLy8gICAgICAgICB9XHJcbi8vICAgICAgIH1cclxuLy8gICAgIH1cclxuLy8gICB9XHJcbi8vXHJcblxyXG4gICAgc2V0RGF0YShhdWRpb0RhdGE6IEF1ZGlvRGF0YUhvbGRlciB8IG51bGwpIHtcclxuICAgICAgICB0aGlzLl9hdWRpb0RhdGFIb2xkZXIgPSBhdWRpb0RhdGE7XHJcbiAgICAgICAgdGhpcy5wbGF5RnJhbWVQb3NpdGlvbiA9IDA7XHJcbiAgICB9XHJcblxyXG59XHJcblxyXG4iXX0=
|