@rocketshow/designer 1.40.0 → 1.44.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/fesm2022/rocketshow-designer.mjs +1389 -1148
- package/fesm2022/rocketshow-designer.mjs.map +1 -1
- package/index.d.ts +1676 -5
- package/package.json +2 -4
- package/rocketshow-designer-1.44.0.tgz +0 -0
- package/esm2022/lib/array-sort-pipe.mjs +0 -30
- package/esm2022/lib/designer.component.mjs +0 -672
- package/esm2022/lib/designer.module.mjs +0 -186
- package/esm2022/lib/designer.service.mjs +0 -14
- package/esm2022/lib/dropzone/dropzone.component.mjs +0 -93
- package/esm2022/lib/effect/effect-curve/effect-curve.component.mjs +0 -577
- package/esm2022/lib/effect/effect-pan-tilt/effect-pan-tilt.component.mjs +0 -36
- package/esm2022/lib/effect/effect.component.mjs +0 -174
- package/esm2022/lib/error-dialog/error-dialog.component.mjs +0 -75
- package/esm2022/lib/fixture/fixture-capability/fixture-capability-channel/fixture-capability-channel.component.mjs +0 -370
- package/esm2022/lib/fixture/fixture-capability/fixture-capability-color/fixture-capability-color.component.mjs +0 -147
- package/esm2022/lib/fixture/fixture-capability/fixture-capability-color-wheel/fixture-capability-color-wheel.component.mjs +0 -213
- package/esm2022/lib/fixture/fixture-capability/fixture-capability-dimmer/fixture-capability-dimmer.component.mjs +0 -78
- package/esm2022/lib/fixture/fixture-capability/fixture-capability-pan-tilt/fixture-capability-pan-tilt.component.mjs +0 -119
- package/esm2022/lib/fixture/fixture-capability/fixture-capability.component.mjs +0 -191
- package/esm2022/lib/fixture/fixture-channel/fixture-channel.component.mjs +0 -162
- package/esm2022/lib/fixture/fixture-settings/fixture-settings-position/fixture-settings-position.component.mjs +0 -365
- package/esm2022/lib/fixture/fixture-settings/fixture-settings-stage/fixture-settings-stage.component.mjs +0 -151
- package/esm2022/lib/fixture/fixture-settings/fixture-settings.component.mjs +0 -46
- package/esm2022/lib/fixture/fixture.component.mjs +0 -148
- package/esm2022/lib/fixture-pool/fixture-pool-create-from-file/fixture-pool-create-from-file.component.mjs +0 -145
- package/esm2022/lib/fixture-pool/fixture-pool.component.mjs +0 -641
- package/esm2022/lib/intro/intro.component.mjs +0 -95
- package/esm2022/lib/master-dimmer/master-dimmer.component.mjs +0 -66
- package/esm2022/lib/models/cached-fixture-capability.mjs +0 -9
- package/esm2022/lib/models/cached-fixture-channel.mjs +0 -7
- package/esm2022/lib/models/cached-fixture.mjs +0 -6
- package/esm2022/lib/models/color.mjs +0 -8
- package/esm2022/lib/models/composition.mjs +0 -46
- package/esm2022/lib/models/effect-curve-profile-channel.mjs +0 -15
- package/esm2022/lib/models/effect-curve.mjs +0 -69
- package/esm2022/lib/models/effect-pan-tilt.mjs +0 -19
- package/esm2022/lib/models/effect.mjs +0 -12
- package/esm2022/lib/models/fixture-capability-value.mjs +0 -15
- package/esm2022/lib/models/fixture-capability.mjs +0 -127
- package/esm2022/lib/models/fixture-channel-value.mjs +0 -11
- package/esm2022/lib/models/fixture-channel.mjs +0 -24
- package/esm2022/lib/models/fixture-matrix-pixel-group-constraints.mjs +0 -27
- package/esm2022/lib/models/fixture-matrix-pixel-group.mjs +0 -12
- package/esm2022/lib/models/fixture-matrix.mjs +0 -25
- package/esm2022/lib/models/fixture-mode-channel.mjs +0 -26
- package/esm2022/lib/models/fixture-mode.mjs +0 -17
- package/esm2022/lib/models/fixture-physical.mjs +0 -14
- package/esm2022/lib/models/fixture-profile.mjs +0 -85
- package/esm2022/lib/models/fixture-wheel-slot.mjs +0 -26
- package/esm2022/lib/models/fixture-wheel.mjs +0 -15
- package/esm2022/lib/models/fixture.mjs +0 -40
- package/esm2022/lib/models/preset-fixture.mjs +0 -10
- package/esm2022/lib/models/preset-region-scene.mjs +0 -8
- package/esm2022/lib/models/preset.mjs +0 -65
- package/esm2022/lib/models/project.mjs +0 -78
- package/esm2022/lib/models/scene-playback-region.mjs +0 -11
- package/esm2022/lib/models/scene.mjs +0 -27
- package/esm2022/lib/preset/preset-settings/preset-settings.component.mjs +0 -194
- package/esm2022/lib/preset/preset.component.mjs +0 -131
- package/esm2022/lib/preview/models/color-changer-3d.mjs +0 -52
- package/esm2022/lib/preview/models/fixture-3d.mjs +0 -260
- package/esm2022/lib/preview/models/moving-head-3d.mjs +0 -115
- package/esm2022/lib/preview/preview.component.mjs +0 -216
- package/esm2022/lib/project/project-browser/project-browser.component.mjs +0 -143
- package/esm2022/lib/project/project-import/project-import.component.mjs +0 -107
- package/esm2022/lib/project/project-save/project-save.component.mjs +0 -178
- package/esm2022/lib/project/project-share/project-share.component.mjs +0 -71
- package/esm2022/lib/scene/scene-settings/scene-settings.component.mjs +0 -146
- package/esm2022/lib/scene/scene.component.mjs +0 -110
- package/esm2022/lib/services/animation.service.mjs +0 -16
- package/esm2022/lib/services/config.service.mjs +0 -28
- package/esm2022/lib/services/effect.service.mjs +0 -14
- package/esm2022/lib/services/error-dialog.service.mjs +0 -39
- package/esm2022/lib/services/fixture-pool.service.mjs +0 -30
- package/esm2022/lib/services/fixture.service.mjs +0 -699
- package/esm2022/lib/services/hotkey-target-exclude.service.mjs +0 -24
- package/esm2022/lib/services/intro.service.mjs +0 -140
- package/esm2022/lib/services/preset.service.mjs +0 -450
- package/esm2022/lib/services/preview-mesh.service.mjs +0 -57
- package/esm2022/lib/services/preview.service.mjs +0 -481
- package/esm2022/lib/services/project-load.service.mjs +0 -206
- package/esm2022/lib/services/project.service.mjs +0 -93
- package/esm2022/lib/services/scene.service.mjs +0 -164
- package/esm2022/lib/services/timeline.service.mjs +0 -726
- package/esm2022/lib/services/user-ensure-login.service.mjs +0 -38
- package/esm2022/lib/services/user.service.mjs +0 -89
- package/esm2022/lib/services/uuid.service.mjs +0 -23
- package/esm2022/lib/services/warning-dialog.service.mjs +0 -38
- package/esm2022/lib/timeline/composition-settings/composition-settings.component.mjs +0 -304
- package/esm2022/lib/timeline/timeline-grid/timeline-grid.component.mjs +0 -216
- package/esm2022/lib/timeline/timeline.component.mjs +0 -418
- package/esm2022/lib/user/user-login/user-login.component.mjs +0 -144
- package/esm2022/lib/user/user-register/user-register.component.mjs +0 -220
- package/esm2022/lib/wait-dialog/wait-dialog.component.mjs +0 -26
- package/esm2022/lib/warning-dialog/warning-dialog.component.mjs +0 -68
- package/esm2022/public_api.mjs +0 -7
- package/esm2022/rocketshow-designer.mjs +0 -5
- package/lib/array-sort-pipe.d.ts +0 -7
- package/lib/designer.component.d.ts +0 -73
- package/lib/designer.module.d.ts +0 -57
- package/lib/designer.service.d.ts +0 -6
- package/lib/dropzone/dropzone.component.d.ts +0 -24
- package/lib/effect/effect-curve/effect-curve.component.d.ts +0 -59
- package/lib/effect/effect-pan-tilt/effect-pan-tilt.component.d.ts +0 -15
- package/lib/effect/effect.component.d.ts +0 -22
- package/lib/error-dialog/error-dialog.component.d.ts +0 -17
- package/lib/fixture/fixture-capability/fixture-capability-channel/fixture-capability-channel.component.d.ts +0 -41
- package/lib/fixture/fixture-capability/fixture-capability-color/fixture-capability-color.component.d.ts +0 -26
- package/lib/fixture/fixture-capability/fixture-capability-color-wheel/fixture-capability-color-wheel.component.d.ts +0 -34
- package/lib/fixture/fixture-capability/fixture-capability-dimmer/fixture-capability-dimmer.component.d.ts +0 -15
- package/lib/fixture/fixture-capability/fixture-capability-pan-tilt/fixture-capability-pan-tilt.component.d.ts +0 -18
- package/lib/fixture/fixture-capability/fixture-capability.component.d.ts +0 -31
- package/lib/fixture/fixture-channel/fixture-channel.component.d.ts +0 -25
- package/lib/fixture/fixture-settings/fixture-settings-position/fixture-settings-position.component.d.ts +0 -32
- package/lib/fixture/fixture-settings/fixture-settings-stage/fixture-settings-stage.component.d.ts +0 -14
- package/lib/fixture/fixture-settings/fixture-settings.component.d.ts +0 -14
- package/lib/fixture/fixture.component.d.ts +0 -25
- package/lib/fixture-pool/fixture-pool-create-from-file/fixture-pool-create-from-file.component.d.ts +0 -28
- package/lib/fixture-pool/fixture-pool.component.d.ts +0 -62
- package/lib/intro/intro.component.d.ts +0 -11
- package/lib/master-dimmer/master-dimmer.component.d.ts +0 -15
- package/lib/models/cached-fixture-capability.d.ts +0 -11
- package/lib/models/cached-fixture-channel.d.ts +0 -11
- package/lib/models/cached-fixture.d.ts +0 -11
- package/lib/models/color.d.ts +0 -6
- package/lib/models/composition.d.ts +0 -19
- package/lib/models/effect-curve-profile-channel.d.ts +0 -5
- package/lib/models/effect-curve.d.ts +0 -15
- package/lib/models/effect-pan-tilt.d.ts +0 -6
- package/lib/models/effect.d.ts +0 -6
- package/lib/models/fixture-capability-value.d.ts +0 -10
- package/lib/models/fixture-capability.d.ts +0 -117
- package/lib/models/fixture-channel-value.d.ts +0 -6
- package/lib/models/fixture-channel.d.ts +0 -9
- package/lib/models/fixture-matrix-pixel-group-constraints.d.ts +0 -8
- package/lib/models/fixture-matrix-pixel-group.d.ts +0 -6
- package/lib/models/fixture-matrix.d.ts +0 -6
- package/lib/models/fixture-mode-channel.d.ts +0 -8
- package/lib/models/fixture-mode.d.ts +0 -8
- package/lib/models/fixture-physical.d.ts +0 -4
- package/lib/models/fixture-profile.d.ts +0 -39
- package/lib/models/fixture-wheel-slot.d.ts +0 -17
- package/lib/models/fixture-wheel.d.ts +0 -5
- package/lib/models/fixture.d.ts +0 -23
- package/lib/models/preset-fixture.d.ts +0 -5
- package/lib/models/preset-region-scene.d.ts +0 -9
- package/lib/models/preset.d.ts +0 -20
- package/lib/models/project.d.ts +0 -31
- package/lib/models/scene-playback-region.d.ts +0 -6
- package/lib/models/scene.d.ts +0 -11
- package/lib/preset/preset-settings/preset-settings.component.d.ts +0 -22
- package/lib/preset/preset.component.d.ts +0 -25
- package/lib/preview/models/color-changer-3d.d.ts +0 -16
- package/lib/preview/models/fixture-3d.d.ts +0 -38
- package/lib/preview/models/moving-head-3d.d.ts +0 -23
- package/lib/preview/preview.component.d.ts +0 -38
- package/lib/project/project-browser/project-browser.component.d.ts +0 -27
- package/lib/project/project-import/project-import.component.d.ts +0 -23
- package/lib/project/project-save/project-save.component.d.ts +0 -28
- package/lib/project/project-share/project-share.component.d.ts +0 -16
- package/lib/scene/scene-settings/scene-settings.component.d.ts +0 -20
- package/lib/scene/scene.component.d.ts +0 -22
- package/lib/services/animation.service.d.ts +0 -7
- package/lib/services/config.service.d.ts +0 -20
- package/lib/services/effect.service.d.ts +0 -8
- package/lib/services/error-dialog.service.d.ts +0 -12
- package/lib/services/fixture-pool.service.d.ts +0 -10
- package/lib/services/fixture.service.d.ts +0 -70
- package/lib/services/hotkey-target-exclude.service.d.ts +0 -7
- package/lib/services/intro.service.d.ts +0 -21
- package/lib/services/preset.service.d.ts +0 -64
- package/lib/services/preview-mesh.service.d.ts +0 -14
- package/lib/services/preview.service.d.ts +0 -42
- package/lib/services/project-load.service.d.ts +0 -36
- package/lib/services/project.service.d.ts +0 -26
- package/lib/services/scene.service.d.ts +0 -30
- package/lib/services/timeline.service.d.ts +0 -70
- package/lib/services/user-ensure-login.service.d.ts +0 -14
- package/lib/services/user.service.d.ts +0 -22
- package/lib/services/uuid.service.d.ts +0 -7
- package/lib/services/warning-dialog.service.d.ts +0 -12
- package/lib/timeline/composition-settings/composition-settings.component.d.ts +0 -48
- package/lib/timeline/timeline-grid/timeline-grid.component.d.ts +0 -22
- package/lib/timeline/timeline.component.d.ts +0 -50
- package/lib/user/user-login/user-login.component.d.ts +0 -21
- package/lib/user/user-register/user-register.component.d.ts +0 -26
- package/lib/wait-dialog/wait-dialog.component.d.ts +0 -8
- package/lib/warning-dialog/warning-dialog.component.d.ts +0 -16
- package/public_api.d.ts +0 -3
- package/rocketshow-designer-1.40.0.tgz +0 -0
|
@@ -1,726 +0,0 @@
|
|
|
1
|
-
import { HttpClient } from '@angular/common/http';
|
|
2
|
-
import { Injectable } from '@angular/core';
|
|
3
|
-
import { Subject, timer } from 'rxjs';
|
|
4
|
-
import { map } from 'rxjs/operators';
|
|
5
|
-
import WaveSurfer from 'wavesurfer.js';
|
|
6
|
-
import CursorPlugin from 'wavesurfer.js/dist/plugin/wavesurfer.cursor.min.js';
|
|
7
|
-
import RegionsPlugin from 'wavesurfer.js/dist/plugin/wavesurfer.regions.min.js';
|
|
8
|
-
import TimeLinePlugin from 'wavesurfer.js/dist/plugin/wavesurfer.timeline.min.js';
|
|
9
|
-
import { guess } from 'web-audio-beat-detector';
|
|
10
|
-
import { PresetRegionScene } from '../models/preset-region-scene';
|
|
11
|
-
import { ScenePlaybackRegion } from '../models/scene-playback-region';
|
|
12
|
-
import { ConfigService } from './config.service';
|
|
13
|
-
import { PresetService } from './preset.service';
|
|
14
|
-
import { ProjectService } from './project.service';
|
|
15
|
-
import { SceneService } from './scene.service';
|
|
16
|
-
import * as i0 from "@angular/core";
|
|
17
|
-
import * as i1 from "./scene.service";
|
|
18
|
-
import * as i2 from "./preset.service";
|
|
19
|
-
import * as i3 from "./project.service";
|
|
20
|
-
import * as i4 from "@angular/common/http";
|
|
21
|
-
import * as i5 from "./config.service";
|
|
22
|
-
export class TimelineService {
|
|
23
|
-
constructor(sceneService, presetService, projectService, http, configService) {
|
|
24
|
-
this.sceneService = sceneService;
|
|
25
|
-
this.presetService = presetService;
|
|
26
|
-
this.projectService = projectService;
|
|
27
|
-
this.http = http;
|
|
28
|
-
this.configService = configService;
|
|
29
|
-
this.playState = 'paused';
|
|
30
|
-
this.zoom = 0;
|
|
31
|
-
this.timelineClicking = false;
|
|
32
|
-
this.intensity = 0.2;
|
|
33
|
-
this.intensitySelectedScene = 0.4;
|
|
34
|
-
this.intensityHighlighted = 0.8;
|
|
35
|
-
this.waveSurferReady = new Subject();
|
|
36
|
-
this.detectChanges = new Subject();
|
|
37
|
-
// can we add new compositions based on an external pool and
|
|
38
|
-
// should new compositions not available in this pool be added there?
|
|
39
|
-
this.externalCompositionsAvailable = false;
|
|
40
|
-
this.loadingAudioFile = false;
|
|
41
|
-
this.presetService.previewSelectionChanged.subscribe(() => {
|
|
42
|
-
this.selectedPlaybackRegion = undefined;
|
|
43
|
-
this.updateRegionSelection();
|
|
44
|
-
});
|
|
45
|
-
this.sceneService.sceneDeleted.subscribe(() => {
|
|
46
|
-
this.redrawAllRegions();
|
|
47
|
-
});
|
|
48
|
-
this.sceneService.sceneSelected.subscribe(() => {
|
|
49
|
-
this.redrawAllRegions();
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
redrawAllRegions() {
|
|
53
|
-
// remove all regions from wavesurver
|
|
54
|
-
if (this.waveSurfer) {
|
|
55
|
-
for (const key of Object.keys(this.waveSurfer.regions.list)) {
|
|
56
|
-
const region = this.waveSurfer.regions.list[key];
|
|
57
|
-
region.remove();
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
// draw all regions
|
|
61
|
-
this.drawAllRegions();
|
|
62
|
-
}
|
|
63
|
-
pad(num, size) {
|
|
64
|
-
if (!num) {
|
|
65
|
-
num = 0;
|
|
66
|
-
}
|
|
67
|
-
let padded = num.toString();
|
|
68
|
-
while (padded.length < size) {
|
|
69
|
-
padded = '0' + padded;
|
|
70
|
-
}
|
|
71
|
-
return padded;
|
|
72
|
-
}
|
|
73
|
-
msToTime(millis, includeMillis = true) {
|
|
74
|
-
const ms = Math.round(millis % 1000);
|
|
75
|
-
const seconds = Math.floor(((millis % 360000) % 60000) / 1000);
|
|
76
|
-
const minutes = Math.floor((millis % 3600000) / 60000);
|
|
77
|
-
if (includeMillis) {
|
|
78
|
-
return this.pad(minutes, 2) + ':' + this.pad(seconds, 2) + '.' + this.pad(ms, 3);
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
81
|
-
return this.pad(minutes, 2) + ':' + this.pad(seconds, 2);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
updateCurrentTime() {
|
|
85
|
-
if (!this.waveSurfer) {
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
// display the current time
|
|
89
|
-
this.currentTime = this.msToTime(this.waveSurfer.getCurrentTime() * 1000);
|
|
90
|
-
if (!this.waveSurfer.timeline.drawer) {
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
// draw the current cursor on the timeline
|
|
94
|
-
// TODO redrawing the timeline each update is way to expensive.
|
|
95
|
-
// maybe as a better solution use an element, like the cursor inside Wavesurfer to
|
|
96
|
-
// display the progress?
|
|
97
|
-
let x = 0;
|
|
98
|
-
const duration = this.waveSurfer.backend.getDuration();
|
|
99
|
-
const width = this.waveSurfer.params.fillParent && !this.waveSurfer.params.scrollParent
|
|
100
|
-
? this.waveSurfer.timeline.drawer.getWidth()
|
|
101
|
-
: this.waveSurfer.timeline.drawer.wrapper.scrollWidth * this.waveSurfer.params.pixelRatio;
|
|
102
|
-
x = (width / duration) * this.waveSurfer.getCurrentTime() - 2;
|
|
103
|
-
// update the timeline canvas
|
|
104
|
-
this.waveSurfer.timeline.render();
|
|
105
|
-
// draw the cursor on the timeline
|
|
106
|
-
this.waveSurfer.timeline.canvases.forEach((canvas, i) => {
|
|
107
|
-
const leftOffset = i * this.waveSurfer.timeline.maxCanvasWidth;
|
|
108
|
-
const ctx = canvas.getContext('2d');
|
|
109
|
-
ctx.fillStyle = '#fd7e14';
|
|
110
|
-
ctx.beginPath();
|
|
111
|
-
ctx.moveTo(x - 12 - leftOffset, 20);
|
|
112
|
-
ctx.lineTo(x + 12 - leftOffset, 20);
|
|
113
|
-
ctx.lineTo(x - leftOffset, 45);
|
|
114
|
-
ctx.fill();
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
startTimeUpdater() {
|
|
118
|
-
this.stopTimeUpdater();
|
|
119
|
-
const timeUpdater = timer(0, 40);
|
|
120
|
-
this.timeUpdateSubscription = timeUpdater.subscribe(() => {
|
|
121
|
-
this.updateCurrentTime();
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
stopTimeUpdater() {
|
|
125
|
-
if (this.timeUpdateSubscription) {
|
|
126
|
-
this.timeUpdateSubscription.unsubscribe();
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
formatTimeCallback(seconds, pxPerSec) {
|
|
130
|
-
if (this.selectedComposition.gridType === 'musical') {
|
|
131
|
-
return Math.round(seconds / this.selectedComposition.timeSignatureUpper / (60 / this.selectedComposition.beatsPerMinute));
|
|
132
|
-
}
|
|
133
|
-
else {
|
|
134
|
-
// calculate minutes and seconds from seconds count
|
|
135
|
-
const minutes = parseInt((seconds / 60), 10);
|
|
136
|
-
seconds = parseInt((seconds % 60), 10);
|
|
137
|
-
// fill up seconds with zeroes
|
|
138
|
-
const secondsStr = seconds < 10 ? '0' + seconds : seconds;
|
|
139
|
-
return `${minutes}:${secondsStr}`;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
timeInterval(pxPerSec) {
|
|
143
|
-
if (this.selectedComposition.gridType === 'musical') {
|
|
144
|
-
const interval = 60 / this.selectedComposition.beatsPerMinute / this.selectedComposition.gridResolution;
|
|
145
|
-
if (pxPerSec < 40) {
|
|
146
|
-
return interval * 4;
|
|
147
|
-
}
|
|
148
|
-
else if (pxPerSec < 80) {
|
|
149
|
-
return interval * 2;
|
|
150
|
-
}
|
|
151
|
-
return interval;
|
|
152
|
-
}
|
|
153
|
-
else {
|
|
154
|
-
if (pxPerSec >= 25) {
|
|
155
|
-
return 1;
|
|
156
|
-
}
|
|
157
|
-
else if (pxPerSec * 5 >= 25) {
|
|
158
|
-
return 5;
|
|
159
|
-
}
|
|
160
|
-
else if (pxPerSec * 15 >= 25) {
|
|
161
|
-
return 15;
|
|
162
|
-
}
|
|
163
|
-
return Math.ceil(0.5 / pxPerSec) * 60;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
primaryLabelInterval(pxPerSec) {
|
|
167
|
-
if (this.selectedComposition.gridType === 'musical') {
|
|
168
|
-
const interval = this.selectedComposition.timeSignatureUpper * this.selectedComposition.gridResolution;
|
|
169
|
-
return interval;
|
|
170
|
-
}
|
|
171
|
-
else {
|
|
172
|
-
if (pxPerSec >= 25) {
|
|
173
|
-
return 10;
|
|
174
|
-
}
|
|
175
|
-
else if (pxPerSec * 5 >= 25) {
|
|
176
|
-
return 6;
|
|
177
|
-
}
|
|
178
|
-
else if (pxPerSec * 15 >= 25) {
|
|
179
|
-
return 4;
|
|
180
|
-
}
|
|
181
|
-
return 4;
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
secondaryLabelInterval(pxPerSec) {
|
|
185
|
-
if (this.selectedComposition.gridType === 'musical') {
|
|
186
|
-
return 0;
|
|
187
|
-
}
|
|
188
|
-
else {
|
|
189
|
-
if (pxPerSec >= 25) {
|
|
190
|
-
return 5;
|
|
191
|
-
}
|
|
192
|
-
else if (pxPerSec * 5 >= 25) {
|
|
193
|
-
return 2;
|
|
194
|
-
}
|
|
195
|
-
else if (pxPerSec * 15 >= 25) {
|
|
196
|
-
return 2;
|
|
197
|
-
}
|
|
198
|
-
return 2;
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
seeekWithTimeline(e) {
|
|
202
|
-
// taken from wavesurfer -> drawer -> handleEvent
|
|
203
|
-
const clientX = e.targetTouches ? e.targetTouches[0].clientX : e.clientX;
|
|
204
|
-
const bbox = this.waveSurfer.timeline.wrapper.getBoundingClientRect();
|
|
205
|
-
const nominalWidth = this.waveSurfer.timeline.drawer.width;
|
|
206
|
-
const parentWidth = this.waveSurfer.timeline.drawer.getWidth();
|
|
207
|
-
let progress;
|
|
208
|
-
if (!this.waveSurfer.timeline.drawer.params.fillParent && nominalWidth < parentWidth) {
|
|
209
|
-
progress =
|
|
210
|
-
(this.waveSurfer.timeline.drawer.params.rtl ? bbox.right - clientX : clientX - bbox.left) *
|
|
211
|
-
(this.waveSurfer.timeline.drawer.params.pixelRatio / nominalWidth) || 0;
|
|
212
|
-
if (progress > 1) {
|
|
213
|
-
progress = 1;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
else {
|
|
217
|
-
progress =
|
|
218
|
-
((this.waveSurfer.timeline.drawer.params.rtl ? bbox.right - clientX : clientX - bbox.left) +
|
|
219
|
-
this.waveSurfer.timeline.wrapper.scrollLeft) /
|
|
220
|
-
this.waveSurfer.timeline.wrapper.scrollWidth || 0;
|
|
221
|
-
}
|
|
222
|
-
progress = Math.max(progress, 0);
|
|
223
|
-
setTimeout(() => {
|
|
224
|
-
this.waveSurfer.seekTo(progress);
|
|
225
|
-
this.detectChanges.next();
|
|
226
|
-
this.presetService.previewLive(this.selectedComposition.name, Math.round(this.waveSurfer.getCurrentTime() * 1000));
|
|
227
|
-
}, 0);
|
|
228
|
-
}
|
|
229
|
-
applyZoom(zoom) {
|
|
230
|
-
if (zoom < 0 || zoom > 200) {
|
|
231
|
-
return;
|
|
232
|
-
}
|
|
233
|
-
this.zoom = zoom;
|
|
234
|
-
if (this.waveSurfer) {
|
|
235
|
-
setTimeout(() => {
|
|
236
|
-
this.waveSurfer.zoom(this.zoom);
|
|
237
|
-
this.updateCurrentTime();
|
|
238
|
-
}, 0);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
isWaveSurferReady() {
|
|
242
|
-
if (!this.waveSurfer) {
|
|
243
|
-
return false;
|
|
244
|
-
}
|
|
245
|
-
if (!this.waveSurfer.isReady) {
|
|
246
|
-
return false;
|
|
247
|
-
}
|
|
248
|
-
return true;
|
|
249
|
-
}
|
|
250
|
-
addRegion(waveSurferRegion) {
|
|
251
|
-
if (!this.isWaveSurferReady()) {
|
|
252
|
-
return;
|
|
253
|
-
}
|
|
254
|
-
if (!this.sceneService.selectedScenes || this.sceneService.selectedScenes.length !== 1) {
|
|
255
|
-
return;
|
|
256
|
-
}
|
|
257
|
-
if (!this.selectedComposition) {
|
|
258
|
-
return;
|
|
259
|
-
}
|
|
260
|
-
const scenePlaybackRegion = new ScenePlaybackRegion();
|
|
261
|
-
scenePlaybackRegion.sceneUuid = this.sceneService.selectedScenes[0].uuid;
|
|
262
|
-
if (waveSurferRegion) {
|
|
263
|
-
scenePlaybackRegion.startMillis = waveSurferRegion.start * 1000;
|
|
264
|
-
scenePlaybackRegion.endMillis = waveSurferRegion.end * 1000;
|
|
265
|
-
}
|
|
266
|
-
else {
|
|
267
|
-
scenePlaybackRegion.startMillis = (this.waveSurfer.getDuration() * 1000) / 3;
|
|
268
|
-
scenePlaybackRegion.endMillis = ((this.waveSurfer.getDuration() * 1000) / 3) * 2;
|
|
269
|
-
}
|
|
270
|
-
this.selectedComposition.scenePlaybackRegions.push(scenePlaybackRegion);
|
|
271
|
-
this.selectedPlaybackRegion = scenePlaybackRegion;
|
|
272
|
-
if (waveSurferRegion) {
|
|
273
|
-
waveSurferRegion.color =
|
|
274
|
-
'rgba(' +
|
|
275
|
-
this.hexToRgb(this.sceneService.selectedScenes[0].color).r +
|
|
276
|
-
', ' +
|
|
277
|
-
this.hexToRgb(this.sceneService.selectedScenes[0].color).g +
|
|
278
|
-
', ' +
|
|
279
|
-
this.hexToRgb(this.sceneService.selectedScenes[0].color).b +
|
|
280
|
-
', ' +
|
|
281
|
-
this.intensityHighlighted +
|
|
282
|
-
')';
|
|
283
|
-
waveSurferRegion.attributes.selectable = true;
|
|
284
|
-
this.connectRegion(waveSurferRegion, this.sceneService.selectedScenes[0], scenePlaybackRegion);
|
|
285
|
-
this.updateRegionSelection();
|
|
286
|
-
}
|
|
287
|
-
else {
|
|
288
|
-
this.drawRegion(scenePlaybackRegion, this.sceneService.selectedScenes[0]);
|
|
289
|
-
}
|
|
290
|
-
this.presetService.previewLive();
|
|
291
|
-
}
|
|
292
|
-
getSnapToGridInterval() {
|
|
293
|
-
if (this.selectedComposition.snapToGrid) {
|
|
294
|
-
return 60 / this.selectedComposition.beatsPerMinute / this.selectedComposition.gridResolution;
|
|
295
|
-
}
|
|
296
|
-
return undefined;
|
|
297
|
-
}
|
|
298
|
-
getSnapToGridOffset() {
|
|
299
|
-
return this.selectedComposition.gridOffsetMillis / 1000;
|
|
300
|
-
}
|
|
301
|
-
deleteSelectedComposition() {
|
|
302
|
-
this.projectService.project.compositions.splice(this.selectedCompositionIndex, 1);
|
|
303
|
-
this.selectedComposition = undefined;
|
|
304
|
-
this.selectedCompositionIndex = undefined;
|
|
305
|
-
this.destroyWaveSurfer();
|
|
306
|
-
if (this.projectService.project.compositions.length > 0) {
|
|
307
|
-
this.selectCompositionIndex(0);
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
destroyWaveSurfer() {
|
|
311
|
-
this.duration = undefined;
|
|
312
|
-
this.loadingAudioFile = false;
|
|
313
|
-
if (this.waveSurfer) {
|
|
314
|
-
this.waveSurfer.destroy();
|
|
315
|
-
this.waveSurfer = undefined;
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
createWaveSurfer() {
|
|
319
|
-
this.destroyWaveSurfer();
|
|
320
|
-
if (!this.selectedComposition.audioFileName) {
|
|
321
|
-
return;
|
|
322
|
-
}
|
|
323
|
-
this.loadingAudioFile = true;
|
|
324
|
-
setTimeout(() => {
|
|
325
|
-
this.waveSurfer = WaveSurfer.create({
|
|
326
|
-
container: '#waveform',
|
|
327
|
-
waveColor: 'white',
|
|
328
|
-
progressColor: 'white',
|
|
329
|
-
// barWidth: 2,
|
|
330
|
-
height: 1,
|
|
331
|
-
interact: false,
|
|
332
|
-
// Use for timelines without sound. Wave will be displayed
|
|
333
|
-
// wrong, but should work for a dummy audio without any waves.
|
|
334
|
-
// duration: 400,
|
|
335
|
-
plugins: [
|
|
336
|
-
CursorPlugin.create({
|
|
337
|
-
// showTime: true,
|
|
338
|
-
opacity: 1,
|
|
339
|
-
color: '#fd7e14',
|
|
340
|
-
hideOnBlur: false /* don't show/hide the cursor on the wave (only on the timeline) */,
|
|
341
|
-
}),
|
|
342
|
-
RegionsPlugin.create({
|
|
343
|
-
dragSelection: {
|
|
344
|
-
slop: 5,
|
|
345
|
-
},
|
|
346
|
-
color: '#fff',
|
|
347
|
-
snapToGridInterval: this.getSnapToGridInterval(),
|
|
348
|
-
snapToGridOffset: this.getSnapToGridOffset(),
|
|
349
|
-
}),
|
|
350
|
-
TimeLinePlugin.create({
|
|
351
|
-
container: '#waveform-timeline',
|
|
352
|
-
primaryFontColor: '#fff',
|
|
353
|
-
secondaryFontColor: '#fff',
|
|
354
|
-
offset: this.getSnapToGridOffset(),
|
|
355
|
-
formatTimeCallback: this.formatTimeCallback.bind(this),
|
|
356
|
-
timeInterval: this.timeInterval.bind(this),
|
|
357
|
-
primaryLabelInterval: this.primaryLabelInterval.bind(this),
|
|
358
|
-
secondaryLabelInterval: this.secondaryLabelInterval.bind(this),
|
|
359
|
-
}),
|
|
360
|
-
],
|
|
361
|
-
});
|
|
362
|
-
let audioFileName;
|
|
363
|
-
if (this.configService.enableMediaLibrary) {
|
|
364
|
-
// the file name is also used for the real file name
|
|
365
|
-
audioFileName = 'file/get?name=' + this.selectedComposition.audioFileName + '&type=AUDIO';
|
|
366
|
-
}
|
|
367
|
-
else {
|
|
368
|
-
// the composition uuid and extension is used as the file name
|
|
369
|
-
audioFileName =
|
|
370
|
-
'composition-files/?file=' +
|
|
371
|
-
this.selectedComposition.uuid +
|
|
372
|
-
'.' +
|
|
373
|
-
this.selectedComposition.audioFileName.substr(this.selectedComposition.audioFileName.lastIndexOf('.') + 1);
|
|
374
|
-
}
|
|
375
|
-
this.waveSurfer.load(this.configService.restUrl + audioFileName);
|
|
376
|
-
this.waveSurfer.on('ready', () => {
|
|
377
|
-
setTimeout(() => {
|
|
378
|
-
// try guessing the bpm and offset from the file, if necessary
|
|
379
|
-
if (this.selectedComposition.tempoGuessed) {
|
|
380
|
-
// we already guessed the BPM of this file --> don't do it again
|
|
381
|
-
this.loadingAudioFile = false;
|
|
382
|
-
}
|
|
383
|
-
else {
|
|
384
|
-
// we have not yet guessed the BPM --> do it now
|
|
385
|
-
this.selectedComposition.tempoGuessed = true;
|
|
386
|
-
guess(this.waveSurfer.backend.buffer)
|
|
387
|
-
.then(({ bpm, offset }) => {
|
|
388
|
-
// the bpm and offset could be guessed
|
|
389
|
-
this.selectedComposition.beatsPerMinute = bpm;
|
|
390
|
-
this.selectedComposition.gridOffsetMillis = offset * 1000;
|
|
391
|
-
this.loadingAudioFile = false;
|
|
392
|
-
})
|
|
393
|
-
.catch((err) => {
|
|
394
|
-
// something went wrong
|
|
395
|
-
console.error('Could not detect the BPM from the audio file', err);
|
|
396
|
-
this.loadingAudioFile = false;
|
|
397
|
-
});
|
|
398
|
-
}
|
|
399
|
-
this.duration = this.msToTime(this.waveSurfer.getDuration() * 1000);
|
|
400
|
-
this.drawAllRegions();
|
|
401
|
-
// scroll wavesurfer in sync with the timeline
|
|
402
|
-
this.waveSurfer.timeline.wrapper.addEventListener('scroll', () => {
|
|
403
|
-
this.waveSurfer.drawer.wrapper.scrollLeft = this.waveSurfer.timeline.wrapper.scrollLeft;
|
|
404
|
-
// Set the scroll position of the timeline to the same position as the wavesurfer,
|
|
405
|
-
// because the timeline is larger than wavesurfer and might get out of sync.
|
|
406
|
-
// This way, if wavesurfer cannot scroll any further, we reset the position
|
|
407
|
-
// of the timeline as well.
|
|
408
|
-
this.waveSurfer.timeline.wrapper.scrollLeft = this.waveSurfer.drawer.wrapper.scrollLeft;
|
|
409
|
-
});
|
|
410
|
-
// display the cursor also on the timeline
|
|
411
|
-
this.waveSurfer.timeline.wrapper.addEventListener('mouseenter', () => {
|
|
412
|
-
this.waveSurfer.cursor.showCursor();
|
|
413
|
-
});
|
|
414
|
-
this.waveSurfer.timeline.wrapper.addEventListener('mouseleave', () => {
|
|
415
|
-
this.waveSurfer.cursor.hideCursor();
|
|
416
|
-
});
|
|
417
|
-
this.waveSurfer.timeline.wrapper.addEventListener('mousemove', (e) => {
|
|
418
|
-
const bbox = this.waveSurfer.container.getBoundingClientRect();
|
|
419
|
-
const x = e.clientX - bbox.left;
|
|
420
|
-
this.waveSurfer.cursor.updateCursorPosition(x, 0);
|
|
421
|
-
});
|
|
422
|
-
// hide the cursor on the wave initially. in combination with the param hideOnBlur = false,
|
|
423
|
-
// it will never be displayed on the wave now. we handle it on the timeline only.
|
|
424
|
-
this.waveSurfer.cursor.hideCursor();
|
|
425
|
-
// seek on timeline-click
|
|
426
|
-
this.waveSurfer.timeline.wrapper.addEventListener('mousedown', (e) => {
|
|
427
|
-
this.timelineClicking = true;
|
|
428
|
-
this.seeekWithTimeline(e);
|
|
429
|
-
});
|
|
430
|
-
this.waveSurfer.timeline.wrapper.addEventListener('mousemove', (e) => {
|
|
431
|
-
if (this.timelineClicking) {
|
|
432
|
-
this.seeekWithTimeline(e);
|
|
433
|
-
}
|
|
434
|
-
});
|
|
435
|
-
this.waveSurfer.timeline.wrapper.addEventListener('mouseup', (e) => {
|
|
436
|
-
this.timelineClicking = false;
|
|
437
|
-
});
|
|
438
|
-
this.updateCurrentTime();
|
|
439
|
-
this.detectChanges.next();
|
|
440
|
-
this.waveSurferReady.next();
|
|
441
|
-
}, 0);
|
|
442
|
-
});
|
|
443
|
-
this.waveSurfer.on('error', (error) => {
|
|
444
|
-
// could not load the composition --> delete it
|
|
445
|
-
// (this may occur, when the composition has been deleted but the project is not saved afterwards)
|
|
446
|
-
this.deleteSelectedComposition();
|
|
447
|
-
});
|
|
448
|
-
this.waveSurfer.on('seek', () => {
|
|
449
|
-
this.updateCurrentTime();
|
|
450
|
-
});
|
|
451
|
-
this.waveSurfer.on('play', () => {
|
|
452
|
-
this.startTimeUpdater();
|
|
453
|
-
});
|
|
454
|
-
this.waveSurfer.on('pause', () => {
|
|
455
|
-
this.stopTimeUpdater();
|
|
456
|
-
});
|
|
457
|
-
this.waveSurfer.on('region-created', (region) => {
|
|
458
|
-
// region created by selection or programmatically
|
|
459
|
-
if (this.sceneService.selectedScenes && this.sceneService.selectedScenes.length === 1) {
|
|
460
|
-
if (!region.data.handled) {
|
|
461
|
-
this.addRegion(region);
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
else {
|
|
465
|
-
if (!region.data.handled) {
|
|
466
|
-
region.remove();
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
});
|
|
470
|
-
this.waveSurfer.on('region-updated', (region) => {
|
|
471
|
-
this.detectChanges.next();
|
|
472
|
-
this.presetService.previewLive();
|
|
473
|
-
});
|
|
474
|
-
}, 0);
|
|
475
|
-
}
|
|
476
|
-
hexToRgb(hex) {
|
|
477
|
-
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
478
|
-
return result
|
|
479
|
-
? {
|
|
480
|
-
r: parseInt(result[1], 16),
|
|
481
|
-
g: parseInt(result[2], 16),
|
|
482
|
-
b: parseInt(result[3], 16),
|
|
483
|
-
}
|
|
484
|
-
: null;
|
|
485
|
-
}
|
|
486
|
-
updateRegionSelection() {
|
|
487
|
-
if (!this.waveSurfer) {
|
|
488
|
-
return;
|
|
489
|
-
}
|
|
490
|
-
for (const key of Object.keys(this.waveSurfer.regions.list)) {
|
|
491
|
-
const region = this.waveSurfer.regions.list[key];
|
|
492
|
-
// if no scene is set, the region is not valid (e.g. has been created, while
|
|
493
|
-
// no scene has been selected and remove did not work properly)
|
|
494
|
-
if (region.scene) {
|
|
495
|
-
let intensity = this.intensity;
|
|
496
|
-
region.drag = false;
|
|
497
|
-
region.resize = false;
|
|
498
|
-
region.attributes.selectable = false;
|
|
499
|
-
if (this.sceneService.sceneIsSelected(region.scene)) {
|
|
500
|
-
intensity = this.intensitySelectedScene;
|
|
501
|
-
region.drag = true;
|
|
502
|
-
region.resize = true;
|
|
503
|
-
region.attributes.selectable = true;
|
|
504
|
-
}
|
|
505
|
-
region.attributes.selected = false;
|
|
506
|
-
if (this.selectedPlaybackRegion && this.selectedPlaybackRegion === region.scenePlaybackRegion) {
|
|
507
|
-
intensity = this.intensityHighlighted;
|
|
508
|
-
region.attributes.selected = true;
|
|
509
|
-
}
|
|
510
|
-
region.color =
|
|
511
|
-
'rgba(' +
|
|
512
|
-
this.hexToRgb(region.scene.color).r +
|
|
513
|
-
', ' +
|
|
514
|
-
this.hexToRgb(region.scene.color).g +
|
|
515
|
-
', ' +
|
|
516
|
-
this.hexToRgb(region.scene.color).b +
|
|
517
|
-
', ' +
|
|
518
|
-
intensity +
|
|
519
|
-
')';
|
|
520
|
-
region.updateRender();
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
updateSelectedRegion() {
|
|
525
|
-
if (!this.waveSurfer) {
|
|
526
|
-
return;
|
|
527
|
-
}
|
|
528
|
-
if (!this.selectedPlaybackRegion) {
|
|
529
|
-
return;
|
|
530
|
-
}
|
|
531
|
-
for (const key of Object.keys(this.waveSurfer.regions.list)) {
|
|
532
|
-
const region = this.waveSurfer.regions.list[key];
|
|
533
|
-
if (this.selectedPlaybackRegion === region.scenePlaybackRegion) {
|
|
534
|
-
region.start = this.selectedPlaybackRegion.startMillis / 1000;
|
|
535
|
-
region.end = this.selectedPlaybackRegion.endMillis / 1000;
|
|
536
|
-
region.updateRender();
|
|
537
|
-
break;
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
setSelectedRegion(scenePlaybackRegion) {
|
|
542
|
-
if (this.selectedPlaybackRegion && this.selectedPlaybackRegion === scenePlaybackRegion) {
|
|
543
|
-
// No update required
|
|
544
|
-
return;
|
|
545
|
-
}
|
|
546
|
-
if (scenePlaybackRegion) {
|
|
547
|
-
this.selectedPlaybackRegion = scenePlaybackRegion;
|
|
548
|
-
}
|
|
549
|
-
this.updateRegionSelection();
|
|
550
|
-
}
|
|
551
|
-
getRegionSnapToGridValue(value) {
|
|
552
|
-
// the regions should snap to a grid
|
|
553
|
-
const offset = this.getSnapToGridOffset() || 0;
|
|
554
|
-
const interval = this.getSnapToGridInterval() || 0;
|
|
555
|
-
return Math.round((value - offset) / interval) * interval + offset;
|
|
556
|
-
}
|
|
557
|
-
connectRegion(waveSurferRegion, scene, scenePlaybackRegion, preset) {
|
|
558
|
-
waveSurferRegion.scenePlaybackRegion = scenePlaybackRegion;
|
|
559
|
-
waveSurferRegion.scene = scene;
|
|
560
|
-
waveSurferRegion.preset = preset;
|
|
561
|
-
waveSurferRegion.on('click', (event) => {
|
|
562
|
-
if (this.sceneService.sceneIsSelected(scene)) {
|
|
563
|
-
this.setSelectedRegion(scenePlaybackRegion);
|
|
564
|
-
}
|
|
565
|
-
});
|
|
566
|
-
waveSurferRegion.on('update', () => {
|
|
567
|
-
this.setSelectedRegion(scenePlaybackRegion);
|
|
568
|
-
if (this.selectedComposition.snapToGrid) {
|
|
569
|
-
// update the regions boundaries. they may not snap to grid, if it has been
|
|
570
|
-
// disabled during creation of the region but activated afterwards.
|
|
571
|
-
waveSurferRegion.start = this.getRegionSnapToGridValue(waveSurferRegion.start);
|
|
572
|
-
waveSurferRegion.end = this.getRegionSnapToGridValue(waveSurferRegion.end);
|
|
573
|
-
}
|
|
574
|
-
scenePlaybackRegion.startMillis = waveSurferRegion.start * 1000;
|
|
575
|
-
scenePlaybackRegion.endMillis = waveSurferRegion.end * 1000;
|
|
576
|
-
});
|
|
577
|
-
}
|
|
578
|
-
drawRegion(scenePlaybackRegion, scene) {
|
|
579
|
-
// draw the regions of the currently selected scene
|
|
580
|
-
if (!this.isWaveSurferReady()) {
|
|
581
|
-
return;
|
|
582
|
-
}
|
|
583
|
-
// add the playback region
|
|
584
|
-
const waveSurferRegion = this.waveSurfer.addRegion({
|
|
585
|
-
start: scenePlaybackRegion.startMillis / 1000,
|
|
586
|
-
end: scenePlaybackRegion.endMillis / 1000,
|
|
587
|
-
color: '#fff',
|
|
588
|
-
data: { handled: true },
|
|
589
|
-
});
|
|
590
|
-
this.connectRegion(waveSurferRegion, scene, scenePlaybackRegion);
|
|
591
|
-
// TODO show the all presets
|
|
592
|
-
// for (let presetUuid of scene.presetUuids) {
|
|
593
|
-
// const preset = this.presetService.getPresetByUuid(presetUuid);
|
|
594
|
-
// let waveSurferRegion = this.timelineService.waveSurfer.addRegion({
|
|
595
|
-
// start: (scenePlaybackRegion.startMillis + (preset.startMillis ? preset.startMillis : 0)) / 1000,
|
|
596
|
-
// end: (scenePlaybackRegion.startMillis
|
|
597
|
-
// + (preset.endMillis ? preset.endMillis : scenePlaybackRegion.endMillis - scenePlaybackRegion.startMillis)) / 1000,
|
|
598
|
-
// color: '#fff',
|
|
599
|
-
// data: { handled: true },
|
|
600
|
-
// // TODO
|
|
601
|
-
// attributes: {
|
|
602
|
-
// preset: true,
|
|
603
|
-
// name: 'Preset 1'
|
|
604
|
-
// }
|
|
605
|
-
// });
|
|
606
|
-
// this.connectRegion(waveSurferRegion, scene, scenePlaybackRegion, preset);
|
|
607
|
-
// }
|
|
608
|
-
this.updateRegionSelection();
|
|
609
|
-
}
|
|
610
|
-
removeRegion() {
|
|
611
|
-
if (!this.selectedPlaybackRegion) {
|
|
612
|
-
return;
|
|
613
|
-
}
|
|
614
|
-
if (this.sceneService.selectedScenes.length !== 1) {
|
|
615
|
-
return;
|
|
616
|
-
}
|
|
617
|
-
for (let i = 0; i < this.selectedComposition.scenePlaybackRegions.length; i++) {
|
|
618
|
-
if (this.selectedComposition.scenePlaybackRegions[i] === this.selectedPlaybackRegion) {
|
|
619
|
-
// remove the region from wavesurfer
|
|
620
|
-
for (const key of Object.keys(this.waveSurfer.regions.list)) {
|
|
621
|
-
const region = this.waveSurfer.regions.list[key];
|
|
622
|
-
if (region.scenePlaybackRegion === this.selectedPlaybackRegion) {
|
|
623
|
-
region.remove();
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
this.selectedPlaybackRegion = undefined;
|
|
627
|
-
this.selectedComposition.scenePlaybackRegions.splice(i, 1);
|
|
628
|
-
return;
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
this.presetService.previewLive();
|
|
632
|
-
}
|
|
633
|
-
getPresetsInTime(timeMillis) {
|
|
634
|
-
// Return all presets which should be active during the specified time
|
|
635
|
-
const activePresets = [];
|
|
636
|
-
for (let sceneIndex = this.projectService.project.scenes.length - 1; sceneIndex >= 0; sceneIndex--) {
|
|
637
|
-
const scene = this.projectService.project.scenes[sceneIndex];
|
|
638
|
-
for (const region of this.selectedComposition.scenePlaybackRegions) {
|
|
639
|
-
if (region.sceneUuid === scene.uuid) {
|
|
640
|
-
for (let presetIndex = this.projectService.project.presets.length - 1; presetIndex >= 0; presetIndex--) {
|
|
641
|
-
for (const presetUuid of scene.presetUuids) {
|
|
642
|
-
if (presetUuid === this.projectService.project.presets[presetIndex].uuid) {
|
|
643
|
-
const preset = this.presetService.getPresetByUuid(presetUuid);
|
|
644
|
-
if (preset) {
|
|
645
|
-
let presetStartMillis = preset.startMillis === undefined ? region.startMillis : region.startMillis + preset.startMillis;
|
|
646
|
-
let presetEndMillis = preset.endMillis === undefined ? region.endMillis : region.startMillis + preset.endMillis;
|
|
647
|
-
// extend the running time, if fading is done outside the boundaries
|
|
648
|
-
presetStartMillis -= preset.fadeInPre ? preset.fadeInMillis : 0;
|
|
649
|
-
presetEndMillis += preset.fadeOutPost ? preset.fadeOutMillis : 0;
|
|
650
|
-
if (presetStartMillis <= timeMillis && presetEndMillis >= timeMillis) {
|
|
651
|
-
activePresets.push(new PresetRegionScene(preset, region, scene));
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
return activePresets;
|
|
661
|
-
}
|
|
662
|
-
drawAllRegions() {
|
|
663
|
-
if (!this.selectedComposition) {
|
|
664
|
-
return;
|
|
665
|
-
}
|
|
666
|
-
// draw the regions in the same order as their corresponding scenes, but draw
|
|
667
|
-
// the selected ones last, to make sure they're always clickable.
|
|
668
|
-
for (let sceneIndex = this.projectService.project.scenes.length - 1; sceneIndex >= 0; sceneIndex--) {
|
|
669
|
-
const scene = this.projectService.project.scenes[sceneIndex];
|
|
670
|
-
if (!this.sceneService.sceneIsSelected(scene)) {
|
|
671
|
-
for (const scenePlaybackRegion of this.selectedComposition.scenePlaybackRegions) {
|
|
672
|
-
if (scenePlaybackRegion.sceneUuid === scene.uuid) {
|
|
673
|
-
this.drawRegion(scenePlaybackRegion, scene);
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
// draw all selected scenes afterwards
|
|
679
|
-
for (let sceneIndex = this.projectService.project.scenes.length - 1; sceneIndex >= 0; sceneIndex--) {
|
|
680
|
-
const scene = this.projectService.project.scenes[sceneIndex];
|
|
681
|
-
if (this.sceneService.sceneIsSelected(scene)) {
|
|
682
|
-
for (const scenePlaybackRegion of this.selectedComposition.scenePlaybackRegions) {
|
|
683
|
-
if (scenePlaybackRegion.sceneUuid === scene.uuid) {
|
|
684
|
-
this.drawRegion(scenePlaybackRegion, scene);
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
updateGrid() {
|
|
691
|
-
if (this.waveSurferReady) {
|
|
692
|
-
this.waveSurfer.timeline.params.offset = this.getSnapToGridOffset();
|
|
693
|
-
this.waveSurfer.regions.params.snapToGridInterval = this.getSnapToGridInterval();
|
|
694
|
-
this.waveSurfer.regions.params.snapToGridOffset = this.getSnapToGridOffset();
|
|
695
|
-
}
|
|
696
|
-
this.updateCurrentTime();
|
|
697
|
-
}
|
|
698
|
-
getExternalCompositionNames() {
|
|
699
|
-
// get available compositions from an external pool (e.g. Rocket Show)
|
|
700
|
-
return this.http.get('composition/list').pipe(map((response) => {
|
|
701
|
-
const compositionNames = [];
|
|
702
|
-
for (const responseComposition of response) {
|
|
703
|
-
compositionNames.push(responseComposition.name);
|
|
704
|
-
}
|
|
705
|
-
return compositionNames;
|
|
706
|
-
}));
|
|
707
|
-
}
|
|
708
|
-
selectCompositionIndex(index) {
|
|
709
|
-
this.selectedComposition = this.projectService.project.compositions[index];
|
|
710
|
-
this.selectedCompositionIndex = index;
|
|
711
|
-
this.projectService.project.selectedCompositionUuid = this.selectedComposition.uuid;
|
|
712
|
-
this.createWaveSurfer();
|
|
713
|
-
// required to trigger timeline.component.resize()
|
|
714
|
-
this.waveSurferReady.next();
|
|
715
|
-
this.applyZoom(0);
|
|
716
|
-
}
|
|
717
|
-
static { this.ɵfac = function TimelineService_Factory(t) { return new (t || TimelineService)(i0.ɵɵinject(i1.SceneService), i0.ɵɵinject(i2.PresetService), i0.ɵɵinject(i3.ProjectService), i0.ɵɵinject(i4.HttpClient), i0.ɵɵinject(i5.ConfigService)); }; }
|
|
718
|
-
static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: TimelineService, factory: TimelineService.ɵfac, providedIn: 'root' }); }
|
|
719
|
-
}
|
|
720
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TimelineService, [{
|
|
721
|
-
type: Injectable,
|
|
722
|
-
args: [{
|
|
723
|
-
providedIn: 'root',
|
|
724
|
-
}]
|
|
725
|
-
}], () => [{ type: i1.SceneService }, { type: i2.PresetService }, { type: i3.ProjectService }, { type: i4.HttpClient }, { type: i5.ConfigService }], null); })();
|
|
726
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGltZWxpbmUuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2Rlc2lnbmVyL3NyYy9saWIvc2VydmljZXMvdGltZWxpbmUuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDbEQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzQyxPQUFPLEVBQWMsT0FBTyxFQUFnQixLQUFLLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDaEUsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3JDLE9BQU8sVUFBVSxNQUFNLGVBQWUsQ0FBQztBQUN2QyxPQUFPLFlBQVksTUFBTSxvREFBb0QsQ0FBQztBQUM5RSxPQUFPLGFBQWEsTUFBTSxxREFBcUQsQ0FBQztBQUNoRixPQUFPLGNBQWMsTUFBTSxzREFBc0QsQ0FBQztBQUNsRixPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFHaEQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFFbEUsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDdEUsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ2pELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNqRCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDbkQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDOzs7Ozs7O0FBSy9DLE1BQU0sT0FBTyxlQUFlO0lBMEIxQixZQUNVLFlBQTBCLEVBQzFCLGFBQTRCLEVBQzVCLGNBQThCLEVBQzlCLElBQWdCLEVBQ2hCLGFBQTRCO1FBSjVCLGlCQUFZLEdBQVosWUFBWSxDQUFjO1FBQzFCLGtCQUFhLEdBQWIsYUFBYSxDQUFlO1FBQzVCLG1CQUFjLEdBQWQsY0FBYyxDQUFnQjtRQUM5QixTQUFJLEdBQUosSUFBSSxDQUFZO1FBQ2hCLGtCQUFhLEdBQWIsYUFBYSxDQUFlO1FBN0IvQixjQUFTLEdBQUcsUUFBUSxDQUFDO1FBRXJCLFNBQUksR0FBRyxDQUFDLENBQUM7UUFHUixxQkFBZ0IsR0FBRyxLQUFLLENBQUM7UUFFekIsY0FBUyxHQUFHLEdBQUcsQ0FBQztRQUNoQiwyQkFBc0IsR0FBRyxHQUFHLENBQUM7UUFDN0IseUJBQW9CLEdBQUcsR0FBRyxDQUFDO1FBRTVCLG9CQUFlLEdBQWtCLElBQUksT0FBTyxFQUFFLENBQUM7UUFDL0Msa0JBQWEsR0FBa0IsSUFBSSxPQUFPLEVBQUUsQ0FBQztRQU1wRCw0REFBNEQ7UUFDNUQscUVBQXFFO1FBQzlELGtDQUE2QixHQUFHLEtBQUssQ0FBQztRQUV0QyxxQkFBZ0IsR0FBRyxLQUFLLENBQUM7UUFTOUIsSUFBSSxDQUFDLGFBQWEsQ0FBQyx1QkFBdUIsQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFO1lBQ3hELElBQUksQ0FBQyxzQkFBc0IsR0FBRyxTQUFTLENBQUM7WUFDeEMsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7UUFDL0IsQ0FBQyxDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFO1lBQzVDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1FBQzFCLENBQUMsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLFlBQVksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRTtZQUM3QyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztRQUMxQixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTyxnQkFBZ0I7UUFDdEIscUNBQXFDO1FBQ3JDLElBQUksSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ3BCLEtBQUssTUFBTSxHQUFHLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO2dCQUM1RCxNQUFNLE1BQU0sR0FBUSxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQ3RELE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNsQixDQUFDO1FBQ0gsQ0FBQztRQUVELG1CQUFtQjtRQUNuQixJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7SUFDeEIsQ0FBQztJQUVPLEdBQUcsQ0FBQyxHQUFXLEVBQUUsSUFBWTtRQUNuQyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDVCxHQUFHLEdBQUcsQ0FBQyxDQUFDO1FBQ1YsQ0FBQztRQUVELElBQUksTUFBTSxHQUFXLEdBQUcsQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNwQyxPQUFPLE1BQU0sQ0FBQyxNQUFNLEdBQUcsSUFBSSxFQUFFLENBQUM7WUFDNUIsTUFBTSxHQUFHLEdBQUcsR0FBRyxNQUFNLENBQUM7UUFDeEIsQ0FBQztRQUVELE9BQU8sTUFBTSxDQUFDO0lBQ2hCLENBQUM7SUFFTyxRQUFRLENBQUMsTUFBYyxFQUFFLGdCQUF5QixJQUFJO1FBQzVELE1BQU0sRUFBRSxHQUFXLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxDQUFDO1FBQzdDLE1BQU0sT0FBTyxHQUFXLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUMsR0FBRyxLQUFLLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQztRQUN2RSxNQUFNLE9BQU8sR0FBVyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDO1FBRS9ELElBQUksYUFBYSxFQUFFLENBQUM7WUFDbEIsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsR0FBRyxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLEdBQUcsR0FBRyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ25GLENBQUM7YUFBTSxDQUFDO1lBQ04sT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsR0FBRyxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDM0QsQ0FBQztJQUNILENBQUM7SUFFTyxpQkFBaUI7UUFDdkIsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUNyQixPQUFPO1FBQ1QsQ0FBQztRQUVELDJCQUEyQjtRQUMzQixJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxjQUFjLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQztRQUUxRSxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDckMsT0FBTztRQUNULENBQUM7UUFFRCwwQ0FBMEM7UUFDMUMsK0RBQStEO1FBQy9ELGtGQUFrRjtRQUNsRix3QkFBd0I7UUFDeEIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ1YsTUFBTSxRQUFRLEdBQVcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDL0QsTUFBTSxLQUFLLEdBQ1QsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsVUFBVSxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsWUFBWTtZQUN2RSxDQUFDLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRTtZQUM1QyxDQUFDLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDO1FBRTlGLENBQUMsR0FBRyxDQUFDLEtBQUssR0FBRyxRQUFRLENBQUMsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLGNBQWMsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUU5RCw2QkFBNkI7UUFDN0IsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLENBQUM7UUFFbEMsa0NBQWtDO1FBQ2xDLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDdEQsTUFBTSxVQUFVLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLGNBQWMsQ0FBQztZQUUvRCxNQUFNLEdBQUcsR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBRXBDLEdBQUcsQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFDO1lBQzFCLEdBQUcsQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUNoQixHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxFQUFFLEdBQUcsVUFBVSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQ3BDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxVQUFVLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDcEMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsVUFBVSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQy9CLEdBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNiLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVPLGdCQUFnQjtRQUN0QixJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7UUFFdkIsTUFBTSxXQUFXLEdBQUcsS0FBSyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUNqQyxJQUFJLENBQUMsc0JBQXNCLEdBQUcsV0FBVyxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUU7WUFDdkQsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7UUFDM0IsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU8sZUFBZTtRQUNyQixJQUFJLElBQUksQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO1lBQ2hDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUM1QyxDQUFDO0lBQ0gsQ0FBQztJQUVELGtCQUFrQixDQUFDLE9BQWUsRUFBRSxRQUFnQjtRQUNsRCxJQUFJLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxRQUFRLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDcEQsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQUMsa0JBQWtCLEdBQUcsQ0FBQyxFQUFFLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUM7UUFDNUgsQ0FBQzthQUFNLENBQUM7WUFDTixtREFBbUQ7WUFDbkQsTUFBTSxPQUFPLEdBQUcsUUFBUSxDQUFDLENBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBUSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQ3BELE9BQU8sR0FBRyxRQUFRLENBQUMsQ0FBQyxPQUFPLEdBQUcsRUFBRSxDQUFRLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFFOUMsOEJBQThCO1lBQzlCLE1BQU0sVUFBVSxHQUFHLE9BQU8sR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQztZQUMxRCxPQUFPLEdBQUcsT0FBTyxJQUFJLFVBQVUsRUFBRSxDQUFDO1FBQ3BDLENBQUM7SUFDSCxDQUFDO0lBRUQsWUFBWSxDQUFDLFFBQWdCO1FBQzNCLElBQUksSUFBSSxDQUFDLG1CQUFtQixDQUFDLFFBQVEsS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUNwRCxNQUFNLFFBQVEsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQUMsY0FBYyxDQUFDO1lBRXhHLElBQUksUUFBUSxHQUFHLEVBQUUsRUFBRSxDQUFDO2dCQUNsQixPQUFPLFFBQVEsR0FBRyxDQUFDLENBQUM7WUFDdEIsQ0FBQztpQkFBTSxJQUFJLFFBQVEsR0FBRyxFQUFFLEVBQUUsQ0FBQztnQkFDekIsT0FBTyxRQUFRLEdBQUcsQ0FBQyxDQUFDO1lBQ3RCLENBQUM7WUFFRCxPQUFPLFFBQVEsQ0FBQztRQUNsQixDQUFDO2FBQU0sQ0FBQztZQUNOLElBQUksUUFBUSxJQUFJLEVBQUUsRUFBRSxDQUFDO2dCQUNuQixPQUFPLENBQUMsQ0FBQztZQUNYLENBQUM7aUJBQU0sSUFBSSxRQUFRLEdBQUcsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDO2dCQUM5QixPQUFPLENBQUMsQ0FBQztZQUNYLENBQUM7aUJBQU0sSUFBSSxRQUFRLEdBQUcsRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDO2dCQUMvQixPQUFPLEVBQUUsQ0FBQztZQUNaLENBQUM7WUFFRCxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxHQUFHLFFBQVEsQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUN4QyxDQUFDO0lBQ0gsQ0FBQztJQUVELG9CQUFvQixDQUFDLFFBQWdCO1FBQ25DLElBQUksSUFBSSxDQUFDLG1CQUFtQixDQUFDLFFBQVEsS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUNwRCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQUMsa0JBQWtCLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUFDLGNBQWMsQ0FBQztZQUV2RyxPQUFPLFFBQVEsQ0FBQztRQUNsQixDQUFDO2FBQU0sQ0FBQztZQUNOLElBQUksUUFBUSxJQUFJLEVBQUUsRUFBRSxDQUFDO2dCQUNuQixPQUFPLEVBQUUsQ0FBQztZQUNaLENBQUM7aUJBQU0sSUFBSSxRQUFRLEdBQUcsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDO2dCQUM5QixPQUFPLENBQUMsQ0FBQztZQUNYLENBQUM7aUJBQU0sSUFBSSxRQUFRLEdBQUcsRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDO2dCQUMvQixPQUFPLENBQUMsQ0FBQztZQUNYLENBQUM7WUFFRCxPQUFPLENBQUMsQ0FBQztRQUNYLENBQUM7SUFDSCxDQUFDO0lBRUQsc0JBQXNCLENBQUMsUUFBZ0I7UUFDckMsSUFBSSxJQUFJLENBQUMsbUJBQW1CLENBQUMsUUFBUSxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQ3BELE9BQU8sQ0FBQyxDQUFDO1FBQ1gsQ0FBQzthQUFNLENBQUM7WUFDTixJQUFJLFFBQVEsSUFBSSxFQUFFLEVBQUUsQ0FBQztnQkFDbkIsT0FBTyxDQUFDLENBQUM7WUFDWCxDQUFDO2lCQUFNLElBQUksUUFBUSxHQUFHLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQztnQkFDOUIsT0FBTyxDQUFDLENBQUM7WUFDWCxDQUFDO2lCQUFNLElBQUksUUFBUSxHQUFHLEVBQUUsSUFBSSxFQUFFLEVBQUUsQ0FBQztnQkFDL0IsT0FBTyxDQUFDLENBQUM7WUFDWCxDQUFDO1lBQ0QsT0FBTyxDQUFDLENBQUM7UUFDWCxDQUFDO0lBQ0gsQ0FBQztJQUVPLGlCQUFpQixDQUFDLENBQU07UUFDOUIsaURBQWlEO1FBQ2pELE1BQU0sT0FBTyxHQUFHLENBQUMsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDO1FBQ3pFLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1FBRXRFLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUM7UUFDM0QsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBRS9ELElBQUksUUFBZ0IsQ0FBQztRQUVyQixJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxVQUFVLElBQUksWUFBWSxHQUFHLFdBQVcsRUFBRSxDQUFDO1lBQ3JGLFFBQVE7Z0JBQ04sQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDO29CQUN2RixDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsVUFBVSxHQUFHLFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUU1RSxJQUFJLFFBQVEsR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDakIsUUFBUSxHQUFHLENBQUMsQ0FBQztZQUNmLENBQUM7UUFDSCxDQUFDO2FBQU0sQ0FBQztZQUNOLFFBQVE7Z0JBQ04sQ0FBQyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUM7b0JBQ3hGLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUM7b0JBQzVDLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxXQUFXLElBQUksQ0FBQyxDQUFDO1FBQ3hELENBQUM7UUFFRCxRQUFRLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFFakMsVUFBVSxDQUFDLEdBQUcsRUFBRTtZQUNkLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ2pDLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDMUIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsY0FBYyxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUNySCxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDUixDQUFDO0lBRUQsU0FBUyxDQUFDLElBQVM7UUFDakIsSUFBSSxJQUFJLEdBQUcsQ0FBQyxJQUFJLElBQUksR0FBRyxHQUFHLEVBQUUsQ0FBQztZQUMzQixPQUFPO1FBQ1QsQ0FBQztRQUVELElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO1FBQ2pCLElBQUksSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ3BCLFVBQVUsQ0FBQyxHQUFHLEVBQUU7Z0JBQ2QsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUNoQyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztZQUMzQixDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDUixDQUFDO0lBQ0gsQ0FBQztJQUVPLGlCQUFpQjtRQUN2QixJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ3JCLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQztRQUVELElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQzdCLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQztRQUVELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVELFNBQVMsQ0FBQyxnQkFBc0I7UUFDOUIsSUFBSSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxFQUFFLENBQUM7WUFDOUIsT0FBTztRQUNULENBQUM7UUFFRCxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxjQUFjLElBQUksSUFBSSxDQUFDLFlBQVksQ0FBQyxjQUFjLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ3ZGLE9BQU87UUFDVCxDQUFDO1FBRUQsSUFBSSxDQUFDLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1lBQzlCLE9BQU87UUFDVCxDQUFDO1FBRUQsTUFBTSxtQkFBbUIsR0FBd0IsSUFBSSxtQkFBbUIsRUFBRSxDQUFDO1FBQzNFLG1CQUFtQixDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7UUFFekUsSUFBSSxnQkFBZ0IsRUFBRSxDQUFDO1lBQ3JCLG1CQUFtQixDQUFDLFdBQVcsR0FBRyxnQkFBZ0IsQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDO1lBQ2hFLG1CQUFtQixDQUFDLFNBQVMsR0FBRyxnQkFBZ0IsQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDO1FBQzlELENBQUM7YUFBTSxDQUFDO1lBQ04sbUJBQW1CLENBQUMsV0FBVyxHQUFHLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxXQUFXLEVBQUUsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDN0UsbUJBQW1CLENBQUMsU0FBUyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFdBQVcsRUFBRSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNuRixDQUFDO1FBRUQsSUFBSSxDQUFDLG1CQUFtQixDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO1FBRXhFLElBQUksQ0FBQyxzQkFBc0IsR0FBRyxtQkFBbUIsQ0FBQztRQUVsRCxJQUFJLGdCQUFnQixFQUFFLENBQUM7WUFDckIsZ0JBQWdCLENBQUMsS0FBSztnQkFDcEIsT0FBTztvQkFDUCxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7b0JBQzFELElBQUk7b0JBQ0osSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO29CQUMxRCxJQUFJO29CQUNKLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztvQkFDMUQsSUFBSTtvQkFDSixJQUFJLENBQUMsb0JBQW9CO29CQUN6QixHQUFHLENBQUM7WUFDTixnQkFBZ0IsQ0FBQyxVQUFVLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQztZQUM5QyxJQUFJLENBQUMsYUFBYSxDQUFDLGdCQUFnQixFQUFFLElBQUksQ0FBQyxZQUFZLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxFQUFFLG1CQUFtQixDQUFDLENBQUM7WUFDL0YsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7UUFDL0IsQ0FBQzthQUFNLENBQUM7WUFDTixJQUFJLENBQUMsVUFBVSxDQUFDLG1CQUFtQixFQUFFLElBQUksQ0FBQyxZQUFZLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDNUUsQ0FBQztRQUVELElBQUksQ0FBQyxhQUFhLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDbkMsQ0FBQztJQUVPLHFCQUFxQjtRQUMzQixJQUFJLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUN4QyxPQUFPLEVBQUUsR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQUMsY0FBYyxHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxjQUFjLENBQUM7UUFDaEcsQ0FBQztRQUVELE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFFTyxtQkFBbUI7UUFDekIsT0FBTyxJQUFJLENBQUMsbUJBQW1CLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDO0lBQzFELENBQUM7SUFFRCx5QkFBeUI7UUFDdkIsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsd0JBQXdCLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDbEYsSUFBSSxDQUFDLG1CQUFtQixHQUFHLFNBQVMsQ0FBQztRQUNyQyxJQUFJLENBQUMsd0JBQXdCLEdBQUcsU0FBUyxDQUFDO1FBQzFDLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1FBQ3pCLElBQUksSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUN4RCxJQUFJLENBQUMsc0JBQXNCLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDakMsQ0FBQztJQUNILENBQUM7SUFFRCxpQkFBaUI7UUFDZixJQUFJLENBQUMsUUFBUSxHQUFHLFNBQVMsQ0FBQztRQUMxQixJQUFJLENBQUMsZ0JBQWdCLEdBQUcsS0FBSyxDQUFDO1FBRTlCLElBQUksSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ3BCLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDMUIsSUFBSSxDQUFDLFVBQVUsR0FBRyxTQUFTLENBQUM7UUFDOUIsQ0FBQztJQUNILENBQUM7SUFFRCxnQkFBZ0I7UUFDZCxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztRQUV6QixJQUFJLENBQUMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQzVDLE9BQU87UUFDVCxDQUFDO1FBRUQsSUFBSSxDQUFDLGdCQUFnQixHQUFHLElBQUksQ0FBQztRQUU3QixVQUFVLENBQUMsR0FBRyxFQUFFO1lBQ2QsSUFBSSxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDO2dCQUNsQyxTQUFTLEVBQUUsV0FBVztnQkFDdEIsU0FBUyxFQUFFLE9BQU87Z0JBQ2xCLGFBQWEsRUFBRSxPQUFPO2dCQUN0QixlQUFlO2dCQUNmLE1BQU0sRUFBRSxDQUFDO2dCQUNULFFBQVEsRUFBRSxLQUFLO2dCQUNmLDBEQUEwRDtnQkFDMUQsOERBQThEO2dCQUM5RCxpQkFBaUI7Z0JBQ2pCLE9BQU8sRUFBRTtvQkFDUCxZQUFZLENBQUMsTUFBTSxDQUFDO3dCQUNsQixrQkFBa0I7d0JBQ2xCLE9BQU8sRUFBRSxDQUFDO3dCQUNWLEtBQUssRUFBRSxTQUFTO3dCQUNoQixVQUFVLEVBQUUsS0FBSyxDQUFDLG1FQUFtRTtxQkFDdEYsQ0FBQztvQkFDRixhQUFhLENBQUMsTUFBTSxDQUFDO3dCQUNuQixhQUFhLEVBQUU7NEJBQ2IsSUFBSSxFQUFFLENBQUM7eUJBQ1I7d0JBQ0QsS0FBSyxFQUFFLE1BQU07d0JBQ2Isa0JBQWtCLEVBQUUsSUFBSSxDQUFDLHFCQUFxQixFQUFFO3dCQUNoRCxnQkFBZ0IsRUFBRSxJQUFJLENBQUMsbUJBQW1CLEVBQUU7cUJBQzdDLENBQUM7b0JBQ0YsY0FBYyxDQUFDLE1BQU0sQ0FBQzt3QkFDcEIsU0FBUyxFQUFFLG9CQUFvQjt3QkFDL0IsZ0JBQWdCLEVBQUUsTUFBTTt3QkFDeEIsa0JBQWtCLEVBQUUsTUFBTTt3QkFDMUIsTUFBTSxFQUFFLElBQUksQ0FBQyxtQkFBbUIsRUFBRTt3QkFDbEMsa0JBQWtCLEVBQUUsSUFBSSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7d0JBQ3RELFlBQVksRUFBRSxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7d0JBQzFDLG9CQUFvQixFQUFFLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO3dCQUMxRCxzQkFBc0IsRUFBRSxJQUFJLENBQUMsc0JBQXNCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztxQkFDL0QsQ0FBQztpQkFDSDthQUNGLENBQUMsQ0FBQztZQUVILElBQUksYUFBcUIsQ0FBQztZQUUxQixJQUFJLElBQUksQ0FBQyxhQUFhLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztnQkFDMUMsb0RBQW9EO2dCQUNwRCxhQUFhLEdBQUcsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUFDLGFBQWEsR0FBRyxhQUFhLENBQUM7WUFDNUYsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLDhEQUE4RDtnQkFDOUQsYUFBYTtvQkFDWCwwQkFBMEI7d0JBQzFCLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJO3dCQUM3QixHQUFHO3dCQUNILElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxhQUFhLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQy9HLENBQUM7WUFFRCxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLE9BQU8sR0FBRyxhQUFhLENBQUMsQ0FBQztZQUVqRSxJQUFJLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsR0FBRyxFQUFFO2dCQUMvQixVQUFVLENBQUMsR0FBRyxFQUFFO29CQUNkLDhEQUE4RDtvQkFDOUQsSUFBSSxJQUFJLENBQUMsbUJBQW1CLENBQUMsWUFBWSxFQUFFLENBQUM7d0JBQzFDLGdFQUFnRTt3QkFDaEUsSUFBSSxDQUFDLGdCQUFnQixHQUFHLEtBQUssQ0FBQztvQkFDaEMsQ0FBQzt5QkFBTSxDQUFDO3dCQUNOLGdEQUFnRDt3QkFDaEQsSUFBSSxDQUFDLG1CQUFtQixDQUFDLFlBQVksR0FBRyxJQUFJLENBQUM7d0JBQzdDLEtBQUssQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUM7NkJBQ2xDLElBQUksQ0FBQyxDQUFDLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxFQUFFLEVBQUU7NEJBQ3hCLHNDQUFzQzs0QkFDdEMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLGNBQWMsR0FBRyxHQUFHLENBQUM7NEJBQzlDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxnQkFBZ0IsR0FBRyxNQUFNLEdBQUcsSUFBSSxDQUFDOzRCQUMxRCxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsS0FBSyxDQUFDO3dCQUNoQyxDQUFDLENBQUM7NkJBQ0QsS0FBSyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUU7NEJBQ2IsdUJBQXVCOzRCQUN2QixPQUFPLENBQUMsS0FBSyxDQUFDLDhDQUE4QyxFQUFFLEdBQUcsQ0FBQyxDQUFDOzRCQUNuRSxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsS0FBSyxDQUFDO3dCQUNoQyxDQUFDLENBQUMsQ0FBQztvQkFDUCxDQUFDO29CQUVELElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFdBQVcsRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDO29CQUNwRSxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7b0JBRXRCLDhDQUE4QztvQkFDOUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLFFBQVEsRUFBRSxHQUFHLEVBQUU7d0JBQy9ELElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQzt3QkFFeEYsa0ZBQWtGO3dCQUNsRiw0RUFBNEU7d0JBQzVFLDJFQUEyRTt3QkFDM0UsMkJBQTJCO3dCQUMzQixJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUM7b0JBQzFGLENBQUMsQ0FBQyxDQUFDO29CQUVILDBDQUEwQztvQkFDMUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLFlBQVksRUFBRSxHQUFHLEVBQUU7d0JBQ25FLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRSxDQUFDO29CQUN0QyxDQUFDLENBQUMsQ0FBQztvQkFDSCxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLENBQUMsWUFBWSxFQUFFLEdBQUcsRUFBRTt3QkFDbkUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsVUFBVSxFQUFFLENBQUM7b0JBQ3RDLENBQUMsQ0FBQyxDQUFDO29CQUNILElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFNLEVBQUUsRUFBRTt3QkFDeEUsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMscUJBQXFCLEVBQUUsQ0FBQzt3QkFDL0QsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDO3dCQUNoQyxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7b0JBQ3BELENBQUMsQ0FBQyxDQUFDO29CQUVILDJGQUEyRjtvQkFDM0YsaUZBQWlGO29CQUNqRixJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxVQUFVLEVBQUUsQ0FBQztvQkFFcEMseUJBQXlCO29CQUN6QixJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBTSxFQUFFLEVBQUU7d0JBQ3hFLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxJQUFJLENBQUM7d0JBQzdCLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUMsQ0FBQztvQkFDNUIsQ0FBQyxDQUFDLENBQUM7b0JBRUgsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLFdBQVcsRUFBRSxDQUFDLENBQU0sRUFBRSxFQUFFO3dCQUN4RSxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDOzRCQUMxQixJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDLENBQUM7d0JBQzVCLENBQUM7b0JBQ0gsQ0FBQyxDQUFDLENBQUM7b0JBRUgsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLFNBQVMsRUFBRSxDQUFDLENBQU0sRUFBRSxFQUFFO3dCQUN0RSxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsS0FBSyxDQUFDO29CQUNoQyxDQUFDLENBQUMsQ0FBQztvQkFFSCxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztvQkFFekIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLEVBQUUsQ0FBQztvQkFDMUIsSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztnQkFDOUIsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ1IsQ0FBQyxDQUFDLENBQUM7WUFFSCxJQUFJLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxLQUFVLEVBQUUsRUFBRTtnQkFDekMsK0NBQStDO2dCQUMvQyxrR0FBa0c7Z0JBQ2xHLElBQUksQ0FBQyx5QkFBeUIsRUFBRSxDQUFDO1lBQ25DLENBQUMsQ0FBQyxDQUFDO1lBRUgsSUFBSSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLEdBQUcsRUFBRTtnQkFDOUIsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7WUFDM0IsQ0FBQyxDQUFDLENBQUM7WUFFSCxJQUFJLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFO2dCQUM5QixJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztZQUMxQixDQUFDLENBQUMsQ0FBQztZQUVILElBQUksQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxHQUFHLEVBQUU7Z0JBQy9CLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztZQUN6QixDQUFDLENBQUMsQ0FBQztZQUVILElBQUksQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLGdCQUFnQixFQUFFLENBQUMsTUFBTSxFQUFFLEVBQUU7Z0JBQzlDLGtEQUFrRDtnQkFDbEQsSUFBSSxJQUFJLENBQUMsWUFBWSxDQUFDLGNBQWMsSUFBSSxJQUFJLENBQUMsWUFBWSxDQUFDLGNBQWMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7b0JBQ3RGLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO3dCQUN6QixJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO29CQUN6QixDQUFDO2dCQUNILENBQUM7cUJBQU0sQ0FBQztvQkFDTixJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQzt3QkFDekIsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDO29CQUNsQixDQUFDO2dCQUNILENBQUM7WUFDSCxDQUFDLENBQUMsQ0FBQztZQUVILElBQUksQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLGdCQUFnQixFQUFFLENBQUMsTUFBVyxFQUFFLEVBQUU7Z0JBQ25ELElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxFQUFFLENBQUM7Z0JBQzFCLElBQUksQ0FBQyxhQUFhLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDbkMsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDUixDQUFDO0lBRU8sUUFBUSxDQUFDLEdBQVc7UUFDMUIsTUFBTSxNQUFNLEdBQUcsMkNBQTJDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3JFLE9BQU8sTUFBTTtZQUNYLENBQUMsQ0FBQztnQkFDRSxDQUFDLEVBQUUsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUM7Z0JBQzFCLENBQUMsRUFBRSxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQztnQkFDMUIsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDO2FBQzNCO1lBQ0gsQ0FBQyxDQUFDLElBQUksQ0FBQztJQUNYLENBQUM7SUFFTyxxQkFBcUI7UUFDM0IsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUNyQixPQUFPO1FBQ1QsQ0FBQztRQUVELEtBQUssTUFBTSxHQUFHLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1lBQzVELE1BQU0sTUFBTSxHQUFRLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUV0RCw0RUFBNEU7WUFDNUUsK0RBQStEO1lBQy9ELElBQUksTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUNqQixJQUFJLFNBQVMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDO2dCQUUvQixNQUFNLENBQUMsSUFBSSxHQUFHLEtBQUssQ0FBQztnQkFDcEIsTUFBTSxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUM7Z0JBQ3RCLE1BQU0sQ0FBQyxVQUFVLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQztnQkFFckMsSUFBSSxJQUFJLENBQUMsWUFBWSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztvQkFDcEQsU0FBUyxHQUFHLElBQUksQ0FBQyxzQkFBc0IsQ0FBQztvQkFDeEMsTUFBTSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7b0JBQ25CLE1BQU0sQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDO29CQUNyQixNQUFNLENBQUMsVUFBVSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUM7Z0JBQ3RDLENBQUM7Z0JBRUQsTUFBTSxDQUFDLFVBQVUsQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDO2dCQUVuQyxJQUFJLElBQUksQ0FBQyxzQkFBc0IsSUFBSSxJQUFJLENBQUMsc0JBQXNCLEtBQUssTUFBTSxDQUFDLG1CQUFtQixFQUFFLENBQUM7b0JBQzlGLFNBQVMsR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQUM7b0JBQ3RDLE1BQU0sQ0FBQyxVQUFVLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQztnQkFDcEMsQ0FBQztnQkFFRCxNQUFNLENBQUMsS0FBSztvQkFDVixPQUFPO3dCQUNQLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO3dCQUNuQyxJQUFJO3dCQUNKLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO3dCQUNuQyxJQUFJO3dCQUNKLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO3dCQUNuQyxJQUFJO3dCQUNKLFNBQVM7d0JBQ1QsR0FBRyxDQUFDO2dCQUNOLE1BQU0sQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUN4QixDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFFRCxvQkFBb0I7UUFDbEIsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUNyQixPQUFPO1FBQ1QsQ0FBQztRQUVELElBQUksQ0FBQyxJQUFJLENBQUMsc0JBQXNCLEVBQUUsQ0FBQztZQUNqQyxPQUFPO1FBQ1QsQ0FBQztRQUVELEtBQUssTUFBTSxHQUFHLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1lBQzVELE1BQU0sTUFBTSxHQUFRLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUV0RCxJQUFJLElBQUksQ0FBQyxzQkFBc0IsS0FBSyxNQUFNLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztnQkFDL0QsTUFBTSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsc0JBQXNCLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQztnQkFDOUQsTUFBTSxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsc0JBQXNCLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQztnQkFDMUQsTUFBTSxDQUFDLFlBQVksRUFBRSxDQUFDO2dCQUN0QixNQUFNO1lBQ1IsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRU8saUJBQWlCLENBQUMsbUJBQXlDO1FBQ2pFLElBQUksSUFBSSxDQUFDLHNCQUFzQixJQUFJLElBQUksQ0FBQyxzQkFBc0IsS0FBSyxtQkFBbUIsRUFBRSxDQUFDO1lBQ3ZGLHFCQUFxQjtZQUNyQixPQUFPO1FBQ1QsQ0FBQztRQUVELElBQUksbUJBQW1CLEVBQUUsQ0FBQztZQUN4QixJQUFJLENBQUMsc0JBQXNCLEdBQUcsbUJBQW1CLENBQUM7UUFDcEQsQ0FBQztRQUVELElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO0lBQy9CLENBQUM7SUFFTyx3QkFBd0IsQ0FBQyxLQUFhO1FBQzVDLG9DQUFvQztRQUNwQyxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsbUJBQW1CLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDL0MsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLHFCQUFxQixFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ25ELE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEtBQUssR0FBRyxNQUFNLENBQUMsR0FBRyxRQUFRLENBQUMsR0FBRyxRQUFRLEdBQUcsTUFBTSxDQUFDO0lBQ3JFLENBQUM7SUFFTyxhQUFhLENBQUMsZ0JBQXFCLEVBQUUsS0FBWSxFQUFFLG1CQUF3QyxFQUFFLE1BQWU7UUFDbEgsZ0JBQWdCLENBQUMsbUJBQW1CLEdBQUcsbUJBQW1CLENBQUM7UUFDM0QsZ0JBQWdCLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztRQUMvQixnQkFBZ0IsQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO1FBRWpDLGdCQUFnQixDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxLQUFLLEVBQUUsRUFBRTtZQUNyQyxJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsZUFBZSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7Z0JBQzdDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO1lBQzlDLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztRQUVILGdCQUFnQixDQUFDLEVBQUUsQ0FBQyxRQUFRLEVBQUUsR0FBRyxFQUFFO1lBQ2pDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO1lBQzVDLElBQUksSUFBSSxDQUFDLG1CQUFtQixDQUFDLFVBQVUsRUFBRSxDQUFDO2dCQUN4QywyRUFBMkU7Z0JBQzNFLG1FQUFtRTtnQkFDbkUsZ0JBQWdCLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDL0UsZ0JBQWdCLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUM3RSxDQUFDO1lBQ0QsbUJBQW1CLENBQUMsV0FBVyxHQUFHLGdCQUFnQixDQUFDLEtBQUssR0FBRyxJQUFJLENBQUM7WUFDaEUsbUJBQW1CLENBQUMsU0FBUyxHQUFHLGdCQUFnQixDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUM7UUFDOUQsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU8sVUFBVSxDQUFDLG1CQUF3QyxFQUFFLEtBQVk7UUFDdkUsbURBQW1EO1FBQ25ELElBQUksQ0FBQyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsRUFBRSxDQUFDO1lBQzlCLE9BQU87UUFDVCxDQUFDO1FBRUQsMEJBQTBCO1FBQzFCLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUM7WUFDakQsS0FBSyxFQUFFLG1CQUFtQixDQUFDLFdBQVcsR0FBRyxJQUFJO1lBQzdDLEdBQUcsRUFBRSxtQkFBbUIsQ0FBQyxTQUFTLEdBQUcsSUFBSTtZQUN6QyxLQUFLLEVBQUUsTUFBTTtZQUNiLElBQUksRUFBRSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUU7U0FDeEIsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLGFBQWEsQ0FBQyxnQkFBZ0IsRUFBRSxLQUFLLEVBQUUsbUJBQW1CLENBQUMsQ0FBQztRQUVqRSw0QkFBNEI7UUFDNUIsOENBQThDO1FBQzlDLG1FQUFtRTtRQUVuRSx1RUFBdUU7UUFDdkUsdUdBQXVHO1FBQ3ZHLDRDQUE0QztRQUM1QywySEFBMkg7UUFDM0gscUJBQXFCO1FBQ3JCLCtCQUErQjtRQUMvQixjQUFjO1FBQ2Qsb0JBQW9CO1FBQ3BCLHNCQUFzQjtRQUN0Qix5QkFBeUI7UUFDekIsUUFBUTtRQUNSLFFBQVE7UUFDUiw4RUFBOEU7UUFDOUUsSUFBSTtRQUVKLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO0lBQy9CLENBQUM7SUFFRCxZQUFZO1FBQ1YsSUFBSSxDQUFDLElBQUksQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO1lBQ2pDLE9BQU87UUFDVCxDQUFDO1FBRUQsSUFBSSxJQUFJLENBQUMsWUFBWSxDQUFDLGNBQWMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDbEQsT0FBTztRQUNULENBQUM7UUFFRCxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUFDLG9CQUFvQixDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQzlFLElBQUksSUFBSSxDQUFDLG1CQUFtQixDQUFDLG9CQUFvQixDQUFDLENBQUMsQ0FBQyxLQUFLLElBQUksQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO2dCQUNyRixvQ0FBb0M7Z0JBQ3BDLEtBQUssTUFBTSxHQUFHLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO29CQUM1RCxNQUFNLE1BQU0sR0FBUSxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7b0JBRXRELElBQUksTUFBTSxDQUFDLG1CQUFtQixLQUFLLElBQUksQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO3dCQUMvRCxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUM7b0JBQ2xCLENBQUM7Z0JBQ0gsQ0FBQztnQkFFRCxJQUFJLENBQUMsc0JBQXNCLEdBQUcsU0FBUyxDQUFDO2dCQUN4QyxJQUFJLENBQUMsbUJBQW1CLENBQUMsb0JBQW9CLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztnQkFFM0QsT0FBTztZQUNULENBQUM7UUFDSCxDQUFDO1FBRUQsSUFBSSxDQUFDLGFBQWEsQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUNuQyxDQUFDO0lBRUQsZ0JBQWdCLENBQUMsVUFBa0I7UUFDakMsc0VBQXNFO1FBQ3RFLE1BQU0sYUFBYSxHQUF3QixFQUFFLENBQUM7UUFFOUMsS0FBSyxJQUFJLFVBQVUsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxVQUFVLElBQUksQ0FBQyxFQUFFLFVBQVUsRUFBRSxFQUFFLENBQUM7WUFDbkcsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBRTdELEtBQUssTUFBTSxNQUFNLElBQUksSUFBSSxDQUFDLG1CQUFtQixDQUFDLG9CQUFvQixFQUFFLENBQUM7Z0JBQ25FLElBQUksTUFBTSxDQUFDLFNBQVMsS0FBSyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUM7b0JBQ3BDLEtBQUssSUFBSSxXQUFXLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsV0FBVyxJQUFJLENBQUMsRUFBRSxXQUFXLEVBQUUsRUFBRSxDQUFDO3dCQUN2RyxLQUFLLE1BQU0sVUFBVSxJQUFJLEtBQUssQ0FBQyxXQUFXLEVBQUUsQ0FBQzs0QkFDM0MsSUFBSSxVQUFVLEtBQUssSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO2dDQUN6RSxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLGVBQWUsQ0FBQyxVQUFVLENBQUMsQ0FBQztnQ0FFOUQsSUFBSSxNQUFNLEVBQUUsQ0FBQztvQ0FDWCxJQUFJLGlCQUFpQixHQUFHLE1BQU0sQ0FBQyxXQUFXLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsV0FBVyxHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUM7b0NBQ3hILElBQUksZUFBZSxHQUFHLE1BQU0sQ0FBQyxTQUFTLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsV0FBVyxHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUM7b0NBRWhILG9FQUFvRTtvQ0FDcEUsaUJBQWlCLElBQUksTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO29DQUNoRSxlQUFlLElBQUksTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO29DQUVqRSxJQUFJLGlCQUFpQixJQUFJLFVBQVUsSUFBSSxlQUFlLElBQUksVUFBVSxFQUFFLENBQUM7d0NBQ3JFLGFBQWEsQ0FBQyxJQUFJLENBQUMsSUFBSSxpQkFBaUIsQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUM7b0NBQ25FLENBQUM7Z0NBQ0gsQ0FBQzs0QkFDSCxDQUFDO3dCQUNILENBQUM7b0JBQ0gsQ0FBQztnQkFDSCxDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7UUFFRCxPQUFPLGFBQWEsQ0FBQztJQUN2QixDQUFDO0lBRUQsY0FBYztRQUNaLElBQUksQ0FBQyxJQUFJLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztZQUM5QixPQUFPO1FBQ1QsQ0FBQztRQUVELDZFQUE2RTtRQUM3RSxpRUFBaUU7UUFDakUsS0FBSyxJQUFJLFVBQVUsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxVQUFVLElBQUksQ0FBQyxFQUFFLFVBQVUsRUFBRSxFQUFFLENBQUM7WUFDbkcsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQzdELElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLGVBQWUsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO2dCQUM5QyxLQUFLLE1BQU0sbUJBQW1CLElBQUksSUFBSSxDQUFDLG1CQUFtQixDQUFDLG9CQUFvQixFQUFFLENBQUM7b0JBQ2hGLElBQUksbUJBQW1CLENBQUMsU0FBUyxLQUFLLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQzt3QkFDakQsSUFBSSxDQUFDLFVBQVUsQ0FBQyxtQkFBbUIsRUFBRSxLQUFLLENBQUMsQ0FBQztvQkFDOUMsQ0FBQztnQkFDSCxDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7UUFFRCxzQ0FBc0M7UUFDdEMsS0FBSyxJQUFJLFVBQVUsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxVQUFVLElBQUksQ0FBQyxFQUFFLFVBQVUsRUFBRSxFQUFFLENBQUM7WUFDbkcsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBRTdELElBQUksSUFBSSxDQUFDLFlBQVksQ0FBQyxlQUFlLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztnQkFDN0MsS0FBSyxNQUFNLG1CQUFtQixJQUFJLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO29CQUNoRixJQUFJLG1CQUFtQixDQUFDLFNBQVMsS0FBSyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUM7d0JBQ2pELElBQUksQ0FBQyxVQUFVLENBQUMsbUJBQW1CLEVBQUUsS0FBSyxDQUFDLENBQUM7b0JBQzlDLENBQUM7Z0JBQ0gsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVELFVBQVU7UUFDUixJQUFJLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztZQUN6QixJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1lBRXBFLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxrQkFBa0IsR0FBRyxJQUFJLENBQUMscUJBQXFCLEVBQUUsQ0FBQztZQUNqRixJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUM7UUFDL0UsQ0FBQztRQUNELElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO0lBQzNCLENBQUM7SUFFRCwyQkFBMkI7UUFDekIsc0VBQXNFO1FBQ3RFLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxJQUFJLENBQzNDLEdBQUcsQ0FBQyxDQUFDLFFBQWtCLEVBQUUsRUFBRTtZQUN6QixNQUFNLGdCQUFnQixHQUFhLEVBQUUsQ0FBQztZQUV0QyxLQUFLLE1BQU0sbUJBQW1CLElBQUksUUFBUSxFQUFFLENBQUM7Z0JBQzNDLGdCQUFnQixDQUFDLElBQUksQ0FBRSxtQkFBMkIsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUMzRCxDQUFDO1lBRUQsT0FBTyxnQkFBZ0IsQ0FBQztRQUMxQixDQUFDLENBQUMsQ0FDSCxDQUFDO0lBQ0osQ0FBQztJQUVELHNCQUFzQixDQUFDLEtBQWE7UUFDbEMsSUFBSSxDQUFDLG1CQUFtQixHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUMzRSxJQUFJLENBQUMsd0JBQXdCLEdBQUcsS0FBSyxDQUFDO1FBQ3RDLElBQUksQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFDLHVCQUF1QixHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUM7UUFDcEYsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7UUFFeEIsa0RBQWtEO1FBQ2xELElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxFQUFFLENBQUM7UUFFNUIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNwQixDQUFDO2dGQXh6QlUsZUFBZTt1RUFBZixlQUFlLFdBQWYsZUFBZSxtQkFGZCxNQUFNOztpRkFFUCxlQUFlO2NBSDNCLFVBQVU7ZUFBQztnQkFDVixVQUFVLEVBQUUsTUFBTTthQUNuQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEh0dHBDbGllbnQgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XG5pbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBTdWJqZWN0LCBTdWJzY3JpcHRpb24sIHRpbWVyIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBtYXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgV2F2ZVN1cmZlciBmcm9tICd3YXZlc3VyZmVyLmpzJztcbmltcG9ydCBDdXJzb3JQbHVnaW4gZnJvbSAnd2F2ZXN1cmZlci5qcy9kaXN0L3BsdWdpbi93YXZlc3VyZmVyLmN1cnNvci5taW4uanMnO1xuaW1wb3J0IFJlZ2lvbnNQbHVnaW4gZnJvbSAnd2F2ZXN1cmZlci5qcy9kaXN0L3BsdWdpbi93YXZlc3VyZmVyLnJlZ2lvbnMubWluLmpzJztcbmltcG9ydCBUaW1lTGluZVBsdWdpbiBmcm9tICd3YXZlc3VyZmVyLmpzL2Rpc3QvcGx1Z2luL3dhdmVzdXJmZXIudGltZWxpbmUubWluLmpzJztcbmltcG9ydCB7IGd1ZXNzIH0gZnJvbSAnd2ViLWF1ZGlvLWJlYXQtZGV0ZWN0b3InO1xuaW1wb3J0IHsgQ29tcG9zaXRpb24gfSBmcm9tICcuLi9tb2RlbHMvY29tcG9zaXRpb24nO1xuaW1wb3J0IHsgUHJlc2V0IH0gZnJvbSAnLi4vbW9kZWxzL3ByZXNldCc7XG5pbXBvcnQgeyBQcmVzZXRSZWdpb25TY2VuZSB9IGZyb20gJy4uL21vZGVscy9wcmVzZXQtcmVnaW9uLXNjZW5lJztcbmltcG9ydCB7IFNjZW5lIH0gZnJvbSAnLi4vbW9kZWxzL3NjZW5lJztcbmltcG9ydCB7IFNjZW5lUGxheWJhY2tSZWdpb24gfSBmcm9tICcuLi9tb2RlbHMvc2NlbmUtcGxheWJhY2stcmVnaW9uJztcbmltcG9ydCB7IENvbmZpZ1NlcnZpY2UgfSBmcm9tICcuL2NvbmZpZy5zZXJ2aWNlJztcbmltcG9ydCB7IFByZXNldFNlcnZpY2UgfSBmcm9tICcuL3ByZXNldC5zZXJ2aWNlJztcbmltcG9ydCB7IFByb2plY3RTZXJ2aWNlIH0gZnJvbSAnLi9wcm9qZWN0LnNlcnZpY2UnO1xuaW1wb3J0IHsgU2NlbmVTZXJ2aWNlIH0gZnJvbSAnLi9zY2VuZS5zZXJ2aWNlJztcblxuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCcsXG59KVxuZXhwb3J0IGNsYXNzIFRpbWVsaW5lU2VydmljZSB7XG4gIHB1YmxpYyB3YXZlU3VyZmVyOiBXYXZlU3VyZmVyO1xuICBwdWJsaWMgcGxheVN0YXRlID0gJ3BhdXNlZCc7XG5cbiAgcHVibGljIHpvb20gPSAwO1xuICBwcml2YXRlIHRpbWVVcGRhdGVTdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbjtcbiAgcHVibGljIGN1cnJlbnRUaW1lOiBzdHJpbmc7XG4gIHByaXZhdGUgdGltZWxpbmVDbGlja2luZyA9IGZhbHNlO1xuICBwdWJsaWMgc2VsZWN0ZWRQbGF5YmFja1JlZ2lvbjogU2NlbmVQbGF5YmFja1JlZ2lvbjtcbiAgcHJpdmF0ZSBpbnRlbnNpdHkgPSAwLjI7XG4gIHByaXZhdGUgaW50ZW5zaXR5U2VsZWN0ZWRTY2VuZSA9IDAuNDtcbiAgcHJpdmF0ZSBpbnRlbnNpdHlIaWdobGlnaHRlZCA9IDAuODtcbiAgcHVibGljIGR1cmF0aW9uOiBzdHJpbmc7XG4gIHB1YmxpYyB3YXZlU3VyZmVyUmVhZHk6IFN1YmplY3Q8dm9pZD4gPSBuZXcgU3ViamVjdCgpO1xuICBwdWJsaWMgZGV0ZWN0Q2hhbmdlczogU3ViamVjdDx2b2lkPiA9IG5ldyBTdWJqZWN0KCk7XG5cbiAgLy8gdGhlIGN1cnJlbnQgY29tcG9zaXRpb25cbiAgcHVibGljIHNlbGVjdGVkQ29tcG9zaXRpb246IENvbXBvc2l0aW9uO1xuICBwdWJsaWMgc2VsZWN0ZWRDb21wb3NpdGlvbkluZGV4OiBudW1iZXI7XG5cbiAgLy8gY2FuIHdlIGFkZCBuZXcgY29tcG9zaXRpb25zIGJhc2VkIG9uIGFuIGV4dGVybmFsIHBvb2wgYW5kXG4gIC8vIHNob3VsZCBuZXcgY29tcG9zaXRpb25zIG5vdCBhdmFpbGFibGUgaW4gdGhpcyBwb29sIGJlIGFkZGVkIHRoZXJlP1xuICBwdWJsaWMgZXh0ZXJuYWxDb21wb3NpdGlvbnNBdmFpbGFibGUgPSBmYWxzZTtcblxuICBwdWJsaWMgbG9hZGluZ0F1ZGlvRmlsZSA9IGZhbHNlO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgc2NlbmVTZXJ2aWNlOiBTY2VuZVNlcnZpY2UsXG4gICAgcHJpdmF0ZSBwcmVzZXRTZXJ2aWNlOiBQcmVzZXRTZXJ2aWNlLFxuICAgIHByaXZhdGUgcHJvamVjdFNlcnZpY2U6IFByb2plY3RTZXJ2aWNlLFxuICAgIHByaXZhdGUgaHR0cDogSHR0cENsaWVudCxcbiAgICBwcml2YXRlIGNvbmZpZ1NlcnZpY2U6IENvbmZpZ1NlcnZpY2VcbiAgKSB7XG4gICAgdGhpcy5wcmVzZXRTZXJ2aWNlLnByZXZpZXdTZWxlY3Rpb25DaGFuZ2VkLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICB0aGlzLnNlbGVjdGVkUGxheWJhY2tSZWdpb24gPSB1bmRlZmluZWQ7XG4gICAgICB0aGlzLnVwZGF0ZVJlZ2lvblNlbGVjdGlvbigpO1xuICAgIH0pO1xuICAgIHRoaXMuc2NlbmVTZXJ2aWNlLnNjZW5lRGVsZXRlZC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgdGhpcy5yZWRyYXdBbGxSZWdpb25zKCk7XG4gICAgfSk7XG4gICAgdGhpcy5zY2VuZVNlcnZpY2Uuc2NlbmVTZWxlY3RlZC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgdGhpcy5yZWRyYXdBbGxSZWdpb25zKCk7XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIHJlZHJhd0FsbFJlZ2lvbnMoKSB7XG4gICAgLy8gcmVtb3ZlIGFsbCByZWdpb25zIGZyb20gd2F2ZXN1cnZlclxuICAgIGlmICh0aGlzLndhdmVTdXJmZXIpIHtcbiAgICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKHRoaXMud2F2ZVN1cmZlci5yZWdpb25zLmxpc3QpKSB7XG4gICAgICAgIGNvbnN0IHJlZ2lvbjogYW55ID0gdGhpcy53YXZlU3VyZmVyLnJlZ2lvbnMubGlzdFtrZXldO1xuICAgICAgICByZWdpb24ucmVtb3ZlKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gZHJhdyBhbGwgcmVnaW9uc1xuICAgIHRoaXMuZHJhd0FsbFJlZ2lvbnMoKTtcbiAgfVxuXG4gIHByaXZhdGUgcGFkKG51bTogbnVtYmVyLCBzaXplOiBudW1iZXIpOiBzdHJpbmcge1xuICAgIGlmICghbnVtKSB7XG4gICAgICBudW0gPSAwO1xuICAgIH1cblxuICAgIGxldCBwYWRkZWQ6IHN0cmluZyA9IG51bS50b1N0cmluZygpO1xuICAgIHdoaWxlIChwYWRkZWQubGVuZ3RoIDwgc2l6ZSkge1xuICAgICAgcGFkZGVkID0gJzAnICsgcGFkZGVkO1xuICAgIH1cblxuICAgIHJldHVybiBwYWRkZWQ7XG4gIH1cblxuICBwcml2YXRlIG1zVG9UaW1lKG1pbGxpczogbnVtYmVyLCBpbmNsdWRlTWlsbGlzOiBib29sZWFuID0gdHJ1ZSk6IHN0cmluZyB7XG4gICAgY29uc3QgbXM6IG51bWJlciA9IE1hdGgucm91bmQobWlsbGlzICUgMTAwMCk7XG4gICAgY29uc3Qgc2Vjb25kczogbnVtYmVyID0gTWF0aC5mbG9vcigoKG1pbGxpcyAlIDM2MDAwMCkgJSA2MDAwMCkgLyAxMDAwKTtcbiAgICBjb25zdCBtaW51dGVzOiBudW1iZXIgPSBNYXRoLmZsb29yKChtaWxsaXMgJSAzNjAwMDAwKSAvIDYwMDAwKTtcblxuICAgIGlmIChpbmNsdWRlTWlsbGlzKSB7XG4gICAgICByZXR1cm4gdGhpcy5wYWQobWludXRlcywgMikgKyAnOicgKyB0aGlzLnBhZChzZWNvbmRzLCAyKSArICcuJyArIHRoaXMucGFkKG1zLCAzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaXMucGFkKG1pbnV0ZXMsIDIpICsgJzonICsgdGhpcy5wYWQoc2Vjb25kcywgMik7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVDdXJyZW50VGltZSgpIHtcbiAgICBpZiAoIXRoaXMud2F2ZVN1cmZlcikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIGRpc3BsYXkgdGhlIGN1cnJlbnQgdGltZVxuICAgIHRoaXMuY3VycmVudFRpbWUgPSB0aGlzLm1zVG9UaW1lKHRoaXMud2F2ZVN1cmZlci5nZXRDdXJyZW50VGltZSgpICogMTAwMCk7XG5cbiAgICBpZiAoIXRoaXMud2F2ZVN1cmZlci50aW1lbGluZS5kcmF3ZXIpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBkcmF3IHRoZSBjdXJyZW50IGN1cnNvciBvbiB0aGUgdGltZWxpbmVcbiAgICAvLyBUT0RPIHJlZHJhd2luZyB0aGUgdGltZWxpbmUgZWFjaCB1cGRhdGUgaXMgd2F5IHRvIGV4cGVuc2l2ZS5cbiAgICAvLyBtYXliZSBhcyBhIGJldHRlciBzb2x1dGlvbiB1c2UgYW4gZWxlbWVudCwgbGlrZSB0aGUgY3Vyc29yIGluc2lkZSBXYXZlc3VyZmVyIHRvXG4gICAgLy8gZGlzcGxheSB0aGUgcHJvZ3Jlc3M/XG4gICAgbGV0IHggPSAwO1xuICAgIGNvbnN0IGR1cmF0aW9uOiBudW1iZXIgPSB0aGlzLndhdmVTdXJmZXIuYmFja2VuZC5nZXREdXJhdGlvbigpO1xuICAgIGNvbnN0IHdpZHRoOiBudW1iZXIgPVxuICAgICAgdGhpcy53YXZlU3VyZmVyLnBhcmFtcy5maWxsUGFyZW50ICYmICF0aGlzLndhdmVTdXJmZXIucGFyYW1zLnNjcm9sbFBhcmVudFxuICAgICAgICA/IHRoaXMud2F2ZVN1cmZlci50aW1lbGluZS5kcmF3ZXIuZ2V0V2lkdGgoKVxuICAgICAgICA6IHRoaXMud2F2ZVN1cmZlci50aW1lbGluZS5kcmF3ZXIud3JhcHBlci5zY3JvbGxXaWR0aCAqIHRoaXMud2F2ZVN1cmZlci5wYXJhbXMucGl4ZWxSYXRpbztcblxuICAgIHggPSAod2lkdGggLyBkdXJhdGlvbikgKiB0aGlzLndhdmVTdXJmZXIuZ2V0Q3VycmVudFRpbWUoKSAtIDI7XG5cbiAgICAvLyB1cGRhdGUgdGhlIHRpbWVsaW5lIGNhbnZhc1xuICAgIHRoaXMud2F2ZVN1cmZlci50aW1lbGluZS5yZW5kZXIoKTtcblxuICAgIC8vIGRyYXcgdGhlIGN1cnNvciBvbiB0aGUgdGltZWxpbmVcbiAgICB0aGlzLndhdmVTdXJmZXIudGltZWxpbmUuY2FudmFzZXMuZm9yRWFjaCgoY2FudmFzLCBpKSA9PiB7XG4gICAgICBjb25zdCBsZWZ0T2Zmc2V0ID0gaSAqIHRoaXMud2F2ZVN1cmZlci50aW1lbGluZS5tYXhDYW52YXNXaWR0aDtcblxuICAgICAgY29uc3QgY3R4ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG5cbiAgICAgIGN0eC5maWxsU3R5bGUgPSAnI2ZkN2UxNCc7XG4gICAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgICBjdHgubW92ZVRvKHggLSAxMiAtIGxlZnRPZmZzZXQsIDIwKTtcbiAgICAgIGN0eC5saW5lVG8oeCArIDEyIC0gbGVmdE9mZnNldCwgMjApO1xuICAgICAgY3R4LmxpbmVUbyh4IC0gbGVmdE9mZnNldCwgNDUpO1xuICAgICAgY3R4LmZpbGwoKTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgc3RhcnRUaW1lVXBkYXRlcigpIHtcbiAgICB0aGlzLnN0b3BUaW1lVXBkYXRlcigpO1xuXG4gICAgY29uc3QgdGltZVVwZGF0ZXIgPSB0aW1lcigwLCA0MCk7XG4gICAgdGhpcy50aW1lVXBkYXRlU3Vic2NyaXB0aW9uID0gdGltZVVwZGF0ZXIuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgIHRoaXMudXBkYXRlQ3VycmVudFRpbWUoKTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgc3RvcFRpbWVVcGRhdGVyKCkge1xuICAgIGlmICh0aGlzLnRpbWVVcGRhdGVTdWJzY3JpcHRpb24pIHtcbiAgICAgIHRoaXMudGltZVVwZGF0ZVN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgIH1cbiAgfVxuXG4gIGZvcm1hdFRpbWVDYWxsYmFjayhzZWNvbmRzOiBudW1iZXIsIHB4UGVyU2VjOiBudW1iZXIpIHtcbiAgICBpZiAodGhpcy5zZWxlY3RlZENvbXBvc2l0aW9uLmdyaWRUeXBlID09PSAnbXVzaWNhbCcpIHtcbiAgICAgIHJldHVybiBNYXRoLnJvdW5kKHNlY29uZHMgLyB0aGlzLnNlbGVjdGVkQ29tcG9zaXRpb24udGltZVNpZ25hdHVyZVVwcGVyIC8gKDYwIC8gdGhpcy5zZWxlY3RlZENvbXBvc2l0aW9uLmJlYXRzUGVyTWludXRlKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGNhbGN1bGF0ZSBtaW51dGVzIGFuZCBzZWNvbmRzIGZyb20gc2Vjb25kcyBjb3VudFxuICAgICAgY29uc3QgbWludXRlcyA9IHBhcnNlSW50KChzZWNvbmRzIC8gNjApIGFzIGFueSwgMTApO1xuICAgICAgc2Vjb25kcyA9IHBhcnNlSW50KChzZWNvbmRzICUgNjApIGFzIGFueSwgMTApO1xuXG4gICAgICAvLyBmaWxsIHVwIHNlY29uZHMgd2l0aCB6ZXJvZXNcbiAgICAgIGNvbnN0IHNlY29uZHNTdHIgPSBzZWNvbmRzIDwgMTAgPyAnMCcgKyBzZWNvbmRzIDogc2Vjb25kcztcbiAgICAgIHJldHVybiBgJHttaW51dGVzfToke3NlY29uZHNTdHJ9YDtcbiAgICB9XG4gIH1cblxuICB0aW1lSW50ZXJ2YWwocHhQZXJTZWM6IG51bWJlcikge1xuICAgIGlmICh0aGlzLnNlbGVjdGVkQ29tcG9zaXRpb24uZ3JpZFR5cGUgPT09ICdtdXNpY2FsJykge1xuICAgICAgY29uc3QgaW50ZXJ2YWwgPSA2MCAvIHRoaXMuc2VsZWN0ZWRDb21wb3NpdGlvbi5iZWF0c1Blck1pbnV0ZSAvIHRoaXMuc2VsZWN0ZWRDb21wb3NpdGlvbi5ncmlkUmVzb2x1dGlvbjtcblxuICAgICAgaWYgKHB4UGVyU2VjIDwgNDApIHtcbiAgICAgICAgcmV0dXJuIGludGVydmFsICogNDtcbiAgICAgIH0gZWxzZSBpZiAocHhQZXJTZWMgPCA4MCkge1xuICAgICAgICByZXR1cm4gaW50ZXJ2YWwgKiAyO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gaW50ZXJ2YWw7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChweFBlclNlYyA+PSAyNSkge1xuICAgICAgICByZXR1cm4gMTtcbiAgICAgIH0gZWxzZSBpZiAocHhQZXJTZWMgKiA1ID49IDI1KSB7XG4gICAgICAgIHJldHVybiA1O1xuICAgICAgfSBlbHNlIGlmIChweFBlclNlYyAqIDE1ID49IDI1KSB7XG4gICAgICAgIHJldHVybiAxNTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIE1hdGguY2VpbCgwLjUgLyBweFBlclNlYykgKiA2MDtcbiAgICB9XG4gIH1cblxuICBwcmltYXJ5TGFiZWxJbnRlcnZhbChweFBlclNlYzogbnVtYmVyKSB7XG4gICAgaWYgKHRoaXMuc2VsZWN0ZWRDb21wb3NpdGlvbi5ncmlkVHlwZSA9PT0gJ211c2ljYWwnKSB7XG4gICAgICBjb25zdCBpbnRlcnZhbCA9IHRoaXMuc2VsZWN0ZWRDb21wb3NpdGlvbi50aW1lU2lnbmF0dXJlVXBwZXIgKiB0aGlzLnNlbGVjdGVkQ29tcG9zaXRpb24uZ3JpZFJlc29sdXRpb247XG5cbiAgICAgIHJldHVybiBpbnRlcnZhbDtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHB4UGVyU2VjID49IDI1KSB7XG4gICAgICAgIHJldHVybiAxMDtcbiAgICAgIH0gZWxzZSBpZiAocHhQZXJTZWMgKiA1ID49IDI1KSB7XG4gICAgICAgIHJldHVybiA2O1xuICAgICAgfSBlbHNlIGlmIChweFBlclNlYyAqIDE1ID49IDI1KSB7XG4gICAgICAgIHJldHVybiA0O1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gNDtcbiAgICB9XG4gIH1cblxuICBzZWNvbmRhcnlMYWJlbEludGVydmFsKHB4UGVyU2VjOiBudW1iZXIpIHtcbiAgICBpZiAodGhpcy5zZWxlY3RlZENvbXBvc2l0aW9uLmdyaWRUeXBlID09PSAnbXVzaWNhbCcpIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAocHhQZXJTZWMgPj0gMjUpIHtcbiAgICAgICAgcmV0dXJuIDU7XG4gICAgICB9IGVsc2UgaWYgKHB4UGVyU2VjICogNSA+PSAyNSkge1xuICAgICAgICByZXR1cm4gMjtcbiAgICAgIH0gZWxzZSBpZiAocHhQZXJTZWMgKiAxNSA+PSAyNSkge1xuICAgICAgICByZXR1cm4gMjtcbiAgICAgIH1cbiAgICAgIHJldHVybiAyO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgc2VlZWtXaXRoVGltZWxpbmUoZTogYW55KSB7XG4gICAgLy8gdGFrZW4gZnJvbSB3YXZlc3VyZmVyIC0+IGRyYXdlciAtPiBoYW5kbGVFdmVudFxuICAgIGNvbnN0IGNsaWVudFggPSBlLnRhcmdldFRvdWNoZXMgPyBlLnRhcmdldFRvdWNoZXNbMF0uY2xpZW50WCA6IGUuY2xpZW50WDtcbiAgICBjb25zdCBiYm94ID0gdGhpcy53YXZlU3VyZmVyLnRpbWVsaW5lLndyYXBwZXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cbiAgICBjb25zdCBub21pbmFsV2lkdGggPSB0aGlzLndhdmVTdXJmZXIudGltZWxpbmUuZHJhd2VyLndpZHRoO1xuICAgIGNvbnN0IHBhcmVudFdpZHRoID0gdGhpcy53YXZlU3VyZmVyLnRpbWVsaW5lLmRyYXdlci5nZXRXaWR0aCgpO1xuXG4gICAgbGV0IHByb2dyZXNzOiBudW1iZXI7XG5cbiAgICBpZiAoIXRoaXMud2F2ZVN1cmZlci50aW1lbGluZS5kcmF3ZXIucGFyYW1zLmZpbGxQYXJlbnQgJiYgbm9taW5hbFdpZHRoIDwgcGFyZW50V2lkdGgpIHtcbiAgICAgIHByb2dyZXNzID1cbiAgICAgICAgKHRoaXMud2F2ZVN1cmZlci50aW1lbGluZS5kcmF3ZXIucGFyYW1zLnJ0bCA/IGJib3gucmlnaHQgLSBjbGllbnRYIDogY2xpZW50WCAtIGJib3gubGVmdCkgKlxuICAgICAgICAgICh0aGlzLndhdmVTdXJmZXIudGltZWxpbmUuZHJhd2VyLnBhcmFtcy5waXhlbFJhdGlvIC8gbm9taW5hbFdpZHRoKSB8fCAwO1xuXG4gICAgICBpZiAocHJvZ3Jlc3MgPiAxKSB7XG4gICAgICAgIHByb2dyZXNzID0gMTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcHJvZ3Jlc3MgPVxuICAgICAgICAoKHRoaXMud2F2ZVN1cmZlci50aW1lbGluZS5kcmF3ZXIucGFyYW1zLnJ0bCA/IGJib3gucmlnaHQgLSBjbGllbnRYIDogY2xpZW50WCAtIGJib3gubGVmdCkgK1xuICAgICAgICAgIHRoaXMud2F2ZVN1cmZlci50aW1lbGluZS53cmFwcGVyLnNjcm9sbExlZnQpIC9cbiAgICAgICAgICB0aGlzLndhdmVTdXJmZXIudGltZWxpbmUud3JhcHBlci5zY3JvbGxXaWR0aCB8fCAwO1xuICAgIH1cblxuICAgIHByb2dyZXNzID0gTWF0aC5tYXgocHJvZ3Jlc3MsIDApO1xuXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICB0aGlzLndhdmVTdXJmZXIuc2Vla1RvKHByb2dyZXNzKTtcbiAgICAgIHRoaXMuZGV0ZWN0Q2hhbmdlcy5uZXh0KCk7XG4gICAgICB0aGlzLnByZXNldFNlcnZpY2UucHJldmlld0xpdmUodGhpcy5zZWxlY3RlZENvbXBvc2l0aW9uLm5hbWUsIE1hdGgucm91bmQodGhpcy53YXZlU3VyZmVyLmdldEN1cnJlbnRUaW1lKCkgKiAxMDAwKSk7XG4gICAgfSwgMCk7XG4gIH1cblxuICBhcHBseVpvb20oem9vbTogYW55KSB7XG4gICAgaWYgKHpvb20gPCAwIHx8IHpvb20gPiAyMDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLnpvb20gPSB6b29tO1xuICAgIGlmICh0aGlzLndhdmVTdXJmZXIpIHtcbiAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICB0aGlzLndhdmVTdXJmZXIuem9vbSh0aGlzLnpvb20pO1xuICAgICAgICB0aGlzLnVwZGF0ZUN1cnJlbnRUaW1lKCk7XG4gICAgICB9LCAwKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGlzV2F2ZVN1cmZlclJlYWR5KCk6IGJvb2xlYW4ge1xuICAgIGlmICghdGhpcy53YXZlU3VyZmVyKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLndhdmVTdXJmZXIuaXNSZWFkeSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgYWRkUmVnaW9uKHdhdmVTdXJmZXJSZWdpb24/OiBhbnkpIHtcbiAgICBpZiAoIXRoaXMuaXNXYXZlU3VyZmVyUmVhZHkoKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghdGhpcy5zY2VuZVNlcnZpY2Uuc2VsZWN0ZWRTY2VuZXMgfHwgdGhpcy5zY2VuZVNlcnZpY2Uuc2VsZWN0ZWRTY2VuZXMubGVuZ3RoICE9PSAxKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLnNlbGVjdGVkQ29tcG9zaXRpb24pIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBzY2VuZVBsYXliYWNrUmVnaW9uOiBTY2VuZVBsYXliYWNrUmVnaW9uID0gbmV3IFNjZW5lUGxheWJhY2tSZWdpb24oKTtcbiAgICBzY2VuZVBsYXliYWNrUmVnaW9uLnNjZW5lVXVpZCA9IHRoaXMuc2NlbmVTZXJ2aWNlLnNlbGVjdGVkU2NlbmVzWzBdLnV1aWQ7XG5cbiAgICBpZiAod2F2ZVN1cmZlclJlZ2lvbikge1xuICAgICAgc2NlbmVQbGF5YmFja1JlZ2lvbi5zdGFydE1pbGxpcyA9IHdhdmVTdXJmZXJSZWdpb24uc3RhcnQgKiAxMDAwO1xuICAgICAgc2NlbmVQbGF5YmFja1JlZ2lvbi5lbmRNaWxsaXMgPSB3YXZlU3VyZmVyUmVnaW9uLmVuZCAqIDEwMDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIHNjZW5lUGxheWJhY2tSZWdpb24uc3RhcnRNaWxsaXMgPSAodGhpcy53YXZlU3VyZmVyLmdldER1cmF0aW9uKCkgKiAxMDAwKSAvIDM7XG4gICAgICBzY2VuZVBsYXliYWNrUmVnaW9uLmVuZE1pbGxpcyA9ICgodGhpcy53YXZlU3VyZmVyLmdldER1cmF0aW9uKCkgKiAxMDAwKSAvIDMpICogMjtcbiAgICB9XG5cbiAgICB0aGlzLnNlbGVjdGVkQ29tcG9zaXRpb24uc2NlbmVQbGF5YmFja1JlZ2lvbnMucHVzaChzY2VuZVBsYXliYWNrUmVnaW9uKTtcblxuICAgIHRoaXMuc2VsZWN0ZWRQbGF5YmFja1JlZ2lvbiA9IHNjZW5lUGxheWJhY2tSZWdpb247XG5cbiAgICBpZiAod2F2ZVN1cmZlclJlZ2lvbikge1xuICAgICAgd2F2ZVN1cmZlclJlZ2lvbi5jb2xvciA9XG4gICAgICAgICdyZ2JhKCcgK1xuICAgICAgICB0aGlzLmhleFRvUmdiKHRoaXMuc2NlbmVTZXJ2aWNlLnNlbGVjdGVkU2NlbmVzWzBdLmNvbG9yKS5yICtcbiAgICAgICAgJywgJyArXG4gICAgICAgIHRoaXMuaGV4VG9SZ2IodGhpcy5zY2VuZVNlcnZpY2Uuc2VsZWN0ZWRTY2VuZXNbMF0uY29sb3IpLmcgK1xuICAgICAgICAnLCAnICtcbiAgICAgICAgdGhpcy5oZXhUb1JnYih0aGlzLnNjZW5lU2VydmljZS5zZWxlY3RlZFNjZW5lc1swXS5jb2xvcikuYiArXG4gICAgICAgICcsICcgK1xuICAgICAgICB0aGlzLmludGVuc2l0eUhpZ2hsaWdodGVkICtcbiAgICAgICAgJyknO1xuICAgICAgd2F2ZVN1cmZlclJlZ2lvbi5hdHRyaWJ1dGVzLnNlbGVjdGFibGUgPSB0cnVlO1xuICAgICAgdGhpcy5jb25uZWN0UmVnaW9uKHdhdmVTdXJmZXJSZWdpb24sIHRoaXMuc2NlbmVTZXJ2aWNlLnNlbGVjdGVkU2NlbmVzWzBdLCBzY2VuZVBsYXliYWNrUmVnaW9uKTtcbiAgICAgIHRoaXMudXBkYXRlUmVnaW9uU2VsZWN0aW9uKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZHJhd1JlZ2lvbihzY2VuZVBsYXliYWNrUmVnaW9uLCB0aGlzLnNjZW5lU2VydmljZS5zZWxlY3RlZFNjZW5lc1swXSk7XG4gICAgfVxuXG4gICAgdGhpcy5wcmVzZXRTZXJ2aWNlLnByZXZpZXdMaXZlKCk7XG4gIH1cblxuICBwcml2YXRlIGdldFNuYXBUb0dyaWRJbnRlcnZhbCgpOiBudW1iZXIge1xuICAgIGlmICh0aGlzLnNlbGVjdGVkQ29tcG9zaXRpb24uc25hcFRvR3JpZCkge1xuICAgICAgcmV0dXJuIDYwIC8gdGhpcy5zZWxlY3RlZENvbXBvc2l0aW9uLmJlYXRzUGVyTWludXRlIC8gdGhpcy5zZWxlY3RlZENvbXBvc2l0aW9uLmdyaWRSZXNvbHV0aW9uO1xuICAgIH1cblxuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBwcml2YXRlIGdldFNuYXBUb0dyaWRPZmZzZXQoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5zZWxlY3RlZENvbXBvc2l0aW9uLmdyaWRPZmZzZXRNaWxsaXMgLyAxMDAwO1xuICB9XG5cbiAgZGVsZXRlU2VsZWN0ZWRDb21wb3NpdGlvbigpIHtcbiAgICB0aGlzLnByb2plY3RTZXJ2aWNlLnByb2plY3QuY29tcG9zaXRpb25zLnNwbGljZSh0aGlzLnNlbGVjdGVkQ29tcG9zaXRpb25JbmRleCwgMSk7XG4gICAgdGhpcy5zZWxlY3RlZENvbXBvc2l0aW9uID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuc2VsZWN0ZWRDb21wb3NpdGlvbkluZGV4ID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuZGVzdHJveVdhdmVTdXJmZXIoKTtcbiAgICBpZiAodGhpcy5wcm9qZWN0U2VydmljZS5wcm9qZWN0LmNvbXBvc2l0aW9ucy5sZW5ndGggPiAwKSB7XG4gICAgICB0aGlzLnNlbGVjdENvbXBvc2l0aW9uSW5kZXgoMCk7XG4gICAgfVxuICB9XG5cbiAgZGVzdHJveVdhdmVTdXJmZXIoKSB7XG4gICAgdGhpcy5kdXJhdGlvbiA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLmxvYWRpbmdBdWRpb0ZpbGUgPSBmYWxzZTtcblxuICAgIGlmICh0aGlzLndhdmVTdXJmZXIpIHtcbiAgICAgIHRoaXMud2F2ZVN1cmZlci5kZXN0cm95KCk7XG4gICAgICB0aGlzLndhdmVTdXJmZXIgPSB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG5cbiAgY3JlYXRlV2F2ZVN1cmZlcigpIHtcbiAgICB0aGlzLmRlc3Ryb3lXYXZlU3VyZmVyKCk7XG5cbiAgICBpZiAoIXRoaXMuc2VsZWN0ZWRDb21wb3NpdGlvbi5hdWRpb0ZpbGVOYW1lKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5sb2FkaW5nQXVkaW9GaWxlID0gdHJ1ZTtcblxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGhpcy53YXZlU3VyZmVyID0gV2F2ZVN1cmZlci5jcmVhdGUoe1xuICAgICAgICBjb250YWluZXI6ICcjd2F2ZWZvcm0nLFxuICAgICAgICB3YXZlQ29sb3I6ICd3aGl0ZScsXG4gICAgICAgIHByb2dyZXNzQ29sb3I6ICd3aGl0ZScsXG4gICAgICAgIC8vIGJhcldpZHRoOiAyLFxuICAgICAgICBoZWlnaHQ6IDEsXG4gICAgICAgIGludGVyYWN0OiBmYWxzZSxcbiAgICAgICAgLy8gVXNlIGZvciB0aW1lbGluZXMgd2l0aG91dCBzb3VuZC4gV2F2ZSB3aWxsIGJlIGRpc3BsYXllZFxuICAgICAgICAvLyB3cm9uZywgYnV0IHNob3VsZCB3b3JrIGZvciBhIGR1bW15IGF1ZGlvIHdpdGhvdXQgYW55IHdhdmVzLlxuICAgICAgICAvLyBkdXJhdGlvbjogNDAwLFxuICAgICAgICBwbHVnaW5zOiBbXG4gICAgICAgICAgQ3Vyc29yUGx1Z2luLmNyZWF0ZSh7XG4gICAgICAgICAgICAvLyBzaG93VGltZTogdHJ1ZSxcbiAgICAgICAgICAgIG9wYWNpdHk6IDEsXG4gICAgICAgICAgICBjb2xvcjogJyNmZDdlMTQnLFxuICAgICAgICAgICAgaGlkZU9uQmx1cjogZmFsc2UgLyogZG9uJ3Qgc2hvdy9oaWRlIHRoZSBjdXJzb3Igb24gdGhlIHdhdmUgKG9ubHkgb24gdGhlIHRpbWVsaW5lKSAqLyxcbiAgICAgICAgICB9KSxcbiAgICAgICAgICBSZWdpb25zUGx1Z2luLmNyZWF0ZSh7XG4gICAgICAgICAgICBkcmFnU2VsZWN0aW9uOiB7XG4gICAgICAgICAgICAgIHNsb3A6IDUsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY29sb3I6ICcjZmZmJyxcbiAgICAgICAgICAgIHNuYXBUb0dyaWRJbnRlcnZhbDogdGhpcy5nZXRTbmFwVG9HcmlkSW50ZXJ2YWwoKSxcbiAgICAgICAgICAgIHNuYXBUb0dyaWRPZmZzZXQ6IHRoaXMuZ2V0U25hcFRvR3JpZE9mZnNldCgpLFxuICAgICAgICAgIH0pLFxuICAgICAgICAgIFRpbWVMaW5lUGx1Z2luLmNyZWF0ZSh7XG4gICAgICAgICAgICBjb250YWluZXI6ICcjd2F2ZWZvcm0tdGltZWxpbmUnLFxuICAgICAgICAgICAgcHJpbWFyeUZvbnRDb2xvcjogJyNmZmYnLFxuICAgICAgICAgICAgc2Vjb25kYXJ5Rm9udENvbG9yOiAnI2ZmZicsXG4gICAgICAgICAgICBvZmZzZXQ6IHRoaXMuZ2V0U25hcFRvR3JpZE9mZnNldCgpLFxuICAgICAgICAgICAgZm9ybWF0VGltZUNhbGxiYWNrOiB0aGlzLmZvcm1hdFRpbWVDYWxsYmFjay5iaW5kKHRoaXMpLFxuICAgICAgICAgICAgdGltZUludGVydmFsOiB0aGlzLnRpbWVJbnRlcnZhbC5iaW5kKHRoaXMpLFxuICAgICAgICAgICAgcHJpbWFyeUxhYmVsSW50ZXJ2YWw6IHRoaXMucHJpbWFyeUxhYmVsSW50ZXJ2YWwuYmluZCh0aGlzKSxcbiAgICAgICAgICAgIHNlY29uZGFyeUxhYmVsSW50ZXJ2YWw6IHRoaXMuc2Vjb25kYXJ5TGFiZWxJbnRlcnZhbC5iaW5kKHRoaXMpLFxuICAgICAgICAgIH0pLFxuICAgICAgICBdLFxuICAgICAgfSk7XG5cbiAgICAgIGxldCBhdWRpb0ZpbGVOYW1lOiBzdHJpbmc7XG5cbiAgICAgIGlmICh0aGlzLmNvbmZpZ1NlcnZpY2UuZW5hYmxlTWVkaWFMaWJyYXJ5KSB7XG4gICAgICAgIC8vIHRoZSBmaWxlIG5hbWUgaXMgYWxzbyB1c2VkIGZvciB0aGUgcmVhbCBmaWxlIG5hbWVcbiAgICAgICAgYXVkaW9GaWxlTmFtZSA9ICdmaWxlL2dldD9uYW1lPScgKyB0aGlzLnNlbGVjdGVkQ29tcG9zaXRpb24uYXVkaW9GaWxlTmFtZSArICcmdHlwZT1BVURJTyc7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyB0aGUgY29tcG9zaXRpb24gdXVpZCBhbmQgZXh0ZW5zaW9uIGlzIHVzZWQgYXMgdGhlIGZpbGUgbmFtZVxuICAgICAgICBhdWRpb0ZpbGVOYW1lID1cbiAgICAgICAgICAnY29tcG9zaXRpb24tZmlsZXMvP2ZpbGU9JyArXG4gICAgICAgICAgdGhpcy5zZWxlY3RlZENvbXBvc2l0aW9uLnV1aWQgK1xuICAgICAgICAgICcuJyArXG4gICAgICAgICAgdGhpcy5zZWxlY3RlZENvbXBvc2l0aW9uLmF1ZGlvRmlsZU5hbWUuc3Vic3RyKHRoaXMuc2VsZWN0ZWRDb21wb3NpdGlvbi5hdWRpb0ZpbGVOYW1lLmxhc3RJbmRleE9mKCcuJykgKyAxKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy53YXZlU3VyZmVyLmxvYWQodGhpcy5jb25maWdTZXJ2aWNlLnJlc3RVcmwgKyBhdWRpb0ZpbGVOYW1lKTtcblxuICAgICAgdGhpcy53YXZlU3VyZmVyLm9uKCdyZWFkeScsICgpID0+IHtcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgLy8gdHJ5IGd1ZXNzaW5nIHRoZSBicG0gYW5kIG9mZnNldCBmcm9tIHRoZSBmaWxlLCBpZiBuZWNlc3NhcnlcbiAgICAgICAgICBpZiAodGhpcy5zZWxlY3RlZENvbXBvc2l0aW9uLnRlbXBvR3Vlc3NlZCkge1xuICAgICAgICAgICAgLy8gd2UgYWxyZWFkeSBndWVzc2VkIHRoZSBCUE0gb2YgdGhpcyBmaWxlIC0tPiBkb24ndCBkbyBpdCBhZ2FpblxuICAgICAgICAgICAgdGhpcy5sb2FkaW5nQXVkaW9GaWxlID0gZmFsc2U7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIHdlIGhhdmUgbm90IHlldCBndWVzc2VkIHRoZSBCUE0gLS0+IGRvIGl0IG5vd1xuICAgICAgICAgICAgdGhpcy5zZWxlY3RlZENvbXBvc2l0aW9uLnRlbXBvR3Vlc3NlZCA9IHRydWU7XG4gICAgICAgICAgICBndWVzcyh0aGlzLndhdmVTdXJmZXIuYmFja2VuZC5idWZmZXIpXG4gICAgICAgICAgICAgIC50aGVuKCh7IGJwbSwgb2Zmc2V0IH0pID0+IHtcbiAgICAgICAgICAgICAgICAvLyB0aGUgYnBtIGFuZCBvZmZzZXQgY291bGQgYmUgZ3Vlc3NlZFxuICAgICAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWRDb21wb3NpdGlvbi5iZWF0c1Blck1pbnV0ZSA9IGJwbTtcbiAgICAgICAgICAgICAgICB0aGlzLnNlbGVjdGVkQ29tcG9zaXRpb24uZ3JpZE9mZnNldE1pbGxpcyA9IG9mZnNldCAqIDEwMDA7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2FkaW5nQXVkaW9GaWxlID0gZmFsc2U7XG4gICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgIC5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICAgICAgICAgICAgLy8gc29tZXRoaW5nIHdlbnQgd3JvbmdcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdDb3VsZCBub3QgZGV0ZWN0IHRoZSBCUE0gZnJvbSB0aGUgYXVkaW8gZmlsZScsIGVycik7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2FkaW5nQXVkaW9GaWxlID0gZmFsc2U7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHRoaXMuZHVyYXRpb24gPSB0aGlzLm1zVG9UaW1lKHRoaXMud2F2ZVN1cmZlci5nZXREdXJhdGlvbigpICogMTAwMCk7XG4gICAgICAgICAgdGhpcy5kcmF3QWxsUmVnaW9ucygpO1xuXG4gICAgICAgICAgLy8gc2Nyb2xsIHdhdmVzdXJmZXIgaW4gc3luYyB3aXRoIHRoZSB0aW1lbGluZVxuICAgICAgICAgIHRoaXMud2F2ZVN1cmZlci50aW1lbGluZS53cmFwcGVyLmFkZEV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMud2F2ZVN1cmZlci5kcmF3ZXIud3JhcHBlci5zY3JvbGxMZWZ0ID0gdGhpcy53YXZlU3VyZmVyLnRpbWVsaW5lLndyYXBwZXIuc2Nyb2xsTGVmdDtcblxuICAgICAgICAgICAgLy8gU2V0IHRoZSBzY3JvbGwgcG9zaXRpb24gb2YgdGhlIHRpbWVsaW5lIHRvIHRoZSBzYW1lIHBvc2l0aW9uIGFzIHRoZSB3YXZlc3VyZmVyLFxuICAgICAgICAgICAgLy8gYmVjYXVzZSB0aGUgdGltZWxpbmUgaXMgbGFyZ2VyIHRoYW4gd2F2ZXN1cmZlciBhbmQgbWlnaHQgZ2V0IG91dCBvZiBzeW5jLlxuICAgICAgICAgICAgLy8gVGhpcyB3YXksIGlmIHdhdmVzdXJmZXIgY2Fubm90IHNjcm9sbCBhbnkgZnVydGhlciwgd2UgcmVzZXQgdGhlIHBvc2l0aW9uXG4gICAgICAgICAgICAvLyBvZiB0aGUgdGltZWxpbmUgYXMgd2VsbC5cbiAgICAgICAgICAgIHRoaXMud2F2ZVN1cmZlci50aW1lbGluZS53cmFwcGVyLnNjcm9sbExlZnQgPSB0aGlzLndhdmVTdXJmZXIuZHJhd2VyLndyYXBwZXIuc2Nyb2xsTGVmdDtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIC8vIGRpc3BsYXkgdGhlIGN1cnNvciBhbHNvIG9uIHRoZSB0aW1lbGluZVxuICAgICAgICAgIHRoaXMud2F2ZVN1cmZlci50aW1lbGluZS53cmFwcGVyLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZW50ZXInLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLndhdmVTdXJmZXIuY3Vyc29yLnNob3dDdXJzb3IoKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICB0aGlzLndhdmVTdXJmZXIudGltZWxpbmUud3JhcHBlci5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWxlYXZlJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy53YXZlU3VyZmVyLmN1cnNvci5oaWRlQ3Vyc29yKCk7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgdGhpcy53YXZlU3VyZmVyLnRpbWVsaW5lLndyYXBwZXIuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgKGU6IGFueSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgYmJveCA9IHRoaXMud2F2ZVN1cmZlci5jb250YWluZXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgICAgICBjb25zdCB4ID0gZS5jbGllbnRYIC0gYmJveC5sZWZ0O1xuICAgICAgICAgICAgdGhpcy53YXZlU3VyZmVyLmN1cnNvci51cGRhdGVDdXJzb3JQb3NpdGlvbih4LCAwKTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIC8vIGhpZGUgdGhlIGN1cnNvciBvbiB0aGUgd2F2ZSBpbml0aWFsbHkuIGluIGNvbWJpbmF0aW9uIHdpdGggdGhlIHBhcmFtIGhpZGVPbkJsdXIgPSBmYWxzZSxcbiAgICAgICAgICAvLyBpdCB3aWxsIG5ldmVyIGJlIGRpc3BsYXllZCBvbiB0aGUgd2F2ZSBub3cuIHdlIGhhbmRsZSBpdCBvbiB0aGUgdGltZWxpbmUgb25seS5cbiAgICAgICAgICB0aGlzLndhdmVTdXJmZXIuY3Vyc29yLmhpZGVDdXJzb3IoKTtcblxuICAgICAgICAgIC8vIHNlZWsgb24gdGltZWxpbmUtY2xpY2tcbiAgICAgICAgICB0aGlzLndhdmVTdXJmZXIudGltZWxpbmUud3JhcHBlci5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCAoZTogYW55KSA9PiB7XG4gICAgICAgICAgICB0aGlzLnRpbWVsaW5lQ2xpY2tpbmcgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5zZWVla1dpdGhUaW1lbGluZShlKTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIHRoaXMud2F2ZVN1cmZlci50aW1lbGluZS53cmFwcGVyLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIChlOiBhbnkpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnRpbWVsaW5lQ2xpY2tpbmcpIHtcbiAgICAgICAgICAgICAgdGhpcy5zZWVla1dpdGhUaW1lbGluZShlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIHRoaXMud2F2ZVN1cmZlci50aW1lbGluZS53cmFwcGVyLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCAoZTogYW55KSA9PiB7XG4gICAgICAgICAgICB0aGlzLnRpbWVsaW5lQ2xpY2tpbmcgPSBmYWxzZTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIHRoaXMudXBkYXRlQ3VycmVudFRpbWUoKTtcblxuICAgICAgICAgIHRoaXMuZGV0ZWN0Q2hhbmdlcy5uZXh0KCk7XG4gICAgICAgICAgdGhpcy53YXZlU3VyZmVyUmVhZHkubmV4dCgpO1xuICAgICAgICB9LCAwKTtcbiAgICAgIH0pO1xuXG4gICAgICB0aGlzLndhdmVTdXJmZXIub24oJ2Vycm9yJywgKGVycm9yOiBhbnkpID0+IHtcbiAgICAgICAgLy8gY291bGQgbm90IGxvYWQgdGhlIGNvbXBvc2l0aW9uIC0tPiBkZWxldGUgaXRcbiAgICAgICAgLy8gKHRoaXMgbWF5IG9jY3VyLCB3aGVuIHRoZSBjb21wb3NpdGlvbiBoYXMgYmVlbiBkZWxldGVkIGJ1dCB0aGUgcHJvamVjdCBpcyBub3Qgc2F2ZWQgYWZ0ZXJ3YXJkcylcbiAgICAgICAgdGhpcy5kZWxldGVTZWxlY3RlZENvbXBvc2l0aW9uKCk7XG4gICAgICB9KTtcblxuICAgICAgdGhpcy53YXZlU3VyZmVyLm9uKCdzZWVrJywgKCkgPT4ge1xuICAgICAgICB0aGlzLnVwZGF0ZUN1cnJlbnRUaW1lKCk7XG4gICAgICB9KTtcblxuICAgICAgdGhpcy53YXZlU3VyZmVyLm9uKCdwbGF5JywgKCkgPT4ge1xuICAgICAgICB0aGlzLnN0YXJ0VGltZVVwZGF0ZXIoKTtcbiAgICAgIH0pO1xuXG4gICAgICB0aGlzLndhdmVTdXJmZXIub24oJ3BhdXNlJywgKCkgPT4ge1xuICAgICAgICB0aGlzLnN0b3BUaW1lVXBkYXRlcigpO1xuICAgICAgfSk7XG5cbiAgICAgIHRoaXMud2F2ZVN1cmZlci5vbigncmVnaW9uLWNyZWF0ZWQnLCAocmVnaW9uKSA9PiB7XG4gICAgICAgIC8vIHJlZ2lvbiBjcmVhdGVkIGJ5IHNlbGVjdGlvbiBvciBwcm9ncmFtbWF0aWNhbGx5XG4gICAgICAgIGlmICh0aGlzLnNjZW5lU2VydmljZS5zZWxlY3RlZFNjZW5lcyAmJiB0aGlzLnNjZW5lU2VydmljZS5zZWxlY3RlZFNjZW5lcy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICBpZiAoIXJlZ2lvbi5kYXRhLmhhbmRsZWQpIHtcbiAgICAgICAgICAgIHRoaXMuYWRkUmVnaW9uKHJlZ2lvbik7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmICghcmVnaW9uLmRhdGEuaGFuZGxlZCkge1xuICAgICAgICAgICAgcmVnaW9uLnJlbW92ZSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIHRoaXMud2F2ZVN1cmZlci5vbigncmVnaW9uLXVwZGF0ZWQnLCAocmVnaW9uOiBhbnkpID0+IHtcbiAgICAgICAgdGhpcy5kZXRlY3RDaGFuZ2VzLm5leHQoKTtcbiAgICAgICAgdGhpcy5wcmVzZXRTZXJ2aWNlLnByZXZpZXdMaXZlKCk7XG4gICAgICB9KTtcbiAgICB9LCAwKTtcbiAgfVxuXG4gIHByaXZhdGUgaGV4VG9SZ2IoaGV4OiBzdHJpbmcpIHtcbiAgICBjb25zdCByZXN1bHQgPSAvXiM/KFthLWZcXGRdezJ9KShbYS1mXFxkXXsyfSkoW2EtZlxcZF17Mn0pJC9pLmV4ZWMoaGV4KTtcbiAgICByZXR1cm4gcmVzdWx0XG4gICAgICA/IHtcbiAgICAgICAgICByOiBwYXJzZUludChyZXN1bHRbMV0sIDE2KSxcbiAgICAgICAgICBnOiBwYXJzZUludChyZXN1bHRbMl0sIDE2KSxcbiAgICAgICAgICBiOiBwYXJzZUludChyZXN1bHRbM10sIDE2KSxcbiAgICAgICAgfVxuICAgICAgOiBudWxsO1xuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVSZWdpb25TZWxlY3Rpb24oKSB7XG4gICAgaWYgKCF0aGlzLndhdmVTdXJmZXIpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyh0aGlzLndhdmVTdXJmZXIucmVnaW9ucy5saXN0KSkge1xuICAgICAgY29uc3QgcmVnaW9uOiBhbnkgPSB0aGlzLndhdmVTdXJmZXIucmVnaW9ucy5saXN0W2tleV07XG5cbiAgICAgIC8vIGlmIG5vIHNjZW5lIGlzIHNldCwgdGhlIHJlZ2lvbiBpcyBub3QgdmFsaWQgKGUuZy4gaGFzIGJlZW4gY3JlYXRlZCwgd2hpbGVcbiAgICAgIC8vIG5vIHNjZW5lIGhhcyBiZWVuIHNlbGVjdGVkIGFuZCByZW1vdmUgZGlkIG5vdCB3b3JrIHByb3Blcmx5KVxuICAgICAgaWYgKHJlZ2lvbi5zY2VuZSkge1xuICAgICAgICBsZXQgaW50ZW5zaXR5ID0gdGhpcy5pbnRlbnNpdHk7XG5cbiAgICAgICAgcmVnaW9uLmRyYWcgPSBmYWxzZTtcbiAgICAgICAgcmVnaW9uLnJlc2l6ZSA9IGZhbHNlO1xuICAgICAgICByZWdpb24uYXR0cmlidXRlcy5zZWxlY3RhYmxlID0gZmFsc2U7XG5cbiAgICAgICAgaWYgKHRoaXMuc2NlbmVTZXJ2aWNlLnNjZW5lSXNTZWxlY3RlZChyZWdpb24uc2NlbmUpKSB7XG4gICAgICAgICAgaW50ZW5zaXR5ID0gdGhpcy5pbnRlbnNpdHlTZWxlY3RlZFNjZW5lO1xuICAgICAgICAgIHJlZ2lvbi5kcmFnID0gdHJ1ZTtcbiAgICAgICAgICByZWdpb24ucmVzaXplID0gdHJ1ZTtcbiAgICAgICAgICByZWdpb24uYXR0cmlidXRlcy5zZWxlY3RhYmxlID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJlZ2lvbi5hdHRyaWJ1dGVzLnNlbGVjdGVkID0gZmFsc2U7XG5cbiAgICAgICAgaWYgKHRoaXMuc2VsZWN0ZWRQbGF5YmFja1JlZ2lvbiAmJiB0aGlzLnNlbGVjdGVkUGxheWJhY2tSZWdpb24gPT09IHJlZ2lvbi5zY2VuZVBsYXliYWNrUmVnaW9uKSB7XG4gICAgICAgICAgaW50ZW5zaXR5ID0gdGhpcy5pbnRlbnNpdHlIaWdobGlnaHRlZDtcbiAgICAgICAgICByZWdpb24uYXR0cmlidXRlcy5zZWxlY3RlZCA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICByZWdpb24uY29sb3IgPVxuICAgICAgICAgICdyZ2JhKCcgK1xuICAgICAgICAgIHRoaXMuaGV4VG9SZ2IocmVnaW9uLnNjZW5lLmNvbG9yKS5yICtcbiAgICAgICAgICAnLCAnICtcbiAgICAgICAgICB0aGlzLmhleFRvUmdiKHJlZ2lvbi5zY2VuZS5jb2xvcikuZyArXG4gICAgICAgICAgJywgJyArXG4gICAgICAgICAgdGhpcy5oZXhUb1JnYihyZWdpb24uc2NlbmUuY29sb3IpLmIgK1xuICAgICAgICAgICcsICcgK1xuICAgICAgICAgIGludGVuc2l0eSArXG4gICAgICAgICAgJyknO1xuICAgICAgICByZWdpb24udXBkYXRlUmVuZGVyKCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgdXBkYXRlU2VsZWN0ZWRSZWdpb24oKSB7XG4gICAgaWYgKCF0aGlzLndhdmVTdXJmZXIpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuc2VsZWN0ZWRQbGF5YmFja1JlZ2lvbikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKHRoaXMud2F2ZVN1cmZlci5yZWdpb25zLmxpc3QpKSB7XG4gICAgICBjb25zdCByZWdpb246IGFueSA9IHRoaXMud2F2ZVN1cmZlci5yZWdpb25zLmxpc3Rba2V5XTtcblxuICAgICAgaWYgKHRoaXMuc2VsZWN0ZWRQbGF5YmFja1JlZ2lvbiA9PT0gcmVnaW9uLnNjZW5lUGxheWJhY2tSZWdpb24pIHtcbiAgICAgICAgcmVnaW9uLnN0YXJ0ID0gdGhpcy5zZWxlY3RlZFBsYXliYWNrUmVnaW9uLnN0YXJ0TWlsbGlzIC8gMTAwMDtcbiAgICAgICAgcmVnaW9uLmVuZCA9IHRoaXMuc2VsZWN0ZWRQbGF5YmFja1JlZ2lvbi5lbmRNaWxsaXMgLyAxMDAwO1xuICAgICAgICByZWdpb24udXBkYXRlUmVuZGVyKCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgc2V0U2VsZWN0ZWRSZWdpb24oc2NlbmVQbGF5YmFja1JlZ2lvbj86IFNjZW5lUGxheWJhY2tSZWdpb24pIHtcbiAgICBpZiAodGhpcy5zZWxlY3RlZFBsYXliYWNrUmVnaW9uICYmIHRoaXMuc2VsZWN0ZWRQbGF5YmFja1JlZ2lvbiA9PT0gc2NlbmVQbGF5YmFja1JlZ2lvbikge1xuICAgICAgLy8gTm8gdXBkYXRlIHJlcXVpcmVkXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHNjZW5lUGxheWJhY2tSZWdpb24pIHtcbiAgICAgIHRoaXMuc2VsZWN0ZWRQbGF5YmFja1JlZ2lvbiA9IHNjZW5lUGxheWJhY2tSZWdpb247XG4gICAgfVxuXG4gICAgdGhpcy51cGRhdGVSZWdpb25TZWxlY3Rpb24oKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0UmVnaW9uU25hcFRvR3JpZFZhbHVlKHZhbHVlOiBudW1iZXIpOiBudW1iZXIge1xuICAgIC8vIHRoZSByZWdpb25zIHNob3VsZCBzbmFwIHRvIGEgZ3JpZFxuICAgIGNvbnN0IG9mZnNldCA9IHRoaXMuZ2V0U25hcFRvR3JpZE9mZnNldCgpIHx8IDA7XG4gICAgY29uc3QgaW50ZXJ2YWwgPSB0aGlzLmdldFNuYXBUb0dyaWRJbnRlcnZhbCgpIHx8IDA7XG4gICAgcmV0dXJuIE1hdGgucm91bmQoKHZhbHVlIC0gb2Zmc2V0KSAvIGludGVydmFsKSAqIGludGVydmFsICsgb2Zmc2V0O1xuICB9XG5cbiAgcHJpdmF0ZSBjb25uZWN0UmVnaW9uKHdhdmVTdXJmZXJSZWdpb246IGFueSwgc2NlbmU6IFNjZW5lLCBzY2VuZVBsYXliYWNrUmVnaW9uOiBTY2VuZVBsYXliYWNrUmVnaW9uLCBwcmVzZXQ/OiBQcmVzZXQpIHtcbiAgICB3YXZlU3VyZmVyUmVnaW9uLnNjZW5lUGxheWJhY2tSZWdpb24gPSBzY2VuZVBsYXliYWNrUmVnaW9uO1xuICAgIHdhdmVTdXJmZXJSZWdpb24uc2NlbmUgPSBzY2VuZTtcbiAgICB3YXZlU3VyZmVyUmVnaW9uLnByZXNldCA9IHByZXNldDtcblxuICAgIHdhdmVTdXJmZXJSZWdpb24ub24oJ2NsaWNrJywgKGV2ZW50KSA9PiB7XG4gICAgICBpZiAodGhpcy5zY2VuZVNlcnZpY2Uuc2NlbmVJc1NlbGVjdGVkKHNjZW5lKSkge1xuICAgICAgICB0aGlzLnNldFNlbGVjdGVkUmVnaW9uKHNjZW5lUGxheWJhY2tSZWdpb24pO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgd2F2ZVN1cmZlclJlZ2lvbi5vbigndXBkYXRlJywgKCkgPT4ge1xuICAgICAgdGhpcy5zZXRTZWxlY3RlZFJlZ2lvbihzY2VuZVBsYXliYWNrUmVnaW9uKTtcbiAgICAgIGlmICh0aGlzLnNlbGVjdGVkQ29tcG9zaXRpb24uc25hcFRvR3JpZCkge1xuICAgICAgICAvLyB1cGRhdGUgdGhlIHJlZ2lvbnMgYm91bmRhcmllcy4gdGhleSBtYXkgbm90IHNuYXAgdG8gZ3JpZCwgaWYgaXQgaGFzIGJlZW5cbiAgICAgICAgLy8gZGlzYWJsZWQgZHVyaW5nIGNyZWF0aW9uIG9mIHRoZSByZWdpb24gYnV0IGFjdGl2YXRlZCBhZnRlcndhcmRzLlxuICAgICAgICB3YXZlU3VyZmVyUmVnaW9uLnN0YXJ0ID0gdGhpcy5nZXRSZWdpb25TbmFwVG9HcmlkVmFsdWUod2F2ZVN1cmZlclJlZ2lvbi5zdGFydCk7XG4gICAgICAgIHdhdmVTdXJmZXJSZWdpb24uZW5kID0gdGhpcy5nZXRSZWdpb25TbmFwVG9HcmlkVmFsdWUod2F2ZVN1cmZlclJlZ2lvbi5lbmQpO1xuICAgICAgfVxuICAgICAgc2NlbmVQbGF5YmFja1JlZ2lvbi5zdGFydE1pbGxpcyA9IHdhdmVTdXJmZXJSZWdpb24uc3RhcnQgKiAxMDAwO1xuICAgICAgc2NlbmVQbGF5YmFja1JlZ2lvbi5lbmRNaWxsaXMgPSB3YXZlU3VyZmVyUmVnaW9uLmVuZCAqIDEwMDA7XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGRyYXdSZWdpb24oc2NlbmVQbGF5YmFja1JlZ2lvbjogU2NlbmVQbGF5YmFja1JlZ2lvbiwgc2NlbmU6IFNjZW5lKSB7XG4gICAgLy8gZHJhdyB0aGUgcmVnaW9ucyBvZiB0aGUgY3VycmVudGx5IHNlbGVjdGVkIHNjZW5lXG4gICAgaWYgKCF0aGlzLmlzV2F2ZVN1cmZlclJlYWR5KCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBhZGQgdGhlIHBsYXliYWNrIHJlZ2lvblxuICAgIGNvbnN0IHdhdmVTdXJmZXJSZWdpb24gPSB0aGlzLndhdmVTdXJmZXIuYWRkUmVnaW9uKHtcbiAgICAgIHN0YXJ0OiBzY2VuZVBsYXliYWNrUmVnaW9uLnN0YXJ0TWlsbGlzIC8gMTAwMCxcbiAgICAgIGVuZDogc2NlbmVQbGF5YmFja1JlZ2lvbi5lbmRNaWxsaXMgLyAxMDAwLFxuICAgICAgY29sb3I6ICcjZmZmJyxcbiAgICAgIGRhdGE6IHsgaGFuZGxlZDogdHJ1ZSB9LFxuICAgIH0pO1xuICAgIHRoaXMuY29ubmVjdFJlZ2lvbih3YXZlU3VyZmVyUmVnaW9uLCBzY2VuZSwgc2NlbmVQbGF5YmFja1JlZ2lvbik7XG5cbiAgICAvLyBUT0RPIHNob3cgdGhlIGFsbCBwcmVzZXRzXG4gICAgLy8gZm9yIChsZXQgcHJlc2V0VXVpZCBvZiBzY2VuZS5wcmVzZXRVdWlkcykge1xuICAgIC8vICAgY29uc3QgcHJlc2V0ID0gdGhpcy5wcmVzZXRTZXJ2aWNlLmdldFByZXNldEJ5VXVpZChwcmVzZXRVdWlkKTtcblxuICAgIC8vICAgbGV0IHdhdmVTdXJmZXJSZWdpb24gPSB0aGlzLnRpbWVsaW5lU2VydmljZS53YXZlU3VyZmVyLmFkZFJlZ2lvbih7XG4gICAgLy8gICAgIHN0YXJ0OiAoc2NlbmVQbGF5YmFja1JlZ2lvbi5zdGFydE1pbGxpcyArIChwcmVzZXQuc3RhcnRNaWxsaXMgPyBwcmVzZXQuc3RhcnRNaWxsaXMgOiAwKSkgLyAxMDAwLFxuICAgIC8vICAgICBlbmQ6IChzY2VuZVBsYXliYWNrUmVnaW9uLnN0YXJ0TWlsbGlzXG4gICAgLy8gICAgICAgKyAocHJlc2V0LmVuZE1pbGxpcyA/IHByZXNldC5lbmRNaWxsaXMgOiBzY2VuZVBsYXliYWNrUmVnaW9uLmVuZE1pbGxpcyAtIHNjZW5lUGxheWJhY2tSZWdpb24uc3RhcnRNaWxsaXMpKSAvIDEwMDAsXG4gICAgLy8gICAgIGNvbG9yOiAnI2ZmZicsXG4gICAgLy8gICAgIGRhdGE6IHsgaGFuZGxlZDogdHJ1ZSB9LFxuICAgIC8vICAgICAvLyBUT0RPXG4gICAgLy8gICAgIGF0dHJpYnV0ZXM6IHtcbiAgICAvLyAgICAgICBwcmVzZXQ6IHRydWUsXG4gICAgLy8gICAgICAgbmFtZTogJ1ByZXNldCAxJ1xuICAgIC8vICAgICB9XG4gICAgLy8gICB9KTtcbiAgICAvLyAgIHRoaXMuY29ubmVjdFJlZ2lvbih3YXZlU3VyZmVyUmVnaW9uLCBzY2VuZSwgc2NlbmVQbGF5YmFja1JlZ2lvbiwgcHJlc2V0KTtcbiAgICAvLyB9XG5cbiAgICB0aGlzLnVwZGF0ZVJlZ2lvblNlbGVjdGlvbigpO1xuICB9XG5cbiAgcmVtb3ZlUmVnaW9uKCkge1xuICAgIGlmICghdGhpcy5zZWxlY3RlZFBsYXliYWNrUmVnaW9uKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuc2NlbmVTZXJ2aWNlLnNlbGVjdGVkU2NlbmVzLmxlbmd0aCAhPT0gMSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZWxlY3RlZENvbXBvc2l0aW9uLnNjZW5lUGxheWJhY2tSZWdpb25zLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAodGhpcy5zZWxlY3RlZENvbXBvc2l0aW9uLnNjZW5lUGxheWJhY2tSZWdpb25zW2ldID09PSB0aGlzLnNlbGVjdGVkUGxheWJhY2tSZWdpb24pIHtcbiAgICAgICAgLy8gcmVtb3ZlIHRoZSByZWdpb24gZnJvbSB3YXZlc3VyZmVyXG4gICAgICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKHRoaXMud2F2ZVN1cmZlci5yZWdpb25zLmxpc3QpKSB7XG4gICAgICAgICAgY29uc3QgcmVnaW9uOiBhbnkgPSB0aGlzLndhdmVTdXJmZXIucmVnaW9ucy5saXN0W2tleV07XG5cbiAgICAgICAgICBpZiAocmVnaW9uLnNjZW5lUGxheWJhY2tSZWdpb24gPT09IHRoaXMuc2VsZWN0ZWRQbGF5YmFja1JlZ2lvbikge1xuICAgICAgICAgICAgcmVnaW9uLnJlbW92ZSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc2VsZWN0ZWRQbGF5YmFja1JlZ2lvbiA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5zZWxlY3RlZENvbXBvc2l0aW9uLnNjZW5lUGxheWJhY2tSZWdpb25zLnNwbGljZShpLCAxKTtcblxuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5wcmVzZXRTZXJ2aWNlLnByZXZpZXdMaXZlKCk7XG4gIH1cblxuICBnZXRQcmVzZXRzSW5UaW1lKHRpbWVNaWxsaXM6IG51bWJlcik6IFByZXNldFJlZ2lvblNjZW5lW10ge1xuICAgIC8vIFJldHVybiBhbGwgcHJlc2V0cyB3aGljaCBzaG91bGQgYmUgYWN0aXZlIGR1cmluZyB0aGUgc3BlY2lmaWVkIHRpbWVcbiAgICBjb25zdCBhY3RpdmVQcmVzZXRzOiBQcmVzZXRSZWdpb25TY2VuZVtdID0gW107XG5cbiAgICBmb3IgKGxldCBzY2VuZUluZGV4ID0gdGhpcy5wcm9qZWN0U2VydmljZS5wcm9qZWN0LnNjZW5lcy5sZW5ndGggLSAxOyBzY2VuZUluZGV4ID49IDA7IHNjZW5lSW5kZXgtLSkge1xuICAgICAgY29uc3Qgc2NlbmUgPSB0aGlzLnByb2plY3RTZXJ2aWNlLnByb2plY3Quc2NlbmVzW3NjZW5lSW5kZXhdO1xuXG4gICAgICBmb3IgKGNvbnN0IHJlZ2lvbiBvZiB0aGlzLnNlbGVjdGVkQ29tcG9zaXRpb24uc2NlbmVQbGF5YmFja1JlZ2lvbnMpIHtcbiAgICAgICAgaWYgKHJlZ2lvbi5zY2VuZVV1aWQgPT09IHNjZW5lLnV1aWQpIHtcbiAgICAgICAgICBmb3IgKGxldCBwcmVzZXRJbmRleCA9IHRoaXMucHJvamVjdFNlcnZpY2UucHJvamVjdC5wcmVzZXRzLmxlbmd0aCAtIDE7IHByZXNldEluZGV4ID49IDA7IHByZXNldEluZGV4LS0pIHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgcHJlc2V0VXVpZCBvZiBzY2VuZS5wcmVzZXRVdWlkcykge1xuICAgICAgICAgICAgICBpZiAocHJlc2V0VXVpZCA9PT0gdGhpcy5wcm9qZWN0U2VydmljZS5wcm9qZWN0LnByZXNldHNbcHJlc2V0SW5kZXhdLnV1aWQpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBwcmVzZXQgPSB0aGlzLnByZXNldFNlcnZpY2UuZ2V0UHJlc2V0QnlVdWlkKHByZXNldFV1aWQpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHByZXNldCkge1xuICAgICAgICAgICAgICAgICAgbGV0IHByZXNldFN0YXJ0TWlsbGlzID0gcHJlc2V0LnN0YXJ0TWlsbGlzID09PSB1bmRlZmluZWQgPyByZWdpb24uc3RhcnRNaWxsaXMgOiByZWdpb24uc3RhcnRNaWxsaXMgKyBwcmVzZXQuc3RhcnRNaWxsaXM7XG4gICAgICAgICAgICAgICAgICBsZXQgcHJlc2V0RW5kTWlsbGlzID0gcHJlc2V0LmVuZE1pbGxpcyA9PT0gdW5kZWZpbmVkID8gcmVnaW9uLmVuZE1pbGxpcyA6IHJlZ2lvbi5zdGFydE1pbGxpcyArIHByZXNldC5lbmRNaWxsaXM7XG5cbiAgICAgICAgICAgICAgICAgIC8vIGV4dGVuZCB0aGUgcnVubmluZyB0aW1lLCBpZiBmYWRpbmcgaXMgZG9uZSBvdXRzaWRlIHRoZSBib3VuZGFyaWVzXG4gICAgICAgICAgICAgICAgICBwcmVzZXRTdGFydE1pbGxpcyAtPSBwcmVzZXQuZmFkZUluUHJlID8gcHJlc2V0LmZhZGVJbk1pbGxpcyA6IDA7XG4gICAgICAgICAgICAgICAgICBwcmVzZXRFbmRNaWxsaXMgKz0gcHJlc2V0LmZhZGVPdXRQb3N0ID8gcHJlc2V0LmZhZGVPdXRNaWxsaXMgOiAwO1xuXG4gICAgICAgICAgICAgICAgICBpZiAocHJlc2V0U3RhcnRNaWxsaXMgPD0gdGltZU1pbGxpcyAmJiBwcmVzZXRFbmRNaWxsaXMgPj0gdGltZU1pbGxpcykge1xuICAgICAgICAgICAgICAgICAgICBhY3RpdmVQcmVzZXRzLnB1c2gobmV3IFByZXNldFJlZ2lvblNjZW5lKHByZXNldCwgcmVnaW9uLCBzY2VuZSkpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBhY3RpdmVQcmVzZXRzO1xuICB9XG5cbiAgZHJhd0FsbFJlZ2lvbnMoKSB7XG4gICAgaWYgKCF0aGlzLnNlbGVjdGVkQ29tcG9zaXRpb24pIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBkcmF3IHRoZSByZWdpb25zIGluIHRoZSBzYW1lIG9yZGVyIGFzIHRoZWlyIGNvcnJlc3BvbmRpbmcgc2NlbmVzLCBidXQgZHJhd1xuICAgIC8vIHRoZSBzZWxlY3RlZCBvbmVzIGxhc3QsIHRvIG1ha2Ugc3VyZSB0aGV5J3JlIGFsd2F5cyBjbGlja2FibGUuXG4gICAgZm9yIChsZXQgc2NlbmVJbmRleCA9IHRoaXMucHJvamVjdFNlcnZpY2UucHJvamVjdC5zY2VuZXMubGVuZ3RoIC0gMTsgc2NlbmVJbmRleCA+PSAwOyBzY2VuZUluZGV4LS0pIHtcbiAgICAgIGNvbnN0IHNjZW5lID0gdGhpcy5wcm9qZWN0U2VydmljZS5wcm9qZWN0LnNjZW5lc1tzY2VuZUluZGV4XTtcbiAgICAgIGlmICghdGhpcy5zY2VuZVNlcnZpY2Uuc2NlbmVJc1NlbGVjdGVkKHNjZW5lKSkge1xuICAgICAgICBmb3IgKGNvbnN0IHNjZW5lUGxheWJhY2tSZWdpb24gb2YgdGhpcy5zZWxlY3RlZENvbXBvc2l0aW9uLnNjZW5lUGxheWJhY2tSZWdpb25zKSB7XG4gICAgICAgICAgaWYgKHNjZW5lUGxheWJhY2tSZWdpb24uc2NlbmVVdWlkID09PSBzY2VuZS51dWlkKSB7XG4gICAgICAgICAgICB0aGlzLmRyYXdSZWdpb24oc2NlbmVQbGF5YmFja1JlZ2lvbiwgc2NlbmUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIGRyYXcgYWxsIHNlbGVjdGVkIHNjZW5lcyBhZnRlcndhcmRzXG4gICAgZm9yIChsZXQgc2NlbmVJbmRleCA9IHRoaXMucHJvamVjdFNlcnZpY2UucHJvamVjdC5zY2VuZXMubGVuZ3RoIC0gMTsgc2NlbmVJbmRleCA+PSAwOyBzY2VuZUluZGV4LS0pIHtcbiAgICAgIGNvbnN0IHNjZW5lID0gdGhpcy5wcm9qZWN0U2VydmljZS5wcm9qZWN0LnNjZW5lc1tzY2VuZUluZGV4XTtcblxuICAgICAgaWYgKHRoaXMuc2NlbmVTZXJ2aWNlLnNjZW5lSXNTZWxlY3RlZChzY2VuZSkpIHtcbiAgICAgICAgZm9yIChjb25zdCBzY2VuZVBsYXliYWNrUmVnaW9uIG9mIHRoaXMuc2VsZWN0ZWRDb21wb3NpdGlvbi5zY2VuZVBsYXliYWNrUmVnaW9ucykge1xuICAgICAgICAgIGlmIChzY2VuZVBsYXliYWNrUmVnaW9uLnNjZW5lVXVpZCA9PT0gc2NlbmUudXVpZCkge1xuICAgICAgICAgICAgdGhpcy5kcmF3UmVnaW9uKHNjZW5lUGxheWJhY2tSZWdpb24sIHNjZW5lKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICB1cGRhdGVHcmlkKCkge1xuICAgIGlmICh0aGlzLndhdmVTdXJmZXJSZWFkeSkge1xuICAgICAgdGhpcy53YXZlU3VyZmVyLnRpbWVsaW5lLnBhcmFtcy5vZmZzZXQgPSB0aGlzLmdldFNuYXBUb0dyaWRPZmZzZXQoKTtcblxuICAgICAgdGhpcy53YXZlU3VyZmVyLnJlZ2lvbnMucGFyYW1zLnNuYXBUb0dyaWRJbnRlcnZhbCA9IHRoaXMuZ2V0U25hcFRvR3JpZEludGVydmFsKCk7XG4gICAgICB0aGlzLndhdmVTdXJmZXIucmVnaW9ucy5wYXJhbXMuc25hcFRvR3JpZE9mZnNldCA9IHRoaXMuZ2V0U25hcFRvR3JpZE9mZnNldCgpO1xuICAgIH1cbiAgICB0aGlzLnVwZGF0ZUN1cnJlbnRUaW1lKCk7XG4gIH1cblxuICBnZXRFeHRlcm5hbENvbXBvc2l0aW9uTmFtZXMoKTogT2JzZXJ2YWJsZTxzdHJpbmdbXT4ge1xuICAgIC8vIGdldCBhdmFpbGFibGUgY29tcG9zaXRpb25zIGZyb20gYW4gZXh0ZXJuYWwgcG9vbCAoZS5nLiBSb2NrZXQgU2hvdylcbiAgICByZXR1cm4gdGhpcy5odHRwLmdldCgnY29tcG9zaXRpb24vbGlzdCcpLnBpcGUoXG4gICAgICBtYXAoKHJlc3BvbnNlOiBvYmplY3RbXSkgPT4ge1xuICAgICAgICBjb25zdCBjb21wb3NpdGlvbk5hbWVzOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgICAgIGZvciAoY29uc3QgcmVzcG9uc2VDb21wb3NpdGlvbiBvZiByZXNwb25zZSkge1xuICAgICAgICAgIGNvbXBvc2l0aW9uTmFtZXMucHVzaCgocmVzcG9uc2VDb21wb3NpdGlvbiBhcyBhbnkpLm5hbWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGNvbXBvc2l0aW9uTmFtZXM7XG4gICAgICB9KVxuICAgICk7XG4gIH1cblxuICBzZWxlY3RDb21wb3NpdGlvbkluZGV4KGluZGV4OiBudW1iZXIpIHtcbiAgICB0aGlzLnNlbGVjdGVkQ29tcG9zaXRpb24gPSB0aGlzLnByb2plY3RTZXJ2aWNlLnByb2plY3QuY29tcG9zaXRpb25zW2luZGV4XTtcbiAgICB0aGlzLnNlbGVjdGVkQ29tcG9zaXRpb25JbmRleCA9IGluZGV4O1xuICAgIHRoaXMucHJvamVjdFNlcnZpY2UucHJvamVjdC5zZWxlY3RlZENvbXBvc2l0aW9uVXVpZCA9IHRoaXMuc2VsZWN0ZWRDb21wb3NpdGlvbi51dWlkO1xuICAgIHRoaXMuY3JlYXRlV2F2ZVN1cmZlcigpO1xuXG4gICAgLy8gcmVxdWlyZWQgdG8gdHJpZ2dlciB0aW1lbGluZS5jb21wb25lbnQucmVzaXplKClcbiAgICB0aGlzLndhdmVTdXJmZXJSZWFkeS5uZXh0KCk7XG5cbiAgICB0aGlzLmFwcGx5Wm9vbSgwKTtcbiAgfVxufVxuIl19
|