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