diff --git a/x-pack/plugins/data_visualizer/common/constants.ts b/x-pack/plugins/data_visualizer/common/constants.ts index 60a87c37d9f1b..ff277b9bb4785 100644 --- a/x-pack/plugins/data_visualizer/common/constants.ts +++ b/x-pack/plugins/data_visualizer/common/constants.ts @@ -28,7 +28,7 @@ export const FILE_FORMATS = { DELIMITED: 'delimited', NDJSON: 'ndjson', SEMI_STRUCTURED_TEXT: 'semi_structured_text', - // XML: 'xml', + TIKA: 'tika', }; export const SUPPORTED_FIELD_TYPES = { diff --git a/x-pack/plugins/data_visualizer/common/utils/tika_utils.ts b/x-pack/plugins/data_visualizer/common/utils/tika_utils.ts new file mode 100644 index 0000000000000..934378464d70a --- /dev/null +++ b/x-pack/plugins/data_visualizer/common/utils/tika_utils.ts @@ -0,0 +1,90 @@ +/* + * 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 { i18n } from '@kbn/i18n'; + +export function isTikaType(type: string) { + return getTikaDisplayType(type).isTikaType; +} + +export const getTikaDisplayType = (type: string): { isTikaType: boolean; label: string } => { + switch (type) { + case 'application/doc': + case 'application/ms-doc': + case 'application/msword': + case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': + return { + isTikaType: true, + label: i18n.translate('xpack.dataVisualizer.file.tikaTypes.word', { + defaultMessage: 'Microsoft Office Word document', + }), + }; + + case 'application/excel': + case 'application/vnd.ms-excel': + case 'application/x-excel': + case 'application/x-msexcel': + case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': + return { + isTikaType: true, + label: i18n.translate('xpack.dataVisualizer.file.tikaTypes.excel', { + defaultMessage: 'Microsoft Office Excel document', + }), + }; + + case 'application/mspowerpoint': + case 'application/powerpoint': + case 'application/vnd.ms-powerpoint': + case 'application/x-mspowerpoint': + case 'application/vnd.openxmlformats-officedocument.presentationml.presentation': + return { + isTikaType: true, + label: i18n.translate('xpack.dataVisualizer.file.tikaTypes.powerPoint', { + defaultMessage: 'Microsoft Office Power Point document', + }), + }; + + case 'application/vnd.oasis.opendocument.presentation': + case 'application/vnd.oasis.opendocument.spreadsheet': + case 'application/vnd.oasis.opendocument.text': + return { + isTikaType: true, + label: i18n.translate('xpack.dataVisualizer.file.tikaTypes.openDoc', { + defaultMessage: 'Open Document Format', + }), + }; + + case 'text/rtf': + case 'application/rtf': + return { + isTikaType: true, + label: i18n.translate('xpack.dataVisualizer.file.tikaTypes.richText', { + defaultMessage: 'Rich Text Format', + }), + }; + + case 'application/pdf': + return { + isTikaType: true, + label: i18n.translate('xpack.dataVisualizer.file.tikaTypes.pdf', { + defaultMessage: 'PDF', + }), + }; + + case 'text/plain': + case 'text/plain; charset=UTF-8': + return { + isTikaType: true, + label: i18n.translate('xpack.dataVisualizer.file.tikaTypes.plainText', { + defaultMessage: 'Plain text', + }), + }; + + default: + return { isTikaType: false, label: type }; + } +}; diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/combined_fields/combined_field_label.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/combined_fields/combined_field_label.tsx index b1ca6e31450be..0a00518f251e5 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/combined_fields/combined_field_label.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/combined_fields/combined_field_label.tsx @@ -8,6 +8,7 @@ import React from 'react'; import { EuiText } from '@elastic/eui'; +import { ES_FIELD_TYPES } from '@kbn/field-types'; import type { CombinedField } from './types'; export function CombinedFieldLabel({ combinedField }: { combinedField: CombinedField }) { @@ -15,7 +16,11 @@ export function CombinedFieldLabel({ combinedField }: { combinedField: CombinedF } function getCombinedFieldLabel(combinedField: CombinedField) { - return `${combinedField.fieldNames.join(combinedField.delimiter)} => ${ - combinedField.combinedFieldName - } (${combinedField.mappingType})`; + if (combinedField.mappingType === ES_FIELD_TYPES.GEO_POINT) { + return `${combinedField.fieldNames.join(combinedField.delimiter)} => ${ + combinedField.combinedFieldName + } (${combinedField.mappingType})`; + } + + return combinedField.combinedFieldName; } diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/combined_fields/combined_fields_form.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/combined_fields/combined_fields_form.tsx index 8676be744cb53..7bf8d7f0aaaf3 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/combined_fields/combined_fields_form.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/combined_fields/combined_fields_form.tsx @@ -19,17 +19,13 @@ import { EuiFlexItem, } from '@elastic/eui'; -import type { FindFileStructureResponse } from '@kbn/file-upload-plugin/common'; +import type { FindFileStructureResponse, IngestPipeline } from '@kbn/file-upload-plugin/common'; +import type { MappingTypeMapping } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { CombinedField } from './types'; import { GeoPointForm } from './geo_point'; +import { SemanticTextForm } from './semantic_text'; import { CombinedFieldLabel } from './combined_field_label'; -import { - addCombinedFieldsToMappings, - addCombinedFieldsToPipeline, - getNameCollisionMsg, - removeCombinedFieldsFromMappings, - removeCombinedFieldsFromPipeline, -} from './utils'; +import { removeCombinedFieldsFromMappings, removeCombinedFieldsFromPipeline } from './utils'; interface Props { mappingsString: string; @@ -46,6 +42,12 @@ interface State { isPopoverOpen: boolean; } +export type AddCombinedField = ( + combinedField: CombinedField, + addToMappings: (mappings: MappingTypeMapping) => MappingTypeMapping, + addToPipeline: (pipeline: IngestPipeline) => IngestPipeline +) => void; + export class CombinedFieldsForm extends Component { state: State = { isPopoverOpen: false, @@ -63,20 +65,20 @@ export class CombinedFieldsForm extends Component { }); }; - addCombinedField = (combinedField: CombinedField) => { - if (this.hasNameCollision(combinedField.combinedFieldName)) { - throw new Error(getNameCollisionMsg(combinedField.combinedFieldName)); - } - + addCombinedField = ( + combinedField: CombinedField, + addToMappings: (mappings: MappingTypeMapping) => {}, + addToPipeline: (pipeline: IngestPipeline) => {} + ) => { const mappings = this.parseMappings(); const pipeline = this.parsePipeline(); - this.props.onMappingsStringChange( - JSON.stringify(addCombinedFieldsToMappings(mappings, [combinedField]), null, 2) - ); - this.props.onPipelineStringChange( - JSON.stringify(addCombinedFieldsToPipeline(pipeline, [combinedField]), null, 2) - ); + const newMappings = addToMappings(mappings); + const newPipeline = addToPipeline(pipeline); + + this.props.onMappingsStringChange(JSON.stringify(newMappings, null, 2)); + this.props.onPipelineStringChange(JSON.stringify(newPipeline, null, 2)); + this.props.onCombinedFieldsChange([...this.props.combinedFields, combinedField]); this.closePopover(); @@ -155,6 +157,13 @@ export class CombinedFieldsForm extends Component { defaultMessage: 'Add geo point field', } ); + + const semanticTextLabel = i18n.translate( + 'xpack.dataVisualizer.file.semanticTextForm.combinedFieldLabel', + { + defaultMessage: 'Add semantic text field', + } + ); const panels = [ { id: 0, @@ -163,6 +172,10 @@ export class CombinedFieldsForm extends Component { name: geoPointLabel, panel: 1, }, + { + name: semanticTextLabel, + panel: 2, + }, ], }, { @@ -176,11 +189,22 @@ export class CombinedFieldsForm extends Component { /> ), }, + { + id: 2, + title: semanticTextLabel, + content: ( + + ), + }, ]; return (
@@ -217,7 +241,7 @@ export class CombinedFieldsForm extends Component { > } diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/combined_fields/geo_point.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/combined_fields/geo_point.tsx index f855d61a463d6..65ee3a6b58b5b 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/combined_fields/geo_point.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/combined_fields/geo_point.tsx @@ -23,17 +23,19 @@ import { } from '@elastic/eui'; import type { FindFileStructureResponse } from '@kbn/file-upload-plugin/common'; -import type { CombinedField } from './types'; import { createGeoPointCombinedField, isWithinLatRange, isWithinLonRange, getFieldNames, getNameCollisionMsg, + addCombinedFieldsToMappings, + addCombinedFieldsToPipeline, } from './utils'; +import type { AddCombinedField } from './combined_fields_form'; interface Props { - addCombinedField: (combinedField: CombinedField) => void; + addCombinedField: AddCombinedField; hasNameCollision: (name: string) => boolean; results: FindFileStructureResponse; } @@ -99,13 +101,18 @@ export class GeoPointForm extends Component { onSubmit = () => { try { + const combinedField = createGeoPointCombinedField( + this.state.latField, + this.state.lonField, + this.state.geoPointField + ); + this.props.addCombinedField( - createGeoPointCombinedField( - this.state.latField, - this.state.lonField, - this.state.geoPointField - ) + combinedField, + (mappings) => addCombinedFieldsToMappings(mappings, [combinedField]), + (pipeline) => addCombinedFieldsToPipeline(pipeline, [combinedField]) ); + this.setState({ submitError: '' }); } catch (error) { this.setState({ submitError: error.message }); diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/combined_fields/semantic_text.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/combined_fields/semantic_text.tsx new file mode 100644 index 0000000000000..581e92d23dc9d --- /dev/null +++ b/x-pack/plugins/data_visualizer/public/application/common/components/combined_fields/semantic_text.tsx @@ -0,0 +1,210 @@ +/* + * 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, { useState, useEffect, useMemo } from 'react'; +import type { FC } from 'react'; +import type { + FindFileStructureResponse, + IngestPipeline, +} from '@kbn/file-upload-plugin/common/types'; +import type { EuiSelectOption } from '@elastic/eui'; +import { + EuiButton, + EuiFormRow, + EuiSelect, + EuiSpacer, + EuiTextAlign, + EuiFieldText, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { cloneDeep } from 'lodash'; +import useDebounce from 'react-use/lib/useDebounce'; +import type { + InferenceModelConfigContainer, + MappingTypeMapping, +} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { createSemanticTextCombinedField, getFieldNames, getNameCollisionMsg } from './utils'; +import { useDataVisualizerKibana } from '../../../kibana_context'; +import type { AddCombinedField } from './combined_fields_form'; + +interface Props { + addCombinedField: AddCombinedField; + hasNameCollision: (name: string) => boolean; + results: FindFileStructureResponse; +} +export const SemanticTextForm: FC = ({ addCombinedField, hasNameCollision, results }) => { + const { + services: { http }, + } = useDataVisualizerKibana(); + const [inferenceServices, setInferenceServices] = useState([]); + const [selectedInference, setSelectedInference] = useState(); + const [selectedFieldOption, setSelectedFieldOption] = useState(); + const [renameToFieldOption, setRenameToFieldOption] = useState(''); + const [fieldError, setFieldError] = useState(); + + const fieldOptions = useMemo( + () => + getFieldNames(results).map((columnName: string) => { + return { value: columnName, text: columnName }; + }), + [results] + ); + + useEffect(() => { + setSelectedFieldOption(fieldOptions[0].value ?? null); + }, [fieldOptions]); + + useEffect(() => { + http + .fetch('/internal/data_visualizer/inference_services', { + method: 'GET', + version: '1', + }) + .then((response) => { + const inferenceServiceOptions = response.map((service) => ({ + value: service.model_id, + text: service.model_id, + })); + setInferenceServices(inferenceServiceOptions); + setSelectedInference(inferenceServiceOptions[0]?.value ?? undefined); + }); + }, [http]); + + useEffect(() => { + if (selectedFieldOption?.includes('.')) { + setRenameToFieldOption(selectedFieldOption.split('.').pop()!); + } else { + setRenameToFieldOption(`${selectedFieldOption}_semantic`); + } + }, [selectedFieldOption]); + + const onSubmit = () => { + if ( + renameToFieldOption === '' || + renameToFieldOption === undefined || + selectedFieldOption === undefined || + selectedInference === undefined + ) { + return; + } + addCombinedField( + createSemanticTextCombinedField(renameToFieldOption, selectedFieldOption), + (mappings: MappingTypeMapping) => { + if (renameToFieldOption === undefined || selectedFieldOption === undefined) { + return mappings; + } + + const newMappings = cloneDeep(mappings); + newMappings.properties![renameToFieldOption ?? selectedFieldOption] = { + // @ts-ignore types are missing semantic_text + type: 'semantic_text', + inference_id: selectedInference, + }; + return newMappings; + }, + (pipeline: IngestPipeline) => { + const newPipeline = cloneDeep(pipeline); + if (renameToFieldOption !== null) { + newPipeline.processors.push({ + set: { + field: renameToFieldOption, + copy_from: selectedFieldOption, + }, + }); + } + return newPipeline; + } + ); + }; + + useDebounce( + () => { + if (renameToFieldOption === undefined) { + return; + } + const error = hasNameCollision(renameToFieldOption) + ? getNameCollisionMsg(renameToFieldOption) + : undefined; + setFieldError(error); + }, + 250, + [renameToFieldOption] + ); + + const isInvalid = useMemo(() => { + return ( + !selectedInference || + !selectedFieldOption || + renameToFieldOption === '' || + fieldError !== undefined + ); + }, [selectedInference, selectedFieldOption, renameToFieldOption, fieldError]); + + return ( + <> + + + + setSelectedFieldOption(e.target.value)} + /> + + + {renameToFieldOption !== null ? ( + + setRenameToFieldOption(e.target.value)} + aria-label="field name" + /> + + ) : null} + + + setSelectedInference(e.target.value)} + /> + + + + + + + + + + + ); +}; diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/combined_fields/types.ts b/x-pack/plugins/data_visualizer/public/application/common/components/combined_fields/types.ts index 8127b208fb59c..6e6fa70e967fc 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/combined_fields/types.ts +++ b/x-pack/plugins/data_visualizer/public/application/common/components/combined_fields/types.ts @@ -7,7 +7,7 @@ export interface CombinedField { mappingType: string; - delimiter: string; + delimiter?: string; combinedFieldName: string; fieldNames: string[]; } diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/combined_fields/utils.ts b/x-pack/plugins/data_visualizer/public/application/common/components/combined_fields/utils.ts index 75cf8cd8d91fe..4b0f57d1ca932 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/combined_fields/utils.ts +++ b/x-pack/plugins/data_visualizer/public/application/common/components/combined_fields/utils.ts @@ -123,6 +123,17 @@ export function createGeoPointCombinedField( }; } +export function createSemanticTextCombinedField( + sematicTextField: string, + originalField: string +): CombinedField { + return { + mappingType: 'semantic_text', + combinedFieldName: sematicTextField, + fieldNames: [originalField], + }; +} + export function getNameCollisionMsg(name: string) { return i18n.translate('xpack.dataVisualizer.nameCollisionMsg', { defaultMessage: '"{name}" already exists, please provide a unique name', diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/filebeat_config_flyout/filebeat_config.ts b/x-pack/plugins/data_visualizer/public/application/common/components/filebeat_config_flyout/filebeat_config.ts index dbef1b4497893..b3c02aa177de8 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/filebeat_config_flyout/filebeat_config.ts +++ b/x-pack/plugins/data_visualizer/public/application/common/components/filebeat_config_flyout/filebeat_config.ts @@ -11,7 +11,7 @@ import type { FindFileStructureResponse } from '@kbn/file-upload-plugin/common'; export function createFilebeatConfig( index: string, results: FindFileStructureResponse, - ingestPipelineId: string, + pipelineId: string, username: string | null ) { return [ @@ -27,7 +27,7 @@ export function createFilebeatConfig( ' hosts: [""]', ...getUserDetails(username), ` index: "${index}"`, - ` pipeline: "${ingestPipelineId}"`, + ` pipeline: "${pipelineId}"`, '', 'setup:', ' template.enabled: false', diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/filebeat_config_flyout/filebeat_config_flyout.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/filebeat_config_flyout/filebeat_config_flyout.tsx index 7682e771ac155..c6f62f4eef456 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/filebeat_config_flyout/filebeat_config_flyout.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/filebeat_config_flyout/filebeat_config_flyout.tsx @@ -34,15 +34,10 @@ export enum EDITOR_MODE { interface Props { index: string; results: FindFileStructureResponse; - ingestPipelineId: string; + pipelineId: string; closeFlyout(): void; } -export const FilebeatConfigFlyout: FC = ({ - index, - results, - ingestPipelineId, - closeFlyout, -}) => { +export const FilebeatConfigFlyout: FC = ({ index, results, pipelineId, closeFlyout }) => { const [fileBeatConfig, setFileBeatConfig] = useState(''); const [username, setUsername] = useState(null); const { @@ -56,9 +51,9 @@ export const FilebeatConfigFlyout: FC = ({ }, [security]); useEffect(() => { - const config = createFilebeatConfig(index, results, ingestPipelineId, username); + const config = createFilebeatConfig(index, results, pipelineId, username); setFileBeatConfig(config); - }, [username, index, ingestPipelineId, results]); + }, [username, index, pipelineId, results]); return ( diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx index 259b45d4e297b..a48dde6f4fa6b 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx @@ -19,6 +19,7 @@ import { isDefined } from '@kbn/ml-is-defined'; import type { ResultLinks } from '../../../../../common/app'; import type { LinkCardProps } from '../link_card/link_card'; import { useDataVisualizerKibana } from '../../../kibana_context'; +import type { CombinedField } from '../combined_fields/types'; type LinkType = 'file' | 'index'; @@ -44,7 +45,7 @@ export interface ResultLink { } interface Props { - fieldStats: FindFileStructureResponse['field_stats']; + results: FindFileStructureResponse; index: string; dataViewId: string; timeFieldName?: string; @@ -52,6 +53,7 @@ interface Props { showFilebeatFlyout(): void; getAdditionalLinks?: GetAdditionalLinks; resultLinks?: ResultLinks; + combinedFields: CombinedField[]; } interface GlobalState { @@ -62,7 +64,7 @@ interface GlobalState { const RECHECK_DELAY_MS = 3000; export const ResultsLinks: FC = ({ - fieldStats, + results, index, dataViewId, timeFieldName, @@ -70,6 +72,7 @@ export const ResultsLinks: FC = ({ showFilebeatFlyout, getAdditionalLinks, resultLinks, + combinedFields, }) => { const { services: { @@ -78,7 +81,7 @@ export const ResultsLinks: FC = ({ application: { getUrlForApp, capabilities }, }, } = useDataVisualizerKibana(); - + const fieldStats = results.field_stats; const [duration, setDuration] = useState({ from: 'now-30m', to: 'now', @@ -88,6 +91,7 @@ export const ResultsLinks: FC = ({ const [discoverLink, setDiscoverLink] = useState(''); const [indexManagementLink, setIndexManagementLink] = useState(''); const [dataViewsManagementLink, setDataViewsManagementLink] = useState(''); + const [playgroundLink, setPlaygroundLink] = useState(''); const [asyncHrefCards, setAsyncHrefCards] = useState(); useEffect(() => { @@ -96,7 +100,7 @@ export const ResultsLinks: FC = ({ const getDiscoverUrl = async (): Promise => { const isDiscoverAvailable = capabilities.discover?.show ?? false; if (!isDiscoverAvailable) return; - const discoverLocator = url?.locators.get('DISCOVER_APP_LOCATOR'); + const discoverLocator = url.locators.get('DISCOVER_APP_LOCATOR'); if (!discoverLocator) { // eslint-disable-next-line no-console @@ -116,13 +120,13 @@ export const ResultsLinks: FC = ({ if (Array.isArray(getAdditionalLinks)) { Promise.all( getAdditionalLinks.map(async (asyncCardGetter) => { - const results = await asyncCardGetter({ + const cardResults = await asyncCardGetter({ dataViewId, globalState, }); - if (Array.isArray(results)) { + if (Array.isArray(cardResults)) { return await Promise.all( - results.map(async (c) => ({ + cardResults.map(async (c) => ({ ...c, canDisplay: await c.canDisplay(), href: await c.getUrl(), @@ -140,6 +144,12 @@ export const ResultsLinks: FC = ({ } if (!unmounted) { + const playgroundLocator = url.locators.get('PLAYGROUND_LOCATOR_ID'); + + if (playgroundLocator !== undefined) { + playgroundLocator.getUrl({ 'default-index': index }).then(setPlaygroundLink); + } + setIndexManagementLink( getUrlForApp('management', { path: '/data/index_management/indices' }) ); @@ -228,7 +238,6 @@ export const ResultsLinks: FC = ({ /> )} - {indexManagementLink && ( = ({ /> )} - {dataViewsManagementLink && ( = ({ /> )} - {resultLinks?.fileBeat?.enabled === false ? null : ( = ({ )} + {playgroundLink ? ( + + } + data-test-subj="fileDataVisFilebeatConfigLink" + title={ + + } + description="" + href={playgroundLink} + /> + + ) : null} + {Array.isArray(asyncHrefCards) && asyncHrefCards.map((link) => ( diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/utils/utils.ts b/x-pack/plugins/data_visualizer/public/application/common/components/utils/utils.ts index 0aca4f9260b7d..776f687f7732f 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/utils/utils.ts +++ b/x-pack/plugins/data_visualizer/public/application/common/components/utils/utils.ts @@ -26,7 +26,7 @@ const overrideDefaults = { linesToSample: undefined, }; -export function readFile(file: File) { +export function readFile(file: File): Promise<{ fileContents: string; data: ArrayBuffer }> { return new Promise((resolve, reject) => { if (file && file.size) { const reader = new FileReader(); diff --git a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/about_panel/welcome_content.tsx b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/about_panel/welcome_content.tsx index 61681db6b3ef5..a5437ad49dc2d 100644 --- a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/about_panel/welcome_content.tsx +++ b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/about_panel/welcome_content.tsx @@ -34,10 +34,11 @@ interface Props { export const WelcomeContent: FC = ({ hasPermissionToImport }) => { const { services: { - fileUpload: { getMaxBytesFormatted }, + fileUpload: { getMaxBytesFormatted, getMaxTikaBytesFormatted }, }, } = useDataVisualizerKibana(); const maxFileSize = getMaxBytesFormatted(); + const maxTikaFileSize = getMaxTikaBytesFormatted(); return ( @@ -57,10 +58,17 @@ export const WelcomeContent: FC = ({ hasPermissionToImport }) => {

{hasPermissionToImport ? ( - + <> + +
+ + ) : ( = ({ hasPermissionToImport }) => {

- + @@ -87,8 +96,8 @@ export const WelcomeContent: FC = ({ hasPermissionToImport }) => {

@@ -103,8 +112,8 @@ export const WelcomeContent: FC = ({ hasPermissionToImport }) => {

@@ -119,23 +128,89 @@ export const WelcomeContent: FC = ({ hasPermissionToImport }) => {

+

+
+
+
+ + + + + + + +

+

+ +

+ + + + + + + +

+ +

+
+
+
+ + + + + + + +

+ +

+
+
+
+ + + + + + + +

+ +

+
+
+
); diff --git a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/analysis_summary/analysis_summary.tsx b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/analysis_summary/analysis_summary.tsx index 7f67f6f4f4868..8efacc7a5de06 100644 --- a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/analysis_summary/analysis_summary.tsx +++ b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/analysis_summary/analysis_summary.tsx @@ -11,6 +11,7 @@ import React from 'react'; import { EuiTitle, EuiSpacer, EuiDescriptionList } from '@elastic/eui'; import type { FindFileStructureResponse } from '@kbn/file-upload-plugin/common'; +import { getTikaDisplayType } from '../../../../../common/utils/tika_utils'; import { FILE_FORMATS } from '../../../../../common/constants'; export const AnalysisSummary: FC<{ results: FindFileStructureResponse }> = ({ results }) => { @@ -64,7 +65,7 @@ function createDisplayItems(results: FindFileStructureResponse) { defaultMessage="Format" /> ), - description: results.format, + description: getFormatLabel(results), }); if (results.format === FILE_FORMATS.DELIMITED) { @@ -131,3 +132,9 @@ function createDisplayItems(results: FindFileStructureResponse) { return items; } + +function getFormatLabel(results: FindFileStructureResponse) { + return results.format === FILE_FORMATS.TIKA && results.document_type !== undefined + ? getTikaDisplayType(results.document_type).label + : results.format; +} diff --git a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/file_contents/file_contents.tsx b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/file_contents/file_contents.tsx index ef57ab6204c6d..412423a0ba0d8 100644 --- a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/file_contents/file_contents.tsx +++ b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/file_contents/file_contents.tsx @@ -26,7 +26,7 @@ import { useGrokHighlighter } from './use_text_parser'; import { LINE_LIMIT } from './grok_highlighter'; interface Props { - data: string; + fileContents: string; format: string; numberOfLines: number; semiStructureTextData: SemiStructureTextData | null; @@ -51,7 +51,12 @@ function semiStructureTextDataGuard( ); } -export const FileContents: FC = ({ data, format, numberOfLines, semiStructureTextData }) => { +export const FileContents: FC = ({ + fileContents, + format, + numberOfLines, + semiStructureTextData, +}) => { let mode = EDITOR_MODE.TEXT; if (format === EDITOR_MODE.JSON) { mode = EDITOR_MODE.JSON; @@ -63,8 +68,8 @@ export const FileContents: FC = ({ data, format, numberOfLines, semiStruc semiStructureTextDataGuard(semiStructureTextData) ); const formattedData = useMemo( - () => limitByNumberOfLines(data, numberOfLines), - [data, numberOfLines] + () => limitByNumberOfLines(fileContents, numberOfLines), + [fileContents, numberOfLines] ); const [highlightedLines, setHighlightedLines] = useState(null); @@ -78,7 +83,7 @@ export const FileContents: FC = ({ data, format, numberOfLines, semiStruc semiStructureTextData!; grokHighlighter( - data, + fileContents, grokPattern!, mappings, ecsCompatibility, @@ -96,7 +101,7 @@ export const FileContents: FC = ({ data, format, numberOfLines, semiStruc setIsSemiStructureTextData(false); } }); - }, [data, semiStructureTextData, grokHighlighter, isSemiStructureTextData, isMounted]); + }, [fileContents, semiStructureTextData, grokHighlighter, isSemiStructureTextData, isMounted]); return ( <> diff --git a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/file_contents/preview_pdf.ts b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/file_contents/preview_pdf.ts new file mode 100644 index 0000000000000..7a850a9f5b965 --- /dev/null +++ b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/file_contents/preview_pdf.ts @@ -0,0 +1,30 @@ +/* + * 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 type { HttpSetup } from '@kbn/core-http-browser'; + +const URL = '/internal/file_upload/preview_pdf_contents'; + +export async function previewPDF(http: HttpSetup, data: ArrayBuffer) { + const dataString: string = [].reduce.call( + new Uint8Array(data), + (p, c) => { + return p + String.fromCharCode(c); + }, + '' + ) as string; + const pdfBase64 = btoa(dataString); + + const { preview } = await http.fetch(URL, { + method: 'POST', + version: '1', + body: JSON.stringify({ + pdfBase64, + }), + }); + return preview; +} diff --git a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/file_data_visualizer_view/file_data_visualizer_view.js b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/file_data_visualizer_view/file_data_visualizer_view.js index e6435c554fc63..e19b2cbceda33 100644 --- a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/file_data_visualizer_view/file_data_visualizer_view.js +++ b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/file_data_visualizer_view/file_data_visualizer_view.js @@ -28,8 +28,11 @@ import { createUrlOverrides, processResults, } from '../../../common/components/utils'; +import { analyzeTikaFile } from './tika_analyzer'; import { MODE } from './constants'; +import { FileSizeChecker } from './file_size_check'; +import { isTikaType } from '../../../../../common/utils/tika_utils'; export class FileDataVisualizerView extends Component { constructor(props) { @@ -40,7 +43,7 @@ export class FileDataVisualizerView extends Component { fileName: '', fileContents: '', data: [], - fileSize: 0, + base64Data: '', fileTooLarge: false, fileCouldNotBeRead: false, serverError: null, @@ -60,8 +63,6 @@ export class FileDataVisualizerView extends Component { this.originalSettings = { linesToSample: DEFAULT_LINES_TO_SAMPLE, }; - - this.maxFileUploadBytes = props.fileUpload.getMaxBytes(); } async componentDidMount() { @@ -85,7 +86,6 @@ export class FileDataVisualizerView extends Component { fileName: '', fileContents: '', data: [], - fileSize: 0, fileTooLarge: false, fileCouldNotBeRead: false, fileCouldNotBeReadPermissionError: false, @@ -102,17 +102,25 @@ export class FileDataVisualizerView extends Component { }; async loadFile(file) { - if (file.size <= this.maxFileUploadBytes) { + this.fileSizeChecker = new FileSizeChecker(this.props.fileUpload, file); + if (this.fileSizeChecker.check()) { try { const { data, fileContents } = await readFile(file); - this.setState({ - data, - fileContents, - fileName: file.name, - fileSize: file.size, - }); - - await this.analyzeFile(fileContents); + if (isTikaType(file.type)) { + this.setState({ + data, + fileName: file.name, + }); + + await this.analyzeTika(data); + } else { + this.setState({ + data, + fileContents, + fileName: file.name, + }); + await this.analyzeFile(fileContents); + } } catch (error) { this.setState({ loaded: false, @@ -126,7 +134,6 @@ export class FileDataVisualizerView extends Component { loading: false, fileTooLarge: true, fileName: file.name, - fileSize: file.size, }); } } @@ -206,6 +213,21 @@ export class FileDataVisualizerView extends Component { } } + async analyzeTika(data, isRetry = false) { + const { tikaResults, standardResults } = await analyzeTikaFile(data, this.props.fileUpload); + const serverSettings = processResults(standardResults); + this.originalSettings = serverSettings; + + this.setState({ + fileContents: tikaResults.content, + results: standardResults.results, + explanation: standardResults.explanation, + loaded: true, + loading: false, + fileCouldNotBeRead: isRetry, + }); + } + closeEditFlyout = () => { this.setState({ isEditFlyoutVisible: false }); }; @@ -258,7 +280,6 @@ export class FileDataVisualizerView extends Component { fileContents, data, fileName, - fileSize, fileTooLarge, fileCouldNotBeRead, serverError, @@ -287,9 +308,7 @@ export class FileDataVisualizerView extends Component { {loading && } - {fileTooLarge && ( - - )} + {fileTooLarge && } {fileCouldNotBeRead && loading === false && ( <> @@ -311,7 +330,7 @@ export class FileDataVisualizerView extends Component { results={results} explanation={explanation} fileName={fileName} - data={fileContents} + fileContents={fileContents} showEditFlyout={this.showEditFlyout} showExplanationFlyout={this.showExplanationFlyout} disableButtons={isEditFlyoutVisible || isExplanationFlyoutVisible} diff --git a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/file_data_visualizer_view/file_error_callouts.tsx b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/file_data_visualizer_view/file_error_callouts.tsx index cb160a3e2763e..13c4ed5f7336f 100644 --- a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/file_data_visualizer_view/file_error_callouts.tsx +++ b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/file_data_visualizer_view/file_error_callouts.tsx @@ -11,18 +11,16 @@ import React from 'react'; import { EuiCallOut, EuiSpacer, EuiButtonEmpty, EuiHorizontalRule } from '@elastic/eui'; -import numeral from '@elastic/numeral'; import type { FindFileStructureErrorResponse } from '@kbn/file-upload-plugin/common'; -import { FILE_SIZE_DISPLAY_FORMAT } from '../../../../../common/constants'; +import type { FileSizeChecker } from './file_size_check'; interface FileTooLargeProps { - fileSize: number; - maxFileSize: number; + fileSizeChecker: FileSizeChecker; } -export const FileTooLarge: FC = ({ fileSize, maxFileSize }) => { - const fileSizeFormatted = numeral(fileSize).format(FILE_SIZE_DISPLAY_FORMAT); - const maxFileSizeFormatted = numeral(maxFileSize).format(FILE_SIZE_DISPLAY_FORMAT); +export const FileTooLarge: FC = ({ fileSizeChecker }) => { + const fileSizeFormatted = fileSizeChecker.fileSizeFormatted(); + const maxFileSizeFormatted = fileSizeChecker.maxFileSizeFormatted(); // Format the byte values, using the second format if the difference between // the file size and the max is so small that the formatted values are identical @@ -43,7 +41,7 @@ export const FileTooLarge: FC = ({ fileSize, maxFileSize }) =

); } else { - const diffFormatted = numeral(fileSize - maxFileSize).format(FILE_SIZE_DISPLAY_FORMAT); + const diffFormatted = fileSizeChecker.fileSizeDiffFormatted(); errorText = (

{ + const resp = await fileUpload.previewTikaFile(data); + const numLinesAnalyzed = (resp.content.match(/\n/g) || '').length + 1; + + return { + tikaResults: resp, + standardResults: { + results: { + format: FILE_FORMATS.TIKA, + document_type: resp.content_type, + charset: 'utf-8', + has_header_row: false, + has_byte_order_marker: false, + sample_start: '', + quote: '', + delimiter: '', + need_client_timezone: false, + num_lines_analyzed: numLinesAnalyzed, + num_messages_analyzed: 0, + field_stats: { + // @ts-expect-error semantic_text not supported + 'attachment.content': {}, + // @ts-expect-error semantic_text not supported + 'attachment.content_length': {}, + // @ts-expect-error semantic_text not supported + 'attachment.content_type': {}, + // @ts-expect-error semantic_text not supported + 'attachment.format': {}, + // @ts-expect-error semantic_text not supported + 'attachment.language': {}, + }, + mappings: { + properties: { + attachment: { + // @ts-expect-error semantic_text not supported + properties: { + content: { + type: 'text', + fields: { + keyword: { + type: 'keyword', + ignore_above: 256, + }, + }, + }, + content_length: { + type: 'long', + }, + content_type: { + type: 'text', + fields: { + keyword: { + type: 'keyword', + ignore_above: 256, + }, + }, + }, + format: { + type: 'text', + fields: { + keyword: { + type: 'keyword', + ignore_above: 256, + }, + }, + }, + language: { + type: 'text', + fields: { + keyword: { + type: 'keyword', + ignore_above: 256, + }, + }, + }, + }, + }, + }, + }, + ingest_pipeline: { + description: 'Ingest pipeline created by file data visualizer', + processors: [ + { + attachment: { + field: 'data', + remove_binary: true, + }, + }, + ], + }, + }, + }, + }; +} diff --git a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_settings/advanced.tsx b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_settings/advanced/advanced.tsx similarity index 67% rename from x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_settings/advanced.tsx rename to x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_settings/advanced/advanced.tsx index 186198622a3ef..309145a374715 100644 --- a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_settings/advanced.tsx +++ b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_settings/advanced/advanced.tsx @@ -20,17 +20,18 @@ import { } from '@elastic/eui'; import type { FindFileStructureResponse } from '@kbn/file-upload-plugin/common'; -import type { CombinedField } from '../../../common/components/combined_fields'; -import { CombinedFieldsForm } from '../../../common/components/combined_fields'; -import { JsonEditor, EDITOR_MODE } from '../json_editor'; -import { CreateDataViewToolTip } from './create_data_view_tooltip'; -const EDITOR_HEIGHT = '300px'; +import type { CombinedField } from '../../../../common/components/combined_fields'; +import { CombinedFieldsForm } from '../../../../common/components/combined_fields'; + +import { CreateDataViewToolTip } from '../create_data_view_tooltip'; +import { IndexSettings, IngestPipeline, Mappings } from './inputs'; +import { SemanticTextInfo } from '../semantic_text_info'; interface Props { index: string; dataView: string; initialized: boolean; - onIndexChange(): void; + onIndexChange(index: string): void; createDataView: boolean; onCreateDataViewChange(): void; onDataViewChange(): void; @@ -70,7 +71,7 @@ export const AdvancedSettings: FC = ({ canCreateDataView, }) => { return ( - + <> = ({ )} value={index} disabled={initialized === true} - onChange={onIndexChange} + onChange={(e) => onIndexChange(e.target.value)} isInvalid={indexNameError !== ''} aria-label={i18n.translate( 'xpack.dataVisualizer.file.advancedImportSettings.indexNameAriaLabel', @@ -139,6 +140,8 @@ export const AdvancedSettings: FC = ({ /> + + = ({ isDisabled={initialized === true} /> + + = ({ /> - - ); -}; - -interface JsonEditorProps { - initialized: boolean; - data: string; - onChange(value: string): void; -} - -const IndexSettings: FC = ({ initialized, data, onChange }) => { - return ( - - - } - fullWidth - > - - - - ); -}; - -const Mappings: FC = ({ initialized, data, onChange }) => { - return ( - - - } - fullWidth - > - - - - ); -}; - -const IngestPipeline: FC = ({ initialized, data, onChange }) => { - return ( - - - } - fullWidth - > - - - + ); }; diff --git a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_settings/advanced/index.ts b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_settings/advanced/index.ts new file mode 100644 index 0000000000000..2e0fc86ab3ad2 --- /dev/null +++ b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_settings/advanced/index.ts @@ -0,0 +1,8 @@ +/* + * 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. + */ + +export { AdvancedSettings } from './advanced'; diff --git a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_settings/advanced/inputs.tsx b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_settings/advanced/inputs.tsx new file mode 100644 index 0000000000000..7a0d952ef31db --- /dev/null +++ b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_settings/advanced/inputs.tsx @@ -0,0 +1,96 @@ +/* + * 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 { FormattedMessage } from '@kbn/i18n-react'; +import type { FC } from 'react'; +import React from 'react'; + +import { EuiFormRow } from '@elastic/eui'; +import { JsonEditor, EDITOR_MODE } from '../../json_editor'; + +const EDITOR_HEIGHT = '300px'; + +interface JsonEditorProps { + initialized: boolean; + data: string; + onChange(value: string): void; + indexName?: string; +} + +export const IndexSettings: FC = ({ initialized, data, onChange }) => { + return ( + + } + fullWidth + > + + + ); +}; + +export const Mappings: FC = ({ initialized, data, onChange, indexName }) => { + return ( + + ) : ( + + ) + } + fullWidth + > + + + ); +}; + +export const IngestPipeline: FC = ({ initialized, data, onChange }) => { + return ( + + } + fullWidth + > + + + ); +}; diff --git a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_settings/advanced/use_existing_indices.ts b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_settings/advanced/use_existing_indices.ts new file mode 100644 index 0000000000000..19526c799d2aa --- /dev/null +++ b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_settings/advanced/use_existing_indices.ts @@ -0,0 +1,58 @@ +/* + * 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 { useCallback, useState, useEffect } from 'react'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { useDataVisualizerKibana } from '../../../../kibana_context'; + +interface EsIndex { + name: string; + hidden: boolean; + frozen: boolean; +} + +type Pipeline = estypes.IngestPipelineConfig & { + name: string; +}; + +export function useExistingIndices() { + const { + services: { http }, + } = useDataVisualizerKibana(); + + const [indices, setIndices] = useState([]); + const [pipelines, setPipelines] = useState([]); + + const loadIndices = useCallback(() => { + http.get('/api/index_management/indices').then((resp) => { + setIndices(resp.filter((i) => !(i.hidden || i.frozen))); + }); + }, [http]); + + const loadPipelines = useCallback(() => { + http.get('/api/ingest_pipelines').then((resp) => { + setPipelines(resp.sort((a, b) => a.name.localeCompare(b.name))); + }); + }, [http]); + + useEffect(() => { + loadIndices(); + loadPipelines(); + }, [loadIndices, loadPipelines]); + + const getMapping = useCallback( + async (indexName: string) => { + const resp = await http.get( + `/api/index_management/mapping/${indexName}` + ); + return resp.mappings; + }, + [http] + ); + + return { indices, pipelines, getMapping }; +} diff --git a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_settings/import_settings.tsx b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_settings/import_settings.tsx index 381a3ff6e0488..a4c1187d014c8 100644 --- a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_settings/import_settings.tsx +++ b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_settings/import_settings.tsx @@ -21,7 +21,7 @@ interface Props { index: string; dataView: string; initialized: boolean; - onIndexChange(): void; + onIndexChange(index: string): void; createDataView: boolean; onCreateDataViewChange(): void; onDataViewChange(): void; @@ -74,7 +74,7 @@ export const ImportSettings: FC = ({ defaultMessage: 'Simple', }), content: ( - + <> = ({ indexNameError={indexNameError} combinedFields={combinedFields} canCreateDataView={canCreateDataView} + results={results} /> - + ), }, { @@ -96,7 +97,7 @@ export const ImportSettings: FC = ({ defaultMessage: 'Advanced', }), content: ( - + <> = ({ results={results} canCreateDataView={canCreateDataView} /> - + ), }, ]; return ( - + <> {}} /> - + ); }; diff --git a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_settings/semantic_text_info.tsx b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_settings/semantic_text_info.tsx new file mode 100644 index 0000000000000..cf49c23a539db --- /dev/null +++ b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_settings/semantic_text_info.tsx @@ -0,0 +1,60 @@ +/* + * 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 type { FC } from 'react'; +import React from 'react'; + +import type { FindFileStructureResponse } from '@kbn/file-upload-plugin/common'; +import { EuiCallOut, EuiLink, EuiSpacer } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { FILE_FORMATS } from '../../../../../common/constants'; + +interface Props { + results: FindFileStructureResponse; +} + +export const SemanticTextInfo: FC = ({ results }) => { + return results.format === FILE_FORMATS.TIKA ? ( + <> + + + + } + color="primary" + iconType="iInCircle" + > + + semantic_text + + ), + }} + /> +
+ +
+ + + + ) : null; +}; diff --git a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_settings/simple.tsx b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_settings/simple.tsx index 1ae343155e87c..ecbfb2ee8ed85 100644 --- a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_settings/simple.tsx +++ b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_settings/simple.tsx @@ -11,19 +11,22 @@ import type { FC } from 'react'; import React from 'react'; import { EuiFieldText, EuiFormRow, EuiCheckbox, EuiSpacer } from '@elastic/eui'; +import type { FindFileStructureResponse } from '@kbn/file-upload-plugin/common'; import type { CombinedField } from '../../../common/components/combined_fields'; import { CombinedFieldsReadOnlyForm } from '../../../common/components/combined_fields'; import { CreateDataViewToolTip } from './create_data_view_tooltip'; +import { SemanticTextInfo } from './semantic_text_info'; interface Props { index: string; initialized: boolean; - onIndexChange(): void; + onIndexChange(i: string): void; createDataView: boolean; onCreateDataViewChange(): void; indexNameError: string; combinedFields: CombinedField[]; canCreateDataView: boolean; + results: FindFileStructureResponse; } export const SimpleSettings: FC = ({ @@ -35,6 +38,7 @@ export const SimpleSettings: FC = ({ indexNameError, combinedFields, canCreateDataView, + results, }) => { return ( @@ -57,7 +61,7 @@ export const SimpleSettings: FC = ({ )} value={index} disabled={initialized === true} - onChange={onIndexChange} + onChange={(e) => onIndexChange(e.target.value)} isInvalid={indexNameError !== ''} aria-label={i18n.translate( 'xpack.dataVisualizer.file.simpleImportSettings.indexNameAriaLabel', @@ -87,7 +91,7 @@ export const SimpleSettings: FC = ({ /> - + diff --git a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_summary/import_summary.tsx b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_summary/import_summary.tsx index a1f6693e0bb9b..b71c2433f4ce0 100644 --- a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_summary/import_summary.tsx +++ b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_summary/import_summary.tsx @@ -16,7 +16,7 @@ import { Failures } from './failures'; interface Props { index: string; dataView: string; - ingestPipelineId: string; + pipelineId: string; docCount: number; importFailures: DocFailure[]; createDataView: boolean; @@ -26,7 +26,7 @@ interface Props { export const ImportSummary: FC = ({ index, dataView, - ingestPipelineId, + pipelineId, docCount, importFailures, createDataView, @@ -35,7 +35,7 @@ export const ImportSummary: FC = ({ const items = createDisplayItems( index, dataView, - ingestPipelineId, + pipelineId, docCount, importFailures, createDataView, @@ -99,7 +99,7 @@ export const ImportSummary: FC = ({ function createDisplayItems( index: string, dataView: string, - ingestPipelineId: string, + pipelineId: string, docCount: number, importFailures: DocFailure[], createDataView: boolean, @@ -134,7 +134,7 @@ function createDisplayItems( defaultMessage="Ingest pipeline" /> ), - description: ingestPipelineId, + description: pipelineId, }); } diff --git a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_view/import.ts b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_view/import.ts new file mode 100644 index 0000000000000..f4cbe2f03e966 --- /dev/null +++ b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_view/import.ts @@ -0,0 +1,242 @@ +/* + * 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 type { DataViewsServicePublic } from '@kbn/data-views-plugin/public/types'; +import type { + FindFileStructureResponse, + IngestPipeline, +} from '@kbn/file-upload-plugin/common/types'; +import type { FileUploadStartApi } from '@kbn/file-upload-plugin/public/api'; +import { i18n } from '@kbn/i18n'; +import { IMPORT_STATUS } from '../import_progress/import_progress'; + +interface Props { + data: ArrayBuffer; + results: FindFileStructureResponse; + dataViewsContract: DataViewsServicePublic; + fileUpload: FileUploadStartApi; +} + +interface Config { + index: string; + dataView: string; + createDataView: boolean; + indexSettingsString: string; + mappingsString: string; + pipelineString: string; + pipelineId: string | null; +} + +export async function importData(props: Props, config: Config, setState: (state: unknown) => void) { + const { data, results, dataViewsContract, fileUpload } = props; + const { + index, + dataView, + createDataView, + indexSettingsString, + mappingsString, + pipelineString, + pipelineId, + } = config; + const { format } = results; + + const errors = []; + + if (index === '') { + return; + } + + if ( + (await fileUpload.hasImportPermission({ + checkCreateDataView: createDataView, + checkHasManagePipeline: true, + indexName: index, + })) === false + ) { + errors.push( + i18n.translate('xpack.dataVisualizer.file.importView.importPermissionError', { + defaultMessage: 'You do not have permission to create or import data into index {index}.', + values: { + index, + }, + }) + ); + setState({ + permissionCheckStatus: IMPORT_STATUS.FAILED, + importing: false, + imported: false, + errors, + }); + return; + } + + setState({ + importing: true, + imported: false, + reading: true, + initialized: true, + permissionCheckStatus: IMPORT_STATUS.COMPLETE, + }); + + let success = true; + + let settings = {}; + let mappings = {}; + let pipeline = {}; + + try { + settings = JSON.parse(indexSettingsString); + } catch (error) { + success = false; + const parseError = i18n.translate('xpack.dataVisualizer.file.importView.parseSettingsError', { + defaultMessage: 'Error parsing settings:', + }); + errors.push(`${parseError} ${error.message}`); + } + + try { + mappings = JSON.parse(mappingsString); + } catch (error) { + success = false; + const parseError = i18n.translate('xpack.dataVisualizer.file.importView.parseMappingsError', { + defaultMessage: 'Error parsing mappings:', + }); + errors.push(`${parseError} ${error.message}`); + } + + try { + pipeline = JSON.parse(pipelineString); + } catch (error) { + success = false; + const parseError = i18n.translate('xpack.dataVisualizer.file.importView.parsePipelineError', { + defaultMessage: 'Error parsing ingest pipeline:', + }); + errors.push(`${parseError} ${error.message}`); + } + + setState({ + parseJSONStatus: getSuccess(success), + }); + + if (success === false) { + return; + } + + const importer = await fileUpload.importerFactory(format, { + excludeLinesPattern: results.exclude_lines_pattern, + multilineStartPattern: results.multiline_start_pattern, + }); + + const readResp = importer.read(data); + success = readResp.success; + setState({ + readStatus: getSuccess(success), + reading: false, + importer, + }); + + if (success === false) { + return; + } + + const initializeImportResp = await importer.initializeImport( + index, + settings, + mappings, + pipeline as IngestPipeline + ); + + const timeFieldName = importer.getTimeField(); + setState({ timeFieldName }); + + const indexCreated = initializeImportResp.index !== undefined; + setState({ + indexCreatedStatus: getSuccess(indexCreated), + }); + + const pipelineCreated = initializeImportResp.pipelineId !== undefined; + if (indexCreated) { + setState({ + ingestPipelineCreatedStatus: pipelineCreated ? IMPORT_STATUS.COMPLETE : IMPORT_STATUS.FAILED, + pipelineId: pipelineCreated ? initializeImportResp.pipelineId : '', + }); + } + success = indexCreated && pipelineCreated; + + if (success === false) { + errors.push(initializeImportResp.error); + return; + } + + const importResp = await importer.import( + initializeImportResp.id, + index, + pipelineId ?? initializeImportResp.pipelineId, + (progress: number) => { + setState({ + uploadProgress: progress, + }); + } + ); + success = importResp.success; + setState({ + uploadStatus: getSuccess(importResp.success), + importFailures: importResp.failures, + docCount: importResp.docCount, + }); + + if (success === false) { + errors.push(importResp.error); + return; + } + + if (createDataView) { + const dataViewName = dataView === '' ? index : dataView; + const dataViewResp = await createKibanaDataView(dataViewName, dataViewsContract, timeFieldName); + success = dataViewResp.success; + setState({ + dataViewCreatedStatus: dataViewResp.success ? IMPORT_STATUS.COMPLETE : IMPORT_STATUS.FAILED, + dataViewId: dataViewResp.id, + }); + if (success === false) { + errors.push(dataViewResp.error); + } + } + + setState({ + importing: false, + imported: success, + errors, + }); +} + +async function createKibanaDataView( + dataViewName: string, + dataViewsContract: DataViewsServicePublic, + timeFieldName?: string +) { + try { + const emptyPattern = await dataViewsContract.createAndSave({ + title: dataViewName, + timeFieldName, + }); + + return { + success: true, + id: emptyPattern.id, + }; + } catch (error) { + return { + success: false, + error, + }; + } +} + +function getSuccess(success: boolean) { + return success ? IMPORT_STATUS.COMPLETE : IMPORT_STATUS.FAILED; +} diff --git a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_view/import_view.js b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_view/import_view.js index 728b9fcbc6d75..aecf755c1c7c1 100644 --- a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_view/import_view.js +++ b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_view/import_view.js @@ -20,7 +20,6 @@ import { EuiButtonEmpty, } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; import { debounce } from 'lodash'; import { ResultsLinks } from '../../../common/components/results_links'; import { FilebeatConfigFlyout } from '../../../common/components/filebeat_config_flyout'; @@ -35,6 +34,8 @@ import { getDefaultCombinedFields, } from '../../../common/components/combined_fields'; import { MODE as DATAVISUALIZER_MODE } from '../file_data_visualizer_view/constants'; +import { importData } from './import'; +import { FILE_FORMATS } from '../../../../../common/constants'; const DEFAULT_INDEX_SETTINGS = {}; const CONFIG_MODE = { SIMPLE: 0, ADVANCED: 1 }; @@ -57,7 +58,7 @@ const DEFAULT_STATE = { createDataView: true, dataView: '', dataViewId: '', - ingestPipelineId: '', + pipelineId: null, errors: [], importFailures: [], docCount: 0, @@ -74,6 +75,7 @@ const DEFAULT_STATE = { checkingValidIndex: false, combinedFields: [], importer: undefined, + createPipeline: true, }; export class ImportView extends Component { @@ -96,228 +98,31 @@ export class ImportView extends Component { }; clickImport = () => { - this.import(); - }; - - // TODO - sort this function out. it's a mess - async import() { const { data, results, dataViewsContract, fileUpload } = this.props; + const { + index, + dataView, + createDataView, + indexSettingsString, + mappingsString, + pipelineString, + pipelineId, + } = this.state; - const { format } = results; - let { timeFieldName } = this.state; - const { index, dataView, createDataView, indexSettingsString, mappingsString, pipelineString } = - this.state; - - const errors = []; - - if (index !== '') { - this.setState( - { - importing: true, - errors, - }, - async () => { - // check to see if the user has permission to create and ingest data into the specified index - if ( - (await fileUpload.hasImportPermission({ - checkCreateDataView: createDataView, - checkHasManagePipeline: true, - indexName: index, - })) === false - ) { - errors.push( - i18n.translate('xpack.dataVisualizer.file.importView.importPermissionError', { - defaultMessage: - 'You do not have permission to create or import data into index {index}.', - values: { - index, - }, - }) - ); - this.setState({ - permissionCheckStatus: IMPORT_STATUS.FAILED, - importing: false, - imported: false, - errors, - }); - return; - } - - this.setState( - { - importing: true, - imported: false, - reading: true, - initialized: true, - permissionCheckStatus: IMPORT_STATUS.COMPLETE, - }, - () => { - setTimeout(async () => { - let success = true; - const createPipeline = pipelineString !== ''; - - let settings = {}; - let mappings = {}; - let pipeline = {}; - - try { - settings = JSON.parse(indexSettingsString); - } catch (error) { - success = false; - const parseError = i18n.translate( - 'xpack.dataVisualizer.file.importView.parseSettingsError', - { - defaultMessage: 'Error parsing settings:', - } - ); - errors.push(`${parseError} ${error.message}`); - } - - try { - mappings = JSON.parse(mappingsString); - } catch (error) { - success = false; - const parseError = i18n.translate( - 'xpack.dataVisualizer.file.importView.parseMappingsError', - { - defaultMessage: 'Error parsing mappings:', - } - ); - errors.push(`${parseError} ${error.message}`); - } - - try { - if (createPipeline) { - pipeline = JSON.parse(pipelineString); - } - } catch (error) { - success = false; - const parseError = i18n.translate( - 'xpack.dataVisualizer.file.importView.parsePipelineError', - { - defaultMessage: 'Error parsing ingest pipeline:', - } - ); - errors.push(`${parseError} ${error.message}`); - } - - this.setState({ - parseJSONStatus: success ? IMPORT_STATUS.COMPLETE : IMPORT_STATUS.FAILED, - }); - - if (success) { - const importer = await fileUpload.importerFactory(format, { - excludeLinesPattern: results.exclude_lines_pattern, - multilineStartPattern: results.multiline_start_pattern, - }); - if (importer !== undefined) { - const readResp = importer.read(data, this.setReadProgress); - success = readResp.success; - this.setState({ - readStatus: success ? IMPORT_STATUS.COMPLETE : IMPORT_STATUS.FAILED, - reading: false, - importer, - }); - - if (readResp.success === false) { - console.error(readResp.error); - errors.push(readResp.error); - } - - if (success) { - const initializeImportResp = await importer.initializeImport( - index, - settings, - mappings, - pipeline - ); - - timeFieldName = importer.getTimeField(); - this.setState({ timeFieldName }); - - const indexCreated = initializeImportResp.index !== undefined; - this.setState({ - indexCreatedStatus: indexCreated - ? IMPORT_STATUS.COMPLETE - : IMPORT_STATUS.FAILED, - }); - - if (createPipeline) { - const pipelineCreated = initializeImportResp.pipelineId !== undefined; - if (indexCreated) { - this.setState({ - ingestPipelineCreatedStatus: pipelineCreated - ? IMPORT_STATUS.COMPLETE - : IMPORT_STATUS.FAILED, - ingestPipelineId: pipelineCreated - ? initializeImportResp.pipelineId - : '', - }); - } - success = indexCreated && pipelineCreated; - } else { - success = indexCreated; - } - - if (success) { - const importId = initializeImportResp.id; - const pipelineId = initializeImportResp.pipelineId; - const importResp = await importer.import( - importId, - index, - pipelineId, - this.setImportProgress - ); - success = importResp.success; - this.setState({ - uploadStatus: importResp.success - ? IMPORT_STATUS.COMPLETE - : IMPORT_STATUS.FAILED, - importFailures: importResp.failures, - docCount: importResp.docCount, - }); - - if (success) { - if (createDataView) { - const dataViewName = dataView === '' ? index : dataView; - const dataViewResp = await createKibanaDataView( - dataViewName, - dataViewsContract, - timeFieldName - ); - success = dataViewResp.success; - this.setState({ - dataViewCreatedStatus: dataViewResp.success - ? IMPORT_STATUS.COMPLETE - : IMPORT_STATUS.FAILED, - dataViewId: dataViewResp.id, - }); - if (dataViewResp.success === false) { - errors.push(dataViewResp.error); - } - } - } else { - errors.push(importResp.error); - } - } else { - errors.push(initializeImportResp.error); - } - } - } - } - - this.setState({ - importing: false, - imported: success, - errors, - }); - }, 500); - } - ); - } - ); - } - } + importData( + { data, results, dataViewsContract, fileUpload }, + { + index, + dataView, + createDataView, + indexSettingsString, + mappingsString, + pipelineString, + pipelineId, + }, + (state) => this.setState(state) + ); + }; onConfigModeChange = (configMode) => { this.setState({ @@ -325,8 +130,7 @@ export class ImportView extends Component { }); }; - onIndexChange = (e) => { - const index = e.target.value; + onIndexChange = (index) => { this.setState({ index, checkingValidIndex: true, @@ -385,16 +189,22 @@ export class ImportView extends Component { }); }; - onCombinedFieldsChange = (combinedFields) => { - this.setState({ combinedFields }); + onPipelineIdChange = (text) => { + this.setState({ + pipelineId: text, + }); }; - setImportProgress = (progress) => { + onCreatePipelineChange = (b) => { this.setState({ - uploadProgress: progress, + createPipeline: b, }); }; + onCombinedFieldsChange = (combinedFields) => { + this.setState({ combinedFields }); + }; + setReadProgress = (progress) => { this.setState({ readProgress: progress, @@ -409,6 +219,10 @@ export class ImportView extends Component { this.setState({ isFilebeatFlyoutVisible: false }); }; + closeFilebeatFlyout = () => { + this.setState({ isFilebeatFlyoutVisible: false }); + }; + async loadDataViewNames() { try { const dataViewNames = await this.dataViewsContract.getTitles(); @@ -423,7 +237,7 @@ export class ImportView extends Component { index, dataView, dataViewId, - ingestPipelineId, + pipelineId, importing, imported, reading, @@ -450,10 +264,9 @@ export class ImportView extends Component { checkingValidIndex, combinedFields, importer, + createPipeline, } = this.state; - const createPipeline = pipelineString !== ''; - const statuses = { reading, readStatus, @@ -567,13 +380,15 @@ export class ImportView extends Component { - {importer !== undefined && importer.initialized() && ( - - )} + {importer !== undefined && + importer.initialized() && + this.props.results.format !== FILE_FORMATS.TIKA && ( + + )} {imported === true && ( @@ -582,7 +397,7 @@ export class ImportView extends Component { {isFilebeatFlyoutVisible && ( )} @@ -648,25 +464,6 @@ export class ImportView extends Component { } } -async function createKibanaDataView(dataViewName, dataViewsContract, timeFieldName) { - try { - const emptyPattern = await dataViewsContract.createAndSave({ - title: dataViewName, - timeFieldName, - }); - - return { - success: true, - id: emptyPattern.id, - }; - } catch (error) { - return { - success: false, - error, - }; - } -} - function getDefaultState(state, results, capabilities) { const indexSettingsString = state.indexSettingsString === '' diff --git a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/results_view/results_view.tsx b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/results_view/results_view.tsx index 0c55b838e37b8..5e8658ab85433 100644 --- a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/results_view/results_view.tsx +++ b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/results_view/results_view.tsx @@ -28,7 +28,8 @@ import { FieldsStatsGrid } from '../../../common/components/fields_stats_grid'; import { MODE as DATAVISUALIZER_MODE } from '../file_data_visualizer_view/constants'; interface Props { - data: string; + fileContents: string; + data: ArrayBuffer; fileName: string; results: FindFileStructureResponse; showEditFlyout(): void; @@ -40,7 +41,7 @@ interface Props { } export const ResultsView: FC = ({ - data, + fileContents, fileName, results, showEditFlyout, @@ -87,7 +88,7 @@ export const ResultsView: FC = ({

= ({ - showExplanationFlyout()} disabled={disableButtons}> - - + {results.format !== FILE_FORMATS.TIKA ? ( + showExplanationFlyout()} disabled={disableButtons}> + + + ) : null} - + {results.format !== FILE_FORMATS.TIKA ? ( + <> + - - -

- -

-
+ + +

+ +

+
- -
+ +
+ + ) : null}
); diff --git a/x-pack/plugins/data_visualizer/server/routes.ts b/x-pack/plugins/data_visualizer/server/routes.ts index c4e286f9671d1..a21f1ed93c1d3 100644 --- a/x-pack/plugins/data_visualizer/server/routes.ts +++ b/x-pack/plugins/data_visualizer/server/routes.ts @@ -66,4 +66,32 @@ export function routes(coreSetup: CoreSetup, logger: Logger) } } ); + + router.versioned + .get({ + path: '/internal/data_visualizer/inference_services', + access: 'internal', + options: { + tags: ['access:fileUpload:analyzeFile'], + }, + }) + .addVersion( + { + version: '1', + validate: false, + }, + async (context, request, response) => { + try { + const esClient = (await context.core).elasticsearch.client; + // @ts-expect-error types are wrong + const { endpoints } = await esClient.asCurrentUser.inference.getModel({ + inference_id: '_all', + }); + + return response.ok({ body: endpoints }); + } catch (e) { + return response.customError(wrapError(e)); + } + } + ); } diff --git a/x-pack/plugins/data_visualizer/tsconfig.json b/x-pack/plugins/data_visualizer/tsconfig.json index ed8a3540f6d8a..79060fbbe53f9 100644 --- a/x-pack/plugins/data_visualizer/tsconfig.json +++ b/x-pack/plugins/data_visualizer/tsconfig.json @@ -83,6 +83,7 @@ "@kbn/shared-ux-utility", "@kbn/search-types", "@kbn/unified-field-list", + "@kbn/core-http-browser", "@kbn/content-management-utils", "@kbn/core-lifecycle-browser", "@kbn/presentation-containers", diff --git a/x-pack/plugins/file_upload/common/constants.ts b/x-pack/plugins/file_upload/common/constants.ts index 725cd3f81a650..af0c3c07db6c8 100644 --- a/x-pack/plugins/file_upload/common/constants.ts +++ b/x-pack/plugins/file_upload/common/constants.ts @@ -8,9 +8,10 @@ export const UI_SETTING_MAX_FILE_SIZE = 'fileUpload:maxFileSize'; export const MB = Math.pow(2, 20); export const MAX_FILE_SIZE = '100MB'; -export const MAX_FILE_SIZE_BYTES = 104857600; // 100MB +export const MAX_FILE_SIZE_BYTES = 524288000; // 500MB export const ABSOLUTE_MAX_FILE_SIZE_BYTES = 1073741274; // 1GB export const FILE_SIZE_DISPLAY_FORMAT = '0,0.[0] b'; +export const MAX_TIKA_FILE_SIZE_BYTES = 62914560; // 60MB // Value to use in the Elasticsearch index mapping meta data to identify the // index as having been created by the ML File Data Visualizer. @@ -20,5 +21,5 @@ export const FILE_FORMATS = { DELIMITED: 'delimited', NDJSON: 'ndjson', SEMI_STRUCTURED_TEXT: 'semi_structured_text', - // XML: 'xml', + TIKA: 'tika', }; diff --git a/x-pack/plugins/file_upload/common/types.ts b/x-pack/plugins/file_upload/common/types.ts index f752d5e5a8507..409b5fcac80a1 100644 --- a/x-pack/plugins/file_upload/common/types.ts +++ b/x-pack/plugins/file_upload/common/types.ts @@ -28,6 +28,7 @@ export interface FindFileStructureResponse { has_header_row: boolean; has_byte_order_marker: boolean; format: string; + document_type?: string; field_stats: { [fieldName: string]: { count: number; @@ -56,6 +57,7 @@ export interface FindFileStructureResponse { }; }; }; + ingest_pipeline: IngestPipeline; quote: string; delimiter: string; need_client_timezone: boolean; @@ -123,14 +125,32 @@ export interface ImportDocMessage { message: string; } -export type ImportDoc = ImportDocMessage | string | object; +export interface ImportDocTika { + data: string; +} + +export type ImportDoc = ImportDocMessage | ImportDocTika | string | object; export interface IngestPipelineWrapper { id: string; - pipeline: IngestPipeline; + pipeline?: IngestPipeline; } export interface IngestPipeline { description: string; processors: any[]; + isManaged?: boolean; + name?: string; +} + +export interface PreviewTikaResponse { + date?: string; + content_type: string; + author?: string; + format: string; + modified: string; + language: string; + creator_tool?: string; + content: string; + content_length: number; } diff --git a/x-pack/plugins/file_upload/public/api/index.ts b/x-pack/plugins/file_upload/public/api/index.ts index 4d6483f2b2a50..36314ae849680 100644 --- a/x-pack/plugins/file_upload/public/api/index.ts +++ b/x-pack/plugins/file_upload/public/api/index.ts @@ -5,10 +5,20 @@ * 2.0. */ +import { fromByteArray } from 'base64-js'; import { lazyLoadModules } from '../lazy_load_bundle'; import type { IImporter, ImportFactoryOptions } from '../importer'; -import type { HasImportPermission, FindFileStructureResponse } from '../../common/types'; -import type { getMaxBytes, getMaxBytesFormatted } from '../importer/get_max_bytes'; +import type { + HasImportPermission, + FindFileStructureResponse, + PreviewTikaResponse, +} from '../../common/types'; +import type { + getMaxBytes, + getMaxBytesFormatted, + getMaxTikaBytes, + getMaxTikaBytesFormatted, +} from '../importer/get_max_bytes'; import { GeoUploadWizardAsyncWrapper } from './geo_upload_wizard_async_wrapper'; import { IndexNameFormAsyncWrapper } from './index_name_form_async_wrapper'; @@ -18,10 +28,13 @@ export interface FileUploadStartApi { importerFactory: typeof importerFactory; getMaxBytes: typeof getMaxBytes; getMaxBytesFormatted: typeof getMaxBytesFormatted; + getMaxTikaBytes: typeof getMaxTikaBytes; + getMaxTikaBytesFormatted: typeof getMaxTikaBytesFormatted; hasImportPermission: typeof hasImportPermission; checkIndexExists: typeof checkIndexExists; getTimeFieldRange: typeof getTimeFieldRange; analyzeFile: typeof analyzeFile; + previewTikaFile: typeof previewTikaFile; } export interface GetTimeFieldRangeResponse { @@ -36,7 +49,7 @@ export const IndexNameFormComponent = IndexNameFormAsyncWrapper; export async function importerFactory( format: string, options: ImportFactoryOptions -): Promise { +): Promise { const fileUploadModules = await lazyLoadModules(); return fileUploadModules.importerFactory(format, options); } @@ -62,6 +75,24 @@ export async function analyzeFile( }); } +export async function previewTikaFile( + data: ArrayBuffer, + params: Record = {} +): Promise { + const { getHttp } = await lazyLoadModules(); + const base64File = fromByteArray(new Uint8Array(data)); + const body = JSON.stringify({ + base64File, + }); + return await getHttp().fetch({ + path: `/internal/file_upload/preview_tika_contents`, + method: 'POST', + version: '1', + body, + query: params, + }); +} + export async function hasImportPermission(params: HasImportPermissionParams): Promise { const fileUploadModules = await lazyLoadModules(); try { diff --git a/x-pack/plugins/file_upload/public/importer/get_max_bytes.ts b/x-pack/plugins/file_upload/public/importer/get_max_bytes.ts index e05f1978dcf95..d4f7457384533 100644 --- a/x-pack/plugins/file_upload/public/importer/get_max_bytes.ts +++ b/x-pack/plugins/file_upload/public/importer/get_max_bytes.ts @@ -12,6 +12,7 @@ import { MAX_FILE_SIZE, MAX_FILE_SIZE_BYTES, UI_SETTING_MAX_FILE_SIZE, + MAX_TIKA_FILE_SIZE_BYTES, } from '../../common/constants'; import { getUiSettings } from '../kibana_services'; @@ -28,3 +29,11 @@ export function getMaxBytes() { export function getMaxBytesFormatted() { return numeral(getMaxBytes()).format(FILE_SIZE_DISPLAY_FORMAT); } + +export function getMaxTikaBytes() { + return MAX_TIKA_FILE_SIZE_BYTES; +} + +export function getMaxTikaBytesFormatted() { + return numeral(getMaxTikaBytes()).format(FILE_SIZE_DISPLAY_FORMAT); +} diff --git a/x-pack/plugins/file_upload/public/importer/importer.ts b/x-pack/plugins/file_upload/public/importer/importer.ts index 94a15b9905ff0..6337e892868fe 100644 --- a/x-pack/plugins/file_upload/public/importer/importer.ts +++ b/x-pack/plugins/file_upload/public/importer/importer.ts @@ -27,7 +27,7 @@ const DEFAULT_TIME_FIELD = '@timestamp'; export abstract class Importer implements IImporter { protected _docArray: ImportDoc[] = []; - private _chunkSize = CHUNK_SIZE; + protected _chunkSize = CHUNK_SIZE; private _index: string | undefined; private _pipeline: IngestPipeline | undefined; private _timeFieldName: string | undefined; @@ -282,6 +282,10 @@ function updatePipelineTimezone(ingestPipeline: IngestPipeline) { } function createDocumentChunks(docArray: ImportDoc[], chunkSize: number) { + if (chunkSize === 0) { + return [docArray]; + } + const chunks: ImportDoc[][] = []; // chop docArray into chunks const tempChunks = chunk(docArray, chunkSize); diff --git a/x-pack/plugins/file_upload/public/importer/importer_factory.ts b/x-pack/plugins/file_upload/public/importer/importer_factory.ts index 0ad05676244be..28c7364b2eb21 100644 --- a/x-pack/plugins/file_upload/public/importer/importer_factory.ts +++ b/x-pack/plugins/file_upload/public/importer/importer_factory.ts @@ -7,6 +7,7 @@ import { MessageImporter } from './message_importer'; import { NdjsonImporter } from './ndjson_importer'; +import { TikaImporter } from './tika_importer'; import { ImportFactoryOptions } from './types'; import { FILE_FORMATS } from '../../common/constants'; @@ -21,7 +22,9 @@ export function importerFactory(format: string, options: ImportFactoryOptions) { return new MessageImporter(options); case FILE_FORMATS.NDJSON: return new NdjsonImporter(); + case FILE_FORMATS.TIKA: + return new TikaImporter(); default: - return; + throw new Error('Importer not found for format'); } } diff --git a/x-pack/plugins/file_upload/public/importer/tika_importer.ts b/x-pack/plugins/file_upload/public/importer/tika_importer.ts new file mode 100644 index 0000000000000..78ccf86003385 --- /dev/null +++ b/x-pack/plugins/file_upload/public/importer/tika_importer.ts @@ -0,0 +1,48 @@ +/* + * 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 { fromByteArray } from 'base64-js'; +import { ImportDocTika } from '../../common/types'; +import { Importer } from './importer'; +import { CreateDocsResponse } from './types'; + +export class TikaImporter extends Importer { + constructor() { + super(); + } + + public read(data: ArrayBuffer) { + this._chunkSize = 0; + const pdfBase64 = fromByteArray(new Uint8Array(data)); + const { success, docs } = this._createDocs(pdfBase64); + if (success) { + this._docArray = this._docArray.concat(docs); + } else { + return { success: false }; + } + return { success: true }; + } + + protected _createDocs(base64String: string): CreateDocsResponse { + const remainder = 0; + try { + const docs = [{ data: base64String }]; + return { + success: true, + docs, + remainder, + }; + } catch (error) { + return { + success: false, + docs: [], + remainder, + error, + }; + } + } +} diff --git a/x-pack/plugins/file_upload/public/lazy_load_bundle/index.ts b/x-pack/plugins/file_upload/public/lazy_load_bundle/index.ts index 0066a2efbc5cb..d7886ec35b675 100644 --- a/x-pack/plugins/file_upload/public/lazy_load_bundle/index.ts +++ b/x-pack/plugins/file_upload/public/lazy_load_bundle/index.ts @@ -35,7 +35,7 @@ let loadModulesPromise: Promise; export interface LazyLoadedFileUploadModules { GeoUploadWizard: React.ComponentType; IndexNameForm: React.ComponentType; - importerFactory: (format: string, options: ImportFactoryOptions) => IImporter | undefined; + importerFactory: (format: string, options: ImportFactoryOptions) => IImporter; getHttp: () => HttpStart; } diff --git a/x-pack/plugins/file_upload/public/plugin.ts b/x-pack/plugins/file_upload/public/plugin.ts index cbf64371fc4c3..cfb3e2fcf723d 100644 --- a/x-pack/plugins/file_upload/public/plugin.ts +++ b/x-pack/plugins/file_upload/public/plugin.ts @@ -16,9 +16,15 @@ import { checkIndexExists, getTimeFieldRange, analyzeFile, + previewTikaFile, } from './api'; import { setStartServices } from './kibana_services'; -import { getMaxBytes, getMaxBytesFormatted } from './importer/get_max_bytes'; +import { + getMaxBytes, + getMaxBytesFormatted, + getMaxTikaBytes, + getMaxTikaBytesFormatted, +} from './importer/get_max_bytes'; // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface FileUploadSetupDependencies {} @@ -48,10 +54,13 @@ export class FileUploadPlugin importerFactory, getMaxBytes, getMaxBytesFormatted, + getMaxTikaBytes, + getMaxTikaBytesFormatted, hasImportPermission, checkIndexExists, getTimeFieldRange, analyzeFile, + previewTikaFile, }; } } diff --git a/x-pack/plugins/file_upload/server/preview_tika_contents.ts b/x-pack/plugins/file_upload/server/preview_tika_contents.ts new file mode 100644 index 0000000000000..f99a070d90414 --- /dev/null +++ b/x-pack/plugins/file_upload/server/preview_tika_contents.ts @@ -0,0 +1,50 @@ +/* + * 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 type { IScopedClusterClient } from '@kbn/core/server'; +import type { PreviewTikaResponse } from '../common/types'; + +/** + * Returns the contents of a file using the attachment ingest processor + * @param client IScopedClusterClient + * @param base64File bae64 encoded file + */ +export async function previewTikaContents( + client: IScopedClusterClient, + base64File: string +): Promise { + const pipeline = { + description: '', + processors: [ + { + attachment: { + field: 'data', + remove_binary: true, + }, + }, + ], + }; + + const resp = await client.asInternalUser.ingest.simulate({ + pipeline, + docs: [ + { + _index: 'index', + _id: 'id', + _source: { + data: base64File, + }, + }, + ], + }); + + if (!resp.docs[0].doc?._source.attachment) { + throw new Error('Failed to extract text from file.'); + } + + return resp.docs[0].doc?._source.attachment; +} diff --git a/x-pack/plugins/file_upload/server/routes.ts b/x-pack/plugins/file_upload/server/routes.ts index 6d80f8f05cb3a..4336049b7fe58 100644 --- a/x-pack/plugins/file_upload/server/routes.ts +++ b/x-pack/plugins/file_upload/server/routes.ts @@ -12,7 +12,7 @@ import type { IndicesIndexSettings, MappingTypeMapping, } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { MAX_FILE_SIZE_BYTES } from '../common/constants'; +import { MAX_FILE_SIZE_BYTES, MAX_TIKA_FILE_SIZE_BYTES } from '../common/constants'; import type { IngestPipelineWrapper, InputData } from '../common/types'; import { wrapError } from './error_wrapper'; import { importDataProvider } from './import_data'; @@ -29,6 +29,7 @@ import { import type { StartDeps } from './types'; import { checkFileUploadPrivileges } from './check_privileges'; import { previewIndexTimeRange } from './preview_index_time_range'; +import { previewTikaContents } from './preview_tika_contents'; function importData( client: IScopedClusterClient, @@ -314,6 +315,51 @@ export function fileUploadRoutes(coreSetup: CoreSetup, logge const esClient = (await context.core).elasticsearch.client; const resp = await previewIndexTimeRange(esClient, timeField, pipeline, docs); + return response.ok({ + body: resp, + }); + } catch (e) { + return response.customError(wrapError(e)); + } + } + ); + + /** + * @apiGroup FileDataVisualizer + * + * @api {post} /internal/file_upload/preview_tika_contents Returns the contents of a file using the attachment ingest processor + * @apiName PreviewTikaContents + * @apiDescription Preview the contents of a file using the attachment ingest processor + */ + router.versioned + .post({ + path: '/internal/file_upload/preview_tika_contents', + access: 'internal', + options: { + tags: ['access:fileUpload:analyzeFile'], + body: { + accepts: ['application/json'], + maxBytes: MAX_TIKA_FILE_SIZE_BYTES, + }, + }, + }) + .addVersion( + { + version: '1', + validate: { + request: { + body: schema.object({ + base64File: schema.string(), + }), + }, + }, + }, + async (context, request, response) => { + try { + const { base64File } = request.body; + const esClient = (await context.core).elasticsearch.client; + const resp = await previewTikaContents(esClient, base64File); + return response.ok({ body: resp, }); diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 580e8255cb29a..a0443e37fa617 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -14992,8 +14992,6 @@ "xpack.dataVisualizer.file.welcomeContent.delimitedTextFilesDescription": "Fichiers texte délimités, tels que CSV et TSV", "xpack.dataVisualizer.file.welcomeContent.logFilesWithCommonFormatDescription": "Fichiers log avec un format d'horodatage courant", "xpack.dataVisualizer.file.welcomeContent.newlineDelimitedJsonDescription": "JSON délimité par une nouvelle ligne", - "xpack.dataVisualizer.file.welcomeContent.supportedFileFormatDescription": "Les formats de fichier suivants sont pris en charge :", - "xpack.dataVisualizer.file.welcomeContent.uploadedFilesAllowedSizeDescription": "Vous pouvez charger des fichiers d'une taille allant jusqu'à {maxFileSize}.", "xpack.dataVisualizer.file.welcomeContent.visualizeAndImportDataFromLogFileDescription": "Chargez votre fichier, analysez ses données et, si vous le souhaitez, importez les données dans un index Elasticsearch.", "xpack.dataVisualizer.file.welcomeContent.visualizeDataFromLogFileDescription": "Téléchargez votre fichier et analysez ses données.", "xpack.dataVisualizer.file.welcomeContent.visualizeDataFromLogFileTitle": "Charger les données à partir d'un fichier", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 7eea338195202..e662987308271 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -14978,8 +14978,6 @@ "xpack.dataVisualizer.file.welcomeContent.delimitedTextFilesDescription": "CSV や TSV などの区切られたテキストファイル", "xpack.dataVisualizer.file.welcomeContent.logFilesWithCommonFormatDescription": "タイムスタンプの一般的フォーマットのログファイル", "xpack.dataVisualizer.file.welcomeContent.newlineDelimitedJsonDescription": "改行区切りの JSON", - "xpack.dataVisualizer.file.welcomeContent.supportedFileFormatDescription": "次のファイル形式がサポートされます。", - "xpack.dataVisualizer.file.welcomeContent.uploadedFilesAllowedSizeDescription": "最大{maxFileSize}のファイルをアップロードできます。", "xpack.dataVisualizer.file.welcomeContent.visualizeAndImportDataFromLogFileDescription": "ファイルをアップロードして、データを分析し、任意でデータをElasticsearchインデックスにインポートできます。", "xpack.dataVisualizer.file.welcomeContent.visualizeDataFromLogFileDescription": "ファイルをアップロードし、データを分析します。", "xpack.dataVisualizer.file.welcomeContent.visualizeDataFromLogFileTitle": "ファイルからデータをアップロード", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 76ac5c13e4e13..ef6badee07f44 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -15003,8 +15003,6 @@ "xpack.dataVisualizer.file.welcomeContent.delimitedTextFilesDescription": "分隔的文本文件,例如 CSV 和 TSV", "xpack.dataVisualizer.file.welcomeContent.logFilesWithCommonFormatDescription": "具有时间戳通用格式的日志文件", "xpack.dataVisualizer.file.welcomeContent.newlineDelimitedJsonDescription": "换行符分隔的 JSON", - "xpack.dataVisualizer.file.welcomeContent.supportedFileFormatDescription": "支持以下文件格式:", - "xpack.dataVisualizer.file.welcomeContent.uploadedFilesAllowedSizeDescription": "您可以上传不超过 {maxFileSize} 的文件。", "xpack.dataVisualizer.file.welcomeContent.visualizeAndImportDataFromLogFileDescription": "上传文件、分析文件数据,然后根据需要将数据导入 Elasticsearch 索引。", "xpack.dataVisualizer.file.welcomeContent.visualizeDataFromLogFileDescription": "上传您的文件并分析其数据。", "xpack.dataVisualizer.file.welcomeContent.visualizeDataFromLogFileTitle": "从文件上传数据", diff --git a/x-pack/test/api_integration/apis/file_upload/index.ts b/x-pack/test/api_integration/apis/file_upload/index.ts index f2232c0cfcbce..9e1a913664a83 100644 --- a/x-pack/test/api_integration/apis/file_upload/index.ts +++ b/x-pack/test/api_integration/apis/file_upload/index.ts @@ -12,5 +12,6 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./has_import_permission')); loadTestFile(require.resolve('./index_exists')); loadTestFile(require.resolve('./preview_index_time_range')); + loadTestFile(require.resolve('./preview_tika_contents')); }); } diff --git a/x-pack/test/api_integration/apis/file_upload/pdf_base64.ts b/x-pack/test/api_integration/apis/file_upload/pdf_base64.ts new file mode 100644 index 0000000000000..8d6e40b2c9162 --- /dev/null +++ b/x-pack/test/api_integration/apis/file_upload/pdf_base64.ts @@ -0,0 +1,8 @@ +/* + * 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. + */ +export const pdfBase64 = + 'JVBERi0xLjUNCiW1tbW1DQoxIDAgb2JqDQo8PC9UeXBlL0NhdGFsb2cvUGFnZXMgMiAwIFIvTGFuZyhlbi1VUykgL1N0cnVjdFRyZWVSb290IDkgMCBSL01hcmtJbmZvPDwvTWFya2VkIHRydWU+Pj4+DQplbmRvYmoNCjIgMCBvYmoNCjw8L1R5cGUvUGFnZXMvQ291bnQgMS9LaWRzWyAzIDAgUl0gPj4NCmVuZG9iag0KMyAwIG9iag0KPDwvVHlwZS9QYWdlL1BhcmVudCAyIDAgUi9SZXNvdXJjZXM8PC9Gb250PDwvRjEgNSAwIFI+Pi9FeHRHU3RhdGU8PC9HUzcgNyAwIFI+Pi9Qcm9jU2V0Wy9QREYvVGV4dC9JbWFnZUIvSW1hZ2VDL0ltYWdlSV0gPj4vTWVkaWFCb3hbIDAgMCA2MTIgNzkyXSAvQ29udGVudHMgNCAwIFIvR3JvdXA8PC9UeXBlL0dyb3VwL1MvVHJhbnNwYXJlbmN5L0NTL0RldmljZVJHQj4+L1RhYnMvUy9TdHJ1Y3RQYXJlbnRzIDA+Pg0KZW5kb2JqDQo0IDAgb2JqDQo8PC9GaWx0ZXIvRmxhdGVEZWNvZGUvTGVuZ3RoIDE3Mz4+DQpzdHJlYW0NCnicdY0/C4MwFMT3QL7DjclgTGIaGxAH/9KCUKibdOigVmgn/f40DoU6hPd4HLy73yG+IcvirrxUkHmOoipR9JTEjYJSQhr0EyUK0o9CqoXUBql04uQ/H+9r7ynmlRKJeT8tJQPrX8sKv09wx7aRRwlbNy/BH+ivlNS+YC/5YZV2Qtt/7MBu3LKKR4Y1oZCxIj0fQ8EC40RytE7Lmxs2hgI2ESrMRt2V+AImUj6DDQplbmRzdHJlYW0NCmVuZG9iag0KNSAwIG9iag0KPDwvVHlwZS9Gb250L1N1YnR5cGUvVHJ1ZVR5cGUvTmFtZS9GMS9CYXNlRm9udC9BQkNERUUrQ2FsaWJyaS9FbmNvZGluZy9XaW5BbnNpRW5jb2RpbmcvRm9udERlc2NyaXB0b3IgNiAwIFIvRmlyc3RDaGFyIDMyL0xhc3RDaGFyIDExNi9XaWR0aHMgMTYgMCBSPj4NCmVuZG9iag0KNiAwIG9iag0KPDwvVHlwZS9Gb250RGVzY3JpcHRvci9Gb250TmFtZS9BQkNERUUrQ2FsaWJyaS9GbGFncyAzMi9JdGFsaWNBbmdsZSAwL0FzY2VudCA3NTAvRGVzY2VudCAtMjUwL0NhcEhlaWdodCA3NTAvQXZnV2lkdGggNTIxL01heFdpZHRoIDE3NDMvRm9udFdlaWdodCA0MDAvWEhlaWdodCAyNTAvU3RlbVYgNTIvRm9udEJCb3hbIC01MDMgLTI1MCAxMjQwIDc1MF0gL0ZvbnRGaWxlMiAxNyAwIFI+Pg0KZW5kb2JqDQo3IDAgb2JqDQo8PC9UeXBlL0V4dEdTdGF0ZS9CTS9Ob3JtYWwvY2EgMT4+DQplbmRvYmoNCjggMCBvYmoNCjw8L0F1dGhvcihKb2huKSAvQ3JlYXRvcij+/wBNAGkAYwByAG8AcwBvAGYAdACuACAAVwBvAHIAZAAgADIAMAAxADApIC9DcmVhdGlvbkRhdGUoRDoyMDEwMTIwMTA4MzMyNC0wNScwMCcpIC9Nb2REYXRlKEQ6MjAxMDEyMDEwODMzMjQtMDUnMDAnKSAvUHJvZHVjZXIo/v8ATQBpAGMAcgBvAHMAbwBmAHQArgAgAFcAbwByAGQAIAAyADAAMQAwKSA+Pg0KZW5kb2JqDQoxNSAwIG9iag0KPDwvVHlwZS9PYmpTdG0vTiA2L0ZpcnN0IDM4L0ZpbHRlci9GbGF0ZURlY29kZS9MZW5ndGggMjgzPj4NCnN0cmVhbQ0KeJxtUcGKgzAQvRf6D/MHY1zLIpTCsm3ZpVREhT2UHlKd1VBNShqh/ftN1GIOC2GYN/Pey2TC3iAAFsKKQQwssLk9MQPGIArfgUUQrQJYrzF1rAAyzDHF4nkjzI3uS7NrqcPDCYIzYFqDs8s2m+VikMQvBdfmPxEb6GeYBB6j0ESZUgYz1dKR39xczss6kRy6bkRXcTbhaON1E3qYAz2BTdZ76yWVIUxc2MlqBoWlXtQDcyoNfhGvSI+507zyb9kKSXnD3YSu8CGtAzdCyQlrI365TQb0o/T1otQVt6rsOzvTULk3RGZcxpGXWnn4s7HRw1vBW1V7hbwVFXnc8R5LqzXvcC/qXtP01qTv7if3rdG83XnXy8Ufkl+bXw0KZW5kc3RyZWFtDQplbmRvYmoNCjE2IDAgb2JqDQpbIDIyNiAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgNjE1IDAgNDU5IDAgMCAwIDAgMCAwIDAgMCAwIDUxNyAwIDAgMCA0ODcgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgNDc5IDAgMCAwIDQ5OCAzMDUgMCA1MjUgMjMwIDAgMCAyMzAgMCAwIDAgMCAwIDAgMzkxIDMzNV0gDQplbmRvYmoNCjE3IDAgb2JqDQo8PC9GaWx0ZXIvRmxhdGVEZWNvZGUvTGVuZ3RoIDgwMTQ2L0xlbmd0aDEgMTc0MjYwPj4NCnN0cmVhbQ0KeJzsewl8lNW5/jnfrJklM5PJZJskM8kkgZCEAAkhYcuQlRAChGQgAQIJCZuChH0REEFRgyjWFUXEqmDFZTKABFdU1Grdaq22bsXWrSruSwUh9znfOwcCtf5779/e3v5+Ockzz3Pes3znvGf53sjIOGPMhQ8tm1BWV1V5fMXXaUzZks2Y+9LykrJ6j+65txjbiUq6F8tLxpa+9chFyGwPMqaZUFlWXvHBE1/9wJTLhiP/aeWE8XXz2oZtYOyOlxjfbqmsC5Q8+fZfupky6k3GKqePr8sd9P27B1cyxv+ADptbF7S0Z8VmLmSsj+ivrHX5Um/wpsMvM9bgxfMSZ7fPWfDttzUWxvp9zVhEwpyWJe0skfnwfDEg+5z5q2b77jlxC2NNeL7jw7mzWtreTz85Av1PQ3nBXBis9+hfR/4a5NPmLli6ssRprGdMKWQsffm5sxafl3Fh+j7GtsxH+Q/zF7a2HB/y/TrGFqYxllyxoGVle0pO2la070K597yWBbMyltdiLFfMZSwypn3hkqXdbrYJ41kvytsXz2o/9z7lJGP5djzOzoRvdTu6joz9cvYM2/BvWLyRifTgx2ueE/xk6g2rjx87sTniE8P9yEYwhVFCOz07yfhh087jx47tjPhE7alH0mwTFlsqG890qkFhdpbLZsELW/FctYo2i29FqVG3TZeHLpOJNS+xTQozMsWmUxRFq1G07zCl28/u7lZHgFRT5/UyP8ROGoNhh5LhZfwWtdMDukgxU/QeeXo0/EX2syftJ+zu/0k7zT3/s3b/v0n/2s/3XG3qf78vzfvM9nM9vzf1pn82aX7Ppv0r+9fms+YznnecNf0z7ZRFLP1fMqD/5YT5b5Oav8ou/jn6RD/b/t+1ft6kPHvmMzUprPafancvS/nXjKg39abe1Jt6U2/61yXlJm76d4/hPy1pBrPN/+4x9Kbe1Jt6U2/qTb2pN/Wm3tSbelNv6k29qTf1pt7Um3pTb+pN/8tJE0Zi+FthDyAHpexiWrYD+WRmh0V8P8vKUlkZq2A1bAKrZy1sNpvH5rOlbGd3t9rSyrxnlLexuShfrJbz7m8Y636l+0j3d8yAHm8VDTie290afm7CGaOKYjH4jKERasZorucJPJn35VN4E7+cb+U3Mj3/RC394uxvsyGvhL/7prCfTvx0//9tv/19igMyzrCUqZ+Tw7m2fzgMdZw0QzDmqOYX9qhBc/7PSZqftbf/0zvRX9k2Y3rTtKlTGhsC9XUTayeMH1cztnpM1ejKivKy0pJR/uKRI4YPG1pUOKRgcG7/nOy+GelpvlRPXLTDbrOaTRFGg16n1SicZZf7Kpq9wYzmoDbDN3p0jsj7WmBo6WFoDnphqjizTtDbrFbznlnTj5qzz6rpp5r+UzW53TucDc/J9pb7vMHny3zeLj6ltgF6S5mv0Rs8quoaVWsz1IwVmZQUtPCWx80t8wZ5s7c8WLF8bkd5cxn66zSbSn2ls0w52azTZIY0QwX7+to7ed+RXBVK3/KhnQozWsVjg5r08pa24ITahvIyd0pKo2pjpWpfQX1p0KD25Z0nxsw2ezuzD3Vc3mVnM5uzLG2+tpZpDUFNCxp1aMo7Oi4JOrKCmb6yYObqd+Mw5VnBbF9ZeTDLh86qJ556AA/q0u0+b8c3DIP3Hf3kTEtL2KJPt3/DhBRTPOUmlEvNMDaMEPNLSRFj2dzlZzORCa6vbaC8l810h5g/N6sxqDSLkkOyxBUQJetlyanmzb4UsVTlzeHf5XPjgutnenOy4X31Nx2/KPcGNRnNM1vnCm6Z1eErKyO/1TcE/WUQ/pbwXMs7B+SifkszJjFPuKG2IZjraw9G+0qoAgxesQbz6hrUJuFmwejSIGtuDbcK5paXiXF5yzuay2iAoi9fbcNBltd9pDPf696bx/JZoxhHMKYUi5JR3tHQNjvoaXa3YX/O9ja4U4L+Rriv0dcwq1Gsks8ezDyCx6WoT1RbYW5n1ZaVxcwN6UZvg+LWNIrVgsFbgQ9fyXAU2LFcalasaMlwbwN3M1kNTwnXEOqMfpDRpJeOFkUa0bR0tDulMYXSTwzJHR6TLj1o7NGXHYZTY6Ln/MOhUW0xoExv+ayyHgM8o1NdeIDh3n58nIrwRfjBaGEUyzlaFmnScXJhU9CNahKrGOcNsgneBt8sX6MPe8g/oUHMTfhaXd/qOl917ZQGdbXDu6T+jByVF1IuyFJQLDNKKfZgRZZbLquar1Tzp7KjzyquksXeDqOvuq5DdO4Ld8i8OEGYtD6jqmVzYVQ+jmYFbjdfRYvPa/dWdLR0da+f2dHp93e0lzfPHSr68FW1dfjqGoa71bFObFjrXi0eFcWqeXV9SU427p6STh+/tLbTzy+tm9Jw0M6Y99L6hpDCldLmksbONJQ1HPQy5letirAKo8h4RUb0NBEZo1rffdDP2Hq1VKsa1HxrF2eqzShtnLV2KWSzS5sCm5ZsftUmEhYpbi5cjOu23NsmlmdN49yO5kZxuFgMlhK/PMh9I1lQ8Y3s5IreEjT5ZpUEzb4SYS8W9mKy64XdgI3BYzicI+6kjmYf7ilsqAbm5rQVNaJLb1d3d31DyvPuo40p2GrTgCkNwYgs3P269DGoVynQDHNlcH1rixgHCzSItob0qtZGbFvZIapUBSPQQ0S4B9SoUNuI7YhGrVgbLKDafj0ywfWNwcYs8dCGeY3qdrYH2WjfUCw79anLEA/KbeyI8g1SzyaOgin9EkERGBurayCLG1k8rJGcZLBg5K0+FLU2e+FtLWutw1anu9TkJsssXInajFkqTO5wIRPT0qSbraZgRH90iF+hzf3FkdSlGxobafBq7pJwBTzbHjRjRBk9XBluAO+gqEqMBb+XYKii6mOim9ouNtG3EjeLGLTakwHFQWt6VQsuf2pvhsVXKBsbxR1hDvdxmKwGMXML/K5Jr+/q3u1bldIj5WT7xMtBbEzmPoiNzRo7zjYEp2blZBvPtlpVc0eH0frjDchfRuspFkZvOd4ajIUiNN4u5aJ9EXF8DMRGKTZIcaEU66W4QIp1UqyVYo0U50uxWopVUqyUYoUUy6VYJsVSKZZIsUiKdikWSnGeFAukmC/FuVKcI8U8KeZKMUeK2VLMkqJNilYpZkrRIkWzFDOkmC5FkxTTpJgqxRQpGqVokGKyFJOkCEhRL0WdFBOlqJVighTjpRgnRY0UY6WolmKMFFVSjJaiUooKKcqlKJOiVIoSKUZJ4ZeiWIqRUoyQYrgUw6QYKkWRFIVSDJGiQIrBUuRLkSfFICkGSjFAilwp+kuRI0W2FFlS9JMiU4q+UvSRIkOKdCnSpPBJkSpFihReKTxSJEuRJEWiFG4pEqSIlyJOilgpYqRwSREthVOKKCkcUtilsEkRKYVVCosUZilMUkRIYZTCIIVeCp0UWik0UihScClYWPBuKU5KcUKKH6Q4LsUxKb6X4m9SfCfFt1J8I8XXUnwlxZdSfCHF51J8JsWnUhyV4hMpPpbiIyn+KsWHUnwgxftSvCfFu1L8RYo/S/GOFEek+JMUb0vxlhRvSvGGFK9L8Ucp/iDFa1K8KsXvpXhFit9J8bIUv5XiJSlelOIFKZ6X4jkpfiPFs1I8I8WvpXhaiqekeFKKw1I8IcXjUjwmxSEpHpXiESkeluIhKR6U4gEpDkrRJcUBKe6XYr8U+6TYK0VIik4pglLcJ8W9Utwjxd1S7JHiLil+JcWdUuyWYpcUd0hxuxS3SfFLKW6VYqcUt0ixQ4qbpdguxU1S3CjFNilukOJ6Ka6T4loprpHiail+IcVVUmyV4koprpBiixSXS7FZig4pLpPiUikukWKTFBdLIcMeLsMeLsMeLsMeLsMeLsMeLsMeLsMeLsMeLsMeLsMeLsMeLsMeLsMeLsMeLsMeLsMeLsMevlgKGf9wGf9wGf9wGf9wGf9wGf9wGf9wGf9wGf9wGf9wGf9wGf9wGf9wGf9wGf9wGf9wGf9wGf9wGf9wGf9wGf9wGf9wGf9wGf9wGf9wGf9wGf9wGf9wGf9wGf9wGf9wGf9wGfZwGfZwGfZwGe1wGe1wGe1wGe1wGe1wGe1wGe1wGe1wGe3w0r1CIGoOJY/0IGYOJbtAGyh3YSh5KGg95S4gWhdKtoDWUm4N0flEq4lWhZJGgVaGkkpBK4iWEy2jsqWUW0K0mIyLQkkloHaihUTnUZUFRPOJzg0lloPOIZpHNJdoDtHsUGIZaBbl2ohaiWYStRA1E80gmk7tmig3jWgq0RSiRqIGoslEk4gCRPVEdUQTiWqJJhCNJxpHVEM0lqiaaEzIXQWqIhodco8BVRJVhNzVoPKQeyyojKiUqITKRlE7P1ExtRtJNIJoONUcRjSUmhcRFRINISogGkyd5RPlUS+DiAYSDaDOcon6U7scomyiLKJ+RJlEfYn6UNcZROnUZxqRjyiVuk4h8lI7D1EyURJRIpGbKCGUMA4UTxQXShgPiiWKIaOLKJqMTqIoIgeV2YlsZIwkshJZqMxMZCKKoDIjkYFIH4qfANKF4mtBWiINGRXKcSKmEu8mOqlW4Sco9wPRcaJjVPY95f5G9B3Rt0TfhOLqQV+H4upAX1HuS6IviD6nss8o9ynRUaJPqOxjoo/I+FeiD4k+IHqfqrxHuXcp9xfK/ZnoHaIjVPYnorfJ+BbRm0RvEL1OVf5IuT8QvRaKnQx6NRQ7CfR7olfI+Duil4l+S/QSVXmR6AUyPk/0HNFviJ6lKs8Q/ZqMTxM9RfQk0WGiJ6jm45R7jOgQ0aNU9gjRw2R8iOhBogeIDhJ1Uc0DlLufaD/RPqK9oZhiUCgUMxXUSRQkuo/oXqJ7iO4m2kN0VygG9zX/FfVyJ9FuKttFdAfR7US3Ef2S6FainUS3UGc7qJebibZT2U1ENxJtI7qBGlxPueuIriW6hsqupl5+QXQVlW0lupLoCqItRJdTzc2U6yC6jOhSokuINoVcLaCLQ66ZoIuINoZcs0EbiC4MuQKg9SEXLmN+QchVAFpHtJaar6F25xOtDrnaQKuo+UqiFUTLiZYRLSVaQl0vpuaLiNpDrlbQQursPKq5gGg+0blE5xDNo3ZziebQyGZT81lEbVSzlWgmUQtRM9EMouk06SYa2TSiqTTpKdR1Iz2ogWgyDXcSPShAvdQT1RFNJKoNRftBE0LR4gnjQ9Fie48LRW8E1YSic0BjqUo10ZhQNOICXkW50USVZKwIRa8DlYeiLwGVhaIvAJWGoteDSkJRFaBRRH6iYqKRoSi83/kIyg0PORpBw4iGhhxiaxQRFYYclaAhIUcDqCDkmAIaTGX5RHkhRzZoENUcGHKIiQ0IOcTZzCXqT81z6AnZRFnUWT+iTOqsL1Efogyi9JBDeCmNyEd9plKfKdSZl3rxECVTuySiRCI3UQJRfMjeBIoL2aeDYkP2GaAYIhdRNJGTKIoaOKiBnYw2okgiK5GFapqppomMEURGIgORnmrqqKaWjBoihYgTMX+3baZH4KSt1XPC1ub5Afo4cAz4Hra/wfYd8C3wDfA17F8BX6LsC+Q/Bz4DPgWOwv4J8DHKPkL+r8CHwAfA+5FzPO9FzvW8C/wF+DPwDmxHwH8C3gbeQv5N8BvA68AfgT9Yz/W8Zh3oeRX8e+t8zyvWDM/vgJehf2vN8rwEvAi8gPLnYXvOusDzG+hnoZ+B/rX1HM/T1nmep6xzPU9a53gOo+0T6O9x4DHA330In48CjwAPWxZ5HrIs9jxoWeJ5wLLUcxDoAg7Afj+wH2X7ULYXthDQCQSB+8yrPPeaV3vuMa/x3G1e69ljXue5C/gVcCewG9gF3GHO8dwOvg34JdrcCt5pPtdzC/QO6JuB7dA3oa8b0dc29HUDbNcD1wHXAtcAVwO/QLur0N9W0zjPlabxnitMczxbTHd4Ljft9lysSfdcpCn0bOSFng2B9YEL96wPXBBYG1i3Z23AvJab17rXVq89f+2etW+s9UfpTWsCqwPn71kdWBVYEVi5Z0XgAWUTm61c7B8eWL5nWUC7LHrZ0mWar5fxPct42TI+YBlX2DL7Mu8yjWVpYHFgyZ7FAbZ4wuL1i4OLtcOCi48sVthiburqPrR3sTu5Auxfs9hqr1gUWBho37MwcN7sBYFzMMB5hXMCc/fMCcwubAvM2tMWaC2cGWgpbA7MKGwKTN/TFJhWOCUwdc+UQGNhQ2Ay6k8qrA8E9tQH6gprAxP31AbGF44LjIO9prA6MHZPdWBM4ehA1Z7RgcrCikA5Js8S7YneRI1dDGBcIkbC3LxkgNvvPuL+3K1l7qD7kFsTZUvwJCiZtnheOj6eL4y/IP7KeI0t7sU4xR+XmV1hi30x9k+xn8Vqnf7YzP4VLMYe443RuMTcYmrqK1QuLiMeOFida02ML6PC5uI2l8ellHtcnDmOOD53aFyP2l+0KzYbt9m6bYrfhuq2SE+kIj66IzX+yIFDKmxWj1URH91WTYzfCovosY9lQn2FzewxK4Fi83iz4jcXl1b4zTkDKpiGezln3A7SGMUouMtTgXO9N4brON7nnfV1WVnVXUY2sTponDA1yC8NpteJT3/tlKD+0iALTJna0Mn5FY2dXCmtD0aLf7FV8xdv2cJKkqqDSXUNwZ1JjdXB9RB+IbohWFJnDCtpzJq+ZNmSrKyl0/ExfcnSLPUXOb5M5LKEUfwuWYq8+Fmm5lnWTyaqBpqxBGmpNC796Vb/1xP/dw/gPz91MvElg1HdykWsTdkIbAAuBNYDFwDrgLXAGuB8YDWwClgJrACWA8uApcASYBHQDiwEzgMWAPOBc4FzgHnAXGAOMBuYBbQBrcBMoAVoBmYA04EmYBowFZgCNAINwGRgEhAA6oE6YCJQC0wAxgPjgBpgLFANjAGqgNFAJVABlANlQClQAowC/EAxMBIYAQwHhgFDgSKgEBgCFACDgXwgDxgEDAQGALlAfyAHyAaygH5AJtAX6ANkAOlAGuADUoEUwAt4gGQgCUgE3EACEA/EAbFADOACogEnEAU4ADtgAyIBK2ABzIAJiACMgAHQAzpAO6obnxpAATjAWBuHjZ8ETgA/AMeBY8D3wN+A74BvgW+Ar4GvgC+BL4DPgc+AT4GjwCfAx8BHwF+BD4EPgPeB94B3gb8AfwbeAY4AfwLeBt4C3gTeAF4H/gj8AXgNeBX4PfAK8DvgZeC3wEvAi8ALwPPAc8BvgGeBZ4BfA08DTwFPAoeBJ4DHgceAQ8CjwCPAw8BDwIPAA8BBoAs4ANwP7Af2AXuBENAJBIH7gHuBe4C7gT3AXcCvgDuB3cAu4A7gduA24JfArcBO4BZgB3AzsB24CbgR2AbcAFwPXAdcC1wDXA38ArgK2ApcCVwBbAEuBzYDHcBlwKXAJcAm4GLWNmo9x/nnOP8c55/j/HOcf47zz3H+Oc4/x/nnOP8c55/j/HOcf47zz3H+Oc4/x/nnOP98MYA7gOMO4LgDOO4AjjuA4w7guAM47gCOO4DjDuC4AzjuAI47gOMO4LgDOO4AjjuA4w7guAM47gCOO4DjDuC4AzjuAI47gOMO4LgDOO4AjjuA4w7guAM47gCO889x/jnOP8fZ5zj7HGef4+xznH2Os89x9jnOPsfZ5zj7/+57+D88Nf67B/AfnuJmTGfMsIOxk1ef8Q3rCewctoStx88mtoVdzR5lb7CZbCPUNraT7WK/YkH2GHuGvfYzfZtcTSdX6RYwi+YA0zMnY93Huo+e3AV06SJ7WK5Gzqn1nrZ027s/Pcv26cmru+0nu/RRzKS2tSovw/oVP9F9DO9X5LsLRF65BNqmtvjCsOPkfSd3n+WDWjaFTWXTWBNrZi2Yv/jO+jx45lw2ny1g56m581A2B5+zkZuBWrhLVH261kLWDixmS9kythw/7dBLwjlRtkjNL2Mr8LOSrWKr2flsDVsb/lyhWtagZLWaXwmsYxdgZS5kG1QlmSwb2UXsYqzaJexSdtlP5i47pTrYZnY51vkKduU/1FvOyG3Fz1XsF9gP17Br2XXsBuyLm9j2s6zXq/Yb2Q52C/aMKLsWlltUJUofYk+x/exedh+7X/VlK7xGHpF+ma36sB0+WIMZbuwxYvLfilPeWoe5i7l1hGe6EvYNPVosD/tR1NyImtQLrYPoZe1ZntiKOZA+PSPKXavO/7S1p1d+yir9sb2HZ25Sc0Kdbf1H+jp2M07grfgUXhXql9CkblF1T/uOU3V3qvnb2O3sDqzFblVJJssu6N3sTpztu9gedjd+Tuueivhedo+6ckHWyUJsL9uHlbyfHWBdqv2nyn7MvjdsD52yHGQPsAexQx5hh3DTPI4faXkYtkfD1sOqjfKPsyeQF7Uo9xR7GjfUs+w37Dn2InsSuRfUz18j9xJ7mf2OvcatUL9lf8XnCfaS7l0WyUYxpnsAft7OpuNHh1tpieZl3CIaZmBFrIaNY1MfYla87mPYUL5/v6uszJhjeASvcoV5EQwYGeelfptWsR5ISCj2HRis36JxVHXxnH3Fhi0Ic4tPvH3ihdwTbx+NKso9ynPfeuftd+xfvOAoys1755V3Bg7gjhSHiuhIxWCI1vtS+yuD+2QU5OUNGqkMzs/wpUYqqi2/YMhITd6gZEUTLS0jFZHnmpd/mKIZf0KvrPMVT8rTJSfYoq16nZIYF5UzPN1eNzV9eP8kg8ag1+iMhr5DSlKr55envm5wJLlikqKMxqikGFeSw3DiDV3ksS91kcdLtfOPX6PRD5tWnKa5wWRUtHp9V3JcfL9hKVWTbE671uy0O2KMhiiHpW/ZtBObXImij0SXi/o6UQO33M2Y9kp4MIp52Ap/UnEKd8bZeY3TbsNHtBUfURZ8xJnx8SD+lmEsofvDvaiR0NX9+V5bmK0qf7vXovKHe1E74UH81RHB4rglFFnr7uIZnbp6Vny0GH59R327vUI0cECT8KcvJTVjsCO/IC8FbjLk91d8Podwq/bKSXd8vuvkp7GZmbE8/c4Pb67dn7/wrk33da65a3GRcuOdx++Y6Omj3dDHM/m2D7fN23/RmB8cI9c/Jv5Ptbu7j2nqMbM+bFqnwdlFo3aGR+0Mj9oZHrUzPGpnl+LYb01iyUmGLm7Z63TG67t4372ptfEBVlwc3he5hx1FNPhB2BTq4B1i2C6Scs3lbDT1WpPVcDKDHzJYTVpV+43R3oS41GhjZqxSoVoPOxMdxpOjDXa3y+l2RJx4z2A16HT40N7bx4PFCs9In4UZDWd3++3NI9tHKtYBA2Jzc0394+ISuv7JZcEE/clpAy0Wk1hnk1hnkx0VTSbUMol1Nj2AlWPdh/zxyLC0glpzXKw1N25gf72nb60nEBXQCV8UF0fFFjnyinnuK1lhZzjy7KeUo2hEbl6eIw/Lm37KIT4eqRGqD/ed4SVxNGJ5HsehEdKlzzJGe+JjU5xG5WSexuxKinYlR5uVk5UcfouP8zoN2e653gFpcRF8hY5vMid4MuIX2NxOS4LRIrxmMWrnHL/GYDJotAaTHodk2yn7rn5ploS+7h8ma3Yl94s3RziTXOIUYK88Dc8msky2sjNNH3amPuxMfdiZ+rAz9WFn6oUzYx1JwpNJwpNJdouVj03yoixJfKWAOdK7uGmvXm/xdXHzXletpcc2ogNgP3Mn+c7ePtoeh0HztH/FPSuvjnCmxMenRBv7JXBXv5p5C8Zm7h82uSn7lpvGzalI01zdsv284Sf7n5rxXX1TDbHF01ZNHn9OfuSJ7/tWtoq9ZMOMX8OMU9msA3F+zC3Owbq6D+2DYv/09MVGcXQf2o8yhz5KHJSk8AwH8dysL9SJPZllP5x16picmlyKvBXVE/KaNsJqPHmNMTolXpwKKKtRp8OH5iKjNSJ8Oo7vODWnmUZHotNJ15j4v1andR/VFGueZXnMz4J+r63EU5JbojFHxOZbMN58sb/zxdbOt9vsfGx+F//Oj4uhj41xCxPrxoaKKaLqUDE1a5jNxPtEm6FditEf7Yh9kuXb85Vhh/I5y+f5+f1H9evibr/tpVSemqpN+qj/mBFvWmq0LFfcdFjmpqMO8bloepO89w5nTW8qyqVVH1Q0cMB0nA89XiUZGYMH6/WnXhZ5g8Wyn3qhjNSqB8MgLK7omLxBBUM0xfZEd4IncthVtZVLanNGLr1z3pqYgeOKRrRUDbQYLRFag7tk0uz8lkvrM27fUtZW4mmcMGrhiDiLBbvRMqW4Ir1i9qix7WPSK/InDHYn+ZKM9nhbfFKCL8mZHVhXfzg2pzizoq6kDN5thne3I/rPwDt2s99TPIyb3UXCp0Xiziiy28UHvFgkXFz0IP8eb4nc7iPCj7nhrZQb3kq5YT/nhv2b26WY/CZnSoW5qI9bG9lP/GNa3BgskHZvZI1urNhK8GNsUfFZbw3hudMXS0/HDYqJdYTfti5NRgY5LFkRx2eIZrvBkRgtXoOV26a2Xj6576CZV80Yv9FviPbExXujInaVri0rbhgS78qfNCplhL+iTzx2nFaLHbeiZlLNxs6ZSx+8qLK8VDHLy/lEed3k4TPX+Ms2zBoR1a90oNiLTfDWNuzFLJbP7vX3yy0oLlhYoHF6xdvGK149zpRsO1yQLbyVLdyYre7K7C7+/f6yrNuzlCw4aT9qZuVru8iN4E+F29S8WWXallrhv5SU7KfXa7dqlUNa/pKWa7WJuW9mjIn7qDmyPVKJjPgosQaRzStN4R25aLHcioPeympSBczhF7HelxJ2Vh690PQ9wxdXnwLVoQbNtj7xJ0LJFe21/raqXIvBrNcoGoO5YNIi/8Ldi4cOX7Sz9Zxrm3N2aVatGDFtZKqiKH1SqldO6u9KcBki46OsTpvFHB/nHLm6a/XSgxeWly25qcG54Zr+Y2cNEXdTOv4S3KRbifdcWyjGjmvpyD7xJnKHryHB6uTd4fvIHd5MbvG1oQH90ru6X/JH2R18bLrpaEFlQsbRAaO9Y+2jxUvr6CARgGQdzvuCzmLe4fDVlEqnzeWieet7XsQ4nPJMqn7QKpu0OqPe4ErOdKfneyOfMZojdFG2Z4xObxxeTsYL7Hat0WK8wDd6wRhfSZrFqNHZnLGRughzRFxe7dCZBkeCM837w8dGs1GrxYfG5U1zJjgMTdMvmZRptVmcbuGFbbihd+oWsUFs1b7ifN7vdIgSnn6P2CUcy/C/+WOTzeJQmsW+MosdZlY3l1mUmZgfRQzvPXsX1x/IGZNWET9WPWTqOwmBTVaPV9IZJ8yh3kZ6Q4+3U3hLOAoK6KztNEZ5xSkyxvWvGjByTRmy6qva4CRz5daqKeePTYmXs1ZsNdPL0hoCJzZLi64QXtMK1514r7pqxOzLWsR5urj7GK/V5TIXS2GXHyj2jfct9Gliwvd0TNgHat6p8hFx38SE75uYsNNiHlQW4e3uIk+5wq1c4VKXdKkLbrrf5PGjpfiaxb54e5Xqn1ePZoXPTPj+yTrTOWFfOMXfBNgr8EgMH3m2A5zZw4ZmCZxygeYiA03YwAcM7ZdZBIRXno/EyruY/0Bx7PjYhbEaFl5jFh45C4+cyZEz8b9UmOwV6nDDY/3RMf79uOL/3v/hUSi71Xdq6772wTzDFn60Lfxom3y0LTw2m9hjUcyPZWB+Bz7ElccSTF083R+RNSbD5vJWucTwooqKxCk8jCGe2mk9D+GP7DKX+veUXtmt6COMxtikNFf8gMFDfXIq+qjE2JgkuyF91NCiJGtKWpJFq+GamTHJjoiICGN0/7FDTgRPOx3HVaOJMBs3FpT1sWmMJlNEpHriaruPKi9gxlXsBb8lt7q4enz1BdX3VetGhSc4KuyBUeHNNUr8O7AznLeH2SyYv+n3pA1KG2Rxi3PoFifSLV6Tbru4psS70v0A/1YNsk0i/LD4YbeIf4LOQH/FlvssiqX/W0NMHzsmOJod7Q7NEMcQR8zwN0a5dZljYj7U1Yi/pODGo46iotzcJvtRO/zZhN0ZDsWjhPn0Tg07Vyvvcfp7tb8+nNe7et6A0XDzC3nTN4wbMLl8QIxJqzcbzFnFkwr7lQ1y9/FPCNT6+2ROPH9i2uihmS6DRqNBhB2RWlCV28+f6errnxio8/fhkeXzsd6x8dFpHmeC3eD2uqN8BekZ+X09qVkjJw0f3FKVbYly2S22GLsj3m6IiY9x+gYk9hnc15vab3i9WIuU7s+UBdp72FA2bV8mc/hywj7PCa9FTngtcsIBRk54V+aITWiJteYc9Y1Osh6NHT0QsUSnQXXY0efFtssLRxDPH0bMjfOh/fFL/sxXQYx8JSoLjHZvZv/YijZ/0jpblIhR18qD9IGIuqJsHwypjE1LjDbqInTaqUmp9sgIfXr1knFKJN3yrxpQSxthgVDfAydNTTMiTBG6yDjcdtzU/S1/UzcdZz+TRe7Xpbtr7BU4Mm+9cPo9NViTceq+Oes/LzxsEH/eJ0YZHNzo8iW6fS5jZER8X48nMy4iIi7T4+kbH8GXyVOuecASZdHpLQ7L8aKULLfZ7M5KScmJN5vjc3DvbtbMVm7ULZMjcWdU2isxkucH9RxJ+MGGsywxLmWj3h4bFRVn08eaolNi41L+i70zAY+qOhv/uTOTmcnMJISwhUWYAEJYDAgoFBBRUdkMEQURtwnJEAayMZlAAoIjQUSlFq0i4oZUEZeiNa1t1dooFEEEEUNMCbUQCVYaFP2YkFI+7vc7594kE8AW+/y35/ln3v7uPffec977Lmeb2JD2sdqZ+1vcG9zHuqLRFO2TxtKZS1veS0hgN/n8jxMt/l/Iwv9cLL0vSJ75IbHaWuU/lrIfJ7aJpvz9XInJ+z8g30uxz7sA2fyfiqOvKcfOFWegVVqlVf63yeb/Z+VEq7RKq7RKq7RKq7RKq7RKq7RKq7RKq7RKq7RKq7RKq7TK/y+ifmtI/r2KBo59RbmIEf1FksjSvxZ9NIu+g2MXvY5jd72G42r9L+IWnp4Ut/C0gmMX/QuO3fXPOaYID8fV+kGO6yhnId1EFjXlbyh20eXvNnbX5W8XrtLl702u1rM1i5ain+C4Tj8m/x6G/g3HdXpES6FVFccu+k6O3fVdHFP0Oo6r9Vptpmo1U7VaRc1Kjl30wxy783SVtFNbTZ1j8i9r6F9r66jzFccuqtxdP8pxnf4lfl9i6Ska/86I8ZdVrCoi8epKli0i3moTjX/hZrA10SzbourEiCTr1WbZHnXfIU5ZZ5plp+hv3WOWY4XXdrNZdlnWN9V3i+m2kFn2iP62j8xynGWt7YRZjhc5jlVNf61miKPBLGvC4exvli3CEbuo8e/SiKTYe82yLapOjPDEPmmW7VH3HWJJ7Itm2Sk6xB40y7EiwdXTLLu09Kb6bjHANcQse0QH1x1mOU6b7Aqa5Xhxufs9+ReBbLFmnI2yEWejbMTZKBtxNsq2qDpGnI2yPeq+EWejbMTZKBtxNspGnI2yEWejbMTZKBtxNspGnF8WXjFEDEZGULpB/cZXUOSLQpgtQty7Rv2mnPH7chncCVDKE6k8uUrkIF4xlXvZYg7PCtWVn7Of2gs4ZlHzGtrlUGcW9wLUCKh6GZCLrixVN4+rQu7lqWdG+wAWeCGDevIv15RwtZBSiHd51e/nzaKcQ12vsrmI1lnq9/+ylZZ8U2uIGrnmO2UNLz7mq3f61e/5SV8mKF9ncydD/f5ZUHnhVecM5aV8r+FHJk8GKs256k6O0phBjIz7jW/JRU+OiliBaWUed3LVWw2d0s9QlAXyjQXKl8bfTzSibdgu35RPBLzqN/OyVRQC6nfx5O84htSV9DjUlA8jZsZbvMr2PNOvfBXbWapms8XRHsmoFat2htfzuE5V/SE6m32VtlyloUTFocjMfHS8ZcYM//3Kfum/kZeg6g3ybLxR5tqLjoImbwwbs806hVwtMrWH8MLI0IKmLGWoPpLB3dwWfjX25kwsyVDvzzTfn6p6bLbKlXxy7hgYeY7XI5tGzWViutmLAmZ/uwyNl/P0/L3eb/Zfw5sM0/5s9dSwx29GLKj+IpNfxTZI9L2qRxhtzv909o8awc29xcjNNK4Cygb5/ptUbw+1yOMg04L8KA8yzXEXUl76VV+ezJ1MkaJy3I86WUr/9coqo20IKSCKg5CFSlLVGG9pearSnkudEH1L2p+tPChAQwl3ZQZnK1/kyGmptfH+bPVbwkHVfxv13apsNnptiepthcrCkBpXhWoeMFp7lQ9yTPpVjwqodxgRmqXaNkbvWuI3mRnRaBuMemKM5ywVk+YxutD87do5P/Be41rWzaQXFakYZjX1+Sz1vED12JKofl6gPM0ze7qhy6+OcuSe7bd8bswQKbTqp3pnLn75m8bsuVblnaP5wmPUrL1xlvaa86zRezJbzHfn+t7cX1vaNSoqAtITwxdj1m/s9cGmFSRLzaF5ai7N+EFPjThntIip3+z9Z48BGVXZ84pUyyw1H0lv/E16ZM0cNaf9qwz9rxoXzWNikLJGjgFjJUpVuSoQxS97hwwePMJ7QyAzmF+YPzvkvSY/WJAfzAgF8vNSvVfl5HinBrLnhAq9U/2F/uACf1bqNRk5gVnBgDdQ6M3w5uZn+YN53sKMvEIvzwOzvbMzcgM5Jd6FgdAcb2HRrFCO3xvML8rLCuRlF3rzqRry59IyL8ubmR/M8wcLU70TQt7Z/oxQUdBf6A36M3K8gRDvyCwc6C3MzcCCzIwCyrJJblFOKFCAyryiXH+QmoX+kFJQ6C0I5mO3NBvtOTn5C71zMNwbyC3IyAx5A3nekPQDy2jizQnk8a782d5ZgWyl2HhRyF8conFgnj/Va7rZt9Cbm5FX4s0swnnD7tAc3u9f6A1m4EswgNs0zMj1FhXI16AxmzuFgUVUD+Xj0ALpUoZ3YUYw13iXDHPmnIwghvmDqVP92UU5GcGmDIxsfPVImZrLphMinPJelnr5kKjQ+4kvr8lAf3ZA2uHHsGBGlj83IzjPmy+fRF3OPn+CVVjwZlpeIET7m0IZIcPHQSjIVy/IJHehYMBfmDq5KDMlo7CfN8vvvT6Yz9NQqGDkoEELFy5MzW1UnpqZnzsoVFKQnx3MKJhTMigzNDs/L1RoVpXl2Rk4ME/WuzW/iNCWeIsK/RiBS/KxN4NM+oO5gZA0aFaJMu/aaZOv4mlQXZDnrCIjowvnBDLnRLXlHMjLzCnKkrHI92YFCgtyeIGMeUEwQIVMavnzQqnexnfn59EhUgL9vP7cWbJRs6q8xsrntUhVl12a8BcSnkyj3zW9XcXV1DVKGZAS4C10fRn6oBwgWfkL83LyM6Jfis0ZhqUEvikD+UWhgqIQYV8QyPTLOnP8OQVnOXQhuVCZGJTln53BIErNKCwobvo+KPQkseK8/+yHRg2+UYh2wqHroo35F0LtPEjhfLsQTd/Pzv9Jsj7h8WjU0ZZfaP24OFX/4IXWb9NG1reMvtD6CQmq/toLrd+2rap/4kLrt2tH/ST1F1KdfKeT9eW36rbm3zuNE+NEF3EL++UsMUyziKu0LmKy1l3cSkTlv2Q0X7tDLNXyxUPaKrFWWy1+oa0Tm60Txdto/BANn5yl+7Pz6Jaz/Wh0T0D3zeiehe5cdC9G9wPoXoPuF9D9OrrfRveHaNyHhr+01K29EaU7Ht3d0D0U3Vehewq6b0P3XHQvQPd96H4M3RvQ/St0/wHdO9D9ORqPoOHblrotz0XpboPu7ugeju7r0D0N3Rnono/uJej+KbqfQfer6H4H3R+i+zN0H0Ljd2g41VK39cko3Qno9qJ7FLonofs2dM9Bdwm6V6D7CXRvQvdv0b0d3fvQXYPu76xPyL8zq7lb6ra9EKX7InSnonsSum+ndi66F6P7p+h+Ct2/RPcf0f0pur9E93fo1q0TtTboTkb3ADmenHbN6Ty+cjmflcedNs1pPx4O879w2OnUnK4tW17k8+STzhj5ZOXKlfKRM4ZmDV7jY4/R7I7jzuKVK4tlJYdTFrlQ9wtWNoTDxU6bcNoGjz0+Vn5UpXD4je2yllPTnLawCKuPcWF+7FbNbjtoFG2a3V4QLh+ccNBhEw6boWhwVHURtlo1Z8z69ev/hTuxmtP9fvj98AbkMWQlooz5d27FxmixuNXol7TGt5oGBbE2EYtfpmOqWvi8nsVqWmyTZ8qfmDfKz3JNBcnUNTi6gXIuVjoX69BiYxuWL5Of5Q3qfYQ33KBe4dJiPeV8nh/7/NhHlaxCYu1arLOBaBiVHCLWcSbB/DhiNAcZwq+1c1x2zeW02WyhVdRdFXLYNYezePny0+Hw3S6bcMU0eTlW1UTX77bKIC83LDX9DLs0zdXsaNhh0xymp6qMq2FfQsJBGbiYRo2DXZrFFdPkbNhm01z21XxcTs3lOr3sXvVZdtoVo7ma/Q273JorrtxX7iMw6x/xPuJ9EFmOKAOly4bPLodwOZt8TjA9s92Nl267Jn8t77xeu23CLb1udFvVDf+Q325Nc0f53dJxGeZiugsds6Xjbs3ibnTc9NytPHc7NberYYXh+rIVDerlp2Wt08br4jR3m/Kk8qT1KetTVo9fPV72uPuc9zmXOd0OzW30EcN9t0O4o9xPUANE+Y/DHofmibXwGXmd7FPXjVRPR4yTERg3whMjPDEjmkMwVlU3YqD64DIj3Y1BCLPUeqKjEFYD0AyDMdYKVtIBnCsLZDLtY8c2GIpHeDSLx97UzAiFxyFD4XFpHs8ZsYWBWx71eT+8JXxGKIPOyOszxm1PvOZJONjtYLfjo/cMrMqpytk++eOPt676cNUWzxaPx6l5XKe3bdmyZdtpo7ZTeGL1pOaPGmB3b7Pbl27btntBnFOLc1n5jMreIj/Zo2KdPB89e9s2XjdrdJxdi7OP9vl8DT7zo1pIzQeObDE+cRYtzlZeLkST5eadqI8ayFUHG6/kiC3eWn6wuJtnVbE7hi7R/IYRcRZLnL25KWpjsML5sfwYuwOX2GCZIayZJcEc0T476J8nRuZkhPLEZJ5oN0292itXD3ZTcldgZ81ub15pwsEq20HdN+5YWHXaiI6IdUJ6+njRe+qUG7xi8M1TJ3nFGLOO3J8liE7qysob2jZpZ/yIRNHZvKIrsYvrIrpmFhQWiBfU8RV1fEMd31LHd9Xxg3l8qRPb1XG3Olao4351PKiOR9SxTn6/EN/Lo2ZXxy7qmKqOV6vjdHWcmzsvd562VB1XqOPD6rhGHZ9Vx43quLlpl/XvjtoFHp1E0koM7ETYKeRPxf/v3bOQh7gffY5nfyR/Pil/grVMPCo2iDfFB2KvqBHfs++IVZ46TW/rhPxvA1batWfHpsk9hjbSOK9cYZyfaYhqQ3/7ZkOLa81zuuV1fJ+W120TW163W9fy+uIzLa9Tznrev0vL62GDRawl+vpE1HO70K4f3fJ68oOcXfTpFJEu/3sKbZYRqsGWdHGP5QXL52K99RnrM6LCFrI9L/bFfGZfqVldN7kytN+77mel2O5J8FxrucZzm+dZS0lcVtxcyx/i7olbZdkab4l3WvbGn4w/afmz0ML1Mjb2yri3zit7kP1xh6PkqCl7ziMn4ns2SQoyEhmHzFWy9myJ2xO/If7XCWtMWR8lr0hpK84rrrbpTfJg28eapN6QxG7nkVRkWPt1UfKCIerJWdL+zfbbm2R3h4PIESkdbeeTxNSOiR1TOj0YJY8p+eC8sqfTqUZJap/UpUnGmTLxvJKuZLp5bilh8yjrbVNS0SRG6y+Sjnfu3zmr87OdN0k5W3vnzecTQ3vn33WuMeVEs8i3dD6l3hWWXDS518gmmdxrapNkmTIXCfeaK//BgN5jL069eFyvuRxTL/6gz/a+lUpOpMxECvr1QQb2q+nXADX9zvTfPuBZKf1qBrw74OiAowNtA+MHth/4NlKROgZJT5056GlT3rs0PLTP0L8Ne/TyYciY4UnDZw4vHvGmKe+O2DaiYmR/ZMTIFaMOXGFXsvqKD5ScHnP5mNdMeeuK01y/Nua4ujp+peVKy5jXrhw49uGx716Veu0M5Ivr51yx2qjN+bhRa8IYWW/C5Ik9Jw6eOGbipkl9lKRPmqukeNKKSU9zLJ70EXJw8qLJ4clf3FCArEnzUSs9bXfa7kkfcTwgS0hNWl3aqSlhJRunfKzkiyl18MWU+nTblHqe16XPTD+QXnNjCHl0qpd6G6fUG0+mLppSP/Xw1G+mpU/fNmPGHYl3dLujT7Yte2Z2VfapxvOcgcibeQl5PQuKC5YVlBfUFNQV1M+3zR8yf9z82fML5i+av3L+mvmvzX9r/tb5e4MFwUeDm4LfF4rCxMLxhbMK3y2sDA0LzQo9XTS9aGXRe0UnFtgXDFxw3YLXFhxZOG7hqeJuxdcV+4qDxU8Xby6uKulZcnvJWyVVJacWeRZ1XDRi0dWLshZtXFS1uP/icYvvXLx28SuLDyyuv3vs3YvufneJfcnYJcElbyzZtuT00i5L5yzduLTunpH3FN+zOZz+A3PVW2fPRy1nm/CCZpHzSHh9sxgzyA+MvYlnj7iW48To6eeddRpnnihpOXeEtzWLnB3CFc1izAtyDk14JWlbp8eYh/ePOc6sqeZgdWa+bZvO/Lo2fkPCmrg9TXMmddvW98qSbePeil/bPHcaUWJ2HqfmX6NWz/gNjdGTd+VcrOrul89VfTOC6H0r7jAz+QZa7Ffa9mDdGs77lTSvDkfPWhXGRa0DzSvBBmn3ObP/K+fM/i5zzn9Qzfdqlld6aB0/jvLaxpmQfGwy88XcZMw/xvxm5pE5kRlQZi2raXZszChzXNLEcI1s0ZzjXlPDNeEatMlaJ3iW3rmm19Rz+wTzYEXUjHqeeTZ6Xj13TjVn7m2qNxmz6OTG+VPO69zhreG6zpu4MzUp/fJhabs72ox1TJ1Zszqd6nCQXpXYuPo0riqJ3Tramlcgo1fKtU3VtskatP2gY6J8Iu/IWvJ+Yre4PY09NalLYjdWwETZXpaNu83raPRKKm1Rq6a5bkatnIloOHudfKzF6rjHXBnbN1rP81PG2+X7J6V3OJg0DntaRF9GTcaYTEWN2MYYGyNRRtPoKb2yiPdEmU0ZiaT09utUvjfJ3ESN6pGdN+Nr4wpbYWgN1yWFw3WGyDfIc6+pMiuyZPQ0eQ7XXZzae4iBscL1HqJWpSiRK5yxuqn18T8UtaZGybk11EobJeaK2yTntpAr7Y8TtRZfsDSt2D8gZ0dKStM6/gOiVvYLFrXbuEA5OzpqjxIl58ZP7V2iRPZ7I9M/Ts7V/O+tuzAx4iz3LvEbrrBP7HnF6bj9ctejZLW6Y5c7HXW1emJPuQcynyHsoEbIXZNxV879siRF7Y5mqJ2V3EMdH3Nc7Y/YHVH64IrVancSbtrFSNk4JZx2YEpY7mDU1UZzn2OUN7ILqpF35I5GtkszRe14QmpvRF31dKM8dt5M7Y1yN8Vs0SftgNp3FZuSru70kbsudZWedkDOS+YzhJ3bYPZqcocm261QJUTt0wrUfo66aqfWtF+blH6lRUXktIzFjSEjElfYlT9YbFg66SOlW75phdKl9LYciedmNLof9K00roRdK9f3W2/Q37VOE22sM4THGtS/s74nhgsLT/ZwVatKddZp+mGhcTwpLBx3WGfoe/iG/qp+WmzVT2s+0U7LEFO1WaKzlimStSzRVpsn2lJzGDWvtObofxQaer4UNup6qNuWuh7qupS+Wmp9I2K1O0U3nvfi+TSeX8TzXui6GF3JtH4Ke74QbkpvYm9b693YsUT/LfaOtH6pP2E9LAZba8UQ61digPVr/VPrUb7tSu170F4jbJQs1hln/ok1j6FpiygWbcREkQAjRT8xCrL0T4UfZkOh/pUI6SdEESyAhVAMJcIjFul7xWK4G5bAUiil/XK4D1bA/bASHoAH4SFYBb8XV4u3oYHyGdBFP02ABulilHYjTIWb4GYIiCnaNtEDjwPW6WK09TbhtN4FOWKl9R7R3Xqv8FpLRXfbc/pe23p4HvaKfrbPoAL2QSV8DlXwZ9gP1XAA/iL6xSTon8Yc1PfG/F14YuooH4Pj+l57jJho78d5qOhnv5xzjv6pPRfyIB+K9K/sC4DY2ImNndjYFwGxsb8uRtnfgN/CSTHK0V/0cAyAu0Q/hw9mwXwIQgmE4V4gRo7V8Ag8B8+Lqx2vcj4G38Bx+A6+h5NADJ2ZkAV+KBI9YoUYFdte9FB99wj92qVKX5P1k6IDvbaMXltGb+tDb7uK3raM3nYTvW0WvW0CvW0stV+gv6Rap+sPW2/RF9GDLqPfPI4Gn/U9faP1S/pZrbBaj9AHvxa3qX52mFoH2GY2joo7xaAo/ePRvwD916J/OLVnovsxdP+WVkPRvQbdT6HvXfRNF/Fo+RYt36IlAS190ZKHlkFoGYSWAWjpi5VfoCkFTVloGYKGTcrTHZReF0no+CM6/oiOFO0u/W30DELPXegZhp6b0HOlFtA/Qdcgba3+O1q+gz4b+hZg2Wx0tsOyUrQ9ZK3RT2DdR9a/MVq/FpdYj5ojti1a+6M1gNbhaL0Wrb3RmIK2z2j5GSPvBrycJtzmDPPfzCRyZnlSlOp1YjncByvgflgJD8CD8BCsgo/0BrETPoZdsBs+gT3wKeyFz6AC9kEV/EXXxRfwVzgIh6AGvtR3isNQC9/r1eK/GOcnIAL1cBIamN3+wfNT8E84Df8NZ7BF1+s0AZqaFb+0zqSH3a5/a72Ts0//1rZXr7N9BhWwDyrhc6iCP8N+qIYD8Bf4m95g+xqOwt+hDo7BN/AtHIfv4Hv4LzgB2GI7A7q+MyZR3+kYqzc4roWJMAnS9K8cN3OeBjN5fhvcCXfpdQ4fzIJ5PJvPOQghyguhGEq4vptzmPO9sILy/UAeHD/jvJrzI/Bzyo/B47AGnkD/c9zfQPkFyq9Sfp3yO0COHOTIQY4c5MhRreuOA0COHOTIQY4cB2lzCGqAHDm+1qsdR+Hv+FIHx/Q9jm/gW54dR/d38D2c4JrcOeo5n+SaHDkzIQv85MsiHhbt1cplFQ/Td6fRh+XqFcPVL7mayNUEevlW6ydigNC4Wy/G0TOr6ZnV9MxqemY1PbOanllNz6ymZ1bTM6vpmdXU/oqe1kBPa6CnNdDTGuhpDfS0BnpRHT2mnh5TT4+pp8fU875y3ldtvUPEWDNgFj0oU/+SXlNNr6mm11TTa6rpNdX0mmp6TTW9pppeU02vqabXVNNrqslkPZmsJ5P1ZLGaLFaTuXqyVk3WqslWPZmqJ1PVZKWabFQT9Qai3kDUG4h6A1FvIKp1RLWOiNYT0XoiWk8Uq4liPVGsJorVRLFajdj9wkEsr2IkO1l7/8Da+xvrHtbaT1mFWG1UfI/i4ad4eEjF926ukrjqRnyXoeFzMYN1Mpl1Mpl1Mpl1Mpl1Mpl1Mpl1Mpl1Mpl1Mpl1Mpk3Xc5a2Zu1sjdjtoIxW8GYrWDMHmLMRhizEcZshDEbYcxGWE8TGbO1jNlaxmwtY7aWMUu+xSTWzWGM00OM078yTg8xTv9qnSX6WDMhRyxnHe3BOtqDdbQra2cya2cya2cya2cya2cya2cya2cya2cya2cya2cya2cya2cyY7GWsVjLWKxlLFYw9iKMuQrGXAVjrpY1Lpk1Lpn1LZn1LZl1LZmxUsvalsza1puxUsv6lkz/r6D/V9D/K+j/FfT/Q/T/Q/T/CP0/wvqXyPqXSP+vpc9X0Ocj9Pla1sBk1r9k1r9k1r9k2d/174n19+zPHtbvIwPjmc8PMZ8XkYnxZOJFnq6it19r3ctOqkI/Y90nZqnsVVN7P7WqWDEf1pdyNYu2e2n7GXfH0vZh2n5I24m0raDdrcJujqNbqLmPmhXUnKj2V7LPvKQ0+Xl+Jc9387yS56PQ9ABP30DT1Wj6CE2DVf0/q33iF+pYL1xaG9FDmwk5kAv5UADzIQgheJCVvq1WLuJ4yzK0F6Nnh9obrRedrO+Iy6zvk/8a0YtV+yZ2iYms3F3YJfay/o2Z4WssOMq9v4vLWM+D+vu06Miesqdc02mfIyawgs2kz98mJljvVLuvCSIey7piWVcs64plXbGsK5Z1xbKuWNYVy7piWVdatqdlHi3b0zJPtYyjZRwt42gZR8s4WsbRMo6WcbSMo2UcLfvQ8lJa9qHlpaqlh5YeWnpo6aGlh5YeWnpo6aGlh5Yes+Uws+UwPLlN9KfUX8W4TO0RThKtavk7O3AjTIWb4GbhYu/mYu/mYu/mYu/mipX/ndZGhNvRJt3caWxVOTokKrQUvUbrB/1hAAyESyAVBsFguBSGwFAYBpfB5TAcRsBPYCSMgtFwBYyBK2EsXAVXwzUwDq6F6+B6GA8TYCJMgslwA6TBFFgHT8HT8Cw8B+vhedgAv4AX4EXYCC/BJngZXoFX4TX4JWyG1+EN+BW8CWXwa/gNu7Vyzu/r+7UPYAtshT/BNu5/qO/TtsMO+Ah2wsf6EW0X7IZP2EHM5NvKnfoe25/YSWyDD2E77ICPYCd8DLv0fbbd8Im+L6atXhPTHjpAR+gESdBZr7H/DJ4EYmB/Vj9i36h/a38JNsHL8Ar8mvtbOLPbtP+J8h59n/0z6ldRrtdrHBdBd+gBXkjWv3X0hF7QGy6GPvo+R19I0fc7+gF9wUFfcJB3xxCuh/JslH7EMZrzVP1bp0WvcVrBBjFgBwc4IRZc4AYPxEE8tIEEwF9nIrQD/HbitxO/nfjtxG8nfju7QFfoBtjvxH4n9jux35kMPaEX9IaLoQ82DdGPOIfCT/R9zpEwintj4Tq4Hu6i3izOs3mWTb05EIC5UMSzJbAU7oEw/Iz7v6D+S9TfpO93vsz1K/A99yJ6TawG+BrbTt8Xix+xHfQjsV760GKN6GhERyM6GtHRiI5GdDSio9FCIzoa0dGIjJagf6W1hURoB+2hA3SETpAEnaELe9bu0AO8kAw9oRf0houhD/SVv0/Jt+x+0B8GwEC4BFJhEAyGS2EIDIVhcBlcDsNhBPwERsIoGA1XwBi4EsbCVXA1XAPj4Fq4Dq6H8TABJsIkmCzkv9/u1tJgCqTrh7UbYSrcBDfDNOyeDrfADLgVlujHtKVwD4ThXlgGpbAc7oMVcD+sBL5vaKv1k9oj8Cj8HB6Dx2ENPAHrmCOfgqfhWXgO1sPzsAF+AS/Ai7ARWAG1TfAyvAKvwmvwS9gMzLUac632K3gTyuDXUM5c/j58AFtgK/wJPoTtsAM+gp1w9iwyTc9glp7BOtCGmX8060AbZv/RzNqf2pjxbMx4NmY8GzOejRnPxoxnY8azMePZmPFszHg2ZjwbM55tM99RXoc34FfwJpTBr+E38Dv9mO338Da8A+/CH+A9+COUw/vwAWyBrbBLeGy74RPhiWkrXDHthTumA3SETpAEnYXbvko/Zv+pXmf/GeU1lNfqX9mfZE0iB2o2W88zfLG/yDNstmOzHZvtzNL21/XD9jfgTZ6VgZzl3qL+b7n3e56/De9w/S5gpx071ez3Idcf8Wwn54+5twt2wyewR3jsn/FuvtvZ+W5nr+Te5/pJNVPuxza+z9m/oi3fWex1lNld29ld278FvrPY+c5i5zuL/b/gBESgHt9O6ocd8foxRxtIgLaQpJ90dIYu0BW6wUXC5egOPcALfYTH0RdSoB9cyr0hnIcCq6yD1dWYdYXHaRFupxVsEAN2kP9vOyfEggvc4IE4iIc2kABtIRHaQXvhcnaAjtAJkqAzdIGu0A2w04mdTux0YqczGXpCL+gNF0Nf/ZhzAN/RBsIlkMo1OwXnpZQbZ+JhlC+H4TACfoIfI2Ey5RuA77nOKbRL17c6b4SpcKt+0nkXds6m3tmzNN93nXzfdS6EJdiwFO6BMPUf4N2MfzVrr+G8Fr1Pwjp4Cl5C3yZonMVf5R45dEZo+0/9ZKzQD8dq7JWcel0s8Yx1cW7L/XbCo2Z2VqjYTtxLgs7AfBzbTf5cUo50c1+1hBG6T+3RPmi6n8f9EvVzFLnf+kbEWMbrt1tv0LewO3XJn23x7JgYaBmsH7UMg+FwJYzXP7VM0HdaJsEN7Mqn6V+wuzjA7uKAa4a+0zUT7tePulbCA/AgPASr4KfAdznXz2A1PAKPws/hMXgc1sATsBaehHXwFDwNz8Cz8Bysh+dhA/wCXtCPegboR4UVS+stM/hOHOQ79Cjsj2B/xDJSr8X+iOUazg/ohywP8t3lNnEJ89cl1Nzpukmvdd0M0+F2yNQPueZCDuRBAYTgfj2CbxF8i+BbBN8i+BbBtwi+RfAtgm8RfIvgWwTfIvgWwbcIvkXwLYJvEXyL4FsE3yL4FsG3CL5F8C2CbxF8i+BbBN8i+BZxT9QPuSfBZLgB0mAKpMON+iF8j5DD4frnZOhji8qjvl395LAHvm/C702W2/TNlizIhQf0cmJQLr9/4/smfN+E75vwfRO+l+N7Ob6X43s5vpfje7mrWN/sKoHFcC/cp2/GrnLsKseucuwqx65y7CrHrnLsKhdXkYEAGQhg25dkIIB9J+lBJ+hBJ7Dzr1hShSVV1mlnTlhnnImwusSRmUGsLnFkZ5D5HX8rvesEvesE1lVhXRXWVWFdFdZVYV0VmQmQmQCZCZCZAJkJkJkAmQmQmQCZCZCZAJkJkJkAmQmQmQCZCZCZAJkJkJkAmQmQmQCZCZCZAJkJkJkAmQmQmQCZCZCZAJkJkJkAEagiAlVEoIoIVBGBKiJQRQSqiEAVmQmIa4iCjyj4yMUOouAjHzss48VFeJ+G92nmz1sfMr9P9ycKHYnCUKLQkSgMNX9KfCu52kGudpCrHeRqB9FIIxppRCONaKQRjTSikUY0fETDRzR8RMNHNHxEw0c0fETDRzR8RMNHNHxEw0c0fETDRzR8RMNHNHxEw0c0fETDRzR8RMNHNHxEw0c0fETDRzR8RMNHNHxEw0c00ohGGtFIIxppRCONaKQRjTSikUY0fMJBXziBxx48fgSPF+BxIh4uxcOFojMx2kp8thKbSmJTSRwSiUEiT3+O/1vxfyv+b8X/rfhfif+V+F+J/5X4X4n/ldhRiR2V2FGJHZXYUYkdldhRiR2VjJWA/tJZ890JcYnlRua4GRBgnpvLHDcPcgDdWHywaa5bwpxxj77TvVg/6r4blsBSuAfCcC8sg1JYDvfBCmBudDM3upkb3cyNbuZGN3Ojm7nRzdzoZm50Mze6mRfdzItu5kU386KbedHNvOhmXnQzL8bHggvczHlyZj+qbI8wxmsZ47WM8VriJr+n9+HpXsZuLWO3lrFby9itZezWYnsE2yPYHsH2CLZHsD2C7RFsj2B7BNsj2B7B9gi2R7A9gu0RbI9gewTbI9gewfYItkewPYLtEWyPYHsE2yPYHsH2CLZHsD2C7RFsj2C7nLNm6H8m2h8T4feb5izp0V/FEDwq43kNz0+SjdNk4zTZOE3dv1LXSV03I8WFp6mMFBfeppo/A9pGhk6TodN4WYaXZXhZhpdleFmGl2V4WYaXZXhZhpdleFmGl2V4WYaXZXhZhpdleFmGl2V4WYaXZXhZhpdleFmGl2V4WYaXZXhZhpdleFmGl2V4WYaXZXhZJi7Dk1Jys53cbLcERDfysx0PMhkB/2AE1OPJcjzpZP5kppP8yQyePCF/mkXutpO77eRuO7nbTu6241UpXpXiVSleleJVKV6V4lUpXpXiVSleleJVKV6V4lUpXpXiVSleleJVKV6V4lUpXpXiVSleleJVKV6V4lUpXpXiVSleleJVKV6V4lUpXpXiVSnjeIYaxyPw4hPzvzldh9U/x+o3hRt/d+HvLnzdhV8d8KkDTx7Hn134swt/duHPLvzZJeyWIvK6QP+HZaF+xLKcfvFT/RvL4/In7dw9ZVmu1wuN4z9EP2rUW4rpESWwXN9nWSGclvtpvUr/m2WN/HdV9H9antT/6WZ/62Z/674IukMP8EIy9IQs6vhhNmTDHAjA3P8h7s7j467rfY//MpOlnUwoSykgKLK6HUUU8QhuaOXg8Yi7oh7xnCOILVRaoEBbC60iqCwFZClKAQ+1FrQUiUVZGrZiSyAlaSfNdBKa0DQkmf4yTdJkMg3Q731OTvWi997Hvf/ce/94PSYzmfn9vt/3+7N9QxpwPi7ALHwfF2I25uAiXIxLMBeX4jJcjnmYH16d2M+4lXYnFoZee9mRuCXsSjjpRd9IXCTaL8Zcr15ul/NwZWhOLMJi/BBXRQcnrg6rE0u878bQlbgJN+PnWBoesb9HahPhhdokKlGFatRgEiYjhVqkUYf9MAX74wAciIMwFQdjGg7BoTgMb8LhoUDDAg0LNCzQsEDDAg0LNCzUnhKaa0/Fh/ERfBQfw8dxGj6BT2I6PoXT8U84A5/GOfZxLr6L8/A9zMBMnI8LMAvfx4WYjTm4CBfjEszFpbgMl2Me5odHokqRs42Km6n4cuK2MCSWrgrD4mQs+jwXSlwocWCcA+UIe1nHKeo4Re8oUrlE5ZIOU9RhijpMUYcp6jBFHaZI/RL1S9QvUb9E/RL1S9QvUb9E/RL1S9QvUb9E/RL1S9QvUb9E/RL1S9QvUb9E/RL1S9QvUb9E/RL1x6k/Tv1x6o9Tf5z649Qfp/64LlfU5Yq6XFGXK+pyRV2uqMsVdbkidUvULVG3RN0SdUvULVG3RN0SdUvULVG3RN0SdUvULVG3RN0SdUvULVG3RN0SdUvULVG3JOcuFd3lXFxI0ytE91XRftTupvZ2au+KZtO4gcYNIr3POzfQupvW3Yn5ni8M/T41LPJjkR+L/Fjkx3x4nQ8NfGjgw1DihrBeBrTJgDYZ0CYD2uTSC2rDn3nUyqNWHjXwqIFHDTxq4FEDjxp41MCjBh418KiBRw08auBRA48aeNTAowYeNfCogUcNPGrgUQOPGnjUwKMGHjXwqIFHDTxq4FEDjxp41MCjbh5186ibR9086uZRN4+6edQtQ2IZEsuQWIbEMiSWIbEMiWVILENiGRLLkFiGxDIkliGxDIllSMzjBh438LiBxw08buBxA48beNzA41Yet/K4lcetPG7lcSuPW3ncyuNWHrfyuJXHrTxu5XErj1t53MrjVh638riVx608buVxK49boxkc7OFgDwd38/tpLu7iXI5zOzlX4FyBcwXOFfif5v9D3Iu5Fyeu9dr1nF4SVnGwj4N9HOzjYB8HBzg4JE7WcrGTi51cjLkYczHmYszFmIsxF3u42MPFHi72cLGHiz1c7OFiDxd7uNjDxR4u9nCxh4s9XOzhYg8Xe7jYw8UeLvZwsYeLPVzs4WIPF3u4VOBSgUsFLhW4VOBSgUsFLhW4VOBSgUsFLhW4VOBSgUsFLhW4FHMp5lLMpZhLMZdiLsVcirnUyaVOLnVyqZNLnVzq5FInlzq51MmlTi51cqmTS51c6uRSJ5c6udTJpU4udXKpk0udXOrkUmf0Xi4VuVScyMb/cmGEC0NcGOJAkQPlc9MQdYeoO0TdIeoOUXeIukXqFqlbpG6RukXqFqlbpG6RukXqFqlbpG6RukXqFqlbpG6RukXqFqlbpG6RukXqFqlbpG6RukXqDFFniDpD1BmizhB1hqgzRJ2h6J0qw2sqw2uyP9bPU4lr7eI6u5hYva9vw1L9/g59+3BT3RF4M96CI/FWHIWjcY73nIvv4jx8DyZIWo/ReozWY7Qeo/UYrcdoPUbrMVqP0XqM1mO0HqP1GK3HaD1G6zFaj0Xfo3UfrfusOLbiWBbkZUFeFuRlQX5C/79kAN3/h8g3wSfKP9n4X0d7Hz/6+NHHjz5+9PGjjx99/OjjRx8/+vjRx48+fvTxo48fffzo40cfP/r40cePPn708aOPH3386ONHHwVjCsYUjCkYUzCmYEzBmIKxbMjLhrxsyMuGvGzIy4a8bMjLhrxsyMuGvGzIy4a8bMjLhrxsyMuG/P9BNuQ5lOdQnkN5DuU5lOdQnkN5DuU5lOdQnkN5DuU5lOdQnkN5DuU5lOdQnkN5DuU5lOdQfqLHD078V8iTeRXzKlZtYtWmh/Yx7csaxzSOaRzTOKZxTOOYxjGNYxrHNI5pHNM4pnFM45jGMY1jGsc0jmkc0zimcUzjmMYxjWMal/cY22Nsj7E9xvYY22Nsj7E9xvYY22Nsj7E9xvYY22Nsj7E9xrXlWJiLS3EZxJs9xvYYR/urxaN/mzMi7dqJTC+qqcX/XY6Y3S81ozqZyra0bKuWbS/LtINlWio6868VZa5uvBBXOJdf5V4/DYMie9C7S3JzUHce8an3ULhI4ZE3TE2DontQdA+K7kHRPSi6B/8fVZtB0Tco+gZF36DoGxR9g6JvUPQN/l+disqnlRKl1v/13DISJfe9VuLSq9FXaNtI20b+DfBvgLblk02OE1X07aVv70T9W+L5Lc4It5qUlnrtjtBL11669tK1l669dO2lay9dG+naSNdGujbStZGujXRtpGsjXRvp2kjXRro20rWRro10baRrI10b6dpI10a6NtK1ka6NdG2kayNdG8XUgJgaEFMDYmpATA2IqQExNSCmBujeS/deuvfSvZfuvXTvpXsv3Xvp3kv3Xrr30r2X7r1076V7L9176d5L916699K9l+69dO+ley/de2vL+5yLS3EZLsc8zA+9Exrv2ZcJpeigxJpoWuIpE+fT4vKZsCixPqxM7DZnjIYliT2hOalyJt/t9HpCWJ08KfT89beVvxrtn/xalN73O4V96fawkWPLXfcBPC0DngmZxDqR/izWu+cGj8+H9sRGJ92Mu7V63IK+aHKiX6aOmnGLJqExjIehZBS6kjWYhMOc/k8I3ckTw+7k+/B+fCAUk6eG7el/C3H63NCUPh9qRPpCj7NDe3oO1IT0Ao8LPV4BM3T6R9Ax09dDVqaX+P7Pvab2pW/3fCnudI3lYU/6PtdfjQfD7vTv8ZDX6j1/xKM9pZu91oJNaPM8i3Zfd6DL+wZCV3o3xkJX3dRQqDsY0+B0WOd0WHes12eGpjozfZ111V0TRuquD7vrbsUduDcUon/ep2qOTyWqtlF1gKoDVH2NqjuomqVqG1V3U7WNqm3ULFJzmJrDlBym5DAlh6m4h4qjVByl4igFByiYo2AbBdsomKNgGwWzFMxSMEfB7N8pmKPgAAUHKDhAwSwFcxTMUXCAggMUbKPeAPUGqDdKvVHKDVBslGKjFBul1CilRik1QKlhSg1TaphSw5QaptQwpYYpNUypYUq17VMqR6kBSo1SapRSo5Qajo5O3B8WJNaEBynVIAZfpdAKquxMbAvnibO5if5wt+j+amLEpL0nfFSc/TmZDOuS1eGGZDp8X7S3JqeGo5JHRt9NHhcuEflHJ98TPkG1e0X/6WLul8mPhiuSp4Vv7vvtrM7k18I9ybPCzOSMsLb8+0t29aia9JQu8QzWh5fc8RV+bHPHHnfod9VBV9zuirvk0qly6SNOhPdz7KnQ4lPlfHlhIkf6orf49CaffM4nd1hbj7XVukJmIh9OChmffCo851Ov+NTDPnGQT7zsfp0T+etUPZHDR8rTd3t+QtjmU11WuS56s8jaPfHJdSLrWWwQMc/79EZRlTFFtnrcEnaIjh2iY4fI2CEyXhYZL4uKl0XFblGxW1TsFhElEVESESUR8bJIKImEkkjYwbkdnNvNtXLl74v2s55qK1/ufve775/s9RFsCON07aBnT/ryUHT9Ydcfdv3h9B2e3xWKrjMcVfrUiJVf5BPby3FvEr5fLVljL8+EZq+2J1rUkbKG20Kebi2u2+a6bdFZ7rrEuxfJqe6JaPlTWOjuC31yiBLjlBh3hW5KBEqM7MurEUqMJLLhAVesF0nNiVj0pDA1nJucxo1DcCiOCRcnj8VxYWfy7Xx+B97NPbonP+b7p0387vKJVnOi3Oum7gh1R+ReN4VHKBwoHOReNxUWUjpQYgklllBiifzrpvY4tcepPU7tIP+65V831cepPk6thZQfodjC9CqV6AE8Fi5Or/P4ApqwEVuRw0u+1+nxZdfYHi6ui8Kf66rCA3XVqMFRnh+PmSrU4rBEDnZzc7zutrC97nYsxS+wLDwQ1YrIYdG4ndPvV31eV31eV31e5/oHZfrrMv11mf66rH49OoIfZS+LtB+k/aBPVatRQ2rUkBo1ZO8j9j5i7yP2PWjfg/Y9aK+D9jqovgypL0Nqy5DaMqS2DInvIbVlyFpHrHNQrRhSK4bUiqGKlDsuFgG3cf9J7t/M/ZsTaznagKfC+sQ6XfFZrA/3ioJXE5u8nhFb2TA3sTU8nsihHR14CdvCNYlOj9vR7Zo7PPagF33RYtFSn8j7eidikTfgsYBd4eLEIIZ8PYzdYYba1KxyZ1XurAz+qhq1MfGq772G18PaxF6PQReuQALl+lUp2qp8Xa1OpcKiZK2v02HWRD2b4nF/HIADMTWcKlrPEK1niNYz9Nark28KlyUP970jcGT09eRRHo/GMWresTgu/GvyeM/fhrd7/g6809f/gHeHT6qR/66yrOLaYq4t5tpi0f5Z9fL65Mne80H8Y/hh8kMeT8Gp4crkhz1+BB8N35IVZyQ/7uvTwkUy46v7fmN2lQy5LPmN6NDk2ZgRXlRff5eeEZrTMzE7vCpLXpUhN8uQV0XJYlGyWJQsTi/2/R/iJ/gpfobromnp63EDlnj/rV67Dbd7vhR3uM4vPb/L491hVvpXuBfLw9XpX4fLdLMr0/d7/lv8DqvC6bLqdB3uShG4WAQuNh9crctdmf5D+GF6DR72vke89pj3Pe7rtWjw+jrP13t9g+s2eu15vOC1JmxEs2u1YBM2e3+b92ax1fdyUL1F92JZe3p6W3hc5p6ui14pe8+Qvaenu70mBtNiMP0KxGG6D/3hybQ4TIvDdAwxmN6FQQypAMMo+roU1qb3YNzXr0PMpcWcqrCoTtzVibu6ZFhbV+mxKsxVJeaqEnPrJnk+WfVIQQzWpcOTdXXYz9dTsL/XD8CBOMjrU0NWp8/q9Nm6Q1zvUO85DG/C4TgCb/beI33/rTjK/Y/2mgqrGi2quzI0y/DFdddE0+p4XcfrOl7XXYvrcL3v/TxcJvMXq1Snq1Snq1SnqwKLVavT637pOsus+27XvNf1l3v+a6zAb8LF0VGqxEWqxO8nOvPTE/38WZWgV8YvkdnfktlrZO1qWfucnjsqY5+Qsd2yskU2NsrCtbJws6z7lMw6WyatljHXy5hnZUyvLLlVlmyWBQ2i/9ei/3Oi/0nRX/6XCieL+Bej/1Cv7rOS3+lYmxKrdak1asKfvPYIntbnnvG9dWGL6rlF53pSzRrQudbogQNW2697rdG91qhfy638WXWq38o3qkXrrDqr3mxXb7Zbea96nbHyXWp2Rs3OqCfrrH6VWrBKLVhlla9a5RfLM4/utSn97yrtuWGNDrZGB9ukg62RmwNyc0AH2yQ/75OfA/LzPvl5n/y8TwfblL7K536Ma3Fd2KKqb1HVt8jNAd1sk262SYXfosJvkZv36WZr5OZ9cmmVuF8lzleJ6X79JKOfZMRtv56SEav94nSduFwuLpeLy+VisV+sbRdr28XadrHVL7b6xdV2cbVdXK3TizJiap0Ot0ZM3afDbdI5toiP5eKjX3xsN0GuFQcNeMqEtj78idI7dIcWsfAJ1bxDNe8QD89TtYuqzVRtFhN/VLm3UXaDSt1B2Q2U3SA2doqNV1TjzarxZtV4sxj5BzEypsrmVNmcWNkqTnpU1iaVtUllbRIzrarpVlU0q3JuVhFbVMQWqu+g+g5q71ABW1TAFhWwRQVsUQFbKLtD1WtR9VpUuhYVLauK5VSxnCqWVcWaVLEmFSyrgm1VwbaqVltVq5zqlFOdcqpTTnVqUp2aVKcm1WmrqpRTlXL7qlKTapRTjbKq0WbubFBZOlSWDi5t4NAG1WWb6rJNBdmmWnSoFh0qQ4fK0KEydHCqmVPNnGpWFbapAB2cauZUs8zv4NQGmd8i41tkfIuMb5HxLTK+RcY3yfYm2Z6T7TnZnpPtTbI9J9s7uNgsyztkeYcs75DlHc7Efabj8lx9Ungt+oAsK5+zzpdRS2XUUhn1NJ8XyZo9fF3B13q+1suWPF+7+foATx/g6QMyoiQLSrxYxItFMqDEj0UiviTKl4rypaJ8KS8WifKSKC+J8qWifKlo3kOvB+j0gGjeQ6sHaNVNq25RvYde3SJ5D33q6VNPn3r6dIvmPaJ5D43qaVRPnwdEb0n0LhW5e+y53h6fCdeL2DE7WOvZbmsfDfeLzW3Rm+xst2c9dtZvZ/12NmhXTepA3s6a7KzJ6nZbXZPVNVndbqtrsqrdVrTbivqtqN+K+q1mt9Xstpp+q+m3miarKJ9l+6Mj3WnUnba6U4879bhTHw3LZ9Rmdxtxt2Z3a3a3UXdrdrdmdxt1t2ZaDNNi2F1HaTHszqPu3OPOPe7cQ4thdx9191F373H3Hndvdvfy+bDHGWGberk7vGjXL7rziDt2qGWPqLhtKm75fPDHiYpb7V0j+85Q+X3/humE5FnR+yaU6/KdDt/pmnhWPtu9OqFj1b5PDXsWu/4W1x8yDWfNtDGFx+0zRYkIVWbSatTgKM+Px7Iw6BrbJpxp8e52XaS8xpHoeNd41nf+RL9h13rUO175y/l+ot9E6ksNJiEVHrWrL9jNd+g4TMdtdNxGx/L5ehv9hq3hUWt41hqetYZnafm35+7DccQbzt9Hef+xcvF4j8u8/26vlc/cFfZciA6xviFrGrKmnda0c99PcHZZfb917bKuXdaxyzp2WcMu9x5y7yH3HnLfne670313ut9O99vpXrvcZ8g9dkbHuvpjdv9nO9/whiqbofMqdypOVNXUxG+K/Hifl1vtfkb5N3r+Un3seIO7Puauj7nrY//TylOuNEd5X7nKHO+xXDGWee/fV4zJE110tzlgj7N1NV+/Embv++2OF9356xO/Mfo+697mnX/kWpNzwRbrf4JKq99QQcqdIUupZbwu991XqLWMWsvs5wlXvdbVHuBik9ltCwWXUXAZJ5uouExGZGVElqNN9veErMja4zZ73GaP27jaZAbbYgbbYt7a8neVI8vlJi43/bVyHOUax4Zl9v6EfW/jctNE9Tic6u1Ub5/4acSoKrInPGPVA5Rvt+IBKy7/DGeA2u3UbrfKASscoHI7ldup3E7ldiq3U7mdwu3uNEDhduq2U7eduu3UbZdVo6ruuO4nekTYaHgiSuiC4yalPVHSNLLesyHPeqOjPCs4w5TMJwXzSUGnHNMpx3TKsX0/I8ybWQbN8SUdL6/T5XW6MZ1uzLxe0u3yZvSSuaJgJi/pbmO625juNmbuLpm7SzrbmM42Zu4o6Gx5s0dBpxnTacZ0l7Fosl6+x0ru1LsLenZ5rnvFXQscvJeD905Ulcm6/Uhyqkry7hDbQb93xckPRFNUGGee6ET3yUaVrrPDdco/cy2Vd2DH6YmfIOTL76fEVPn0gVDyevmnst7hc9ujgz0r737E7kfsfmRi598wK5wdWt+w8xE7H5nYdbPHFmxCOzpgd3Y2YmcjdjYSvdXdNtJ3lL5t9G1748ncvWN36aHtqDv0uEPPX0/jD038xK+HtqO0baPt6N+c0Ns8z078FHDipE7bNnfvoW3bG0/rUYWdj0bHJut8NTXcbVoqmJYKpqWCNT1sTQ9Ta9TE1G9iKv90bYBOO01GBQ68xoHfcuC3zpEHOkeWfzuyPPX0m3r6reth002/6abfdNNvuuk3zfSbZvqt52GTTL8ppmBND5so+k0U/SaKftNEf1RjNb93593uWHLH3e62x92ed7fno2N892W69VrjVmvc6p3FfT/D/u8OfcBkd6q4Po0Oy0MvDcdpOP5Xlx7yWr3nj3h8zKS13uMbXWvzPIu/uPeS93R5//aw9W9cnEa1Lqp1Ua2LUl2U6rLuzn0/k+qiSBdFuqjRRY0uanRRo4saXdTookQXJbqo0EWFLip0UaErepN9vmSPL9njS/a4yx4z9rjZHjfb42aTajnqNtvPZlNl3lSZt5eXTJblCNxsL5vtZbNJMm8fm+1js328ZA8v2cNme9hsD5sn/hXlMclvR8dES6Nzwh3RufguLg73RPPDTdEC/AALcQW6w9JoB3ow7D17wo3ROF7Fa3g9lP9vdM0V78A78S78A96N9+AEvBcn4n14P07CB3AyPoh/xIdwCk7Fh/ERfBQfw8dxGj6BT2I6PoXT8U84A5/GP+Mz+Bd8Fmfic5gRHVLxZHii4qnwx4qn8QzW4VmsD2srNuA5NOL5sLby7nBT5T34FZo834gXYa+VexHCjVX7hzuqDgxLq0zZVabsKlN21SE4FIehK9xUFXvPAAbDTdXvwMm4INxRPQvfx4WYG+6pvhR0r14Smqubw9pqJ56a48Pamrfh7eGPNe/A+/B+zz+Mb4SlNd/E2eHGmtuxHF2ev4zt4FlNf7inJo9dvjfieTHcOCkRmiclUYkqVMOkOMmkOGkyUqhFGnXYD1OwPw7AgTgIHwprJ52Cb/v6ux4XefyNx5Xhj5NGQ/Nk15p8kPn4W9GBYWN0EFS/6GBMwyF4G96Od+CdeBc+g3/BZ3EmPofP4wv4Ir6Er+LrOCfcKXLvFLl3itwrokvCsmguLsVluBzzw0rRvFI0rxTNK0XzysqfhY2V1+I6XI8bsAQ34ibcjJ/jFtyK23C3z92DX4WVXL+zqi1srOrAS+hEl9df8diL2PcHMOi118PG6mrUYDJSOBSH4TgcDzpU00F0rKw+yePJHk/1+E/4Fs7Gt/FvuCDcKXLuFDl3ipw7Rc4VIueKavuttl8RtHLShWVtoptCc3Qzfo5bcCtuwwr8BitxH+5HI57HC2jCRryIZrRgEzYjg1Zk0R0eUhMeUhMeUhOei3ZjBKMoYgx7wmp1YrU6sVqdWK1OrK7sC82V/chjJ2I4nVQWsAuDGMIwnFgqR1D+3F6EsFq+PVSjFtTI/Rq5XiPXa+R5zZnhuZove/wKvuE938TZYXXN+Z5fgrm4DJfjB7ga10C+1dCohkY1NKqhkXxaXfOfHpd7XO3xMdChhg41dKihg1x7SK49JNcekmsPybXn5NpzNTsRY5fPjnidHvJudcV7osrogKgK1ajBJExG+a931yJd/hOT2A+nRNOiU3FOWCDGF4jxBWJ8rhifKcZnivGZYnymGJ8ZzXOF+WGWOJ8lzmeJ81nifFb0o2hKdBV+jKtxDX6Cn+JnuBbX4ZHoLdGj6A7zOTqfo/M5egtHV3J0JUdXcnQlR1dG5b8gvScs5OpCri7k6kKuLqz4RWit+CXuxF24G/fgV/hP3Ivl+DVW4DdYiftwP36L32EVHsBqPIjf4yHU4w+hNfHeaErixGha4iSPH8MZYUHi0+HixGfwBc9nhMWJmeGCxPm4IFxgZvtM8pvhEnPbZ5Lf9nhJaEzODS3J5qgq2RJNTW429bY6lW+JUsnusDK5wyzSE709+YrH3vLfBvK4Mzqw8pLogMq5uBSX4XLMw3wswA+wEFfgStwdZqkXs9SLWZWboimVm5FBK7agDVlsRQ7t6MBLoKdoXyjaF6o1C6oOCK2ifr4aM6tqZ5RSXxaoLwvUl1lVr0YHVCchtqoPxEE4Bu8Is6rf6fFEvD+apqbMqv6gry8IC9SPBerHAvVjgfoxV/2Yq37MVD9mVoul6vkQS9V3hNbqX0z8C/rWmjfjLTgSb8WJODOslGnzZdp8mbawZk40peYiLMJi3ITbvX63x19Fb5FNC2t+6+su738Z2yHmZM4tMucWmbNS5qysGYgm1xSwy/tHfF/8yaCFNWPRlElTQ+ukgzENh+BQHIY34XAcAWudZK2TrHWStU46CkfjGByL4/Ad1zoH52Kh51fgytA6uSK0ps4KF6e+gYXhgtSVkDcpeZOSNyl5k5I3KXmTuh43YAluhP2mbsbPcQtuxW24HUtxB36BX+JOLMNdoE/qHvwK/4l7sTyaUrsAP8BCXIErQdta2tb+EPK7Vn7Xyu9a+V1rnbXWWWudtdZZa5211llrnbXWWWudtdZZa4211lhrjbXWWGuNtdZYa4211ph+VzRlv8lIobb8f39KvihTulWj8lflvz1ySOIy1Sw98X8XqEYNJqH8f5tNoRbpib9gn1bN0iaAnAkgZwLImQByJoCcCSBnAsiZAHImgJwJIGcCyKl8B6l8B5kE8iaBvEkgbxLImwTyJoG8SSBvEsibBPImgbxJIK9KnqdKnqdKnhd9LxSiGZiJ83EBZuH7uBCzMQcX4eIwQ0WdraLOVlFnq6izVdTZqul01XS6ajpdNZ2umk5XTVOqaUo1TammKdU0pZqmVNOUappSTVOqaUrf7dB3O/TdDn23Q9/t0Hc79N2OqPzzjpW4D/fjkegwlfcw/beg/xb034L+W9B/C/pvQf8t6L8F/beg/xb034L+W9B/C6r1HNV6jmo9J+p1lu1DP/LYiRgDKGAXBjGE4XC7yr5CZV+hsq9Q2Veo7CtU9Xmq+jxVfZ6qPk9Vn2emz5rps2b6rJk+a6bPmumzZvqsmT5rps+a6bNm+qyZPmumz5rps2b6rJk+a6bPmumzZvqsmT5rps+a6bNm+qyZPmumz5rps2b6rJk+a6bPmumzZvqsmT5rps+a6bNm+qyZPmumz5rps2b6rJk+W/H5aFrFF/BFfAlfxi9CRifK6EQZnSijE2V0ooxOlNGJMjpRRifK6EQZnSijE2V0ooxOlNGJMjpRRifK6EQZnSijE2V0ooxOlNGJMjpRRifKOEvUO0s87izxuLPE484SjztLPO4sUe8sUe8sUe8sUe8sUV/xQpSqaMJGvBildLG0LpbWxdKJU8r/RtXjJz2eEa7Uzc7Uzc6c6GbfDHHiHMzQ3d7Q1RKzQqyzfURnm6mzfURnm+ksviR5cViVfCw8nWyI9ks+pfu96Dzf4py+OTpEl8vrcslkm/P9f3W6Kp3u2Im/MZn3+k6d55Iorculdbm0LpfW5dK6XFqXS+tyaV0urculdbm0Lpc2SedN0nmTdN4knTdJ503SeZN03iSdN0nnTdJ5k3TeJJ03Secrbw+FyqW4A7/AL3EnluEu3B2m65zTdc7pzl31zl31zl31umhKF03poildNKWLpnTRlC6a0kVTumhKF03poildNGXOLJgzC+bMgjmzYM4smDML5syCObNgziyYMwvmzII5s2DOLFSOhriyiDGUsAfjeBWvQU7ozPN05nk683k6c0ZnnuP8l3X+yzr/ZZ3/ss5/Wee/rFNCzikh55SQd0rI6eDTq3aEgpNCzkkhp5Ofp5OfV2VNVdako0/X0dNODbmqvZ6HUKiOUIEEklFap087UeScKHJOFDknipzOn9b5004WOSeLXPUR3vtmHOO14zw/HmqtU0bOZDDdZJCufq/vi0HTwUFOHTkTwnQTQtrJI+fkkXPyyDl55Jw8ck4eOZPDeSaH80wO55kczqtWR6vV0Wp1tPpiXIK5YYZpYoZpYrZpYrYpYrrzbNYkkTFJZKrvmviLTNOqH8QfJv4q07TqZz02h3pTRqaal8692eqxaJqJI2PiyJg4MiaOjLNwvbNwvbPw487Cj5tAMs7DjzsP19ecGqWcieudCwrOBQXngoJzQcG5oMOUssK5oOBcUDCtzDGtzKn51xDXfAtnh3nOB4WaC3wtp2q+jwsxG3Nc8yLYl7NDh7NDwdmh4OxQMOGkTDgpZ4iCM0Sh5mfef+3EXxUsmHpSzhMF54mC80TBeaJgCppnCkqZgg5zriiYhOaZhFLOFgVni4KzRcHZouBsUXC2KJiQ5piQ5piQ5piQ5tTscO0evAK1vkatNzXdbmq63dS0wtS0wrQ0z7Q0x7S0wrQ0z7SUctbPOutnnfWzzvpZZ/2ss37WWT/rrJ911s8662ed9bPO+lln/ayzftZZP+usn3XWzzrrZ01dGVNXxtSVMXVlTF0ZU1fG1JUxdWVMXRlTV8bUlTF1ZUxdGVNXxtSVMXVlTF0ZU1dm0vus6f34UKifdAq+7drf8fwcnIvveu08j9/DDMzEhSFvQsuY0DImtMykRT6zxOu/8d6V4fFJ9/n6foyG7OQommaCy0y2t8kHhfrJB0ep1JdCd+rL+CrOCmea7M5M/auvLw9xah4W4C+T3mJf/xjXRGkTX9rElzbxpU18aRNf2sSXNvGlTXxpE1/axJc28aVNfGkTX9rElzbxpU18aRNf2sSXNvGlTXxpE1/axJc28aVNfGkTX9rElzbxpU18aRNf+v/jxJf+m4nv4OiG8OGKs6PPVvxb9KWKf48ur/iP6FMV34k+XHFO9LXEGdFZiRnRV5NfCZ9InhVOSz4aViQbwmeT28NzZsOpSRUu+Uq4KdkX1if7o8OTeeetnaEYHRndsPeZ6LdhU7QubHL1j+77a7Anu/q7XP1drv7xihmhqLf2uIvTnFPZV8Ip7vIRd5mbfDw8llyLhr1x8smwRo9rSz4dnk0+E25w96vcuZTsCb3ufoq7L3H3pLvf5e7PRJOSG8PyZLM1OcknN4XvJDeHR5IZn9oS2nXFl8ypvw1/trY/e+fX9c6N3n27dy9Ibtq717t/5d2f1kfX+MRlPvGLib/teILVLtTN36x7fzrxWZ18RpiR+H6UTNxvTn4m/EdifVia2BZ9IDGqI0+NpiRPCL9OPh6ldekT7OD37rTeeTSZ3OSs2Rr+oEtXufpeO8ro1Av2derkvjNp0s56k/12lff6zjBQ8bWoMjwSVaEaNZiEyUihFmnUYT9MCY9F++OU0B6dih+FB6Or8GNcjWvwE/wUP8O1uA430PCR0BI9GloqEqG9IolKVKEaNZiEyUihFnXYHwfgQByEqTgY03AIDsVheAuOxFtxFI7GMTgWx+F4vA2fDy9VfAFfxJfwZSzEFbgSi7AYP8SPcBV+jKtxDX6CG8PWiptwM36OW3ArbsPtYWviveHBxEn4GL4Q/pT4acglfhZyovwrXInF2Wti7EFOxGLsc2LstWRxb19yTEaUQk1yz96x5Pje9uSroTr52t7e5OvhY8m9Xg/hsMqqvX2V1eETlTWhpnLS3rHKyXvbK1OhurJ2b2/lf6PuS+CjKLL/X1X1dHVmekIIIYRw36irgsui4hF1PX4KiK7iwa2irAoeCIicHqsiIiAooCCHoK7iIl4gh+ABKh4gNwTDkQAJEDoc4UxI/b9V04kJCeSA1f33fL491dV1vK5+9a33qntqXJVkhREfjXR91DyrL9APeBLoDzwFDAAGAoOAwcAQYCjwttpkTQdmAO8A7wLvAf8G3gc+AGYCHwL/AWYBHwGzgY+BT4BPgc+Az4EvVIo1D5gPLAAWAl8Ci4DFwFfA18A3wLfAEmCVmm2tBtYAa4F1wHpgA7ARSAY2Ab8BKWp2IEfNswUA/bUDaoEdi+8qQAPgXKA58Fe1yb4Y3yNUij0OmIBjXKf9DsK4HhvXY+N6bFyP/RHiZgOfAJ8Cc4F5iJ8PLAAWApDdhuz2jwj/BPyM8C/AcmAFsA5YrzbayTiXDuwB9gMHgINANnAIOKJSZDRQCYgBKgMJaqOsDiQCNYCaQAu1SV4MPK5my97A08AzwKvAFGCaWiln4vuImu00USnOeWqTcwG+m+H7ZqAdwnerjc59ON8duB94CfETEP8G8CYwEZgJ5KiNUaRSoirjG/0rCv0qKhGoqTYF71PJwYeAnsAjwGNAHwD9PYj+HkR/D6K/B9Hfg+jvwVeAkcAoYDQAeYNjgLHAa8DrwDhgPDABeAN4E5gITALeAiYDuMbgVGAa8DYwHZihZoduUsmh1kAboC1wM9AOuAW4FRiovggNAgYDQ4ChwNPAM8CzwHPAv4DngReAF4FhwEvAcOBlYATwCjASGAWMBsYAY4HXgNeBccB4YALwhvrCPU/Njo5SX0QHgZD6giyMFbPB/LvFWroAvJxLr9MANZEGAoOAwcAQ4JhKhv+cDP85Gf5zMvznZPjPHvxnD/6zB//Zg//swX/24D978J89+M8e/GcP/rMH/9mD/+zBf/bgP3vwnz34zx78Zw/+swf/2YP/7MF/9uA/e/CfPfjPHvxnD/6zB//Zg//swX/24D978J89+M8e/GcP/rMH/9mD/+zBf/bgP3vwnz29Chf7DnJ+rzLhs2bCZ82Ez5oJnzUTfugE+KET4Heuht+5Gn7naj5DZZj3IyNvHW3jR9Q2jGYbMIpNFCuoDsbLrRjBRsCHmwgfbiJ8uInw4TLhw2XCh9P+UzL8p2T4T8nwmTz4TB58Jg8+kwefyYPP5MFHmgg/aCL8lInwSSbCh5gIH8KDj5AJ38CDH5AJPyBTnquS5XlmPc5M2P7alk+GnZ0M2zoZtnAybOBk2L8e7F8P9q8H+9eD/evB/vVg/3qwfz3Yvx7sXw/2rwf714P968H+9WD/erB/Pdi/HuxfD/ZqJuzVTNirHmzUTKcvyn4a4ff0qmnKg73pwd7MjIpDf7pLTYCNOQE25WrYlKvdwSrDHQIMVRnhOLUtXBWIB+oAdYFnED9dbSOOUeVDjOuw48R8ulQsoM5iMbUQX1EC2neu+AaW1LfURCynm9HWN8OvD8BiuBK+faxYQxeh3bfAcqgNOycVsWl0LuyFm2EvNBYZdD3K/cafyz4PNX2tZiL9WFPnbJx7CFbFAopG3DIcrdDrUhZfS5c9SEklr6cLeZqjd1yOWttgPLwRMkRimmO0PILYazBaLsBoudusUbxH/xslYmvi6Eozp1gNaRtBBv1fBDvpfKS4AEcrKAlXGIdztXGtetW3u9Qvog+1gvzfWFfAXuOI+QFHPyE1xibYhFk4SsFRTwrj6DiOfqAmZFESBQAbkIADRAFBIAS4QBiIRo3tqaroABuvC9AT17QAduBXsDO/ViutPpRk9QX6AU8C/YGngAHAQGAQMBgYAgylJPjySfDZk+CzJ8FHT4KPngSfPAn+dxJ87yT420nm/y/CsG6zUVMKrmKnWIw7qf/N5Gs1B9btHlx7H7TJfMj1JVLhanHtYYplv1IDtpKaoWW6oB3+LjogVUfqKLqYNeY6ip7qa70qkeinUsU4ainG08Wox8OdbgRLZpZ1KV1ktaJmaK2OVBs5aqOeFribfaguatqr6zc1hf3/NfledELuzkjfDd/34LsPNOxXtRE2cibs42NGf9aRg1yCbP1PKEgdj5TxSBmFlB5SZFE8pYFFYUPRDthNvVGTvqf91GrY3Zm465XAuCtNeWtwB9ciF8rUFnEgVuXCh8+FD58LHzkXPnIufORc+Mi58H1zUWd7laF/8YQSz0VPkaa0tSqbqhWpsxM4qxvQC9fWB5b4CrUf0mXhOjxoXFXUfQi5lqLeEOo9Wmq9IdSbqv+bBaXFot4ASjyEEjNRYjZKjEJp+/2ryEU/a49YvV5gJ1jy3YDeONOHqiNnFCS2kfMwcuYiZxiy5OlWQ84c9Io0uoG2AzuAY9Ds40AOkAucADu0h+dyl2omOoEtOlNX0Q3f9+C7F3yf3pCnn5ouBkEvxtEl0IfL0eK/osZW5t6sUm+Z2taodehzcfByjvs6cpGFsq08QFGTQCzdIDsAHYEu1ESOB2YAW3G8DUgFIKfMQlw2vg9DNr3+YxYkO4ZrPgbJzsV1H4Nk5+K6E3HdmjEcXG8Q15ou1lOM0bqFyPENcmxHjkTk2I4cichxCVLHQOadRvNWqRzIfRQ5t5tca8z/EnRAfR2hyV3w3RXffcGKqVQfjJcFjgmCGauDGSuD7xaaf9TR9y8ZqQRisnAf2iN0l+kbejW8ePEEtOpJjHc7IXcGatylPKNvW5FvO/IFUbqDkjnOJFN16q720/3AA8ATuPvtcT87QK4uQF9opk6dBi3ZiZZOh0y74F/uRil7ME5eQdUCMWp/IBPYq/bbPYFewCPAo0BfoB/Kjfb/E2gDSk5GycniCVxVX3B+Ku5jGrRoO3qQuVrwcAbaaJf62fji1SBfDuTLgXw5/tXrOeXNKGUzSuEo5VzIGINSjqCUPJSiV5p3UMI2/X9EkC8H8uVAvhzIlwP5ciBfDuTLofOpO7Wh+4EHgAF0LQ0EBgGDgSF0LWqshBr/As4KoIVvBWcF0Mq3grPeQ0t/gpb+Enr6PfT0RuhpG/GBehXX9BNGiMYRaTBuaWkyYE1cSq2go62sK9QGawpda00FptG1gRhqE9iK70x87wX20bX2OUBLoCe1sXsBjwCPAlo+B1Id9vWG+3rDzb3SLbhLpZvZiFmQ+10/VbyfKh5ye0h5kZmB2KVWQzN65n0LX3AvfL+t8PX2wrfbajXN2wFd65nnITYLMVlWU3UlSu2Zt1kcRjvnIHcuuOGEWm4F1BH4hUetkMpGyuVIeb3J+zXOrkTMSsQETV5PHEd9OWiVE2otfMw8K4ps5M1DqrXwJfOQMgm81DNvJ2rJg5eaDckyxTF856DWXGhmJGcuas2Dd5oNiTMtB99BSBFCfKSkXFzBIWhdT/i1R4ihlCyUkodSFErIMHXbxJA7C7nzkFshZ4Yvwzm6nfJGQ4ZU5G6A3JuQ+7A4jh6rpc+FHp+AxuXBTlDqBGRJRWkNUNomlHbYilJrzFWFcJ9dioGnvBsln4BM/9GjqOIo8SjkSBF5xJHrKOpOscIIN1X1dIq8FUiRjvp0SyUjRTrK1K2UjDL2oXVPul+4+/59Qu5S7o9Ja+4L0pZyP3CNZ3gfwKflbH+wzFlud1zjKdrbnCmxnSnaiqMoqyrkS6CglYjSaiBPTdgMtRCujXN1cK4+zjXEcSOca4xzTTAeWFY8aqiBs3Xx3Qj3xLXicAQfwqqG+hNRQw3UpMuqjfg6iK+H+IaIb4R4lIO7oFPrmmv4KXRNuqxYyMVxdocVj5hqQALVhnyxSLkDZdaGfBzyceTaYdXF+XpAfcQ3RJpGiGuMcBP9r+QoJQWy6ivkVnXImkgBvxSdOwXy6yvkVgOca4hzkdwc1xsHVIXuxUPmBJSbiGupgbtfE3XV0teF83Vwvi7O18f5hohrhPONcb4Jrg9XgXtTFeXGI7YakKDWQYY8tE6qVRP3shauuTbS1EGaujhfD6iPNA2QpiHSNEaaJhjZ9H1yTbsmUBzk0C12FHLEQY4Q5HBN29bHcUPTgkchQxxkCOm7QsJce6LfzhHpdesJc92RHFm+1JwqVVQn0Gs9tN9JeoHefiGFy6sbyNWM5Kn0A2cbUZWzpSMo7S+46grqCXI3pcpnqiso5VJ9RWdHX3AnfjT3sUI6Y8aGcHn1xrB6U3E4bxeYtBsYpyZYra04npcFVrtO5ObtBvt0B6vVBau1sgJ5u8Co3cBGNcFqba2ovCyw2nVWKG83mKk7WK0uWK2VFZd3GC1yPlrkHLTIOVYCjqurv6BFoiFVc7RKY7RKI6s24usgXV2kqQfUx3EDpGuIdI2QrjHSNYHWRMFzc+FzJQn9vz7fUhVYu3GwdBvCqrgEtsJSWHuVzH8LzWdd6DLWja5n99DL7F583wfPvb2aJO6AL3Knmg/LY5L5p7pzTpNqqUml/wNpvYnNP5pdcMThyS9iX6nZJqT/3S4VoUrwks8nolbwSc+lq/FpRq3pNmpOd9CdiL0bttzl9E8aQTfRSPqAHqX5tAhHX+HzKv1I62gMbcBnCqXAO5lK6SjxfVaD1aBVrDY7n1azNqwtpbF27HbawTqwTrSHdWVdyWP3sO6UxXqyR+gg68sm0GH2Jj6JbBI+NdhkfGqy99kHrBb7iq1gdXgzfhG7kLfgF7OLeCveirXkV/IkdjH/O7+WXcqv59ezy/j/8dbsct6Wt2VX8Vv5bexqfge/i13LO/KO7AbelXdl/8e78/vZjbwH78Fa8wf5I6wN7837sX/w/vxFdid/ib/CevBRfBzrySfwN1gfPoN/zPrxT/lS9i/+PV/HxvMNPI29x3fxPexTnsX3sTn8AD/CvuDHeA5bxJUg9rXgQrBvhRRhtlRUErHsZxEn4tivIl4kspWinqjP1omGohHbIJqIc1iy+Is4n6WIC8WFbItoLi5iW0UL0ZKlilbiMrZDXCGuZOniKnEV2yWuEdew3eJacS3bI9qKdixT3C7uYlmig7iPZYueohfLE73Fk5zEIDGI22KIGMKlGCfGc0fMErN4UHwmPuMhMVfM5a6YJ77lYbFcrOcJIlXs4fXFYaH4X6yAFc1bWnFWU36VdYV1BW9v9bFe5HdYw63P+UPWF9YiPs76xVrB37JWWTv4VCvDUvyzQDAQ5D8H3IDLfwnEBGL58sDqwEa+MvBbYCvfEEgLpPGUwM7ATr45kBHYxbcE9gT28W2BA4EDPD1wKHCEZwSOBY7xPYGcQA7PDJywA3yvLe1oftiOsWN4nh1rV+XKTrBrC2HXs/8qgvbf7L+JWvbF9g2itt3Obi8utDvbz4qW9r/sF0Qn+yX7ZdHVHmWPEvfar9pjxH326/br4n57vD1JPGBPtaeKnvZ0e7roZb9jvyMesWfan4pH7Tn2QtHfXmx/I4ba39nfi+fsZfZa8by93t4gxtjJdrJ4zd5sbxGv2+n2bjHe3m/niomSJBfvSSnrig9kY9lCLJGXyivEanmVvEpskH+XN4iN8iZ5s9gsb5W3ijR5u7xdbJd3yDvEDtlBdhU75X2yu8iUD8oHhScflv1Flhwgh4gT8mn5jMXlC/JFy5LD5cuWLUfJCZYj35RvWrFykpxkVZGT5RQrTs6QM6x4OVMusKrJb+Uyq6lcKddZF8pN8oD1N5ktj1ttZa5U1u1OY6exdZfT1DnXutu5wLnQ6uS0cFpYXZxLnVZWV+dy5wrrHucq5yrrPuf/nJus7k4bp43Vw7nZaWf907nNaW895Nzt3G31cu5zeliPOI86j1tPOAOcAVY/Z7Az2HrSedp51urvvOi8ZA10XnZGWEOcUc4o62lnjDPGesYZ50y0nnXec/5tDXNmOjOt4c4sZ5b1snPAOWiNcA45h6yRzlHnqDUqCsRnjY6yoixrTJSMClpjo9yoatb4qOpR1a3pUTWialszoupG1bX+Hbwt2MF6P9gt2M36ONg92N36JPjP4IPWp8GHgw9bnwd7BR+x5gQfCz5mfRHsF+xnzQsOCA6w5gcHBYdaC4IvBj+0Fge/Cv5g7QiuDf5mecHNwR3W4eCxUKKVF2oQGh2oGxoTmhYYGZoTWhSYHFoROhB4z5VuQuAn9zz3ukCKe5f7z8BR92H3MTvK7e32sSu5/dz+dqw7wB1gV3UHuc/b8e4wd6Rd1x3tjrabuGPc1+ym7jh3qn2e+7b7tt3SneF+aF/sfuR+Zl/lznUX2Ne7X7pf2q3dxe5iu437tfuD3db92V1lt3fXuGvsTu46d4Pd2U12t9jd3G3uPvsB96B71O7nHndz7UFuXpjsoWEe5vazYSts28+FnXDYfiEcE463R4QTwgn22HBiuKb9Wrh2uKE9Ptw43NieHB4aHmpPCT8Tft6eGh4WfsV+J/xqeKw9M/x6eJw9K/xG+A17dnhieKL9cfit8DT7k/D08Hv23GgeHW0vjI6NrmYvi64RXcteEX0k+ri9ingQ9juRe03lW6gp1aWztKn5Kk3tpGYqA+FNJabIUxPVR/hkqeE4ukV1RJ6lCGX45zPUbuy3+UeHi+XXZ3erbHx+PydLqOcg8Fqp8g4EviwSsxk1xOtaTrnB80K6jSoHYRcjeScK4zitqIz5V1NCnT+rrcpTv6CEVFxtemkylmFzUOo4v/TtKlMtVTv8owPFat8DpKgtarU6qm6iKLTduVSv0Pm80ipTh3DvslHC75Kj/WGxRM6+o94hFyi4hyfl3gvsUMkoYzMOA7CzGtOVCNUxZ5eo5Wod9Ae6A7+95Po/UG+ryfgeBiSpC1Rf1QehQu2Yf/UIZRbLnae+U+nQoO/UT5AD90G3XtFcBWl/LqUpCH4qUbQJjfRjPJT9S75uFtYKPyYbV34Abb9JHYS9XwlRLXAXCmpXe8wd2pOfulj+TLULfczLb3E9M2q+fyucpjS5/XTJRY4eL3L0Q9nKwNbcpPc1Ta3H/XPU+lJqPlKobzenS0pJ/aH6t+7R6rsyy1Q0/06tHVpni51ZW4bcuDL1ggnNObk/q3vLkB86oj4zvLVZ37fybup9w6bvo12Lb06ZSshS8w1rllEvSijhQNm1qoTcPsOqVRXKPdvs12vmOOvbX8tQ/87IWKZyoEcHy12De9qzTYB/mFryR7xtkY9/vk4Jec7Bpw4+5xSR8l3/e0Xkc5r8zUvM77cutOQQ2OnQqQQGf+5V+8FgW02f0lp91MSPNadrq6/UIrVGj+inyJ9bKPwyVQf/30ntdA/x41IwNiwozsUFeXIKhUdj5KlEN1I3hGf5cWlovZWnHlXz6zca/QbyR4F9evtMruM/UR+RUHNPmf9kLQzAeuqB+Ff88z+o79H+P/pHxfn7eKHwcOSuTm1JW0JJftyXah5K+M8p699ecnwe7pjmR3Wrull1V+381FOK5X8WLPaO+o/6Va0pFM2pMz1HIxAaSaP0b2boQ2juLJoL63ABLaKLzKxCS/qW1tHFtJF2UGtKZ4zuYt1YN3oCHv0/qI/25amf9uLpSf4Q70VPwR/fQIP5Jp5GQ3gGz6AX+W6+h4Zp35yG88P8CI3gOTyHRmrfnEZp35xehW8eorGijqhDE0Qn0ZneEN3EPTTRmmPNIe3VKpociA3E0s/25/bn9Iv9pb2Iltub7N/oV1vZilZpn45Wa5+ONshb5K2Uon062gKf7k7aqn06StU+HWVon452a5+O9mifjo5pn47y4NO9zAje3KvMlmPlBBalfTpWSft0LEb7dKyynC5nsCrap2NVtU/HGsOnO8DOhzenWDtHOAHW0XGcIOviuE40u8ep7FRh3Z2qTjXWw0l0arKHnNpOXdbLaeA0Yo85VzpJ7Al4bfezvvDOhrH+8M5eZgO0/8UGap+IDdI+ERscGhgazZ7Rng4b78a4CWyB+6H7IVviprn72FLta7DV2tdgG7WvwX7Tvgbbon0NtlX7GixN+xpsl/Y12D7ta7D92tdg2drXYDnaj2C52o9gJ7QfwXl0VHSIy+iq0dV4MPpo9HGunymsNxrDjMZwaMw4eBTj6U3o9ESagZh38JH0Ln2AUWom9Mk2+mRDnxai130JrQoarQpCq5Yh/kdaQyFaiw+Hlq2DVb2RfoN1lUKp6GNp0Ll6lE770eMP4FOfDtIRakBH8WlIx+gENaI8aGRlo5G1jEYKo5Gu0UgXGtmTYngv6KVr9DIWeplC8Xwz30xV+Ba+jarxVJ5KCTwN+lrT6GsNo68JRl+rGn1NNPpahSuuqIqA+U9x0FqOPTaqCt2VCOPmU3URBT2OM3pcA3rciRqLztDmJtDmbgjfA51uYnS6FnQ6hZi12dpB3NpppZNtZVgehawsK5tqW4esw1TJOmLlUh3rBLS/kdH+ekb7axntr2W0v5bR/lrQ/r9TnLxWXksheZ28jix5PfpDAP3hJsS0lq0R00a2ISnbyrbkyJvRTxqgn9yCvLeit0SZ3hLSMyAUlneiz0Sjz3SkerKT7EyVZBfZhRrJruhFlU0vqmx6EUMvehi5esrHkOZx2RsxT8gniMs+si9q6Sf7oeQn0dNC6GkDkWuQHIT4wXIw0g9B3wubvsf0fArSDJMvod7h8mWcHSVHIWa0HI1cr8pXkWasHIeY8XI8JJkgJyAG/ZOCun+inMlyMnJNkVMQP11ORzkz5AyknClnIuZDOQt5P5IfoR1my8/QMp/LeZBzvpyPNlkgF0Cqb+VSSPudXIYyV0poplwroZNyvUxGaZvkFqort8o0tMl2mYG6dsndVF/ukZloyb3So4YyS2ahxn3yAGTOltlIeUgewtnD8jDij8gjkOSoPIbyj8vjKDlH5qDkXJlLVeQJeQK158k85FVS6f9XdQJUS7MJ9mAT7MEm2INNsAebYA82wR5sgj3YBHuwCTGwyYvYD3OGEdecQpbmFGKaU8gFpwzCfnBwKMVoZiEBZllHbmh9aAOFQxtDByhGswwJzTJUHSyTRlXc7e52inN3uDso7O50d1K8m+6m42yGm0EJ7i53F9V0d7t7EfZcD+mz3Cyk2efuQ5qD7kGEs91DlOgedg8jzRH3KNIcd4/jbI6bSyE3z1WUENaudRXNX9hbYQv7QNimWLCYQ9XCUeEgVQ2HwiGkdMNhqgleq4KYuHA8JWp2o3iwWyL2NcI1kaZ2uA7FheuG66KceuH6CDcIN0D6huGGCIP7EA/uQ8xb4cmoZUp4KnJNC09DydPDM1DmO+H3qKpmQxKaDSlGsyHFgLE+9tlwND7CsGEAbDgB4YngQWF40AYLfojwLPoC+3kEbQMbfoXwN+BAQUvBgwI8uBaMuQ78Ksz8vWN4UBgerGp4MN7wYNDwYDXDgwmGB6sbHkw0POiySqwShVkH1gH7nqwX9o+y3tj3YX2wH86GUxgseStxw5JRYMnu2GuWDBmWjDIsGW04MY5n8kyqbHgw1vBgFX6Cn6BKhgFjhCUsigX3OQgHRZAqiw6iA9UUHc2bbJr7ahnuqyO6iC6I72rebtM8WMvwYB1xr7iPahTwYDoJMGA2OeC+XAoa1ks0rBevZ23RP6+WV6P3XiOvIWE4zpE3gOMscFxrhDW7CcNutmG3BNlOtkOMZjchb5O3YX+7bI+UmuMsw27xht2Cht0SwW7dyJX3ynuxv0/eh/T3y/ux7yF7YK+ZzjFMF/SZro/sg5i+YDrbcJwjn5JPIe8AOQDp85luKMIRjntWPoewZjrHMJ0wTBeUI+QI5HpFjkSMZj3HsJ7rs94YOQbxmvscw32JhvWEYT1LvgXWEz7rTZVTEZ4mp4HR3pZvI73mQWF4MLEQDwrDgw54cD7CEe5bKL9G+Fv5K/aa+xxwXzLCmvWqGtaLN6wXNKxXzbBegmG96ob1Eg3rufKgPIhcmvviDfclGO5L9LkvFxwnDMe5DnMYiQhbBfsHn6Ko4MDgQOwHBwdTKDgU3BQKPhN8BjHPB5+nKMNTPDQm9AZxwzhx7l5wTYy73z1AsYZfYgyzxIFZjiB81D1GlcApeejnmlMqh0VYUCWwiaRowyOxhkfiwCCxCGsGqRKuFq6GNJo74sK1wrUQX8fnjnooQXNHrOGOGMMdlQ13xII73kKZU8JTkGt6eDrSzwBrxBrW4MQv2qdnXi/e+feWdBPddSo7//+PTWWoXRr+0daS/C49z2Pm+spb9nY9w2U876/M8ab8Os3+V9/7zNT+p/FFk1WqSi86o1N6vfkzdOqx8kt4djfVGp6n/j6l710sRwY87e8rPi9TUE7myUdqv9n78fAVs9GyqcoDCmb2CnmicYVyJyPVBtLzHtUQ8mcY873rP2gLFkhTuF6X7jZxe0qaXVC7i8/NqQNqm9qIM8WeQlR0y58lL3qk+4+v1YXmCyC7KAhnnuouqy3FZzXP1lbyE5xSc81Q08x3rpkN/0FDzw+p9xFa5qfJ1yzdgw+pFfnx5apnu9HR1N+P9SyYSimU4hUzH6TnyreY0HZIU5ih/PYt6/01s9appacr/wZNK1SuOqxygeN6rkudKJLudM+l/se2P7jPl2FTk84g8y0llJdKTaGDtc+g1NNvTclwq+ZTw6klbuCGMj9DPPOx4qTyikhVuO+VMf8napGa7T8fiFNT1CITm6ZH98Kjd4Xshw3gxq3Gfkg3tolhMz0mqa34numn8szzth+BpfikF525NkxWnfLnZpdgLFimVgKTEHuTWq1+MvFrIlaEeaJ9d/klLSb5riJHZgxVHxeKeUhNV73US3qWX/UuiL0McV/oflf8qSPpZ67Fn4XuVl/hWpLPXk/N1wc9joHB8u3CZeQ/ny0sA3i54NmIfsZSSsm/nC0ZK7qhlcLm+1X9vLnY2T5qSZG0ke8UjG5pWkMqUN9arfXG3jLtpEMY37b6rYa9elAtN/f7CIkSxrAwNStWpod+sNd/uiTAHPlPnY5Ezp75+Pb7c+iizyvzrRRte5lxezs+XjHbc4uxPUvo7ejNZ5m7StpO4rPVxc7nnhzjxz9ecjyV5zl6uTf1QDkzRN6xGKaeN99ZhgE+1UDo32pOJGTO5dtn5nkn7tS8Ckj3ifoCjPm5f7REfUD6/aC5OgyAOcFiS8AS+VZwFtj3J58nIs/PoouV+b36XC32y4zTR358EXZQqvzSmnzopWpjwVG+77JNh/L9yoglbhhtmdaPyDsifv85YBi5s7rFHC0m/TTvMeBJhEarCRjrnvRLKfRuC1pggRpQAWnvUYPV26oXQt+gV7+tehh+eAWj0dto58VqkvonxtYs/QzQXNl8NUtNjdTsjxqJ6puTykxX6+BVRnru3wpCvt2pjkVQdou5SNnZpr8XvBVUdJQy43SB52ss363mvYfCb1xcUPSNlT9qK/oU17zBtLd0ScwVFXv/6o/YinqyulWhwwdL409zd86ap1uerbD9gd6gvaz1+D7Fk+6ClLvPXF71lhqk/qXGm/AK6Ps0/aaMPw5F7MVD6jNg0ZnVY0pqFnmT5YzKSFM7MRKa8RH3dCf0sMDmjtx1tQ82x76SLMBy11UBm7tQ7p8idxWyaB78xT/a4vcfX+o/pz+XtKkH1P1qoZpD3BwNVv3A1t0iFoGaq47iaIR6XF2qGoBHW6gn1YNnUFfEfqx7RvL6nBTxaQveN5xW9OzZ3NSMs1CG1t51EVaHfVvs7pvzqWrV76Pwn7tBmk3oc2bOEzqsPcUCTyVi6eLs98Ap3lX9ozfIO7Jwz4V9Nf/PlOfUG3pbH207Rd50VU/AOlqD3hc5t9jsN6l5qqN6CaFR6rdIXAXr+v7M5S1njdmF3/P6390KbNwDZ/52ZUnvup/NLWIdwv7egVHvLMxYlPaO8mnzllGj1Edmbn9PxWsqtFU/K6WUaYMtdMaWq3r1bEhSSh0+08G6PeN5+bN0l0qrJQ2W7X+5p5y9DVZP9llrmdgzkONs9Pc/8HlERbQRdk9qJKf/y478eZHl5jnD8tNmfsRPO7v89f7RW0V+A1GsjFM+DTlNHjNbr2eKIp5wZEan4Flw8HT+sZnbrU69yC5/vSZ/BX7lpdLN2PH7b8ny5+TK6tuF6Iby1/qnbvEVzVj+J0+k32rQz6ULPHu1wOz3gp9LfRrxv7bB7j906t9MFEp39L8vS9m2sjFkRUf1En8rVWpd5g2C3387aJ5YFGhWsMRM+Wn1XFVN6og+9ydsRW33CGvAeyqFZ82TmD9hvk/tP4tlbSN/RrnEXxydY37lpJ+gryjhbGll699RbcvPmR8yM/zb/Jj8Oi8zdZ0kV6GjF38vM18W/XutYlLpX2U1109pKuK1q0nqXTW/4HdgfkhbBP6c5ooCOZoXk/fd8tdXJH8F3hRSq8xTiR8Ljs07QLA37TI/6SvDr/dOUXeJv00uJc9OM2ulR3LDBeZoCfpehBmCp7MvzYhSia4s2+81S8hfkfcfVuvfWxocjhybvT9rfnp28K+lZtH3jaBf+9VKg0lUDTbpLv9p0tZInza69lD5JS3lOiJP2Ap566qbelK9pyabdQMK3ulRrdUn5Sx5yR9jMWsZT12PyivpqXLkieJJcftLf4pT0c28I+MzszoAe+IA7KMNKvl3JlKZiNPPjC9Rd5jjT6EB61RntVQfq8XqNfWdnjE358YWKTslP75cErVTvdQz6ib/yISggT1M+F01XfWGHkyCtTYfI69OMUd9rj7zR209Ox9Pzcwz5/6qp4mLvI84GXb1W/p+6FUSCt4CKjIXpI7l/5q/XPK+od6Hr/amf7Tc1D3J8Pxy0wb66etsla2+Ngkiv9r33zDwtfhv5a/1z9r+K7/GLl7LtnzGijx3/rO2ijynwp3eS4VmHQpWSCjL2FOF9Ps7t5lwTWoB37OuybsDVscOM5rUoL+qteih+pOiNqtL0V96kKsi47rvp6J3Rnyqav7xJ/6TCk4Fv5g28R+e5jrMuxVqAMY5fwZSXa26Aq3VA1RFRcbg/DU0BgPXqctUe+X/skH9oH4zb0voHrsbY9I23389j5qakfM8k+r0sxslyzVNTcf+/YLj+dqXK/Jmxe1+oCP9gy6hi8w6MY3MmcLXHsxbpUJ5R8xIuVA9rD7VY5gaop7TIZQ6vEi1kXfAHq6AvD3Vo7j+R82Bg1BPw5vPmZF6Je5lel7kl/Rzzaog+ZtpWfWEX0YZfLwS695VeppieTLNGwHaTjDaZLR5CY4tc9o9rb2jc1WiyyE9p9WlrGPXwV/H7lm6kXFWlbqb1en6m9XphpnV6YazDqwzjWYPsgfpNbMu3eusLxtOE9gINp5m6dXpaL5enY4W6NXpaKFenY6+ZF+zFbSYN+PNaTlvwVvSr3p1OlrNk3gSrdGr09FafiNvTet5b/4EJfP+/Cn6jY/mY2kzn8FnUCp/j8+iND6Hz6U9fB6fR3v5Qr6IPL6EL6X9fBlfRgf5L3w5ZfNf+Uo6zFfz1XSUr+Pr6JhwRZiOixgRS7l6hTlSZoU5MivMBURD0ZBJs8KcY1aVC4mWoiULm1Xlos2qcjFmVblYs55cFdFBdGRxoovoyuL1b+VYgl71jSXqVd/YBdZcaxHroFd9Y/fqld7Y/XqlN/ZAICZQmfUIxAWqswf1em/s0cBvgW2sn17vjQ3S672xwXq9NzZEr/fGntbrvbEXAocCOexFvcYbG6nXeGPj9RpvbIpe441N1Wu8sRl6jTc2U6/xxhbpNd7YYr3GG/vV7my/wNbr1d0406u7cUuv7sYDenU3LvXqbtyxp9rTebRe143H6nXdeBW9rhuvqdd14w30um68ib3M3sDP0Su68Uv1im68lZ1u7+GX6xXd+NV6RTfeVq/oxm/RK7rxh/SKbv+PsvMPi+q61/2aPTN79sDmh0gMIhIlBAkSgkiQIhgkhBhjCSXGeKxhBhhmJjAMwzAzjDPDnp+MxlpjrTXUWmOt9RhijTXWWuv1eKy1XuP1cIw11hpjPR5jrcdrrTXWWnvf9R1CPX2e+zz3xme9rOe71157ZoDv+rx/8EZYxv8+TlAkQRKEoCRKOiEkJUvJQkRKk9KFqJQpZQqDUpY0UYhLk6XJwgppqpQnvMkT14Sv8cQ1YRVPXBPekmZIM4Rv8Nw1YS3PXRO+yXPXhG9JtdJc4W2euyZ8m+euCRt57prwXZ67JrzDc9eELZJZsgjf57lrwg8kl+QStvP0NeFdnr4mDPP0NeE96U3pTWGntEpaJbwvvSWtEXbx9DVhN09fEz7g6WvCT3n6mvAz6QPpoHBAOiR9JByTzkgfC+elX0u/ES5In0ifCb+Vfif9UbjOU9mEz3kqm3BX+pteJfyZp7IJ93kqm/BXnsqmVukn6nPVKTyPTT1en6cvVGfqp+tL1JP0Zfoy9WP6Z/TPqKfoZ+lnq6fqa/R16gJ9vb5eXaxv0M9TP6Wfr39JXar/sv5ldZn+Nf1i9TN6u96pnpU0JSlfXc3T3dRzebqb+kWe1qaez9Pa1A6e1qZextPa1GGe1qZ+M3lhcrv6Pf5Xe+qf8bQ29c9lnZymPsFz2tS/kr8qW9U3eU6b+gHPadNoeE6bRsdz2jRJPKdNk8xz2jSP8Jw2TQ7PadNM5jltmik8p00zXd4qv6cp5jltmnKe06ap4jltmmd5Tpumlue0aebynDbNizynTdPEc9o0X+E5bZqF8m/lS5olPGVNs5SnrGle5ylrmjaesqax8pQ1TRdPWdN0pwqpksaeKqematypGamZGi9PVtP4Uz9P/VyjpLE0lSbIBNUldL1UOL40ls5UbBz+qVkGzmENy8LZrcWp/gTqBfinY9NwCkqsGF1Sj344m8noh/z/8zCH/g8YvGOmUsdMQ8dchLtew79x6JuvY8cW1s5qmQk9dC56qBPk0Id/dczFvOwRtgz/JjAfU/DkIDpsFjqszCaqUlSpLJv+QniSKh099yn03GmoFKoKWanqSVUR6tNV0zEvRi+eSL14Bnrxy9AmdOTnKS90oup19OUy6stl1Jdnoi8HUB9QLWflqhWqFdjzTXTqSejUb7EK1RrVt9gs1Xp07RnUtWdQ155BXbsUXftdzIfRu0vRu3+B8+Co6iibrfql6kNWrTqBbl5D3VxANy+HPoOeLlJPT6eeLlBPT6eenkk9/Tnq6U9TT6+knp6Dnv4ue0wYFobZZOE94YdsqrATXT6Punwedfkp6PIHoP8DvT6Xen0+9frJ6PX/C3oSHX8KOv4I9N/R93Op7+dS338cfV9mT6hT0P0LqPsXUvefhu6fxYrUE9UT2XR1tjqb1fOTAHOcBOxJnATToIXqJ3EXzgNWzM8D3FWlroLOVs/G1Rp1DXSOeg7W4GyA4mxAhf+t9Qv0t9bz6O+rX6C/r55Hf1PdgHMiyOZoQprlTIXTYg1L03xDs559SfO2ZoiN13xbs4lVad7RfI89qtmi+SGbqNmp+THLxonyE1bG00RZOT9XWDU/V5jMzxVoujadzdWO045jM/jpwspwupxmau2vtL9iU7RntGdYmvZj7cdMoz2r/TXT4tQ5j8on2k9QuaC9wHTaT7WfMkl7UXuRPaL9rfa3LJmfSSyFn0lYeVV7lY3T/k77O5aBk+n3TKW9rv0vPPGG9n+z8dqb2pvsUX5W4Yl/0v6JZWnvaO+wGu3n2s/x2u5q7+L1/Fn7Z8zvae9h/hftX9gc7V+1f8XOD0SBjRfVoobNEbWilqlwwukYDgtRYimiXkxiaWKymMzUoizKLEtMEVNYjZgqpmINTkH+f3UXx+PeTPER3JslTsT6bHESyxBzxMnYOVfMZTwBdSo0T8zDDo+Lj2N9vpiP9U+IhVj/pPgke1QsEotQny5OZxqxWCxmqeJTYgn2f1p8GveWiqXYbYY4A2vKxDLcO1OcyWR+4uJZs8RZqFeKVVg5W5yNHarFWqYV54rPY2WD2MB04gviC3jNL4tfwftqFl/F/q+LRjy9VWzDU9pFM/axiF2sVrSJPWyu6BBdeKJb9LA6sV9E9xCXiT42QfSLfrzagKjgvQTFEPYJi2HsEBEj2CEqRlmyGBNjeMqgOIg1cTGOp4AA2CROAKwUBPANVi6uFdeymZwD2ERwwNu4OiQOsWzx2yL6gPgd8TusWtwobsSnvVncDP2euIWV8QxYrAcrYIf3xPegO0T8lIo7xZ24931xF3te/JH4I+y8W/wAV/eKe3HvT8SfoL5P3I+VPxMPYOW/iIdw9V/Fw6wChHEU9V+Kv2Ql4Iz/ifXHxeOofCh+iJUnxH/DyhFxBK/n38VTWPOR+BFe4WnxV3jNZ8Qz7CnxY/FjNks8K57FvWAU3HVBvICdPxU/xV2fiZ9ht6viNaz/vfh7rP+D+CesuSPewafxufg5Xttd8T6byDmGzQTHpGCeqhvHynUZuvFski5T9yir0GXpctgs3WTdFDYDlDONVesKdU+yF3VFuulstq5YV4zKU7qnWY2uVFeKHWboZmBlma4Ma2bqZuJquQ7eEWz0JfaMrkpXhWfN1s3G+mpdNa7W6GrwLJ4poOLMxMo4M0HBTFAwExTMBAUzQcFMUDATFMzEsjkzsUmcmaBgJvYUZybMwUysmjMTm8izalmJNFeai7tATqiAnLAG5AQFObEKTk5sFsgJTkCySBZWA37qYWmSQ+rFGlAU7gVFoQ6KwsqQFMI+YSmMeUSKoA6iwusBUWH9W9JbrFxaI63BXeAqNhNctR6VtyX81ElD0ncw/2fpn/Gs7dJ29iInLVRAWiyJkxYUpAUFaUFBWtDfSX9gz0q3pFt4yh+lP2IfUBcr5dSF+d+kv/H/95aesef1Kr2KTeQExiaBwHRQSS+xZ/T4j5Xqk/RJmMv6VGiaHuevPl2fzir04/QZqIzXj2fV+kx9Jpupf0T/CKvRT9A/ivpE/URWrs/WZ7On9JP0kzDP0efgKZP1k3E1V5+LCtgOc7AdXgnYDgq2g4LtoGA7KNgOCraDgu2gYDso2A4KtoOC7VgSZzv2LNjuFZaetDBpIROTXk16FfNFSYswfy3pNcwXJy1hmZz8UFmetJUJST9I2oE5+A9z8B/WgP+w5s/JKiYkC8nZ7DlOgawykd3AKZAJnAKhoEDoV+WvssnyUnkpmyK/Lr/Oxsktcgt7TDbIBva4bJSNLE9ulVuZWm6TOzA3y2ast8gWrLHKVqzpkrswt8ndLF+2y3as6ZEdWOOUnbjaJ7tYLsiyH3Wv7EUdfAkNyAHogKywHDkoh9hUOSxHsDIqR7EyJg/iiSvkr6GySl6NncGgeMpaeS30m/I6rFkvv43XPCQPYZ9vyxsw/478HazfKG/E/Lvyd7HnJnkTrr4jv8OmyZvlzexJTq6sEOS6lU2XfyD/gNXL2+R3MR+Wh7HmPfk9XH1ffh+6S/4RK5Z3y7tx9QN5D67+RN7HiuSfyvtR+Zn8M1TAu1DwLvRf5cPsCfnn8hGs+YV8lBXIv5R/iZXH5GN4ygn531AZkU9hT9Aw9j8jn4F+LJ/FmnPyb3D1vHwe+3wiX8D8U/lTVg5K/i12uyRfYtM4K7NcsHKE5aREU2IsL2UwBZ8SuHkFK055MwWfVcqqlFXssZSvp3wdlW+krGXTU76Z8k1Wz3kaFfA0K+Y8zTI5TzOB8zQUPA0FT7NMztOsDGRXSzzdQDwtEEknuPkLYuZ8nEp8nMr+Cf9SiYznERnPJzLOIDJeQGQ8gcj4USLjLCLjiQ/l92gpv0ei/B4t5fdoKb8nifJ7tJTfo6X8nhTK79FSfo+W8nu0lN+TRvk9WsrvSaP8Hi3l97xI+T0vUX7PeMrv+TLl9zRSfs/LlN/TRPk92SD1ZHBziiqFGH0ie0aVrcoGQ3NSrwSpv8yqiMVfUb2q+ifUOYvPVplVZhC2W+WGelQ+cHMARD4LRL6C1YDF38T8a6qvYT0n8lkg8rdZLVh8I5sLCt8D/bHqx6xOtVf1L7jKKfw1ovDniMLricKfB4WXMjVRuPoh/laDv58j/n4R/P0SUThPGNJQwtA4ShgaRwlDj1DC0Dhi9K8Qo39JeFNYyebwZH+2cJTUOZdPF94X3mdPCvvA5Y8TkT9BRD5N+FD4EPzNWXyqcEo4hfqvwN9TKbVosvBr4RMQ+afCp1CeYFRMqW5FwmXhP1H5TPgMyrPdcinZKF/4L+EG5jzfqED4g3ALc55yVCj8RbiPOc86ekx4IPyN5VLiUZ5apRYw57lHBWqtWos5Tz/Ko/SjfHWyOhmVNNB/CXF/GXF/OXF/s3qSOgd1Tv8l6sdB/0+rC0D/JUT/peoidRHmxepi6Az1TDYTTmAW5pXqSvaU+kvwAyXkB2aoq+EHStTPqp/F/twPlJATeJWcwCJyAq+SE1hEHqAB9L+epYL7N7EMIv4sIv5JRPyVmr0g/tkg/iOsRvMLzQlWR9xf/1Amk5YymdIok2k8ZTI1kROYT05gLuUzvUR+oAp+4CMmkgfQaX8NDyCSB9CRB0gl+tcR/WdpL2svg/KvaD9DhXO/SMT/KBH/fCL+DCL+LCL+idrb2ttQzvQNxPQ6YvoMYvoGYnpBFMH0OqJ5HdH8RKL2BuJ1HZF6BpH6RKLzBuJyHXF5FnF5A1gcvlcsAZGLxOIZxOINoxReLpZjfYVYgfWcxRuIwhPMrSPO1hFbzyO2nk9snUFsvYDYegKx9aPE1lnE1hOJnieKq8RVYMqvi18HTXJ6riJirhbXi+tR58T8DBHzXHGTuAkcyVm5QtwCVq4mVp5ErFwjbhOHwfHvgZInESW/QnxcI+4R9+AuTskVRMmvgJL34d6fgpUnEStXEivXiD8Xj2CHX4i/wHrOyhVEyZOIkiuJkmuIkuvFU6DkaqLkuUTJFUTJNUTJtUTJzxMlPyN+In6Cq5yPE2T8jHhdvIkK5+NK4uMq4uNXxAfiAxAqJ+NqIuMakPGjmHMmriUmnqubqnuC1REZ1xMZv0Zk/Bxx8Fzi4NeIg+uJgyfpZulmQTkBP08EXK97Vvcs9uSJYmmUJaalLLE0ShFLoxQxLaWIJVGKWCOliGkpRUyra9Y14+k8S0xLWWJplCL2EqWIjacUsSZKEcumFLFsShHTUoqYllLEtJQilkYpYuMfShFLoxSxJEoRS6MUsWxKEdNSilgapYhpH0oR01KKWBqliGkpRWw8pYhlU4qYllLE0ihFLPuhFDEtpYilUYpYE6WIaSk/TPtQfpiW8sNSKD8sjfLDtJQf1vRQfpiW8sPSKD9MS/lhaZQfpqX8MC3lh6VRfpiW8sNepPywlyg/bDzlh32Z8sMaKT/sZcoPa6L8sGzKD9NSfthLlB/WSPlhTQ/lh2kpPyyb8sO08DDjWRUcyxNsLvmTOmmaNA3eoFAqBOtPl6azSqlYegp+o0QqQb1UKh31LRVSmTSTPU/upUKqkCqh3MPUS7Ol2diHe5g6qUF6ATpPegm7LZC+jDWNUiN7RnoZTqZGapKa4RBek17DVe5naiWDZMDraZPacFciiZE7nHo4nE48izucVKlXcmKfPqkPd7klN3tO6pf6URmQgngX3OdUkbeZRMmNFeRwqqXV0moo9znPk8+plr4loUuQz6kgh1MjvSO9g8r3pe/j6dzt1JPbeU16VxrGXdzz1Eg/lH6INe9Lu6AfwPkkSxek/4D+JzxPMnmeF8jz1Em3pdvYmXueKukv0l/w7rjnSSbP8wp5nrnkearJ7VSQ26kit1OhT4HDqYbDGcdqyeHUk8N5jhzO83A4E+CCHtVnYeVEOJxK8jaTyM/Uwc9Mw1OK4GeS4WfKoRX6KmgNPEwyeZhkeJiXody9JJN7SSb38gLcy8JRx8K9ymL4kCXkWJYmLUWlPamdzUnqTOqE2pJsUHuSHepIckBdSS4oz6IbR1l04yiL7hHKonuEsujGURbdOHI+avI2X0melJzHvpQ8P/krbE6yKdnHFlJSnYbcjgYOZzpcBPcw08nDPCl3wMNMld+QO0Hq3LdMJccyHY6lB3OH3Avn4JE9qHCv8rjsl/2oDMhBuBTuT54gfzKd/MmT8CcrUfkaXMqT5FKmyW/Jb2E99yfT5W/J63H1bfiTafAn38Zu3J88Qf4k4UweJ2dSIn9P/h70+/L3odyZlJMzaZbfhTOZAWeyA/UfyjtZKTmTGeRMZpIzKYcz+QCVPfKP2VPyXnkvVv5U/inq3J88LR+APymRD8oHcfUInEkpeZJy8iTN8nH5Q1w9IZ9EnTuTmfJH8kdYyT1Jufxr+Rzqv4EnmQlP8gl2uwBnkkvOpFS+KF/Ec7k/KSN/8rT8HzIYj9IBiymPtEi+Jl9HhScF5sk35JuY87zAAsoLzKO8wGLKC8yjvMDHKI80V/6r/Fcozw4slv8mgwApQTAfYA4CpBzBxyibNJfSBCdTNmkuZQoWUKZgMWWTFqWkpqShzvMFC1LGp4xHhacMFlLK4GMpWSnZuMqzBospa7CAsgYLKWswPyUvJQ9XeeJgASUO5lHiYH5KZ0onm0pO7Ak4sTA5Mfw8pCxPWQ6HtgLu6wlyXzPJdzXDd30L8/UpQ6yU3NfMlA0pGzDnyYUFlFw4mZILiym5sJCSCwsouVDDVJNu5YQAv7J6JfuUMeMSDCOGGcOG4cTwjn1VOYbxVcGIYazEWIOxHmMjxhaM7Rg7MfZg7Mc4hHEU4wTGKYyzGBeYEDpOgxkv0xBCIxhnML+GcRPjDsZ9xloFDAkjFSMTIxtjSuI1tBb8X74WJ/ZqLRsd/J5KjDl0jbXWY8xPvF66Z0viPbY2YSzCWJqoj34VQudpqBy7MPZifmmslhhXMW6Mzs9g3B6d30uMMBsdIoaMkYGRhZGbWBvOp/WstQ3DmvicWu1jn3libRGtY60uDB9GCCM++h5WJZ4XLh19r2sxhjA2jV7fOnq9YnRUo4bvYyt/PwcwDo+9l8R73otxAOMwxjGMkxinMc5hXMS4Mvr1+kNfv1h/C+Pu6Ndzo/fdfej6A8baNBhJGOkYEzBy/v6Vf//a8jAK/5+/CuG6v3+v+HtrKxn9Xv//juz/Pujne2XiOfRzlZ1YR899eJRjVP3969geiX2F8DzUazEaRn/+cK1twd+/tjVjLNaMa7nYPX9gxBjrYaQiqQxd2ZMBXdOTBV3fkwvd2JMP3dJTNDDC7wouNW7vKQ22tVzpbho403K9e9HAeePOngrS6rH5np66gfP8atDacqt76cAl4/6eeQOXEvNRvdvdNnDVeKinkXQh9CjNj9L8RM8S6KkeI/Rsjxl6occ2cJXfFbRDrZg/6LYP3DBe7nFCr/V4oTd7lIEbvB50GTTdroHbxjs9Mej9npVBnyGp2zdwr1XoWUO6nnQjVGqth6b2bIFm9myHZvfshE7p2TNwj98VDLUW9OxXNhrSu0MKPtmeQwozTOiOKyLXYNyQ071KkVvLeo5CK3tOKDKvBFcl6qOa171WyTAUdg8pWa1zek6NaX3PWSWL14NrR7Wke5OS2zq/5wLpZWgTzRf1XIMu7bkJbeu5A7X23B9Tu0MIDrW6HFJwk6G8e6uS3+pzpCr5tFvRaCXkyPxCeSW41VDVPayUtsYd2aRTvpjzenDYUNu9S6loXeUoUCr4PLjLUOsoxryhe69S3brWUUZaOTYfcsyBbnLUQ7c65kOHHU3QXY5FNF+qVPN7g3sNC7oPKHWG5u7DyrzWvY62MT3gaAseaD3ssCrzDIu7jymNhpbuk/Qa7KSusfkxhw+vxNR9WlnYetIRGtPTjriy0NDZfU5Z8sahZSHSOOkq6NFla6Enlg1BTy3bBD27bCv0wrJhZQm/a9D3xuVluwZDBkf3RcVo8HRfUcxvXFu2F3pz2QFSPr+z7LBi5lcH44ZA93VFfOP+smOK2Cl0Xx9clVBDpPuWYuuUlp0kPQ1NpXkqzTOXnYNmL7sInbLsCrRg2XXFxu8aXAu9i/mK7geKs7N42S1o2bK70MplqPD64JBhtV2jeDvn+LjW+5IGNxnW2ZMUpXO+L51rZ5zmE6BNvhzoIl8edKmvENrmK4FafeWKwu8a3Npp91UNDhs2GC4psU6Xr1aJGTbb05WVXMP5hm32CcqaTp+vARryLVDW8MrgrkR9VHfYc5T1ht32PGVjZ9zXPKarfIvxu4P64N5R3WcvVLZ0rvW1kJrG5kO+TugmnwO61eeBDvsC0F2+CHSvb8Xggc4DvtXBNsNBe4myvfOwb93gYdpt52jlmG8D9CRXXhk8ZjhiL1f2dJ72bSbd9sWc1wdPGo7bq5T9ned8O5T9fD54uvOib/fgOcOIvVY51HkFnzzUt29sft13EHrLdwR613cc+sA3ohzq0vjOQJN855VD/N7Bi4Yz9gblqOG8fYFyoivdd+kfdILvqnLCcMnerJwyXLUvVs525fhukN4em+f57ilnDTfsLcqFrkI/G9MSv6hcMNy2m5TLreccq0jXQi/S/IpjCHrdsQl6y7EVetcxDH3g2KVc5ncFD7dpHHuDxwz37J3KNSOzO5SbbUmOA9B00gmkOY7Dyk1+NXjSKNo9yh2j6DjGlc/b8hwng6lG2R5Q7rcVOk6TnvuHeYnjIrTccQVa5bgOrXXcUu7zu4KnjRn2SFAwZtlXBKW2Bsdd6ALHA2hzrwa6uDcpKBlz7auDqW0tpKbe9OA5Y759XTCzrbN3AmkOaV4w05jfW4i5o7cE6ukthwZ6q3gd6y+2RXprUVnR2xC8Yiyybwhmt63uXQBd19sczDaW2jcrp7gGr7dt6F0cvGWssG/D+s29LdihotfEFZWLifqoVtt3BKcY6+y78dq29XZCd5Du7nXgk+H1u237ej04PWlunGffFyxoO9gbII2M6ZHeFdDjvauhI73roGd6N0DP926GXurdFnzQdrV3R0iDfQ4Gi425vbuhdfYj0Eb7cbzOG737oLe5UuWicaF9JFjWdq/34H9XXg/BtvYeCRa0i73HQ+nGJfYzwcp2uXckWMnnoQnGJb2oGI328/S+Enrpi3l7Ru9VaFbvDWhu721ofu89aJGTQUudIt47v/eu0Wy/FJxjtNmvBuvbK5zyP2i1MyNYb3TabwTnG73228Gm9jrHWq7OrDGd58wNNhkV+73govZGZz50IekSZxHU6CwN5XAmCeW1m50V4BOwQaiw3easHrja7nTWQb3OeYkTPFTCz8FQebvibFRy22POhUouP4lCVe0rnUv4qeQ0QnHWhGrb1zjNSkX7eqcN5wt+X0IN7RudTuUy/7kNLWjf4vQq99u3OxXoTmcs8TMWaubf39Di9j3OlcEC4zznGig+h1BL+37nev6ZODdCE+/0kHML9Khze7CJTpwrXeV+GacP7/zXu6r8GYqtq9afBW3w547251u8yw3e7Vrgz1e2GPb5i6C8zzzoavaX8p7jr4Cik8Q1XYv91egeLf465Sz95F9sP+HcGTK1n3LuCXW2n3XuDznaLzgPhTztl51HB863X3OeGLjUftN5KhTAmrNYc8d5IRRpv++8HFphEpzXQqtNkvNmaJ0p1Xln4IZhgfO+UmfK7BNCG0zZfVJos2FxX6rSaJrSlxnaZijsyw7tMJT0TVFyTQV9BcFjpuK+4tBuU1lfWWhfgjdMlX2VoYOmOX1zBkY4UYSOmOr76kPHTfP75vPvQl/TFye7qalvEelS6CK8thHT0r620BlTW581dN5k7bOHLpnsfa7QVZOrzxe6YfL1hUK3E0zbKvTFQXEJjiJKMYX6VoFdiRtN8b610FV9Q6A4/rNxr7WtD2pa27c1zExDfcNh0bSpb1dYNm3lKw2avr0Dt03DfQfCGQlyM27sOzwwYtrVdwy/48Sopr19Jweutmb3nR64ZzrQdw5Pt/ZdxOdwuO8K9FjfdSXfdLLvFhhsuO8uXs/pvgfQcy5NaLXxjisJ+190pYezTFdcE0Ij/BMI55quu3ISP9vhfNMtVx72uesqVCpMD1wl4aIOjas8XJogzI4kV1W4oiPdVRuu5r8X4bqOCa4GUDpYPTwvoR05rgUJAg83PqQLSZfQU4yk5o48V/PA1Y5C1+KBGx0lrpaB25yow7aOcpdpdO4k9fLfr7Ay+kmCh8Mx0pX8VYXXdFS5OsNrEnPS9R21LoeS0dHg8oCHQcXhjR0LXIEEA4e3PKTbQaouJb+j2RWBLubKqTW8M6EdLa4VCVIN7+kwuVYrpR2drnVQ1FFxuDYkqDVU+3cN7+e/9eFDpEcT2uFxbQaLgkjDJzoCrm0gT3Bp+FRHxLVDaexY4doNdbj2gTlPug6CLfn35WxCO1a7joQvtOW5juO3m3fm1I51rhGcnnmuM5hvcJ0PXzbmui7xE8F1NXytY7PrRvBWxzbX7fDNjh2ue+E7HbvdLHy/Y59bjAijvZ26t3GJW45IHQfdGejGXndWJDXRCTuOuHMjmR3H3fmR7I6R3obIlI4z7qJIQYIB2jrdpTgL6JTpOM/7duKM7rjkrogUd1x1V0fKOm7w07bjtrsOpx66VqSybcQ9L1LZcc9xOjKnbZ27MZhtZu6FkezRc3mbe0kw1Sy6jZwl3Gblsll22/iZ7nYq980Zbm8w05zlVvDc8+4YP7/c6IHmXPca1PPd64OZ7aXujV+cFOYi95ZIvbnUvR2vDSwRzjBXuHeGRvi7i8w3V7v3JDpt8LS5zr0f+8xzH8IpgDM30mRutO+OLOLnVGSpeaH7aKTNvMR9ImI1G92nInb+uUVctI/PbHafjYTMNvcFeBz08Eg8QTtcQy0J/YJq7J7IKq6JSmQt6RB/DZFNpFvNTvfloGD2uq8FJbPCaYSTSajFHHPfTMxx3kFxF86CyDDvupFh80r3nQRXRHaNKt5FqNm8xn0f5wXN6X0Nm9d7hOAU80aPBKIAV0T2mrd4UhMUgVc1ppGhtm2ezGCxebsnG7rTMyVx4mMfaOSAeY+nIHHKRw6b93uKg2XmQ54yKOqoHPVUJk75yLGH9CQ/pyKnSYdIz5lPeObg7MYJHrloPuWpx0mNczxyxXzWMz8433zB0wS97FmEU6zRszS4iD7z66S3Rj+Za562YKX5pscarDff8diDTeb7Hpdy2SJ4fJG7XSb/vHhSV6e/MdbY5fAvhHr8S5Q1XQG/UTF3RfxmRexa4bfF07HGiaur/d74hK51fgVXN/hj8Zyuzf6V8byubf41cEOb/euVlV07/BvjhYZ1/i2K0rXbvz1e0rXPvzNe3nXQvydehRNzv7Kl64j/UHRF13H/0Xht14j/RLwh4Q4Mx/2nlP1dZ/xn4wu6zvt2x5u7LvkvxBd3XfVfho+76r82xuE3/DfjLV23/Xcwv+e/H91tYwEhbrKJASneaZMDqXGHLSOQGffYsgLZ8YAtNzAlHkk40M75gQJ4roTTIU9hyw8Ux1ckXJ6tCBWnrTRQBs+Fsz6+unNroDK+uqswMCe+zlYRqI9vsFUH5sc7O4v5SsPqQJPitdUFFsU3J3zWG4cCS7/wswmPaZtHvnJ+5xXu+AJtY08fDlih5JVsjQE7HFPC4zyAxzxkW+i/Ga7unBNwYf8lAV98m80YCMFn4ROI77CZA/FRVllrswVWKVtszsBa5azNGxiK77YpgU3xfQk/aIsFtsYP2lYGhuNHOOfEj9vWBHbBU8NZx0dIz9jWB/bi1ICDxnkBjZ/nGiRPHb/EnxK/mlDbxsABvKMt8FxO2/bAYcXL/W/8hm1n4Njo/DbpPc5Ly9noJwn3ulwcVbyq5bJtT+DkcjkxJ82w7Q+cVtbbDgXOwb3Cwy7Psh0NXEw41uW5D2l+57HAFXxiJwLXoae4co8ZWpxQ29nArYSvXF5kuxC4q+yxXQ48gKKOyrUBTcJjLi99SCs4xS2vJq1LqO3mQBKcI/zj8nm2OwPp8IlwkcsbbfcHJiinuoWBHKg0kKec7U4dKIy38O/L8oWkSwyrB0riN7ozB8qV/d3ZA1XKie4pA7VYWTDQoCyxSJ5Q5AF5BzqPqHfBs1hSPfGoxpLpWRVNMoqeteEMS7ZniJ8dnk3RdMsUrphvjU6wFHiGoznQXWNa7NkbzbOUeQ5ECy2VuEtKeDrLHM/haIml3nMsWm6Z7zkZrbI0eU5Hay3ZvH+S3rUs8pwL3+TdMtpAuqAt4rkYzLQs9VyJNlvaPNeji40VnlvBixar5260xWL3PIiaSDt5n4w6Rr0VNOqxuPo10UDCZ1l8/UnRiCXUnx5dYYn3T4iutqzqz4mus6ztz4MO9RdGN/CeGd1Mus2yqb8kugNaHhQsW/urorstw/210d2JM8Wyq78hus+yt39B9KDlQH9z9IjlcP/i6HHLsf6WcDV1Uclyst+kmC2n+zujI5Zz/Y7oGcvFfk/0vNHWHwjWW670R4JzLNf7Vyh7EicU1+glo4LTEPP+1RFfgtw60vvXRa9abvVviN4wsv7N0duWu/3bovcsD/p3RB5Yivt3R/Osmv590RJrUv/BGLOm9x+JidYJ/cdjsjWnf0RZY83zDMUyHt7NWth/JpZlLek/H8u1lvdfiuVbq/qvxoqstf03YqXWhv7bsQrrgv57sWprs5fF6qyLvWJsnrXFK8carSZvBrTTmxXLGFWHN1e5bPV482MLrQFvUTRijXhLY0usK7wVMaN1tbc6Zrau89bFbNYN3nkxp3WztzHm5d/fmGLdZvTGYtYd3oWxldYcL3q+dbfXGFuT+N5Z93nNsfXWg15baLX1iNcZ22g97vVCR7xKbIv1DG7dbj3vXRnJNM7zwmFZL3nXQ696N8Z2Wm94t8T2WG97/w973wNV1Xnl+51zz71cDd4gIUgJoYQYQgixhljKUEqsRYP3n8QS6xhqbrnn/jv33Mv9LziWqAUXpY5FxxhrjfE5PodHLENdjrXUGOsYax0eJdQYxuVjqHWMJTzKM5Y41pK39z7n4hVJY9fMW+ut1a69fvt8fOc7+3x/9r/zec61HfjNNaVN3R5W37lh0KOrP9yo8yTXdzed8KTWn2g67cmoP90oe7Lre5p6PHPr+5v6PQX1A00Dnvn+vg1lnuL6wW+VesrqLzcNQsthaLmofqzpsnIXT2X9eNOwx1p/a32fp7qBbxqz6dz5jeOeVQ36pnFbWYPh5RyPrSGt6ZbH2ZDZzHvkhpxmvSfkXtest1U3QHT21DcUNkMu11D08gpPY0NJc5qnqaG8OdPT2lDRnONpazA257mKGqo2jCFvLlSe+j07GlY0F3l2N9Q0l2D20lyOWUpzBe6iNBsVi6MdjM3qTsWd1nFc3SugnYHmKs++htpv5WN8b16Bz+DNNaiNzbXK7hD5hxue9thOkE+ZmKezwf3yOVdeg//lc+ruDe2reA77A81u17WGSLNfeer3dDesbY7gWq9fzng2hxvj/g9j3O+4ccZzN7nfM4H7mOeYjtfyOjaDv49PZvfxKfxsNot/kE9n9/OZ/ENsNp/LP8oe4PP5J9iD/Gv8a2yOplKzlGVol2ifY5nakDbMsrQ/1f6UZRuA2GcNOQYLyzFUGWqY1fCSoZm9aNhqeIttNJwxjLAfGkYN4+w89OZ5JtD/fmBg97MZbDarZvexFayWLWMi+w6rYX/LtrAm1sZ+yTaxd9mv2Fn2a24me49L5maxj7n7uQc5jsNvnPT43iQ3h1vFubgszsNt4gq4Fm47V8nt5F7jXuD+ifsF96LmB5ofcDEhIkS5NcJ6YSPXILQI3+HWCVuFrdx64VXhe9wG4XXh77kmoVPo4r4tHBF+zG0W3hLe4tqEt4WfcVvpe8ztQr/wS+5VYVAY4r4nXBF+w+0Wfiv8ltsr/E74iPtv+BYdt1/7gPYB7h+0v9ROcO06rW4ud073uO5x7rruCd087ne6L+hKud/jFx7cx7qv6Cp4QbdEZ+F1umW6Gt6g+4ZO5LN0Tl2Iz9FFdY38U7pv67bwX9C16XbzX9K9rjvAG/HLCX65rlP3L/xXdb26Xj6o69MN8CHdRd1F/m90Q7ohfp3ufd0w/018H4vfoPtQd53fpBvXTfAtSSxpFr81KTXpQf71pDlJj/J/n5SX9Hm+K+nLSTJ/IimctI0fSXol6RVNctKrSbs1s5LeSOrUPID/r6pmTtKPko5qspK6k36qycb3gTR5Se8mDWgWJF1IuqIpSfpN0keaxfo8/SFNtf7DGY9ofmX4veH3An4vJ7MW4MksG782XtSlQg8oZHlybeUN2V1RufR8xXzZL0fktZVD8np5U4Vc1SYfkY/JJyu65TNyr3xOviAPyVfMM8258mZzTN622LjYLe+U98j75Q65y5y7uAK0SgAdHyMd/x3juI+5jxkPGp3CNHDuYXoTlfFv8G8wjv8B/wM418X/kGn4N/k3mZbeRNXxv+B/wfT0JdgM/pf8OTaT3kFNprdPZ/G/4n/FDPTe6f38b/nfgnXgm6WpGk7DTf6vwVqNjqXTl2MZmnRNOvuMJkOTwTLpTdGHNPmafPYwfRWWrSnTlLEc+gbsEc1CzZdZLn0VM5fe2XgM+p/MpdLMIWfeU2yd95T3rLfPe9570XvJe9U76r3uvSkz73VZJyfLqXIGIVueKxd4R+X5crFcJi+SK2WrXC2vkm2yU5blkFwvN8pNcqvcJu+Qd8v7CO1yp3xY7pZPyKflHrlfHkgk3wp5UL4sD8tjkzQu3/LxPn0CGXxpvkxfDtTm3UE1vjxoW+gr8pXIt+LkK/dV+IzAkap8tfKYzw1t/b5aX8S31rfet8m3GWTm+bb5dvr2+PbD+LkZsuo18Jv12TQnGUAalgUksDz2ONOyQqAk9jkgPSsFmsHKgGaycqD7WAVbTG+Xm8Dr4HeX97O/ZqtYClsNlAp+R2QPMDdQGguzCH1xuZa+tXyZ3ij/FssEf7SVPcReBXqYfR8om/13doB9lr0B9AjrBMplPwZ6lP0EaC57E+gx9s/sFPTvLFA+/W/YT7AB9q+sgP0voEL2a6Cn2PtA89g19iH0/Qb7D/Y0mwB6huO5JLaAmwm+r5TeH/8i+L4UVkbvj5dz2dwj7FnuUe5R9hX63rMCvGEVfdG5ii3hvs7Z2HNcLVfLTPQuuZm+7rRwMiczK1fH1bFlXJSLsSrum9xGthx85ya2Erznt9lfc9/hNrMXuTaujX2dvu5cDZ70KHuJ6+a6mZ07wf2Uidxp7mfMyf2c+zlzc//C9TAP6a8XvEA+k/UF+gJWR2/nBfRP64tYkN7IC+tL9aUsoi/Xl7MofUkUo/fv1uht+m+wBr1db2d/A2t7hY2T7hfjL0tIhwHdgBOA04AeFf0qBgCD7GtSt3RCOi31SP3SgDQoXZaGpTFpHPgtL+/VAxm8ad5Mb443z1voLfKWeMu9FV6jt8q7wlvjrfW6vX5vxLvWu967ybvZu82707vHux+ow9vlPeI95j3pPePt9Z7zXvAOea94R7zXvDe8E3KLLMgz5RQ5Xc6Sc+V8eZ68QC6VFwItkc3ycnkl0GpZlCU5IMfkdfJGoC3ydnkX/g+i2lqtB4Lg1w2r6fcVFv+X6bcF6H7S8hTS8tmk5Q+QlqeRlj9IWp5OWp5BWp5JWv4QaXkWaXk2aflnSctzSMtzScsfJS2fS1r+GGl5Hmn546TlT7AeoALS9SdJ1wtJ1+eRrn+OdH0+6frTpOvPkK5/HnSdZ8Wk318g/f4r7mEuG/QeNbuMNPtLpNnl9H3Es6TNC0mbv0zavIi0+Sugzd8EG3iZexlsAL+SeI60uZK02cj9Hfd3YA+o02b6PsJC2mwlba7iekCPl3O9XC/7qv4F/QusWr9Kv4q9oPfoPfi9dsr6lFZYp2SY+/sYF1wNelcEKAGUAyrUOiOgCrACUIN1wmxpQbDY2//HQW0GQuek0mCZtDC4yDt4J7BOWhKs9F4GDIcuICRz0Ood++PANtLyYLW0MrjKO34b+Le0Omjz3graZD40JIlBp6z/46A2htAVSQrKclpQlgLBECEWrJczATkhP5XzQiNyYeiatC7YKG0MNslFt0F/l4RuSC3BVrn8U1ARmpCNYUHaEmwjbA/ukHYFd8tVCrCMY5NX3AaNdW9wn1wT3IdHwoFgu1z76cB20sFgp3QoeFh23wnpaLA7LjcR0vHgCdl/G9Kp4Ol7QWB1bJd0Ntgj9QX7p8X54AAiIMb2IqSLwcF7wqXgZelqcPgujAbHEAEpvEW6Hhy/FwQCsQPSzeAthJeFeIIupEcEYrGDeKzzRzu8tlCtNzlk8KaG0qYisC52yJsRyvw0BDbGjpKM7FAOYW4oz1sQKrwD80NFd6E4VHIHykLl94xFoQpvZch4F6yhKm91aMVdWBWquQM47nuAHAnP9DpDbq8c8k8LOCevDafI68Pp1C4UitwT6kNrvY2h9XcB5W0CbA5neZtCm+4F8rZwrrc1tHkSbaFtk8DzOwF7wvlU3h+eJ3eEF3h3hHZSf6dA7gqXUnl3aM+nQT4SXigfCy+5Q8a+0P470B7quAt47cmw2dsZ6pLPhJfTsTe8crr+fCIOh454u0PH7sKJ0Env6dCZu9AT6k2EfC68Ou7bE31x3FdO+rgLYXHSBw2FpUQ/MqkniesaX5f4HF0JBybndiQcS+wT+ZIW8Clg+4Etig8IbFfsl+xqVyiT4gboe2Av4EDseFyfAwfhCPfB8/K18Dr5RnijPBFu8QnhLRhffDPD27Eex+ZLCe/ypYf3on/1ZYUPoJ/05YYP+vLDhzAG+OaFj6JvpzGDvvsWhI/H/bOvNHzKtzB8FsftWxLuw7nwmcPn0XeiTMLy8EXfyvAl3+rwVZ8YHvVJ4eu+QPimLxZhOL8Ug3AuYQ596yBOqvHMtxHijzrPvhaQsyWiQxl0bnsk2bcrkopxZzLWJqzRpEyEGlPisQD7hLHRtzeSQX07EMmOrzO1R98Pa09xGWIeje1gZC7W+Q5BDC9VgPEa5/cOmJW4jPGK4jHcJx6L8UgA/aGxTYmxdC+A72iwEYExNh5X4/AdD7YhJmMkxkw1NibGyjtipBon4/CdgjgIa0yxD+Kh72ywG0F6i3HuuIJJnwXw9UUK6Hg+Mt93MVJM9eA/fJciZb6rkUW+0Uil73rESvVowxhL0G7BjtCefDcj1X4WWYW+yK+L2Mgu4nag+kXSLZCDfs6fDL5JtRFaL/BbeH3cB95lW1PsatK/xPsPMtBv+lMjTlxzf0ZEnrwe24O9+bMjIf/cSD32218QafTPjzSRD8fxwBj8xZFWf1mkja77NP+j9su/SPXjcRvflNBG7TONdYo/nhwP+uE4Pulen+BP/ZXq0RrqwjFNYqqfTPSV6B/jPjLRJ0JbkoNt8BzMgb86bA4cip0KHI2dRWBug+tNec3xWB/Vgc/y90cNgVOx8/H8JXA2dtHfFDlBfgzyjkBf7BLlFODT/J2RYX9jpDueEwTOx66ST8P4j3kD+rqLsVGM0YFLseuBq7Gb/hORW4HRNSxwfY0ucHNNcpCtSQ3q1mQEk9dkU06m+ku6FnMzNW+inCeeo6AsVQaeC6aumYv+Evs1mdvF87Drt30wIZ7DqLkHysJ8LJixpgDznWD2mvnx66k9jIf+hvkiO4GxBeeuKaY6zBvjUPPEOzA1F1RzvzugzuvUvG4SmIvFMTWvi+do0+RmwQIFn5qbYe6VmH9hzhXPuxJyLOwrXYtt1Dm5y7bA/vyrIjvusitbZHc8x/I7I/v8cqQdfVG8nT8U6US99tdHDpM+xf0AtkGbA/2jY2vktL8t0kPlHZF+/+7IACLR3vz7IoPoI/ztkcukn4cjY3flMQB/d2ScAPqIIDtEv3U6ytOxJ6qP2yDahH8gmuYfjGZO2h/6oMvRHPI1w9E8/1i00D8eLcLYEweOF5+xyP5gzP5b0ZI6PlpOssF/1OmjFTROtX2dIWqsS4tW1WVGV9TlRGvQF9XlRWvrCqPuuqKov64kGsH4RzEQ/RPkBHXl0bV1FdH16I/rjNFN9MwCsbCuKrq5bkV0W11NdCfOV11tdE+dO7ofnxPqItEunKe6tdEj2L5uffRY3aboybrN0TOYA6L/j/vmum3R3rqd0XMEkIdxBnW7bk/0As573f7oUF1H9ArqWV1XdIR8GKxj3ZHoNTp3LHqDZJyMTqAvrzsTE+p6YzPrzsVS6i7E0uuGYll1V2K5dSOx/LprsXk4v3U3YgvIj+H4J2KleAwIsYWoD4GZsSWBlJg5kB5bHsiKrZzUH8jBMf8I5MZWB/JjYmBeTKJ61ecGFsQCgdJYjNYP7CSwMLYusCS2MWCOtUzqavw5IB6joBxYHtuCbQIrY9uxjvGMM2wytDH2l39B+TP6F5QRdu32vwOI40x2ZDpyHHmOQkeRo8RRXi04KhxGRxXwFY4acVwhRw7CUetwi7cUcvgdEcdax3rHJsdmxzbHTscex35Hh6OreovjiONY9XHHSccZR6/DoNI2wjnHBUeaSkOOK44RxzXHDceEU3DOdKY4051ZzlxnvnOec4Gz1LnQucTBxwlamJ3LnSudqx16hZyiU3IGoF2Meog9wpZ4Du8Hd8B9/lkdoNtL/0v2QS1gG8uAZtM+aCrtgz5A+6AP0j5oOnMzic1hMlAm7YY+RLuhD9Nu6GdpNzSHdkMfod3QR2k3dC7thj5Gu6GP025oPu2GPkG7oQW0G/ok7YYWgs31sHmsF+hp2g0tot3QZ2g39PO0G1rM3me/YV9gHwCV0p7oF2lP9Eu0J/os7YkupD3RL9Oe6Fe4bC6bVdCe6GLaE11Ce6LP0Z5oJe2JLqU9USPtiZpoT9TMfZN7mVm5DdwG9jztiS6nPdGv0p7oC7QbugIs/Ufsa9yPuR+zVbQn+iLtiX6d9kRfElqF7zAb/dJgrXBU+DETwa5PM6dwVfgNc4P9jsNccqyeNd7WVTuM2H7eftF+yX7VPgp03X4TJl4nJoupYoaYTeQUZTEk1ouNQE1iq9gm7hB3i/vEdrGTaK5YIM4Xi8UyokXEK0Ur8GpxlWhDQr3hnwS9eUrVm1S6P2oMD2v0OGgP6ooA818E2oO6oiNdSQJNWQw6hHvmM0A7VoEOoX7cR/qRTPvks2BcXtAk1IYU0IWtoE+oB6mgBQdAn1AD0tgPgR4kDUgnDZgD638K9Bb3wz8Da/6voGG46g/RqmfRHvjDsPLDLJvWOIdLgTV+hFY3l9b1UVrRudxLnI09Riv6OKxogOVzMVjRAtrlfpLbDKtYSKv4FK3iPNrT/hz3I+4om884fbG+LGE9CoTZ9oKpJK4V19vn24vjJObZy1RaNJXETfZKu1UhcbO92l4tboOaKSTuFPfYVwHZgJxI4n46yvZQnMQOe/3dJHaRhHp7o0pNColH7K32VvEY8La7STxp32HfPUn7sK1K7Sp1TiVPp+ew/bC9O07OMfsJlU5PJU+3vSd+L88Jez/QPqiZQo4F9nH7ABDebxDJnS8a4HiZriByjN4t3X7avYQknI7PrH1YIc9p+5h9zNMOfPxu8vTA+G5NklXkJ0mv0DQzdUbsFQ1i2iSdEzOJLtyeiTiJQ2KOmBcnWvErYuEUGgFcE4uISoBuqPUTDgF4+eSIrPZGx0yx4m5ypIhGR7pYJa5AcmSJNQo5ckU/1NSKtY58sTZBziQ55tmHRfck+cVInJTZtw/CioB+O0pJdysdCx1LUMccZpwJx3LUD8dKKK2m0RY6RIdEPZJorIok1JR+WqUez4BnkLThMs3+MM30iCMAtjMf5q/YXuaI2dsd62CWDY6N0L8WxxbQZZtjO+h7vWOXyDv2gi631bY4DoglcN8toCdN0Pag45DjqP2W47jjlOMs9Bj1v83RR6O0wYqdsTc5zkMLq+Oi4xLIQqulEVFLxVZwdZvs1Y6r0P9RGPN1qG+FdsVgda2Om1Ca71jtZPYyp86Z7Ex1ZjiznXPJlqsVchY456O9OoudZUCLnJVgrbJisU6rs5ruBndyrrI3OW1ok06QDC1lZ8hZ72x0Ntl3OFtV+0MLbHe2OWXQNQPpWyac3SEaxRLnbjHTuc/Z7uwUa5yHYX1htRxbnN3OE87TMHOFYgX0aYfY6+xx9kPrAaBBscjZTRqIo6S1wnZAoDE4S87LgGGxAmy4zTkO9RHnLRfvHHTpXXBvV5or05XjynMVwlxLriLUd1eJq9xV4TK6qlDHYWZpzV0rHPmgbSWuGqfsqgVyu/xiORKci7iKXGthBEZxBZxZL9a4NqGeAq91bXZtc+107XHOde23D7s6RLerC/TRj2NzHXEdg3vWgoZGcHyeMfthz7hbBM9wwnML1mcQxlMB+tIm8ZIevEC7ZABPcdq5wzUipdkz7N21Z11VUqaUg3YNOgOzJeVJhVKRs10qkcpBQ9FzjIM3w9lp93R7upUW9jZ3n1QBstDfkQZTS8XLgAaDrH7JaN8hVdk7pRX20yIP7bqhP2NSDZQOu2qkWvsJR6mryF0quSW/FCEvqHoyaa2HPKurxNPv6ZfWS5vAz11WfJ20WdpGd4M7STvtw9Ie9GbAx6Q90n6pQ+pyp0vg0V01iuci36X3DEvHpM1ijXQSe+I6CeuEulPjOuPqRf1RyLEF+n3adQ59kusCrPGQWAWrcwX0qhD8QaFrBOZ6v+uaWO664ZqwW92CG/yO/bI7xZ1ee7b2rDsLVnA/6M2Yvd6d6853z3MvcJe6F4q1zkGcd/thscS9xG22j7mXu1c6L7tXg/W0goORRD/cfxDi4xX3QrBgA/isWjgTcMfc68RM90Z3i3uLe7u9UdS7d7n3ug/Y+90H3YfcR0WD+zhINbhPuc/aB0DyoLsP+mSAvpx3X3Rfcl91j7qvQx97QLbePgYtb3qYR2dv9SSDt0kFW7KC3mTANYWgKyWebNDfEc9ce6c73zXiGnFscQ3ZB539ngLPfM9cmAfeU+wp8yxy9ngqPVZPtWeVx+ZxeipFIxxl57gn5KmH1o3uLa5eT5OnVYx42jw7PLs9+9xbPO0OkbKpp/7yhPln9ITpZgF6qyEd/zcZWzvjvsGzNNt+oA6gLqAjQMdsx1YB2U7aTr408NKA7QxQr62X6s4BXQDCuiGgK0Bw3crRlaO2EaBrNnyG5Q1WwzK4Rwo90TB6ouHpWUZDOa9AzzJaeorRUc6bRE8xenqKmUFPLvfRk0sy5bwGynnvp5w3hZ5ZZtPTygOMSxFT/DQmeu/QtoBxNjMcS+G4XJhdecC25F5gNMLxIODQJ+CoAmONgsrj94hTgLPToE+BMQLH8/cG43o4XlRxScVVBUsHlaNxJ2APlEcB1++GsQOONz8dxiOAYyCXqdABku8EjW0KlqZOQcafgGzA3GlQMI1cxPwpKL43WGHel5YBFn0CKhVYzytYar1HVANWTQObAius21LnvcEKa7tUVhFSUa/AelU5Wobg2A9oBDTdDSvowNLWT4f1uiqjTcUOwO4p2DcN2qeg80/AYUD3NDgBOD0Neqag/95gvALHARvZx7SAc8YRwDW13eV7xDBgbBoMqDIn4Dh+bzAJcLx1G0b+NibbpKjHdEAWnNPfvlciTLnq/Q2fDlM+YN6d1xvTpiBzGuC1C+CYA8dS9bhw+v58Eox5gMJpUAQomQbld8K0JMF/J/rbuL9U/ZjJbJv0L6bltjv9R1xPEtdVne/JOVqZMLer7+zTpE9J9AFxG1ZtC2NGXOeXZUzR6XHlvEkESICA4iMwvpjWKfU4JtNGQIviX224XuAnTdsBu5QYYNqr+vebir6bYE7i/tkEMc10SBmv6ag6DyAT/SXKJKBcWE8T+EUTzJ0J+mBCuVfV+VXnE6+lOBmPYZcS5hnkmJkiA8+ZIV6Yk9V+TV2nKWs0GVPi69SixEZzqtI3c0bC9TeVsdDfh9TYB3+bs9W6gwk4Og2mxuW+aXA+Ib4mxNhJjCZgSnydjJf/mTiZbbszFhbYbsfAhHg36bMA5kXqEeKW2araGPgPM8QkM8QgM8Qfs1OtBxvG+EF2u0SxJzPEGXNI8UXmetUuVDuI+0XULZSDfo78U9xGWhS/hddP+sCptjXFruL+ZdK2WtT+N6lr3nr7emoP9maG2GTeofTbDDHJjDFoUPVJOAaIQeZO9bpP80FT/fh0beJ9nsYfT57T38Yn+rpP86c5d+IuP5noK4sSfGSCP6S2OWqbEmUO0EcvA/1ZVqAAcxtcb8xpls1X60BXLBVQRj+m5i/LIDcyj6t+DNZ0GepWk+LPLDj3OF9qTrCsUvVlGP93qH4O9Q9i9DKQtwzkWaC/y0BvloG8ZaBny1Am6NiyRtV/xv1lp5qbxfOm0G0/SrJUGdTHJsVfUr+m+uEpPngyh4n7YRwnysJzoFPL2hKub1XHU6zMF+VcMLZlO9S6sgRUToOpuaBtGqjzOjWvm0RjAqbmdfEc7T+Tmx223Zl/nbDdzrsScyybem13wpxMtS2wP3OP7S67MvfbJnMsM9r1oOKLJv3VZUWvzcOqPsXrsc24qn94BL9iUe3OAjZmMShItDdLmuIjLJmKflrypsljAJZCFUUKyA+i/BL1WH7bBtEmLBDrLFUJ9gftLCsUe7NAjLbUAtxK7ImD/FGHMk84ZosfEFFlwzgsa9Vxqu0t8Exn2QTYDNhmI19k2QmAZzjLfkCHEv8Q5CchJ7B0AY4o/thyTNFTjIWWk4AzgF51vs4BLijPCZYryjxZRpT2FogdlhuACSUHRP8f981WiAHWmQpQHsUZ0G1rijLvVshBrVmKnllzlXnEdbTmq+fmqTIWKL7cCjmiFfJDK/oeyMeskIdZIa+yQj5lFZX5tUqqH4PxWwPqMabogxVyISvkQFaIEdYtt/UHfTfmA1bIhayQC1n3qvWqz7VCPmA9qMhHO7HCHFkhB7AeT9DV+HNAPEZB2XpKaWM9q9Th2xizTs56+y9vY/w57ZUJBcIp/BdV/iz7R8aScgB5gEJAEaAEUJ5wrAAYAVWAFYAaQC3ADfADIoC1gPWATYDNgG2AnYA9gP2ADhVdgCOAY4CTgDOAXsA5wAXAEOCKes+RTzheA9xQge0nGNMLSr1+JiBF7duIeoQx6NMBWYBcpX7ymA+Yp/RVv+D2mPWlgIWAJQCzIke/XLmffiVgNUBU6yVAABBT5OrXATYCWgBbANsBuwB7AQcAB9XjoYRjvP1RwHH1uFe97njC+VOAs4A+wHnARcCl20ecH/1VwOifcIzPxXVlHv9U0BokokoByqf1GlLbXp2Cm8p/Ox8/xq+Py52hAySr6w31M1JvH2dkALLZP5oqTVZTtWmVyWZyEmRTyFRvajQ1mVpNbaYdpt2mfaZ2U6fpsKnbdMJ02tRj6gcaMA2aLpuGTWOmcdMtM2/Wmw3mNHMmIcecR38XAhWZSwDl5gqz0VxlXmFqM9eY2s21ZrfZT4iY15rXmzeZN5u3mXea95j3mzvMXfD3EfMx80nzGXOv+Zz5gnnIfMU8Yr5mvmGesAiWmZYUS7oly5JrybfMsyywlFoWWpZYzHge6pdbVlpWW0SLZAlYYpZ1lo2EFssWy/Zpscuy13LAJFsOqnQIaLryUaDjllOWs1DuU+m85SLhEtBVoFHLdctNK7PqCMnWVIgJn5n2FxeY+osLevrFhZn0iwvJ9IsLBvrFhRT6xYVU+sWFNPrFhXT6xYU59FsLnzHkGJ5mDxmeMVSwpwx2g5s9a5ANQbbYEDE0MJOh0fAye97QZGhmXzVsNfyEvWB403CcrTecMXzANtKvLxz4/7hnHJfKBeh9lW783+Rzi1SAZ8ktV1GhwphQRoDV5K5Qy9iuRi3XqnCrAK+bC143F7xuLnjd3E1q281qe6zblvD3TvW4R8X+hHt2qH93sSeNZ4H6jOeNF42XgK4Sv2QcBbpuvGliJp0pWSHjWVOqKcOUbZoLtQVQn22abyo2XjKVmRaBTZJVGq+DXVpNNlir++mXNhj9xgZPv7GhMRQZiphgWGxYwrSGpQYLS6Lf20g2vGSohXXwGLzsYUPIEGY5hrWGb7Jcw0bDt1ie4ZjhGMs3vGV4iz1hGDGMsIL/x9K5iReFrwBfBdrBTdxH5ZlUfprKT1P5GaES+AJthOprqf5VKm8GXqT9IZUrqaxc+zSVq+jazwGfR/ULBD/JwWuLSH6N8Axy7Yv47pN2LZTThEXItVHgh6jN63jfP1D5D29SHzZSvZfKz1D5GSovUHqr8rXEg9QGZP7hV8KTwIfUET1JZ1+kXtFIhb+icXmo524sawaorKezjK76H1Tjo2tNVHM/lZ+la9eQtPupJ88S11KbYmrjBD6fyvOpXCSUUr1E5WKSQPXEn6GzRXT2C8IXkWu91JNSaonlZzTXqI0yD5tJ2jGShmvxOaGd6hVeQnw5tRFJ5hGSCbPBP4935J/S2oA3a8G6+RiVnyU+oA0Bb8Q2HE/8FWpP/eQZco2TWr6itQM/QDJnYw33Hpa5D+nsVmq/mNp/l8ppJO1D4kPU/qbwL1DPC28DXy6cw7tgmfst1TiF94CXYRs2jpwzEv8P4m8i12io5VKS8wK2535NEtqp/AM6+xy1/5jaF1D5CvGTxP+J2n8g1EFLs/afoXwD9ZbXad+C8gTWc7Xas8AvCaAJfCa2YR9oNwD/HXLuiloDXFNEcjKJZ9G1DuJbic8RPqaz34DyL5DzF6l8jHgf8VeEGlwj3QfEjxDvIN5CfBR5Ugbca4GygtSyWYe/oVJL5WeJz1J5B/EW4njtHGp5is52Uc0A1TRSzV5l3bEM/AjxDuItxEeJY/ul1HIdXcUUrv0eagWVX6GeH6ByN/EDak0H8Rbio8QrYCwntC2kRW7kdPf3iH9I125V+RHiHcRbiKOErTQb38U2mp3Ev0t9/pD4EMkZwj5zH2h7gF8n/oH2NeIB4i8RJ03QjoCEObReN6jlEPFhlW8gHTiJukE1EyRhgiRMkIQJ0opLdPYS1VxSa7qBa2gsj2hPkc70EA8Qf4n4O8hJE4YUHcMyaBpKe4fKH0BOj32AGr5U5TAW/meopXwW1WRRTRZZdxZKBv428W7SzIMwxrWKfpLkNuJb1WvRLsKk83Pwf+KGe71GPED8JeJvEx8hjjIv0rUXaTb6SFoflV+h8usqx9k7S/18PgmlzVK4omlUPqBw7U9oZQO0jnj2Qyp/oPsSzrDCsVeMauCZFnkm1ffRyvZRzSGykTziOeSFnib/1qzLB/4y1b9Pvug6lbdhBOH+nXzaLMUfYktuptYF/AHyZk3E59BsdFKbQrKFd6n8PPF21QdCfOFIPp+EXPcOrr7uOzgbWvKlgg3nRHcUy7pCLGuukm63k54Ukfb20FVHtYfwWqGTeoVnJcWf69BzPokcbPMc2dQ5siO0jseovJXO/rs6xjD1x0nXvkHt36B5Jg+jvYrzgxx8NXJlvZ7SQXzkY9R+FpVPUftG1Xt0kB9owehANuik+leIzyb+GN3lPeIfJ1XiaiYdpPvi2cW4ymC5WE5TOcr8vOqT90A5g3TyHarJIX5B9xCuL/nb10mfv0Z++zB6UW0/6WQfttTmk+7psQbWDnU4Df0516NYMTwrQ0SgdenHGQY/0E061k1WqfC3yV66ib9NEQR9dSZeC/P5Fl21gSxoA+kh3iWKvdIsxbOapYpXESBX4R4mG19EVx3VfUT+AduXYG9Bk7HmClo6aPi7GFmo50Wq/9lALfEu+4lvJX5S9ziWdX9LlrsMowxZ7kU6e0zlioViuVr3JJ0doZoR6j/OcLHuHfR11NvXMBpy/5NiYib19g9U/0Oa84epnENjuYSZEl8loPxewQD8KmaP/GeQw3ptIK+Cq7aLxrgHbU3zNMXBJ5BrcgSo4X9Okr9PLT8kyf9G5X+j8nMkvwdnHjhKNlKf/chZF5WHiX9NO5NhXoHyv0grVUASepX4i3kU5AnfIO+HGt5K2cuwINEoUN8epbO7qOfv0L3eJGmZOFLhlzgbWpoT4SNa3xjGd006StO8i2Xhi1ReQuMdpVF8RL7iI7LETOoneXv+GPZQs4DGPkPtLfYkl8qFAuSu3M9o1D8SIBvkFlLfztC1pO18qSCjjdNV1ZgD89Wa/w18u7AYJJfTOh4WRNRP/vtQPkfS3lc5Snud5HyeZBYJAvBfIwete5hhVgYzoEmiefgHuipEvI104KqAs9dJEvKJv0pyrFSO0thfo3leRGOU6Kr3iV8k7sEZgywLR7ERs1Yoz0CtoBjkI2m11M9qkqPT7kAPoGojju4n1J+burnItR8Sf5f4m1SfS9yIPkHJObElP594qfY9iiNY/r/snXucjtX68Ne91n3fMxgraYhxaEzOx3FISE4NMw4JUZKUYxKanMlGUmFLlEpCkkpCJco5iSEJSURl22WrrUJMsmWeedf1vZ/9eTO/3+fd7ffd/72/j8/n+1zPta51rbWuda113+t+nnm0ie5C8fMp3IGfHfjZgZ8vsR+A/QDR6Gw0TdF0jO5aRVbnpSeOn8NN6NOQxb5odGdLK5sich/VFj9tpa7uhtwtksWP4yb0abAcmrLkD/cb+PwWb7lwKVwBl/tyBczEZyY+M/GZic9MfGYSpUzxbKqLpalOBLbiYSvyGuQ1MgoX1YX0X/hONF6RXd8W4mchtc7hQTSN6Oevce5iZUkfugR1WK0yOw/7cre5JX46kFa2+wdZs5wOxFJFd/LHubcvzSkgC36Et9L4Pw8PwuXU7Q7bUHct+u/gbt9laZgm4wqXCf1BYuPvCda5lU5b4bBArlM9iVU2EfgH9laiGi5jXdelt5+SJ9/CWfFzyiFmJ4ecPMSsHSIy5KesMheByjJTwdWO8zkTaSzLY/kp8hRabxrlG3PxumiMYaYM+rbYfwt/hUthDnfyS8MTtCKafJkXN78in4iTuUZeG2WOaFwmtGMG2zHj7hytppjP3LmyY1BEGLpza95eWYl5ewM3y+YF7pR2SUz8xnLd8fuLbN6GT6NfKvdj/ovsiti7e2O5L7qGuu25L7ofyw/kvOnvkF3acH403eS87Bej9B1qvSJMKIO+JB4uweXY30OeTJC5MGsktuYociasL/RTZY78NHJjKvbvk1GHhcESbOqTFSliaaYxsz8hD6K0GqWlyJYMPERn1eUwi7aac1fwIlfANhIx8y1XkKnsjdu4auTI/YlZxB3pTK5Bi7k/HI/mUe5qTuFnMzwAP4eH8XMc7oGjuTYd5jq7Vhh8gDwBrmN3Pc816HG5f/NrcBd3OC6/C5fBqfCUlMrJKzhJ/NtimQQbh3c4RicyTohmXZzL4FQoHt7Gcgy11ojGUTSdRBP0Iit6cq87GraH2dwZDuP+sw1nUu5g/crkzwbawtJMlb3UR+Moo/gez5XifBcug1Oh8xZUkzNp+D45syMo6WoVwdsi2BdyPvWTGftY5HfjfBcug1MplXGNlVj5m0ROKBc+D7uLf2r5cUp8OCOY5RIH05y7vvFxLoDZ8G5ILsmdW1iYeb8LyzayNwaVgh1OPh184Pg8+oNxZsO74XZYR/KN0hw0OWimyb2ueVNWqPcn7qXLwxvhaO4tUzkHNebetSZ3xTPJqNFk7Ey5D9Rt8PwO8lhOr6vp29fovxY/fnv6f1Q0fpk4F8BseDeU9VVFeuVfI2fY8LUo52VF6ON4KwIXcYcwiXWUzP3Dg+T/fEoPx7kAZsO74XZsXDz9CtJK8IE8V3QUm3XUWoecTATOE6UjwTLWQnkpjciJ9YScWP3vRRNskp747yKfRvbJEx/78cEPzEJEOb3uldOri4ZkxR5/En2TjFXI6+j5OkqjXbQZLBIkOyqZr6B02NnJi0UfVCCTv4Zj43up7Dwb2UtnYzMd+9dZcT+xjoqwozZiB56HvEF2YJdXrlawhXnJwSenV/MUnofgrQbyu3L+dSdcKc3GcqMwcZNkeKLitPUcnnlmkhDt9h9zupnKCj3JClrD6rgOcjo2K/DwGt6U/6irtRE/70nffJ5T+ZyI3VzINbQ/Z+HhIjsPp+AB1vUpeIDVegoeoLfvOPkJWlxLlC7JPYB5gd1pB/Tp2wY5I/svwxFCw5MTsyt8TK53rOLZyGuwf5G6T7DSp4omHCi7QXg/+g+wPwa7wUXheWFCD7nSYfOKZE5CGeSSsD7eLmE/hz4XlquDX1yeU/l1ghTyR2QtfQt+lNn3i7N2xkfnTfJhebBT8kT0/rfxM7U8sVzGGacx6zpTrhEJWczd58zUDSKHhYOirvQC16x1ciJ22St7QoaUJmRxZVkkq8ntV+vhdval9VCuoe14jlQD/VH0R9GfRn8c/WH0PfH2Na1EJ6/xXBkPwHXSbnBMRhTyPNas4sS9mGvcXLHXH8r52u1ydxPhX+mz7EuN5awdFmXVn2J1bxa6SO5mn6lDT4R7KC3CfVERufNx+2Eea2EBO4aUToBT47uH1DrEvvG+nLudzTz08+g/+1U40cnv0ufWfhnHl4R+KvF/i5F+yeyMwub2uKVoynMO+kjG6F8pZ2TDU2UTndq+4NS2kz35IeJQlnmvxbnsebKlVOD2ojCRWr9yh/CmnMeDQb47Wfgz2WOHUncodWcgL5W29PW02Id5eZFTfz9G9Dgn3AOsCB/NE3Iq92vQzzuxP0OL9CqYgjxezubmAeTIZggeGsK75H7J3TfKqlznXy3XBXr4HXkenaZbkgmZjL2O2ejG1UP8hCPgOKG/yF/Bzikr4iaRgzHBGHol8eyKTfR5xyZ2s0BKzXC5igUefooR/3X08BU5d5sjyKfltG7qImfKad28wViukJ4ErCD/dr+00yyk/5PMaceJxmWCf1I+5Qlf5p6wt5zW3eikP2XkzG6m43N4nBLDovB2OacH6+Adco4wv8nYw5JEoB1n8G+odY+c000J5M2U5tKfv9PDVeh/5rOMVIlMWJXWm8G7Ge9g2DB+bylX1dLU2i0nd/2ZnNzN48SnNM8Pj9HD3rAdszONeWwvs+ay11GvQFOWfs7jFDMbNo9kTiizWWuzOenMllOVK3UnkaAKd9RbsHwErgkeZT8U2cL2EfHQHg/t8ZCJ5SnOejVE49dAcwjNPN/NuEddXRE+xnn5Vs7Lt3IKa8z57nk5K7lMcPZ6IJaHabEk95+18FZL6voZyA9HRPOweHPchD4NluPK7iITfMroBvnuVGjm47Mx/qPRNYMPydnT9Z9R4LMGPmsw0lOM9JTEyr9dPIcZwX74iGQRHt6KSHz6IGcRh+ZhB2IlvIXz+xE5v7tRdJBnX/6ntNuBFfQlHs7hrYNcraRXbucRvuBXcuzlT3b6MeyonJfd+VpKp8GyaJr5U5yc7UvfaqFhv/XLMRc/wZ+FZpcw2CP0a8GHpW5Qm1ZK4LMtbAKX4G1qFCs8nIZVifBYOER2vIQdEoHEjsTzAue++3lKP0TkhJCrXm8pDaoQ4V1YZiD3Fzlhh3hL7Ch3JkGM82BjxhXlRiNmOYN5mY+cjIem2LwhzwfMPRJ/P4VZeIvcqCBXMXNCRmdWIBdDnoDNUViLWmkwmdksKXWDxTLjwRL09bF8jVmeJrL+CU3jsCGcI/mGZWmZTZcnj7IHCvfhczlyJfqcTAwfEr2zvEBvL7BC+aQ+/3XlKZP/EfIK+Swb1st/DbkanCqfksdLX4eLsR+HHLEUnI0+qrsSeSXelsOv0XyN/AU2Tq8758sT0VrwUTgKNodfwAlCTwtVLpp6UAnNAORn4Kvwyrgsnxocou45NLNha2o9iZxM6TF4EQ2t6C5oTiNH/pvS+nl4mNJ/wE14M9i0hd3QfxuXpQ9L0axAk4mcT63qyCfgVrgG/oBlB+QLyCFyDJaC38Sqy50h/cFe/SIaE0WmLEwRjceovdvhXvRfIW+E+7CJotc51tJ5aBDNhci6OVwIF0WzgFwPKvgMfDUmd6dboviLxnsTnqP0EzzPjUaHfHUUeWxi2FSIxoLmGL06gfxpfCwtGVeiqzuOuuNFo4iPNxHLerGOjGIePZ9Hb+fRN+FsNOfgD2gqCFUkl4Up8DgtVoapsC78jraiDHwK+W8wJdbKsSvyVczslCgnRa9XIteMyen7c+Qm6MkKnSAMybRwtNBfh4c8iUA4RORgF3P9ahSZ/Bfk00bs/xzlBt6eog+/YvMPYtVZVqVbU6XIf+GsaJbzzsqKY6Sj4tQw1fFq2BxOoHQC3iaIxsVT9G3Q14MqzlS5LiA/E6dYdiTah+KRT2UWFkKRW4vePElpLrWuo4dRhucyIuLvHYlmhJG+GOUzcj9sVhOl/dHuIbHyDxCxaP0mI5clMlux3xprIU+lkEfhZyTyAqFhFZu2ZOAF4jabUmbTK4f+B4mhd4k+h0QvhRElEqWY0OVVJMsYiZX3ZxjlYe84U6m7ED9ivxef+yl9HRJPdYZRn4QL4Cf5VznmMcbCaN5GLoecyqx1Qt5Dz7+ntLTIbsdY6jQtKB0O51G6kAiQ7aYucrTSUyRiuhr6aEV8BF/Ac3889MfzwXiURI52tt2s622s1u+YBXYVzyfyN+An2gn3wL/n15dIIu+K9kAsp2N5bbQH0sqn6Fl9/iTWzg7kX/MzXT+j68hidpvPJVb+Dcht0J/Cz6/I7IS6EKwB06I1i80O+F58d7rOkSuFtxOb1dGKhuwAeg5RaobNARjtG+St5rrgourOFIa1770Gh8For6gKn4Mj0Y9AbgUHkYFj0b8evxZIPk+OyxKB6NrRE3v2EN0nuqYwmyHxLwVnw71wI2Q/995mvvKRN8CL1N0XzRcykfROIw+AHYnSeeSilG5Cbgu7xc5LD9F/i89ZcAVcHl+/UVuS+TvI/POsiG4wE/1W5EbYP4w3rjvedlqPkRtcGT12clMay01kC7J3nt34IPJy9N2Ro32V2Q+XkVHF4CPsMNyfhOXxFu1I3ejtmvz58hkTHvJjf2a8jl4OvMg+3IWdZAXsheVF9uEkxhJdp5Lj+2oquS07Q1M0TYleU3aV8+iLEodNccrea7BsG6d4WErpijhTue4MJoap9FP2pVRKd8M11O3EM8ZcnuGX5Ulj2fAdZ5kU/3aNfDulEd/JyePZcjX5lqO3V6iX8fnvds6ePKHy/ubLN3O2cCLj0xadERaRlc4nOHtE1h8gn/W/4KzKZ15yf6566MoyL/JEwlT375PW/ZflHkNkfcr/WbJRaM76ryp5vuQs1VdCbyC1soTBMp5phLC2P17WJh6W+u6+1/TEwyUpDbtSqwtswPcTLsBEP0Vm3DwkETPbxEZkPUn+wkUPFppscxRvzlLtFHppUS00+4X+j0I3CuFi84SMAj8Z8lRB50R+KO0uDCbj4QI8CqfDVUae51QX6o1GTvepcq7XF9AUD3rQT/kWWZJo1H6R1VdCZy/yTrEPmuInlVrpRr6/V9nMldk3i+nbcnmmTa1VsAmaqmIfbKbW8XhPpLQ7moVmnOw26JvFKd8j8uPeFkuU6Nu7InvH6I/RnjDIlV+9QdZai8bbTKl8A7m+9w3fmJVvtXXS0x1ryVMXvVE/Kbuuflx6rl+RdS2yfkw/5jhBy6fbWuy92bCL0NyPzTOa7zrqWY51zDTHt5Frmtfw42TvHJbU1a2p+yTyVXg7J1nq/YXWL+qrZC1ryYruuhT9LCb5r/mUX4dO01JfIWtZV5G1LPZeR9hZqH4RGoOHLLx106Vlz9R78Snyef2tXDWQl2PZAQ8x6l6DfAJ+4EmEV9OHk961zrK2J0843b7oNJc8+ZQ5z8uVa4FOl31VT+JTe/ll2R+8Y9IfoddSlxSNXitXLu9vcs2FZWFtofPmqL5FngWLe0exPCorHfkrb5xcTfC511viOMf7Uq5H0hP1HR5+kZ7oS0rJt9D9M8IwGfmvyEX5dnoR5OvRv4nG+fFfCp1PvwfMgD8KzfdwhTBIQn9JqH34BJqq2NwlDA9hWR12oDQNuQ9ydyxPoEHvTxcmlEeuQun7MBcNrZiPkfsjT4Kd0EyGY4QevdXNKP0I+Rj9CbGZDZdRuh35beSf4C3wDvSMyORRN/K2Gz4C74OfY9kAmXGZ32jxQeRt9OcgPInmZbz1o1YjLHehr4C8EnkBMVmLPBq+CKtR66UEd/UJy0SzI7L/I8yP5kjkIAnNJeQW0RyheSqaKZHNXbAPzMZbr2i+qJUQzRoyMQlPR7OG/Qp4gtI0YUJ5NO/TtzpYzoCDovjQ+k30cEsUE9G4a6LIUcSIs78YNqVFou39TCmR1BvxQNYFc2AO9ovgfngzZNR+lGkL6OcE7CvhgZgHlj6QP7oyuVcI++PYvIHcHMsox1pBK0x8Q+omlqCfBptMPLwHk9GXYdRVicwu7J+hlDXiH6BWRdoitmZOtO6I4SHqElt/OqyCn3ewScc/8dQtqbsaPassiHJ1IG1FK7F8lHv4+QQZSz2NWj9g8zSMMoTomWFRJtNuBWK1Uuj9jOYF2ory8Dp4A+xM3X3I9fFQD34H/4H+Mdrqi3wrfhhXQOtBQyxn4mcuMpHX7A/+EjgKdsMmavEzGGXIBkrvh8yLKU2LD0Ain4DGP0eL49BHexpr0I9WNys3uAJNccjOYMgKgzcd7VTsKvoM9tT1R8DX4VL00d6IbPai2YF8lNbJK8Pa0WepRdYF0WqKRrQJm8LYz0cTzftm9F1gCqTPhj0znIrPqFdkhf8lZE355IZHz8OJ1HoI+4vIrER/PPwCPXNqiH/QEz17lM+u5ZMPml3dHwDXY59Lzkwif6L9ahlkLwpYR+YRNNHOeYq60Zwy74aZCsklcydkrZlZkOxN2CNMJCsCrl8B2R4S7QTGHlLqY2/Yo0xjeIu0rpScQfyXYvJpUQ+YAX8Umu/hCmGQhP6SUPvwCTRVsblLGB7CsjrsQGkach/k7lieQIPeny5MKI9chdL3YS4aWjEfI/dHngQ7oZkMxwg9equbUfoR8jH6E2IzGy6jdDvy28g/wVvgHegZkcmjbuRtN3wE3gc/x7IBMuMyv9Hig8jb6M9BeBLNy3jrR61GWO5CXwF5JfICYrIWeTR8EVajbhnq5mPTAvkpSrORe6FPgIwlPA3rUDoDDoI3UWsL7Zalh1HPGa+/GDalLqP2fqaUEemN1GX2gzkwB/tFcD+8GUY9jGY8GtcEWAkPjD2w+GQedWVyoBD2x7F5A7k5ltFct4LUSqQ0sQT9NNhk4uE9mEzpM8hkpn8Am4p4JjKG/pt3KE3HD5HRLdGvRk/2BlEODMRblOFRrn6CHhs9Dc0PlD4NmR1NHMww+ALeonm8Dt4AO1O6D7k+terB7+A/0D+Gz77It+KHnge0EjTEciZ+5iITK83K8pfAUbAbNlGLn8FoTjdQej8kkqY0LT4AiV4CGv8cLY5DH+0GZK8frQtyPrgCTXHImjLMo8GbjtY461GfwZ66/gj4OlyKPtpVkM1eNDuQj9I6mWDIcH2WWuRJEOV8NKJN2BTGfj6aaGY3o+8CUyB9Nuw24VR8Rr1i3v0vIavAZ/Y9eh5OpNZD2F9EZu344+EX6JlTQ/yDnuhZ3T6ZoNkJ/QFwPTZktR/tJKeQo5liNg3xD8kQcyck580sSO4l7CH/meuA/TwgV0NimMCIQkp97A37g2ksVF/qw0qeiuxxpRWj5xhmptNkce4eIE8bzGKeJLSldKH8baxJle+nmbk8S9Gi0X9HP1P08gULJX9tIZqewmC/0K+NPpe62ZR+LwyHIQ+AWXg7FVnSbvf404yKSp5RyNlwIZpH4088avO3dfIUpR3PTy7yPCSZZyPL0S+RunofmgGUPous8XAKjoJLGXuSUE8iAl3lCYnO4alFA+QG5j2pKzYqn+cVV8Wfnziqv4pNUA8/XaiVwROSJqLxrvLnO33J+LOR5TwDWc7zEMfYU/nynKpT/h7Ze5G7y9lW7xPZa43cg9IM5E3IX2A5HjkRuQmlH1LrJJrikTc038TkpF8Tm+LUSod9KD0YkdIU5IuUPo+HiuhfQd8QuTqlIfK9yI9HfRDZOxz1gdIxIse65J93mVAZzSpV2vEI8kKRzRWc5fOFphk8i+Yi8lws/yIM9gt9D72GyylNFHq5yKdgOvYKm5mwOpxC6Sj6MAe5D/JSWvwBm3HIOykdjJ/C+N8Kl8R7Lj0ZhGYtmo1wOmSkJotSi2ZSbAP/C7t43hyTJ4GpeB4a74Pov5I5Ms2E6ivqroSz8MYTD30cTVex8SvH5LtqzSltGXvNMaY6OH0xbOqKRp+J+oznxdKHsByaTSJ7s9B3ib0t+Sn2/jZKD0qpG7vMThKeu6Avhc8n6X+Z/Iuun5Pp7S/07YjUCrIZywn0i8i6CVLLa0hb45DT8JMeu8QnCJcknnC60N1NCY+hKYvNCeTiQnMTvWrArOXQ1hg8D6CHx4ShT2yrRhmS302yTmx0cdHI7++4HZJV5heTsYSlsD8hctAGmyQ0PaI8JNplaSWJyBSXiHmPMeruMXk2O5geLkUuHLtdciwmTzuvgh1pPYdotEbuI5ZeLrXSkc9jmYOHWcgz0B8kGrvRV0ZzjtLZaI7gbTaa5lieFrodh/mK8pD+d2Asf6UPx8iEKJPnyKjdKeAoUWLe4SRmKhf7GB5q01YTStPJn2PoGwnd/i7z0jZuIzxODuzH874o/vFoSM8zGMsxYlUSfVHYHcvB8XYvsS4ukXtnyYTIUuJWXmSX22fJZLHpBWehuR3LFNpKwXIPtXKwmQfXUtoxvn7rubGE9Hk1Y/wEfVn4Pv0ZGFky3qHRqMXSZRFPrcmoMB7VxWQ10ZDIeAPx/Cz7wGaitzXelvipx0yVjHYqap2i1lYsY2R7OparycxkkcM0dQWZtoEZl/7Pj1Z0fI2It57MUUV4Dz38Mb7jleZaI63sjq/Zua70rWgtize3Wz5Lr+pRK9pXxfMUnhKfUv3Iq35yTc/v7OTbyLqT2LAPmGgdzaBuR/0xmb+B2ZQxbon2Riwnou9K5OcI3b60gb1CdpVoRpbCREpTGXUrxnsUzoSX8JzBfLWAabBd3EZ2uQnxeZSd7WnZM10+bGA1vUZWXOKT3Evk6iXy+RJzIfIF4jYpfhUrjUZGPY+RNo2uYuw5p5idjcIEsiiBq4z5Hst+kGucOiN56O6Bv2YPPMseKDtMV/rZhCxNJ4f3kdXsRc5yMZZi/yb6wVhmIbdHv4SeH0Rejr5N7ADMZvWdlXtyaSU2N/8b5quLrFbm9GbGlRZd12If8nl9CektPZ/MWFKx7BLjnoe6ZVV55zMlPrNOzlshnpXid96UL3+nE3/SKFSF0RcWvVKiid0p37KO9ZBvwsf4e5BYYeS6yHWR68v3tGMN5Lv0Tp+Nfhny3fL9MflmvpO3I59C/lFk+SseV3e9/MoN+gbybUDn5w1+m+UXft9mo1D+jkAp+Tv3WLL8NUcsWf4eJLYqHCy/cpPwsPzKjch5m0SOTQ6flF+5STgj/sPjwoTTyF+K/4TvkX9Djmw6w/pY9ob95HdvpG95x6I+h89hvxg5qnWSPueir4i+mDChBaOrDU8z3imUroYJ6K/HshVt/Yh+Fz7roWlCZCLNRUrvxH46Le4iShfhRFpviWUN6oplOnI6cr1wJ/oLyDXwE+kr05PbkKsh34GfQ8LEBGR+yScxkdI70UzD2zr5DRw8XI+Hush1kevL38s7+0+RS8IS1GpNn+vR5z7M8gJG+gul9C18Fc3dcDvMpfRqxzoJbyK/hc/NyDOweQc+jX418n7kc9JD+RUO11vJw/p8Lm/y8pGJm3ySHqub93fpTx5zIZ+8O81ZKc3bJJGMNLGJMBVSCw9187ZhSd08Rp23APk4Pj9EPoh8ilIyKu8wmu/wI9/AUaqwNzXxpDJ9xw4brJLvHdb/fjVhcO8RQ9Uq5U5+t3ZplarcySI/X5VQSSpUZdW1qriqra5TjVUL1U7dru5yPjqrh9TDqq+6Tz2gRqrH4/ZFVYIqpyqqq1Qd1dB5aanaq+6ql2u1ixqvJrudY5DKVqPUVP6PwaiOVYluz6ikklW6ul7doFq53fkOdbfS6lb1J/WI6q/uVw+q0WqaKqlM206dslS7LrfcnKr6dO3SPlXNxcvV/GboNW5vruw81lVN1U0qU92seqh7lFHVVVc1QU1RA9RgNUyNUdOpU0ilqipKrnQ3qgzVUdVQf0ZfShVzcaigUlRV57e+aqSaqdYqS92i7lS9Xb9rqm5qonpU3auGqOFqrJoR78GVqohKU2VUNeehgWqu2qi2qpPqqfqoQNVSt6lJ6jE1UA1VI9Q4+S3TvvWG9zW3wV5wABwKR8EJfXsPHmEeg7PgPLgEroRr+/Ye3t9shTvhHngAHoHH+vYdkm1OwFyhr2ExWB7WhE36Db7vXr8N7AC79Bv6wBC/O+wF+8FBMBuOguMHDOvd158MZ8Bn4SK4DK6Gm53j3v5OuAcegEcGDx05xD8GT8Af4Vl4AcaEgT/4gb6Dg8KwGCwFy7vCYUFFWB2mw4awKWwFsx4QPx1hV9gD3gMHwMFw2APD+g0NxsAJcEq26KfDWfBZOB8uhkvhyuFujoLVcD3cCnfCPfDg8PuGDgi+gt/A7+EpmAsvDh/SNztUsDBMhuVhVVhv+PD0umFTmAE7wK6wJ+znWC8cDEfA8XAKnAHnONYP58MlcDlcDTfCbY4Nwt1wP/wCHoXH4cnhI/sMD8/A8/CSMEHDRGiHj8wenpAMU2AqrAxrwnojXCQTGsFmMAO2g53gbVDuxrXbe5L/jVfj1nkZVfb/SvL44dD/MwO3YwRuF01Qif+xdz7vItlzu15BFv2DNG6fK8JvLv+/SJ7bvf97Fv/D1MyIdl7lHU975Pogd4l/mFf+YZb7Lyz2h5lKTw2v3u8oI/i9zv5LGnelKqlK/ZvS1UjaXZ/S/q3Xa1XFf+u1kqr8b7x67kr6r/mvY+K5K/i/5hV/iHXd3cYId9Wfo5ao1WqbOqCOq1zP95K9il4DL8Pr6vXzRnhTvDneEm+1t8074B33crWvy+sOepyerufpZXq93qWP6JP6oilsUkx108S0Mz3MIDPOTDfzzDK3BqWtxChnTccC7/sUeD+jwPuZv3vvFygP3TL/QiV4v3tfuMHl75MWX17fnr/cf3KPy9+XUJf7L5Fc4H3lAvZZBd73LPC+wHhKHLn8fcmqBd53KvB+zOX9L7vo8vJyGy9/X6lmgfe1f/ferb9K6QXKJ/Neu/2heDTCKp2i16rRyH2XcyXdXlU5rt0Xfz0Sfz0efz3z31lXXxV/3Rh/zYm/7r+8FzXs5aOssf7y93UmX25f56vL39fdffn7eu8WeL/28vf1uxZ4f1uB99kF3g8r8P7Z32WZExrOLfB+/eX2DQvM0n8p31Pg/b4C7/dfPouN9zhaF5m+3jNqgDef3baP+6fcSp2jvKBYcCXXiuIqTGprc5Ky7Da7xW51mtD7yfvJ2Z3xzijPO+udVdr7xftFGdvStlS+vcne5K6bkg/atDZZ0p4urks4jfwFkZX+mKKuZm33vqQ7jQxT81WOOqYuesmuD4muV8lJnZVOykrq4tg26VbHdq73xdyenOpOC+nuzNPUfq+MLub69Hdec6w7aekS7v0PvObYg0q7d1845tgjjjvdWCVDU1SaPeb6usWV/pXXHPuNe93q3n/La87vLI/HLf8WtzwRt/wubvnP/ranvx3o7830958lHSm5hZJOvy+xu+jhbnq4hx7+s2QfJfspOUCJVgna/XPLrIiWb24X08VcVEu4qJqkNkmZLupb7BYVuj5tdZEyzkI+jYyu+m5pufq9mS/FTHneRe+im7V8L99FK9Duvge/AX5D/CboFJ2iEnWaTlOFdFVdVRU2WW42iwR9gj4qKegX9FNFgwHBAGWDgcFAdUUwLBimigUjghHqymBUMEoVt6k2VV1l02yaG1NFW1GVsJVtZVXSVrXuzGer2+qqlK1pa6rStratrVJsuk3nd7nrq7L2OnudKmevt9er8raxbayusTfYG1SqvdHeqCrY5ra5mx3Jt2vJt4o202aqSvYue5eqbPvavqqK7W/7q6r2XnuvqmYH28Gquh1qh7qNIttmq5p2hB2hatlRdpSqbcfYMaqOnWAnqHQ7yU5Sde0UO0XVs4/bx1V9O81OUw3sDDtDXWdn2pmqoZ1tZ6vr7dP2adXIPmOfUY3tc/Y51cQ+b59XN9gX7AsuPxfYBepG+6J9UTWzL9mXVHP7sn1ZtbCv2FdUS/uafU21sq/b19VN9g37hsqwK+wK1dq+Zd9Sbewqu0pl2tV2tcqy79p3VVu71q5V7ex6u161t5vsJtWB+b6Z+e7ocmWbusXlSo7qZHe6bOlsd7ns6mJ3u+y61e5x2dXV7nNZ1c3ud1l1mz3gsup2e9Ctke72C7dG7rBH3BrpYY/ao+pOfhO7pz1tT6u77M/2Z9XLnrPn1N32F/uLkt/5nuzWx2SXSVd4V6iJXopXTk3if0ad4vXweqpHvcHeEDWV/w11uvegN0L92ZvuTVdPenO959Us72fvZ/WUd947r572fvN+U3Nkk1HP6FCH6lmdpJPUc/pKfaWaq0vqkup5XUaXUfP0tfpa9YKupqup+Tpdd1IL9Ag9Um3Wo/VotcXdR4xTH+g/6Qlqq56ip6ht+nH9uNqu5+g5Kkc/p59TO/QSfUjtNEXd/nPJNDANVMy0Mhkq37Q1bT1tFpgFnvFH+C95ftA36OvVC/oH/b36wb3BvV6D4L7gPu+6YHgw3GsYjAxGetcHo4PRXqPgs3Cq17jwrYV7e6cLP17E82JJxZJa67FJdyYt1G8W7Vd0kD5XdGLRGfqi1TbRJNoKtoK5wl5rrzXFbCVbyVxpq9gqpritZquZq2wNW8Mk21q2lilh69g6pqSta+uaq20D28CUsg1tQ1PaNrKNTIptYpuYMrapbWrK2ma2mSlnW9gWprxtZVuZa2yGzTCpNstmmQq2l+1l0uQ/pzbX2gF2gKloB9qBppIdYoeYyvYB+4CpYh+0D5qqdqQdaarZ0Xa0qW7H2rGmhp1oJ5qa9mH7sKllH7WPmtp2qp1q6tjpdrpJt0/YJ0xd+6R90tSzT9mnTH07x84xDeyz9llznZ1r55qGdp6dZ6638+1808gutAtNY7vILjJN7GK72Nxgl9glpql91b5qbrRL7VLTzC6zy0xzu9wuNy3sSrvStLRv27dNK/uOfcfcZNfYNSbDvmffM63tOrvOtLEb7AaTaTfbzSbLfmA/MG3th/ZD085ut9tNe7vD7jAd7Ef2I3Oz/dh+bDraT+wn5ha71+41neyn9lPT2X5mPzNd7Of2c3OrPWQPma72sD1sutkv7ZfmNvsX+xdzu/3J/mS62zP2jLnDnrVnTQ+ba3PNnfa8/dX0jJ+l5M6nAXttNZfOgXeXd5dT9/f6K89/z39P6TAvzFMmsVliM7d6/jO7scvc/9mN/z/fjf939qWQfdXlbsu7L/zyf3Lsf3LsP5RjXjDI3c8X89J0A9PG767KqiaqlWqnuqge7rwwyN2/j3P3A9PVU2qeWqyWqVVqvdqqdqn96oj6Rp1UZ92dvfJCL6nQGGUKDS80otBYXkcWGsfrqEIP8Tq60J/c6wgnTeB1RKGJvI4sNInXUf+Lve+AiyLZ3q3QPTXTCQQURGXBnB0wgXENmHNYw6qrKComUFF0jWBe45oziDlncVXMOeuaMOecc4T/6WPr4q77dt+979773vtd6ked6jA9fb6q+s5X1T3djmi0UY4BYLvBfgPRRjoGoe3mGIy2u2MI2ijHMLDdYb+f0EY6hqPt5hiBtrtjJNoox2iwUbDfGLSRjp/RdnOMRdvdMQ5tlKM3YbA1BvJujqGQd3eMgjzqn0BkAnre1THRQmaShcxkC5kpFjJTLWSmWYhMtxCZYSESayESZyEyy0Ik3kJktoXIXAuReRYi8y1EFliILLQQWWwhssRCZKmFyDILkeUWIuPB/66OmYjIHERk0T+JyEoLkVUWIqstRNZYiKy1EEmwEFlvtZVfLGQ2WMhstJDZZCGTaCGz2UJki4XINguR7RYiOyxEdlqI7LIQ2WMhstdCZJ+FyH4LkQMWIisQkXXYUrYiIrv/SUQOWYgcthA5YiFy1ELkmIXIrxYiJyxETlqInLIQOW0hkmQhctZC5JzVVs5byFywkLloIXPJQuayhcwVC5FrFiLXLURuWIjctBC5ZSFyEBE5joicwZZy9Z9E5I6FyF0LkXsWIvctRB5YiDyyEHlsIfLEQuSphcgzC5EXFiIvLUReWYi8thB5YyHyzkLkvYXIBwuRZKutpHxERiEfkVHoR2QU9hEZhVvI3EZEHiIizxGRt2ZLMd/TaJ43zqY1JLnocRbLq/GavDVvw9vx9rwr78ajeE/ehw/lw/hPfDgfwUfC2OUqv8av8xv8Jr/Fb/M7/C6/x+/zB/whf8Qf8yf8KX/Gn/MXehHzPUr0KD0KXzDT/HUur8qrEsZr8BqE81Y8lEi8LQ8jNt6FdyF2HskjiYN3591BCfTgPYjKe/PeRON9+QCi82l8GnHnG/gh4qEX1gvjLIM3USQf6RvJV/KTMktZpKxSNim7lMP0DM7oBc6uU+KVam4iD84HdTD3gE/msPbImGqPvKm2AZK8A+xNJA/JfBZYTiknUa3v9ZDSSukkT8lLSi95m8++gz1++15GshIXyU1yl2TJJgnJLjkkRVIlTdIlQ3KRXCVzvksC3/rBKZifYVJJqRTRpDJSGWLAtiLEi8/jC/gSvpzv5Lv4br6H7+X7+H5+gB/kh76GuDlbxufyuXDE+ebvmvlivhjwXsaBRwG5HfB9V/m9z0efC3sthq0b+Ea+iSfyzXwL38q38e18x9fqGI8+j8+Doy/gC8w7MvkSOPpyDuwMZ3gIjm76YR49P/H46lG/4gdidtXCzPzc32xd+DmzNcDn5E5sDRlABpJBZDAZQoaSYdCvh5MR+HbR0WQM+Rl6+TgynkwgE8kkMplMgT4/jUwnM8hMEkviyCxggNlkDplL5pH5ZAFZCHywmCwhS8kyspysICuBHVaTNWQtWUcSyHryC3DFRrKJJJLNZAvZSrYBc+wgO8kuspvsIXvJPuCRA+QgOUQOkyPkKDkGrPIrOUFOklPkNDlDkoBjzpHz5AK5SC6Ry+QKMM41cp3cIDfJLXKb3AH+uUfukwfkIXlEHpMnwEbPyHPygrwkr8hr8oa8Je/Ie/KBJJMUaNCU1WZ1WF1Wj9Vn37EGrCFrxBqz71kT1pQ1Yz+w5qwFC2EtWSsWylqzNqwtC2PtWHvWgXVknVg4i2CdWRw7w5LYWXaOnWcX2EV2iV1mV9hVdo1dZzfYTXaL3WZ32F12j93nCnvAHnKVPWKP2RP2lD1jz9kL9pK9Yq/ZG/aWvWPv2QeWzFKAgsy77TmXuMxtXHA7d/DavA6vy+vxJrwpb85b8I68Mx/IB/HBfAgfx6fw6XwFX8lX8zV8Pf+FH+ZH+FF+jB/nv/IT/CQ/xU/zMzyJn+Xn+Hl+gV/kl/hlfkUqLpUw39sqnZBOSqek09IZKUk6K52TzksXpIvSJemydEW6Kl2Trks3pJvSLem2dEe6K92T7ksPpIfSI+mx9ER6Kj2TnksvpJfSK+m19EZ6K72T3ksfpGQpRdZlN1FGlBXlRHkRLCqIiqKSqCyqiKqimqguaoiaopaoLeqIuqKeqC++Ew1EQ9FINBbfiyaiqWgmfhDNRQsRIlpCCoXUBlKYaCfaiw6io+gkwkWE6Cy6iK4iUnQT3UWU6CF6ih8h9RZ9RF/RT/QX0SJGDBADxSAxWAwRQ8Uw8ZMYLkaIkWKUGC3GiJ/FWDFOjBcTxEQxSUwWU8RUMU1MFzPETBEr4sQsES9mizlisVgiloplYrlYIVaKVWK1WCPWinXmu1/FL2KD2Cg2iUSxWWwRW8U2sV3sEDvFLrFb7BF7xT6xXxwQB8UhcVgcEUfFMXFc/CpOiJPilDgtzogkcVacE+fFBXFRXBKXxRVxVVwT18UNcVPcErfFHXFX3BP3xQPxUDwSj8UT8VS8Fm/EW/FOvBcfRLJIsRM7FXPFPDFfLBALxSLxTDwXL8RL8UrpofRUflR6Kb2VPkpfpZ/SX4lWYpQBykBlkDJY7aX2VvuofdV+an81Wo1RB6gD1cHqEHWoOkz9SR2ujlBHqqPU0eoYdao6TZ2uzlBnqrFqnDpLjVdnq3PUueo8db66QF2oLlIXq0vVZepydYW6Ul2lrlbXqGvVLepWdZu6Xd2h7lR3qbvV/eoB9ZB6WD2iHlWPqcfVX9UT6kn1lHpGvaJeU2+ot9Q76j31kfpEfaY+V1+oL9VX6mv1jfpWfae+V5PVFI1oVGMa1yRN1mzaNe26dkO7qd3Sbmt3tLvaPe2+9kB7qD3SHmtPtKfaM+259kJ7qb3SXmtvtLfaO+299kFL1lJ0olOd6VyXdFm36UK36w5d0VVd03Xd0F10Vz2N7qa76x56Wj2d7ql76el1bz2DnlHPpPvo3+i+up+eWc+iZ9Wz6dn1afp0fYY+U4/V4/RZerw+W5+jz9Xn6fP1BXj1GWdkcWa0H4tlwKA43zmLV4H4fpJXh/h+mjfm35Mk3oz/QM5hDL3AI3gEuQgRL5pc4mP5WHKNT+aTyXWM7Dcwbt3EuHUL49ZtjFt3+DqeQO5ihLgvBUnFKMF5UyYrskKdsqvsSv1xZjTAdsV2k94WTlGIPsRZ0mfKEGUaY8pcZQvzVPYpr1kAzpWG4CzpPIj2T4kD1EFmiPk1QAFNhQiwGdgZvkIdRJixD0tLsGReo3El6UhGdQ8sn1b3Qp6k7oP8nHrw876nobSN2EFLeBEfUAC5P149UpPM9eo5yA+oFyA/pF6C/Ij6wPykkdY8opHOPKLhaR4Rj/UBj/rpGo0DlnYZCuR7DPWLLS64xRW3pPliixduSY9bvHELIw6oNSfUXSAz35ZUnBUnjFVgFQhnlVllIrGarCaRlXHKOGJTEpQEIpTHymM4HpMXsGP/ohj7ZYT9/zu+/nsirBlD/27c/FfGTDfRSrQWbUUviEBm5AyGmFkNo1ltiEyjME42hBhpRsePsTH0b0bF3n8RD/8YDadAHPwtAqaOLv+3RcPP0Q7i4mSI36mjYhlQH6b2+Kg8TN1RC5THG0t3vAPV0QgUx0zUHLGgON5Cq/0OWuoPZrv8FDtZxy/jpuaqpdHcNHfNQ0urpdM8NS8tveatZdAyapk0H+0bzVfz0zJrWbSsWjYtu5ZDy6nl0nJ/NdoO+nq8NRyGYqh/K+ou+WPcNVwMVyPNH6LvHnWvug9j8MGvRuHTEIeT1HPqBfXSp3hspDM8MSY/+NOo/OGPcdnwMtIb3v9QdP4iNmsf/g3RuQZlNC0MZb1pTuJBa9F6JAteKc1Jm9FQkoe2oW1IQRpGw0gh2p52JIVpOP2RBNLedAIpT6fSGaQZXUuPkBDWhUWSPqw760P6s34smgxlA9gQMpwNYyPJGDaajSUT8JrnFDaRAdvjGH8m17gbieUe3IPM4+l4bjKf5+UFyCbuz8uTrRjxT2DEP4mjt1NSvHSE3JXTyGmol/xSfknTy6/l19Rbfiu/pRlsABfNaBtmG0kz2UbbxtHMtgm2yTSHbaptBs1ji7UtogVsS2xraHHbOttuWt6213aU1redsp2izWxJtnP0B9sF2yUaAtrgAw21pYA2iBFFRHG6XpQUpelmey57brrNntdegO6w+9v96R57EXsRutceZA+i+8zrZ3S//Vv7t/SAvay9LD1or2CvQA/ZK9sr08P2avZq9Ii9nr0ePWpvYG9Aj9kb2xvT4/Yf7C3pr/Ywexg944BhP01SQpSW9KwSqrSl55V2SiS9rHRXutN7EGen0fsQZ7fQFxBnX9NklanfM6E2VX9kLbRY7Srrp4/Up7IdH+9vgdHoMrzi0pS2ttasS7WGkmLEZmmP7KBpCsH2uZDMfBmogrlozaVEaykRli5AMu+yyUPzQKvJT/NDuAukgXDMirQiBJeqtCqR6GQ6Ge+y2UtayN5yBjmjnEn2kb+RfWU/ObOcRc4qZ5OzyznknHIuObecR84r55PzywVkp+wvB8gF6a/0BD1JT9HT9AxNomfpOXqeXqAX6SV6mV6hV+k1ep3eoDfpLXqb3qF36T16X+KSxF/yV/w1f8Pf8nf8Pf/Ak3nKP7NOAlckhjMNEv5aIQ1ezfKCxElGSBIglwM8zUvM+9IKQLIDqsVAJ5aApJBSkFRSngQTjVSFZJAGkFxII9IY9GEzSG6kFSR30haSB+lKIkla0pP8SDxJP0jpoXcy4k1dqCvJAH3Um2SiPtSH+OA9Dd9Af61FfKG/NiZ+eFU3M/bULLQD7UCy4l0O2Wg32p1kp31oH+jTw+gwkosOpyNIbjqGjiF5oQdPJfmgB68l+elWuo0UoLvpHuJPD9KDpCDONxXCnlcENXUVnHVqhrNOzXEuzDvVXFg+vJuqOGsCiGVi/swflGMRVsT8jRgrD1uqsCqgHOuwOqAcG7AGRAb9E0psoHzag3IcqvxE7MoIZQxRlXnKfOKqLFSWEDfllHKapFOSlPPES7mkXANN3VvtS/wgigwkWc0IQXJBhJhF8ph8TgoAn58i/sDiF0hhYPJLpAhw+TVSFPj8BgmEMdYtEgScfocUA16/R4oDtz+Auvq9L/nRl8qsHfji84UvQSwItpgecVYLxjQSeiSjRzbQeY2JQL/soOI6Ewf6paBfOvrlhn55KMuUFeDRKmUdyYA++qKPmZVbyh2SXbmnPAK/TE/zo6f+6GkR9DQQ4uBcGCfMh9FGafQ6GL2uCPHpJakK0ekDjFA+Xn01f+XYCj0qYPpoPmmPFLN8LGDtkxN67xg68fM6RhfRFbDk8Xk/6AFfwaAEA9wQCQnrVkY8bIiHQDzsiIcDdG9ToiAqKta2htjoSiOlETFgZN6XuMDoayzU+XhlGskIY7B1JKuyXtlCisBI7BEppTxRXpNQ0BBDSEdQC2PIj6AOlpAYiP1ryQSI9UlkBtb5eqzzXyCCXyEbsOY3Ys1vwppPxJrfjDW/BWt+K0T2R2QbRPcnZDtE+A9kB8RzGzkMGseLnAJd40cugpbJTW6CKlHJQ1AXacgTiPHeMAIAJoQRUmdCzBEkKWvOMpDa5t02pK7aSwsmh+EzmeiUv70fPu3yX7T35/ZAQrBWndjma6VqD87f2gOpR0p9XsdIBbx27/F5P0a4Ml2ZA9+5VdkLbfyNavYcWIuj/I9n4ofn4LTO8tO5FgM2+wfYHT6ZFrmQIBdS5EKOXCghF8rIhTbkQoFcaEcudCAXKsiFKnKhhlxoIBe6IBe6Ihe6IRe6Ixd6IBemRS70RC40f9u8HTzQWCW+gXz7l9eCGFWoG5xlZpqbBtBitCytQuvA2YXQdjSCdgf9FEOH0lF0PHxrHJ1Hl9BVdD3dTHfS/fQoYHMecLhNH9Ln9C0EIBvTmBvzYj4sK8sNGBehucH7nIBFPrSNIQKbtikNQtuMFkP7Ay2OtjktgbYFLYk2hJZC25KWRtuKfos2lJZB25qWRxtGK6DtAFHdtOG0JtqpsqdppXWyF9oEOb1pjXd21bSyu10zrW2OXUebaDfQbra7oP1gd0WbbE+DNsXuZlpQUO5oS7tQ/J52NBewkQtoDQZLeSFvDIrD1C/ASeAltETw0R/y5jQA8ha0IOQhFLQM+FYY8la0COShtCjkrWlZ8/4TWg7y9jQY8g6gWRh4VQnyCFoZ8s60CuRdaDXIp9LqkE+nNSCfJnsQBv6mhTxBNmdf3tmhYsBTaNXgpwR5oh00D/hoM++osgvIk+12yFPsDsLAN1Bg9tIkF/StJhDzO0Cs700GkhFkPJlO5pAlZA3ZRHaSg+QEOU+uk/vAL9Y1RWhJXtDWs0JbctIitAS0pkq0Bq0HaDQHrzrQRYDWVEBoMdqmdAnaZnQp2h/oMrTN6XK0IcDupm1JV6JtQVehbUVXow2la9C2tmcyLfjoY1rw8hu0iXZftJvtfmg/2DOjTbZnQZtiz2pa8Dgb2tJ0JtZfLNZcHNbcLKy5eKy52Vhnc7DO5mItzsOam481twBrbqFZH3YPRDwtIp4OEfdExL0Q8fSIuDcingERz4iIUyK5ELyznCNXEOzp1MX8mYj5NOEaeF9/ThKAOgBnw2g6bGue2Ea8zO82j0LTfy61NVuSyb3AJxOxrWBuXqWjrsBQhKaFcRVFJmLIL2Zc9SLDaH3agDaiDel3tK3SECJg449z06wb68uGsgl8Kl/IVxnvjQ9GspECLDtDmanEKnHKLCVema3MAcbdpmxXdig7lV3KbmWPstd4ZTCDG5IhGzZDGHbljfJWeae8Vz4oyUqKCrSn/qyOVcep49UJ6kR1kjpZnaKuUxPU9eov6gZ1o7pJTVQ3q2fV8+pF9bJ6Vb2u3lRvq3fV++pD9bH6VBOaXXNoiqZqmqZrhuai5dHyavm0/FoBzan5awFaQa2QVlgrohXVArUgrZhWXCuhldRKaaW1b7UyWlmtnFZeCzY0QzcMw81wNzyM18Yb462RwchomNdBs+PIk+BoUwbVVRViWjvWAZRDJIwqNdYHRpU63jdr4BjSBUeGrjj/m4av5CuJm225bQVxtyXYEkha2yvbK9CMMF4inuZ4CbTVReUGyWWOmkBJDQX9UExdCsqhHIz4k0g1GPWfI9VRP9RA/VAT9UMt1A+1UT/UQf1QF/VDPdQP9VE/fIf6oQHqh4ZqMiiHRporqIUQVAt9UC30N9KCWhgAfm4gjf9Ojf5jNfgvqadPNaQgmgTRdCCObohjBsQxK3qeDz0vgp7XRs/roU5q8HH0KePbBqFchZhzy2WJT+r2//tW/Oft8WPbgSOkwZZCsKVwrGEb1qeB9emC9emK9ZkG69MN69Md69MD6zMt1mc6rE9PrE8vrM/0WJ/eUG+eJIN19qpspDp7AzSv1WPNPo/tlGA7pdhOGbZTbn1Wk11SfdYLVMlnFvjU05E5sBdgS5axJQtsyfaPI2n6hL6k7yw1kIalYxlYFpaLV5ZbyqFyGzlM7ip3k6MMPyOLkc3IYeQy8hj5jAKGv1HIKGIEGsWMEkYp41ujrFHeqGQ0M1oZrY22Rkcj3OhsdDOijJ5GPyPaGGQMNX4yRhqjjbHGeGOiMdmYakw3ZhpxRrwxx5hnLDAWGUuMZcZKY7Wx1kgwfjE2GpuNbcYOY5exx9hnHDAOGUeMY8avxknjtJFknDMuGQ+Mx8ZT47nx8r+/9PjvfZ//x37p4Qqav7XsbryDmF/6b93XDj2RtrOdT3UXst28S+fzPT7/i/t0Pt/hA8dgJVmzVDMd5pqqwECf5wvoc/IKNHphFgh7lIN1NVlt9h1rxJqwVsBVEcB6fczral9L5rW01AmO8mUK/GMyr7ylTuZ1uq+mcr9LFcyreF+kmn9M5hW91Al8+ZME8eCLBD5/mRp9LUH8+CIBSl+mZph+W271u9QGUrs/SRFfS2rylwmi1pcp/e9S5i+T5d/H88Uj/Hd+5E/mRyi5CPGzBMT6SqCy6+GzWD49gcV8GstPZAyZCKOfeLKALIPxzwayleyGEdBxcgbwc+L15v/dPPAfymv+I/lXZ0E+zpFoYCaa4x5SxhwLQKxLh6MH8zoLpblgHM0g2k+A8kQ6CcqTqfkG8Zkw8mJ0LX1kPoWWPoHxylN8D8cL+hLKr+gbjJnvoPyeJkM5hZlvQWFMgjYnMxuUBTOf3KoyGH8zHd8p4spgjM3cmAeU07J0UPY03xECcTUDlDMyPyhnZjByY1nNt49AjM0F5dwsN5TzsDxQzsvyEvOtKvmgnJ+ZbwOaxqZBeTqbDuUZbAaUZ/KK+CTZyoTzKrK7+aw6GfyVveVg8+mKckXC5UpyC/NZ4XIYlNuZbyaGWB0F5R7mU6vkQfIgKA+WtxLzLcvboLzdDsxsZzCKZPbsjvaEOjo4QOk5OuoLCdUX6TDq1Rfr26C8Xd8F5d2gVKnhAzqDg5pMwREesLILc/H7+DtrrBlGQqxfB/+mQShqEIoahKb6FStFDUJRg1DUIBQ1CMXfnlDUIBQ1CEUNQlGDUNQgFDUIRQ3y8QwZKhGKSoSiEqGoRCgqEYpKhKISoahEKCoRikqEohKhqEQoKhGKSoSiEqGoRCgqEYpKhKISoahEKCoRikqEohKhqEQoKhGKSoSiEqGoRCgqEYpKhKISoahEKCoRikqEohKhqEQoKhGKSoSiEqGoRCgqEYpKhKISoahEKCoRikqEohKhqEQoKhGKSoSiEqGoRCgqEYpKhKISoahEKCoRikqEohKhqEQoKhGKSoSiEqGoRCgqEYpKhKISoahEKCoRikqEohKhqEQoKhGKSoSiEqGoRCgqEYpK5NMzSj4/sSRDV7AeuJZkaO+MydDG5sg9uNLgVzoVLC4mQ0NYVY9R6q86HTY5j8GZt0ycLWxKHhuVaExRRqW4us7azryp1mSM9+mfES8plSA1SQjpSsKBRENJJPybl5hKOf1SHUzyyCFm1wx8lm/YnbLUq/O9n87eKbfxaFxMutzOGMnNGcPexnFGGZDDNjK8RImhaY6Vetny/qVvnfrnM6USnFOEfx5nLhuvL6numcuFR/TsEtambaRvzpa5fP2Dgor6Vg9r2SW8a3jrSN9y4V0i8vv7ODN+3Dntl1vCu7SIDAvv5O/n/Mbczt29ftteJzw80rdMt8i24V3CIns6fTz1oKJOf3+ns6gT/hp76gFO/4CC/tbif+CMYmjm1LCYb6qKAVqB9QqLoZQsZInbIm4Wf1ojQ87YST2aOe/GLxyZ7YfXyROqzU5InhHvW6p37fhp8aObB7Q/VrZVz4dLuu+rd/bpvemDM46OHdh69a72P4ZkOZWpxEUXOvb2xJ1b8rWeOrVt9ilHi+Xdoq1tmH1bhVtKqcCJeRfmDFpwv/KAstcGumyc2qF+iyUxvWc1zxdV7c6UNa2KT62V0d+e1SN24a2f83jdLDm5pUfzhnJobKaidYa8mv9oPNud4dct9YNXD+u/pdj9euNrLPsw/8eOkTWWex2c6MjpRxqMaR5WdGNVN1Hiu5Tv381prdjnHY/+rsGjdcWbpYuOks6+3Lys/4TkFYf6nZrv3aVJif2bHttnZ3autg3at9o3yn3QJcah4c+OXuCMnuuMjgc0M1EpeqozelJ/1++PRjwK6zIzS+2+Hquqj0o5MKvLv7/+Yv6ijXOzDifcVreOfDbJq/CD9TTrmag0z5o0D4idqR4oJf88dPS+Yjf9nj5uMC7v2riKe0MevT99sHjxxguL1AtLztqx9L6Diy7KvS/4jywZ6xrRbmOyW02vsK3vj5a7lqaxb827Ib2WL0q/N0/RbPk2h85y+ymbS8vZr+plfOO371TaZ3WWdCoXID7EeL6+0aaDXvtl4pM6exJv7XS+9/V3DM00IZd39ZOZ2Nwn/S/zNd8/X3lhb4OHoZX31Km3bg3P6ZYy5tRj++i+6yftWlw07/Ufry+IutY9jhxtV3rb8SI/XS7jtqBwuwztzhW+ciKjdH1BsLS3ccHATtUz6iEJSvyIX0/WK13hUMb68yLOuRUbMq5b7PzjccAKzZ0xvNpHVlDyL05zvlZKkxkHtn7ilEz/KTKAfh8YAH/AAAFABv4BsFj4Exn0RAaFg9jcWf26/u7ONOaC3V1p0KJr27BObSLha1ydhrlSuIs6oa06hndq9enElD87sSxOv48n5p16e6tQ37phbTrBUX1rlSvzl6yQ0LPPqaarg4MWFFrif/ZNtsKVo7a++2bmnuDOj45VuH1ixI721eqEPJ/CdlQ/U7lDgaylQrcczpKgVkro1+1CcOKi0UatXdnyPI27pWf55liZrG9DphxJHzx3XJVvphxaXSDzjir5eocnpfUpPiLINehCYq7nrYvnowEpyTkqzVvbgQ6Z/m7Dqpb9Yt40iYseOGjUiqfrx88+Ejiv1iDPHENqXHC+JCWf735TMnrz4AcdgubnL/RyTf7lSp+Qn3u0nj65qz54+dOdz3x/qek2suWBvEkBwekfbqwysXitul6HW9fuuWjpkL3flYqNqTW0k7yy8LZeWRPrtC45pcbBPH0LdhpY0XZs5tEqg1mnwWTO1iGX6lqs8NYZ/crpbpJCNklzKjY7BDRZFpz/v0EVLuY5upuvnZSdHIwzk7nCkNJJHgczHe5OIr5f/uTszhpTa5fPP7t8y8dO1dzsIknQjQan6jrIMb0WL+tbJfvTw5tqRMY3zBGZu9vqwR8WVxvfg1S/s/+e1/mwXUZ872es3O79Qw6+rntwe2zid+GPW5ZfWJ48nLh36smM69XY9Pr402d9lubq8+jBvK5LRl8MGlVycrtNgR2PD12e5cOlO6fCHD8PTUy+QjYWevaq9xtXt/zyvVwTx5Vtn7NzQuDoy0Lf17TtocT+Zdq3XrAxYeOoQvufctfeP744frnspV7JV64sSX556aS+OuLU2Gs11wXG9853ouS5QmpIURYb3S7LsJdNWo5e0Xhj0OnmI+oP9C74ovjkuBgt/ofhq/MmzJp7YPFZ33VbnOkH+XrouTfVeV7mcjPntbE5w4Zsi7j6bP7iw/3LduluAMe0A46pY3FMC5ce1VEh8dT9SAae+Q/26k+EU9DpBMYpCITjDHIGmIsFzUVn5L/k1Kzt/E+2/yXXxJ9TRh7Zvq3ytEOLihVamqVR+3MdNvtlThi/9+6yLbtPZt8ekGb4prNN874r8p1P2jzLRusXPGZ3ylmtX7rSZZaM/HZlhaF6UvT4pZNsRxuU797k7pP3xtV+kbMLHoi88ehai1l9eUJwyslSbidX7G+mH+31NMFdf9+8Xc5B3UYkLN006LbnmjGbX6RbF9L0QZpLxR76fT98ef+uO4KvTRgW1XzaraVR24qOLOhRwP1cyL5l3gtrTm6z9IRvkLPz5ZFtKlzdnfG5XiuyTIHbctZ2fu0rrxi7c1XQnrJzOzbxqrJ49OlRA0r1UCqembNqYJYdV5/2ar2ySmRi9jJVp7fwaF7DuTfm2VE1ovfD+tWjjtvrd4+2uOa1M/oFYp/Jxeyx0AltW1N12Gd+347qXft1vaqTb3iebjegkJw/++2vU5PJE5mySF7OdP2/3s3Lmzt8I5V0FncGxRWNKzy4YNvIyIhiBQq07NIhf8dPdZi/ZXjHAhHtw8y1BSK6hLfq1jKya4FydaGh5YdVzkqfvhJ0SAlnMWfgp2UnG5zXOmBUVNTXDhjaJdWRIn/XgZBtvm0QXrfNTN8Bhahx07NqiaX3zkT3e6j3jIyqOami1zOSNqzvuZAx8R/azJp+PWeut/VPT0mutaWZY/Uv8x7EPJvsE97o7YsnV7Rfh9tLpfP0PbZ1bXBFe/bmDRxVxz+2H9xQvdPjq5XcchYe7tfl0g/rloe5ZR3/8E4hx7m+ncLHKnX2565WeVFA3sG3Zx1smn3TphKXv181QN1QOGPNgcEVUzaOn9VILJx4oUdig35z59c4+HTp9Kllrh5okrXU+X6FKtZ4eWRvrxn31u2b3tKj7vKlUx+d3nIkbtbiCft/zDMk79Y9Se878LNbApc+OdYkvafL1lf7+89ztXtfGJPl1opZ1UrdXZEmew9jW95f5rTfM7oEsM0MYJtBn9imcu8HyDbyf45t6oV1DO0a2aJjRGq2KeIM8i/i9C9cOADljT8uBjjNRWf0vH/JueVwZvsYKH06lQuLaBvaxbd83WDf4Lo1ivk7ywfmKxxYqGi+cmUrBH7akbv7/IkTdUO7dA9rGfqXBHV3g9xyb1LPZQPLl5q7eueDajOzXgrq7uM4FVClYY/jeZLmijGPbpV8l5i99+x3N/r0DTiSVHJ4UNGnr88UL5TuxNiYd4Xutx3UxXv05fXVLq8f9KygwrbFd+9auFrTJwlXqvTJtH58j3MpPoPSlq3Q+XC/HA3cjg2oWfzI24svhz8oTa6dvNjijefIqnOiS7wI+/bulWFbRM0Nkb3uaDcq3l3c4cnJNtH21+n293Hf2PWqo9rbkHcP4oKmFku+l2ZvC5+QhmeUegNOFq9a9Wr9xALNvUeNlcudbXovRskyyREn+4cOH1fDp4xf/NgxH4LLB4cXXhlcdGnYwtA3hcqt9NxePOiK64in3kOu1fufBchbzzVci1xAIQqkuqIPevZhmg9Uv2fsYPzj/bDu/GM7lLIn/4Wf/fSdJqu92/r3zHm1xtrR+dgFisqekuKC5ESqlD0wk0qwlaAcGKUwlgIqs6qJk0fs4r3zbp16+y+aVDXWq2s4an2+rDiJb/ra+OA4zZ9vD4Z4raj9LnyBW+Sn76c2UYa8x82yGq7LdSyN7ubPMo96pxzUH8Lca798TorFN7MTIs7brOxmnOQ9XNio8TltueGjmNj+n0FBD2NeT54wN5PTp/PixTIfE96shzUuy7Wjm0PqXVUkVY90uR1VfSzZkKkp8k382AclnUa3OO0vP5cdK7dTzv+5LKW1b1ES70pduRVPJ9jV/9/Q92f6m49/Wdaf9TwXVbLm12dheWnLc4u3XNvzZcu7E2s/hcn9tvl44pqWy579c+xr0yTOblJI5jrlYJtqJFmzaYftQTUPPyXJmXk9Bgc/TkQtoASyuGf6H2BQXS1421U+oip9EXoxNTCdL2jpZGBiYg4qnSyB3AHofGEUnITKmzvmeb/Xn3DyKpQ4cc7DLvjAr9Uiu3SMdgv5B51ofmtnfNPTcJLGtokpD+QDWnYd8r5Yz/rjfem+7uMrrq7LLEirUE97sW37+9adZ9+t+iu0hDtSSVP/vMPNMBbpsq25KbleIbfvfry3f37z8Yb79T5M5lO+HpjHESaX4X725oGyGP3abaosW8Kis2SS/zfU2Ly7yqLqa1lewh57KOZGm7lO6Um+V3KWnDVl/+bm5FU9eGPXP31eIV+8lr9EUoLRvEvNftpKMRmu3ff0WwQCNv3cKtWb8051tvCP0wLXW/m+NJUVmx2bWrXoTALbG9YNbcbbf0yJbnFsiWidkrdBXsfjTP4c5wdZL+rV+rIh5U0TowYwRFSw59Ah0f0SYOOEDoCKMoL6VAxIpSfWwlESrkGEiYVHjoshmKGUIYnBmcERtWuG0a/DUkBN8RU0PFQTsFuwb2EiOyNfT4Fr7/vikL32nKy6/3cEBrfKvLWcuH1xGPe9nm3W0hd/r1l+cvvGQEXpfI7MumzmRUpub3O25NYo7XC73PK5l38fe5fZwdd1LwtiXedPunTm3N2+Aw/3a52teXNyndHV9p2nk4+YXZRQ3F92z3rWZunieYodN7ZsEQrp+TLnUKrXLA21OQld/NbHhVMrPHafX9ts5b8hKeKewcuXlrKPOz/dsmz8KazYk9KQzMYy7dMsJmf9areOXf+Zbqb+9Lp3i7lk8mbWPJ4zc+9oJNZ4fBSfI6howSTTvobt6DSjHU8djgXb7l3Zee9FmnnvF6Vpc85sKA8JtLpW5LJJ+ZthE8t6YCG1momR0aCxfQB7ZSh9RcQY94LGWwYi8PjWYDRkZ2YFr14GpQJoZHIyG/IgD6sDXYPgcRvyGSDLihooIzSyGALT2Pd+L/ZG74n3tnLMCtjQuf+vhv/ErQYpSFp4DMMMQhZoNWgw+DJkMiQzFDHkg0fm0xhKGBQYQhgqGQqAvHSgeCKQlcFQuVCtQQVn9VpSWZCfXpRYkFGpgFa8sTQxMijsf7YjUpLBSmSWVIfvuc9TN8yZ7LDoFZ9xOMs7i2K3P382rpv5/oHB47qur6+/MFd/vRrz82vJ3AbuvM231ukz57EUvGK+9k28U/dAy1TzpeftWmLD+SpP3pC8sf+vcfe8O5sVFm13e72zbv7b9Qfsjr3a73L/ouOeHy9FJLu8P05mdD0fb8zTXb+uZ7Fz74k/fv+T1046fNZQPbR4S8L2iSzfT/KWrfOoWMc0q+HUuokmZmrHnqXwLOhjOpkrX7uuLsz0yGXhmk1OSlNnnq/yKyhbvE77qNLzquLrsQv6F74P9zdk0hYoc/k1xU0maYpwdX/NkxblB4tn+5mzHPNJW/Vi6a2lEcq1nQYX5UUWNjHJGzQxSSPiiM2wiYkHKMRB9ySKXiOhdDDYoUl0QayBBHJK5EbMAjEC7YTLsBryA6taC0MDI2BFa2RpbBqFkRCZ/qvw3d+W2BurF2/Q4Sr1df2DNz/QyixQErk//bAXh+79HSell91UZD3O8yatTeW/E9N55w97TyxUKJv2aM/DyX1CDo/UtBYtm9id2CPx84zWxgCp9h/VE18FH3V4sVs3tv+cy6SUvLAEVSfu421MDY7vlGZWHzWqCniX0/Hkl5n412Pdk5JkQ2ZdeSostPDa3HXf/4dbMbu/vPou4nOanWO6d9z2fXtvtuo+Cd9xYuLqpMIs++XCHIfOa58pvTezq7KioHmt26xDm5s7/dyttJuDFY1W/Ht13L6kjOnAulVFwbE7Mo7XvTa0zZil3vB5C9uG55d3COo0XcrZv/5+4aYXzUkrtjGWGdzicwjeFM36+fsWsxTWYEXR7nS3PIGs3EjhoLwtvAwAgfW2Aw0KZW5kc3RyZWFtDQplbmRvYmoNCjE4IDAgb2JqDQo8PC9UeXBlL1hSZWYvU2l6ZSAxOC9XWyAxIDQgMl0gL1Jvb3QgMSAwIFIvSW5mbyA4IDAgUi9JRFs8REUwMjI4M0E3RkU4QTM0NDg1NERENUI3MzdEQkM4QUU+PERFMDIyODNBN0ZFOEEzNDQ4NTRERDVCNzM3REJDOEFFPl0gL0ZpbHRlci9GbGF0ZURlY29kZS9MZW5ndGggNzU+Pg0Kc3RyZWFtDQp4nGNgAIL//xmBpCADA4iqgVBbwBTjJjDFtBJMMQeCKRYHCFUKlACq5GdgglDMEIoFQjFCKKgSVqAGVj+wPrazYIp9BQMDAGJaCAQNCmVuZHN0cmVhbQ0KZW5kb2JqDQp4cmVmDQowIDE5DQowMDAwMDAwMDA5IDY1NTM1IGYNCjAwMDAwMDAwMTcgMDAwMDAgbg0KMDAwMDAwMDEyNCAwMDAwMCBuDQowMDAwMDAwMTgwIDAwMDAwIG4NCjAwMDAwMDA0MzQgMDAwMDAgbg0KMDAwMDAwMDY4MSAwMDAwMCBuDQowMDAwMDAwODQ5IDAwMDAwIG4NCjAwMDAwMDEwODggMDAwMDAgbg0KMDAwMDAwMTE0MSAwMDAwMCBuDQowMDAwMDAwMDEwIDY1NTM1IGYNCjAwMDAwMDAwMTEgNjU1MzUgZg0KMDAwMDAwMDAxMiA2NTUzNSBmDQowMDAwMDAwMDEzIDY1NTM1IGYNCjAwMDAwMDAwMTQgNjU1MzUgZg0KMDAwMDAwMDAxNSA2NTUzNSBmDQowMDAwMDAwMDAwIDY1NTM1IGYNCjAwMDAwMDE3NDEgMDAwMDAgbg0KMDAwMDAwMTk2MCAwMDAwMCBuDQowMDAwMDgyMTk4IDAwMDAwIG4NCnRyYWlsZXINCjw8L1NpemUgMTkvUm9vdCAxIDAgUi9JbmZvIDggMCBSL0lEWzxERTAyMjgzQTdGRThBMzQ0ODU0REQ1QjczN0RCQzhBRT48REUwMjI4M0E3RkU4QTM0NDg1NERENUI3MzdEQkM4QUU+XSA+Pg0Kc3RhcnR4cmVmDQo4MjQ3Mg0KJSVFT0YNCnhyZWYNCjAgMA0KdHJhaWxlcg0KPDwvU2l6ZSAxOS9Sb290IDEgMCBSL0luZm8gOCAwIFIvSURbPERFMDIyODNBN0ZFOEEzNDQ4NTRERDVCNzM3REJDOEFFPjxERTAyMjgzQTdGRThBMzQ0ODU0REQ1QjczN0RCQzhBRT5dIC9QcmV2IDgyNDcyL1hSZWZTdG0gODIxOTg+Pg0Kc3RhcnR4cmVmDQo4MzAwOA0KJSVFT0Y='; diff --git a/x-pack/test/api_integration/apis/file_upload/preview_tika_contents.ts b/x-pack/test/api_integration/apis/file_upload/preview_tika_contents.ts new file mode 100644 index 0000000000000..b961ca8f3225b --- /dev/null +++ b/x-pack/test/api_integration/apis/file_upload/preview_tika_contents.ts @@ -0,0 +1,49 @@ +/* + * 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 { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; +import { pdfBase64 } from './pdf_base64'; + +export default ({ getService }: FtrProviderContext) => { + const supertest = getService('supertest'); + + async function runRequest(base64File: string, expectedResponseCode: number = 200) { + const { body } = await supertest + .post(`/internal/file_upload/preview_tika_contents`) + .set('kbn-xsrf', 'kibana') + .set(ELASTIC_HTTP_VERSION_HEADER, '1') + .send({ base64File }) + .expect(expectedResponseCode); + + return body; + } + const expectedResponse = { + date: '2010-12-01T13:33:24Z', + content_type: 'application/pdf', + author: 'John', + format: 'application/pdf; version=1.5', + modified: '2010-12-01T13:33:24Z', + language: 'en', + creator_tool: 'Microsoft® Word 2010', + content: 'This is a test PDF file', + content_length: 28, + }; + + describe('POST /internal/file_upload/preview_tika_content', () => { + it('should return the text content from the file', async () => { + const resp = await runRequest(pdfBase64); + + expect(resp).to.eql(expectedResponse); + }); + + it('should fail to return text when bad data is sent', async () => { + await runRequest('bad data', 500); + }); + }); +};