UNPKG

44 kBJavaScriptView Raw
1import { isDevMode } from '@angular/core';
2import { isNgrxMockEnvironment } from './flags';
3export function isEqualCheck(a, b) {
4 return a === b;
5}
6function isArgumentsChanged(args, lastArguments, comparator) {
7 for (let i = 0; i < args.length; i++) {
8 if (!comparator(args[i], lastArguments[i])) {
9 return true;
10 }
11 }
12 return false;
13}
14export function resultMemoize(projectionFn, isResultEqual) {
15 return defaultMemoize(projectionFn, isEqualCheck, isResultEqual);
16}
17export function defaultMemoize(projectionFn, isArgumentsEqual = isEqualCheck, isResultEqual = isEqualCheck) {
18 let lastArguments = null;
19 // eslint-disable-next-line @typescript-eslint/no-explicit-any, , , , ,
20 let lastResult = null;
21 let overrideResult;
22 function reset() {
23 lastArguments = null;
24 lastResult = null;
25 }
26 function setResult(result = undefined) {
27 overrideResult = { result };
28 }
29 function clearResult() {
30 overrideResult = undefined;
31 }
32 /* eslint-disable prefer-rest-params, prefer-spread */
33 // disabled because of the use of `arguments`
34 function memoized() {
35 if (overrideResult !== undefined) {
36 return overrideResult.result;
37 }
38 if (!lastArguments) {
39 lastResult = projectionFn.apply(null, arguments);
40 lastArguments = arguments;
41 return lastResult;
42 }
43 if (!isArgumentsChanged(arguments, lastArguments, isArgumentsEqual)) {
44 return lastResult;
45 }
46 const newResult = projectionFn.apply(null, arguments);
47 lastArguments = arguments;
48 if (isResultEqual(lastResult, newResult)) {
49 return lastResult;
50 }
51 lastResult = newResult;
52 return newResult;
53 }
54 return { memoized, reset, setResult, clearResult };
55}
56export function createSelector(...input) {
57 return createSelectorFactory(defaultMemoize)(...input);
58}
59export function defaultStateFn(state, selectors, props, memoizedProjector) {
60 if (props === undefined) {
61 const args = selectors.map((fn) => fn(state));
62 return memoizedProjector.memoized.apply(null, args);
63 }
64 const args = selectors.map((fn) => fn(state, props));
65 return memoizedProjector.memoized.apply(null, [...args, props]);
66}
67/**
68 *
69 * @param memoize The function used to memoize selectors
70 * @param options Config Object that may include a `stateFn` function defining how to return the selector's value, given the entire `Store`'s state, parent `Selector`s, `Props`, and a `MemoizedProjection`
71 *
72 * @usageNotes
73 *
74 * **Creating a Selector Factory Where Array Order Does Not Matter**
75 *
76 * ```ts
77 * function removeMatch(arr: string[], target: string): string[] {
78 * const matchIndex = arr.indexOf(target);
79 * return [...arr.slice(0, matchIndex), ...arr.slice(matchIndex + 1)];
80 * }
81 *
82 * function orderDoesNotMatterComparer(a: any, b: any): boolean {
83 * if (!Array.isArray(a) || !Array.isArray(b)) {
84 * return a === b;
85 * }
86 * if (a.length !== b.length) {
87 * return false;
88 * }
89 * let tempB = [...b];
90 * function reduceToDetermineIfArraysContainSameContents(
91 * previousCallResult: boolean,
92 * arrayMember: any
93 * ): boolean {
94 * if (previousCallResult === false) {
95 * return false;
96 * }
97 * if (tempB.includes(arrayMember)) {
98 * tempB = removeMatch(tempB, arrayMember);
99 * return true;
100 * }
101 * return false;
102 * }
103 * return a.reduce(reduceToDetermineIfArraysContainSameContents, true);
104 * }
105 *
106 * export const creactOrderDoesNotMatterSelector = createSelectorFactory(
107 * (projectionFun) => defaultMemoize(
108 * projectionFun,
109 * orderDoesNotMatterComparer,
110 * orderDoesNotMatterComparer
111 * )
112 * );
113 * ```
114 *
115 * **Creating an Alternative Memoization Strategy**
116 *
117 * ```ts
118 * function serialize(x: any): string {
119 * return JSON.stringify(x);
120 * }
121 *
122 * export const createFullHistorySelector = createSelectorFactory(
123 * (projectionFunction) => {
124 * const cache = {};
125 *
126 * function memoized() {
127 * const serializedArguments = serialize(...arguments);
128 * if (cache[serializedArguments] != null) {
129 * cache[serializedArguments] = projectionFunction.apply(null, arguments);
130 * }
131 * return cache[serializedArguments];
132 * }
133 * return {
134 * memoized,
135 * reset: () => {},
136 * setResult: () => {},
137 * clearResult: () => {},
138 * };
139 * }
140 * );
141 * ```
142 *
143 *
144 */
145export function createSelectorFactory(memoize, options = {
146 stateFn: defaultStateFn,
147}) {
148 return function (...input) {
149 let args = input;
150 if (Array.isArray(args[0])) {
151 const [head, ...tail] = args;
152 args = [...head, ...tail];
153 }
154 const selectors = args.slice(0, args.length - 1);
155 const projector = args[args.length - 1];
156 const memoizedSelectors = selectors.filter((selector) => selector.release && typeof selector.release === 'function');
157 const memoizedProjector = memoize(function (...selectors) {
158 return projector.apply(null, selectors);
159 });
160 const memoizedState = defaultMemoize(function (state, props) {
161 return options.stateFn.apply(null, [
162 state,
163 selectors,
164 props,
165 memoizedProjector,
166 ]);
167 });
168 function release() {
169 memoizedState.reset();
170 memoizedProjector.reset();
171 memoizedSelectors.forEach((selector) => selector.release());
172 }
173 return Object.assign(memoizedState.memoized, {
174 release,
175 projector: memoizedProjector.memoized,
176 setResult: memoizedState.setResult,
177 clearResult: memoizedState.clearResult,
178 });
179 };
180}
181export function createFeatureSelector(featureName) {
182 return createSelector((state) => {
183 const featureState = state[featureName];
184 if (!isNgrxMockEnvironment() && isDevMode() && !(featureName in state)) {
185 console.warn(`@ngrx/store: The feature name "${featureName}" does ` +
186 'not exist in the state, therefore createFeatureSelector ' +
187 'cannot access it. Be sure it is imported in a loaded module ' +
188 `using StoreModule.forRoot('${featureName}', ...) or ` +
189 `StoreModule.forFeature('${featureName}', ...). If the default ` +
190 'state is intended to be undefined, as is the case with router ' +
191 'state, this development-only warning message can be ignored.');
192 }
193 return featureState;
194 }, (featureState) => featureState);
195}
196//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VsZWN0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9tb2R1bGVzL3N0b3JlL3NyYy9zZWxlY3Rvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzFDLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLFNBQVMsQ0FBQztBQTJDaEQsTUFBTSxVQUFVLFlBQVksQ0FBQyxDQUFNLEVBQUUsQ0FBTTtJQUN6QyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDakIsQ0FBQztBQUVELFNBQVMsa0JBQWtCLENBQ3pCLElBQWdCLEVBQ2hCLGFBQXlCLEVBQ3pCLFVBQXdCO0lBRXhCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO1FBQ3BDLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFO1lBQzFDLE9BQU8sSUFBSSxDQUFDO1NBQ2I7S0FDRjtJQUNELE9BQU8sS0FBSyxDQUFDO0FBQ2YsQ0FBQztBQUVELE1BQU0sVUFBVSxhQUFhLENBQzNCLFlBQW1CLEVBQ25CLGFBQTJCO0lBRTNCLE9BQU8sY0FBYyxDQUFDLFlBQVksRUFBRSxZQUFZLEVBQUUsYUFBYSxDQUFDLENBQUM7QUFDbkUsQ0FBQztBQUVELE1BQU0sVUFBVSxjQUFjLENBQzVCLFlBQW1CLEVBQ25CLGdCQUFnQixHQUFHLFlBQVksRUFDL0IsYUFBYSxHQUFHLFlBQVk7SUFFNUIsSUFBSSxhQUFhLEdBQXNCLElBQUksQ0FBQztJQUM1Qyx1RUFBdUU7SUFDdkUsSUFBSSxVQUFVLEdBQVEsSUFBSSxDQUFDO0lBQzNCLElBQUksY0FBbUIsQ0FBQztJQUV4QixTQUFTLEtBQUs7UUFDWixhQUFhLEdBQUcsSUFBSSxDQUFD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LENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQztBQUNKLENBQUM7QUFRRCxNQUFNLFVBQVUscUJBQXFCLENBQ25DLFdBQWdCO0lBRWhCLE9BQU8sY0FBYyxDQUNuQixDQUFDLEtBQVUsRUFBRSxFQUFFO1FBQ2IsTUFBTSxZQUFZLEdBQUcsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ3hDLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxJQUFJLFNBQVMsRUFBRSxJQUFJLENBQUMsQ0FBQyxXQUFXLElBQUksS0FBSyxDQUFDLEVBQUU7WUFDdEUsT0FBTyxDQUFDLElBQUksQ0FDVixrQ0FBa0MsV0FBVyxTQUFTO2dCQUNwRCwwREFBMEQ7Z0JBQzFELCtEQUErRDtnQkFDL0QsOEJBQThCLFdBQVcsYUFBYTtnQkFDdEQsMkJBQTJCLFdBQVcsMkJBQTJCO2dCQUNqRSxnRUFBZ0U7Z0JBQ2hFLDhEQUE4RCxDQUNqRSxDQUFDO1NBQ0g7UUFDRCxPQUFPLFlBQVksQ0FBQztJQUN0QixDQUFDLEVBQ0QsQ0FBQyxZQUFpQixFQUFFLEVBQUUsQ0FBQyxZQUFZLENBQ3BDLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgU2VsZWN0b3IsIFNlbGVjdG9yV2l0aFByb3BzIH0gZnJvbSAnLi9tb2RlbHMnO1xuaW1wb3J0IHsgaXNEZXZNb2RlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBpc05ncnhNb2NrRW52aXJvbm1lbnQgfSBmcm9tICcuL2ZsYWdzJztcblxuZXhwb3J0IHR5cGUgQW55Rm4gPSAoLi4uYXJnczogYW55W10pID0+IGFueTtcblxuZXhwb3J0IHR5cGUgTWVtb2l6ZWRQcm9qZWN0aW9uID0ge1xuICBtZW1vaXplZDogQW55Rm47XG4gIHJlc2V0OiAoKSA9PiB2b2lkO1xuICBzZXRSZXN1bHQ6IChyZXN1bHQ/OiBhbnkpID0+IHZvaWQ7XG4gIGNsZWFyUmVzdWx0OiAoKSA9PiB2b2lkO1xufTtcblxuZXhwb3J0IHR5cGUgTWVtb2l6ZUZuID0gKHQ6IEFueUZuKSA9PiBNZW1vaXplZFByb2plY3Rpb247XG5cbmV4cG9ydCB0eXBlIENvbXBhcmF0b3JGbiA9IChhOiBhbnksIGI6IGFueSkgPT4gYm9vbGVhbjtcblxuZXhwb3J0IHR5cGUgRGVmYXVsdFByb2plY3RvckZuPFQ+ID0gKC4uLmFyZ3M6IGFueVtdKSA9PiBUO1xuXG5leHBvcnQgaW50ZXJmYWNlIE1lbW9pemVkU2VsZWN0b3I8XG4gIFN0YXRlLFxuICBSZXN1bHQsXG4gIFByb2plY3RvckZuID0gRGVmYXVsdFByb2plY3RvckZuPFJlc3VsdD5cbj4gZXh0ZW5kcyBTZWxlY3RvcjxTdGF0ZSwgUmVzdWx0PiB7XG4gIHJlbGVhc2UoKTogdm9pZDtcbiAgcHJvamVjdG9yOiBQcm9qZWN0b3JGbjtcbiAgc2V0UmVzdWx0OiAocmVzdWx0PzogUmVzdWx0KSA9PiB2b2lkO1xuICBjbGVhclJlc3VsdDogKCkgPT4gdm9pZDtcbn1cblxuLyoqXG4gKiBAZGVwcmVjYXRlZCBTZWxlY3RvcnMgd2l0aCBwcm9wcyBhcmUgZGVwcmVjYXRlZCwgZm9yIG1vcmUgaW5mbyBzZWUge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9uZ3J4L3BsYXRmb3JtL2lzc3Vlcy8yOTgwIEdpdGh1YiBJc3N1ZX1cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBNZW1vaXplZFNlbGVjdG9yV2l0aFByb3BzPFxuICBTdGF0ZSxcbiAgUHJvcHMsXG4gIFJlc3VsdCxcbiAgUHJvamVjdG9yRm4gPSBEZWZhdWx0UHJvamVjdG9yRm48UmVzdWx0PlxuPiBleHRlbmRzIFNlbGVjdG9yV2l0aFByb3BzPFN0YXRlLCBQcm9wcywgUmVzdWx0PiB7XG4gIHJlbGVhc2UoKTogdm9pZDtcbiAgcHJvamVjdG9yOiBQcm9qZWN0b3JGbjtcbiAgc2V0UmVzdWx0OiAocmVzdWx0PzogUmVzdWx0KSA9PiB2b2lkO1xuICBjbGVhclJlc3VsdDogKCkgPT4gdm9pZDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzRXF1YWxDaGVjayhhOiBhbnksIGI6IGFueSk6IGJvb2xlYW4ge1xuICByZXR1cm4gYSA9PT0gYjtcbn1cblxuZnVuY3Rpb24gaXNBcmd1bWVudHNDaGFuZ2VkKFxuICBhcmdzOiBJQXJndW1lbnRzLFxuICBsYXN0QXJndW1lbnRzOiBJQXJndW1lbnRzLFxuICBjb21wYXJhdG9yOiBDb21wYXJhdG9yRm5cbikge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIWNvbXBhcmF0b3IoYXJnc1tpXSwgbGFzdEFyZ3VtZW50c1tpXSkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuICByZXR1cm4gZmFsc2U7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZXN1bHRNZW1vaXplKFxuICBwcm9qZWN0aW9uRm46IEFueUZuLFxuICBpc1Jlc3VsdEVxdWFsOiBDb21wYXJhdG9yRm5cbikge1xuICByZXR1cm4gZGVmYXVsdE1lbW9pemUocHJvamVjdGlvbkZuLCBpc0VxdWFsQ2hlY2ssIGlzUmVzdWx0RXF1YWwpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVmYXVsdE1lbW9pemUoXG4gIHByb2plY3Rpb25GbjogQW55Rm4sXG4gIGlzQXJndW1lbnRzRXF1YWwgPSBpc0VxdWFsQ2hlY2ssXG4gIGlzUmVzdWx0RXF1YWwgPSBpc0VxdWFsQ2hlY2tcbik6IE1lbW9pemVkUHJvamVjdGlvbiB7XG4gIGxldCBsYXN0QXJndW1lbnRzOiBudWxsIHwgSUFyZ3VtZW50cyA9IG51bGw7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55LCAsICwgLCAsXG4gIGxldCBsYXN0UmVzdWx0OiBhbnkgPSBudWxsO1xuICBsZXQgb3ZlcnJpZGVSZXN1bHQ6IGFueTtcblxuICBmdW5jdGlvbiByZXNldCgpIHtcbiAgICBsYXN0QXJndW1lbnRzID0gbnVsbDtcbiAgICBsYXN0UmVzdWx0ID0gbnVsbDtcbiAgfVxuXG4gIGZ1bmN0aW9uIHNldFJlc3VsdChyZXN1bHQ6IGFueSA9IHVuZGVmaW5lZCkge1xuICAgIG92ZXJyaWRlUmVzdWx0ID0geyByZXN1bHQgfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNsZWFyUmVzdWx0KCkge1xuICAgIG92ZXJyaWRlUmVzdWx0ID0gdW5kZWZpbmVkO1xuICB9XG5cbiAgLyogZXNsaW50LWRpc2FibGUgcHJlZmVyLXJlc3QtcGFyYW1zLCBwcmVmZXItc3ByZWFkICovXG4gIC8vIGRpc2FibGVkIGJlY2F1c2Ugb2YgdGhlIHVzZSBvZiBgYXJndW1lbnRzYFxuICBmdW5jdGlvbiBtZW1vaXplZCgpOiBhbnkge1xuICAgIGlmIChvdmVycmlkZVJlc3VsdCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gb3ZlcnJpZGVSZXN1bHQucmVzdWx0O1xuICAgIH1cblxuICAgIGlmICghbGFzdEFyZ3VtZW50cykge1xuICAgICAgbGFzdFJlc3VsdCA9IHByb2plY3Rpb25Gbi5hcHBseShudWxsLCBhcmd1bWVudHMgYXMgYW55KTtcbiAgICAgIGxhc3RBcmd1bWVudHMgPSBhcmd1bWVudHM7XG4gICAgICByZXR1cm4gbGFzdFJlc3VsdDtcbiAgICB9XG5cbiAgICBpZiAoIWlzQXJndW1lbnRzQ2hhbmdlZChhcmd1bWVudHMsIGxhc3RBcmd1bWVudHMsIGlzQXJndW1lbnRzRXF1YWwpKSB7XG4gICAgICByZXR1cm4gbGFzdFJlc3VsdDtcbiAgICB9XG5cbiAgICBjb25zdCBuZXdSZXN1bHQgPSBwcm9qZWN0aW9uRm4uYXBwbHkobnVsbCwgYXJndW1lbnRzIGFzIGFueSk7XG4gICAgbGFzdEFyZ3VtZW50cyA9IGFyZ3VtZW50cztcblxuICAgIGlmIChpc1Jlc3VsdEVxdWFsKGxhc3RSZXN1bHQsIG5ld1Jlc3VsdCkpIHtcbiAgICAgIHJldHVybiBsYXN0UmVzdWx0O1xuICAgIH1cblxuICAgIGxhc3RSZXN1bHQgPSBuZXdSZXN1bHQ7XG5cbiAgICByZXR1cm4gbmV3UmVzdWx0O1xuICB9XG5cbiAgcmV0dXJuIHsgbWVtb2l6ZWQsIHJlc2V0LCBzZXRSZXN1bHQsIGNsZWFyUmVzdWx0IH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVTZWxlY3RvcjxTdGF0ZSwgUzEsIFJlc3VsdD4oXG4gIHMxOiBTZWxlY3RvcjxTdGF0ZSwgUzE+LFxuICBwcm9qZWN0b3I6IChzMTogUzEpID0+IFJlc3VsdFxuKTogTWVtb2l6ZWRTZWxlY3RvcjxTdGF0ZSwgUmVzdWx0Pjtcbi8qKlxuICogQGRlcHJlY2F0ZWQgU2VsZWN0b3JzIHdpdGggcHJvcHMgYXJlIGRlcHJlY2F0ZWQsIGZvciBtb3JlIGluZm8gc2VlIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vbmdyeC9wbGF0Zm9ybS9pc3N1ZXMvMjk4MCBHaXRodWIgSXNzdWV9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVTZWxlY3RvcjxTdGF0ZSwgUHJvcHMsIFMxLCBSZXN1bHQ+KFxuICBzMTogU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBTMT4sXG4gIHByb2plY3RvcjogKHMxOiBTMSwgcHJvcHM6IFByb3BzKSA9PiBSZXN1bHRcbik6IE1lbW9pemVkU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBSZXN1bHQ+O1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVNlbGVjdG9yPFN0YXRlLCBTMSwgUmVzdWx0PihcbiAgc2VsZWN0b3JzOiBbU2VsZWN0b3I8U3RhdGUsIFMxPl0sXG4gIHByb2plY3RvcjogKHMxOiBTMSkgPT4gUmVzdWx0XG4pOiBNZW1vaXplZFNlbGVjdG9yPFN0YXRlLCBSZXN1bHQ+O1xuLyoqXG4gKiBAZGVwcmVjYXRlZCBTZWxlY3RvcnMgd2l0aCBwcm9wcyBhcmUgZGVwcmVjYXRlZCwgZm9yIG1vcmUgaW5mbyBzZWUge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9uZ3J4L3BsYXRmb3JtL2lzc3Vlcy8yOTgwIEdpdGh1YiBJc3N1ZX1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVNlbGVjdG9yPFN0YXRlLCBQcm9wcywgUzEsIFJlc3VsdD4oXG4gIHNlbGVjdG9yczogW1NlbGVjdG9yV2l0aFByb3BzPFN0YXRlLCBQcm9wcywgUzE+XSxcbiAgcHJvamVjdG9yOiAoczE6IFMxLCBwcm9wczogUHJvcHMpID0+IFJlc3VsdFxuKTogTWVtb2l6ZWRTZWxlY3RvcldpdGhQcm9wczxTdGF0ZSwgUHJvcHMsIFJlc3VsdD47XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVTZWxlY3RvcjxTdGF0ZSwgUzEsIFMyLCBSZXN1bHQ+KFxuICBzMTogU2VsZWN0b3I8U3RhdGUsIFMxPixcbiAgczI6IFNlbGVjdG9yPFN0YXRlLCBTMj4sXG4gIHByb2plY3RvcjogKHMxOiBTMSwgczI6IFMyKSA9PiBSZXN1bHRcbik6IE1lbW9pemVkU2VsZWN0b3I8U3RhdGUsIFJlc3VsdD47XG4vKipcbiAqIEBkZXByZWNhdGVkIFNlbGVjdG9ycyB3aXRoIHByb3BzIGFyZSBkZXByZWNhdGVkLCBmb3IgbW9yZSBpbmZvIHNlZSB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL25ncngvcGxhdGZvcm0vaXNzdWVzLzI5ODAgR2l0aHViIElzc3VlfVxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlU2VsZWN0b3I8U3RhdGUsIFByb3BzLCBTMSwgUzIsIFJlc3VsdD4oXG4gIHMxOiBTZWxlY3RvcldpdGhQcm9wczxTdGF0ZSwgUHJvcHMsIFMxPixcbiAgczI6IFNlbGVjdG9yV2l0aFByb3BzPFN0YXRlLCBQcm9wcywgUzI+LFxuICBwcm9qZWN0b3I6IChzMTogUzEsIHMyOiBTMiwgcHJvcHM6IFByb3BzKSA9PiBSZXN1bHRcbik6IE1lbW9pemVkU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBSZXN1bHQ+O1xuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlU2VsZWN0b3I8U3RhdGUsIFMxLCBTMiwgUmVzdWx0PihcbiAgc2VsZWN0b3JzOiBbU2VsZWN0b3I8U3RhdGUsIFMxPiwgU2VsZWN0b3I8U3RhdGUsIFMyPl0sXG4gIHByb2plY3RvcjogKHMxOiBTMSwgczI6IFMyKSA9PiBSZXN1bHRcbik6IE1lbW9pemVkU2VsZWN0b3I8U3RhdGUsIFJlc3VsdD47XG4vKipcbiAqIEBkZXByZWNhdGVkIFNlbGVjdG9ycyB3aXRoIHByb3BzIGFyZSBkZXByZWNhdGVkLCBmb3IgbW9yZSBpbmZvIHNlZSB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL25ncngvcGxhdGZvcm0vaXNzdWVzLzI5ODAgR2l0aHViIElzc3VlfVxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlU2VsZWN0b3I8U3RhdGUsIFByb3BzLCBTMSwgUzIsIFJlc3VsdD4oXG4gIHNlbGVjdG9yczogW1xuICAgIFNlbGVjdG9yV2l0aFByb3BzPFN0YXRlLCBQcm9wcywgUzE+LFxuICAgIFNlbGVjdG9yV2l0aFByb3BzPFN0YXRlLCBQcm9wcywgUzI+XG4gIF0sXG4gIHByb2plY3RvcjogKHMxOiBTMSwgczI6IFMyLCBwcm9wczogUHJvcHMpID0+IFJlc3VsdFxuKTogTWVtb2l6ZWRTZWxlY3RvcldpdGhQcm9wczxTdGF0ZSwgUHJvcHMsIFJlc3VsdD47XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVTZWxlY3RvcjxTdGF0ZSwgUzEsIFMyLCBTMywgUmVzdWx0PihcbiAgczE6IFNlbGVjdG9yPFN0YXRlLCBTMT4sXG4gIHMyOiBTZWxlY3RvcjxTdGF0ZSwgUzI+LFxuICBzMzogU2VsZWN0b3I8U3RhdGUsIFMzPixcbiAgcHJvamVjdG9yOiAoczE6IFMxLCBzMjogUzIsIHMzOiBTMykgPT4gUmVzdWx0XG4pOiBNZW1vaXplZFNlbGVjdG9yPFN0YXRlLCBSZXN1bHQ+O1xuLyoqXG4gKiBAZGVwcmVjYXRlZCBTZWxlY3RvcnMgd2l0aCBwcm9wcyBhcmUgZGVwcmVjYXRlZCwgZm9yIG1vcmUgaW5mbyBzZWUge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9uZ3J4L3BsYXRmb3JtL2lzc3Vlcy8yOTgwIEdpdGh1YiBJc3N1ZX1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVNlbGVjdG9yPFN0YXRlLCBQcm9wcywgUzEsIFMyLCBTMywgUmVzdWx0PihcbiAgczE6IFNlbGVjdG9yV2l0aFByb3BzPFN0YXRlLCBQcm9wcywgUzE+LFxuICBzMjogU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBTMj4sXG4gIHMzOiBTZWxlY3RvcldpdGhQcm9wczxTdGF0ZSwgUHJvcHMsIFMzPixcbiAgcHJvamVjdG9yOiAoczE6IFMxLCBzMjogUzIsIHMzOiBTMywgcHJvcHM6IFByb3BzKSA9PiBSZXN1bHRcbik6IE1lbW9pemVkU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBSZXN1bHQ+O1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVNlbGVjdG9yPFN0YXRlLCBTMSwgUzIsIFMzLCBSZXN1bHQ+KFxuICBzZWxlY3RvcnM6IFtTZWxlY3RvcjxTdGF0ZSwgUzE+LCBTZWxlY3RvcjxTdGF0ZSwgUzI+LCBTZWxlY3RvcjxTdGF0ZSwgUzM+XSxcbiAgcHJvamVjdG9yOiAoczE6IFMxLCBzMjogUzIsIHMzOiBTMykgPT4gUmVzdWx0XG4pOiBNZW1vaXplZFNlbGVjdG9yPFN0YXRlLCBSZXN1bHQ+O1xuLyoqXG4gKiBAZGVwcmVjYXRlZCBTZWxlY3RvcnMgd2l0aCBwcm9wcyBhcmUgZGVwcmVjYXRlZCwgZm9yIG1vcmUgaW5mbyBzZWUge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9uZ3J4L3BsYXRmb3JtL2lzc3Vlcy8yOTgwIEdpdGh1YiBJc3N1ZX1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVNlbGVjdG9yPFN0YXRlLCBQcm9wcywgUzEsIFMyLCBTMywgUmVzdWx0PihcbiAgc2VsZWN0b3JzOiBbXG4gICAgU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBTMT4sXG4gICAgU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBTMj4sXG4gICAgU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBTMz5cbiAgXSxcbiAgcHJvamVjdG9yOiAoczE6IFMxLCBzMjogUzIsIHMzOiBTMywgcHJvcHM6IFByb3BzKSA9PiBSZXN1bHRcbik6IE1lbW9pemVkU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBSZXN1bHQ+O1xuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlU2VsZWN0b3I8U3RhdGUsIFMxLCBTMiwgUzMsIFM0LCBSZXN1bHQ+KFxuICBzMTogU2VsZWN0b3I8U3RhdGUsIFMxPixcbiAgczI6IFNlbGVjdG9yPFN0YXRlLCBTMj4sXG4gIHMzOiBTZWxlY3RvcjxTdGF0ZSwgUzM+LFxuICBzNDogU2VsZWN0b3I8U3RhdGUsIFM0PixcbiAgcHJvamVjdG9yOiAoczE6IFMxLCBzMjogUzIsIHMzOiBTMywgczQ6IFM0KSA9PiBSZXN1bHRcbik6IE1lbW9pemVkU2VsZWN0b3I8U3RhdGUsIFJlc3VsdD47XG4vKipcbiAqIEBkZXByZWNhdGVkIFNlbGVjdG9ycyB3aXRoIHByb3BzIGFyZSBkZXByZWNhdGVkLCBmb3IgbW9yZSBpbmZvIHNlZSB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL25ncngvcGxhdGZvcm0vaXNzdWVzLzI5ODAgR2l0aHViIElzc3VlfVxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlU2VsZWN0b3I8U3RhdGUsIFByb3BzLCBTMSwgUzIsIFMzLCBTNCwgUmVzdWx0PihcbiAgczE6IFNlbGVjdG9yV2l0aFByb3BzPFN0YXRlLCBQcm9wcywgUzE+LFxuICBzMjogU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBTMj4sXG4gIHMzOiBTZWxlY3RvcldpdGhQcm9wczxTdGF0ZSwgUHJvcHMsIFMzPixcbiAgczQ6IFNlbGVjdG9yV2l0aFByb3BzPFN0YXRlLCBQcm9wcywgUzQ+LFxuICBwcm9qZWN0b3I6IChzMTogUzEsIHMyOiBTMiwgczM6IFMzLCBzNDogUzQsIHByb3BzOiBQcm9wcykgPT4gUmVzdWx0XG4pOiBNZW1vaXplZFNlbGVjdG9yV2l0aFByb3BzPFN0YXRlLCBQcm9wcywgUmVzdWx0PjtcbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVTZWxlY3RvcjxTdGF0ZSwgUzEsIFMyLCBTMywgUzQsIFJlc3VsdD4oXG4gIHNlbGVjdG9yczogW1xuICAgIFNlbGVjdG9yPFN0YXRlLCBTMT4sXG4gICAgU2VsZWN0b3I8U3RhdGUsIFMyPixcbiAgICBTZWxlY3RvcjxTdGF0ZSwgUzM+LFxuICAgIFNlbGVjdG9yPFN0YXRlLCBTND5cbiAgXSxcbiAgcHJvamVjdG9yOiAoczE6IFMxLCBzMjogUzIsIHMzOiBTMywgczQ6IFM0KSA9PiBSZXN1bHRcbik6IE1lbW9pemVkU2VsZWN0b3I8U3RhdGUsIFJlc3VsdD47XG4vKipcbiAqIEBkZXByZWNhdGVkIFNlbGVjdG9ycyB3aXRoIHByb3BzIGFyZSBkZXByZWNhdGVkLCBmb3IgbW9yZSBpbmZvIHNlZSB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL25ncngvcGxhdGZvcm0vaXNzdWVzLzI5ODAgR2l0aHViIElzc3VlfVxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlU2VsZWN0b3I8U3RhdGUsIFByb3BzLCBTMSwgUzIsIFMzLCBTNCwgUmVzdWx0PihcbiAgc2VsZWN0b3JzOiBbXG4gICAgU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBTMT4sXG4gICAgU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBTMj4sXG4gICAgU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBTMz4sXG4gICAgU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBTND5cbiAgXSxcbiAgcHJvamVjdG9yOiAoczE6IFMxLCBzMjogUzIsIHMzOiBTMywgczQ6IFM0LCBwcm9wczogUHJvcHMpID0+IFJlc3VsdFxuKTogTWVtb2l6ZWRTZWxlY3RvcldpdGhQcm9wczxTdGF0ZSwgUHJvcHMsIFJlc3VsdD47XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVTZWxlY3RvcjxTdGF0ZSwgUzEsIFMyLCBTMywgUzQsIFM1LCBSZXN1bHQ+KFxuICBzMTogU2VsZWN0b3I8U3RhdGUsIFMxPixcbiAgczI6IFNlbGVjdG9yPFN0YXRlLCBTMj4sXG4gIHMzOiBTZWxlY3RvcjxTdGF0ZSwgUzM+LFxuICBzNDogU2VsZWN0b3I8U3RhdGUsIFM0PixcbiAgczU6IFNlbGVjdG9yPFN0YXRlLCBTNT4sXG4gIHByb2plY3RvcjogKHMxOiBTMSwgczI6IFMyLCBzMzogUzMsIHM0OiBTNCwgczU6IFM1KSA9PiBSZXN1bHRcbik6IE1lbW9pemVkU2VsZWN0b3I8U3RhdGUsIFJlc3VsdD47XG4vKipcbiAqIEBkZXByZWNhdGVkIFNlbGVjdG9ycyB3aXRoIHByb3BzIGFyZSBkZXByZWNhdGVkLCBmb3IgbW9yZSBpbmZvIHNlZSB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL25ncngvcGxhdGZvcm0vaXNzdWVzLzI5ODAgR2l0aHViIElzc3VlfVxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlU2VsZWN0b3I8U3RhdGUsIFByb3BzLCBTMSwgUzIsIFMzLCBTNCwgUzUsIFJlc3VsdD4oXG4gIHMxOiBTZWxlY3RvcldpdGhQcm9wczxTdGF0ZSwgUHJvcHMsIFMxPixcbiAgczI6IFNlbGVjdG9yV2l0aFByb3BzPFN0YXRlLCBQcm9wcywgUzI+LFxuICBzMzogU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBTMz4sXG4gIHM0OiBTZWxlY3RvcldpdGhQcm9wczxTdGF0ZSwgUHJvcHMsIFM0PixcbiAgczU6IFNlbGVjdG9yV2l0aFByb3BzPFN0YXRlLCBQcm9wcywgUzU+LFxuICBwcm9qZWN0b3I6IChzMTogUzEsIHMyOiBTMiwgczM6IFMzLCBzNDogUzQsIHM1OiBTNSwgcHJvcHM6IFByb3BzKSA9PiBSZXN1bHRcbik6IE1lbW9pemVkU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBSZXN1bHQ+O1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVNlbGVjdG9yPFN0YXRlLCBTMSwgUzIsIFMzLCBTNCwgUzUsIFJlc3VsdD4oXG4gIHNlbGVjdG9yczogW1xuICAgIFNlbGVjdG9yPFN0YXRlLCBTMT4sXG4gICAgU2VsZWN0b3I8U3RhdGUsIFMyPixcbiAgICBTZWxlY3RvcjxTdGF0ZSwgUzM+LFxuICAgIFNlbGVjdG9yPFN0YXRlLCBTND4sXG4gICAgU2VsZWN0b3I8U3RhdGUsIFM1PlxuICBdLFxuICBwcm9qZWN0b3I6IChzMTogUzEsIHMyOiBTMiwgczM6IFMzLCBzNDogUzQsIHM1OiBTNSkgPT4gUmVzdWx0XG4pOiBNZW1vaXplZFNlbGVjdG9yPFN0YXRlLCBSZXN1bHQ+O1xuLyoqXG4gKiBAZGVwcmVjYXRlZCBTZWxlY3RvcnMgd2l0aCBwcm9wcyBhcmUgZGVwcmVjYXRlZCwgZm9yIG1vcmUgaW5mbyBzZWUge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9uZ3J4L3BsYXRmb3JtL2lzc3Vlcy8yOTgwIEdpdGh1YiBJc3N1ZX1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVNlbGVjdG9yPFN0YXRlLCBQcm9wcywgUzEsIFMyLCBTMywgUzQsIFM1LCBSZXN1bHQ+KFxuICBzZWxlY3RvcnM6IFtcbiAgICBTZWxlY3RvcldpdGhQcm9wczxTdGF0ZSwgUHJvcHMsIFMxPixcbiAgICBTZWxlY3RvcldpdGhQcm9wczxTdGF0ZSwgUHJvcHMsIFMyPixcbiAgICBTZWxlY3RvcldpdGhQcm9wczxTdGF0ZSwgUHJvcHMsIFMzPixcbiAgICBTZWxlY3RvcldpdGhQcm9wczxTdGF0ZSwgUHJvcHMsIFM0PixcbiAgICBTZWxlY3RvcldpdGhQcm9wczxTdGF0ZSwgUHJvcHMsIFM1PlxuICBdLFxuICBwcm9qZWN0b3I6IChzMTogUzEsIHMyOiBTMiwgczM6IFMzLCBzNDogUzQsIHM1OiBTNSwgcHJvcHM6IFByb3BzKSA9PiBSZXN1bHRcbik6IE1lbW9pemVkU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBSZXN1bHQ+O1xuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlU2VsZWN0b3I8U3RhdGUsIFMxLCBTMiwgUzMsIFM0LCBTNSwgUzYsIFJlc3VsdD4oXG4gIHMxOiBTZWxlY3RvcjxTdGF0ZSwgUzE+LFxuICBzMjogU2VsZWN0b3I8U3RhdGUsIFMyPixcbiAgczM6IFNlbGVjdG9yPFN0YXRlLCBTMz4sXG4gIHM0OiBTZWxlY3RvcjxTdGF0ZSwgUzQ+LFxuICBzNTogU2VsZWN0b3I8U3RhdGUsIFM1PixcbiAgczY6IFNlbGVjdG9yPFN0YXRlLCBTNj4sXG4gIHByb2plY3RvcjogKHMxOiBTMSwgczI6IFMyLCBzMzogUzMsIHM0OiBTNCwgczU6IFM1LCBzNjogUzYpID0+IFJlc3VsdFxuKTogTWVtb2l6ZWRTZWxlY3RvcjxTdGF0ZSwgUmVzdWx0Pjtcbi8qKlxuICogQGRlcHJlY2F0ZWQgU2VsZWN0b3JzIHdpdGggcHJvcHMgYXJlIGRlcHJlY2F0ZWQsIGZvciBtb3JlIGluZm8gc2VlIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vbmdyeC9wbGF0Zm9ybS9pc3N1ZXMvMjk4MCBHaXRodWIgSXNzdWV9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVTZWxlY3RvcjxTdGF0ZSwgUHJvcHMsIFMxLCBTMiwgUzMsIFM0LCBTNSwgUzYsIFJlc3VsdD4oXG4gIHMxOiBTZWxlY3RvcldpdGhQcm9wczxTdGF0ZSwgUHJvcHMsIFMxPixcbiAgczI6IFNlbGVjdG9yV2l0aFByb3BzPFN0YXRlLCBQcm9wcywgUzI+LFxuICBzMzogU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBTMz4sXG4gIHM0OiBTZWxlY3RvcldpdGhQcm9wczxTdGF0ZSwgUHJvcHMsIFM0PixcbiAgczU6IFNlbGVjdG9yV2l0aFByb3BzPFN0YXRlLCBQcm9wcywgUzU+LFxuICBzNjogU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBTNj4sXG4gIHByb2plY3RvcjogKFxuICAgIHMxOiBTMSxcbiAgICBzMjogUzIsXG4gICAgczM6IFMzLFxuICAgIHM0OiBTNCxcbiAgICBzNTogUzUsXG4gICAgczY6IFM2LFxuICAgIHByb3BzOiBQcm9wc1xuICApID0+IFJlc3VsdFxuKTogTWVtb2l6ZWRTZWxlY3RvcldpdGhQcm9wczxTdGF0ZSwgUHJvcHMsIFJlc3VsdD47XG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlU2VsZWN0b3I8U3RhdGUsIFMxLCBTMiwgUzMsIFM0LCBTNSwgUzYsIFJlc3VsdD4oXG4gIHNlbGVjdG9yczogW1xuICAgIFNlbGVjdG9yPFN0YXRlLCBTMT4sXG4gICAgU2VsZWN0b3I8U3RhdGUsIFMyPixcbiAgICBTZWxlY3RvcjxTdGF0ZSwgUzM+LFxuICAgIFNlbGVjdG9yPFN0YXRlLCBTND4sXG4gICAgU2VsZWN0b3I8U3RhdGUsIFM1PixcbiAgICBTZWxlY3RvcjxTdGF0ZSwgUzY+XG4gIF0sXG4gIHByb2plY3RvcjogKHMxOiBTMSwgczI6IFMyLCBzMzogUzMsIHM0OiBTNCwgczU6IFM1LCBzNjogUzYpID0+IFJlc3VsdFxuKTogTWVtb2l6ZWRTZWxlY3RvcjxTdGF0ZSwgUmVzdWx0Pjtcbi8qKlxuICogQGRlcHJlY2F0ZWQgU2VsZWN0b3JzIHdpdGggcHJvcHMgYXJlIGRlcHJlY2F0ZWQsIGZvciBtb3JlIGluZm8gc2VlIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vbmdyeC9wbGF0Zm9ybS9pc3N1ZXMvMjk4MCBHaXRodWIgSXNzdWV9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVTZWxlY3RvcjxTdGF0ZSwgUHJvcHMsIFMxLCBTMiwgUzMsIFM0LCBTNSwgUzYsIFJlc3VsdD4oXG4gIHNlbGVjdG9yczogW1xuICAgIFNlbGVjdG9yV2l0aFByb3BzPFN0YXRlLCBQcm9wcywgUzE+LFxuICAgIFNlbGVjdG9yV2l0aFByb3BzPFN0YXRlLCBQcm9wcywgUzI+LFxuICAgIFNlbGVjdG9yV2l0aFByb3BzPFN0YXRlLCBQcm9wcywgUzM+LFxuICAgIFNlbGVjdG9yV2l0aFByb3BzPFN0YXRlLCBQcm9wcywgUzQ+LFxuICAgIFNlbGVjdG9yV2l0aFByb3BzPFN0YXRlLCBQcm9wcywgUzU+LFxuICAgIFNlbGVjdG9yV2l0aFByb3BzPFN0YXRlLCBQcm9wcywgUzY+XG4gIF0sXG4gIHByb2plY3RvcjogKFxuICAgIHMxOiBTMSxcbiAgICBzMjogUzIsXG4gICAgczM6IFMzLFxuICAgIHM0OiBTNCxcbiAgICBzNTogUzUsXG4gICAgczY6IFM2LFxuICAgIHByb3BzOiBQcm9wc1xuICApID0+IFJlc3VsdFxuKTogTWVtb2l6ZWRTZWxlY3RvcldpdGhQcm9wczxTdGF0ZSwgUHJvcHMsIFJlc3VsdD47XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVTZWxlY3RvcjxTdGF0ZSwgUzEsIFMyLCBTMywgUzQsIFM1LCBTNiwgUzcsIFJlc3VsdD4oXG4gIHMxOiBTZWxlY3RvcjxTdGF0ZSwgUzE+LFxuICBzMjogU2VsZWN0b3I8U3RhdGUsIFMyPixcbiAgczM6IFNlbGVjdG9yPFN0YXRlLCBTMz4sXG4gIHM0OiBTZWxlY3RvcjxTdGF0ZSwgUzQ+LFxuICBzNTogU2VsZWN0b3I8U3RhdGUsIFM1PixcbiAgczY6IFNlbGVjdG9yPFN0YXRlLCBTNj4sXG4gIHM3OiBTZWxlY3RvcjxTdGF0ZSwgUzc+LFxuICBwcm9qZWN0b3I6IChzMTogUzEsIHMyOiBTMiwgczM6IFMzLCBzNDogUzQsIHM1OiBTNSwgczY6IFM2LCBzNzogUzcpID0+IFJlc3VsdFxuKTogTWVtb2l6ZWRTZWxlY3RvcjxTdGF0ZSwgUmVzdWx0Pjtcbi8qKlxuICogQGRlcHJlY2F0ZWQgU2VsZWN0b3JzIHdpdGggcHJvcHMgYXJlIGRlcHJlY2F0ZWQsIGZvciBtb3JlIGluZm8gc2VlIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vbmdyeC9wbGF0Zm9ybS9pc3N1ZXMvMjk4MCBHaXRodWIgSXNzdWV9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVTZWxlY3RvcjxcbiAgU3RhdGUsXG4gIFByb3BzLFxuICBTMSxcbiAgUzIsXG4gIFMzLFxuICBTNCxcbiAgUzUsXG4gIFM2LFxuICBTNyxcbiAgUmVzdWx0XG4+KFxuICBzMTogU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBTMT4sXG4gIHMyOiBTZWxlY3RvcldpdGhQcm9wczxTdGF0ZSwgUHJvcHMsIFMyPixcbiAgczM6IFNlbGVjdG9yV2l0aFByb3BzPFN0YXRlLCBQcm9wcywgUzM+LFxuICBzNDogU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBTND4sXG4gIHM1OiBTZWxlY3RvcldpdGhQcm9wczxTdGF0ZSwgUHJvcHMsIFM1PixcbiAgczY6IFNlbGVjdG9yV2l0aFByb3BzPFN0YXRlLCBQcm9wcywgUzY+LFxuICBzNzogU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBTNz4sXG4gIHByb2plY3RvcjogKFxuICAgIHMxOiBTMSxcbiAgICBzMjogUzIsXG4gICAgczM6IFMzLFxuICAgIHM0OiBTNCxcbiAgICBzNTogUzUsXG4gICAgczY6IFM2LFxuICAgIHM3OiBTNyxcbiAgICBwcm9wczogUHJvcHNcbiAgKSA9PiBSZXN1bHRcbik6IE1lbW9pemVkU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBSZXN1bHQ+O1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVNlbGVjdG9yPFN0YXRlLCBTMSwgUzIsIFMzLCBTNCwgUzUsIFM2LCBTNywgUmVzdWx0PihcbiAgc2VsZWN0b3JzOiBbXG4gICAgU2VsZWN0b3I8U3RhdGUsIFMxPixcbiAgICBTZWxlY3RvcjxTdGF0ZSwgUzI+LFxuICAgIFNlbGVjdG9yPFN0YXRlLCBTMz4sXG4gICAgU2VsZWN0b3I8U3RhdGUsIFM0PixcbiAgICBTZWxlY3RvcjxTdGF0ZSwgUzU+LFxuICAgIFNlbGVjdG9yPFN0YXRlLCBTNj4sXG4gICAgU2VsZWN0b3I8U3RhdGUsIFM3PlxuICBdLFxuICBwcm9qZWN0b3I6IChzMTogUzEsIHMyOiBTMiwgczM6IFMzLCBzNDogUzQsIHM1OiBTNSwgczY6IFM2LCBzNzogUzcpID0+IFJlc3VsdFxuKTogTWVtb2l6ZWRTZWxlY3RvcjxTdGF0ZSwgUmVzdWx0Pjtcbi8qKlxuICogQGRlcHJlY2F0ZWQgU2VsZWN0b3JzIHdpdGggcHJvcHMgYXJlIGRlcHJlY2F0ZWQsIGZvciBtb3JlIGluZm8gc2VlIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vbmdyeC9wbGF0Zm9ybS9pc3N1ZXMvMjk4MCBHaXRodWIgSXNzdWV9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVTZWxlY3RvcjxcbiAgU3RhdGUsXG4gIFByb3BzLFxuICBTMSxcbiAgUzIsXG4gIFMzLFxuICBTNCxcbiAgUzUsXG4gIFM2LFxuICBTNyxcbiAgUmVzdWx0XG4+KFxuICBzZWxlY3RvcnM6IFtcbiAgICBTZWxlY3RvcldpdGhQcm9wczxTdGF0ZSwgUHJvcHMsIFMxPixcbiAgICBTZWxlY3RvcldpdGhQcm9wczxTdGF0ZSwgUHJvcHMsIFMyPixcbiAgICBTZWxlY3RvcldpdGhQcm9wczxTdGF0ZSwgUHJvcHMsIFMzPixcbiAgICBTZWxlY3RvcldpdGhQcm9wczxTdGF0ZSwgUHJvcHMsIFM0PixcbiAgICBTZWxlY3RvcldpdGhQcm9wczxTdGF0ZSwgUHJvcHMsIFM1PixcbiAgICBTZWxlY3RvcldpdGhQcm9wczxTdGF0ZSwgUHJvcHMsIFM2PixcbiAgICBTZWxlY3RvcldpdGhQcm9wczxTdGF0ZSwgUHJvcHMsIFM3PlxuICBdLFxuICBwcm9qZWN0b3I6IChcbiAgICBzMTogUzEsXG4gICAgczI6IFMyLFxuICAgIHMzOiBTMyxcbiAgICBzNDogUzQsXG4gICAgczU6IFM1LFxuICAgIHM2OiBTNixcbiAgICBzNzogUzcsXG4gICAgcHJvcHM6IFByb3BzXG4gICkgPT4gUmVzdWx0XG4pOiBNZW1vaXplZFNlbGVjdG9yV2l0aFByb3BzPFN0YXRlLCBQcm9wcywgUmVzdWx0PjtcblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVNlbGVjdG9yPFN0YXRlLCBTMSwgUzIsIFMzLCBTNCwgUzUsIFM2LCBTNywgUzgsIFJlc3VsdD4oXG4gIHMxOiBTZWxlY3RvcjxTdGF0ZSwgUzE+LFxuICBzMjogU2VsZWN0b3I8U3RhdGUsIFMyPixcbiAgczM6IFNlbGVjdG9yPFN0YXRlLCBTMz4sXG4gIHM0OiBTZWxlY3RvcjxTdGF0ZSwgUzQ+LFxuICBzNTogU2VsZWN0b3I8U3RhdGUsIFM1PixcbiAgczY6IFNlbGVjdG9yPFN0YXRlLCBTNj4sXG4gIHM3OiBTZWxlY3RvcjxTdGF0ZSwgUzc+LFxuICBzODogU2VsZWN0b3I8U3RhdGUsIFM4PixcbiAgcHJvamVjdG9yOiAoXG4gICAgczE6IFMxLFxuICAgIHMyOiBTMixcbiAgICBzMzogUzMsXG4gICAgczQ6IFM0LFxuICAgIHM1OiBTNSxcbiAgICBzNjogUzYsXG4gICAgczc6IFM3LFxuICAgIHM4OiBTOFxuICApID0+IFJlc3VsdFxuKTogTWVtb2l6ZWRTZWxlY3RvcjxTdGF0ZSwgUmVzdWx0Pjtcbi8qKlxuICogQGRlcHJlY2F0ZWQgU2VsZWN0b3JzIHdpdGggcHJvcHMgYXJlIGRlcHJlY2F0ZWQsIGZvciBtb3JlIGluZm8gc2VlIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vbmdyeC9wbGF0Zm9ybS9pc3N1ZXMvMjk4MCBHaXRodWIgSXNzdWV9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVTZWxlY3RvcjxcbiAgU3RhdGUsXG4gIFByb3BzLFxuICBTMSxcbiAgUzIsXG4gIFMzLFxuICBTNCxcbiAgUzUsXG4gIFM2LFxuICBTNyxcbiAgUzgsXG4gIFJlc3VsdFxuPihcbiAgczE6IFNlbGVjdG9yV2l0aFByb3BzPFN0YXRlLCBQcm9wcywgUzE+LFxuICBzMjogU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBTMj4sXG4gIHMzOiBTZWxlY3RvcldpdGhQcm9wczxTdGF0ZSwgUHJvcHMsIFMzPixcbiAgczQ6IFNlbGVjdG9yV2l0aFByb3BzPFN0YXRlLCBQcm9wcywgUzQ+LFxuICBzNTogU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBTNT4sXG4gIHM2OiBTZWxlY3RvcldpdGhQcm9wczxTdGF0ZSwgUHJvcHMsIFM2PixcbiAgczc6IFNlbGVjdG9yV2l0aFByb3BzPFN0YXRlLCBQcm9wcywgUzc+LFxuICBzODogU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBTOD4sXG4gIHByb2plY3RvcjogKFxuICAgIHMxOiBTMSxcbiAgICBzMjogUzIsXG4gICAgczM6IFMzLFxuICAgIHM0OiBTNCxcbiAgICBzNTogUzUsXG4gICAgczY6IFM2LFxuICAgIHM3OiBTNyxcbiAgICBzODogUzgsXG4gICAgcHJvcHM6IFByb3BzXG4gICkgPT4gUmVzdWx0XG4pOiBNZW1vaXplZFNlbGVjdG9yV2l0aFByb3BzPFN0YXRlLCBQcm9wcywgUmVzdWx0PjtcbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVTZWxlY3RvcjxTdGF0ZSwgUzEsIFMyLCBTMywgUzQsIFM1LCBTNiwgUzcsIFM4LCBSZXN1bHQ+KFxuICBzZWxlY3RvcnM6IFtcbiAgICBTZWxlY3RvcjxTdGF0ZSwgUzE+LFxuICAgIFNlbGVjdG9yPFN0YXRlLCBTMj4sXG4gICAgU2VsZWN0b3I8U3RhdGUsIFMzPixcbiAgICBTZWxlY3RvcjxTdGF0ZSwgUzQ+LFxuICAgIFNlbGVjdG9yPFN0YXRlLCBTNT4sXG4gICAgU2VsZWN0b3I8U3RhdGUsIFM2PixcbiAgICBTZWxlY3RvcjxTdGF0ZSwgUzc+LFxuICAgIFNlbGVjdG9yPFN0YXRlLCBTOD5cbiAgXSxcbiAgcHJvamVjdG9yOiAoXG4gICAgczE6IFMxLFxuICAgIHMyOiBTMixcbiAgICBzMzogUzMsXG4gICAgczQ6IFM0LFxuICAgIHM1OiBTNSxcbiAgICBzNjogUzYsXG4gICAgczc6IFM3LFxuICAgIHM4OiBTOFxuICApID0+IFJlc3VsdFxuKTogTWVtb2l6ZWRTZWxlY3RvcjxTdGF0ZSwgUmVzdWx0Pjtcbi8qKlxuICogQGRlcHJlY2F0ZWQgU2VsZWN0b3JzIHdpdGggcHJvcHMgYXJlIGRlcHJlY2F0ZWQsIGZvciBtb3JlIGluZm8gc2VlIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vbmdyeC9wbGF0Zm9ybS9pc3N1ZXMvMjk4MCBHaXRodWIgSXNzdWV9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVTZWxlY3RvcjxcbiAgU3RhdGUsXG4gIFByb3BzLFxuICBTMSxcbiAgUzIsXG4gIFMzLFxuICBTNCxcbiAgUzUsXG4gIFM2LFxuICBTNyxcbiAgUzgsXG4gIFJlc3VsdFxuPihcbiAgc2VsZWN0b3JzOiBbXG4gICAgU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBTMT4sXG4gICAgU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBTMj4sXG4gICAgU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBTMz4sXG4gICAgU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBTND4sXG4gICAgU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBTNT4sXG4gICAgU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBTNj4sXG4gICAgU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBTNz4sXG4gICAgU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBTOD5cbiAgXSxcbiAgcHJvamVjdG9yOiAoXG4gICAgczE6IFMxLFxuICAgIHMyOiBTMixcbiAgICBzMzogUzMsXG4gICAgczQ6IFM0LFxuICAgIHM1OiBTNSxcbiAgICBzNjogUzYsXG4gICAgczc6IFM3LFxuICAgIHM4OiBTOCxcbiAgICBwcm9wczogUHJvcHNcbiAgKSA9PiBSZXN1bHRcbik6IE1lbW9pemVkU2VsZWN0b3JXaXRoUHJvcHM8U3RhdGUsIFByb3BzLCBSZXN1bHQ+O1xuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlU2VsZWN0b3IoXG4gIC4uLmlucHV0OiBhbnlbXVxuKTogTWVtb2l6ZWRTZWxlY3RvcjxhbnksIGFueT4gfCBNZW1vaXplZFNlbGVjdG9yV2l0aFByb3BzPGFueSwgYW55LCBhbnk+IHtcbiAgcmV0dXJuIGNyZWF0ZVNlbGVjdG9yRmFjdG9yeShkZWZhdWx0TWVtb2l6ZSkoLi4uaW5wdXQpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVmYXVsdFN0YXRlRm4oXG4gIHN0YXRlOiBhbnksXG4gIHNlbGVjdG9yczogU2VsZWN0b3I8YW55LCBhbnk+W10gfCBTZWxlY3RvcldpdGhQcm9wczxhbnksIGFueSwgYW55PltdLFxuICBwcm9wczogYW55LFxuICBtZW1vaXplZFByb2plY3RvcjogTWVtb2l6ZWRQcm9qZWN0aW9uXG4pOiBhbnkge1xuICBpZiAocHJvcHMgPT09IHVuZGVmaW5lZCkge1xuICAgIGNvbnN0IGFyZ3MgPSAoPFNlbGVjdG9yPGFueSwgYW55PltdPnNlbGVjdG9ycykubWFwKChmbikgPT4gZm4oc3RhdGUpKTtcbiAgICByZXR1cm4gbWVtb2l6ZWRQcm9qZWN0b3IubWVtb2l6ZWQuYXBwbHkobnVsbCwgYXJncyk7XG4gIH1cblxuICBjb25zdCBhcmdzID0gKDxTZWxlY3RvcldpdGhQcm9wczxhbnksIGFueSwgYW55PltdPnNlbGVjdG9ycykubWFwKChmbikgPT5cbiAgICBmbihzdGF0ZSwgcHJvcHMpXG4gICk7XG4gIHJldHVybiBtZW1vaXplZFByb2plY3Rvci5tZW1vaXplZC5hcHBseShudWxsLCBbLi4uYXJncywgcHJvcHNdKTtcbn1cblxuZXhwb3J0IHR5cGUgU2VsZWN0b3JGYWN0b3J5Q29uZmlnPFQgPSBhbnksIFYgPSBhbnk+ID0ge1xuICBzdGF0ZUZuOiAoXG4gICAgc3RhdGU6IFQsXG4gICAgc2VsZWN0b3JzOiBTZWxlY3RvcjxhbnksIGFueT5bXSxcbiAgICBwcm9wczogYW55LFxuICAgIG1lbW9pemVkUHJvamVjdG9yOiBNZW1vaXplZFByb2plY3Rpb25cbiAgKSA9PiBWO1xufTtcblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVNlbGVjdG9yRmFjdG9yeTxUID0gYW55LCBWID0gYW55PihcbiAgbWVtb2l6ZTogTWVtb2l6ZUZuXG4pOiAoLi4uaW5wdXQ6IGFueVtdKSA9PiBNZW1vaXplZFNlbGVjdG9yPFQsIFY+O1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVNlbGVjdG9yRmFjdG9yeTxUID0gYW55LCBWID0gYW55PihcbiAgbWVtb2l6ZTogTWVtb2l6ZUZuLFxuICBvcHRpb25zOiBTZWxlY3RvckZhY3RvcnlDb25maWc8VCwgVj5cbik6ICguLi5pbnB1dDogYW55W10pID0+IE1lbW9pemVkU2VsZWN0b3I8VCwgVj47XG4vKipcbiAqIEBkZXByZWNhdGVkIFNlbGVjdG9ycyB3aXRoIHByb3BzIGFyZSBkZXByZWNhdGVkLCBmb3IgbW9yZSBpbmZvIHNlZSB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL25ncngvcGxhdGZvcm0vaXNzdWVzLzI5ODAgR2l0aHViIElzc3VlfVxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlU2VsZWN0b3JGYWN0b3J5PFQgPSBhbnksIFByb3BzID0gYW55LCBWID0gYW55PihcbiAgbWVtb2l6ZTogTWVtb2l6ZUZuXG4pOiAoLi4uaW5wdXQ6IGFueVtdKSA9PiBNZW1vaXplZFNlbGVjdG9yV2l0aFByb3BzPFQsIFByb3BzLCBWPjtcbi8qKlxuICogQGRlcHJlY2F0ZWQgU2VsZWN0b3JzIHdpdGggcHJvcHMgYXJlIGRlcHJlY2F0ZWQsIGZvciBtb3JlIGluZm8gc2VlIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vbmdyeC9wbGF0Zm9ybS9pc3N1ZXMvMjk4MCBHaXRodWIgSXNzdWV9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVTZWxlY3RvckZhY3Rvcnk8VCA9IGFueSwgUHJvcHMgPSBhbnksIFYgPSBhbnk+KFxuICBtZW1vaXplOiBNZW1vaXplRm4sXG4gIG9wdGlvbnM6IFNlbGVjdG9yRmFjdG9yeUNvbmZpZzxULCBWPlxuKTogKC4uLmlucHV0OiBhbnlbXSkgPT4gTWVtb2l6ZWRTZWxlY3RvcldpdGhQcm9wczxULCBQcm9wcywgVj47XG4vKipcbiAqXG4gKiBAcGFyYW0gbWVtb2l6ZSBUaGUgZnVuY3Rpb24gdXNlZCB0byBtZW1vaXplIHNlbGVjdG9yc1xuICogQHBhcmFtIG9wdGlvbnMgQ29uZmlnIE9iamVjdCB0aGF0IG1heSBpbmNsdWRlIGEgYHN0YXRlRm5gIGZ1bmN0aW9uIGRlZmluaW5nIGhvdyB0byByZXR1cm4gdGhlIHNlbGVjdG9yJ3MgdmFsdWUsIGdpdmVuIHRoZSBlbnRpcmUgYFN0b3JlYCdzIHN0YXRlLCBwYXJlbnQgYFNlbGVjdG9yYHMsIGBQcm9wc2AsIGFuZCBhIGBNZW1vaXplZFByb2plY3Rpb25gXG4gKlxuICogQHVzYWdlTm90ZXNcbiAqXG4gKiAqKkNyZWF0aW5nIGEgU2VsZWN0b3IgRmFjdG9yeSBXaGVyZSBBcnJheSBPcmRlciBEb2VzIE5vdCBNYXR0ZXIqKlxuICpcbiAqIGBgYHRzXG4gKiBmdW5jdGlvbiByZW1vdmVNYXRjaChhcnI6IHN0cmluZ1tdLCB0YXJnZXQ6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAqICAgY29uc3QgbWF0Y2hJbmRleCA9IGFyci5pbmRleE9mKHRhcmdldCk7XG4gKiAgIHJldHVybiBbLi4uYXJyLnNsaWNlKDAsIG1hdGNoSW5kZXgpLCAuLi5hcnIuc2xpY2UobWF0Y2hJbmRleCArIDEpXTtcbiAqIH1cbiAqXG4gKiBmdW5jdGlvbiBvcmRlckRvZXNOb3RNYXR0ZXJDb21wYXJlcihhOiBhbnksIGI6IGFueSk6IGJvb2xlYW4ge1xuICogICBpZiAoIUFycmF5LmlzQXJyYXkoYSkgfHwgIUFycmF5LmlzQXJyYXkoYikpIHtcbiAqICAgICByZXR1cm4gYSA9PT0gYjtcbiAqICAgfVxuICogICBpZiAoYS5sZW5ndGggIT09IGIubGVuZ3RoKSB7XG4gKiAgICAgcmV0dXJuIGZhbHNlO1xuICogICB9XG4gKiAgIGxldCB0ZW1wQiA9IFsuLi5iXTtcbiAqICAgZnVuY3Rpb24gcmVkdWNlVG9EZXRlcm1pbmVJZkFycmF5c0NvbnRhaW5TYW1lQ29udGVudHMoXG4gKiAgICAgcHJldmlvdXNDYWxsUmVzdWx0OiBib29sZWFuLFxuICogICAgIGFycmF5TWVtYmVyOiBhbnlcbiAqICAgKTogYm9vbGVhbiB7XG4gKiAgICAgaWYgKHByZXZpb3VzQ2FsbFJlc3VsdCA9PT0gZmFsc2UpIHtcbiAqICAgICAgIHJldHVybiBmYWxzZTtcbiAqICAgICB9XG4gKiAgICAgaWYgKHRlbXBCLmluY2x1ZGVzKGFycmF5TWVtYmVyKSkge1xuICogICAgICAgdGVtcEIgPSByZW1vdmVNYXRjaCh0ZW1wQiwgYXJyYXlNZW1iZXIpO1xuICogICAgICAgcmV0dXJuIHRydWU7XG4gKiAgICAgfVxuICogICAgIHJldHVybiBmYWxzZTtcbiAqICAgfVxuICogICByZXR1cm4gYS5yZWR1Y2UocmVkdWNlVG9EZXRlcm1pbmVJZkFycmF5c0NvbnRhaW5TYW1lQ29udGVudHMsIHRydWUpO1xuICogfVxuICpcbiAqIGV4cG9ydCBjb25zdCBjcmVhY3RPcmRlckRvZXNOb3RNYXR0ZXJTZWxlY3RvciA9IGNyZWF0ZVNlbGVjdG9yRmFjdG9yeShcbiAqICAgKHByb2plY3Rpb25GdW4pID0+IGRlZmF1bHRNZW1vaXplKFxuICogICAgIHByb2plY3Rpb25GdW4sXG4gKiAgICAgb3JkZXJEb2VzTm90TWF0dGVyQ29tcGFyZXIsXG4gKiAgICAgb3JkZXJEb2VzTm90TWF0dGVyQ29tcGFyZXJcbiAqICAgKVxuICogKTtcbiAqIGBgYFxuICpcbiAqICoqQ3JlYXRpbmcgYW4gQWx0ZXJuYXRpdmUgTWVtb2l6YXRpb24gU3RyYXRlZ3kqKlxuICpcbiAqIGBgYHRzXG4gKiBmdW5jdGlvbiBzZXJpYWxpemUoeDogYW55KTogc3RyaW5nIHtcbiAqICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHgpO1xuICogfVxuICpcbiAqIGV4cG9ydCBjb25zdCBjcmVhdGVGdWxsSGlzdG9yeVNlbGVjdG9yID0gY3JlYXRlU2VsZWN0b3JGYWN0b3J5KFxuICogIChwcm9qZWN0aW9uRnVuY3Rpb24pID0+IHtcbiAqICAgIGNvbnN0IGNhY2hlID0ge307XG4gKlxuICogICAgZnVuY3Rpb24gbWVtb2l6ZWQoKSB7XG4gKiAgICAgIGNvbnN0IHNlcmlhbGl6ZWRBcmd1bWVudHMgPSBzZXJpYWxpemUoLi4uYXJndW1lbnRzKTtcbiAqICAgICAgIGlmIChjYWNoZVtzZXJpYWxpemVkQXJndW1lbnRzXSAhPSBudWxsKSB7XG4gKiAgICAgICAgIGNhY2hlW3NlcmlhbGl6ZWRBcmd1bWVudHNdID0gcHJvamVjdGlvbkZ1bmN0aW9uLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG4gKiAgICAgICB9XG4gKiAgICAgICByZXR1cm4gY2FjaGVbc2VyaWFsaXplZEFyZ3VtZW50c107XG4gKiAgICAgfVxuICogICAgIHJldHVybiB7XG4gKiAgICAgICBtZW1vaXplZCxcbiAqICAgICAgIHJlc2V0OiAoKSA9PiB7fSxcbiAqICAgICAgIHNldFJlc3VsdDogKCkgPT4ge30sXG4gKiAgICAgICBjbGVhclJlc3VsdDogKCkgPT4ge30sXG4gKiAgICAgfTtcbiAqICAgfVxuICogKTtcbiAqIGBgYFxuICpcbiAqXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVTZWxlY3RvckZhY3RvcnkoXG4gIG1lbW9pemU6IE1lbW9pemVGbixcbiAgb3B0aW9uczogU2VsZWN0b3JGYWN0b3J5Q29uZmlnPGFueSwgYW55PiA9IHtcbiAgICBzdGF0ZUZuOiBkZWZhdWx0U3RhdGVGbixcbiAgfVxuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoXG4gICAgLi4uaW5wdXQ6IGFueVtdXG4gICk6IE1lbW9pemVkU2VsZWN0b3I8YW55LCBhbnk+IHwgTWVtb2l6ZWRTZWxlY3RvcldpdGhQcm9wczxhbnksIGFueSwgYW55PiB7XG4gICAgbGV0IGFyZ3MgPSBpbnB1dDtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShhcmdzWzBdKSkge1xuICAgICAgY29uc3QgW2hlYWQsIC4uLnRhaWxdID0gYXJncztcbiAgICAgIGFyZ3MgPSBbLi4uaGVhZCwgLi4udGFpbF07XG4gICAgfVxuXG4gICAgY29uc3Qgc2VsZWN0b3JzID0gYXJncy5zbGljZSgwLCBhcmdzLmxlbmd0aCAtIDEpO1xuICAgIGNvbnN0IHByb2plY3RvciA9IGFyZ3NbYXJncy5sZW5ndGggLSAxXTtcbiAgICBjb25zdCBtZW1vaXplZFNlbGVjdG9ycyA9IHNlbGVjdG9ycy5maWx0ZXIoXG4gICAgICAoc2VsZWN0b3I6IGFueSkgPT5cbiAgICAgICAgc2VsZWN0b3IucmVsZWFzZSAmJiB0eXBlb2Ygc2VsZWN0b3IucmVsZWFzZSA9PT0gJ2Z1bmN0aW9uJ1xuICAgICk7XG5cbiAgICBjb25zdCBtZW1vaXplZFByb2plY3RvciA9IG1lbW9pemUoZnVuY3Rpb24gKC4uLnNlbGVjdG9yczogYW55W10pIHtcbiAgICAgIHJldHVybiBwcm9qZWN0b3IuYXBwbHkobnVsbCwgc2VsZWN0b3JzKTtcbiAgICB9KTtcblxuICAgIGNvbnN0IG1lbW9pemVkU3RhdGUgPSBkZWZhdWx0TWVtb2l6ZShmdW5jdGlvbiAoc3RhdGU6IGFueSwgcHJvcHM6IGFueSkge1xuICAgICAgcmV0dXJuIG9wdGlvbnMuc3RhdGVGbi5hcHBseShudWxsLCBbXG4gICAgICAgIHN0YXRlLFxuICAgICAgICBzZWxlY3RvcnMsXG4gICAgICAgIHByb3BzLFxuICAgICAgICBtZW1vaXplZFByb2plY3RvcixcbiAgICAgIF0pO1xuICAgIH0pO1xuXG4gICAgZnVuY3Rpb24gcmVsZWFzZSgpIHtcbiAgICAgIG1lbW9pemVkU3RhdGUucmVzZXQoKTtcbiAgICAgIG1lbW9pemVkUHJvamVjdG9yLnJlc2V0KCk7XG5cbiAgICAgIG1lbW9pemVkU2VsZWN0b3JzLmZvckVhY2goKHNlbGVjdG9yKSA9PiBzZWxlY3Rvci5yZWxlYXNlKCkpO1xuICAgIH1cblxuICAgIHJldHVybiBPYmplY3QuYXNzaWduKG1lbW9pemVkU3RhdGUubWVtb2l6ZWQsIHtcbiAgICAgIHJlbGVhc2UsXG4gICAgICBwcm9qZWN0b3I6IG1lbW9pemVkUHJvamVjdG9yLm1lbW9pemVkLFxuICAgICAgc2V0UmVzdWx0OiBtZW1vaXplZFN0YXRlLnNldFJlc3VsdCxcbiAgICAgIGNsZWFyUmVzdWx0OiBtZW1vaXplZFN0YXRlLmNsZWFyUmVzdWx0LFxuICAgIH0pO1xuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlRmVhdHVyZVNlbGVjdG9yPFQ+KFxuICBmZWF0dXJlTmFtZTogc3RyaW5nXG4pOiBNZW1vaXplZFNlbGVjdG9yPG9iamVjdCwgVD47XG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlRmVhdHVyZVNlbGVjdG9yPFQsIFY+KFxuICBmZWF0dXJlTmFtZToga2V5b2YgVFxuKTogTWVtb2l6ZWRTZWxlY3RvcjxULCBWPjtcbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVGZWF0dXJlU2VsZWN0b3IoXG4gIGZlYXR1cmVOYW1lOiBhbnlcbik6IE1lbW9pemVkU2VsZWN0b3I8YW55LCBhbnk+IHtcbiAgcmV0dXJuIGNyZWF0ZVNlbGVjdG9yKFxuICAgIChzdGF0ZTogYW55KSA9PiB7XG4gICAgICBjb25zdCBmZWF0dXJlU3RhdGUgPSBzdGF0ZVtmZWF0dXJlTmFtZV07XG4gICAgICBpZiAoIWlzTmdyeE1vY2tFbnZpcm9ubWVudCgpICYmIGlzRGV2TW9kZSgpICYmICEoZmVhdHVyZU5hbWUgaW4gc3RhdGUpKSB7XG4gICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICBgQG5ncngvc3RvcmU6IFRoZSBmZWF0dXJlIG5hbWUgXCIke2ZlYXR1cmVOYW1lfVwiIGRvZXMgYCArXG4gICAgICAgICAgICAnbm90IGV4aXN0IGluIHRoZSBzdGF0ZSwgdGhlcmVmb3JlIGNyZWF0ZUZlYXR1cmVTZWxlY3RvciAnICtcbiAgICAgICAgICAgICdjYW5ub3QgYWNjZXNzIGl0LiAgQmUgc3VyZSBpdCBpcyBpbXBvcnRlZCBpbiBhIGxvYWRlZCBtb2R1bGUgJyArXG4gICAgICAgICAgICBgdXNpbmcgU3RvcmVNb2R1bGUuZm9yUm9vdCgnJHtmZWF0dXJlTmFtZX0nLCAuLi4pIG9yIGAgK1xuICAgICAgICAgICAgYFN0b3JlTW9kdWxlLmZvckZlYXR1cmUoJyR7ZmVhdHVyZU5hbWV9JywgLi4uKS4gIElmIHRoZSBkZWZhdWx0IGAgK1xuICAgICAgICAgICAgJ3N0YXRlIGlzIGludGVuZGVkIHRvIGJlIHVuZGVmaW5lZCwgYXMgaXMgdGhlIGNhc2Ugd2l0aCByb3V0ZXIgJyArXG4gICAgICAgICAgICAnc3RhdGUsIHRoaXMgZGV2ZWxvcG1lbnQtb25seSB3YXJuaW5nIG1lc3NhZ2UgY2FuIGJlIGlnbm9yZWQuJ1xuICAgICAgICApO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGZlYXR1cmVTdGF0ZTtcbiAgICB9LFxuICAgIChmZWF0dXJlU3RhdGU6IGFueSkgPT4gZmVhdHVyZVN0YXRlXG4gICk7XG59XG4iXX0=
\No newline at end of file