speechrecorderng 3.6.0 → 3.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2022/lib/action/action.mjs +73 -0
- package/{esm2020 → esm2022}/lib/audio/array_audio_buffer.mjs +163 -163
- package/{esm2020 → esm2022}/lib/audio/array_audio_buffer_input_stream.mjs +85 -85
- package/{esm2020 → esm2022}/lib/audio/array_audio_buffer_random_access_stream.mjs +15 -15
- package/esm2022/lib/audio/audio_data_holder.mjs +264 -0
- package/{esm2020 → esm2022}/lib/audio/audio_display.mjs +93 -93
- package/{esm2020 → esm2022}/lib/audio/audio_player.mjs +213 -213
- package/esm2022/lib/audio/capture/capture.mjs +855 -0
- package/esm2022/lib/audio/context.mjs +79 -0
- package/{esm2020 → esm2022}/lib/audio/dsp/level_measure.mjs +515 -515
- package/{esm2020 → esm2022}/lib/audio/format.mjs +16 -16
- package/esm2022/lib/audio/impl/wavformat.mjs +6 -0
- package/{esm2020 → esm2022}/lib/audio/impl/wavreader.mjs +133 -133
- package/esm2022/lib/audio/impl/wavwriter.mjs +105 -0
- package/esm2022/lib/audio/inddb_audio_buffer.mjs +508 -0
- package/{esm2020 → esm2022}/lib/audio/io/stream.mjs +58 -58
- package/esm2022/lib/audio/net_audio_buffer.mjs +293 -0
- package/{esm2020 → esm2022}/lib/audio/persistor.mjs +80 -80
- package/{esm2020 → esm2022}/lib/audio/playback/array_audio_buffer_source_node.mjs +125 -125
- package/esm2022/lib/audio/playback/audio_source_node.mjs +18 -0
- package/esm2022/lib/audio/playback/audio_source_worklet_module_loader.mjs +167 -0
- package/{esm2020 → esm2022}/lib/audio/playback/inddb_audio_buffer_source_node.mjs +166 -166
- package/{esm2020 → esm2022}/lib/audio/playback/net_audio_buffer_source_node.mjs +217 -217
- package/esm2022/lib/audio/playback/player.mjs +402 -0
- package/esm2022/lib/audio/ui/audio_canvas_layer_comp.mjs +347 -0
- package/{esm2020 → esm2022}/lib/audio/ui/audio_display_control.mjs +65 -65
- package/{esm2020 → esm2022}/lib/audio/ui/audio_display_scroll_pane.mjs +139 -139
- package/{esm2020 → esm2022}/lib/audio/ui/audiosignal.mjs +524 -524
- package/{esm2020 → esm2022}/lib/audio/ui/common.mjs +18 -18
- package/esm2022/lib/audio/ui/container.mjs +414 -0
- package/{esm2020 → esm2022}/lib/audio/ui/livelevel.mjs +352 -352
- package/esm2022/lib/audio/ui/scroll_pane_horizontal.mjs +11 -0
- package/esm2022/lib/audio/ui/sonagram.mjs +900 -0
- package/esm2022/lib/db/inddb.mjs +120 -0
- package/esm2022/lib/dsp/utils.mjs +48 -0
- package/{esm2020 → esm2022}/lib/io/BinaryReader.mjs +84 -84
- package/esm2022/lib/io/BinaryWriter.mjs +74 -0
- package/{esm2020 → esm2022}/lib/io/stream.mjs +258 -258
- package/{esm2020 → esm2022}/lib/math/2d/geometry.mjs +27 -27
- package/esm2022/lib/math/complex.mjs +58 -0
- package/{esm2020 → esm2022}/lib/math/dft.mjs +195 -195
- package/{esm2020 → esm2022}/lib/media/utils.mjs +13 -13
- package/esm2022/lib/net/uploader.mjs +367 -0
- package/{esm2020 → esm2022}/lib/recorder_component.mjs +64 -64
- package/esm2022/lib/speechrecorder/project/project.mjs +49 -0
- package/esm2022/lib/speechrecorder/project/project.service.mjs +64 -0
- package/{esm2020 → esm2022}/lib/speechrecorder/recording.mjs +123 -123
- package/esm2022/lib/speechrecorder/recordings/basic_recording.service.mjs +218 -0
- package/esm2022/lib/speechrecorder/recordings/recordings.service.mjs +1014 -0
- package/{esm2020 → esm2022}/lib/speechrecorder/script/script.mjs +114 -114
- package/{esm2020 → esm2022}/lib/speechrecorder/script/script.service.mjs +47 -47
- package/esm2022/lib/speechrecorder/session/audiorecorder.mjs +1179 -0
- package/esm2022/lib/speechrecorder/session/basicrecorder.mjs +668 -0
- package/esm2022/lib/speechrecorder/session/controlpanel.mjs +416 -0
- package/{esm2020 → esm2022}/lib/speechrecorder/session/item.mjs +29 -29
- package/{esm2020 → esm2022}/lib/speechrecorder/session/progress.mjs +69 -69
- package/{esm2020 → esm2022}/lib/speechrecorder/session/prompting.mjs +571 -571
- package/{esm2020 → esm2022}/lib/speechrecorder/session/recorder_combi_pane.mjs +65 -65
- package/esm2022/lib/speechrecorder/session/recording_file_cache.mjs +195 -0
- package/{esm2020 → esm2022}/lib/speechrecorder/session/recording_list.mjs +103 -103
- package/{esm2020 → esm2022}/lib/speechrecorder/session/recordingfile/recording-file-meta.component.mjs +63 -63
- package/{esm2020 → esm2022}/lib/speechrecorder/session/recordingfile/recording-file-navi.component.mjs +51 -51
- package/{esm2020 → esm2022}/lib/speechrecorder/session/recordingfile/recording-file-u-i.component.mjs +104 -104
- package/{esm2020 → esm2022}/lib/speechrecorder/session/recordingfile/recording-file-view.component.mjs +381 -381
- package/{esm2020 → esm2022}/lib/speechrecorder/session/recordingfile/recording-file.mjs +67 -67
- package/esm2022/lib/speechrecorder/session/recordingfile/recordingfile-service.mjs +288 -0
- package/{esm2020 → esm2022}/lib/speechrecorder/session/session.mjs +1 -1
- package/esm2022/lib/speechrecorder/session/session.service.mjs +69 -0
- package/{esm2020 → esm2022}/lib/speechrecorder/session/session_finished_dialog.mjs +29 -29
- package/esm2022/lib/speechrecorder/session/sessionmanager.mjs +1386 -0
- package/{esm2020 → esm2022}/lib/speechrecorder/session/warning_bar.mjs +28 -28
- package/{esm2020 → esm2022}/lib/speechrecorder/spruploader.mjs +22 -22
- package/{esm2020 → esm2022}/lib/speechrecorder/startstopsignal/startstopsignal.mjs +1 -1
- package/esm2022/lib/speechrecorder/startstopsignal/ui/simpletrafficlight.mjs +57 -0
- package/{esm2020 → esm2022}/lib/speechrecorderng.component.mjs +388 -388
- package/{esm2020 → esm2022}/lib/speechrecorderng.module.mjs +100 -100
- package/{esm2020 → esm2022}/lib/spr.config.mjs +26 -26
- package/{esm2020 → esm2022}/lib/spr.module.version.mjs +2 -2
- package/{esm2020 → esm2022}/lib/ui/canvas_layer_comp.mjs +38 -38
- package/{esm2020 → esm2022}/lib/ui/message_dialog.mjs +30 -30
- package/esm2022/lib/ui/recordingitem_display.mjs +253 -0
- package/{esm2020 → esm2022}/lib/ui/responsive_component.mjs +24 -24
- package/{esm2020 → esm2022}/lib/utils/scrollIntoViewToBottom.mjs +23 -23
- package/esm2022/lib/utils/ua-parser.mjs +190 -0
- package/esm2022/lib/utils/utils.mjs +105 -0
- package/esm2022/lib/utils/wake_lock.mjs +114 -0
- package/{esm2020 → esm2022}/lib/utils/wake_lock_media.mjs +1 -1
- package/{esm2020 → esm2022}/public-api.mjs +33 -33
- package/{esm2020 → esm2022}/speechrecorderng.mjs +4 -4
- package/{fesm2020 → fesm2022}/speechrecorderng.mjs +16518 -16454
- package/fesm2022/speechrecorderng.mjs.map +1 -0
- package/index.d.ts +5 -5
- package/lib/action/action.d.ts +27 -27
- package/lib/audio/array_audio_buffer.d.ts +31 -31
- package/lib/audio/array_audio_buffer_input_stream.d.ts +14 -14
- package/lib/audio/array_audio_buffer_random_access_stream.d.ts +9 -9
- package/lib/audio/audio_data_holder.d.ts +84 -84
- package/lib/audio/audio_display.d.ts +36 -36
- package/lib/audio/audio_player.d.ts +47 -47
- package/lib/audio/capture/capture.d.ts +67 -67
- package/lib/audio/context.d.ts +6 -6
- package/lib/audio/dsp/level_measure.d.ts +60 -60
- package/lib/audio/format.d.ts +11 -11
- package/lib/audio/impl/wavformat.d.ts +5 -5
- package/lib/audio/impl/wavreader.d.ts +16 -16
- package/lib/audio/impl/wavwriter.d.ts +13 -13
- package/lib/audio/inddb_audio_buffer.d.ts +68 -68
- package/lib/audio/io/stream.d.ts +28 -28
- package/lib/audio/net_audio_buffer.d.ts +57 -57
- package/lib/audio/persistor.d.ts +29 -29
- package/lib/audio/playback/array_audio_buffer_source_node.d.ts +18 -18
- package/lib/audio/playback/audio_source_node.d.ts +10 -10
- package/lib/audio/playback/audio_source_worklet_module_loader.d.ts +4 -4
- package/lib/audio/playback/inddb_audio_buffer_source_node.d.ts +21 -21
- package/lib/audio/playback/net_audio_buffer_source_node.d.ts +27 -27
- package/lib/audio/playback/player.d.ts +65 -65
- package/lib/audio/ui/audio_canvas_layer_comp.d.ts +68 -68
- package/lib/audio/ui/audio_display_control.d.ts +25 -25
- package/lib/audio/ui/audio_display_scroll_pane.d.ts +26 -26
- package/lib/audio/ui/audiosignal.d.ts +30 -30
- package/lib/audio/ui/common.d.ts +11 -11
- package/lib/audio/ui/container.d.ts +63 -63
- package/lib/audio/ui/livelevel.d.ts +60 -60
- package/lib/audio/ui/scroll_pane_horizontal.d.ts +5 -5
- package/lib/audio/ui/sonagram.d.ts +37 -37
- package/lib/db/inddb.d.ts +21 -21
- package/lib/dsp/utils.d.ts +19 -19
- package/lib/io/BinaryReader.d.ts +18 -18
- package/lib/io/BinaryWriter.d.ts +15 -15
- package/lib/io/stream.d.ts +59 -59
- package/lib/math/2d/geometry.d.ts +18 -18
- package/lib/math/complex.d.ts +17 -17
- package/lib/math/dft.d.ts +22 -22
- package/lib/media/utils.d.ts +3 -3
- package/lib/net/uploader.d.ts +81 -81
- package/lib/recorder_component.d.ts +16 -16
- package/lib/speechrecorder/project/project.d.ts +59 -59
- package/lib/speechrecorder/project/project.service.d.ts +21 -21
- package/lib/speechrecorder/recording.d.ts +51 -51
- package/lib/speechrecorder/recordings/basic_recording.service.d.ts +27 -27
- package/lib/speechrecorder/recordings/recordings.service.d.ts +48 -48
- package/lib/speechrecorder/script/script.d.ts +80 -79
- package/lib/speechrecorder/script/script.service.d.ts +16 -16
- package/lib/speechrecorder/session/audiorecorder.d.ts +122 -122
- package/lib/speechrecorder/session/basicrecorder.d.ts +139 -139
- package/lib/speechrecorder/session/controlpanel.d.ts +109 -107
- package/lib/speechrecorder/session/item.d.ts +12 -12
- package/lib/speechrecorder/session/progress.d.ts +17 -17
- package/lib/speechrecorder/session/prompting.d.ts +121 -121
- package/lib/speechrecorder/session/recorder_combi_pane.d.ts +32 -32
- package/lib/speechrecorder/session/recording_file_cache.d.ts +33 -33
- package/lib/speechrecorder/session/recording_list.d.ts +24 -24
- package/lib/speechrecorder/session/recordingfile/recording-file-meta.component.d.ts +15 -15
- package/lib/speechrecorder/session/recordingfile/recording-file-navi.component.d.ts +20 -20
- package/lib/speechrecorder/session/recordingfile/recording-file-u-i.component.d.ts +31 -31
- package/lib/speechrecorder/session/recordingfile/recording-file-view.component.d.ts +55 -55
- package/lib/speechrecorder/session/recordingfile/recording-file.d.ts +7 -7
- package/lib/speechrecorder/session/recordingfile/recordingfile-service.d.ts +24 -24
- package/lib/speechrecorder/session/session.d.ts +15 -15
- package/lib/speechrecorder/session/session.service.d.ts +20 -20
- package/lib/speechrecorder/session/session_finished_dialog.d.ts +10 -10
- package/lib/speechrecorder/session/sessionmanager.d.ts +129 -123
- package/lib/speechrecorder/session/warning_bar.d.ts +8 -8
- package/lib/speechrecorder/spruploader.d.ts +11 -11
- package/lib/speechrecorder/startstopsignal/startstopsignal.d.ts +10 -10
- package/lib/speechrecorder/startstopsignal/ui/simpletrafficlight.d.ts +11 -11
- package/lib/speechrecorderng.component.d.ts +61 -61
- package/lib/speechrecorderng.module.d.ts +56 -56
- package/lib/spr.config.d.ts +17 -17
- package/lib/spr.module.version.d.ts +1 -1
- package/lib/ui/canvas_layer_comp.d.ts +13 -13
- package/lib/ui/message_dialog.d.ts +10 -10
- package/lib/ui/recordingitem_display.d.ts +84 -84
- package/lib/ui/responsive_component.d.ts +9 -9
- package/lib/utils/scrollIntoViewToBottom.d.ts +9 -9
- package/lib/utils/ua-parser.d.ts +43 -43
- package/lib/utils/utils.d.ts +19 -19
- package/lib/utils/wake_lock.d.ts +23 -23
- package/lib/utils/wake_lock_media.d.ts +1 -1
- package/package.json +17 -23
- package/public-api.d.ts +33 -33
- package/esm2020/lib/action/action.mjs +0 -73
- package/esm2020/lib/audio/audio_data_holder.mjs +0 -264
- package/esm2020/lib/audio/capture/capture.mjs +0 -855
- package/esm2020/lib/audio/context.mjs +0 -79
- package/esm2020/lib/audio/impl/wavformat.mjs +0 -6
- package/esm2020/lib/audio/impl/wavwriter.mjs +0 -105
- package/esm2020/lib/audio/inddb_audio_buffer.mjs +0 -508
- package/esm2020/lib/audio/net_audio_buffer.mjs +0 -293
- package/esm2020/lib/audio/playback/audio_source_node.mjs +0 -18
- package/esm2020/lib/audio/playback/audio_source_worklet_module_loader.mjs +0 -167
- package/esm2020/lib/audio/playback/player.mjs +0 -402
- package/esm2020/lib/audio/ui/audio_canvas_layer_comp.mjs +0 -347
- package/esm2020/lib/audio/ui/container.mjs +0 -414
- package/esm2020/lib/audio/ui/scroll_pane_horizontal.mjs +0 -11
- package/esm2020/lib/audio/ui/sonagram.mjs +0 -900
- package/esm2020/lib/db/inddb.mjs +0 -120
- package/esm2020/lib/dsp/utils.mjs +0 -48
- package/esm2020/lib/io/BinaryWriter.mjs +0 -74
- package/esm2020/lib/math/complex.mjs +0 -58
- package/esm2020/lib/net/uploader.mjs +0 -367
- package/esm2020/lib/speechrecorder/project/project.mjs +0 -49
- package/esm2020/lib/speechrecorder/project/project.service.mjs +0 -64
- package/esm2020/lib/speechrecorder/recordings/basic_recording.service.mjs +0 -216
- package/esm2020/lib/speechrecorder/recordings/recordings.service.mjs +0 -1014
- package/esm2020/lib/speechrecorder/session/audiorecorder.mjs +0 -1179
- package/esm2020/lib/speechrecorder/session/basicrecorder.mjs +0 -666
- package/esm2020/lib/speechrecorder/session/controlpanel.mjs +0 -409
- package/esm2020/lib/speechrecorder/session/recording_file_cache.mjs +0 -195
- package/esm2020/lib/speechrecorder/session/recordingfile/recordingfile-service.mjs +0 -288
- package/esm2020/lib/speechrecorder/session/session.service.mjs +0 -69
- package/esm2020/lib/speechrecorder/session/sessionmanager.mjs +0 -1333
- package/esm2020/lib/speechrecorder/startstopsignal/ui/simpletrafficlight.mjs +0 -57
- package/esm2020/lib/ui/recordingitem_display.mjs +0 -253
- package/esm2020/lib/utils/ua-parser.mjs +0 -190
- package/esm2020/lib/utils/utils.mjs +0 -105
- package/esm2020/lib/utils/wake_lock.mjs +0 -114
- package/fesm2015/speechrecorderng.mjs +0 -17708
- package/fesm2015/speechrecorderng.mjs.map +0 -1
- package/fesm2020/speechrecorderng.mjs.map +0 -1
|
@@ -1,1333 +0,0 @@
|
|
|
1
|
-
import { AudioCapture } from '../../audio/capture/capture';
|
|
2
|
-
import { EventType } from '../../audio/playback/player';
|
|
3
|
-
import { WavWriter } from '../../audio/impl/wavwriter';
|
|
4
|
-
import { PromptitemUtil } from '../script/script';
|
|
5
|
-
import { SprRecordingFile } from '../recording';
|
|
6
|
-
import { UploadHolder } from '../../net/uploader';
|
|
7
|
-
import { Component, HostListener, Inject, Input, ViewChild } from "@angular/core";
|
|
8
|
-
import { SessionService } from "./session.service";
|
|
9
|
-
import { SPEECHRECORDER_CONFIG } from "../../spr.config";
|
|
10
|
-
import { Prompting } from "./prompting";
|
|
11
|
-
import { SessionFinishedDialog } from "./session_finished_dialog";
|
|
12
|
-
import { MessageDialog } from "../../ui/message_dialog";
|
|
13
|
-
import { RecordingService } from "../recordings/recordings.service";
|
|
14
|
-
import { AudioClip } from "../../audio/persistor";
|
|
15
|
-
import { Item } from "./item";
|
|
16
|
-
import { LevelBar } from "../../audio/ui/livelevel";
|
|
17
|
-
import { BasicRecorder, MAX_RECORDING_TIME_MS, RECFILE_API_CTX } from "./basicrecorder";
|
|
18
|
-
import { ArrayAudioBuffer } from "../../audio/array_audio_buffer";
|
|
19
|
-
import { AudioBufferSource, AudioDataHolder } from "../../audio/audio_data_holder";
|
|
20
|
-
import { SprItemsCache } from "./recording_file_cache";
|
|
21
|
-
import { State as LiveLevelState } from "../../audio/ui/livelevel";
|
|
22
|
-
import { AudioStorageType } from "../project/project";
|
|
23
|
-
import { NetAudioBuffer } from "../../audio/net_audio_buffer";
|
|
24
|
-
import * as i0 from "@angular/core";
|
|
25
|
-
import * as i1 from "@angular/cdk/layout";
|
|
26
|
-
import * as i2 from "@angular/material/dialog";
|
|
27
|
-
import * as i3 from "./session.service";
|
|
28
|
-
import * as i4 from "../recordings/recordings.service";
|
|
29
|
-
import * as i5 from "../spruploader";
|
|
30
|
-
import * as i6 from "@angular/common";
|
|
31
|
-
import * as i7 from "@angular/material/progress-bar";
|
|
32
|
-
import * as i8 from "../../audio/ui/livelevel";
|
|
33
|
-
import * as i9 from "./prompting";
|
|
34
|
-
import * as i10 from "./controlpanel";
|
|
35
|
-
import * as i11 from "../../ui/recordingitem_display";
|
|
36
|
-
import * as i12 from "./warning_bar";
|
|
37
|
-
import * as i13 from "../../spr.config";
|
|
38
|
-
const DEFAULT_PRE_REC_DELAY = 1000;
|
|
39
|
-
const DEFAULT_POST_REC_DELAY = 500;
|
|
40
|
-
export class SessionManager extends BasicRecorder {
|
|
41
|
-
constructor(bpo, changeDetectorRef, renderer, dialog, sessionService, recFileService, uploader, config) {
|
|
42
|
-
super(bpo, changeDetectorRef, dialog, sessionService, uploader, config);
|
|
43
|
-
this.bpo = bpo;
|
|
44
|
-
this.renderer = renderer;
|
|
45
|
-
this.recFileService = recFileService;
|
|
46
|
-
this.offlineAudioContext = null;
|
|
47
|
-
this.enableUploadRecordings = true;
|
|
48
|
-
this.enableDownloadRecordings = false;
|
|
49
|
-
this.status = 0 /* BLOCKED */;
|
|
50
|
-
this.dataSaved = true;
|
|
51
|
-
this.preRecTimerId = null;
|
|
52
|
-
this.preRecTimerRunning = null;
|
|
53
|
-
this.postDelay = DEFAULT_POST_REC_DELAY;
|
|
54
|
-
this.postRecTimerId = null;
|
|
55
|
-
this.postRecTimerRunning = null;
|
|
56
|
-
this._promptIndex = 0;
|
|
57
|
-
this.items = null;
|
|
58
|
-
//selectedItemIdx: number;
|
|
59
|
-
this._displayRecFile = null;
|
|
60
|
-
this.showSessionCompleteMessage = true;
|
|
61
|
-
this.status = 1 /* IDLE */;
|
|
62
|
-
this.audio = document.getElementById('audio');
|
|
63
|
-
if (this.config && this.config.enableUploadRecordings !== undefined) {
|
|
64
|
-
this.enableUploadRecordings = this.config.enableUploadRecordings;
|
|
65
|
-
}
|
|
66
|
-
if (this.config && this.config.enableDownloadRecordings !== undefined) {
|
|
67
|
-
this.enableDownloadRecordings = this.config.enableDownloadRecordings;
|
|
68
|
-
}
|
|
69
|
-
this.init();
|
|
70
|
-
}
|
|
71
|
-
get persistentAudioStorageTarget() {
|
|
72
|
-
return this._persistentAudioStorageTarget;
|
|
73
|
-
}
|
|
74
|
-
set persistentAudioStorageTarget(value) {
|
|
75
|
-
this._persistentAudioStorageTarget = value;
|
|
76
|
-
if (this.ac) {
|
|
77
|
-
this.ac.persistentAudioStorageTarget = this.persistentAudioStorageTarget;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
ngAfterViewInit() {
|
|
81
|
-
this.streamLevelMeasure.levelListener = this.liveLevelDisplay;
|
|
82
|
-
this.streamLevelMeasure.peakLevelListener = (peakLvlInDb) => {
|
|
83
|
-
this.peakLevelInDb = peakLvlInDb;
|
|
84
|
-
this.changeDetectorRef.detectChanges();
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
ngOnDestroy() {
|
|
88
|
-
//console.debug("Com destroy, disable wake lock.")
|
|
89
|
-
this.disableWakeLockCond();
|
|
90
|
-
this.destroyed = true;
|
|
91
|
-
// TODO stop capture /playback
|
|
92
|
-
}
|
|
93
|
-
init() {
|
|
94
|
-
this.sectIdx = 0;
|
|
95
|
-
this.groupIdxInSection = 0;
|
|
96
|
-
this.promptItemIdxInGroup = 0;
|
|
97
|
-
this.autorecording = false;
|
|
98
|
-
this.transportActions.startAction.disabled = true;
|
|
99
|
-
this.transportActions.stopAction.disabled = true;
|
|
100
|
-
this.transportActions.nextAction.disabled = true;
|
|
101
|
-
this.transportActions.pauseAction.disabled = true;
|
|
102
|
-
this.playStartAction.disabled = true;
|
|
103
|
-
// let context:AudioContext|null=null;
|
|
104
|
-
// try {
|
|
105
|
-
// context = AudioContextProvider.audioContextInstance();
|
|
106
|
-
// } catch (err) {
|
|
107
|
-
// this.status = Status.ERROR;
|
|
108
|
-
// let errMsg = 'Unknown error';
|
|
109
|
-
// if(err instanceof Error){
|
|
110
|
-
// errMsg=err.message;
|
|
111
|
-
// }
|
|
112
|
-
// this.statusMsg = 'ERROR: ' + errMsg;
|
|
113
|
-
// this.statusAlertType = 'error';
|
|
114
|
-
// this.dialog.open(MessageDialog, {
|
|
115
|
-
// data: {
|
|
116
|
-
// type: 'error',
|
|
117
|
-
// title: 'Error',
|
|
118
|
-
// msg: errMsg,
|
|
119
|
-
// advice: 'Please use a supported browser.',
|
|
120
|
-
// }
|
|
121
|
-
// });
|
|
122
|
-
// return;
|
|
123
|
-
// }
|
|
124
|
-
// if(context) {
|
|
125
|
-
// console.info("State of audio context: " + context.state)
|
|
126
|
-
// }else{
|
|
127
|
-
// console.info("No audio context available!");
|
|
128
|
-
// }
|
|
129
|
-
// if (!context || !navigator.mediaDevices) {
|
|
130
|
-
// this.status = Status.ERROR;
|
|
131
|
-
// let errMsg = 'Browser does not support Media streams!';
|
|
132
|
-
// this.statusMsg = 'ERROR: ' + errMsg;
|
|
133
|
-
// this.statusAlertType = 'error';
|
|
134
|
-
// this.dialog.open(MessageDialog, {
|
|
135
|
-
// data: {
|
|
136
|
-
// type: 'error',
|
|
137
|
-
// title: 'Error',
|
|
138
|
-
// msg: errMsg,
|
|
139
|
-
// advice: 'Please use a supported browser.',
|
|
140
|
-
// }
|
|
141
|
-
// });
|
|
142
|
-
// return;
|
|
143
|
-
// } else {
|
|
144
|
-
this.ac = new AudioCapture();
|
|
145
|
-
if (this.ac) {
|
|
146
|
-
this.transportActions.startAction.onAction = () => this.startItem();
|
|
147
|
-
this.ac.listener = this;
|
|
148
|
-
this.configureStreamCaptureStream();
|
|
149
|
-
// Don't list the devices here. If we do not have audio permissions we only get anonymized devices without labels.
|
|
150
|
-
//this.ac.listDevices();
|
|
151
|
-
}
|
|
152
|
-
else {
|
|
153
|
-
this.transportActions.startAction.disabled = true;
|
|
154
|
-
let errMsg = 'Browser does not support Media/Audio API!';
|
|
155
|
-
this.statusMsg = 'ERROR: ' + errMsg;
|
|
156
|
-
this.statusAlertType = 'error';
|
|
157
|
-
this.dialog.open(MessageDialog, {
|
|
158
|
-
data: {
|
|
159
|
-
type: 'error',
|
|
160
|
-
title: 'Error',
|
|
161
|
-
msg: errMsg,
|
|
162
|
-
advice: 'Please use a supported browser.',
|
|
163
|
-
}
|
|
164
|
-
});
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
167
|
-
this.transportActions.stopAction.onAction = () => this.stopItem();
|
|
168
|
-
this.transportActions.nextAction.onAction = () => this.stopItem();
|
|
169
|
-
this.transportActions.pauseAction.onAction = () => this.pauseItem();
|
|
170
|
-
this.transportActions.fwdAction.onAction = () => this.nextItem();
|
|
171
|
-
this.transportActions.fwdNextAction.onAction = () => this.nextUnrecordedItem();
|
|
172
|
-
this.transportActions.bwdAction.onAction = () => this.prevItem();
|
|
173
|
-
this.playStartAction.onAction = () => this.controlAudioPlayer?.start();
|
|
174
|
-
this.startStopSignalState = 4 /* OFF */;
|
|
175
|
-
}
|
|
176
|
-
onKeyPress(ke) {
|
|
177
|
-
if (ke.key == ' ') {
|
|
178
|
-
this.transportActions.startAction.perform();
|
|
179
|
-
this.transportActions.nextAction.perform();
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
onKeyDown(ke) {
|
|
183
|
-
if (ke.key == ' ') {
|
|
184
|
-
this.transportActions.stopAction.perform();
|
|
185
|
-
}
|
|
186
|
-
if (ke.key == 'p') {
|
|
187
|
-
this.transportActions.pauseAction.perform();
|
|
188
|
-
}
|
|
189
|
-
if (ke.key == 'Escape') {
|
|
190
|
-
if (!this.audioSignalCollapsed) {
|
|
191
|
-
this.audioSignalCollapsed = true;
|
|
192
|
-
}
|
|
193
|
-
this.transportActions.stopAction.perform();
|
|
194
|
-
this.transportActions.pauseAction.perform();
|
|
195
|
-
}
|
|
196
|
-
if (ke.key == 'MediaPlayPause') {
|
|
197
|
-
this.playStartAction.perform();
|
|
198
|
-
}
|
|
199
|
-
if (ke.key === 'ArrowRight') {
|
|
200
|
-
this.transportActions.fwdAction.perform();
|
|
201
|
-
}
|
|
202
|
-
if (ke.key === 'ArrowLeft') {
|
|
203
|
-
this.transportActions.bwdAction.perform();
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
updateWakeLock(dataSaved = this.dataSaved) {
|
|
207
|
-
//console.debug("Update wake lock: dataSaved: "+dataSaved+", not active: "+! this.isActive())
|
|
208
|
-
if (dataSaved && !this.isActive()) {
|
|
209
|
-
this.disableWakeLockCond();
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
progressPercentValue() {
|
|
213
|
-
let v = 100;
|
|
214
|
-
if (this.items) {
|
|
215
|
-
v = this.promptIndex * 100 / (this.items.length() - 1);
|
|
216
|
-
}
|
|
217
|
-
return v;
|
|
218
|
-
}
|
|
219
|
-
isTestSession() {
|
|
220
|
-
return ((this._session != null) && (this._session.type === 'TEST' || this._session.type === 'TEST_DEF_A' || this._session.type === 'SINUS_TEST'));
|
|
221
|
-
}
|
|
222
|
-
isDefaultAudioTestSession() {
|
|
223
|
-
return ((this._session != null) && (this._session.type === 'TEST_DEF_A'));
|
|
224
|
-
}
|
|
225
|
-
isDefaultAudioTestSessionOverwritingProjectRequirements() {
|
|
226
|
-
return ((this._session != null) && (this._session.type === 'TEST_DEF_A') && (this.audioDevices != null) && this.audioDevices.length > 0);
|
|
227
|
-
}
|
|
228
|
-
set controlAudioPlayer(controlAudioPlayer) {
|
|
229
|
-
this._controlAudioPlayer = controlAudioPlayer;
|
|
230
|
-
if (this._controlAudioPlayer) {
|
|
231
|
-
this._controlAudioPlayer.listener = this;
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
get controlAudioPlayer() {
|
|
235
|
-
return this._controlAudioPlayer;
|
|
236
|
-
}
|
|
237
|
-
set script(script) {
|
|
238
|
-
this._script = script;
|
|
239
|
-
this.loadScript();
|
|
240
|
-
}
|
|
241
|
-
update(e) {
|
|
242
|
-
if (e.type == EventType.STARTED) {
|
|
243
|
-
this.playStartAction.disabled = true;
|
|
244
|
-
this.updateTimerId = window.setInterval(() => {
|
|
245
|
-
//this.audioSignal.playFramePosition = this.ap.playPositionFrames;
|
|
246
|
-
}, 50);
|
|
247
|
-
}
|
|
248
|
-
else if (e.type == EventType.STOPPED || e.type == EventType.ENDED) {
|
|
249
|
-
window.clearInterval(this.updateTimerId);
|
|
250
|
-
// this.audioSignal.playFramePosition = this.ap.playPositionFrames;
|
|
251
|
-
this.playStartAction.disabled = (!(this.displayRecFile));
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
get promptIndex() {
|
|
255
|
-
return this._promptIndex;
|
|
256
|
-
}
|
|
257
|
-
set promptIndex(promptIndex) {
|
|
258
|
-
if (promptIndex < 0 || promptIndex >= this.promptItemCount) {
|
|
259
|
-
throw new Error("Prompt index out of range");
|
|
260
|
-
}
|
|
261
|
-
let i = 0;
|
|
262
|
-
let sections = this._script.sections;
|
|
263
|
-
let found = false;
|
|
264
|
-
for (let si = 0; si < sections.length && !found; si++) {
|
|
265
|
-
let section = sections[si];
|
|
266
|
-
let gs = section._shuffledGroups;
|
|
267
|
-
for (let gi = 0; gi < gs.length; gi++) {
|
|
268
|
-
let pis = gs[gi]._shuffledPromptItems;
|
|
269
|
-
let pisSize = pis.length;
|
|
270
|
-
if (promptIndex < i + pisSize) {
|
|
271
|
-
this.sectIdx = si;
|
|
272
|
-
this.groupIdxInSection = gi;
|
|
273
|
-
this.promptItemIdxInGroup = promptIndex - i;
|
|
274
|
-
found = true;
|
|
275
|
-
break;
|
|
276
|
-
}
|
|
277
|
-
else {
|
|
278
|
-
i += pisSize;
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
if (found) {
|
|
283
|
-
this._promptIndex = promptIndex;
|
|
284
|
-
}
|
|
285
|
-
else {
|
|
286
|
-
throw new Error("Internal error: Prompt index not found");
|
|
287
|
-
}
|
|
288
|
-
this.keepLiveLevel = false;
|
|
289
|
-
this.applyItem();
|
|
290
|
-
}
|
|
291
|
-
itemSelect(itemIdx) {
|
|
292
|
-
if (this.status === 1 /* IDLE */) {
|
|
293
|
-
this.promptIndex = itemIdx;
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
clearPreRecTimer() {
|
|
297
|
-
if (this.preRecTimerRunning) {
|
|
298
|
-
if (this.preRecTimerId) {
|
|
299
|
-
window.clearTimeout(this.preRecTimerId);
|
|
300
|
-
}
|
|
301
|
-
this.preRecTimerRunning = false;
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
clearPostRecTimer() {
|
|
305
|
-
if (this.postRecTimerRunning) {
|
|
306
|
-
if (this.postRecTimerId) {
|
|
307
|
-
window.clearTimeout(this.postRecTimerId);
|
|
308
|
-
}
|
|
309
|
-
this.postRecTimerRunning = false;
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
clearMaxRecTimer() {
|
|
313
|
-
if (this.maxRecTimerRunning) {
|
|
314
|
-
if (this.maxRecTimerId) {
|
|
315
|
-
window.clearTimeout(this.maxRecTimerId);
|
|
316
|
-
}
|
|
317
|
-
this.maxRecTimerRunning = false;
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
startItem() {
|
|
321
|
-
this.status = 2 /* STARTING */;
|
|
322
|
-
super.startItem();
|
|
323
|
-
if (this.readonly) {
|
|
324
|
-
this.status = 1 /* IDLE */;
|
|
325
|
-
return;
|
|
326
|
-
}
|
|
327
|
-
this.transportActions.fwdAction.disabled = true;
|
|
328
|
-
this.transportActions.fwdNextAction.disabled = true;
|
|
329
|
-
this.transportActions.bwdAction.disabled = true;
|
|
330
|
-
this.updateDisplayRecFile(null);
|
|
331
|
-
this.displayRecFileVersion = 0;
|
|
332
|
-
this.displayAudioClip = null;
|
|
333
|
-
this.liveLevelDisplay.reset(true);
|
|
334
|
-
// Hide loading hint on livelevel display
|
|
335
|
-
this.liveLevelDisplayState = LiveLevelState.READY;
|
|
336
|
-
this.showRecording();
|
|
337
|
-
if (this.section.mode === 'AUTORECORDING') {
|
|
338
|
-
this.autorecording = true;
|
|
339
|
-
}
|
|
340
|
-
this.startCapture();
|
|
341
|
-
}
|
|
342
|
-
loadScript() {
|
|
343
|
-
this.promptItemCount = 0;
|
|
344
|
-
this.items = new SprItemsCache();
|
|
345
|
-
let ln = 0;
|
|
346
|
-
//TODO randomize not supported
|
|
347
|
-
for (let si = 0; si < this._script.sections.length; si++) {
|
|
348
|
-
let section = this._script.sections[si];
|
|
349
|
-
let gs = section._shuffledGroups;
|
|
350
|
-
for (let gi = 0; gi < gs.length; gi++) {
|
|
351
|
-
let pis = gs[gi]._shuffledPromptItems;
|
|
352
|
-
let pisLen = pis.length;
|
|
353
|
-
this.promptItemCount += pisLen;
|
|
354
|
-
for (let piSectIdx = 0; piSectIdx < pisLen; piSectIdx++) {
|
|
355
|
-
let pi = pis[piSectIdx];
|
|
356
|
-
let promptAsStr = PromptitemUtil.toPlainTextString(pi);
|
|
357
|
-
let it = new Item(promptAsStr, section.training, (!pi.type || pi.type === 'recording'));
|
|
358
|
-
this.items.addItem(it);
|
|
359
|
-
ln++;
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
promptIndexByItemcode(itemcode) {
|
|
365
|
-
let pix = 0;
|
|
366
|
-
for (let si = 0; si < this._script.sections.length; si++) {
|
|
367
|
-
let section = this._script.sections[si];
|
|
368
|
-
let gs = section._shuffledGroups;
|
|
369
|
-
for (let gi = 0; gi < gs.length; gi++) {
|
|
370
|
-
let pis = gs[gi]._shuffledPromptItems;
|
|
371
|
-
let pisLen = pis.length;
|
|
372
|
-
for (let piSectIdx = 0; piSectIdx < pisLen; piSectIdx++) {
|
|
373
|
-
let pi = pis[piSectIdx];
|
|
374
|
-
let ic = pi.itemcode;
|
|
375
|
-
if (ic === itemcode) {
|
|
376
|
-
return pix;
|
|
377
|
-
}
|
|
378
|
-
pix++;
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
return null;
|
|
383
|
-
}
|
|
384
|
-
clearPrompt() {
|
|
385
|
-
//this.prompting.promptContainer.prompter.promptText='';
|
|
386
|
-
//this.mediaitem = null;
|
|
387
|
-
this.showPrompt = false;
|
|
388
|
-
this.changeDetectorRef.detectChanges();
|
|
389
|
-
}
|
|
390
|
-
applyPrompt() {
|
|
391
|
-
//this.prompting.promptContainer.prompter.promptText=this.promptUnit.mediaitems[0].text;
|
|
392
|
-
//this.promptText = this.promptUnit.mediaitems[0].text;
|
|
393
|
-
//this.mediaitem=this.promptUnit.mediaitems[0];
|
|
394
|
-
this.showPrompt = true;
|
|
395
|
-
this.changeDetectorRef.detectChanges();
|
|
396
|
-
}
|
|
397
|
-
downloadRecording() {
|
|
398
|
-
if (this.displayRecFile) {
|
|
399
|
-
let adh = this.displayRecFile.audioDataHolder;
|
|
400
|
-
let as = null;
|
|
401
|
-
if (adh) {
|
|
402
|
-
as = adh.audioSource;
|
|
403
|
-
}
|
|
404
|
-
const ww = new WavWriter();
|
|
405
|
-
if (as instanceof AudioBufferSource) {
|
|
406
|
-
ww.writeAsync(as.audioBuffer, (wavFile) => {
|
|
407
|
-
const blob = new Blob([wavFile], { type: 'audio/wav' });
|
|
408
|
-
const rfUrl = URL.createObjectURL(blob);
|
|
409
|
-
const dataDnlLnk = this.renderer.createElement('a');
|
|
410
|
-
//dataDnlLnk.name = 'Recording';
|
|
411
|
-
dataDnlLnk.href = rfUrl;
|
|
412
|
-
this.renderer.appendChild(document.body, dataDnlLnk);
|
|
413
|
-
// download property not yet in TS def
|
|
414
|
-
if (this.displayRecFile) {
|
|
415
|
-
let fn = this.displayRecFile.filenameString();
|
|
416
|
-
fn += '_' + this.displayRecFileVersion;
|
|
417
|
-
fn += '.wav';
|
|
418
|
-
dataDnlLnk.download = fn;
|
|
419
|
-
dataDnlLnk.click();
|
|
420
|
-
}
|
|
421
|
-
this.renderer.removeChild(document.body, dataDnlLnk);
|
|
422
|
-
});
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
set displayRecFile(displayRecFile) {
|
|
427
|
-
this._displayRecFile = displayRecFile;
|
|
428
|
-
}
|
|
429
|
-
updateDisplayRecFile(displayRecFile, fetchAndApplyRecordingFile = true) {
|
|
430
|
-
this.displayRecFile = displayRecFile;
|
|
431
|
-
if (this._displayRecFile) {
|
|
432
|
-
if (this.items) {
|
|
433
|
-
this.items.currentRecordingFile = this._displayRecFile;
|
|
434
|
-
}
|
|
435
|
-
let adh = this._displayRecFile.audioDataHolder;
|
|
436
|
-
if (adh) {
|
|
437
|
-
this.displayAudioClip = new AudioClip(adh);
|
|
438
|
-
if (this._controlAudioPlayer) {
|
|
439
|
-
this._controlAudioPlayer.audioClip = this.displayAudioClip;
|
|
440
|
-
}
|
|
441
|
-
this.showRecording();
|
|
442
|
-
}
|
|
443
|
-
else {
|
|
444
|
-
// clear for now ...
|
|
445
|
-
this.displayAudioClip = null;
|
|
446
|
-
if (this.controlAudioPlayer) {
|
|
447
|
-
this.controlAudioPlayer.audioClip = null;
|
|
448
|
-
}
|
|
449
|
-
if (fetchAndApplyRecordingFile) {
|
|
450
|
-
if (this._controlAudioPlayer && this._session) {
|
|
451
|
-
//... and try to fetch from server
|
|
452
|
-
this.liveLevelDisplayState = LiveLevelState.LOADING;
|
|
453
|
-
const rf = this._displayRecFile;
|
|
454
|
-
let audioDownloadType = this._clientAudioStorageType;
|
|
455
|
-
if (AudioStorageType.MEM_ENTIRE_AUTO_NET_CHUNKED === this._clientAudioStorageType || AudioStorageType.MEM_CHUNKED_AUTO_NET_CHUNKED === this._clientAudioStorageType) {
|
|
456
|
-
// Default is network mode
|
|
457
|
-
audioDownloadType = AudioStorageType.NET_CHUNKED;
|
|
458
|
-
if (rf.channels && rf.frames) {
|
|
459
|
-
const samples = rf.channels * rf.frames;
|
|
460
|
-
if (samples <= this._maxAutoNetMemStoreSamples) {
|
|
461
|
-
// But if audio file is small, load in continuous resp. chunked mode
|
|
462
|
-
if (AudioStorageType.MEM_ENTIRE_AUTO_NET_CHUNKED === this._clientAudioStorageType) {
|
|
463
|
-
audioDownloadType = AudioStorageType.MEM_ENTIRE;
|
|
464
|
-
}
|
|
465
|
-
else if (AudioStorageType.MEM_CHUNKED_AUTO_NET_CHUNKED === this._clientAudioStorageType) {
|
|
466
|
-
audioDownloadType = AudioStorageType.MEM_CHUNKED;
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
console.debug("Audio download type: " + audioDownloadType);
|
|
472
|
-
if (AudioStorageType.DB_CHUNKED === this._clientAudioStorageType) {
|
|
473
|
-
// Fetch chunked indexed db audio buffer
|
|
474
|
-
let nextIab = null;
|
|
475
|
-
if (!this._persistentAudioStorageTarget) {
|
|
476
|
-
throw Error('Error: Persistent storage target not set.');
|
|
477
|
-
}
|
|
478
|
-
else {
|
|
479
|
-
//console.debug("Fetch audio and store to indexed db...");
|
|
480
|
-
this.audioFetchSubscription = this.recFileService.fetchSprRecordingFileIndDbAudioBuffer(this._persistentAudioStorageTarget, this._session.project, rf).subscribe({
|
|
481
|
-
next: (iab) => {
|
|
482
|
-
//console.debug("Sessionmanager: Received inddb audio buffer: "+iab);
|
|
483
|
-
nextIab = iab;
|
|
484
|
-
},
|
|
485
|
-
complete: () => {
|
|
486
|
-
this.liveLevelDisplayState = LiveLevelState.READY;
|
|
487
|
-
let fabDh = null;
|
|
488
|
-
if (nextIab) {
|
|
489
|
-
if (rf && this.items) {
|
|
490
|
-
fabDh = new AudioDataHolder(nextIab);
|
|
491
|
-
this.items.setSprRecFileAudioData(rf, fabDh);
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
else {
|
|
495
|
-
// Should actually be handled by the error resolver
|
|
496
|
-
this.statusMsg = 'Recording file could not be loaded.';
|
|
497
|
-
this.statusAlertType = 'error';
|
|
498
|
-
}
|
|
499
|
-
if (fabDh) {
|
|
500
|
-
// this.displayAudioClip could have been changed meanwhile, but the recorder unsubcribes before changing the item, therefore there should be no risk to set to wrong item
|
|
501
|
-
this.displayAudioClip = new AudioClip(fabDh);
|
|
502
|
-
}
|
|
503
|
-
if (this._controlAudioPlayer) {
|
|
504
|
-
this._controlAudioPlayer.audioClip = this.displayAudioClip;
|
|
505
|
-
}
|
|
506
|
-
this.showRecording();
|
|
507
|
-
},
|
|
508
|
-
error: err => {
|
|
509
|
-
console.error("Could not load recording file from server: " + err);
|
|
510
|
-
this.liveLevelDisplayState = LiveLevelState.READY;
|
|
511
|
-
this.statusMsg = 'Recording file could not be loaded: ' + err;
|
|
512
|
-
this.statusAlertType = 'error';
|
|
513
|
-
this.changeDetectorRef.detectChanges();
|
|
514
|
-
}
|
|
515
|
-
});
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
else if (AudioStorageType.NET_CHUNKED === audioDownloadType) {
|
|
519
|
-
// Fetch chunked audio buffer from network
|
|
520
|
-
let nextNetAb = null;
|
|
521
|
-
//console.debug("Fetch chunked audio from network");
|
|
522
|
-
this.audioFetchSubscription = this.recFileService.fetchSprRecordingFileNetAudioBuffer(this._session.project, rf).subscribe({
|
|
523
|
-
next: (netAb) => {
|
|
524
|
-
//console.debug("Sessionmanager: Received net audio buffer: "+netAb);
|
|
525
|
-
nextNetAb = netAb;
|
|
526
|
-
},
|
|
527
|
-
complete: () => {
|
|
528
|
-
this.liveLevelDisplayState = LiveLevelState.READY;
|
|
529
|
-
let fabDh = null;
|
|
530
|
-
if (nextNetAb) {
|
|
531
|
-
if (rf && this.items) {
|
|
532
|
-
fabDh = new AudioDataHolder(nextNetAb);
|
|
533
|
-
this.items.setSprRecFileAudioData(rf, fabDh);
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
else {
|
|
537
|
-
// Should actually be handled by the error resolver
|
|
538
|
-
this.statusMsg = 'Recording file could not be loaded.';
|
|
539
|
-
this.statusAlertType = 'error';
|
|
540
|
-
}
|
|
541
|
-
if (fabDh) {
|
|
542
|
-
// this.displayAudioClip could have been changed meanwhile, but the recorder unsubcribes before changing the item, therefore there should be no risk to set to wrong item
|
|
543
|
-
//console.debug("set displayRecFile(): fetch net ab complete, set displayAudioClip.")
|
|
544
|
-
this.displayAudioClip = new AudioClip(fabDh);
|
|
545
|
-
}
|
|
546
|
-
if (this._controlAudioPlayer) {
|
|
547
|
-
this._controlAudioPlayer.audioClip = this.displayAudioClip;
|
|
548
|
-
}
|
|
549
|
-
this.showRecording();
|
|
550
|
-
},
|
|
551
|
-
error: err => {
|
|
552
|
-
console.error("Could not load recording file from server: " + err);
|
|
553
|
-
this.liveLevelDisplayState = LiveLevelState.READY;
|
|
554
|
-
this.statusMsg = 'Recording file could not be loaded: ' + err;
|
|
555
|
-
this.statusAlertType = 'error';
|
|
556
|
-
this.changeDetectorRef.detectChanges();
|
|
557
|
-
}
|
|
558
|
-
});
|
|
559
|
-
}
|
|
560
|
-
else if (AudioStorageType.MEM_CHUNKED === audioDownloadType) {
|
|
561
|
-
// Fetch chunked array audio buffer
|
|
562
|
-
let nextAab = null;
|
|
563
|
-
//console.debug("Fetch audio and store to (chunked) array buffer...");
|
|
564
|
-
this.audioFetchSubscription = this.recFileService.fetchSprRecordingFileArrayAudioBuffer(this._session.project, rf).subscribe({
|
|
565
|
-
next: (aab) => {
|
|
566
|
-
nextAab = aab;
|
|
567
|
-
},
|
|
568
|
-
complete: () => {
|
|
569
|
-
this.liveLevelDisplayState = LiveLevelState.READY;
|
|
570
|
-
let fabDh = null;
|
|
571
|
-
if (nextAab) {
|
|
572
|
-
if (rf && this.items) {
|
|
573
|
-
fabDh = new AudioDataHolder(nextAab);
|
|
574
|
-
this.items.setSprRecFileAudioData(rf, fabDh);
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
else {
|
|
578
|
-
// Should actually be handled by the error resolver
|
|
579
|
-
this.statusMsg = 'Recording file could not be loaded.';
|
|
580
|
-
this.statusAlertType = 'error';
|
|
581
|
-
}
|
|
582
|
-
if (fabDh) {
|
|
583
|
-
// this.displayAudioClip could have been changed meanwhile, but the recorder unsubcribes before changing the item, therefore there should be no risk to set to wrong item
|
|
584
|
-
this.displayAudioClip = new AudioClip(fabDh);
|
|
585
|
-
}
|
|
586
|
-
if (this._controlAudioPlayer) {
|
|
587
|
-
this._controlAudioPlayer.audioClip = this.displayAudioClip;
|
|
588
|
-
}
|
|
589
|
-
this.showRecording();
|
|
590
|
-
},
|
|
591
|
-
error: err => {
|
|
592
|
-
console.error("Could not load recording file from server: " + err);
|
|
593
|
-
this.liveLevelDisplayState = LiveLevelState.READY;
|
|
594
|
-
this.statusMsg = 'Recording file could not be loaded: ' + err;
|
|
595
|
-
this.statusAlertType = 'error';
|
|
596
|
-
}
|
|
597
|
-
});
|
|
598
|
-
}
|
|
599
|
-
else {
|
|
600
|
-
// Fetch regular audio buffer
|
|
601
|
-
//console.debug("Fetch audio and store to audio buffer...");
|
|
602
|
-
this.audioFetchSubscription = this.recFileService.fetchSprRecordingFileAudioBuffer(this._session.project, rf).subscribe({
|
|
603
|
-
next: (ab) => {
|
|
604
|
-
this.liveLevelDisplayState = LiveLevelState.READY;
|
|
605
|
-
let fabDh = null;
|
|
606
|
-
if (ab) {
|
|
607
|
-
if (rf && this.items) {
|
|
608
|
-
if (SessionManager.FORCE_ARRRAY_AUDIO_BUFFER) {
|
|
609
|
-
let aab = ArrayAudioBuffer.fromAudioBuffer(ab);
|
|
610
|
-
fabDh = new AudioDataHolder(aab);
|
|
611
|
-
}
|
|
612
|
-
else {
|
|
613
|
-
fabDh = new AudioDataHolder(new AudioBufferSource(ab));
|
|
614
|
-
}
|
|
615
|
-
this.items.setSprRecFileAudioData(rf, fabDh);
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
else {
|
|
619
|
-
// Should actually be handled by the error resolver
|
|
620
|
-
this.statusMsg = 'Recording file could not be loaded.';
|
|
621
|
-
this.statusAlertType = 'error';
|
|
622
|
-
}
|
|
623
|
-
if (fabDh) {
|
|
624
|
-
// this.displayAudioClip could have been changed meanwhile, but the recorder unsubcribes before changing the item, therefore there should be no risk to set to wrong item
|
|
625
|
-
this.displayAudioClip = new AudioClip(fabDh);
|
|
626
|
-
}
|
|
627
|
-
if (this._controlAudioPlayer) {
|
|
628
|
-
this._controlAudioPlayer.audioClip = this.displayAudioClip;
|
|
629
|
-
}
|
|
630
|
-
this.showRecording();
|
|
631
|
-
}, error: err => {
|
|
632
|
-
console.error("Could not load recording file from server: " + err);
|
|
633
|
-
this.liveLevelDisplayState = LiveLevelState.READY;
|
|
634
|
-
this.statusMsg = 'Recording file could not be loaded: ' + err;
|
|
635
|
-
this.statusAlertType = 'error';
|
|
636
|
-
}
|
|
637
|
-
});
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
else {
|
|
641
|
-
this.statusMsg = 'Recording file could not be decoded. Audio context unavailable.';
|
|
642
|
-
this.statusAlertType = 'error';
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
}
|
|
647
|
-
else {
|
|
648
|
-
this.displayAudioClip = null;
|
|
649
|
-
if (this.controlAudioPlayer) {
|
|
650
|
-
this.controlAudioPlayer.audioClip = null;
|
|
651
|
-
}
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
get displayRecFile() {
|
|
655
|
-
return this._displayRecFile;
|
|
656
|
-
}
|
|
657
|
-
isRecordingItem() {
|
|
658
|
-
return (this.promptItem != null && this.promptItem.type !== 'nonrecording');
|
|
659
|
-
}
|
|
660
|
-
updateStartActionDisableState() {
|
|
661
|
-
this.transportActions.startAction.disabled = !(this.ac && this.isRecordingItem());
|
|
662
|
-
}
|
|
663
|
-
applyItem(temporary = false) {
|
|
664
|
-
this.section = this._script.sections[this.sectIdx];
|
|
665
|
-
this.group = this.section._shuffledGroups[this.groupIdxInSection];
|
|
666
|
-
this.promptItem = this.group._shuffledPromptItems[this.promptItemIdxInGroup];
|
|
667
|
-
//this.selectedItemIdx = this.promptIndex;
|
|
668
|
-
if (this.audioFetchSubscription) {
|
|
669
|
-
//console.debug("Unsubscribe from audio fetch.");
|
|
670
|
-
this.audioFetchSubscription.unsubscribe();
|
|
671
|
-
}
|
|
672
|
-
if (!temporary) {
|
|
673
|
-
this.displayAudioClip = null;
|
|
674
|
-
this.showRecording();
|
|
675
|
-
}
|
|
676
|
-
this.liveLevelDisplayState = LiveLevelState.READY;
|
|
677
|
-
this.clearPrompt();
|
|
678
|
-
const isNonrecording = (this.promptItem.type === 'nonrecording');
|
|
679
|
-
if (isNonrecording || !this.section.promptphase || this.section.promptphase === 'IDLE') {
|
|
680
|
-
this.applyPrompt();
|
|
681
|
-
}
|
|
682
|
-
if (isNonrecording) {
|
|
683
|
-
this.updateDisplayRecFile(null);
|
|
684
|
-
this.displayRecFileVersion = 0;
|
|
685
|
-
this.startStopSignalState = 4 /* OFF */;
|
|
686
|
-
}
|
|
687
|
-
else {
|
|
688
|
-
if (this.items) {
|
|
689
|
-
let it = this.items.getItem(this.promptIndex);
|
|
690
|
-
if (!it.recs) {
|
|
691
|
-
it.recs = new Array();
|
|
692
|
-
}
|
|
693
|
-
let recentRecFile = null;
|
|
694
|
-
let availRecfiles = it.recs.length;
|
|
695
|
-
if (availRecfiles > 0) {
|
|
696
|
-
let rfVers = availRecfiles - 1;
|
|
697
|
-
recentRecFile = it.recs[rfVers];
|
|
698
|
-
this.updateDisplayRecFile(recentRecFile, !temporary);
|
|
699
|
-
this.displayRecFileVersion = rfVers;
|
|
700
|
-
}
|
|
701
|
-
else {
|
|
702
|
-
this.updateDisplayRecFile(null);
|
|
703
|
-
this.displayRecFileVersion = 0;
|
|
704
|
-
}
|
|
705
|
-
}
|
|
706
|
-
if (!this.readonly) {
|
|
707
|
-
this.startStopSignalState = 0 /* IDLE */;
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
// console.debug("applyItem(): temporary: "+temporary);
|
|
711
|
-
//if (!temporary) {
|
|
712
|
-
// console.debug("applyItem(): Call showRecording(): displayAudioClip: "+this.displayAudioClip);
|
|
713
|
-
//this.showRecording();
|
|
714
|
-
//}
|
|
715
|
-
this.updateStartActionDisableState();
|
|
716
|
-
this.updateNavigationActions();
|
|
717
|
-
}
|
|
718
|
-
start() {
|
|
719
|
-
super.start();
|
|
720
|
-
if (this.promptItemCount > 0) {
|
|
721
|
-
this.promptIndex = 0;
|
|
722
|
-
}
|
|
723
|
-
this.enableNavigation();
|
|
724
|
-
}
|
|
725
|
-
isRecording() {
|
|
726
|
-
return (this.status === 3 /* PRE_RECORDING */ || this.status === 4 /* RECORDING */ || this.status === 5 /* POST_REC_STOP */ || this.status === 6 /* POST_REC_PAUSE */ || this.status === 7 /* STOPPING_STOP */);
|
|
727
|
-
}
|
|
728
|
-
isActive() {
|
|
729
|
-
return (!(this.status === 0 /* BLOCKED */ || this.status === 1 /* IDLE */ || this.status === 9 /* ERROR */) || this.processingRecording || this.sessionService.uploadCount > 0);
|
|
730
|
-
}
|
|
731
|
-
prevItem() {
|
|
732
|
-
let newPrIdx = this._promptIndex;
|
|
733
|
-
newPrIdx--;
|
|
734
|
-
if (newPrIdx < 0) {
|
|
735
|
-
newPrIdx = this.promptItemCount - 1;
|
|
736
|
-
}
|
|
737
|
-
this.promptIndex = newPrIdx;
|
|
738
|
-
//this.updateNavigationActions()
|
|
739
|
-
}
|
|
740
|
-
nextItem() {
|
|
741
|
-
let newPrIdx = this._promptIndex;
|
|
742
|
-
newPrIdx++;
|
|
743
|
-
if (newPrIdx >= this.promptItemCount) {
|
|
744
|
-
newPrIdx = 0;
|
|
745
|
-
}
|
|
746
|
-
this.promptIndex = newPrIdx;
|
|
747
|
-
//this.updateNavigationActions();
|
|
748
|
-
}
|
|
749
|
-
updateNavigationActions() {
|
|
750
|
-
let fwdNxtActionDisabled = true;
|
|
751
|
-
if (this.items) {
|
|
752
|
-
let currRecs = this.items.getItem(this._promptIndex).recs;
|
|
753
|
-
fwdNxtActionDisabled = !(currRecs != null && currRecs.length > 0);
|
|
754
|
-
}
|
|
755
|
-
this.transportActions.fwdNextAction.disabled = this.navigationDisabled || fwdNxtActionDisabled;
|
|
756
|
-
this.transportActions.fwdAction.disabled = this.navigationDisabled;
|
|
757
|
-
this.transportActions.bwdAction.disabled = this.navigationDisabled;
|
|
758
|
-
}
|
|
759
|
-
nextUnrecordedItem() {
|
|
760
|
-
let newPrIdx = this._promptIndex;
|
|
761
|
-
newPrIdx++;
|
|
762
|
-
if (newPrIdx >= this.promptItemCount) {
|
|
763
|
-
newPrIdx = 0;
|
|
764
|
-
}
|
|
765
|
-
if (this.items != null) {
|
|
766
|
-
let it = this.items.getItem(newPrIdx);
|
|
767
|
-
while ((!it.recording || it.itemDone()) && newPrIdx < this.promptItemCount) {
|
|
768
|
-
newPrIdx++;
|
|
769
|
-
it = this.items.getItem(newPrIdx);
|
|
770
|
-
}
|
|
771
|
-
if (!it.itemDone()) {
|
|
772
|
-
this.promptIndex = newPrIdx;
|
|
773
|
-
}
|
|
774
|
-
}
|
|
775
|
-
}
|
|
776
|
-
enableStartUserGesture() {
|
|
777
|
-
super.enableStartUserGesture();
|
|
778
|
-
this.transportActions.startAction.disabled = !(this.ac && this.isRecordingItem());
|
|
779
|
-
}
|
|
780
|
-
enableNavigation() {
|
|
781
|
-
this.navigationDisabled = false;
|
|
782
|
-
this.updateNavigationActions();
|
|
783
|
-
}
|
|
784
|
-
started() {
|
|
785
|
-
let ic = this.promptItem.itemcode;
|
|
786
|
-
let rf = null;
|
|
787
|
-
if (this._session && ic) {
|
|
788
|
-
let sessId = this._session.sessionId;
|
|
789
|
-
let cpIdx = this.promptIndex;
|
|
790
|
-
if (this.items) {
|
|
791
|
-
let it = this.items.getItem(cpIdx);
|
|
792
|
-
if (!it.recs) {
|
|
793
|
-
it.recs = new Array();
|
|
794
|
-
}
|
|
795
|
-
rf = new SprRecordingFile(sessId, ic, it.recs.length, null);
|
|
796
|
-
rf.uuid = this.rfUuid;
|
|
797
|
-
//it.recs.push(rf);
|
|
798
|
-
this.items.addSprRecFile(it, rf);
|
|
799
|
-
this.items.currentRecordingFile = rf;
|
|
800
|
-
}
|
|
801
|
-
}
|
|
802
|
-
this._recordingFile = rf;
|
|
803
|
-
this.status = 3 /* PRE_RECORDING */;
|
|
804
|
-
super.started();
|
|
805
|
-
this.startStopSignalState = 1 /* PRERECORDING */;
|
|
806
|
-
if (this._session) {
|
|
807
|
-
if (this._session.status === "LOADED") {
|
|
808
|
-
let body = {};
|
|
809
|
-
if (this.section.training) {
|
|
810
|
-
this._session.status = "STARTED_TRAINING";
|
|
811
|
-
body.status = this._session.status;
|
|
812
|
-
if (!this._session.startedTrainingDate) {
|
|
813
|
-
this._session.startedTrainingDate = new Date();
|
|
814
|
-
body.startedTrainingDate = this._session.startedTrainingDate;
|
|
815
|
-
}
|
|
816
|
-
}
|
|
817
|
-
else {
|
|
818
|
-
this._session.status = "STARTED";
|
|
819
|
-
body.status = this._session.status;
|
|
820
|
-
if (!this._session.startedDate) {
|
|
821
|
-
this._session.startedDate = new Date();
|
|
822
|
-
body.startedDate = this._session.startedDate;
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
this.sessionService.patchSessionObserver(this._session, body).subscribe();
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
if (this.section.promptphase === 'PRERECORDING' || this.section.promptphase === 'PRERECORDINGONLY') {
|
|
829
|
-
this.applyPrompt();
|
|
830
|
-
}
|
|
831
|
-
this.statusAlertType = 'info';
|
|
832
|
-
this.statusMsg = 'Recording...';
|
|
833
|
-
let preDelay = DEFAULT_PRE_REC_DELAY;
|
|
834
|
-
if (this.promptItem.prerecdelay != null) {
|
|
835
|
-
preDelay = this.promptItem.prerecdelay;
|
|
836
|
-
}
|
|
837
|
-
else if (this.promptItem.prerecording != null) {
|
|
838
|
-
preDelay = this.promptItem.prerecording;
|
|
839
|
-
}
|
|
840
|
-
this.postDelay = DEFAULT_POST_REC_DELAY;
|
|
841
|
-
if (this.promptItem.postrecdelay != null) {
|
|
842
|
-
this.postDelay = this.promptItem.postrecdelay;
|
|
843
|
-
}
|
|
844
|
-
else if (this.promptItem.postrecording != null) {
|
|
845
|
-
this.postDelay = this.promptItem.postrecording;
|
|
846
|
-
}
|
|
847
|
-
let maxRecordingTimeMs = MAX_RECORDING_TIME_MS;
|
|
848
|
-
if (this.promptItem.recduration !== null && this.promptItem.recduration !== undefined) {
|
|
849
|
-
maxRecordingTimeMs = preDelay + this.promptItem.recduration + this.postDelay;
|
|
850
|
-
}
|
|
851
|
-
this.maxRecTimerId = window.setTimeout(() => {
|
|
852
|
-
this.stopRecordingMaxRec();
|
|
853
|
-
}, maxRecordingTimeMs);
|
|
854
|
-
this.maxRecTimerRunning = true;
|
|
855
|
-
this.preRecTimerId = window.setTimeout(() => {
|
|
856
|
-
this.preRecTimerRunning = false;
|
|
857
|
-
this.status = 4 /* RECORDING */;
|
|
858
|
-
this.startStopSignalState = 3 /* RECORDING */;
|
|
859
|
-
if (this.section.mode === 'AUTORECORDING') {
|
|
860
|
-
this.transportActions.nextAction.disabled = false;
|
|
861
|
-
this.transportActions.pauseAction.disabled = false;
|
|
862
|
-
}
|
|
863
|
-
else {
|
|
864
|
-
this.transportActions.stopAction.disabled = false;
|
|
865
|
-
}
|
|
866
|
-
if (this.section.promptphase === 'RECORDING') {
|
|
867
|
-
this.applyPrompt();
|
|
868
|
-
}
|
|
869
|
-
if (this.section.promptphase === 'PRERECORDINGONLY') {
|
|
870
|
-
this.clearPrompt();
|
|
871
|
-
}
|
|
872
|
-
}, preDelay);
|
|
873
|
-
this.preRecTimerRunning = true;
|
|
874
|
-
}
|
|
875
|
-
stopItem() {
|
|
876
|
-
this.status = 5 /* POST_REC_STOP */;
|
|
877
|
-
this.startStopSignalState = 2 /* POSTRECORDING */;
|
|
878
|
-
this.transportActions.stopAction.disabled = true;
|
|
879
|
-
this.transportActions.nextAction.disabled = true;
|
|
880
|
-
this.clearPreRecTimer();
|
|
881
|
-
this.postRecTimerId = window.setTimeout(() => {
|
|
882
|
-
this.postRecTimerRunning = false;
|
|
883
|
-
this.status = 7 /* STOPPING_STOP */;
|
|
884
|
-
this.stopRecording();
|
|
885
|
-
}, this.postDelay);
|
|
886
|
-
this.postRecTimerRunning = true;
|
|
887
|
-
}
|
|
888
|
-
pauseItem() {
|
|
889
|
-
this.status = 6 /* POST_REC_PAUSE */;
|
|
890
|
-
this.transportActions.pauseAction.disabled = true;
|
|
891
|
-
this.startStopSignalState = 2 /* POSTRECORDING */;
|
|
892
|
-
this.transportActions.stopAction.disabled = true;
|
|
893
|
-
this.transportActions.nextAction.disabled = true;
|
|
894
|
-
this.transportActions.pauseAction.disabled = true;
|
|
895
|
-
this.clearPreRecTimer();
|
|
896
|
-
this.postRecTimerId = window.setTimeout(() => {
|
|
897
|
-
this.postRecTimerRunning = false;
|
|
898
|
-
this.status = 8 /* STOPPING_PAUSE */;
|
|
899
|
-
this.stopRecording();
|
|
900
|
-
}, this.postDelay);
|
|
901
|
-
this.postRecTimerRunning = true;
|
|
902
|
-
}
|
|
903
|
-
stopRecording() {
|
|
904
|
-
this.clearMaxRecTimer();
|
|
905
|
-
if (this.ac) {
|
|
906
|
-
this.ac.stop();
|
|
907
|
-
}
|
|
908
|
-
}
|
|
909
|
-
stopRecordingMaxRec() {
|
|
910
|
-
this.clearPreRecTimer();
|
|
911
|
-
this.clearPostRecTimer();
|
|
912
|
-
this.maxRecTimerRunning = false;
|
|
913
|
-
this.status = 7 /* STOPPING_STOP */;
|
|
914
|
-
if (this.ac) {
|
|
915
|
-
this.ac.stop();
|
|
916
|
-
}
|
|
917
|
-
}
|
|
918
|
-
addRecordingFileByDescriptor(rfd) {
|
|
919
|
-
if (rfd.recording && rfd.recording.itemcode) {
|
|
920
|
-
let prIdx = this.promptIndexByItemcode(rfd.recording.itemcode);
|
|
921
|
-
if (this.items != null && prIdx !== null) {
|
|
922
|
-
let it = this.items.getItem(prIdx);
|
|
923
|
-
if (it && this._session) {
|
|
924
|
-
// if (!it.recs) {
|
|
925
|
-
// it.recs = new Array<SprRecordingFile>();
|
|
926
|
-
// }
|
|
927
|
-
let rf = new SprRecordingFile(this._session.sessionId, rfd.recording.itemcode, rfd.version, null);
|
|
928
|
-
rf.serverPersisted = true;
|
|
929
|
-
//console.debug("addRecordingFileByDescriptor(): sr: "+rfd.samplerate+", frames: "+rfd.frames);
|
|
930
|
-
if (rfd.samplerate && rfd.frames) {
|
|
931
|
-
rf.samplerate = rfd.samplerate;
|
|
932
|
-
rf.frames = rfd.frames;
|
|
933
|
-
}
|
|
934
|
-
if (rfd.channels) {
|
|
935
|
-
rf.channels = rfd.channels;
|
|
936
|
-
}
|
|
937
|
-
this.items.addSprRecFile(it, rf);
|
|
938
|
-
}
|
|
939
|
-
else {
|
|
940
|
-
//console.debug("WARN: No recording item with code: \"" +rfd.recording.itemcode+ "\" found.");
|
|
941
|
-
}
|
|
942
|
-
}
|
|
943
|
-
else {
|
|
944
|
-
//console.debug("WARN: No recording item with code: \"" +rfd.recording.itemcode+ "\" found.");
|
|
945
|
-
}
|
|
946
|
-
}
|
|
947
|
-
}
|
|
948
|
-
// addRecordingFileByPromptIndex(promptIndex:number, rf:SprRecordingFile){
|
|
949
|
-
//
|
|
950
|
-
// }
|
|
951
|
-
stopped() {
|
|
952
|
-
this.clearPreRecTimer();
|
|
953
|
-
this.clearPostRecTimer();
|
|
954
|
-
this.clearMaxRecTimer();
|
|
955
|
-
this.updateStartActionDisableState();
|
|
956
|
-
this.transportActions.stopAction.disabled = true;
|
|
957
|
-
this.transportActions.nextAction.disabled = true;
|
|
958
|
-
this.transportActions.pauseAction.disabled = true;
|
|
959
|
-
this.statusAlertType = 'info';
|
|
960
|
-
this.statusMsg = 'Recorded.';
|
|
961
|
-
this.startStopSignalState = 0 /* IDLE */;
|
|
962
|
-
let adh = null;
|
|
963
|
-
let as = null;
|
|
964
|
-
let ab = null;
|
|
965
|
-
if (this.ac) {
|
|
966
|
-
if (AudioStorageType.NET_CHUNKED === this.ac.audioStorageType) {
|
|
967
|
-
this.playStartAction.disabled = true;
|
|
968
|
-
this.keepLiveLevel = true;
|
|
969
|
-
let burl = null;
|
|
970
|
-
if (this._session) {
|
|
971
|
-
if (this._displayRecFile) {
|
|
972
|
-
// TODO is this branch ever called ?
|
|
973
|
-
let rf = this._displayRecFile;
|
|
974
|
-
rf.frames = this.ac.framesRecorded;
|
|
975
|
-
//console.debug("stopped(): Set frames: "+rf.frames+" on rfId: "+this.displayRecFile?.recordingFileId);
|
|
976
|
-
burl = this.recFileService.sprAudioFileUrl(this._session?.project, rf);
|
|
977
|
-
}
|
|
978
|
-
else if (this.session?.project && this._recordingFile && this._recordingFile instanceof SprRecordingFile) {
|
|
979
|
-
burl = this.recFileService.sprAudioFileUrlByItemcode(this.session?.project, this.session?.sessionId, this._recordingFile.itemCode, this._recordingFile.version);
|
|
980
|
-
}
|
|
981
|
-
else {
|
|
982
|
-
console.error("Could not create net audio buffer.");
|
|
983
|
-
}
|
|
984
|
-
if (burl) {
|
|
985
|
-
const rUUID = this.ac.recUUID;
|
|
986
|
-
const sr = this.ac.currentSampleRate;
|
|
987
|
-
const chFl = sr * RecordingService.DEFAULT_CHUNKED_DOWNLOAD_SECONDS;
|
|
988
|
-
//console.debug("stopped(): rfID: "+this._recordingFile?.recordingFileId+", net ab url: " + burl+", frames: "+this.ac.framesRecorded+", sample rate: "+sr);
|
|
989
|
-
let netAb = new NetAudioBuffer(this.recFileService, burl, this.ac.channelCount, sr, chFl, this.ac.framesRecorded, rUUID, chFl);
|
|
990
|
-
as = netAb;
|
|
991
|
-
if (this.uploadSet) {
|
|
992
|
-
//let rp=new ReadyProvider();
|
|
993
|
-
//netAb.readyProvider=rp;
|
|
994
|
-
this.uploadSet.onDone = (uploadSet) => {
|
|
995
|
-
console.debug("upload set on done: Call ready provider.ready");
|
|
996
|
-
//rp.ready();
|
|
997
|
-
netAb.ready();
|
|
998
|
-
};
|
|
999
|
-
}
|
|
1000
|
-
}
|
|
1001
|
-
}
|
|
1002
|
-
}
|
|
1003
|
-
else if (AudioStorageType.MEM_ENTIRE_AUTO_NET_CHUNKED === this.ac.audioStorageType || AudioStorageType.MEM_CHUNKED_AUTO_NET_CHUNKED === this.ac.audioStorageType) {
|
|
1004
|
-
if (AudioStorageType.MEM_ENTIRE_AUTO_NET_CHUNKED === this.ac.audioStorageType) {
|
|
1005
|
-
const acAb = this.ac.audioBuffer();
|
|
1006
|
-
if (acAb) {
|
|
1007
|
-
as = new AudioBufferSource(acAb);
|
|
1008
|
-
}
|
|
1009
|
-
}
|
|
1010
|
-
if (AudioStorageType.MEM_CHUNKED_AUTO_NET_CHUNKED === this.ac.audioStorageType) {
|
|
1011
|
-
as = this.ac.audioBufferArray();
|
|
1012
|
-
}
|
|
1013
|
-
if (!as) {
|
|
1014
|
-
this.playStartAction.disabled = true;
|
|
1015
|
-
this.keepLiveLevel = true;
|
|
1016
|
-
let burl = null;
|
|
1017
|
-
if (this._session) {
|
|
1018
|
-
if (this._displayRecFile) {
|
|
1019
|
-
// TODO is this branch ever called ?
|
|
1020
|
-
let rf = this._displayRecFile;
|
|
1021
|
-
rf.frames = this.ac.framesRecorded;
|
|
1022
|
-
//console.debug("stopped(): Set frames: "+rf.frames+" on rfId: "+this.displayRecFile?.recordingFileId);
|
|
1023
|
-
burl = this.recFileService.sprAudioFileUrl(this._session?.project, rf);
|
|
1024
|
-
}
|
|
1025
|
-
else if (this.session?.project && this._recordingFile && this._recordingFile instanceof SprRecordingFile) {
|
|
1026
|
-
burl = this.recFileService.sprAudioFileUrlByItemcode(this.session?.project, this.session?.sessionId, this._recordingFile.itemCode, this._recordingFile.version);
|
|
1027
|
-
}
|
|
1028
|
-
else {
|
|
1029
|
-
console.error("Could not create net audio buffer.");
|
|
1030
|
-
}
|
|
1031
|
-
if (burl) {
|
|
1032
|
-
const rUUID = this.ac.recUUID;
|
|
1033
|
-
const sr = this.ac.currentSampleRate;
|
|
1034
|
-
const chFl = sr * RecordingService.DEFAULT_CHUNKED_DOWNLOAD_SECONDS;
|
|
1035
|
-
//console.debug("stopped(): rfID: "+this._recordingFile?.recordingFileId+", net ab url: " + burl+", frames: "+this.ac.framesRecorded+", sample rate: "+sr);
|
|
1036
|
-
const netAb = new NetAudioBuffer(this.recFileService, burl, this.ac.channelCount, sr, chFl, this.ac.framesRecorded, rUUID, chFl);
|
|
1037
|
-
as = netAb;
|
|
1038
|
-
if (this.uploadSet) {
|
|
1039
|
-
this.uploadSet.onDone = (uploadSet) => {
|
|
1040
|
-
console.debug("upload set on done: Call ready provider.ready");
|
|
1041
|
-
netAb.ready();
|
|
1042
|
-
};
|
|
1043
|
-
}
|
|
1044
|
-
}
|
|
1045
|
-
}
|
|
1046
|
-
}
|
|
1047
|
-
}
|
|
1048
|
-
else if (AudioStorageType.DB_CHUNKED === this.ac.audioStorageType) {
|
|
1049
|
-
as = this.ac.inddbAudioBufferArray();
|
|
1050
|
-
}
|
|
1051
|
-
else if (AudioStorageType.MEM_CHUNKED === this.ac.audioStorageType) {
|
|
1052
|
-
as = this.ac.audioBufferArray();
|
|
1053
|
-
}
|
|
1054
|
-
else {
|
|
1055
|
-
ab = this.ac.audioBuffer();
|
|
1056
|
-
if (ab) {
|
|
1057
|
-
as = new AudioBufferSource(ab);
|
|
1058
|
-
}
|
|
1059
|
-
}
|
|
1060
|
-
if (as) {
|
|
1061
|
-
adh = new AudioDataHolder(as);
|
|
1062
|
-
}
|
|
1063
|
-
}
|
|
1064
|
-
// Use an own reference since the writing of the wave file is asynchronous and this._recordingFile might already contain the next recording
|
|
1065
|
-
let rf = this._recordingFile;
|
|
1066
|
-
if (rf && rf instanceof SprRecordingFile) {
|
|
1067
|
-
this.items?.setSprRecFileAudioData(rf, adh);
|
|
1068
|
-
if (this.enableUploadRecordings && this._uploadChunkSizeSeconds === null && AudioStorageType.MEM_ENTIRE === this._clientAudioStorageType) {
|
|
1069
|
-
// TODO use SpeechRecorderconfig resp. RecfileService
|
|
1070
|
-
// convert asynchronously to 16-bit integer PCM
|
|
1071
|
-
// TODO could we avoid conversion to save CPU resources and transfer float PCM directly?
|
|
1072
|
-
// TODO duplicate conversion for manual download
|
|
1073
|
-
//console.log("Build wav writer...");
|
|
1074
|
-
if (ab) {
|
|
1075
|
-
this.processingRecording = true;
|
|
1076
|
-
let ww = new WavWriter();
|
|
1077
|
-
//new REST API URL
|
|
1078
|
-
let apiEndPoint = '';
|
|
1079
|
-
if (this.config && this.config.apiEndPoint) {
|
|
1080
|
-
apiEndPoint = this.config.apiEndPoint;
|
|
1081
|
-
}
|
|
1082
|
-
if (apiEndPoint !== '') {
|
|
1083
|
-
apiEndPoint = apiEndPoint + '/';
|
|
1084
|
-
}
|
|
1085
|
-
let sessionsUrl = apiEndPoint + SessionService.SESSION_API_CTX;
|
|
1086
|
-
let recUrl = sessionsUrl + '/' + rf.session + '/' + RECFILE_API_CTX + '/' + rf.itemCode;
|
|
1087
|
-
ww.writeAsync(ab, (wavFile) => {
|
|
1088
|
-
this.postRecording(wavFile, recUrl, rf);
|
|
1089
|
-
this.processingRecording = false;
|
|
1090
|
-
this.updateWakeLock();
|
|
1091
|
-
});
|
|
1092
|
-
}
|
|
1093
|
-
}
|
|
1094
|
-
}
|
|
1095
|
-
// check complete session
|
|
1096
|
-
let complete = true;
|
|
1097
|
-
if (this.items) {
|
|
1098
|
-
// search backwards, to gain faster detection of incomplete state
|
|
1099
|
-
for (let ri = this.items.length() - 1; ri >= 0; ri--) {
|
|
1100
|
-
let it = this.items.getItem(ri);
|
|
1101
|
-
if (it.recording && !it.training && !it.itemDone()) {
|
|
1102
|
-
complete = false;
|
|
1103
|
-
break;
|
|
1104
|
-
}
|
|
1105
|
-
}
|
|
1106
|
-
}
|
|
1107
|
-
let autoStart = (this.status === 7 /* STOPPING_STOP */);
|
|
1108
|
-
this.status = 1 /* IDLE */;
|
|
1109
|
-
let startNext = false;
|
|
1110
|
-
if (complete) {
|
|
1111
|
-
if (this._session != null) {
|
|
1112
|
-
if (!this._session.sealed && this._session.status !== "COMPLETED") {
|
|
1113
|
-
let body = {};
|
|
1114
|
-
this._session.status = "COMPLETED";
|
|
1115
|
-
body.status = this._session.status;
|
|
1116
|
-
if (!this._session.completedDate) {
|
|
1117
|
-
this._session.completedDate = new Date();
|
|
1118
|
-
body.completedDate = this._session.completedDate;
|
|
1119
|
-
}
|
|
1120
|
-
this.sessionService.patchSessionObserver(this._session, body).subscribe();
|
|
1121
|
-
}
|
|
1122
|
-
}
|
|
1123
|
-
this.statusMsg = 'Session complete!';
|
|
1124
|
-
this.updateWakeLock();
|
|
1125
|
-
if (this.showSessionCompleteMessage) {
|
|
1126
|
-
this.dialog.open(SessionFinishedDialog, {});
|
|
1127
|
-
}
|
|
1128
|
-
// enable navigation
|
|
1129
|
-
this.transportActions.fwdAction.disabled = false;
|
|
1130
|
-
this.transportActions.bwdAction.disabled = false;
|
|
1131
|
-
}
|
|
1132
|
-
else {
|
|
1133
|
-
if (this.section.mode === 'AUTOPROGRESS' || this.section.mode === 'AUTORECORDING') {
|
|
1134
|
-
this.nextItem();
|
|
1135
|
-
}
|
|
1136
|
-
if (this.section.mode === 'AUTORECORDING' && this.autorecording && autoStart) {
|
|
1137
|
-
startNext = true;
|
|
1138
|
-
}
|
|
1139
|
-
else {
|
|
1140
|
-
this.navigationDisabled = false;
|
|
1141
|
-
this.updateNavigationActions();
|
|
1142
|
-
this.updateWakeLock();
|
|
1143
|
-
}
|
|
1144
|
-
}
|
|
1145
|
-
// apply recorded item
|
|
1146
|
-
this.applyItem(startNext);
|
|
1147
|
-
if (startNext) {
|
|
1148
|
-
this.startItem();
|
|
1149
|
-
}
|
|
1150
|
-
this.changeDetectorRef.detectChanges();
|
|
1151
|
-
}
|
|
1152
|
-
error(msg = 'An unknown error occured during recording.', advice = 'Please retry.') {
|
|
1153
|
-
this.status = 9 /* ERROR */;
|
|
1154
|
-
super.error(msg, advice);
|
|
1155
|
-
this.updateNavigationActions();
|
|
1156
|
-
this.updateStartActionDisableState();
|
|
1157
|
-
}
|
|
1158
|
-
postChunkAudioBuffer(audioBuffer, chunkIdx) {
|
|
1159
|
-
this.processingRecording = true;
|
|
1160
|
-
let ww = new WavWriter();
|
|
1161
|
-
let sessionsUrl = this.sessionsBaseUrl();
|
|
1162
|
-
let recUrl = sessionsUrl + '/' + this.session?.sessionId + '/' + RECFILE_API_CTX + '/' + this.promptItem.itemcode + '/' + this.rfUuid + '/' + chunkIdx;
|
|
1163
|
-
// The upload holder is required to add the upload now to the upload set. The real upload is created async in postrecording and the upload set is already complete at that time.
|
|
1164
|
-
let ulh = new UploadHolder();
|
|
1165
|
-
if (this.uploadSet) {
|
|
1166
|
-
this.uploadSet.add(ulh);
|
|
1167
|
-
}
|
|
1168
|
-
ww.writeAsync(audioBuffer, (wavFile) => {
|
|
1169
|
-
this.postRecording(wavFile, recUrl, null, ulh);
|
|
1170
|
-
this.processingRecording = false;
|
|
1171
|
-
});
|
|
1172
|
-
}
|
|
1173
|
-
// postRecording(wavFile: Uint8Array, recUrl: string,rf:RecordingFile|null) {
|
|
1174
|
-
// let wavBlob = new Blob([wavFile], {type: 'audio/wav'});
|
|
1175
|
-
// let ul = new Upload(wavBlob, recUrl,rf);
|
|
1176
|
-
// this.uploader.queueUpload(ul);
|
|
1177
|
-
// }
|
|
1178
|
-
stop() {
|
|
1179
|
-
if (this.ac != null) {
|
|
1180
|
-
this.ac.close();
|
|
1181
|
-
}
|
|
1182
|
-
}
|
|
1183
|
-
updateControlPlaybackPosition() {
|
|
1184
|
-
if (this._controlAudioPlayer) {
|
|
1185
|
-
const ppFrames = this._controlAudioPlayer.playPositionFrames;
|
|
1186
|
-
if (ppFrames !== null) {
|
|
1187
|
-
if (this.prompting.audioDisplay) {
|
|
1188
|
-
this.prompting.audioDisplay.playFramePosition = ppFrames;
|
|
1189
|
-
}
|
|
1190
|
-
this.liveLevelDisplay.playFramePosition = ppFrames;
|
|
1191
|
-
}
|
|
1192
|
-
}
|
|
1193
|
-
}
|
|
1194
|
-
audioPlayerUpdate(e) {
|
|
1195
|
-
if (EventType.READY === e.type) {
|
|
1196
|
-
}
|
|
1197
|
-
else if (EventType.STARTED === e.type) {
|
|
1198
|
-
//this.status = 'Playback...';
|
|
1199
|
-
this.updateTimerId = window.setInterval(() => this.updateControlPlaybackPosition(), 50);
|
|
1200
|
-
}
|
|
1201
|
-
else if (EventType.ENDED === e.type) {
|
|
1202
|
-
//.status='Ready.';
|
|
1203
|
-
window.clearInterval(this.updateTimerId);
|
|
1204
|
-
}
|
|
1205
|
-
if (!this.destroyed) {
|
|
1206
|
-
this.changeDetectorRef.detectChanges();
|
|
1207
|
-
}
|
|
1208
|
-
}
|
|
1209
|
-
}
|
|
1210
|
-
SessionManager.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: SessionManager, deps: [{ token: i1.BreakpointObserver }, { token: i0.ChangeDetectorRef }, { token: i0.Renderer2 }, { token: i2.MatDialog }, { token: i3.SessionService }, { token: i4.RecordingService }, { token: i5.SpeechRecorderUploader }, { token: SPEECHRECORDER_CONFIG }], target: i0.ɵɵFactoryTarget.Component });
|
|
1211
|
-
SessionManager.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: SessionManager, selector: "app-sprrecordingsession", inputs: { projectName: "projectName", dataSaved: "dataSaved" }, host: { listeners: { "window:keypress": "onKeyPress($event)", "window:keydown": "onKeyDown($event)" } }, providers: [SessionService], viewQueries: [{ propertyName: "prompting", first: true, predicate: Prompting, descendants: true, static: true }, { propertyName: "liveLevelDisplay", first: true, predicate: LevelBar, descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: `
|
|
1212
|
-
<app-warningbar [show]="isTestSession()" warningText="Test recording only!"></app-warningbar>
|
|
1213
|
-
<app-warningbar [show]="isDefaultAudioTestSession()" warningText="This test uses default audio device! Regular sessions may require a particular audio device (microphone)!"></app-warningbar>
|
|
1214
|
-
<app-sprprompting [projectName]="projectName"
|
|
1215
|
-
[startStopSignalState]="startStopSignalState" [promptItem]="promptItem" [showPrompt]="showPrompt"
|
|
1216
|
-
[items]="items?.items"
|
|
1217
|
-
[transportActions]="transportActions"
|
|
1218
|
-
[selectedItemIdx]="promptIndex" (onItemSelect)="itemSelect($event)" (onNextItem)="nextItem()" (onPrevItem)="prevItem()"
|
|
1219
|
-
[audioSignalCollapsed]="audioSignalCollapsed" [displayAudioClip]="displayAudioClip"
|
|
1220
|
-
[playStartAction]="controlAudioPlayer?.startAction"
|
|
1221
|
-
[playSelectionAction]="controlAudioPlayer?.startSelectionAction"
|
|
1222
|
-
[autoPlayOnSelectToggleAction]="controlAudioPlayer?.autoPlayOnSelectToggleAction"
|
|
1223
|
-
[playStopAction]="controlAudioPlayer?.stopAction">
|
|
1224
|
-
|
|
1225
|
-
</app-sprprompting>
|
|
1226
|
-
<mat-progress-bar [value]="progressPercentValue()" *ngIf="screenXs" ></mat-progress-bar>
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
<div [class]="{audioStatusDisplay:!screenXs,audioStatusDisplayXs:screenXs}">
|
|
1230
|
-
<audio-levelbar style="flex:1 0 1%" [streamingMode]="isRecording() || keepLiveLevel" [displayLevelInfos]="displayAudioClip?.levelInfos" [state]="liveLevelDisplayState"></audio-levelbar>
|
|
1231
|
-
<div style="display:flex;flex-direction: row">
|
|
1232
|
-
<spr-recordingitemcontrols style="display:flex;flex:10 0 1px"
|
|
1233
|
-
[audioLoaded]="audioLoaded"
|
|
1234
|
-
[disableAudioDetails]="disableAudioDetails"
|
|
1235
|
-
[playStartAction]="controlAudioPlayer?.startAction"
|
|
1236
|
-
[playStopAction]="controlAudioPlayer?.stopAction"
|
|
1237
|
-
[peakDbLvl]="peakLevelInDb"
|
|
1238
|
-
[agc]="this.ac?.agcStatus"
|
|
1239
|
-
(onShowRecordingDetails)="audioSignalCollapsed=!audioSignalCollapsed">
|
|
1240
|
-
</spr-recordingitemcontrols>
|
|
1241
|
-
|
|
1242
|
-
<app-uploadstatus *ngIf="screenXs && enableUploadRecordings" class="ricontrols dark" style="flex:0 0 0" [value]="uploadProgress"
|
|
1243
|
-
[status]="uploadStatus" [awaitNewUpload]="processingRecording"></app-uploadstatus>
|
|
1244
|
-
<app-wakelockindicator *ngIf="screenXs" class="ricontrols dark" style="flex:0 0 0" [screenLocked]="screenLocked"></app-wakelockindicator>
|
|
1245
|
-
<app-readystateindicator *ngIf="screenXs" class="ricontrols dark" style="flex:0 0 0" [ready]="dataSaved && !isActive()"></app-readystateindicator>
|
|
1246
|
-
</div>
|
|
1247
|
-
</div>
|
|
1248
|
-
<div #controlpanel class="controlpanel">
|
|
1249
|
-
<div style="flex:1 1 30%;justify-content: flex-start;align-items: center; align-content: center">
|
|
1250
|
-
<app-sprstatusdisplay *ngIf="!screenXs" [statusMsg]="statusMsg" [statusAlertType]="statusAlertType" [statusWaiting]="statusWaiting"></app-sprstatusdisplay>
|
|
1251
|
-
</div>
|
|
1252
|
-
<app-sprtransport style="display:flex;flex:10 0 30%;justify-content: center;align-items: center; align-content: center" [readonly]="readonly" [actions]="transportActions" [navigationEnabled]="!items || items.length()>1"></app-sprtransport>
|
|
1253
|
-
<div style="display:flex;flex:1 1 30%;flex-direction:row;justify-content: flex-end;align-items: center; align-content: center">
|
|
1254
|
-
<app-uploadstatus *ngIf="!screenXs && enableUploadRecordings" class="ricontrols" [value]="uploadProgress"
|
|
1255
|
-
[status]="uploadStatus" [awaitNewUpload]="processingRecording"></app-uploadstatus>
|
|
1256
|
-
<app-wakelockindicator *ngIf="!screenXs" class="ricontrols" [screenLocked]="screenLocked"></app-wakelockindicator>
|
|
1257
|
-
<app-readystateindicator *ngIf="!screenXs" class="ricontrols" [ready]="dataSaved && !isActive()"></app-readystateindicator>
|
|
1258
|
-
</div>
|
|
1259
|
-
</div>
|
|
1260
|
-
`, isInline: true, styles: [":host{flex:2;background:lightgrey;display:flex;flex-direction:column;margin:0;padding:0;min-height:0px;overflow:hidden}\n", ".ricontrols{display:flex;padding:4px;box-sizing:border-box;height:100%;flex-direction:row;justify-content:flex-end;align-items:center;align-content:center}\n", ".dark{background:darkgray}\n", ".controlpanel{display:flex;flex-direction:row;align-content:center;align-items:center;margin:0;padding:20px;min-height:min-content}\n", ".audioStatusDisplay{display:flex;flex-direction:row;height:100px;min-height:100px}\n", ".audioStatusDisplayXs{display:flex;flex-direction:column;height:125px;min-height:125px}\n"], dependencies: [{ kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i7.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: i8.LevelBar, selector: "audio-levelbar", inputs: ["streamingMode", "displayLevelInfos", "state"] }, { kind: "component", type: i9.Prompting, selector: "app-sprprompting", inputs: ["projectName", "startStopSignalState", "promptItem", "showPrompt", "items", "selectedItemIdx", "transportActions", "enableDownload", "audioSignalCollapsed", "displayAudioClip", "playStartAction", "playSelectionAction", "autoPlayOnSelectToggleAction", "playStopAction"], outputs: ["onItemSelect", "onNextItem", "onPrevItem"] }, { kind: "component", type: i10.StatusDisplay, selector: "app-sprstatusdisplay", inputs: ["statusAlertType", "statusMsg", "statusWaiting"] }, { kind: "component", type: i11.RecordingItemControls, selector: "spr-recordingitemcontrols", inputs: ["audioSignalCollapsed", "enableDownload", "peakDbLvl", "agc", "disableAudioDetails", "audioLoaded", "playStartAction", "playStopAction", "displayLevelInfos"], outputs: ["onShowRecordingDetails", "onDownloadRecording"] }, { kind: "component", type: i10.UploadStatus, selector: "app-uploadstatus", inputs: ["value", "awaitNewUpload", "status"] }, { kind: "component", type: i10.TransportPanel, selector: "app-sprtransport", inputs: ["readonly", "actions", "navigationEnabled", "pausingEnabled"] }, { kind: "component", type: i10.WakeLockIndicator, selector: "app-wakelockindicator", inputs: ["screenLocked"] }, { kind: "component", type: i10.ReadyStateIndicator, selector: "app-readystateindicator", inputs: ["ready"] }, { kind: "component", type: i12.WarningBar, selector: "app-warningbar", inputs: ["warningText", "show"] }] });
|
|
1261
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: SessionManager, decorators: [{
|
|
1262
|
-
type: Component,
|
|
1263
|
-
args: [{ selector: 'app-sprrecordingsession', providers: [SessionService], template: `
|
|
1264
|
-
<app-warningbar [show]="isTestSession()" warningText="Test recording only!"></app-warningbar>
|
|
1265
|
-
<app-warningbar [show]="isDefaultAudioTestSession()" warningText="This test uses default audio device! Regular sessions may require a particular audio device (microphone)!"></app-warningbar>
|
|
1266
|
-
<app-sprprompting [projectName]="projectName"
|
|
1267
|
-
[startStopSignalState]="startStopSignalState" [promptItem]="promptItem" [showPrompt]="showPrompt"
|
|
1268
|
-
[items]="items?.items"
|
|
1269
|
-
[transportActions]="transportActions"
|
|
1270
|
-
[selectedItemIdx]="promptIndex" (onItemSelect)="itemSelect($event)" (onNextItem)="nextItem()" (onPrevItem)="prevItem()"
|
|
1271
|
-
[audioSignalCollapsed]="audioSignalCollapsed" [displayAudioClip]="displayAudioClip"
|
|
1272
|
-
[playStartAction]="controlAudioPlayer?.startAction"
|
|
1273
|
-
[playSelectionAction]="controlAudioPlayer?.startSelectionAction"
|
|
1274
|
-
[autoPlayOnSelectToggleAction]="controlAudioPlayer?.autoPlayOnSelectToggleAction"
|
|
1275
|
-
[playStopAction]="controlAudioPlayer?.stopAction">
|
|
1276
|
-
|
|
1277
|
-
</app-sprprompting>
|
|
1278
|
-
<mat-progress-bar [value]="progressPercentValue()" *ngIf="screenXs" ></mat-progress-bar>
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
<div [class]="{audioStatusDisplay:!screenXs,audioStatusDisplayXs:screenXs}">
|
|
1282
|
-
<audio-levelbar style="flex:1 0 1%" [streamingMode]="isRecording() || keepLiveLevel" [displayLevelInfos]="displayAudioClip?.levelInfos" [state]="liveLevelDisplayState"></audio-levelbar>
|
|
1283
|
-
<div style="display:flex;flex-direction: row">
|
|
1284
|
-
<spr-recordingitemcontrols style="display:flex;flex:10 0 1px"
|
|
1285
|
-
[audioLoaded]="audioLoaded"
|
|
1286
|
-
[disableAudioDetails]="disableAudioDetails"
|
|
1287
|
-
[playStartAction]="controlAudioPlayer?.startAction"
|
|
1288
|
-
[playStopAction]="controlAudioPlayer?.stopAction"
|
|
1289
|
-
[peakDbLvl]="peakLevelInDb"
|
|
1290
|
-
[agc]="this.ac?.agcStatus"
|
|
1291
|
-
(onShowRecordingDetails)="audioSignalCollapsed=!audioSignalCollapsed">
|
|
1292
|
-
</spr-recordingitemcontrols>
|
|
1293
|
-
|
|
1294
|
-
<app-uploadstatus *ngIf="screenXs && enableUploadRecordings" class="ricontrols dark" style="flex:0 0 0" [value]="uploadProgress"
|
|
1295
|
-
[status]="uploadStatus" [awaitNewUpload]="processingRecording"></app-uploadstatus>
|
|
1296
|
-
<app-wakelockindicator *ngIf="screenXs" class="ricontrols dark" style="flex:0 0 0" [screenLocked]="screenLocked"></app-wakelockindicator>
|
|
1297
|
-
<app-readystateindicator *ngIf="screenXs" class="ricontrols dark" style="flex:0 0 0" [ready]="dataSaved && !isActive()"></app-readystateindicator>
|
|
1298
|
-
</div>
|
|
1299
|
-
</div>
|
|
1300
|
-
<div #controlpanel class="controlpanel">
|
|
1301
|
-
<div style="flex:1 1 30%;justify-content: flex-start;align-items: center; align-content: center">
|
|
1302
|
-
<app-sprstatusdisplay *ngIf="!screenXs" [statusMsg]="statusMsg" [statusAlertType]="statusAlertType" [statusWaiting]="statusWaiting"></app-sprstatusdisplay>
|
|
1303
|
-
</div>
|
|
1304
|
-
<app-sprtransport style="display:flex;flex:10 0 30%;justify-content: center;align-items: center; align-content: center" [readonly]="readonly" [actions]="transportActions" [navigationEnabled]="!items || items.length()>1"></app-sprtransport>
|
|
1305
|
-
<div style="display:flex;flex:1 1 30%;flex-direction:row;justify-content: flex-end;align-items: center; align-content: center">
|
|
1306
|
-
<app-uploadstatus *ngIf="!screenXs && enableUploadRecordings" class="ricontrols" [value]="uploadProgress"
|
|
1307
|
-
[status]="uploadStatus" [awaitNewUpload]="processingRecording"></app-uploadstatus>
|
|
1308
|
-
<app-wakelockindicator *ngIf="!screenXs" class="ricontrols" [screenLocked]="screenLocked"></app-wakelockindicator>
|
|
1309
|
-
<app-readystateindicator *ngIf="!screenXs" class="ricontrols" [ready]="dataSaved && !isActive()"></app-readystateindicator>
|
|
1310
|
-
</div>
|
|
1311
|
-
</div>
|
|
1312
|
-
`, styles: [":host{flex:2;background:lightgrey;display:flex;flex-direction:column;margin:0;padding:0;min-height:0px;overflow:hidden}\n", ".ricontrols{display:flex;padding:4px;box-sizing:border-box;height:100%;flex-direction:row;justify-content:flex-end;align-items:center;align-content:center}\n", ".dark{background:darkgray}\n", ".controlpanel{display:flex;flex-direction:row;align-content:center;align-items:center;margin:0;padding:20px;min-height:min-content}\n", ".audioStatusDisplay{display:flex;flex-direction:row;height:100px;min-height:100px}\n", ".audioStatusDisplayXs{display:flex;flex-direction:column;height:125px;min-height:125px}\n"] }]
|
|
1313
|
-
}], ctorParameters: function () { return [{ type: i1.BreakpointObserver }, { type: i0.ChangeDetectorRef }, { type: i0.Renderer2 }, { type: i2.MatDialog }, { type: i3.SessionService }, { type: i4.RecordingService }, { type: i5.SpeechRecorderUploader }, { type: i13.SpeechRecorderConfig, decorators: [{
|
|
1314
|
-
type: Inject,
|
|
1315
|
-
args: [SPEECHRECORDER_CONFIG]
|
|
1316
|
-
}] }]; }, propDecorators: { projectName: [{
|
|
1317
|
-
type: Input
|
|
1318
|
-
}], prompting: [{
|
|
1319
|
-
type: ViewChild,
|
|
1320
|
-
args: [Prompting, { static: true }]
|
|
1321
|
-
}], liveLevelDisplay: [{
|
|
1322
|
-
type: ViewChild,
|
|
1323
|
-
args: [LevelBar, { static: true }]
|
|
1324
|
-
}], dataSaved: [{
|
|
1325
|
-
type: Input
|
|
1326
|
-
}], onKeyPress: [{
|
|
1327
|
-
type: HostListener,
|
|
1328
|
-
args: ['window:keypress', ['$event']]
|
|
1329
|
-
}], onKeyDown: [{
|
|
1330
|
-
type: HostListener,
|
|
1331
|
-
args: ['window:keydown', ['$event']]
|
|
1332
|
-
}] } });
|
|
1333
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2Vzc2lvbm1hbmFnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9zcGVlY2hyZWNvcmRlcm5nL3NyYy9saWIvc3BlZWNocmVjb3JkZXIvc2Vzc2lvbi9zZXNzaW9ubWFuYWdlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUMsWUFBWSxFQUF1QixNQUFNLDZCQUE2QixDQUFDO0FBQy9FLE9BQU8sRUFBZ0MsU0FBUyxFQUFDLE1BQU0sNkJBQTZCLENBQUE7QUFDcEYsT0FBTyxFQUFDLFNBQVMsRUFBQyxNQUFNLDRCQUE0QixDQUFBO0FBQ3BELE9BQU8sRUFBb0IsY0FBYyxFQUFrQixNQUFNLGtCQUFrQixDQUFDO0FBQ3BGLE9BQU8sRUFBQyxnQkFBZ0IsRUFBOEIsTUFBTSxjQUFjLENBQUE7QUFDMUUsT0FBTyxFQUFDLFlBQVksRUFBQyxNQUFNLG9CQUFvQixDQUFDO0FBQ2hELE9BQU8sRUFHTCxTQUFTLEVBQ1QsWUFBWSxFQUNaLE1BQU0sRUFDTixLQUFLLEVBR0wsU0FBUyxFQUNWLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBQyxjQUFjLEVBQUMsTUFBTSxtQkFBbUIsQ0FBQztBQUlqRCxPQUFPLEVBQUMscUJBQXFCLEVBQXVCLE1BQU0sa0JBQWtCLENBQUM7QUFDN0UsT0FBTyxFQUFDLFNBQVMsRUFBQyxNQUFNLGFBQWEsQ0FBQztBQUN0QyxPQUFPLEVBQUMscUJBQXFCLEVBQUMsTUFBTSwyQkFBMkIsQ0FBQztBQUNoRSxPQUFPLEVBQUMsYUFBYSxFQUFDLE1BQU0seUJBQXlCLENBQUM7QUFDdEQsT0FBTyxFQUFDLGdCQUFnQixFQUFDLE1BQU0sa0NBQWtDLENBQUM7QUFFbEUsT0FBTyxFQUFDLFNBQVMsRUFBQyxNQUFNLHVCQUF1QixDQUFDO0FBQ2hELE9BQU8sRUFBQyxJQUFJLEVBQUMsTUFBTSxRQUFRLENBQUM7QUFDNUIsT0FBTyxFQUFDLFFBQVEsRUFB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Q0FBQyxjQUFjLENBQUMsWUFDakI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FpRFQ7OzBCQTZHWSxNQUFNOzJCQUFDLHFCQUFxQjs0Q0FwRGhDLFdBQVc7c0JBQW5CLEtBQUs7Z0JBS2tDLFNBQVM7c0JBQWhELFNBQVM7dUJBQUMsU0FBUyxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRTtnQkFDQyxnQkFBZ0I7c0JBQXRELFNBQVM7dUJBQUMsUUFBUSxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRTtnQkFFNUIsU0FBUztzQkFBakIsS0FBSztnQkFrS04sVUFBVTtzQkFEVCxZQUFZO3VCQUFDLGlCQUFpQixFQUFFLENBQUMsUUFBUSxDQUFDO2dCQVMzQyxTQUFTO3NCQURSLFlBQVk7dUJBQUMsZ0JBQWdCLEVBQUUsQ0FBQyxRQUFRLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0F1ZGlvQ2FwdHVyZSwgQXVkaW9DYXB0dXJlTGlzdGVuZXJ9IGZyb20gJy4uLy4uL2F1ZGlvL2NhcHR1cmUvY2FwdHVyZSc7XHJcbmltcG9ydCB7QXVkaW9QbGF5ZXIsIEF1ZGlvUGxheWVyRXZlbnQsIEV2ZW50VHlwZX0gZnJvbSAnLi4vLi4vYXVkaW8vcGxheWJhY2svcGxheWVyJ1xyXG5pbXBvcnQge1dhdldyaXRlcn0gZnJvbSAnLi4vLi4vYXVkaW8vaW1wbC93YXZ3cml0ZXInXHJcbmltcG9ydCB7R3JvdXAsIFByb21wdEl0ZW0sIFByb21wdGl0ZW1VdGlsLCBTY3JpcHQsIFNlY3Rpb259IGZyb20gJy4uL3NjcmlwdC9zY3JpcHQnO1xyXG5pbXBvcnQge1NwclJlY29yZGluZ0ZpbGUsIFJlY29yZGluZ0ZpbGVEZXNjcmlwdG9ySW1wbH0gZnJvbSAnLi4vcmVjb3JkaW5nJ1xyXG5pbXBvcnQge1VwbG9hZEhvbGRlcn0gZnJvbSAnLi4vLi4vbmV0L3VwbG9hZGVyJztcclxuaW1wb3J0IHtcclxuICBBZnRlclZpZXdJbml0LFxyXG4gIENoYW5nZURldGVjdG9yUmVmLFxyXG4gIENvbXBvbmVudCxcclxuICBIb3N0TGlzdGVuZXIsXHJcbiAgSW5qZWN0LFxyXG4gIElucHV0LFxyXG4gIE9uRGVzdHJveSxcclxuICBSZW5kZXJlcjIsXHJcbiAgVmlld0NoaWxkXHJcbn0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcclxuaW1wb3J0IHtTZXNzaW9uU2VydmljZX0gZnJvbSBcIi4vc2Vzc2lvbi5zZXJ2aWNlXCI7XHJcbmltcG9ydCB7U3RhdGUgYXMgU3RhcnRTdG9wU2lnbmFsU3RhdGV9IGZyb20gXCIuLi9zdGFydHN0b3BzaWduYWwvc3RhcnRzdG9wc2lnbmFsXCI7XHJcbmltcG9ydCB7TWF0RGlhbG9nfSBmcm9tIFwiQGFuZ3VsYXIvbWF0ZXJpYWwvZGlhbG9nXCI7XHJcbmltcG9ydCB7U3BlZWNoUmVjb3JkZXJVcGxvYWRlcn0gZnJvbSBcIi4uL3NwcnVwbG9hZGVyXCI7XHJcbmltcG9ydCB7U1BFRUNIUkVDT1JERVJfQ09ORklHLCBTcGVlY2hSZWNvcmRlckNvbmZpZ30gZnJvbSBcIi4uLy4uL3Nwci5jb25maWdcIjtcclxuaW1wb3J0IHtQcm9tcHRpbmd9IGZyb20gXCIuL3Byb21wdGluZ1wiO1xyXG5pbXBvcnQge1Nlc3Npb25GaW5pc2hlZERpYWxvZ30gZnJvbSBcIi4vc2Vzc2lvbl9maW5pc2hlZF9kaWFsb2dcIjtcclxuaW1wb3J0IHtNZXNzYWdlRGlhbG9nfSBmcm9tIFwiLi4vLi4vdWkvbWVzc2FnZV9kaWFsb2dcIjtcclxuaW1wb3J0IHtSZWNvcmRpbmdTZXJ2aWNlfSBmcm9tIFwiLi4vcmVjb3JkaW5ncy9yZWNvcmRpbmdzLnNlcnZpY2VcIjtcclxuaW1wb3J0IHtBdWRpb0NvbnRleHRQcm92aWRlcn0gZnJvbSBcIi4uLy4uL2F1ZGlvL2NvbnRleHRcIjtcclxuaW1wb3J0IHtBdWRpb0NsaXB9IGZyb20gXCIuLi8uLi9hdWRpby9wZXJzaXN0b3JcIjtcclxuaW1wb3J0IHtJdGVtfSBmcm9tIFwiLi9pdGVtXCI7XHJcbmltcG9ydCB7TGV2ZWxCYXJ9IGZyb20gXCIuLi8uLi9hdWRpby91aS9saXZlbGV2ZWxcIjtcclxuaW1wb3J0IHtcclxuICBCYXNpY1JlY29yZGVyLFxyXG4gIENodW5rQXVkaW9CdWZmZXJSZWNlaXZlcixcclxuICBNQVhfUkVDT1JESU5HX1RJTUVfTVMsXHJcbiAgUkVDRklMRV9BUElfQ1RYXHJcbn0gZnJvbSBcIi4vYmFzaWNyZWNvcmRlclwiO1xyXG5pbXBvcnQge0FycmF5QXVkaW9CdWZmZXJ9IGZyb20gXCIuLi8uLi9hdWRpby9hcnJheV9hdWRpb19idWZmZXJcIjtcclxuaW1wb3J0IHtBdWRpb0J1ZmZlclNvdXJjZSwgQXVkaW9EYXRhSG9sZGVyLCBBdWRpb1NvdXJjZX0gZnJvbSBcIi4uLy4uL2F1ZGlvL2F1ZGlvX2RhdGFfaG9sZGVyXCI7XHJcbmltcG9ydCB7U3BySXRlbXNDYWNoZX0gZnJvbSBcIi4vcmVjb3JkaW5nX2ZpbGVfY2FjaGVcIjtcclxuaW1wb3J0IHtTdGF0ZSBhcyBMaXZlTGV2ZWxTdGF0ZX0gZnJvbSBcIi4uLy4uL2F1ZGlvL3VpL2xpdmVsZXZlbFwiXHJcbmltcG9ydCB7SW5kZXhlZERiQXVkaW9CdWZmZXIsIFBlcnNpc3RlbnRBdWRpb1N0b3JhZ2VUYXJnZXR9IGZyb20gXCIuLi8uLi9hdWRpby9pbmRkYl9hdWRpb19idWZmZXJcIjtcclxuaW1wb3J0IHtBdWRpb1N0b3JhZ2VUeXBlfSBmcm9tIFwiLi4vcHJvamVjdC9wcm9qZWN0XCI7XHJcbmltcG9ydCB7TmV0QXVkaW9CdWZmZXJ9IGZyb20gXCIuLi8uLi9hdWRpby9uZXRfYXVkaW9fYnVmZmVyXCI7XHJcbmltcG9ydCB7QnJlYWtwb2ludE9ic2VydmVyfSBmcm9tIFwiQGFuZ3VsYXIvY2RrL2xheW91dFwiO1xyXG5cclxuY29uc3QgREVGQVVMVF9QUkVfUkVDX0RFTEFZPTEwMDA7XHJcbmNvbnN0IERFRkFVTFRfUE9TVF9SRUNfREVMQVk9NTAwO1xyXG5cclxuZXhwb3J0IGNvbnN0IGVudW0gU3RhdHVzIHtcclxuICBCTE9DS0VELCBJRExFLCBTVEFSVElORywgUFJFX1JFQ09SRElORywgUkVDT1JESU5HLCBQT1NUX1JFQ19TVE9QLCBQT1NUX1JFQ19QQVVTRSwgU1RPUFBJTkdfU1RPUCwgU1RPUFBJTkdfUEFVU0UsIEVSUk9SXHJcbn1cclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnYXBwLXNwcnJlY29yZGluZ3Nlc3Npb24nLFxyXG4gIHByb3ZpZGVyczogW1Nlc3Npb25TZXJ2aWNlXSxcclxuICB0ZW1wbGF0ZTogYFxyXG4gICAgPGFwcC13YXJuaW5nYmFyIFtzaG93XT1cImlzVGVzdFNlc3Npb24oKVwiIHdhcm5pbmdUZXh0PVwiVGVzdCByZWNvcmRpbmcgb25seSFcIj48L2FwcC13YXJuaW5nYmFyPlxyXG4gICAgPGFwcC13YXJuaW5nYmFyIFtzaG93XT1cImlzRGVmYXVsdEF1ZGlvVGVzdFNlc3Npb24oKVwiIHdhcm5pbmdUZXh0PVwiVGhpcyB0ZXN0IHVzZXMgZGVmYXVsdCBhdWRpbyBkZXZpY2UhIFJlZ3VsYXIgc2Vzc2lvbnMgbWF5IHJlcXVpcmUgYSBwYXJ0aWN1bGFyIGF1ZGlvIGRldmljZSAobWljcm9waG9uZSkhXCI+PC9hcHAtd2FybmluZ2Jhcj5cclxuICAgICAgPGFwcC1zcHJwcm9tcHRpbmcgW3Byb2plY3ROYW1lXT1cInByb2plY3ROYW1lXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgW3N0YXJ0U3RvcFNpZ25hbFN0YXRlXT1cInN0YXJ0U3RvcFNpZ25hbFN0YXRlXCIgW3Byb21wdEl0ZW1dPVwicHJvbXB0SXRlbVwiIFtzaG93UHJvbXB0XT1cInNob3dQcm9tcHRcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBbaXRlbXNdPVwiaXRlbXM/Lml0ZW1zXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgW3RyYW5zcG9ydEFjdGlvbnNdPVwidHJhbnNwb3J0QWN0aW9uc1wiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtzZWxlY3RlZEl0ZW1JZHhdPVwicHJvbXB0SW5kZXhcIiAob25JdGVtU2VsZWN0KT1cIml0ZW1TZWxlY3QoJGV2ZW50KVwiIChvbk5leHRJdGVtKT1cIm5leHRJdGVtKClcIiAob25QcmV2SXRlbSk9XCJwcmV2SXRlbSgpXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgW2F1ZGlvU2lnbmFsQ29sbGFwc2VkXT1cImF1ZGlvU2lnbmFsQ29sbGFwc2VkXCIgW2Rpc3BsYXlBdWRpb0NsaXBdPVwiZGlzcGxheUF1ZGlvQ2xpcFwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtwbGF5U3RhcnRBY3Rpb25dPVwiY29udHJvbEF1ZGlvUGxheWVyPy5zdGFydEFjdGlvblwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtwbGF5U2VsZWN0aW9uQWN0aW9uXT1cImNvbnRyb2xBdWRpb1BsYXllcj8uc3RhcnRTZWxlY3Rpb25BY3Rpb25cIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBbYXV0b1BsYXlPblNlbGVjdFRvZ2dsZUFjdGlvbl09XCJjb250cm9sQXVkaW9QbGF5ZXI/LmF1dG9QbGF5T25TZWxlY3RUb2dnbGVBY3Rpb25cIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBbcGxheVN0b3BBY3Rpb25dPVwiY29udHJvbEF1ZGlvUGxheWVyPy5zdG9wQWN0aW9uXCI+XHJcblxyXG4gICAgPC9hcHAtc3BycHJvbXB0aW5nPlxyXG4gICAgPG1hdC1wcm9ncmVzcy1iYXIgW3ZhbHVlXT1cInByb2dyZXNzUGVyY2VudFZhbHVlKClcIiAqbmdJZj1cInNjcmVlblhzXCIgPjwvbWF0LXByb2dyZXNzLWJhcj5cclxuXHJcblxyXG4gICAgPGRpdiBbY2xhc3NdPVwie2F1ZGlvU3RhdHVzRGlzcGxheTohc2NyZWVuWHMsYXVkaW9TdGF0dXNEaXNwbGF5WHM6c2NyZWVuWHN9XCI+XHJcbiAgICAgIDxhdWRpby1sZXZlbGJhciBzdHlsZT1cImZsZXg6MSAwIDElXCIgW3N0cmVhbWluZ01vZGVdPVwiaXNSZWNvcmRpbmcoKSB8fCBrZWVwTGl2ZUxldmVsXCIgW2Rpc3BsYXlMZXZlbEluZm9zXT1cImRpc3BsYXlBdWRpb0NsaXA/LmxldmVsSW5mb3NcIiAgW3N0YXRlXT1cImxpdmVMZXZlbERpc3BsYXlTdGF0ZVwiPjwvYXVkaW8tbGV2ZWxiYXI+XHJcbiAgICAgIDxkaXYgc3R5bGU9XCJkaXNwbGF5OmZsZXg7ZmxleC1kaXJlY3Rpb246IHJvd1wiPlxyXG4gICAgICAgIDxzcHItcmVjb3JkaW5naXRlbWNvbnRyb2xzIHN0eWxlPVwiZGlzcGxheTpmbGV4O2ZsZXg6MTAgMCAxcHhcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFthdWRpb0xvYWRlZF09XCJhdWRpb0xvYWRlZFwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2Rpc2FibGVBdWRpb0RldGFpbHNdPVwiZGlzYWJsZUF1ZGlvRGV0YWlsc1wiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3BsYXlTdGFydEFjdGlvbl09XCJjb250cm9sQXVkaW9QbGF5ZXI/LnN0YXJ0QWN0aW9uXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbcGxheVN0b3BBY3Rpb25dPVwiY29udHJvbEF1ZGlvUGxheWVyPy5zdG9wQWN0aW9uXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbcGVha0RiTHZsXT1cInBlYWtMZXZlbEluRGJcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFthZ2NdPVwidGhpcy5hYz8uYWdjU3RhdHVzXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAob25TaG93UmVjb3JkaW5nRGV0YWlscyk9XCJhdWRpb1NpZ25hbENvbGxhcHNlZD0hYXVkaW9TaWduYWxDb2xsYXBzZWRcIj5cclxuICAgICAgICA8L3Nwci1yZWNvcmRpbmdpdGVtY29udHJvbHM+XHJcblxyXG4gICAgICAgIDxhcHAtdXBsb2Fkc3RhdHVzICpuZ0lmPVwic2NyZWVuWHMgJiYgZW5hYmxlVXBsb2FkUmVjb3JkaW5nc1wiIGNsYXNzPVwicmljb250cm9scyBkYXJrXCIgIHN0eWxlPVwiZmxleDowIDAgMFwiIFt2YWx1ZV09XCJ1cGxvYWRQcm9ncmVzc1wiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgW3N0YXR1c109XCJ1cGxvYWRTdGF0dXNcIiBbYXdhaXROZXdVcGxvYWRdPVwicHJvY2Vzc2luZ1JlY29yZGluZ1wiPjwvYXBwLXVwbG9hZHN0YXR1cz5cclxuICAgICAgICA8YXBwLXdha2Vsb2NraW5kaWNhdG9yICpuZ0lmPVwic2NyZWVuWHNcIiBjbGFzcz1cInJpY29udHJvbHMgZGFya1wiIHN0eWxlPVwiZmxleDowIDAgMFwiIFtzY3JlZW5Mb2NrZWRdPVwic2NyZWVuTG9ja2VkXCI+PC9hcHAtd2FrZWxvY2tpbmRpY2F0b3I+XHJcbiAgICAgICAgPGFwcC1yZWFkeXN0YXRlaW5kaWNhdG9yICpuZ0lmPVwic2NyZWVuWHNcIiBjbGFzcz1cInJpY29udHJvbHMgZGFya1wiIHN0eWxlPVwiZmxleDowIDAgMFwiIFtyZWFkeV09XCJkYXRhU2F2ZWQgJiYgIWlzQWN0aXZlKClcIj48L2FwcC1yZWFkeXN0YXRlaW5kaWNhdG9yPlxyXG4gICAgICA8L2Rpdj5cclxuICAgIDwvZGl2PlxyXG4gICAgPGRpdiAjY29udHJvbHBhbmVsIGNsYXNzPVwiY29udHJvbHBhbmVsXCI+XHJcbiAgICAgIDxkaXYgc3R5bGU9XCJmbGV4OjEgMSAzMCU7anVzdGlmeS1jb250ZW50OiBmbGV4LXN0YXJ0O2FsaWduLWl0ZW1zOiBjZW50ZXI7IGFsaWduLWNvbnRlbnQ6IGNlbnRlclwiPlxyXG4gICAgICAgIDxhcHAtc3Byc3RhdHVzZGlzcGxheSAqbmdJZj1cIiFzY3JlZW5Yc1wiIFtzdGF0dXNNc2ddPVwic3RhdHVzTXNnXCIgW3N0YXR1c0FsZXJ0VHlwZV09XCJzdGF0dXNBbGVydFR5cGVcIiBbc3RhdHVzV2FpdGluZ109XCJzdGF0dXNXYWl0aW5nXCI+PC9hcHAtc3Byc3RhdHVzZGlzcGxheT5cclxuICAgICAgPC9kaXY+XHJcbiAgICAgIDxhcHAtc3BydHJhbnNwb3J0IHN0eWxlPVwiZGlzcGxheTpmbGV4O2ZsZXg6MTAgMCAzMCU7anVzdGlmeS1jb250ZW50OiBjZW50ZXI7YWxpZ24taXRlbXM6IGNlbnRlcjsgYWxpZ24tY29udGVudDogY2VudGVyXCIgW3JlYWRvbmx5XT1cInJlYWRvbmx5XCIgW2FjdGlvbnNdPVwidHJhbnNwb3J0QWN0aW9uc1wiIFtuYXZpZ2F0aW9uRW5hYmxlZF09XCIhaXRlbXMgfHwgaXRlbXMubGVuZ3RoKCk+MVwiPjwvYXBwLXNwcnRyYW5zcG9ydD5cclxuICAgICAgPGRpdiBzdHlsZT1cImRpc3BsYXk6ZmxleDtmbGV4OjEgMSAzMCU7ZmxleC1kaXJlY3Rpb246cm93O2p1c3RpZnktY29udGVudDogZmxleC1lbmQ7YWxpZ24taXRlbXM6IGNlbnRlcjsgYWxpZ24tY29udGVudDogY2VudGVyXCI+XHJcbiAgICAgICAgPGFwcC11cGxvYWRzdGF0dXMgKm5nSWY9XCIhc2NyZWVuWHMgJiYgZW5hYmxlVXBsb2FkUmVjb3JkaW5nc1wiICBjbGFzcz1cInJpY29udHJvbHNcIiAgW3ZhbHVlXT1cInVwbG9hZFByb2dyZXNzXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICBbc3RhdHVzXT1cInVwbG9hZFN0YXR1c1wiIFthd2FpdE5ld1VwbG9hZF09XCJwcm9jZXNzaW5nUmVjb3JkaW5nXCI+PC9hcHAtdXBsb2Fkc3RhdHVzPlxyXG4gICAgICAgIDxhcHAtd2FrZWxvY2tpbmRpY2F0b3IgKm5nSWY9XCIhc2NyZWVuWHNcIiBjbGFzcz1cInJpY29udHJvbHNcIiBbc2NyZWVuTG9ja2VkXT1cInNjcmVlbkxvY2tlZFwiPjwvYXBwLXdha2Vsb2NraW5kaWNhdG9yPlxyXG4gICAgICAgIDxhcHAtcmVhZHlzdGF0ZWluZGljYXRvciAqbmdJZj1cIiFzY3JlZW5Yc1wiIGNsYXNzPVwicmljb250cm9sc1wiIFtyZWFkeV09XCJkYXRhU2F2ZWQgJiYgIWlzQWN0aXZlKClcIj48L2FwcC1yZWFkeXN0YXRlaW5kaWNhdG9yPlxyXG4gICAgICA8L2Rpdj5cclxuICAgIDwvZGl2PlxyXG4gIGAsXHJcbiAgc3R5bGVzOiBbYDpob3N0IHtcclxuICAgIGZsZXg6IDI7XHJcbiAgICBiYWNrZ3JvdW5kOiBsaWdodGdyZXk7XHJcbiAgICBkaXNwbGF5OiBmbGV4OyAvKiBWZXJ0aWNhbCBmbGV4IGNvbnRhaW5lcjogQm90dG9tIHRyYW5zcG9ydCBwYW5lbCwgYWJvdmUgcHJvbXB0aW5nIHBhbmVsICovXHJcbiAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gICAgbWFyZ2luOiAwO1xyXG4gICAgcGFkZGluZzogMDtcclxuICAgIG1pbi1oZWlnaHQ6IDBweDtcclxuXHJcbiAgICAgIC8qIFByZXZlbnRzIGhvcml6b250YWwgc2Nyb2xsIGJhciBvbiBzd2lwZSByaWdodCAqL1xyXG4gICAgICBvdmVyZmxvdzogaGlkZGVuO1xyXG4gIH1gLGAucmljb250cm9scyB7XHJcbiAgICAgICAgZGlzcGxheTpmbGV4O1xyXG4gICAgICAgIHBhZGRpbmc6IDRweDtcclxuICAgICAgICBib3gtc2l6aW5nOiBib3JkZXItYm94O1xyXG4gICAgICAgIGhlaWdodDogMTAwJTtcclxuICAgICAgICBmbGV4LWRpcmVjdGlvbjogcm93O1xyXG4gICAgICAgIGp1c3RpZnktY29udGVudDogZmxleC1lbmQ7YWxpZ24taXRlbXM6IGNlbnRlcjsgYWxpZ24tY29udGVudDogY2VudGVyO1xyXG4gICAgfWAsYC5kYXJrIHtcclxuICAgIGJhY2tncm91bmQ6IGRhcmtncmF5O1xyXG4gIH1gLGAuY29udHJvbHBhbmVsIHtcclxuICAgIGRpc3BsYXk6ZmxleDtcclxuICAgIGZsZXgtZGlyZWN0aW9uOiByb3c7XHJcbiAgICBhbGlnbi1jb250ZW50OiBjZW50ZXI7XHJcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAgbWFyZ2luOiAwO1xyXG4gICAgcGFkZGluZzogMjBweDtcclxuICAgIG1pbi1oZWlnaHQ6IG1pbi1jb250ZW50OyAvKiBpbXBvcnRhbnQgKi9cclxuICB9YCxgLmF1ZGlvU3RhdHVzRGlzcGxheXtcclxuICAgIGRpc3BsYXk6ZmxleDtcclxuICAgIGZsZXgtZGlyZWN0aW9uOiByb3c7XHJcbiAgICBoZWlnaHQ6MTAwcHg7XHJcbiAgICBtaW4taGVpZ2h0OiAxMDBweDtcclxuICB9YCxgLmF1ZGlvU3RhdHVzRGlzcGxheVhze1xyXG4gICAgZGlzcGxheTpmbGV4O1xyXG4gICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICAgIGhlaWdodDoxMjVweDtcclxuICAgIG1pbi1oZWlnaHQ6IDEyNXB4O1xyXG4gIH1gXHJcbiAgXVxyXG59KVxyXG5leHBvcnQgY2xhc3MgU2Vzc2lvbk1hbmFnZXIgZXh0ZW5kcyBCYXNpY1JlY29yZGVyIGltcGxlbWVudHMgQWZ0ZXJWaWV3SW5pdCxPbkRlc3Ryb3ksIEF1ZGlvQ2FwdHVyZUxpc3RlbmVyLENodW5rQXVkaW9CdWZmZXJSZWNlaXZlciB7XHJcblxyXG4gIHByaXZhdGUgb2ZmbGluZUF1ZGlvQ29udGV4dDpPZmZsaW5lQXVkaW9Db250ZXh0fG51bGw9bnVsbDtcclxuXHJcbiAgZ2V0IHBlcnNpc3RlbnRBdWRpb1N0b3JhZ2VUYXJnZXQoKTogUGVyc2lzdGVudEF1ZGlvU3RvcmFnZVRhcmdldCB8IG51bGwge1xyXG4gICAgcmV0dXJuIHRoaXMuX3BlcnNpc3RlbnRBdWRpb1N0b3JhZ2VUYXJnZXQ7XHJcbiAgfVxyXG5cclxuICBzZXQgcGVyc2lzdGVudEF1ZGlvU3RvcmFnZVRhcmdldCh2YWx1ZTogUGVyc2lzdGVudEF1ZGlvU3RvcmFnZVRhcmdldCB8IG51bGwpIHtcclxuICAgIHRoaXMuX3BlcnNpc3RlbnRBdWRpb1N0b3JhZ2VUYXJnZXQgPSB2YWx1ZTtcclxuICAgIGlmKHRoaXMuYWMpIHtcclxuICAgICAgdGhpcy5hYy5wZXJzaXN0ZW50QXVkaW9TdG9yYWdlVGFyZ2V0ID0gdGhpcy5wZXJzaXN0ZW50QXVkaW9TdG9yYWdlVGFyZ2V0O1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgQElucHV0KCkgcHJvamVjdE5hbWU6c3RyaW5nfHVuZGVmaW5lZDtcclxuICBlbmFibGVVcGxvYWRSZWNvcmRpbmdzOiBib29sZWFuID0gdHJ1ZTtcclxuICBlbmFibGVEb3dubG9hZFJlY29yZGluZ3M6IGJvb2xlYW4gPSBmYWxzZTtcclxuICBzdGF0dXM6IFN0YXR1cyA9IFN0YXR1cy5CTE9DS0VEO1xyXG5cclxuICBAVmlld0NoaWxkKFByb21wdGluZywgeyBzdGF0aWM6IHRydWUgfSkgcHJvbXB0aW5nITogUHJvbXB0aW5nO1xyXG4gIEBWaWV3Q2hpbGQoTGV2ZWxCYXIsIHsgc3RhdGljOiB0cnVlIH0pIGxpdmVMZXZlbERpc3BsYXkhOiBMZXZlbEJhcjtcclxuXHJcbiAgQElucHV0KCkgZGF0YVNhdmVkPXRydWVcclxuXHJcbiAgc3RhcnRTdG9wU2lnbmFsU3RhdGUhOiBTdGFydFN0b3BTaWduYWxTdGF0ZTtcclxuXHJcbiAgcHJpdmF0ZSBwcmVSZWNUaW1lcklkOiBudW1iZXJ8bnVsbD1udWxsO1xyXG4gIHByaXZhdGUgcHJlUmVjVGltZXJSdW5uaW5nOiBib29sZWFufG51bGw9bnVsbDtcclxuICBwcml2YXRlIHBvc3REZWxheTpudW1iZXI9REVGQVVMVF9QT1NUX1JFQ19ERUxBWTtcclxuICBwcml2YXRlIHBvc3RSZWNUaW1lcklkOiBudW1iZXJ8bnVsbD1udWxsO1xyXG4gIHByaXZhdGUgcG9zdFJlY1RpbWVyUnVubmluZzogYm9vbGVhbnxudWxsPW51bGw7XHJcbiAgLy9wcml2YXRlIG1heFJlY1RpbWVyUnVubmluZzogYm9vbGVhbnxudWxsPW51bGw7XHJcblxyXG4gIGF1ZGlvOiBhbnk7XHJcbiAgX3NjcmlwdCE6IFNjcmlwdDtcclxuICBwcml2YXRlIF9wcm9tcHRJbmRleD0wO1xyXG4gIHByaXZhdGUgc2VjdGlvbiE6IFNlY3Rpb247XHJcbiAgZ3JvdXAhOiBHcm91cDtcclxuICBwcm9tcHRJdGVtITpQcm9tcHRJdGVtO1xyXG4gIHNob3dQcm9tcHQhOiBib29sZWFuO1xyXG5cclxuICAvLyBpbmRleCBvZiBjdXJyZW50IHNlY3Rpb25cclxuICBzZWN0SWR4ITogbnVtYmVyO1xyXG4gIC8vIGluZGV4IG9mIGN1cnJlbnQgZ3JvdXAgaW4gc2VjdGlvblxyXG4gIGdyb3VwSWR4SW5TZWN0aW9uITogbnVtYmVyO1xyXG4gIC8vIGluZGV4IG9mIGN1cnJlbnQgcHJvbXB0IGl0ZW0gaW4gZ3JvdXBcclxuICBwcm9tcHRJdGVtSWR4SW5Hcm91cCE6IG51bWJlcjtcclxuXHJcbiAgcHJpdmF0ZSBhdXRvcmVjb3JkaW5nITogYm9vbGVhbjtcclxuXHJcbiAgaXRlbXM6IFNwckl0ZW1zQ2FjaGV8bnVsbD1udWxsO1xyXG4gIC8vc2VsZWN0ZWRJdGVtSWR4OiBudW1iZXI7XHJcbiAgcHJpdmF0ZSBfZGlzcGxheVJlY0ZpbGU6IFNwclJlY29yZGluZ0ZpbGUgfCBudWxsPW51bGw7XHJcbiAgcHJpdmF0ZSBkaXNwbGF5UmVjRmlsZVZlcnNpb24hOiBudW1iZXI7XHJcblxyXG4gIHByb21wdEl0ZW1Db3VudCE6IG51bWJlcjtcclxuXHJcbiAgc2hvd1Nlc3Npb25Db21wbGV0ZU1lc3NhZ2U9dHJ1ZTtcclxuXHJcbiAgY29uc3RydWN0b3IocHJvdGVjdGVkIGJwbzpCcmVha3BvaW50T2JzZXJ2ZXIsXHJcbiAgICAgICAgICAgICAgY2hhbmdlRGV0ZWN0b3JSZWY6IENoYW5nZURldGVjdG9yUmVmLFxyXG4gICAgICAgICAgICAgIHByaXZhdGUgcmVuZGVyZXI6IFJlbmRlcmVyMixcclxuICAgICAgICAgICAgICBkaWFsb2c6IE1hdERpYWxvZyxcclxuICAgICAgICAgICAgICBzZXNzaW9uU2VydmljZTpTZXNzaW9uU2VydmljZSxcclxuICAgICAgICAgICAgICBwcml2YXRlIHJlY0ZpbGVTZXJ2aWNlOlJlY29yZGluZ1NlcnZpY2UsXHJcbiAgICAgICAgICAgICAgdXBsb2FkZXI6IFNwZWVjaFJlY29yZGVyVXBsb2FkZXIsXHJcbiAgICAgICAgICAgICAgQEluamVjdChTUEVFQ0hSRUNPUkRFUl9DT05GSUcpIGNvbmZpZz86IFNwZWVjaFJlY29yZGVyQ29uZmlnKSB7XHJcbiAgICBzdXBlcihicG8sY2hhbmdlRGV0ZWN0b3JSZWYsZGlhbG9nLHNlc3Npb25TZXJ2aWNlLHVwbG9hZGVyLGNvbmZpZyk7XHJcbiAgICB0aGlzLnN0YXR1cyA9IFN0YXR1cy5JRExFO1xyXG4gICAgdGhpcy5hdWRpbyA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdhdWRpbycpO1xyXG4gICAgaWYgKHRoaXMuY29uZmlnICYmIHRoaXMuY29uZmlnLmVuYWJsZVVwbG9hZFJlY29yZGluZ3MgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICB0aGlzLmVuYWJsZVVwbG9hZFJlY29yZGluZ3MgPSB0aGlzLmNvbmZpZy5lbmFibGVVcGxvYWRSZWNvcmRpbmdzO1xyXG4gICAgfVxyXG4gICAgaWYgKHRoaXMuY29uZmlnICYmIHRoaXMuY29uZmlnLmVuYWJsZURvd25sb2FkUmVjb3JkaW5ncyAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgIHRoaXMuZW5hYmxlRG93bmxvYWRSZWNvcmRpbmdzID0gdGhpcy5jb25maWcuZW5hYmxlRG93bmxvYWRSZWNvcmRpbmdzO1xyXG4gICAgfVxyXG4gICAgdGhpcy5pbml0KCk7XHJcbiAgfVxyXG5cclxuXHJcblxyXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcclxuICAgIHRoaXMuc3RyZWFtTGV2ZWxNZWFzdXJlLmxldmVsTGlzdGVuZXIgPSB0aGlzLmxpdmVMZXZlbERpc3BsYXk7XHJcbiAgICB0aGlzLnN0cmVhbUxldmVsTWVhc3VyZS5wZWFrTGV2ZWxMaXN0ZW5lcj0ocGVha0x2bEluRGIpPT57XHJcbiAgICAgIHRoaXMucGVha0xldmVsSW5EYj1wZWFrTHZsSW5EYjtcclxuICAgICAgdGhpcy5jaGFuZ2VEZXRlY3RvclJlZi5kZXRlY3RDaGFuZ2VzKCk7XHJcbiAgICB9XHJcbiAgfVxyXG4gICAgbmdPbkRlc3Ryb3koKSB7XHJcbiAgICAgIC8vY29uc29sZS5kZWJ1ZyhcIkNvbSBkZXN0cm95LCBkaXNhYmxlIHdha2UgbG9jay5cIilcclxuICAgICAgdGhpcy5kaXNhYmxlV2FrZUxvY2tDb25kKCk7XHJcbiAgICAgICB0aGlzLmRlc3Ryb3llZD10cnVlO1xyXG4gICAgICAgLy8gVE9ETyBzdG9wIGNhcHR1cmUgL3BsYXliYWNrXHJcbiAgICB9XHJcblxyXG4gIHByaXZhdGUgaW5pdCgpIHtcclxuICAgIHRoaXMuc2VjdElkeCA9IDA7XHJcbiAgICB0aGlzLmdyb3VwSWR4SW5TZWN0aW9uID0gMDtcclxuICAgIHRoaXMucHJvbXB0SXRlbUlkeEluR3JvdXAgPSAwO1xyXG4gICAgdGhpcy5hdXRvcmVjb3JkaW5nID0gZmFsc2U7XHJcbiAgICB0aGlzLnRyYW5zcG9ydEFjdGlvbnMuc3RhcnRBY3Rpb24uZGlzYWJsZWQgPSB0cnVlO1xyXG4gICAgdGhpcy50cmFuc3BvcnRBY3Rpb25zLnN0b3BBY3Rpb24uZGlzYWJsZWQgPSB0cnVlO1xyXG4gICAgdGhpcy50cmFuc3BvcnRBY3Rpb25zLm5leHRBY3Rpb24uZGlzYWJsZWQgPSB0cnVlO1xyXG4gICAgdGhpcy50cmFuc3BvcnRBY3Rpb25zLnBhdXNlQWN0aW9uLmRpc2FibGVkID0gdHJ1ZTtcclxuICAgIHRoaXMucGxheVN0YXJ0QWN0aW9uLmRpc2FibGVkID0gdHJ1ZTtcclxuXHJcbiAgICAvLyBsZXQgY29udGV4dDpBdWRpb0NvbnRleHR8bnVsbD1udWxsO1xyXG4gICAgLy8gdHJ5IHtcclxuICAgIC8vICAgY29udGV4dCA9IEF1ZGlvQ29udGV4dFByb3ZpZGVyLmF1ZGlvQ29udGV4dEluc3RhbmNlKCk7XHJcbiAgICAvLyB9IGNhdGNoIChlcnIpIHtcclxuICAgIC8vICAgdGhpcy5zdGF0dXMgPSBTdGF0dXMuRVJST1I7XHJcbiAgICAvLyAgIGxldCBlcnJNc2cgPSAnVW5rbm93biBlcnJvcic7XHJcbiAgICAvLyAgIGlmKGVyciBpbnN0YW5jZW9mIEVycm9yKXtcclxuICAgIC8vICAgICBlcnJNc2c9ZXJyLm1lc3NhZ2U7XHJcbiAgICAvLyAgIH1cclxuICAgIC8vICAgdGhpcy5zdGF0dXNNc2cgPSAnRVJST1I6ICcgKyBlcnJNc2c7XHJcbiAgICAvLyAgIHRoaXMuc3RhdHVzQWxlcnRUeXBlID0gJ2Vycm9yJztcclxuICAgIC8vICAgdGhpcy5kaWFsb2cub3BlbihNZXNzYWdlRGlhbG9nLCB7XHJcbiAgICAvLyAgICAgZGF0YToge1xyXG4gICAgLy8gICAgICAgdHlwZTogJ2Vycm9yJyxcclxuICAgIC8vICAgICAgIHRpdGxlOiAnRXJyb3InLFxyXG4gICAgLy8gICAgICAgbXNnOiBlcnJNc2csXHJcbiAgICAvLyAgICAgICBhZHZpY2U6ICdQbGVhc2UgdXNlIGEgc3VwcG9ydGVkIGJyb3dzZXIuJyxcclxuICAgIC8vICAgICB9XHJcbiAgICAvLyAgIH0pO1xyXG4gICAgLy8gICByZXR1cm47XHJcbiAgICAvLyB9XHJcbiAgICAvLyBpZihjb250ZXh0KSB7XHJcbiAgICAvLyAgIGNvbnNvbGUuaW5mbyhcIlN0YXRlIG9mIGF1ZGlvIGNvbnRleHQ6IFwiICsgY29udGV4dC5zdGF0ZSlcclxuICAgIC8vIH1lbHNle1xyXG4gICAgLy8gICBjb25zb2xlLmluZm8oXCJObyBhdWRpbyBjb250ZXh0IGF2YWlsYWJsZSFcIik7XHJcbiAgICAvLyB9XHJcbiAgICAvLyBpZiAoIWNvbnRleHQgfHwgIW5hdmlnYXRvci5tZWRpYURldmljZXMpIHtcclxuICAgIC8vICAgdGhpcy5zdGF0dXMgPSBTdGF0dXMuRVJST1I7XHJcbiAgICAvLyAgIGxldCBlcnJNc2cgPSAnQnJvd3NlciBkb2VzIG5vdCBzdXBwb3J0IE1lZGlhIHN0cmVhbXMhJztcclxuICAgIC8vICAgdGhpcy5zdGF0dXNNc2cgPSAnRVJST1I6ICcgKyBlcnJNc2c7XHJcbiAgICAvLyAgIHRoaXMuc3RhdHVzQWxlcnRUeXBlID0gJ2Vycm9yJztcclxuICAgIC8vICAgdGhpcy5kaWFsb2cub3BlbihNZXNzYWdlRGlhbG9nLCB7XHJcbiAgICAvLyAgICAgZGF0YToge1xyXG4gICAgLy8gICAgICAgdHlwZTogJ2Vycm9yJyxcclxuICAgIC8vICAgICAgIHRpdGxlOiAnRXJyb3InLFxyXG4gICAgLy8gICAgICAgbXNnOiBlcnJNc2csXHJcbiAgICAvLyAgICAgICBhZHZpY2U6ICdQbGVhc2UgdXNlIGEgc3VwcG9ydGVkIGJyb3dzZXIuJyxcclxuICAgIC8vICAgICB9XHJcbiAgICAvLyAgIH0pO1xyXG4gICAgLy8gICByZXR1cm47XHJcbiAgICAvLyB9IGVsc2Uge1xyXG4gICAgICB0aGlzLmFjID0gbmV3IEF1ZGlvQ2FwdHVyZSgpO1xyXG4gICAgICBpZiAodGhpcy5hYykge1xyXG4gICAgICAgIHRoaXMudHJhbnNwb3J0QWN0aW9ucy5zdGFydEFjdGlvbi5vbkFjdGlvbiA9ICgpID0+IHRoaXMuc3RhcnRJdGVtKCk7XHJcbiAgICAgICAgdGhpcy5hYy5saXN0ZW5lciA9IHRoaXM7XHJcblxyXG4gICAgICAgIHRoaXMuY29uZmlndXJlU3RyZWFtQ2FwdHVyZVN0cmVhbSgpO1xyXG5cclxuICAgICAgICAvLyBEb24ndCBsaXN0IHRoZSBkZXZpY2VzIGhlcmUuIElmIHdlIGRvIG5vdCBoYXZlIGF1ZGlvIHBlcm1pc3Npb25zIHdlIG9ubHkgZ2V0IGFub255bWl6ZWQgZGV2aWNlcyB3aXRob3V0IGxhYmVscy5cclxuICAgICAgICAvL3RoaXMuYWMubGlzdERldmljZXMoKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICB0aGlzLnRyYW5zcG9ydEFjdGlvbnMuc3RhcnRBY3Rpb24uZGlzYWJsZWQgPSB0cnVlO1xyXG4gICAgICAgIGxldCBlcnJNc2cgPSAnQnJvd3NlciBkb2VzIG5vdCBzdXBwb3J0IE1lZGlhL0F1ZGlvIEFQSSEnO1xyXG4gICAgICAgIHRoaXMuc3RhdHVzTXNnID0gJ0VSUk9SOiAnICsgZXJyTXNnO1xyXG4gICAgICAgIHRoaXMuc3RhdHVzQWxlcnRUeXBlID0gJ2Vycm9yJztcclxuICAgICAgICB0aGlzLmRpYWxvZy5vcGVuKE1lc3NhZ2VEaWFsb2csIHtcclxuICAgICAgICAgIGRhdGE6IHtcclxuICAgICAgICAgICAgdHlwZTogJ2Vycm9yJyxcclxuICAgICAgICAgICAgdGl0bGU6ICdFcnJvcicsXHJcbiAgICAgICAgICAgIG1zZzogZXJyTXNnLFxyXG4gICAgICAgICAgICBhZHZpY2U6ICdQbGVhc2UgdXNlIGEgc3VwcG9ydGVkIGJyb3dzZXIuJyxcclxuICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuICAgICAgdGhpcy50cmFuc3BvcnRBY3Rpb25zLnN0b3BBY3Rpb24ub25BY3Rpb24gPSAoKSA9PiB0aGlzLnN0b3BJdGVtKCk7XHJcbiAgICAgIHRoaXMudHJhbnNwb3J0QWN0aW9ucy5uZXh0QWN0aW9uLm9uQWN0aW9uID0gKCkgPT4gdGhpcy5zdG9wSXRlbSgpO1xyXG4gICAgICB0aGlzLnRyYW5zcG9ydEFjdGlvbnMucGF1c2VBY3Rpb24ub25BY3Rpb24gPSAoKSA9PiB0aGlzLnBhdXNlSXRlbSgpO1xyXG4gICAgICB0aGlzLnRyYW5zcG9ydEFjdGlvbnMuZndkQWN0aW9uLm9uQWN0aW9uID0gKCkgPT4gdGhpcy5uZXh0SXRlbSgpO1xyXG4gICAgICB0aGlzLnRyYW5zcG9ydEFjdGlvbnMuZndkTmV4dEFjdGlvbi5vbkFjdGlvbiA9ICgpID0+IHRoaXMubmV4dFVucmVjb3JkZWRJdGVtKCk7XHJcbiAgICAgIHRoaXMudHJhbnNwb3J0QWN0aW9ucy5id2RBY3Rpb24ub25BY3Rpb24gPSAoKSA9PiB0aGlzLnByZXZJdGVtKCk7XHJcbiAgICAgIHRoaXMucGxheVN0YXJ0QWN0aW9uLm9uQWN0aW9uID0gKCkgPT4gdGhpcy5jb250cm9sQXVkaW9QbGF5ZXI/LnN0YXJ0KCk7XHJcblxyXG4gICAgdGhpcy5zdGFydFN0b3BTaWduYWxTdGF0ZSA9IFN0YXJ0U3RvcFNpZ25hbFN0YXRlLk9GRjtcclxuXHJcbn1cclxuXHJcbiAgQEhvc3RMaXN0ZW5lcignd2luZG93OmtleXByZXNzJywgWyckZXZlbnQnXSlcclxuICBvbktleVByZXNzKGtlOiBLZXlib2FyZEV2ZW50KSB7XHJcbiAgICBpZiAoa2Uua2V5ID09ICcgJykge1xyXG4gICAgICB0aGlzLnRyYW5zcG9ydEFjdGlvbnMuc3RhcnRBY3Rpb24ucGVyZm9ybSgpO1xyXG4gICAgICB0aGlzLnRyYW5zcG9ydEFjdGlvbnMubmV4dEFjdGlvbi5wZXJmb3JtKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBASG9zdExpc3RlbmVyKCd3aW5kb3c6a2V5ZG93bicsIFsnJGV2ZW50J10pXHJcbiAgb25LZXlEb3duKGtlOiBLZXlib2FyZEV2ZW50KSB7XHJcbiAgICBpZiAoa2Uua2V5ID09ICcgJykge1xyXG4gICAgICB0aGlzLnRyYW5zcG9ydEFjdGlvbnMuc3RvcEFjdGlvbi5wZXJmb3JtKCk7XHJcbiAgICB9XHJcbiAgICBpZiAoa2Uua2V5ID09ICdwJykge1xyXG4gICAgICB0aGlzLnRyYW5zcG9ydEFjdGlvbnMucGF1c2VBY3Rpb24ucGVyZm9ybSgpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChrZS5rZXkgPT0gJ0VzY2FwZScpIHtcclxuICAgICAgaWYoIXRoaXMuYXVkaW9TaWduYWxDb2xsYXBzZWQpe1xyXG4gICAgICAgIHRoaXMuYXVkaW9TaWduYWxDb2xsYXBzZWQ9dHJ1ZTtcclxuICAgICAgfVxyXG4gICAgICB0aGlzLnRyYW5zcG9ydEFjdGlvbnMuc3RvcEFjdGlvbi5wZXJmb3JtKCk7XHJcbiAgICAgIHRoaXMudHJhbnNwb3J0QWN0aW9ucy5wYXVzZUFjdGlvbi5wZXJmb3JtKCk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGtlLmtleSA9PSAnTWVkaWFQbGF5UGF1c2UnKSB7XHJcbiAgICAgIHRoaXMucGxheVN0YXJ0QWN0aW9uLnBlcmZvcm0oKTtcclxuICAgIH1cclxuICAgIGlmIChrZS5rZXkgPT09ICdBcnJvd1JpZ2h0Jykge1xyXG4gICAgICB0aGlzLnRyYW5zcG9ydEFjdGlvbnMuZndkQWN0aW9uLnBlcmZvcm0oKTtcclxuICAgIH1cclxuICAgIGlmIChrZS5rZXkgPT09ICdBcnJvd0xlZnQnKSB7XHJcbiAgICAgIHRoaXMudHJhbnNwb3J0QWN0aW9ucy5id2RBY3Rpb24ucGVyZm9ybSgpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgdXBkYXRlV2FrZUxvY2soZGF0YVNhdmVkOmJvb2xlYW49dGhpcy5kYXRhU2F2ZWQpe1xyXG4gICAgLy9jb25zb2xlLmRlYnVnKFwiVXBkYXRlIHdha2UgbG9jazogZGF0YVNhdmVkOiBcIitkYXRhU2F2ZWQrXCIsIG5vdCBhY3RpdmU6IFwiKyEgdGhpcy5pc0FjdGl2ZSgpKVxyXG4gICAgaWYoZGF0YVNhdmVkICYmICEgdGhpcy5pc0FjdGl2ZSgpKXtcclxuICAgICAgdGhpcy5kaXNhYmxlV2FrZUxvY2tDb25kKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcm9ncmVzc1BlcmNlbnRWYWx1ZSgpOm51bWJlciB7XHJcbiAgICBsZXQgdj0xMDA7XHJcbiAgICBpZih0aGlzLml0ZW1zKSB7XHJcbiAgICAgIHY9dGhpcy5wcm9tcHRJbmRleCAqIDEwMCAvICh0aGlzLml0ZW1zLmxlbmd0aCgpIC0gMSk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdjtcclxuICB9XHJcbiAgaXNUZXN0U2Vzc2lvbigpOmJvb2xlYW4ge1xyXG4gICAgcmV0dXJuICgodGhpcy5fc2Vzc2lvbiE9bnVsbCkgJiYgKHRoaXMuX3Nlc3Npb24udHlwZSA9PT0gJ1RFU1QnIHx8IHRoaXMuX3Nlc3Npb24udHlwZT09PSdURVNUX0RFRl9BJyB8fCB0aGlzLl9zZXNzaW9uLnR5cGUgPT09ICdTSU5VU19URVNUJykpO1xyXG4gIH1cclxuXHJcbiAgaXNEZWZhdWx0QXVkaW9UZXN0U2Vzc2lvbigpOmJvb2xlYW4ge1xyXG4gICAgcmV0dXJuICgodGhpcy5fc2Vzc2lvbiE9bnVsbCkgJiYgKHRoaXMuX3Nlc3Npb24udHlwZT09PSdURVNUX0RFRl9BJykpO1xyXG4gIH1cclxuXHJcbiAgaXNEZWZhdWx0QXVkaW9UZXN0U2Vzc2lvbk92ZXJ3cml0aW5nUHJvamVjdFJlcXVpcmVtZW50cygpOmJvb2xlYW4ge1xyXG4gICAgcmV0dXJuICgodGhpcy5fc2Vzc2lvbiE9bnVsbCkgJiYgKHRoaXMuX3Nlc3Npb24udHlwZT09PSdURVNUX0RFRl9BJykgJiYgKHRoaXMuYXVkaW9EZXZpY2VzIT1udWxsKSAmJiB0aGlzLmF1ZGlvRGV2aWNlcy5sZW5ndGg+MClcclxuICB9XHJcblxyXG4gIHNldCBjb250cm9sQXVkaW9QbGF5ZXIoY29udHJvbEF1ZGlvUGxheWVyOiBBdWRpb1BsYXllcnxudWxsKSB7XHJcbiAgICB0aGlzLl9jb250cm9sQXVkaW9QbGF5ZXI9Y29udHJvbEF1ZGlvUGxheWVyO1xyXG4gICAgaWYgKHRoaXMuX2NvbnRyb2xBdWRpb1BsYXllcikge1xyXG4gICAgICB0aGlzLl9jb250cm9sQXVkaW9QbGF5ZXIubGlzdGVuZXIgPSB0aGlzO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgZ2V0IGNvbnRyb2xBdWRpb1BsYXllcigpOiBBdWRpb1BsYXllcnxudWxsIHtcclxuICAgIHJldHVybiB0aGlzLl9jb250cm9sQXVkaW9QbGF5ZXI7XHJcbiAgfVxyXG5cclxuICBzZXQgc2NyaXB0KHNjcmlwdDogYW55KSB7XHJcbiAgICB0aGlzLl9zY3JpcHQgPSBzY3JpcHQ7XHJcbiAgICB0aGlzLmxvYWRTY3JpcHQoKTtcclxuICB9XHJcblxyXG4gIHVwZGF0ZShlOiBBdWRpb1BsYXllckV2ZW50KSB7XHJcbiAgICBpZiAoZS50eXBlID09IEV2ZW50VHlwZS5TVEFSVEVEKSB7XHJcbiAgICAgIHRoaXMucGxheVN0YXJ0QWN0aW9uLmRpc2FibGVkID0gdHJ1ZTtcclxuICAgICAgdGhpcy51cGRhdGVUaW1lcklkID0gd2luZG93LnNldEludGVydmFsKCgpID0+IHtcclxuICAgICAgICAvL3RoaXMuYXVkaW9TaWduYWwucGxheUZyYW1lUG9zaXRpb24gPSB0aGlzLmFwLnBsYXlQb3NpdGlvbkZyYW1lcztcclxuICAgICAgfSwgNTApO1xyXG4gICAgfSBlbHNlIGlmIChlLnR5cGUgPT0gRXZlbnRUeXBlLlNUT1BQRUQgfHwgZS50eXBlID09IEV2ZW50VHlwZS5FTkRFRCkge1xyXG4gICAgICB3aW5kb3cuY2xlYXJJbnRlcnZhbCh0aGlzLnVwZGF0ZVRpbWVySWQpO1xyXG4gICAgICAvLyB0aGlzLmF1ZGlvU2lnbmFsLnBsYXlGcmFtZVBvc2l0aW9uID0gdGhpcy5hcC5wbGF5UG9zaXRpb25GcmFtZXM7XHJcbiAgICAgIHRoaXMucGxheVN0YXJ0QWN0aW9uLmRpc2FibGVkID0gKCEodGhpcy5kaXNwbGF5UmVjRmlsZSkpO1xyXG5cclxuICAgIH1cclxuICB9XHJcblxyXG4gIGdldCBwcm9tcHRJbmRleCgpOm51bWJlcntcclxuICAgIHJldHVybiB0aGlzLl9wcm9tcHRJbmRleDtcclxuICB9XHJcblxyXG4gIHNldCBwcm9tcHRJbmRleChwcm9tcHRJbmRleDpudW1iZXIpe1xyXG4gICAgaWYocHJvbXB0SW5kZXg8MCB8fCBwcm9tcHRJbmRleD49dGhpcy5wcm9tcHRJdGVtQ291bnQpe1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJQcm9tcHQgaW5kZXggb3V0IG9mIHJhbmdlXCIpXHJcbiAgICB9XHJcbiAgICBsZXQgaSA9IDA7XHJcbiAgICBsZXQgc2VjdGlvbnM9dGhpcy5fc2NyaXB0LnNlY3Rpb25zO1xyXG4gICAgbGV0IGZvdW5kPWZhbHNlO1xyXG4gICAgZm9yIChsZXQgc2kgPSAwOyBzaSA8IHNlY3Rpb25zLmxlbmd0aCAmJiAhZm91bmQ7IHNpKyspIHtcclxuICAgICAgbGV0IHNlY3Rpb24gPSBzZWN0aW9uc1tzaV07XHJcbiAgICAgIGxldCBncyA9IHNlY3Rpb24uX3NodWZmbGVkR3JvdXBzO1xyXG4gICAgICBmb3IgKGxldCBnaSA9IDA7IGdpIDwgZ3MubGVuZ3RoOyBnaSsrKSB7XHJcbiAgICAgICAgbGV0IHBpcz1nc1tnaV0uX3NodWZmbGVkUHJvbXB0SXRlbXM7XHJcblxyXG4gICAgICAgIGxldCBwaXNTaXplID0gcGlzLmxlbmd0aDtcclxuICAgICAgICBpZiAocHJvbXB0SW5kZXggPCBpICsgcGlzU2l6ZSkge1xyXG4gICAgICAgICAgdGhpcy5zZWN0SWR4ID0gc2k7XHJcbiAgICAgICAgICB0aGlzLmdyb3VwSWR4SW5TZWN0aW9uPWdpO1xyXG4gICAgICAgICAgdGhpcy5wcm9tcHRJdGVtSWR4SW5Hcm91cCA9IHByb21wdEluZGV4IC0gaTtcclxuICAgICAgICAgIGZvdW5kPXRydWU7XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgaSArPSBwaXNTaXplO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgaWYoZm91bmQpe1xyXG4gICAgICB0aGlzLl9wcm9tcHRJbmRleD1wcm9tcHRJbmRleDtcclxuICAgIH1lbHNle1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnRlcm5hbCBlcnJvcjogUHJvbXB0IGluZGV4IG5vdCBmb3VuZFwiKVxyXG4gICAgfVxyXG4gICAgdGhpcy5rZWVwTGl2ZUxldmVsPWZhbHNlO1xyXG4gICAgdGhpcy5hcHBseUl0ZW0oKTtcclxuICB9XHJcblxyXG4gIGl0ZW1TZWxlY3QoaXRlbUlkeDogbnVtYmVyKSB7XHJcbiAgICBpZiAodGhpcy5zdGF0dXMgPT09IFN0YXR1cy5JRExFKSB7XHJcbiAgICAgIHRoaXMucHJvbXB0SW5kZXg9aXRlbUlkeDtcclxuICAgIH1cclxuXHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGNsZWFyUHJlUmVjVGltZXIoKSB7XHJcbiAgICBpZiAodGhpcy5wcmVSZWNUaW1lclJ1bm5pbmcpIHtcclxuICAgICAgaWYgKHRoaXMucHJlUmVjVGltZXJJZCkge1xyXG4gICAgICAgIHdpbmRvdy5jbGVhclRpbWVvdXQodGhpcy5wcmVSZWNUaW1lcklkKTtcclxuICAgICAgfVxyXG4gICAgICB0aGlzLnByZVJlY1RpbWVyUnVubmluZyA9IGZhbHNlO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBjbGVhclBvc3RSZWNUaW1lcigpe1xyXG4gICAgaWYgKHRoaXMucG9zdFJlY1RpbWVyUnVubmluZykge1xyXG4gICAgICBpZiAodGhpcy5wb3N0UmVjVGltZXJJZCkge1xyXG4gICAgICAgIHdpbmRvdy5jbGVhclRpbWVvdXQodGhpcy5wb3N0UmVjVGltZXJJZCk7XHJcbiAgICAgIH1cclxuICAgICAgdGhpcy5wb3N0UmVjVGltZXJSdW5uaW5nID0gZmFsc2U7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGNsZWFyTWF4UmVjVGltZXIoKXtcclxuICAgIGlmICh0aGlzLm1heFJlY1RpbWVyUnVubmluZykge1xyXG4gICAgICBpZiAodGhpcy5tYXhSZWNUaW1lcklkKSB7XHJcbiAgICAgICAgd2luZG93LmNsZWFyVGltZW91dCh0aGlzLm1heFJlY1RpbWVySWQpO1xyXG4gICAgICB9XHJcbiAgICAgIHRoaXMubWF4UmVjVGltZXJSdW5uaW5nID0gZmFsc2U7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBzdGFydEl0ZW0oKSB7XHJcbiAgICB0aGlzLnN0YXR1cz1TdGF0dXMuU1RBUlRJTkc7XHJcbiAgICBzdXBlci5zdGFydEl0ZW0oKTtcclxuICAgIGlmICh0aGlzLnJlYWRvbmx5KSB7XHJcbiAgICAgIHRoaXMuc3RhdHVzPVN0YXR1cy5JRExFO1xyXG4gICAgICByZXR1cm5cclxuICAgIH1cclxuICAgIHRoaXMudHJhbnNwb3J0QWN0aW9ucy5md2RBY3Rpb24uZGlzYWJsZWQgPSB0cnVlXHJcbiAgICB0aGlzLnRyYW5zcG9ydEFjdGlvbnMuZndkTmV4dEFjdGlvbi5kaXNhYmxlZCA9IHRydWVcclxuICAgIHRoaXMudHJhbnNwb3J0QWN0aW9ucy5id2RBY3Rpb24uZGlzYWJsZWQgPSB0cnVlXHJcbiAgICB0aGlzLnVwZGF0ZURpc3BsYXlSZWNGaWxlKG51bGwpO1xyXG4gICAgdGhpcy5kaXNwbGF5UmVjRmlsZVZlcnNpb24gPSAwO1xyXG4gICAgdGhpcy5kaXNwbGF5QXVkaW9DbGlwID0gbnVsbDtcclxuICAgIHRoaXMubGl2ZUxldmVsRGlzcGxheS5yZXNldCh0cnVlKTtcclxuICAgIC8vIEhpZGUgbG9hZGluZyBoaW50IG9uIGxpdmVsZXZlbCBkaXNwbGF5XHJcbiAgICB0aGlzLmxpdmVMZXZlbERpc3BsYXlTdGF0ZT1MaXZlTGV2ZWxTdGF0ZS5SRUFEWTtcclxuICAgIHRoaXMuc2hvd1JlY29yZGluZygpO1xyXG4gICAgaWYgKHRoaXMuc2VjdGlvbi5tb2RlID09PSAnQVVUT1JFQ09SRElORycpIHtcclxuICAgICAgdGhpcy5hdXRvcmVjb3JkaW5nID0gdHJ1ZTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLnN0YXJ0Q2FwdHVyZSgpO1xyXG4gIH1cclxuXHJcblxyXG4gIHByaXZhdGUgbG9hZFNjcmlwdCgpIHtcclxuICAgIHRoaXMucHJvbXB0SXRlbUNvdW50ID0gMDtcclxuXHJcbiAgICB0aGlzLml0ZW1zID0gbmV3IFNwckl0ZW1zQ2FjaGUoKTtcclxuICAgIGxldCBsbiA9IDA7XHJcblxyXG4gICAgLy9UT0RPIHJhbmRvbWl6ZSBub3Qgc3VwcG9ydGVkXHJcbiAgICBmb3IgKGxldCBzaSA9IDA7IHNpIDwgdGhpcy5fc2NyaXB0LnNlY3Rpb25zLmxlbmd0aDsgc2krKykge1xyXG4gICAgICBsZXQgc2VjdGlvbiA9IHRoaXMuX3NjcmlwdC5zZWN0aW9uc1tzaV07XHJcbiAgICAgIGxldCBncyA9IHNlY3Rpb24uX3NodWZmbGVkR3JvdXBzO1xyXG4gICAgICBmb3IobGV0IGdpPTA7Z2k8Z3MubGVuZ3RoO2dpKyspIHtcclxuXHJcbiAgICAgICAgICBsZXQgcGlzID0gZ3NbZ2ldLl9zaHVmZmxlZFByb21wdEl0ZW1zO1xyXG5cclxuICAgICAgICAgIGxldCBwaXNMZW4gPSBwaXMubGVuZ3RoO1xyXG4gICAgICAgICAgdGhpcy5wcm9tcHRJdGVtQ291bnQgKz0gcGlzTGVuO1xyXG4gICAgICAgICAgZm9yIChsZXQgcGlTZWN0SWR4ID0gMDsgcGlTZWN0SWR4IDwgcGlzTGVuOyBwaVNlY3RJZHgrKykge1xyXG4gICAgICAgICAgICBsZXQgcGkgPSBwaXNbcGlTZWN0SWR4XTtcclxuICAgICAgICAgICAgbGV0IHByb21wdEFzU3RyID0gUHJvbXB0aXRlbVV0aWwudG9QbGFpblRleHRTdHJpbmcocGkpO1xyXG5cclxuICAgICAgICAgICAgbGV0IGl0ID0gbmV3IEl0ZW0ocHJvbXB0QXNTdHIsIHNlY3Rpb24udHJhaW5pbmcsKCFwaS50eXBlIHx8IHBpLnR5cGU9PT0ncmVjb3JkaW5nJykpO1xyXG4gICAgICAgICAgICB0aGlzLml0ZW1zLmFkZEl0ZW0oaXQpO1xyXG4gICAgICAgICAgICBsbisrO1xyXG4gICAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcm9tcHRJbmRleEJ5SXRlbWNvZGUoaXRlbWNvZGU6c3RyaW5nKTpudW1iZXJ8bnVsbHtcclxuICAgIGxldCBwaXggPSAwO1xyXG5cclxuICAgIGZvciAobGV0IHNpID0gMDsgc2kgPCB0aGlzLl9zY3JpcHQuc2VjdGlvbnMubGVuZ3RoOyBzaSsrKSB7XHJcbiAgICAgIGxldCBzZWN0aW9uID0gdGhpcy5fc2NyaXB0LnNlY3Rpb25zW3NpXTtcclxuICAgICAgbGV0IGdzID0gc2VjdGlvbi5fc2h1ZmZsZWRHcm91cHM7XHJcbiAgICAgIGZvcihsZXQgZ2k9MDtnaTxncy5sZW5ndGg7Z2krKykge1xyXG4gICAgICAgIGxldCBwaXM9Z3NbZ2ldLl9zaHVmZmxlZFByb21wdEl0ZW1zO1xyXG4gICAgICAgIGxldCBwaXNMZW4gPSBwaXMubGVuZ3RoO1xyXG4gICAgICAgIGZvciAobGV0IHBpU2VjdElkeCA9IDA7IHBpU2VjdElkeCA8IHBpc0xlbjsgcGlTZWN0SWR4KyspIHtcclxuICAgICAgICAgIGxldCBwaSA9IHBpc1twaVNlY3RJZHhdO1xyXG4gICAgICAgICAgbGV0IGljPXBpLml0ZW1jb2RlO1xyXG4gICAgICAgICAgaWYoaWMgPT09IGl0ZW1jb2RlKXtcclxuICAgICAgICAgICAgcmV0dXJuIHBpeDtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIHBpeCsrO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIG51bGw7XHJcbiAgfVxyXG5cclxuICBjbGVhclByb21wdCgpIHtcclxuICAgIC8vdGhpcy5wcm9tcHRpbmcucHJvbXB0Q29udGFpbmVyLnByb21wdGVyLnByb21wdFRleHQ9Jyc7XHJcbiAgICAvL3RoaXMubWVkaWFpdGVtID0gbnVsbDtcclxuICAgIHRoaXMuc2hvd1Byb21wdCA9IGZhbHNlO1xyXG4gICAgdGhpcy5jaGFuZ2VEZXRlY3RvclJlZi5kZXRlY3RDaGFuZ2VzKClcclxuICB9XHJcblxyXG4gIGFwcGx5UHJvbXB0KCkge1xyXG4gICAgLy90aGlzLnByb21wdGluZy5wcm9tcHRDb250YWluZXIucHJvbXB0ZXIucHJvbXB0VGV4dD10aGlzLnByb21wdFVuaXQubWVkaWFpdGVtc1swXS50ZXh0O1xyXG4gICAgLy90aGlzLnByb21wdFRleHQgPSB0aGlzLnByb21wdFVuaXQubWVkaWFpdGVtc1swXS50ZXh0O1xyXG4gICAgLy90aGlzLm1lZGlhaXRlbT10aGlzLnByb21wdFVuaXQubWVkaWFpdGVtc1swXTtcclxuICAgIHRoaXMuc2hvd1Byb21wdCA9IHRydWU7XHJcbiAgICB0aGlzLmNoYW5nZURldGVjdG9yUmVmLmRldGVjdENoYW5nZXMoKVxyXG4gIH1cclxuXHJcbiAgZG93bmxvYWRSZWNvcmRpbmcoKSB7XHJcbiAgICBpZiAodGhpcy5kaXNwbGF5UmVjRmlsZSkge1xyXG4gICAgICBsZXQgYWRoOiBBdWRpb0RhdGFIb2xkZXIgfCBudWxsID0gdGhpcy5kaXNwbGF5UmVjRmlsZS5hdWRpb0RhdGFIb2xkZXI7XHJcbiAgICAgIGxldCBhczogQXVkaW9Tb3VyY2V8bnVsbD1udWxsO1xyXG4gICAgICBpZihhZGgpe1xyXG4gICAgICAgIGFzPWFkaC5hdWRpb1NvdXJjZTtcclxuICAgICAgfVxyXG4gICAgICBjb25zdCB3dyA9IG5ldyBXYXZXcml0ZXIoKTtcclxuICAgICAgaWYoYXMgaW5zdGFuY2VvZiBBdWRpb0J1ZmZlclNvdXJjZSkge1xyXG4gICAgICAgIHd3LndyaXRlQXN5bmMoYXMuYXVkaW9CdWZmZXIsICh3YXZGaWxlKSA9PiB7XHJcbiAgICAgICAgICBjb25zdCBibG9iID0gbmV3IEJsb2IoW3dhdkZpbGVdLCB7dHlwZTogJ2F1ZGlvL3dhdid9KTtcclxuICAgICAgICAgIGNvbnN0IHJmVXJsID0gVVJMLmNyZWF0ZU9iamVjdFVSTChibG9iKTtcclxuXHJcbiAgICAgICAgICBjb25zdCBkYXRhRG5sTG5rID0gdGhpcy5yZW5kZXJlci5jcmVhdGVFbGVtZW50KCdhJyk7XHJcbiAgICAgICAgICAvL2RhdGFEbmxMbmsubmFtZSA9ICdSZWNvcmRpbmcnO1xyXG4gICAgICAgICAgZGF0YURubExuay5ocmVmID0gcmZVcmw7XHJcblxyXG4gICAgICAgICAgdGhpcy5yZW5kZXJlci5hcHBlbmRDaGlsZChkb2N1bWVudC5ib2R5LCBkYXRhRG5sTG5rKTtcclxuXHJcbiAgICAgICAgICAvLyBkb3dubG9hZCBwcm9wZXJ0eSBub3QgeWV0IGluIFRTIGRlZlxyXG4gICAgICAgICAgaWYgKHRoaXMuZGlzcGxheVJlY0ZpbGUpIHtcclxuICAgICAgICAgICAgbGV0IGZuID0gdGhpcy5kaXNwbGF5UmVjRmlsZS5maWxlbmFtZVN0cmluZygpO1xyXG4gICAgICAgICAgICBmbiArPSAnXycgKyB0aGlzLmRpc3BsYXlSZWNGaWxlVmVyc2lvbjtcclxuICAgICAgICAgICAgZm4gKz0gJy53YXYnO1xyXG4gICAgICAgICAgICBkYXRhRG5sTG5rLmRvd25sb2FkID0gZm47XHJcbiAgICAgICAgICAgIGRhdGFEbmxMbmsuY2xpY2soKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIHRoaXMucmVuZGVyZXIucmVtb3ZlQ2hpbGQoZG9jdW1lbnQuYm9keSwgZGF0YURubExuayk7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIHNldCBkaXNwbGF5UmVjRmlsZShkaXNwbGF5UmVjRmlsZTogU3ByUmVjb3JkaW5nRmlsZSB8IG51bGwpIHtcclxuICAgIHRoaXMuX2Rpc3BsYXlSZWNGaWxlID0gZGlzcGxheVJlY0ZpbGU7XHJcbiAgfVxyXG5cclxuICBwcm90ZWN0ZWQgdXBkYXRlRGlzcGxheVJlY0ZpbGUoZGlzcGxheVJlY0ZpbGU6IFNwclJlY29yZGluZ0ZpbGUgfCBudWxsLGZldGNoQW5kQXBwbHlSZWNvcmRpbmdGaWxlOmJvb2xlYW49dHJ1ZSkge1xyXG4gICAgdGhpcy5kaXNwbGF5UmVjRmlsZT1kaXNwbGF5UmVjRmlsZTtcclxuICAgIGlmICh0aGlzLl9kaXNwbGF5UmVjRmlsZSkge1xyXG4gICAgICBpZih0aGlzLml0ZW1zKSB7XHJcbiAgICAgICAgdGhpcy5pdGVtcy5jdXJyZW50UmVjb3JkaW5nRmlsZSA9IHRoaXMuX2Rpc3BsYXlSZWNGaWxlO1xyXG4gICAgICB9XHJcbiAgICAgIGxldCBhZGg6IEF1ZGlvRGF0YUhvbGRlcnwgbnVsbCA9IHRoaXMuX2Rpc3BsYXlSZWNGaWxlLmF1ZGlvRGF0YUhvbGRlcjtcclxuICAgICAgaWYoYWRoKSB7XHJcbiAgICAgICAgdGhpcy5kaXNwbGF5QXVkaW9DbGlwID0gbmV3IEF1ZGlvQ2xpcChhZGgpO1xyXG4gICAgICAgIGlmKHRoaXMuX2NvbnRyb2xBdWRpb1BsYXllcikge1xyXG4gICAgICAgICAgdGhpcy5fY29udHJvbEF1ZGlvUGxheWVyLmF1ZGlvQ2xpcCA9IHRoaXMuZGlzcGxheUF1ZGlvQ2xpcDtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5zaG93UmVjb3JkaW5nKCk7XHJcbiAgICAgIH1lbHNlIHtcclxuICAgICAgICAvLyBjbGVhciBmb3Igbm93IC4uLlxyXG4gICAgICAgIHRoaXMuZGlzcGxheUF1ZGlvQ2xpcCA9IG51bGw7XHJcbiAgICAgICAgaWYodGhpcy5jb250cm9sQXVkaW9QbGF5ZXIpIHtcclxuICAgICAgICAgIHRoaXMuY29udHJvbEF1ZGlvUGxheWVyLmF1ZGlvQ2xpcCA9IG51bGw7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmKGZldGNoQW5kQXBwbHlSZWNvcmRpbmdGaWxlKSB7XHJcbiAgICAgICAgICBpZiAodGhpcy5fY29udHJvbEF1ZGlvUGxheWVyICYmIHRoaXMuX3Nlc3Npb24pIHtcclxuICAgICAgICAgICAgLy8uLi4gYW5kIHRyeSB0byBmZXRjaCBmcm9tIHNlcnZlclxyXG4gICAgICAgICAgICB0aGlzLmxpdmVMZXZlbERpc3BsYXlTdGF0ZSA9IExpdmVMZXZlbFN0YXRlLkxPQURJTkc7XHJcbiAgICAgICAgICAgIGNvbnN0IHJmID0gdGhpcy5fZGlzcGxheVJlY0ZpbGU7XHJcblxyXG4gICAgICAgICAgICBsZXQgYXVkaW9Eb3dubG9hZFR5cGUgPSB0aGlzLl9jbGllbnRBdWRpb1N0b3JhZ2VUeXBlO1xyXG4gICAgICAgICAgICBpZiAoQXVkaW9TdG9yYWdlVHlwZS5NRU1fRU5USVJFX0FVVE9fTkVUX0NIVU5LRUQgPT09IHRoaXMuX2NsaWVudEF1ZGlvU3RvcmFnZVR5cGUgfHwgQXVkaW9TdG9yYWdlVHlwZS5NRU1fQ0hVTktFRF9BVVRPX05FVF9DSFVOS0VEID09PSB0aGlzLl9jbGllbnRBdWRpb1N0b3JhZ2VUeXBlKSB7XHJcbiAgICAgICAgICAgICAgLy8gRGVmYXVsdCBpcyBuZXR3b3JrIG1vZGVcclxuICAgICAgICAgICAgICBhdWRpb0Rvd25sb2FkVHlwZSA9IEF1ZGlvU3RvcmFnZVR5cGUuTkVUX0NIVU5LRUQ7XHJcbiAgICAgICAgICAgICAgaWYgKHJmLmNoYW5uZWxzICYmIHJmLmZyYW1lcykge1xyXG4gICAgICAgICAgICAgICAgY29uc3Qgc2FtcGxlcyA9IHJmLmNoYW5uZWxzICogcmYuZnJhbWVzO1xyXG4gICAgICAgICAgICAgICAgaWYgKHNhbXBsZXMgPD0gdGhpcy5fbWF4QXV0b05ldE1lbVN0b3JlU2FtcGxlcykge1xyXG4gICAgICAgICAgICAgICAgICAvLyBCdXQgaWYgYXVkaW8gZmlsZSBpcyBzbWFsbCwgbG9hZCBpbiBjb250aW51b3VzIHJlc3AuIGNodW5rZWQgbW9kZVxyXG4gICAgICAgICAgICAgICAgICBpZiAoQXVkaW9TdG9yYWdlVHlwZS5NRU1fRU5USVJFX0FVVE9fTkVUX0NIVU5LRUQgPT09IHRoaXMuX2NsaWVudEF1ZGlvU3RvcmFnZVR5cGUpIHtcclxuICAgICAgICAgICAgICAgICAgICBhdWRpb0Rvd25sb2FkVHlwZSA9IEF1ZGlvU3RvcmFnZVR5cGUuTUVNX0VOVElSRTtcclxuICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChBdWRpb1N0b3JhZ2VUeXBlLk1FTV9DSFVOS0VEX0FVVE9fTkVUX0NIVU5LRUQgPT09IHRoaXMuX2NsaWVudEF1ZGlvU3RvcmFnZVR5cGUpIHtcclxuICAgICAgICAgICAgICAgICAgICBhdWRpb0Rvd25sb2FkVHlwZSA9IEF1ZGlvU3RvcmFnZVR5cGUuTUVNX0NIVU5LRUQ7XHJcbiAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZyhcIkF1ZGlvIGRvd25sb2FkIHR5cGU6IFwiICsgYXVkaW9Eb3dubG9hZFR5cGUpO1xyXG4gICAgICAgICAgICBpZiAoQXVkaW9TdG9yYWdlVHlwZS5EQl9DSFVOS0VEID09PSB0aGlzLl9jbGllbnRBdWRpb1N0b3JhZ2VUeXBlKSB7XHJcbiAgICAgICAgICAgICAgLy8gRmV0Y2ggY2h1bmtlZCBpbmRleGVkIGRiIGF1ZGlvIGJ1ZmZlclxyXG4gICAgICAgICAgICAgIGxldCBuZXh0SWFiOiBJbmRleGVkRGJBdWRpb0J1ZmZlciB8IG51bGwgPSBudWxsO1xyXG4gICAgICAgICAgICAgIGlmICghdGhpcy5fcGVyc2lzdGVudEF1ZGlvU3RvcmFnZVRhcmdldCkge1xyXG4gICAgICAgICAgICAgICAgdGhyb3cgRXJyb3IoJ0Vycm9yOiBQZXJzaXN0ZW50IHN0b3JhZ2UgdGFyZ2V0IG5vdCBzZXQuJyk7XHJcbiAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIC8vY29uc29sZS5kZWJ1ZyhcIkZldGNoIGF1ZGlvIGFuZCBzdG9yZSB0byBpbmRleGVkIGRiLi4uXCIpO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5hdWRpb0ZldGNoU3Vic2NyaXB0aW9uID0gdGhpcy5yZWNGaWxlU2VydmljZS5mZXRjaFNwclJlY29yZGluZ0ZpbGVJbmREYkF1ZGlvQnVmZmVyKHRoaXMuX3BlcnNpc3RlbnRBdWRpb1N0b3JhZ2VUYXJnZXQsIHRoaXMuX3Nlc3Npb24ucHJvamVjdCwgcmYpLnN1YnNjcmliZSh7XHJcbiAgICAgICAgICAgICAgICAgIG5leHQ6IChpYWIpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAvL2NvbnNvbGUuZGVidWcoXCJTZXNzaW9ubWFuYWdlcjogUmVjZWl2ZWQgaW5kZGIgYXVkaW8gYnVmZmVyOiBcIitpYWIpO1xyXG4gICAgICAgICAgICAgICAgICAgIG5leHRJYWIgPSBpYWI7XHJcbiAgICAgICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgICAgICAgIGNvbXBsZXRlOiAoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5saXZlTGV2ZWxEaXNwbGF5U3RhdGUgPSBMaXZlTGV2ZWxTdGF0ZS5SRUFEWTtcclxuICAgICAgICAgICAgICAgICAgICBsZXQgZmFiRGggPSBudWxsO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChuZXh0SWFiKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICBpZiAocmYgJiYgdGhpcy5pdGVtcykge1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgZmFiRGggPSBuZXcgQXVkaW9EYXRhSG9sZGVyKG5leHRJYWIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLml0ZW1zLnNldFNwclJlY0ZpbGVBdWRpb0RhdGEocmYsIGZhYkRoKTtcclxuICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgLy8gU2hvdWxkIGFjdHVhbGx5IGJlIGhhbmRsZWQgYnkgdGhlIGVycm9yIHJlc29sdmVyXHJcbiAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXR1c01zZyA9ICdSZWNvcmRpbmcgZmlsZSBjb3VsZCBub3QgYmUgbG9hZGVkLidcclxuICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHVzQWxlcnRUeXBlID0gJ2Vycm9yJ1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAoZmFiRGgpIHtcclxuICAgICAgICAgICAgICAgICAgICAgIC8vIHRoaXMuZGlzcGxheUF1ZGlvQ2xpcCBjb3VsZCBoYXZlIGJlZW4gY2hhbmdlZCBtZWFud2hpbGUsIGJ1dCB0aGUgcmVjb3JkZXIgdW5zdWJjcmliZXMgYmVmb3JlIGNoYW5naW5nIHRoZSBpdGVtLCB0aGVyZWZvcmUgdGhlcmUgc2hvdWxkIGJlIG5vIHJpc2sgdG8gc2V0IHRvIHdyb25nIGl0ZW1cclxuICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGlzcGxheUF1ZGlvQ2xpcCA9IG5ldyBBdWRpb0NsaXAoZmFiRGgpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBpZih0aGlzLl9jb250cm9sQXVkaW9QbGF5ZXIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2NvbnRyb2xBdWRpb1BsYXllci5hdWRpb0NsaXAgPSB0aGlzLmRpc3BsYXlBdWRpb0NsaXBcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zaG93UmVjb3JkaW5nKCk7XHJcbiAgICAgICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgICAgICAgIGVycm9yOiBlcnIgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJDb3VsZCBub3QgbG9hZCByZWNvcmRpbmcgZmlsZSBmcm9tIHNlcnZlcjogXCIgKyBlcnIpO1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMubGl2ZUxldmVsRGlzcGxheVN0YXRlID0gTGl2ZUxldmVsU3RhdGUuUkVBRFk7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0dXNNc2cgPSAnUmVjb3JkaW5nIGZpbGUgY291bGQgbm90IGJlIGxvYWRlZDogJyArIGVycjtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXR1c0FsZXJ0VHlwZSA9ICdlcnJvcic7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jaGFuZ2VEZXRlY3RvclJlZi5kZXRlY3RDaGFuZ2VzKCk7XHJcbiAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSBlbHNlIGlmIChBdWRpb1N0b3JhZ2VUeXBlLk5FVF9DSFVOS0VEID09PSBhdWRpb0Rvd25sb2FkVHlwZSkge1xyXG4gICAgICAgICAgICAgIC8vIEZldGNoIGNodW5rZWQgYXVkaW8gYnVmZmVyIGZyb20gbmV0d29ya1xyXG4gICAgICAgICAgICAgIGxldCBuZXh0TmV0QWI6IE5ldEF1ZGlvQnVmZmVyIHwgbnVsbCA9IG51bGw7XHJcblxyXG4gICAgICAgICAgICAgIC8vY29uc29sZS5kZWJ1ZyhcIkZldGNoIGNodW5rZWQgYXVkaW8gZnJvbSBuZXR3b3JrXCIpO1xyXG4gICAgICAgICAgICAgIHRoaXMuYXVkaW9GZXRjaFN1YnNjcmlwdGlvbiA9IHRoaXMucmVjRmlsZVNlcnZpY2UuZmV0Y2hTcHJSZWNvcmRpbmdGaWxlTmV0QXVkaW9CdWZmZXIoIHRoaXMuX3Nlc3Npb24ucHJvamVjdCwgcmYpLnN1YnNjcmliZSh7XHJcbiAgICAgICAgICAgICAgICBuZXh0OiAobmV0QWIpID0+IHtcclxuICAgICAgICAgICAgICAgICAgLy9jb25zb2xlLmRlYnVnKFwiU2Vzc2lvbm1hbmFnZXI6IFJlY2VpdmVkIG5ldCBhdWRpbyBidWZmZXI6IFwiK25ldEFiKTtcclxuICAgICAgICAgICAgICAgICAgbmV4dE5ldEFiID0gbmV0QWI7XHJcbiAgICAgICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAgICAgY29tcGxldGU6ICgpID0+IHtcclxuICAgICAgICAgICAgICAgICAgdGhpcy5saXZlTGV2ZWxEaXNwbGF5U3RhdGUgPSBMaXZlTGV2ZWxTdGF0ZS5SRUFEWTtcclxuICAgICAgICAgICAgICAgICAgbGV0IGZhYkRoID0gbnVsbDtcclxuICAgICAgICAgICAgICAgICAgaWYgKG5leHROZXRBYikge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChyZiAmJiB0aGlzLml0ZW1zKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICBmYWJEaCA9IG5ldyBBdWRpb0RhdGFIb2xkZXIobmV4dE5ldEFiKTtcclxuICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaXRlbXMuc2V0U3ByUmVjRmlsZUF1ZGlvRGF0YShyZiwgZmFiRGgpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAvLyBTaG91bGQgYWN0dWFsbHkgYmUgaGFuZGxlZCBieSB0aGUgZXJyb3IgcmVzb2x2ZXJcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXR1c01zZyA9ICdSZWNvcmRpbmcgZmlsZSBjb3VsZCBub3QgYmUgbG9hZGVkLidcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXR1c0FsZXJ0VHlwZSA9ICdlcnJvcidcclxuICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICBpZiAoZmFiRGgpIHtcclxuICAgICAgICAgICAgICAgICAgICAvLyB0aGlzLmRpc3BsYXlBdWRpb0NsaXAgY291bGQgaGF2ZSBiZWVuIGNoYW5nZWQgbWVhbndoaWxlLCBidXQgdGhlIHJlY29yZGVyIHVuc3ViY3JpYmVzIGJlZm9yZSBjaGFuZ2luZyB0aGUgaXRlbSwgdGhlcmVmb3JlIHRoZXJlIHNob3VsZCBiZSBubyByaXNrIHRvIHNldCB0byB3cm9uZyBpdGVtXHJcbiAgICAgICAgICAgICAgICAgICAgLy9jb25zb2xlLmRlYnVnKFwic2V0IGRpc3BsYXlSZWNGaWxlKCk6IGZldGNoIG5ldCBhYiBjb21wbGV0ZSwgc2V0IGRpc3BsYXlBdWRpb0NsaXAuXCIpXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kaXNwbGF5QXVkaW9DbGlwID0gbmV3IEF1ZGlvQ2xpcChmYWJEaCk7XHJcbiAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgaWYodGhpcy5fY29udHJvbEF1ZGlvUGxheWVyKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fY29udHJvbEF1ZGlvUGxheWVyLmF1ZGlvQ2xpcCA9IHRoaXMuZGlzcGxheUF1ZGlvQ2xpcDtcclxuICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICB0aGlzLnNob3dSZWNvcmRpbmcoKTtcclxuICAgICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgICAgICBlcnJvcjogZXJyID0+IHtcclxuICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkNvdWxkIG5vdCBsb2FkIHJlY29yZGluZyBmaWxlIGZyb20gc2VydmVyOiBcIiArIGVycik7XHJcbiAgICAgICAgICAgICAgICAgIHRoaXMubGl2ZUxldmVsRGlzcGxheVN0YXRlID0gTGl2ZUxldmVsU3RhdGUuUkVBRFk7XHJcbiAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHVzTXNnID0gJ1JlY29yZGluZyBmaWxlIGNvdWxkIG5vdCBiZSBsb2FkZWQ6ICcgKyBlcnI7XHJcbiAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHVzQWxlcnRUeXBlID0gJ2Vycm9yJztcclxuICAgICAgICAgICAgICAgICAgdGhpcy5jaGFuZ2VEZXRlY3RvclJlZi5kZXRlY3RDaGFuZ2VzKCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKEF1ZGlvU3RvcmFnZVR5cGUuTUVNX0NIVU5LRUQgPT09IGF1ZGlvRG93bmxvYWRUeXBlKSB7XHJcbiAgICAgICAgICAgICAgLy8gRmV0Y2ggY2h1bmtlZCBhcnJheSBhdWRpbyBidWZmZXJcclxuICAgICAgICAgICAgICBsZXQgbmV4dEFhYjogQXJyYXlBdWRpb0J1ZmZlciB8IG51bGwgPSBudWxsO1xyXG4gICAgICAgICAgICAgIC8vY29uc29sZS5kZWJ1ZyhcIkZldGNoIGF1ZGlvIGFuZCBzdG9yZSB0byAoY2h1bmtlZCkgYXJyYXkgYnVmZmVyLi4uXCIpO1xyXG4gICAgICAgICAgICAgIHRoaXMuYXVkaW9GZXRjaFN1YnNjcmlwdGlvbiA9IHRoaXMucmVjRmlsZVNlcnZpY2UuZmV0Y2hTcHJSZWNvcmRpbmdGaWxlQXJyYXlBdWRpb0J1ZmZlciggdGhpcy5fc2Vzc2lvbi5wcm9qZWN0LCByZikuc3Vic2NyaWJlKHtcclxuICAgICAgICAgICAgICAgIG5leHQ6IChhYWIpID0+IHtcclxuICAgICAgICAgICAgICAgICAgbmV4dEFhYiA9IGFhYjtcclxuICAgICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgICAgICBjb21wbGV0ZTogKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICB0aGlzLmxpdmVMZXZlbERpc3BsYXlTdGF0ZSA9IExpdmVMZXZlbFN0YXRlLlJFQURZO1xyXG4gICAgICAgICAgICAgICAgICBsZXQgZmFiRGggPSBudWxsO1xyXG4gICAgICAgICAgICAgICAgICBpZiAobmV4dEFhYikge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChyZiAmJiB0aGlzLml0ZW1zKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICBmYWJEaCA9IG5ldyBBdWRpb0RhdGFIb2xkZXIobmV4dEFhYik7XHJcbiAgICAgICAgICAgICAgICAgICAgICB0aGlzLml0ZW1zLnNldFNwclJlY0ZpbGVBdWRpb0RhdGEocmYsIGZhYkRoKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gU2hvdWxkIGFjdHVhbGx5IGJlIGhhbmRsZWQgYnkgdGhlIGVycm9yIHJlc29sdmVyXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0dXNNc2cgPSAnUmVjb3JkaW5nIGZpbGUgY291bGQgbm90IGJlIGxvYWRlZC4nXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0dXNBbGVydFR5cGUgPSAnZXJyb3InXHJcbiAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgaWYgKGZhYkRoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhpcy5kaXNwbGF5QXVkaW9DbGlwIGNvdWxkIGhhdmUgYmVlbiBjaGFuZ2VkIG1lYW53aGlsZSwgYnV0IHRoZSByZWNvcmRlciB1bnN1YmNyaWJlcyBiZWZvcmUgY2hhbmdpbmcgdGhlIGl0ZW0sIHRoZXJlZm9yZSB0aGVyZSBzaG91bGQgYmUgbm8gcmlzayB0byBzZXQgdG8gd3JvbmcgaXRlbVxyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGlzcGxheUF1ZGlvQ2xpcCA9IG5ldyBBdWRpb0NsaXAoZmFiRGgpO1xyXG4gICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgIGlmKHRoaXMuX2NvbnRyb2xBdWRpb1BsYXllcikge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2NvbnRyb2xBdWRpb1BsYXllci5hdWRpb0NsaXAgPSB0aGlzLmRpc3BsYXlBdWRpb0NsaXBcclxuICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICB0aGlzLnNob3dSZWNvcmRpbmcoKTtcclxuICAgICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgICAgICBlcnJvcjogZXJyID0+IHtcclxuICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkNvdWxkIG5vdCBsb2FkIHJlY29yZGluZyBmaWxlIGZyb20gc2VydmVyOiBcIiArIGVycik7XHJcbiAgICAgICAgICAgICAgICAgIHRoaXMubGl2ZUxldmVsRGlzcGxheVN0YXRlID0gTGl2ZUxldmVsU3RhdGUuUkVBRFk7XHJcbiAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHVzTXNnID0gJ1JlY29yZGluZyBmaWxlIGNvdWxkIG5vdCBiZSBsb2FkZWQ6ICcgKyBlcnI7XHJcbiAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHVzQWxlcnRUeXBlID0gJ2Vycm9yJztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgLy8gRmV0Y2ggcmVndWxhciBhdWRpbyBidWZmZXJcclxuICAgICAgICAgICAgICAvL2NvbnNvbGUuZGVidWcoXCJGZXRjaCBhdWRpbyBhbmQgc3RvcmUgdG8gYXVkaW8gYnVmZmVyLi4uXCIpO1xyXG4gICAgICAgICAgICAgIHRoaXMuYXVkaW9GZXRjaFN1YnNjcmlwdGlvbiA9IHRoaXMucmVjRmlsZVNlcnZpY2UuZmV0Y2hTcHJSZWNvcmRpbmdGaWxlQXVkaW9CdWZmZXIoIHRoaXMuX3Nlc3Npb24ucHJvamVjdCwgcmYpLnN1YnNjcmliZSh7XHJcbiAgICAgICAgICAgICAgICBuZXh0OiAoYWIpID0+IHtcclxuICAgICAgICAgICAgICAgICAgdGhpcy5saXZlTGV2ZWxEaXNwbGF5U3RhdGUgPSBMaXZlTGV2ZWxTdGF0ZS5SRUFEWTtcclxuICAgICAgICAgICAgICAgICAgbGV0IGZhYkRoID0gbnVsbDtcclxuICAgICAgICAgICAgICAgICAgaWYgKGFiKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJmICYmIHRoaXMuaXRlbXMpIHtcclxuICAgICAgICAgICAgICAgICAgICAgIGlmIChTZXNzaW9uTWFuYWdlci5GT1JDRV9BUlJSQVlfQVVESU9fQlVGRkVSKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBhYWIgPSBBcnJheUF1ZGlvQnVmZmVyLmZyb21BdWRpb0J1ZmZlcihhYik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZhYkRoID0gbmV3IEF1ZGlvRGF0YUhvbGRlcihhYWIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZmFiRGggPSBuZXcgQXVkaW9EYXRhSG9sZGVyKG5ldyBBdWRpb0J1ZmZlclNvdXJjZShhYikpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgdGhpcy5pdGVtcy5zZXRTcHJSZWNGaWxlQXVkaW9EYXRhKHJmLCBmYWJEaCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIFNob3VsZCBhY3R1YWxseSBiZSBoYW5kbGVkIGJ5IHRoZSBlcnJvciByZXNvbHZlclxyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHVzTXNnID0gJ1JlY29yZGluZyBmaWxlIGNvdWxkIG5vdCBiZSBsb2FkZWQuJ1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHVzQWxlcnRUeXBlID0gJ2Vycm9yJ1xyXG4gICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgIGlmIChmYWJEaCkge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIHRoaXMuZGlzcGxheUF1ZGlvQ2xpcCBjb3VsZCBoYXZlIGJlZW4gY2hhbmdlZCBtZWFud2hpbGUsIGJ1dCB0aGUgcmVjb3JkZXIgdW5zdWJjcmliZXMgYmVmb3JlIGNoYW5naW5nIHRoZSBpdGVtLCB0aGVyZWZvcmUgdGhlcmUgc2hvdWxkIGJlIG5vIHJpc2sgdG8gc2V0IHRvIHdyb25nIGl0ZW1cclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmRpc3BsYXlBdWRpb0NsaXAgPSBuZXcgQXVkaW9DbGlwKGZhYkRoKTtcclxuICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICBpZih0aGlzLl9jb250cm9sQXVkaW9QbGF5ZXIpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9jb250cm9sQXVkaW9QbGF5ZXIuYXVkaW9DbGlwID0gdGhpcy5kaXNwbGF5QXVkaW9DbGlwXHJcbiAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgdGhpcy5zaG93UmVjb3JkaW5nKCk7XHJcbiAgICAgICAgICAgICAgICB9LCBlcnJvcjogZXJyID0+IHtcclxuICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkNvdWxkIG5vdCBsb2FkIHJlY29yZGluZyBmaWxlIGZyb20gc2VydmVyOiBcIiArIGVycik7XHJcbiAgICAgICAgICAgICAgICAgIHRoaXMubGl2ZUxldmVsRGlzcGxheVN0YXRlID0gTGl2ZUxldmVsU3RhdGUuUkVBRFk7XHJcbiAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHVzTXNnID0gJ1JlY29yZGluZyBmaWxlIGNvdWxkIG5vdCBiZSBsb2FkZWQ6ICcgKyBlcnI7XHJcbiAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHVzQWxlcnRUeXBlID0gJ2Vycm9yJztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgdGhpcy5zdGF0dXNNc2cgPSAnUmVjb3JkaW5nIGZpbGUgY291bGQgbm90IGJlIGRlY29kZWQuIEF1ZGlvIGNvbnRleHQgdW5hdmFpbGFibGUuJ1xyXG4gICAgICAgICAgICB0aGlzLnN0YXR1c0FsZXJ0VHlwZSA9ICdlcnJvcidcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLmRpc3BsYXlBdWRpb0NsaXAgPSBudWxsO1xyXG4gICAgICBpZih0aGlzLmNvbnRyb2xBdWRpb1BsYXllcikge1xyXG4gICAgICAgIHRoaXMuY29udHJvbEF1ZGlvUGxheWVyLmF1ZGlvQ2xpcCA9IG51bGw7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIGdldCBkaXNwbGF5UmVjRmlsZSgpOiBTcHJSZWNvcmRpbmdGaWxlIHwgbnVsbCB7XHJcbiAgICByZXR1cm4gdGhpcy5fZGlzcGxheVJlY0ZpbGU7XHJcbiAgfVxyXG5cclxuICBpc1JlY29yZGluZ0l0ZW0oKTpib29sZWFue1xyXG4gICAgcmV0dXJuKHRoaXMucHJvbXB0SXRlbSE9bnVsbCAmJiB0aGlzLnByb21wdEl0ZW0udHlwZSE9PSdub25yZWNvcmRpbmcnKVxyXG4gIH1cclxuXHJcbiAgdXBkYXRlU3RhcnRBY3Rpb25EaXNhYmxlU3RhdGUoKXtcclxuICAgIHRoaXMudHJhbnNwb3J0QWN0aW9ucy5zdGFydEFjdGlvbi5kaXNhYmxlZD0hKHRoaXMuYWMgICYmIHRoaXMuaXNSZWNvcmRpbmdJdGVtKCkpO1xyXG4gIH1cclxuXHJcbiAgYXBwbHlJdGVtKHRlbXBvcmFyeT1mYWxzZSkge1xyXG5cclxuICAgIHRoaXMuc2VjdGlvbiA9IHRoaXMuX3NjcmlwdC5zZWN0aW9uc1t0aGlzLnNlY3RJZHhdXHJcbiAgICB0aGlzLmdyb3VwID0gdGhpcy5zZWN0aW9uLl9zaHVmZmxlZEdyb3Vwc1t0aGlzLmdyb3VwSWR4SW5TZWN0aW9uXTtcclxuICAgIHRoaXMucHJvbXB0SXRlbSA9IHRoaXMuZ3JvdXAuX3NodWZmbGVkUHJvbXB0SXRlbXNbdGhpcy5wcm9tcHRJdGVtSWR4SW5Hcm91cF07XHJcblxyXG4gICAgLy90aGlzLnNlbGVjdGVkSXRlbUlkeCA9IHRoaXMucHJvbXB0SW5kZXg7XHJcblxyXG4gICAgaWYodGhpcy5hdWRpb0ZldGNoU3Vic2NyaXB0aW9uKXtcclxuICAgICAgLy9jb25zb2xlLmRlYnVnKFwiVW5zdWJzY3JpYmUgZnJvbSBhdWRpbyBmZXRjaC5cIik7XHJcbiAgICAgIHRoaXMuYXVkaW9GZXRjaFN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xyXG4gICAgfVxyXG4gICAgaWYgKCF0ZW1wb3JhcnkpIHtcclxuICAgICAgdGhpcy5kaXNwbGF5QXVkaW9DbGlwPW51bGw7XHJcbiAgICAgIHRoaXMuc2hvd1JlY29yZGluZygpO1xyXG4gICAgfVxyXG4gICAgdGhpcy5saXZlTGV2ZWxEaXNwbGF5U3RhdGU9TGl2ZUxldmVsU3RhdGUuUkVBRFk7XHJcblxyXG4gICAgdGhpcy5jbGVhclByb21wdCgpO1xyXG5cclxuICAgIGNvbnN0IGlzTm9ucmVjb3JkaW5nPSh0aGlzLnByb21wdEl0ZW0udHlwZT09PSdub25yZWNvcmRpbmcnKTtcclxuXHJcbiAgICBpZiAoaXNOb25yZWNvcmRpbmcgfHwgIXRoaXMuc2VjdGlvbi5wcm9tcHRwaGFzZSB8fCB0aGlzLnNlY3Rpb24ucHJvbXB0cGhhc2UgPT09ICdJRExFJykge1xyXG4gICAgICB0aGlzLmFwcGx5UHJvbXB0KCk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYoaXNOb25yZWNvcmRpbmcpe1xyXG4gICAgICB0aGlzLnVwZGF0ZURpc3BsYXlSZWNGaWxlKG51bGwpO1xyXG4gICAgICB0aGlzLmRpc3BsYXlSZWNGaWxlVmVyc2lvbiA9IDA7XHJcbiAgICAgIHRoaXMuc3RhcnRTdG9wU2lnbmFsU3RhdGUgPSBTdGFydFN0b3BTaWduYWxTdGF0ZS5PRkY7XHJcbiAgICB9ZWxzZSB7XHJcbiAgICAgIGlmICh0aGlzLml0ZW1zKSB7XHJcbiAgICAgICAgbGV0IGl0ID0gdGhpcy5pdGVtcy5nZXRJdGVtKHRoaXMucHJvbXB0SW5kZXgpO1xyXG4gICAgICAgIGlmICghaXQucmVjcykge1xyXG4gICAgICAgICAgaXQucmVjcyA9IG5ldyBBcnJheTxTcHJSZWNvcmRpbmdGaWxlPigpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgbGV0IHJlY2VudFJlY0ZpbGU6IFNwclJlY29yZGluZ0ZpbGUgfCBudWxsID0gbnVsbDtcclxuICAgICAgICBsZXQgYXZhaWxSZWNmaWxlczogbnVtYmVyID0gaXQucmVjcy5sZW5ndGg7XHJcbiAgICAgICAgaWYgKGF2YWlsUmVjZmlsZXMgPiAwKSB7XHJcbiAgICAgICAgICBsZXQgcmZWZXJzOiBudW1iZXIgPSBhdmFpbFJlY2ZpbGVzIC0gMTtcclxuICAgICAgICAgIHJlY2VudFJlY0ZpbGUgPSBpdC5yZWNzW3JmVmVyc107XHJcbiAgICAgICAgICB0aGlzLnVwZGF0ZURpc3BsYXlSZWNGaWxlKHJlY2VudFJlY0ZpbGUsIXRlbXBvcmFyeSk7XHJcbiAgICAgICAgICB0aGlzLmRpc3BsYXlSZWNGaWxlVmVyc2lvbiA9IHJmVmVycztcclxuXHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHRoaXMudXBkYXRlRGlzcGxheVJlY0ZpbGUobnVsbCk7XHJcbiAgICAgICAgICB0aGlzLmRpc3BsYXlSZWNGaWxlVmVyc2lvbiA9IDA7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICAgIGlmKCF0aGlzLnJlYWRvbmx5KSB7XHJcbiAgICAgICAgdGhpcy5zdGFydFN0b3BTaWduYWxTdGF0ZSA9IFN0YXJ0U3RvcFNpZ25hbFN0YXRlLklETEU7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIC8vIGNvbnNvbGUuZGVidWcoXCJhcHBseUl0ZW0oKTogdGVtcG9yYXJ5OiBcIit0ZW1wb3JhcnkpO1xyXG4gICAgLy9pZiAoIXRlbXBvcmFyeSkge1xyXG4gICAgLy8gICBjb25zb2xlLmRlYnVnKFwiYXBwbHlJdGVtKCk6IENhbGwgc2hvd1JlY29yZGluZygpOiBkaXNwbGF5QXVkaW9DbGlwOiBcIit0aGlzLmRpc3BsYXlBdWRpb0NsaXApO1xyXG4gICAgICAvL3RoaXMuc2hvd1JlY29yZGluZygpO1xyXG4gICAgLy99XHJcbiAgICB0aGlzLnVwZGF0ZVN0YXJ0QWN0aW9uRGlzYWJsZVN0YXRlKClcclxuICAgIHRoaXMudXBkYXRlTmF2aWdhdGlvbkFjdGlvbnMoKVxyXG4gIH1cclxuXHJcblxyXG4gIHN0YXJ0KCkge1xyXG4gICAgc3VwZXIuc3RhcnQoKTtcclxuICAgIGlmKHRoaXMucHJvbXB0SXRlbUNvdW50PjApIHtcclxuICAgICAgdGhpcy5wcm9tcHRJbmRleCA9IDA7XHJcbiAgICB9XHJcbiAgICB0aGlzLmVuYWJsZU5hdmlnYXRpb24oKVxyXG4gIH1cclxuXHJcbiAgaXNSZWNvcmRpbmcoKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gKHRoaXMuc3RhdHVzID09PSBTdGF0dXMuUFJFX1JFQ09SRElORyB8fCB0aGlzLnN0YXR1cyA9PT0gU3RhdHVzLlJFQ09SRElORyB8fCB0aGlzLnN0YXR1cyA9PT0gU3RhdHVzLlBPU1RfUkVDX1NUT1AgfHwgdGhpcy5zdGF0dXMgPT09IFN0YXR1cy5QT1NUX1JFQ19QQVVTRSB8fCB0aGlzLnN0YXR1cz09PVN0YXR1cy5TVE9QUElOR19TVE9QKTtcclxuICB9XHJcblxyXG4gIGlzQWN0aXZlKCk6IGJvb2xlYW57XHJcbiAgICByZXR1cm4gKCEodGhpcy5zdGF0dXMgPT09IFN0YXR1cy5CTE9DS0VEIHx8IHRoaXMuc3RhdHVzPT09IFN0YXR1cy5JRExFIHx8IHRoaXMuc3RhdHVzPT09U3RhdHVzLkVSUk9SKSB8fCB0aGlzLnByb2Nlc3NpbmdSZWNvcmRpbmcgfHwgdGhpcy5zZXNzaW9uU2VydmljZS51cGxvYWRDb3VudD4wKVxyXG4gIH1cclxuXHJcbiAgICBwcmV2SXRlbSgpIHtcclxuICAgICAgIGxldCBuZXdQcklkeD10aGlzLl9wcm9tcHRJbmRleDtcclxuICAgICAgIG5ld1BySWR4LS07XHJcbiAgICAgICBpZihuZXdQcklkeDwwKXtcclxuICAgICAgICAgbmV3UHJJZHg9dGhpcy5wcm9tcHRJdGVtQ291bnQtMTtcclxuICAgICAgIH1cclxuICAgICAgIHRoaXMucHJvbXB0SW5kZXg9bmV3UHJJZHg7XHJcbiAgICAgIC8vdGhpcy51cGRhdGVOYXZpZ2F0aW9uQWN0aW9ucygpXHJcbiAgICB9XHJcblxyXG5cclxuICBuZXh0SXRlbSgpIHtcclxuICAgIGxldCBuZXdQcklkeD10aGlzLl9wcm9tcHRJbmRleDtcclxuICAgIG5ld1BySWR4Kys7XHJcbiAgICBpZihuZXdQcklkeD49dGhpcy5wcm9tcHRJdGVtQ291bnQpe1xyXG4gICAgICBuZXdQcklkeD0wO1xyXG4gICAgfVxyXG4gICAgdGhpcy5wcm9tcHRJbmRleD1uZXdQcklkeDtcclxuICAgIC8vdGhpcy51cGRhdGVOYXZpZ2F0aW9uQWN0aW9ucygpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSB1cGRhdGVOYXZpZ2F0aW9uQWN0aW9ucygpe1xyXG4gICAgbGV0IGZ3ZE54dEFjdGlvbkRpc2FibGVkPXRydWU7XHJcbiAgICBpZih0aGlzLml0ZW1zKXtcclxuICAgICAgbGV0IGN1cnJSZWNzPXRoaXMuaXRlbXMuZ2V0SXRlbSh0aGlzLl9wcm9tcHRJbmRleCkucmVjcztcclxuICAgICAgZndkTnh0QWN0aW9uRGlzYWJsZWQ9ICEgKGN1cnJSZWNzIT1udWxsICYmIGN1cnJSZWNzLmxlbmd0aD4wKTtcclxuICAgIH1cclxuICAgIHRoaXMudHJhbnNwb3J0QWN0aW9ucy5md2ROZXh0QWN0aW9uLmRpc2FibGVkID0gdGhpcy5uYXZpZ2F0aW9uRGlzYWJsZWQgfHwgZndkTnh0QWN0aW9uRGlzYWJsZWQ7XHJcbiAgICB0aGlzLnRyYW5zcG9ydEFjdGlvbnMuZndkQWN0aW9uLmRpc2FibGVkID0gdGhpcy5uYXZpZ2F0aW9uRGlzYWJsZWQ7XHJcbiAgICB0aGlzLnRyYW5zcG9ydEFjdGlvbnMuYndkQWN0aW9uLmRpc2FibGVkID0gdGhpcy5uYXZpZ2F0aW9uRGlzYWJsZWQ7XHJcbiAgfVxyXG5cclxuICBuZXh0VW5yZWNvcmRlZEl0ZW0oKSB7XHJcbiAgICBsZXQgbmV3UHJJZHggPSB0aGlzLl9wcm9tcHRJbmRleDtcclxuICAgIG5ld1BySWR4Kys7XHJcbiAgICBpZiAobmV3UHJJZHggPj0gdGhpcy5wcm9tcHRJdGVtQ291bnQpIHtcclxuICAgICAgbmV3UHJJZHggPSAwO1xyXG4gICAgfVxyXG4gICAgaWYodGhpcy5pdGVtcyE9bnVsbCkge1xyXG4gICAgICBsZXQgaXQ9dGhpcy5pdGVtcy5nZXRJdGVtKG5ld1BySWR4KTtcclxuICAgICAgd2hpbGUgKCghaXQucmVjb3JkaW5nIHx8IGl0Lml0ZW1Eb25lKCkpICYmIG5ld1BySWR4IDwgdGhpcy5wcm9tcHRJdGVtQ291bnQpIHtcclxuICAgICAgICBuZXdQcklkeCsrO1xyXG4gICAgICAgIGl0PXRoaXMuaXRlbXMuZ2V0SXRlbShuZXdQcklkeCk7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKCFpdC5pdGVtRG9uZSgpKSB7XHJcbiAgICAgICAgdGhpcy5wcm9tcHRJbmRleCA9IG5ld1BySWR4O1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBlbmFibGVTdGFydFVzZXJHZXN0dXJlKCkge1xyXG4gICAgc3VwZXIuZW5hYmxlU3RhcnRVc2VyR2VzdHVyZSgpO1xyXG4gICAgdGhpcy50cmFuc3BvcnRBY3Rpb25zLnN0YXJ0QWN0aW9uLmRpc2FibGVkPSEodGhpcy5hYyAmJiB0aGlzLmlzUmVjb3JkaW5nSXRlbSgpKTtcclxuICB9XHJcblxyXG4gIGVuYWJsZU5hdmlnYXRpb24oKXtcclxuICAgIHRoaXMubmF2aWdhdGlvbkRpc2FibGVkPWZhbHNlO1xyXG4gICAgdGhpcy51cGRhdGVOYXZpZ2F0aW9uQWN0aW9ucygpO1xyXG4gIH1cclxuXHJcbiAgc3RhcnRlZCgpIHtcclxuICAgIGxldCBpYyA9IHRoaXMucHJvbXB0SXRlbS5pdGVtY29kZTtcclxuICAgIGxldCByZj1udWxsO1xyXG5cclxuICAgIGlmICh0aGlzLl9zZXNzaW9uICYmIGljKSB7XHJcbiAgICAgIGxldCBzZXNzSWQ6IHN0cmluZyB8IG51bWJlciA9IHRoaXMuX3Nlc3Npb24uc2Vzc2lvbklkO1xyXG4gICAgICBsZXQgY3BJZHggPSB0aGlzLnByb21wdEluZGV4O1xyXG4gICAgICBpZiAodGhpcy5pdGVtcykge1xyXG4gICAgICAgIGxldCBpdCA9IHRoaXMuaXRlbXMuZ2V0SXRlbShjcElkeCk7XHJcbiAgICAgICAgaWYgKCFpdC5yZWNzKSB7XHJcbiAgICAgICAgICBpdC5yZWNzID0gbmV3IEFycmF5PFNwclJlY29yZGluZ0ZpbGU+KCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJmID0gbmV3IFNwclJlY29yZGluZ0ZpbGUoc2Vzc0lkLCBpYywgaXQucmVjcy5sZW5ndGgsbnVsbCk7XHJcbiAgICAgICAgcmYudXVpZD10aGlzLnJmVXVpZDtcclxuICAgICAgICAvL2l0LnJlY3MucHVzaChyZik7XHJcbiAgICAgICAgdGhpcy5pdGVtcy5hZGRTcHJSZWNGaWxlKGl0LHJmKTtcclxuICAgICAgICB0aGlzLml0ZW1zLmN1cnJlbnRSZWNvcmRpbmdGaWxlPXJmO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICB0aGlzLl9yZWNvcmRpbmdGaWxlID0gcmY7XHJcbiAgICB0aGlzLnN0YXR1cyA9IFN0YXR1cy5QUkVfUkVDT1JESU5HO1xyXG4gICAgc3VwZXIuc3RhcnRlZCgpO1xyXG5cclxuICAgIHRoaXMuc3RhcnRTdG9wU2lnbmFsU3RhdGUgPSBTdGFydFN0b3BTaWduYWxTdGF0ZS5QUkVSRUNPUkRJTkc7XHJcbiAgICBpZih0aGlzLl9zZXNzaW9uKSB7XHJcbiAgICAgIGlmICh0aGlzLl9zZXNzaW9uLnN0YXR1cyA9PT0gXCJMT0FERURcIikge1xyXG4gICAgICAgIGxldCBib2R5OiBhbnkgPSB7fTtcclxuICAgICAgICBpZiAodGhpcy5zZWN0aW9uLnRyYWluaW5nKSB7XHJcbiAgICAgICAgICB0aGlzLl9zZXNzaW9uLnN0YXR1cyA9IFwiU1RBUlRFRF9UUkFJTklOR1wiXHJcbiAgICAgICAgICBib2R5LnN0YXR1cyA9IHRoaXMuX3Nlc3Npb24uc3RhdHVzO1xyXG4gICAgICAgICAgaWYgKCF0aGlzLl9zZXNzaW9uLnN0YXJ0ZWRUcmFpbmluZ0RhdGUpIHtcclxuICAgICAgICAgICAgdGhpcy5fc2Vzc2lvbi5zdGFydGVkVHJhaW5pbmdEYXRlID0gbmV3IERhdGUoKTtcclxuICAgICAgICAgICAgYm9keS5zdGFydGVkVHJhaW5pbmdEYXRlID0gdGhpcy5fc2Vzc2lvbi5zdGFydGVkVHJhaW5pbmdEYXRlO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB0aGlzLl9zZXNzaW9uLnN0YXR1cyA9IFwiU1RBUlRFRFwiXHJcbiAgICAgICAgICBib2R5LnN0YXR1cyA9IHRoaXMuX3Nlc3Npb24uc3RhdHVzO1xyXG4gICAgICAgICAgaWYgKCF0aGlzLl9zZXNzaW9uLnN0YXJ0ZWREYXRlKSB7XHJcbiAgICAgICAgICAgIHRoaXMuX3Nlc3Npb24uc3RhcnRlZERhdGUgPSBuZXcgRGF0ZSgpO1xyXG4gICAgICAgICAgICBib2R5LnN0YXJ0ZWREYXRlID0gdGhpcy5fc2Vzc2lvbi5zdGFydGVkRGF0ZTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5zZXNzaW9uU2VydmljZS5wYXRjaFNlc3Npb25PYnNlcnZlcih0aGlzLl9zZXNzaW9uLCBib2R5KS5zdWJzY3JpYmUoKVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICBpZiAodGhpcy5zZWN0aW9uLnByb21wdHBoYXNlID09PSAnUFJFUkVDT1JESU5HJyB8fCB0aGlzLnNlY3Rpb24ucHJvbXB0cGhhc2UgPT09ICdQUkVSRUNPUkRJTkdPTkxZJykge1xyXG4gICAgICB0aGlzLmFwcGx5UHJvbXB0KCk7XHJcbiAgICB9XHJcbiAgICB0aGlzLnN0YXR1c0FsZXJ0VHlwZSA9ICdpbmZvJztcclxuICAgIHRoaXMuc3RhdHVzTXNnID0gJ1JlY29yZGluZy4uLic7XHJcblxyXG4gICAgbGV0IHByZURlbGF5ID0gREVGQVVMVF9QUkVfUkVDX0RFTEFZO1xyXG4gICAgaWYgKHRoaXMucHJvbXB0SXRlbS5wcmVyZWNkZWxheSE9bnVsbCkge1xyXG4gICAgICBwcmVEZWxheSA9IHRoaXMucHJvbXB0SXRlbS5wcmVyZWNkZWxheTtcclxuICAgIH1lbHNlIGlmICh0aGlzLnByb21wdEl0ZW0ucHJlcmVjb3JkaW5nIT1udWxsKSB7XHJcbiAgICAgIHByZURlbGF5ID0gdGhpcy5wcm9tcHRJdGVtLnByZXJlY29yZGluZztcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLnBvc3REZWxheT1ERUZBVUxUX1BPU1RfUkVDX0RFTEFZO1xyXG4gICAgaWYodGhpcy5wcm9tcHRJdGVtLnBvc3RyZWNkZWxheSE9bnVsbCl7XHJcbiAgICAgIHRoaXMucG9zdERlbGF5PXRoaXMucHJvbXB0SXRlbS5wb3N0cmVjZGVsYXk7XHJcbiAgICB9ZWxzZSBpZih0aGlzLnByb21wdEl0ZW0ucG9zdHJlY29yZGluZyE9bnVsbCl7XHJcbiAgICAgIHRoaXMucG9zdERlbGF5PXRoaXMucHJvbXB0SXRlbS5wb3N0cmVjb3JkaW5nO1xyXG4gICAgfVxyXG5cclxuICAgIGxldCBtYXhSZWNvcmRpbmdUaW1lTXMgPSBNQVhfUkVDT1JESU5HX1RJTUVfTVM7XHJcbiAgICBpZiAodGhpcy5wcm9tcHRJdGVtLnJlY2R1cmF0aW9uIT09bnVsbCAmJiB0aGlzLnByb21wdEl0ZW0ucmVjZHVyYXRpb24hPT11bmRlZmluZWQpIHtcclxuICAgICAgbWF4UmVjb3JkaW5nVGltZU1zID0gcHJlRGVsYXkrdGhpcy5wcm9tcHRJdGVtLnJlY2R1cmF0aW9uK3RoaXMucG9zdERlbGF5O1xyXG4gICAgfVxyXG4gICAgdGhpcy5tYXhSZWNUaW1lcklkID0gd2luZG93LnNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICB0aGlzLnN0b3BSZWNvcmRpbmdNYXhSZWMoKVxyXG4gICAgfSwgbWF4UmVjb3JkaW5nVGltZU1zKTtcclxuICAgIHRoaXMubWF4UmVjVGltZXJSdW5uaW5nID0gdHJ1ZTtcclxuXHJcblxyXG5cclxuICAgIHRoaXMucHJlUmVjVGltZXJJZCA9IHdpbmRvdy5zZXRUaW1lb3V0KCgpID0+IHtcclxuXHJcbiAgICAgIHRoaXMucHJlUmVjVGltZXJSdW5uaW5nID0gZmFsc2U7XHJcbiAgICAgIHRoaXMuc3RhdHVzID0gU3RhdHVzLlJFQ09SRElORztcclxuICAgICAgdGhpcy5zdGFydFN0b3BTaWduYWxTdGF0ZSA9IFN0YXJ0U3RvcFNpZ25hbFN0YXRlLlJFQ09SRElORztcclxuICAgICAgaWYgKHRoaXMuc2VjdGlvbi5tb2RlID09PSAnQVVUT1JFQ09SRElORycpIHtcclxuICAgICAgICB0aGlzLnRyYW5zcG9ydEFjdGlvbnMubmV4dEFjdGlvbi5kaXNhYmxlZCA9IGZhbHNlO1xyXG4gICAgICAgIHRoaXMudHJhbnNwb3J0QWN0aW9ucy5wYXVzZUFjdGlvbi5kaXNhYmxlZCA9IGZhbHNlO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMudHJhbnNwb3J0QWN0aW9ucy5zdG9wQWN0aW9uLmRpc2FibGVkID0gZmFsc2U7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKHRoaXMuc2VjdGlvbi5wcm9tcHRwaGFzZSA9PT0gJ1JFQ09SRElORycpIHtcclxuICAgICAgICB0aGlzLmFwcGx5UHJvbXB0KCk7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKHRoaXMuc2VjdGlvbi5wcm9tcHRwaGFzZSA9PT0gJ1BSRVJFQ09SRElOR09OTFknKXtcclxuICAgICAgICB0aGlzLmNsZWFyUHJvbXB0KCk7XHJcbiAgICAgIH1cclxuXHJcbiAgICB9LCBwcmVEZWxheSk7XHJcbiAgICB0aGlzLnByZVJlY1RpbWVyUnVubmluZyA9IHRydWU7XHJcbiAgfVxyXG5cclxuICBzdG9wSXRlbSgpIHtcclxuICAgIHRoaXMuc3RhdHVzID0gU3RhdHVzLlBPU1RfUkVDX1NUT1A7XHJcbiAgICB0aGlzLnN0YXJ0U3RvcFNpZ25hbFN0YXRlID0gU3RhcnRTdG9wU2lnbmFsU3RhdGUuUE9TVFJFQ09SRElORztcclxuICAgIHRoaXMudHJhbnNwb3J0QWN0aW9ucy5zdG9wQWN0aW9uLmRpc2FibGVkID0gdHJ1ZTtcclxuICAgIHRoaXMudHJhbnNwb3J0QWN0aW9ucy5uZXh0QWN0aW9uLmRpc2FibGVkID0gdHJ1ZTtcclxuICAgIHRoaXMuY2xlYXJQcmVSZWNUaW1lcigpO1xyXG4gICAgdGhpcy5wb3N0UmVjVGltZXJJZCA9IHdpbmRvdy5zZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgdGhpcy5wb3N0UmVjVGltZXJSdW5uaW5nID0gZmFsc2U7XHJcbiAgICAgIHRoaXMuc3RhdHVzID0gU3RhdHVzLlNUT1BQSU5HX1NUT1A7XHJcbiAgICAgIHRoaXMuc3RvcFJlY29yZGluZygpO1xyXG4gICAgfSwgdGhpcy5wb3N0RGVsYXkpO1xyXG4gICAgdGhpcy5wb3N0UmVjVGltZXJSdW5uaW5nID0gdHJ1ZTtcclxuICB9XHJcblxyXG4gIHBhdXNlSXRlbSgpIHtcclxuICAgIHRoaXMuc3RhdHVzID0gU3RhdHVzLlBPU1RfUkVDX1BBVVNFO1xyXG4gICAgdGhpcy50cmFuc3BvcnRBY3Rpb25zLnBhdXNlQWN0aW9uLmRpc2FibGVkID0gdHJ1ZTtcclxuICAgIHRoaXMuc3RhcnRTdG9wU2lnbmFsU3RhdGUgPSBTdGFydFN0b3BTaWduYWxTdGF0ZS5QT1NUUkVDT1JESU5HO1xyXG4gICAgdGhpcy50cmFuc3BvcnRBY3Rpb25zLnN0b3BBY3Rpb24uZGlzYWJsZWQgPSB0cnVlO1xyXG4gICAgdGhpcy50cmFuc3BvcnRBY3Rpb25zLm5leHRBY3Rpb24uZGlzYWJsZWQgPSB0cnVlO1xyXG4gICAgdGhpcy50cmFuc3BvcnRBY3Rpb25zLnBhdXNlQWN0aW9uLmRpc2FibGVkID0gdHJ1ZTtcclxuICAgIHRoaXMuY2xlYXJQcmVSZWNUaW1lcigpO1xyXG4gICAgdGhpcy5wb3N0UmVjVGltZXJJZCA9IHdpbmRvdy5zZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgdGhpcy5wb3N0UmVjVGltZXJSdW5uaW5nID0gZmFsc2U7XHJcbiAgICAgIHRoaXMuc3RhdHVzID0gU3RhdHVzLlNUT1BQSU5HX1BBVVNFO1xyXG4gICAgICB0aGlzLnN0b3BSZWNvcmRpbmcoKTtcclxuICAgIH0sIHRoaXMucG9zdERlbGF5KTtcclxuICAgIHRoaXMucG9zdFJlY1RpbWVyUnVubmluZyA9IHRydWU7XHJcbiAgfVxyXG5cclxuICBzdG9wUmVjb3JkaW5nKCkge1xyXG4gICAgdGhpcy5jbGVhck1heFJlY1RpbWVyKCk7XHJcbiAgICBpZih0aGlzLmFjKSB7XHJcbiAgICAgIHRoaXMuYWMuc3RvcCgpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgc3RvcFJlY29yZGluZ01heFJlYygpe1xyXG4gICAgdGhpcy5jbGVhclByZVJlY1RpbWVyKCk7XHJcbiAgICB0aGlzLmNsZWFyUG9zdFJlY1RpbWVyKCk7XHJcbiAgICB0aGlzLm1heFJlY1RpbWVyUnVubmluZyA9IGZhbHNlO1xyXG4gICAgdGhpcy5zdGF0dXMgPSBTdGF0dXMuU1RPUFBJTkdfU1RPUDtcclxuICAgIGlmKHRoaXMuYWMpIHtcclxuICAgICAgdGhpcy5hYy5zdG9wKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBhZGRSZWNvcmRpbmdGaWxlQnlEZXNjcmlwdG9yKHJmZDpSZWNvcmRpbmdGaWxlRGVzY3JpcHRvckltcGwpe1xyXG4gICAgaWYocmZkLnJlY29yZGluZyAmJiByZmQucmVjb3JkaW5nLml0ZW1jb2RlKSB7XHJcbiAgICAgIGxldCBwcklkeCA9IHRoaXMucHJvbXB0SW5kZXhCeUl0ZW1jb2RlKHJmZC5yZWNvcmRpbmcuaXRlbWNvZGUpO1xyXG4gICAgICBpZiAodGhpcy5pdGVtcyE9bnVsbCAmJiBwcklkeCAhPT0gbnVsbCkge1xyXG4gICAgICAgIGxldCBpdCA9IHRoaXMuaXRlbXMuZ2V0SXRlbShwcklkeCk7XHJcbiAgICAgICAgaWYgKGl0ICYmIHRoaXMuX3Nlc3Npb24pIHtcclxuICAgICAgICAgIC8vIGlmICghaXQucmVjcykge1xyXG4gICAgICAgICAgLy8gICBpdC5yZWNzID0gbmV3IEFycmF5PFNwclJlY29yZGluZ0ZpbGU+KCk7XHJcbiAgICAgICAgICAvLyB9XHJcbiAgICAgICAgICBsZXQgcmYgPSBuZXcgU3ByUmVjb3JkaW5nRmlsZSh0aGlzLl9zZXNzaW9uLnNlc3Npb25JZCwgcmZkLnJlY29yZGluZy5pdGVtY29kZSwgcmZkLnZlcnNpb24sIG51bGwpO1xyXG4gICAgICAgICAgcmYuc2VydmVyUGVyc2lzdGVkPXRydWU7XHJcbiAgICAgICAgICAvL2NvbnNvbGUuZGVidWcoXCJhZGRSZWNvcmRpbmdGaWxlQnlEZXNjcmlwdG9yKCk6IHNyOiBcIityZmQuc2FtcGxlcmF0ZStcIiwgZnJhbWVzOiBcIityZmQuZnJhbWVzKTtcclxuICAgICAgICAgIGlmKHJmZC5zYW1wbGVyYXRlICYmIHJmZC5mcmFtZXMpe1xyXG4gICAgICAgICAgICByZi5zYW1wbGVyYXRlPXJmZC5zYW1wbGVyYXRlO1xyXG4gICAgICAgICAgICByZi5mcmFtZXM9cmZkLmZyYW1lcztcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIGlmKHJmZC5jaGFubmVscyl7XHJcbiAgICAgICAgICAgIHJmLmNoYW5uZWxzPXJmZC5jaGFubmVscztcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIHRoaXMuaXRlbXMuYWRkU3ByUmVjRmlsZShpdCxyZik7XHJcblxyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAvL2NvbnNvbGUuZGVidWcoXCJXQVJOOiBObyByZWNvcmRpbmcgaXRlbSB3aXRoIGNvZGU6IFxcXCJcIiArcmZkLnJlY29yZGluZy5pdGVtY29kZSsgXCJcXFwiIGZvdW5kLlwiKTtcclxuICAgICAgICB9XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgLy9jb25zb2xlLmRlYnVnKFwiV0FSTjogTm8gcmVjb3JkaW5nIGl0ZW0gd2l0aCBjb2RlOiBcXFwiXCIgK3JmZC5yZWNvcmRpbmcuaXRlbWNvZGUrIFwiXFxcIiBmb3VuZC5cIik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8vIGFkZFJlY29yZGluZ0ZpbGVCeVByb21wdEluZGV4KHByb21wdEluZGV4Om51bWJlciwgcmY6U3ByUmVjb3JkaW5nRmlsZSl7XHJcbiAgLy9cclxuICAvLyB9XHJcblxyXG5cclxuICBzdG9wcGVkKCkge1xyXG4gICAgdGhpcy5jbGVhclByZVJlY1RpbWVyKCk7XHJcbiAgICB0aGlzLmNsZWFyUG9zdFJlY1RpbWVyKCk7XHJcbiAgICB0aGlzLmNsZWFyTWF4UmVjVGltZXIoKTtcclxuICAgIHRoaXMudXBkYXRlU3RhcnRBY3Rpb25EaXNhYmxlU3RhdGUoKVxyXG4gICAgdGhpcy50cmFuc3BvcnRBY3Rpb25zLnN0b3BBY3Rpb24uZGlzYWJsZWQgPSB0cnVlO1xyXG4gICAgdGhpcy50cmFuc3BvcnRBY3Rpb25zLm5leHRBY3Rpb24uZGlzYWJsZWQgPSB0cnVlO1xyXG4gICAgdGhpcy50cmFuc3BvcnRBY3Rpb25zLnBhdXNlQWN0aW9uLmRpc2FibGVkID0gdHJ1ZTtcclxuICAgIHRoaXMuc3RhdHVzQWxlcnRUeXBlID0gJ2luZm8nO1xyXG4gICAgdGhpcy5zdGF0dXNNc2cgPSAnUmVjb3JkZWQuJztcclxuICAgIHRoaXMuc3RhcnRTdG9wU2lnbmFsU3RhdGUgPSBTdGFydFN0b3BTaWduYWxTdGF0ZS5JRExFO1xyXG5cclxuICAgICAgbGV0IGFkaDpBdWRpb0RhdGFIb2xkZXJ8bnVsbD1udWxsO1xyXG4gICAgICBsZXQgYXM6QXVkaW9Tb3VyY2V8bnVsbD1udWxsO1xyXG4gICAgIGxldCBhYjpBdWRpb0J1ZmZlcnxudWxsPW51bGw7XHJcbiAgICAgIGlmKHRoaXMuYWMpIHtcclxuICAgICAgICBpZiAoQXVkaW9TdG9yYWdlVHlwZS5ORVRfQ0hVTktFRCA9PT0gdGhpcy5hYy5hdWRpb1N0b3JhZ2VUeXBlKSB7XHJcbiAgICAgICAgICB0aGlzLnBsYXlTdGFydEFjdGlvbi5kaXNhYmxlZCA9IHRydWU7XHJcbiAgICAgICAgICB0aGlzLmtlZXBMaXZlTGV2ZWw9dHJ1ZTtcclxuICAgICAgICAgIGxldCBidXJsOnN0cmluZ3xudWxsPW51bGw7XHJcbiAgICAgICAgICBpZih0aGlzLl9zZXNzaW9uKSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLl9kaXNwbGF5UmVjRmlsZSkge1xyXG4gICAgICAgICAgICAgIC8vIFRPRE8gaXMgdGhpcyBicmFuY2ggZXZlciBjYWxsZWQgP1xyXG4gICAgICAgICAgICAgIGxldCByZiA9IHRoaXMuX2Rpc3BsYXlSZWNGaWxlO1xyXG4gICAgICAgICAgICAgIHJmLmZyYW1lcyA9IHRoaXMuYWMuZnJhbWVzUmVjb3JkZWQ7XHJcbiAgICAgICAgICAgICAgLy9jb25zb2xlLmRlYnVnKFwic3RvcHBlZCgpOiBTZXQgZnJhbWVzOiBcIityZi5mcmFtZXMrXCIgb24gcmZJZDogXCIrdGhpcy5kaXNwbGF5UmVjRmlsZT8ucmVjb3JkaW5nRmlsZUlkKTtcclxuICAgICAgICAgICAgICBidXJsID0gdGhpcy5yZWNGaWxlU2VydmljZS5zcHJBdWRpb0ZpbGVVcmwodGhpcy5fc2Vzc2lvbj8ucHJvamVjdCwgcmYpO1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuc2Vzc2lvbj8ucHJvamVjdCAmJiB0aGlzLl9yZWNvcmRpbmdGaWxlICYmIHRoaXMuX3JlY29yZGluZ0ZpbGUgaW5zdGFuY2VvZiBTcHJSZWNvcmRpbmdGaWxlKSB7XHJcbiAgICAgICAgICAgICAgYnVybCA9IHRoaXMucmVjRmlsZVNlcnZpY2Uuc3ByQXVkaW9GaWxlVXJsQnlJdGVtY29kZSh0aGlzLnNlc3Npb24/LnByb2plY3QsIHRoaXMuc2Vzc2lvbj8uc2Vzc2lvbklkLCB0aGlzLl9yZWNvcmRpbmdGaWxlLml0ZW1Db2RlLCB0aGlzLl9yZWNvcmRpbmdGaWxlLnZlcnNpb24pO1xyXG4gICAgICAgICAgICB9ZWxzZXtcclxuICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiQ291bGQgbm90IGNyZWF0ZSBuZXQgYXVkaW8gYnVmZmVyLlwiKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBpZiAoYnVybCkge1xyXG4gICAgICAgICAgICAgIGNvbnN0IHJVVUlEID0gdGhpcy5hYy5yZWNVVUlEO1xyXG4gICAgICAgICAgICAgIGNvbnN0IHNyID0gdGhpcy5hYy5jdXJyZW50U2FtcGxlUmF0ZTtcclxuICAgICAgICAgICAgICBjb25zdCBjaEZsPXNyKlJlY29yZGluZ1NlcnZpY2UuREVGQVVMVF9DSFVOS0VEX0RPV05MT0FEX1NFQ09ORFM7XHJcbiAgICAgICAgICAgICAgLy9jb25zb2xlLmRlYnVnKFwic3RvcHBlZCgpOiByZklEOiBcIit0aGlzLl9yZWNvcmRpbmdGaWxlPy5yZWNvcmRpbmdGaWxlSWQrXCIsIG5ldCBhYiB1cmw6IFwiICsgYnVybCtcIiwgZnJhbWVzOiBcIit0aGlzLmFjLmZyYW1lc1JlY29yZGVkK1wiLCBzYW1wbGUgcmF0ZTogXCIrc3IpO1xyXG4gICAgICAgICAgICAgIGxldCBuZXRBYiA9IG5ldyBOZXRBdWRpb0J1ZmZlcih0aGlzLnJlY0ZpbGVTZXJ2aWNlLCBidXJsLCB0aGlzLmFjLmNoYW5uZWxDb3VudCwgc3IsIGNoRmwsIHRoaXMuYWMuZnJhbWVzUmVjb3JkZWQsIHJVVUlELCBjaEZsKTtcclxuICAgICAgICAgICAgICBhcz1uZXRBYjtcclxuICAgICAgICAgICAgICBpZih0aGlzLnVwbG9hZFNldCl7XHJcbiAgICAgICAgICAgICAgICAvL2xldCBycD1uZXcgUmVhZHlQcm92aWRlcigpO1xyXG4gICAgICAgICAgICAgICAgLy9uZXRBYi5yZWFkeVByb3ZpZGVyPXJwO1xyXG4gICAgICAgICAgICAgICAgdGhpcy51cGxvYWRTZXQub25Eb25lPSh1cGxvYWRTZXQpPT57XHJcbiAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoXCJ1cGxvYWQgc2V0IG9uIGRvbmU6IENhbGwgcmVhZHkgcHJvdmlkZXIucmVhZHlcIik7XHJcbiAgICAgICAgICAgICAgICAgIC8vcnAucmVhZHkoKTtcclxuICAgICAgICAgICAgICAgICAgbmV0QWIucmVhZHkoKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9ZWxzZSBpZiAoQXVkaW9TdG9yYWdlVHlwZS5NRU1fRU5USVJFX0FVVE9fTkVUX0NIVU5LRUQgPT09IHRoaXMuYWMuYXVkaW9TdG9yYWdlVHlwZSB8fCBBdWRpb1N0b3JhZ2VUeXBlLk1FTV9DSFVOS0VEX0FVVE9fTkVUX0NIVU5LRUQgPT09IHRoaXMuYWMuYXVkaW9TdG9yYWdlVHlwZSkge1xyXG4gICAgICAgICAgaWYgKEF1ZGlvU3RvcmFnZVR5cGUuTUVNX0VOVElSRV9BVVRPX05FVF9DSFVOS0VEID09PSB0aGlzLmFjLmF1ZGlvU3RvcmFnZVR5cGUpe1xyXG4gICAgICAgICAgICBjb25zdCBhY0FiPXRoaXMuYWMuYXVkaW9CdWZmZXIoKTtcclxuICAgICAgICAgICAgaWYoYWNBYikge1xyXG4gICAgICAgICAgICAgIGFzID0gbmV3IEF1ZGlvQnVmZmVyU291cmNlKGFjQWIpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICBpZihBdWRpb1N0b3JhZ2VUeXBlLk1FTV9DSFVOS0VEX0FVVE9fTkVUX0NIVU5LRUQgPT09IHRoaXMuYWMuYXVkaW9TdG9yYWdlVHlwZSl7XHJcbiAgICAgICAgICAgIGFzID0gdGhpcy5hYy5hdWRpb0J1ZmZlckFycmF5KCk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICBpZighYXMpe1xyXG4gICAgICAgICAgICB0aGlzLnBsYXlTdGFydEFjdGlvbi5kaXNhYmxlZCA9IHRydWU7XHJcbiAgICAgICAgICAgIHRoaXMua2VlcExpdmVMZXZlbD10cnVlO1xyXG4gICAgICAgICAgICBsZXQgYnVybDpzdHJpbmd8bnVsbD1udWxsO1xyXG4gICAgICAgICAgICBpZih0aGlzLl9zZXNzaW9uKSB7XHJcbiAgICAgICAgICAgICAgaWYgKHRoaXMuX2Rpc3BsYXlSZWNGaWxlKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBUT0RPIGlzIHRoaXMgYnJhbmNoIGV2ZXIgY2FsbGVkID9cclxuICAgICAgICAgICAgICAgIGxldCByZiA9IHRoaXMuX2Rpc3BsYXlSZWNGaWxlO1xyXG4gICAgICAgICAgICAgICAgcmYuZnJhbWVzID0gdGhpcy5hYy5mcmFtZXNSZWNvcmRlZDtcclxuICAgICAgICAgICAgICAgIC8vY29uc29sZS5kZWJ1ZyhcInN0b3BwZWQoKTogU2V0IGZyYW1lczogXCIrcmYuZnJhbWVzK1wiIG9uIHJmSWQ6IFwiK3RoaXMuZGlzcGxheVJlY0ZpbGU/LnJlY29yZGluZ0ZpbGVJZCk7XHJcbiAgICAgICAgICAgICAgICBidXJsID0gdGhpcy5yZWNGaWxlU2VydmljZS5zcHJBdWRpb0ZpbGVVcmwodGhpcy5fc2Vzc2lvbj8ucHJvamVjdCwgcmYpO1xyXG4gICAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5zZXNzaW9uPy5wcm9qZWN0ICYmIHRoaXMuX3JlY29yZGluZ0ZpbGUgJiYgdGhpcy5fcmVjb3JkaW5nRmlsZSBpbnN0YW5jZW9mIFNwclJlY29yZGluZ0ZpbGUpIHtcclxuICAgICAgICAgICAgICAgIGJ1cmwgPSB0aGlzLnJlY0ZpbGVTZXJ2aWNlLnNwckF1ZGlvRmlsZVVybEJ5SXRlbWNvZGUodGhpcy5zZXNzaW9uPy5wcm9qZWN0LCB0aGlzLnNlc3Npb24/LnNlc3Npb25JZCwgdGhpcy5fcmVjb3JkaW5nRmlsZS5pdGVtQ29kZSwgdGhpcy5fcmVjb3JkaW5nRmlsZS52ZXJzaW9uKTtcclxuICAgICAgICAgICAgICB9ZWxzZXtcclxuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJDb3VsZCBub3QgY3JlYXRlIG5ldCBhdWRpbyBidWZmZXIuXCIpO1xyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICBpZiAoYnVybCkge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgclVVSUQgPSB0aGlzLmFjLnJlY1VVSUQ7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBzciA9IHRoaXMuYWMuY3VycmVudFNhbXBsZVJhdGU7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBjaEZsPXNyKlJlY29yZGluZ1NlcnZpY2UuREVGQVVMVF9DSFVOS0VEX0RPV05MT0FEX1NFQ09ORFM7XHJcbiAgICAgICAgICAgICAgICAvL2NvbnNvbGUuZGVidWcoXCJzdG9wcGVkKCk6IHJmSUQ6IFwiK3RoaXMuX3JlY29yZGluZ0ZpbGU/LnJlY29yZGluZ0ZpbGVJZCtcIiwgbmV0IGFiIHVybDogXCIgKyBidXJsK1wiLCBmcmFtZXM6IFwiK3RoaXMuYWMuZnJhbWVzUmVjb3JkZWQrXCIsIHNhbXBsZSByYXRlOiBcIitzcik7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBuZXRBYiA9IG5ldyBOZXRBdWRpb0J1ZmZlcih0aGlzLnJlY0ZpbGVTZXJ2aWNlLCBidXJsLCB0aGlzLmFjLmNoYW5uZWxDb3VudCwgc3IsIGNoRmwsIHRoaXMuYWMuZnJhbWVzUmVjb3JkZWQsIHJVVUlELCBjaEZsKTtcclxuICAgICAgICAgICAgICAgIGFzID0gbmV0QWI7XHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy51cGxvYWRTZXQpIHtcclxuICAgICAgICAgICAgICAgICAgdGhpcy51cGxvYWRTZXQub25Eb25lID0gKHVwbG9hZFNldCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoXCJ1cGxvYWQgc2V0IG9uIGRvbmU6IENhbGwgcmVhZHkgcHJvdmlkZXIucmVhZHlcIik7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIG5ldEFiLnJlYWR5KCk7XHJcbiAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9IGVsc2UgaWYgKEF1ZGlvU3RvcmFnZVR5cGUuREJfQ0hVTktFRCA9PT0gdGhpcy5hYy5hdWRpb1N0b3JhZ2VUeXBlKSB7XHJcbiAgICAgICAgICBhcyA9IHRoaXMuYWMuaW5kZGJBdWRpb0J1ZmZlckFycmF5KCk7XHJcbiAgICAgICAgfSBlbHNlIGlmIChBdWRpb1N0b3JhZ2VUeXBlLk1FTV9DSFVOS0VEID09PSB0aGlzLmFjLmF1ZGlvU3RvcmFnZVR5cGUpIHtcclxuICAgICAgICAgIGFzID0gdGhpcy5hYy5hdWRpb0J1ZmZlckFycmF5KCk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGFiID0gdGhpcy5hYy5hdWRpb0J1ZmZlcigpO1xyXG4gICAgICAgICAgaWYoYWIpIHtcclxuICAgICAgICAgICAgYXMgPSBuZXcgQXVkaW9CdWZmZXJTb3VyY2UoYWIpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoYXMpIHtcclxuICAgICAgICAgIGFkaCA9IG5ldyBBdWRpb0RhdGFIb2xkZXIoYXMpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgIC8vIFVzZSBhbiBvd24gcmVmZXJlbmNlIHNpbmNlIHRoZSB3cml0aW5nIG9mIHRoZSB3YXZlIGZpbGUgaXMgYXN5bmNocm9ub3VzIGFuZCB0aGlzLl9yZWNvcmRpbmdGaWxlIG1pZ2h0IGFscmVhZHkgY29udGFpbiB0aGUgbmV4dCByZWNvcmRpbmdcclxuICAgIGxldCByZiA9IHRoaXMuX3JlY29yZGluZ0ZpbGU7XHJcbiAgICBpZiAocmYgJiYgcmYgaW5zdGFuY2VvZiBTcHJSZWNvcmRpbmdGaWxlKSB7XHJcbiAgICAgIHRoaXMuaXRlbXM/LnNldFNwclJlY0ZpbGVBdWRpb0RhdGEocmYsYWRoKTtcclxuICAgICAgaWYgKHRoaXMuZW5hYmxlVXBsb2FkUmVjb3JkaW5ncyAmJiB0aGlzLl91cGxvYWRDaHVua1NpemVTZWNvbmRzPT09bnVsbCAmJiBBdWRpb1N0b3JhZ2VUeXBlLk1FTV9FTlRJUkU9PT10aGlzLl9jbGllbnRBdWRpb1N0b3JhZ2VUeXBlKSB7XHJcbiAgICAgICAgLy8gVE9ETyB1c2UgU3BlZWNoUmVjb3JkZXJjb25maWcgcmVzcC4gUmVjZmlsZVNlcnZpY2VcclxuICAgICAgICAvLyBjb252ZXJ0IGFzeW5jaHJvbm91c2x5IHRvIDE2LWJpdCBpbnRlZ2VyIFBDTVxyXG4gICAgICAgIC8vIFRPRE8gY291bGQgd2UgYXZvaWQgY29udmVyc2lvbiB0byBzYXZlIENQVSByZXNvdXJjZXMgYW5kIHRyYW5zZmVyIGZsb2F0IFBDTSBkaXJlY3RseT9cclxuICAgICAgICAvLyBUT0RPIGR1cGxpY2F0ZSBjb252ZXJzaW9uIGZvciBtYW51YWwgZG93bmxvYWRcclxuICAgICAgICAvL2NvbnNvbGUubG9nKFwiQnVpbGQgd2F2IHdyaXRlci4uLlwiKTtcclxuICAgICAgICBpZihhYikge1xyXG4gICAgICAgICAgdGhpcy5wcm9jZXNzaW5nUmVjb3JkaW5nPXRydWU7XHJcbiAgICAgICAgICBsZXQgd3cgPSBuZXcgV2F2V3JpdGVyKCk7XHJcbiAgICAgICAgICAvL25ldyBSRVNUIEFQSSBVUkxcclxuICAgICAgICAgIGxldCBhcGlFbmRQb2ludCA9ICcnO1xyXG4gICAgICAgICAgaWYgKHRoaXMuY29uZmlnICYmIHRoaXMuY29uZmlnLmFwaUVuZFBvaW50KSB7XHJcbiAgICAgICAgICAgIGFwaUVuZFBvaW50ID0gdGhpcy5jb25maWcuYXBpRW5kUG9pbnQ7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICBpZiAoYXBpRW5kUG9pbnQgIT09ICcnKSB7XHJcbiAgICAgICAgICAgIGFwaUVuZFBvaW50ID0gYXBpRW5kUG9pbnQgKyAnLydcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIGxldCBzZXNzaW9uc1VybCA9IGFwaUVuZFBvaW50ICsgU2Vzc2lvblNlcnZpY2UuU0VTU0lPTl9BUElfQ1RYO1xyXG4gICAgICAgICAgbGV0IHJlY1VybDogc3RyaW5nID0gc2Vzc2lvbnNVcmwgKyAnLycgKyByZi5zZXNzaW9uICsgJy8nICsgUkVDRklMRV9BUElfQ1RYICsgJy8nICsgcmYuaXRlbUNvZGU7XHJcbiAgICAgICAgICB3dy53cml0ZUFzeW5jKGFiLCAod2F2RmlsZSkgPT4ge1xyXG4gICAgICAgICAgICB0aGlzLnBvc3RSZWNvcmRpbmcod2F2RmlsZSwgcmVjVXJsLHJmKTtcclxuICAgICAgICAgICAgdGhpcy5wcm9jZXNzaW5nUmVjb3JkaW5nID0gZmFsc2VcclxuICAgICAgICAgICAgdGhpcy51cGRhdGVXYWtlTG9jaygpO1xyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8gY2hlY2sgY29tcGxldGUgc2Vzc2lvblxyXG4gICAgbGV0IGNvbXBsZXRlID0gdHJ1ZTtcclxuICAgIGlmKHRoaXMuaXRlbXMpIHtcclxuICAgICAgLy8gc2VhcmNoIGJhY2t3YXJkcywgdG8gZ2FpbiBmYXN0ZXIgZGV0ZWN0aW9uIG9mIGluY29tcGxldGUgc3RhdGVcclxuICAgICAgZm9yIChsZXQgcmkgPSB0aGlzLml0ZW1zLmxlbmd0aCgpIC0gMTsgcmkgPj0gMDsgcmktLSkge1xyXG4gICAgICAgIGxldCBpdCA9IHRoaXMuaXRlbXMuZ2V0SXRlbShyaSk7XHJcbiAgICAgICAgaWYgKGl0LnJlY29yZGluZyAmJiAhaXQudHJhaW5pbmcgJiYgIWl0Lml0ZW1Eb25lKCkpIHtcclxuICAgICAgICAgIGNvbXBsZXRlID0gZmFsc2U7XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBsZXQgYXV0b1N0YXJ0ID0gKHRoaXMuc3RhdHVzID09PSBTdGF0dXMuU1RPUFBJTkdfU1RPUCk7XHJcbiAgICB0aGlzLnN0YXR1cyA9IFN0YXR1cy5JRExFO1xyXG4gICAgbGV0IHN0YXJ0TmV4dD1mYWxzZTtcclxuICAgIGlmIChjb21wbGV0ZSkge1xyXG4gICAgICBpZih0aGlzLl9zZXNzaW9uIT1udWxsKSB7XHJcbiAgICAgICAgaWYgKCF0aGlzLl9zZXNzaW9uLnNlYWxlZCAmJiB0aGlzLl9zZXNzaW9uLnN0YXR1cyAhPT0gXCJDT01QTEVURURcIikge1xyXG4gICAgICAgICAgbGV0IGJvZHk6IGFueSA9IHt9XHJcbiAgICAgICAgICB0aGlzLl9zZXNzaW9uLnN0YXR1cyA9IFwiQ09NUExFVEVEXCI7XHJcbiAgICAgICAgICBib2R5LnN0YXR1cyA9IHRoaXMuX3Nlc3Npb24uc3RhdHVzO1xyXG4gICAgICAgICAgaWYgKCF0aGlzLl9zZXNzaW9uLmNvbXBsZXRlZERhdGUpIHtcclxuICAgICAgICAgICAgdGhpcy5fc2Vzc2lvbi5jb21wbGV0ZWREYXRlID0gbmV3IERhdGUoKTtcclxuICAgICAgICAgICAgYm9keS5jb21wbGV0ZWREYXRlID0gdGhpcy5fc2Vzc2lvbi5jb21wbGV0ZWREYXRlO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgdGhpcy5zZXNzaW9uU2VydmljZS5wYXRjaFNlc3Npb25PYnNlcnZlcih0aGlzLl9zZXNzaW9uLCBib2R5KS5zdWJzY3JpYmUoKVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgICB0aGlzLnN0YXR1c01zZyA9ICdTZXNzaW9uIGNvbXBsZXRlISc7XHJcbiAgICAgIHRoaXMudXBkYXRlV2FrZUxvY2soKTtcclxuICAgICAgaWYodGhpcy5zaG93U2Vzc2lvbkNvbXBsZXRlTWVzc2FnZSkge1xyXG4gICAgICAgIHRoaXMuZGlhbG9nLm9wZW4oU2Vzc2lvbkZpbmlzaGVkRGlhbG9nLCB7fSk7XHJcbiAgICAgIH1cclxuICAgICAgLy8gZW5hYmxlIG5hdmlnYXRpb25cclxuICAgICAgdGhpcy50cmFuc3BvcnRBY3Rpb25zLmZ3ZEFjdGlvbi5kaXNhYmxlZCA9IGZhbHNlXHJcbiAgICAgIHRoaXMudHJhbnNwb3J0QWN0aW9ucy5id2RBY3Rpb24uZGlzYWJsZWQgPSBmYWxzZVxyXG5cclxuICAgIH0gZWxzZSB7XHJcblxyXG4gICAgICBpZiAodGhpcy5zZWN0aW9uLm1vZGUgPT09ICdBVVRPUFJPR1JFU1MnIHx8IHRoaXMuc2VjdGlvbi5tb2RlID09PSAnQVVUT1JFQ09SRElORycpIHtcclxuICAgICAgICB0aGlzLm5leHRJdGVtKCk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGlmICh0aGlzLnNlY3Rpb24ubW9kZSA9PT0gJ0FVVE9SRUNPUkRJTkcnICYmIHRoaXMuYXV0b3JlY29yZGluZyAmJiBhdXRvU3RhcnQpIHtcclxuICAgICAgICBzdGFydE5leHQ9dHJ1ZTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICB0aGlzLm5hdmlnYXRpb25EaXNhYmxlZCA9IGZhbHNlO1xyXG4gICAgICAgIHRoaXMudXBkYXRlTmF2aWdhdGlvbkFjdGlvbnMoKTtcclxuICAgICAgICB0aGlzLnVwZGF0ZVdha2VMb2NrKCk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIC8vIGFwcGx5IHJlY29yZGVkIGl0ZW1cclxuICAgIHRoaXMuYXBwbHlJdGVtKHN0YXJ0TmV4dCk7XHJcbiAgICBpZihzdGFydE5leHQpe1xyXG4gICAgICB0aGlzLnN0YXJ0SXRlbSgpO1xyXG4gICAgfVxyXG4gICAgdGhpcy5jaGFuZ2VEZXRlY3RvclJlZi5kZXRlY3RDaGFuZ2VzKCk7XHJcbiAgfVxyXG5cclxuICBlcnJvcihtc2c9J0FuIHVua25vd24gZXJyb3Igb2NjdXJlZCBkdXJpbmcgcmVjb3JkaW5nLicsYWR2aWNlOnN0cmluZz0nUGxlYXNlIHJldHJ5LicpIHtcclxuICAgIHRoaXMuc3RhdHVzPVN0YXR1cy5FUlJPUjtcclxuICAgIHN1cGVyLmVycm9yKG1zZyxhZHZpY2UpO1xyXG4gICAgdGhpcy51cGRhdGVOYXZpZ2F0aW9uQWN0aW9ucygpO1xyXG4gICAgdGhpcy51cGRhdGVTdGFydEFjdGlvbkRpc2FibGVTdGF0ZSgpO1xyXG4gIH1cclxuXHJcbiAgcG9zdENodW5rQXVkaW9CdWZmZXIoYXVkaW9CdWZmZXI6IEF1ZGlvQnVmZmVyLCBjaHVua0lkeDogbnVtYmVyKTogdm9pZCB7XHJcbiAgICB0aGlzLnByb2Nlc3NpbmdSZWNvcmRpbmcgPSB0cnVlO1xyXG4gICAgbGV0IHd3ID0gbmV3IFdhdldyaXRlcigpO1xyXG4gICAgbGV0IHNlc3Npb25zVXJsID0gdGhpcy5zZXNzaW9uc0Jhc2VVcmwoKTtcclxuICAgIGxldCByZWNVcmw6IHN0cmluZyA9IHNlc3Npb25zVXJsICsgJy8nICsgdGhpcy5zZXNzaW9uPy5zZXNzaW9uSWQgKyAnLycgKyBSRUNGSUxFX0FQSV9DVFggKyAnLycgKyB0aGlzLnByb21wdEl0ZW0uaXRlbWNvZGUrJy8nK3RoaXMucmZVdWlkKycvJytjaHVua0lkeDtcclxuICAgIC8vIFRoZSB1cGxvYWQgaG9sZGVyIGlzIHJlcXVpcmVkIHRvIGFkZCB0aGUgdXBsb2FkIG5vdyB0byB0aGUgdXBsb2FkIHNldC4gVGhlIHJlYWwgdXBsb2FkIGlzIGNyZWF0ZWQgYXN5bmMgaW4gcG9zdHJlY29yZGluZyBhbmQgdGhlIHVwbG9hZCBzZXQgaXMgYWxyZWFkeSBjb21wbGV0ZSBhdCB0aGF0IHRpbWUuXHJcbiAgICBsZXQgdWxoPW5ldyBVcGxvYWRIb2xkZXIoKTtcclxuICAgIGlmKHRoaXMudXBsb2FkU2V0KXtcclxuICAgICAgdGhpcy51cGxvYWRTZXQuYWRkKHVsaCk7XHJcbiAgICB9XHJcblxyXG4gICAgd3cud3JpdGVBc3luYyhhdWRpb0J1ZmZlciwgKHdhdkZpbGUpID0+IHtcclxuICAgICAgdGhpcy5wb3N0UmVjb3JkaW5nKHdhdkZpbGUsIHJlY1VybCxudWxsLHVsaCk7XHJcbiAgICAgIHRoaXMucHJvY2Vzc2luZ1JlY29yZGluZyA9IGZhbHNlXHJcbiAgICB9KTtcclxuICB9XHJcblxyXG5cclxuICAvLyBwb3N0UmVjb3JkaW5nKHdhdkZpbGU6IFVpbnQ4QXJyYXksIHJlY1VybDogc3RyaW5nLHJmOlJlY29yZGluZ0ZpbGV8bnVsbCkge1xyXG4gIC8vICAgbGV0IHdhdkJsb2IgPSBuZXcgQmxvYihbd2F2RmlsZV0sIHt0eXBlOiAnYXVkaW8vd2F2J30pO1xyXG4gIC8vICAgbGV0IHVsID0gbmV3IFVwbG9hZCh3YXZCbG9iLCByZWNVcmwscmYpO1xyXG4gIC8vICAgdGhpcy51cGxvYWRlci5xdWV1ZVVwbG9hZCh1bCk7XHJcbiAgLy8gfVxyXG5cclxuICBzdG9wKCkge1xyXG4gICAgaWYodGhpcy5hYyE9bnVsbCl7XHJcbiAgICAgIHRoaXMuYWMuY2xvc2UoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG5cclxuICBwcml2YXRlIHVwZGF0ZUNvbnRyb2xQbGF5YmFja1Bvc2l0aW9uKCkge1xyXG4gICAgaWYodGhpcy5fY29udHJvbEF1ZGlvUGxheWVyKSB7XHJcbiAgICAgIGNvbnN0IHBwRnJhbWVzPXRoaXMuX2NvbnRyb2xBdWRpb1BsYXllci5wbGF5UG9zaXRpb25GcmFtZXM7XHJcbiAgICAgIGlmIChwcEZyYW1lcyE9PW51bGwpIHtcclxuICAgICAgICBpZih0aGlzLnByb21wdGluZy5hdWRpb0Rpc3BsYXkpIHtcclxuICAgICAgICAgIHRoaXMucHJvbXB0aW5nLmF1ZGlvRGlzcGxheS5wbGF5RnJhbWVQb3NpdGlvbiA9IHBwRnJhbWVzO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLmxpdmVMZXZlbERpc3BsYXkucGxheUZyYW1lUG9zaXRpb24gPSBwcEZyYW1lcztcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgYXVkaW9QbGF5ZXJVcGRhdGUoZTogQXVkaW9QbGF5ZXJFdmVudCkge1xyXG4gICAgaWYgKEV2ZW50VHlwZS5SRUFEWSA9PT0gZS50eXBlKSB7XHJcblxyXG4gICAgfSBlbHNlIGlmIChFdmVudFR5cGUuU1RBUlRFRCA9PT0gZS50eXBlKSB7XHJcbiAgICAgIC8vdGhpcy5zdGF0dXMgPSAnUGxheWJhY2suLi4nO1xyXG4gICAgICB0aGlzLnVwZGF0ZVRpbWVySWQgPSB3aW5kb3cuc2V0SW50ZXJ2YWwoKCkgPT4gdGhpcy51cGRhdGVDb250cm9sUGxheWJhY2tQb3NpdGlvbigpLCA1MCk7XHJcblxyXG4gICAgfSBlbHNlIGlmIChFdmVudFR5cGUuRU5ERUQgPT09IGUudHlwZSkge1xyXG4gICAgICAvLy5zdGF0dXM9J1JlYWR5Lic7XHJcbiAgICAgIHdpbmRvdy5jbGVhckludGVydmFsKHRoaXMudXBkYXRlVGltZXJJZCk7XHJcblxyXG4gICAgfVxyXG5cclxuICAgIGlmKCF0aGlzLmRlc3Ryb3llZCkge1xyXG4gICAgICAgIHRoaXMuY2hhbmdlRGV0ZWN0b3JSZWYuZGV0ZWN0Q2hhbmdlcygpO1xyXG4gICAgfVxyXG5cclxuICB9XHJcbn1cclxuXHJcbiJdfQ==
|