@aws-cdk/core
Version:
AWS Cloud Development Kit Core Library
578 lines • 72 kB
JavaScript
"use strict";
const lib_1 = require("../lib");
const encoding_1 = require("../lib/private/encoding");
const intrinsic_1 = require("../lib/private/intrinsic");
const resolve_1 = require("../lib/private/resolve");
const evaluate_cfn_1 = require("./evaluate-cfn");
class Promise2 {
constructor() {
this.creationStack = [];
}
resolve() {
return {
Data: {
stringProp: 'hello',
numberProp: 1234,
},
Recurse: new intrinsic_1.Intrinsic(42)
};
}
}
class Promise1 {
constructor() {
this.creationStack = [];
this.p2 = [new Promise2(), new Promise2()];
}
resolve() {
return this.p2;
}
}
class BaseDataType {
constructor(foo) {
this.foo = foo;
}
}
class DataType extends BaseDataType {
constructor() {
super(12);
this.goo = 'hello';
}
}
/**
* Return Tokens in both flavors that resolve to the given string
*/
function tokensThatResolveTo(value) {
return [
new intrinsic_1.Intrinsic(value),
lib_1.Lazy.anyValue({ produce: () => value })
];
}
/**
* Wrapper for resolve that creates an throwaway Construct to call it on
*
* So I don't have to change all call sites in this file.
*/
function resolve(x) {
return new lib_1.Stack().resolve(x);
}
module.exports = {
'resolve a plain old object should just return the object'(test) {
const obj = { PlainOldObject: 123, Array: [1, 2, 3] };
test.deepEqual(resolve(obj), obj);
test.done();
},
'if a value is an object with a token value, it will be evaluated'(test) {
const obj = {
RegularValue: 'hello',
LazyValue: new intrinsic_1.Intrinsic('World')
};
test.deepEqual(resolve(obj), {
RegularValue: 'hello',
LazyValue: 'World'
});
test.done();
},
'tokens are evaluated anywhere in the object tree'(test) {
const obj = new Promise1();
const actual = resolve({ Obj: obj });
test.deepEqual(actual, {
Obj: [
{
Data: {
stringProp: "hello",
numberProp: 1234
},
Recurse: 42
},
{
Data: {
stringProp: "hello",
numberProp: 1234
},
Recurse: 42
}
]
});
test.done();
},
'tokens are evaluated recursively'(test) {
const obj = new Promise1();
const actual = resolve(new intrinsic_1.Intrinsic({ Obj: obj }));
test.deepEqual(actual, {
Obj: [
{
Data: {
stringProp: "hello",
numberProp: 1234
},
Recurse: 42
},
{
Data: {
stringProp: "hello",
numberProp: 1234
},
Recurse: 42
}
]
});
test.done();
},
'empty arrays or objects are kept'(test) {
test.deepEqual(resolve({}), {});
test.deepEqual(resolve([]), []);
const obj = {
Prop1: 1234,
Prop2: {},
Prop3: [],
Prop4: 'hello',
Prop5: {
PropA: {},
PropB: {
PropC: [undefined, undefined],
PropD: 'Yoohoo'
}
}
};
test.deepEqual(resolve(obj), {
Prop1: 1234,
Prop2: {},
Prop3: [],
Prop4: 'hello',
Prop5: {
PropA: {},
PropB: {
PropC: [],
PropD: 'Yoohoo'
}
}
});
test.done();
},
'if an object has a "resolve" property that is not a function, it is not considered a token'(test) {
test.deepEqual(resolve({ a_token: { resolve: () => 78787 } }), { a_token: 78787 });
test.deepEqual(resolve({ not_a_token: { resolve: 12 } }), { not_a_token: { resolve: 12 } });
test.done();
},
// tslint:disable-next-line:max-line-length
'if a resolvable object inherits from a class that is also resolvable, the "constructor" function will not get in the way (uses Object.keys instead of "for in")'(test) {
test.deepEqual(resolve({ prop: new DataType() }), { prop: { foo: 12, goo: 'hello' } });
test.done();
},
'isToken(obj) can be used to determine if an object is a token'(test) {
test.ok(lib_1.isResolvableObject({ resolve: () => 123 }));
test.ok(lib_1.isResolvableObject({ a: 1, b: 2, resolve: () => 'hello' }));
test.ok(!lib_1.isResolvableObject({ a: 1, b: 2, resolve: 3 }));
test.done();
},
'Token can be used to create tokens that contain a constant value'(test) {
test.equal(resolve(new intrinsic_1.Intrinsic(12)), 12);
test.equal(resolve(new intrinsic_1.Intrinsic('hello')), 'hello');
test.deepEqual(resolve(new intrinsic_1.Intrinsic(['hi', 'there'])), ['hi', 'there']);
test.done();
},
'resolving leaves a Date object in working order'(test) {
const date = new Date('2000-01-01');
const resolved = resolve(date);
test.equal(date.toString(), resolved.toString());
test.done();
},
'tokens can be stringified and evaluated to conceptual value'(test) {
// GIVEN
const token = new intrinsic_1.Intrinsic('woof woof');
// WHEN
const stringified = `The dog says: ${token}`;
const resolved = resolve(stringified);
// THEN
test.deepEqual(evaluate_cfn_1.evaluateCFN(resolved), 'The dog says: woof woof');
test.done();
},
'tokens stringification can be reversed'(test) {
// GIVEN
const token = new intrinsic_1.Intrinsic('woof woof');
// THEN
test.equal(token, lib_1.Tokenization.reverseString(`${token}`).firstToken);
test.done();
},
'Tokens stringification and reversing of CloudFormation Tokens is implemented using Fn::Join'(test) {
// GIVEN
const token = new intrinsic_1.Intrinsic(({ woof: 'woof' }));
// WHEN
const stringified = `The dog says: ${token}`;
const resolved = resolve(stringified);
// THEN
test.deepEqual(resolved, {
'Fn::Join': ['', ['The dog says: ', { woof: 'woof' }]]
});
test.done();
},
'Doubly nested strings evaluate correctly in scalar context'(test) {
// GIVEN
const token1 = new intrinsic_1.Intrinsic("world");
const token2 = new intrinsic_1.Intrinsic(`hello ${token1}`);
// WHEN
const resolved1 = resolve(token2.toString());
const resolved2 = resolve(token2);
// THEN
test.deepEqual(evaluate_cfn_1.evaluateCFN(resolved1), "hello world");
test.deepEqual(evaluate_cfn_1.evaluateCFN(resolved2), "hello world");
test.done();
},
'integer Tokens can be stringified and evaluate to conceptual value'(test) {
// GIVEN
for (const token of tokensThatResolveTo(1)) {
// WHEN
const stringified = `the number is ${token}`;
const resolved = resolve(stringified);
// THEN
test.deepEqual(evaluate_cfn_1.evaluateCFN(resolved), 'the number is 1');
}
test.done();
},
'intrinsic Tokens can be stringified and evaluate to conceptual value'(test) {
// GIVEN
for (const bucketName of tokensThatResolveTo({ Ref: 'MyBucket' })) {
// WHEN
const resolved = resolve(`my bucket is named ${bucketName}`);
// THEN
const context = { MyBucket: 'TheName' };
test.equal(evaluate_cfn_1.evaluateCFN(resolved, context), 'my bucket is named TheName');
}
test.done();
},
'tokens resolve properly in initial position'(test) {
// GIVEN
for (const token of tokensThatResolveTo('Hello')) {
// WHEN
const resolved = resolve(`${token} world`);
// THEN
test.equal(evaluate_cfn_1.evaluateCFN(resolved), 'Hello world');
}
test.done();
},
'side-by-side Tokens resolve correctly'(test) {
// GIVEN
for (const token1 of tokensThatResolveTo('Hello ')) {
for (const token2 of tokensThatResolveTo('world')) {
// WHEN
const resolved = resolve(`${token1}${token2}`);
// THEN
test.equal(evaluate_cfn_1.evaluateCFN(resolved), 'Hello world');
}
}
test.done();
},
'tokens can be used in hash keys but must resolve to a string'(test) {
// GIVEN
const token = new intrinsic_1.Intrinsic('I am a string');
// WHEN
const s = {
[token.toString()]: `boom ${token}`
};
// THEN
test.deepEqual(resolve(s), { 'I am a string': 'boom I am a string' });
test.done();
},
'tokens can be nested in hash keys'(test) {
// GIVEN
const token = new intrinsic_1.Intrinsic(lib_1.Lazy.stringValue({ produce: () => lib_1.Lazy.stringValue({ produce: (() => 'I am a string') }) }));
// WHEN
const s = {
[token.toString()]: `boom ${token}`
};
// THEN
test.deepEqual(resolve(s), { 'I am a string': 'boom I am a string' });
test.done();
},
'tokens can be nested and concatenated in hash keys'(test) {
// GIVEN
const innerToken = new intrinsic_1.Intrinsic('toot');
const token = new intrinsic_1.Intrinsic(`${innerToken} the woot`);
// WHEN
const s = {
[token.toString()]: `boom chicago`
};
// THEN
test.deepEqual(resolve(s), { 'toot the woot': 'boom chicago' });
test.done();
},
'can find nested tokens in hash keys'(test) {
// GIVEN
const innerToken = new intrinsic_1.Intrinsic('toot');
const token = new intrinsic_1.Intrinsic(`${innerToken} the woot`);
// WHEN
const s = {
[token.toString()]: `boom chicago`
};
// THEN
const tokens = resolve_1.findTokens(new lib_1.Stack(), () => s);
test.ok(tokens.some(t => t === innerToken), 'Cannot find innerToken');
test.ok(tokens.some(t => t === token), 'Cannot find token');
test.done();
},
'fails if token in a hash key resolves to a non-string'(test) {
// GIVEN
const token = new intrinsic_1.Intrinsic({ Ref: 'Other' });
// WHEN
const s = {
[token.toString()]: `boom ${token}`
};
// THEN
test.throws(() => resolve(s), 'The key "${Token[TOKEN.19]}" has been resolved to {"Ref":"Other"} but must be resolvable to a string');
test.done();
},
'list encoding': {
'can encode Token to string and resolve the encoding'(test) {
// GIVEN
const token = new intrinsic_1.Intrinsic({ Ref: 'Other' });
// WHEN
const struct = {
XYZ: lib_1.Token.asList(token)
};
// THEN
test.deepEqual(resolve(struct), {
XYZ: { Ref: 'Other' }
});
test.done();
},
'cannot add to encoded list'(test) {
// GIVEN
const token = new intrinsic_1.Intrinsic({ Ref: 'Other' });
// WHEN
const encoded = lib_1.Token.asList(token);
encoded.push('hello');
// THEN
test.throws(() => {
resolve(encoded);
}, /Cannot add elements to list token/);
test.done();
},
'cannot add to strings in encoded list'(test) {
// GIVEN
const token = new intrinsic_1.Intrinsic({ Ref: 'Other' });
// WHEN
const encoded = lib_1.Token.asList(token);
encoded[0] += 'hello';
// THEN
test.throws(() => {
resolve(encoded);
}, /concatenate strings in/);
test.done();
},
'can pass encoded lists to FnSelect'(test) {
// GIVEN
const encoded = lib_1.Token.asList(new intrinsic_1.Intrinsic({ Ref: 'Other' }));
// WHEN
const struct = lib_1.Fn.select(1, encoded);
// THEN
test.deepEqual(resolve(struct), {
'Fn::Select': [1, { Ref: 'Other' }]
});
test.done();
},
'can pass encoded lists to FnJoin'(test) {
// GIVEN
const encoded = lib_1.Token.asList(new intrinsic_1.Intrinsic({ Ref: 'Other' }));
// WHEN
const struct = lib_1.Fn.join('/', encoded);
// THEN
test.deepEqual(resolve(struct), {
'Fn::Join': ['/', { Ref: 'Other' }]
});
test.done();
},
'can pass encoded lists to FnJoin, even if join is stringified'(test) {
// GIVEN
const encoded = lib_1.Token.asList(new intrinsic_1.Intrinsic({ Ref: 'Other' }));
// WHEN
const struct = lib_1.Fn.join('/', encoded).toString();
// THEN
test.deepEqual(resolve(struct), {
'Fn::Join': ['/', { Ref: 'Other' }]
});
test.done();
},
},
'number encoding': {
'basic integer encoding works'(test) {
test.equal(16, encoding_1.extractTokenDouble(encoding_1.createTokenDouble(16)));
test.done();
},
'arbitrary integers can be encoded, stringified, and recovered'(test) {
for (let i = 0; i < 100; i++) {
// We can encode all numbers up to 2^48-1
const x = Math.floor(Math.random() * (Math.pow(2, 48) - 1));
const encoded = encoding_1.createTokenDouble(x);
// Roundtrip through JSONification
const roundtripped = JSON.parse(JSON.stringify({ theNumber: encoded })).theNumber;
const decoded = encoding_1.extractTokenDouble(roundtripped);
test.equal(decoded, x, `Fail roundtrip encoding of ${x}`);
}
test.done();
},
'arbitrary numbers are correctly detected as not being tokens'(test) {
test.equal(undefined, encoding_1.extractTokenDouble(0));
test.equal(undefined, encoding_1.extractTokenDouble(1243));
test.equal(undefined, encoding_1.extractTokenDouble(4835e+532));
test.done();
},
'can number-encode and resolve Token objects'(test) {
// GIVEN
const x = new intrinsic_1.Intrinsic(123);
// THEN
const encoded = lib_1.Token.asNumber(x);
test.equal(false, lib_1.isResolvableObject(encoded), 'encoded number does not test as token');
test.equal(true, lib_1.Token.isUnresolved(encoded), 'encoded number does not test as token');
// THEN
const resolved = resolve({ value: encoded });
test.deepEqual(resolved, { value: 123 });
test.done();
},
},
'stack trace is captured at token creation'(test) {
function fn1() {
function fn2() {
class ExposeTrace extends intrinsic_1.Intrinsic {
get creationTrace() {
return this.creationStack;
}
}
return new ExposeTrace('hello');
}
return fn2();
}
const token = fn1();
test.ok(token.creationTrace.find(x => x.includes('fn1')));
test.ok(token.creationTrace.find(x => x.includes('fn2')));
test.done();
},
'newError returns an error with the creation stack trace'(test) {
function fn1() {
function fn2() {
function fn3() {
class ThrowingToken extends intrinsic_1.Intrinsic {
throwError(message) {
throw this.newError(message);
}
}
return new ThrowingToken('boom');
}
return fn3();
}
return fn2();
}
const token = fn1();
test.throws(() => token.throwError('message!'), /Token created:/);
test.done();
},
'type coercion': (() => {
const tests = {};
const inputs = [
'a string',
1234,
{ an_object: 1234 },
[1, 2, 3],
false
];
for (const input of inputs) {
// GIVEN
const stringToken = lib_1.Token.asString(new intrinsic_1.Intrinsic(input));
const numberToken = lib_1.Token.asNumber(new intrinsic_1.Intrinsic(input));
const listToken = lib_1.Token.asList(new intrinsic_1.Intrinsic(input));
// THEN
const expected = input;
tests[`${input}<string>.toNumber()`] = (test) => {
test.deepEqual(resolve(lib_1.Token.asNumber(new intrinsic_1.Intrinsic(stringToken))), expected);
test.done();
};
tests[`${input}<list>.toNumber()`] = (test) => {
test.deepEqual(resolve(lib_1.Token.asNumber(new intrinsic_1.Intrinsic(listToken))), expected);
test.done();
};
tests[`${input}<number>.toNumber()`] = (test) => {
test.deepEqual(resolve(lib_1.Token.asNumber(new intrinsic_1.Intrinsic(numberToken))), expected);
test.done();
};
tests[`${input}<string>.toString()`] = (test) => {
test.deepEqual(resolve(new intrinsic_1.Intrinsic(stringToken).toString()), expected);
test.done();
};
tests[`${input}<list>.toString()`] = (test) => {
test.deepEqual(resolve(new intrinsic_1.Intrinsic(listToken).toString()), expected);
test.done();
};
tests[`${input}<number>.toString()`] = (test) => {
test.deepEqual(resolve(new intrinsic_1.Intrinsic(numberToken).toString()), expected);
test.done();
};
tests[`${input}<string>.toList()`] = (test) => {
test.deepEqual(resolve(lib_1.Token.asList(new intrinsic_1.Intrinsic(stringToken))), expected);
test.done();
};
tests[`${input}<list>.toList()`] = (test) => {
test.deepEqual(resolve(lib_1.Token.asList(new intrinsic_1.Intrinsic(listToken))), expected);
test.done();
};
tests[`${input}<number>.toList()`] = (test) => {
test.deepEqual(resolve(lib_1.Token.asList(new intrinsic_1.Intrinsic(numberToken))), expected);
test.done();
};
}
return tests;
})(),
'creation stack is attached to errors emitted during resolve'(test) {
function showMeInTheStackTrace() {
return lib_1.Lazy.stringValue({ produce: () => { throw new Error('fooError'); } });
}
const x = showMeInTheStackTrace();
let message;
try {
resolve(x);
}
catch (e) {
message = e.message;
}
test.ok(message && message.includes('showMeInTheStackTrace'));
test.done();
},
'stringifyNumber': {
'converts number to string'(test) {
test.equal(lib_1.Tokenization.stringifyNumber(100), '100');
test.done();
},
'converts tokenized number to string'(test) {
test.equal(resolve(lib_1.Tokenization.stringifyNumber({
resolve: () => 100
})), '100');
test.done();
},
'string remains the same'(test) {
test.equal(lib_1.Tokenization.stringifyNumber('123'), '123');
test.done();
},
'Ref remains the same'(test) {
const val = { Ref: 'SomeLogicalId' };
test.deepEqual(lib_1.Tokenization.stringifyNumber(val), val);
test.done();
},
'lazy Ref remains the same'(test) {
const resolvedVal = { Ref: 'SomeLogicalId' };
const tokenizedVal = lib_1.Lazy.anyValue({
produce: () => resolvedVal
});
const res = lib_1.Tokenization.stringifyNumber(tokenizedVal);
test.notDeepEqual(res, resolvedVal);
test.deepEqual(resolve(res), resolvedVal);
test.done();
},
'tokenized Ref remains the same'(test) {
const resolvedVal = { Ref: 'SomeLogicalId' };
const tokenizedVal = lib_1.Token.asNumber(resolvedVal);
const res = lib_1.Tokenization.stringifyNumber(tokenizedVal);
test.notDeepEqual(res, resolvedVal);
test.deepEqual(resolve(res), resolvedVal);
test.done();
},
}
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC50b2tlbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJ0ZXN0LnRva2Vucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQ0EsZ0NBQWtGO0FBQ2xGLHNEQUFnRjtBQUNoRix3REFBcUQ7QUFDckQsb0RBQW9EO0FBRXBELGlEQUE2QztBQWtvQjdDLE1BQU0sUUFBUTtJQUFkO1FBQ2tCLGtCQUFhLEdBQUcsRUFBRSxDQUFDO0lBV3JDLENBQUM7SUFUUSxPQUFPO1FBQ1osT0FBTztZQUNMLElBQUksRUFBRTtnQkFDSixVQUFVLEVBQUUsT0FBTztnQkFDbkIsVUFBVSxFQUFFLElBQUk7YUFDakI7WUFDRCxPQUFPLEVBQUUsSUFBSSxxQkFBUyxDQUFFLEVBQUUsQ0FBQztTQUM1QixDQUFDO0lBQ0osQ0FBQztDQUNGO0FBRUQsTUFBTSxRQUFRO0lBQWQ7UUFDa0Isa0JBQWEsR0FBRyxFQUFFLENBQUM7UUFDNUIsT0FBRSxHQUFHLENBQUUsSUFBSSxRQUFRLEVBQUUsRUFBRSxJQUFJLFFBQVEsRUFBRSxDQUFFLENBQUM7SUFLakQsQ0FBQztJQUhRLE9BQU87UUFDWixPQUFPLElBQUksQ0FBQyxFQUFFLENBQUM7SUFDakIsQ0FBQztDQUNGO0FBRUQsTUFBTSxZQUFZO0lBQ2hCLFlBQXFCLEdBQVc7UUFBWCxRQUFHLEdBQUgsR0FBRyxDQUFRO0lBQ2hDLENBQUM7Q0FDRjtBQUVELE1BQU0sUUFBUyxTQUFRLFlBQVk7SUFHakM7UUFDRSxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7UUFITCxRQUFHLEdBQUcsT0FBTyxDQUFDO0lBSXJCLENBQUM7Q0FDRjtBQUVEOztHQUVHO0FBQ0gsU0FBUyxtQkFBbUIsQ0FBQyxLQUFVO0lBQ3JDLE9BQU87UUFDTCxJQUFJLHFCQUFTLENBQUMsS0FBSyxDQUFDO1FBQ3BCLFVBQUksQ0FBQyxRQUFRLENBQUMsRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsS0FBSyxFQUFFLENBQUM7S0FDeEMsQ0FBQztBQUNKLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBUyxPQUFPLENBQUMsQ0FBTTtJQUNyQixPQUFPLElBQUksV0FBSyxFQUFFLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ2hDLENBQUM7QUFyckJELGlCQUFTO0lBQ1AsMERBQTBELENBQUMsSUFBVTtRQUNuRSxNQUFNLEdBQUcsR0FBRyxFQUFFLGNBQWMsRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLENBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUUsRUFBRSxDQUFDO1FBQ3hELElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQ2xDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUNkLENBQUM7SUFFRCxrRUFBa0UsQ0FBQyxJQUFVO1FBQzNFLE1BQU0sR0FBRyxHQUFHO1lBQ1YsWUFBWSxFQUFFLE9BQU87WUFDckIsU0FBUyxFQUFFLElBQUkscUJBQVMsQ0FBQyxPQUFPLENBQUM7U0FDbEMsQ0FBQztRQUVGLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxFQUFFO1lBQzNCLFlBQVksRUFBRSxPQUFPO1lBQ3JCLFNBQVMsRUFBRSxPQUFPO1NBQ25CLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUNkLENBQUM7SUFFRCxrREFBa0QsQ0FBQyxJQUFVO1FBQzNELE1BQU0sR0FBRyxHQUFHLElBQUksUUFBUSxFQUFFLENBQUM7UUFDM0IsTUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUM7UUFFckMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUU7WUFDckIsR0FBRyxFQUFFO2dCQUNIO29CQUNBLElBQUksRUFBRTt3QkFDSixVQUFVLEVBQUUsT0FBTzt3QkFDbkIsVUFBVSxFQUFFLElBQUk7cUJBQ2pCO29CQUNELE9BQU8sRUFBRSxFQUFFO2lCQUNWO2dCQUNEO29CQUNBLElBQUksRUFBRTt3QkFDSixVQUFVLEVBQUUsT0FBTzt3QkFDbkIsVUFBVSxFQUFFLElBQUk7cUJBQ2pCO29CQUNELE9BQU8sRUFBRSxFQUFFO2lCQUNWO2FBQ0Y7U0FDRixDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDZCxDQUFDO0lBRUQsa0NBQWtDLENBQUMsSUFBVTtRQUMzQyxNQUFNLEdBQUcsR0FBRyxJQUFJLFFBQVEsRUFBRSxDQUFDO1FBQzNCLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxJQUFJLHFCQUFTLENBQUMsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBRXBELElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFO1lBQ3JCLEdBQUcsRUFBRTtnQkFDSDtvQkFDQSxJQUFJLEVBQUU7d0JBQ0osVUFBVSxFQUFFLE9BQU87d0JBQ25CLFVBQVUsRUFBRSxJQUFJO3FCQUNqQjtvQkFDRCxPQUFPLEVBQUUsRUFBRTtpQkFDVjtnQkFDRDtvQkFDQSxJQUFJLEVBQUU7d0JBQ0osVUFBVSxFQUFFLE9BQU87d0JBQ25CLFVBQVUsRUFBRSxJQUFJO3FCQUNqQjtvQkFDRCxPQUFPLEVBQUUsRUFBRTtpQkFDVjthQUNGO1NBQ0YsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO0lBQ2QsQ0FBQztJQUVELGtDQUFrQyxDQUFDLElBQVU7UUFDM0MsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsRUFBRyxDQUFDLEVBQUUsRUFBRyxDQUFDLENBQUM7UUFDbEMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsRUFBRyxDQUFDLEVBQUUsRUFBRyxDQUFDLENBQUM7UUFFbEMsTUFBTSxHQUFHLEdBQUc7WUFDVixLQUFLLEVBQUUsSUFBSTtZQUNYLEtBQUssRUFBRSxFQUFHO1lBQ1YsS0FBSyxFQUFFLEVBQUc7WUFDVixLQUFLLEVBQUUsT0FBTztZQUNkLEtBQUssRUFBRTtnQkFDTCxLQUFLLEVBQUUsRUFBRztnQkFDVixLQUFLLEVBQUU7b0JBQ0wsS0FBSyxFQUFFLENBQUUsU0FBUyxFQUFFLFNBQVMsQ0FBRTtvQkFDL0IsS0FBSyxFQUFFLFFBQVE7aUJBQ2hCO2FBQ0Y7U0FDRixDQUFDO1FBRUYsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUU7WUFDM0IsS0FBSyxFQUFFLElBQUk7WUFDWCxLQUFLLEVBQUUsRUFBRztZQUNWLEtBQUssRUFBRSxFQUFHO1lBQ1YsS0FBSyxFQUFFLE9BQU87WUFDZCxLQUFLLEVBQUU7Z0JBQ0wsS0FBSyxFQUFFLEVBQUc7Z0JBQ1YsS0FBSyxFQUFFO29CQUNMLEtBQUssRUFBRSxFQUFHO29CQUNWLEtBQUssRUFBRSxRQUFRO2lCQUNoQjthQUNGO1NBQ0YsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO0lBQ2QsQ0FBQztJQUVELDRGQUE0RixDQUFDLElBQVU7UUFDckcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsRUFBRSxPQUFPLEVBQUUsRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsS0FBSyxFQUFFLEVBQUMsQ0FBQyxFQUFFLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDbEYsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsRUFBRSxXQUFXLEVBQUUsRUFBRSxPQUFPLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFJLEVBQUUsV0FBVyxFQUFFLEVBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUM5RixJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDZCxDQUFDO0lBRUQsMkNBQTJDO0lBQzNDLGlLQUFpSyxDQUFDLElBQVU7UUFDMUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsRUFBRSxJQUFJLEVBQUUsSUFBSSxRQUFRLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxJQUFJLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDdkYsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO0lBQ2QsQ0FBQztJQUVELCtEQUErRCxDQUFDLElBQVU7UUFDeEUsSUFBSSxDQUFDLEVBQUUsQ0FBQyx3QkFBa0IsQ0FBQyxFQUFFLE9BQU8sRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDcEQsSUFBSSxDQUFDLEVBQUUsQ0FBQyx3QkFBa0IsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ3BFLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyx3QkFBa0IsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ3pELElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUNkLENBQUM7SUFFRCxrRUFBa0UsQ0FBQyxJQUFVO1FBQzNFLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUkscUJBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQzNDLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUkscUJBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3JELElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLElBQUkscUJBQVMsQ0FBQyxDQUFFLElBQUksRUFBRSxPQUFPLENBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBRSxJQUFJLEVBQUUsT0FBTyxDQUFFLENBQUMsQ0FBQztRQUM3RSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDZCxDQUFDO0lBRUQsaURBQWlELENBQUMsSUFBVTtRQUMxRCxNQUFNLElBQUksR0FBRyxJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUNwQyxNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFL0IsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLEVBQUUsUUFBUSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7UUFDakQsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO0lBQ2QsQ0FBQztJQUVELDZEQUE2RCxDQUFDLElBQVU7UUFDdEUsUUFBUTtRQUNSLE1BQU0sS0FBSyxHQUFHLElBQUkscUJBQVMsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUV6QyxPQUFPO1FBQ1AsTUFBTSxXQUFXLEdBQUcsaUJBQWlCLEtBQUssRUFBRSxDQUFDO1FBQzdDLE1BQU0sUUFBUSxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUV0QyxPQUFPO1FBQ1AsSUFBSSxDQUFDLFNBQVMsQ0FBQywwQkFBVyxDQUFDLFFBQVEsQ0FBQyxFQUFFLHlCQUF5QixDQUFDLENBQUM7UUFDakUsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO0lBQ2QsQ0FBQztJQUVELHdDQUF3QyxDQUFDLElBQVU7UUFDakQsUUFBUTtRQUNSLE1BQU0sS0FBSyxHQUFHLElBQUkscUJBQVMsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUV6QyxPQUFPO1FBQ1AsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsa0JBQVksQ0FBQyxhQUFhLENBQUMsR0FBRyxLQUFLLEVBQUUsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ3JFLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUNkLENBQUM7SUFFRCw2RkFBNkYsQ0FBQyxJQUFVO1FBQ3RHLFFBQVE7UUFDUixNQUFNLEtBQUssR0FBRyxJQUFJLHFCQUFTLENBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFFakQsT0FBTztRQUNQLE1BQU0sV0FBVyxHQUFHLGlCQUFpQixLQUFLLEVBQUUsQ0FBQztRQUM3QyxNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUM7UUFFdEMsT0FBTztRQUNQLElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxFQUFFO1lBQ3ZCLFVBQVUsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLGdCQUFnQixFQUFFLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUM7U0FDdkQsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO0lBQ2QsQ0FBQztJQUVELDREQUE0RCxDQUFDLElBQVU7UUFDckUsUUFBUTtRQUNSLE1BQU0sTUFBTSxHQUFHLElBQUkscUJBQVMsQ0FBRSxPQUFPLENBQUMsQ0FBQztRQUN2QyxNQUFNLE1BQU0sR0FBRyxJQUFJLHFCQUFTLENBQUUsU0FBUyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBRWpELE9BQU87UUFDUCxNQUFNLFNBQVMsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7UUFDN0MsTUFBTSxTQUFTLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRWxDLE9BQU87UUFDUCxJQUFJLENBQUMsU0FBUyxDQUFDLDBCQUFXLENBQUMsU0FBUyxDQUFDLEVBQUUsYUFBYSxDQUFDLENBQUM7UUFDdEQsSUFBSSxDQUFDLFNBQVMsQ0FBQywwQkFBVyxDQUFDLFNBQVMsQ0FBQyxFQUFFLGFBQWEsQ0FBQyxDQUFDO1FBRXRELElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUNkLENBQUM7SUFFRCxvRUFBb0UsQ0FBQyxJQUFVO1FBQzdFLFFBQVE7UUFDUixLQUFLLE1BQU0sS0FBSyxJQUFJLG1CQUFtQixDQUFDLENBQUMsQ0FBQyxFQUFFO1lBQzFDLE9BQU87WUFDUCxNQUFNLFdBQVcsR0FBRyxpQkFBaUIsS0FBSyxFQUFFLENBQUM7WUFDN0MsTUFBTSxRQUFRLEdBQUcsT0FBTyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBRXRDLE9BQU87WUFDUCxJQUFJLENBQUMsU0FBUyxDQUFDLDBCQUFXLENBQUMsUUFBUSxDQUFDLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztTQUMxRDtRQUNELElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUNkLENBQUM7SUFFRCxzRUFBc0UsQ0FBQyxJQUFVO1FBQy9FLFFBQVE7UUFDUixLQUFLLE1BQU0sVUFBVSxJQUFJLG1CQUFtQixDQUFDLEVBQUUsR0FBRyxFQUFFLFVBQVUsRUFBRSxDQUFDLEVBQUU7WUFDakUsT0FBTztZQUNQLE1BQU0sUUFBUSxHQUFHLE9BQU8sQ0FBQyxzQkFBc0IsVUFBVSxFQUFFLENBQUMsQ0FBQztZQUU3RCxPQUFPO1lBQ1AsTUFBTSxPQUFPLEdBQUcsRUFBQyxRQUFRLEVBQUUsU0FBUyxFQUFDLENBQUM7WUFDdEMsSUFBSSxDQUFDLEtBQUssQ0FBQywwQkFBVyxDQUFDLFFBQVEsRUFBRSxPQUFPLENBQUMsRUFBRSw0QkFBNEIsQ0FBQyxDQUFDO1NBQzFFO1FBRUQsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO0lBQ2QsQ0FBQztJQUVELDZDQUE2QyxDQUFDLElBQVU7UUFDdEQsUUFBUTtRQUNSLEtBQUssTUFBTSxLQUFLLElBQUksbUJBQW1CLENBQUMsT0FBTyxDQUFDLEVBQUU7WUFDaEQsT0FBTztZQUNQLE1BQU0sUUFBUSxHQUFHLE9BQU8sQ0FBQyxHQUFHLEtBQUssUUFBUSxDQUFDLENBQUM7WUFFM0MsT0FBTztZQUNQLElBQUksQ0FBQyxLQUFLLENBQUMsMEJBQVcsQ0FBQyxRQUFRLENBQUMsRUFBRSxhQUFhLENBQUMsQ0FBQztTQUNsRDtRQUVELElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUNkLENBQUM7SUFFRCx1Q0FBdUMsQ0FBQyxJQUFVO1FBQ2hELFFBQVE7UUFDUixLQUFLLE1BQU0sTUFBTSxJQUFJLG1CQUFtQixDQUFDLFFBQVEsQ0FBQyxFQUFFO1lBQ2xELEtBQUssTUFBTSxNQUFNLElBQUksbUJBQW1CLENBQUMsT0FBTyxDQUFDLEVBQUU7Z0JBQ2pELE9BQU87Z0JBQ1AsTUFBTSxRQUFRLEdBQUcsT0FBTyxDQUFDLEdBQUcsTUFBTSxHQUFHLE1BQU0sRUFBRSxDQUFDLENBQUM7Z0JBRS9DLE9BQU87Z0JBQ1AsSUFBSSxDQUFDLEtBQUssQ0FBQywwQkFBVyxDQUFDLFFBQVEsQ0FBQyxFQUFFLGFBQWEsQ0FBQyxDQUFDO2FBQ2xEO1NBQ0Y7UUFFRCxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDZCxDQUFDO0lBRUQsOERBQThELENBQUMsSUFBVTtRQUN2RSxRQUFRO1FBQ1IsTUFBTSxLQUFLLEdBQUcsSUFBSSxxQkFBUyxDQUFFLGVBQWUsQ0FBQyxDQUFDO1FBRTlDLE9BQU87UUFDUCxNQUFNLENBQUMsR0FBRztZQUNSLENBQUMsS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDLEVBQUUsUUFBUSxLQUFLLEVBQUU7U0FDcEMsQ0FBQztRQUVGLE9BQU87UUFDUCxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLGVBQWUsRUFBRSxvQkFBb0IsRUFBRSxDQUFDLENBQUM7UUFDdEUsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO0lBQ2QsQ0FBQztJQUVELG1DQUFtQyxDQUFDLElBQVU7UUFDNUMsUUFBUTtRQUNSLE1BQU0sS0FBSyxHQUFHLElBQUkscUJBQVMsQ0FBQyxVQUFJLENBQUMsV0FBVyxDQUFDLEVBQUUsT0FBTyxFQUFFLEdBQUcsRUFBRSxDQUFDLFVBQUksQ0FBQyxXQUFXLENBQUMsRUFBRSxPQUFPLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxlQUFlLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFFekgsT0FBTztRQUNQLE1BQU0sQ0FBQyxHQUFHO1lBQ1IsQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFLENBQUMsRUFBRSxRQUFRLEtBQUssRUFBRTtTQUNwQyxDQUFDO1FBRUYsT0FBTztRQUNQLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsZUFBZSxFQUFFLG9CQUFvQixFQUFFLENBQUMsQ0FBQztRQUN0RSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDZCxDQUFDO0lBRUQsb0RBQW9ELENBQUMsSUFBVTtRQUM3RCxRQUFRO1FBQ1IsTUFBTSxVQUFVLEdBQUcsSUFBSSxxQkFBUyxDQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQzFDLE1BQU0sS0FBSyxHQUFHLElBQUkscUJBQVMsQ0FBRSxHQUFHLFVBQVUsV0FBVyxDQUFDLENBQUM7UUFFdkQsT0FBTztRQUNQLE1BQU0sQ0FBQyxHQUFHO1lBQ1IsQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFLENBQUMsRUFBRSxjQUFjO1NBQ25DLENBQUM7UUFFRixPQUFPO1FBQ1AsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxlQUFlLEVBQUUsY0FBYyxFQUFFLENBQUMsQ0FBQztRQUNoRSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDZCxDQUFDO0lBRUQscUNBQXFDLENBQUMsSUFBVTtRQUM5QyxRQUFRO1FBQ1IsTUFBTSxVQUFVLEdBQUcsSUFBSSxxQkFBUyxDQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQzFDLE1BQU0sS0FBSyxHQUFHLElBQUkscUJBQVMsQ0FBRSxHQUFHLFVBQVUsV0FBVyxDQUFDLENBQUM7UUFFdkQsT0FBTztRQUNQLE1BQU0sQ0FBQyxHQUFHO1lBQ1IsQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFLENBQUMsRUFBRSxjQUFjO1NBQ25DLENBQUM7UUFFRixPQUFPO1FBQ1AsTUFBTSxNQUFNLEdBQUcsb0JBQVUsQ0FBQyxJQUFJLFdBQUssRUFBRSxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2hELElBQUksQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsS0FBSyxVQUFVLENBQUMsRUFBRSx3QkFBd0IsQ0FBQyxDQUFDO1FBQ3RFLElBQUksQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsS0FBSyxLQUFLLENBQUMsRUFBRSxtQkFBbUIsQ0FBQyxDQUFDO1FBQzVELElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUNkLENBQUM7SUFFRCx1REFBdUQsQ0FBQyxJQUFVO1FBQ2hFLFFBQVE7UUFDUixNQUFNLEtBQUssR0FBRyxJQUFJLHFCQUFTLENBQUMsRUFBRSxHQUFHLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztRQUU5QyxPQUFPO1FBQ1AsTUFBTSxDQUFDLEdBQUc7WUFDUixDQUFDLEtBQUssQ0FBQyxRQUFRLEVBQUUsQ0FBQyxFQUFFLFFBQVEsS0FBSyxFQUFFO1NBQ3BDLENBQUM7UUFFRixPQUFPO1FBQ1AsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsc0dBQXNHLENBQUMsQ0FBQztRQUN0SSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDZCxDQUFDO0lBRUQsZUFBZSxFQUFFO1FBQ2YscURBQXFELENBQUMsSUFBVTtZQUM5RCxRQUFRO1lBQ1IsTUFBTSxLQUFLLEdBQUcsSUFBSSxxQkFBUyxDQUFDLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUM7WUFFOUMsT0FBTztZQUNQLE1BQU0sTUFBTSxHQUFHO2dCQUNiLEdBQUcsRUFBRSxXQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQzthQUN6QixDQUFDO1lBRUYsT0FBTztZQUNQLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFO2dCQUM5QixHQUFHLEVBQUUsRUFBRSxHQUFHLEVBQUUsT0FBTyxFQUFDO2FBQ3JCLENBQUMsQ0FBQztZQUVILElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNkLENBQUM7UUFFRCw0QkFBNEIsQ0FBQyxJQUFVO1lBQ3JDLFFBQVE7WUFDUixNQUFNLEtBQUssR0FBRyxJQUFJLHFCQUFTLENBQUMsRUFBRSxHQUFHLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztZQUU5QyxPQUFPO1lBQ1AsTUFBTSxPQUFPLEdBQWEsV0FBSyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUM5QyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBRXRCLE9BQU87WUFDUCxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsRUFBRTtnQkFDZixPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDbkIsQ0FBQyxFQUFFLG1DQUFtQyxDQUFDLENBQUM7WUFFeEMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ2QsQ0FBQztRQUVELHVDQUF1QyxDQUFDLElBQVU7WUFDaEQsUUFBUTtZQUNSLE1BQU0sS0FBSyxHQUFHLElBQUkscUJBQVMsQ0FBQyxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDO1lBRTlDLE9BQU87WUFDUCxNQUFNLE9BQU8sR0FBYSxXQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQzlDLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxPQUFPLENBQUM7WUFFdEIsT0FBTztZQUNQLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFO2dCQUNmLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUNuQixDQUFDLEVBQUUsd0JBQXdCLENBQUMsQ0FBQztZQUU3QixJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDZCxDQUFDO1FBRUQsb0NBQW9DLENBQUMsSUFBVTtZQUM3QyxRQUFRO1lBQ1IsTUFBTSxPQUFPLEdBQWEsV0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFJLHFCQUFTLENBQUMsRUFBRSxHQUFHLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBRXhFLE9BQU87WUFDUCxNQUFNLE1BQU0sR0FBRyxRQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQztZQUVyQyxPQUFPO1lBQ1AsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEVBQUU7Z0JBQzlCLFlBQVksRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUMsQ0FBQzthQUNuQyxDQUFDLENBQUM7WUFFSCxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDZCxDQUFDO1FBRUQsa0NBQWtDLENBQUMsSUFBVTtZQUMzQyxRQUFRO1lBQ1IsTUFBTSxPQUFPLEdBQWEsV0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFJLHFCQUFTLENBQUMsRUFBRSxHQUFHLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBRXhFLE9BQU87WUFDUCxNQUFNLE1BQU0sR0FBRyxRQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxPQUFPLENBQUMsQ0FBQztZQUVyQyxPQUFPO1lBQ1AsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEVBQUU7Z0JBQzlCLFVBQVUsRUFBRSxDQUFDLEdBQUcsRUFBRSxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUMsQ0FBQzthQUNuQyxDQUFDLENBQUM7WUFFSCxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDZCxDQUFDO1FBRUQsK0RBQStELENBQUMsSUFBVTtZQUN4RSxRQUFRO1lBQ1IsTUFBTSxPQUFPLEdBQWEsV0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFJLHFCQUFTLENBQUMsRUFBRSxHQUFHLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBRXhFLE9BQU87WUFDUCxNQUFNLE1BQU0sR0FBRyxRQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxPQUFPLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUVoRCxPQUFPO1lBQ1AsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEVBQUU7Z0JBQzlCLFVBQVUsRUFBRSxDQUFDLEdBQUcsRUFBRSxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUMsQ0FBQzthQUNuQyxDQUFDLENBQUM7WUFFSCxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDZCxDQUFDO0tBQ0Y7SUFFRCxpQkFBaUIsRUFBRTtRQUNqQiw4QkFBOEIsQ0FBQyxJQUFVO1lBQ3ZDLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxFQUFFLDZCQUFrQixDQUFDLDRCQUFpQixDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUMxRCxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDZCxDQUFDO1FBRUQsK0RBQStELENBQUMsSUFBVTtZQUN4RSxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsR0FBRyxFQUFFLENBQUMsRUFBRSxFQUFFO2dCQUM1Qix5Q0FBeUM7Z0JBQ3pDLE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFFNUQsTUFBTSxPQUFPLEdBQUcsNEJBQWlCLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ3JDLGtDQUFrQztnQkFDbEMsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7Z0JBQ2xGLE1BQU0sT0FBTyxHQUFHLDZCQUFrQixDQUFDLFlBQVksQ0FBQyxDQUFDO2dCQUNqRCxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDLEVBQUUsOEJBQThCLENBQUMsRUFBRSxDQUFDLENBQUM7YUFDM0Q7WUFFRCxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDZCxDQUFDO1FBRUQsOERBQThELENBQUMsSUFBVTtZQUN2RSxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsRUFBRSw2QkFBa0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzdDLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxFQUFFLDZCQUFrQixDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7WUFDaEQsSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLEVBQUUsNkJBQWtCLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztZQUVyRCxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDZCxDQUFDO1FBRUQsNkNBQTZDLENBQUMsSUFBVTtZQUN0RCxRQUFRO1lBQ1IsTUFBTSxDQUFDLEdBQUcsSUFBSSxxQkFBUyxDQUFFLEdBQUcsQ0FBQyxDQUFDO1lBRTlCLE9BQU87WUFDUCxNQUFNLE9BQU8sR0FBRyxXQUFLLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2xDLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLHdCQUFrQixDQUFDLE9BQU8sQ0FBQyxFQUFFLHVDQUF1QyxDQUFDLENBQUM7WUFDeEYsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsV0FBSyxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsRUFBRSx1Q0FBdUMsQ0FBQyxDQUFDO1lBRXZGLE9BQU87WUFDUCxNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztZQUM3QyxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsRUFBRSxFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDO1lBRXpDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNkLENBQUM7S0FDRjtJQUVELDJDQUEyQyxDQUFDLElBQVU7UUFDcEQsU0FBUyxHQUFHO1lBQ1YsU0FBUyxHQUFHO2dCQUNWLE1BQU0sV0FBWSxTQUFRLHFCQUFTO29CQUNqQyxJQUFXLGFBQWE7d0JBQ3RCLE9BQU8sSUFBSSxDQUFDLGFBQWEsQ0FBQztvQkFDNUIsQ0FBQztpQkFDRjtnQkFFRCxPQUFPLElBQUksV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ2xDLENBQUM7WUFFRCxPQUFPLEdBQUcsRUFBRSxDQUFDO1FBQ2YsQ0FBQztRQUVELE1BQU0sS0FBSyxHQUFHLEdBQUcsRUFBRSxDQUFDO1FBQ3BCLElBQUksQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMxRCxJQUFJLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDMUQsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO0lBQ2QsQ0FBQztJQUVELHlEQUF5RCxDQUFDLElBQVU7UUFDbEUsU0FBUyxHQUFHO1lBQ1YsU0FBUyxHQUFHO2dCQUNWLFNBQVMsR0FBRztvQkFDVixNQUFNLGFBQWMsU0FBUSxxQkFBUzt3QkFDNUIsVUFBVSxDQUFDLE9BQWU7NEJBQy9CLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQzt3QkFDL0IsQ0FBQztxQkFDRjtvQkFDRCxPQUFPLElBQUksYUFBYSxDQUFDLE1BQU0sQ0FBQyxDQUFDO2dCQUNuQyxDQUFDO2dCQUVELE9BQU8sR0FBRyxFQUFFLENBQUM7WUFDZixDQUFDO1lBQ0QsT0FBTyxHQUFHLEVBQUUsQ0FBQztRQUNmLENBQUM7UUFDRCxNQUFNLEtBQUssR0FBRyxHQUFHLEVBQUUsQ0FBQztRQUNwQixJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztRQUNsRSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDZCxDQUFDO0lBRUQsZUFBZSxFQUFFLENBQUMsR0FBRyxFQUFFO1FBQ3JCLE1BQU0sS0FBSyxHQUFRLEVBQUcsQ0FBQztRQUV2QixNQUFNLE1BQU0sR0FBRztZQUNiLFVBQVU7WUFDVixJQUFJO1lBQ0osRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFO1lBQ25CLENBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUU7WUFDWCxLQUFLO1NBQ04sQ0FBQztRQUVGLEtBQUssTUFBTSxLQUFLLElBQUksTUFBTSxFQUFFO1lBQzFCLFFBQVE7WUFDUixNQUFNLFdBQVcsR0FBRyxXQUFLLENBQUMsUUFBUSxDQUFDLElBQUkscUJBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1lBQ3pELE1BQU0sV0FBVyxHQUFHLFdBQUssQ0FBQyxRQUFRLENBQUMsSUFBSSxxQkFBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7WUFDekQsTUFBTSxTQUFTLEdBQUcsV0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFJLHFCQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztZQUVyRCxPQUFPO1lBQ1AsTUFBTSxRQUFRLEdBQUcsS0FBSyxDQUFDO1lBRXZCLEtBQUssQ0FBQyxHQUFHLEtBQUsscUJBQXFCLENBQUMsR0FBRyxDQUFDLElBQVUsRUFBRSxFQUFFO2dCQUNwRCxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxXQUFLLENBQUMsUUFBUSxDQUFDLElBQUkscUJBQVMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLEVBQUUsUUFBUSxDQUFDLENBQUM7Z0JBQzlFLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNkLENBQUMsQ0FBQztZQUVGLEtBQUssQ0FBQyxHQUFHLEtBQUssbUJBQW1CLENBQUMsR0FBRyxDQUFDLElBQVUsRUFBRSxFQUFFO2dCQUNsRCxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxXQUFLLENBQUMsUUFBUSxDQUFDLElBQUkscUJBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsUUFBUSxDQUFDLENBQUM7Z0JBQzVFLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNkLENBQUMsQ0FBQztZQUVGLEtBQUssQ0FBQyxHQUFHLEtBQUsscUJBQXFCLENBQUMsR0FBRyxDQUFDLElBQVUsRUFBRSxFQUFFO2dCQUNwRCxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxXQUFLLENBQUMsUUFBUSxDQUFDLElBQUkscUJBQVMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLEVBQUUsUUFBUSxDQUFDLENBQUM7Z0JBQzlFLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNkLENBQUMsQ0FBQztZQUVGLEtBQUssQ0FBQyxHQUFHLEtBQUsscUJBQXFCLENBQUMsR0FBRyxDQUFDLElBQVUsRUFBRSxFQUFFO2dCQUNwRCxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxJQUFJLHFCQUFTLENBQUMsV0FBVyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUMsRUFBRSxRQUFRLENBQUMsQ0FBQztnQkFDekUsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ2QsQ0FBQyxDQUFDO1lBRUYsS0FBSyxDQUFDLEdBQUcsS0FBSyxtQkFBbUIsQ0FBQyxHQUFHLENBQUMsSUFBVSxFQUFFLEVBQUU7Z0JBQ2xELElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLElBQUkscUJBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxDQUFDO2dCQUN2RSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDZCxDQUFDLENBQUM7WUFFRixLQUFLLENBQUMsR0FBRyxLQUFLLHFCQUFxQixDQUFDLEdBQUcsQ0FBQyxJQUFVLEVBQUUsRUFBRTtnQkFDcEQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsSUFBSSxxQkFBUyxDQUFDLFdBQVcsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDLEVBQUUsUUFBUSxDQUFDLENBQUM7Z0JBQ3pFLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNkLENBQUMsQ0FBQztZQUVGLEtBQUssQ0FBQyxHQUFHLEtBQUssbUJBQW1CLENBQUMsR0FBRyxDQUFDLElBQVUsRUFBRSxFQUFFO2dCQUNsRCxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxXQUFLLENBQUMsTUFBTSxDQUFDLElBQUkscUJBQVMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLEVBQUUsUUFBUSxDQUFDLENBQUM7Z0JBQzVFLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNkLENBQUMsQ0FBQztZQUVGLEtBQUssQ0FBQyxHQUFHLEtBQUssaUJBQWlCLENBQUMsR0FBRyxDQUFDLElBQVUsRUFBRSxFQUFFO2dCQUNoRCxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxXQUFLLENBQUMsTUFBTSxDQUFDLElBQUkscUJBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsUUFBUSxDQUFDLENBQUM7Z0JBQzFFLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNkLENBQUMsQ0FBQztZQUVGLEtBQUssQ0FBQyxHQUFHLEtBQUssbUJBQW1CLENBQUMsR0FBRyxDQUFDLElBQVUsRUFBRSxFQUFFO2dCQUNsRCxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxXQUFLLENBQUMsTUFBTSxDQUFDLElBQUkscUJBQVMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLEVBQUUsUUFBUSxDQUFDLENBQUM7Z0JBQzVFLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNkLENBQUMsQ0FBQztTQUNIO1FBRUQsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDLENBQUMsRUFBRTtJQUVKLDZEQUE2RCxDQUFDLElBQVU7UUFDdEUsU0FBUyxxQkFBcUI7WUFDNUIsT0FBTyxVQUFJLENBQUMsV0FBVyxDQUFDLEVBQUUsT0FBTyxFQUFFLEdBQUcsRUFBRSxHQUFHLE1BQU0sSUFBSSxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQy9FLENBQUM7UUFFRCxNQUFNLENBQUMsR0FBRyxxQkFBcUIsRUFBRSxDQUFDO1FBQ2xDLElBQUksT0FBTyxDQUFDO1FBQ1osSUFBSTtZQUNGLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNaO1FBQUMsT0FBTyxDQUFDLEVBQUU7WUFDVixPQUFPLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQztTQUNyQjtRQUVELElBQUksQ0FBQyxFQUFFLENBQUMsT0FBTyxJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsdUJBQXVCLENBQUMsQ0FBQyxDQUFDO1FBQzlELElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUNkLENBQUM7SUFFRCxpQkFBaUIsRUFBRTtRQUNqQiwyQkFBMkIsQ0FBQyxJQUFVO1lBQ3BDLElBQUksQ0FBQyxLQUFLLENBQUMsa0JBQVksQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDckQsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ2QsQ0FBQztRQUVELHFDQUFxQyxDQUFDLElBQVU7WUFDOUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsa0JBQVksQ0FBQyxlQUFlLENBQUM7Z0JBQzlDLE9BQU8sRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHO2FBQ1osQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDbkIsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ2QsQ0FBQztRQUVELHlCQUF5QixDQUFDLElBQVU7WUFDbEMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBWSxDQUFDLGVBQWUsQ0FBQyxLQUFZLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUM5RCxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDZCxDQUFDO1FBRUQsc0JBQXNCLENBQUMsSUFBVTtZQUMvQixNQUFNLEdBQUcsR0FBRyxFQUFFLEdBQUcsRUFBRSxlQUFlLEVBQUUsQ0FBQztZQUNyQyxJQUFJLENBQUMsU0FBUyxDQUFDLGtCQUFZLENBQUMsZUFBZSxDQUFDLEdBQVUsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1lBQzlELElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNkLENBQUM7UUFFRCwyQkFBMkIsQ0FBQyxJQUFVO1lBQ3BDLE1BQU0sV0FBVyxHQUFHLEVBQUUsR0FBRyxFQUFFLGVBQWUsRUFBRSxDQUFDO1lBQzdDLE1BQU0sWUFBWSxHQUFHLFVBQUksQ0FBQyxRQUFRLENBQUM7Z0JBQ2pDLE9BQU8sRUFBRSxHQUFHLEVBQUUsQ0FBQyxXQUFXO2FBQzNCLENBQUMsQ0FBQztZQUNILE1BQU0sR0FBRyxHQUFHLGtCQUFZLENBQUMsZUFBZSxDQUFDLFlBQW1CLENBQVEsQ0FBQztZQUNyRSxJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsRUFBRSxXQUFXLENBQUMsQ0FBQztZQUNwQyxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxXQUFXLENBQUMsQ0FBQztZQUMxQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDZCxDQUFDO1FBRUQsZ0NBQWdDLENBQUMsSUFBVTtZQUN6QyxNQUFNLFdBQVcsR0FBRyxFQUFFLEdBQUcsRUFBRSxlQUFlLEVBQUUsQ0FBQztZQUM3QyxNQUFNLFlBQVksR0FBRyxXQUFLLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQ2pELE1BQU0sR0FBRyxHQUFHLGtCQUFZLENBQUMsZUFBZSxDQUFDLFlBQVksQ0FBUSxDQUFDO1lBQzlELElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxFQUFFLFdBQVcsQ0FBQyxDQUFDO1lBQ3BDLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxFQUFFLFdBQVcsQ0FBQyxDQUFDO1lBQzFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNkLENBQUM7S0FDRjtDQUNGLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBUZXN0IH0gZnJvbSAnbm9kZXVuaXQnO1xuaW1wb3J0IHsgRm4sIGlzUmVzb2x2YWJsZU9iamVjdCwgTGF6eSwgU3RhY2ssIFRva2VuLCBUb2tlbml6YXRpb24gfSBmcm9tICcuLi9saWInO1xuaW1wb3J0IHsgY3JlYXRlVG9rZW5Eb3VibGUsIGV4dHJhY3RUb2tlbkRvdWJsZSB9IGZyb20gJy4uL2xpYi9wcml2YXRlL2VuY29kaW5nJztcbmltcG9ydCB7IEludHJpbnNpYyB9IGZyb20gJy4uL2xpYi9wcml2YXRlL2ludHJpbnNpYyc7XG5pbXBvcnQgeyBmaW5kVG9rZW5zIH0gZnJvbSAnLi4vbGliL3ByaXZhdGUvcmVzb2x2ZSc7XG5pbXBvcnQgeyBJUmVzb2x2YWJsZSB9IGZyb20gJy4uL2xpYi9yZXNvbHZhYmxlJztcbmltcG9ydCB7IGV2YWx1YXRlQ0ZOIH0gZnJvbSAnLi9ldmFsdWF0ZS1jZm4nO1xuXG5leHBvcnQgPSB7XG4gICdyZXNvbHZlIGEgcGxhaW4gb2xkIG9iamVjdCBzaG91bGQganVzdCByZXR1cm4gdGhlIG9iamVjdCcodGVzdDogVGVzdCkge1xuICAgIGNvbnN0IG9iaiA9IHsgUGxhaW5PbGRPYmplY3Q6IDEyMywgQXJyYXk6IFsgMSwgMiwgMyBdIH07XG4gICAgdGVzdC5kZWVwRXF1YWwocmVzb2x2ZShvYmopLCBvYmopO1xuICAgIHRlc3QuZG9uZSgpO1xuICB9LFxuXG4gICdpZiBhIHZhbHVlIGlzIGFuIG9iamVjdCB3aXRoIGEgdG9rZW4gdmFsdWUsIGl0IHdpbGwgYmUgZXZhbHVhdGVkJyh0ZXN0OiBUZXN0KSB7XG4gICAgY29uc3Qgb2JqID0ge1xuICAgICAgUmVndWxhclZhbHVlOiAnaGVsbG8nLFxuICAgICAgTGF6eVZhbHVlOiBuZXcgSW50cmluc2ljKCdXb3JsZCcpXG4gICAgfTtcblxuICAgIHRlc3QuZGVlcEVxdWFsKHJlc29sdmUob2JqKSwge1xuICAgICAgUmVndWxhclZhbHVlOiAnaGVsbG8nLFxuICAgICAgTGF6eVZhbHVlOiAnV29ybGQnXG4gICAgfSk7XG5cbiAgICB0ZXN0LmRvbmUoKTtcbiAgfSxcblxuICAndG9rZW5zIGFyZSBldmFsdWF0ZWQgYW55d2hlcmUgaW4gdGhlIG9iamVjdCB0cmVlJyh0ZXN0OiBUZXN0KSB7XG4gICAgY29uc3Qgb2JqID0gbmV3IFByb21pc2UxKCk7XG4gICAgY29uc3QgYWN0dWFsID0gcmVzb2x2ZSh7IE9iajogb2JqIH0pO1xuXG4gICAgdGVzdC5kZWVwRXF1YWwoYWN0dWFsLCB7XG4gICAgICBPYmo6IFtcbiAgICAgICAge1xuICAgICAgICBEYXRhOiB7XG4gICAgICAgICAgc3RyaW5nUHJvcDogXCJoZWxsb1wiLFxuICAgICAgICAgIG51bWJlclByb3A6IDEyMzRcbiAgICAgICAgfSxcbiAgICAgICAgUmVjdXJzZTogNDJcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICBEYXRhOiB7XG4gICAgICAgICAgc3RyaW5nUHJvcDogXCJoZWxsb1wiLFxuICAgICAgICAgIG51bWJlclByb3A6IDEyMzRcbiAgICAgICAgfSxcbiAgICAgICAgUmVjdXJzZTogNDJcbiAgICAgICAgfVxuICAgICAgXVxuICAgIH0pO1xuXG4gICAgdGVzdC5kb25lKCk7XG4gIH0sXG5cbiAgJ3Rva2VucyBhcmUgZXZhbHVhdGVkIHJlY3Vyc2l2ZWx5Jyh0ZXN0OiBUZXN0KSB7XG4gICAgY29uc3Qgb2JqID0gbmV3IFByb21pc2UxKCk7XG4gICAgY29uc3QgYWN0dWFsID0gcmVzb2x2ZShuZXcgSW50cmluc2ljKHsgT2JqOiBvYmogfSkpO1xuXG4gICAgdGVzdC5kZWVwRXF1YWwoYWN0dWFsLCB7XG4gICAgICBPYmo6IFtcbiAgICAgICAge1xuICAgICAgICBEYXRhOiB7XG4gICAgICAgICAgc3RyaW5nUHJvcDogXCJoZWxsb1wiLFxuICAgICAgICAgIG51bWJlclByb3A6IDEyMzRcbiAgICAgICAgfSxcbiAgICAgICAgUmVjdXJzZTogNDJcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICBEYXRhOiB7XG4gICAgICAgICAgc3RyaW5nUHJvcDogXCJoZWxsb1wiLFxuICAgICAgICAgIG51bWJlclByb3A6IDEyMzRcbiAgICAgICAgfSxcbiAgICAgICAgUmVjdXJzZTogNDJcbiAgICAgICAgfVxuICAgICAgXVxuICAgIH0pO1xuXG4gICAgdGVzdC5kb25lKCk7XG4gIH0sXG5cbiAgJ2VtcHR5IGFycmF5cyBvciBvYmplY3RzIGFyZSBrZXB0Jyh0ZXN0OiBUZXN0KSB7XG4gICAgdGVzdC5kZWVwRXF1YWwocmVzb2x2ZSh7IH0pLCB7IH0pO1xuICAgIHRlc3QuZGVlcEVxdWFsKHJlc29sdmUoWyBdKSwgWyBdKTtcblxuICAgIGNvbnN0IG9iaiA9IHtcbiAgICAgIFByb3AxOiAxMjM0LFxuICAgICAgUHJvcDI6IHsgfSxcbiAgICAgIFByb3AzOiBbIF0sXG4gICAgICBQcm9wNDogJ2hlbGxvJyxcbiAgICAgIFByb3A1OiB7XG4gICAgICAgIFByb3BBOiB7IH0sXG4gICAgICAgIFByb3BCOiB7XG4gICAgICAgICAgUHJvcEM6IFsgdW5kZWZpbmVkLCB1bmRlZmluZWQgXSxcbiAgICAgICAgICBQcm9wRDogJ1lvb2hvbydcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICB0ZXN0LmRlZXBFcXVhbChyZXNvbHZlKG9iaiksIHtcbiAgICAgIFByb3AxOiAxMjM0LFxuICAgICAgUHJvcDI6IHsgfSxcbiAgICAgIFByb3AzOiBbIF0sXG4gICAgICBQcm9wNDogJ2hlbGxvJyxcbiAgICAgIFByb3A1OiB7XG4gICAgICAgIFByb3BBOiB7IH0sXG4gICAgICAgIFByb3BCOiB7XG4gICAgICAgICAgUHJvcEM6IFsgXSxcbiAgICAgICAgICBQcm9wRDogJ1lvb2hvbydcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuXG4gICAgdGVzdC5kb25lKCk7XG4gIH0sXG5cbiAgJ2lmIGFuIG9iamVjdCBoYXMgYSBcInJlc29sdmVcIiBwcm9wZXJ0eSB0aGF0IGlzIG5vdCBhIGZ1bmN