firebase-rules-parser
Version:
Parser for Firebase rule files
443 lines (442 loc) • 37.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const __1 = require("..");
describe('Firebase Rules', () => {
describe('Path matching', () => {
const ruleFile = `service cloud.firestore {
match /databases/{database}/documents {
match /organizations/{doc} {
allow read: if true;
}
}
}`;
it('Will give ', () => {
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile);
expect(rules.hasAccess('/databases/DEFAULT/documents/organizations/mindhive', {
auth: undefined,
resource: undefined,
}).read).toBe(true);
expect(rules.hasAccess('/databases/DEFAULT/documents/someother', {
auth: undefined,
resource: undefined,
})).toEqual({});
});
});
describe('Path matching', () => {
const ruleFile = (left, rule, right) => `service cloud.firestore {
match /databases/{database}/documents {
match /organizations/{doc} {
allow read, write: if ${left} ${rule} ${right};
}
}
}`;
const path = '/databases/DEFAULT/documents/organizations/mindhive';
const result = (value) => ({
read: value,
write: value,
});
describe('Comparization Rules', () => {
it('Will support greater than (>)', () => {
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile(5, '>', 2));
expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(true));
});
it('Will support greater or equal than (>=)', () => {
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile(5, '>=', 5));
expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(true));
});
it('Will support less or equal than (<=)', () => {
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile(5, '<=', 3));
expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(false));
});
it('Will support less than (<)', () => {
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile(3, '<', 4));
expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(true));
});
it('Will support equality (==)', () => {
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile(3, '==', 3));
expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(true));
});
it('Will support inequality (!=)', () => {
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile(3, '!=', 2));
expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(true));
});
});
describe('Parenthesis', () => {
it('Will support parenthesis, (2 + 3) == 5', () => {
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile('(2 + 3)', '==', 5));
expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(true));
});
it('Will support recuresive parenthesis resolvling, (2 + (4 * 3)) == 14', () => {
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile('(2 + (4 * 3))', '==', 14));
expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(true));
});
});
describe('Arithmetics', () => {
it('Will do addition, (5 + 2) == 7', () => {
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile('(5 + 2)', '==', 7));
expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(true));
});
it('Will do subtraction, (3 - 2) == 1', () => {
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile('(3 - 2)', '==', 1));
expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(true));
});
it('Will do multipication, (3 * 2) == 6', () => {
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile('(3 * 2)', '==', 6));
expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(true));
});
it('Will do division, (4 / 2) == 2', () => {
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile('(4 / 2)', '==', 2));
expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(true));
});
});
describe('Logical operations', () => {
it('Will support logical or, (5 == 2) || true', () => {
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile('(5 == 2)', '||', true));
expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(true));
});
it('Will support logical and, (5 == 2) && true', () => {
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile('(5 == 2)', '&&', true));
expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(false));
});
it('Will support logical operations withour parenthesis, 5 == 2 || true', () => {
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile('5 == 2', '||', true));
expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(true));
});
});
describe('Unary operations', () => {
it('Will support negation, (10+(-5)) == 5', () => {
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile('(10+(-5))', '==', 5));
expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(true));
});
it('Will support exclusion, !true == false', () => {
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile('!true', '==', false));
expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(true));
});
});
});
describe('Functions', () => {
it('will support function calls without arguments', () => {
const ruleFile = `service cloud.firestore {
match /databases/{database}/documents {
function common() {
return true;
}
match /organizations/{doc} {
allow read: if common();
}
}
}`;
const path = '/databases/DEFAULT/documents/organizations/mindhive';
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile);
expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual({
read: true,
});
});
it('will support function calls expressions in arguments', () => {
const ruleFile = `service cloud.firestore {
match /databases/{database}/documents {
function common(value1, value2) {
return value1 == value2;
}
match /organizations/{doc} {
allow read: if common(2 + 4, 2 * 3);
}
}
}`;
const path = '/databases/DEFAULT/documents/organizations/mindhive';
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile);
expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual({
read: true,
});
});
});
describe('Object references', () => {
it('will support basic request object reference calls', () => {
const ruleFile = `service cloud.firestore {
match /databases/{database}/documents {
match /organizations/{doc} {
allow read: if request.auth != null;
}
}
}`;
const path = '/databases/DEFAULT/documents/organizations/mindhive';
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile);
expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual({
read: true,
});
});
it('will match given auth uid value (double quotes)', () => {
const ruleFile = `service cloud.firestore {
match /databases/{database}/documents {
match /organizations/{doc} {
allow read: if request.auth.uid == "ABC";
}
}
}`;
const path = '/databases/DEFAULT/documents/organizations/mindhive';
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile);
rules.request.auth.uid = 'ABC';
expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual({
read: true,
});
});
it('will match given auth uid value (single quotes)', () => {
const ruleFile = `service cloud.firestore {
match /databases/{database}/documents {
match /organizations/{doc} {
allow read: if request.auth.uid == 'ABC';
}
}
}`;
const path = '/databases/DEFAULT/documents/organizations/mindhive';
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile);
rules.request.auth.uid = 'ABC';
expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual({
read: true,
});
});
it('will match given auth uid value (empty string)', () => {
const ruleFile = `service cloud.firestore {
match /databases/{database}/documents {
match /organizations/{doc} {
allow read: if request.auth.uid == '';
}
}
}`;
const path = '/databases/DEFAULT/documents/organizations/mindhive';
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile);
rules.request.auth.uid = '';
expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual({
read: true,
});
});
it('will support a map in operator', () => {
const ruleFile = `service cloud.firestore {
match /databases/{database}/documents {
match /organizations/{doc} {
allow read: if 'auth' in request;
}
}
}`;
const path = '/databases/DEFAULT/documents/organizations/mindhive';
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile);
expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual({
read: true,
});
});
// it('will give a null value error if object member do not exists', () => {
// const ruleFile = `service cloud.firestore {
// match /databases/{database}/documents {
// match /organizations/{doc} {
// allow read: if request.auth.daa == '';
// }
// }
// }`;
// const path = '/databases/DEFAULT/documents/organizations/mindhive';
// const rules = new RulesParser().init(ruleFile);
// expect(() => rules.hasAccess(path, createFirebaseRulesContext())).toThrow();
// });
});
describe('arrays', () => {
it('will read a cell value from an array', () => {
const ruleFile = `service cloud.firestore {
match /databases/{database}/documents {
match /organizations/{doc} {
allow read: if resource.data.list[1] == 'Joy';
}
}
}`;
const path = '/databases/DEFAULT/documents/organizations/mindhive';
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile);
rules.resource.data = {
list: ['Happy', 'Joy'],
};
expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual({
read: true,
});
});
it('will match arrays to be equal', () => {
const ruleFile = `service cloud.firestore {
match /databases/{database}/documents {
match /organizations/{doc} {
allow read: if resource.data.list == [1, 2];
}
}
}`;
const path = '/databases/DEFAULT/documents/organizations/mindhive';
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile);
rules.resource.data = {
list: [1, 2],
};
expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual({
read: true,
});
});
it('will support a list in operator', () => {
const ruleFile = `service cloud.firestore {
match /databases/{database}/documents {
match /organizations/{doc} {
allow read: if 2 in [1, 2];
}
}
}`;
const path = '/databases/DEFAULT/documents/organizations/mindhive';
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile);
expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual({
read: true,
});
});
});
describe('exists -function', () => {
it('will read a cell value from an array', () => {
const ruleFile = `service cloud.firestore {
match /databases/{database}/documents {
match /organizations/{doc} {
allow read: if exists(/databases/$(database)/documents/users/$(request.auth.uid));
}
}
}`;
const path = '/databases/DEFAULT/documents/organizations/mindhive';
const context = __1.createFirebaseRulesContext();
context.onExistsCall = () => true;
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile);
rules.request.auth.uid = '123';
expect(rules.hasAccess(path, context)).toEqual({
read: true,
});
});
});
describe('get -function', () => {
it('will call onGet event handler when get is executed on rules code', () => {
const ruleFile = `service cloud.firestore {
match /databases/{database}/documents {
match /organizations/{doc} {
allow read: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.value == 'cool';
}
}
}`;
const path = '/databases/DEFAULT/documents/organizations/mindhive';
const context = __1.createFirebaseRulesContext();
context.onGetCall = () => ({
data: {
value: 'cool',
},
id: '123',
});
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile);
rules.request.auth.uid = '123';
rules.resource.data = {
value: 'cool',
};
expect(rules.hasAccess(path, context)).toEqual({
read: true,
});
});
it('will return a get data as a function return and function call can point into its fields', () => {
const ruleFile = `service cloud.firestore {
match /databases/{database}/documents {
match /organizations/{doc} {
function test() {
return get(/databases/$(database)/documents/users/$(request.auth.uid));
}
allow read: if test().data.value == 'cool';
}
}
}`;
const path = '/databases/DEFAULT/documents/organizations/mindhive';
const context = __1.createFirebaseRulesContext();
context.onGetCall = () => ({
data: {
value: 'cool',
},
id: '123',
});
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile);
rules.request.auth.uid = '123';
rules.resource.data = {
value: 'cool',
};
expect(rules.hasAccess(path, context)).toEqual({
read: true,
});
});
});
describe('string member functions', () => {
it('will trim input string', () => {
const ruleFile = `service cloud.firestore {
match /databases/{database}/documents {
match /organizations/{doc} {
allow read: if ' cool '.trim() == 'cool';
}
}
}`;
const path = '/databases/DEFAULT/documents/organizations/mindhive';
const context = __1.createFirebaseRulesContext();
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile);
expect(rules.hasAccess(path, context)).toEqual({
read: true,
});
});
it('will lowercase input string', () => {
const ruleFile = `service cloud.firestore {
match /databases/{database}/documents {
match /organizations/{doc} {
allow read: if 'COOL'.lower() == 'cool';
}
}
}`;
const path = '/databases/DEFAULT/documents/organizations/mindhive';
const context = __1.createFirebaseRulesContext();
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile);
expect(rules.hasAccess(path, context)).toEqual({
read: true,
});
});
it('will uppercase input string', () => {
const ruleFile = `service cloud.firestore {
match /databases/{database}/documents {
match /organizations/{doc} {
allow read: if 'Cool'.upper() == 'COOL';
}
}
}`;
const path = '/databases/DEFAULT/documents/organizations/mindhive';
const context = __1.createFirebaseRulesContext();
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile);
expect(rules.hasAccess(path, context)).toEqual({
read: true,
});
});
it('will return a size of input string', () => {
const ruleFile = `service cloud.firestore {
match /databases/{database}/documents {
match /organizations/{doc} {
allow read: if 'Cool'.size() == 4;
}
}
}`;
const path = '/databases/DEFAULT/documents/organizations/mindhive';
const context = __1.createFirebaseRulesContext();
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile);
expect(rules.hasAccess(path, context)).toEqual({
read: true,
});
});
it('will match regex pattern of input string', () => {
const ruleFile = `service cloud.firestore {
match /databases/{database}/documents {
match /organizations/{doc} {
allow read: if 'This is very cool thingie'.matches('.*cool.*') == true;
}
}
}`;
const path = '/databases/DEFAULT/documents/organizations/mindhive';
const context = __1.createFirebaseRulesContext();
const rules = new __1.FirebaseRulesIntepreter().init(ruleFile);
expect(rules.hasAccess(path, context)).toEqual({
read: true,
});
});
});
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguc3BlYy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9pbnRlcHJldGVyL19fc3BlY3NfXy9pbmRleC5zcGVjLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsMEJBQXlFO0FBRXpFLFFBQVEsQ0FBQyxnQkFBZ0IsRUFBRSxHQUFHLEVBQUU7SUFDOUIsUUFBUSxDQUFDLGVBQWUsRUFBRSxHQUFHLEVBQUU7UUFDN0IsTUFBTSxRQUFRLEdBQUc7Ozs7OztNQU1mLENBQUM7UUFFSCxFQUFFLENBQUMsWUFBWSxFQUFFLEdBQUcsRUFBRTtZQUNwQixNQUFNLEtBQUssR0FBRyxJQUFJLDJCQUF1QixFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBRTNELE1BQU0sQ0FDSixLQUFLLENBQUMsU0FBUyxDQUFDLHFEQUFxRCxFQUFFO2dCQUNyRSxJQUFJLEVBQUUsU0FBUztnQkFDZixRQUFRLEVBQUUsU0FBUzthQUNwQixDQUFDLENBQUMsSUFBSSxDQUNSLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBRWIsTUFBTSxDQUNKLEtBQUssQ0FBQyxTQUFTLENBQUMsd0NBQXdDLEVBQUU7Z0JBQ3hELElBQUksRUFBRSxTQUFTO2dCQUNmLFFBQVEsRUFBRSxTQUFTO2FBQ3BCLENBQUMsQ0FDSCxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUNoQixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLGVBQWUsRUFBRSxHQUFHLEVBQUU7UUFDN0IsTUFBTSxRQUFRLEdBQUcsQ0FBQyxJQUErQixFQUFFLElBQVksRUFBRSxLQUFnQyxFQUFFLEVBQUUsQ0FDbkc7OztxQ0FHK0IsSUFBSSxJQUFJLElBQUksSUFBSSxLQUFLOzs7UUFHbEQsQ0FBQztRQUNMLE1BQU0sSUFBSSxHQUFHLHFEQUFxRCxDQUFDO1FBRW5FLE1BQU0sTUFBTSxHQUFHLENBQUMsS0FBYyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQ2xDLElBQUksRUFBRSxLQUFLO1lBQ1gsS0FBSyxFQUFFLEtBQUs7U0FDYixDQUFDLENBQUM7UUFFSCxRQUFRLENBQUMscUJBQXFCLEVBQUUsR0FBRyxFQUFFO1lBQ25DLEVBQUUsQ0FBQywrQkFBK0IsRUFBRSxHQUFHLEVBQUU7Z0JBQ3ZDLE1BQU0sS0FBSyxHQUFHLElBQUksMkJBQXVCLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDdEUsTUFBTSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLDhCQUEwQixFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztZQUNwRixDQUFDLENBQUMsQ0FBQztZQUNILEVBQUUsQ0FBQyx5Q0FBeUMsRUFBRSxHQUFHLEVBQUU7Z0JBQ2pELE1BQU0sS0FBSyxHQUFHLElBQUksMkJBQXVCLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDdkUsTUFBTSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLDhCQUEwQixFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztZQUNwRixDQUFDLENBQUMsQ0FBQztZQUNILEVBQUUsQ0FBQyxzQ0FBc0MsRUFBRSxHQUFHLEVBQUU7Z0JBQzlDLE1BQU0sS0FBSyxHQUFHLElBQUksMkJBQXVCLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDdkUsTUFBTSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLDhCQUEwQixFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztZQUNyRixDQUFDLENBQUMsQ0FBQztZQUNILEVBQUUsQ0FBQyw0QkFBNEIsRUFBRSxHQUFHLEVBQUU7Z0JBQ3BDLE1BQU0sS0FBSyxHQUFHLElBQUksMkJBQXVCLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDdEUsTUFBTSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLDhCQUEwQixFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztZQUNwRixDQUFDLENBQUMsQ0FBQztZQUNILEVBQUUsQ0FBQyw0QkFBNEIsRUFBRSxHQUFHLEVBQUU7Z0JBQ3BDLE1BQU0sS0FBSyxHQUFHLElBQUksMkJBQXVCLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDdkUsTUFBTSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLDhCQUEwQixFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztZQUNwRixDQUFDLENBQUMsQ0FBQztZQUVILEVBQUUsQ0FBQyw4QkFBOEIsRUFBRSxHQUFHLEVBQUU7Z0JBQ3RDLE1BQU0sS0FBSyxHQUFHLElBQUksMkJBQXVCLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDdkUsTUFBTSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLDhCQUEwQixFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztZQUNwRixDQUFDLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO1FBQ0gsUUFBUSxDQUFDLGFBQWEsRUFBRSxHQUFHLEVBQUU7WUFDM0IsRUFBRSxDQUFDLHdDQUF3QyxFQUFFLEdBQUcsRUFBRTtnQkFDaEQsTUFBTSxLQUFLLEdBQUcsSUFBSSwyQkFBdUIsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUMvRSxNQUFNLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsOEJBQTBCLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQ3BGLENBQUMsQ0FBQyxDQUFDO1lBRUgsRUFBRSxDQUFDLHFFQUFxRSxFQUFFLEdBQUcsRUFBRTtnQkFDN0UsTUFBTSxLQUFLLEdBQUcsSUFBSSwyQkFBdUIsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsZUFBZSxFQUFFLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO2dCQUN0RixNQUFNLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsOEJBQTBCLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQ3BGLENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUM7UUFFSCxRQUFRLENBQUMsYUFBYSxFQUFFLEdBQUcsRUFBRTtZQUMzQixFQUFFLENBQUMsZ0NBQWdDLEVBQUUsR0FBRyxFQUFFO2dCQUN4QyxNQUFNLEtBQUssR0FBRyxJQUFJLDJCQUF1QixFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQy9FLE1BQU0sQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSw4QkFBMEIsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7WUFDcEYsQ0FBQyxDQUFDLENBQUM7WUFDSCxFQUFFLENBQUMsbUNBQW1DLEVBQUUsR0FBRyxFQUFFO2dCQUMzQyxNQUFNLEtBQUssR0FBRyxJQUFJLDJCQUF1QixFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQy9FLE1BQU0sQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSw4QkFBMEIsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7WUFDcEYsQ0FBQyxDQUFDLENBQUM7WUFDSCxFQUFFLENBQUMscUNBQXFDLEVBQUUsR0FBRyxFQUFFO2dCQUM3QyxNQUFNLEtBQUssR0FBRyxJQUFJLDJCQUF1QixFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQy9FLE1BQU0sQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSw4QkFBMEIsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7WUFDcEYsQ0FBQyxDQUFDLENBQUM7WUFDSCxFQUFFLENBQUMsZ0NBQWdDLEVBQUUsR0FBRyxFQUFFO2dCQUN4QyxNQUFNLEtBQUssR0FBRyxJQUFJLDJCQUF1QixFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQy9FLE1BQU0sQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSw4QkFBMEIsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7WUFDcEYsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztRQUVILFFBQVEsQ0FBQyxvQkFBb0IsRUFBRSxHQUFHLEVBQUU7WUFDbEMsRUFBRSxDQUFDLDJDQUEyQyxFQUFFLEdBQUcsRUFBRTtnQkFDbkQsTUFBTSxLQUFLLEdBQUcsSUFBSSwyQkFBdUIsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsVUFBVSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO2dCQUNuRixNQUFNLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsOEJBQTBCLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQ3BGLENBQUMsQ0FBQyxDQUFDO1lBQ0gsRUFBRSxDQUFDLDRDQUE0QyxFQUFFLEdBQUcsRUFBRTtnQkFDcEQsTUFBTSxLQUFLLEdBQUcsSUFBSSwyQkFBdUIsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsVUFBVSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO2dCQUNuRixNQUFNLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsOEJBQTBCLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1lBQ3JGLENBQUMsQ0FBQyxDQUFDO1lBRUgsRUFBRSxDQUFDLHFFQUFxRSxFQUFFLEdBQUcsRUFBRTtnQkFDN0UsTUFBTSxLQUFLLEdBQUcsSUFBSSwyQkFBdUIsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO2dCQUNqRixNQUFNLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsOEJBQTBCLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQ3BGLENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUM7UUFFSCxRQUFRLENBQUMsa0JBQWtCLEVBQUUsR0FBRyxFQUFFO1lBQ2hDLEVBQUUsQ0FBQyx1Q0FBdUMsRUFBRSxHQUFHLEVBQUU7Z0JBQy9DLE1BQU0sS0FBSyxHQUFHLElBQUksMkJBQXVCLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFdBQVcsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDakYsTUFBTSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLDhCQUEwQixFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztZQUNwRixDQUFDLENBQUMsQ0FBQztZQUNILEVBQUUsQ0FBQyx3Q0FBd0MsRUFBRSxHQUFHLEVBQUU7Z0JBQ2hELE1BQU0sS0FBSyxHQUFHLElBQUksMkJBQXVCLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztnQkFDakYsTUFBTSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLDhCQUEwQixFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztZQUNwRixDQUFDLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxRQUFRLENBQUMsV0FBVyxFQUFFLEdBQUcsRUFBRTtRQUN6QixFQUFFLENBQUMsK0NBQStDLEVBQUUsR0FBRyxFQUFFO1lBQ3ZELE1BQU0sUUFBUSxHQUFHOzs7Ozs7Ozs7UUFTZixDQUFDO1lBQ0gsTUFBTSxJQUFJLEdBQUcscURBQXFELENBQUM7WUFFbkUsTUFBTSxLQUFLLEdBQUcsSUFBSSwyQkFBdUIsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUMzRCxNQUFNLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsOEJBQTBCLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDO2dCQUNsRSxJQUFJLEVBQUUsSUFBSTthQUNYLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLHNEQUFzRCxFQUFFLEdBQUcsRUFBRTtZQUM5RCxNQUFNLFFBQVEsR0FBRzs7Ozs7Ozs7O1FBU2YsQ0FBQztZQUNILE1BQU0sSUFBSSxHQUFHLHFEQUFxRCxDQUFDO1lBRW5FLE1BQU0sS0FBSyxHQUFHLElBQUksMkJBQXVCLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDM0QsTUFBTSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLDhCQUEwQixFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQztnQkFDbEUsSUFBSSxFQUFFLElBQUk7YUFDWCxDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLG1CQUFtQixFQUFFLEdBQUcsRUFBRTtRQUNqQyxFQUFFLENBQUMsbURBQW1ELEVBQUUsR0FBRyxFQUFFO1lBQzNELE1BQU0sUUFBUSxHQUFHOzs7Ozs7UUFNZixDQUFDO1lBQ0gsTUFBTSxJQUFJLEdBQUcscURBQXFELENBQUM7WUFFbkUsTUFBTSxLQUFLLEdBQUcsSUFBSSwyQkFBdUIsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUMzRCxNQUFNLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsOEJBQTBCLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDO2dCQUNsRSxJQUFJLEVBQUUsSUFBSTthQUNYLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLGlEQUFpRCxFQUFFLEdBQUcsRUFBRTtZQUN6RCxNQUFNLFFBQVEsR0FBRzs7Ozs7O1FBTWYsQ0FBQztZQUNILE1BQU0sSUFBSSxHQUFHLHFEQUFxRCxDQUFDO1lBRW5FLE1BQU0sS0FBSyxHQUFHLElBQUksMkJBQXVCLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDM0QsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsR0FBRyxHQUFHLEtBQUssQ0FBQztZQUMvQixNQUFNLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsOEJBQTBCLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDO2dCQUNsRSxJQUFJLEVBQUUsSUFBSTthQUNYLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLGlEQUFpRCxFQUFFLEdBQUcsRUFBRTtZQUN6RCxNQUFNLFFBQVEsR0FBRzs7Ozs7O1FBTWYsQ0FBQztZQUNILE1BQU0sSUFBSSxHQUFHLHFEQUFxRCxDQUFDO1lBRW5FLE1BQU0sS0FBSyxHQUFHLElBQUksMkJBQXVCLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDM0QsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsR0FBRyxHQUFHLEtBQUssQ0FBQztZQUMvQixNQUFNLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsOEJBQTBCLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDO2dCQUNsRSxJQUFJLEVBQUUsSUFBSTthQUNYLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO1FBQ0gsRUFBRSxDQUFDLGdEQUFnRCxFQUFFLEdBQUcsRUFBRTtZQUN4RCxNQUFNLFFBQVEsR0FBRzs7Ozs7O1FBTWYsQ0FBQztZQUNILE1BQU0sSUFBSSxHQUFHLHFEQUFxRCxDQUFDO1lBRW5FLE1BQU0sS0FBSyxHQUFHLElBQUksMkJBQXVCLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDM0QsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQztZQUM1QixNQUFNLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsOEJBQTBCLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDO2dCQUNsRSxJQUFJLEVBQUUsSUFBSTthQUNYLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLGdDQUFnQyxFQUFFLEdBQUcsRUFBRTtZQUN4QyxNQUFNLFFBQVEsR0FBRzs7Ozs7O1FBTWYsQ0FBQztZQUNILE1BQU0sSUFBSSxHQUFHLHFEQUFxRCxDQUFDO1lBRW5FLE1BQU0sS0FBSyxHQUFHLElBQUksMkJBQXVCLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDM0QsTUFBTSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLDhCQUEwQixFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQztnQkFDbEUsSUFBSSxFQUFFLElBQUk7YUFDWCxDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztRQUVILDRFQUE0RTtRQUM1RSxnREFBZ0Q7UUFDaEQsOENBQThDO1FBQzlDLHFDQUFxQztRQUNyQyxpREFBaUQ7UUFDakQsVUFBVTtRQUNWLFFBQVE7UUFDUixRQUFRO1FBQ1Isd0VBQXdFO1FBRXhFLG9EQUFvRDtRQUNwRCxpRkFBaUY7UUFDakYsTUFBTTtJQUNSLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLFFBQVEsRUFBRSxHQUFHLEVBQUU7UUFDdEIsRUFBRSxDQUFDLHNDQUFzQyxFQUFFLEdBQUcsRUFBRTtZQUM5QyxNQUFNLFFBQVEsR0FBRzs7Ozs7O1FBTWYsQ0FBQztZQUNILE1BQU0sSUFBSSxHQUFHLHFEQUFxRCxDQUFDO1lBRW5FLE1BQU0sS0FBSyxHQUFHLElBQUksMkJBQXVCLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDM0QsS0FBSyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEdBQUc7Z0JBQ3BCLElBQUksRUFBRSxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUM7YUFDdkIsQ0FBQztZQUNGLE1BQU0sQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSw4QkFBMEIsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUM7Z0JBQ2xFLElBQUksRUFBRSxJQUFJO2FBQ1gsQ0FBQyxDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsK0JBQStCLEVBQUUsR0FBRyxFQUFFO1lBQ3ZDLE1BQU0sUUFBUSxHQUFHOzs7Ozs7UUFNZixDQUFDO1lBQ0gsTUFBTSxJQUFJLEdBQUcscURBQXFELENBQUM7WUFFbkUsTUFBTSxLQUFLLEdBQUcsSUFBSSwyQkFBdUIsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUMzRCxLQUFLLENBQUMsUUFBUSxDQUFDLElBQUksR0FBRztnQkFDcEIsSUFBSSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQzthQUNiLENBQUM7WUFDRixNQUFNLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsOEJBQTBCLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDO2dCQUNsRSxJQUFJLEVBQUUsSUFBSTthQUNYLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLGlDQUFpQyxFQUFFLEdBQUcsRUFBRTtZQUN6QyxNQUFNLFFBQVEsR0FBRzs7Ozs7O1FBTWYsQ0FBQztZQUNILE1BQU0sSUFBSSxHQUFHLHFEQUFxRCxDQUFDO1lBRW5FLE1BQU0sS0FBSyxHQUFHLElBQUksMkJBQXVCLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDM0QsTUFBTSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLDhCQUEwQixFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQztnQkFDbEUsSUFBSSxFQUFFLElBQUk7YUFDWCxDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ0gsUUFBUSxDQUFDLGtCQUFrQixFQUFFLEdBQUcsRUFBRTtRQUNoQyxFQUFFLENBQUMsc0NBQXNDLEVBQUUsR0FBRyxFQUFFO1lBQzlDLE1BQU0sUUFBUSxHQUFHOzs7Ozs7TUFNakIsQ0FBQztZQUNELE1BQU0sSUFBSSxHQUFHLHFEQUFxRCxDQUFDO1lBRW5FLE1BQU0sT0FBTyxHQUFHLDhCQUEwQixFQUFFLENBQUM7WUFFN0MsT0FBTyxDQUFDLFlBQVksR0FBRyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUM7WUFFbEMsTUFBTSxLQUFLLEdBQUcsSUFBSSwyQkFBdUIsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUUzRCxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLEdBQUcsS0FBSyxDQUFDO1lBRS9CLE1BQU0sQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQztnQkFDN0MsSUFBSSxFQUFFLElBQUk7YUFDWCxDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ0gsUUFBUSxDQUFDLGVBQWUsRUFBRSxHQUFHLEVBQUU7UUFDN0IsRUFBRSxDQUFDLGtFQUFrRSxFQUFFLEdBQUcsRUFBRTtZQUMxRSxNQUFNLFFBQVEsR0FBRzs7Ozs7O01BTWpCLENBQUM7WUFDRCxNQUFNLElBQUksR0FBRyxxREFBcUQsQ0FBQztZQUNuRSxNQUFNLE9BQU8sR0FBRyw4QkFBMEIsRUFBRSxDQUFDO1lBRTdDLE9BQU8sQ0FBQyxTQUFTLEdBQUcsR0FBRyxFQUFFLENBQUMsQ0FBQztnQkFDekIsSUFBSSxFQUFFO29CQUNKLEtBQUssRUFBRSxNQUFNO2lCQUNkO2dCQUNELEVBQUUsRUFBRSxLQUFLO2FBQ1YsQ0FBQyxDQUFDO1lBQ0gsTUFBTSxLQUFLLEdBQUcsSUFBSSwyQkFBdUIsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUUzRCxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLEdBQUcsS0FBSyxDQUFDO1lBQy9CLEtBQUssQ0FBQyxRQUFRLENBQUMsSUFBSSxHQUFHO2dCQUNwQixLQUFLLEVBQUUsTUFBTTthQUNkLENBQUM7WUFFRixNQUFNLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUM7Z0JBQzdDLElBQUksRUFBRSxJQUFJO2FBQ1gsQ0FBQyxDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMseUZBQXlGLEVBQUUsR0FBRyxFQUFFO1lBQ2pHLE1BQU0sUUFBUSxHQUFHOzs7Ozs7Ozs7O01BVWpCLENBQUM7WUFDRCxNQUFNLElBQUksR0FBRyxxREFBcUQsQ0FBQztZQUNuRSxNQUFNLE9BQU8sR0FBRyw4QkFBMEIsRUFBRSxDQUFDO1lBRTdDLE9BQU8sQ0FBQyxTQUFTLEdBQUcsR0FBRyxFQUFFLENBQUMsQ0FBQztnQkFDekIsSUFBSSxFQUFFO29CQUNKLEtBQUssRUFBRSxNQUFNO2lCQUNkO2dCQUNELEVBQUUsRUFBRSxLQUFLO2FBQ1YsQ0FBQyxDQUFDO1lBQ0gsTUFBTSxLQUFLLEdBQUcsSUFBSSwyQkFBdUIsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUUzRCxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLEdBQUcsS0FBSyxDQUFDO1lBQy9CLEtBQUssQ0FBQyxRQUFRLENBQUMsSUFBSSxHQUFHO2dCQUNwQixLQUFLLEVBQUUsTUFBTTthQUNkLENBQUM7WUFFRixNQUFNLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUM7Z0JBQzdDLElBQUksRUFBRSxJQUFJO2FBQ1gsQ0FBQyxDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQyx5QkFBeUIsRUFBRSxHQUFHLEVBQUU7UUFDdkMsRUFBRSxDQUFDLHdCQUF3QixFQUFFLEdBQUcsRUFBRTtZQUNoQyxNQUFNLFFBQVEsR0FBRzs7Ozs7O01BTWpCLENBQUM7WUFDRCxNQUFNLElBQUksR0FBRyxxREFBcUQsQ0FBQztZQUNuRSxNQUFNLE9BQU8sR0FBRyw4QkFBMEIsRUFBRSxDQUFDO1lBQzdDLE1BQU0sS0FBSyxHQUFHLElBQUksMkJBQXVCLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7WUFFM0QsTUFBTSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDO2dCQUM3QyxJQUFJLEVBQUUsSUFBSTthQUNYLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLDZCQUE2QixFQUFFLEdBQUcsRUFBRTtZQUNyQyxNQUFNLFFBQVEsR0FBRzs7Ozs7O1FBTWYsQ0FBQztZQUNILE1BQU0sSUFBSSxHQUFHLHFEQUFxRCxDQUFDO1lBQ25FLE1BQU0sT0FBTyxHQUFHLDhCQUEwQixFQUFFLENBQUM7WUFDN0MsTUFBTSxLQUFLLEdBQUcsSUFBSSwyQkFBdUIsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUUzRCxNQUFNLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUM7Z0JBQzdDLElBQUksRUFBRSxJQUFJO2FBQ1gsQ0FBQyxDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsNkJBQTZCLEVBQUUsR0FBRyxFQUFFO1lBQ3JDLE1BQU0sUUFBUSxHQUFHOzs7Ozs7UUFNZixDQUFDO1lBQ0gsTUFBTSxJQUFJLEdBQUcscURBQXFELENBQUM7WUFDbkUsTUFBTSxPQUFPLEdBQUcsOEJBQTBCLEVBQUUsQ0FBQztZQUM3QyxNQUFNLEtBQUssR0FBRyxJQUFJLDJCQUF1QixFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBRTNELE1BQU0sQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQztnQkFDN0MsSUFBSSxFQUFFLElBQUk7YUFDWCxDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxvQ0FBb0MsRUFBRSxHQUFHLEVBQUU7WUFDNUMsTUFBTSxRQUFRLEdBQUc7Ozs7OztRQU1mLENBQUM7WUFDSCxNQUFNLElBQUksR0FBRyxxREFBcUQsQ0FBQztZQUNuRSxNQUFNLE9BQU8sR0FBRyw4QkFBMEIsRUFBRSxDQUFDO1lBQzdDLE1BQU0sS0FBSyxHQUFHLElBQUksMkJBQXVCLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7WUFFM0QsTUFBTSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDO2dCQUM3QyxJQUFJLEVBQUUsSUFBSTthQUNYLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLDBDQUEwQyxFQUFFLEdBQUcsRUFBRTtZQUNsRCxNQUFNLFFBQVEsR0FBRzs7Ozs7O1FBTWYsQ0FBQztZQUNILE1BQU0sSUFBSSxHQUFHLHFEQUFxRCxDQUFDO1lBQ25FLE1BQU0sT0FBTyxHQUFHLDhCQUEwQixFQUFFLENBQUM7WUFDN0MsTUFBTSxLQUFLLEdBQUcsSUFBSSwyQkFBdUIsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUUzRCxNQUFNLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUM7Z0JBQzdDLElBQUksRUFBRSxJQUFJO2FBQ1gsQ0FBQyxDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIn0=