@ng-formworks/core 17.2.7 → 17.4.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/LICENSE +21 -0
- package/README.md +836 -0
- package/esm2022/lib/framework-library/framework-library.service.mjs +175 -0
- package/esm2022/lib/framework-library/framework.mjs +15 -0
- package/esm2022/lib/framework-library/no-framework.component.mjs +18 -0
- package/esm2022/lib/framework-library/no-framework.module.mjs +27 -0
- package/esm2022/lib/framework-library/no.framework.mjs +19 -0
- package/esm2022/lib/json-schema-form.component.mjs +765 -0
- package/esm2022/lib/json-schema-form.module.mjs +26 -0
- package/esm2022/lib/json-schema-form.service.mjs +679 -0
- package/esm2022/lib/locale/de-validation-messages.mjs +60 -0
- package/esm2022/lib/locale/en-validation-messages.mjs +60 -0
- package/esm2022/lib/locale/es-validation-messages.mjs +57 -0
- package/esm2022/lib/locale/fr-validation-messages.mjs +60 -0
- package/esm2022/lib/locale/index.mjs +8 -0
- package/esm2022/lib/locale/it-validation-messages.mjs +60 -0
- package/esm2022/lib/locale/pt-validation-messages.mjs +60 -0
- package/esm2022/lib/locale/zh-validation-messages.mjs +60 -0
- package/esm2022/lib/shared/convert-schema-to-draft6.function.mjs +300 -0
- package/esm2022/lib/shared/form-group.functions.mjs +442 -0
- package/esm2022/lib/shared/format-regex.constants.mjs +54 -0
- package/esm2022/lib/shared/index.mjs +12 -0
- package/esm2022/lib/shared/json-schema.functions.mjs +784 -0
- package/esm2022/lib/shared/json.validators.mjs +884 -0
- package/esm2022/lib/shared/jsonpointer.functions.mjs +1026 -0
- package/esm2022/lib/shared/layout.functions.mjs +1154 -0
- package/esm2022/lib/shared/merge-schemas.function.mjs +345 -0
- package/esm2022/lib/shared/utility.functions.mjs +380 -0
- package/esm2022/lib/shared/validator.functions.mjs +584 -0
- package/esm2022/lib/widget-library/add-reference.component.mjs +61 -0
- package/esm2022/lib/widget-library/button.component.mjs +72 -0
- package/esm2022/lib/widget-library/checkbox.component.mjs +105 -0
- package/esm2022/lib/widget-library/checkboxes.component.mjs +147 -0
- package/esm2022/lib/widget-library/file.component.mjs +35 -0
- package/esm2022/lib/widget-library/hidden.component.mjs +54 -0
- package/esm2022/lib/widget-library/index.mjs +55 -0
- package/esm2022/lib/widget-library/input.component.mjs +119 -0
- package/esm2022/lib/widget-library/message.component.mjs +38 -0
- package/esm2022/lib/widget-library/none.component.mjs +21 -0
- package/esm2022/lib/widget-library/number.component.mjs +123 -0
- package/esm2022/lib/widget-library/one-of.component.mjs +35 -0
- package/esm2022/lib/widget-library/orderable.directive.mjs +123 -0
- package/esm2022/lib/widget-library/radios.component.mjs +153 -0
- package/esm2022/lib/widget-library/root.component.mjs +79 -0
- package/esm2022/lib/widget-library/section.component.mjs +199 -0
- package/esm2022/lib/widget-library/select-framework.component.mjs +51 -0
- package/esm2022/lib/widget-library/select-widget.component.mjs +46 -0
- package/esm2022/lib/widget-library/select.component.mjs +150 -0
- package/esm2022/lib/widget-library/submit.component.mjs +82 -0
- package/esm2022/lib/widget-library/tab.component.mjs +41 -0
- package/esm2022/lib/widget-library/tabs.component.mjs +108 -0
- package/esm2022/lib/widget-library/template.component.mjs +46 -0
- package/esm2022/lib/widget-library/textarea.component.mjs +104 -0
- package/esm2022/lib/widget-library/widget-library.module.mjs +42 -0
- package/esm2022/lib/widget-library/widget-library.service.mjs +226 -0
- package/esm2022/ng-formworks-core.mjs +5 -0
- package/esm2022/public_api.mjs +13 -0
- package/fesm2022/ng-formworks-core.mjs +10149 -0
- package/fesm2022/ng-formworks-core.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/lib/framework-library/framework-library.service.d.ts +55 -0
- package/lib/framework-library/framework.d.ts +13 -0
- package/lib/framework-library/no-framework.component.d.ts +8 -0
- package/lib/framework-library/no-framework.module.d.ts +9 -0
- package/lib/framework-library/no.framework.d.ts +10 -0
- package/lib/json-schema-form.component.d.ts +218 -0
- package/lib/json-schema-form.module.d.ts +11 -0
- package/lib/json-schema-form.service.d.ts +115 -0
- package/lib/locale/de-validation-messages.d.ts +1 -0
- package/lib/locale/en-validation-messages.d.ts +1 -0
- package/lib/locale/es-validation-messages.d.ts +1 -0
- package/lib/locale/fr-validation-messages.d.ts +1 -0
- package/{src/lib/locale/index.ts → lib/locale/index.d.ts} +7 -7
- package/lib/locale/it-validation-messages.d.ts +1 -0
- package/lib/locale/pt-validation-messages.d.ts +1 -0
- package/lib/locale/zh-validation-messages.d.ts +1 -0
- package/lib/shared/convert-schema-to-draft6.function.d.ts +21 -0
- package/lib/shared/form-group.functions.d.ts +100 -0
- package/lib/shared/format-regex.constants.d.ts +19 -0
- package/lib/shared/index.d.ts +9 -0
- package/lib/shared/json-schema.functions.d.ts +193 -0
- package/lib/shared/json.validators.d.ts +441 -0
- package/lib/shared/jsonpointer.functions.d.ts +416 -0
- package/lib/shared/layout.functions.d.ts +83 -0
- package/lib/shared/merge-schemas.function.d.ts +19 -0
- package/lib/shared/utility.functions.d.ts +165 -0
- package/{src/lib/shared/validator.functions.ts → lib/shared/validator.functions.d.ts} +364 -601
- package/lib/widget-library/add-reference.component.d.ts +20 -0
- package/lib/widget-library/button.component.d.ts +21 -0
- package/lib/widget-library/checkbox.component.d.ts +24 -0
- package/lib/widget-library/checkboxes.component.d.ts +24 -0
- package/lib/widget-library/file.component.d.ts +21 -0
- package/lib/widget-library/hidden.component.d.ts +19 -0
- package/{src/lib/widget-library/index.ts → lib/widget-library/index.d.ts} +47 -56
- package/lib/widget-library/input.component.d.ts +22 -0
- package/lib/widget-library/message.component.d.ts +15 -0
- package/lib/widget-library/none.component.d.ts +8 -0
- package/lib/widget-library/number.component.d.ts +25 -0
- package/lib/widget-library/one-of.component.d.ts +21 -0
- package/lib/widget-library/orderable.directive.d.ts +41 -0
- package/lib/widget-library/radios.component.d.ts +23 -0
- package/lib/widget-library/root.component.d.ts +17 -0
- package/lib/widget-library/section.component.d.ts +19 -0
- package/lib/widget-library/select-framework.component.d.ts +18 -0
- package/lib/widget-library/select-widget.component.d.ts +18 -0
- package/lib/widget-library/select.component.d.ts +24 -0
- package/lib/widget-library/submit.component.d.ts +24 -0
- package/lib/widget-library/tab.component.d.ts +14 -0
- package/lib/widget-library/tabs.component.d.ts +20 -0
- package/lib/widget-library/template.component.d.ts +18 -0
- package/lib/widget-library/textarea.component.d.ts +21 -0
- package/lib/widget-library/widget-library.module.d.ts +31 -0
- package/lib/widget-library/widget-library.service.d.ts +22 -0
- package/package.json +64 -53
- package/{src/public_api.ts → public_api.d.ts} +9 -21
- package/karma.conf.js +0 -46
- package/ng-package.json +0 -11
- package/src/lib/framework-library/framework-library.service.ts +0 -195
- package/src/lib/framework-library/framework.ts +0 -11
- package/src/lib/framework-library/no-framework.component.html +0 -2
- package/src/lib/framework-library/no-framework.component.ts +0 -11
- package/src/lib/framework-library/no-framework.module.ts +0 -18
- package/src/lib/framework-library/no.framework.ts +0 -11
- package/src/lib/json-schema-form.component.html +0 -7
- package/src/lib/json-schema-form.component.ts +0 -809
- package/src/lib/json-schema-form.module.ts +0 -17
- package/src/lib/json-schema-form.service.ts +0 -907
- package/src/lib/locale/de-validation-messages.ts +0 -58
- package/src/lib/locale/en-validation-messages.ts +0 -58
- package/src/lib/locale/es-validation-messages.ts +0 -55
- package/src/lib/locale/fr-validation-messages.ts +0 -58
- package/src/lib/locale/it-validation-messages.ts +0 -58
- package/src/lib/locale/pt-validation-messages.ts +0 -58
- package/src/lib/locale/zh-validation-messages.ts +0 -58
- package/src/lib/locale-dates/en-US.ts +0 -5
- package/src/lib/shared/convert-schema-to-draft6.function.ts +0 -321
- package/src/lib/shared/form-group.functions.ts +0 -522
- package/src/lib/shared/format-regex.constants.ts +0 -73
- package/src/lib/shared/index.ts +0 -40
- package/src/lib/shared/json-schema.functions.ts +0 -788
- package/src/lib/shared/json.validators.ts +0 -878
- package/src/lib/shared/jsonpointer.functions.ts +0 -1012
- package/src/lib/shared/jspointer.functions.json.spec.ts +0 -103
- package/src/lib/shared/layout.functions.ts +0 -1233
- package/src/lib/shared/merge-schemas.function.ts +0 -329
- package/src/lib/shared/utility.functions.ts +0 -373
- package/src/lib/shared/validator.functions.spec.ts +0 -55
- package/src/lib/widget-library/add-reference.component.ts +0 -59
- package/src/lib/widget-library/button.component.ts +0 -54
- package/src/lib/widget-library/checkbox.component.ts +0 -74
- package/src/lib/widget-library/checkboxes.component.ts +0 -104
- package/src/lib/widget-library/file.component.ts +0 -36
- package/src/lib/widget-library/hidden.component.ts +0 -39
- package/src/lib/widget-library/input.component.ts +0 -76
- package/src/lib/widget-library/message.component.ts +0 -29
- package/src/lib/widget-library/none.component.ts +0 -12
- package/src/lib/widget-library/number.component.ts +0 -79
- package/src/lib/widget-library/one-of.component.ts +0 -36
- package/src/lib/widget-library/orderable.directive.ts +0 -130
- package/src/lib/widget-library/radios.component.ts +0 -101
- package/src/lib/widget-library/root.component.ts +0 -78
- package/src/lib/widget-library/section.component.ts +0 -133
- package/src/lib/widget-library/select-framework.component.ts +0 -50
- package/src/lib/widget-library/select-widget.component.ts +0 -46
- package/src/lib/widget-library/select.component.ts +0 -96
- package/src/lib/widget-library/submit.component.ts +0 -68
- package/src/lib/widget-library/tab.component.ts +0 -29
- package/src/lib/widget-library/tabs.component.ts +0 -83
- package/src/lib/widget-library/template.component.ts +0 -52
- package/src/lib/widget-library/textarea.component.ts +0 -68
- package/src/lib/widget-library/widget-library.module.ts +0 -13
- package/src/lib/widget-library/widget-library.service.ts +0 -234
- package/src/test.ts +0 -18
- package/tsconfig.lib.json +0 -25
- package/tsconfig.lib.prod.json +0 -9
- package/tsconfig.spec.json +0 -17
- package/tslint.json +0 -11
|
@@ -0,0 +1,884 @@
|
|
|
1
|
+
import isEqual from 'lodash/isEqual';
|
|
2
|
+
import { _executeAsyncValidators, _executeValidators, _mergeErrors, _mergeObjects, getType, hasValue, isArray, isBoolean, isDefined, isEmpty, isNumber, isString, isType, toJavaScriptType, toObservable, xor } from './validator.functions';
|
|
3
|
+
import { forEachCopy } from './utility.functions';
|
|
4
|
+
import { forkJoin } from 'rxjs';
|
|
5
|
+
import { jsonSchemaFormatTests } from './format-regex.constants';
|
|
6
|
+
import { map } from 'rxjs/operators';
|
|
7
|
+
/**
|
|
8
|
+
* 'JsonValidators' class
|
|
9
|
+
*
|
|
10
|
+
* Provides an extended set of validators to be used by form controls,
|
|
11
|
+
* compatible with standard JSON Schema validation options.
|
|
12
|
+
* http://json-schema.org/latest/json-schema-validation.html
|
|
13
|
+
*
|
|
14
|
+
* Note: This library is designed as a drop-in replacement for the Angular
|
|
15
|
+
* Validators library, and except for one small breaking change to the 'pattern'
|
|
16
|
+
* validator (described below) it can even be imported as a substitute, like so:
|
|
17
|
+
*
|
|
18
|
+
* import { JsonValidators as Validators } from 'json-validators';
|
|
19
|
+
*
|
|
20
|
+
* and it should work with existing code as a complete replacement.
|
|
21
|
+
*
|
|
22
|
+
* The one exception is the 'pattern' validator, which has been changed to
|
|
23
|
+
* matche partial values by default (the standard 'pattern' validator wrapped
|
|
24
|
+
* all patterns in '^' and '$', forcing them to always match an entire value).
|
|
25
|
+
* However, the old behavior can be restored by simply adding '^' and '$'
|
|
26
|
+
* around your patterns, or by passing an optional second parameter of TRUE.
|
|
27
|
+
* This change is to make the 'pattern' validator match the behavior of a
|
|
28
|
+
* JSON Schema pattern, which allows partial matches, rather than the behavior
|
|
29
|
+
* of an HTML input control pattern, which does not.
|
|
30
|
+
*
|
|
31
|
+
* This library replaces Angular's validators and combination functions
|
|
32
|
+
* with the following validators and transformation functions:
|
|
33
|
+
*
|
|
34
|
+
* Validators:
|
|
35
|
+
* For all formControls: required (*), type, enum, const
|
|
36
|
+
* For text formControls: minLength (*), maxLength (*), pattern (*), format
|
|
37
|
+
* For numeric formControls: maximum, exclusiveMaximum,
|
|
38
|
+
* minimum, exclusiveMinimum, multipleOf
|
|
39
|
+
* For formGroup objects: minProperties, maxProperties, dependencies
|
|
40
|
+
* For formArray arrays: minItems, maxItems, uniqueItems, contains
|
|
41
|
+
* Not used by JSON Schema: min (*), max (*), requiredTrue (*), email (*)
|
|
42
|
+
* (Validators originally included with Angular are maked with (*).)
|
|
43
|
+
*
|
|
44
|
+
* NOTE / TODO: The dependencies validator is not complete.
|
|
45
|
+
* NOTE / TODO: The contains validator is not complete.
|
|
46
|
+
*
|
|
47
|
+
* Validators not used by JSON Schema (but included for compatibility)
|
|
48
|
+
* and their JSON Schema equivalents:
|
|
49
|
+
*
|
|
50
|
+
* Angular validator | JSON Schema equivalent
|
|
51
|
+
* ------------------|-----------------------
|
|
52
|
+
* min(number) | minimum(number)
|
|
53
|
+
* max(number) | maximum(number)
|
|
54
|
+
* requiredTrue() | const(true)
|
|
55
|
+
* email() | format('email')
|
|
56
|
+
*
|
|
57
|
+
* Validator transformation functions:
|
|
58
|
+
* composeAnyOf, composeOneOf, composeAllOf, composeNot
|
|
59
|
+
* (Angular's original combination funciton, 'compose', is also included for
|
|
60
|
+
* backward compatibility, though it is functionally equivalent to composeAllOf,
|
|
61
|
+
* asside from its more generic error message.)
|
|
62
|
+
*
|
|
63
|
+
* All validators have also been extended to accept an optional second argument
|
|
64
|
+
* which, if passed a TRUE value, causes the validator to perform the opposite
|
|
65
|
+
* of its original finction. (This is used internally to enable 'not' and
|
|
66
|
+
* 'composeOneOf' to function and return useful error messages.)
|
|
67
|
+
*
|
|
68
|
+
* The 'required' validator has also been overloaded so that if called with
|
|
69
|
+
* a boolean parameter (or no parameters) it returns the original validator
|
|
70
|
+
* function (rather than executing it). However, if it is called with an
|
|
71
|
+
* AbstractControl parameter (as was previously required), it behaves
|
|
72
|
+
* exactly as before.
|
|
73
|
+
*
|
|
74
|
+
* This enables all validators (including 'required') to be constructed in
|
|
75
|
+
* exactly the same way, so they can be automatically applied using the
|
|
76
|
+
* equivalent key names and values taken directly from a JSON Schema.
|
|
77
|
+
*
|
|
78
|
+
* This source code is partially derived from Angular,
|
|
79
|
+
* which is Copyright (c) 2014-2017 Google, Inc.
|
|
80
|
+
* Use of this source code is therefore governed by the same MIT-style license
|
|
81
|
+
* that can be found in the LICENSE file at https://angular.io/license
|
|
82
|
+
*
|
|
83
|
+
* Original Angular Validators:
|
|
84
|
+
* https://github.com/angular/angular/blob/master/packages/forms/src/validators.ts
|
|
85
|
+
*/
|
|
86
|
+
export class JsonValidators {
|
|
87
|
+
static required(input) {
|
|
88
|
+
if (input === undefined) {
|
|
89
|
+
input = true;
|
|
90
|
+
}
|
|
91
|
+
switch (input) {
|
|
92
|
+
case true: // Return required function (do not execute it yet)
|
|
93
|
+
return (control, invert = false) => {
|
|
94
|
+
if (invert) {
|
|
95
|
+
return null;
|
|
96
|
+
} // if not required, always return valid
|
|
97
|
+
return hasValue(control.value) ? null : { 'required': true };
|
|
98
|
+
};
|
|
99
|
+
case false: // Do nothing (if field is not required, it is always valid)
|
|
100
|
+
return JsonValidators.nullValidator;
|
|
101
|
+
default: // Execute required function
|
|
102
|
+
return hasValue(input.value) ? null : { 'required': true };
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* 'type' validator
|
|
107
|
+
*
|
|
108
|
+
* Requires a control to only accept values of a specified type,
|
|
109
|
+
* or one of an array of types.
|
|
110
|
+
*
|
|
111
|
+
* Note: SchemaPrimitiveType = 'string'|'number'|'integer'|'boolean'|'null'
|
|
112
|
+
*
|
|
113
|
+
* // {SchemaPrimitiveType|SchemaPrimitiveType[]} type - type(s) to accept
|
|
114
|
+
* // {IValidatorFn}
|
|
115
|
+
*/
|
|
116
|
+
static type(requiredType) {
|
|
117
|
+
if (!hasValue(requiredType)) {
|
|
118
|
+
return JsonValidators.nullValidator;
|
|
119
|
+
}
|
|
120
|
+
return (control, invert = false) => {
|
|
121
|
+
if (isEmpty(control.value)) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
const currentValue = control.value;
|
|
125
|
+
const isValid = isArray(requiredType) ?
|
|
126
|
+
requiredType.some(type => isType(currentValue, type)) :
|
|
127
|
+
isType(currentValue, requiredType);
|
|
128
|
+
return xor(isValid, invert) ?
|
|
129
|
+
null : { 'type': { requiredType, currentValue } };
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* 'enum' validator
|
|
134
|
+
*
|
|
135
|
+
* Requires a control to have a value from an enumerated list of values.
|
|
136
|
+
*
|
|
137
|
+
* Converts types as needed to allow string inputs to still correctly
|
|
138
|
+
* match number, boolean, and null enum values.
|
|
139
|
+
*
|
|
140
|
+
* // {any[]} allowedValues - array of acceptable values
|
|
141
|
+
* // {IValidatorFn}
|
|
142
|
+
*/
|
|
143
|
+
static enum(allowedValues) {
|
|
144
|
+
if (!isArray(allowedValues)) {
|
|
145
|
+
return JsonValidators.nullValidator;
|
|
146
|
+
}
|
|
147
|
+
return (control, invert = false) => {
|
|
148
|
+
if (isEmpty(control.value)) {
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
const currentValue = control.value;
|
|
152
|
+
const isEqualVal = (enumValue, inputValue) => enumValue === inputValue ||
|
|
153
|
+
(isNumber(enumValue) && +inputValue === +enumValue) ||
|
|
154
|
+
(isBoolean(enumValue, 'strict') &&
|
|
155
|
+
toJavaScriptType(inputValue, 'boolean') === enumValue) ||
|
|
156
|
+
(enumValue === null && !hasValue(inputValue)) ||
|
|
157
|
+
isEqual(enumValue, inputValue);
|
|
158
|
+
const isValid = isArray(currentValue) ?
|
|
159
|
+
currentValue.every(inputValue => allowedValues.some(enumValue => isEqualVal(enumValue, inputValue))) :
|
|
160
|
+
allowedValues.some(enumValue => isEqualVal(enumValue, currentValue));
|
|
161
|
+
return xor(isValid, invert) ?
|
|
162
|
+
null : { 'enum': { allowedValues, currentValue } };
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* 'const' validator
|
|
167
|
+
*
|
|
168
|
+
* Requires a control to have a specific value.
|
|
169
|
+
*
|
|
170
|
+
* Converts types as needed to allow string inputs to still correctly
|
|
171
|
+
* match number, boolean, and null values.
|
|
172
|
+
*
|
|
173
|
+
* TODO: modify to work with objects
|
|
174
|
+
*
|
|
175
|
+
* // {any[]} requiredValue - required value
|
|
176
|
+
* // {IValidatorFn}
|
|
177
|
+
*/
|
|
178
|
+
static const(requiredValue) {
|
|
179
|
+
if (!hasValue(requiredValue)) {
|
|
180
|
+
return JsonValidators.nullValidator;
|
|
181
|
+
}
|
|
182
|
+
return (control, invert = false) => {
|
|
183
|
+
if (isEmpty(control.value)) {
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
const currentValue = control.value;
|
|
187
|
+
const isEqualVal = (constValue, inputValue) => constValue === inputValue ||
|
|
188
|
+
isNumber(constValue) && +inputValue === +constValue ||
|
|
189
|
+
isBoolean(constValue, 'strict') &&
|
|
190
|
+
toJavaScriptType(inputValue, 'boolean') === constValue ||
|
|
191
|
+
constValue === null && !hasValue(inputValue);
|
|
192
|
+
const isValid = isEqualVal(requiredValue, currentValue);
|
|
193
|
+
return xor(isValid, invert) ?
|
|
194
|
+
null : { 'const': { requiredValue, currentValue } };
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* 'minLength' validator
|
|
199
|
+
*
|
|
200
|
+
* Requires a control's text value to be greater than a specified length.
|
|
201
|
+
*
|
|
202
|
+
* // {number} minimumLength - minimum allowed string length
|
|
203
|
+
* // {boolean = false} invert - instead return error object only if valid
|
|
204
|
+
* // {IValidatorFn}
|
|
205
|
+
*/
|
|
206
|
+
static minLength(minimumLength) {
|
|
207
|
+
if (!hasValue(minimumLength)) {
|
|
208
|
+
return JsonValidators.nullValidator;
|
|
209
|
+
}
|
|
210
|
+
return (control, invert = false) => {
|
|
211
|
+
if (isEmpty(control.value)) {
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
const currentLength = isString(control.value) ? control.value.length : 0;
|
|
215
|
+
const isValid = currentLength >= minimumLength;
|
|
216
|
+
return xor(isValid, invert) ?
|
|
217
|
+
null : { 'minLength': { minimumLength, currentLength } };
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* 'maxLength' validator
|
|
222
|
+
*
|
|
223
|
+
* Requires a control's text value to be less than a specified length.
|
|
224
|
+
*
|
|
225
|
+
* // {number} maximumLength - maximum allowed string length
|
|
226
|
+
* // {boolean = false} invert - instead return error object only if valid
|
|
227
|
+
* // {IValidatorFn}
|
|
228
|
+
*/
|
|
229
|
+
static maxLength(maximumLength) {
|
|
230
|
+
if (!hasValue(maximumLength)) {
|
|
231
|
+
return JsonValidators.nullValidator;
|
|
232
|
+
}
|
|
233
|
+
return (control, invert = false) => {
|
|
234
|
+
const currentLength = isString(control.value) ? control.value.length : 0;
|
|
235
|
+
const isValid = currentLength <= maximumLength;
|
|
236
|
+
return xor(isValid, invert) ?
|
|
237
|
+
null : { 'maxLength': { maximumLength, currentLength } };
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* 'pattern' validator
|
|
242
|
+
*
|
|
243
|
+
* Note: NOT the same as Angular's default pattern validator.
|
|
244
|
+
*
|
|
245
|
+
* Requires a control's value to match a specified regular expression pattern.
|
|
246
|
+
*
|
|
247
|
+
* This validator changes the behavior of default pattern validator
|
|
248
|
+
* by replacing RegExp(`^${pattern}$`) with RegExp(`${pattern}`),
|
|
249
|
+
* which allows for partial matches.
|
|
250
|
+
*
|
|
251
|
+
* To return to the default funcitonality, and match the entire string,
|
|
252
|
+
* pass TRUE as the optional second parameter.
|
|
253
|
+
*
|
|
254
|
+
* // {string} pattern - regular expression pattern
|
|
255
|
+
* // {boolean = false} wholeString - match whole value string?
|
|
256
|
+
* // {IValidatorFn}
|
|
257
|
+
*/
|
|
258
|
+
static pattern(pattern, wholeString = false) {
|
|
259
|
+
if (!hasValue(pattern)) {
|
|
260
|
+
return JsonValidators.nullValidator;
|
|
261
|
+
}
|
|
262
|
+
return (control, invert = false) => {
|
|
263
|
+
if (isEmpty(control.value)) {
|
|
264
|
+
return null;
|
|
265
|
+
}
|
|
266
|
+
let regex;
|
|
267
|
+
let requiredPattern;
|
|
268
|
+
if (typeof pattern === 'string') {
|
|
269
|
+
requiredPattern = (wholeString) ? `^${pattern}$` : pattern;
|
|
270
|
+
regex = new RegExp(requiredPattern);
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
requiredPattern = pattern.toString();
|
|
274
|
+
regex = pattern;
|
|
275
|
+
}
|
|
276
|
+
const currentValue = control.value;
|
|
277
|
+
const isValid = isString(currentValue) ? regex.test(currentValue) : false;
|
|
278
|
+
return xor(isValid, invert) ?
|
|
279
|
+
null : { 'pattern': { requiredPattern, currentValue } };
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* 'format' validator
|
|
284
|
+
*
|
|
285
|
+
* Requires a control to have a value of a certain format.
|
|
286
|
+
*
|
|
287
|
+
* This validator currently checks the following formsts:
|
|
288
|
+
* date, time, date-time, email, hostname, ipv4, ipv6,
|
|
289
|
+
* uri, uri-reference, uri-template, url, uuid, color,
|
|
290
|
+
* json-pointer, relative-json-pointer, regex
|
|
291
|
+
*
|
|
292
|
+
* Fast format regular expressions copied from AJV:
|
|
293
|
+
* https://github.com/epoberezkin/ajv/blob/master/lib/compile/formats.js
|
|
294
|
+
*
|
|
295
|
+
* // {JsonSchemaFormatNames} requiredFormat - format to check
|
|
296
|
+
* // {IValidatorFn}
|
|
297
|
+
*/
|
|
298
|
+
static format(requiredFormat) {
|
|
299
|
+
if (!hasValue(requiredFormat)) {
|
|
300
|
+
return JsonValidators.nullValidator;
|
|
301
|
+
}
|
|
302
|
+
return (control, invert = false) => {
|
|
303
|
+
if (isEmpty(control.value)) {
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
let isValid;
|
|
307
|
+
const currentValue = control.value;
|
|
308
|
+
if (isString(currentValue)) {
|
|
309
|
+
const formatTest = jsonSchemaFormatTests[requiredFormat];
|
|
310
|
+
if (typeof formatTest === 'object') {
|
|
311
|
+
isValid = formatTest.test(currentValue);
|
|
312
|
+
}
|
|
313
|
+
else if (typeof formatTest === 'function') {
|
|
314
|
+
isValid = formatTest(currentValue);
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
console.error(`format validator error: "${requiredFormat}" is not a recognized format.`);
|
|
318
|
+
isValid = true;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
else {
|
|
322
|
+
// Allow JavaScript Date objects
|
|
323
|
+
isValid = ['date', 'time', 'date-time'].includes(requiredFormat) &&
|
|
324
|
+
Object.prototype.toString.call(currentValue) === '[object Date]';
|
|
325
|
+
}
|
|
326
|
+
return xor(isValid, invert) ?
|
|
327
|
+
null : { 'format': { requiredFormat, currentValue } };
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* 'minimum' validator
|
|
332
|
+
*
|
|
333
|
+
* Requires a control's numeric value to be greater than or equal to
|
|
334
|
+
* a minimum amount.
|
|
335
|
+
*
|
|
336
|
+
* Any non-numeric value is also valid (according to the HTML forms spec,
|
|
337
|
+
* a non-numeric value doesn't have a minimum).
|
|
338
|
+
* https://www.w3.org/TR/html5/forms.html#attr-input-max
|
|
339
|
+
*
|
|
340
|
+
* // {number} minimum - minimum allowed value
|
|
341
|
+
* // {IValidatorFn}
|
|
342
|
+
*/
|
|
343
|
+
static minimum(minimumValue) {
|
|
344
|
+
if (!hasValue(minimumValue)) {
|
|
345
|
+
return JsonValidators.nullValidator;
|
|
346
|
+
}
|
|
347
|
+
return (control, invert = false) => {
|
|
348
|
+
if (isEmpty(control.value)) {
|
|
349
|
+
return null;
|
|
350
|
+
}
|
|
351
|
+
const currentValue = control.value;
|
|
352
|
+
const isValid = !isNumber(currentValue) || currentValue >= minimumValue;
|
|
353
|
+
return xor(isValid, invert) ?
|
|
354
|
+
null : { 'minimum': { minimumValue, currentValue } };
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* 'exclusiveMinimum' validator
|
|
359
|
+
*
|
|
360
|
+
* Requires a control's numeric value to be less than a maximum amount.
|
|
361
|
+
*
|
|
362
|
+
* Any non-numeric value is also valid (according to the HTML forms spec,
|
|
363
|
+
* a non-numeric value doesn't have a maximum).
|
|
364
|
+
* https://www.w3.org/TR/html5/forms.html#attr-input-max
|
|
365
|
+
*
|
|
366
|
+
* // {number} exclusiveMinimumValue - maximum allowed value
|
|
367
|
+
* // {IValidatorFn}
|
|
368
|
+
*/
|
|
369
|
+
static exclusiveMinimum(exclusiveMinimumValue) {
|
|
370
|
+
if (!hasValue(exclusiveMinimumValue)) {
|
|
371
|
+
return JsonValidators.nullValidator;
|
|
372
|
+
}
|
|
373
|
+
return (control, invert = false) => {
|
|
374
|
+
if (isEmpty(control.value)) {
|
|
375
|
+
return null;
|
|
376
|
+
}
|
|
377
|
+
const currentValue = control.value;
|
|
378
|
+
const isValid = !isNumber(currentValue) || +currentValue < exclusiveMinimumValue;
|
|
379
|
+
return xor(isValid, invert) ?
|
|
380
|
+
null : { 'exclusiveMinimum': { exclusiveMinimumValue, currentValue } };
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* 'maximum' validator
|
|
385
|
+
*
|
|
386
|
+
* Requires a control's numeric value to be less than or equal to
|
|
387
|
+
* a maximum amount.
|
|
388
|
+
*
|
|
389
|
+
* Any non-numeric value is also valid (according to the HTML forms spec,
|
|
390
|
+
* a non-numeric value doesn't have a maximum).
|
|
391
|
+
* https://www.w3.org/TR/html5/forms.html#attr-input-max
|
|
392
|
+
*
|
|
393
|
+
* // {number} maximumValue - maximum allowed value
|
|
394
|
+
* // {IValidatorFn}
|
|
395
|
+
*/
|
|
396
|
+
static maximum(maximumValue) {
|
|
397
|
+
if (!hasValue(maximumValue)) {
|
|
398
|
+
return JsonValidators.nullValidator;
|
|
399
|
+
}
|
|
400
|
+
return (control, invert = false) => {
|
|
401
|
+
if (isEmpty(control.value)) {
|
|
402
|
+
return null;
|
|
403
|
+
}
|
|
404
|
+
const currentValue = control.value;
|
|
405
|
+
const isValid = !isNumber(currentValue) || +currentValue <= maximumValue;
|
|
406
|
+
return xor(isValid, invert) ?
|
|
407
|
+
null : { 'maximum': { maximumValue, currentValue } };
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* 'exclusiveMaximum' validator
|
|
412
|
+
*
|
|
413
|
+
* Requires a control's numeric value to be less than a maximum amount.
|
|
414
|
+
*
|
|
415
|
+
* Any non-numeric value is also valid (according to the HTML forms spec,
|
|
416
|
+
* a non-numeric value doesn't have a maximum).
|
|
417
|
+
* https://www.w3.org/TR/html5/forms.html#attr-input-max
|
|
418
|
+
*
|
|
419
|
+
* // {number} exclusiveMaximumValue - maximum allowed value
|
|
420
|
+
* // {IValidatorFn}
|
|
421
|
+
*/
|
|
422
|
+
static exclusiveMaximum(exclusiveMaximumValue) {
|
|
423
|
+
if (!hasValue(exclusiveMaximumValue)) {
|
|
424
|
+
return JsonValidators.nullValidator;
|
|
425
|
+
}
|
|
426
|
+
return (control, invert = false) => {
|
|
427
|
+
if (isEmpty(control.value)) {
|
|
428
|
+
return null;
|
|
429
|
+
}
|
|
430
|
+
const currentValue = control.value;
|
|
431
|
+
const isValid = !isNumber(currentValue) || +currentValue < exclusiveMaximumValue;
|
|
432
|
+
return xor(isValid, invert) ?
|
|
433
|
+
null : { 'exclusiveMaximum': { exclusiveMaximumValue, currentValue } };
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* 'multipleOf' validator
|
|
438
|
+
*
|
|
439
|
+
* Requires a control to have a numeric value that is a multiple
|
|
440
|
+
* of a specified number.
|
|
441
|
+
*
|
|
442
|
+
* // {number} multipleOfValue - number value must be a multiple of
|
|
443
|
+
* // {IValidatorFn}
|
|
444
|
+
*/
|
|
445
|
+
static multipleOf(multipleOfValue) {
|
|
446
|
+
if (!hasValue(multipleOfValue)) {
|
|
447
|
+
return JsonValidators.nullValidator;
|
|
448
|
+
}
|
|
449
|
+
return (control, invert = false) => {
|
|
450
|
+
if (isEmpty(control.value)) {
|
|
451
|
+
return null;
|
|
452
|
+
}
|
|
453
|
+
const currentValue = control.value;
|
|
454
|
+
const isValid = isNumber(currentValue) &&
|
|
455
|
+
currentValue % multipleOfValue === 0;
|
|
456
|
+
return xor(isValid, invert) ?
|
|
457
|
+
null : { 'multipleOf': { multipleOfValue, currentValue } };
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* 'minProperties' validator
|
|
462
|
+
*
|
|
463
|
+
* Requires a form group to have a minimum number of properties (i.e. have
|
|
464
|
+
* values entered in a minimum number of controls within the group).
|
|
465
|
+
*
|
|
466
|
+
* // {number} minimumProperties - minimum number of properties allowed
|
|
467
|
+
* // {IValidatorFn}
|
|
468
|
+
*/
|
|
469
|
+
static minProperties(minimumProperties) {
|
|
470
|
+
if (!hasValue(minimumProperties)) {
|
|
471
|
+
return JsonValidators.nullValidator;
|
|
472
|
+
}
|
|
473
|
+
return (control, invert = false) => {
|
|
474
|
+
if (isEmpty(control.value)) {
|
|
475
|
+
return null;
|
|
476
|
+
}
|
|
477
|
+
const currentProperties = Object.keys(control.value).length || 0;
|
|
478
|
+
const isValid = currentProperties >= minimumProperties;
|
|
479
|
+
return xor(isValid, invert) ?
|
|
480
|
+
null : { 'minProperties': { minimumProperties, currentProperties } };
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* 'maxProperties' validator
|
|
485
|
+
*
|
|
486
|
+
* Requires a form group to have a maximum number of properties (i.e. have
|
|
487
|
+
* values entered in a maximum number of controls within the group).
|
|
488
|
+
*
|
|
489
|
+
* Note: Has no effect if the form group does not contain more than the
|
|
490
|
+
* maximum number of controls.
|
|
491
|
+
*
|
|
492
|
+
* // {number} maximumProperties - maximum number of properties allowed
|
|
493
|
+
* // {IValidatorFn}
|
|
494
|
+
*/
|
|
495
|
+
static maxProperties(maximumProperties) {
|
|
496
|
+
if (!hasValue(maximumProperties)) {
|
|
497
|
+
return JsonValidators.nullValidator;
|
|
498
|
+
}
|
|
499
|
+
return (control, invert = false) => {
|
|
500
|
+
const currentProperties = Object.keys(control.value).length || 0;
|
|
501
|
+
const isValid = currentProperties <= maximumProperties;
|
|
502
|
+
return xor(isValid, invert) ?
|
|
503
|
+
null : { 'maxProperties': { maximumProperties, currentProperties } };
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
/**
|
|
507
|
+
* 'dependencies' validator
|
|
508
|
+
*
|
|
509
|
+
* Requires the controls in a form group to meet additional validation
|
|
510
|
+
* criteria, depending on the values of other controls in the group.
|
|
511
|
+
*
|
|
512
|
+
* Examples:
|
|
513
|
+
* https://spacetelescope.github.io/understanding-json-schema/reference/object.html#dependencies
|
|
514
|
+
*
|
|
515
|
+
* // {any} dependencies - required dependencies
|
|
516
|
+
* // {IValidatorFn}
|
|
517
|
+
*/
|
|
518
|
+
static dependencies(dependencies) {
|
|
519
|
+
if (getType(dependencies) !== 'object' || isEmpty(dependencies)) {
|
|
520
|
+
return JsonValidators.nullValidator;
|
|
521
|
+
}
|
|
522
|
+
return (control, invert = false) => {
|
|
523
|
+
if (isEmpty(control.value)) {
|
|
524
|
+
return null;
|
|
525
|
+
}
|
|
526
|
+
const allErrors = _mergeObjects(forEachCopy(dependencies, (value, requiringField) => {
|
|
527
|
+
if (!hasValue(control.value[requiringField])) {
|
|
528
|
+
return null;
|
|
529
|
+
}
|
|
530
|
+
let requiringFieldErrors = {};
|
|
531
|
+
let requiredFields;
|
|
532
|
+
let properties = {};
|
|
533
|
+
if (getType(dependencies[requiringField]) === 'array') {
|
|
534
|
+
requiredFields = dependencies[requiringField];
|
|
535
|
+
}
|
|
536
|
+
else if (getType(dependencies[requiringField]) === 'object') {
|
|
537
|
+
requiredFields = dependencies[requiringField]['required'] || [];
|
|
538
|
+
properties = dependencies[requiringField]['properties'] || {};
|
|
539
|
+
}
|
|
540
|
+
// Validate property dependencies
|
|
541
|
+
for (const requiredField of requiredFields) {
|
|
542
|
+
if (xor(!hasValue(control.value[requiredField]), invert)) {
|
|
543
|
+
requiringFieldErrors[requiredField] = { 'required': true };
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
// Validate schema dependencies
|
|
547
|
+
requiringFieldErrors = _mergeObjects(requiringFieldErrors, forEachCopy(properties, (requirements, requiredField) => {
|
|
548
|
+
const requiredFieldErrors = _mergeObjects(forEachCopy(requirements, (requirement, parameter) => {
|
|
549
|
+
let validator = null;
|
|
550
|
+
if (requirement === 'maximum' || requirement === 'minimum') {
|
|
551
|
+
const exclusive = !!requirements['exclusiveM' + requirement.slice(1)];
|
|
552
|
+
validator = JsonValidators[requirement](parameter, exclusive);
|
|
553
|
+
}
|
|
554
|
+
else if (typeof JsonValidators[requirement] === 'function') {
|
|
555
|
+
validator = JsonValidators[requirement](parameter);
|
|
556
|
+
}
|
|
557
|
+
return !isDefined(validator) ?
|
|
558
|
+
null : validator(control.value[requiredField]);
|
|
559
|
+
}));
|
|
560
|
+
return isEmpty(requiredFieldErrors) ?
|
|
561
|
+
null : { [requiredField]: requiredFieldErrors };
|
|
562
|
+
}));
|
|
563
|
+
return isEmpty(requiringFieldErrors) ?
|
|
564
|
+
null : { [requiringField]: requiringFieldErrors };
|
|
565
|
+
}));
|
|
566
|
+
return isEmpty(allErrors) ? null : allErrors;
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* 'minItems' validator
|
|
571
|
+
*
|
|
572
|
+
* Requires a form array to have a minimum number of values.
|
|
573
|
+
*
|
|
574
|
+
* // {number} minimumItems - minimum number of items allowed
|
|
575
|
+
* // {IValidatorFn}
|
|
576
|
+
*/
|
|
577
|
+
static minItems(minimumItems) {
|
|
578
|
+
if (!hasValue(minimumItems)) {
|
|
579
|
+
return JsonValidators.nullValidator;
|
|
580
|
+
}
|
|
581
|
+
return (control, invert = false) => {
|
|
582
|
+
if (isEmpty(control.value)) {
|
|
583
|
+
return null;
|
|
584
|
+
}
|
|
585
|
+
const currentItems = isArray(control.value) ? control.value.length : 0;
|
|
586
|
+
const isValid = currentItems >= minimumItems;
|
|
587
|
+
return xor(isValid, invert) ?
|
|
588
|
+
null : { 'minItems': { minimumItems, currentItems } };
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
/**
|
|
592
|
+
* 'maxItems' validator
|
|
593
|
+
*
|
|
594
|
+
* Requires a form array to have a maximum number of values.
|
|
595
|
+
*
|
|
596
|
+
* // {number} maximumItems - maximum number of items allowed
|
|
597
|
+
* // {IValidatorFn}
|
|
598
|
+
*/
|
|
599
|
+
static maxItems(maximumItems) {
|
|
600
|
+
if (!hasValue(maximumItems)) {
|
|
601
|
+
return JsonValidators.nullValidator;
|
|
602
|
+
}
|
|
603
|
+
return (control, invert = false) => {
|
|
604
|
+
const currentItems = isArray(control.value) ? control.value.length : 0;
|
|
605
|
+
const isValid = currentItems <= maximumItems;
|
|
606
|
+
return xor(isValid, invert) ?
|
|
607
|
+
null : { 'maxItems': { maximumItems, currentItems } };
|
|
608
|
+
};
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* 'uniqueItems' validator
|
|
612
|
+
*
|
|
613
|
+
* Requires values in a form array to be unique.
|
|
614
|
+
*
|
|
615
|
+
* // {boolean = true} unique? - true to validate, false to disable
|
|
616
|
+
* // {IValidatorFn}
|
|
617
|
+
*/
|
|
618
|
+
static uniqueItems(unique = true) {
|
|
619
|
+
if (!unique) {
|
|
620
|
+
return JsonValidators.nullValidator;
|
|
621
|
+
}
|
|
622
|
+
return (control, invert = false) => {
|
|
623
|
+
if (isEmpty(control.value)) {
|
|
624
|
+
return null;
|
|
625
|
+
}
|
|
626
|
+
const sorted = control.value.slice().sort();
|
|
627
|
+
const duplicateItems = [];
|
|
628
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
629
|
+
if (sorted[i - 1] === sorted[i] && duplicateItems.includes(sorted[i])) {
|
|
630
|
+
duplicateItems.push(sorted[i]);
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
const isValid = !duplicateItems.length;
|
|
634
|
+
return xor(isValid, invert) ?
|
|
635
|
+
null : { 'uniqueItems': { duplicateItems } };
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
/**
|
|
639
|
+
* 'contains' validator
|
|
640
|
+
*
|
|
641
|
+
* TODO: Complete this validator
|
|
642
|
+
*
|
|
643
|
+
* Requires values in a form array to be unique.
|
|
644
|
+
*
|
|
645
|
+
* // {boolean = true} unique? - true to validate, false to disable
|
|
646
|
+
* // {IValidatorFn}
|
|
647
|
+
*/
|
|
648
|
+
static contains(requiredItem = true) {
|
|
649
|
+
if (!requiredItem) {
|
|
650
|
+
return JsonValidators.nullValidator;
|
|
651
|
+
}
|
|
652
|
+
return (control, invert = false) => {
|
|
653
|
+
if (isEmpty(control.value) || !isArray(control.value)) {
|
|
654
|
+
return null;
|
|
655
|
+
}
|
|
656
|
+
const currentItems = control.value;
|
|
657
|
+
// const isValid = currentItems.some(item =>
|
|
658
|
+
//
|
|
659
|
+
// );
|
|
660
|
+
const isValid = true;
|
|
661
|
+
return xor(isValid, invert) ?
|
|
662
|
+
null : { 'contains': { requiredItem, currentItems } };
|
|
663
|
+
};
|
|
664
|
+
}
|
|
665
|
+
/**
|
|
666
|
+
* No-op validator. Included for backward compatibility.
|
|
667
|
+
*/
|
|
668
|
+
static nullValidator(control) {
|
|
669
|
+
return null;
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
* Validator transformation functions:
|
|
673
|
+
* composeAnyOf, composeOneOf, composeAllOf, composeNot,
|
|
674
|
+
* compose, composeAsync
|
|
675
|
+
*
|
|
676
|
+
* TODO: Add composeAnyOfAsync, composeOneOfAsync,
|
|
677
|
+
* composeAllOfAsync, composeNotAsync
|
|
678
|
+
*/
|
|
679
|
+
/**
|
|
680
|
+
* 'composeAnyOf' validator combination function
|
|
681
|
+
*
|
|
682
|
+
* Accepts an array of validators and returns a single validator that
|
|
683
|
+
* evaluates to valid if any one or more of the submitted validators are
|
|
684
|
+
* valid. If every validator is invalid, it returns combined errors from
|
|
685
|
+
* all validators.
|
|
686
|
+
*
|
|
687
|
+
* // {IValidatorFn[]} validators - array of validators to combine
|
|
688
|
+
* // {IValidatorFn} - single combined validator function
|
|
689
|
+
*/
|
|
690
|
+
static composeAnyOf(validators) {
|
|
691
|
+
if (!validators) {
|
|
692
|
+
return null;
|
|
693
|
+
}
|
|
694
|
+
const presentValidators = validators.filter(isDefined);
|
|
695
|
+
if (presentValidators.length === 0) {
|
|
696
|
+
return null;
|
|
697
|
+
}
|
|
698
|
+
return (control, invert = false) => {
|
|
699
|
+
const arrayOfErrors = _executeValidators(control, presentValidators, invert).filter(isDefined);
|
|
700
|
+
const isValid = validators.length > arrayOfErrors.length;
|
|
701
|
+
return xor(isValid, invert) ?
|
|
702
|
+
null : _mergeObjects(...arrayOfErrors, { 'anyOf': !invert });
|
|
703
|
+
};
|
|
704
|
+
}
|
|
705
|
+
/**
|
|
706
|
+
* 'composeOneOf' validator combination function
|
|
707
|
+
*
|
|
708
|
+
* Accepts an array of validators and returns a single validator that
|
|
709
|
+
* evaluates to valid only if exactly one of the submitted validators
|
|
710
|
+
* is valid. Otherwise returns combined information from all validators,
|
|
711
|
+
* both valid and invalid.
|
|
712
|
+
*
|
|
713
|
+
* // {IValidatorFn[]} validators - array of validators to combine
|
|
714
|
+
* // {IValidatorFn} - single combined validator function
|
|
715
|
+
*/
|
|
716
|
+
static composeOneOf(validators) {
|
|
717
|
+
if (!validators) {
|
|
718
|
+
return null;
|
|
719
|
+
}
|
|
720
|
+
const presentValidators = validators.filter(isDefined);
|
|
721
|
+
if (presentValidators.length === 0) {
|
|
722
|
+
return null;
|
|
723
|
+
}
|
|
724
|
+
return (control, invert = false) => {
|
|
725
|
+
const arrayOfErrors = _executeValidators(control, presentValidators);
|
|
726
|
+
const validControls = validators.length - arrayOfErrors.filter(isDefined).length;
|
|
727
|
+
const isValid = validControls === 1;
|
|
728
|
+
if (xor(isValid, invert)) {
|
|
729
|
+
return null;
|
|
730
|
+
}
|
|
731
|
+
const arrayOfValids = _executeValidators(control, presentValidators, invert);
|
|
732
|
+
return _mergeObjects(...arrayOfErrors, ...arrayOfValids, { 'oneOf': !invert });
|
|
733
|
+
};
|
|
734
|
+
}
|
|
735
|
+
/**
|
|
736
|
+
* 'composeAllOf' validator combination function
|
|
737
|
+
*
|
|
738
|
+
* Accepts an array of validators and returns a single validator that
|
|
739
|
+
* evaluates to valid only if all the submitted validators are individually
|
|
740
|
+
* valid. Otherwise it returns combined errors from all invalid validators.
|
|
741
|
+
*
|
|
742
|
+
* // {IValidatorFn[]} validators - array of validators to combine
|
|
743
|
+
* // {IValidatorFn} - single combined validator function
|
|
744
|
+
*/
|
|
745
|
+
static composeAllOf(validators) {
|
|
746
|
+
if (!validators) {
|
|
747
|
+
return null;
|
|
748
|
+
}
|
|
749
|
+
const presentValidators = validators.filter(isDefined);
|
|
750
|
+
if (presentValidators.length === 0) {
|
|
751
|
+
return null;
|
|
752
|
+
}
|
|
753
|
+
return (control, invert = false) => {
|
|
754
|
+
const combinedErrors = _mergeErrors(_executeValidators(control, presentValidators, invert));
|
|
755
|
+
const isValid = combinedErrors === null;
|
|
756
|
+
return (xor(isValid, invert)) ?
|
|
757
|
+
null : _mergeObjects(combinedErrors, { 'allOf': !invert });
|
|
758
|
+
};
|
|
759
|
+
}
|
|
760
|
+
/**
|
|
761
|
+
* 'composeNot' validator inversion function
|
|
762
|
+
*
|
|
763
|
+
* Accepts a single validator function and inverts its result.
|
|
764
|
+
* Returns valid if the submitted validator is invalid, and
|
|
765
|
+
* returns invalid if the submitted validator is valid.
|
|
766
|
+
* (Note: this function can itself be inverted
|
|
767
|
+
* - e.g. composeNot(composeNot(validator)) -
|
|
768
|
+
* but this can be confusing and is therefore not recommended.)
|
|
769
|
+
*
|
|
770
|
+
* // {IValidatorFn[]} validators - validator(s) to invert
|
|
771
|
+
* // {IValidatorFn} - new validator function that returns opposite result
|
|
772
|
+
*/
|
|
773
|
+
static composeNot(validator) {
|
|
774
|
+
if (!validator) {
|
|
775
|
+
return null;
|
|
776
|
+
}
|
|
777
|
+
return (control, invert = false) => {
|
|
778
|
+
if (isEmpty(control.value)) {
|
|
779
|
+
return null;
|
|
780
|
+
}
|
|
781
|
+
const error = validator(control, !invert);
|
|
782
|
+
const isValid = error === null;
|
|
783
|
+
return (xor(isValid, invert)) ?
|
|
784
|
+
null : _mergeObjects(error, { 'not': !invert });
|
|
785
|
+
};
|
|
786
|
+
}
|
|
787
|
+
/**
|
|
788
|
+
* 'compose' validator combination function
|
|
789
|
+
*
|
|
790
|
+
* // {IValidatorFn[]} validators - array of validators to combine
|
|
791
|
+
* // {IValidatorFn} - single combined validator function
|
|
792
|
+
*/
|
|
793
|
+
static compose(validators) {
|
|
794
|
+
if (!validators) {
|
|
795
|
+
return null;
|
|
796
|
+
}
|
|
797
|
+
const presentValidators = validators.filter(isDefined);
|
|
798
|
+
if (presentValidators.length === 0) {
|
|
799
|
+
return null;
|
|
800
|
+
}
|
|
801
|
+
return (control, invert = false) => _mergeErrors(_executeValidators(control, presentValidators, invert));
|
|
802
|
+
}
|
|
803
|
+
/**
|
|
804
|
+
* 'composeAsync' async validator combination function
|
|
805
|
+
*
|
|
806
|
+
* // {AsyncIValidatorFn[]} async validators - array of async validators
|
|
807
|
+
* // {AsyncIValidatorFn} - single combined async validator function
|
|
808
|
+
*/
|
|
809
|
+
static composeAsync(validators) {
|
|
810
|
+
if (!validators) {
|
|
811
|
+
return null;
|
|
812
|
+
}
|
|
813
|
+
const presentValidators = validators.filter(isDefined);
|
|
814
|
+
if (presentValidators.length === 0) {
|
|
815
|
+
return null;
|
|
816
|
+
}
|
|
817
|
+
return (control) => {
|
|
818
|
+
const observables = _executeAsyncValidators(control, presentValidators).map(toObservable);
|
|
819
|
+
return map.call(forkJoin(observables), _mergeErrors);
|
|
820
|
+
};
|
|
821
|
+
}
|
|
822
|
+
// Additional angular validators (not used by Angualr JSON Schema Form)
|
|
823
|
+
// From https://github.com/angular/angular/blob/master/packages/forms/src/validators.ts
|
|
824
|
+
/**
|
|
825
|
+
* Validator that requires controls to have a value greater than a number.
|
|
826
|
+
*/
|
|
827
|
+
static min(min) {
|
|
828
|
+
if (!hasValue(min)) {
|
|
829
|
+
return JsonValidators.nullValidator;
|
|
830
|
+
}
|
|
831
|
+
return (control) => {
|
|
832
|
+
// don't validate empty values to allow optional controls
|
|
833
|
+
if (isEmpty(control.value) || isEmpty(min)) {
|
|
834
|
+
return null;
|
|
835
|
+
}
|
|
836
|
+
const value = parseFloat(control.value);
|
|
837
|
+
const actual = control.value;
|
|
838
|
+
// Controls with NaN values after parsing should be treated as not having a
|
|
839
|
+
// minimum, per the HTML forms spec: https://www.w3.org/TR/html5/forms.html#attr-input-min
|
|
840
|
+
return isNaN(value) || value >= min ? null : { 'min': { min, actual } };
|
|
841
|
+
};
|
|
842
|
+
}
|
|
843
|
+
/**
|
|
844
|
+
* Validator that requires controls to have a value less than a number.
|
|
845
|
+
*/
|
|
846
|
+
static max(max) {
|
|
847
|
+
if (!hasValue(max)) {
|
|
848
|
+
return JsonValidators.nullValidator;
|
|
849
|
+
}
|
|
850
|
+
return (control) => {
|
|
851
|
+
// don't validate empty values to allow optional controls
|
|
852
|
+
if (isEmpty(control.value) || isEmpty(max)) {
|
|
853
|
+
return null;
|
|
854
|
+
}
|
|
855
|
+
const value = parseFloat(control.value);
|
|
856
|
+
const actual = control.value;
|
|
857
|
+
// Controls with NaN values after parsing should be treated as not having a
|
|
858
|
+
// maximum, per the HTML forms spec: https://www.w3.org/TR/html5/forms.html#attr-input-max
|
|
859
|
+
return isNaN(value) || value <= max ? null : { 'max': { max, actual } };
|
|
860
|
+
};
|
|
861
|
+
}
|
|
862
|
+
/**
|
|
863
|
+
* Validator that requires control value to be true.
|
|
864
|
+
*/
|
|
865
|
+
static requiredTrue(control) {
|
|
866
|
+
if (!control) {
|
|
867
|
+
return JsonValidators.nullValidator;
|
|
868
|
+
}
|
|
869
|
+
return control.value === true ? null : { 'required': true };
|
|
870
|
+
}
|
|
871
|
+
/**
|
|
872
|
+
* Validator that performs email validation.
|
|
873
|
+
*/
|
|
874
|
+
static email(control) {
|
|
875
|
+
if (!control) {
|
|
876
|
+
return JsonValidators.nullValidator;
|
|
877
|
+
}
|
|
878
|
+
const EMAIL_REGEXP =
|
|
879
|
+
// tslint:disable-next-line:max-line-length
|
|
880
|
+
/^(?=.{1,254}$)(?=.{1,64}@)[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+(\.[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$/;
|
|
881
|
+
return EMAIL_REGEXP.test(control.value) ? null : { 'email': true };
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoianNvbi52YWxpZGF0b3JzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmctZm9ybXdvcmtzLWNvcmUvc3JjL2xpYi9zaGFyZWQvanNvbi52YWxpZGF0b3JzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sT0FBTyxNQUFNLGdCQUFnQixDQUFDO0FBQ3JDLE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIsa0JBQWtCLEVBQ2xCLFlBQVksRUFDWixhQUFhLEVBRWIsT0FBTyxFQUNQLFFBQVEsRUFDUixPQUFPLEVBQ1AsU0FBUyxFQUNULFNBQVMsRUFDVCxPQUFPLEVBQ1AsUUFBUSxFQUNSLFFBQVEsRUFDUixNQUFNLEVBR04sZ0JBQWdCLEVBQ2hCLFlBQVksRUFDWixHQUFHLEVBQ0YsTUFBTSx1QkFBdUIsQ0FBQztBQUVqQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDbEQsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNoQyxPQUFPLEVBQXlCLHFCQUFxQixFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDeEYsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBSXJDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0E4RUc7QUFDSCxNQUFNLE9BQU8sY0FBYztJQXNDekIsTUFBTSxDQUFDLFFBQVEsQ0FBQyxLQUErQjtRQUM3QyxJQUFJLEtBQUssS0FBSyxTQUFTLEVBQUU7WUFBRSxLQUFLLEdBQUcsSUFBSSxDQUFDO1NBQUU7UUFDMUMsUUFBUSxLQUFLLEVBQUU7WUFDYixLQUFLLElBQUksRUFBRSxtREFBbUQ7Z0JBQzVELE9BQU8sQ0FBQyxPQUF3QixFQUFFLE1BQU0sR0FBRyxLQUFLLEVBQXlCLEVBQUU7b0JBQ3pFLElBQUksTUFBTSxFQUFFO3dCQUFFLE9BQU8sSUFBSSxDQUFDO3FCQUFFLENBQUMsdUNBQXVDO29CQUNwRSxPQUFPLFFBQVEsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLENBQUM7Z0JBQy9ELENBQUMsQ0FBQztZQUNKLEtBQUssS0FBSyxFQUFFLDREQUE0RDtnQkFDdEUsT0FBTyxjQUFjLENBQUMsYUFBYSxDQUFDO1lBQ3RDLFNBQVMsNEJBQTRCO2dCQUNuQyxPQUFPLFFBQVEsQ0FBbUIsS0FBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxDQUFDO1NBQ2pGO0lBQ0gsQ0FBQztJQUVEOzs7Ozs7Ozs7O09BVUc7SUFDSCxNQUFNLENBQUMsSUFBSSxDQUFDLFlBQXVEO1FBQ2pFLElBQUksQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDLEVBQUU7WUFBRSxPQUFPLGNBQWMsQ0FBQyxhQUFhLENBQUM7U0FBRTtRQUNyRSxPQUFPLENBQUMsT0FBd0IsRUFBRSxNQUFNLEdBQUcsS0FBSyxFQUF5QixFQUFFO1lBQ3pFLElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRTtnQkFBRSxPQUFPLElBQUksQ0FBQzthQUFFO1lBQzVDLE1BQU0sWUFBWSxHQUFRLE9BQU8sQ0FBQyxLQUFLLENBQUM7WUFDeEMsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUM7Z0JBQ2IsWUFBYSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxZQUFZLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUNoRixNQUFNLENBQUMsWUFBWSxFQUF1QixZQUFZLENBQUMsQ0FBQztZQUMxRCxPQUFPLEdBQUcsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQztnQkFDM0IsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsRUFBRSxDQUFDO1FBQ3RELENBQUMsQ0FBQztJQUNKLENBQUM7SUFFRDs7Ozs7Ozs7OztPQVVHO0lBQ0gsTUFBTSxDQUFDLElBQUksQ0FBQyxhQUFvQjtRQUM5QixJQUFJLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxFQUFFO1lBQUUsT0FBTyxjQUFjLENBQUMsYUFBYSxDQUFDO1NBQUU7UUFDckUsT0FBTyxDQUFDLE9BQXdCLEVBQUUsTUFBTSxHQUFHLEtBQUssRUFBeUIsRUFBRTtZQUN6RSxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUU7Z0JBQUUsT0FBTyxJQUFJLENBQUM7YUFBRTtZQUM1QyxNQUFNLFlBQVksR0FBUSxPQUFPLENBQUMsS0FBSyxDQUFDO1lBQ3hDLE1BQU0sVUFBVSxHQUFHLENBQUMsU0FBUyxFQUFFLFVBQVUsRUFBRSxFQUFFLENBQzNDLFNBQVMsS0FBSyxVQUFVO2dCQUN4QixDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFVBQVUsS0FBSyxDQUFDLFNBQVMsQ0FBQztnQkFDbkQsQ0FBQyxTQUFTLENBQUMsU0FBUyxFQUFFLFFBQVEsQ0FBQztvQkFDN0IsZ0JBQWdCLENBQUMsVUFBVSxFQUFFLFNBQVMsQ0FBQyxLQUFLLFNBQVMsQ0FBQztnQkFDeEQsQ0FBQyxTQUFTLEtBQUssSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxDQUFDO2dCQUM3QyxPQUFPLENBQUMsU0FBUyxFQUFFLFVBQVUsQ0FBQyxDQUFDO1lBQ2pDLE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDO2dCQUNyQyxZQUFZLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUM5RCxVQUFVLENBQUMsU0FBUyxFQUFFLFVBQVUsQ0FBQyxDQUNsQyxDQUFDLENBQUMsQ0FBQztnQkFDSixhQUFhLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLFNBQVMsRUFBRSxZQUFZLENBQUMsQ0FBQyxDQUFDO1lBQ3ZFLE9BQU8sR0FBRyxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO2dCQUMzQixJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxFQUFFLEVBQUUsYUFBYSxFQUFFLFlBQVksRUFBRSxFQUFFLENBQUM7UUFDdkQsQ0FBQyxDQUFDO0lBQ0osQ0FBQztJQUVEOzs7Ozs7Ozs7Ozs7T0FZRztJQUNILE1BQU0sQ0FBQyxLQUFLLENBQUMsYUFBa0I7UUFDN0IsSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsRUFBRTtZQUFFLE9BQU8sY0FBYyxDQUFDLGFBQWEsQ0FBQztTQUFFO1FBQ3RFLE9BQU8sQ0FBQyxPQUF3QixFQUFFLE1BQU0sR0FBRyxLQUFLLEVBQXlCLEVBQUU7WUFDekUsSUFBSSxPQUFPLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFO2dCQUFFLE9BQU8sSUFBSSxDQUFDO2FBQUU7WUFDNUMsTUFBTSxZQUFZLEdBQVEsT0FBTyxDQUFDLEtBQUssQ0FBQztZQUN4QyxNQUFNLFVBQVUsR0FBRyxDQUFDLFVBQVUsRUFBRSxVQUFVLEVBQUUsRUFBRSxDQUM1QyxVQUFVLEtBQUssVUFBVTtnQkFDekIsUUFBUSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsVUFBVSxLQUFLLENBQUMsVUFBVTtnQkFDbkQsU0FBUyxDQUFDLFVBQVUsRUFBRSxRQUFRLENBQUM7b0JBQzdCLGdCQUFnQixDQUFDLFVBQVUsRUFBRSxTQUFTLENBQUMsS0FBSyxVQUFVO2dCQUN4RCxVQUFVLEtBQUssSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQy9DLE1BQU0sT0FBTyxHQUFHLFVBQVUsQ0FBQyxhQUFhLEVBQUUsWUFBWSxDQUFDLENBQUM7WUFDeEQsT0FBTyxHQUFHLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUM7Z0JBQzNCLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxPQUFPLEVBQUUsRUFBRSxhQUFhLEVBQUUsWUFBWSxFQUFFLEVBQUUsQ0FBQztRQUN4RCxDQUFDLENBQUM7SUFDSixDQUFDO0lBRUQ7Ozs7Ozs7O09BUUc7SUFDSCxNQUFNLENBQUMsU0FBUyxDQUFDLGFBQXFCO1FBQ3BDLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLEVBQUU7WUFBRSxPQUFPLGNBQWMsQ0FBQyxhQUFhLENBQUM7U0FBRTtRQUN0RSxPQUFPLENBQUMsT0FBd0IsRUFBRSxNQUFNLEdBQUcsS0FBSyxFQUF5QixFQUFFO1lBQ3pFLElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRTtnQkFBRSxPQUFPLElBQUksQ0FBQzthQUFFO1lBQzVDLE1BQU0sYUFBYSxHQUFHLFFBQVEsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDekUsTUFBTSxPQUFPLEdBQUcsYUFBYSxJQUFJLGFBQWEsQ0FBQztZQUMvQyxPQUFPLEdBQUcsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQztnQkFDM0IsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLFdBQVcsRUFBRSxFQUFFLGFBQWEsRUFBRSxhQUFhLEVBQUUsRUFBRSxDQUFDO1FBQzdELENBQUMsQ0FBQztJQUNKLENBQUM7SUFFRDs7Ozs7Ozs7T0FRRztJQUNILE1BQU0sQ0FBQyxTQUFTLENBQUMsYUFBcUI7UUFDcEMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsRUFBRTtZQUFFLE9BQU8sY0FBYyxDQUFDLGFBQWEsQ0FBQztTQUFFO1FBQ3RFLE9BQU8sQ0FBQyxPQUF3QixFQUFFLE1BQU0sR0FBRyxLQUFLLEVBQXlCLEVBQUU7WUFDekUsTUFBTSxhQUFhLEdBQUcsUUFBUSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUN6RSxNQUFNLE9BQU8sR0FBRyxhQUFhLElBQUksYUFBYSxDQUFDO1lBQy9DLE9BQU8sR0FBRyxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO2dCQUMzQixJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsV0FBVyxFQUFFLEVBQUUsYUFBYSxFQUFFLGFBQWEsRUFBRSxFQUFFLENBQUM7UUFDN0QsQ0FBQyxDQUFDO0lBQ0osQ0FBQztJQUVEOzs7Ozs7Ozs7Ozs7Ozs7OztPQWlCRztJQUNILE1BQU0sQ0FBQyxPQUFPLENBQUMsT0FBc0IsRUFBRSxXQUFXLEdBQUcsS0FBSztRQUN4RCxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxFQUFFO1lBQUUsT0FBTyxjQUFjLENBQUMsYUFBYSxDQUFDO1NBQUU7UUFDaEUsT0FBTyxDQUFDLE9BQXdCLEVBQUUsTUFBTSxHQUFHLEtBQUssRUFBeUIsRUFBRTtZQUN6RSxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUU7Z0JBQUUsT0FBTyxJQUFJLENBQUM7YUFBRTtZQUM1QyxJQUFJLEtBQWEsQ0FBQztZQUNsQixJQUFJLGVBQXVCLENBQUM7WUFDNUIsSUFBSSxPQUFPLE9BQU8sS0FBSyxRQUFRLEVBQUU7Z0JBQy9CLGVBQWUsR0FBRyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLE9BQU8sR0FBRyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUM7Z0JBQzNELEtBQUssR0FBRyxJQUFJLE1BQU0sQ0FBQyxlQUFlLENBQUMsQ0FBQzthQUNyQztpQkFBTTtnQkFDTCxlQUFlLEdBQUcsT0FBTyxDQUFDLFFBQVEsRUFBRSxDQUFDO2dCQUNyQyxLQUFLLEdBQUcsT0FBTyxDQUFDO2FBQ2pCO1lBQ0QsTUFBTSxZQUFZLEdBQVcsT0FBTyxDQUFDLEtBQUssQ0FBQztZQUMzQyxNQUFNLE9BQU8sR0FBRyxRQUFRLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQztZQUMxRSxPQUFPLEdBQUcsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQztnQkFDM0IsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLFNBQVMsRUFBRSxFQUFFLGVBQWUsRUFBRSxZQUFZLEVBQUUsRUFBRSxDQUFDO1FBQzVELENBQUMsQ0FBQztJQUNKLENBQUM7SUFFRDs7Ozs7Ozs7Ozs7Ozs7O09BZUc7SUFDSCxNQUFNLENBQUMsTUFBTSxDQUFDLGNBQXFDO1FBQ2pELElBQUksQ0FBQyxRQUFRLENBQUMsY0FBYyxDQUFDLEVBQUU7WUFBRSxPQUFPLGNBQWMsQ0FBQyxhQUFhLENBQUM7U0FBRTtRQUN2RSxPQUFPLENBQUMsT0FBd0IsRUFBRSxNQUFNLEdBQUcsS0FBSyxFQUF5QixFQUFFO1lBQ3pFLElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRTtnQkFBRSxPQUFPLElBQUksQ0FBQzthQUFFO1lBQzVDLElBQUksT0FBZ0IsQ0FBQztZQUNyQixNQUFNLFlBQVksR0FBZ0IsT0FBTyxDQUFDLEtBQUssQ0FBQztZQUNoRCxJQUFJLFFBQVEsQ0FBQyxZQUFZLENBQUMsRUFBRTtnQkFDMUIsTUFBTSxVQUFVLEdBQW9CLHFCQUFxQixDQUFDLGNBQWMsQ0FBQyxDQUFDO2dCQUMxRSxJQUFJLE9BQU8sVUFBVSxLQUFLLFFBQVEsRUFBRTtvQkFDbEMsT0FBTyxHQUFZLFVBQVcsQ0FBQyxJQUFJLENBQVMsWUFBWSxDQUFDLENBQUM7aUJBQzNEO3FCQUFNLElBQUksT0FBTyxVQUFVLEtBQUssVUFBVSxFQUFFO29CQUMzQyxPQUFPLEdBQWMsVUFBVyxDQUFTLFlBQVksQ0FBQyxDQUFDO2lCQUN4RDtxQkFBTTtvQkFDTCxPQUFPLENBQUMsS0FBSyxDQUFDLDRCQUE0QixjQUFjLCtCQUErQixDQUFDLENBQUM7b0JBQ3pGLE9BQU8sR0FBRyxJQUFJLENBQUM7aUJBQ2hCO2FBQ0Y7aUJBQU07Z0JBQ0wsZ0NBQWdDO2dCQUNoQyxPQUFPLEdBQUcsQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLFdBQVcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxjQUFjLENBQUM7b0JBQzlELE1BQU0sQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxlQUFlLENBQUM7YUFDcEU7WUFDRCxPQUFPLEdBQUcsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQztnQkFDM0IsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLFFBQVEsRUFBRSxFQUFFLGNBQWMsRUFBRSxZQUFZLEVBQUUsRUFBRSxDQUFDO1FBQzFELENBQUMsQ0FBQztJQUNKLENBQUM7SUFFRDs7Ozs7Ozs7Ozs7O09BWUc7SUFDSCxNQUFNLENBQUMsT0FBTyxDQUFDLFlBQW9CO1FBQ2pDLElBQUksQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDLEVBQUU7WUFBRSxPQUFPLGNBQWMsQ0FBQyxhQUFhLENBQUM7U0FBRTtRQUNyRSxPQUFPLENBQUMsT0FBd0IsRUFBRSxNQUFNLEdBQUcsS0FBSyxFQUF5QixFQUFFO1lBQ3pFLElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRTtnQkFBRSxPQUFPLElBQUksQ0FBQzthQUFFO1lBQzVDLE1BQU0sWUFBWSxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUM7WUFDbkMsTUFBTSxPQUFPLEdBQUcsQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDLElBQUksWUFBWSxJQUFJLFlBQVksQ0FBQztZQUN4RSxPQUFPLEdBQUcsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQztnQkFDM0IsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLFNBQVMsRUFBRSxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsRUFBRSxDQUFDO1FBQ3pELENBQUMsQ0FBQztJQUNKLENBQUM7SUFFRDs7Ozs7Ozs7Ozs7T0FXRztJQUNILE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxxQkFBNkI7UUFDbkQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxxQkFBcUIsQ0FBQyxFQUFFO1lBQUUsT0FBTyxjQUFjLENBQUMsYUFBYSxDQUFDO1NBQUU7UUFDOUUsT0FBTyxDQUFDLE9BQXdCLEVBQUUsTUFBTSxHQUFHLEtBQUssRUFBeUIsRUFBRTtZQUN6RSxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUU7Z0JBQUUsT0FBTyxJQUFJLENBQUM7YUFBRTtZQUM1QyxNQUFNLFlBQVksR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDO1lBQ25DLE1BQU0sT0FBTyxHQUFHLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsWUFBWSxHQUFHLHFCQUFxQixDQUFDO1lBQ2pGLE9BQU8sR0FBRyxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO2dCQUMzQixJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsa0JBQWtCLEVBQUUsRUFBRSxxQkFBcUIsRUFBRSxZQUFZLEVBQUUsRUFBRSxDQUFDO1FBQzNFLENBQUMsQ0FBQztJQUNKLENBQUM7SUFFRDs7Ozs7Ozs7Ozs7O09BWUc7SUFDSCxNQUFNLENBQUMsT0FBTyxDQUFDLFlBQW9CO1FBQ2pDLElBQUksQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDLEVBQUU7WUFBRSxPQUFPLGNBQWMsQ0FBQyxhQUFhLENBQUM7U0FBRTtRQUNyRSxPQUFPLENBQUMsT0FBd0IsRUFBRSxNQUFNLEdBQUcsS0FBSyxFQUF5QixFQUFFO1lBQ3pFLElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRTtnQkFBRSxPQUFPLElBQUksQ0FBQzthQUFFO1lBQzVDLE1BQU0sWUFBWSxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUM7WUFDbkMsTUFBTSxPQUFPLEdBQUcsQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxZQUFZLElBQUksWUFBWSxDQUFDO1lBQ3pFLE9BQU8sR0FBRyxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO2dCQUMzQixJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsU0FBUyxFQUFFLEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxFQUFFLENBQUM7UUFDekQsQ0FBQyxDQUFDO0lBQ0osQ0FBQztJQUVEOzs7Ozs7Ozs7OztPQVdHO0lBQ0gsTUFBTSxDQUFDLGdCQUFnQixDQUFDLHFCQUE2QjtRQUNuRCxJQUFJLENBQUMsUUFBUSxDQUFDLHFCQUFxQixDQUFDLEVBQUU7WUFBRSxPQUFPLGNBQWMsQ0FBQyxhQUFhLENBQUM7U0FBRTtRQUM5RSxPQUFPLENBQUMsT0FBd0IsRUFBRSxNQUFNLEdBQUcsS0FBSyxFQUF5QixFQUFFO1lBQ3pFLElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRTtnQkFBRSxPQUFPLElBQUksQ0FBQzthQUFFO1lBQzVDLE1BQU0sWUFBWSxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUM7WUFDbkMsTUFBTSxPQUFPLEdBQUcsQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxZQUFZLEdBQUcscUJBQXFCLENBQUM7WUFDakYsT0FBTyxHQUFHLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUM7Z0JBQzNCLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxrQkFBa0IsRUFBRSxFQUFFLHFCQUFxQixFQUFFLFlBQVksRUFBRSxFQUFFLENBQUM7UUFDM0UsQ0FBQyxDQUFDO0lBQ0osQ0FBQztJQUVEOzs7Ozs7OztPQVFHO0lBQ0gsTUFBTSxDQUFDLFVBQVUsQ0FBQyxlQUF1QjtRQUN2QyxJQUFJLENBQUMsUUFBUSxDQUFDLGVBQWUsQ0FBQyxFQUFFO1lBQUUsT0FBTyxjQUFjLENBQUMsYUFBYSxDQUFDO1NBQUU7UUFDeEUsT0FBTyxDQUFDLE9BQXdCLEVBQUUsTUFBTSxHQUFHLEtBQUssRUFBeUIsRUFBRTtZQUN6RSxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUU7Z0JBQUUsT0FBTyxJQUFJLENBQUM7YUFBRTtZQUM1QyxNQUFNLFlBQVksR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDO1lBQ25DLE1BQU0sT0FBTyxHQUFHLFFBQVEsQ0FBQyxZQUFZLENBQUM7Z0JBQ3BDLFlBQVksR0FBRyxlQUFlLEtBQUssQ0FBQyxDQUFDO1lBQ3ZDLE9BQU8sR0FBRyxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO2dCQUMzQixJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsWUFBWSxFQUFFLEVBQUUsZUFBZSxFQUFFLFlBQVksRUFBRSxFQUFFLENBQUM7UUFDL0QsQ0FBQyxDQUFDO0lBQ0osQ0FBQztJQUVEOzs7Ozs7OztPQVFHO0lBQ0gsTUFBTSxDQUFDLGFBQWEsQ0FBQyxpQkFBeUI7UUFDNUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFO1lBQUUsT0FBTyxjQUFjLENBQUMsYUFBYSxDQUFDO1NBQUU7UUFDMUUsT0FBTyxDQUFDLE9BQXdCLEVBQUUsTUFBTSxHQUFHLEtBQUssRUFBeUIsRUFBRTtZQUN6RSxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUU7Z0JBQUUsT0FBTyxJQUFJLENBQUM7YUFBRTtZQUM1QyxNQUFNLGlCQUFpQixHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU0sSUFBSSxDQUFDLENBQUM7WUFDakUsTUFBTSxPQUFPLEdBQUcsaUJBQWlCLElBQUksaUJBQWlCLENBQUM7WUFDdkQsT0FBTyxHQUFHLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUM7Z0JBQzNCLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxlQUFlLEVBQUUsRUFBRSxpQkFBaUIsRUFBRSxpQkFBaUIsRUFBRSxFQUFFLENBQUM7UUFDekUsQ0FBQyxDQUFDO0lBQ0osQ0FBQztJQUVEOzs7Ozs7Ozs7OztPQVdHO0lBQ0gsTUFBTSxDQUFDLGFBQWEsQ0FBQyxpQkFBeUI7UUFDNUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFO1lBQUUsT0FBTyxjQUFjLENBQUMsYUFBYSxDQUFDO1NBQUU7UUFDMUUsT0FBTyxDQUFDLE9BQXdCLEVBQUUsTUFBTSxHQUFHLEtBQUssRUFBeUIsRUFBRTtZQUN6RSxNQUFNLGlCQUFpQixHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU0sSUFBSSxDQUFDLENBQUM7WUFDakUsTUFBTSxPQUFPLEdBQUcsaUJBQWlCLElBQUksaUJBQWlCLENBQUM7WUFDdkQsT0FBTyxHQUFHLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUM7Z0JBQzNCLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxlQUFlLEVBQUUsRUFBRSxpQkFBaUIsRUFBRSxpQkFBaUIsRUFBRSxFQUFFLENBQUM7UUFDekUsQ0FBQyxDQUFDO0lBQ0osQ0FBQztJQUVEOzs7Ozs7Ozs7OztPQVdHO0lBQ0gsTUFBTSxDQUFDLFlBQVksQ0FBQyxZQUFpQjtRQUNuQyxJQUFJLE9BQU8sQ0FBQyxZQUFZLENBQUMsS0FBSyxRQUFRLElBQUksT0FBTyxDQUFDLFlBQVksQ0FBQyxFQUFFO1lBQy9ELE9BQU8sY0FBYyxDQUFDLGFBQWEsQ0FBQztTQUNyQztRQUNELE9BQU8sQ0FBQyxPQUF3QixFQUFFLE1BQU0sR0FBRyxLQUFLLEVBQXlCLEVBQUU7WUFDekUsSUFBSSxPQUFPLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFO2dCQUFFLE9BQU8sSUFBSSxDQUFDO2FBQUU7WUFDNUMsTUFBTSxTQUFTLEdBQUcsYUFBYSxDQUM3QixXQUFXLENBQUMsWUFBWSxFQUFFLENBQUMsS0FBSyxFQUFFLGNBQWMsRUFBRSxFQUFFO2dCQUNsRCxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsY0FBYyxDQUFDLENBQUMsRUFBRTtvQkFBRSxPQUFPLElBQUksQ0FBQztpQkFBRTtnQkFDOUQsSUFBSSxvQkFBb0IsR0FBcUIsRUFBRyxDQUFDO2dCQUNqRCxJQUFJLGNBQXdCLENBQUM7Z0JBQzdCLElBQUksVUFBVSxHQUFxQixFQUFHLENBQUM7Z0JBQ3ZDLElBQUksT0FBTyxDQUFDLFlBQVksQ0FBQyxjQUFjLENBQUMsQ0FBQyxLQUFLLE9BQU8sRUFBRTtvQkFDckQsY0FBYyxHQUFHLFlBQVksQ0FBQyxjQUFjLENBQUMsQ0FBQztpQkFDL0M7cUJBQU0sSUFBSSxPQUFPLENBQUMsWUFBWSxDQUFDLGNBQWMsQ0FBQyxDQUFDLEtBQUssUUFBUSxFQUFFO29CQUM3RCxjQUFjLEdBQUcsWUFBWSxDQUFDLGNBQWMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztvQkFDaEUsVUFBVSxHQUFHLFlBQVksQ0FBQyxjQUFjLENBQUMsQ0FBQyxZQUFZLENBQUMsSUFBSSxFQUFHLENBQUM7aUJBQ2hFO2dCQUVELGlDQUFpQztnQkFDakMsS0FBSyxNQUFNLGFBQWEsSUFBSSxjQUFjLEVBQUU7b0JBQzFDLElBQUksR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLENBQUMsRUFBRSxNQUFNLENBQUMsRUFBRTt3QkFDeEQsb0JBQW9CLENBQUMsYUFBYSxDQUFDLEdBQUcsRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLENBQUM7cUJBQzVEO2lCQUNGO2dCQUVELCtCQUErQjtnQkFDL0Isb0JBQW9CLEdBQUcsYUFBYSxDQUFDLG9CQUFvQixFQUN2RCxXQUFXLENBQUMsVUFBVSxFQUFFLENBQUMsWUFBWSxFQUFFLGFBQWEsRUFBRSxFQUFFO29CQUN0RCxNQUFNLG1CQUFtQixHQUFHLGFBQWEsQ0FDdkMsV0FBVyxDQUFDLFlBQVksRUFBRSxDQUFDLFdBQVcsRUFBRSxTQUFTLEVBQUUsRUFBRTt3QkFDbkQsSUFBSSxTQUFTLEdBQWlCLElBQUksQ0FBQzt3QkFDbkMsSUFBSSxXQUFXLEtBQUssU0FBUyxJQUFJLFdBQVcsS0FBSyxTQUFTLEVBQUU7NEJBQzFELE1BQU0sU0FBUyxHQUFHLENBQUMsQ0FBQyxZQUFZLENBQUMsWUFBWSxHQUFHLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQzs0QkFDdEUsU0FBUyxHQUFHLGNBQWMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxTQUFTLEVBQUUsU0FBUyxDQUFDLENBQUM7eUJBQy9EOzZCQUFNLElBQUksT0FBTyxjQUFjLENBQUMsV0FBVyxDQUFDLEtBQUssVUFBVSxFQUFFOzRCQUM1RCxTQUFTLEdBQUcsY0FBYyxDQUFDLFdBQVcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDO3lCQUNwRDt3QkFDRCxPQUFPLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7NEJBQzVCLElBQUksQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQztvQkFDbkQsQ0FBQyxDQUFDLENBQ0gsQ0FBQztvQkFDRixPQUFPLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDLENBQUM7d0JBQ25DLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLGFBQWEsQ0FBQyxFQUFFLG1CQUFtQixFQUFFLENBQUM7Z0JBQ3BELENBQUMsQ0FBQyxDQUNILENBQUM7Z0JBQ0YsT0FBTyxPQUFPLENBQUMsb0JBQW9CLENBQUMsQ0FBQyxDQUFDO29CQUNwQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxjQUFjLENBQUMsRUFBRSxvQkFBb0IsRUFBRSxDQUFDO1lBQ3RELENBQUMsQ0FBQyxDQUNILENBQUM7WUFDRixPQUFPLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7UUFDL0MsQ0FBQyxDQUFDO0lBQ0osQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSCxNQUFNLENBQUMsUUFBUSxDQUFDLFlBQW9CO1FBQ2xDLElBQUksQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDLEVBQUU7WUFBRSxPQUFPLGNBQWMsQ0FBQyxhQUFhLENBQUM7U0FBRTtRQUNyRSxPQUFPLENBQUMsT0FBd0IsRUFBRSxNQUFNLEdBQUcsS0FBSyxFQUF5QixFQUFFO1lBQ3pFLElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRTtnQkFBRSxPQUFPLElBQUksQ0FBQzthQUFFO1lBQzVDLE1BQU0sWUFBWSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDdkUsTUFBTSxPQUFPLEdBQUcsWUFBWSxJQUFJLFlBQVksQ0FBQztZQUM3QyxPQUFPLEdBQUcsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQztnQkFDM0IsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLFVBQVUsRUFBRSxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsRUFBRSxDQUFDO1FBQzFELENBQUMsQ0FBQztJQUNKLENBQUM7SUFFRDs7Ozs7OztPQU9HO0lBQ0gsTUFBTSxDQUFDLFFBQVEsQ0FBQyxZQUFvQjtRQUNsQyxJQUFJLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQyxFQUFFO1lBQUUsT0FBTyxjQUFjLENBQUMsYUFBYSxDQUFDO1NBQUU7UUFDckUsT0FBTyxDQUFDLE9BQXdCLEVBQUUsTUFBTSxHQUFHLEtBQUssRUFBeUIsRUFBRTtZQUN6RSxNQUFNLFlBQVksR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3ZFLE1BQU0sT0FBTyxHQUFHLFlBQVksSUFBSSxZQUFZLENBQUM7WUFDN0MsT0FBTyxHQUFHLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUM7Z0JBQzNCLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxVQUFVLEVBQUUsRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLEVBQUUsQ0FBQztRQUMxRCxDQUFDLENBQUM7SUFDSixDQUFDO0lBRUQ7Ozs7Ozs7T0FPRztJQUNILE1BQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxHQUFHLElBQUk7UUFDOUIsSUFBSSxDQUFDLE1BQU0sRUFBRTtZQUFFLE9BQU8sY0FBYyxDQUFDLGFBQWEsQ0FBQztTQUFFO1FBQ3JELE9BQU8sQ0FBQyxPQUF3QixFQUFFLE1BQU0sR0FBRyxLQUFLLEVBQXlCLEVBQUU7WUFDekUsSUFBSSxPQUFPLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFO2dCQUFFLE9BQU8sSUFBSSxDQUFDO2FBQUU7WUFDNUMsTUFBTSxNQUFNLEdBQVUsT0FBTyxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNuRCxNQUFNLGNBQWMsR0FBRyxFQUFFLENBQUM7WUFDMUIsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7Z0JBQ3RDLElBQUksTUFBTSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksY0FBYyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRTtvQkFDckUsY0FBYyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztpQkFDaEM7YUFDRjtZQUNELE1BQU0sT0FBTyxHQUFHLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQztZQUN2QyxPQUFPLEdBQUcsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQztnQkFDM0IsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLGFBQWEsRUFBRSxFQUFFLGNBQWMsRUFBRSxFQUFFLENBQUM7UUFDakQsQ0FBQyxDQUFDO0lBQ0osQ0FBQztJQUVEOzs7Ozs7Ozs7T0FTRztJQUNILE1BQU0sQ0FBQyxRQUFRLENBQUMsWUFBWSxHQUFHLElBQUk7UUFDakMsSUFBSSxDQUFDLFlBQVksRUFBRTtZQUFFLE9BQU8sY0FBYyxDQUFDLGFBQWEsQ0FBQztTQUFFO1FBQzNELE9BQU8sQ0FBQyxPQUF3QixFQUFFLE1BQU0sR0FBRyxLQUFLLEVBQXlCLEVBQUU7WUFDekUsSUFBSSxPQUFPLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRTtnQkFBRSxPQUFPLElBQUksQ0FBQzthQUFFO1lBQ3ZFLE1BQU0sWUFBWSxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUM7WUFDbkMsNENBQTRDO1lBQzVDLEVBQUU7WUFDRixLQUFLO1lBQ0wsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDO1lBQ3JCLE9BQU8sR0FBRyxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO2dCQUMzQixJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsVUFBVSxFQUFFLEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxFQUFFLENBQUM7UUFDMUQsQ0FBQyxDQUFDO0lBQ0osQ0FBQztJQUVEOztPQUVHO0lBQ0gsTUFBTSxDQUFDLGFBQWEsQ0FBQyxPQUF3QjtRQUMzQyxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRDs7Ozs7OztPQU9HO0lBRUg7Ozs7Ozs7Ozs7T0FVRztJQUNILE1BQU0sQ0FBQyxZQUFZLENBQUMsVUFBMEI7UUFDNUMsSUFBSSxDQUFDLFVBQVUsRUFBRTtZQUFFLE9BQU8sSUFBSSxDQUFDO1NBQUU7UUFDakMsTUFBTSxpQkFBaUIsR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ3ZELElBQUksaUJBQWlCLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtZQUFFLE9BQU8sSUFBSSxDQUFDO1NBQUU7UUFDcEQsT0FBTyxDQUFDLE9BQXdCLEVBQUUsTUFBTSxHQUFHLEtBQUssRUFBeUIsRUFBRTtZQUN6RSxNQUFNLGFBQWEsR0FDakIsa0JBQWtCLENBQUMsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sQ0FBQyxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUMzRSxNQUFNLE9BQU8sR0FBRyxVQUFVLENBQUMsTUFBTSxHQUFHLGFBQWEsQ0FBQyxNQUFNLENBQUM7WUFDekQsT0FBTyxHQUFHLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUM7Z0JBQzNCLElBQUksQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLEdBQUcsYUFBYSxFQUFFLEVBQUUsT0FBTyxFQUFFLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUNqRSxDQUFDLENBQUM7SUFDSixDQUFDO0lBRUQ7Ozs7Ozs7Ozs7T0FVRztJQUNILE1BQU0sQ0FBQyxZQUFZLENBQUMsVUFBMEI7UUFDNUMsSUFBSSxDQUFDLFVBQVUsRUFBRTtZQUFFLE9BQU8sSUFBSSxDQUFDO1NBQUU7UUFDakMsTUFBTSxpQkFBaUIsR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ3ZELElBQUksaUJBQWlCLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtZQUFFLE9BQU8sSUFBSSxDQUFDO1NBQUU7UUFDcEQsT0FBTyxDQUFDLE9BQXdCLEVBQUUsTUFBTSxHQUFHLEtBQUssRUFBeUIsRUFBRTtZQUN6RSxNQUFNLGFBQWEsR0FDakIsa0JBQWtCLENBQUMsT0FBTyxFQUFFLGlCQUFpQixDQUFDLENBQUM7WUFDakQsTUFBTSxhQUFhLEdBQ2pCLFVBQVUsQ0FBQyxNQUFNLEdBQUcsYUFBYSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQyxNQUFNLENBQUM7WUFDN0QsTUFBTSxPQUFPLEdBQUcsYUFBYSxLQUFLLENBQUMsQ0FBQztZQUNwQyxJQUFJLEdBQUcsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLEVBQUU7Z0JBQUUsT0FBTyxJQUFJLENBQUM7YUFBRTtZQUMxQyxNQUFNLGFBQWEsR0FDakIsa0JBQWtCLENBQUMsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQ3pELE9BQU8sYUFBYSxDQUFDLEdBQUcsYUFBYSxFQUFFLEdBQUcsYUFBYSxFQUFFLEVBQUUsT0FBTyxFQUFFLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUNqRixDQUFDLENBQUM7SUFDSixDQUFDO0lBRUQ7Ozs7Ozs7OztPQVNHO0lBQ0gsTUFBTSxDQUFDLFlBQVksQ0FBQyxVQUEwQjtRQUM1QyxJQUFJLENBQUMsVUFBVSxFQUFFO1lBQUUsT0FBTyxJQUFJLENBQUM7U0FBRTtRQUNqQyxNQUFNLGlCQUFpQixHQUFHLFVBQVUsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDdkQsSUFBSSxpQkFBaUIsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO1lBQUUsT0FBTyxJQUFJLENBQUM7U0FBRTtRQUNwRCxPQUFPLENBQUMsT0FBd0IsRUFBRSxNQUFNLEdBQUcsS0FBSyxFQUF5QixFQUFFO1lBQ3pFLE1BQU0sY0FBYyxHQUFHLFlBQVksQ0FDakMsa0JBQWtCLENBQUMsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sQ0FBQyxDQUN2RCxDQUFDO1lBQ0YsTUFBTSxPQUFPLEdBQUcsY0FBYyxLQUFLLElBQUksQ0FBQztZQUN4QyxPQUFPLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQzdCLElBQUksQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLGNBQWMsRUFBRSxFQUFFLE9BQU8sRUFBRSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7UUFDL0QsQ0FBQyxDQUFDO0lBQ0osQ0FBQztJQUVEOzs7Ozs7Ozs7Ozs7T0FZRztJQUNILE1BQU0sQ0FBQyxVQUFVLENBQUMsU0FBdUI7UUFDdkMsSUFBSSxDQUFDLFNBQVMsRUFBRTtZQUFFLE9BQU8sSUFBSSxDQUFDO1NBQUU7UUFDaEMsT0FBTyxDQUFDLE9BQXdCLEVBQUUsTUFBTSxHQUFHLEtBQUssRUFBeUIsRUFBRTtZQUN6RSxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUU7Z0JBQUUsT0FBTyxJQUFJLENBQUM7YUFBRTtZQUM1QyxNQUFNLEtBQUssR0FBRyxTQUFTLENBQUMsT0FBTyxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDMUMsTUFBTSxPQUFPLEdBQUcsS0FBSyxLQUFLLElBQUksQ0FBQztZQUMvQixPQUFPLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQzdCLElBQUksQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLEtBQUssRUFBRSxFQUFFLEtBQUssRUFBRSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7UUFDcEQsQ0FBQyxDQUFDO0lBQ0osQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsTUFBTSxDQUFDLE9BQU8sQ0FBQyxVQUEwQjtRQUN2QyxJQUFJLENBQUMsVUFBVSxFQUFFO1lBQUUsT0FBTyxJQUFJLENBQUM7U0FBRTtRQUNqQyxNQUFNLGlCQUFpQixHQUFHLFVBQVUsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDdkQsSUFBSSxpQkFBaUIsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO1lBQUUsT0FBTyxJQUFJLENBQUM7U0FBRTtRQUNwRCxPQUFPLENBQUMsT0FBd0IsRUFBRSxNQUFNLEdBQUcsS0FBSyxFQUF5QixFQUFFLENBQ3pFLFlBQVksQ0FBQyxrQkFBa0IsQ0FBQyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUN6RSxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxNQUFNLENBQUMsWUFBWSxDQUFDLFVBQStCO1FBQ2pELElBQUksQ0FBQyxVQUFVLEVBQUU7WUFBRSxPQUFPLElBQUksQ0FBQztTQUFFO1FBQ2pDLE1BQU0saUJBQWlCLEdBQUcsVUFBVSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUN2RCxJQUFJLGlCQUFpQixDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7WUFBRSxPQUFPLElBQUksQ0FBQztTQUFFO1FBQ3BELE9BQU8sQ0FBQyxPQUF3QixFQUFFLEVBQUU7WUFDbEMsTUFBTSxXQUFXLEdBQ2YsdUJBQXVCLENBQUMsT0FBTyxFQUFFLGlCQUFpQixDQUFDLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ3hFLE9BQU8sR0FBRyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDdkQsQ0FBQyxDQUFDO0lBQ0osQ0FBQztJQUVELHVFQUF1RTtJQUN2RSx1RkFBdUY7SUFFdkY7O09BRUc7SUFDSCxNQUFNLENBQUMsR0FBRyxDQUFDLEdBQVc7UUFDcEIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRTtZQUFFLE9BQU8sY0FBYyxDQUFDLGFBQWEsQ0FBQztTQUFFO1FBQzVELE9BQU8sQ0FBQyxPQUF3QixFQUF5QixFQUFFO1lBQ3pELHlEQUF5RDtZQUN6RCxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxFQUFFO2dCQUFFLE9BQU8sSUFBSSxDQUFDO2FBQUU7WUFDNUQsTUFBTSxLQUFLLEdBQUcsVUFBVSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUN4QyxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDO1lBQzdCLDJFQUEyRTtZQUMzRSwwRkFBMEY7WUFDMUYsT0FBTyxLQUFLLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxJQUFJLEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsRUFBRSxDQUFDO1FBQzFFLENBQUMsQ0FBQztJQUNKLENBQUM7SUFFRDs7T0FFRztJQUNILE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBVztRQUNwQixJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFO1lBQUUsT0FBTyxjQUFjLENBQUMsYUFBYSxDQUFDO1NBQUU7UUFDNUQsT0FBTyxDQUFDLE9BQXdCLEVBQXlCLEVBQUU7WUFDekQseURBQXlEO1lBQ3pELElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUU7Z0JBQUUsT0FBTyxJQUFJLENBQUM7YUFBRTtZQUM1RCxNQUFNLEtBQUssR0FBRyxVQUFVLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3hDLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUM7WUFDN0IsMkVBQTJFO1lBQzNFLDBGQUEwRjtZQUMxRixPQUFPLEtBQUssQ0FBQyxLQUFLLENBQUMsSUFBSSxLQUFLLElBQUksR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxFQUFFLENBQUM7UUFDMUUsQ0FBQyxDQUFDO0lBQ0osQ0FBQztJQUVEOztPQUVHO0lBQ0gsTUFBTSxDQUFDLFlBQVksQ0FBQyxPQUF3QjtRQUMxQyxJQUFJLENBQUMsT0FBTyxFQUFFO1lBQUUsT0FBTyxjQUFjLENBQUMsYUFBYSxDQUFDO1NBQUU7UUFDdEQsT0FBTyxPQUFPLENBQUMsS0FBSyxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsQ0FBQztJQUM5RCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxNQUFNLENBQUMsS0FBSyxDQUFDLE9BQXdCO1FBQ25DLElBQUksQ0FBQyxPQUFPLEVBQUU7WUFBRSxPQUFPLGNBQWMsQ0FBQyxhQUFhLENBQUM7U0FBRTtRQUN0RCxNQUFNLFlBQVk7UUFDaEIsMkNBQTJDO1FBQzNDLDRMQUE0TCxDQUFDO1FBQy9MLE9BQU8sWUFBWSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLENBQUM7SUFDckUsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGlzRXF1YWwgZnJvbSAnbG9kYXNoL2lzRXF1YWwnO1xyXG5pbXBvcnQge1xyXG4gIF9leGVjdXRlQXN5bmNWYWxpZGF0b3JzLFxyXG4gIF9leGVjdXRlVmFsaWRhdG9ycyxcclxuICBfbWVyZ2VFcnJvcnMsXHJcbiAgX21lcmdlT2JqZWN0cyxcclxuICBBc3luY0lWYWxpZGF0b3JGbixcclxuICBnZXRUeXBlLFxyXG4gIGhhc1ZhbHVlLFxyXG4gIGlzQXJyYXksXHJcbiAgaXNCb29sZWFuLFxyXG4gIGlzRGVmaW5lZCxcclxuICBpc0VtcHR5LFxyXG4gIGlzTnVtYmVyLFxyXG4gIGlzU3RyaW5nLFxyXG4gIGlzVHlwZSxcclxuICBJVmFsaWRhdG9yRm4sXHJcbiAgU2NoZW1hUHJpbWl0aXZlVHlwZSxcclxuICB0b0phdmFTY3JpcHRUeXBlLFxyXG4gIHRvT2JzZXJ2YWJsZSxcclxuICB4b3JcclxuICB9IGZyb20gJy4vdmFsaWRhdG9yLmZ1bmN0aW9ucyc7XHJcbmltcG9ydCB7IEFic3RyYWN0Q29udHJvbCwgVmFsaWRhdGlvbkVycm9ycywgVmFsaWRhdG9yRm4gfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XHJcbmltcG9ydCB7IGZvckVhY2hDb3B5IH0gZnJvbSAnLi91dGlsaXR5LmZ1bmN0aW9ucyc7XHJcbmltcG9ydCB7IGZvcmtKb2luIH0gZnJvbSAncnhqcyc7XHJcbmltcG9ydCB7IEpzb25TY2hlbWFGb3JtYXROYW1lcywganNvblNjaGVtYUZvcm1hdFRlc3RzIH0gZnJvbSAnLi9mb3JtYXQtcmVnZXguY29uc3RhbnRzJztcclxuaW1wb3J0IHsgbWFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xyXG5cclxuXHJcblxyXG4vKipcclxuICogJ0pzb25WYWxpZGF0b3JzJyBjbGFzc1xyXG4gKlxyXG4gKiBQcm92aWRlcyBhbiBleHRlbmRlZCBzZXQgb2YgdmFsaWRhdG9ycyB0byBiZSB1c2VkIGJ5IGZvcm0gY29udHJvbHMsXHJcbiAqIGNvbXBhdGlibGUgd2l0aCBzdGFuZGFyZCBKU09OIFNjaGVtYSB2YWxpZGF0aW9uIG9wdGlvbnMuXHJcbiAqIGh0dHA6Ly9qc29uLXNjaGVtYS5vcmcvbGF0ZXN0L2pzb24tc2NoZW1hLXZhbGlkYXRpb24uaHRtbFxyXG4gKlxyXG4gKiBOb3RlOiBUaGlzIGxpYnJhcnkgaXMgZGVzaWduZWQgYXMgYSBkcm9wLWluIHJlcGxhY2VtZW50IGZvciB0aGUgQW5ndWxhclxyXG4gKiBWYWxpZGF0b3JzIGxpYnJhcnksIGFuZCBleGNlcHQgZm9yIG9uZSBzbWFsbCBicmVha2luZyBjaGFuZ2UgdG8gdGhlICdwYXR0ZXJuJ1xyXG4gKiB2YWxpZGF0b3IgKGRlc2NyaWJlZCBiZWxvdykgaXQgY2FuIGV2ZW4gYmUgaW1wb3J0ZWQgYXMgYSBzdWJzdGl0dXRlLCBsaWtlIHNvOlxyXG4gKlxyXG4gKiAgIGltcG9ydCB7IEpzb25WYWxpZGF0b3JzIGFzIFZhbGlkYXRvcnMgfSBmcm9tICdqc29uLXZhbGlkYXRvcnMnO1xyXG4gKlxyXG4gKiBhbmQgaXQgc2hvdWxkIHdvcmsgd2l0aCBleGlzdGluZyBjb2RlIGFzIGEgY29tcGxldGUgcmVwbGFjZW1lbnQuXHJcbiAqXHJcbiAqIFRoZSBvbmUgZXhjZXB0aW9uIGlzIHRoZSAncGF0dGVybicgdmFsaWRhdG9yLCB3aGljaCBoYXMgYmVlbiBjaGFuZ2VkIHRvXHJcbiAqIG1hdGNoZSBwYXJ0aWFsIHZhbHVlcyBieSBkZWZhdWx0ICh0aGUgc3RhbmRhcmQgJ3BhdHRlcm4nIHZhbGlkYXRvciB3cmFwcGVkXHJcbiAqIGFsbCBwYXR0ZXJucyBpbiAnXicgYW5kICckJywgZm9yY2luZyB0aGVtIHRvIGFsd2F5cyBtYXRjaCBhbiBlbnRpcmUgdmFsdWUpLlxyXG4gKiBIb3dldmVyLCB0aGUgb2xkIGJlaGF2aW9yIGNhbiBiZSByZXN0b3JlZCBieSBzaW1wbHkgYWRkaW5nICdeJyBhbmQgJyQnXHJcbiAqIGFyb3VuZCB5b3VyIHBhdHRlcm5zLCBvciBieSBwYXNzaW5nIGFuIG9wdGlvbmFsIHNlY29uZCBwYXJhbWV0ZXIgb2YgVFJVRS5cclxuICogVGhpcyBjaGFuZ2UgaXMgdG8gbWFrZSB0aGUgJ3BhdHRlcm4nIHZhbGlkYXRvciBtYXRjaCB0aGUgYmVoYXZpb3Igb2YgYVxyXG4gKiBKU09OIFNjaGVtYSBwYXR0ZXJuLCB3aGljaCBhbGxvd3MgcGFydGlhbCBtYXRjaGVzLCByYXRoZXIgdGhhbiB0aGUgYmVoYXZpb3JcclxuICogb2YgYW4gSFRNTCBpbnB1dCBjb250cm9sIHBhdHRlcm4sIHdoaWNoIGRvZXMgbm90LlxyXG4gKlxyXG4gKiBUaGlzIGxpYnJhcnkgcmVwbGFjZXMgQW5ndWxhcidzIHZhbGlkYXRvcnMgYW5kIGNvbWJpbmF0aW9uIGZ1bmN0aW9uc1xyXG4gKiB3aXRoIHRoZSBmb2xsb3dpbmcgdmFsaWRhdG9ycyBhbmQgdHJhbnNmb3JtYXRpb24gZnVuY3Rpb25zOlxyXG4gKlxyXG4gKiBWYWxpZGF0b3JzOlxyXG4gKiAgIEZvciBhbGwgZm9ybUNvbnRyb2xzOiAgICAgcmVxdWlyZWQgKCopLCB0eXBlLCBlbnVtLCBjb25zdFxyXG4gKiAgIEZvciB0ZXh0IGZvcm1Db250cm9sczogICAgbWluTGVuZ3RoICgqKSwgbWF4TGVuZ3RoICgqKSwgcGF0dGVybiAoKiksIGZvcm1hdFxyXG4gKiAgIEZvciBudW1lcmljIGZvcm1Db250cm9sczogbWF4aW11bSwgZXhjbHVzaXZlTWF4aW11bSxcclxuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbmltdW0sIGV4Y2x1c2l2ZU1pbmltdW0sIG11bHRpcGxlT2ZcclxuICogICBGb3IgZm9ybUdyb3VwIG9iamVjdHM6ICAgIG1pblByb3BlcnRpZXMsIG1heFByb3BlcnRpZXMsIGRlcGVuZGVuY2llc1xyXG4gKiAgIEZvciBmb3JtQXJyYXkgYXJyYXlzOiAgICAgbWluSXRlbXMsIG1heEl0ZW1zLCB1bmlxdWVJdGVtcywgY29udGFpbnNcclxuICogICBOb3QgdXNlZCBieSBKU09OIFNjaGVtYTogIG1pbiAoKiksIG1heCAoKiksIHJlcXVpcmVkVHJ1ZSAoKiksIGVtYWlsICgqKVxyXG4gKiAoVmFsaWRhdG9ycyBvcmlnaW5hbGx5IGluY2x1ZGVkIHdpdGggQW5ndWxhciBhcmUgbWFrZWQgd2l0aCAoKikuKVxyXG4gKlxyXG4gKiBOT1RFIC8gVE9ETzogVGhlIGRlcGVuZGVuY2llcyB2YWxpZGF0b3IgaXMgbm90IGNvbXBsZXRlLlxyXG4gKiBOT1RFIC8gVE9ETzogVGhlIGNvbnRhaW5zIHZhbGlkYXRvciBpcyBub3QgY29tcGxldGUuXHJcbiAqXHJcbiAqIFZhbGlkYXRvcnMgbm90IHVzZWQgYnkgSlNPTiBTY2hlbWEgKGJ1dCBpbmNsdWRlZCBmb3IgY29tcGF0aWJpbGl0eSlcclxuICogYW5kIHRoZWlyIEpTT04gU2NoZW1hIGVxdWl2YWxlbnRzOlxyXG4gKlxyXG4gKiAgIEFuZ3VsYXIgdmFsaWRhdG9yIHwgSlNPTiBTY2hlbWEgZXF1aXZhbGVudFxyXG4gKiAgIC0tLS0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG4gKiAgICAgbWluKG51bWJlcikgICAgIHwgICBtaW5pbXVtKG51bWJlcilcclxuICogICAgIG1heChudW1iZXIpICAgICB8ICAgbWF4aW11bShudW1iZXIpXHJcbiAqICAgICByZXF1aXJlZFRydWUoKSAgfCAgIGNvbnN0KHRydWUpXHJcbiAqICAgICBlbWFpbCgpICAgICAgICAgfCAgIGZvcm1hdCgnZW1haWwnKVxyXG4gKlxyXG4gKiBWYWxpZGF0b3IgdHJhbnNmb3JtYXRpb24gZnVuY3Rpb25zOlxyXG4gKiAgIGNvbXBvc2VBbnlPZiwgY29tcG9zZU9uZU9mLCBjb21wb3NlQWxsT2YsIGNvbXBvc2VOb3RcclxuICogKEFuZ3VsYXIncyBvcmlnaW5hbCBjb21iaW5hdGlvbiBmdW5jaXRvbiwgJ2NvbXBvc2UnLCBpcyBhbHNvIGluY2x1ZGVkIGZvclxyXG4gKiBiYWNrd2FyZCBjb21wYXRpYmlsaXR5LCB0aG91Z2ggaXQgaXMgZnVuY3Rpb25hbGx5IGVxdWl2YWxlbnQgdG8gY29tcG9zZUFsbE9mLFxyXG4gKiBhc3NpZGUgZnJvbSBpdHMgbW9yZSBnZW5lcmljIGVycm9yIG1lc3NhZ2UuKVxyXG4gKlxyXG4gKiBBbGwgdmFsaWRhdG9ycyBoYXZlIGFsc28gYmVlbiBleHRlbmRlZCB0byBhY2NlcHQgYW4gb3B0aW9uYWwgc2Vjb25kIGFyZ3VtZW50XHJcbiAqIHdoaWNoLCBpZiBwYXNzZWQgYSBUUlVFIHZhbHVlLCBjYXVzZXMgdGhlIHZhbGlkYXRvciB0byBwZXJmb3JtIHRoZSBvcHBvc2l0ZVxyXG4gKiBvZiBpdHMgb3JpZ2luYWwgZmluY3Rpb24uIChUaGlzIGlzIHVzZWQgaW50ZXJuYWxseSB0byBlbmFibGUgJ25vdCcgYW5kXHJcbiAqICdjb21wb3NlT25lT2YnIHRvIGZ1bmN0aW9uIGFuZCByZXR1cm4gdXNlZnVsIGVycm9yIG1lc3NhZ2VzLilcclxuICpcclxuICogVGhlICdyZXF1aXJlZCcgdmFsaWRhdG9yIGhhcyBhbHNvIGJlZW4gb3ZlcmxvYWRlZCBzbyB0aGF0IGlmIGNhbGxlZCB3aXRoXHJcbiAqIGEgYm9vbGVhbiBwYXJhbWV0ZXIgKG9yIG5vIHBhcmFtZXRlcnMpIGl0IHJldHVybnMgdGhlIG9yaWdpbmFsIHZhbGlkYXRvclxyXG4gKiBmdW5jdGlvbiAocmF0aGVyIHRoYW4gZXhlY3V0aW5nIGl0KS4gSG93ZXZlciwgaWYgaXQgaXMgY2FsbGVkIHdpdGggYW5cclxuICogQWJzdHJhY3RDb250cm9sIHBhcmFtZXRlciAoYXMgd2FzIHByZXZpb3VzbHkgcmVxdWlyZWQpLCBpdCBiZWhhdmVzXHJcbiAqIGV4YWN0bHkgYXMgYmVmb3JlLlxyXG4gKlxyXG4gKiBUaGlzIGVuYWJsZXMgYWxsIHZhbGlkYXRvcnMgKGluY2x1ZGluZyAncmVxdWlyZWQnKSB0byBiZSBjb25zdHJ1Y3RlZCBpblxyXG4gKiBleGFjdGx5IHRoZSBzYW1lIHdheSwgc28gdGhleSBjYW4gYmUgYXV0b21hdGljYWxseSBhcHBsaWVkIHVzaW5nIHRoZVxyXG4gKiBlcXVpdmFsZW50IGtleSBuYW1lcyBhbmQgdmFsdWVzIHRha2VuIGRpcmVjdGx5IGZyb20gYSBKU09OIFNjaGVtYS5cclxuICpcclxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBwYXJ0aWFsbHkgZGVyaXZlZCBmcm9tIEFuZ3VsYXIsXHJcbiAqIHdoaWNoIGlzIENvcHlyaWdodCAoYykgMjAxNC0yMDE3IEdvb2dsZSwgSW5jLlxyXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyB0aGVyZWZvcmUgZ292ZXJuZWQgYnkgdGhlIHNhbWUgTUlULXN0eWxlIGxpY2Vuc2VcclxuICogdGhhdCBjYW4gYmUgZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxyXG4gKlxyXG4gKiBPcmlnaW5hbCBBbmd1bGFyIFZhbGlkYXRvcnM6XHJcbiAqIGh0dHBzOi8vZ2l0aHViLmNvbS9hbmd1bGFyL2FuZ3VsYXIvYmxvYi9tYXN0ZXIvcGFja2FnZXMvZm9ybXMvc3JjL3ZhbGlkYXRvcnMudHNcclxuICovXHJcbmV4cG9ydCBjbGFzcyBKc29uVmFsaWRhdG9ycyB7XHJcblxyXG4gIC8qKlxyXG4gICAqIFZhbGlkYXRvciBmdW5jdGlvbnM6XHJcbiAgICpcclxuICAgKiBGb3IgYWxsIGZvcm1Db250cm9sczogICAgIHJlcXVpcmVkLCB0eXBlLCBlbnVtLCBjb25zdFxyXG4gICAqIEZvciB0ZXh0IGZvcm1Db250cm9sczogICAgbWluTGVuZ3RoLCBtYXhMZW5ndGgsIHBhdHRlcm4sIGZvcm1hdFxyXG4gICAqIEZvciBudW1lcmljIGZvcm1Db250cm9sczogbWF4aW11bSwgZXhjbHVzaXZlTWF4aW11bSxcclxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbmltdW0sIGV4Y2x1c2l2ZU1pbmltdW0sIG11bHRpcGxlT2ZcclxuICAgKiBGb3IgZm9ybUdyb3VwIG9iamVjdHM6ICAgIG1pblByb3BlcnRpZXMsIG1heFByb3BlcnRpZXMsIGRlcGVuZGVuY2llc1xyXG4gICAqIEZvciBmb3JtQXJyYXkgYXJyYXlzOiAgICAgbWluSXRlbXMsIG1heEl0ZW1zLCB1bmlxdWVJdGVtcywgY29udGFpbnNcclxuICAgKlxyXG4gICAqIFRPRE86IGZpbmlzaCBkZXBlbmRlbmNpZXMgdmFsaWRhdG9yXHJcbiAgICovXHJcblxyXG4gIC8qKlxyXG4gICAqICdyZXF1aXJlZCcgdmFsaWRhdG9yXHJcbiAgICpcclxuICAgKiBUaGlzIHZhbGlkYXRvciBpcyBvdmVybG9hZGVkLCBjb21wYXJlZCB0byB0aGUgZGVmYXVsdCByZXF1aXJlZCB2YWxpZGF0b3IuXHJcbiAgICogSWYgY2FsbGVkIHdpdGggbm8gcGFyYW1ldGVycywgb3IgVFJVRSwgdGhpcyB2YWxpZGF0b3IgcmV0dXJucyB0aGVcclxuICAgKiAncmVxdWlyZWQnIHZhbGlkYXRvciBmdW5jdGlvbiAocmF0aGVyIHRoYW4gZXhlY3V0aW5nIGl0KS4gVGhpcyBtYXRjaGVzXHJcbiAgICogdGhlIGJlaGF2aW9yIG9mIGFsbCBvdGhlciB2YWxpZGF0b3JzIGluIHRoaXMgbGlicmFyeS5cclxuICAgKlxyXG4gICAqIElmIHRoaXMgdmFsaWRhdG9yIGlzIGNhbGxlZCB3aXRoIGFuIEFic3RyYWN0Q29udHJvbCBwYXJhbWV0ZXJcclxuICAgKiAoYXMgd2FzIHByZXZpb3VzbHkgcmVxdWlyZWQpIGl0IGJlaGF2ZXMgdGhlIHNhbWUgYXMgQW5ndWxhcidzIGRlZmF1bHRcclxuICAgKiByZXF1aXJlZCB2YWxpZGF0b3IsIGFuZCByZXR1cm5zIGFuIGVycm9yIGlmIHRoZSBjb250cm9sIGlzIGVtcHR5LlxyXG4gICAqXHJcbiAgICogT2xkIGJlaGF2aW9yOiAoaWYgaW5wdXQgdHlwZSA9IEFic3RyYWN0Q29udHJvbClcclxuICAgKiAvLyB7QWJzdHJhY3RDb250cm9sfSBjb250cm9sIC0gcmVxdWlyZWQgY29udHJvbFxyXG4gICAqIC8vIHt7W2tleTogc3RyaW5nXTogYm9vbGVhbn19IC0gcmV0dXJucyBlcnJvciBtZXNzYWdlIGlmIG5vIGlucHV0XHJcbiAgICpcclxuICAgKiBOZXcgYmVoYXZpb3I6IChpZiBubyBpbnB1dCwgb3IgaW5wdXQgdHlwZSA9IGJvb2xlYW4pXHJcbiAgICogLy8ge2Jvb2xlYW4gPSB0cnVlfSByZXF1aXJlZD8gLSB0cnVlIHRvIHZhbGlkYXRlLCBmYWxzZSB0byBkaXNhYmxlXHJcbiAgICogLy8ge0lWYWxpZGF0b3JGbn0gLSByZXR1cm5zIHRoZSAncmVxdWlyZWQnIHZhbGlkYXRvciBmdW5jdGlvbiBpdHNlbGZcclxuICAgKi9cclxuICBzdGF0aWMgcmVxdWlyZWQoaW5wdXQ6IEFic3RyYWN0Q29udHJvbCk6IFZhbGlkYXRpb25FcnJvcnN8bnVsbDtcclxuICBzdGF0aWMgcmVxdWlyZWQoaW5wdXQ/OiBib29sZWFuKTogSVZhbGlkYXRvckZuO1xyXG5cclxuICBzdGF0aWMgcmVxdWlyZWQoaW5wdXQ/OiBBYnN0cmFjdENvbnRyb2x8Ym9vbGVhbik6IFZhbGlkYXRpb25FcnJvcnN8bnVsbHxJVmFsaWRhdG9yRm4ge1xyXG4gICAgaWYgKGlucHV0ID09PSB1bmRlZmluZWQpIHsgaW5wdXQgPSB0cnVlOyB9XHJcbiAgICBzd2l0Y2ggKGlucHV0KSB7XHJcbiAgICAgIGNhc2UgdHJ1ZTogLy8gUmV0dXJuIHJlcXVpcmVkIGZ1bmN0aW9uIChkbyBub3QgZXhlY3V0ZSBpdCB5ZXQpXHJcbiAgICAgICAgcmV0dXJuIChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wsIGludmVydCA9IGZhbHNlKTogVmFsaWRhdGlvbkVycm9yc3xudWxsID0+IHtcclxuICAgICAgICAgIGlmIChpbnZlcnQpIHsgcmV0dXJuIG51bGw7IH0gLy8gaWYgbm90IHJlcXVpcmVkLCBhbHdheXMgcmV0dXJuIHZhbGlkXHJcbiAgICAgICAgICByZXR1cm4gaGFzVmFsdWUoY29udHJvbC52YWx1ZSkgPyBudWxsIDogeyAncmVxdWlyZWQnOiB0cnVlIH07XHJcbiAgICAgICAgfTtcclxuICAgICAgY2FzZSBmYWxzZTogLy8gRG8gbm90aGluZyAoaWYgZmllbGQgaXMgbm90IHJlcXVpcmVkLCBpdCBpcyBhbHdheXMgdmFsaWQpXHJcbiAgICAgICAgcmV0dXJuIEpzb25WYWxpZGF0b3JzLm51bGxWYWxpZGF0b3I7XHJcbiAgICAgIGRlZmF1bHQ6IC8vIEV4ZWN1dGUgcmVxdWlyZWQgZnVuY3Rpb25cclxuICAgICAgICByZXR1cm4gaGFzVmFsdWUoKDxBYnN0cmFjdENvbnRyb2w+aW5wdXQpLnZhbHVlKSA/IG51bGwgOiB7ICdyZXF1aXJlZCc6IHRydWUgfTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqICd0eXBlJyB2YWxpZGF0b3JcclxuICAgKlxyXG4gICAqIFJlcXVpcmVzIGEgY29udHJvbCB0byBvbmx5IGFjY2VwdCB2YWx1ZXMgb2YgYSBzcGVjaWZpZWQgdHlwZSxcclxuICAgKiBvciBvbmUgb2YgYW4gYXJyYXkgb2YgdHlwZXMuXHJcbiAgICpcclxuICAgKiBOb3RlOiBTY2hlbWFQcmltaXRpdmVUeXBlID0gJ3N0cmluZyd8J251bWJlcid8J2ludGVnZXInfCdib29sZWFuJ3wnbnVsbCdcclxuICAgKlxyXG4gICAqIC8vIHtTY2hlbWFQcmltaXRpdmVUeXBlfFNjaGVtYVByaW1pdGl2ZVR5cGVbXX0gdHlwZSAtIHR5cGUocykgdG8gYWNjZXB0XHJcbiAgICogLy8ge0lWYWxpZGF0b3JGbn1cclxuICAgKi9cclxuICBzdGF0aWMgdHlwZShyZXF1aXJlZFR5cGU6IFNjaGVtYVByaW1pdGl2ZVR5cGV8U2NoZW1hUHJpbWl0aXZlVHlwZVtdKTogSVZhbGlkYXRvckZuIHtcclxuICAgIGlmICghaGFzVmFsdWUocmVxdWlyZWRUeXBlKSkgeyByZXR1cm4gSnNvblZhbGlkYXRvcnMubnVsbFZhbGlkYXRvcjsgfVxyXG4gICAgcmV0dXJuIChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wsIGludmVydCA9IGZhbHNlKTogVmFsaWRhdGlvbkVycm9yc3xudWxsID0+IHtcclxuICAgICAgaWYgKGlzRW1wdHkoY29udHJvbC52YWx1ZSkpIHsgcmV0dXJuIG51bGw7IH1cclxuICAgICAgY29uc3QgY3VycmVudFZhbHVlOiBhbnkgPSBjb250cm9sLnZhbHVlO1xyXG4gICAgICBjb25zdCBpc1ZhbGlkID0gaXNBcnJheShyZXF1aXJlZFR5cGUpID9cclxuICAgICAgICAoPFNjaGVtYVByaW1pdGl2ZVR5cGVbXT5yZXF1aXJlZFR5cGUpLnNvbWUodHlwZSA9PiBpc1R5cGUoY3VycmVudFZhbHVlLCB0eXBlKSkgOlxyXG4gICAgICAgIGlzVHlwZShjdXJyZW50VmFsdWUsIDxTY2hlbWFQcmltaXRpdmVUeXBlPnJlcXVpcmVkVHlwZSk7XHJcbiAgICAgIHJldHVybiB4b3IoaXNWYWxpZCwgaW52ZXJ0KSA/XHJcbiAgICAgICAgbnVsbCA6IHsgJ3R5cGUnOiB7IHJlcXVpcmVkVHlwZSwgY3VycmVudFZhbHVlIH0gfTtcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAnZW51bScgdmFsaWRhdG9yXHJcbiAgICpcclxuICAgKiBSZXF1aXJlcyBhIGNvbnRyb2wgdG8gaGF2ZSBhIHZhbHVlIGZyb20gYW4gZW51bWVyYXRlZCBsaXN0IG9mIHZhbHVlcy5cclxuICAgKlxyXG4gICAqIENvbnZlcnRzIHR5cGVzIGFzIG5lZWRlZCB0byBhbGxvdyBzdHJpbmcgaW5wdXRzIHRvIHN0aWxsIGNvcnJlY3RseVxyXG4gICAqIG1hdGNoIG51bWJlciwgYm9vbGVhbiwgYW5kIG51bGwgZW51bSB2YWx1ZXMuXHJcbiAgICpcclxuICAgKiAvLyB7YW55W119IGFsbG93ZWRWYWx1ZXMgLSBhcnJheSBvZiBhY2NlcHRhYmxlIHZhbHVlc1xyXG4gICAqIC8vIHtJVmFsaWRhdG9yRm59XHJcbiAgICovXHJcbiAgc3RhdGljIGVudW0oYWxsb3dlZFZhbHVlczogYW55W10pOiBJVmFsaWRhdG9yRm4ge1xyXG4gICAgaWYgKCFpc0FycmF5KGFsbG93ZWRWYWx1ZXMpKSB7IHJldHVybiBKc29uVmFsaWRhdG9ycy5udWxsVmFsaWRhdG9yOyB9XHJcbiAgICByZXR1cm4gKGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCwgaW52ZXJ0ID0gZmFsc2UpOiBWYWxpZGF0aW9uRXJyb3JzfG51bGwgPT4ge1xyXG4gICAgICBpZiAoaXNFbXB0eShjb250cm9sLnZhbHVlKSkgeyByZXR1cm4gbnVsbDsgfVxyXG4gICAgICBjb25zdCBjdXJyZW50VmFsdWU6IGFueSA9IGNvbnRyb2wudmFsdWU7XHJcbiAgICAgIGNvbnN0IGlzRXF1YWxWYWwgPSAoZW51bVZhbHVlLCBpbnB1dFZhbHVlKSA9PlxyXG4gICAgICAgIGVudW1WYWx1ZSA9PT0gaW5wdXRWYWx1ZSB8fFxyXG4gICAgICAgIChpc051bWJlcihlbnVtVmFsdWUpICYmICtpbnB1dFZhbHVlID09PSArZW51bVZhbHVlKSB8fFxyXG4gICAgICAgIChpc0Jvb2xlYW4oZW51bVZhbHVlLCAnc3RyaWN0JykgJiZcclxuICAgICAgICAgIHRvSmF2YVNjcmlwdFR5cGUoaW5wdXRWYWx1ZSwgJ2Jvb2xlYW4nKSA9PT0gZW51bVZhbHVlKSB8fFxyXG4gICAgICAgIChlbnVtVmFsdWUgPT09IG51bGwgJiYgIWhhc1ZhbHVlKGlucHV0VmFsdWUpKSB8fFxyXG4gICAgICAgIGlzRXF1YWwoZW51bVZhbHVlLCBpbnB1dFZhbHVlKTtcclxuICAgICAgY29uc3QgaXNWYWxpZCA9IGlzQXJyYXkoY3VycmVudFZhbHVlKSA/XHJcbiAgICAgICAgY3VycmVudFZhbHVlLmV2ZXJ5KGlucHV0VmFsdWUgPT4gYWxsb3dlZFZhbHVlcy5zb21lKGVudW1WYWx1ZSA9PlxyXG4gICAgICAgICAgaXNFcXVhbFZhbChlbnVtVmFsdWUsIGlucHV0VmFsdWUpXHJcbiAgICAgICAgKSkgOlxyXG4gICAgICAgIGFsbG93ZWRWYWx1ZXMuc29tZShlbnVtVmFsdWUgPT4gaXNFcXVhbFZhbChlbnVtVmFsdWUsIGN1cnJlbnRWYWx1ZSkpO1xyXG4gICAgICByZXR1cm4geG9yKGlzVmFsaWQsIGludmVydCkgP1xyXG4gICAgICAgIG51bGwgOiB7ICdlbnVtJzogeyBhbGxvd2VkVmFsdWVzLCBjdXJyZW50VmFsdWUgfSB9O1xyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqICdjb25zdCcgdmFsaWRhdG9yXHJcbiAgICpcclxuICAgKiBSZXF1aXJlcyBhIGNvbnRyb2wgdG8gaGF2ZSBhIHNwZWNpZmljIHZhbHVlLlxyXG4gICAqXHJcbiAgICogQ29udmVydHMgdHlwZXMgYXMgbmVlZGVkIHRvIGFsbG93IHN0cmluZyBpbnB1dHMgdG8gc3RpbGwgY29ycmVjdGx5XHJcbiAgICogbWF0Y2ggbnVtYmVyLCBib29sZWFuLCBhbmQgbnVsbCB2YWx1ZXMuXHJcbiAgICpcclxuICAgKiBUT0RPOiBtb2RpZnkgdG8gd29yayB3aXRoIG9iamVjdHNcclxuICAgKlxyXG4gICAqIC8vIHthbnlbXX0gcmVxdWlyZWRWYWx1ZSAtIHJlcXVpcmVkIHZhbHVlXHJcbiAgICogLy8ge0lWYWxpZGF0b3JGbn1cclxuICAgKi9cclxuICBzdGF0aWMgY29uc3QocmVxdWlyZWRWYWx1ZTogYW55KTogSVZhbGlkYXRvckZuIHtcclxuICAgIGlmICghaGFzVmFsdWUocmVxdWlyZWRWYWx1ZSkpIHsgcmV0dXJuIEpzb25WYWxpZGF0b3JzLm51bGxWYWxpZGF0b3I7IH1cclxuICAgIHJldHVybiAoY29udHJvbDogQWJzdHJhY3RDb250cm9sLCBpbnZlcnQgPSBmYWxzZSk6IFZhbGlkYXRpb25FcnJvcnN8bnVsbCA9PiB7XHJcbiAgICAgIGlmIChpc0VtcHR5KGNvbnRyb2wudmFsdWUpKSB7IHJldHVybiBudWxsOyB9XHJcbiAgICAgIGNvbnN0IGN1cnJlbnRWYWx1ZTogYW55ID0gY29udHJvbC52YWx1ZTtcclxuICAgICAgY29uc3QgaXNFcXVhbFZhbCA9IChjb25zdFZhbHVlLCBpbnB1dFZhbHVlKSA9PlxyXG4gICAgICAgIGNvbnN0VmFsdWUgPT09IGlucHV0VmFsdWUgfHxcclxuICAgICAgICBpc051bWJlcihjb25zdFZhbHVlKSAmJiAraW5wdXRWYWx1ZSA9PT0gK2NvbnN0VmFsdWUgfHxcclxuICAgICAgICBpc0Jvb2xlYW4oY29uc3RWYWx1ZSwgJ3N0cmljdCcpICYmXHJcbiAgICAgICAgICB0b0phdmFTY3JpcHRUeXBlKGlucHV0VmFsdWUsICdib29sZWFuJykgPT09IGNvbnN0VmFsdWUgfHxcclxuICAgICAgICBjb25zdFZhbHVlID09PSBudWxsICYmICFoYXNWYWx1ZShpbnB1dFZhbHVlKTtcclxuICAgICAgY29uc3QgaXNWYWxpZCA9IGlzRXF1YWxWYWwocmVxdWlyZWRWYWx1ZSwgY3VycmVudFZhbHVlKTtcclxuICAgICAgcmV0dXJuIHhvcihpc1ZhbGlkLCBpbnZlcnQpID9cclxuICAgICAgICBudWxsIDogeyAnY29uc3QnOiB7IHJlcXVpcmVkVmFsdWUsIGN1cnJlbnRWYWx1ZSB9IH07XHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ21pbkxlbmd0aCcgdmFsaWRhdG9yXHJcbiAgICpcclxuICAgKiBSZXF1aXJlcyBhIGNvbnRyb2wncyB0ZXh0IHZhbHVlIHRvIGJlIGdyZWF0ZXIgdGhhbiBhIHNwZWNpZmllZCBsZW5ndGguXHJcbiAgICpcclxuICAgKiAvLyB7bnVtYmVyfSBtaW5pbXVtTGVuZ3RoIC0gbWluaW11bSBhbGxvd2VkIHN0cmluZyBsZW5ndGhcclxuICAgKiAvLyB7Ym9vbGVhbiA9IGZhbHNlfSBpbnZlcnQgLSBpbnN0ZWFkIHJldHVybiBlcnJvciBvYmplY3Qgb25seSBpZiB2YWxpZFxyXG4gICAqIC8vIHtJVmFsaWRhdG9yRm59XHJcbiAgICovXHJcbiAgc3RhdGljIG1pbkxlbmd0aChtaW5pbXVtTGVuZ3RoOiBudW1iZXIpOiBJVmFsaWRhdG9yRm4ge1xyXG4gICAgaWYgKCFoYXNWYWx1ZShtaW5pbXVtTGVuZ3RoKSkgeyByZXR1cm4gSnNvblZhbGlkYXRvcnMubnVsbFZhbGlkYXRvcjsgfVxyXG4gICAgcmV0dXJuIChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wsIGludmVydCA9IGZhbHNlKTogVmFsaWRhdGlvbkVycm9yc3xudWxsID0+IHtcclxuICAgICAgaWYgKGlzRW1wdHkoY29udHJvbC52YWx1ZSkpIHsgcmV0dXJuIG51bGw7IH1cclxuICAgICAgY29uc3QgY3VycmVudExlbmd0aCA9IGlzU3RyaW5nKGNvbnRyb2wudmFsdWUpID8gY29udHJvbC52YWx1ZS5sZW5ndGggOiAwO1xyXG4gICAgICBjb25zdCBpc1ZhbGlkID0gY3VycmVudExlbmd0aCA+PSBtaW5pbXVtTGVuZ3RoO1xyXG4gICAgICByZXR1cm4geG9yKGlzVmFsaWQsIGludmVydCkgP1xyXG4gICAgICAgIG51bGwgOiB7ICdtaW5MZW5ndGgnOiB7IG1pbmltdW1MZW5ndGgsIGN1cnJlbnRMZW5ndGggfSB9O1xyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqICdtYXhMZW5ndGgnIHZhbGlkYXRvclxyXG4gICAqXHJcbiAgICogUmVxdWlyZXMgYSBjb250cm9sJ3MgdGV4dCB2YWx1ZSB0byBiZSBsZXNzIHRoYW4gYSBzcGVjaWZpZWQgbGVuZ3RoLlxyXG4gICAqXHJcbiAgICogLy8ge251bWJlcn0gbWF4aW11bUxlbmd0aCAtIG1heGltdW0gYWxsb3dlZCBzdHJpbmcgbGVuZ3RoXHJcbiAgICogLy8ge2Jvb2xlYW4gPSBmYWxzZX0gaW52ZXJ0IC0gaW5zdGVhZCByZXR1cm4gZXJyb3Igb2JqZWN0IG9ubHkgaWYgdmFsaWRcclxuICAgKiAvLyB7SVZhbGlkYXRvckZufVxyXG4gICAqL1xyXG4gIHN0YXRpYyBtYXhMZW5ndGgobWF4aW11bUxlbmd0aDogbnVtYmVyKTogSVZhbGlkYXRvckZuIHtcclxuICAgIGlmICghaGFzVmFsdWUobWF4aW11bUxlbmd0aCkpIHsgcmV0dXJuIEpzb25WYWxpZGF0b3JzLm51bGxWYWxpZGF0b3I7IH1cclxuICAgIHJldHVybiAoY29udHJvbDogQWJzdHJhY3RDb250cm9sLCBpbnZlcnQgPSBmYWxzZSk6IFZhbGlkYXRpb25FcnJvcnN8bnVsbCA9PiB7XHJcbiAgICAgIGNvbnN0IGN1cnJlbnRMZW5ndGggPSBpc1N0cmluZyhjb250cm9sLnZhbHVlKSA/IGNvbnRyb2wudmFsdWUubGVuZ3RoIDogMDtcclxuICAgICAgY29uc3QgaXNWYWxpZCA9IGN1cnJlbnRMZW5ndGggPD0gbWF4aW11bUxlbmd0aDtcclxuICAgICAgcmV0dXJuIHhvcihpc1ZhbGlkLCBpbnZlcnQpID9cclxuICAgICAgICBudWxsIDogeyAnbWF4TGVuZ3RoJzogeyBtYXhpbXVtTGVuZ3RoLCBjdXJyZW50TGVuZ3RoIH0gfTtcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAncGF0dGVybicgdmFsaWRhdG9yXHJcbiAgICpcclxuICAgKiBOb3RlOiBOT1QgdGhlIHNhbWUgYXMgQW5ndWxhcidzIGRlZmF1bHQgcGF0dGVybiB2YWxpZGF0b3IuXHJcbiAgICpcclxuICAgKiBSZXF1aXJlcyBhIGNvbnRyb2wncyB2YWx1ZSB0byBtYXRjaCBhIHNwZWNpZmllZCByZWd1bGFyIGV4cHJlc3Npb24gcGF0dGVybi5cclxuICAgKlxyXG4gICAqIFRoaXMgdmFsaWRhdG9yIGNoYW5nZXMgdGhlIGJlaGF2aW9yIG9mIGRlZmF1bHQgcGF0dGVybiB2YWxpZGF0b3JcclxuICAgKiBieSByZXBsYWNpbmcgUmVnRXhwKGBeJHtwYXR0ZXJufSRgKSB3aXRoIFJlZ0V4cChgJHtwYXR0ZXJufWApLFxyXG4gICAqIHdoaWNoIGFsbG93cyBmb3IgcGFydGlhbCBtYXRjaGVzLlxyXG4gICAqXHJcbiAgICogVG8gcmV0dXJuIHRvIHRoZSBkZWZhdWx0IGZ1bmNpdG9uYWxpdHksIGFuZCBtYXRjaCB0aGUgZW50aXJlIHN0cmluZyxcclxuICAgKiBwYXNzIFRSVUUgYXMgdGhlIG9wdGlvbmFsIHNlY29uZCBwYXJhbWV0ZXIuXHJcbiAgICpcclxuICAgKiAvLyB7c3RyaW5nfSBwYXR0ZXJuIC0gcmVndWxhciBleHByZXNzaW9uIHBhdHRlcm5cclxuICAgKiAvLyB7Ym9vbGVhbiA9IGZhbHNlfSB3aG9sZVN0cmluZyAtIG1hdGNoIHdob2xlIHZhbHVlIHN0cmluZz9cclxuICAgKiAvLyB7SVZhbGlkYXRvckZufVxyXG4gICAqL1xyXG4gIHN0YXRpYyBwYXR0ZXJuKHBhdHRlcm46IHN0cmluZ3xSZWdFeHAsIHdob2xlU3RyaW5nID0gZmFsc2UpOiBJVmFsaWRhdG9yRm4ge1xyXG4gICAgaWYgKCFoYXNWYWx1ZShwYXR0ZXJuKSkgeyByZXR1cm4gSnNvblZhbGlkYXRvcnMubnVsbFZhbGlkYXRvcjsgfVxyXG4gICAgcmV0dXJuIChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wsIGludmVydCA9IGZhbHNlKTogVmFsaWRhdGlvbkVycm9yc3xudWxsID0+IHtcclxuICAgICAgaWYgKGlzRW1wdHkoY29udHJvbC52YWx1ZSkpIHsgcmV0dXJuIG51bGw7IH1cclxuICAgICAgbGV0IHJlZ2V4OiBSZWdFeHA7XHJcbiAgICAgIGxldCByZXF1aXJlZFBhdHRlcm46IHN0cmluZztcclxuICAgICAgaWYgKHR5cGVvZiBwYXR0ZXJuID09PSAnc3RyaW5nJykge1xyXG4gICAgICAgIHJlcXVpcmVkUGF0dGVybiA9ICh3aG9sZVN0cmluZykgPyBgXiR7cGF0dGVybn0kYCA6IHBhdHRlcm47XHJcbiAgICAgICAgcmVnZXggPSBuZXcgUmVnRXhwKHJlcXVpcmVkUGF0dGVybik7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgcmVxdWlyZWRQYXR0ZXJuID0gcGF0dGVybi50b1N0cmluZygpO1xyXG4gICAgICAgIHJlZ2V4ID0gcGF0dGVybjtcclxuICAgICAgfVxyXG4gICAgICBjb25zdCBjdXJyZW50VmFsdWU6IHN0cmluZyA9IGNvbnRyb2wudmFsdWU7XHJcbiAgICAgIGNvbnN0IGlzVmFsaWQgPSBpc1N0cmluZyhjdXJyZW50VmFsdWUpID8gcmVnZXgudGVzdChjdXJyZW50VmFsdWUpIDogZmFsc2U7XHJcbiAgICAgIHJldHVybiB4b3IoaXNWYWxpZCwgaW52ZXJ0KSA/XHJcbiAgICAgICAgbnVsbCA6IHsgJ3BhdHRlcm4nOiB7IHJlcXVpcmVkUGF0dGVybiwgY3VycmVudFZhbHVlIH0gfTtcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAnZm9ybWF0JyB2YWxpZGF0b3JcclxuICAgKlxyXG4gICAqIFJlcXVpcmVzIGEgY29udHJvbCB0byBoYXZlIGEgdmFsdWUgb2YgYSBjZXJ0YWluIGZvcm1hdC5cclxuICAgKlxyXG4gICAqIFRoaXMgdmFsaWRhdG9yIGN1cnJlbnRseSBjaGVja3MgdGhlIGZvbGxvd2luZyBmb3Jtc3RzOlxyXG4gICAqICAgZGF0ZSwgdGltZSwgZGF0ZS10aW1lLCBlbWFpbCwgaG9zdG5hbWUsIGlwdjQsIGlwdjYsXHJcbiAgICogICB1cmksIHVyaS1yZWZlcmVuY2UsIHVyaS10ZW1wbGF0ZSwgdXJsLCB1dWlkLCBjb2xvcixcclxuICAgKiAgIGpzb24tcG9pbnRlciwgcmVsYXRpdmUtanNvbi1wb2ludGVyLCByZWdleFxyXG4gICAqXHJcbiAgICogRmFzdCBmb3JtYXQgcmVndWxhciBleHByZXNzaW9ucyBjb3BpZWQgZnJvbSBBSlY6XHJcbiAgICogaHR0cHM6Ly9naXRodWIuY29tL2Vwb2JlcmV6a2luL2Fqdi9ibG9iL21hc3Rlci9saWIvY29tcGlsZS9mb3JtYXRzLmpzXHJcbiAgICpcclxuICAgKiAvLyB7SnNvblNjaGVtYUZvcm1hdE5hbWVzfSByZXF1aXJlZEZvcm1hdCAtIGZvcm1hdCB0byBjaGVja1xyXG4gICAqIC8vIHtJVmFsaWRhdG9yRm59XHJcbiAgICovXHJcbiAgc3RhdGljIGZvcm1hdChyZXF1aXJlZEZvcm1hdDogSnNvblNjaGVtYUZvcm1hdE5hbWVzKTogSVZhbGlkYXRvckZuIHtcclxuICAgIGlmICghaGFzVmFsdWUocmVxdWlyZWRGb3JtYXQpKSB7IHJldHVybiBKc29uVmFsaWRhdG9ycy5udWxsVmFsaWRhdG9yOyB9XHJcbiAgICByZXR1cm4gKGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCwgaW52ZXJ0ID0gZmFsc2UpOiBWYWxpZGF0aW9uRXJyb3JzfG51bGwgPT4ge1xyXG4gICAgICBpZiAoaXNFbXB0eShjb250cm9sLnZhbHVlKSkgeyByZXR1cm4gbnVsbDsgfVxyXG4gICAgICBsZXQgaXNWYWxpZDogYm9vbGVhbjtcclxuICAgICAgY29uc3QgY3VycmVudFZhbHVlOiBzdHJpbmd8RGF0ZSA9IGNvbnRyb2wudmFsdWU7XHJcbiAgICAgIGlmIChpc1N0cmluZyhjdXJyZW50VmFsdWUpKSB7XHJcbiAgICAgICAgY29uc3QgZm9ybWF0VGVzdDogRnVuY3Rpb258UmVnRXhwID0ganNvblNjaGVtYUZvcm1hdFRlc3RzW3JlcXVpcmVkRm9ybWF0XTtcclxuICAgICAgICBpZiAodHlwZW9mIGZvcm1hdFRlc3QgPT09ICdvYmplY3QnKSB7XHJcbiAgICAgICAgICBpc1ZhbGlkID0gKDxSZWdFeHA+Zm9ybWF0VGVzdCkudGVzdCg8c3RyaW5nPmN1cnJlbnRWYWx1ZSk7XHJcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgZm9ybWF0VGVzdCA9PT0gJ2Z1bmN0aW9uJykge1xyXG4gICAgICAgICAgaXNWYWxpZCA9ICg8RnVuY3Rpb24+Zm9ybWF0VGVzdCkoPHN0cmluZz5jdXJyZW50VmFsdWUpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBjb25zb2xlLmVycm9yKGBmb3JtYXQgdmFsaWRhdG9yIGVycm9yOiBcIiR7cmVxdWlyZWRGb3JtYXR9XCIgaXMgbm90IGEgcmVjb2duaXplZCBmb3JtYXQuYCk7XHJcbiAgICAgICAgICBpc1ZhbGlkID0gdHJ1ZTtcclxuICAgICAgICB9XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgLy8gQWxsb3cgSmF2YVNjcmlwdCBEYXRlIG9iamVjdHNcclxuICAgICAgICBpc1ZhbGlkID0gWydkYXRlJywgJ3RpbWUnLCAnZGF0ZS10aW1lJ10uaW5jbHVkZXMocmVxdWlyZWRGb3JtYXQpICYmXHJcbiAgICAgICAgICBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoY3VycmVudFZhbHVlKSA9PT0gJ1tvYmplY3QgRGF0ZV0nO1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiB4b3IoaXNWYWxpZCwgaW52ZXJ0KSA/XHJcbiAgICAgICAgbnVsbCA6IHsgJ2Zvcm1hdCc6IHsgcmVxdWlyZWRGb3JtYXQsIGN1cnJlbnRWYWx1ZSB9IH07XHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ21pbmltdW0nIHZhbGlkYXRvclxyXG4gICAqXHJcbiAgICogUmVxdWlyZXMgYSBjb250cm9sJ3MgbnVtZXJpYyB2YWx1ZSB0byBiZSBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG9cclxuICAgKiBhIG1pbmltdW0gYW1vdW50LlxyXG4gICAqXHJcbiAgICogQW55IG5vbi1udW1lcmljIHZhbHVlIGlzIGFsc28gdmFsaWQgKGFjY29yZGluZyB0byB0aGUgSFRNTCBmb3JtcyBzcGVjLFxyXG4gICAqIGEgbm9uLW51bWVyaWMgdmFsdWUgZG9lc24ndCBoYXZlIGEgbWluaW11bSkuXHJcbiAgICogaHR0cHM6Ly93d3cudzMub3JnL1RSL2h0bWw1L2Zvcm1zLmh0bWwjYXR0ci1pbnB1dC1tYXhcclxuICAgKlxyXG4gICAqIC8vIHtudW1iZXJ9IG1pbmltdW0gLSBtaW5pbXVtIGFsbG93ZWQgdmFsdWVcclxuICAgKiAvLyB7SVZhbGlkYXRvckZufVxyXG4gICAqL1xyXG4gIHN0YXRpYyBtaW5pbXVtKG1pbmltdW1WYWx1ZTogbnVtYmVyKTogSVZhbGlkYXRvckZuIHtcclxuICAgIGlmICghaGFzVmFsdWUobWluaW11bVZhbHVlKSkgeyByZXR1cm4gSnNvblZhbGlkYXRvcnMubnVsbFZhbGlkYXRvcjsgfVxyXG4gICAgcmV0dXJuIChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wsIGludmVydCA9IGZhbHNlKTogVmFsaWRhdGlvbkVycm9yc3xudWxsID0+IHtcclxuICAgICAgaWYgKGlzRW1wdHkoY29udHJvbC52YWx1ZSkpIHsgcmV0dXJuIG51bGw7IH1cclxuICAgICAgY29uc3QgY3VycmVudFZhbHVlID0gY29udHJvbC52YWx1ZTtcclxuICAgICAgY29uc3QgaXNWYWxpZCA9ICFpc051bWJlcihjdXJyZW50VmFsdWUpIHx8IGN1cnJlbnRWYWx1ZSA+PSBtaW5pbXVtVmFsdWU7XHJcbiAgICAgIHJldHVybiB4b3IoaXNWYWxpZCwgaW52ZXJ0KSA/XHJcbiAgICAgICAgbnVsbCA6IHsgJ21pbmltdW0nOiB7IG1pbmltdW1WYWx1ZSwgY3VycmVudFZhbHVlIH0gfTtcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAnZXhjbHVzaXZlTWluaW11bScgdmFsaWRhdG9yXHJcbiAgICpcclxuICAgKiBSZXF1aXJlcyBhIGNvbnRyb2wncyBudW1lcmljIHZhbHVlIHRvIGJlIGxlc3MgdGhhbiBhIG1heGltdW0gYW1vdW50LlxyXG4gICAqXHJcbiAgICogQW55IG5vbi1udW1lcmljIHZhbHVlIGlzIGFsc28gdmFsaWQgKGFjY29yZGluZyB0byB0aGUgSFRNTCBmb3JtcyBzcGVjLFxyXG4gICAqIGEgbm9uLW51bWVyaWMgdmFsdWUgZG9lc24ndCBoYXZlIGEgbWF4aW11bSkuXHJcbiAgICogaHR0cHM6Ly93d3cudzMub3JnL1RSL2h0bWw1L2Zvcm1zLmh0bWwjYXR0ci1pbnB1dC1tYXhcclxuICAgKlxyXG4gICAqIC8vIHtudW1iZXJ9IGV4Y2x1c2l2ZU1pbmltdW1WYWx1ZSAtIG1heGltdW0gYWxsb3dlZCB2YWx1ZVxyXG4gICAqIC8vIHtJVmFsaWRhdG9yRm59XHJcbiAgICovXHJcbiAgc3RhdGljIGV4Y2x1c2l2ZU1pbmltdW0oZXhjbHVzaXZlTWluaW11bVZhbHVlOiBudW1iZXIpOiBJVmFsaWRhdG9yRm4ge1xyXG4gICAgaWYgKCFoYXNWYWx1ZShleGNsdXNpdmVNaW5pbXVtVmFsdWUpKSB7IHJldHVybiBKc29uVmFsaWRhdG9ycy5udWxsVmFsaWRhdG9yOyB9XHJcbiAgICByZXR1cm4gKGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCwgaW52ZXJ0ID0gZmFsc2UpOiBWYWxpZGF0aW9uRXJyb3JzfG51bGwgPT4ge1xyXG4gICAgICBpZiAoaXNFbXB0eShjb250cm9sLnZhbHVlKSkgeyByZXR1cm4gbnVsbDsgfVxyXG4gICAgICBjb25zdCBjdXJyZW50VmFsdWUgPSBjb250cm9sLnZhbHVlO1xyXG4gICAgICBjb25zdCBpc1ZhbGlkID0gIWlzTnVtYmVyKGN1cnJlbnRWYWx1ZSkgfHwgK2N1cnJlbnRWYWx1ZSA8IGV4Y2x1c2l2ZU1pbmltdW1WYWx1ZTtcclxuICAgICAgcmV0dXJuIHhvcihpc1ZhbGlkLCBpbnZlcnQpID9cclxuICAgICAgICBudWxsIDogeyAnZXhjbHVzaXZlTWluaW11bSc6IHsgZXhjbHVzaXZlTWluaW11bVZhbHVlLCBjdXJyZW50VmFsdWUgfSB9O1xyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqICdtYXhpbXVtJyB2YWxpZGF0b3JcclxuICAgKlxyXG4gICAqIFJlcXVpcmVzIGEgY29udHJvbCdzIG51bWVyaWMgdmFsdWUgdG8gYmUgbGVzcyB0aGFuIG9yIGVxdWFsIHRvXHJcbiAgICogYSBtYXhpbXVtIGFtb3VudC5cclxuICAgKlxyXG4gICAqIEFueSBub24tbnVtZXJpYyB2YWx1ZSBpcyBhbHNvIHZhbGlkIChhY2NvcmRpbmcgdG8gdGhlIEhUTUwgZm9ybXMgc3BlYyxcclxuICAgKiBhIG5vbi1udW1lcmljIHZhbHVlIGRvZXNuJ3QgaGF2ZSBhIG1heGltdW0pLlxyXG4gICAqIGh0dHBzOi8vd3d3LnczLm9yZy9UUi9odG1sNS9mb3Jtcy5odG1sI2F0dHItaW5wdXQtbWF4XHJcbiAgICpcclxuICAgKiAvLyB7bnVtYmVyfSBtYXhpbXVtVmFsdWUgLSBtYXhpbXVtIGFsbG93ZWQgdmFsdWVcclxuICAgKiAvLyB7SVZhbGlkYXRvckZufVxyXG4gICAqL1xyXG4gIHN0YXRpYyBtYXhpbXVtKG1heGltdW1WYWx1ZTogbnVtYmVyKTogSVZhbGlkYXRvckZuIHtcclxuICAgIGlmICghaGFzVmFsdWUobWF4aW11bVZhbHVlKSkgeyByZXR1cm4gSnNvblZhbGlkYXRvcnMubnVsbFZhbGlkYXRvcjsgfVxyXG4gICAgcmV0dXJuIChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wsIGludmVydCA9IGZhbHNlKTogVmFsaWRhdGlvbkVycm9yc3xudWxsID0+IHtcclxuICAgICAgaWYgKGlzRW1wdHkoY29udHJvbC52YWx1ZSkpIHsgcmV0dXJuIG51bGw7IH1cclxuICAgICAgY29uc3QgY3VycmVudFZhbHVlID0gY29udHJvbC52YWx1ZTtcclxuICAgICAgY29uc3QgaXNWYWxpZCA9ICFpc051bWJlcihjdXJyZW50VmFsdWUpIHx8ICtjdXJyZW50VmFsdWUgPD0gbWF4aW11bVZhbHVlO1xyXG4gICAgICByZXR1cm4geG9yKGlzVmFsaWQsIGludmVydCkgP1xyXG4gICAgICAgIG51bGwgOiB7ICdtYXhpbXVtJzogeyBtYXhpbXVtVmFsdWUsIGN1cnJlbnRWYWx1ZSB9IH07XHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ2V4Y2x1c2l2ZU1heGltdW0nIHZhbGlkYXRvclxyXG4gICAqXHJcbiAgICogUmVxdWlyZXMgYSBjb250cm9sJ3MgbnVtZXJpYyB2YWx1ZSB0byBiZSBsZXNzIHRoYW4gYSBtYXhpbXVtIGFtb3VudC5cclxuICAgKlxyXG4gICAqIEFueSBub24tbnVtZXJpYyB2YWx1ZSBpcyBhbHNvIHZhbGlkIChhY2NvcmRpbmcgdG8gdGhlIEhUTUwgZm9ybXMgc3BlYyxcclxuICAgKiBhIG5vbi1udW1lcmljIHZhbHVlIGRvZXNuJ3QgaGF2ZSBhIG1heGltdW0pLlxyXG4gICAqIGh0dHBzOi8vd3d3LnczLm9yZy9UUi9odG1sNS9mb3Jtcy5odG1sI2F0dHItaW5wdXQtbWF4XHJcbiAgICpcclxuICAgKiAvLyB7bnVtYmVyfSBleGNsdXNpdmVNYXhpbXVtVmFsdWUgLSBtYXhpbXVtIGFsbG93ZWQgdmFsdWVcclxuICAgKiAvLyB7SVZhbGlkYXRvckZufVxyXG4gICAqL1xyXG4gIHN0YXRpYyBleGNsdXNpdmVNYXhpbXVtKGV4Y2x1c2l2ZU1heGltdW1WYWx1ZTogbnVtYmVyKTogSVZhbGlkYXRvckZuIHtcclxuICAgIGlmICghaGFzVmFsdWUoZXhjbHVzaXZlTWF4aW11bVZhbHVlKSkgeyByZXR1cm4gSnNvblZhbGlkYXRvcnMubnVsbFZhbGlkYXRvcjsgfVxyXG4gICAgcmV0dXJuIChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wsIGludmVydCA9IGZhbHNlKTogVmFsaWRhdGlvbkVycm9yc3xudWxsID0+IHtcclxuICAgICAgaWYgKGlzRW1wdHkoY29udHJvbC52YWx1ZSkpIHsgcmV0dXJuIG51bGw7IH1cclxuICAgICAgY29uc3QgY3VycmVudFZhbHVlID0gY29udHJvbC52YWx1ZTtcclxuICAgICAgY29uc3QgaXNWYWxpZCA9ICFpc051bWJlcihjdXJyZW50VmFsdWUpIHx8ICtjdXJyZW50VmFsdWUgPCBleGNsdXNpdmVNYXhpbXVtVmFsdWU7XHJcbiAgICAgIHJldHVybiB4b3IoaXNWYWxpZCwgaW52ZXJ0KSA/XHJcbiAgICAgICAgbnVsbCA6IHsgJ2V4Y2x1c2l2ZU1heGltdW0nOiB7IGV4Y2x1c2l2ZU1heGltdW1WYWx1ZSwgY3VycmVudFZhbHVlIH0gfTtcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAnbXVsdGlwbGVPZicgdmFsaWRhdG9yXHJcbiAgICpcclxuICAgKiBSZXF1aXJlcyBhIGNvbnRyb2wgdG8gaGF2ZSBhIG51bWVyaWMgdmFsdWUgdGhhdCBpcyBhIG11bHRpcGxlXHJcbiAgICogb2YgYSBzcGVjaWZpZWQgbnVtYmVyLlxyXG4gICAqXHJcbiAgICogLy8ge251bWJlcn0gbXVsdGlwbGVPZlZhbHVlIC0gbnVtYmVyIHZhbHVlIG11c3QgYmUgYSBtdWx0aXBsZSBvZlxyXG4gICAqIC8vIHtJVmFsaWRhdG9yRm59XHJcbiAgICovXHJcbiAgc3RhdGljIG11bHRpcGxlT2YobXVsdGlwbGVPZlZhbHVlOiBudW1iZXIpOiBJVmFsaWRhdG9yRm4ge1xyXG4gICAgaWYgKCFoYXNWYWx1ZShtdWx0aXBsZU9mVmFsdWUpKSB7IHJldHVybiBKc29uVmFsaWRhdG9ycy5udWxsVmFsaWRhdG9yOyB9XHJcbiAgICByZXR1cm4gKGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCwgaW52ZXJ0ID0gZmFsc2UpOiBWYWxpZGF0aW9uRXJyb3JzfG51bGwgPT4ge1xyXG4gICAgICBpZiAoaXNFbXB0eShjb250cm9sLnZhbHVlKSkgeyByZXR1cm4gbnVsbDsgfVxyXG4gICAgICBjb25zdCBjdXJyZW50VmFsdWUgPSBjb250cm9sLnZhbHVlO1xyXG4gICAgICBjb25zdCBpc1ZhbGlkID0gaXNOdW1iZXIoY3VycmVudFZhbHVlKSAmJlxyXG4gICAgICAgIGN1cnJlbnRWYWx1ZSAlIG11bHRpcGxlT2ZWYWx1ZSA9PT0gMDtcclxuICAgICAgcmV0dXJuIHhvcihpc1ZhbGlkLCBpbnZlcnQpID9cclxuICAgICAgICBudWxsIDogeyAnbXVsdGlwbGVPZic6IHsgbXVsdGlwbGVPZlZhbHVlLCBjdXJyZW50VmFsdWUgfSB9O1xyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqICdtaW5Qcm9wZXJ0aWVzJyB2YWxpZGF0b3JcclxuICAgKlxyXG4gICAqIFJlcXVpcmVzIGEgZm9ybSBncm91cCB0byBoYXZlIGEgbWluaW11bSBudW1iZXIgb2YgcHJvcGVydGllcyAoaS5lLiBoYXZlXHJcbiAgICogdmFsdWVzIGVudGVyZWQgaW4gYSBtaW5pbXVtIG51bWJlciBvZiBjb250cm9scyB3aXRoaW4gdGhlIGdyb3VwKS5cclxuICAgKlxyXG4gICAqIC8vIHtudW1iZXJ9IG1pbmltdW1Qcm9wZXJ0aWVzIC0gbWluaW11bSBudW1iZXIgb2YgcHJvcGVydGllcyBhbGxvd2VkXHJcbiAgICogLy8ge0lWYWxpZGF0b3JGbn1cclxuICAgKi9cclxuICBzdGF0aWMgbWluUHJvcGVydGllcyhtaW5pbXVtUHJvcGVydGllczogbnVtYmVyKTogSVZhbGlkYXRvckZuIHtcclxuICAgIGlmICghaGFzVmFsdWUobWluaW11bVByb3BlcnRpZXMpKSB7IHJldHVybiBKc29uVmFsaWRhdG9ycy5udWxsVmFsaWRhdG9yOyB9XHJcbiAgICByZXR1cm4gKGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCwgaW52ZXJ0ID0gZmFsc2UpOiBWYWxpZGF0aW9uRXJyb3JzfG51bGwgPT4ge1xyXG4gICAgICBpZiAoaXNFbXB0eShjb250cm9sLnZhbHVlKSkgeyByZXR1cm4gbnVsbDsgfVxyXG4gICAgICBjb25zdCBjdXJyZW50UHJvcGVydGllcyA9IE9iamVjdC5rZXlzKGNvbnRyb2wudmFsdWUpLmxlbmd0aCB8fCAwO1xyXG4gICAgICBjb25zdCBpc1ZhbGlkID0gY3VycmVudFByb3BlcnRpZXMgPj0gbWluaW11bVByb3BlcnRpZXM7XHJcbiAgICAgIHJldHVybiB4b3IoaXNWYWxpZCwgaW52ZXJ0KSA/XHJcbiAgICAgICAgbnVsbCA6IHsgJ21pblByb3BlcnRpZXMnOiB7IG1pbmltdW1Qcm9wZXJ0aWVzLCBjdXJyZW50UHJvcGVydGllcyB9IH07XHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ21heFByb3BlcnRpZXMnIHZhbGlkYXRvclxyXG4gICAqXHJcbiAgICogUmVxdWlyZXMgYSBmb3JtIGdyb3VwIHRvIGhhdmUgYSBtYXhpbXVtIG51bWJlciBvZiBwcm9wZXJ0aWVzIChpLmUuIGhhdmVcclxuICAgKiB2YWx1ZXMgZW50ZXJlZCBpbiBhIG1heGltdW0gbnVtYmVyIG9mIGNvbnRyb2xzIHdpdGhpbiB0aGUgZ3JvdXApLlxyXG4gICAqXHJcbiAgICogTm90ZTogSGFzIG5vIGVmZmVjdCBpZiB0aGUgZm9ybSBncm91cCBkb2VzIG5vdCBjb250YWluIG1vcmUgdGhhbiB0aGVcclxuICAgKiBtYXhpbXVtIG51bWJlciBvZiBjb250cm9scy5cclxuICAgKlxyXG4gICAqIC8vIHtudW1iZXJ9IG1heGltdW1Qcm9wZXJ0aWVzIC0gbWF4aW11bSBudW1iZXIgb2YgcHJvcGVydGllcyBhbGxvd2VkXHJcbiAgICogLy8ge0lWYWxpZGF0b3JGbn1cclxuICAgKi9cclxuICBzdGF0aWMgbWF4UHJvcGVydGllcyhtYXhpbXVtUHJvcGVydGllczogbnVtYmVyKTogSVZhbGlkYXRvckZuIHtcclxuICAgIGlmICghaGFzVmFsdWUobWF4aW11bVByb3BlcnRpZXMpKSB7IHJldHVybiBKc29uVmFsaWRhdG9ycy5udWxsVmFsaWRhdG9yOyB9XHJcbiAgICByZXR1cm4gKGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCwgaW52ZXJ0ID0gZmFsc2UpOiBWYWxpZGF0aW9uRXJyb3JzfG51bGwgPT4ge1xyXG4gICAgICBjb25zdCBjdXJyZW50UHJvcGVydGllcyA9IE9iamVjdC5rZXlzKGNvbnRyb2wudmFsdWUpLmxlbmd0aCB8fCAwO1xyXG4gICAgICBjb25zdCBpc1ZhbGlkID0gY3VycmVudFByb3BlcnRpZXMgPD0gbWF4aW11bVByb3BlcnRpZXM7XHJcbiAgICAgIHJldHVybiB4b3IoaXNWYWxpZCwgaW52ZXJ0KSA/XHJcbiAgICAgICAgbnVsbCA6IHsgJ21heFByb3BlcnRpZXMnOiB7IG1heGltdW1Qcm9wZXJ0aWVzLCBjdXJyZW50UHJvcGVydGllcyB9IH07XHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ2RlcGVuZGVuY2llcycgdmFsaWRhdG9yXHJcbiAgICpcclxuICAgKiBSZXF1aXJlcyB0aGUgY29udHJvbHMgaW4gYSBmb3JtIGdyb3VwIHRvIG1lZXQgYWRkaXRpb25hbCB2YWxpZGF0aW9uXHJcbiAgICogY3JpdGVyaWEsIGRlcGVuZGluZyBvbiB0aGUgdmFsdWVzIG9mIG90aGVyIGNvbnRyb2xzIGluIHRoZSBncm91cC5cclxuICAgKlxyXG4gICAqIEV4YW1wbGVzOlxyXG4gICAqIGh0dHBzOi8vc3BhY2V0ZWxlc2NvcGUuZ2l0aHViLmlvL3VuZGVyc3RhbmRpbmctanNvbi1zY2hlbWEvcmVmZXJlbmNlL29iamVjdC5odG1sI2RlcGVuZGVuY2llc1xyXG4gICAqXHJcbiAgICogLy8ge2FueX0gZGVwZW5kZW5jaWVzIC0gcmVxdWlyZWQgZGVwZW5kZW5jaWVzXHJcbiAgICogLy8ge0lWYWxpZGF0b3JGbn1cclxuICAgKi9cclxuICBzdGF0aWMgZGVwZW5kZW5jaWVzKGRlcGVuZGVuY2llczogYW55KTogSVZhbGlkYXRvckZuIHtcclxuICAgIGlmIChnZXRUeXBlKGRlcGVuZGVuY2llcykgIT09ICdvYmplY3QnIHx8IGlzRW1wdHkoZGVwZW5kZW5jaWVzKSkge1xyXG4gICAgICByZXR1cm4gSnNvblZhbGlkYXRvcnMubnVsbFZhbGlkYXRvcjtcclxuICAgIH1cclxuICAgIHJldHVybiAoY29udHJvbDogQWJzdHJhY3RDb250cm9sLCBpbnZlcnQgPSBmYWxzZSk6IFZhbGlkYXRpb25FcnJvcnN8bnVsbCA9PiB7XHJcbiAgICAgIGlmIChpc0VtcHR5KGNvbnRyb2wudmFsdWUpKSB7IHJldHVybiBudWxsOyB9XHJcbiAgICAgIGNvbnN0IGFsbEVycm9ycyA9IF9tZXJnZU9iamVjdHMoXHJcbiAgICAgICAgZm9yRWFjaENvcHkoZGVwZW5kZW5jaWVzLCAodmFsdWUsIHJlcXVpcmluZ0ZpZWxkKSA9PiB7XHJcbiAgICAgICAgICBpZiAoIWhhc1ZhbHVlKGNvbnRyb2wudmFsdWVbcmVxdWlyaW5nRmllbGRdKSkgeyByZXR1cm4gbnVsbDsgfVxyXG4gICAgICAgICAgbGV0IHJlcXVpcmluZ0ZpZWxkRXJyb3JzOiBWYWxpZGF0aW9uRXJyb3JzID0geyB9O1xyXG4gICAgICAgICAgbGV0IHJlcXVpcmVkRmllbGRzOiBzdHJpbmdbXTtcclxuICAgICAgICAgIGxldCBwcm9wZXJ0aWVzOiBWYWxpZGF0aW9uRXJyb3JzID0geyB9O1xyXG4gICAgICAgICAgaWYgKGdldFR5cGUoZGVwZW5kZW5jaWVzW3JlcXVpcmluZ0ZpZWxkXSkgPT09ICdhcnJheScpIHtcclxuICAgICAgICAgICAgcmVxdWlyZWRGaWVsZHMgPSBkZXBlbmRlbmNpZXNbcmVxdWlyaW5nRmllbGRdO1xyXG4gICAgICAgICAgfSBlbHNlIGlmIChnZXRUeXBlKGRlcGVuZGVuY2llc1tyZXF1aXJpbmdGaWVsZF0pID09PSAnb2JqZWN0Jykge1xyXG4gICAgICAgICAgICByZXF1aXJlZEZpZWxkcyA9IGRlcGVuZGVuY2llc1tyZXF1aXJpbmdGaWVsZF1bJ3JlcXVpcmVkJ10gfHwgW107XHJcbiAgICAgICAgICAgIHByb3BlcnRpZXMgPSBkZXBlbmRlbmNpZXNbcmVxdWlyaW5nRmllbGRdWydwcm9wZXJ0aWVzJ10gfHwgeyB9O1xyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIC8vIFZhbGlkYXRlIHByb3BlcnR5IGRlcGVuZGVuY2llc1xyXG4gICAgICAgICAgZm9yIChjb25zdCByZXF1aXJlZEZpZWxkIG9mIHJlcXVpcmVkRmllbGRzKSB7XHJcbiAgICAgICAgICAgIGlmICh4b3IoIWhhc1ZhbHVlKGNvbnRyb2wudmFsdWVbcmVxdWlyZWRGaWVsZF0pLCBpbnZlcnQpKSB7XHJcbiAgICAgICAgICAgICAgcmVxdWlyaW5nRmllbGRFcnJvcnNbcmVxdWlyZWRGaWVsZF0gPSB7ICdyZXF1aXJlZCc6IHRydWUgfTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIC8vIFZhbGlkYXRlIHNjaGVtYSBkZXBlbmRlbmNpZXNcclxuICAgICAgICAgIHJlcXVpcmluZ0ZpZWxkRXJyb3JzID0gX21lcmdlT2JqZWN0cyhyZXF1aXJpbmdGaWVsZEVycm9ycyxcclxuICAgICAgICAgICAgZm9yRWFjaENvcHkocHJvcGVydGllcywgKHJlcXVpcmVtZW50cywgcmVxdWlyZWRGaWVsZCkgPT4ge1xyXG4gICAgICAgICAgICAgIGNvbnN0IHJlcXVpcmVkRmllbGRFcnJvcnMgPSBfbWVyZ2VPYmplY3RzKFxyXG4gICAgICAgICAgICAgICAgZm9yRWFjaENvcHkocmVxdWlyZW1lbnRzLCAocmVxdWlyZW1lbnQsIHBhcmFtZXRlcikgPT4ge1xyXG4gICAgICAgICAgICAgICAgICBsZXQgdmFsaWRhdG9yOiBJVmFsaWRhdG9yRm4gPSBudWxsO1xyXG4gICAgICAgICAgICAgICAgICBpZiAocmVxdWlyZW1lbnQgPT09ICdtYXhpbXVtJyB8fCByZXF1aXJlbWVudCA9PT0gJ21pbmltdW0nKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZXhjbHVzaXZlID0gISFyZXF1aXJlbWVudHNbJ2V4Y2x1c2l2ZU0nICsgcmVxdWlyZW1lbnQuc2xpY2UoMSldO1xyXG4gICAgICAgICAgICAgICAgICAgIHZhbGlkYXRvciA9IEpzb25WYWxpZGF0b3JzW3JlcXVpcmVtZW50XShwYXJhbWV0ZXIsIGV4Y2x1c2l2ZSk7XHJcbiAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIEpzb25WYWxpZGF0b3JzW3JlcXVpcmVtZW50XSA9PT0gJ2Z1bmN0aW9uJykge1xyXG4gICAgICAgICAgICAgICAgICAgIHZhbGlkYXRvciA9IEpzb25WYWxpZGF0b3JzW3JlcXVpcmVtZW50XShwYXJhbWV0ZXIpO1xyXG4gICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgIHJldHVybiAhaXNEZWZpbmVkKHZhbGlkYXRvcikgP1xyXG4gICAgICAgICAgICAgICAgICAgIG51bGwgOiB2YWxpZGF0b3IoY29udHJvbC52YWx1ZVtyZXF1aXJlZEZpZWxkXSk7XHJcbiAgICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgcmV0dXJuIGlzRW1wdHkocmVxdWlyZWRGaWVsZEVycm9ycykgP1xyXG4gICAgICAgICAgICAgICAgbnVsbCA6IHsgW3JlcXVpcmVkRmllbGRdOiByZXF1aXJlZEZpZWxkRXJyb3JzIH07XHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICApO1xyXG4gICAgICAgICAgcmV0dXJuIGlzRW1wdHkocmVxdWlyaW5nRmllbGRFcnJvcnMpID9cclxuICAgICAgICAgICAgbnVsbCA6IHsgW3JlcXVpcmluZ0ZpZWxkXTogcmVxdWlyaW5nRmllbGRFcnJvcnMgfTtcclxuICAgICAgICB9KVxyXG4gICAgICApO1xyXG4gICAgICByZXR1cm4gaXNFbXB0eShhbGxFcnJvcnMpID8gbnVsbCA6IGFsbEVycm9ycztcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAnbWluSXRlbXMnIHZhbGlkYXRvclxyXG4gICAqXHJcbiAgICogUmVxdWlyZXMgYSBmb3JtIGFycmF5IHRvIGhhdmUgYSBtaW5pbXVtIG51bWJlciBvZiB2YWx1ZXMuXHJcbiAgICpcclxuICAgKiAvLyB7bnVtYmVyfSBtaW5pbXVtSXRlbXMgLSBtaW5pbXVtIG51bWJlciBvZiBpdGVtcyBhbGxvd2VkXHJcbiAgICogLy8ge0lWYWxpZGF0b3JGbn1cclxuICAgKi9cclxuICBzdGF0aWMgbWluSXRlbXMobWluaW11bUl0ZW1zOiBudW1iZXIpOiBJVmFsaWRhdG9yRm4ge1xyXG4gICAgaWYgKCFoYXNWYWx1ZShtaW5pbXVtSXRlbXMpKSB7IHJldHVybiBKc29uVmFsaWRhdG9ycy5udWxsVmFsaWRhdG9yOyB9XHJcbiAgICByZXR1cm4gKGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCwgaW52ZXJ0ID0gZmFsc2UpOiBWYWxpZGF0aW9uRXJyb3JzfG51bGwgPT4ge1xyXG4gICAgICBpZiAoaXNFbXB0eShjb250cm9sLnZhbHVlKSkgeyByZXR1cm4gbnVsbDsgfVxyXG4gICAgICBjb25zdCBjdXJyZW50SXRlbXMgPSBpc0FycmF5KGNvbnRyb2wudmFsdWUpID8gY29udHJvbC52YWx1ZS5sZW5ndGggOiAwO1xyXG4gICAgICBjb25zdCBpc1ZhbGlkID0gY3VycmVudEl0ZW1zID49IG1pbmltdW1JdGVtcztcclxuICAgICAgcmV0dXJuIHhvcihpc1ZhbGlkLCBpbnZlcnQpID9cclxuICAgICAgICBudWxsIDogeyAnbWluSXRlbXMnOiB7IG1pbmltdW1JdGVtcywgY3VycmVudEl0ZW1zIH0gfTtcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAnbWF4SXRlbXMnIHZhbGlkYXRvclxyXG4gICAqXHJcbiAgICogUmVxdWlyZXMgYSBmb3JtIGFycmF5IHRvIGhhdmUgYSBtYXhpbXVtIG51bWJlciBvZiB2YWx1ZXMuXHJcbiAgICpcclxuICAgKiAvLyB7bnVtYmVyfSBtYXhpbXVtSXRlbXMgLSBtYXhpbXVtIG51bWJlciBvZiBpdGVtcyBhbGxvd2VkXHJcbiAgICogLy8ge0lWYWxpZGF0b3JGbn1cclxuICAgKi9cclxuICBzdGF0aWMgbWF4SXRlbXMobWF4aW11bUl0ZW1zOiBudW1iZXIpOiBJVmFsaWRhdG9yRm4ge1xyXG4gICAgaWYgKCFoYXNWYWx1ZShtYXhpbXVtSXRlbXMpKSB7IHJldHVybiBKc29uVmFsaWRhdG9ycy5udWxsVmFsaWRhdG9yOyB9XHJcbiAgICByZXR1cm4gKGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCwgaW52ZXJ0ID0gZmFsc2UpOiBWYWxpZGF0aW9uRXJyb3JzfG51bGwgPT4ge1xyXG4gICAgICBjb25zdCBjdXJyZW50SXRlbXMgPSBpc0FycmF5KGNvbnRyb2wudmFsdWUpID8gY29udHJvbC52YWx1ZS5sZW5ndGggOiAwO1xyXG4gICAgICBjb25zdCBpc1ZhbGlkID0gY3VycmVudEl0ZW1zIDw9IG1heGltdW1JdGVtcztcclxuICAgICAgcmV0dXJuIHhvcihpc1ZhbGlkLCBpbnZlcnQpID9cclxuICAgICAgICBudWxsIDogeyAnbWF4SXRlbXMnOiB7IG1heGltdW1JdGVtcywgY3VycmVudEl0ZW1zIH0gfTtcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAndW5pcXVlSXRlbXMnIHZhbGlkYXRvclxyXG4gICAqXHJcbiAgICogUmVxdWlyZXMgdmFsdWVzIGluIGEgZm9ybSBhcnJheSB0byBiZSB1bmlxdWUuXHJcbiAgICpcclxuICAgKiAvLyB7Ym9vbGVhbiA9IHRydWV9IHVuaXF1ZT8gLSB0cnVlIHRvIHZhbGlkYXRlLCBmYWxzZSB0byBkaXNhYmxlXHJcbiAgICogLy8ge0lWYWxpZGF0b3JGbn1cclxuICAgKi9cclxuICBzdGF0aWMgdW5pcXVlSXRlbXModW5pcXVlID0gdHJ1ZSk6IElWYWxpZGF0b3JGbiB7XHJcbiAgICBpZiAoIXVuaXF1ZSkgeyByZXR1cm4gSnNvblZhbGlkYXRvcnMubnVsbFZhbGlkYXRvcjsgfVxyXG4gICAgcmV0dXJuIChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wsIGludmVydCA9IGZhbHNlKTogVmFsaWRhdGlvbkVycm9yc3xudWxsID0+IHtcclxuICAgICAgaWYgKGlzRW1wdHkoY29udHJvbC52YWx1ZSkpIHsgcmV0dXJuIG51bGw7IH1cclxuICAgICAgY29uc3Qgc29ydGVkOiBhbnlbXSA9IGNvbnRyb2wudmFsdWUuc2xpY2UoKS5zb3J0KCk7XHJcbiAgICAgIGNvbnN0IGR1cGxpY2F0ZUl0ZW1zID0gW107XHJcbiAgICAgIGZvciAobGV0IGkgPSAxOyBpIDwgc29ydGVkLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgaWYgKHNvcnRlZFtpIC0gMV0gPT09IHNvcnRlZFtpXSAmJiBkdXBsaWNhdGVJdGVtcy5pbmNsdWRlcyhzb3J0ZWRbaV0pKSB7XHJcbiAgICAgICAgICBkdXBsaWNhdGVJdGVtcy5wdXNoKHNvcnRlZFtpXSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICAgIGNvbnN0IGlzVmFsaWQgPSAhZHVwbGljYXRlSXRlbXMubGVuZ3RoO1xyXG4gICAgICByZXR1cm4geG9yKGlzVmFsaWQsIGludmVydCkgP1xyXG4gICAgICAgIG51bGwgOiB7ICd1bmlxdWVJdGVtcyc6IHsgZHVwbGljYXRlSXRlbXMgfSB9O1xyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqICdjb250YWlucycgdmFsaWRhdG9yXHJcbiAgICpcclxuICAgKiBUT0RPOiBDb21wbGV0ZSB0aGlzIHZhbGlkYXRvclxyXG4gICAqXHJcbiAgICogUmVxdWlyZXMgdmFsdWVzIGluIGEgZm9ybSBhcnJheSB0byBiZSB1bmlxdWUuXHJcbiAgICpcclxuICAgKiAvLyB7Ym9vbGVhbiA9IHRydWV9IHVuaXF1ZT8gLSB0cnVlIHRvIHZhbGlkYXRlLCBmYWxzZSB0byBkaXNhYmxlXHJcbiAgICogLy8ge0lWYWxpZGF0b3JGbn1cclxuICAgKi9cclxuICBzdGF0aWMgY29udGFpbnMocmVxdWlyZWRJdGVtID0gdHJ1ZSk6IElWYWxpZGF0b3JGbiB7XHJcbiAgICBpZiAoIXJlcXVpcmVkSXRlbSkgeyByZXR1cm4gSnNvblZhbGlkYXRvcnMubnVsbFZhbGlkYXRvcjsgfVxyXG4gICAgcmV0dXJuIChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wsIGludmVydCA9IGZhbHNlKTogVmFsaWRhdGlvbkVycm9yc3xudWxsID0+IHtcclxuICAgICAgaWYgKGlzRW1wdHkoY29udHJvbC52YWx1ZSkgfHwgIWlzQXJyYXkoY29udHJvbC52YWx1ZSkpIHsgcmV0dXJuIG51bGw7IH1cclxuICAgICAgY29uc3QgY3VycmVudEl0ZW1zID0gY29udHJvbC52YWx1ZTtcclxuICAgICAgLy8gY29uc3QgaXNWYWxpZCA9IGN1cnJlbnRJdGVtcy5zb21lKGl0ZW0gPT5cclxuICAgICAgLy9cclxuICAgICAgLy8gKTtcclxuICAgICAgY29uc3QgaXNWYWxpZCA9IHRydWU7XHJcbiAgICAgIHJldHVybiB4b3IoaXNWYWxpZCwgaW52ZXJ0KSA/XHJcbiAgICAgICAgbnVsbCA6IHsgJ2NvbnRhaW5zJzogeyByZXF1aXJlZEl0ZW0sIGN1cnJlbnRJdGVtcyB9IH07XHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogTm8tb3AgdmFsaWRhdG9yLiBJbmNsdWRlZCBmb3IgYmFja3dhcmQgY29tcGF0aWJpbGl0eS5cclxuICAgKi9cclxuICBzdGF0aWMgbnVsbFZhbGlkYXRvcihjb250cm9sOiBBYnN0cmFjdENvbnRyb2wpOiBWYWxpZGF0aW9uRXJyb3JzfG51bGwge1xyXG4gICAgcmV0dXJuIG51bGw7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBWYWxpZGF0b3IgdHJhbnNmb3JtYXRpb24gZnVuY3Rpb25zOlxyXG4gICAqIGNvbXBvc2VBbnlPZiwgY29tcG9zZU9uZU9mLCBjb21wb3NlQWxsT2YsIGNvbXBvc2VOb3QsXHJcbiAgICogY29tcG9zZSwgY29tcG9zZUFzeW5jXHJcbiAgICpcclxuICAgKiBUT0RPOiBBZGQgY29tcG9zZUFueU9mQXN5bmMsIGNvbXBvc2VPbmVPZkFzeW5jLFxyXG4gICAqICAgICAgICAgICBjb21wb3NlQWxsT2ZBc3luYywgY29tcG9zZU5vdEFzeW5jXHJcbiAgICovXHJcblxyXG4gIC8qKlxyXG4gICAqICdjb21wb3NlQW55T2YnIHZhbGlkYXRvciBjb21iaW5hdGlvbiBmdW5jdGlvblxyXG4gICAqXHJcbiAgICogQWNjZXB0cyBhbiBhcnJheSBvZiB2YWxpZGF0b3JzIGFuZCByZXR1cm5zIGEgc2luZ2xlIHZhbGlkYXRvciB0aGF0XHJcbiAgICogZXZhbHVhdGVzIHRvIHZhbGlkIGlmIGFueSBvbmUgb3IgbW9yZSBvZiB0aGUgc3VibWl0dGVkIHZhbGlkYXRvcnMgYXJlXHJcbiAgICogdmFsaWQuIElmIGV2ZXJ5IHZhbGlkYXRvciBpcyBpbnZhbGlkLCBpdCByZXR1cm5zIGNvbWJpbmVkIGVycm9ycyBmcm9tXHJcbiAgICogYWxsIHZhbGlkYXRvcnMuXHJcbiAgICpcclxuICAgKiAvLyB7SVZhbGlkYXRvckZuW119IHZhbGlkYXRvcnMgLSBhcnJheSBvZiB2YWxpZGF0b3JzIHRvIGNvbWJpbmVcclxuICAgKiAvLyB7SVZhbGlkYXRvckZufSAtIHNpbmdsZSBjb21iaW5lZCB2YWxpZGF0b3IgZnVuY3Rpb25cclxuICAgKi9cclxuICBzdGF0aWMgY29tcG9zZUFueU9mKHZhbGlkYXRvcnM6IElWYWxpZGF0b3JGbltdKTogSVZhbGlkYXRvckZuIHtcclxuICAgIGlmICghdmFsaWRhdG9ycykgeyByZXR1cm4gbnVsbDsgfVxyXG4gICAgY29uc3QgcHJlc2VudFZhbGlkYXRvcnMgPSB2YWxpZGF0b3JzLmZpbHRlcihpc0RlZmluZWQpO1xyXG4gICAgaWYgKHByZXNlbnRWYWxpZGF0b3JzLmxlbmd0aCA9PT0gMCkgeyByZXR1cm4gbnVsbDsgfVxyXG4gICAgcmV0dXJuIChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wsIGludmVydCA9IGZhbHNlKTogVmFsaWRhdGlvbkVycm9yc3xudWxsID0+IHtcclxuICAgICAgY29uc3QgYXJyYXlPZkVycm9ycyA9XHJcbiAgICAgICAgX2V4ZWN1dGVWYWxpZGF0b3JzKGNvbnRyb2wsIHByZXNlbnRWYWxpZGF0b3JzLCBpbnZlcnQpLmZpbHRlcihpc0RlZmluZWQpO1xyXG4gICAgICBjb25zdCBpc1ZhbGlkID0gdmFsaWRhdG9ycy5sZW5ndGggPiBhcnJheU9mRXJyb3JzLmxlbmd0aDtcclxuICAgICAgcmV0dXJuIHhvcihpc1ZhbGlkLCBpbnZlcnQpID9cclxuICAgICAgICBudWxsIDogX21lcmdlT2JqZWN0cyguLi5hcnJheU9mRXJyb3JzLCB7ICdhbnlPZic6ICFpbnZlcnQgfSk7XHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ2NvbXBvc2VPbmVPZicgdmFsaWRhdG9yIGNvbWJpbmF0aW9uIGZ1bmN0aW9uXHJcbiAgICpcclxuICAgKiBBY2NlcHRzIGFuIGFycmF5IG9mIHZhbGlkYXRvcnMgYW5kIHJldHVybnMgYSBzaW5nbGUgdmFsaWRhdG9yIHRoYXRcclxuICAgKiBldmFsdWF0ZXMgdG8gdmFsaWQgb25seSBpZiBleGFjdGx5IG9uZSBvZiB0aGUgc3VibWl0dGVkIHZhbGlkYXRvcnNcclxuICAgKiBpcyB2YWxpZC4gT3RoZXJ3aXNlIHJldHVybnMgY29tYmluZWQgaW5mb3JtYXRpb24gZnJvbSBhbGwgdmFsaWRhdG9ycyxcclxuICAgKiBib3RoIHZhbGlkIGFuZCBpbnZhbGlkLlxyXG4gICAqXHJcbiAgICogLy8ge0lWYWxpZGF0b3JGbltdfSB2YWxpZGF0b3JzIC0gYXJyYXkgb2YgdmFsaWRhdG9ycyB0byBjb21iaW5lXHJcbiAgICogLy8ge0lWYWxpZGF0b3JGbn0gLSBzaW5nbGUgY29tYmluZWQgdmFsaWRhdG9yIGZ1bmN0aW9uXHJcbiAgICovXHJcbiAgc3RhdGljIGNvbXBvc2VPbmVPZih2YWxpZGF0b3JzOiBJVmFsaWRhdG9yRm5bXSk6IElWYWxpZGF0b3JGbiB7XHJcbiAgICBpZiAoIXZhbGlkYXRvcnMpIHsgcmV0dXJuIG51bGw7IH1cclxuICAgIGNvbnN0IHByZXNlbnRWYWxpZGF0b3JzID0gdmFsaWRhdG9ycy5maWx0ZXIoaXNEZWZpbmVkKTtcclxuICAgIGlmIChwcmVzZW50VmFsaWRhdG9ycy5sZW5ndGggPT09IDApIHsgcmV0dXJuIG51bGw7IH1cclxuICAgIHJldHVybiAoY29udHJvbDogQWJzdHJhY3RDb250cm9sLCBpbnZlcnQgPSBmYWxzZSk6IFZhbGlkYXRpb25FcnJvcnN8bnVsbCA9PiB7XHJcbiAgICAgIGNvbnN0IGFycmF5T2ZFcnJvcnMgPVxyXG4gICAgICAgIF9leGVjdXRlVmFsaWRhdG9ycyhjb250cm9sLCBwcmVzZW50VmFsaWRhdG9ycyk7XHJcbiAgICAgIGNvbnN0IHZhbGlkQ29udHJvbHMgPVxyXG4gICAgICAgIHZhbGlkYXRvcnMubGVuZ3RoIC0gYXJyYXlPZkVycm9ycy5maWx0ZXIoaXNEZWZpbmVkKS5sZW5ndGg7XHJcbiAgICAgIGNvbnN0IGlzVmFsaWQgPSB2YWxpZENvbnRyb2xzID09PSAxO1xyXG4gICAgICBpZiAoeG9yKGlzVmFsaWQsIGludmVydCkpIHsgcmV0dXJuIG51bGw7IH1cclxuICAgICAgY29uc3QgYXJyYXlPZlZhbGlkcyA9XHJcbiAgICAgICAgX2V4ZWN1dGVWYWxpZGF0b3JzKGNvbnRyb2wsIHByZXNlbnRWYWxpZGF0b3JzLCBpbnZlcnQpO1xyXG4gICAgICByZXR1cm4gX21lcmdlT2JqZWN0cyguLi5hcnJheU9mRXJyb3JzLCAuLi5hcnJheU9mVmFsaWRzLCB7ICdvbmVPZic6ICFpbnZlcnQgfSk7XHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ2NvbXBvc2VBbGxPZicgdmFsaWRhdG9yIGNvbWJpbmF0aW9uIGZ1bmN0aW9uXHJcbiAgICpcclxuICAgKiBBY2NlcHRzIGFuIGFycmF5IG9mIHZhbGlkYXRvcnMgYW5kIHJldHVybnMgYSBzaW5nbGUgdmFsaWRhdG9yIHRoYXRcclxuICAgKiBldmFsdWF0ZXMgdG8gdmFsaWQgb25seSBpZiBhbGwgdGhlIHN1Ym1pdHRlZCB2YWxpZGF0b3JzIGFyZSBpbmRpdmlkdWFsbHlcclxuICAgKiB2YWxpZC4gT3RoZXJ3aXNlIGl0IHJldHVybnMgY29tYmluZWQgZXJyb3JzIGZyb20gYWxsIGludmFsaWQgdmFsaWRhdG9ycy5cclxuICAgKlxyXG4gICAqIC8vIHtJVmFsaWRhdG9yRm5bXX0gdmFsaWRhdG9ycyAtIGFycmF5IG9mIHZhbGlkYXRvcnMgdG8gY29tYmluZVxyXG4gICAqIC8vIHtJVmFsaWRhdG9yRm59IC0gc2luZ2xlIGNvbWJpbmVkIHZhbGlkYXRvciBmdW5jdGlvblxyXG4gICAqL1xyXG4gIHN0YXRpYyBjb21wb3NlQWxsT2YodmFsaWRhdG9yczogSVZhbGlkYXRvckZuW10pOiBJVmFsaWRhdG9yRm4ge1xyXG4gICAgaWYgKCF2YWxpZGF0b3JzKSB7IHJldHVybiBudWxsOyB9XHJcbiAgICBjb25zdCBwcmVzZW50VmFsaWRhdG9ycyA9IHZhbGlkYXRvcnMuZmlsdGVyKGlzRGVmaW5lZCk7XHJcbiAgICBpZiAocHJlc2VudFZhbGlkYXRvcnMubGVuZ3RoID09PSAwKSB7IHJldHVybiBudWxsOyB9XHJcbiAgICByZXR1cm4gKGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCwgaW52ZXJ0ID0gZmFsc2UpOiBWYWxpZGF0aW9uRXJyb3JzfG51bGwgPT4ge1xyXG4gICAgICBjb25zdCBjb21iaW5lZEVycm9ycyA9IF9tZXJnZUVycm9ycyhcclxuICAgICAgICBfZXhlY3V0ZVZhbGlkYXRvcnMoY29udHJvbCwgcHJlc2VudFZhbGlkYXRvcnMsIGludmVydClcclxuICAgICAgKTtcclxuICAgICAgY29uc3QgaXNWYWxpZCA9IGNvbWJpbmVkRXJyb3JzID09PSBudWxsO1xyXG4gICAgICByZXR1cm4gKHhvcihpc1ZhbGlkLCBpbnZlcnQpKSA/XHJcbiAgICAgICAgbnVsbCA6IF9tZXJnZU9iamVjdHMoY29tYmluZWRFcnJvcnMsIHsgJ2FsbE9mJzogIWludmVydCB9KTtcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAnY29tcG9zZU5vdCcgdmFsaWRhdG9yIGludmVyc2lvbiBmdW5jdGlvblxyXG4gICAqXHJcbiAgICogQWNjZXB0cyBhIHNpbmdsZSB2YWxpZGF0b3IgZnVuY3Rpb24gYW5kIGludmVydHMgaXRzIHJlc3VsdC5cclxuICAgKiBSZXR1cm5zIHZhbGlkIGlmIHRoZSBzdWJtaXR0ZWQgdmFsaWRhdG9yIGlzIGludmFsaWQsIGFuZFxyXG4gICAqIHJldHVybnMgaW52YWxpZCBpZiB0aGUgc3VibWl0dGVkIHZhbGlkYXRvciBpcyB2YWxpZC5cclxuICAgKiAoTm90ZTogdGhpcyBmdW5jdGlvbiBjYW4gaXRzZWxmIGJlIGludmVydGVkXHJcbiAgICogICAtIGUuZy4gY29tcG9zZU5vdChjb21wb3NlTm90KHZhbGlkYXRvcikpIC1cclxuICAgKiAgIGJ1dCB0aGlzIGNhbiBiZSBjb25mdXNpbmcgYW5kIGlzIHRoZXJlZm9yZSBub3QgcmVjb21tZW5kZWQuKVxyXG4gICAqXHJcbiAgICogLy8ge0lWYWxpZGF0b3JGbltdfSB2YWxpZGF0b3JzIC0gdmFsaWRhdG9yKHMpIHRvIGludmVydFxyXG4gICAqIC8vIHtJVmFsaWRhdG9yRm59IC0gbmV3IHZhbGlkYXRvciBmdW5jdGlvbiB0aGF0IHJldHVybnMgb3Bwb3NpdGUgcmVzdWx0XHJcbiAgICovXHJcbiAgc3RhdGljIGNvbXBvc2VOb3QodmFsaWRhdG9yOiBJVmFsaWRhdG9yRm4pOiBJVmFsaWRhdG9yRm4ge1xyXG4gICAgaWYgKCF2YWxpZGF0b3IpIHsgcmV0dXJuIG51bGw7IH1cclxuICAgIHJldHVybiAoY29udHJvbDogQWJzdHJhY3RDb250cm9sLCBpbnZlcnQgPSBmYWxzZSk6IFZhbGlkYXRpb25FcnJvcnN8bnVsbCA9PiB7XHJcbiAgICAgIGlmIChpc0VtcHR5KGNvbnRyb2wudmFsdWUpKSB7IHJldHVybiBudWxsOyB9XHJcbiAgICAgIGNvbnN0IGVycm9yID0gdmFsaWRhdG9yKGNvbnRyb2wsICFpbnZlcnQpO1xyXG4gICAgICBjb25zdCBpc1ZhbGlkID0gZXJyb3IgPT09IG51bGw7XHJcbiAgICAgIHJldHVybiAoeG9yKGlzVmFsaWQsIGludmVydCkpID9cclxuICAgICAgICBudWxsIDogX21lcmdlT2JqZWN0cyhlcnJvciwgeyAnbm90JzogIWludmVydCB9KTtcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAnY29tcG9zZScgdmFsaWRhdG9yIGNvbWJpbmF0aW9uIGZ1bmN0aW9uXHJcbiAgICpcclxuICAgKiAvLyB7SVZhbGlkYXRvckZuW119IHZhbGlkYXRvcnMgLSBhcnJheSBvZiB2YWxpZGF0b3JzIHRvIGNvbWJpbmVcclxuICAgKiAvLyB7SVZhbGlkYXRvckZufSAtIHNpbmdsZSBjb21iaW5lZCB2YWxpZGF0b3IgZnVuY3Rpb25cclxuICAgKi9cclxuICBzdGF0aWMgY29tcG9zZSh2YWxpZGF0b3JzOiBJVmFsaWRhdG9yRm5bXSk6IElWYWxpZGF0b3JGbiB7XHJcbiAgICBpZiAoIXZhbGlkYXRvcnMpIHsgcmV0dXJuIG51bGw7IH1cclxuICAgIGNvbnN0IHByZXNlbnRWYWxpZGF0b3JzID0gdmFsaWRhdG9ycy5maWx0ZXIoaXNEZWZpbmVkKTtcclxuICAgIGlmIChwcmVzZW50VmFsaWRhdG9ycy5sZW5ndGggPT09IDApIHsgcmV0dXJuIG51bGw7IH1cclxuICAgIHJldHVybiAoY29udHJvbDogQWJzdHJhY3RDb250cm9sLCBpbnZlcnQgPSBmYWxzZSk6IFZhbGlkYXRpb25FcnJvcnN8bnVsbCA9PlxyXG4gICAgICBfbWVyZ2VFcnJvcnMoX2V4ZWN1dGVWYWxpZGF0b3JzKGNvbnRyb2wsIHByZXNlbnRWYWxpZGF0b3JzLCBpbnZlcnQpKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqICdjb21wb3NlQXN5bmMnIGFzeW5jIHZhbGlkYXRvciBjb21iaW5hdGlvbiBmdW5jdGlvblxyXG4gICAqXHJcbiAgICogLy8ge0FzeW5jSVZhbGlkYXRvckZuW119IGFzeW5jIHZhbGlkYXRvcnMgLSBhcnJheSBvZiBhc3luYyB2YWxpZGF0b3JzXHJcbiAgICogLy8ge0FzeW5jSVZhbGlkYXRvckZufSAtIHNpbmdsZSBjb21iaW5lZCBhc3luYyB2YWxpZGF0b3IgZnVuY3Rpb25cclxuICAgKi9cclxuICBzdGF0aWMgY29tcG9zZUFzeW5jKHZhbGlkYXRvcnM6IEFzeW5jSVZhbGlkYXRvckZuW10pOiBBc3luY0lWYWxpZGF0b3JGbiB7XHJcbiAgICBpZiAoIXZhbGlkYXRvcnMpIHsgcmV0dXJuIG51bGw7IH1cclxuICAgIGNvbnN0IHByZXNlbnRWYWxpZGF0b3JzID0gdmFsaWRhdG9ycy5maWx0ZXIoaXNEZWZpbmVkKTtcclxuICAgIGlmIChwcmVzZW50VmFsaWRhdG9ycy5sZW5ndGggPT09IDApIHsgcmV0dXJuIG51bGw7IH1cclxuICAgIHJldHVybiAoY29udHJvbDogQWJzdHJhY3RDb250cm9sKSA9PiB7XHJcbiAgICAgIGNvbnN0IG9ic2VydmFibGVzID1cclxuICAgICAgICBfZXhlY3V0ZUFzeW5jVmFsaWRhdG9ycyhjb250cm9sLCBwcmVzZW50VmFsaWRhdG9ycykubWFwKHRvT2JzZXJ2YWJsZSk7XHJcbiAgICAgIHJldHVybiBtYXAuY2FsbChmb3JrSm9pbihvYnNlcnZhYmxlcyksIF9tZXJnZUVycm9ycyk7XHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgLy8gQWRkaXRpb25hbCBhbmd1bGFyIHZhbGlkYXRvcnMgKG5vdCB1c2VkIGJ5IEFuZ3VhbHIgSlNPTiBTY2hlbWEgRm9ybSlcclxuICAvLyBGcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9hbmd1bGFyL2FuZ3VsYXIvYmxvYi9tYXN0ZXIvcGFja2FnZXMvZm9ybXMvc3JjL3ZhbGlkYXRvcnMudHNcclxuXHJcbiAgLyoqXHJcbiAgICogVmFsaWRhdG9yIHRoYXQgcmVxdWlyZXMgY29udHJvbHMgdG8gaGF2ZSBhIHZhbHVlIGdyZWF0ZXIgdGhhbiBhIG51bWJlci5cclxuICAgKi9cclxuICBzdGF0aWMgbWluKG1pbjogbnVtYmVyKTogVmFsaWRhdG9yRm4ge1xyXG4gICAgaWYgKCFoYXNWYWx1ZShtaW4pKSB7IHJldHVybiBKc29uVmFsaWRhdG9ycy5udWxsVmFsaWRhdG9yOyB9XHJcbiAgICByZXR1cm4gKGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCk6IFZhbGlkYXRpb25FcnJvcnN8bnVsbCA9PiB7XHJcbiAgICAgIC8vIGRvbid0IHZhbGlkYXRlIGVtcHR5IHZhbHVlcyB0byBhbGxvdyBvcHRpb25hbCBjb250cm9sc1xyXG4gICAgICBpZiAoaXNFbXB0eShjb250cm9sLnZhbHVlKSB8fCBpc0VtcHR5KG1pbikpIHsgcmV0dXJuIG51bGw7IH1cclxuICAgICAgY29uc3QgdmFsdWUgPSBwYXJzZUZsb2F0KGNvbnRyb2wudmFsdWUpO1xyXG4gICAgICBjb25zdCBhY3R1YWwgPSBjb250cm9sLnZhbHVlO1xyXG4gICAgICAvLyBDb250cm9scyB3aXRoIE5hTiB2YWx1ZXMgYWZ0ZXIgcGFyc2luZyBzaG91bGQgYmUgdHJlYXRlZCBhcyBub3QgaGF2aW5nIGFcclxuICAgICAgLy8gbWluaW11bSwgcGVyIHRoZSBIVE1MIGZvcm1zIHNwZWM6IGh0dHBzOi8vd3d3LnczLm9yZy9UUi9odG1sNS9mb3Jtcy5odG1sI2F0dHItaW5wdXQtbWluXHJcbiAgICAgIHJldHVybiBpc05hTih2YWx1ZSkgfHwgdmFsdWUgPj0gbWluID8gbnVsbCA6IHsgJ21pbic6IHsgbWluLCBhY3R1YWwgfSB9O1xyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFZhbGlkYXRvciB0aGF0IHJlcXVpcmVzIGNvbnRyb2xzIHRvIGhhdmUgYSB2YWx1ZSBsZXNzIHRoYW4gYSBudW1iZXIuXHJcbiAgICovXHJcbiAgc3RhdGljIG1heChtYXg6IG51bWJlcik6IFZhbGlkYXRvckZuIHtcclxuICAgIGlmICghaGFzVmFsdWUobWF4KSkgeyByZXR1cm4gSnNvblZhbGlkYXRvcnMubnVsbFZhbGlkYXRvcjsgfVxyXG4gICAgcmV0dXJuIChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wpOiBWYWxpZGF0aW9uRXJyb3JzfG51bGwgPT4ge1xyXG4gICAgICAvLyBkb24ndCB2YWxpZGF0ZSBlbXB0eSB2YWx1ZXMgdG8gYWxsb3cgb3B0aW9uYWwgY29udHJvbHNcclxuICAgICAgaWYgKGlzRW1wdHkoY29udHJvbC52YWx1ZSkgfHwgaXNFbXB0eShtYXgpKSB7IHJldHVybiBudWxsOyB9XHJcbiAgICAgIGNvbnN0IHZhbHVlID0gcGFyc2VGbG9hdChjb250cm9sLnZhbHVlKTtcclxuICAgICAgY29uc3QgYWN0dWFsID0gY29udHJvbC52YWx1ZTtcclxuICAgICAgLy8gQ29udHJvbHMgd2l0aCBOYU4gdmFsdWVzIGFmdGVyIHBhcnNpbmcgc2hvdWxkIGJlIHRyZWF0ZWQgYXMgbm90IGhhdmluZyBhXHJcbiAgICAgIC8vIG1heGltdW0sIHBlciB0aGUgSFRNTCBmb3JtcyBzcGVjOiBodHRwczovL3d3dy53My5vcmcvVFIvaHRtbDUvZm9ybXMuaHRtbCNhdHRyLWlucHV0LW1heFxyXG4gICAgICByZXR1cm4gaXNOYU4odmFsdWUpIHx8IHZhbHVlIDw9IG1heCA/IG51bGwgOiB7ICdtYXgnOiB7IG1heCwgYWN0dWFsIH0gfTtcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBWYWxpZGF0b3IgdGhhdCByZXF1aXJlcyBjb250cm9sIHZhbHVlIHRvIGJlIHRydWUuXHJcbiAgICovXHJcbiAgc3RhdGljIHJlcXVpcmVkVHJ1ZShjb250cm9sOiBBYnN0cmFjdENvbnRyb2wpOiBWYWxpZGF0aW9uRXJyb3JzfG51bGwge1xyXG4gICAgaWYgKCFjb250cm9sKSB7IHJldHVybiBKc29uVmFsaWRhdG9ycy5udWxsVmFsaWRhdG9yOyB9XHJcbiAgICByZXR1cm4gY29udHJvbC52YWx1ZSA9PT0gdHJ1ZSA/IG51bGwgOiB7ICdyZXF1aXJlZCc6IHRydWUgfTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFZhbGlkYXRvciB0aGF0IHBlcmZvcm1zIGVtYWlsIHZhbGlkYXRpb24uXHJcbiAgICovXHJcbiAgc3RhdGljIGVtYWlsKGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCk6IFZhbGlkYXRpb25FcnJvcnN8bnVsbCB7XHJcbiAgICBpZiAoIWNvbnRyb2wpIHsgcmV0dXJuIEpzb25WYWxpZGF0b3JzLm51bGxWYWxpZGF0b3I7IH1cclxuICAgIGNvbnN0IEVNQUlMX1JFR0VYUCA9XHJcbiAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTptYXgtbGluZS1sZW5ndGhcclxuICAgICAgL14oPz0uezEsMjU0fSQpKD89LnsxLDY0fUApWy0hIyQlJicqKy8wLTk9P0EtWl5fYGEtent8fX5dKyhcXC5bLSEjJCUmJyorLzAtOT0/QS1aXl9gYS16e3x9fl0rKSpAW0EtWmEtejAtOV0oW0EtWmEtejAtOS1dezAsNjF9W0EtWmEtejAtOV0pPyhcXC5bQS1aYS16MC05XShbQS1aYS16MC05LV17MCw2MX1bQS1aYS16MC05XSk/KSokLztcclxuICAgIHJldHVybiBFTUFJTF9SRUdFWFAudGVzdChjb250cm9sLnZhbHVlKSA/IG51bGwgOiB7ICdlbWFpbCc6IHRydWUgfTtcclxuICB9XHJcbn1cclxuIl19
|