@smarterplan/ngx-smarterplan-core 0.3.11
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 -0
- package/esm2020/lib/components/csv-export/csv-export.component.mjs +59 -0
- package/esm2020/lib/components/loader/loader.component.mjs +14 -0
- package/esm2020/lib/components/menu-bar/avatar/avatar.component.mjs +75 -0
- package/esm2020/lib/components/menu-bar/menu-bar.component.mjs +115 -0
- package/esm2020/lib/components/menu-bar/navigation-bar/navigation-bar.component.mjs +254 -0
- package/esm2020/lib/components/menu-bar/range-date-picker/range-date-picker.component.mjs +81 -0
- package/esm2020/lib/components/modal-switch-visit/modal-switch-visit.component.mjs +39 -0
- package/esm2020/lib/components/search-bar/search-bar.component.mjs +63 -0
- package/esm2020/lib/components/support-modal/support-modal.component.mjs +59 -0
- package/esm2020/lib/config.mjs +4 -0
- package/esm2020/lib/helpers.service.mjs +468 -0
- package/esm2020/lib/mattertagData.mjs +177 -0
- package/esm2020/lib/ngx-smarterplan-core.module.mjs +117 -0
- package/esm2020/lib/ngx-smarterplan-core.service.mjs +14 -0
- package/esm2020/lib/pipes/duration-to-string.pipe.mjs +66 -0
- package/esm2020/lib/pipes/hashtag-from-id.pipe.mjs +26 -0
- package/esm2020/lib/pipes/safe-url.pipe.mjs +20 -0
- package/esm2020/lib/pipes/time-date-to-local-string.pipe.mjs +104 -0
- package/esm2020/lib/pipes/username-from-id.pipe.mjs +29 -0
- package/esm2020/lib/services/base-tab.service.mjs +24 -0
- package/esm2020/lib/services/baseVisibility.service.mjs +17 -0
- package/esm2020/lib/services/booking.service.mjs +161 -0
- package/esm2020/lib/services/content.service.mjs +135 -0
- package/esm2020/lib/services/filter.service.mjs +560 -0
- package/esm2020/lib/services/intervention.service.mjs +236 -0
- package/esm2020/lib/services/locale.service.mjs +45 -0
- package/esm2020/lib/services/matterport-import.service.mjs +339 -0
- package/esm2020/lib/services/matterport.service.mjs +876 -0
- package/esm2020/lib/services/models/affectation.service.mjs +60 -0
- package/esm2020/lib/services/models/base-object.service.mjs +70 -0
- package/esm2020/lib/services/models/capture.service.mjs +34 -0
- package/esm2020/lib/services/models/comment.service.mjs +98 -0
- package/esm2020/lib/services/models/domain.service.mjs +77 -0
- package/esm2020/lib/services/models/equipment.service.mjs +629 -0
- package/esm2020/lib/services/models/event.service.mjs +128 -0
- package/esm2020/lib/services/models/feature.service.mjs +339 -0
- package/esm2020/lib/services/models/hashtag.service.mjs +38 -0
- package/esm2020/lib/services/models/layer.service.mjs +33 -0
- package/esm2020/lib/services/models/measurement.service.mjs +158 -0
- package/esm2020/lib/services/models/mission.service.mjs +185 -0
- package/esm2020/lib/services/models/navigation.service.mjs +76 -0
- package/esm2020/lib/services/models/node.service.mjs +31 -0
- package/esm2020/lib/services/models/operation.service.mjs +59 -0
- package/esm2020/lib/services/models/organisation.service.mjs +73 -0
- package/esm2020/lib/services/models/plan.service.mjs +573 -0
- package/esm2020/lib/services/models/poi.service.mjs +48 -0
- package/esm2020/lib/services/models/profile.service.mjs +54 -0
- package/esm2020/lib/services/models/property.service.mjs +34 -0
- package/esm2020/lib/services/models/space.service.mjs +184 -0
- package/esm2020/lib/services/models/template.service.mjs +41 -0
- package/esm2020/lib/services/models/ticket.service.mjs +454 -0
- package/esm2020/lib/services/models/visit.service.mjs +130 -0
- package/esm2020/lib/services/models/zone.service.mjs +184 -0
- package/esm2020/lib/services/navigator.service.mjs +165 -0
- package/esm2020/lib/services/s3.service.mjs +124 -0
- package/esm2020/lib/services/search.service.mjs +124 -0
- package/esm2020/lib/services/support.service.mjs +42 -0
- package/esm2020/lib/services/tag.service.mjs +101 -0
- package/esm2020/lib/services/user.service.mjs +444 -0
- package/esm2020/lib/services/viewer.service.mjs +395 -0
- package/esm2020/lib/services/zone-drawer.service.mjs +76 -0
- package/esm2020/lib/types.service.mjs +266 -0
- package/esm2020/public-api.mjs +63 -0
- package/esm2020/smarterplan-ngx-smarterplan-core.mjs +5 -0
- package/fesm2015/smarterplan-ngx-smarterplan-core.mjs +10057 -0
- package/fesm2015/smarterplan-ngx-smarterplan-core.mjs.map +1 -0
- package/fesm2020/smarterplan-ngx-smarterplan-core.mjs +9371 -0
- package/fesm2020/smarterplan-ngx-smarterplan-core.mjs.map +1 -0
- package/lib/components/csv-export/csv-export.component.d.ts +18 -0
- package/lib/components/loader/loader.component.d.ts +8 -0
- package/lib/components/menu-bar/avatar/avatar.component.d.ts +18 -0
- package/lib/components/menu-bar/menu-bar.component.d.ts +35 -0
- package/lib/components/menu-bar/navigation-bar/navigation-bar.component.d.ts +66 -0
- package/lib/components/menu-bar/range-date-picker/range-date-picker.component.d.ts +24 -0
- package/lib/components/modal-switch-visit/modal-switch-visit.component.d.ts +22 -0
- package/lib/components/search-bar/search-bar.component.d.ts +16 -0
- package/lib/components/support-modal/support-modal.component.d.ts +24 -0
- package/lib/config.d.ts +17 -0
- package/lib/helpers.service.d.ts +79 -0
- package/lib/mattertagData.d.ts +65 -0
- package/lib/ngx-smarterplan-core.module.d.ts +28 -0
- package/lib/ngx-smarterplan-core.service.d.ts +6 -0
- package/lib/pipes/duration-to-string.pipe.d.ts +12 -0
- package/lib/pipes/hashtag-from-id.pipe.d.ts +10 -0
- package/lib/pipes/safe-url.pipe.d.ts +10 -0
- package/lib/pipes/time-date-to-local-string.pipe.d.ts +16 -0
- package/lib/pipes/username-from-id.pipe.d.ts +11 -0
- package/lib/services/base-tab.service.d.ts +10 -0
- package/lib/services/baseVisibility.service.d.ts +8 -0
- package/lib/services/booking.service.d.ts +21 -0
- package/lib/services/content.service.d.ts +28 -0
- package/lib/services/filter.service.d.ts +58 -0
- package/lib/services/intervention.service.d.ts +25 -0
- package/lib/services/locale.service.d.ts +23 -0
- package/lib/services/matterport-import.service.d.ts +46 -0
- package/lib/services/matterport.service.d.ts +141 -0
- package/lib/services/models/affectation.service.d.ts +14 -0
- package/lib/services/models/base-object.service.d.ts +20 -0
- package/lib/services/models/capture.service.d.ts +13 -0
- package/lib/services/models/comment.service.d.ts +26 -0
- package/lib/services/models/domain.service.d.ts +19 -0
- package/lib/services/models/equipment.service.d.ts +88 -0
- package/lib/services/models/event.service.d.ts +43 -0
- package/lib/services/models/feature.service.d.ts +71 -0
- package/lib/services/models/hashtag.service.d.ts +13 -0
- package/lib/services/models/layer.service.d.ts +11 -0
- package/lib/services/models/measurement.service.d.ts +43 -0
- package/lib/services/models/mission.service.d.ts +32 -0
- package/lib/services/models/navigation.service.d.ts +22 -0
- package/lib/services/models/node.service.d.ts +12 -0
- package/lib/services/models/operation.service.d.ts +15 -0
- package/lib/services/models/organisation.service.d.ts +19 -0
- package/lib/services/models/plan.service.d.ts +117 -0
- package/lib/services/models/poi.service.d.ts +15 -0
- package/lib/services/models/profile.service.d.ts +15 -0
- package/lib/services/models/property.service.d.ts +13 -0
- package/lib/services/models/space.service.d.ts +38 -0
- package/lib/services/models/template.service.d.ts +15 -0
- package/lib/services/models/ticket.service.d.ts +86 -0
- package/lib/services/models/visit.service.d.ts +24 -0
- package/lib/services/models/zone.service.d.ts +25 -0
- package/lib/services/navigator.service.d.ts +55 -0
- package/lib/services/s3.service.d.ts +13 -0
- package/lib/services/search.service.d.ts +20 -0
- package/lib/services/support.service.d.ts +17 -0
- package/lib/services/tag.service.d.ts +45 -0
- package/lib/services/user.service.d.ts +104 -0
- package/lib/services/viewer.service.d.ts +113 -0
- package/lib/services/zone-drawer.service.d.ts +7 -0
- package/lib/types.service.d.ts +723 -0
- package/package.json +41 -0
- package/public-api.d.ts +56 -0
- package/smarterplan-ngx-smarterplan-core.d.ts +5 -0
|
@@ -0,0 +1,560 @@
|
|
|
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 filterTicketsForCurrentUserInSpace(tickets, spaceID) {
|
|
106
|
+
const finalTickets = [];
|
|
107
|
+
let domFiltered = tickets;
|
|
108
|
+
let roleFiltered = tickets;
|
|
109
|
+
let levelFiltered = tickets;
|
|
110
|
+
let zoneFiltered = tickets;
|
|
111
|
+
const missions = this.userService.currentMissions;
|
|
112
|
+
if (missions) {
|
|
113
|
+
const currentSpaceMissions = missions.filter((m) => m.spaceID === spaceID);
|
|
114
|
+
if (currentSpaceMissions.length > 0) {
|
|
115
|
+
const highestLelel = getHighestLevelForMissions(currentSpaceMissions);
|
|
116
|
+
const highestRole = getHighestRoleForMissions(currentSpaceMissions);
|
|
117
|
+
// console.log("Highest level: ", highestLelel, ", Highest Role: ", highestRole)
|
|
118
|
+
const filters = this.getFiltersForRole(highestRole);
|
|
119
|
+
for (const filter of filters) {
|
|
120
|
+
if (filter === FilterType.DOMAIN) {
|
|
121
|
+
let domains = [];
|
|
122
|
+
for (const m of currentSpaceMissions) {
|
|
123
|
+
if (m.domains) {
|
|
124
|
+
domains = [...domains, ...m.domains];
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
let allDomainsFiltered = [];
|
|
128
|
+
for (const d of domains) {
|
|
129
|
+
const currentDomFiltered = this.filterTicketsByDomain(tickets, d);
|
|
130
|
+
allDomainsFiltered = [
|
|
131
|
+
...allDomainsFiltered,
|
|
132
|
+
...currentDomFiltered,
|
|
133
|
+
];
|
|
134
|
+
}
|
|
135
|
+
domFiltered = allDomainsFiltered;
|
|
136
|
+
}
|
|
137
|
+
if (filter === FilterType.ROLE) {
|
|
138
|
+
const highestRoleMission = currentSpaceMissions.find((m) => m.role === highestRole);
|
|
139
|
+
roleFiltered = this.filterTicketsForMission(tickets, highestRoleMission);
|
|
140
|
+
}
|
|
141
|
+
if (filter === FilterType.LEVEL) {
|
|
142
|
+
levelFiltered = this.filterObjectsByLevel(tickets, highestLelel);
|
|
143
|
+
}
|
|
144
|
+
if (filter === FilterType.ZONE) {
|
|
145
|
+
zoneFiltered = await this.applyZoneFilterForMissions(currentSpaceMissions, tickets);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
// keep only tickets present in all filtered arrays
|
|
149
|
+
// console.log(domFiltered);
|
|
150
|
+
// console.log(roleFiltered);
|
|
151
|
+
// console.log(levelFiltered);
|
|
152
|
+
// console.log(zoneFiltered);
|
|
153
|
+
for (const tic of levelFiltered) {
|
|
154
|
+
if (domFiltered.includes(tic) &&
|
|
155
|
+
roleFiltered.includes(tic) &&
|
|
156
|
+
zoneFiltered.includes(tic)) {
|
|
157
|
+
finalTickets.push(tic);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
// console.log(finalTickets);
|
|
163
|
+
return finalTickets;
|
|
164
|
+
}
|
|
165
|
+
subscribeToDataFilterUpdate(next, error, complete) {
|
|
166
|
+
const s = this.updateDateFilter.subscribe(next, error, complete);
|
|
167
|
+
return s;
|
|
168
|
+
}
|
|
169
|
+
dateFilterUpdated(dateRange) {
|
|
170
|
+
this.currentDateFilter = dateRange;
|
|
171
|
+
this.updateDateFilter.next(dateRange);
|
|
172
|
+
}
|
|
173
|
+
filterObjectsForDateRange(objects, dateRange) {
|
|
174
|
+
return objects.filter((object) => {
|
|
175
|
+
const createdAtDate = new Date(object.createdAt);
|
|
176
|
+
return (createdAtDate >= dateRange[0] && createdAtDate <= dateRange[1]);
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
filterMeasurementsForDateRange(measurements, dateRange) {
|
|
180
|
+
return measurements.filter((measure) => {
|
|
181
|
+
const createdAtDate = new Date(measure.comment.createdAt);
|
|
182
|
+
return (createdAtDate >= dateRange[0] && createdAtDate <= dateRange[1]);
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
async filterObjectsForZone(objects, zoneID = null, zone = null) {
|
|
186
|
+
const filteredObjects = [];
|
|
187
|
+
await Promise.all(objects.map(async (object) => {
|
|
188
|
+
const [poi] = object.pois.items;
|
|
189
|
+
if (poi && zone) {
|
|
190
|
+
if (zone.sweepIDs && zone.sweepIDs.includes(poi.matterportSweepID)) {
|
|
191
|
+
if (this.poiService.poiIsVirtual(poi) && zone.layer && zone.layer.name === "FLOOR") {
|
|
192
|
+
// we include in Floor zone only
|
|
193
|
+
filteredObjects.push(object);
|
|
194
|
+
}
|
|
195
|
+
if (!this.poiService.poiIsVirtual(poi)) {
|
|
196
|
+
filteredObjects.push(object);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
if (poi && !zone && zoneID) {
|
|
201
|
+
const zones = await this.zoneService.getZonesForObject(object);
|
|
202
|
+
if (zones &&
|
|
203
|
+
zones.some((zone_) => zone_.id === zoneID ||
|
|
204
|
+
zone_.parentID === zoneID)) {
|
|
205
|
+
filteredObjects.push(object);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}));
|
|
209
|
+
return filteredObjects;
|
|
210
|
+
}
|
|
211
|
+
filterEquipmentsByDomainList(equipments, domainIDList) {
|
|
212
|
+
let filtered = [];
|
|
213
|
+
const filteredByDomain = equipments.filter((equip) => domainIDList.includes(equip.domainID));
|
|
214
|
+
filtered = [...filtered, ...filteredByDomain];
|
|
215
|
+
const filteredByParentDomain = equipments.filter((equip) => equip.domain &&
|
|
216
|
+
equip.domain.parentID &&
|
|
217
|
+
domainIDList.includes(equip.domain.parentID));
|
|
218
|
+
filtered = [...filtered, ...filteredByParentDomain];
|
|
219
|
+
return filterUniqueArrayByID(filtered);
|
|
220
|
+
}
|
|
221
|
+
filterEquipmentsForTerm(equips, term) {
|
|
222
|
+
// filter domains
|
|
223
|
+
let byDomain = equips.filter((eq) => {
|
|
224
|
+
if (eq.domain && eq.domain.name) {
|
|
225
|
+
const normalizedDomain = eq.domain.name.toLowerCase();
|
|
226
|
+
const lev = levenshtein(normalizedDomain, term);
|
|
227
|
+
return lev <= 2 || normalizedDomain.includes(term);
|
|
228
|
+
}
|
|
229
|
+
return false;
|
|
230
|
+
});
|
|
231
|
+
const byParentDomain = equips.filter((eq) => {
|
|
232
|
+
if (eq.domain && eq.domain.parentID) {
|
|
233
|
+
const normalizedParent = eq.domain.parent.name.toLowerCase();
|
|
234
|
+
const lev = levenshtein(normalizedParent, term);
|
|
235
|
+
return lev <= 2 || normalizedParent.includes(term);
|
|
236
|
+
}
|
|
237
|
+
return false;
|
|
238
|
+
});
|
|
239
|
+
byDomain = [...byDomain, ...byParentDomain];
|
|
240
|
+
// filter name
|
|
241
|
+
let byName = [];
|
|
242
|
+
const terms = term.split(" ").filter((token) => token.length > 2);
|
|
243
|
+
for (const eq of equips) {
|
|
244
|
+
const words = eq.name
|
|
245
|
+
.toLowerCase()
|
|
246
|
+
.split(" ")
|
|
247
|
+
.filter((token) => token.length > 2);
|
|
248
|
+
const matched = [];
|
|
249
|
+
for (const token of terms) {
|
|
250
|
+
for (const word of words) {
|
|
251
|
+
if (levenshtein(token, word) <= 1) {
|
|
252
|
+
matched.push(true);
|
|
253
|
+
break;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
if (matched.length === terms.length) {
|
|
258
|
+
byName.push(eq);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
const byNameSimple = equips.filter((eq) => eq.name.toLowerCase().includes(term));
|
|
262
|
+
byName = [...byName, ...byNameSimple];
|
|
263
|
+
// by serial number
|
|
264
|
+
const bySerialNumber = equips.filter((eq) => eq.serialNumber && eq.serialNumber.toLowerCase() === term);
|
|
265
|
+
const result = [...byDomain, ...byName, ...bySerialNumber];
|
|
266
|
+
return filterUniqueArrayByID(result);
|
|
267
|
+
}
|
|
268
|
+
filterTicketsForTerm(tickets, term) {
|
|
269
|
+
// filter term in title and description
|
|
270
|
+
const byTitle = this.filterObjectsForTerm(tickets, term);
|
|
271
|
+
// by equipment
|
|
272
|
+
const byEquipment = tickets.filter((ticket) => ticket.equipments &&
|
|
273
|
+
this.filterEquipmentsForTerm(ticket.equipments, term).length >
|
|
274
|
+
0);
|
|
275
|
+
return filterUniqueArrayByID([...byTitle, ...byEquipment]);
|
|
276
|
+
}
|
|
277
|
+
filterLocationsForTerm(locations, term) {
|
|
278
|
+
// by name
|
|
279
|
+
const byName = locations.filter((loc) => loc.name.toLowerCase().includes(term));
|
|
280
|
+
// by address
|
|
281
|
+
const byAddress = locations.filter((loc) => loc.addresses.toLowerCase().includes(term));
|
|
282
|
+
return filterUniqueArrayByID([...byName, ...byAddress]);
|
|
283
|
+
}
|
|
284
|
+
filterOrganisationsForTerm(orgs, term) {
|
|
285
|
+
const byName = orgs.filter((org) => {
|
|
286
|
+
const words = org.name.toLowerCase().split(" ");
|
|
287
|
+
return (words.some((word) => word.length > 2 && levenshtein(word, term) <= 1) || org.name.toLowerCase().includes(term));
|
|
288
|
+
});
|
|
289
|
+
return byName;
|
|
290
|
+
}
|
|
291
|
+
filterUsersForTerm(users, term) {
|
|
292
|
+
const byName = users.filter((user) => {
|
|
293
|
+
const words = user.displayName.toLowerCase().split(" ");
|
|
294
|
+
return (words.some((word) => word.length > 2 && levenshtein(word, term) <= 1) || user.displayName.toLowerCase().includes(term));
|
|
295
|
+
});
|
|
296
|
+
return byName;
|
|
297
|
+
}
|
|
298
|
+
async filterFeaturesForCurrentUserInSpace(features, spaceID) {
|
|
299
|
+
const finalFeatures = [];
|
|
300
|
+
let levelFiltered = features;
|
|
301
|
+
let zoneFiltered = features;
|
|
302
|
+
let hashtagFiltered = features;
|
|
303
|
+
const missions = this.userService.currentMissions;
|
|
304
|
+
if (missions) {
|
|
305
|
+
const currentSpaceMissions = missions.filter((m) => m.spaceID === spaceID);
|
|
306
|
+
if (currentSpaceMissions.length > 0) {
|
|
307
|
+
const highestLelel = getHighestLevelForMissions(currentSpaceMissions);
|
|
308
|
+
const highestRole = getHighestRoleForMissions(currentSpaceMissions);
|
|
309
|
+
const filters = this.getFiltersForRole(highestRole);
|
|
310
|
+
for (const filter of filters) {
|
|
311
|
+
if (filter === FilterType.LEVEL) {
|
|
312
|
+
levelFiltered = this.filterObjectsByLevel(features, highestLelel);
|
|
313
|
+
}
|
|
314
|
+
if (filter === FilterType.ZONE) {
|
|
315
|
+
zoneFiltered = await this.applyZoneFilterForMissions(currentSpaceMissions, features);
|
|
316
|
+
}
|
|
317
|
+
if (filter === FilterType.HASHTAG) {
|
|
318
|
+
hashtagFiltered =
|
|
319
|
+
this.filterFeaturesByHashtagsAndLocale(currentSpaceMissions, features);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
for (const feature of levelFiltered) {
|
|
323
|
+
if (hashtagFiltered.includes(feature) &&
|
|
324
|
+
zoneFiltered.includes(feature)) {
|
|
325
|
+
finalFeatures.push(feature);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return finalFeatures;
|
|
331
|
+
}
|
|
332
|
+
filterFeaturesForTerm(features, term) {
|
|
333
|
+
// filter term in title
|
|
334
|
+
const byTitle = this.filterObjectsForTerm(features, term);
|
|
335
|
+
// by comments
|
|
336
|
+
const byComment = features.filter((feature) => this.filterObjectsForTerm(feature.comments.items, term).length >
|
|
337
|
+
0);
|
|
338
|
+
return filterUniqueArrayByID([...byTitle, ...byComment]);
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
*
|
|
342
|
+
* @param objects Array of Comments, Tickets, Features. Obligatory proporties: title, description
|
|
343
|
+
* @param term string
|
|
344
|
+
*/
|
|
345
|
+
filterObjectsForTerm(objects, term) {
|
|
346
|
+
// filter term in title
|
|
347
|
+
const byTitle = objects.filter((feature) => {
|
|
348
|
+
const words = feature.title.toLowerCase().split(" ");
|
|
349
|
+
return (words.some((word) => word.length > 2 && levenshtein(word, term) <= 1) || feature.title.toLowerCase().includes(term));
|
|
350
|
+
});
|
|
351
|
+
// term present in description
|
|
352
|
+
const byDescription = objects.filter((feature) => feature.description &&
|
|
353
|
+
feature.description.toLowerCase().includes(term));
|
|
354
|
+
return filterUniqueArrayByID([...byTitle, ...byDescription]);
|
|
355
|
+
}
|
|
356
|
+
filterMissionByStartTimeDateForDateRange(missions, dateRange) {
|
|
357
|
+
return missions.filter((mission) => {
|
|
358
|
+
const startDateTime = new Date(mission.startDateTime);
|
|
359
|
+
return (startDateTime >= dateRange[0] && startDateTime <= dateRange[1]);
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
async applyZoneFilterForMissions(currentSpaceMissions, objects) {
|
|
363
|
+
const allowedZones = [];
|
|
364
|
+
for (const mission of currentSpaceMissions) {
|
|
365
|
+
if (mission.zoneID) {
|
|
366
|
+
allowedZones.push(mission.zoneID);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
if (allowedZones.length === currentSpaceMissions.length) {
|
|
370
|
+
let allZoneFiltered = [];
|
|
371
|
+
await Promise.all(allowedZones.map(async (zoneID) => {
|
|
372
|
+
const currentZoneFiltered = await this.filterObjectsForZone(objects, zoneID);
|
|
373
|
+
allZoneFiltered = [
|
|
374
|
+
...allZoneFiltered,
|
|
375
|
+
...currentZoneFiltered,
|
|
376
|
+
];
|
|
377
|
+
}));
|
|
378
|
+
return filterUniqueArrayByID(allZoneFiltered);
|
|
379
|
+
}
|
|
380
|
+
return objects;
|
|
381
|
+
}
|
|
382
|
+
async filterEquipmentsForCurrentUserInSpace(spaceID, equips) {
|
|
383
|
+
const finalEquips = [];
|
|
384
|
+
let domFiltered = equips;
|
|
385
|
+
const roleFiltered = equips;
|
|
386
|
+
const levelFiltered = equips;
|
|
387
|
+
let zoneFiltered = equips;
|
|
388
|
+
const missions = this.userService.currentMissions;
|
|
389
|
+
if (missions) {
|
|
390
|
+
const currentSpaceMissions = missions.filter((m) => m.spaceID === spaceID);
|
|
391
|
+
if (currentSpaceMissions.length > 0) {
|
|
392
|
+
const highestLelel = getHighestLevelForMissions(currentSpaceMissions);
|
|
393
|
+
const highestRole = getHighestRoleForMissions(currentSpaceMissions);
|
|
394
|
+
// console.log("Highest level: ", highestLelel, ", Highest Role: ", highestRole)
|
|
395
|
+
const filters = this.getFiltersForRole(highestRole);
|
|
396
|
+
for (const filter of filters) {
|
|
397
|
+
if (filter === FilterType.DOMAIN) {
|
|
398
|
+
let domains = [];
|
|
399
|
+
for (const m of currentSpaceMissions) {
|
|
400
|
+
if (m.domains) {
|
|
401
|
+
domains = [...domains, ...m.domains];
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
let allDomainsFiltered = [];
|
|
405
|
+
const currentDomFiltered = this.filterEquipmentsByDomainList(equips, domains);
|
|
406
|
+
allDomainsFiltered = [
|
|
407
|
+
...allDomainsFiltered,
|
|
408
|
+
...currentDomFiltered,
|
|
409
|
+
];
|
|
410
|
+
domFiltered = allDomainsFiltered;
|
|
411
|
+
}
|
|
412
|
+
if (filter === FilterType.ROLE) {
|
|
413
|
+
// const highestRoleMission = currentSpaceMissions.find(
|
|
414
|
+
// (m) => m.role === highestRole,
|
|
415
|
+
// );
|
|
416
|
+
// TODO
|
|
417
|
+
}
|
|
418
|
+
if (filter === FilterType.LEVEL) {
|
|
419
|
+
// TODO, equipment does not have level
|
|
420
|
+
}
|
|
421
|
+
if (filter === FilterType.ZONE) {
|
|
422
|
+
zoneFiltered = await this.applyZoneFilterForMissions(currentSpaceMissions, equips);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
for (const tic of levelFiltered) {
|
|
426
|
+
if (domFiltered.includes(tic) &&
|
|
427
|
+
roleFiltered.includes(tic) &&
|
|
428
|
+
zoneFiltered.includes(tic)) {
|
|
429
|
+
finalEquips.push(tic);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
return finalEquips;
|
|
435
|
+
}
|
|
436
|
+
async filterMeasurementsForCurrentUserInSpace(spaceID, comments) {
|
|
437
|
+
let finalMeasurements = [];
|
|
438
|
+
let zoneFiltered = comments;
|
|
439
|
+
const missions = this.userService.currentMissions;
|
|
440
|
+
if (missions) {
|
|
441
|
+
const currentSpaceMissions = missions.filter((m) => m.spaceID === spaceID);
|
|
442
|
+
if (currentSpaceMissions.length > 0) {
|
|
443
|
+
const highestRole = getHighestRoleForMissions(currentSpaceMissions);
|
|
444
|
+
const filters = this.getFiltersForRole(highestRole);
|
|
445
|
+
for (const filter of filters) {
|
|
446
|
+
if (filter === FilterType.ZONE) {
|
|
447
|
+
zoneFiltered = await this.applyZoneFilterForMissions(currentSpaceMissions, comments);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
finalMeasurements = zoneFiltered;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
return finalMeasurements;
|
|
454
|
+
}
|
|
455
|
+
async isObjectAllowedForUserInSpace(object, spaceID) {
|
|
456
|
+
const mission = this.userService.currentMission(spaceID);
|
|
457
|
+
const filters = this.getFiltersForRole(mission.role);
|
|
458
|
+
for (const filter of filters) {
|
|
459
|
+
if (filter === FilterType.LEVEL &&
|
|
460
|
+
Object.prototype.hasOwnProperty.call(object, "level")) {
|
|
461
|
+
const levelFiltered = this.filterObjectsByLevel([object], mission.level);
|
|
462
|
+
if (levelFiltered.length === 0) {
|
|
463
|
+
return false;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
if (filter === FilterType.ZONE) {
|
|
467
|
+
const zoneFiltered = await this.applyZoneFilterForMissions([mission], [object]);
|
|
468
|
+
if (zoneFiltered.length === 0) {
|
|
469
|
+
return false;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
return true;
|
|
474
|
+
}
|
|
475
|
+
filterTemplatesForTerm(missions, term) {
|
|
476
|
+
// term present in description
|
|
477
|
+
const byDescription = missions.filter((mis) => mis.description && mis.description.toLowerCase().includes(term));
|
|
478
|
+
// by user lastName which is the name of the visit:
|
|
479
|
+
// metadata: "{\"firstName\":\"\",\"lastName\":\"Visite du 5 Juillet\"}"
|
|
480
|
+
const userProfiles = missions.map((mis) => new ProfileEntity(mis.user));
|
|
481
|
+
const byUserLastname = this.filterUsersForTerm(userProfiles, term);
|
|
482
|
+
const userIds = new Set(byUserLastname.map((user) => user.id));
|
|
483
|
+
const missionsByUser = missions.filter((mis) => userIds.has(mis.userID));
|
|
484
|
+
return filterUniqueArrayByID([...byDescription, ...missionsByUser]);
|
|
485
|
+
}
|
|
486
|
+
async filterObjectsForSweep(objects, objectType, sweep) {
|
|
487
|
+
let filtered = [];
|
|
488
|
+
switch (objectType) {
|
|
489
|
+
case PoiType.EQUIPMENT:
|
|
490
|
+
const pois = await this.poiService.getPoisByMatterportSweepByType(sweep, objectType);
|
|
491
|
+
const equipIDs = new Set(pois.map((poi) => poi.elementID));
|
|
492
|
+
filtered = objects.filter((object) => equipIDs.has(object.id));
|
|
493
|
+
break;
|
|
494
|
+
default:
|
|
495
|
+
break;
|
|
496
|
+
}
|
|
497
|
+
return filtered;
|
|
498
|
+
}
|
|
499
|
+
filterFeaturesByHashtagsAndLocale(currentSpaceMissions, features) {
|
|
500
|
+
const [currentMission] = currentSpaceMissions;
|
|
501
|
+
// filter by locale
|
|
502
|
+
let filteredLocale = [...features];
|
|
503
|
+
if (currentMission.locale) {
|
|
504
|
+
filteredLocale = features.filter((feature) => feature.locale && feature.locale === currentMission.locale);
|
|
505
|
+
}
|
|
506
|
+
// filter by hashtags
|
|
507
|
+
if (currentMission.hashtags && currentMission.hashtags.length > 0) {
|
|
508
|
+
const filteredByHashtags = [];
|
|
509
|
+
for (const feature of filteredLocale) {
|
|
510
|
+
if (!feature.hashtags || feature.hashtags.length === 0) {
|
|
511
|
+
// Feature without hashtag is available for everybody
|
|
512
|
+
filteredByHashtags.push(feature);
|
|
513
|
+
}
|
|
514
|
+
else if (currentMission.hashtags.every((hashtag) => feature.hashtags.includes(hashtag))) {
|
|
515
|
+
filteredByHashtags.push(feature);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
return filteredByHashtags;
|
|
519
|
+
}
|
|
520
|
+
return filteredLocale;
|
|
521
|
+
}
|
|
522
|
+
filterFeaturesForMissionWithoutZone(features, mission) {
|
|
523
|
+
const finalFeatures = [];
|
|
524
|
+
let levelFiltered = features;
|
|
525
|
+
let zoneFiltered = features;
|
|
526
|
+
let hashtagFiltered = features;
|
|
527
|
+
const filters = this.getFiltersForRole(mission.role);
|
|
528
|
+
for (const filter of filters) {
|
|
529
|
+
if (filter === FilterType.LEVEL) {
|
|
530
|
+
levelFiltered = this.filterObjectsByLevel(features, mission.level);
|
|
531
|
+
}
|
|
532
|
+
// if (filter === FilterType.ZONE) {
|
|
533
|
+
// zoneFiltered = await this.applyZoneFilterForMissions(
|
|
534
|
+
// currentSpaceMissions,
|
|
535
|
+
// features,
|
|
536
|
+
// );
|
|
537
|
+
// }
|
|
538
|
+
if (filter === FilterType.HASHTAG) {
|
|
539
|
+
hashtagFiltered =
|
|
540
|
+
this.filterFeaturesByHashtagsAndLocale([mission], features);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
for (const feature of levelFiltered) {
|
|
544
|
+
if (hashtagFiltered.includes(feature) &&
|
|
545
|
+
zoneFiltered.includes(feature)) {
|
|
546
|
+
finalFeatures.push(feature);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
return finalFeatures;
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
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 });
|
|
553
|
+
FilterService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: FilterService, providedIn: "root" });
|
|
554
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: FilterService, decorators: [{
|
|
555
|
+
type: Injectable,
|
|
556
|
+
args: [{
|
|
557
|
+
providedIn: "root",
|
|
558
|
+
}]
|
|
559
|
+
}], ctorParameters: function () { return [{ type: i1.BaseUserService }, { type: i2.ZoneService }, { type: i3.PoiService }]; } });
|
|
560
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsdGVyLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtc21hcnRlcnBsYW4tY29yZS9zcmMvbGliL3NlcnZpY2VzL2ZpbHRlci5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLHlDQUF5QztBQUN6QyxxQ0FBcUM7QUFDckMsaUNBQWlDO0FBQ2pDLDJDQUEyQztBQUMzQyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNDLE9BQU8sRUFBRSxPQUFPLEVBQWdCLE1BQU0sTUFBTSxDQUFDO0FBQzdDLE9BQU8sRUFBRSxjQUFjLEVBQUUsMEJBQTBCLEVBQUUseUJBQXlCLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNsSSxPQUFPLEVBQW9FLE9BQU8sRUFBRSxhQUFhLEVBQUUsVUFBVSxFQUFnRSxNQUFNLGtCQUFrQixDQUFDO0FBWXRNLE9BQU8sV0FBVyxNQUFNLGdCQUFnQixDQUFDOzs7OztBQVJ6QyxJQUFLLFVBT0o7QUFQRCxXQUFLLFVBQVU7SUFDWCwrQkFBaUIsQ0FBQTtJQUNqQiw2QkFBZSxDQUFBO0lBQ2YsMkJBQWEsQ0FBQTtJQUNiLDJCQUFhLENBQUE7SUFDYiw2QkFBZSxDQUFBO0lBQ2YsaUNBQW1CLENBQUE7QUFDdkIsQ0FBQyxFQVBJLFVBQVUsS0FBVixVQUFVLFFBT2Q7QUFLRCxNQUFNLE9BQU8sYUFBYTtJQUt0QixZQUNZLFdBQTRCLEVBQzVCLFdBQXdCLEVBQ3hCLFVBQXNCO1FBRnRCLGdCQUFXLEdBQVgsV0FBVyxDQUFpQjtRQUM1QixnQkFBVyxHQUFYLFdBQVcsQ0FBYTtRQUN4QixlQUFVLEdBQVYsVUFBVSxDQUFZO1FBUDFCLHFCQUFnQixHQUFvQixJQUFJLE9BQU8sRUFBRSxDQUFDO0lBUXZELENBQUM7SUFFSixxQkFBcUIsQ0FBQyxlQUF5QixFQUFFLE1BQWM7UUFDM0QsT0FBTyxlQUFlLENBQUMs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VCxhQUFhO2tCQUh6QixVQUFVO21CQUFDO29CQUNSLFVBQVUsRUFBRSxNQUFNO2lCQUNyQiIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNhc2UtZGVjbGFyYXRpb25zICovXHJcbi8qIGVzbGludC1kaXNhYmxlIG5vLWF3YWl0LWluLWxvb3AgKi9cclxuLyogZXNsaW50LWRpc2FibGUgZ3VhcmQtZm9yLWluICovXHJcbi8qIGVzbGludC1kaXNhYmxlIGNsYXNzLW1ldGhvZHMtdXNlLXRoaXMgKi9cclxuaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XHJcbmltcG9ydCB7IFN1YmplY3QsIFN1YnNjcmlwdGlvbiB9IGZyb20gXCJyeGpzXCI7XHJcbmltcG9ydCB7IGdldExldmVsc0JlbG93LCBnZXRIaWdoZXN0TGV2ZWxGb3JNaXNzaW9ucywgZ2V0SGlnaGVzdFJvbGVGb3JNaXNzaW9ucywgZmlsdGVyVW5pcXVlQXJyYXlCeUlEIH0gZnJvbSBcIi4uL2hlbHBlcnMuc2VydmljZVwiO1xyXG5pbXBvcnQgeyBab25lLCBFcXVpcG1lbnQsIExldmVsU3RhdHVzLCBNZWFzdXJlbWVudCwgTWlzc2lvbiwgT3JnYW5pc2F0aW9uLCBQb2lUeXBlLCBQcm9maWxlRW50aXR5LCBSb2xlU3RhdHVzLCBTcGFjZSwgVGlja2V0LCBEYk9iamVjdFR5cGUsIEZlYXR1cmUsIENvbW1lbnQsIFZpc2l0VGVtcGxhdGUgfSBmcm9tIFwiLi4vdHlwZXMuc2VydmljZVwiO1xyXG5pbXBvcnQgeyBQb2lTZXJ2aWNlIH0gZnJvbSBcIi4vbW9kZWxzL3BvaS5zZXJ2aWNlXCI7XHJcbmltcG9ydCB7IFpvbmVTZXJ2aWNlIH0gZnJvbSBcIi4vbW9kZWxzL3pvbmUuc2VydmljZVwiO1xyXG5pbXBvcnQgeyBCYXNlVXNlclNlcnZpY2UgfSBmcm9tIFwiLi91c2VyLnNlcnZpY2VcIjtcclxuZW51bSBGaWx0ZXJUeXBlIHtcclxuICAgIERPTUFJTiA9IFwiRE9NQUlOXCIsXHJcbiAgICBMRVZFTCA9IFwiTEVWRUxcIixcclxuICAgIFJPTEUgPSBcIlJPTEVcIixcclxuICAgIFpPTkUgPSBcIlpPTkVcIixcclxuICAgIFNQQUNFID0gXCJTUEFDRVwiLFxyXG4gICAgSEFTSFRBRyA9IFwiSEFTSFRBR1wiLFxyXG59XHJcbmltcG9ydCBsZXZlbnNodGVpbiBmcm9tICdqcy1sZXZlbnNodGVpbic7XHJcbkBJbmplY3RhYmxlKHtcclxuICAgIHByb3ZpZGVkSW46IFwicm9vdFwiLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgRmlsdGVyU2VydmljZSB7XHJcbiAgICBwcml2YXRlIHVwZGF0ZURhdGVGaWx0ZXI6IFN1YmplY3Q8RGF0ZVtdPiA9IG5ldyBTdWJqZWN0KCk7XHJcblxyXG4gICAgcHVibGljIGN1cnJlbnREYXRlRmlsdGVyOiBEYXRlW107XHJcblxyXG4gICAgY29uc3RydWN0b3IoXHJcbiAgICAgICAgcHJpdmF0ZSB1c2VyU2VydmljZTogQmFzZVVzZXJTZXJ2aWNlLFxyXG4gICAgICAgIHByaXZhdGUgem9uZVNlcnZpY2U6IFpvbmVTZXJ2aWNlLFxyXG4gICAgICAgIHByaXZhdGUgcG9pU2VydmljZTogUG9pU2VydmljZSxcclxuICAgICkge31cclxuXHJcbiAgICBmaWx0ZXJUaWNrZXRzQnlEb21haW4odGlja2V0c1RvRmlsdGVyOiBUaWNrZXRbXSwgZG9tYWluOiBzdHJpbmcpIHtcclxuICAgICAgICByZXR1cm4gdGlja2V0c1RvRmlsdGVyLmZpbHRlcigodGljKSA9PiB0aWMuZG9tYWluSUQgPT09IGRvbWFpbik7XHJcbiAgICB9XHJcblxyXG4gICAgZmlsdGVyT2JqZWN0c0J5TGV2ZWwob2JqZWN0c1RvRmlsdGVyOiBhbnlbXSwgbGV2ZWw6IExldmVsU3RhdHVzKTogYW55W10ge1xyXG4gICAgICAgIGNvbnN0IHZpc2libGVMZXZlbHMgPSBnZXRMZXZlbHNCZWxvdyhsZXZlbCk7XHJcbiAgICAgICAgY29uc3QgZmlsdGVyZWQgPSBvYmplY3RzVG9GaWx0ZXIuZmlsdGVyKCh0aWMpID0+XHJcbiAgICAgICAgICAgIHZpc2libGVMZXZlbHMuaW5jbHVkZXModGljLmxldmVsKSxcclxuICAgICAgICApO1xyXG4gICAgICAgIHJldHVybiBmaWx0ZXJlZDtcclxuICAgIH1cclxuXHJcbiAgICBmaWx0ZXJUaWNrZXRzRm9yTWlzc2lvbihcclxuICAgICAgICB0aWNrZXRzVG9GaWx0ZXI6IFRpY2tldFtdLFxyXG4gICAgICAgIG1pc3Npb246IE1pc3Npb24sXHJcbiAgICApOiBUaWNrZXRbXSB7XHJcbiAgICAgICAgY29uc3QgbWFuYWdlclJvbGVzOiBSb2xlU3RhdHVzW10gPSBbXHJcbiAgICAgICAgICAgIFJvbGVTdGF0dXMuTUFOQUdFUixcclxuICAgICAgICAgICAgUm9sZVN0YXR1cy5BRE1JTixcclxuICAgICAgICAgICAgUm9sZVN0YXR1cy5PV05FUixcclxuICAgICAgICBdO1xyXG4gICAgICAgIGlmICghbWFuYWdlclJvbGVzLmluY2x1ZGVzKG1pc3Npb24ucm9sZSkpIHtcclxuICAgICAgICAgICAgaWYgKG1pc3Npb24ucm9sZSA9PT0gUm9sZVN0YXR1cy5TRVJWSUNFKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBTRVJWSUNFIGNhbiBzZWUgdGlja2V0cyB0byB3aGljaCBoZSBpcyBhc3NpZ25lZFxyXG4gICAgICAgICAgICAgICAgY29uc3QgdGlja2V0c0Fzc2lnbmVkID0gW107XHJcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHQgb2YgdGlja2V0c1RvRmlsdGVyKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHQuYXNzaWduZWVzLml0ZW1zLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBhc3NpZ25tZW50IG9mIHQuYXNzaWduZWVzLml0ZW1zKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXNzaWdubWVudC5taXNzaW9uSUQgPT09IG1pc3Npb24uaWQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aWNrZXRzQXNzaWduZWQucHVzaCh0KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIHJldHVybiB0aWNrZXRzQXNzaWduZWQ7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgLy8gT0NDVVBBTlQgYW5kIFZJU0lUT1IgY2FuIHNlZSBvbmx5IHRpY2tldHMgdGhhdCB0aGV5IGNyZWF0ZWRcclxuICAgICAgICAgICAgcmV0dXJuIHRpY2tldHNUb0ZpbHRlci5maWx0ZXIoKHRpY2tldCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRpY2tldC5vd25lck1pc3Npb25JRCA9PT0gbWlzc2lvbi5pZDtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0aWNrZXRzVG9GaWx0ZXI7XHJcbiAgICB9XHJcblxyXG4gICAgZ2V0RmlsdGVyc0ZvclJvbGUocm9sZTogUm9sZVN0YXR1cyk6IEZpbHRlclR5cGVbXSB7XHJcbiAgICAgICAgc3dpdGNoIChyb2xlKSB7XHJcbiAgICAgICAgICAgIGNhc2UgUm9sZVN0YXR1cy5BRE1JTjpcclxuICAgICAgICAgICAgICAgIHJldHVybiBbRmlsdGVyVHlwZS5MRVZFTF07XHJcbiAgICAgICAgICAgIGNhc2UgUm9sZVN0YXR1cy5NQU5BR0VSOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIFtGaWx0ZXJUeXBlLlpPTkUsIEZpbHRlclR5cGUuTEVWRUxdO1xyXG4gICAgICAgICAgICBjYXNlIFJvbGVTdGF0dXMuT1dORVI6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gW0ZpbHRlclR5cGUuWk9ORSwgRmlsdGVyVHlwZS5MRVZFTF07XHJcbiAgICAgICAgICAgIGNhc2UgUm9sZVN0YXR1cy5TRVJWSUNFOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIFtcclxuICAgICAgICAgICAgICAgICAgICAvLyBGaWx0ZXJUeXBlLlpPTkUsXHJcbiAgICAgICAgICAgICAgICAgICAgLy8gRmlsdGVyVHlwZS5MRVZFTCxcclxuICAgICAgICAgICAgICAgICAgICAvLyBGaWx0ZXJUeXBlLkRPTUFJTixcclxuICAgICAgICAgICAgICAgICAgICBGaWx0ZXJUeXBlLlJPTEUsIC8vIHRoYXQgaXMgdGhlIG1vc3Qgc2V2ZXJlIGZpbHRlclxyXG4gICAgICAgICAgICAgICAgXTtcclxuICAgICAgICAgICAgY2FzZSBSb2xlU3RhdHVzLk9DQ1VQQU5UOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIFtcclxuICAgICAgICAgICAgICAgICAgICBGaWx0ZXJUeXBlLlpPTkUsXHJcbiAgICAgICAgICAgICAgICAgICAgRmlsdGVyVHlwZS5ET01BSU4sXHJcbiAgICAgICAgICAgICAgICAgICAgRmlsdGVyVHlwZS5ST0xFLFxyXG4gICAgICAgICAgICAgICAgICAgIEZpbHRlclR5cGUuTEVWRUwsXHJcbiAgICAgICAgICAgICAgICAgICAgRmlsdGVyVHlwZS5IQVNIVEFHLFxyXG4gICAgICAgICAgICAgICAgXTtcclxuICAgICAgICAgICAgY2FzZSBSb2xlU3RhdHVzLlZJU0lUT1I6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gW1xyXG4gICAgICAgICAgICAgICAgICAgIEZpbHRlclR5cGUuWk9ORSxcclxuICAgICAgICAgICAgICAgICAgICBGaWx0ZXJUeXBlLkxFVkVMLFxyXG4gICAgICAgICAgICAgICAgICAgIEZpbHRlclR5cGUuRE9NQUlOLFxyXG4gICAgICAgICAgICAgICAgICAgIEZpbHRlclR5cGUuUk9MRSxcclxuICAgICAgICAgICAgICAgICAgICBGaWx0ZXJUeXBlLkhBU0hUQUcsXHJcbiAgICAgICAgICAgICAgICBdO1xyXG4gICAgICAgICAgICBjYXNlIFJvbGVTdGF0dXMuVklTSVRPUl9NVVNFVU06XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gW0ZpbHRlclR5cGUuWk9ORSwgRmlsdGVyVHlwZS5MRVZFTCwgRmlsdGVyVHlwZS5IQVNIVEFHXTtcclxuICAgICAgICAgICAgY2FzZSBSb2xlU3RhdHVzLkdVSURFX01VU0VVTTpcclxuICAgICAgICAgICAgICAgIHJldHVybiBbRmlsdGVyVHlwZS5MRVZFTF07XHJcbiAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gW0ZpbHRlclR5cGUuTEVWRUxdO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBhc3luYyBmaWx0ZXJUaWNrZXRzRm9yQ3VycmVudFVzZXJJblNwYWNlKFxyXG4gICAgICAgIHRpY2tldHM6IFRpY2tldFtdLFxyXG4gICAgICAgIHNwYWNlSUQ6IHN0cmluZyxcclxuICAgICk6IFByb21pc2U8VGlja2V0W10+IHtcclxuICAgICAgICBjb25zdCBmaW5hbFRpY2tldHM6IFRpY2tldFtdID0gW107XHJcbiAgICAgICAgbGV0IGRvbUZpbHRlcmVkOiBUaWNrZXRbXSA9IHRpY2tldHM7XHJcbiAgICAgICAgbGV0IHJvbGVGaWx0ZXJlZDogVGlja2V0W10gPSB0aWNrZXRzO1xyXG4gICAgICAgIGxldCBsZXZlbEZpbHRlcmVkOiBUaWNrZXRbXSA9IHRpY2tldHM7XHJcbiAgICAgICAgbGV0IHpvbmVGaWx0ZXJlZDogVGlja2V0W10gPSB0aWNrZXRzO1xyXG4gICAgICAgIGNvbnN0IG1pc3Npb25zID0gdGhpcy51c2VyU2VydmljZS5jdXJyZW50TWlzc2lvbnM7XHJcbiAgICAgICAgaWYgKG1pc3Npb25zKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRTcGFjZU1pc3Npb25zID0gbWlzc2lvbnMuZmlsdGVyKFxyXG4gICAgICAgICAgICAgICAgKG0pID0+IG0uc3BhY2VJRCA9PT0gc3BhY2VJRCxcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgaWYgKGN1cnJlbnRTcGFjZU1pc3Npb25zLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGhpZ2hlc3RMZWxlbCA9XHJcbiAgICAgICAgICAgICAgICAgICAgZ2V0SGlnaGVzdExldmVsRm9yTWlzc2lvbnMoY3VycmVudFNwYWNlTWlzc2lvbnMpO1xyXG4gICAgICAgICAgICAgICAgY29uc3QgaGlnaGVzdFJvbGUgPVxyXG4gICAgICAgICAgICAgICAgICAgIGdldEhpZ2hlc3RSb2xlRm9yTWlzc2lvbnMoY3VycmVudFNwYWNlTWlzc2lvbnMpO1xyXG4gICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJIaWdoZXN0IGxldmVsOiBcIiwgaGlnaGVzdExlbGVsLCBcIiwgSGlnaGVzdCBSb2xlOiBcIiwgaGlnaGVzdFJvbGUpXHJcblxyXG4gICAgICAgICAgICAgICAgY29uc3QgZmlsdGVycyA9IHRoaXMuZ2V0RmlsdGVyc0ZvclJvbGUoaGlnaGVzdFJvbGUpO1xyXG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBmaWx0ZXIgb2YgZmlsdGVycykge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChmaWx0ZXIgPT09IEZpbHRlclR5cGUuRE9NQUlOKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBkb21haW5zOiBzdHJpbmdbXSA9IFtdO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IG0gb2YgY3VycmVudFNwYWNlTWlzc2lvbnMpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtLmRvbWFpbnMpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb21haW5zID0gWy4uLmRvbWFpbnMsIC4uLm0uZG9tYWluc107XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGFsbERvbWFpbnNGaWx0ZXJlZCA9IFtdO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGQgb2YgZG9tYWlucykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY3VycmVudERvbUZpbHRlcmVkID1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmZpbHRlclRpY2tldHNCeURvbWFpbih0aWNrZXRzLCBkKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsbERvbWFpbnNGaWx0ZXJlZCA9IFtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5hbGxEb21haW5zRmlsdGVyZWQsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uY3VycmVudERvbUZpbHRlcmVkLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBkb21GaWx0ZXJlZCA9IGFsbERvbWFpbnNGaWx0ZXJlZDtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGZpbHRlciA9PT0gRmlsdGVyVHlwZS5ST0xFKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGhpZ2hlc3RSb2xlTWlzc2lvbiA9IGN1cnJlbnRTcGFjZU1pc3Npb25zLmZpbmQoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAobSkgPT4gbS5yb2xlID09PSBoaWdoZXN0Um9sZSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcm9sZUZpbHRlcmVkID0gdGhpcy5maWx0ZXJUaWNrZXRzRm9yTWlzc2lvbihcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpY2tldHMsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoaWdoZXN0Um9sZU1pc3Npb24sXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICBpZiAoZmlsdGVyID09PSBGaWx0ZXJUeXBlLkxFVkVMKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsRmlsdGVyZWQgPSB0aGlzLmZpbHRlck9iamVjdHNCeUxldmVsKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGlja2V0cyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhpZ2hlc3RMZWxlbCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChmaWx0ZXIgPT09IEZpbHRlclR5cGUuWk9ORSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB6b25lRmlsdGVyZWQgPSBhd2FpdCB0aGlzLmFwcGx5Wm9uZUZpbHRlckZvck1pc3Npb25zKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudFNwYWNlTWlzc2lvbnMsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aWNrZXRzLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIC8vIGtlZXAgb25seSB0aWNrZXRzIHByZXNlbnQgaW4gYWxsIGZpbHRlcmVkIGFycmF5c1xyXG4gICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coZG9tRmlsdGVyZWQpO1xyXG4gICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2cocm9sZUZpbHRlcmVkKTtcclxuICAgICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKGxldmVsRmlsdGVyZWQpO1xyXG4gICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coem9uZUZpbHRlcmVkKTtcclxuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgdGljIG9mIGxldmVsRmlsdGVyZWQpIHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvbUZpbHRlcmVkLmluY2x1ZGVzKHRpYykgJiZcclxuICAgICAgICAgICAgICAgICAgICAgICAgcm9sZUZpbHRlcmVkLmluY2x1ZGVzKHRpYykgJiZcclxuICAgICAgICAgICAgICAgICAgICAgICAgem9uZUZpbHRlcmVkLmluY2x1ZGVzKHRpYylcclxuICAgICAgICAgICAgICAgICAgICApIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxUaWNrZXRzLnB1c2godGljKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgLy8gY29uc29sZS5sb2coZmluYWxUaWNrZXRzKTtcclxuICAgICAgICByZXR1cm4gZmluYWxUaWNrZXRzO1xyXG4gICAgfVxyXG5cclxuICAgIHN1YnNjcmliZVRvRGF0YUZpbHRlclVwZGF0ZShcclxuICAgICAgICBuZXh0PzogKHZhbHVlOiBhbnkpID0+IHZvaWQsXHJcbiAgICAgICAgZXJyb3I/OiAoZXJyb3I6IGFueSkgPT4gdm9pZCxcclxuICAgICAgICBjb21wbGV0ZT86ICgpID0+IHZvaWQsXHJcbiAgICApOiBTdWJzY3JpcHRpb24ge1xyXG4gICAgICAgIGNvbnN0IHMgPSB0aGlzLnVwZGF0ZURhdGVGaWx0ZXIuc3Vic2NyaWJlKG5leHQsIGVycm9yLCBjb21wbGV0ZSk7XHJcbiAgICAgICAgcmV0dXJuIHM7XHJcbiAgICB9XHJcblxyXG4gICAgZGF0ZUZpbHRlclVwZGF0ZWQoZGF0ZVJhbmdlOiBEYXRlW10gfCBudWxsKSB7XHJcbiAgICAgICAgdGhpcy5jdXJyZW50RGF0ZUZpbHRlciA9IGRhdGVSYW5nZTtcclxuICAgICAgICB0aGlzLnVwZGF0ZURhdGVGaWx0ZXIubmV4dChkYXRlUmFuZ2UpO1xyXG4gICAgfVxyXG5cclxuICAgIGZpbHRlck9iamVjdHNGb3JEYXRlUmFuZ2Uob2JqZWN0czogYW55W10sIGRhdGVSYW5nZTogRGF0ZVtdKTogYW55W10ge1xyXG4gICAgICAgIHJldHVybiBvYmplY3RzLmZpbHRlcigob2JqZWN0KSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnN0IGNyZWF0ZWRBdERhdGUgPSBuZXcgRGF0ZShvYmplY3QuY3JlYXRlZEF0KTtcclxuICAgICAgICAgICAgcmV0dXJuIChcclxuICAgICAgICAgICAgICAgIGNyZWF0ZWRBdERhdGUgPj0gZGF0ZVJhbmdlWzBdICYmIGNyZWF0ZWRBdERhdGUgPD0gZGF0ZVJhbmdlWzFdXHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgZmlsdGVyTWVhc3VyZW1lbnRzRm9yRGF0ZVJhbmdlKFxyXG4gICAgICAgIG1lYXN1cmVtZW50czogTWVhc3VyZW1lbnRbXSxcclxuICAgICAgICBkYXRlUmFuZ2U6IERhdGVbXSxcclxuICAgICk6IE1lYXN1cmVtZW50W10ge1xyXG4gICAgICAgIHJldHVybiBtZWFzdXJlbWVudHMuZmlsdGVyKChtZWFzdXJlKSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnN0IGNyZWF0ZWRBdERhdGUgPSBuZXcgRGF0ZShtZWFzdXJlLmNvbW1lbnQuY3JlYXRlZEF0KTtcclxuICAgICAgICAgICAgcmV0dXJuIChcclxuICAgICAgICAgICAgICAgIGNyZWF0ZWRBdERhdGUgPj0gZGF0ZVJhbmdlWzBdICYmIGNyZWF0ZWRBdERhdGUgPD0gZGF0ZVJhbmdlWzFdXHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgYXN5bmMgZmlsdGVyT2JqZWN0c0ZvclpvbmUoXHJcbiAgICAgICAgb2JqZWN0czogYW55W10sXHJcbiAgICAgICAgem9uZUlEOiBzdHJpbmcgPSBudWxsLFxyXG4gICAgICAgIHpvbmU6IFpvbmUgPSBudWxsLFxyXG4gICAgKTogUHJvbWlzZTxhbnlbXT4ge1xyXG4gICAgICAgIGNvbnN0IGZpbHRlcmVkT2JqZWN0cyA9IFtdO1xyXG4gICAgICAgIGF3YWl0IFByb21pc2UuYWxsKFxyXG4gICAgICAgICAgICBvYmplY3RzLm1hcChhc3luYyAob2JqZWN0KSA9PiB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBbcG9pXSA9IG9iamVjdC5wb2lzLml0ZW1zO1xyXG4gICAgICAgICAgICAgICAgaWYgKHBvaSAmJiB6b25lKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHpvbmUuc3dlZXBJRHMgJiYgem9uZS5zd2VlcElEcy5pbmNsdWRlcyhwb2kubWF0dGVycG9ydFN3ZWVwSUQpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnBvaVNlcnZpY2UucG9pSXNWaXJ0dWFsKHBvaSkgJiYgem9uZS5sYXllciAmJiB6b25lLmxheWVyLm5hbWUgPT09IFwiRkxPT1JcIiApIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHdlIGluY2x1ZGUgaW4gRmxvb3Igem9uZSBvbmx5XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXJlZE9iamVjdHMucHVzaChvYmplY3QpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5wb2lTZXJ2aWNlLnBvaUlzVmlydHVhbChwb2kpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXJlZE9iamVjdHMucHVzaChvYmplY3QpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgaWYgKHBvaSAmJiAhem9uZSAmJiB6b25lSUQpIHtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCB6b25lcyA9IGF3YWl0IHRoaXMuem9uZVNlcnZpY2UuZ2V0Wm9uZXNGb3JPYmplY3QoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdCxcclxuICAgICAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChcclxuICAgICAgICAgICAgICAgICAgICAgICAgem9uZXMgJiZcclxuICAgICAgICAgICAgICAgICAgICAgICAgem9uZXMuc29tZShcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICh6b25lXykgPT5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB6b25lXy5pZCA9PT0gem9uZUlEIHx8XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgem9uZV8ucGFyZW50SUQgPT09IHpvbmVJRCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgKVxyXG4gICAgICAgICAgICAgICAgICAgICkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXJlZE9iamVjdHMucHVzaChvYmplY3QpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSksXHJcbiAgICAgICAgKTtcclxuICAgICAgICByZXR1cm4gZmlsdGVyZWRPYmplY3RzO1xyXG4gICAgfVxyXG5cclxuICAgIGZpbHRlckVxdWlwbWVudHNCeURvbWFpbkxpc3QoXHJcbiAgICAgICAgZXF1aXBtZW50czogRXF1aXBtZW50W10sXHJcbiAgICAgICAgZG9tYWluSURMaXN0OiBzdHJpbmdbXSxcclxuICAgICk6IEVxdWlwbWVudFtdIHtcclxuICAgICAgICBsZXQgZmlsdGVyZWQgPSBbXTtcclxuICAgICAgICBjb25zdCBmaWx0ZXJlZEJ5RG9tYWluID0gZXF1aXBtZW50cy5maWx0ZXIoKGVxdWlwKSA9PlxyXG4gICAgICAgICAgICBkb21haW5JRExpc3QuaW5jbHVkZXMoZXF1aXAuZG9tYWluSUQpLFxyXG4gICAgICAgICk7XHJcbiAgICAgICAgZmlsdGVyZWQgPSBbLi4uZmlsdGVyZWQsIC4uLmZpbHRlcmVkQnlEb21haW5dO1xyXG4gICAgICAgIGNvbnN0IGZpbHRlcmVkQnlQYXJlbnREb21haW4gPSBlcXVpcG1lbnRzLmZpbHRlcihcclxuICAgICAgICAgICAgKGVxdWlwKSA9PlxyXG4gICAgICAgICAgICAgICAgZXF1aXAuZG9tYWluICYmXHJcbiAgICAgICAgICAgICAgICBlcXVpcC5kb21haW4ucGFyZW50SUQgJiZcclxuICAgICAgICAgICAgICAgIGRvbWFpbklETGlzdC5pbmNsdWRlcyhlcXVpcC5kb21haW4ucGFyZW50SUQpLFxyXG4gICAgICAgICk7XHJcbiAgICAgICAgZmlsdGVyZWQgPSBbLi4uZmlsdGVyZWQsIC4uLmZpbHRlcmVkQnlQYXJlbnREb21haW5dO1xyXG4gICAgICAgIHJldHVybiBmaWx0ZXJVbmlxdWVBcnJheUJ5SUQoZmlsdGVyZWQpO1xyXG4gICAgfVxyXG5cclxuICAgIGZpbHRlckVxdWlwbWVudHNGb3JUZXJtKGVxdWlwczogRXF1aXBtZW50W10sIHRlcm06IHN0cmluZyk6IEVxdWlwbWVudFtdIHtcclxuICAgICAgICAvLyBmaWx0ZXIgZG9tYWluc1xyXG4gICAgICAgIGxldCBieURvbWFpbiA9IGVxdWlwcy5maWx0ZXIoKGVxKSA9PiB7XHJcbiAgICAgICAgICAgIGlmIChlcS5kb21haW4gJiYgZXEuZG9tYWluLm5hbWUpIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IG5vcm1hbGl6ZWREb21haW4gPSBlcS5kb21haW4ubmFtZS50b0xvd2VyQ2FzZSgpO1xyXG4gICAgICAgICAgICAgICAgY29uc3QgbGV2ID0gbGV2ZW5zaHRlaW4obm9ybWFsaXplZERvbWFpbiwgdGVybSk7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbGV2IDw9IDIgfHwgbm9ybWFsaXplZERvbWFpbi5pbmNsdWRlcyh0ZXJtKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgY29uc3QgYnlQYXJlbnREb21haW4gPSBlcXVpcHMuZmlsdGVyKChlcSkgPT4ge1xyXG4gICAgICAgICAgICBpZiAoZXEuZG9tYWluICYmIGVxLmRvbWFpbi5wYXJlbnRJRCkge1xyXG4gICAgICAgICAgICAgICAgY29uc3Qgbm9ybWFsaXplZFBhcmVudCA9IGVxLmRvbWFpbi5wYXJlbnQubmFtZS50b0xvd2VyQ2FzZSgpO1xyXG4gICAgICAgICAgICAgICAgY29uc3QgbGV2ID0gbGV2ZW5zaHRlaW4obm9ybWFsaXplZFBhcmVudCwgdGVybSk7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbGV2IDw9IDIgfHwgbm9ybWFsaXplZFBhcmVudC5pbmNsdWRlcyh0ZXJtKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgYnlEb21haW4gPSBbLi4uYnlEb21haW4sIC4uLmJ5UGFyZW50RG9tYWluXTtcclxuICAgICAgICAvLyBmaWx0ZXIgbmFtZVxyXG4gICAgICAgIGxldCBieU5hbWUgPSBbXTtcclxuICAgICAgICBjb25zdCB0ZXJtcyA9IHRlcm0uc3BsaXQoXCIgXCIpLmZpbHRlcigodG9rZW4pID0+IHRva2VuLmxlbmd0aCA+IDIpO1xyXG4gICAgICAgIGZvciAoY29uc3QgZXEgb2YgZXF1aXBzKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IHdvcmRzID0gZXEubmFtZVxyXG4gICAgICAgICAgICAgICAgLnRvTG93ZXJDYXNlKClcclxuICAgICAgICAgICAgICAgIC5zcGxpdChcIiBcIilcclxuICAgICAgICAgICAgICAgIC5maWx0ZXIoKHRva2VuKSA9PiB0b2tlbi5sZW5ndGggPiAyKTtcclxuICAgICAgICAgICAgY29uc3QgbWF0Y2hlZCA9IFtdO1xyXG4gICAgICAgICAgICBmb3IgKGNvbnN0IHRva2VuIG9mIHRlcm1zKSB7XHJcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHdvcmQgb2Ygd29yZHMpIHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAobGV2ZW5zaHRlaW4odG9rZW4sIHdvcmQpIDw9IDEpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hlZC5wdXNoKHRydWUpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKG1hdGNoZWQubGVuZ3RoID09PSB0ZXJtcy5sZW5ndGgpIHtcclxuICAgICAgICAgICAgICAgIGJ5TmFtZS5wdXNoKGVxKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgYnlOYW1lU2ltcGxlID0gZXF1aXBzLmZpbHRlcigoZXEpID0+XHJcbiAgICAgICAgICAgIGVxLm5hbWUudG9Mb3dlckNhc2UoKS5pbmNsdWRlcyh0ZXJtKSxcclxuICAgICAgICApO1xyXG4gICAgICAgIGJ5TmFtZSA9IFsuLi5ieU5hbWUsIC4uLmJ5TmFtZVNpbXBsZV07XHJcbiAgICAgICAgLy8gYnkgc2VyaWFsIG51bWJlclxyXG4gICAgICAgIGNvbnN0IGJ5U2VyaWFsTnVtYmVyID0gZXF1aXBzLmZpbHRlcihcclxuICAgICAgICAgICAgKGVxKSA9PiBlcS5zZXJpYWxOdW1iZXIgJiYgZXEuc2VyaWFsTnVtYmVyLnRvTG93ZXJDYXNlKCkgPT09IHRlcm0sXHJcbiAgICAgICAgKTtcclxuICAgICAgICBjb25zdCByZXN1bHQgPSBbLi4uYnlEb21haW4sIC4uLmJ5TmFtZSwgLi4uYnlTZXJpYWxOdW1iZXJdO1xyXG4gICAgICAgIHJldHVybiBmaWx0ZXJVbmlxdWVBcnJheUJ5SUQocmVzdWx0KTtcclxuICAgIH1cclxuXHJcbiAgICBmaWx0ZXJUaWNrZXRzRm9yVGVybSh0aWNrZXRzOiBUaWNrZXRbXSwgdGVybTogc3RyaW5nKTogVGlja2V0W10ge1xyXG4gICAgICAgIC8vIGZpbHRlciB0ZXJtIGluIHRpdGxlIGFuZCBkZXNjcmlwdGlvblxyXG4gICAgICAgIGNvbnN0IGJ5VGl0bGUgPSB0aGlzLmZpbHRlck9iamVjdHNGb3JUZXJtKHRpY2tldHMsIHRlcm0pO1xyXG4gICAgICAgIC8vIGJ5IGVxdWlwbWVudFxyXG4gICAgICAgIGNvbnN0IGJ5RXF1aXBtZW50ID0gdGlja2V0cy5maWx0ZXIoXHJcbiAgICAgICAgICAgICh0aWNrZXQpID0+XHJcbiAgICAgICAgICAgICAgICB0aWNrZXQuZXF1aXBtZW50cyAmJlxyXG4gICAgICAgICAgICAgICAgdGhpcy5maWx0ZXJFcXVpcG1lbnRzRm9yVGVybSh0aWNrZXQuZXF1aXBtZW50cywgdGVybSkubGVuZ3RoID5cclxuICAgICAgICAgICAgICAgICAgICAwLFxyXG4gICAgICAgICk7XHJcbiAgICAgICAgcmV0dXJuIGZpbHRlclVuaXF1ZUFycmF5QnlJRChbLi4uYnlUaXRsZSwgLi4uYnlFcXVpcG1lbnRdKTtcclxuICAgIH1cclxuXHJcbiAgICBmaWx0ZXJMb2NhdGlvbnNGb3JUZXJtKGxvY2F0aW9uczogU3BhY2VbXSwgdGVybTogc3RyaW5nKTogU3BhY2VbXSB7XHJcbiAgICAgICAgLy8gYnkgbmFtZVxyXG4gICAgICAgIGNvbnN0IGJ5TmFtZSA9IGxvY2F0aW9ucy5maWx0ZXIoKGxvYykgPT5cclxuICAgICAgICAgICAgbG9jLm5hbWUudG9Mb3dlckNhc2UoKS5pbmNsdWRlcyh0ZXJtKSxcclxuICAgICAgICApO1xyXG4gICAgICAgIC8vIGJ5IGFkZHJlc3NcclxuICAgICAgICBjb25zdCBieUFkZHJlc3MgPSBsb2NhdGlvbnMuZmlsdGVyKChsb2MpID0+XHJcbiAgICAgICAgICAgIGxvYy5hZGRyZXNzZXMudG9Mb3dlckNhc2UoKS5pbmNsdWRlcyh0ZXJtKSxcclxuICAgICAgICApO1xyXG4gICAgICAgIHJldHVybiBmaWx0ZXJVbmlxdWVBcnJheUJ5SUQoWy4uLmJ5TmFtZSwgLi4uYnlBZGRyZXNzXSk7XHJcbiAgICB9XHJcblxyXG4gICAgZmlsdGVyT3JnYW5pc2F0aW9uc0ZvclRlcm0oXHJcbiAgICAgICAgb3JnczogT3JnYW5pc2F0aW9uW10sXHJcbiAgICAgICAgdGVybTogc3RyaW5nLFxyXG4gICAgKTogT3JnYW5pc2F0aW9uW10ge1xyXG4gICAgICAgIGNvbnN0IGJ5TmFtZSA9IG9yZ3MuZmlsdGVyKChvcmcpID0+IHtcclxuICAgICAgICAgICAgY29uc3Qgd29yZHMgPSBvcmcubmFtZS50b0xvd2VyQ2FzZSgpLnNwbGl0KFwiIFwiKTtcclxuICAgICAgICAgICAgcmV0dXJuIChcclxuICAgICAgICAgICAgICAgIHdvcmRzLnNvbWUoXHJcbiAgICAgICAgICAgICAgICAgICAgKHdvcmQpID0+IHdvcmQubGVuZ3RoID4gMiAmJiBsZXZlbnNodGVpbih3b3JkLCB0ZXJtKSA8PSAxLFxyXG4gICAgICAgICAgICAgICAgKSB8fCBvcmcubmFtZS50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHRlcm0pXHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgcmV0dXJuIGJ5TmFtZTtcclxuICAgIH1cclxuXHJcbiAgICBmaWx0ZXJVc2Vyc0ZvclRlcm0odXNlcnM6IFByb2ZpbGVFbnRpdHlbXSwgdGVybTogc3RyaW5nKSB7XHJcbiAgICAgICAgY29uc3QgYnlOYW1lID0gdXNlcnMuZmlsdGVyKCh1c2VyKSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnN0IHdvcmRzID0gdXNlci5kaXNwbGF5TmFtZS50b0xvd2VyQ2FzZSgpLnNwbGl0KFwiIFwiKTtcclxuICAgICAgICAgICAgcmV0dXJuIChcclxuICAgICAgICAgICAgICAgIHdvcmRzLnNvbWUoXHJcbiAgICAgICAgICAgICAgICAgICAgKHdvcmQpID0+IHdvcmQubGVuZ3RoID4gMiAmJiBsZXZlbnNodGVpbih3b3JkLCB0ZXJtKSA8PSAxLFxyXG4gICAgICAgICAgICAgICAgKSB8fCB1c2VyLmRpc3BsYXlOYW1lLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXModGVybSlcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICB9KTtcclxuICAgICAgICByZXR1cm4gYnlOYW1lO1xyXG4gICAgfVxyXG5cclxuICAgIGFzeW5jIGZpbHRlckZlYXR1cmVzRm9yQ3VycmVudFVzZXJJblNwYWNlKFxyXG4gICAgICAgIGZlYXR1cmVzOiBGZWF0dXJlW10sXHJcbiAgICAgICAgc3BhY2VJRDogc3RyaW5nLFxyXG4gICAgKTogUHJvbWlzZTxGZWF0dXJlW10+IHtcclxuICAgICAgICBjb25zdCBmaW5hbEZlYXR1cmVzOiBGZWF0dXJlW10gPSBbXTtcclxuICAgICAgICBsZXQgbGV2ZWxGaWx0ZXJlZDogRmVhdHVyZVtdID0gZmVhdHVyZXM7XHJcbiAgICAgICAgbGV0IHpvbmVGaWx0ZXJlZDogRmVhdHVyZVtdID0gZmVhdHVyZXM7XHJcbiAgICAgICAgbGV0IGhhc2h0YWdGaWx0ZXJlZDogRmVhdHVyZVtdID0gZmVhdHVyZXM7XHJcbiAgICAgICAgY29uc3QgbWlzc2lvbnMgPSB0aGlzLnVzZXJTZXJ2aWNlLmN1cnJlbnRNaXNzaW9ucztcclxuICAgICAgICBpZiAobWlzc2lvbnMpIHtcclxuICAgICAgICAgICAgY29uc3QgY3VycmVudFNwYWNlTWlzc2lvbnMgPSBtaXNzaW9ucy5maWx0ZXIoXHJcbiAgICAgICAgICAgICAgICAobSkgPT4gbS5zcGFjZUlEID09PSBzcGFjZUlELFxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgICAgICBpZiAoY3VycmVudFNwYWNlTWlzc2lvbnMubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgaGlnaGVzdExlbGVsID1cclxuICAgICAgICAgICAgICAgICAgICBnZXRIaWdoZXN0TGV2ZWxGb3JNaXNzaW9ucyhjdXJyZW50U3BhY2VNaXNzaW9ucyk7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBoaWdoZXN0Um9sZSA9XHJcbiAgICAgICAgICAgICAgICAgICAgZ2V0SGlnaGVzdFJvbGVGb3JNaXNzaW9ucyhjdXJyZW50U3BhY2VNaXNzaW9ucyk7XHJcblxyXG4gICAgICAgICAgICAgICAgY29uc3QgZmlsdGVycyA9IHRoaXMuZ2V0RmlsdGVyc0ZvclJvbGUoaGlnaGVzdFJvbGUpO1xyXG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBmaWx0ZXIgb2YgZmlsdGVycykge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChmaWx0ZXIgPT09IEZpbHRlclR5cGUuTEVWRUwpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxGaWx0ZXJlZCA9IHRoaXMuZmlsdGVyT2JqZWN0c0J5TGV2ZWwoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhpZ2hlc3RMZWxlbCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGZpbHRlciA9PT0gRmlsdGVyVHlwZS5aT05FKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHpvbmVGaWx0ZXJlZCA9IGF3YWl0IHRoaXMuYXBwbHlab25lRmlsdGVyRm9yTWlzc2lvbnMoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50U3BhY2VNaXNzaW9ucyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAoZmlsdGVyID09PSBGaWx0ZXJUeXBlLkhBU0hUQUcpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaGFzaHRhZ0ZpbHRlcmVkID1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZmlsdGVyRmVhdHVyZXNCeUhhc2h0YWdzQW5kTG9jYWxlKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRTcGFjZU1pc3Npb25zLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGZlYXR1cmUgb2YgbGV2ZWxGaWx0ZXJlZCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChcclxuICAgICAgICAgICAgICAgICAgICAgICAgaGFzaHRhZ0ZpbHRlcmVkLmluY2x1ZGVzKGZlYXR1cmUpICYmXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHpvbmVGaWx0ZXJlZC5pbmNsdWRlcyhmZWF0dXJlKVxyXG4gICAgICAgICAgICAgICAgICAgICkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBmaW5hbEZlYXR1cmVzLnB1c2goZmVhdHVyZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBmaW5hbEZlYXR1cmVzO1xyXG4gICAgfVxyXG5cclxuICAgIGZpbHRlckZlYXR1cmVzRm9yVGVybShmZWF0dXJlczogRmVhdHVyZVtdLCB0ZXJtOiBzdHJpbmcpOiBGZWF0dXJlW10ge1xyXG4gICAgICAgIC8vIGZpbHRlciB0ZXJtIGluIHRpdGxlXHJcbiAgICAgICAgY29uc3QgYnlUaXRsZSA9IHRoaXMuZmlsdGVyT2JqZWN0c0ZvclRlcm0oZmVhdHVyZXMsIHRlcm0pO1xyXG4gICAgICAgIC8vIGJ5IGNvbW1lbnRzXHJcbiAgICAgICAgY29uc3QgYnlDb21tZW50ID0gZmVhdHVyZXMuZmlsdGVyKFxyXG4gICAgICAgICAgICAoZmVhdHVyZSkgPT5cclxuICAgICAgICAgICAgICAgIHRoaXMuZmlsdGVyT2JqZWN0c0ZvclRlcm0oZmVhdHVyZS5jb21tZW50cy5pdGVtcywgdGVybSkubGVuZ3RoID5cclxuICAgICAgICAgICAgICAgIDAsXHJcbiAgICAgICAgKTtcclxuICAgICAgICByZXR1cm4gZmlsdGVyVW5pcXVlQXJyYXlCeUlEKFsuLi5ieVRpdGxlLCAuLi5ieUNvbW1lbnRdKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0gb2JqZWN0cyBBcnJheSBvZiBDb21tZW50cywgVGlja2V0cywgRmVhdHVyZXMuIE9ibGlnYXRvcnkgcHJvcG9ydGllczogdGl0bGUsIGRlc2NyaXB0aW9uXHJcbiAgICAgKiBAcGFyYW0gdGVybSBzdHJpbmdcclxuICAgICAqL1xyXG4gICAgZmlsdGVyT2JqZWN0c0ZvclRlcm0ob2JqZWN0czogYW55W10sIHRlcm06IHN0cmluZyk6IGFueVtdIHtcclxuICAgICAgICAvLyBmaWx0ZXIgdGVybSBpbiB0aXRsZVxyXG4gICAgICAgIGNvbnN0IGJ5VGl0bGUgPSBvYmplY3RzLmZpbHRlcigoZmVhdHVyZSkgPT4ge1xyXG4gICAgICAgICAgICBjb25zdCB3b3JkcyA9IGZlYXR1cmUudGl0bGUudG9Mb3dlckNhc2UoKS5zcGxpdChcIiBcIik7XHJcbiAgICAgICAgICAgIHJldHVybiAoXHJcbiAgICAgICAgICAgICAgICB3b3Jkcy5zb21lKFxyXG4gICAgICAgICAgICAgICAgICAgICh3b3JkKSA9PiB3b3JkLmxlbmd0aCA+IDIgJiYgbGV2ZW5zaHRlaW4od29yZCwgdGVybSkgPD0gMSxcclxuICAgICAgICAgICAgICAgICkgfHwgZmVhdHVyZS50aXRsZS50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHRlcm0pXHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgLy8gdGVybSBwcmVzZW50IGluIGRlc2NyaXB0aW9uXHJcbiAgICAgICAgY29uc3QgYnlEZXNjcmlwdGlvbiA9IG9iamVjdHMuZmlsdGVyKFxyXG4gICAgICAgICAgICAoZmVhdHVyZSkgPT5cclxuICAgICAgICAgICAgICAgIGZlYXR1cmUuZGVzY3JpcHRpb24gJiZcclxuICAgICAgICAgICAgICAgIGZlYXR1cmUuZGVzY3JpcHRpb24udG9Mb3dlckNhc2UoKS5pbmNsdWRlcyh0ZXJtKSxcclxuICAgICAgICApO1xyXG4gICAgICAgIHJldHVybiBmaWx0ZXJVbmlxdWVBcnJheUJ5SUQoWy4uLmJ5VGl0bGUsIC4uLmJ5RGVzY3JpcHRpb25dKTtcclxuICAgIH1cclxuXHJcbiAgICBmaWx0ZXJNaXNzaW9uQnlTdGFydFRpbWVEYXRlRm9yRGF0ZVJhbmdlKFxyXG4gICAgICAgIG1pc3Npb25zOiBhbnlbXSxcclxuICAgICAgICBkYXRlUmFuZ2U6IERhdGVbXSxcclxuICAgICk6IGFueVtdIHtcclxuICAgICAgICByZXR1cm4gbWlzc2lvbnMuZmlsdGVyKChtaXNzaW9uKSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnN0IHN0YXJ0RGF0ZVRpbWUgPSBuZXcgRGF0ZShtaXNzaW9uLnN0YXJ0RGF0ZVRpbWUpO1xyXG4gICAgICAgICAgICByZXR1cm4gKFxyXG4gICAgICAgICAgICAgICAgc3RhcnREYXRlVGltZSA+PSBkYXRlUmFuZ2VbMF0gJiYgc3RhcnREYXRlVGltZSA8PSBkYXRlUmFuZ2VbMV1cclxuICAgICAgICAgICAgKTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBhc3luYyBhcHBseVpvbmVGaWx0ZXJGb3JNaXNzaW9ucyhcclxuICAgICAgICBjdXJyZW50U3BhY2VNaXNzaW9uczogTWlzc2lvbltdLFxyXG4gICAgICAgIG9iamVjdHM6IGFueVtdLFxyXG4gICAgKTogUHJvbWlzZTxhbnlbXT4ge1xyXG4gICAgICAgIGNvbnN0IGFsbG93ZWRab25lcyA9IFtdO1xyXG4gICAgICAgIGZvciAoY29uc3QgbWlzc2lvbiBvZiBjdXJyZW50U3BhY2VNaXNzaW9ucykge1xyXG4gICAgICAgICAgICBpZiAobWlzc2lvbi56b25lSUQpIHtcclxuICAgICAgICAgICAgICAgIGFsbG93ZWRab25lcy5wdXNoKG1pc3Npb24uem9uZUlEKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoYWxsb3dlZFpvbmVzLmxlbmd0aCA9PT0gY3VycmVudFNwYWNlTWlzc2lvbnMubGVuZ3RoKSB7XHJcbiAgICAgICAgICAgIGxldCBhbGxab25lRmlsdGVyZWQgPSBbXTtcclxuICAgICAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXHJcbiAgICAgICAgICAgICAgICBhbGxvd2VkWm9uZXMubWFwKGFzeW5jICh6b25lSUQpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBjdXJyZW50Wm9uZUZpbHRlcmVkID0gYXdhaXQgdGhpcy5maWx0ZXJPYmplY3RzRm9yWm9uZShcclxuICAgICAgICAgICAgICAgICAgICAgICAgb2JqZWN0cyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgem9uZUlELFxyXG4gICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgYWxsWm9uZUZpbHRlcmVkID0gW1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAuLi5hbGxab25lRmlsdGVyZWQsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC4uLmN1cnJlbnRab25lRmlsdGVyZWQsXHJcbiAgICAgICAgICAgICAgICAgICAgXTtcclxuICAgICAgICAgICAgICAgIH0pLFxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgICAgICByZXR1cm4gZmlsdGVyVW5pcXVlQXJyYXlCeUlEKGFsbFpvbmVGaWx0ZXJlZCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBvYmplY3RzO1xyXG4gICAgfVxyXG5cclxuICAgIGFzeW5jIGZpbHRlckVxdWlwbWVudHNGb3JDdXJyZW50VXNlckluU3BhY2UoXHJcbiAgICAgICAgc3BhY2VJRDogc3RyaW5nLFxyXG4gICAgICAgIGVxdWlwczogRXF1aXBtZW50W10sXHJcbiAgICApOiBQcm9taXNlPEVxdWlwbWVudFtdPiB7XHJcbiAgICAgICAgY29uc3QgZmluYWxFcXVpcHM6IEVxdWlwbWVudFtdID0gW107XHJcbiAgICAgICAgbGV0IGRvbUZpbHRlcmVkOiBFcXVpcG1lbnRbXSA9IGVxdWlwcztcclxuICAgICAgICBjb25zdCByb2xlRmlsdGVyZWQ6IEVxdWlwbWVudFtdID0gZXF1aXBzO1xyXG4gICAgICAgIGNvbnN0IGxldmVsRmlsdGVyZWQ6IEVxdWlwbWVudFtdID0gZXF1aXBzO1xyXG4gICAgICAgIGxldCB6b25lRmlsdGVyZWQ6IEVxdWlwbWVudFtdID0gZXF1aXBzO1xyXG4gICAgICAgIGNvbnN0IG1pc3Npb25zID0gdGhpcy51c2VyU2VydmljZS5jdXJyZW50TWlzc2lvbnM7XHJcbiAgICAgICAgaWYgKG1pc3Npb25zKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRTcGFjZU1pc3Npb25zID0gbWlzc2lvbnMuZmlsdGVyKFxyXG4gICAgICAgICAgICAgICAgKG0pID0+IG0uc3BhY2VJRCA9PT0gc3BhY2VJRCxcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgaWYgKGN1cnJlbnRTcGFjZU1pc3Npb25zLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGhpZ2hlc3RMZWxlbCA9XHJcbiAgICAgICAgICAgICAgICAgICAgZ2V0SGlnaGVzdExldmVsRm9yTWlzc2lvbnMoY3VycmVudFNwYWNlTWlzc2lvbnMpO1xyXG4gICAgICAgICAgICAgICAgY29uc3QgaGlnaGVzdFJvbGUgPVxyXG4gICAgICAgICAgICAgICAgICAgIGdldEhpZ2hlc3RSb2xlRm9yTWlzc2lvbnMoY3VycmVudFNwYWNlTWlzc2lvbnMpO1xyXG4gICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJIaWdoZXN0IGxldmVsOiBcIiwgaGlnaGVzdExlbGVsLCBcIiwgSGlnaGVzdCBSb2xlOiBcIiwgaGlnaGVzdFJvbGUpXHJcblxyXG4gICAgICAgICAgICAgICAgY29uc3QgZmlsdGVycyA9IHRoaXMuZ2V0RmlsdGVyc0ZvclJvbGUoaGlnaGVzdFJvbGUpO1xyXG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBmaWx0ZXIgb2YgZmlsdGVycykge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChmaWx0ZXIgPT09IEZpbHRlclR5cGUuRE9NQUlOKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBkb21haW5zOiBzdHJpbmdbXSA9IFtdO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IG0gb2YgY3VycmVudFNwYWNlTWlzc2lvbnMpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtLmRvbWFpbnMpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb21haW5zID0gWy4uLmRvbWFpbnMsIC4uLm0uZG9tYWluc107XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGFsbERvbWFpbnNGaWx0ZXJlZCA9IFtdO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjdXJyZW50RG9tRmlsdGVyZWQgPVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5maWx0ZXJFcXVpcG1lbnRzQnlEb21haW5MaXN0KGVxdWlwcywgZG9tYWlucyk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGFsbERvbWFpbnNGaWx0ZXJlZCA9IFtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLmFsbERvbWFpbnNGaWx0ZXJlZCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLmN1cnJlbnREb21GaWx0ZXJlZCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgXTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZG9tRmlsdGVyZWQgPSBhbGxEb21haW5zRmlsdGVyZWQ7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChmaWx0ZXIgPT09IEZpbHRlclR5cGUuUk9MRSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBjb25zdCBoaWdoZXN0Um9sZU1pc3Npb24gPSBjdXJyZW50U3BhY2VNaXNzaW9ucy5maW5kKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAgKG0pID0+IG0ucm9sZSA9PT0gaGlnaGVzdFJvbGUsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRPRE9cclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChmaWx0ZXIgPT09IEZpbHRlclR5cGUuTEVWRUwpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVE9ETywgZXF1aXBtZW50IGRvZXMgbm90IGhhdmUgbGV2ZWxcclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChmaWx0ZXIgPT09IEZpbHRlclR5cGUuWk9ORSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB6b25lRmlsdGVyZWQgPSBhd2FpdCB0aGlzLmFwcGx5Wm9uZUZpbHRlckZvck1pc3Npb25zKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudFNwYWNlTWlzc2lvbnMsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcXVpcHMsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCB0aWMgb2YgbGV2ZWxGaWx0ZXJlZCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChcclxuICAgICAgICAgICAgICAgICAgICAgICAgZG9tRmlsdGVyZWQuaW5jbHVkZXModGljKSAmJlxyXG4gICAgICAgICAgICAgICAgICAgICAgICByb2xlRmlsdGVyZWQuaW5jbHVkZXModGljKSAmJlxyXG4gICAgICAgICAgICAgICAgICAgICAgICB6b25lRmlsdGVyZWQuaW5jbHVkZXModGljKVxyXG4gICAgICAgICAgICAgICAgICAgICkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBmaW5hbEVxdWlwcy5wdXNoKHRpYyk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBmaW5hbEVxdWlwcztcclxuICAgIH1cclxuXHJcbiAgICBhc3luYyBmaWx0ZXJNZWFzdXJlbWVudHNGb3JDdXJyZW50VXNlckluU3BhY2UoXHJcbiAgICAgICAgc3BhY2VJRDogc3RyaW5nLFxyXG4gICAgICAgIGNvbW1lbnRzOiBDb21tZW50W10sXHJcbiAgICApOiBQcm9taXNlPENvbW1lbnRbXT4ge1xyXG4gICAgICAgIGxldCBmaW5hbE1lYXN1cmVtZW50czogQ29tbWVudFtdID0gW107XHJcbiAgICAgICAgbGV0IHpvbmVGaWx0ZXJlZDogQ29tbWVudFtdID0gY29tbWVudHM7XHJcbiAgICAgICAgY29uc3QgbWlzc2lvbnMgPSB0aGlzLnVzZXJTZXJ2aWNlLmN1cnJlbnRNaXNzaW9ucztcclxuICAgICAgICBpZiAobWlzc2lvbnMpIHtcclxuICAgICAgICAgICAgY29uc3QgY3VycmVudFNwYWNlTWlzc2lvbnMgPSBtaXNzaW9ucy5maWx0ZXIoXHJcbiAgICAgICAgICAgICAgICAobSkgPT4gbS5zcGFjZUlEID09PSBzcGFjZUlELFxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgICAgICBpZiAoY3VycmVudFNwYWNlTWlzc2lvbnMubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgaGlnaGVzdFJvbGUgPVxyXG4gICAgICAgICAgICAgICAgICAgIGdldEhpZ2hlc3RSb2xlRm9yTWlzc2lvbnMoY3VycmVudFNwYWNlTWlzc2lvbnMpO1xyXG5cclxuICAgICAgICAgICAgICAgIGNvbnN0IGZpbHRlcnMgPSB0aGlzLmdldEZpbHRlcnNGb3JSb2xlKGhpZ2hlc3RSb2xlKTtcclxuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZmlsdGVyIG9mIGZpbHRlcnMpIHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoZmlsdGVyID09PSBGaWx0ZXJUeXBlLlpPTkUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgem9uZUZpbHRlcmVkID0gYXdhaXQgdGhpcy5hcHBseVpvbmVGaWx0ZXJGb3JNaXNzaW9ucyhcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRTcGFjZU1pc3Npb25zLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tbWVudHMsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgZmluYWxNZWFzdXJlbWVudHMgPSB6b25lRmlsdGVyZWQ7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIGZpbmFsTWVhc3VyZW1lbnRzO1xyXG4gICAgfVxyXG5cclxuICAgIGFzeW5jIGlzT2JqZWN0QWxsb3dlZEZvclVzZXJJblNwYWNlKFxyXG4gICAgICAgIG9iamVjdDogT2JqZWN0LFxyXG4gICAgICAgIHNwYWNlSUQ6IHN0cmluZyxcclxuICAgICk6IFByb21pc2U8Ym9vbGVhbj4ge1xyXG4gICAgICAgIGNvbnN0IG1pc3Npb24gPSB0aGlzLnVzZXJTZXJ2aWNlLmN1cnJlbnRNaXNzaW9uKHNwYWNlSUQpO1xyXG4gICAgICAgIGNvbnN0IGZpbHRlcnMgPSB0aGlzLmdldEZpbHRlcnNGb3JSb2xlKG1pc3Npb24ucm9sZSk7XHJcbiAgICAgICAgZm9yIChjb25zdCBmaWx0ZXIgb2YgZmlsdGVycykge1xyXG4gICAgICAgICAgICBpZiAoXHJcbiAgICAgICAgICAgICAgICBmaWx0ZXIgPT09IEZpbHRlclR5cGUuTEVWRUwgJiZcclxuICAgICAgICAgICAgICAgIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIFwibGV2ZWxcIilcclxuICAgICAgICAgICAgKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBsZXZlbEZpbHRlcmVkID0gdGhpcy5maWx0ZXJPYmplY3RzQnlMZXZlbChcclxuICAgICAgICAgICAgICAgICAgICBbb2JqZWN0XSxcclxuICAgICAgICAgICAgICAgICAgICBtaXNzaW9uLmxldmVsLFxyXG4gICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgIGlmIChsZXZlbEZpbHRlcmVkLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBpZiAoZmlsdGVyID09PSBGaWx0ZXJUeXBlLlpPTkUpIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHpvbmVGaWx0ZXJlZCA9IGF3YWl0IHRoaXMuYXBwbHlab25lRmlsdGVyRm9yTWlzc2lvbnMoXHJcbiAgICAgICAgICAgICAgICAgICAgW21pc3Npb25dLFxyXG4gICAgICAgICAgICAgICAgICAgIFtvYmplY3RdLFxyXG4gICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgIGlmICh6b25lRmlsdGVyZWQubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgfVxyXG5cclxuICAgIGZpbHRlclRlbXBsYXRlc0ZvclRlcm0obWlzc2lvbnM6IE1pc3Npb25bXSwgdGVybTogc3RyaW5nKTogTWlzc2lvbltdIHtcclxuICAgICAgICAvLyB0ZXJtIHByZXNlbnQgaW4gZGVzY3JpcHRpb25cclxuICAgICAgICBjb25zdCBieURlc2NyaXB0aW9uID0gbWlzc2lvbnMuZmlsdGVyKFxyXG4gICAgICAgICAgICAobWlzKSA9PlxyXG4gICAgICAgICAgICAgICAgbWlzLmRlc2NyaXB0aW9uICYmIG1pcy5kZXNjcmlwdGlvbi50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHRlcm0pLFxyXG4gICAgICAgICk7XHJcbiAgICAgICAgLy8gYnkgdXNlciBsYXN0TmFtZSB3aGljaCBpcyB0aGUgbmFtZSBvZiB0aGUgdmlzaXQ6XHJcbiAgICAgICAgLy8gbWV0YWRhdGE6IFwie1xcXCJmaXJzdE5hbWVcXFwiOlxcXCJcXFwiLFxcXCJsYXN0TmFtZVxcXCI6XFxcIlZpc2l0ZSBkdSA1IEp1aWxsZXRcXFwifVwiXHJcbiAgICAgICAgY29uc3QgdXNlclByb2ZpbGVzID0gbWlzc2lvbnMubWFwKChtaXMpID0+IG5ldyBQcm9maWxlRW50aXR5KG1pcy51c2VyKSk7XHJcbiAgICAgICAgY29uc3QgYnlVc2VyTGFzdG5hbWUgPSB0aGlzLmZpbHRlclVzZXJzRm9yVGVybSh1c2VyUHJvZmlsZXMsIHRlcm0pO1xyXG4gICAgICAgIGNvbnN0IHVzZXJJZHMgPSBuZXcgU2V0KGJ5VXNlckxhc3RuYW1lLm1hcCgodXNlcikgPT4gdXNlci5pZCkpO1xyXG4gICAgICAgIGNvbnN0IG1pc3Npb25zQnlVc2VyID0gbWlzc2lvbnMuZmlsdGVyKChtaXMpID0+XHJcbiAgICAgICAgICAgIHVzZXJJZHMuaGFzKG1pcy51c2VySUQpLFxyXG4gICAgICAgICk7XHJcbiAgICAgICAgcmV0dXJuIGZpbHRlclVuaXF1ZUFycmF5QnlJRChbLi4uYnlEZXNjcmlwdGlvbiwgLi4ubWlzc2lvbnNCeVVzZXJdKTtcclxuICAgIH1cclxuXHJcbiAgICBhc3luYyBmaWx0ZXJPYmplY3RzRm9yU3dlZXAoXHJcbiAgICAgICAgb2JqZWN0czogYW55W10sXHJcbiAgICAgICAgb2JqZWN0VHlwZTogUG9pVHlwZSxcclxuICAgICAgICBzd2VlcDogc3RyaW5nLFxyXG4gICAgKTogUHJvbWlzZTxhbnlbXT4ge1xyXG4gICAgICAgIGxldCBmaWx0ZXJlZCA9IFtdO1xyXG4gICAgICAgIHN3aXRjaCAob2JqZWN0VHlwZSkge1xyXG4gICAgICAgICAgICBjYXNlIFBvaVR5cGUuRVFVSVBNRU5UOlxyXG4gICAgICAgICAgICAgICAgY29uc3QgcG9pcyA9XHJcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5wb2lTZXJ2aWNlLmdldFBvaXNCeU1hdHRlcnBvcnRTd2VlcEJ5VHlwZShcclxuICAgICAgICAgICAgICAgICAgICAgICAgc3dlZXAsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdFR5cGUsXHJcbiAgICAgICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGVxdWlwSURzID0gbmV3IFNldChwb2lzLm1hcCgocG9pKSA9PiBwb2kuZWxlbWVudElEKSk7XHJcbiAgICAgICAgICAgICAgICBmaWx0ZXJlZCA9IG9iamVjdHMuZmlsdGVyKChvYmplY3QpID0+IGVxdWlwSURzLmhhcyhvYmplY3QuaWQpKTtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBkZWZhdWx0OlxyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBmaWx0ZXJlZDtcclxuICAgIH1cclxuXHJcbiAgICBmaWx0ZXJGZWF0dXJlc0J5SGFzaHRhZ3NBbmRMb2NhbGUoXHJcbiAgICAgICAgY3VycmVudFNwYWNlTWlzc2lvbnM6IE1pc3Npb25bXSxcclxuICAgICAgICBmZWF0dXJlczogRmVhdHVyZVtdLFxyXG4gICAgKTogRmVhdHVyZVtdIHtcclxuICAgICAgICBjb25zdCBbY3VycmVudE1pc3Npb25dID0gY3VycmVudFNwYWNlTWlzc2lvbnM7XHJcbiAgICAgICAgLy8gZmlsdGVyIGJ5IGxvY2FsZVxyXG4gICAgICAgIGxldCBmaWx0ZXJlZExvY2FsZSA9IFsuLi5mZWF0dXJlc107XHJcbiAgICAgICAgaWYgKGN1cnJlbnRNaXNzaW9uLmxvY2FsZSkge1xyXG4gICAgICAgICAgICBmaWx0ZXJlZExvY2FsZSA9IGZlYXR1cmVzLmZpbHRlcihcclxuICAgICAgICAgICAgICAgIChmZWF0dXJlKSA9PlxyXG4gICAgICAgICAgICAgICAgICAgIGZlYXR1cmUubG9jYWxlICYmIGZlYXR1cmUubG9jYWxlID09PSBjdXJyZW50TWlzc2lvbi5sb2NhbGUsXHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIC8vIGZpbHRlciBieSBoYXNodGFnc1xyXG4gICAgICAgIGlmIChjdXJyZW50TWlzc2lvbi5oYXNodGFncyAmJiBjdXJyZW50TWlzc2lvbi5oYXNodGFncy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGZpbHRlcmVkQnlIYXNodGFncyA9IFtdO1xyXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGZlYXR1cmUgb2YgZmlsdGVyZWRMb2NhbGUpIHtcclxuICAgICAgICAgICAgICAgIGlmICghZmVhdHVyZS5oYXNodGFncyB8fCBmZWF0dXJlLmhhc2h0YWdzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIEZlYXR1cmUgd2l0aG91dCBoYXNodGFnIGlzIGF2YWlsYWJsZSBmb3IgZXZlcnlib2R5XHJcbiAgICAgICAgICAgICAgICAgICAgZmlsdGVyZWRCeUhhc2h0YWdzLnB1c2goZmVhdHVyZSk7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKFxyXG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRNaXNzaW9uLmhhc2h0YWdzLmV2ZXJ5KChoYXNodGFnKSA9PlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlLmhhc2h0YWdzLmluY2x1ZGVzKGhhc2h0YWcpLFxyXG4gICAgICAgICAgICAgICAgICAgIClcclxuICAgICAgICAgICAgICAgICkge1xyXG4gICAgICAgICAgICAgICAgICAgIGZpbHRlcmVkQnlIYXNodGFncy5wdXNoKGZlYXR1cmUpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJldHVybiBmaWx0ZXJlZEJ5SGFzaHRhZ3M7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBmaWx0ZXJlZExvY2FsZTtcclxuICAgIH1cclxuXHJcbiAgICBmaWx0ZXJGZWF0dXJlc0Zvck1pc3Npb25XaXRob3V0Wm9uZShcclxuICAgICAgICBmZWF0dXJlczogRmVhdHVyZVtdLFxyXG4gICAgICAgIG1pc3Npb246IE1pc3Npb24sXHJcbiAgICApOiBGZWF0dXJlW10ge1xyXG4gICAgICAgIGNvbnN0IGZpbmFsRmVhdHVyZXM6IEZlYXR1cmVbXSA9IFtdO1xyXG4gICAgICAgIGxldCBsZXZlbEZpbHRlcmVkOiBGZWF0dXJlW10gPSBmZWF0dXJlcztcclxuICAgICAgICBsZXQgem9uZUZpbHRlcmVkOiBGZWF0dXJlW10gPSBmZWF0dXJlcztcclxuICAgICAgICBsZXQgaGFzaHRhZ0ZpbHRlcmVkOiBGZWF0dXJlW10gPSBmZWF0dXJlcztcclxuXHJcbiAgICAgICAgY29uc3QgZmlsdGVycyA9IHRoaXMuZ2V0RmlsdGVyc0ZvclJvbGUobWlzc2lvbi5yb2xlKTtcclxuICAgICAgICBmb3IgKGNvbnN0IGZpbHRlciBvZiBmaWx0ZXJzKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGZpbHRlciA9PT0gRmlsdGVyVHlwZS5MRVZFTCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXZlbEZpbHRlcmVkID0gdGhpcy5maWx0ZXJPYmplY3RzQnlMZXZlbChcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWlzc2lvbi5sZXZlbCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gaWYgKGZpbHRlciA9PT0gRmlsdGVyVHlwZS5aT05FKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gICAgIHpvbmVGaWx0ZXJlZCA9IGF3YWl0IHRoaXMuYXBwbHlab25lRmlsdGVyRm9yTWlzc2lvbnMoXHJcbiAgICAgICAgICAgICAgICAgICAgLy8gICAgICAgICBjdXJyZW50U3BhY2VNaXNzaW9ucyxcclxuICAgICAgICAgICAgICAgICAgICAvLyAgICAgICAgIGZlYXR1cmVzLFxyXG4gICAgICAgICAgICAgICAgICAgIC8vICAgICApO1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAoZmlsdGVyID09PSBGaWx0ZXJUeXBlLkhBU0hUQUcpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaGFzaHRhZ0ZpbHRlcmVkID1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZmlsdGVyRmVhdHVyZXNCeUhhc2h0YWdzQW5kTG9jYWxlKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFttaXNzaW9uXSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgIGZvciAoY29uc3QgZmVhdHVyZSBvZiBsZXZlbEZpbHRlcmVkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBoYXNodGFnRmlsdGVyZWQuaW5jbHVkZXMoZmVhdHVyZSkgJiZcclxuICAgICAgICAgICAgICAgICAgICAgICAgem9uZUZpbHRlcmVkLmluY2x1ZGVzKGZlYXR1cmUpXHJcbiAgICAgICAgICAgICAgICAgICAgKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsRmVhdHVyZXMucHVzaChmZWF0dXJlKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBmaW5hbEZlYXR1cmVzO1xyXG4gICAgfVxyXG59XHJcbiJdfQ==
|