@infrab4a/connect-angular 4.5.2-beta.3 → 4.5.3-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/angular-connect.module.d.ts +26 -26
  2. package/angular-elastic-search.module.d.ts +9 -9
  3. package/angular-firebase-auth.module.d.ts +11 -11
  4. package/angular-firestore.module.d.ts +18 -18
  5. package/angular-hasura-graphql.module.d.ts +16 -16
  6. package/consts/backend-url.const.d.ts +1 -1
  7. package/consts/category-structure.d.ts +1 -1
  8. package/consts/default-shop.const.d.ts +1 -1
  9. package/consts/es-config.const.d.ts +1 -1
  10. package/consts/firebase-const.d.ts +3 -3
  11. package/consts/hasura-options.const.d.ts +1 -1
  12. package/consts/index.d.ts +7 -7
  13. package/consts/persistence.const.d.ts +1 -1
  14. package/consts/storage-base-url.const.d.ts +1 -1
  15. package/esm2020/angular-connect.module.mjs +115 -115
  16. package/esm2020/angular-elastic-search.module.mjs +34 -34
  17. package/esm2020/angular-firebase-auth.module.mjs +115 -115
  18. package/esm2020/angular-firestore.module.mjs +504 -504
  19. package/esm2020/angular-hasura-graphql.module.mjs +287 -287
  20. package/esm2020/consts/backend-url.const.mjs +1 -1
  21. package/esm2020/consts/category-structure.mjs +2 -2
  22. package/esm2020/consts/default-shop.const.mjs +2 -2
  23. package/esm2020/consts/es-config.const.mjs +2 -2
  24. package/esm2020/consts/firebase-const.mjs +4 -4
  25. package/esm2020/consts/hasura-options.const.mjs +2 -2
  26. package/esm2020/consts/index.mjs +8 -8
  27. package/esm2020/consts/persistence.const.mjs +2 -2
  28. package/esm2020/consts/storage-base-url.const.mjs +2 -2
  29. package/esm2020/helpers/index.mjs +2 -2
  30. package/esm2020/helpers/mobile-operation-system-checker.helper.mjs +7 -7
  31. package/esm2020/index.mjs +7 -7
  32. package/esm2020/infrab4a-connect-angular.mjs +4 -4
  33. package/esm2020/persistence/cookie-data-persistence.mjs +22 -22
  34. package/esm2020/persistence/data-persistence.mjs +2 -2
  35. package/esm2020/persistence/index.mjs +3 -3
  36. package/esm2020/services/auth.service.mjs +37 -37
  37. package/esm2020/services/cart.service.mjs +282 -282
  38. package/esm2020/services/catalog/adapters/category-structure.adapter.mjs +2 -2
  39. package/esm2020/services/catalog/adapters/index.mjs +4 -4
  40. package/esm2020/services/catalog/adapters/new-category-structure.adapter.mjs +43 -43
  41. package/esm2020/services/catalog/adapters/old-category-structure.adapter.mjs +23 -23
  42. package/esm2020/services/catalog/catalog.service.mjs +245 -202
  43. package/esm2020/services/catalog/category.service.mjs +51 -51
  44. package/esm2020/services/catalog/enums/index.mjs +2 -2
  45. package/esm2020/services/catalog/enums/product-sorts.enum.mjs +11 -11
  46. package/esm2020/services/catalog/index.mjs +8 -8
  47. package/esm2020/services/catalog/models/category-with-tree.model.mjs +10 -10
  48. package/esm2020/services/catalog/models/index.mjs +2 -2
  49. package/esm2020/services/catalog/types/index.mjs +2 -2
  50. package/esm2020/services/catalog/types/product-sort.type.mjs +2 -2
  51. package/esm2020/services/catalog/wishlist.service.mjs +119 -119
  52. package/esm2020/services/checkout-subscription.service.mjs +50 -50
  53. package/esm2020/services/checkout.service.mjs +68 -68
  54. package/esm2020/services/coupon.service.mjs +260 -260
  55. package/esm2020/services/helpers/index.mjs +2 -2
  56. package/esm2020/services/helpers/util.helper.mjs +18 -18
  57. package/esm2020/services/home-shop.service.mjs +125 -125
  58. package/esm2020/services/index.mjs +11 -11
  59. package/esm2020/services/order.service.mjs +30 -30
  60. package/esm2020/services/shipping.service.mjs +96 -96
  61. package/esm2020/services/types/index.mjs +3 -3
  62. package/esm2020/services/types/required-checkout-data.type.mjs +2 -2
  63. package/esm2020/services/types/required-checkout-subscription-data.type.mjs +2 -2
  64. package/esm2020/services/types/shipping-methods.type.mjs +2 -2
  65. package/esm2020/types/firebase-app-config.type.mjs +2 -2
  66. package/esm2020/types/index.mjs +2 -2
  67. package/fesm2015/infrab4a-connect-angular.mjs +2429 -2387
  68. package/fesm2015/infrab4a-connect-angular.mjs.map +1 -1
  69. package/fesm2020/infrab4a-connect-angular.mjs +2369 -2326
  70. package/fesm2020/infrab4a-connect-angular.mjs.map +1 -1
  71. package/helpers/index.d.ts +1 -1
  72. package/helpers/mobile-operation-system-checker.helper.d.ts +3 -3
  73. package/index.d.ts +6 -6
  74. package/package.json +2 -2
  75. package/persistence/cookie-data-persistence.d.ts +10 -10
  76. package/persistence/data-persistence.d.ts +6 -6
  77. package/persistence/index.d.ts +2 -2
  78. package/services/auth.service.d.ts +18 -18
  79. package/services/cart.service.d.ts +42 -42
  80. package/services/catalog/adapters/category-structure.adapter.d.ts +4 -4
  81. package/services/catalog/adapters/index.d.ts +3 -3
  82. package/services/catalog/adapters/new-category-structure.adapter.d.ts +12 -12
  83. package/services/catalog/adapters/old-category-structure.adapter.d.ts +10 -10
  84. package/services/catalog/catalog.service.d.ts +89 -88
  85. package/services/catalog/category.service.d.ts +20 -20
  86. package/services/catalog/enums/index.d.ts +1 -1
  87. package/services/catalog/enums/product-sorts.enum.d.ts +9 -9
  88. package/services/catalog/index.d.ts +7 -7
  89. package/services/catalog/models/category-with-tree.model.d.ts +4 -4
  90. package/services/catalog/models/index.d.ts +1 -1
  91. package/services/catalog/types/index.d.ts +1 -1
  92. package/services/catalog/types/product-sort.type.d.ts +2 -2
  93. package/services/catalog/wishlist.service.d.ts +40 -40
  94. package/services/checkout-subscription.service.d.ts +19 -19
  95. package/services/checkout.service.d.ts +27 -27
  96. package/services/coupon.service.d.ts +33 -33
  97. package/services/helpers/index.d.ts +1 -1
  98. package/services/helpers/util.helper.d.ts +3 -3
  99. package/services/home-shop.service.d.ts +26 -26
  100. package/services/index.d.ts +10 -10
  101. package/services/order.service.d.ts +13 -13
  102. package/services/shipping.service.d.ts +19 -19
  103. package/services/types/index.d.ts +2 -2
  104. package/services/types/required-checkout-data.type.d.ts +2 -2
  105. package/services/types/required-checkout-subscription-data.type.d.ts +2 -2
  106. package/services/types/shipping-methods.type.d.ts +12 -12
  107. package/types/firebase-app-config.type.d.ts +1 -1
  108. package/types/index.d.ts +1 -1
