From 0194407c7c4de028c5a05c6f1a62f45c52309334 Mon Sep 17 00:00:00 2001 From: Paulo Gustavo Veiga Date: Fri, 13 Jan 2023 22:33:17 -0800 Subject: [PATCH] Add string validation --- docker-compose.snapshots.update.yml | 2 +- jsconfig.json | 2 +- packages/editor/tsconfig.json | 4 +- .../mindplot/src/components/ConnectionLine.ts | 14 +- packages/mindplot/src/components/Designer.ts | 10 +- .../mindplot/src/components/EmojiCharIcon.ts | 28 ++- packages/mindplot/src/components/Icon.ts | 2 +- packages/mindplot/src/components/IconGroup.ts | 16 +- .../src/components/IconGroupRemoveTip.ts | 1 + packages/mindplot/src/components/ImageIcon.ts | 5 +- .../src/components/MindplotWebComponent.ts | 21 +- .../src/components/MultilineTextEditor.ts | 22 ++- packages/mindplot/src/components/NodeGraph.ts | 5 +- .../components/RelationshipControlPoints.ts | 13 +- .../src/components/RelationshipPivot.ts | 5 +- .../src/components/RestPersistenceManager.ts | 1 + .../mindplot/src/components/ScreenManager.ts | 2 +- .../components/StandaloneActionDispatcher.ts | 1 - packages/mindplot/src/components/Topic.ts | 31 +-- packages/mindplot/src/components/Workspace.ts | 9 +- .../components/commands/DragTopicCommand.ts | 14 +- .../commands/GenericFunctionCommand.ts | 21 +- .../commands/RemoveFeatureFromTopicCommand.ts | 5 +- .../src/components/export/FreemindExporter.ts | 4 +- .../components/export/freemind/Arrowlink.ts | 36 ++-- .../src/components/export/freemind/Cloud.ts | 9 +- .../src/components/export/freemind/Edge.ts | 42 +++- .../src/components/export/freemind/Font.ts | 10 +- .../src/components/export/freemind/Hook.ts | 12 +- .../src/components/export/freemind/Icon.ts | 9 +- .../src/components/export/freemind/Map.ts | 10 +- .../src/components/export/freemind/Node.ts | 72 +++---- .../components/export/freemind/Parameters.ts | 4 +- .../components/export/freemind/Richcontent.ts | 14 +- .../src/components/import/FreemindImporter.ts | 181 +++++++++--------- .../components/import/WisemappingImporter.ts | 9 +- .../components/layout/EventBusDispatcher.ts | 25 +-- .../mindplot/src/components/layout/Node.ts | 35 ++-- .../src/components/layout/RootedTreeSet.ts | 13 +- .../src/components/model/NodeModel.ts | 3 +- .../persistence/XMLSerializerBeta.ts | 7 - .../persistence/XMLSerializerTango.ts | 5 +- .../src/components/widget/LineTopicShape.ts | 8 +- .../playground/layout/SymmetricTestSuite.js | 82 ++++---- .../expected/anonymity_on_the_edge.wxml | 2 +- .../test/unit/import/expected/bug3.wxml | 4 +- .../test/unit/import/expected/enc.wxml | 9 +- .../import/expected/freeMind_resources.wxml | 22 +-- .../expected/writing_an_essay_with.wxml | 82 ++++---- packages/mindplot/tsconfig.json | 11 +- .../registration-page.snap.png | Bin 91662 -> 79647 bytes packages/webapp/public/index.html | 2 +- packages/webapp/src/app.tsx | 31 ++- .../webapp/src/classes/app-config/index.ts | 4 +- packages/webapp/src/classes/app-i18n/index.ts | 4 +- .../client/cache-decorator-client/index.ts | 143 -------------- packages/webapp/src/classes/client/index.ts | 4 +- .../src/classes/client/mock-client/index.ts | 4 +- .../HOCs/withSessionExpirationHandling.tsx | 32 ---- .../common}/client-health-sentinel/index.tsx | 0 .../components/common/csrf-input/index.tsx | 10 + .../components/common/google-button/index.tsx | 17 ++ .../src/components/common/separator/index.tsx | 17 ++ .../src/components/common/separator/style.ts | 2 +- .../src/components/editor-page/index.tsx | 27 ++- .../components/forgot-password-page/index.tsx | 4 +- .../src/components/login-page/index.tsx | 11 +- .../action-dispatcher/import-dialog/index.tsx | 6 +- .../action-dispatcher/label-dialog/index.tsx | 65 ++++--- .../webapp/src/components/maps-page/index.tsx | 25 ++- .../registration-callback/index.tsx | 13 +- .../components/registration-page/index.tsx | 7 +- packages/webapp/src/redux/clientSlice.ts | 8 +- packages/webapp/src/tsconfig.json | 18 -- packages/webapp/src/utils.ts | 2 +- packages/webapp/tsconfig.json | 42 ++-- 76 files changed, 697 insertions(+), 755 deletions(-) delete mode 100644 packages/webapp/src/classes/client/cache-decorator-client/index.ts delete mode 100644 packages/webapp/src/components/HOCs/withSessionExpirationHandling.tsx rename packages/webapp/src/{classes/client => components/common}/client-health-sentinel/index.tsx (100%) create mode 100644 packages/webapp/src/components/common/csrf-input/index.tsx delete mode 100644 packages/webapp/src/tsconfig.json diff --git a/docker-compose.snapshots.update.yml b/docker-compose.snapshots.update.yml index fe41036a..9b158bbc 100644 --- a/docker-compose.snapshots.update.yml +++ b/docker-compose.snapshots.update.yml @@ -1,7 +1,7 @@ version: '3' services: e2e: - image: cypress/included:12.3.0 + image: cypress/included:12.2.0 container_name: wisemapping-integration-tests entrypoint: '/bin/sh -c "yarn install && yarn build && yarn test:integration"' working_dir: /e2e diff --git a/jsconfig.json b/jsconfig.json index 45ef1f1e..bc23d29d 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "baseUrl": ".", + "baseUrl": "." "module": "ES6", }, "exclude": ["node_modules"] diff --git a/packages/editor/tsconfig.json b/packages/editor/tsconfig.json index 5d66567d..7e16ac6a 100644 --- a/packages/editor/tsconfig.json +++ b/packages/editor/tsconfig.json @@ -3,7 +3,7 @@ "src/**/*" ], "compilerOptions": { - "jsx": "react", + "jsx": "react-jsx", "outDir": "./dist/", "sourceMap": true, "noImplicitAny": false, @@ -13,8 +13,8 @@ "target": "es6", "allowJs": true, "esModuleInterop": true, - "declaration": true, "strictNullChecks": false, + "declaration": true, "rootDirs": [ "src", ], diff --git a/packages/mindplot/src/components/ConnectionLine.ts b/packages/mindplot/src/components/ConnectionLine.ts index f2e43b55..182efdc4 100644 --- a/packages/mindplot/src/components/ConnectionLine.ts +++ b/packages/mindplot/src/components/ConnectionLine.ts @@ -35,8 +35,6 @@ class ConnectionLine { protected _sourceTopic: Topic; - protected _lineType: LineType; - protected _line: Line; private _type: LineType; @@ -50,7 +48,7 @@ class ConnectionLine { this._sourceTopic = sourceNode; this._type = type; this._line = this.createLine(type); - this.updateColor(); + this._color = this.updateColor(); } private _getCtrlPoints(sourceNode: Topic, targetNode: Topic) { @@ -64,7 +62,6 @@ class ConnectionLine { } protected createLine(lineType: LineType): ConnectionLine { - this._lineType = lineType; let line: ConnectionLine; switch (lineType) { case LineType.POLYLINE_MIDDLE: @@ -88,7 +85,7 @@ class ConnectionLine { return line; } - private updateColor(): void { + private updateColor(): string { // In case that the main topic has changed the color, overwrite the main topic definiton. let color = this._targetTopic.getConnectionColor(); if (this._targetTopic.isCentralTopic()) { @@ -96,7 +93,7 @@ class ConnectionLine { } this._color = color; - switch (this._lineType) { + switch (this._type) { case LineType.POLYLINE_MIDDLE: this._line.setStroke(1, 'solid', color, 1); break; @@ -112,8 +109,9 @@ class ConnectionLine { this._line.setFill(color, 1); break; default: - throw new Error(`Unexpected line type. ${this._lineType}`); + throw new Error(`Unexpected line type. ${this._type}`); } + return color; } setVisibility(value: boolean, fade = 0): void { @@ -207,7 +205,7 @@ class ConnectionLine { } getLineType(): number { - return this._lineType; + return this._type; } getLine(): Line { diff --git a/packages/mindplot/src/components/Designer.ts b/packages/mindplot/src/components/Designer.ts index a3c557e4..b23d4e4f 100644 --- a/packages/mindplot/src/components/Designer.ts +++ b/packages/mindplot/src/components/Designer.ts @@ -58,7 +58,7 @@ import { TopicShapeType } from './model/INodeModel'; import { LineType } from './ConnectionLine'; class Designer extends Events { - private _mindmap: Mindmap; + private _mindmap: Mindmap | null; private _options: DesignerOptions; @@ -70,13 +70,13 @@ class Designer extends Events { _eventBussDispatcher: EventBusDispatcher; - private _dragManager: DragManager; + private _dragManager!: DragManager; private _relPivot: RelationshipPivot; private _clipboard: NodeModel[]; - private _cleanScreen: () => void; + private _cleanScreen!: () => void; constructor(options: DesignerOptions, divElement: JQuery) { super(); @@ -133,6 +133,7 @@ class Designer extends Events { // Hack: There are static reference to designer variable. Needs to be reviewed. globalThis.designer = this; + this._mindmap = null; } private _registerWheelEvents(): void { @@ -539,7 +540,6 @@ class Designer extends Events { } loadMap(mindmap: Mindmap): Promise { - $assert(mindmap, 'mindmapModel can not be null'); this._mindmap = mindmap; this._workspace.enableQueueRender(true); @@ -587,7 +587,7 @@ class Designer extends Events { } getMindmap(): Mindmap { - return this._mindmap; + return this._mindmap!; } undo(): void { diff --git a/packages/mindplot/src/components/EmojiCharIcon.ts b/packages/mindplot/src/components/EmojiCharIcon.ts index 1df6ef33..e90d79a9 100644 --- a/packages/mindplot/src/components/EmojiCharIcon.ts +++ b/packages/mindplot/src/components/EmojiCharIcon.ts @@ -16,7 +16,6 @@ * limitations under the License. */ import { Text, Group, ElementClass, Point } from '@wisemapping/web2d'; -import { $assert } from '@wisemapping/core-js'; import Icon from './Icon'; import IconGroup from './IconGroup'; @@ -28,17 +27,15 @@ import ActionDispatcher from './ActionDispatcher'; class EmojiCharIcon implements Icon { private element: ElementClass; - private group: IconGroup; + private _group: IconGroup | null; - private iconModel: SvgIconModel; + private _iconModel: SvgIconModel; - private topic: Topic; + private _topic: Topic; constructor(topic: Topic, iconModel: SvgIconModel, readOnly: boolean) { - $assert(iconModel, 'iconModel can not be null'); - $assert(topic, 'topic can not be null'); - this.iconModel = iconModel; - this.topic = topic; + this._iconModel = iconModel; + this._topic = topic; this.element = new Group({ width: 90, @@ -57,6 +54,7 @@ class EmojiCharIcon implements Icon { if (!readOnly) { this.element.setCursor('pointer'); } + this._group = null; } getElement(): ElementClass { @@ -64,19 +62,19 @@ class EmojiCharIcon implements Icon { } setGroup(group: IconGroup) { - this.group = group; + this._group = group; } getGroup(): IconGroup { - return this.group; + return this._group!; } getSize(): SizeType { - return this.group.getSize(); + return this._group!.getSize(); } getPosition(): Point { - return this.group.getPosition(); + return this._group!.getPosition(); } addEvent(type: string, fnc: (e: object) => void): void { @@ -85,12 +83,12 @@ class EmojiCharIcon implements Icon { remove() { const actionDispatcher = ActionDispatcher.getInstance(); - const featureId = this.iconModel.getId(); - actionDispatcher.removeFeatureFromTopic(this.topic.getId(), featureId); + const featureId = this._iconModel.getId(); + actionDispatcher.removeFeatureFromTopic(this._topic.getId(), featureId); } getModel(): SvgIconModel { - return this.iconModel; + return this._iconModel; } } diff --git a/packages/mindplot/src/components/Icon.ts b/packages/mindplot/src/components/Icon.ts index 6e37dd31..4de70fe2 100644 --- a/packages/mindplot/src/components/Icon.ts +++ b/packages/mindplot/src/components/Icon.ts @@ -8,7 +8,7 @@ interface Icon { setGroup(group: IconGroup): Group; - getGroup(): IconGroup; + getGroup(): IconGroup | null; getSize(): SizeType; diff --git a/packages/mindplot/src/components/IconGroup.ts b/packages/mindplot/src/components/IconGroup.ts index af6c7800..b7da90e3 100644 --- a/packages/mindplot/src/components/IconGroup.ts +++ b/packages/mindplot/src/components/IconGroup.ts @@ -36,14 +36,11 @@ class IconGroup { private _removeTip: IconGroupRemoveTip; - private _iconSize: SizeType; + private _iconSize: SizeType | null; private _topicId: number; constructor(topicId: number, iconSize: number) { - $assert($defined(topicId), 'topicId can not be null'); - $assert($defined(iconSize), 'iconSize can not be null'); - this._topicId = topicId; this._icons = []; this._group = new Group({ @@ -57,6 +54,7 @@ class IconGroup { this._removeTip = new IconGroupRemoveTip(this._group); this.seIconSize(iconSize, iconSize); this._registerListeners(); + this._iconSize = null; } setPosition(x: number, y: number): void { @@ -142,8 +140,6 @@ class IconGroup { } private _removeIcon(icon: Icon) { - $assert(icon, 'icon can not be null'); - this._removeTip.close(0); this._group.removeChild(icon.getElement()); @@ -174,10 +170,12 @@ class IconGroup { } private _resize(iconsLength: number) { - this._group.setSize(iconsLength * this._iconSize.width, this._iconSize.height); + if (this._iconSize) { + this._group.setSize(iconsLength * this._iconSize.width, this._iconSize.height); - const iconSize = ImageIcon.SIZE + IconGroup.ICON_PADDING * 2; - this._group.setCoordSize(iconsLength * iconSize, iconSize); + const iconSize = ImageIcon.SIZE + IconGroup.ICON_PADDING * 2; + this._group.setCoordSize(iconsLength * iconSize, iconSize); + } } private _positionIcon(icon: Icon, order: number) { diff --git a/packages/mindplot/src/components/IconGroupRemoveTip.ts b/packages/mindplot/src/components/IconGroupRemoveTip.ts index 82886d54..04562077 100644 --- a/packages/mindplot/src/components/IconGroupRemoveTip.ts +++ b/packages/mindplot/src/components/IconGroupRemoveTip.ts @@ -14,6 +14,7 @@ class IconGroupRemoveTip { constructor(group: Group) { $assert(group, 'group can not be null'); this._group = group; + this._activeIcon = null; } show(topicId: number, icon: ImageIcon) { diff --git a/packages/mindplot/src/components/ImageIcon.ts b/packages/mindplot/src/components/ImageIcon.ts index 5d403b20..334072f0 100644 --- a/packages/mindplot/src/components/ImageIcon.ts +++ b/packages/mindplot/src/components/ImageIcon.ts @@ -25,13 +25,14 @@ import Icon from './Icon'; abstract class ImageIcon implements Icon { private _image: Image; - private _group: IconGroup; + private _group: IconGroup | null; constructor(url: string) { $assert(url, 'image url can not be null'); this._image = new Image(); this._image.setHref(url); this._image.setSize(ImageIcon.SIZE, ImageIcon.SIZE); + this._group = null; } getElement(): ElementClass { @@ -42,7 +43,7 @@ abstract class ImageIcon implements Icon { this._group = group; } - getGroup(): IconGroup { + getGroup(): IconGroup | null { return this._group; } diff --git a/packages/mindplot/src/components/MindplotWebComponent.ts b/packages/mindplot/src/components/MindplotWebComponent.ts index 22dbd926..721081d5 100644 --- a/packages/mindplot/src/components/MindplotWebComponent.ts +++ b/packages/mindplot/src/components/MindplotWebComponent.ts @@ -43,9 +43,9 @@ export type MindplotWebComponentInterface = { class MindplotWebComponent extends HTMLElement { private _shadowRoot: ShadowRoot; - private _designer: Designer; + private _designer: Designer | null; - private saveRequired: boolean; + private _saveRequired: boolean; private _isLoaded: boolean; @@ -62,12 +62,15 @@ class MindplotWebComponent extends HTMLElement { wrapper.setAttribute('id', 'mindplot'); this._shadowRoot.appendChild(wrapper); + this._isLoaded = false; + this._saveRequired = false; + this._designer = null; } /** * @returns the designer */ - getDesigner(): Designer { + getDesigner(): Designer | null { return this._designer; } @@ -124,24 +127,24 @@ class MindplotWebComponent extends HTMLElement { } setSaveRequired(value: boolean) { - this.saveRequired = value; + this._saveRequired = value; } getSaveRequired() { - return this.saveRequired; + return this._saveRequired; } loadMap(id: string): Promise { const instance = PersistenceManager.getInstance(); - return instance.load(id).then((mindmap) => this._designer.loadMap(mindmap)); + return instance.load(id).then((mindmap) => this._designer!.loadMap(mindmap)); } save(saveHistory: boolean) { if (!saveHistory && !this.getSaveRequired()) return; console.log('Saving...'); // Load map content ... - const mindmap = this._designer.getMindmap(); - const mindmapProp = this._designer.getMindmapProperties(); + const mindmap = this._designer!.getMindmap(); + const mindmapProp = this._designer!.getMindmapProperties(); // Display save message .. if (saveHistory) { @@ -166,7 +169,7 @@ class MindplotWebComponent extends HTMLElement { } unlockMap() { - const mindmap = this._designer.getMindmap(); + const mindmap = this._designer!.getMindmap(); const persistenceManager = PersistenceManager.getInstance(); // If the map could not be loaded, partial map load could happen. diff --git a/packages/mindplot/src/components/MultilineTextEditor.ts b/packages/mindplot/src/components/MultilineTextEditor.ts index 6a97e41e..c942a48d 100644 --- a/packages/mindplot/src/components/MultilineTextEditor.ts +++ b/packages/mindplot/src/components/MultilineTextEditor.ts @@ -256,31 +256,35 @@ class MultitTextEditor { // eslint-disable-next-line no-use-before-define private static instance: MultitTextEditor = new MultitTextEditor(); - private component: EditorComponent | null; + private _component: EditorComponent | null; + + constructor() { + this._component = null; + } static getInstance(): MultitTextEditor { return MultitTextEditor.instance; } isActive(): boolean { - return this.component !== null; + return this._component !== null; } show(topic: Topic, textOverwrite?: string): void { // Is it active ? - if (this.component) { + if (this._component) { console.error('Editor was already displayed. Please, clouse it'); - this.component.close(false); + this._component.close(false); } // Create a new instance - this.component = new EditorComponent(topic); - this.component.show(textOverwrite); + this._component = new EditorComponent(topic); + this._component.show(textOverwrite); } close(update: boolean): void { - if (this.component) { - this.component.close(update); - this.component = null; + if (this._component) { + this._component.close(update); + this._component = null; } } } diff --git a/packages/mindplot/src/components/NodeGraph.ts b/packages/mindplot/src/components/NodeGraph.ts index 4e006cf8..15bdb493 100644 --- a/packages/mindplot/src/components/NodeGraph.ts +++ b/packages/mindplot/src/components/NodeGraph.ts @@ -46,7 +46,7 @@ abstract class NodeGraph { this._options = options; this._mouseEvents = true; - this.setModel(nodeModel); + this._model = nodeModel; this._onFocus = false; this._size = { width: 50, height: 20 }; } @@ -70,7 +70,6 @@ abstract class NodeGraph { } get2DElement(): ElementClass { - $assert(this._elem2d, 'NodeGraph has not been initialized properly'); return this._elem2d; } @@ -118,7 +117,7 @@ abstract class NodeGraph { return this._model; } - setModel(model: NodeModel) { + setModel(model: NodeModel): void { $assert(model, 'Model can not be null'); this._model = model; } diff --git a/packages/mindplot/src/components/RelationshipControlPoints.ts b/packages/mindplot/src/components/RelationshipControlPoints.ts index 180592ed..30077850 100644 --- a/packages/mindplot/src/components/RelationshipControlPoints.ts +++ b/packages/mindplot/src/components/RelationshipControlPoints.ts @@ -36,7 +36,7 @@ class ControlPivotLine { private _pivotType: PivotType; - private _workspace: Workspace; + private _workspace: Workspace | null; private _relationship: Relationship; @@ -93,6 +93,9 @@ class ControlPivotLine { this._mouseMoveHandler = (e: MouseEvent) => this.mouseMoveHandler(e); this._mouseUpHandler = () => this.mouseUpHandler(); this._mouseDownHandler = (event: MouseEvent) => this.mouseDownHandler(event); + + this._isVisible = false; + this._workspace = null; } private mouseDownHandler(event: MouseEvent) { @@ -153,7 +156,7 @@ class ControlPivotLine { } private mouseMoveHandler(event: MouseEvent) { - const screen = this._workspace.getScreenManager(); + const screen = this._workspace!.getScreenManager(); const mousePosition = screen.getWorkspaceMousePosition(event); // Update relatioship position ... @@ -213,8 +216,6 @@ class RelationshipControlPoints { private _relationship: Relationship; - private _relationshipLinePositions: [PositionType, PositionType]; - constructor(relationship: Relationship) { this._relationship = relationship; const startControlLine = new ControlPivotLine( @@ -278,10 +279,6 @@ class RelationshipControlPoints { getControlPointPosition(pivotType: PivotType): PositionType { return this._pivotLines[pivotType].getPosition(); } - - getRelationshipPosition(index: number): PositionType { - return { ...this._relationshipLinePositions[index] }; - } } export default RelationshipControlPoints; diff --git a/packages/mindplot/src/components/RelationshipPivot.ts b/packages/mindplot/src/components/RelationshipPivot.ts index 3304a74c..b36793fd 100644 --- a/packages/mindplot/src/components/RelationshipPivot.ts +++ b/packages/mindplot/src/components/RelationshipPivot.ts @@ -32,7 +32,7 @@ class RelationshipPivot { private _onClickEvent: (event: MouseEvent) => void; - private _onTopicClick: (event: MouseEvent) => void; + private _onTopicClick: (event: MouseEvent, targetTopic: Topic) => void; private _sourceTopic: Topic | null; @@ -49,6 +49,7 @@ class RelationshipPivot { this._mouseMoveEvent = this.mouseMoveHandler.bind(this); this._onClickEvent = this.cleanOnMouseClick.bind(this); this._onTopicClick = this._connectOnFocus.bind(this); + this._sourceTopic = null; } start(sourceTopic: Topic, targetPos: Point) { @@ -156,7 +157,7 @@ class RelationshipPivot { return Shape.calculateRelationShipPointCoordinates(sourceTopic, point); } - private _connectOnFocus(event: string, targetTopic: Topic): void { + private _connectOnFocus(event: MouseEvent, targetTopic: Topic): void { const sourceTopic = this._sourceTopic; const mindmap = this._designer.getMindmap(); diff --git a/packages/mindplot/src/components/RestPersistenceManager.ts b/packages/mindplot/src/components/RestPersistenceManager.ts index 53cd9325..5e5e546b 100644 --- a/packages/mindplot/src/components/RestPersistenceManager.ts +++ b/packages/mindplot/src/components/RestPersistenceManager.ts @@ -39,6 +39,7 @@ class RESTPersistenceManager extends PersistenceManager { this.documentUrl = options.documentUrl; this.revertUrl = options.revertUrl; this.lockUrl = options.lockUrl; + this.onSave = false; } saveMapXml(mapId: string, mapXml: Document, pref: string, saveHistory: boolean, events): void { diff --git a/packages/mindplot/src/components/ScreenManager.ts b/packages/mindplot/src/components/ScreenManager.ts index 1ed35f81..75355424 100644 --- a/packages/mindplot/src/components/ScreenManager.ts +++ b/packages/mindplot/src/components/ScreenManager.ts @@ -52,6 +52,7 @@ class ScreenManager { event.preventDefault(); }, ); + this._scale = 1; } /** @@ -65,7 +66,6 @@ class ScreenManager { } setScale(scale: number) { - $assert(scale, 'Screen scale can not be null'); this._scale = scale; } diff --git a/packages/mindplot/src/components/StandaloneActionDispatcher.ts b/packages/mindplot/src/components/StandaloneActionDispatcher.ts index 5cff4d05..df3d0d7c 100644 --- a/packages/mindplot/src/components/StandaloneActionDispatcher.ts +++ b/packages/mindplot/src/components/StandaloneActionDispatcher.ts @@ -157,7 +157,6 @@ class StandaloneActionDispatcher extends ActionDispatcher { this.execute(command); } - /** */ changeBackgroundColorToTopic(topicsIds: number[], color: string | undefined) { const commandFunc = (topic: Topic, value: string | undefined) => { const result = topic.getBackgroundColor(); diff --git a/packages/mindplot/src/components/Topic.ts b/packages/mindplot/src/components/Topic.ts index 77dddac7..892ee3b6 100644 --- a/packages/mindplot/src/components/Topic.ts +++ b/packages/mindplot/src/components/Topic.ts @@ -67,11 +67,11 @@ abstract class Topic extends NodeGraph { private _text: Text | null; - private _iconsGroup: IconGroup; + private _iconsGroup!: IconGroup; - private _connector: ShirinkConnector; + private _connector!: ShirinkConnector; - private _outgoingLine: ConnectionLine | null; + private _outgoingLine!: ConnectionLine | null; constructor(model: NodeModel, options: NodeOption) { super(model, options); @@ -83,7 +83,7 @@ abstract class Topic extends NodeGraph { // Position a topic .... const pos = model.getPosition(); - if (pos != null && this.isCentralTopic()) { + if (pos && this.isCentralTopic()) { this.setPosition(pos); } @@ -121,7 +121,7 @@ abstract class Topic extends NodeGraph { protected redrawShapeType() { const oldInnerShape = this.getInnerShape(); - if (oldInnerShape != null) { + if (oldInnerShape) { this._removeInnerShape(); // Create a new one ... @@ -208,7 +208,7 @@ abstract class Topic extends NodeGraph { } getInnerShape(): ElementClass { - if (!$defined(this._innerShape)) { + if (!this._innerShape) { // Create inner box. this._innerShape = this._buildShape(TopicConfig.INNER_RECT_ATTRIBUTES, this.getShapeType()); @@ -285,16 +285,17 @@ abstract class Topic extends NodeGraph { private getOrBuildIconGroup(): Group { if (!this._iconsGroup) { - this._iconsGroup = this._buildIconGroup(); + const iconGroup = this._buildIconGroup(); const group = this.get2DElement(); - group.append(this._iconsGroup.getNativeElement()); - this._iconsGroup.moveToFront(); + group.append(iconGroup.getNativeElement()); + iconGroup.moveToFront(); + this._iconsGroup = iconGroup; } return this._iconsGroup; } - private getIconGroup(): IconGroup { + private getIconGroup(): IconGroup | null { return this._iconsGroup; } @@ -351,7 +352,7 @@ abstract class Topic extends NodeGraph { // Removing the icon from UI const iconGroup = this.getIconGroup(); - if ($defined(iconGroup)) { + if (iconGroup) { iconGroup.removeIconByModel(featureModel); } this.redraw(); @@ -837,7 +838,7 @@ abstract class Topic extends NodeGraph { setBranchVisibility(value: boolean): void { let current: Topic = this; let parent: Topic | null = this; - while (parent != null && !parent.isCentralTopic()) { + while (parent && !parent.isCentralTopic()) { current = parent; parent = current.getParent(); } @@ -896,8 +897,8 @@ abstract class Topic extends NodeGraph { const sourceParent = sourceTopic.getModel().getParent(); relationship.setVisibility( value && - (targetParent == null || !targetParent.areChildrenShrunken()) && - (sourceParent == null || !sourceParent.areChildrenShrunken()), + (!targetParent || !targetParent.areChildrenShrunken()) && + (!sourceParent || !sourceParent.areChildrenShrunken()), fade, ); }); @@ -1242,7 +1243,7 @@ abstract class Topic extends NodeGraph { // Force the repaint in case that the main topic color has changed. if (this.getParent()) { - this._connector.setColor(borderColor); + this._connector!.setColor(borderColor); if (this.getParent()?.isCentralTopic()) { this._outgoingLine?.redraw(); diff --git a/packages/mindplot/src/components/Workspace.ts b/packages/mindplot/src/components/Workspace.ts index 7d1f956a..0f45bab3 100644 --- a/packages/mindplot/src/components/Workspace.ts +++ b/packages/mindplot/src/components/Workspace.ts @@ -33,7 +33,7 @@ class Workspace { private _eventsEnabled: boolean; - private _visibleAreaSize: SizeType; + private _visibleAreaSize!: SizeType; private _renderQueue: Element2D[]; @@ -61,8 +61,9 @@ class Workspace { workspace.addItAsChildTo(divContainer); this.setZoom(zoom, true); - this._renderQueue = []; + this._eventsEnabled = false; + this._queueRenderEnabled = false; } private _adjustWorkspace(): void { @@ -163,11 +164,11 @@ class Workspace { } } - addEvent(type: string, listener: (event: Event) => void): void { + addEvent(type: string, listener: (event: MouseEvent) => void): void { this._workspace.addEvent(type, listener); } - removeEvent(type: string, listener: (event: Event) => void): void { + removeEvent(type: string, listener: (event: MouseEvent) => void): void { $assert(type, 'type can not be null'); $assert(listener, 'listener can not be null'); this._workspace.removeEvent(type, listener); diff --git a/packages/mindplot/src/components/commands/DragTopicCommand.ts b/packages/mindplot/src/components/commands/DragTopicCommand.ts index 7737291d..a0c0b6a6 100644 --- a/packages/mindplot/src/components/commands/DragTopicCommand.ts +++ b/packages/mindplot/src/components/commands/DragTopicCommand.ts @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { $assert, $defined } from '@wisemapping/core-js'; +import { $assert } from '@wisemapping/core-js'; import Point from '@wisemapping/web2d'; import Command from '../Command'; import CommandContext from '../CommandContext'; @@ -30,18 +30,10 @@ class DragTopicCommand extends Command { private _order: number; - /** - * @classdesc This command class handles do/undo of dragging a topic to a new position. - * @constructs - */ constructor(topicId: number, position: Point, order: number, parentTopic: Topic) { - $assert(topicId, 'topicId must be defined'); super(); - this._topicsId = topicId; - if ($defined(parentTopic)) { - this._parentId = parentTopic.getId(); - } + this._parentId = parentTopic ? parentTopic.getId() : null; this._position = position; this._order = order; @@ -59,7 +51,7 @@ class DragTopicCommand extends Command { const origPosition = topic.getPosition(); // Disconnect topic .. - if ($defined(origParentTopic)) { + if (origParentTopic) { commandContext.disconnect(topic); } diff --git a/packages/mindplot/src/components/commands/GenericFunctionCommand.ts b/packages/mindplot/src/components/commands/GenericFunctionCommand.ts index d61aa4e3..1d659df1 100644 --- a/packages/mindplot/src/components/commands/GenericFunctionCommand.ts +++ b/packages/mindplot/src/components/commands/GenericFunctionCommand.ts @@ -15,37 +15,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { $assert, $defined } from '@wisemapping/core-js'; import Command from '../Command'; import CommandContext from '../CommandContext'; import Topic from '../Topic'; -type CommandTypes = string | object | boolean | number | undefined; - -class GenericFunctionCommand extends Command { - private _value: CommandTypes; +class GenericFunctionCommand extends Command { + private _value: T; private _topicsIds: number[]; - private _commandFunc: (topic: Topic, value: CommandTypes) => CommandTypes; + private _commandFunc: (topic: Topic, value: T) => T; - private _oldValues: CommandTypes[]; + private _oldValues: T[]; private _applied: boolean; - constructor( - commandFunc: (topic: Topic, value: CommandTypes) => CommandTypes, - topicsIds: number[], - value: CommandTypes, - ) { - $assert(commandFunc, 'commandFunc must be defined'); - $assert($defined(topicsIds), 'topicsIds must be defined'); - + constructor(commandFunc: (topic: Topic, value: T) => T, topicsIds: number[], value: T) { super(); this._value = value; this._topicsIds = topicsIds; this._commandFunc = commandFunc; this._oldValues = []; + this._applied = false; } /** diff --git a/packages/mindplot/src/components/commands/RemoveFeatureFromTopicCommand.ts b/packages/mindplot/src/components/commands/RemoveFeatureFromTopicCommand.ts index 5ea780a2..cbb8eaf6 100644 --- a/packages/mindplot/src/components/commands/RemoveFeatureFromTopicCommand.ts +++ b/packages/mindplot/src/components/commands/RemoveFeatureFromTopicCommand.ts @@ -25,7 +25,7 @@ class RemoveFeatureFromTopicCommand extends Command { private _featureId: number; - private _oldFeature: FeatureModel; + private _oldFeature: FeatureModel | null; /** * @classdesc This command handles do/undo of removing a feature from a topic, e.g. an icon or @@ -38,6 +38,7 @@ class RemoveFeatureFromTopicCommand extends Command { super(); this._topicId = topicId; this._featureId = featureId; + this._oldFeature = null; } /** @@ -56,7 +57,7 @@ class RemoveFeatureFromTopicCommand extends Command { */ undoExecute(commandContext: CommandContext) { const topic = commandContext.findTopics([this._topicId])[0]; - topic.addFeature(this._oldFeature); + topic.addFeature(this._oldFeature!); } } diff --git a/packages/mindplot/src/components/export/FreemindExporter.ts b/packages/mindplot/src/components/export/FreemindExporter.ts index cddfe5e6..0b3f6a21 100644 --- a/packages/mindplot/src/components/export/FreemindExporter.ts +++ b/packages/mindplot/src/components/export/FreemindExporter.ts @@ -22,11 +22,11 @@ import Font from './freemind/Font'; class FreemindExporter extends Exporter { private mindmap: Mindmap; - private nodeMap: Map; + private nodeMap!: Map; private version: VersionNumber = FreemindConstant.SUPPORTED_FREEMIND_VERSION; - private objectFactory: ObjectFactory; + private objectFactory!: ObjectFactory; private static wisweToFreeFontSize: Map = new Map(); diff --git a/packages/mindplot/src/components/export/freemind/Arrowlink.ts b/packages/mindplot/src/components/export/freemind/Arrowlink.ts index 1acae11c..a3ceb5cb 100644 --- a/packages/mindplot/src/components/export/freemind/Arrowlink.ts +++ b/packages/mindplot/src/components/export/freemind/Arrowlink.ts @@ -1,43 +1,43 @@ export default class Arrowlink { - protected COLOR: string; + protected COLOR: string | undefined; - protected DESTINATION: string; + protected DESTINATION: string | undefined; - protected ENDARROW: string; + protected ENDARROW: string | undefined; - protected ENDINCLINATION: string; + protected ENDINCLINATION: string | undefined; - protected ID: string; + protected ID: string | undefined; - protected STARTARROW: string; + protected STARTARROW: string | undefined; - protected STARTINCLINATION: string; + protected STARTINCLINATION: string | undefined; - getColor(): string { + getColor(): string | undefined { return this.COLOR; } - getDestination(): string { + getDestination(): string | undefined { return this.DESTINATION; } - getEndarrow(): string { + getEndarrow(): string | undefined { return this.ENDARROW; } - getEndInclination(): string { + getEndInclination(): string | undefined { return this.ENDINCLINATION; } - getId(): string { + getId(): string | undefined { return this.ID; } - getStartarrow(): string { + getStartarrow(): string | undefined { return this.STARTARROW; } - getStartinclination(): string { + getStartinclination(): string | undefined { return this.STARTINCLINATION; } @@ -72,8 +72,12 @@ export default class Arrowlink { toXml(document: Document): HTMLElement { const arrowlinkElem = document.createElement('arrowlink'); - arrowlinkElem.setAttribute('DESTINATION', this.DESTINATION); - arrowlinkElem.setAttribute('STARTARROW', this.STARTARROW); + if (this.DESTINATION) { + arrowlinkElem.setAttribute('DESTINATION', this.DESTINATION); + } + if (this.STARTARROW) { + arrowlinkElem.setAttribute('STARTARROW', this.STARTARROW); + } if (this.COLOR) { arrowlinkElem.setAttribute('COLOR', this.COLOR); diff --git a/packages/mindplot/src/components/export/freemind/Cloud.ts b/packages/mindplot/src/components/export/freemind/Cloud.ts index 67986fec..52a4ca65 100644 --- a/packages/mindplot/src/components/export/freemind/Cloud.ts +++ b/packages/mindplot/src/components/export/freemind/Cloud.ts @@ -1,7 +1,7 @@ export default class Cloud { - protected COLOR: string; + protected COLOR: string | undefined; - getColor(): string { + getColor(): string | undefined { return this.COLOR; } @@ -12,8 +12,9 @@ export default class Cloud { toXml(document: Document): HTMLElement { // Set node attributes const cloudElem = document.createElement('cloud'); - - cloudElem.setAttribute('COLOR', this.COLOR); + if (this.COLOR) { + cloudElem.setAttribute('COLOR', this.COLOR); + } return cloudElem; } diff --git a/packages/mindplot/src/components/export/freemind/Edge.ts b/packages/mindplot/src/components/export/freemind/Edge.ts index b3a041f7..d97c3e70 100644 --- a/packages/mindplot/src/components/export/freemind/Edge.ts +++ b/packages/mindplot/src/components/export/freemind/Edge.ts @@ -1,19 +1,36 @@ +/* + * Copyright [2021] [wisemapping] + * + * Licensed under WiseMapping Public License, Version 1.0 (the "License"). + * It is basically the Apache License, Version 2.0 (the "License") plus the + * "powered by wisemapping" text requirement on every single page; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the license at + * + * http://www.wisemapping.org/license + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ export default class Edge { - protected COLOR: string; + protected COLOR: string | undefined; - protected STYLE: string; + protected STYLE: string | undefined; - protected WIDTH: string; + protected WIDTH: string | undefined; - getColor(): string { + getColor(): string | undefined { return this.COLOR; } - getStyle(): string { + getStyle(): string | undefined { return this.STYLE; } - getWidth(): string { + getWidth(): string | undefined { return this.WIDTH; } @@ -32,10 +49,15 @@ export default class Edge { toXml(document: Document): HTMLElement { // Set node attributes const edgeElem = document.createElement('edge'); - - edgeElem.setAttribute('COLOR', this.COLOR); - if (this.STYLE) edgeElem.setAttribute('STYLE', this.STYLE); - if (this.WIDTH) edgeElem.setAttribute('WIDTH', this.WIDTH); + if (this.COLOR) { + edgeElem.setAttribute('COLOR', this.COLOR); + } + if (this.STYLE) { + edgeElem.setAttribute('STYLE', this.STYLE); + } + if (this.WIDTH) { + edgeElem.setAttribute('WIDTH', this.WIDTH); + } return edgeElem; } diff --git a/packages/mindplot/src/components/export/freemind/Font.ts b/packages/mindplot/src/components/export/freemind/Font.ts index bcab647e..edeef44b 100644 --- a/packages/mindplot/src/components/export/freemind/Font.ts +++ b/packages/mindplot/src/components/export/freemind/Font.ts @@ -1,11 +1,11 @@ export default class Font { - protected BOLD?: string; + protected BOLD: string | undefined; - protected ITALIC?: string; + protected ITALIC: string | undefined; - protected NAME?: string; + protected NAME: string | undefined; - protected SIZE: string; + protected SIZE: string | undefined; getBold(): string | undefined { return this.BOLD; @@ -19,7 +19,7 @@ export default class Font { return this.NAME; } - getSize(): string { + getSize(): string | undefined { return this.SIZE; } diff --git a/packages/mindplot/src/components/export/freemind/Hook.ts b/packages/mindplot/src/components/export/freemind/Hook.ts index b9f868f6..cd131ab4 100644 --- a/packages/mindplot/src/components/export/freemind/Hook.ts +++ b/packages/mindplot/src/components/export/freemind/Hook.ts @@ -1,21 +1,21 @@ import Parameters from './Parameters'; export default class Hook { - protected PARAMETERS: Parameters; + protected PARAMETERS: Parameters | undefined; - protected TEXT: string; + protected TEXT: string | undefined; - protected NAME: string; + protected NAME: string | undefined; - getParameters(): Parameters { + getParameters(): Parameters | undefined { return this.PARAMETERS; } - getText(): string { + getText(): string | undefined { return this.TEXT; } - getName(): string { + getName(): string | undefined { return this.NAME; } diff --git a/packages/mindplot/src/components/export/freemind/Icon.ts b/packages/mindplot/src/components/export/freemind/Icon.ts index c819f960..3588d414 100644 --- a/packages/mindplot/src/components/export/freemind/Icon.ts +++ b/packages/mindplot/src/components/export/freemind/Icon.ts @@ -1,7 +1,7 @@ export default class Icon { - protected BUILTIN: string; + protected BUILTIN: string | undefined; - getBuiltin(): string { + getBuiltin(): string | undefined { return this.BUILTIN; } @@ -12,8 +12,9 @@ export default class Icon { toXml(document: Document): HTMLElement { // Set node attributes const iconElem = document.createElement('icon'); - - iconElem.setAttribute('BUILTIN', this.BUILTIN); + if (this.BUILTIN) { + iconElem.setAttribute('BUILTIN', this.BUILTIN); + } return iconElem; } diff --git a/packages/mindplot/src/components/export/freemind/Map.ts b/packages/mindplot/src/components/export/freemind/Map.ts index 672bfe6d..060efeee 100644 --- a/packages/mindplot/src/components/export/freemind/Map.ts +++ b/packages/mindplot/src/components/export/freemind/Map.ts @@ -8,15 +8,15 @@ import Node, { Choise } from './Node'; import Richcontent from './Richcontent'; export default class Freemap { - protected node: Node; + protected node: Node | undefined; - protected version: string; + protected version: string | undefined; - getNode(): Node { + getNode(): Node | undefined { return this.node; } - getVersion(): string { + getVersion(): string | undefined { return this.version; } @@ -38,7 +38,7 @@ export default class Freemap { document.appendChild(mapElem); // Create main node - const mainNode: Node = this.node; + const mainNode: Node = this.node!; mainNode.setCentralTopic(true); const mainNodeElem = mainNode.toXml(document); mapElem.appendChild(mainNodeElem); diff --git a/packages/mindplot/src/components/export/freemind/Node.ts b/packages/mindplot/src/components/export/freemind/Node.ts index 00e7717f..873db993 100644 --- a/packages/mindplot/src/components/export/freemind/Node.ts +++ b/packages/mindplot/src/components/export/freemind/Node.ts @@ -7,43 +7,43 @@ import Icon from './Icon'; import Richcontent from './Richcontent'; class Node { - protected arrowlinkOrCloudOrEdge: Array< - Arrowlink | Cloud | Edge | Font | Hook | Icon | Richcontent | this - >; + protected arrowlinkOrCloudOrEdge: + | Array + | undefined; - protected BACKGROUND_COLOR: string; + protected BACKGROUND_COLOR: string | undefined; - protected COLOR: string; + protected COLOR: string | undefined; - protected FOLDED: string; + protected FOLDED: string | undefined; - protected ID: string; + protected ID: string | undefined; - protected LINK: string; + protected LINK: string | undefined; - protected POSITION: string; + protected POSITION: string | undefined; - protected STYLE: string; + protected STYLE: string | undefined; - protected TEXT: string; + protected TEXT: string | undefined; - protected CREATED: string; + protected CREATED: string | undefined; - protected MODIFIED: string; + protected MODIFIED: string | undefined; - protected HGAP: string; + protected HGAP: string | undefined; - protected VGAP: string; + protected VGAP: string | undefined; - protected WCOORDS: string; + protected WCOORDS: string | undefined; - protected WORDER: string; + protected WORDER: string | undefined; - protected VSHIFT: string; + protected VSHIFT: string | undefined; - protected ENCRYPTED_CONTENT: string; + protected ENCRYPTED_CONTENT: string | undefined; - private centralTopic: boolean; + private centralTopic = false; getArrowlinkOrCloudOrEdge(): Array< /* eslint-disable */ @@ -57,67 +57,67 @@ class Node { return this.arrowlinkOrCloudOrEdge; } - getBackgroundColor(): string { + getBackgroundColor(): string | undefined { return this.BACKGROUND_COLOR; } - getColor(): string { + getColor(): string | undefined { return this.COLOR; } - getFolded(): string { + getFolded(): string | undefined { return this.FOLDED; } - getId(): string | null { + getId(): string | undefined { return this.ID; } - getLink(): string { + getLink(): string | undefined { return this.LINK; } - getPosition(): string { + getPosition(): string | undefined { return this.POSITION; } - getStyle(): string { + getStyle(): string | undefined { return this.STYLE; } - getText(): string { + getText(): string | undefined { return this.TEXT; } - getCreated(): string { + getCreated(): string | undefined { return this.CREATED; } - getModified(): string { + getModified(): string | undefined { return this.MODIFIED; } - getHgap(): string { + getHgap(): string | undefined { return this.HGAP; } - getVgap(): string { + getVgap(): string | undefined { return this.VGAP; } - getWcoords(): string { + getWcoords(): string | undefined { return this.WCOORDS; } - getWorder(): string { + getWorder(): string | undefined { return this.WORDER; } - getVshift(): string { + getVshift(): string | undefined { return this.VSHIFT; } - getEncryptedContent(): string { + getEncryptedContent(): string | undefined { return this.ENCRYPTED_CONTENT; } diff --git a/packages/mindplot/src/components/export/freemind/Parameters.ts b/packages/mindplot/src/components/export/freemind/Parameters.ts index aa67c2d2..f5c94124 100644 --- a/packages/mindplot/src/components/export/freemind/Parameters.ts +++ b/packages/mindplot/src/components/export/freemind/Parameters.ts @@ -1,7 +1,7 @@ export default class Parameters { - protected REMINDUSERAT: number; + protected REMINDUSERAT: number | undefined; - getReminduserat(): number { + getReminduserat(): number | undefined { return this.REMINDUSERAT; } diff --git a/packages/mindplot/src/components/export/freemind/Richcontent.ts b/packages/mindplot/src/components/export/freemind/Richcontent.ts index 9f041762..163a11a5 100644 --- a/packages/mindplot/src/components/export/freemind/Richcontent.ts +++ b/packages/mindplot/src/components/export/freemind/Richcontent.ts @@ -1,13 +1,13 @@ export default class Richcontent { - protected html: string; + protected html: string | undefined; - protected type: string; + protected type: string | undefined; - getHtml(): string { + getHtml(): string | undefined { return this.html; } - getType(): string { + getType(): string | undefined { return this.type; } @@ -22,9 +22,9 @@ export default class Richcontent { toXml(document: Document): HTMLElement { // Set node attributes const richcontentElem = document.createElement('richcontent'); - - richcontentElem.setAttribute('TYPE', this.type); - + if (this.type) { + richcontentElem.setAttribute('TYPE', this.type); + } if (this.html) { const htmlElement: DocumentFragment = document .createRange() diff --git a/packages/mindplot/src/components/import/FreemindImporter.ts b/packages/mindplot/src/components/import/FreemindImporter.ts index 42aa2ae0..2761fbb1 100644 --- a/packages/mindplot/src/components/import/FreemindImporter.ts +++ b/packages/mindplot/src/components/import/FreemindImporter.ts @@ -6,7 +6,6 @@ import NodeModel from '../model/NodeModel'; import FreemindConstant from '../export/freemind/FreemindConstant'; import FreemindMap from '../export/freemind/Map'; import FreemindNode, { Choise } from '../export/freemind/Node'; -import FreemindFont from '../export/freemind/Font'; import FreemindEdge from '../export/freemind/Edge'; import FreemindIcon from '../export/freemind/Icon'; import FreemindHook from '../export/freemind/Hook'; @@ -21,15 +20,15 @@ import XMLSerializerFactory from '../persistence/XMLSerializerFactory'; import { TopicShapeType } from '../model/INodeModel'; export default class FreemindImporter extends Importer { - private mindmap: Mindmap; + private mindmap!: Mindmap; private freemindInput: string; - private freemindMap: FreemindMap; + private freemindMap!: FreemindMap; - private nodesmap: Map; + private nodesmap!: Map; - private relationship: Array; + private relationship!: Array; private idDefault = 0; @@ -47,7 +46,7 @@ export default class FreemindImporter extends Importer { const freemindDoc = parser.parseFromString(this.freemindInput, 'application/xml'); this.freemindMap = new FreemindMap().loadFromDom(freemindDoc); - const version: string = this.freemindMap.getVersion(); + const version: string | undefined = this.freemindMap.getVersion(); if (!version || version.startsWith('freeplane')) { throw new Error( @@ -60,10 +59,10 @@ export default class FreemindImporter extends Importer { } } - const freeNode: FreemindNode = this.freemindMap.getNode(); + const freeNode = this.freemindMap.getNode()!; this.mindmap.setVersion(FreemindConstant.CODE_VERSION); - const wiseTopicId = this.getIdNode(this.freemindMap.getNode()); + const wiseTopicId = this.getIdNode(freeNode); const wiseTopic = this.mindmap.createNode('CentralTopic'); wiseTopic.setPosition(0, 0); wiseTopic.setId(wiseTopicId); @@ -158,7 +157,7 @@ export default class FreemindImporter extends Importer { wiseTopic: NodeModel, centralTopic: boolean, ): void { - const text: string = freeNode.getText(); + const text = freeNode.getText(); if (text) { if (!centralTopic && text.length > 100) { wiseTopic.setText(text.replace(/([^\n]{1,100})\s/g, '$1\n')); @@ -167,7 +166,7 @@ export default class FreemindImporter extends Importer { } } - const bgColor: string = freeNode.getBackgroundColor(); + const bgColor = freeNode.getBackgroundColor(); if (bgColor) { wiseTopic.setBackgroundColor(bgColor); } @@ -186,7 +185,7 @@ export default class FreemindImporter extends Importer { // } // Is there any link... - const url: string = freeNode.getLink(); + const url = freeNode.getLink(); if (url) { const link: FeatureModel = FeatureModelFactory.createModel('link', { url }); wiseTopic.addFeature(link); @@ -214,7 +213,7 @@ export default class FreemindImporter extends Importer { const wiseChild = mindmap.createNode('MainTopic', wiseId); const id = child.getId(); - if (id !== null) { + if (id !== undefined) { this.nodesmap.set(id, wiseChild); } @@ -269,13 +268,15 @@ export default class FreemindImporter extends Importer { if (child instanceof FreemindIcon) { const freeIcon: FreemindIcon = child as FreemindIcon; - const iconId: string = freeIcon.getBuiltin(); - const wiseIconId = FreemindIconConverter.toWiseId(iconId); - if (wiseIconId) { - const mindmapIcon: FeatureModel = FeatureModelFactory.createModel('icon', { - id: wiseIconId, - }); - currentWiseTopic.addFeature(mindmapIcon); + const iconId = freeIcon.getBuiltin(); + if (iconId) { + const wiseIconId = FreemindIconConverter.toWiseId(iconId); + if (wiseIconId) { + const mindmapIcon: FeatureModel = FeatureModelFactory.createModel('icon', { + id: wiseIconId, + }); + currentWiseTopic.addFeature(mindmapIcon); + } } } @@ -283,7 +284,7 @@ export default class FreemindImporter extends Importer { const hook: FreemindHook = child as FreemindHook; const mindmapNote: NoteModel = new NoteModel({ text: '' }); - let textNote: string = hook.getText(); + let textNote = hook.getText(); if (!textNote) { textNote = FreemindConstant.EMPTY_NOTE; mindmapNote.setText(textNote); @@ -294,27 +295,28 @@ export default class FreemindImporter extends Importer { if (child instanceof FreemindRichcontent) { const type = child.getType(); const html = child.getHtml(); - const text = this.html2Text(html); + if (html) { + const text = this.html2Text(html); + switch (type) { + case 'NOTE': { + const noteModel: FeatureModel = FeatureModelFactory.createModel('note', { + text: text || FreemindConstant.EMPTY_NOTE, + }); + currentWiseTopic.addFeature(noteModel); + break; + } - switch (type) { - case 'NOTE': { - const noteModel: FeatureModel = FeatureModelFactory.createModel('note', { - text: text || FreemindConstant.EMPTY_NOTE, - }); - currentWiseTopic.addFeature(noteModel); - break; - } + case 'NODE': { + currentWiseTopic.setText(text); + break; + } - case 'NODE': { - currentWiseTopic.setText(text); - break; - } - - default: { - const noteModel: FeatureModel = FeatureModelFactory.createModel('note', { - text: text || FreemindConstant.EMPTY_NOTE, - }); - currentWiseTopic.addFeature(noteModel); + default: { + const noteModel: FeatureModel = FeatureModelFactory.createModel('note', { + text: text || FreemindConstant.EMPTY_NOTE, + }); + currentWiseTopic.addFeature(noteModel); + } } } } @@ -322,28 +324,28 @@ export default class FreemindImporter extends Importer { if (child instanceof FreemindArrowLink) { const arrow: FreemindArrowLink = child as FreemindArrowLink; const relationship: RelationshipModel = new RelationshipModel(0, 0); - const destId: string = arrow.getDestination(); + const destId = arrow.getDestination(); relationship.setSrcCtrlPoint(destId); relationship.setDestCtrlPoint(freeParent.getId()); - const endinclination: string = arrow.getEndInclination(); + const endinclination = arrow.getEndInclination(); if (endinclination) { const inclination: Array = endinclination.split(';'); relationship.setDestCtrlPoint(`${inclination[0]},${inclination[1]}`); } - const startinclination: string = arrow.getStartinclination(); + const startinclination = arrow.getStartinclination(); if (startinclination) { const inclination: Array = startinclination.split(';'); relationship.setSrcCtrlPoint(`${inclination[0]},${inclination[1]}`); } - const endarrow: string = arrow.getEndarrow(); + const endarrow = arrow.getEndarrow(); if (endarrow) { relationship.setEndArrow(endarrow.toLowerCase() !== 'none'); } - const startarrow: string = arrow.getStartarrow(); + const startarrow = arrow.getStartarrow(); if (startarrow) { relationship.setStartArrow(startarrow.toLowerCase() !== 'none'); } @@ -375,7 +377,7 @@ export default class FreemindImporter extends Importer { private getChildrenCountSameSide(freeChilden: Array, freeChild: FreemindNode): number { let result = 0; - let childSide: string = freeChild.getPosition(); + let childSide = freeChild.getPosition(); if (!childSide) { childSide = FreemindConstant.POSITION_RIGHT; @@ -410,55 +412,54 @@ export default class FreemindImporter extends Importer { return result; } - private generateFontStyle(node: FreemindNode, font: FreemindFont | undefined): string { - const fontStyle: Array = []; + // private generateFontStyle(node: FreemindNode, font: FreemindFont | undefined): string { + // const fontStyle: Array = []; - // Font family - if (font) { - const name = font.getName(); - if (name) { - fontStyle.push(name); - } - } - fontStyle.push(';'); + // // Font family + // if (font) { + // const name = font.getName(); + // if (name) { + // fontStyle.push(name); + // } + // } + // fontStyle.push(';'); - // Font Size - if (font) { - const fontSize: number = - !font.getSize() || parseInt(font.getSize(), 10) < 8 - ? FreemindConstant.FONT_SIZE_NORMAL - : parseInt(font.getSize(), 10); - let wiseFontSize: number = FreemindConstant.FONT_SIZE_SMALL; - if (fontSize >= 24) { - wiseFontSize = FreemindConstant.FONT_SIZE_HUGE; - } - if (fontSize >= 16) { - wiseFontSize = FreemindConstant.FONT_SIZE_LARGE; - } - if (fontSize >= 8) { - wiseFontSize = FreemindConstant.FONT_SIZE_NORMAL; - } - fontStyle.push(wiseFontSize.toString()); - } - fontStyle.push(';'); + // // Font Size + // if (font) { + // const size = font.getSize(); + // const fontSize: number = + // !size || parseInt(size, 10) < 8 ? FreemindConstant.FONT_SIZE_NORMAL : parseInt(size, 10); + // let wiseFontSize: number = FreemindConstant.FONT_SIZE_SMALL; + // if (fontSize >= 24) { + // wiseFontSize = FreemindConstant.FONT_SIZE_HUGE; + // } + // if (fontSize >= 16) { + // wiseFontSize = FreemindConstant.FONT_SIZE_LARGE; + // } + // if (fontSize >= 8) { + // wiseFontSize = FreemindConstant.FONT_SIZE_NORMAL; + // } + // fontStyle.push(wiseFontSize.toString()); + // } + // fontStyle.push(';'); - // Font Color - const color: string = node.getColor(); - if (color && color !== '') { - fontStyle.push(color); - } - fontStyle.push(';'); + // // Font Color + // const color = node.getColor(); + // if (color && color !== '') { + // fontStyle.push(color); + // } + // fontStyle.push(';'); - // Font Italic - if (font) { - const hasItalic = Boolean(font.getItalic()); - fontStyle.push(hasItalic ? FreemindConstant.ITALIC : ''); - } - fontStyle.push(';'); + // // Font Italic + // if (font) { + // const hasItalic = Boolean(font.getItalic()); + // fontStyle.push(hasItalic ? FreemindConstant.ITALIC : ''); + // } + // fontStyle.push(';'); - const result: string = fontStyle.join(''); - return result; - } + // const result: string = fontStyle.join(''); + // return result; + // } private convertPosition( wiseParent: NodeModel, @@ -471,7 +472,7 @@ export default class FreemindImporter extends Importer { FreemindConstant.CENTRAL_TO_TOPIC_DISTANCE + (depth - 1) * FreemindConstant.TOPIC_TO_TOPIC_DISTANCE; if (depth === 1) { - const side: string = freeChild.getPosition(); + const side = freeChild.getPosition(); x *= side && FreemindConstant.POSITION_LEFT === side ? -1 : 1; } else { const position = wiseParent.getPosition(); diff --git a/packages/mindplot/src/components/import/WisemappingImporter.ts b/packages/mindplot/src/components/import/WisemappingImporter.ts index 31a58a37..9315a1ac 100644 --- a/packages/mindplot/src/components/import/WisemappingImporter.ts +++ b/packages/mindplot/src/components/import/WisemappingImporter.ts @@ -1,12 +1,9 @@ -import Mindmap from '../model/Mindmap'; import XMLSerializerFactory from '../persistence/XMLSerializerFactory'; import Importer from './Importer'; export default class WisemappingImporter extends Importer { private wisemappingInput: string; - private mindmap: Mindmap; - constructor(map: string) { super(); this.wisemappingInput = map; @@ -17,11 +14,11 @@ export default class WisemappingImporter extends Importer { const wiseDoc = parser.parseFromString(this.wisemappingInput, 'application/xml'); const serialize = XMLSerializerFactory.createInstanceFromDocument(wiseDoc); - this.mindmap = serialize.loadFromDom(wiseDoc, nameMap); + const mindmap = serialize.loadFromDom(wiseDoc, nameMap); - this.mindmap.setDescription(description); + mindmap.setDescription(description); - const mindmapToXml = serialize.toXML(this.mindmap); + const mindmapToXml = serialize.toXML(mindmap); const xmlStr = new XMLSerializer().serializeToString(mindmapToXml); return Promise.resolve(xmlStr); diff --git a/packages/mindplot/src/components/layout/EventBusDispatcher.ts b/packages/mindplot/src/components/layout/EventBusDispatcher.ts index 2285bbe7..d0b6d567 100644 --- a/packages/mindplot/src/components/layout/EventBusDispatcher.ts +++ b/packages/mindplot/src/components/layout/EventBusDispatcher.ts @@ -22,10 +22,11 @@ import EventBus from './EventBus'; import LayoutManager from './LayoutManager'; class EventBusDispatcher { - private _layoutManager: LayoutManager; + private _layoutManager: LayoutManager | null; constructor() { this.registerBusEvents(); + this._layoutManager = null; } setLayoutManager(layoutManager: LayoutManager) { @@ -44,19 +45,19 @@ class EventBusDispatcher { } private _topicResizeEvent(args: { node: Topic; size: SizeType }) { - this._layoutManager.updateNodeSize(args.node.getId(), args.size); + this._layoutManager!.updateNodeSize(args.node.getId(), args.size); } private _topicMoved(args: { node: Topic; position: PositionType }) { - this._layoutManager.moveNode(args.node.getId(), args.position); + this._layoutManager!.moveNode(args.node.getId(), args.position); } private _topicDisconect(node: Topic) { - this._layoutManager.disconnectNode(node.getId()); + this._layoutManager!.disconnectNode(node.getId()); } private _topicConnected(args: { parentNode: Topic; childNode: Topic }) { - this._layoutManager.connectNode( + this._layoutManager!.connectNode( args.parentNode.getId(), args.childNode.getId(), args.childNode.getOrder(), @@ -64,27 +65,27 @@ class EventBusDispatcher { } private _childShrinked(node: Topic) { - this._layoutManager.updateShrinkState(node.getId(), node.areChildrenShrunken()); + this._layoutManager!.updateShrinkState(node.getId(), node.areChildrenShrunken()); } private _topicAdded(node: Topic) { // Central topic must not be added twice ... if (node.getId() !== 0) { - this._layoutManager.addNode(node.getId(), { width: 10, height: 10 }, node.getPosition()); - this._layoutManager.updateShrinkState(node.getId(), node.areChildrenShrunken()); + this._layoutManager!.addNode(node.getId(), { width: 10, height: 10 }, node.getPosition()); + this._layoutManager!.updateShrinkState(node.getId(), node.areChildrenShrunken()); } } private _topicRemoved(node: Topic) { - this._layoutManager.removeNode(node.getId()); + this._layoutManager!.removeNode(node.getId()); } private _forceLayout() { - this._layoutManager.layout(true); + this._layoutManager!.layout(true); } - getLayoutManager() { - return this._layoutManager; + getLayoutManager(): LayoutManager { + return this._layoutManager!; } } diff --git a/packages/mindplot/src/components/layout/Node.ts b/packages/mindplot/src/components/layout/Node.ts index da366b51..c2f8c4ee 100644 --- a/packages/mindplot/src/components/layout/Node.ts +++ b/packages/mindplot/src/components/layout/Node.ts @@ -24,21 +24,17 @@ class Node { private _id: number; // eslint-disable-next-line no-use-before-define - _parent: Node | null; + _parent!: Node | null; private _sorter: ChildrenSorterStrategy; private _properties; // eslint-disable-next-line no-use-before-define - _children: Node[]; + _children!: Node[]; constructor(id: number, size: SizeType, position: PositionType, sorter: ChildrenSorterStrategy) { $assert(typeof id === 'number' && Number.isFinite(id), 'id can not be null'); - $assert(size, 'size can not be null'); - $assert(position, 'position can not be null'); - $assert(sorter, 'sorter can not be null'); - this._id = id; this._sorter = sorter; this._properties = {}; @@ -49,7 +45,7 @@ class Node { } /** */ - getId() { + getId(): number { return this._id; } @@ -74,7 +70,7 @@ class Node { } /** */ - setShrunken(value) { + setShrunken(value: boolean) { this._setProperty('shrink', value); } @@ -132,31 +128,27 @@ class Node { } /** */ - hasSizeChanged() { + hasSizeChanged(): boolean { return this._isPropertyChanged('size'); } /** */ - getPosition() { + getPosition(): PositionType { return this._getProperty('position'); } /** */ - setSize(size) { + setSize(size: SizeType) { $assert($defined(size), 'Size can not be null'); this._setProperty('size', { ...size }); } /** */ - getSize() { + getSize(): SizeType { return this._getProperty('size'); } - /** */ - setFreeDisplacement(displacement) { - $assert($defined(displacement), 'Position can not be null'); - $assert($defined(displacement.x), 'x can not be null'); - $assert($defined(displacement.y), 'y can not be null'); + setFreeDisplacement(displacement: PositionType) { const oldDisplacement = this.getFreeDisplacement(); const newDisplacement = { x: oldDisplacement.x + displacement.x, @@ -177,12 +169,7 @@ class Node { return freeDisplacement || { x: 0, y: 0 }; } - /** */ setPosition(position: PositionType) { - $assert($defined(position), 'Position can not be null'); - $assert($defined(position.x), 'x can not be null'); - $assert($defined(position.y), 'y can not be null'); - // This is a performance improvement to avoid movements that really could be avoided. const currentPos = this.getPosition(); if ( @@ -213,7 +200,7 @@ class Node { this._properties[key] = prop; } - _getProperty(key) { + _getProperty(key: string) { const prop = this._properties[key]; return $defined(prop) ? prop.value : null; } @@ -229,7 +216,7 @@ class Node { } /** @return {String} returns id, order, position, size and shrink information */ - toString() { + toString(): string { return `[id:${this.getId()}, order:${this.getOrder()}, position: {${this.getPosition().x},${ this.getPosition().y }}, size: {${this.getSize().width},${ diff --git a/packages/mindplot/src/components/layout/RootedTreeSet.ts b/packages/mindplot/src/components/layout/RootedTreeSet.ts index 49a32437..3b6b4d82 100644 --- a/packages/mindplot/src/components/layout/RootedTreeSet.ts +++ b/packages/mindplot/src/components/layout/RootedTreeSet.ts @@ -15,21 +15,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { $assert, $defined } from '@wisemapping/core-js'; +import { $assert } from '@wisemapping/core-js'; import PositionType from '../PositionType'; import Node from './Node'; class RootedTreeSet { private _rootNodes: Node[]; - protected _children: Node[]; + protected _children!: Node[]; constructor() { this._rootNodes = []; } setRoot(root: Node) { - $assert(root, 'root can not be null'); this._rootNodes.push(this._decodate(root)); } @@ -43,7 +42,6 @@ class RootedTreeSet { } add(node: Node) { - $assert(node, 'node can not be null'); if (this.find(node.getId(), false)) { throw new Error(`node already exits with this id. Id:${node.getId()}: ${this.dump()}`); } @@ -56,7 +54,6 @@ class RootedTreeSet { * @throws will throw an error if nodeId is null or undefined */ remove(nodeId: number) { - $assert($defined(nodeId), 'nodeId can not be null'); const node = this.find(nodeId); this._rootNodes = this._rootNodes.filter((n) => n !== node); } @@ -69,9 +66,6 @@ class RootedTreeSet { * @throws will throw an error if node with id childId is already a child of parent */ connect(parentId: number, childId: number) { - $assert($defined(parentId), 'parent can not be null'); - $assert($defined(childId), 'child can not be null'); - const parent = this.find(parentId); const child = this.find(childId, true); $assert( @@ -90,7 +84,6 @@ class RootedTreeSet { * @throws will throw an error if node is not connected */ disconnect(nodeId: number) { - $assert($defined(nodeId), 'nodeId can not be null'); const node = this.find(nodeId); $assert(node._parent, 'Node is not connected'); @@ -107,8 +100,6 @@ class RootedTreeSet { * @return node */ find(id: number, validate = true): Node { - $assert($defined(id), 'id can not be null'); - const graphs = this._rootNodes; let result: Node | null = null; for (let i = 0; i < graphs.length; i++) { diff --git a/packages/mindplot/src/components/model/NodeModel.ts b/packages/mindplot/src/components/model/NodeModel.ts index 9accc482..2ea1b93b 100644 --- a/packages/mindplot/src/components/model/NodeModel.ts +++ b/packages/mindplot/src/components/model/NodeModel.ts @@ -35,8 +35,6 @@ class NodeModel extends INodeModel { private _parent: NodeModel | null; constructor(type: NodeModelType, mindmap: Mindmap, id?: number) { - $assert(type, 'Node type can not be null'); - $assert(mindmap, 'mindmap can not be null'); super(mindmap); this._properties = {}; @@ -46,6 +44,7 @@ class NodeModel extends INodeModel { this._children = []; this._features = []; + this._parent = null; } /** diff --git a/packages/mindplot/src/components/persistence/XMLSerializerBeta.ts b/packages/mindplot/src/components/persistence/XMLSerializerBeta.ts index e597946f..6cc6f7e7 100644 --- a/packages/mindplot/src/components/persistence/XMLSerializerBeta.ts +++ b/packages/mindplot/src/components/persistence/XMLSerializerBeta.ts @@ -20,7 +20,6 @@ import Mindmap from '../model/Mindmap'; import FeatureModelFactory from '../model/FeatureModelFactory'; import NodeModel from '../model/NodeModel'; import XMLMindmapSerializer from './XMLMindmapSerializer'; -import FeatureModel from '../model/FeatureModel'; class XMLSerializerBeta implements XMLMindmapSerializer { private static MAP_ROOT_NODE = 'map'; @@ -297,12 +296,6 @@ class XMLSerializerBeta implements XMLMindmapSerializer { return topic; } - private _deserializeIcon(domElem: Element): FeatureModel { - let icon = domElem.getAttribute('id'); - icon = icon ? icon.replace('images/', 'icons/legacy/') : 'missing'; - return FeatureModelFactory.createModel('icon', { id: icon }); - } - _deserializeLink(domElem: Element) { return FeatureModelFactory.createModel('link', { url: domElem.getAttribute('url') }); } diff --git a/packages/mindplot/src/components/persistence/XMLSerializerTango.ts b/packages/mindplot/src/components/persistence/XMLSerializerTango.ts index c5239cff..2714e7a1 100644 --- a/packages/mindplot/src/components/persistence/XMLSerializerTango.ts +++ b/packages/mindplot/src/components/persistence/XMLSerializerTango.ts @@ -33,6 +33,10 @@ class XMLSerializerTango implements XMLMindmapSerializer { private _idsMap: Record; + constructor() { + this._idsMap = {}; + } + toXML(mindmap: Mindmap): Document { $assert(mindmap, 'Can not save a null mindmap'); @@ -242,7 +246,6 @@ class XMLSerializerTango implements XMLMindmapSerializer { `This seem not to be a map document. Found tag: ${rootElem.tagName}`, ); - this._idsMap = {}; // Start the loading process ... const version = rootElem.getAttribute('version') || 'pela'; const mindmap = new Mindmap(mapId, version); diff --git a/packages/mindplot/src/components/widget/LineTopicShape.ts b/packages/mindplot/src/components/widget/LineTopicShape.ts index 213fb63a..74325f22 100644 --- a/packages/mindplot/src/components/widget/LineTopicShape.ts +++ b/packages/mindplot/src/components/widget/LineTopicShape.ts @@ -20,9 +20,7 @@ import SizeType from '../SizeType'; import Topic from '../Topic'; class LineTopicShape extends Line { - private _topic: Topic; - - private _size: SizeType; + private _size: SizeType | null; constructor(topic: Topic) { const stokeColor = topic.getConnectionColor(); @@ -30,7 +28,7 @@ class LineTopicShape extends Line { strokeColor: stokeColor, strokeWidth: 1, }); - this._topic = topic; + this._size = null; } setSize(width: number, height: number): void { @@ -39,7 +37,7 @@ class LineTopicShape extends Line { super.setTo(width, height); } - getSize() { + getSize(): SizeType | null { return this._size; } diff --git a/packages/mindplot/test/playground/layout/SymmetricTestSuite.js b/packages/mindplot/test/playground/layout/SymmetricTestSuite.js index 86f829ed..96d0e40e 100644 --- a/packages/mindplot/test/playground/layout/SymmetricTestSuite.js +++ b/packages/mindplot/test/playground/layout/SymmetricTestSuite.js @@ -83,12 +83,12 @@ class SymmetricTestSuite extends TestSuite { 'Symmetry is not respected', ); $assert( - manager.find(8).getPosition().y - manager.find(1).getPosition().y == + manager.find(8).getPosition().y - manager.find(1).getPosition().y === -(manager.find(11).getPosition().y - manager.find(1).getPosition().y), 'Symmetry is not respected', ); $assert( - manager.find(9).getPosition().y - manager.find(1).getPosition().y == + manager.find(9).getPosition().y - manager.find(1).getPosition().y === -(manager.find(11).getPosition().y - manager.find(1).getPosition().y), 'Symmetry is not respected', ); @@ -136,20 +136,20 @@ class SymmetricTestSuite extends TestSuite { this._plotPrediction(graph1, prediction1a); $assert( prediction1a.position.x < manager.find(9).getPosition().x && - prediction1a.position.y == manager.find(9).getPosition().y, + prediction1a.position.y === manager.find(9).getPosition().y, 'Prediction incorrectly positioned', ); - $assert(prediction1a.order == 0, 'Prediction order should be 0'); + $assert(prediction1a.order === 0, 'Prediction order should be 0'); console.log('\tAdded as child of node 1 and dropped at (155, -90):'); const prediction1b = manager.predict(1, null, { x: -155, y: -90 }); this._plotPrediction(graph1, prediction1b); $assert( prediction1b.position.x > manager.find(1).getPosition().x && - prediction1b.position.y == manager.find(1).getPosition().y, + prediction1b.position.y === manager.find(1).getPosition().y, 'Prediction is incorrectly positioned', ); - $assert(prediction1b.order == 0, 'Prediction order should be 0'); + $assert(prediction1b.order === 0, 'Prediction order should be 0'); // Graph 2 const graph2 = manager.plot('testSymmetricPredict2', { width: 1000, height: 400 }); @@ -161,10 +161,10 @@ class SymmetricTestSuite extends TestSuite { // Prediction calculator error $assert( prediction2d.position.y < manager.find(7).getPosition().y && - prediction2d.position.x == manager.find(7).getPosition().x, + prediction2d.position.x === manager.find(7).getPosition().x, 'Prediction is incorrectly positioned', ); - $assert(prediction2d.order == 0, 'Prediction order should be 0'); + $assert(prediction2d.order === 0, 'Prediction order should be 0'); console.log('\tAdded as child of node 5 and dropped at (375, 15):'); const prediction2a = manager.predict(5, null, { x: 375, y: 15 }); @@ -173,10 +173,10 @@ class SymmetricTestSuite extends TestSuite { $assert( prediction2a.position.y > manager.find(7).getPosition().y && prediction2a.position.y < manager.find(8).getPosition().y && - prediction2a.position.x == manager.find(7).getPosition().x, + prediction2a.position.x === manager.find(7).getPosition().x, 'Prediction is incorrectly positioned', ); - $assert(prediction2a.order == 1, 'Prediction order should be 1'); + $assert(prediction2a.order === 1, 'Prediction order should be 1'); console.log('\tAdded as child of node 5 and dropped at (375, 45):'); const prediction2b = manager.predict(5, null, { x: 375, y: 45 }); @@ -184,20 +184,20 @@ class SymmetricTestSuite extends TestSuite { $assert( prediction2b.position.y > manager.find(8).getPosition().y && prediction2b.position.y < manager.find(11).getPosition().y && - prediction2b.position.x == manager.find(7).getPosition().x, + prediction2b.position.x === manager.find(7).getPosition().x, 'Prediction is incorrectly positioned', ); - $assert(prediction2b.order == 2, 'Prediction order should be 2'); + $assert(prediction2b.order === 2, 'Prediction order should be 2'); console.log('\tAdded as child of node 5 and dropped at (375, 45):'); const prediction2c = manager.predict(5, null, { x: 375, y: 65 }); this._plotPrediction(graph2, prediction2c); $assert( prediction2c.position.y > manager.find(11).getPosition().y && - prediction2c.position.x == manager.find(11).getPosition().x, + prediction2c.position.x === manager.find(11).getPosition().x, 'Prediction is incorrectly positioned', ); - $assert(prediction2c.order == 3, 'Prediction order should be 3'); + $assert(prediction2c.order === 3, 'Prediction order should be 3'); // Graph 3 const graph3 = manager.plot('testSymmetricPredict3', { width: 1000, height: 400 }); @@ -208,20 +208,20 @@ class SymmetricTestSuite extends TestSuite { $assert( prediction3a.position.y > manager.find(5).getPosition().y && prediction3a.position.y < manager.find(6).getPosition().y && - prediction3a.position.x == manager.find(5).getPosition().x, + prediction3a.position.x === manager.find(5).getPosition().x, 'Prediction is incorrectly positioned', ); - $assert(prediction3a.order == 2, 'Prediction order should be 2'); + $assert(prediction3a.order === 2, 'Prediction order should be 2'); console.log('\tAdded as child of node 3 and dropped at (255, 110):'); const prediction3b = manager.predict(3, null, { x: 255, y: 110 }); this._plotPrediction(graph3, prediction3b); $assert( prediction3b.position.y > manager.find(6).getPosition().y && - prediction3b.position.x == manager.find(6).getPosition().x, + prediction3b.position.x === manager.find(6).getPosition().x, 'Prediction incorrectly positioned', ); - $assert(prediction3b.order == 3, 'Prediction order should be 3'); + $assert(prediction3b.order === 3, 'Prediction order should be 3'); // Graph 4 console.log('\tAdded as child of node 2 and dropped at (-260, 0):'); @@ -231,10 +231,10 @@ class SymmetricTestSuite extends TestSuite { $assert( prediction4.position.y > manager.find(9).getPosition().y && prediction4.position.y < manager.find(10).getPosition().y && - prediction4.position.x == manager.find(9).getPosition().x, + prediction4.position.x === manager.find(9).getPosition().x, 'Prediction is incorrectly positioned', ); - $assert(prediction4.order == 1, 'Prediction order should be 1'); + $assert(prediction4.order === 1, 'Prediction order should be 1'); // Graph 5 console.log('\tPredict nodes added with no position:'); @@ -242,40 +242,40 @@ class SymmetricTestSuite extends TestSuite { const prediction5a = manager.predict(1, null, null); this._plotPrediction(graph5, prediction5a); $assert( - prediction5a.position.y == manager.find(1).getPosition().y && + prediction5a.position.y === manager.find(1).getPosition().y && prediction5a.position.x > manager.find(1).getPosition().x, 'Prediction is incorrectly positioned', ); - $assert(prediction5a.order == 0, 'Prediction order should be 0'); + $assert(prediction5a.order === 0, 'Prediction order should be 0'); const prediction5b = manager.predict(2, null, null); this._plotPrediction(graph5, prediction5b); $assert( prediction5b.position.y > manager.find(10).getPosition().y && prediction5b.position.x < manager.find(2).getPosition().x && - prediction5b.position.x == manager.find(10).getPosition().x, + prediction5b.position.x === manager.find(10).getPosition().x, 'Prediction is incorrectly positioned', ); - $assert(prediction5b.order == 2, 'Prediction order should be 2'); + $assert(prediction5b.order === 2, 'Prediction order should be 2'); const prediction5c = manager.predict(3, null, null); this._plotPrediction(graph5, prediction5c); $assert( prediction5c.position.y > manager.find(6).getPosition().y && prediction5c.position.x > manager.find(3).getPosition().x && - prediction5c.position.x == manager.find(6).getPosition().x, + prediction5c.position.x === manager.find(6).getPosition().x, 'Prediction is incorrectly positioned', ); - $assert(prediction5c.order == 3, 'Prediction order should be 3'); + $assert(prediction5c.order === 3, 'Prediction order should be 3'); const prediction5d = manager.predict(10, null, null); this._plotPrediction(graph5, prediction5d); $assert( - prediction5d.position.y == manager.find(10).getPosition().y && + prediction5d.position.y === manager.find(10).getPosition().y && prediction5d.position.x < manager.find(10).getPosition().x, 'Prediction is incorrectly positioned', ); - $assert(prediction5d.order == 0, 'Prediction order should be 0'); + $assert(prediction5d.order === 0, 'Prediction order should be 0'); console.log('OK!\n\n'); } @@ -295,54 +295,54 @@ class SymmetricTestSuite extends TestSuite { const prediction1a = manager.predict(1, 2, { x: -250, y: -20 }); this._plotPrediction(graph1, prediction1a); $assert( - prediction1a.position.x == manager.find(2).getPosition().x && - prediction1a.position.y == manager.find(2).getPosition().y, + prediction1a.position.x === manager.find(2).getPosition().x && + prediction1a.position.y === manager.find(2).getPosition().y, 'Prediction position should be the same as node 2', ); $assert( - prediction1a.order == manager.find(2).getOrder(), + prediction1a.order === manager.find(2).getOrder(), 'Predicition order should be the same as node 2', ); const prediction1b = manager.predict(1, 2, { x: -250, y: 20 }); this._plotPrediction(graph1, prediction1b); $assert( - prediction1b.position.x == manager.find(2).getPosition().x && - prediction1b.position.y == manager.find(2).getPosition().y, + prediction1b.position.x === manager.find(2).getPosition().x && + prediction1b.position.y === manager.find(2).getPosition().y, 'Prediction position should be the same as node 2', ); $assert( - prediction1b.order == manager.find(2).getOrder(), + prediction1b.order === manager.find(2).getOrder(), 'Predicition order should be the same as node 2', ); const prediction1c = manager.predict(0, 2, { x: -100, y: -20 }); this._plotPrediction(graph1, prediction1c); $assert( - prediction1c.position.x == manager.find(1).getPosition().x && + prediction1c.position.x === manager.find(1).getPosition().x && prediction1c.position.y < manager.find(1).getPosition().y, 'Prediction is incorrectly positioned', ); - $assert(prediction1c.order == 1, 'Prediction order should be 1'); + $assert(prediction1c.order === 1, 'Prediction order should be 1'); const prediction1d = manager.predict(0, 2, { x: -100, y: 20 }); this._plotPrediction(graph1, prediction1d); $assert( - prediction1d.position.x == manager.find(1).getPosition().x && + prediction1d.position.x === manager.find(1).getPosition().x && prediction1d.position.y > manager.find(1).getPosition().y, 'Prediction is incorrectly positioned', ); - $assert(prediction1d.order == 3, 'Prediction order should be 3'); + $assert(prediction1d.order === 3, 'Prediction order should be 3'); const prediction1e = manager.predict(1, 2, { x: -250, y: 0 }); this._plotPrediction(graph1, prediction1e); $assert( - prediction1e.position.x == manager.find(2).getPosition().x && - prediction1e.position.y == manager.find(2).getPosition().y, + prediction1e.position.x === manager.find(2).getPosition().x && + prediction1e.position.y === manager.find(2).getPosition().y, 'Prediction position should be the same as node 2', ); $assert( - prediction1e.order == manager.find(2).getOrder(), + prediction1e.order === manager.find(2).getOrder(), 'Predicition order should be the same as node 2', ); diff --git a/packages/mindplot/test/unit/import/expected/anonymity_on_the_edge.wxml b/packages/mindplot/test/unit/import/expected/anonymity_on_the_edge.wxml index 73b66a4e..2a4dac82 100644 --- a/packages/mindplot/test/unit/import/expected/anonymity_on_the_edge.wxml +++ b/packages/mindplot/test/unit/import/expected/anonymity_on_the_edge.wxml @@ -197,7 +197,7 @@ unencrypted.]]> - + - + @@ -330,7 +330,7 @@ per 1,000 researchers [contracts/researchers]]]> - + diff --git a/packages/mindplot/test/unit/import/expected/enc.wxml b/packages/mindplot/test/unit/import/expected/enc.wxml index 3e7a14a3..37d704f3 100644 --- a/packages/mindplot/test/unit/import/expected/enc.wxml +++ b/packages/mindplot/test/unit/import/expected/enc.wxml @@ -3,7 +3,7 @@ - + failed to accurately estimate the variance of trait values. This indicates that in situations where accurate estimation of plotlevel variance is desired, complete censuses are essential.]]> - - - - + + + - - + + - + - + - + @@ -64,12 +64,12 @@ Ctrl + F in your browser?]]> - - + + - + @@ -101,8 +101,8 @@ site.]]> - - + + @@ -110,7 +110,7 @@ site.]]> - + diff --git a/packages/mindplot/test/unit/import/expected/writing_an_essay_with.wxml b/packages/mindplot/test/unit/import/expected/writing_an_essay_with.wxml index 5caa9805..e979e0fb 100644 --- a/packages/mindplot/test/unit/import/expected/writing_an_essay_with.wxml +++ b/packages/mindplot/test/unit/import/expected/writing_an_essay_with.wxml @@ -2,19 +2,19 @@ - - + + New on the menu, and a blank file will appear. ]]> - + - + @@ -28,22 +28,22 @@ it.]]> (When you're a bit more familiar with FreeMind, you'll find it quicker to use the Shortcut Keys -- you can also use Alt + Shift + Left, or Alt + Shift + Right to move between maps.)]]> - + - - + + - - + + - + @@ -57,7 +57,7 @@ thoughts.]]> - + @@ -67,8 +67,8 @@ thoughts.]]> - - + + @@ -83,18 +83,18 @@ later.]]> - - + + - + - + @@ -104,8 +104,8 @@ helpful to hide it after you've added your note, by selecting "Show Note Window" menu.]]> - - + + - + - + @@ -237,14 +237,14 @@ point.]]> - - + + - - + + - + @@ -296,50 +296,50 @@ best results.]]> - + - + - + - + - + - + - + - + - + - + - + - - - + + + - + 2T+a)dcub) zKa5L!{Jy&IThP-NU9@=jY3YvL_?UGTSk=1bqqAIIUL2Hrks>SmG_GI%3ai>Hc(f6^G;h3gf-(aG1Kr9{5)MZ5KJc7te`e)S|88j*IRK4!tBR^HCb8w>J1WL3X; zxdz;5sg9}&Gg$MpIMF$C3}eD7Wq#i(x=iszNu7M*V!p$)aw&De)EAQTClUJA_n97| z`0k`k-b$6Iky(zxW(p#f4NFcBF^J)%@e9YOK+`{o!~OPDCnn*-n3q;wN}x_mvRrVX zuTG{_!>LK}y)Q;@uzfCQQ}db|JNMox~d9bLvACwZ;6e_ODA zb+F8Y2}i8q>+pB@Y*NbPiberu_F8!_oKZS4-c(7uvq`Tare-KUj}yq}HO3O@k{V~r z{^WYY^HZZlA3sBP)x@yL{al3;-t5Jkf~nyoWKtW4W6#Ue#mrZ;!pE;*hvn*C$JDsC z%fmG-?hnH`J{{C?uu)C*InZEDrQ9R*$D=8D?j833S`8}o=rn}bja8fLB5nV9WCO-) z1;)Em0;ivl8pe-cnr4iqFr!28RFC>0gX}0q!{`G>mFLBEM-1=~J=FO$@{Fj+mD+a5aaBeEwgMX zCYYCNme>jvr^LM>v&nIrL%p%4-QOZxip=`?hRz#rN0QL|l7L7Bv!3eg=k&8DT(!iV zMg*b+B(B|I!#z!xt^Jooq>GUHr~svSwp{0EZn7#t$jE zzgGJ_zbY=@CBr!{{GAJjhihKAGmbIWochL+0=W?0>%!S2Px!9tt#7p5-qSInQO6lPpt zbnP6)$u%s#w;}q*0S_ZCtxIYD84LRq$(vh~gscf#c{2|`OSY)~ZWuD=daZld=HDYn zesVK^YL_veuE4l6(AO;gWe%CvCz-Ro8Bfv~=ja@qmM-&;{aMe1mUDg&9h1A3Ym zl1?#_>3`ec5gI=1|z9(RZ++F3N0E*oN-L1ajBB0GZ`=kz;U7PhW{@pKd% zQ)#S5u;K-e-PhrzluXO4w+^FlDJvU(UZ46#FfQibi~j7}^Hgk4#r)F4HR1{y!1vU3+XD;HeEMoOOZsb4zepSPVV(>#?MJ#T-DVqdFcoMFA$rJmvpcl?Z+%&Yw zM6B^Q%Il{ViE@2Deq+AoHqm zU>5)L6ZBVjdp8f2HrIEI78@$HOIpv8l_%slLf}bU1qD4D)#vk{7Dx~R5aHV z1ttd_Sz5reRAYYa;6Mf!gSM+pMnQ$?jK9S>49CwWSNdBDJ1n0QBjT~R>2`UJF0*O% z)6HQ!2LgF)rsCi~yLVm@bdP!Dzs^`nsc|e|Iht54(q`a51M*E$==2#=WKOwEr$<**g zrl2bF{3`N_Dx%e6qN)%LW>hNH_A&jc2Rg(^l60wld&<4-nRjBJFzPD(Gq1X8XY@!< zPn`OxW##2pFw4{1~u1!Y?-}wEReB&4TvD*`M?jYhBbxrFVYiM3X{oei)=-c!eyXWHK6}mcz1k{YV z&L@+%<_Kmm1`$`DCs0ko73j^_y^uh>zJz%~6zHwE^g5sMA;$$tw2rq-e+)j0C@$_N4JS=!CB(>=6H9_`HXvC3NGb9h(Hs&+{5I zH`dVY=o;M5U64BOWq(48A=VfAg?Vb*>DCzLRmuh}e8Qf_YJv->6FPkYba~~Md9H!0 zT}&=wDfiKTi8G$EQI(^SFZwp@3t7=)pbbn>H>vjQ8hNZ=NV$(^DIMJOQp1ZxN6f(% zV?q+nMBo%pPfkx zgHm#qzzOs_5mHvGukgj(I}_boGd)5w>wWPP%mqzE_r#LKbB#|txxU+#^Dw*$ZtJH_ zL5GN!t5$YQgybqmZSh2>m??jXFqSKh_%6QDk4%nz$>UMw$pbqEHy_)2w(~xYRB$Ae z`(eSxF*z}+#LsgoL8+m!y_(^6gKkqKpWtqvUEAiEx7DHj4aY~Jsq>?ucezjebDKrT z5*Te;DS2VknW?9_3#R{_tcAD#k0f;xCKC#o z+rZo?ACd7mv5f1|2WE{>^^AZVGS?cC{D70F)EQd;owQ0`zX4Liz=4U%OB$uxp{*ue z`xwi=2=c`xBT_&9z#jgssIBI>uHgNZ_F3{8hBFB`Fva&(=d*~9d6udN=Ga!5ti0=+ zufFHf$-}Km=b-h`FbvQ@VaTK7#<5S_FEyvj3dowi*!v`7(B#@j|CulGk4&vX01w&- z{Dl~~inG{iC&RaMFpBsS`o*#rCG*t=J{niVYBuWli~dqAq;wCcj>Xkw9_@w)s+_3L zAVN_7(<}|jttWbL)9S>ZjNOcsjdC^Q1~Cq}0fl^0_)wUxi6I|25r}IpYRnF4yJchm zoC*R<68&2oCI0-FHWC4~VXW3=!ooaK4Z%-%!zmNi&aq5 z-2>P4F6|$gp?S}4tOw0i)zbNN8rw!zP3>kqVgTL3-e!-UV8OFNsH%cgmFim#H}K?0 zUx;9StPh2&G!R0;LPBzpJCIof5fi8d|NQ`eqfWv7*VnQFBIN(R$;ts)(ceb~rgZ-O zY*u5zzrJRY3)KGivtgKdXY2o8k1()jW!M;tOli407K>Vs8vXBRSsRY{{xf7SnxSPY z`xMm;vy8vv3P?qrX!sDq5MS?Y+;hNx&8zWuIBJGU2R1ciXI*uD2**$B(pT8p+S>5#yLWsn>S^6{?&C6jX_DXI zQe}Wqo!7=}w6v4xqp!tRIXG}5TAO+}FJBG_#3H&3K~v1h8c$69)-iH2Uprb$AQ*AU z2w+m%UHo*kiHAqY_3-rMcy3`~2vvBG-)m>3V{stc`fD+rTYY`~_OBrVJv}xyAz`k1x>Wv%4Qxr6 z7={FXXgb!-b5+4Gmn`~u`jEoY8>80*C^+oSw@1;LE%s*y1qH2dv@?{W%-RWm_9Tba z)QGRuA9Bs>SJG|VLB+tp zAS)|tHBl>iezkT>&7%8N;~$6hDVdM1%WZKUyFc8YMnv2cphI5k=;#QhoUyJqy+U2J zCkSV?1e-E7E{2Wr4sMfcRyCgQjKilE2*V*|(I}RWpm156pc@d0i;d0rx=aGM%SmFV z<17d@beK<#UZh2D;63-=4(zMye69qW+LM`bjo9;qJ&Y^l)HDRbPYMe;WpCar=qfX7 zr;_mCQH-X~N$GfK+VSG5?P%$f_wNOcj*l<#nqDw5F_AzWZx01b00nKmW^&491z687dJ6#`!2Z@ithtsMj{z{N>A+@0OWjJU|@_KJeMVNK8z; zfPq0mN!i};1igS0p7Y%LS>}7_rlh2VO+YaJD=(deo&D)cR&_r62?;J%Hnydy0mw2Fj%0?3X{dg#m#!>d$_alnK{~ccMWx#T%eto zHS|jaCVow?crGv9@3N3k{QlNLHXClb@6IKZTR}lVcOrjis<^u;U*h6m4xVtAXWlhhY0qG8Zhip^iT}BR6ARyp-w!%SK6zaAMUPMHU?nOin(A%D%^bd@Cs@u zS2dgKf#3eswNIx~G{SbT4K*}~$13gfT$jJ-e0bP#@x_Z5cWXU(-C&<7A&9;8_Tw!IMot~CSm-0n<{7kfTaCgrWnnayS_DO8v!!6lx7Nfr>Kc(;O zc@WZx1vMIHJox0Nk}5_{L`1~J%F7#L-W6YFKPlDO*$J-4!o?MppU-APNqjEOEnJvgdOpoy7!?6#K z$tWlWb5&{Ry;pcKiRe|#Nk~XIAJnI)CJU80&MM&I;$jmKSwcVv3Ju)?quOl5VtAgC z@+>-de4xBmf-SDu^&+f$L-c)hkL=~4`gTb&J#MIPE)p6JKHiy)uH(E&5*MBD4 zzleQwt(i4Lc=f6G8I~WqK@5 zmgg_Z0O3sU#w>0W+7uObz2+3HirMRFmi{_#_X+Pc$<^uwdT@>^EurK{Ub8k0ef`dv z)(Gp#dP#P6_S*fQ$v%g_D~BI04HwAC$(6eN(sB`_LrwY}UY~7`wuArxPM`W6b~!FA z3_G6dez;oR?3n#0^P|0uLc{78t3PVY65`@oZxTtiJUH2;6tWu+gSCVE)b7nhh=_~N zE-Wbe@+S9494uyUFAfB%OCOV^sdf2LkJfCczv+_*0es|e6P++kco+D^!G$va#fWGk}!_;x7ay3AAWmhE~lutHJ|Xn zl!q$6*GhoTbMv98nOUOHV`_a=QT*ev4;#bU>ScC6#G0C$+4W%Cz{5TFrb91D`$+@` z2OljzI5pi{pSJz+k=)(geZ_5UqDT5_0p^Y^X8={kxURNBpdvrIStHJIbFGD=eOqsAQ^ zzkRObWui1n3g*da@Zs6wqE-FTrZVJ-kxP*ZunQ`-ww&POH{XuDdpstDOzumOfg*TB zMWUE1ha}2t8;SjQi*%(97MT^IXgiPqQtiyjZ_&-j$mkE}ur;X6J-xViOGO3W?c29+ z65IVZU4DO$o9{}Pou8LCHNDJl**gb0tEIJ7^BXMp*FZKF#JU!nip>E<23~Nr5CWPu z@QFlTGfXrzv=wmd1S2mTMMXtZQ}=BhXc9`h6hK{zFJf{ zk)@rdR=e4GEp~alnjZ-_KR&ve!P#efuSwu-CSggrubB{(QnE5tIX? zeo_2K*uK!w(Ys=9D`BY+;^Dw%^;0A~UtBl%Kz#9{Y<1;?R|JH(T-9WS>Va& z$A7-wgEZ*IUAulBIf0YIwf5fj_RxFf7QA-jB2q`|H`^j<6kWwqqlyeFvqo&#g-u(q z3F#$1!&@Mf6Q-+3D%+%@29@VCT28rY4D+nwrk; zh~5L<$KM4Yq$oj>pEvTD#<1v3={Vk<&q7>IQb^3vhX@8+&9yqboF8}Ht|yIXESz{|@! z+S=YudhueDfqk8P_2Js5^rH*8gC8yBh9>CCXGMqWCSH05ef=8+F(F z92xrSRTO#NzGi{!nOYYN{j)MLK0GMk^HQZXGO_l$*BVcBYEChL?Og zNpk!B-Gq{uxB-Igudzz*JhjxzkP6Rm?|?vl6%Jc?Q!KmoXvHJSva&MdR7sc>cpRo~ z5Hd)0qvmbLK19M=%pf+YwQF}PxhDAn8-k%~uOqnsCd zHGgEt1m>$0=|XCiftk4Fsi(7Cy&8;+9}yMx(@V2J$7Qkq31IRqNEIgK->T>Zs0l_Y zY({YFjQRlP6xhwSMILRXpUy=JPh`ORW5sXsH1MnfvJw**my?i?fCpG$27`lIKYLS^A$$TFY9AX*UV_x~3+5q+18ASc$jC@% zVP;0w+M3;UV{bpF%ybOupTQA51s9tBk&AD?`+9Iff)Wn~2g zOud;z%d|#gp7n9(K2%Ivn%dpFR76sHjIgj9Ia-c_`tPk|Tz~!g)zZ>31y8ubA%a1| z=j4xlZ z!{v^;-3jIU5a&DIw3;6cTj4AAFL1AIxvqza?C(D(W0UC+@~$(sW_MXG`_q&$6Pg2jmqv#;L77>Gq+amrhV+=~UW`aC|9w z5Dhko7#h^f=1_x02Al;JMw^Ykt;E((|9{FT6cPKc!h;U zi&9<_cof(sNH7tU+=KtxCJ2F9eE+)k^=krDP07XgYmobin{3K8we%Gb5vCriB0iy)i#`DqmZ%`BTAlF=ekc2uHdY zH4~wBgwP-&D(aXmFE3x_G_UkV9Jbl5xVU&Y7qSpC!NdWphY)FoACA1aqf-fq-BySO zCO2b)WT?~QU4AG^kb=s0aq^Qi)R`G#<=>utvu#5a!wW84xKIk{@6EMq*JhofXhmfm z9C%`4VxXMwOa+wo$Z_m(B?%SPX8>sV5Qbe1BOqo$6?V%UTr-kJ*hv&Jti^D?CfJwb zR0G-y95GzEmO1o`hdNTneX*a3-gAxwe1Sb7HB}YL%D8W~LP!EyK=r0tLj`YNzt2)q zf4~9kK=Xewqvayh>50$wfTE83$|x`7^jlE={mFqZ3-6W%EOlG(Ta+h0`a67BZeB)y z(A<{wYm1*68ae?Z7PB@~suq0CTeolbFrp;IDa%^}kN`-{N-q2a&;tqN2S5%GKUuC{ zj|6D5HEI@(q+h5f3p&t=ByLz)u|XzV`Cbvx-K|1ME7D*VEvZmx_hWs1eM%vj$K-r_ zGy^LXWl&ZIKYNB>f4C}+;De7YzXFtUvV;(92Sq5rVuxu|69yERNC}Aq)I6;M1bc2R z^esS5j38j7aDp(oF%!WJWpsW-j|IY>AW$I%Y`?Zv0*sz|dX?94 zMh1*8kck~Ep{}jgtVu=DODd@X_!sruyyCsP z+S+STj?{b?FJ7$DEvenag$Y>>WXZpN{n}x5TogiXQ#kpx^{uU08v+KY6bw9y=g*%v z0EWM%q+|-Q6G=hfp3XihKiUF?_-mi%Vb0`Ih5a=f>D7{~@ zs9wHuB`E2=-H#-A%*gB4RiG03m;Y=pjYL?cqkQ8fy>}e0du=Z^!jMm+qb;GngUEwa z3yKWBEpW!w`rvJMIVm76w?N+50J|$|r*AebTL((P5*@v{6G6BV9 zJ(N38Y5!m)B{els+?@+xs#u@&sRSSdZubdKR>5juTAxNn&ZD42Yqf(CKPV(*6P#>w z>21j%a80zdv;c-pXIh?uLun?!>AwKhNtwH@1;{a(1g`tY;o(tm8t-q;10B>~@9WK? znk0AY7Pg@EkB@>I8ymITgUV!NWKhrj8hK0ECw0i_y|Xgy<>c;e359!ix^%i`wt^-~ zL*oVj(?ls>F(~P?q^fIbUOs<*19&fWsr@UEdH44Bc>%SXnwnNoAdE0<1wt^4Mnd+4 zQ)}sAFUbh&9``9us13NRq|{|KJ^NIlNC7dl$UxIWhVcNT-gu_K42)PVZ>fHf#Cikz zvrGITq4Zv1(#xpPGBc#2J=z(w4{I|!KKSFa*}>`qUInD5>R`DuI~&Kef(AS8^; z8{6A+O~H6bi4Jr&CLwK@l|DHBZ4{tXAhT@8t73qx0_R})^{twWEY2YtGG=d{`QW>1 zVMv)sF(JT7p!zBz0^tWuTEoc^9tFZL;De`OVaDK$@9ihkXs!bX4%Gz2I%>cDc}iS7 zJQ(>kaMNI!6j)eTazhYqAxx6qQdeInu31IR6y&ABqTXC%vqnS1Ea@O2FR?^Ps=2U%%|dSVE?&w8Py)cK5RTTG5w z*MW93>V_jO&{oyw;Ld+&t3@I^y2c!W$e6!NdWCwy$9&aXfjTgy_B?)1Epenyrx?$C zVCGeU==1I8`adFMKJKf{3=xd*KAD5v=ZE|kBvj0@&y*DeERxp}+Ol4E-vW%GhKVJ| z{BoOCAR@@$3TaHB7tvHzKQW*}K^NdfT3}SUmC9L5BufUeUpEC_G1dA9sv$-FpXO0ylG@uwn+g*?gZ$fx17TTg zR)RJh{E0n?E6@DQM9hp>I7L5a#;aWau_0cC(pg8$PU5U3RW%Lk*6Xwq$kt-F5~Q}7 z$ryralqd1}FjlJW-=+P%(Q3F;g#~`s{rwl?y@ivxkTH){Ju)$()#Y7MvL;8xMX!-UXewlEz%O1_tz4eMml1UAQaSL%W_o^ zU0si|R&re9t z*3B&!=fCSw473_X$U`7!p?*+F5s5*btMzmaB2G|JRh@@g3VH}(tr3(6ue#YrW6vmO zw(#p`Q}8w?^^2E{Xke;U6|dY*(Bllmhuu|V44IWL{k-pJ<;4x6l@m^atN~m?LW}V# zlw)_YFcFj74`9_UL8k{Di?GEGP}+Ozp%4Hi@K%fdWvidR5Hvv`lQ+`e-9XPt-MnEKNwrGl4`>jC_0-nOe?xQG`nXwvblZkCus=pOO{* zs<}B5m6;33f+?iZAT$oVXG^0S*fCOyeBV1-a5F8Vp6Y9GCS55>t6-QIXm8vkBkdX} zGhBaKysr8nGr(&4UFy8S^gWfDQ=%j_ZHP6}H-oKQSWv)IOP}tmUuI?|kv$Rxrb*&t zZ&u=Pr5t-;RB+3sy|tquGE0k0Uuah$TbDVBF%I)g15$^zD0wCe(Xh652oLa_bRK_C zCK#@Ktu(1Y#~*Y6rdCnJvPYMw<+9&7FQ^R;4J8WO)60e(Yyh8(P<%jIwMy=eqXLN| z@A0dxN%!d0VlWr7uJo+)yWiNZbL9%hOT%*svS%@qIs8D*k6@$9N6=__0fiROM6 zKZ;gn{N;kaQrZVmMU0p5do(KPqCOs5y(y(GJK7|S=YMeHo>2HBn&C_{jeVjFK7&>J zyK1Z%zw5}HXCm@%(zp9e-4UpZ2R`7dQlOO%^a^C5pGGV@TvA%fgLDp1um`XOsmT$f z)R9TuDL#-H{`B;;;;0K#g1ZureA`qvo;bx_>g~(g1afvhq4h5J>J3;_c)9e48G%B} z`g6*cmiis@Z?>BlQiixSD3E<+EDoBPpjS;;08PfzFEym$idbAQ6G5K6jNixf;enK2 zR+wMy_MEFAbVb!@>R3!{alZNKp8flfX_WJ>-zn8lRJ#TiQESoxb5d_#rpUfo&v-PL zJ6R<2n<>S;z@BjH1uC*QipPEOY*Bu9`H4&?PWh+7o!uDv_GWTzX z-$1lcVB(@Ki^Skha@d-mpcU5*P=sX0V)~&2s-a`*hKwc-qzuSjC!ApFX?9#z!!|)x zv<4^a@6m;`sw(nQ1bw-egm~G~rbpSuh=x;T_sVq|qcfCFafVhm77tK_`j$3XzetEU zuFvcE`3?j{w>z0$UvkUNS3v|V`=XuJAM2m7FI#ecstaAsJoTR-6_0a1xAcyd6U8bm zLw^n)d{BI_b8xlVlso1?7%x_fqN3eid{5m{)Ew`5ZZ-t_jdms76EUCj z3E5ScnN=02Jia(fs`%M!nzRO40yU&MVoMP}d-ZsIw}iV7({2u#p$TeP7pQ^Yrf5-O zq`=Pm)f+Oh5;eA{>o?YJn{%vj-SxXCC%U}DkzD$c{e)14BWqWDP|32pD+SW?Eq?WWbZyGits-KK1Ko zKx(5*bgEIFd=6Wf!OI!?fDa4ehO*1DMfmkPdG%&|`E)#2>(5=aW}`RB*O&DFsLIL4 zaY7bJn&eGk{GB@T&u+A4MP!bc!O3k->AvP9Un*PO6ODKb4!RL`!Ze*ctNW$*R1HzG z%je_yI=?BEm!3#qEf=`zSYDIBGZ%&2_UEMg$mAmBv+8ET$dP3Xbf-)agu z3l4f`;#LuLx87Cr3rIRu%t3z}^C-uLAOFq)y-H1cV2@JpJ5Dx~SoFtZHjQO=%P#5L zzS{ef5&QkL!@m^*+G033%`?6*L*#ggJMcQrul#8WYpB`5{yEn&a&oQro4&X|YtK~J zEvN5HzSBp{?>X6GST?*0y}m%n$@(R0Gb$rx#!)=}<)g+|5!a7dOYc?dCy84+;?z-! zRJ4G97&rIEJEJaaO?#An%U9<(J;@)x$>V#<_FxOvk zRw8G<5I$bpy|LDMXFx3bH%aubnoJ!H9V>6{RtSzL&i43hD>_ZXfPOb$j3E?@)+aK7 z-P*|cQ7llEHtEKm*Vogzej30sgYnNit~^@8z@_ZV6MNj=DMAFcIl9I{M%G7-eRWML&p!Em^UYEce6eU$P zHT*7%8b~Uae)FMOvw}|TzQ8W$YrZ>U)A`>C^TcxG?FFuTY16b8(S7%p&gKd?5O;~D zopmCM=5ZNN%txs>J`NOe5*_&!vXaO5V{%7>^bg(3f~PaoL0kveci3!(nNC4|2NJ#+ z1vrG)FaDI5!tp0|#Zo#@tuw|I_#8V>?@v-;N`zIE600V=8AfE@3`MGFr?2*_J%WLWsr3!|CIi1*F2F|yIEqeYRJ4RFv^e6}!)1YP zht?SaEy1*?S;5iDa_w8xCa;rL*yCK4mNWJc30ame`T7zl%=;mPbV^X91H(NEeP*N| z2WlS&C#NQx3a3fm-OK^2&pkc!Pg&C%?BJ9H>?cw{WB?^NJyhaA;v$Ih6Z9brQN6$^ z$N}#He5=mR{zAI*&+bbsDzE&1ytt~o4rR5la6(Yf1?UDm+$_S3LeF}r+)^DX zc25vXuq7lUpxS{oLnLRVrNog6%|O~!13y@B8#>0JL<|-{QyLZ^dYZV;KGQm&Oe^^@bo zvn1*}9No;?S|93k7sc<)U54bWKtI`?Gx(@6v{RH2~w zGKKSL2WbbiPPSKn(A2lg9yAtqFN*YB44JI=Nt2$~UeHkUUQ zO)n>;9ifw1#@56S`Z#xYMd5Rc^VP0=UVq2j{D1$8aC>b^1memQb>4^#7uW6RhY&IJ zqM$>$$BU?w1Z{?=ppJT7RkQjr0wSTwJ&IPrM_-=7-jNcMk~Y8MHA5Oq`$axd42bq^ zcM>Iy7Gi=(nfUnlK7an4@ftcW@1Tzn4sBLCpsZPecAh~Rc5!+}9o&M@C#4HGdge1Yr2aRG4TzNrKr%bzUoDmC=LHx7h$i6w-CUZ)P+Gh7|c4 zIB-xN$;qAES_w;G6&`m$7e>L4c=Ix7*dPS0nCnstXm8koy;KE_OU$65>&Tsl=H{A) z%U_Dv3!r8Jy-mpE5|E+@+ck)E)__@j1`#40EEvQmp>^K7S|vu3pwUs)(z=MWhVwO^ zK*vG5&dc?K-47+;oA(64MpbV^kNf9mR19-0q8~$aF4{(Z`{s5vzlDyRoSgFYD>$yY zu8u>i))Vs+gk(M_nv^&m)JqtZP)4^m!(LkrWMSlhev1gv&HwMW_U(7@UC$--N)l0SOXe z^*|uGQL|iJFEP zplSJ!R#H=wtlu*eDrmPzBBVL!-$+Q%NUP_l%!?U~YicBpKZ)J2{)r#<@HmL=i+Y&p z-#=#JbqT{C=?}HpBYAo3ckXLArZV6km9~Ie)+{rX_j?P>_SWypNv%QXG_nQb00taz|)!K__O9H^juD9z;e1 zr6xBKy+$=O>VJYI#KJ4YifcEOj=q0*-1WWU5&JJNgi%|e6*qA>Hw$>no{yB$!Pw-9 z0(1x1RiRJ#t=5x2-kb?e22RKLasqAnV9(z59`(7#6*r%k3C%Mlr;U9b*Zp_vU9`u^ zafJMOk!T4G2oX>(v=%{H28|r7O7XVdeOGc&Mb++ne{|t)d@FRNtbqSsxEW0^=`kOt z_qnt4@>F@B6w;R-V)oqGgT(j*d*=BXjL<|_f~ zi;`a3Q+YZiMyWvL;7X_WwcG!J&{OKMVTv?oz(#ONIU^7yB**~HBZ4=OQuly8;vgzA z=oOiRDeg(`O$BzRiYI`+^r8cpB_;uN3kav99zf0oqeodnD6jfqcV6mb&kQsKw^dYL z3qUR&cj~(Sj8^nw<(O&%G&>RU;IAbMAeO8dQ5}VK*J*|a&G|zf@$ayi+!n%EmdbN! z`-*6u!AFWZA_7I$vkRbr#AxQJf@5aq;AjFvcB`@O&p?ZyxIWX4^v2A-zeicSEPsgv zMHXjQ7W90_-Nqgx`bvX4uxt=l4SqtQXbG{v5Cv>UpMyHN)P2n;oCbVle}5l3D0rVh zd;opLCg^tessH*~!f@w}4wJZe@(fVyw?Kx1ppZO#T9M~Z(6QbDFOT1Bd~&o8?V9yR z@^W&|<5BT#S@IE8Adci!B~9)L`MNy+ak+RFvd)F~HY4Gz={_%H0x?afFs0I?K|}&} zrvlvj#x;WvoQRec8Ydv=x%l_N7)AO_zzP>6V9RSa+GxgIhEyTiL2QK3Xx16a-kl=) zl7S!M$b`o%fnEK+MN>1XdBdv?I-xv}%m2nkEBxij=g(opc=HVd-vsv*zqLrFzTa6@ z6mis!ipQ%0CBtD>ie!`Xbe0BR^lD2VUoA#IE~UIevThaa@X^R_VRr|_#|~ZBD;-Ae z=xum={K`pSgXtnk-^mX&<>4UZcmWBT6c@j_0riekj!XWKFIt1Op2G=ee}=?rn@Yr# zgd_&RNoO+fu3B&(I3I!Wd9bikK_z zkO0Ikr8tg_F9!A|Ni0qqi(iUpKz1qsK(o!R(u@kzttJ&P(2M8K{lmhJaC@nz#4eOY zo-Hm8t@ncL6FOA&>mRYBPY&j7c)iCie=zrL?W?Zyb5{^vZePoUWRG-NjB5b9#7yQw zUW5|_DU@imX>!9xG%;*aw<|V>D+@ARqri7hYsYyLPetn^;wJq*f3>VPUrP+!lNU`9 zU^9q#^yvN1k4r@b6nAjInsLwu{!DczIBcUN^9RXc+2^7PpR9)y-%r*sRy^U+*Rhd{ zP>LjmnMTMR6+J(pl54wZ3p+I@A@-7xRaj>Bp=|KepjeJOZydH4HRa}x#6VyUrY|Em zmo@Z|<6$kD;sn@t?@Q)KQ~gd>DJpEdG0z9zTWcd{0=Iv!_Z0`DyeWs8%Nl-&>v6x- z9*y=M`Zw{$)X1=~6lQm!higI1Z>N(J8V$}xzQhr9yYdR zE?=fBqONTCX3r>27v+1dSY>?H3d0WMy@v+LYX$$5fa+ZTthbQX;2Cz zv~_^Ah+ac(t`brGB54lM@}9+~%x*c^LBLp^>y225RPgfVGUT#U=z(vQppNm7loq35 znS5k_>z3DIX6PQOUHYUEBETs8tCH&KY7h!Td+n0k+$TCouUMp)XZwxsk@*SRrAYcpyJLEiY`isDowTHByve z=+s`Qg9TR0q*8tvvZ%|Mzq_7l{1OZML_k8aPflA#OoLYzxj!+mJJt2nVP8P@DfAn| z!h(wFNEtWO@&_@%AJpHt1Sg?09y|W)Vs7`mMm4&e@C~rR^3g8F;_I|t$r>hSYs_3& z`8p+qcjqJ62_@>*h@FNDZm-`>HlDM?>3>;AdigD6X3Dz{T|cX_lD+!707vrxetNK& zhLnw|&MW`>Z#Pmf6!Bpzo`{+@zWnFK$iZjuBSXNi|9nFI=i~n$pJE=g8H6poJR~L& zO;1AYn@XI@ zBv{mBgvr!5v6zT>ljg8u94XFm_y{sgx--a3-^RBT z>_&a}Exk&B+1$3vNi>nlJtg@HbHBau9!9yWwrwPROTs?a#CG*w_1AI#bj=*Ps7DXx z^F)f%BD{b6-rK2q7C-Qh~rr?<7?yGufr*5aVsT=)aaV9=Py_5xYXhepRAZ}$j` zo4nTv?x9W_daV+bU00Yaiqpr%Ga@V&Y0iX#9&Be;oOjV6PQZuG8NNY|^IU zbuAO54ZoLtt@WPeN$~EN4(;!S+5ICN+uMN~w#nhgNeRRx`$cEQ{h1-ka?B;HFf9AH zi;9GNJ@xxj%jH>Pyk=b#vERgf?iuk-lBl-}rm+Q2=EXwRZcuyRl?nO~8#H6VaiFLa zzq<37+BkDPdq+?zjKc5xz%DYAWE%UZB^m}Ij3IY?kGjO1b-rF(e8bk4*4AWni6~2? z&vKUM+JoTi=F6qE9=r8XhuPkxBh_@11L|eM$zddS&?ldsHkLoe4f*l(ULN;kxlfh! zrEn85hxdp4A?4Kdq+=ULeJ@8NoOn==CKdcOclcKHB=PDmA3dw07%j1W@}C29SkaTl z$_+eMu8*~%O5b+abJ6w>*7SmSJ%+&#ah^`$#y;$8p+(jgKgGc~KR0@+PWO3CzLuO* zyrg9I=|Gf+?!v1PF=P8po(cPS~Nv&=%-;FKv;*fxsqc!yeA#~E^UaYj5BaSGZ=cP%)Pp$_r@X(DKsLRXE z`S6`to;3ZC%xwi*-@@AF3$NyBW{(f-?vZNJ}?rY`-zIZlzaMv@G zy+froj)9MdL!h+~^#!e|OFQM#SK4d4jA-@E48~uUa6(dNp1r#bHn2{2`s~!=hTK&! za#nF9dTfS*OElM*QPgYyGTz@an!e4`j9q%47t@xcN;>_*emi1bh2Q85ew-M;I%3&j zTY0=N<990Lu!W3T*_wFWl4mwVT$!iigC=05qmq_N>I~?T9_Q#JX6$L!- za7uC2X2v$~>yNwGJ34#(n}z^9(Enp=5%bN*9d)A@?XRvZEi_O>rMq&_?J5TD5j95@ zbzs}7D%_a9?bBX4rHUflBs6;@7B$()=6z|$f^^+BJ&L)QUD|lx0p-N~p~V2F=0LO* z6+CO1s?>fwz<81@Q-B|sZYHPOV#{|Ptdp1ohvm$%_s!TPa6CiH1gS23a5xVuILcqg zeYGKMT(ctO!}?)^!GdZpe6OPW<1x=$_om~%(8kRThG15vHJ%TcfejRD{&D5eTRnvX z7;7iOjk7bKJRlA3*PTU~�XCg^&PFw$B0o`LT{me1~pLSos{D^zycv#IL?5<{O_l z#~HTU4_$G;d_&iWjdb;*L=38}g0X?k{nCW5a>gS5myI4ck(`yH+>HlK*KX*z)=qMw zaUK;8iEq4?#)@yneE6?Fq5i)=63`okKoUdRUOxf=%yEFd z)>9C${dbmyXk`gEUGD!gOB~1 z0I!jGUwQ89~?=5mTdqGDPQr^8z%lAzD+Bi3WEdV;!))E zaQf%P5Vil;CXVng|C`JI{Z-Tz&rmk~@8>v)ayC|91w&K@K$QH~QeFdA39%d_^J^dp z)GTKDaDdMH)?MKwS=g5gW$`D<_|@M24tHSbyH|q6iV%qYVkIt7NNBWlCvB(iN;jit z#dp*t(j%L{IIw+q?H$9w_vlZ{VXO9@+9{s>PiotZAEkmTkha%a|JsHZtvO>YEt-Od zr>*%*9@C|%eHW?^-z#PA-kUq6BAI7;gGu`XJBsQVA4;&1{^`G;J2H87rvzi@iK`8( zLY&(aAi}r%d-aFdxay`NZ%w|e241)3p%SXsb2#5e**7J=iQ}=w+u35KTa9Uujnzm( zfWf-%19^)%-Cvj?TSdYm?osJ|H*Wd2_6-B(mlP6{$n>_O)kc?gn&Smt&D4rp1YAOe z6m>Kkd#;}>llx5OnpQ{om-BtluPePTM5cm;mKI55qHBXr<*|E02MEMgwS8tm{CT*$ zI-~)6rb1fCVmy!jycS5K>oe803p9ytD)b_#Uz2KbU#II%l7uuPIr}$SccmHH z096in;waq3*X{MI#Tsl_ZF%;I{y`guEdj%o2C;pNIl3lyhpQi6Hy$zI*|*uyeyzv7 z>mhYas(XU7ay`8ztSG{D=Uf`Mb?BM;8{ssSbmd1+-L>IsR#{~+#5zGBzoSG)R<6kyMf*N$8CxqB$Zo8L(E(zRU zIb+$mG6T_r59W0BL=OwUn2~DH#erQp=f{a$lDh6N=V!-I&fXTGcl21m zPq1}++`RtiHzoH6#5T8Bpt+;-@@>iwle*6|(#SfTm#*WAH zp9-XEStT8qeA_!o`q9D8X@C)11<&8PU#su6Z|hWT_r)jAyzEnGDBVA>MP1q(hzgc`INT$(y(C#@`LkPiYWzY+~&TI&>82fOZaZH^OFT-x$?j zu8WjhdW-}7SqUV=*AZmex9+0%o0fyVbBefU z7FK(%h@O`2%(&0lwBliato(;>CD%P*Urc>~P z0y|ck#Hl1TvihaZy|`f82gw;fGwbq;bFQ%keGqEiVWqZ7(dSePyNvi}{m-SR-RD^Y zx!-giy1xEhwyNkIW~K3+*S2h)CZE+0H5@*<m}{vSJ^eL>joW&Ad5%rAcum(w;X&Zc89G=%pBXVk2cM@*|H-dpS#4>YWuFz z{jKXC_BpX)UERf&d+j|^c)AMNiMBB9%L@7qD z(VGOuV8%~0J0WF^;nOb9bk@|)bY@-0o$z6?O+pP1mii2SUx8<%KDV3b$#kFi zpR;uHHhC8C-9EV?gyEi`zinDSE7I3(cK|)F*N*E|U4_UqE=Ym(g+u+x-dBQHSw2%5 zPK`;w`;{`0;m-NjTh7HbvYI?=&sNQ4pP4IUtHI}KWFtuF?e{JwANi@zP|K#;gPo33 z`1%04wSEvQ!T01{GGc;vyfV%^Xe2MT?&RB-DrU1=UMq%mEKb_G=3^kDV6^PyqHe1@ zPl{eU%GhRpDD3|GuXCi%s`J5NV_R{q|48{iM>h3qN>sLUAw6yP#bjG2xRtqWe;(z~^*I@qrxBt`chE{D09=m@L;m4fx zqUpbrIxQ#JHzMTVs|rO^^naszTCR^}ZfF9jjBmR?W(Uh}NK@Z&vh#MF{K98GOuS>c z?zf+wY{6H2zofdCXxG+qQH~Uj>dfDeYgF@Y-|IXf-v#j=(HC_5!_UQP?*>ImK+WgI z?Ddi@JSyGu>6?JH{--qoH;<2E1BP>#-lf90Eb9gqXA{DvEk*n%z<`e1zbIRw=+xK) zXD1qRiq4tr@RLVNa^X7voh|Kg(+l>-`>guBc*&oH8;kKf?(Od<{vh1SOC@vXuY3+v zIA3ox)cz}!!~BowzJL2N|La%z&-0Ie^-2C0mvHmm2=ikVuWN5LTCqqpCu5q5vlrT< zQ_)`y-HrW_KltU*n>`Eme>Nwt4=C$W z^1q2vg&f4|oMp?-gLr<77E5$Ri@?tT{eb9b>Do+%5EQ-{enG)feNsoF$9y~5#YiTC znp)`T)7l`&uc8X3_C2?N!N;T$ z`OeL_dRVzoQ>8#Jb^XCnr9TzTqmw32zPjnx8LF3Ym(T?_(HX5^pL0LVr+U~$-BTek zk*GgIU82(9l-aF;Ae6cx(%owv+?sB?kHKmtxccf8NB?P2wr`N5yG9w z>n!FvDXJ9EOg2Ax2YRyKT{_pd9DRG<^DT0n<8bS!-b8W5+1b)_Ms_feWt?(s{5m~klpiW>ATnYOMC0~@znP*)y#|ld z`Bpvk>oHhdEnhvTg$EW0=w!tLE1}M5R2OUW4=SUD93^kKxp1Qc>WtD(A+oxl#T{wk zHibHYNCRg+A0`*2l~*nEmyoC;=1?~$%&OwD(JD+^!pUj={KykneG9PCP=+i)LDv+Y zczUpZ9aCp6s^oA74MFnU-l#;AJIy2^A#G336)4ER30nGDV&1$HsKkVyJ9py28}gx| zzGa2&_YI8D9I)oJj3l-gggb29B5H8w>Uss61FW};5Gvs2IiriOCSeudP@R)9lwH=n zpX=T8EfGRQl%2#N2I^xjUc5+6C2^Lo`K3Md_k%o`D#kbprt74Z$(>TYg=3Mo}4S#&d_jOhDAvq*(RWWGL;$eba;M4uMpjO zAD{|-w5+8G{fcC^fWRkSfHv;Yk3uDJw@+r&(22*4E!_q`n2cSoPNR1)!i%~=Nlb-6 z2WSHj1MQ8}zKCt;zHB-fEa?uktB%}*imzV@ z6>LpNrRWzt*?GmRa79%1@7qTS@v`>l@p)6_-k*Mc~=P5gC5_KL%FF%KHFOS0wG6>J$W!)U; z?2$yYvq8fzwKbz_a0rcrT~lGG1|OeKUtGy@EMPMh84kc13l{LFJb!@J z@j_Udyd`fOC=}@<7BNT1zxd>aWTOqb`_a;ls%snOA;?m9v|f~A z6ZXdroVnCE3pI-o4mboeO&#j%#&1D3(gG>yiH2kRGs!^;`|!?g++y-*fImqK#5WLO zw%wZ((~3&)JWpDMvu87Y=$YNqTFyU2_yBHoSlh*NaHxPIMtD?IKm+;<4p3l#YA3bU zk=$Ew?iePUDM4`s`3-ItN$%zvU-5eWVLPn=2!Y7kBn(I1YCXMKfBoo(zwkpkN)51h zb__IG!7B!&p_!egYKwN|Jm498l*jP&IxV+l9c&7_{`L`iG6Roe$S?67G!LF6Ae^)A zd|`VJ#mTnH7=8FMc_IMQGNFLImjDg05n?U^Fm-<+#I9<8#9W}FwGNs=p}lS2`jh(d zz_XcyxKDybFNi6O%&~QUd%#$?{8g|ggAoVmEym(m*y6GDSseV7NkcHIYq{sr6%a4z5f%Ok{jpHLy5R2JrDpc@nsGsQ}{V1$mSg{PK4Ih#@MA1vIs9-f` zzJFcz?ZvjCGw_>v^pup6FrVvx95cMqg`Bj2wPEB2ON8 zuqNxvguDz}p&HWj8`;ehpd(Xp@01|zBOW964-@5ubKB4ew+6dM3Qm%$mmljukItD5 z(TB^D3w@<`?o^@0n#?0;d%$W7J!(>m7oQz-tNsym1v+|q+gr;+X>+x^E+GS;vCs-Z z6PapPJp;Y*-X%?q=3hV8pF>0N&<|INtvD!MAuWXFlG!`(#hwmnHN>ulLp?mB>mR0f zoq)Y9ZnqA=yCMg+dtDz8ym6ao@xwt82usTzD#i+!G}*z;W}~^wc(|zj^h&CZRUc=P zVyRaMO|~>i&=V7-2t2}qryTI=3_b(wWdyQta4?X%uEV48T|Axd^TA!zUAjFm&8vcb4{N7$Djxh{X7Jm^-3_<#@Qv25pMq_R4!FL>7uLZ) z>H)SM^gWQ9@K@pS4UvBo@BafZsdn2QD>v(ZuG$Vol)eVV~uOph-iz`35txwSA0ftv|byX~# z;-?Nh{#gk7F2Y;G7UDcbhbIh20ZbF7MLzItAVV|cDzz}cs9fGF26SA~h|&R@zV2`EfdRPUIoTji{NYxmem4(l)iyA48)}@zrWP0iqi7Y^3Qw^Ah#J1KLhBT_9Faq{=C?uNKyvp z?Ah*=*QHHf4$wa$h%kxSq{xOF5~4>ZT>~ukE@Cwdou@Pu$n>?x2iehsjLfkvlc^(l zq&PR<;e36#*W%FzIIoZ^RwK|ES&~3x_1G^WLV&VYShSG_31$cp5im6XriP4prWIBJ z94%Uq$ZF;=d){=W%bXy8H!p0Rkcfzt2(|9;AE?E_jV%q6+H@Q+EMy!43y@h9NpPGI z9EbdRE6gI!pFox*zw?<43whby>bQMk3v52l!fz3RroJ5W`LuBgY43+fYLYG(SVaPN zrv?()3Cx5EDjRWUYyoB<+HPuhyJec|`itr%q)~YT?~|}}V6vyJ207~)6_**ZW*LP| z&IVEcqf6D&*6yy-UUobN$13E0b-;8(MtEBrB(mq19~3HxkDo!!L^!XdN9E#>k)pAN zl0f+BmLbfM10!KGL}Ply07Hb6_U4#V(hkM=5QRvlkd`~X56$po@*=^3%SxyVVW%lF zBH|9PH<=Q7LeupIE3r8eC;+w=&Ob9x;rt1LbLEkqL4SL4yD3=;{r8XcNSdEiRcvMT|&j4yNI7}05E25}FsF|#I26{X65iJ4gn%gswPSJ0Z$wqN; z`GW@upeu&Xpk=BGx?u88av?P+QW1KjHFzxY%q<4GeT1vfL~}Py1|}L)lpF*IPE7GD z07#~g)aQzZi1;m}5Q1%<$K6JpgGP(j!`1ls&SR^OJqwSkD zYgYBG{kzGb`tds;S-*3;Z=c=Lj6<955>C2>2njf6IX3ux-HjVkuC;4R8~^(|8;O*3 zLTueZ#;6P&(V~!M{$wTklJhL(&>c}wQsfBR40-D5~Z3z-#}1Kyv6rklDl5D_#}!G9Ul zA!(#2C42&nN}*^|limc=RhY;OS>o}OVaN4fM7m>I;JG|9o&bJyH1o(e3|>h*%5{al z5#aD#km=P8jnsMzU%B#uwXq?l;h~E6!X^D|yY}c#)?#0EhU?+2f*#eqy#573 znV)v%HndM!95(U4ugzXsUH%@_gc8`f_>UE_-&WZh^pXG2@d>IthpT`eKbj( zeD)HD0z99u7|-?O!8W*q-*%zyFF5M7Sksvvp*yR94L<=3s;0I!zfQaE&dyj0F<9e^ z7C>a~X^)UlLI%?y2d3&X`uaYD>m})Jj!G;uCNnR1{lM#$4AR9G@9|l>|Fgm7%@5E> zK}p`GRI9N3$V2cPMR#kZ!UA5`&X5JuV?(J&ULcI0O%2Fn4He4w=6;t2O#*O}^Th-yY3CtDy z_}#G+Ct8qtBR)@6R#rv^M(rZVdnAx$)nY5w!r~Hsrvn2Xu#}>XsSu(?Gk0zTvFKOp z*oK@3IGwC|qmq)6X5uC=$X?=&u7=cpazoc)As}lu-2cv=Ju7`m7dC2STZB$3qCFAL zypuMjC}3BKy=F!Z*VWb0VJaHPc1pK&XG%V0S1>YE!R_D|6I)A2m9XN4rFHoSh4uCI zk$MnPmlYHiPT%=_J{}Z2+Kw^DIN;Tr27glEm>1yAczAeV#*3W#F3g?u;1-DFh)3r5=-zkWjjgSbg+*Y6Z9-h!5&UHJWqon6`R3U~Ux7q>^7N^-yvP|iG^GL0 z5i<|B*yB<LaB&q2q z4-eSSWm|s@fpz4*eM)em^z&n5$ZQaZCuBTq%t6IdTa}$%p+jaGgx4gkwjp0|eC~EU zI~aSxC+i3fQ%mAeu!CWTz%$2t?l1c6XjWJ%tqQi^uXb_&1^%%Gc=X9mhqJ`T38)$UO7LmI5kL z?EhTX1hmh%dw8HdK@F+JivmU!J*RhV6wp13JYzc&70MD3?yMG_!zTr$>M0mCE|_s-o5jZ#za@xZj(07J{M9baJok<}PlUx_0}8Y?kx{`@xbRzdeD=w;{kPksR- zQIdZM94k5BG6*d2CbqY;BlndZJ9f}+fI}8}q&Z~56^=+TwACF;PhZFj-~Jt)jYXrK zsneH>)}kNy0M1PLa}~fQp+Lluk-}+s4&aHYji4+KVWT`gA%Oxu9I02jwcO>Q$qn%3 zA9X83{9@1pwaUcMP#w*JI4Bg!t8wn!xxgBl7mchH&K`sHE`Y!L!Gqfto$Ch!MX)^W z{(W7d8(~8VY>#!m06_tUe1RX~i(_nT91m6faDe7t3gKD^XC@}p0~8WgD@`rK#U zI@AwC>W6WOiL7Vqo#w!+4`j9&3{yp?P9@_w1a|Vt23dkgz{$X5o z046`wRVqxJFMFmLz}rrheeVUR#*;&yrhxurk7`4#7Hrz!TD14K$ISfYIX@P~eVhsJ zd91FPNms6r`5_7^HgKVX?;4 zbP74x0mo{%wLhAMjHWE*!UWom6Iq+$gv7*7VzDY*WQ@otn24X@;o%HpBcozuE?D{H z=g*(VX*W|?}7qV40Tv#oAt^RUB6gt8n6%^ z9y$OE(qzMb@p3ZAypv5%tW9~|!nCw#ZrC9B=+PrZVOV?ux+2lg2$LdkK^0ciu5fDK zg~K-ale4g}U}ME*f*B{%O|W}35d|%HjhGD^w7|Tf-<^2MT0BJHTD;y-tQE?;#ooVv-?spFxE=W^ zENCThY}`@*$4{_JHtqd;2RxZ0M~GF3 z3&0<<5X`7>07u(nQaZ~}sHHNPPFSDh+*26wqp^2(I46LgnFpcV)0Vzxe!vONi8Q*iYe{&WU8u z`br)Zy}dh7s~~UM3@M#SsKep#-6K~p^1Wj*iicYce-)$}BS?t4yaSUHs>{h56#Zy= zJK<#-wLa-7Fr$rVpdSDW62g*7Nu5dLqk_;ypEjfQvOtP`#Y~fRa{O zuUrh~o>Ej)be6;T4M47K3TH!<6cq{O;RI8q!88C1WN?X=X&X;ZPt2q-+_1q{6ZX97 z>Wq3hsRaOVHv-e7VSgK$n?KCQW;|Lj^hWMFDp|-!X6Q`9n58GrpRdQ#*WA8+7P9B~ zi!il^uNi<*`E`?dFlx;>jr`;0O(Fk3f1{2{Zg5B_jJtHn4`kPjsUVth+MiiFo3Z)& z^()oUU}atv1_N^3w$))iAF&h6b6q+80ny;TTMU#EqO@pH8j4<+k#QVPou>RW5fl>@ z747`;WhDZpB2Fyy8`C(dv)G?V(BWV_)*nXdFg-~lGV(P31GthF7~FVUk;*U`cXxaC zOvNstK?ZSodFP*@;*|hPS`fO87~v97ZMX6pP%OFK<2x?<_FY76Bm-H~D$H*Xo^M_l zmyscmP<_l1ZVjk+Q!NW5#L16*Oy4*v^O+?JVOM?Dx@ufgRi(Dm*T*L$Iy&f{jfQQe z*)KATOkyTH@2{k!Tm~fc2e5(BU#T2Mg3QBhD6*13)Wom^5@!5yd@+6)ho$UPhXy{D zKyB|@M_cqkV z?F6RCaS;J@T=K)pYGi6;7ELkVToc{7Q>&T+94AI zU}$JbKGHRsc7bC8Wb9o@obsUY!%(sZ-i1#%a)ZZVbkVzCL(jp2jSEw8)K@c@XL!=4 z(CL5;r|Kn%N_yJ#K>Wl09P5KB#^0%`1qylgy7R{X<(;z9otrdlsGxwi1eYH7)FD*r zI5sksq0KyiNNL;?q7Bk?BAVc(?u;!DT~9dnC$dUxCxCCfw2veFk1|Pegb*pQ*UgOz zX(~twu;8&tku}-?N&}Z+^25n`r^~l*Psh}+qeqXXZjzySDHI<71e&3rk)uXn)M02M z0}?abq-rx_n<11@{r*lLmy(yCPc&9?6Abjh`lFbHstfb}!v|nkSO#qqk-;GU7xPd zg*Ga%0_CG{)_hq(G>{5d@OSoEb>cVB%sc}-1Dh-)X4OWZtx?8kgsI3Sq-W(|Bu29w zJh+Mj?(POiW8~t}(qPP>jaqKM5~(AwKuU|Y{z`^9Wb{&3U*CUGkP#HbV1<5t_>9n> zN;J1j_u{0p8gZi|@x)XnBGqcgCC@@ujomxE9{Ljc^s8|Sfx-Yj?%oU33Qww|Ribl$ zJZhg+&v0PSkUGShm0?l{0_CLQ1F=dB7Ai%UxzpU%rfp=zOyWf#wZabih|(DnifzpkaKgDT3qXUAd-$Um)k;twL|Z|9 zN!6{pceMeqN6BGPOp84p$o?X0?3Q1{3oemn?3~z9>rYjaW?NG!26GD{w*)a{FxXutFco= z6#A?cCWX{l2Z0WO9A{Zt`d{x<$YG3N0GC9=|8Rnn1sA46&|HRcq#oo105TFD-QXNf zAbNvcLk6_xUCk^!&Cm;wlKirsxkSTvkoVVu`@_OZuSKgCD|U-1jKfg6#ai*l$$|ii z?B^h`4uEYp)aOF;vlO;ZC@n3;1PO-gqS5hMYM*5BE-Fm;Ep&I52OK|6%0gfd8`63pW>Iba z4+=?h4e4Dl7!jz#^IBAtC{;NvEvMtK$FToI!OvR z+?Vgm+qs9lMgj)dlkUO{p7dN-rOP5XsbRy#GdTuVc_d`e;@Dbz4 zs6Ys!RB|)Q3pk(wZuw0?Y2qNojJQ*Pg3hYr$B)O92~ks!bIjnYhD~WUoLIx{D8pLe zBsw{5sSpyTdMAch8$!8l*aMVriDPOQidt$W=H@5w*);o;XAF`BocSTsRvbEm4@yQ^ zVsMvwgsn-#$4IAX`FEcZN&Ukpr4uv|4D$b>A{v3A#vExg zP9@T4g7}sJSq7s%aPTDH0I0XiG`rp3HZ_+)rIvCj=O~;~&ioh5Q=%g7uHYknY9w@+fkl0_O5=5qA z@BZtL#{^IKt;#d=9TcyKl$6rTi*VD76NFJxw|p*h%Iet*rGfMJfql3M{+d`-6~6xd z2|%9jz7jaQa_w4iZSC1-MAKs(pS4UWgQ4EFYje+ExPa&J2J+)Mvu2HFN38;SDe`|q zLWRi|O!HqEmTrJNXH|f?tq9sGC|^WEblKR}b{D4xQQ*i_THs+tlm$4lgy$dZZ{R;s z!XR>fwCVy&$j@)^X^!sA|@A$BPAh3StuQHyYrimIY6<&&MEJ{i;BiyNU9pl5EKKC{1@)b3a8aau!Jbwj~4kE6eZHFOW3X@C1Fql&1Z3Z znQ^?0T)MzwX1je7#d$s(@>D1RXlG)0qPTyP6*J05hJthG-J12vP+DLpgjV{gQ@+R$FF)>D z|2wr&7yJiLlL?UiliX3jR4fd{IjRvCI}2H;Wyf1^=E9q-Ky!$uh)=%+i^p+A2QM$4)Xv%2{dX9&W96vdLaKj7Mz4GeA0|6Nd2} z8K_#UM^o;OUY zOA|+11+v2_D8V8XkHwq~ayCVv2P>?GhiRDfG(!MQ6hN-DGm)Fx5>qFo6F=)#eUL_+ z8gt1&nm(2NW45!UTQUBi2F0w&h;pd$0q}%iCxP8}p-D2lfABjAYk#I6ovTsbRRfq> zAx5k|I2x27haiv^CPo%CJcVDED_5^t1DN1k{9IO985|Zi3DrF>O_VRRnS{`1nEh3k zyYEEI&KIfH$lV$Z)~_#tA|@w>s_3DiM>G*i$;s1XCTWtU|<;d;n;G)S&3<`zY(8Dlf zjCh0##5v|n*>f+(H~y7*ih+?Zxdzf6fer%1@#uUN&_8K^y4FQd90IakO-j;4#fqRf zb)3jPefqQu=xHG^*QK>*QOIM&pd%{>Sq|pBSQ3MJP(E5ad$Ix$6#%m;s?SYuy}W~7 z5ig|Fuppj-F^NF5Do;?PfES$^u{9XahDa-hx)tTf&wxnCV;uxJt&23M6uL1afkwZ9 zK`771v@w#a;_6V1WJ;`2lEL0>az+uH2n1NFhJHm41Q3)M&1|c6yfo`X=~3WEP_gAs z4Y&2MnMQ99G#jY|4g|qi9%ZcFW6(6 z*tcXQf7KWf!xRFmUXstjGLxhifUuCo;JcTjZR`3$l&U%zNQ; zT2KS12$5toN1rxyD)h8b=Uqjs42dsXim`_L2T6QQl67XdCx$>Q^uQRR!)=O~94f_W z3b0JUg4i4M>BJEJCOQS`eGtA_Qs665lVdmQ{`&O|*c#{qW2@~@FeK$DvV$IGO*dxg zVe11|lMn<+PWioi*5J~>C;`FJMA>iM59HQw-n<6yg-4(jXF&6@qN1Yg-hq<3j?O9A z{{ay@WKI$n55|adYjPX|sv!$PfP_DDPD3Q^M85ee2Fi*uqwFCDgb7l9_2;)vBtjg^ ziW#?k>kn*C6>^fvs4hyvdpqAU7&UgR*)~sr^_&AevvI|U znAjLV1aVxs4NJS6$?=zzOTiM}g=ZS#eU_AMyDEdRNT3YfJ z0iO~TQv^*QMHvio$H?iDM*IkYY7}uEKY8Nw)Zq;X6C0R0bM$Upzg`n8B6taexXB`n z$g$3mAe#~8(ahcb%7ucVY0IPE{vdGp;Hir`nS{(!*~AYzE$s& z%XWP?38MCGkcSV|%$+yS-oYUrb(bMA=+(DkY_|%HPR7;?!6+_fD-;f(-6aMG8%7>c zMcalF0Sd*|BwNLfy9=LB@|(7QJ%h0Uxj~E&h9$?$Mdn81nrVg_lA7^^2LVRRaD6Sr@Syxb;10UNOBopvBTqmT zQ@F($u`CS&4@APXDEv_L?S;^x5L=sANR1CyMsF1ZGHrwfgGC{->)(9^#WmY>q8>bh ze%C88LoMPi?qF4^;&b2(6?&+W4m<07N{;ZT*Bcmkp&a-P?#-Q8wauSC>Fp&sBDUht zBwQy%EchtGO~W`{Xv8ld`v?U;IIuD&N~rdL<~o{4mmP^BW=m_UPnE~-R1Td3sM+Cc z!l%SoPyjE{TGaKh%Ss&=;fGhED2*pYIRJ!;e-@_Xcz$1k+6u)o)Zd%mz0<+n0LxqA zkQoMv4)Yg{4hXm(3Kit5Xtjxlm=BSG4cICvX&xF!Kt9=EE-QFcN_`Q&vkJb;0vXbD za***QxF3+0YrCNqiX*NVoJ$|v=mBskU@tmHWpip`*!41_2y7SwtWXBUDUE0Uq2-di zh5e4q>B+Nad!Uz~fpt)@d!drL03sEQ(HB9xBBkDD&r`OL$uyRZbMI#h%(q0zho)@P zI>iG3u*Q(o#7mc`S(T1NkeGoix(jknziP%6~wKZ zWRNBTevoM1{xh_#Gcba6lq_h2pm;kF{ODYE{CR%)!P9`zJ+NP%Bq|!9iSv)FgTb@;K|K8A9nk*_;=xM>Gm^2WA=c3XhJu+pIPETUV5CFX_6J!r z%GE^8!xYx|coyKdYC9=VQ%D(GoSTZrql+U5HB6*1U@{PwLhG|#ydg<;Mm+(54^TW0 zouc5`_%Z0QOq@AsbakaIll6*Z`8dB~uU!j3kpUG)6pOj1DEQC_zZ%rQiIA~PcY%n2 zAU!C46dS16jY1E0u_h|#U=SNGMp|w~fGbB84VA4!P%A+_%X?v+|K-bbu-poG$8=96GaUYpk2nky ze<_lfByGn71L@T4{OP3NbPT&X6j82y{urok1r~#Hj zFkuRO2BZjc-$s-}koWKq0|Rl2V%EW4ryrpx9`n~jp`S58T@y-JOp~ zJe%d;JU!<5wyamweg-D74EX~HW|YIpo*P{$k|;g`M}ZItorWp!)N2Rgl5%5wB;xYY zpdKeFIKTsnAG74-_%?3b2-Jo!i7JT#D4D1a)d}pVDwF)RoU|g47L)@KhW?bqF@Mp- z!2}!8d@F`hmLn;rDF*1m$Pf@0*N099a-MiJhtPpXxg1Jm)E!(7oKD#+3Aa&UMmPQu?y#R4XU3uD3wzqV{>ycT2aX>nKXo? zB>;6rX&ez3=#)fn{5VrYWF)Cn>%@6jmAqNm=7)oAPwF2V2B*O)gjUcVI$_!FT{9x( zwp>D-1(?Ha^wErARvflNfZ>Cz$wpYtvK3AC)PM~trG@q{y<#5P&(QPV7;AJj+vDq8 z)URW6aQ`QZh#b=dJ&q5pO+qs&9a2LQl}T44e@+GxR0oM|X=$l~9AFX>Vr-yflx~lX zDxZD`pO_!YC%|DtAZ+L&c~SgBrG_SK2j}2|A$honUKDU9Q~g2xH#N4m`$K_I;p>Mv zIITVpk<(m`_6VSiqOqexAAtro-vbNK2SEMc3oDmtVqe%_{XtNny5S4}JxfBu3k%%y z82Hy!VN#w!@$oYpcJ8DT9a`hPpX(MQ)rW`#BKj5@(oUDQ6Ff{19wv}9q#(%ENEe5f zFG1G?Cl3z}mGNhdu1YOf5DM;+3h)|n67upB*>M(Nbi!(^9f&&MJ1&o|DI4Iq8ECJ> zK4uVD9)ap~zLJ#GVhMna9u$o@0|}i;h@uH-@={@CXKw+6x%R4Yb9;LkipV7SB2h5( z!KFp`_!v;&mz%r9ED2wv=^zs!NCWp4`X|0H**fc0ZSFqkG3QefMJ0Num6)c_pC9ET zEg}p~4Zh$mprvg^t4loU6)=Ku`S45@q-=X-%&NIp_z7(gQy0gQC43K z^);v)wEd)*klQPa@-{=}AY5W<-nlAXuC@bZQvQdcCq^?&iYzUl;p`Pifh@2=vY3Lq&-Y-y7DMLac>{HSLon{RwW_DI6D08%;bQKrO5_tx zS?BvPTGHfJjQ5q%Z2u#EOLzw+{F;&3YFex)5X#tRK|0wJUlj4UZ0~q>b${DFE z>LG|CFz5);&KM z9XrNwOdtQVK<%>%vxAGAvL2(HXM@V#B?v;!qQ*pRF=+~7XwJRQ*M)8ZDEzy-_lN;k zFGh9mPsGcc%L<^bQJ)4V6Y?jQfjvFae z)fnsn2!|=zK1W^A~eDmI;N3%gi=!5~}5vE1XonVq=Z~r?D)3XL=^6qj7sWCL{sRKAz zPz2}Oz;XdHZAI5pIq(9Y9f^FIXDA=pqND@GLp-j`(J>J>4KqoD#hZafv73*3q9|Ug7iNQITj?M{c?S&$d`iNDbjrYaDg){~M3L3f=luS^S8R3Bl<_iNh z4&C91acL+sL%c!BBBJZEt~-+vryt^XF|~)1h3iPou-LFvL-NrWN;5^k#0IbO{TuRR z=*+)jewM8!$r{Ot(b$J*#yCJU2PVK7%sk5O#9Cm)4=GX*?WGNVHYN>K5_?GO;4=hb zNV*7gpgIxzss2_Z3c4&hVQ73HpC!asP%l+=VCELPG_#^02OSvHRDYD&MoxNpje(H4 zPbmt$xeS;dRack2e*i!HS(n0)Fva)Wxv8=MRD`ba(>NTk)^J36BQD|$!D2*wC?PQh$P-DhhiHu^ z*#c`5^Be078fOs821lL^wA6sG1P?!=F^d#QekU`B`at>7`#}*Q}8>EIFkWq35r)$Xd;ByOrOOriY6wdv>p5+62drOXpqE zP`LwYheLfO;lmII{eB{IUJrXDbi+iH|USW#-OB<0)4=^l9f7O@|vbtMMu|TR`!+;G|AlN={DI zF~eWxKrgs5fp84uc%+5I9lQlChq&nSfwu|gU2Aj{Jy4b;OAg4e+ECYQKiDuh9eGU4 z`MrJt*vV_flsrc`6KbM;6$i#On%IBJ?$!);1Jy z!Fj&7gh#ovVz=kytBX&B6`(^PKSkCw$L~n~K?$9XIkk?bU6)kg70O`n@DQdHAyMgy zbT_`p-Ne+L`T1XrjIIh0CkN5x>Iw@{9ei^@_(L6&v#_^*zj)Yij2C`dN@s5NfA>%3 z|Ne&bIcj*%wUW- zTG?(L3$D*0`dPu46Q9+>zHR1mI`Xyhu{kTf&obHEX~#knzi;GTmXe9^LLaSwZpz0P z_v!l3jE)~`PIaz8$pU@#Tv^xU6QY-o*BP8mH!HC>CXHddOT@Pd^C%f)iJ7Q!b2)kY z=?$&9V|rx^`>vP8&rYp=xu0&B)M00VOmE(V*b?ctBlhmyB?eg$%x#h3WxOx>{COU~ z*scOOA3+0C|SACVXs~z|Lc}S!a*PAVVuXku9t*A2K*%{;a z+{r6yW35iaQFY;Buf4IKCYC$-X0Eq-{k-w*oVX2J`X0EXx=lDR`LguY6EaYtd}39Gl;6&H6e=w@!p98u+s*U8#u{dRkm{jx;e zSX)V%!C&%*3qo4$6kJ4IqsA<(^gUf4+rbon%j|q&xO(u`=+0Wq9f8O^dYMoLb%h@bKK9A3Wj1-FjSz|hh!Dq{ndboP!{ z8Q^@Y63yg&+7L4LNX-I+C8DQ?INm44x=ChC(+z*=Ymjwxw&r}_1zBVHZLV1lvPn-H zcX3;6+40Vgzl5~Dxc6ej*I?yqzlzlz>_47Rr>jcH>{ri1ls^wvxyd`8VZ#F7+~8F; zN!ya=&BkJXPu}1!-tJ4ea|CkrkD4!ksKWl*eatZ?&Q(V2n}oo=#*X)UR9waQa&~pz zaeuKaCU22<>;r%69`hH=goWz3|9HTcb^I5|4+yQEF+-1(BnAdBVQcL@nBo_F2}*)zYa;JSM#GVg1p`gaGr+G+RKjhp1&rE0}| znA%$U6%Xr$%49P)|LJo=l{?d0WwWQe&K5s*FDZKb!pdzaiDos4S{tJr4@^7#JtAMB z)BKoG>d=nVFaBz4Utg+~|1hJQ?U0{^V>J8Y72}ms)Nk2nW2-im**-y;&5#s<^RIGk9{`_pw!PINt7IG7uu{CVWk(#PCUylTPv z>3-aEn@vl7FMNr5Xu0!>-}4*(&u_5Luv^Ni-7sOfzMpku$vI|*-0^!SSeDi*3g?QA z{Sf1yvoS4c%$?QZtQ5&~#Kq=`Gd>&m)Fb@5RQ;s&UVodrsbAuN|8fre{uPdR0oQXJ z;g){i6714iox0g9$Gq97ZpeNtAolq?`ET>T>DqDn*YVZsdl_&`8Dw!QOf5e#)h=zH z;DP#}St*Gp^Jb}fNpaN&`@5)mg}rXgd^;gww=ZX}#9@O($X&v|6e)brc95SCR4Jo~&Uat0irp8@ao@j>Kq?Ps9=IQR(AzhIHEfM$miLVM<60nNT?2|nC zeT#_ubnaz*&1@W6t#57?B|R@b&CFWe@iWAwK1n%J8(C7MdNg!n$u<92x3P-GC6gyx zy`5FnE@QWFV!Xf;8Lv00-lZcCMkbe}UoJuvDZCu_$%=xIe(}!dC7gTj?Yv?ge0qf2 zXjat+MLX3=X0AuqDqX+8BB)$4u)|(q#7yGoZE=4gi&&3EiDn^Ltxn7fMPWa47K;_! zvbk#C&l!9bcK^EMMH=fnZwcMu3AjzSZ`!;OW&8H|NQS=WG|BvV^|Ol&_0=Yo>|P_e z+53zBJ`;_-6LGGDC1$P3^lRC2G%iy8!`N0|p{lPUBE5&Py2sXvO64p6I0#;SjpDwz z4O{-?ZNV^^mA^>LV0I6Bxc76d_UIUWDv4Q}yY{}wois2a?7Bk0?5m%&U-CTbiWUQx znU0%%6MNT<0*99u_N}+BHC5Iy>I~)!)!U68d=AmNt7hWwHPwp3qX)14G;R7jZ^Dm*(IJ}c{J6OBVHph*O640D z{`Nz={5ASdt*-Ih*_w$kSfPbpADxQlok_8u3~-h|w&v!(b+k0ng#0zlei}Cge`OJtK-KIv;M-7$L z8b-X7f=m4DQ>{fElU9ZeU)8-I``ADBG3#5G85!a_Kj7%gxbLg64s>b?Ea^(Zqy)|X z=}+d*U-*yyp2%EkSDhfJoYvr;D1QAyv1)67utq5eKB@djJn=8VeJv8JvySMbhelmc z8F!)s%h&&<*2MAB)3|1)_}#$$WomA(o~cuFD|2{pxuf5wsj(hH5kXo5g;5?X5#OhB z=X%Y?F~*}L|K8)R`~*=4>)Pd=kvj5SV$nW!Toxjtd&(#HR9)Iw#k)!Z8rN= z)5V>(cFNouT-~}}<8~j_+iP7~8P}pBrSoz#PAU)On;VMXs}`&8S96-WY!Snv-M}K7 z+ZiO(z`21rq8{UYU<><Yu6;FY$%_TGT7)vyvCg3pY%E|X5)_PwxnvB1FLNo(fJ${M|~d?kLB8H1576#`1lHi!Hixe)Q65xnjJU z1ss2KB?lv3O~C6Zd-80y^cT7iS9aXFQO}?*bao{pkUM?6)-LO!T?V&A%-npBw5#`@ znt1U=0=?Ux-pnn{p5c91Ao^@MmkZmH!yMWceACJv+dLLK!zkf6YUXwwn0PXG`jVi_ z_wKV>741qrup;r5MrCl}l@GDo`J$HX6ZkTyFVbo1mS!!wY_GyvOZ{;FB_)Q8->HHl zf~x)lnN?0AC;OIsS>lazwPi3jmViV@ZPbBb6gjn&kI~=RgsW7U?{S0IrlBGn&end*<~*B zu1i>XhsSc~vo?Q{Z&_H?veK@WrxDksGVRgm*N)J6`p{Rb=l}?tYd;v!aKU8kOO=SRbL(J~t89 zu}f=BIMe04IeRrUdH()NnZSCpLvyYl#xi7OH|JZv&gV^U(aT?|+8gZCy2rZra9*+C zNZ9SyofLa`@xuZ(Jd)*M^#KbzzpQ+_Z^_9V9=}6ljgqa}cEq*o7}SL0HkUju)96^( z7`xP}ycFwdO1nl(u)52tO(V;e9hUjBVjOSoI6rgl9FH?D^S|_q2r&D7#%C4hr4*GX zSwGw#TX_}>`Qh-SFN3U!uR^juPRFj(<=Z;vl}S;+7LEQ$yR=5zO@jg%Z@F=2i-grz z7hOLQ`+>hIS3KkWxS1(Ocph85edByb-0IHr7YVuBk`FHE~*hhvvxmgZ}Qq*R3%rFIP}2aiIATqC|j}NTsjo)$s9p(LD>e^CM=<-YW96G{bi#HD=p~%#}>37;`LLzI}~+^M{Wne|PC^{qo(SKnGFWw^%%wXqH`UVah#+ zL=Nz9f1jb}XEAoU{*guF;yigC4$fVBXsm8o*v6X4I36rjxY`c$@DB5L=q4$M^e&Ie zxHZ9Hi~sWiK8qlm7)J|EW-;&m0@e$&C3I?TBely&0fg1{&}c8QtJyXwQ5T75|E-s& zGzZ7M(0MbnYDCO!LE~csMoBPjb2*pR$N2B7uWVjt`Dwat9ZfaD zKkdWXl%QpBQ|HCA|HaW~Pq;`ysP`u*7)2W+fZ>61x{}%G+MY=EXI{bYa@&DQqsfy9F8qawO`~aQZZeNIbsnJQ509;_sIX(RhcIm zeS=G^`80Z4By~fx8cjBhh#ioq=2RB5wqo{rZ0?kRkdwQmoJ+?n#$b6Lmn_mOe+@&H*&uO0}r;2vI~ou_ zjA`5-qP^p`*vxtGxk-GInOfe3G#`AfN?V%o zk$3bz4TiUG>YDfBcJyI|ZZqV(jO7rk;~~zQ8;f#xSik4&9O%6_ZyJ{pmsS13Aw8De zLlaInl&!n_dVJ4q-V_V=eGg)t78}>Gp7`u#a`=T-dr92({b!bN;t)FKt{)NP8#O-l z^OWJ)N0dFsKj_#djNDAhuYH~W*q9?#M`zDW@eN$qRH|QiH`3~$An?Vd=rJh_6SMri z;@H#mTsg_KQKqzaM*s4c3*fyywe9dY%kQ%tO($&LSX|su98*?wdRFVSL&^^a+42VT z5VUUI@bPW%RmC`|H2^0fUw57Hm~_2wmg8m~PeS|qsk;P`!@n{~4?o3+bV?Gi6qIga{?~!txDSSS6bFr$u<4c| zzG?Jt_?X!ol@(s9#R`4B@b7=qZPIukiHH4@0ERCJ?DuK0 zEgVW}%DI=CKf&zlk>MRBh>r>0PW~I``>OIDG3Ly8JAwTW*P@55%d6ew#k$v=*|$K^ z@u)GUtLk*#yeZH0F6vy?Y<#i9`n9rE(})^#{>ZwPrYmJ}6>8l}rm>W*;OeOE)PP9WBEZN&+1s^YoUW((_j)FgT=ay&n_q`(iknRdjGAX1$D3m+Y64w4^OMETbQ zN$k^uI|1$X33ePDSLyvw+r7o}?cv$i53-qjpT6$A{_C(?p|2+=d#DG8110W8s%XFa ztIBb{lOKgPeVzEQUjgXD|25yN<@ct#Pe+vi(FLiG2F-A9cV&?prN^SFej)>2(9G(~$P-(V0&1trd#jHRh&B{x5&Eup#*wW89 zSZEJ)-a7V@N8&(_X@GtVr;DFWiI}MGjmgqW`hN-Aw@~N*wD#6}_ zEz%&JLxTt^Qqqc)loB`10MZ~xNJ~j~2+{(IfFL0`prmw3&AUgx&vSn7IiC~H`8@yN zFy8mx`(AtPwXW-0iWOZd6lLqpSySno@r`1|kOzEy> zoKfj1^7XyFGTM?y+6G1Lv(8Ut1mZ(LKD6jXZp zBEcc0lcY${EPv%Axc#|co`%}D)(?YhBVj(t`xf;Hbbgn!$03)zlQ-%wJ{bX{y&O7X z@8ZeycVIltzY#0552-PqKx$FP4B6vw{r4R4OnX=L@lE9o9%!HSS+_|Oqy|t_4jk%6K{zHY~;iGtiFPudtgT_}G-APwrVsXZ90$sGTUvdWV z^?W)y^HfZ8q9;hS0{fZ zI1Eu&dcDXG{2g8mq_GD+`Ms3G??9XG2i;?}VjesF(dfJvmz|PEO9S1c=(_I;-Jm9Y?oDW^&8x)f4z72iBR+9$FgZ=N zVti3PLQg7w4fl*azG-Zz_@zo?_fb6EbMowU96IIFfsc2!M@+58;o$;@3IB>*vGdaDFT+ z=+PglI6{+(T^h_*F%eU-bk2A#Kd5rtp6FxCsyJR`03c0LWRc0SFA;9Fc$?0&g{tly zTwo?*U*3#;Up6R5(J6PKNT*6xo%oz6`v?XfE06cxiGz&G1ltyd>GLyGm@YqehMtyx_ z8-}W;?x?G^Vv@natnETV;ixlwYCj!kh1%J^t7h}Uga`(C*0_^rpMIPGsOpPY|=l~6^=+1o38eK8-qVFgP-o!vxI~1 zf6X_(<2Lb2cQksMXO5$O#grvmZ`A#^a@YlF(XbiEtax%^9?z;`t48k7kwL`i8}$~H zMb+0b^RU9FvJuh8ta`~VvEQ{FyV;k1PGh-*w%kxIKJ(GX9`t`@qE^=;?>PJgnJgn` ziV%y?@eTD_#g2ssoA!R){`4GUFgoZruKu}pz$=q%Kk1#G-&SUgOm$_TBkxz5FtZ%u zZD_+|$>uR#4FgG{;7FNvMCHaQP^aKb?-NZY8+ zWH&t*Zl)~vc{#LqV}#N%75l=+qtHP5bO95qc?hBPIuvhXSF`TdY)~J`1XYj_yA@lmgTI?2U@7w zuOC0Zj~Xo;uuDwyrbl#A??y<)(s@z4j1k4VS0mNK$nkujmu`{TR+*=_qZH=8szEC@ z9}U3sq!(J-cKFBWkJd3yCbw$09Mc51XJ+X+ZaxL(*@@wn+?P@^>7gt?mhP)_SNatu zSHcwAwedw^E=F#EADkza`W2>G?xIxr!~7Bivj=ApD_Yrc))PsC4!n6xDcld1WwpmP z%Pq12Rf7YAG?G##&Z%Mc9Tx9 z5*=T&T1Sqzs>M$#JwC?89JQ)LT+~&Fg?m+H2`ZGB*;abD9Y zjKh>l2aw6=SB$8BPPM28WWz4v<0v$AqyF&~;OMNtc8n;kt3$dP#b_&6!mWHg;B9%? z)VD-7w1HP)E*V3+xeoYg^lIHBF3S+sWXdwBrjdM+siMl>Wlej1w ze7$E`YCB2aZkQUgA7@n67n9)BdQ{BqcBzPwJXPPgJR2@z9Y3rpW5_;{&V{vzoQA?( zG8Uw>L-;Amx{HUoKyTFVhH@`DbhJ=_qTDZaCY&cTM{h;!wF+^JHX8`)vudPm{tW~7 zX1P!MwPK4xZ^Y8=BI2ihfRoJW#;S_GH1nEaWh7kntj97> zU6m~9Rf2=*N56c?+SYC|Der~M=-nz+z0~~xqYsCVZ^dL{9jt?u`CTr;=D#kovbaQj zhGcY&++si4br+6kVpbWBlV#nP4)Hqpy2QQ7Au_M2R?7m?rq-Ha-0zueGFyLw9J%4H zQKB;hxCa?#rxDxivVLrPZm61%}W>?8uAlGNtq&s}puevIm<+aU;1fi`A)62O`X*89>Sg=j03(N-P^T^rA6;$_bGfd|50KTsIo zvC3?V1=o+Rln>ny`N6bgwU@~RVflQiu(lSYznN8jQFnScD9w39g2y8${^DlRVY3b$;fjQp{ivsON~yg z2YZV6Mc;CF=#NqwIajTVzpzngub5*vt?T^GnhO;i9rxqU@1c_;QU ztntMx_v7y|Ik}sxlPv^Q-;t7xYS+#(mrPruK@f{`NKphPKP+??P*^wJu)1K3E#lah zWO|T9-sXz^9HHshcb-Smkf`gy3o>ac9JciY(IFK+br|p}BRpA#;9z}{_2{G=!RXAT zw;beE;x!_Y06EAVGmZFyF>${ z*uOWxiACUJSA)wa?Gi`t?s_y%iUBX7xLSMt@k}IG1;zn1Zi&DLpvckfj{J%r#IwbP zPnmN@;?A^`a=ktqxb8VF|B7!?Kh)})gSVKx*cj6tO%3hU2??dsXK#~x+!YcWjZfxI zr{#DK4YVX|d@3gw@Qs~806djDno=H1w|5o9=6wcKKbLMBQ{7#1_iK2iFFL-BZNRSt z%WwkAm6^BQ`R9MGl)m`zO{Aq7nW1!srkLgK`!)>kQ=m|!^5QIN&twr>(x) zz5cvWj#@K<$=#3&1`d z*XmSdmfP<oM z(i*XyOCx@{PP7ILWv6c(Mpd|rMCEv3Bk1bn-llp|oMg(kY={X*NHQypJ}2t?84~+_ z@VoNUQ$?tbsmdKB#5P6+@}k{6yF}wdsoAK)#mh?h?DmP?2ijmGP;3Al0Heejw5bC) zg#jYUVduhS?hJa}q=>qAS$ZqpSNh(D02m-&_NK*+XBP2LB#4R(&o_NKVy^S>F14FYH&Pw(+kcb>{ar4`{+u!Dz2I}x%SAJH5{w<9Ycd)A%xHmk70y?Y~z zt%%%dRAyXq2`7NrzDe)Wlyiry85$#+SqF!1ta%V1#)#BhH}qV%5M#nsPBI`7uX{yA zx5fb0)p$@1WCPGx=0Wk7DuQK^24cuyQ#7a8A~)Eqyf&V`xC~z*z=ZUC&YZ%>HA8Yl zL2FbPdAV;K0CS5Od88NAF6H5|Gb$_3g_XEmpS2Bu%!5|Aw(kO{A>Ymv4RWLu_CDG& zEJx8X-(t;{wXaeDkko9w&P;9g$r}Iqi1FJR!(C7Qm6w^BGx$ zr%@|7((9dO>rTJP^N=7GFzvbEhU({4l^9h4dd)fR>IJbl@E3i!dYEFQwi07#yziz$ zRkafbKzBFZ9J2s8q;!1-*~F-zUmZLhZ&oc3AGH^LLVDeIA|qBfHsd!jDrye{W2M*h zT?ZhY6^|Qw%ay_iS1a2&r4z+^eYa`st|xC;0Zbl!&fC{SD}4I^LV&V+)7@Yu)p#aP zKDglI{qbE75Hq`Ym@xSrKol%h5rhNp|);pf*h*)8{vI{VlA~T&8$p96E zJNPtS`?-9*gdumV)m%s=7eMYlkfXOeCzl0+0hn(EI4|14h7z18g7?v3a1K+csOfZL zFV*kg;!BQMi!7GqA_p-@KLdjB`%-NuGByUrK{R^H!yt5k zZPrn5B7dR7b|0jgx411PRTiR%gOcD`&JXFv=HDMw37D!E`oxcBRU?~T+J;S^eedII z!LM>B%V+7UoI^aS`T_+ELAQ!7GqbPVq?#fI*+u1S>Zp(J0>X_#T_sKU{4EY62OPm- zOW93NE=@|*10H_LCUw+IRlA|E;&*M-i3P)Mmd2NWbpQ@km{f{CC?^v@GiJ}VRVuci z$g7BJF;EyBRjYN7Y~?%-KW~8Z{{z@s5#UCvuUG`#WVT+-8~XwYQ!Pla91L@VN;pl0 zk^p&D6CGT10{k2uF|@1%FpHd~{yE*Gy;&$oBc6RH$$hsyuB-xcO2@$0TyI*{lNre% z9NTr&zI{QJ0{E1^-|&RsoFl>E!KLh!_emMQMf63=De=+~E1q;#kCA3=nbRZa0jY2! zY5CC{_G||>(0&9$^C9%Z2{0ObOgN6Lo0EmhKL=Pi0g!zuD?e!}gm=L)yN+Bj?(49a zdEZiH)d)_ROF#km+!o|@a3>G%LJDC++4vj{{@fyd{|kj~g4GO>$49;<8pP+J!zima zXQUV>W!#>l(mIj0n7g&XgpGcToM070Yv+8k4!%gR zPXt$j%xxOwK%KiF))=}Vvw9pW zQ+Nxy9Zi~=_u>NG%as1X=0~ zd}V{u1Y#LYshOWx~eA_BrK-7u;OhZILcl zIKL`*unx|LA6J)m7$&p*nF;);d26qzS%ah+EAj_-7F%A1Nj5{VRAcrmTpUfY=Psc$ zc&5}aQNw_6YKt7@`K=D6NVVbTi(tHjM>)z9_iz!W)Uy-IEb$?jrDH}NPSv1)G+?W+ zNeeG@4AB*(2aUIpaBeDkDX@3n3{vm`Io(zGz^W;g4mB!*^NJqdSn!2XM^Igw4 z6qR-l?aj+<_k{~?x#}?zs_j0hti0vs!7ABIMi2TBqOr;USsv?yXZ9MX+KJS=h0)mH zO0e=let5f5y>)3D;lbTUaaq-b!xD>#%Bw;WWX2{D=omuS zcpKIQe|!sXy8QSeQCpPsaWmLB%^CtqK49BFFChZsI}!iWoRLn{z z{?|IiuceCi^z;kubH^@(ifjJ>_0QQ3)q}ed^#~Yu5yk(C0D8_BH`Z5%y zTb3&wwPB65;)6Bc9U#y^BTG%AkJnsvUR;}5=dB2Z(?43Tx9GPednJRr^SG7QprGB0 zQ-}59rv%xi3g!XObjhMOc%jVj#W_4vjyjvGqK4XmTxqZi{_R_pl~;h_@fEF?D#bV+ zDCr7^Q-K|oJylP)sL!q@wAWIu0&Nv=LROjD{msIcwLJbRK`cyuG->$^Pv3dd_0E_4j$jy-aeZ9Ye$2m?E}2|+!&JlPMD376#utA2 zD2FgyXP}_=cs~wA3j}b;iF*>FhM`eOUsFr@uc!E4=Vqr#iVN%i*xl1#>Bk2SlH%1e zFQTM4e8`l;V#k+Y$6liMp?bqbxw)bndH@#5Ea&4c;oFALJ-bxr!H3wP`xI(K{xnu( z!ekvL(}G{%NI8pWYtP(q^5FtLop}bsgaaQ*{--JZA4Alr!35t73a~IX%&8_s+!V2F{4 z6x^Xr4j>Ls-=kYlB@GJy8tCeRhsIf6aSBL?E;W_Mtk32u7k7#5W`(h?NvJ>U=GAH# z5S(^0;NsXEaw_}_Bd2zQQoq_@hSDKX{P5iaiP%}jjAxR<4(w;gxE;_4=Wk(yaq@;v z&TPs3&Df=`|Jw~@XdzYP37ebMBvv`AI*a+fk#mA#2pZbPErQ+ zW>g;W&?IC%>jA+Dxi&|b zxSaoNj>I=nQYdY=dUA7xjWS{!9;Qx5V}DF?pl+-Y1lG%yqy`bjelYP%*SpMUrfn18 z2V8G`I2Iy$E5@Mwyp@)nhLD8zfgA}+J~m#!i%irb2I*sj?ASnx`aF40!lu)$L*$Em z%PXo3F(%&)9B@D1aV-ejut-it%)7p9n-j}wAf5(J8pUVr_2kB6_z&{u;kLc1Z~*RY zg&ZGIfD_tIl!`xJ{5wy_J1-(i6Qo@;G~P&7o?m)p{C12t>OA;*429zhN)O0rr+lQ*R_=x8 znS_yIr>H^lf*0p`#HC2CQ%;2XV)Spmgh;-yAA-pce&L#JcA znKQeGDlE@>F}jJ~v&#f0a*L&#(Ur1YwTSxrQ}Qa@Z!=rih3C)SJlJ1#oUDXI^ZHMG2(nsK+f@VBA4_pdPSJF&usdd3;3Us%S@ zVuwjEb|u13Uk)d@X(|~38`th!g(UdI?a5Y^8how<6Ppv;EY1AL6qIQ{2@H zch7!{M#o^cyanV7v|&QGxxOLk>z&-f~3<8ZTRXJIB>z*b%UM7wD0J za1NagHgn?veu0S63j}lS4F&@U_UVyga!%N;ZG;}kx}8V2K( zAJ*jp`#*LX@Z<5`3o3mW3^Fk0+#5F5SYV)&^Dd`v0=Cy6h{tA0QqMC; z1ptWl_iZE&CxrDEs#(;NQ){8jU)zz3KER371V~5?gYC3&C)V^SK(Yqd7&E`2W_wS+ zp07X$fHf$Bp=>ek5&@e5@4SgpXit}YQ-v`pW~MO}XDnL`#HG^L5t9w<5F&8xR-*F` zV~tH+OW5WuDzJkxcQ`KPPxAZ+U$yaE@7#$@ z!>?fpOBXyXrK4+#H_><`_b1ez)wz-v`;q`h5{)+(ZIyrW_K|4ufbIk&NeVCw2oQY1 z#3}vVD}#zRD_tox?+T*ssI6l)d-|sZJf6cgZcL%>z|;Kk$ZeT5<(>rWE#~^>N@8O@ zdy`5(#ub9W`SoFGl^_@bz4V+q?P^HYa4V5G^~Zb-cl?Hi3#FsBT#GKl3t7P-p7Ja3`cC2Mf_kT@AaZz`Io*#1m%J>{Iy z;axgTfiWxU<20DlW{$4<`nC}*T%)0cL&re?sl)Fe}#D_4y6xDL^*dt>+p%5Un}XAHS;x! z?sQ6oqBz2*mN}8mVOm&X*n!uyYQhE?BV~_Xq*hC*6L=tWP$@@Y#p za%8z7EO>rIiEKrc6iJiGKMj_%vxL2!M_3%-%GNZGEPs$~aws1)Bc1KJKCh-%1~a2c zaReRSVI`R$qo{|WuBR~|Cz-GMZX}END{N#6nPcG`0LO&`zR3*;9bZoPccz)A@b-~Y z@q5KzSw8g&_!A@aXx~>H7~4Nml&jW}C!#Nr12g3+3%h*JZH|K9d%+wAHw^u~r2L6f zAV-q8Lwa>Qg}5BUgKL!OD)F5*o{4ulDcaHmCgVb;7$O|j-_wuKGo{9Vv{>tN!HfEs z>zxrfS;;_GR~6RtD`kbvEwemdoS&U{{OG@U;%KGp$X6+UgJqD1{ZM|!oUos=MH$m*) zatWPAmd;_hry&T$+MrZd;HB6)thN^fhSi;UX|XD8l=^TSo5Qh z+|o>~c2Cot(P86yFXc_?xBsN2qpy&^6QRBpAaz3i>1TabYhVzR!!S+mnJr0r`B%UQ zATO+jp?^~dlG^Ps958N-A6N{-HQiYMN*m8^VDi1FVNXDz8b>Dnojd9g{U4RBmw=-o z*~7k~T{}k5Hf9~Q0t+PPI-jQO;Wz_K3f7E@OD*;7Ph)2E0%cDh7nZXWwPHbsIO!Hp zg0s%CM9QT*GKA=ik`Kr5-?hhE=VV90nTyd4lyuxMLm3iny3ZjcZ+htW2nLmz&AF4w zKAj7CQ}Q-a7R-lvDnnAi< z!1#tQsl$v-APQg5TFCAZ@x>XvGoC31aDRBj{d4|HBc6jC;3mrEiqquvxwlT+Hy?v% zr+jr0fGv3S+0gqzR@VjZiIbm7A`G>f+)uCt&AAY%uDdyip8PlS=I%9Wry18=;@zi2526fNUpbU6TfJ-P*d_L*wVz$NBc4X zwZ-c`z`e-2FPR5V4|^RmBHP^gVeL8J5ikuV8#9Mrl7UAT8RwOEHFj*z=s&+cC?8U= zq=LTHORzj4Fp`mP*o7VTm9sxQWLc=fmw43GPXM|@AZ)?)3r(MyOnZL7q)T6GIXx16 z-*++LCDI<4Ho<&H5FfB_Ul{ew;Ozatka`xDd(POr^I5MWBvK+IHZ&?$JPv!HQ>@fr zVjMyzi#EF4Y{8Htmpo^3zKMP| zNI%_=CT?k5;q)O%7wv8GBonnjpiy0aD4q1)1y4uGnkF8ASO7%Zuy!8EXaKIhQu!q) zIUI0gS~qFbNAgAo5!I&S8lNdT&wZ!i_k#;xBY+gp_|dv#G7Y?)8u_p;^-J1)*^I0e z!)SQZ`16KbW|fUJ^q^-&QY4uIM8G;lM>8A#flGq*zvb%u$WzOO{iQ!uk?jdc4NdVY^A^VOGj zB>3Iu@Y7GRa2;<-j6%Th{NdC!O1>PC^>Lsm!Y5Moq14f2OYm|mIf3HSsUSv9lUTI> z{4MbjPvitWxKzSeFaZF4|BMt95B%bO2<0}$np3`=MR9IiDP_6J>kR^yvjRq z{r6yB(=ob-H{<6<%S=undXOtHy#CY!z}iI=b~yT66C+--b}e`2Ls2jrGsF`hSePFs z)lipZlB^e0107;vt*GJ!cUZ?C^s-<+X-5t)&_>K(HKjCUy`b}C^`FbXrmh+IZyF*? zxxhrMKw^}}1_p^J;`)~g*R`;~7EJ);G~0=%8ybMlcRl%+Lg@l|*>%M&6k;7-e<+j$ zlr0SY!l;+xJ`cMJ9*Ju98dArZTUs+9CvP$u-&YEZO4?Bd>Ys(7ro8o1cGFb_-N;hY zkRq-SFTQ_?o+JV^J4Js4puzU4N>>1+IsvGttaL^4EB!NkS90VZ4NQRm0`rAs{PWBI zoNJA!GxE_gmPw#TJi=vzb`cqB^hvM|s2BLG4J4=ZXj z$;y0bs}HR|u*pbq@7cBN&03tXhh{@)&%QiEalgvOsOuuYI&U<>*rag*G zG^dFO0(_ahsh109uMD3TC1hZxeRkl26y@Nfcba}S@r#)P#Cnf$JiBq+f~^q1+ZMj0 zAxj^AT6inT7PzfGgv;g~_HEoCsiAP$6r#B=OFettWOOkpFeUxu762jrg)z#&gT zvh1bZXGaMM^g6u2Mo9r69!0$XwLQDeoy$4+0k{N1iYLk!gcTg+dXNiDURpOsjPzB)@>lvg zLsOlsXgK3N1o~aTv37@!DI2eE{Ll2WlHv1mx!U!YrC@bCI5vCVH}1ah1X?dEuivF= z=!eM^mb-yW@uFNu<9M~$+l|bLTmku`_kU>Vd#Tw8TcCc>dQQL%dN0q9lb4+fS*&ig z)5ZT?{{Oyu_=?P&oF{!i(fyD#h&ay{;~F5NP83^jB^g1OQq<^1y`fz|B2kAZblBX^Hpxh0S+*110;z=MRi8C?&Ue zou@2Hj3{_BUV@rT;MzTZV4Sr=9|C%qSgUr!nchtqOmImK2jO)?qnUrDjGaK{m=?Cs zl<2*u4oI6KFCdxeEi86&1Pg##yT2S9qH*>v1g*Lbh8E$u6eX zE2PHdRG4P_Vip8Wa6P{JY)j5FLD-H9R)M4!lr>>uhxb3dIzqMyk_6(pl|S22ktO;z z0>C|Ei{{y+k)kEl*mHu}l`vQZI3YjUW$a2p4l^nMiUHMNE@E&k zM%Ei^)Jfi*F4!Ao_34l_n^m1~RT@ZKiWue4cs9ROcak083Kj=*vyRVB+1_s=elO|3 z3lF7TRA-edj`@LRV3!$W%BuV?F&zYGhwSv#V%r_?l=6mI}Y<~ z(3<$ATdu>;Z53NWw{y)DbxH4m^e1RM8$|Nnj&&s5ygh2@+V%F$V*+S_Pdo@xfb@Mh zE&ABWcsPsv2p86Dhi7_Y6JJGrJxV*?^TRqYR;w7}*`8}9qsyroYUP}5SSCo8jpj;| zH_lza38LbA zG8wNo0Vldyc;^Y=ZkL-&+PegwKm`__W%9O}A7>{rm>0h^VO?ECid|T@>|F#19lt;_ zDC<8E)t)2VSw>UQ)y10wxA)l=nr0Pq{TTQnkaP=3tT-8-)Hnyh1Ae&jL=}MdEPQE6 z$Elw`#o@{9a!k{SH&X>i5Y*pT*l94KYM@J*z@=-*SAcEg)F)L4y1GU2DedDMszJeI zRGT-S)|up|R}$i&^l-ehx4~+PZEuoo!E>53($ul}xXZTCmmi4mcC1Kp=*JVl^;y|T zoi?g#=B*#m=fGFq6aabL;?ytWr$Mtea7sOs=w65CG2c3f%X3blH0j`G`$0o~mD(+s zHeGPkO0Gb=1axBT&mr$li^0%=o42pssU-@$#&X?8Gza3l~(RNcI(AD zRLytq-Yk17Vf;Rw8m#j$AFM!LA~p_l1|NW`5wV{Br^81Tp+7gu4q|7Md@E~#rDw7F z<*jK@OJ-4?JsQVC0*anYFN+@F$-n#w4$C$qDc3w$;f;?!uyKz>6s`0f49`6-kF?b4ueQJ%`Xb<-P>FJ}b}SBMDKoh%Zi_#dZ>7*aU;U~et;>M@=GNp-)SUh3*tHbe@OUuDK* z?ad>;AtpOg-%t4s>|3nuiRYA{Zk;U_G=4cTXmiiq?aLh&Llwd(z5iWTcy(Jnu;_l! zrVL%WaQuk(Je5x-M^sYqx>-BD5bmvAHQfxn#f&|=Jllk&Ew<@>JVaE|F`-kZ)T+_E z_3*1>LdZ#R`DG{Lfmva0H103?7oO>XP%o(dUYunrkmZK&fV>g{unYo(aZ4ul>1|12 z$FLstjwq-3j5G0KMP^Lp75HY3U@oh7{w;#71C{-03R0}%d2G6?xIrw=|IJ2Q-cZoaO^x&4R`4!85|++KHJl z9O!yX7AQSl=WS))E$47O5sLkG6=H(>I<6omUVj}z;10|1XM&RX#R$k3%1x((!;%arED5j%6|OdGTE;4{R)(<@qSJR2&b^cYtGl`BEe zwg5A_U}_;z8a(3>C;wE3dkm(MT9G^)2nE7M593Lu(x5l}v>S-1f!&_*25q>1#2v9k zP-RN&a5(h``XUA>n~6R?(!l0bAlQ+>$Y+}_x1e@>+0M-=|3O;9)yWi{3y`6N;%75H z9@B)k$&i3s6nxwp0Y`2Dgj(Vu>g#T$NQraXAq#gYk4>*@;PsIDNbo77Ah< zOb$InKCDWwShDCyYFn;e^83XK;HMxxTE#fGDKi*&cOk!`y!XVE4#9Zq%loId%zyJ1 zw8D*E0!4ku;LeEK&tNAIE<6B?44$jx%F8yXlW^ zxA)7M*SE%CEEaq`4y=gM=vswvK~1!M^Fhp@1aT!)Jm3uEdp4Op*H6$}F_u=!j+qHN z@(U@WoLetYL@m^RmbUW)FiA4B#*rkc?NE%a{Y*u33FZg`DJAjaZy^lxW4ukCE_`<1 zDC^V*d*&&Q$1c-)tvu@9k2Z z&7i-hL_iY4G!hUVD3^jJudq!+f*#K4?JEmaWx&|VgWFUrc*mzI^*~8^POgoo{YyO&N2dMg`?pY zF12rCU?}S_!+|Mblth5|1M2gD^J@N|OCNs0K&0oWzgdT6a>%-CDp)rhBdV;=ZmYA*mFJ=1ZKvFj~_pRTq1UJ`$5MD zCt?V&Qt1o4Gh8uq&qTQwqMIMhazI*kc%E6OWE%s&SdiX`oY^5y5$9gFbNKaunP^JnQ-Ey3J$EfZt69otH2k988<0i578<}?1OLjNWT+BN_F!?8 z1OWXN^BjP7#XtISyaz$x!-O8B5`wOP(uX+ThO9hA+T*=Hl!s)!ah@#KeeEkqKli~g zgYcU<*sro<#-{Q68wm-aU)LW3P#b5Z2!5g%p3(B%Q*2nX2QB16}j8p9=3AAW3(LiEB(B<HbG12& ztQ<5Qkb(tbyg|Wd41~>S2S+?$Yalugr9K{q)!_GVwi{mknhNmmz0?UZOb z6VU70n@rHmEMtM#PFBu}$sTb#0u=n2SfVW5hWu|Onx9B>zvn@i;v2jW{aY=q0bNO; zL`wX9f+p$PRS%iRD{r!B+)+6sgr`ade>yZ4By zARfO9KDmOK7pffNu?Gxe#Uo4l4{ryKe3u{K&*m%W3?2zG`mTwf@M?U@K+t*wyZpJe zA@?FOSnVjmj!~zyvS4qn*X7Sy9`sh2SC^G`-J`3 zxcTypHDq1K!hj8e+Wm)CP&eRsh~~C|+O_h$Y|oRZHPfY2E`c8tWV(Otm-NSe@lLPE7t_jkfv|b&9;g zK7=+XLZOnyvVe?&Gvn|g=u1Xgz@Sv*ahh$lktoYUS;iSq9m-FTxMs7LhI4OP&olSd zE>v*qSW4c zv+I9l z7%iNa{WbGuAkCBHjt)tMa-vnr0Yr?X`h8Qpn>9XRj(milzk7M~N-NM#FD^*CPS zR)<4|YQ=urhvUC{y`u~sq~`fr;RR^dHY_)9ON{h95lVSV2zu8v3FtumuLtz5o!v*1 z0|L>&h*%T8<~b@I`z`7{ z3;>?VIx^72bqt!lPV*iD65sA%EC*CJg(3e^oF$wYIw(aLcx^$o4Rk(W)F{d_KkDTM<`E^;ZJODLnOc%}?S}kpXU7mQ z4F@QpKo;wwik*h>D3KI*=+7BdKz1s#2iu*ZL<(!l7?5kXaH@YuKM*pWRdlCSPv}uc zCJm>9agt`EaAuz0d|P}i@Y?4|#_K*0iU-I561My7@SJqa`i2%A538ZdGmmjegBM~H zpT0H5&Rzvk43HkZj4({40s#7jJaP!^9>9%ceM;_hT>)H&d6zUODQ!tXJ~1QeenVw$ z|LBj3!qGPuf{p>5G}6Rzywl`uAEfra%)4Xyt4s*FZ0nYgf+cPQ|=t? zhJ1<`#Y1vg7@$#-SCe{yo01GIB*FzvMAmH%1a^nLf3AT3eMvYmkSVVN(E~IXRz!UV zjVp@(V|cdUk_-Cp4cJc8dxab2KxAm)b;~3SPe11d%?l}2w4kGp=sj%xpSjK*96BlV^QKA8haO{N` z&*=}jS`$F#Vzbo=t00FKo=&Xb*O+6Ud6u^`z7PWCD1Q&2&}=V1Bz8{|zvr>syV6n} z4!UZcM=FSuf=ejW~ z>hFEenK|!#GiT2C$Hxpj56^SQ-h0)x)?U{guBEAjk3)@vf`WptqO72Uf`YaTzk}GA z@QK}*0DqJVW}_+!vU(mD)>|%mB?Ql&Z}$&})V1p>*jbujbIJu`O~tNofgtZr`BYnIvoUOwDMj=D9Oxhc1R(O5M`!h5%M@0PRCk~S$H0V2$X%1M^!xG5$LepO@h8 zfy7o0j{go+4vdul&m|52`;xR?gbG)PcXoELgXP-pJP+<(_$a86o36=*hKbj_;_~-` zPD309gmq1R4Z&J>u@_i6_#K#KcJ~MBuQTua-O{AS#bPUQ5LMUIBzSH{j1yeUQ)(gk z?YW|@rp0Z;vUi;w9nBkVOnair#Vg zoS#0U62SbsE;m+&ZA1&CE1PhR$VEvm=U_4K&G>Do%?{fvFXZJ=?fW{CgehE6PvP^I zxh!L?gf;cJYugyNFPiqfGCw*`M1)-oZ^&&o;|};AO5>| zJ~L7om>H6>1NdV85nttIUpag~ABvqjJy&F+zzJUddNsyt@ED|M|IFg(0+$yZ z$%nvi6k;uD??bvywRWhOU5aubg$J1#3LrhR_4?uS$Dopm z2wuzl_LdR9MuG`n$83-squa)J#k+T@3$2{k;mng0FCAT7NAZlm_fRpnXRK^QIf@pt zCzN@TVA7im7fha($_7Js+peR6Y$Z0tZh z6ZNs~oeIwA!93s3dn^4zjowcQ%$of!wAD=7fxd^`t@q%!tA4@WG<_3PjW;#H4#3O;Fg`t0nq?mWA4ZDaLh-eaM{{2V` zkc{m(1nv{DZ!+#59TK~km@Jck{zGC>*>8u0IwBAgBdI&)>d>g;X4Ir`=A^V~k({aIqhgywjkR$O#4#y40$S8zW- zmg+4xZcKZinL(R}Bs~F}h)8luva#pIVZm^iRvWApt9pt|Po>qcL#-h?>IL(@bQNY2 zMhS@*GMD}SdLKbe0_r=~)|_>bOnYMez1w3SIMhcDO&vB0XdhXlM9kCu`IMa_qP&hh zpnD-#Jh@vD4nI0N`mwM;4C^pz@I1JEz6Hi3NlzI1&Us1m0cZ|Q_n}-+)2y?Cy5<_A36hSn8`-_&xL6u?Y$CD%wFo%n1*F4IYzg(~G$7)G)5465SIC zw))!H`S$K+x+4`z?7JX~7uzlV{OoUEkxS64-i-z2A})8^J2UzN%tg!|sO zfmvupa)}@`9Bynj`cl7b{rmgKVi4WG1u%9LP37SYtW-%GaFA za%$dFVs&_}8gWJ4_YrDINeL{o^{!_F_+v$5V|s0=te9dg_8?^a8;qlwVPU}`JpdK( zY09#j{6I_)TEat1@X!GKrKtgVoHF`f=WlgFE67(g+?m4vFh$In^|nVnvdV*L$3a<> zip2C;&5U9a%_)yf7rA7g^WZqOT%wQuB5iK=&Q&*sO2Ax;;=g6^;|CGUZ0E=eq@NEyt5hXV_VHgAWQg{Qx0#&GZ_pYH;$q069R{o!1s%kqGK-hx|Qs?cNd3<>uen#N{kW+w|* zeP;`jjdRP(V}pXw%W4;?SvArW-kJBtCNxjUdCa3)ey8@S$D2#LG94vK?Z3Wm6Q7XK zS?kWtqDUP5xk6F)jGrr%5v}@$ zLU5~TZU`Qg94G-RCoKV~kV!KN1VSYeoZzr)8l)h-%S4x1;fsZBkFd_}?uTE?jKHWT z>_qIUX@&(IYYk~jwbLXT6)7U9cGlN5@v=d_>CMhtg1lrwV65G1%+3*8|JP#Aw`SUA;{{|sF-RJc8Ti0 z3|uf`%oif|tYTuR#7sB%d`>(baB^~boNTv0nGL33=itb>{l@qNREce|w0dd|^y$&h ziCVpCt6^53v)!zB4zqH2t=Uz*FGLcOl0H4%Y*0#I)u=i9y>_%=@2dvy!@BzWm)^G1 zKU^6q(9_c!sB^cksHj*T%)^S2+`$HQWny9qTs8JwVF45V+)60j6HO=KG2@SQr{d8? zZ3;t&3kMUu@AO_|^!>}qB)KgTfK^zxESN=lO4?GXTT z3^l5A8!S+xu&dh;#w4IsRtG0;-*hUhqN39F+ORgBL$`42WVfI65+3H!Odz4?{4;?R zDR1$6)pi9I{h5!<&4=FHm!9%H_qJ;~byHPSt6k2GwER}VGF+%JkKni}040EpA_P$% zXQ9uT%&1y^OX7UGlM~)~!A-1w2%p3U{p;(6$HHD`zUBKI>;|~KeoYpn3qj}Q@?MoLx_a} zC%*ovzTK<`_TMU1udPgVD;^9Ry}m~}mv_LEi@436p0=f3(=^s!#CVv1AX5s%tBPuMgboTAo8NVQ)ySv#V=vw_kdxa#)ke z91LZ`V?K&9MAo*-R={yif!=eOG1GIEL)dO2tbb`f)gse$qQ+5y=YAt?OnWQnzB(98 ziiA7w{O73oUtjNAw1p8rqZNxEx2uafJoI?5*pu4oeK4tHU_kZo^RwCCYj2ijLm58v z;UVU8BZgkX&W@MoZe{j|+}ta|w%^;{^-HN0X=aR7nBj^{dkIW_aGhU$^@eq^1&iTF zw8YODu;>TVjo!#gOrI=@^rVX=eBl0{2E+C;JKHagNy+J}k^AB&+?d);QE+U8UPymhx6 zeR;{1gO_(PPKmx{X_qld#*1t0KDvbbKn0in-9o23T%TLNv*qZ!FQ;C(^mJyoJ;w&i z_4kP*MDy?WF`nYis^LyGl4FKkUcrm*y1m&PeUQ^Cqx=)?-WkK|J%1+R57TW2;ej_k zuej{I@jZ={^7b6=n~-0sB9`04Ft~+ULTA!}vQ^U}fYPH7o%#+9{aT9%Y5@5it}8)O zZxO>tWG0~Ge}JxAsNS;T;v@)BUb86SyCE+{D5yDv7UV6&gWpcIh5+iLlR@EW2@v&- zY6o9T3C>yLg)oct@<7hX%1z(g;^MIUd}e}$cs1VH&ouVTi&uS*a1q^r4;VT5`Qspq zK(GrA4$ksKtpF*TCUYTV6en{OO(p<@484Di+I*`B_60{>f4V=;%*;$QT6B{EqNaQ( z0ZSJj-i>J5&esO-I=Z^9Sf8Jr{#abxiSa!N{6HDfVp~1=nI+j!4vg|gS>4YEJ3l&~ z(TGGBo3@5%PlEe?vY2Wy_Q93Q=z~j+QVcye_)CyteDO``)5MC3Ye-B2c%mLde|-xO zCmxOPv(Z<#cR~G}CSAX3XIQ1Fr;Em=fUn<)ynhnFqW0Y3*XV81dAB;M>z;zz5Kq{^ zLnA&N?309)w8VC-+*D7*bI&sK$s$#i-K1)r+lB}Dc1j^@GRSV&Lt9(g!bwYBzh+)V z3?39D2h>pE{o}9EO#t`WK7D%Yx^@dOlqt_O9ug9gF!8n5?+)h~&O0`$r~77F0>!Aq z!^0&HX9C;W+ew9-ekdD1S-6A*rKH=&opFgtNshxBB96U6UmZsEZ-eTcuWa?CUlDQ}1LXV?yPq!#nsC-{VdHDj`?Eof!G|l7thZa{?e<%mYGRQ@0(v}ZlWi2#^ zJaM>1uCy`aD-$Y9Th4*479!`t>e3XxNs1K}JG}B}=Lc3QpDAkfB+8fJbiT68nN^jf zfuey;3qC+eh!+^dMn?r{kr0Gl43<+!Eer=}As~K`1!FzgN)KEFy&~ z0QMCSAO!>?Ru5r(vG+wgf@f9K)tMn1ZaP2R1cy#g020$nPEKymRgCQD?Jf8~C*f8O z-d5cGXV1yeu0grUg(_RpOE|%Y+cCcCBdepY#K2FhC@W`wfC0Tc&N@G0DEqL=`Lljk z^X_}=PmkX;+yJ$Pcs#4sC$TB{a&4+XV!XG67?eMdOg|75ZFh)$GqvDX*4h#$ zlhl?;s}m|akV~rnoiM21Dcglqsnp=!GG7?y29}e|3TvZ1lv@BKLM0_gdeM~C@1Te_ z4WE*>dY~xQhl`nwjRYHA^e$8jprY_HQsD~VRS3nSidTr?1+rVHcj#o88R$_Egl-?7 zf)fYi9uDsiwYZ3m3W49eC&eEW_Vea}?mbajcuB~}K=3`JItp+ZD3Nqk**<_5B5bXD z>|`I;ej)3J)Jx#Anr3 zM+8N1rXB?YLyYZs+oMO19Ke0WLC)U;9^BpN*S>U(<;@CGHvAR#XQt&6R z-83I5)*fjeDo}$-BWMxOcrH25-8RtVk}|mH$fAR2@$1+5ykL!na1vsq0uT;u#tWrj zI1cd2TV;z>jzUbejEyy20pa9TA<+HaUl=;les+3HCFaCD)FH?}t5n?_V>jzp8fnt0 zb;n1*Wyde?lIzQfn+-xL`5}kov|0vz+K=Ov@wa(Ivn$d!Ux-q_g*pU4)`y#+&D~zD zg{*<|#aCsVeX}lpGLwevYP7VzKKaGgp50BFS=QZ}$zQ#alPxqdg84E-h1Xh}L zKi4*bf3*PtL6WEaZ$xc^8k%AYWVxExf9ZXBbN{C6X4AP;`xPmvOz@ejP5?xmR|=A^ zM0JGJYJEth)@&e4WA<-g;M{kJ6{c{O@nB7Sod>Xnak@;DntxajoH9&>Z{LUV_dWLS z_>^9+GJS}DpW?;qia#)T@&|x?UHi0oK#GkX2Brr{8nHvj2*be5x54*dCq7LKP{@Q; zhiV38cSUjJ^kzGpffKB(p~1pQ5>AANS<<`WGIwwc`Fd_PyL$w=E>g`nwVkR@C6qpil?}wyPM&QI6?puGdv)z=)0vQf zMc0&*^-wrMH*8{>%WAUT?>>;)*Y zVZ*THjAt=LZ*qp z?G%4BEGWsQ0GgF>|Jhb$JN0CVE`*Rl6D0Qj*Xn3wfm*W8-MgwIaNQ@rSBk`pVF=>5 z6uivfwlY2DE<$3%Up?i?<-F9l5KLig0*-xss^LXD{nKZVk&?OslD%d%#4L3wa0bIsSJ$|XPPomTL;`B;5 z#I|J)Jd|AL2@>fGT@Y!JXr0v%ndXa~U&@XHKWV}jHob{pufE%@x=n#JWvEJ$?PkC3 zQa)kuswDUPwfd>Ttea0G!9D>zxH(dh1V6BfEEm)Qq2`kUB35T6nRQSfZd>~m4;BsT zF!%32@SETvptu$N97@}8vYv$jIlu863IrGk!*ZEz&9n&Geoy>>I7GlNQLsOt%K$Lo z(U;c-$n+ss!5FVXGUXab)x)Ww&c@(-g4DNv{CK23{3or65}CRTXd?j(Gad9vS5L2v z$|Aibkwdqmqaz!s!-8)@WaDvtf9&Ce>sKT7EU66h-ZaOJ_g|g*#Fn&-03?WQR1S|- zT9ID&+`IgF)`8D?QJvmmsA~n7M%0Is*yh($v#U zmenqTs-`3#C7&XqqK4vdl97V^e+NFUUEe!aR+y!#RNDuk527@s|+d}7N7 zA1~RrelIe)N56g|Lb)Bg#k4Fy<*D%_w(m%QIfLMFR?vyqz-yj#M>ZQHyzyyFr7KP+ zwCT(ckijb;s9(G3JmCJ#V665Q9{C&t-DuS_a!OYQZX*mw%n6s_KiPD;C2V*>_O1b- z6Tu3wu>f9%mhkT)e+h zah}!s97WR(^Def7!~pTr32||lq`R$o) zk76FMsntH|b1xVVukZ2rbnK17Urz?kB?-D6nxlk;z##1&&Qy*US4iMxoe`&HqL!x9 z4*XQD8C<+cU_pk^NmCQK*o$tQ2KwLZk%j*L1pJAJ(B_v%)t<6(CF@ z*IicLgpG4QaED}BgzA~-k3%uhi%1m)@#hd?S=DPY)@vm^j%+>lr6?VQT{*wwi%4VR zlFP}-sj=SlA%ZISL&zhL@;?NgT=n7nM)0B#0GJ^e*BLJ}szWv(kqQOqP;d1oD5IvQ z_rS;H+>sy!NL|3?gBLmSx%c(~2I71ngZ@E4D|Ih!|Xfh)~agL@p~qsmum_4 z>hX1aL%bwt)7y}^AoSHR5V9A@tvue%8SJQIWPI0=S7dos^K~Xm%?2so!(s_)P}9Kf z1+pUz*(Yph!zPw!Jm5N5S5RPOW;s1TN#KjVLrwrH)4JmF0Q?(3c$iZo57gAL(J94U z*tP#`sDPgDoVs`OR6D@$fY~9&A69`K zA$2y`Za{V$oN7VtjGW-IVBO&70@gGsxME1-z>#fO+&g?EOSN&+zv#?vYrjhs!R%kx z78Ib459301^7#SwjV!u|Lw%3A3$_(Wp}L2T3h)mmuU%+0=Tz$;o&m?MUbFo!2--yw zKI2vgI|4|&h=2Y(1d>Whygzjjnm1n~p(F@j06q+N63;;PQXe3LD+%2f9fGH|Sqt0s|MY^ZW6o*6Y&JC^fY~>BFwEd^IBJ`~UxN85AxDI!ANnFha zyt}RijFkJn|9Uy1)MjaBEHB#f-e^P{p9<-^X6cTB&+@Om!^-RXIi;Hy%BRP1q^}Qk z!(Iot-5!Yj*Ci77xx@mKtPyAY`DM0_s_L9Ad?+1Lr=k6sA+c3GR6NE$5bZ3A_--qRN$__UHQ({EJIi`sC~V9;6ic-8-y!)yDN2&9 zh-Eo-;kz*=PuvKdi&OjW5j6WSkbC z=I_E2i;)C+mfJp{9cjVDYc&1a7jxx`QtKiO=5+amz(BF$Pm7O*l}!F~1!W$nOA8Bq z^OMzZ9C@I1GsOSjrS%?Cj)bgY6aT<8jGh3y?l7lNrCewl$fq>|8s2ICRZ!p zVU?IDAUc_U16#ccxBB-!f0i=DKkyueN;zKjPi%3d-F$d2owWc%D17_R_`DrZ->sMtJ@&~^kO0HiG zAkWC2Od6=b6;y#%u~pM^-m!PY`((|@k&G2M9}N2kVf3V(Ef>uxF{jf8>}Q7Ciy6@7 z?#U%QQeMBnu_R+bnC?k+NEyr`e@6AEuybgEp{`RZys9z4b!y zn---5xoIpbby_d`Z(46@INe&OddoL>4sEC_e-bWTM>D^VEE{!$zPtPZf9x1Epd3A~ zWWeV6@KNbNHmg&R-0@^!{SHASZwOsCvY1vQ!cv4ALyT`JAh7bNNuhl=#KZ6{dh6hD z?Xer@UWQx-XSeCJ@K`NsRXt9UnI6Ygf3v*VRUtn_@s;y*PpHDj(HXHad_C+U*qZei^+^ zDxi&CP!LNRz4SxNH?dfeSZcS>*~DG3*SSJOXEa_%tYp5J$B~!Is47=+N{{7}O$WBE zo3p1l4_ZD`nC^C$JF_I(1w`mLFw4miT1ud#=e4Nk8DDvI*;m->h&<7Y;P1K1*c=w} zMJ)pho?(wan=ar7eEeGMG`Ksk;G4ZHU4AAu_8W8k8@3s-r5jHEULbGl3@rc#hAKTsQM!kv2|`%c)TQ1l^UV+O#%4=C8qX_ud^=PJHt@Sk}*I}OB=`)aG^x+8;o_q zR5Dw8QSK;Z<4fTdnv+XLdogwZ4WdAabYP+n?H3sLY_OinD!#M<{-pw~EfSj)EX8yG z>o1zaLW6z|2-A6<;KcXkhcpD2`(WA}QIL6~!U|Z+MfMGt5{W9w4^h!3?2tfpRJbp6 zu0PvFpiLZBTh-gYRDb@M-NQdnFHyd8Noz;UCY>;6TJGE;yLEKrg%JV66n>T@ zo}NzYl-$@3r_GZ~QmHr;O(>n-*_QbABA9O6OPA}uw)}K0KVsPG)T?nIV9xqP>|IOw zJj#D4iuTd;twSd+FRK=7>Ak)n0UxXzwCy(iH?U7Jag5RH0s<2^Lt)M6LNsc(X0JQ+ z&BuyI*iZH)ZT-Y%KT8Z;|BdbDjsEzY(DM}Yx8|&$5MgV3LQZZX^}cPO_xR-sk}r}t z4V%FNn;1-)t>5WF%<@c+N&av1^bIOwnwenB4p(W|Fub@K?KgK*tfMT(UXoOtswIf=R^wmcGVRS9I5rmDHRhWusn$66JMg`DT%|2qQ!!6p%o)#wZgQbnT16)YT00o}RlGr^xEEfuavtLdOA=n3H0>lBJH=3{+*BJoM9q&5 zVpX9X@-1wB`Y^|fLg~@%=4AVi0KL|th?ZtjxEtt&n^4C_)E11{4<#y>u}k}BQw!)W530JRk-86KIdXS2+1EV8TO?| zsSDtQ@ytG^&F@tlIOA0K!F+4$ipvp$g2E55{=KE z7lJVkoZ-EGm0cgk z>8O!2taUiZGjl>!SsR9?`UOoGE0Ln*i%8CRKVun((EryPd}~Cn;>~4!!C7R8jVv*5 zfO%1KCcepSt%6)K;d5zlu^REk;L~6GYgMLELukJKS-zToU?0cw3ueUEfQBrzb*HgC z92aW5-f^ecb4e684E=q(991thOJ~MPDXi~?5b~I=u)XblBh#LRKu!NY?}i3w(|c4K z{Z0%d=qV5xp%@w1E^=sb9%#!CnL23sU@;qbuVt$L z!ffimO3}cPXY}2*vjJN?%I$$Q0%h?8@ltP+ThFj;2#P0gA7=$fB^=#iIS9tJkl!)T zD`5{Fus7W}*Dh)sp8fbO)=5~Ov)ja#)$3Z4{aCr3IG`4xZ?JK#Wvr0YX6(>8&A6g& zy(~oB=t=Q>3Z(#pR%?&n%Y!2Q)MAyT_Nt*MO?-c@sv<{_5ANgh7;%li0pFBVe>t5!L1E62#XqiUZ91nA?#b(FEG<7_rQD(xdi}o^!c5pR z4^b{$PYu7r=LjV4=;Vk_n5-Bqw-Mx~!SBA&`sZ!^63ot|)ew|BsVZ6iyB^=1Xh-A5 z)~Df-f%7*5o$?uXT>`p|{e$TBzWrh(Yt+Plbvgn7!|*Nocf%f8+R~YIS_mA6gKuWO zzjs)iG--2|0pX8Ij10Kr>^(t2e7f${V6G`p-<>GcLyv2}oW7hod^Q4sQfrDa^bu+m z4Q~cX9mspBS@Ru#RNO7;4C%e<9DB1!_7nZf{B(Q@X+jP4)sa&Q2RC7%*GFjWug~w# z*0036u!fGz-%_Si#J@+eU1~jbf!CK5mKJvA9Qv{l)yY@E$-f!^OABVW=Z!6X5=1S$ z;1sKIRsPW>eOeWVZ_*&CRhO<{hi_aaf;n9j{mo}awA#A_4o5G*?1kE@{hZJ6YihEkb@6U*{I^7g_YhGA<-K6?~bx{(q~&Q(9vn^6Hu{w-NfV$!l!tRgpN(+;nz zvji6v>)NvU^(CxwIJA=*=KP}MJ9N~Sy{WBYMSe%M_{X|9XYE6DQ4DRS>blD_+Fb@} zjHmakN8M1DB}+0<-6dNt-Ho{r$Z-489$8YNxqm^>W0GxxV!9ITHaV@8k{>px3w`$J zui~7_HW+7`isQau$g%2l*5Z$J<>6M+Mia?lGX_~63Qj~ntKHJ&F2)}?d6U?!ksn`A zHufdsu913fyc$Ph_ctY$2+R|Pg^-2yg81fkl;FD<1R-dSiSG<%<}O&0f6^B^#x1TK z>3B~^mXVWwTVy~~m+32ChlE1y9Il>D8it}p@sF);hdmx^eXr-LymSHP-ZhMiay8`` z74Gu09DGKYuP&Br^FF0WqP(h8_Zlmw z*sN)m^0I1o7LZvloQnh@^H!M8&S7-M2?>pM*1yG+Xx{pXS@b<#pO2>43k(vaz)iI5 zp`E&Tm$KM~$Tjnx977fHB+3(+jb?lrY8k-_r1k zG5My;WoV6zsQx*~Y0aQSLHqDNj;oxuE>{#Oq8~)Ljsp%7RssYBO*qfxx{S^)9nv%j z9O`t^F=clvoiJibb8?6gKEI+R;UtgeV**RnVsDrbkH<%$6&`r?SA0t{7oI47G*8XS zGqKofQL1T#K?4-cEa-xodhy$I>or+7+GlV-({{NUVe*7JKP|t2^SB<1tc+= ziM#8nEEc5AhJJtVDx~cw!6Ak9iK19xQ&FrbRCYsIOqYJ0MzNHeCH4$|^x9$IZ9+~l z(MzhlT6uv9rkl#_Qc5iT{CYYb)IO=QQ8+hS``>7XZw6+&7EIxIJX7`YCIwY|^*Y1k zLmNJqxEf1YPWF(qzE##RJBH*9meldtHWF+7M4aS!s{sN@+(lIDN_(;~b-g+1Fee|v z!0&NRg_2_;5qAw#FQ3u`)ey4{@m>av4hzxvw2>=FdPa(Sr=+cpZK2X`zzsDi-2g*^ zAs`?@Z*9(JjQ*koL&%he zPsDK>V*(f$FkXez%ndwKbt3fRPqsGO2qN7aWsJwJ_l(vZp z${>{gT@Cj8@Zt9(LT;=jtJ4aL8p2=V{+KEt8UmG?PZA^Jpk(w=t#Y-2o zXWy)&&hnFZW;8?fqj5lb*5!GLE~7Ej7u9}B6b`mn;_iHla&}jK&=pSnY?2?bbGTR# zUl>Oug+|aIQ~PnaJdaTHJ!TB{zz5kus*W*&FC<+C5!o}$?ABeAb<~XwG!gwf=VLR= zlA?{2Y5SN;zI;X@k;jbZl(&~f2`89}zwS*9YzQ3YNRRcL^toKzzm9>$CO@pqCx~UE z=|Bm(NA>eNfvehKpVA zp-oTWvn(BD^r9*)eYD>MIaxYk72|8g6BwL_%sD5Hi=q5J!A@fpR8A)NC_>lLKw1;x zuZo4i#`u_RtVeHd2FvKVQ*e3mNRT*ma#nP{!N(+&cx4KakZ+W zgIUiI(G=w{a`gtB=G8L(Hh1V()zSlN%pSMcnrDiApP=e=AotVQS}#rhyq8e;2` zsgoALynKV^2I+14S@hJ_+Ojn0cF5lASZN<0eA=5A7~{=qtMq1Hy(OQm;v7UY=axO^ z_Tw03;+(;6TeuC>1tW08nXL&w|=(hyL!=h+Fg)$wl0!+<@@pU{6ZAz zZHF}!!hD$-ld^C|6i;uojp=MzD>1y^EdEQ^4N0SLD}CvH8sSHT&^UeNwiKY((#~U* z9dO2tN_(oboQ290iiY!Ew}p-=r@yJCB^k5bmuT-dwTtn{ODp?jUn0pmC;k7If%p^2 zoiK9ZFHg#D5_q}~)CEq_?fuLi(yCadAz>T94qDtepEv_2z2-`EqBe}k)+sK(w!Lpqie-3CRzj2l4w_ zmF)JDax#B;0S9Xgf8S7Yd6~hXWh7YS;-(4W=%;p|P#xL^rJ2KZTm zm}GZr8R(@5EWR|S_GizaCmNz85zyZAyDfrEi`RShQAqoLHB*p#|ATIc5UXQ8m(#}P zbV=ODzwNZh^rWs2xTIlHvvG$~n5ax*7u2$sl@3-i#LNwY_k6&uB-Q3=j$0J~T$Q|? zjo`(y@NDP2XHRa^MkrCPN+>z%-y(gUFETJ8baA&u%(AYh&C7(98s>%revVq=)4ntk zqZ9(&u56&TTxblt!R$!p;*<5qVxJ4V7~D6|(6D*Z&Sx8S!x2Ye(wdJmD|1Y>f{!5` zjh)?7L`x!@;0ehH=4%V#heyA>E4{zw)l{|gIqfmMrtpy&w!@2XCaTKCO(E=2aNLp^ z_9iy#shiW1{HQf8h9j|N&-FI_oZj}0uQuIqG_fU9GC&32h&JtkBX2t){J+Ry@U0m` zbB$EM%aPL190CR^p z$f@5P2>vZWTd{6hTBx7_ne)y~`2J_FC zgNJuCwBi-t3r1&K$r))$ZhrLSyrBQ?sf?{(yn4@ZArt7+Z!6>~K}1o}JO@Oduh!|( zxz<@|g?`ee5X>-cPTv#%-0Lm7;g@@$Kq^K4xDUCmA;bTm5)AOIZ@@p5ia(ksMK1B@|FCW<93oOkx$+m1*_U(iYn z0inKl&5lotR!sPJcwxWW2N@#zuD~E!xx~?;{YS7k{|r^(be@_((F&PKXGCAXEw|6W%p!}n(stN;a)A%t#?LrTj5B{->$Gz`AMUx&_OeiQw zBz=A&03F&$^POR%S1R<)4mCV=2gZZS3t`*x-R*6J*;Z3i;~;Q!csTIt_EkeeL(6Ag zUS7+iuPC4md!iV+G#wXvs2Y!dN;o+=Ik>wk$v8OhHF*A#E4>BEAUDD}qb<6JN{QMm zLM(!%3+0gY0`j@Hb}+k55vd#+p`PF~&{Z@wb)2@?l&)mIius@C#WOcc}aA&R9D zF(?GS`V*~0Oht=qK786Vxv^Ix0OtIFY9J>sU(yRbv{a%FmzAPvbDniRdaynB38BmZ zk@)2FluFo!($v%xAyXl=#6ooi1$5}%U0Qq7vQp`0VP`Is+wY;!z?5v*lQPb8Y z25uqJ=e!4vov*||YG_ylKRV)=#!`FDfo>=RO{4|}28W;{Ir3OAR%{%cT;y>D+hY%7 zOb<4F&tE`KXWsCND2$uy*6SJQ1-&9H{QSx8Vh%e_mhYLE+sevHPv-R(z&?I(Ep>UM zgcNBU6ckL1*x#H+7=^%Oq{PGgy|>c(qcg$L-F?X#2rmZE;fgeTS5_v@%$UG^!y+Pb zdyv(>_6Yl4m5nJhM6OTNCJYVfh`X(K;9jklfu_Y0OIRSJGZb2Y1gY`k;^GjR!*`pB znm9tKLqB{PVXgmZae(7IuJz+_mF~&ENC)cC4mwM zI{NReM{!<_Mj(8Mw?Js51O3jgsY!v(*a{$QAP-w`cP|11L;5vEL`1B2P7kI9peYey zV8XQCjyL&AZ*OlyXVODH%H`oALTH%(JUN;13Me6ufGWB^UL6Bd3kVDh2TCs|XG9w8 z1((}=yN2-ELhxxi`uo`=CDWl3ikP0h&mznFb0~w4GPD*?O-&*6Shg&$_z19CkG0b3 zG2lr+Gk2x+XarlPM*wv9>S!aH_?+hwkT@ zm!F@XJ!%~u5%BZDEof!EkMo3;1txOu9 zfdM|wcD&Gz;(&*q#qNMpC^a;I;~0K?Qn-W;^J2H?-IrKtmibRSQ^QiJ`d?;aX)6uN>}= z+fzxnaf8YtEplTEKYna=FvV;oH=P87n#^o$Xh1{z)rLJ1O-;?iqa*FxJ>~*2(r2Ow zix7x~@=U?^8ggiX{sCMF3!opPqoc<{Lnasx7^a@}Wi z2|c}LYJ5Bi!gtGyk?Mj~;b3QFC|*5$K;;T55;!M!$O}z;-i}nUV2A>8);HW+RQNAeHsWy5uxkX`gh6 zZZY7uf-!K(wFZHv^sUbQ>YMrjPMsSMDDMbx z$2wiszC>N(x@GeI?$P0V43(6ZD6|QhF7;&~ea?Pnm1JYpcUUlM`ORRqN;1S1D}E$XY$E`;v@MuGStXpescehY+M4qS9& zpCdC`IyyMHg%?~j^z-w>qYi+`5M%tt0;~;T^6S64MNC2>mkKmRe&}9Cp1J_7l%h}f zx$Wz>G5aNV@qn4p_7m7l^{|L1&=$>oryK>WWpM&0{T@WwTt~19g!m2W0)F5I1oLHh z00MYAq>+2%5m+=L0U+XF2DbPaMUwM`#l#eW{uhs0zuej0HU-W~BEm5&x|xM^pd$vB z2HqVW&4bs4xH{<7erG+(`N3@?VshNRNh6ei&I7249K&xPDj{t94=yVovt%hlk(5=-90G=ihsPE)Zx1y2`c~fMc@M6F5QJ1|KTR*;?(Pn~#9dLMj&tbXx)}iz zTtkTB+S=NPd%nh`6s=HtYZoY<<7N-LfT+P%12=x>^Lp@Cd}=wKu2)-1m@| zF5+|`4aHZZI_A*(%*?{_7TEaUzc>(Pi;WF8+%_>4Si}&d0K)L#QC&l?TNy4w9to7` zwWHD{2^0uXF|qBr$g55QcS>)8+O>lgA=GoX%*@OQXcZqRK$_R5^IzdN# zY%I}~&#`S6!q7y=!rBFbND`>nVEq&4E_6)HYu>+Ix{y%-V-{gqHF_U!?d`Sk^6>#L ziT2hTV-0n6Jh%UO)w|LqpTxr>MbaR^m{1TAHN#*K#X{_yo&7H&9~3RNL?Kf&1;>v( zhGlH*j%K=O3(N_@FQ6xL*07A90mC4Mny*uWaDf#S74oR@hw`HL1~h_xy~54?41~B1WTpp#)JIGZ z5P>0`lWPm@TXb|9`r!YNhaCX>Lo-7hdA1d>nDSl%?WY{ru4OksNA$r$5c@)|>K8F$ zEd&7qLfZrP)e#PO;zU?@c+Sh^WlKBqBvnN)#T0l>O4HeIF5wqZFJ$uuwe-P)2G)M1 zOSnhB6t)>_mOekaIpwvh0cIeV3LW`z!0>4DIW4vZ@&Q8neg&RaZ?sT@rZ4llnr&`g zUWu|cnYin!LY9;_2qZtZFGC^$o`8{BdawE#blJbO9)1|zr|71&p9+s9e z6O)tS(b25p;%VUbp{-jU3}d|7zP-CU@+DALSAZ`)dXa#jP#m;PZ()619s1heZ^HmN zEi5clRaMy&fUE*~S`wX=#Xxb@_{WVg8{wDp5Ek`0lW-Uq7@#@6h8$sfoA4n|c}M`t z+nqaB2Mov;=r~>nh+V=7Jd~6aN=Pe;yDSAkrRD!V(gq=gz2v>$_zZmT?RU20 z!boE_z!x(ZTkZMTafx!#@a){2oPJ+l9|U`o$Dw1ar>+B8tDw;tOM0K;)0d@ulRH*F;)C5yYheWS`7RQ@xf=g)Om zB_wF>-@pHIer-(+^zPCV4-c&*2#gShU#4edaPaUHr~}Ui0t|Rpt)xLqz6ZB)*8UgsF=eH%BVJ3FiinF&in11 zojFkWO1sIlmwj2%H!UsMg$CDtA*?8UXv-f37TRYJaRlHkNH0B}JaOa!98AipZt^kc zA}}n=E&AyZ0yt=4J8%nY=p%Bql44>AH|uu^0H7~g!-=rSK%2(^1oa*imkdIc86X<) z^=R+!Moog3lL2P$C5{L=+xq(Yj_&Tf;$mziB_&Qy9-f68%fCDUniO-wWFzVu8h{>6 z;P!tJ_ulbXzx~61MfN6y2t`Kr$cSu`Y+0GvBbyLq?-8;`HkC+LWUtD|3XvHaGE(;V zy$*do*Y|$hzx#eX?mzDD@7HzZImU9Evj`nkahCtKLELa%`gpwv`hmZgsVA5U@6@|7dN|5}cAb2&S&WSw+ zvce$v#;~D17<|`Gf|wkZSEne=LzA?*x!4+v|DQ<$(Nqk(@bB-|*Jm?5r=CFn6MFx# z%ijJ|N)E$mZAPjTX%JIWMzkkj&=S7u9aKQdQjZ7E4%}}6o53JS11&8IWHgq-6-<|4 ziK^&V+bf|NIU6kx65^V>PMM(+k~*!Hl>^{2l_kSI2JhoMxL=mwo(uxfu9Ppm zH>KBd8GZiRwG&{47L6tTfx4%u)aD#ta#9lcbHEzEs|J6-2N}l;Rj*>g8F>nI4 zuYe3glLT8G)+g!;L`rsT%?X@1MRx=U0k0bDV+(*lK|`kNO!G<9Q3%pDpuS$rzuI}e z(|LJ}7c9hW=!`_T5x`^2uXiyNfh;c8Vz=c3iy6^L!17+|&t?U$7<|Tg*m5AYB4C9h z+xcd;MDNbV5^@asC6C0BkuRDV^9ckT7BPK~0>k}wFc*MCH4hKsnSNCSY!*!_us;>R zBbe`sT>?)SZKb=@63CziZr&w+=#E3}@?xtEZP4xxK#4gp66PLa)6ak_t%Y1QaL&s; zSB;kKg=lGo?9YQNqWuGw1R4(|mmz9I27l86;s=O8A}J|ZHVU^vZT6t=kkJfnHh?&Z zhP7k?s^$Ik;ifQfR1|^P1HJkCYi-0x+QCT8Mew7(vd0Po6wMTCy#a z7`nt-xSRF^Zo{6?1;4eUqhrj%(vt7quREn06v0I2MAZsm9LR+Pr}8m$<}V|220o4W zBUeBiKrp};>_G$`qZ4rn`VNMS>s&kT=E~>DOmNOX_ycFdsS*Tj3^H<|mDBIw&n;+d z83zmtvwYMH1S>lF`(t18IZj^D(9ock^b?1{FoD2;vGM|U0vw)>XdFU93(#|D=|M2X zZ)bt(Z*;9K_sPj^Sa=X6A_P+zncvjW^85SyUSFStBG>#DNC4C~40;pZj&F7z+LYJlZ|+AYCu1x-puN!bZ88Ke~ktObTI2nkU}cC>;7K_0Q6pP%@8 zJGm|=rQhy1R`x;LD%5!mw@3DevokNuEtu#Jy1Nz2f^#n+3mROHa+8)*AO_dK-Uc)x z5?8Nh78m8=uHf_|`xDj=a;CtLMh3_Ypwu85HOAnO2OIl@*aTXzw<(KyalQ z)L=jAK6Xb9m2lO2fXJ$#1qT|wKWZLs*!*M%J%OOcu*I)lJqr&N^xLrI{`NXF82$o3 zW@9n^?jRU85VvVVFpFyYv#|JHIZQkT4}t`IB6lPQAshtDlMj3gP$b^JzqSAZr3(d5 zQz3MS{9fGp6EXDK-43Ffo!~GRD?2(mBD@Ps!jP(@3TQ%jYy>m{VPJbWwnJ=C z8O$H#y?el#yeJ@m;+4`k15TH!k6IkQ0t2hvT7VDrU1NZQCqsO-9k>@>U*Z+E^H5Zd zIaa(COyh`RNyPAhse1=|146>X1>`nVI7Dl5NR1OFhsbkEN@f>jc}JiIYI^z@(5uLD zLhb^XrOym%Vk8YfQJ^pZ#LdLO8wP>wbhv*HMTKl^*ber#6a=`yHf91t85U!uX&V;! zH4uYD!woAH5HJIC2(jHz<3FIszMg10T7d>n%aZV zP;7|VBK>vc%9Zmp$$$z$vJ7k!L>5CX=ilq&s3)22F`!%JN{PjLJe)aU{CAT6iTM-C z9P)OH5y;s>?NIH1se2rM%jbpYRVhQEg$I8#;bAEhg&W+o|N^zJ=>Zmzv1?kg*5R73NI z!}vXW-`wOKcJ>~M<|b@!Vw-b)VJMRL&u<&rOx9#jFx}Fc=w2v9&;L#W8=Ih+6`ui* z0p}Q7L~FS(~`M`+>*B4GTKXJ#tNaDkB!Gm|NZKb-Q#&uI? z++ewjx(-663F*nI+M>^~l38M?>3)BGMI(!$k%$#@67Es^mJTE5QuOY%z~fOq-)}X0 z$-QV=HC{_9pOCt&oLu4RXx7{|ayD8&+WJJ#PL4YmjO{9g?x!~_zGEDxvx+_OB9*%v zz0Ov4NZ)?T&B@YKPJL^M#j92{Pvh9QQTMk#ekyMsB^xVl7QCP2ytflfk(@a9>DAVB*4dT@bS$-a3ORi#P;Co8lYvtgaQk`5~7Zv zcDo^d9!~N{+gXY2kBX@}uGe`-^1{rcYYU&S{@hL=5$@KAfP`sUmNI-x$?Ji|HQ=|R zhHTI|ayaT@;64GrQWcEBiu9{KLeKT9<{;vOqt0-fi!-;e;*&j01n*b(u#opqM$&_A z=_L4RibE~ULvG|1M}+1He-?u&-W$_I(zJirB7DS3&G(mY9w$maE8VwvFBT#AlXjR< z^;dnaYl{ED36=KuFlEt$=f4*~wgH83z>p)Ao=kzb{SXLbM9--(?;^=<Lvn2c>ELWF}Uv-on7YnF= zi^{eYdc9JZaK#-N6g4d(x)<@<%#b#udK!x&`Mj-#py{VSoUi?i13rd_C_38&=c+<| z0(Er&e~QNugTOf!SP%X|c+QhFBTJ)85z^Yd4U+>uUfnTnxM3v4I46`h_~5v7z!Uq8*l{%h z`{kO9T$8CSal*&B^3IMYb;whGsndz85%i*mBpq0M%VT8{VO#z_Bw>V&jAN7;tFohl z@GXP%Fg7gVG6jBa;p^9<^R0~YZA$t*mouHMD_(KkYa}7tO79zn@&D z$X>DbIfzWNuJ7&o{n_MM)BS)_cTPce(a@dbi@N=*4+iNd6eP8zj)FzMD5(u6^0K(e z(e7|RD@m`&cRZyj0m=HbnEofVp{7@NL>`;JFJCAMc*6Gmql`M_uP^E_KhB=+aM@M9 z)GG&1L)49e{m4)2PW^9=$C|j-K3pvs+hpJ4Sa}(|2vuS`{#iar5Rm==$qx_W4g)HzYC`AibQO#Aoeg(Ii`|PSqH>rvvX;~Y>!}=8W1B5o zeoe5Zc!)m~_2T*Xn_&Kq8&t*9q5AG|cb8L5TzI*hWh^(_&JhL&#xqz(_D|czd zG-vDDNCWYwEM*?nek^6&TWU4~Zuba5gW`j*LsTOWjUf1+gA)jC{GbVf^$X@KEA<^F zajLEdTW{NsWAl{7=CHf}FfDHDau$qGCV>I4YupPm6{$YeQ6X}Ds9vfdugrSIk8nuX zzpY{Qp1|it&C5xTODRT$#_;;plfK6&l-!V7Uw$z672lf}KI-23YeV{-Zoh-Vh|Bp) zH0&Ca(rShQ6|g-PCL-TaI9W%)h)xsc8bPi+2h40xK##$Yf+Ql2x-qEFG6 zT_^djQ;}1=EhC`vVN#f3=%e*N8%ukfE4$gniRl_zR+>O2bkGh_dZbyOqi`3ym#kt`(LSqSHh&FX zWgECshC{b25j6J&rM7kphVSGK-)Vi{8;n0*2hmZA$=jKAhPqKCN!D~v!X-yl)SXYu z1&aF8eP44{OA8cq<$f%)uI5GL9=f!h2TNtZEh9wan>*}-;&#i9R~rn)t6mhhYrNEc zR8%g|x4tsRyroh6I9H9fV>h<8$7#{v5!}XIp zmBz@<>0KIZkGHenOIK3vZ?)!|Us$=mQD_8%(Nxpw8IQ6DN7`Mg;1Z~wplxHJ8x!Ug zbOs@pj|8YU%5U$VeZMYP+`x1xuXZ|op`C`usP*v<`PefN!pYNmO@L-74_mb&l;Jl>jL>l%fcyV+~x=8|v3A zx2D&&nec31AE18aDVK9a#9T#EbzM09l2H?lSWV58!cZyUC7;z{}Hd*GqwbGj*;))oXf{36D&M3q*o!)R#;xpX;O`7eu%LXxF z2o83bF+!@kw)P4g9bK(9gmk0Q(`lg!L>}iPO%)ATvEyb>8l4>H!mPKoo`>ezUQPUD zy<%`pt`yW#75#PXh`Xu+jaN&;=RRTmJjm9h?WiJr-4){^7~wO5lC&UmLZv=!?K^9C1!8mE6RBg)7Zf`cOY&S3!0LNv+8g$Oseq`}>2fL(gtI z-FOvBIErqVn4GVvhddGcCl~=lso>@JR;ZJ>w_MQ`26<#AIdzC2FtV^)s zJs@%oHmcL_uj*+6HUT5H3lP4#mN($^ZSW$Z_Aa9kJrwF(@mQvY$U}>@0Llx4-MaI` z_~_jT3QvI5hT`vX#=h&PQP3AqLSsOZrUrYL>-K9|2!BAhSxZY6f`^Fj2@$zcl*0t4 zA0n=ab#C9tAjSzOJrf@4ORnG-8~Go&LvXAcScBoQv0Y%w1Ed?}2q8}^4+KbDV&WwP zNV@^>LpY@4JQPs{1e}6^H!R&*AYSH+Lgfsds9P9B`&^%+JRgL4Vlq3-T6%k z9cEU(XTuk2QzQJRUgWXB_uk&y+n7E&n7)xEo(dr_=gT2P=iWiw3Q~z!7LU1&`=F+y z6_RTu){xq0*!}(#)t1!50_BG+vwn?ZFNC$hVy395Xo9d=$BA-4^Js%rM*y>e+!HhjwvbLo^)xWyW}XmuMFCPs zg+iE2s|qSX5ZAa&8)6y=UHnw%dF#*+c|D|aNyy3DcK`f?iH`j))szBqO1z1wW#1gD^9xpa;M8ENs5A~DBFy%Zcx+l9^y8&X~0t>g&9C! zjhzN+2T&m$N;jbhHAL4fpiT}|C!o?M|3ug&P)va$dWn#tflxiHytD9pWV9jTv)2UY z8JTF0JXxKc*7wQ25r^5D5yum(eoabF{Yh@lnwGuxaO8FMr{b6U^nVPCp3q*_{_tH} zy`ot0$;hXV4THPVFd-mC(dj*9zGK79({XamLS%#ClMim7-Lc5ND!k=H}` z^6Jl_KmgSbi0^*QYrhKN&Pk^>LX=Un1;`P?-!C2Rt+JNo<_5s7$pkpt33GxGlmdn7 z4LvAS^Fb-Re^KsHyjpwX{eGQ*q-5jfR`{a$$cQ89w|>d~hiAM3HgUm%=v1K+Jqadk zMaZ0fg*;rJ2pS*ay8&UV?{dv#YZm$ko1)ClDYwAm)9b7@voA_W53x0xUvQ7X#VVMTmc)!iW5#B2D0b;o;+h3y+Qup!45f_oYHe zGgVma`9PU|Q)1jCfeP)WzrX-2(P=h_tO$~zya-l1KLn-cP<9TY2;-WN?2{rPiR{n? ziXtElIelDPPE+ytZaZzFa|clM6oRlW+dvitGM90{XYG#9H`O^eS8YGhN8Caqb2D#u zI}05&H7w2`vY#&$s=}br>)^|vxuvkL7R8(4HmKCFvzU&)I3%*w>OCAbDKJm^AO>y} z?=lxeH?G1Lr4Ct+ta^MNXG{~Yj6Qg6ac`XaD!2o&29N8QDWSU+e`=#HjUDZKEK3cc?ibSA;9_zkmfE>EcQ|o?h(lwawJQFxvT=0-ZP7u zjo>IVfuL(x_mORicIX$ypqDD?A}NoUBt)XWn@3AQX&PCe9FbVz=783oKw8JeNS&9$ zu|{d{>ODWseHOD@U&*ZU+UnEK@bnG(d~T>`eykm06 zr*GxSN9#gj#s{*0l=XIl`M8i{HoeQDnsuYb@$*i#@@ZB+H{ zU0b^Y@OF@oG&hdorMm=d<02?-ieiw=I*8B8x(StzK52lognSc|Gl)_?e_+{<4}tz! z6DOYDLR4c=ZcGF+n*xxSfby4jQwUQC3Cy_+8QDg5{x_7-KSn#Y#EC+Be(Qe`D2+W{ z$4YdRkY^4#2;Xblq%<_}!-Ik(%l$`9>kic`58iI%F0XtQkG;DA$_RnIT;(=a({2-DQrh(i8w_Czv&zj(suOs7`d{qMJ$=HL>G=_pYJF{`;&o-cbez{*AW zD^L-4pa@aRwT~A9UZ^;r3Vj-(d?9V4;Q;lA2v`oG|M*&9NI!-QS|ubjN)gN%>;(wP zZ;>Pec@y~Pt$^uQ6`(2j1a)tSJPLSNle>^Q7lDLw?YF}8F!?+!6yic8NG65X`Xy`v z?;RD}o{8$3Um+Q^D;VUgXZ-Wyj>+Fe6d6nBr;)}l>Ox5V4zFbMYY}%GeMyJNW$y}M z1JCB}rk^GT7wdC>{@(o($s4Y(6ZCO{P&xvHH zoyc%S5%H54SWpSmvy}v8H7L7`;O+q1g#;ml2c00fg~-Sr!cZRz?CL(iz?;t@h&7aL zpwmEhSfDI6AF_{$$;p-V@44!up#BP~dfo}wEx&wU3xB=99^~y@gDN>F{A=+{di1Cj z<&;1>e1qzkkNV>M%s8hI*%ky*i3eQL6@n)S{~yI0WQx*w@MMahpr?JLL^Bi$`CPir zd6onA`S^3_hz$^TN>%7_+%mcs3=~ZSRF2|x`!*PiV3`p6Ou2s+G&riWgG2%=h>7z! zXg5HOR9JUY!RYk@9eunBPpy{@dqmaR%jex<4w5L=-xepy+g|5WB4q%ftYp}Efd7am ziucOWcH>7!4%3-02IG{^O+34V#3PPuT`6zV(#v`0Q`*%e@f5j{s`l(~oZ-NpTeViG zGS0~CNzJ_PXI=BzgBE6!9)T)D*M>D!)r)SP<7(VC`_k+UP|y_NyYwiT9o|eG=t>kX zb6ZwNzfw-zn|bw+&K`0@LXc^- zf=sBc9dGA{a#NYZ-$jz9&*g~DfdRCDPM<*MH*DRH;@xiShx|FDnt?Id82GACtpbZr z42r+8)jMnz-!qeLcbopqpnPMkStAnLbM}44pqy`dv$fIxD0tt!!-sSH zRX{s228~+jQHE(6I zhp}|LF%Di7uq5!{jUuvNvWPcULxv5zml5FVTKZz!?%5CPeq_ONWY=LM!f_SyvP91y zlT0J*7!}sdSTw|=dw@sr23TZt=jHCUq$#0yhs%+@swG?fyasQ!!2Vf{9!)*$cd9ZUo4`IsfJ|`lUs6=q_tp+ASptN;F_4af8R#-0%ff0%3Jt zP}!9p!5VuRC2N9y7vHYgctWERUIcOqV!vBTz~MZ8?q2ZSE(5|@qFLD0weznt&nba;(O9M;y?eRhj zO>+9CEIWO`O%~2!EIpDRQyYyxo?IIK(>a|oq1$kW3KO3mgUY-pLfY)8feJp>a{RGh z=d@M6hfVBX+`AY>mg#p@w#KEH@9a*>7jM}jBY9n+(63!JGlF8+|MdYG-jK27`YU(N z5+_U%v|f^}G0}L*QxZ)=DnbHV3pQ7`rn;j20Dq8Ok<^0s4Sk{Nh0|U?%P{9F5+X@C zy#h=|ew4q#9HcS-aW2qvxGL!MUGg3V6~o`p{n}GIi%50`TzwO|mGZ)G)}=Uodq4Iu zc`ce9FZ{B1h|^DjV#8Ra_np-ZCtiF`G7&G;e&cZ}UNf87@DEl?X_J&2KFd>Pzhq;x z?;aQSf5l=d8#O!Voh~6<*EfzB-E?VWdd8%?joI>U^oa`w3p2xuHWK?G{_)I-S1BeP zcCy|QGRq0Z^Huea#xhK|uVzWhe%bqVyi%BN+V|loI$X5QSCO$#l+*Y_l`x&$0jwoi5*SWHeA5NFG6GX{GHn>xw9xoGX7G3rmtqC?ekV-y`xW4k#OEm z{rZYy4Nw`n`=ox!^*mK+WRDLL#xk&Z{Aj92YWKp*vX#rXZ65iFV?3%1tE_TeXBQ^pJi>s%wg;cS+Zyv{ z+o}<-leKR#<7U1N(LhOZ{O~f}n#MLBZOf_2HU!@T_VPIZd|#~sz`jve2mmSHih^w0Q@D#tRPPoJrAKQq$W zS~9k{6tF&?Su#YFFc4Axg~2!TVPXgf1jS?Gp-a1SdNO&>!R6VIof&D5QbS^)aNDVY znt){K-wDPoo9-#E&sFsHwZ3n{j9Tznx0}rtPx~r{fs@=AsmKmy*c&L965Iwatvw2N zrClV?6iT@r6+8M(zTu{@^ny1$63h*SmTKt+bHBG+7T;fWt-7#Qs49?@_!Ah2#(vyZmHt*ZlDlnc`) z8Zt0?g?`GcEif?Zw2WdVg@x^_9g9tuZQQ)_JPMD*))^OhQY(wFpE1hEXx3goSKf@Y@ac=FCE?;U(;${?D@-ySV zD+9AScRZ`1=W0wPv|nVmPF=Xo6RX&771n!JeysyPMUjT(&Bgfn6;{!Cmc!ne8V2d| z-xqW7vxC0sDB49OdkPtK{U}~!*t0XMT*?2=eU&%WA?&v=&7&Xd4B^8pE`yhHHMuOQ z%)@{ChJcK~G;Vkho^Lv6Kqj){m&@-s*UY!gDhW5*XkR4ga^QHNh$XZnuy5`k9M(Q5J~Y4qJ$d{pEzJ_`OZXE{WA*pNf7h${_IayouizYI zk?!1u8LPN|H6K!VC(yql6`1_5=1cfU!T#}B$NjZp|Ek^fJ01ZMr;siAR2L&P^B>ix zB>wF=BO87MGBvQ31`OgRPYfD7`sey7F8!f{#7}%lk*0P?BmQA^Z74hL(qFY(D@qtR z^5WV60DZepYW${rmWp|9l{Nk!GvUYY6VL9Qc`S)aLMaPbpVa+;m1kY??nIuMCf^jXg$vqBEz#ySP3TsN%}F<@@g!uLiTJO_R~{1TbUI z$?`Gslk_~Z&X|`Oj z9>yP>0OJ5#*V3ohpYPedBw5qr0k>CL;L6rqo0mX#&|p5dmcxU~?-lrz zv}@J&ZxIp$!;~T5?^n{ZC+j;+eO|~4GhgWZ;D*hO>sMO|@xyu>u^TQl2tg+;=qHxT z>58kkDftAGi`=+6jYLAyhQH@&d2GgIy;YkpSj-6dE0zCpUmGf~vmz<;!+6nFrRDlV zGSI;e=hnd)up#%k70P#2m?XW4oZ2OJMI3$39y)KC@@+U9=#Zsv;h277mG%2APOV&J zvLmZl66)V7lhWfm7ZBXUth>wSmn>F6sM@UUaADhwvm&+Tr7(P$l*- zl_?EfsQ*63Ou++u=Ys4Rce)6ryF_pGQn0#a8IDePv3d3OF@nikkFRrZ`o)k+?YSS$ z=}q}*9O;2dWsz^Km2}sHU~$QMAJ7jKi{%S63tY+Sj?HRwxP0F5;FiadMN$AaKY={cHrD%;9T5C%ol$w zyd1ERQFD`Lt0stcF%W;e#O3PPg;F^%?d@0YhJ(#u80O%_Ddc~?`fY4jBvRv((`5JW zlGKt+%;?%5UV~k966?kIc+k`7<{!f$V?d8 z8fQm^v(-|!Haqi$m^icgR&Lmuqp39=Oe+@_suW~m3h!1x5|v0240e$}_vQ$&9t|>< zaQ$ygwo2ve82jY(OnnZwL4@X9v%G zEK{jORrj}q&wTYWaGgo@&;Y-bgPmw*E8I5hh*h<59!98HM_+wruId~CJcG%_h2_YS z&jc@e&)eU;YdBuC{C3zeWYm&Gs7SbMS#$12<|Z|5OHv;T=PpkAM6zwQo30I6uwmRrOn5cblwL`+6h%{dI&arx7)^xdA zoFr3je`+Som6nPmT@q;BMGkghjjktWzYCk}i55?WaqK>D`ni{~+tpevC_7#E!08Wd z`TcWRj_qgeUxRtOabONN%~bh4pI#n)^MRs6>Al`PIQD_xbU?s~gi4AaqlR%ct!9i& zkG?`9X-R2mt4LRTGXzWFfRuQdPo2F6Z{OWexZ@95S2alZHW)azJTnOO?-fiL)aaS( zfCJjrUNmJvlX{6IC3mOKrk-Iey)TvJcddqSa^8-Pl&$G5ziq}cAJ4g-rR;>^Dvp*j zx2|2sbDo-you786($bzi=szOy_#Px|Pi^^Gl<8n^{`*K9*fx|8vcfrQY@D1Uck!rj_*09sJuQkb68gr;GVzE@hf{iM8FP6v$| z%6NU$tKIzh#747K;(i$Z-tUKnD$YMADu)((gIKepV6Zqc9!sBUSZn8r8pF4mF@lnf zBJ4g!9hg4m>bRNGT*IrJY{q)yJeQCy#T|?FXfs~j>L?kF&#&V$d;Q*aH&;2Tc)er8 z95s%;e{?@go>44a)*{=7=;Jd}m04Tojd{+2YsS|NvK>c+^iV)eMBV7=EAVy362 zgMSQ%-?bp9m_Ew7OHM0@_wr@4NW)SVbHg0oo#}rfnZvcb#zVEdL5!QR{_Q@8_sp2( zn-_b%<~vD!ektuwI5LaRVjAjDmfba;>w!bdgr{%7Db7I$yQaqX&x|%+U5w;*V$BTt z@!@3DlQg@D$C()z)2y|>HJC84$qtvTmfuoPk!Rf(8ZK$OHCz&y$%`@i1cO>eaJ2gJ zbmz^i8(u4QDfc#bG>hiEw+hpCW-uC@=fke9+7^S*S=`JKVSG2{>IFLdaWC(B2ulbJ@f+yzAUeQG#n12E1)V?xz$MN(<*iF%~bMU$@kr~|=ocdWa@BOFsnURXuq;rtu z4(`+o|L7kd3HJsR+CzxDn!dA7DzUZ{s*HUbGVLO2Wt3^&GX1H)Z1;lH;|JEgdt>3` z&hRxB-sAcm*m-=az_>ej0a`uR9x3zC3Y%r$!&)WwKfk+}K6cAE_}%rM$vW6Wfp$Y7 zSH%3p6O+w>w^6$yx*y5K1P#Dr|BEN;v&^e_ovE*3kE^hOZZElsgq9y`Z%NYp~Q-<@%Ofx$O-794)&(u|3$978VWP?BfoNIZ4YFzBtNa$XPVr-Z>6_9;M0rOmDq3i*oyeFF&j){}F zU%aSa4JmLLr>)N^NgTWj3vux$wY5n?OfLJF7pit8CYerqVN^SIa2m)9R@$H4Otr%C z`P1sY+GiBZsQbRr>qTS4IbovJkz3=L@Vxgv*}?YRnu}cStFnK4Q(HS_XM^!F;b;+Y zy?`B7Gz}>cU05dH=`>+hI-V1w!2kGl2LzpIe->uV^i9F!Y*i?xihC3QGDlIVMbH-0 zZq#hCKlGJ=VYWmqFq6ntgLIys7fZh~T1dF^H4j%ls+r;psg+ef3mwmcwM0#mHmuUR zeP39zm@=VrF_QGKRs?LMGweR6U4grm-8>gizse$h;Pzkd*xQ`&QWcl-`dNi3JQcQ8 zKiv{Sn9?uFx;%C6W#xKj)Wc_--Tk2>PkD`fPo@izW_i-rCq9N{$=tAQ2B%uK`+R3J zOc$!ni)EqaJ*BDDz7p``MHiPcCh6?fAv6M^Lb6qJ=fNg7*0?!2vDnq1yU$nZ~`e)sDj&nmC83e^JV1| zXLG~pMlWd9^g7%@@;gEpv)m~wNSVt4a;0p` ze#eS@>9t2Niwe%(rrc)lact_PaOVTpvtxsRDH2l`sya=inmi`q5L4G^Rk${apW;%he znTCzAf^w44s^bqe?O(K9Hydk6eW9epxLYLI@~O(pbF#&cH{|xS1-n)f4NY7q@~B;v zfZ6|=eF!Ua?lWlPchqyO^jFKtS!TX}?8x+>@v$J-mY~MytGM;?WhC#+-tyaXKAaWm zd25|99gXW)S~_H#KNQwBvgf_GScEJI%I>*>rg<6Z>Kn|9{wt?XV>(*q#jG%QQ!?{D zuBt@pOb9I~sP&lFRN#*|j z0edTf8FY=E`o+&KERV*{EJ=3#S?T5Ke6YG9*jXM~wJf}}tpoF_rl&Oaf}y3~Kjz2h zblVoNWZ-DmFW;X&d6oDAS4L6g;_`I%Oyk~p)==BSyjZdt3B_Q}im==c(5!|8)%(X4V*Cy?mhUOymdnFACoAe#J84D8kR&zsItkml+~czSWSCz0 zgDaILC+#P3-ano_S`>yy^2+ht9gA5)S}cQV5-ZBftrS#kg9ToB3gkFL;7h*csIy~DhiCTIyI_l(dKQ+G>~%?+={#pzo=9FB zGhYuS?z)kV1r)8ueKJiQEKujEt+;d9 z5<3@Qj~FI%c@bX?0to{8e6wze2cK&0Q+05IIEaR+H(O?1vDiyvY&bl@!JwhS@c)O= z$!FZ(y4|2a&sclt-RgHR^PamRfyGqk*?IAKf*YocuukTX@zO7Wzp$X?N=Rd3>>X~> zO|qP?G?r}KdCrvpmWbeJ9sg8iKa9RTF{x$u56raXAKL&%nYB=&4v8c2#3c1zi7h(I zS!u(GYLZCU#$z3k&cIj#(U_P#|7&A?lHJfdOF=0OFTZK@ytGi$#ZgXfg}d3Gg$GyZa?!E_?-F}}bz-KF0|=&yNGkKj z?Nis4O~?7}Oh@fep`cA%bwf^=PMr$LI0JA&b5zoWx*3aKlC8!o;H=bQRNw7t+BP$T ziZwXqd%Nbdy#2E7rZU*}U^&u?J*KJgySmv%j0)g|Qq^<&-1Xxib<4bDz# z+fM*Uum;*_)>1rF=gmUI{`e0OZ6|e1>8;LXi*JcKg@G7dO(NJa{?5x^wreg{-Xcr+ zbi<4Pbom#7>$6rE`h(A1@24#ccj`yd`5sqn#A7Z@docqU%JZc;_F?lwus6p$ME1eB ziEm3?y60v;681jkv*P2Xhj-`cu8;>jZLf{173|R7->vAc+fS}Md(dje&XKpQLM{5G z`8eMacA@y#?dTAW=r9@Q^T0jTK*|idEjb+@g!YrTR zIx{8)-<-WA_)6DJISVnb@5CHuz21Z7uL`&A6VWLf?+H}x?-B{6qn>(m6adjsx|du0XsG>ICeZ)nKZ%toxMUB~Jz6f^MDv z>`H8T;Jq)l3bnpO%lENbW>6kplT(y;G>nZ2N&pTNzx zoDy%1BVIeKfR^d zOF?O-Q+5G(XCGg5HEs~)=g-gx0->^ewE=^TtyVtT!@-w{;`MCK7q*fpTgdCW}SH)$CggHik z&iG5LjjPSh(}{^3cAO-lGhX0n7n!3Y!H_N$!M2O=bQ-$5xN+Dc9U`%Yi=XTuN5pw- zuG6Is4&u~%bbvDR-2FB~XKYG<3<}}@K?$2v**$srsN7gGAp3}Jv|e~5;71uV)ZBKD z+>)_j%P%C`Tvdf$;Sa??Ui;^DTtb`CSs6p{Ej?N>4L`rG9lAMBdls%+58herVsAJB zU0C<*ovs*m`fS@v6SgIbW5Qi41XpA-nDK&^9o^T7LWt74S}o2jQ!ru2{S6T5&c-o< ztI<~FfKNy}C+gYR_zTZtP8Ni*lft>+tx!o5)*BC^X`j@l*p~U-2f^P0WHE^&I%HD5 z3abUtzW+p~qF=KA$eh?{#+7Tk>!?X0`^P8u+hQWiUvxs=rU-n|EiMBw1i6$O&~xoRDF4Yawc8Cp-Zw$*(vr(3%jE{U`m+Aj!^y4r-NUUd=9Rs^-rs%_ zZ{M~^-F`!}&`tWPGx~|+?N{I`_oN2C_PFeI?+FA*O#A4DtLzxLiTkn@4!*HoamBis z84yXu$cpXaqPDdx)!TjTVApP#yK%;UXFDfDB=A>F)06#8+IQcEE)}Wf8NSBsij{HX z$`B7Xos~}HxK%EEmq22&I5sY;Nb9e;<~zG z0Q;_v#em04o?854ZULf~DqE-;&VcQ{q=2ZTJ_vXq_oDl2cI$R!%ODJsU{k?~zuxeqh5f zdOf2qt5dR$_Se0#w=Zf%#MWn}l9mU*e+5*Hvxi4#O&K#lhN zWSuKOe_UBpZ?FK$s93KOdIR=UiT_$5eVb2y zCrNNG;{<<_h?tmWe~r)-eUl60XiOoSb=oO-zBETUHer%+q-gBWraTMSG-z&H5dgpq zz@z`(Vxq`~CbVySV3{VZ@Fc7QBFCErZom!!{P&fV8!Y+)esSxIbQu|w#mm26jHaCN z48pJTSVm9ircBXEytI(*z_WkpG;@^D(DfSHDjtb_0|ZBIZ7nrpdz1W-fZto4iivjv z0<$0S2g%9K};-OWUbN*0Q z{&@88L(3+u(78aZ&9NqT{N2Fvf=Nx@(20anGod=O%5f((?K5)fJk$hNGIoB_XfCZT zbaS76fJb98dhN8pX*mpm58GnVO;4}wJ4YQqOZZXzD{Ea+X|##LiGSKRPkkI1KLN?f zR7oSh1jvOeNec=JtkXJIp{L7sr1VKC`&{fl&kF!INiblK`poG(8ybN7f@VmD_c&h# zZsPaR7yUmqC{D|%llT+-U7s-brQ)!W1fr)kjf@~l?!LCQ)pdu@nYpx-X@%&_-^UX~ zvUL@3($Iw&O(WQ9R^cQDt$TA#3ddw2xJ3K?eiI(GN=p@(wVGTTnq+Qc%jueF4e)8U zSJnP`1QH*r?9dUcAAq@80sR_>%k=*H&d}!;L?Rm4(hRM>bzbXaFpd217ifnubUX36 zt|a&kEUnqtjds+hsUC0z1KREWo0V#^QoOtfl6aQ|I(|wTc?E-+Wb#H z0G$SqdYn*V2I%)AMqq5mF2@?!B6Z$>*d-6#5}^~vv{E~VgNjh%fC+DTE>wyZjZ8|v_@wCZ1k7FPlLu{gk;A|MrXwWUhj7kv#K zk$eC#M(j3=v_fFBcL7fM77&^40jCzaRhOW~f7Tn?=TIw+dY=3`Q2y7U_WuJ=_yJ#s zdYqs+6)|RjZ#uiW8rudu7U;ZzFxzU^^mI0$QIny0F9%Q?cc7x&clTS7b(%cz9>L;< z_EkdYsfE(*kUo2%g!J@Cn2B85@`<09A_8(RO-A)v=9QPn!9+O94G93wd}pP8)n??o zy5a5Hr2gXnEV>nbsIY$mT(B#sX$@hzp!v<^OE)P@Z6B%|2P_0Nvn zUB_#knW5=<=6TH&6CmsWpGWr@e)k?AT-4Bf0%N!OkRwF^s8s};hej#{O>+ZuwdGX9 zJ;S?@)@kqPsBl@h-gtEALnC0_46VI&sW8xphzP*wa$7^+Gvs~D2Xf^&q3aV`L}!53 z22D8S`p>Tbwv`W{$*8pzq$FZPo;h>oD?qjTV6wWPb3k5R9t#a&u08xKY_$$3)Q43M zDyk0n){Lbg00V_CQ^y)t*a1&$Xli7J1n90`kEr$dNi)~?pKT-z41Iv&$iQI-h_VK# zcP7B7LgO_8JZot$zyh8O1BC?rB3}j+7!ZBG0Qg(JM+aM9QJ*dl$aju2X$5mdS@2$vivdFa;90Gz3u%vAv$f_{fPR-j-K(+y|aS2F{T`gu6AE3`OhE60P z5P+&g^z`(@PjAHn;87jq9b6tzW^GSk*Fb0X228d(B>QAXG}P6l;M>~3tb@z~dYbG0 zwlj2{2Mt(%F@}eol$30+^WOMS8c>@+Q414m3;QeX=B5D-3)7-ySvh`*gJa&K;b3zD z%_zWLPttn>NmKi@Bq|s{5y6ZJvmypm3}EO66qF2t0*aVW z$%2_+07W>z3HIu}S9hPi@2P!n-4DmARkd2-eV^waW*BqKF-NBHKIq4vn(^Brv^^a! zUAiROhI$~Pjavbrn~utwhrJt?8g3J06_j37QgV`}FaACH=*enB=3W{kzanDl2{$Xg zF0NI(_C55+K8OSXLT>0XH$Uq?e)441p!0kQZrw9%^_Of!2@+^uZlI(T?R)A}9Zy;V z5rd3F%WfnujGms>kX21RKivGbgJxPpp0^lJZaOmUcqc{lt$9%0-iPnffS!s}Kh6vX zQWp>SY?I$YeO@XdG4Y()`Q`}Yp2m<>J?oF4s6mnK!GX(lQ7XvCBAi(Lf%F33 z{QA0!W8Xy&hMJin{dmqI3?c+Glew8 zi0>l8t6fhi+=?FjK1-kO#cY>+eG^c^+2IJOE7hxw>>$dMSDA>=XQDOQw)D7odTOs~ za1^;aBr403E6Y{noZP;xVE+MSOHFndIo!!%tCpinj7;uJhZX%!w{QRW-HJXH5PZ{ShuybmOyf5TTw&|FEbWASubahzRSzt50OE2l{{mQL&DW zjs1B#UE*kH=7r=Ri$Y?Ne$7BSR=Zn-j%E9Ty`@R~-P69(cYettY&^oaqKt`vp}xqv zi$E^zdun_E66Bn%pcjlQN2N#)}8^(WxEbfh09{mwe@I&th{uvJabmMsvox1Wh z^){?WlZ?*B%~2KKzfDJwRAlg#xo$alT|&^NqkJ)JGMhveMofUIse4jdS~EKIQ8A38 z9sMpFk-|~iv9cT^s-_~ z0IgHOsaR*C{K|!gJWg~nw?&RyfO zDI(FqWswGaI)@L?x_M&4gb5tH%}BO8auC{M{iJ8JW#2`Gw9#Khtsarv5N~uK8Brj! z5u`gd`^&#VX`Gw>%J*9Ics(1}VUGgeX4AA~X@77D2!E%vrV9ty-rU->l6M#^0 zv5a8AwsSe;j1Za@5R)_YpdC8lVj{4=pSV{5e|h8^-1cSdWTu3^{sErs_!~q;@tyfA z#PHyfE~B@M4mg3}=x0a%STA4n@E%;4uGWSlbZ@~Nyfo&4X)V%hx8+2Y{y!>|Fg{Q| zjqs(7PG3vkZrvDdXLk`ArMbA6reudO+y&NsI2y^K>uD~Hfg6Z@MG!*fy6B4l>dm#Q zwNUIBGiT0E>fOyVk@-DI5V`4a?>`P(_OaYIZ?^jT9~roOi>P4WwH@cqor_*G@%ok% zcI~i6rwIv}aYPJp8->%tl9CbockWzwdrstnKB7g6+I;-ov;JEMnW$PfB!MX4$i&j1 zm+~ERBcAW#jJ~3+!9KrA@vWWx@(+vP9-QBo-R53SK1kj`C|COR>xn^*1&v7!_~~V( zg;p3~&l8=XqloY?o0_tno^9d?8&B>i;caXd!K8!@((;`_sHu&lcQP{$Qf7uYY((Ke z!nOW>f4=Z9K{hi*azAFPI%iOXQm#Ic?qsC0a3_S@A_d)i>qas21aDW6F&CK&=|kpv zm91nN!!c|%gAB0jXnb!ZAhMZ@8jDDL;8!lwDUK12uEcz{wn_ToAct>SeF(2hyv)Rd zI*0GZiiT{2Wor%&P0)0yulM&yuR1l@-kQL+fT>E#@87>iA*c`qhLV8dPoGW`y)Z;U zo#V;?g@PwnJKoC2U!mzu}$B75WhUqdqwuMy4uATw>J(F z9p*lZ9!S=vxI@QK6zRF$TVo=>8~u~D`Bz>w{Mm9{KCU{A41Qz!M?TrW{?U*7hKiHP zL0Z(sYa?*6Ws4%3tM(Ym{XRa)EStpSEAOK{A`Td#-V;Ej=(g(FWe!Ef9dzW!5-y0!uck{#JQ#7)C|78?S08S zBocWUba=CA=oV!biGmTxwd{8|9x*_A71b! zAUwh_hx$5ecA^@9PP5AKg)IrL<|7p%O48^lV^gn&qIs>XV_<}VmRSL^63)&t2WJxf(-;8_^iq(Zh)hpE%)Kry zE-w81Id)0E9A-q+vsm@2y{PGa5O?SA&ryjaIKRiFizY2wZt+_vNkd?u9={}?0?<>= zh#pEx%?M6KB>}+>)&BFUQ4_q*5Q#gjqC6%aJkiPYC4r~kLK#XS0zph*B4}FpIIs(hvXa+5B2e7e$!U<9>i~$vP>K) zY3KYtExBk9F3l9Fe@R&wS#SqY$i|gD{`6<3WL5~$;@K}>#sVV@r;E&tW;n@zdg(Bkp*?Jlac>e$Wb%^#! zWVnwERFf+u=ht8V?=Uj)zpGIMo{yN%rq%!2Z}H0iC5#iS9&3Rgw>yayxKxlm@;&NvV`x23rdKlPWATo-c_BN`um^gr1)h}^^#?qoCY{# zV}Ce6l;Bn)upbEoAbzNmqQAextshpt!qn94G(N{Pz@pW}RN{-(yH0efGT7Bt`$M%k z-elN}VK=}BWbKFi1j1-CYH~{FEpGn))d}&RKX>vTR&CR2uRjj`e`^si7U%x3A&s*y z{XdR<{>xSV|N0Ah-zh`Jb9jTvr}OgEvnM}qW$!v@?bkj?t+eUZZ96nf8F8}W-P2Ln z8kG1?;v1g55$zFzD-ri%ve{`gS4@8~H>Vnzh!B|sISl{UNt7s~2*9b@v}wbX50yQ) zN8-ZCD43E|=tEwuCYK{E%{!w6zjPn5dSxyBp?nWgLhYC_hE17_KY&rhVNBU5Tgo&U8Vz(CbaR>t`k_iQqCN*9;gU1qEIBeLkXPw_X3Xnk| zWF3;gKf=Zn{xtNjReh>Yj2BHC9;g5%{0Y=T30qI=im8*}PUNv3B_hUwMVBZa6O2-5 z5H0;!#PKq?ZV8D6nN>vt85}|E&Kx0|)94pKc+Dzg4pYzB(G3{fko`>%Y{BwQ>KWFku5uUg~t<= z;lqotGFzGW$XDeVW9u%=ys?j=Mg|q7){Gmt8zz!mSmi%nGyA5@$-uEO;)kIlGO5PG zDXXp{V@|M=hY7s*5qR`kQ)RAUFJ<3 zIdVkwMNsPM2(C%Lt+(?E8#H+NP91R+Q+6!yaSZ%rD(b%6J@#&{ScA^01tj-$}N|* zXe$eB!;ZD@*>e}C7P%L3%;dVAwnPF;lp(aFchHEaP>?_-zKvue4kN3YGSP?WBh(r< zZ`&4)KHZzsXU^<7a)e15en?dDMpc`MM-$B&j4#P!0@`r0dDn}J9ng?ZAVs|VWC_Oz zlev*7>H5cyj!>n09=_YOSu;^x`}+A^;wK4l3AsdppEymD1oCgW8#tgWhR&dEcpY&i zSk=SO)dM^ekP_#fEnXaXY{F!e#F#s1OmcDV4tAS(_bT}bmwQ8Z>;R(sJisW1BTz^v z_xKLMDw^O%nb4ebUg>|B#f`Szf zBNM|=h6XATnG{ZZ!R*$`qH`F^UG?KTfgv2^^VVPK3gaIlpWHB)J2R)&_G1 zh=eV~{K@n;enmzgabN}v7(nL4Sfm4FP5@j0J}MGjGsq8Y39!MM=O5|xu$$4RSsss76 z#WE0**&XA?jtx&tY&bDhB+MAoAY)dab8SV#l6>^ilkL&VPr#eyXwtkWX_}XkYydYDcrDn>gwv_CrpqbbG(^MdSbpL8zko7 z(KqrctYlWkW#pCwrsq4aGjpyt^UK8OILaVLG{9zqc^Am&L&PC5VDp&sAwezKbumkI zQd0&4-8hf}peJMKnC);fF(E;)UKC7q<$Vao=CT)Jgt(f3%gQo&lq*V3xzoo-tmi_4 zN8VBpUK0}&&fkXjWHvHcM`m!4c3)ZXZif6d859XUIh!5hC{}x+1XKhl4`5-3HIR`a z?BHdjEp-#`+>t4M%$&5k`b4Iq;2zqMYk{NgWY`!Yn$#6Z4rM$DdqX+t%oRC{NQ-f1 zMi9bxG(OTAp;COdERT*y!na0T{vX`BTl?0g~DRW z7QX3WtNVi@OBi4tY*+K>?Ky1+57wdr;fMvWCaMIPKQU<8OC?zzevo{GT7d#C3JFm` zO*m@T7O3(fQ3ynmL9#?;Y@_H^J(^%*(y?#fW{kX{=0*50pC6L}ccOiR{bHIDI~8ja zBr|p-KfWuK3NW!|0B?XFxaIkH)dIxZZ;MsqJOR35jTv>b{=JCrFysZ0toC!tCGnKs zZGzNPRU?>M3HCZ7h>TZsO|dmW5`7>SMxu_SwCKi>9;s?+!SYBPKwd9Wu)05rP5z-5 zE_B6U$p|53W~-X^gOExztlVMGW)#wL8f$570~Hvu>SK5twvPDZ#Ol}Q&WJK08-E(d zC8*|`(-btQAxT|ede`QZ?r@N&klZcTo|sy?QpRDC;HavpZP);aogK54F!(4QLmY<| z$zUvFc|s0K@$rTXX_mT(po+S(6DYL$qVU5`XN!QVBNiyMC|0v7Y?k4&jKOr|{n~Td zx%u}IyA?S)to&mJHxfB?=-pe*6O(Bl#*#3-aSP{nAQ!tHjOnOg`y4xa`(aZB9Qkcg z3^5h?i)CJdx750@{#xLaOg<6VAJ`@P_3JH3F)cM^6^1Vg{_sjv_^;fH6p)AN=@B^=h@AqJ0Nu~S?0m{$09h;M*%~C z7u9F2*@c^S2m|*Mw5NqqJ*1Q+yg@uxMi67Xe=aC-m@964~7izHwvO5ET^_EzT_#%yeF_gJ;j4 z9je~4WrDTWkXRmrzAj6&Oa);erqH5vv5M-Dzi!ZdW`QE|CzDkxbtRHxm>Y$$Rg@X9 zjFS%H*XjLojq9JWW(0%XBs}3=Mqs)KI86OIDN=ZB!^zX+99Us~xeQI8gAk4+WVkL0 zqZAJv0MH~00kK3y>?B8VhjhIUGCL*Cp zN%Kf~WLBA`^Y>4WBzUB*{SuHPdiG^K(S}6#lo%;UuCD0eV(8;#A}U1=?^e)afC7p! z?WDZd5y6{s&~Krs-@=xF3W6k4E2g&HpF1&rE_Eta#_`8LNWtX}sP{rNFDbdkX0g@i zdZpfSb!Fw5ERZ#i|9xTF6%m^^;R~_ac5y4-OzM^r&6esUeWW*&sz>6u!KxyySUali zC1c7cY)cVGPJ6FjO#rGyrFJf56hWA9CysnS5r}(A$|Re)?1>CJA>I>rluI<5_eCbf z;yH76BA^HpAnBdM^5yNR_Ipx~lvs4T;47q#BquWZRALLNi{=5GOo2ct3TY{8502-C zq~zu2!;hOtu6~)X(82(X=0-_e6X90(EmOU@+Jya)M5=cBTtdbaWUt~;sU1(oV_yQP zLHy8W4Er=4*)#}F1J+cOYI4??pzEf+(40Noqv5+2Ql3GQ1nH05L z&A?}68ai%9V)cNq&n;akWCp)LwN_p3HMPUZKhFO z@i99FcunbI4(A6#0^tTJ+X;TVe6kp2i?yH3fJI3U``ErXLTEi@Iu)+lcki|*V!&e) z-AYm2WXPwcL2?Pmlx2K3fl@409l}?tDMUXxUqlAGwA4w^I$Q%hF4@8xqKQrMVtUxB zzR*%~$tz^+I!>n8hdIadSu>&o7(s=_#j|-p3HSjgVi<`D)Xjjg&6gM`kE!3yJkglh zzJ&1%ZgWH=TM%%-K|&C6L5Y3d$b=8lAen|umfA^IcQz8Z&vpoaz?dcSZ+7h1zmqA9~Dys}GtTAxZWbyilL7ub-TXk*8lidliJ6a`zA=<56IiFbU znN$En9P$*w*YS1oyG)kupNetvP--Dl=+0dLZjnclBYNt;`}~@MTVrRlMhgoFbYTQ# zNg_uuHXPr&5!52(^zg0hBD=z(wsIUc&qAaaEG1O}`B97@9!g{&MPNb)Vw`(tOmr%m;n3#t zH2AKoBQ7ZW%jE?h7T`BfisDd`GE%%`7rgeoD2j$ zfr=--0>mK}ldD>}_FqJ^@>gWySD1iJcn2PW-fJofo-z+Tc+g*K6F{r}-Tz;N_s;&z zjAAG9mXMjej%c|GRpk8C0EZv|sL9ibUxdqK78AW$Ed(0N7dOg#yBJ&Rnn<+4Uggh{ z>C3%|yUX;3+>b^k%HNb>EMFFy^o!S{;;7ko@Ge~G;RGj!t(3ZV!3!8Yr) z++F~gflyC;5SQTcoZC&XeH1nO(BDkbAWsBt5{Vl=hy=Z|Ozq_XsGQV*heAQNFf&3J z2t+bkguu|>d__^1zhQJa9+5Tfi1VkQaw+IPY5iU3YH?U?Y5SEw-9;v#&Ak@@HYV5h#;5ms|?C= z)!-q)1=Sw1%C6l%U^&@#%<0CBjDeEEA4fFlNo&My=E>j=j4lWd0I%E;CSA(RN0LTX z4fe8zzFljs%1g#&;32IUD$%Laan@CEi)Y)?7R?2bVrupwP&)96g9wf@hM_=!OC+{i zv}hr24+If^BX50Oip)%FCDz%(bX#9fZKjjCX+9xeU~c#ch9KkKfOhJuXp>K96J?-> zO@f|{4!b4BSO&LC4M?AytQhwpV3D{pUhZD2!A?7Ic09JcpSPUvE4Y6`sp6WY}xR2T+!J$@8*{I9V?L}KLML_jhjmN;)T zY&#ZMX6pimXg#NPE=ZH0FJu&un{ZZABqIeZSn>8T9r}yGO(YAmLwN~B!U=F z`qRvmk!Icx3htKTGXTb@UnF$EPCxg|?ycdjyP{a!U04ijfDm9y7^X7FR z{u>>H5ru0pkzgd?=2u-_nc_0cJ&rF`5P=UI+JUbyEE?Q2g)B>Au|00-^87vWBj zyvR+K#M{+saBV#=~K_+S*&phte!7v z9CMBL35$vd;T|E4K+2a$mGB1dmsf{BBfXn9Y2t>zhA%D!FrGz_$A84B3hF6o2%82P zl_=S3G3Am0^^y$egWz2Se3TRqkX&pg5Ef?=@98jzt9lT?R;mM}_f#J^VE5&!aYDFe zb!TE|7Nq$%>u7Q;Ix1>I0?sCe`!5mamJ_Uaw9MItfc*pP@Ff1f&v+1OFCjApuBPlJ z1D5mhM&Z=0tgQY90DAN*Vkgyvy===~2TMV`g_ysjU+)!fr)kOP6!541SMgKCyplrj zjz#2xnJ~5C{tCCx>aTzo1BjSklbN0EmIONi=AXDzn>mDT@StiyWq%LfS^tQ>y&HZx z>(#5xNtSwoS3u=O2IR~nGjA#nIbwByU5CguhQcgYNAAb|y?aNJ(ZOzHGWu0kRf`eR z!QOz24zxeAkk=V!l?_v*1!I|&IpiJ5&gC}uJZQu)kyf5mUR+GrRs#bA0m*c1cK^$T zX~O_+pZva5Q>vwx{tc$QcX8IOW1*pgaU}NGZDvLF5CU2kA}-Vxh6r))&K)By;p>j5 zenQiJL`CvaLXTl;4X$#FP_pgq?F&fcZUdpgP4govlA#%J1BryB|N{N5r6&?Hg7JsmiXXOJ~VWyl%+g4 zlpW$lVJ`gzkGcDaL??n_8gVi+8zgHY)fjxszu+q%AN)A%l#mvHsk*(1kty)~0ZLU7 zPbK;pVf`ET%h8xLWhY qvhA-MQ-nYTH*N46wnzLZe^u7BY&$vG0_ZHWU_Gh=h zb$WBqhB4jq!^=M8e6asI$Zyoe?GL_`EPTrT8F*OXxI=b6dJ{AIvZY2n^_)+u2(8@R z-6;u1;H%-%xO;fqKR&FsQdDbKjLDAl)DlpZ&2E=i90odDPGi}{FH;sB}q3jLO! z)<0@2Rb#2K`6p!A*|oXxd`J4bSP(7=-#Nh9XY`ad@H@S&W0ktMrwEb&1RK2bxlKpL zy6N!KaXAr=jG-Vt2?)gBRD2G)CC$JRYff`%3C{HgbRR*e)O~-$DR@0xbw@Y| zK3h{?og#}b6(`^nX0e9ogFM6Bh{0Nfi^1mIjrdPN62QP+wvcEDKUr=D$P7i?P83Bt zcj^@0kwOFa+;=V)6$YoGB1+A4n+ds^ z#F|(5e2$=JVqRqKiW?x7e*U#;)zV-7x~Tz)22^U5{fQfIzgxj{i@T=)QpQGu1l0g0}7^rDc8uWzPfBmug^O$mcBq6JI^ zBmy`fSzR*rw^QfNZMt?Zp^w}v zE(%Go!Y8;fGhodaF8lzy%o+wVT7(3yR z`6NOm<{SYHfs{)<+-FU(!Y#*s)o0@#v!umXu&JQ$BnkI1i0{L`Sh#fOZQC(;MaW<) zZiK)H?x|GU2TGbA-f_{ROA|@g)nCISWldX?BT(}q@sRUPNw9~Z*xXXGa2W?7!;t(i z#Z)y85AdztZv>9xorCgtD_3{1l!&_mPNvV~3vt$V-#8h;Ah>HTj z5Mlzb?AZ&{7^R9zszJL)_x)R`RZTI29&JT$l*Gd%0#a@#u9A6sHbFTKA<|~EUpje! z4qK2=ah(GmC6a(_#_O^S_HO(V&*5REx8$+j3#Xh$x;H?C%0PmsX2F7+3~6=7wFT?F ztTYBQSqxYI^Nbl=67x=Q?Ul3#Yor2k3ICEzEf!Z4&3_hAI*ig&8mz5?^FBaSK{cd( z=gtZNk0y}Cvc;zfBW0QybqIlxCh>l2-iMYL8+C?1l;s}^4oUR zU6pY;%q)GI8d3#vg^F0 z(wK=&<~B>@hc=m8!EhJ~s_gg-1c~{-zbPn#4Nm!nJb@fBoR^n3LJHiMiTD0Tw;k* zfs&w@B;ocZK#&oDl`KN)W6VS=^hrog&SwU@lsL_eNb|J4JYka^dtD5bUk;Gv-r-y@CW zA>8zo?YS((97wh@*-wgNsocov zH&%2LIAJ&zm;kV3S$uLb$3R$2F1MvpL2gsjxl5OmkgcCFqYHmsxD5V#D=b8LM{+G` zRJb(}Z8w0xa&b zKgM7gMGA_Fv*}bYed#!`1v#%+`Mq!{Fj&}Vpkg7Q<4}6G@7OUF>`4+UjN|~)8Kx?o zf!Y#^W8zL)J*9sRgC;CF)6bN*WR??!9T_|-!@sDg>`8yufsmY<*Cco%95l|h)FIBK z-WK}U^Xq-3TM*<~+D3u01SO|qrlO)kN~$E9F56&G6AYar5*E=EjvJ_=jt{ILw%-ZG zyI>}w-xy232Td`b-%jVO#jz;omTecxsMsZ#`K(-rk1yT)1LKAPvS#`kQ{rp5o{#^n> zrM-=kwSbNCzXSjHX}Tp<@QZy<3^z#%6}QoZP&Pq_|85@9Va@$lt9Lbf{x$} zQBMy})+Vf76B?Fip)DgmE?N~v!A}ocBvf(4JpH)6da%z}oH6wIQ5ci0<~86E3fb)e zolW2iPK*uH=(j|Jh9xK>F@#f?@-j%^nBEQqL6m3kq1*p{Pmd%>kjxX{2XV;`iQR(q z7;c9zyvx^0e~JNj*H9n`?#BV_fS7FDW2sV$Uhc3)Fg81+_d@t|q*O1-@Nx)3yC{3s zCP2aO2EY3~ok6h=HXBwHd6}QZdo5u`WCAe+^Sh$ne9GoLgJqNW$LwXaI;Qps4Fj#v za4JagB^@oqv(Nr*M(1wb+Cw)Wwz%|DbwIJDFGwlx4{0g(BMm|{jcP#kOavoL=5V2q zmVfRoEpzRA_1ew5lvu;t5&T|)OL%f#kKPFRmR1bO#yj`#zaOjvhm3_`x9lIyTqzT= zcwuZL#HQ|Zsq|dg7oi1+(#E8w9v!&kAKJf&S)#ze@nP zRSJq-x-|Uvcj!s-PI+wtz(r4N%~mQKjTuNhR|jEN8H^_{mt`l-3UC?evSA@*euUj^W0d$>34!*IZb~u*hH-Aq3V%Pmp7rgE*w_rp#kzwCgmO4^m8&q6Psc zI2w?a9WWh-LVBY38fjJ|YSc^>qfC7{Bn69G_WgrvGHoeaUrD_mph61z1k0k?D<^@Y zOms6^U^by*dkNo!zHdEv{`YRIv>mwey-ch2Q!yxA*9_gTpmb^V{fC#dI~^!tLEEXP zI31u>a`q`r>=q7<@Cj~Jtm+=~=2P($#s%Bc$SbqNO(1fr6RSyRq)1;4(HQY!W5^C> zlpGW}3!QQ1cz$FN1ifNcva&pNi2hpWU{Ig|aE6ufp0H4B`am2lBwZDTt=HXoIlxQi ztKa=*p1^yzfOKad%r>E>;KeAk-@mzbwX{{Q{qlSazz{9(gK(?n1YnfSSEbO?vql&L zMqIkBLKgF|5|Y*$0;_em$zfJ8eoa0VORY_-N!HI?cQTU$(xyV>31SX1OFOWTmJB3~ z{TT*SGO^o^sI2hZ44d1Va~ogv^Acz`oU9U&}n6T&&0mTqP)dqFD=%VRJ14L>a^DUyl*>g~!5ud9ZvC zqaxTtfmngXqnm=-V2*)sOy_CT!wWPN35}k7G;CQOMp<|pWb>nMxqL4rZ5}a~b0UZ= z&EQoSia)i|dfv`q7DlWU)Yev8V}{Q)KBJ~1PmRBu3u8ctHbgWj{0I)PN5Ik1 zHbGOSlPa^x^9lQewTuC>>ZP#KoQ=`l1E{kQK5Q z97Zk|<%B|Mm*mF!%SN+8<)(y^?Md5w;8pjtc^3Z{?1b=?iLevRzLzDt`e7Om2+;vr zB}1s^%eY&}5`I^zfu1KpwmJqB47k|#odq;`;qq3y%q*W7!f>2N7uFk3`R)1#G-;WR4y>Fj~33P1D{x;DM zU`$9US64UElv@f}RKyXy2^x!FV%!&k3FSvDi`2pWh*WvC?IwIF_1&mE2P=mg&n3^8 zLZV%S#zod1*vCMipnv}cDS1;Ql)^mqP6KH^Aw`~o_mu`b37R?f2c8DmCL_=hOR-8o z1oc#`fkgH^pMdLU2t(iyXG?KJAOt9OZs%BED*jnlA&Qd#oV!3<82|ttvFA|;o#5Nc zI{yXj@{X-ae9bST%M#BU3sJ}q+*@Q?%m#l<8G(`MDU{pp>XHcIw7J|$QJFvg1IS=1 zbcPlX*MXg-dlvs!XuVCd{|?Y)}q<&lI@Be78m98BKAJOLz2 zIt9dHk`&MkyNQr?_99jouom5*{BviH%`Pj>qt0DoEd^KT3GA0NfpGR<$Vv@K_su^- zPiJtO_aV^|agUoY!TMRSJymMKAAvY60`@~XXp%bQ%d;rl0(kiu>as9GNdrVf#JiQD z3*g|(%pxaz8W)(*aoah#^Fjn5;*`DTHKl=rf+2znEIyTrm-0#TG0Sofz~;EP;&CVi z`~_+nHj^;hhj7yZ4u-ou7WHgByB9(ml91 zz8xhMRWha?Gf6l3*R1PrE=A3!7(?n(406_X|H~pLSm<|-4LM9PMzvL|?d7(Q0fB&l ze9}lT2dw@q-drGw#Cu@L0u=cXe_|;Q_FLMrX3d)B$|#PA;EKqmap&0=o8YW^1gLK2 zGq4b99gM&M?sEXgopGGH;Lm}3yJQRabj=F0~B`JoOAaUR0N zp)^yWNg7oZ$x4YqgJvAb;j7x%IN-bduU5z3d&wKAa2Bo#1E%LaN0JTnlnYIugw+N5 z5(Yiyh&<{xohyj|a)~${`w(+FRHSqQDM(mdm?=atcEA^71bihv zH{pvosjKY<9+eRwbQ=&9_k=O16@|je1}%-eM(84- zCKZv#H0w~LfrkRNoX{=kStP|t5&AM9q%bCr{D{96nIxWQGh453YEqt;LC+nt?q zPbR_Z+@nXn^dk<(9iG8qn*NS#hqR<&$a|s&^B2&;h>+Y8cr3K+&?HLlEZCGpumEX7$m;*XskYGP-hAqX!4~oZkpciX9dIyO#QkyHPhFuG;wopJ z&y}SHE$Ps+r)rd5)iRT4%U_~)BoznF;9=_QmbzWKNYjq+Z{Rm!P=`WZggbEJ3JWR$ z98isl&GlCuq#v@H?#mioMreamC}cQr6Pf{xsQXAu6yS`m?g`GsHmw1>{e$z5trkj? zWD?Tz43rv^=a5CIk;A}Y%g0j1X4w@A;_ON1D??b*d8~NO5T_xfE7Ac2!rRrBU9o#5D5{<4oS@i!l}oX z3A@VlcMKvaC4&w+>UE?R`7$QxNQZ|AROr4T>mu~`iW>nH!H+l@ z(n~Z6pwNP0d=KUgd5>`N#**@q)00>71xK?~0OSknEc1qCRhJa`yCWjQqa2`s6`Ca?=jmC;gWrh+i zF~zY2DI;{nKN@$QEr6xINZVmY`!(I8$;}&ZKUR%V|R+;#OeJIrIx3fZ;4f zR0@O=TTn=&E4sAAr&3ByER2xeg~tV7x!2!`g1u3d96 zN%MfVFz7mj>=-?~pXht|i@lRadEuPjN?HUJ6taek=Ob-cgINdLt3zm<2q9dEN7zVi zV=E)!U4awAyP5>VCCoNR1`BvIKXOEF{wRtEL{Xw;ctEsOh&F?tJ&|x}SC@ppLk6%B zlr&N)AFh#KpG(F}xx^BtTx>oUt?C1j`jaY?0l61I-OoHzcSjzV?%M4p zDEUzkZ|NtcA(&!50;>3s1rWiEH6wumcTy3qoX~iPcH1GF=)Y<6<~HCWd(sxQrymKg zE~;jK3%iuIk>(e+=L9EIl<7*PaZdV_CH2H4ZxGs2QwVEpD7C;5g|de%=K(1fix;GH zAwURVs^1kDIEao6pb{~gDqv8IJTbli^N9q2BQx{!<5^JbBAM8y%B~%uor_Nd%LuzveuCoB(gz5*#8erYi4si%B3_ykSOBn!O zg`)8&n4P9(qVT!o5TjPJ>)0`2TT$MShKN$hn0tZ+Lq48;c^dc&!a(lSax+t_SF-2y zi@!hs5dARv8>GW2l=68gj@cfVZ3>x_*-Y2(pP*&uNScW?^AO_!-Y-1^Yj8Pd6}fpp znv$-gXeS*hO%fgaSo3o%T;I&VE zZKoQkM2ym>L&fM6a098@?lV3vhZ2ugLrk-Yp~yyz2r-Dxr2xTw*YH@M{_dqG<+f~V zje1yxd9*2;i=G@U(Qzmu987(cJ6ze5!IbY-km7fU(kpZtTyDy4`6!Yb4krg7us8Y> z7jaRH(ktM~Qbfr7nMmqfSAnwmZFn$+ka4Nr7~zlG2^tP_H{aIvnTwtZr+V*b^e4PE^02ZK zT?QdbFj=$*QEkIe^H&4=`w z_YGJ;50_0k-T_#VD!W-Ta#DpZKi1gtK%gMVDHW$rx6Fe zRj?1@JyVWbQ<}Wzf|f7zPXPl#pCxOP zULPN96ttDC#CNhfRJ}bV))#U+S&}p00L65vKXh6D-W>kSei%w~!jfTpY8ht&50 zL+ri!^Af&OWJIV*vQuE)QKtnhnV+NucViqGy@Zy~RUl>L#M8}BM+ZC0yNbe@;V*by ziNz>OMClO?3f&*{b#_qtxeI>*O^77tv(g7h#c*zoFxr{3g<=R?E`TV#f8{%|!FI*D z<0z(bzlor#dQx}cjM;E08enIB3|DmN&Uuh_L&^dagFt{OeA@f|EzRic77D=#7ewJ= zfc$>+K}ke*(*&3F?`V#n|MeB`5&(*E-6z3>QMsw5<614!NV0_vT69j49j$+2VkBa~ zKLB=QJA@SAuYiMMuOX5-FZtMAAi|y$L@x86YrurSya_gm>xB)4-;vCZYl$8MbWpRN_Gli9>5N6=hPpJjMdZLq@{RLRIQ6qCbB}O+t z_g}Dk{ub-`JHAjAZ=`M8%8%z~ec!?w&(`hH16y8#I9&?tIhRf3mqagezlBakvEU5n zebd;qYS2ry>nRq7y@4wyGNJ&nqI2Ox+L3a8Y7c4} zp7Ckbn9ip7_V``dL&7^Xx@URlstAx|D-eRy&19r`K(>Xbb^y?SJct`fZmvK*k`Vfd zQWB?LQ23FTMpv;;IVRZ@D_)8OIq60&NjM-Y=v6dDsmLg`1vYyWJG zdKn$zB#^=MCYKk^1SY+4$c(BGT9w5oruC50?AAZbJx|qhX|;ePcNFZ#+z5=zkGkk# zVql$AVp)OziNLG0Ex*5C3Fxh+skt>i?M@X!ziDhU$;^PMuToDof-^4vsdEKA4uR*S z>l!W(h}vv1fBy;3)+?b?>!-yk&*(tT7yAI*}9-$!N^PVs`wQn zM^?na!IAJA)(Muj2~m4|T2l36#8*z^pp-@FRIJ-nUim+D-2dD6;(z`Jt8bdY{0ila z(ApgFHKDfyMix)RV*eYi8}pn-tJ@s#8_ z)40&82mf%n3Qujj-)HgH;hvw$HG|a5>u0@b6gb}?*rdd8a@P9YIg`%!JMv9YwXCT6 za>jd~9NqdsSl!nzYGv8)e57h#xBQD)_>G_uNB7xfTf1CyX>VDyLFN61lbWg_Evv8M zuEg}O^(IY@bgpRRYt{5wan}b+YOU<*`K4W%kDZTO$J0L z+c_mgT)rE)xaG)~>vIN{T2Iyg{b0%UHA)e;JdP?9##}uzzoGj+g_J(^v>pvB8(`PU zE%IVu|5j~dhnI|7lmB9+{)e|N@nP#f^x5Y2a!>10<-mt^@-6fOn|$t8&vrn@tKyz@ zDqH@pQoqu}?s?-*L+brHuubuV`PEN-X>dowyg_{r553(#Q@z&YUwv29aZ2RO38gQFC`ksEdpX_dUr`E0y!%|uunfkTcw8g{2 z9!~nu@9{0A@i#Y~2%B_cKt|`M4KIyYlOL;)vdX}6=#$Q!hSdBtV?@})lu`pe)+w<} zeX06})AjO?>Tih83$L~g=FYEQB&^(WD=Rd8*1D&vYztRFf2Bs(io)|}vi#1axbzKe zQLou)yPP@;nl{R7UpTI-mPJF;p<%zd;1g zYQ(M1-<$7B++G#WtA>PLJg?BK{gIVR4TBeVa~hJ_VB;0FBP(AnE8MriYGdW<+Qw_5 zZ(XU;Y|WVhoyJaTeYUT+K3t|g(fVw!FP$F`slOt*rV{t!*}i%cR}J5K+s;uf-?@u^ za$sQ(;}7ojz6{Ok_jrJ}>-?I!jYFDDt1i=ZiJST+Gk%rc61zADy(Mxe*Zj7ljjqic={>DHD{1QS$twdN z*X$9jJoJe|(s{d*qszwV2Us=DPYd-Z`CO?Ts=eSrBb&-04?_2qln>ARy-(>U-I14? z{@A62;zvDG^qRc>&7-+VxO%ePi!&$N1h&WC47{oELNUCdhj&Ta*vK>O^grkvOwm(3 z^wIs-pELJ04R5G1X~pgjPF;dey~%0gSi@a;onrsJN8MX44}Y!l!l86bhl~NcYxkeH z@uiyY6T84Px9vd@2agu=T`PL_(X4rQ^w5o(UHj?>glZW0D9r!T&LQN7$(*`xw{7Ot z+bK3J%3m+kzoNb6^SWHpjcB)#x#`_75lRJ-znv^fM`In$$5*c5ZIi;FVI)t#IeK7qz|A zRLh*jOYTavxVl)gUEAWTi(1zH^t8D0a{Z2llOKBC^t|<<@@R_&>vsm$85?=?r<$gX zl|~H)hnjYI!Ef)DdOwXhePYbT-)+p&XRLe^;+Ajv?p3p;Z&oP&a&bbVwz`VLn)W$R zWBAZs!#u*>-Ph~&{_ySAO27VPjr$E-T0iT{;N0zQs^~tr<nYa=Ed*rmi$`(`z@8{J2onZMHE@351dxn%k;TI`eM~Te{9GTeU*MmBSu#ARU)pE zKfCSgRegf0>TUfE)Pm*DoFl`?W#mtVIK)!PmY81M96is(jRQS+HW&)80Q( zVplL&iy-RJKd!_7?6OuGmE2M=Tj`MEbW>+Zr~HNoD<_`4jL+cb( zerB&Pcq-ANhov!kV_1mta%%5*o**rQZe8X1IIVsii7W_up84Pt1(-O}}jSpw-SnZohmg z@%?J?xU_@QT|Pg`#v}6fwaJzJOkXG-ZoW=oc)&QlZ0)C=44Z#Fs@m>4IH*j=w>zx^&etd0@8DagjzphoOSH7tqC$j%d=y~mHkY&=XU7ufd2`v3t?_K7zdGSNG3{lKmpI(#0 zQ9J9!*Gdkq!*Tx)9-oICuQY9t7wK0wCA8*s9TUwr$2>07Dsa(Sc({w@_pOt@wACup z>=aV3R;%OAwL@1aIksvTH@HsBRJU8TbzK^S8GC*n67CiCOkt8^zipu^9_BS|>QDRF zuG4`!)9apEdZ4zgk(*1#hI^F?wR?E9(zLp5(nfpZiwyT2wZrea<=xsCVd%Sk>0+x_ z%k^INv`fEyc)7`l=NYYkson0q$Ne|H%Q~~cE?UJVt?&NBS6DucNT_d_(*7C;Yl4fS z^*m0j#gKZ}cWkuQcFXP(kx{dmp}WPI5#O}m-b-i^m}RD6udY?3$=+RX*6O!+gpY0N zqUWiFug<4j(;EG((dkDc@_#-X+N@kZ*C$-N%>KZjnp=`Qc72K1*(Lm4jjb+q>h5WM ze%-aNWqM!c6s%R&8q&(cT-lb8R1jX z`axa)4;xi%-Lith<1>c)EVD|jHLbXJ!Izm09Dlm_a&r8TCdE7aw!ix=@N@E{uf1oO zWi-;X*s$WcW$s!%rQ~g&SfRGM+4=SDA4RGL z4fAY^S^GRyZhq~&59`cSqU^6O>|4-FcH;X0{hFW8T~;*yR%4*fu=5FreG9v4*sEOh zFjp|HvCpDm$Ix0G>g@54sI#zdX|KoEYCJSha6UQq*K#%e>_?N<^u0LVRXM^qu(a2V zPX_Ay%A58}+VH+(%A&jtDIZohzGD@TeK_;uc)P1(-{{vU|EcTu7E0ghF8u4~9Zz;H ztVj!d)v93NzF%|<>#R-MFiAUfbb86Do3^t{ghKfJ#aZrCAD?Wqe?*blwM7}V zZ+_M&U)uPmpy9{cUHtt~WaozAciUdfsZqEm@Z)^Fx9V?qDMXxFq&I9vqnk?Hhu=(w zzvy(o`Aj9&DEs_EGly6lRjq@eh$ivI-GeRqa?(!ll#5OQRk1m@qJ}oTDmgjdmZKY-c_*2Psv6>XY7NXqV=w|97cy9Mpa2YL-7 zis$2&_YeIN{xD6iaQ2GS%KF!=+^|N|%35CxeHZvuMX%K1^SR26ne*9H10>;Cb%eoy}cp7Vq!~o&0uQ zp~-QCEP})amgn&H%A0Q0etA@J?M*HP2H)Yh7<{d>%~GvW=3dJSKR&@K#<5_n_P4!e z(Kf8;;vC-*syB*O4qaAf;0pKa`B^6iS-sJn@$PYrjq`Us46QlbxpDlw{x+*u^e$-P zWYu~}z=jL8rj_VBcH3Y);_;c!Wp6t?KG?^0P@OB|&ac)sxUTm5r4wm88clL)ezD$6 z#U70|lzwmgS~2U%&gbgIJ33r+9unG5dtlScny&Txj5%&SX2qVzwRFr?-pq2#T`{BV zuBFww>kQiSa;fLgeydHt3|`~dammb4=UZtWFYJ1s)tRJS=gO1wFHPF)t-pTB zXaBM(1u2JzBi{-9J!8Fn^3deXnZc*bG8%re-SzNh z{pgcBw+(B3xL@eJ6{$DXsY98mL=?`7OlW}zGdLVIf6gc$+ndGpPGK)_&-V8?~DJnz?sW$|cQ<6=&MrSf+0| zu}kK=58=V{kLQoHGry1R`5H7f@pavzPCr?*30_xL4I8X@TZ8vMdBGyEV$|ma=>r=q zuiJ6xp>*vg+u!;Ph&(o6O=ky>$O6xZp5o=TC1_HPPI#4KtE;uVu;h*j*4E;DHzVmvEGpVC<#$0>dr_MlScQX}y>9xrv^*=9&?{mPl zyQ5}(7p+ysxf4{^syK{4{^-@Ud!?#3T9m6feaP_5KbJDCZdmeZvwKaa71eOm9HZH9 z+#xkfuYTR!Rlf|sVRP;2WEG2TJx2YfuhDOSZ~fFxFL(UY1v3j+kR+F*>Iylg)0N69`ziS zZ&el3$Swb#7OK5yeng6z4c7t(iwZM7~^U zHKtC#n+hey8@yb{%y`jh!3B@)wuLIq4V-H|9Biz4Qrlg{wWiMVdY4;ny13r|h9x&A z#q+u2AZ0$+`Ap=_E;T%RjQY1TrJB6l=c zvPSLY(RwMThR7vFF#GPZ!_yq=;V}XjWjbdb-J!8u5-cpNWUG<8U~>) z_I+3U{gTJhH>qKW=CiH^15|fh*X);c(#&g*Rr&cz&J9hUH!`lV z%Gg~kG3(QmCnvQ#4vT71(BHeq#4{0kpOXVi9me)qcew75jznuwvCh}BG&CF)#35aG z?>BsA=3d3Kp>im%E?AH~`|<^}9Jvw*7J>LeaCQ^l(<5~y5^<-992mAQ3HXENl z3H*rMmWtN5pXM~%*{@LIhmjR&RW^Rdz>n*T0^~~^0`>S}`SX{wj(`21%o6|a$NisY z*#CF!{{OXh>r1D^RNtCSW9R)F8uEYl>ObvO_jOv=j=UXiRN47dY2T}tFY66j=4sL{ zW_0tcF`|ese`d|Bsods$yr!MQgeM2Lr$xpph8}vdrrCgy5j{6{v~IUG@Uq_0Y4wAg zbdN1>edPxnRrb1<*6{MG4>Vq(+VAJ}+f9dFP+pn4J$UZQLNjY?tMX>OpJ>`XaV%fZ ztomDu)6_E?&pv6^xS_T6Z%&DRsgXA4+UmU@Rz9~kU(nguqO)EGtXradzo_-ZY=wx#KwS)&^o{yc0(r}}$-b(`47>ZIAJjShMt?N62NQalp+ z^UwUuwMohyg6bSz5IOq%WAEENqB?M z!;)(RobqRYejR)8wthUVmGO!;{eGD+`+Z&gCmVnK zgi3Nm(_`Co&b1!!WzDmS`8hj6wGC%%zuhIqtLsl?59jhO4UUy+$YM6H*VQMc>CtVk zT>Jgh(%xZ0q3)%)^9MH$Djt30S(7Cr`c`zApEXB4dq=2h$Dlg4F-D;*vCq_kZBrwb zjwuhx0SVmmYS6*(NAKH&6m%$0qgn?N6;#8s=9$7dWBai0{A$gPH#U_v>^Lk`HK_6l zdzQ)HhPe*v;Hu=ZbU?ouby>Bn+dCIT@_eJu7w(%F*UG-#?U4LEO$HbB49)Y(>ULP! zSIbSUa!b0a;)~*gKUoaeni90nI%j*dk8X#U+ufsEIS+YprG-=C{NbHEQy$HVdgt1Y zb$q7Ue`sLuB6VXor*<|)rq5JQzdbx6`@?*B4kulkC#_0%ZIsW-e3YLZaB$R??Z0F_ z+Gkzk!}s)EQ4=zQ>-XHKwyE-6)5l*G1~oJ;Z)p6&E<0JPrppo6b3^;BKWQ7;bYcy) zXq8)|i=Q8EbJ;u0-qR?im2>UYvklkoi4N7dr+Z^l%A@?9OS*ua5k1-uvqNy{~S4_5OKPx64v!yZ2tb)|_LGG3MI4pKOVk zqiNDVk+IsYuW~J1C6L&naY=@V2l=Rdvgpl{~0Iz!^UZw~qALo3m)nMZ4i2D+QA5;gVQ;<;R?*w@JzGR)3H-NAgIiT%&^=YBZ8ukbO+D zejd^&e|UZ@+n^?$tS zFt?aJE3p1E7kMi)$W!`^vDzv1xOU8;Vyh+D<1Vj#?tInxMTTBjK?@{Le}kMsTX2Dw zF`L%0F!i@{o9D4Tflm#XAWm~TvevUFQyTD0FoAtfMcak@dRA~bgF@YAX8>{PXuml; z|Ac+t^Sf}mK@w!3+B_v-K%89!%8e6{fnS9IfC}bfI&;F*w<#yXDK50Qa6C?WM>?G> zQR02|fV<`^SV{XY?LS4^; z?iBZy7m(ak4q??;xa#4@dz^pEH{R~VT9ZS=E1?_e{LRM>fFMsQv0`im3Mjt#V>}SC|B=}(7Lek?VcdNiuQa?34FQTP6XlU7G3NyHhOscGkv5t?+zJkB$8+>V zWW&z=mKVDbf|7&2zGm`0Fnx7DQ>PASrjvSc*18vMt}*Fn&9ozq&RkEH$~T!$Nv{6j z+Spmuz7{A^Hyr;h7(e((Y=*$#VVedq#Fu*_UWnJbEA6yP8tX;1`{K+uOz2>p2XryF zIaIF21L#?JN!=WzVD=Wf6d(!d1b`2~DHY&MA=SU1qt}vgl<7f!8W8ifs>MwjL(Yx+ z>f;pY9%8c73D(NIWi#wopvE$L8@eFgN8F|1yUQCe;Mc;DHt#R+z;?sg{KqBMO=SDD z+FS8PWBX{tu7+5HGp(ga5WZ7vriC5lB^NSZ6+&aBP}H8QDf}0Y{@WlKw+&Yxssg%5 zkCsQ_9W?$zK9kY8BuleZcv0C&VJoy{deGs8gijx(-=-`+LomOWMK9ls8-2^&?5a-1 z+ptH9V-x#^V60K7z?0wn>Ti>aoDov^CWoovA!OzF)CN0H78xrLxLLz>sWKI9$lC(s z>ye7cAjVP$t;ov_nUgzG$8i)vf|Kzfir;eL)e7^*C((g&2Esjju4(aePdirBIscEWR$A(w4$+QB8 zwgo?2_wEpqrrKD_HkrSV(7hT)zu(d(`x4j->p7id46Nn1^w3>S(gn9!#(kaXcvLrH zU-JFz&&>HSAHjeD+JJA_c~=OO`Grgh}||X`8({Yv1^bolL`#L84MOJ=K3C@Zvh}-kwwaP45{^1A)Ee ztFozYEgi6s1l3weh#h!=&tY+jwQ@4MWEDGag-ACr2C3W=XI~RZkafo`-;DtWSH>=0 z-{i8)d1L9@j$`j7d?x9yWO`pTVDyH%dTk!zlh$(bS0u$FM7y^h>tC4fwyL>!2O}8yG-ozYuzM); z=L|SnYLtO}`v4^v25)D6vWd@Z+)9u3-szHXehG|zC4jjt-u3%<$~F#ar>ZwMU;qR% zqx4#{-eIUm9jlY$&N~`rwG|r-i}>+I-iV!LlI9lcq-bRa{}zAC%FJko?Y`P{NJGZ_ z7N0RLM%Uq>C=sE`Rkh+cNwO3*!3aOtbpM{H8*+Njx1FSyxd10tiW5^1uGWcU(T(Q6 zJTGq<_l;VrbXd%zlh$M5_spwIEGO~y_&39ISGC{gpqKr`>U}x-W5>v{!+q2+c`c45 zdvog8M1(Elbb$Fyss5f%V&wuNXZD%_R65IpbM42!E3tl^A=M>$s-=Hx2)%ZAuSGm? zelgqOz@i6n$OnhYm{(_F)|z9Pe9E;TOCYPjt0kg}qdor=?uN5TB?eYT@;~0AqN*m= zqDVR)YG32&2&sYywv`yo4a$~X?_1VTXB45l`^>+_T<6Y0#98}lt8kXaPF*Jfj@kLO zuKM0rwWG3G`Nw+YL84IiM2WeKw5nd0fFcF(;^^!MbvYeqoPaI7)h0G2b{#mPY%>`V zSco61L9R3HbeFA4;cQ|W+ra^!$LR+tpECaA4c(Omml)BB!_dl+Y+wh#1@6p=bOFvv zh33Qe=`Z5ko?-+8M3226DzG@BP7P;ocBK$&Sb(Tg-U|u(IdvY0Tg~I_d03H~u3V0_$+w^TX>>i$ zeU>=#l$mfeVftEU`cFyUv_@L1ASGmD!L`pDkKAMr=lxg6)|%(4kd*nW?sH*y_8%

*X|Hin@X*P3dT%M9cdR%r;cNVt-}Fcus@LW@0kG}=d2o@fZFlKlz#fx zdasYY?}=MVcVbJyUT(?g0}A=O^c^XBnI6N54`RREpwOW}Fe3$zC0ZBl?i} z?BiVaz(od7G!D1C)?@eP{BBpqud#qE`F`od#LDeX#ax}T44_@(`+!|X^ zo~z@k@hW`Bx&uQVO6O%BldncQW4Howfkb+a*f(x@GaOwk=CgQJO*@UO_p2F)w-6`@ zCu@rUl06!e9urf!M$XOUQ1fA5wfmh4zgSl89tew2Iw~36CVDcUf3PIZ)}=TXpVzqO zSFucwAAE@8qT=(RpG}{?YSCL2QaI&t$o}P?aQ6?)`yqT9!Q5$8V{*D|ZjqszzLmXU z%Zc@FnbRs4bYVoOB-(|$&X-qX1z~P$10gG#H$>^ip9hJ;kDgt;>+lPtCHxY?PGkrr zv4S`HrhykosZ1xN#E!E8HwUTuY+l1qC)v}6OjCuptUoaH6DuaZew0pZw!#9g2y?<+ z+?`|nq|vq81zw^xw%O4Q(U4jP2DLnyidS0RQMHo;jS=ZCzn?wax$H*{O6N+8t1>1} z)8nMY?gy9%;4eWk0-f3`C!-dQRTCSkVy@?&Y0!?$_{EvMUbTDO7(({}y#C106<71p z0APx$ST#}Bn|zuxUlmT)yl-%OIzcM`#8p%@Jnw6UG)bD;lcVYgp77N#9M2oQuOQX` zl>m3!D50pm?fCe!{^oh}4^nDZ(;ONq#k;q(*(R#_Ak%{eODHs|<&h<%Tnf=`(G5FQ z)uI=O1>XNu7ZAK_PqjdT&H}4t58V6O*jeh>l-iEaO^bd6S)+iTQ6xjfx?fKvtQWh_ z`STh%Y*m@8U(-3CKW1+8gpBH)mz{aivd&4U1Gt3}HSHcJQ4R;~9qEVhDW`?@mmim? z?Yoj&hVoejvEDp#`c;w1(^bIlfIoN>iukDZ#5CuP0iuHL=|~8bSk18WQ;k#%WXV^f z3qR7L4(QtAi-#hg>3#EE8+q#fS>y+D6R%$O0_xP{UGxzYid_x2kw9vTf>_j?XTdp@ z((mjx;FSRJ!}D6tRRkxIIjUOEZ^=t2cu``=`;Al=yeqrt)pFW1;D7gJ zN_%V6rp|wO7c7=DX*7FhmsRVlJAT`H790bAUZ^p8^KUkV+bEpgPbi4hLDVNQDv~B&R9dIHS@=(duIfZI;4ho>wELoi z`TSp5`W?lh|&9NvB^5P1WG)e{J}J(yYA@^psM9BemoR< zn?ja>pG8KkH9H5VMt{2qcF|sWQO7EV3T&C&4jRnC?)sQk^71Z&4GB3VXF-r;TL}_%V2cgSU<);y_8IO;S z-d$${h;}}>ND}I?C7MZx1j8kuFLD|7fUYUfU<=?2I{W`nznDni<+PG2r?Jkwy=AhU^@qG`D z7kyq*mhFWkhMa|pJO*M|UR_5Oc0BDlFH>{*@6(CH>41r8E*>&t4U-Vcyu5T-PGCc1 z*@7$4UL`Bpy_kmP4^WqadH!`~mLJsvrt6{{mz0yi+I(6y9O=O5$!-y0$OfKU9Z@dW z22gn}<`BmUX5-(fLY%N>qC0CsAq&3fM}2j*w=aHqpCDxGa8SOu0=pQP-vet{0dWR~ zDA5!IJ&`0an?0om9&03UMb7uaU}ZAD`)5m{i#2$}Dt3&ql3DZq^3h-XCOc@b?_sz= zGnaMZIFIwkvB_EXCUjNv8bBa-y7*O6IB#}u2c3OwLc_OP3^iIfH`-Q>q{{7IwzH-( zpMHyvx-4*7_o)F)-e~Is_N;JvccL$w6n5dvhYldLfqk%Zs#+ODm1M)iIzv&FYsuj2 zF6KCj(z!pf{pa$7zDiQQ3-c+MxZi<^6ii+Lb7y0~1m+D4-vap4bcOm``uwNt%^NMQ zql){k%-EPL`vhR)5R15L@4Lzi^pdjd4a*%EBiRIRS;7&1t(T!;fU8>9-W|6O9pJx7 zHm9?D_pcEr(i}~0gK6^9Nlv+z5%l#mDEai;BC@&B#OTgYt$u9C2GtOz5f+u`3riCv zaGdnNj>$30yfBu%klGl@9*8+}1&;%Fo0hk{vtO=Vwk@I#-t4J<*xAz$D}+mGhg z;t1S3a|JZ~`ZS6k^)%@k+CuDa;QRZCJMnYOM8h4&_c2Pn1mmMF1wrqQ=DX7J#cwBm zg5UuT8Q==DcNaoAd5TD2IO?b^LODT%!qiKk=;4RS`Imgvml(l-B~J}u2L1VuFMbBh z$Z;Qa_9AmSps4J&){IAGBOM6!tRu%?ar>?aKHDjdJg4Mrhj z43HHs!fR8yZ|MagIwFYQeDKeizn^=C*9zcJ`=)|F=!TYr`gPFOv6mR9Gn+AwZ1H5@ zN7%sbRkwQ^J={xwz-SR)1S6lRV+SY)LAk#|`=C{DG(_Zj@tIY}2G4dTRFd`f409T| zksEPrT3#CKT$W_sR7B9&Cs!lCKj$|I!H$jb{Das5*n9Ie{dSatq{k~p-U_F1$YN|F z7=kx^`DG#Kx+XV$jVB}e<(;i9PQ}Z2(0mozh;`j=@0SzlUdC`W-;>Q_-)o4+S!+iE zFYucMhr#jSqJ%oZ&tpNF`l}Od51@Ew^0ket3!H=#wM`4MZ|NczpFPIiam)I~U62~) zOBJ3r@-kdlXZNsrn+=-5gdOJNKP7RiH_KwDnzCI!iO#M;)7el5bt3**km&l2=i^y> zuRdT?1aFw&UpfVF6rVl$kLAcqY@=YVgJ8YQ0XEYDly?^{XbU(wJN}Xd^XKjlxIxj^ zt7Zea$+G`!GID9|6Q1H#JkORVNLpcpy%)+m-Oi5-1hV@&CI0NNNW9Rh^W)!5z`>oY zC}!q6v}LVAW<~2iqaiHl5~(r5Ji;LNU;P++_4_XXaEiMZb28?^)o95Wb^@jap?;m4 zmu~Y0#1^t7sx?V9Gjvrll#}Rb(1EFZ#QF{mQF6XKy)$89enam&MvNrRKev+n(G<|ORqM=90%O7_ zKNCMb(81ZQbbPx)$UzUhkGdvZ;i2$4frsRCCv*Uob!fvEoPaOSx_pHUYjGtcA`WR~ z^>4LYn6GdrT0&dgW=W{yd*GCitjpFZP)Gt2$BovgLY7_APO(0szFthUSm(TLqLwvS zLEb`iiu%0w%zb8M;(J&SDQJIwW6&&P>b{Jd6D5+j?C>_2+NO&C+vAMM_w@58P26H7 z*O>JVdc4@&aPF?Qd!z?(j62$FQH9kLD>$7!S>%+R5B*bRMEom(+^F^HFtX`)y5NYA z6T1yTQG1(`A3E3zVl+cfTJ%msdf9HDxw$Rs5O#&McQOuv;+70Nv`9g>BSTq4bZ3pY1-;H5#QkQX$D~ zuUODoZ<8)#5p!dMFJfhREw3Y$4ZG{U{V8K|YdQv@n!{P|p@mMTQ?#cX&9AEJkVQV& zYNZmgHKwyw5jcEHgUR&!lCWx$gF2_N>DKr8Lq|5>d9@u9Kf8Mr{R0Te-t3fKq!(#@ zNrB3|#>cPn=|e3%wfE{Wq$Id~#r4L65|Z2puUgN#5ooQoIowem%W9KN>Lb5hOtsxq zssCx(C~i4oqlUloaaT~}a4T_E#rd%CfaMwopR#$mzKo5 z?V04vHhN;oqlcn9ib|BjlduK0`?U2-r#|K{V?M6Oh{{P8`OzRf#n~S+3j}M=^{twe zBFvI~x*mx=LWv#zrB=;PZER=ZkFiWds2B5%x-z#pijSj^G_|XWQ%n*XD;BlkhqPy2 zi5=!Vr%7v~YnWwfgT) zlB%9;E@2>%@la}AW+{tJAXv05_~iJQJh`)i_Idq};LDhVxVqo+SPnA3EM@!p#R5$l z{w%ENXLzPVG4SL008ztkkHPGRY$;(UtbV&d_j=61JO}MD$o`0x{%yi-ELpl#Y3%qN z1$d9AVK?~^%G@8nkS_JDGq;t}+3el;`QOY(2m>+BKT1-}74xhRV&4g_2}$GmvQoWU zr;WcfI1pa@(h0mUYMNzDo1QN!R;L{*`Ya!$AGebRZ2FER~#zVrP#4u^bZ-{|DoQo_lb zXLKWLu=PvjE)&Ez8QJStB$TVOO&bXs;VftVRg2D z(X86FSMRcv?BqLZA3-hhWj9El>0_GGUSZ~YBE41jd3Vu2g`11`5SnBSPOSC4CIQ9@ z*eml%GV6C_+&}+zQE8vmW8C)=%yPp9$0QY#UK7u}MrK2J)Uq$NVPT)5k!xfAas<^+ z+}Tmw>a>xeVM!~kd+*1n=C`6E+2G|bFtzKAkeLgghsDEw zBCqQ*ArP@r(%p=2sjdE^dgkOY9`td4_w`w8`^c)wh=1N?PstYQ1+bCmK}_FrnLZlI zixGb)1GqSJT`l3Tt}X`vXlo)>Dx{&b5bDi-=-kBE17*iTVO}~R>DLfmOU|#BD;ySC zj1c@?m_}X-mIfhUPTc3LTO)byYr9qH?J;cjD;6Hi{dv>jj#u|U%yXoE>atFO|G^uN z!HQ6hi7+*<^@Y$9JJOz7dlmAW5syt9KsH0kV~U2Y8+L2v_!X&Hr!UH=m9z6#tMo7| z6SqzSlGTKy3Fn0>Hp_ZGJBv_e7_DI#9G)O;wUK=bMU&ihI>e~N0Xs5ZW^T=;#uqoRm({2nA=owe}V zb&U{_!Ay-P7VC_Kv0?E-?F_feih6|6e#H=mxUcdfr)`Zj79?yoefj5dHTxB{nWBm7 zhOpNozVGv}=qXfQfy0P;$!p2lf1XuuD~ zdqOGV)-8HU+?h>AXZ?B>e}};R!8_Gcan;(T)m&{zb=gc+`A&aLYFj^Ubj0hLuLKMH zy9V6q(uW`748#w8&0J)&+w{_Jl-mR75CsxXZaN8<9B#6pdWGz@%`?hzYswL~l1l{k z567pCv&>Q1ZavjulsJ#MT93{b5#o~E8}{aomcL*be(_azz{vhDFX)vGeTZG@$4nbL z9`ap;#!4nn!z`z6DiPz@YpHOn-)fBh%9C9w$5fgtqT9-xFZ4P$3!F=>s&Y#HLs?M5 zev4agfACCllA=A;!q}jzvEBA>cyPt#sM4LA>3gnPx;A{Wt~op5svsMBL>n5$Q5#>w zQa`K))rj(>^@sC%OiGg449ebdB_t?!srs3hfSakEpN2$w$A-Fg)U*9P#Vf{jdeh~Q znS3*Kln}F?ns zgG(r0_-FoIGCU2P1%=f1q&-a44ZE2+oSW#~0{0K3ZF2v}Wm8U;Xi5c2-cY3>gtwEn0f$6ME$LMcg?tmB0oI@bn4Q;Ikp} zPC2ydtC))eeWp3u#tJw-^E87K(NfdJK6@`boHuPcJ~SB2O)usO#4|sdF+cdh?{OJb z@MQS92Pz9q4uyc*m%`Af@z0z-)0uts%lm`5Kd44u`FO+I7P7VJ7-TR!D0iCrC6j8N zQ>XQ8lyip;Sq1zU&`)Tf(mypi7#dD|=iTG4o9h-E!j{^`-+;Yw`#QREV|B^-@WG4N z<$L7yST&o?$JtK7{CclDZhBb$Z{8xONCH$uVJa>%rTw}`zvCqoTtb+!BW?JlT0Gvd ziCzL?L8zjU)LQ$|6G9HnJ8!qZ+-Fy8_71*=a%U~S??qP>o6%YQmIMW5%vv}k)uH`H z$z4J+zbTiNxf*`PhfY9PGVdO5X;8S5q%M`CG5*Vi`JCa{IF2)SuIu49$N}t_1vW%| zXew8X=5vNfxJFM`iXyi)W8(1%K8tBjYvNpn3YpnQY&3ofJX367D>#;@{3e?@hU(oB z^FGRTzy&6ppJ9w`1!}jPDQPMb-p@I{J?o^@J59&mq*t5hzx)~i_l5mN>fR%77RF2gtDRba@9AFRt+>q`rOpnOMGM5aJp;0_MG~ z>yNWD-nVcx;P2PtQiC?S$*Bs=)HZq}dMk1bwU)JTH0m&X)?(JwmXo7zbv7r58+sqyP@*3qi9P;)BhzdeL= zV9D!nfH93{Y{fAi{K(GGkM{#d|KGC#oIhDiN1X5e+0wh=n3hz3^z)Lt;k|O3j16;P z9hb+PHGa~`C70(}*sY6#e*RLD8M_~w+?u+ev3hNXdwamN6ww*) zOGhvXm=koDJ;a=<|CX&2ZF@kkx$qiDvfaBOm_;8Mi5k)Vy7F-yOQmf;@=PhNPWFI2 zTSXe+P@0)=`nAMj%}25y&u6~Od2My^QMKw$*0$ft(5q9O`;KrrEb7yhKI{{+8Gz^4`gN2N zKEvI)mKMHoYM;O2D;~l+vFp#LG&R zodsgCe7O5sl*q@S5S1u<&p-b*HYkqVUnMt?>+t7!Ahi+=4t8-xXZFLJfyb*a|KfTOZ0%8lXbe;%)5|K45Go2ZD-9W_iJI{+j^LL?d%@Abr^|8 z+I~<>oigajTX#U0XXc=WK7TYyLqF@qoUc!XHBcZR1LCVHg@6&+e=P^)YUy$d-}F{Y zKD@Bv1yEh1w3;{mADpYdE7rRK58XN4OB{Dql(}O4)+Q)eo5t!Yd|E%K0y+fvj+q<{vv$~{T|LX(6RqIvE`|*1R(!da!-;G(%t(Nyu z0r7@Wt-ORKAg)4LGO+hwkBuQPkA6Mw-}-x?EEz4tujL{>Or~QK`UKEF!a3*q1fwl6 zHXA*=zA`u6jH4oFpq5^!4L?cZE-Kiwr4a=J$*GBnig#{RN5~#`$_xEG!dOS6bQ5VP zsY@p}@cHAefLP%@8NtUEM}2&ERmaQHM0A$~8hVI^D_?gv4VD{Qaz_2syxkN-l z=o=PkGGAI(H)EkLkC}J=xGU{7CpezxFmj)qY*;vNTY2)KnUH6Pzo3O0mK8f~oYCUT zGMkZh$$(>AvR8P`T#x2MBNgt>w8Z_RkiC@Trv`yhVV0sN3DoPnT=REIv%E`JBMsvT z4}(@X_O50Le~(!9RnS9O`3?}0V79Ot$q9WHxtX0$YVut^dyan(FMs3|Qzw8}FHe_t5W9N^#2qxOOP$g)f%jvD!iHzK}{1{F-(UnfYs-%hh6T-G89nl(!G2i{TTT31k}RON4Qy;>ee(OpGg5@W?W$6Cwr7ImjkUCZW|JTaIyhkg(uJlpp>a8 zi=w4g$i^8;1hvdHcI9m7C<~MMeN;*fR6{#yKaQh%WJ6Ndq_IZ+*jA!H0q(?F#fp->^98u4?Ym* z-q4OZM#Mc~Ml?jYd>+QVQSPfb3}uJQVYu0a4x^z(bZdge?$O zn+=7DGAQLnxvMW1AQrN9EtB8plmSGa?&5WKY-0N5u_PmYg`~%D#@=n9Fe*NR59&hMeNdPwo%j5$UrKoRoP^=9dNM$J!XSua4BHez=T6gXw9z!>5i$TRSCFF{89d zPF{0rVieZGx=rRcJgv!Bq1}}@86v-|Nr)t_R;(0HEL1$OW5n!tPS@{#XkV1 z`}}ne)LADOK&fE~@4Ta;yh^-hOe})>J~0P~9ZtG4k2wZE5Yxb`%#X>pdk3ZQK@cgB zjB~Zo`fAq`mJN-kjCNiQ8(bNNa^0KIqivXKi=%Gy61JsdY-62xt2@p`5Ij@a;jf*J zOCX$hjFt_{pK?4bN`M+YzGM;I$Y^eIW=98vQmtk22~)EApNTQgDui{h!v=rlt-bS)EVT*f zQLTt%w9l|K(W9x~RTSgUjcQEgLjn1_(ZE7~K&cK2HRJtTI#jUI;QU2mtU;J2U8r%D zJQtw7tf?DcLV{~_9iF|`Mq7CB@qDRF|3kAUFZ20e+2>#8u+bms4A%0R$au#eNW*uW zi4}$m){k-Lb3A0m9*WPawlOit^sleFvFQe$JacXIeDAd3f`CxiuEpfWlDnmOsZ86; z?85bn@TFu;wMLgrl-7Fp-aPunX~6?LETH9YGWhqyw(TOWRqWtuyDL~;Xzw5<5Xut^ zsx6lI`SDzHu4n6Mtc7^%sHa?dZt}l|6LNBWQSjV?v>(1nUCjG9-3KF%tuKiLqAFY| z+MCVKWJk^p_-tGQ8)J87=97FSCppU;uA}Vy#l}Zj)H_G4;JDSMV1rM6CrK&Cuvm?dsZ<&0 z=<}QP7hE>wHPs&16--@IVNZIO&@*k!d-+zV^I7%!-OCuA1>7Mr^0Rq-Wo~LK*p?j? zp^uOw&=yen1yySNRM--X7P~nlx7dC`8f5>d0(5aZZj5V5rBEu#pR>7g!b?$cAkT{o( zZtTN>T813bY^JYPV3UcJmof8)$b%*XX~3@>QI;3zp#OzhqdKLeXlhQ?Tj>7g6&NOP z5uLTuA|exxR0S86zFw)dd?0+-#r>~;(&(W$GL7D4w>4Xux~Q<&e5p}&qMBu{?~cjR z6kX6_*4*c7P9XxcdcvOEW^@QmwuxJO6AIaUh(pHuVMUL@9nHKoTH4!#U@ffX7&P%r zY@eHaHzw3v#98`>yzJzc3m&_3%=ezjc5>>GfSB+#D-uI)#zO_~+Tu11nOA)ew9e9J zWOrP^Rzm>9J-CB)!1rFH{J~b=OAXo4_~sF&C|>`P32)B^6HPKkVCFhQ&nyh8nJNAc zwu-zTox;r|DpjJrsugJe>736VX_rH}p=wVYa@V`|fg@ZK)>Fga3{+;nt|lP?FK?w4 z0X#ha9yVo7haM`eN183}6gr|R!#RnHnZ5vAqe4B6r3RNC-3M!d(%@+LgKt7K$!DsQ z{Ew#=bLUCO$s~mYUzeWzC~nEZe_yh6RA({Q;*dE7dbI9>ewlAkqTE4@^#tqo^A4iG zn8f++k*Ry_&j?9Na3gsP3){)T{)m8R{7b$prS$jz)mDJ6hPoH*)4cgy_|%gdbJOI} zsBX@SXG@Zg&Cj@rus_NGS5{nOo#xc(r#D(M{FklH-1$?uD3}9!9?^f~?ufyU5ab;O z1pe1!OYP?`VUitiDCkaz5&`GRFsGaZ-#z})3B5Bi(xN9fWj=OW>W`kh{im?~2K$GM zKqrkggVg0ZCP+WU!kxLF9N9A_L49Yzs`&8!JO(N09Fo#=wUzvz@f5WeC zEhL#AG(LcCivzva_G2++uV;D5iHM?eLAXaQ7GWgSji7{E)~gJSkK#a%n}JPl*gKuP zjG;rh^Yp(jp8xZvP;XT*!`Sw@XJA73@*_7jGT%+qyeKX+(%9tW_Ls|Z{uvu30NzT; z>z^?_zt_X7Q~Z~eW57e*=rO9}1z9^B9{X#JAd;K~`@GuW-XDA2uW`IwM3voNcZZtk z?a9%53NEWATv``^uGK-Cj}*X9>mV?PPAYCZ|rvxV%{JeJY#xHqY zRiSJuRpMY2)6r|By~j{JF|fw>h=btlzS?>&*?-6z=+C!CLZnc%t#&LBq8I}?hqBNM z&`Rr=Bb@)XxFmEMx*%eC$Iirpio8#XP9V}p#-7=0C{v|{Ul)>lzW)|a1)Ga>B%p0l z9U^GD@r?<1J-Ak}9jud7DB$8Ev8{a%2xLStKwM^fVUdqNT!#uQ+gt>BVqjw=4rdFc zz~|14`2AH%KhV_x3ugE+dEsVxz9Tb_8MX`p8)|EKFW)^hd%R7OE%lh9`CnpOaNNk3 zf4r9wgxBI|hX*p~32{%9PBU#t1`mO%)-siN8%UjIz(A3W@z0I<*sKN6hZ(~v#4FE; zkHy0Ore?eGOV}A2iv1)WjQGe5D)zUE*h+?+UFf|M{VwYq&${2_Qg_fZB>oK8c z3xqCC71Ep&MSKk)QpyRxHUMFZm|5I+0mh#iLBFe-=VKsps4PQPQvg~V4k%@lrAdk) zm!&AZB^G+Ec;NFsR&tSbG;o5sUu$Fp!56Xg8~|AIus8ZP)Vp+-p`W<&o4@Xvd5q*_ z$*|0DXdf5*iKjv?hF=XgVkD#xvTl-NlwX+G_m-PBj?0Z#y#OB+BU!q$lw&SKDTv%4dX(^tC^R^! zY1i-3nYbO%BQ&Gk3J+KX{1xlRZYyx2ycqi@bkSq7C16B@gve;wW&>^Gm~;s8T0GB} zt}Q@fEf$IGUpm1T zMqm?WHXx%Ao1C&(9Ynh-uUdk{AI|uu7k6*N8vwYYQXO1dT%`mn=2S1nSV<6*LUs4CFYv^aZvOmtHQ6 zHQ9MPDpc7CRo#Ejv#SabF@qDRUwYcuZJGX?9fe%ak8p{(+{CWoB7HimzjA=hCQ612 zu2_TmBg%=r?MM_KbfS+iIk zlb}hKMr~jx06@Ylzb)9a8=o1N$Mim)(^$O)5foo#drsp}71P%H+CYy) zZzjuxOIJ_1I8zQ;;6PAz@6`Nwe|Of}lJcj+=oR8r?r3LlqDOwRS=&WIhvs$9@0tBv z2Bk7<7NvA&KGiC>xik2Gf9FM`$!dw>RFQRU;CSc|B4}`BT{K~}j~Jlfi=&@-r!R17 z$AP>nxj1VD0N6`Tap_VAr;12rBdv-oS@CSPcCzh}L~g`Z>tVaAaC7Qn1#fj&8WFY@ zU(3NAw>%tKN`rL4Q+BvhYG7T>(wGaa<*bUgUv5O)qAQ+i)!5dqI*wjB767si+U{hCpr>KsddjCWGFT(Ec_s6uF!T!`3!Uu#ovK$y zp(}Or+DQIP9XW)&=b1{<2@(%-x%0n94x9a4?#iy4A(lG#N{T!iPfz$rHJN1~y@#~wwuQjQo826fD&uj{qpX2R` zqHz~}xg;2lkGUrZ1EH*7mn?8m zmi3EAfzVKT02@~ZHFkvg!ZgpkDrp7gO0=uo@SPZBnf`C|dQ>n@*eZidDK}l3xtQ!f zeiy7a^p+aALhk$#O+4bA@t-f_{QIp80S17T%ZQaXiHb5mA@+yg_ zgYDNhbV*yf)?zqs)iI~rg*|&BlM>i0SZUq8a;H18`7L+y*f4U%>2ksJnzN@r@~FO+ zff+Nw#l+uClalUKeI-$-&2oY9x%P#nsT5n)cyK9MQ=1q)VyX@!{Lz8{T@*iW&y|;D z{x%K!Un(wP*ids}AX|krzIo|fSblHoF!DCWn7{~O=?%vUXM)W3%Tx_Ff#gR&*=%<; z&CyB$&?6Sv5T)1qbCCitwZun%IkE5oMKC^2t17yH-%tJv2B7*X`L8jKzZkW5OO*YI(>x36K6Z)3y6M#G^W7@ym!LzQyJ=|VBoF^uLU+f+Pbb)J zazYh$=e#GuhvcdE=fg0g>N8!wRe%xw;Z-#kXc3cALaxsqlVV61)5M2HnccO~4>+{AAUq6UHZ& zf@zZk<;=96OkjeBta|Am4}88GiFw~lovGs#F^(UPLA!eWDuC%_9@GFh52_L&XDbhyDzCn)#KEuCZLqG1FSbl8baaG=VG zl7tf{iQ7$D%{D$;wqHMHsmBJHtPq>hVhjf%Uw5F-l;>n|C%~>X3hh0G(nAGkq>ks??n^@-z5e!} zkq2Lig{F&rN31u1H>tdk#uWPUZyw>F|Kq)!ZP>VKzB}jf;Wx7F0rx>~y96n$X{znE z2K$cC$q-#=z$;G0{e2=!IMFUXj!9^g2R0`N4pqy-E)t&`^>bI+H~JMk22K>o+GP_< z%9&(UR>HPFl<#w;xju_$4SSDRo>>rAKVdN%@b?6)QY%=NWV|&gj8k9)ysi#Qb%Y%g zijZgHSG_#N>wD4QOq>NutohZd9cp_3=iiowIwi_YqPe>aY@_sR$C-Qk%D9Vnz_9;y zRe+e_X^~oElcgiBHg{QQYAA}w8;p=VbHc(kfa-I;<_*z41I1Jmkq&#V%=bvy91aWh z6?{nhCz~;@DW4$sSW?=^k}mYa2WCla;miyU=u&;v?k^qP(JFi@;*Z>lw_k^&*Ul;6 zl@c@}X{wJbgt^rsU4GbOrELTF(Cv4h7zE~X{76}D5rl0ye@6>55h{u^TaN9q$G2dE zAib5=2|G^U3qkK*0H0gzswyy6!z(G3X)&pEjSYzu`OA6Oy!&A?-4;39PS^J!gjxx1 z-f`Cy#3SF4AofxKnfq6M7mFbJj}k!F=gMbF7>b!uegbp2fxdzbEetb4Gdbwv+iG{I z=6BFou?-;2BSVqtk+jvsfj_eM1wiN5B8=m4=ZNN`aJKeO9CFaQ7m diff --git a/packages/webapp/public/index.html b/packages/webapp/public/index.html index 901dbd8c..0cb531f7 100644 --- a/packages/webapp/public/index.html +++ b/packages/webapp/public/index.html @@ -7,7 +7,7 @@ - + diff --git a/packages/webapp/src/app.tsx b/packages/webapp/src/app.tsx index daa223cd..d58a1dfb 100644 --- a/packages/webapp/src/app.tsx +++ b/packages/webapp/src/app.tsx @@ -1,3 +1,20 @@ +/* + * Copyright [2021] [wisemapping] + * + * Licensed under WiseMapping Public License, Version 1.0 (the "License"). + * It is basically the Apache License, Version 2.0 (the "License") plus the + * "powered by wisemapping" text requirement on every single page; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the license at + * + * http://www.wisemapping.org/license + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ import React, { ReactElement, Suspense, useEffect } from 'react'; import { FormattedMessage, IntlProvider } from 'react-intl'; import { Route, Routes, BrowserRouter as Router, useNavigate } from 'react-router-dom'; @@ -22,12 +39,14 @@ const EditorPage = React.lazy(() => import('./components/editor-page')); const MapsPage = React.lazy(() => import('./components/maps-page')); // Google Analytics Initialization. -ReactGA.initialize([ - { - trackingId: AppConfig.getGoogleAnalyticsAccount(), - }, -]); - +const trackingId = AppConfig.getGoogleAnalyticsAccount(); +if (trackingId) { + ReactGA.initialize([ + { + trackingId: trackingId, + }, + ]); +} const queryClient = new QueryClient({ defaultOptions: { queries: { diff --git a/packages/webapp/src/classes/app-config/index.ts b/packages/webapp/src/classes/app-config/index.ts index 5c32c0db..02a42569 100644 --- a/packages/webapp/src/classes/app-config/index.ts +++ b/packages/webapp/src/classes/app-config/index.ts @@ -17,7 +17,6 @@ */ import Client from '../client'; -import CacheDecoratorClient from '../client/cache-decorator-client'; import MockClient from '../client/mock-client'; import RestClient from '../client/rest-client'; @@ -91,8 +90,7 @@ class _AppConfig { result = new MockClient(); } - // Wrap with a cache decorator ... - return new CacheDecoratorClient(result); + return result; } getBaseUrl(): string { diff --git a/packages/webapp/src/classes/app-i18n/index.ts b/packages/webapp/src/classes/app-i18n/index.ts index 5a6ed1ea..a6f694f5 100644 --- a/packages/webapp/src/classes/app-i18n/index.ts +++ b/packages/webapp/src/classes/app-i18n/index.ts @@ -57,8 +57,8 @@ export default abstract class AppI18n { public static getDefaultLocale(): Locale { // Fetch local from local storage ... - let result: Locale; - const userLocaleCode: string = localStorage.getItem(AppI18n.LOCAL_STORAGE_KEY); + let result: Locale | null = null; + const userLocaleCode: string | null = localStorage.getItem(AppI18n.LOCAL_STORAGE_KEY); if (userLocaleCode) { result = localeFromStr(userLocaleCode); } diff --git a/packages/webapp/src/classes/client/cache-decorator-client/index.ts b/packages/webapp/src/classes/client/cache-decorator-client/index.ts deleted file mode 100644 index 8b84e2ca..00000000 --- a/packages/webapp/src/classes/client/cache-decorator-client/index.ts +++ /dev/null @@ -1,143 +0,0 @@ -import Client, { - AccountInfo, - BasicMapInfo, - ChangeHistory, - ImportMapInfo, - Label, - MapInfo, - NewUser, - Permission, - Oauth2CallbackResult, - ForgotPasswordResult, -} from '..'; -import { LocaleCode } from '../../app-i18n'; - -class CacheDecoratorClient implements Client { - private client: Client; - - constructor(client: Client) { - this.client = client; - } - - processGoogleCallback(code: string): Promise { - return this.client.processGoogleCallback(code); - } - - confirmAccountSync(email: string, code: string): Promise { - return this.client.confirmAccountSync(email, code); - } - - fetchStarred(id: number): Promise { - return this.client.fetchStarred(id); - } - - onSessionExpired(callback?: () => void): () => void { - return this.client.onSessionExpired(callback); - } - - deleteAccount(): Promise { - return this.client.deleteAccount(); - } - - importMap(model: ImportMapInfo): Promise { - return this.client.importMap(model); - } - - createMap(map: BasicMapInfo): Promise { - return this.client.createMap(map); - } - - deleteMaps(ids: number[]): Promise { - return this.client.deleteMaps(ids); - } - - deleteMap(id: number): Promise { - return this.client.deleteMap(id); - } - - renameMap(id: number, basicInfo: BasicMapInfo): Promise { - return this.client.renameMap(id, basicInfo); - } - - fetchAllMaps(): Promise { - return this.client.fetchAllMaps(); - } - - fetchMapPermissions(id: number): Promise { - return this.client.fetchMapPermissions(id); - } - - addMapPermissions(id: number, message: string, permissions: Permission[]): Promise { - return this.client.addMapPermissions(id, message, permissions); - } - - deleteMapPermission(id: number, email: string): Promise { - return this.client.deleteMapPermission(id, email); - } - - duplicateMap(id: number, basicInfo: BasicMapInfo): Promise { - return this.client.duplicateMap(id, basicInfo); - } - - updateAccountLanguage(locale: LocaleCode): Promise { - return this.client.updateAccountLanguage(locale); - } - - updateAccountPassword(pasword: string): Promise { - return this.client.updateAccountPassword(pasword); - } - - updateAccountInfo(firstname: string, lastname: string): Promise { - return this.client.updateAccountInfo(firstname, lastname); - } - - updateStarred(id: number, starred: boolean): Promise { - return this.client.updateStarred(id, starred); - } - - updateMapToPublic(id: number, isPublic: boolean): Promise { - return this.client.updateMapToPublic(id, isPublic); - } - - fetchLabels(): Promise { - return this.client.fetchLabels(); - } - - createLabel(title: string, color: string): Promise { - return this.client.createLabel(title, color); - } - - deleteLabel(id: number): Promise { - return this.client.deleteLabel(id); - } - - addLabelToMap(labelId: number, mapId: number): Promise { - return this.client.addLabelToMap(labelId, mapId); - } - - deleteLabelFromMap(labelId: number, mapId: number): Promise { - return this.client.deleteLabelFromMap(labelId, mapId); - } - - fetchAccountInfo(): Promise { - return this.client.fetchAccountInfo(); - } - - registerNewUser(user: NewUser): Promise { - return this.client.registerNewUser(user); - } - - resetPassword(email: string): Promise { - return this.client.resetPassword(email); - } - - fetchHistory(id: number): Promise { - return this.client.fetchHistory(id); - } - - revertHistory(id: number, cid: number): Promise { - return this.client.revertHistory(id, cid); - } -} - -export default CacheDecoratorClient; diff --git a/packages/webapp/src/classes/client/index.ts b/packages/webapp/src/classes/client/index.ts index d224c286..442943df 100644 --- a/packages/webapp/src/classes/client/index.ts +++ b/packages/webapp/src/classes/client/index.ts @@ -118,12 +118,12 @@ interface Client { registerNewUser(user: NewUser): Promise; resetPassword(email: string): Promise; processGoogleCallback(code: string): Promise; - confirmAccountSync(email: string, code: string): Promise; + confirmAccountSync(email: string, code?: string): Promise; fetchHistory(id: number): Promise; revertHistory(id: number, cid: number): Promise; - onSessionExpired(callback?: () => void): () => void; + onSessionExpired(callback?: () => void): (() => void) | undefined; } export default Client; diff --git a/packages/webapp/src/classes/client/mock-client/index.ts b/packages/webapp/src/classes/client/mock-client/index.ts index 2ac5ded1..a052e09e 100644 --- a/packages/webapp/src/classes/client/mock-client/index.ts +++ b/packages/webapp/src/classes/client/mock-client/index.ts @@ -128,10 +128,10 @@ class MockClient implements Client { } fetchStarred(id: number): Promise { - return Promise.resolve(this.maps.find((m) => m.id == id).starred); + return Promise.resolve(Boolean(this.maps.find((m) => m.id == id)?.starred)); } - onSessionExpired(callback?: () => void): () => void { + onSessionExpired(callback?: () => void): (() => void) | undefined { return callback; } diff --git a/packages/webapp/src/components/HOCs/withSessionExpirationHandling.tsx b/packages/webapp/src/components/HOCs/withSessionExpirationHandling.tsx deleted file mode 100644 index 28f5c03e..00000000 --- a/packages/webapp/src/components/HOCs/withSessionExpirationHandling.tsx +++ /dev/null @@ -1,32 +0,0 @@ -/* eslint-disable react/display-name */ -import React, { ComponentType, useEffect } from 'react'; -import { useDispatch, useSelector } from 'react-redux'; -import Client from '../../classes/client'; -import ClientHealthSentinel from '../../classes/client/client-health-sentinel'; -import { activeInstance, sessionExpired } from '../../redux/clientSlice'; - -function withSessionExpirationHandling(Component: ComponentType) { - return (hocProps: T): React.ReactElement => { - const client: Client = useSelector(activeInstance); - const dispatch = useDispatch(); - - useEffect(() => { - if (client) { - client.onSessionExpired(() => { - dispatch(sessionExpired()); - }); - } else { - console.warn('Session expiration wont be handled because could not find client'); - } - }, []); - - return ( - <> - - - - ); - }; -} - -export default withSessionExpirationHandling; diff --git a/packages/webapp/src/classes/client/client-health-sentinel/index.tsx b/packages/webapp/src/components/common/client-health-sentinel/index.tsx similarity index 100% rename from packages/webapp/src/classes/client/client-health-sentinel/index.tsx rename to packages/webapp/src/components/common/client-health-sentinel/index.tsx diff --git a/packages/webapp/src/components/common/csrf-input/index.tsx b/packages/webapp/src/components/common/csrf-input/index.tsx new file mode 100644 index 00000000..d79285e1 --- /dev/null +++ b/packages/webapp/src/components/common/csrf-input/index.tsx @@ -0,0 +1,10 @@ +import React from 'react'; +import { getCsrfToken, getCsrfTokenParameter } from '../../../utils'; + +const CSRFInput = (): React.ReactElement => { + const token = getCsrfToken(); + const tokenParam = getCsrfTokenParameter(); + return <>{token && tokenParam && }; +}; + +export default CSRFInput; diff --git a/packages/webapp/src/components/common/google-button/index.tsx b/packages/webapp/src/components/common/google-button/index.tsx index 25a2cd0d..631a31d4 100644 --- a/packages/webapp/src/components/common/google-button/index.tsx +++ b/packages/webapp/src/components/common/google-button/index.tsx @@ -1,3 +1,20 @@ +/* + * Copyright [2021] [wisemapping] + * + * Licensed under WiseMapping Public License, Version 1.0 (the "License"). + * It is basically the Apache License, Version 2.0 (the "License") plus the + * "powered by wisemapping" text requirement on every single page; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the license at + * + * http://www.wisemapping.org/license + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ import React from 'react'; import { css } from '@emotion/react'; import { Button } from '@mui/material'; diff --git a/packages/webapp/src/components/common/separator/index.tsx b/packages/webapp/src/components/common/separator/index.tsx index a04c9a7e..56fd4d1e 100644 --- a/packages/webapp/src/components/common/separator/index.tsx +++ b/packages/webapp/src/components/common/separator/index.tsx @@ -1,3 +1,20 @@ +/* + * Copyright [2021] [wisemapping] + * + * Licensed under WiseMapping Public License, Version 1.0 (the "License"). + * It is basically the Apache License, Version 2.0 (the "License") plus the + * "powered by wisemapping" text requirement on every single page; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the license at + * + * http://www.wisemapping.org/license + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ import React from 'react'; import { useTheme } from '@mui/material/styles'; import { containerStyle, lineStyle, textStyle } from './style'; diff --git a/packages/webapp/src/components/common/separator/style.ts b/packages/webapp/src/components/common/separator/style.ts index cb95f61a..faf4fc1d 100644 --- a/packages/webapp/src/components/common/separator/style.ts +++ b/packages/webapp/src/components/common/separator/style.ts @@ -2,7 +2,7 @@ import { css, SerializedStyles } from '@emotion/react'; export const containerStyle = ( responsive: boolean, - maxWidth: number, + maxWidth: number | undefined, breakPointDownMd: string, ): SerializedStyles => { return css([ diff --git a/packages/webapp/src/components/editor-page/index.tsx b/packages/webapp/src/components/editor-page/index.tsx index 51944000..bc9b62cc 100644 --- a/packages/webapp/src/components/editor-page/index.tsx +++ b/packages/webapp/src/components/editor-page/index.tsx @@ -26,19 +26,23 @@ import { } from '@wisemapping/editor'; import { IntlProvider } from 'react-intl'; import AppI18n, { Locales } from '../../classes/app-i18n'; -import { useSelector } from 'react-redux'; +import { useDispatch, useSelector } from 'react-redux'; import { hotkeysEnabled } from '../../redux/editorSlice'; import ReactGA from 'react-ga4'; -import { useFetchAccount, useFetchMapById } from '../../redux/clientSlice'; +import { + useFetchAccount, + useFetchMapById, + activeInstance, + sessionExpired, +} from '../../redux/clientSlice'; import EditorOptionsBuilder from './EditorOptionsBuilder'; import { useTheme } from '@mui/material/styles'; import MapInfoImpl from '../../classes/editor-map-info'; import { MapInfo } from '@wisemapping/editor'; -import { activeInstance } from '../../redux/clientSlice'; import Client from '../../classes/client'; import AppConfig from '../../classes/app-config'; import exampleMap from '../../classes/client/mock-client/example-map.wxml'; -import withSessionExpirationHandling from '../HOCs/withSessionExpirationHandling'; +import ClientHealthSentinel from '../common/client-health-sentinel'; const buildPersistenceManagerForEditor = (mode: string): PersistenceManager => { let persistenceManager: PersistenceManager; @@ -72,6 +76,7 @@ const buildPersistenceManagerForEditor = (mode: string): PersistenceManager => { export type EditorPropsType = { isTryMode: boolean; }; + type ActionType = | 'open' | 'share' @@ -98,6 +103,17 @@ const EditorPage = ({ isTryMode }: EditorPropsType): React.ReactElement => { const userLocale = AppI18n.getUserLocale(); const theme = useTheme(); const client: Client = useSelector(activeInstance); + const dispatch = useDispatch(); + + useEffect(() => { + if (client) { + client.onSessionExpired(() => { + dispatch(sessionExpired()); + }); + } else { + console.warn('Session expiration wont be handled because could not find client'); + } + }, []); useEffect(() => { ReactGA.send({ hitType: 'pageview', page: window.location.pathname, title: `Map Editor` }); @@ -163,6 +179,7 @@ const EditorPage = ({ isTryMode }: EditorPropsType): React.ReactElement => { defaultLocale={Locales.EN.code} messages={userLocale.message as Record} > + { ); }; -export default withSessionExpirationHandling(EditorPage); +export default EditorPage; diff --git a/packages/webapp/src/components/forgot-password-page/index.tsx b/packages/webapp/src/components/forgot-password-page/index.tsx index 0d194c8a..65b2bd3c 100644 --- a/packages/webapp/src/components/forgot-password-page/index.tsx +++ b/packages/webapp/src/components/forgot-password-page/index.tsx @@ -15,9 +15,9 @@ import ReactGA from 'react-ga4'; import { Link as RouterLink } from 'react-router-dom'; import Typography from '@mui/material/Typography'; -import { getCsrfToken, getCsrfTokenParameter } from '../../utils'; import { useNavigate } from 'react-router-dom'; import { Button } from '@mui/material'; +import CSRFInput from '../common/csrf-input'; const ForgotPassword = () => { const [email, setEmail] = useState(''); @@ -84,7 +84,7 @@ const ForgotPassword = () => {

- + { // @Todo: This must be reviewed to be based on navigation state. @@ -70,7 +70,7 @@ const LoginPage = (): React.ReactElement => { - + { defaultMessage: 'Sign in with Google', })} onClick={() => { - window.location.href = AppConfig.getGoogleOauth2Url(); + const authUrl = AppConfig.getGoogleOauth2Url(); + if (authUrl) { + window.location.href = authUrl; + } else { + console.log('GoogleOauth2Url is not configured.'); + } }} /> diff --git a/packages/webapp/src/components/maps-page/action-dispatcher/import-dialog/index.tsx b/packages/webapp/src/components/maps-page/action-dispatcher/import-dialog/index.tsx index f090a644..c98cb774 100644 --- a/packages/webapp/src/components/maps-page/action-dispatcher/import-dialog/index.tsx +++ b/packages/webapp/src/components/maps-page/action-dispatcher/import-dialog/index.tsx @@ -89,7 +89,7 @@ const ImportDialog = ({ onClose }: CreateProps): React.ReactElement => { const extensionFile = file.name.split('.').pop(); const extensionAccept = ['wxml', 'mm']; - if (!extensionAccept.includes(extensionFile)) { + if (!extensionAccept.includes(extensionFile!)) { setErrorFile({ error: true, message: intl.formatMessage( @@ -108,8 +108,8 @@ const ImportDialog = ({ onClose }: CreateProps): React.ReactElement => { model.contentType = 'application/xml'; const fileContent = event?.target?.result; - const mapConent: string = - typeof fileContent === 'string' ? fileContent : fileContent.toString(); + const mapConent: string | undefined = + typeof fileContent === 'string' ? fileContent : fileContent?.toString(); try { const importer: Importer = TextImporterFactory.create(extensionFile, mapConent); diff --git a/packages/webapp/src/components/maps-page/action-dispatcher/label-dialog/index.tsx b/packages/webapp/src/components/maps-page/action-dispatcher/label-dialog/index.tsx index ce6942e5..6613284d 100644 --- a/packages/webapp/src/components/maps-page/action-dispatcher/label-dialog/index.tsx +++ b/packages/webapp/src/components/maps-page/action-dispatcher/label-dialog/index.tsx @@ -1,3 +1,20 @@ +/* + * Copyright [2021] [wisemapping] + * + * Licensed under WiseMapping Public License, Version 1.0 (the "License"). + * It is basically the Apache License, Version 2.0 (the "License") plus the + * "powered by wisemapping" text requirement on every single page; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the license at + * + * http://www.wisemapping.org/license + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ import React from 'react'; import { useSelector } from 'react-redux'; import { FormattedMessage, useIntl } from 'react-intl'; @@ -19,13 +36,11 @@ const LabelDialog = ({ mapsId, onClose }: MultiDialogProps): React.ReactElement const client: Client = useSelector(activeInstance); const queryClient = useQueryClient(); - // TODO: pass down map data instead of using query? const { data } = useQuery('maps', () => { return client.fetchAllMaps(); }); const [error, setError] = React.useState(); - - const maps = data.filter((m) => mapsId.includes(m.id)); + const maps = data?.filter((m) => mapsId.includes(m.id)); const changeLabelMutation = useMutation< void, @@ -44,11 +59,9 @@ const LabelDialog = ({ mapsId, onClose }: MultiDialogProps): React.ReactElement const handleChangesInLabels = (label: Label, checked: boolean) => { setError(undefined); - changeLabelMutation.mutate({ - maps, - label, - checked, - }); + if (maps) { + changeLabelMutation.mutate({ maps, label, checked }); + } }; return ( @@ -66,21 +79,27 @@ const LabelDialog = ({ mapsId, onClose }: MultiDialogProps): React.ReactElement paperCss={classes.paper} error={error} > - <> - }> - - {maps.length > 1 ? ( - - ) : ( - maps.map((m) => m.title).join(', ') - )} - - - + {maps && ( + <> + } + > + + {maps && maps.length > 1 ? ( + + ) : ( + maps.map((m) => m.title).join(', ') + )} + + + + )} ); diff --git a/packages/webapp/src/components/maps-page/index.tsx b/packages/webapp/src/components/maps-page/index.tsx index 712b74c5..cf4c4a91 100644 --- a/packages/webapp/src/components/maps-page/index.tsx +++ b/packages/webapp/src/components/maps-page/index.tsx @@ -1,3 +1,20 @@ +/* + * Copyright [2021] [wisemapping] + * + * Licensed under WiseMapping Public License, Version 1.0 (the "License"). + * It is basically the Apache License, Version 2.0 (the "License") plus the + * "powered by wisemapping" text requirement on every single page; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the license at + * + * http://www.wisemapping.org/license + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ import React, { ErrorInfo, ReactElement, useEffect } from 'react'; import Drawer from '@mui/material/Drawer'; import AppBar from '@mui/material/AppBar'; @@ -200,7 +217,7 @@ const MapsPage = (): ReactElement => { ); const container = document !== undefined ? () => document.body : undefined; - + const label = labels.find((l) => l.id === labelToDelete); return ( {
@@ -321,14 +338,14 @@ const MapsPage = (): ReactElement => {
- {labelToDelete && ( + {label && labelToDelete && ( setLabelToDelete(null)} onConfirm={() => { handleLabelDelete(labelToDelete); setLabelToDelete(null); }} - label={labels.find((l) => l.id === labelToDelete)} + label={label} /> )}
diff --git a/packages/webapp/src/components/registration-callback/index.tsx b/packages/webapp/src/components/registration-callback/index.tsx index 71248eb9..dc43aa70 100644 --- a/packages/webapp/src/components/registration-callback/index.tsx +++ b/packages/webapp/src/components/registration-callback/index.tsx @@ -20,7 +20,7 @@ const RegistrationCallbackPage = (): React.ReactElement => { const client: Client = useSelector(activeInstance); const [showError, setShowError] = useState(false); - const [callbackResult, setCallbackResult] = useState(undefined); + const [callbackResult, setCallbackResult] = useState(); const navigate = useNavigate(); useEffect(() => { @@ -37,6 +37,10 @@ const RegistrationCallbackPage = (): React.ReactElement => { useEffect(() => { const googleOauthCode = new URLSearchParams(window.location.search).get('code'); + if (!googleOauthCode) { + throw new Error(`Missing code definition: ${window.location.search}`); + } + client .processGoogleCallback(googleOauthCode) .then((result) => { @@ -54,8 +58,13 @@ const RegistrationCallbackPage = (): React.ReactElement => { }, []); const confirmAccountSynching = () => { + const callback = callbackResult; + if (!callback) { + throw new Error(`callbackResult can not be null`); + } + client - .confirmAccountSync(callbackResult.email, callbackResult.syncCode) + .confirmAccountSync(callback.email, callback.syncCode) .then(() => { navigate('/c/maps/'); }) diff --git a/packages/webapp/src/components/registration-page/index.tsx b/packages/webapp/src/components/registration-page/index.tsx index f350a176..5ca9a26c 100644 --- a/packages/webapp/src/components/registration-page/index.tsx +++ b/packages/webapp/src/components/registration-page/index.tsx @@ -69,7 +69,12 @@ const RegistrationForm = () => { const maxFormWidth = 350; const handleRegisterWithGoogleClick = () => { - window.location.href = AppConfig.getGoogleOauth2Url(); + const url = AppConfig.getGoogleOauth2Url(); + if (url) { + window.location.href = url; + } else { + console.error('Auth callback url is null'); + } }; return ( diff --git a/packages/webapp/src/redux/clientSlice.ts b/packages/webapp/src/redux/clientSlice.ts index d8ffa22e..9c59c025 100644 --- a/packages/webapp/src/redux/clientSlice.ts +++ b/packages/webapp/src/redux/clientSlice.ts @@ -55,7 +55,7 @@ export const clientSlice = createSlice({ type MapLoadResult = { isLoading: boolean; error: ErrorInfo | null; - map: MapInfo | null; + map: MapInfo | undefined; }; export const useFetchMapById = (id: number): MapLoadResult => { @@ -65,12 +65,12 @@ export const useFetchMapById = (id: number): MapLoadResult => { }); // If the map can not be loaded, create an error object. - let map: MapInfo; - let errorMsg: ErrorInfo = error; + let map: MapInfo | undefined; + let errorMsg: ErrorInfo | null = error; if (!isLoading) { // Sanitize error structure ... if (errorMsg) { - errorMsg = Object.keys(error).length !== 0 ? error : null; + errorMsg = Object.keys(errorMsg).length !== 0 ? error : null; } // Seach for object... map = data?.find((m) => m.id == id); diff --git a/packages/webapp/src/tsconfig.json b/packages/webapp/src/tsconfig.json deleted file mode 100644 index 81daad90..00000000 --- a/packages/webapp/src/tsconfig.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "compilerOptions": { - "outDir": "./dist/", - "sourceMap": true, - "noImplicitAny": false, - "module": "amd", - "moduleResolution": "node", - "strict": false, - "target": "es6", - "allowJs": true, - "esModuleInterop": true, - "declaration": true, - "jsx": "react-jsx", - "jsxImportSource": "@emotion/react" - - } -} - \ No newline at end of file diff --git a/packages/webapp/src/utils.ts b/packages/webapp/src/utils.ts index 17f0ab3f..7c578712 100644 --- a/packages/webapp/src/utils.ts +++ b/packages/webapp/src/utils.ts @@ -6,7 +6,7 @@ export const getCsrfToken = (): string | null => { return meta.getAttribute('content'); }; -export const getCsrfTokenParameter = (): string => { +export const getCsrfTokenParameter = (): string | null => { const meta = document.head.querySelector('meta[name="_csrf_parameter"]'); if (!meta) { return ''; diff --git a/packages/webapp/tsconfig.json b/packages/webapp/tsconfig.json index 072d6cd5..63b24c62 100644 --- a/packages/webapp/tsconfig.json +++ b/packages/webapp/tsconfig.json @@ -1,15 +1,27 @@ - { - "compilerOptions": { - "outDir": "./dist/", - "sourceMap": true, - "noImplicitAny": false, - "module": "es6", - "target": "es6", - "allowJs": true, - "esModuleInterop": true, - "jsx": "react-jsx", - "jsxImportSource": "@emotion/react" - - }, - "exclude": ["node_modules"] - } \ No newline at end of file +{ + "include": [ + "src/**/*" + ], + "compilerOptions": { + "jsx": "react-jsx", + "outDir": "./dist/", + "sourceMap": true, + "noImplicitAny": false, + "module": "amd", + "moduleResolution": "node", + "strict": false, + "target": "es6", + "allowJs": true, + "esModuleInterop": true, + "declaration": true, + "strictNullChecks": true, + "rootDirs": [ + "src", + ], + "jsxImportSource": "@emotion/react", + "resolveJsonModule": true + }, + "exclude": [ + "node_modules" + ] +} \ No newline at end of file