mobx-keystone-loro 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/LICENSE +21 -0
- package/README.md +119 -0
- package/dist/mobx-keystone-loro.esm.js +957 -0
- package/dist/mobx-keystone-loro.esm.mjs +957 -0
- package/dist/mobx-keystone-loro.umd.js +957 -0
- package/dist/types/binding/LoroTextModel.d.ts +72 -0
- package/dist/types/binding/applyLoroEventToMobx.d.ts +9 -0
- package/dist/types/binding/applyMobxChangeToLoroObject.d.ts +7 -0
- package/dist/types/binding/bindLoroToMobxKeystone.d.ts +33 -0
- package/dist/types/binding/convertJsonToLoroData.d.ts +51 -0
- package/dist/types/binding/convertLoroDataToJson.d.ts +11 -0
- package/dist/types/binding/loroBindingContext.d.ts +39 -0
- package/dist/types/binding/loroSnapshotTracking.d.ts +26 -0
- package/dist/types/binding/moveWithinArray.d.ts +36 -0
- package/dist/types/binding/resolveLoroPath.d.ts +11 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/plainTypes.d.ts +6 -0
- package/dist/types/utils/error.d.ts +4 -0
- package/dist/types/utils/getOrCreateLoroCollectionAtom.d.ts +7 -0
- package/dist/types/utils/isBindableLoroContainer.d.ts +9 -0
- package/package.json +92 -0
- package/src/binding/LoroTextModel.ts +211 -0
- package/src/binding/applyLoroEventToMobx.ts +280 -0
- package/src/binding/applyMobxChangeToLoroObject.ts +182 -0
- package/src/binding/bindLoroToMobxKeystone.ts +353 -0
- package/src/binding/convertJsonToLoroData.ts +315 -0
- package/src/binding/convertLoroDataToJson.ts +68 -0
- package/src/binding/loroBindingContext.ts +46 -0
- package/src/binding/loroSnapshotTracking.ts +36 -0
- package/src/binding/moveWithinArray.ts +112 -0
- package/src/binding/resolveLoroPath.ts +37 -0
- package/src/index.ts +16 -0
- package/src/plainTypes.ts +7 -0
- package/src/utils/error.ts +12 -0
- package/src/utils/getOrCreateLoroCollectionAtom.ts +17 -0
- package/src/utils/isBindableLoroContainer.ts +13 -0
|
@@ -0,0 +1,957 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
+
import { LoroMap, LoroMovableList, LoroText, isContainer } from "loro-crdt";
|
|
5
|
+
import { createAtom, computed, remove, action } from "mobx";
|
|
6
|
+
import { createContext, types, getSnapshotModelType, Model, tProp, frozen, getParentToChildPath, modelAction, model, modelSnapshotOutWithMetadata, toFrozenSnapshot, resolvePath, runUnprotected, isModel, isDataModel, modelIdKey, isFrozenSnapshot, getSnapshotModelId, fromSnapshot, frozenKey, DeepChangeType, onGlobalDeepChange, getSnapshot, onDeepChange, onSnapshot, isTreeNode } from "mobx-keystone";
|
|
7
|
+
let nanoid = (size = 21) => crypto.getRandomValues(new Uint8Array(size)).reduce((id, byte) => {
|
|
8
|
+
byte &= 63;
|
|
9
|
+
if (byte < 36) {
|
|
10
|
+
id += byte.toString(36);
|
|
11
|
+
} else if (byte < 62) {
|
|
12
|
+
id += (byte - 26).toString(36).toUpperCase();
|
|
13
|
+
} else if (byte > 62) {
|
|
14
|
+
id += "-";
|
|
15
|
+
} else {
|
|
16
|
+
id += "_";
|
|
17
|
+
}
|
|
18
|
+
return id;
|
|
19
|
+
}, "");
|
|
20
|
+
const atomMap = /* @__PURE__ */ new WeakMap();
|
|
21
|
+
function getOrCreateLoroCollectionAtom(collection) {
|
|
22
|
+
let atom = atomMap.get(collection);
|
|
23
|
+
if (!atom) {
|
|
24
|
+
atom = createAtom(`loroCollectionAtom`);
|
|
25
|
+
atomMap.set(collection, atom);
|
|
26
|
+
}
|
|
27
|
+
return atom;
|
|
28
|
+
}
|
|
29
|
+
class MobxKeystoneLoroError extends Error {
|
|
30
|
+
constructor(msg) {
|
|
31
|
+
super(msg);
|
|
32
|
+
Object.setPrototypeOf(this, MobxKeystoneLoroError.prototype);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function failure(message) {
|
|
36
|
+
throw new MobxKeystoneLoroError(message);
|
|
37
|
+
}
|
|
38
|
+
const loroBindingContext = createContext(void 0);
|
|
39
|
+
function resolveLoroPath(loroObject, path) {
|
|
40
|
+
let currentLoroObject = loroObject;
|
|
41
|
+
path.forEach((pathPart, i) => {
|
|
42
|
+
if (currentLoroObject instanceof LoroMap) {
|
|
43
|
+
getOrCreateLoroCollectionAtom(currentLoroObject).reportObserved();
|
|
44
|
+
const key = String(pathPart);
|
|
45
|
+
currentLoroObject = currentLoroObject.get(key);
|
|
46
|
+
} else if (currentLoroObject instanceof LoroMovableList) {
|
|
47
|
+
getOrCreateLoroCollectionAtom(currentLoroObject).reportObserved();
|
|
48
|
+
const key = Number(pathPart);
|
|
49
|
+
currentLoroObject = currentLoroObject.get(key);
|
|
50
|
+
} else {
|
|
51
|
+
throw failure(
|
|
52
|
+
`LoroMap or LoroMovableList was expected at path ${JSON.stringify(
|
|
53
|
+
path.slice(0, i)
|
|
54
|
+
)} in order to resolve path ${JSON.stringify(path)}, but got ${currentLoroObject} instead`
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
return currentLoroObject;
|
|
59
|
+
}
|
|
60
|
+
var __defProp2 = Object.defineProperty;
|
|
61
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
62
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
63
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
64
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
65
|
+
if (decorator = decorators[i])
|
|
66
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
67
|
+
if (kind && result) __defProp2(target, key, result);
|
|
68
|
+
return result;
|
|
69
|
+
};
|
|
70
|
+
const loroTextModelId = "mobx-keystone-loro/LoroTextModel";
|
|
71
|
+
let LoroTextModel = class extends Model({
|
|
72
|
+
/**
|
|
73
|
+
* The current delta representing the rich text content.
|
|
74
|
+
* Uses Quill delta format.
|
|
75
|
+
*/
|
|
76
|
+
deltaList: tProp(types.frozen(types.unchecked()), () => frozen([]))
|
|
77
|
+
}) {
|
|
78
|
+
constructor() {
|
|
79
|
+
super(...arguments);
|
|
80
|
+
/**
|
|
81
|
+
* Atom that gets changed when the associated Loro text changes.
|
|
82
|
+
*/
|
|
83
|
+
__publicField(this, "loroTextChangedAtom", createAtom("loroTextChangedAtom"));
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Creates a LoroTextModel with initial text content.
|
|
87
|
+
*/
|
|
88
|
+
static withText(text) {
|
|
89
|
+
return new LoroTextModel({
|
|
90
|
+
deltaList: frozen([{ insert: text }])
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Creates a LoroTextModel with initial delta.
|
|
95
|
+
*/
|
|
96
|
+
static withDelta(delta) {
|
|
97
|
+
return new LoroTextModel({
|
|
98
|
+
deltaList: frozen(delta)
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
get loroText() {
|
|
102
|
+
const ctx = loroBindingContext.get(this);
|
|
103
|
+
if ((ctx == null ? void 0 : ctx.boundObject) == null) {
|
|
104
|
+
return void 0;
|
|
105
|
+
}
|
|
106
|
+
try {
|
|
107
|
+
const path = getParentToChildPath(ctx.boundObject, this);
|
|
108
|
+
if (!path) {
|
|
109
|
+
return void 0;
|
|
110
|
+
}
|
|
111
|
+
if (path.length === 0) {
|
|
112
|
+
const loroObject2 = ctx.loroObject;
|
|
113
|
+
if (loroObject2 instanceof LoroText) {
|
|
114
|
+
getOrCreateLoroCollectionAtom(loroObject2).reportObserved();
|
|
115
|
+
return loroObject2;
|
|
116
|
+
}
|
|
117
|
+
return void 0;
|
|
118
|
+
}
|
|
119
|
+
const loroObject = resolveLoroPath(ctx.loroObject, path);
|
|
120
|
+
if (loroObject instanceof LoroText) {
|
|
121
|
+
getOrCreateLoroCollectionAtom(loroObject).reportObserved();
|
|
122
|
+
return loroObject;
|
|
123
|
+
}
|
|
124
|
+
} catch {
|
|
125
|
+
}
|
|
126
|
+
return void 0;
|
|
127
|
+
}
|
|
128
|
+
get text() {
|
|
129
|
+
this.loroTextChangedAtom.reportObserved();
|
|
130
|
+
return this.deltaToText(this.deltaList.data);
|
|
131
|
+
}
|
|
132
|
+
get currentDelta() {
|
|
133
|
+
this.loroTextChangedAtom.reportObserved();
|
|
134
|
+
const loroText = this.loroText;
|
|
135
|
+
if (loroText) {
|
|
136
|
+
try {
|
|
137
|
+
return loroText.toDelta();
|
|
138
|
+
} catch {
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return this.deltaList.data;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Converts delta to plain text.
|
|
145
|
+
*/
|
|
146
|
+
deltaToText(delta) {
|
|
147
|
+
let result = "";
|
|
148
|
+
for (const op of delta) {
|
|
149
|
+
if ("insert" in op && typeof op.insert === "string") {
|
|
150
|
+
result += op.insert;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return result;
|
|
154
|
+
}
|
|
155
|
+
setDelta(delta) {
|
|
156
|
+
this.deltaList = frozen(delta);
|
|
157
|
+
}
|
|
158
|
+
insertText(index, text) {
|
|
159
|
+
const loroText = this.loroText;
|
|
160
|
+
if (loroText) {
|
|
161
|
+
loroText.insert(index, text);
|
|
162
|
+
} else {
|
|
163
|
+
const currentText = this.text;
|
|
164
|
+
const newText = currentText.slice(0, index) + text + currentText.slice(index);
|
|
165
|
+
this.deltaList = frozen([{ insert: newText }]);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
deleteText(index, length) {
|
|
169
|
+
const loroText = this.loroText;
|
|
170
|
+
if (loroText) {
|
|
171
|
+
loroText.delete(index, length);
|
|
172
|
+
} else {
|
|
173
|
+
const currentText = this.text;
|
|
174
|
+
const newText = currentText.slice(0, index) + currentText.slice(index + length);
|
|
175
|
+
this.deltaList = frozen([{ insert: newText }]);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
_updateDeltaFromLoro(delta) {
|
|
179
|
+
this.deltaList = frozen(delta);
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
__decorateClass([
|
|
183
|
+
computed
|
|
184
|
+
], LoroTextModel.prototype, "loroText", 1);
|
|
185
|
+
__decorateClass([
|
|
186
|
+
computed
|
|
187
|
+
], LoroTextModel.prototype, "text", 1);
|
|
188
|
+
__decorateClass([
|
|
189
|
+
computed
|
|
190
|
+
], LoroTextModel.prototype, "currentDelta", 1);
|
|
191
|
+
__decorateClass([
|
|
192
|
+
modelAction
|
|
193
|
+
], LoroTextModel.prototype, "setDelta", 1);
|
|
194
|
+
__decorateClass([
|
|
195
|
+
modelAction
|
|
196
|
+
], LoroTextModel.prototype, "insertText", 1);
|
|
197
|
+
__decorateClass([
|
|
198
|
+
modelAction
|
|
199
|
+
], LoroTextModel.prototype, "deleteText", 1);
|
|
200
|
+
__decorateClass([
|
|
201
|
+
modelAction
|
|
202
|
+
], LoroTextModel.prototype, "_updateDeltaFromLoro", 1);
|
|
203
|
+
LoroTextModel = __decorateClass([
|
|
204
|
+
model(loroTextModelId)
|
|
205
|
+
], LoroTextModel);
|
|
206
|
+
const loroTextModelType = types.model(LoroTextModel);
|
|
207
|
+
function isLoroTextModelSnapshot(value) {
|
|
208
|
+
return getSnapshotModelType(value) === loroTextModelId;
|
|
209
|
+
}
|
|
210
|
+
function convertLoroDataToJson(value) {
|
|
211
|
+
if (value === null) {
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
if (typeof value !== "object") {
|
|
215
|
+
if (value === void 0) {
|
|
216
|
+
throw new Error("undefined values are not supported by Loro");
|
|
217
|
+
}
|
|
218
|
+
return value;
|
|
219
|
+
}
|
|
220
|
+
if (isContainer(value)) {
|
|
221
|
+
if (value instanceof LoroMap) {
|
|
222
|
+
const result2 = {};
|
|
223
|
+
for (const [k, v] of value.entries()) {
|
|
224
|
+
result2[k] = convertLoroDataToJson(v);
|
|
225
|
+
}
|
|
226
|
+
return result2;
|
|
227
|
+
}
|
|
228
|
+
if (value instanceof LoroMovableList) {
|
|
229
|
+
const result2 = [];
|
|
230
|
+
for (let i = 0; i < value.length; i++) {
|
|
231
|
+
result2.push(convertLoroDataToJson(value.get(i)));
|
|
232
|
+
}
|
|
233
|
+
return result2;
|
|
234
|
+
}
|
|
235
|
+
if (value instanceof LoroText) {
|
|
236
|
+
const deltas = value.toDelta();
|
|
237
|
+
return modelSnapshotOutWithMetadata(LoroTextModel, {
|
|
238
|
+
deltaList: toFrozenSnapshot(deltas)
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
throw failure(`unsupported bindable Loro container type`);
|
|
242
|
+
}
|
|
243
|
+
if (Array.isArray(value)) {
|
|
244
|
+
return value.map((item) => convertLoroDataToJson(item));
|
|
245
|
+
}
|
|
246
|
+
const result = {};
|
|
247
|
+
for (const [k, v] of Object.entries(value)) {
|
|
248
|
+
result[k] = convertLoroDataToJson(v);
|
|
249
|
+
}
|
|
250
|
+
return result;
|
|
251
|
+
}
|
|
252
|
+
function applyLoroEventToMobx(event, loroDoc, boundObject, rootPath, reconciliationMap, newlyInsertedContainers) {
|
|
253
|
+
if (newlyInsertedContainers.has(event.target)) {
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
const eventPath = loroDoc.getPathToContainer(event.target);
|
|
257
|
+
if (!eventPath) {
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
const relativePath = resolveEventPath(eventPath, rootPath);
|
|
261
|
+
if (relativePath === void 0) {
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
const { value: target } = resolvePath(boundObject, relativePath);
|
|
265
|
+
if (!target) {
|
|
266
|
+
throw failure(`cannot resolve path ${JSON.stringify(relativePath)}`);
|
|
267
|
+
}
|
|
268
|
+
runUnprotected(() => {
|
|
269
|
+
const diff = event.diff;
|
|
270
|
+
if (diff.type === "map") {
|
|
271
|
+
applyMapEventToMobx(diff, loroDoc, event.target, target, reconciliationMap);
|
|
272
|
+
} else if (diff.type === "list") {
|
|
273
|
+
applyListEventToMobx(
|
|
274
|
+
diff,
|
|
275
|
+
loroDoc,
|
|
276
|
+
event.target,
|
|
277
|
+
target,
|
|
278
|
+
reconciliationMap,
|
|
279
|
+
newlyInsertedContainers
|
|
280
|
+
);
|
|
281
|
+
} else if (diff.type === "text") {
|
|
282
|
+
applyTextEventToMobx(loroDoc, event.target, target);
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
function processDeletedValue(val, reconciliationMap) {
|
|
287
|
+
if (isModel(val) || isDataModel(val)) {
|
|
288
|
+
const id = modelIdKey in val ? val[modelIdKey] : void 0;
|
|
289
|
+
if (id) {
|
|
290
|
+
reconciliationMap.set(id, val);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
function reviveValue(jsonValue, reconciliationMap) {
|
|
295
|
+
if (jsonValue === null || typeof jsonValue !== "object") {
|
|
296
|
+
return jsonValue;
|
|
297
|
+
}
|
|
298
|
+
if (isFrozenSnapshot(jsonValue)) {
|
|
299
|
+
return frozen(jsonValue.data);
|
|
300
|
+
}
|
|
301
|
+
if (reconciliationMap) {
|
|
302
|
+
const modelId = getSnapshotModelId(jsonValue);
|
|
303
|
+
if (modelId) {
|
|
304
|
+
const existing = reconciliationMap.get(modelId);
|
|
305
|
+
if (existing) {
|
|
306
|
+
reconciliationMap.delete(modelId);
|
|
307
|
+
return existing;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
return fromSnapshot(jsonValue);
|
|
312
|
+
}
|
|
313
|
+
function applyMapEventToMobx(diff, loroDoc, containerTarget, target, reconciliationMap) {
|
|
314
|
+
const container = loroDoc.getContainerById(containerTarget);
|
|
315
|
+
if (!container || !(container instanceof LoroMap)) {
|
|
316
|
+
throw failure(`${containerTarget} was not a Loro map`);
|
|
317
|
+
}
|
|
318
|
+
for (const key of Object.keys(diff.updated)) {
|
|
319
|
+
const loroValue = container.get(key);
|
|
320
|
+
if (loroValue === void 0) {
|
|
321
|
+
if (key in target) {
|
|
322
|
+
processDeletedValue(target[key], reconciliationMap);
|
|
323
|
+
if (isModel(target)) {
|
|
324
|
+
remove(target.$, key);
|
|
325
|
+
} else {
|
|
326
|
+
remove(target, key);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
} else {
|
|
330
|
+
if (key in target) {
|
|
331
|
+
processDeletedValue(target[key], reconciliationMap);
|
|
332
|
+
}
|
|
333
|
+
const jsonValue = convertLoroDataToJson(loroValue);
|
|
334
|
+
target[key] = reviveValue(jsonValue, reconciliationMap);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
function applyListEventToMobx(diff, loroDoc, containerTarget, target, reconciliationMap, newlyInsertedContainers) {
|
|
339
|
+
const container = loroDoc.getContainerById(containerTarget);
|
|
340
|
+
if (!container || !(container instanceof LoroMovableList)) {
|
|
341
|
+
throw failure(`${containerTarget} was not a Loro movable list`);
|
|
342
|
+
}
|
|
343
|
+
let currentIndex = 0;
|
|
344
|
+
for (const change of diff.diff) {
|
|
345
|
+
if (change.retain) {
|
|
346
|
+
currentIndex += change.retain;
|
|
347
|
+
}
|
|
348
|
+
if (change.delete) {
|
|
349
|
+
const deletedItems = target.slice(currentIndex, currentIndex + change.delete);
|
|
350
|
+
deletedItems.forEach((item) => {
|
|
351
|
+
processDeletedValue(item, reconciliationMap);
|
|
352
|
+
});
|
|
353
|
+
target.splice(currentIndex, change.delete);
|
|
354
|
+
}
|
|
355
|
+
if (change.insert) {
|
|
356
|
+
const insertedItems = change.insert;
|
|
357
|
+
const values = insertedItems.map((loroValue) => {
|
|
358
|
+
if (isContainer(loroValue)) {
|
|
359
|
+
newlyInsertedContainers.add(loroValue.id);
|
|
360
|
+
collectNestedContainerIds(loroValue, newlyInsertedContainers);
|
|
361
|
+
}
|
|
362
|
+
const jsonValue = convertLoroDataToJson(loroValue);
|
|
363
|
+
return reviveValue(jsonValue, reconciliationMap);
|
|
364
|
+
});
|
|
365
|
+
target.splice(currentIndex, 0, ...values);
|
|
366
|
+
currentIndex += values.length;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
function applyTextEventToMobx(loroDoc, containerTarget, target) {
|
|
371
|
+
const container = loroDoc.getContainerById(containerTarget);
|
|
372
|
+
if (!container || !(container instanceof LoroText)) {
|
|
373
|
+
throw failure(`${containerTarget} was not a Loro text container`);
|
|
374
|
+
}
|
|
375
|
+
if (!("deltaList" in target)) {
|
|
376
|
+
throw failure("target does not have a deltaList property - expected LoroTextModel");
|
|
377
|
+
}
|
|
378
|
+
target.deltaList = frozen(container.toDelta());
|
|
379
|
+
}
|
|
380
|
+
function collectNestedContainerIds(container, containerIds) {
|
|
381
|
+
if (!isContainer(container)) {
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
containerIds.add(container.id);
|
|
385
|
+
if (container instanceof LoroMap) {
|
|
386
|
+
for (const key of Object.keys(container.toJSON())) {
|
|
387
|
+
const value = container.get(key);
|
|
388
|
+
collectNestedContainerIds(value, containerIds);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
if (container instanceof LoroMovableList) {
|
|
392
|
+
for (let i = 0; i < container.length; i++) {
|
|
393
|
+
collectNestedContainerIds(container.get(i), containerIds);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
function resolveEventPath(eventPath, rootPath) {
|
|
398
|
+
if (eventPath.length < rootPath.length) {
|
|
399
|
+
return void 0;
|
|
400
|
+
}
|
|
401
|
+
for (let i = 0; i < rootPath.length; i++) {
|
|
402
|
+
if (eventPath[i] !== rootPath[i]) {
|
|
403
|
+
return void 0;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
return eventPath.slice(rootPath.length);
|
|
407
|
+
}
|
|
408
|
+
function isBindableLoroContainer(value) {
|
|
409
|
+
return value instanceof LoroMap || value instanceof LoroMovableList || value instanceof LoroText;
|
|
410
|
+
}
|
|
411
|
+
const loroContainerToSnapshot = /* @__PURE__ */ new WeakMap();
|
|
412
|
+
function setLoroContainerSnapshot(container, snapshot) {
|
|
413
|
+
loroContainerToSnapshot.set(container, snapshot);
|
|
414
|
+
}
|
|
415
|
+
function isLoroContainerUpToDate(container, snapshot) {
|
|
416
|
+
return loroContainerToSnapshot.get(container) === snapshot;
|
|
417
|
+
}
|
|
418
|
+
function isPlainPrimitive(v) {
|
|
419
|
+
const t = typeof v;
|
|
420
|
+
return t === "string" || t === "number" || t === "boolean" || v === null || v === void 0;
|
|
421
|
+
}
|
|
422
|
+
function isPlainArray(v) {
|
|
423
|
+
return Array.isArray(v);
|
|
424
|
+
}
|
|
425
|
+
function isPlainObject(v) {
|
|
426
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
427
|
+
}
|
|
428
|
+
function extractTextDeltaFromSnapshot(delta) {
|
|
429
|
+
if (isFrozenSnapshot(delta)) {
|
|
430
|
+
const data = delta.data;
|
|
431
|
+
if (Array.isArray(data)) {
|
|
432
|
+
return data;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
if (Array.isArray(delta)) {
|
|
436
|
+
return delta;
|
|
437
|
+
}
|
|
438
|
+
return [];
|
|
439
|
+
}
|
|
440
|
+
function applyDeltaToLoroText(text, deltas) {
|
|
441
|
+
let position = 0;
|
|
442
|
+
const markOperations = [];
|
|
443
|
+
for (const delta of deltas) {
|
|
444
|
+
if (delta.insert !== void 0) {
|
|
445
|
+
const content = delta.insert;
|
|
446
|
+
text.insert(position, content);
|
|
447
|
+
if (delta.attributes && Object.keys(delta.attributes).length > 0) {
|
|
448
|
+
markOperations.push({
|
|
449
|
+
start: position,
|
|
450
|
+
end: position + content.length,
|
|
451
|
+
attributes: delta.attributes
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
position += content.length;
|
|
455
|
+
} else if (delta.retain) {
|
|
456
|
+
position += delta.retain;
|
|
457
|
+
} else if (delta.delete) {
|
|
458
|
+
text.delete(position, delta.delete);
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
for (const op of markOperations) {
|
|
462
|
+
for (const [key, value] of Object.entries(op.attributes)) {
|
|
463
|
+
text.mark({ start: op.start, end: op.end }, key, value);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
function convertJsonToLoroData(v) {
|
|
468
|
+
if (isPlainPrimitive(v)) {
|
|
469
|
+
return v;
|
|
470
|
+
}
|
|
471
|
+
if (isPlainArray(v)) {
|
|
472
|
+
const list = new LoroMovableList();
|
|
473
|
+
applyJsonArrayToLoroMovableList(list, v);
|
|
474
|
+
return list;
|
|
475
|
+
}
|
|
476
|
+
if (isPlainObject(v)) {
|
|
477
|
+
if (v[frozenKey] === true) {
|
|
478
|
+
return v;
|
|
479
|
+
}
|
|
480
|
+
if (isLoroTextModelSnapshot(v)) {
|
|
481
|
+
const text = new LoroText();
|
|
482
|
+
const deltas = extractTextDeltaFromSnapshot(v.deltaList);
|
|
483
|
+
if (deltas.length > 0) {
|
|
484
|
+
applyDeltaToLoroText(text, deltas);
|
|
485
|
+
}
|
|
486
|
+
return text;
|
|
487
|
+
}
|
|
488
|
+
const map = new LoroMap();
|
|
489
|
+
applyJsonObjectToLoroMap(map, v);
|
|
490
|
+
return map;
|
|
491
|
+
}
|
|
492
|
+
throw new Error(`unsupported value type: ${v}`);
|
|
493
|
+
}
|
|
494
|
+
const applyJsonArrayToLoroMovableList = (dest, source, options = {}) => {
|
|
495
|
+
const { mode = "add" } = options;
|
|
496
|
+
if (mode === "add") {
|
|
497
|
+
for (const item of source) {
|
|
498
|
+
const converted = convertJsonToLoroData(item);
|
|
499
|
+
if (isBindableLoroContainer(converted)) {
|
|
500
|
+
dest.pushContainer(converted);
|
|
501
|
+
} else {
|
|
502
|
+
dest.push(converted);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
if (isLoroContainerUpToDate(dest, source)) {
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
510
|
+
const destLen = dest.length;
|
|
511
|
+
const srcLen = source.length;
|
|
512
|
+
if (destLen > srcLen) {
|
|
513
|
+
dest.delete(srcLen, destLen - srcLen);
|
|
514
|
+
}
|
|
515
|
+
const minLen = Math.min(destLen, srcLen);
|
|
516
|
+
for (let i = 0; i < minLen; i++) {
|
|
517
|
+
const srcItem = source[i];
|
|
518
|
+
const destItem = dest.get(i);
|
|
519
|
+
if (isPlainObject(srcItem) && destItem instanceof LoroMap) {
|
|
520
|
+
applyJsonObjectToLoroMap(destItem, srcItem, options);
|
|
521
|
+
continue;
|
|
522
|
+
}
|
|
523
|
+
if (isPlainArray(srcItem) && destItem instanceof LoroMovableList) {
|
|
524
|
+
applyJsonArrayToLoroMovableList(destItem, srcItem, options);
|
|
525
|
+
continue;
|
|
526
|
+
}
|
|
527
|
+
if (isPlainPrimitive(srcItem) && destItem === srcItem) {
|
|
528
|
+
continue;
|
|
529
|
+
}
|
|
530
|
+
dest.delete(i, 1);
|
|
531
|
+
const converted = convertJsonToLoroData(srcItem);
|
|
532
|
+
if (isBindableLoroContainer(converted)) {
|
|
533
|
+
dest.insertContainer(i, converted);
|
|
534
|
+
} else {
|
|
535
|
+
dest.insert(i, converted);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
for (let i = destLen; i < srcLen; i++) {
|
|
539
|
+
const converted = convertJsonToLoroData(source[i]);
|
|
540
|
+
if (isBindableLoroContainer(converted)) {
|
|
541
|
+
dest.pushContainer(converted);
|
|
542
|
+
} else {
|
|
543
|
+
dest.push(converted);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
setLoroContainerSnapshot(dest, source);
|
|
547
|
+
};
|
|
548
|
+
const applyJsonObjectToLoroMap = (dest, source, options = {}) => {
|
|
549
|
+
const { mode = "add" } = options;
|
|
550
|
+
if (mode === "add") {
|
|
551
|
+
for (const k of Object.keys(source)) {
|
|
552
|
+
const v = source[k];
|
|
553
|
+
if (v !== void 0) {
|
|
554
|
+
const converted = convertJsonToLoroData(v);
|
|
555
|
+
if (isBindableLoroContainer(converted)) {
|
|
556
|
+
dest.setContainer(k, converted);
|
|
557
|
+
} else {
|
|
558
|
+
dest.set(k, converted);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
return;
|
|
563
|
+
}
|
|
564
|
+
if (isLoroContainerUpToDate(dest, source)) {
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
567
|
+
const sourceKeysWithValues = new Set(Object.keys(source).filter((k) => source[k] !== void 0));
|
|
568
|
+
for (const key of dest.keys()) {
|
|
569
|
+
if (!sourceKeysWithValues.has(key)) {
|
|
570
|
+
dest.delete(key);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
for (const k of Object.keys(source)) {
|
|
574
|
+
const v = source[k];
|
|
575
|
+
if (v === void 0) {
|
|
576
|
+
continue;
|
|
577
|
+
}
|
|
578
|
+
const existing = dest.get(k);
|
|
579
|
+
if (isPlainObject(v) && existing instanceof LoroMap) {
|
|
580
|
+
applyJsonObjectToLoroMap(existing, v, options);
|
|
581
|
+
continue;
|
|
582
|
+
}
|
|
583
|
+
if (isPlainArray(v) && existing instanceof LoroMovableList) {
|
|
584
|
+
applyJsonArrayToLoroMovableList(existing, v, options);
|
|
585
|
+
continue;
|
|
586
|
+
}
|
|
587
|
+
if (isPlainPrimitive(v) && existing === v) {
|
|
588
|
+
continue;
|
|
589
|
+
}
|
|
590
|
+
const converted = convertJsonToLoroData(v);
|
|
591
|
+
if (isBindableLoroContainer(converted)) {
|
|
592
|
+
dest.setContainer(k, converted);
|
|
593
|
+
} else {
|
|
594
|
+
dest.set(k, converted);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
setLoroContainerSnapshot(dest, source);
|
|
598
|
+
};
|
|
599
|
+
function convertValue(v) {
|
|
600
|
+
if (v === null || v === void 0 || typeof v !== "object") {
|
|
601
|
+
return v;
|
|
602
|
+
}
|
|
603
|
+
if (Array.isArray(v) && v.length === 0) {
|
|
604
|
+
return new LoroMovableList();
|
|
605
|
+
}
|
|
606
|
+
if (isLoroTextModelSnapshot(v)) {
|
|
607
|
+
return v;
|
|
608
|
+
}
|
|
609
|
+
return convertJsonToLoroData(v);
|
|
610
|
+
}
|
|
611
|
+
function insertIntoList(list, index, value) {
|
|
612
|
+
if (value instanceof LoroMap || value instanceof LoroMovableList || value instanceof LoroText) {
|
|
613
|
+
list.insertContainer(index, value);
|
|
614
|
+
} else if (isLoroTextModelSnapshot(value)) {
|
|
615
|
+
const attachedText = list.insertContainer(index, new LoroText());
|
|
616
|
+
const deltas = extractTextDeltaFromSnapshot(value.deltaList);
|
|
617
|
+
if (deltas.length > 0) {
|
|
618
|
+
applyDeltaToLoroText(attachedText, deltas);
|
|
619
|
+
}
|
|
620
|
+
} else {
|
|
621
|
+
list.insert(index, value);
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
function setInMap(map, key, value) {
|
|
625
|
+
if (value === void 0) {
|
|
626
|
+
map.delete(key);
|
|
627
|
+
} else if (value instanceof LoroMap || value instanceof LoroMovableList || value instanceof LoroText) {
|
|
628
|
+
map.setContainer(key, value);
|
|
629
|
+
} else if (isLoroTextModelSnapshot(value)) {
|
|
630
|
+
const attachedText = map.setContainer(key, new LoroText());
|
|
631
|
+
const deltas = extractTextDeltaFromSnapshot(value.deltaList);
|
|
632
|
+
if (deltas.length > 0) {
|
|
633
|
+
applyDeltaToLoroText(attachedText, deltas);
|
|
634
|
+
}
|
|
635
|
+
} else {
|
|
636
|
+
map.set(key, value);
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
function applyMobxChangeToLoroObject(change, loroObject) {
|
|
640
|
+
const loroContainer = resolveLoroPath(loroObject, change.path);
|
|
641
|
+
if (!loroContainer) {
|
|
642
|
+
throw failure(
|
|
643
|
+
`cannot apply change to missing Loro container at path: ${JSON.stringify(change.path)}`
|
|
644
|
+
);
|
|
645
|
+
}
|
|
646
|
+
switch (change.type) {
|
|
647
|
+
case "ArrayMove": {
|
|
648
|
+
if (!(loroContainer instanceof LoroMovableList)) {
|
|
649
|
+
throw failure(`ArrayMove change requires a LoroMovableList container`);
|
|
650
|
+
}
|
|
651
|
+
loroContainer.move(change.fromIndex, change.toIndex);
|
|
652
|
+
break;
|
|
653
|
+
}
|
|
654
|
+
case DeepChangeType.ArraySplice: {
|
|
655
|
+
if (!(loroContainer instanceof LoroMovableList)) {
|
|
656
|
+
throw failure(`ArraySplice change requires a LoroMovableList container`);
|
|
657
|
+
}
|
|
658
|
+
if (change.removedValues.length > 0) {
|
|
659
|
+
loroContainer.delete(change.index, change.removedValues.length);
|
|
660
|
+
}
|
|
661
|
+
if (change.addedValues.length > 0) {
|
|
662
|
+
const valuesToInsert = change.addedValues.map(convertValue);
|
|
663
|
+
for (let i = 0; i < valuesToInsert.length; i++) {
|
|
664
|
+
insertIntoList(loroContainer, change.index + i, valuesToInsert[i]);
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
break;
|
|
668
|
+
}
|
|
669
|
+
case DeepChangeType.ArrayUpdate: {
|
|
670
|
+
if (!(loroContainer instanceof LoroMovableList)) {
|
|
671
|
+
throw failure(`ArrayUpdate change requires a LoroMovableList container`);
|
|
672
|
+
}
|
|
673
|
+
const converted = convertValue(change.newValue);
|
|
674
|
+
if (converted instanceof LoroMap || converted instanceof LoroMovableList || converted instanceof LoroText) {
|
|
675
|
+
loroContainer.setContainer(change.index, converted);
|
|
676
|
+
} else if (isLoroTextModelSnapshot(converted)) {
|
|
677
|
+
const attachedText = loroContainer.setContainer(change.index, new LoroText());
|
|
678
|
+
const deltas = extractTextDeltaFromSnapshot(converted.deltaList);
|
|
679
|
+
if (deltas.length > 0) {
|
|
680
|
+
applyDeltaToLoroText(attachedText, deltas);
|
|
681
|
+
}
|
|
682
|
+
} else {
|
|
683
|
+
loroContainer.set(change.index, converted);
|
|
684
|
+
}
|
|
685
|
+
break;
|
|
686
|
+
}
|
|
687
|
+
case DeepChangeType.ObjectAdd:
|
|
688
|
+
case DeepChangeType.ObjectUpdate: {
|
|
689
|
+
if (loroContainer instanceof LoroText) {
|
|
690
|
+
if (change.key === "deltaList") {
|
|
691
|
+
const deltas = extractTextDeltaFromSnapshot(change.newValue);
|
|
692
|
+
if (loroContainer.length > 0) {
|
|
693
|
+
loroContainer.delete(0, loroContainer.length);
|
|
694
|
+
}
|
|
695
|
+
if (deltas.length > 0) {
|
|
696
|
+
applyDeltaToLoroText(loroContainer, deltas);
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
} else if (loroContainer instanceof LoroMap) {
|
|
700
|
+
const converted = convertValue(change.newValue);
|
|
701
|
+
setInMap(loroContainer, change.key, converted);
|
|
702
|
+
} else {
|
|
703
|
+
throw failure(`ObjectAdd/ObjectUpdate change requires a LoroMap or LoroText container`);
|
|
704
|
+
}
|
|
705
|
+
break;
|
|
706
|
+
}
|
|
707
|
+
case DeepChangeType.ObjectRemove: {
|
|
708
|
+
if (loroContainer instanceof LoroText) ;
|
|
709
|
+
else if (loroContainer instanceof LoroMap) {
|
|
710
|
+
loroContainer.delete(change.key);
|
|
711
|
+
} else {
|
|
712
|
+
throw failure(`ObjectRemove change requires a LoroMap or LoroText container`);
|
|
713
|
+
}
|
|
714
|
+
break;
|
|
715
|
+
}
|
|
716
|
+
default: {
|
|
717
|
+
const _exhaustiveCheck = change;
|
|
718
|
+
throw failure(`unsupported change type: ${_exhaustiveCheck.type}`);
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
let activeMoveContext;
|
|
723
|
+
function moveWithinArray(array, fromIndex, toIndex) {
|
|
724
|
+
if (fromIndex < 0 || fromIndex >= array.length) {
|
|
725
|
+
throw new Error(`fromIndex ${fromIndex} is out of bounds (array length: ${array.length})`);
|
|
726
|
+
}
|
|
727
|
+
if (toIndex < 0 || toIndex > array.length) {
|
|
728
|
+
throw new Error(`toIndex ${toIndex} is out of bounds (array length: ${array.length})`);
|
|
729
|
+
}
|
|
730
|
+
if (fromIndex === toIndex) {
|
|
731
|
+
return;
|
|
732
|
+
}
|
|
733
|
+
activeMoveContext = {
|
|
734
|
+
array,
|
|
735
|
+
fromIndex,
|
|
736
|
+
toIndex,
|
|
737
|
+
path: void 0,
|
|
738
|
+
receivedFirstSplice: false
|
|
739
|
+
};
|
|
740
|
+
try {
|
|
741
|
+
const [item] = array.splice(fromIndex, 1);
|
|
742
|
+
const adjustedTarget = toIndex > fromIndex ? toIndex - 1 : toIndex;
|
|
743
|
+
array.splice(adjustedTarget, 0, item);
|
|
744
|
+
} finally {
|
|
745
|
+
activeMoveContext = void 0;
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
function processChangeForMove(change) {
|
|
749
|
+
const ctx = activeMoveContext;
|
|
750
|
+
if (!ctx.receivedFirstSplice) {
|
|
751
|
+
ctx.path = change.path;
|
|
752
|
+
ctx.receivedFirstSplice = true;
|
|
753
|
+
return void 0;
|
|
754
|
+
}
|
|
755
|
+
const adjustedToIndex = ctx.toIndex > ctx.fromIndex ? ctx.toIndex - 1 : ctx.toIndex;
|
|
756
|
+
return {
|
|
757
|
+
type: "ArrayMove",
|
|
758
|
+
path: ctx.path,
|
|
759
|
+
fromIndex: ctx.fromIndex,
|
|
760
|
+
toIndex: adjustedToIndex
|
|
761
|
+
};
|
|
762
|
+
}
|
|
763
|
+
function isInMoveContextForArray(array) {
|
|
764
|
+
return activeMoveContext !== void 0 && activeMoveContext.array === array;
|
|
765
|
+
}
|
|
766
|
+
function captureChangeSnapshots(change) {
|
|
767
|
+
if (change.type === DeepChangeType.ArraySplice && change.addedValues.length > 0) {
|
|
768
|
+
const snapshots = change.addedValues.map((v) => isTreeNode(v) ? getSnapshot(v) : v);
|
|
769
|
+
return { ...change, addedValues: snapshots };
|
|
770
|
+
} else if (change.type === DeepChangeType.ArrayUpdate) {
|
|
771
|
+
const snapshot = isTreeNode(change.newValue) ? getSnapshot(change.newValue) : change.newValue;
|
|
772
|
+
return { ...change, newValue: snapshot };
|
|
773
|
+
} else if (change.type === DeepChangeType.ObjectAdd || change.type === DeepChangeType.ObjectUpdate) {
|
|
774
|
+
const snapshot = isTreeNode(change.newValue) ? getSnapshot(change.newValue) : change.newValue;
|
|
775
|
+
return { ...change, newValue: snapshot };
|
|
776
|
+
}
|
|
777
|
+
return change;
|
|
778
|
+
}
|
|
779
|
+
function bindLoroToMobxKeystone({
|
|
780
|
+
loroDoc,
|
|
781
|
+
loroObject,
|
|
782
|
+
mobxKeystoneType
|
|
783
|
+
}) {
|
|
784
|
+
var _a;
|
|
785
|
+
const loroOrigin = `bindLoroToMobxKeystoneTransactionOrigin-${nanoid()}`;
|
|
786
|
+
let applyingLoroChangesToMobxKeystone = 0;
|
|
787
|
+
const bindingContext = {
|
|
788
|
+
loroDoc,
|
|
789
|
+
loroObject,
|
|
790
|
+
mobxKeystoneType,
|
|
791
|
+
loroOrigin,
|
|
792
|
+
boundObject: void 0,
|
|
793
|
+
// not yet created
|
|
794
|
+
get isApplyingLoroChangesToMobxKeystone() {
|
|
795
|
+
return applyingLoroChangesToMobxKeystone > 0;
|
|
796
|
+
}
|
|
797
|
+
};
|
|
798
|
+
const loroJson = convertLoroDataToJson(loroObject);
|
|
799
|
+
let boundObject;
|
|
800
|
+
let hasInitChanges = false;
|
|
801
|
+
const createBoundObject = () => {
|
|
802
|
+
const disposeGlobalListener = onGlobalDeepChange((_target, change) => {
|
|
803
|
+
if (change.isInit) {
|
|
804
|
+
hasInitChanges = true;
|
|
805
|
+
}
|
|
806
|
+
});
|
|
807
|
+
try {
|
|
808
|
+
const result = loroBindingContext.apply(
|
|
809
|
+
() => fromSnapshot(mobxKeystoneType, loroJson),
|
|
810
|
+
bindingContext
|
|
811
|
+
);
|
|
812
|
+
loroBindingContext.set(result, { ...bindingContext, boundObject: result });
|
|
813
|
+
return result;
|
|
814
|
+
} finally {
|
|
815
|
+
disposeGlobalListener();
|
|
816
|
+
}
|
|
817
|
+
};
|
|
818
|
+
boundObject = createBoundObject();
|
|
819
|
+
const rootLoroPath = (_a = loroDoc.getPathToContainer(loroObject.id)) != null ? _a : [];
|
|
820
|
+
const loroSubscribeCb = action((eventBatch) => {
|
|
821
|
+
if (eventBatch.origin === loroOrigin) {
|
|
822
|
+
return;
|
|
823
|
+
}
|
|
824
|
+
const newlyInsertedContainers = /* @__PURE__ */ new Set();
|
|
825
|
+
const reconciliationMap = /* @__PURE__ */ new Map();
|
|
826
|
+
const initChanges = [];
|
|
827
|
+
const disposeGlobalListener = onGlobalDeepChange((target, change) => {
|
|
828
|
+
if (change.isInit) {
|
|
829
|
+
initChanges.push({ target, change: captureChangeSnapshots(change) });
|
|
830
|
+
}
|
|
831
|
+
});
|
|
832
|
+
applyingLoroChangesToMobxKeystone++;
|
|
833
|
+
try {
|
|
834
|
+
try {
|
|
835
|
+
for (const event of eventBatch.events) {
|
|
836
|
+
applyLoroEventToMobx(
|
|
837
|
+
event,
|
|
838
|
+
loroDoc,
|
|
839
|
+
boundObject,
|
|
840
|
+
rootLoroPath,
|
|
841
|
+
reconciliationMap,
|
|
842
|
+
newlyInsertedContainers
|
|
843
|
+
);
|
|
844
|
+
}
|
|
845
|
+
} finally {
|
|
846
|
+
disposeGlobalListener();
|
|
847
|
+
}
|
|
848
|
+
if (initChanges.length > 0) {
|
|
849
|
+
loroDoc.setNextCommitOrigin(loroOrigin);
|
|
850
|
+
for (const { target, change } of initChanges) {
|
|
851
|
+
const pathToTarget = getParentToChildPath(boundObject, target);
|
|
852
|
+
if (pathToTarget !== void 0) {
|
|
853
|
+
const changeWithCorrectPath = {
|
|
854
|
+
...change,
|
|
855
|
+
path: [...pathToTarget, ...change.path]
|
|
856
|
+
};
|
|
857
|
+
applyMobxChangeToLoroObject(changeWithCorrectPath, loroObject);
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
loroDoc.commit();
|
|
861
|
+
}
|
|
862
|
+
if (loroObject instanceof LoroMap || loroObject instanceof LoroMovableList) {
|
|
863
|
+
setLoroContainerSnapshot(loroObject, getSnapshot(boundObject));
|
|
864
|
+
}
|
|
865
|
+
} finally {
|
|
866
|
+
applyingLoroChangesToMobxKeystone--;
|
|
867
|
+
}
|
|
868
|
+
});
|
|
869
|
+
const loroUnsubscribe = loroDoc.subscribe(loroSubscribeCb);
|
|
870
|
+
let pendingChanges = [];
|
|
871
|
+
const disposeOnDeepChange = onDeepChange(boundObject, (change) => {
|
|
872
|
+
if (bindingContext.isApplyingLoroChangesToMobxKeystone) {
|
|
873
|
+
return;
|
|
874
|
+
}
|
|
875
|
+
if (change.isInit) {
|
|
876
|
+
return;
|
|
877
|
+
}
|
|
878
|
+
if (change.type === DeepChangeType.ArraySplice) {
|
|
879
|
+
const resolved = resolvePath(boundObject, change.path);
|
|
880
|
+
if (resolved.resolved && isInMoveContextForArray(resolved.value)) {
|
|
881
|
+
const moveResult = processChangeForMove(change);
|
|
882
|
+
if (moveResult === void 0) {
|
|
883
|
+
return;
|
|
884
|
+
}
|
|
885
|
+
pendingChanges.push(moveResult);
|
|
886
|
+
return;
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
pendingChanges.push(captureChangeSnapshots(change));
|
|
890
|
+
});
|
|
891
|
+
const disposeOnSnapshot = onSnapshot(boundObject, () => {
|
|
892
|
+
if (pendingChanges.length === 0) {
|
|
893
|
+
return;
|
|
894
|
+
}
|
|
895
|
+
const changesToApply = pendingChanges;
|
|
896
|
+
pendingChanges = [];
|
|
897
|
+
if (bindingContext.isApplyingLoroChangesToMobxKeystone) {
|
|
898
|
+
return;
|
|
899
|
+
}
|
|
900
|
+
loroDoc.setNextCommitOrigin(loroOrigin);
|
|
901
|
+
for (const change of changesToApply) {
|
|
902
|
+
applyMobxChangeToLoroObject(change, loroObject);
|
|
903
|
+
}
|
|
904
|
+
loroDoc.commit();
|
|
905
|
+
if (loroObject instanceof LoroMap || loroObject instanceof LoroMovableList) {
|
|
906
|
+
setLoroContainerSnapshot(loroObject, getSnapshot(boundObject));
|
|
907
|
+
}
|
|
908
|
+
getOrCreateLoroCollectionAtom(loroObject).reportChanged();
|
|
909
|
+
});
|
|
910
|
+
const finalSnapshot = getSnapshot(boundObject);
|
|
911
|
+
if (hasInitChanges) {
|
|
912
|
+
loroDoc.setNextCommitOrigin(loroOrigin);
|
|
913
|
+
if (loroObject instanceof LoroMap) {
|
|
914
|
+
applyJsonObjectToLoroMap(loroObject, finalSnapshot, { mode: "merge" });
|
|
915
|
+
} else if (loroObject instanceof LoroMovableList) {
|
|
916
|
+
applyJsonArrayToLoroMovableList(loroObject, finalSnapshot, { mode: "merge" });
|
|
917
|
+
} else if (loroObject instanceof LoroText) {
|
|
918
|
+
const snapshot = finalSnapshot;
|
|
919
|
+
if (snapshot.$modelType === loroTextModelId) {
|
|
920
|
+
if (loroObject.length > 0) {
|
|
921
|
+
loroObject.delete(0, loroObject.length);
|
|
922
|
+
}
|
|
923
|
+
const deltas = extractTextDeltaFromSnapshot(snapshot.deltaList);
|
|
924
|
+
if (deltas.length > 0) {
|
|
925
|
+
applyDeltaToLoroText(loroObject, deltas);
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
loroDoc.commit();
|
|
930
|
+
}
|
|
931
|
+
if (loroObject instanceof LoroMap || loroObject instanceof LoroMovableList) {
|
|
932
|
+
setLoroContainerSnapshot(loroObject, finalSnapshot);
|
|
933
|
+
}
|
|
934
|
+
const dispose = () => {
|
|
935
|
+
loroUnsubscribe();
|
|
936
|
+
disposeOnDeepChange();
|
|
937
|
+
disposeOnSnapshot();
|
|
938
|
+
};
|
|
939
|
+
return {
|
|
940
|
+
boundObject,
|
|
941
|
+
dispose,
|
|
942
|
+
loroOrigin
|
|
943
|
+
};
|
|
944
|
+
}
|
|
945
|
+
export {
|
|
946
|
+
LoroTextModel,
|
|
947
|
+
MobxKeystoneLoroError,
|
|
948
|
+
applyJsonArrayToLoroMovableList,
|
|
949
|
+
applyJsonObjectToLoroMap,
|
|
950
|
+
bindLoroToMobxKeystone,
|
|
951
|
+
convertJsonToLoroData,
|
|
952
|
+
isLoroTextModelSnapshot,
|
|
953
|
+
loroBindingContext,
|
|
954
|
+
loroTextModelType,
|
|
955
|
+
moveWithinArray
|
|
956
|
+
};
|
|
957
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9ieC1rZXlzdG9uZS1sb3JvLmVzbS5tanMiLCJzb3VyY2VzIjpbIi4uL25vZGVfbW9kdWxlcy9uYW5vaWQvaW5kZXguYnJvd3Nlci5qcyIsIi4uL3NyYy91dGlscy9nZXRPckNyZWF0ZUxvcm9Db2xsZWN0aW9uQXRvbS50cyIsIi4uL3NyYy91dGlscy9lcnJvci50cyIsIi4uL3NyYy9iaW5kaW5nL2xvcm9CaW5kaW5nQ29udGV4dC50cyIsIi4uL3NyYy9iaW5kaW5nL3Jlc29sdmVMb3JvUGF0aC50cyIsIi4uL3NyYy9iaW5kaW5nL0xvcm9UZXh0TW9kZWwudHMiLCIuLi9zcmMvYmluZGluZy9jb252ZXJ0TG9yb0RhdGFUb0pzb24udHMiLCIuLi9zcmMvYmluZGluZy9hcHBseUxvcm9FdmVudFRvTW9ieC50cyIsIi4uL3NyYy91dGlscy9pc0JpbmRhYmxlTG9yb0NvbnRhaW5lci50cyIsIi4uL3NyYy9iaW5kaW5nL2xvcm9TbmFwc2hvdFRyYWNraW5nLnRzIiwiLi4vc3JjL2JpbmRpbmcvY29udmVydEpzb25Ub0xvcm9EYXRhLnRzIiwiLi4vc3JjL2JpbmRpbmcvYXBwbHlNb2J4Q2hhbmdlVG9Mb3JvT2JqZWN0LnRzIiwiLi4vc3JjL2JpbmRpbmcvbW92ZVdpdGhpbkFycmF5LnRzIiwiLi4vc3JjL2JpbmRpbmcvYmluZExvcm9Ub01vYnhLZXlzdG9uZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyB1cmxBbHBoYWJldCB9IGZyb20gJy4vdXJsLWFscGhhYmV0L2luZGV4LmpzJ1xubGV0IHJhbmRvbSA9IGJ5dGVzID0+IGNyeXB0by5nZXRSYW5kb21WYWx1ZXMobmV3IFVpbnQ4QXJyYXkoYnl0ZXMpKVxubGV0IGN1c3RvbVJhbmRvbSA9IChhbHBoYWJldCwgZGVmYXVsdFNpemUsIGdldFJhbmRvbSkgPT4ge1xuICBsZXQgbWFzayA9ICgyIDw8IChNYXRoLmxvZyhhbHBoYWJldC5sZW5ndGggLSAxKSAvIE1hdGguTE4yKSkgLSAxXG4gIGxldCBzdGVwID0gLX4oKDEuNiAqIG1hc2sgKiBkZWZhdWx0U2l6ZSkgLyBhbHBoYWJldC5sZW5ndGgpXG4gIHJldHVybiAoc2l6ZSA9IGRlZmF1bHRTaXplKSA9PiB7XG4gICAgbGV0IGlkID0gJydcbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgbGV0IGJ5dGVzID0gZ2V0UmFuZG9tKHN0ZXApXG4gICAgICBsZXQgaiA9IHN0ZXAgfCAwXG4gICAgICB3aGlsZSAoai0tKSB7XG4gICAgICAgIGlkICs9IGFscGhhYmV0W2J5dGVzW2pdICYgbWFza10gfHwgJydcbiAgICAgICAgaWYgKGlkLmxlbmd0aCA9PT0gc2l6ZSkgcmV0dXJuIGlkXG4gICAgICB9XG4gICAgfVxuICB9XG59XG5sZXQgY3VzdG9tQWxwaGFiZXQgPSAoYWxwaGFiZXQsIHNpemUgPSAyMSkgPT5cbiAgY3VzdG9tUmFuZG9tKGFscGhhYmV0LCBzaXplLCByYW5kb20pXG5sZXQgbmFub2lkID0gKHNpemUgPSAyMSkgPT5cbiAgY3J5cHRvLmdldFJhbmRvbVZhbHVlcyhuZXcgVWludDhBcnJheShzaXplKSkucmVkdWNlKChpZCwgYnl0ZSkgPT4ge1xuICAgIGJ5dGUgJj0gNjNcbiAgICBpZiAoYnl0ZSA8IDM2KSB7XG4gICAgICBpZCArPSBieXRlLnRvU3RyaW5nKDM2KVxuICAgIH0gZWxzZSBpZiAoYnl0ZSA8IDYyKSB7XG4gICAgICBpZCArPSAoYnl0ZSAtIDI2KS50b1N0cmluZygzNikudG9VcHBlckNhc2UoKVxuICAgIH0gZWxzZSBpZiAoYnl0ZSA+IDYyKSB7XG4gICAgICBpZCArPSAnLSdcbiAgICB9IGVsc2Uge1xuICAgICAgaWQgKz0gJ18nXG4gICAgfVxuICAgIHJldHVybiBpZFxuICB9LCAnJylcbmV4cG9ydCB7IG5hbm9pZCwgY3VzdG9tQWxwaGFiZXQsIGN1c3RvbVJhbmRvbSwgdXJsQWxwaGFiZXQsIHJhbmRvbSB9XG4iLCJpbXBvcnQgeyBjcmVhdGVBdG9tLCB0eXBlIElBdG9tIH0gZnJvbSBcIm1vYnhcIlxuaW1wb3J0IHR5cGUgeyBCaW5kYWJsZUxvcm9Db250YWluZXIgfSBmcm9tIFwiLi9pc0JpbmRhYmxlTG9yb0NvbnRhaW5lclwiXG5cbmNvbnN0IGF0b21NYXAgPSBuZXcgV2Vha01hcDxCaW5kYWJsZUxvcm9Db250YWluZXIsIElBdG9tPigpXG5cbi8qKlxuICogR2V0cyBvciBjcmVhdGVzIGEgTW9iWCBhdG9tIGZvciBhIExvcm8gY29sbGVjdGlvbi5cbiAqIFRoaXMgaXMgdXNlZCB0byB0cmFjayByZWFjdGl2aXR5IGZvciBjb21wdXRlZCBwcm9wZXJ0aWVzIHRoYXQgcmVhZCBmcm9tIExvcm8gY29udGFpbmVycy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldE9yQ3JlYXRlTG9yb0NvbGxlY3Rpb25BdG9tKGNvbGxlY3Rpb246IEJpbmRhYmxlTG9yb0NvbnRhaW5lcik6IElBdG9tIHtcbiAgbGV0IGF0b20gPSBhdG9tTWFwLmdldChjb2xsZWN0aW9uKVxuICBpZiAoIWF0b20pIHtcbiAgICBhdG9tID0gY3JlYXRlQXRvbShgbG9yb0NvbGxlY3Rpb25BdG9tYClcbiAgICBhdG9tTWFwLnNldChjb2xsZWN0aW9uLCBhdG9tKVxuICB9XG4gIHJldHVybiBhdG9tXG59XG4iLCJleHBvcnQgY2xhc3MgTW9ieEtleXN0b25lTG9yb0Vycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcihtc2c6IHN0cmluZykge1xuICAgIHN1cGVyKG1zZylcblxuICAgIC8vIFNldCB0aGUgcHJvdG90eXBlIGV4cGxpY2l0bHkgZm9yIGJldHRlciBpbnN0YW5jZW9mIHN1cHBvcnRcbiAgICBPYmplY3Quc2V0UHJvdG90eXBlT2YodGhpcywgTW9ieEtleXN0b25lTG9yb0Vycm9yLnByb3RvdHlwZSlcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZmFpbHVyZShtZXNzYWdlOiBzdHJpbmcpOiBuZXZlciB7XG4gIHRocm93IG5ldyBNb2J4S2V5c3RvbmVMb3JvRXJyb3IobWVzc2FnZSlcbn1cbiIsImltcG9ydCB0eXBlIHsgTG9yb0RvYyB9IGZyb20gXCJsb3JvLWNyZHRcIlxuaW1wb3J0IHsgdHlwZSBBbnlUeXBlLCBjcmVhdGVDb250ZXh0IH0gZnJvbSBcIm1vYngta2V5c3RvbmVcIlxuaW1wb3J0IHR5cGUgeyBCaW5kYWJsZUxvcm9Db250YWluZXIgfSBmcm9tIFwiLi4vdXRpbHMvaXNCaW5kYWJsZUxvcm9Db250YWluZXJcIlxuXG4vKipcbiAqIENvbnRleHQgZm9yIHRoZSBMb3JvIGJpbmRpbmcsIHByb3ZpZGluZyBhY2Nlc3MgdG8gdGhlIExvcm8gZG9jdW1lbnRcbiAqIGFuZCBiaW5kaW5nIHN0YXRlIGZyb20gd2l0aGluIG1vYngta2V5c3RvbmUgbW9kZWxzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIExvcm9CaW5kaW5nQ29udGV4dCB7XG4gIC8qKlxuICAgKiBUaGUgTG9ybyBkb2N1bWVudCBiZWluZyBib3VuZC5cbiAgICovXG4gIGxvcm9Eb2M6IExvcm9Eb2NcblxuICAvKipcbiAgICogVGhlIHJvb3QgTG9ybyBvYmplY3QgYmVpbmcgYm91bmQuXG4gICAqL1xuICBsb3JvT2JqZWN0OiBCaW5kYWJsZUxvcm9Db250YWluZXJcblxuICAvKipcbiAgICogVGhlIG1vYngta2V5c3RvbmUgbW9kZWwgdHlwZSBiZWluZyB1c2VkLlxuICAgKi9cbiAgbW9ieEtleXN0b25lVHlwZTogQW55VHlwZVxuXG4gIC8qKlxuICAgKiBTdHJpbmcgdXNlZCBhcyBvcmlnaW4gZm9yIExvcm8gdHJhbnNhY3Rpb25zIHRvIGlkZW50aWZ5IGNoYW5nZXNcbiAgICogY29taW5nIGZyb20gbW9ieC1rZXlzdG9uZS5cbiAgICovXG4gIGxvcm9PcmlnaW46IHN0cmluZ1xuXG4gIC8qKlxuICAgKiBUaGUgYm91bmQgbW9ieC1rZXlzdG9uZSBvYmplY3QgKG9uY2UgY3JlYXRlZCkuXG4gICAqL1xuICBib3VuZE9iamVjdDogdW5rbm93blxuXG4gIC8qKlxuICAgKiBXaGV0aGVyIGNoYW5nZXMgYXJlIGN1cnJlbnRseSBiZWluZyBhcHBsaWVkIGZyb20gTG9ybyB0byBtb2J4LWtleXN0b25lLlxuICAgKiBVc2VkIHRvIHByZXZlbnQgaW5maW5pdGUgbG9vcHMuXG4gICAqL1xuICBpc0FwcGx5aW5nTG9yb0NoYW5nZXNUb01vYnhLZXlzdG9uZTogYm9vbGVhblxufVxuXG4vKipcbiAqIENvbnRleHQgZm9yIGFjY2Vzc2luZyB0aGUgTG9ybyBiaW5kaW5nIGZyb20gd2l0aGluIG1vYngta2V5c3RvbmUgbW9kZWxzLlxuICovXG5leHBvcnQgY29uc3QgbG9yb0JpbmRpbmdDb250ZXh0ID0gY3JlYXRlQ29udGV4dDxMb3JvQmluZGluZ0NvbnRleHQgfCB1bmRlZmluZWQ+KHVuZGVmaW5lZClcbiIsImltcG9ydCB7IExvcm9NYXAsIExvcm9Nb3ZhYmxlTGlzdCB9IGZyb20gXCJsb3JvLWNyZHRcIlxuaW1wb3J0IHR5cGUgeyBQYXRoIH0gZnJvbSBcIm1vYngta2V5c3RvbmVcIlxuaW1wb3J0IHsgZmFpbHVyZSB9IGZyb20gXCIuLi91dGlscy9lcnJvclwiXG5pbXBvcnQgeyBnZXRPckNyZWF0ZUxvcm9Db2xsZWN0aW9uQXRvbSB9IGZyb20gXCIuLi91dGlscy9nZXRPckNyZWF0ZUxvcm9Db2xsZWN0aW9uQXRvbVwiXG5pbXBvcnQgdHlwZSB7IEJpbmRhYmxlTG9yb0NvbnRhaW5lciB9IGZyb20gXCIuLi91dGlscy9pc0JpbmRhYmxlTG9yb0NvbnRhaW5lclwiXG5cbi8qKlxuICogUmVzb2x2ZXMgYSBwYXRoIHdpdGhpbiBhIExvcm8gb2JqZWN0IHN0cnVjdHVyZS5cbiAqIFJldHVybnMgdGhlIExvcm8gY29udGFpbmVyIGF0IHRoZSBzcGVjaWZpZWQgcGF0aC5cbiAqXG4gKiBAcGFyYW0gbG9yb09iamVjdCBUaGUgcm9vdCBMb3JvIG9iamVjdFxuICogQHBhcmFtIHBhdGggQXJyYXkgb2Yga2V5cy9pbmRpY2VzIHRvIHRyYXZlcnNlXG4gKiBAcmV0dXJucyBUaGUgTG9ybyBjb250YWluZXIgYXQgdGhlIHBhdGhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVMb3JvUGF0aChsb3JvT2JqZWN0OiBCaW5kYWJsZUxvcm9Db250YWluZXIsIHBhdGg6IFBhdGgpOiB1bmtub3duIHtcbiAgbGV0IGN1cnJlbnRMb3JvT2JqZWN0OiB1bmtub3duID0gbG9yb09iamVjdFxuXG4gIHBhdGguZm9yRWFjaCgocGF0aFBhcnQsIGkpID0+IHtcbiAgICBpZiAoY3VycmVudExvcm9PYmplY3QgaW5zdGFuY2VvZiBMb3JvTWFwKSB7XG4gICAgICBnZXRPckNyZWF0ZUxvcm9Db2xsZWN0aW9uQXRvbShjdXJyZW50TG9yb09iamVjdCkucmVwb3J0T2JzZXJ2ZWQoKVxuICAgICAgY29uc3Qga2V5ID0gU3RyaW5nKHBhdGhQYXJ0KVxuICAgICAgY3VycmVudExvcm9PYmplY3QgPSBjdXJyZW50TG9yb09iamVjdC5nZXQoa2V5KVxuICAgIH0gZWxzZSBpZiAoY3VycmVudExvcm9PYmplY3QgaW5zdGFuY2VvZiBMb3JvTW92YWJsZUxpc3QpIHtcbiAgICAgIGdldE9yQ3JlYXRlTG9yb0NvbGxlY3Rpb25BdG9tKGN1cnJlbnRMb3JvT2JqZWN0KS5yZXBvcnRPYnNlcnZlZCgpXG4gICAgICBjb25zdCBrZXkgPSBOdW1iZXIocGF0aFBhcnQpXG4gICAgICBjdXJyZW50TG9yb09iamVjdCA9IGN1cnJlbnRMb3JvT2JqZWN0LmdldChrZXkpXG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IGZhaWx1cmUoXG4gICAgICAgIGBMb3JvTWFwIG9yIExvcm9Nb3ZhYmxlTGlzdCB3YXMgZXhwZWN0ZWQgYXQgcGF0aCAke0pTT04uc3RyaW5naWZ5KFxuICAgICAgICAgIHBhdGguc2xpY2UoMCwgaSlcbiAgICAgICAgKX0gaW4gb3JkZXIgdG8gcmVzb2x2ZSBwYXRoICR7SlNPTi5zdHJpbmdpZnkocGF0aCl9LCBidXQgZ290ICR7Y3VycmVudExvcm9PYmplY3R9IGluc3RlYWRgXG4gICAgICApXG4gICAgfVxuICB9KVxuXG4gIHJldHVybiBjdXJyZW50TG9yb09iamVjdFxufVxuIiwiaW1wb3J0IHsgdHlwZSBEZWx0YSwgTG9yb1RleHQgfSBmcm9tIFwibG9yby1jcmR0XCJcclxuaW1wb3J0IHsgY29tcHV0ZWQsIGNyZWF0ZUF0b20gfSBmcm9tIFwibW9ieFwiXHJcbmltcG9ydCB7XHJcbiAgZnJvemVuLFxyXG4gIGdldFBhcmVudFRvQ2hpbGRQYXRoLFxyXG4gIGdldFNuYXBzaG90TW9kZWxUeXBlLFxyXG4gIE1vZGVsLFxyXG4gIG1vZGVsLFxyXG4gIG1vZGVsQWN0aW9uLFxyXG4gIHR5cGUgU25hcHNob3RPdXRPZixcclxuICB0UHJvcCxcclxuICB0eXBlcyxcclxufSBmcm9tIFwibW9ieC1rZXlzdG9uZVwiXHJcbmltcG9ydCB7IGdldE9yQ3JlYXRlTG9yb0NvbGxlY3Rpb25BdG9tIH0gZnJvbSBcIi4uL3V0aWxzL2dldE9yQ3JlYXRlTG9yb0NvbGxlY3Rpb25BdG9tXCJcclxuaW1wb3J0IHsgbG9yb0JpbmRpbmdDb250ZXh0IH0gZnJvbSBcIi4vbG9yb0JpbmRpbmdDb250ZXh0XCJcclxuaW1wb3J0IHsgcmVzb2x2ZUxvcm9QYXRoIH0gZnJvbSBcIi4vcmVzb2x2ZUxvcm9QYXRoXCJcclxuXHJcbmV4cG9ydCBjb25zdCBsb3JvVGV4dE1vZGVsSWQgPSBcIm1vYngta2V5c3RvbmUtbG9yby9Mb3JvVGV4dE1vZGVsXCJcclxuXHJcbi8qKlxyXG4gKiBUeXBlIGZvciB0aGUgZGVsdGEgc3RvcmVkIGluIHRoZSBtb2RlbC5cclxuICogVXNlcyBRdWlsbCBkZWx0YSBmb3JtYXQ6IGFycmF5IG9mIG9wZXJhdGlvbnMgd2l0aCBpbnNlcnQsIGRlbGV0ZSwgcmV0YWluLlxyXG4gKi9cclxuZXhwb3J0IHR5cGUgTG9yb1RleHREZWx0YUxpc3QgPSBEZWx0YTxzdHJpbmc+W11cclxuXHJcbi8qKlxyXG4gKiBBIG1vYngta2V5c3RvbmUgbW9kZWwgcmVwcmVzZW50aW5nIExvcm8gcmljaCB0ZXh0LlxyXG4gKiBUaGlzIG1vZGVsIHN0b3JlcyB0aGUgY3VycmVudCBkZWx0YSBzdGF0ZSAoUXVpbGwgZm9ybWF0KSBhbmQgc3luY3Mgd2l0aCBMb3JvVGV4dC5cclxuICovXHJcbkBtb2RlbChsb3JvVGV4dE1vZGVsSWQpXHJcbmV4cG9ydCBjbGFzcyBMb3JvVGV4dE1vZGVsIGV4dGVuZHMgTW9kZWwoe1xyXG4gIC8qKlxyXG4gICAqIFRoZSBjdXJyZW50IGRlbHRhIHJlcHJlc2VudGluZyB0aGUgcmljaCB0ZXh0IGNvbnRlbnQuXHJcbiAgICogVXNlcyBRdWlsbCBkZWx0YSBmb3JtYXQuXHJcbiAgICovXHJcbiAgZGVsdGFMaXN0OiB0UHJvcCh0eXBlcy5mcm96ZW4odHlwZXMudW5jaGVja2VkPExvcm9UZXh0RGVsdGFMaXN0PigpKSwgKCkgPT4gZnJvemVuKFtdKSksXHJcbn0pIHtcclxuICAvKipcclxuICAgKiBDcmVhdGVzIGEgTG9yb1RleHRNb2RlbCB3aXRoIGluaXRpYWwgdGV4dCBjb250ZW50LlxyXG4gICAqL1xyXG4gIHN0YXRpYyB3aXRoVGV4dCh0ZXh0OiBzdHJpbmcpOiBMb3JvVGV4dE1vZGVsIHtcclxuICAgIHJldHVybiBuZXcgTG9yb1RleHRNb2RlbCh7XHJcbiAgICAgIGRlbHRhTGlzdDogZnJvemVuKFt7IGluc2VydDogdGV4dCB9XSksXHJcbiAgICB9KVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ3JlYXRlcyBhIExvcm9UZXh0TW9kZWwgd2l0aCBpbml0aWFsIGRlbHRhLlxyXG4gICAqL1xyXG4gIHN0YXRpYyB3aXRoRGVsdGEoZGVsdGE6IExvcm9UZXh0RGVsdGFMaXN0KTogTG9yb1RleHRNb2RlbCB7XHJcbiAgICByZXR1cm4gbmV3IExvcm9UZXh0TW9kZWwoe1xyXG4gICAgICBkZWx0YUxpc3Q6IGZyb3plbihkZWx0YSksXHJcbiAgICB9KVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQXRvbSB0aGF0IGdldHMgY2hhbmdlZCB3aGVuIHRoZSBhc3NvY2lhdGVkIExvcm8gdGV4dCBjaGFuZ2VzLlxyXG4gICAqL1xyXG4gIGxvcm9UZXh0Q2hhbmdlZEF0b20gPSBjcmVhdGVBdG9tKFwibG9yb1RleHRDaGFuZ2VkQXRvbVwiKVxyXG5cclxuICAvKipcclxuICAgKiBUaGUgTG9yb1RleHQgb2JqZWN0IHJlcHJlc2VudGVkIGJ5IHRoaXMgbW9ieC1rZXlzdG9uZSBub2RlLCBpZiBib3VuZC5cclxuICAgKiBSZXR1cm5zIHVuZGVmaW5lZCB3aGVuIHRoZSBtb2RlbCBpcyBub3QgcGFydCBvZiBhIGJvdW5kIG9iamVjdCB0cmVlLlxyXG4gICAqL1xyXG4gIEBjb21wdXRlZFxyXG4gIGdldCBsb3JvVGV4dCgpOiBMb3JvVGV4dCB8IHVuZGVmaW5lZCB7XHJcbiAgICAvLyBDaGVjayBpZiB3ZSBoYXZlIGEgYmluZGluZyBjb250ZXh0IGZpcnN0IC0gcmV0dXJuIHVuZGVmaW5lZCBpZiBub3QgYm91bmRcclxuICAgIGNvbnN0IGN0eCA9IGxvcm9CaW5kaW5nQ29udGV4dC5nZXQodGhpcylcclxuICAgIGlmIChjdHg/LmJvdW5kT2JqZWN0ID09IG51bGwpIHtcclxuICAgICAgcmV0dXJuIHVuZGVmaW5lZFxyXG4gICAgfVxyXG5cclxuICAgIHRyeSB7XHJcbiAgICAgIGNvbnN0IHBhdGggPSBnZXRQYXJlbnRUb0NoaWxkUGF0aChjdHguYm91bmRPYmplY3QsIHRoaXMpXHJcbiAgICAgIGlmICghcGF0aCkge1xyXG4gICAgICAgIHJldHVybiB1bmRlZmluZWRcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gSWYgdGhpcyBtb2RlbCBJUyB0aGUgYm91bmQgb2JqZWN0LCB0aGUgbG9yb09iamVjdCBpcyB0aGUgTG9yb1RleHRcclxuICAgICAgaWYgKHBhdGgubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgY29uc3QgbG9yb09iamVjdCA9IGN0eC5sb3JvT2JqZWN0XHJcbiAgICAgICAgaWYgKGxvcm9PYmplY3QgaW5zdGFuY2VvZiBMb3JvVGV4dCkge1xyXG4gICAgICAgICAgZ2V0T3JDcmVhdGVMb3JvQ29sbGVjdGlvbkF0b20obG9yb09iamVjdCkucmVwb3J0T2JzZXJ2ZWQoKVxyXG4gICAgICAgICAgcmV0dXJuIGxvcm9PYmplY3RcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZFxyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBPdGhlcndpc2UgcmVzb2x2ZSB0aGUgcGF0aFxyXG4gICAgICBjb25zdCBsb3JvT2JqZWN0ID0gcmVzb2x2ZUxvcm9QYXRoKGN0eC5sb3JvT2JqZWN0LCBwYXRoKVxyXG5cclxuICAgICAgaWYgKGxvcm9PYmplY3QgaW5zdGFuY2VvZiBMb3JvVGV4dCkge1xyXG4gICAgICAgIGdldE9yQ3JlYXRlTG9yb0NvbGxlY3Rpb25BdG9tKGxvcm9PYmplY3QpLnJlcG9ydE9ic2VydmVkKClcclxuICAgICAgICByZXR1cm4gbG9yb09iamVjdFxyXG4gICAgICB9XHJcbiAgICB9IGNhdGNoIHtcclxuICAgICAgLy8gUGF0aCByZXNvbHV0aW9uIGZhaWxlZCAtIHJldHVybiB1bmRlZmluZWRcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gdW5kZWZpbmVkXHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXRzIHRoZSBwbGFpbiB0ZXh0IGNvbnRlbnQuXHJcbiAgICogVGhpcyBhbHdheXMgdXNlcyB0aGUgc3RvcmVkIGRlbHRhLCB3aGljaCBpcyBrZXB0IGluIHN5bmMgd2l0aCBMb3JvLlxyXG4gICAqL1xyXG4gIEBjb21wdXRlZFxyXG4gIGdldCB0ZXh0KCk6IHN0cmluZyB7XHJcbiAgICB0aGlzLmxvcm9UZXh0Q2hhbmdlZEF0b20ucmVwb3J0T2JzZXJ2ZWQoKVxyXG5cclxuICAgIC8vIEFsd2F5cyBjb21wdXRlIGZyb20gZGVsdGEgLSBpdCdzIHRoZSBzb3VyY2Ugb2YgdHJ1dGggZm9yIHRoaXMgbW9kZWxcclxuICAgIC8vIFRoZSBkZWx0YSBpcyBrZXB0IGluIHN5bmMgd2l0aCBMb3JvIHZpYSBwYXRjaGVzXHJcbiAgICByZXR1cm4gdGhpcy5kZWx0YVRvVGV4dCh0aGlzLmRlbHRhTGlzdC5kYXRhKVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2V0cyB0aGUgY3VycmVudCBkZWx0YSAoUXVpbGwgZm9ybWF0KS5cclxuICAgKi9cclxuICBAY29tcHV0ZWRcclxuICBnZXQgY3VycmVudERlbHRhKCk6IExvcm9UZXh0RGVsdGFMaXN0IHtcclxuICAgIHRoaXMubG9yb1RleHRDaGFuZ2VkQXRvbS5yZXBvcnRPYnNlcnZlZCgpXHJcblxyXG4gICAgLy8gVHJ5IHRvIGdldCBmcm9tIGJvdW5kIExvcm9UZXh0IGZpcnN0XHJcbiAgICBjb25zdCBsb3JvVGV4dCA9IHRoaXMubG9yb1RleHRcclxuICAgIGlmIChsb3JvVGV4dCkge1xyXG4gICAgICB0cnkge1xyXG4gICAgICAgIHJldHVybiBsb3JvVGV4dC50b0RlbHRhKClcclxuICAgICAgfSBjYXRjaCB7XHJcbiAgICAgICAgLy8gZmFsbCBiYWNrIHRvIHN0b3JlZCBkZWx0YVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHRoaXMuZGVsdGFMaXN0LmRhdGFcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENvbnZlcnRzIGRlbHRhIHRvIHBsYWluIHRleHQuXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBkZWx0YVRvVGV4dChkZWx0YTogTG9yb1RleHREZWx0YUxpc3QpOiBzdHJpbmcge1xyXG4gICAgbGV0IHJlc3VsdCA9IFwiXCJcclxuICAgIGZvciAoY29uc3Qgb3Agb2YgZGVsdGEpIHtcclxuICAgICAgaWYgKFwiaW5zZXJ0XCIgaW4gb3AgJiYgdHlwZW9mIG9wLmluc2VydCA9PT0gXCJzdHJpbmdcIikge1xyXG4gICAgICAgIHJlc3VsdCArPSBvcC5pbnNlcnRcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIHJlc3VsdFxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogU2V0cyB0aGUgZGVsdGEuXHJcbiAgICovXHJcbiAgQG1vZGVsQWN0aW9uXHJcbiAgc2V0RGVsdGEoZGVsdGE6IExvcm9UZXh0RGVsdGFMaXN0KTogdm9pZCB7XHJcbiAgICB0aGlzLmRlbHRhTGlzdCA9IGZyb3plbihkZWx0YSlcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEluc2VydHMgdGV4dCBhdCB0aGUgc3BlY2lmaWVkIHBvc2l0aW9uLlxyXG4gICAqL1xyXG4gIEBtb2RlbEFjdGlvblxyXG4gIGluc2VydFRleHQoaW5kZXg6IG51bWJlciwgdGV4dDogc3RyaW5nKTogdm9pZCB7XHJcbiAgICBjb25zdCBsb3JvVGV4dCA9IHRoaXMubG9yb1RleHRcclxuICAgIGlmIChsb3JvVGV4dCkge1xyXG4gICAgICBsb3JvVGV4dC5pbnNlcnQoaW5kZXgsIHRleHQpXHJcbiAgICAgIC8vIFRoZSBiaW5kaW5nIHdpbGwgaGFuZGxlIHN5bmNpbmcgYmFja1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgLy8gRmFsbGJhY2s6IG1vZGlmeSBkZWx0YSBkaXJlY3RseVxyXG4gICAgICBjb25zdCBjdXJyZW50VGV4dCA9IHRoaXMudGV4dFxyXG4gICAgICBjb25zdCBuZXdUZXh0ID0gY3VycmVudFRleHQuc2xpY2UoMCwgaW5kZXgpICsgdGV4dCArIGN1cnJlbnRUZXh0LnNsaWNlKGluZGV4KVxyXG4gICAgICB0aGlzLmRlbHRhTGlzdCA9IGZyb3plbihbeyBpbnNlcnQ6IG5ld1RleHQgfV0pXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBEZWxldGVzIHRleHQgYXQgdGhlIHNwZWNpZmllZCByYW5nZS5cclxuICAgKi9cclxuICBAbW9kZWxBY3Rpb25cclxuICBkZWxldGVUZXh0KGluZGV4OiBudW1iZXIsIGxlbmd0aDogbnVtYmVyKTogdm9pZCB7XHJcbiAgICBjb25zdCBsb3JvVGV4dCA9IHRoaXMubG9yb1RleHRcclxuICAgIGlmIChsb3JvVGV4dCkge1xyXG4gICAgICBsb3JvVGV4dC5kZWxldGUoaW5kZXgsIGxlbmd0aClcclxuICAgICAgLy8gVGhlIGJpbmRpbmcgd2lsbCBoYW5kbGUgc3luY2luZyBiYWNrXHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICAvLyBGYWxsYmFjazogbW9kaWZ5IGRlbHRhIGRpcmVjdGx5XHJcbiAgICAgIGNvbnN0IGN1cnJlbnRUZXh0ID0gdGhpcy50ZXh0XHJcbiAgICAgIGNvbnN0IG5ld1RleHQgPSBjdXJyZW50VGV4dC5zbGljZSgwLCBpbmRleCkgKyBjdXJyZW50VGV4dC5zbGljZShpbmRleCArIGxlbmd0aClcclxuICAgICAgdGhpcy5kZWx0YUxpc3QgPSBmcm96ZW4oW3sgaW5zZXJ0OiBuZXdUZXh0IH1dKVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogSW50ZXJuYWwgYWN0aW9uIHRvIHVwZGF0ZSBkZWx0YSBmcm9tIExvcm8gc3luYy5cclxuICAgKiBAaW50ZXJuYWxcclxuICAgKi9cclxuICBAbW9kZWxBY3Rpb25cclxuICBfdXBkYXRlRGVsdGFGcm9tTG9ybyhkZWx0YTogTG9yb1RleHREZWx0YUxpc3QpOiB2b2lkIHtcclxuICAgIHRoaXMuZGVsdGFMaXN0ID0gZnJvemVuKGRlbHRhKVxyXG4gIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIFR5cGUgZm9yIExvcm9UZXh0TW9kZWwgZm9yIHVzZSB3aXRoIHRQcm9wLlxyXG4gKi9cclxuZXhwb3J0IGNvbnN0IGxvcm9UZXh0TW9kZWxUeXBlID0gdHlwZXMubW9kZWwoTG9yb1RleHRNb2RlbClcclxuXHJcbi8qKlxyXG4gKiBDaGVja3MgaWYgYSBzbmFwc2hvdCBpcyBhIExvcm9UZXh0TW9kZWwgc25hcHNob3QuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gaXNMb3JvVGV4dE1vZGVsU25hcHNob3QodmFsdWU6IHVua25vd24pOiB2YWx1ZSBpcyBTbmFwc2hvdE91dE9mPExvcm9UZXh0TW9kZWw+IHtcclxuICByZXR1cm4gZ2V0U25hcHNob3RNb2RlbFR5cGUodmFsdWUpID09PSBsb3JvVGV4dE1vZGVsSWRcclxufVxyXG4iLCJpbXBvcnQgeyBpc0NvbnRhaW5lciwgTG9yb01hcCwgTG9yb01vdmFibGVMaXN0LCBMb3JvVGV4dCB9IGZyb20gXCJsb3JvLWNyZHRcIlxuaW1wb3J0IHsgbW9kZWxTbmFwc2hvdE91dFdpdGhNZXRhZGF0YSwgdG9Gcm96ZW5TbmFwc2hvdCB9IGZyb20gXCJtb2J4LWtleXN0b25lXCJcbmltcG9ydCB0eXBlIHsgUGxhaW5WYWx1ZSB9IGZyb20gXCIuLi9wbGFpblR5cGVzXCJcbmltcG9ydCB7IGZhaWx1cmUgfSBmcm9tIFwiLi4vdXRpbHMvZXJyb3JcIlxuaW1wb3J0IHsgdHlwZSBCaW5kYWJsZUxvcm9Db250YWluZXIgfSBmcm9tIFwiLi4vdXRpbHMvaXNCaW5kYWJsZUxvcm9Db250YWluZXJcIlxuaW1wb3J0IHsgTG9yb1RleHRNb2RlbCB9IGZyb20gXCIuL0xvcm9UZXh0TW9kZWxcIlxuXG50eXBlIExvcm9WYWx1ZSA9IEJpbmRhYmxlTG9yb0NvbnRhaW5lciB8IFBsYWluVmFsdWVcblxuLyoqXG4gKiBDb252ZXJ0cyBMb3JvIGRhdGEgdG8gSlNPTi1jb21wYXRpYmxlIGZvcm1hdCBmb3IgbW9ieC1rZXlzdG9uZSBzbmFwc2hvdHMuXG4gKlxuICogQHBhcmFtIHZhbHVlIFRoZSBMb3JvIHZhbHVlIHRvIGNvbnZlcnRcbiAqIEByZXR1cm5zIEpTT04tY29tcGF0aWJsZSB2YWx1ZVxuICovXG5leHBvcnQgZnVuY3Rpb24gY29udmVydExvcm9EYXRhVG9Kc29uKHZhbHVlOiBMb3JvVmFsdWUpOiBQbGFpblZhbHVlIHtcbiAgaWYgKHZhbHVlID09PSBudWxsKSB7XG4gICAgcmV0dXJuIG51bGxcbiAgfVxuXG4gIGlmICh0eXBlb2YgdmFsdWUgIT09IFwib2JqZWN0XCIpIHtcbiAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwidW5kZWZpbmVkIHZhbHVlcyBhcmUgbm90IHN1cHBvcnRlZCBieSBMb3JvXCIpXG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlIGFzIFBsYWluVmFsdWVcbiAgfVxuXG4gIGlmIChpc0NvbnRhaW5lcih2YWx1ZSkpIHtcbiAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBMb3JvTWFwKSB7XG4gICAgICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIFBsYWluVmFsdWU+ID0ge31cbiAgICAgIGZvciAoY29uc3QgW2ssIHZdIG9mIHZhbHVlLmVudHJpZXMoKSkge1xuICAgICAgICByZXN1bHRba10gPSBjb252ZXJ0TG9yb0RhdGFUb0pzb24odiBhcyBMb3JvVmFsdWUpXG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0XG4gICAgfVxuXG4gICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgTG9yb01vdmFibGVMaXN0KSB7XG4gICAgICBjb25zdCByZXN1bHQ6IFBsYWluVmFsdWVbXSA9IFtdXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHZhbHVlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGNvbnZlcnRMb3JvRGF0YVRvSnNvbih2YWx1ZS5nZXQoaSkgYXMgTG9yb1ZhbHVlKSlcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHRcbiAgICB9XG5cbiAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBMb3JvVGV4dCkge1xuICAgICAgY29uc3QgZGVsdGFzID0gdmFsdWUudG9EZWx0YSgpXG4gICAgICAvLyBSZXR1cm4gYSBMb3JvVGV4dE1vZGVsLWNvbXBhdGlibGUgc25hcHNob3RcbiAgICAgIHJldHVybiBtb2RlbFNuYXBzaG90T3V0V2l0aE1ldGFkYXRhKExvcm9UZXh0TW9kZWwsIHtcbiAgICAgICAgZGVsdGFMaXN0OiB0b0Zyb3plblNuYXBzaG90KGRlbHRhcyksXG4gICAgICB9KSBhcyB1bmtub3duIGFzIFBsYWluVmFsdWVcbiAgICB9XG5cbiAgICB0aHJvdyBmYWlsdXJlKGB1bnN1cHBvcnRlZCBiaW5kYWJsZSBMb3JvIGNvbnRhaW5lciB0eXBlYClcbiAgfVxuXG4gIC8vIFBsYWluIG9iamVjdCBvciBhcnJheVxuICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICByZXR1cm4gdmFsdWUubWFwKChpdGVtKSA9PiBjb252ZXJ0TG9yb0RhdGFUb0pzb24oaXRlbSBhcyBMb3JvVmFsdWUpKVxuICB9XG5cbiAgY29uc3QgcmVzdWx0OiBSZWNvcmQ8c3RyaW5nLCBQbGFpblZhbHVlPiA9IHt9XG4gIGZvciAoY29uc3QgW2ssIHZdIG9mIE9iamVjdC5lbnRyaWVzKHZhbHVlKSkge1xuICAgIHJlc3VsdFtrXSA9IGNvbnZlcnRMb3JvRGF0YVRvSnNvbih2IGFzIExvcm9WYWx1ZSlcbiAgfVxuXG4gIHJldHVybiByZXN1bHRcbn1cbiIsImltcG9ydCB0eXBlIHsgQ29udGFpbmVySUQsIExpc3REaWZmLCBMb3JvRG9jLCBMb3JvRXZlbnQsIE1hcERpZmYgfSBmcm9tIFwibG9yby1jcmR0XCJcbmltcG9ydCB7IGlzQ29udGFpbmVyLCBMb3JvTWFwLCBMb3JvTW92YWJsZUxpc3QsIExvcm9UZXh0IH0gZnJvbSBcImxvcm8tY3JkdFwiXG5pbXBvcnQgeyByZW1vdmUgfSBmcm9tIFwibW9ieFwiXG5pbXBvcnQge1xuICBGcm96ZW4sXG4gIGZyb21TbmFwc2hvdCxcbiAgZnJvemVuLFxuICBnZXRTbmFwc2hvdE1vZGVsSWQsXG4gIGlzRGF0YU1vZGVsLFxuICBpc0Zyb3plblNuYXBzaG90LFxuICBpc01vZGVsLFxuICBtb2RlbElkS2V5LFxuICBQYXRoLFxuICByZXNvbHZlUGF0aCxcbiAgcnVuVW5wcm90ZWN0ZWQsXG59IGZyb20gXCJtb2J4LWtleXN0b25lXCJcbmltcG9ydCB0eXBlIHsgUGxhaW5WYWx1ZSB9IGZyb20gXCIuLi9wbGFpblR5cGVzXCJcbmltcG9ydCB7IGZhaWx1cmUgfSBmcm9tIFwiLi4vdXRpbHMvZXJyb3JcIlxuaW1wb3J0IHsgY29udmVydExvcm9EYXRhVG9Kc29uIH0gZnJvbSBcIi4vY29udmVydExvcm9EYXRhVG9Kc29uXCJcblxuLy8gUmVwcmVzZW50cyB0aGUgbWFwIG9mIHBvdGVudGlhbCBvYmplY3RzIHRvIHJlY29uY2lsZSAoSUQgLT4gT2JqZWN0KVxuZXhwb3J0IHR5cGUgUmVjb25jaWxpYXRpb25NYXAgPSBNYXA8c3RyaW5nLCBvYmplY3Q+XG5cbi8qKlxuICogQXBwbGllcyBhIExvcm8gZXZlbnQgZGlyZWN0bHkgdG8gdGhlIE1vYlggbW9kZWwgdHJlZSB1c2luZyBwcm9wZXIgbXV0YXRpb25zXG4gKiAoc3BsaWNlIGZvciBhcnJheXMsIHByb3BlcnR5IGFzc2lnbm1lbnQgZm9yIG9iamVjdHMpLlxuICogVGhpcyBpcyBtb3JlIGVmZmljaWVudCB0aGFuIGNvbnZlcnRpbmcgdG8gcGF0Y2hlcyBmaXJzdC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5TG9yb0V2ZW50VG9Nb2J4KFxuICBldmVudDogTG9yb0V2ZW50LFxuICBsb3JvRG9jOiBMb3JvRG9jLFxuICBib3VuZE9iamVjdDogb2JqZWN0LFxuICByb290UGF0aDogUGF0aCxcbiAgcmVjb25jaWxpYXRpb25NYXA6IFJlY29uY2lsaWF0aW9uTWFwLFxuICBuZXdseUluc2VydGVkQ29udGFpbmVyczogU2V0PENvbnRhaW5lcklEPlxuKTogdm9pZCB7XG4gIC8vIFNraXAgZXZlbnRzIGZvciBjb250YWluZXJzIHRoYXQgd2VyZSBqdXN0IGluc2VydGVkIGFzIHBhcnQgb2YgYW5vdGhlciBjb250YWluZXJcbiAgLy8gVGhlaXIgY29udGVudCBpcyBhbHJlYWR5IGluY2x1ZGVkIGluIHRoZSBwYXJlbnQncyBjb252ZXJ0TG9yb0RhdGFUb0pzb24gY2FsbFxuICBpZiAobmV3bHlJbnNlcnRlZENvbnRhaW5lcnMuaGFzKGV2ZW50LnRhcmdldCkpIHtcbiAgICByZXR1cm5cbiAgfVxuXG4gIC8vIFJlc29sdmUgdGhlIHBhdGggcmVsYXRpdmUgdG8gdGhlIHJvb3RcbiAgY29uc3QgZXZlbnRQYXRoID0gbG9yb0RvYy5nZXRQYXRoVG9Db250YWluZXIoZXZlbnQudGFyZ2V0KVxuICBpZiAoIWV2ZW50UGF0aCkge1xuICAgIHJldHVyblxuICB9XG5cbiAgLy8gU3RyaXAgdGhlIHJvb3QgcGF0aCB0byBnZXQgcmVsYXRpdmUgcGF0aFxuICBjb25zdCByZWxhdGl2ZVBhdGggPSByZXNvbHZlRXZlbnRQYXRoKGV2ZW50UGF0aCwgcm9vdFBhdGgpXG4gIGlmIChyZWxhdGl2ZVBhdGggPT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVyblxuICB9XG5cbiAgY29uc3QgeyB2YWx1ZTogdGFyZ2V0IH0gPSByZXNvbHZlUGF0aChib3VuZE9iamVjdCwgcmVsYXRpdmVQYXRoKVxuXG4gIGlmICghdGFyZ2V0KSB7XG4gICAgdGhyb3cgZmFpbHVyZShgY2Fubm90IHJlc29sdmUgcGF0aCAke0pTT04uc3RyaW5naWZ5KHJlbGF0aXZlUGF0aCl9YClcbiAgfVxuXG4gIC8vIFdyYXAgaW4gcnVuVW5wcm90ZWN0ZWQgc2luY2Ugd2UncmUgbW9kaWZ5aW5nIHRoZSB0cmVlIGZyb20gb3V0c2lkZSBhIG1vZGVsIGFjdGlvblxuICBydW5VbnByb3RlY3RlZCgoKSA9PiB7XG4gICAgY29uc3QgZGlmZiA9IGV2ZW50LmRpZmZcbiAgICBpZiAoZGlmZi50eXBlID09PSBcIm1hcFwiKSB7XG4gICAgICBhcHBseU1hcEV2ZW50VG9Nb2J4KGRpZmYsIGxvcm9Eb2MsIGV2ZW50LnRhcmdldCwgdGFyZ2V0LCByZWNvbmNpbGlhdGlvbk1hcClcbiAgICB9IGVsc2UgaWYgKGRpZmYudHlwZSA9PT0gXCJsaXN0XCIpIHtcbiAgICAgIGFwcGx5TGlzdEV2ZW50VG9Nb2J4KFxuICAgICAgICBkaWZmLFxuICAgICAgICBsb3JvRG9jLFxuICAgICAgICBldmVudC50YXJnZXQsXG4gICAgICAgIHRhcmdldCxcbiAgICAgICAgcmVjb25jaWxpYXRpb25NYXAsXG4gICAgICAgIG5ld2x5SW5zZXJ0ZWRDb250YWluZXJzXG4gICAgICApXG4gICAgfSBlbHNlIGlmIChkaWZmLnR5cGUgPT09IFwidGV4dFwiKSB7XG4gICAgICBhcHBseVRleHRFdmVudFRvTW9ieChsb3JvRG9jLCBldmVudC50YXJnZXQsIHRhcmdldClcbiAgICB9XG4gIH0pXG59XG5cbmZ1bmN0aW9uIHByb2Nlc3NEZWxldGVkVmFsdWUodmFsOiB1bmtub3duLCByZWNvbmNpbGlhdGlvbk1hcDogUmVjb25jaWxpYXRpb25NYXApIHtcbiAgLy8gSGFuZGxlIGJvdGggTW9kZWwgYW5kIERhdGFNb2RlbCBpbnN0YW5jZXNcbiAgaWYgKGlzTW9kZWwodmFsKSB8fCBpc0RhdGFNb2RlbCh2YWwpKSB7XG4gICAgY29uc3QgaWQgPSBtb2RlbElkS2V5IGluIHZhbCA/IHZhbFttb2RlbElkS2V5XSA6IHVuZGVmaW5lZFxuICAgIGlmIChpZCkge1xuICAgICAgcmVjb25jaWxpYXRpb25NYXAuc2V0KGlkLCB2YWwpXG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIHJldml2ZVZhbHVlKGpzb25WYWx1ZTogdW5rbm93biwgcmVjb25jaWxpYXRpb25NYXA6IFJlY29uY2lsaWF0aW9uTWFwKTogdW5rbm93biB7XG4gIC8vIEhhbmRsZSBwcmltaXRpdmVzXG4gIGlmIChqc29uVmFsdWUgPT09IG51bGwgfHwgdHlwZW9mIGpzb25WYWx1ZSAhPT0gXCJvYmplY3RcIikge1xuICAgIHJldHVybiBqc29uVmFsdWVcbiAgfVxuXG4gIC8vIEhhbmRsZSBmcm96ZW5cbiAgaWYgKGlzRnJvemVuU25hcHNob3QoanNvblZhbHVlKSkge1xuICAgIHJldHVybiBmcm96ZW4oanNvblZhbHVlLmRhdGEpXG4gIH1cblxuICAvLyBJZiB3ZSBoYXZlIGEgcmVjb25jaWxpYXRpb24gbWFwIGFuZCB0aGUgdmFsdWUgbG9va3MgbGlrZSBhIG1vZGVsIHdpdGggYW4gSUQsIGNoZWNrIGlmIHdlIGhhdmUgaXRcbiAgaWYgKHJlY29uY2lsaWF0aW9uTWFwKSB7XG4gICAgY29uc3QgbW9kZWxJZCA9IGdldFNuYXBzaG90TW9kZWxJZChqc29uVmFsdWUpXG4gICAgaWYgKG1vZGVsSWQpIHtcbiAgICAgIGNvbnN0IGV4aXN0aW5nID0gcmVjb25jaWxpYXRpb25NYXAuZ2V0KG1vZGVsSWQpXG4gICAgICBpZiAoZXhpc3RpbmcpIHtcbiAgICAgICAgcmVjb25jaWxpYXRpb25NYXAuZGVsZXRlKG1vZGVsSWQpXG4gICAgICAgIHJldHVybiBleGlzdGluZ1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmcm9tU25hcHNob3QoanNvblZhbHVlKVxufVxuXG5mdW5jdGlvbiBhcHBseU1hcEV2ZW50VG9Nb2J4KFxuICBkaWZmOiBNYXBEaWZmLFxuICBsb3JvRG9jOiBMb3JvRG9jLFxuICBjb250YWluZXJUYXJnZXQ6IENvbnRhaW5lcklELFxuICB0YXJnZXQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuICByZWNvbmNpbGlhdGlvbk1hcDogUmVjb25jaWxpYXRpb25NYXBcbik6IHZvaWQge1xuICBjb25zdCBjb250YWluZXIgPSBsb3JvRG9jLmdldENvbnRhaW5lckJ5SWQoY29udGFpbmVyVGFyZ2V0KVxuXG4gIGlmICghY29udGFpbmVyIHx8ICEoY29udGFpbmVyIGluc3RhbmNlb2YgTG9yb01hcCkpIHtcbiAgICB0aHJvdyBmYWlsdXJlKGAke2NvbnRhaW5lclRhcmdldH0gd2FzIG5vdCBhIExvcm8gbWFwYClcbiAgfVxuXG4gIC8vIFByb2Nlc3MgYWRkaXRpb25zIGFuZCB1cGRhdGVzIGZyb20gZGlmZi51cGRhdGVkXG4gIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKGRpZmYudXBkYXRlZCkpIHtcbiAgICBjb25zdCBsb3JvVmFsdWUgPSBjb250YWluZXIuZ2V0KGtleSlcblxuICAgIGlmIChsb3JvVmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgLy8gS2V5IHdhcyBkZWxldGVkIChMb3JvIHJldHVybnMgdW5kZWZpbmVkIGZvciBkZWxldGVkIGtleXMpXG4gICAgICBpZiAoa2V5IGluIHRhcmdldCkge1xuICAgICAgICBwcm9jZXNzRGVsZXRlZFZhbHVlKHRhcmdldFtrZXldLCByZWNvbmNpbGlhdGlvbk1hcClcbiAgICAgICAgLy8gVXNlIE1vYlgncyByZW1vdmUgdG8gcHJvcGVybHkgZGVsZXRlIHRoZSBrZXkgZnJvbSB0aGUgb2JzZXJ2YWJsZSBvYmplY3RcbiAgICAgICAgaWYgKGlzTW9kZWwodGFyZ2V0KSkge1xuICAgICAgICAgIHJlbW92ZSh0YXJnZXQuJCwga2V5KVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJlbW92ZSh0YXJnZXQsIGtleSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBLZXkgd2FzIGFkZGVkIG9yIHVwZGF0ZWRcbiAgICAgIGlmIChrZXkgaW4gdGFyZ2V0KSB7XG4gICAgICAgIHByb2Nlc3NEZWxldGVkVmFsdWUodGFyZ2V0W2tleV0sIHJlY29uY2lsaWF0aW9uTWFwKVxuICAgICAgfVxuICAgICAgY29uc3QganNvblZhbHVlID0gY29udmVydExvcm9EYXRhVG9Kc29uKGxvcm9WYWx1ZSBhcyBQbGFpblZhbHVlKVxuICAgICAgdGFyZ2V0W2tleV0gPSByZXZpdmVWYWx1ZShqc29uVmFsdWUsIHJlY29uY2lsaWF0aW9uTWFwKVxuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBhcHBseUxpc3RFdmVudFRvTW9ieChcbiAgZGlmZjogTGlzdERpZmYsXG4gIGxvcm9Eb2M6IExvcm9Eb2MsXG4gIGNvbnRhaW5lclRhcmdldDogQ29udGFpbmVySUQsXG4gIHRhcmdldDogdW5rbm93bltdLFxuICByZWNvbmNpbGlhdGlvbk1hcDogUmVjb25jaWxpYXRpb25NYXAsXG4gIG5ld2x5SW5zZXJ0ZWRDb250YWluZXJzOiBTZXQ8Q29udGFpbmVySUQ+XG4pOiB2b2lkIHtcbiAgY29uc3QgY29udGFpbmVyID0gbG9yb0RvYy5nZXRDb250YWluZXJCeUlkKGNvbnRhaW5lclRhcmdldClcblxuICBpZiAoIWNvbnRhaW5lciB8fCAhKGNvbnRhaW5lciBpbnN0YW5jZW9mIExvcm9Nb3ZhYmxlTGlzdCkpIHtcbiAgICB0aHJvdyBmYWlsdXJlKGAke2NvbnRhaW5lclRhcmdldH0gd2FzIG5vdCBhIExvcm8gbW92YWJsZSBsaXN0YClcbiAgfVxuXG4gIC8vIFByb2Nlc3MgZGVsdGEgb3BlcmF0aW9ucyBpbiBvcmRlclxuICBsZXQgY3VycmVudEluZGV4ID0gMFxuXG4gIGZvciAoY29uc3QgY2hhbmdlIG9mIGRpZmYuZGlmZikge1xuICAgIGlmIChjaGFuZ2UucmV0YWluKSB7XG4gICAgICBjdXJyZW50SW5kZXggKz0gY2hhbmdlLnJldGFpblxuICAgIH1cblxuICAgIGlmIChjaGFuZ2UuZGVsZXRlKSB7XG4gICAgICAvLyBDYXB0dXJlIGRlbGV0ZWQgaXRlbXMgZm9yIHJlY29uY2lsaWF0aW9uXG4gICAgICBjb25zdCBkZWxldGVkSXRlbXMgPSB0YXJnZXQuc2xpY2UoY3VycmVudEluZGV4LCBjdXJyZW50SW5kZXggKyBjaGFuZ2UuZGVsZXRlKVxuICAgICAgZGVsZXRlZEl0ZW1zLmZvckVhY2goKGl0ZW0pID0+IHtcbiAgICAgICAgcHJvY2Vzc0RlbGV0ZWRWYWx1ZShpdGVtLCByZWNvbmNpbGlhdGlvbk1hcClcbiAgICAgIH0pXG5cbiAgICAgIC8vIERlbGV0ZSBpdGVtcyBhdCBjdXJyZW50IHBvc2l0aW9uXG4gICAgICB0YXJnZXQuc3BsaWNlKGN1cnJlbnRJbmRleCwgY2hhbmdlLmRlbGV0ZSlcbiAgICB9XG5cbiAgICBpZiAoY2hhbmdlLmluc2VydCkge1xuICAgICAgLy8gSW5zZXJ0IGl0ZW1zIGF0IGN1cnJlbnQgcG9zaXRpb25cbiAgICAgIGNvbnN0IGluc2VydGVkSXRlbXMgPSBjaGFuZ2UuaW5zZXJ0XG4gICAgICBjb25zdCB2YWx1ZXMgPSBpbnNlcnRlZEl0ZW1zLm1hcCgobG9yb1ZhbHVlKSA9PiB7XG4gICAgICAgIC8vIFRyYWNrIGNvbnRhaW5lciBJRHMgdG8gYXZvaWQgZG91YmxlLXByb2Nlc3NpbmcgdGhlaXIgZXZlbnRzXG4gICAgICAgIC8vIFdoZW4gYSBjb250YWluZXIgd2l0aCBkYXRhIGlzIGluc2VydGVkLCBMb3JvIGZpcmVzIGV2ZW50cyBmb3IgYm90aFxuICAgICAgICAvLyB0aGUgY29udGFpbmVyIGluc2VydCBhbmQgdGhlIGNvbnRhaW5lcidzIGNvbnRlbnQsIGJ1dCB0aGUgY29udGVudFxuICAgICAgICAvLyBpcyBhbHJlYWR5IGluY2x1ZGVkIGluIGNvbnZlcnRMb3JvRGF0YVRvSnNvblxuICAgICAgICBpZiAoaXNDb250YWluZXIobG9yb1ZhbHVlKSkge1xuICAgICAgICAgIG5ld2x5SW5zZXJ0ZWRDb250YWluZXJzLmFkZChsb3JvVmFsdWUuaWQpXG4gICAgICAgICAgLy8gQWxzbyByZWN1cnNpdmVseSB0cmFjayBhbnkgbmVzdGVkIGNvbnRhaW5lcnNcbiAgICAgICAgICBjb2xsZWN0TmVzdGVkQ29udGFpbmVySWRzKGxvcm9WYWx1ZSwgbmV3bHlJbnNlcnRlZENvbnRhaW5lcnMpXG4gICAgICAgIH1cbiAgICAgICAgY29uc3QganNvblZhbHVlID0gY29udmVydExvcm9EYXRhVG9Kc29uKGxvcm9WYWx1ZSBhcyBQbGFpblZhbHVlKVxuICAgICAgICByZXR1cm4gcmV2aXZlVmFsdWUoanNvblZhbHVlLCByZWNvbmNpbGlhdGlvbk1hcClcbiAgICAgIH0pXG5cbiAgICAgIHRhcmdldC5zcGxpY2UoY3VycmVudEluZGV4LCAwLCAuLi52YWx1ZXMpXG4gICAgICBjdXJyZW50SW5kZXggKz0gdmFsdWVzLmxlbmd0aFxuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBhcHBseVRleHRFdmVudFRvTW9ieChcbiAgbG9yb0RvYzogTG9yb0RvYyxcbiAgY29udGFpbmVyVGFyZ2V0OiBDb250YWluZXJJRCxcbiAgdGFyZ2V0OiB7IGRlbHRhTGlzdD86IEZyb3plbjx1bmtub3duW10+IH1cbik6IHZvaWQge1xuICBjb25zdCBjb250YWluZXIgPSBsb3JvRG9jLmdldENvbnRhaW5lckJ5SWQoY29udGFpbmVyVGFyZ2V0KVxuXG4gIGlmICghY29udGFpbmVyIHx8ICEoY29udGFpbmVyIGluc3RhbmNlb2YgTG9yb1RleHQpKSB7XG4gICAgdGhyb3cgZmFpbHVyZShgJHtjb250YWluZXJUYXJnZXR9IHdhcyBub3QgYSBMb3JvIHRleHQgY29udGFpbmVyYClcbiAgfVxuXG4gIC8vIExvcm9UZXh0TW9kZWwgaGFzIGRlbHRhTGlzdCBhcyBhIHNpbmdsZSBGcm96ZW48TG9yb1RleHREZWx0YUxpc3Q+LCBub3QgYW4gYXJyYXlcbiAgLy8gUmVwbGFjZSBpdCB3aXRoIHRoZSBjdXJyZW50IGRlbHRhIGZyb20gdGhlIExvcm9UZXh0XG4gIGlmICghKFwiZGVsdGFMaXN0XCIgaW4gdGFyZ2V0KSkge1xuICAgIHRocm93IGZhaWx1cmUoXCJ0YXJnZXQgZG9lcyBub3QgaGF2ZSBhIGRlbHRhTGlzdCBwcm9wZXJ0eSAtIGV4cGVjdGVkIExvcm9UZXh0TW9kZWxcIilcbiAgfVxuICB0YXJnZXQuZGVsdGFMaXN0ID0gZnJvemVuKGNvbnRhaW5lci50b0RlbHRhKCkpXG59XG5cbi8qKlxuICogUmVjdXJzaXZlbHkgY29sbGVjdHMgYWxsIGNvbnRhaW5lciBJRHMgZnJvbSBhIExvcm8gY29udGFpbmVyLlxuICogVGhpcyBpcyB1c2VkIHRvIHRyYWNrIGNvbnRhaW5lcnMgdGhhdCBoYXZlIGJlZW4gaW5zZXJ0ZWQgYW5kIHNob3VsZCBub3RcbiAqIGhhdmUgdGhlaXIgZXZlbnRzIHByb2Nlc3NlZCBhZ2FpbiAoc2luY2UgdGhlaXIgY29udGVudCB3YXMgYWxyZWFkeSBpbmNsdWRlZFxuICogaW4gdGhlIHBhcmVudCdzIGNvbnZlcnRMb3JvRGF0YVRvSnNvbiBjYWxsKS5cbiAqL1xuZnVuY3Rpb24gY29sbGVjdE5lc3RlZENvbnRhaW5lcklkcyhjb250YWluZXI6IHVua25vd24sIGNvbnRhaW5lcklkczogU2V0PENvbnRhaW5lcklEPik6IHZvaWQge1xuICBpZiAoIWlzQ29udGFpbmVyKGNvbnRhaW5lcikpIHtcbiAgICByZXR1cm5cbiAgfVxuXG4gIC8vIEFkZCB0aGlzIGNvbnRhaW5lcidzIElEXG4gIGNvbnRhaW5lcklkcy5hZGQoY29udGFpbmVyLmlkKVxuXG4gIC8vIEhhbmRsZSBMb3JvTWFwIC0gaXRlcmF0ZSBvdmVyIHZhbHVlc1xuICBpZiAoY29udGFpbmVyIGluc3RhbmNlb2YgTG9yb01hcCkge1xuICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKGNvbnRhaW5lci50b0pTT04oKSkpIHtcbiAgICAgIGNvbnN0IHZhbHVlID0gY29udGFpbmVyLmdldChrZXkpXG4gICAgICBjb2xsZWN0TmVzdGVkQ29udGFpbmVySWRzKHZhbHVlLCBjb250YWluZXJJZHMpXG4gICAgfVxuICB9XG5cbiAgLy8gSGFuZGxlIExvcm9Nb3ZhYmxlTGlzdCAtIGl0ZXJhdGUgb3ZlciBpdGVtc1xuICBpZiAoY29udGFpbmVyIGluc3RhbmNlb2YgTG9yb01vdmFibGVMaXN0KSB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb250YWluZXIubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbGxlY3ROZXN0ZWRDb250YWluZXJJZHMoY29udGFpbmVyLmdldChpKSwgY29udGFpbmVySWRzKVxuICAgIH1cbiAgfVxuXG4gIC8vIExvcm9UZXh0IGRvZXNuJ3QgY29udGFpbiBuZXN0ZWQgY29udGFpbmVyc1xufVxuXG4vKipcbiAqIFJlc29sdmVzIHRoZSBwYXRoIGZyb20gYSBMb3JvIGV2ZW50IHRvIGEgbW9ieC1rZXlzdG9uZSBwYXRoLlxuICogVGhlIGV2ZW50IHBhdGggaXMgdGhlIHBhdGggZnJvbSB0aGUgZG9jIHJvb3QgdG8gdGhlIGNvbnRhaW5lciB0aGF0IGVtaXR0ZWQgdGhlIGV2ZW50LlxuICogV2UgbmVlZCB0byBzdHJpcCB0aGUgcGF0aCBvZiBvdXIgcm9vdCBjb250YWluZXIgdG8gZ2V0IGEgcGF0aCByZWxhdGl2ZSB0byBvdXIgYm91bmQgb2JqZWN0LlxuICovXG5mdW5jdGlvbiByZXNvbHZlRXZlbnRQYXRoKGV2ZW50UGF0aDogUGF0aCwgcm9vdFBhdGg6IFBhdGgpOiBQYXRoIHwgdW5kZWZpbmVkIHtcbiAgaWYgKGV2ZW50UGF0aC5sZW5ndGggPCByb290UGF0aC5sZW5ndGgpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkXG4gIH1cblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHJvb3RQYXRoLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGV2ZW50UGF0aFtpXSAhPT0gcm9vdFBhdGhbaV0pIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWRcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZXZlbnRQYXRoLnNsaWNlKHJvb3RQYXRoLmxlbmd0aCkgYXMgUGF0aFxufVxuIiwiaW1wb3J0IHsgTG9yb01hcCwgTG9yb01vdmFibGVMaXN0LCBMb3JvVGV4dCB9IGZyb20gXCJsb3JvLWNyZHRcIlxuXG4vKipcbiAqIEEgYmluZGFibGUgTG9ybyBjb250YWluZXIgKE1hcCwgTW92YWJsZUxpc3QsIG9yIFRleHQpLlxuICovXG5leHBvcnQgdHlwZSBCaW5kYWJsZUxvcm9Db250YWluZXIgPSBMb3JvTWFwIHwgTG9yb01vdmFibGVMaXN0IHwgTG9yb1RleHRcblxuLyoqXG4gKiBDaGVja3MgaWYgYSB2YWx1ZSBpcyBhIGJpbmRhYmxlIExvcm8gY29udGFpbmVyLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNCaW5kYWJsZUxvcm9Db250YWluZXIodmFsdWU6IHVua25vd24pOiB2YWx1ZSBpcyBCaW5kYWJsZUxvcm9Db250YWluZXIge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBMb3JvTWFwIHx8IHZhbHVlIGluc3RhbmNlb2YgTG9yb01vdmFibGVMaXN0IHx8IHZhbHVlIGluc3RhbmNlb2YgTG9yb1RleHRcbn1cbiIsImltcG9ydCB0eXBlIHsgTG9yb01hcCwgTG9yb01vdmFibGVMaXN0IH0gZnJvbSBcImxvcm8tY3JkdFwiXG5cbnR5cGUgTG9yb0NvbnRhaW5lciA9IExvcm9NYXAgfCBMb3JvTW92YWJsZUxpc3RcblxuLyoqXG4gKiBXZWFrTWFwIHRoYXQgdHJhY2tzIHdoaWNoIHNuYXBzaG90IGVhY2ggTG9ybyBjb250YWluZXIgd2FzIGxhc3Qgc3luY2VkIGZyb20uXG4gKiBUaGlzIGlzIHVzZWQgZHVyaW5nIHJlY29uY2lsaWF0aW9uIHRvIHNraXAgY29udGFpbmVycyB0aGF0IGFyZSBhbHJlYWR5IHVwLXRvLWRhdGUuXG4gKlxuICogVGhlIGtleSBpcyB0aGUgTG9ybyBjb250YWluZXIgKExvcm9NYXAgb3IgTG9yb01vdmFibGVMaXN0KS5cbiAqIFRoZSB2YWx1ZSBpcyB0aGUgc25hcHNob3QgKHBsYWluIG9iamVjdCBvciBhcnJheSkgdGhhdCB3YXMgbGFzdCBzeW5jZWQgdG8gaXQuXG4gKi9cbmV4cG9ydCBjb25zdCBsb3JvQ29udGFpbmVyVG9TbmFwc2hvdCA9IG5ldyBXZWFrTWFwPExvcm9Db250YWluZXIsIHVua25vd24+KClcblxuLyoqXG4gKiBVcGRhdGVzIHRoZSBzbmFwc2hvdCB0cmFja2luZyBmb3IgYSBMb3JvIGNvbnRhaW5lci5cbiAqIENhbGwgdGhpcyBhZnRlciBzeW5jaW5nIGEgc25hcHNob3QgdG8gYSBMb3JvIGNvbnRhaW5lci5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldExvcm9Db250YWluZXJTbmFwc2hvdChjb250YWluZXI6IExvcm9Db250YWluZXIsIHNuYXBzaG90OiB1bmtub3duKTogdm9pZCB7XG4gIGxvcm9Db250YWluZXJUb1NuYXBzaG90LnNldChjb250YWluZXIsIHNuYXBzaG90KVxufVxuXG4vKipcbiAqIEdldHMgdGhlIGxhc3Qgc3luY2VkIHNuYXBzaG90IGZvciBhIExvcm8gY29udGFpbmVyLlxuICogUmV0dXJucyB1bmRlZmluZWQgaWYgdGhlIGNvbnRhaW5lciBoYXMgbmV2ZXIgYmVlbiBzeW5jZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRMb3JvQ29udGFpbmVyU25hcHNob3QoY29udGFpbmVyOiBMb3JvQ29udGFpbmVyKTogdW5rbm93biB7XG4gIHJldHVybiBsb3JvQ29udGFpbmVyVG9TbmFwc2hvdC5nZXQoY29udGFpbmVyKVxufVxuXG4vKipcbiAqIENoZWNrcyBpZiBhIExvcm8gY29udGFpbmVyIGlzIHVwLXRvLWRhdGUgd2l0aCB0aGUgZ2l2ZW4gc25hcHNob3QuXG4gKiBVc2VzIHJlZmVyZW5jZSBlcXVhbGl0eSB0byBjaGVjayBpZiB0aGUgc25hcHNob3QgaXMgdGhlIHNhbWUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0xvcm9Db250YWluZXJVcFRvRGF0ZShjb250YWluZXI6IExvcm9Db250YWluZXIsIHNuYXBzaG90OiB1bmtub3duKTogYm9vbGVhbiB7XG4gIHJldHVybiBsb3JvQ29udGFpbmVyVG9TbmFwc2hvdC5nZXQoY29udGFpbmVyKSA9PT0gc25hcHNob3Rcbn1cbiIsImltcG9ydCB0eXBlIHsgRGVsdGEgfSBmcm9tIFwibG9yby1jcmR0XCJcbmltcG9ydCB7IExvcm9NYXAsIExvcm9Nb3ZhYmxlTGlzdCwgTG9yb1RleHQgfSBmcm9tIFwibG9yby1jcmR0XCJcbmltcG9ydCB7IGZyb3plbktleSwgaXNGcm96ZW5TbmFwc2hvdCB9IGZyb20gXCJtb2J4LWtleXN0b25lXCJcbmltcG9ydCB0eXBlIHsgUGxhaW5BcnJheSwgUGxhaW5PYmplY3QsIFBsYWluUHJpbWl0aXZlLCBQbGFpblZhbHVlIH0gZnJvbSBcIi4uL3BsYWluVHlwZXNcIlxuaW1wb3J0IHtcbiAgdHlwZSBCaW5kYWJsZUxvcm9Db250YWluZXIsXG4gIGlzQmluZGFibGVMb3JvQ29udGFpbmVyLFxufSBmcm9tIFwiLi4vdXRpbHMvaXNCaW5kYWJsZUxvcm9Db250YWluZXJcIlxuaW1wb3J0IHsgaXNMb3JvVGV4dE1vZGVsU25hcHNob3QgfSBmcm9tIFwiLi9Mb3JvVGV4dE1vZGVsXCJcbmltcG9ydCB7IGlzTG9yb0NvbnRhaW5lclVwVG9EYXRlLCBzZXRMb3JvQ29udGFpbmVyU25hcHNob3QgfSBmcm9tIFwiLi9sb3JvU25hcHNob3RUcmFja2luZ1wiXG5cbnR5cGUgTG9yb1ZhbHVlID0gQmluZGFibGVMb3JvQ29udGFpbmVyIHwgUGxhaW5WYWx1ZVxuXG4vKipcbiAqIE9wdGlvbnMgZm9yIGFwcGx5aW5nIEpTT04gZGF0YSB0byBMb3JvIGRhdGEgc3RydWN0dXJlcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBcHBseUpzb25Ub0xvcm9PcHRpb25zIHtcbiAgLyoqXG4gICAqIFRoZSBtb2RlIHRvIHVzZSB3aGVuIGFwcGx5aW5nIEpTT04gZGF0YSB0byBMb3JvIGRhdGEgc3RydWN0dXJlcy5cbiAgICogLSBgYWRkYDogQ3JlYXRlcyBuZXcgTG9ybyBjb250YWluZXJzIGZvciBvYmplY3RzL2FycmF5cyAoZGVmYXVsdCwgYmFja3dhcmRzIGNvbXBhdGlibGUpXG4gICAqIC0gYG1lcmdlYDogUmVjdXJzaXZlbHkgbWVyZ2VzIHZhbHVlcywgcHJlc2VydmluZyBleGlzdGluZyBjb250YWluZXIgcmVmZXJlbmNlcyB3aGVyZSBwb3NzaWJsZVxuICAgKi9cbiAgbW9kZT86IFwiYWRkXCIgfCBcIm1lcmdlXCJcbn1cblxuZnVuY3Rpb24gaXNQbGFpblByaW1pdGl2ZSh2OiBQbGFpblZhbHVlKTogdiBpcyBQbGFpblByaW1pdGl2ZSB7XG4gIGNvbnN0IHQgPSB0eXBlb2YgdlxuICByZXR1cm4gdCA9PT0gXCJzdHJpbmdcIiB8fCB0ID09PSBcIm51bWJlclwiIHx8IHQgPT09IFwiYm9vbGVhblwiIHx8IHYgPT09IG51bGwgfHwgdiA9PT0gdW5kZWZpbmVkXG59XG5cbmZ1bmN0aW9uIGlzUGxhaW5BcnJheSh2OiBQbGFpblZhbHVlKTogdiBpcyBQbGFpbkFycmF5IHtcbiAgcmV0dXJuIEFycmF5LmlzQXJyYXkodilcbn1cblxuZnVuY3Rpb24gaXNQbGFpbk9iamVjdCh2OiBQbGFpblZhbHVlKTogdiBpcyBQbGFpbk9iamVjdCB7XG4gIHJldHVybiB0eXBlb2YgdiA9PT0gXCJvYmplY3RcIiAmJiB2ICE9PSBudWxsICYmICFBcnJheS5pc0FycmF5KHYpXG59XG5cbi8qKlxuICogRXh0cmFjdHMgZGVsdGEgYXJyYXkgZnJvbSBhIExvcm9UZXh0TW9kZWwgc25hcHNob3QncyBkZWx0YSBmaWVsZC5cbiAqIFRoZSBkZWx0YSBmaWVsZCBpcyBhIGZyb3plbiBEZWx0YTxzdHJpbmc+W10gKGFycmF5IG9mIGRlbHRhIG9wZXJhdGlvbnMpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZXh0cmFjdFRleHREZWx0YUZyb21TbmFwc2hvdChkZWx0YTogdW5rbm93bik6IERlbHRhPHN0cmluZz5bXSB7XG4gIC8vIFRoZSBkZWx0YSBmaWVsZCBpcyBmcm96ZW4sIHNvIHdlIG5lZWQgdG8gZXh0cmFjdCBpdFxuICBpZiAoaXNGcm96ZW5TbmFwc2hvdDxEZWx0YTxzdHJpbmc+W10+KGRlbHRhKSkge1xuICAgIGNvbnN0IGRhdGEgPSBkZWx0YS5kYXRhXG4gICAgaWYgKEFycmF5LmlzQXJyYXkoZGF0YSkpIHtcbiAgICAgIHJldHVybiBkYXRhXG4gICAgfVxuICB9XG5cbiAgLy8gSGFuZGxlIHBsYWluIGRlbHRhIGFycmF5IChub3Qgd3JhcHBlZCBpbiBmcm96ZW4pXG4gIGlmIChBcnJheS5pc0FycmF5KGRlbHRhKSkge1xuICAgIHJldHVybiBkZWx0YSBhcyBEZWx0YTxzdHJpbmc+W11cbiAgfVxuXG4gIHJldHVybiBbXVxufVxuXG4vKipcbiAqIEFwcGxpZXMgZGVsdGEgb3BlcmF0aW9ucyB0byBhIExvcm9UZXh0IHVzaW5nIGluc2VydC9tYXJrIEFQSXMuXG4gKiBUaGlzIHdvcmtzIG9uIGJvdGggYXR0YWNoZWQgYW5kIGRldGFjaGVkIGNvbnRhaW5lcnMuXG4gKlxuICogU3RyYXRlZ3k6IEluc2VydCBhbGwgdGV4dCBmaXJzdCwgdGhlbiBhcHBseSBtYXJrcy4gVGhpcyBhdm9pZHMgbWFyayBpbmhlcml0YW5jZVxuICogaXNzdWVzIHdoZW4gaW5zZXJ0aW5nIGF0IHRoZSBib3VuZGFyeSBvZiBhIG1hcmtlZCByZWdpb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcHBseURlbHRhVG9Mb3JvVGV4dCh0ZXh0OiBMb3JvVGV4dCwgZGVsdGFzOiBEZWx0YTxzdHJpbmc+W10pOiB2b2lkIHtcbiAgLy8gUGhhc2UgMTogSW5zZXJ0IGFsbCB0ZXh0IGNvbnRlbnRcbiAgbGV0IHBvc2l0aW9uID0gMFxuICBjb25zdCBtYXJrT3BlcmF0aW9uczogQXJyYXk8e1xuICAgIHN0YXJ0OiBudW1iZXJcbiAgICBlbmQ6IG51bWJlclxuICAgIGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+XG4gIH0+ID0gW11cblxuICBmb3IgKGNvbnN0IGRlbHRhIG9mIGRlbHRhcykge1xuICAgIGlmIChkZWx0YS5pbnNlcnQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgY29uc3QgY29udGVudCA9IGRlbHRhLmluc2VydFxuICAgICAgdGV4dC5pbnNlcnQocG9zaXRpb24sIGNvbnRlbnQpXG5cbiAgICAgIC8vIENvbGxlY3QgbWFyayBvcGVyYXRpb25zIHRvIGFwcGx5IGxhdGVyXG4gICAgICBpZiAoZGVsdGEuYXR0cmlidXRlcyAmJiBPYmplY3Qua2V5cyhkZWx0YS5hdHRyaWJ1dGVzKS5sZW5ndGggPiAwKSB7XG4gICAgICAgIG1hcmtPcGVyYXRpb25zLnB1c2goe1xuICAgICAgICAgIHN0YXJ0OiBwb3NpdGlvbixcbiAgICAgICAgICBlbmQ6IHBvc2l0aW9uICsgY29udGVudC5sZW5ndGgsXG4gICAgICAgICAgYXR0cmlidXRlczogZGVsdGEuYXR0cmlidXRlcyxcbiAgICAgICAgfSlcbiAgICAgIH1cblxuICAgICAgcG9zaXRpb24gKz0gY29udGVudC5sZW5ndGhcbiAgICB9IGVsc2UgaWYgKGRlbHRhLnJldGFpbikge1xuICAgICAgcG9zaXRpb24gKz0gZGVsdGEucmV0YWluXG4gICAgfSBlbHNlIGlmIChkZWx0YS5kZWxldGUpIHtcbiAgICAgIHRleHQuZGVsZXRlKHBvc2l0aW9uLCBkZWx0YS5kZWxldGUpXG4gICAgfVxuICB9XG5cbiAgLy8gUGhhc2UgMjogQXBwbHkgYWxsIG1hcmtzIGFmdGVyIHRleHQgaXMgaW5zZXJ0ZWRcbiAgZm9yIChjb25zdCBvcCBvZiBtYXJrT3BlcmF0aW9ucykge1xuICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKG9wLmF0dHJpYnV0ZXMpKSB7XG4gICAgICB0ZXh0Lm1hcmsoeyBzdGFydDogb3Auc3RhcnQsIGVuZDogb3AuZW5kIH0sIGtleSwgdmFsdWUpXG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogQ29udmVydHMgYSBwbGFpbiB2YWx1ZSB0byBhIExvcm8gZGF0YSBzdHJ1Y3R1cmUuXG4gKiBPYmplY3RzIGFyZSBjb252ZXJ0ZWQgdG8gTG9yb01hcHMsIGFycmF5cyB0byBMb3JvTW92YWJsZUxpc3RzLCBwcmltaXRpdmVzIGFyZSB1bnRvdWNoZWQuXG4gKiBGcm96ZW4gdmFsdWVzIGFyZSBhIHNwZWNpYWwgY2FzZSBhbmQgdGhleSBhcmUga2VwdCBhcyBpbW11dGFibGUgcGxhaW4gdmFsdWVzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY29udmVydEpzb25Ub0xvcm9EYXRhKHY6IFBsYWluVmFsdWUpOiBMb3JvVmFsdWUge1xuICBpZiAoaXNQbGFpblByaW1pdGl2ZSh2KSkge1xuICAgIHJldHVybiB2XG4gIH1cblxuICBpZiAoaXNQbGFpbkFycmF5KHYpKSB7XG4gICAgY29uc3QgbGlzdCA9IG5ldyBMb3JvTW92YWJsZUxpc3QoKVxuICAgIGFwcGx5SnNvbkFycmF5VG9Mb3JvTW92YWJsZUxpc3QobGlzdCwgdilcbiAgICByZXR1cm4gbGlzdFxuICB9XG5cbiAgaWYgKGlzUGxhaW5PYmplY3QodikpIHtcbiAgICBpZiAodltmcm96ZW5LZXldID09PSB0cnVlKSB7XG4gICAgICAvLyBmcm96ZW4gdmFsdWUgd2l0aCBleHBsaWNpdCAkZnJvemVuIG1hcmtlciAoc2hvdWxkbid0IHJlYWNoIGhlcmUgYWZ0ZXIgYWJvdmUgY2hlY2spXG4gICAgICByZXR1cm4gdlxuICAgIH1cblxuICAgIGlmIChpc0xvcm9UZXh0TW9kZWxTbmFwc2hvdCh2KSkge1xuICAgICAgY29uc3QgdGV4dCA9IG5ldyBMb3JvVGV4dCgpXG4gICAgICAvLyBFeHRyYWN0IGRlbHRhIGZyb20gdGhlIHNuYXBzaG90IGFuZCBhcHBseSB1c2luZyBpbnNlcnQvbWFyayBBUElzXG4gICAgICAvLyAoYXBwbHlEZWx0YSBkb2Vzbid0IHdvcmsgb24gZGV0YWNoZWQgY29udGFpbmVycywgYnV0IGluc2VydC9tYXJrIGRvKVxuICAgICAgY29uc3QgZGVsdGFzID0gZXh0cmFjdFRleHREZWx0YUZyb21TbmFwc2hvdCh2LmRlbHRhTGlzdClcbiAgICAgIGlmIChkZWx0YXMubGVuZ3RoID4gMCkge1xuICAgICAgICBhcHBseURlbHRhVG9Mb3JvVGV4dCh0ZXh0LCBkZWx0YXMpXG4gICAgICB9XG4gICAgICByZXR1cm4gdGV4dFxuICAgIH1cblxuICAgIGNvbnN0IG1hcCA9IG5ldyBMb3JvTWFwKClcbiAgICBhcHBseUpzb25PYmplY3RUb0xvcm9NYXAobWFwLCB2KVxuICAgIHJldHVybiBtYXBcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcihgdW5zdXBwb3J0ZWQgdmFsdWUgdHlwZTogJHt2fWApXG59XG5cbi8qKlxuICogQXBwbGllcyBhIEpTT04gYXJyYXkgdG8gYSBMb3JvTW92YWJsZUxpc3QsIHVzaW5nIGNvbnZlcnRKc29uVG9Mb3JvRGF0YSB0byBjb252ZXJ0IHRoZSB2YWx1ZXMuXG4gKlxuICogQHBhcmFtIGRlc3QgVGhlIGRlc3RpbmF0aW9uIExvcm9Nb3ZhYmxlTGlzdC5cbiAqIEBwYXJhbSBzb3VyY2UgVGhlIHNvdXJjZSBKU09OIGFycmF5LlxuICogQHBhcmFtIG9wdGlvbnMgT3B0aW9ucyBmb3IgYXBwbHlpbmcgdGhlIEpTT04gZGF0YS5cbiAqL1xuZXhwb3J0IGNvbnN0IGFwcGx5SnNvbkFycmF5VG9Mb3JvTW92YWJsZUxpc3QgPSAoXG4gIGRlc3Q6IExvcm9Nb3ZhYmxlTGlzdCxcbiAgc291cmNlOiBQbGFpbkFycmF5LFxuICBvcHRpb25zOiBBcHBseUpzb25Ub0xvcm9PcHRpb25zID0ge31cbikgPT4ge1xuICBjb25zdCB7IG1vZGUgPSBcImFkZFwiIH0gPSBvcHRpb25zXG5cbiAgaWYgKG1vZGUgPT09IFwiYWRkXCIpIHtcbiAgICAvLyBBZGQgbW9kZToganVzdCBwdXNoIGFsbCBpdGVtcyB0byB0aGUgZW5kXG4gICAgZm9yIChjb25zdCBpdGVtIG9mIHNvdXJjZSkge1xuICAgICAgY29uc3QgY29udmVydGVkID0gY29udmVydEpzb25Ub0xvcm9EYXRhKGl0ZW0pXG4gICAgICBpZiAoaXNCaW5kYWJsZUxvcm9Db250YWluZXIoY29udmVydGVkKSkge1xuICAgICAgICBkZXN0LnB1c2hDb250YWluZXIoY29udmVydGVkKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZGVzdC5wdXNoKGNvbnZlcnRlZClcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuXG4gIH1cblxuICAvLyBNZXJnZSBtb2RlOiByZWN1cnNpdmVseSBtZXJnZSB2YWx1ZXMsIHByZXNlcnZpbmcgZXhpc3RpbmcgY29udGFpbmVyIHJlZmVyZW5jZXNcbiAgLy8gSW4gbWVyZ2UgbW9kZSwgY2hlY2sgaWYgdGhlIGNvbnRhaW5lciBpcyBhbHJlYWR5IHVwLXRvLWRhdGUgd2l0aCB0aGlzIHNuYXBzaG90XG4gIGlmIChpc0xvcm9Db250YWluZXJVcFRvRGF0ZShkZXN0LCBzb3VyY2UpKSB7XG4gICAgcmV0dXJuXG4gIH1cblxuICAvLyBSZW1vdmUgZXh0cmEgaXRlbXMgZnJvbSB0aGUgZW5kXG4gIGNvbnN0IGRlc3RMZW4gPSBkZXN0Lmxlbmd0aFxuICBjb25zdCBzcmNMZW4gPSBzb3VyY2UubGVuZ3RoXG4gIGlmIChkZXN0TGVuID4gc3JjTGVuKSB7XG4gICAgZGVzdC5kZWxldGUoc3JjTGVuLCBkZXN0TGVuIC0gc3JjTGVuKVxuICB9XG5cbiAgLy8gVXBkYXRlIGV4aXN0aW5nIGl0ZW1zXG4gIGNvbnN0IG1pbkxlbiA9IE1hdGgubWluKGRlc3RMZW4sIHNyY0xlbilcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBtaW5MZW47IGkrKykge1xuICAgIGNvbnN0IHNyY0l0ZW0gPSBzb3VyY2VbaV1cbiAgICBjb25zdCBkZXN0SXRlbSA9IGRlc3QuZ2V0KGkpXG5cbiAgICAvLyBJZiBib3RoIGFyZSBvYmplY3RzLCBtZXJnZSByZWN1cnNpdmVseVxuICAgIGlmIChpc1BsYWluT2JqZWN0KHNyY0l0ZW0pICYmIGRlc3RJdGVtIGluc3RhbmNlb2YgTG9yb01hcCkge1xuICAgICAgYXBwbHlKc29uT2JqZWN0VG9Mb3JvTWFwKGRlc3RJdGVtLCBzcmNJdGVtLCBvcHRpb25zKVxuICAgICAgY29udGludWVcbiAgICB9XG5cbiAgICAvLyBJZiBib3RoIGFyZSBhcnJheXMsIG1lcmdlIHJlY3Vyc2l2ZWx5XG4gICAgaWYgKGlzUGxhaW5BcnJheShzcmNJdGVtKSAmJiBkZXN0SXRlbSBpbnN0YW5jZW9mIExvcm9Nb3ZhYmxlTGlzdCkge1xuICAgICAgYXBwbHlKc29uQXJyYXlUb0xvcm9Nb3ZhYmxlTGlzdChkZXN0SXRlbSwgc3JjSXRlbSwgb3B0aW9ucylcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuXG4gICAgLy8gU2tpcCBpZiBwcmltaXRpdmUgdmFsdWUgaXMgdW5jaGFuZ2VkIChvcHRpbWl6YXRpb24pXG4gICAgaWYgKGlzUGxhaW5QcmltaXRpdmUoc3JjSXRlbSkgJiYgZGVzdEl0ZW0gPT09IHNyY0l0ZW0pIHtcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuXG4gICAgLy8gT3RoZXJ3aXNlLCByZXBsYWNlIHRoZSBpdGVtXG4gICAgZGVzdC5kZWxldGUoaSwgMSlcbiAgICBjb25zdCBjb252ZXJ0ZWQgPSBjb252ZXJ0SnNvblRvTG9yb0RhdGEoc3JjSXRlbSlcbiAgICBpZiAoaXNCaW5kYWJsZUxvcm9Db250YWluZXIoY29udmVydGVkKSkge1xuICAgICAgZGVzdC5pbnNlcnRDb250YWluZXIoaSwgY29udmVydGVkKVxuICAgIH0gZWxzZSB7XG4gICAgICBkZXN0Lmluc2VydChpLCBjb252ZXJ0ZWQpXG4gICAgfVxuICB9XG5cbiAgLy8gQWRkIG5ldyBpdGVtcyBhdCB0aGUgZW5kXG4gIGZvciAobGV0IGkgPSBkZXN0TGVuOyBpIDwgc3JjTGVuOyBpKyspIHtcbiAgICBjb25zdCBjb252ZXJ0ZWQgPSBjb252ZXJ0SnNvblRvTG9yb0RhdGEoc291cmNlW2ldKVxuICAgIGlmIChpc0JpbmRhYmxlTG9yb0NvbnRhaW5lcihjb252ZXJ0ZWQpKSB7XG4gICAgICBkZXN0LnB1c2hDb250YWluZXIoY29udmVydGVkKVxuICAgIH0gZWxzZSB7XG4gICAgICBkZXN0LnB1c2goY29udmVydGVkKVxuICAgIH1cbiAgfVxuXG4gIC8vIFVwZGF0ZSBzbmFwc2hvdCB0cmFja2luZyBhZnRlciBzdWNjZXNzZnVsIG1lcmdlXG4gIHNldExvcm9Db250YWluZXJTbmFwc2hvdChkZXN0LCBzb3VyY2UpXG59XG5cbi8qKlxuICogQXBwbGllcyBhIEpTT04gb2JqZWN0IHRvIGEgTG9yb01hcCwgdXNpbmcgY29udmVydEpzb25Ub0xvcm9EYXRhIHRvIGNvbnZlcnQgdGhlIHZhbHVlcy5cbiAqXG4gKiBAcGFyYW0gZGVzdCBUaGUgZGVzdGluYXRpb24gTG9yb01hcC5cbiAqIEBwYXJhbSBzb3VyY2UgVGhlIHNvdXJjZSBKU09OIG9iamVjdC5cbiAqIEBwYXJhbSBvcHRpb25zIE9wdGlvbnMgZm9yIGFwcGx5aW5nIHRoZSBKU09OIGRhdGEuXG4gKi9cbmV4cG9ydCBjb25zdCBhcHBseUpzb25PYmplY3RUb0xvcm9NYXAgPSAoXG4gIGRlc3Q6IExvcm9NYXAsXG4gIHNvdXJjZTogUGxhaW5PYmplY3QsXG4gIG9wdGlvbnM6IEFwcGx5SnNvblRvTG9yb09wdGlvbnMgPSB7fVxuKSA9PiB7XG4gIGNvbnN0IHsgbW9kZSA9IFwiYWRkXCIgfSA9IG9wdGlvbnNcblxuICBpZiAobW9kZSA9PT0gXCJhZGRcIikge1xuICAgIC8vIEFkZCBtb2RlOiBqdXN0IHNldCBhbGwgdmFsdWVzXG4gICAgZm9yIChjb25zdCBrIG9mIE9iamVjdC5rZXlzKHNvdXJjZSkpIHtcbiAgICAgIGNvbnN0IHYgPSBzb3VyY2Vba11cbiAgICAgIGlmICh2ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgY29uc3QgY29udmVydGVkID0gY29udmVydEpzb25Ub0xvcm9EYXRhKHYpXG4gICAgICAgIGlmIChpc0JpbmRhYmxlTG9yb0NvbnRhaW5lcihjb252ZXJ0ZWQpKSB7XG4gICAgICAgICAgZGVzdC5zZXRDb250YWluZXIoaywgY29udmVydGVkKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGRlc3Quc2V0KGssIGNvbnZlcnRlZClcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm5cbiAgfVxuXG4gIC8vIE1lcmdlIG1vZGU6IHJlY3Vyc2l2ZWx5IG1lcmdlIHZhbHVlcywgcHJlc2VydmluZyBleGlzdGluZyBjb250YWluZXIgcmVmZXJlbmNlc1xuICAvLyBJbiBtZXJnZSBtb2RlLCBjaGVjayBpZiB0aGUgY29udGFpbmVyIGlzIGFscmVhZHkgdXAtdG8tZGF0ZSB3aXRoIHRoaXMgc25hcHNob3RcbiAgaWYgKGlzTG9yb0NvbnRhaW5lclVwVG9EYXRlKGRlc3QsIHNvdXJjZSkpIHtcbiAgICByZXR1cm5cbiAgfVxuXG4gIC8vIERlbGV0ZSBrZXlzIHRoYXQgYXJlIG5vdCBwcmVzZW50IGluIHNvdXJjZSAob3IgaGF2ZSB1bmRlZmluZWQgdmFsdWUpXG4gIGNvbnN0IHNvdXJjZUtleXNXaXRoVmFsdWVzID0gbmV3IFNldChPYmplY3Qua2V5cyhzb3VyY2UpLmZpbHRlcigoaykgPT4gc291cmNlW2tdICE9PSB1bmRlZmluZWQpKVxuICBmb3IgKGNvbnN0IGtleSBvZiBkZXN0LmtleXMoKSkge1xuICAgIGlmICghc291cmNlS2V5c1dpdGhWYWx1ZXMuaGFzKGtleSkpIHtcbiAgICAgIGRlc3QuZGVsZXRlKGtleSlcbiAgICB9XG4gIH1cblxuICBmb3IgKGNvbnN0IGsgb2YgT2JqZWN0LmtleXMoc291cmNlKSkge1xuICAgIGNvbnN0IHYgPSBzb3VyY2Vba11cbiAgICAvLyBTa2lwIHVuZGVmaW5lZCB2YWx1ZXMgLSBMb3JvIG1hcHMgY2Fubm90IHN0b3JlIHVuZGVmaW5lZFxuICAgIGlmICh2ID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuXG4gICAgY29uc3QgZXhpc3RpbmcgPSBkZXN0LmdldChrKVxuXG4gICAgLy8gSWYgc291cmNlIGlzIGFuIG9iamVjdCBhbmQgZGVzdCBoYXMgYSBMb3JvTWFwLCBtZXJnZSByZWN1cnNpdmVseVxuICAgIGlmIChpc1BsYWluT2JqZWN0KHYpICYmIGV4aXN0aW5nIGluc3RhbmNlb2YgTG9yb01hcCkge1xuICAgICAgYXBwbHlKc29uT2JqZWN0VG9Mb3JvTWFwKGV4aXN0aW5nLCB2LCBvcHRpb25zKVxuICAgICAgY29udGludWVcbiAgICB9XG5cbiAgICAvLyBJZiBzb3VyY2UgaXMgYW4gYXJyYXkgYW5kIGRlc3QgaGFzIGEgTG9yb01vdmFibGVMaXN0LCBtZXJnZSByZWN1cnNpdmVseVxuICAgIGlmIChpc1BsYWluQXJyYXkodikgJiYgZXhpc3RpbmcgaW5zdGFuY2VvZiBMb3JvTW92YWJsZUxpc3QpIHtcbiAgICAgIGFwcGx5SnNvbkFycmF5VG9Mb3JvTW92YWJsZUxpc3QoZXhpc3RpbmcsIHYsIG9wdGlvbnMpXG4gICAgICBjb250aW51ZVxuICAgIH1cblxuICAgIC8vIFNraXAgaWYgcHJpbWl0aXZlIHZhbHVlIGlzIHVuY2hhbmdlZCAob3B0aW1pemF0aW9uKVxuICAgIGlmIChpc1BsYWluUHJpbWl0aXZlKHYpICYmIGV4aXN0aW5nID09PSB2KSB7XG4gICAgICBjb250aW51ZVxuICAgIH1cblxuICAgIC8vIE90aGVyd2lzZSwgY29udmVydCBhbmQgc2V0IHRoZSB2YWx1ZSAodGhpcyBjcmVhdGVzIG5ldyBjb250YWluZXJzIGlmIG5lZWRlZClcbiAgICBjb25zdCBjb252ZXJ0ZWQgPSBjb252ZXJ0SnNvblRvTG9yb0RhdGEodilcbiAgICBpZiAoaXNCaW5kYWJsZUxvcm9Db250YWluZXIoY29udmVydGVkKSkge1xuICAgICAgZGVzdC5zZXRDb250YWluZXIoaywgY29udmVydGVkKVxuICAgIH0gZWxzZSB7XG4gICAgICBkZXN0LnNldChrLCBjb252ZXJ0ZWQpXG4gICAgfVxuICB9XG5cbiAgLy8gVXBkYXRlIHNuYXBzaG90IHRyYWNraW5nIGFmdGVyIHN1Y2Nlc3NmdWwgbWVyZ2VcbiAgc2V0TG9yb0NvbnRhaW5lclNuYXBzaG90KGRlc3QsIHNvdXJjZSlcbn1cbiIsImltcG9ydCB7IExvcm9NYXAsIExvcm9Nb3ZhYmxlTGlzdCwgTG9yb1RleHQgfSBmcm9tIFwibG9yby1jcmR0XCJcbmltcG9ydCB7IERlZXBDaGFuZ2UsIERlZXBDaGFuZ2VUeXBlIH0gZnJvbSBcIm1vYngta2V5c3RvbmVcIlxuaW1wb3J0IHR5cGUgeyBQbGFpblZhbHVlIH0gZnJvbSBcIi4uL3BsYWluVHlwZXNcIlxuaW1wb3J0IHsgZmFpbHVyZSB9IGZyb20gXCIuLi91dGlscy9lcnJvclwiXG5pbXBvcnQgdHlwZSB7IEJpbmRhYmxlTG9yb0NvbnRhaW5lciB9IGZyb20gXCIuLi91dGlscy9pc0JpbmRhYmxlTG9yb0NvbnRhaW5lclwiXG5pbXBvcnQge1xuICBhcHBseURlbHRhVG9Mb3JvVGV4dCxcbiAgY29udmVydEpzb25Ub0xvcm9EYXRhLFxuICBleHRyYWN0VGV4dERlbHRhRnJvbVNuYXBzaG90LFxufSBmcm9tIFwiLi9jb252ZXJ0SnNvblRvTG9yb0RhdGFcIlxuaW1wb3J0IHsgaXNMb3JvVGV4dE1vZGVsU25hcHNob3QgfSBmcm9tIFwiLi9Mb3JvVGV4dE1vZGVsXCJcbmltcG9ydCB0eXBlIHsgQXJyYXlNb3ZlQ2hhbmdlIH0gZnJvbSBcIi4vbW92ZVdpdGhpbkFycmF5XCJcbmltcG9ydCB7IHJlc29sdmVMb3JvUGF0aCB9IGZyb20gXCIuL3Jlc29sdmVMb3JvUGF0aFwiXG5cbi8qKlxuICogQ29udmVydHMgYSBzbmFwc2hvdCB2YWx1ZSB0byBhIExvcm8tY29tcGF0aWJsZSB2YWx1ZS5cbiAqIE5vdGU6IEFsbCB2YWx1ZXMgcGFzc2VkIGhlcmUgYXJlIGFscmVhZHkgc25hcHNob3RzIChjYXB0dXJlZCBhdCBjaGFuZ2UgdGltZSkuXG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRWYWx1ZSh2OiB1bmtub3duKTogdW5rbm93biB7XG4gIC8vIEhhbmRsZSBwcmltaXRpdmVzIGRpcmVjdGx5XG4gIGlmICh2ID09PSBudWxsIHx8IHYgPT09IHVuZGVmaW5lZCB8fCB0eXBlb2YgdiAhPT0gXCJvYmplY3RcIikge1xuICAgIHJldHVybiB2XG4gIH1cbiAgLy8gSGFuZGxlIHBsYWluIGFycmF5cyAtIHVzZWQgZm9yIGVtcHR5IGFycmF5IGluaXRcbiAgaWYgKEFycmF5LmlzQXJyYXkodikgJiYgdi5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gbmV3IExvcm9Nb3ZhYmxlTGlzdCgpXG4gIH1cbiAgLy8gSGFuZGxlIExvcm9UZXh0TW9kZWwgc25hcHNob3Qgc3BlY2lhbGx5IC0gd2UgbmVlZCB0byByZXR1cm4gaXQgYXMtaXNcbiAgLy8gc28gdGhlIGNhbGxlciBjYW4gaGFuZGxlIGNyZWF0aW5nIHRoZSBMb3JvVGV4dCBjb250YWluZXIgcHJvcGVybHlcbiAgaWYgKGlzTG9yb1RleHRNb2RlbFNuYXBzaG90KHYpKSB7XG4gICAgcmV0dXJuIHZcbiAgfVxuICAvLyBWYWx1ZSBpcyBhbHJlYWR5IGEgc25hcHNob3QsIGNvbnZlcnQgdG8gTG9ybyBkYXRhXG4gIHJldHVybiBjb252ZXJ0SnNvblRvTG9yb0RhdGEodiBhcyBQbGFpblZhbHVlKVxufVxuXG4vKipcbiAqIEluc2VydHMgYSB2YWx1ZSBpbnRvIGEgTG9yb01vdmFibGVMaXN0IGF0IHRoZSBnaXZlbiBpbmRleC5cbiAqL1xuZnVuY3Rpb24gaW5zZXJ0SW50b0xpc3QobGlzdDogTG9yb01vdmFibGVMaXN0LCBpbmRleDogbnVtYmVyLCB2YWx1ZTogdW5rbm93bik6IHZvaWQge1xuICBpZiAodmFsdWUgaW5zdGFuY2VvZiBMb3JvTWFwIHx8IHZhbHVlIGluc3RhbmNlb2YgTG9yb01vdmFibGVMaXN0IHx8IHZhbHVlIGluc3RhbmNlb2YgTG9yb1RleHQpIHtcbiAgICBsaXN0Lmluc2VydENvbnRhaW5lcihpbmRleCwgdmFsdWUpXG4gIH0gZWxzZSBpZiAoaXNMb3JvVGV4dE1vZGVsU25hcHNob3QodmFsdWUpKSB7XG4gICAgY29uc3QgYXR0YWNoZWRUZXh0ID0gbGlzdC5pbnNlcnRDb250YWluZXIoaW5kZXgsIG5ldyBMb3JvVGV4dCgpKVxuICAgIGNvbnN0IGRlbHRhcyA9IGV4dHJhY3RUZXh0RGVsdGFGcm9tU25hcHNob3QoKHZhbHVlIGFzIGFueSkuZGVsdGFMaXN0KVxuICAgIGlmIChkZWx0YXMubGVuZ3RoID4gMCkge1xuICAgICAgYXBwbHlEZWx0YVRvTG9yb1RleHQoYXR0YWNoZWRUZXh0LCBkZWx0YXMpXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGxpc3QuaW5zZXJ0KGluZGV4LCB2YWx1ZSlcbiAgfVxufVxuXG4vKipcbiAqIFNldHMgYSB2YWx1ZSBpbiBhIExvcm9NYXAgYXQgdGhlIGdpdmVuIGtleS5cbiAqL1xuZnVuY3Rpb24gc2V0SW5NYXAobWFwOiBMb3JvTWFwLCBrZXk6IHN0cmluZywgdmFsdWU6IHVua25vd24pOiB2b2lkIHtcbiAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICBtYXAuZGVsZXRlKGtleSlcbiAgfSBlbHNlIGlmIChcbiAgICB2YWx1ZSBpbnN0YW5jZW9mIExvcm9NYXAgfHxcbiAgICB2YWx1ZSBpbnN0YW5jZW9mIExvcm9Nb3ZhYmxlTGlzdCB8fFxuICAgIHZhbHVlIGluc3RhbmNlb2YgTG9yb1RleHRcbiAgKSB7XG4gICAgbWFwLnNldENvbnRhaW5lcihrZXksIHZhbHVlKVxuICB9IGVsc2UgaWYgKGlzTG9yb1RleHRNb2RlbFNuYXBzaG90KHZhbHVlKSkge1xuICAgIGNvbnN0IGF0dGFjaGVkVGV4dCA9IG1hcC5zZXRDb250YWluZXIoa2V5LCBuZXcgTG9yb1RleHQoKSlcbiAgICBjb25zdCBkZWx0YXMgPSBleHRyYWN0VGV4dERlbHRhRnJvbVNuYXBzaG90KCh2YWx1ZSBhcyBhbnkpLmRlbHRhTGlzdClcbiAgICBpZiAoZGVsdGFzLmxlbmd0aCA+IDApIHtcbiAgICAgIGFwcGx5RGVsdGFUb0xvcm9UZXh0KGF0dGFjaGVkVGV4dCwgZGVsdGFzKVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBtYXAuc2V0KGtleSwgdmFsdWUpXG4gIH1cbn1cblxuLyoqXG4gKiBBcHBsaWVzIGEgTW9iWCBEZWVwQ2hhbmdlIG9yIGFuIEFycmF5TW92ZUNoYW5nZSB0byBhIExvcm8gb2JqZWN0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gYXBwbHlNb2J4Q2hhbmdlVG9Mb3JvT2JqZWN0KFxuICBjaGFuZ2U6IERlZXBDaGFuZ2UgfCBBcnJheU1vdmVDaGFuZ2UsXG4gIGxvcm9PYmplY3Q6IEJpbmRhYmxlTG9yb0NvbnRhaW5lclxuKTogdm9pZCB7XG4gIGNvbnN0IGxvcm9Db250YWluZXIgPSByZXNvbHZlTG9yb1BhdGgobG9yb09iamVjdCwgY2hhbmdlLnBhdGgpXG5cbiAgLy8gSWYgY29udGFpbmVyIGRvZXNuJ3QgZXhpc3QgYXQgdGhpcyBwYXRoLCB0aHJvdyBhbiBlcnJvclxuICBpZiAoIWxvcm9Db250YWluZXIpIHtcbiAgICB0aHJvdyBmYWlsdXJlKFxuICAgICAgYGNhbm5vdCBhcHBseSBjaGFuZ2UgdG8gbWlzc2luZyBMb3JvIGNvbnRhaW5lciBhdCBwYXRoOiAke0pTT04uc3RyaW5naWZ5KGNoYW5nZS5wYXRoKX1gXG4gICAgKVxuICB9XG5cbiAgc3dpdGNoIChjaGFuZ2UudHlwZSkge1xuICAgIGNhc2UgXCJBcnJheU1vdmVcIjoge1xuICAgICAgaWYgKCEobG9yb0NvbnRhaW5lciBpbnN0YW5jZW9mIExvcm9Nb3ZhYmxlTGlzdCkpIHtcbiAgICAgICAgdGhyb3cgZmFpbHVyZShgQXJyYXlNb3ZlIGNoYW5nZSByZXF1aXJlcyBhIExvcm9Nb3ZhYmxlTGlzdCBjb250YWluZXJgKVxuICAgICAgfVxuICAgICAgbG9yb0NvbnRhaW5lci5tb3ZlKGNoYW5nZS5mcm9tSW5kZXgsIGNoYW5nZS50b0luZGV4KVxuICAgICAgYnJlYWtcbiAgICB9XG5cbiAgICBjYXNlIERlZXBDaGFuZ2VUeXBlLkFycmF5U3BsaWNlOiB7XG4gICAgICBpZiAoIShsb3JvQ29udGFpbmVyIGluc3RhbmNlb2YgTG9yb01vdmFibGVMaXN0KSkge1xuICAgICAgICB0aHJvdyBmYWlsdXJlKGBBcnJheVNwbGljZSBjaGFuZ2UgcmVxdWlyZXMgYSBMb3JvTW92YWJsZUxpc3QgY29udGFpbmVyYClcbiAgICAgIH1cbiAgICAgIGlmIChjaGFuZ2UucmVtb3ZlZFZhbHVlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGxvcm9Db250YWluZXIuZGVsZXRlKGNoYW5nZS5pbmRleCwgY2hhbmdlLnJlbW92ZWRWYWx1ZXMubGVuZ3RoKVxuICAgICAgfVxuICAgICAgaWYgKGNoYW5nZS5hZGRlZFZhbHVlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGNvbnN0IHZhbHVlc1RvSW5zZXJ0ID0gY2hhbmdlLmFkZGVkVmFsdWVzLm1hcChjb252ZXJ0VmFsdWUpXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdmFsdWVzVG9JbnNlcnQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBpbnNlcnRJbnRvTGlzdChsb3JvQ29udGFpbmVyLCBjaGFuZ2UuaW5kZXggKyBpLCB2YWx1ZXNUb0luc2VydFtpXSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgYnJlYWtcbiAgICB9XG5cbiAgICBjYXNlIERlZXBDaGFuZ2VUeXBlLkFycmF5VXBkYXRlOiB7XG4gICAgICBpZiAoIShsb3JvQ29udGFpbmVyIGluc3RhbmNlb2YgTG9yb01vdmFibGVMaXN0KSkge1xuICAgICAgICB0aHJvdyBmYWlsdXJlKGBBcnJheVVwZGF0ZSBjaGFuZ2UgcmVxdWlyZXMgYSBMb3JvTW92YWJsZUxpc3QgY29udGFpbmVyYClcbiAgICAgIH1cbiAgICAgIGNvbnN0IGNvbnZlcnRlZCA9IGNvbnZlcnRWYWx1ZShjaGFuZ2UubmV3VmFsdWUpXG4gICAgICBpZiAoXG4gICAgICAgIGNvbnZlcnRlZCBpbnN0YW5jZW9mIExvcm9NYXAgfHxcbiAgICAgICAgY29udmVydGVkIGluc3RhbmNlb2YgTG9yb01vdmFibGVMaXN0IHx8XG4gICAgICAgIGNvbnZlcnRlZCBpbnN0YW5jZW9mIExvcm9UZXh0XG4gICAgICApIHtcbiAgICAgICAgbG9yb0NvbnRhaW5lci5zZXRDb250YWluZXIoY2hhbmdlLmluZGV4LCBjb252ZXJ0ZWQpXG4gICAgICB9IGVsc2UgaWYgKGlzTG9yb1RleHRNb2RlbFNuYXBzaG90KGNvbnZlcnRlZCkpIHtcbiAgICAgICAgY29uc3QgYXR0YWNoZWRUZXh0ID0gbG9yb0NvbnRhaW5lci5zZXRDb250YWluZXIoY2hhbmdlLmluZGV4LCBuZXcgTG9yb1RleHQoKSlcbiAgICAgICAgY29uc3QgZGVsdGFzID0gZXh0cmFjdFRleHREZWx0YUZyb21TbmFwc2hvdCgoY29udmVydGVkIGFzIGFueSkuZGVsdGFMaXN0KVxuICAgICAgICBpZiAoZGVsdGFzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBhcHBseURlbHRhVG9Mb3JvVGV4dChhdHRhY2hlZFRleHQsIGRlbHRhcylcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9yb0NvbnRhaW5lci5zZXQoY2hhbmdlLmluZGV4LCBjb252ZXJ0ZWQpXG4gICAgICB9XG4gICAgICBicmVha1xuICAgIH1cblxuICAgIGNhc2UgRGVlcENoYW5nZVR5cGUuT2JqZWN0QWRkOlxuICAgIGNhc2UgRGVlcENoYW5nZVR5cGUuT2JqZWN0VXBkYXRlOiB7XG4gICAgICBpZiAobG9yb0NvbnRhaW5lciBpbnN0YW5jZW9mIExvcm9UZXh0KSB7XG4gICAgICAgIC8vIEhhbmRsZSBjaGFuZ2VzIHRvIExvcm9UZXh0IHByb3BlcnRpZXMgKG1haW5seSBkZWx0YUxpc3QpXG4gICAgICAgIGlmIChjaGFuZ2Uua2V5ID09PSBcImRlbHRhTGlzdFwiKSB7XG4gICAgICAgICAgLy8gY2hhbmdlLm5ld1ZhbHVlIGlzIGFscmVhZHkgYSBzbmFwc2hvdCAoY2FwdHVyZWQgYXQgY2hhbmdlIHRpbWUpXG4gICAgICAgICAgY29uc3QgZGVsdGFzID0gZXh0cmFjdFRleHREZWx0YUZyb21TbmFwc2hvdChjaGFuZ2UubmV3VmFsdWUpXG4gICAgICAgICAgaWYgKGxvcm9Db250YWluZXIubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgbG9yb0NvbnRhaW5lci5kZWxldGUoMCwgbG9yb0NvbnRhaW5lci5sZW5ndGgpXG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChkZWx0YXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgYXBwbHlEZWx0YVRvTG9yb1RleHQobG9yb0NvbnRhaW5lciwgZGVsdGFzKVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBpZ25vcmUgb3RoZXIgcHJvcGVydHkgY2hhbmdlcyBvbiBMb3JvVGV4dCBhcyB0aGV5J3JlIG5vdCBzeW5jZWRcbiAgICAgIH0gZWxzZSBpZiAobG9yb0NvbnRhaW5lciBpbnN0YW5jZW9mIExvcm9NYXApIHtcbiAgICAgICAgY29uc3QgY29udmVydGVkID0gY29udmVydFZhbHVlKGNoYW5nZS5uZXdWYWx1ZSlcbiAgICAgICAgc2V0SW5NYXAobG9yb0NvbnRhaW5lciwgY2hhbmdlLmtleSwgY29udmVydGVkKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgZmFpbHVyZShgT2JqZWN0QWRkL09iamVjdFVwZGF0ZSBjaGFuZ2UgcmVxdWlyZXMgYSBMb3JvTWFwIG9yIExvcm9UZXh0IGNvbnRhaW5lcmApXG4gICAgICB9XG4gICAgICBicmVha1xuICAgIH1cblxuICAgIGNhc2UgRGVlcENoYW5nZVR5cGUuT2JqZWN0UmVtb3ZlOiB7XG4gICAgICBpZiAobG9yb0NvbnRhaW5lciBpbnN0YW5jZW9mIExvcm9UZXh0KSB7XG4gICAgICAgIC8vIGlnbm9yZSByZW1vdmVzIG9uIExvcm9UZXh0IHByb3BlcnRpZXNcbiAgICAgIH0gZWxzZSBpZiAobG9yb0NvbnRhaW5lciBpbnN0YW5jZW9mIExvcm9NYXApIHtcbiAgICAgICAgbG9yb0NvbnRhaW5lci5kZWxldGUoY2hhbmdlLmtleSlcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IGZhaWx1cmUoYE9iamVjdFJlbW92ZSBjaGFuZ2UgcmVxdWlyZXMgYSBMb3JvTWFwIG9yIExvcm9UZXh0IGNvbnRhaW5lcmApXG4gICAgICB9XG4gICAgICBicmVha1xuICAgIH1cblxuICAgIGRlZmF1bHQ6IHtcbiAgICAgIC8vIEV4aGF1c3RpdmUgY2hlY2sgLSBUeXBlU2NyaXB0IHdpbGwgZXJyb3IgaWYgd2UgbWlzcyBhIGNhc2VcbiAgICAgIGNvbnN0IF9leGhhdXN0aXZlQ2hlY2s6IG5ldmVyID0gY2hhbmdlXG4gICAgICB0aHJvdyBmYWlsdXJlKGB1bnN1cHBvcnRlZCBjaGFuZ2UgdHlwZTogJHsoX2V4aGF1c3RpdmVDaGVjayBhcyBhbnkpLnR5cGV9YClcbiAgICB9XG4gIH1cbn1cbiIsImltcG9ydCB7IERlZXBDaGFuZ2UgfSBmcm9tIFwibW9ieC1rZXlzdG9uZVwiXG5cbi8qKlxuICogU3ludGhldGljIGNoYW5nZSB0eXBlIGZvciBhcnJheSBtb3Zlcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBcnJheU1vdmVDaGFuZ2Uge1xuICB0eXBlOiBcIkFycmF5TW92ZVwiXG4gIHBhdGg6IHJlYWRvbmx5IChzdHJpbmcgfCBudW1iZXIpW11cbiAgZnJvbUluZGV4OiBudW1iZXJcbiAgdG9JbmRleDogbnVtYmVyXG59XG5cbi8qKlxuICogVHJhY2tzIHRoZSBjdXJyZW50bHkgYWN0aXZlIG1vdmUgb3BlcmF0aW9uLlxuICogV2hlbiBzZXQsIHRoZSBuZXh0IHR3byBzcGxpY2Ugb3BlcmF0aW9ucyBvbiB0aGlzIGFycmF5IGFyZSBpbnRlcmNlcHRlZC5cbiAqL1xubGV0IGFjdGl2ZU1vdmVDb250ZXh0OlxuICB8IHtcbiAgICAgIGFycmF5OiB1bmtub3duW11cbiAgICAgIGZyb21JbmRleDogbnVtYmVyXG4gICAgICB0b0luZGV4OiBudW1iZXJcbiAgICAgIHBhdGg6IHJlYWRvbmx5IChzdHJpbmcgfCBudW1iZXIpW10gfCB1bmRlZmluZWQgLy8gQ2FwdHVyZWQgZnJvbSBmaXJzdCBzcGxpY2VcbiAgICAgIHJlY2VpdmVkRmlyc3RTcGxpY2U6IGJvb2xlYW5cbiAgICB9XG4gIHwgdW5kZWZpbmVkXG5cbi8qKlxuICogTW92ZXMgYW4gaXRlbSB3aXRoaW4gYW4gYXJyYXkgZnJvbSBvbmUgaW5kZXggdG8gYW5vdGhlci5cbiAqXG4gKiBXaGVuIHVzZWQgb24gYSBtb2J4LWtleXN0b25lIGFycmF5IGJvdW5kIHRvIGEgTG9ybyBtb3ZhYmxlIGxpc3QsXG4gKiB0aGlzIHRyYW5zbGF0ZXMgdG8gYSBuYXRpdmUgTG9ybyBtb3ZlIG9wZXJhdGlvbiBmb3Igb3B0aW1hbCBDUkRUIG1lcmdpbmcuXG4gKlxuICogRm9yIHVuYm91bmQgYXJyYXlzLCBwZXJmb3JtcyBhIHN0YW5kYXJkIHNwbGljZS1iYXNlZCBtb3ZlLlxuICpcbiAqIEBwYXJhbSBhcnJheSBUaGUgYXJyYXkgdG8gbW92ZSB3aXRoaW5cbiAqIEBwYXJhbSBmcm9tSW5kZXggVGhlIGluZGV4IG9mIHRoZSBpdGVtIHRvIG1vdmVcbiAqIEBwYXJhbSB0b0luZGV4IFRoZSB0YXJnZXQgaW5kZXggdG8gbW92ZSB0aGUgaXRlbSB0b1xuICovXG5leHBvcnQgZnVuY3Rpb24gbW92ZVdpdGhpbkFycmF5PFQ+KGFycmF5OiBUW10sIGZyb21JbmRleDogbnVtYmVyLCB0b0luZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgLy8gVmFsaWRhdGUgaW5kaWNlc1xuICBpZiAoZnJvbUluZGV4IDwgMCB8fCBmcm9tSW5kZXggPj0gYXJyYXkubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBmcm9tSW5kZXggJHtmcm9tSW5kZXh9IGlzIG91dCBvZiBib3VuZHMgKGFycmF5IGxlbmd0aDogJHthcnJheS5sZW5ndGh9KWApXG4gIH1cbiAgaWYgKHRvSW5kZXggPCAwIHx8IHRvSW5kZXggPiBhcnJheS5sZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYHRvSW5kZXggJHt0b0luZGV4fSBpcyBvdXQgb2YgYm91bmRzIChhcnJheSBsZW5ndGg6ICR7YXJyYXkubGVuZ3RofSlgKVxuICB9XG4gIGlmIChmcm9tSW5kZXggPT09IHRvSW5kZXgpIHtcbiAgICByZXR1cm4gLy8gTm8tb3BcbiAgfVxuXG4gIC8vIFNldCB1cCB0aGUgbW92ZSBjb250ZXh0IGJlZm9yZSBtdXRhdGlvbnNcbiAgYWN0aXZlTW92ZUNvbnRleHQgPSB7XG4gICAgYXJyYXksXG4gICAgZnJvbUluZGV4LFxuICAgIHRvSW5kZXgsXG4gICAgcGF0aDogdW5kZWZpbmVkLFxuICAgIHJlY2VpdmVkRmlyc3RTcGxpY2U6IGZhbHNlLFxuICB9XG5cbiAgdHJ5IHtcbiAgICAvLyBQZXJmb3JtIHRoZSBhY3R1YWwgc3BsaWNlIG9wZXJhdGlvbnNcbiAgICAvLyBUaGlzIHdpbGwgdHJpZ2dlciBvbkRlZXBDaGFuZ2UgZm9yIGVhY2ggc3BsaWNlXG4gICAgY29uc3QgW2l0ZW1dID0gYXJyYXkuc3BsaWNlKGZyb21JbmRleCwgMSlcbiAgICBjb25zdCBhZGp1c3RlZFRhcmdldCA9IHRvSW5kZXggPiBmcm9tSW5kZXggPyB0b0luZGV4IC0gMSA6IHRvSW5kZXhcbiAgICBhcnJheS5zcGxpY2UoYWRqdXN0ZWRUYXJnZXQsIDAsIGl0ZW0pXG4gIH0gZmluYWxseSB7XG4gICAgYWN0aXZlTW92ZUNvbnRleHQgPSB1bmRlZmluZWRcbiAgfVxufVxuXG4vKipcbiAqIENoZWNrIGlmIGEgY2hhbmdlIGlzIHBhcnQgb2YgYW4gYWN0aXZlIG1vdmUgb3BlcmF0aW9uIGFuZCBwcm9jZXNzIGl0LlxuICogVGhpcyBpcyBjYWxsZWQgZm9yIEFycmF5U3BsaWNlIGNoYW5nZXMgb24gdGhlIHRhcmdldCBhcnJheS5cbiAqXG4gKiBAcGFyYW0gY2hhbmdlIFRoZSBkZWVwIGNoYW5nZSAobXVzdCBiZSBBcnJheVNwbGljZSB0eXBlKVxuICogQHJldHVybnMgVGhlIEFycmF5TW92ZUNoYW5nZSBpZiB0aGUgbW92ZSBpcyBjb21wbGV0ZSAoc2Vjb25kIHNwbGljZSksXG4gKiAgICAgICAgICB1bmRlZmluZWQgaWYgaW50ZXJjZXB0ZWQgYnV0IG5vdCBjb21wbGV0ZSAoZmlyc3Qgc3BsaWNlKVxuICovXG5leHBvcnQgZnVuY3Rpb24gcHJvY2Vzc0NoYW5nZUZvck1vdmUoY2hhbmdlOiBEZWVwQ2hhbmdlKTogQXJyYXlNb3ZlQ2hhbmdlIHwgdW5kZWZpbmVkIHtcbiAgLy8gV2Uga25vdyB3ZSdyZSBpbiBhIG1vdmUgY29udGV4dCBhbmQgdGhpcyBpcyBhbiBBcnJheVNwbGljZSBvbiB0aGUgdGFyZ2V0IGFycmF5XG4gIGNvbnN0IGN0eCA9IGFjdGl2ZU1vdmVDb250ZXh0IVxuXG4gIGlmICghY3R4LnJlY2VpdmVkRmlyc3RTcGxpY2UpIHtcbiAgICAvLyBGaXJzdCBzcGxpY2UgLSBjYXB0dXJlIHRoZSBwYXRoIGFuZCBtYXJrIGFzIHJlY2VpdmVkXG4gICAgY3R4LnBhdGggPSBjaGFuZ2UucGF0aFxuICAgIGN0eC5yZWNlaXZlZEZpcnN0U3BsaWNlID0gdHJ1ZVxuICAgIHJldHVybiB1bmRlZmluZWRcbiAgfVxuXG4gIC8vIFNlY29uZCBzcGxpY2UgLSB0aGUgbW92ZSBpcyBjb21wbGV0ZS5cbiAgLy8gTm90ZTogV2UgYWRqdXN0IHRvSW5kZXggaGVyZSBmb3IgTG9ybydzIG1vdmUoKSBzZW1hbnRpY3MsIHdoaWNoIGV4cGVjdHNcbiAgLy8gdGhlIHRhcmdldCBwb3NpdGlvbiBhZnRlciByZW1vdmFsLiBUaGlzIGlzIGludGVudGlvbmFsbHkgc2VwYXJhdGUgZnJvbVxuICAvLyB0aGUgYWRqdXN0bWVudCBvbiBsaW5lIDY0LCB3aGljaCBpcyBmb3IgdGhlIHNwbGljZSBvcGVyYXRpb24gb24gdGhlIE1vYlggYXJyYXkuXG4gIC8vIEJvdGggYWRqdXN0bWVudHMgYXJlIG5lZWRlZCBiZWNhdXNlOlxuICAvLyAtIExpbmUgNjQ6IHNwbGljZSgpIGluc2VydHMgYXQgYSBwb3NpdGlvbiBpbiB0aGUgYWxyZWFkeS1zaG9ydGVuZWQgYXJyYXlcbiAgLy8gLSBIZXJlOiBMb3JvJ3MgbW92ZShmcm9tLCB0bykgYWxzbyBleHBlY3RzIGB0b2AgYXMgdGhlIHBvc2l0aW9uIGFmdGVyIHJlbW92YWxcbiAgY29uc3QgYWRqdXN0ZWRUb0luZGV4ID0gY3R4LnRvSW5kZXggPiBjdHguZnJvbUluZGV4ID8gY3R4LnRvSW5kZXggLSAxIDogY3R4LnRvSW5kZXhcblxuICByZXR1cm4ge1xuICAgIHR5cGU6IFwiQXJyYXlNb3ZlXCIsXG4gICAgcGF0aDogY3R4LnBhdGghLFxuICAgIGZyb21JbmRleDogY3R4LmZyb21JbmRleCxcbiAgICB0b0luZGV4OiBhZGp1c3RlZFRvSW5kZXgsXG4gIH1cbn1cblxuLyoqXG4gKiBDaGVjayBpZiB3ZSdyZSBjdXJyZW50bHkgaW4gYSBtb3ZlIGNvbnRleHQgZm9yIGEgc3BlY2lmaWMgYXJyYXkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0luTW92ZUNvbnRleHRGb3JBcnJheShhcnJheTogdW5rbm93bltdKTogYm9vbGVhbiB7XG4gIHJldHVybiBhY3RpdmVNb3ZlQ29udGV4dCAhPT0gdW5kZWZpbmVkICYmIGFjdGl2ZU1vdmVDb250ZXh0LmFycmF5ID09PSBhcnJheVxufVxuIiwiaW1wb3J0IHtcbiAgdHlwZSBDb250YWluZXJJRCxcbiAgdHlwZSBMb3JvRG9jLFxuICB0eXBlIExvcm9FdmVudEJhdGNoLFxuICBMb3JvTWFwLFxuICBMb3JvTW92YWJsZUxpc3QsXG4gIExvcm9UZXh0LFxufSBmcm9tIFwibG9yby1jcmR0XCJcbmltcG9ydCB7IGFjdGlvbiB9IGZyb20gXCJtb2J4XCJcbmltcG9ydCB7XG4gIEFueURhdGFNb2RlbCxcbiAgQW55TW9kZWwsXG4gIEFueVN0YW5kYXJkVHlwZSxcbiAgRGVlcENoYW5nZSxcbiAgRGVlcENoYW5nZVR5cGUsXG4gIGZyb21TbmFwc2hvdCxcbiAgZ2V0UGFyZW50VG9DaGlsZFBhdGgsXG4gIGdldFNuYXBzaG90LFxuICBpc1RyZWVOb2RlLFxuICBNb2RlbENsYXNzLFxuICBvbkRlZXBDaGFuZ2UsXG4gIG9uR2xvYmFsRGVlcENoYW5nZSxcbiAgb25TbmFwc2hvdCxcbiAgcmVzb2x2ZVBhdGgsXG4gIFNuYXBzaG90T3V0T2YsXG4gIFR5cGVUb0RhdGEsXG59IGZyb20gXCJtb2J4LWtleXN0b25lXCJcbmltcG9ydCB7IG5hbm9pZCB9IGZyb20gXCJuYW5vaWRcIlxuaW1wb3J0IHR5cGUgeyBQbGFpbkFycmF5LCBQbGFpbk9iamVjdCB9IGZyb20gXCIuLi9wbGFpblR5cGVzXCJcbmltcG9ydCB7IGdldE9yQ3JlYXRlTG9yb0NvbGxlY3Rpb25BdG9tIH0gZnJvbSBcIi4uL3V0aWxzL2dldE9yQ3JlYXRlTG9yb0NvbGxlY3Rpb25BdG9tXCJcbmltcG9ydCB0eXBlIHsgQmluZGFibGVMb3JvQ29udGFpbmVyIH0gZnJvbSBcIi4uL3V0aWxzL2lzQmluZGFibGVMb3JvQ29udGFpbmVyXCJcblxuaW1wb3J0IHsgYXBwbHlMb3JvRXZlbnRUb01vYngsIFJlY29uY2lsaWF0aW9uTWFwIH0gZnJvbSBcIi4vYXBwbHlMb3JvRXZlbnRUb01vYnhcIlxuaW1wb3J0IHsgYXBwbHlNb2J4Q2hhbmdlVG9Mb3JvT2JqZWN0IH0gZnJvbSBcIi4vYXBwbHlNb2J4Q2hhbmdlVG9Mb3JvT2JqZWN0XCJcbmltcG9ydCB7XG4gIGFwcGx5RGVsdGFUb0xvcm9UZXh0LFxuICBhcHBseUpzb25BcnJheVRvTG9yb01vdmFibGVMaXN0LFxuICBhcHBseUpzb25PYmplY3RUb0xvcm9NYXAsXG4gIGV4dHJhY3RUZXh0RGVsdGFGcm9tU25hcHNob3QsXG59IGZyb20gXCIuL2NvbnZlcnRKc29uVG9Mb3JvRGF0YVwiXG5pbXBvcnQgeyBjb252ZXJ0TG9yb0RhdGFUb0pzb24gfSBmcm9tIFwiLi9jb252ZXJ0TG9yb0RhdGFUb0pzb25cIlxuaW1wb3J0IHsgbG9yb1RleHRNb2RlbElkIH0gZnJvbSBcIi4vTG9yb1RleHRNb2RlbFwiXG5pbXBvcnQgeyB0eXBlIExvcm9CaW5kaW5nQ29udGV4dCwgbG9yb0JpbmRpbmdDb250ZXh0IH0gZnJvbSBcIi4vbG9yb0JpbmRpbmdDb250ZXh0XCJcbmltcG9ydCB7IHNldExvcm9Db250YWluZXJTbmFwc2hvdCB9IGZyb20gXCIuL2xvcm9TbmFwc2hvdFRyYWNraW5nXCJcbmltcG9ydCB7XG4gIHR5cGUgQXJyYXlNb3ZlQ2hhbmdlLFxuICBpc0luTW92ZUNvbnRleHRGb3JBcnJheSxcbiAgcHJvY2Vzc0NoYW5nZUZvck1vdmUsXG59IGZyb20gXCIuL21vdmVXaXRoaW5BcnJheVwiXG5cbi8qKlxuICogQ2FwdHVyZXMgc25hcHNob3RzIG9mIHRyZWUgbm9kZXMgaW4gYSBEZWVwQ2hhbmdlLlxuICogVGhpcyBlbnN1cmVzIHZhbHVlcyBhcmUgY2FwdHVyZWQgYXQgY2hhbmdlIHRpbWUsIG5vdCBhdCBhcHBseSB0aW1lLFxuICogcHJldmVudGluZyBpc3N1ZXMgd2hlbiB2YWx1ZXMgYXJlIG11dGF0ZWQgYWZ0ZXIgYmVpbmcgYWRkZWQgdG8gYSBjb2xsZWN0aW9uLlxuICovXG5mdW5jdGlvbiBjYXB0dXJlQ2hhbmdlU25hcHNob3RzKGNoYW5nZTogRGVlcENoYW5nZSk6IERlZXBDaGFuZ2Uge1xuICBpZiAoY2hhbmdlLnR5cGUgPT09IERlZXBDaGFuZ2VUeXBlLkFycmF5U3BsaWNlICYmIGNoYW5nZS5hZGRlZFZhbHVlcy5sZW5ndGggPiAwKSB7XG4gICAgY29uc3Qgc25hcHNob3RzID0gY2hhbmdlLmFkZGVkVmFsdWVzLm1hcCgodikgPT4gKGlzVHJlZU5vZGUodikgPyBnZXRTbmFwc2hvdCh2KSA6IHYpKVxuICAgIHJldHVybiB7IC4uLmNoYW5nZSwgYWRkZWRWYWx1ZXM6IHNuYXBzaG90cyB9XG4gIH0gZWxzZSBpZiAoY2hhbmdlLnR5cGUgPT09IERlZXBDaGFuZ2VUeXBlLkFycmF5VXBkYXRlKSB7XG4gICAgY29uc3Qgc25hcHNob3QgPSBpc1RyZWVOb2RlKGNoYW5nZS5uZXdWYWx1ZSkgPyBnZXRTbmFwc2hvdChjaGFuZ2UubmV3VmFsdWUpIDogY2hhbmdlLm5ld1ZhbHVlXG4gICAgcmV0dXJuIHsgLi4uY2hhbmdlLCBuZXdWYWx1ZTogc25hcHNob3QgfVxuICB9IGVsc2UgaWYgKFxuICAgIGNoYW5nZS50eXBlID09PSBEZWVwQ2hhbmdlVHlwZS5PYmplY3RBZGQgfHxcbiAgICBjaGFuZ2UudHlwZSA9PT0gRGVlcENoYW5nZVR5cGUuT2JqZWN0VXBkYXRlXG4gICkge1xuICAgIGNvbnN0IHNuYXBzaG90ID0gaXNUcmVlTm9kZShjaGFuZ2UubmV3VmFsdWUpID8gZ2V0U25hcHNob3QoY2hhbmdlLm5ld1ZhbHVlKSA6IGNoYW5nZS5uZXdWYWx1ZVxuICAgIHJldHVybiB7IC4uLmNoYW5nZSwgbmV3VmFsdWU6IHNuYXBzaG90IH1cbiAgfVxuICByZXR1cm4gY2hhbmdlXG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIGJpZGlyZWN0aW9uYWwgYmluZGluZyBiZXR3ZWVuIGEgTG9ybyBkYXRhIHN0cnVjdHVyZSBhbmQgYSBtb2J4LWtleXN0b25lIG1vZGVsLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYmluZExvcm9Ub01vYnhLZXlzdG9uZTxcbiAgVFR5cGUgZXh0ZW5kcyBBbnlTdGFuZGFyZFR5cGUgfCBNb2RlbENsYXNzPEFueU1vZGVsPiB8IE1vZGVsQ2xhc3M8QW55RGF0YU1vZGVsPixcbj4oe1xuICBsb3JvRG9jLFxuICBsb3JvT2JqZWN0LFxuICBtb2J4S2V5c3RvbmVUeXBlLFxufToge1xuICAvKipcbiAgICogVGhlIExvcm8gZG9jdW1lbnQuXG4gICAqL1xuICBsb3JvRG9jOiBMb3JvRG9jXG4gIC8qKlxuICAgKiBUaGUgYm91bmQgTG9ybyBkYXRhIHN0cnVjdHVyZS5cbiAgICovXG4gIGxvcm9PYmplY3Q6IEJpbmRhYmxlTG9yb0NvbnRhaW5lclxuICAvKipcbiAgICogVGhlIG1vYngta2V5c3RvbmUgbW9kZWwgdHlwZS5cbiAgICovXG4gIG1vYnhLZXlzdG9uZVR5cGU6IFRUeXBlXG59KToge1xuICAvKipcbiAgICogVGhlIGJvdW5kIG1vYngta2V5c3RvbmUgaW5zdGFuY2UuXG4gICAqL1xuICBib3VuZE9iamVjdDogVHlwZVRvRGF0YTxUVHlwZT5cbiAgLyoqXG4gICAqIERpc3Bvc2VzIHRoZSBiaW5kaW5nLlxuICAgKi9cbiAgZGlzcG9zZTogKCkgPT4gdm9pZFxuICAvKipcbiAgICogVGhlIExvcm8gb3JpZ2luIHN0cmluZyB1c2VkIGZvciBiaW5kaW5nIHRyYW5zYWN0aW9ucy5cbiAgICovXG4gIGxvcm9PcmlnaW46IHN0cmluZ1xufSB7XG4gIGNvbnN0IGxvcm9PcmlnaW4gPSBgYmluZExvcm9Ub01vYnhLZXlzdG9uZVRyYW5zYWN0aW9uT3JpZ2luLSR7bmFub2lkKCl9YFxuXG4gIGxldCBhcHBseWluZ0xvcm9DaGFuZ2VzVG9Nb2J4S2V5c3RvbmUgPSAwXG5cbiAgY29uc3QgYmluZGluZ0NvbnRleHQ6IExvcm9CaW5kaW5nQ29udGV4dCA9IHtcbiAgICBsb3JvRG9jLFxuICAgIGxvcm9PYmplY3QsXG4gICAgbW9ieEtleXN0b25lVHlwZSxcbiAgICBsb3JvT3JpZ2luLFxuICAgIGJvdW5kT2JqZWN0OiB1bmRlZmluZWQsIC8vIG5vdCB5ZXQgY3JlYXRlZFxuXG4gICAgZ2V0IGlzQXBwbHlpbmdMb3JvQ2hhbmdlc1RvTW9ieEtleXN0b25lKCkge1xuICAgICAgcmV0dXJuIGFwcGx5aW5nTG9yb0NoYW5nZXNUb01vYnhLZXlzdG9uZSA+IDBcbiAgICB9LFxuICB9XG5cbiAgY29uc3QgbG9yb0pzb24gPSBjb252ZXJ0TG9yb0RhdGFUb0pzb24obG9yb09iamVjdCkgYXMgU25hcHNob3RPdXRPZjxUeXBlVG9EYXRhPFRUeXBlPj5cblxuICBsZXQgYm91bmRPYmplY3Q6IFR5cGVUb0RhdGE8VFR5cGU+XG5cbiAgLy8gVHJhY2sgaWYgYW55IGluaXQgY2hhbmdlcyBvY2N1cnJlZCBkdXJpbmcgZnJvbVNuYXBzaG90XG4gIC8vIElmIHRoZXkgZGlkLCB3ZSBuZWVkIHRvIHN5bmMgdGhlIG1vZGVsIHNuYXBzaG90IHRvIHRoZSBDUkRUXG4gIGxldCBoYXNJbml0Q2hhbmdlcyA9IGZhbHNlXG5cbiAgY29uc3QgY3JlYXRlQm91bmRPYmplY3QgPSAoKSA9PiB7XG4gICAgLy8gU2V0IHVwIGEgdGVtcG9yYXJ5IGdsb2JhbCBsaXN0ZW5lciB0byBkZXRlY3QgaW5pdCBjaGFuZ2VzIGR1cmluZyBmcm9tU25hcHNob3RcbiAgICBjb25zdCBkaXNwb3NlR2xvYmFsTGlzdGVuZXIgPSBvbkdsb2JhbERlZXBDaGFuZ2UoKF90YXJnZXQsIGNoYW5nZSkgPT4ge1xuICAgICAgaWYgKGNoYW5nZS5pc0luaXQpIHtcbiAgICAgICAgaGFzSW5pdENoYW5nZXMgPSB0cnVlXG4gICAgICB9XG4gICAgfSlcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXN1bHQgPSBsb3JvQmluZGluZ0NvbnRleHQuYXBwbHkoXG4gICAgICAgICgpID0+IGZyb21TbmFwc2hvdChtb2J4S2V5c3RvbmVUeXBlLCBsb3JvSnNvbiksXG4gICAgICAgIGJpbmRpbmdDb250ZXh0XG4gICAgICApXG4gICAgICBsb3JvQmluZGluZ0NvbnRleHQuc2V0KHJlc3VsdCwgeyAuLi5iaW5kaW5nQ29udGV4dCwgYm91bmRPYmplY3Q6IHJlc3VsdCB9KVxuICAgICAgcmV0dXJuIHJlc3VsdFxuICAgIH0gZmluYWxseSB7XG4gICAgICBkaXNwb3NlR2xvYmFsTGlzdGVuZXIoKVxuICAgIH1cbiAgfVxuXG4gIGJvdW5kT2JqZWN0ID0gY3JlYXRlQm91bmRPYmplY3QoKVxuXG4gIC8vIEdldCB0aGUgcGF0aCB0byB0aGUgcm9vdCBMb3JvIG9iamVjdCBmb3IgcGF0aCByZXNvbHV0aW9uXG4gIGNvbnN0IHJvb3RMb3JvUGF0aCA9IGxvcm9Eb2MuZ2V0UGF0aFRvQ29udGFpbmVyKGxvcm9PYmplY3QuaWQpID8/IFtdXG5cbiAgLy8gYmluZCBhbnkgY2hhbmdlcyBmcm9tIExvcm8gdG8gbW9ieC1rZXlzdG9uZVxuICBjb25zdCBsb3JvU3Vic2NyaWJlQ2IgPSBhY3Rpb24oKGV2ZW50QmF0Y2g6IExvcm9FdmVudEJhdGNoKSA9PiB7XG4gICAgLy8gU2tpcCBjaGFuZ2VzIHRoYXQgb3JpZ2luYXRlZCBmcm9tIHRoaXMgYmluZGluZ1xuICAgIGlmIChldmVudEJhdGNoLm9yaWdpbiA9PT0gbG9yb09yaWdpbikge1xuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgLy8gVHJhY2sgbmV3bHkgaW5zZXJ0ZWQgY29udGFpbmVycyB0byBhdm9pZCBkb3VibGUtcHJvY2Vzc2luZyB0aGVpciBldmVudHNcbiAgICBjb25zdCBuZXdseUluc2VydGVkQ29udGFpbmVycyA9IG5ldyBTZXQ8Q29udGFpbmVySUQ+KClcblxuICAgIC8vIENyZWF0ZSBhIG1hcCB0byBzdG9yZSByZWNvbmNpbGlhdGlvbiBkYXRhIGZvciB0aGlzIGJhdGNoXG4gICAgY29uc3QgcmVjb25jaWxpYXRpb25NYXA6IFJlY29uY2lsaWF0aW9uTWFwID0gbmV3IE1hcCgpXG5cbiAgICAvLyBDb2xsZWN0IGluaXQgY2hhbmdlcyB0aGF0IG9jY3VyIGR1cmluZyBldmVudCBhcHBsaWNhdGlvblxuICAgIC8vIChlLmcuLCBmcm9tU25hcHNob3QgY2FsbHMgdGhhdCB0cmlnZ2VyIG9uSW5pdCBob29rcylcbiAgICAvLyBXZSBzdG9yZSBib3RoIHRhcmdldCBhbmQgY2hhbmdlIHNvIHdlIGNhbiBjb21wdXRlIHRoZSBjb3JyZWN0IHBhdGggbGF0ZXJcbiAgICAvLyBTbmFwc2hvdHMgYXJlIGNhcHR1cmVkIGltbWVkaWF0ZWx5IHRvIHByZXNlcnZlIHZhbHVlcyBhdCBpbml0IHRpbWVcbiAgICBjb25zdCBpbml0Q2hhbmdlczogeyB0YXJnZXQ6IG9iamVjdDsgY2hhbmdlOiBEZWVwQ2hhbmdlIH1bXSA9IFtdXG4gICAgY29uc3QgZGlzcG9zZUdsb2JhbExpc3RlbmVyID0gb25HbG9iYWxEZWVwQ2hhbmdlKCh0YXJnZXQsIGNoYW5nZSkgPT4ge1xuICAgICAgaWYgKGNoYW5nZS5pc0luaXQpIHtcbiAgICAgICAgaW5pdENoYW5nZXMucHVzaCh7IHRhcmdldCwgY2hhbmdlOiBjYXB0dXJlQ2hhbmdlU25hcHNob3RzKGNoYW5nZSkgfSlcbiAgICAgIH1cbiAgICB9KVxuXG4gICAgYXBwbHlpbmdMb3JvQ2hhbmdlc1RvTW9ieEtleXN0b25lKytcbiAgICB0cnkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZm9yIChjb25zdCBldmVudCBvZiBldmVudEJhdGNoLmV2ZW50cykge1xuICAgICAgICAgIGFwcGx5TG9yb0V2ZW50VG9Nb2J4KFxuICAgICAgICAgICAgZXZlbnQsXG4gICAgICAgICAgICBsb3JvRG9jLFxuICAgICAgICAgICAgYm91bmRPYmplY3QsXG4gICAgICAgICAgICByb290TG9yb1BhdGgsXG4gICAgICAgICAgICByZWNvbmNpbGlhdGlvbk1hcCxcbiAgICAgICAgICAgIG5ld2x5SW5zZXJ0ZWRDb250YWluZXJzXG4gICAgICAgICAgKVxuICAgICAgICB9XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBkaXNwb3NlR2xvYmFsTGlzdGVuZXIoKVxuICAgICAgfVxuXG4gICAgICAvLyBTeW5jIGJhY2sgYW55IGluaXQtdGltZSBtdXRhdGlvbnMgZnJvbSBmcm9tU25hcHNob3QgY2FsbHNcbiAgICAgIC8vIChlLmcuLCBvbkluaXQgaG9va3MgdGhhdCBtb2RpZnkgdGhlIG1vZGVsKVxuICAgICAgLy8gVGhpcyBpcyBuZWVkZWQgYmVjYXVzZSBpbml0IGNoYW5nZXMgZHVyaW5nIExvcm8gZXZlbnQgaGFuZGxpbmcgYXJlIG5vdFxuICAgICAgLy8gY2FwdHVyZWQgYnkgdGhlIG1haW4gb25EZWVwQ2hhbmdlIChpdCBza2lwcyBjaGFuZ2VzIHdoZW4gYXBwbHlpbmdMb3JvQ2hhbmdlc1RvTW9ieEtleXN0b25lID4gMClcbiAgICAgIGlmIChpbml0Q2hhbmdlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGxvcm9Eb2Muc2V0TmV4dENvbW1pdE9yaWdpbihsb3JvT3JpZ2luKVxuXG4gICAgICAgIGZvciAoY29uc3QgeyB0YXJnZXQsIGNoYW5nZSB9IG9mIGluaXRDaGFuZ2VzKSB7XG4gICAgICAgICAgLy8gQ29tcHV0ZSB0aGUgcGF0aCBmcm9tIGJvdW5kT2JqZWN0IHRvIHRoZSB0YXJnZXRcbiAgICAgICAgICBjb25zdCBwYXRoVG9UYXJnZXQgPSBnZXRQYXJlbnRUb0NoaWxkUGF0aChib3VuZE9iamVjdCwgdGFyZ2V0KVxuICAgICAgICAgIGlmIChwYXRoVG9UYXJnZXQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgLy8gQ3JlYXRlIGEgbmV3IGNoYW5nZSB3aXRoIHRoZSBjb3JyZWN0IHBhdGggZnJvbSB0aGUgcm9vdFxuICAgICAgICAgICAgY29uc3QgY2hhbmdlV2l0aENvcnJlY3RQYXRoOiBEZWVwQ2hhbmdlID0ge1xuICAgICAgICAgICAgICAuLi5jaGFuZ2UsXG4gICAgICAgICAgICAgIHBhdGg6IFsuLi5wYXRoVG9UYXJnZXQsIC4uLmNoYW5nZS5wYXRoXSxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGFwcGx5TW9ieENoYW5nZVRvTG9yb09iamVjdChjaGFuZ2VXaXRoQ29ycmVjdFBhdGgsIGxvcm9PYmplY3QpXG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgbG9yb0RvYy5jb21taXQoKVxuICAgICAgfVxuXG4gICAgICAvLyBVcGRhdGUgc25hcHNob3QgdHJhY2tpbmc6IHRoZSBMb3JvIGNvbnRhaW5lciBpcyBub3cgaW4gc3luYyB3aXRoIHRoZSBjdXJyZW50IE1vYlggc25hcHNob3RcbiAgICAgIC8vIFRoaXMgZW5hYmxlcyB0aGUgbWVyZ2Ugb3B0aW1pemF0aW9uIHRvIHNraXAgdW5jaGFuZ2VkIHN1YnRyZWVzIGR1cmluZyByZWNvbmNpbGlhdGlvblxuICAgICAgaWYgKGxvcm9PYmplY3QgaW5zdGFuY2VvZiBMb3JvTWFwIHx8IGxvcm9PYmplY3QgaW5zdGFuY2VvZiBMb3JvTW92YWJsZUxpc3QpIHtcbiAgICAgICAgc2V0TG9yb0NvbnRhaW5lclNuYXBzaG90KGxvcm9PYmplY3QsIGdldFNuYXBzaG90KGJvdW5kT2JqZWN0KSlcbiAgICAgIH1cbiAgICB9IGZpbmFsbHkge1xuICAgICAgYXBwbHlpbmdMb3JvQ2hhbmdlc1RvTW9ieEtleXN0b25lLS1cbiAgICB9XG4gIH0pXG4gIGNvbnN0IGxvcm9VbnN1YnNjcmliZSA9IGxvcm9Eb2Muc3Vic2NyaWJlKGxvcm9TdWJzY3JpYmVDYilcblxuICAvLyBiaW5kIGFueSBjaGFuZ2VzIGZyb20gbW9ieC1rZXlzdG9uZSB0byBMb3JvXG4gIC8vIENvbGxlY3QgY2hhbmdlcyBkdXJpbmcgYW4gYWN0aW9uIGFuZCBhcHBseSB0aGVtIGFmdGVyIHRoZSBhY3Rpb24gY29tcGxldGVzXG4gIGxldCBwZW5kaW5nQ2hhbmdlczogKERlZXBDaGFuZ2UgfCBBcnJheU1vdmVDaGFuZ2UpW10gPSBbXVxuXG4gIGNvbnN0IGRpc3Bvc2VPbkRlZXBDaGFuZ2UgPSBvbkRlZXBDaGFuZ2UoYm91bmRPYmplY3QsIChjaGFuZ2UpID0+IHtcbiAgICAvLyBTa2lwIGlmIHdlJ3JlIGN1cnJlbnRseSBhcHBseWluZyBMb3JvIGNoYW5nZXMgdG8gTW9iWFxuICAgIGlmIChiaW5kaW5nQ29udGV4dC5pc0FwcGx5aW5nTG9yb0NoYW5nZXNUb01vYnhLZXlzdG9uZSkge1xuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgLy8gU2tpcCBpbml0IGNoYW5nZXMgLSB0aGV5IGFyZSBoYW5kbGVkIGJ5IHRoZSBnZXRTbmFwc2hvdCArIG1lcmdlIGF0IHRoZSBlbmQgb2YgYmluZGluZ1xuICAgIGlmIChjaGFuZ2UuaXNJbml0KSB7XG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICAvLyBDaGVjayBpZiB0aGlzIGlzIHBhcnQgb2YgYSBtb3ZlV2l0aGluQXJyYXkgb3BlcmF0aW9uXG4gICAgaWYgKGNoYW5nZS50eXBlID09PSBEZWVwQ2hhbmdlVHlwZS5BcnJheVNwbGljZSkge1xuICAgICAgY29uc3QgcmVzb2x2ZWQgPSByZXNvbHZlUGF0aChib3VuZE9iamVjdCwgY2hhbmdlLnBhdGgpXG4gICAgICBpZiAocmVzb2x2ZWQucmVzb2x2ZWQgJiYgaXNJbk1vdmVDb250ZXh0Rm9yQXJyYXkocmVzb2x2ZWQudmFsdWUgYXMgdW5rbm93bltdKSkge1xuICAgICAgICBjb25zdCBtb3ZlUmVzdWx0ID0gcHJvY2Vzc0NoYW5nZUZvck1vdmUoY2hhbmdlKVxuXG4gICAgICAgIGlmIChtb3ZlUmVzdWx0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAvLyBJbnRlcmNlcHRlZCBidXQgbW92ZSBub3QgY29tcGxldGUgLSBza2lwIHRoaXMgY2hhbmdlXG4gICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cblxuICAgICAgICAvLyBNb3ZlIGNvbXBsZXRlIC0gYWRkIHRoZSBtb3ZlIGNoYW5nZSBpbnN0ZWFkXG4gICAgICAgIHBlbmRpbmdDaGFuZ2VzLnB1c2gobW92ZVJlc3VsdClcbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ2FwdHVyZSBzbmFwc2hvdHMgbm93IGJlZm9yZSB0aGUgdmFsdWVzIGNhbiBiZSBtdXRhdGVkIHdpdGhpbiB0aGUgc2FtZSB0cmFuc2FjdGlvbi5cbiAgICAvLyBUaGlzIGlzIG5lY2Vzc2FyeSBiZWNhdXNlIGNoYW5nZXMgYXJlIGNvbGxlY3RlZCBhbmQgYXBwbGllZCBhZnRlciB0aGUgYWN0aW9uIGNvbXBsZXRlcyxcbiAgICAvLyBieSB3aGljaCB0aW1lIHRoZSBvcmlnaW5hbCB2YWx1ZXMgbWF5IGhhdmUgYmVlbiBtb2RpZmllZC5cbiAgICAvLyBFeGFtcGxlOiBgb2JqLml0ZW1zID0gW2EsIGJdOyBvYmouaXRlbXMuc3BsaWNlKDAsIDEpYCAtIHdpdGhvdXQgZWFybHkgY2FwdHVyZSxcbiAgICAvLyB0aGUgT2JqZWN0VXBkYXRlIGZvciBgaXRlbXNgIHdvdWxkIGdldCB0aGUgcG9zdC1zcGxpY2UgYXJyYXkgc3RhdGUuXG4gICAgcGVuZGluZ0NoYW5nZXMucHVzaChjYXB0dXJlQ2hhbmdlU25hcHNob3RzKGNoYW5nZSkpXG4gIH0pXG5cbiAgLy8gQXBwbHkgY29sbGVjdGVkIGNoYW5nZXMgd2hlbiBzbmFwc2hvdCBjaGFuZ2VzIChpLmUuLCBhZnRlciBhY3Rpb24gY29tcGxldGVzKVxuICAvLyBBbHNvIG5vdGlmeSB0aGF0IHRoZSBsb3JvIGNvbnRhaW5lciBhdG9tcyBoYXZlIGJlZW4gdXBkYXRlZFxuICBjb25zdCBkaXNwb3NlT25TbmFwc2hvdCA9IG9uU25hcHNob3QoYm91bmRPYmplY3QsICgpID0+IHtcbiAgICBpZiAocGVuZGluZ0NoYW5nZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBjb25zdCBjaGFuZ2VzVG9BcHBseSA9IHBlbmRpbmdDaGFuZ2VzXG4gICAgcGVuZGluZ0NoYW5nZXMgPSBbXVxuXG4gICAgLy8gU2tpcCBpZiB3ZSdyZSBjdXJyZW50bHkgYXBwbHlpbmcgTG9ybyBjaGFuZ2VzIHRvIE1vYlhcbiAgICBpZiAoYmluZGluZ0NvbnRleHQuaXNBcHBseWluZ0xvcm9DaGFuZ2VzVG9Nb2J4S2V5c3RvbmUpIHtcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIGxvcm9Eb2Muc2V0TmV4dENvbW1pdE9yaWdpbihsb3JvT3JpZ2luKVxuXG4gICAgLy8gQXBwbHkgYWxsIGNoYW5nZXMgZGlyZWN0bHkgdG8gTG9yb1xuICAgIGZvciAoY29uc3QgY2hhbmdlIG9mIGNoYW5nZXNUb0FwcGx5KSB7XG4gICAgICBhcHBseU1vYnhDaGFuZ2VUb0xvcm9PYmplY3QoY2hhbmdlLCBsb3JvT2JqZWN0KVxuICAgIH1cblxuICAgIGxvcm9Eb2MuY29tbWl0KClcblxuICAgIC8vIFVwZGF0ZSBzbmFwc2hvdCB0cmFja2luZzogdGhlIExvcm8gY29udGFpbmVyIGlzIG5vdyBpbiBzeW5jIHdpdGggdGhlIGN1cnJlbnQgTW9iWCBzbmFwc2hvdFxuICAgIGlmIChsb3JvT2JqZWN0IGluc3RhbmNlb2YgTG9yb01hcCB8fCBsb3JvT2JqZWN0IGluc3RhbmNlb2YgTG9yb01vdmFibGVMaXN0KSB7XG4gICAgICBzZXRMb3JvQ29udGFpbmVyU25hcHNob3QobG9yb09iamVjdCwgZ2V0U25hcHNob3QoYm91bmRPYmplY3QpKVxuICAgIH1cblxuICAgIC8vIE5vdGlmeSBNb2JYIHRoYXQgdGhlIExvcm8gY29udGFpbmVyIGhhcyBiZWVuIHVwZGF0ZWRcbiAgICBnZXRPckNyZWF0ZUxvcm9Db2xsZWN0aW9uQXRvbShsb3JvT2JqZWN0KS5yZXBvcnRDaGFuZ2VkKClcbiAgfSlcblxuICAvLyBTeW5jIHRoZSBtb2RlbCBzbmFwc2hvdCB0byB0aGUgQ1JEVCBpZiBhbnkgaW5pdCBjaGFuZ2VzIG9jY3VycmVkLlxuICAvLyBJbml0IGNoYW5nZXMgaW5jbHVkZTogZGVmYXVsdHMgYmVpbmcgYXBwbGllZCwgb25Jbml0IGhvb2tzIG11dGF0aW5nIHRoZSBtb2RlbC5cbiAgLy8gVGhpcyBpcyBhbiBvcHRpbWl6YXRpb246IGlmIG5vIGluaXQgY2hhbmdlcyBvY2N1cnJlZCwgd2Ugc2tpcCB0aGUgc3luYyBlbnRpcmVseS5cbiAgY29uc3QgZmluYWxTbmFwc2hvdCA9IGdldFNuYXBzaG90KGJvdW5kT2JqZWN0KVxuXG4gIGlmIChoYXNJbml0Q2hhbmdlcykge1xuICAgIGxvcm9Eb2Muc2V0TmV4dENvbW1pdE9yaWdpbihsb3JvT3JpZ2luKVxuXG4gICAgaWYgKGxvcm9PYmplY3QgaW5zdGFuY2VvZiBMb3JvTWFwKSB7XG4gICAgICBhcHBseUpzb25PYmplY3RUb0xvcm9NYXAobG9yb09iamVjdCwgZmluYWxTbmFwc2hvdCBhcyBQbGFpbk9iamVjdCwgeyBtb2RlOiBcIm1lcmdlXCIgfSlcbiAgICB9IGVsc2UgaWYgKGxvcm9PYmplY3QgaW5zdGFuY2VvZiBMb3JvTW92YWJsZUxpc3QpIHtcbiAgICAgIGFwcGx5SnNvbkFycmF5VG9Mb3JvTW92YWJsZUxpc3QobG9yb09iamVjdCwgZmluYWxTbmFwc2hvdCBhcyBQbGFpbkFycmF5LCB7IG1vZGU6IFwibWVyZ2VcIiB9KVxuICAgIH0gZWxzZSBpZiAobG9yb09iamVjdCBpbnN0YW5jZW9mIExvcm9UZXh0KSB7XG4gICAgICAvLyBGb3IgTG9yb1RleHQsIHdlIG5lZWQgdG8gaGFuZGxlIExvcm9UZXh0TW9kZWwgc25hcHNob3RcbiAgICAgIGNvbnN0IHNuYXBzaG90ID0gZmluYWxTbmFwc2hvdCBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPlxuICAgICAgaWYgKHNuYXBzaG90LiRtb2RlbFR5cGUgPT09IGxvcm9UZXh0TW9kZWxJZCkge1xuICAgICAgICAvLyBDbGVhciBleGlzdGluZyBjb250ZW50IGFuZCBhcHBseSBkZWx0YXNcbiAgICAgICAgaWYgKGxvcm9PYmplY3QubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGxvcm9PYmplY3QuZGVsZXRlKDAsIGxvcm9PYmplY3QubGVuZ3RoKVxuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGRlbHRhcyA9IGV4dHJhY3RUZXh0RGVsdGFGcm9tU25hcHNob3Qoc25hcHNob3QuZGVsdGFMaXN0KVxuICAgICAgICBpZiAoZGVsdGFzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBhcHBseURlbHRhVG9Mb3JvVGV4dChsb3JvT2JqZWN0LCBkZWx0YXMpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBsb3JvRG9jLmNvbW1pdCgpXG4gIH1cblxuICAvLyBBbHdheXMgdXBkYXRlIHNuYXBzaG90IHRyYWNraW5nIGFmdGVyIGJpbmRpbmcgaW5pdGlhbGl6YXRpb25cbiAgLy8gVGhpcyBlbnN1cmVzIHRoZSBtZXJnZSBvcHRpbWl6YXRpb24gY2FuIHNraXAgdW5jaGFuZ2VkIHN1YnRyZWVzIGluIGZ1dHVyZSByZWNvbmNpbGlhdGlvbnNcbiAgaWYgKGxvcm9PYmplY3QgaW5zdGFuY2VvZiBMb3JvTWFwIHx8IGxvcm9PYmplY3QgaW5zdGFuY2VvZiBMb3JvTW92YWJsZUxpc3QpIHtcbiAgICBzZXRMb3JvQ29udGFpbmVyU25hcHNob3QobG9yb09iamVjdCwgZmluYWxTbmFwc2hvdClcbiAgfVxuXG4gIGNvbnN0IGRpc3Bvc2UgPSAoKSA9PiB7XG4gICAgbG9yb1Vuc3Vic2NyaWJlKClcbiAgICBkaXNwb3NlT25EZWVwQ2hhbmdlKClcbiAgICBkaXNwb3NlT25TbmFwc2hvdCgpXG4gIH1cblxuICByZXR1cm4ge1xuICAgIGJvdW5kT2JqZWN0LFxuICAgIGRpc3Bvc2UsXG4gICAgbG9yb09yaWdpbixcbiAgfVxufVxuIl0sIm5hbWVzIjpbImxvcm9PYmplY3QiLCJyZXN1bHQiXSwibWFwcGluZ3MiOiI7Ozs7OztBQW1CQSxJQUFJLFNBQVMsQ0FBQyxPQUFPLE9BQ25CLE9BQU8sZ0JBQWdCLElBQUksV0FBVyxJQUFJLENBQUMsRUFBRSxPQUFPLENBQUMsSUFBSSxTQUFTO0FBQ2hFLFVBQVE7QUFDUixNQUFJLE9BQU8sSUFBSTtBQUNiLFVBQU0sS0FBSyxTQUFTLEVBQUU7QUFBQSxFQUN4QixXQUFXLE9BQU8sSUFBSTtBQUNwQixXQUFPLE9BQU8sSUFBSSxTQUFTLEVBQUUsRUFBRSxZQUFXO0FBQUEsRUFDNUMsV0FBVyxPQUFPLElBQUk7QUFDcEIsVUFBTTtBQUFBLEVBQ1IsT0FBTztBQUNMLFVBQU07QUFBQSxFQUNSO0FBQ0EsU0FBTztBQUNULEdBQUcsRUFBRTtBQzdCUCxNQUFNLDhCQUFjLFFBQUE7QUFNYixTQUFTLDhCQUE4QixZQUEwQztBQUN0RixNQUFJLE9BQU8sUUFBUSxJQUFJLFVBQVU7QUFDakMsTUFBSSxDQUFDLE1BQU07QUFDVCxXQUFPLFdBQVcsb0JBQW9CO0FBQ3RDLFlBQVEsSUFBSSxZQUFZLElBQUk7QUFBQSxFQUM5QjtBQUNBLFNBQU87QUFDVDtBQ2hCTyxNQUFNLDhCQUE4QixNQUFNO0FBQUEsRUFDL0MsWUFBWSxLQUFhO0FBQ3ZCLFVBQU0sR0FBRztBQUdULFdBQU8sZUFBZSxNQUFNLHNCQUFzQixTQUFTO0FBQUEsRUFDN0Q7QUFDRjtBQUVPLFNBQVMsUUFBUSxTQUF3QjtBQUM5QyxRQUFNLElBQUksc0JBQXNCLE9BQU87QUFDekM7QUNrQ08sTUFBTSxxQkFBcUIsY0FBOEMsTUFBUztBQy9CbEYsU0FBUyxnQkFBZ0IsWUFBbUMsTUFBcUI7QUFDdEYsTUFBSSxvQkFBNkI7QUFFakMsT0FBSyxRQUFRLENBQUMsVUFBVSxNQUFNO0FBQzVCLFFBQUksNkJBQTZCLFNBQVM7QUFDeEMsb0NBQThCLGlCQUFpQixFQUFFLGVBQUE7QUFDakQsWUFBTSxNQUFNLE9BQU8sUUFBUTtBQUMzQiwwQkFBb0Isa0JBQWtCLElBQUksR0FBRztBQUFBLElBQy9DLFdBQVcsNkJBQTZCLGlCQUFpQjtBQUN2RCxvQ0FBOEIsaUJBQWlCLEVBQUUsZUFBQTtBQUNqRCxZQUFNLE1BQU0sT0FBTyxRQUFRO0FBQzNCLDBCQUFvQixrQkFBa0IsSUFBSSxHQUFHO0FBQUEsSUFDL0MsT0FBTztBQUNMLFlBQU07QUFBQSxRQUNKLG1EQUFtRCxLQUFLO0FBQUEsVUFDdEQsS0FBSyxNQUFNLEdBQUcsQ0FBQztBQUFBLFFBQUEsQ0FDaEIsNkJBQTZCLEtBQUssVUFBVSxJQUFJLENBQUMsYUFBYSxpQkFBaUI7QUFBQSxNQUFBO0FBQUEsSUFFcEY7QUFBQSxFQUNGLENBQUM7QUFFRCxTQUFPO0FBQ1Q7Ozs7Ozs7Ozs7O0FDbkJPLE1BQU0sa0JBQWtCO0FBYXhCLElBQU0sZ0JBQU4sY0FBNEIsTUFBTTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFLdkMsV0FBVyxNQUFNLE1BQU0sT0FBTyxNQUFNLFdBQThCLEdBQUcsTUFBTSxPQUFPLEVBQUUsQ0FBQztBQUN2RixDQUFDLEVBQUU7QUFBQSxFQU5JO0FBQUE7QUE0Qkw7QUFBQTtBQUFBO0FBQUEsK0NBQXNCLFdBQVcscUJBQXFCO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQWxCdEQsT0FBTyxTQUFTLE1BQTZCO0FBQzNDLFdBQU8sSUFBSSxjQUFjO0FBQUEsTUFDdkIsV0FBVyxPQUFPLENBQUMsRUFBRSxRQUFRLEtBQUEsQ0FBTSxDQUFDO0FBQUEsSUFBQSxDQUNyQztBQUFBLEVBQ0g7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQUtBLE9BQU8sVUFBVSxPQUF5QztBQUN4RCxXQUFPLElBQUksY0FBYztBQUFBLE1BQ3ZCLFdBQVcsT0FBTyxLQUFLO0FBQUEsSUFBQSxDQUN4QjtBQUFBLEVBQ0g7QUFBQSxFQVlBLElBQUksV0FBaUM7QUFFbkMsVUFBTSxNQUFNLG1CQUFtQixJQUFJLElBQUk7QUFDdkMsU0FBSSwyQkFBSyxnQkFBZSxNQUFNO0FBQzVCLGFBQU87QUFBQSxJQUNUO0FBRUEsUUFBSTtBQUNGLFlBQU0sT0FBTyxxQkFBcUIsSUFBSSxhQUFhLElBQUk7QUFDdkQsVUFBSSxDQUFDLE1BQU07QUFDVCxlQUFPO0FBQUEsTUFDVDtBQUdBLFVBQUksS0FBSyxXQUFXLEdBQUc7QUFDckIsY0FBTUEsY0FBYSxJQUFJO0FBQ3ZCLFlBQUlBLHVCQUFzQixVQUFVO0FBQ2xDLHdDQUE4QkEsV0FBVSxFQUFFLGVBQUE7QUFDMUMsaUJBQU9BO0FBQUFBLFFBQ1Q7QUFDQSxlQUFPO0FBQUEsTUFDVDtBQUdBLFlBQU0sYUFBYSxnQkFBZ0IsSUFBSSxZQUFZLElBQUk7QUFFdkQsVUFBSSxzQkFBc0IsVUFBVTtBQUNsQyxzQ0FBOEIsVUFBVSxFQUFFLGVBQUE7QUFDMUMsZUFBTztBQUFBLE1BQ1Q7QUFBQSxJQUNGLFFBQVE7QUFBQSxJQUVSO0FBRUEsV0FBTztBQUFBLEVBQ1Q7QUFBQSxFQU9BLElBQUksT0FBZTtBQUNqQixTQUFLLG9CQUFvQixlQUFBO0FBSXpCLFdBQU8sS0FBSyxZQUFZLEtBQUssVUFBVSxJQUFJO0FBQUEsRUFDN0M7QUFBQSxFQU1BLElBQUksZUFBa0M7QUFDcEMsU0FBSyxvQkFBb0IsZUFBQTtBQUd6QixVQUFNLFdBQVcsS0FBSztBQUN0QixRQUFJLFVBQVU7QUFDWixVQUFJO0FBQ0YsZUFBTyxTQUFTLFFBQUE7QUFBQSxNQUNsQixRQUFRO0FBQUEsTUFFUjtBQUFBLElBQ0Y7QUFFQSxXQUFPLEtBQUssVUFBVTtBQUFBLEVBQ3hCO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFLUSxZQUFZLE9BQWtDO0FBQ3BELFFBQUksU0FBUztBQUNiLGVBQVcsTUFBTSxPQUFPO0FBQ3RCLFVBQUksWUFBWSxNQUFNLE9BQU8sR0FBRyxXQUFXLFVBQVU7QUFDbkQsa0JBQVUsR0FBRztBQUFBLE1BQ2Y7QUFBQSxJQUNGO0FBQ0EsV0FBTztBQUFBLEVBQ1Q7QUFBQSxFQU1BLFNBQVMsT0FBZ0M7QUFDdkMsU0FBSyxZQUFZLE9BQU8sS0FBSztBQUFBLEVBQy9CO0FBQUEsRUFNQSxXQUFXLE9BQWUsTUFBb0I7QUFDNUMsVUFBTSxXQUFXLEtBQUs7QUFDdEIsUUFBSSxVQUFVO0FBQ1osZUFBUyxPQUFPLE9BQU8sSUFBSTtBQUFBLElBRTdCLE9BQU87QUFFTCxZQUFNLGNBQWMsS0FBSztBQUN6QixZQUFNLFVBQVUsWUFBWSxNQUFNLEdBQUcsS0FBSyxJQUFJLE9BQU8sWUFBWSxNQUFNLEtBQUs7QUFDNUUsV0FBSyxZQUFZLE9BQU8sQ0FBQyxFQUFFLFFBQVEsUUFBQSxDQUFTLENBQUM7QUFBQSxJQUMvQztBQUFBLEVBQ0Y7QUFBQSxFQU1BLFdBQVcsT0FBZSxRQUFzQjtBQUM5QyxVQUFNLFdBQVcsS0FBSztBQUN0QixRQUFJLFVBQVU7QUFDWixlQUFTLE9BQU8sT0FBTyxNQUFNO0FBQUEsSUFFL0IsT0FBTztBQUVMLFlBQU0sY0FBYyxLQUFLO0FBQ3pCLFlBQU0sVUFBVSxZQUFZLE1BQU0sR0FBRyxLQUFLLElBQUksWUFBWSxNQUFNLFFBQVEsTUFBTTtBQUM5RSxXQUFLLFlBQVksT0FBTyxDQUFDLEVBQUUsUUFBUSxRQUFBLENBQVMsQ0FBQztBQUFBLElBQy9DO0FBQUEsRUFDRjtBQUFBLEVBT0EscUJBQXFCLE9BQWdDO0FBQ25ELFNBQUssWUFBWSxPQUFPLEtBQUs7QUFBQSxFQUMvQjtBQUNGO0FBcklNLGdCQUFBO0FBQUEsRUFESDtBQUFBLEdBbENVLGNBbUNQLFdBQUEsWUFBQSxDQUFBO0FBMENBLGdCQUFBO0FBQUEsRUFESDtBQUFBLEdBNUVVLGNBNkVQLFdBQUEsUUFBQSxDQUFBO0FBWUEsZ0JBQUE7QUFBQSxFQURIO0FBQUEsR0F4RlUsY0F5RlAsV0FBQSxnQkFBQSxDQUFBO0FBaUNKLGdCQUFBO0FBQUEsRUFEQztBQUFBLEdBekhVLGNBMEhYLFdBQUEsWUFBQSxDQUFBO0FBUUEsZ0JBQUE7QUFBQSxFQURDO0FBQUEsR0FqSVUsY0FrSVgsV0FBQSxjQUFBLENBQUE7QUFpQkEsZ0JBQUE7QUFBQSxFQURDO0FBQUEsR0FsSlUsY0FtSlgsV0FBQSxjQUFBLENBQUE7QUFrQkEsZ0JBQUE7QUFBQSxFQURDO0FBQUEsR0FwS1UsY0FxS1gsV0FBQSx3QkFBQSxDQUFBO0FBcktXLGdCQUFOLGdCQUFBO0FBQUEsRUFETixNQUFNLGVBQWU7QUFBQSxHQUNULGFBQUE7QUE2S04sTUFBTSxvQkFBb0IsTUFBTSxNQUFNLGFBQWE7QUFLbkQsU0FBUyx3QkFBd0IsT0FBdUQ7QUFDN0YsU0FBTyxxQkFBcUIsS0FBSyxNQUFNO0FBQ3pDO0FDbk1PLFNBQVMsc0JBQXNCLE9BQThCO0FBQ2xFLE1BQUksVUFBVSxNQUFNO0FBQ2xCLFdBQU87QUFBQSxFQUNUO0FBRUEsTUFBSSxPQUFPLFVBQVUsVUFBVTtBQUM3QixRQUFJLFVBQVUsUUFBVztBQUN2QixZQUFNLElBQUksTUFBTSw0Q0FBNEM7QUFBQSxJQUM5RDtBQUVBLFdBQU87QUFBQSxFQUNUO0FBRUEsTUFBSSxZQUFZLEtBQUssR0FBRztBQUN0QixRQUFJLGlCQUFpQixTQUFTO0FBQzVCLFlBQU1DLFVBQXFDLENBQUE7QUFDM0MsaUJBQVcsQ0FBQyxHQUFHLENBQUMsS0FBSyxNQUFNLFdBQVc7QUFDcENBLGdCQUFPLENBQUMsSUFBSSxzQkFBc0IsQ0FBYztBQUFBLE1BQ2xEO0FBQ0EsYUFBT0E7QUFBQUEsSUFDVDtBQUVBLFFBQUksaUJBQWlCLGlCQUFpQjtBQUNwQyxZQUFNQSxVQUF1QixDQUFBO0FBQzdCLGVBQVMsSUFBSSxHQUFHLElBQUksTUFBTSxRQUFRLEtBQUs7QUFDckNBLGdCQUFPLEtBQUssc0JBQXNCLE1BQU0sSUFBSSxDQUFDLENBQWMsQ0FBQztBQUFBLE1BQzlEO0FBQ0EsYUFBT0E7QUFBQUEsSUFDVDtBQUVBLFFBQUksaUJBQWlCLFVBQVU7QUFDN0IsWUFBTSxTQUFTLE1BQU0sUUFBQTtBQUVyQixhQUFPLDZCQUE2QixlQUFlO0FBQUEsUUFDakQsV0FBVyxpQkFBaUIsTUFBTTtBQUFBLE1BQUEsQ0FDbkM7QUFBQSxJQUNIO0FBRUEsVUFBTSxRQUFRLDBDQUEwQztBQUFBLEVBQzFEO0FBR0EsTUFBSSxNQUFNLFFBQVEsS0FBSyxHQUFHO0FBQ3hCLFdBQU8sTUFBTSxJQUFJLENBQUMsU0FBUyxzQkFBc0IsSUFBaUIsQ0FBQztBQUFBLEVBQ3JFO0FBRUEsUUFBTSxTQUFxQyxDQUFBO0FBQzNDLGFBQVcsQ0FBQyxHQUFHLENBQUMsS0FBSyxPQUFPLFFBQVEsS0FBSyxHQUFHO0FBQzFDLFdBQU8sQ0FBQyxJQUFJLHNCQUFzQixDQUFjO0FBQUEsRUFDbEQ7QUFFQSxTQUFPO0FBQ1Q7QUN2Q08sU0FBUyxxQkFDZCxPQUNBLFNBQ0EsYUFDQSxVQUNBLG1CQUNBLHlCQUNNO0FBR04sTUFBSSx3QkFBd0IsSUFBSSxNQUFNLE1BQU0sR0FBRztBQUM3QztBQUFBLEVBQ0Y7QUFHQSxRQUFNLFlBQVksUUFBUSxtQkFBbUIsTUFBTSxNQUFNO0FBQ3pELE1BQUksQ0FBQyxXQUFXO0FBQ2Q7QUFBQSxFQUNGO0FBR0EsUUFBTSxlQUFlLGlCQUFpQixXQUFXLFFBQVE7QUFDekQsTUFBSSxpQkFBaUIsUUFBVztBQUM5QjtBQUFBLEVBQ0Y7QUFFQSxRQUFNLEVBQUUsT0FBTyxPQUFBLElBQVcsWUFBWSxhQUFhLFlBQVk7QUFFL0QsTUFBSSxDQUFDLFFBQVE7QUFDWCxVQUFNLFFBQVEsdUJBQXVCLEtBQUssVUFBVSxZQUFZLENBQUMsRUFBRTtBQUFBLEVBQ3JFO0FBR0EsaUJBQWUsTUFBTTtBQUNuQixVQUFNLE9BQU8sTUFBTTtBQUNuQixRQUFJLEtBQUssU0FBUyxPQUFPO0FBQ3ZCLDBCQUFvQixNQUFNLFNBQVMsTUFBTSxRQUFRLFFBQVEsaUJBQWlCO0FBQUEsSUFDNUUsV0FBVyxLQUFLLFNBQVMsUUFBUTtBQUMvQjtBQUFBLFFBQ0U7QUFBQSxRQUNBO0FBQUEsUUFDQSxNQUFNO0FBQUEsUUFDTjtBQUFBLFFBQ0E7QUFBQSxRQUNBO0FBQUEsTUFBQTtBQUFBLElBRUosV0FBVyxLQUFLLFNBQVMsUUFBUTtBQUMvQiwyQkFBcUIsU0FBUyxNQUFNLFFBQVEsTUFBTTtBQUFBLElBQ3BEO0FBQUEsRUFDRixDQUFDO0FBQ0g7QUFFQSxTQUFTLG9CQUFvQixLQUFjLG1CQUFzQztBQUUvRSxNQUFJLFFBQVEsR0FBRyxLQUFLLFlBQVksR0FBRyxHQUFHO0FBQ3BDLFVBQU0sS0FBSyxjQUFjLE1BQU0sSUFBSSxVQUFVLElBQUk7QUFDakQsUUFBSSxJQUFJO0FBQ04sd0JBQWtCLElBQUksSUFBSSxHQUFHO0FBQUEsSUFDL0I7QUFBQSxFQUNGO0FBQ0Y7QUFFQSxTQUFTLFlBQVksV0FBb0IsbUJBQStDO0FBRXRGLE1BQUksY0FBYyxRQUFRLE9BQU8sY0FBYyxVQUFVO0FBQ3ZELFdBQU87QUFBQSxFQUNUO0FBR0EsTUFBSSxpQkFBaUIsU0FBUyxHQUFHO0FBQy9CLFdBQU8sT0FBTyxVQUFVLElBQUk7QUFBQSxFQUM5QjtBQUdBLE1BQUksbUJBQW1CO0FBQ3JCLFVBQU0sVUFBVSxtQkFBbUIsU0FBUztBQUM1QyxRQUFJLFNBQVM7QUFDWCxZQUFNLFdBQVcsa0JBQWtCLElBQUksT0FBTztBQUM5QyxVQUFJLFVBQVU7QUFDWiwwQkFBa0IsT0FBTyxPQUFPO0FBQ2hDLGVBQU87QUFBQSxNQUNUO0FBQUEsSUFDRjtBQUFBLEVBQ0Y7QUFFQSxTQUFPLGFBQWEsU0FBUztBQUMvQjtBQUVBLFNBQVMsb0JBQ1AsTUFDQSxTQUNBLGlCQUNBLFFBQ0EsbUJBQ007QUFDTixRQUFNLFlBQVksUUFBUSxpQkFBaUIsZUFBZTtBQUUxRCxNQUFJLENBQUMsYUFBYSxFQUFFLHFCQUFxQixVQUFVO0FBQ2pELFVBQU0sUUFBUSxHQUFHLGVBQWUscUJBQXFCO0FBQUEsRUFDdkQ7QUFHQSxhQUFXLE9BQU8sT0FBTyxLQUFLLEtBQUssT0FBTyxHQUFHO0FBQzNDLFVBQU0sWUFBWSxVQUFVLElBQUksR0FBRztBQUVuQyxRQUFJLGNBQWMsUUFBVztBQUUzQixVQUFJLE9BQU8sUUFBUTtBQUNqQiw0QkFBb0IsT0FBTyxHQUFHLEdBQUcsaUJBQWlCO0FBRWxELFlBQUksUUFBUSxNQUFNLEdBQUc7QUFDbkIsaUJBQU8sT0FBTyxHQUFHLEdBQUc7QUFBQSxRQUN0QixPQUFPO0FBQ0wsaUJBQU8sUUFBUSxHQUFHO0FBQUEsUUFDcEI7QUFBQSxNQUNGO0FBQUEsSUFDRixPQUFPO0FBRUwsVUFBSSxPQUFPLFFBQVE7QUFDakIsNEJBQW9CLE9BQU8sR0FBRyxHQUFHLGlCQUFpQjtBQUFBLE1BQ3BEO0FBQ0EsWUFBTSxZQUFZLHNCQUFzQixTQUF1QjtBQUMvRCxhQUFPLEdBQUcsSUFBSSxZQUFZLFdBQVcsaUJBQWlCO0FBQUEsSUFDeEQ7QUFBQSxFQUNGO0FBQ0Y7QUFFQSxTQUFTLHFCQUNQLE1BQ0EsU0FDQSxpQkFDQSxRQUNBLG1CQUNBLHlCQUNNO0FBQ04sUUFBTSxZQUFZLFFBQVEsaUJBQWlCLGVBQWU7QUFFMUQsTUFBSSxDQUFDLGFBQWEsRUFBRSxxQkFBcUIsa0JBQWtCO0FBQ3pELFVBQU0sUUFBUSxHQUFHLGVBQWUsOEJBQThCO0FBQUEsRUFDaEU7QUFHQSxNQUFJLGVBQWU7QUFFbkIsYUFBVyxVQUFVLEtBQUssTUFBTTtBQUM5QixRQUFJLE9BQU8sUUFBUTtBQUNqQixzQkFBZ0IsT0FBTztBQUFBLElBQ3pCO0FBRUEsUUFBSSxPQUFPLFFBQVE7QUFFakIsWUFBTSxlQUFlLE9BQU8sTUFBTSxjQUFjLGVBQWUsT0FBTyxNQUFNO0FBQzVFLG1CQUFhLFFBQVEsQ0FBQyxTQUFTO0FBQzdCLDRCQUFvQixNQUFNLGlCQUFpQjtBQUFBLE1BQzdDLENBQUM7QUFHRCxhQUFPLE9BQU8sY0FBYyxPQUFPLE1BQU07QUFBQSxJQUMzQztBQUVBLFFBQUksT0FBTyxRQUFRO0FBRWpCLFlBQU0sZ0JBQWdCLE9BQU87QUFDN0IsWUFBTSxTQUFTLGNBQWMsSUFBSSxDQUFDLGNBQWM7QUFLOUMsWUFBSSxZQUFZLFNBQVMsR0FBRztBQUMxQixrQ0FBd0IsSUFBSSxVQUFVLEVBQUU7QUFFeEMsb0NBQTBCLFdBQVcsdUJBQXVCO0FBQUEsUUFDOUQ7QUFDQSxjQUFNLFlBQVksc0JBQXNCLFNBQXVCO0FBQy9ELGVBQU8sWUFBWSxXQUFXLGlCQUFpQjtBQUFBLE1BQ2pELENBQUM7QUFFRCxhQUFPLE9BQU8sY0FBYyxHQUFHLEdBQUcsTUFBTTtBQUN4QyxzQkFBZ0IsT0FBTztBQUFBLElBQ3pCO0FBQUEsRUFDRjtBQUNGO0FBRUEsU0FBUyxxQkFDUCxTQUNBLGlCQUNBLFFBQ007QUFDTixRQUFNLFlBQVksUUFBUSxpQkFBaUIsZUFBZTtBQUUxRCxNQUFJLENBQUMsYUFBYSxFQUFFLHFCQUFxQixXQUFXO0FBQ2xELFVBQU0sUUFBUSxHQUFHLGVBQWUsZ0NBQWdDO0FBQUEsRUFDbEU7QUFJQSxNQUFJLEVBQUUsZUFBZSxTQUFTO0FBQzVCLFVBQU0sUUFBUSxvRUFBb0U7QUFBQSxFQUNwRjtBQUNBLFNBQU8sWUFBWSxPQUFPLFVBQVUsUUFBQSxDQUFTO0FBQy9DO0FBUUEsU0FBUywwQkFBMEIsV0FBb0IsY0FBc0M7QUFDM0YsTUFBSSxDQUFDLFlBQVksU0FBUyxHQUFHO0FBQzNCO0FBQUEsRUFDRjtBQUdBLGVBQWEsSUFBSSxVQUFVLEVBQUU7QUFHN0IsTUFBSSxxQkFBcUIsU0FBUztBQUNoQyxlQUFXLE9BQU8sT0FBTyxLQUFLLFVBQVUsT0FBQSxDQUFRLEdBQUc7QUFDakQsWUFBTSxRQUFRLFVBQVUsSUFBSSxHQUFHO0FBQy9CLGdDQUEwQixPQUFPLFlBQVk7QUFBQSxJQUMvQztBQUFBLEVBQ0Y7QUFHQSxNQUFJLHFCQUFxQixpQkFBaUI7QUFDeEMsYUFBUyxJQUFJLEdBQUcsSUFBSSxVQUFVLFFBQVEsS0FBSztBQUN6QyxnQ0FBMEIsVUFBVSxJQUFJLENBQUMsR0FBRyxZQUFZO0FBQUEsSUFDMUQ7QUFBQSxFQUNGO0FBR0Y7QUFPQSxTQUFTLGlCQUFpQixXQUFpQixVQUFrQztBQUMzRSxNQUFJLFVBQVUsU0FBUyxTQUFTLFFBQVE7QUFDdEMsV0FBTztBQUFBLEVBQ1Q7QUFFQSxXQUFTLElBQUksR0FBRyxJQUFJLFNBQVMsUUFBUSxLQUFLO0FBQ3hDLFFBQUksVUFBVSxDQUFDLE1BQU0sU0FBUyxDQUFDLEdBQUc7QUFDaEMsYUFBTztBQUFBLElBQ1Q7QUFBQSxFQUNGO0FBRUEsU0FBTyxVQUFVLE1BQU0sU0FBUyxNQUFNO0FBQ3hDO0FDN1FPLFNBQVMsd0JBQXdCLE9BQWdEO0FBQ3RGLFNBQU8saUJBQWlCLFdBQVcsaUJBQWlCLG1CQUFtQixpQkFBaUI7QUFDMUY7QUNETyxNQUFNLDhDQUE4QixRQUFBO0FBTXBDLFNBQVMseUJBQXlCLFdBQTBCLFVBQXlCO0FBQzFGLDBCQUF3QixJQUFJLFdBQVcsUUFBUTtBQUNqRDtBQWNPLFNBQVMsd0JBQXdCLFdBQTBCLFVBQTRCO0FBQzVGLFNBQU8sd0JBQXdCLElBQUksU0FBUyxNQUFNO0FBQ3BEO0FDVkEsU0FBUyxpQkFBaUIsR0FBb0M7QUFDNUQsUUFBTSxJQUFJLE9BQU87QUFDakIsU0FBTyxNQUFNLFlBQVksTUFBTSxZQUFZLE1BQU0sYUFBYSxNQUFNLFFBQVEsTUFBTTtBQUNwRjtBQUVBLFNBQVMsYUFBYSxHQUFnQztBQUNwRCxTQUFPLE1BQU0sUUFBUSxDQUFDO0FBQ3hCO0FBRUEsU0FBUyxjQUFjLEdBQWlDO0FBQ3RELFNBQU8sT0FBTyxNQUFNLFlBQVksTUFBTSxRQUFRLENBQUMsTUFBTSxRQUFRLENBQUM7QUFDaEU7QUFNTyxTQUFTLDZCQUE2QixPQUFpQztBQUU1RSxNQUFJLGlCQUFrQyxLQUFLLEdBQUc7QUFDNUMsVUFBTSxPQUFPLE1BQU07QUFDbkIsUUFBSSxNQUFNLFFBQVEsSUFBSSxHQUFHO0FBQ3ZCLGFBQU87QUFBQSxJQUNUO0FBQUEsRUFDRjtBQUdBLE1BQUksTUFBTSxRQUFRLEtBQUssR0FBRztBQUN4QixXQUFPO0FBQUEsRUFDVDtBQUVBLFNBQU8sQ0FBQTtBQUNUO0FBU08sU0FBUyxxQkFBcUIsTUFBZ0IsUUFBK0I7QUFFbEYsTUFBSSxXQUFXO0FBQ2YsUUFBTSxpQkFJRCxDQUFBO0FBRUwsYUFBVyxTQUFTLFFBQVE7QUFDMUIsUUFBSSxNQUFNLFdBQVcsUUFBVztBQUM5QixZQUFNLFVBQVUsTUFBTTtBQUN0QixXQUFLLE9BQU8sVUFBVSxPQUFPO0FBRzdCLFVBQUksTUFBTSxjQUFjLE9BQU8sS0FBSyxNQUFNLFVBQVUsRUFBRSxTQUFTLEdBQUc7QUFDaEUsdUJBQWUsS0FBSztBQUFBLFVBQ2xCLE9BQU87QUFBQSxVQUNQLEtBQUssV0FBVyxRQUFRO0FBQUEsVUFDeEIsWUFBWSxNQUFNO0FBQUEsUUFBQSxDQUNuQjtBQUFBLE1BQ0g7QUFFQSxrQkFBWSxRQUFRO0FBQUEsSUFDdEIsV0FBVyxNQUFNLFFBQVE7QUFDdkIsa0JBQVksTUFBTTtBQUFBLElBQ3BCLFdBQVcsTUFBTSxRQUFRO0FBQ3ZCLFdBQUssT0FBTyxVQUFVLE1BQU0sTUFBTTtBQUFBLElBQ3BDO0FBQUEsRUFDRjtBQUdBLGFBQVcsTUFBTSxnQkFBZ0I7QUFDL0IsZUFBVyxDQUFDLEtBQUssS0FBSyxLQUFLLE9BQU8sUUFBUSxHQUFHLFVBQVUsR0FBRztBQUN4RCxXQUFLLEtBQUssRUFBRSxPQUFPLEdBQUcsT0FBTyxLQUFLLEdBQUcsT0FBTyxLQUFLLEtBQUs7QUFBQSxJQUN4RDtBQUFBLEVBQ0Y7QUFDRjtBQU9PLFNBQVMsc0JBQXNCLEdBQTBCO0FBQzlELE1BQUksaUJBQWlCLENBQUMsR0FBRztBQUN2QixXQUFPO0FBQUEsRUFDVDtBQUVBLE1BQUksYUFBYSxDQUFDLEdBQUc7QUFDbkIsVUFBTSxPQUFPLElBQUksZ0JBQUE7QUFDakIsb0NBQWdDLE1BQU0sQ0FBQztBQUN2QyxXQUFPO0FBQUEsRUFDVDtBQUVBLE1BQUksY0FBYyxDQUFDLEdBQUc7QUFDcEIsUUFBSSxFQUFFLFNBQVMsTUFBTSxNQUFNO0FBRXpCLGFBQU87QUFBQSxJQUNUO0FBRUEsUUFBSSx3QkFBd0IsQ0FBQyxHQUFHO0FBQzlCLFlBQU0sT0FBTyxJQUFJLFNBQUE7QUFHakIsWUFBTSxTQUFTLDZCQUE2QixFQUFFLFNBQVM7QUFDdkQsVUFBSSxPQUFPLFNBQVMsR0FBRztBQUNyQiw2QkFBcUIsTUFBTSxNQUFNO0FBQUEsTUFDbkM7QUFDQSxhQUFPO0FBQUEsSUFDVDtBQUVBLFVBQU0sTUFBTSxJQUFJLFFBQUE7QUFDaEIsNkJBQXlCLEtBQUssQ0FBQztBQUMvQixXQUFPO0FBQUEsRUFDVDtBQUVBLFFBQU0sSUFBSSxNQUFNLDJCQUEyQixDQUFDLEVBQUU7QUFDaEQ7QUFTTyxNQUFNLGtDQUFrQyxDQUM3QyxNQUNBLFFBQ0EsVUFBa0MsQ0FBQSxNQUMvQjtBQUNILFFBQU0sRUFBRSxPQUFPLE1BQUEsSUFBVTtBQUV6QixNQUFJLFNBQVMsT0FBTztBQUVsQixlQUFXLFFBQVEsUUFBUTtBQUN6QixZQUFNLFlBQVksc0JBQXNCLElBQUk7QUFDNUMsVUFBSSx3QkFBd0IsU0FBUyxHQUFHO0FBQ3RDLGFBQUssY0FBYyxTQUFTO0FBQUEsTUFDOUIsT0FBTztBQUNMLGFBQUssS0FBSyxTQUFTO0FBQUEsTUFDckI7QUFBQSxJQUNGO0FBQ0E7QUFBQSxFQUNGO0FBSUEsTUFBSSx3QkFBd0IsTUFBTSxNQUFNLEdBQUc7QUFDekM7QUFBQSxFQUNGO0FBR0EsUUFBTSxVQUFVLEtBQUs7QUFDckIsUUFBTSxTQUFTLE9BQU87QUFDdEIsTUFBSSxVQUFVLFFBQVE7QUFDcEIsU0FBSyxPQUFPLFFBQVEsVUFBVSxNQUFNO0FBQUEsRUFDdEM7QUFHQSxRQUFNLFNBQVMsS0FBSyxJQUFJLFNBQVMsTUFBTTtBQUN2QyxXQUFTLElBQUksR0FBRyxJQUFJLFFBQVEsS0FBSztBQUMvQixVQUFNLFVBQVUsT0FBTyxDQUFDO0FBQ3hCLFVBQU0sV0FBVyxLQUFLLElBQUksQ0FBQztBQUczQixRQUFJLGNBQWMsT0FBTyxLQUFLLG9CQUFvQixTQUFTO0FBQ3pELCtCQUF5QixVQUFVLFNBQVMsT0FBTztBQUNuRDtBQUFBLElBQ0Y7QUFHQSxRQUFJLGFBQWEsT0FBTyxLQUFLLG9CQUFvQixpQkFBaUI7QUFDaEUsc0NBQWdDLFVBQVUsU0FBUyxPQUFPO0FBQzFEO0FBQUEsSUFDRjtBQUdBLFFBQUksaUJBQWlCLE9BQU8sS0FBSyxhQUFhLFNBQVM7QUFDckQ7QUFBQSxJQUNGO0FBR0EsU0FBSyxPQUFPLEdBQUcsQ0FBQztBQUNoQixVQUFNLFlBQVksc0JBQXNCLE9BQU87QUFDL0MsUUFBSSx3QkFBd0IsU0FBUyxHQUFHO0FBQ3RDLFdBQUssZ0JBQWdCLEdBQUcsU0FBUztBQUFBLElBQ25DLE9BQU87QUFDTCxXQUFLLE9BQU8sR0FBRyxTQUFTO0FBQUEsSUFDMUI7QUFBQSxFQUNGO0FBR0EsV0FBUyxJQUFJLFNBQVMsSUFBSSxRQUFRLEtBQUs7QUFDckMsVUFBTSxZQUFZLHNCQUFzQixPQUFPLENBQUMsQ0FBQztBQUNqRCxRQUFJLHdCQUF3QixTQUFTLEdBQUc7QUFDdEMsV0FBSyxjQUFjLFNBQVM7QUFBQSxJQUM5QixPQUFPO0FBQ0wsV0FBSyxLQUFLLFNBQVM7QUFBQSxJQUNyQjtBQUFBLEVBQ0Y7QUFHQSwyQkFBeUIsTUFBTSxNQUFNO0FBQ3ZDO0FBU08sTUFBTSwyQkFBMkIsQ0FDdEMsTUFDQSxRQUNBLFVBQWtDLENBQUEsTUFDL0I7QUFDSCxRQUFNLEVBQUUsT0FBTyxNQUFBLElBQVU7QUFFekIsTUFBSSxTQUFTLE9BQU87QUFFbEIsZUFBVyxLQUFLLE9BQU8sS0FBSyxNQUFNLEdBQUc7QUFDbkMsWUFBTSxJQUFJLE9BQU8sQ0FBQztBQUNsQixVQUFJLE1BQU0sUUFBVztBQUNuQixjQUFNLFlBQVksc0JBQXNCLENBQUM7QUFDekMsWUFBSSx3QkFBd0IsU0FBUyxHQUFHO0FBQ3RDLGVBQUssYUFBYSxHQUFHLFNBQVM7QUFBQSxRQUNoQyxPQUFPO0FBQ0wsZUFBSyxJQUFJLEdBQUcsU0FBUztBQUFBLFFBQ3ZCO0FBQUEsTUFDRjtBQUFBLElBQ0Y7QUFDQTtBQUFBLEVBQ0Y7QUFJQSxNQUFJLHdCQUF3QixNQUFNLE1BQU0sR0FBRztBQUN6QztBQUFBLEVBQ0Y7QUFHQSxRQUFNLHVCQUF1QixJQUFJLElBQUksT0FBTyxLQUFLLE1BQU0sRUFBRSxPQUFPLENBQUMsTUFBTSxPQUFPLENBQUMsTUFBTSxNQUFTLENBQUM7QUFDL0YsYUFBVyxPQUFPLEtBQUssUUFBUTtBQUM3QixRQUFJLENBQUMscUJBQXFCLElBQUksR0FBRyxHQUFHO0FBQ2xDLFdBQUssT0FBTyxHQUFHO0FBQUEsSUFDakI7QUFBQSxFQUNGO0FBRUEsYUFBVyxLQUFLLE9BQU8sS0FBSyxNQUFNLEdBQUc7QUFDbkMsVUFBTSxJQUFJLE9BQU8sQ0FBQztBQUVsQixRQUFJLE1BQU0sUUFBVztBQUNuQjtBQUFBLElBQ0Y7QUFFQSxVQUFNLFdBQVcsS0FBSyxJQUFJLENBQUM7QUFHM0IsUUFBSSxjQUFjLENBQUMsS0FBSyxvQkFBb0IsU0FBUztBQUNuRCwrQkFBeUIsVUFBVSxHQUFHLE9BQU87QUFDN0M7QUFBQSxJQUNGO0FBR0EsUUFBSSxhQUFhLENBQUMsS0FBSyxvQkFBb0IsaUJBQWlCO0FBQzFELHNDQUFnQyxVQUFVLEdBQUcsT0FBTztBQUNwRDtBQUFBLElBQ0Y7QUFHQSxRQUFJLGlCQUFpQixDQUFDLEtBQUssYUFBYSxHQUFHO0FBQ3pDO0FBQUEsSUFDRjtBQUdBLFVBQU0sWUFBWSxzQkFBc0IsQ0FBQztBQUN6QyxRQUFJLHdCQUF3QixTQUFTLEdBQUc7QUFDdEMsV0FBSyxhQUFhLEdBQUcsU0FBUztBQUFBLElBQ2hDLE9BQU87QUFDTCxXQUFLLElBQUksR0FBRyxTQUFTO0FBQUEsSUFDdkI7QUFBQSxFQUNGO0FBR0EsMkJBQXlCLE1BQU0sTUFBTTtBQUN2QztBQ3hTQSxTQUFTLGFBQWEsR0FBcUI7QUFFekMsTUFBSSxNQUFNLFFBQVEsTUFBTSxVQUFhLE9BQU8sTUFBTSxVQUFVO0FBQzFELFdBQU87QUFBQSxFQUNUO0FBRUEsTUFBSSxNQUFNLFFBQVEsQ0FBQyxLQUFLLEVBQUUsV0FBVyxHQUFHO0FBQ3RDLFdBQU8sSUFBSSxnQkFBQTtBQUFBLEVBQ2I7QUFHQSxNQUFJLHdCQUF3QixDQUFDLEdBQUc7QUFDOUIsV0FBTztBQUFBLEVBQ1Q7QUFFQSxTQUFPLHNCQUFzQixDQUFlO0FBQzlDO0FBS0EsU0FBUyxlQUFlLE1BQXVCLE9BQWUsT0FBc0I7QUFDbEYsTUFBSSxpQkFBaUIsV0FBVyxpQkFBaUIsbUJBQW1CLGlCQUFpQixVQUFVO0FBQzdGLFNBQUssZ0JBQWdCLE9BQU8sS0FBSztBQUFBLEVBQ25DLFdBQVcsd0JBQXdCLEtBQUssR0FBRztBQUN6QyxVQUFNLGVBQWUsS0FBSyxnQkFBZ0IsT0FBTyxJQUFJLFVBQVU7QUFDL0QsVUFBTSxTQUFTLDZCQUE4QixNQUFjLFNBQVM7QUFDcEUsUUFBSSxPQUFPLFNBQVMsR0FBRztBQUNyQiwyQkFBcUIsY0FBYyxNQUFNO0FBQUEsSUFDM0M7QUFBQSxFQUNGLE9BQU87QUFDTCxTQUFLLE9BQU8sT0FBTyxLQUFLO0FBQUEsRUFDMUI7QUFDRjtBQUtBLFNBQVMsU0FBUyxLQUFjLEtBQWEsT0FBc0I7QUFDakUsTUFBSSxVQUFVLFFBQVc7QUFDdkIsUUFBSSxPQUFPLEdBQUc7QUFBQSxFQUNoQixXQUNFLGlCQUFpQixXQUNqQixpQkFBaUIsbUJBQ2pCLGlCQUFpQixVQUNqQjtBQUNBLFFBQUksYUFBYSxLQUFLLEtBQUs7QUFBQSxFQUM3QixXQUFXLHdCQUF3QixLQUFLLEdBQUc7QUFDekMsVUFBTSxlQUFlLElBQUksYUFBYSxLQUFLLElBQUksVUFBVTtBQUN6RCxVQUFNLFNBQVMsNkJBQThCLE1BQWMsU0FBUztBQUNwRSxRQUFJLE9BQU8sU0FBUyxHQUFHO0FBQ3JCLDJCQUFxQixjQUFjLE1BQU07QUFBQSxJQUMzQztBQUFBLEVBQ0YsT0FBTztBQUNMLFFBQUksSUFBSSxLQUFLLEtBQUs7QUFBQSxFQUNwQjtBQUNGO0FBS08sU0FBUyw0QkFDZCxRQUNBLFlBQ007QUFDTixRQUFNLGdCQUFnQixnQkFBZ0IsWUFBWSxPQUFPLElBQUk7QUFHN0QsTUFBSSxDQUFDLGVBQWU7QUFDbEIsVUFBTTtBQUFBLE1BQ0osMERBQTBELEtBQUssVUFBVSxPQUFPLElBQUksQ0FBQztBQUFBLElBQUE7QUFBQSxFQUV6RjtBQUVBLFVBQVEsT0FBTyxNQUFBO0FBQUEsSUFDYixLQUFLLGFBQWE7QUFDaEIsVUFBSSxFQUFFLHlCQUF5QixrQkFBa0I7QUFDL0MsY0FBTSxRQUFRLHVEQUF1RDtBQUFBLE1BQ3ZFO0FBQ0Esb0JBQWMsS0FBSyxPQUFPLFdBQVcsT0FBTyxPQUFPO0FBQ25EO0FBQUEsSUFDRjtBQUFBLElBRUEsS0FBSyxlQUFlLGFBQWE7QUFDL0IsVUFBSSxFQUFFLHlCQUF5QixrQkFBa0I7QUFDL0MsY0FBTSxRQUFRLHlEQUF5RDtBQUFBLE1BQ3pFO0FBQ0EsVUFBSSxPQUFPLGNBQWMsU0FBUyxHQUFHO0FBQ25DLHNCQUFjLE9BQU8sT0FBTyxPQUFPLE9BQU8sY0FBYyxNQUFNO0FBQUEsTUFDaEU7QUFDQSxVQUFJLE9BQU8sWUFBWSxTQUFTLEdBQUc7QUFDakMsY0FBTSxpQkFBaUIsT0FBTyxZQUFZLElBQUksWUFBWTtBQUMxRCxpQkFBUyxJQUFJLEdBQUcsSUFBSSxlQUFlLFFBQVEsS0FBSztBQUM5Qyx5QkFBZSxlQUFlLE9BQU8sUUFBUSxHQUFHLGVBQWUsQ0FBQyxDQUFDO0FBQUEsUUFDbkU7QUFBQSxNQUNGO0FBQ0E7QUFBQSxJQUNGO0FBQUEsSUFFQSxLQUFLLGVBQWUsYUFBYTtBQUMvQixVQUFJLEVBQUUseUJBQXlCLGtCQUFrQjtBQUMvQyxjQUFNLFFBQVEseURBQXlEO0FBQUEsTUFDekU7QUFDQSxZQUFNLFlBQVksYUFBYSxPQUFPLFFBQVE7QUFDOUMsVUFDRSxxQkFBcUIsV0FDckIscUJBQXFCLG1CQUNyQixxQkFBcUIsVUFDckI7QUFDQSxzQkFBYyxhQUFhLE9BQU8sT0FBTyxTQUFTO0FBQUEsTUFDcEQsV0FBVyx3QkFBd0IsU0FBUyxHQUFHO0FBQzdDLGNBQU0sZUFBZSxjQUFjLGFBQWEsT0FBTyxPQUFPLElBQUksVUFBVTtBQUM1RSxjQUFNLFNBQVMsNkJBQThCLFVBQWtCLFNBQVM7QUFDeEUsWUFBSSxPQUFPLFNBQVMsR0FBRztBQUNyQiwrQkFBcUIsY0FBYyxNQUFNO0FBQUEsUUFDM0M7QUFBQSxNQUNGLE9BQU87QUFDTCxzQkFBYyxJQUFJLE9BQU8sT0FBTyxTQUFTO0FBQUEsTUFDM0M7QUFDQTtBQUFBLElBQ0Y7QUFBQSxJQUVBLEtBQUssZUFBZTtBQUFBLElBQ3BCLEtBQUssZUFBZSxjQUFjO0FBQ2hDLFVBQUkseUJBQXlCLFVBQVU7QUFFckMsWUFBSSxPQUFPLFFBQVEsYUFBYTtBQUU5QixnQkFBTSxTQUFTLDZCQUE2QixPQUFPLFFBQVE7QUFDM0QsY0FBSSxjQUFjLFNBQVMsR0FBRztBQUM1QiwwQkFBYyxPQUFPLEdBQUcsY0FBYyxNQUFNO0FBQUEsVUFDOUM7QUFDQSxjQUFJLE9BQU8sU0FBUyxHQUFHO0FBQ3JCLGlDQUFxQixlQUFlLE1BQU07QUFBQSxVQUM1QztBQUFBLFFBQ0Y7QUFBQSxNQUVGLFdBQVcseUJBQXlCLFNBQVM7QUFDM0MsY0FBTSxZQUFZLGFBQWEsT0FBTyxRQUFRO0FBQzlDLGlCQUFTLGVBQWUsT0FBTyxLQUFLLFNBQVM7QUFBQSxNQUMvQyxPQUFPO0FBQ0wsY0FBTSxRQUFRLHdFQUF3RTtBQUFBLE1BQ3hGO0FBQ0E7QUFBQSxJQUNGO0FBQUEsSUFFQSxLQUFLLGVBQWUsY0FBYztBQUNoQyxVQUFJLHlCQUF5QixTQUFVO0FBQUEsZUFFNUIseUJBQXlCLFNBQVM7QUFDM0Msc0JBQWMsT0FBTyxPQUFPLEdBQUc7QUFBQSxNQUNqQyxPQUFPO0FBQ0wsY0FBTSxRQUFRLDhEQUE4RDtBQUFBLE1BQzlFO0FBQ0E7QUFBQSxJQUNGO0FBQUEsSUFFQSxTQUFTO0FBRVAsWUFBTSxtQkFBMEI7QUFDaEMsWUFBTSxRQUFRLDRCQUE2QixpQkFBeUIsSUFBSSxFQUFFO0FBQUEsSUFDNUU7QUFBQSxFQUFBO0FBRUo7QUNyS0EsSUFBSTtBQXNCRyxTQUFTLGdCQUFtQixPQUFZLFdBQW1CLFNBQXVCO0FBRXZGLE1BQUksWUFBWSxLQUFLLGFBQWEsTUFBTSxRQUFRO0FBQzlDLFVBQU0sSUFBSSxNQUFNLGFBQWEsU0FBUyxvQ0FBb0MsTUFBTSxNQUFNLEdBQUc7QUFBQSxFQUMzRjtBQUNBLE1BQUksVUFBVSxLQUFLLFVBQVUsTUFBTSxRQUFRO0FBQ3pDLFVBQU0sSUFBSSxNQUFNLFdBQVcsT0FBTyxvQ0FBb0MsTUFBTSxNQUFNLEdBQUc7QUFBQSxFQUN2RjtBQUNBLE1BQUksY0FBYyxTQUFTO0FBQ3pCO0FBQUEsRUFDRjtBQUdBLHNCQUFvQjtBQUFBLElBQ2xCO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUNBLE1BQU07QUFBQSxJQUNOLHFCQUFxQjtBQUFBLEVBQUE7QUFHdkIsTUFBSTtBQUdGLFVBQU0sQ0FBQyxJQUFJLElBQUksTUFBTSxPQUFPLFdBQVcsQ0FBQztBQUN4QyxVQUFNLGlCQUFpQixVQUFVLFlBQVksVUFBVSxJQUFJO0FBQzNELFVBQU0sT0FBTyxnQkFBZ0IsR0FBRyxJQUFJO0FBQUEsRUFDdEMsVUFBQTtBQUNFLHdCQUFvQjtBQUFBLEVBQ3RCO0FBQ0Y7QUFVTyxTQUFTLHFCQUFxQixRQUFpRDtBQUVwRixRQUFNLE1BQU07QUFFWixNQUFJLENBQUMsSUFBSSxxQkFBcUI7QUFFNUIsUUFBSSxPQUFPLE9BQU87QUFDbEIsUUFBSSxzQkFBc0I7QUFDMUIsV0FBTztBQUFBLEVBQ1Q7QUFTQSxRQUFNLGtCQUFrQixJQUFJLFVBQVUsSUFBSSxZQUFZLElBQUksVUFBVSxJQUFJLElBQUk7QUFFNUUsU0FBTztBQUFBLElBQ0wsTUFBTTtBQUFBLElBQ04sTUFBTSxJQUFJO0FBQUEsSUFDVixXQUFXLElBQUk7QUFBQSxJQUNmLFNBQVM7QUFBQSxFQUFBO0FBRWI7QUFLTyxTQUFTLHdCQUF3QixPQUEyQjtBQUNqRSxTQUFPLHNCQUFzQixVQUFhLGtCQUFrQixVQUFVO0FBQ3hFO0FDeERBLFNBQVMsdUJBQXVCLFFBQWdDO0FBQzlELE1BQUksT0FBTyxTQUFTLGVBQWUsZUFBZSxPQUFPLFlBQVksU0FBUyxHQUFHO0FBQy9FLFVBQU0sWUFBWSxPQUFPLFlBQVksSUFBSSxDQUFDLE1BQU8sV0FBVyxDQUFDLElBQUksWUFBWSxDQUFDLElBQUksQ0FBRTtBQUNwRixXQUFPLEVBQUUsR0FBRyxRQUFRLGFBQWEsVUFBQTtBQUFBLEVBQ25DLFdBQVcsT0FBTyxTQUFTLGVBQWUsYUFBYTtBQUNyRCxVQUFNLFdBQVcsV0FBVyxPQUFPLFFBQVEsSUFBSSxZQUFZLE9BQU8sUUFBUSxJQUFJLE9BQU87QUFDckYsV0FBTyxFQUFFLEdBQUcsUUFBUSxVQUFVLFNBQUE7QUFBQSxFQUNoQyxXQUNFLE9BQU8sU0FBUyxlQUFlLGFBQy9CLE9BQU8sU0FBUyxlQUFlLGNBQy9CO0FBQ0EsVUFBTSxXQUFXLFdBQVcsT0FBTyxRQUFRLElBQUksWUFBWSxPQUFPLFFBQVEsSUFBSSxPQUFPO0FBQ3JGLFdBQU8sRUFBRSxHQUFHLFFBQVEsVUFBVSxTQUFBO0FBQUEsRUFDaEM7QUFDQSxTQUFPO0FBQ1Q7QUFLTyxTQUFTLHVCQUVkO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxFQUNBO0FBQ0YsR0EwQkU7O0FBQ0EsUUFBTSxhQUFhLDJDQUEyQyxPQUFBLENBQVE7QUFFdEUsTUFBSSxvQ0FBb0M7QUFFeEMsUUFBTSxpQkFBcUM7QUFBQSxJQUN6QztBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0EsYUFBYTtBQUFBO0FBQUEsSUFFYixJQUFJLHNDQUFzQztBQUN4QyxhQUFPLG9DQUFvQztBQUFBLElBQzdDO0FBQUEsRUFBQTtBQUdGLFFBQU0sV0FBVyxzQkFBc0IsVUFBVTtBQUVqRCxNQUFJO0FBSUosTUFBSSxpQkFBaUI7QUFFckIsUUFBTSxvQkFBb0IsTUFBTTtBQUU5QixVQUFNLHdCQUF3QixtQkFBbUIsQ0FBQyxTQUFTLFdBQVc7QUFDcEUsVUFBSSxPQUFPLFFBQVE7QUFDakIseUJBQWlCO0FBQUEsTUFDbkI7QUFBQSxJQUNGLENBQUM7QUFFRCxRQUFJO0FBQ0YsWUFBTSxTQUFTLG1CQUFtQjtBQUFBLFFBQ2hDLE1BQU0sYUFBYSxrQkFBa0IsUUFBUTtBQUFBLFFBQzdDO0FBQUEsTUFBQTtBQUVGLHlCQUFtQixJQUFJLFFBQVEsRUFBRSxHQUFHLGdCQUFnQixhQUFhLFFBQVE7QUFDekUsYUFBTztBQUFBLElBQ1QsVUFBQTtBQUNFLDRCQUFBO0FBQUEsSUFDRjtBQUFBLEVBQ0Y7QUFFQSxnQkFBYyxrQkFBQTtBQUdkLFFBQU0sZ0JBQWUsYUFBUSxtQkFBbUIsV0FBVyxFQUFFLE1BQXhDLFlBQTZDLENBQUE7QUFHbEUsUUFBTSxrQkFBa0IsT0FBTyxDQUFDLGVBQStCO0FBRTdELFFBQUksV0FBVyxXQUFXLFlBQVk7QUFDcEM7QUFBQSxJQUNGO0FBR0EsVUFBTSw4Q0FBOEIsSUFBQTtBQUdwQyxVQUFNLHdDQUEyQyxJQUFBO0FBTWpELFVBQU0sY0FBd0QsQ0FBQTtBQUM5RCxVQUFNLHdCQUF3QixtQkFBbUIsQ0FBQyxRQUFRLFdBQVc7QUFDbkUsVUFBSSxPQUFPLFFBQVE7QUFDakIsb0JBQVksS0FBSyxFQUFFLFFBQVEsUUFBUSx1QkFBdUIsTUFBTSxHQUFHO0FBQUEsTUFDckU7QUFBQSxJQUNGLENBQUM7QUFFRDtBQUNBLFFBQUk7QUFDRixVQUFJO0FBQ0YsbUJBQVcsU0FBUyxXQUFXLFFBQVE7QUFDckM7QUFBQSxZQUNFO0FBQUEsWUFDQTtBQUFBLFlBQ0E7QUFBQSxZQUNBO0FBQUEsWUFDQTtBQUFBLFlBQ0E7QUFBQSxVQUFBO0FBQUEsUUFFSjtBQUFBLE1BQ0YsVUFBQTtBQUNFLDhCQUFBO0FBQUEsTUFDRjtBQU1BLFVBQUksWUFBWSxTQUFTLEdBQUc7QUFDMUIsZ0JBQVEsb0JBQW9CLFVBQVU7QUFFdEMsbUJBQVcsRUFBRSxRQUFRLE9BQUEsS0FBWSxhQUFhO0FBRTVDLGdCQUFNLGVBQWUscUJBQXFCLGFBQWEsTUFBTTtBQUM3RCxjQUFJLGlCQUFpQixRQUFXO0FBRTlCLGtCQUFNLHdCQUFvQztBQUFBLGNBQ3hDLEdBQUc7QUFBQSxjQUNILE1BQU0sQ0FBQyxHQUFHLGNBQWMsR0FBRyxPQUFPLElBQUk7QUFBQSxZQUFBO0FBRXhDLHdDQUE0Qix1QkFBdUIsVUFBVTtBQUFBLFVBQy9EO0FBQUEsUUFDRjtBQUVBLGdCQUFRLE9BQUE7QUFBQSxNQUNWO0FBSUEsVUFBSSxzQkFBc0IsV0FBVyxzQkFBc0IsaUJBQWlCO0FBQzFFLGlDQUF5QixZQUFZLFlBQVksV0FBVyxDQUFDO0FBQUEsTUFDL0Q7QUFBQSxJQUNGLFVBQUE7QUFDRTtBQUFBLElBQ0Y7QUFBQSxFQUNGLENBQUM7QUFDRCxRQUFNLGtCQUFrQixRQUFRLFVBQVUsZUFBZTtBQUl6RCxNQUFJLGlCQUFtRCxDQUFBO0FBRXZELFFBQU0sc0JBQXNCLGFBQWEsYUFBYSxDQUFDLFdBQVc7QUFFaEUsUUFBSSxlQUFlLHFDQUFxQztBQUN0RDtBQUFBLElBQ0Y7QUFHQSxRQUFJLE9BQU8sUUFBUTtBQUNqQjtBQUFBLElBQ0Y7QUFHQSxRQUFJLE9BQU8sU0FBUyxlQUFlLGFBQWE7QUFDOUMsWUFBTSxXQUFXLFlBQVksYUFBYSxPQUFPLElBQUk7QUFDckQsVUFBSSxTQUFTLFlBQVksd0JBQXdCLFNBQVMsS0FBa0IsR0FBRztBQUM3RSxjQUFNLGFBQWEscUJBQXFCLE1BQU07QUFFOUMsWUFBSSxlQUFlLFFBQVc7QUFFNUI7QUFBQSxRQUNGO0FBR0EsdUJBQWUsS0FBSyxVQUFVO0FBQzlCO0FBQUEsTUFDRjtBQUFBLElBQ0Y7QUFPQSxtQkFBZSxLQUFLLHVCQUF1QixNQUFNLENBQUM7QUFBQSxFQUNwRCxDQUFDO0FBSUQsUUFBTSxvQkFBb0IsV0FBVyxhQUFhLE1BQU07QUFDdEQsUUFBSSxlQUFlLFdBQVcsR0FBRztBQUMvQjtBQUFBLElBQ0Y7QUFFQSxVQUFNLGlCQUFpQjtBQUN2QixxQkFBaUIsQ0FBQTtBQUdqQixRQUFJLGVBQWUscUNBQXFDO0FBQ3REO0FBQUEsSUFDRjtBQUVBLFlBQVEsb0JBQW9CLFVBQVU7QUFHdEMsZUFBVyxVQUFVLGdCQUFnQjtBQUNuQyxrQ0FBNEIsUUFBUSxVQUFVO0FBQUEsSUFDaEQ7QUFFQSxZQUFRLE9BQUE7QUFHUixRQUFJLHNCQUFzQixXQUFXLHNCQUFzQixpQkFBaUI7QUFDMUUsK0JBQXlCLFlBQVksWUFBWSxXQUFXLENBQUM7QUFBQSxJQUMvRDtBQUdBLGtDQUE4QixVQUFVLEVBQUUsY0FBQTtBQUFBLEVBQzVDLENBQUM7QUFLRCxRQUFNLGdCQUFnQixZQUFZLFdBQVc7QUFFN0MsTUFBSSxnQkFBZ0I7QUFDbEIsWUFBUSxvQkFBb0IsVUFBVTtBQUV0QyxRQUFJLHNCQUFzQixTQUFTO0FBQ2pDLCtCQUF5QixZQUFZLGVBQThCLEVBQUUsTUFBTSxTQUFTO0FBQUEsSUFDdEYsV0FBVyxzQkFBc0IsaUJBQWlCO0FBQ2hELHNDQUFnQyxZQUFZLGVBQTZCLEVBQUUsTUFBTSxTQUFTO0FBQUEsSUFDNUYsV0FBVyxzQkFBc0IsVUFBVTtBQUV6QyxZQUFNLFdBQVc7QUFDakIsVUFBSSxTQUFTLGVBQWUsaUJBQWlCO0FBRTNDLFlBQUksV0FBVyxTQUFTLEdBQUc7QUFDekIscUJBQVcsT0FBTyxHQUFHLFdBQVcsTUFBTTtBQUFBLFFBQ3hDO0FBQ0EsY0FBTSxTQUFTLDZCQUE2QixTQUFTLFNBQVM7QUFDOUQsWUFBSSxPQUFPLFNBQVMsR0FBRztBQUNyQiwrQkFBcUIsWUFBWSxNQUFNO0FBQUEsUUFDekM7QUFBQSxNQUNGO0FBQUEsSUFDRjtBQUVBLFlBQVEsT0FBQTtBQUFBLEVBQ1Y7QUFJQSxNQUFJLHNCQUFzQixXQUFXLHNCQUFzQixpQkFBaUI7QUFDMUUsNkJBQXlCLFlBQVksYUFBYTtBQUFBLEVBQ3BEO0FBRUEsUUFBTSxVQUFVLE1BQU07QUFDcEIsb0JBQUE7QUFDQSx3QkFBQTtBQUNBLHNCQUFBO0FBQUEsRUFDRjtBQUVBLFNBQU87QUFBQSxJQUNMO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxFQUFBO0FBRUo7IiwieF9nb29nbGVfaWdub3JlTGlzdCI6WzBdfQ==
|