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