From ef2610a8f9cca58f09b005717ebe2a026331fe5b Mon Sep 17 00:00:00 2001 From: Jan Monschke Date: Fri, 7 Jan 2022 14:52:37 +0100 Subject: [PATCH 01/11] [Security Solution][Investigations] Fix favorite filter behaviour in timeline search (#122265) * fix: apply correct search options for favorited timelines * test: add timeline overview page tests Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../integration/timelines/overview.tsx | 88 +++++++++++++++++++ .../cypress/objects/timeline.ts | 12 ++- .../cypress/screens/timelines.ts | 8 ++ .../public/timelines/pages/timelines_page.tsx | 2 +- .../saved_object/timelines/index.test.ts | 5 +- .../timeline/saved_object/timelines/index.ts | 46 +++++++--- 6 files changed, 143 insertions(+), 18 deletions(-) create mode 100644 x-pack/plugins/security_solution/cypress/integration/timelines/overview.tsx diff --git a/x-pack/plugins/security_solution/cypress/integration/timelines/overview.tsx b/x-pack/plugins/security_solution/cypress/integration/timelines/overview.tsx new file mode 100644 index 0000000000000..f961f94d5f867 --- /dev/null +++ b/x-pack/plugins/security_solution/cypress/integration/timelines/overview.tsx @@ -0,0 +1,88 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + TIMELINES_OVERVIEW_TABLE, + TIMELINES_OVERVIEW_ONLY_FAVORITES, + TIMELINES_OVERVIEW_SEARCH, +} from '../../screens/timelines'; + +import { + getTimeline, + getFavoritedTimeline, + sharedTimelineTitleFragment, +} from '../../objects/timeline'; + +import { cleanKibana } from '../../tasks/common'; + +import { loginAndWaitForPageWithoutDateRange } from '../../tasks/login'; +import { createTimeline, favoriteTimeline } from '../../tasks/api_calls/timelines'; + +import { TIMELINES_URL } from '../../urls/navigation'; + +describe('timeline overview search', () => { + before(() => { + cleanKibana(); + + createTimeline(getFavoritedTimeline()) + .then((response) => response.body.data.persistTimeline.timeline.savedObjectId) + .then((timelineId) => favoriteTimeline({ timelineId, timelineType: 'default' })); + createTimeline(getTimeline()); + + loginAndWaitForPageWithoutDateRange(TIMELINES_URL); + }); + + beforeEach(() => { + cy.get(TIMELINES_OVERVIEW_SEARCH).clear(); + }); + + it('should show all timelines when no search term was entered', () => { + cy.get(TIMELINES_OVERVIEW_TABLE).contains(getTimeline().title); + cy.get(TIMELINES_OVERVIEW_TABLE).contains(getFavoritedTimeline().title); + }); + + it('should show the correct favorite count without search', () => { + cy.get(TIMELINES_OVERVIEW_ONLY_FAVORITES).contains(1); + }); + + it('should show the correct timelines when the favorite filter is activated', () => { + cy.get(TIMELINES_OVERVIEW_ONLY_FAVORITES).click(); // enable the filter + + cy.get(TIMELINES_OVERVIEW_TABLE).contains(getTimeline().title).should('not.exist'); + cy.get(TIMELINES_OVERVIEW_TABLE).contains(getFavoritedTimeline().title); + cy.get(TIMELINES_OVERVIEW_ONLY_FAVORITES).contains(1); + + cy.get(TIMELINES_OVERVIEW_ONLY_FAVORITES).click(); // disable the filter + }); + + it('should find the correct timeline and have the correct favorite count when searching by timeline title', () => { + cy.get(TIMELINES_OVERVIEW_SEARCH).type(`"${getTimeline().title}"{enter}`); + + cy.get(TIMELINES_OVERVIEW_TABLE).contains(getFavoritedTimeline().title).should('not.exist'); + cy.get(TIMELINES_OVERVIEW_TABLE).contains(getTimeline().title); + cy.get(TIMELINES_OVERVIEW_ONLY_FAVORITES).contains(0); + }); + + it('should find the correct timelines when searching for favorited timelines', () => { + cy.get(TIMELINES_OVERVIEW_ONLY_FAVORITES).click(); // enable the filter + cy.get(TIMELINES_OVERVIEW_SEARCH).type(`"${getFavoritedTimeline().title}"{enter}`); + + cy.get(TIMELINES_OVERVIEW_TABLE).contains(getTimeline().title).should('not.exist'); + cy.get(TIMELINES_OVERVIEW_TABLE).contains(getFavoritedTimeline().title); + cy.get(TIMELINES_OVERVIEW_ONLY_FAVORITES).contains(1); + + cy.get(TIMELINES_OVERVIEW_ONLY_FAVORITES).click(); // disable the filter + }); + + it('should find the correct timelines when both favorited and non-favorited timelines match', () => { + cy.get(TIMELINES_OVERVIEW_SEARCH).type(`"${sharedTimelineTitleFragment}"{enter}`); + + cy.get(TIMELINES_OVERVIEW_TABLE).contains(getTimeline().title); + cy.get(TIMELINES_OVERVIEW_TABLE).contains(getFavoritedTimeline().title); + cy.get(TIMELINES_OVERVIEW_ONLY_FAVORITES).contains(1); + }); +}); diff --git a/x-pack/plugins/security_solution/cypress/objects/timeline.ts b/x-pack/plugins/security_solution/cypress/objects/timeline.ts index 27d901f5a74ac..028de768ae204 100644 --- a/x-pack/plugins/security_solution/cypress/objects/timeline.ts +++ b/x-pack/plugins/security_solution/cypress/objects/timeline.ts @@ -34,14 +34,24 @@ export const getFilter = (): TimelineFilter => ({ value: 'exists', }); +export const sharedTimelineTitleFragment = 'Timeline'; + export const getTimeline = (): CompleteTimeline => ({ - title: 'Security Timeline', + title: `Security ${sharedTimelineTitleFragment}`, description: 'This is the best timeline', query: 'host.name: *', notes: 'Yes, the best timeline', filter: getFilter(), }); +export const getFavoritedTimeline = (): CompleteTimeline => ({ + title: `Darkest ${sharedTimelineTitleFragment}`, + description: 'This is the darkest timeline', + query: 'host.name: *', + notes: 'Yes, the darkest timeline, you heard me right', + filter: getFilter(), +}); + export const getIndicatorMatchTimelineTemplate = (): CompleteTimeline => ({ ...getTimeline(), title: 'Generic Threat Match Timeline', diff --git a/x-pack/plugins/security_solution/cypress/screens/timelines.ts b/x-pack/plugins/security_solution/cypress/screens/timelines.ts index 21febda41d062..c9f06fa88b52f 100644 --- a/x-pack/plugins/security_solution/cypress/screens/timelines.ts +++ b/x-pack/plugins/security_solution/cypress/screens/timelines.ts @@ -45,3 +45,11 @@ export const TIMELINES_TABLE = '[data-test-subj="timelines-table"]'; export const TIMELINES_USERNAME = '[data-test-subj="username"]'; export const REFRESH_BUTTON = '[data-test-subj="refreshButton-linkIcon"]'; + +export const TIMELINES_OVERVIEW = '[data-test-subj="timelines-container"]'; + +export const TIMELINES_OVERVIEW_ONLY_FAVORITES = `${TIMELINES_OVERVIEW} [data-test-subj="only-favorites-toggle"]`; + +export const TIMELINES_OVERVIEW_SEARCH = `${TIMELINES_OVERVIEW} [data-test-subj="search-bar"]`; + +export const TIMELINES_OVERVIEW_TABLE = `${TIMELINES_OVERVIEW} [data-test-subj="timelines-table"]`; diff --git a/x-pack/plugins/security_solution/public/timelines/pages/timelines_page.tsx b/x-pack/plugins/security_solution/public/timelines/pages/timelines_page.tsx index b91c4ac59e303..6151316cc303d 100644 --- a/x-pack/plugins/security_solution/public/timelines/pages/timelines_page.tsx +++ b/x-pack/plugins/security_solution/public/timelines/pages/timelines_page.tsx @@ -79,7 +79,7 @@ export const TimelinesPageComponent: React.FC = () => { - + { test('should send correct options for counts of favorite timeline', async () => { expect(mockFindSavedObject.mock.calls[5][0]).toEqual({ filter: - 'not siem-ui-timeline.attributes.status: draft and not siem-ui-timeline.attributes.status: immutable', + 'not siem-ui-timeline.attributes.status: draft and not siem-ui-timeline.attributes.status: immutable and siem-ui-timeline.attributes.favorite.keySearch: dXNlcm5hbWU=', page: 1, perPage: 1, - search: ' dXNlcm5hbWU=', - searchFields: ['title', 'description', 'favorite.keySearch'], + searchFields: ['title', 'description'], type: 'siem-ui-timeline', }); }); diff --git a/x-pack/plugins/security_solution/server/lib/timeline/saved_object/timelines/index.ts b/x-pack/plugins/security_solution/server/lib/timeline/saved_object/timelines/index.ts index cc28e0c9eb853..d9bc1ccfa2fe4 100644 --- a/x-pack/plugins/security_solution/server/lib/timeline/saved_object/timelines/index.ts +++ b/x-pack/plugins/security_solution/server/lib/timeline/saved_object/timelines/index.ts @@ -161,9 +161,26 @@ const getTimelineTypeFilter = ( : `not siem-ui-timeline.attributes.status: ${TimelineStatus.immutable}`; const filters = [typeFilter, draftFilter, immutableFilter]; - return filters.filter((f) => f != null).join(' and '); + return combineFilters(filters); }; +const getTimelineFavoriteFilter = ({ + onlyUserFavorite, + request, +}: { + onlyUserFavorite: boolean | null; + request: FrameworkRequest; +}) => { + if (!onlyUserFavorite) { + return null; + } + const username = request.user?.username ?? UNAUTHENTICATED_USER; + return `siem-ui-timeline.attributes.favorite.keySearch: ${convertStringToBase64(username)}`; +}; + +const combineFilters = (filters: Array) => + filters.filter((f) => f != null).join(' and '); + export const getExistingPrepackagedTimelines = async ( request: FrameworkRequest, countsOnly?: boolean, @@ -197,15 +214,19 @@ export const getAllTimeline = async ( status: TimelineStatusLiteralWithNull, timelineType: TimelineTypeLiteralWithNull ): Promise => { + const searchTerm = search != null ? search : undefined; + const searchFields = ['title', 'description']; + const filter = combineFilters([ + getTimelineTypeFilter(timelineType ?? null, status ?? null), + getTimelineFavoriteFilter({ onlyUserFavorite, request }), + ]); const options: SavedObjectsFindOptions = { type: timelineSavedObjectType, perPage: pageInfo.pageSize, page: pageInfo.pageIndex, - search: search != null ? search : undefined, - searchFields: onlyUserFavorite - ? ['title', 'description', 'favorite.keySearch'] - : ['title', 'description'], - filter: getTimelineTypeFilter(timelineType ?? null, status ?? null), + filter, + search: searchTerm, + searchFields, sortField: sort != null ? sort.sortField : undefined, sortOrder: sort != null ? sort.sortOrder : undefined, }; @@ -233,10 +254,14 @@ export const getAllTimeline = async ( const favoriteTimelineOptions = { type: timelineSavedObjectType, - searchFields: ['title', 'description', 'favorite.keySearch'], + search: searchTerm, + searchFields, perPage: 1, page: 1, - filter: getTimelineTypeFilter(timelineType ?? null, TimelineStatus.active), + filter: combineFilters([ + getTimelineTypeFilter(timelineType ?? null, TimelineStatus.active), + getTimelineFavoriteFilter({ onlyUserFavorite: true, request }), + ]), }; const result = await Promise.all([ @@ -623,11 +648,6 @@ const getSavedTimeline = async (request: FrameworkRequest, timelineId: string) = const getAllSavedTimeline = async (request: FrameworkRequest, options: SavedObjectsFindOptions) => { const userName = request.user?.username ?? UNAUTHENTICATED_USER; const savedObjectsClient = request.context.core.savedObjects.client; - if (options.searchFields != null && options.searchFields.includes('favorite.keySearch')) { - options.search = `${options.search != null ? options.search : ''} ${ - userName != null ? convertStringToBase64(userName) : null - }`; - } const savedObjects = await savedObjectsClient.find(options); From 119a2d780df761c7b5c9eb821be742f962308aaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20Kopyci=C5=84ski?= Date: Fri, 7 Jan 2022 17:24:49 +0100 Subject: [PATCH 02/11] [Osquery] Add `KibanaThemeProvider` to the app (#122051) --- x-pack/plugins/osquery/public/application.tsx | 48 ++++++++++--------- .../osquery_action/index.tsx | 17 ++++--- .../plugins/osquery/public/shared_imports.ts | 1 + 3 files changed, 36 insertions(+), 30 deletions(-) diff --git a/x-pack/plugins/osquery/public/application.tsx b/x-pack/plugins/osquery/public/application.tsx index 20d5132f5c452..17d47f757a2a6 100644 --- a/x-pack/plugins/osquery/public/application.tsx +++ b/x-pack/plugins/osquery/public/application.tsx @@ -15,7 +15,7 @@ import { ThemeProvider } from 'styled-components'; import { QueryClientProvider } from 'react-query'; import { ReactQueryDevtools } from 'react-query/devtools'; -import { useUiSetting$ } from '../../../../src/plugins/kibana_react/public'; +import { useUiSetting$, KibanaThemeProvider } from './shared_imports'; import { Storage } from '../../../../src/plugins/kibana_utils/public'; import { AppMountParameters, CoreStart } from '../../../../src/core/public'; import { AppPluginStartDependencies } from './types'; @@ -44,32 +44,34 @@ const OsqueryAppContext = () => { export const renderApp = ( core: CoreStart, services: AppPluginStartDependencies, - { element, history }: AppMountParameters, + { element, history, theme$ }: AppMountParameters, storage: Storage, kibanaVersion: string ) => { ReactDOM.render( - - - - - - - - - - - - , + + + + + + + + + + + + + + , element ); diff --git a/x-pack/plugins/osquery/public/shared_components/osquery_action/index.tsx b/x-pack/plugins/osquery/public/shared_components/osquery_action/index.tsx index 8fc289b7ef36b..7bc54b44de775 100644 --- a/x-pack/plugins/osquery/public/shared_components/osquery_action/index.tsx +++ b/x-pack/plugins/osquery/public/shared_components/osquery_action/index.tsx @@ -17,6 +17,7 @@ import { KibanaContextProvider, useKibana } from '../../common/lib/kibana'; import { LiveQuery } from '../../live_queries'; import { queryClient } from '../../query_client'; import { OsqueryIcon } from '../../components/osquery_icon'; +import { KibanaThemeProvider } from '../../shared_imports'; interface OsqueryActionProps { metadata?: { @@ -134,13 +135,15 @@ export const OsqueryAction = React.memo(OsqueryActionComponent); // @ts-expect-error update types const OsqueryActionWrapperComponent = ({ services, ...props }) => ( - - - - - - - + + + + + + + + + ); const OsqueryActionWrapper = React.memo(OsqueryActionWrapperComponent); diff --git a/x-pack/plugins/osquery/public/shared_imports.ts b/x-pack/plugins/osquery/public/shared_imports.ts index c0f9d35ba51a8..c8f163b5bccfc 100644 --- a/x-pack/plugins/osquery/public/shared_imports.ts +++ b/x-pack/plugins/osquery/public/shared_imports.ts @@ -43,3 +43,4 @@ export type { ERROR_CODE } from '../../../../src/plugins/es_ui_shared/static/for export { EuiCodeEditor } from '../../../../src/plugins/es_ui_shared/public'; export type { EuiCodeEditorProps } from '../../../../src/plugins/es_ui_shared/public'; +export { useUiSetting$, KibanaThemeProvider } from '../../../../src/plugins/kibana_react/public'; From 526367c83169482575bd0303f4d085a27c52889a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 7 Jan 2022 14:04:01 -0500 Subject: [PATCH 03/11] Update node-forge to v1.1.0 (#122475) Co-authored-by: Renovate Bot --- package.json | 5 +++-- yarn.lock | 16 ++++++++-------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index e6be8c8f1f068..0118e28918310 100644 --- a/package.json +++ b/package.json @@ -86,6 +86,7 @@ "**/istanbul-lib-coverage": "^3.2.0", "**/json-schema": "^0.4.0", "**/minimist": "^1.2.5", + "**/node-forge": "^1.1.0", "**/pdfkit/crypto-js": "4.0.0", "**/react-syntax-highlighter": "^15.3.1", "**/react-syntax-highlighter/**/highlight.js": "^10.4.1", @@ -299,7 +300,7 @@ "mustache": "^2.3.2", "nock": "12.0.3", "node-fetch": "^2.6.1", - "node-forge": "^0.10.0", + "node-forge": "^1.1.0", "nodemailer": "^6.6.2", "normalize-path": "^3.0.0", "object-hash": "^1.3.1", @@ -623,7 +624,7 @@ "@types/nock": "^10.0.3", "@types/node": "16.10.2", "@types/node-fetch": "^2.5.7", - "@types/node-forge": "^0.10.10", + "@types/node-forge": "^1.0.0", "@types/nodemailer": "^6.4.0", "@types/normalize-path": "^3.0.0", "@types/object-hash": "^1.3.0", diff --git a/yarn.lock b/yarn.lock index e19fac5e0a395..e3adc81008ffc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6280,10 +6280,10 @@ "@types/node" "*" form-data "^3.0.0" -"@types/node-forge@^0.10.10": - version "0.10.10" - resolved "https://registry.yarnpkg.com/@types/node-forge/-/node-forge-0.10.10.tgz#07ffccf0f7f3ebb97de67446555912803be50e7b" - integrity sha512-iixn5bedlE9fm/5mN7fPpXraXlxCVrnNWHZekys8c5fknridLVWGnNRqlaWpenwaijIuB3bNI0lEOm+JD6hZUA== +"@types/node-forge@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/node-forge/-/node-forge-1.0.0.tgz#0b4e9507209485945115a4db4879f39632230593" + integrity sha512-h0bgwPKq5u99T9Gor4qtV1lCZ41xNkai0pie1n/a2mh2/4+jENWOlo7AJ4YKxTZAnSZ8FRurUpdIN7ohaPPuHA== dependencies: "@types/node" "*" @@ -20509,10 +20509,10 @@ node-fetch@2.6.1, node-fetch@^1.0.1, node-fetch@^2.3.0, node-fetch@^2.6.1: resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== -node-forge@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3" - integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA== +node-forge@^0.10.0, node-forge@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.1.0.tgz#53e61b039eea78b442a4e13f9439dbd61b5cd3a8" + integrity sha512-HeZMFB41cirRysIhIFFgORmR51/qhkjRTXXIH9QiwS3AjF9L9Kre9XvOnyE7NMubOSHDuN0GsrFpnqhlJcNWTA== node-gyp-build@^4.2.3: version "4.2.3" From 25f4d0cc0bb77e10c113f30ffbcbd38b1bf0bfac Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Mon, 10 Jan 2022 10:35:32 +0100 Subject: [PATCH 04/11] [Lens] Wait for vis before asserting (#122333) --- x-pack/test/functional/page_objects/lens_page.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/test/functional/page_objects/lens_page.ts b/x-pack/test/functional/page_objects/lens_page.ts index f55b05bc65a05..4e562067637c5 100644 --- a/x-pack/test/functional/page_objects/lens_page.ts +++ b/x-pack/test/functional/page_objects/lens_page.ts @@ -474,6 +474,7 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont async useFixAction() { await testSubjects.click('errorFixAction'); + await this.waitForVisualization(); }, async isTopLevelAggregation() { From 786f41631a47938748754d70df527671c08f5068 Mon Sep 17 00:00:00 2001 From: Abdul Wahab Zahid Date: Mon, 10 Jan 2022 10:49:00 +0100 Subject: [PATCH 05/11] [Uptime][Monitor Management UI] Add Enabled column in monitor management monitors list table. (#121682) (elastic/uptime/issues/415) * Add enabled column in monitor management monitors list table. --- .../monitor_list/actions.tsx | 2 +- .../monitor_list/monitor_enabled.test.tsx | 79 ++++++++++++ .../monitor_list/monitor_enabled.tsx | 113 ++++++++++++++++++ .../monitor_list/monitor_list.tsx | 28 +++-- .../monitor_management/monitor_management.tsx | 2 +- .../public/state/api/monitor_management.ts | 4 +- 6 files changed, 215 insertions(+), 13 deletions(-) create mode 100644 x-pack/plugins/uptime/public/components/monitor_management/monitor_list/monitor_enabled.test.tsx create mode 100644 x-pack/plugins/uptime/public/components/monitor_management/monitor_list/monitor_enabled.tsx diff --git a/x-pack/plugins/uptime/public/components/monitor_management/monitor_list/actions.tsx b/x-pack/plugins/uptime/public/components/monitor_management/monitor_list/actions.tsx index cf3606270f0bd..b0567b1723d9e 100644 --- a/x-pack/plugins/uptime/public/components/monitor_management/monitor_list/actions.tsx +++ b/x-pack/plugins/uptime/public/components/monitor_management/monitor_list/actions.tsx @@ -10,7 +10,7 @@ import { i18n } from '@kbn/i18n'; import { EuiButtonIcon, EuiFlexItem, EuiFlexGroup, EuiLoadingSpinner } from '@elastic/eui'; import { UptimeSettingsContext } from '../../../contexts'; import { useFetcher, FETCH_STATUS } from '../../../../../observability/public'; -import { deleteMonitor } from '../../../state/api/monitor_management'; +import { deleteMonitor } from '../../../state/api'; import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; interface Props { diff --git a/x-pack/plugins/uptime/public/components/monitor_management/monitor_list/monitor_enabled.test.tsx b/x-pack/plugins/uptime/public/components/monitor_management/monitor_list/monitor_enabled.test.tsx new file mode 100644 index 0000000000000..5130a8bfb5132 --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor_management/monitor_list/monitor_enabled.test.tsx @@ -0,0 +1,79 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { ConfigKey, DataStream, SyntheticsMonitor } from '../../../../common/runtime_types'; +import { render } from '../../../lib/helper/rtl_helpers'; +import { FETCH_STATUS } from '../../../../../observability/public'; +import { spyOnUseFetcher } from '../../../lib/helper/spy_use_fetcher'; +import { MonitorEnabled } from './monitor_enabled'; + +describe('', () => { + const setRefresh = jest.fn(); + const testMonitor = { + [ConfigKey.MONITOR_TYPE]: DataStream.HTTP, + [ConfigKey.ENABLED]: true, + } as unknown as SyntheticsMonitor; + + const assertMonitorEnabled = (button: HTMLButtonElement) => + expect(button).toHaveAttribute('aria-checked', 'true'); + const assertMonitorDisabled = (button: HTMLButtonElement) => + expect(button).toHaveAttribute('aria-checked', 'false'); + + let useFetcher: jest.SpyInstance; + + beforeEach(() => { + useFetcher?.mockClear(); + useFetcher = spyOnUseFetcher({}); + }); + + it('correctly renders "enabled" state', () => { + render(); + + const switchButton = screen.getByRole('switch') as HTMLButtonElement; + assertMonitorEnabled(switchButton); + }); + + it('correctly renders "disabled" state', () => { + render( + + ); + + const switchButton = screen.getByRole('switch') as HTMLButtonElement; + assertMonitorDisabled(switchButton); + }); + + it('toggles on click', () => { + render(); + + const switchButton = screen.getByRole('switch') as HTMLButtonElement; + userEvent.click(switchButton); + assertMonitorDisabled(switchButton); + userEvent.click(switchButton); + assertMonitorEnabled(switchButton); + }); + + it('is disabled while request is in progress', () => { + useFetcher.mockReturnValue({ + data: {}, + status: FETCH_STATUS.LOADING, + refetch: () => {}, + }); + + render(); + const switchButton = screen.getByRole('switch') as HTMLButtonElement; + userEvent.click(switchButton); + + expect(switchButton).toHaveAttribute('disabled'); + }); +}); diff --git a/x-pack/plugins/uptime/public/components/monitor_management/monitor_list/monitor_enabled.tsx b/x-pack/plugins/uptime/public/components/monitor_management/monitor_list/monitor_enabled.tsx new file mode 100644 index 0000000000000..4b3aba5d6a3ab --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor_management/monitor_list/monitor_enabled.tsx @@ -0,0 +1,113 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiSwitch, EuiProgress, EuiSwitchEvent } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import React, { useEffect, useState } from 'react'; +import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; +import { FETCH_STATUS, useFetcher } from '../../../../../observability/public'; +import { ConfigKey, SyntheticsMonitor } from '../../../../common/runtime_types'; +import { setMonitor } from '../../../state/api'; + +interface Props { + id: string; + monitor: SyntheticsMonitor; + setRefresh: React.Dispatch>; +} + +export const MonitorEnabled = ({ id, monitor, setRefresh }: Props) => { + const [isEnabled, setIsEnabled] = useState(null); + + const { notifications } = useKibana(); + + const { status } = useFetcher(() => { + if (isEnabled !== null) { + return setMonitor({ id, monitor: { ...monitor, [ConfigKey.ENABLED]: isEnabled } }); + } + }, [isEnabled]); + + useEffect(() => { + if (status === FETCH_STATUS.FAILURE) { + notifications.toasts.danger({ + title: ( +

+ {getMonitorEnabledUpdateFailureMessage(monitor[ConfigKey.NAME])} +

+ ), + toastLifeTimeMs: 3000, + }); + setIsEnabled(null); + } else if (status === FETCH_STATUS.SUCCESS) { + notifications.toasts.success({ + title: ( +

+ {isEnabled + ? getMonitorEnabledSuccessLabel(monitor[ConfigKey.NAME]) + : getMonitorDisabledSuccessLabel(monitor[ConfigKey.NAME])} +

+ ), + toastLifeTimeMs: 3000, + }); + setRefresh(true); + } + }, [status]); // eslint-disable-line react-hooks/exhaustive-deps + + const enabled = isEnabled ?? monitor[ConfigKey.ENABLED]; + const isLoading = status === FETCH_STATUS.LOADING; + + const handleEnabledChange = (event: EuiSwitchEvent) => { + const checked = event.target.checked; + setIsEnabled(checked); + }; + + return ( +
+ + {isLoading ? ( + + ) : null} +
+ ); +}; + +const ENABLE_MONITOR_LABEL = i18n.translate('xpack.uptime.monitorManagement.enableMonitorLabel', { + defaultMessage: 'Enable monitor', +}); + +const DISABLE_MONITOR_LABEL = i18n.translate('xpack.uptime.monitorManagement.disableMonitorLabel', { + defaultMessage: 'Disable monitor', +}); + +const getMonitorEnabledSuccessLabel = (name: string) => + i18n.translate('xpack.uptime.monitorManagement.monitorEnabledSuccessMessage', { + defaultMessage: 'Monitor {name} enabled successfully.', + values: { name }, + }); + +const getMonitorDisabledSuccessLabel = (name: string) => + i18n.translate('xpack.uptime.monitorManagement.monitorDisabledSuccessMessage', { + defaultMessage: 'Monitor {name} disabled successfully.', + values: { name }, + }); + +const getMonitorEnabledUpdateFailureMessage = (name: string) => + i18n.translate('xpack.uptime.monitorManagement.monitorEnabledUpdateFailureMessage', { + defaultMessage: 'Unable to update monitor {name}.', + values: { name }, + }); diff --git a/x-pack/plugins/uptime/public/components/monitor_management/monitor_list/monitor_list.tsx b/x-pack/plugins/uptime/public/components/monitor_management/monitor_list/monitor_list.tsx index 813511b31761a..75c94c2d07d1e 100644 --- a/x-pack/plugins/uptime/public/components/monitor_management/monitor_list/monitor_list.tsx +++ b/x-pack/plugins/uptime/public/components/monitor_management/monitor_list/monitor_list.tsx @@ -7,12 +7,14 @@ import React, { useContext, useMemo, useCallback } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiBasicTable, EuiPanel, EuiSpacer, EuiLink } from '@elastic/eui'; +import { SyntheticsMonitorSavedObject } from '../../../../common/types'; import { MonitorManagementList as MonitorManagementListState } from '../../../state/reducers/monitor_management'; -import { MonitorFields } from '../../../../common/runtime_types'; +import { MonitorFields, SyntheticsMonitor } from '../../../../common/runtime_types'; import { UptimeSettingsContext } from '../../../contexts'; import { Actions } from './actions'; import { MonitorLocations } from './monitor_locations'; import { MonitorTags } from './tags'; +import { MonitorEnabled } from './monitor_enabled'; import * as labels from '../../overview/monitor_list/translations'; interface Props { @@ -32,7 +34,8 @@ export const MonitorManagementList = ({ setPageSize, setPageIndex, }: Props) => { - const { monitors, total, perPage, page: pageIndex } = list as MonitorManagementListState['list']; + const { total, perPage, page: pageIndex } = list as MonitorManagementListState['list']; + const monitors = list.monitors as SyntheticsMonitorSavedObject[]; const { basePath } = useContext(UptimeSettingsContext); const pagination = useMemo( @@ -84,7 +87,7 @@ export const MonitorManagementList = ({ name: i18n.translate('xpack.uptime.monitorManagement.monitorList.monitorType', { defaultMessage: 'Monitor type', }), - render: ({ type }: Partial) => type, + render: ({ type }: SyntheticsMonitor) => type, }, { align: 'left' as const, @@ -92,7 +95,7 @@ export const MonitorManagementList = ({ name: i18n.translate('xpack.uptime.monitorManagement.monitorList.tags', { defaultMessage: 'Tags', }), - render: ({ tags }: Partial) => (tags ? : null), + render: ({ tags }: SyntheticsMonitor) => (tags ? : null), }, { align: 'left' as const, @@ -100,7 +103,7 @@ export const MonitorManagementList = ({ name: i18n.translate('xpack.uptime.monitorManagement.monitorList.locations', { defaultMessage: 'Locations', }), - render: ({ locations }: Partial) => + render: ({ locations }: SyntheticsMonitor) => locations ? : null, }, { @@ -109,8 +112,7 @@ export const MonitorManagementList = ({ name: i18n.translate('xpack.uptime.monitorManagement.monitorList.schedule', { defaultMessage: 'Schedule', }), - render: ({ schedule }: Partial) => - `@every ${schedule?.number}${schedule?.unit}`, + render: ({ schedule }: SyntheticsMonitor) => `@every ${schedule?.number}${schedule?.unit}`, }, { align: 'left' as const, @@ -118,9 +120,19 @@ export const MonitorManagementList = ({ name: i18n.translate('xpack.uptime.monitorManagement.monitorList.URL', { defaultMessage: 'URL', }), - render: (attributes: Partial) => attributes.urls || attributes.hosts, + render: (attributes: MonitorFields) => attributes.urls || attributes.hosts, truncateText: true, }, + { + align: 'left' as const, + field: 'attributes', + name: i18n.translate('xpack.uptime.monitorManagement.monitorList.enabled', { + defaultMessage: 'Enabled', + }), + render: (attributes: SyntheticsMonitor, record: SyntheticsMonitorSavedObject) => ( + + ), + }, { align: 'left' as const, field: 'id', diff --git a/x-pack/plugins/uptime/public/pages/monitor_management/monitor_management.tsx b/x-pack/plugins/uptime/public/pages/monitor_management/monitor_management.tsx index a272583a2e7b7..0619f4d4bed1c 100644 --- a/x-pack/plugins/uptime/public/pages/monitor_management/monitor_management.tsx +++ b/x-pack/plugins/uptime/public/pages/monitor_management/monitor_management.tsx @@ -24,7 +24,7 @@ export const MonitorManagementPage: React.FC = () => { useEffect(() => { if (refresh) { dispatch(getMonitors({ page: pageIndex, perPage: pageSize })); - setRefresh(false); + setRefresh(false); // TODO: avoid extra re-rendering when `refresh` turn to false (pass down the handler instead) } }, [dispatch, refresh, pageIndex, pageSize]); diff --git a/x-pack/plugins/uptime/public/state/api/monitor_management.ts b/x-pack/plugins/uptime/public/state/api/monitor_management.ts index 33c04c060588d..5f18869257386 100644 --- a/x-pack/plugins/uptime/public/state/api/monitor_management.ts +++ b/x-pack/plugins/uptime/public/state/api/monitor_management.ts @@ -17,14 +17,13 @@ import { import { SyntheticsMonitorSavedObject } from '../../../common/types'; import { apiService } from './utils'; -// TODO: Type the return type from runtime types export const setMonitor = async ({ monitor, id, }: { monitor: SyntheticsMonitor; id?: string; -}): Promise => { +}): Promise => { if (id) { return await apiService.put(`${API_URLS.SYNTHETICS_MONITORS}/${id}`, monitor); } else { @@ -32,7 +31,6 @@ export const setMonitor = async ({ } }; -// TODO, change to monitor runtime type export const getMonitor = async ({ id }: { id: string }): Promise => { return await apiService.get(`${API_URLS.SYNTHETICS_MONITORS}/${id}`); }; From e938f4cb12d6bd8b4ecb8edd9d95b34ec34bdb34 Mon Sep 17 00:00:00 2001 From: Matthias Wilhelm Date: Mon, 10 Jan 2022 11:16:43 +0100 Subject: [PATCH 06/11] [Discover] Unskip flaky histogram time range test (#122324) --- test/functional/apps/discover/_discover.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/test/functional/apps/discover/_discover.ts b/test/functional/apps/discover/_discover.ts index 7becb217c877a..03a8dbcffa2d9 100644 --- a/test/functional/apps/discover/_discover.ts +++ b/test/functional/apps/discover/_discover.ts @@ -38,8 +38,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { after(async () => { await kibanaServer.savedObjects.clean({ types: ['search', 'index-pattern'] }); }); - // FLAKY: https://github.com/elastic/kibana/issues/86602 - describe.skip('query', function () { + describe('query', function () { const queryName1 = 'Query # 1'; it('should show correct time range string by timepicker', async function () { @@ -121,8 +120,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { ); return actualCount === expectedCount; }); - const prevRowData = await PageObjects.discover.getDocTableField(1); - log.debug(`The first timestamp value in doc table before brushing: ${prevRowData}`); + let prevRowData = ''; + // to make sure the table is already rendered + await retry.try(async () => { + prevRowData = await PageObjects.discover.getDocTableField(1); + log.debug(`The first timestamp value in doc table before brushing: ${prevRowData}`); + }); + await PageObjects.discover.brushHistogram(); await PageObjects.discover.waitUntilSearchingHasFinished(); await retry.waitFor('chart rendering complete after being brushed', async () => { From 3cca7f06305e2a322f1b92adabed2c7338b88631 Mon Sep 17 00:00:00 2001 From: Esteban Beltran Date: Mon, 10 Jan 2022 11:18:04 +0100 Subject: [PATCH 07/11] [Security Solution] Remove feature flag trustedAppsByPolicyEnabled (#122107) --- .../common/experimental_features.ts | 1 - .../endpoint_policy_edit_extension.tsx | 111 ++++++++---------- .../pages/policy/view/policy_details.tsx | 17 +-- .../list/policy_trusted_apps_list.test.tsx | 1 - .../components/create_trusted_app_flyout.tsx | 22 +--- .../components/create_trusted_app_form.tsx | 9 +- .../view/trusted_apps_page.test.tsx | 25 ---- .../trusted_apps/view/trusted_apps_page.tsx | 6 +- .../security_solution/server/config.ts | 2 +- .../test/security_solution_endpoint/config.ts | 2 - 10 files changed, 60 insertions(+), 136 deletions(-) diff --git a/x-pack/plugins/security_solution/common/experimental_features.ts b/x-pack/plugins/security_solution/common/experimental_features.ts index 67488ba1612bf..4f43e9b61faf9 100644 --- a/x-pack/plugins/security_solution/common/experimental_features.ts +++ b/x-pack/plugins/security_solution/common/experimental_features.ts @@ -16,7 +16,6 @@ export const allowedExperimentalValues = Object.freeze({ ruleRegistryEnabled: true, tGridEnabled: true, tGridEventRenderedViewEnabled: true, - trustedAppsByPolicyEnabled: true, excludePoliciesInFilterEnabled: false, uebaEnabled: false, disableIsolationUIPendingStatuses: false, diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_edit_extension.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_edit_extension.tsx index e4f2e6e70c02b..4f49ff91b5a8d 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_edit_extension.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_edit_extension.tsx @@ -15,7 +15,6 @@ import { NewPackagePolicy, pagePathGetters, } from '../../../../../../../fleet/public'; -import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; import { INTEGRATIONS_PLUGIN_ID } from '../../../../../../../fleet/common'; import { useAppUrl } from '../../../../../common/lib/kibana/hooks'; import { PolicyDetailsRouteState } from '../../../../../../common/endpoint/types'; @@ -58,10 +57,6 @@ const WrappedPolicyDetailsForm = memo<{ const endpointDetailsLoadingError = usePolicyDetailsSelector(apiError); const { getAppUrl } = useAppUrl(); const [, setLastUpdatedPolicy] = useState(updatedPolicy); - // TODO: Remove this and related code when removing FF - const isTrustedAppsByPolicyEnabled = useIsExperimentalFeatureEnabled( - 'trustedAppsByPolicyEnabled' - ); // When the form is initially displayed, trigger the Redux middleware which is based on // the location information stored via the `userChangedUrl` action. @@ -164,63 +159,59 @@ const WrappedPolicyDetailsForm = memo<{ return (
- {isTrustedAppsByPolicyEnabled ? ( - <> -
- -
- -
-
- - - - - - -
- -
- -
+ <> +
+ +
+ +
+
+ + + + + + +
+ +
+ +
+ +
+
+ + {endpointDetailsLoadingError ? ( + -
-
- - {endpointDetailsLoadingError ? ( - - } - iconType="alert" - color="warning" - data-test-subj="endpiontPolicySettingsLoadingError" - > - {endpointDetailsLoadingError.message} - - ) : !endpointPolicyDetails ? ( - - ) : ( - - )} -
- - ) : ( - - )} + } + iconType="alert" + color="warning" + data-test-subj="endpiontPolicySettingsLoadingError" + > + {endpointDetailsLoadingError.message} + + ) : !endpointPolicyDetails ? ( + + ) : ( + + )} +
+ ); }); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_details.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_details.tsx index b9dd3419062df..df660bedd3ab9 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_details.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_details.tsx @@ -12,10 +12,8 @@ import { EuiCallOut, EuiLoadingSpinner, EuiPageTemplate } from '@elastic/eui'; import { usePolicyDetailsSelector } from './policy_hooks'; import { policyDetails, agentStatusSummary, apiError } from '../store/policy_details/selectors'; import { AgentsSummary } from './agents_summary'; -import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; import { PolicyTabs } from './tabs'; import { AdministrationListPage } from '../../../components/administration_list_page'; -import { PolicyFormLayout } from './policy_forms/components'; import { BackToExternalAppButton, BackToExternalAppButtonProps, @@ -26,10 +24,6 @@ import { useAppUrl } from '../../../../common/lib/kibana'; import { APP_UI_ID } from '../../../../../common/constants'; export const PolicyDetails = React.memo(() => { - // TODO: Remove this and related code when removing FF - const isTrustedAppsByPolicyEnabled = useIsExperimentalFeatureEnabled( - 'trustedAppsByPolicyEnabled' - ); const { state: routeState = {} } = useLocation(); const { getAppUrl } = useAppUrl(); @@ -106,13 +100,8 @@ export const PolicyDetails = React.memo(() => { ); } - // TODO: Remove this and related code when removing FF - if (isTrustedAppsByPolicyEnabled) { - return ; - } - - return ; - }, [isTrustedAppsByPolicyEnabled, policyApiError, policyItem]); + return ; + }, [policyApiError, policyItem]); return ( { headerBackComponent={backToEndpointList} actions={policyApiError ? undefined : headerRightContent} restrictWidth={true} - hasBottomBorder={!isTrustedAppsByPolicyEnabled} // TODO: Remove this and related code when removing FF + hasBottomBorder={false} > {pageBody} diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/trusted_apps/list/policy_trusted_apps_list.test.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/trusted_apps/list/policy_trusted_apps_list.test.tsx index 32568ec2b48ee..67b435f4873a1 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/trusted_apps/list/policy_trusted_apps_list.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/trusted_apps/list/policy_trusted_apps_list.test.tsx @@ -86,7 +86,6 @@ describe('when rendering the PolicyTrustedAppsList', () => { }); mockedApis = policyDetailsPageAllApiHttpMocks(appTestContext.coreStart.http); - appTestContext.setExperimentalFlag({ trustedAppsByPolicyEnabled: true }); waitForAction = appTestContext.middlewareSpy.waitForAction; componentRenderProps = {}; diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_flyout.tsx b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_flyout.tsx index d7404961fd71d..f76ac89474e7b 100644 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_flyout.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_flyout.tsx @@ -51,7 +51,6 @@ import { useTestIdGenerator } from '../../../../components/hooks/use_test_id_gen import { useLicense } from '../../../../../common/hooks/use_license'; import { isGlobalEffectScope } from '../../state/type_guards'; import { NewTrustedApp } from '../../../../../../common/endpoint/types'; -import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; export type CreateTrustedAppFlyoutProps = Omit; export const CreateTrustedAppFlyout = memo( @@ -116,10 +115,6 @@ export const CreateTrustedAppFlyout = memo( [dispatch, formValues] ); - const isTrustedAppsByPolicyEnabled = useIsExperimentalFeatureEnabled( - 'trustedAppsByPolicyEnabled' - ); - const [wasByPolicy, setWasByPolicy] = useState(!isGlobalEffectScope(formValues.effectScope)); // set initial state of `wasByPolicy` that checks if the initial state of the exception was by policy or not useEffect(() => { @@ -133,21 +128,8 @@ export const CreateTrustedAppFlyout = memo( }, [formValues]); const showExpiredLicenseBanner = useMemo(() => { - return ( - isTrustedAppsByPolicyEnabled && - !isPlatinumPlus && - isEditMode && - wasByPolicy && - (!isGlobal || isFormDirty) - ); - }, [ - isTrustedAppsByPolicyEnabled, - isPlatinumPlus, - isEditMode, - isGlobal, - isFormDirty, - wasByPolicy, - ]); + return !isPlatinumPlus && isEditMode && wasByPolicy && (!isGlobal || isFormDirty); + }, [isPlatinumPlus, isEditMode, isGlobal, isFormDirty, wasByPolicy]); // If there was a failure trying to retrieve the Trusted App for edit item, // then redirect back to the list ++ show toast message. diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_form.tsx b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_form.tsx index 5f9b51d52e485..d9b1cc6624042 100644 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_form.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_form.tsx @@ -33,7 +33,6 @@ import { hasSimpleExecutableName, } from '../../../../../../common/endpoint/service/trusted_apps/validations'; -import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; import { isGlobalEffectScope, isMacosLinuxTrustedAppCondition, @@ -238,10 +237,6 @@ export const CreateTrustedAppForm = memo( const dataTestSubj = formProps['data-test-subj']; - const isTrustedAppsByPolicyEnabled = useIsExperimentalFeatureEnabled( - 'trustedAppsByPolicyEnabled' - ); - const isPlatinumPlus = useLicense().isPlatinumPlus(); const isGlobal = useMemo(() => { @@ -519,7 +514,7 @@ export const CreateTrustedAppForm = memo( value={trustedApp.description} onChange={handleDomChangeEvents} fullWidth - compressed={isTrustedAppsByPolicyEnabled} + compressed maxLength={256} data-test-subj={getTestId('descriptionField')} /> @@ -577,7 +572,7 @@ export const CreateTrustedAppForm = memo( data-test-subj={getTestId('conditionsBuilder')} /> - {isTrustedAppsByPolicyEnabled && showAssignmentSection ? ( + {showAssignmentSection ? ( <> diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_page.test.tsx b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_page.test.tsx index 01330eb0e246c..ab0bbaa875a39 100644 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_page.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_page.test.tsx @@ -20,16 +20,11 @@ import { HttpFetchOptions, HttpFetchOptionsWithPath } from 'kibana/public'; import { isFailedResourceState, isLoadedResourceState } from '../state'; import { forceHTMLElementOffsetWidth } from '../../../components/effected_policy_select/test_utils'; import { toUpdateTrustedApp } from '../../../../../common/endpoint/service/trusted_apps/to_update_trusted_app'; -import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; import { licenseService } from '../../../../common/hooks/use_license'; import { FoundExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; import { EXCEPTION_LIST_ITEM_URL } from '@kbn/securitysolution-list-constants'; import { trustedAppsAllHttpMocks } from '../../mocks'; -// TODO: remove this mock when feature flag is removed -jest.mock('../../../../common/hooks/use_experimental_features'); -const useIsExperimentalFeatureEnabledMock = useIsExperimentalFeatureEnabled as jest.Mock; - jest.mock('../../../../common/hooks/use_license', () => { const licenseServiceInstance = { isPlatinumPlus: jest.fn(), @@ -173,7 +168,6 @@ describe('When on the Trusted Apps Page', () => { describe('the license is downgraded to gold or below and the user is editing a per policy TA', () => { beforeEach(async () => { (licenseService.isPlatinumPlus as jest.Mock).mockReturnValue(false); - useIsExperimentalFeatureEnabledMock.mockReturnValue(true); const originalFakeTrustedAppProvider = getFakeTrustedApp.getMockImplementation(); getFakeTrustedApp.mockImplementation(() => { @@ -198,7 +192,6 @@ describe('When on the Trusted Apps Page', () => { describe('the license is downgraded to gold or below and the user is adding a new TA', () => { beforeEach(async () => { (licenseService.isPlatinumPlus as jest.Mock).mockReturnValue(false); - useIsExperimentalFeatureEnabledMock.mockReturnValue(true); const originalFakeTrustedAppProvider = getFakeTrustedApp.getMockImplementation(); getFakeTrustedApp.mockImplementation(() => { @@ -467,7 +460,6 @@ describe('When on the Trusted Apps Page', () => { }); it('should have list of policies populated', async () => { - useIsExperimentalFeatureEnabledMock.mockReturnValue(true); const resetEnv = forceHTMLElementOffsetWidth(); const renderResult = await renderAndClickAddButton(); act(() => { @@ -700,23 +692,6 @@ describe('When on the Trusted Apps Page', () => { expect(flyoutAddButton.disabled).toBe(true); }); }); - - describe('and there is a feature flag for agents policy', () => { - it('should hide agents policy if feature flag is disabled', async () => { - useIsExperimentalFeatureEnabledMock.mockReturnValue(false); - const renderResult = await renderAndClickAddButton(); - expect( - renderResult.queryByTestId('addTrustedAppFlyout-createForm-policySelection') - ).toBeNull(); - }); - it('should display agents policy if feature flag is enabled', async () => { - useIsExperimentalFeatureEnabledMock.mockReturnValue(true); - const renderResult = await renderAndClickAddButton(); - expect( - renderResult.queryByTestId('addTrustedAppFlyout-createForm-policySelection') - ).toBeTruthy(); - }); - }); }); describe('and there are no trusted apps', () => { diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_page.tsx b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_page.tsx index 63cb52785ea96..71076d84c13b1 100644 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_page.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_page.tsx @@ -33,13 +33,9 @@ import { EmptyState } from './components/empty_state'; import { SearchExceptions } from '../../../components/search_exceptions'; import { BackToExternalAppButton } from '../../../components/back_to_external_app_button'; import { ListPageRouteState } from '../../../../../common/endpoint/types'; -import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; import { ManagementPageLoader } from '../../../components/management_page_loader'; export const TrustedAppsPage = memo(() => { - const isTrustedAppsByPolicyEnabled = useIsExperimentalFeatureEnabled( - 'trustedAppsByPolicyEnabled' - ); const dispatch = useDispatch>(); const { state: routeState } = useLocation(); const location = useTrustedAppsSelector(getCurrentLocation); @@ -120,7 +116,7 @@ export const TrustedAppsPage = memo(() => { defaultValue={location.filter} onSearch={handleOnSearch} placeholder={SEARCH_TRUSTED_APP_PLACEHOLDER} - hasPolicyFilter={isTrustedAppsByPolicyEnabled} + hasPolicyFilter={true} policyList={policyList} defaultExcludedPolicies={location.excluded_policies} defaultIncludedPolicies={location.included_policies} diff --git a/x-pack/plugins/security_solution/server/config.ts b/x-pack/plugins/security_solution/server/config.ts index ba1c547a1bbce..b76edf3b50800 100644 --- a/x-pack/plugins/security_solution/server/config.ts +++ b/x-pack/plugins/security_solution/server/config.ts @@ -90,7 +90,7 @@ export const configSchema = schema.object({ * @example * xpack.securitySolution.enableExperimental: * - someCrazyFeature - * - trustedAppsByPolicyEnabled + * - someEvenCrazierFeature */ enableExperimental: schema.arrayOf(schema.string(), { defaultValue: () => [], diff --git a/x-pack/test/security_solution_endpoint/config.ts b/x-pack/test/security_solution_endpoint/config.ts index 2bfb231887ac2..b00df7732ea4f 100644 --- a/x-pack/test/security_solution_endpoint/config.ts +++ b/x-pack/test/security_solution_endpoint/config.ts @@ -44,8 +44,6 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { // always install Endpoint package by default when Fleet sets up `--xpack.fleet.packages.0.name=endpoint`, `--xpack.fleet.packages.0.version=latest`, - // TODO: Remove feature flags once we're good to go - '--xpack.securitySolution.enableExperimental=["trustedAppsByPolicyEnabled"]', ], }, layout: { From f2af5c1bd2e17fda450013d259ee90992907bd55 Mon Sep 17 00:00:00 2001 From: Aleh Zasypkin Date: Mon, 10 Jan 2022 11:43:41 +0100 Subject: [PATCH 08/11] Export all Security, Spaces and EncryptedSavedObjects types referenced in the public API contracts. (#122421) --- .../server/crypto/index.ts | 1 + .../encrypted_saved_objects/server/index.ts | 16 ++++++++++++---- x-pack/plugins/security/common/index.ts | 17 +++++++++++++++-- x-pack/plugins/security/common/model/index.ts | 2 +- x-pack/plugins/security/public/index.ts | 2 ++ x-pack/plugins/security/server/index.ts | 1 + .../public/copy_saved_objects_to_space/index.ts | 6 +++++- x-pack/plugins/spaces/public/index.ts | 3 +++ 8 files changed, 40 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/encrypted_saved_objects/server/crypto/index.ts b/x-pack/plugins/encrypted_saved_objects/server/crypto/index.ts index 532702f213192..c4eec06ae5877 100644 --- a/x-pack/plugins/encrypted_saved_objects/server/crypto/index.ts +++ b/x-pack/plugins/encrypted_saved_objects/server/crypto/index.ts @@ -8,6 +8,7 @@ export type { EncryptedSavedObjectTypeRegistration, SavedObjectDescriptor, + AttributeToEncrypt, } from './encrypted_saved_objects_service'; export { EncryptedSavedObjectsService, descriptorToArray } from './encrypted_saved_objects_service'; export { EncryptionError, EncryptionErrorOperation } from './encryption_error'; diff --git a/x-pack/plugins/encrypted_saved_objects/server/index.ts b/x-pack/plugins/encrypted_saved_objects/server/index.ts index 873c8c0d52cb5..fef302739b7ad 100644 --- a/x-pack/plugins/encrypted_saved_objects/server/index.ts +++ b/x-pack/plugins/encrypted_saved_objects/server/index.ts @@ -10,11 +10,19 @@ import type { PluginConfigDescriptor, PluginInitializerContext } from 'src/core/ import { ConfigSchema } from './config'; import { EncryptedSavedObjectsPlugin } from './plugin'; -export type { EncryptedSavedObjectTypeRegistration } from './crypto'; -export { EncryptionError } from './crypto'; +export type { EncryptedSavedObjectTypeRegistration, AttributeToEncrypt } from './crypto'; +export { EncryptionError, EncryptionErrorOperation } from './crypto'; export type { EncryptedSavedObjectsPluginSetup, EncryptedSavedObjectsPluginStart } from './plugin'; -export type { EncryptedSavedObjectsClient } from './saved_objects'; -export type { IsMigrationNeededPredicate } from './create_migration'; +export type { + EncryptedSavedObjectsClient, + EncryptedSavedObjectsClientOptions, + ClientInstanciator, +} from './saved_objects'; +export type { + IsMigrationNeededPredicate, + CreateEncryptedSavedObjectsMigrationFn, + CreateEncryptedSavedObjectsMigrationFnOpts, +} from './create_migration'; export const config: PluginConfigDescriptor = { schema: ConfigSchema, diff --git a/x-pack/plugins/security/common/index.ts b/x-pack/plugins/security/common/index.ts index 1d05036191635..0da855b153be8 100644 --- a/x-pack/plugins/security/common/index.ts +++ b/x-pack/plugins/security/common/index.ts @@ -5,5 +5,18 @@ * 2.0. */ -export type { SecurityLicense } from './licensing'; -export type { AuthenticatedUser, PrivilegeDeprecationsService } from './model'; +export type { SecurityLicense, SecurityLicenseFeatures, LoginLayout } from './licensing'; +export type { + AuthenticatedUser, + AuthenticationProvider, + PrivilegeDeprecationsService, + PrivilegeDeprecationsRolesByFeatureIdRequest, + PrivilegeDeprecationsRolesByFeatureIdResponse, + Role, + RoleIndexPrivilege, + RoleKibanaPrivilege, + FeaturesPrivileges, + User, + ApiKey, + UserRealm, +} from './model'; diff --git a/x-pack/plugins/security/common/model/index.ts b/x-pack/plugins/security/common/model/index.ts index bc1666af3200c..84d7f261e51a7 100644 --- a/x-pack/plugins/security/common/model/index.ts +++ b/x-pack/plugins/security/common/model/index.ts @@ -8,7 +8,7 @@ export type { ApiKey, ApiKeyToInvalidate, ApiKeyRoleDescriptors } from './api_key'; export type { User, EditUser } from './user'; export { getUserDisplayName } from './user'; -export type { AuthenticatedUser } from './authenticated_user'; +export type { AuthenticatedUser, UserRealm } from './authenticated_user'; export { canUserChangePassword } from './authenticated_user'; export type { AuthenticationProvider } from './authentication_provider'; export { shouldProviderUseLoginForm } from './authentication_provider'; diff --git a/x-pack/plugins/security/public/index.ts b/x-pack/plugins/security/public/index.ts index 55925e142ff24..552442c0b8611 100644 --- a/x-pack/plugins/security/public/index.ts +++ b/x-pack/plugins/security/public/index.ts @@ -19,6 +19,8 @@ export type { SecurityPluginSetup, SecurityPluginStart }; export type { AuthenticatedUser } from '../common/model'; export type { SecurityLicense, SecurityLicenseFeatures } from '../common/licensing'; export type { UserMenuLink, SecurityNavControlServiceStart } from '../public/nav_control'; +export type { UiApi } from './ui_api'; +export type { PersonalInfoProps, ChangePasswordProps } from './account_management'; export type { AuthenticationServiceStart, AuthenticationServiceSetup } from './authentication'; diff --git a/x-pack/plugins/security/server/index.ts b/x-pack/plugins/security/server/index.ts index 8b0ffc3189156..2d85c7e2b2ba1 100644 --- a/x-pack/plugins/security/server/index.ts +++ b/x-pack/plugins/security/server/index.ts @@ -21,6 +21,7 @@ import { SecurityPlugin } from './plugin'; // These exports are part of public Security plugin contract, any change in signature of exported // functions or removal of exports should be considered as a breaking change. export type { + CreateAPIKeyParams, CreateAPIKeyResult, InvalidateAPIKeysParams, InvalidateAPIKeyResult, diff --git a/x-pack/plugins/spaces/public/copy_saved_objects_to_space/index.ts b/x-pack/plugins/spaces/public/copy_saved_objects_to_space/index.ts index 2443c8443c091..cfeb238ce987a 100644 --- a/x-pack/plugins/spaces/public/copy_saved_objects_to_space/index.ts +++ b/x-pack/plugins/spaces/public/copy_saved_objects_to_space/index.ts @@ -6,4 +6,8 @@ */ export { getCopyToSpaceFlyoutComponent } from './components'; -export type { CopyToSpaceFlyoutProps, CopyToSpaceSavedObjectTarget } from './types'; +export type { + CopyToSpaceFlyoutProps, + CopyToSpaceSavedObjectTarget, + CopySavedObjectsToSpaceResponse, +} from './types'; diff --git a/x-pack/plugins/spaces/public/index.ts b/x-pack/plugins/spaces/public/index.ts index 86f1afd234be3..6571e2e22fb75 100644 --- a/x-pack/plugins/spaces/public/index.ts +++ b/x-pack/plugins/spaces/public/index.ts @@ -15,9 +15,12 @@ export type { Space, GetAllSpacesPurpose, GetSpaceResult } from '../common'; export type { SpacesData, SpacesDataEntry, SpacesApi } from './types'; +export type { SpacesManager } from './spaces_manager'; + export type { CopyToSpaceFlyoutProps, CopyToSpaceSavedObjectTarget, + CopySavedObjectsToSpaceResponse, } from './copy_saved_objects_to_space'; export type { LegacyUrlConflictProps, EmbeddableLegacyUrlConflictProps } from './legacy_urls'; From d3691f676aaafd889616f026550cb773391bdb36 Mon Sep 17 00:00:00 2001 From: Marco Liberati Date: Mon, 10 Jan 2022 12:36:04 +0100 Subject: [PATCH 09/11] [Lens] Global filter for formula (#121768) * :sparkles: new global filter feature * :white_check_mark: Add tests * :white_check_mark: Add functional tests * :white_check_mark: Add more tests * :bug: Fix a transition bug with filter + add help message Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../dimension_panel/advanced_options.tsx | 1 + .../dimension_panel/dimension_editor.tsx | 196 ++++++++-------- .../dimension_panel/filtering.tsx | 28 ++- .../operations/definitions/column_types.ts | 2 +- .../formula/editor/formula_editor.tsx | 10 +- .../definitions/formula/formula.test.tsx | 213 +++++++++++++++++- .../definitions/formula/formula.tsx | 19 +- .../operations/definitions/formula/parse.ts | 28 ++- .../operations/definitions/formula/util.ts | 23 ++ .../definitions/formula/validation.ts | 97 +++++++- .../operations/definitions/index.ts | 2 +- x-pack/test/functional/apps/lens/formula.ts | 38 ++++ .../test/functional/page_objects/lens_page.ts | 22 +- 13 files changed, 540 insertions(+), 139 deletions(-) diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/advanced_options.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/advanced_options.tsx index ffd75163e7871..087d2e51f6dd5 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/advanced_options.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/advanced_options.tsx @@ -16,6 +16,7 @@ export function AdvancedOptions(props: { onClick: () => void; showInPopover: boolean; inlineElement: React.ReactElement | null; + helpPopup?: string | null; }>; }) { const [popoverOpen, setPopoverOpen] = useState(false); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.tsx index 6a06130d1cced..2b85e37243237 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.tsx @@ -533,99 +533,6 @@ export function DimensionEditor(props: DimensionEditorProps) { {...services} /> )} - - {!currentFieldIsInvalid && !incompleteInfo && selectedColumn && ( - { - setStateWrapper( - setTimeScaling(columnId, state.layers[layerId], DEFAULT_TIME_SCALE) - ); - }, - showInPopover: Boolean( - operationDefinitionMap[selectedColumn.operationType].timeScalingMode && - operationDefinitionMap[selectedColumn.operationType].timeScalingMode !== - 'disabled' && - Object.values(state.layers[layerId].columns).some( - (col) => col.operationType === 'date_histogram' - ) && - !selectedColumn.timeScale - ), - inlineElement: ( - - ), - }, - { - title: i18n.translate('xpack.lens.indexPattern.filterBy.label', { - defaultMessage: 'Filter by', - }), - dataTestSubj: 'indexPattern-filter-by-enable', - onClick: () => { - setFilterByOpenInitally(true); - setStateWrapper(setFilter(columnId, state.layers[layerId], defaultFilter)); - }, - showInPopover: Boolean( - operationDefinitionMap[selectedColumn.operationType].filterable && - !selectedColumn.filter - ), - inlineElement: - operationDefinitionMap[selectedColumn.operationType].filterable && - selectedColumn.filter ? ( - - ) : null, - }, - { - title: i18n.translate('xpack.lens.indexPattern.timeShift.label', { - defaultMessage: 'Time shift', - }), - dataTestSubj: 'indexPattern-time-shift-enable', - onClick: () => { - setTimeShiftFocused(true); - setStateWrapper(setTimeShift(columnId, state.layers[layerId], '')); - }, - showInPopover: Boolean( - operationDefinitionMap[selectedColumn.operationType].shiftable && - selectedColumn.timeShift === undefined && - (currentIndexPattern.timeFieldName || - Object.values(state.layers[layerId].columns).some( - (col) => col.operationType === 'date_histogram' - )) - ), - inlineElement: - operationDefinitionMap[selectedColumn.operationType].shiftable && - selectedColumn.timeShift !== undefined ? ( - - ) : null, - }, - ]} - /> - )} ); @@ -736,6 +643,109 @@ export function DimensionEditor(props: DimensionEditorProps) { /> {TabContent} + {!isFullscreen && + !currentFieldIsInvalid && + !incompleteInfo && + selectedColumn && + temporaryState === 'none' && + selectedOperationDefinition && ( +
+ { + setStateWrapper( + setTimeScaling(columnId, state.layers[layerId], DEFAULT_TIME_SCALE) + ); + }, + showInPopover: Boolean( + selectedOperationDefinition.timeScalingMode && + selectedOperationDefinition.timeScalingMode !== 'disabled' && + Object.values(state.layers[layerId].columns).some( + (col) => col.operationType === 'date_histogram' + ) && + !selectedColumn.timeScale + ), + inlineElement: ( + + ), + }, + { + title: i18n.translate('xpack.lens.indexPattern.filterBy.label', { + defaultMessage: 'Filter by', + }), + dataTestSubj: 'indexPattern-filter-by-enable', + onClick: () => { + setFilterByOpenInitally(true); + setStateWrapper(setFilter(columnId, state.layers[layerId], defaultFilter)); + }, + showInPopover: Boolean( + selectedOperationDefinition.filterable && !selectedColumn.filter + ), + inlineElement: + selectedOperationDefinition.filterable && selectedColumn.filter ? ( + + ) : null, + }, + { + title: i18n.translate('xpack.lens.indexPattern.timeShift.label', { + defaultMessage: 'Time shift', + }), + dataTestSubj: 'indexPattern-time-shift-enable', + onClick: () => { + setTimeShiftFocused(true); + setStateWrapper(setTimeShift(columnId, state.layers[layerId], '')); + }, + showInPopover: Boolean( + selectedOperationDefinition.shiftable && + selectedColumn.timeShift === undefined && + (currentIndexPattern.timeFieldName || + Object.values(state.layers[layerId].columns).some( + (col) => col.operationType === 'date_histogram' + )) + ), + inlineElement: + selectedOperationDefinition.shiftable && + selectedColumn.timeShift !== undefined ? ( + + ) : null, + }, + ]} + /> +
+ )} + {!isFullscreen && !currentFieldIsInvalid && (
{!incompleteInfo && selectedColumn && temporaryState === 'none' && ( diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/filtering.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/filtering.tsx index b8440feae1a49..11e9110171f40 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/filtering.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/filtering.tsx @@ -16,6 +16,7 @@ import { EuiFlexItem, EuiFlexGroup, EuiPopoverProps, + EuiIconTip, } from '@elastic/eui'; import type { Query } from 'src/plugins/data/public'; import { GenericIndexPatternColumn, operationDefinitionMap } from '../operations'; @@ -53,6 +54,7 @@ export function Filtering({ updateLayer, indexPattern, isInitiallyOpen, + helpMessage, }: { selectedColumn: GenericIndexPatternColumn; indexPattern: IndexPattern; @@ -60,6 +62,7 @@ export function Filtering({ layer: IndexPatternLayer; updateLayer: (newLayer: IndexPatternLayer) => void; isInitiallyOpen: boolean; + helpMessage: string | null; }) { const inputFilter = selectedColumn.filter; const [queryInput, setQueryInput] = useState(inputFilter ?? defaultFilter); @@ -92,13 +95,26 @@ export function Filtering({ indexPattern ); + const labelNode = helpMessage ? ( + <> + {filterByLabel}{' '} + + + ) : ( + filterByLabel + ); + return ( - + { return { @@ -24,6 +25,12 @@ jest.mock('../../layer_helpers', () => { }; }); +interface PartialColumnParams { + kql?: string; + lucene?: string; + shift?: string; +} + const operationDefinitionMap: Record = { average: { input: 'field', @@ -60,7 +67,7 @@ const operationDefinitionMap: Record = { count: { input: 'field', filterable: true, - buildColumn: ({ field }: { field: IndexPatternField }) => ({ + buildColumn: ({ field }: { field: IndexPatternField }, columnsParams: PartialColumnParams) => ({ label: 'avg', dataType: 'number', operationType: 'count', @@ -68,6 +75,7 @@ const operationDefinitionMap: Record = { isBucketed: false, scale: 'ratio', timeScale: false, + filter: getFilter(undefined, columnsParams), }), getPossibleOperationForField: () => ({ scale: 'ratio' }), } as unknown as GenericOperationDefinition, @@ -78,7 +86,10 @@ const operationDefinitionMap: Record = { moving_average: { input: 'fullReference', operationParams: [{ name: 'window', type: 'number', required: true }], - buildColumn: ({ references }: { references: string[] }) => ({ + buildColumn: ( + { references }: { references: string[] }, + columnsParams: PartialColumnParams + ) => ({ label: 'moving_average', dataType: 'number', operationType: 'moving_average', @@ -87,9 +98,11 @@ const operationDefinitionMap: Record = { timeScale: false, params: { window: 5 }, references, + filter: getFilter(undefined, columnsParams), }), getErrorMessage: () => ['mock error'], getPossibleOperationForField: () => ({ scale: 'ratio' }), + filterable: true, } as unknown as GenericOperationDefinition, cumulative_sum: { input: 'fullReference', @@ -246,7 +259,7 @@ describe('formula', () => { }); }); - it('it should move over lucene arguments without', () => { + it('it should move over lucene arguments if set', () => { expect( formulaOperation.buildColumn({ previousColumn: { @@ -415,25 +428,30 @@ describe('formula', () => { let indexPattern: IndexPattern; let currentColumn: FormulaIndexPatternColumn; - function testIsBrokenFormula(formula: string) { + function testIsBrokenFormula( + formula: string, + columnParams: Partial> = {} + ) { + const mergedColumn = { ...currentColumn, ...columnParams }; + const mergedLayer = { ...layer, columns: { ...layer.columns, col1: mergedColumn } }; expect( regenerateLayerFromAst( formula, - layer, + mergedLayer, 'col1', - currentColumn, + mergedColumn, indexPattern, operationDefinitionMap ).newLayer ).toEqual({ - ...layer, + ...mergedLayer, columns: { - ...layer.columns, + ...mergedLayer.columns, col1: { - ...currentColumn, + ...mergedColumn, label: formula, params: { - ...currentColumn.params, + ...mergedColumn.params, formula, isFormulaBroken: true, }, @@ -639,6 +657,19 @@ describe('formula', () => { testIsBrokenFormula(formula); }); + it('returns a filter type error if query types mismatch between column filter and inner formula one', () => { + const formulas = [ + `count(kql='bytes > 4000')`, + `count(lucene='bytes:[400 TO *]') + count(kql='bytes > 4000')`, + `moving_average(average(bytes), kql='bytes: *', window=7)`, + `moving_average(sum(bytes, kql='bytes: *'), window=7)`, + ]; + + for (const formula of formulas) { + testIsBrokenFormula(formula, { filter: { language: 'lucene', query: 'bytes:[400 TO *]' } }); + } + }); + it('returns the locations of each function', () => { expect( regenerateLayerFromAst( @@ -655,12 +686,99 @@ describe('formula', () => { col1X2: { min: 42, max: 50 }, }); }); + + it('add the formula filter to supported operations', () => { + const filter = { language: 'kuery', query: 'bytes > 4000' }; + const mergedColumn = { ...currentColumn, filter }; + const mergedLayer = { ...layer, columns: { ...layer.columns, col1: mergedColumn } }; + const formula = 'moving_average(average(bytes), window=7) + count()'; + + const { newLayer } = regenerateLayerFromAst( + formula, + mergedLayer, + 'col1', + mergedColumn, + indexPattern, + operationDefinitionMap + ); + // average and math are not filterable in the mocks + expect(newLayer.columns).toEqual( + expect.objectContaining({ + col1: expect.objectContaining({ + label: formula, + filter, + }), + col1X1: expect.objectContaining({ + operationType: 'moving_average', + filter, + }), + col1X2: expect.objectContaining({ + operationType: 'count', + filter, + }), + }) + ); + + expect(newLayer.columns).toEqual( + expect.objectContaining({ + col1X0: expect.not.objectContaining({ + filter, + }), + col1X3: expect.not.objectContaining({ + filter, + }), + }) + ); + }); + it('prepend formula filter to supported operations', () => { + const filter = { language: 'kuery', query: 'bytes > 4000' }; + const innerFilter = 'bytes > 5000'; + const mergedColumn = { ...currentColumn, filter }; + const mergedLayer = { ...layer, columns: { ...layer.columns, col1: mergedColumn } }; + const formula = `moving_average(average(bytes), window=7, kql='${innerFilter}') + count(kql='${innerFilter}')`; + + const { newLayer } = regenerateLayerFromAst( + formula, + mergedLayer, + 'col1', + mergedColumn, + indexPattern, + operationDefinitionMap + ); + // average and math are not filterable in the mocks + expect(newLayer.columns).toEqual( + expect.objectContaining({ + col1: expect.objectContaining({ + label: formula, + filter, + }), + col1X1: expect.objectContaining({ + operationType: 'moving_average', + filter: { + ...filter, + query: `(${filter.query}) AND (${innerFilter})`, + }, + }), + col1X2: expect.objectContaining({ + operationType: 'count', + filter: { + ...filter, + query: `(${filter.query}) AND (${innerFilter})`, + }, + }), + }) + ); + }); }); describe('getErrorMessage', () => { let indexPattern: IndexPattern; - function getNewLayerWithFormula(formula: string, isBroken = true): IndexPatternLayer { + function getNewLayerWithFormula( + formula: string, + isBroken = true, + columnParams: Partial> = {} + ): IndexPatternLayer { return { columns: { col1: { @@ -671,6 +789,7 @@ describe('formula', () => { scale: 'ratio', params: { formula, isFormulaBroken: isBroken }, references: [], + ...columnParams, } as FormulaIndexPatternColumn, }, columnOrder: [], @@ -1331,5 +1450,77 @@ invalid: " }); }); } + + it('returns error if formula filter has not same type of inner operations filter', () => { + const formulas = [ + { formula: `count(kql='bytes > 4000')`, operation: 'count' }, + { + formula: `count(lucene='bytes:[400 TO *]') + sum(bytes, kql='bytes > 4000')`, + operation: 'sum', + }, + { + formula: `moving_average(average(bytes), kql='bytes: *', window=7)`, + operation: 'moving_average', + }, + { formula: `moving_average(sum(bytes, kql='bytes: *'), window=7)`, operation: 'sum' }, + ]; + + for (const { formula, operation } of formulas) { + expect( + formulaOperation.getErrorMessage!( + getNewLayerWithFormula(formula, true, { + filter: { language: 'lucene', query: 'bytes:[400 TO *]' }, + }), + 'col1', + indexPattern, + operationDefinitionMap + ) + ).toEqual([ + `The Formula filter of type "lucene" is not compatible with the inner filter of type "kql" from the ${operation} operation.`, + ]); + } + }); + + it('return multiple errors if formula filter has not same type of multiple inner operations filter', () => { + expect( + formulaOperation.getErrorMessage!( + getNewLayerWithFormula( + `count(kql='bytes > 4000') + sum(bytes, kql='bytes > 4000')`, + true, + { + filter: { language: 'lucene', query: 'bytes:[400 TO *]' }, + } + ), + 'col1', + indexPattern, + operationDefinitionMap + ) + ).toEqual([ + `The Formula filter of type "lucene" is not compatible with the inner filter of type "kql" from the count operation.`, + `The Formula filter of type "lucene" is not compatible with the inner filter of type "kql" from the sum operation.`, + ]); + }); + + it('returns no error if formula filter and operation inner filters are compatible', () => { + const formulas = [ + `count(kql='bytes > 4000')`, + `count(kql='bytes > 4000') + sum(bytes, kql='bytes > 4000')`, + `moving_average(average(bytes), kql='bytes: *', window=7)`, + `moving_average(sum(bytes, kql='bytes: *'), window=7)`, + ]; + + for (const formula of formulas) { + expect( + formulaOperation.getErrorMessage!( + getNewLayerWithFormula(formula, true, { + filter: { language: 'kuery', query: 'bytes > 4000' }, + }), + 'col1', + indexPattern, + operationDefinitionMap + ) + ).toEqual(undefined); + } + }); }); }); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.tsx index 5842cde4fea31..15c49a7336c7e 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.tsx @@ -6,16 +6,16 @@ */ import { i18n } from '@kbn/i18n'; -import { OperationDefinition } from '../index'; -import { ReferenceBasedIndexPatternColumn } from '../column_types'; -import { IndexPattern } from '../../../types'; +import type { OperationDefinition } from '../index'; +import type { ReferenceBasedIndexPatternColumn } from '../column_types'; +import type { IndexPattern } from '../../../types'; import { runASTValidation, tryToParse } from './validation'; import { WrappedFormulaEditor } from './editor'; import { regenerateLayerFromAst } from './parse'; import { generateFormula } from './generate'; import { filterByVisibleOperation } from './util'; import { getManagedColumnsFrom } from '../../layer_helpers'; -import { isColumnFormatted } from '../helpers'; +import { getFilter, isColumnFormatted } from '../helpers'; const defaultLabel = i18n.translate('xpack.lens.indexPattern.formulaLabel', { defaultMessage: 'Formula', @@ -43,6 +43,11 @@ export const formulaOperation: OperationDefinition column.params.formula ?? defaultLabel, input: 'managedReference', hidden: true, + filterable: { + helpMessage: i18n.translate('xpack.lens.indexPattern.formulaFilterableHelpText', { + defaultMessage: 'The provided filter will be applied to the entire formula.', + }), + }, getDisabledStatus(indexPattern: IndexPattern) { return undefined; }, @@ -58,7 +63,7 @@ export const formulaOperation: OperationDefinition message); @@ -134,6 +139,10 @@ export const formulaOperation: OperationDefinition { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/parse.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/parse.ts index ead2467416ce2..ee245cc06bff9 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/parse.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/parse.ts @@ -8,12 +8,12 @@ import { i18n } from '@kbn/i18n'; import { isObject } from 'lodash'; import type { TinymathAST, TinymathVariable, TinymathLocation } from '@kbn/tinymath'; -import { +import type { OperationDefinition, GenericOperationDefinition, GenericIndexPatternColumn, } from '../index'; -import { IndexPattern, IndexPatternLayer } from '../../../types'; +import type { IndexPattern, IndexPatternLayer } from '../../../types'; import { mathOperation } from './math'; import { documentField } from '../../../document_field'; import { runASTValidation, shouldHaveFieldArgument, tryToParse } from './validation'; @@ -22,8 +22,9 @@ import { findVariables, getOperationParams, groupArgsByType, + mergeWithGlobalFilter, } from './util'; -import { FormulaIndexPatternColumn } from './formula'; +import type { FormulaIndexPatternColumn } from './formula'; import { getColumnOrder } from '../../layer_helpers'; function getManagedId(mainId: string, index: number) { @@ -43,7 +44,13 @@ function parseAndExtract( return { extracted: [], isValid: false }; } // before extracting the data run the validation task and throw if invalid - const errors = runASTValidation(root, layer, indexPattern, operationDefinitionMap); + const errors = runASTValidation( + root, + layer, + indexPattern, + operationDefinitionMap, + layer.columns[columnId] + ); if (errors.length) { return { extracted: [], isValid: false }; } @@ -73,6 +80,7 @@ function extractColumns( label: string ): Array<{ column: GenericIndexPatternColumn; location?: TinymathLocation }> { const columns: Array<{ column: GenericIndexPatternColumn; location?: TinymathLocation }> = []; + const globalFilter = layer.columns[idPrefix].filter; function parseNode(node: TinymathAST) { if (typeof node === 'number' || node.type !== 'function') { @@ -103,7 +111,11 @@ function extractColumns( ? indexPattern.getFieldByName(fieldName.value)! : documentField; - const mappedParams = getOperationParams(nodeOperation, namedArguments || []); + const mappedParams = mergeWithGlobalFilter( + nodeOperation, + getOperationParams(nodeOperation, namedArguments || []), + globalFilter + ); const newCol = ( nodeOperation as OperationDefinition @@ -141,7 +153,11 @@ function extractColumns( mathColumn.label = label; } - const mappedParams = getOperationParams(nodeOperation, namedArguments || []); + const mappedParams = mergeWithGlobalFilter( + nodeOperation, + getOperationParams(nodeOperation, namedArguments || []), + globalFilter + ); const newCol = ( nodeOperation as OperationDefinition ).buildColumn( diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/util.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/util.ts index db267bfb0d564..e26fa61c5e2dc 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/util.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/util.ts @@ -13,6 +13,7 @@ import type { TinymathNamedArgument, TinymathVariable, } from 'packages/kbn-tinymath'; +import type { Query } from 'src/plugins/data/public'; import type { OperationDefinition, GenericIndexPatternColumn, @@ -48,6 +49,28 @@ export function getValueOrName(node: TinymathAST) { return node.name; } +export function mergeWithGlobalFilter( + operation: + | OperationDefinition + | OperationDefinition, + mappedParams: Record, + globalFilter?: Query +) { + if (globalFilter && operation.filterable) { + const languageKey = 'kql' in mappedParams ? 'kql' : 'lucene'; + if (mappedParams[languageKey]) { + // ignore the initial empty string case + if (globalFilter.query) { + mappedParams[languageKey] = `(${globalFilter.query}) AND (${mappedParams[languageKey]})`; + } + } else { + const language = globalFilter.language === 'kuery' ? 'kql' : globalFilter.language; + mappedParams[language] = globalFilter.query as string; + } + } + return mappedParams; +} + export function getOperationParams( operation: | OperationDefinition diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/validation.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/validation.ts index 559e03c4fe9ea..c7743619b43bb 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/validation.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/validation.ts @@ -10,6 +10,7 @@ import { i18n } from '@kbn/i18n'; import { parse, TinymathLocation, TinymathVariable } from '@kbn/tinymath'; import type { TinymathAST, TinymathFunction, TinymathNamedArgument } from '@kbn/tinymath'; import { luceneStringToDsl, toElasticsearchQuery, fromKueryExpression } from '@kbn/es-query'; +import type { Query } from 'src/plugins/data/public'; import { findMathNodes, findVariables, @@ -84,6 +85,10 @@ interface ValidationErrors { message: string; type: { text: string }; }; + filtersTypeConflict: { + message: string; + type: { operation: string; outerType: string; innerType: string }; + }; } type ErrorTypes = keyof ValidationErrors; @@ -323,6 +328,13 @@ function getMessageFromId({ values: { text: out.text }, }); break; + case 'filtersTypeConflict': + message = i18n.translate('xpack.lens.indexPattern.formulaOperationFiltersTypeConflicts', { + defaultMessage: + 'The Formula filter of type "{outerType}" is not compatible with the inner filter of type "{innerType}" from the {operation} operation.', + values: { operation: out.operation, outerType: out.outerType, innerType: out.innerType }, + }); + break; // case 'mathRequiresFunction': // message = i18n.translate('xpack.lens.indexPattern.formulaMathRequiresFunctionLabel', { // defaultMessage; 'The function {name} requires an Elasticsearch function', @@ -372,11 +384,12 @@ export function runASTValidation( ast: TinymathAST, layer: IndexPatternLayer, indexPattern: IndexPattern, - operations: Record + operations: Record, + currentColumn: GenericIndexPatternColumn ) { return [ ...checkMissingVariableOrFunctions(ast, layer, indexPattern, operations), - ...runFullASTValidation(ast, layer, indexPattern, operations), + ...runFullASTValidation(ast, layer, indexPattern, operations, currentColumn), ]; } @@ -483,6 +496,38 @@ function checkSingleQuery(namedArguments: TinymathNamedArgument[] | undefined) { : undefined; } +function validateFiltersArguments( + node: TinymathFunction, + nodeOperation: + | OperationDefinition + | OperationDefinition, + namedArguments: TinymathNamedArgument[] | undefined, + globalFilters?: Query +) { + const errors = []; + const { conflicts, innerType, outerType } = hasFiltersConflicts( + nodeOperation, + namedArguments, + globalFilters + ); + if (conflicts) { + if (innerType && outerType) { + errors.push( + getMessageFromId({ + messageId: 'filtersTypeConflict', + values: { + operation: node.name, + innerType, + outerType, + }, + locations: node.location ? [node.location] : [], + }) + ); + } + } + return errors; +} + function validateNameArguments( node: TinymathFunction, nodeOperation: @@ -552,13 +597,15 @@ function runFullASTValidation( ast: TinymathAST, layer: IndexPatternLayer, indexPattern: IndexPattern, - operations: Record + operations: Record, + currentColumn?: GenericIndexPatternColumn ): ErrorWrapper[] { const missingVariables = findVariables(ast).filter( // filter empty string as well? ({ value }) => !indexPattern.getFieldByName(value) && !layer.columns[value] ); const missingVariablesSet = new Set(missingVariables.map(({ value }) => value)); + const globalFilter = currentColumn?.filter; function validateNode(node: TinymathAST): ErrorWrapper[] { if (!isObject(node) || node.type !== 'function') { @@ -664,9 +711,14 @@ function runFullASTValidation( namedArguments, indexPattern ); - if (argumentsErrors.length) { - errors.push(...argumentsErrors); - } + + const filtersErrors = validateFiltersArguments( + node, + nodeOperation, + namedArguments, + globalFilter + ); + errors.push(...argumentsErrors, ...filtersErrors); } return errors; } @@ -729,18 +781,19 @@ function runFullASTValidation( firstArg, returnedType: undefined, }); - if (fieldErrors.length) { - errors.push(...fieldErrors); - } const argumentsErrors = validateNameArguments( node, nodeOperation, namedArguments, indexPattern ); - if (argumentsErrors.length) { - errors.push(...argumentsErrors); - } + const filtersErrors = validateFiltersArguments( + node, + nodeOperation, + namedArguments, + globalFilter + ); + errors.push(...fieldErrors, ...argumentsErrors, ...filtersErrors); } } return errors.concat(validateNode(functions[0])); @@ -824,6 +877,26 @@ function getDuplicateParams(params: TinymathNamedArgument[] = []) { return []; } +export function hasFiltersConflicts( + operation: + | OperationDefinition + | OperationDefinition, + params: TinymathNamedArgument[] = [], + globalFilter?: Query +) { + const paramsObj = getOperationParams(operation, params); + if (!operation.filterable || !globalFilter || !(paramsObj.kql || paramsObj.lucene)) { + return { conflicts: false }; + } + const language = globalFilter.language === 'kuery' ? 'kql' : globalFilter.language; + const conflicts = !(language in paramsObj); + return { + conflicts, + innerType: paramsObj.lucene ? 'lucene' : 'kql', + outerType: language, + }; +} + export function validateParams( operation: | OperationDefinition diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts index 275ad1798c788..ccf86be7d2b08 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts @@ -293,7 +293,7 @@ interface BaseOperationDefinitionProps { * This flag is used by the formula to assign the kql= and lucene= named arguments and set up * autocomplete. */ - filterable?: boolean; + filterable?: boolean | { helpMessage: string }; shiftable?: boolean; getHelpMessage?: (props: HelpProps) => React.ReactNode; diff --git a/x-pack/test/functional/apps/lens/formula.ts b/x-pack/test/functional/apps/lens/formula.ts index 2078836e2af8a..64cedd7e88e7c 100644 --- a/x-pack/test/functional/apps/lens/formula.ts +++ b/x-pack/test/functional/apps/lens/formula.ts @@ -287,5 +287,43 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(await PageObjects.lens.getDatatableCellText(0, 0)).to.eql('0'); expect(await PageObjects.lens.getDatatableCellText(0, 1)).to.eql('0'); }); + + it('should apply a global filter to the current formula', async () => { + await PageObjects.visualize.navigateToNewVisualization(); + await PageObjects.visualize.clickVisType('lens'); + await PageObjects.lens.goToTimeRange(); + await PageObjects.lens.switchToVisualization('lnsDatatable'); + + await PageObjects.lens.configureDimension({ + dimension: 'lnsDatatable_metrics > lns-empty-dimension', + operation: 'formula', + formula: `count()`, + keepOpen: true, + }); + + // check the numbers + await PageObjects.header.waitUntilLoadingHasFinished(); + expect(await PageObjects.lens.getDatatableCellText(0, 0)).to.eql('14,005'); + + // add an advanced filter by filter + await PageObjects.lens.enableFilter(); + await PageObjects.lens.setFilterBy('bytes > 4000'); + + // check that numbers changed + await PageObjects.header.waitUntilLoadingHasFinished(); + await retry.try(async () => { + expect(await PageObjects.lens.getDatatableCellText(0, 0)).to.eql('9,169'); + }); + + // now change the formula to add an inner filter to count + await PageObjects.lens.typeFormula(`count(kql=`); + + const input = await find.activeElement(); + await input.type(`bytes > 600000`); + // the autocomplete will add quotes and closing brakets, so do not worry about that + + await PageObjects.header.waitUntilLoadingHasFinished(); + expect(await PageObjects.lens.getDatatableCellText(0, 0)).to.eql('0'); + }); }); } diff --git a/x-pack/test/functional/page_objects/lens_page.ts b/x-pack/test/functional/page_objects/lens_page.ts index 4e562067637c5..0b0fc672e364b 100644 --- a/x-pack/test/functional/page_objects/lens_page.ts +++ b/x-pack/test/functional/page_objects/lens_page.ts @@ -468,6 +468,25 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont await comboBox.setCustom('indexPattern-dimension-time-shift', shift); }, + async enableFilter() { + await testSubjects.click('indexPattern-advanced-popover'); + await retry.try(async () => { + await testSubjects.click('indexPattern-filter-by-enable'); + }); + }, + + async setFilterBy(queryString: string) { + this.typeFilter(queryString); + await retry.try(async () => { + await testSubjects.click('indexPattern-filters-existingFilterTrigger'); + }); + }, + + async typeFilter(queryString: string) { + const queryInput = await testSubjects.find('indexPattern-filters-queryStringInput'); + await queryInput.type(queryString); + }, + async hasFixAction() { return await testSubjects.exists('errorFixAction'); }, @@ -491,8 +510,7 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont */ async addFilterToAgg(queryString: string) { await testSubjects.click('lns-newBucket-add'); - const queryInput = await testSubjects.find('indexPattern-filters-queryStringInput'); - await queryInput.type(queryString); + this.typeFilter(queryString); // Problem here is that after typing in the queryInput a dropdown will fetch the server // with suggestions and show up. Depending on the cursor position and some other factors // pressing Enter at this point may lead to auto-complete the queryInput with random stuff from the From 93aac6615a8818f676620d57c8c8e1e2021aabdb Mon Sep 17 00:00:00 2001 From: Angela Chuang <6295984+angorayc@users.noreply.github.com> Date: Mon, 10 Jan 2022 11:46:52 +0000 Subject: [PATCH 10/11] [Security Solution] Hover actions on overflow items (#121928) * add hover actions to overflow items * unit test * cypress * cypress * review * review * review Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../integration/network/hover_actions.spec.ts | 76 +++++++ .../network/overflow_items.spec.ts | 61 +++++ .../cypress/screens/network/flows.ts | 19 ++ .../security_solution/cypress/tasks/login.ts | 15 +- .../cypress/tasks/network/flows.ts | 36 ++- .../common/components/hover_actions/index.tsx | 1 + .../__snapshots__/helpers.test.tsx.snap | 108 ++++++--- .../common/components/tables/helpers.test.tsx | 84 ++++++- .../common/components/tables/helpers.tsx | 210 ++++++++++++++---- .../public/common/components/top_n/top_n.tsx | 2 +- .../es_archives/auditbeat/data.json.gz | Bin 5130292 -> 4685877 bytes 11 files changed, 524 insertions(+), 88 deletions(-) create mode 100644 x-pack/plugins/security_solution/cypress/integration/network/hover_actions.spec.ts create mode 100644 x-pack/plugins/security_solution/cypress/integration/network/overflow_items.spec.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/network/hover_actions.spec.ts b/x-pack/plugins/security_solution/cypress/integration/network/hover_actions.spec.ts new file mode 100644 index 0000000000000..c457754d1b9ad --- /dev/null +++ b/x-pack/plugins/security_solution/cypress/integration/network/hover_actions.spec.ts @@ -0,0 +1,76 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { TOP_N_CONTAINER } from '../../screens/network/flows'; +import { GLOBAL_SEARCH_BAR_FILTER_ITEM } from '../../screens/search_bar'; +import { DATA_PROVIDERS } from '../../screens/timeline'; +import { cleanKibana } from '../../tasks/common'; + +import { loginAndWaitForPage } from '../../tasks/login'; +import { NETWORK_URL } from '../../urls/navigation'; +import { + clickOnAddToTimeline, + clickOnCopyValue, + clickOnFilterIn, + clickOnFilterOut, + clickOnShowTopN, + openHoverActions, +} from '../../tasks/network/flows'; +import { openTimelineUsingToggle } from '../../tasks/security_main'; + +const testDomain = 'endpoint-dev-es.app.elstc.co'; + +describe('Hover actions', () => { + const onBeforeLoadCallback = (win: Cypress.AUTWindow) => { + // avoid cypress being held by windows prompt and timeout + cy.stub(win, 'prompt').returns(true); + }; + + before(() => { + cleanKibana(); + }); + + beforeEach(() => { + loginAndWaitForPage(NETWORK_URL, undefined, onBeforeLoadCallback); + openHoverActions(); + }); + + it('Adds global filter - filter in', () => { + clickOnFilterIn(); + + cy.get(GLOBAL_SEARCH_BAR_FILTER_ITEM).should('have.text', `destination.domain: ${testDomain}`); + }); + + it('Adds global filter - filter out', () => { + clickOnFilterOut(); + cy.get(GLOBAL_SEARCH_BAR_FILTER_ITEM).should( + 'contains.text', + `NOT destination.domain: ${testDomain}` + ); + }); + + it('Adds to timeline', () => { + const DATA_PROVIDER_ITEM_NUMBER = 1; + clickOnAddToTimeline(); + openTimelineUsingToggle(); + + cy.get(DATA_PROVIDERS).should('have.length', DATA_PROVIDER_ITEM_NUMBER); + cy.get(DATA_PROVIDERS).should('have.text', `destination.domain: "${testDomain}"`); + }); + + it('Show topN', () => { + clickOnShowTopN(); + cy.get(TOP_N_CONTAINER).should('exist').should('contain.text', 'Top destination.domain'); + }); + + it('Copy value', () => { + cy.document().then((doc) => cy.spy(doc, 'execCommand').as('execCommand')); + + clickOnCopyValue(); + + cy.get('@execCommand').should('have.been.calledOnceWith', 'copy'); + }); +}); diff --git a/x-pack/plugins/security_solution/cypress/integration/network/overflow_items.spec.ts b/x-pack/plugins/security_solution/cypress/integration/network/overflow_items.spec.ts new file mode 100644 index 0000000000000..b9a733093c586 --- /dev/null +++ b/x-pack/plugins/security_solution/cypress/integration/network/overflow_items.spec.ts @@ -0,0 +1,61 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + ADD_TO_TIMELINE, + COPY, + DESTINATION_DOMAIN, + FILTER_IN, + FILTER_OUT, + SHOW_TOP_FIELD, +} from '../../screens/network/flows'; +import { cleanKibana } from '../../tasks/common'; + +import { loginAndWaitForPage } from '../../tasks/login'; +import { openHoverActions } from '../../tasks/network/flows'; + +import { NETWORK_URL } from '../../urls/navigation'; + +const testDomainOne = 'endpoint-dev-es.app.elstc.co'; +const testDomainTwo = 'endpoint2-dev-es.app.elstc.co'; + +describe('Overflow items', () => { + context('Network stats and tables', () => { + before(() => { + cleanKibana(); + }); + beforeEach(() => { + loginAndWaitForPage(NETWORK_URL); + }); + + it('Shows more items in the popover', () => { + cy.get(DESTINATION_DOMAIN(testDomainOne)).should('not.exist'); + cy.get(DESTINATION_DOMAIN(testDomainTwo)).should('not.exist'); + + openHoverActions(); + + cy.get(DESTINATION_DOMAIN(testDomainOne)).should('exist'); + cy.get(DESTINATION_DOMAIN(testDomainTwo)).should('exist'); + }); + + it('Shows Hover actions for more items in the popover', () => { + cy.get(FILTER_IN).should('not.exist'); + cy.get(FILTER_OUT).should('not.exist'); + cy.get(ADD_TO_TIMELINE).should('not.exist'); + cy.get(SHOW_TOP_FIELD).should('not.exist'); + cy.get(COPY).should('not.exist'); + + openHoverActions(); + + cy.get(FILTER_IN).should('exist'); + cy.get(FILTER_OUT).should('exist'); + cy.get(ADD_TO_TIMELINE).should('exist'); + cy.get(SHOW_TOP_FIELD).should('exist'); + cy.get(COPY).should('exist'); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/cypress/screens/network/flows.ts b/x-pack/plugins/security_solution/cypress/screens/network/flows.ts index ef76dbc05aac7..d8b68f1a79ca6 100644 --- a/x-pack/plugins/security_solution/cypress/screens/network/flows.ts +++ b/x-pack/plugins/security_solution/cypress/screens/network/flows.ts @@ -6,3 +6,22 @@ */ export const IPS_TABLE_LOADED = '[data-test-subj="table-topNFlowSource-loading-false"]'; + +export const EXPAND_OVERFLOW_ITEMS = '[data-test-subj="overflow-button"]'; + +export const FILTER_IN = '[data-test-subj="hover-actions-filter-for"]'; + +export const FILTER_OUT = '[data-test-subj="hover-actions-filter-out"]'; + +export const ADD_TO_TIMELINE = '[data-test-subj="add-to-timeline"]'; + +export const SHOW_TOP_FIELD = '[data-test-subj="show-top-field"]'; + +export const COPY = '[data-test-subj="clipboard"]'; + +export const TOP_N_CONTAINER = '[data-test-subj="topN-container"]'; + +export const CLOSE_TOP_N = '[data-test-subj="close"]'; + +export const DESTINATION_DOMAIN = (testDomain: string) => + `[data-test-subj="destination.domain-${testDomain}"]`; diff --git a/x-pack/plugins/security_solution/cypress/tasks/login.ts b/x-pack/plugins/security_solution/cypress/tasks/login.ts index 886b7207def9c..0610333352ce8 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/login.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/login.ts @@ -288,10 +288,21 @@ export const getEnvAuth = (): User => { * Authenticates with Kibana, visits the specified `url`, and waits for the * Kibana global nav to be displayed before continuing */ -export const loginAndWaitForPage = (url: string, role?: ROLES) => { +export const loginAndWaitForPage = ( + url: string, + role?: ROLES, + onBeforeLoadCallback?: (win: Cypress.AUTWindow) => void +) => { login(role); cy.visit( - `${url}?timerange=(global:(linkTo:!(timeline),timerange:(from:1547914976217,fromStr:'2019-01-19T16:22:56.217Z',kind:relative,to:1579537385745,toStr:now)),timeline:(linkTo:!(global),timerange:(from:1547914976217,fromStr:'2019-01-19T16:22:56.217Z',kind:relative,to:1579537385745,toStr:now)))` + `${url}?timerange=(global:(linkTo:!(timeline),timerange:(from:1547914976217,fromStr:'2019-01-19T16:22:56.217Z',kind:relative,to:1579537385745,toStr:now)),timeline:(linkTo:!(global),timerange:(from:1547914976217,fromStr:'2019-01-19T16:22:56.217Z',kind:relative,to:1579537385745,toStr:now)))`, + { + onBeforeLoad(win) { + if (onBeforeLoadCallback) { + onBeforeLoadCallback(win); + } + }, + } ); cy.get('[data-test-subj="headerGlobalNav"]'); }; diff --git a/x-pack/plugins/security_solution/cypress/tasks/network/flows.ts b/x-pack/plugins/security_solution/cypress/tasks/network/flows.ts index f6d291989ae41..75ec6f08f535b 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/network/flows.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/network/flows.ts @@ -5,8 +5,42 @@ * 2.0. */ -import { IPS_TABLE_LOADED } from '../../screens/network/flows'; +import { TOASTER } from '../../screens/configure_cases'; +import { + ADD_TO_TIMELINE, + COPY, + FILTER_IN, + FILTER_OUT, + IPS_TABLE_LOADED, + SHOW_TOP_FIELD, + EXPAND_OVERFLOW_ITEMS, +} from '../../screens/network/flows'; export const waitForIpsTableToBeLoaded = () => { cy.get(IPS_TABLE_LOADED).should('exist'); }; + +export const openHoverActions = () => { + cy.get(TOASTER).should('not.exist', { timeout: 12000 }); // Wait until "Your browser does not meet the security requirements for Kibana." toaster goes away + cy.get(EXPAND_OVERFLOW_ITEMS).click({ scrollBehavior: 'center' }); +}; + +export const clickOnFilterIn = () => { + cy.get(FILTER_IN).first().click(); +}; + +export const clickOnFilterOut = () => { + cy.get(FILTER_OUT).first().click(); +}; + +export const clickOnAddToTimeline = () => { + cy.get(ADD_TO_TIMELINE).first().click(); +}; + +export const clickOnShowTopN = () => { + cy.get(SHOW_TOP_FIELD).first().click(); +}; + +export const clickOnCopyValue = () => { + cy.get(COPY).first().invoke('focus').click({ force: true }); +}; diff --git a/x-pack/plugins/security_solution/public/common/components/hover_actions/index.tsx b/x-pack/plugins/security_solution/public/common/components/hover_actions/index.tsx index 311284565ba14..2617a1a4068a4 100644 --- a/x-pack/plugins/security_solution/public/common/components/hover_actions/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/hover_actions/index.tsx @@ -83,6 +83,7 @@ const StyledHoverActionsContainer = styled.div<{ const StyledHoverActionsContainerWithPaddingsAndMinWidth = styled(StyledHoverActionsContainer)` min-width: ${({ $hideTopN }) => `${$hideTopN ? '112px' : '138px'}`}; padding: ${(props) => `0 ${props.theme.eui.paddingSizes.s}`}; + position: relative; `; interface Props { diff --git a/x-pack/plugins/security_solution/public/common/components/tables/__snapshots__/helpers.test.tsx.snap b/x-pack/plugins/security_solution/public/common/components/tables/__snapshots__/helpers.test.tsx.snap index 6f55d92aa9875..009482e043f5e 100644 --- a/x-pack/plugins/security_solution/public/common/components/tables/__snapshots__/helpers.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/common/components/tables/__snapshots__/helpers.test.tsx.snap @@ -1,5 +1,64 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`Table Helpers #RowItemOverflow it returns correctly against snapshot 1`] = ` + + + + + + + + +

+ + 1 + + + +

+
+
+
+`; + exports[`Table Helpers #getRowItemDraggable it returns correctly against snapshot 1`] = ` + `; -exports[`Table Helpers #getRowItemOverflow it returns correctly against snapshot 1`] = ` -
- - -
    -
  • - item2 -
  • -
-

- - 1 - - - -

-
-
-
-`; - exports[`Table Helpers OverflowField it returns correctly against snapshot 1`] = ` This string is exactly fifty-one chars in length!! diff --git a/x-pack/plugins/security_solution/public/common/components/tables/helpers.test.tsx b/x-pack/plugins/security_solution/public/common/components/tables/helpers.test.tsx index 10e4538c802ad..bc397292af4ec 100644 --- a/x-pack/plugins/security_solution/public/common/components/tables/helpers.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/tables/helpers.test.tsx @@ -11,13 +11,15 @@ import { shallow } from 'enzyme'; import '../../mock/match_media'; import { getRowItemDraggables, - getRowItemOverflow, + RowItemOverflowComponent, getRowItemDraggable, OverflowFieldComponent, + OverflowItemComponent, } from './helpers'; import { TestProviders } from '../../mock'; import { getEmptyValue } from '../empty_value'; import { useMountAppended } from '../../utils/use_mount_appended'; +import { IS_OPERATOR, QueryOperator } from '../../../../common/types'; jest.mock('../../lib/kibana'); @@ -181,22 +183,58 @@ describe('Table Helpers', () => { }); }); - describe('#getRowItemOverflow', () => { + describe('#RowItemOverflow', () => { test('it returns correctly against snapshot', () => { - const rowItemOverflow = getRowItemOverflow(items, 'attrName', 1, 1); - const wrapper = shallow(
{rowItemOverflow}
); + const wrapper = shallow( + + ); expect(wrapper).toMatchSnapshot(); }); test('it does not show "more not shown" when maxOverflowItems are not exceeded', () => { - const rowItemOverflow = getRowItemOverflow(items, 'attrName', 1, 5); - const wrapper = shallow(
{rowItemOverflow}
); + const wrapper = shallow( + + ); expect(wrapper.find('[data-test-subj="popover-additional-overflow"]').length).toBe(0); }); + test('it shows correct number of overflow items when maxOverflowItems are not exceeded', () => { + const wrapper = shallow( + + ); + expect( + wrapper.find('[data-test-subj="overflow-items"]').prop('children')?.length + ).toEqual(2); + }); + test('it shows "more not shown" when maxOverflowItems are exceeded', () => { - const rowItemOverflow = getRowItemOverflow(items, 'attrName', 1, 1); - const wrapper = shallow(
{rowItemOverflow}
); + const wrapper = shallow( + + ); expect(wrapper.find('[data-test-subj="popover-additional-overflow"]').length).toBe(1); }); }); @@ -222,4 +260,34 @@ describe('Table Helpers', () => { expect(wrapper.text()).toBe('This string is exact'); }); }); + + describe('OverflowItemComponent', () => { + const id = 'mock id'; + const rowItem = 'endpoint-dev-es.app.elstc.co'; + const field = 'destination.ip'; + const dataProvider = { + and: [], + enabled: true, + id, + name: rowItem, + excluded: false, + kqlQuery: '', + queryMatch: { + field, + value: rowItem, + displayValue: rowItem, + operator: IS_OPERATOR as QueryOperator, + }, + }; + const props = { + dataProvider, + field, + rowItem, + }; + + test('Renders Hover Actions', () => { + const wrapper = shallow(); + expect(wrapper.find('[data-test-subj="hover-actions"]').exists()).toBeTruthy(); + }); + }); }); diff --git a/x-pack/plugins/security_solution/public/common/components/tables/helpers.tsx b/x-pack/plugins/security_solution/public/common/components/tables/helpers.tsx index ccb56ae8a8cd6..f9f2d13bce2d9 100644 --- a/x-pack/plugins/security_solution/public/common/components/tables/helpers.tsx +++ b/x-pack/plugins/security_solution/public/common/components/tables/helpers.tsx @@ -4,10 +4,17 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - -import { EuiLink, EuiPopover, EuiToolTip, EuiText, EuiTextColor } from '@elastic/eui'; +import React, { useCallback, useContext, useMemo, useState } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; -import React, { useState } from 'react'; +import { + EuiLink, + EuiPopover, + EuiToolTip, + EuiText, + EuiTextColor, + EuiFlexGroup, + EuiFlexItem, +} from '@elastic/eui'; import styled from 'styled-components'; import { DragEffects, DraggableWrapper } from '../drag_and_drop/draggable_wrapper'; @@ -16,18 +23,15 @@ import { defaultToEmptyTag, getEmptyTagValue } from '../empty_value'; import { MoreRowItems } from '../page'; import { IS_OPERATOR } from '../../../timelines/components/timeline/data_providers/data_provider'; import { Provider } from '../../../timelines/components/timeline/data_providers/provider'; +import { HoverActions } from '../hover_actions'; +import { DataProvider, QueryOperator } from '../../../../common/types'; +import { TimelineContext } from '../../../../../timelines/public'; const Subtext = styled.div` font-size: ${(props) => props.theme.eui.euiFontSizeXS}; `; -export const getRowItemDraggable = ({ - rowItem, - attrName, - idPrefix, - render, - dragDisplayValue, -}: { +interface GetRowItemDraggableParams { rowItem: string | null | undefined; attrName: string; idPrefix: string; @@ -35,7 +39,15 @@ export const getRowItemDraggable = ({ displayCount?: number; dragDisplayValue?: string; maxOverflow?: number; -}): JSX.Element => { +} + +export const getRowItemDraggable = ({ + rowItem, + attrName, + idPrefix, + render, + dragDisplayValue, +}: GetRowItemDraggableParams): JSX.Element => { if (rowItem != null) { const id = escapeDataProviderId(`${idPrefix}-${attrName}-${rowItem}`); return ( @@ -71,6 +83,15 @@ export const getRowItemDraggable = ({ } }; +interface GetRowItemDraggablesParams { + rowItems: string[] | null | undefined; + attrName: string; + idPrefix: string; + render?: (item: string) => JSX.Element; + displayCount?: number; + dragDisplayValue?: string; + maxOverflow?: number; +} export const getRowItemDraggables = ({ rowItems, attrName, @@ -79,15 +100,7 @@ export const getRowItemDraggables = ({ dragDisplayValue, displayCount = 5, maxOverflow = 5, -}: { - rowItems: string[] | null | undefined; - attrName: string; - idPrefix: string; - render?: (item: string) => JSX.Element; - displayCount?: number; - dragDisplayValue?: string; - maxOverflow?: number; -}): JSX.Element => { +}: GetRowItemDraggablesParams): JSX.Element => { if (rowItems != null && rowItems.length > 0) { const draggables = rowItems.slice(0, displayCount).map((rowItem, index) => { const id = escapeDataProviderId(`${idPrefix}-${attrName}-${rowItem}-${index}`); @@ -125,7 +138,15 @@ export const getRowItemDraggables = ({ return draggables.length > 0 ? ( <> - {draggables} {getRowItemOverflow(rowItems, idPrefix, displayCount, maxOverflow)} + {draggables}{' '} + ) : ( getEmptyTagValue() @@ -135,24 +156,121 @@ export const getRowItemDraggables = ({ } }; -export const getRowItemOverflow = ( - rowItems: string[], - idPrefix: string, +interface OverflowItemProps { + dataProvider?: DataProvider | DataProvider[] | undefined; + dragDisplayValue?: string; + field: string; + rowItem: string; +} + +export const OverflowItemComponent: React.FC = ({ + dataProvider, + dragDisplayValue, + field, + rowItem, +}) => { + const [showTopN, setShowTopN] = useState(false); + const { timelineId: timelineIdFind } = useContext(TimelineContext); + const [hoverActionsOwnFocus] = useState(false); + const toggleTopN = useCallback(() => { + setShowTopN((prevShowTopN) => { + const newShowTopN = !prevShowTopN; + return newShowTopN; + }); + }, []); + + const closeTopN = useCallback(() => { + setShowTopN(false); + }, []); + + return ( + + {defaultToEmptyTag(rowItem)} + + + + + ); +}; + +OverflowItemComponent.displayName = 'OverflowItemComponent'; +export const OverflowItem = React.memo(OverflowItemComponent); + +interface RowItemOverflowProps { + attrName: string; + dragDisplayValue?: string; + idPrefix: string; + maxOverflowItems: number; + overflowIndexStart: number; + rowItems: string[]; +} + +export const RowItemOverflowComponent: React.FC = ({ + attrName, + dragDisplayValue, + idPrefix, + maxOverflowItems = 5, overflowIndexStart = 5, - maxOverflowItems = 5 -): JSX.Element => { + rowItems, +}) => { + const overflowItems = useMemo( + () => + rowItems + .slice(overflowIndexStart, overflowIndexStart + maxOverflowItems) + .map((rowItem, index) => { + const id = escapeDataProviderId(`${idPrefix}-${attrName}-${rowItem}-${index}`); + const dataProvider = { + and: [], + enabled: true, + id, + name: rowItem, + excluded: false, + kqlQuery: '', + queryMatch: { + field: attrName, + value: rowItem, + displayValue: dragDisplayValue || rowItem, + operator: IS_OPERATOR as QueryOperator, + }, + }; + + return ( + + + + ); + }), + [attrName, dragDisplayValue, idPrefix, maxOverflowItems, overflowIndexStart, rowItems] + ); return ( <> {rowItems.length > overflowIndexStart && ( -
    - {rowItems - .slice(overflowIndexStart, overflowIndexStart + maxOverflowItems) - .map((rowItem) => ( -
  • {defaultToEmptyTag(rowItem)}
  • - ))} -
+ + {overflowItems} + {rowItems.length > overflowIndexStart + maxOverflowItems && (

@@ -171,25 +289,37 @@ export const getRowItemOverflow = ( ); }; +RowItemOverflowComponent.displayName = 'RowItemOverflowComponent'; +export const RowItemOverflow = React.memo(RowItemOverflowComponent); -export const PopoverComponent = ({ - children, - count, - idPrefix, -}: { +interface PopoverComponentProps { children: React.ReactNode; count: number; idPrefix: string; -}) => { +} + +const PopoverComponent: React.FC = ({ children, count, idPrefix }) => { const [isOpen, setIsOpen] = useState(false); + const onButtonClick = useCallback(() => { + setIsOpen(!isOpen); + }, [isOpen]); return ( setIsOpen(!isOpen)}>{`+${count} More`}} + button={ + + + + } closePopover={() => setIsOpen(!isOpen)} id={`${idPrefix}-popover`} isOpen={isOpen} + panelClassName="withHoverActions__popover" repositionOnScroll > {children} diff --git a/x-pack/plugins/security_solution/public/common/components/top_n/top_n.tsx b/x-pack/plugins/security_solution/public/common/components/top_n/top_n.tsx index a450b56d70a98..c8569ca53c4dd 100644 --- a/x-pack/plugins/security_solution/public/common/components/top_n/top_n.tsx +++ b/x-pack/plugins/security_solution/public/common/components/top_n/top_n.tsx @@ -116,7 +116,7 @@ const TopNComponent: React.FC = ({ ); return ( - + xVnVIdFnVB(WiYaDhh}kjQF*E(r6<+V6VTa|pk}fc$xYq5tl*P+yg4?tbkO3{lrzcRN^CNw!3@a#$4Y zfj|Qz7Lss$vPh}wP3v{#V=7YjyZ4i9t^<<(Orh`ZnmPhWsLn51xm{I1U3nIKFH_k- z%xS;tm>A`)H0pXLbnEMM;B{_!5r55pv(`M@kbYLr-sJb@I@4`*CHy_t8#XpGv@YLB z|2*>=$K0qD6l#M|Q6FkqCWW$SC9%k+B6choNV$3F7RvABiPW_B{<-n&_ghcvNjtP- zw}#m9`z4M@CWak}uBgTfuAiRIhWW~Az&VIz;(BNO`R^PDFYb2Zm|{t1TXh^KK=LtE zg;WFp6V{>}pF$+XT_Er2O|?|e{Ii>`(M?!qiUmTHW#zU0gCHAE<3NbP%6wHu+8B)q zKm{@SSe2NnzN}h12K8aFC_4A^aQF4b*{ybVbH}Dtv)j&>cb_iJ>t@Wh)xo)*vr1Wv z$J$9N{wT||)-X?7dpolwCcEDO&-lMLSB~1m7s-lQ_WQH*G5Km8>>6#OfhW!E?(Hvg z7GC%4ztv@3LMl!j*q3!|Ze>;j#80h&)boL) za`whVvD2!@gYdAg?t zQ_mZPyQzE^4C&c-Jqn$rOHW4H%vjmIY%6Q=JS=#KPC-oBM9O9wIMPE!-?x`1J1%(N z{N5%%*|o2kHjuBZ6~S!F-qP53`WbSZM!fq?V+6-akCZ%7uy8CaDO_>teIJq&v?dsj zF_G^wZF(}LbY36)a+E z>kaS6HQVsHMM!S+`v>V--&=!1Kkw-^u4TBJYqcp~4yx?!ycwJdhR;^J;eK4FIHzyR zvz?zIGERPOwY1-}t#BvBbDa7Lt_fzmUcfgn|GwwIt-b@^Ti7pHSoNy;Y^?rv&S<$S z#-*Id9D9p?wYR{z%WltIUK;ydp1*nblTnlW31@$_(V9gT#~tIF-d&*$5;V}rxZ;Pp z3c3Rav9oYM^G!|+5#20}Plww%q7E%#(i&@v$ko;(YD~1#jkLjSD-AbWSKijxj#T?M zMeJDf-s&@S8_y|_S9$YmCReAIFzwTTdR(bJs6jgw_^yJf!M)ke6zRTt&%*mRd{5_j zzuEjO$LLkO{0poh^_|s+O&nLlW#n!ii?Av`nYY(-!MEpFzZc3NRu%+qQuWl1N*7?# zuc`egg|QMDqC!i@5e%Vcwyim1zi&={UAG zRij4rT-Z8;WQEqQno($3(MYB(u&B$9MRTD;-Mnv1>!Re+8pf6`7SEwM07R@@oyu z%DlTQ&eDrc{3T9fRZaMbW6~&kx(ODdXc|;vd(h_ul%*}+er9eCZuacZpdDM%ZT|)_ zKfmb)==}xn`rO6&G?ir4ok_UHpz{LPPH+_gf^0jy=9Ru7<5xmA8ol#bTEFO87vJ?- z>m8YG`HuCsXFKuV;BSF)AHU_v&|Ay?Jt3#tjj8VT)Dq20YQeJ^oCiy7+z?A*+|*JP zqu%fVHH8xV<58M|K7H*;0uF{G1J=S7IO#m`eC4WY^MhQpmSxq0_~C-?*Sp%lJI1`b zR4OMs^2^TTz#F~Ho2BWj#;_!v=gJuglJa=x<6PpLjwebcRM0EGg)6_{WeS`rZ*Bs6O_2)hITt~6{38b9&jJbdv8OF!JA4UIZaFa zgx=td1{qQvW!sb&>2jol@$kBX-lx14+NH()0I5nOVQ*=KU)ru1>k^+=)DoVL)7LDg zZqbZh2kRv7I%qr9oPMvo>b0V_$ob`*SrZbdojpy^pI7=B3_{M3?`;e>AGtJibJEtZ zud}Srpjo(@SkE-4=^i1=s!Q56@nSAj*s4kn2xoH%XY&NSS)bF+IVT!KK($;_; z+igp!kNl(;b{}|+pcZR1q*|yKi;#1V);$kFN{>4lKaW!=_dNswR?e(Q|I&Qo9 zX6dxyH8u064Wvu4EmnHgy;x>mjftUY%OFQH3og`rJWzCC7t8DFtEY5}!kVft?*=z7 z7jIR!cXwU1_0Hx{r(>#5__?;u`9qqI;^O*0C z`ZQv*JH6Ke1otyHwOh`F(i6E{oa&e(m( zX)aTokt#)TNWiEcW1|XAgixnIxpOo_ zp@Z=T&z*&o(j%JD?{*$RS_Am8&4WRT#jKuW*)yz%9=VR<{?w%Sh)ma{vo~&`x#z#z zJjC6$DsqXP7K}-oIXY{^dQmm1Q zXrl2KmRG@Bw!3AA-I)X62x)p|l_SF4rVJ4;c(!gAwr`jBLYZ|9Dfsya-dO1Q5F&1v z#&WZeGz7kR>pzAVJrc$&O~5yCx6e1GjtUqipuQ% zv0;qH+%oIGLe?>tl5kcC-ZX>o>%#F53dM@vU}MD-h;Kg1Ja9FSfzU%~Ws%aG63q1e zw5Zej-1>d47E1(vLtAN4J(n=p^1eouqC>iVU%_@p_KVSs{CGJh==n$n zca%+bzs?zv=WUMQM{$?q?!%8rirxo|^+}exaqJb%m3}eK!^)j&6vB!T#e0X)M$WDMmu zL^v3Vm~MChh{wFM5Jq`WHnx=lYOc6V`=$hv>(yPR`D3pfL}2zOMArnq7X8u`$ap!F zqa^tvbZWyQ<-?FEjD3t#x}JJ}lfB`3XGYwhahx5t6o@HiIV0E$yd5@ztA>8A%Y}gI z6igG%jpkw?=c9J3g>Af|bD|r89ksPfT6&Z$ayrWHF1`=iHkk)8X_g45VgXF)QMRlD z(Gs`n*=UVEB(eh>RWErk7bK7^+zu>UBk7^!n@lAVDQv@m1qg5=yX{0l;3+^Uz+`kV zC|D-I30FwqDVnwdC5s^g;VBeLAQKCc;3>dQzkj^7S*Lp&IC9~W1WoyLhVV(|N1!A~ zq@7o9kw0Xj5Ly5kLpIqN9=N2p%}n^GO#Enbo`ynHdKOmPnRsiY1c{H&CD3q27;)=< zHgtfXfs*ZmqgkK|8}24gskM-n^nm~&qSAPQMezM(GzKW)l5E-fG6iB_%n@fogahGM zIHbq4I@Xo#+DRlaE&Cv-M-U{lr~tfN3ygG)cYf;r%kxXLmKDLFO5t_<46lg0p0z_< zH+HMS&F=dB{#a*VdCUxC^ig2~6l6(kW8+OcR1i)GQ5Njd&d*|*GAonYElU$6%GG1H z=yUgzbQfK>CEm(&g_<_n{Do3C$!z7@juHX#M1;@gzND(b|ed<8a^kU-E?i)oHk!!w27mttcd-mI13~R4PuG3i!8fl zp%U(W8Pj6N903D6P{ znL3~hGlb0L3R4JXu9dB#4Cv9trW%iTwkVIcKL!Z3VHIoorZ904o z(xzK+91F@&xMv#P?BTAZ3)GrT!C=Pb5E?37S<2-(0iVp`g`l7&rRy1I2#h>`0oBuxZ*^MxN%IF->m)GNs^I*=?wi$v?n>j*4Y47 z_uHk!431ZNYp~gQ-R%mTWcx{J;V}Ls*o$SgTfMDX25%V>jg)0QYC+%6j2E0|! z-f!z|VCU^b{;;3f{$0i6f*TXDl(>v~ht^Wyy!6uJBKN+bKQbdtD+LjgJ->h=&Qu~e zH;3&+K@okJC2mh_gk^}}c;-MN#UtO`m1oY2hga*!|(2xKTIxo_(4I3Lk zgdqIWNQI0ubp3TyATY;FV80m@*3q-lBy8OROndCpDEJcX* zZz&@M&hu{xe+rjW`9Xw|XwK7{2Kf45gw`1#5Q%!k3N)r2&o2LmnlWIKJZXDmFgbab zC>k5S-jk8;cMpx!TfXC!9%PUWt$l;u2QIZ%YJPrwOHRfSl&dA77T!M$9K2DK3=)|g znzl&_7mzz2#~P=C*p_J}m|`#y`9fO>JtvyL^HZ(c%6mwfsQkJ;Q(ws^%yB}Nzg(bG z`Z%j%ll_*uyx%!r*i<2bfz;2~UIQ`)7O#N{kF^48K?r3H1qVr_oIEHInhl>0m z*<2X7uq&fhUS0FUTm!gZt1-@2Y)wRolSz|X?Kx+OeVUe!W>NA}sN{Mn+5Za3@C&RI`;`qYyo^ozC5$q11dGKp{Pi^RDMP#?PwsfIt%+ zuTV_KL%XfLbw%QQh&2)xT?t)8KQ!HOsu4nPZ;AVdJ!y8+M?A1w8G|4n?(`n`UT9YTieK5aN zZ;xEhL$|d|*x!VA6tV+Fq3rKTrR&Xxzrk1L0kR5DV}5Cwi-!$`+7SadJH+F5-=Ra7 zB4N#@eFs{}TL{9QWA&0ZUF=Q+yds6|%%KM-P-z@E#gQ=ZNpP&HX-ZTO+go49lC30>yR z$Fs@hy#8o>MDU;9y~LQ%EyaCRh#Q%&>Q5u6sjHA5& zn#Ex7EDz5CRgy^NE>Q?%C_HQqP)na8njOcMhLV7Z$$Fxs0%lmm`$6 zc|h?|?O99C+cXk(jG}FpGmo{(?l6?#lkBU#O&r&Xc3%nB?DUQ%b+7doQLw{;q94Kc zNLeNV9YHld9Q=42T+go?MYKfw@TVDv*FywD64PJ~2tzDe-ecf?)r6<-&Ew(2FRC$> zmcq5Reh*u%vhTbjJ5HhLXH^sMtXoXrIb#T|^PLVhb0;Pirai0KGZ5~{GVs6{x>u*( z;X0F8TI`6SxeYEIriA;Qt&FXQ}|>$o^ggi4yO0Vg1QiHg*5Ol>v)GURCyDykbLlPO~?9u$k&;`E zOc4VAY1BaQ;;~}BeONUPyk27lRCJ!L@CASj285J(NQHY>e;lk3x<5r^5JjVN@ih8$ zaQ&^tbnx5$OmK=y=Zje8H%FoTkWu&Ut322q41a16Wsr}m0yK?;^RK$1oe9zmY7A1@ z{O6pWW!#%%UDVes!;z~ozjT}sA>jDdb+1Zfv01+}q3k;xf#}l^6D>1!Kz~twT-k@R zG(}C*=F&4$3yJ&341|YekgAsJwG{`%tYGt4iuuPR3SfoA*rw|07R;J|=9FCk`#89a z;~r6c3e-&7WmfGpV9Meouu@BzEoz8S^7hQA(T|WeI=9Yfy=n6pN>@)l_CVwm8jbT{ z_cnw4v2-&21NSZ}B|h|)92GP|6STG#ymn|`H1ZOS^=SL@B9)p`NunrB^KI9;=PF<{oGT$UDU;!={S2d$Kb44o=2erHWh_|1nmv`P*3#0q7W^B=@s>T zB9S-hcN&Q}o;o6p1W9hb(N?7YM^ONgkS2kqJtTythbqYyXQTN;Sn^LjAVC&U_)4KA zAW0^KhD9EcZ~#Qp{-h7+34hcFXaS8|3K+S}Mpo3B{AfUHF3oMh& zgljS3Dp~~SvyqHqM3*Ih*pto4uRv0{*xU9(RMC4yk}R%H)^K33IpD+G@Zu^4nFEL- zgwRsu(ZW71k~UkxfT=iX#^i5vz}N9eAX}WVQyc(}%t1I|Si*NEd?IHZG7g4_nJ{kn zD-0TGt#@-#8Z$oBpL1DbCeb6Jm@)h)1m<7|$+Y?j6Auw@6r&_^nMt$_1Y{Q03osnM zvqOguQ=-Jj5dC_PDID&9I+sit^NUS1S$N}?o7y{@UXyP8mvVre(s!5jN^gw_zZL>Qer2SFH!##a8pMN&7K=44hNEq?z z-jYo=b2cgg;~dnr(CmPXTMn4oNOPdXTE?O!}c zPC&qI_`X1M5wK87gX%HCCz=HQX)L{ttn^sATueLg^`)l!$kozVe9`~#CZ85Qn(E=w zkbQ0(UuYgayh&5cKfFn?=E-5lU*4p~3*p0?XgoZ8c$4Bdp|!8|7%YT0bXvQS48kilsWsE|0g98w2`C9L zMc*WdBMbxL0467MaU%F4Xq~2VI<%TqJpjd$fdrHsm~Rk2&_Vy&2I4=Ll!>_iqV2_q zvf|lp?vusQQ@r*NjGhX5|DH>(GCyBD6Ib#NM*`6=O!9IA>VQpS3APAU)l>w+#V7t@ zZ8-i|n@0asxJ}NxSfy?Gp(k^i7wR3f|7LH%Q|Tw+Ma5*x%3uMP6YBFAmybK#D)WC; z?7j)^%KqQ2&?F2k6Q~d>;GxMA0CwH+GH9LuqGBxFks0*xf7YTm6AATyb2do?$3#wG z{dHvSP~jhK8w8XgQQuGgRO-+u+GZ{!TI0QK)~jpMHXWSf5& zoU%qCCR|jLNZ`CQPBiw1CoDwu8S-413EzIELYBK(#{rOjm?V&a7X0Y44|f#zp=cj| z??k?PkUOql=HJ>ib;LMFyhfcf03ihf zj-!$~BD+sR8lojL!Ss`5$T3mOkOZUw-11`e0Z|m#s5_VxXUgmJQm8}Psc@*T)qK?_ z%mQ;%EOl>QO07GaJI0z#elgdhvX<`F%ivChR%;7Y(Z27aqfvyV>hUT=M$W=UPh~~I z#79Pl98v(n561{^iVk@6-r%+YN z-5__7TR6{nN>VXwpC)3Zl1x?HC*i6B8-j?@#E8LJ_-aW6V;hbDoeziID@=@zj_4M3 z@H;O5bn1{bPTE`w0M34&6H(@s6xp6FwTnapi-ow1@zJ`O16X^0{!v1C@GwMEN3BdM zJ?I=aU;qDXb4)MFZ1x;}S(0}0PEb+ENXWtj;F!WF)AwfIu@4tavg!7uyJpr3mU7yZ zW63;L7@0i?67ydpIduZDtE2s(pz`IWIvFBZJP)NXO>U;2@vjF7bX?nAc@IlE($@CG zrgAUOzbk&3wjw{DuB&-o)~VHXojjKO7q3Br_n%(lj^iUJ#MJehR_=RS@Wzc@Ov0=j zt#B|4p#-NG+Pp)3$lzN*dt+$Qfl=!X5RoWF3L&~3~u$p6Z>nY;Ro-zQa$uyj(k2A4Eb zU*_0tM-C6KcO}Te==AsNc6Mne@+$cA(DVAf?HaL2;o*D|e>WJj+PD`r3G`Pu#d8*g zgkPFEiYmg2{skanbtGc>IUa-x2HXm**`idRxP3_Gc z@kQXGzI93KwDQhYR+@!@xfw%c|HYyBr%C=XiR@|xREH$fH)s3380vkApCyP4(Vxbn z*?HfL^e9pmA*mm6i;b(o;U$@G6B<`0lG$i3nCtdOsHo9~f&~ggO(Y1v zo#Zml#}rR5oib)3_9@w5W(9;x6(B?opWW`yiWZnxhG8iQ69o!EKrUk6duHn3E_;i_8b%EfD$ z@9CHXO^k2hz@6&|7vF10e&U<_w#}E@qg9Uj32V?rW!j2N&6Ef?}NUrjR?<^=kZUQj18qweye8P#>t0fX|!|oBWxzyiaoyM#=_Wo zicDFo7(4=Pd1=!QKMWzQHI!>iRWeu~=xDOlNy81Vu%cAHEYtP(4@DDLu;L|htnmG_ zOYl1st(~}(H{q+Du`a{9RT~>!C8y`*X1=)iD<%FY^-`gxvrr47KqFlFrK|#%g4Oz1dgb&# zwdiI`HqM5FMY2b+%c6bR35Msa*9QUu)^o?unZsU%4{D?;(`cWS8X?E0zQ@P6QgUm) zMJNWMCeIv{-RQkNDyJMoHJ*n3ye0)BrXeF{mUe zA#k72&F5#7wO5qwbKT?Hce``vm3^#2H>W54)%9538RS!MZhnP{6(x$Ybv}*>1NCSF zd9Tj+$5k|9OSQ@cr49mIo<4WwozdzVMM*tJeipX=Yue8n0*=CLMa(%Pup?d)TJ2c% zVC+dNSm`mAl4me?SQ~e|WXpPc(+3HF?r(IZ{lvEA1}@#OauMwXNw$(~+byrls(r)R zxZVrlsU$P^%L&B%uL_(k;znVCT>?3R*|oEU223LfOhb|n_4{1K!J407o@iFczSi3X zLa-Q+wX-!+L<}z!J52QuAH$buY`kE=FPL?xFQx{Cb#&QeyAlZc66O%xUTlZO>bbt9 z#n73|FZIu28u^+yvO8SUHqI04wT&uz--;C)WI z6;-u>L+mtJx#P%73M0vX3Wt&7^&KnBozWiHgR|Yx*ZC0d^ZI&y8nzL(So^hRztMMQ zu97f27c08W2Ni5v*9!K2)J;XJi#MT^AP|yj-~#ALY`0reb5g0}PhuGr-lD}p(!hwO z{Hkxdgr0>aLD0}_UhC3MEEaQX7^oQk19iqd`celgM`rS35g&E2f-#O1Ov2>S3&Ow)#=MKvpI)>P=hb+@?<>LG^~on+LuqbkkfUa+xz+Ciw!Dkq z9}tLMg`aBOeZ=+Sl~tZMIZr1q>|-0xHjsTkuihqp4ePrj6mYM|ovM7*3~2JpI4pz= zevh&z$+9U1Ose^)jy0tgkdKzWM2M9KYy@7_)~G*9E45ILu}by(J|ClklLog}`Y zCHYldEkP8L$=<}5NtPer`t0TicRePf5WT3=zfd1EBBv zW77CV3O^3HEMar9z%cw_(BjP-1>=coe1R$P(&4!d@-%H9IV4fn%9N>lk z@=qd(X8cKqsHJ*~KT$;|lF`D}93|~i(^8uG!=Mc#v{wwH+LX}nKdj7We0K}{T>2zl z@8GEV&id`{JT&{70uV#T>IfK)iYL{wAQAthhO!4XJnIl=0!yC z-%E5y>J%Bpl+xK^sWp1jnRl;VaKDfl9GIrk|jtnl>y<-z%2bs?4b zjIsl??@qSkdRh*KG+%*W%O(X{W2C3?MXZ*)vY`GGj6GRh7N4va6MOZ~<6jZ%dIxZd)7Fin*T_d_pN3$JPApjr5&#L)!#b$>R%DL9Z=>?=s zPQNo8!CDT_C)vbJ_J`h!t#Zx5@Q0-&sDmc*r72~ZBsOHEguUEZ^Od|;>1=3dH2oU+ zrvsg>w_8iUNbWtBo(0o#KYqVkdEyw@-S>*UZVL4r$i%=Gy~vlTpN&{tI7mgkbcrv7 zHR^AoELqDNksfzvQac^AkgwewuZ-k5PD%PE@?krlEEB2cwqfGkc5`E zj4!@7IvB6v2;MOuc@f&mJ&xq9;}T>9^~oQsULX76qy3^ICYIX>^*Oo{R2K%NcF?VU z;}m&#@0*x=rMVRh#6(1`XQK5|HQd#GIVOcY!67; zxVHr1N}(b4A$h|E z&9>a3b^Ba|zX-l=-CR2+jD~>u$hbsQTskaBFuoTn%*w5Ux*Bn()rTdK55MpE#1|R*^a^mDEojF>Gbz7yd{0xzBAJIy%(x=IM!3D41j!d*To%vdRT2*^ zG_XY}K{q}|p#6H3mc)s->Vf4u1}?(1;oUZ2D&5#7iTWe+*ktAAt)EW!h1v;4fPp;o zICFSeMNf2O)BBRZ%!^#D($01NS~88((lEHml9i~=N8M!uyBWIASlt-AVRLh0!C!{f z@3b9D^QTQyX0})g0V(qwJtjLSY-;}mL0~q8i4Zk$ zJp7}kvm74!mQ7%}7%pxl zt%cMhy;fbTQYe$-1`~+U4d8jiI=u7~8!LU8V}nR%Wx`DL#szbtXkxo<{Z?iXymuVh zYUU3)gyPv){|GJMmEF7TQX2c_-4t8fvO2uX>-S`{HFek5!?yQbDYu7b=fP!AWQuI# zn*CrbH(*#W2h4CIjYr=P$br|I*C5-f+3gy)2<10 z(fKlA-%KMtJY({jHf5g|JeWZEP%&Q(-`nRs;22pDm#{|8eCMWIKI5MEbn1C2_BUk} zkH!J+4ofwUhKf`V+>UzXOUr5ARc&HPr_|n*(Br{p8Y-ebDysJaYQJ0EV-e}X7tLsx zoXRW0T+k#zs&^53p5?j>XgxQ1WWRIlCnKy}JwE2jHixczhvfh<=x>Mmw_lMUK92TK z-&n|A?in+JRN?$wg!(s*3&78r}STIF%T=UQ(E4VM%)S9{lk0yx9p z7t}TeHenO=T*Pk)be?`^yY>6W_6htJ8X@b9yY9^M#*TMnu5)6RNkueLJEYi++AUe8<(%yek1?hq0rvwz<3j2%+k z&=GoD=?=RaHrvUP>b^Kc{==!RLT~c@;Z&nt)PH{an^W!j4^CAfgrI4Om(VnbTb+T! z5U+L1WPIU!Vu_2ElvGjU(Kj8lh%uLxPA$_S1RL5Bn_C3irh})jI)a^LqG$eO-AeAe z<2S~&aP3k-dADX{WLme^{gnHKZYJd?i6!RS!6w<-)Ync;2b-gmqnKog23jMp=7Ae2 zKl64H&&u`kRt}d+DH^DiEA6MqfR>k(PQy6*Zt_~}l}|OT`=zzMuE}ZZXu;}hxoIqe zG@-L}+DV5hZj8~YYl4c!N3T{NcxtRK*G}%8xmh>&2G3JD!u{f~rTUZWrXOI*;^&ik zEByOOc00MYO)S)W0f^;R3r)YYj?ctmVlX}@)WRlm0Mbu|U`W7qf* z4?PyxVe8I_@asgw?BYtlKf|N73|EX@Qu^ZB=QJ!nMUaK@8R9*~K=!rN64^gB{xCki=^53Y@lUP1_m9=vLvi=8a zMBEd6_Ly%C%9Q`x>m&5sU`tEm_^Y!YEGffS44%=Isr>TU>Wg+Hk-Rt!!S?o5Q8DPD5%~Ix@Sf}(Ti!VX7OI+6W_c!at+TQNP4>%WZtN8e;Qt7zhRXhTNR?HClo7?syIJfH&!n6P z1c?U0g@?fPz@2_Dz85b-eH1DzU7Pg>+92RIk@ycv=6($Xwn&?qMcoqKW}n}(*{rdt z!k6toFBuQ3P%2m7*QSmKJ~I~xlzc!=T#Sdimw8V6nw^)HV{^`!CL1l^g{yzXh->fk zmd)buCrlpV+aq&(RIlq?tz z3_T!D^dF)0ZYZ@i47WFVTA;(O2Gp;$q`EZ2_S{h}8RqpVW4sa+q}kvBYinF8uN&gf z!#>EuRW8gnNJ6AedX(MfBqB}(VO!!2@<{C6Pd*2%Vr>JiI6YeaO^(Qx=s$y2URHVr zw0!Be4C&vO&p!qYK?)sXKr7JL>gux|{?65tc9OL$#{tSR1x0|3JH|4Hz=Do}0tvT> zjU)7qJp=nV7FU)uU}r`OZIT?!-2SQYE1nzX2j~jZ0T*kDVgd=Mqf%5WbYqncSJ}16 zSu-#m!r;E5azscRHao;_CHa#-29QxC_TL^T_2I_#&y&>|WFn$=yL)`#sT2_#zUcJ1 zWN1VYUlRZ$PNWh4j5rGD{w?Al6zb0iQ74Xhv9|U}hAFwn1H@u0iIu{|NEMK?E403u>0s4kDntop z-S*_`NP=~#t|E}}mN+)neyzF0XJjv!Jh43n+~SY2bCwr8-7u6pRroH=mlmPTg+QeX zOSVT@e(E*A=`y0X{_k_+(1!k9YNCl>lsDJ49$O=q6(FM3a zt8_7(dNJ23M#y0zDlM>pj|mb~CZ4l|3L%f`i>B;f3`zjS_p68}5=i!BANe4P;Y=X< zoN0_Ox>x|(+*dl#q(5Qpe`vd7AF65(YAvF;Iaz8MECQDyyCS-n0a{U(@CO$2SNIzT z*%MrU^AY|+{Rw{!#{v0=5Y)=U5dVp_f&k*t3tIW00GI73kOoMT|BXrIhWXzxsrlks z|H7p1!VK4856Az_q{bC;0AsXJnpOlmkz^pAgMQi~-= zc0Y1o(9{2GCY8hfUH!)^&Q5b*(hQr4x7ftNE1LlF+qG|sf@0!PhA>%3WX1=ED#1$j zLtZ`u=ObXPM=iUh$G2@pwB;q zN62Q@?Z$~B&i+Nr()Gk9QXoGtbwdH{cq~-XP~8U^1m+b@5F#+4aa5vXg5#}gu>N?m zw2uMeW0?7)WtRT|o=A&@y?y#vk$<5lQ5EJ$tmyqm#ON>uZa1(3Ng;F*I9(BF+kHpb zk5Y!mS?zmFkhENaNzx3)IM_2F1Ymr0aC``3jmJ#rk_cT(iC&1d**`?+|2?l&3n1=l z|6iyW6%j6~K1okMc`u+&g00|F6i`Kr2s=8QMT~UT5lH&9>M>*9e^jUI#%6dZAQgrV z`FBjqNf<5hA&7r2Q*mPdsf55>rfMQU7X067R3K?a0Ua=YM|C2ufj{gUL!Y&!pW`H~%UE`qM z!144-OH1o}^F>T4aQtt!UaTl~dzA{==Vm>fF-;NXN4h{Pb~QERk}xut`fA^$ zhnQ3$r2`kv-l8X@y^KsxB_Ge!d2ZEit7B!Qh$E4p@jS9Gz_;P8Z*X|%T&9X#rYejT z0Yt6DEO^06(ooPLGBRvy%sCCBq0RC$l(CcrbpNA<^_O_UWS)7mF{(w#N=7TgEwkZs z*sui`J5<=R5oE^PS;YkXsyo_!X5#=+HZ?28(>N+H$%~tI3Mlq*W3uH1_b&#K{&<0g zg_ttfbyaR)p%ezH0r!oKQsX!xSGJaM0$jS(Q6ECOwC^1zMJ~)M^>&1a*aS@WflAxJ zhIpYj(A|0VG$lg3?{tN&y&_r_?srx~wQ8ptJji}(GusLL+XANB)O+5|Jpv6?zY_*`d?RJzG|%Gj zj%M#O^~&XBufQi);VWELAh-wQl@`Vo?o3W0GsP}hEHGnhQ0)*%StvJrN`Qc%+@#Wd zl?zw$eSh-8oV_kTe$-D{bfr~*&0=YK-wb=qaP*D}6jj`OftaRnwI=GkarRh^;$B(O z3Etlt^e0%oEU@|RDZU!QI1}-w)D2jDazi}5=s!M!H12?@C;!Ls7nGk;v9EDran%4~ zW7?qMlzgl>dV1pe+m;ilIQltfrKO^K#zp67Pr>+-2}Ik{mW%dYn~x;}VO#3f3}&CX z4+-uK|M2PJG_$WordF~u)J3aLLL0QVxD91(w*w>`9tDfYmZZNrl=v*Wty?O*vRp0` z^%u)}iVjPMRPnb86}v-K(L~SWRV67J`Y=gW)L%4u^_KUAg>;MaZZ-yLU-(suP5a7e zmNZ^Vf}sc6>*+$f0Nz#~Dc}9ikCd;bI-iQKz^kxTDf(Cs1A~1O1ZnLYVt;^#|9)8J zAc`&!%X-gu$C8v^J5QreV~%WwU9J_aOoZ%P$fa^x7)@H=Tb`48v1+js`4UtOA)>86a2Vweg%@wQsn`Sq+_<`&z zuW$;^#;b=Q-*>RC-M+~Ci@AJfHRTN2n2y1t=HdFzwNbV4D8UkrXv@5(_E#uW^H(TD z5cXFnv_{{LXWiU&j_i5Y^F2d;doBYvxT4;2O>LBtR8c)_FZ@; zw4ap_0sk3Q%K7k(9e2&(NXYgxT*BuNABVx@4|zfxjCA2z3CuC#WHuhA{*ba#1tS^c z$BxLe7tBS1MD?(ar9y!lG4jIh;C}0?z7x^}BZm_;(lh>KYs~Z?sbuossU);!ih`69 zaQ^ARQfYD(fG_r3S1I%Dq@{wGBqS)!)jCc4CD!^=0*Cra7e@#VKS@-bf$`u-d-AN#xwf*Rz^0X2)i^7Bm0mIQmWi zt5+#rFySgm5o((vXm~e2Z1)_MT7~wCa4p-|RA>RU#?R?TF%7Zlhe3>T^0295#Dlrylo#jg7Knb+f6w5!(2jLYlI>e0QPS7|QC zr1Vi#Q5KfJR{4(qZiKRxHLWVLX-BIq4;ve-LlInj1jW zNvJXzEyPWXl;YsC$AYdg z_tB-9dbb{5(BK$Gv~&`(#7l~w$=V_d(AvqgM7so1ca?|9x!cUu)sGUwGiG0Z>Y!Qv zOoBC5k)2H1)UT{$!c9?Z`uvGimiqHBD(jNzS|cuy*R)?O!-6BuLLGl{oQ7Pa7I&>v ze_#JAJMOXCXGo1)VkL2P%fRaehADjvbc&)5I`BU?{r`WYy>(C=-`XyU1t&NO5FCO_ z(4d1m!QI`12WN11hd^+*;O_43?(Qx#bNTIkzkR;C=YHp(Q>&`0r)sLFYt@?7&-*^o zE0O#7y9m|A^!|oH1N7QCejnm#bugnAzYn`OnmEF1! zp8?#ked67secJlPn8k7gE|Na{UcBqeug}k-b5-|%RYDTxhfDN}cg`G=omj27n_dR; zmlcs^qW($XpTf;br_ZfYV~JQ0=0c`tXfh{dL9laiaeO+`hAD?e%2AFYiJ4^dVrLeN zfc1OZk3tf&{tpu3kNSIVQn5dN7(949^4kH$!SU>iw1}6eaD}9#Qgfw+#BkGQ(x8j( z?#A2GfgixjtESiOxi4OCtZUoU>I=_nqof*shr}}s!+High64oFake{T=GGmhP`Udw zp*Q=XtU>u`hRMK_ZEeZ3#$jcbBqI`$F~x-ox|xtyBqq`Wi_G{e-@O<#o|(@{D-rRV zwdkS;sh@s%!6U_!*p@ zi>xYD{gOL<6`4flqj%3H!4Vo9k@si#BuMw*!!jMckl@rbDQ%%cbiV+DPc?c_c3wR^ zk>YT_SHK5mr=_^Bl>H2HKfaP%wd^$y5H*`a9iaP3V7RFm(il|c3Jg~t{ROqK14i2= z-l}hRZ(~|X0Oyl?qxUK9-dK@jcNSN|HU!n-jL>XI*fqL0t-NpWRnr=!jF=S!zrfWqIj zGQh=44gT`O=k*8UTaf$a#&O*^v-st~U3Wt(iEA#&%CnTpgoo-%y#~#qcBJ|Lev(0-i#6r>-pFd6&^?g<(Zq&qN zGBg$8`8VjhC1dVoa`iQ|OmH3EnZQ1=^^T3)tBhry5H-sZ-g>l>{d9d1V!6O%Si-or4S+Zw;Q^EE|pXk5Kn zY|G0sFJIN=USAI{CSvj=W_}c1m<12Y!Wz11sf0Vi78I!};AGPXDwazs7MpJ%h(U)N zA%*)>(uQaD?#`;xhZlUnPtjN8Q+>FTPw`P?AKG4^SN)5W)Kpk|=a_>NaX#qFpGb^J zrKKn;ur~qI){QIUK5u%X7p1>RG?TM|+XVSh(tP5-quO0b^ z((exI!aZnj8+vX%-vuvv&Oz0|tlUiQF;X&*I*#+gqdGPPHtsW4^nE)i+G3qGd?ez% z86$nN3l|&}UfsAx%xJ%ycv(ZpBn}XcE$L-Rgz)oYLP_HTa}{e-qy~!qP{;DYtM&`%lBm&L8+mVx*K3Fc^ej7<+TB_B_#q{r z7iYbJ;sTYl9lX@K)VLS9okk58M{by0uX<|+8HHy&Rt=Kic)GW@rRO@WYIGS=!yBl0 zx-Kk9!L{XN!I?2B+^=MWlQN|HGs%KXj4cA2RI$qeYRR2&Sm(f$&B&^!hmqx{X2_vs zi45uSONt<|+P|fk&{DX9ifwda-L=%JLyC%10ULR3%dS4&V8#v(fuE?IXcv(o9=BT$ zaQ`SUy}t81!wQXYt`0Tjpt&!SRB9}PC_&IV!r?a8%k)gg382GkDcb`Aj+;V%m5-s0 z6*n9{Ee-^m&C)P1kd1IrSt3gjh9(20Z$>fpe7g6*xuE(&kkmC}hI(&-IpOS!A`DJzYysd!)1nY37t zIII`*U-2m%V(mSWjg5HVsq@T8_-qiR2xobK{4llPXl=W%#;$hxR{>pKyj9 zQhjVs{Nc1|G4ptIbb3hgqjzJrwdfPgGMYubxjQt0N}2cXd8=FE_~eVGazV7DdNoG7 z@A2);TJGIYzyy1!(zti(U_oQCUlCRiRn|%TAw=I7MH?3OwG}u9$4>J3v z$YOf1ZfN#wr&6*+7}fEi({S|8DTDRUqQ9btE3nQvkR{A4U%AvKuHC1v*z+@&gdUIGWEHBy?BNUuA>(nZ0)9Oe*`qw zOvt2h+8QZ1D!sBHheSB4dyJ_95}m_@jsEOmS$dbfoUT>fhY+=QvQ{v!vsxpX&%Jz+ zNjO@oWIaGExJNU+q{33A%rE$ril{lv{Uf+N8H+`{e%?KFc-)}GaICIGljB>8YQcSw zBSo&u)M`~dGAF070EFH^+^M8{XsQz1O@Jy@xze^2TDgPxkaFR^rGWwU)AiL^6 zQUk!hqz1$D2LD}Z@b(tBjZm_@3K)MF=U5Pk1!TdmoX_ua-KO%l{Q!z;uaSiz8Ir$8 zgy~^^mP>QJQ$kF*bUe7%NA!*Wk2=mNSV8tVzB4DXMas?U)G6!}WMIC2&WJPOp+Lg_ zcyR24_5ao!_EE}(1y17m6HdRx+t_^BU?zqLUB&gJw@rxnW4-ToEvh_)est&qz%9>f zmz!X5BZQBh(JW(4}taeOkxWA&8gHjpRU68 zRnm;101F8T*QhM4MGTR&ozv?988ZdSW-r)?n#^sFpia1L5)`C=%GfT;wISwH`+N(Us$jjeH6;`WE4^=F~fz*VfHp_KZJ9-4)JlC{+~ z59rPYlffYg$Lifk-0742u={vdCcob9@f!X6u{Vp5P#y$`QC}_4!HpXs)6|8UL4^ce zH6C>`NPJ9UfReH_A{tiz?0ZL_$Wkg(_F8r)o~ScJMHzzj5m9N-Dc|ucZN!wI$5PUm zkOD(Bv94NSH9^iKMCNbqH`+e@l*D8UI^o&12Qn=>py)cXaPtdA@j!DRfom-LFGe;j z)OLlvi~j?_h5HY{MT8c+*f5K0O+u9&jmaC)#7(Ln%cKa~Z);|C6{oqMy9^jjm~Y|0 z&`a`>n=PkR!~#%-leSoSPpc*hx~XQ!_fi!y$bHl?C8^_+S(lrHqNgYAubIqC)4P=;a1ad zYzWu$(%0pB2;R$=seng32kt89fC^jBbXO@AHzO+dLub10-jUS?B?*cG^=49B88Y0Y ziZgobqjz&h`8HkNV(!hNbJK=%h@oBy*pBM%r=9ej>;989sJKJhl23I2s{#uPkkr{h zeC82;co}}ug6q0e($xD7ZvXLgyd&9j0@adFSsAtHMwd3`t=^|P{HQUVS(j^XXGhe7 zfZCEds?+J9{mm}~47qlR`n;)}3(MO{C0qz0T#M#PfP!B<_*}}>a`pJ~gp__a$~Yqb zKR6bK>VM%_hpHR;aJ$FNmg1jh5rZ-6mz(-T?>IL59mg(QExLB*KHVH|IhuwGZ;G}B zyFd%2Bze)DoL~tvk)4a=98hu4ewRwQmcviZVCx|BCq0LSQ?I0Jx(Px~O%HqOH@JK= zaJxNy>&+EPCZTf0@IG4h~{~cXim7UnaFKxc_h{ymk4jm%r)LaV_(A7#^+z zI#Z9bIwWAdreCgq15h_+>1!iLARPN{Oj6H7@0eNg=FOwN6K$n)t}GT&5>hV(saH#9 zXm~J>v_dUVfg~POg1?oEz&v+aJwuc%2e&8TMULbjTc$gB1Uj0Zo||5;XRlmkIA5!3 z>x};a%+ehH2F!U}zTorNH-MRbz3K>%sK={^KZ)iRvvw?QCS5^TtjsV?g+ILCMdK@3 z`%3yAz?kwvs)K!B+GNCwrRw`i2>qfi1)pk|gsHV?$4B4t5}%K0^Q2GaM9qjzU|}N; z$9Zq&g4s2$^gDi@mzU>|*}so>7snr@A7Hf3HGlZRhs|%88P&Ii5U%L68k0t{!5t$`sq@)=xHpUufb|GSO0kKyFSG~l`4ci`9i>8i{F z3DBNAFf3fS9j9OBx6Lp4ReBwHG4|BhNc&T6BLsWCAAw0K*6A^nPD~B`R9P`|X;XSX za6pj7&xrn&=Vf%=Cy!NaPD4x&OkaVw`>w!(RkH=EH&mJD(zva1B0l_f=zaO1K zh_Qw;F_=k${#XjLzR&&JoTWQ*XndiZ4~nUd_I&JuxjA~-{7WnkV_~b&AO3lyD2X|o zzxykcor!J}hW<%9cQSObq_irXGO!rK%J-h;zH^qo0qT|D0w%Ll2ubVB68ZV&p~&*9 z)A$OY5vX^GAy7`p^^fSa2XnUvvwA2We9L(zvj}NM4!_y|G0ReP!^j}e^0C^d)$_$Y z>4hX0K`>Z^k6aYpS7+>VOsL|4TVL3ldo(eIOa$?ho8vvm!x%Cfvpuo#_x807B)6G& z?gI)X#-a5fZH3bDx$6RVyT3|~@OPYl(I+`Q9F3Id`#{s;rTgK%@P@(p&`05)>!wTp z#p3<4UvT?prqrKtgDz5wvVKf_sF?up^KdOFsehk(-?PdTd>*kM_C12aVdzgI*(MYn z8RT-ET1QeTN>#WLRbwSp;$o9m49QKX=)(=GOz8;qY+Z@ zoK){DJ3<(J-iFe-=hs~7wz|*xn{oQ!s~DnPsjKDeD|YSEF|8>|&tQRxvNtxqw2W=; zo?VAqOl?rv{K@akXA}Bc@qeOlZQMD_D=y46HLF%! z?|yT+KW}|Rr)LC(4>M`9)KAQiQbp2JsN#>&2*-t6CPfnc2VwHn%w3s7F zx%?PE>o)n9^bDIYdt$N37DTA|Zjr?q1q!1?_Sg-;xyL@DANDP!|L&xJ)vTn_SZ7n{ zdc%nBI60B^t1(f$23`+yzmh&o{AyTjoS5&udU}1H7@v&xaeS+dYyx^GX?$bmIGt3M zN@V^7^ADu(zk)b?5d~GiHgpQlUGDQI`@YaO=QAcMgy7x~f0Dj7F2@d=fq&Rq;|Aml z!cOQXzWcm9R@=5fv;5BXJWFQs=TT)vt)~aa*-lVlF=W@*JKvs16)~uyPBClVjDW6B zr#;LM%mCHSa`7``JC4smV*OGNrqQbG48L&Ef>irYbya1lKHWy)wauM|hcP*$O(uig zW@isL$W4FD06pNLXGrkydV7q5VGig{lD$~!0j)Xttc^0>KMmB!e;TM%+B)TR)zN$OIy!CIXzo;Nhl%Qh@m`MyI%r-xPS_ZDJJEn>Ie?Wo5=5`oWJO z;6u-n&C6Qq-lpTX?*d2XTAMEthd}A(Cby`5bxJ0uCdCez+(c!JNOCPOZRpFjN524U zHOY0&w;1|F(f=yz$A1ps$rxebeXf$aW)pX29fV=V_m1WfGM#zTInuxm{L5aWzl>P8 zPxopWh1~Mz8DU<1r~LH^bhcVqhwv%8kI8q7hk`8=>VJ9)|N7@CJQ}r#89MjhZCuy? z*tiVn)q!jGrtg#Vt>t|1;Ptkneb(}~e&ojZae%EW;6fBoce{Tl$YCv$mi_B?i9JM@ zBbfjEUi`pLCh+U9b-mU}8a!I2VOzwAk~jZJa*3qf3ouISuKf zF;06cF7R#mz4vHc4BvaS>DVG}y>TZ#*cqQ)#OQw+&*9IayWD!R&+7x;h{qqQ4!KNJ ziKDXZIEqJJwT5c#O%0o<@rU?B?GZU_#u%wp_V4}?PHWFi*-*4)MLzH*$HEV=-*}G` z{t+Quf299G;BHs9xV||b6MZUS-t9dikUCI7&7@=PV~6014*!SlxvV0iuoJs2O%Xan zCX4JY`ZJ48K-pCje$BVS>2~Kc7L3#jE2_(rua^X9xYL;xadMFtscr5X8oyQ*xoW0e zLn_s{E)o*71^$!id+;=04``C_#X6^{-4{Uhcy_eX$lmTPqtM0@YJ`TEGux ztMb;7Ur_>}pGy}A8Hv|niE0f4SyxWUQ%?6SJH2Q7k(EofeNQ>vqi)TN)aOTaiSd$_ zO=MH{VSd4*(YJ(1y#~wdoq6YJGggx>=Eg*8)g|}5s{iEq27v#EJYScIc1-KpQzf9C znht%lX-gjI%-P72lI^$l8IttMl}#&Gy2|>s()e({hBwYOqb+6B|3`-}d>|3}HSje6MFUP+O!u%~Pz`if# z$8HfGIgO)9pMEnXA1dy?%4$^n67w?g=#egNo35?lL}=sXIIjXx!V_zUz910=Ijp(@ zXXotxxSoQA*2kHw9Uul5#4bvYt{0nRb0jDCM9yn~{FeX-;9;YU)}itg;!U3jbb;_~ z{dtU56;S2;cpiFt*Lva{6iXVO4Oe%rJn0GGg~k!?@|Egpx@fJ$!y>(1$+};+#@L`2 z>74QT^@y^x`ZpvCOlY^d^5wOvU2YXEW&CUHv&1Lz+IAEhaB9Orx7ZIm$8nNJ$Bo$f z1;Q%F@rweRUsbxJkVG!YHfyK#Zx+8SnO+pP8uLB_v^t0qxuhpAv&oO6z;TR`8%rc3 z6h~1nfiAf5#4M;D>tvOVo3BLINrT(xyc}p0vr4xG(?lQqJK6JnqoZeJ?6zP%XpVA@ zk8=!j41^x;2Gh31T(}IBy~JFeC^n$jtlS0OVgYz)%vj`G!JfM_O1@d^hHvjYo?(_A zy0UUX87d$f6v5es180EYD+Hy72)zUk{WSU^DMu8}09DBJ7%pj?tS~ayW+2h;Cqm15 zhBNP7S}ZG$RAVoO(m~ciHJRycIL+-N9R;Q-h5|ecGF+nHA1Du)BcyLfNSV(kNHBCj zdDT*&QIO0Rz3q74TlU4C&D*o*+9uOZD#dso4VT`OFKAYj>Mpz9C<^z4P!K{Wu(=lI z`uWdwB`*iN%{&lnwZ7-~<>kgIdHPRW2>P|Sm{A3v6g|W`sq2`?-v}F+!b3t>)vkXJ zg@0wayQlNHgg4`gh&iE>vlGQ*zmY$T`WrspBx<&SrPGSquz^ym^X>Lma}T3T39IAY z41;bxW_>wp%~=~o(>qEca94KY9V61&-mejubJXfUEckYh`0=cIh{ z;TV(eLHpHk4REy?H35ToU_y`(4VY`{96=rqg11b=#H9r!gbZ00Tx-1N*DkJ(rVJhu z9%`0D_!o)uHB6gf+;UmsDqyyPbDD-@v5-wWp`LysECHdH^>a$H)Ud#HSb~t|9Do>G zDL>`z*(Am^I$n%4M3_nrBHAqqw*_2zlAkwOha@h7<3z$@&^&x@Zu%b43Zu(g?A`GW5REH<;VdyPgc=D4zaN<20S!JpjDR3t0Z)8%XWdVcpGfi{A9{fkceA)9k1=!x z=?rh4+Oeb{*jHwaQ+Wr?7guw9>MHd4o%!8szuU$Z#gsjt+PaSw0ApKF*nXoe=vgyy zi1=BVAvIp@VHikF`eqjv^@=l0Vk{|?I-;EQ*-@fL_t zPZ4q>%0{p8opUJNi5Cx08B5y*5;kCkueukShT{DYhq19UloU zKx1O1|Lg$zaiROhYmz6)z~vn&yI1!-c%Q&8tJ}_m`ZV?&D~I3J%)% zT( zPK*@u9Sn)Ma5m0P?MuZGKRu6#X^Gaf^>ihJ_1GT3?zCTdxwn4b^z^EWf72x- zFr-C2y%^P(Vin{>j#t}9R4W9@4Tg&!Bm_qga0Gl(vf-5jfruXN;%R<>0&lny$_n9kr2+ha#Y&P_xigl3}* z_&@!_PiV@As&7S)%@d_r3#|p+OMEtcf&Z4okjjG)3-=EU&-8-vf;^RCzt_2n0b+KM>izGk3QyB^FUWvIfJvjL} zqVq6cL$rhYLI^Ay4}2+cibr1+wLb=6GEg*;Y2d*bNwtuH7zK6pB)K$0)x7Sbc9l+B zem#>CM(t;QdVV}8c2Ln4;Q4MROy7~}=^(kg+OYG=E^JapS>^aer9^U~LquxBV8Q+L z*o0qhjVl{pBDcaxvPJW7D#F+z)&MRWz|H|nVJaFHJo6xgt}7+n+4%v+34JPx!uBO4 zP&OZUd;M!Mw{bE=!fTK{=Hc<@TrVh2)tU3M)9ie8l3Lgc21ISbxkXzhL1jJvsS)j+ z_@)L{;Uko=nC03{1-0Uk0$nf1q~hMVVR8UZ`9^+)k29LZDbYBHpj$s5s*sg2xo-kj zk;!l|CWao348 zq3?k~%_fEw^-Ib42U-kqEL*2-TWC5K=*uEC>4yLwiQ?uPE%$1*y%GeC)0f_G}IJX*%`jh*k>nQa7Vc?6&Kq6y? z!(0mdAdM9cK#ngw%fAl2I1BG2Vi>(kr-_UnOr3OmLDf3n*6uDt_FC{BO2JMF+c56Xfy zywz_Y4ALgd!J8(MNOx#mKrV%H^Ff9}BycLslRQ5yb>8Ad(48*gspe4dG?wxgvht8= z7>e)1e~E!8Q=?Er!08@OEXj?at3Ti4UDINij}1d0w|D1# zyJ70y4I}|&ZM6&;G?o<2iO$94xWA}_KJ5rS&Gxu!Vcx6G13b9P`+XannZcE@=ab<{ zKQ&n}e8wYP@_6yGeOm8i2(l$;DEKv!;}m6Jk|9+B|@0L0Dot`IF2)}kjl<^}uy?le2r>3FL*Lm>Gl0O}58b5qYNazYdSy10I+4NWk&$C2xRdW8a zZe={Nw^<}U^?XHs2_NHP`X=KoCV+yCk0z_KY2Z_13j1o_Qh{hfIgSoGT$%RDQI4k> zSR?&T4nkj`mI?*qn@~Z6i=rST^%ya>3$BVq>wizrwylmgL{Hh2@=JQS`%o{o* z>JJ5-jTR_ymT?HC@qnVgX?s<+34^e{(5A3KngQGO23|HQ{ubm5Pt?}%8_<$OjdDYa zTep*)QO}#ti`&DVX`=DRS(;MDh3{WdFWNX>FgRI5B__b!OJ>{s{Gq4$b?u*b()?bkZ$+6^L=Hfe!HzdkQri8 z$DFCNG23TksI$(|O=y!!i%W^mL9UGoH%`B0loD^tBLD6|hS|^k8i`Mvv_O|ALKnuGf#OrvCsZ=* zeaHr02QNgPGpfNp(N9()Ci3exyijs?HD_{kzvyyxX2BM}K%n1t;V7?dgK$|H>ak3Y zU4bfu@nCzeNKWX=75`dEDYm(^Gk5@a+iRS0mZ)M?IiE33wGH+S!z_G0!7xBSn|Id~ zu{3X^o&vD^=00BAf`lu;N1UC|TH$59?Q zYAGyGZz+zsDX{`{G}6NkGq{gT#?!*-`? zw9T)gS?ZuTmFi${p>wl5#y{z%kccHJh8RB6;P)x9JK;|FjZyFi+?|>1x6k1>VRiB& zho^fk?(0moBfIbQ($DkDpLQf|U+}8T3%p_db9#<+w`l`%;yI445k#oMG1IIkLvbs= zZ;}({Vul7gibWJeyv3r$SzKTRn1nvh3mL&7lLZ-e?j@p75InF&V-NTYU>X4Sg!7{y z@v&idkf+O=yUp{;+t=mq?2%4dZ8rE9-BpJx-Y#k{hf{@A!JLf4TK69&0?al^(RWts zEZtFK0i0RdmIp#2iY}z~7PBy7^U%1hiyV%MF5!hgXJrCoet@E1?&$bz2^R($e#rr`%j1TWa zOj;D$R?C;h$m(t2{j%|-ihYHirdc!#Tvf^a=VjNe?utwTB%H>!ZvzMNIP!jXG)66I z>7rz${8lX+lWcvkC~(J$vBdQj$BM#qlqQKr<88i{xqe|_ywCX(LLNBz5@@&z_+k=1 z#nI!t(k`RlLE8OZjSa754@-_e!jDK3jujOTWM@aC(*^qsl|%4P*b`{bOc{8?jct;S zKb6m4eHn@#xdgo?m~DTDUsjwA<6-BXd`@59<296vf;{+B&&??UHG;sUzX@7Fdr=c8P)aMRQdImx$b)V(H?*jm$@)5THn zIln+S2T%MMAbGn0P89l|F&!s}qfgJHBuhk;_CEIuq>Qhk4nJ+`|HL#j*j0?nxO+gj z7LFvp0do=YVmh(WJC)1Vdnjck;rB)T#WV`229T9-C>aenDu>}vTF0A&Ss1yqETtyG zgv_Rb=Z{?2@0v17#2XUH&1mq*c(6`e|HM(|QQYIjvK+8+lw>8bbeybbRh~PLjwzYB zCo6sSa>V@P_}WySs0^}ITW00qTWNJ1c}Tu?^WYYOD&_bpt6bxL7vpF*p4`srY+SXb zdI3Tj;N^cq&DwvP4=5|87zIZ&wQA`KxSku;8WN>eyv}}F^;u(z_9=F=Z^@IlmiwJ8 zUT>nADZwAy{Oi^Ty*dbKS>`A3 z>>!SUi7}&WNSis9`-m13tFSdTMmwM+6l$7E-}_gEPnt-Y0R^T^6qNeDQM)I9dSbGC zX8N)n_DAM=t%J91ZM`xN6jioZQIt0maeLJ^dU15HI93o|aD7hg&p_>5lO$d^n};P9 z8i|*szL^cTFM?nXXvJ5Bvj7Uz$xlaSPDmX%WFdv&MNKPv82 z*?mdTTC5*MShireY#Zw2l8DM%xtZ>EcT(Fi7ksP60QP+Kj+-qV;*u;YRiQMWd4ac7 zeHb4ny@qUvMBxNvBYoH*xt=h0Q~8Dg5yk|hIXHLWBlrZ6_l7D6bsIZ`CzNMTZNf|m zO!@HCF)M|5!~7*dIit27-%WW;fI~C@F^|3gVaq$MckbCWvqY?yEyHntoFGW#J$&(# zl|ejCs~xDS#tbX2FcsUWF#QmCC-`DDas*LK+gtMZhuw1zHq0311=RQ^MXbqI9v#vl-&l|OYUB=WuELN4irn zfrsFWHH}R>5ZFbRF;kb%hJ^1rVPt%`Kj636++|9pRQNr0V!h(`(ef+?K@;|167K-v zVH&7cbNM$?v8AG^T!)dqbx0p%vXnI|knjtIv6BB+0dLB?<6W4wxaJlLCpi{94Pc<6sT;>? zt{df_B*8FGN~{~SE-L7hy}Y)=`K&$ebyNKVi zOm@iq%$JV2FJeJ$0G}5?K|o}0K2x$TeH`0-qAM|i64(ynI#3D@T1D>H2=*ed!l3#P zJ>?l)Nv;x0v;3Et-^k#~va2X9L|!B)Cvq5@aB|TE^wglrr@id5${cb!n(M5^*UW#k zg)~f(IpCf5Jo9;Xj>X=pqewYnqzebQBHg2ssM&iS8JzH>{N$)9?9bJ9oh-UTcTv2OTf%Dj;xzDwATwf)B z+-;v2EA^=i8`+0Ye`;z}$9+koC$c5}`Ezfis+rj70OlKYGl>K*p;Hg_tyxyRD{dRXnB3-zz^@W>+FIwP{#GSL0VUU`iV+gwmj zm9k}P`s2LFi(4Waxjgh(0&IoH^B~Yz>e?;)*+JP{=dQ8B$497FM8Yvz{`z%wHY4kN zd;Yw^?i9$*&J6kj`%Sm@#e8e~9_S#cZMz9S5AywJl@E5wZiI%SUcz?fQyoB&7;pNlhs?oxygPbIWKn<6J}wsf{~@ubbIL#567R_Ha5>A0NPMj(FOZ2`3zd!S8h5@O^! zIrY)ss!Z)%E)lZ1C8fjLF2GoMd3i{@c9IU6CrL$-LhU_@Rxbl%-#c*}E)Q{x62fBE zJMr_@4@70GR`a!KTC+R-sn8is$Ov12XLOtBvkt)HHIJ_sLdj%1CYW$H>z@aba6Fbv z^*C+`d0dND?7`_D$XHmUF!@dTi2^k z{PsGp%uh|=#(ebQg;5Eon!8fZSJf(>UJn+qli`AO65zC*z!k#y0UqX3mZTyJ1b$-o zG#9!oc?`X4A)S7fWX!)fBEU`X)Wj+I=c#Bl#{3YU{#hv^$@xTSxphq|4 zpj|lUsG(}kkB?;(3MAva_oPG{4#d(nN>GZDq{zZhs=5U;B2U~G!KKKan8t_dzwl#g z*jI0R1H4|;cbhr{er?`)>g`ypNmdX;Dch}~a^=LzpfuNo?ac(gFT|mXcTvn{V?=<= zt5lYV;@1sq!iH&`Ivxln(Zoh5wjn(4n3{Ona0Ahx(?piUcLVkTYgxS=4Ohp+wVn>X zgE9y&PJ~*ch!FvvHFfVV(}m3!nrEljo^kWm8jGU+TMuD`yFlh5>TJoT&VD#44e#Wc`7EjgV^^!&^L|4q+J#~3+9|O_hF0D)eDl(6C%U^d>Vqml~g8`8<$B}Qp_(= zUp=={wh&CeQ6vp#7xS3GNh@RDmjOU?jOcR~pw_$BYql*#Ix3Yd5EO18o!aVTl|t&o zrd@p>gO9je7Cpu8={H;NH(2bdi|XC%ni|FJ<~$kU)g?jVn;qwckK)H%!fsWlAnDiT zb!G#*USgjYyEa>Er?bunPFpS=&b+b09@7R_zj2b;1-_=CW4X%bUA+myngx$t)yn1e z#PN%I>*uT+_%K)7N?!PJrg1R<^4l+*U5U}gfE)4SXCf8$c16bc{|kcbgT4RRaSU5; z#L3UD!l&?)D~UE}v$-3uCo&)dfgYu37uw@MK>-w?wfE`VQ@U56ow%^jYJ%_0_knrk zO6ebZ3?AAI6K*SE#_NNDMNhIDHYc>)(!m;bx}pX0y7sdkDUNZWF4c{py8WH0pxvCKpF((X8M3*s zPN7K_1DP5>T|V9KcW5>mKZ$3tmpa&qr{rU0yuk^3`N$+yaPvVo{?=EfrV--xyHX~% z8Pdv0m&PLG56%h|JK6NC2}!OjLM6x_t0-Yho8H=OzEhH_`dzyi`db`n9_xeUUr~{I z5ACOmN<`;Osn)34)G<(zvt7~C>eGDoiC3+bK(o(sQq@hBgM$x%{xPB15y-Fvh}#`5 z{{kqK82=tEzfd{|sE;L;?puO)hZfvm!QsMJg7L=N+qD8_P(H0ffg=#XqOzc-nW@1f zOj1a59E2|*7ccECtw$1H(TvQ*51)Nn6VVQ3Z*@=%`ngCBJZ6AB4N-S!erf69m@Q%f+k_mR6rfG@Jn*YEdN9YJtK#7b$Lh_yzhirbW#(r^&yW*m}?fIztmbD~-|)X8J4& zk5?*zk}Tc3v__4sFI$M1UbL23hn-g}5ML2n(|sqb{7ddKSw5AiIHb@B1ql3Un9@c491Q zo;r&`%s~~)2a4rHqHO`;uOWFaNu!6Z=$RuIo%*E{GB(X>>_2s7{;1#6JaU|>o4vPO zm10=&vWIBEWp=TX9tl~@U=ac9CYNt2|7yA-90RAXvYd=ULyyZ7zh+KI=ftA@1)c=i z1f~vw&EW-j88bQM;jF6O+ATU0ISCFAo<}AC$zsQlQ_5POZ`%OHL|>f+W*M;Adr)k> z9lH`GFp|uR@2MDzK{WLDgoaSKfBuK^0o*}TLv#jpME{{fSa7=CGHQ2k%&0W?{H9qF zV_t7wJAILj9ezwvip2oweNMxQWKH*e?EwrWKV|<#Q@)_cw-)C29s@6nn|-opR}el( z*ait+G?A!(@Q3~pzw~m{w05Mx-1ymaVgPZ}SgWN6J6!3l?7XP45f4u=e0Qw}rxe~{ znz?di5aUDu|2BMD#gLhuRSHq*jm$pnRx-ACDM?kk;iSo6FR4L&}& zcE3;gT=t|jCr$T{r2RjjSLERBOiGcaHA{^#?Ip6+j&hqR!s-3o1D|naQDk!|57pZk z5n-)@{JCz<+v8$(+8;jZpFlK>?M~}&JnV({^v)ZcoI0KC_3BwQ>DiUK)IBDK0-spO zJB+_p`!Fq5 z7lYFi!CA{M|1QPO_S&{7A9vTZ{d}0@#24XCG5aI)vVPoVLYIiUiM=kLKPIRGuz`e` zJJaEWqKy&tdZLxpAKaJ(JfUv6t+BZ{e=Zd@b! z&HKgRP1Ntt>Z|-?BibNHwPi!V*_aBs`aL=f;eTgfoXf@kRisrYX3Vr_?%3_B2bA89 zTRrc+n5uV-bPn`C^IPEbidF-6^|FX?Pm3g0U)Aq<+1@4dDA|fS$-eJA&c8xH z7`afCk+wi-#L4cq$Kmz!o4-wkcKyO-W|Zl*2RcDNi=urEwcdsO^OG6K^e^`49pt!cSTNj7m7J|FGySq!U;BLVsI5cj-3GVI?Jh%pTCj@tQhwj_i``_RB z_1tr%R#n%cs9sHXRlkcl#xusuHQ`dou8G%L4x>c$O@Df14^k_8BRL+WmB3>Zcc(Xj zrIJltDF@=PVvj){P;niEPLH5;8|LJIgbg+CV@%hC)@&~vj0`-Ew_i7UC#&T0d;`A% zADHCDxj-)>B;*lebeV6|wiD`S_jfiy!&)-{CE)V+$i`_N>jzClN_)HW_83kRk|0Qx=QE+-mJioObx{zY~MPNz?H6_u~wB#&d@0JIZ~L^LYBDr=z}<{ zm}lZo7Vf7!+~3ltaz0= zte6&64-T%soifc@4tPmN(J5dJWuy63YCXtJPr37B z>UM?zpMV0YJ3;VL0YMjPTjlFx`E#BETWK78d-3S?R=3_P&cop3`X1See(Kmk1EvV{ zc3kKq7WWYnVT&<3zO(Q#6~Exox~B-8-TZ-$pqfA3H3FW#g_SA!G#=hrLeuC6sKU#<{$;|shI!$06fJ&|XKx&KYZ~l$ zU7#=Y=zev}Z<0@tpFm^v{@aN>8Ds7FEy@^`+Pmr!FsF`>$( zoD%rNQ)Zs^2hYpSUhYHWD+xA6g1GIsGvnN$e+@`vK05CUduMv~4mL%yfEBZnHR`VV z&ZZ74$J5^l!IeWa43}c5rA9QH>Ui?GIoYT$N(BC5 z`YDI4Kaop&4<)%poO4zQlrq!O4P;}t5cDCuarEAvRh%b}L3e+L zWC%5ksH?Uj#^{dMUsD^4*g)sxIIoc5*&~N!L(lOTTE`h4Dm2rfQ>U5>=o#!)se=Zt z-{H(6IVVbCM(bag=ztU+x$=6BJAX{$9MSwra|( zR-3u6(>(F>E}wG>XDw?X^Ak;8r-5VA+|+%EI~X(1yfBgC3y}-=Fl)Y96=_jcy3vtb z@kCVVnH^LlV9w$x6o8gzFZtWmmWCZ1;)RxIK5aOMcnT5N?A?rB?=g27GSPA+Z}kX1 z4$t>LhU4b47iJ+&*{;ACZ4-vf8Ld!C5?`7enr z6)drJ3jRxC(~Jw?vi@6Q8&nW)hQSD1p1(-oq{Nc9i&U!U7I=O~cE^9QQLyQ&U@UeA zx+@(hnP1XpG4aOxK(NjdQkrX>vy?h82VFv7urYSBUg|0ruZU&&)GBmc0-bxvA5m_w&zIr`+EphWbwntZa z^V)q5cX}TK+7BP%U3saQ*RSNuyqNGi9YUD%{W3g8uv~dl@9!?KV{ooK{48cxD}1-=1(bd0y<^-F9MdV%rp z(j)VAL_;@ExiWbsoLjDnmQ$ZtzI=Q8N8tOc(IO#^_P+!^zt8bI{|J2SQpDy_wbbg% z;#6en=<#%kDRel}d93x+ssWskvjgOESc5c0@9Z}UWwBt2-hnv7WwE|e$>Xk|Q;Ehx z@Imbdn^A*bUr?S^p~NKK?DGBe4Norj5GmPxCwcz>PTB_Al7cL@iy0<_K|u#+2d zatc2_u=hvFq;L~^Z;0cPjXX*2nQ?FJe0OvC-bL~%*}y-T$0cB<)%YxP;k@)oz2$KU zo`Y)0fLQQk?}|Cb2Pu{8*&sot33PQL40YI(mYdkjg-DHE1`L*XWH zdU=k0&^88}DSq+M@+-aNW=dQYXV5f)_|7&$47L;ozL9-PC1-(0ew~7YT8Q*7Ec_#K zgqSxg2Mz06;-e$3!HLR=?Vpz4T=ko7@uo{Jx`FZKJS9`>0Frdr3o}W8q6o^_WVCo` zHxiln!9ex%&O*kN8=w99(yJKLL5z%TXD{v2sbQk!1AgPHiWfysyYw$2W6M<8LJ~ZG zf%=xYRUxQ2@2)<`_!ekfk(6$tZ$s!e0%fv&O#pKwO8o~liXf+I6&-E86Ud1?LoD+8 z+b>BN$re>sx3ORP6sk5Cpx4dK0nguH|rWql%2dEcWwgmstG zH^Y+(mF+$7!0QTIKjrPQ~n8h+-DY2ZG#ovk05g<`xsox0zF;(Nt)Z*C6h9K{7Sqi)by{A;DNWz8L^KgQ7 zv+{HqeWl=4YH`r&14}(n>jP-)P-EY6bOm`AA41G#-^aEGIfIfDa@o~eW}Y9nlAl3kIp5v@?UF4YDZmP(zn9>*_WhpJvYv&0x?A0%`r4}u6O=7X za9Sj3+N<1zD9JBYq|Tn8Y>q*Z4aM`SVWM1!hGeaiXF)~0BWW4qd`#Z!6RrLMa@{Pe zO#+C`ri@%nW4AzGsGHKw7z;sU1a{LPcJdoowEM_3NfbB< zw#XFlPIsTkz$fdXBIFe8*VGiV*h%(xJKPoI_bG$)^*ArWI7WHzAceeCV{=yAp+?~EwZ$#8(sqd;qI>oqQ=W5G= z-)31mr^WYK69;ETOg%rr5@ETGOU#3PloEc=7pKJEfSik+M=2x#?$T7s_%-G3|o{D0%^<X*gs#A07=L{CrMOM{g|@Y zMoI;wP*h}U=<&3PDYQ7$Vd9ob*#U>|(5Z32HBhrAu(RH05#f(VolHZnnnRn%RUyTwqQM5;^6Iu1DQXRq@5~k=&E?lyAm;Lw zoO3p3TK0pO^{I$!p?Kkg?2ti?^(A3`aic8=S$BE%PLdTUo0S{JDQvft z?Xsy`3~kY$)T+M^@_&SD+9A3UmWuDLN8pw{-wHD;YxdGX+={Jrca!A31fQd|fwqr; zs?$f6hrle?GeRwT3x$}YvK6DL!TH{c+5!cRA+Z^GoDyWOhw=@OL|kGz za29;j7AtAR*gydSH-)Y42GJI5;LGv`Qz%GyF)pRg%8{L8%2H;c_vUpaHshlEu1VlC zTr9Mek|`JxS0~iC9Xgh-N;Pm)2k~Ae znPE$UmR_#&b%#^ZdV_~!eR-YCp_$lFdOO_H5?Oxumzg@4^KljgdLnFZ6-0!KDUNxR ze8ddDI04q7viN;K`iYHiTAk>#@nITWOacbQxhm`vePGz*UIE6@uJr(T-f@x#SxZJp z|1)B#gt1=Yw;LH3o=$1IBp#JlqlbeY^RVNg)nY&GvR8IUVUDbRlgN`XCt0*l?`IVM3 z_V@MN`)On^V^Q#5!zPBO_80{JB&lc`iZ(>4JLv>IK^~-hhJGuHE?YO3r1<$O{n?p7 z6T?Tr>^%nj)U{9V_OjH{(mIp#`R|*_&P; zyFTn7n!9_Hl?s36{3LtF=7fv)kz^yzjxFYBsQkYfacUwi|Lusg8Tr?U(+o#u1f&YbI7w-Q(iN=N?%rKj! zDGzfR&OduHRc1454+->NMun^dcXipRb`O7IO9wh>9loJ-=b7FH(SQ4qHT`{+Wn%G- zq;%aEkB076r0@b|s9YzQrXmp8>q9*ScokdLqd)(vYrd)|-l97GUu6F$_o)-3Vk_mLd+nbr{TQ}ImQ zcK;T9);lL^OlN9u6~`Z~+t$PSUZYy2TQP`hnGm(-j@26HoOJbTg=@isTlJcbTfr}H z1P9j^_J=yPO{YACv!{(?_$drqVW?<>m!C6doqYBk%7xqp*H8V=uF{$O3X1&m+Fo~m zJ)6l-plujwDL@AZ8Tb4}4OfwOjg~iGSq}$L&FX4nVjMrfWG6IAmqZF{PYK8Q)5#{3 zo2W%x%vrSOnH@{_0)ls04L@LbS#O;8{EWOh z-y>wU>wkOyg`DYLJh{zVEp_`ZslA`T7jNbvM}J|e3BC0dv>@JR`Tp==*4&q9Z+`E(`);Xlb_E*X zYr^nhwz)cZbmJiDr26iNm&=kAWm6x79I{D><4m@IP-|_~{^nml$$j?LAG|S9IBQg2 z=j)3TGrIm%>4OyVi49Z|F^WygSMdE$q#=OzBRQhqgaIicX%ub*R18Jbw*L{QeE}=z zoG``XUI4`nSnvC(+tz5lYOEpSNskah4H@fa^)L69%!h*q?Nm4+z1GNN+G!|ssk~P% zenBxC%+QeZIkpVy;yHy7P7QKS^zp38FZ&v0EAuuPdtU0jcqII6J0(g9w8qLwS=?ui zCT%wAj^5aoN+ye(W(_5t+eJrXJ31$a*HvAeZwd>eKWSXGPcvi1fM0&=&?x;RpGrRt zoNWW`tgo^lvD^OI$p5aRF1%1>Q(yS;)U{*;N^NjoF|x`U<|W9rB$et?24|K;jYE<# z{xSj<@_bl-4Fey?5A)}B65|WSFMaRi0#(VlflV+7hzrHn3kCs0P*H>m!KV7ntJBZl zrdJO@=3o5F{O*J=&pZw_5$QX;ct0pzo#ilz(@h`bFhdK*L!CdGWE>;4Q3md^&kMII zEm6(<1{nl1Q!B=Yi1?6UIb3W#<sM@jNF-c}XGewXNQj z^*>tiaSIxRxmB8RfX`%N-y#&RE-3n-f;&uT9oUOto*9SZQYh;{!k-mh^Wd3;K1$L` zCGtLAz!X%oL|1bbRwo3sMzBpWU^pwm(!(ZUpc6DX)v1LgZto;wj*boIQTC=stmEMR z)lJ=!8(|EN=EeU$i+UMbJQI;$d@8r&qE}fhZIOA2J4?=19F)F8Su-6MR~*J6WtAHt>t(I?un_{apy#w7__Mg)wq z5zRgSxUy2bVb3S}`5HnHVRVDv=uK6{LT&{E-w_9#O-h2ahU|Grt{LNCHSN@{zy@*r zmF0&*Hh1k9Lm3GU?XX9qjSu>y4w8wWn4rsnCm13KO;(ufIOseuCw{WtE@H51_R9AJ zW#V4XNS}pZ*-&p{0yL$8;G&pJM8^A+B7Ai*V1G#(etV37&yjoRn z;pW-svG?taY3J(JrH@jynr-A=nhXox!=l{^g9Ok0sKMU4)dQF#hv9cI6#7xYUw?XW zSYNrY=eoqqO|Tfa(k9|pcQ$mkeHb1EUn=n2xY+pavxY*-g4ev+@`+ZZEpXAC^kcIs ztz;~J!6EXFCcPFOJ=ooi;?MXuch{ga6r3@&wMx2;#|8*w?%L2wKft0ne3=dehfKei zfJ3I*f{7B6D{8){gkkH2-_~$De;!J#ou)!_J_|pXp|3A|^cf9+>3iug4@r|I`+ENtj6T=IQNIEGe&t zw%2;+=ZF0u!c>A+I^}{*r0J&@%6O>zgUe@Hr2WZ}YXV+7{XpuJANVnzT=J`4V?CFEV&moN2Jli0sMb3eFx4ZJZTI(a7kEI6L} z*r2hqHHVwPw>=c5R7BM+mJr?vakbH;kc}OgOG*mFxbRgpxzp)zg&IbK0+C~Me;6Y# zY)mtGrYx6K5V&oDfD+mCr~d&`qe$I2=%W>0nv%^VZr|0O6Z&oQYPPUiz3q$x3#9ea z7w&z=!fzP1OLbNLM#5fk4uD@2L4diLUkwM$n)^XjfmH%r`ev(S$P?%j7Mv3bz9NAb zGryV(_t8Z2Hy}>HUEtlEi60qty)d_ek9&fK0>Ck9&+_ci#cXdQ*azU`wmwdNl9^KM z(Q!r%`|`Gd7U&n+fc!E7B`F>Hc7ZE+=eEsKV|q&te%khq4%saiEy{Iw zTw@UyG*L7J7QNe$5#x2jZ0HMNX9VAYCZrJuy|i0yIwbg9VS+WE6gNIahL#2~(DJhL z>}n%U@hV#iJt8bpm%N?kHa7FF1+ z-zaMMv0PHp`H1V%F^AvEzl%sj~h|X8iO4#W8IxrKg*J%Mf9}AwB~OC z(fV>d4C!&kT4w%oNYSE;;)g|WX7ZZ|s3<>Sdt)ex@Bv7O)Lh0NDefk3LKNLB#=8Z= z_p;xVp|iUgNfs}Dec(E|uCfH;z&A|VILT_FX3nNfGRZDil zg0vdA7y*CwB?tehQj0wx5|29N=?0)5qON4qK z=#66mtW__jwF&O(d4o@TWG){&B$%gMLxcbsTCB-oJ>o$Cg5oNmHgmPz&|ufm_WUHs zpruYk0+5rPK#%~Wo|m2%8>zeL$RB{EbvCq&xR(=_mg<W_xT(JJsSPz+yj`zBq_Wl>&Anja8H z1QRO?v_Bze4u;>k>2fKtT6Qh^zDw_^IW!rsPfu?7uIh#I^6>>@d{|*bHFQP#C))&W z!UmYO?-X)E6y~PB_Lt-jN$19SPvd07oc?I<7n(lL9eg6^(W#y=I*_IVHW5iCp^!R5 z5?H@oI+}r241WnS+7suX)Xoj|u%7^pPj!y1d_2FjpT%v9;Qy+8 z1pOqVSm;8D<%A42{foDMeC+tgMf4EG1-pp&Ju~m$1g1zzkCpsL8ESa+7l`|XS44Ji z`aAn)_qINk<>L_|Hys_%zu9hCr`kujoR!9|eHjl?mEa2eJ=q_8MDcoQZ~4bL9D6N8 z(R!Fu$PN<-x#~o*X|B2zX0uL)T3P^L8&Ss%5)-CK5H@YCJwEE+PZg@qeM6toRoQ~q z`z31=9CBmnru|87@Ydq5K&&Oq;Lwjg3GU+tGRIvk;P>!zj<)`!H8ny@6q>d|gTn@f z9euTpZ~J;VQy-3D?-kGTux7#5VeBsuO3pyj+{xVbGtmFMx4P!Z=q<1{9-EB%4a0T; zP~=~;FUZikugM}4@vAkbSa(Ny^6V2aNiA0f-;{36p4_CQZ7{c>)pnCuW;Vyjue_Ma zbhn9Nudts6{jD++<+h36vmQQh*bHZt+nC2-1mlTg{?E=KCD=K1{@XcxO=toIO`QM~ zp5yI01$)*TN$>u_^LhWl^MzvGx{G^MH?xll?;18paxE_y4~6cC6M*jFIe^Z!t|$GI zl}Y`jZzqmlCj3C5Yk>TVVJ_@u8JgnlmB|(0{!sfKpV*mhyF+aP(+E{^h}}DKh9*WDbNj7Ot zzkCz+*p)stICi3_P`Mvs@fJ>1kP~%jv;xfy*ta%e#O71oWW-(=gwvRIp<3E_vk0I0 zCo4cWH+c9C;d@D$GxI z0rbNs&&TeMu*z{wfRX zhiP|0l{+tDvOu+D=V$@G#bUzHmhUWaPsbqC^87CXlBA!ivXNJlbpR(6xqj#a|G0)3 z;>4VxETwdxBCQc|IYZqzL%n1X*)tQNXc6;h$K}-GbJeh`WTT+qq)j-mIzIflnbKA>eTsi+%%4_al6e=^KK+bz$L5ERS*h*YH7nQy!q7FVS#R)&P2euG(} zfo*cU;NCupjgMa9iyc9(n2^INwNJ13G^!%{^*U9FPTbzm9*2dyFl)Y|DXiS1&zoSW z^jO4R?Urb>lk8b(?aol`ZS=vRlV@D-RE}w#;JkW<;Lh-C@B5G4GcAtoN1bZVG5_1< zEZX{Vr-U;hQy%|I}s;|DV)mQU2%JtdURu&ug=&zM}lc z+AJ8zA4CYWdVqCzb?g8(I#R~&N(jNaXE#r+Bii@K=E>Xf842>FaO6^nH zQk{_(=t`Dkw=0#|>NsJ^KB_&d*&y1J$J3(sVKOMOeGk1b%zzTiaNL?vWXxcjclB$u z98CHQqE7)O&s0D9xF4*aJD%Yw**@fZ`wH1kAhR!J;JLZXAPcGLJ^+6EyjYm7MaQ3K z4Dj}wzQ58`ZVHtl`LYy^uROPrAJ0w@qM~U@0q#Ts;{TGnR^6p1Fv=f*!%|c=shdh! zPLmjkjukqM!Om^b$XG{!cBFhgDh$g2UKQrYkx>8LB4Z_y75YU6xg1Ob=L?8y<1v9( zwoZ7jU zmJL+k%N@ZG{APT8?{s^vvUKmNkr(0-rr?Prp>#ei=RlI0>{8J^L9ZtrF5{!Eyt2+t ztim$miI%sRwh4i(nX5bo?ey=G$bOjJbNy47I+I5KFISMFEDT^g*Z}RXAhNi?0&K~$ zOwABB&GuOe3iCx9DYlw$HdZ2d0ohKF2!-I4fP8&^T^?cZCgIdzku$T0xEzPuP;KJ?tM|3Qo8gy}MyB3t^Tw!@?&0jkK?ghD!ksW@3{&ini1>%@0T zBuTvJ2lmSkStedhy(Bua0Lck-d%3<`VVJ*EsVGb2TdMSXneXTk445+%7=q4mA>vSo zKPWd7Rk`?}EhK~ud5l2Yr5guBZZGv+zq^c^&KiEb&5YyGBI_r%{-Aspr)b0F9RnX# zf0&5-mmZZ@n|aV5<7R+4@ix~=S!K$>oRHoEv*aIK{m{p#J>FqZ<23fMBASqo?eOF; z$(7=NmRxfj`8!0|7z(Wba^UwiXW59Y1cMgW-e0?l;uz)A zn6b6R%7Wz4MY)4*yWIAMf^PlIl?d4{rNV3<*z)7CQ`GBxXTyZt(^Rl&>v@R8{#t;{xk+lw+#eEiY7VW*m?oV6)5CWoQg~ekyL7)@;EkR#p$!M@=?FZDniD=Y}V#6C3JbV?)tJxo|yrq;?^WjgG6}bnby3O^i~Vzo)Os z88LOd{9bbKWDW6;TCgg5UB<+q@26mGPuRMMlVd5HL<-@E!TXt zezSivVz5wfV$|TYdO(3C!Y0H=Hji%AHloo$dJZ6)F z>%w}%LMC}z5tz!UQ)v|7pX=}<{Qreq>J-|#r0u6_295~~*OyI@8A4+E1>j{(!r zu0Bs!8f|FBC*a288zcgF&0b=8H2j#0hKOfZWGRhDf&0d2c+z^06ZxIo%5!5lS5m48`qq*$Qfcc!Cz%T8Q zs1Lx!DYPtwoi;zeR`Le{k46U~D~z}9k4lZvje3z_?Nk>V#Si-4F*V@rL;TyqEnhH9 z1sMze^HdYZn0SLo{xdTMJNX+&3hx_MnK;B_E;kS`k4P1mIE;KLg7Z2hYnud?PCt`d zl_2z{tN&7Nz(Wk<&9%vycW!W_bW2gDN4QB(+83E(AO4CAjKc3vm@q>kD-1GBu_iNj zL_+vZ0_8W`_ZBybl8cv})VcUptWIxe$lqQJAkZV4^Yq#)K3-zv=_q4+`{*}x-Ft;D zxxelE-DPzC303T^_n8#p1qpp#g*6*!^K^i(q0)9{y~4$I)`sJs~R(f9m>(SA)^wEk-s}Kb1#1 z^xSaih;-S%pVD$)yC2(nuBXk$QE@=y_Y{9iR^I8F@wJJ@css~{Zf~(1GsJ6a&_1Vs z5boYM60?5fJg6ns*Cf)p_i$TTIKFPR{g8=r(qp%l+qHbZDVEYG|8EzyDc%aR8({B z1F-0D(HPcYLbh=W84(6mn-t-Z^XAGXFZm@6NQaFUQ?^5h$A~0P#UDJg0X1$M@KBG= z^m~fM-=Kl!pz)^VZnmbwj^ySfSGhWxU!k}rn^CAn6L2n4fj*+}jx!Pp z5W@Z9 zqMd19svT>dp_Kz}RjlN`@WisY2@CEeDi?13k9`Q#S`Kd~VO{6H|Du9MoLP9L$d!ln@ zY0G(h_P?R3cS{(FwZ2KDxq0$f3Ut4@p3HORN=3(J_F;W*WSa{^0+)qN1|&w)F{1A) zqSvSeUa?K~#528A35W`Bp?b3N7V@yB|8`DW$dWx@!(BD8CP99CP;%(n+w!E%dr-V4 zoo)WSU}*mOKWQTlj})sFptLvr39m)BiEC*E$us?_f@)`q19wKWkVX87EGx~WYf7tv zCNaHSj;mjJ_EYKR_R}c`ifxv=g3!A)TfYmbi@4+@CttqaWrw)_8&w@Yu=zh07p&PD zv}gZaTrlvbxBwaScX0u9{^Y;YMwb84MjSVgknz^jg>^+<-mYx!Cxh12FEEZAA0#sK z9*P|;m%O>Tmx$nQS-ylv0g>84;v2=bw00~i@;@808{Q`3JQgU7Q8K>x#MsF(ms6T6 zpqoS}y%Ebvu;&k?EEheu7yhfapalj;17rk{x09zXH|)D*XXfrOLWq-I60Bv(TqB_t zfsQxY0o8FcDgi&gFkf3n75ffg8eqBK#UzZziD7YkiY1vkvXO zT}RjpNwTPA{Uwe-PEP2}PiH9R0SLGw+?{Qo;t4THpQ#=-j!RE?7K2G0i; zM&lJ~2!h8? zi14E8sK&3KfbOcq65|(n1@D$T>q1V1KTD$5+|iwUwiU|5o3|C0OzCo9FQ|{ci(apD zNIOc&V2L@8z<`{TQ5~Bix_gR5N>ZKpu z{199Y{uGCl474_3X>EGOYHtig}#ZS5I_(H(IOf^ zpfdo`GUMZ4fzUE711HIZ-h_$S`Q_p6>+!Q8XVG}7K||7%~UODG}y zq%`f)WkM%I@P)Qdf>{leBCf=+rjtf60)r~{2dcgbA4g>@VlEe+hd3wmpY6M{(o{ov zm`~LFsAm{|DD9v`UPHO@DI+=aJW6S8%(3_MM4X0lw~Lur-y|J7L$|dt-_b_qYGNkK zD#}%9{>8}Q;UzHtXVy?v)Vyn6%<4UQyX+-1sXNA|f#@mfAJmZZU#MZ7e0cD`P{SdW z&N5hE=nrI z7@LHji9jg8Aj8KnmyE~QNyNaDqzFnwFf~;)C4W)mBqxfMo@ZnwjEN|Tk~Uw7mL?RO z%8ils1y$D)#o+SBj*mnl|MhH`pN=Fk!=(5a-y~HrceF9jo){t#|1)g}#;V`{v{J>y z1Al57n0#`~_;tVPNyKDf$k_165?Bi2d0oa-mRcxw10nyg-Y^!Ddq~8uSZtB_$YG|K zOjf+qb>iTY&Om<+>0L+m0@*sdT>szFngi>zpQHwQ8}yqNKWR&z+Lsfg|9Ap5Jd{jC zQcSErXp=qv^qa~O-mLg&?-DYFJ)9g6R?Ul;p=}#RbfznC(IGqjJ#Puy%;coJ5%p!bFtR0ZOi# zRn`%=QSS}GTLdv`)QN{jy+0}cw3Sk14!hT`Q{NYw@m{oVRJ4!vD%-J3astufgocYj zx>=~)GBn4qLHyKxBI?p!xmsr{CC^&wQNyFeIuuEhAt3D3eE|_tlL0~{Qicf{GOuQc;bwgcc<)z8#JhLJ1;+7Aqs3fxeUvUI|?k3uvz_inSMn>B5r-vx(4y z5kLVU0}%^BsD>T;=#9#2+U^ANK1B;5cG@^>H z4KX-o6KBHZ3PKov`}$qFGujozNO3)Skof|ihaqalCt8>T;NGlq8H2)a!myqng}@)O zXGX>Er0(2q4aoNq%tqopW*?e^%w!?z|%?0tuYOtGg6D>RFZVrX2qCBM_+0p1vWt${YXQx2#eXQNPRbS>is^pBV$i} zfW`aa`X3}Qfghrs@#TW#qUU6x6iu_F4g7O(Y5e?*D=mKNq;%UA&nPu`{IDU8Cv6)M zQC5|5P0Nf{@<_+r-M#Q5+@e&_!Q}A95WwEz?5s~uOye&#{gTG8O!sOSSIgDmhDdNnXrjzi$u9K4IHCtVkgSA#z%f(hn=Cr(fG-wx z(-Rgo!6XM3HHKnZ$h)Kf3`mL^L<-C_)_1HJ#@qF*38W;x@fOsIpSRv6$s>i(C>97} zQFqd|5oNLBwM{7~r)8}yX{n?|8xEas4x}>#ze{2@!3@~`n!_rGu9yash(PIlN9lZ1 zzJvgqn8tuVV|r7Fp=9OHSs=A9MZvGg4zr-WsDg<{2cDKIEj|#Kkd!#km`&_K1IrA# zwSzL^!I04ixOJk@vVNQSOc+UJA!4-DGj4rskvQowa<>A{xYCrKK^PdP)M6 zATvu$=Poepyzif!zAM{}+9G^SjZ&I$XK-(dDGdbU+4!RtTMy%OopqQr``JR5{+weh z-fLYgwn{GIJ((=CnJx23HNJZZ966Vatizst7Sa>&bs@jmc$Pa5NQu??d!=QTBt8OFGatwaon_2-Kr!B0zbuk=8#~>QMQF$ zgLIz+0NeU{05EF-@F*E5_^W@-iEuET_8I}w(vF=dWu}x zEkVb^@M4DYViq=M&Ym4|-ah}{Koc+wNAH04?7o^CjNzf7L0jrpau_jsh$|>f*Q$I| zA`Zd#u5?skl=tAZrp>ma(rZ9tiQxeO_cXU%vsxPKSNpKYEgSCqU(Q@Wd}Ort@gYM8jNw@N2WOm1F=%;_NG@ zy~RXa5O`l_*_A8|c81N|&bq(Bg}#;h?EDEt03 z;o~y}=ANS;W!;_0yYpe`H4K#epNt|a7J!h?k}FEl9Nv`tOus35y@V3W+Tc@R^b^lK zFEU$~1TO#sGR)o`)&O1+KG4StV5^Tk^Kqi8lN|SUBKB{N>fbbU8rWwA z3I&c^=p%8m9g9ypTUXu&n8hzQt(5cibXdb>8Ci7Qy;@c#oQ#E^c^EA-K61w=ohQ=n z>2%t1MJtQPedV09Bb}?^&q~*n4>9EW;n6qVi(|_r|Lb3_S^hEs^_ zwm3}2u6W70DPaxI1RIOGi2r*JGDk>x%69a)V1xzO9tmOC7UFK9H40(0zPv)z$GB^@ z8-IVa9Ov4JvA;5kToVD$NJ}^S9*<Mw$()nZ ztVPkOQ`fNvyq}NpI&;a3jnWr6O&zZD>O;lXD`4Ckk;ZzC!G+(orBSf}gj{%rje+-G z?My2(^XrrE+6Hib-_HiWbcy8RXC}qYu1v$ilk@$&AV6Q^At~kCYCzUv6F@&?-;Cs3uWD$9xS!&VPFn&&F_=v{C z@JfXM5)6#I$*`T}&5Mr+xZX&+-Y{3yNKY0?&IX254^IR(fsI#D|JjguJ>tO1td*p~*&jb^QU!j3oEy-QoQtsXJn0HcTaG4cemi~7A&~i!rgu0 z?hqV;yL*7(?(S#h>;LcFyLX>6&dt853q}oO0q?4}=B)WJ4TtUR1#QNzyLkPuFuNti zEz?pGAD*Uj^Je5iDLT^oX3%dBGmIFA6EcF>O-bX*?3ILNzrYH%&o+B-HR2kVGg#Ti)P&mRyI$O8}Rq zRc1-UCP|otK$BdhL03))CJ7!6fni3DF%T7V&o;Gol1#&ss3gKK3-3DgA<3CIT7n3R zuR`M!f}Eu$pa-;EzAd%)j4?jiDL>?EqHE(^G)2mzd;SSUi7B@oG75Cg(3Tpn@i^GP z)3793HchlmZlR?WJ+f=#brg5bK~US+s2g3&Nmor+@XNvf+BFfr8Ss4PYh`_9x0lsl z;ow~3e*07LDnfGVo>U*&s(b2^P9pZib|-I=qhPggw7I#9ZcV=dNpmHqadCxZO(lxn zW#e(=W4^(6RC$ZXQu*GAZ%O=Cb@2OWS>uJ%0gNs;63Cs&4A`8FM&4?xwNdjnx4?cF49EuNzek;o z1+<8ZrvrlG9Ur?Ry{!K9`(rjZQkxHIt*joYm}6u8L7^4u9#V$+5bR|9aX@;@$+Yu6 zwAHz_0iDZJwfP?QL$=DL#Y7-wX{l&@2m>MzAf#!ZU(H}Iv)J(K`ug~CjCE9{m{xWd zQHE4R#A#7GxM+7420@LcR7olSL_J>z8^b)?L3hRpB7#F!3Rflq+C)xUL$pC&FR$<$ zlV6sBaX*s0A_6?(HW)#qwQ;~9QxYEG{wgFWl<9w1%U7X#6S9LTR{z|R`|;)vJ8tx&KNeos+?zBW<~ z+(`>Ww8Cubs7O-@GG3MSq+nhBL}k?RW@IsCjkMm`bNRb8ma{;wm?Qr4g<4rwj9pjd zh^)-X@cf7@+b)JhcAFUb0iWyfY?ejir5cr5V7eT^+50!`m@rN&#H)Q+DPw*qvZiM} z6fZ53KX6f1cIvR}81cw4DkCtIw1%RY;P}25M*+yTuv{jqyrCsZ$%qyt=|*!Gd*i)enROg=L6 z!l$srx@CQj?%t9+qDXR>TpZ6QcW$0FxE&$*y0D}!q1sSOF!krUy?z?$YhyUPE-MZU z=rVZbo(b3w5jhhGn5f24K=rm_m1rMVq zoGQEJHo&C7XcajcFD9IUoYKoEAiumXI;`BOgD}5b6iz)vX~8M9+=-7`E!hk~U43x` zecs~oKwAqbu+tu`bGo@3nc_oo9#0-XZHZ0eFORG_Vk5#@7y z;xa*Dfd_MC+jpnOIEij6DyTVu3vJKN$slCz>mj4!@&YWxqG6nSv{+RugB7!zp1e33l)gcX)wjVi_XEmYcg& zP)$fbqBfxvlsxeU<%RGQ5bV-&e%YFfiztm5(joA9v(iJDi#m5I_yyY!d(K3A;lpt5 zr10RU((g`a7F7LiQ69AAj9;DaUW)BnZ1_D}d=x@Yei0{pqXDbRd9tagKKCMq0(bpB z#ICTgiFwDU`5{_xxo#4`rIA}UJ)dE6m;Jps#bc}U{a%0h>(ab|d=5oNsfj{P|-{h3Wufy zPTFN4WYcBUc8n;=lPx-kP{Q|QX7*%`{+8_Q6;m&X@_TH5UTUQCO8&Uhc?9sq1JiH~{u-D4^QE35FiSP}(wj5attQofA z_?HWs9aB6;4y%5wYVEOmXG)+tJXfk^GK7zUUgbelGk-a>PDHC0R4 zIDoy08{7(dR-4Oe;S*_<>N*|8|e-4|VW) z^+=_ql|Ja-uDj~6x2|diKL%STb$c#IYyF*q@Le zb$JZ=o2aLYbWg^-4TJ^sr1q!D3^IhFeSr=aT42U929-Ot)gD$sy=j|F;-NJP22uyM zJN@P2-R0uMLH{2D_Y==i)EXX~(BllRNCo*qC0>*S(^Ispt5uPub=`!horhE$D-=WQd&uj;bn2HfysYiuY0W8fb?nVr|5RHmAbI{zIG;7 ztRlC_(Y|iJ*2OFVj?I~3v^fR}qb4zdb4Qdc^aav;G$n&|dRmIaZV@EKee5h$8Ke#r|^mDF8@EppoccozdmA?Lg z5&RaO(Gv}yVfoSziKgXwK+n%d@iu!tKYsT!gZ#~yXGxwUdilyZ%kWxhIFeDgZjQLd zXAX?os|pXt1_g)UrP`c1e51B6t)@ScWsGPY3iIhxg^$(kWogSA38*I29K@_9%g+X1 zv@6RtSASJnXGoOK+j6N><}XlFxJ0;Cs)`yU5{uNrE!^X>^UK%-E(L4!u?#2~#!o*( z$ufQ7&O+A-ch$8seGsErWLjjCc452-oE9szJ*hZs_|^~09Cn`PWl*F(&Muw$U8Ffara9{Sf>C6sPMtqydJf?(|9 z=+fc=OMM55@>3jVNi`km`tyQ^xu&;~vXck7*;CUXov82DbD{Qh&XGunt@^Ud+n z^`C59sv}SQNYRp=`N5plyuK98d0Vg@*|_|;x@w=RRlMEU<4igSZ{%?%02}4_0}d*A zZ*CxVE_(@9@fw7GsI4nfu)V!>(r4D0b?=OIU37Q-I4iIp;$weyOO0(__wvHpJUqO; z?rf|2Viw3V;XFrhuSR_DGK)IC834Gf*RD!gxtpHG9(=*mRB(-!dCoeC-;t2hUpc() zfu4yQyyhkqcax@f6J5*;WqBc+)BiF-2%6lzLfR{(=pwx>_$^s=8*SrzVcP~)iCDI> zL<@xg_^y96TK&)5bK27uS~&o{8awQ#@<}w@NXNjwlniaGBpN4ZWcUHAmUHe$D6}$lP|N zdrjQDOM34Dha&I8ZW3=8@6L1Emk?2F;#g2?N@G-x#2+So8Aiay9)lBLzJ2?;S-h-o zwU;BG?`gR-sQGiyRnLC&QHGwSYnv$NU8{x@NZ}{o5UkB%2Ju-vk#&z{`IsRp)J*Lx zbU;pZ6vnCl_f>McM&BXDZHpA^1Pserd0)C#k=UVnkQenhfo+|HsGhZnUKgOaNE9vJ z$5vHJY>B7s7Y&u1l!F>H>o{8RYSv8hOyajiTfRLGIbcQg~JLhwh7NwDVWo(b9KHdfhh@ zTmaZpxBXMi$kXrK^S7VP8*UH2#BaWKZyYo2sD1)O1)UoB>^R9ESi2uGyMDdJK6}sI zQo?lw*Tf_1sUII=GHre@x`H~HuLmzl3vk7Z>hD2Fj2fYW4#`VYRgevCb7w2r-TfVkO0raAbbLzgE?&RuQrx0j_$U|KIP(dAug)@wfrE!x|Jz+)(O(Dx`) zrsh1E+sJL6vwaird)U95yV`K&_{^zUHzC?Un*o7cLSw6hl}96_Tq&*mc(f&?><|2= zp$x~bu1w&=)2-VAwDhyS>0*nXJBfYRo``q6E?7B! zU{kP@a9TW!LMuFsV(3#*-qrBcIp%J`@aLFsmFxy5?z^)H#w{=uMLQ%q9w6SczShZujCv=AumZi_eR^wtyDzl!mc9X61`IqIIj>YJVB3)TffOomIe4u+9m{V`B_78sLuKL76jL= zk#X$iev?Zb>IMc+wzFwjTfsLLq-O<@M$B`owr7kyeZ|PSy>)-Gihjam3VDSWS8z)L z2&LV@h$g{BX;ZW^>l)rgm`d$LHD%DSc>OwrLjyw1oZ!Q$lR5LJy%_8ga=+ML)(8^! zuh(#VT<$-cUie&;eh`TyYkV#bc3wR_PhlR)F z^^m$k$hkn3rE$6jj%V{2G5Atp5-0haQ&ODYSUeL>DlW+>oT-n1#Kwv@BAV_6{MHshZL62nf zOI6AiH)#IpPr1fBLYR;&622$yM(@j z%cF!)p&7KM2T0RG=|mYd5E7@GMyZ5;OUaj3Gs)06oG#>nh-YGh7fwFGOGs)P+>ep= zwf*pZ(~_*MnY8YYd?SR?P~hVSUX{g|53!Nu ze&Dr&@b@P1nD;m~%bKV!kyu#moUqb;S)(}d0%zV0&%|V*!l8Wx6aZY9)-+Dzw1b== zwiLlcfKgpN!07jr$L-Dfnt?{A&+ehaNap>{!pce}s>8PyIrP3K=s(Bgp~O-2?K>!p ziujVd6U4LHR{czj!gcKUe}CgjSWK|+SOY(35t6)6R01N5%?@oIu*D%kHBLu9%TBvv z)J}7sq6i2(edR{-E5P>6(j?vvdN|A#pw2xIS|p6Q(4BGN4~15o;SM2j#yomKdNFZ$ zhJsZ7T&#qof4nrDr0x`e!oW+$4dO0KLuIP$n@!iVe?J*?f6O2`FqP?nhJ}bWa})1m z{uwPcP1jF2wE}_okN+1V7?qX!eAchbBe>DS?lUuh4Rk{ojM_hUlVaPif=ev@?S!oH z&D5V9$BN0Y=_pAs9Bq<6)G6%$+-$YCvkxL$S_^WOTpxVP5Igvh%q*!^W>4eA7+*?8 z`lacY*szS|d!Mf?{O5wzV*#pL$4@w+R;mrw#?@H}dr4}@(Z}kfH1(xbIx$9-(l3}v zrxlnE22d80RzPWml#D3Ta#b}>V$JB&X9ENo%6&N2QFzt+xO%KNVo#zmPcTz>)Sg5- zac(fRP^$Ia!!M5rx?owi$5kWHX%!#L34y_MQ6=1985(m|`6&K=P%zVeT|SMil?@8Q%^V9^N zJ6Y4yiroBL0|Bq-n{|wey^QsNER6k!3|ynCRV1s^^oBNj8a*Dl2k}t&6N}8&V=1e> z8j}kO`k^X?hW4L|zm$e`2eK0iLa8?VY+F-@HvN1&-Vi_f-j5c~IHURNYE=WTBswwd zpzWnasx*NHv}=KBLpV}}G?Yck7t0k)mdeX7jAgj4`rNrUx zCKf@G8eOKWjGLvD$PS*mox(LzycFER{F<66MFJ1R)~b0H#)4se>Q-o8;W~c0VL7VV z4SkcqD@jgy?YnHx{ILUa_fl;F)ytL1_yfD?gpNZ7vrt@ z#arXKH}|`$tH{=x?wjw$sJZRR#bf=&OHGa5OX(W3V)Xm^UV+`i2GIZ~4^O9ejlGTR zN}j^aZ?-W0g+%`BTgVqT60*ZejS91SK{l6=tFFOh2fcy>fdjwYpXiBh9Bq7;qHKkA zSvkWzJjKcF`4Vy=QUTH4@vQ}gib=htK^=cF^Lr(6>4{34HBPLZ2E4@ zXFbKhyBI6x%C%szC7X9d9IeAn1L@;ozk;{@_j2DK`hx8UHLCZ$Y^z;em#0rbg!=rr zkH22(6+ zqiS%wJ$xM&&&v_hi`?~E*6o^kICK7-x~)kI5^aW@G{jmQY)rGzEySe*0Jle}XPO!qR`~LQQNa99p)>s`uZv9#SS%z3Ip)-D+ zI$UtCbFkwbbtwHuA}|t9AUeeU;&GAZOA!}Kh8u3N?iSNtxgK9P8S@guet9bpK7kK zzU{evmML6Gj_2n!^c*0}$kF^heWbyc>8V7C4M{kz{Tva1YW~G*fCRQ7rNh_~_UCpw zvF6(uZIu@ZT#dUQ^Fn+ju1pVs5>Pc85!ev%fUTbK?sxVl693gv!tczmXpP_t@;hCh z58Ai02%Gi>uiK8=Aio0n$4$-S1luM)ftWmv^%X_y1#FG%d(hpi^?G|0>h4Gv+>Pum zt`5(KSG)W3Kpxea@Tl0AENP_@7LIyYazq{YXRxM%yj)zr+9Be3Sx^52h3m1WnT3}M z#k+&4`5PG6D&aK&66!#Bc{HbA@Jk+gK9V9hNwU7bPBMyj)ol^K&huP!OJ>z!#xgfqn z{Q&^K2P6N>=1~XPJoP(p1)FS`zAVL9a9|-zSAvgYMF}L#?la2Qy?&{*DGaQuKZ)NE zjDn#|oJWR?|LmN;jvZ~49DZ6ij}SgVQPsE|(!4mTR#Vk{KL{$rvWkUee0J}U1a%cn zhTn17$Qm1mgg*HoooNKkbvCQpdFB66H#;cLTKsJvZF@h%2Z<-iV1i;ZFVl}l-8{@f zR^x3x3-{L*3KuF!fo2m}u@}OdL9)C}*7-DD8ZA_y0W-~I@9a2z$bR%1RrlWMd)t(= zN5m=b3Oj%H;`ZCDJgBVw;lkOxcP*-PLd^yj2?sh`o8>UeORc+`=aOAdJpBQ(TeZUd zZKk)BwcI60auzv9cyn{~1iUzk?a=U(WZ_B;l47;3lUES^rP>sSE?By*5J>ZDrBM{M zJqOkY*i`BM@nm3U@wagugJ|Z!U~A~00z`!} z2WVo}!MGD%K0jZ2ZugHsF*2tT5xM%cvhYcWc_!_}qQWu|e-o&Ey{>yDt$npa{G#?j z8@P9Zru{Q#CAJ8jNvxe4NcmHImBpZBjG|~}=mGenNA?0Lqi~t8e;pVDt_C5%(7}uy!O$^@U2Da`jY;5( z!IHbTbSC31TxEv;(PHX14McBZr#e@i_@aO=DU0Y2 zFh)YR0z;RSL?FXF0nK3HdiP3VsJJIC=y2LVnBW!nGCaSFddX-yXlq#vd{iE%T|&>A z1_;nuDH%W0{74aq_|8;-7Rz=omH7XmXbS&TG^=VoJQomZCi5+Y77$9c5{g}-K|`d>5CU;#nSt;>2~-0rK_LPWZ12_T(8u$w|M}m{?891c?!nRt zqotvPP&MqqI_bqS%g1`QS3&T{0;83IqP;aEffm;yfrgRV+T2%@Ql^v0zrZK}69Wf8 zph1%$2x0ltM2KKJ(5JTMpr zf~8$LI76h-sQ(W3OW^IHATj>?Ht;XO6DyQF)StW=QIh6uh6YN~G7ie(%tMoFAOSlS znws;`zk@6O^A^bMJQ%q8$L%D2F-c3!0SI{l;cWWNCKdm5m+#I4l+bFd@fsL!fo5Zl2|zY zQ+M(h>L7d{eo)9L!y8ZX5X*Qonl?k@X*L%nk;p3`Gg25l4O)p;(v##^H8sdmI!A8h zlr5~VpVD*Yu;c3B0WVYlFO|V!iXrAyF`_#_e5K-?FS9002_P@l>Ep@+>;d*1^>?@T z?`|mgY?|*MwjP(rz3I}Ww5oL0F-vnve2+VK3`M}=0r^5sT($Y&hzy|&Qgq)RvvPSr zsyH)}G1)}3;{u|3DZ1A(4mg!9#U`OR1i#e>*s{wKA0Iw!fowzb=0t3E(Fc!_hz!=3 z)#HeanUm%0tb0~X7;N@@Ak|;TQ#q0HAhtwF8T0QFHXyw%5ARehO%k3i4V>L*{;otP zeY=EzL@{IF09;5EgP?HKN}!3XC|#)sBZrV+fFZXw>j%W+2;hiDaee{=fT1Bm0cIr$ zR|CNuDd4F<2XN3~e(wMr;OzreXEtz@4^lD@zu%*9PC#PhiGFYiV^0{_2Xd{OAqd|- z2n>eRCs8sN;M9pee)lwErDS$h=yXc^yMT>iW!fmZwNW9jYv zn{;a^DdTF;dNmO%!Iu3r1NfAVA8jceO44-nEKNo}AWqKl@&i?f%)j4Qh>V_GDysAP z3B!_#4fmhrzYlN9|}SlT-Q%(<9`Qr!<<@-8sYA?{sw1)aB=-k~5G?%5|0Q z;Ni24%?eBNYtYg%&NNPW@D(A~8rYMZ6o8%eo0zJ=`%vX?X=!fvJum5>WUAKAyu38m z`LzcVTars6E22;B`3CR?GpNF=9f4}4Xk-J?#QXqp0(a*_l(q+TZS@58SxP?li`G`e zw#yXHisT@^>z+g+a* z6FfOw2i8OSy(I*8_Sh${%dySlnKMruENwv$JH*{0Fv`z5(2}01!>EE1VJEcu7(YL% z#0>QSCx4S$$_C0_8gD!SD1U@B04K^CIzJxg_$jP;`QgrSp2}Q1>9>K{->J z^-&H{%ORE$nK$PPQ77pOs^IX}!P@)G!Un9{rTdS^j9ddEpH_ZC;|G%Y9&I15*|f0i z_LytSL_4J1Y_FOOry;`68Jas1)A+< z?`}6U*5*?;@0EwQrKM`0`LnbViI4N^nPxAC*lm2mZ2d0HmZl2yqe$4>UqaWWfQWu)GSl+Q(^~s|aCHzt9U1tQpR65F*fN`1={4yX_S9Nv1;~UWP)DdWG_k6q_K$hH(-~*m? z3ZEw?2!_24eb{FD_kOySKA3g`>ZLboUG1eGzO>BCnM^e+k}mfQ2>Ii|2q->Rpm5an z4i+GqYct4N)+IP2%!G?ePzwk)l8P=1NILXt{sG@bjn&PDWiohorejMt6Y9(S5-1k` zyeSB=KJG7(P5=fM}*7H)N}U_6fflpqZ1lIN2z)|NjQ z|d+Phi@)Ergu5`lc+kCW_Zg3FKt^ z@s6>EO)D$xWx)q`h+)Fbp&P}}20LF+j*|y_1P_dp&%Y6k<+k-VjFX?b1X%^E3-W(d zB0m)Wnpm}U5cpjgeP7&rR4@|6mBvRiOaYnBIrZI66}In;T_Ey1S<#ImrCj>Ur`8F0 z)kl#t141_z2Rl<<#Ppw^xT}u(*`3JJrlClwv)mJBJIXBoeg9%#UM14LH$?m3?E%1A z+OuwXK7Ta zn>R+Rt1*7*;-G8dmbNUSc4YZPF#zRG6~sP6 zC4mbC__O?h@4@t^W|+bhTfiH?hI+SfZ;{CHhbo+ul3h;si=a`+A(QFxShd_o3jCCr z9p%RD5ULO#T5meB!(NV)3FGYoHJkzd{9a@+@yF7BGK%=VeQT<~?ZGYeesBHgrG1Gw zqvd*h|Km5|*9_L6ByO|NW9o@^{J-p7dN%3`o|1CHurQCn))W#^sB=-9zOiLCfpXuJ`!|^hfiB?W)6D7i<6JE_HjYJ!4K+vw%U)SGo_{ z;g96uk3jjC(L2BRKx4_hZf|f(Z%e4Rlc87;81a;+4e-9sJ!d5z<^&>}!MAP;P}+rqZyb<~lkLGGQn+lGK=QU9m5e_sR1gzZS9g z+K5ybrE`d-C6(*fLY=4-!V1-e))h+wZL+>^c|bVxfvxFDy=98JO?TGJ((Pvynk9ck zq5A}|jEb2v6m)bx8+78xEukA}5rCOl2J6>ClAx_cLHdi1Y~|3-bm$w9j3{vY9Dpm~ zusbYfX&J6%GA@TV?hg@0&N+q+c7qY<>6e159(z*f8?n1+N&*dJohhuDSs56*Q0Nnw z@k-rPYQvd69(RUlM0N)UrR6|Z28{n)87!R(sy|?MjV)X}RND@wyu~oSbbUOpHpR9P z-pn6v>Itm=xHwbxE-08AdpK@xPJ%yXo04~4R`pq)lNMz1gC)bD)2UcsfhDv$MA-3( zzED*I-RsA3N&2^^V)fTkSvaL_lhyW_$k|?)Mp(x&n@A+Yjk*=Xp?VKeA0X!r<|G(V z$;JiU?EhghkKW+s8tKK>2at5Wd$I2%LPoNrxWdq@wtkKO1%QEKO`gc#!U*9R;ogWM zsaJ9^cY%U451ff=@?=T6Y4shq8}fagZ9DHIuAM8He0!Rn-`HqP@UsYO#~n{9J3qiM z`Rt6~VO%$sFBc*czK%aO%~Yb2)-ITGMXK_6Gjug^$K%}Cn{}Lp`FVemY!<@;9UdyN zoRg=_GZ96|idvnOmU4=(A_H5XBBRUw4mGjdNafBsk-lwdoz(a3YVvox=N$KiZ|BQm zdoBLO$(J9U+3&+++3KC-iOd@007Gq8?qYR6+(1DU89%YFar6EZ)a-G8Vr=ILR}PUP zXP?QjO!nfK(kIA`@IVi{kTP{b=wf`A&dI!-u_MTJncC~aX&>>b_E>eV^7~oQpi%MR z%S-Lup_^(dNd>5sz&gv5C4*WONZmDY0qh>g`*ePVhmtg#s^@SJ!tArXs2`B9W7)J# zHz^2~D9h=^zS=j66oHi-l=M&E0CnCsmT9`~!#AL)JZnsW5B3zcdf`d_9vf@;_}HH# znNA$uE0rHrkxbA-+Cg(y$vE)w#MuGS5oLZ+%zK_xZx;*E^o_g0eo(j({`qjY5v6dz z30LWJok}kk&#wX>tv0T8S65wcRaTZ3CF_{2rLw<9`LN=32kljN(2f>fpz@zY3L?&u zNBK~C-Fyf{Ku;&(>fqvGXBW!*ww0V@70MeD0H-M&k$SoM_xCMTArc!gsjWx z-Y?t{z|BK+lf{#B8W>{`4w4E2;Ea{6^Kh8ZddWg+R<16Mvqy7jsS~=?_D~TzzCpit zsOx8zql|CJw^+E@(zCWqRXYjOod>I_HP5P3O}`90N%g4*E&;EX8rwG>+Klwe-Zd$& z?Js0+-S%FAz8ZqnY&mq~;Tqw9+))FZi&&q58#i(G^@yc2wT|<`>!qd^h_^TEt{?JB zWt!KjH;>y#ckNRTk_UZ@XEW3<+p#81ifvD7#}Rjjv)2yb$e-poM{5Y>92Q$%INpce znD{uSGEy%L1Wgkiow3){GOsGx(6NhY9=ZR*>^z#qLYjG2H{rj^OaM^GDqtUTu#xKuuqCKdn(y&YPe|&_afl^?fbt)F}Xx;9(7fhp=Pj2-^5S zJejr?dROtl9B&C-A0Ct&Ic1Y2kb1C@vx|7dj}#0^`tQyty_@q(7u-D!IKbwTJ@^lPw+w2xk`5}&U&6q&|Z=r$QS8t5y*iN!q^4F^oOyFcF-jh)Ta zR7Ls;w134AoSeXPWkkYsBB|tp4V*TxMhPy0?w_>su`aC+0KL~}=ZcX*w+XhNL}D4f zs0A*@vM(gb9Y#LxLG=rKe`5*vA!W`dgIs!OUZ|hQU9eB{-@h@wU51|wuc}Z;0;%DdT%szo2JwUuuq%3T*7m}5VTBvOeL)h@{VG`8eD`=YV1 z*V)e!Uq3(JUeEq{u)kq__j%f@yQ!N(bz{yLVv={=hHRm!6Ws6%TuyaQHSvhR202Lg z;X!cm-SpDY|(R-z(+07o~;>>DB%fgmdZM z6_j6uiyJaQb4V|kO$%XKW~!--mE;QCc9v)MS@jlV3>IV!uwCG;lB;^a1~sEL`MPth z|GDyK<=0=bbIYunj4qjaUjH#$Gt{#6e7dvp)Y70CK4{S#q_%Ine4iUz(D5_wy2%gu ztVeSP;;13M|NQcOFMap51JtNoCKj@azWe)^NtN{}b6jl`yLpt2}}&!*c$VDciL ze_&baa{X5cXr?jYrcO!GyqH7<%7CEew^!$d0ZvFq+{ps&llo^W5YhGS6LWAhO|a-p z1`*xs!}tG6bb*CW0UvYSOgkc?X(rtkYY&+#n=jZ?8ANIN4&iL=EcKSKay36i=P+ks zv+V~O%3;-2n5TOyt7>o`4Hug=k(`)p#^^(T|@~%dC-TH(MuA@WnY| z>EQKobiX@)T032bb}iNiO)q@V%FLTIvo%MR;AqBhfwWc>)?|J+j1??xxdo%l-b=kH zsCdxKJ)X)fKM+RN4r=xh`sYEd-C)e>o3`he;IA~Pufa>~^0bx9pL9!IH~eC`OsEN* z<=+(T22KJIO5eRlxVHlIQ5D^(}T@g$2s+!4T}EnE!-*(IMfGsM!`_F%1r z(gKpi4G|#HfR=K~ctZJSczIxK;Fdr+OA#Fid776T=>J-2ShW{||6h#;a4sMd0W%aq zogLS&_z*F9!yfdL@C+KnM3VN;Y~Y3vJ!0WKP+AajG_twSa)w}kTMyCcG}zfB?N}`T z1uOiM3n&LcW&~xpp?PsqfXG-3O_cAP+~Y`^E{Xpq{h^OPjHxn#{r(b?Bd{NO#oy}3 zfA09+(g&ksL`@WtMmokd+%T4eRH`Av$^2ulsWYX`PUgbUy8tM#q8Z@a|tay!)39H~#;k!{Rw?pFJk| z%Qp=OA2X_f<1Yc5W$GR8hlcZ?)!TZ>k6@|by?iDaXZZnf9z{i~v(CKzg@{TWQ`F$x&Ua%R*P zL)h0V&P}Kf>3BX=t>)vg1WzlIsT5yHe=!L}pJrec)rT zDX0wHE({+g@Cj_vhEH1G1WbzO!>P*B`Cc6VQr#56zf^Y&2gR79_gfmwXzU%c;TvTg za|w{CT<|s(j9(v~e^4lv{5CB)o@i+EN%xVfZUpQLjJ7VxmlS~+qbIAYN{&nSgUU~r zJ^Qws7c<){UA|B;(qJ)=hJ5d0OJOl@_n%+~cLwMw2OAz*t%&~kRZMFV( z9zF%3dwga#24yM+&~~Ds!N|b+e}MrpganTNL_+inVaS2dE;tD79$w#oi8TxOFV}D1 zP8&3fxZrm6$=~=x9Zn0z5L;*y?o$97+T}a)mD+}w_zuy{uK4}97HCuznO}; z&)aCY+l%7l)}USls88|ljt>)=VZXYO82AhT3=^EH8jdQ$42a(Joeek(0YW25^my?X z#%#uq0*pA(TF%nUFLz7#7&;N(z4oH$afrbYDN0p+k%_CtrfMP#FqH!5Sa_7>C zqb=iGX8F6pqpfART1}FwwOR83#vFhZ{#T28Ur%|9gXZ|JFhv$<0-5AUJt#~eGqqPW-J#kD zyRSd>vqsCS+RJ8dFm|p%YAopUznHGfGj3}XAux81J`>&?EATrNU+h5|Oa5f?LZ23i zbT&cx6rSMqjo5L=`ChzQcfRfoi(GkCtaP^OotCPOG-a_YGD}~A3$_(m-#XoQxj$)U zTWOA+r96R`f#2NFMo2!NV>vO;SoWovhD9;t0u|Hc#KbYs@9tHUQ&q$Dgemt5|8fy% z+l&Z#K|4Oe!UW>KU^ln<>~>Z`9~}IYL2Xq!?0D{^OyDe~=(VvcbFV~?1_qL%5{Uwd zeDi5BwN$Xm_N@?ie7Kn!J7{L^MDe6u-_P@&qhvAnhpe){=RK&s1J;CyT^ayt??77< zmTQ0&gUQti%NaoyFLTIk4U7D{y#t@8Nn5Ycv>7?xiI=Ecor`P1N%i@B;b3NcbT5MOcIy;kTeF zk#`JDk;>fo?sWf=XGRvRUwuxI+Wb6|8Nj5p6ds#BfK8O_6_m&c0>R&u00u_+l(JaQ zMrf6-DN9H}?Dwcom#SM+w{OC9uT}=ciXkVf8m0*qS9&gKR>ddjSxgzbrQ zzWbvfYOFR7Rs95{w?3xf_Uk|aeR>KAY284I6q17ssD!k13KpZ|U&3X7X>Vbo*xwY7 zA_jb1znL_Up&DpD2Jtr=gBv9^20$lg^!^%(>%ahp22Sz`4y`Db=kWhTzV81Qk?&`+ z$^VXgMGXNuIMJmb7;DQlB}PsLkO;N}0bhS~&5*y5G6*@Sw4Y>Y!ztks^B~#_3hxx4 zD}(55edY|H;lX3Yvj3>7nHP`QiI6u86Lda^7lRGp5JyXa8fAak_(Ed;!~rYi|A2f; zW&da7%lLmH-{8ldAjbbqR)HU&@Fes>B0pY*BA;d7pH%w~Sw#~bUDVAZgUR{dD;xUF zf39ro3Nfw!TXH9o*kY3Gi?I235%TBKLgCLxCbujMHE`kZq^7 zmEaoHsj3rQg%0 z>tJKo-`At(&IO9WL#{ZEC%$K;aJQ!qz43$X^RHLCQRXN2y*~;thf0@TwD4*GqlG#K zUCwe>)_*qz+6A3RiQyI4+b;T}B7J-+CJ1;<{FBk>^9cl7NB@DX8>BFA`Gm*3kh&%#7JZMOV6k>=|aCB-nDiU|L8y=b%(w5ePe$*B@pnnKa{_z_jAb7 zBW#=Je}B7LI}$Fh0cy>)F&gF`CZ@>x|ts9Ba1xP7+>jh!aiGvn?A>P zT;DVtSH#SAv^!p$4oPJ^UA~yzs~Nwr(y(C zKJzI{n(}wf>N?n%W`Q2fJRWL-2SU|QE4eB+FdfesCv2h&V?{{$dZqp3^4QU^$U6bl`doU&%KD1?tdFszzuFPKi^*;Q> z{YYMPD@ifB`7EV!veO3TW?FC#2%R=g$vv$X6saTOB7k5TBHz-!B7&bhi5FYo|2q!A zwp$h$(v}02+HaeUGSyfhJZ9Haow4-L-T$Z7_W^Q!3CC5M<|hTdqcp;Ky2g1T7G1=T zY0CWK-y*3L2?zJ#NUJBV(n;r22MPb?q{Xi=I@uvJwNd5kwP{u|D?$owvi}chUlkNb zyJ!mp2o8foaCetLg1ZHGcbDMq?(RAeBv^2FclY4#?sg~n_ujSdsdJz13v?AlSJynO z>2E18(e$=rj)@zVhhbW}#!tHC$j(HC8sI*+u?EZfQL}7HE@fG50ZhVvC13bdl8lol zbMhuI(G$m~SH&G)_0v)oK$KZu&_WRAuVP9)J~$enHjmLI)kv~t=n!!wGUyLYSlNjo zZ#&Yj6&L;b*~bym63^I9B++TIk?Q}W17|1YzdLXs2xjnoLE3vQ!(Z(k3+v6Z{j7lj zmvX_!+w&l=D~6HBbDi7cdG~T;;~<3rYwp!3zuAYp+NUC#GUCXU&f)OEp#1451QRY1 zHBI@YR*b4DcEM=~A)HKX1n$vQFYC3Xi0-oOs8&ffjySi%Zqo-3C!*2Y!?IldffUIQ zKz+)t#O&FW#}5$zn$=XUuYwuJ?wJ_zsjjR_-)Q{&$j1W#n$_g*g(nQn&9m!k6uKH% zeBQ6Otsm@>ZQyM6T<_BLcC0*S>m6NwsA_)Xb08;r1s-=Aiu%ke?h z0MfRe>y_u0uFc(z%Ui~y;eow|`vukFkjjb%2fLkJXpz%?ysw;q^^sNu?%O3x zQ!V3@+3_qA@`;U+LVyZfKi!kT0k#&nx32iQfBfX~8tP&*aT${H(%PQYgLIwrMs=B> zsf0f3`VQNzy`@bcMy0}kqJo#`h_^*lpeXFZhxC&G$Nj;5z4sX7nF*XkOfb+*KSIM` z5g4rp4JrN>FX0_!kNNW?mF7`I#;{Co=p5hAe%yLKIvhH3^m9XBG!&1S!C>nDT z?mg{grD7P%PakdciZ}L9ZiqiA(08r9dF7c3dklYA_7Pe*i5c|1siNxtXntFhub-Cwj8N@RNlXNwml3jo91|co{b#)wlNG+uA}Mw%_b`x z0+oC({U|nhFO;m13l;T>%!bN7-2#O>3!OU(pzO_`EFFfvKs6m6nROS#ueU{3AgQG~ zSxdD1JNJ6uOUwX zMNCtu0cnV3%=%~EvyMuqJ{`8%We&{+NHgRK>9iDPA_;f}kakVXQ;b3F8wKvo+dp;9 z)GXMfqA1j7xEO0i6I>vnfrP#n&3zrSmoJXg!H)?q2fS^sLkG8)A*KBUPqXI-w+%6( zF7mgGMDp$mKu0?Jp?4tSA8j|!-{9Uv#v)bm5%tE0O%r%o|N2YxH3oL_O$#m4L4`fn z_nBB;GR={%hr64O^kksXY%vBvCJ8>T8xJzwz8$PRxZhmgC%oo)cs$+Jo96iNY_@H0 z-^UUeCzSbwpcc@T6FNuV8U`#OdBc_fVn~(a-0zV=**sy8bWpDhM1TovQ2BQoLb(!) zl>K;`Fwp}i=>ra_gzVK4vkHz+G`Bzt*&|m9D4MEh<49orP!Uv$#-VR6@t5G3XDf;FACB~P2Tv!>s$bGJM^teP)Ux}RTtlDr4k$Z~s}szZDL z`)?^1>-_&u%JmQOQ2@ETR*`Een-M(vmHxQAezA~w<^XY%*o=OnwkF|m8e9#FrhL?i z2xd!WtTLR^o*w2&VK2_ZXl5Kvr~JZ%eHg|d{qnJt_7oJ;Gb-85n#Cz!iux1anxj9N zYK@B2X&g?kn984Ga%E%A52%$x9E}tW0Y-{`{GC?U$eQTRNqUFJu0rZ~WeX=M8UATE zep;L6b{J|J26;7a7KTD8L8Q?0K87C(DhJv#eJs*KE^5Nbg1|er2NdwlFKt6U+qgWr zVCU=j`eg6H-Rod)f%L^C3q-n+hllwpUbAGS*Evel-dlyMh_oEdgF?O&r2KN2jf|Gxb+Nl0 zyiy3)3C}c(V(xENdsg(H7v|bCdI4g4~NLJD9E<1JsbgomhML3Q3 z%9V?xW>TMK_Kv2dd1mEEue7zm?YIm-a z|+y+r)aV zr@gOuCJa6;O-hbq5SSXc-~WTYAYn2A=nIU=rBYG4k>6u@Qp*LZsXJe;s-lOK4-9a+ z6!m}H5A4_@1J`Z;$++wn`t%O!kcDWCrPIsoJPu-^5-jKkz;aE%H$HXjq zzCHXWQ7AJ8N)!&=>0SMkD6D_0jGmVADGE*PEL$68)A5NRj^%EQy1Ib5VT)ReG86-> zJ1Wz9DKmO0cb09_YJwL;{RtHEO4|Napa|q`Z{zFnbgyog25PQtO)F9L59lh-SI&N& z^1+LRO-;&WzFL}nj8A|cH6@Mvz4_X<8N(W^%jz(BI&k>Cavj(D)nf6xP`s%l(GTIW zDa;xb>MO0+!iUd%@}-o-xUf&Gp12e1BbQ!|8j>!?WW!wO?In?kEaHt8Mp%yuax~0h zsq)`afF@y7w=EN^uqI&ZEq$L*lhf_p)rq@9@@NyoQ!k z%Bk}v{0ke8pTnQXp{3hDk;CPSKaoRg=Rc7{j%HBg(7lh9?hL%*Ch>|3B~YccV_0lf ztq=QWOyYskzW+hlmX}CU;k)jahb?HI%qiV3YKI(RQUM*qWQ34+ja$oSCj>l)t{1ko zZEw$#+VSPdV!)@$b(|#Z@;}4YfTfq8c@9lW|cBJ_FICG^`h8ki0 z?3)Qg!6q;WOR2T*bc+wGEywT(TWOiDAW=o%D0kfYPVl{dRwWabW|l?Z;nQuF{U{FK zop;Vxl~VL3cmBJ@2ajljug$=@XfwsiV`*mKv5VCH2y@041+n0KeH)ZQG@~N~TED&2 zL{7XFHw=6iM0O)tZ!}rZWa#B*>#)0fY6a9;yG*ZlT9cuBHTC5KZ|Wu04&h+?^*i|| z#+`{FY?f=0W~^sL>-4srZ+p#o8aqs@0t6IgIqaK~?=!=?18Wj0(VAH% zE*1Hi2d86*?30+%muH&&OFu|M;sQyk+9)y{Cnf8ZZgH~4<#Q7B54eXkOmMpE@dq3x z2@NEP2;h=fcCwBX`ujAeV-&rgI`U%6>$6aL|09lRX?2yMa1vORS~VD(7j9&JP+a6L z)WhsXXJQJvWeSoZf~wCD|D#(4Ap)T45#*Uz0Z<6ST^(a3!up2%ey2!sVA)__!CfIP zApbb*R65bDHegr!&|=4oh`;(7?Zbi^+n^Q461YA<^lmu4Aivp{kclJkIVO5uoae^6 zn{a&RdjfRB!1nI}BM|&hO!sxaA@hke9B?R>sk)?A1Nqt&WDS2T*In_!N5Rmas&9zo zh_uXYI96IKujtGgDc2R!6tOpGl4f|ZO>C6J34INbyF>;23`37>y+}Jm4{QcYT}Dsc zQtzBiIE6NX8}p^sg);(IG=eM~6zxis^(LVk)=fqeocmX8+ianmFZ+3L6jFuFT*ol5 zn6vX)a5km>*lT*0a=qoYUCy>DM5C2)R5Ksx$ZM~LHt-3kvo5gkOfrWx-X`1pRPb`L z@p19XFG{{w#t~)-DkoqqS+9=hRMuQxPiIqGrP{L1-fdUyPx@_iNB4a5{r5SUqOiZ?rew^PV3q#`DS;zwkdg=|L- zETcsWAY%({?t((+BU;1P37egJkxh|IvEO!;y6zZL6EWn}i2p{o(OrmF_4uzDIC;LI=6jk;T zYvjbmwofs+!#&k_X9Xd%yL*YdU)Bhjo=-Z7rAq|=H63enicY!tIL1@hrCQcT(==+Y zVeNHhC8nW+AoR^qetmpeds))ngJSmmzi6Txt=ILkOEw1uKh!%^DX(%-6ytHIX2dZ5 zBoM{3QLn`UIDkg=SXpl)GqxQ*MH7wf`bD*jSEMWXZLR;-xfvr0nsjM{1BM|wvlXN4%6c^U+p(p+`WObhLLR0Q5)aO>~3g<=X7hpc^=cFiD4*umP9j( zYFQu!@_6MS9)Xkr_OwmAQVQt!E;WYGs`i~Zu8Ad-!cm%tlsOTLR^5#`nrxWmGqCK# zTrG)q+$A8l8N0xZK{=`F&g*?*?OFG=<@i1(fU(~Dc2h|A-L?9@$19M=khX#)cvq^N zrM@h2v7E%PnITOeZU^<$JFaTw$Rwx(ax-U919oCntFCuX5{2qLiuzp!S|myR(K7Sc z-xMe4V)zXxC`K$Q=DPV^KKEsz{H5gEzT~@XgAajE%Y3$RrceJ4u;Ko(yL}E>mXAAT z1t*A2_la`CN-gb7R(6V%Y5g!32=c0*!TS7lW)Z!NiK9%%5F(Ge2l352!1)xe3{xBa zDKb+oS(AIxN^nnFQIMpe50P-FxIkWLCdAQ@d7Z~JQJ!H__+ipha+FviD}I1}tX34< zPB9hp2$9rju0U>wU#WVlSf*cQ9)EyKspWd)6MfXM8id}#<@j;+nWo&JLPA4jh%rbn z!U@G{K!k6;xB@l}>LCFa6DYRxT9slq}w(Z$<#j4>hT@07E!3W>V zsr#-V)go^@%p{4Zp)o~gJCxA zYs-k(%2^vvxUHk3`=ie4d~!8k)?Sl2lE=>v9^8i?>(BXxw+t=oH1>!{5w-P=#U6M? z*l7+O1Vp)PdUv9t7?3kD5Y6dwS`-|8YVAXQsA1F!#)vFk8s$Kd@=RHVz3VB*iA9Ub zT>jbbkcpzzuD{UzJ{!V$#I``env@V~Cnl#COw)-jq%7}cgH{c_-MzTsm-lq%oxMFl#D4ErQ#?o|2O_tO}wAtHb<$pG6`PsRk>K zIJ#LYaS!af6q83BJBd(}s2Xqy-qRpwd{|s9S+O_)Qi-0?$6fG6SxMu93?iXI zb=dxmZOG$|t!HtTS)=3SP{lX;tGs<98#mCFxIEAac1kHMDWK6!nBJWLl={Vx7BI4a z^S6%*H_B5=k5)wbaTN`wh=RhK6jt()K~wD6>9pNL&+#^Y{#0J|_q*5HSF20IRCl$5 z*??X`=OcX^u(-;mkB6TJs{@62yMGIPk)u1b%}5=Ae8$@&C>(K0&-1Jf*1H0Kk}$G9 z6L3R~N4TqrH_}*EM2_U=gH3gNxL`#-H?~);4R2drd-RZVi6-Q1;dK77v=iw#UVEx_ zmoRubD#XjuffW#J&vBi*1YN&~JN~scqLiF;Qre(-xg1T5FxUiDeTSr!ZX{2_cjjRzOH@j4;RIU?te6CEJE( zDd`a+n8iWIgtQvR)|Hhk;6=o6bPIBRL5BZRTJ?IjszVFQ0mt<0@V@2(kQ>fi=FTe~!AWPFI~36idilY|i{Z>>_~!2_WGU=8IU_ zvZ&&PDkH=z1)zC1H_OB)es+kGy3rHa?2?S5$j$2u?|eg;Ya}Jm7d{QY?R%6U;>92r z5Kl+(aSXg6;_bZt-FZDEFJS63^q3M*G`4ql`nEj=`{W&Fdp|i+?#z+Lp^(oGo{@j^ z>k(|+GeX4FHWCvhYGN7r z5n-D!aturs5q~_bU_9QZ_7Em|##nmuo>^*Id|5u_$+EJ&IC>mk8v9Nt>s$6ZZ(aI2 z8(y+Elq)s5oO#5-B>(EViXd{MXmxuyDc zp~;q@(zGorC~+n2!-;Hh4(ScD8lNdM7)j15Ot091s2p-H?JL)dN8RYRLGD@tctm9x zO|^J9@L$Lh73vVr>9NvS5>vbq_@_e15Ma+E5YGskVP@~=3u`m_EnVIVad)RLKZU$& z?>QO2IiEi$6C`LYz@AoWW?TM5A#t(O%`e>Gjwb{=!va6s=ZqGESk{%dfk>A}Byl@u zi*#&Qqmh7lFn_w@6}|%7($%5x&n!Fld38{?ZpS-VDVlI;nOAjcmtCzqxbNA%PxJ7Q z=YN40c%ja?q5F6}7=t=Wx-(E}wXJnKo*ed|9;U~Qzg3hhlg2MPwIhvLQa;{YtS&lL zp+2gVT@sAP47gn9un?sMTCjm+qG0Kk13ME;YCyQ8-F;wM0KH0SiBvf~`fbt2cAUOI z*h7Dtzj6>-=lw}A_vMf)B0X$QuIor&3o4CkNj#RW3r ziZHu>buY4i91!fgK;pyHQmU^mmCk*RI6@h~fUXqTye{p))J&g*rAL3SL2+$pAbTp3 z<0;Qna)z%<=|(BUfH)|+c)YPw6(FE{r!LOZv|Ihw2Vg32K=Qc#c^N}$V+03&I5t8uG$JHOC z;XEtx+o8Zqxh5S?nBcT01^ds{1KbQv~3f@OEUrM zP!|8i31tAn{FlPMUpBO#2-PaxL>Yfgmg@j^UB8x$%@Fb_fBTt~0RPU-J}aGnm}aFa z<6Zk&>cKNH?_)#VdLxSvijz8bT-9|9a-|pC+4%dr@`E^xXUhR3Nl)8S+{@ClZB<0! zb{sP2G>^8UTH4{J!Z*#!r~O^Id$!d^Y5I{2ik;Z1=kKI_oq)zgxRO=g#{Hhn0bC7d32u zslHYJZbGH2uF!bqHd(v|UMNDv#653?Q=3T1rVhSBnI21`i+}gKrY@76+wXcT1OiW2gl%r;$dxN)!ck6dk*F8ipbBu7lD)B!#MJevSV#2FB5v&uLf6*+vZOizTv( z^Ks7)5KG~h^3l0vvaV&@!;#qJaeV{(?LMKIOp_kDp$2!gi3>$S&>qwM%} zVI4{<*rQ0cfe~q~W9&>@&h!W=ZtDAb9qf^os7d|T+NvPGPjVi(jp0)tJ#GZrei)-W zC7aG=Mf61E4?hbOiW<{1BJAkyR=)ZJ9)st?d^4l3N<(e;;U+8l?jR_`C z@{iyu-PssJ5Kqwl`Bx!604uIMA(A^u{r*;`xchT7CxJDsWrMMI8W5SKuXzX^SIB%2 z9or~;cMx4&p4ydH84iV-zhE#{ylWqYI`M}riGm&qb?XWqt%8wc{)XH1-wj0wGPr+@ zDbj}lVNm;;CC~@O$>aTfh2!dlS zv^Ih}LJ7X1u(724(O_Hc8GVOaD~gsm=V21BS)pImx$i6dk6tbkX{85iFbc)qOh!r4q!3}Dwf^O=a4 zI^Hszg|j;?`S7Mn0`6Te%3=n**j7KeA`B4*hz4TbV-J?aQ1Jlv?6$9anW;PvQpdI8&_J9J^sIqg#EfDD z&J{YomwTNn-ls1yGMy2EzQ5L3n0xTN5!{vp$qlCn6DD&e9`l^C|Ke#Fapgdkd_6B39Ah#LACm{`-+pW?i_&FZn z4@9ui-xYy&GM#bqiQGL1heF~_6?hS}grj$Q8fZNdkekL!fV3_C##($g#9dGaA-plr zTg0Iu>Y$lSrt-xcNr{_|g?!6fMlUq@M|50+9-7uHc(c$yLz&o>#Fzp?S}kV6*7j@$ zV{VkV00A}<&@^Tw49gbKNEp<1L`31A+DOCR!B+~PX`y4r|R7dOa**^{`)be0EX~DLvPmu zWa-g-6jLPaslp3WA;!XwG^9sTWg#WOnrb3=3^D@3WTb#NB;nr8IOw>rq!9U}k#_>j z5t`S5Utd#N1RZ3j&eAgO`?ZIbPn>PbaCXI5@{sm60)vn8{h@JG2qkRh#I}(CnrgNB zYoyZT_J?WSXkrTl>*q|P&Rv~IoOHe)i~n4gt7yWYn451Y=q`CGD=9C4m`THAd5v`h z7?Zr(U^q%oGS>hNgD-*hkZ(}LE-1xBhc0l6=D;q$OAUOMUoSFGv-ueEI6p$0J*bOE zr~@ld;GW@OJs?A%i(*5jXQH^FwxMdPFJS{03{Cus)WRmc-lot6*CaK?Z-EZ*3l?=Yjve$<=s;{~M$Eqs3*Ssr>P(Z0sRfjBxEC zp}7pWHDEL#s^ht!eA+v;1`GciNr1k#7{U_EqYA63aYNP*rW&FKRh^Im- zC6X^o5$;NprmPYQAo(m++0qT_&ugRktawZ$hea6+`1V81RU7Yq%F%X%nal?vVHgcS zC5s+Q;D$K@^3`r6FiXWS^ zMHjk!v?qXHEV!j<)M*!BuZo(dD9qJcm zx{ai6!t2*Rm%4;BL5!27qmd3v@-r?u`zOU*^_6vJ#W=0eFSE6TEiC`sap7eWpB*Z? zjPP8MBrl)h&nED6`VkV3T1PDk#l7HWn+*+Wa3OmM(GOHSz3N2*i!kr>X00OFF5d_R< zc4@;R3$UWp&KK{A$oykd!(+weFoSw0Y5BCl$3nqBu#gOfnvaA+jsX(Pn0-KvN)Mn$ zB^H8&1FolEk>a|>!u7q&X%>w^%DtP@eG#EOEiWoe4z2|PMh3h3N+5e}NME(&J2Tw` zJ56+x`Tgja$99F0wQ~#Sywz2{3+8tymXDNdN`x3}gB4E?&Nyz0gl)8+;Qt54UHu2+ zpvXWN2QU2><9<;7Zy0w=`oCcu75)FjIHRd>swf5F)i(6mU35WJxlk_iSQ!Bhs3kTX z4(;z;;yQwAo=QuzRvdz=njVKs6@A1oP&^KioGKf=t#uw}F`k9BtKVJ9sZFAM$BKsj z`f4k_l5GPf;w2fnkrR%|yUolWIG_BkE?&A^nAzN zdoZcEI+xTtyS8po-O^k-k32)4`$dAjeO|U&4IG1{KlCiq%!HrA4Y2-*g<4{Pz_Zkd zc#gBi6Uhbfir@7uJsa2nUDyLpF)8ct!L_! zbp`fS8m;QmQG-?`lPl~+@~h*^)x!b@=R|#0rS7unz}=zsbw-tg;ApjN87KE$sl55U z2Rl@9xtUPNKq(t_#`F==*lJPsd34+IYyT_hE1Q_aE5Fm@P~EMe;UJc)>yWcC5x|;kA9wpHoa0>e9}^68kavb*-~gt7YHbT200DV#`NxBKj%EkxF$V zLNX{SfDbQQraLW%DM{w2-o%vLOOHIwhXj-RJE73Ziu-904UY(`~jBwT|?2hiYSu}4iMY4Te9 zqDFxOATN`Z5KaAC!&RW579Kh4*oR%9vr`WYPy&@qn9$+K$JUs+^i*J49yQc6MWh$T zk+55SlP5O&Tf>EaJUf}f&gIV)#)OfW49N&v9%vky*D0Sb%fz*S5LW(+n_)g44G_*A z$u5Jcy&VWI0|O8e4xTW;gfqBnX}i;o!(?6{%L)i+jH$@Lgw>BcAe#2a0qiQkvgeD}lVu&1 zfvYfy%&fBS5rA*j8Z$DgUaWMHskr{w-}U7J#I&V)$0-coZ7L1#M>Cct`RJ+Fl@dj^ z$Kg!6BJVnmPji3y*f+WDi1PN&_!bLAA+oexxVcu;^!Ri+>6&?`g2iS$BT{EQ`N~6N? z;JQ><9yLay2-oFo;Ll;yz8a??1KvmU;d&1Ms5)nCQ5`>84dnC3x^wH59 zm-*3XsF63~lBjQ8K=Cjk*Ri-GcSG?o?)<=7GCT@1zI9qo`=ZRsD_7X=4SOf2O2dH*YuW>XJh(&DCm|6$Su`9alG^RebwplT`-azT0Wvuq}Z zUwszrP9=55G8JYTtxJHRIY^O#~dX;V`&#nhYF*%>dbQ>FS7JV(9>h)h>34P|FMatyH{>%=B+#T~%}xtwMS%hIz`a zBr%VQ)`|tTzzo9MN*5o^IWKSf`|Df{9@mHVY&4vNeda_(g~2ipOFo&*;ndHZ0uYQW-*}Q7 zzj)T;z8qk&N^5ldlD5Bd^p-Cfg}a0GeKq^VcvI5p-Mr^{so|3jL!zsv%Z)V6HMJB1 z_U!kW&?*x%1^!OpI3^y|v8lL(3&Mb}_t6O9nw2^*nQVNZO+K=qxUg-8tb+?e^W-+as|+(K`2fYQx)heuhe&_I#wd{2cS)W?KJ z_R$h_lef4IH2$}nyk#AVD=cz`+)paqHfqxp>0uVl1T%;unzDF+BWID9js}tzeYfK| z=tyW|d2;^kh}P420lTj$ankoyaK1xa&uSt~LS{x#Nd!XvhvB&D zGX9=@tDW~Xy+DH<%l9W=h>`Ut`AfSDnq8&*bfw1_1*$X5wQ;0n`L=6CGqKya6?v|{ zq~l~%Kbth+hFM^* z>;xW+N%JO1E~r%p+&)oFhrYdA4uotjv^hzyj@_c3u>5L00pq+PKYZv!8?m;)F{gu13v!&;TY1X1$ z7wf|tEAJER5u@u)XTMVh|5MRmSg0QNBkQ`Hz^>1Pep8~jRC;xt77Gb;^QE9)X>%;m zar&0x28pmL&%;_$YkXaRi#@tF?1|20c{M8HV__?EZ$W@TcKZ2Om@s&GFq6!-X!n4| zl?#U`Y)irz(-|DMyT&P~>{oZ%kgqFav-}o2^qHoL8%v!vex@HLptBLbdaSzEx4CD_ z_?c2}E=Aw-twv@GCo3)bTPrl~H5=$RfL+!rsdr4)=BRfqFsaQ-zz096J6-Mgg zY!Z^Fw=t9A`<|EvzCTFzQe#t z8Neg`gfC{W{MmdX;53wUL<0I5e$=g?qz&@_t2;~u?JGEjxijT9`R-LCj0G`DJH+KS z^{#EIjrHL_ZO6lpH1BjfP&fS&kzxQ(KnjPaV#sau-GcaYQA5QbM^23ONJilRyp|ZH zD&J+lOjTpKosBOq4^t=qN~lgw#`h%f;3ptBlunuWKtR0{-?;5Gu7$d=;od}6NGlcj zX*MQPMR09evYxUiiH>(QkiQvr(o&q$&k-$mlfP#nGI+hLu`FPj7#ue{G+4}8C2VKy z+lJ4Sw3dRtdVO9P4g?WRQBuwJA`wg<`Rb6LQdm_!%nGCmT}n?l5Aq!WZFDpKIR-M` zqiSyLF`tah8g_Z}R^CxAeUPS3xV7nR;4Et^fmd8rAUf&Yu(;+aI5E9JN}PKZ-d9}Q zTJ{eLPbQi#1&;ipVmZQO^nK#4y@{-aQ{Y@qSWaSunG3RaD<-QAG2@H-P*cjIkGD-8 z6bnaVN;&RFFjI>A3E27X$sNr7fG@N4um-w+xaAO7GAh%|>Q$FCpe4Na-bZOb>K6C6 z-f*TB`1nrM_Wd&v9yuZPAJ5s=uj`2gy$jcGl%xbXV z24GEA=WDkqx(}~D+yP(8qKmUTYUAi9cD_%weux#UpLXh~xUn^w5g^obnZePQNPL}$ zeEGpxCBgb2AqFV{{5lRexzD;Ap6B+w;F-vu3GH|{JUbtKuZ_d5Z&k-0Klc+RU4vUq zFj*10cUn4WXYmu-q@=jCEpDswan;|cM149>Z*3FXddPc(x`95R$GG80RQRo%jifW_ zk41P35}#aPI^U>gb>JA{amu(l7I|BWTk8sB*0!BtCN!MS-}~8q-Kw1ry867gJUhM{ z7dhN4o)CWilw)$>=waw+>mO6?!CD6HmujFJUBQLRa+5A99T-$XDx)xFZ$U9FLuWS@ z#=!y)UXk4uD)Xhw5Uyx>5wS}#=Gq;_l`|2X>fx!ZB% z!Emrauvl=S5B$)+C#2vkZ_tCksn#FC)x{Yze1|V`*2XVax9_?pW)emu-wjsfmRevx zpfTeBB$(9ue_^}x1$wS-?-w<8Ht8?igPmA>5-TU~W+=l0G86`A|4j)ofKozGEf&q) zq6&52i){jEIbw-|8Q#s6=YYHjJGfUkD))J@%_LykT zmSNFT337fATIXMMY_pAG6D?Qg1cx1NABV7O%|iPF`Wq)mHRI~RtKyp@I!uLX!#s0c zAm6?KRg`Do^&fM-+j+RG*LpZZRyYNJhiUt^j&w?Gb+mpPsfcVz7wKHc#W=c8HiQ5fl|#s0oUZ!rrFS2P54zYXo~$>-1cM2ED?hv0rv zao@bY&?=f>^kRo^?)Q{EJgZp8?a9}iIFLW%yS?`?#oBv)Jjc4+ZEe4F+HUb89%%>1 z5LYX&d#0yd&OO++DK)HZ&Uc68Ary0E|D|)hWQ4XY&-7bpm_e@H=Ww<5L&LR`aocJI z=cy&s{9M?5^8#q$vLq^>*aJJP<1{CcMC4cJThE2MI3BE30F{$Ev=@aOez&Gn004k? z_<;@`@5uIyDA46pAc+q>m8JeUE+U`Prq+EJo5~9N!bii7#9fcIV%4F^nU(@!ZCCbS zNoF0?`Rdri5*wR$Gq<@!7AcM(rn)$BKMc1{9rB}9*grMA;7s3S(1!rVrJWP$%ShnM z(QD7vHck0uXO1ZH;;%$@4!!TLofZmasAOwNiSIZ(lKv*w7_Q(OKJGzo-#2_nt_HMV zq~nQvbWkCGgujG{Jsb=Y8a>2lUYi(|dVXde6(`7HJmdV7W!peG*Avi!CUlZRsBuec z^_zEWSbR_tCyXO4o=U8Q$l!k7J6&9IH2UiGF7-8D1gNXm9<+!#lNfZrQW=IPnlY#^ zN{Qa350eqzQ*fMwIj*PBClm%d%KZx~s40-Vk%!Sk9sH9UtTaE~@9mZ!Re;tXVe$Si zGgSbKr9@aGbeVB<<6m>?*z6-z%j^+pg^BDtpV+;TL~K4{=#efuPaD0^tLZ zfR?|bhZ-{47S?rIy=ch7S9z3tGd8dOk8U!gr}>1*wrE z4qf3vZvS4m<4O;8o%e&I=OF_6YaF z%@E(P7T`sFS z*~2;8YgMnBg)EFGc=3o($%sya;o49~#OJLUl4(fv$BgK|or8}#(UTFSeecrp5}=n= zzRn9r{fB20H}gSvy}OE)duQ7EWEpHG)22kk&OY>wEw#{oBL9NBjjITk!lKvkOot7N=II2F6Fd>I7r zPqBo7M5rLoHN&4-f@@N^r~%^eto)LVN6_DXb{v~ZVxGz&{-+J%TjIBM?b@E%o@mUfv@vMCky3=|fu2^B0OKw>5{ z4-a3z8AsBE0+oUaoN%03K*EXpyZ2SG#mi?=nX< zEJc`frlGsNU@`IDOc3sHT{xRGhQyAoeY{#CF3hfvJdreQMW z6}d3UY>PP#C6drG3VwOSRH|oQPl=ZL1zrM4&izyfCdtJe$R7i=)vvFGH4asebt@j+ zOKTf**I6|g+q~ICb9b5z<#&p-6ny3w^5LtW@(pdD)=tLw=F2~>zf)1}bd2@sx@fB- z(|aH>KG)TKU#fFiroUc1_?^wSbocu9%{4!3`&!6J^V2YN-I4Ol$vUm^HN zkcF%)oLK^}qo%?pS|yhw!VrS_Cm*I1$=TKb*hX4if&JA>kwivIXt)RzY?w@WaTUtC zDyM-#da$XJYAdja^u8|>OLg_5TejTNW`V^mg)*|g>ju5$aivZ95ftm0_`3WzA(^Gs z(y%0_BlU6d!3|RNwhXA{a)`eIj(h}=w^n*sE$b^PI2biD4vzaPc}_pRK4a`MJDdMV z$_~mtzWAX;EPST%jbsEBN#N!~r`M+q@BWSU%)BpjVP{BE;HQ<)rRVF`-Kbe|7tFC4xyyZ~*T(!=AFX3mJ zAPH~_%w$Ow8Y_ zL7i5hl@2U(6`ne0lQ!;&h`Lh@B(H5`lFmpML34mo!3Ky3<-5zngwt6ZCmUkZW+#!I zwZnYV+0YUls#MIyQOp81KQ@|?ePsJjM2f{Fu@4M){W=wEI+lwl>Ui?%Ggnx?PAj?0 zw{I1!{7nq&m8`k8#5&z-Qnn`cu8_s7OiLWgzvH-B@DLpWn6iizP1V$;1`1mD7RQS= zzMN&0gmY-0S=W#+F9XGSU~g%x-E^5Fva=Kli5hhqX4%&SgS!JVM&A` zXnANLU7un0b#0hod2#MLPON#kbP?SbS{rja#%-pcJI?vm=PQv+vcrkw zDBXWW6!n{-Y zeK<7P2vabb>YEFuAU?Rj<7fUibz0Je8r`?AcpT&wGn&u4W~PQBY(TGoUfm4_9mn|Ia)*a4LFt_CuFZS9}l|LU9TStv+dy9v`> zB5(YzH!oJO>i%y>RA|Mdf#_eBs0v%aaEZgtqwnIerG&tJ|p zW{Mw6NJ@%q+eFk}EJ*T_uY=z9iTuj#JT7g&^DZNMdkQ?YOxIscl7d2RvbGe3ySA7; z&*XkBZPH?K{Q6@sY!JS%SW+t-z_n#MKM=Y|Vm_Bo)PIsc(}H?=$m#C~XYnAB6W*E# ziXjZ(!NT5cIV2hb_r6r$z+GbFsnR)ZCJ`zuXS`k6ac-O|MJ@ySLfaWVy&ij+zZ{m@ zFIA*=-x1GaAGu8YLI)) zfk%bi%ya&Z@PRtE?Ij>D*|g`2={hs@8ttI683e{!S0&F7LP#y4sg&~%CqZX5`>uSU z^_ME%$65SWhY*mH4}m9;?;W%`29^?lbU3@?*6xf7#FK1@p~nWoe8q zRcVH52*)M)W<--3meqFzSqmLU z;xvyMShv)vhX7HoJJ+rfu^is>g+6BU0vrXT`7=B!6ya0G#y(iUHH{t8Yr|CXfWbOD z)Ly83&We16KR4|8=)hy*>s^UD0BUO$r87(F(bZ^yB}f?N9b_$m(HrWjMs1#shk;kP z)SJRM=34Is0vJ<{p?k;!>?N%-aj9SJjP_Wqu%m5l46X#I?!fvUXM2o-DF=g5mjFm^ zir6~e4Bcyj2fYoQC4+<1;}x*+N$Q}ubU?<%{GsKTogb&M#O-+5>)|sOMqk<)o5G(R z#^r%a>q=4nGStj#kQ>BC`(JRy-?ei?(BHB)05C+g#6kduXCM5yXkC6eGf^ z2-3S0xy%Blnd8aJCMs`EWi;yVL_>n0!1tKfjo!>p#sl!B!CCd+LN?7t1(heAkUMoeKs zada-k`WhqkpsP@5;>85yb4fJPBz8v!r!HB3n1W|Y43*CZ3Nra}kT-w?UPwvoHDH3EoAp zT-fBMT^(@~HoYYAY-Yx7j6hst#!91AxyaVft(WD74kdI(+4N0IsU8>3mT`=hmd&`? zGD2*ZR)0CUt~W=k`)nWIcl3e21~F?TV+0#$^yI%UB6@#aMA&;C#ajr0y7ce=n*uA5 zUzZ9Ec}(#9H1wc0?q+_e2)Q={renmXtLM=VsmS)#A*^h=DkdxRmRof{r3Hi$z8k47 z@^~a*kn%cae0dEFmaRwAb1H1zNDEhU5tGigQWcjuKQ=RC?ShQjpXbsvYta+(p9vyy zn7+k?5&s}zA66ZNgr9E2oCdcSoG79(ie_B4c!ZA+uH_8oHX>pj^Oi%&Fo^YXfVHxB zI7|WKn?1f>5M9+_3{}C2xt1Y(NZ9aY=+EmlaSCCc$i;;~&gGomf+qd1&<#A)K8%|q z?W5^KPG+QdY}&q8rEQ#bs4>oCtTYsmL-=h}2!(f{{l^R{*qw0DnBz>>{D8?T@Ze&T zL7n%tgHKY_)2CsqWaV;-+>QK-=jdQiDHDm8QC>iVFc0jFn<;U9 zkbQ>t{p^*q{af+EDCzrk$BfUbPvaHc5{sFVw#4-AHO;hqSPj`JJP52yV$L~HjPWTNQDWNbb5x4sQ)P_rGLQ@;8JU486=!(%dt(WE z+q=!1AoHk|{#%Wnj_JVGkkitcC0;@&mr`von2q{ zb?@>0WPV25{-m_v+2xDJGXW2z?gj>T1CwN5daryl{76bJ^?m%b;9ykSn2~@@6^nCd zTl^tfa7QtV~$FF8X*R#UT>F;9c{@(`!`TlOD z%$0&5intR3SRB*9QIkXjAL%`b1F&3Py~u{)1XD9yT6OiQ@&#}N0HXZ)kB*LR)jA^J zHkknq{Xz1ZE`pJ#t<}5C=hIDaN(md8sq;_^-vV+)q@;08EkBUQ#DGytPB&Uo&&8|c ztl8h2mI%iB?CeyTUFe*T+}CYbcCD!rtWG)*D95X@<5OQ}g(lJX4C^jYn5@8BhVA?E zT~klzH!S?LlrFE4a_N3n-b0k*RHHWV?ta$neb(V+6-&6c7$|$N81TCTKQS*n?LMoD zJQzAyt!s?#Zz4qA9JlK@u)TOyJQZB_$9S-qP+sC}7O_7<|PfcyQ>ld^`UcHA4 zk?)TWYh^A~X5{49<}FiOrE{)gt$1=4ud>BI<5L>VwK!rWu`u^4X7X$gg~|;JgekkF ze6qhcr3_24A}XU0OAESqr$pt#q6%((NDJ1Op@R}ls;zb|`g;a9Ea(wL&`(~(nGs18 zb;MOnC)tM{B;}>krolt4C_eodArX$tsCe)FnBZ!Y>ef9jl6@0ZR{72!55uDue|Ev1 zl@&QrwZ1Voa{r+!`{MgL-h%^sHq7ncL%0vBl>r}|?V@5jjy&twff`K&c))`1aX>aK z-*p#L-uhF{_S2=sLDQuT%cgPT0w>RRlhub8?yYFom?`818yl)m^FP#O>wK$tmdEtW z4S=I0L|Mt88QiO|Fc!9*rH;c1TJkOLJJUe4ySI7Z7z~eyFm7f-I9(spXFeMe&AJm?NLX{UEE8 z56SM*QkwD;iiS@J!eudnTvALT;r%R#hE#Zt3^apdmBGM89y=NroHiNn@0+j!dH zJvIGIeUYY(lhPrMpGE#;w)aNo*Q5Iiz+?O1=thDkgGeUZSN(diM+wIRK7au3A1RO&5c0koNfvzywo$c`|A7Sy9zBO*1O9ncAD6n(_m%ZKag1@2r~1y zl1JPpoX_ecsB_yO@D}^whJMQm9%zL7uoQ!j$M{Za+)Yt&5k5|`a_GRu|ac&T93{@e9g;q%R|a^V%uL+t4HyUdLn2SCmZxWP-F9kRwJ zEZk2yKIiur=ZMJbFZ#T7OXooqcOA?|fff9B+PZ|jgai`0abMPq)|8;L8`ybrD7Y=K z7#B&XzW)bfmL_4bKrG_mPaF{$gMw!u?5iH=uz#GsW;9e37GLOKkuWqORia3U)&_*% z=)Znic$&PQQQWH3X7J>Hi%Q4U41?YN*7(^j?X6DLzQS_Zxr2Q6w0Al`IbHAYUKUF{ zRr@T!T6IiRiBaL(+9DRB4nflybYRku&9|QEQIDQ40_)85YqT8Nm_b-;U1^4Si?s7f z#UdqKSR&@o541G%9l(`9hV>po^T#EE^3%moX&B$+BYNah*F0;tp@+lklHf z7s*B~f*4|@|Ko%iTB%;aQvH~TJYyc5&^^Z%S5@hS#9@Hr$b-A+9H1B8=1+6oyIUwr z;}Fx*JiisK9;ynyL9B8^)RnFq@(i6+yvW_J)A&q#=%DK78H*2(K_~7dj7=z%@DBN9 z{o!Jx$Ymn*9&FBDN7e#69H{m%j`M;Da2PQ`^S+1KXp9pewk*hDC1wX+GM0E61(VSj z+lo&5qj6U$;n3@?ueXr(T+B3HtxJMp3G+$kMk4s2L;ID5wr1Pso3VdL1I8j5;o@#0 zWjgWV;Rvaon=&Oo32+k85D|F3P>DP`Z?t%bK#8sOeT{e$WnAc~L@{tQXbAw3qMyiL z50;Vu(KxC_+5FPwG6?__SwuZ~#CX3#SbG^d3NLuCNJj5N1G$$oS!bJ3+%}A;aEl_A<=F@{rJ0M3?QANvC{m{Oa(nTb~z|E@p$>_UeP|%m3J_=;f0BotKg@b zgL-+{*!xY7N<{Nept(2CdBM>}x3R=KHY-Ve^N@getqzby3rUi0>(_ zXK0#d1>eLi@T_pq>&4QEE3OtW|9}kg<*WhIutLTmL1O757G5=NkVUA`aM1*g(j=@_ z!g-2g0n;3~PKJ3i__K4?QOWwrS%k@C56!kexN~hcyGT>Zkc!VYx-Qb8-B|M3lne5f za#RnKW`qv<3q0O`oEo+UFkhHXm0{@kst|A$2zg#gtOS}*Uo|@Nc4vxl*)!Hj7midR zcIhpjoZ;*EM|v!7K@6Wj_rF{(MLII|AJfyM+kdVj*NM#)gV+KUHTXBOL9y<5$Oa8F z&&mqXNYk-+1iJXhJe0l76o+UM5o+q&f8xsQ>H6{|aR2{vW%vJU zuI%#v9#^*g-*IIhq>LQNXT)Oc6+lQ?B|C`3IQKyRtS3p9OE&qFOe#Ag;a9bQ7!(c@ z22Okd-DsFUmJiKGCLRp|0Vr@LQSf-1Z#x!h;0|DL8&Lh=Q10j`F!a8-;PG_w0$()@ z@20gI6^`s*k(MTyaU?=F9NIbNjC`%2uWVA8;6br5@m^HlDE9igMRz6myxMBnpW;re zc!+9gH3sj53DI=?d=76chzJ7Q(=e_WVdo;=%92EYp1iGUz*+X1IGH?Rw({Q97QYZ! zToQ}0E8Oj41bk+E*8U?p zi9jQIF@+cJ#7fo=yUXMs9QHAjcqgMSqn#N3*uqpp4V6|#K^>70DTG9I_!oi!>TdWK zg0WXQy{266xxe4xpkB+?w*JXl>?vNRG?0@cFYmcDS1@EjJVE;|{xJ~ePos6})u|H2 zd`oRa7d%;6oXwr)4!2&GM3(v*SHdxSlC^EHWWybOnf(twYb)BaZs+1)8GbTdk#vbJ zZD@RS=kfBxG{g2%Jbz!oVSFeWiRY|dl?)4egLbu0L^|I@KFxX(sRDqa8w0cpXYe!z zz(@|)MEMVZ5uGZlu8)*pO_V9OV5xtzW)>whiEv4zHfmKHr&UIYqn=HnW+qjrZifR9 z$@;OzlUoK%5X&NRBezq^qQw0L1IwC7CmB4UkpG(l{_{Zcg)<-4vEO3^^*i-&LI_@- zV94@pVn%??Cf0W&wuVb^NppXDYnp-H#7PpZtUlv3PEfw(xxRq)uIBh#T~s%SyE!L> zjV59>6Sml$Glz^JZ6XsYU<2Sb(7{F*FkxZht`m3s))Cm`^%;Z4YaLhQ`ps=-m_$=5 zCS0|NzXyXE*-_HCgVTxAAkRn4&Isbd!d(c)$BbGHE=MJ-{DD+d5wsQu0c##G64?Qt>C(^GePc4 z;5l-u@4mBd34ANCHJEtuRHYY%DTtV!Qk$8!CX6*_Bq0|)KrW3qD{c}st`u}sW}yfR z$=j{jHf2PB>o$hvFn>8mO%QL@ zG%Dcm%$tmGRHm^XQBTBYx37lwlXZBR({W=TfNtkGPsg5AI!7Gx3Z=iVJS-;=(|C zw1XmZKGMJWS;ZVmT*Vu4QX0D7v0@_1qNK+yQDV322b>^^_P$|pCamXVIO}_<@L%+8 z?&DSgstahJBS%f@52g*jTS(PIM@;GmVYi<_|7gaULY!2~M2R(DB!T#_v)1cB?{CVe zXwakiao8SvB_~&?Oa^})7@|0!!@=0{zu4o1ne#6J4b(74OA04N2%?md_^7#787rI*;o#hiSRSW}-ugJED8AuLwftMAL7*7l7hf zkwD0u1}+nWr=Pdf4uvE%ib*8L=S8{nB`B={LgSKwAe5GRxVWa)l9nj*{xoNi*;E;n zv)z{x$eI~Fy|Ad~(P-@eDyro(_LCf(OHgPasfSSnIB2KTw`Vg7tgk9*=?`FkPbide^|m^sEFcBf=t zbqJ>%yVVY~%~2n7=aTB;pZ;I?h^?B+e=TFk_{3fuG&22iwI`1MF*uzVy?U9wwceLT zn!Aa5T6i?#0AxX$yf_Da!!g}^lM2j7F3+wO@`n0Xl`r7T;3gy(%uIM4Gy4(5IW3OK z6+UBk@PVmdcFU`769omWjiEH^XLhMw*|u!i$mcKmlbz0Eoi!VWzpBKF)-M(S8jblM z@d?bqM~mxQg`FPC4%&>XT)P~A68sZ0cMJ-;K8`P4X-YTm4`ZiPU|AQzO6(b|1d{ ziZ=NgRQ6S==?gb)jrxRCbr7Ei+{+=V)vq*dB%vAa+j);j+zgxkyP3KmR>oqA+Zk;a z!j8c=CC`1hgpTZQqmiYR%SpefMN<<29dmIy5f@ecRb1c~4^>tnx@- zc4n5sU2AXO-3zu_liuCmS9xmq^>%zLJ1$?%8>aQ#G28~#OHGfd^iwwAsvM9ZU}1?) zX71=A*rH?|5=txGoQo^n3LpjNxYPE6G$#u^ga~hg?q)%Om>M)55b1f1Q6H#@or;5C z%SsZ^X1(9pr84>OP4M8!P>aL(VN67ORY*yI z1vS&BvA<$pcBE`L?L1h+=&mJPi1u6;SqJvZm;6e?vn zzB_AJXHfFqT6-(}DIZ~u?Bll%*>*YivQ40!ZhTSaY0iO3uuv^l>*yk=`MIGC=VY1e^R0rUM1; zeg-i*t^#F%4>6j8uCS;pDuOdhlgy;>H&m1x0^+Qd-p2l);&l zm(j!u7!?rl&t;wl2q=Te8v4lQ;nQW!bUCM#Qy(g)Od7O)ZZUCd#O zwNGsv0?T^D5`6%7FoPnzl6tKWED43F-trOKj9A93Yt?!a!xGg=c9s)6@nyc%Qg!UN zV`G$w4R{0dymoD^7S87vOQRM$DLfw@|l|9Z^kboyWs7@gPZC!N5__+#Ss3A zi0fFvxIl`*iy-^tl$@IC0G(FJqGJ7-km5)4H*4-s`Gyz1K;ws_2i&fV1`=p}OTh@} z`GPbFp5bz63bO1U-69}6^VS~uEHp~^m~?wffQ)*YecWWYEi9*ba5$rKea=NPT&MD+ zR7)5XBGX+2z~)o8&tP|_$Q-gN8m|hR!5fC5_Yd%2u@EmpDA6+}MOWD9)Tx8UQNory z0xx4iFURXSVfUZ7J&MeE-+i7fFRZsmDzlbO?cN5bV&u$4U+DTQ__eb1v46$pn4$>D z!Q9U^>?4T3l#ztJ`g?=Mw5Vq9J)L?D4?{igF*cUcP%k1$*y(7e%45YcLRFyl-N zJcI>%+WA;u2s>w>}qoh@a55# zorG#+0CM@Voz5}9G)VisM+Uv8$-})#+U5e=HAwV__2WN@(Mf#_x{iG{1$(-{IGG?P z@%<>w{r!kypJLH_iR7enD)gP0(x?K`i+L4M9A(tI;*#R77p^`*A`c5G_>cg0B~*>$ zVgUaOA=|m#S?Jt{)%7!=kvMX*tAAMYHs@!2kNcP;h0)E!;#)JR2 zxG5wEH$?$!jZjPbpXJcdejwGuPS@D~S6?R7KfX-DKfcT~kT3Jlv`C4X>2CTjHB`N@ z6{Lp7ddN7C>gg~4z6OT|)uk7c5?i(v4!G^e5Ptk@&kP+)=<+?zpio>X;Sw1WQ%3YZ zP*ZaGAEl%eZZ35!8GMWxQB1fr&i&>R9{F(5NYm*>(>M`DyL7jpJbjYeyUjFl9E`b9 z(CB=dRRl}uiADykSj9f$8ZpvC*MAPIL{pZ&;c`I|F)`!6bE}>YCT94YG%om94UAja z6MZ2}oTnRL`uu&lFgoH|${J6S?qFvogJe3Rdbk&Zqwv%Ap8pt6N`O|*?&V!X zwGoDTFJa>dkdC&-pn*zQiG4M4E%m!&M_I~sjc1Xe$8I{`+PPYI zn%}Oy)o!bViGP(sA^@9-0SJ;6(M9+rDoMhNyLJS}zqC8f} zUtx9S|Af`OzFkt7sZffyf?+vQ5T)Rs-3Hg@ym=oOH)935Bf%lNkl+v|oc~C};l(H*DlA@;fcS$n*X2kB{Qu~<~>DyRcRdSbX$N%it#W`1?-W3;oB_xJB z5*PU0^b;#~3=u~lE{N4-HdjI~8DC2!U_3`~tqLyO3s(j2n9>#oCxzk|lm}_z0}D2y z^5hS|RS|mf7iBFSSA6pS77xW*s-yjT6G7t5_h-X78f~;8#7CMEqhs_>%<;n^GB?Se z0^gGm4i%~d14mIFhcqm(EhQsjuF&LKgp0U(Z}DkvN}hxxr7RSw!`R~EE}w5GxY~Jv zt_#*#Ib6F{lAY_;ZEd~fQ&OOOS#1>xL$a|G1y28N6fS&!$tBv)*2hLnepKf8G+$P` z8&+^#OHbAPV@wiarg6jwV+gzfhr?1wu;~t?xCa^0RBgm)38-1t)QKRJK|ste%FCI# zmr`7eHwSoTd`7!kxnap`#MQK3QpdIP>A<(O&Ji`ilsJXcYKwC~!mT{a|8<-%!%wL$%1kN1PYyDr?AO zHP#TJvkD~zK?*${?6ALv95z7T10KpB5Efi0unXDD@IgS}L;uPLp_%USz6Kk82CNg| z4i}UYc~Gndn%cXYh`W6Jm{lp^uM2WuPx9JXUt71Nz@H$mr?k#l3^N!g8IYc=^ZONl zv`iI{f?dPx=9DRwRJ_zGf+0HV6IlUBl;>QprsK zs2tk&ZySO03LV7#6w!U^T$2=ee1WQz-@C#EtJ9raJOGN)s`K2)NlIB92r%*ndpEB* zFS~!q^I1OT)OTgCQEO@8@2Kzvwv;Uqx}YCtS7N>&l${^7|Kl9U%{j~O;70;>VP3eV zzyiMwI*q(Z>vrfESMk z@1|s>>1RZ8nOxZ%R+o-fiOQ9|tB1RB{!Z#Bp=RQw5O>k&f}7Nv(x3eR0%afp1^QMG zMx=&FM6me0Bby{&Lu29Ml@xw$n;T|(Xl&q&u#R5BI4>-qoIvsLZSaaCzuCJ}Qx6rw zTY5(U&8F3TJN%14egJ$S8J<;sMWaYv5d6fJ2UGy6uCH5y(xy;({~aKcxf6dYFqBG2 zl9ej_UauA4{k-1&IDDQ3TyJ=pI(^UsK51{Vp5LB(e2}$57*5sF6Rn3kQVsI$zx^@L zowt@OLOQ>1t$`-XP?-^Jf%{VWwf{xa572Bt&+!3qSMm%gFC@BU4=Ul259iUPL-gYW zTfoVPL5DG%rGboa*HSw>f3<>OmPFXjva(&S&%eY-E0avIxtspVW$(WeFM~m1Wao`M zA`m-_XUTYRY_(u&`_?wVhr)nJX6JpSCa~|o=3k~(7v!q1h~=8@1BVkg-{n9<$$lr^ z=$F!u;_6=i)*sig9|A|wK>A~WJs|bg(C&}^cu0b!64mzlSH`7AFz_?W9}DXAh8u3* z-|}M%Hi3koo^|s;vm!i?njIOREM}&ThDM}8%=?`CgIbJj!JGmTf8H6iPp5!Sr$qoy zx7~ZVzk}l`&aBZ8d4Bx7vxUXbvN%Y6oE`eF)JGgF+}Y~O*M$`J{P$&=X13a|t$Zk! zu7(yRqcRN6FU673pk(2mhU7gGYV1-T+a81u^s(Bf0fM7Dn5_mDraJZ$QtEFV>Tz{+ zu%DZKnUpnZ45+>;{;$+WL3-qJhriWF$9RzXxb^&x`WP}}wNUYvucm9T7ggnpJrUy4 z!3#AF^nvGqc#zAn)yHf1&0KHGot(!fDcFfY_I3Fce?^D<+1$`zXd(7Pqt9&*fwuyK z365yiw5H3!_T_fz^}A-vYsu2#mow&NbQz0)I9|EtN!nv>wANgmYhJw>R_J&kZTq~% z7U23;R9OXwa+~TH;OAq0r*aJEPTToK0ZyEe`|;B+(z%OcR70ks8ALzNB|EW91r&aP zR|(PAup~I8qqN=Sfvcjb=%hj7Hg2N=BrSD;RtWHc-?FA37s{jyC)QHdT-d6-DkcbMxi1xHi)IISKPjRn${bN)g-*~>X5?~lnm(o1vKAm>`F9|tB+8#aN^YvcY>ga{Y6xo> z1Z9lA7YWrnAbEG{{zBC(+D2du%KS;g$eKxR#im`XGzDt@ab8bBOg+>6+j;HO9AU+Z z!TH%`mArOE{3b@|OJP5{2u(b3{4oYRD0ZtK0z*QXNVY;M15L8946BWMx_CN`bx+Wr zY!-kcrEF3(n?(5rHBV)?oW!iMr*3*6PCg=Ak!f1q!v59W-sR`JDyC=$_&HX7Cu`d| zrL6b$Ka+-v|D8$0=vNXgGf(tiJUMEvJ)(m6wWm)V0VlPi!oI4Y+)7i=%hNx(m5J_i z`yco$TrKIJRDUo140}ka!rJpVTF_Nt?oc$5w8Lw;hVm$AHG~W{fyExwbc0eQsM$nO zj|ptDD;+^j|0}7I0c9;w9{i){k$hD*%&o$-aB4}YSdkHQP04}zYh=c{pX?Pt6-ZGT z2&bLx#(wP;?~8f>j(h%GBoF?&cGqVYOZ~*z;i#;vx^#;?JtKU>01b})XMDjz3|7@_ z65^MDqnx~zl|~|!uPg!=2KZT#CisOa9hD~C|4W(SN6OOlyeqUVvWW~(hB+hP9!3sQ zlm%*r0&{|+NdQN!BEdyCf2QXxf2ds8eO?%UL@P~qc<{2OPmGbsC7pAD{$6Af4aEn6@meb; zUP?kr2lq)ZKd3py3c70xH8+4TE*@DSK+oF7Jlf)%yB$du`Kn zf5w)I@ruUAr%gbZK1~^29s7&o+n+ZauOL`yM(dAH!*Upp5*sDrRMYXvv+>FIe3SHq z#4-lO1tw8Yq#0bK{!gg6WCD^KHUnOlCuQH7UJefI#&?xHUzT(q_KNhZb$s&f?!FGZ z{((QV*ctwUKbmWnti>fw3?d3$TwlCfl0>%NV^`Q5dZ9*cZRQ;2r-g66a0IwUJ2{{- z7xWC#9-TIG(9G86P}HIhQX5MOHHb)(@GdA+Y@zaTVfYiIQQvldhkboAS+ld-$o^t2 zzdzUbX8fS^zDD`|^xQ4xc5}bHIj0=(zyNhG-+yJIh8Mf1!ojEev-7bm7?3Ao1OV=% zG9&J~=raF#!)SLx*y164dD7F|=H9DMDv^lWOys)cN0>jJ$;mlSfqV_8#Us`+O7NBW zoztuoYl(E~)I>lfvb8=pceYbuI9De|TOEvxBPFS00+FzZG4Ei9z8>KH z&O`of_|_BXSZ6k5eq$zvbnXLi1Szx}hhTVM9OYQ{3U;1dd3rDTFXunca6_tyV7g)a zkiiIzehWM7T?&eW5$=Z|XOp(sZmw1Ymmvq1Wh^T|4R)%o&s6;W^eh4uw zs&&}=2?ky#Dw`4v0Swa`iH?Lagk(mHbtCLYLo$sFXH_L;aU2@vigUiKQ(0&Vu;nAoYwkkzjp5~XN zcJbNjV9_4Q_Z4{Bao~6?)mHiDO9=hNXX5D_cvjmUO%=_jp)EhBm5YsnAP9rRsBXhk zkUgdWmJJO8G6ihMyu#z4n=EhMd){k>a-0S}IU!ZoAz;*%qrg`qn-KO1wXufP90YM(H+5K4h%eRpNIYO6xgm zFf$r--`QJfiDSiM$*1r0!V3?^FSOZdsm)gTRzWB^$y28WgY|pD-1>Oz^Il~^hlp*@ zE@6&f`Ttr*{-r2gh$tA*$))gSX=P$8^HBEnn!oJwUXJfwtY4ydJ9qi~3wiyL!bhz$sg9UL`HUC$qppCPm(kw;vi0z7x1(-8DqY|KJiGY>Xl$N&Ga< z2=CF)gm1}Y)*3SwRu*bJ_*JYX`0E>H{~-EInni{oB3h!*bRmNERPn}@Scl#S(g$sN zIQYCN?K$sEYPXhsQO-hZ!cK|=o1gFr70ox!;Gl@YqU5uwOzLbn`564$J= ze5XyXG8u(6=0}7U;;P4d+VC6RqB$Ea! zBrO#&?IBIQMT*ax_6Gupe^!QnsFjBsjM}JCuc-KqwK<~Gk@gdV8H=+?L|!Y(vpKizlMBQp&Bks{g~yClj#}ed z>hTu#Wrn+3fVk0XK$dbhbSB)S%upjNO>ThFhiwXW#2BW;D5^5^#48ibjqM>CU6Wlm z`zs{1Bd`fGp}Lc4n)RHUr4^o;D6?uNQ%eV14k@bh!t?~!3`?9Owle0~UPUP;(>5JV zK+;68t)jc1_7pw=E5$4n@ZYA#(^{? zQAC=sI6kbHEy1D8aOjH0r61~ZbkWeNUo|5mDAz1sUeqwurD(`0sAwlm2T`a-YPa7$ z3us;)64wxYm4kB9=$Q^sC!QM&JMly!C6+adi0>wNWu~Hh=cADj8d^l};{ME=e=XVI zW3pV~Rkk6v^!mHgyY0^Xi#4x9Xa8OQ3#pXQK>v$Ap`whAoVpCp){K{)tUoB(c!7qp zQU`0fkzl*9;d!tBVr4H;@Yg1nZ$}2@sncgsoX6_leH8v19S$*hQ6xA~ng&FN$d*wv zyFZ0oK6J$B-SgRS2W77fd; z+q`#Ko7yW<#}YI57sg^-j_dE)%w0GKnBAmv`uD%<|GZ_Yv`~S$bf_$SRx7rsWvw@= zm@PBj783OCQaf5Y%Eex$-m3T(fohRV;C-XWYzViwh9>A_9jhSd--3 zYj%W9xlV^4hyp(5vC;F<<11d|oA}h%2iKP~@(Wcb248J%`HFpGO(_@k3SaqC{VcPi z&FJ04Ah^SncbmRXw%6V7(!=jN`SH8`JreKhQebabA@6{^WeT|3?b9j7B{xPv^jUs! z$vJ*zqGFs&-;GCk$i7#`_szj9$--D zeM<$q~6)t>as(I6-5gGc4K0K z1M|K<55p>V16Ad0$c(SL&Qy^~1y&b+Zn`uuWb1JhX!{=R$bow&&JP-Ks$>`T0W5(J zL6P6xKey>1@E@h<&sEG`-o(bt{jz^6*nFy#v*(gtur345Y<(#bM`W-?0f>nd5#E@h zD%4oDK9B9Hc3jK936MjU#6#yJsS{~NK-maB$;L)1`0oOEpLqf}!5~*iw@I%?kd0W( z@)fW9fU-_%MB%Qan+VCumK|*Sg@Ro7gn@|C(-4y88ZkHp2ZIlB#&E;9`Z1=IXt{~T zIPHx~7!l*Oh`7}qbkgAq0x_l~Uz9*wqI64={T7FNb|yf{5_v{j*P?;1TgFp;)5>u94>O{ObQU#QNUDaU4SXij)KBp0<4nC&BE zo!6u)j}e;fiSKjn>U}oqZ+Cz^h|msMp=1?FJ8JX5s+6tBOy5#j*Oy7@=enjw@H8(sS`X4s!8aj z9=V#HJ2g^|7MDZFn&evY{NFT{VpWZ}PWoTJP~;q&sj;>Zi{5Bi&3&W6g#=8faAp*Q z;Nj{9YWb)6J0eRbUl-XiFiWB%oQj*^h99SGVCJqtTBH_H-Bf#fYOSqIt#_Sqm%Q9= z8`LRvwU^s0Y|5SIjth@})0=&)F(v4XLZMw6gg{3~$A0q@saj|I{eFC3PAc%Cuw^(x z!z1Ax5A|au2HZz70mcUogTU`GwWzkQLmFUh*YvYg%$A0vi@f&pL+~jERp2O6B>B7Q zkJC%jC=JE!RQ}xBPalg^F`A@q5H<5P(7PbEk$*Umn@t}C$u|Fho#rPzWDgSP>qObZ z>D>UbZ>vOv6{`p_H3}Wd*W5a3ER&h>3*q!wCY)9^2~daTlE;A~#DPZ#CHv6rN*rO`cwh6(lDg;R>YP+2pLdXl!Md2ni@{+|0U9-%tCc1 zMMw1O!_dIzaD_Fcr*7ik7e6p({D=CmMd^NSha zCUnxLr@@FEzTQ3mF;kyav3uJjs3;6BVoXWIj~PMxyUJ`D6KhVz<8|S#j1o`JHJKrf zEmMEYq%)JSDF9O! zCs?o|SoGU_!W5g}B}R#l_XP#r-bJ#R>N{)h*R?Aa4}SAp2g6L|osT4gtGtqt!uapUta5b#69 z-sOB8{fUVPSdGBiR}n#Kr%DG3FcE$=87wkrKW5?!bKU-mS9P*ZYe4C#9jN&5NSQ*Wl+X%l+_ zpVyW%%?Dr80)SHFZSMJS7X))m{9i6RzR7BtnMOn z89bMhjxF_4svy*KrPcq@H1mbO*>2O8S5GjjhT|kk^3M1q$~&DI>I`B0*ht@u?+U*EtKRhYwaQnyTVbAG2oh&j5j_6`A4=>CxC-L-IMYOmF_VIW!=d1-h( ziK6Xg>#OPZ!xEEvZ$ocY;`vFXsnb^uE!|+flB^@T+d};wE_iaTREL9&_XekgP0kj? z&SDtIv2te$W8Xp_*8qkltt`#goQy>PFvjoA)+UG_5>oHr6J(&uPe8V%5M+cY+k3Oz zb@s}OMXWL!D9btAr;tJ57lI^W_BBwX%;=y??g6># zC3f{?>8SG%!*j|NxFGx>=C&sHEr$Iuy3=;~QT~zOeTtz&I>v{u|B#jRPC9ln)8`27 z#PVgTL6dsbmu-_DD}(u!)VuXt3n)wHJ~rUJ=>7BT=6Q*6!29PnL)QZK!Q$3AzxU#E zl^NgPw}gj3ogqcvMsK{%uYX@#9Ngp_Bb2JOs5-C>SMDZA3AqOI=^BXxqYH`C6^ztR z6@I{3AL0ugFTDcyp$^(05PkslyQEJgD9U_7jt-iC-FFddiCM;%%4g2yP~@hpk17`EuQYi4MKw;2W%}^gHDN1N}-f=64+T z7FB)cWE_RooXZlouMvUw+FcsnyWXOqp-JUQY~D=Ht25!y3yte?-EmzDO?%)QwqXYS z2blnWeHYc~2V2kj^w}79Z~N+{h=8K^<$GTft2Q0l#i0zE`1?K$bH7RKnBJN0IcccYAqve}-=^q(~ulDPV8CDIST4m!uWNx=D1E3SaWCgp6C02?xa07ca zz63&)!&OtHjASr&8pr~MMHZpJt@EAINXx_bn8~9S7|FY1z_=k!VXI01JdjXxlcd6M zgM#)^XB*&|QMm);Y{kJ<^bdshMP+w{546lQuEHy#tuB;d zNy#_~PrSy>yuR;F#j?ltUX)_}560dyD6Xzs7Y**go!~CP3EsFn1Shx$cWpely9N*L zA$V|i2=4A~4Rl}fe(%0#?^E}lIyI`+uU@m~>RvVHnB$QljcRpwAC8~-+VRk0yQ|Xt za)7`|Bb`Gkcye^59HSL9%l2gbU1CPHG;qwDh;c8-XelzM`mt`-T4{#8`1Q)=|!4m*=VU{ zPNE|Yf|yqy`$el;hod8*ft;0`)w>Dm!CzKKRNv7zfFSjf^>krx$kSKt%MGd9mD{x` zn@I~-cc56vG@pA#&XY}HuPcL4yMrrjQ!;?e?v}Ptqr*q;cjVhZ!Z1!uRq@^Ppa+$ zET(EA*mOXh!||gWYJ`492JuJ!^M*ESgbXjAp;-MW!yoV7+ZxpbcL)P~ggBPi#AuZI zdpnLC%Ex*!ioSKcfcJloBCwLRzwF&y=Y;w^kp!m!BGM*Xf(-@`o0B82uK`~y8AnDT zo;elttQ!lNa+4>i<^@M~eyBge_;#kTbu(7k5dx_vOeqNVGbIBUCJEEbwxtTEm7nk(uHr6X3i zEG(TZ4Ow0KuIV(Nj1Fw?UNr)@A3L~yOnxah7O%C$ZE1ogK}OL zSa5)~*nvi+HShuq3EH*lOJOo};jVJDGZDYn1cen%(Z|46DC&!y9zKe- zfiuwP>Qio1y6LvIv9Q@dW~}5H$yQpQ1A1iHqzL+kNV+Y9?&NdTkKO`By6uXT$ zR-97$ZIqijzj{v*6jIWSY`T8pdNs+_{8)O(`!<-y9#2>TD5eV0@iBIGMTVh&|f3rmT~M5Jwf)e zNjzkET-Gf+NwjtxAFZ)C`z;YYO)xHR`vd5d66G_Qd2-3;P4_3p?bxm?OQhvy?gAeK^eN!Df!w{|L*R}f5~b$m#1`D9mO?dVlLR#V1Fkq{ z;O}4Jlcj=b-Y1$c5mWaE@ujI@br;uo{v=ETHDBj^7nN}zD)Cp4tTv?}G8t?pxU)?E z-ud)nqeIahb~dieKW&DsW9~{*lscwx%feAN)RF0uGmU1|CLRAy0>jtDiXZWA8&wHe zJ=8wbA=(3<`}XCV+Xy90Gj$Ay@~eaF(V8sUnW#-)9Q+E-SM^#&>6H@e@N3EFYkeyX<~f7j$*%&0*5}< z(*G`a7iH2eS(k(mMcE|w;knaD6{D6u@h5#M?VUn(rofv{$4G%WiJijqc=ppkI=PX8 z>wA|F_B#C|3ukUYBpEK4|F*HP3z%HpIa0$5m=s8G=1VIC-OZI3Fxhr>O%z~{uNxjv zG1{K^x!rDsj4Z3@5Oa)^&wjmD;Dlkc4Nig6{G(OH93gNY$}V2L^p4ooc^qE*dy*{= z+k=P8xbQw`OP>>bZX1zOS^0r?!mzSZ=+a=Lwcgzmph;)_)oAj2J&(p8cJFirM0dQK3YTJM{trf1`~x@;|1iZ zm5(-P5x6FHC5?ft4gF{XTPIijS#k+Ji?HV#c3lR$u2dGEYqzpF2l@uH5q)rew$Ub= z;l-+S1N?iBgiR{PUs3PK0(;jOfSJFI`2Zd*U(tz2at=(;2uTHdByEFT&vqx=ThADl z)urD9efJPqf8CtD)*3e@chL5{Ep^7dWIjAowmleQ7n~GNiGyer=>ih47F@L)-6Q&V zOq|iyNB0`*rkAbf7q*v6=nbk$m;(Ag)ycZx1SKvpy2VM3D9-o0#b4Y%BOX37!oocy zF~TC2V~F5F*J5@{MUP7Lsf4~8lVHO(<-oquD#w^I!VL-{E*A?ZDHr>$*?`===>)dH z4T`$}t$#)od#-bKrwn6+eY*#>pUf~+L=+eL?~W6_A*&zcT>{S=@uu}z_Vwi|*o%#m zY8+m)k|^d43WB}yz~YnrNaXZ`Nsu7Ih)YFVF|$r(Pw;mt3R6;C{9y=B zVhROsi;hCU9=s`*9agyPEgi_1c=~W99C@65$6&+0_oKJjcq=Uh(GIi+VX+5 zu?a8))SWGfEF^%qQlgA?q&caO4AGqeRR_=pbK^dxVZv2xY74JHx_&RG0(*%DW-xLA zriL7!SntC`5A*SwjZc*~_xMbv7VdM9?}KvYTie~{JDRF_CuM)>Z1L{HOIaMLFvrxR zS7JZPqss^lD>;aWA+0(HfxGlh%|RIK#B`UYN-72ssw#o+bl!Y_Q{}&LbKHK?U-2w} z?b)$*O2$NiN)2Dp$jdF@ZMI1$UjE!&Tj=htEgZiY523PHRu^N7sRjE`I`UYP^stbL=-PruKFyQh}JN`hqVy zge!xgz@1`ybbzXL!N$g(X&nBDxv(_9Q7-GVKzrsa1bjAuUv#fjT`%1kM5cJ6nnm=h zDtZpkvB94@0WIZ5^laOKt4Z1a3KrcUI}Tl4J+TuFy6~&MeOg z;;Qmq$&LSoO@zS|hK+O_UEr^v5}h0G;E@_lk@eB)~kndS$zav3)ase8VdebZ1`2MJ=Z3PIDpBnBqvyS(Vu%8Mx@!M16s z?ap@$GJ&(9(!ve>>ZV(f?`3RU4`?hNZi7((u)~w-vU`IM1w^do&A4Q*mB4g`JREJy z`(i=imk38CPR>FYX<&tSJqJ?~eV=S;ScWl#>qCeimB%%k;bQ4jnemJgT1duwyq{50 zt~OIOD`Q2meC6uFEGZG}QPqnfbm-BC(juqXyBq%uNS5N zo4&~mB~&4b)k0UsoI25Z%kNxQqyUaucP!H?pZh=!&p(%aya&bu@7UHmh!J?UbAB7r z{i<~<^*U&B30DT0N^__2sF54QbZ2 z8TK@7)`P!H6@KCauSb;g`J$HCNM%H} z0F2lO|2Ho)nT+PzH@kj*c5_nLl)wmRQS(iPfYNulVyL-dK6SZ4W8^QULZO7mYN*PI zI}LJWYB+(ua%#dX9$t}0dwRZm3ui|k&e@Usi+uM*3|`M64K?9qybu@t_AnPN38bq zlw#RdjP)rw?U1UugA0M7I<@1C>a{KA44*}+N%Y7s>h#%cF=tr{Qa_8NCb`2k&qT{m z*&#y^T<}-gRi@f>(~}6g19e~Xi9R`B`@|s+@9R>>aVq@M@OKg%W0y{!W|zG7w%o4Z zhh??R5o8|zD(>Icvg=xWy!*ucla4VNpMx1|iV}=BWzvW!MPEOqKg#s+hsOGk?rE-K zb7%8kzrG`0N&BV!O8uQ`l&a@=HRSBoYluj5vyOns(lA)x^=#E>tr$vI8gdj{)>Q7r z@$^-F+VPWbjW6zkHmE4oI3#?jN#~6SN-2IZaFwB&4$K zf666>F!o{~QA`JZZJmI@v~v`TT+t$)R$N`-R9)ufn%cTY#~`AIfuk&HN;!evE}njr zUKKVI4DP2qzBiW(6w%2R$(M_e@!H0h^t|M_vtSp?B~PWG7q<$Fz&yyTZsqSrRgXj+ zqgAJqqp4D&#{RA(k~3zIV>A(cb)|-tV_(p&aoXxl?R39&glp%}ru1jM&SIX{Y+|I( z=94%L^URS7vh4vMWdAyYB_4Fpg=G_-`KD%iP8l|{P@S1_ggRSbiACbr?r8M;1MEbQb(WMy8LP$TrYG9+!(HW(E(0oPgbD zlJ8a?3Mb3Px@(Gpf`K>srvb;TU(g&5V%9C5oBr*q?b!pxM>|q|ZjY3fX4T^Hg*S;B&of{=%4^2UZMDZ{1{|aZBK0yka~zo)DHuOd&{}+Gl+c`v4ubi>{8$mGQvxq0C@H{8z36; z|A(Cq=6-{E1mJ?{1RE!rs`&A~YpcFUA0uo+f*Pn$e?x{+1d6tQ8MN#(!#o0=0;LJC z>Ixf3<4q*4A~@c=O&L5=OB6C4?B78D7KKMRMu<&f%{L!D9SJ<|kYz?6LA8H&WMzA#gP#*{=!#)S^7 z3{S=-kv9oPaw(&sKpI8PhaEzW$3=<94OA2Et=|UKJ6$o``notgx9F51KReyrdY>7e zfuPL#ZFU){1tgj6SW0C$0(F%tD4Ax+nNm4ab+?XgqP6?Zm}oG`nek|u3D9vuAwx+Y z7o;s@)l<5|#xQy~Lh>;Wh-!QbxMr{c6k+U3k?{M&_bpSO*puSv(MC+qN5nC>I)9#S z6?#lBuerxXqW8af29Neu5&u~oCVmpCU&?fEuF}e0-m=qaktSxX?8}s3SnH1J+UyXt@240REVmm*xgM2euJ!+6c4t<}c z+5XLMDU0GDrnMVa7GnMtXHCcRT=J%(xO$rVT58uzw1}PCbF65U-N3{<*yfD}kunF%ZqgKQ*z$2;k!MI*1e_JW zl;_iyUa_Rip*@plb02&_iUJ&r>FQWIQ~rhvbFv(4wUP&8NvY=Oq6K|%JGFm=IST2s zesGrYDxL$BBCPl;1X3(@mG$V2ko{3-sY!4BwJO-Px&-Eik$#Ha34O1>jQj!4uSh+2 zp81pRm-{*udE8r^e2?C*(IREKC&4_nXIZnpub_QNHSh7o;dBBNNb{n_=E4i(6Y$$a zyB3F&G~d5$Ku4SZ!3N|F{mTaIeBG$YQPWrr6CMbj>;#M-nH5Y9Id+LY{m%0H!nzO% zY*krPZ_|McTyRs$Hxq+c53~g5cmxjws!wKLZl=-&n8|wCt%LQi4Ixa&LV_T2X+JmD zT0PfB(aRNKbTtA&zPIWTOXk_D zChLg<>+`7(sh~JN;tl|NwGPT1xswe|MkggWDw0>V-pfn>t=Py;&V8c%L0+%AYtck? zL2Qw0Ey$GJ+PF6#ZlRuJw3r7k9A$+_S#OKQ|1vdvw<>@Pz8$Xp?(@10j04oaLDQ`# zsA|c$QqEKFV9}7OWLoV6t4fLanIncnOolRCEtzP94MQHexBC7*HYaL9sN%9+XLT~~ zV@@7-X00ceF*`Xkc_jf76Iuw|zmf9J*og?=7!5{^?pStKX7)%#6T#>OAp?Qc6|qZ9 zg%rOgnpgm?5#B$ciIrY#7L?8{ z=;85hU-`l2ranX16ArLI$j2z2;%sxL+lrn4)t&BW66y4I__srf@0t~0`qVhEk|2o9|AI)?4d^4jD*xgiY&gcv&{YMf}P zRS7@14dz#ryShPZ7v~`LMD}7D>U{-_*wF4r#2}RH*cuL!C+OZMnRty93=Y#zC?w)B z7$k0M<7HAqkC{6pgz$Nl3z!@#Jsq+9dXGnNVgqq8v5qN$3TYsddNN$@|w zS_0r=Ed3u~jnN79rMyC{?T<|yJlMVOB-o=RH(KX7&kiD8@{@ahzDotl&sTaOYPG*V z>8&rZaAmp&tM1sU!CHI!2YdYYmLK)S@N|EL#MbB+(8--##XTIhM^_neXe{ghujCn% zR8eiY{UK@~mH!CxJzR}0MEUbE^^y+5y%=4@^;DmmQm1$V_PD-Ug{q!k-Ow;}WU4lW zw8tk8cVT7jp6_B_W^a@|25X*Q@IKULMN*Y|Nb^e~mv)lyCi{=18a!n{1UT zn((wioy@{m+1s%3anRwema(5%9z;BazR*R7WS^)o+;2E^DECms@*W+Gtk49EB?gI`2mn z(-!fd&KCd$la68}Q*iY{efpBQ{97xN<1>(J2By{SI&oOIItq1(w2JB)a)2zhsT%ooAnZ zeWu`jt!T#2N*aKa+_G%Mj9vLP&jGZ+Hy|}q<)>aj*6AbK5&8b=3TZ4$vfMAz_did} z&T<&M{M~o_r7np~GF1Y&IdfU>J;?ITZBovn&c=rq?U;-2!k8c-iZ&?)yU{aTjxdhB zHZHvcPM?~?7}!>NzmjcyRmR;e;9NndIdcmw*neJ6blBKASA<|iE$%}U9h$+ZU9DAQ zhRZ(od-vzm9zkGm$M{8o*El3$!oX^}4G3ERdWzt~gqwKnc>dO44@033-+X>Iog)Jl*-5>b9y{9XmoF0E8G@$ zIx)Yvc038=_PCY;tN1wpwvX;4hGrLS%4cnfeqP@uMl7#SjS*hL$yG`8Q{6k7 znt~+SubTg?M$N_osBN~E@Te2(jL-z$?tFZV>0jX zXjwknv-RnR6^$ap_rFh)%Yc)+o3ln9RMT!5nOEMtDjw<8JB7*wu2R~hsE0&HG&0YI zaH>9}S+q4TjDD`scT`$B_}soXcQ?{zNaA%ecf2+k!=g*t0*@&iF^kWVXAJB@6{bhu zg!wm;-aV47^e<&g}3OF|(Jrww!mNyt}Zrnmb@MXQ*H0%BriWME+ zGp0E_FeEKGZdQ2e|usuI7^KX8a9UXqYlVlfB<0)P$3pM zYzt6nDN#0F`r?mK-~ye$2?d1#{cnIU$#M7|flwiMq(@X`?=XlE#Dcqkt7a>O`Lp9Y zcR|)C!MOTvge3(G--oPuEX62!$f%Jsn_@(7c}Q#_Csg@qwBJ6+>VD~~ z#a)^ON|gvEfs|EjdSRBM%8`w7JZ`fDLYvxg!1loh$|}a6lvOL1bp32RW1*<;iE5|&IaDydlOkEXb$5U7Ns-=(g(c7z66fS z{fBT$(t__c$MqLTSpCzSD;;b8KEpoqtD_r#Ce$mQv{TjAKA-$$A^-B`UA1XMH@NlI z2C+Dp(jd3O#@Ok2PfI}clTpcGu~U{*%Sh0jxgpYXHn(0Nk8}dt!KxFgD*1@HwWk8I z?WY2mC}n$ypErQcG}0E)HQNMwHJgE%ZYp;|VdWRcdbobd$<*JEeQskQXyu(+;+sG} zC#@{1M|I$pyWHhLSYgPvQYM3SX@=^QuTn|^UaVRq!^++W5ehi=lVFQ+IpE}fo#wiK z`G*vB*9M|l5Zwg%zp4-5Q1)B(tr0o35qW3kGClkkTtQhh2{HZkcAPW$AIG`FQuuvW zWT@x^C|RO3o~Z)qY*{~~f7z&sK;wkW$OSzv^I44Y*ymP28v-_>vClfvBNdYg>U zp!5rzY~YWC`hP_owYLFL{{RW%{{RV6BLSOffv^Mwmwdf8mB^l*R9TkA7Uvw#E4Cfk zU#lZtB+uJjR|nRuaHr%^$S9zvpfv*iL#sCbORIk02{@Fc_e`Jtzob_Q`yBOEc~!2V;U^~SBP8z9`mPcn&I18NG}Uca%c$KTl1$9R$Sc}gu~<|dJbzo``@ zol-5y6x_))*gb3ImI7i4!6JfkQY{~yaO(`XTY1{pA7)Mmb{p2l>Ps*axjpvUn!QGd z;73@GR$3Li*5g|Hb3nL3>is*PFrOXkS8s-X~}x&%idaiOtupe9gr$E-sa4+L?c z-Iju;6Q%O6y!Wr|yFeOXKhupaE*!tlmT~Fxtj=ipQ0_v=?}Br)t%@(&3x zSg_PX^|Bb)Ob1QB4A#adW(ABsAsir>*Sk5nTF;9H1;9QrU{NQUXc`2O->FlF!(f@Y z(ID;xQN)vzi>4|Dv6W%uX$RHz(ICPgL1URcQ4jIaw2idj0%LBP7g9x6?6QTDTS|L( zKK%W>e>iMJN&0*W`Rd%F8QZ-&wG1)!(6Jnb1qN!q_S;wjJD*-w)NNN+9QH3n{!WVmi#qe~w4#TRb=Z-hm&hxaMR`9_%V5Nl z%hQSe!mK=RFhc72`vf||NY2UJ4@3?FviD+ZKl_~2`8-%ON7CL;O#U;{e;!aT$g$Xe zgi!|DSyWRe$S9Qk??|Is=23@)o@z*xSZUMtG->N|8JZ*^scCsCN z?r%M0nhX&8ppmXksb#49D_ddf{%a^cdT{55*0`MHHpurjgUWGT_!_%EzM=hy+o8mJd>c{riW_ z$YKN=g)&fKM`A?gGqZ-r=h2HTC+69wJw!HjoSZ7v`L!6dHQ3PU&HJEI!b%Lql||qV zvsZkkh5OOYMQ zNU2MFUu0ihyldA?bKewF_KHs~igL>2Wx#6wnnQ;D4a1!}FM{|g&8iH$3o`w#oIP}h zxLDpq2lw+|o-JP7AIJw+og6f;v!J@dhNNtd{tU9W@+GHq{ZT5cd${%lUTLOBZw}P! z0z|$TLW>*n1d#`k;IaZdy*3g4jc*Qp=+P`tfMokTqEnt`^L4(5;+fCG>(2%@4OupB zgV6qmBvidNKJzOF+Z5hTQJ+BsbO4FlG6Pru?{D<~ij4@eIjqax`Ic9GKHf1>^NN%; zgnhi}GGEU1pHYi2f5)hM&|iM3;PEib%kI*8YSMlZWq|`U29gE*8=csIc$&>`!KX}} z0-Ez11DwDmsWHCq#U~9XI|s9-o8KnbK|ZFN!M*!UPR}pe_C)rTFCwWyWaMC|$N$8Z z-c>J09{`64E;g1(Agw8_(j&ocW0j}+oF{9+_F)s?8aMs=v$ewTRFLePXX5z5VNd(X zm|>et7X$L{<&yJJ^c~e%6@iC=}0HFZjrVJ$|zGy;5MmN^=mMXNqALVKq1j?02?OioYxN27&bnK>-y zj2ed-=U}bDtUlWnHlz(P_c3W}bvvi2Nr-hT z!REP$!Yn)J|k;j zt0MkxwE~pu9pY~gkLp&fYHgx#QWyKkU+V2iw$eg->tZp_8uBXfiiM7*SZUZ9>}edt zPx}#P4!?gCx^GC2e&olcX6-(M6i#>oW;0oF-I_mgA7XfdIX0D;O3@{?iG+npk4aH8 z90nD+l>aY+EyOrns;3W=RC>}yWeL)atHFi64T)xx_1BFpi6#=t$(c{>(g)_Uw=xg} z$s^3p8E(^ zh=_(#i40q@EEATwLWN9^D|#X<_3%R)H5c0*s(fPM!Az$mu3p>13Y|tyBiVy)%-VsF z?WlkD=R~%6YLoxb?wGGFJB3xa{x{s?jPjXn}uYjib(R4VhTSIKx z`>qXd-s3-69`5is@q~g=W&==UHJ(9X-_B_$Kpin>DcK1zQ7IN6TP-DkNv z>F&_H@#Xpp_rrB_)6JZXaB8uJ$2_QVRXLSc*;MQlB33>?5IZ|x+tM?_yv)u_8v@6^)<;IvZ7Klm|z!M5);NI#l)x)_79m{8g4MD7W!O(Zb|Yk zDL(sz;szum#?_2T$i;9MuWonhnAslg-d_G;;cb)J*@ln7gW6l>y#QkFcl|fH;`>&> z;Srr@^8amK{lCi<33WeCzU9?5d@8OHuh5*r6SXQd5r|bB{ehlcX1$Xh+$fUCQDqwP zGwN!mt>*8!a0-2=3%wcxx`)D(*?P&sSyr;cgDM_}M&8MxBW=e}E?u8$4>ML2G;d!!47?vf#0G z)|O9s38`@!U<>HN(xa5H9uzs+a}t`c^wD_Nrq29DV>N~bkuq5Wb>7q-Ips=F1m;f9 zvn1xSNsVhe@De`nY%p#rLZaM4o-z1}x%0;q+jA)jSST>}6&F1jZE`#I1O(dlvN|Ne zYlgaU#^3~>0AqZ5H@l-jGl&4!5GtaV>dCKj-PlIL0`ATNk8bTw?;QRsuznLq3tyJp zjHF$a>^IU6L0; z_}imiKI&y}QY*y?a-LqKbz5@oo_IRM>D|DR9daXXCb`yhvtNn3L_tp7i02MggYAPw z)Ue~{e%S|W7 z&j9i(I1HzCV~3I7c}1Ola5iKxQ6c^z>hJb`VAK~O+%Jj`VZlYtkNV|nv%S&oCjBV# zSJQ0H^SLHh@nyW@+6}1eHG?=8FV#cM!pKSe1`DyTWR_#9qQl)F zpUpLm)vP%yJb?>Zp}>K__PVX|-zB3YU8P^zjrch~*T+}r`!P*>sTFVKnGgL?QdH6O z3gbyZO)SeFzf+^2nZ>TjEGl5qB#gjjDV$q^{>HNqFCaum`&yY4oUtZOw}j$!-_xL@ z$>0^!lbO>Yc<(-;SvP(sHcBVEL+5T0jzFPVGs|5UAF+o{|GjTH;8{NG8F^e~lf0Ed z2xi$3^^CO<*sHc9%z?-bedam{1vrR+0R&%Sl7qc4A(k;%KZhNREms~}uAfiO@3)Vg zXZZw#fbHcZ+8Yh3J;xZ3NG{=U1S-wg#{@f<34gKSIp?9xNyF8N1~W!ukr(k}-!MH~ z>Gg66s4Ld6$9#D)uFDgq;7HjszfRwK;VI!Mf3Y>ppAO1Vde1G-&3*^2d0$ArY96Ph zHC2IDhCjGUYcrqLsCb01!t_P9J|n&c+#@PIS;XJP*}I<~^n(bhsOb5jjF$mF4kbFa z=Dr`o!qNj<4q@@EG^Qh7jwWQyrXxD_eOUP^OqlrVypn+&tnaJNW^ayjgV#pvtKD6k z{9G1zwMz=H-(<2WRP_5At|l9ny`sK`qMD#3)myaYA~*wpljYspACgjgD` z2HnD#zz>FuasFlOpyFyvp%;@D+nM)WQ(f2mn%>3L9z}ZoEvw<)mcX={|41aKts{c{ z{bsM0Qzlv*xufAzx3f!s&Ppm#z!62KKP=CeFX>pIezEW`+ckdpHO>66{#s#h13fgm z5>JcS_7H1C9O`Jdp=Md;F!p#(B|#Ac2nOujm@WZg?R8uhLSnCRLL81n<GxT;{ zzm-qZRvrXakIOBA8-POCOIr`bLCLXtgXWi+8h|chaR$g42#3D{J}6wU;Z8Wg-n~Tt8q&X) z)=Flg;JGWEzzjZoF+cJoaS5qFHEYE|NpcJ(f6JR;GHuya9X~v1d9HCgQawK^`d(A= z7V&=g3*w4-uDPz=P2{CZlbH(5guUg?E8tAs&Z@%y$Rlmd+fH@v-hApVMEIrBOQPN^ z5E5G$4+ZLlbjh2kzL1gha6=mA04v})1-mrcevo!PN!k5C7|~Q+K73({v87q`aS|?K z-@U`qkC>7kRqR(ZIB{B9oSY6m%b?G^aXQHZewXSC>4d&&)vBNJJCuYO<#o zP$-SRcIP=mW4HR_mt1IPUgbV@@+2Q*iv}wLzm8;aK59AAXQ@qBEAoql*HdN#`9(jT{5B^`f&6UTq)gU8iY zH&SF7%IvYivOONZYF)=6sx9Gvqt$XtdjG-E`N2J3=PzcjanQnG_v2r!B0`guozXE_ z?fSr7J}8b<^%i#%B6>@PI|-DyEBr5-?ZW?oX8S60a(a$X+ht4!5CA@|{ONT%sOz#W z-LG5v`g3Aka`7t}yq=}f%HxVb3=+H5dRN(U)`j;_oF3vvV3xmfggSz?q=QpnnOx#_vkI z-+|pl&FL{=2*g#Ee1k^tFx4$8EffeJ-8WZQ=!?c4;i+0w zDoGH+CI<#WLz!>V1?0W+?}7Avk)bmbTFflXd)J{^>R`*RXlpi>Kh1bMpxbKlBtdEH zt1CFGUCLqVn4*6*7RMsuz)Wvat07cxZfb)oBd`pNy;_(hm?^uZQjxa+uN*P zUjn;=Y=!Eif~`(hk_%1TDT#u{U#$DZahS;nQfvg|_7k_o@@u9P0a_(Dxt=N$nvP&3 zO?7qpV8~^I_e|stOhYK;C!5;VS4w(o^H1;uLcZ3S4- zeX=%+%{9xuxYdKaCoKN4wR-f@0j%;qpDNqD5r$sYkwo4f!vJN5-C4g+i~?Idex=!^ zWX4*TGP$XvPwBLsHr0bg-7_=3skGCIPE+>G7*07C43Ge%gv70C4WwmU##+@cw2U90 z)@=}bspM*2Lk0{C;j#$K!vPmzHV??%5FPcH$>Q4s5&1c z*C0qnd@B}c{`iFm@q5%lEl@;4U+Cw&FAY-TRZwxb@-8AiJ#Snr7FD=KdXH>m0vOMT z0eabUTr#j$r0v)kPA$pp;PC!?4r}U#yKK{~tGWⓈ6x`!{BHApz!zPk#?`f3ghN2 z%O~g&*S(SMSBU^4s2&9bovu)G^V~{wp-)B>?^-=YC(#@$5N;l6k6I{7&bQ6)#fmq4 z?1vV;?FrCXu4$vMC#o!E?q&q1$KcYnsl<)8T@jYa~?;4Lt2c(f|2EG+5;1Kf1i2hgWIxmPj2v&ha_m+jQlz zl2#H4MY!O?u)?T{=)+?4PhL_Iprrc3utIObZic7^L01suteE+Kkr3ajap{+*(LF!k zn(g(Ycz!N#Z5qEIi|uO0pSIt~(f69GG7u(|mZ~5m=5w7`+#c>m^TK4swH{9*xy3hm zQXlP|RGYHi&KiON$U#E;Q}_ya_fRO>L8A-Qetv8c;L0{~;10hrNRp z<<_^rH%}!G~{34R2 z#<}4$U}Z&+k-uy5<3o9=Z4659qSxZnNAnAj#7d38R?qK$>m)2cF6d;(rm%)j&h!2j zN`831^)FK}B*Bt~za+QvZ1~0K@=tlhJB3dUC$n)QMt?qXVd`?9PAdz0r=_cY&&$Uh zd|Q@b>T~?C_O#-^L%0yDu5*>D=Ls7 z+0@Jxvg>>(2rBD6eFakK^Ktt!wx~o`VLYiT@rh#9$@avlNYSqBd~pa=%)`J`Pm@X~b=j-Okgz#eAhaliolFB7psY69B<9ne8{+HD=&~nPb?lJet;#c7> z?Yv5+te;*=RC4V%%%aupn6?YJ@i$sm=* zd1jum`s*Y07wMG4e?vO!8TJKfOCHmhu}TVfS4>U#%LPg>*GOF6Y@`?nw;4^^OubEs zTpVJo6@*vDnQiUGnr!me9`+e*5zRhF6ZvXK2U9xQz$Yz!PTmFf!dZqV{RXRfR@SKpw2_HFWG$W@xqIE7%QwQ{AUfNpjQslA+scg7iT5- zKJ`FY?Eu(#tgS1`fd5bTFf<|-=#eHTxMYG5_17`S@}knB#gtJJE341JWfI+=Uk2gS zxwGR7%Feqcw5CObepr7%!ut?L?ZHoaEQ^VbLvlr%%f_-;<0}xpG#!1 z_@7%0U#k%L#L`9B|HIci23Hof-J-FzV|9{_ZKq?~wr$(CZM$Qe9oy*Gwom$f@2PWd z-S6JoRkP-gRqMyzYd!lJ;~8@dPoPMwI$D#cyWJ~p{pJ1D*_%FE8(#O!wyJtF_geP7TX5pQuZ6`(FtUOb zV~PIrhKfpbEyRAXk4EK4hq5%9RhG-6N^QMGLJJ!~D~n2fiUrsz4KQ3HMho&KQ3}D6 z*kt+$J;wZ?odhy!{Z=g{X{sQ?ww?nt{heJha!gL0J}sVZ?v8_Xm%W|8J4rid{U&`K zZtmqwlo+H!aOZODhJa0@HcnDljSG*_*_~sv=4_5C6 ztd<&HZnL#(GJ;oLu6oe4kWhmAKZ))B;szr>(ER zlk8*Gy&oh4-YkOKxX7DqkO9@`O)CB-=Tj0YKb}5}sSQS<{dI{E-;wOWuX~`LOD(+4 ztj}y4ob67UaxM-5U36G&KR#dWbf?27JJfgZk%xUPzM_pv3s(*#3ZNPb7*t1_r3&d8 zg^iRAYt+aU-wm$*8tH&Q6gtCMvy~(=7>-LN9y8ACYBc)Q;OOdh=%KFJz=>m>tMzyvCGhEclLmTWDn-wKrnB``5z4G>pLqn`ZBp5U9oVpTWM6!XFYTZpT5y8 zEgn|&N6lBdU5opwP<18@Ly*e=6gIAUQel$3M z0_R{f0Cx)MKos5fhWgK(A$@kDpQ>5}NhOyJ_`Wz`LXH{*ji`&p4-=T-c77-fvu9M% z$~`%=`gL{dP=5Bs+oesFTia3#b9icCs!Ah>x&b|%e$dj#!AMF7b4T${ypd_~Gf{uS zemy+HGt9pbR zMdZ174JiT6J;j=^IAt|JcyOQ!=g({gl#isK`%pP~8jY8M!}RPQHQZCF-1IkVPZ1g~#RMsl2`X)0yrvcG(6&+tixT z3rEsoF9Iz3FJw~M*UMiZE+DQdX0E7tSI0Ya{qE2gp5YfA*w-m9{PyN$<$W)FjXxLP z%G%0rW$n6ZsRN%5egj!)QExruWJ6Qv*tqe->PFV`JO0TZ>F$*1#jG%caRJegz(-dL zx7~)D3Q=?*RS8E?hYC|8=U+=4%oKm! zZjP{PLpOre1TE5T!y^wJPU4%|*l%G|{!^^!WrK!+gc(Q_#F?EsBh1&|V>EZV7R1#7 zgmYSIu%Ai~-Yy0Nn(DPXs#4aLY)PAAR~P}pUr<7T;4BpRecxq#n~TE9mY$=fp#k)7 zQj!q)^iUSnoB-zE=lc8p-DvVqtWBcv1o9hQ>b?!WUp7CQ98Dnyxvf1pE~#d z(VHM_uG4oI!DB-x_O{mC^}}MQ0W>+}S#hHA>u-1LvITK+Se8O0P=qCP;QU0A{N%vJ zb?BPqs{Hv|J6=v!V)y1F@iH`DaHh~pCl}Vh8gK%})MZgaaICD{K1bnk>mR3%-3HcZ zw@0eccSn=&ljR2@iJlc!P}p zcvI-Vo$`L6^`7pLLuZp)Uh;jBeL{GuuU436xNs`AIR)mlOzl!x;vJP?xSC29xfHV(*WLYY73p~8RcUcOB4q3JWpZV*Ig zaoSl_vr$kgNbpgDWf_Xb?5^)S=pqmi#LlD*6JIBx`4yoKf~{dhAK28YCK8KaEWoR# zl$<2(Hk4u|KwL=29XFfU(Vk9}aVSn+(57o61p1>W?$QrI;g|qi#-|-YfyWv0gaGr0 zOWbX+a~$LN>gOMyu=z)M*QcF*&zDoatDJY9H_F)h1%A$a9iEUa8Ga7MdclukiMZD1 za@UR?^fmr5)ouQ@MwMvtJUgPrcL+#g&;~5i7(x;$hYvxY##F(d6fUukv3z+}pacew zCQLe*GJ&g6`mB4?+?fnVx#d%Pj*}+uxMg?juXT5x=?qbRoUwA;>9nP?gF-8qF>zD* zgP={Wp*VB)aE64+?wq%;tsKz}6TI-{b*d1ChuMAz8X zxcg+U4z8-R-*m66?F~MC%rMDz%O5>bB>#*D?Xrz4c4g%y3$BJ5C~t5;J-QKx;~4p#>2m zB^Xffn1BSja`FI$A6qBW}ypc#?tfLO<5Y+9BwtapWRbu%avtWE5 zfX9;@pa%)-)2aG(R}q#%AUvz$S~BTtt;{8l^;BwI(}XqvX;fHB zb&`D?%-xu-uQIxo@{>E zdU;r+WxLAWJ9AyKNpe)jNiNegbT*7{!K`ZAwe`be0301DbWr=NoNZh4(|88-VY z#0W?pRrULAqoa&aAoe=7FrmS27BECD6E>Bh(KwYVgg$BqlutVoL6r%E@@O?%G|G@+ z5b9)kU2O0+u0QhMT`8YkpI&^9#8_?OW40+p<6)*GB_z&IXQp8cH8IBveZCfuP9rB4 z?(b_8aIALo^yrXYFXtmOFe@1j0!(LJL%)rB-&f}ZsulfN<{`QE)KJFaKt1&gVnqng4EK1zySnJRUt*Wf z=hrzJ3XVEs=f|Q45AO$>qI9~N(?@h~XB4hk_=CA9FS|p%VOfNq(*$0R4!ff77;A|2 zQsuy9Xdxgt$2?O?M`uje((EmW8NR&E`lAtCK>OO|fmJc6AGf%4k zMls%gqboOT!^D?>xy1#g*B(jKgwVAaeO&eSJTlnpJ?X@=^*tav;_A7KZFd7vUAN|8 z)vTQ~!x>NkK(IfFtgl^nt>PdqiXwLNl9TQCOb(rqi7p9@Z}pGYu=VJ0F3D7y<6&Kl z+^LRxe0HO3nH?Q_>25By*Yi)Vg`2zNCX;z?TRxp{r$9~ID^eyS%Vy-|!$z^Obc@S} zOT5k&K`U;A?Qr2}ZAEG_7uB7t;im4Uq3eESF;Z&i!4<-JIH3l{<6(^i`TqW00c9Ym z&}3LixPV2&ks>cDb$MZeU@4a;R8Vk1*Fdf@Pf#UZmk}-?)leV>u}F{%K%0ar`Rs!h zz#^33lyK&RxPp>HhQAq~+r{8-4DW+=x90xhyy%4K_Vw2FeA((;Y2`3`?|%1YbwnWs z?Mf{3I6f)yms!m)ZNtkr?7`D8luB=(CUCn&lH=U?y1DrN2f??b2iz;omr7+lBZ%Rc{dh=!zJ`0r?=K&SnAuds_XilbIRvJJX5#=loRenY;e##$>%e}cE_ysj144fV+ zMP4oG5wl`ms!4WLeL1~6GC%D3;ksAk@i7BZ{Ge=t=TOwh!{#%({cFY}_~#>5J6W7E z+i+dCbHm$j<|-Le5V=f|kTuTGg#iggL?vW~%#OS^8J@D`z|mOCn56XH zv8Ce^;IB^ru@OGO8_+6bg(L$5dE4t-SM$wN=|{8bm%BgLwlA)^^wDXD@}~!fr5s^H zmao{td{^iBKoGheqcM^2Sd973x0`1fxhXVMa93GYhnEG~ZJf5RoPyKfz7;)wXy6jz7#3EUEd00*u8S z;!T7CHkr$ULTtn&s|tPwoH;lc1pLn}-ct~Ek%wb~SSQ5CMs7ncmvw66HN6qE8F}sI zMyG+~<4Jp)ZUoZozKe)v)Xy~kgbJ%9Z~vA0~^uuN^P%M-Nr6Z|j9iokGb2>ozYC zCXK;Z)}{XM<^5sr5Atc)fMX^CALQdgg8O|l^RQfN0}yZ2d1)M`IsEn3cQTkRBA#O^hm z<(`;NWJm5qq}--pLb8Tq8VH1g-~Iw4mMeVx?Um6Ye6p<0+^a7oaejJW_eS&PCrb>6 z_z*-Bik`_7B|pF8L}P5iM0h-zZ~b$qy%({!ZDXb^d$JuW9ql4zE-se4ctsCjA@7a& zWnF0QjgHch47CdY(V2(Xr+@1CSWpW~C%+p5xQcv%JsW!uyEHxyRAyeIa_k8EF|~py zC>n+&8<9b75F?>HR7xt3dM(Rs-1F?E&w@l0jqR74Ta#Sdyzk*vB=+&2fShxfdn1My zYG*kyp8(D>zQVh=PapSiHGKb^^Q17}ltFwcV@PMYbV+WpaF!$?DV04EQumCqZ7z^N zPV&)Td_NW-Z$?3Vw#zp=yR=(sea`W8atg){=0jXOHdi>tjDIL4_!+soheF@L=I1i_ zsKa58sqgYPz-bve&=X3++{j`?%~S}d^NGyvO9{iJaKaWUutca7 zk4Y(x!PE~84h|T0888!V(9B6S1V~kyIhvqT06b>@UP3cza&JfoYg>@Oj!7Cs)P<7h zT3q_eOQprxOaU`ZAeF2IZ3upePv8XUiSbscGd0r^%O?2DEUf%wUgR6(4uCibg?5>x z4>G4OUvDLZwukSQwn{WiRGhC_VP^#gZ2c_yiEK%KVSW)n9>zPHtuo}x$PHxvD%r>FTPDk#S4 z?~GOPICCAoc*W;0tkXEBN*%1wFH^SEL*$*FGmm@(^9(odlnIGATwZ5*#v}bV+8z9+< zV8aGL@>3G=VP!C>CF>#9gpAVx)TjjzAFLa20|$q?jt^@1|Xau;B(uILJ|&7}dBy zs0c3}N=%$j4CLn@QSpQUU5zs=>vJB=(&^AD59d4A+6U7f`InFS67hs-oP>Si@_J0U zBti8O31fKUbTfM5e72);c=0>|$~NM)q9D=`nDQ!Rv1)}Mtn+J9NypUuZ&Qf9@+*ghFx)W#nq|dSKwt zZf6sazQm}Y#}upi=Oo0cpgt<=kc~Iru1XEtzLVojM;(C(kaB)8F}L}CQWk5!=`S3s zI(fa`t<|V`zTUmqqT+)rWF}VlsK`I=ZQxj24m=sy{!+r{KL5nW3ePFS@l-oIrpyJWb)M{lq1*t z?ow27%#T6#q@!*Bi^Hv%|2GcL6aI(8t^R|Gdc;=;l3NQK$!m+9g9Z=n z6*}crFwZVE*zra`Z|PeHUg(=GKm2CEnLi9IzsmE`oVNex2P0NgD8H+A5C5jOhf~C5 z?9}Y%^2H|Xt?QTT(}#t`mUrK^hmC+IgcEweFG`iGD4UeehltN=azPiJ?GAPxH))7# zQimC$W_41UD3NmeqFXQ|Z~_=UR7nBU({!%?WRwHR$FU35Il4J?TM5W0KnC`3-o|v3|gG?X#ny_5bDe3r$h$ov!f@L@j+f^7Pr+3&&UyS z790~TFyhQ9Lf8E1nE96Gq?%nsNMg+b_0HgbR45oS(=5HaD{xzegg+!WO&z{QazC^~ zG)j{}UF0-N9VADaObC`Unz=MAqK`K)$xGE$s#Gxz!hGtfsbIx~aT{wg#`lF7gy{3P zWc=e(49p?H7$l($$n&$#@{f*9fRC@Y(?luyV-xJf&0`3$;2npx+nL1=$SI+7YCN(* ze%5rNf-xaYP;;lrL+FP6+58@<8oix&cRAMC|8>%dZRxp9yvx>o64gE*3}xCpG;DZS ziwZX($a*Q-nNYx;-$kQS5D|8#!D}KZU(2m=L)HA`5YVi~_f0`xnvo{ugCbhHzZRB0 zftA3dQtFS3%MOn+FA|BDq8B6wknB!vr*FaKZvn1La|xheTvPBSj-6IHF>#&f(enc9 zOdQXO!io7H4XvH&?OdCB@r!B;jc=XX%D&^XpFyvuF|SLtV2BfdeNU#=(6yrZ zz79ZrdDK4&9zKHrXQ~UnM5Xkttcp+u8mO5Ye#qp7fZit~6skbOHB2Sk?_G8Qh z(4SF-MkjqrAMv9*{*NfgqGa6Is1ox)l4HUzb@D=@c!%!=p&SlMmvJuNYqI)scyhax zb$KiHsS*ccb3O5C-uwNxZXm*eunRfti#b=)(J*2gm5xAyn#utaDxESYMN~&%?vg_t z51OKZcTBOklMNbHLva6VNc|IXI3aR;&$A{tCj@u+* z-NcUjq`GC2a-dyU%&zOOt)W+dEhQ=ddCT%V`hxCYFY)#!*f*OIqGa|utIo1qm-_2e zX5?=7i&$wdYy* zM%qiFxh-v7du3}G{skG95IR2Ojb6RH`n$E}988L=@jy{vtcb;A+-f%~hDR^SUp_cC z%QyzDs25P5=C^7(en?kxzJDAI0mV?{0OJ2#rU~%Cu_$6h#2dFf4h_q&7j)Fsf zBX$3!X1;9s;dl83X1lxeGWjy~xTC-Gr`+0|_XD!hOhr(Mn`61b+GF5+dosXMxyqo@Nbw9#&@A$^KrYLD{bQR3#o2u93y&3>IPwyX68r&?iRr|p!4si@)gn&Y={7jX40|JQNVH4UmxM%j3?d7r=gRNx;NkIEs4@4-LeTVeN$C6iE7Z6=aLW!iSoFIp57!HBlm69xdGO+P%iDuCGpS zyCWklt6i|CQky>+*)Ky``LoA+Cu|<9t@4i`7IHjl46ggIz2t09&?7jPMiL-POHC1u&8%yGO<|N|02{U}+aPpL)2m>bPUtNnc8cfj{atu zfbVw-kjmBvf3Zrujj&$T4UkW;9qj<1*w^9q0lV}km^mgA2C>1fZ{2qrpnGp8OCwyS zCP+U>8d+83=0EHDxJ4(rCtG|&wT3#%iGPtQ)oOR~V1}m7>hgvyII<;9L`$(ao@nwj z{k$EQ;^;1ClNy$U<;dc^QbrJsSe7{4IGo*$vY5|=7PbVUKN{nHi!te+Z@bDu6Hby3 zWDxH*TCI~L=m_Nfl+qd&Dyx&Xzl7PVa}u!Mk5u}E6cC?pTborv5o1IU6-!G-JjX*&+alWoPpc z%7Rd{C}-5N4wan~AWe z-2?4q1dH>kFHf2T;K}W}Dt5%1d5Zg2$bKw8kwBy;oYB(AOqnYCrkPSCe2Yta*|}Ey ze8N0s{31^VV%RWGDucge64owuXmgnbn9j?f6cJK1AG1lAS(13zui^@lI6}uY`*HuKR$aDc~%&`E{yn=9D`@_6kO8p#cGdF9ZYWYCII%9=c?l@8va2LY;>+SKwsL4PWxjp5t4Od@9 zXFLc#kGOGsT!dDyzqkJ5(|D=2)mh`In62-`T0DCi$zld#iXtiKF-wYALkF=-Oy4W4 zrorSK%RKYUeIpNqhOf+8nqoY5<@Q4gkY^{-BPOUPu3qc|b^XYWs}JQXyTd4uCY+VM zhgIDmUSXl^Gaqb6XxD$e#suj$RnEI2SQEWbRs2Nu5b>s+YffOUneWc(Qb3I^HYrZSiM28 zf0+Vx;EyHq=o$ocAGapWTSsQrf3^0{MEpEB&UCrq$Oy+xi0NhmAqAuf=^^i>3(Y8K zc90rJ7tIw#<%_#>XjrJ9C>_2eDFjjq{0(MQ5*|G=Q&maf5l8zO;$nQoIzm})Tw$7i zBrXPzo$8<|Jjh&*e=hvq9+Im5gO}`arbM?bIoj*z2TiaVORG7DB-W zuuFNsFqhaLv_F|yWZc{bRl2Yb>pP8Mt8K7*23Q;;?<+Dp_uQ&~4_z(@%M@x4qjI== z;w!O>=lp>w?G@fH>o<2YCgO}c%c`(5R{b57%Kj4f7epe<3lIJ@(@$tZ!dnrk1g%36 zjq7Fmtgq=cHD)a98r4|l!9w4Ow)ZDUC={*%b*Nb`P-v?QeB#=E$e)N0{sH2E5OK3K zFl>O?pzv%MCN`dkmxkR=rYeB$n-)| zd0qdNOXNzUPSRP&`=8kHW`fx9v~{a0@GbO_E4uA+$oB8F%M&zfM1VKZQ)SYW zFF4ZO=PRE`&6A$j&AdyPNp9gvLz`bXvc;z%dmE~yCHSJI05)aOtDx8O!T^YLBYe=* zc%nypCu75*C<|!Q{%AKB3Y1eV_0{casWBr>@1^IM<>{)s`t_?SAHlXm7lF!ZSMhYk z2X#eFaqto*X`|PlCxj;T*B#1#8T>~kU}CX`BgX*G7(pBSdI_*SifIuj@CZ@*vaWhB zVSwWJDDv3?OnFy2aA%I-88lP_8EiAfJZXQ{=u&CbTBcGWI1oQ^>UI;J+~tfpGutJL?E zX-IkkOZ=uW^fT$8|DJ0!1ytcYau|+;{@lO<0zUa7X?b>aeKNJJ6==vXXaZ73A*tWs z(0^qKNTHBWwya|aNVBBuk*V>sfs6 zqT{)`FbK(<1ujutjtXnb?uZ}lh#0HS;Oz_c`U#>%G;Of0y9m{JJOA(jJPRdc$okFT zd6WHRclbW7XW?BSKMpd>j_IghF#BT;_7e1db59;$Z`&9_1DKZ{HjtH{1)EdbbOuL_ z+C@jR+4R|DpXVj0ySEkPgk{m4o-VRFppOct2?pWHt!G&tIN!MyC?Qj4q>gGFDYa{? zdqnSdW7zOWtQ~lx0LWfWvdU;#uRUeh##5NT%UHZ_Rs{J;66u3ElZZW9IGR-% zHG{)7axzHre*s33$z{PZK+ItBC=?1Q7zvJv{Yu1&0;k!HQ^e~i3QZSqYf5K1p9dbO zO+=(+q;a4jm@N9EGUSjT1)l%F?t)E}K{uk$XgJPm^b;`*!YMo(uJk7M;}3x3pnj%Z zU5W3+dU>nCwe2qCmvU`?WPOac7>x)6C>*(9~mPXdoWonRsQEqM2IGD z5F>)nc`j!kyw(E-0YD8dKnrmY`LBe634+ui0*8PZY#+!95=0yT!X7NrxbIVn`F@N6 zJBxWN=>ial?hK*%$7N!b@LJMY=X-r@dHk8Mn(OVkptl7(*oLr=VptNu$knZxPV8sA zM{@W9Z(umrX9r!1@@s8(&4wOAEd2ja&0_!OYIaGDDb)&?rZpDGrlNWaMifuCs+`8& zz9|AY>$nu7EZUMUYsm{YJqre~&k{I>fngwnZ={$h;maJJ zD=GB{k%~m0P8G?#l_r&pl3E>T-;Y?7g%68A$kvm&kf zS*;dx5=u3kdA^EZo^mZKU05PWhq=|We?kQyUR*%iRL?iJV6`B)tl@s8R?{UPZ#P5d z*`0>mM7JYKdRVwUNHZL^27#^uoSlIwb4CP`R{-7$NXnMxr| z5cvu2X3W)L-PU@uD@A;e$aZ*i=2gtj=Fl+_{Rb-{y}6sz#@COL1KH{C-&L5;p<_D5 zX-%7|vGjN5^UNJJZ%mpIHoRaOL}Gh1RRYrT;rbve2dg$niNRjkc-ZQW(debq8qCP% zG{l;@cw2D+HMZ=co{Q=4FKt`M;H!~ToKPDf{MfBR1QyoL`+nXJ$Lz4Rw?dL{t3;5O zoTYiimJ^M?Thb$$w%_v_-J{pLSQuo;U3b$=+^Y*E&K9z#YMSldZ~x340u=^V;ruy^ zM*W+<)8<*H*QEo=5sX8)3#*TpV4rlu5bmCcxBc`-1Jq5Fp&wlziCD!a;OOx;0!V{& zTxI9ALWc^%U3sh*4|>=n^bRa`DnSg{gfJsYq%lE5#xAWlFb>O(*2v_2Az5G5`D^QG3$F^vSP-y*DQ3Dm#&LudXKBvE`i|IE&7~- zCeoRBZWPH-3fpZDa9#ao+Lx~@(Fv03VMSU54vRUM$f)&?i^(BmL|y}@&jW6aJHmyQDgw(5yl;W?QQmmfCm^;Ha5HAp*E z_6w!;3&r(=JTRGTR@Me{uzM`4_Yo z(hm{8FLZZoCol$>X95xb7q82*M{@?OA-=~+29`Y7L$w3MQ-I-%G2ofdi3vyts8bAH z$Bl?TKeF!*%m{eYU@~6V$cDTarlw7P?B!2|e1s94oWzn?jK!vV4q7gKFPWe0ZGh~C z|BQp*Cr}&+fw42e5J+4C5v4E(*N6sYs=A3xc00a2N=ZF$)q& z+C|%JODe3qQ+^#-$rQ=v5o+-mOEBs(pJU{Rg-u%< zX(4EaCa6CsY1$xDxQ#vbddaD?64#T+;xZiT261`~3JDgHi-3mDX$0vnv>E5I^qNG= zLsX-OoTG~3?64y~wys%Js*9q4#NW**uEpUHJVVK(*iS!ec;b(kw73iWBTz2O*%>O} znX~A1b3ziis6Vh}24*>FcZrAizILYOujQs+y|F)vdg0-Z$)ZJG*SG1P6Lunib)q)|cMYIPY_R z)G+zG$$f|Ioe;z!zzo$&#vw>xk08i!kajyuJF4}Hs$Y`7Nbkc{n>(9|QUx3^8L9rp_w7T1+#)PaMq6faRxFrG!AOg~oAsGz&#@3o8 zwblH997BP=Qr~8obC|X=FFdFr$dTm!Vi)u#y)}^O_hsuIXa|E&lM3>);-j8thLPj4 z|EBeW1V#kGo4~<4|6T!j_nk5IuQ`*=8Fbw}hKHSRM(nX&vXifwPx8+Y7m1vWU&i(}+pq=fq;Q%IPZjW7?7TSdx1?h}bg~CScl; z^QEe#k?8a>;;%%!E!XU2kc>x%YArHAX9g)1R+^j%_h?s`W@4^MY=Oe*U) zjrS*qAfSyJLX~LxfK|&x@c2}B3~Sriv#WUGfa|e!xW~T44mqPH)c1VGAMf)S!+T}E z)=N8oyCU`=uW;MZxI4zDF(Tx%4i+>9ioM`rCybD66JaV|+p_H3CQLqAP>x&<&;c~kFM;dUm_9>{fDsmGJjgaw?c-k> zuidH2v%)NlF}Q~YaWSNe)W`ifgdxmpEKCJ%yL&Tp51e%9X8VX^F!ad=q~TtDYF66* zXFAz$i%UrFwM`yy*Z_?U!`=p-5RtC_6Olpr z6(V}%#1)recmnjP{8P`FI!LH=1FbM~5F-h!Qn5Q$!~6oaw1EI}yOT_NBzm2Q9nKFP zXTcQ7P4*|BT@!kRku&6i9SM`alYNy`$=oPZ6%$B>q98cY4_ zMS*!!)+mzT3BSg^;`6fHx9t`3VVuPUd{@o8L_pEfWzn@iUE?st(QUoM7+Xuxm!-)> z_M>2e#C7#&ziSYW% zi6O9kiD?pFJc<{ML#5vxuUu zABK~_U*m(;=JBIAp%VXADy}{>$(xhHvtEYc?f52+-4>rKi@+Q4{NPF>}^I| zCu9vd)t@&^Id=M|&tk{o6C%<6xP@>Hj@>FFr!gI&;`35+IzM6_;+vo0JxRo$$>8Ge zAQO72ZV+4zvkq0k()y+>l?~{?a^xU>gnqx`xyDv%j9%MsZ!Y)ud9%%LIj7}%&z+F~ z0zy!Wppun%P|mO0tK&iqML`b~m5^yR;rM&v0@QQ|)1Sy=-q$5i_G?`wV zhXm{}h*|uO7HDhMeu}1N199wZBVSOd{Tcs8w`k*OSBW{06uphZmIti~(Os^8VDYei zv-xYubN!K)1bOPAJnhDBIP=bP4$!~gH2^E}dBqOr?qQ?$;|VF-W%>4om%Hqk7U6xVL@Js+N@-LU9&fb_b!*i~Z`Wx}Wu!9~K4T`~ zRzO&tIj5p8qonWCwd)6JH@>b7Zu_4~w~#gwO{a9f$b`9t3*lit~q3VKMFCoyx2(+{KHWPS^$y*4F0Je^1nkeD|zrtL(g*z8;B6gRiXL`F#P~oJ$omvF0Dx7o8DJ2+4P*XIL116+ffY@2ui*{%?%!Musc&zH^Hen_uApCF;K2j8U2)LC8*uw3DjAtK z>Iu*cUSL+3#dgfNv?YorOe!BH=Xt>dSPblOxsjt%>OYeD`6;v>C3f&4ddaFVa{Z`D z6?afZ?>~kyv15*`+0hkr-3D%cI~g!q0$&Wz*!*(rs4FoJ%f}Yz>xIot%XaWf12M1= z9!z5OX1ifW6%&y9K1p~J5k?XF0&OS1RWJO26l!BJxzYbYYH-D;^YlC5{D^=vt+>m zE-&yrKV`}wo*F=ax~hWxm|$pKOueB}K~X#L(?^2I=T$BzK!Vof%={1*sVt4hPcw^e zNXQwcf?~e!I`kH`A1yYIT-ZJ06R^^Fi^|{G`T2?pbju4qnp>9D7dNdHT+H-5YkkK5 zb|c0q%Zq4>dvk=Tt5Qp+TOs?_AYrQ4sc->j4ZMqGq6rLSIpOz*aF&jKTgWQWd~BE~ z7dVrsC?l_l|5-@`$K10dxYD`^HWIngx+-u1;sC}={zoB4F{=tewmz6ruI8JtX*#Dn zazO&7C&R$;z-(cxfL#4tUQpgD9PgB)SO7!5fGpDYnZANOQiB`7pTAH@@q9wJt3=2# zq{BqMtO&BX2wQ6pU7=@{nfO2MKR+(kb-g}1s7#|p#Zm?U2jpn`j(F9}QDDS@C=oDX zD@wrP?KDBY!RZ=AwK5YPRE`NGa>%ZlLCN76FJI1W~n@`Pr+1Q zsX}D7LMh!`LY==kt!(Y%KfID}*FO#gMrb54YXo3i06E@hCmNv+yRc_7v zr+}={V>3znDb)nszxhGNV2c^R-@%0&YNXzwsYgvLS+H3>EYq7zr_u2pq%w0E(-ax< zQz}q=a~SP}lS9bLAQLw;E5l`IxbAgx=SM)ulNu?AEZ8TDy%G=Co8n8;+f-)qa_aV5 zYU*}P_Iy3jUD-}H($jSQE;sO~VY(^WmD0B$QmE5en=z2^56M_h*wZ4k-WQyKZ+Hn_ zHL*t{q2DJ};3sxQ{KZd>kxx|nXfbM(0^jn|=+E*Xp>J8F@qn+i%;Cqh<#x_hxtll2 zd+qyc^cvUP0+%i8p_$6FEbu2C*k`HL8b-|5JQylR@Ryhm$g}OYT=ER)i>T1K9|Nu0 zvG5jDO%&+czv;`N^lITm=zROb=W(Su%5anK>aaHQBheO|x%P!NqI+hw1?_ouxt5#$Y9DpegK`0-MA^yqP7_{=AG*CaW+Rmhx;l~AT zd@(?-9!rG2&}C%CM-Dax4!UMS&4T&3jCXS9KeRD!!hB&Zj?uMR6zw*}cXB0N!C#-o zjn1(}%FV8hW1Y8rj;*q+bGJV`SK7K~+PRW(oVblk&jW7EZbKBP(ZTx#o<)M2vS%mj zGZ3>+C$}lT+8p0L-zsz9Mx=$Th^$BxmjH$LNWvKZzk;@#$9ttO=NjIxG6H*o9M|SQ zH(N5rj-C$NAVNE$s69EHIGapfzqLQQJ&o~rXi(+j7KtJ<`K)*6rR_b_!va!Ke`g@b z({CndF;2v7ggt0tmN~Q@*&x^%ppmmffmhk+{ zSFAG3#`b_XMP`uD672=Vl(mSV49ivNSD7aqW0PsM+L?ev)n%mWcsDDGg^9GV#N+XM)Xs5#(&-OAMdVUPOf zR)#0Gow>Z<)VL_XGBJTr2Nv9mcpCG2IW4yHuQFWr_(Em9KV6eRGtp+ojd>!rUFqP{@*)%1_@ z@SIp0)GtGnUxwchbxIdMgo?96E_j?FC0UEU^#dS|p%)B4E`WsXr#hdXF3&Q&OxqZ1 z9rw0Zw%=LkF4jI+YFVCCaHen9k{1Pt-qjC7MCO{j&5-gM!O6m2iadEoeJ(Ki{`_e& z_-$VGPKxduWxt##oiU!J4q50=j(!TLp+5Yf8Qi&XWWpF^A*sAVy%r*x6WXX*tKez! za9MRzYjm*Pv|1^js2-r!{|wEi4Be;R zHz(gr&ziIMlji*S16ryNF8H?N+~cPo7VT^3FczxwGA$mopXwia+-F|xqXI<(D%54^ z-Kzg-%9u;1RwUn&SM1P$8M-tS#tT>m{GY#E1=Os&z7Ed}Bn$p;2$eMaGMYi#4y|O` zYTP)M*Th+i%SGG;d(1#jrL#M7WDp%~4rV+;COX0iC>3Ky0uRGhSeRI$9Ije~kwhBr z#DKhSJ;D+~9vBQY#F&Mq&@0H#%fFBMB6PXD=11VyHJkh3@p9DeYZGjBZF7U;g|3iK zAiB#K6hzTbJz+_$$=d{Re$d7S8J#A~#AEt}1RzV9i~uQAQUUERtq1XF2>S?ONF zLD+RO{sArvPcP4pIm>kcxQF5N>IHdq1_f{b#o7KPY^!mK3)RS@MTp%Zsdop^BoqkK zW~SfO{m*)DEcWj99^Uu%+H4P+Psiv#MIW(^$AI^xHS-!DXE6iABdnDkZawPaLOfwi z?7!S@Aa!~uxX#8Sj2R<>sj4Utp%+a!Jiu!GbU=Mur*-Qnf!BERyfJ*$e?kTboBCee zoT2~smmpNY-UIOlgUDc|IBL~ha9=T_ARyjkXRXLzd~5V=}$s&ga46}FzVR_LW$_e zf!F7|{jW~iReU2en>aqZzsle3?ATZKK9NR46r;^h8B!jn_PI?LJWkJFfk|W?f#Pyl zZp11wok?-bZi>fL{S897l*8Y&tQIk3izwz;6zCEZW*RljfXWf_XooHbS^|UWHUn~c z<20nf=5lRz7A>PNfC@YNe*%*%VPIgg{ELA6Y&iay50AIPY#Yx^ z>qnlg?**j;a-fmG%zW)00)p-hVm}n?ycZ)i<3g{ge~`&vv>ZAb35IuseU-~EI0o7m z99>~r$Q%51lnryLIE~w}cbu)cl2w|H8y(Z#>o($V-d_k969R|}UIpLLSFAWUkXBlA z9R_^_TcOH(EiC_1ll{t!6vSL~iVsKQm%JTsb@?mSErWSpGiTlbCrs<5J0T)(&=p9P z_ieas>Oq!gC^O6BoSR`-Y4GyL|2H)`gYJH*06@r`$fOwzi;=uG5=NAz+=piaQxjKq|7`1Rux(&2gPx}*ytN#f!52`a zhjeuCoCXQaT*Wl(oOb_PG$O}EpXNo({EO)WNT(-Fv8J#2K`ZOLCV!ogJDsgp3dh9Z zKat7RhL&XID&iWCmSZToHa`z@_T$B_v+WBg#=)NXvNaqb!QLO|`pTBaACvl>gqjhK z_24Yrs~k;{1h@+C7hJGHP?xqsyye=I7qs7bS2}+6anlF*Rx(0q3O56*h<*N8npU4wXQJDIk}BrRA>NVM!Np_S&b7o9$l=b2ib z1_GS6TfpDUY}KwRjxdQeC!S@@ZIh_3RM7k}YpPP=HO3BTr5I+%$aG_tIjLH9lkezu zkq;YBE*eqK`T8@33p$Ir2mO`ZEq|I7^*-@%M0hThS0hgxQIMj|Vz{zM_Pc*gFc7gr_1ya|YMGXhbZG0>V zRkW}bh6L#!Q-zuEc&4+6!Xd831ir+Qk2>(t+Q=Uv|47Ew3vVusDt zW&woom~r5xk(RIeJSV>elYSB{sn`m6U{s^mHtF1{0MUg4&|?+M#4L71;+6b~>`CC- ztQJj>b*c!OiUr!eaXf~zJ5Pm3s!3&k@ANkb5DOQPVzE}xv5xrE8z#OYgqTO*fOK6Z^PEY}fgPdU|Sj19G(nFnn z+j5ByB1fpDP&+7#2>(9En+G`)#&$689ezAIS{b=^^E#-^-6dX@cl)q#_A>L`yfUPs z>!BcFD!2sp%A8A1i-%wtcl|7J}M5a)3r!MLA zRB|T|{v25P%FMz#rR-r2r9%Q;BSd9CRUsX>c;PJ+5^gu9)}zJhL!t5=nikbPW-S;qCzqFFpZ+b>uye-?|R$Z zByR=Bybbj@Rj391jD9#-J)6 zflhb4Ho=f7nYl9Tl-QinmgwtuBQU@@eaGTqwkVj)A+Id)aWzx)6OBSZkfeNsq?z_t z05q7IBsB4?hX{g)F^PsDyD9(3Nf-1h1cn@{;RB>3jLFPjzUX+89E<@m`y4XpQoC{c zN7(LTAE`uaICb;Rn|Rp3IW!p*I{1PZ3|r`#HEkvWT##Mj!1lQ`#9Z40}@PI3nv ziUlKWq52V{jERw=Hi;6$8S6CgVWk`f)O}b!HsmEkx})J9@@`?~#o0m&0<%Ue`C@uK zk43XVV!5^WDmh?|u|cR@Qd~I>ei2L=LB+LG<0pxMntZA# z(qk21j(stbcfyk6&!b;{8@^L>-CeCDvYu4@;m}-~2nU%uIaJYOMHRpeW-;>L{l6#aT!J)(PULBo$g& zpWoS(J6Up7lq1y-K>F1K;XB~^qgWgP>=uKN4onF3NhKgj2VjxpAc8f zZS4CsfLxXgPlZT|rTE+c@z@!$h>m(Fm;EnT1Z9sem$RhB^nr$>P@yc_Z#Df&jjsa( z{`0-O8s8D~%dN9TfqNtCTl3Vx?fgf1IB5CL*qO`~Uj1#krtj9~ClM+AxAr~@X3XBF zuk)ShFHdEo4ldxOA}6qrm~Zj7yztp~!&&U3`F&yBb0UrK?3!Z=j30L5>g z+Zp3uta5!kk;h2}DZI#_uEim10hTKH|4{NryHSBwFvU)b;w6`3l>9wLbN@#oGo9{w zeJ4pz1x#dO#t1SaL35D*Lu8T~tN)wGEZrBBvc#e?#PlE&I3q#bH&>aX_5`=_OSXwF z*Lj3&&`U15(VBZrIfwA?r9QvS@L1#Y9`R#wAln#J3QmjlB42uPr zQoPX16t*8Q;H3p#<{m7|q!}E|D~sJ07@jnSR6-1xdU*JHDb*`TA6AEAZIS)II7;Y) zIAKcW5+Inx?A|XcP)U(I8MOr;Ge>==nC_>jHE>ZF{Z0Y2K(E3wK_D1rjoR=g&zHGf z%CWkVCxZk!830vExk@a05ZS?C;?ZoR4z~5scO)UK2wY-%VN$4|OyZz&(}d$$3ktNC zL?da^`%m8!g-^R)t>ML6`JoyNP?{pZuhdl|dinI&+N2YBZ{z24B%1gbLbzN1d$-HV zMQ8H_JQbmi*4o+q|EDU){s&d*`LO|s@Xx9SxlKwHfbRaoVkCSe08CN--B)lV$W_ZF zVORlUL$FCvuK$Cj9COi*JM5Zq(Ik&Qv#qHDge)iV@g{*;%zw7HqbdLoc##6$+x}z? zEuLf@BWDg(R068(oH>fEm1-rclVuhovw?U}*7JL8|C0$&8{xKQAGvFJ+GTyE{_ikUF-nyR zBU|&JWzoO8iJ)egThzEd&YR7y%OT!z|N5N~a$j&g-G{O_ZT)^r(5Vum;JRtCT5=Vh zLN+%R%esrZ<}b-el$0vD85c)z2__i_GRX_qB4@vDJ2`Hd@26zb&4rV=C54>hcsk`>a{<`l&s9+vzeCi!luFFEZRm zn@2sIP|{q~ivQ``{Wm)ZoazR>v93)#>6+flVMqA~JpoN}Asfte|L!<&wp6b=+lT?d_N*KS{M0OzQ->X)#tgch0UA$J5e@;}bl678 zm8j4X%vgz&te)qjils<`znFd7jtrl*OE1{vAuhuIq&lB0NkRCHD5>4usxy)z^86D; zP@>tJ82XO`?}1NIPENn7IXdt9v@X&dmk%yR@9rlzhW8x0v~xHpiqMj)DJW!C*ckYM zGFX^$%fideFaa7nRyc^?xOg-UxsXJV)(!vqX#G|-aPq5gkRw_j(G)%LVS**n`g+pJ;{Na;&XeWWV! zFPm@W-G8%dFGx?7qn#+eQb*zJL%#1jIV-$;dvxBJW$=teg(wD7uATp)T!|iU#@j); zV`V8Jjb2U~XXhk@czq9jZC5PbeD+{3!OOU;6G+quBu=PgF?{t|F>GhPT)@vM=t2^hGUJr>{~OO045p4 zKdwj(#?T@Kz5NaVk!r^tTkbvt4PPL z4>*o?u+{$ZUtLO;mb5i*-~y}2BiCJ?^Az5uTL8#-C(HI#ACXjKC#&wqq@(z!2ZWB9 zy*sxbNpUg49|tYy_9yEEP?KHRD;H@!XGIeeaS6v}B!&C1ZgoZaH2BMuVHAyfxM9s$ z(h!8booGMZsSj14qu~@P>;+&KDsaScrcLeYWwFt!L2|$@EL4`$@boY* z{>`8j0Dbt2(d8B1q39ZZLA>hQImgi}wr>cm5v=NnjULrOXc~if)Jk4+H7{YEG5WQ` zZv($MjtkE%1$#xynU3$yntwB?`fdMy`&y+$JAM8J(e=T7yX;|Dpp|uW!}4KPbH0e} zryXmy1p&a$&x;P0krn8O<%QLe*oJ7JZSgpghN%CveU>Y#Wz2-atMxsiHW)Q77lQpu zXMVvIlMOdy&L5V_cLlu<7_Iyy4!cieATYmS+GU7y_a8NMo7Dk{FgrG5`Z*Yr_ph%#RL2P;)BTlIn%_nat z$crfiPb86g`C^srX|dE=NwBn)bPEMS2m}#OYz4RHTWmA3N%cI|rFCC>w^RLgJyyU; zYkzaGhQw;d2;2Q~1H*$iH$jlAn5s!U)8y;X`Gwk2#|shTgfXVYUB@dS=(N<~y_$&) zAF`&qqWOl3=C^pf0BeCKSL9xeJ#Mmj1OEv3oSAA1f0jT?_iqU@()2dFhVBI5c|!u1 zmF3!#f2Z2JQ-G%$k5#IKu48j;m*q*+%S}moMoN??HWW~pk;(hCE=X^q1op2X#!!*T z0gpySi5+n^zILQ0?upmT}^KTjoN&t?}wf^vadDgu-Dtf=x z^Y^I`9hjnu=r)-K=kG4rV#@c)2sKDu<{PwlchRs@095WrGHR!WiUrVU=0(%^0 zg?2*>ulX?sI`1&=Qbmzv5j&t{Xb*aHJP%YS6+{p+8g_99ub2-=ju`yy->)0W6zMBS{PwhoS< z{p~rxM_ek4U#xC76-TeXDnh;nY&Z|atP>_<(!q!x&I_4y< znQP_rt-Bi$yPFF+MV+{Nyl}dD9#3kSZEU-2Jo!*f zABQc#!Z7cY;N0MaGsOW3(8QUmqKv+x*>M*1I};B`hf|ayK;c$qWG>7j8+DUQTa^Zv zn`^7YEO2nL*zr^up836viYB3X8ieyvZyJX!8_aqJF0npf9$h7nplcw zB`&FbNbe;nsXlH}Uv5|hAV@GIT9iZi*4HUA1K|k)dW>X(X_{Hx$@RM;#8n;KRSF&t zS+2(sdj%l9Sy*P$wijya-7@s$6?z;-`$@OQudlt&zdV}jxy@%_lA}p zSw}iZwR6e$3Rcz{D)P6n9~tr_`>f^n=XKI0s zdE8LjK{%=2dN`>khqwB?wH=#pu`49DN}RN35v6V-b++0zUt$ZSl-FY^Ik*J{K$Uv$ ztGx|Opx&#toDd04ZX4e_l=wxme`R38tdMBK-k%UzTg*hGBmZ2^dRi3}P436McgyKK z+&1dkuIa2l?n4w`l1J|hy1W(lKe%_jv~lg%_9%;sXeLm{LP%Y84IG0Lq{3rCzqdeX zJ;AMBGv<5&WH)qT8t`DG{kN#+K9mM@ z%o?Iy_ob^Q0TkGwZ$X7$D6pT)Y!})1z384`=!Gg&pJ{lLXd#Oln#4>PFrF}sp2P&= zGo`+PM^Ymgpz9z^wgX4Yn{$oO7e+KgU-8I!vqWxGz}Bc*2(A2RUl@R>R4j1&WwEE2 zTBFynD1cFf1+N{X0Ry3DnIZ<^40_d&?YbWci-4UJ)`cCrEio*_Fh zF>xyJ_*?ZJYx(r;SAC?TX%H(nlsc0Lt!ambe6CWgsedjW*Cug`?hS%|uX|p`+33gN zxVDM=J5%DS%%w6*;~x{5s$uA}4fU-Zu@QlAh^&)8%*g_Xobl$(h{|%V;qkFGwfeq7 z?k5bqiYn)qt7XxME1G3z27G}TGZKa~g{72VZS2Cq-DMKAd?z!vOx@-onLleEQ~zV) zyeVOTfs+uVS{-qZ_QGWT)B8^L56vLXf7@RW4UzX+|0Bz!Vg%b?2F(7kzZ4!;P7vf^ zbHo7m8_Nf9ipa<-aj*_WHEfPF)|fTvJH&tc0ropR zVZFc!9x%BvQ+VWoe_z2Uk*63B$Nn4E6!im8v#cw$#Gr>#f(=6qFBXp~nJUtp-2k0` z(E#}YUOvJgcKm+sPwPUGv27+n=n+g7@8E>VDsT^Lt+5Yg)0w0&j??hmzKLR0of~ai z;f~eb+mIzjGI@d!=0R?}^qG>Cb8$xb-zk&EzfvZ;eJ_Q7QYO)`zbTVzPM(9W^kUp+ zA;GCMvC^;r_w^L|Q`-8CY=LGI_^7Cc#UBEGzr4IRNju*jO)YoUly07vU#9z^LC4i) zA5&Wczsib7irpejaRJuMvRSVVOVBJ&eJy_UCmuoNG!xDLbS=RSiAIm$JeieI>=-au zU_UscFdUZW2rAr_j3kjmmSsogNlW}z7(9{LLHsZJ0717!28OzuM&M( zVy35>U9yX~jlax1m%OWmM#~a3A1ku}V5cDMgL+ESSkO?(8y~-!@B5v2*7R~eJv