@smarterplan/ngx-smarterplan-core 1.2.39 → 1.2.45
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/README.md +24 -24
- package/esm2020/lib/components/csv-export/csv-export.component.mjs +59 -59
- package/esm2020/lib/components/loader/loader.component.mjs +23 -23
- package/esm2020/lib/components/menu-bar/avatar/avatar.component.mjs +80 -80
- package/esm2020/lib/components/menu-bar/menu-bar.component.mjs +99 -99
- package/esm2020/lib/components/menu-bar/navigation-bar/navigation-bar.component.mjs +384 -384
- package/esm2020/lib/components/menu-bar/range-date-picker/range-date-picker.component.mjs +147 -147
- package/esm2020/lib/components/modal-switch-visit/modal-switch-visit.component.mjs +40 -40
- package/esm2020/lib/components/search-bar/search-bar.component.mjs +63 -63
- package/esm2020/lib/components/support-modal/support-modal.component.mjs +66 -66
- package/esm2020/lib/config.mjs +4 -4
- package/esm2020/lib/helpers.service.mjs +470 -470
- package/esm2020/lib/matterport-extensions/hsl-loader/HlsLoader.mjs +69 -69
- package/esm2020/lib/matterport-extensions/nest-thermostat/CanvasImage.mjs +51 -51
- package/esm2020/lib/matterport-extensions/nest-thermostat/CanvasRenderer.mjs +61 -61
- package/esm2020/lib/matterport-extensions/nest-thermostat/NestThermostat.mjs +158 -158
- package/esm2020/lib/matterport-extensions/nest-thermostat/PlaneRenderer.mjs +85 -85
- package/esm2020/lib/matterport-extensions/scene-component/SceneComponent.mjs +128 -128
- package/esm2020/lib/matterport-extensions/security-camera/SecurityCamera.mjs +249 -249
- package/esm2020/lib/matterport-extensions/tv-player/TvPlayer.mjs +98 -98
- package/esm2020/lib/matterport-extensions/video-renderer/VideoRenderer.mjs +64 -64
- package/esm2020/lib/matterport-extensions/view-frustum-mesh/ViewFrustumMesh.mjs +221 -221
- package/esm2020/lib/mattertagData.mjs +165 -165
- package/esm2020/lib/ngx-smarterplan-core.module.mjs +122 -122
- package/esm2020/lib/ngx-smarterplan-core.service.mjs +14 -14
- package/esm2020/lib/pipes/duration-to-string.pipe.mjs +66 -66
- package/esm2020/lib/pipes/format-date-number-to-digits.pipe.mjs +30 -30
- package/esm2020/lib/pipes/hashtag-from-id.pipe.mjs +26 -26
- package/esm2020/lib/pipes/safe-url.pipe.mjs +20 -20
- package/esm2020/lib/pipes/time-date-to-local-string.pipe.mjs +104 -104
- package/esm2020/lib/pipes/username-from-id.pipe.mjs +29 -29
- package/esm2020/lib/services/amplify-cache.service.mjs +72 -72
- package/esm2020/lib/services/base-tab.service.mjs +24 -24
- package/esm2020/lib/services/baseVisibility.service.mjs +18 -18
- package/esm2020/lib/services/content.service.mjs +135 -135
- package/esm2020/lib/services/filter.service.mjs +599 -599
- package/esm2020/lib/services/intervention.service.mjs +236 -236
- package/esm2020/lib/services/locale.service.mjs +45 -45
- package/esm2020/lib/services/matterport-import.service.mjs +340 -340
- package/esm2020/lib/services/matterport.service.mjs +1587 -1587
- package/esm2020/lib/services/models/affectation.service.mjs +60 -60
- package/esm2020/lib/services/models/base-object.service.mjs +70 -70
- package/esm2020/lib/services/models/capture.service.mjs +34 -34
- package/esm2020/lib/services/models/comment.service.mjs +98 -98
- package/esm2020/lib/services/models/domain.service.mjs +78 -78
- package/esm2020/lib/services/models/equipment.service.mjs +683 -683
- package/esm2020/lib/services/models/event.service.mjs +128 -128
- package/esm2020/lib/services/models/feature.service.mjs +380 -364
- package/esm2020/lib/services/models/hashtag.service.mjs +38 -38
- package/esm2020/lib/services/models/layer.service.mjs +33 -33
- package/esm2020/lib/services/models/measurement.service.mjs +199 -199
- package/esm2020/lib/services/models/mission.service.mjs +206 -206
- package/esm2020/lib/services/models/navigation.service.mjs +92 -92
- package/esm2020/lib/services/models/node.service.mjs +31 -31
- package/esm2020/lib/services/models/object3D.service.mjs +364 -364
- package/esm2020/lib/services/models/operation.service.mjs +59 -59
- package/esm2020/lib/services/models/organisation.service.mjs +73 -73
- package/esm2020/lib/services/models/plan.service.mjs +799 -799
- package/esm2020/lib/services/models/poi.service.mjs +103 -103
- package/esm2020/lib/services/models/profile.service.mjs +58 -58
- package/esm2020/lib/services/models/property.service.mjs +44 -44
- package/esm2020/lib/services/models/space.service.mjs +204 -204
- package/esm2020/lib/services/models/template.service.mjs +41 -41
- package/esm2020/lib/services/models/ticket.service.mjs +526 -526
- package/esm2020/lib/services/models/visit.service.mjs +130 -130
- package/esm2020/lib/services/models/zone.service.mjs +225 -225
- package/esm2020/lib/services/navigator.service.mjs +212 -212
- package/esm2020/lib/services/s3.service.mjs +137 -137
- package/esm2020/lib/services/search.service.mjs +124 -124
- package/esm2020/lib/services/support.service.mjs +42 -42
- package/esm2020/lib/services/tag.service.mjs +111 -111
- package/esm2020/lib/services/user.service.mjs +501 -501
- package/esm2020/lib/services/validators.service.mjs +50 -50
- package/esm2020/lib/services/viewer.service.mjs +389 -389
- package/esm2020/lib/services/zone-drawer.service.mjs +76 -76
- package/esm2020/lib/services/zoneChange.service.mjs +30 -30
- package/esm2020/lib/types.service.mjs +311 -310
- package/esm2020/lib/validators/email.directive.mjs +7 -7
- package/esm2020/lib/validators/no-empty.directive.mjs +12 -12
- package/esm2020/lib/validators/number.directive.mjs +12 -12
- package/esm2020/lib/validators/text.directive.mjs +12 -12
- package/esm2020/public-api.mjs +72 -72
- package/esm2020/smarterplan-ngx-smarterplan-core.mjs +4 -4
- package/fesm2015/smarterplan-ngx-smarterplan-core.mjs +13009 -12992
- package/fesm2015/smarterplan-ngx-smarterplan-core.mjs.map +1 -1
- package/fesm2020/smarterplan-ngx-smarterplan-core.mjs +12258 -12241
- package/fesm2020/smarterplan-ngx-smarterplan-core.mjs.map +1 -1
- package/lib/components/csv-export/csv-export.component.d.ts +18 -18
- package/lib/components/loader/loader.component.d.ts +10 -10
- package/lib/components/menu-bar/avatar/avatar.component.d.ts +21 -21
- package/lib/components/menu-bar/menu-bar.component.d.ts +38 -38
- package/lib/components/menu-bar/navigation-bar/navigation-bar.component.d.ts +73 -73
- package/lib/components/menu-bar/range-date-picker/range-date-picker.component.d.ts +35 -35
- package/lib/components/modal-switch-visit/modal-switch-visit.component.d.ts +22 -22
- package/lib/components/search-bar/search-bar.component.d.ts +16 -16
- package/lib/components/support-modal/support-modal.component.d.ts +26 -26
- package/lib/config.d.ts +22 -22
- package/lib/helpers.service.d.ts +79 -79
- package/lib/matterport-extensions/hsl-loader/HlsLoader.d.ts +26 -26
- package/lib/matterport-extensions/nest-thermostat/CanvasImage.d.ts +31 -31
- package/lib/matterport-extensions/nest-thermostat/CanvasRenderer.d.ts +37 -37
- package/lib/matterport-extensions/nest-thermostat/NestThermostat.d.ts +42 -42
- package/lib/matterport-extensions/nest-thermostat/PlaneRenderer.d.ts +46 -46
- package/lib/matterport-extensions/scene-component/SceneComponent.d.ts +388 -388
- package/lib/matterport-extensions/security-camera/SecurityCamera.d.ts +47 -47
- package/lib/matterport-extensions/tv-player/TvPlayer.d.ts +26 -26
- package/lib/matterport-extensions/video-renderer/VideoRenderer.d.ts +26 -26
- package/lib/matterport-extensions/view-frustum-mesh/ViewFrustumMesh.d.ts +43 -43
- package/lib/mattertagData.d.ts +70 -70
- package/lib/ngx-smarterplan-core.module.d.ts +29 -29
- package/lib/ngx-smarterplan-core.service.d.ts +6 -6
- package/lib/pipes/duration-to-string.pipe.d.ts +12 -12
- package/lib/pipes/format-date-number-to-digits.pipe.d.ts +10 -10
- package/lib/pipes/hashtag-from-id.pipe.d.ts +10 -10
- package/lib/pipes/safe-url.pipe.d.ts +10 -10
- package/lib/pipes/time-date-to-local-string.pipe.d.ts +16 -16
- package/lib/pipes/username-from-id.pipe.d.ts +11 -11
- package/lib/services/amplify-cache.service.d.ts +37 -37
- package/lib/services/base-tab.service.d.ts +10 -10
- package/lib/services/baseVisibility.service.d.ts +9 -9
- package/lib/services/content.service.d.ts +28 -28
- package/lib/services/filter.service.d.ts +60 -60
- package/lib/services/intervention.service.d.ts +25 -25
- package/lib/services/locale.service.d.ts +23 -23
- package/lib/services/matterport-import.service.d.ts +53 -53
- package/lib/services/matterport.service.d.ts +336 -336
- package/lib/services/models/affectation.service.d.ts +14 -14
- package/lib/services/models/base-object.service.d.ts +20 -20
- package/lib/services/models/capture.service.d.ts +13 -13
- package/lib/services/models/comment.service.d.ts +26 -26
- package/lib/services/models/domain.service.d.ts +19 -19
- package/lib/services/models/equipment.service.d.ts +93 -93
- package/lib/services/models/event.service.d.ts +43 -43
- package/lib/services/models/feature.service.d.ts +75 -74
- package/lib/services/models/hashtag.service.d.ts +13 -13
- package/lib/services/models/layer.service.d.ts +11 -11
- package/lib/services/models/measurement.service.d.ts +51 -51
- package/lib/services/models/mission.service.d.ts +39 -39
- package/lib/services/models/navigation.service.d.ts +29 -29
- package/lib/services/models/node.service.d.ts +12 -12
- package/lib/services/models/object3D.service.d.ts +57 -57
- package/lib/services/models/operation.service.d.ts +15 -15
- package/lib/services/models/organisation.service.d.ts +19 -19
- package/lib/services/models/plan.service.d.ts +133 -133
- package/lib/services/models/poi.service.d.ts +25 -25
- package/lib/services/models/profile.service.d.ts +16 -16
- package/lib/services/models/property.service.d.ts +13 -13
- package/lib/services/models/space.service.d.ts +46 -46
- package/lib/services/models/template.service.d.ts +15 -15
- package/lib/services/models/ticket.service.d.ts +93 -93
- package/lib/services/models/visit.service.d.ts +24 -24
- package/lib/services/models/zone.service.d.ts +50 -50
- package/lib/services/navigator.service.d.ts +61 -61
- package/lib/services/s3.service.d.ts +14 -14
- package/lib/services/search.service.d.ts +20 -20
- package/lib/services/support.service.d.ts +17 -17
- package/lib/services/tag.service.d.ts +29 -29
- package/lib/services/user.service.d.ts +118 -118
- package/lib/services/validators.service.d.ts +18 -18
- package/lib/services/viewer.service.d.ts +110 -110
- package/lib/services/zone-drawer.service.d.ts +7 -7
- package/lib/services/zoneChange.service.d.ts +17 -17
- package/lib/types.service.d.ts +842 -840
- package/lib/validators/email.directive.d.ts +2 -2
- package/lib/validators/no-empty.directive.d.ts +2 -2
- package/lib/validators/number.directive.d.ts +2 -2
- package/lib/validators/text.directive.d.ts +2 -2
- package/package.json +1 -1
- package/public-api.d.ts +64 -64
- package/smarterplan-ngx-smarterplan-core.d.ts +5 -5
|
@@ -1,599 +1,599 @@
|
|
|
1
|
-
/* eslint-disable no-case-declarations */
|
|
2
|
-
/* eslint-disable no-await-in-loop */
|
|
3
|
-
/* eslint-disable guard-for-in */
|
|
4
|
-
/* eslint-disable class-methods-use-this */
|
|
5
|
-
import { Injectable } from "@angular/core";
|
|
6
|
-
import { Subject } from "rxjs";
|
|
7
|
-
import { getLevelsBelow, getHighestLevelForMissions, getHighestRoleForMissions, filterUniqueArrayByID } from "../helpers.service";
|
|
8
|
-
import { PoiType, ProfileEntity, RoleStatus } from "../types.service";
|
|
9
|
-
import levenshtein from 'js-levenshtein';
|
|
10
|
-
import * as i0 from "@angular/core";
|
|
11
|
-
import * as i1 from "./user.service";
|
|
12
|
-
import * as i2 from "./models/zone.service";
|
|
13
|
-
import * as i3 from "./models/poi.service";
|
|
14
|
-
var FilterType;
|
|
15
|
-
(function (FilterType) {
|
|
16
|
-
FilterType["DOMAIN"] = "DOMAIN";
|
|
17
|
-
FilterType["LEVEL"] = "LEVEL";
|
|
18
|
-
FilterType["ROLE"] = "ROLE";
|
|
19
|
-
FilterType["ZONE"] = "ZONE";
|
|
20
|
-
FilterType["SPACE"] = "SPACE";
|
|
21
|
-
FilterType["HASHTAG"] = "HASHTAG";
|
|
22
|
-
})(FilterType || (FilterType = {}));
|
|
23
|
-
export class FilterService {
|
|
24
|
-
constructor(userService, zoneService, poiService) {
|
|
25
|
-
this.userService = userService;
|
|
26
|
-
this.zoneService = zoneService;
|
|
27
|
-
this.poiService = poiService;
|
|
28
|
-
this.updateDateFilter = new Subject();
|
|
29
|
-
}
|
|
30
|
-
filterTicketsByDomain(ticketsToFilter, domain) {
|
|
31
|
-
return ticketsToFilter.filter((tic) => tic.domainID === domain);
|
|
32
|
-
}
|
|
33
|
-
filterObjectsByLevel(objectsToFilter, level) {
|
|
34
|
-
const visibleLevels = getLevelsBelow(level);
|
|
35
|
-
const filtered = objectsToFilter.filter((tic) => visibleLevels.includes(tic.level));
|
|
36
|
-
return filtered;
|
|
37
|
-
}
|
|
38
|
-
filterTicketsForMission(ticketsToFilter, mission) {
|
|
39
|
-
const managerRoles = [
|
|
40
|
-
RoleStatus.MANAGER,
|
|
41
|
-
RoleStatus.ADMIN,
|
|
42
|
-
RoleStatus.OWNER,
|
|
43
|
-
];
|
|
44
|
-
if (!managerRoles.includes(mission.role)) {
|
|
45
|
-
if (mission.role === RoleStatus.SERVICE) {
|
|
46
|
-
// SERVICE can see tickets to which he is assigned
|
|
47
|
-
const ticketsAssigned = [];
|
|
48
|
-
for (const t of ticketsToFilter) {
|
|
49
|
-
if (t.assignees.items.length > 0) {
|
|
50
|
-
for (const assignment of t.assignees.items) {
|
|
51
|
-
if (assignment.missionID === mission.id) {
|
|
52
|
-
ticketsAssigned.push(t);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
return ticketsAssigned;
|
|
58
|
-
}
|
|
59
|
-
// OCCUPANT and VISITOR can see only tickets that they created
|
|
60
|
-
return ticketsToFilter.filter((ticket) => {
|
|
61
|
-
return ticket.ownerMissionID === mission.id;
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
return ticketsToFilter;
|
|
65
|
-
}
|
|
66
|
-
getFiltersForRole(role) {
|
|
67
|
-
switch (role) {
|
|
68
|
-
case RoleStatus.ADMIN:
|
|
69
|
-
return [FilterType.LEVEL];
|
|
70
|
-
case RoleStatus.MANAGER:
|
|
71
|
-
return [FilterType.ZONE, FilterType.LEVEL];
|
|
72
|
-
case RoleStatus.OWNER:
|
|
73
|
-
return [FilterType.ZONE, FilterType.LEVEL];
|
|
74
|
-
case RoleStatus.SERVICE:
|
|
75
|
-
return [
|
|
76
|
-
FilterType.ZONE,
|
|
77
|
-
FilterType.LEVEL,
|
|
78
|
-
FilterType.DOMAIN,
|
|
79
|
-
FilterType.ROLE, // that is the most severe filter
|
|
80
|
-
];
|
|
81
|
-
case RoleStatus.OCCUPANT:
|
|
82
|
-
return [
|
|
83
|
-
FilterType.ZONE,
|
|
84
|
-
FilterType.DOMAIN,
|
|
85
|
-
FilterType.ROLE,
|
|
86
|
-
FilterType.LEVEL,
|
|
87
|
-
FilterType.HASHTAG,
|
|
88
|
-
];
|
|
89
|
-
case RoleStatus.VISITOR:
|
|
90
|
-
return [
|
|
91
|
-
FilterType.ZONE,
|
|
92
|
-
FilterType.LEVEL,
|
|
93
|
-
FilterType.DOMAIN,
|
|
94
|
-
FilterType.ROLE,
|
|
95
|
-
FilterType.HASHTAG,
|
|
96
|
-
];
|
|
97
|
-
case RoleStatus.VISITOR_MUSEUM:
|
|
98
|
-
return [FilterType.ZONE, FilterType.LEVEL, FilterType.HASHTAG];
|
|
99
|
-
case RoleStatus.GUIDE_MUSEUM:
|
|
100
|
-
return [FilterType.LEVEL];
|
|
101
|
-
default:
|
|
102
|
-
return [FilterType.LEVEL];
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
async filterObjectsForCurrentUserInSpace(objects, spaceID) {
|
|
106
|
-
const finalObject3Ds = [];
|
|
107
|
-
let domFiltered = objects;
|
|
108
|
-
let levelFiltered = objects;
|
|
109
|
-
let zoneFiltered = objects;
|
|
110
|
-
const missions = this.userService.currentMissions;
|
|
111
|
-
if (missions) {
|
|
112
|
-
const currentSpaceMissions = missions.filter((m) => m.spaceID === spaceID);
|
|
113
|
-
if (currentSpaceMissions.length > 0) {
|
|
114
|
-
for (const obj of levelFiltered) {
|
|
115
|
-
if (domFiltered.includes(obj) &&
|
|
116
|
-
zoneFiltered.includes(obj)) {
|
|
117
|
-
finalObject3Ds.push(obj);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
return finalObject3Ds;
|
|
123
|
-
}
|
|
124
|
-
async filterTicketsForCurrentUserInSpace(tickets, spaceID) {
|
|
125
|
-
const finalTickets = [];
|
|
126
|
-
let domFiltered = tickets;
|
|
127
|
-
let roleFiltered = tickets;
|
|
128
|
-
let levelFiltered = tickets;
|
|
129
|
-
let zoneFiltered = tickets;
|
|
130
|
-
const missions = this.userService.currentMissions;
|
|
131
|
-
if (missions) {
|
|
132
|
-
const currentSpaceMissions = missions.filter((m) => m.spaceID === spaceID);
|
|
133
|
-
if (currentSpaceMissions.length > 0) {
|
|
134
|
-
const highestLelel = getHighestLevelForMissions(currentSpaceMissions);
|
|
135
|
-
const highestRole = getHighestRoleForMissions(currentSpaceMissions);
|
|
136
|
-
// console.log("Highest level: ", highestLelel, ", Highest Role: ", highestRole)
|
|
137
|
-
const filters = this.getFiltersForRole(highestRole);
|
|
138
|
-
for (const filter of filters) {
|
|
139
|
-
if (filter === FilterType.DOMAIN) {
|
|
140
|
-
let domains = [];
|
|
141
|
-
for (const m of currentSpaceMissions) {
|
|
142
|
-
if (m.domains) {
|
|
143
|
-
domains = [...domains, ...m.domains];
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
let allDomainsFiltered = [];
|
|
147
|
-
for (const d of domains) {
|
|
148
|
-
const currentDomFiltered = this.filterTicketsByDomain(tickets, d);
|
|
149
|
-
allDomainsFiltered = [
|
|
150
|
-
...allDomainsFiltered,
|
|
151
|
-
...currentDomFiltered,
|
|
152
|
-
];
|
|
153
|
-
}
|
|
154
|
-
domFiltered = allDomainsFiltered;
|
|
155
|
-
}
|
|
156
|
-
if (filter === FilterType.ROLE) {
|
|
157
|
-
const highestRoleMission = currentSpaceMissions.find((m) => m.role === highestRole);
|
|
158
|
-
roleFiltered = this.filterTicketsForMission(tickets, highestRoleMission);
|
|
159
|
-
}
|
|
160
|
-
if (filter === FilterType.LEVEL) {
|
|
161
|
-
levelFiltered = this.filterObjectsByLevel(tickets, highestLelel);
|
|
162
|
-
}
|
|
163
|
-
if (filter === FilterType.ZONE) {
|
|
164
|
-
zoneFiltered = await this.applyZoneFilterForMissions(currentSpaceMissions, tickets);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
// keep only tickets present in all filtered arrays
|
|
168
|
-
// console.log(domFiltered);
|
|
169
|
-
// console.log(roleFiltered);
|
|
170
|
-
// console.log(levelFiltered);
|
|
171
|
-
// console.log(zoneFiltered);
|
|
172
|
-
for (const tic of levelFiltered) {
|
|
173
|
-
if (domFiltered.includes(tic) &&
|
|
174
|
-
roleFiltered.includes(tic) &&
|
|
175
|
-
zoneFiltered.includes(tic)) {
|
|
176
|
-
finalTickets.push(tic);
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
// console.log(finalTickets);
|
|
182
|
-
return finalTickets;
|
|
183
|
-
}
|
|
184
|
-
subscribeToDataFilterUpdate(next, error, complete) {
|
|
185
|
-
const s = this.updateDateFilter.subscribe(next, error, complete);
|
|
186
|
-
return s;
|
|
187
|
-
}
|
|
188
|
-
dateFilterUpdated(dateRange) {
|
|
189
|
-
this.currentDateFilter = dateRange;
|
|
190
|
-
this.updateDateFilter.next(dateRange);
|
|
191
|
-
}
|
|
192
|
-
filterObjectsForDateRange(objects, dateRange) {
|
|
193
|
-
return objects.filter((object) => {
|
|
194
|
-
const createdAtDate = new Date(object.createdAt);
|
|
195
|
-
return (createdAtDate >= dateRange[0] && createdAtDate <= dateRange[1]);
|
|
196
|
-
});
|
|
197
|
-
}
|
|
198
|
-
filterMeasurementsForDateRange(measurements, dateRange) {
|
|
199
|
-
return measurements.filter((measure) => {
|
|
200
|
-
const createdAtDate = new Date(measure.comment.createdAt);
|
|
201
|
-
return (createdAtDate >= dateRange[0] && createdAtDate <= dateRange[1]);
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
async filterObjectsForZone(objects, // TODO: remove any here..
|
|
205
|
-
zoneID = null, zone = null) {
|
|
206
|
-
const filteredObjects = [];
|
|
207
|
-
await Promise.all(objects.map(async (object) => {
|
|
208
|
-
const [poi] = object.pois.items;
|
|
209
|
-
if (poi && zone) {
|
|
210
|
-
if (zone.sweepIDs && zone.sweepIDs.includes(poi.matterportSweepID)) {
|
|
211
|
-
if (this.poiService.poiIsVirtual(poi) && zone.layer && zone.layer.name === "FLOOR") {
|
|
212
|
-
// we include in Floor zone only
|
|
213
|
-
filteredObjects.push(object);
|
|
214
|
-
}
|
|
215
|
-
if (!this.poiService.poiIsVirtual(poi)) {
|
|
216
|
-
filteredObjects.push(object);
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
if (poi && !zone && zoneID) {
|
|
221
|
-
const zones = await this.zoneService.getZonesForObject(object);
|
|
222
|
-
if (zones &&
|
|
223
|
-
zones.some((zone_) => zone_.id === zoneID ||
|
|
224
|
-
zone_.parentID === zoneID)) {
|
|
225
|
-
filteredObjects.push(object);
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
}));
|
|
229
|
-
return filteredObjects;
|
|
230
|
-
}
|
|
231
|
-
filterEquipmentsByDomainList(equipments, domainIDList) {
|
|
232
|
-
let filtered = [];
|
|
233
|
-
const filteredByDomain = equipments.filter((equip) => domainIDList.includes(equip.domainID));
|
|
234
|
-
filtered = [...filtered, ...filteredByDomain];
|
|
235
|
-
const filteredByParentDomain = equipments.filter((equip) => equip.domain &&
|
|
236
|
-
equip.domain.parentID &&
|
|
237
|
-
domainIDList.includes(equip.domain.parentID));
|
|
238
|
-
filtered = [...filtered, ...filteredByParentDomain];
|
|
239
|
-
return filterUniqueArrayByID(filtered);
|
|
240
|
-
}
|
|
241
|
-
// Not implemented yet!
|
|
242
|
-
// filterObjects3DByDomainList(
|
|
243
|
-
// objects3D: Object3D[],
|
|
244
|
-
// domainIDList: string[],
|
|
245
|
-
// ): Object3D[] {
|
|
246
|
-
// let filtered = [];
|
|
247
|
-
// const filteredByDomain = objects3D.filter((equip) =>
|
|
248
|
-
// domainIDList.includes(equip.domainID),
|
|
249
|
-
// );
|
|
250
|
-
// filtered = [...filtered, ...filteredByDomain];
|
|
251
|
-
// const filteredByParentDomain = objects3D.filter(
|
|
252
|
-
// (obj) =>
|
|
253
|
-
// obj.domain &&
|
|
254
|
-
// obj.domain.parentID &&
|
|
255
|
-
// domainIDList.includes(obj.domain.parentID),
|
|
256
|
-
// );
|
|
257
|
-
// filtered = [...filtered, ...filteredByParentDomain];
|
|
258
|
-
// return filterUniqueArrayByID(filtered);
|
|
259
|
-
// }
|
|
260
|
-
filterEquipmentsForTerm(equips, term) {
|
|
261
|
-
// filter domains
|
|
262
|
-
let byDomain = equips.filter((eq) => {
|
|
263
|
-
if (eq.domain && eq.domain.name) {
|
|
264
|
-
const normalizedDomain = eq.domain.name.toLowerCase();
|
|
265
|
-
const lev = levenshtein(normalizedDomain, term);
|
|
266
|
-
return lev <= 2 || normalizedDomain.includes(term);
|
|
267
|
-
}
|
|
268
|
-
return false;
|
|
269
|
-
});
|
|
270
|
-
const byParentDomain = equips.filter((eq) => {
|
|
271
|
-
if (eq.domain && eq.domain.parentID) {
|
|
272
|
-
const normalizedParent = eq.domain.parent.name.toLowerCase();
|
|
273
|
-
const lev = levenshtein(normalizedParent, term);
|
|
274
|
-
return lev <= 2 || normalizedParent.includes(term);
|
|
275
|
-
}
|
|
276
|
-
return false;
|
|
277
|
-
});
|
|
278
|
-
byDomain = [...byDomain, ...byParentDomain];
|
|
279
|
-
// filter name
|
|
280
|
-
let byName = [];
|
|
281
|
-
const terms = term.split(" ").filter((token) => token.length > 2);
|
|
282
|
-
for (const eq of equips) {
|
|
283
|
-
const words = eq.name
|
|
284
|
-
.toLowerCase()
|
|
285
|
-
.split(" ")
|
|
286
|
-
.filter((token) => token.length > 2);
|
|
287
|
-
const matched = [];
|
|
288
|
-
for (const token of terms) {
|
|
289
|
-
for (const word of words) {
|
|
290
|
-
if (levenshtein(token, word) <= 1) {
|
|
291
|
-
matched.push(true);
|
|
292
|
-
break;
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
if (matched.length === terms.length) {
|
|
297
|
-
byName.push(eq);
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
const byNameSimple = equips.filter((eq) => eq.name.toLowerCase().includes(term));
|
|
301
|
-
byName = [...byName, ...byNameSimple];
|
|
302
|
-
// by serial number
|
|
303
|
-
const bySerialNumber = equips.filter((eq) => eq.serialNumber && eq.serialNumber.toLowerCase() === term);
|
|
304
|
-
const result = [...byDomain, ...byName, ...bySerialNumber];
|
|
305
|
-
return filterUniqueArrayByID(result);
|
|
306
|
-
}
|
|
307
|
-
filterTicketsForTerm(tickets, term) {
|
|
308
|
-
// filter term in title and description
|
|
309
|
-
const byTitle = this.filterObjectsForTerm(tickets, term);
|
|
310
|
-
// by equipment
|
|
311
|
-
const byEquipment = tickets.filter((ticket) => ticket.equipments &&
|
|
312
|
-
this.filterEquipmentsForTerm(ticket.equipments, term).length >
|
|
313
|
-
0);
|
|
314
|
-
return filterUniqueArrayByID([...byTitle, ...byEquipment]);
|
|
315
|
-
}
|
|
316
|
-
filterLocationsForTerm(locations, term) {
|
|
317
|
-
// by name
|
|
318
|
-
const byName = locations.filter((loc) => loc.name.toLowerCase().includes(term));
|
|
319
|
-
// by address
|
|
320
|
-
const byAddress = locations.filter((loc) => loc.addresses.toLowerCase().includes(term));
|
|
321
|
-
return filterUniqueArrayByID([...byName, ...byAddress]);
|
|
322
|
-
}
|
|
323
|
-
filterOrganisationsForTerm(orgs, term) {
|
|
324
|
-
const byName = orgs.filter((org) => {
|
|
325
|
-
const words = org.name.toLowerCase().split(" ");
|
|
326
|
-
return (words.some((word) => word.length > 2 && levenshtein(word, term) <= 1) || org.name.toLowerCase().includes(term));
|
|
327
|
-
});
|
|
328
|
-
return byName;
|
|
329
|
-
}
|
|
330
|
-
filterUsersForTerm(users, term) {
|
|
331
|
-
const byName = users.filter((user) => {
|
|
332
|
-
const words = user.displayName.toLowerCase().split(" ");
|
|
333
|
-
return (words.some((word) => word.length > 2 && levenshtein(word, term) <= 1) || user.displayName.toLowerCase().includes(term));
|
|
334
|
-
});
|
|
335
|
-
return byName;
|
|
336
|
-
}
|
|
337
|
-
async filterFeaturesForCurrentUserInSpace(features, spaceID) {
|
|
338
|
-
const finalFeatures = [];
|
|
339
|
-
let levelFiltered = features;
|
|
340
|
-
let zoneFiltered = features;
|
|
341
|
-
let hashtagFiltered = features;
|
|
342
|
-
const missions = this.userService.currentMissions;
|
|
343
|
-
if (missions) {
|
|
344
|
-
const currentSpaceMissions = missions.filter((m) => m.spaceID === spaceID);
|
|
345
|
-
if (currentSpaceMissions.length > 0) {
|
|
346
|
-
const highestLelel = getHighestLevelForMissions(currentSpaceMissions);
|
|
347
|
-
const highestRole = getHighestRoleForMissions(currentSpaceMissions);
|
|
348
|
-
const filters = this.getFiltersForRole(highestRole);
|
|
349
|
-
for (const filter of filters) {
|
|
350
|
-
if (filter === FilterType.LEVEL) {
|
|
351
|
-
levelFiltered = this.filterObjectsByLevel(features, highestLelel);
|
|
352
|
-
}
|
|
353
|
-
if (filter === FilterType.ZONE) {
|
|
354
|
-
zoneFiltered = await this.applyZoneFilterForMissions(currentSpaceMissions, features);
|
|
355
|
-
}
|
|
356
|
-
if (filter === FilterType.HASHTAG) {
|
|
357
|
-
hashtagFiltered =
|
|
358
|
-
this.filterFeaturesByHashtagsAndLocale(currentSpaceMissions, features);
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
for (const feature of levelFiltered) {
|
|
362
|
-
if (hashtagFiltered.includes(feature) &&
|
|
363
|
-
zoneFiltered.includes(feature)) {
|
|
364
|
-
finalFeatures.push(feature);
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
return finalFeatures;
|
|
370
|
-
}
|
|
371
|
-
filterFeaturesForTerm(features, term) {
|
|
372
|
-
// filter term in title
|
|
373
|
-
const byTitle = this.filterObjectsForTerm(features, term);
|
|
374
|
-
// by comments
|
|
375
|
-
const byComment = features.filter((feature) => this.filterObjectsForTerm(feature.comments.items, term).length >
|
|
376
|
-
0);
|
|
377
|
-
return filterUniqueArrayByID([...byTitle, ...byComment]);
|
|
378
|
-
}
|
|
379
|
-
/**
|
|
380
|
-
*
|
|
381
|
-
* @param objects Array of Comments, Tickets, Features. Obligatory proporties: title, description
|
|
382
|
-
* @param term string
|
|
383
|
-
*/
|
|
384
|
-
filterObjectsForTerm(objects, term) {
|
|
385
|
-
// filter term in title
|
|
386
|
-
const byTitle = objects.filter((feature) => {
|
|
387
|
-
const words = feature.title.toLowerCase().split(" ");
|
|
388
|
-
return (words.some((word) => word.length > 2 && levenshtein(word, term) <= 1) || feature.title.toLowerCase().includes(term));
|
|
389
|
-
});
|
|
390
|
-
// term present in description
|
|
391
|
-
const byDescription = objects.filter((feature) => feature.description &&
|
|
392
|
-
feature.description.toLowerCase().includes(term));
|
|
393
|
-
return filterUniqueArrayByID([...byTitle, ...byDescription]);
|
|
394
|
-
}
|
|
395
|
-
filterMissionByStartTimeDateForDateRange(missions, dateRange) {
|
|
396
|
-
return missions.filter((mission) => {
|
|
397
|
-
const startDateTime = new Date(mission.startDateTime);
|
|
398
|
-
return (startDateTime >= dateRange[0] && startDateTime <= dateRange[1]);
|
|
399
|
-
});
|
|
400
|
-
}
|
|
401
|
-
async applyZoneFilterForMissions(currentSpaceMissions, objects) {
|
|
402
|
-
const allowedZones = [];
|
|
403
|
-
for (const mission of currentSpaceMissions) {
|
|
404
|
-
if (mission.zoneID) {
|
|
405
|
-
allowedZones.push(mission.zoneID);
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
if (allowedZones.length === currentSpaceMissions.length) {
|
|
409
|
-
let allZoneFiltered = [];
|
|
410
|
-
await Promise.all(allowedZones.map(async (zoneID) => {
|
|
411
|
-
const currentZoneFiltered = await this.filterObjectsForZone(objects, zoneID);
|
|
412
|
-
allZoneFiltered = [
|
|
413
|
-
...allZoneFiltered,
|
|
414
|
-
...currentZoneFiltered,
|
|
415
|
-
];
|
|
416
|
-
}));
|
|
417
|
-
return filterUniqueArrayByID(allZoneFiltered);
|
|
418
|
-
}
|
|
419
|
-
return objects;
|
|
420
|
-
}
|
|
421
|
-
async filterEquipmentsForCurrentUserInSpace(spaceID, equips) {
|
|
422
|
-
const finalEquips = [];
|
|
423
|
-
let domFiltered = equips;
|
|
424
|
-
const roleFiltered = equips;
|
|
425
|
-
const levelFiltered = equips;
|
|
426
|
-
let zoneFiltered = equips;
|
|
427
|
-
const missions = this.userService.currentMissions;
|
|
428
|
-
if (missions) {
|
|
429
|
-
const currentSpaceMissions = missions.filter((m) => m.spaceID === spaceID);
|
|
430
|
-
if (currentSpaceMissions.length > 0) {
|
|
431
|
-
const highestLelel = getHighestLevelForMissions(currentSpaceMissions);
|
|
432
|
-
const highestRole = getHighestRoleForMissions(currentSpaceMissions);
|
|
433
|
-
// console.log("Highest level: ", highestLelel, ", Highest Role: ", highestRole)
|
|
434
|
-
const filters = this.getFiltersForRole(highestRole);
|
|
435
|
-
for (const filter of filters) {
|
|
436
|
-
if (filter === FilterType.DOMAIN) {
|
|
437
|
-
let domains = [];
|
|
438
|
-
for (const m of currentSpaceMissions) {
|
|
439
|
-
if (m.domains) {
|
|
440
|
-
domains = [...domains, ...m.domains];
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
let allDomainsFiltered = [];
|
|
444
|
-
const currentDomFiltered = this.filterEquipmentsByDomainList(equips, domains);
|
|
445
|
-
allDomainsFiltered = [
|
|
446
|
-
...allDomainsFiltered,
|
|
447
|
-
...currentDomFiltered,
|
|
448
|
-
];
|
|
449
|
-
domFiltered = allDomainsFiltered;
|
|
450
|
-
}
|
|
451
|
-
if (filter === FilterType.ROLE) {
|
|
452
|
-
// const highestRoleMission = currentSpaceMissions.find(
|
|
453
|
-
// (m) => m.role === highestRole,
|
|
454
|
-
// );
|
|
455
|
-
// TODO
|
|
456
|
-
}
|
|
457
|
-
if (filter === FilterType.LEVEL) {
|
|
458
|
-
// TODO, equipment does not have level
|
|
459
|
-
}
|
|
460
|
-
if (filter === FilterType.ZONE) {
|
|
461
|
-
zoneFiltered = await this.applyZoneFilterForMissions(currentSpaceMissions, equips);
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
for (const tic of levelFiltered) {
|
|
465
|
-
if (domFiltered.includes(tic) &&
|
|
466
|
-
roleFiltered.includes(tic) &&
|
|
467
|
-
zoneFiltered.includes(tic)) {
|
|
468
|
-
finalEquips.push(tic);
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
return finalEquips;
|
|
474
|
-
}
|
|
475
|
-
async filterMeasurementsForCurrentUserInSpace(spaceID, comments) {
|
|
476
|
-
let finalMeasurements = [];
|
|
477
|
-
let zoneFiltered = comments;
|
|
478
|
-
const missions = this.userService.currentMissions;
|
|
479
|
-
if (missions) {
|
|
480
|
-
const currentSpaceMissions = missions.filter((m) => m.spaceID === spaceID);
|
|
481
|
-
if (currentSpaceMissions.length > 0) {
|
|
482
|
-
const highestRole = getHighestRoleForMissions(currentSpaceMissions);
|
|
483
|
-
const filters = this.getFiltersForRole(highestRole);
|
|
484
|
-
for (const filter of filters) {
|
|
485
|
-
if (filter === FilterType.ZONE) {
|
|
486
|
-
zoneFiltered = await this.applyZoneFilterForMissions(currentSpaceMissions, comments);
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
finalMeasurements = zoneFiltered;
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
return finalMeasurements;
|
|
493
|
-
}
|
|
494
|
-
async isObjectAllowedForUserInSpace(object, spaceID) {
|
|
495
|
-
const mission = this.userService.currentMission(spaceID);
|
|
496
|
-
const filters = this.getFiltersForRole(mission.role);
|
|
497
|
-
for (const filter of filters) {
|
|
498
|
-
if (filter === FilterType.LEVEL &&
|
|
499
|
-
Object.prototype.hasOwnProperty.call(object, "level")) {
|
|
500
|
-
const levelFiltered = this.filterObjectsByLevel([object], mission.level);
|
|
501
|
-
if (levelFiltered.length === 0) {
|
|
502
|
-
return false;
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
if (filter === FilterType.ZONE) {
|
|
506
|
-
const zoneFiltered = await this.applyZoneFilterForMissions([mission], [object]);
|
|
507
|
-
if (zoneFiltered.length === 0) {
|
|
508
|
-
return false;
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
return true;
|
|
513
|
-
}
|
|
514
|
-
filterTemplatesForTerm(missions, term) {
|
|
515
|
-
// term present in description
|
|
516
|
-
const byDescription = missions.filter((mis) => mis.description && mis.description.toLowerCase().includes(term));
|
|
517
|
-
// by user lastName which is the name of the visit:
|
|
518
|
-
// metadata: "{\"firstName\":\"\",\"lastName\":\"Visite du 5 Juillet\"}"
|
|
519
|
-
const userProfiles = missions.map((mis) => new ProfileEntity(mis.user));
|
|
520
|
-
const byUserLastname = this.filterUsersForTerm(userProfiles, term);
|
|
521
|
-
const userIds = new Set(byUserLastname.map((user) => user.id));
|
|
522
|
-
const missionsByUser = missions.filter((mis) => userIds.has(mis.userID));
|
|
523
|
-
return filterUniqueArrayByID([...byDescription, ...missionsByUser]);
|
|
524
|
-
}
|
|
525
|
-
async filterObjectsForSweep(objects, objectType, sweep) {
|
|
526
|
-
let filtered = [];
|
|
527
|
-
switch (objectType) {
|
|
528
|
-
case PoiType.EQUIPMENT:
|
|
529
|
-
const pois = await this.poiService.getPoisByMatterportSweepByType(sweep, objectType);
|
|
530
|
-
const equipIDs = new Set(pois.map((poi) => poi.elementID));
|
|
531
|
-
filtered = objects.filter((object) => equipIDs.has(object.id));
|
|
532
|
-
break;
|
|
533
|
-
default:
|
|
534
|
-
break;
|
|
535
|
-
}
|
|
536
|
-
return filtered;
|
|
537
|
-
}
|
|
538
|
-
filterFeaturesByHashtagsAndLocale(currentSpaceMissions, features) {
|
|
539
|
-
const [currentMission] = currentSpaceMissions;
|
|
540
|
-
// filter by locale
|
|
541
|
-
let filteredLocale = [...features];
|
|
542
|
-
if (currentMission.locale) {
|
|
543
|
-
filteredLocale = features.filter((feature) => feature.locale && feature.locale === currentMission.locale);
|
|
544
|
-
}
|
|
545
|
-
// filter by hashtags
|
|
546
|
-
if (currentMission.hashtags && currentMission.hashtags.length > 0) {
|
|
547
|
-
const filteredByHashtags = [];
|
|
548
|
-
for (const feature of filteredLocale) {
|
|
549
|
-
if (!feature.hashtags || feature.hashtags.length === 0) {
|
|
550
|
-
// Feature without hashtag is available for everybody
|
|
551
|
-
filteredByHashtags.push(feature);
|
|
552
|
-
}
|
|
553
|
-
else if (currentMission.hashtags.every((hashtag) => feature.hashtags.includes(hashtag))) {
|
|
554
|
-
filteredByHashtags.push(feature);
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
return filteredByHashtags;
|
|
558
|
-
}
|
|
559
|
-
return filteredLocale;
|
|
560
|
-
}
|
|
561
|
-
filterFeaturesForMissionWithoutZone(features, mission) {
|
|
562
|
-
const finalFeatures = [];
|
|
563
|
-
let levelFiltered = features;
|
|
564
|
-
let zoneFiltered = features;
|
|
565
|
-
let hashtagFiltered = features;
|
|
566
|
-
const filters = this.getFiltersForRole(mission.role);
|
|
567
|
-
for (const filter of filters) {
|
|
568
|
-
if (filter === FilterType.LEVEL) {
|
|
569
|
-
levelFiltered = this.filterObjectsByLevel(features, mission.level);
|
|
570
|
-
}
|
|
571
|
-
// if (filter === FilterType.ZONE) {
|
|
572
|
-
// zoneFiltered = await this.applyZoneFilterForMissions(
|
|
573
|
-
// currentSpaceMissions,
|
|
574
|
-
// features,
|
|
575
|
-
// );
|
|
576
|
-
// }
|
|
577
|
-
if (filter === FilterType.HASHTAG) {
|
|
578
|
-
hashtagFiltered =
|
|
579
|
-
this.filterFeaturesByHashtagsAndLocale([mission], features);
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
for (const feature of levelFiltered) {
|
|
583
|
-
if (hashtagFiltered.includes(feature) &&
|
|
584
|
-
zoneFiltered.includes(feature)) {
|
|
585
|
-
finalFeatures.push(feature);
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
return finalFeatures;
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
FilterService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: FilterService, deps: [{ token: i1.BaseUserService }, { token: i2.ZoneService }, { token: i3.PoiService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
592
|
-
FilterService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: FilterService, providedIn: "root" });
|
|
593
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: FilterService, decorators: [{
|
|
594
|
-
type: Injectable,
|
|
595
|
-
args: [{
|
|
596
|
-
providedIn: "root",
|
|
597
|
-
}]
|
|
598
|
-
}], ctorParameters: function () { return [{ type: i1.BaseUserService }, { type: i2.ZoneService }, { type: i3.PoiService }]; } });
|
|
599
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsdGVyLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtc21hcnRlcnBsYW4tY29yZS9zcmMvbGliL3NlcnZpY2VzL2ZpbHRlci5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLHlDQUF5QztBQUN6QyxxQ0FBcUM7QUFDckMsaUNBQWlDO0FBQ2pDLDJDQUEyQztBQUMzQyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNDLE9BQU8sRUFBRSxPQUFPLEVBQWdCLE1BQU0sTUFBTSxDQUFDO0FBQzdDLE9BQU8sRUFBRSxjQUFjLEVBQUUsMEJBQTBCLEVBQUUseUJBQXlCLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNsSSxPQUFPLEVBT0wsT0FBTyxFQUNQLGFBQWEsRUFDYixVQUFVLEVBT1gsTUFBTSxrQkFBa0IsQ0FBQztBQVkxQixPQUFPLFdBQVcsTUFBTSxnQkFBZ0IsQ0FBQzs7Ozs7QUFSekMsSUFBSyxVQU9KO0FBUEQsV0FBSyxVQUFVO0lBQ1gsK0JBQWlCLENBQUE7SUFDakIsNkJBQWUsQ0FBQTtJQUNmLDJCQUFhLENBQUE7SUFDYiwyQkFBYSxDQUFBO0lBQ2IsNkJBQWUsQ0FBQTtJQUNmLGlDQUFtQixDQUFBO0FBQ3ZCLENBQUMsRUFQSSxVQUFVLEtBQVYsVUFBVSxRQU9kO0FBS0QsTUFBTSxPQUFPLGFBQWE7SUFLdEIsWUFDWSxXQUE0QixFQUM1QixXQUF3QixFQUN4QixVQUFzQjtRQUZ0QixnQkFBVyxHQUFYLFdBQVcsQ0FBaUI7UUFDNUIsZ0JBQVcsR0FBWCxXQUFXLENBQWE7UUFDeEIsZUFBVSxHQUFWLFVBQVUsQ0FBWTtRQVAxQixxQkFBZ0IsR0FBb0IsSUFBSSxPQUFPLEVBQUUsQ0FBQztJQVF2RCxDQUFDO0lBRUoscUJBQXFCLENBQUMsZUFBeUIsRUFBRSxNQUFjO1FBQzNELE9BQU8sZUFBZSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLFFBQVEsS0FBSyxNQUFNLENBQUMsQ0FBQztJQUNwRSxDQUFDO0lBRUQsb0JBQW9CLENBQUMsZUFBc0IsRUFBRSxLQUFrQjtRQUMzRCxNQUFNLGFBQWEsR0FBRyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDNUMsTUFBTSxRQUFRLEdBQUcsZUFBZSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQzVDLGFBQWEsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUNwQyxDQUFDO1FBQ0YsT0FBTyxRQUFRLENBQUM7SUFDcEIsQ0FBQztJQUVELHVCQUF1QixDQUNuQixlQUF5QixFQUN6QixPQUFnQjtRQUVoQixNQUFNLFlBQVksR0FBaUI7WUFDL0IsVUFBVSxDQUFDLE9BQU87WUFDbEIsVUFBVSxDQUFDLEtBQUs7WUFDaEIsVUFBVSxDQUFDLEtBQUs7U0FDbkIsQ0FBQztRQUNGLElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRTtZQUN0QyxJQUFJLE9BQU8sQ0FBQyxJQUFJLEtBQUssVUFBVSxDQUFDLE9BQU8sRUFBRTtnQkFDckMsa0RBQWtEO2dCQUNsRCxNQUFNLGVBQWUsR0FBRyxFQUFFLENBQUM7Z0JBQzNCLEtBQUssTUFBTSxDQUFDLElBQUksZUFBZSxFQUFFO29CQUM3QixJQUFJLENBQUMsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7d0JBQzlCLEtBQUssTUFBTSxVQUFVLElBQUksQ0FBQyxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUU7NEJBQ3hDLElBQUksVUFBVSxDQUFDLFNBQVMsS0FBSyxPQUFPLENBQUMsRUFBRSxFQUFFO2dDQUNyQyxlQUFlLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDOzZCQUMzQjt5QkFDSjtxQkFDSjtpQkFDSjtnQkFDRCxPQUFPLGVBQWUsQ0FBQzthQUMxQjtZQUNELDhEQUE4RDtZQUM5RCxPQUFPLGVBQWUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRTtnQkFDckMsT0FBTyxNQUFNLENBQUMsY0FBYyxLQUFLLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDaEQsQ0FBQyxDQUFDLENBQUM7U0FDTjtRQUNELE9BQU8sZUFBZSxDQUFDO0lBQzNCLENBQUM7SUFFRCxpQkFBaUIsQ0FBQyxJQUFnQjtRQUM5QixRQUFRLElBQUksRUFBRTtZQUNWLEtBQUssVUFBVSxDQUFDLEtBQUs7Z0JBQ2pCLE9BQU8sQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDOUIsS0FBSyxVQUFVLENBQUMsT0FBTztnQkFDbkIsT0FBTyxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQy9DLEtBQUssVUFBVSxDQUFDLEtBQUs7Z0JBQ2pCLE9BQU8sQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUMvQyxLQUFLLFVBQVUsQ0FBQyxPQUFPO2dCQUNuQixPQUFPO29CQUNILFVBQVUsQ0FBQyxJQUFJO29CQUNmLFVBQVUsQ0FBQyxLQUFLO29CQUNoQixVQUFVLENBQUMsTUFBTTtvQkFDakIsVUFBVSxDQUFDLElBQUksRUFBRSxpQ0FBaUM7aUJBQ3JELENBQUM7WUFDTixLQUFLLFVBQVUsQ0FBQyxRQUFRO2dCQUNwQixPQUFPO29CQUNILFVBQVUsQ0FBQyxJQUFJO29CQUNmLFVBQVUsQ0FBQyxNQUFNO29CQUNqQixVQUFVLENBQUMsSUFBSTtvQkFDZixVQUFVLENBQUMsS0FBSztvQkFDaEIsVUFBVSxDQUFDLE9BQU87aUJBQ3JCLENBQUM7WUFDTixLQUFLLFVBQVUsQ0FBQyxPQUFPO2dCQUNuQixPQUFPO29CQUNILFVBQVUsQ0FBQyxJQUFJO29CQUNmLFVBQVUsQ0FBQyxLQUFLO29CQUNoQixVQUFVLENBQUMsTUFBTTtvQkFDakIsVUFBVSxDQUFDLElBQUk7b0JBQ2YsVUFBVSxDQUFDLE9BQU87aUJBQ3JCLENBQUM7WUFDTixLQUFLLFVBQVUsQ0FBQyxjQUFjO2dCQUMxQixPQUFPLENBQUMsVUFBVSxDQUFDLElBQUksRUFBRSxVQUFVLENBQUMsS0FBSyxFQUFFLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUNuRSxLQUFLLFVBQVUsQ0FBQyxZQUFZO2dCQUN4QixPQUFPLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQzlCO2dCQUNJLE9BQU8sQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7U0FDakM7SUFDTCxDQUFDO0lBRUQsS0FBSyxDQUFDLGtDQUFrQyxDQUNwQyxPQUFtQixFQUNuQixPQUFlO1FBRWYsTUFBTSxjQUFjLEdBQWUsRUFBRSxDQUFDO1FBQ3RDLElBQUksV0FBVyxHQUFlLE9BQU8sQ0FBQztRQUN0QyxJQUFJLGFBQWEsR0FBZSxPQUFPLENBQUM7UUFDeEMsSUFBSSxZQUFZLEdBQWUsT0FBTyxDQUFDO1FBQ3ZDLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsZUFBZSxDQUFDO1FBQ2xELElBQUksUUFBUSxFQUFFO1lBQ1YsTUFBTSxvQkFBb0IsR0FBRyxRQUFRLENBQUMsTUFBTSxDQUN4QyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sS0FBSyxPQUFPLENBQy9CLENBQUM7WUFDRixJQUFJLG9CQUFvQixDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7Z0JBQ2pDLEtBQUssTUFBTSxHQUFHLElBQUksYUFBYSxFQUFFO29CQUM3QixJQUNJLFdBQVcsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDO3dCQUN6QixZQUFZLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUM1Qjt3QkFDRSxjQUFjLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO3FCQUM1QjtpQkFDSjthQUNKO1NBQ0o7UUFDRCxPQUFPLGNBQWMsQ0FBQztJQUMxQixDQUFDO0lBRUQsS0FBSyxDQUFDLGtDQUFrQyxDQUNwQyxPQUFpQixFQUNqQixPQUFlO1FBRWYsTUFBTSxZQUFZLEdBQWEsRUFBRSxDQUFDO1FBQ2xDLElBQUksV0FBVyxHQUFhLE9BQU8sQ0FBQztRQUNwQyxJQUFJLFlBQVksR0FBYSxPQUFPLENBQUM7UUFDckMsSUFBSSxhQUFhLEdBQWEsT0FBTyxDQUFDO1FBQ3RDLElBQUksWUFBWSxHQUFhLE9BQU8sQ0FBQztRQUNyQyxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLGVBQWUsQ0FBQztRQUNsRCxJQUFJLFFBQVEsRUFBRTtZQUNWLE1BQU0sb0JBQW9CLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FDeEMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLEtBQUssT0FBTyxDQUMvQixDQUFDO1lBQ0YsSUFBSSxvQkFBb0IsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO2dCQUNqQyxNQUFNLFlBQVksR0FDZCwwQkFBMEIsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO2dCQUNyRCxNQUFNLFdBQVcsR0FDYix5QkFBeUIsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO2dCQUNwRCxnRkFBZ0Y7Z0JBRWhGLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLENBQUMsQ0FBQztnQkFDcEQsS0FBSyxNQUFNLE1BQU0sSUFBSSxPQUFPLEVBQUU7b0JBQzFCLElBQUksTUFBTSxLQUFLLFVBQVUsQ0FBQyxNQUFNLEVBQUU7d0JBQzlCLElBQUksT0FBTyxHQUFhLEVBQUUsQ0FBQzt3QkFDM0IsS0FBSyxNQUFNLENBQUMsSUFBSSxvQkFBb0IsRUFBRTs0QkFDbEMsSUFBSSxDQUFDLENBQUMsT0FBTyxFQUFFO2dDQUNYLE9BQU8sR0FBRyxDQUFDLEdBQUcsT0FBTyxFQUFFLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDOzZCQUN4Qzt5QkFDSjt3QkFDRCxJQUFJLGtCQUFrQixHQUFHLEVBQUUsQ0FBQzt3QkFDNUIsS0FBSyxNQUFNLENBQUMsSUFBSSxPQUFPLEVBQUU7NEJBQ3JCLE1BQU0sa0JBQWtCLEdBQ3BCLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUM7NEJBQzNDLGtCQUFrQixHQUFHO2dDQUNqQixHQUFHLGtCQUFrQjtnQ0FDckIsR0FBRyxrQkFBa0I7NkJBQ3hCLENBQUM7eUJBQ0w7d0JBQ0QsV0FBVyxHQUFHLGtCQUFrQixDQUFDO3FCQUNwQztvQkFDRCxJQUFJLE1BQU0sS0FBSyxVQUFVLENBQUMsSUFBSSxFQUFFO3dCQUM1QixNQUFNLGtCQUFrQixHQUFHLG9CQUFvQixDQUFDLElBQUksQ0FDaEQsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssV0FBVyxDQUNoQyxDQUFDO3dCQUNGLFlBQVksR0FBRyxJQUFJLENBQUMsdUJBQXVCLENBQ3ZDLE9BQU8sRUFDUCxrQkFBa0IsQ0FDckIsQ0FBQztxQkFDTDtvQkFFRCxJQUFJLE1BQU0sS0FBSyxVQUFVLENBQUMsS0FBSyxFQUFFO3dCQUM3QixhQUFhLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixDQUNyQyxPQUFPLEVBQ1AsWUFBWSxDQUNmLENBQUM7cUJBQ0w7b0JBRUQsSUFBSSxNQUFNLEtBQUssVUFBVSxDQUFDLElBQUksRUFBRTt3QkFDNUIsWUFBWSxHQUFHLE1BQU0sSUFBSSxDQUFDLDBCQUEwQixDQUNoRCxvQkFBb0IsRUFDcEIsT0FBTyxDQUNWLENBQUM7cUJBQ0w7aUJBQ0o7Z0JBQ0QsbURBQW1EO2dCQUNuRCw0QkFBNEI7Z0JBQzVCLDZCQUE2QjtnQkFDN0IsOEJBQThCO2dCQUM5Qiw2QkFBNkI7Z0JBQzdCLEtBQUssTUFBTSxHQUFHLElBQUksYUFBYSxFQUFFO29CQUM3QixJQUNJLFdBQVcsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDO3dCQUN6QixZQUFZLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQzt3QkFDMUIsWUFBWSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFDNUI7d0JBQ0UsWUFBWSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztxQkFDMUI7aUJBQ0o7YUFDSjtTQUNKO1FBQ0QsNkJBQTZCO1FBQzdCLE9BQU8sWUFBWSxDQUFDO0lBQ3hCLENBQUM7SUFFRCwyQkFBMkIsQ0FDdkIsSUFBMkIsRUFDM0IsS0FBNEIsRUFDNUIsUUFBcUI7UUFFckIsTUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQ2pFLE9BQU8sQ0FBQyxDQUFDO0lBQ2IsQ0FBQztJQUVELGlCQUFpQixDQUFDLFNBQXdCO1FBQ3RDLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxTQUFTLENBQUM7UUFDbkMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUMxQyxDQUFDO0lBRUQseUJBQXlCLENBQUMsT0FBYyxFQUFFLFNBQWlCO1FBQ3ZELE9BQU8sT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFO1lBQzdCLE1BQU0sYUFBYSxHQUFHLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUNqRCxPQUFPLENBQ0gsYUFBYSxJQUFJLFNBQVMsQ0FBQyxDQUFDLENBQUMsSUFBSSxhQUFhLElBQUksU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUNqRSxDQUFDO1FBQ04sQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBRUQsOEJBQThCLENBQzFCLFlBQTJCLEVBQzNCLFNBQWlCO1FBRWpCLE9BQU8sWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFO1lBQ25DLE1BQU0sYUFBYSxHQUFHLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDMUQsT0FBTyxDQUNILGFBQWEsSUFBSSxTQUFTLENBQUMsQ0FBQyxDQUFDLElBQUksYUFBYSxJQUFJLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FDakUsQ0FBQztRQUNOLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUVELEtBQUssQ0FBQyxvQkFBb0IsQ0FDdEIsT0FBYyxFQUFFLDBCQUEwQjtJQUMxQyxTQUFpQixJQUFJLEVBQ3JCLE9BQWEsSUFBSTtRQUVqQixNQUFNLGVBQWUsR0FBRyxFQUFFLENBQUM7UUFDM0IsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUNiLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQ3pCLE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQztZQUNoQyxJQUFJLEdBQUcsSUFBSSxJQUFJLEVBQUU7Z0JBQ2IsSUFBSSxJQUFJLENBQUMsUUFBUSxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFO29CQUNoRSxJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxJQUFJLElBQUksQ0FBQyxLQUFLLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLEtBQUssT0FBTyxFQUFHO3dCQUNqRixnQ0FBZ0M7d0JBQ2hDLGVBQWUsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7cUJBQ2hDO29CQUNELElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsRUFBRTt3QkFDcEMsZUFBZSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztxQkFDaEM7aUJBQ0o7YUFDSjtZQUNELElBQUksR0FBRyxJQUFJLENBQUMsSUFBSSxJQUFJLE1BQU0sRUFBRTtnQkFDeEIsTUFBTSxLQUFLLEdBQUcsTUFBTSxJQUFJLENBQUMsV0FBVyxDQUFDLGlCQUFpQixDQUNsRCxNQUFNLENBQ1QsQ0FBQztnQkFDRixJQUNJLEtBQUs7b0JBQ0wsS0FBSyxDQUFDLElBQUksQ0FDTixDQUFDLEtBQUssRUFBRSxFQUFFLENBQ04sS0FBSyxDQUFDLEVBQUUsS0FBSyxNQUFNO3dCQUNuQixLQUFLLENBQUMsUUFBUSxLQUFLLE1BQU0sQ0FDaEMsRUFDSDtvQkFDRSxlQUFlLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO2lCQUNoQzthQUNKO1FBQ0wsQ0FBQyxDQUFDLENBQ0wsQ0FBQztRQUNGLE9BQU8sZUFBZSxDQUFDO0lBQzNCLENBQUM7SUFFRCw0QkFBNEIsQ0FDeEIsVUFBdUIsRUFDdkIsWUFBc0I7UUFFdEIsSUFBSSxRQUFRLEdBQUcsRUFBRSxDQUFDO1FBQ2xCLE1BQU0sZ0JBQWdCLEdBQUcsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQ3JELFlBQVksQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUNwQyxDQUFDO1FBQ0YsUUFBUSxHQUFHLENBQUMsR0FBRyxRQUFRLEVBQUUsR0FBRyxnQkFBZ0IsQ0FBQyxDQUFDO1FBQzlDLE1BQU0sc0JBQXNCLEdBQUcsVUFBVSxDQUFDLE1BQU0sQ0FDNUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUNOLEtBQUssQ0FBQyxNQUFNO1lBQ1osS0FBSyxDQUFDLE1BQU0sQ0FBQyxRQUFRO1lBQ3JCLFlBQVksQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FDbkQsQ0FBQztRQUNGLFFBQVEsR0FBRyxDQUFDLEdBQUcsUUFBUSxFQUFFLEdBQUcsc0JBQXNCLENBQUMsQ0FBQztRQUNwRCxPQUFPLHFCQUFxQixDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQzNDLENBQUM7SUFHSCx1QkFBdUI7SUFDdkIsK0JBQStCO0lBQy9CLDJCQUEyQjtJQUMzQiw0QkFBNEI7SUFDNUIsa0JBQWtCO0lBQ2xCLHVCQUF1QjtJQUN2Qix5REFBeUQ7SUFDekQsNkNBQTZDO0lBQzdDLE9BQU87SUFDUCxtREFBbUQ7SUFDbkQscURBQXFEO0lBQ3JELGVBQWU7SUFDZixzQkFBc0I7SUFDdEIsK0JBQStCO0lBQy9CLG9EQUFvRDtJQUNwRCxPQUFPO0lBQ1AseURBQXlEO0lBQ3pELDRDQUE0QztJQUM1QyxJQUFJO0lBRUosdUJBQXVCLENBQUMsTUFBbUIsRUFBRSxJQUFZO1FBQ25ELGlCQUFpQjtRQUNqQixJQUFJLFFBQVEsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUU7WUFDaEMsSUFBSSxFQUFFLENBQUMsTUFBTSxJQUFJLEVBQUUsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFO2dCQUM3QixNQUFNLGdCQUFnQixHQUFHLEVBQUUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO2dCQUN0RCxNQUFNLEdBQUcsR0FBRyxXQUFXLENBQUMsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLENBQUM7Z0JBQ2hELE9BQU8sR0FBRyxJQUFJLENBQUMsSUFBSSxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7YUFDdEQ7WUFDRCxPQUFPLEtBQUssQ0FBQztRQUNqQixDQUFDLENBQUMsQ0FBQztRQUNILE1BQU0sY0FBYyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRTtZQUN4QyxJQUFJLEVBQUUsQ0FBQyxNQUFNLElBQUksRUFBRSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEVBQUU7Z0JBQ2pDLE1BQU0sZ0JBQWdCLEdBQUcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO2dCQUM3RCxNQUFNLEdBQUcsR0FBRyxXQUFXLENBQUMsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLENBQUM7Z0JBQ2hELE9BQU8sR0FBRyxJQUFJLENBQUMsSUFBSSxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7YUFDdEQ7WUFDRCxPQUFPLEtBQUssQ0FBQztRQUNqQixDQUFDLENBQUMsQ0FBQztRQUNILFFBQVEsR0FBRyxDQUFDLEdBQUcsUUFBUSxFQUFFLEdBQUcsY0FBYyxDQUFDLENBQUM7UUFDNUMsY0FBYztRQUNkLElBQUksTUFBTSxHQUFHLEVBQUUsQ0FBQztRQUNoQixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQztRQUNsRSxLQUFLLE1BQU0sRUFBRSxJQUFJLE1BQU0sRUFBRTtZQUNyQixNQUFNLEtBQUssR0FBRyxFQUFFLENBQUMsSUFBSTtpQkFDaEIsV0FBVyxFQUFFO2lCQUNiLEtBQUssQ0FBQyxHQUFHLENBQUM7aUJBQ1YsTUFBTSxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQ3pDLE1BQU0sT0FBTyxHQUFHLEVBQUUsQ0FBQztZQUNuQixLQUFLLE1BQU0sS0FBSyxJQUFJLEtBQUssRUFBRTtnQkFDdkIsS0FBSyxNQUFNLElBQUksSUFBSSxLQUFLLEVBQUU7b0JBQ3RCLElBQUksV0FBVyxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUU7d0JBQy9CLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7d0JBQ25CLE1BQU07cUJBQ1Q7aUJBQ0o7YUFDSjtZQUNELElBQUksT0FBTyxDQUFDLE1BQU0sS0FBSyxLQUFLLENBQUMsTUFBTSxFQUFFO2dCQUNqQyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO2FBQ25CO1NBQ0o7UUFFRCxNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FDdEMsRUFBRSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQ3ZDLENBQUM7UUFDRixNQUFNLEdBQUcsQ0FBQyxHQUFHLE1BQU0sRUFBRSxHQUFHLFlBQVksQ0FBQyxDQUFDO1FBQ3RDLG1CQUFtQjtRQUNuQixNQUFNLGNBQWMsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUNoQyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLFlBQVksSUFBSSxFQUFFLENBQUMsWUFBWSxDQUFDLFdBQVcsRUFBRSxLQUFLLElBQUksQ0FDcEUsQ0FBQztRQUNGLE1BQU0sTUFBTSxHQUFHLENBQUMsR0FBRyxRQUFRLEVBQUUsR0FBRyxNQUFNLEVBQUUsR0FBRyxjQUFjLENBQUMsQ0FBQztRQUMzRCxPQUFPLHFCQUFxQixDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3pDLENBQUM7SUFFRCxvQkFBb0IsQ0FBQyxPQUFpQixFQUFFLElBQVk7UUFDaEQsdUNBQXVDO1FBQ3ZDLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDekQsZUFBZTtRQUNmLE1BQU0sV0FBVyxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQzlCLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FDUCxNQUFNLENBQUMsVUFBVTtZQUNqQixJQUFJLENBQUMsdUJBQXVCLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsQ0FBQyxNQUFNO2dCQUN4RCxDQUFDLENBQ1osQ0FBQztRQUNGLE9BQU8scUJBQXFCLENBQUMsQ0FBQyxHQUFHLE9BQU8sRUFBRSxHQUFHLFdBQVcsQ0FBQyxDQUFDLENBQUM7SUFDL0QsQ0FBQztJQUVELHNCQUFzQixDQUFDLFNBQWtCLEVBQUUsSUFBWTtRQUNuRCxVQUFVO1FBQ1YsTUFBTSxNQUFNLEdBQUcsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQ3BDLEdBQUcsQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUN4QyxDQUFDO1FBQ0YsYUFBYTtRQUNiLE1BQU0sU0FBUyxHQUFHLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUN2QyxHQUFHLENBQUMsU0FBUyxDQUFDLFdBQVcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FDN0MsQ0FBQztRQUNGLE9BQU8scUJBQXFCLENBQUMsQ0FBQyxHQUFHLE1BQU0sRUFBRSxHQUFHLFNBQVMsQ0FBQyxDQUFDLENBQUM7SUFDNUQsQ0FBQztJQUVELDBCQUEwQixDQUN0QixJQUFvQixFQUNwQixJQUFZO1FBRVosTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFO1lBQy9CLE1BQU0sS0FBSyxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ2hELE9BQU8sQ0FDSCxLQUFLLENBQUMsSUFBSSxDQUNOLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsSUFBSSxXQUFXLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FDNUQsSUFBSSxHQUFHLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FDN0MsQ0FBQztRQUNOLENBQUMsQ0FBQyxDQUFDO1FBQ0gsT0FBTyxNQUFNLENBQUM7SUFDbEIsQ0FBQztJQUVELGtCQUFrQixDQUFDLEtBQXNCLEVBQUUsSUFBWTtRQUNuRCxNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUU7WUFDakMsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDeEQsT0FBTyxDQUNILEtBQUssQ0FBQyxJQUFJLENBQ04sQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLFdBQVcsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUM1RCxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsV0FBVyxFQUFFLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUNyRCxDQUFDO1FBQ04sQ0FBQyxDQUFDLENBQUM7UUFDSCxPQUFPLE1BQU0sQ0FBQztJQUNsQixDQUFDO0lBRUQsS0FBSyxDQUFDLG1DQUFtQyxDQUNyQyxRQUFtQixFQUNuQixPQUFlO1FBRWYsTUFBTSxhQUFhLEdBQWMsRUFBRSxDQUFDO1FBQ3BDLElBQUksYUFBYSxHQUFjLFFBQVEsQ0FBQztRQUN4QyxJQUFJLFlBQVksR0FBYyxRQUFRLENBQUM7UUFDdkMsSUFBSSxlQUFlLEdBQWMsUUFBUSxDQUFDO1FBQzFDLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsZUFBZSxDQUFDO1FBQ2xELElBQUksUUFBUSxFQUFFO1lBQ1YsTUFBTSxvQkFBb0IsR0FBRyxRQUFRLENBQUMsTUFBTSxDQUN4QyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sS0FBSyxPQUFPLENBQy9CLENBQUM7WUFDRixJQUFJLG9CQUFvQixDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7Z0JBQ2pDLE1BQU0sWUFBWSxHQUNkLDBCQUEwQixDQUFDLG9CQUFvQixDQUFDLENBQUM7Z0JBQ3JELE1BQU0sV0FBVyxHQUNiLHlCQUF5QixDQUFDLG9CQUFvQixDQUFDLENBQUM7Z0JBRXBELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLENBQUMsQ0FBQztnQkFDcEQsS0FBSyxNQUFNLE1BQU0sSUFBSSxPQUFPLEVBQUU7b0JBQzFCLElBQUksTUFBTSxLQUFLLFVBQVUsQ0FBQyxLQUFLLEVBQUU7d0JBQzdCLGFBQWEsR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQ3JDLFFBQVEsRUFDUixZQUFZLENBQ2YsQ0FBQztxQkFDTDtvQkFDRCxJQUFJLE1BQU0sS0FBSyxVQUFVLENBQUMsSUFBSSxFQUFFO3dCQUM1QixZQUFZLEdBQUcsTUFBTSxJQUFJLENBQUMsMEJBQTBCLENBQ2hELG9CQUFvQixFQUNwQixRQUFRLENBQ1gsQ0FBQztxQkFDTDtvQkFDRCxJQUFJLE1BQU0sS0FBSyxVQUFVLENBQUMsT0FBTyxFQUFFO3dCQUMvQixlQUFlOzRCQUNYLElBQUksQ0FBQyxpQ0FBaUMsQ0FDbEMsb0JBQW9CLEVBQ3BCLFFBQVEsQ0FDWCxDQUFDO3FCQUNUO2lCQUNKO2dCQUNELEtBQUssTUFBTSxPQUFPLElBQUksYUFBYSxFQUFFO29CQUNqQyxJQUNJLGVBQWUsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO3dCQUNqQyxZQUFZLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxFQUNoQzt3QkFDRSxhQUFhLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO3FCQUMvQjtpQkFDSjthQUNKO1NBQ0o7UUFDRCxPQUFPLGFBQWEsQ0FBQztJQUN6QixDQUFDO0lBRUQscUJBQXFCLENBQUMsUUFBbUIsRUFBRSxJQUFZO1FBQ25ELHVCQUF1QjtRQUN2QixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQzFELGNBQWM7UUFDZCxNQUFNLFNBQVMsR0FBRyxRQUFRLENBQUMsTUFBTSxDQUM3QixDQUFDLE9BQU8sRUFBRSxFQUFFLENBQ1IsSUFBSSxDQUFDLG9CQUFvQixDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDLE1BQU07WUFDOUQsQ0FBQyxDQUNSLENBQUM7UUFDRixPQUFPLHFCQUFxQixDQUFDLENBQUMsR0FBRyxPQUFPLEVBQUUsR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDO0lBQzdELENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsb0JBQW9CLENBQUMsT0FBYyxFQUFFLElBQVk7UUFDN0MsdUJBQXVCO1FBQ3ZCLE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRTtZQUN2QyxNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUNyRCxPQUFPLENBQ0gsS0FBSyxDQUFDLElBQUksQ0FDTixDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksV0FBVyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQzVELElBQUksT0FBTyxDQUFDLEtBQUssQ0FBQyxXQUFXLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQ2xELENBQUM7UUFDTixDQUFDLENBQUMsQ0FBQztRQUNILDhCQUE4QjtRQUM5QixNQUFNLGFBQWEsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUNoQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQ1IsT0FBTyxDQUFDLFdBQVc7WUFDbkIsT0FBTyxDQUFDLFdBQVcsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQ3ZELENBQUM7UUFDRixPQUFPLHFCQUFxQixDQUFDLENBQUMsR0FBRyxPQUFPLEVBQUUsR0FBRyxhQUFhLENBQUMsQ0FBQyxDQUFDO0lBQ2pFLENBQUM7SUFFRCx3Q0FBd0MsQ0FDcEMsUUFBZSxFQUNmLFNBQWlCO1FBRWpCLE9BQU8sUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFO1lBQy9CLE1BQU0sYUFBYSxHQUFHLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUN0RCxPQUFPLENBQ0gsYUFBYSxJQUFJLFNBQVMsQ0FBQyxDQUFDLENBQUMsSUFBSSxhQUFhLElBQUksU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUNqRSxDQUFDO1FBQ04sQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBRUQsS0FBSyxDQUFDLDBCQUEwQixDQUM1QixvQkFBK0IsRUFDL0IsT0FBYztRQUVkLE1BQU0sWUFBWSxHQUFHLEVBQUUsQ0FBQztRQUN4QixLQUFLLE1BQU0sT0FBTyxJQUFJLG9CQUFvQixFQUFFO1lBQ3hDLElBQUksT0FBTyxDQUFDLE1BQU0sRUFBRTtnQkFDaEIsWUFBWSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7YUFDckM7U0FDSjtRQUNELElBQUksWUFBWSxDQUFDLE1BQU0sS0FBSyxvQkFBb0IsQ0FBQyxNQUFNLEVBQUU7WUFDckQsSUFBSSxlQUFlLEdBQUcsRUFBRSxDQUFDO1lBQ3pCLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FDYixZQUFZLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxNQUFNLEVBQUUsRUFBRTtnQkFDOUIsTUFBTSxtQkFBbUIsR0FBRyxNQUFNLElBQUksQ0FBQyxvQkFBb0IsQ0FDdkQsT0FBTyxFQUNQLE1BQU0sQ0FDVCxDQUFDO2dCQUNGLGVBQWUsR0FBRztvQkFDZCxHQUFHLGVBQWU7b0JBQ2xCLEdBQUcsbUJBQW1CO2lCQUN6QixDQUFDO1lBQ04sQ0FBQyxDQUFDLENBQ0wsQ0FBQztZQUNGLE9BQU8scUJBQXFCLENBQUMsZUFBZSxDQUFDLENBQUM7U0FDakQ7UUFDRCxPQUFPLE9BQU8sQ0FBQztJQUNuQixDQUFDO0lBRUQsS0FBSyxDQUFDLHFDQUFxQyxDQUN2QyxPQUFlLEVBQ2YsTUFBbUI7UUFFbkIsTUFBTSxXQUFXLEdBQWdCLEVBQUUsQ0FBQztRQUNwQyxJQUFJLFdBQVcsR0FBZ0IsTUFBTSxDQUFDO1FBQ3RDLE1BQU0sWUFBWSxHQUFnQixNQUFNLENBQUM7UUFDekMsTUFBTSxhQUFhLEdBQWdCLE1BQU0sQ0FBQztRQUMxQyxJQUFJLFlBQVksR0FBZ0IsTUFBTSxDQUFDO1FBQ3ZDLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsZUFBZSxDQUFDO1FBQ2xELElBQUksUUFBUSxFQUFFO1lBQ1YsTUFBTSxvQkFBb0IsR0FBRyxRQUFRLENBQUMsTUFBTSxDQUN4QyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sS0FBSyxPQUFPLENBQy9CLENBQUM7WUFDRixJQUFJLG9CQUFvQixDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7Z0JBQ2pDLE1BQU0sWUFBWSxHQUNkLDBCQUEwQixDQUFDLG9CQUFvQixDQUFDLENBQUM7Z0JBQ3JELE1BQU0sV0FBVyxHQUNiLHlCQUF5QixDQUFDLG9CQUFvQixDQUFDLENBQUM7Z0JBQ3BELGdGQUFnRjtnQkFFaEYsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFdBQVcsQ0FBQyxDQUFDO2dCQUNwRCxLQUFLLE1BQU0sTUFBTSxJQUFJLE9BQU8sRUFBRTtvQkFDMUIsSUFBSSxNQUFNLEtBQUssVUFBVSxDQUFDLE1BQU0sRUFBRTt3QkFDOUIsSUFBSSxPQUFPLEdBQWEsRUFBRSxDQUFDO3dCQUMzQixLQUFLLE1BQU0sQ0FBQyxJQUFJLG9CQUFvQixFQUFFOzRCQUN0QyxJQUFJLENBQUMsQ0FBQyxPQUFPLEVBQUU7Z0NBQ1AsT0FBTyxHQUFHLENBQUMsR0FBRyxPQUFPLEVBQUUsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUM7NkJBQ3hDO3lCQUNKO3dCQUVELElBQUksa0JBQWtCLEdBQUcsRUFBRSxDQUFDO3dCQUU1QixNQUFNLGtCQUFrQixHQUNwQixJQUFJLENBQUMsNEJBQTRCLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDO3dCQUN2RCxrQkFBa0IsR0FBRzs0QkFDakIsR0FBRyxrQkFBa0I7NEJBQ3JCLEdBQUcsa0JBQWtCO3lCQUN4QixDQUFDO3dCQUNGLFdBQVcsR0FBRyxrQkFBa0IsQ0FBQztxQkFDcEM7b0JBQ0QsSUFBSSxNQUFNLEtBQUssVUFBVSxDQUFDLElBQUksRUFBRTt3QkFDNUIsd0RBQXdEO3dCQUN4RCxxQ0FBcUM7d0JBQ3JDLEtBQUs7d0JBQ0wsT0FBTztxQkFDVjtvQkFFRCxJQUFJLE1BQU0sS0FBSyxVQUFVLENBQUMsS0FBSyxFQUFFO3dCQUM3QixzQ0FBc0M7cUJBQ3pDO29CQUVELElBQUksTUFBTSxLQUFLLFVBQVUsQ0FBQyxJQUFJLEVBQUU7d0JBQzVCLFlBQVksR0FBRyxNQUFNLElBQUksQ0FBQywwQkFBMEIsQ0FDaEQsb0JBQW9CLEVBQ3BCLE1BQU0sQ0FDVCxDQUFDO3FCQUNMO2lCQUNKO2dCQUNELEtBQUssTUFBTSxHQUFHLElBQUksYUFBYSxFQUFFO29CQUM3QixJQUNJLFdBQVcsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDO3dCQUN6QixZQUFZLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQzt3QkFDMUIsWUFBWSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFDNUI7d0JBQ0UsV0FBVyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztxQkFDekI7aUJBQ0o7YUFDSjtTQUNKO1FBQ0QsT0FBTyxXQUFXLENBQUM7SUFDdkIsQ0FBQztJQUVELEtBQUssQ0FBQyx1Q0FBdUMsQ0FDekMsT0FBZSxFQUNmLFFBQW1CO1FBRW5CLElBQUksaUJBQWlCLEdBQWMsRUFBRSxDQUFDO1FBQ3RDLElBQUksWUFBWSxHQUFjLFFBQVEsQ0FBQztRQUN2QyxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLGVBQWUsQ0FBQztRQUNsRCxJQUFJLFFBQVEsRUFBRTtZQUNWLE1BQU0sb0JBQW9CLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FDeEMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLEtBQUssT0FBTyxDQUMvQixDQUFDO1lBQ0YsSUFBSSxvQkFBb0IsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO2dCQUNqQyxNQUFNLFdBQVcsR0FDYix5QkFBeUIsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO2dCQUVwRCxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsV0FBVyxDQUFDLENBQUM7Z0JBQ3BELEtBQUssTUFBTSxNQUFNLElBQUksT0FBTyxFQUFFO29CQUMxQixJQUFJLE1BQU0sS0FBSyxVQUFVLENBQUMsSUFBSSxFQUFFO3dCQUM1QixZQUFZLEdBQUcsTUFBTSxJQUFJLENBQUMsMEJBQTBCLENBQ2hELG9CQUFvQixFQUNwQixRQUFRLENBQ1gsQ0FBQztxQkFDTDtpQkFDSjtnQkFDRCxpQkFBaUIsR0FBRyxZQUFZLENBQUM7YUFDcEM7U0FDSjtRQUNELE9BQU8saUJBQWlCLENBQUM7SUFDN0IsQ0FBQztJQUVELEtBQUssQ0FBQyw2QkFBNkIsQ0FDL0IsTUFBYyxFQUNkLE9BQWU7UUFFZixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUN6RCxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3JELEtBQUssTUFBTSxNQUFNLElBQUksT0FBTyxFQUFFO1lBQzFCLElBQ0ksTUFBTSxLQUFLLFVBQVUsQ0FBQyxLQUFLO2dCQUMzQixNQUFNLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxFQUN2RDtnQkFDRSxNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQzNDLENBQUMsTUFBTSxDQUFDLEVBQ1IsT0FBTyxDQUFDLEtBQUssQ0FDaEIsQ0FBQztnQkFDRixJQUFJLGFBQWEsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO29CQUM1QixPQUFPLEtBQUssQ0FBQztpQkFDaEI7YUFDSjtZQUNELElBQUksTUFBTSxLQUFLLFVBQVUsQ0FBQyxJQUFJLEVBQUU7Z0JBQzVCLE1BQU0sWUFBWSxHQUFHLE1BQU0sSUFBSSxDQUFDLDBCQUEwQixDQUN0RCxDQUFDLE9BQU8sQ0FBQyxFQUNULENBQUMsTUFBTSxDQUFDLENBQ1gsQ0FBQztnQkFDRixJQUFJLFlBQVksQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO29CQUMzQixPQUFPLEtBQUssQ0FBQztpQkFDaEI7YUFDSjtTQUNKO1FBQ0QsT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztJQUVELHNCQUFzQixDQUFDLFFBQW1CLEVBQUUsSUFBWTtRQUNwRCw4QkFBOEI7UUFDOUIsTUFBTSxhQUFhLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FDakMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUNKLEdBQUcsQ0FBQyxXQUFXLElBQUksR0FBRyxDQUFDLFdBQVcsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQ3RFLENBQUM7UUFDRixtREFBbUQ7UUFDbkQsd0VBQXdFO1FBQ3hFLE1BQU0sWUFBWSxHQUFHLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLElBQUksYUFBYSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQ3hFLE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxZQUFZLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDbkUsTUFBTSxPQUFPLEdBQUcsSUFBSSxHQUFHLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDL0QsTUFBTSxjQUFjLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQzNDLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUMxQixDQUFDO1FBQ0YsT0FBTyxxQkFBcUIsQ0FBQyxDQUFDLEdBQUcsYUFBYSxFQUFFLEdBQUcsY0FBYyxDQUFDLENBQUMsQ0FBQztJQUN4RSxDQUFDO0lBRUQsS0FBSyxDQUFDLHFCQUFxQixDQUN2QixPQUFjLEVBQ2QsVUFBbUIsRUFDbkIsS0FBYTtRQUViLElBQUksUUFBUSxHQUFHLEVBQUUsQ0FBQztRQUNsQixRQUFRLFVBQVUsRUFBRTtZQUNoQixLQUFLLE9BQU8sQ0FBQyxTQUFTO2dCQUNsQixNQUFNLElBQUksR0FDTixNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsOEJBQThCLENBQ2hELEtBQUssRUFDTCxVQUFVLENBQ2IsQ0FBQztnQkFDTixNQUFNLFFBQVEsR0FBRyxJQUFJLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztnQkFDM0QsUUFBUSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7Z0JBQy9ELE1BQU07WUFDVjtnQkFDSSxNQUFNO1NBQ2I7UUFDRCxPQUFPLFFBQVEsQ0FBQztJQUNwQixDQUFDO0lBRUQsaUNBQWlDLENBQzdCLG9CQUErQixFQUMvQixRQUFtQjtRQUVuQixNQUFNLENBQUMsY0FBYyxDQUFDLEdBQUcsb0JBQW9CLENBQUM7UUFDOUMsbUJBQW1CO1FBQ25CLElBQUksY0FBYyxHQUFHLENBQUMsR0FBRyxRQUFRLENBQUMsQ0FBQztRQUNuQyxJQUFJLGNBQWMsQ0FBQyxNQUFNLEVBQUU7WUFDdkIsY0FBYyxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQzVCLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FDUixPQUFPLENBQUMsTUFBTSxJQUFJLE9BQU8sQ0FBQyxNQUFNLEtBQUssY0FBYyxDQUFDLE1BQU0sQ0FDakUsQ0FBQztTQUNMO1FBQ0QscUJBQXFCO1FBQ3JCLElBQUksY0FBYyxDQUFDLFFBQVEsSUFBSSxjQUFjLENBQUMsUUFBUSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7WUFDL0QsTUFBTSxrQkFBa0IsR0FBRyxFQUFFLENBQUM7WUFDOUIsS0FBSyxNQUFNLE9BQU8sSUFBSSxjQUFjLEVBQUU7Z0JBQ2xDLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtvQkFDcEQscURBQXFEO29CQUNyRCxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7aUJBQ3BDO3FCQUFNLElBQ0gsY0FBYyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUN0QyxPQUFPLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FDckMsRUFDSDtvQkFDRSxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7aUJBQ3BDO2FBQ0o7WUFDRCxPQUFPLGtCQUFrQixDQUFDO1NBQzdCO1FBQ0QsT0FBTyxjQUFjLENBQUM7SUFDMUIsQ0FBQztJQUVELG1DQUFtQyxDQUMvQixRQUFtQixFQUNuQixPQUFnQjtRQUVoQixNQUFNLGFBQWEsR0FBYyxFQUFFLENBQUM7UUFDcEMsSUFBSSxhQUFhLEdBQWMsUUFBUSxDQUFDO1FBQ3hDLElBQUksWUFBWSxHQUFjLFFBQVEsQ0FBQztRQUN2QyxJQUFJLGVBQWUsR0FBYyxRQUFRLENBQUM7UUFFMUMsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNyRCxLQUFLLE1BQU0sTUFBTSxJQUFJLE9BQU8sRUFBRTtZQUNsQixJQUFJLE1BQU0sS0FBSyxVQUFVLENBQUMsS0FBSyxFQUFFO2dCQUM3QixhQUFhLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixDQUNyQyxRQUFRLEVBQ1IsT0FBTyxDQUFDLEtBQUssQ0FDaEIsQ0FBQzthQUNMO1lBQ0Qsb0NBQW9DO1lBQ3BDLDREQUE0RDtZQUM1RCxnQ0FBZ0M7WUFDaEMsb0JBQW9CO1lBQ3BCLFNBQVM7WUFDVCxJQUFJO1lBQ0osSUFBSSxNQUFNLEtBQUssVUFBVSxDQUFDLE9BQU8sRUFBRTtnQkFDL0IsZUFBZTtvQkFDWCxJQUFJLENBQUMsaUNBQWlDLENBQ2xDLENBQUMsT0FBTyxDQUFDLEVBQ1QsUUFBUSxDQUNYLENBQUM7YUFDVDtTQUNKO1FBQ1QsS0FBSyxNQUFNLE9BQU8sSUFBSSxhQUFhLEVBQUU7WUFDekIsSUFDSSxlQUFlLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQztnQkFDakMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFDaEM7Z0JBQ0UsYUFBYSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQzthQUMvQjtTQUNaO1FBQ0QsT0FBTyxhQUFhLENBQUM7SUFDekIsQ0FBQzs7MEdBcnlCUSxhQUFhOzhHQUFiLGFBQWEsY0FGVixNQUFNOzJGQUVULGFBQWE7a0JBSHpCLFVBQVU7bUJBQUM7b0JBQ1IsVUFBVSxFQUFFLE1BQU07aUJBQ3JCIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgbm8tY2FzZS1kZWNsYXJhdGlvbnMgKi9cclxuLyogZXNsaW50LWRpc2FibGUgbm8tYXdhaXQtaW4tbG9vcCAqL1xyXG4vKiBlc2xpbnQtZGlzYWJsZSBndWFyZC1mb3ItaW4gKi9cclxuLyogZXNsaW50LWRpc2FibGUgY2xhc3MtbWV0aG9kcy11c2UtdGhpcyAqL1xyXG5pbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcclxuaW1wb3J0IHsgU3ViamVjdCwgU3Vic2NyaXB0aW9uIH0gZnJvbSBcInJ4anNcIjtcclxuaW1wb3J0IHsgZ2V0TGV2ZWxzQmVsb3csIGdldEhpZ2hlc3RMZXZlbEZvck1pc3Npb25zLCBnZXRIaWdoZXN0Um9sZUZvck1pc3Npb25zLCBmaWx0ZXJVbmlxdWVBcnJheUJ5SUQgfSBmcm9tIFwiLi4vaGVscGVycy5zZXJ2aWNlXCI7XHJcbmltcG9ydCB7XHJcbiAgWm9uZSxcclxuICBFcXVpcG1lbnQsXHJcbiAgTGV2ZWxTdGF0dXMsXHJcbiAgTWVhc3VyZW1lbnQsXHJcbiAgTWlzc2lvbixcclxuICBPcmdhbmlzYXRpb24sXHJcbiAgUG9pVHlwZSxcclxuICBQcm9maWxlRW50aXR5LFxyXG4gIFJvbGVTdGF0dXMsXHJcbiAgU3BhY2UsXHJcbiAgVGlja2V0LFxyXG4gIERiT2JqZWN0VHlwZSxcclxuICBGZWF0dXJlLFxyXG4gIENvbW1lbnQsXHJcbiAgVmlzaXRUZW1wbGF0ZSwgT2JqZWN0M0RcclxufSBmcm9tIFwiLi4vdHlwZXMuc2VydmljZVwiO1xyXG5pbXBvcnQgeyBQb2lTZXJ2aWNlIH0gZnJvbSBcIi4vbW9kZWxzL3BvaS5zZXJ2aWNlXCI7XHJcbmltcG9ydCB7IFpvbmVTZXJ2aWNlIH0gZnJvbSBcIi4vbW9kZWxzL3pvbmUuc2VydmljZVwiO1xyXG5pbXBvcnQgeyBCYXNlVXNlclNlcnZpY2UgfSBmcm9tIFwiLi91c2VyLnNlcnZpY2VcIjtcclxuZW51bSBGaWx0ZXJUeXBlIHtcclxuICAgIERPTUFJTiA9IFwiRE9NQUlOXCIsXHJcbiAgICBMRVZFTCA9IFwiTEVWRUxcIixcclxuICAgIFJPTEUgPSBcIlJPTEVcIixcclxuICAgIFpPTkUgPSBcIlpPTkVcIixcclxuICAgIFNQQUNFID0gXCJTUEFDRVwiLFxyXG4gICAgSEFTSFRBRyA9IFwiSEFTSFRBR1wiLFxyXG59XHJcbmltcG9ydCBsZXZlbnNodGVpbiBmcm9tICdqcy1sZXZlbnNodGVpbic7XHJcbkBJbmplY3RhYmxlKHtcclxuICAgIHByb3ZpZGVkSW46IFwicm9vdFwiLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgRmlsdGVyU2VydmljZSB7XHJcbiAgICBwcml2YXRlIHVwZGF0ZURhdGVGaWx0ZXI6IFN1YmplY3Q8RGF0ZVtdPiA9IG5ldyBTdWJqZWN0KCk7XHJcblxyXG4gICAgcHVibGljIGN1cnJlbnREYXRlRmlsdGVyOiBEYXRlW107XHJcblxyXG4gICAgY29uc3RydWN0b3IoXHJcbiAgICAgICAgcHJpdmF0ZSB1c2VyU2VydmljZTogQmFzZVVzZXJTZXJ2aWNlLFxyXG4gICAgICAgIHByaXZhdGUgem9uZVNlcnZpY2U6IFpvbmVTZXJ2aWNlLFxyXG4gICAgICAgIHByaXZhdGUgcG9pU2VydmljZTogUG9pU2VydmljZSxcclxuICAgICkge31cclxuXHJcbiAgICBmaWx0ZXJUaWNrZXRzQnlEb21haW4odGlja2V0c1RvRmlsdGVyOiBUaWNrZXRbXSwgZG9tYWluOiBzdHJpbmcpIHtcclxuICAgICAgICByZXR1cm4gdGlja2V0c1RvRmlsdGVyLmZpbHRlcigodGljKSA9PiB0aWMuZG9tYWluSUQgPT09IGRvbWFpbik7XHJcbiAgICB9XHJcblxyXG4gICAgZmlsdGVyT2JqZWN0c0J5TGV2ZWwob2JqZWN0c1RvRmlsdGVyOiBhbnlbXSwgbGV2ZWw6IExldmVsU3RhdHVzKTogYW55W10ge1xyXG4gICAgICAgIGNvbnN0IHZpc2libGVMZXZlbHMgPSBnZXRMZXZlbHNCZWxvdyhsZXZlbCk7XHJcbiAgICAgICAgY29uc3QgZmlsdGVyZWQgPSBvYmplY3RzVG9GaWx0ZXIuZmlsdGVyKCh0aWMpID0+XHJcbiAgICAgICAgICAgIHZpc2libGVMZXZlbHMuaW5jbHVkZXModGljLmxldmVsKSxcclxuICAgICAgICApO1xyXG4gICAgICAgIHJldHVybiBmaWx0ZXJlZDtcclxuICAgIH1cclxuXHJcbiAgICBmaWx0ZXJUaWNrZXRzRm9yTWlzc2lvbihcclxuICAgICAgICB0aWNrZXRzVG9GaWx0ZXI6IFRpY2tldFtdLFxyXG4gICAgICAgIG1pc3Npb246IE1pc3Npb24sXHJcbiAgICApOiBUaWNrZXRbXSB7XHJcbiAgICAgICAgY29uc3QgbWFuYWdlclJvbGVzOiBSb2xlU3RhdHVzW10gPSBbXHJcbiAgICAgICAgICAgIFJvbGVTdGF0dXMuTUFOQUdFUixcclxuICAgICAgICAgICAgUm9sZVN0YXR1cy5BRE1JTixcclxuICAgICAgICAgICAgUm9sZVN0YXR1cy5PV05FUixcclxuICAgICAgICBdO1xyXG4gICAgICAgIGlmICghbWFuYWdlclJvbGVzLmluY2x1ZGVzKG1pc3Npb24ucm9sZSkpIHtcclxuICAgICAgICAgICAgaWYgKG1pc3Npb24ucm9sZSA9PT0gUm9sZVN0YXR1cy5TRVJWSUNFKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBTRVJWSUNFIGNhbiBzZWUgdGlja2V0cyB0byB3aGljaCBoZSBpcyBhc3NpZ25lZFxyXG4gICAgICAgICAgICAgICAgY29uc3QgdGlja2V0c0Fzc2lnbmVkID0gW107XHJcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHQgb2YgdGlja2V0c1RvRmlsdGVyKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHQuYXNzaWduZWVzLml0ZW1zLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBhc3NpZ25tZW50IG9mIHQuYXNzaWduZWVzLml0ZW1zKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXNzaWdubWVudC5taXNzaW9uSUQgPT09IG1pc3Npb24uaWQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aWNrZXRzQXNzaWduZWQucHVzaCh0KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIHJldHVybiB0aWNrZXRzQXNzaWduZWQ7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgLy8gT0NDVVBBTlQgYW5kIFZJU0lUT1IgY2FuIHNlZSBvbmx5IHRpY2tldHMgdGhhdCB0aGV5IGNyZWF0ZWRcclxuICAgICAgICAgICAgcmV0dXJuIHRpY2tldHNUb0ZpbHRlci5maWx0ZXIoKHRpY2tldCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRpY2tldC5vd25lck1pc3Npb25JRCA9PT0gbWlzc2lvbi5pZDtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0aWNrZXRzVG9GaWx0ZXI7XHJcbiAgICB9XHJcblxyXG4gICAgZ2V0RmlsdGVyc0ZvclJvbGUocm9sZTogUm9sZVN0YXR1cyk6IEZpbHRlclR5cGVbXSB7XHJcbiAgICAgICAgc3dpdGNoIChyb2xlKSB7XHJcbiAgICAgICAgICAgIGNhc2UgUm9sZVN0YXR1cy5BRE1JTjpcclxuICAgICAgICAgICAgICAgIHJldHVybiBbRmlsdGVyVHlwZS5MRVZFTF07XHJcbiAgICAgICAgICAgIGNhc2UgUm9sZVN0YXR1cy5NQU5BR0VSOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIFtGaWx0ZXJUeXBlLlpPTkUsIEZpbHRlclR5cGUuTEVWRUxdO1xyXG4gICAgICAgICAgICBjYXNlIFJvbGVTdGF0dXMuT1dORVI6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gW0ZpbHRlclR5cGUuWk9ORSwgRmlsdGVyVHlwZS5MRVZFTF07XHJcbiAgICAgICAgICAgIGNhc2UgUm9sZVN0YXR1cy5TRVJWSUNFOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIFtcclxuICAgICAgICAgICAgICAgICAgICBGaWx0ZXJUeXBlLlpPTkUsXHJcbiAgICAgICAgICAgICAgICAgICAgRmlsdGVyVHlwZS5MRVZFTCxcclxuICAgICAgICAgICAgICAgICAgICBGaWx0ZXJUeXBlLkRPTUFJTixcclxuICAgICAgICAgICAgICAgICAgICBGaWx0ZXJUeXBlLlJPTEUsIC8vIHRoYXQgaXMgdGhlIG1vc3Qgc2V2ZXJlIGZpbHRlclxyXG4gICAgICAgICAgICAgICAgXTtcclxuICAgICAgICAgICAgY2FzZSBSb2xlU3RhdHVzLk9DQ1VQQU5UOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIFtcclxuICAgICAgICAgICAgICAgICAgICBGaWx0ZXJUeXBlLlpPTkUsXHJcbiAgICAgICAgICAgICAgICAgICAgRmlsdGVyVHlwZS5ET01BSU4sXHJcbiAgICAgICAgICAgICAgICAgICAgRmlsdGVyVHlwZS5ST0xFLFxyXG4gICAgICAgICAgICAgICAgICAgIEZpbHRlclR5cGUuTEVWRUwsXHJcbiAgICAgICAgICAgICAgICAgICAgRmlsdGVyVHlwZS5IQVNIVEFHLFxyXG4gICAgICAgICAgICAgICAgXTtcclxuICAgICAgICAgICAgY2FzZSBSb2xlU3RhdHVzLlZJU0lUT1I6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gW1xyXG4gICAgICAgICAgICAgICAgICAgIEZpbHRlclR5cGUuWk9ORSxcclxuICAgICAgICAgICAgICAgICAgICBGaWx0ZXJUeXBlLkxFVkVMLFxyXG4gICAgICAgICAgICAgICAgICAgIEZpbHRlclR5cGUuRE9NQUlOLFxyXG4gICAgICAgICAgICAgICAgICAgIEZpbHRlclR5cGUuUk9MRSxcclxuICAgICAgICAgICAgICAgICAgICBGaWx0ZXJUeXBlLkhBU0hUQUcsXHJcbiAgICAgICAgICAgICAgICBdO1xyXG4gICAgICAgICAgICBjYXNlIFJvbGVTdGF0dXMuVklTSVRPUl9NVVNFVU06XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gW0ZpbHRlclR5cGUuWk9ORSwgRmlsdGVyVHlwZS5MRVZFTCwgRmlsdGVyVHlwZS5IQVNIVEFHXTtcclxuICAgICAgICAgICAgY2FzZSBSb2xlU3RhdHVzLkdVSURFX01VU0VVTTpcclxuICAgICAgICAgICAgICAgIHJldHVybiBbRmlsdGVyVHlwZS5MRVZFTF07XHJcbiAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gW0ZpbHRlclR5cGUuTEVWRUxdO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBhc3luYyBmaWx0ZXJPYmplY3RzRm9yQ3VycmVudFVzZXJJblNwYWNlKFxyXG4gICAgICAgIG9iamVjdHM6IE9iamVjdDNEW10sXHJcbiAgICAgICAgc3BhY2VJRDogc3RyaW5nLFxyXG4gICAgKTogUHJvbWlzZTxPYmplY3QzRFtdPiB7XHJcbiAgICAgICAgY29uc3QgZmluYWxPYmplY3QzRHM6IE9iamVjdDNEW10gPSBbXTtcclxuICAgICAgICBsZXQgZG9tRmlsdGVyZWQ6IE9iamVjdDNEW10gPSBvYmplY3RzO1xyXG4gICAgICAgIGxldCBsZXZlbEZpbHRlcmVkOiBPYmplY3QzRFtdID0gb2JqZWN0cztcclxuICAgICAgICBsZXQgem9uZUZpbHRlcmVkOiBPYmplY3QzRFtdID0gb2JqZWN0cztcclxuICAgICAgICBjb25zdCBtaXNzaW9ucyA9IHRoaXMudXNlclNlcnZpY2UuY3VycmVudE1pc3Npb25zO1xyXG4gICAgICAgIGlmIChtaXNzaW9ucykge1xyXG4gICAgICAgICAgICBjb25zdCBjdXJyZW50U3BhY2VNaXNzaW9ucyA9IG1pc3Npb25zLmZpbHRlcihcclxuICAgICAgICAgICAgICAgIChtKSA9PiBtLnNwYWNlSUQgPT09IHNwYWNlSUQsXHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgIGlmIChjdXJyZW50U3BhY2VNaXNzaW9ucy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IG9iaiBvZiBsZXZlbEZpbHRlcmVkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBkb21GaWx0ZXJlZC5pbmNsdWRlcyhvYmopICYmXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHpvbmVGaWx0ZXJlZC5pbmNsdWRlcyhvYmopXHJcbiAgICAgICAgICAgICAgICAgICAgKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsT2JqZWN0M0RzLnB1c2gob2JqKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIGZpbmFsT2JqZWN0M0RzO1xyXG4gICAgfVxyXG5cclxuICAgIGFzeW5jIGZpbHRlclRpY2tldHNGb3JDdXJyZW50VXNlckluU3BhY2UoXHJcbiAgICAgICAgdGlja2V0czogVGlja2V0W10sXHJcbiAgICAgICAgc3BhY2VJRDogc3RyaW5nLFxyXG4gICAgKTogUHJvbWlzZTxUaWNrZXRbXT4ge1xyXG4gICAgICAgIGNvbnN0IGZpbmFsVGlja2V0czogVGlja2V0W10gPSBbXTtcclxuICAgICAgICBsZXQgZG9tRmlsdGVyZWQ6IFRpY2tldFtdID0gdGlja2V0cztcclxuICAgICAgICBsZXQgcm9sZUZpbHRlcmVkOiBUaWNrZXRbXSA9IHRpY2tldHM7XHJcbiAgICAgICAgbGV0IGxldmVsRmlsdGVyZWQ6IFRpY2tldFtdID0gdGlja2V0cztcclxuICAgICAgICBsZXQgem9uZUZpbHRlcmVkOiBUaWNrZXRbXSA9IHRpY2tldHM7XHJcbiAgICAgICAgY29uc3QgbWlzc2lvbnMgPSB0aGlzLnVzZXJTZXJ2aWNlLmN1cnJlbnRNaXNzaW9ucztcclxuICAgICAgICBpZiAobWlzc2lvbnMpIHtcclxuICAgICAgICAgICAgY29uc3QgY3VycmVudFNwYWNlTWlzc2lvbnMgPSBtaXNzaW9ucy5maWx0ZXIoXHJcbiAgICAgICAgICAgICAgICAobSkgPT4gbS5zcGFjZUlEID09PSBzcGFjZUlELFxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgICAgICBpZiAoY3VycmVudFNwYWNlTWlzc2lvbnMubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgaGlnaGVzdExlbGVsID1cclxuICAgICAgICAgICAgICAgICAgICBnZXRIaWdoZXN0TGV2ZWxGb3JNaXNzaW9ucyhjdXJyZW50U3BhY2VNaXNzaW9ucyk7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBoaWdoZXN0Um9sZSA9XHJcbiAgICAgICAgICAgICAgICAgICAgZ2V0SGlnaGVzdFJvbGVGb3JNaXNzaW9ucyhjdXJyZW50U3BhY2VNaXNzaW9ucyk7XHJcbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIkhpZ2hlc3QgbGV2ZWw6IFwiLCBoaWdoZXN0TGVsZWwsIFwiLCBIaWdoZXN0IFJvbGU6IFwiLCBoaWdoZXN0Um9sZSlcclxuXHJcbiAgICAgICAgICAgICAgICBjb25zdCBmaWx0ZXJzID0gdGhpcy5nZXRGaWx0ZXJzRm9yUm9sZShoaWdoZXN0Um9sZSk7XHJcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGZpbHRlciBvZiBmaWx0ZXJzKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGZpbHRlciA9PT0gRmlsdGVyVHlwZS5ET01BSU4pIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGRvbWFpbnM6IHN0cmluZ1tdID0gW107XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgbSBvZiBjdXJyZW50U3BhY2VNaXNzaW9ucykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG0uZG9tYWlucykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvbWFpbnMgPSBbLi4uZG9tYWlucywgLi4ubS5kb21haW5zXTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgYWxsRG9tYWluc0ZpbHRlcmVkID0gW107XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZCBvZiBkb21haW5zKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjdXJyZW50RG9tRmlsdGVyZWQgPVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZmlsdGVyVGlja2V0c0J5RG9tYWluKHRpY2tldHMsIGQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxsRG9tYWluc0ZpbHRlcmVkID0gW1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLmFsbERvbWFpbnNGaWx0ZXJlZCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5jdXJyZW50RG9tRmlsdGVyZWQsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBdO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvbUZpbHRlcmVkID0gYWxsRG9tYWluc0ZpbHRlcmVkO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAoZmlsdGVyID09PSBGaWx0ZXJUeXBlLlJPTEUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaGlnaGVzdFJvbGVNaXNzaW9uID0gY3VycmVudFNwYWNlTWlzc2lvbnMuZmluZChcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChtKSA9PiBtLnJvbGUgPT09IGhpZ2hlc3RSb2xlLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByb2xlRmlsdGVyZWQgPSB0aGlzLmZpbHRlclRpY2tldHNGb3JNaXNzaW9uKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGlja2V0cyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhpZ2hlc3RSb2xlTWlzc2lvbixcclxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChmaWx0ZXIgPT09IEZpbHRlclR5cGUuTEVWRUwpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxGaWx0ZXJlZCA9IHRoaXMuZmlsdGVyT2JqZWN0c0J5TGV2ZWwoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aWNrZXRzLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGlnaGVzdExlbGVsLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGZpbHRlciA9PT0gRmlsdGVyVHlwZS5aT05FKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHpvbmVGaWx0ZXJlZCA9IGF3YWl0IHRoaXMuYXBwbHlab25lRmlsdGVyRm9yTWlzc2lvbnMoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50U3BhY2VNaXNzaW9ucyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpY2tldHMsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgLy8ga2VlcCBvbmx5IHRpY2tldHMgcHJlc2VudCBpbiBhbGwgZmlsdGVyZWQgYXJyYXlzXHJcbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhkb21GaWx0ZXJlZCk7XHJcbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhyb2xlRmlsdGVyZWQpO1xyXG4gICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2cobGV2ZWxGaWx0ZXJlZCk7XHJcbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyh6b25lRmlsdGVyZWQpO1xyXG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCB0aWMgb2YgbGV2ZWxGaWx0ZXJlZCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChcclxuICAgICAgICAgICAgICAgICAgICAgICAgZG9tRmlsdGVyZWQuaW5jbHVkZXModGljKSAmJlxyXG4gICAgICAgICAgICAgICAgICAgICAgICByb2xlRmlsdGVyZWQuaW5jbHVkZXModGljKSAmJlxyXG4gICAgICAgICAgICAgICAgICAgICAgICB6b25lRmlsdGVyZWQuaW5jbHVkZXModGljKVxyXG4gICAgICAgICAgICAgICAgICAgICkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFRpY2tldHMucHVzaCh0aWMpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICAvLyBjb25zb2xlLmxvZyhmaW5hbFRpY2tldHMpO1xyXG4gICAgICAgIHJldHVybiBmaW5hbFRpY2tldHM7XHJcbiAgICB9XHJcblxyXG4gICAgc3Vic2NyaWJlVG9EYXRhRmlsdGVyVXBkYXRlKFxyXG4gICAgICAgIG5leHQ/OiAodmFsdWU6IGFueSkgPT4gdm9pZCxcclxuICAgICAgICBlcnJvcj86IChlcnJvcjogYW55KSA9PiB2b2lkLFxyXG4gICAgICAgIGNvbXBsZXRlPzogKCkgPT4gdm9pZCxcclxuICAgICk6IFN1YnNjcmlwdGlvbiB7XHJcbiAgICAgICAgY29uc3QgcyA9IHRoaXMudXBkYXRlRGF0ZUZpbHRlci5zdWJzY3JpYmUobmV4dCwgZXJyb3IsIGNvbXBsZXRlKTtcclxuICAgICAgICByZXR1cm4gcztcclxuICAgIH1cclxuXHJcbiAgICBkYXRlRmlsdGVyVXBkYXRlZChkYXRlUmFuZ2U6IERhdGVbXSB8IG51bGwpIHtcclxuICAgICAgICB0aGlzLmN1cnJlbnREYXRlRmlsdGVyID0gZGF0ZVJhbmdlO1xyXG4gICAgICAgIHRoaXMudXBkYXRlRGF0ZUZpbHRlci5uZXh0KGRhdGVSYW5nZSk7XHJcbiAgICB9XHJcblxyXG4gICAgZmlsdGVyT2JqZWN0c0ZvckRhdGVSYW5nZShvYmplY3RzOiBhbnlbXSwgZGF0ZVJhbmdlOiBEYXRlW10pOiBhbnlbXSB7XHJcbiAgICAgICAgcmV0dXJuIG9iamVjdHMuZmlsdGVyKChvYmplY3QpID0+IHtcclxuICAgICAgICAgICAgY29uc3QgY3JlYXRlZEF0RGF0ZSA9IG5ldyBEYXRlKG9iamVjdC5jcmVhdGVkQXQpO1xyXG4gICAgICAgICAgICByZXR1cm4gKFxyXG4gICAgICAgICAgICAgICAgY3JlYXRlZEF0RGF0ZSA+PSBkYXRlUmFuZ2VbMF0gJiYgY3JlYXRlZEF0RGF0ZSA8PSBkYXRlUmFuZ2VbMV1cclxuICAgICAgICAgICAgKTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBmaWx0ZXJNZWFzdXJlbWVudHNGb3JEYXRlUmFuZ2UoXHJcbiAgICAgICAgbWVhc3VyZW1lbnRzOiBNZWFzdXJlbWVudFtdLFxyXG4gICAgICAgIGRhdGVSYW5nZTogRGF0ZVtdLFxyXG4gICAgKTogTWVhc3VyZW1lbnRbXSB7XHJcbiAgICAgICAgcmV0dXJuIG1lYXN1cmVtZW50cy5maWx0ZXIoKG1lYXN1cmUpID0+IHtcclxuICAgICAgICAgICAgY29uc3QgY3JlYXRlZEF0RGF0ZSA9IG5ldyBEYXRlKG1lYXN1cmUuY29tbWVudC5jcmVhdGVkQXQpO1xyXG4gICAgICAgICAgICByZXR1cm4gKFxyXG4gICAgICAgICAgICAgICAgY3JlYXRlZEF0RGF0ZSA+PSBkYXRlUmFuZ2VbMF0gJiYgY3JlYXRlZEF0RGF0ZSA8PSBkYXRlUmFuZ2VbMV1cclxuICAgICAgICAgICAgKTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBhc3luYyBmaWx0ZXJPYmplY3RzRm9yWm9uZShcclxuICAgICAgICBvYmplY3RzOiBhbnlbXSwgLy8gVE9ETzogcmVtb3ZlIGFueSBoZXJlLi5cclxuICAgICAgICB6b25lSUQ6IHN0cmluZyA9IG51bGwsXHJcbiAgICAgICAgem9uZTogWm9uZSA9IG51bGwsXHJcbiAgICApOiBQcm9taXNlPGFueVtdPiB7XHJcbiAgICAgICAgY29uc3QgZmlsdGVyZWRPYmplY3RzID0gW107XHJcbiAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXHJcbiAgICAgICAgICAgIG9iamVjdHMubWFwKGFzeW5jIChvYmplY3QpID0+IHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IFtwb2ldID0gb2JqZWN0LnBvaXMuaXRlbXM7XHJcbiAgICAgICAgICAgICAgICBpZiAocG9pICYmIHpvbmUpIHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoem9uZS5zd2VlcElEcyAmJiB6b25lLnN3ZWVwSURzLmluY2x1ZGVzKHBvaS5tYXR0ZXJwb3J0U3dlZXBJRCkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMucG9pU2VydmljZS5wb2lJc1ZpcnR1YWwocG9pKSAmJiB6b25lLmxheWVyICYmIHpvbmUubGF5ZXIubmFtZSA9PT0gXCJGTE9PUlwiICkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gd2UgaW5jbHVkZSBpbiBGbG9vciB6b25lIG9ubHlcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcmVkT2JqZWN0cy5wdXNoKG9iamVjdCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLnBvaVNlcnZpY2UucG9pSXNWaXJ0dWFsKHBvaSkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcmVkT2JqZWN0cy5wdXNoKG9iamVjdCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBpZiAocG9pICYmICF6b25lICYmIHpvbmVJRCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHpvbmVzID0gYXdhaXQgdGhpcy56b25lU2VydmljZS5nZXRab25lc0Zvck9iamVjdChcclxuICAgICAgICAgICAgICAgICAgICAgICAgb2JqZWN0LFxyXG4gICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICB6b25lcyAmJlxyXG4gICAgICAgICAgICAgICAgICAgICAgICB6b25lcy5zb21lKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKHpvbmVfKSA9PlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHpvbmVfLmlkID09PSB6b25lSUQgfHxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB6b25lXy5wYXJlbnRJRCA9PT0gem9uZUlELFxyXG4gICAgICAgICAgICAgICAgICAgICAgICApXHJcbiAgICAgICAgICAgICAgICAgICAgKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcmVkT2JqZWN0cy5wdXNoKG9iamVjdCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9KSxcclxuICAgICAgICApO1xyXG4gICAgICAgIHJldHVybiBmaWx0ZXJlZE9iamVjdHM7XHJcbiAgICB9XHJcblxyXG4gICAgZmlsdGVyRXF1aXBtZW50c0J5RG9tYWluTGlzdChcclxuICAgICAgICBlcXVpcG1lbnRzOiBFcXVpcG1lbnRbXSxcclxuICAgICAgICBkb21haW5JRExpc3Q6IHN0cmluZ1tdLFxyXG4gICAgKTogRXF1aXBtZW50W10ge1xyXG4gICAgICAgIGxldCBmaWx0ZXJlZCA9IFtdO1xyXG4gICAgICAgIGNvbnN0IGZpbHRlcmVkQnlEb21haW4gPSBlcXVpcG1lbnRzLmZpbHRlcigoZXF1aXApID0+XHJcbiAgICAgICAgZG9tYWluSURMaXN0LmluY2x1ZGVzKGVxdWlwLmRvbWFpbklEKSxcclxuICAgICAgICApO1xyXG4gICAgICAgIGZpbHRlcmVkID0gWy4uLmZpbHRlcmVkLCAuLi5maWx0ZXJlZEJ5RG9tYWluXTtcclxuICAgICAgICBjb25zdCBmaWx0ZXJlZEJ5UGFyZW50RG9tYWluID0gZXF1aXBtZW50cy5maWx0ZXIoXHJcbiAgICAgICAgICAgIChlcXVpcCkgPT5cclxuICAgICAgICAgICAgICAgIGVxdWlwLmRvbWFpbiAmJlxyXG4gICAgICAgICAgICAgICAgZXF1aXAuZG9tYWluLnBhcmVudElEICYmXHJcbiAgICAgICAgICAgICAgICBkb21haW5JRExpc3QuaW5jbHVkZXMoZXF1aXAuZG9tYWluLnBhcmVudElEKSxcclxuICAgICAgICApO1xyXG4gICAgICAgIGZpbHRlcmVkID0gWy4uLmZpbHRlcmVkLCAuLi5maWx0ZXJlZEJ5UGFyZW50RG9tYWluXTtcclxuICAgICAgICByZXR1cm4gZmlsdGVyVW5pcXVlQXJyYXlCeUlEKGZpbHRlcmVkKTtcclxuICAgIH1cclxuXHJcblxyXG4gIC8vIE5vdCBpbXBsZW1lbnRlZCB5ZXQhXHJcbiAgLy8gZmlsdGVyT2JqZWN0czNEQnlEb21haW5MaXN0KFxyXG4gIC8vICAgb2JqZWN0czNEOiBPYmplY3QzRFtdLFxyXG4gIC8vICAgZG9tYWluSURMaXN0OiBzdHJpbmdbXSxcclxuICAvLyApOiBPYmplY3QzRFtdIHtcclxuICAvLyAgIGxldCBmaWx0ZXJlZCA9IFtdO1xyXG4gIC8vICAgY29uc3QgZmlsdGVyZWRCeURvbWFpbiA9IG9iamVjdHMzRC5maWx0ZXIoKGVxdWlwKSA9PlxyXG4gIC8vICAgICBkb21haW5JRExpc3QuaW5jbHVkZXMoZXF1aXAuZG9tYWluSUQpLFxyXG4gIC8vICAgKTtcclxuICAvLyAgIGZpbHRlcmVkID0gWy4uLmZpbHRlcmVkLCAuLi5maWx0ZXJlZEJ5RG9tYWluXTtcclxuICAvLyAgIGNvbnN0IGZpbHRlcmVkQnlQYXJlbnREb21haW4gPSBvYmplY3RzM0QuZmlsdGVyKFxyXG4gIC8vICAgICAob2JqKSA9PlxyXG4gIC8vICAgICAgIG9iai5kb21haW4gJiZcclxuICAvLyAgICAgICBvYmouZG9tYWluLnBhcmVudElEICYmXHJcbiAgLy8gICAgICAgZG9tYWluSURMaXN0LmluY2x1ZGVzKG9iai5kb21haW4ucGFyZW50SUQpLFxyXG4gIC8vICAgKTtcclxuICAvLyAgIGZpbHRlcmVkID0gWy4uLmZpbHRlcmVkLCAuLi5maWx0ZXJlZEJ5UGFyZW50RG9tYWluXTtcclxuICAvLyAgIHJldHVybiBmaWx0ZXJVbmlxdWVBcnJheUJ5SUQoZmlsdGVyZWQpO1xyXG4gIC8vIH1cclxuXHJcbiAgZmlsdGVyRXF1aXBtZW50c0ZvclRlcm0oZXF1aXBzOiBFcXVpcG1lbnRbXSwgdGVybTogc3RyaW5nKTogRXF1aXBtZW50W10ge1xyXG4gICAgICAgIC8vIGZpbHRlciBkb21haW5zXHJcbiAgICAgICAgbGV0IGJ5RG9tYWluID0gZXF1aXBzLmZpbHRlcigoZXEpID0+IHtcclxuICAgICAgICAgICAgaWYgKGVxLmRvbWFpbiAmJiBlcS5kb21haW4ubmFtZSkge1xyXG4gICAgICAgICAgICAgICAgY29uc3Qgbm9ybWFsaXplZERvbWFpbiA9IGVxLmRvbWFpbi5uYW1lLnRvTG93ZXJDYXNlKCk7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBsZXYgPSBsZXZlbnNodGVpbihub3JtYWxpemVkRG9tYWluLCB0ZXJtKTtcclxuICAgICAgICAgICAgICAgIHJldHVybiBsZXYgPD0gMiB8fCBub3JtYWxpemVkRG9tYWluLmluY2x1ZGVzKHRlcm0pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICB9KTtcclxuICAgICAgICBjb25zdCBieVBhcmVudERvbWFpbiA9IGVxdWlwcy5maWx0ZXIoKGVxKSA9PiB7XHJcbiAgICAgICAgICAgIGlmIChlcS5kb21haW4gJiYgZXEuZG9tYWluLnBhcmVudElEKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBub3JtYWxpemVkUGFyZW50ID0gZXEuZG9tYWluLnBhcmVudC5uYW1lLnRvTG93ZXJDYXNlKCk7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBsZXYgPSBsZXZlbnNodGVpbihub3JtYWxpemVkUGFyZW50LCB0ZXJtKTtcclxuICAgICAgICAgICAgICAgIHJldHVybiBsZXYgPD0gMiB8fCBub3JtYWxpemVkUGFyZW50LmluY2x1ZGVzKHRlcm0pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICB9KTtcclxuICAgICAgICBieURvbWFpbiA9IFsuLi5ieURvbWFpbiwgLi4uYnlQYXJlbnREb21haW5dO1xyXG4gICAgICAgIC8vIGZpbHRlciBuYW1lXHJcbiAgICAgICAgbGV0IGJ5TmFtZSA9IFtdO1xyXG4gICAgICAgIGNvbnN0IHRlcm1zID0gdGVybS5zcGxpdChcIiBcIikuZmlsdGVyKCh0b2tlbikgPT4gdG9rZW4ubGVuZ3RoID4gMik7XHJcbiAgICAgICAgZm9yIChjb25zdCBlcSBvZiBlcXVpcHMpIHtcclxuICAgICAgICAgICAgY29uc3Qgd29yZHMgPSBlcS5uYW1lXHJcbiAgICAgICAgICAgICAgICAudG9Mb3dlckNhc2UoKVxyXG4gICAgICAgICAgICAgICAgLnNwbGl0KFwiIFwiKVxyXG4gICAgICAgICAgICAgICAgLmZpbHRlcigodG9rZW4pID0+IHRva2VuLmxlbmd0aCA+IDIpO1xyXG4gICAgICAgICAgICBjb25zdCBtYXRjaGVkID0gW107XHJcbiAgICAgICAgICAgIGZvciAoY29uc3QgdG9rZW4gb2YgdGVybXMpIHtcclxuICAgICAgICAgICAgICAgIGZvciAoY29uc3Qgd29yZCBvZiB3b3Jkcykge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChsZXZlbnNodGVpbih0b2tlbiwgd29yZCkgPD0gMSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRjaGVkLnB1c2godHJ1ZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBpZiAobWF0Y2hlZC5sZW5ndGggPT09IHRlcm1zLmxlbmd0aCkge1xyXG4gICAgICAgICAgICAgICAgYnlOYW1lLnB1c2goZXEpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBieU5hbWVTaW1wbGUgPSBlcXVpcHMuZmlsdGVyKChlcSkgPT5cclxuICAgICAgICAgICAgZXEubmFtZS50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHRlcm0pLFxyXG4gICAgICAgICk7XHJcbiAgICAgICAgYnlOYW1lID0gWy4uLmJ5TmFtZSwgLi4uYnlOYW1lU2ltcGxlXTtcclxuICAgICAgICAvLyBieSBzZXJpYWwgbnVtYmVyXHJcbiAgICAgICAgY29uc3QgYnlTZXJpYWxOdW1iZXIgPSBlcXVpcHMuZmlsdGVyKFxyXG4gICAgICAgICAgICAoZXEpID0+IGVxLnNlcmlhbE51bWJlciAmJiBlcS5zZXJpYWxOdW1iZXIudG9Mb3dlckNhc2UoKSA9PT0gdGVybSxcclxuICAgICAgICApO1xyXG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IFsuLi5ieURvbWFpbiwgLi4uYnlOYW1lLCAuLi5ieVNlcmlhbE51bWJlcl07XHJcbiAgICAgICAgcmV0dXJuIGZpbHRlclVuaXF1ZUFycmF5QnlJRChyZXN1bHQpO1xyXG4gICAgfVxyXG5cclxuICAgIGZpbHRlclRpY2tldHNGb3JUZXJtKHRpY2tldHM6IFRpY2tldFtdLCB0ZXJtOiBzdHJpbmcpOiBUaWNrZXRbXSB7XHJcbiAgICAgICAgLy8gZmlsdGVyIHRlcm0gaW4gdGl0bGUgYW5kIGRlc2NyaXB0aW9uXHJcbiAgICAgICAgY29uc3QgYnlUaXRsZSA9IHRoaXMuZmlsdGVyT2JqZWN0c0ZvclRlcm0odGlja2V0cywgdGVybSk7XHJcbiAgICAgICAgLy8gYnkgZXF1aXBtZW50XHJcbiAgICAgICAgY29uc3QgYnlFcXVpcG1lbnQgPSB0aWNrZXRzLmZpbHRlcihcclxuICAgICAgICAgICAgKHRpY2tldCkgPT5cclxuICAgICAgICAgICAgICAgIHRpY2tldC5lcXVpcG1lbnRzICYmXHJcbiAgICAgICAgICAgICAgICB0aGlzLmZpbHRlckVxdWlwbWVudHNGb3JUZXJtKHRpY2tldC5lcXVpcG1lbnRzLCB0ZXJtKS5sZW5ndGggPlxyXG4gICAgICAgICAgICAgICAgICAgIDAsXHJcbiAgICAgICAgKTtcclxuICAgICAgICByZXR1cm4gZmlsdGVyVW5pcXVlQXJyYXlCeUlEKFsuLi5ieVRpdGxlLCAuLi5ieUVxdWlwbWVudF0pO1xyXG4gICAgfVxyXG5cclxuICAgIGZpbHRlckxvY2F0aW9uc0ZvclRlcm0obG9jYXRpb25zOiBTcGFjZVtdLCB0ZXJtOiBzdHJpbmcpOiBTcGFjZVtdIHtcclxuICAgICAgICAvLyBieSBuYW1lXHJcbiAgICAgICAgY29uc3QgYnlOYW1lID0gbG9jYXRpb25zLmZpbHRlcigobG9jKSA9PlxyXG4gICAgICAgICAgICBsb2MubmFtZS50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHRlcm0pLFxyXG4gICAgICAgICk7XHJcbiAgICAgICAgLy8gYnkgYWRkcmVzc1xyXG4gICAgICAgIGNvbnN0IGJ5QWRkcmVzcyA9IGxvY2F0aW9ucy5maWx0ZXIoKGxvYykgPT5cclxuICAgICAgICAgICAgbG9jLmFkZHJlc3Nlcy50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHRlcm0pLFxyXG4gICAgICAgICk7XHJcbiAgICAgICAgcmV0dXJuIGZpbHRlclVuaXF1ZUFycmF5QnlJRChbLi4uYnlOYW1lLCAuLi5ieUFkZHJlc3NdKTtcclxuICAgIH1cclxuXHJcbiAgICBmaWx0ZXJPcmdhbmlzYXRpb25zRm9yVGVybShcclxuICAgICAgICBvcmdzOiBPcmdhbmlzYXRpb25bXSxcclxuICAgICAgICB0ZXJtOiBzdHJpbmcsXHJcbiAgICApOiBPcmdhbmlzYXRpb25bXSB7XHJcbiAgICAgICAgY29uc3QgYnlOYW1lID0gb3Jncy5maWx0ZXIoKG9yZykgPT4ge1xyXG4gICAgICAgICAgICBjb25zdCB3b3JkcyA9IG9yZy5uYW1lLnRvTG93ZXJDYXNlKCkuc3BsaXQoXCIgXCIpO1xyXG4gICAgICAgICAgICByZXR1cm4gKFxyXG4gICAgICAgICAgICAgICAgd29yZHMuc29tZShcclxuICAgICAgICAgICAgICAgICAgICAod29yZCkgPT4gd29yZC5sZW5ndGggPiAyICYmIGxldmVuc2h0ZWluKHdvcmQsIHRlcm0pIDw9IDEsXHJcbiAgICAgICAgICAgICAgICApIHx8IG9yZy5uYW1lLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXModGVybSlcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICB9KTtcclxuICAgICAgICByZXR1cm4gYnlOYW1lO1xyXG4gICAgfVxyXG5cclxuICAgIGZpbHRlclVzZXJzRm9yVGVybSh1c2VyczogUHJvZmlsZUVudGl0eVtdLCB0ZXJtOiBzdHJpbmcpIHtcclxuICAgICAgICBjb25zdCBieU5hbWUgPSB1c2Vycy5maWx0ZXIoKHVzZXIpID0+IHtcclxuICAgICAgICAgICAgY29uc3Qgd29yZHMgPSB1c2VyLmRpc3BsYXlOYW1lLnRvTG93ZXJDYXNlKCkuc3BsaXQoXCIgXCIpO1xyXG4gICAgICAgICAgICByZXR1cm4gKFxyXG4gICAgICAgICAgICAgICAgd29yZHMuc29tZShcclxuICAgICAgICAgICAgICAgICAgICAod29yZCkgPT4gd29yZC5sZW5ndGggPiAyICYmIGxldmVuc2h0ZWluKHdvcmQsIHRlcm0pIDw9IDEsXHJcbiAgICAgICAgICAgICAgICApIHx8IHVzZXIuZGlzcGxheU5hbWUudG9Mb3dlckNhc2UoKS5pbmNsdWRlcyh0ZXJtKVxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIHJldHVybiBieU5hbWU7XHJcbiAgICB9XHJcblxyXG4gICAgYXN5bmMgZmlsdGVyRmVhdHVyZXNGb3JDdXJyZW50VXNlckluU3BhY2UoXHJcbiAgICAgICAgZmVhdHVyZXM6IEZlYXR1cmVbXSxcclxuICAgICAgICBzcGFjZUlEOiBzdHJpbmcsXHJcbiAgICApOiBQcm9taXNlPEZlYXR1cmVbXT4ge1xyXG4gICAgICAgIGNvbnN0IGZpbmFsRmVhdHVyZXM6IEZlYXR1cmVbXSA9IFtdO1xyXG4gICAgICAgIGxldCBsZXZlbEZpbHRlcmVkOiBGZWF0dXJlW10gPSBmZWF0dXJlcztcclxuICAgICAgICBsZXQgem9uZUZpbHRlcmVkOiBGZWF0dXJlW10gPSBmZWF0dXJlcztcclxuICAgICAgICBsZXQgaGFzaHRhZ0ZpbHRlcmVkOiBGZWF0dXJlW10gPSBmZWF0dXJlcztcclxuICAgICAgICBjb25zdCBtaXNzaW9ucyA9IHRoaXMudXNlclNlcnZpY2UuY3VycmVudE1pc3Npb25zO1xyXG4gICAgICAgIGlmIChtaXNzaW9ucykge1xyXG4gICAgICAgICAgICBjb25zdCBjdXJyZW50U3BhY2VNaXNzaW9ucyA9IG1pc3Npb25zLmZpbHRlcihcclxuICAgICAgICAgICAgICAgIChtKSA9PiBtLnNwYWNlSUQgPT09IHNwYWNlSUQsXHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgIGlmIChjdXJyZW50U3BhY2VNaXNzaW9ucy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBoaWdoZXN0TGVsZWwgPVxyXG4gICAgICAgICAgICAgICAgICAgIGdldEhpZ2hlc3RMZXZlbEZvck1pc3Npb25zKGN1cnJlbnRTcGFjZU1pc3Npb25zKTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGhpZ2hlc3RSb2xlID1cclxuICAgICAgICAgICAgICAgICAgICBnZXRIaWdoZXN0Um9sZUZvck1pc3Npb25zKGN1cnJlbnRTcGFjZU1pc3Npb25zKTtcclxuXHJcbiAgICAgICAgICAgICAgICBjb25zdCBmaWx0ZXJzID0gdGhpcy5nZXRGaWx0ZXJzRm9yUm9sZShoaWdoZXN0Um9sZSk7XHJcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGZpbHRlciBvZiBmaWx0ZXJzKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGZpbHRlciA9PT0gRmlsdGVyVHlwZS5MRVZFTCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXZlbEZpbHRlcmVkID0gdGhpcy5maWx0ZXJPYmplY3RzQnlMZXZlbChcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGlnaGVzdExlbGVsLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAoZmlsdGVyID09PSBGaWx0ZXJUeXBlLlpPTkUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgem9uZUZpbHRlcmVkID0gYXdhaXQgdGhpcy5hcHBseVpvbmVGaWx0ZXJGb3JNaXNzaW9ucyhcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRTcGFjZU1pc3Npb25zLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChmaWx0ZXIgPT09IEZpbHRlclR5cGUuSEFTSFRBRykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBoYXNodGFnRmlsdGVyZWQgPVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5maWx0ZXJGZWF0dXJlc0J5SGFzaHRhZ3NBbmRMb2NhbGUoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudFNwYWNlTWlzc2lvbnMsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZmVhdHVyZSBvZiBsZXZlbEZpbHRlcmVkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBoYXNodGFnRmlsdGVyZWQuaW5jbHVkZXMoZmVhdHVyZSkgJiZcclxuICAgICAgICAgICAgICAgICAgICAgICAgem9uZUZpbHRlcmVkLmluY2x1ZGVzKGZlYXR1cmUpXHJcbiAgICAgICAgICAgICAgICAgICAgKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsRmVhdHVyZXMucHVzaChmZWF0dXJlKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIGZpbmFsRmVhdHVyZXM7XHJcbiAgICB9XHJcblxyXG4gICAgZmlsdGVyRmVhdHVyZXNGb3JUZXJtKGZlYXR1cmVzOiBGZWF0dXJlW10sIHRlcm06IHN0cmluZyk6IEZlYXR1cmVbXSB7XHJcbiAgICAgICAgLy8gZmlsdGVyIHRlcm0gaW4gdGl0bGVcclxuICAgICAgICBjb25zdCBieVRpdGxlID0gdGhpcy5maWx0ZXJPYmplY3RzRm9yVGVybShmZWF0dXJlcywgdGVybSk7XHJcbiAgICAgICAgLy8gYnkgY29tbWVudHNcclxuICAgICAgICBjb25zdCBieUNvbW1lbnQgPSBmZWF0dXJlcy5maWx0ZXIoXHJcbiAgICAgICAgICAgIChmZWF0dXJlKSA9PlxyXG4gICAgICAgICAgICAgICAgdGhpcy5maWx0ZXJPYmplY3RzRm9yVGVybShmZWF0dXJlLmNvbW1lbnRzLml0ZW1zLCB0ZXJtKS5sZW5ndGggPlxyXG4gICAgICAgICAgICAgICAgMCxcclxuICAgICAgICApO1xyXG4gICAgICAgIHJldHVybiBmaWx0ZXJVbmlxdWVBcnJheUJ5SUQoWy4uLmJ5VGl0bGUsIC4uLmJ5Q29tbWVudF0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSBvYmplY3RzIEFycmF5IG9mIENvbW1lbnRzLCBUaWNrZXRzLCBGZWF0dXJlcy4gT2JsaWdhdG9yeSBwcm9wb3J0aWVzOiB0aXRsZSwgZGVzY3JpcHRpb25cclxuICAgICAqIEBwYXJhbSB0ZXJtIHN0cmluZ1xyXG4gICAgICovXHJcbiAgICBmaWx0ZXJPYmplY3RzRm9yVGVybShvYmplY3RzOiBhbnlbXSwgdGVybTogc3RyaW5nKTogYW55W10ge1xyXG4gICAgICAgIC8vIGZpbHRlciB0ZXJtIGluIHRpdGxlXHJcbiAgICAgICAgY29uc3QgYnlUaXRsZSA9IG9iamVjdHMuZmlsdGVyKChmZWF0dXJlKSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnN0IHdvcmRzID0gZmVhdHVyZS50aXRsZS50b0xvd2VyQ2FzZSgpLnNwbGl0KFwiIFwiKTtcclxuICAgICAgICAgICAgcmV0dXJuIChcclxuICAgICAgICAgICAgICAgIHdvcmRzLnNvbWUoXHJcbiAgICAgICAgICAgICAgICAgICAgKHdvcmQpID0+IHdvcmQubGVuZ3RoID4gMiAmJiBsZXZlbnNodGVpbih3b3JkLCB0ZXJtKSA8PSAxLFxyXG4gICAgICAgICAgICAgICAgKSB8fCBmZWF0dXJlLnRpdGxlLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXModGVybSlcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICB9KTtcclxuICAgICAgICAvLyB0ZXJtIHByZXNlbnQgaW4gZGVzY3JpcHRpb25cclxuICAgICAgICBjb25zdCBieURlc2NyaXB0aW9uID0gb2JqZWN0cy5maWx0ZXIoXHJcbiAgICAgICAgICAgIChmZWF0dXJlKSA9PlxyXG4gICAgICAgICAgICAgICAgZmVhdHVyZS5kZXNjcmlwdGlvbiAmJlxyXG4gICAgICAgICAgICAgICAgZmVhdHVyZS5kZXNjcmlwdGlvbi50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHRlcm0pLFxyXG4gICAgICAgICk7XHJcbiAgICAgICAgcmV0dXJuIGZpbHRlclVuaXF1ZUFycmF5QnlJRChbLi4uYnlUaXRsZSwgLi4uYnlEZXNjcmlwdGlvbl0pO1xyXG4gICAgfVxyXG5cclxuICAgIGZpbHRlck1pc3Npb25CeVN0YXJ0VGltZURhdGVGb3JEYXRlUmFuZ2UoXHJcbiAgICAgICAgbWlzc2lvbnM6IGFueVtdLFxyXG4gICAgICAgIGRhdGVSYW5nZTogRGF0ZVtdLFxyXG4gICAgKTogYW55W10ge1xyXG4gICAgICAgIHJldHVybiBtaXNzaW9ucy5maWx0ZXIoKG1pc3Npb24pID0+IHtcclxuICAgICAgICAgICAgY29uc3Qgc3RhcnREYXRlVGltZSA9IG5ldyBEYXRlKG1pc3Npb24uc3RhcnREYXRlVGltZSk7XHJcbiAgICAgICAgICAgIHJldHVybiAoXHJcbiAgICAgICAgICAgICAgICBzdGFydERhdGVUaW1lID49IGRhdGVSYW5nZVswXSAmJiBzdGFydERhdGVUaW1lIDw9IGRhdGVSYW5nZVsxXVxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIGFzeW5jIGFwcGx5Wm9uZUZpbHRlckZvck1pc3Npb25zKFxyXG4gICAgICAgIGN1cnJlbnRTcGFjZU1pc3Npb25zOiBNaXNzaW9uW10sXHJcbiAgICAgICAgb2JqZWN0czogYW55W10sXHJcbiAgICApOiBQcm9taXNlPGFueVtdPiB7XHJcbiAgICAgICAgY29uc3QgYWxsb3dlZFpvbmVzID0gW107XHJcbiAgICAgICAgZm9yIChjb25zdCBtaXNzaW9uIG9mIGN1cnJlbnRTcGFjZU1pc3Npb25zKSB7XHJcbiAgICAgICAgICAgIGlmIChtaXNzaW9uLnpvbmVJRCkge1xyXG4gICAgICAgICAgICAgICAgYWxsb3dlZFpvbmVzLnB1c2gobWlzc2lvbi56b25lSUQpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChhbGxvd2VkWm9uZXMubGVuZ3RoID09PSBjdXJyZW50U3BhY2VNaXNzaW9ucy5sZW5ndGgpIHtcclxuICAgICAgICAgICAgbGV0IGFsbFpvbmVGaWx0ZXJlZCA9IFtdO1xyXG4gICAgICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChcclxuICAgICAgICAgICAgICAgIGFsbG93ZWRab25lcy5tYXAoYXN5bmMgKHpvbmVJRCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRab25lRmlsdGVyZWQgPSBhd2FpdCB0aGlzLmZpbHRlck9iamVjdHNGb3Jab25lKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBvYmplY3RzLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICB6b25lSUQsXHJcbiAgICAgICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgICAgICBhbGxab25lRmlsdGVyZWQgPSBbXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC4uLmFsbFpvbmVGaWx0ZXJlZCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgLi4uY3VycmVudFpvbmVGaWx0ZXJlZCxcclxuICAgICAgICAgICAgICAgICAgICBdO1xyXG4gICAgICAgICAgICAgICAgfSksXHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgIHJldHVybiBmaWx0ZXJVbmlxdWVBcnJheUJ5SUQoYWxsWm9uZUZpbHRlcmVkKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIG9iamVjdHM7XHJcbiAgICB9XHJcblxyXG4gICAgYXN5bmMgZmlsdGVyRXF1aXBtZW50c0ZvckN1cnJlbnRVc2VySW5TcGFjZShcclxuICAgICAgICBzcGFjZUlEOiBzdHJpbmcsXHJcbiAgICAgICAgZXF1aXBzOiBFcXVpcG1lbnRbXSxcclxuICAgICk6IFByb21pc2U8RXF1aXBtZW50W10+IHtcclxuICAgICAgICBjb25zdCBmaW5hbEVxdWlwczogRXF1aXBtZW50W10gPSBbXTtcclxuICAgICAgICBsZXQgZG9tRmlsdGVyZWQ6IEVxdWlwbWVudFtdID0gZXF1aXBzO1xyXG4gICAgICAgIGNvbnN0IHJvbGVGaWx0ZXJlZDogRXF1aXBtZW50W10gPSBlcXVpcHM7XHJcbiAgICAgICAgY29uc3QgbGV2ZWxGaWx0ZXJlZDogRXF1aXBtZW50W10gPSBlcXVpcHM7XHJcbiAgICAgICAgbGV0IHpvbmVGaWx0ZXJlZDogRXF1aXBtZW50W10gPSBlcXVpcHM7XHJcbiAgICAgICAgY29uc3QgbWlzc2lvbnMgPSB0aGlzLnVzZXJTZXJ2aWNlLmN1cnJlbnRNaXNzaW9ucztcclxuICAgICAgICBpZiAobWlzc2lvbnMpIHtcclxuICAgICAgICAgICAgY29uc3QgY3VycmVudFNwYWNlTWlzc2lvbnMgPSBtaXNzaW9ucy5maWx0ZXIoXHJcbiAgICAgICAgICAgICAgICAobSkgPT4gbS5zcGFjZUlEID09PSBzcGFjZUlELFxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgICAgICBpZiAoY3VycmVudFNwYWNlTWlzc2lvbnMubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgaGlnaGVzdExlbGVsID1cclxuICAgICAgICAgICAgICAgICAgICBnZXRIaWdoZXN0TGV2ZWxGb3JNaXNzaW9ucyhjdXJyZW50U3BhY2VNaXNzaW9ucyk7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBoaWdoZXN0Um9sZSA9XHJcbiAgICAgICAgICAgICAgICAgICAgZ2V0SGlnaGVzdFJvbGVGb3JNaXNzaW9ucyhjdXJyZW50U3BhY2VNaXNzaW9ucyk7XHJcbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIkhpZ2hlc3QgbGV2ZWw6IFwiLCBoaWdoZXN0TGVsZWwsIFwiLCBIaWdoZXN0IFJvbGU6IFwiLCBoaWdoZXN0Um9sZSlcclxuXHJcbiAgICAgICAgICAgICAgICBjb25zdCBmaWx0ZXJzID0gdGhpcy5nZXRGaWx0ZXJzRm9yUm9sZShoaWdoZXN0Um9sZSk7XHJcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGZpbHRlciBvZiBmaWx0ZXJzKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGZpbHRlciA9PT0gRmlsdGVyVHlwZS5ET01BSU4pIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGRvbWFpbnM6IHN0cmluZ1tdID0gW107XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgbSBvZiBjdXJyZW50U3BhY2VNaXNzaW9ucykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobS5kb21haW5zKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9tYWlucyA9IFsuLi5kb21haW5zLCAuLi5tLmRvbWFpbnNdO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgYWxsRG9tYWluc0ZpbHRlcmVkID0gW107XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjdXJyZW50RG9tRmlsdGVyZWQgPVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5maWx0ZXJFcXVpcG1lbnRzQnlEb21haW5MaXN0KGVxdWlwcywgZG9tYWlucyk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGFsbERvbWFpbnNGaWx0ZXJlZCA9IFtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLmFsbERvbWFpbnNGaWx0ZXJlZCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLmN1cnJlbnREb21GaWx0ZXJlZCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgXTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZG9tRmlsdGVyZWQgPSBhbGxEb21haW5zRmlsdGVyZWQ7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChmaWx0ZXIgPT09IEZpbHRlclR5cGUuUk9MRSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBjb25zdCBoaWdoZXN0Um9sZU1pc3Npb24gPSBjdXJyZW50U3BhY2VNaXNzaW9ucy5maW5kKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAgKG0pID0+IG0ucm9sZSA9PT0gaGlnaGVzdFJvbGUsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRPRE9cclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChmaWx0ZXIgPT09IEZpbHRlclR5cGUuTEVWRUwpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVE9ETywgZXF1aXBtZW50IGRvZXMgbm90IGhhdmUgbGV2ZWxcclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChmaWx0ZXIgPT09IEZpbHRlclR5cGUuWk9ORSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB6b25lRmlsdGVyZWQgPSBhd2FpdCB0aGlzLmFwcGx5Wm9uZUZpbHRlckZvck1pc3Npb25zKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudFNwYWNlTWlzc2lvbnMsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcXVpcHMsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCB0aWMgb2YgbGV2ZWxGaWx0ZXJlZCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChcclxuICAgICAgICAgICAgICAgICAgICAgICAgZG9tRmlsdGVyZWQuaW5jbHVkZXModGljKSAmJlxyXG4gICAgICAgICAgICAgICAgICAgICAgICByb2xlRmlsdGVyZWQuaW5jbHVkZXModGljKSAmJlxyXG4gICAgICAgICAgICAgICAgICAgICAgICB6b25lRmlsdGVyZWQuaW5jbHVkZXModGljKVxyXG4gICAgICAgICAgICAgICAgICAgICkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBmaW5hbEVxdWlwcy5wdXNoKHRpYyk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBmaW5hbEVxdWlwcztcclxuICAgIH1cclxuXHJcbiAgICBhc3luYyBmaWx0ZXJNZWFzdXJlbWVudHNGb3JDdXJyZW50VXNlckluU3BhY2UoXHJcbiAgICAgICAgc3BhY2VJRDogc3RyaW5nLFxyXG4gICAgICAgIGNvbW1lbnRzOiBDb21tZW50W10sXHJcbiAgICApOiBQcm9taXNlPENvbW1lbnRbXT4ge1xyXG4gICAgICAgIGxldCBmaW5hbE1lYXN1cmVtZW50czogQ29tbWVudFtdID0gW107XHJcbiAgICAgICAgbGV0IHpvbmVGaWx0ZXJlZDogQ29tbWVudFtdID0gY29tbWVudHM7XHJcbiAgICAgICAgY29uc3QgbWlzc2lvbnMgPSB0aGlzLnVzZXJTZXJ2aWNlLmN1cnJlbnRNaXNzaW9ucztcclxuICAgICAgICBpZiAobWlzc2lvbnMpIHtcclxuICAgICAgICAgICAgY29uc3QgY3VycmVudFNwYWNlTWlzc2lvbnMgPSBtaXNzaW9ucy5maWx0ZXIoXHJcbiAgICAgICAgICAgICAgICAobSkgPT4gbS5zcGFjZUlEID09PSBzcGFjZUlELFxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgICAgICBpZiAoY3VycmVudFNwYWNlTWlzc2lvbnMubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgaGlnaGVzdFJvbGUgPVxyXG4gICAgICAgICAgICAgICAgICAgIGdldEhpZ2hlc3RSb2xlRm9yTWlzc2lvbnMoY3VycmVudFNwYWNlTWlzc2lvbnMpO1xyXG5cclxuICAgICAgICAgICAgICAgIGNvbnN0IGZpbHRlcnMgPSB0aGlzLmdldEZpbHRlcnNGb3JSb2xlKGhpZ2hlc3RSb2xlKTtcclxuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZmlsdGVyIG9mIGZpbHRlcnMpIHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoZmlsdGVyID09PSBGaWx0ZXJUeXBlLlpPTkUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgem9uZUZpbHRlcmVkID0gYXdhaXQgdGhpcy5hcHBseVpvbmVGaWx0ZXJGb3JNaXNzaW9ucyhcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRTcGFjZU1pc3Npb25zLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tbWVudHMsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgZmluYWxNZWFzdXJlbWVudHMgPSB6b25lRmlsdGVyZWQ7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIGZpbmFsTWVhc3VyZW1lbnRzO1xyXG4gICAgfVxyXG5cclxuICAgIGFzeW5jIGlzT2JqZWN0QWxsb3dlZEZvclVzZXJJblNwYWNlKFxyXG4gICAgICAgIG9iamVjdDogT2JqZWN0LFxyXG4gICAgICAgIHNwYWNlSUQ6IHN0cmluZyxcclxuICAgICk6IFByb21pc2U8Ym9vbGVhbj4ge1xyXG4gICAgICAgIGNvbnN0IG1pc3Npb24gPSB0aGlzLnVzZXJTZXJ2aWNlLmN1cnJlbnRNaXNzaW9uKHNwYWNlSUQpO1xyXG4gICAgICAgIGNvbnN0IGZpbHRlcnMgPSB0aGlzLmdldEZpbHRlcnNGb3JSb2xlKG1pc3Npb24ucm9sZSk7XHJcbiAgICAgICAgZm9yIChjb25zdCBmaWx0ZXIgb2YgZmlsdGVycykge1xyXG4gICAgICAgICAgICBpZiAoXHJcbiAgICAgICAgICAgICAgICBmaWx0ZXIgPT09IEZpbHRlclR5cGUuTEVWRUwgJiZcclxuICAgICAgICAgICAgICAgIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIFwibGV2ZWxcIilcclxuICAgICAgICAgICAgKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBsZXZlbEZpbHRlcmVkID0gdGhpcy5maWx0ZXJPYmplY3RzQnlMZXZlbChcclxuICAgICAgICAgICAgICAgICAgICBbb2JqZWN0XSxcclxuICAgICAgICAgICAgICAgICAgICBtaXNzaW9uLmxldmVsLFxyXG4gICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgIGlmIChsZXZlbEZpbHRlcmVkLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBpZiAoZmlsdGVyID09PSBGaWx0ZXJUeXBlLlpPTkUpIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHpvbmVGaWx0ZXJlZCA9IGF3YWl0IHRoaXMuYXBwbHlab25lRmlsdGVyRm9yTWlzc2lvbnMoXHJcbiAgICAgICAgICAgICAgICAgICAgW21pc3Npb25dLFxyXG4gICAgICAgICAgICAgICAgICAgIFtvYmplY3RdLFxyXG4gICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgIGlmICh6b25lRmlsdGVyZWQubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgfVxyXG5cclxuICAgIGZpbHRlclRlbXBsYXRlc0ZvclRlcm0obWlzc2lvbnM6IE1pc3Npb25bXSwgdGVybTogc3RyaW5nKTogTWlzc2lvbltdIHtcclxuICAgICAgICAvLyB0ZXJtIHByZXNlbnQgaW4gZGVzY3JpcHRpb25cclxuICAgICAgICBjb25zdCBieURlc2NyaXB0aW9uID0gbWlzc2lvbnMuZmlsdGVyKFxyXG4gICAgICAgICAgICAobWlzKSA9PlxyXG4gICAgICAgICAgICAgICAgbWlzLmRlc2NyaXB0aW9uICYmIG1pcy5kZXNjcmlwdGlvbi50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHRlcm0pLFxyXG4gICAgICAgICk7XHJcbiAgICAgICAgLy8gYnkgdXNlciBsYXN0TmFtZSB3aGljaCBpcyB0aGUgbmFtZSBvZiB0aGUgdmlzaXQ6XHJcbiAgICAgICAgLy8gbWV0YWRhdGE6IFwie1xcXCJmaXJzdE5hbWVcXFwiOlxcXCJcXFwiLFxcXCJsYXN0TmFtZVxcXCI6XFxcIlZpc2l0ZSBkdSA1IEp1aWxsZXRcXFwifVwiXHJcbiAgICAgICAgY29uc3QgdXNlclByb2ZpbGVzID0gbWlzc2lvbnMubWFwKChtaXMpID0+IG5ldyBQcm9maWxlRW50aXR5KG1pcy51c2VyKSk7XHJcbiAgICAgICAgY29uc3QgYnlVc2VyTGFzdG5hbWUgPSB0aGlzLmZpbHRlclVzZXJzRm9yVGVybSh1c2VyUHJvZmlsZXMsIHRlcm0pO1xyXG4gICAgICAgIGNvbnN0IHVzZXJJZHMgPSBuZXcgU2V0KGJ5VXNlckxhc3RuYW1lLm1hcCgodXNlcikgPT4gdXNlci5pZCkpO1xyXG4gICAgICAgIGNvbnN0IG1pc3Npb25zQnlVc2VyID0gbWlzc2lvbnMuZmlsdGVyKChtaXMpID0+XHJcbiAgICAgICAgICAgIHVzZXJJZHMuaGFzKG1pcy51c2VySUQpLFxyXG4gICAgICAgICk7XHJcbiAgICAgICAgcmV0dXJuIGZpbHRlclVuaXF1ZUFycmF5QnlJRChbLi4uYnlEZXNjcmlwdGlvbiwgLi4ubWlzc2lvbnNCeVVzZXJdKTtcclxuICAgIH1cclxuXHJcbiAgICBhc3luYyBmaWx0ZXJPYmplY3RzRm9yU3dlZXAoXHJcbiAgICAgICAgb2JqZWN0czogYW55W10sXHJcbiAgICAgICAgb2JqZWN0VHlwZTogUG9pVHlwZSxcclxuICAgICAgICBzd2VlcDogc3RyaW5nLFxyXG4gICAgKTogUHJvbWlzZTxhbnlbXT4ge1xyXG4gICAgICAgIGxldCBmaWx0ZXJlZCA9IFtdO1xyXG4gICAgICAgIHN3aXRjaCAob2JqZWN0VHlwZSkge1xyXG4gICAgICAgICAgICBjYXNlIFBvaVR5cGUuRVFVSVBNRU5UOlxyXG4gICAgICAgICAgICAgICAgY29uc3QgcG9pcyA9XHJcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5wb2lTZXJ2aWNlLmdldFBvaXNCeU1hdHRlcnBvcnRTd2VlcEJ5VHlwZShcclxuICAgICAgICAgICAgICAgICAgICAgICAgc3dlZXAsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdFR5cGUsXHJcbiAgICAgICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGVxdWlwSURzID0gbmV3IFNldChwb2lzLm1hcCgocG9pKSA9PiBwb2kuZWxlbWVudElEKSk7XHJcbiAgICAgICAgICAgICAgICBmaWx0ZXJlZCA9IG9iamVjdHMuZmlsdGVyKChvYmplY3QpID0+IGVxdWlwSURzLmhhcyhvYmplY3QuaWQpKTtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBkZWZhdWx0OlxyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBmaWx0ZXJlZDtcclxuICAgIH1cclxuXHJcbiAgICBmaWx0ZXJGZWF0dXJlc0J5SGFzaHRhZ3NBbmRMb2NhbGUoXHJcbiAgICAgICAgY3VycmVudFNwYWNlTWlzc2lvbnM6IE1pc3Npb25bXSxcclxuICAgICAgICBmZWF0dXJlczogRmVhdHVyZVtdLFxyXG4gICAgKTogRmVhdHVyZVtdIHtcclxuICAgICAgICBjb25zdCBbY3VycmVudE1pc3Npb25dID0gY3VycmVudFNwYWNlTWlzc2lvbnM7XHJcbiAgICAgICAgLy8gZmlsdGVyIGJ5IGxvY2FsZVxyXG4gICAgICAgIGxldCBmaWx0ZXJlZExvY2FsZSA9IFsuLi5mZWF0dXJlc107XHJcbiAgICAgICAgaWYgKGN1cnJlbnRNaXNzaW9uLmxvY2FsZSkge1xyXG4gICAgICAgICAgICBmaWx0ZXJlZExvY2FsZSA9IGZlYXR1cmVzLmZpbHRlcihcclxuICAgICAgICAgICAgICAgIChmZWF0dXJlKSA9PlxyXG4gICAgICAgICAgICAgICAgICAgIGZlYXR1cmUubG9jYWxlICYmIGZlYXR1cmUubG9jYWxlID09PSBjdXJyZW50TWlzc2lvbi5sb2NhbGUsXHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIC8vIGZpbHRlciBieSBoYXNodGFnc1xyXG4gICAgICAgIGlmIChjdXJyZW50TWlzc2lvbi5oYXNodGFncyAmJiBjdXJyZW50TWlzc2lvbi5oYXNodGFncy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGZpbHRlcmVkQnlIYXNodGFncyA9IFtdO1xyXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGZlYXR1cmUgb2YgZmlsdGVyZWRMb2NhbGUpIHtcclxuICAgICAgICAgICAgICAgIGlmICghZmVhdHVyZS5oYXNodGFncyB8fCBmZWF0dXJlLmhhc2h0YWdzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIEZlYXR1cmUgd2l0aG91dCBoYXNodGFnIGlzIGF2YWlsYWJsZSBmb3IgZXZlcnlib2R5XHJcbiAgICAgICAgICAgICAgICAgICAgZmlsdGVyZWRCeUhhc2h0YWdzLnB1c2goZmVhdHVyZSk7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKFxyXG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRNaXNzaW9uLmhhc2h0YWdzLmV2ZXJ5KChoYXNodGFnKSA9PlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlLmhhc2h0YWdzLmluY2x1ZGVzKGhhc2h0YWcpLFxyXG4gICAgICAgICAgICAgICAgICAgIClcclxuICAgICAgICAgICAgICAgICkge1xyXG4gICAgICAgICAgICAgICAgICAgIGZpbHRlcmVkQnlIYXNodGFncy5wdXNoKGZlYXR1cmUpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJldHVybiBmaWx0ZXJlZEJ5SGFzaHRhZ3M7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBmaWx0ZXJlZExvY2FsZTtcclxuICAgIH1cclxuXHJcbiAgICBmaWx0ZXJGZWF0dXJlc0Zvck1pc3Npb25XaXRob3V0Wm9uZShcclxuICAgICAgICBmZWF0dXJlczogRmVhdHVyZVtdLFxyXG4gICAgICAgIG1pc3Npb246IE1pc3Npb24sXHJcbiAgICApOiBGZWF0dXJlW10ge1xyXG4gICAgICAgIGNvbnN0IGZpbmFsRmVhdHVyZXM6IEZlYXR1cmVbXSA9IFtdO1xyXG4gICAgICAgIGxldCBsZXZlbEZpbHRlcmVkOiBGZWF0dXJlW10gPSBmZWF0dXJlcztcclxuICAgICAgICBsZXQgem9uZUZpbHRlcmVkOiBGZWF0dXJlW10gPSBmZWF0dXJlcztcclxuICAgICAgICBsZXQgaGFzaHRhZ0ZpbHRlcmVkOiBGZWF0dXJlW10gPSBmZWF0dXJlcztcclxuXHJcbiAgICAgICAgY29uc3QgZmlsdGVycyA9IHRoaXMuZ2V0RmlsdGVyc0ZvclJvbGUobWlzc2lvbi5yb2xlKTtcclxuICAgICAgICBmb3IgKGNvbnN0IGZpbHRlciBvZiBmaWx0ZXJzKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGZpbHRlciA9PT0gRmlsdGVyVHlwZS5MRVZFTCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXZlbEZpbHRlcmVkID0gdGhpcy5maWx0ZXJPYmplY3RzQnlMZXZlbChcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWlzc2lvbi5sZXZlbCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gaWYgKGZpbHRlciA9PT0gRmlsdGVyVHlwZS5aT05FKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gICAgIHpvbmVGaWx0ZXJlZCA9IGF3YWl0IHRoaXMuYXBwbHlab25lRmlsdGVyRm9yTWlzc2lvbnMoXHJcbiAgICAgICAgICAgICAgICAgICAgLy8gICAgICAgICBjdXJyZW50U3BhY2VNaXNzaW9ucyxcclxuICAgICAgICAgICAgICAgICAgICAvLyAgICAgICAgIGZlYXR1cmVzLFxyXG4gICAgICAgICAgICAgICAgICAgIC8vICAgICApO1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAoZmlsdGVyID09PSBGaWx0ZXJUeXBlLkhBU0hUQUcpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaGFzaHRhZ0ZpbHRlcmVkID1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZmlsdGVyRmVhdHVyZXNCeUhhc2h0YWdzQW5kTG9jYWxlKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFttaXNzaW9uXSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgIGZvciAoY29uc3QgZmVhdHVyZSBvZiBsZXZlbEZpbHRlcmVkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBoYXNodGFnRmlsdGVyZWQuaW5jbHVkZXMoZmVhdHVyZSkgJiZcclxuICAgICAgICAgICAgICAgICAgICAgICAgem9uZUZpbHRlcmVkLmluY2x1ZGVzKGZlYXR1cmUpXHJcbiAgICAgICAgICAgICAgICAgICAgKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsRmVhdHVyZXMucHVzaChmZWF0dXJlKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBmaW5hbEZlYXR1cmVzO1xyXG4gICAgfVxyXG59XHJcbiJdfQ==
|
|
1
|
+
/* eslint-disable no-case-declarations */
|
|
2
|
+
/* eslint-disable no-await-in-loop */
|
|
3
|
+
/* eslint-disable guard-for-in */
|
|
4
|
+
/* eslint-disable class-methods-use-this */
|
|
5
|
+
import { Injectable } from "@angular/core";
|
|
6
|
+
import { Subject } from "rxjs";
|
|
7
|
+
import { getLevelsBelow, getHighestLevelForMissions, getHighestRoleForMissions, filterUniqueArrayByID } from "../helpers.service";
|
|
8
|
+
import { PoiType, ProfileEntity, RoleStatus } from "../types.service";
|
|
9
|
+
import levenshtein from 'js-levenshtein';
|
|
10
|
+
import * as i0 from "@angular/core";
|
|
11
|
+
import * as i1 from "./user.service";
|
|
12
|
+
import * as i2 from "./models/zone.service";
|
|
13
|
+
import * as i3 from "./models/poi.service";
|
|
14
|
+
var FilterType;
|
|
15
|
+
(function (FilterType) {
|
|
16
|
+
FilterType["DOMAIN"] = "DOMAIN";
|
|
17
|
+
FilterType["LEVEL"] = "LEVEL";
|
|
18
|
+
FilterType["ROLE"] = "ROLE";
|
|
19
|
+
FilterType["ZONE"] = "ZONE";
|
|
20
|
+
FilterType["SPACE"] = "SPACE";
|
|
21
|
+
FilterType["HASHTAG"] = "HASHTAG";
|
|
22
|
+
})(FilterType || (FilterType = {}));
|
|
23
|
+
export class FilterService {
|
|
24
|
+
constructor(userService, zoneService, poiService) {
|
|
25
|
+
this.userService = userService;
|
|
26
|
+
this.zoneService = zoneService;
|
|
27
|
+
this.poiService = poiService;
|
|
28
|
+
this.updateDateFilter = new Subject();
|
|
29
|
+
}
|
|
30
|
+
filterTicketsByDomain(ticketsToFilter, domain) {
|
|
31
|
+
return ticketsToFilter.filter((tic) => tic.domainID === domain);
|
|
32
|
+
}
|
|
33
|
+
filterObjectsByLevel(objectsToFilter, level) {
|
|
34
|
+
const visibleLevels = getLevelsBelow(level);
|
|
35
|
+
const filtered = objectsToFilter.filter((tic) => visibleLevels.includes(tic.level));
|
|
36
|
+
return filtered;
|
|
37
|
+
}
|
|
38
|
+
filterTicketsForMission(ticketsToFilter, mission) {
|
|
39
|
+
const managerRoles = [
|
|
40
|
+
RoleStatus.MANAGER,
|
|
41
|
+
RoleStatus.ADMIN,
|
|
42
|
+
RoleStatus.OWNER,
|
|
43
|
+
];
|
|
44
|
+
if (!managerRoles.includes(mission.role)) {
|
|
45
|
+
if (mission.role === RoleStatus.SERVICE) {
|
|
46
|
+
// SERVICE can see tickets to which he is assigned
|
|
47
|
+
const ticketsAssigned = [];
|
|
48
|
+
for (const t of ticketsToFilter) {
|
|
49
|
+
if (t.assignees.items.length > 0) {
|
|
50
|
+
for (const assignment of t.assignees.items) {
|
|
51
|
+
if (assignment.missionID === mission.id) {
|
|
52
|
+
ticketsAssigned.push(t);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return ticketsAssigned;
|
|
58
|
+
}
|
|
59
|
+
// OCCUPANT and VISITOR can see only tickets that they created
|
|
60
|
+
return ticketsToFilter.filter((ticket) => {
|
|
61
|
+
return ticket.ownerMissionID === mission.id;
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
return ticketsToFilter;
|
|
65
|
+
}
|
|
66
|
+
getFiltersForRole(role) {
|
|
67
|
+
switch (role) {
|
|
68
|
+
case RoleStatus.ADMIN:
|
|
69
|
+
return [FilterType.LEVEL];
|
|
70
|
+
case RoleStatus.MANAGER:
|
|
71
|
+
return [FilterType.ZONE, FilterType.LEVEL];
|
|
72
|
+
case RoleStatus.OWNER:
|
|
73
|
+
return [FilterType.ZONE, FilterType.LEVEL];
|
|
74
|
+
case RoleStatus.SERVICE:
|
|
75
|
+
return [
|
|
76
|
+
FilterType.ZONE,
|
|
77
|
+
FilterType.LEVEL,
|
|
78
|
+
FilterType.DOMAIN,
|
|
79
|
+
FilterType.ROLE, // that is the most severe filter
|
|
80
|
+
];
|
|
81
|
+
case RoleStatus.OCCUPANT:
|
|
82
|
+
return [
|
|
83
|
+
FilterType.ZONE,
|
|
84
|
+
FilterType.DOMAIN,
|
|
85
|
+
FilterType.ROLE,
|
|
86
|
+
FilterType.LEVEL,
|
|
87
|
+
FilterType.HASHTAG,
|
|
88
|
+
];
|
|
89
|
+
case RoleStatus.VISITOR:
|
|
90
|
+
return [
|
|
91
|
+
FilterType.ZONE,
|
|
92
|
+
FilterType.LEVEL,
|
|
93
|
+
FilterType.DOMAIN,
|
|
94
|
+
FilterType.ROLE,
|
|
95
|
+
FilterType.HASHTAG,
|
|
96
|
+
];
|
|
97
|
+
case RoleStatus.VISITOR_MUSEUM:
|
|
98
|
+
return [FilterType.ZONE, FilterType.LEVEL, FilterType.HASHTAG];
|
|
99
|
+
case RoleStatus.GUIDE_MUSEUM:
|
|
100
|
+
return [FilterType.LEVEL];
|
|
101
|
+
default:
|
|
102
|
+
return [FilterType.LEVEL];
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
async filterObjectsForCurrentUserInSpace(objects, spaceID) {
|
|
106
|
+
const finalObject3Ds = [];
|
|
107
|
+
let domFiltered = objects;
|
|
108
|
+
let levelFiltered = objects;
|
|
109
|
+
let zoneFiltered = objects;
|
|
110
|
+
const missions = this.userService.currentMissions;
|
|
111
|
+
if (missions) {
|
|
112
|
+
const currentSpaceMissions = missions.filter((m) => m.spaceID === spaceID);
|
|
113
|
+
if (currentSpaceMissions.length > 0) {
|
|
114
|
+
for (const obj of levelFiltered) {
|
|
115
|
+
if (domFiltered.includes(obj) &&
|
|
116
|
+
zoneFiltered.includes(obj)) {
|
|
117
|
+
finalObject3Ds.push(obj);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return finalObject3Ds;
|
|
123
|
+
}
|
|
124
|
+
async filterTicketsForCurrentUserInSpace(tickets, spaceID) {
|
|
125
|
+
const finalTickets = [];
|
|
126
|
+
let domFiltered = tickets;
|
|
127
|
+
let roleFiltered = tickets;
|
|
128
|
+
let levelFiltered = tickets;
|
|
129
|
+
let zoneFiltered = tickets;
|
|
130
|
+
const missions = this.userService.currentMissions;
|
|
131
|
+
if (missions) {
|
|
132
|
+
const currentSpaceMissions = missions.filter((m) => m.spaceID === spaceID);
|
|
133
|
+
if (currentSpaceMissions.length > 0) {
|
|
134
|
+
const highestLelel = getHighestLevelForMissions(currentSpaceMissions);
|
|
135
|
+
const highestRole = getHighestRoleForMissions(currentSpaceMissions);
|
|
136
|
+
// console.log("Highest level: ", highestLelel, ", Highest Role: ", highestRole)
|
|
137
|
+
const filters = this.getFiltersForRole(highestRole);
|
|
138
|
+
for (const filter of filters) {
|
|
139
|
+
if (filter === FilterType.DOMAIN) {
|
|
140
|
+
let domains = [];
|
|
141
|
+
for (const m of currentSpaceMissions) {
|
|
142
|
+
if (m.domains) {
|
|
143
|
+
domains = [...domains, ...m.domains];
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
let allDomainsFiltered = [];
|
|
147
|
+
for (const d of domains) {
|
|
148
|
+
const currentDomFiltered = this.filterTicketsByDomain(tickets, d);
|
|
149
|
+
allDomainsFiltered = [
|
|
150
|
+
...allDomainsFiltered,
|
|
151
|
+
...currentDomFiltered,
|
|
152
|
+
];
|
|
153
|
+
}
|
|
154
|
+
domFiltered = allDomainsFiltered;
|
|
155
|
+
}
|
|
156
|
+
if (filter === FilterType.ROLE) {
|
|
157
|
+
const highestRoleMission = currentSpaceMissions.find((m) => m.role === highestRole);
|
|
158
|
+
roleFiltered = this.filterTicketsForMission(tickets, highestRoleMission);
|
|
159
|
+
}
|
|
160
|
+
if (filter === FilterType.LEVEL) {
|
|
161
|
+
levelFiltered = this.filterObjectsByLevel(tickets, highestLelel);
|
|
162
|
+
}
|
|
163
|
+
if (filter === FilterType.ZONE) {
|
|
164
|
+
zoneFiltered = await this.applyZoneFilterForMissions(currentSpaceMissions, tickets);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
// keep only tickets present in all filtered arrays
|
|
168
|
+
// console.log(domFiltered);
|
|
169
|
+
// console.log(roleFiltered);
|
|
170
|
+
// console.log(levelFiltered);
|
|
171
|
+
// console.log(zoneFiltered);
|
|
172
|
+
for (const tic of levelFiltered) {
|
|
173
|
+
if (domFiltered.includes(tic) &&
|
|
174
|
+
roleFiltered.includes(tic) &&
|
|
175
|
+
zoneFiltered.includes(tic)) {
|
|
176
|
+
finalTickets.push(tic);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
// console.log(finalTickets);
|
|
182
|
+
return finalTickets;
|
|
183
|
+
}
|
|
184
|
+
subscribeToDataFilterUpdate(next, error, complete) {
|
|
185
|
+
const s = this.updateDateFilter.subscribe(next, error, complete);
|
|
186
|
+
return s;
|
|
187
|
+
}
|
|
188
|
+
dateFilterUpdated(dateRange) {
|
|
189
|
+
this.currentDateFilter = dateRange;
|
|
190
|
+
this.updateDateFilter.next(dateRange);
|
|
191
|
+
}
|
|
192
|
+
filterObjectsForDateRange(objects, dateRange) {
|
|
193
|
+
return objects.filter((object) => {
|
|
194
|
+
const createdAtDate = new Date(object.createdAt);
|
|
195
|
+
return (createdAtDate >= dateRange[0] && createdAtDate <= dateRange[1]);
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
filterMeasurementsForDateRange(measurements, dateRange) {
|
|
199
|
+
return measurements.filter((measure) => {
|
|
200
|
+
const createdAtDate = new Date(measure.comment.createdAt);
|
|
201
|
+
return (createdAtDate >= dateRange[0] && createdAtDate <= dateRange[1]);
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
async filterObjectsForZone(objects, // TODO: remove any here..
|
|
205
|
+
zoneID = null, zone = null) {
|
|
206
|
+
const filteredObjects = [];
|
|
207
|
+
await Promise.all(objects.map(async (object) => {
|
|
208
|
+
const [poi] = object.pois.items;
|
|
209
|
+
if (poi && zone) {
|
|
210
|
+
if (zone.sweepIDs && zone.sweepIDs.includes(poi.matterportSweepID)) {
|
|
211
|
+
if (this.poiService.poiIsVirtual(poi) && zone.layer && zone.layer.name === "FLOOR") {
|
|
212
|
+
// we include in Floor zone only
|
|
213
|
+
filteredObjects.push(object);
|
|
214
|
+
}
|
|
215
|
+
if (!this.poiService.poiIsVirtual(poi)) {
|
|
216
|
+
filteredObjects.push(object);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
if (poi && !zone && zoneID) {
|
|
221
|
+
const zones = await this.zoneService.getZonesForObject(object);
|
|
222
|
+
if (zones &&
|
|
223
|
+
zones.some((zone_) => zone_.id === zoneID ||
|
|
224
|
+
zone_.parentID === zoneID)) {
|
|
225
|
+
filteredObjects.push(object);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}));
|
|
229
|
+
return filteredObjects;
|
|
230
|
+
}
|
|
231
|
+
filterEquipmentsByDomainList(equipments, domainIDList) {
|
|
232
|
+
let filtered = [];
|
|
233
|
+
const filteredByDomain = equipments.filter((equip) => domainIDList.includes(equip.domainID));
|
|
234
|
+
filtered = [...filtered, ...filteredByDomain];
|
|
235
|
+
const filteredByParentDomain = equipments.filter((equip) => equip.domain &&
|
|
236
|
+
equip.domain.parentID &&
|
|
237
|
+
domainIDList.includes(equip.domain.parentID));
|
|
238
|
+
filtered = [...filtered, ...filteredByParentDomain];
|
|
239
|
+
return filterUniqueArrayByID(filtered);
|
|
240
|
+
}
|
|
241
|
+
// Not implemented yet!
|
|
242
|
+
// filterObjects3DByDomainList(
|
|
243
|
+
// objects3D: Object3D[],
|
|
244
|
+
// domainIDList: string[],
|
|
245
|
+
// ): Object3D[] {
|
|
246
|
+
// let filtered = [];
|
|
247
|
+
// const filteredByDomain = objects3D.filter((equip) =>
|
|
248
|
+
// domainIDList.includes(equip.domainID),
|
|
249
|
+
// );
|
|
250
|
+
// filtered = [...filtered, ...filteredByDomain];
|
|
251
|
+
// const filteredByParentDomain = objects3D.filter(
|
|
252
|
+
// (obj) =>
|
|
253
|
+
// obj.domain &&
|
|
254
|
+
// obj.domain.parentID &&
|
|
255
|
+
// domainIDList.includes(obj.domain.parentID),
|
|
256
|
+
// );
|
|
257
|
+
// filtered = [...filtered, ...filteredByParentDomain];
|
|
258
|
+
// return filterUniqueArrayByID(filtered);
|
|
259
|
+
// }
|
|
260
|
+
filterEquipmentsForTerm(equips, term) {
|
|
261
|
+
// filter domains
|
|
262
|
+
let byDomain = equips.filter((eq) => {
|
|
263
|
+
if (eq.domain && eq.domain.name) {
|
|
264
|
+
const normalizedDomain = eq.domain.name.toLowerCase();
|
|
265
|
+
const lev = levenshtein(normalizedDomain, term);
|
|
266
|
+
return lev <= 2 || normalizedDomain.includes(term);
|
|
267
|
+
}
|
|
268
|
+
return false;
|
|
269
|
+
});
|
|
270
|
+
const byParentDomain = equips.filter((eq) => {
|
|
271
|
+
if (eq.domain && eq.domain.parentID) {
|
|
272
|
+
const normalizedParent = eq.domain.parent.name.toLowerCase();
|
|
273
|
+
const lev = levenshtein(normalizedParent, term);
|
|
274
|
+
return lev <= 2 || normalizedParent.includes(term);
|
|
275
|
+
}
|
|
276
|
+
return false;
|
|
277
|
+
});
|
|
278
|
+
byDomain = [...byDomain, ...byParentDomain];
|
|
279
|
+
// filter name
|
|
280
|
+
let byName = [];
|
|
281
|
+
const terms = term.split(" ").filter((token) => token.length > 2);
|
|
282
|
+
for (const eq of equips) {
|
|
283
|
+
const words = eq.name
|
|
284
|
+
.toLowerCase()
|
|
285
|
+
.split(" ")
|
|
286
|
+
.filter((token) => token.length > 2);
|
|
287
|
+
const matched = [];
|
|
288
|
+
for (const token of terms) {
|
|
289
|
+
for (const word of words) {
|
|
290
|
+
if (levenshtein(token, word) <= 1) {
|
|
291
|
+
matched.push(true);
|
|
292
|
+
break;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
if (matched.length === terms.length) {
|
|
297
|
+
byName.push(eq);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
const byNameSimple = equips.filter((eq) => eq.name.toLowerCase().includes(term));
|
|
301
|
+
byName = [...byName, ...byNameSimple];
|
|
302
|
+
// by serial number
|
|
303
|
+
const bySerialNumber = equips.filter((eq) => eq.serialNumber && eq.serialNumber.toLowerCase() === term);
|
|
304
|
+
const result = [...byDomain, ...byName, ...bySerialNumber];
|
|
305
|
+
return filterUniqueArrayByID(result);
|
|
306
|
+
}
|
|
307
|
+
filterTicketsForTerm(tickets, term) {
|
|
308
|
+
// filter term in title and description
|
|
309
|
+
const byTitle = this.filterObjectsForTerm(tickets, term);
|
|
310
|
+
// by equipment
|
|
311
|
+
const byEquipment = tickets.filter((ticket) => ticket.equipments &&
|
|
312
|
+
this.filterEquipmentsForTerm(ticket.equipments, term).length >
|
|
313
|
+
0);
|
|
314
|
+
return filterUniqueArrayByID([...byTitle, ...byEquipment]);
|
|
315
|
+
}
|
|
316
|
+
filterLocationsForTerm(locations, term) {
|
|
317
|
+
// by name
|
|
318
|
+
const byName = locations.filter((loc) => loc.name.toLowerCase().includes(term));
|
|
319
|
+
// by address
|
|
320
|
+
const byAddress = locations.filter((loc) => loc.addresses.toLowerCase().includes(term));
|
|
321
|
+
return filterUniqueArrayByID([...byName, ...byAddress]);
|
|
322
|
+
}
|
|
323
|
+
filterOrganisationsForTerm(orgs, term) {
|
|
324
|
+
const byName = orgs.filter((org) => {
|
|
325
|
+
const words = org.name.toLowerCase().split(" ");
|
|
326
|
+
return (words.some((word) => word.length > 2 && levenshtein(word, term) <= 1) || org.name.toLowerCase().includes(term));
|
|
327
|
+
});
|
|
328
|
+
return byName;
|
|
329
|
+
}
|
|
330
|
+
filterUsersForTerm(users, term) {
|
|
331
|
+
const byName = users.filter((user) => {
|
|
332
|
+
const words = user.displayName.toLowerCase().split(" ");
|
|
333
|
+
return (words.some((word) => word.length > 2 && levenshtein(word, term) <= 1) || user.displayName.toLowerCase().includes(term));
|
|
334
|
+
});
|
|
335
|
+
return byName;
|
|
336
|
+
}
|
|
337
|
+
async filterFeaturesForCurrentUserInSpace(features, spaceID) {
|
|
338
|
+
const finalFeatures = [];
|
|
339
|
+
let levelFiltered = features;
|
|
340
|
+
let zoneFiltered = features;
|
|
341
|
+
let hashtagFiltered = features;
|
|
342
|
+
const missions = this.userService.currentMissions;
|
|
343
|
+
if (missions) {
|
|
344
|
+
const currentSpaceMissions = missions.filter((m) => m.spaceID === spaceID);
|
|
345
|
+
if (currentSpaceMissions.length > 0) {
|
|
346
|
+
const highestLelel = getHighestLevelForMissions(currentSpaceMissions);
|
|
347
|
+
const highestRole = getHighestRoleForMissions(currentSpaceMissions);
|
|
348
|
+
const filters = this.getFiltersForRole(highestRole);
|
|
349
|
+
for (const filter of filters) {
|
|
350
|
+
if (filter === FilterType.LEVEL) {
|
|
351
|
+
levelFiltered = this.filterObjectsByLevel(features, highestLelel);
|
|
352
|
+
}
|
|
353
|
+
if (filter === FilterType.ZONE) {
|
|
354
|
+
zoneFiltered = await this.applyZoneFilterForMissions(currentSpaceMissions, features);
|
|
355
|
+
}
|
|
356
|
+
if (filter === FilterType.HASHTAG) {
|
|
357
|
+
hashtagFiltered =
|
|
358
|
+
this.filterFeaturesByHashtagsAndLocale(currentSpaceMissions, features);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
for (const feature of levelFiltered) {
|
|
362
|
+
if (hashtagFiltered.includes(feature) &&
|
|
363
|
+
zoneFiltered.includes(feature)) {
|
|
364
|
+
finalFeatures.push(feature);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
return finalFeatures;
|
|
370
|
+
}
|
|
371
|
+
filterFeaturesForTerm(features, term) {
|
|
372
|
+
// filter term in title
|
|
373
|
+
const byTitle = this.filterObjectsForTerm(features, term);
|
|
374
|
+
// by comments
|
|
375
|
+
const byComment = features.filter((feature) => this.filterObjectsForTerm(feature.comments.items, term).length >
|
|
376
|
+
0);
|
|
377
|
+
return filterUniqueArrayByID([...byTitle, ...byComment]);
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
*
|
|
381
|
+
* @param objects Array of Comments, Tickets, Features. Obligatory proporties: title, description
|
|
382
|
+
* @param term string
|
|
383
|
+
*/
|
|
384
|
+
filterObjectsForTerm(objects, term) {
|
|
385
|
+
// filter term in title
|
|
386
|
+
const byTitle = objects.filter((feature) => {
|
|
387
|
+
const words = feature.title.toLowerCase().split(" ");
|
|
388
|
+
return (words.some((word) => word.length > 2 && levenshtein(word, term) <= 1) || feature.title.toLowerCase().includes(term));
|
|
389
|
+
});
|
|
390
|
+
// term present in description
|
|
391
|
+
const byDescription = objects.filter((feature) => feature.description &&
|
|
392
|
+
feature.description.toLowerCase().includes(term));
|
|
393
|
+
return filterUniqueArrayByID([...byTitle, ...byDescription]);
|
|
394
|
+
}
|
|
395
|
+
filterMissionByStartTimeDateForDateRange(missions, dateRange) {
|
|
396
|
+
return missions.filter((mission) => {
|
|
397
|
+
const startDateTime = new Date(mission.startDateTime);
|
|
398
|
+
return (startDateTime >= dateRange[0] && startDateTime <= dateRange[1]);
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
async applyZoneFilterForMissions(currentSpaceMissions, objects) {
|
|
402
|
+
const allowedZones = [];
|
|
403
|
+
for (const mission of currentSpaceMissions) {
|
|
404
|
+
if (mission.zoneID) {
|
|
405
|
+
allowedZones.push(mission.zoneID);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
if (allowedZones.length === currentSpaceMissions.length) {
|
|
409
|
+
let allZoneFiltered = [];
|
|
410
|
+
await Promise.all(allowedZones.map(async (zoneID) => {
|
|
411
|
+
const currentZoneFiltered = await this.filterObjectsForZone(objects, zoneID);
|
|
412
|
+
allZoneFiltered = [
|
|
413
|
+
...allZoneFiltered,
|
|
414
|
+
...currentZoneFiltered,
|
|
415
|
+
];
|
|
416
|
+
}));
|
|
417
|
+
return filterUniqueArrayByID(allZoneFiltered);
|
|
418
|
+
}
|
|
419
|
+
return objects;
|
|
420
|
+
}
|
|
421
|
+
async filterEquipmentsForCurrentUserInSpace(spaceID, equips) {
|
|
422
|
+
const finalEquips = [];
|
|
423
|
+
let domFiltered = equips;
|
|
424
|
+
const roleFiltered = equips;
|
|
425
|
+
const levelFiltered = equips;
|
|
426
|
+
let zoneFiltered = equips;
|
|
427
|
+
const missions = this.userService.currentMissions;
|
|
428
|
+
if (missions) {
|
|
429
|
+
const currentSpaceMissions = missions.filter((m) => m.spaceID === spaceID);
|
|
430
|
+
if (currentSpaceMissions.length > 0) {
|
|
431
|
+
const highestLelel = getHighestLevelForMissions(currentSpaceMissions);
|
|
432
|
+
const highestRole = getHighestRoleForMissions(currentSpaceMissions);
|
|
433
|
+
// console.log("Highest level: ", highestLelel, ", Highest Role: ", highestRole)
|
|
434
|
+
const filters = this.getFiltersForRole(highestRole);
|
|
435
|
+
for (const filter of filters) {
|
|
436
|
+
if (filter === FilterType.DOMAIN) {
|
|
437
|
+
let domains = [];
|
|
438
|
+
for (const m of currentSpaceMissions) {
|
|
439
|
+
if (m.domains) {
|
|
440
|
+
domains = [...domains, ...m.domains];
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
let allDomainsFiltered = [];
|
|
444
|
+
const currentDomFiltered = this.filterEquipmentsByDomainList(equips, domains);
|
|
445
|
+
allDomainsFiltered = [
|
|
446
|
+
...allDomainsFiltered,
|
|
447
|
+
...currentDomFiltered,
|
|
448
|
+
];
|
|
449
|
+
domFiltered = allDomainsFiltered;
|
|
450
|
+
}
|
|
451
|
+
if (filter === FilterType.ROLE) {
|
|
452
|
+
// const highestRoleMission = currentSpaceMissions.find(
|
|
453
|
+
// (m) => m.role === highestRole,
|
|
454
|
+
// );
|
|
455
|
+
// TODO
|
|
456
|
+
}
|
|
457
|
+
if (filter === FilterType.LEVEL) {
|
|
458
|
+
// TODO, equipment does not have level
|
|
459
|
+
}
|
|
460
|
+
if (filter === FilterType.ZONE) {
|
|
461
|
+
zoneFiltered = await this.applyZoneFilterForMissions(currentSpaceMissions, equips);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
for (const tic of levelFiltered) {
|
|
465
|
+
if (domFiltered.includes(tic) &&
|
|
466
|
+
roleFiltered.includes(tic) &&
|
|
467
|
+
zoneFiltered.includes(tic)) {
|
|
468
|
+
finalEquips.push(tic);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
return finalEquips;
|
|
474
|
+
}
|
|
475
|
+
async filterMeasurementsForCurrentUserInSpace(spaceID, comments) {
|
|
476
|
+
let finalMeasurements = [];
|
|
477
|
+
let zoneFiltered = comments;
|
|
478
|
+
const missions = this.userService.currentMissions;
|
|
479
|
+
if (missions) {
|
|
480
|
+
const currentSpaceMissions = missions.filter((m) => m.spaceID === spaceID);
|
|
481
|
+
if (currentSpaceMissions.length > 0) {
|
|
482
|
+
const highestRole = getHighestRoleForMissions(currentSpaceMissions);
|
|
483
|
+
const filters = this.getFiltersForRole(highestRole);
|
|
484
|
+
for (const filter of filters) {
|
|
485
|
+
if (filter === FilterType.ZONE) {
|
|
486
|
+
zoneFiltered = await this.applyZoneFilterForMissions(currentSpaceMissions, comments);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
finalMeasurements = zoneFiltered;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
return finalMeasurements;
|
|
493
|
+
}
|
|
494
|
+
async isObjectAllowedForUserInSpace(object, spaceID) {
|
|
495
|
+
const mission = this.userService.currentMission(spaceID);
|
|
496
|
+
const filters = this.getFiltersForRole(mission.role);
|
|
497
|
+
for (const filter of filters) {
|
|
498
|
+
if (filter === FilterType.LEVEL &&
|
|
499
|
+
Object.prototype.hasOwnProperty.call(object, "level")) {
|
|
500
|
+
const levelFiltered = this.filterObjectsByLevel([object], mission.level);
|
|
501
|
+
if (levelFiltered.length === 0) {
|
|
502
|
+
return false;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
if (filter === FilterType.ZONE) {
|
|
506
|
+
const zoneFiltered = await this.applyZoneFilterForMissions([mission], [object]);
|
|
507
|
+
if (zoneFiltered.length === 0) {
|
|
508
|
+
return false;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
return true;
|
|
513
|
+
}
|
|
514
|
+
filterTemplatesForTerm(missions, term) {
|
|
515
|
+
// term present in description
|
|
516
|
+
const byDescription = missions.filter((mis) => mis.description && mis.description.toLowerCase().includes(term));
|
|
517
|
+
// by user lastName which is the name of the visit:
|
|
518
|
+
// metadata: "{\"firstName\":\"\",\"lastName\":\"Visite du 5 Juillet\"}"
|
|
519
|
+
const userProfiles = missions.map((mis) => new ProfileEntity(mis.user));
|
|
520
|
+
const byUserLastname = this.filterUsersForTerm(userProfiles, term);
|
|
521
|
+
const userIds = new Set(byUserLastname.map((user) => user.id));
|
|
522
|
+
const missionsByUser = missions.filter((mis) => userIds.has(mis.userID));
|
|
523
|
+
return filterUniqueArrayByID([...byDescription, ...missionsByUser]);
|
|
524
|
+
}
|
|
525
|
+
async filterObjectsForSweep(objects, objectType, sweep) {
|
|
526
|
+
let filtered = [];
|
|
527
|
+
switch (objectType) {
|
|
528
|
+
case PoiType.EQUIPMENT:
|
|
529
|
+
const pois = await this.poiService.getPoisByMatterportSweepByType(sweep, objectType);
|
|
530
|
+
const equipIDs = new Set(pois.map((poi) => poi.elementID));
|
|
531
|
+
filtered = objects.filter((object) => equipIDs.has(object.id));
|
|
532
|
+
break;
|
|
533
|
+
default:
|
|
534
|
+
break;
|
|
535
|
+
}
|
|
536
|
+
return filtered;
|
|
537
|
+
}
|
|
538
|
+
filterFeaturesByHashtagsAndLocale(currentSpaceMissions, features) {
|
|
539
|
+
const [currentMission] = currentSpaceMissions;
|
|
540
|
+
// filter by locale
|
|
541
|
+
let filteredLocale = [...features];
|
|
542
|
+
if (currentMission.locale) {
|
|
543
|
+
filteredLocale = features.filter((feature) => feature.locale && feature.locale === currentMission.locale);
|
|
544
|
+
}
|
|
545
|
+
// filter by hashtags
|
|
546
|
+
if (currentMission.hashtags && currentMission.hashtags.length > 0) {
|
|
547
|
+
const filteredByHashtags = [];
|
|
548
|
+
for (const feature of filteredLocale) {
|
|
549
|
+
if (!feature.hashtags || feature.hashtags.length === 0) {
|
|
550
|
+
// Feature without hashtag is available for everybody
|
|
551
|
+
filteredByHashtags.push(feature);
|
|
552
|
+
}
|
|
553
|
+
else if (currentMission.hashtags.every((hashtag) => feature.hashtags.includes(hashtag))) {
|
|
554
|
+
filteredByHashtags.push(feature);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
return filteredByHashtags;
|
|
558
|
+
}
|
|
559
|
+
return filteredLocale;
|
|
560
|
+
}
|
|
561
|
+
filterFeaturesForMissionWithoutZone(features, mission) {
|
|
562
|
+
const finalFeatures = [];
|
|
563
|
+
let levelFiltered = features;
|
|
564
|
+
let zoneFiltered = features;
|
|
565
|
+
let hashtagFiltered = features;
|
|
566
|
+
const filters = this.getFiltersForRole(mission.role);
|
|
567
|
+
for (const filter of filters) {
|
|
568
|
+
if (filter === FilterType.LEVEL) {
|
|
569
|
+
levelFiltered = this.filterObjectsByLevel(features, mission.level);
|
|
570
|
+
}
|
|
571
|
+
// if (filter === FilterType.ZONE) {
|
|
572
|
+
// zoneFiltered = await this.applyZoneFilterForMissions(
|
|
573
|
+
// currentSpaceMissions,
|
|
574
|
+
// features,
|
|
575
|
+
// );
|
|
576
|
+
// }
|
|
577
|
+
if (filter === FilterType.HASHTAG) {
|
|
578
|
+
hashtagFiltered =
|
|
579
|
+
this.filterFeaturesByHashtagsAndLocale([mission], features);
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
for (const feature of levelFiltered) {
|
|
583
|
+
if (hashtagFiltered.includes(feature) &&
|
|
584
|
+
zoneFiltered.includes(feature)) {
|
|
585
|
+
finalFeatures.push(feature);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
return finalFeatures;
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
FilterService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: FilterService, deps: [{ token: i1.BaseUserService }, { token: i2.ZoneService }, { token: i3.PoiService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
592
|
+
FilterService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: FilterService, providedIn: "root" });
|
|
593
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: FilterService, decorators: [{
|
|
594
|
+
type: Injectable,
|
|
595
|
+
args: [{
|
|
596
|
+
providedIn: "root",
|
|
597
|
+
}]
|
|
598
|
+
}], ctorParameters: function () { return [{ type: i1.BaseUserService }, { type: i2.ZoneService }, { type: i3.PoiService }]; } });
|
|
599
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsdGVyLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtc21hcnRlcnBsYW4tY29yZS9zcmMvbGliL3NlcnZpY2VzL2ZpbHRlci5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLHlDQUF5QztBQUN6QyxxQ0FBcUM7QUFDckMsaUNBQWlDO0FBQ2pDLDJDQUEyQztBQUMzQyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNDLE9BQU8sRUFBRSxPQUFPLEVBQWdCLE1BQU0sTUFBTSxDQUFDO0FBQzdDLE9BQU8sRUFBRSxjQUFjLEVBQUUsMEJBQTBCLEVBQUUseUJBQXlCLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNsSSxPQUFPLEVBT0wsT0FBTyxFQUNQLGFBQWEsRUFDYixVQUFVLEVBT1gsTUFBTSxrQkFBa0IsQ0FBQztBQVkxQixPQUFPLFdBQVcsTUFBTSxnQkFBZ0IsQ0FBQzs7Ozs7QUFSekMsSUFBSyxVQU9KO0FBUEQsV0FBSyxVQUFVO0lBQ1gsK0JBQWlCLENBQUE7SUFDakIsNkJBQWUsQ0FBQTtJQUNmLDJCQUFhLENBQUE7SUFDYiwyQkFBYSxDQUFBO0lBQ2IsNkJBQWUsQ0FBQTtJQUNmLGlDQUFtQixDQUFBO0FBQ3ZCLENBQUMsRUFQSSxVQUFVLEtBQVYsVUFBVSxRQU9kO0FBS0QsTUFBTSxPQUFPLGFBQWE7SUFLdEIsWUFDWSxXQUE0QixFQUM1QixXQUF3QixFQUN4QixVQUFzQjtRQUZ0QixnQkFBVyxHQUFYLFdBQVcsQ0FBaUI7UUFDNUIsZ0JBQVcsR0FBWCxXQUFXLENBQWE7UUFDeEIsZUFBVSxHQUFWLFVBQVUsQ0FBWTtRQVAxQixxQkFBZ0IsR0FBb0IsSUFBSSxPQUFPLEVBQUUsQ0FBQztJQVF2RCxDQUFDO0lBRUoscUJBQXFCLENBQUMsZUFBeUIsRUFBRSxNQUFjO1FBQzNELE9BQU8sZUFBZSxDQUFDLE1B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Q1IsVUFBVSxFQUFFLE1BQU07aUJBQ3JCIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgbm8tY2FzZS1kZWNsYXJhdGlvbnMgKi9cbi8qIGVzbGludC1kaXNhYmxlIG5vLWF3YWl0LWluLWxvb3AgKi9cbi8qIGVzbGludC1kaXNhYmxlIGd1YXJkLWZvci1pbiAqL1xuLyogZXNsaW50LWRpc2FibGUgY2xhc3MtbWV0aG9kcy11c2UtdGhpcyAqL1xuaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgeyBTdWJqZWN0LCBTdWJzY3JpcHRpb24gfSBmcm9tIFwicnhqc1wiO1xuaW1wb3J0IHsgZ2V0TGV2ZWxzQmVsb3csIGdldEhpZ2hlc3RMZXZlbEZvck1pc3Npb25zLCBnZXRIaWdoZXN0Um9sZUZvck1pc3Npb25zLCBmaWx0ZXJVbmlxdWVBcnJheUJ5SUQgfSBmcm9tIFwiLi4vaGVscGVycy5zZXJ2aWNlXCI7XG5pbXBvcnQge1xuICBab25lLFxuICBFcXVpcG1lbnQsXG4gIExldmVsU3RhdHVzLFxuICBNZWFzdXJlbWVudCxcbiAgTWlzc2lvbixcbiAgT3JnYW5pc2F0aW9uLFxuICBQb2lUeXBlLFxuICBQcm9maWxlRW50aXR5LFxuICBSb2xlU3RhdHVzLFxuICBTcGFjZSxcbiAgVGlja2V0LFxuICBEYk9iamVjdFR5cGUsXG4gIEZlYXR1cmUsXG4gIENvbW1lbnQsXG4gIFZpc2l0VGVtcGxhdGUsIE9iamVjdDNEXG59IGZyb20gXCIuLi90eXBlcy5zZXJ2aWNlXCI7XG5pbXBvcnQgeyBQb2lTZXJ2aWNlIH0gZnJvbSBcIi4vbW9kZWxzL3BvaS5zZXJ2aWNlXCI7XG5pbXBvcnQgeyBab25lU2VydmljZSB9IGZyb20gXCIuL21vZGVscy96b25lLnNlcnZpY2VcIjtcbmltcG9ydCB7IEJhc2VVc2VyU2VydmljZSB9IGZyb20gXCIuL3VzZXIuc2VydmljZVwiO1xuZW51bSBGaWx0ZXJUeXBlIHtcbiAgICBET01BSU4gPSBcIkRPTUFJTlwiLFxuICAgIExFVkVMID0gXCJMRVZFTFwiLFxuICAgIFJPTEUgPSBcIlJPTEVcIixcbiAgICBaT05FID0gXCJaT05FXCIsXG4gICAgU1BBQ0UgPSBcIlNQQUNFXCIsXG4gICAgSEFTSFRBRyA9IFwiSEFTSFRBR1wiLFxufVxuaW1wb3J0IGxldmVuc2h0ZWluIGZyb20gJ2pzLWxldmVuc2h0ZWluJztcbkBJbmplY3RhYmxlKHtcbiAgICBwcm92aWRlZEluOiBcInJvb3RcIixcbn0pXG5leHBvcnQgY2xhc3MgRmlsdGVyU2VydmljZSB7XG4gICAgcHJpdmF0ZSB1cGRhdGVEYXRlRmlsdGVyOiBTdWJqZWN0PERhdGVbXT4gPSBuZXcgU3ViamVjdCgpO1xuXG4gICAgcHVibGljIGN1cnJlbnREYXRlRmlsdGVyOiBEYXRlW107XG5cbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgcHJpdmF0ZSB1c2VyU2VydmljZTogQmFzZVVzZXJTZXJ2aWNlLFxuICAgICAgICBwcml2YXRlIHpvbmVTZXJ2aWNlOiBab25lU2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSBwb2lTZXJ2aWNlOiBQb2lTZXJ2aWNlLFxuICAgICkge31cblxuICAgIGZpbHRlclRpY2tldHNCeURvbWFpbih0aWNrZXRzVG9GaWx0ZXI6IFRpY2tldFtdLCBkb21haW46IHN0cmluZykge1xuICAgICAgICByZXR1cm4gdGlja2V0c1RvRmlsdGVyLmZpbHRlcigodGljKSA9PiB0aWMuZG9tYWluSUQgPT09IGRvbWFpbik7XG4gICAgfVxuXG4gICAgZmlsdGVyT2JqZWN0c0J5TGV2ZWwob2JqZWN0c1RvRmlsdGVyOiBhbnlbXSwgbGV2ZWw6IExldmVsU3RhdHVzKTogYW55W10ge1xuICAgICAgICBjb25zdCB2aXNpYmxlTGV2ZWxzID0gZ2V0TGV2ZWxzQmVsb3cobGV2ZWwpO1xuICAgICAgICBjb25zdCBmaWx0ZXJlZCA9IG9iamVjdHNUb0ZpbHRlci5maWx0ZXIoKHRpYykgPT5cbiAgICAgICAgICAgIHZpc2libGVMZXZlbHMuaW5jbHVkZXModGljLmxldmVsKSxcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIGZpbHRlcmVkO1xuICAgIH1cblxuICAgIGZpbHRlclRpY2tldHNGb3JNaXNzaW9uKFxuICAgICAgICB0aWNrZXRzVG9GaWx0ZXI6IFRpY2tldFtdLFxuICAgICAgICBtaXNzaW9uOiBNaXNzaW9uLFxuICAgICk6IFRpY2tldFtdIHtcbiAgICAgICAgY29uc3QgbWFuYWdlclJvbGVzOiBSb2xlU3RhdHVzW10gPSBbXG4gICAgICAgICAgICBSb2xlU3RhdHVzLk1BTkFHRVIsXG4gICAgICAgICAgICBSb2xlU3RhdHVzLkFETUlOLFxuICAgICAgICAgICAgUm9sZVN0YXR1cy5PV05FUixcbiAgICAgICAgXTtcbiAgICAgICAgaWYgKCFtYW5hZ2VyUm9sZXMuaW5jbHVkZXMobWlzc2lvbi5yb2xlKSkge1xuICAgICAgICAgICAgaWYgKG1pc3Npb24ucm9sZSA9PT0gUm9sZVN0YXR1cy5TRVJWSUNFKSB7XG4gICAgICAgICAgICAgICAgLy8gU0VSVklDRSBjYW4gc2VlIHRpY2tldHMgdG8gd2hpY2ggaGUgaXMgYXNzaWduZWRcbiAgICAgICAgICAgICAgICBjb25zdCB0aWNrZXRzQXNzaWduZWQgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHQgb2YgdGlja2V0c1RvRmlsdGVyKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0LmFzc2lnbmVlcy5pdGVtcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGFzc2lnbm1lbnQgb2YgdC5hc3NpZ25lZXMuaXRlbXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXNzaWdubWVudC5taXNzaW9uSUQgPT09IG1pc3Npb24uaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGlja2V0c0Fzc2lnbmVkLnB1c2godCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0aWNrZXRzQXNzaWduZWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBPQ0NVUEFOVCBhbmQgVklTSVRPUiBjYW4gc2VlIG9ubHkgdGlja2V0cyB0aGF0IHRoZXkgY3JlYXRlZFxuICAgICAgICAgICAgcmV0dXJuIHRpY2tldHNUb0ZpbHRlci5maWx0ZXIoKHRpY2tldCkgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aWNrZXQub3duZXJNaXNzaW9uSUQgPT09IG1pc3Npb24uaWQ7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGlja2V0c1RvRmlsdGVyO1xuICAgIH1cblxuICAgIGdldEZpbHRlcnNGb3JSb2xlKHJvbGU6IFJvbGVTdGF0dXMpOiBGaWx0ZXJUeXBlW10ge1xuICAgICAgICBzd2l0Y2ggKHJvbGUpIHtcbiAgICAgICAgICAgIGNhc2UgUm9sZVN0YXR1cy5BRE1JTjpcbiAgICAgICAgICAgICAgICByZXR1cm4gW0ZpbHRlclR5cGUuTEVWRUxdO1xuICAgICAgICAgICAgY2FzZSBSb2xlU3RhdHVzLk1BTkFHRVI6XG4gICAgICAgICAgICAgICAgcmV0dXJuIFtGaWx0ZXJUeXBlLlpPTkUsIEZpbHRlclR5cGUuTEVWRUxdO1xuICAgICAgICAgICAgY2FzZSBSb2xlU3RhdHVzLk9XTkVSOlxuICAgICAgICAgICAgICAgIHJldHVybiBbRmlsdGVyVHlwZS5aT05FLCBGaWx0ZXJUeXBlLkxFVkVMXTtcbiAgICAgICAgICAgIGNhc2UgUm9sZVN0YXR1cy5TRVJWSUNFOlxuICAgICAgICAgICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICAgICAgICAgIEZpbHRlclR5cGUuWk9ORSxcbiAgICAgICAgICAgICAgICAgICAgRmlsdGVyVHlwZS5MRVZFTCxcbiAgICAgICAgICAgICAgICAgICAgRmlsdGVyVHlwZS5ET01BSU4sXG4gICAgICAgICAgICAgICAgICAgIEZpbHRlclR5cGUuUk9MRSwgLy8gdGhhdCBpcyB0aGUgbW9zdCBzZXZlcmUgZmlsdGVyXG4gICAgICAgICAgICAgICAgXTtcbiAgICAgICAgICAgIGNhc2UgUm9sZVN0YXR1cy5PQ0NVUEFOVDpcbiAgICAgICAgICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgICAgICAgICBGaWx0ZXJUeXBlLlpPTkUsXG4gICAgICAgICAgICAgICAgICAgIEZpbHRlclR5cGUuRE9NQUlOLFxuICAgICAgICAgICAgICAgICAgICBGaWx0ZXJUeXBlLlJPTEUsXG4gICAgICAgICAgICAgICAgICAgIEZpbHRlclR5cGUuTEVWRUwsXG4gICAgICAgICAgICAgICAgICAgIEZpbHRlclR5cGUuSEFTSFRBRyxcbiAgICAgICAgICAgICAgICBdO1xuICAgICAgICAgICAgY2FzZSBSb2xlU3RhdHVzLlZJU0lUT1I6XG4gICAgICAgICAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgICAgICAgICAgRmlsdGVyVHlwZS5aT05FLFxuICAgICAgICAgICAgICAgICAgICBGaWx0ZXJUeXBlLkxFVkVMLFxuICAgICAgICAgICAgICAgICAgICBGaWx0ZXJUeXBlLkRPTUFJTixcbiAgICAgICAgICAgICAgICAgICAgRmlsdGVyVHlwZS5ST0xFLFxuICAgICAgICAgICAgICAgICAgICBGaWx0ZXJUeXBlLkhBU0hUQUcsXG4gICAgICAgICAgICAgICAgXTtcbiAgICAgICAgICAgIGNhc2UgUm9sZVN0YXR1cy5WSVNJVE9SX01VU0VVTTpcbiAgICAgICAgICAgICAgICByZXR1cm4gW0ZpbHRlclR5cGUuWk9ORSwgRmlsdGVyVHlwZS5MRVZFTCwgRmlsdGVyVHlwZS5IQVNIVEFHXTtcbiAgICAgICAgICAgIGNhc2UgUm9sZVN0YXR1cy5HVUlERV9NVVNFVU06XG4gICAgICAgICAgICAgICAgcmV0dXJuIFtGaWx0ZXJUeXBlLkxFVkVMXTtcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgcmV0dXJuIFtGaWx0ZXJUeXBlLkxFVkVMXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGFzeW5jIGZpbHRlck9iamVjdHNGb3JDdXJyZW50VXNlckluU3BhY2UoXG4gICAgICAgIG9iamVjdHM6IE9iamVjdDNEW10sXG4gICAgICAgIHNwYWNlSUQ6IHN0cmluZyxcbiAgICApOiBQcm9taXNlPE9iamVjdDNEW10+IHtcbiAgICAgICAgY29uc3QgZmluYWxPYmplY3QzRHM6IE9iamVjdDNEW10gPSBbXTtcbiAgICAgICAgbGV0IGRvbUZpbHRlcmVkOiBPYmplY3QzRFtdID0gb2JqZWN0cztcbiAgICAgICAgbGV0IGxldmVsRmlsdGVyZWQ6IE9iamVjdDNEW10gPSBvYmplY3RzO1xuICAgICAgICBsZXQgem9uZUZpbHRlcmVkOiBPYmplY3QzRFtdID0gb2JqZWN0cztcbiAgICAgICAgY29uc3QgbWlzc2lvbnMgPSB0aGlzLnVzZXJTZXJ2aWNlLmN1cnJlbnRNaXNzaW9ucztcbiAgICAgICAgaWYgKG1pc3Npb25zKSB7XG4gICAgICAgICAgICBjb25zdCBjdXJyZW50U3BhY2VNaXNzaW9ucyA9IG1pc3Npb25zLmZpbHRlcihcbiAgICAgICAgICAgICAgICAobSkgPT4gbS5zcGFjZUlEID09PSBzcGFjZUlELFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGlmIChjdXJyZW50U3BhY2VNaXNzaW9ucy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBvYmogb2YgbGV2ZWxGaWx0ZXJlZCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgICAgICBkb21GaWx0ZXJlZC5pbmNsdWRlcyhvYmopICYmXG4gICAgICAgICAgICAgICAgICAgICAgICB6b25lRmlsdGVyZWQuaW5jbHVkZXMob2JqKVxuICAgICAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsT2JqZWN0M0RzLnB1c2gob2JqKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmluYWxPYmplY3QzRHM7XG4gICAgfVxuXG4gICAgYXN5bmMgZmlsdGVyVGlja2V0c0ZvckN1cnJlbnRVc2VySW5TcGFjZShcbiAgICAgICAgdGlja2V0czogVGlja2V0W10sXG4gICAgICAgIHNwYWNlSUQ6IHN0cmluZyxcbiAgICApOiBQcm9taXNlPFRpY2tldFtdPiB7XG4gICAgICAgIGNvbnN0IGZpbmFsVGlja2V0czogVGlja2V0W10gPSBbXTtcbiAgICAgICAgbGV0IGRvbUZpbHRlcmVkOiBUaWNrZXRbXSA9IHRpY2tldHM7XG4gICAgICAgIGxldCByb2xlRmlsdGVyZWQ6IFRpY2tldFtdID0gdGlja2V0cztcbiAgICAgICAgbGV0IGxldmVsRmlsdGVyZWQ6IFRpY2tldFtdID0gdGlja2V0cztcbiAgICAgICAgbGV0IHpvbmVGaWx0ZXJlZDogVGlja2V0W10gPSB0aWNrZXRzO1xuICAgICAgICBjb25zdCBtaXNzaW9ucyA9IHRoaXMudXNlclNlcnZpY2UuY3VycmVudE1pc3Npb25zO1xuICAgICAgICBpZiAobWlzc2lvbnMpIHtcbiAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRTcGFjZU1pc3Npb25zID0gbWlzc2lvbnMuZmlsdGVyKFxuICAgICAgICAgICAgICAgIChtKSA9PiBtLnNwYWNlSUQgPT09IHNwYWNlSUQsXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgaWYgKGN1cnJlbnRTcGFjZU1pc3Npb25zLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBjb25zdCBoaWdoZXN0TGVsZWwgPVxuICAgICAgICAgICAgICAgICAgICBnZXRIaWdoZXN0TGV2ZWxGb3JNaXNzaW9ucyhjdXJyZW50U3BhY2VNaXNzaW9ucyk7XG4gICAgICAgICAgICAgICAgY29uc3QgaGlnaGVzdFJvbGUgPVxuICAgICAgICAgICAgICAgICAgICBnZXRIaWdoZXN0Um9sZUZvck1pc3Npb25zKGN1cnJlbnRTcGFjZU1pc3Npb25zKTtcbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIkhpZ2hlc3QgbGV2ZWw6IFwiLCBoaWdoZXN0TGVsZWwsIFwiLCBIaWdoZXN0IFJvbGU6IFwiLCBoaWdoZXN0Um9sZSlcblxuICAgICAgICAgICAgICAgIGNvbnN0IGZpbHRlcnMgPSB0aGlzLmdldEZpbHRlcnNGb3JSb2xlKGhpZ2hlc3RSb2xlKTtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGZpbHRlciBvZiBmaWx0ZXJzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChmaWx0ZXIgPT09IEZpbHRlclR5cGUuRE9NQUlOKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgZG9tYWluczogc3RyaW5nW10gPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgbSBvZiBjdXJyZW50U3BhY2VNaXNzaW9ucykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtLmRvbWFpbnMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9tYWlucyA9IFsuLi5kb21haW5zLCAuLi5tLmRvbWFpbnNdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBhbGxEb21haW5zRmlsdGVyZWQgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZCBvZiBkb21haW5zKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY3VycmVudERvbUZpbHRlcmVkID1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5maWx0ZXJUaWNrZXRzQnlEb21haW4odGlja2V0cywgZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxsRG9tYWluc0ZpbHRlcmVkID0gW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5hbGxEb21haW5zRmlsdGVyZWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLmN1cnJlbnREb21GaWx0ZXJlZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZG9tRmlsdGVyZWQgPSBhbGxEb21haW5zRmlsdGVyZWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGZpbHRlciA9PT0gRmlsdGVyVHlwZS5ST0xFKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBoaWdoZXN0Um9sZU1pc3Npb24gPSBjdXJyZW50U3BhY2VNaXNzaW9ucy5maW5kKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChtKSA9PiBtLnJvbGUgPT09IGhpZ2hlc3RSb2xlLFxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvbGVGaWx0ZXJlZCA9IHRoaXMuZmlsdGVyVGlja2V0c0Zvck1pc3Npb24oXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGlja2V0cyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoaWdoZXN0Um9sZU1pc3Npb24sXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGZpbHRlciA9PT0gRmlsdGVyVHlwZS5MRVZFTCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxGaWx0ZXJlZCA9IHRoaXMuZmlsdGVyT2JqZWN0c0J5TGV2ZWwoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGlja2V0cyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoaWdoZXN0TGVsZWwsXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGZpbHRlciA9PT0gRmlsdGVyVHlwZS5aT05FKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB6b25lRmlsdGVyZWQgPSBhd2FpdCB0aGlzLmFwcGx5Wm9uZUZpbHRlckZvck1pc3Npb25zKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRTcGFjZU1pc3Npb25zLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpY2tldHMsXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIGtlZXAgb25seSB0aWNrZXRzIHByZXNlbnQgaW4gYWxsIGZpbHRlcmVkIGFycmF5c1xuICAgICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKGRvbUZpbHRlcmVkKTtcbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhyb2xlRmlsdGVyZWQpO1xuICAgICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKGxldmVsRmlsdGVyZWQpO1xuICAgICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKHpvbmVGaWx0ZXJlZCk7XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCB0aWMgb2YgbGV2ZWxGaWx0ZXJlZCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgICAgICBkb21GaWx0ZXJlZC5pbmNsdWRlcyh0aWMpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICByb2xlRmlsdGVyZWQuaW5jbHVkZXModGljKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgem9uZUZpbHRlcmVkLmluY2x1ZGVzKHRpYylcbiAgICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFRpY2tldHMucHVzaCh0aWMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKGZpbmFsVGlja2V0cyk7XG4gICAgICAgIHJldHVybiBmaW5hbFRpY2tldHM7XG4gICAgfVxuXG4gICAgc3Vic2NyaWJlVG9EYXRhRmlsdGVyVXBkYXRlKFxuICAgICAgICBuZXh0PzogKHZhbHVlOiBhbnkpID0+IHZvaWQsXG4gICAgICAgIGVycm9yPzogKGVycm9yOiBhbnkpID0+IHZvaWQsXG4gICAgICAgIGNvbXBsZXRlPzogKCkgPT4gdm9pZCxcbiAgICApOiBTdWJzY3JpcHRpb24ge1xuICAgICAgICBjb25zdCBzID0gdGhpcy51cGRhdGVEYXRlRmlsdGVyLnN1YnNjcmliZShuZXh0LCBlcnJvciwgY29tcGxldGUpO1xuICAgICAgICByZXR1cm4gcztcbiAgICB9XG5cbiAgICBkYXRlRmlsdGVyVXBkYXRlZChkYXRlUmFuZ2U6IERhdGVbXSB8IG51bGwpIHtcbiAgICAgICAgdGhpcy5jdXJyZW50RGF0ZUZpbHRlciA9IGRhdGVSYW5nZTtcbiAgICAgICAgdGhpcy51cGRhdGVEYXRlRmlsdGVyLm5leHQoZGF0ZVJhbmdlKTtcbiAgICB9XG5cbiAgICBmaWx0ZXJPYmplY3RzRm9yRGF0ZVJhbmdlKG9iamVjdHM6IGFueVtdLCBkYXRlUmFuZ2U6IERhdGVbXSk6IGFueVtdIHtcbiAgICAgICAgcmV0dXJuIG9iamVjdHMuZmlsdGVyKChvYmplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNyZWF0ZWRBdERhdGUgPSBuZXcgRGF0ZShvYmplY3QuY3JlYXRlZEF0KTtcbiAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgY3JlYXRlZEF0RGF0ZSA+PSBkYXRlUmFuZ2VbMF0gJiYgY3JlYXRlZEF0RGF0ZSA8PSBkYXRlUmFuZ2VbMV1cbiAgICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGZpbHRlck1lYXN1cmVtZW50c0ZvckRhdGVSYW5nZShcbiAgICAgICAgbWVhc3VyZW1lbnRzOiBNZWFzdXJlbWVudFtdLFxuICAgICAgICBkYXRlUmFuZ2U6IERhdGVbXSxcbiAgICApOiBNZWFzdXJlbWVudFtdIHtcbiAgICAgICAgcmV0dXJuIG1lYXN1cmVtZW50cy5maWx0ZXIoKG1lYXN1cmUpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNyZWF0ZWRBdERhdGUgPSBuZXcgRGF0ZShtZWFzdXJlLmNvbW1lbnQuY3JlYXRlZEF0KTtcbiAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgY3JlYXRlZEF0RGF0ZSA+PSBkYXRlUmFuZ2VbMF0gJiYgY3JlYXRlZEF0RGF0ZSA8PSBkYXRlUmFuZ2VbMV1cbiAgICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGFzeW5jIGZpbHRlck9iamVjdHNGb3Jab25lKFxuICAgICAgICBvYmplY3RzOiBhbnlbXSwgLy8gVE9ETzogcmVtb3ZlIGFueSBoZXJlLi5cbiAgICAgICAgem9uZUlEOiBzdHJpbmcgPSBudWxsLFxuICAgICAgICB6b25lOiBab25lID0gbnVsbCxcbiAgICApOiBQcm9taXNlPGFueVtdPiB7XG4gICAgICAgIGNvbnN0IGZpbHRlcmVkT2JqZWN0cyA9IFtdO1xuICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgICAgIG9iamVjdHMubWFwKGFzeW5jIChvYmplY3QpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBbcG9pXSA9IG9iamVjdC5wb2lzLml0ZW1zO1xuICAgICAgICAgICAgICAgIGlmIChwb2kgJiYgem9uZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoem9uZS5zd2VlcElEcyAmJiB6b25lLnN3ZWVwSURzLmluY2x1ZGVzKHBvaS5tYXR0ZXJwb3J0U3dlZXBJRCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnBvaVNlcnZpY2UucG9pSXNWaXJ0dWFsKHBvaSkgJiYgem9uZS5sYXllciAmJiB6b25lLmxheWVyLm5hbWUgPT09IFwiRkxPT1JcIiApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB3ZSBpbmNsdWRlIGluIEZsb29yIHpvbmUgb25seVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcmVkT2JqZWN0cy5wdXNoKG9iamVjdCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMucG9pU2VydmljZS5wb2lJc1ZpcnR1YWwocG9pKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcmVkT2JqZWN0cy5wdXNoKG9iamVjdCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHBvaSAmJiAhem9uZSAmJiB6b25lSUQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgem9uZXMgPSBhd2FpdCB0aGlzLnpvbmVTZXJ2aWNlLmdldFpvbmVzRm9yT2JqZWN0KFxuICAgICAgICAgICAgICAgICAgICAgICAgb2JqZWN0LFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgICAgICB6b25lcyAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgem9uZXMuc29tZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoem9uZV8pID0+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHpvbmVfLmlkID09PSB6b25lSUQgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgem9uZV8ucGFyZW50SUQgPT09IHpvbmVJRCxcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXJlZE9iamVjdHMucHVzaChvYmplY3QpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSksXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiBmaWx0ZXJlZE9iamVjdHM7XG4gICAgfVxuXG4gICAgZmlsdGVyRXF1aXBtZW50c0J5RG9tYWluTGlzdChcbiAgICAgICAgZXF1aXBtZW50czogRXF1aXBtZW50W10sXG4gICAgICAgIGRvbWFpbklETGlzdDogc3RyaW5nW10sXG4gICAgKTogRXF1aXBtZW50W10ge1xuICAgICAgICBsZXQgZmlsdGVyZWQgPSBbXTtcbiAgICAgICAgY29uc3QgZmlsdGVyZWRCeURvbWFpbiA9IGVxdWlwbWVudHMuZmlsdGVyKChlcXVpcCkgPT5cbiAgICAgICAgZG9tYWluSURMaXN0LmluY2x1ZGVzKGVxdWlwLmRvbWFpbklEKSxcbiAgICAgICAgKTtcbiAgICAgICAgZmlsdGVyZWQgPSBbLi4uZmlsdGVyZWQsIC4uLmZpbHRlcmVkQnlEb21haW5dO1xuICAgICAgICBjb25zdCBmaWx0ZXJlZEJ5UGFyZW50RG9tYWluID0gZXF1aXBtZW50cy5maWx0ZXIoXG4gICAgICAgICAgICAoZXF1aXApID0+XG4gICAgICAgICAgICAgICAgZXF1aXAuZG9tYWluICYmXG4gICAgICAgICAgICAgICAgZXF1aXAuZG9tYWluLnBhcmVudElEICYmXG4gICAgICAgICAgICAgICAgZG9tYWluSURMaXN0LmluY2x1ZGVzKGVxdWlwLmRvbWFpbi5wYXJlbnRJRCksXG4gICAgICAgICk7XG4gICAgICAgIGZpbHRlcmVkID0gWy4uLmZpbHRlcmVkLCAuLi5maWx0ZXJlZEJ5UGFyZW50RG9tYWluXTtcbiAgICAgICAgcmV0dXJuIGZpbHRlclVuaXF1ZUFycmF5QnlJRChmaWx0ZXJlZCk7XG4gICAgfVxuXG5cbiAgLy8gTm90IGltcGxlbWVudGVkIHlldCFcbiAgLy8gZmlsdGVyT2JqZWN0czNEQnlEb21haW5MaXN0KFxuICAvLyAgIG9iamVjdHMzRDogT2JqZWN0M0RbXSxcbiAgLy8gICBkb21haW5JRExpc3Q6IHN0cmluZ1tdLFxuICAvLyApOiBPYmplY3QzRFtdIHtcbiAgLy8gICBsZXQgZmlsdGVyZWQgPSBbXTtcbiAgLy8gICBjb25zdCBmaWx0ZXJlZEJ5RG9tYWluID0gb2JqZWN0czNELmZpbHRlcigoZXF1aXApID0+XG4gIC8vICAgICBkb21haW5JRExpc3QuaW5jbHVkZXMoZXF1aXAuZG9tYWluSUQpLFxuICAvLyAgICk7XG4gIC8vICAgZmlsdGVyZWQgPSBbLi4uZmlsdGVyZWQsIC4uLmZpbHRlcmVkQnlEb21haW5dO1xuICAvLyAgIGNvbnN0IGZpbHRlcmVkQnlQYXJlbnREb21haW4gPSBvYmplY3RzM0QuZmlsdGVyKFxuICAvLyAgICAgKG9iaikgPT5cbiAgLy8gICAgICAgb2JqLmRvbWFpbiAmJlxuICAvLyAgICAgICBvYmouZG9tYWluLnBhcmVudElEICYmXG4gIC8vICAgICAgIGRvbWFpbklETGlzdC5pbmNsdWRlcyhvYmouZG9tYWluLnBhcmVudElEKSxcbiAgLy8gICApO1xuICAvLyAgIGZpbHRlcmVkID0gWy4uLmZpbHRlcmVkLCAuLi5maWx0ZXJlZEJ5UGFyZW50RG9tYWluXTtcbiAgLy8gICByZXR1cm4gZmlsdGVyVW5pcXVlQXJyYXlCeUlEKGZpbHRlcmVkKTtcbiAgLy8gfVxuXG4gIGZpbHRlckVxdWlwbWVudHNGb3JUZXJtKGVxdWlwczogRXF1aXBtZW50W10sIHRlcm06IHN0cmluZyk6IEVxdWlwbWVudFtdIHtcbiAgICAgICAgLy8gZmlsdGVyIGRvbWFpbnNcbiAgICAgICAgbGV0IGJ5RG9tYWluID0gZXF1aXBzLmZpbHRlcigoZXEpID0+IHtcbiAgICAgICAgICAgIGlmIChlcS5kb21haW4gJiYgZXEuZG9tYWluLm5hbWUpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBub3JtYWxpemVkRG9tYWluID0gZXEuZG9tYWluLm5hbWUudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICAgICAgICBjb25zdCBsZXYgPSBsZXZlbnNodGVpbihub3JtYWxpemVkRG9tYWluLCB0ZXJtKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbGV2IDw9IDIgfHwgbm9ybWFsaXplZERvbWFpbi5pbmNsdWRlcyh0ZXJtKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IGJ5UGFyZW50RG9tYWluID0gZXF1aXBzLmZpbHRlcigoZXEpID0+IHtcbiAgICAgICAgICAgIGlmIChlcS5kb21haW4gJiYgZXEuZG9tYWluLnBhcmVudElEKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgbm9ybWFsaXplZFBhcmVudCA9IGVxLmRvbWFpbi5wYXJlbnQubmFtZS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGxldiA9IGxldmVuc2h0ZWluKG5vcm1hbGl6ZWRQYXJlbnQsIHRlcm0pO1xuICAgICAgICAgICAgICAgIHJldHVybiBsZXYgPD0gMiB8fCBub3JtYWxpemVkUGFyZW50LmluY2x1ZGVzKHRlcm0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9KTtcbiAgICAgICAgYnlEb21haW4gPSBbLi4uYnlEb21haW4sIC4uLmJ5UGFyZW50RG9tYWluXTtcbiAgICAgICAgLy8gZmlsdGVyIG5hbWVcbiAgICAgICAgbGV0IGJ5TmFtZSA9IFtdO1xuICAgICAgICBjb25zdCB0ZXJtcyA9IHRlcm0uc3BsaXQoXCIgXCIpLmZpbHRlcigodG9rZW4pID0+IHRva2VuLmxlbmd0aCA+IDIpO1xuICAgICAgICBmb3IgKGNvbnN0IGVxIG9mIGVxdWlwcykge1xuICAgICAgICAgICAgY29uc3Qgd29yZHMgPSBlcS5uYW1lXG4gICAgICAgICAgICAgICAgLnRvTG93ZXJDYXNlKClcbiAgICAgICAgICAgICAgICAuc3BsaXQoXCIgXCIpXG4gICAgICAgICAgICAgICAgLmZpbHRlcigodG9rZW4pID0+IHRva2VuLmxlbmd0aCA+IDIpO1xuICAgICAgICAgICAgY29uc3QgbWF0Y2hlZCA9IFtdO1xuICAgICAgICAgICAgZm9yIChjb25zdCB0b2tlbiBvZiB0ZXJtcykge1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3Qgd29yZCBvZiB3b3Jkcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAobGV2ZW5zaHRlaW4odG9rZW4sIHdvcmQpIDw9IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoZWQucHVzaCh0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1hdGNoZWQubGVuZ3RoID09PSB0ZXJtcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBieU5hbWUucHVzaChlcSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBieU5hbWVTaW1wbGUgPSBlcXVpcHMuZmlsdGVyKChlcSkgPT5cbiAgICAgICAgICAgIGVxLm5hbWUudG9Mb3dlckNhc2UoKS5pbmNsdWRlcyh0ZXJtKSxcbiAgICAgICAgKTtcbiAgICAgICAgYnlOYW1lID0gWy4uLmJ5TmFtZSwgLi4uYnlOYW1lU2ltcGxlXTtcbiAgICAgICAgLy8gYnkgc2VyaWFsIG51bWJlclxuICAgICAgICBjb25zdCBieVNlcmlhbE51bWJlciA9IGVxdWlwcy5maWx0ZXIoXG4gICAgICAgICAgICAoZXEpID0+IGVxLnNlcmlhbE51bWJlciAmJiBlcS5zZXJpYWxOdW1iZXIudG9Mb3dlckNhc2UoKSA9PT0gdGVybSxcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gWy4uLmJ5RG9tYWluLCAuLi5ieU5hbWUsIC4uLmJ5U2VyaWFsTnVtYmVyXTtcbiAgICAgICAgcmV0dXJuIGZpbHRlclVuaXF1ZUFycmF5QnlJRChyZXN1bHQpO1xuICAgIH1cblxuICAgIGZpbHRlclRpY2tldHNGb3JUZXJtKHRpY2tldHM6IFRpY2tldFtdLCB0ZXJtOiBzdHJpbmcpOiBUaWNrZXRbXSB7XG4gICAgICAgIC8vIGZpbHRlciB0ZXJtIGluIHRpdGxlIGFuZCBkZXNjcmlwdGlvblxuICAgICAgICBjb25zdCBieVRpdGxlID0gdGhpcy5maWx0ZXJPYmplY3RzRm9yVGVybSh0aWNrZXRzLCB0ZXJtKTtcbiAgICAgICAgLy8gYnkgZXF1aXBtZW50XG4gICAgICAgIGNvbnN0IGJ5RXF1aXBtZW50ID0gdGlja2V0cy5maWx0ZXIoXG4gICAgICAgICAgICAodGlja2V0KSA9PlxuICAgICAgICAgICAgICAgIHRpY2tldC5lcXVpcG1lbnRzICYmXG4gICAgICAgICAgICAgICAgdGhpcy5maWx0ZXJFcXVpcG1lbnRzRm9yVGVybSh0aWNrZXQuZXF1aXBtZW50cywgdGVybSkubGVuZ3RoID5cbiAgICAgICAgICAgICAgICAgICAgMCxcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIGZpbHRlclVuaXF1ZUFycmF5QnlJRChbLi4uYnlUaXRsZSwgLi4uYnlFcXVpcG1lbnRdKTtcbiAgICB9XG5cbiAgICBmaWx0ZXJMb2NhdGlvbnNGb3JUZXJtKGxvY2F0aW9uczogU3BhY2VbXSwgdGVybTogc3RyaW5nKTogU3BhY2VbXSB7XG4gICAgICAgIC8vIGJ5IG5hbWVcbiAgICAgICAgY29uc3QgYnlOYW1lID0gbG9jYXRpb25zLmZpbHRlcigobG9jKSA9PlxuICAgICAgICAgICAgbG9jLm5hbWUudG9Mb3dlckNhc2UoKS5pbmNsdWRlcyh0ZXJtKSxcbiAgICAgICAgKTtcbiAgICAgICAgLy8gYnkgYWRkcmVzc1xuICAgICAgICBjb25zdCBieUFkZHJlc3MgPSBsb2NhdGlvbnMuZmlsdGVyKChsb2MpID0+XG4gICAgICAgICAgICBsb2MuYWRkcmVzc2VzLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXModGVybSksXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiBmaWx0ZXJVbmlxdWVBcnJheUJ5SUQoWy4uLmJ5TmFtZSwgLi4uYnlBZGRyZXNzXSk7XG4gICAgfVxuXG4gICAgZmlsdGVyT3JnYW5pc2F0aW9uc0ZvclRlcm0oXG4gICAgICAgIG9yZ3M6IE9yZ2FuaXNhdGlvbltdLFxuICAgICAgICB0ZXJtOiBzdHJpbmcsXG4gICAgKTogT3JnYW5pc2F0aW9uW10ge1xuICAgICAgICBjb25zdCBieU5hbWUgPSBvcmdzLmZpbHRlcigob3JnKSA9PiB7XG4gICAgICAgICAgICBjb25zdCB3b3JkcyA9IG9yZy5uYW1lLnRvTG93ZXJDYXNlKCkuc3BsaXQoXCIgXCIpO1xuICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICB3b3Jkcy5zb21lKFxuICAgICAgICAgICAgICAgICAgICAod29yZCkgPT4gd29yZC5sZW5ndGggPiAyICYmIGxldmVuc2h0ZWluKHdvcmQsIHRlcm0pIDw9IDEsXG4gICAgICAgICAgICAgICAgKSB8fCBvcmcubmFtZS50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHRlcm0pXG4gICAgICAgICAgICApO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGJ5TmFtZTtcbiAgICB9XG5cbiAgICBmaWx0ZXJVc2Vyc0ZvclRlcm0odXNlcnM6IFByb2ZpbGVFbnRpdHlbXSwgdGVybTogc3RyaW5nKSB7XG4gICAgICAgIGNvbnN0IGJ5TmFtZSA9IHVzZXJzLmZpbHRlcigodXNlcikgPT4ge1xuICAgICAgICAgICAgY29uc3Qgd29yZHMgPSB1c2VyLmRpc3BsYXlOYW1lLnRvTG93ZXJDYXNlKCkuc3BsaXQoXCIgXCIpO1xuICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICB3b3Jkcy5zb21lKFxuICAgICAgICAgICAgICAgICAgICAod29yZCkgPT4gd29yZC5sZW5ndGggPiAyICYmIGxldmVuc2h0ZWluKHdvcmQsIHRlcm0pIDw9IDEsXG4gICAgICAgICAgICAgICAgKSB8fCB1c2VyLmRpc3BsYXlOYW1lLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXModGVybSlcbiAgICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gYnlOYW1lO1xuICAgIH1cblxuICAgIGFzeW5jIGZpbHRlckZlYXR1cmVzRm9yQ3VycmVudFVzZXJJblNwYWNlKFxuICAgICAgICBmZWF0dXJlczogRmVhdHVyZVtdLFxuICAgICAgICBzcGFjZUlEOiBzdHJpbmcsXG4gICAgKTogUHJvbWlzZTxGZWF0dXJlW10+IHtcbiAgICAgICAgY29uc3QgZmluYWxGZWF0dXJlczogRmVhdHVyZVtdID0gW107XG4gICAgICAgIGxldCBsZXZlbEZpbHRlcmVkOiBGZWF0dXJlW10gPSBmZWF0dXJlcztcbiAgICAgICAgbGV0IHpvbmVGaWx0ZXJlZDogRmVhdHVyZVtdID0gZmVhdHVyZXM7XG4gICAgICAgIGxldCBoYXNodGFnRmlsdGVyZWQ6IEZlYXR1cmVbXSA9IGZlYXR1cmVzO1xuICAgICAgICBjb25zdCBtaXNzaW9ucyA9IHRoaXMudXNlclNlcnZpY2UuY3VycmVudE1pc3Npb25zO1xuICAgICAgICBpZiAobWlzc2lvbnMpIHtcbiAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRTcGFjZU1pc3Npb25zID0gbWlzc2lvbnMuZmlsdGVyKFxuICAgICAgICAgICAgICAgIChtKSA9PiBtLnNwYWNlSUQgPT09IHNwYWNlSUQsXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgaWYgKGN1cnJlbnRTcGFjZU1pc3Npb25zLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBjb25zdCBoaWdoZXN0TGVsZWwgPVxuICAgICAgICAgICAgICAgICAgICBnZXRIaWdoZXN0TGV2ZWxGb3JNaXNzaW9ucyhjdXJyZW50U3BhY2VNaXNzaW9ucyk7XG4gICAgICAgICAgICAgICAgY29uc3QgaGlnaGVzdFJvbGUgPVxuICAgICAgICAgICAgICAgICAgICBnZXRIaWdoZXN0Um9sZUZvck1pc3Npb25zKGN1cnJlbnRTcGFjZU1pc3Npb25zKTtcblxuICAgICAgICAgICAgICAgIGNvbnN0IGZpbHRlcnMgPSB0aGlzLmdldEZpbHRlcnNGb3JSb2xlKGhpZ2hlc3RSb2xlKTtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGZpbHRlciBvZiBmaWx0ZXJzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChmaWx0ZXIgPT09IEZpbHRlclR5cGUuTEVWRUwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsRmlsdGVyZWQgPSB0aGlzLmZpbHRlck9iamVjdHNCeUxldmVsKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhpZ2hlc3RMZWxlbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGZpbHRlciA9PT0gRmlsdGVyVHlwZS5aT05FKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB6b25lRmlsdGVyZWQgPSBhd2FpdCB0aGlzLmFwcGx5Wm9uZUZpbHRlckZvck1pc3Npb25zKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRTcGFjZU1pc3Npb25zLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoZmlsdGVyID09PSBGaWx0ZXJUeXBlLkhBU0hUQUcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGhhc2h0YWdGaWx0ZXJlZCA9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5maWx0ZXJGZWF0dXJlc0J5SGFzaHRhZ3NBbmRMb2NhbGUoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRTcGFjZU1pc3Npb25zLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZmVhdHVyZSBvZiBsZXZlbEZpbHRlcmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgICAgIGhhc2h0YWdGaWx0ZXJlZC5pbmNsdWRlcyhmZWF0dXJlKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgem9uZUZpbHRlcmVkLmluY2x1ZGVzKGZlYXR1cmUpXG4gICAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxGZWF0dXJlcy5wdXNoKGZlYXR1cmUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmaW5hbEZlYXR1cmVzO1xuICAgIH1cblxuICAgIGZpbHRlckZlYXR1cmVzRm9yVGVybShmZWF0dXJlczogRmVhdHVyZVtdLCB0ZXJtOiBzdHJpbmcpOiBGZWF0dXJlW10ge1xuICAgICAgICAvLyBmaWx0ZXIgdGVybSBpbiB0aXRsZVxuICAgICAgICBjb25zdCBieVRpdGxlID0gdGhpcy5maWx0ZXJPYmplY3RzRm9yVGVybShmZWF0dXJlcywgdGVybSk7XG4gICAgICAgIC8vIGJ5IGNvbW1lbnRzXG4gICAgICAgIGNvbnN0IGJ5Q29tbWVudCA9IGZlYXR1cmVzLmZpbHRlcihcbiAgICAgICAgICAgIChmZWF0dXJlKSA9PlxuICAgICAgICAgICAgICAgIHRoaXMuZmlsdGVyT2JqZWN0c0ZvclRlcm0oZmVhdHVyZS5jb21tZW50cy5pdGVtcywgdGVybSkubGVuZ3RoID5cbiAgICAgICAgICAgICAgICAwLFxuICAgICAgICApO1xuICAgICAgICByZXR1cm4gZmlsdGVyVW5pcXVlQXJyYXlCeUlEKFsuLi5ieVRpdGxlLCAuLi5ieUNvbW1lbnRdKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKlxuICAgICAqIEBwYXJhbSBvYmplY3RzIEFycmF5IG9mIENvbW1lbnRzLCBUaWNrZXRzLCBGZWF0dXJlcy4gT2JsaWdhdG9yeSBwcm9wb3J0aWVzOiB0aXRsZSwgZGVzY3JpcHRpb25cbiAgICAgKiBAcGFyYW0gdGVybSBzdHJpbmdcbiAgICAgKi9cbiAgICBmaWx0ZXJPYmplY3RzRm9yVGVybShvYmplY3RzOiBhbnlbXSwgdGVybTogc3RyaW5nKTogYW55W10ge1xuICAgICAgICAvLyBmaWx0ZXIgdGVybSBpbiB0aXRsZVxuICAgICAgICBjb25zdCBieVRpdGxlID0gb2JqZWN0cy5maWx0ZXIoKGZlYXR1cmUpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHdvcmRzID0gZmVhdHVyZS50aXRsZS50b0xvd2VyQ2FzZSgpLnNwbGl0KFwiIFwiKTtcbiAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgd29yZHMuc29tZShcbiAgICAgICAgICAgICAgICAgICAgKHdvcmQpID0+IHdvcmQubGVuZ3RoID4gMiAmJiBsZXZlbnNodGVpbih3b3JkLCB0ZXJtKSA8PSAxLFxuICAgICAgICAgICAgICAgICkgfHwgZmVhdHVyZS50aXRsZS50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHRlcm0pXG4gICAgICAgICAgICApO1xuICAgICAgICB9KTtcbiAgICAgICAgLy8gdGVybSBwcmVzZW50IGluIGRlc2NyaXB0aW9uXG4gICAgICAgIGNvbnN0IGJ5RGVzY3JpcHRpb24gPSBvYmplY3RzLmZpbHRlcihcbiAgICAgICAgICAgIChmZWF0dXJlKSA9PlxuICAgICAgICAgICAgICAgIGZlYXR1cmUuZGVzY3JpcHRpb24gJiZcbiAgICAgICAgICAgICAgICBmZWF0dXJlLmRlc2NyaXB0aW9uLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXModGVybSksXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiBmaWx0ZXJVbmlxdWVBcnJheUJ5SUQoWy4uLmJ5VGl0bGUsIC4uLmJ5RGVzY3JpcHRpb25dKTtcbiAgICB9XG5cbiAgICBmaWx0ZXJNaXNzaW9uQnlTdGFydFRpbWVEYXRlRm9yRGF0ZVJhbmdlKFxuICAgICAgICBtaXNzaW9uczogYW55W10sXG4gICAgICAgIGRhdGVSYW5nZTogRGF0ZVtdLFxuICAgICk6IGFueVtdIHtcbiAgICAgICAgcmV0dXJuIG1pc3Npb25zLmZpbHRlcigobWlzc2lvbikgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc3RhcnREYXRlVGltZSA9IG5ldyBEYXRlKG1pc3Npb24uc3RhcnREYXRlVGltZSk7XG4gICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgIHN0YXJ0RGF0ZVRpbWUgPj0gZGF0ZVJhbmdlWzBdICYmIHN0YXJ0RGF0ZVRpbWUgPD0gZGF0ZVJhbmdlWzFdXG4gICAgICAgICAgICApO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBhc3luYyBhcHBseVpvbmVGaWx0ZXJGb3JNaXNzaW9ucyhcbiAgICAgICAgY3VycmVudFNwYWNlTWlzc2lvbnM6IE1pc3Npb25bXSxcbiAgICAgICAgb2JqZWN0czogYW55W10sXG4gICAgKTogUHJvbWlzZTxhbnlbXT4ge1xuICAgICAgICBjb25zdCBhbGxvd2VkWm9uZXMgPSBbXTtcbiAgICAgICAgZm9yIChjb25zdCBtaXNzaW9uIG9mIGN1cnJlbnRTcGFjZU1pc3Npb25zKSB7XG4gICAgICAgICAgICBpZiAobWlzc2lvbi56b25lSUQpIHtcbiAgICAgICAgICAgICAgICBhbGxvd2VkWm9uZXMucHVzaChtaXNzaW9uLnpvbmVJRCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGFsbG93ZWRab25lcy5sZW5ndGggPT09IGN1cnJlbnRTcGFjZU1pc3Npb25zLmxlbmd0aCkge1xuICAgICAgICAgICAgbGV0IGFsbFpvbmVGaWx0ZXJlZCA9IFtdO1xuICAgICAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgICAgICAgICAgYWxsb3dlZFpvbmVzLm1hcChhc3luYyAoem9uZUlEKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRab25lRmlsdGVyZWQgPSBhd2FpdCB0aGlzLmZpbHRlck9iamVjdHNGb3Jab25lKFxuICAgICAgICAgICAgICAgICAgICAgICAgb2JqZWN0cyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHpvbmVJRCxcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgYWxsWm9uZUZpbHRlcmVkID0gW1xuICAgICAgICAgICAgICAgICAgICAgICAgLi4uYWxsWm9uZUZpbHRlcmVkLFxuICAgICAgICAgICAgICAgICAgICAgICAgLi4uY3VycmVudFpvbmVGaWx0ZXJlZCxcbiAgICAgICAgICAgICAgICAgICAgXTtcbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm4gZmlsdGVyVW5pcXVlQXJyYXlCeUlEKGFsbFpvbmVGaWx0ZXJlZCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG9iamVjdHM7XG4gICAgfVxuXG4gICAgYXN5bmMgZmlsdGVyRXF1aXBtZW50c0ZvckN1cnJlbnRVc2VySW5TcGFjZShcbiAgICAgICAgc3BhY2VJRDogc3RyaW5nLFxuICAgICAgICBlcXVpcHM6IEVxdWlwbWVudFtdLFxuICAgICk6IFByb21pc2U8RXF1aXBtZW50W10+IHtcbiAgICAgICAgY29uc3QgZmluYWxFcXVpcHM6IEVxdWlwbWVudFtdID0gW107XG4gICAgICAgIGxldCBkb21GaWx0ZXJlZDogRXF1aXBtZW50W10gPSBlcXVpcHM7XG4gICAgICAgIGNvbnN0IHJvbGVGaWx0ZXJlZDogRXF1aXBtZW50W10gPSBlcXVpcHM7XG4gICAgICAgIGNvbnN0IGxldmVsRmlsdGVyZWQ6IEVxdWlwbWVudFtdID0gZXF1aXBzO1xuICAgICAgICBsZXQgem9uZUZpbHRlcmVkOiBFcXVpcG1lbnRbXSA9IGVxdWlwcztcbiAgICAgICAgY29uc3QgbWlzc2lvbnMgPSB0aGlzLnVzZXJTZXJ2aWNlLmN1cnJlbnRNaXNzaW9ucztcbiAgICAgICAgaWYgKG1pc3Npb25zKSB7XG4gICAgICAgICAgICBjb25zdCBjdXJyZW50U3BhY2VNaXNzaW9ucyA9IG1pc3Npb25zLmZpbHRlcihcbiAgICAgICAgICAgICAgICAobSkgPT4gbS5zcGFjZUlEID09PSBzcGFjZUlELFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGlmIChjdXJyZW50U3BhY2VNaXNzaW9ucy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgaGlnaGVzdExlbGVsID1cbiAgICAgICAgICAgICAgICAgICAgZ2V0SGlnaGVzdExldmVsRm9yTWlzc2lvbnMoY3VycmVudFNwYWNlTWlzc2lvbnMpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGhpZ2hlc3RSb2xlID1cbiAgICAgICAgICAgICAgICAgICAgZ2V0SGlnaGVzdFJvbGVGb3JNaXNzaW9ucyhjdXJyZW50U3BhY2VNaXNzaW9ucyk7XG4gICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJIaWdoZXN0IGxldmVsOiBcIiwgaGlnaGVzdExlbGVsLCBcIiwgSGlnaGVzdCBSb2xlOiBcIiwgaGlnaGVzdFJvbGUpXG5cbiAgICAgICAgICAgICAgICBjb25zdCBmaWx0ZXJzID0gdGhpcy5nZXRGaWx0ZXJzRm9yUm9sZShoaWdoZXN0Um9sZSk7XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBmaWx0ZXIgb2YgZmlsdGVycykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZmlsdGVyID09PSBGaWx0ZXJUeXBlLkRPTUFJTikge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGRvbWFpbnM6IHN0cmluZ1tdID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IG0gb2YgY3VycmVudFNwYWNlTWlzc2lvbnMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtLmRvbWFpbnMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9tYWlucyA9IFsuLi5kb21haW5zLCAuLi5tLmRvbWFpbnNdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGFsbERvbWFpbnNGaWx0ZXJlZCA9IFtdO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjdXJyZW50RG9tRmlsdGVyZWQgPVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZmlsdGVyRXF1aXBtZW50c0J5RG9tYWluTGlzdChlcXVpcHMsIGRvbWFpbnMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYWxsRG9tYWluc0ZpbHRlcmVkID0gW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLmFsbERvbWFpbnNGaWx0ZXJlZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5jdXJyZW50RG9tRmlsdGVyZWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgZG9tRmlsdGVyZWQgPSBhbGxEb21haW5zRmlsdGVyZWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGZpbHRlciA9PT0gRmlsdGVyVHlwZS5ST0xFKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBjb25zdCBoaWdoZXN0Um9sZU1pc3Npb24gPSBjdXJyZW50U3BhY2VNaXNzaW9ucy5maW5kKFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgIChtKSA9PiBtLnJvbGUgPT09IGhpZ2hlc3RSb2xlLFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRPRE9cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmIChmaWx0ZXIgPT09IEZpbHRlclR5cGUuTEVWRUwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRPRE8sIGVxdWlwbWVudCBkb2VzIG5vdCBoYXZlIGxldmVsXG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoZmlsdGVyID09PSBGaWx0ZXJUeXBlLlpPTkUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHpvbmVGaWx0ZXJlZCA9IGF3YWl0IHRoaXMuYXBwbHlab25lRmlsdGVyRm9yTWlzc2lvbnMoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudFNwYWNlTWlzc2lvbnMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXF1aXBzLFxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHRpYyBvZiBsZXZlbEZpbHRlcmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvbUZpbHRlcmVkLmluY2x1ZGVzKHRpYykgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvbGVGaWx0ZXJlZC5pbmNsdWRlcyh0aWMpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICB6b25lRmlsdGVyZWQuaW5jbHVkZXModGljKVxuICAgICAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsRXF1aXBzLnB1c2godGljKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmluYWxFcXVpcHM7XG4gICAgfVxuXG4gICAgYXN5bmMgZmlsdGVyTWVhc3VyZW1lbnRzRm9yQ3VycmVudFVzZXJJblNwYWNlKFxuICAgICAgICBzcGFjZUlEOiBzdHJpbmcsXG4gICAgICAgIGNvbW1lbnRzOiBDb21tZW50W10sXG4gICAgKTogUHJvbWlzZTxDb21tZW50W10+IHtcbiAgICAgICAgbGV0IGZpbmFsTWVhc3VyZW1lbnRzOiBDb21tZW50W10gPSBbXTtcbiAgICAgICAgbGV0IHpvbmVGaWx0ZXJlZDogQ29tbWVudFtdID0gY29tbWVudHM7XG4gICAgICAgIGNvbnN0IG1pc3Npb25zID0gdGhpcy51c2VyU2VydmljZS5jdXJyZW50TWlzc2lvbnM7XG4gICAgICAgIGlmIChtaXNzaW9ucykge1xuICAgICAgICAgICAgY29uc3QgY3VycmVudFNwYWNlTWlzc2lvbnMgPSBtaXNzaW9ucy5maWx0ZXIoXG4gICAgICAgICAgICAgICAgKG0pID0+IG0uc3BhY2VJRCA9PT0gc3BhY2VJRCxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBpZiAoY3VycmVudFNwYWNlTWlzc2lvbnMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGhpZ2hlc3RSb2xlID1cbiAgICAgICAgICAgICAgICAgICAgZ2V0SGlnaGVzdFJvbGVGb3JNaXNzaW9ucyhjdXJyZW50U3BhY2VNaXNzaW9ucyk7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBmaWx0ZXJzID0gdGhpcy5nZXRGaWx0ZXJzRm9yUm9sZShoaWdoZXN0Um9sZSk7XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBmaWx0ZXIgb2YgZmlsdGVycykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZmlsdGVyID09PSBGaWx0ZXJUeXBlLlpPTkUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHpvbmVGaWx0ZXJlZCA9IGF3YWl0IHRoaXMuYXBwbHlab25lRmlsdGVyRm9yTWlzc2lvbnMoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudFNwYWNlTWlzc2lvbnMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tbWVudHMsXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZpbmFsTWVhc3VyZW1lbnRzID0gem9uZUZpbHRlcmVkO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmaW5hbE1lYXN1cmVtZW50cztcbiAgICB9XG5cbiAgICBhc3luYyBpc09iamVjdEFsbG93ZWRGb3JVc2VySW5TcGFjZShcbiAgICAgICAgb2JqZWN0OiBPYmplY3QsXG4gICAgICAgIHNwYWNlSUQ6IHN0cmluZyxcbiAgICApOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgICAgY29uc3QgbWlzc2lvbiA9IHRoaXMudXNlclNlcnZpY2UuY3VycmVudE1pc3Npb24oc3BhY2VJRCk7XG4gICAgICAgIGNvbnN0IGZpbHRlcnMgPSB0aGlzLmdldEZpbHRlcnNGb3JSb2xlKG1pc3Npb24ucm9sZSk7XG4gICAgICAgIGZvciAoY29uc3QgZmlsdGVyIG9mIGZpbHRlcnMpIHtcbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICBmaWx0ZXIgPT09IEZpbHRlclR5cGUuTEVWRUwgJiZcbiAgICAgICAgICAgICAgICBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBcImxldmVsXCIpXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICBjb25zdCBsZXZlbEZpbHRlcmVkID0gdGhpcy5maWx0ZXJPYmplY3RzQnlMZXZlbChcbiAgICAgICAgICAgICAgICAgICAgW29iamVjdF0sXG4gICAgICAgICAgICAgICAgICAgIG1pc3Npb24ubGV2ZWwsXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICBpZiAobGV2ZWxGaWx0ZXJlZC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChmaWx0ZXIgPT09IEZpbHRlclR5cGUuWk9ORSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHpvbmVGaWx0ZXJlZCA9IGF3YWl0IHRoaXMuYXBwbHlab25lRmlsdGVyRm9yTWlzc2lvbnMoXG4gICAgICAgICAgICAgICAgICAgIFttaXNzaW9uXSxcbiAgICAgICAgICAgICAgICAgICAgW29iamVjdF0sXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICBpZiAoem9uZUZpbHRlcmVkLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIGZpbHRlclRlbXBsYXRlc0ZvclRlcm0obWlzc2lvbnM6IE1pc3Npb25bXSwgdGVybTogc3RyaW5nKTogTWlzc2lvbltdIHtcbiAgICAgICAgLy8gdGVybSBwcmVzZW50IGluIGRlc2NyaXB0aW9uXG4gICAgICAgIGNvbnN0IGJ5RGVzY3JpcHRpb24gPSBtaXNzaW9ucy5maWx0ZXIoXG4gICAgICAgICAgICAobWlzKSA9PlxuICAgICAgICAgICAgICAgIG1pcy5kZXNjcmlwdGlvbiAmJiBtaXMuZGVzY3JpcHRpb24udG9Mb3dlckNhc2UoKS5pbmNsdWRlcyh0ZXJtKSxcbiAgICAgICAgKTtcbiAgICAgICAgLy8gYnkgdXNlciBsYXN0TmFtZSB3aGljaCBpcyB0aGUgbmFtZSBvZiB0aGUgdmlzaXQ6XG4gICAgICAgIC8vIG1ldGFkYXRhOiBcIntcXFwiZmlyc3ROYW1lXFxcIjpcXFwiXFxcIixcXFwibGFzdE5hbWVcXFwiOlxcXCJWaXNpdGUgZHUgNSBKdWlsbGV0XFxcIn1cIlxuICAgICAgICBjb25zdCB1c2VyUHJvZmlsZXMgPSBtaXNzaW9ucy5tYXAoKG1pcykgPT4gbmV3IFByb2ZpbGVFbnRpdHkobWlzLnVzZXIpKTtcbiAgICAgICAgY29uc3QgYnlVc2VyTGFzdG5hbWUgPSB0aGlzLmZpbHRlclVzZXJzRm9yVGVybSh1c2VyUHJvZmlsZXMsIHRlcm0pO1xuICAgICAgICBjb25zdCB1c2VySWRzID0gbmV3IFNldChieVVzZXJMYXN0bmFtZS5tYXAoKHVzZXIpID0+IHVzZXIuaWQpKTtcbiAgICAgICAgY29uc3QgbWlzc2lvbnNCeVVzZXIgPSBtaXNzaW9ucy5maWx0ZXIoKG1pcykgPT5cbiAgICAgICAgICAgIHVzZXJJZHMuaGFzKG1pcy51c2VySUQpLFxuICAgICAgICApO1xuICAgICAgICByZXR1cm4gZmlsdGVyVW5pcXVlQXJyYXlCeUlEKFsuLi5ieURlc2NyaXB0aW9uLCAuLi5taXNzaW9uc0J5VXNlcl0pO1xuICAgIH1cblxuICAgIGFzeW5jIGZpbHRlck9iamVjdHNGb3JTd2VlcChcbiAgICAgICAgb2JqZWN0czogYW55W10sXG4gICAgICAgIG9iamVjdFR5cGU6IFBvaVR5cGUsXG4gICAgICAgIHN3ZWVwOiBzdHJpbmcsXG4gICAgKTogUHJvbWlzZTxhbnlbXT4ge1xuICAgICAgICBsZXQgZmlsdGVyZWQgPSBbXTtcbiAgICAgICAgc3dpdGNoIChvYmplY3RUeXBlKSB7XG4gICAgICAgICAgICBjYXNlIFBvaVR5cGUuRVFVSVBNRU5UOlxuICAgICAgICAgICAgICAgIGNvbnN0IHBvaXMgPVxuICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnBvaVNlcnZpY2UuZ2V0UG9pc0J5TWF0dGVycG9ydFN3ZWVwQnlUeXBlKFxuICAgICAgICAgICAgICAgICAgICAgICAgc3dlZXAsXG4gICAgICAgICAgICAgICAgICAgICAgICBvYmplY3RUeXBlLFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIGNvbnN0IGVxdWlwSURzID0gbmV3IFNldChwb2lzLm1hcCgocG9pKSA9PiBwb2kuZWxlbWVudElEKSk7XG4gICAgICAgICAgICAgICAgZmlsdGVyZWQgPSBvYmplY3RzLmZpbHRlcigob2JqZWN0KSA9PiBlcXVpcElEcy5oYXMob2JqZWN0LmlkKSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmaWx0ZXJlZDtcbiAgICB9XG5cbiAgICBmaWx0ZXJGZWF0dXJlc0J5SGFzaHRhZ3NBbmRMb2NhbGUoXG4gICAgICAgIGN1cnJlbnRTcGFjZU1pc3Npb25zOiBNaXNzaW9uW10sXG4gICAgICAgIGZlYXR1cmVzOiBGZWF0dXJlW10sXG4gICAgKTogRmVhdHVyZVtdIHtcbiAgICAgICAgY29uc3QgW2N1cnJlbnRNaXNzaW9uXSA9IGN1cnJlbnRTcGFjZU1pc3Npb25zO1xuICAgICAgICAvLyBmaWx0ZXIgYnkgbG9jYWxlXG4gICAgICAgIGxldCBmaWx0ZXJlZExvY2FsZSA9IFsuLi5mZWF0dXJlc107XG4gICAgICAgIGlmIChjdXJyZW50TWlzc2lvbi5sb2NhbGUpIHtcbiAgICAgICAgICAgIGZpbHRlcmVkTG9jYWxlID0gZmVhdHVyZXMuZmlsdGVyKFxuICAgICAgICAgICAgICAgIChmZWF0dXJlKSA9PlxuICAgICAgICAgICAgICAgICAgICBmZWF0dXJlLmxvY2FsZSAmJiBmZWF0dXJlLmxvY2FsZSA9PT0gY3VycmVudE1pc3Npb24ubG9jYWxlLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBmaWx0ZXIgYnkgaGFzaHRhZ3NcbiAgICAgICAgaWYgKGN1cnJlbnRNaXNzaW9uLmhhc2h0YWdzICYmIGN1cnJlbnRNaXNzaW9uLmhhc2h0YWdzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGNvbnN0IGZpbHRlcmVkQnlIYXNodGFncyA9IFtdO1xuICAgICAgICAgICAgZm9yIChjb25zdCBmZWF0dXJlIG9mIGZpbHRlcmVkTG9jYWxlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFmZWF0dXJlLmhhc2h0YWdzIHx8IGZlYXR1cmUuaGFzaHRhZ3MubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEZlYXR1cmUgd2l0aG91dCBoYXNodGFnIGlzIGF2YWlsYWJsZSBmb3IgZXZlcnlib2R5XG4gICAgICAgICAgICAgICAgICAgIGZpbHRlcmVkQnlIYXNodGFncy5wdXNoKGZlYXR1cmUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRNaXNzaW9uLmhhc2h0YWdzLmV2ZXJ5KChoYXNodGFnKSA9PlxuICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZS5oYXNodGFncy5pbmNsdWRlcyhoYXNodGFnKSxcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICBmaWx0ZXJlZEJ5SGFzaHRhZ3MucHVzaChmZWF0dXJlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZmlsdGVyZWRCeUhhc2h0YWdzO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmaWx0ZXJlZExvY2FsZTtcbiAgICB9XG5cbiAgICBmaWx0ZXJGZWF0dXJlc0Zvck1pc3Npb25XaXRob3V0Wm9uZShcbiAgICAgICAgZmVhdHVyZXM6IEZlYXR1cmVbXSxcbiAgICAgICAgbWlzc2lvbjogTWlzc2lvbixcbiAgICApOiBGZWF0dXJlW10ge1xuICAgICAgICBjb25zdCBmaW5hbEZlYXR1cmVzOiBGZWF0dXJlW10gPSBbXTtcbiAgICAgICAgbGV0IGxldmVsRmlsdGVyZWQ6IEZlYXR1cmVbXSA9IGZlYXR1cmVzO1xuICAgICAgICBsZXQgem9uZUZpbHRlcmVkOiBGZWF0dXJlW10gPSBmZWF0dXJlcztcbiAgICAgICAgbGV0IGhhc2h0YWdGaWx0ZXJlZDogRmVhdHVyZVtdID0gZmVhdHVyZXM7XG5cbiAgICAgICAgY29uc3QgZmlsdGVycyA9IHRoaXMuZ2V0RmlsdGVyc0ZvclJvbGUobWlzc2lvbi5yb2xlKTtcbiAgICAgICAgZm9yIChjb25zdCBmaWx0ZXIgb2YgZmlsdGVycykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZmlsdGVyID09PSBGaWx0ZXJUeXBlLkxFVkVMKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXZlbEZpbHRlcmVkID0gdGhpcy5maWx0ZXJPYmplY3RzQnlMZXZlbChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaXNzaW9uLmxldmVsLFxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvLyBpZiAoZmlsdGVyID09PSBGaWx0ZXJUeXBlLlpPTkUpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gICAgIHpvbmVGaWx0ZXJlZCA9IGF3YWl0IHRoaXMuYXBwbHlab25lRmlsdGVyRm9yTWlzc2lvbnMoXG4gICAgICAgICAgICAgICAgICAgIC8vICAgICAgICAgY3VycmVudFNwYWNlTWlzc2lvbnMsXG4gICAgICAgICAgICAgICAgICAgIC8vICAgICAgICAgZmVhdHVyZXMsXG4gICAgICAgICAgICAgICAgICAgIC8vICAgICApO1xuICAgICAgICAgICAgICAgICAgICAvLyB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChmaWx0ZXIgPT09IEZpbHRlclR5cGUuSEFTSFRBRykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaGFzaHRhZ0ZpbHRlcmVkID1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmZpbHRlckZlYXR1cmVzQnlIYXNodGFnc0FuZExvY2FsZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW21pc3Npb25dLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICBmb3IgKGNvbnN0IGZlYXR1cmUgb2YgbGV2ZWxGaWx0ZXJlZCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgICAgICBoYXNodGFnRmlsdGVyZWQuaW5jbHVkZXMoZmVhdHVyZSkgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIHpvbmVGaWx0ZXJlZC5pbmNsdWRlcyhmZWF0dXJlKVxuICAgICAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsRmVhdHVyZXMucHVzaChmZWF0dXJlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmaW5hbEZlYXR1cmVzO1xuICAgIH1cbn1cbiJdfQ==
|