@@ -1,202 +1,245 @@
1
- import { Inject, Injectable } from '@angular/core';
2
- import { InvalidArgumentError, ProductsIndex, RoundProductPricesHelper, Shops, Where, set, } from '@infrab4a/connect';
3
- import { CATEGORY_STRUCTURE, DEFAULT_SHOP } from '../../consts';
4
- import * as i0 from "@angular/core";
5
- import * as i1 from "@infrab4a/connect";
6
- export class CatalogService {
7
- constructor(productRepository, productStockNotificationRepository, categoryRepository, categoryStructureAdapter, shop, productIndex) {
8
- this.productRepository = productRepository;
9
- this.productStockNotificationRepository = productStockNotificationRepository;
10
- this.categoryRepository = categoryRepository;
11
- this.categoryStructureAdapter = categoryStructureAdapter;
12
- this.shop = shop;
13
- this.productIndex = productIndex;
14
- this.productsByTerm = {};
15
- this.buildFilterQuery = ({ clubDiscount, brands, prices, gender, tags, rate, customOptions, }) => {
16
- const filters = {};
17
- if (clubDiscount?.length)
18
- set(filters, 'price.subscriberDiscountPercentage', { operator: Where.IN, value: clubDiscount });
19
- if (brands?.length)
20
- filters.brand = { operator: Where.IN, value: brands };
21
- if (gender?.length)
22
- filters.gender = { operator: Where.IN, value: gender };
23
- if (prices?.min || prices?.max)
24
- set(filters, prices.subscriberPrice ? 'price.subscriberPrice' : 'price.price', [
25
- ...(prices.min ? [{ operator: Where.GTE, value: Math.round(prices.min) }] : []),
26
- ...(prices.max ? [{ operator: Where.LTE, value: Math.ceil(prices.max) }] : []),
27
- ]);
28
- if (rate)
29
- filters.rate = { operator: Where.GTE, value: rate };
30
- if (tags?.length)
31
- filters.tags = { operator: Where.LIKE, value: tags };
32
- if (customOptions?.length)
33
- filters.filters = { operator: Where.LIKE, value: customOptions };
34
- return filters;
35
- };
36
- this.buildSortQuery = (sort) => {
37
- if (!sort || sort === 'most-relevant')
38
- return {};
39
- if (sort === 'best-sellers')
40
- return {
41
- shoppingCount: 'desc',
42
- rate: 'desc',
43
- stock: 'desc',
44
- name: 'asc',
45
- };
46
- if (sort === 'biggest-price')
47
- return { subscriberPrice: 'desc', rate: 'desc', shoppingCount: 'desc' };
48
- if (sort === 'lowest-price')
49
- return { subscriberPrice: 'asc', rate: 'desc', shoppingCount: 'desc' };
50
- if (sort === 'best-rating')
51
- return { rate: 'desc', shoppingCount: 'desc', stock: 'desc', name: 'asc' };
52
- if (sort === 'news')
53
- return { createdAt: 'desc' };
54
- if (sort === 'biggest-discount')
55
- return { subscriberDiscountPercentage: 'desc', rate: 'desc', shoppingCount: 'desc' };
56
- };
57
- this.buildLimitQuery = (options) => {
58
- const limit = options?.perPage || 20;
59
- return {
60
- limit,
61
- offset: ((options?.page || 1) - 1) * limit,
62
- };
63
- };
64
- this.hasProfile = (options) => 'profile' in options;
65
- this.hasTerm = (options) => 'term' in options;
66
- this.hasCategory = (options) => 'category' in options;
67
- }
68
- async fetchProducts(options) {
69
- const limits = this.buildLimitQuery(options);
70
- if (this.hasProfile(options) && options.filters?.customOptions)
71
- throw new InvalidArgumentError(`It couldn't filled customOptions when profile is given`);
72
- if (this.hasProfile(options) && options.filters?.tags)
73
- throw new InvalidArgumentError(`It couldn't filled tags when profile is given`);
74
- if (this.hasTerm(options) && options.filters?.customOptions)
75
- throw new InvalidArgumentError(`It couldn't filled customOptions when term is given`);
76
- return await this.findCatalog(options, limits).then(({ data, count: total, maximum, minimal, distinct }) => ({
77
- products: { data: data.map((product) => RoundProductPricesHelper.roundProductPrices(product)), total },
78
- pages: Math.ceil(total / limits.limit),
79
- prices: {
80
- price: { min: +minimal?.price?.price?.toFixed(2), max: +maximum?.price?.price?.toFixed(2) },
81
- subscriberPrice: {
82
- min: +minimal?.price?.subscriberPrice?.toFixed(2),
83
- max: +maximum?.price?.subscriberPrice?.toFixed(2),
84
- },
85
- },
86
- brands: distinct?.brand,
87
- }));
88
- }
89
- async addCustomerToStockNotification(shop, productId, name, email) {
90
- return this.productStockNotificationRepository.addCustomerEmail(shop, productId, name, email);
91
- }
92
- async findCatalog(options, limits) {
93
- if (this.hasTerm(options) && options.sort === 'most-relevant') {
94
- const productsIds = await this.findCatalogIdsByElasticSearch(options.term);
95
- return this.findCatalogAndSortByMostRevelant(productsIds, options, limits);
96
- }
97
- if (this.hasCategory(options) && options.sort === 'most-relevant') {
98
- const productsIds = await this.productRepository
99
- .find({
100
- fields: ['id'],
101
- filters: {
102
- ...(await this.buildMainFilter(options)),
103
- },
104
- })
105
- .then((products) => products.data.map((product) => product.id));
106
- return this.findCatalogAndSortByMostRevelant(productsIds, options, limits);
107
- }
108
- const repoParams = {
109
- filters: {
110
- ...(await this.buildMainFilter(options)),
111
- ...this.buildFilterQuery(options?.filters || {}),
112
- },
113
- ...(options?.sort ? { orderBy: this.buildSortQuery(options?.sort) } : {}),
114
- limits,
115
- options: {
116
- minimal: ['price'],
117
- maximum: ['price'],
118
- ...(!this.hasCategory(options) ? { distinct: ['brand'] } : {}),
119
- },
120
- };
121
- if (['biggest-price', 'lowest-price', 'biggest-discount', 'best-rating'].includes(options.sort))
122
- return this.productRepository.findCatalog(repoParams);
123
- return this.productRepository.findCatalog(repoParams, options?.mainGender || this.shop === Shops.MENSMARKET ? 'male' : 'female');
124
- }
125
- async buildMainFilter({ category, profile, term, }) {
126
- if (category)
127
- return this.categoryStructureAdapter.buildProductFilterByCategory(category);
128
- if (profile)
129
- return { tags: { operator: Where.LIKE, value: profile } };
130
- if (term)
131
- return this.productIndex
132
- .search(term, 999, this.shop)
133
- .then((data) => ({ id: { operator: Where.IN, value: data.hits.map(({ _source }) => _source.id) } }));
134
- }
135
- async findCatalogAndSortByMostRevelant(productIds, options, limits) {
136
- const totalResult = await this.productRepository.findCatalog({
137
- fields: ['id', 'stock'],
138
- filters: {
139
- id: { operator: Where.IN, value: productIds },
140
- ...this.buildFilterQuery(options?.filters || {}),
141
- },
142
- options: {
143
- minimal: ['price'],
144
- maximum: ['price'],
145
- distinct: ['brand'],
146
- },
147
- }, options?.mainGender || this.shop === Shops.MENSMARKET ? 'male' : 'female');
148
- const stockData = totalResult.data.filter((product) => product.stock.quantity > 0);
149
- const stockOut = totalResult.data.filter((product) => product.stock.quantity <= 0);
150
- const productIdsStock = productIds.filter((product) => stockData.some((result) => result.id == product));
151
- const productIdsStockOut = productIds.filter((product) => stockOut.some((result) => result.id == product));
152
- const limitedProductId = productIdsStock
153
- .concat(productIdsStockOut)
154
- .slice(limits.offset, limits.offset + limits.limit);
155
- const orderedId = productIds.filter((product) => limitedProductId.includes(product));
156
- const productResult = await this.productRepository.findCatalog({
157
- filters: {
158
- id: { operator: Where.IN, value: orderedId },
159
- },
160
- });
161
- return {
162
- data: limitedProductId.map((id) => productResult.data.find((product) => product.id === id)).filter(Boolean),
163
- count: totalResult.count,
164
- maximum: totalResult.maximum,
165
- minimal: totalResult.minimal,
166
- distinct: totalResult.distinct,
167
- };
168
- }
169
- async findCatalogIdsByElasticSearch(term) {
170
- if (this.productsByTerm[term])
171
- return this.productsByTerm[term];
172
- return (this.productsByTerm[term] = await this.productIndex
173
- .search(term, 999, this.shop)
174
- .then(({ hits: products }) => {
175
- const withStock = products.filter(({ _source }) => _source.stock.quantity > 0);
176
- const withOutStock = products.filter(({ _source }) => _source.stock.quantity <= 0);
177
- const sorted = [...withStock, ...withOutStock];
178
- return [...new Set(sorted.map(({ _source }) => _source.id))];
179
- }));
180
- }
181
- }
182
- CatalogService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.0", ngImport: i0, type: CatalogService, deps: [{ token: 'ProductRepository' }, { token: 'ProductStockNotificationRepository' }, { token: 'CategoryRepository' }, { token: CATEGORY_STRUCTURE }, { token: DEFAULT_SHOP }, { token: i1.ProductsIndex }], target: i0.ɵɵFactoryTarget.Injectable });
183
- CatalogService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.1.0", ngImport: i0, type: CatalogService });
184
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.0", ngImport: i0, type: CatalogService, decorators: [{
185
- type: Injectable
186
- }], ctorParameters: function () { return [{ type: undefined, decorators: [{
187
- type: Inject,
188
- args: ['ProductRepository']
189
- }] }, { type: undefined, decorators: [{
190
- type: Inject,
191
- args: ['ProductStockNotificationRepository']
192
- }] }, { type: undefined, decorators: [{
193
- type: Inject,
194
- args: ['CategoryRepository']
195
- }] }, { type: undefined, decorators: [{
196
- type: Inject,
197
- args: [CATEGORY_STRUCTURE]
198
- }] }, { type: i1.Shops, decorators: [{
199
- type: Inject,
200
- args: [DEFAULT_SHOP]
201
- }] }, { type: i1.ProductsIndex }]; } });
202
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2F0YWxvZy5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvY29ubmVjdC1hbmd1bGFyL3NyYy9zZXJ2aWNlcy9jYXRhbG9nL2NhdGFsb2cuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQTtBQUNsRCxPQUFPLEVBSUwsb0JBQW9CLEVBS3BCLGFBQWEsRUFJYix3QkFBd0IsRUFDeEIsS0FBSyxFQUNMLEtBQUssRUFDTCxHQUFHLEdBQ0osTUFBTSxtQkFBbUIsQ0FBQTtBQUMxQixPQUFPLEVBQUUsa0JBQWtCLEVBQUUsWUFBWSxFQUFFLE1BQU0sY0FBYyxDQUFBOzs7QUFzRC9ELE1BQU0sT0FBTyxjQUFjO0lBR3pCLFlBQ2dELGlCQUFvQyxFQUVqRSxrQ0FBc0UsRUFDeEMsa0JBQXNDLEVBQ3hDLHdCQUFrRCxFQUN4RCxJQUFXLEVBQ2pDLFlBQTJCO1FBTkUsc0JBQWlCLEdBQWpCLGlCQUFpQixDQUFtQjtRQUVqRSx1Q0FBa0MsR0FBbEMsa0NBQWtDLENBQW9DO1FBQ3hDLHVCQUFrQixHQUFsQixrQkFBa0IsQ0FBb0I7UUFDeEMsNkJBQXdCLEdBQXhCLHdCQUF3QixDQUEwQjtRQUN4RCxTQUFJLEdBQUosSUFBSSxDQUFPO1FBQ2pDLGlCQUFZLEdBQVosWUFBWSxDQUFlO1FBVHRDLG1CQUFjLEdBQTZCLEVBQUUsQ0FBQTtRQXdLN0MscUJBQWdCLEdBQUcsQ0FBQyxFQUMxQixZQUFZLEVBQ1osTUFBTSxFQUNOLE1BQU0sRUFDTixNQUFNLEVBQ04sSUFBSSxFQUNKLElBQUksRUFDSixhQUFhLEdBQ1EsRUFBbUMsRUFBRTtZQUMxRCxNQUFNLE9BQU8sR0FBRyxFQUFxQyxDQUFBO1lBRXJELElBQUksWUFBWSxFQUFFLE1BQU07Z0JBQ3RCLEdBQUcsQ0FBQyxPQUFPLEVBQUUsb0NBQW9DLEVBQUUsRUFB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WSxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLE9BQU8sRUFBRSxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLFFBQVEsSUFBSSxDQUFDLENBQUMsQ0FBQTtZQUNsRixNQUFNLE1BQU0sR0FBRyxDQUFDLEdBQUcsU0FBUyxFQUFFLEdBQUcsWUFBWSxDQUFDLENBQUE7WUFFOUMsT0FBTyxDQUFDLEdBQUcsSUFBSSxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUE7UUFDOUQsQ0FBQyxDQUFDLENBQUMsQ0FBQTtJQUNQLENBQUM7OzJHQXZLVSxjQUFjLGtCQUlmLG1CQUFtQixhQUNuQixvQ0FBb0MsYUFFcEMsb0JBQW9CLGFBQ3BCLGtCQUFrQixhQUNsQixZQUFZOytHQVRYLGNBQWM7MkZBQWQsY0FBYztrQkFEMUIsVUFBVTs7MEJBS04sTUFBTTsyQkFBQyxtQkFBbUI7OzBCQUMxQixNQUFNOzJCQUFDLG9DQUFvQzs7MEJBRTNDLE1BQU07MkJBQUMsb0JBQW9COzswQkFDM0IsTUFBTTsyQkFBQyxrQkFBa0I7OzBCQUN6QixNQUFNOzJCQUFDLFlBQVkiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3QsIEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJ1xuaW1wb3J0IHtcbiAgQ2F0ZWdvcnksXG4gIENhdGVnb3J5UmVwb3NpdG9yeSxcbiAgRmluZFJlcG9zaXRvcnlQYXJhbXMsXG4gIEludmFsaWRBcmd1bWVudEVycm9yLFxuICBQcm9kdWN0LFxuICBQcm9kdWN0R2VuZGVyLFxuICBQcm9kdWN0UmVwb3NpdG9yeSxcbiAgUHJvZHVjdFN0b2NrTm90aWZpY2F0aW9uUmVwb3NpdG9yeSxcbiAgUHJvZHVjdHNJbmRleCxcbiAgUmVwb3NpdG9yeUZpbmRGaWVsdGVycyxcbiAgUmVwb3NpdG9yeUZpbmRSZXN1bHQsXG4gIFJlcG9zaXRvcnlPcmRlckJ5LFxuICBSb3VuZFByb2R1Y3RQcmljZXNIZWxwZXIsXG4gIFNob3BzLFxuICBXaGVyZSxcbiAgc2V0LFxufSBmcm9tICdAaW5mcmFiNGEvY29ubmVjdCdcbmltcG9ydCB7IENBVEVHT1JZX1NUUlVDVFVSRSwgREVGQVVMVF9TSE9QIH0gZnJvbSAnLi4vLi4vY29uc3RzJ1xuaW1wb3J0IHsgQ2F0ZWdvcnlTdHJ1Y3R1cmVBZGFwdGVyIH0gZnJvbSAnLi9hZGFwdGVycydcbmltcG9ydCB7IFByb2R1Y3RTb3J0IH0gZnJvbSAnLi90eXBlcy9wcm9kdWN0LXNvcnQudHlwZSdcblxudHlwZSBGZXRjaFByb2R1Y3RzRmlsdGVycyA9IHtcbiAgY2x1YkRpc2NvdW50PzogbnVtYmVyW11cbiAgYnJhbmRzPzogc3RyaW5nW11cbiAgcHJpY2VzPzogeyBtaW4/OiBudW1iZXI7IG1heD86IG51bWJlcjsgc3Vic2NyaWJlclByaWNlPzogYm9vbGVhbiB9XG4gIGdlbmRlcj86IFByb2R1Y3RHZW5kZXJbXVxuICByYXRlPzogbnVtYmVyXG4gIGN1c3RvbU9wdGlvbnM/OiBzdHJpbmdbXVxuICB0YWdzPzogc3RyaW5nW11cbn1cblxudHlwZSBGZXRjaFByb2R1Y3RzT3B0aW9ucyA9IHtcbiAgcGFnZT86IG51bWJlclxuICBwZXJQYWdlPzogbnVtYmVyXG4gIHNvcnQ/OiBQcm9kdWN0U29ydFxuICBtYWluR2VuZGVyPzogUHJvZHVjdEdlbmRlclxufVxuXG50eXBlIEZldGNoUHJvZHVjdHNNYWluUGFyYW1zPFQgZXh0ZW5kcyBDYXRlZ29yeT4gPSB7XG4gIGNhdGVnb3J5PzogVFxuICBwcm9maWxlPzogc3RyaW5nW11cbiAgdGVybT86IHN0cmluZ1xufVxuXG50eXBlIEZldGNoUHJvZHVjdHNQYXJhbXM8VCBleHRlbmRzIENhdGVnb3J5PiA9IEZldGNoUHJvZHVjdHNPcHRpb25zICZcbiAgKFxuICAgIHwge1xuICAgICAgICBjYXRlZ29yeTogRmV0Y2hQcm9kdWN0c01haW5QYXJhbXM8VD5bJ2NhdGVnb3J5J11cbiAgICAgICAgZmlsdGVycz86IEZldGNoUHJvZHVjdHNGaWx0ZXJzICYgeyBjdXN0b21PcHRpb25zPzogbmV2ZXIgfVxuICAgICAgfVxuICAgIHwge1xuICAgICAgICBwcm9maWxlOiBGZXRjaFByb2R1Y3RzTWFpblBhcmFtczxUPlsncHJvZmlsZSddXG4gICAgICAgIGZpbHRlcnM/OiBGZXRjaFByb2R1Y3RzRmlsdGVycyAmIHsgY3VzdG9tT3B0aW9ucz86IG5ldmVyOyB0YWdzPzogbmV2ZXIgfVxuICAgICAgfVxuICAgIHwge1xuICAgICAgICB0ZXJtOiBGZXRjaFByb2R1Y3RzTWFpblBhcmFtczxUPlsndGVybSddXG4gICAgICAgIGZpbHRlcnM/OiBGZXRjaFByb2R1Y3RzRmlsdGVycyAmIHsgY3VzdG9tT3B0aW9ucz86IG5ldmVyIH1cbiAgICAgIH1cbiAgKVxuXG50eXBlIEZldGNoUHJvZHVjdHNSZXNwb25zZSA9IHtcbiAgcHJvZHVjdHM6IHsgZGF0YTogUHJvZHVjdFtdOyB0b3RhbDogbnVtYmVyIH1cbiAgcGFnZXM6IG51bWJlclxuICBwcmljZXM6IHtcbiAgICBwcmljZTogeyBtaW46IG51bWJlcjsgbWF4OiBudW1iZXIgfVxuICAgIHN1YnNjcmliZXJQcmljZTogeyBtaW46IG51bWJlcjsgbWF4OiBudW1iZXIgfVxuICB9XG4gIGJyYW5kcz86IHN0cmluZ1tdXG59XG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBDYXRhbG9nU2VydmljZTxUIGV4dGVuZHMgQ2F0ZWdvcnkgPSBDYXRlZ29yeT4ge1xuICBwcml2YXRlIHByb2R1Y3RzQnlUZXJtOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmdbXT4gPSB7fVxuXG4gIGNvbnN0cnVjdG9yKFxuICAgIEBJbmplY3QoJ1Byb2R1Y3RSZXBvc2l0b3J5JykgcHJpdmF0ZSByZWFkb25seSBwcm9kdWN0UmVwb3NpdG9yeTogUHJvZHVjdFJlcG9zaXRvcnksXG4gICAgQEluamVjdCgnUHJvZHVjdFN0b2NrTm90aWZpY2F0aW9uUmVwb3NpdG9yeScpXG4gICAgcHJpdmF0ZSByZWFkb25seSBwcm9kdWN0U3RvY2tOb3RpZmljYXRpb25SZXBvc2l0b3J5OiBQcm9kdWN0U3RvY2tOb3RpZmljYXRpb25SZXBvc2l0b3J5LFxuICAgIEBJbmplY3QoJ0NhdGVnb3J5UmVwb3NpdG9yeScpIHByaXZhdGUgcmVhZG9ubHkgY2F0ZWdvcnlSZXBvc2l0b3J5OiBDYXRlZ29yeVJlcG9zaXRvcnksXG4gICAgQEluamVjdChDQVRFR09SWV9TVFJVQ1RVUkUpIHByaXZhdGUgcmVhZG9ubHkgY2F0ZWdvcnlTdHJ1Y3R1cmVBZGFwdGVyOiBDYXRlZ29yeVN0cnVjdHVyZUFkYXB0ZXIsXG4gICAgQEluamVjdChERUZBVUxUX1NIT1ApIHByaXZhdGUgcmVhZG9ubHkgc2hvcDogU2hvcHMsXG4gICAgcHJpdmF0ZSByZWFkb25seSBwcm9kdWN0SW5kZXg6IFByb2R1Y3RzSW5kZXgsXG4gICkge31cblxuICBhc3luYyBmZXRjaFByb2R1Y3RzKG9wdGlvbnM6IEZldGNoUHJvZHVjdHNQYXJhbXM8VD4pOiBQcm9taXNlPEZldGNoUHJvZHVjdHNSZXNwb25zZT4ge1xuICAgIGNvbnN0IGxpbWl0cyA9IHRoaXMuYnVpbGRMaW1pdFF1ZXJ5KG9wdGlvbnMpXG5cbiAgICBpZiAodGhpcy5oYXNQcm9maWxlKG9wdGlvbnMpICYmIG9wdGlvbnMuZmlsdGVycz8uY3VzdG9tT3B0aW9ucylcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkQXJndW1lbnRFcnJvcihgSXQgY291bGRuJ3QgZmlsbGVkIGN1c3RvbU9wdGlvbnMgd2hlbiBwcm9maWxlIGlzIGdpdmVuYClcbiAgICBpZiAodGhpcy5oYXNQcm9maWxlKG9wdGlvbnMpICYmIG9wdGlvbnMuZmlsdGVycz8udGFncylcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkQXJndW1lbnRFcnJvcihgSXQgY291bGRuJ3QgZmlsbGVkIHRhZ3Mgd2hlbiBwcm9maWxlIGlzIGdpdmVuYClcbiAgICBpZiAodGhpcy5oYXNUZXJtKG9wdGlvbnMpICYmIG9wdGlvbnMuZmlsdGVycz8uY3VzdG9tT3B0aW9ucylcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkQXJndW1lbnRFcnJvcihgSXQgY291bGRuJ3QgZmlsbGVkIGN1c3RvbU9wdGlvbnMgd2hlbiB0ZXJtIGlzIGdpdmVuYClcblxuICAgIHJldHVybiBhd2FpdCB0aGlzLmZpbmRDYXRhbG9nKG9wdGlvbnMsIGxpbWl0cykudGhlbigoeyBkYXRhLCBjb3VudDogdG90YWwsIG1heGltdW0sIG1pbmltYWwsIGRpc3RpbmN0IH0pID0+ICh7XG4gICAgICBwcm9kdWN0czogeyBkYXRhOiBkYXRhLm1hcCgocHJvZHVjdCkgPT4gUm91bmRQcm9kdWN0UHJpY2VzSGVscGVyLnJvdW5kUHJvZHVjdFByaWNlcyhwcm9kdWN0KSksIHRvdGFsIH0sXG4gICAgICBwYWdlczogTWF0aC5jZWlsKHRvdGFsIC8gbGltaXRzLmxpbWl0KSxcbiAgICAgIHByaWNlczoge1xuICAgICAgICBwcmljZTogeyBtaW46ICttaW5pbWFsPy5wcmljZT8ucHJpY2U/LnRvRml4ZWQoMiksIG1heDogK21heGltdW0/LnByaWNlPy5wcmljZT8udG9GaXhlZCgyKSB9LFxuICAgICAgICBzdWJzY3JpYmVyUHJpY2U6IHtcbiAgICAgICAgICBtaW46ICttaW5pbWFsPy5wcmljZT8uc3Vic2NyaWJlclByaWNlPy50b0ZpeGVkKDIpLFxuICAgICAgICAgIG1heDogK21heGltdW0/LnByaWNlPy5zdWJzY3JpYmVyUHJpY2U/LnRvRml4ZWQoMiksXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgYnJhbmRzOiBkaXN0aW5jdD8uYnJhbmQsXG4gICAgfSkpXG4gIH1cblxuICBhc3luYyBhZGRDdXN0b21lclRvU3RvY2tOb3RpZmljYXRpb24oc2hvcDogU2hvcHMsIHByb2R1Y3RJZDogc3RyaW5nLCBuYW1lOiBzdHJpbmcsIGVtYWlsOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gdGhpcy5wcm9kdWN0U3RvY2tOb3RpZmljYXRpb25SZXBvc2l0b3J5LmFkZEN1c3RvbWVyRW1haWwoc2hvcCwgcHJvZHVjdElkLCBuYW1lLCBlbWFpbClcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZmluZENhdGFsb2coXG4gICAgb3B0aW9uczogRmV0Y2hQcm9kdWN0c1BhcmFtczxUPixcbiAgICBsaW1pdHM6IHtcbiAgICAgIGxpbWl0PzogbnVtYmVyXG4gICAgICBvZmZzZXQ/OiBudW1iZXJcbiAgICB9LFxuICApOiBQcm9taXNlPFJlcG9zaXRvcnlGaW5kUmVzdWx0PFByb2R1Y3Q+PiB7XG4gICAgaWYgKHRoaXMuaGFzVGVybShvcHRpb25zKSAmJiBvcHRpb25zLnNvcnQgPT09ICdtb3N0LXJlbGV2YW50Jykge1xuICAgICAgY29uc3QgcHJvZHVjdHNJZHMgPSBhd2FpdCB0aGlzLmZpbmRDYXRhbG9nSWRzQnlFbGFzdGljU2VhcmNoKG9wdGlvbnMudGVybSlcblxuICAgICAgcmV0dXJuIHRoaXMuZmluZENhdGFsb2dBbmRTb3J0QnlNb3N0UmV2ZWxhbnQocHJvZHVjdHNJZHMsIG9wdGlvbnMsIGxpbWl0cylcbiAgICB9XG5cbiAgICBpZiAodGhpcy5oYXNDYXRlZ29yeShvcHRpb25zKSAmJiBvcHRpb25zLnNvcnQgPT09ICdtb3N0LXJlbGV2YW50Jykge1xuICAgICAgY29uc3QgcHJvZHVjdHNJZHMgPSBhd2FpdCB0aGlzLnByb2R1Y3RSZXBvc2l0b3J5XG4gICAgICAgIC5maW5kKHtcbiAgICAgICAgICBmaWVsZHM6IFsnaWQnXSxcbiAgICAgICAgICBmaWx0ZXJzOiB7XG4gICAgICAgICAgICAuLi4oYXdhaXQgdGhpcy5idWlsZE1haW5GaWx0ZXIob3B0aW9ucykpLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pXG4gICAgICAgIC50aGVuKChwcm9kdWN0cykgPT4gcHJvZHVjdHMuZGF0YS5tYXAoKHByb2R1Y3QpID0+IHByb2R1Y3QuaWQpKVxuXG4gICAgICByZXR1cm4gdGhpcy5maW5kQ2F0YWxvZ0FuZFNvcnRCeU1vc3RSZXZlbGFudChwcm9kdWN0c0lkcywgb3B0aW9ucywgbGltaXRzKVxuICAgIH1cblxuICAgIGNvbnN0IHJlcG9QYXJhbXM6IEZpbmRSZXBvc2l0b3J5UGFyYW1zPFByb2R1Y3Q+ID0ge1xuICAgICAgZmlsdGVyczoge1xuICAgICAgICAuLi4oYXdhaXQgdGhpcy5idWlsZE1haW5GaWx0ZXIob3B0aW9ucykpLFxuICAgICAgICAuLi50aGlzLmJ1aWxkRmlsdGVyUXVlcnkob3B0aW9ucz8uZmlsdGVycyB8fCB7fSksXG4gICAgICB9LFxuICAgICAgLi4uKG9wdGlvbnM/LnNvcnQgPyB7IG9yZGVyQnk6IHRoaXMuYnVpbGRTb3J0UXVlcnkob3B0aW9ucz8uc29ydCkgfSA6IHt9KSxcbiAgICAgIGxpbWl0cyxcbiAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgbWluaW1hbDogWydwcmljZSddLFxuICAgICAgICBtYXhpbXVtOiBbJ3ByaWNlJ10sXG4gICAgICAgIC4uLighdGhpcy5oYXNDYXRlZ29yeShvcHRpb25zKSA/IHsgZGlzdGluY3Q6IFsnYnJhbmQnXSB9IDoge30pLFxuICAgICAgfSxcbiAgICB9XG5cbiAgICBpZiAoWydiaWdnZXN0LXByaWNlJywgJ2xvd2VzdC1wcmljZScsICdiaWdnZXN0LWRpc2NvdW50JywgJ2Jlc3QtcmF0aW5nJ10uaW5jbHVkZXMob3B0aW9ucy5zb3J0KSlcbiAgICAgIHJldHVybiB0aGlzLnByb2R1Y3RSZXBvc2l0b3J5LmZpbmRDYXRhbG9nKHJlcG9QYXJhbXMpXG5cbiAgICByZXR1cm4gdGhpcy5wcm9kdWN0UmVwb3NpdG9yeS5maW5kQ2F0YWxvZyhcbiAgICAgIHJlcG9QYXJhbXMsXG4gICAgICBvcHRpb25zPy5tYWluR2VuZGVyIHx8IHRoaXMuc2hvcCA9PT0gU2hvcHMuTUVOU01BUktFVCA/ICdtYWxlJyA6ICdmZW1hbGUnLFxuICAgIClcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgYnVpbGRNYWluRmlsdGVyKHtcbiAgICBjYXRlZ29yeSxcbiAgICBwcm9maWxlLFxuICAgIHRlcm0sXG4gIH06IEZldGNoUHJvZHVjdHNNYWluUGFyYW1zPFQ+KTogUHJvbWlzZTxSZXBvc2l0b3J5RmluZEZpZWx0ZXJzPFByb2R1Y3Q+PiB7XG4gICAgaWYgKGNhdGVnb3J5KSByZXR1cm4gdGhpcy5jYXRlZ29yeVN0cnVjdHVyZUFkYXB0ZXIuYnVpbGRQcm9kdWN0RmlsdGVyQnlDYXRlZ29yeShjYXRlZ29yeSlcbiAgICBpZiAocHJvZmlsZSkgcmV0dXJuIHsgdGFnczogeyBvcGVyYXRvcjogV2hlcmUuTElLRSwgdmFsdWU6IHByb2ZpbGUgfSB9XG4gICAgaWYgKHRlcm0pXG4gICAgICByZXR1cm4gdGhpcy5wcm9kdWN0SW5kZXhcbiAgICAgICAgLnNlYXJjaCh0ZXJtLCA5OTksIHRoaXMuc2hvcClcbiAgICAgICAgLnRoZW4oKGRhdGEpID0+ICh7IGlkOiB7IG9wZXJhdG9yOiBXaGVyZS5JTiwgdmFsdWU6IGRhdGEuaGl0cy5tYXAoKHsgX3NvdXJjZSB9KSA9PiBfc291cmNlLmlkKSB9IH0pKVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBmaW5kQ2F0YWxvZ0FuZFNvcnRCeU1vc3RSZXZlbGFudChcbiAgICBwcm9kdWN0SWRzOiBzdHJpbmdbXSxcbiAgICBvcHRpb25zOiBPbWl0PEZldGNoUHJvZHVjdHNPcHRpb25zLCAnc29ydCc+ICYge1xuICAgICAgdGVybT86IEZldGNoUHJvZHVjdHNNYWluUGFyYW1zPFQ+Wyd0ZXJtJ11cbiAgICAgIGZpbHRlcnM/OiBGZXRjaFByb2R1Y3RzRmlsdGVycyAmIHsgY3VzdG9tT3B0aW9ucz86IG5ldmVyIH1cbiAgICB9LFxuICAgIGxpbWl0czoge1xuICAgICAgbGltaXQ/OiBudW1iZXJcbiAgICAgIG9mZnNldD86IG51bWJlclxuICAgIH0sXG4gICk6IFByb21pc2U8UmVwb3NpdG9yeUZpbmRSZXN1bHQ8UHJvZHVjdD4+IHtcbiAgICBjb25zdCB0b3RhbFJlc3VsdCA9IGF3YWl0IHRoaXMucHJvZHVjdFJlcG9zaXRvcnkuZmluZENhdGFsb2coXG4gICAgICB7XG4gICAgICAgIGZpZWxkczogWydpZCcsICdzdG9jayddLFxuICAgICAgICBmaWx0ZXJzOiB7XG4gICAgICAgICAgaWQ6IHsgb3BlcmF0b3I6IFdoZXJlLklOLCB2YWx1ZTogcHJvZHVjdElkcyB9LFxuICAgICAgICAgIC4uLnRoaXMuYnVpbGRGaWx0ZXJRdWVyeShvcHRpb25zPy5maWx0ZXJzIHx8IHt9KSxcbiAgICAgICAgfSxcbiAgICAgICAgb3B0aW9uczoge1xuICAgICAgICAgIG1pbmltYWw6IFsncHJpY2UnXSxcbiAgICAgICAgICBtYXhpbXVtOiBbJ3ByaWNlJ10sXG4gICAgICAgICAgZGlzdGluY3Q6IFsnYnJhbmQnXSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICBvcHRpb25zPy5tYWluR2VuZGVyIHx8IHRoaXMuc2hvcCA9PT0gU2hvcHMuTUVOU01BUktFVCA/ICdtYWxlJyA6ICdmZW1hbGUnLFxuICAgIClcblxuICAgIGNvbnN0IHN0b2NrRGF0YSA9IHRvdGFsUmVzdWx0LmRhdGEuZmlsdGVyKChwcm9kdWN0KSA9PiBwcm9kdWN0LnN0b2NrLnF1YW50aXR5ID4gMClcbiAgICBjb25zdCBzdG9ja091dCA9IHRvdGFsUmVzdWx0LmRhdGEuZmlsdGVyKChwcm9kdWN0KSA9PiBwcm9kdWN0LnN0b2NrLnF1YW50aXR5IDw9IDApXG4gICAgY29uc3QgcHJvZHVjdElkc1N0b2NrID0gcHJvZHVjdElkcy5maWx0ZXIoKHByb2R1Y3QpID0+IHN0b2NrRGF0YS5zb21lKChyZXN1bHQpID0+IHJlc3VsdC5pZCA9PSBwcm9kdWN0KSlcbiAgICBjb25zdCBwcm9kdWN0SWRzU3RvY2tPdXQgPSBwcm9kdWN0SWRzLmZpbHRlcigocHJvZHVjdCkgPT4gc3RvY2tPdXQuc29tZSgocmVzdWx0KSA9PiByZXN1bHQuaWQgPT0gcHJvZHVjdCkpXG5cbiAgICBjb25zdCBsaW1pdGVkUHJvZHVjdElkID0gcHJvZHVjdElkc1N0b2NrXG4gICAgICAuY29uY2F0KHByb2R1Y3RJZHNTdG9ja091dClcbiAgICAgIC5zbGljZShsaW1pdHMub2Zmc2V0LCBsaW1pdHMub2Zmc2V0ICsgbGltaXRzLmxpbWl0KVxuXG4gICAgY29uc3Qgb3JkZXJlZElkID0gcHJvZHVjdElkcy5maWx0ZXIoKHByb2R1Y3QpID0+IGxpbWl0ZWRQcm9kdWN0SWQuaW5jbHVkZXMocHJvZHVjdCkpXG4gICAgY29uc3QgcHJvZHVjdFJlc3VsdCA9IGF3YWl0IHRoaXMucHJvZHVjdFJlcG9zaXRvcnkuZmluZENhdGFsb2coe1xuICAgICAgZmlsdGVyczoge1xuICAgICAgICBpZDogeyBvcGVyYXRvcjogV2hlcmUuSU4sIHZhbHVlOiBvcmRlcmVkSWQgfSxcbiAgICAgIH0sXG4gICAgfSlcblxuICAgIHJldHVybiB7XG4gICAgICBkYXRhOiBsaW1pdGVkUHJvZHVjdElkLm1hcCgoaWQpID0+IHByb2R1Y3RSZXN1bHQuZGF0YS5maW5kKChwcm9kdWN0KSA9PiBwcm9kdWN0LmlkID09PSBpZCkpLmZpbHRlcihCb29sZWFuKSxcbiAgICAgIGNvdW50OiB0b3RhbFJlc3VsdC5jb3VudCxcbiAgICAgIG1heGltdW06IHRvdGFsUmVzdWx0Lm1heGltdW0sXG4gICAgICBtaW5pbWFsOiB0b3RhbFJlc3VsdC5taW5pbWFsLFxuICAgICAgZGlzdGluY3Q6IHRvdGFsUmVzdWx0LmRpc3RpbmN0LFxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZmluZENhdGFsb2dJZHNCeUVsYXN0aWNTZWFyY2godGVybTogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICAgIGlmICh0aGlzLnByb2R1Y3RzQnlUZXJtW3Rlcm1dKSByZXR1cm4gdGhpcy5wcm9kdWN0c0J5VGVybVt0ZXJtXVxuXG4gICAgcmV0dXJuICh0aGlzLnByb2R1Y3RzQnlUZXJtW3Rlcm1dID0gYXdhaXQgdGhpcy5wcm9kdWN0SW5kZXhcbiAgICAgIC5zZWFyY2godGVybSwgOTk5LCB0aGlzLnNob3ApXG4gICAgICAudGhlbigoeyBoaXRzOiBwcm9kdWN0cyB9KSA9PiB7XG4gICAgICAgIGNvbnN0IHdpdGhTdG9jayA9IHByb2R1Y3RzLmZpbHRlcigoeyBfc291cmNlIH0pID0+IF9zb3VyY2Uuc3RvY2sucXVhbnRpdHkgPiAwKVxuICAgICAgICBjb25zdCB3aXRoT3V0U3RvY2sgPSBwcm9kdWN0cy5maWx0ZXIoKHsgX3NvdXJjZSB9KSA9PiBfc291cmNlLnN0b2NrLnF1YW50aXR5IDw9IDApXG4gICAgICAgIGNvbnN0IHNvcnRlZCA9IFsuLi53aXRoU3RvY2ssIC4uLndpdGhPdXRTdG9ja11cblxuICAgICAgICByZXR1cm4gWy4uLm5ldyBTZXQoc29ydGVkLm1hcCgoeyBfc291cmNlIH0pID0+IF9zb3VyY2UuaWQpKV1cbiAgICAgIH0pKVxuICB9XG5cbiAgcHJpdmF0ZSBidWlsZEZpbHRlclF1ZXJ5ID0gKHtcbiAgICBjbHViRGlzY291bnQsXG4gICAgYnJhbmRzLFxuICAgIHByaWNlcyxcbiAgICBnZW5kZXIsXG4gICAgdGFncyxcbiAgICByYXRlLFxuICAgIGN1c3RvbU9wdGlvbnMsXG4gIH06IEZldGNoUHJvZHVjdHNGaWx0ZXJzKTogUmVwb3NpdG9yeUZpbmRGaWVsdGVyczxQcm9kdWN0PiA9PiB7XG4gICAgY29uc3QgZmlsdGVycyA9IHt9IGFzIFJlcG9zaXRvcnlGaW5kRmllbHRlcnM8UHJvZHVjdD5cblxuICAgIGlmIChjbHViRGlzY291bnQ/Lmxlbmd0aClcbiAgICAgIHNldChmaWx0ZXJzLCAncHJpY2Uuc3Vic2NyaWJlckRpc2NvdW50UGVyY2VudGFnZScsIHsgb3BlcmF0b3I6IFdoZXJlLklOLCB2YWx1ZTogY2x1YkRpc2NvdW50IH0pXG4gICAgaWYgKGJyYW5kcz8ubGVuZ3RoKSBmaWx0ZXJzLmJyYW5kID0geyBvcGVyYXRvcjogV2hlcmUuSU4sIHZhbHVlOiBicmFuZHMgfVxuICAgIGlmIChnZW5kZXI/Lmxlbmd0aCkgZmlsdGVycy5nZW5kZXIgPSB7IG9wZXJhdG9yOiBXaGVyZS5JTiwgdmFsdWU6IGdlbmRlciB9XG4gICAgaWYgKHByaWNlcz8ubWluIHx8IHByaWNlcz8ubWF4KVxuICAgICAgc2V0KGZpbHRlcnMsIHByaWNlcy5zdWJzY3JpYmVyUHJpY2UgPyAncHJpY2Uuc3Vic2NyaWJlclByaWNlJyA6ICdwcmljZS5wcmljZScsIFtcbiAgICAgICAgLi4uKHByaWNlcy5taW4gPyBbeyBvcGVyYXRvcjogV2hlcmUuR1RFLCB2YWx1ZTogTWF0aC5yb3VuZChwcmljZXMubWluKSB9XSA6IFtdKSxcbiAgICAgICAgLi4uKHByaWNlcy5tYXggPyBbeyBvcGVyYXRvcjogV2hlcmUuTFRFLCB2YWx1ZTogTWF0aC5jZWlsKHByaWNlcy5tYXgpIH1dIDogW10pLFxuICAgICAgXSlcbiAgICBpZiAocmF0ZSkgZmlsdGVycy5yYXRlID0geyBvcGVyYXRvcjogV2hlcmUuR1RFLCB2YWx1ZTogcmF0ZSB9XG4gICAgaWYgKHRhZ3M/Lmxlbmd0aCkgZmlsdGVycy50YWdzID0geyBvcGVyYXRvcjogV2hlcmUuTElLRSwgdmFsdWU6IHRhZ3MgfVxuICAgIGlmIChjdXN0b21PcHRpb25zPy5sZW5ndGgpIGZpbHRlcnMuZmlsdGVycyA9IHsgb3BlcmF0b3I6IFdoZXJlLkxJS0UsIHZhbHVlOiBjdXN0b21PcHRpb25zIH1cblxuICAgIHJldHVybiBmaWx0ZXJzXG4gIH1cblxuICBwcml2YXRlIGJ1aWxkU29ydFF1ZXJ5ID0gKHNvcnQ6IFByb2R1Y3RTb3J0KTogUmVwb3NpdG9yeU9yZGVyQnk8UHJvZHVjdD4gPT4ge1xuICAgIGlmICghc29ydCB8fCBzb3J0ID09PSAnbW9zdC1yZWxldmFudCcpIHJldHVybiB7fVxuXG4gICAgaWYgKHNvcnQgPT09ICdiZXN0LXNlbGxlcnMnKVxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgc2hvcHBpbmdDb3VudDogJ2Rlc2MnLFxuICAgICAgICByYXRlOiAnZGVzYycsXG4gICAgICAgIHN0b2NrOiAnZGVzYycsXG4gICAgICAgIG5hbWU6ICdhc2MnLFxuICAgICAgfVxuICAgIGlmIChzb3J0ID09PSAnYmlnZ2VzdC1wcmljZScpIHJldHVybiB7IHN1YnNjcmliZXJQcmljZTogJ2Rlc2MnLCByYXRlOiAnZGVzYycsIHNob3BwaW5nQ291bnQ6ICdkZXNjJyB9IGFzIGFueVxuICAgIGlmIChzb3J0ID09PSAnbG93ZXN0LXByaWNlJykgcmV0dXJuIHsgc3Vic2NyaWJlclByaWNlOiAnYXNjJywgcmF0ZTogJ2Rlc2MnLCBzaG9wcGluZ0NvdW50OiAnZGVzYycgfSBhcyBhbnlcbiAgICBpZiAoc29ydCA9PT0gJ2Jlc3QtcmF0aW5nJykgcmV0dXJuIHsgcmF0ZTogJ2Rlc2MnLCBzaG9wcGluZ0NvdW50OiAnZGVzYycsIHN0b2NrOiAnZGVzYycsIG5hbWU6ICdhc2MnIH1cbiAgICBpZiAoc29ydCA9PT0gJ25ld3MnKSByZXR1cm4geyBjcmVhdGVkQXQ6ICdkZXNjJyB9XG4gICAgaWYgKHNvcnQgPT09ICdiaWdnZXN0LWRpc2NvdW50JylcbiAgICAgIHJldHVybiB7IHN1YnNjcmliZXJEaXNjb3VudFBlcmNlbnRhZ2U6ICdkZXNjJywgcmF0ZTogJ2Rlc2MnLCBzaG9wcGluZ0NvdW50OiAnZGVzYycgfSBhcyBhbnlcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRMaW1pdFF1ZXJ5ID0gKG9wdGlvbnM6IHsgcGFnZT86IG51bWJlcjsgcGVyUGFnZT86IG51bWJlciB9KTogeyBsaW1pdD86IG51bWJlcjsgb2Zmc2V0PzogbnVtYmVyIH0gPT4ge1xuICAgIGNvbnN0IGxpbWl0ID0gb3B0aW9ucz8ucGVyUGFnZSB8fCAyMFxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGxpbWl0LFxuICAgICAgb2Zmc2V0OiAoKG9wdGlvbnM/LnBhZ2UgfHwgMSkgLSAxKSAqIGxpbWl0LFxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgaGFzUHJvZmlsZSA9IChcbiAgICBvcHRpb25zOiBGZXRjaFByb2R1Y3RzUGFyYW1zPFQ+LFxuICApOiBvcHRpb25zIGlzIEZldGNoUHJvZHVjdHNPcHRpb25zICYge1xuICAgIHByb2ZpbGU6IEZldGNoUHJvZHVjdHNNYWluUGFyYW1zPFQ+Wydwcm9maWxlJ11cbiAgICBmaWx0ZXJzPzogRmV0Y2hQcm9kdWN0c0ZpbHRlcnMgJiB7IGN1c3RvbU9wdGlvbnM/OiBuZXZlcjsgdGFncz86IG5ldmVyIH1cbiAgfSA9PiAncHJvZmlsZScgaW4gb3B0aW9uc1xuXG4gIHByaXZhdGUgaGFzVGVybSA9IChcbiAgICBvcHRpb25zOiBGZXRjaFByb2R1Y3RzUGFyYW1zPFQ+LFxuICApOiBvcHRpb25zIGlzIEZldGNoUHJvZHVjdHNPcHRpb25zICYge1xuICAgIHRlcm06IEZldGNoUHJvZHVjdHNNYWluUGFyYW1zPFQ+Wyd0ZXJtJ11cbiAgICBmaWx0ZXJzPzogRmV0Y2hQcm9kdWN0c0ZpbHRlcnMgJiB7IGN1c3RvbU9wdGlvbnM/OiBuZXZlciB9XG4gIH0gPT4gJ3Rlcm0nIGluIG9wdGlvbnNcblxuICBwcml2YXRlIGhhc0NhdGVnb3J5ID0gKFxuICAgIG9wdGlvbnM6IEZldGNoUHJvZHVjdHNQYXJhbXM8VD4sXG4gICk6IG9wdGlvbnMgaXMgRmV0Y2hQcm9kdWN0c09wdGlvbnMgJiB7XG4gICAgY2F0ZWdvcnk6IEZldGNoUHJvZHVjdHNNYWluUGFyYW1zPFQ+WydjYXRlZ29yeSddXG4gICAgZmlsdGVycz86IEZldGNoUHJvZHVjdHNGaWx0ZXJzICYgeyBjdXN0b21PcHRpb25zPzogbmV2ZXIgfVxuICB9ID0+ICdjYXRlZ29yeScgaW4gb3B0aW9uc1xufVxuIl19
1
+ import { Inject, Injectable } from '@angular/core';
2
+ import { InvalidArgumentError, ProductsIndex, RoundProductPricesHelper, set, Shops, Where, } from '@infrab4a/connect';
3
+ import { CATEGORY_STRUCTURE, DEFAULT_SHOP } from '../../consts';
4
+ import * as i0 from "@angular/core";
5
+ import * as i1 from "@infrab4a/connect";
6
+ export class CatalogService {
7
+ constructor(productRepository, productStockNotificationRepository, categoryRepository, categoryStructureAdapter, shop, productIndex) {
8
+ this.productRepository = productRepository;
9
+ this.productStockNotificationRepository = productStockNotificationRepository;
10
+ this.categoryRepository = categoryRepository;
11
+ this.categoryStructureAdapter = categoryStructureAdapter;
12
+ this.shop = shop;
13
+ this.productIndex = productIndex;
14
+ this.productsByTerm = {};
15
+ this.buildFilterQuery = ({ clubDiscount, brands, prices, gender, tags, rate, customOptions, }) => {
16
+ const filters = {};
17
+ if (clubDiscount?.length)
18
+ set(filters, 'price.subscriberDiscountPercentage', { operator: Where.IN, value: clubDiscount });
19
+ if (brands?.length)
20
+ filters.brand = { operator: Where.IN, value: brands };
21
+ if (gender?.length)
22
+ filters.gender = { operator: Where.IN, value: gender };
23
+ if (prices?.min || prices?.max)
24
+ set(filters, prices.subscriberPrice ? 'price.subscriberPrice' : 'price.price', [
25
+ ...(prices.min ? [{ operator: Where.GTE, value: Math.round(prices.min) }] : []),
26
+ ...(prices.max ? [{ operator: Where.LTE, value: Math.ceil(prices.max) }] : []),
27
+ ]);
28
+ if (rate)
29
+ filters.rate = { operator: Where.GTE, value: rate };
30
+ if (tags?.length)
31
+ filters.tags = { operator: Where.LIKE, value: tags };
32
+ if (customOptions?.length)
33
+ filters.filters = { operator: Where.LIKE, value: customOptions };
34
+ return filters;
35
+ };
36
+ this.buildSortQuery = (sort) => {
37
+ if (!sort || sort === 'most-relevant')
38
+ return {};
39
+ if (sort === 'best-sellers')
40
+ return {
41
+ shoppingCount: 'desc',
42
+ rate: 'desc',
43
+ stock: 'desc',
44
+ name: 'asc',
45
+ };
46
+ if (sort === 'biggest-price')
47
+ return { subscriberPrice: 'desc', rate: 'desc', shoppingCount: 'desc' };
48
+ if (sort === 'lowest-price')
49
+ return { subscriberPrice: 'asc', rate: 'desc', shoppingCount: 'desc' };
50
+ if (sort === 'best-rating')
51
+ return { rate: 'desc', shoppingCount: 'desc', stock: 'desc', name: 'asc' };
52
+ if (sort === 'news')
53
+ return { createdAt: 'desc' };
54
+ if (sort === 'biggest-discount')
55
+ return { subscriberDiscountPercentage: 'desc', rate: 'desc', shoppingCount: 'desc' };
56
+ };
57
+ this.buildLimitQuery = (options) => {
58
+ const limit = options?.perPage || 20;
59
+ return {
60
+ limit,
61
+ offset: ((options?.page || 1) - 1) * limit,
62
+ };
63
+ };
64
+ this.hasProfile = (options) => 'profile' in options;
65
+ this.hasTerm = (options) => 'term' in options;
66
+ this.hasCategory = (options) => 'category' in options;
67
+ }
68
+ async fetchProducts(options) {
69
+ const limits = this.buildLimitQuery(options);
70
+ if (this.hasProfile(options) && options.filters?.customOptions)
71
+ throw new InvalidArgumentError(`It couldn't filled customOptions when profile is given`);
72
+ if (this.hasProfile(options) && options.filters?.tags)
73
+ throw new InvalidArgumentError(`It couldn't filled tags when profile is given`);
74
+ if (this.hasTerm(options) && options.filters?.customOptions)
75
+ throw new InvalidArgumentError(`It couldn't filled customOptions when term is given`);
76
+ return await this.findCatalog(options, limits).then(({ data, count: total, maximum, minimal, distinct }) => ({
77
+ products: { data: data.map((product) => RoundProductPricesHelper.roundProductPrices(product)), total },
78
+ pages: Math.ceil(total / limits.limit),
79
+ prices: {
80
+ price: { min: +minimal?.price?.price?.toFixed(2), max: +maximum?.price?.price?.toFixed(2) },
81
+ subscriberPrice: {
82
+ min: +minimal?.price?.subscriberPrice?.toFixed(2),
83
+ max: +maximum?.price?.subscriberPrice?.toFixed(2),
84
+ },
85
+ },
86
+ brands: distinct?.brand,
87
+ }));
88
+ }
89
+ async addCustomerToStockNotification(shop, productId, name, email) {
90
+ return this.productStockNotificationRepository.addCustomerEmail(shop, productId, name, email);
91
+ }
92
+ async findCatalog(options, limits) {
93
+ if (this.hasTerm(options) && options.sort === 'most-relevant') {
94
+ const productsIds = await this.findCatalogIdsByElasticSearch(options.term);
95
+ return this.findCatalogAndSortByMostRevelantByTerm(productsIds, options, limits);
96
+ }
97
+ if (this.hasCategory(options) && options.sort === 'most-relevant') {
98
+ const { mostRelevant } = options.category;
99
+ console.log('mostRelevant', mostRelevant);
100
+ const productsIds = await this.productRepository
101
+ .find({
102
+ filters: {
103
+ ...(await this.buildMainFilter(options)),
104
+ },
105
+ })
106
+ .then((products) => products.data.map((product) => product.id));
107
+ return this.findCatalogAndSortByMostRevelant(mostRelevant, productsIds, options, limits);
108
+ }
109
+ const repoParams = {
110
+ filters: {
111
+ ...(await this.buildMainFilter(options)),
112
+ ...this.buildFilterQuery(options?.filters || {}),
113
+ },
114
+ ...(options?.sort ? { orderBy: this.buildSortQuery(options?.sort) } : {}),
115
+ limits,
116
+ options: {
117
+ minimal: ['price'],
118
+ maximum: ['price'],
119
+ ...(!this.hasCategory(options) ? { distinct: ['brand'] } : {}),
120
+ },
121
+ };
122
+ if (['biggest-price', 'lowest-price', 'biggest-discount', 'best-rating'].includes(options.sort))
123
+ return this.productRepository.findCatalog(repoParams);
124
+ return this.productRepository.findCatalog(repoParams, options?.mainGender || this.shop === Shops.MENSMARKET ? 'male' : 'female');
125
+ }
126
+ async buildMainFilter({ category, profile, term, }) {
127
+ if (category)
128
+ return this.categoryStructureAdapter.buildProductFilterByCategory(category);
129
+ if (profile)
130
+ return { tags: { operator: Where.LIKE, value: profile } };
131
+ if (term)
132
+ return this.productIndex
133
+ .search(term, 999, this.shop)
134
+ .then((data) => ({ id: { operator: Where.IN, value: data.hits.map(({ _source }) => _source.id) } }));
135
+ }
136
+ async findCatalogAndSortByMostRevelant(mostRelevants, productIds, options, limits) {
137
+ const { offset } = limits;
138
+ if (offset === 0) {
139
+ limits.limit -= mostRelevants.length;
140
+ }
141
+ if (offset > 0) {
142
+ limits.offset -= mostRelevants.length;
143
+ }
144
+ const mostRelevantProductsIds = [...new Set(...mostRelevants, ...productIds)];
145
+ const totalResult = await this.productRepository.findCatalog({
146
+ fields: ['id', 'stock'],
147
+ filters: {
148
+ id: { operator: Where.IN, value: mostRelevantProductsIds },
149
+ ...this.buildFilterQuery(options?.filters || {}),
150
+ },
151
+ options: {
152
+ minimal: ['price'],
153
+ maximum: ['price'],
154
+ distinct: ['brand'],
155
+ },
156
+ }, options?.mainGender || this.shop === Shops.MENSMARKET ? 'male' : 'female');
157
+ const stockData = totalResult.data.filter((product) => product.stock.quantity > 0);
158
+ const stockOut = totalResult.data.filter((product) => product.stock.quantity <= 0);
159
+ const productIdsStock = productIds.filter((product) => stockData.some((result) => result.id == product));
160
+ const productIdsStockOut = productIds.filter((product) => stockOut.some((result) => result.id == product));
161
+ const limitedProductId = productIdsStock
162
+ .concat(productIdsStockOut)
163
+ .slice(limits.offset, limits.offset + limits.limit);
164
+ const orderedId = productIds.filter((product) => limitedProductId.includes(product));
165
+ const productResult = await this.productRepository.findCatalog({
166
+ filters: {
167
+ id: { operator: Where.IN, value: orderedId },
168
+ },
169
+ });
170
+ return {
171
+ data: limitedProductId.map((id) => productResult.data.find((product) => product.id === id)).filter(Boolean),
172
+ count: totalResult.count,
173
+ maximum: totalResult.maximum,
174
+ minimal: totalResult.minimal,
175
+ distinct: totalResult.distinct,
176
+ };
177
+ }
178
+ async findCatalogAndSortByMostRevelantByTerm(productIds, options, limits) {
179
+ const totalResult = await this.productRepository.findCatalog({
180
+ fields: ['id', 'stock'],
181
+ filters: {
182
+ id: { operator: Where.IN, value: productIds },
183
+ ...this.buildFilterQuery(options?.filters || {}),
184
+ },
185
+ options: {
186
+ minimal: ['price'],
187
+ maximum: ['price'],
188
+ distinct: ['brand'],
189
+ },
190
+ }, options?.mainGender || this.shop === Shops.MENSMARKET ? 'male' : 'female');
191
+ const stockData = totalResult.data.filter((product) => product.stock.quantity > 0);
192
+ const stockOut = totalResult.data.filter((product) => product.stock.quantity <= 0);
193
+ const productIdsStock = productIds.filter((product) => stockData.some((result) => result.id == product));
194
+ const productIdsStockOut = productIds.filter((product) => stockOut.some((result) => result.id == product));
195
+ const limitedProductId = productIdsStock
196
+ .concat(productIdsStockOut)
197
+ .slice(limits.offset, limits.offset + limits.limit);
198
+ const orderedId = productIds.filter((product) => limitedProductId.includes(product));
199
+ const productResult = await this.productRepository.findCatalog({
200
+ filters: {
201
+ id: { operator: Where.IN, value: orderedId },
202
+ },
203
+ });
204
+ return {
205
+ data: limitedProductId.map((id) => productResult.data.find((product) => product.id === id)).filter(Boolean),
206
+ count: totalResult.count,
207
+ maximum: totalResult.maximum,
208
+ minimal: totalResult.minimal,
209
+ distinct: totalResult.distinct,
210
+ };
211
+ }
212
+ async findCatalogIdsByElasticSearch(term) {
213
+ if (this.productsByTerm[term])
214
+ return this.productsByTerm[term];
215
+ return (this.productsByTerm[term] = await this.productIndex
216
+ .search(term, 999, this.shop)
217
+ .then(({ hits: products }) => {
218
+ const withStock = products.filter(({ _source }) => _source.stock.quantity > 0);
219
+ const withOutStock = products.filter(({ _source }) => _source.stock.quantity <= 0);
220
+ const sorted = [...withStock, ...withOutStock];
221
+ return [...new Set(sorted.map(({ _source }) => _source.id))];
222
+ }));
223
+ }
224
+ }
225
+ CatalogService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.0", ngImport: i0, type: CatalogService, deps: [{ token: 'ProductRepository' }, { token: 'ProductStockNotificationRepository' }, { token: 'CategoryRepository' }, { token: CATEGORY_STRUCTURE }, { token: DEFAULT_SHOP }, { token: i1.ProductsIndex }], target: i0.ɵɵFactoryTarget.Injectable });
226
+ CatalogService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.1.0", ngImport: i0, type: CatalogService });
227
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.0", ngImport: i0, type: CatalogService, decorators: [{
228
+ type: Injectable
229
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
230
+ type: Inject,
231
+ args: ['ProductRepository']
232
+ }] }, { type: undefined, decorators: [{
233
+ type: Inject,
234
+ args: ['ProductStockNotificationRepository']
235
+ }] }, { type: undefined, decorators: [{
236
+ type: Inject,
237
+ args: ['CategoryRepository']
238
+ }] }, { type: undefined, decorators: [{
239
+ type: Inject,
240
+ args: [CATEGORY_STRUCTURE]
241
+ }] }, { type: i1.Shops, decorators: [{
242
+ type: Inject,
243
+ args: [DEFAULT_SHOP]
244
+ }] }, { type: i1.ProductsIndex }]; } });
245
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2F0YWxvZy5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvY29ubmVjdC1hbmd1bGFyL3NyYy9zZXJ2aWNlcy9jYXRhbG9nL2NhdGFsb2cuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQTtBQUNsRCxPQUFPLEVBSUwsb0JBQW9CLEVBSXBCLGFBQWEsRUFLYix3QkFBd0IsRUFDeEIsR0FBRyxFQUNILEtBQUssRUFDTCxLQUFLLEdBQ04sTUFBTSxtQkFBbUIsQ0FBQTtBQUMxQixPQUFPLEVBQUUsa0JBQWtCLEVBQUUsWUFBWSxFQUFFLE1BQU0sY0FBYyxDQUFBOzs7QUFzRC9ELE1BQU0sT0FBTyxjQUFjO0lBR3pCLFlBQ2dELGlCQUFvQyxFQUVqRSxrQ0FBc0UsRUFDeEMsa0JBQXNDLEVBQ3hDLHdCQUFrRCxFQUN4RCxJQUFXLEVBQ2pDLFlBQTJCO1FBTkUsc0JBQWlCLEdBQWpCLGlCQUFpQixDQUFtQjtRQUVqRSx1Q0FBa0MsR0FBbEMsa0NBQWtDLENBQW9DO1FBQ3hDLHVCQUFrQixHQUFsQixrQkFBa0IsQ0FBb0I7UUFDeEMsNkJBQXdCLEdBQXhCLHdCQUF3QixDQUEwQjtRQUN4RCxTQUFJLEdBQUosSUFBSSxDQUFPO1FBQ2pDLGlCQUFZLEdBQVosWUFBWSxDQUFlO1FBVHRDLG1CQUFjLEdBQTZCLEVBQUUsQ0FBQTtRQXlPN0MscUJBQWdCLEdBQUcsQ0FBQyxFQUMxQixZQUFZLEVBQ1osTUFBTSxFQUNOLE1BQU0sRUFDTixNQUFNLEVBQ04sSUFBSSxFQUNKLElBQUksRUFDSixhQUFhLEdBQ1EsRUFBbUMsRUFBRTtZQUMxRCxNQUFNLE9BQU8sR0FBRyxFQUFxQyxDQUFBO1lBRXJELElBQUksWUFBWSxFQUFFLE1BQU07Z0JBQ3RCLEdBQUcsQ0FBQyxPQUFPLEVBQUUsb0NBQW9DLEVBQUUsRUFBRSxRQUFRLEVBQUUsS0FBSyxDQUFDLEVBQUUsRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLENBQUMsQ0FBQTtZQUNqRyxJQUFJLE1BQU0sRUFBRSxNQUFNO2dCQUFFLE9BQU8sQ0FBQyxLQUFLLEdBQUcsRUFBRSxRQUFRLEVBQUUsS0FBSyxDQUFDLEVBQUUsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLENBQUE7WUFDekUsSUFBSSxNQUFNLEVBQUUsTUFBTTtnQkFBRSxPQUFPLENBQUMsTUFBTSxHQUFHLEVBQUUsUUFBUSxFQUFFLEtBQUssQ0FBQyxFQUFFLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxDQUFBO1lBQzFFLElBQUksTUFBTSxFQUFFLEdBQUcsSUFBSSxNQUFNLEVBQUUsR0FBRztnQkFDNUIsR0FBRyxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDLENBQUMsYUFBYSxFQUFFO29CQUM3RSxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLFFBQVEsRUFBRSxLQUFLLENBQUMsR0FBRyxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztvQkFDL0UsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxRQUFRLEVBQUUsS0FBSyxDQUFDLEdBQUcsRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7aUJBQy9FLENBQUMsQ0FBQTtZQUNKLElBQUksSUFBSTtnQkFBRSxPQUFPLENBQUMsSUFBSSxHQUFHLEVBQUUsUUFBUSxFQUFFLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxDQUFBO1lBQzdELElBQUksSUFBSSxFQUFFLE1BQU07Z0JBQUUsT0FBTyxDQUFDLElBQUksR0FBRyxFQUFFLFFBQVEsRUFBRSxLQUFLLENBQUMsSUFBSSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsQ0FBQTtZQUN0RSxJQUFJLGFBQWEsRUFBRSxNQUFNO2dCQUFFLE9BQU8sQ0FBQyxPQUFPLEdBQUcsRUFBRSxRQUFRLEVBQUUsS0FBSyxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsYUFBYSxFQUFFLENBQUE7WUFFM0YsT0FBTyxPQUFPLENBQUE7UUFDaEIsQ0FBQyxDQUFBO1FBRU8sbUJBQWMsR0FBRyxDQUFDLElBQWlCLEVBQThCLEVBQUU7WUFDekUsSUFBSSxDQUFDLElBQUksSUFBSSxJQUFJLEtBQUssZUFBZTtnQkFBRSxPQUFPLEVBQUUsQ0FBQTtZQUVoRCxJQUFJLElBQUksS0FBSyxjQUFjO2dCQUN6QixPQUFPO29CQUNMLGFBQWEsRUFBRSxNQUFNO29CQUNyQixJQUFJLEVBQUUsTUFBTTtvQkFDWixLQUFLLEVBQUUsTUFBTTtvQkFDYixJQUFJLEVBQUUsS0FBSztpQkFDWixDQUFBO1lBQ0gsSUFBSSxJQUFJLEtBQUssZUFBZTtnQkFBRSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLGFBQWEsRUFBRSxNQUFNLEVBQVMsQ0FBQTtZQUM1RyxJQUFJLElBQUksS0FBSyxjQUFjO2dCQUFFLE9BQU8sRUFBRSxlQUFlLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsYUFBYSxFQUFFLE1BQU0sRUFBUyxDQUFBO1lBQzFHLElBQUksSUFBSSxLQUFLLGFBQWE7Z0JBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsYUFBYSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsQ0FBQTtZQUN0RyxJQUFJLElBQUksS0FBSyxNQUFNO2dCQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLENBQUE7WUFDakQsSUFBSSxJQUFJLEtBQUssa0JBQWtCO2dCQUM3QixPQUFPLEVBQUUsNEJBQTRCLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsYUFBYSxFQUFFLE1BQU0sRUFBUyxDQUFBO1FBQy9GLENBQUMsQ0FBQTtRQUVPLG9CQUFlLEdBQUcsQ0FBQyxPQUE0QyxFQUF1QyxFQUFFO1lBQzlHLE1BQU0sS0FBSyxHQUFHLE9BQU8sRUFBRSxPQUFPLElBQUksRUFBRSxDQUFBO1lBRXBDLE9BQU87Z0JBQ0wsS0FBSztnQkFDTCxNQUFNLEVBQUUsQ0FBQyxDQUFDLE9BQU8sRUFBRSxJQUFJLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsS0FBSzthQUMzQyxDQUFBO1FBQ0gsQ0FBQyxDQUFBO1FBRU8sZUFBVSxHQUFHLENBQ25CLE9BQStCLEVBSS9CLEVBQUUsQ0FBQyxTQUFTLElBQUksT0FBTyxDQUFBO1FBRWpCLFlBQU8sR0FBRyxDQUNoQixPQUErQixFQUkvQixFQUFFLENBQUMsTUFBTSxJQUFJLE9BQU8sQ0FBQTtRQUVkLGdCQUFXLEdBQUcsQ0FDcEIsT0FBK0IsRUFJL0IsRUFBRSxDQUFDLFVBQVUsSUFBSSxPQUFPLENBQUE7SUF4U3ZCLENBQUM7SUFFSixLQUFLLENBQUMsYUFBYSxDQUFDLE9BQStCO1FBQ2pELE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsT0FBTyxDQUFDLENBQUE7UUFFNUMsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxJQUFJLE9BQU8sQ0FBQyxPQUFPLEVBQUUsYUFBYTtZQUM1RCxNQUFNLElBQUksb0JBQW9CLENBQUMsd0RBQXdELENBQUMsQ0FBQTtRQUMxRixJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLElBQUksT0FBTyxDQUFDLE9BQU8sRUFBRSxJQUFJO1lBQ25ELE1BQU0sSUFBSSxvQkFBb0IsQ0FBQywrQ0FBK0MsQ0FBQyxDQUFBO1FBQ2pGLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxPQUFPLENBQUMsT0FBTyxFQUFFLGFBQWE7WUFDekQsTUFBTSxJQUFJLG9CQUFvQixDQUFDLHFEQUFxRCxDQUFDLENBQUE7UUFFdkYsT0FBTyxNQUFNLElBQUksQ0FBQyxXQUFXLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUMzRyxRQUFRLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsd0JBQXdCLENBQUMsa0JBQWtCLENBQUMsT0FBTyxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUU7WUFDdEcsS0FBSyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUM7WUFDdEMsTUFBTSxFQUFFO2dCQUNOLEtBQUssRUFBRSxFQUFFLEdBQUcsRUFBRSxDQUFDLE9BQU8sRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxPQUFPLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUU7Z0JBQzNGLGVBQWUsRUFBRTtvQkFDZixHQUFHLEVBQUUsQ0FBQyxPQUFPLEVBQUUsS0FBSyxFQUFFLGVBQWUsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDO29CQUNqRCxHQUFHLEVBQUUsQ0FBQyxPQUFPLEVBQUUsS0FBSyxFQUFFLGVBQWUsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDO2lCQUNsRDthQUNGO1lBQ0QsTUFBTSxFQUFFLFFBQVEsRUFBRSxLQUFLO1NBQ3hCLENBQUMsQ0FBQyxDQUFBO0lBQ0wsQ0FBQztJQUVELEtBQUssQ0FBQyw4QkFBOEIsQ0FBQyxJQUFXLEVBQUUsU0FBaUIsRUFBRSxJQUFZLEVBQUUsS0FBYTtRQUM5RixPQUFPLElBQUksQ0FBQyxrQ0FBa0MsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQTtJQUMvRixDQUFDO0lBRU8sS0FBSyxDQUFDLFdBQVcsQ0FDdkIsT0FBK0IsRUFDL0IsTUFHQztRQUVELElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxPQUFPLENBQUMsSUFBSSxLQUFLLGVBQWUsRUFBRTtZQUM3RCxNQUFNLFdBQVcsR0FBRyxNQUFNLElBQUksQ0FBQyw2QkFBNkIsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUE7WUFFMUUsT0FBTyxJQUFJLENBQUMsc0NBQXNDLENBQUMsV0FBVyxFQUFFLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQTtTQUNqRjtRQUVELElBQUksSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsSUFBSSxPQUFPLENBQUMsSUFBSSxLQUFLLGVBQWUsRUFBRTtZQUNqRSxNQUFNLEVBQUUsWUFBWSxFQUFFLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQTtZQUN6QyxPQUFPLENBQUMsR0FBRyxDQUFDLGNBQWMsRUFBRSxZQUFZLENBQUMsQ0FBQTtZQUN6QyxNQUFNLFdBQVcsR0FBRyxNQUFNLElBQUksQ0FBQyxpQkFBaUI7aUJBQzdDLElBQUksQ0FBQztnQkFDSixPQUFPLEVBQUU7b0JBQ1AsR0FBRyxDQUFDLE1BQU0sSUFBSSxDQUFDLGVBQWUsQ0FBQyxPQUFPLENBQUMsQ0FBQztpQkFDekM7YUFDRixDQUFDO2lCQUNELElBQUksQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFBO1lBRWpFLE9BQU8sSUFBSSxDQUFDLGdDQUFnQyxDQUFDLFlBQVksRUFBRSxXQUFXLEVBQUUsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFBO1NBQ3pGO1FBRUQsTUFBTSxVQUFVLEdBQWtDO1lBQ2hELE9BQU8sRUFBRTtnQkFDUCxHQUFHLENBQUMsTUFBTSxJQUFJLENBQUMsZUFBZSxDQUFDLE9BQU8sQ0FBQyxDQUFDO2dCQUN4QyxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsT0FBTyxJQUFJLEVBQUUsQ0FBQzthQUNqRDtZQUNELEdBQUcsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLE9BQU8sRUFBRSxJQUFJLENBQUMsY0FBYyxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDekUsTUFBTTtZQUNOLE9BQU8sRUFBRTtnQkFDUCxPQUFPLEVBQUUsQ0FBQyxPQUFPLENBQUM7Z0JBQ2xCLE9BQU8sRUFBRSxDQUFDLE9BQU8sQ0FBQztnQkFDbEIsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxRQUFRLEVBQUUsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7YUFDL0Q7U0FDRixDQUFBO1FBRUQsSUFBSSxDQUFDLGVBQWUsRUFBRSxjQUFjLEVBQUUsa0JBQWtCLEVBQUUsYUFBYSxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUM7WUFDN0YsT0FBTyxJQUFJLENBQUMsaUJBQWlCLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FBQyxDQUFBO1FBRXZELE9BQU8sSUFBSSxDQUFDLGlCQUFpQixDQUFDLFdBQVcsQ0FDdkMsVUFBVSxFQUNWLE9BQU8sRUFBRSxVQUFVLElBQUksSUFBSSxDQUFDLElBQUksS0FBSyxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FDMUUsQ0FBQTtJQUNILENBQUM7SUFFTyxLQUFLLENBQUMsZUFBZSxDQUFDLEVBQzVCLFFBQVEsRUFDUixPQUFPLEVBQ1AsSUFBSSxHQUN1QjtRQUMzQixJQUFJLFFBQVE7WUFBRSxPQUFPLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyw0QkFBNEIsQ0FBQyxRQUFRLENBQUMsQ0FBQTtRQUN6RixJQUFJLE9BQU87WUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLEVBQUUsUUFBUSxFQUFFLEtBQUssQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFLENBQUE7UUFDdEUsSUFBSSxJQUFJO1lBQ04sT0FBTyxJQUFJLENBQUMsWUFBWTtpQkFDckIsTUFBTSxDQUFDLElBQUksRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQztpQkFDNUIsSUFBSSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsUUFBUSxFQUFFLEtBQUssQ0FBQyxFQUFFLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxPQUFPLEVBQUUsRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUE7SUFDMUcsQ0FBQztJQUVPLEtBQUssQ0FBQyxnQ0FBZ0MsQ0FDNUMsYUFBdUIsRUFDdkIsVUFBb0IsRUFDcEIsT0FHQyxFQUNELE1BR0M7UUFFRCxNQUFNLEVBQUUsTUFBTSxFQUFFLEdBQUcsTUFBTSxDQUFBO1FBRXpCLElBQUksTUFBTSxLQUFLLENBQUMsRUFBRTtZQUNoQixNQUFNLENBQUMsS0FBSyxJQUFJLGFBQWEsQ0FBQyxNQUFNLENBQUE7U0FDckM7UUFFRCxJQUFJLE1BQU0sR0FBRyxDQUFDLEVBQUU7WUFDZCxNQUFNLENBQUMsTUFBTSxJQUFJLGFBQWEsQ0FBQyxNQUFNLENBQUE7U0FDdEM7UUFFRCxNQUFNLHVCQUF1QixHQUFHLENBQUMsR0FBRyxJQUFJLEdBQUcsQ0FBQyxHQUFHLGFBQWEsRUFBRSxHQUFHLFVBQVUsQ0FBQyxDQUFDLENBQUE7UUFDN0UsTUFBTSxXQUFXLEdBQUcsTUFBTSxJQUFJLENBQUMsaUJBQWlCLENBQUMsV0FBVyxDQUMxRDtZQUNFLE1BQU0sRUFBRSxDQUFDLElBQUksRUFBRSxPQUFPLENBQUM7WUFDdkIsT0FBTyxFQUFFO2dCQUNQLEVBQUUsRUFBRSxFQUFFLFFBQVEsRUFBRSxLQUFLLENBQUMsRUFBRSxFQUFFLEtBQUssRUFBRSx1QkFBdUIsRUFBRTtnQkFDMUQsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLE9BQU8sSUFBSSxFQUFFLENBQUM7YUFDakQ7WUFDRCxPQUFPLEVBQUU7Z0JBQ1AsT0FBTyxFQUFFLENBQUMsT0FBTyxDQUFDO2dCQUNsQixPQUFPLEVBQUUsQ0FBQyxPQUFPLENBQUM7Z0JBQ2xCLFFBQVEsRUFBRSxDQUFDLE9BQU8sQ0FBQzthQUNwQjtTQUNGLEVBQ0QsT0FBTyxFQUFFLFVBQVUsSUFBSSxJQUFJLENBQUMsSUFBSSxLQUFLLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUMxRSxDQUFBO1FBRUQsTUFBTSxTQUFTLEdBQUcsV0FBVyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsUUFBUSxHQUFHLENBQUMsQ0FBQyxDQUFBO1FBQ2xGLE1BQU0sUUFBUSxHQUFHLFdBQVcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLFFBQVEsSUFBSSxDQUFDLENBQUMsQ0FBQTtRQUNsRixNQUFNLGVBQWUsR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLE9BQU8sQ0FBQyxDQUFDLENBQUE7UUFDeEcsTUFBTSxrQkFBa0IsR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLE9BQU8sQ0FBQyxDQUFDLENBQUE7UUFFMUcsTUFBTSxnQkFBZ0IsR0FBRyxlQUFlO2FBQ3JDLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQzthQUMxQixLQUFLLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQTtRQUVyRCxNQUFNLFNBQVMsR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQTtRQUNwRixNQUFNLGFBQWEsR0FBRyxNQUFNLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLENBQUM7WUFDN0QsT0FBTyxFQUFFO2dCQUNQLEVBQUUsRUFBRSxFQUFFLFFBQVEsRUFBRSxLQUFLLENBQUMsRUFBRSxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUU7YUFDN0M7U0FDRixDQUFDLENBQUE7UUFFRixPQUFPO1lBQ0wsSUFBSSxFQUFFLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDO1lBQzNHLEtBQUssRUFBRSxXQUFXLENBQUMsS0FBSztZQUN4QixPQUFPLEVBQUUsV0FBVyxDQUFDLE9BQU87WUFDNUIsT0FBTyxFQUFFLFdBQVcsQ0FBQyxPQUFPO1lBQzVCLFFBQVEsRUFBRSxXQUFXLENBQUMsUUFBUTtTQUMvQixDQUFBO0lBQ0gsQ0FBQztJQUVPLEtBQUssQ0FBQyxzQ0FBc0MsQ0FDbEQsVUFBb0IsRUFDcEIsT0FHQyxFQUNELE1BR0M7UUFFRCxNQUFNLFdBQVcsR0FBRyxNQUFNLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLENBQzFEO1lBQ0UsTUFBTSxFQUFFLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQztZQUN2QixPQUFPLEVBQUU7Z0JBQ1AsRUFBRSxFQUFFLEVBQUUsUUFBUSxFQUFFLEtBQUssQ0FBQyxFQUFFLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRTtnQkFDN0MsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLE9BQU8sSUFBSSxFQUFFLENBQUM7YUFDakQ7WUFDRCxPQUFPLEVBQUU7Z0JBQ1AsT0FBTyxFQUFFLENBQUMsT0FBTyxDQUFDO2dCQUNsQixPQUFPLEVBQUUsQ0FBQyxPQUFPLENBQUM7Z0JBQ2xCLFFBQVEsRUFBRSxDQUFDLE9BQU8sQ0FBQzthQUNwQjtTQUNGLEVBQ0QsT0FBTyxFQUFFLFVBQVUsSUFBSSxJQUFJLENBQUMsSUFBSSxLQUFLLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUMxRSxDQUFBO1FBRUQsTUFBTSxTQUFTLEdBQUcsV0FBVyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsUUFBUSxHQUFHLENBQUMsQ0FBQyxDQUFBO1FBQ2xGLE1BQU0sUUFBUSxHQUFHLFdBQVcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLFFBQVEsSUFBSSxDQUFDLENBQUMsQ0FBQTtRQUNsRixNQUFNLGVBQWUsR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLE9BQU8sQ0FBQyxDQUFDLENBQUE7UUFDeEcsTUFBTSxrQkFBa0IsR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLE9BQU8sQ0FBQyxDQUFDLENBQUE7UUFFMUcsTUFBTSxnQkFBZ0IsR0FBRyxlQUFlO2FBQ3JDLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQzthQUMxQixLQUFLLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQTtRQUVyRCxNQUFNLFNBQVMsR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQTtRQUNwRixNQUFNLGFBQWEsR0FBRyxNQUFNLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLENBQUM7WUFDN0QsT0FBTyxFQUFFO2dCQUNQLEVBQUUsRUFBRSxFQUFFLFFBQVEsRUFBRSxLQUFLLENBQUMsRUFBRSxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUU7YUFDN0M7U0FDRixDQUFDLENBQUE7UUFFRixPQUFPO1lBQ0wsSUFBSSxFQUFFLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDO1lBQzNHLEtBQUssRUFBRSxXQUFXLENBQUMsS0FBSztZQUN4QixPQUFPLEVBQUUsV0FBVyxDQUFDLE9BQU87WUFDNUIsT0FBTyxFQUFFLFdBQVcsQ0FBQyxPQUFPO1lBQzVCLFFBQVEsRUFBRSxXQUFXLENBQUMsUUFBUTtTQUMvQixDQUFBO0lBQ0gsQ0FBQztJQUVPLEtBQUssQ0FBQyw2QkFBNkIsQ0FBQyxJQUFZO1FBQ3RELElBQUksSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUM7WUFBRSxPQUFPLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLENBQUE7UUFFL0QsT0FBTyxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLEdBQUcsTUFBTSxJQUFJLENBQUMsWUFBWTthQUN4RCxNQUFNLENBQUMsSUFBSSxFQUFFLEdBQUcsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDO2FBQzVCLElBQUksQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxFQUFFLEVBQUU7WUFDM0IsTUFBTSxTQUFTLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsUUFBUSxHQUFHLENBQUMsQ0FBQyxDQUFBO1lBQzlFLE1BQU0sWUFBWSxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLE9BQU8sRUFBRSxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLFFBQVEsSUFBSSxDQUFDLENBQUMsQ0FBQTtZQUNsRixNQUFNLE1BQU0sR0FBRyxDQUFDLEdBQUcsU0FBUyxFQUFFLEdBQUcsWUFBWSxDQUFDLENBQUE7WUFFOUMsT0FBTyxDQUFDLEdBQUcsSUFBSSxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUE7UUFDOUQsQ0FBQyxDQUFDLENBQUMsQ0FBQTtJQUNQLENBQUM7OzJHQXhPVSxjQUFjLGtCQUlmLG1CQUFtQixhQUNuQixvQ0FBb0MsYUFFcEMsb0JBQW9CLGFBQ3BCLGtCQUFrQixhQUNsQixZQUFZOytHQVRYLGNBQWM7MkZBQWQsY0FBYztrQkFEMUIsVUFBVTs7MEJBS04sTUFBTTsyQkFBQyxtQkFBbUI7OzBCQUMxQixNQUFNOzJCQUFDLG9DQUFvQzs7MEJBRTNDLE1BQU07MkJBQUMsb0JBQW9COzswQkFDM0IsTUFBTTsyQkFBQyxrQkFBa0I7OzBCQUN6QixNQUFNOzJCQUFDLFlBQVkiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3QsIEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJ1xyXG5pbXBvcnQge1xyXG4gIENhdGVnb3J5LFxyXG4gIENhdGVnb3J5UmVwb3NpdG9yeSxcclxuICBGaW5kUmVwb3NpdG9yeVBhcmFtcyxcclxuICBJbnZhbGlkQXJndW1lbnRFcnJvcixcclxuICBQcm9kdWN0LFxyXG4gIFByb2R1Y3RHZW5kZXIsXHJcbiAgUHJvZHVjdFJlcG9zaXRvcnksXHJcbiAgUHJvZHVjdHNJbmRleCxcclxuICBQcm9kdWN0U3RvY2tOb3RpZmljYXRpb25SZXBvc2l0b3J5LFxyXG4gIFJlcG9zaXRvcnlGaW5kRmllbHRlcnMsXHJcbiAgUmVwb3NpdG9yeUZpbmRSZXN1bHQsXHJcbiAgUmVwb3NpdG9yeU9yZGVyQnksXHJcbiAgUm91bmRQcm9kdWN0UHJpY2VzSGVscGVyLFxyXG4gIHNldCxcclxuICBTaG9wcyxcclxuICBXaGVyZSxcclxufSBmcm9tICdAaW5mcmFiNGEvY29ubmVjdCdcclxuaW1wb3J0IHsgQ0FURUdPUllfU1RSVUNUVVJFLCBERUZBVUxUX1NIT1AgfSBmcm9tICcuLi8uLi9jb25zdHMnXHJcbmltcG9ydCB7IENhdGVnb3J5U3RydWN0dXJlQWRhcHRlciB9IGZyb20gJy4vYWRhcHRlcnMnXHJcbmltcG9ydCB7IFByb2R1Y3RTb3J0IH0gZnJvbSAnLi90eXBlcy9wcm9kdWN0LXNvcnQudHlwZSdcclxuXHJcbnR5cGUgRmV0Y2hQcm9kdWN0c0ZpbHRlcnMgPSB7XHJcbiAgY2x1YkRpc2NvdW50PzogbnVtYmVyW11cclxuICBicmFuZHM/OiBzdHJpbmdbXVxyXG4gIHByaWNlcz86IHsgbWluPzogbnVtYmVyOyBtYXg/OiBudW1iZXI7IHN1YnNjcmliZXJQcmljZT86IGJvb2xlYW4gfVxyXG4gIGdlbmRlcj86IFByb2R1Y3RHZW5kZXJbXVxyXG4gIHJhdGU/OiBudW1iZXJcclxuICBjdXN0b21PcHRpb25zPzogc3RyaW5nW11cclxuICB0YWdzPzogc3RyaW5nW11cclxufVxyXG5cclxudHlwZSBGZXRjaFByb2R1Y3RzT3B0aW9ucyA9IHtcclxuICBwYWdlPzogbnVtYmVyXHJcbiAgcGVyUGFnZT86IG51bWJlclxyXG4gIHNvcnQ/OiBQcm9kdWN0U29ydFxyXG4gIG1haW5HZW5kZXI/OiBQcm9kdWN0R2VuZGVyXHJcbn1cclxuXHJcbnR5cGUgRmV0Y2hQcm9kdWN0c01haW5QYXJhbXM8VCBleHRlbmRzIENhdGVnb3J5PiA9IHtcclxuICBjYXRlZ29yeT86IFRcclxuICBwcm9maWxlPzogc3RyaW5nW11cclxuICB0ZXJtPzogc3RyaW5nXHJcbn1cclxuXHJcbnR5cGUgRmV0Y2hQcm9kdWN0c1BhcmFtczxUIGV4dGVuZHMgQ2F0ZWdvcnk+ID0gRmV0Y2hQcm9kdWN0c09wdGlvbnMgJlxyXG4gIChcclxuICAgIHwge1xyXG4gICAgICAgIGNhdGVnb3J5OiBGZXRjaFByb2R1Y3RzTWFpblBhcmFtczxUPlsnY2F0ZWdvcnknXVxyXG4gICAgICAgIGZpbHRlcnM/OiBGZXRjaFByb2R1Y3RzRmlsdGVycyAmIHsgY3VzdG9tT3B0aW9ucz86IG5ldmVyIH1cclxuICAgICAgfVxyXG4gICAgfCB7XHJcbiAgICAgICAgcHJvZmlsZTogRmV0Y2hQcm9kdWN0c01haW5QYXJhbXM8VD5bJ3Byb2ZpbGUnXVxyXG4gICAgICAgIGZpbHRlcnM/OiBGZXRjaFByb2R1Y3RzRmlsdGVycyAmIHsgY3VzdG9tT3B0aW9ucz86IG5ldmVyOyB0YWdzPzogbmV2ZXIgfVxyXG4gICAgICB9XHJcbiAgICB8IHtcclxuICAgICAgICB0ZXJtOiBGZXRjaFByb2R1Y3RzTWFpblBhcmFtczxUPlsndGVybSddXHJcbiAgICAgICAgZmlsdGVycz86IEZldGNoUHJvZHVjdHNGaWx0ZXJzICYgeyBjdXN0b21PcHRpb25zPzogbmV2ZXIgfVxyXG4gICAgICB9XHJcbiAgKVxyXG5cclxudHlwZSBGZXRjaFByb2R1Y3RzUmVzcG9uc2UgPSB7XHJcbiAgcHJvZHVjdHM6IHsgZGF0YTogUHJvZHVjdFtdOyB0b3RhbDogbnVtYmVyIH1cclxuICBwYWdlczogbnVtYmVyXHJcbiAgcHJpY2VzOiB7XHJcbiAgICBwcmljZTogeyBtaW46IG51bWJlcjsgbWF4OiBudW1iZXIgfVxyXG4gICAgc3Vic2NyaWJlclByaWNlOiB7IG1pbjogbnVtYmVyOyBtYXg6IG51bWJlciB9XHJcbiAgfVxyXG4gIGJyYW5kcz86IHN0cmluZ1tdXHJcbn1cclxuXHJcbkBJbmplY3RhYmxlKClcclxuZXhwb3J0IGNsYXNzIENhdGFsb2dTZXJ2aWNlPFQgZXh0ZW5kcyBDYXRlZ29yeSA9IENhdGVnb3J5PiB7XHJcbiAgcHJpdmF0ZSBwcm9kdWN0c0J5VGVybTogUmVjb3JkPHN0cmluZywgc3RyaW5nW10+ID0ge31cclxuXHJcbiAgY29uc3RydWN0b3IoXHJcbiAgICBASW5qZWN0KCdQcm9kdWN0UmVwb3NpdG9yeScpIHByaXZhdGUgcmVhZG9ubHkgcHJvZHVjdFJlcG9zaXRvcnk6IFByb2R1Y3RSZXBvc2l0b3J5LFxyXG4gICAgQEluamVjdCgnUHJvZHVjdFN0b2NrTm90aWZpY2F0aW9uUmVwb3NpdG9yeScpXHJcbiAgICBwcml2YXRlIHJlYWRvbmx5IHByb2R1Y3RTdG9ja05vdGlmaWNhdGlvblJlcG9zaXRvcnk6IFByb2R1Y3RTdG9ja05vdGlmaWNhdGlvblJlcG9zaXRvcnksXHJcbiAgICBASW5qZWN0KCdDYXRlZ29yeVJlcG9zaXRvcnknKSBwcml2YXRlIHJlYWRvbmx5IGNhdGVnb3J5UmVwb3NpdG9yeTogQ2F0ZWdvcnlSZXBvc2l0b3J5LFxyXG4gICAgQEluamVjdChDQVRFR09SWV9TVFJVQ1RVUkUpIHByaXZhdGUgcmVhZG9ubHkgY2F0ZWdvcnlTdHJ1Y3R1cmVBZGFwdGVyOiBDYXRlZ29yeVN0cnVjdHVyZUFkYXB0ZXIsXHJcbiAgICBASW5qZWN0KERFRkFVTFRfU0hPUCkgcHJpdmF0ZSByZWFkb25seSBzaG9wOiBTaG9wcyxcclxuICAgIHByaXZhdGUgcmVhZG9ubHkgcHJvZHVjdEluZGV4OiBQcm9kdWN0c0luZGV4LFxyXG4gICkge31cclxuXHJcbiAgYXN5bmMgZmV0Y2hQcm9kdWN0cyhvcHRpb25zOiBGZXRjaFByb2R1Y3RzUGFyYW1zPFQ+KTogUHJvbWlzZTxGZXRjaFByb2R1Y3RzUmVzcG9uc2U+IHtcclxuICAgIGNvbnN0IGxpbWl0cyA9IHRoaXMuYnVpbGRMaW1pdFF1ZXJ5KG9wdGlvbnMpXHJcblxyXG4gICAgaWYgKHRoaXMuaGFzUHJvZmlsZShvcHRpb25zKSAmJiBvcHRpb25zLmZpbHRlcnM/LmN1c3RvbU9wdGlvbnMpXHJcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkQXJndW1lbnRFcnJvcihgSXQgY291bGRuJ3QgZmlsbGVkIGN1c3RvbU9wdGlvbnMgd2hlbiBwcm9maWxlIGlzIGdpdmVuYClcclxuICAgIGlmICh0aGlzLmhhc1Byb2ZpbGUob3B0aW9ucykgJiYgb3B0aW9ucy5maWx0ZXJzPy50YWdzKVxyXG4gICAgICB0aHJvdyBuZXcgSW52YWxpZEFyZ3VtZW50RXJyb3IoYEl0IGNvdWxkbid0IGZpbGxlZCB0YWdzIHdoZW4gcHJvZmlsZSBpcyBnaXZlbmApXHJcbiAgICBpZiAodGhpcy5oYXNUZXJtKG9wdGlvbnMpICYmIG9wdGlvbnMuZmlsdGVycz8uY3VzdG9tT3B0aW9ucylcclxuICAgICAgdGhyb3cgbmV3IEludmFsaWRBcmd1bWVudEVycm9yKGBJdCBjb3VsZG4ndCBmaWxsZWQgY3VzdG9tT3B0aW9ucyB3aGVuIHRlcm0gaXMgZ2l2ZW5gKVxyXG5cclxuICAgIHJldHVybiBhd2FpdCB0aGlzLmZpbmRDYXRhbG9nKG9wdGlvbnMsIGxpbWl0cykudGhlbigoeyBkYXRhLCBjb3VudDogdG90YWwsIG1heGltdW0sIG1pbmltYWwsIGRpc3RpbmN0IH0pID0+ICh7XHJcbiAgICAgIHByb2R1Y3RzOiB7IGRhdGE6IGRhdGEubWFwKChwcm9kdWN0KSA9PiBSb3VuZFByb2R1Y3RQcmljZXNIZWxwZXIucm91bmRQcm9kdWN0UHJpY2VzKHByb2R1Y3QpKSwgdG90YWwgfSxcclxuICAgICAgcGFnZXM6IE1hdGguY2VpbCh0b3RhbCAvIGxpbWl0cy5saW1pdCksXHJcbiAgICAgIHByaWNlczoge1xyXG4gICAgICAgIHByaWNlOiB7IG1pbjogK21pbmltYWw/LnByaWNlPy5wcmljZT8udG9GaXhlZCgyKSwgbWF4OiArbWF4aW11bT8ucHJpY2U/LnByaWNlPy50b0ZpeGVkKDIpIH0sXHJcbiAgICAgICAgc3Vic2NyaWJlclByaWNlOiB7XHJcbiAgICAgICAgICBtaW46ICttaW5pbWFsPy5wcmljZT8uc3Vic2NyaWJlclByaWNlPy50b0ZpeGVkKDIpLFxyXG4gICAgICAgICAgbWF4OiArbWF4aW11bT8ucHJpY2U/LnN1YnNjcmliZXJQcmljZT8udG9GaXhlZCgyKSxcclxuICAgICAgICB9LFxyXG4gICAgICB9LFxyXG4gICAgICBicmFuZHM6IGRpc3RpbmN0Py5icmFuZCxcclxuICAgIH0pKVxyXG4gIH1cclxuXHJcbiAgYXN5bmMgYWRkQ3VzdG9tZXJUb1N0b2NrTm90aWZpY2F0aW9uKHNob3A6IFNob3BzLCBwcm9kdWN0SWQ6IHN0cmluZywgbmFtZTogc3RyaW5nLCBlbWFpbDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICByZXR1cm4gdGhpcy5wcm9kdWN0U3RvY2tOb3RpZmljYXRpb25SZXBvc2l0b3J5LmFkZEN1c3RvbWVyRW1haWwoc2hvcCwgcHJvZHVjdElkLCBuYW1lLCBlbWFpbClcclxuICB9XHJcblxyXG4gIHByaXZhdGUgYXN5bmMgZmluZENhdGFsb2coXHJcbiAgICBvcHRpb25zOiBGZXRjaFByb2R1Y3RzUGFyYW1zPFQ+LFxyXG4gICAgbGltaXRzOiB7XHJcbiAgICAgIGxpbWl0PzogbnVtYmVyXHJcbiAgICAgIG9mZnNldD86IG51bWJlclxyXG4gICAgfSxcclxuICApOiBQcm9taXNlPFJlcG9zaXRvcnlGaW5kUmVzdWx0PFByb2R1Y3Q+PiB7XHJcbiAgICBpZiAodGhpcy5oYXNUZXJtKG9wdGlvbnMpICYmIG9wdGlvbnMuc29ydCA9PT0gJ21vc3QtcmVsZXZhbnQnKSB7XHJcbiAgICAgIGNvbnN0IHByb2R1Y3RzSWRzID0gYXdhaXQgdGhpcy5maW5kQ2F0YWxvZ0lkc0J5RWxhc3RpY1NlYXJjaChvcHRpb25zLnRlcm0pXHJcblxyXG4gICAgICByZXR1cm4gdGhpcy5maW5kQ2F0YWxvZ0FuZFNvcnRCeU1vc3RSZXZlbGFudEJ5VGVybShwcm9kdWN0c0lkcywgb3B0aW9ucywgbGltaXRzKVxyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLmhhc0NhdGVnb3J5KG9wdGlvbnMpICYmIG9wdGlvbnMuc29ydCA9PT0gJ21vc3QtcmVsZXZhbnQnKSB7XHJcbiAgICAgIGNvbnN0IHsgbW9zdFJlbGV2YW50IH0gPSBvcHRpb25zLmNhdGVnb3J5XHJcbiAgICAgIGNvbnNvbGUubG9nKCdtb3N0UmVsZXZhbnQnLCBtb3N0UmVsZXZhbnQpXHJcbiAgICAgIGNvbnN0IHByb2R1Y3RzSWRzID0gYXdhaXQgdGhpcy5wcm9kdWN0UmVwb3NpdG9yeVxyXG4gICAgICAgIC5maW5kKHtcclxuICAgICAgICAgIGZpbHRlcnM6IHtcclxuICAgICAgICAgICAgLi4uKGF3YWl0IHRoaXMuYnVpbGRNYWluRmlsdGVyKG9wdGlvbnMpKSxcclxuICAgICAgICAgIH0sXHJcbiAgICAgICAgfSlcclxuICAgICAgICAudGhlbigocHJvZHVjdHMpID0+IHByb2R1Y3RzLmRhdGEubWFwKChwcm9kdWN0KSA9PiBwcm9kdWN0LmlkKSlcclxuXHJcbiAgICAgIHJldHVybiB0aGlzLmZpbmRDYXRhbG9nQW5kU29ydEJ5TW9zdFJldmVsYW50KG1vc3RSZWxldmFudCwgcHJvZHVjdHNJZHMsIG9wdGlvbnMsIGxpbWl0cylcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCByZXBvUGFyYW1zOiBGaW5kUmVwb3NpdG9yeVBhcmFtczxQcm9kdWN0PiA9IHtcclxuICAgICAgZmlsdGVyczoge1xyXG4gICAgICAgIC4uLihhd2FpdCB0aGlzLmJ1aWxkTWFpbkZpbHRlcihvcHRpb25zKSksXHJcbiAgICAgICAgLi4udGhpcy5idWlsZEZpbHRlclF1ZXJ5KG9wdGlvbnM/LmZpbHRlcnMgfHwge30pLFxyXG4gICAgICB9LFxyXG4gICAgICAuLi4ob3B0aW9ucz8uc29ydCA/IHsgb3JkZXJCeTogdGhpcy5idWlsZFNvcnRRdWVyeShvcHRpb25zPy5zb3J0KSB9IDoge30pLFxyXG4gICAgICBsaW1pdHMsXHJcbiAgICAgIG9wdGlvbnM6IHtcclxuICAgICAgICBtaW5pbWFsOiBbJ3ByaWNlJ10sXHJcbiAgICAgICAgbWF4aW11bTogWydwcmljZSddLFxyXG4gICAgICAgIC4uLighdGhpcy5oYXNDYXRlZ29yeShvcHRpb25zKSA/IHsgZGlzdGluY3Q6IFsnYnJhbmQnXSB9IDoge30pLFxyXG4gICAgICB9LFxyXG4gICAgfVxyXG5cclxuICAgIGlmIChbJ2JpZ2dlc3QtcHJpY2UnLCAnbG93ZXN0LXByaWNlJywgJ2JpZ2dlc3QtZGlzY291bnQnLCAnYmVzdC1yYXRpbmcnXS5pbmNsdWRlcyhvcHRpb25zLnNvcnQpKVxyXG4gICAgICByZXR1cm4gdGhpcy5wcm9kdWN0UmVwb3NpdG9yeS5maW5kQ2F0YWxvZyhyZXBvUGFyYW1zKVxyXG5cclxuICAgIHJldHVybiB0aGlzLnByb2R1Y3RSZXBvc2l0b3J5LmZpbmRDYXRhbG9nKFxyXG4gICAgICByZXBvUGFyYW1zLFxyXG4gICAgICBvcHRpb25zPy5tYWluR2VuZGVyIHx8IHRoaXMuc2hvcCA9PT0gU2hvcHMuTUVOU01BUktFVCA/ICdtYWxlJyA6ICdmZW1hbGUnLFxyXG4gICAgKVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBhc3luYyBidWlsZE1haW5GaWx0ZXIoe1xyXG4gICAgY2F0ZWdvcnksXHJcbiAgICBwcm9maWxlLFxyXG4gICAgdGVybSxcclxuICB9OiBGZXRjaFByb2R1Y3RzTWFpblBhcmFtczxUPik6IFByb21pc2U8UmVwb3NpdG9yeUZpbmRGaWVsdGVyczxQcm9kdWN0Pj4ge1xyXG4gICAgaWYgKGNhdGVnb3J5KSByZXR1cm4gdGhpcy5jYXRlZ29yeVN0cnVjdHVyZUFkYXB0ZXIuYnVpbGRQcm9kdWN0RmlsdGVyQnlDYXRlZ29yeShjYXRlZ29yeSlcclxuICAgIGlmIChwcm9maWxlKSByZXR1cm4geyB0YWdzOiB7IG9wZXJhdG9yOiBXaGVyZS5MSUtFLCB2YWx1ZTogcHJvZmlsZSB9IH1cclxuICAgIGlmICh0ZXJtKVxyXG4gICAgICByZXR1cm4gdGhpcy5wcm9kdWN0SW5kZXhcclxuICAgICAgICAuc2VhcmNoKHRlcm0sIDk5OSwgdGhpcy5zaG9wKVxyXG4gICAgICAgIC50aGVuKChkYXRhKSA9PiAoeyBpZDogeyBvcGVyYXRvcjogV2hlcmUuSU4sIHZhbHVlOiBkYXRhLmhpdHMubWFwKCh7IF9zb3VyY2UgfSkgPT4gX3NvdXJjZS5pZCkgfSB9KSlcclxuICB9XHJcblxyXG4gIHByaXZhdGUgYXN5bmMgZmluZENhdGFsb2dBbmRTb3J0QnlNb3N0UmV2ZWxhbnQoXHJcbiAgICBtb3N0UmVsZXZhbnRzOiBzdHJpbmdbXSxcclxuICAgIHByb2R1Y3RJZHM6IHN0cmluZ1tdLFxyXG4gICAgb3B0aW9uczogT21pdDxGZXRjaFByb2R1Y3RzT3B0aW9ucywgJ3NvcnQnPiAmIHtcclxuICAgICAgdGVybT86IEZldGNoUHJvZHVjdHNNYWluUGFyYW1zPFQ+Wyd0ZXJtJ11cclxuICAgICAgZmlsdGVycz86IEZldGNoUHJvZHVjdHNGaWx0ZXJzICYgeyBjdXN0b21PcHRpb25zPzogbmV2ZXIgfVxyXG4gICAgfSxcclxuICAgIGxpbWl0czoge1xyXG4gICAgICBsaW1pdD86IG51bWJlclxyXG4gICAgICBvZmZzZXQ/OiBudW1iZXJcclxuICAgIH0sXHJcbiAgKTogUHJvbWlzZTxSZXBvc2l0b3J5RmluZFJlc3VsdDxQcm9kdWN0Pj4ge1xyXG4gICAgY29uc3QgeyBvZmZzZXQgfSA9IGxpbWl0c1xyXG5cclxuICAgIGlmIChvZmZzZXQgPT09IDApIHtcclxuICAgICAgbGltaXRzLmxpbWl0IC09IG1vc3RSZWxldmFudHMubGVuZ3RoXHJcbiAgICB9XHJcblxyXG4gICAgaWYgKG9mZnNldCA+IDApIHtcclxuICAgICAgbGltaXRzLm9mZnNldCAtPSBtb3N0UmVsZXZhbnRzLmxlbmd0aFxyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IG1vc3RSZWxldmFudFByb2R1Y3RzSWRzID0gWy4uLm5ldyBTZXQoLi4ubW9zdFJlbGV2YW50cywgLi4ucHJvZHVjdElkcyldXHJcbiAgICBjb25zdCB0b3RhbFJlc3VsdCA9IGF3YWl0IHRoaXMucHJvZHVjdFJlcG9zaXRvcnkuZmluZENhdGFsb2coXHJcbiAgICAgIHtcclxuICAgICAgICBmaWVsZHM6IFsnaWQnLCAnc3RvY2snXSxcclxuICAgICAgICBmaWx0ZXJzOiB7XHJcbiAgICAgICAgICBpZDogeyBvcGVyYXRvcjogV2hlcmUuSU4sIHZhbHVlOiBtb3N0UmVsZXZhbnRQcm9kdWN0c0lkcyB9LFxyXG4gICAgICAgICAgLi4udGhpcy5idWlsZEZpbHRlclF1ZXJ5KG9wdGlvbnM/LmZpbHRlcnMgfHwge30pLFxyXG4gICAgICAgIH0sXHJcbiAgICAgICAgb3B0aW9uczoge1xyXG4gICAgICAgICAgbWluaW1hbDogWydwcmljZSddLFxyXG4gICAgICAgICAgbWF4aW11bTogWydwcmljZSddLFxyXG4gICAgICAgICAgZGlzdGluY3Q6IFsnYnJhbmQnXSxcclxuICAgICAgICB9LFxyXG4gICAgICB9LFxyXG4gICAgICBvcHRpb25zPy5tYWluR2VuZGVyIHx8IHRoaXMuc2hvcCA9PT0gU2hvcHMuTUVOU01BUktFVCA/ICdtYWxlJyA6ICdmZW1hbGUnLFxyXG4gICAgKVxyXG5cclxuICAgIGNvbnN0IHN0b2NrRGF0YSA9IHRvdGFsUmVzdWx0LmRhdGEuZmlsdGVyKChwcm9kdWN0KSA9PiBwcm9kdWN0LnN0b2NrLnF1YW50aXR5ID4gMClcclxuICAgIGNvbnN0IHN0b2NrT3V0ID0gdG90YWxSZXN1bHQuZGF0YS5maWx0ZXIoKHByb2R1Y3QpID0+IHByb2R1Y3Quc3RvY2sucXVhbnRpdHkgPD0gMClcclxuICAgIGNvbnN0IHByb2R1Y3RJZHNTdG9jayA9IHByb2R1Y3RJZHMuZmlsdGVyKChwcm9kdWN0KSA9PiBzdG9ja0RhdGEuc29tZSgocmVzdWx0KSA9PiByZXN1bHQuaWQgPT0gcHJvZHVjdCkpXHJcbiAgICBjb25zdCBwcm9kdWN0SWRzU3RvY2tPdXQgPSBwcm9kdWN0SWRzLmZpbHRlcigocHJvZHVjdCkgPT4gc3RvY2tPdXQuc29tZSgocmVzdWx0KSA9PiByZXN1bHQuaWQgPT0gcHJvZHVjdCkpXHJcblxyXG4gICAgY29uc3QgbGltaXRlZFByb2R1Y3RJZCA9IHByb2R1Y3RJZHNTdG9ja1xyXG4gICAgICAuY29uY2F0KHByb2R1Y3RJZHNTdG9ja091dClcclxuICAgICAgLnNsaWNlKGxpbWl0cy5vZmZzZXQsIGxpbWl0cy5vZmZzZXQgKyBsaW1pdHMubGltaXQpXHJcblxyXG4gICAgY29uc3Qgb3JkZXJlZElkID0gcHJvZHVjdElkcy5maWx0ZXIoKHByb2R1Y3QpID0+IGxpbWl0ZWRQcm9kdWN0SWQuaW5jbHVkZXMocHJvZHVjdCkpXHJcbiAgICBjb25zdCBwcm9kdWN0UmVzdWx0ID0gYXdhaXQgdGhpcy5wcm9kdWN0UmVwb3NpdG9yeS5maW5kQ2F0YWxvZyh7XHJcbiAgICAgIGZpbHRlcnM6IHtcclxuICAgICAgICBpZDogeyBvcGVyYXRvcjogV2hlcmUuSU4sIHZhbHVlOiBvcmRlcmVkSWQgfSxcclxuICAgICAgfSxcclxuICAgIH0pXHJcblxyXG4gICAgcmV0dXJuIHtcclxuICAgICAgZGF0YTogbGltaXRlZFByb2R1Y3RJZC5tYXAoKGlkKSA9PiBwcm9kdWN0UmVzdWx0LmRhdGEuZmluZCgocHJvZHVjdCkgPT4gcHJvZHVjdC5pZCA9PT0gaWQpKS5maWx0ZXIoQm9vbGVhbiksXHJcbiAgICAgIGNvdW50OiB0b3RhbFJlc3VsdC5jb3VudCxcclxuICAgICAgbWF4aW11bTogdG90YWxSZXN1bHQubWF4aW11bSxcclxuICAgICAgbWluaW1hbDogdG90YWxSZXN1bHQubWluaW1hbCxcclxuICAgICAgZGlzdGluY3Q6IHRvdGFsUmVzdWx0LmRpc3RpbmN0LFxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBhc3luYyBmaW5kQ2F0YWxvZ0FuZFNvcnRCeU1vc3RSZXZlbGFudEJ5VGVybShcclxuICAgIHByb2R1Y3RJZHM6IHN0cmluZ1tdLFxyXG4gICAgb3B0aW9uczogT21pdDxGZXRjaFByb2R1Y3RzT3B0aW9ucywgJ3NvcnQnPiAmIHtcclxuICAgICAgdGVybT86IEZldGNoUHJvZHVjdHNNYWluUGFyYW1zPFQ+Wyd0ZXJtJ11cclxuICAgICAgZmlsdGVycz86IEZldGNoUHJvZHVjdHNGaWx0ZXJzICYgeyBjdXN0b21PcHRpb25zPzogbmV2ZXIgfVxyXG4gICAgfSxcclxuICAgIGxpbWl0czoge1xyXG4gICAgICBsaW1pdD86IG51bWJlclxyXG4gICAgICBvZmZzZXQ/OiBudW1iZXJcclxuICAgIH0sXHJcbiAgKTogUHJvbWlzZTxSZXBvc2l0b3J5RmluZFJlc3VsdDxQcm9kdWN0Pj4ge1xyXG4gICAgY29uc3QgdG90YWxSZXN1bHQgPSBhd2FpdCB0aGlzLnByb2R1Y3RSZXBvc2l0b3J5LmZpbmRDYXRhbG9nKFxyXG4gICAgICB7XHJcbiAgICAgICAgZmllbGRzOiBbJ2lkJywgJ3N0b2NrJ10sXHJcbiAgICAgICAgZmlsdGVyczoge1xyXG4gICAgICAgICAgaWQ6IHsgb3BlcmF0b3I6IFdoZXJlLklOLCB2YWx1ZTogcHJvZHVjdElkcyB9LFxyXG4gICAgICAgICAgLi4udGhpcy5idWlsZEZpbHRlclF1ZXJ5KG9wdGlvbnM/LmZpbHRlcnMgfHwge30pLFxyXG4gICAgICAgIH0sXHJcbiAgICAgICAgb3B0aW9uczoge1xyXG4gICAgICAgICAgbWluaW1hbDogWydwcmljZSddLFxyXG4gICAgICAgICAgbWF4aW11bTogWydwcmljZSddLFxyXG4gICAgICAgICAgZGlzdGluY3Q6IFsnYnJhbmQnXSxcclxuICAgICAgICB9LFxyXG4gICAgICB9LFxyXG4gICAgICBvcHRpb25zPy5tYWluR2VuZGVyIHx8IHRoaXMuc2hvcCA9PT0gU2hvcHMuTUVOU01BUktFVCA/ICdtYWxlJyA6ICdmZW1hbGUnLFxyXG4gICAgKVxyXG5cclxuICAgIGNvbnN0IHN0b2NrRGF0YSA9IHRvdGFsUmVzdWx0LmRhdGEuZmlsdGVyKChwcm9kdWN0KSA9PiBwcm9kdWN0LnN0b2NrLnF1YW50aXR5ID4gMClcclxuICAgIGNvbnN0IHN0b2NrT3V0ID0gdG90YWxSZXN1bHQuZGF0YS5maWx0ZXIoKHByb2R1Y3QpID0+IHByb2R1Y3Quc3RvY2sucXVhbnRpdHkgPD0gMClcclxuICAgIGNvbnN0IHByb2R1Y3RJZHNTdG9jayA9IHByb2R1Y3RJZHMuZmlsdGVyKChwcm9kdWN0KSA9PiBzdG9ja0RhdGEuc29tZSgocmVzdWx0KSA9PiByZXN1bHQuaWQgPT0gcHJvZHVjdCkpXHJcbiAgICBjb25zdCBwcm9kdWN0SWRzU3RvY2tPdXQgPSBwcm9kdWN0SWRzLmZpbHRlcigocHJvZHVjdCkgPT4gc3RvY2tPdXQuc29tZSgocmVzdWx0KSA9PiByZXN1bHQuaWQgPT0gcHJvZHVjdCkpXHJcblxyXG4gICAgY29uc3QgbGltaXRlZFByb2R1Y3RJZCA9IHByb2R1Y3RJZHNTdG9ja1xyXG4gICAgICAuY29uY2F0KHByb2R1Y3RJZHNTdG9ja091dClcclxuICAgICAgLnNsaWNlKGxpbWl0cy5vZmZzZXQsIGxpbWl0cy5vZmZzZXQgKyBsaW1pdHMubGltaXQpXHJcblxyXG4gICAgY29uc3Qgb3JkZXJlZElkID0gcHJvZHVjdElkcy5maWx0ZXIoKHByb2R1Y3QpID0+IGxpbWl0ZWRQcm9kdWN0SWQuaW5jbHVkZXMocHJvZHVjdCkpXHJcbiAgICBjb25zdCBwcm9kdWN0UmVzdWx0ID0gYXdhaXQgdGhpcy5wcm9kdWN0UmVwb3NpdG9yeS5maW5kQ2F0YWxvZyh7XHJcbiAgICAgIGZpbHRlcnM6IHtcclxuICAgICAgICBpZDogeyBvcGVyYXRvcjogV2hlcmUuSU4sIHZhbHVlOiBvcmRlcmVkSWQgfSxcclxuICAgICAgfSxcclxuICAgIH0pXHJcblxyXG4gICAgcmV0dXJuIHtcclxuICAgICAgZGF0YTogbGltaXRlZFByb2R1Y3RJZC5tYXAoKGlkKSA9PiBwcm9kdWN0UmVzdWx0LmRhdGEuZmluZCgocHJvZHVjdCkgPT4gcHJvZHVjdC5pZCA9PT0gaWQpKS5maWx0ZXIoQm9vbGVhbiksXHJcbiAgICAgIGNvdW50OiB0b3RhbFJlc3VsdC5jb3VudCxcclxuICAgICAgbWF4aW11bTogdG90YWxSZXN1bHQubWF4aW11bSxcclxuICAgICAgbWluaW1hbDogdG90YWxSZXN1bHQubWluaW1hbCxcclxuICAgICAgZGlzdGluY3Q6IHRvdGFsUmVzdWx0LmRpc3RpbmN0LFxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBhc3luYyBmaW5kQ2F0YWxvZ0lkc0J5RWxhc3RpY1NlYXJjaCh0ZXJtOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZ1tdPiB7XHJcbiAgICBpZiAodGhpcy5wcm9kdWN0c0J5VGVybVt0ZXJtXSkgcmV0dXJuIHRoaXMucHJvZHVjdHNCeVRlcm1bdGVybV1cclxuXHJcbiAgICByZXR1cm4gKHRoaXMucHJvZHVjdHNCeVRlcm1bdGVybV0gPSBhd2FpdCB0aGlzLnByb2R1Y3RJbmRleFxyXG4gICAgICAuc2VhcmNoKHRlcm0sIDk5OSwgdGhpcy5zaG9wKVxyXG4gICAgICAudGhlbigoeyBoaXRzOiBwcm9kdWN0cyB9KSA9PiB7XHJcbiAgICAgICAgY29uc3Qgd2l0aFN0b2NrID0gcHJvZHVjdHMuZmlsdGVyKCh7IF9zb3VyY2UgfSkgPT4gX3NvdXJjZS5zdG9jay5xdWFudGl0eSA+IDApXHJcbiAgICAgICAgY29uc3Qgd2l0aE91dFN0b2NrID0gcHJvZHVjdHMuZmlsdGVyKCh7IF9zb3VyY2UgfSkgPT4gX3NvdXJjZS5zdG9jay5xdWFudGl0eSA8PSAwKVxyXG4gICAgICAgIGNvbnN0IHNvcnRlZCA9IFsuLi53aXRoU3RvY2ssIC4uLndpdGhPdXRTdG9ja11cclxuXHJcbiAgICAgICAgcmV0dXJuIFsuLi5uZXcgU2V0KHNvcnRlZC5tYXAoKHsgX3NvdXJjZSB9KSA9PiBfc291cmNlLmlkKSldXHJcbiAgICAgIH0pKVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBidWlsZEZpbHRlclF1ZXJ5ID0gKHtcclxuICAgIGNsdWJEaXNjb3VudCxcclxuICAgIGJyYW5kcyxcclxuICAgIHByaWNlcyxcclxuICAgIGdlbmRlcixcclxuICAgIHRhZ3MsXHJcbiAgICByYXRlLFxyXG4gICAgY3VzdG9tT3B0aW9ucyxcclxuICB9OiBGZXRjaFByb2R1Y3RzRmlsdGVycyk6IFJlcG9zaXRvcnlGaW5kRmllbHRlcnM8UHJvZHVjdD4gPT4ge1xyXG4gICAgY29uc3QgZmlsdGVycyA9IHt9IGFzIFJlcG9zaXRvcnlGaW5kRmllbHRlcnM8UHJvZHVjdD5cclxuXHJcbiAgICBpZiAoY2x1YkRpc2NvdW50Py5sZW5ndGgpXHJcbiAgICAgIHNldChmaWx0ZXJzLCAncHJpY2Uuc3Vic2NyaWJlckRpc2NvdW50UGVyY2VudGFnZScsIHsgb3BlcmF0b3I6IFdoZXJlLklOLCB2YWx1ZTogY2x1YkRpc2NvdW50IH0pXHJcbiAgICBpZiAoYnJhbmRzPy5sZW5ndGgpIGZpbHRlcnMuYnJhbmQgPSB7IG9wZXJhdG9yOiBXaGVyZS5JTiwgdmFsdWU6IGJyYW5kcyB9XHJcbiAgICBpZiAoZ2VuZGVyPy5sZW5ndGgpIGZpbHRlcnMuZ2VuZGVyID0geyBvcGVyYXRvcjogV2hlcmUuSU4sIHZhbHVlOiBnZW5kZXIgfVxyXG4gICAgaWYgKHByaWNlcz8ubWluIHx8IHByaWNlcz8ubWF4KVxyXG4gICAgICBzZXQoZmlsdGVycywgcHJpY2VzLnN1YnNjcmliZXJQcmljZSA/ICdwcmljZS5zdWJzY3JpYmVyUHJpY2UnIDogJ3ByaWNlLnByaWNlJywgW1xyXG4gICAgICAgIC4uLihwcmljZXMubWluID8gW3sgb3BlcmF0b3I6IFdoZXJlLkdURSwgdmFsdWU6IE1hdGgucm91bmQocHJpY2VzLm1pbikgfV0gOiBbXSksXHJcbiAgICAgICAgLi4uKHByaWNlcy5tYXggPyBbeyBvcGVyYXRvcjogV2hlcmUuTFRFLCB2YWx1ZTogTWF0aC5jZWlsKHByaWNlcy5tYXgpIH1dIDogW10pLFxyXG4gICAgICBdKVxyXG4gICAgaWYgKHJhdGUpIGZpbHRlcnMucmF0ZSA9IHsgb3BlcmF0b3I6IFdoZXJlLkdURSwgdmFsdWU6IHJhdGUgfVxyXG4gICAgaWYgKHRhZ3M/Lmxlbmd0aCkgZmlsdGVycy50YWdzID0geyBvcGVyYXRvcjogV2hlcmUuTElLRSwgdmFsdWU6IHRhZ3MgfVxyXG4gICAgaWYgKGN1c3RvbU9wdGlvbnM/Lmxlbmd0aCkgZmlsdGVycy5maWx0ZXJzID0geyBvcGVyYXRvcjogV2hlcmUuTElLRSwgdmFsdWU6IGN1c3RvbU9wdGlvbnMgfVxyXG5cclxuICAgIHJldHVybiBmaWx0ZXJzXHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGJ1aWxkU29ydFF1ZXJ5ID0gKHNvcnQ6IFByb2R1Y3RTb3J0KTogUmVwb3NpdG9yeU9yZGVyQnk8UHJvZHVjdD4gPT4ge1xyXG4gICAgaWYgKCFzb3J0IHx8IHNvcnQgPT09ICdtb3N0LXJlbGV2YW50JykgcmV0dXJuIHt9XHJcblxyXG4gICAgaWYgKHNvcnQgPT09ICdiZXN0LXNlbGxlcnMnKVxyXG4gICAgICByZXR1cm4ge1xyXG4gICAgICAgIHNob3BwaW5nQ291bnQ6ICdkZXNjJyxcclxuICAgICAgICByYXRlOiAnZGVzYycsXHJcbiAgICAgICAgc3RvY2s6ICdkZXNjJyxcclxuICAgICAgICBuYW1lOiAnYXNjJyxcclxuICAgICAgfVxyXG4gICAgaWYgKHNvcnQgPT09ICdiaWdnZXN0LXByaWNlJykgcmV0dXJuIHsgc3Vic2NyaWJlclByaWNlOiAnZGVzYycsIHJhdGU6ICdkZXNjJywgc2hvcHBpbmdDb3VudDogJ2Rlc2MnIH0gYXMgYW55XHJcbiAgICBpZiAoc29ydCA9PT0gJ2xvd2VzdC1wcmljZScpIHJldHVybiB7IHN1YnNjcmliZXJQcmljZTogJ2FzYycsIHJhdGU6ICdkZXNjJywgc2hvcHBpbmdDb3VudDogJ2Rlc2MnIH0gYXMgYW55XHJcbiAgICBpZiAoc29ydCA9PT0gJ2Jlc3QtcmF0aW5nJykgcmV0dXJuIHsgcmF0ZTogJ2Rlc2MnLCBzaG9wcGluZ0NvdW50OiAnZGVzYycsIHN0b2NrOiAnZGVzYycsIG5hbWU6ICdhc2MnIH1cclxuICAgIGlmIChzb3J0ID09PSAnbmV3cycpIHJldHVybiB7IGNyZWF0ZWRBdDogJ2Rlc2MnIH1cclxuICAgIGlmIChzb3J0ID09PSAnYmlnZ2VzdC1kaXNjb3VudCcpXHJcbiAgICAgIHJldHVybiB7IHN1YnNjcmliZXJEaXNjb3VudFBlcmNlbnRhZ2U6ICdkZXNjJywgcmF0ZTogJ2Rlc2MnLCBzaG9wcGluZ0NvdW50OiAnZGVzYycgfSBhcyBhbnlcclxuICB9XHJcblxyXG4gIHByaXZhdGUgYnVpbGRMaW1pdFF1ZXJ5ID0gKG9wdGlvbnM6IHsgcGFnZT86IG51bWJlcjsgcGVyUGFnZT86IG51bWJlciB9KTogeyBsaW1pdD86IG51bWJlcjsgb2Zmc2V0PzogbnVtYmVyIH0gPT4ge1xyXG4gICAgY29uc3QgbGltaXQgPSBvcHRpb25zPy5wZXJQYWdlIHx8IDIwXHJcblxyXG4gICAgcmV0dXJuIHtcclxuICAgICAgbGltaXQsXHJcbiAgICAgIG9mZnNldDogKChvcHRpb25zPy5wYWdlIHx8IDEpIC0gMSkgKiBsaW1pdCxcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgaGFzUHJvZmlsZSA9IChcclxuICAgIG9wdGlvbnM6IEZldGNoUHJvZHVjdHNQYXJhbXM8VD4sXHJcbiAgKTogb3B0aW9ucyBpcyBGZXRjaFByb2R1Y3RzT3B0aW9ucyAmIHtcclxuICAgIHByb2ZpbGU6IEZldGNoUHJvZHVjdHNNYWluUGFyYW1zPFQ+Wydwcm9maWxlJ11cclxuICAgIGZpbHRlcnM/OiBGZXRjaFByb2R1Y3RzRmlsdGVycyAmIHsgY3VzdG9tT3B0aW9ucz86IG5ldmVyOyB0YWdzPzogbmV2ZXIgfVxyXG4gIH0gPT4gJ3Byb2ZpbGUnIGluIG9wdGlvbnNcclxuXHJcbiAgcHJpdmF0ZSBoYXNUZXJtID0gKFxyXG4gICAgb3B0aW9uczogRmV0Y2hQcm9kdWN0c1BhcmFtczxUPixcclxuICApOiBvcHRpb25zIGlzIEZldGNoUHJvZHVjdHNPcHRpb25zICYge1xyXG4gICAgdGVybTogRmV0Y2hQcm9kdWN0c01haW5QYXJhbXM8VD5bJ3Rlcm0nXVxyXG4gICAgZmlsdGVycz86IEZldGNoUHJvZHVjdHNGaWx0ZXJzICYgeyBjdXN0b21PcHRpb25zPzogbmV2ZXIgfVxyXG4gIH0gPT4gJ3Rlcm0nIGluIG9wdGlvbnNcclxuXHJcbiAgcHJpdmF0ZSBoYXNDYXRlZ29yeSA9IChcclxuICAgIG9wdGlvbnM6IEZldGNoUHJvZHVjdHNQYXJhbXM8VD4sXHJcbiAgKTogb3B0aW9ucyBpcyBGZXRjaFByb2R1Y3RzT3B0aW9ucyAmIHtcclxuICAgIGNhdGVnb3J5OiBGZXRjaFByb2R1Y3RzTWFpblBhcmFtczxUPlsnY2F0ZWdvcnknXVxyXG4gICAgZmlsdGVycz86IEZldGNoUHJvZHVjdHNGaWx0ZXJzICYgeyBjdXN0b21PcHRpb25zPzogbmV2ZXIgfVxyXG4gIH0gPT4gJ2NhdGVnb3J5JyBpbiBvcHRpb25zXHJcbn1cclxuIl19