From 3070e2696cb948341c23d72c9b5e30e43986361f Mon Sep 17 00:00:00 2001
From: nyqykk <65393845+nyqykk@users.noreply.github.com>
Date: Thu, 19 Sep 2024 10:48:44 +0800
Subject: [PATCH] feat: support interface data prefetch (#2543)
---
.changeset/light-items-battle.md | 5 +
.github/workflows/e2e-manifest.yml | 2 +-
.../3009-webpack-provider/tsconfig.app.json | 12 +-
.../3009-webpack-provider/tsconfig.json | 31 +-
.../3010-rspack-provider/package.json | 3 +-
.../3010-rspack-provider/rspack.config.js | 1 +
.../3010-rspack-provider/src/App.tsx | 2 +
apps/manifest-demo/webpack-host/src/App.tsx | 3 +
.../webpack-host/webpack.config.js | 1 +
apps/modernjs/cypress/e2e/app.cy.ts | 2 +-
apps/modernjs/modern.config.ts | 5 +-
.../components/react-component.prefetch.ts | 19 +
.../src/components/react-component.tsx | 44 +
apps/modernjs/src/routes/page.tsx | 2 +
apps/website-new/docs/en/guide/_meta.json | 5 +
.../docs/en/guide/performance/_meta.json | 1 +
.../docs/en/guide/performance/prefetch.mdx | 288 +
.../performance/data-prefetch/common.jpg | Bin 0 -> 135618 bytes
.../guide/performance/data-prefetch/log.jpg | Bin 0 -> 774989 bytes
.../performance/data-prefetch/prefetch.jpg | Bin 0 -> 133791 bytes
apps/website-new/docs/zh/guide/_meta.json | 5 +
.../docs/zh/guide/performance/_meta.json | 1 +
.../docs/zh/guide/performance/prefetch.mdx | 284 +
package.json | 2 +-
packages/data-prefetch/CHANGELOG.md | 1 +
packages/data-prefetch/README.md | 1 +
.../data-prefetch/__tests__/babel.spec.ts | 75 +
.../data-prefetch/__tests__/prefetch.spec.ts | 138 +
.../data-prefetch/__tests__/react.spec.ts | 119 +
packages/data-prefetch/jest.config.js | 29 +
packages/data-prefetch/package.json | 96 +
packages/data-prefetch/project.json | 21 +
packages/data-prefetch/src/cli/babel.ts | 94 +
packages/data-prefetch/src/cli/index.ts | 171 +
packages/data-prefetch/src/common/constant.ts | 1 +
packages/data-prefetch/src/common/index.ts | 1 +
.../data-prefetch/src/common/node-utils.ts | 24 +
.../data-prefetch/src/common/runtime-utils.ts | 34 +
packages/data-prefetch/src/index.ts | 2 +
packages/data-prefetch/src/logger/index.ts | 3 +
packages/data-prefetch/src/plugin.ts | 191 +
packages/data-prefetch/src/prefetch.ts | 207 +
packages/data-prefetch/src/react/hooks.ts | 95 +
packages/data-prefetch/src/react/index.ts | 1 +
packages/data-prefetch/src/react/utils.ts | 11 +
packages/data-prefetch/src/shared/index.ts | 26 +
packages/data-prefetch/src/universal/index.ts | 27 +
packages/data-prefetch/tsconfig.json | 27 +
packages/data-prefetch/tsup.config.ts | 35 +
packages/enhanced/package.json | 9 +
.../src/lib/container/ContainerEntryModule.ts | 3 +
.../lib/container/ModuleFederationPlugin.ts | 2 +
.../runtime/FederationRuntimePlugin.ts | 43 +-
packages/enhanced/src/prefetch.ts | 2 +
.../container/ModuleFederationPlugin.ts | 0
packages/manifest/src/ManifestManager.ts | 18 +
packages/manifest/tsconfig.json | 1 -
packages/rspack/src/ModuleFederationPlugin.ts | 1 -
packages/runtime/src/core.ts | 7 +-
packages/runtime/src/index.ts | 1 +
packages/runtime/src/module/index.ts | 11 +-
.../src/plugins/generate-preload-assets.ts | 3 +-
packages/runtime/src/remote/index.ts | 33 +-
packages/sdk/src/constant.ts | 8 +
.../types/plugins/ModuleFederationPlugin.ts | 5 +
.../src/initContainerEntry.ts | 4 +-
packages/webpack-bundler-runtime/src/types.ts | 1 +
pnpm-lock.yaml | 45088 +++++++++-------
68 files changed, 26661 insertions(+), 20727 deletions(-)
create mode 100644 .changeset/light-items-battle.md
create mode 100644 apps/modernjs/src/components/react-component.prefetch.ts
create mode 100644 apps/modernjs/src/components/react-component.tsx
create mode 100644 apps/website-new/docs/en/guide/performance/_meta.json
create mode 100644 apps/website-new/docs/en/guide/performance/prefetch.mdx
create mode 100644 apps/website-new/docs/public/guide/performance/data-prefetch/common.jpg
create mode 100644 apps/website-new/docs/public/guide/performance/data-prefetch/log.jpg
create mode 100644 apps/website-new/docs/public/guide/performance/data-prefetch/prefetch.jpg
create mode 100644 apps/website-new/docs/zh/guide/performance/_meta.json
create mode 100644 apps/website-new/docs/zh/guide/performance/prefetch.mdx
create mode 100644 packages/data-prefetch/CHANGELOG.md
create mode 100644 packages/data-prefetch/README.md
create mode 100644 packages/data-prefetch/__tests__/babel.spec.ts
create mode 100644 packages/data-prefetch/__tests__/prefetch.spec.ts
create mode 100644 packages/data-prefetch/__tests__/react.spec.ts
create mode 100644 packages/data-prefetch/jest.config.js
create mode 100644 packages/data-prefetch/package.json
create mode 100644 packages/data-prefetch/project.json
create mode 100644 packages/data-prefetch/src/cli/babel.ts
create mode 100644 packages/data-prefetch/src/cli/index.ts
create mode 100644 packages/data-prefetch/src/common/constant.ts
create mode 100644 packages/data-prefetch/src/common/index.ts
create mode 100644 packages/data-prefetch/src/common/node-utils.ts
create mode 100644 packages/data-prefetch/src/common/runtime-utils.ts
create mode 100644 packages/data-prefetch/src/index.ts
create mode 100644 packages/data-prefetch/src/logger/index.ts
create mode 100644 packages/data-prefetch/src/plugin.ts
create mode 100644 packages/data-prefetch/src/prefetch.ts
create mode 100644 packages/data-prefetch/src/react/hooks.ts
create mode 100644 packages/data-prefetch/src/react/index.ts
create mode 100644 packages/data-prefetch/src/react/utils.ts
create mode 100644 packages/data-prefetch/src/shared/index.ts
create mode 100644 packages/data-prefetch/src/universal/index.ts
create mode 100644 packages/data-prefetch/tsconfig.json
create mode 100644 packages/data-prefetch/tsup.config.ts
create mode 100644 packages/enhanced/src/prefetch.ts
create mode 100644 packages/enhanced/src/schemas/container/ModuleFederationPlugin.ts
diff --git a/.changeset/light-items-battle.md b/.changeset/light-items-battle.md
new file mode 100644
index 0000000000..af9ddd01fe
--- /dev/null
+++ b/.changeset/light-items-battle.md
@@ -0,0 +1,5 @@
+---
+'@module-federation/data-prefetch': patch
+---
+
+feat(@module-federation/data-prefetch): support data prefetch in Module Federation
diff --git a/.github/workflows/e2e-manifest.yml b/.github/workflows/e2e-manifest.yml
index 379794c635..dd330e65bb 100644
--- a/.github/workflows/e2e-manifest.yml
+++ b/.github/workflows/e2e-manifest.yml
@@ -43,4 +43,4 @@ jobs:
- name: E2E Test for Manifest Demo
if: steps.check-ci.outcome == 'success'
- run: pnpm run app:manifest:dev & echo "done" && npx wait-on tcp:3009 && npx wait-on tcp:3012 && npx nx run-many --target=e2e --projects=manifest-webpack-host --parallel=1 && npx kill-port 3013 3009 3010 3011 3012
+ run: pnpm run app:manifest:dev & echo "done" && npx wait-on tcp:3009 && npx wait-on tcp:3012 && npx wait-on http://127.0.0.1:4001/ && npx nx run-many --target=e2e --projects=manifest-webpack-host --parallel=1 && npx kill-port 3013 3009 3010 3011 3012 4001
diff --git a/apps/manifest-demo/3009-webpack-provider/tsconfig.app.json b/apps/manifest-demo/3009-webpack-provider/tsconfig.app.json
index a7eb506691..a45db13b46 100644
--- a/apps/manifest-demo/3009-webpack-provider/tsconfig.app.json
+++ b/apps/manifest-demo/3009-webpack-provider/tsconfig.app.json
@@ -1,6 +1,16 @@
{
- "extends": "./tsconfig.json",
+ "extends": "../../../tsconfig.base.json",
"compilerOptions": {
+ "jsx": "react-jsx",
+ "allowJs": true,
+ "esModuleInterop": true,
+ "allowSyntheticDefaultImports": true,
+ "forceConsistentCasingInFileNames": true,
+ "strict": true,
+ "noImplicitOverride": true,
+ "noPropertyAccessFromIndexSignature": true,
+ "noImplicitReturns": true,
+ "noFallthroughCasesInSwitch": true,
"outDir": "../../../dist/out-tsc",
"types": [
"node",
diff --git a/apps/manifest-demo/3009-webpack-provider/tsconfig.json b/apps/manifest-demo/3009-webpack-provider/tsconfig.json
index e4c42c6665..a45db13b46 100644
--- a/apps/manifest-demo/3009-webpack-provider/tsconfig.json
+++ b/apps/manifest-demo/3009-webpack-provider/tsconfig.json
@@ -10,12 +10,29 @@
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
- "noFallthroughCasesInSwitch": true
+ "noFallthroughCasesInSwitch": true,
+ "outDir": "../../../dist/out-tsc",
+ "types": [
+ "node",
+ "@nx/react/typings/cssmodule.d.ts",
+ "@nx/react/typings/image.d.ts"
+ ]
},
- "files": [],
- "references": [
- {
- "path": "./tsconfig.app.json"
- }
- ]
+ "files": [
+ "../../../node_modules/@nx/react/typings/cssmodule.d.ts",
+ "../../../node_modules/@nx/react/typings/image.d.ts"
+ ],
+ "exclude": [
+ "jest.config.ts",
+ "**/*.spec.ts",
+ "**/*.test.ts",
+ "**/*.spec.tsx",
+ "**/*.test.tsx",
+ "**/*.spec.js",
+ "**/*.test.js",
+ "**/*.spec.jsx",
+ "**/*.test.jsx",
+ "dist/**"
+ ],
+ "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
}
diff --git a/apps/manifest-demo/3010-rspack-provider/package.json b/apps/manifest-demo/3010-rspack-provider/package.json
index e557608b5e..1ff74ca18f 100644
--- a/apps/manifest-demo/3010-rspack-provider/package.json
+++ b/apps/manifest-demo/3010-rspack-provider/package.json
@@ -9,6 +9,7 @@
"@rspack/plugin-react-refresh": "0.5.9"
},
"dependencies": {
- "antd": "4.24.15"
+ "antd": "4.24.15",
+ "react-router-dom": "^6.23.1"
}
}
diff --git a/apps/manifest-demo/3010-rspack-provider/rspack.config.js b/apps/manifest-demo/3010-rspack-provider/rspack.config.js
index a218319bc6..fb159c9621 100644
--- a/apps/manifest-demo/3010-rspack-provider/rspack.config.js
+++ b/apps/manifest-demo/3010-rspack-provider/rspack.config.js
@@ -66,6 +66,7 @@ module.exports = composePlugins(
'react-dom': {},
'react-dom/': {},
},
+ dataPrefetch: true,
}),
);
(config.devServer = {
diff --git a/apps/manifest-demo/3010-rspack-provider/src/App.tsx b/apps/manifest-demo/3010-rspack-provider/src/App.tsx
index a7d1ac1bdc..0dc66a43c1 100644
--- a/apps/manifest-demo/3010-rspack-provider/src/App.tsx
+++ b/apps/manifest-demo/3010-rspack-provider/src/App.tsx
@@ -1,4 +1,6 @@
import LocalButton from './Button';
+import { Await } from 'react-router-dom';
+console.log(Await);
const App = () => (
diff --git a/apps/manifest-demo/webpack-host/src/App.tsx b/apps/manifest-demo/webpack-host/src/App.tsx
index 4f818f509f..9514d598c7 100644
--- a/apps/manifest-demo/webpack-host/src/App.tsx
+++ b/apps/manifest-demo/webpack-host/src/App.tsx
@@ -1,4 +1,6 @@
import React, { Suspense, lazy } from 'react';
+// @ts-ignore
+import ReactComponent from 'modern-js-provider/react-component';
import TestRemoteHook from './test-remote-hook';
import { loadRemote } from '@module-federation/runtime';
import LocalBtn from './components/ButtonOldAnt';
@@ -29,6 +31,7 @@ const WebpackPngRemote = lazy(() => import('remote1/WebpackPng'));
const App = () => (
+
Manifest Basic Usage
check static remote
diff --git a/apps/manifest-demo/webpack-host/webpack.config.js b/apps/manifest-demo/webpack-host/webpack.config.js
index 98ec444535..b0fd705f0b 100644
--- a/apps/manifest-demo/webpack-host/webpack.config.js
+++ b/apps/manifest-demo/webpack-host/webpack.config.js
@@ -20,6 +20,7 @@ module.exports = composePlugins(withNx(), withReact(), (config, context) => {
'rspack_manifest_provider@http://localhost:3011/mf-manifest.json',
'js-entry-provider':
'rspack_js_entry_provider@http://localhost:3012/remoteEntry.js',
+ 'modern-js-provider': 'app1@http://127.0.0.1:4001/mf-manifest.json',
},
filename: 'remoteEntry.js',
exposes: {
diff --git a/apps/modernjs/cypress/e2e/app.cy.ts b/apps/modernjs/cypress/e2e/app.cy.ts
index 9e9fb59fc4..1b05cf1a47 100644
--- a/apps/modernjs/cypress/e2e/app.cy.ts
+++ b/apps/modernjs/cypress/e2e/app.cy.ts
@@ -3,7 +3,7 @@ describe('modernjs/', () => {
describe('Welcome message', () => {
it('should display welcome message', () => {
- cy.get('.title').contains('Welcome');
+ cy.get('.container-box').contains('Resend request with parameters');
});
});
});
diff --git a/apps/modernjs/modern.config.ts b/apps/modernjs/modern.config.ts
index 58a9096391..78d2a9373f 100644
--- a/apps/modernjs/modern.config.ts
+++ b/apps/modernjs/modern.config.ts
@@ -32,7 +32,8 @@ export default defineConfig({
},
webpack: (config, { webpack, appendPlugins }) => {
if (config?.output) {
- config.output.publicPath = 'http://localhost:4001/';
+ config.output.publicPath = 'http://127.0.0.1:4001/';
+ config.output.uniqueName = 'modern-js-app1';
}
appendPlugins([
@@ -44,12 +45,14 @@ export default defineConfig({
name: 'app1',
exposes: {
'./thing': './src/test.ts',
+ './react-component': './src/components/react-component.tsx',
},
runtimePlugins: ['./runtimePlugin.ts'],
shared: {
react: { singleton: true },
'react-dom': { singleton: true },
},
+ dataPrefetch: true,
}),
]);
},
diff --git a/apps/modernjs/src/components/react-component.prefetch.ts b/apps/modernjs/src/components/react-component.prefetch.ts
new file mode 100644
index 0000000000..f836b6b7a2
--- /dev/null
+++ b/apps/modernjs/src/components/react-component.prefetch.ts
@@ -0,0 +1,19 @@
+import { defer } from '@modern-js/runtime/router';
+import React from 'react';
+
+console.log(React);
+const defaultVal = {
+ data: {
+ id: 1,
+ title: 'A Prefetch Title',
+ },
+};
+
+export default (params = defaultVal) =>
+ defer({
+ userInfo: new Promise(resolve => {
+ setTimeout(() => {
+ resolve(params);
+ }, 2000);
+ }),
+ });
diff --git a/apps/modernjs/src/components/react-component.tsx b/apps/modernjs/src/components/react-component.tsx
new file mode 100644
index 0000000000..19eea740c0
--- /dev/null
+++ b/apps/modernjs/src/components/react-component.tsx
@@ -0,0 +1,44 @@
+import { Suspense } from 'react';
+import { usePrefetch } from '@module-federation/enhanced/prefetch';
+import { Await } from '@modern-js/runtime/router';
+
+interface UserInfo {
+ id: number;
+ title: string;
+}
+const reFetchParams = {
+ data: {
+ id: 2,
+ title: 'Another Prefetch Title',
+ },
+};
+
+const ReactComponent = () => {
+ const [prefetchResult, reFetchUserInfo] = usePrefetch({
+ id: 'app1/react-component',
+ // Optional parameters, required after using defer
+ deferId: 'userInfo',
+ });
+
+ return (
+ <>
+ reFetchUserInfo(reFetchParams)}>
+ Resend request with parameters
+
+ Loading...}>
+ (
+
+
{userInfo.data.id}
+
{userInfo.data.title}
+
+ )}
+ />
+
+ >
+ );
+};
+
+export default ReactComponent;
diff --git a/apps/modernjs/src/routes/page.tsx b/apps/modernjs/src/routes/page.tsx
index 5c8d48fd83..e22d30c11a 100644
--- a/apps/modernjs/src/routes/page.tsx
+++ b/apps/modernjs/src/routes/page.tsx
@@ -1,5 +1,6 @@
// @ts-nocheck
import { Helmet } from '@modern-js/runtime/head';
+import Component from '../components/react-component';
import './index.css';
const Index = () => (
@@ -87,6 +88,7 @@ const Index = () => (
+
);
diff --git a/apps/website-new/docs/en/guide/_meta.json b/apps/website-new/docs/en/guide/_meta.json
index 4188a69d56..17fba4f39f 100644
--- a/apps/website-new/docs/en/guide/_meta.json
+++ b/apps/website-new/docs/en/guide/_meta.json
@@ -13,5 +13,10 @@
"type": "dir",
"name": "framework",
"label": "Frameworks"
+ },
+ {
+ "type": "dir",
+ "name": "performance",
+ "label": "Performance"
}
]
diff --git a/apps/website-new/docs/en/guide/performance/_meta.json b/apps/website-new/docs/en/guide/performance/_meta.json
new file mode 100644
index 0000000000..033162d887
--- /dev/null
+++ b/apps/website-new/docs/en/guide/performance/_meta.json
@@ -0,0 +1 @@
+["prefetch"]
diff --git a/apps/website-new/docs/en/guide/performance/prefetch.mdx b/apps/website-new/docs/en/guide/performance/prefetch.mdx
new file mode 100644
index 0000000000..33ad9b21e7
--- /dev/null
+++ b/apps/website-new/docs/en/guide/performance/prefetch.mdx
@@ -0,0 +1,288 @@
+# Data Prefetch
+
+:::warning
+This function is not currently supported in Rspack provider projects.
+:::
+
+## What is Data Prefetch
+Data Prefetch can prefetch remote module API requests in parallel with the loading of js and css, improving the speed of the first screen.
+
+- The normal loading process for consumers:
+
+Host HTML (consumer HTML) -> Host main.js (consumer entry js) -> Host fetch (consumer authentication and other pre-actions) -> Provider main.js (producer entry js) -> Provider fetch (producer sends requests)
+![](@public/guide/performance/data-prefetch/common.jpg)
+- The loading process after using Prefetch
+![](@public/guide/performance/data-prefetch/prefetch.jpg)
+
+As you can see, the producer's request is moved forward to be parallel with some js, **currently in the simplest scenario with no pre-operations, the first screen can see an improvement of tens to hundreds of milliseconds, theoretically second screens can fully achieve render on load**, and in scenarios with long pre-processes, the overall rendering speed of the module can be greatly improved.
+
+## How to use
+1. Install the `@module-federation/enhanced` package for both `producer` and `consumer`.
+
+import { Tab, Tabs } from '@theme';
+
+
+
+```bash
+npm install @module-federation/enhanced
+```
+
+
+```bash
+yarn add @module-federation/enhanced
+```
+
+
+```bash
+pnpm add @module-federation/enhanced
+```
+
+
+
+2. In the producer project, create a `.prefetch.ts` or `.prefetch.js` file in the same directory as the expose module. For example, given the following exposes:
+```ts title=rsbuild(webpack).config.ts
+new ModuleFederationPlugin({
+ exposes: {
+ '.': './src/index.tsx',
+ './Button': './src/Button.tsx',
+ },
+ // ...
+})
+```
+In this case, the producer project has two `exposes`: `.` and `./Button`.
+So you can create two prefetch files `index.prefetch.ts` and `Button.prefetch.ts` under `src`. Here's an example for `Button`:
+
+**Note: exported functions must be either default exported or end with Prefetch (case insensitive) to be recognized as Prefetch functions**
+```ts title=Button.prefetch.ts
+// Here we use the defer API provided by react-router-dom as an example.
+// Whether to use this API depends on your needs.
+// Refer to the FAQ: "Why use defer, Suspense, Await components".
+// You can install this package with npm install react-router-dom
+import { defer } from 'react-router-dom';
+
+const defaultVal = {
+ data: {
+ id: 1,
+ title: 'A Prefetch Title',
+ }
+};
+
+// Note: exported functions must be either default exported or end with Prefetch (case insensitive) to be recognized as Prefetch functions
+export default (params = defaultVal) => defer({
+ userInfo: new Promise(resolve => {
+ setTimeout(() => {
+ resolve(params);
+ }, 2000);
+ })
+})
+```
+
+In `Button`
+```tsx title=Button.tsx
+import { Suspense } from 'react';
+import { usePrefetch } from '@module-federation/enhanced/prefetch';
+import { Await } from 'react-router-dom';
+
+interface UserInfo {
+ id: number;
+ title: string;
+};
+const reFetchParams = {
+ data: {
+ id: 2,
+ title: 'Another Prefetch Title',
+ }
+}
+export default function Button() {
+ const [prefetchResult, reFetchUserInfo] = usePrefetch({
+ // Corresponding to (name + expose) in ModuleFederationPlugin, e.g., `@mf/app2/Button` for consuming `Button.prefetch.ts`
+ id: '@mf/app2/Button',
+ // Optional, required if using defer
+ deferId: 'userInfo',
+ // Default export usually doesn't need functionId. This is for illustration.
+ // If not a default export, the function name should be provided.
+ // functionId: 'default',
+ });
+
+ return (
+ <>
+ reFetchUserInfo(reFetchParams)}>Resend request with parameters
+ Loading...}>
+ (
+
+
{userInfo.data.id}
+
{userInfo.data.title}
+
+ )}
+ />
+
+ >
+ )
+};
+```
+
+3. Set `dataPrefetch`: true in the producer's ModuleFederationPlugin configuration
+```ts
+ new ModuleFederationPlugin({
+ // ...
+ dataPrefetch: true
+ }),
+```
+
+With this setup, interface prefetching is completed. After the consumer uses `Button`, the interface request will be sent out early (when loading js resources, instead of waiting for the component to render).
+In the example above, `Button` will first render `loading...`, then after 2 seconds, display the data.
+Clicking `Resend request with parameters` will resend the request with parameters, updating the component.
+
+## Viewing Optimization Effects
+Open log mode in the browser console to view outputs (it is best to simulate user scenarios under browser caching mode, otherwise the data may be inaccurate).
+The default optimization effect is data3 minus data1 (simulating user requests in `useEffect`). If your request is not sent in `useEffect`, you can manually call `performance.now()` where the interface is executed to subtract data1.
+```ts
+localStorage.setItem('FEDERATION_DEBUG', 1)
+```
+![](@public/guide/performance/data-prefetch/log.jpg)
+
+## API
+### usePrefetch
+#### Function
+- Used to retrieve prefetch data results and control refetching.
+
+#### Type
+```ts
+type Options = {
+ id: string; // Required. Corresponds to (name + expose) in the producer MF configuration, e.g., `@mf/app2/Button` for consuming `Button.prefetch.ts`
+ functionId?: string; // Optional (default is 'default'). Used to get the export function name in .prefetch.ts files. The function must end with Prefetch (case insensitive)
+ deferId?: string; // Optional (required if using defer). If using defer, the function returns an object with multiple keys corresponding to multiple requests. deferId is a key in this object used to get the specific request.
+ cacheStrategy?: () => boolean; // Optional. Generally, this is managed by the framework and controls whether to update the request result cache. It currently refreshes the cache after the component is unmounted or after manually executing the reFetch function.
+} => [
+ Promise,
+ reFetch: (refetchParams?: refetchParams) => void, // Used to re-send requests, typically for scenarios where the component's internal state changes and the interface needs to re-request data. Calling this function will resend and update the request result cache.
+];
+
+type refetchParams: any; // Used to send parameters with the request when the component refetches.
+```
+
+#### Usage
+```ts
+import { Suspense } from 'react';
+import { usePrefetch } from '@module-federation/enhanced/prefetch';
+import { Await } from 'react-router-dom';
+
+export const Button = () => {
+ const [userInfoPrefetch, reFetchUserInfo] = usePrefetch({
+ // Corresponding to (name + expose) in the producer MF configuration, e.g., `@mf/app2/Button` for consuming `Button.prefetch.ts`
+ id: '@mf/app2/Button',
+ // Optional, required if using defer
+ deferId: 'userInfo'
+ // Default export usually doesn't need functionId. This is for illustration.
+ // If not a default export, the function name should be provided.
+ // functionId: 'default',
+ });
+
+ return (
+ <>
+ reFetchUserInfo(reFetchParams)}>Resend request with parameters
+ Loading...}>
+ (
+
+
{userInfo.data.id}
+
{userInfo.data.title}
+
+ )}
+ />
+
+ <>
+ )
+}
+```
+
+### loadRemote
+#### Function
+If users manually call the [loadRemote](/guide/basic/runtime.html#loadremote) API in the consumer project, it will be considered that the consumer wishes to load both the producer's static resources and prefetch the interface request. This can give the project faster rendering speeds, especially for scenarios where the first screen has pre-requests or where it is desired for second screens to be rendered immediately.
+#### Usage
+```ts
+import { loadRemote } from '@module-federation/enhanced/runtime';
+
+loadRemote('@mf/app2/Button');
+```
+
+#### Note
+This may cause data caching issues. The producer will prioritize using the prefetched interface results (the user may have already modified the server-side data through interaction). In such cases, outdated data might be used for rendering. Please use this feature according to your project's needs.
+
+## Frequently Asked Questions
+
+### 1. Is there a difference with React Router v6's [Data Loader](https://reactrouter.com/en/main/route/loader)?
+React Router's Data Loader can only be used in monolithic projects, it cannot be reused across projects. Additionally, Data Loader is bound to routes, not modules (exposes). Data Prefetch is more suitable for remote loading scenarios.
+
+### 2. Why use defer, Suspense, and Await components? [Reference link](https://reactrouter.com/en/main/guides/deferred)
+The defer and Await components are APIs and components provided by React Router v6 for handling data loading and rendering during the loading phase. They are typically used in conjunction with React's Suspense to achieve: rendering loading -> rendering content process. As you can see, defer returns an object. When the Prefetch function is executed, all the keys in the object corresponding to the requests (i.e., values) are sent out at once. defer will track the states of these Promises, working with Suspense and Await to complete the rendering, and these requests will not block the component's rendering (the component will display loading... until the component finishes rendering).
+
+### 3. Can I not use defer, Suspense, and Await?
+Yes, but if the exported function contains blocking operations (such as an await or a Promise), the component will wait for the function to complete before rendering. Even if the component's content is already loaded, the component may still wait for the interface to complete before rendering. For example:
+```ts
+export default (params) => (
+ new Promise(resolve => {
+ setTimeout(() => {
+ resolve(params);
+ }, 2000);
+ })
+)
+```
+
+### 4. Why not defer everything by default?
+To make the developer's scenario more controllable. In some scenarios, developers may prefer the user to see a complete page all at once, rather than rendering loading. This allows developers to better balance the scenario. [Reference](https://reactrouter.com/en/main/guides/deferred#why-not-defer-everything-by-default)
+
+### 5. Can Prefetch carry parameters?
+The initial request, due to the parallel nature of request time and js resource loading, does not support passing parameters from within the component. You can manually set default values. The usePrefetch function returns a reFetch function, which can be used to resend the request with parameters and update data within the component.
+
+### 6. How to minimally modify the business for Prefetch?
+1. Place the interface that needs to be prefetched into the `.prefetch.ts` file.
+2. Wrap the prefetch function with `defer` and return an object (you can also directly return an object. If you return a value, it will block with the component js loading).
+3. In the business component, requests generally sent in `useEffect`:
+```ts title=Button.tsx
+import { useState, useEffect } from 'react';
+import { usePrefetch } from '@module-federation/enhanced/prefetch';
+
+export const Button = () => {
+ const [state, setState] = useState(defaultVal);
+ const [userInfoPrefetch, reFetchUserInfo] = usePrefetch({
+ // Corresponding to (name + expose) in producer MF configuration, e.g., `@mf/app2/Button` for consuming `Button.prefetch.ts`
+ id: '@mf/app2/Button',
+ // Optional parameter, required if using defer
+ deferId: 'userInfo',
+ // Default export usually doesn't need functionId. This is for illustration.
+ // If not default export, the function name should be provided.
+ // functionId: 'default',
+ });
+
+ useEffect(() => {
+ // Requests are commonly sent here in normal scenarios
+ userInfoPrefetch
+ .then(data => (
+ // Update data
+ setState(data)
+ ));
+ }, []);
+
+ return (
+ <>{state.defaultVal}>
+ )
+}
+```
+
+### 7. Why does the Prefetch function I defined not work?
+Note that exported functions must be either default exported or end with Prefetch (case insensitive) to be recognized as Prefetch functions.
+
+### 8. Can modules optimize performance for second screens?
+Yes, the performance improvement is quite significant. Since Data Prefetch is for all expose modules, the second screen modules can also optimize performance.
+```ts
+import { loadRemote } from '@module-federation/enhanced/runtime';
+
+loadRemote('@mf/app2/Button');
+```
+
+### 9. What if I want to use it with Vue or other frameworks?
+We provide a universal Web API but have not yet provided hooks like `usePrefetch` for Vue or other frameworks. We will support this in the future.
diff --git a/apps/website-new/docs/public/guide/performance/data-prefetch/common.jpg b/apps/website-new/docs/public/guide/performance/data-prefetch/common.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..e19fbd9ae490499e684fc359a88ab794195f9d40
GIT binary patch
literal 135618
zcmb??2UL^Ix^Czq1nDh7=_n9-2~9zH<&-={px!)@Q+6U^I>Hs1l0D$Q7
z2l$Nzs9e_m-|UY`{@-S}9R0f!KzD_xjM9LFh#NpmM?^wL^t%^u<8qP2#Ka_jEcoB-
z3MCOaDH$;d#Z{`y4t}%%A`)U!A`&WU>MN8Kl*HFA2au4GkyBiuqi5g}r(|Yf1RO*wz1$mrqjqo{IgzA^&|N--y~i
z0a-bX2R=2Et4EHg$Yd!QHFXmw7r*dlFB>l3%W=6P62RrU{(WIY|Mp(W%g3g403u>y
zG79o5RODpDWF%yN{2wHAq+I%Thh+5P%E+W@at4Vf?l_JBy@l~fS*6O{~Ig)E>Ie!
zs;UKwW#-krb3xnUnYmPd;5R
z9g8`t>3cZz8IlcO;dve8?)R>u+_@E=h!M8uA+>Jg2O0L(EtGX
zMsi>nNmj}T@k~KcuT+wJjo(8p20%#Ngil)@l0fy*U;O}d1l1I>ILC>)3N4}-7H_&*
z+@C#`PVW4kKtH}^*xZJ=#@E#FZp>S*{NZMlz>zG(toj*jP!!cb2Alx>p`#mPqe%n|uT=z{_wc(lLdunB4ozf_tgY
zU#s<7JZDV#*nc%DFI85(bE`4>trfygG%-D
zD5DeabM9mpYHv`uZ_d94n_9dy5?N~`S67C|u6ru45F7#pq8_J`hWi6uc_Zqw-?`1Y
z-xMA#sBABCkY6RsXGa`9}>hDU)zBDys1x4S%InGyS4xN*fgw%lMDp
z28%qdYf-T?{Lz!QnTJ97aU{IT2NGgX;>k0T-tiS>(y%L>39t4o-gEDX_}_S_L7Tv%
zWUQU_N{Z)o{10r}^&I9SDG#~ftcejyRM23FIFMJjEc+#WZ|4n&lx5{DaB%oB$3(08
z4_*2PGe6I%7OrM+d>8F&5q)@{8BOZzfBJS00((b02Fcp>0~pp
zn6kmat8)S8*wDqn&%Xhy0fCT?>q;F=-ObU2mr{^C_&4@J+fWTkSJW-sk}O5?%3`J;
zFN$y`1w03QuNXHkhMaWn6x*jI`4`X4)MEG_-rhLqKcO4w8B!Xs?_OC`<_se@oN+QW
z4sAde@#0@TE0y1N2`#N_!r3);ItJ3bT8RlzUOdqp0RT`D#4zh$VKhDdsr5^-f5AKZ
z8j_MHEci>~lcx<;&RL*G$98@Bk)Fd^bN%W>oGr3-hlfq{O(vteqW&P&ApyVkT9ON!|}H7espW}5;_C!F8sHmN|+ei(E@sxmZV
zYymJ;YvzEHBJKoFTGU$LB%g_Q1$&Gp2$c^BvLG#<@^IGo9W}f?^cQbS>Af>dtgH}G
zN3R0Yqf5nG9Z;FD2=Y6lvo&<;
zF-n=KYf&+=|8TZHmu9@z#`SvTbr%(Y0~!r<%=)%a`nxn+XA4^ik6jaGzcym$vB-|c
z>rVgGajiwX5!lbwXMS7ToJ1cQG>OVV&At2MfoF%3V)T?)=QL<`7+fWwDMu3wItjbc
zyF>>HmOBkC?pK{9@2iz16|QkH|K5X-?cPlD_)*@^mZtx6Z`d-BEOPUYJW
z7wlPD*sBE6x@3wP3h_C5zdO6YCxnOtURv;du1mxZh@@ZvT=Vf$2p`welUZT8b`}N^
z@CM)azJCATrjDiYM)Y0?AQI)qE_{=k1)RfVd6PyPHiB}CBFt|v@Y#r3wiSGt_Exi<_z;-jh9Ni?RpMFclAvS+`aZLV;WFFNct%(dCt0D4Zgp^)nr
z|22#ERrv*hrH+a47q-?&ow=Nz@423RgHPu((34dj$oajO<%iLt+2PGn2thVru|uywPVcFg~x
z3~re~k?ZxCvQ)`^41`mNZ84-~N2*%lIzM+iwWRI_H66#(_B`04P@!81RZS3CPuhOd
zEaDLN{7K%C7y)d#?eyNKFvlpR
z0(A-i%(^om6MTg;k%*LTviQ#`Lu2==
zt#1F$^u^uc67>no@0;(3&hkdO!kgz@8S5}9|92f7NNwVjEosHhs>{
zw;<#{`5N6{b;|!d>Q6P}pA4AZ%P78&j_zN$Z`7s#URvEYStKh|nvRYkiy3UYGOenr
z>urX7`c$8ePOi(Yp9Xk&rv0hQz5P{Aso}%RAkA{X>H{nJZW0}X_^ekyQH!Ih>IfQp
z6o$y4qm$Hf)D2U;xLl*f|2VfA*GeMat##HUIu_yvtypdCw}s)lw?zzK(NqqRi0jvH
zE?DsNG%D`%CNMN@gK(xlCs4Bm?wLWzKE_PQ&tBg8ahFy^q6BZ*jk>gr9}N_xAWX_hIKM?L43{
z>$8t@xPZH)1d!7>n%%QKJaG!mqpy;*Z8?t(uQS*FNJnh@JPV_&R4pM^H*XlWaESVkRMDenn6!H%ESu=T5%kwcU*y+OLAr|3Y74Kw5fB;x}m`A;I(bJqzJ$@x{I8}
zrS;eFoS@9BZg?u~$*T6g@>Mr7!peMZXvcQXhX()KW5fNQwfH<+3UVOLru7N70=C;4
zJbcu+M54zOS40#!6ZOOvAF2Xk>Z50C9wz`zxE9t%Q5tp07naS`=U|uGhT`13ihX<->Q5)7zyriEWzZS5VAj*{|`*}Fl
z5*$!BJ9aOJ-OUs8t1O0J8~+As2D&K?x+zHSBOyqV*w+YdfR$5}jNo3qv?T63YhL_>zooWg!Ws>n
zQs7ben266-Z}&Ds_3drDAzguEW2U;pA?tnG(~SK@l0z$A=7$1K#%Rk~$~B~~
zWf66Rg(Pq^1q9@}dAy*(om3@5b=R}JiUzE_E7uwHd_)|U2Bs|B<{2EY
zuL-Y09G
zzoXZfOzj`&1whd%Rv3%CD=tY*cs?<$3AQiTR84A**Dqop^L!3`8e&F!+nX7<5%gBQ-5(rBSiRU@_rdyS1%wDC$X
zN0Dh482Y2zly$;M_vwD^@jdtN8Sce=#id2OGVD>Ct54o+WG;E15iBjbS192;IAR&l
z)rlA7wZ`p)w=wJ}L}+&$c?TQVZgI?`EXIL|W}`rnE9y^S@))kXB#h-I}iW
znNdJuQeS(mrO>8$2<=Rbv$AxHo{{>ufH+mei}Ps`z&-$DGZdFL@VzeYA97Nv*_tu+p)>NSj)?rY`0?`G)Y6=zsAOZRvH83
zo#dkO!UzNHmxp7d8psB$TmoM!;!0p3Hl3D{rO{~H^qjSGJ0P`T^PH-dy)
zbzY}R;H-I~AXr+m)uhJ|`+oDTqj-)zl^sn04JomVxAO}980Qtjgtdz*0bdj3iNnZULw;w5zKqDk^KGYMp}ovPr{x1ygrMB#S)tokt4-}eubAEo
zJ@;%`x`Qw%;AIz>inGi~RS-1^bs$Qo6
z@xFNREP3hXhJZaOVtXzo$?+FcK{Cjse`>c;Ut&BhiO&%4GsNC;oyIUmo_uY0?s(_i
zS2)yHBr&y)p}%|2VBE`uMLqjr@TfKAkhV(np)-5}TOvXj(#F(d#m*#}VLRXaO)bT6
zGqGFTJpq|lS?$nPXz9!gLv+J<5m8Lf!{I;Ul^@mQChlx_7&!wc@
zdZ3STz$1g1S)aP+?fdmtwG~2(Q+Gvz7s}4CR604cddxa1hREKT*TO~(-xccBj#F1j
z(ZbCdS~Lu#4i7{Z#gYm`6IOtO;1%NWLtSiA6OZj(s12VO8;EcOWWS`bLR%0G7`WJQ%`Zp;RLXvgT~Qjdd&fu(T^2
zP_lu=Y`MAzVY*o#)7Xfn&A*Fz&|r3eX~2JvIedH=Uayg87D=vC`KZ9p!;#-)y|i^_
zSNtcb+1Qlt+b0v#(=t>D@W9u5pWOOQOGCl-HG7e-W4$q3R7TRKl3os2CZ6Mei|8K}
ze^WpC68}VmpeHtWJv34>iZkN+XM0N5GoqCX8j`5GG^sjb*&DmwX~ceTEtRLSPuw85
zD1oBeMG+ZwdwExZ@HMdQzFtaG$!LU#oTFIa`?6lP*U0|5gtG3hF63B*u`k_dREgXB
zCR5Xgrdq0dz?zAWlJ=TZA*N2lhXYuOy%5`*(hvcIPmF4LE=KowNA#nS>$es?l2>l>
zwyL~%o#xT=@ZoKjnq}amrNSPstpA`g-vNg1wt(c{k6oMcyNAjOP|riJ4~>nKeis}I
z8hW&fSmu=Vp+*;aFo{a^*4mcKvS+7NuZFCoKW`2#Rpwbkto-Y2!%$^+tOl$ZGXvis
zSgroxc_}N5>2Ul>L)YJ}mC9Lb>v6-ozt(9w859ILdTBZ+
zB5eYeXMmfqD*V04^grJeG0L=?EkoPmb+)VJ*Sur;<_*>=h?k|Gmn;?s>lFi|W=jKzIy
zu9rw5^eOOr)ucS`dz6|=$*rJrSG1uQ?BVRvi!Y`s$!BezUKqY%!J<-0@=`Fy%)QD%
zk_QSu?r?MSo`#z2k?qbj?J9-9o!YRWR+6I~rhUv9;S$}7^i_N-N;`ZL99@%&{PQb)YnN;UqGvYRjlPye`YpoGRbu14`?t7lz$%Iv|Qo_gW
z+{=#h@!HP9@~FJ}*e_qtisw6i$Z|xOEt=~@xr|2D1g5it6kl3Ct65ZXN4Ib(>Vux<
z7roy+Rr|go>I(V++SgKEB}GER)kj^uQH|Sx1OzvGm7^=DHTtdRP9U)0MEak^$?!NoQ9qa?R=b>8#*`##r;DssN$CtshEuI-^Y_>6TLYP38~
zCKmV4*+KDqvoy=a&8&!-g{XN`9gp^LYvGv|i~bwkcOFqr(-it{^Cwo*$c=auk7ju$
z&of0Fe`d9+=I0(8K|ilm{~YFKj%+Y+x+v_fJ3YHV5h@F6B-w0)5T|u!kA|Hpn2cqw
zN{CK-C*>hzA!k~C-hh)j!lXY92SvQIHEyKD9?@qzcCPklBY%B*>&eu
z&resR`KHHaBI>2R9*<>040rlh^Y%>46sRXw&)05>A7q}!RI(It3f^I$qF
z<$E7z`%cx66RyKU}pd)AV{<)HU;?y=B&5;q@;OX6-
zpUB0A#)%G)cm8RpvFMP+53Zle8_Z6t+7Ju?@8fKeQ)MmMVlokcBr~@g|FhQ
zHTmE-U;>9KWCf(O-UX#WJ(jMcdacIEJ5!p;az8)y2X+6{gliEy^2Z(BZm1e#@0B}9
zJsTl=Ud!L7l4@wNXdEq;Dv|ne__jbo!=AK|>)|MbgOGauxGfWwiRB09S2W3t8hmG4
z@!zgl|G@*m&uCJDsO>|JdU&Z
z0q4(6SkH4XHtY&N!;XMuvnGag3X^iDCI=LsnF;UvM76HS^e87>TP^IUFI`!Bvd2GX
zQMj(&dsNxjt7ERBZjE`dYH@4U!cYxfiVkfEe|-WkJ<4D`xg%bod@57t8C@TJ+giuw
zI`4=(taYOavA*Zzdv@`B{hGOVXinQ;ctN?tE#ZLfZ_x+gm+W5kw8j4M#Hd$!Gu@+1
z>Uh#{KThcW{blEaUO&?8hy&cguh&Xx9#y<<%bz1DSN+9t3aBPd#A?+%PL-TlsS=(w
z)$*fi*QK<)G~Rgc4R>9NaxRYNrKzcvczc=wtDYEgacwpZ^3ZHI+uSCoJN|(41*oPa!WA*`y+FwrmyGwc+lMGem9fOljr|zNFDn}s
zPVYXgw%Dtv^OdH?S?)DkY1OwMT5Z%7u
zgKjwG#mMg#J-)wyoE9;0FXR^!3Ek-6Lhuc@_0+vCPi;O5N?p~EVnWO8)hC=Id~3Db
zKg@}ILC?S!YczQo{RP>h)>F;CI)z+*QQLSVD(p;^+5+tC#ldWd90R
zZ^L^Dl9DXk89vqhTJf3$aYpyENG!m
z18oV)n5pW~)5p)sXD+?adVJ%Q=^H)%QR1Cvr5G~aFSgWM0)-jvfsVGK0&k_D^@XSp
z4A?53sD^(Fkbk13-;0H242c0N@2`435pN4$jhQyfsvXO1``7`H`z_gFJD)
zifgk|EIc53zBRSg9gj~$Kk!j0ZhqO&7Md~LXlWjQl&!Wf`%2ExHZ?W*BB9bG#$B$$
zN6WW7CP;{erKV-qEt1}zMa@QuN94=P2DsYyQ&SbUqWtfK%B9Ad3rZ|%U0(i`dF+!f
z^N&hu<);#CY|>vo%CED=uY@PB-@e(gSq}+c1y0JRZ*`AVG_DF+3l(LCQ%SFx;fwQ=
zRk|?P*b7L}2a^I5V52wq2XC4bd8;=SRZ~+y|BnOGrhPxMpn|f3LeM8EBrpM2I?sj#
zokQs5@>=aa+y&A4&lM@BWPThjSKAH4R|+J^k0{dagJQ&uSnp8I-&`5FRazC#7pk^S
zOy$&nprOMojkaomOLG97RvSv62k(>=5sqQ-9Rg}xn8RAh+WD2VuC3c|KruSw>i}<2
zVXKkmi;Y;R>SwY-YVU)Z3d)Q7SZzePyZz?582cLCVP;5>@TZvk6C7WDLC)JbS{+n}
z@w`V#<$cndk{FTZ^*Yg+K0Z%~uh%7qA@z3-BRBqC1t+pTFFs4*EtTHw-hI=n?^lHo
zFH^s=4nz*{V!R;1Bl=I;?AmC+*Ze6trmQKGZ`<`kORp7&VswYBi$#e0FzLaRxSB#~
ziT;8KmGnTXz?KQ?*LqA_f@v1w%)pMRK4lTU?)rKoSx`XE`%#w`3j`w~qGOgxx_{8d
zZ#<~rr>SBV-ham2TZfspX^ZgwsIMb=)ovIh{b|NdE3(ubU;c9LDeW2q`~#JdasABD
zUTDOuihE_NHQ^;U%cOxtSc?YHN;dfci<|UglwfJHsj1O#K*Q2itv#$6VLTyI(%(RP
zc>d&(2N|k!`b#=lQ;jyWC{2IB3C&7oI8JY7Od??h0_?S4f$b~7+|9kvG+#W5LOt({
zf6*v1leQ|@ubh5;*cL!j2tC|G-tE%s)whp6+|X&lK}H*I|G*kY;c)Xeb3Pk^q?-vZ
zlCBk!l?Q*|R5GwGk*SqTQD?p2t(To9477MvZ9o4^Je>BeH7Y@&r_OtJ)uX#-Zi`CV
zSVp|_Yzrs&*(3zw`{aGjsau5IWhYPgSxkw9Y>Y&gDqoeU6NStT2IMo+l~
zDxw2$m)oQF->g41N)nHkuM-K^{5%`OJy*h72}rEV
zz7TR6BA?WuuIflSYmkv!B@{p$h`er2_8%!C23Qg&LFb!&6*P)4_%@dwP^tm{8(^Zw
zz_npc;d8D&-k+MRvM{?((=F>wPzmTHJ@zz0i)1#eT7m3C{i)Q%=W(=kw4}M7(ZbY-
zUJ6>UHAxnXx6M@SZngpE?yGH+4?fYfE^-*2JKZoL%LYTNh^Lc37n6n%t7}L+E}|}H
zqb@u144T^Xq;Is54j@v|3t~bqWM*uB5x+m6v4|8;hBnES@n(Mq|2s!~{{P4k3tC@+
zFjN@iggGmqUH=13Jcau^O-yQVU!f!@yq|tGAeTVADUkiDdw
zH?}dA?sm^`Y~R1|Ezz-++oGDoGxmeBf03^>Kj&F|(B
zJ$~hlJvX-yD!eBS%pMgL{U;hFPm!K9U(td7vePA(@^=e&&)(G<5#Yng680zUl3v+HN??`;?_xjotwR{Ae{r^Q0KiBz#B*rqV#!q$s
zJ4w92pXleRcp+<7ZJ-)9WpjpAl2^XFrb&KJMGZAz92=_?@_tX#tIz{+E&jx~xob>Z
zoqT^4;!TZ&T&CHcZ1QXY2th-CCC5dLE3r~BG=^|csxNhZ_97rVh>Ag^&l^Y&%10q!<FKcmq^>LJ6Fo8*~U{TWRvZulBiA(aIQk%0EJX3d*3_7h(dxCNxfhRLGFOr|{k
zp5TH8x|vxMm=7DDwc|2?xP!J3-jkE;Pcj!b?}XKKeeg-m%x}P!N;aV8Os{^^wjq@+
z%ShBgq+sYeta<1_bgOlKXC!7&>HCqY1rx8-xb_(S-Y=H1smZyX
z#a4&M4d%6(cj=i^K0NlzPi|N=)MNRk@gH+%6gU2!J6j)biGi<%|2@G~8pE&lj|3M=
zlWP=yMqvkP(u8=i0y5Z1OF1#t@$7|VMe>fCfOy!*=HgpV%hJCDkOlt|z4%HJ@~2F2
zLb)CWrrvc1Cko-r@nJ7Lt5KQklUFEg*ABtQGhhD|Neqn$hnK(<{5i;7jtm4id4VvX
z1q4%Yx?4@&XXRH=5d21kF{wplFFGy>r#x!M`+3~FZ_IKo-Ez%OVA;DcJ1y1~b_SMk4~RYrb|z+LXpOPnhI6Kehw8~+RW{0FMVP$p(_a|{0I
zt^Z`M|10E*ka?srr)MbZk!FQh=GD_P576Kg74_>HG$Ij!bDCfQKf_Szc|;ZUUbR|X(qI++Vu11Y*-GoR~9r(4g5Wumi3Qpn&)?#_40B@
z;kYJ=!qbA!F&^}huDyjMv@$F|%`!5v&YJVsM+}tk}0+QSzbS~{ZhY`
zvLwa+q*{UjQ;@&@&orCsvI6h3p>4TxB#m!U-MR9+EKggvIY1|1YtBa)mzdL004vdS
zhYM1|?TQktS=l~ZY6PM|ALzWOGOtm4;83Ul!@sBzcxK^T7QCoTZAAE+M&Jf@f*4_2
z#zaj#?CIbG71(GKi9c_0MnroUJ)dB$AAG9vNZa_aRjTfI<1?6tKj=%+0FMQcM;v@1
zkYsGO4tnFmS&V?xXStl&v)=frxYb7o*ZR
zS^yDb+?Cw0%oTtKIlVV1dYuZ}JW`(G5tBA9@k>Z7^1NLt%f#Wt0ZyG!5gy6WFxL5G
zv{j$nTmh$wF7%SL7yb>^z{V1-wTy%T>6EgS-Dr)|RE&;!@hj=+XG0OSQ
z0cT~UJDMMy$s0_h*hbxo48(UKhNq2brCSJZ?d(0n`x9Hqw_ufE2nfR{myS$yL
zkXdC!azgpL+S#BSf7nkr-5{$g-EmkncgClc#|*MAL@WNjE3)8i(E{{P!%fec#+3Sp
z1A6#EDS5Vh=L2e<7I?-@5qRS@hfF?RrDsUbPj7RRq1>U0dQP$woZ!U~``g!P!NKJ(
zr~(!=>4|E4o^S=*7KUfuevreja)ZvFiX9+=+!nwJq$B+202E>X=M(*xrw^*s-@P|6
z?sr#lg0N(mxC4OvBPK0-o@%H?y!)_s9&NWwszBXTtNlz3G<|%l${V3_DQqI~<7y3S
z^;HY6`M0Q&J9QVNaj9Lul%xM&*q`oo{Kv8XyyGFNqk1%@!h4){WgV;wamYDnB*`cv
z8_0?u!xFV-sVMWPgovaTROC(2X&A~vs49%f!^uDX#C_wSeU*^K0*&zT;+6FrkaJz$
zaJdCqUkirLZ6W&!Y;3)gOZ-q&{lT(dlP{FG?&@FhTNy+aO!P)VpN9JcmtR6pp>v|p
zbXz{H`iu(199d$wu`B#CE~A-Po_Ra8@WrnOPi=ik2z-6YgPNP$Y?^)F08NWs?G4SsHeRmucJ5f^Y#an
z-i`XpY%qHS5#!4z^=G8Zb6TfQT4wjm67GM!>vEIIF~Q}|lhqNj2+7X%-W9nPzpE|s
z*nDXz)cu=g=Pag%wQkm1k%)eYhg$w%&O~KbRMU$a{H%noFN{7KqglY4KVGPl}SZQ(AI^V!hE;yGsoU0t1qQu^srANKj{te|Qjj%=<=k4!k^m7;dUZ2^VnPi-yNn+4{1FM}Kf0J{u;h+xLx
zH>_c0nElh>@`lI5KTiFq7>hhlus$6f;%~J-8Y*{kD!AzAm~Z~0CBH>|;!?cGyz|FX
zAX?{Z$AC$*mftTyw(};x%?d9EZB@(JYmRbHMsXgiAAGh5_p?esr>bK8eEluJ8Qp7L
zO+nvckE8gnw#!Ua(3{JQQdty+S)psL5orHopy!MOYJM=AsV$jt9>VhM
zF#inX`!y$4T=?t)eZkyvd?5|Anxa_Tw#$&myZqZRiUju
zSY-t3n``-0_MHoSl9qY6Sh5SLM`t{a*v@ar5;cYQa?P2FX9)XK^*$=C@?I?VY-*^z
zHf8?d5bcAKsWH53+QybGXO*6z630J%+iuyuJ1{%EnxDA0#=HV*DpI^7a%7HFYr*)S
z8%l!Mcicq04O>zJcku5DN+k@ZrC-fs#3!r^edRFhLmkC;45#>O8Km5hziw8xyU-YJ
zUZ?J3?K@hhTod2ogZu_uTcv^=Z|XfkOU8{S?}v#(nd$iT^W)x
zAiv$WXrYAO`jvD{ajPC!q|Nl=lu}tU0);>Ed>1KF1&ow}WSFW1_0%q&XbA}*ZuUT(
zshBNeG8GnG8_Yz{V_0C^1;x<^wN|DRkFPkGeSbUxk$2uUT)$63vZcns!G|8|dr=i<
z7Sre5uvmnc3I4@a+U~w~>e;Y-&k3#G$W54kL1+lxoD_P*S@O0@
z<{;`Y!9m$jf99uj%an7AQD|~&DFX)mNz0R&Zpy~snuO0b$DnWHLtJ$Myf5893&c2X
zssZdC7euOCIU*Q(q)}S!ysw~7!KNzi&oS|-JVqb)*10P~gI!}y<=CeACR2$=_gTyl
z?YmP3a!((R#DQGe=8i&GWl5dYK8p!-n-!cOdsyHH5iQ{fzX8!~UTM>&0x^Pdp=x@H
zQqoD&K`~f_mD%lrQ!j&@7P|DNYqLYyf?6-NC$Skr4(e<3#}jkF48%U?0{=&`#Fk?t
zAN!BD=AT(avJdx^TIg=|2ruF5VW)-hEje>Dvw0qOkWUq=g`p3?U0vx0?`NaL!-iY)
zCFe7~!U40|3owQHGnQcv)=aDh-_ogF_yse2uG3b_^Xf-B60thXd(X;cKua{guAzsS
z?1dRLbog)e%Ey;rXoQOTFlSXWmT)(pp`S6w=j6tNsAM*G&N}R&3|~R^E0O$y+={ow
zanp1#4Sg0t@iSt)5WE#^zvnqL5qT2cRWzcLW^{T~bHhdq6U!BZDeq@Q)>nIK`1huk
zjz&;!6z0a1+36XNcV8IId|zm$`oS~_n*KV*)ub3SJi;Q0NRx8R$-(xr`aS9!A0j^>
zJ%m2#rh1u*cQ{q?)-b-qDS5(mB%fxQ|QpQB{hsPoMKMs
zzV=Ys)SNwKo3i`9uZMpCzKyebenLgD+2Lwd>9=ncQO0UJW5>Q{T*zovA!S5stl`uI
zif`XAuqdS`h*W$w&`6K3rb&BUJx9M<8vL1-XtR}-1P8_iuMwt<
zy}qgJujfNv;N3t#Vr@w>&2+cz0}>|cKYM78cvRzy@bHq#w?K1uFU`P|r&S}(t%b3D
zDL^LzQUBMn1zWK;%axpMs8J%C=X6_wdpkRHY
z-rVLeT*{>+v+9l_#Kf`Jxm;4aTTZP!+nyR`Kmjk4mX6jyUf>NCc;`%Dm(@q9>&xxGRrpF
zmF%fmb5^ZcG(ft~UT;e6XLev!Tod*Tr5#N_I?QAT6=oX+o4h`*yl<{Foi@6M2;A(j
zu>;4{Igg1~Ib5a*)8XY{IkjhpOG3S0{pmKx*sACA3mYtU5iC?rSSjHda^vcAXeozF
zmN^k~{SOBG>%NZLMb{~tZ{J+$33#fDp?(*As0ox_+mIw+LXvO23yI5q@d(^FNy(G>
z?u93>A*H2@H==zSG2A8^Bj3tlScVF%H?;K1a7j3|FnyX=79q!B-?lcYjj`K%wH4J~
z01JLC_9ZP&k>8H4W%*I7N?VpE>QVeO>!6P5jty*~Wy&P4MnL>#f{&S4zfh#YL6iH5
zMapb!zlmkFCt7O8!_SkE6|wE!&pa~Sd?~LHD#Gs|&Qc;POyE|lul%t7)AET6k3W^w
z;2Td3P(l(C8nRX7Rt`Vha!|J5!1$VF)>TWkcsDQk^om}Ypg67=(X$|s3}0T0*Duqw~6m01G|Ai|0e_r?I8S
zj@jS7HO$e(H-Gzfetl57>rz~`4IW63U%0Z^4&g=ZuYifRi5$O#cz(af{UdtUs?7iJ
z9XiNz+!99;_m!hpCDSVHo6PLtK1>4_JLpdfkoC;kmJ;&8?>iBwMriV93OD*086`)b
zlr_2BSiwH`5b-^;^tA1lxf-lyRlV<;%#O`g>femG!K0Y~M}O}~wRdyRr#kV>G`}cP
zlKKs}qG0l^ybyTX8m$xup{~s94b+U-IU;lBZnc%i)ea*=o6Qo~8f_51{zAqcCV^`e
ztPTt+)Owk6!l&fU&2QW>74PNCmCP-eQXa6myw&cW%+a;C)Pt9e#3^SmLXUF>P$@K+
zn$OD2&=H(dTHs^%ydKs^4a+)FLf+3`P~wi_XHMO!Gp~q9C+gc>WH3(Rz2LQwI^;C%
zu;Rfq2gd+|-H2q=$zvfg8JghLidN_Lv4f1JV~;!GMNX~X3!-4(#Mge7HhaMI$)}4lVNuC#H*~{
z2)kX9u4t#myhNw=u5IKBYR%W#FzvM&U?EV(9w(m;qR_%6&eU|OC{yc@%7Jb
zYtDraq$jQR7~HCmYqT#^=e`bfmJs
ziP-pL%urGsBOxFvRhew{z;dRW?IfZ~mt{!CMc39`ynt~?k;OF9BNZp75hpUI$G+LX
zUcI`T`!1h_*&L~E+tBCQG}T2~wHEAwf)#Rq`+R8Q&uMKhaGc3;u8m>5R$d~)C~E$uE26kGuk(v(h;;Dq-WhL6grEZY6XlZjtdJTI?eTDVwHH0Lz+o)x
zPd<9{&eO$|psev`>O_^|Pu)l-P`7`Mcap
zg*3IN+X$7_^3{&zo8|9bP+PBbV2dkn7d2wx0`gMZ6*$9EtGjESHmAZUFDtg(7-W67
zFx`vQ4i|NrkNZmD2hy*^R$n7HnjJl@-cT=!oj__VvR!jKoPivZi|TVbm31`j$|2>d
z2DyUOGqkgXhsoY&L2l}a%RVn|9c-PvkW~K!M{|^1cy+QV_zn+uNR&vbXc-zRMvni3eA^KCcfTplWsCUnwrq@(ks
z+(eNgdFHBMh>llbtFwrup+v#VMY*$snL|PEesT)a;&Sw@@`w-NL4j#+2}Qp+$Ne5{
zCd5ihPLFp6fofdN_moY4KJ8Sk9)+D&V^d^*70
zCFNbCIVC0&!(9-Dj#-QYJ^+sutxpRNDp}Mmh3HC*X32Zh&o`$U=@zvti<(-B+P&@c
zUMw?HdnJW(h?9*yp0BkH>FV~A|E{g=ke{#_Sxhk1I$bCkQys%O{oww2*NNH5F~=S)
z|HTg3`K>Vgi2O>g_dvqoI)1nOe9vQAw`rl>s_g0zR5UgE25_>^?52wo*;-7@D(DR_
zU-|2HWhEYbu-d}ifo8Q5Z9bhRM{3S*#jPc~S$)73&yHRfd!x6Bo$A|+s4A|0SOf7g
zo~FkPKh6OK@9{MENtWyhy@ym3Bpq^BmMUPJMybUO!)k(yzP&b6ksDRKyx)qBFAHq7
z3OhVF)=;KCt%u(G4S3ZY49r+Lo`QMK>S1H@
zbYK?}6#Ny9U!x0E8}LlP9yDWLzjgtX``1jdl^&oN$1a)IXIz~u!3fdr
z>45OT=u)xM{yu%xJt3^Iw~J*%5Vd}=e1RWK`0y7Ue`HOtegb3f6*
zwC}kvUA)9P>#DZCnlWR_q+Vp@*GDz8zMDL8J_!zPf*Z)9=M%$v-TZ~Alq#EyRG18W
zFdlRVc|BA9y}VSl?t$*^@uz1(pUu682GpWHn+0FB!Dc|kzZzh?nfG*-8CSG5{dy;?
zt4@ui8ZBMyn`$CvfyVvAo;{6M%Cp;z2&IT(2^)GhxJb~;`Sq89qv`2^^MUDXx%!bO
z8Z#DZALt*-55@>pZPqe7rP9_r4Yv208fzkYp_Ss*Ofu|^I2$V+8*@Wa7I}M!%~$#P
zZ;{7Z8thB`&Go*g9|Vpy812A)t=2#tD^H-b@xT>pH?KqsPov6EtIMFwf}FO8k@lg!
z8h$u`vSLw_GP6LP>{PK7pLl9fzo#GEa(c)2P4c{4Ven<51Th$kawDATSfM-aYtKaC
z-+ovf4qYq%VmLKwW#2s~^BK{@L~jfuKnq%`Umkxtx2(nAUe7AR-`nJ^N`)4VQ&ZxASsJ>k*Fl6y3R*Q}m28dB4Cfq97_DAR#RwjY>E2AYIbkQqm0Fg3=+~gOmu;
z9Rebybl1?`-TB>!fgT@^=Y7xjzTbCUXa1O(duHGJ-g~XJ*ZS?f_F6j{ty^UilP0II
za^3%)+&dv}1Ai_Zg$LrG8l=~?CGMa}X35S;5vM~WA@G};{v6T9xg``Ov%326%SQ%1
z>AK*`%)5(BcNtCVr=P^B?HjyaP|#b}BytEtY#`Q3NqLiMSjx-`8L%9e7Gig=+(00J
zaTL46BtqSaibAEn>ztH^ks7TT8>EcNLLe>qUg6)!Gd#_Vc_3
zO&rY9VRjA{CB5Z0rIeo3hW3(!QOBQt7^xh3J8xVd6Fi}8I**n{;bvZ>vdzYj;+9W<
zFyVJSV2RblAeSGlz6hrXt1jFjX&vvtj;Kn(w7bBj+}JXx2{$&Z5l)5+_C_rV;a&QI
zk56C5`V}f_!1{H|8y)02GxT36N-SO3X4EN>x~hpIf;MO{oNK6vE2=&@=bPA3Hs~d@aAaOa4pwSNP`NK-l!3K%~ZTwY}>yz{5pjU`E%H&7e}K
z1~b@8pG4pEMQ3+UcQg_Cg6?#JRpYDnhXVxV@x+O!xm`d~lvc4RkL8kC8k{4)X<|o5
z2|XO#R+ix!VwPy-+6E-+it?2{Bu|jsGj&m@W~^+xeR8X=4xUk1K(JVopkcCSBxm!4
zVXUaAz74(5%-xnQU%tup{x{1?B(xp?1-GuMU3Hc}vSE$`MBz92AuIc$e*N
zVGr_+;FN%%EbSy0av(By)Tq?jgp#e1jg=)?!EsR_Vn=6Ccs7RXmBj
zycsNCL_xipQ-jXOt3s$j!f&1Klm6E}i9Yxn(*Dl2(<
zvLlC|Xhu-Wo12%es|+_`cb+)K?qZf;viQf>Ef9zmw
z4v|ZIY&W3T;yy4Yu3z=TT9?WRn;6#7H4M(Wp6;bV`O*Yvu3sqX
zaKlxSn@YGV#0{T3*mIn&;09Hr%}+Q`l(2$kRC@`(qm
zTH=7)L2+k^*jKw)MxM1kI&XyH@&lyXS`K3DJ2ZyG-u_62Al=#Lf-5(Ny-dcCK3ub<
zNSaEUc=BK!(=7MZrCEFnr#w54StnNz7zAI+!)#Pw)x$d4Lvl%JXF%^s!F(YK%3px*
z<
zj^d3%o%%G-kmNimIwoQK*+;!)3FE;sxt)y7mZsCVB7%p@5&ll}#vbPKJPRSLQK43O
za%@7(G;i%^O!2ZYJ^^_F0V0NX!gVEx(_hb~gOxt1^fA7u?JADS#c+8I!!Z@sR+=Yd_?D$M
zGsUMtvOE_5j^&U94Gozt>oSsIX)$5Gb~~o}A30uZtSqgHg`eurynLJsERm(^c2=|?
z4f{QL6~4m4L+I8%YmUz)`k-B+K2GVi9{WP4NxoK22L;-zXM|*rJ1q?=4PO-t3COh%
zELKRcXF3;pP5Cig-GBHfNOX3M+dC%Tb&b8u3?~2_(Zx2ce2Zy7`P1MV?bL1QXuKPp
z`PLpN!;HRh{zf-gdSGTTV7UnC#|Jpknd5W
z6t>AqZyB7d7S>=tRR1-iw$l6C45GR%FiFqcoT7(4EjpSza&}OR-h^x`Lq~0JghhI7
z^sI)A$-R7iGQRpuzI}dop7>r~E|%bCzE8Hb+_87Sndg<~3tByPfv;{U8FJuQB>%1J
zrOa!Yw`VmwJ#O2Av7tM|fmi#rUJmwq5tSJeUe$ac+kzzx-OHWL3IU<=wlsrXNB^)>
zka=KPSj?KB1H`7-yOw?R893lDq>2<3JQf`Md6fM)qSnEK!zErgtDOQ5aYFVy^Y{;u
z=9bz8i8lBar`aL2n3kqR>#Mu5P8^QhORIH7$Gu1K*6*Ts%AHY>pbo^Z{Hu=y`pJwN
zESU{1pJzNG`6HKUHM@&^%^G-#nX7>fw(^)`XlN|3qe^0OZpVkH@ryF}NA2+CkIx_9
zGzD!U`{Qkg#f4NS6@T+>D*X2T`KTqh9MnG6n3sJ<9aY2EMUy!zO4%J;Fqh`J`j}>2
zG+{=ed#4~h!JX0__Co|#tL|VGQ^`(~%>^Z=QDPmJA?=kE-6K@|*|_BibELyDmC4Gf
z)lX;k`Jdb7A9pnU!
z+Yo!Y=mfx|4A)FLsH|X`bhb<6qF}zczj_h?#n&vsLxgJXmNOJA;o=KmEQ3K~Ttuj>
zpG?vCo7s(6tf6{^DY3kRsTb88CBsa2&GAci#R>8NW{xr
zm$+i$>DzFc?AHkaZRmXHWdQ@6t&}!H>85zOrLUGhblTO|)g?@4A=x0z+Mszkc-}+;
z$4(Bfb4lpqIFOvsSJw0sAVIg5Yx##B1(h`tZErXL+YsPiS>9wGNOk(C51){XWDe=@ZqNQR3jcYMCj23bKWav6n?44Wu++)MvbdM({!2(DTKrdd7{})bf?C+Pa9iT?jFu6u-`w?&oy91?$BG6vEGseDRG?sHx^%H0Ebpc-}+m1fo?o*-5)&T4l2sp5DS^}8odBOtyi5hEK1Ce)Ps-m7A&`=>=U9teiD=3ehhczlS)a~2vNS)jXNQG!s8x`v=M?v
zHjBD+$+-%~woJ$V6f{^iXzH2P9e%6*HTWX_PGTlLeMX7lSIHML)HC67{C8IDJg+}A
zv}0NkgzAPzfCT6I5u=fgOkF}0#&D5gaFq){N}!oLS?uM0>*g#~nza%mmzcTQ0CgMi
zoNxX?$OmS_hchcIF(qVWARtwft>?puJD%}+FFQw>7z%6zz&Ut`AehScW`z|vhsvg<
zh6>16H_vsdZ}l=Q4b)Qum}!=f+`Ky5AAmYjnhf?dhi53(v%OkoTe@q=>pEwSUrk~j
zz7>F3I#wK`nL9e%$nF;^DfK
zp-Ct2;bc7b(m@0yz-AifL$G_{fi+bk+F&XszzC{1GfTqZDw1qYb&1)5maBmU?3p7(>@>XF%Kl(A
zEa4SQ(bT=CMEBHTz53Ty9$sFq>*&ZKWHz&_rWuE~AfBb7*3>;LDGBKm37E97Aq;L`
z9HCaeot
zt`MNmy(&GSozi0V!>e9iNGGEWhin3cZMmcUfaUy$nedr8{rRQ($U0$Rx35S1pcH#@
zL5?#aw~M|XQG+xK%zP(nAjzc+BTCT0!OG1Vni?MyiFRN;cjSaWAk>tV96Wgt5MmQA
z)wQyZLv=DqU`53|_HvhF)fCOkX7ti5-Y%K5@O$=Ckb3nR*n}CsjqNMQ_yr`oh%$ih
ze}j-d;}12#3ddA%-G>$boe|EH&A`+^&*QkgqS3O^kd?j=wLa4iJW$gomMA6MUWb>L
zOMv{1gmE2qUmx%z5(9qyVQzC)>H-A1$gy7{rk`&9BUtoq^`FC@*gcZuZ@AXWt7PuN
z#rfB7VAr>Pw?Ny0*dT
z>@{y
z`e0k8ynL!03^vi0l6GDmw7Hd|TR+?B-mY6T-ps>%qSl{P>s)X!-$$Svr)yPyg12a+
zG*V^1dxF--{HCgI;XO7k!jKyq{}9wf9DuRIrn&4(z0cajTn>3oLCw(PUD>9enDbQv
ze(^~TlbtC&gCBk<;y|FdrZZW@tZr}FnZ<*L!m9F$~X)c5mi{v53!zmuB6z;yMpd1Tw
zH{NZsEt}qXj7w-Xym-sE_f9QhMm^&!O7Fq0x;};o<3o?20&6znTiFnobi)PK6LjP@
ziY$U%4X-T8KTVy9>Fe%|a}!=@G~UUpALhUza|hmdaLn#45TqFYfUA+)06AliDpy{g
zz*s^>t!R|}jy2!1&yv8RL{^;nc4@Dka@F`qu~p{cZnn!fC)nQiNG$_FTH>VLWs~U?
zk@Zs#ncP0G~v!CyOeO2&2Aj3tOeb1E2&XI;*
z$J@5c{(U2H3~&8C=!!>aFZDzWRGQn>Mr2S^mv|x<1!A=WJ2DnYorctwx+k6%^(rii
z=5isNq-DRoy+?Hl;&|;@HDW)E{)w?16RoZEvZVKrnK-6551k;#`lDkKAs@efvx{H?f;5wxH4
zZDo?_LhiJQ(HLa2=UU-K5BqF}5L$p4%^9nZqj7fJ_6Me|^I)l#`n0-dg&@RwCf!I}PGduBp6rco_>Yaln>3{EhN;kzJ|hlrOJ;_q(@K~o0c+T5v+vy=|I)xyjK
ztBVe&->F(0k|W(@G1>OvTf8{|*Q<@a>9y$OkX>+{H2M{<;2=95ijRC7cMsz>?kVV+
z=WJ*n@?p*eEdo6IcZ%fiH1Bz*lK^tJ%#d+Oo
zoP>YEgr1++%eGW(6FrIvADjBMBVqVt!baZDP#=09srv9fYu9@=>ist*owb7Ihz?n*
z;F5n$kCt8RR&deKt;6L`LDTdSFGC)%FHb*W<$kkaY#nhs-;TA5OTAJ^y`OpD6VcpIuV8pt(XcGX9$H#wQ)lbe;IZuIrWx*#_w;bO
zepK*N0?l}wo8Hyf8FO~MOBoKun|zS^w1OS}8VmYj%F@_}=9;5eAeG+IEYg&gf#reP
z6?i%f{-y`ecvzBYtme(J4&pk^EPjb6%nTo!Z)5wVQuL^qL%=po*fN!THyvCU6jxt&
zjka0K9BAb+?k3ipg4m2XksIO$q_~Tyct0IguKLj3m5n-hL1mf<^$CgfoGrF3e@9{O
zb7$vRKYvsrH6C)5wpGXOT%fp`+SS(P3{;eK#MnrXK$qQ5q239^@dQ{CK-%=R0da}&
zN+dAt_2t|;u-jj4j2D$IUgU!uIB^{9PD{L|IKiGqZjX{*x|Kbz#Xn!#@9e;t;O}Te
zsYc}GRHa0{+ciHsTSe*gKzuY4!(o1Fb8|F|D>8M@FqHc*9rYZksuXXW*Rz`YOFJHn
z>p5w*ziXj;h{~%-G9n!%z}&q`aS{3B8-W!cr0G-8m(Gd*Y0vPQ066ivk;$=3+?+vx{
zm~*x8NjQl~Oq}Oz{vhB?{g5(2?g`yaY;)p*I6G{lcHLS&?9ey`#hqQ|y*b9J=C0vL
z;I5`i?Wf@GtSu62t=WXWqX6h`eLQz28QGAb^sQ=k=PfxlE6LQLu2yh4rRxyl4mjXG
zq6Q)U{B#BmxP)v^?~H#EIh_($?Wii
zcgPRXRecYMti|3}=rv|m242o@Pk&((NgnSiM2j*Wg-iFxl2i>AkWSh{8Ee`(B)GF
zq^{a>|CCcd4c`zD`?%_Ivr|lvUYSS4;_Y&ZWYD
zzUOTWq!OctW0GTM71QR$y`V?P{^?*Q
zXXTFg6cKbjDxv;J76g#tiIugKg`b&x(4kiuFTu^ZFFo&5wP$nhi)aM@@i6`$5%$yz
zEd%Eq?Ktpa@Ab>P!Lko|#kSOL+mOl|xF!7UW0Sao-qHj_y}k^hb1
zZkFP_tgeSS)(shM0C@Oo6dsC;TtzGb
z;Hr>7^D?8E!3V38n#yc6+TRe>H@qW(l5*C+hLT|>urb!|dQN5>M(#HN_YLp7S!a`e
zB6>CWvc$xa6fTlG2hx$?uS>q&ycNiUIZ(I9_=O&rY)J$MoZG|u*b6QPs0|3+vp^2B
z)dYf%eWC>I;qa>PGVCbrz54Jf1wnjr1C#}JY0Yq=2&QZO&GvaTx3#*U7E8nGwBkbQ!k*;wPMuAZ{W7Yi;em6%tI%hur
z@5XwnkCYR@jo1G_m-)VM)MGq}4h=kr9@RTm!GAw`5}Y>Mm#&__znD!Xx!{tsyXXRc
z*|C@gnzGPJi!bjUJXH>%l@1J@85>{e#-<@b*aRl0$t-wqws?C%@=Cr6ELlU`-Mxnd
z3u8OL{)VmZ6WO@4J
zBhcmV=KZ$*_u3!rh;!D@=l@n)eVh0X{LUgK)y|6r-6s-6;r7iHG-JE5#tzt6D={a9
zwrchLX$HVQ(o?kkbsa!vyT`erQw3gXtp<iKH#vdUql@@;$T71mCaGiNOB~vE5z>
zN8Y_G{B|x@`^j&)QuqZK{mwvqMNj|TGGRywor1(s-b*pkzq2!P&i{y=ep*U>L4NRc
zDd>$u4^piqV>C=34T+>|k#HvdQ(XwN;74BA*-u8sXxE$c!0xcI*L{^H;0_reTI<;A
z01%9I@bCH}`l|;&`UDnq$Z5LQYb_bj
zCSBys?4Ara$LkW8VYgB~VW)oq)fm3`wnqA@!+=mC(t9cF&igs~_kXLFvwzZJzqUH!
z|702SU%@uA-S$GLGeq(WF~PqxbTWT1d-@aW^e2-!!9*#cm(NhEWRmM)%BxU+J;$UR
z`KBSv{|$@Cq5q&1F51n{3(dubaz;uI!)wH
zF-}hnuDl7sf}vC3wwVL5%YpFErtJT|5bz{Psjfe|8p4$Z9rX#;1_AMUe=`}!{~x6K
zckjbBbV`j#6w2&GbN`Uv!j-;rfb?72@dU>*^7nQhJU;~$w5SE)=kIo4lZHAZQh|yEX+dtsnHixsO+AX;2&5o(;!athZlI_
z6TuL!m0VJSfuS3wYc-nExsQv0mM!>}N7m-iB%k4$q`(Ur?8vs^zqF&3VhRI6T1#^+
z91~1s4qj<#9=kDnmGdszw-=wIJ%*Q4qR@B+WOg5Unog9js7Vu4@GjX!k&U~F)&ysV
zl{gl0MUHm*)mpBnBQu%x$HDq{o@Nl^;&~-nzlWT`tkHs4+|NtjJ-KPFI5BGNrdc
zW5hf@2W!_BZOl#ssTo2f=x1Une+BVBdkuEQVGH!MJ8+4-_k@1M9A($70XKkGdruUrZ`yTnG<@R0dNm}kd}
zproZjPE6n;4!EE!=7ygm$bG_Y@)Efgew&h>W?E%@V?q8DL}i5kdIb6?uZ;_QoHmem
z()84)BDK_bWrk&6yk_o$HDtQDJaTfH9XaWm>^kxka?c@}mkXhDc7M^vi0uA0mHeu*
zOhV&A&fCTIF%HJ4dIYS{mcHSBw!~C}6=jFg050jAgZpt8niA&7yAQkVTsuMVk>KqP
zS@=eFTbfdpJ+wlsqR5**Fm`!nab*clQo3N5redgpfTG_C>taiUEAJdVJE+n!Kkr17
zo&0Qfrh0|($XWNJ8d|M4t#+-E-lPpWgpaIf2Zkn11(m
zb3rb9q-a&z)HqRea+ck$?64eOMrN6_$<*dSL!&hTKiY+sNM)Z>E%v+*Kho~5`DWa^
zVW(mDbjl0#M!3)t3i)%QiJ$ku&Xn@#AnfgKW_dRhsvp9#-#TJaxl-K&2*5XTKflnD
zTW`M*?Ys{h#bM4)!aaw*!wbgC1wyfov!=}IHW~{)7s-90B|mW(PW!x
zXOQIY7@ybdw7rXq1c`Z#uRliuu0n(w~qv04JG70A%#w)(%UBnHlpwt9uCViPD@wwOJNd5FJU6Op_~)
zP#AA|K2o4XGujDP1FRP8vog(@(j?#KD}9V36)4ain~%JMvmHO3QD
zjoi|T3t5*;m7UC9O*gl`Hm3H#9<(E+4aj>MQN~mlQ^5ALp4mwHjWPyKiQ)>zFq@yT
zypJifK#P9xxPEnEaig=+sJ?GsS;^bg8@X~VJSO4k!q;>o6&VMya7l5o_3n*7HsGQX
zX);aX(?LRHBV%VV(!t;)t|P2_P@0bh2Hy&G!(&eoEWWt#t
zdTBuPwnywTYKG8YnD!22x(XgXJ95$lv4qnqXTxE+uBKRNNZH(meceL&xUYMNVC*eY
z$Bq(G%m^C^5rZEVr
zd-sqr0IW17ag+2FLqraHT}>HrR5{{D5_lt~mDsjQLtAe@&XyZ=47Gi?tu>e0C@5Od
zb!>_>v#xZEqfqzO#(JS$@ni#sCNE!e=N28cdZJH=XJ25l;KP}^Z`g9e-k^*MLo}^n
zT{nEC#RTh~A?yB#^7~d3=3?uW<%dmTr=YfyDNDRK^IV3PW4L{Au@6eMqj{qUagpIm
z&1uZg;;GES@Hv~C%iix^OOM9J)eE>EfR&MvY;-p-*!||{9E~g^LuQ(f0*>qrE7T3G
zL`)CC*4sod)lH>sH>wgEGX@%>Yz(u~N|kfM?_?Bo^vUPJ^>*{1Jr62NmKH!~4ayb4
zb(G}2E~s&d=~-JZl0rSJSQKgLU!e;Qa~`qny`MaM`u*MJ63GpolzzBP(cCPXq0TrS
zJO2QdcfT|OW&L9-4K$ie?G@k?FE|C!a1H}HP2o(Z9Tn`_;5w!N+Euust@;3dN$m5x
zYU+D2O)$!RL&B!oeiaLCGJU}y%HABBAB9{0mz@ALPcG}`9u
zqn%u5L_nQhc(x)oSCe#y)46h$dJA52es+k#TQmj9rFB$*X2Fd?Ris_q*eDOsM{l_9X*Zzq`x(+WepwB$AA0Sf1L8y|m
z5A`i|2-wrsE8tgSC4=y_f=Pn19^6MzJhxQ}WUrppaYkYeWz68&^aoLS8B)z)RwMd9Jhp0dt66A|GW
z5#U|%#j?w2B{*vzb&8H0lB!#*$j`=
z&wM4*)K4}9Lud{*Z3o;&n`u*pe_qCkEq!f_Ljgh|TQ8^Zrw!@Q-Kp{mo;}
z{`%?VlUx>phbOh#+Lw`?M2lXO9=srGX(dv{u9jEnSMo@1@XPM(?^yjy1wOw<_TQ`b
zB~G2NX_pmp##@~UIoZ1g6_BW1eU%=3#6H?WcD!~Tm{86T7w;uEXzzUY7)JBS){)r3
zr4MzVQ}utZ==|H?bm;=+D1#UBx2zak*wy@<{Tk#3(?!zTI=VZKmhBl2=<&1)fxeu-
z{%O;{l>3)c{!j18OL~H1g(8Z>PZiJ&IIcR?wptUsT;oVNt33X7;?x0
z^`psD%*Uha+-~=2n7Y_
zhjggE6LVe_z-R(qRP@Pgd+73867n~_yo$aBs(;=_dft04uUw_XwUAZ3y@=@Tj}D&5
zde4JOL8xpvr87u2EGAP(T0$Vy&pSJL3-CPMj!5*YQt4bUZXP_4ihYWt{~m9XShJK<
z?^!PHp`UCk(&0^b*8X5t59lUE!}8H(cOY^~bBD9=7_muq`f4o-t?moTI*Y`=Vl%_d
zVpCI}t_AVT65;XGJL#ZcJS0mxh>-h0|3Vw~(0`Hfxta>nPL;xO+WS?*?ZCmJ$O7#V
z=EQZr>GSK@^FJTxH@q|DoA7OVHqy69P{@L}?3{ZjrPUE=JK|f1839|7-OK&djD7G}
zdndUr34gr;)8`&7yn}j%bN84{;X%W)kS{;yr2V~HKRzu4!_T39OO5$2C&uhO+
zgSG2F_fFF8yu#G;+C`Nftm1UoCT^TpD1Ki1m*&bn=&k}S@E0bRKcCK`m_T$GT&}RF
zard&&4m7VCHD`Q<$~*z)$%1^osfTE*CSE|CHBd5=^Xc}8UJbJm8&shZmuoH#oL1C*
zZCs5;9&!it3d||2zZ2HQIHB*SIvO@zDUqV1COrKv{^4_jTV-MhYjbN#GmITXsGYrq
zZD55PQ#@c-^xJbPJ|z4flK*l@#_n?y%7Edd3+l+*W-Dk2EYP!QQz6R^ZwY<)V`w^Btq$%tGr0sDXE}g!0=sWRk%K8U80pX+E5BLg*Zl
zg8LGK8#S^U8n~maH>yiDuyG~a!SzX4+w&1t#kK=j33bKkhdHSpyNgswZ=<1C>Wlgq
zf(HyH-n9==K{;+&A-_(4y&q5RNFdd$@`la|J0?tnZ)zL#a3hREDt`JJlY$N`AjQ6Te9&srp~D8mf4cYt-&!nE{fKln@omi3+j??
zJ9G2u1~6QLL=&!d#pd8GVd60PU~>#j=5k_o6dQCeALW&F*)o(VWDO2MZ~enlOhcqD|Rs>L3U
zs%6n+y=aYhi_YMoVHQZEo~^Ol3`pC&))ry8@8noANHJC~**P-%uG*!tlS^3N6eWs$
zjyM^qkeBE3%LdVgPwb@OiNfigLW+_@79xZ?M!peq9f?zW?Rf?X8@_j|Lv0`M!3C^5
zt^+bdK0@-+vVA9v;?~IO3E2_k_4=rBGe5cE1qO_v%Fu*HJyB_-2adwpJ=6MDGBJzT
zZih#F+ohis*Fpyh>St}|<&_7+Nzk3~MSsra{HPM;y8c}n?Z2;p+j6*XA7JO7>+$C(
z&33NCb+!Jk(19H%_oDalJr$}H2Iv?e3hlTE?8QBlANk-46S~4jeKC)*WSv)t59?1z
z_XK)9`IUm&`R{Q6ak55~%%s(?U|acT_IO2;
zu||S~+1|De+|$m;9&Usd0UF&d3wio|uXEGvIlNC|P4{8DAFfcfpkU5Sk0gFJpBLW#
z%#ywd`5iz(;*yxGsb1Vj1i_~;1z%H%4f-A$oWkmHrlcp|HXOm70c2ompI^-w{PlN-(1
zH3xta->dod?Qc4D0fhV>F)3uq0=+qZ{nN&u7bE|P4`%??8OWZ1XXq@%7I@V{C4=N7BGOpzqn5B&Jdj?Yn7{{;g6mNmdc<2&~JjK02f?c&F;Np{Yd7eSxd
z@j2uD=eY^xw~56$H)KioY^tIq4#%jBKeHuQDdTJ1e@MPG+PB;S(gK@>bA5BoR%f#H
z1E5X(T-^o!eeOo}+#Yo6MVNcXdhz_VmQ#?;k;ItqqFnZ-PSr_@$SKI8u1)2-{C?i(
zDM%{i6jZ7;n+-%_Z4&?sFhf(19`XNpV#UAiNRc+Tkb=93uQYZ&rj{AVx#il2ky9qH
z44QDTRi=V4kI(ERj7Ao$mEhF?XZ?+64>Pcr((ZuF`c3OfXh0v|xD!6%$;!R2OO~qI
zpxK_#Mfk}XX+vsK_hWNM%hB70T{Z{Vkq+PV`!a<+9HPYy4)5iUfHQ--3(?IBx4Ol*
z>$b&%?Hi;!^1FKwA&HoDa1t~Q_=&?hNtyd5L&?&xL$wXoGFa49(+C5Sw4aTF4s+9ZEDYy
zawa#^e4Lg>8#dXw#&bIpxrUhth?n#wptaL|7M4)+gi@4^6z&S0*ErHG7M?Zy1z!Bl
z72|v)P?KE#EYTCMdg6G*_j=0gmM9cTR>K8~XxSxUy
zjbMQxCYP`SyY+0GN=i*$$FuvOtsl7)K0k^rWTTuK{t!YH*>)ZO#-?Y}KJP9Ke%ozUmeIoB>ibEcdTvpDB&2!!)dHW$V1$co4tR1kXU%
z73o)74Z^n$^36Gn-Z=#&?v$u_joYrowBjl#lU)rE90G#CoqU|QoPqYlv5001C`>T4hRoL+k>Uuph)F+W2+gC51g0j`E7vsALCbn6*-dn$fIR&-K
zC6~dCZj@8)f>xHjO(YnzIK<8G-3at`@&&>09swOeJO$OVK70ztOZ2`#Mo$R6N5wDw
z&72gS*j=Z)rgvN9Y_7--hthR@puM`0SAAH=POg*sTm@xX$9>nQkRXR385uz-7*Jze
zsa;F(^ROS}lHX-DA*XG7erRy#j^FTHQQ{m`Dn~^v4mMB&bH+tzDWl6t^T0-2|
z1P^Glgm4IonLt=LGN8?z-#fqLAbl#*xRi4c4`{Osm5*yz$G3gfkE@xg-Uu8a!kbY`
zOXaBj>E(GIO16B}_;L!|wy8Qd3f6qxI5Kja*X5Fa(78^o$Aq@R-4S5}n%i9QKdMH6
zfAXS@IQIGcQ6ef$M-chcJV@9w
zlM&erh9g9f5wl2XYSNksrf2`SRVn($eoIDFBL|E{V!7%%233*9;Pp5fCmOzVBi<-1
zPh`y)v9!Y0NJ;zG*JEV@%uv}dt~EX+ahQ3Kzw2<-%;Ro}+c*yE`*9>(LUS{>hcsrE
zAU9sO(?dt?4&qEWE+MKLooE`HTI;}SE5l@>YZUpwHad)bEvLm;d94RrU
zQTs6L%;|5As=gkLr_SAqW4C0mTg~b+Z3|a85Qhjfj`B?tl@n&DbDhvh@aM3_x+MGHk4X|H9)X^~z@(`WubC@Nx3d4Uvgvg(>44Y%O&!Bj=iQ0)wd>9emVX*+ZIUUXwk{Yy8++ioM
zBojYR_V4O~6=dibKYqW@Ab+xrI+sA4TuxV@aiHcXn;bB1pQMbq8z0ZTY!ZbG@4g_F
zMA1)RQY|e(`hmx5%2RdyJ8trd3Aq!)Sd?#04n_ldwzD*jX52N+$+%7=gws?-5
ztps-PmIFXuy*7w~{o@Pdjau4_Sw`CaZT)B;_m$_~CGAj3Y=v+_z)lGx$?4=h(DxKJntVIi8DcpG4xbp>*f
zvKe^#`g@j7^Tkq6K@H&wfy-uwpCX98Ql!=!4}}3@;%STP9wLn-uoQb?ccr^1
zHkEW#GBVGi>uugL@nJh$l=-+aY|b4<<+I_CM=)rS^y&5)(fj^N4g`$Y=UXN^DukX$
zCINChaxl!~xIZ0{+(fK|&Be)<*#(5jug?N<`oen3G5fw_L@3)EOZW7-r+BEh4ML!m
zYrydNkz>nk9jn0biRZG@od2uu0>u^oJreOl{TGI(UVf`-0eg2CA9ndgk&G)n-~>iq
z{%jjHC%MFTg(13Q*RtbjAN(ds{-VgE6>|$z0_p}Jf@ccCg~1GIW36mom6E;n^oIug
zFcvrh!zz6nxwU|$Eg|}WS>{2!1>r=0)r&0<|6#CwANzM5IA#ucD}-bu-~P~o9|pq)
zm)yZU@?)QnW0L=&(fH$X6X#m}o2@qgRhdZBD+|QL=FY%*W&*sLANKQIS9jAJ$^<90
z4UDa0j#aIAEIVtiPH8xIirutsA#HhvClvodjWc{(*($VaZ_i?2s3D<7&$zZzxfXYL
zFLI2fW3C{b0x`KGsUvorsfdI8rOLSBBmROCqbq`hbA(HjP)QW?&;I?6Z@XLn)N%SB
zkNJN*=Ks4MbMNINSZ56(&MxIg$rZoMTi$WYV_;{5n3z^D&ZWx=+0<47TkOgiils(}GQ;COimy`L63Y~9rms*-IBIz2ah8hX
z1+>{3LVC+shHwYe8UoPl=F4~;%RjVOe=J+TiA8Sg|ef3K;U}#%yu!Ok8H20`+=?f8uen9FxaRp4+S&RIH+8jQY%Fu*T^;;#m&W<
zPL7IUSS2^mw=+k)LHwc>Cn5l^zt43C!k#Iw{2V3v&{si7I|k&+c3(xQ_x2+#!d;7i
zCptiW{emj9&i5OHZetJ2y`(sM8u@#2tMA>rOmDWf(IIdTfjxY~4|$wy0P0jc;2k1vG+h&=CG7(bRN$INlgWF+SIvXk45H5Z?po}kql<(JcZjdH*K{QZ;9y_0o6;0S73
z)>u7DJT|+>dJ@vovTS*DEjvovm5xMMTkxG4gZrD_WMQjq5y_q;;iD6mtME9=b963Z
zB?$g+Q)|OYhh<~>wbuDmNpJN=FQruPD&tTR24f&7s-o90(lB4cE?G!Z7mzeY)^5)B
z?~vxl?}S5PQZ`&?+(awdC&gokz{+H_ZnVFq6qPm(QDW0yq+w=NMW+rf!yhc8A-|miiMuQXU?YtLmkw(8+0f(c}l23|GYrE$lC#gKYZVy
zdodt`^3&+xG3oB4BkHUH6s{I@o+RDZ|=YS2o65
zZQF?s!n9RFthzH82eZDOOz-n58yjG&9w1@aIGaG63GJ`;zbqL}-8WcSVc8c3;zGjo
z#t%Rz$w>IUrywupQ&8yJ4^6jKb4e#d>mMxNezxxZdZu?Wp)QqKGIYxF_FcQpLh(5P76!Bf!qDQH^!&a%teDQF`#oUW=ZjjhU_
z_C)P0%;Q%z|5MQ#7`8FRBmT!(Ca%n*PE}Gs%t+71g6tFIZRO>q=E;F?7H*pvCr;`C}26piUnpgLmo`7>M
zJ)DPiq+@0WulWzTbif;jW?df+HrUU{Hv1d*3_m+u2_9$)k$`K;b5W-RGyI+18
zZ#Z}C|FHMgaZ$Bh-}fL0C{mI#bV_%JA`K$aF@PXB4BaiFGz_8CP)fHnLrQl@cXxLP
zsL!D1b)9lv_Z9c^-0%B&-_PgSe{9g1y=U*)9P3zX9qad9tiS*l2A?;TtVL9{ly~9=
zzXjmwyAv-?x9MlaD>2pHq8|j~%%o5@KQ!WTNM8dW--+iMdS2NcPf?zrGbZq~hj*}-
z!E$rdRSG$sv}9GRe#vJL3HziQ`v}d2)y)QE3XhWAFkvurO;)OvT#y@Aa0Bb6Vq8O)#JteD#|U%0x-mXKCCXKR+!wYaomHnIb@G)uwAqUuhgK1
zEDP`DHgCYEIOscc?N9u9PSqR1ken1vnSg9&CZo*Unh{kAUf^nGs&Q>u<4D=_#|=zd
zOgY)}+1UZ_WLHpCQU{h)mWDQ1U(39uX$=yyOC>iGAO!?mKG7kSc#wF+1d~I0+|Sm7
zO7CoIT>5$1gi1F+cjd!YF2U)CmE>i_^Qa`F8GHH&zD84xe2<*y7AXc<>7@9g`R(*&
z^GjB_)q10Fo2xa0_4A_sZB-Wzj-BwkMk0y<9J4GR+WDBt`ZE3JLRlk)FuX1hIhXD*
z7WV8sN3|n~#7HZYb{d&9#O1e^LBi8=5c>buYymz9t
zamUJhIwNC{YGCO}mt6=Lhf3u`*=lp(IWCOi&ehc9cqkV5%V_{I$7*@QYpi~-tz9t2
z)6kv<+i3L%v{H6xG
zp-ap9DdNEUweOx#T`Q}5QEN3@ctaFd@S7CvhA8gY+Wa@HsjA}{GT^@u4js4}(OY5I|HxDMy)7ZSTu$qyZV!WDvB6`W0
zzM}Zx-STUHc&hewhh1|I=#qy}QU0j}Wd7~*ZYTj&Z-{obbB-qUKh5&(Y2J__{`GNt
zO}C3ouR)^Ue7JmZXqI?Hj&KxyeF5inbrlrZR-aFf9ViixUpz|%KrPuqwUduD01=PR
z=Xs-=H}HYfa}Ag&6`LT8ppAWAKe{6{refPi(-JYWXby`W3z%fXR}tbz?hs=FsaKdk
zZ8yDJ%##_NF@l+%>uD7<#(YJQ4^e#a-aWd(cv#8vV_z4`RErBqHEgmg!EcJUCJj6;)%X#tNxz)R|{%QUG-RpGeRk-WYqCdsmm$2
z8IpiO1J_a2k4-`RvZUih)Kcasu%uK2+)3j~JUJuN4PgPCr>#$O-T6G0AIZxGetsZ0
z@5|gcStqO`o_ON&%284Z_IKLwU#o@Kl2eaR9E4!WB*7CCa1X}#wo%+3iDU$++1Uj{
zm&65&s@Yg-ntChS+ICDx_6@ynDp_d6v%Whdf&nR>RuW
z)D+3ccy_b=lZkB6gt!o}SpmF?zUcsA7sB#h$YWa2lda6E!DbL9a!BZrCBHe?*rZ{f
zPof3gp#!M^lfjI)-2n7iUAB|;%m$Q}49+pjbnJ!9v~0S#cwX)l2^T?4%W!D~UbCX?
z@A7@LPJ@>4*So`+mXa+3-qpMozOHOn=sb#ABNA-wqx2bMTiwu9=>$JC?>0&#Jl
zbDe>kL!1{7J#fjIs1e)$L@6KREmQeBw@Ly73*xNE>bk0SK09+@4pCE^0%dIM%__c)
zH}F3V47z@;^N&0UH6sL_a^!XK-%=mAgdseCL~v4Acqm5lrBA~=aMfbfQ_^zMzD^!P
zj!lIsMpX1PyrG%lYmk9Y194j-&E`A1n!lpoBt-e&zxp&xR>3wELU1uXDLN@1q7Ows
zA$i}4zU3t6n>Wh1cp_RJ!b1ssp$7BAl9Jai9k2GL5ex9*;&QhJl-3EBnzvzLN=iOG
zFx=jI_J45DUn>k_x@fm<6ny@6Azz3Na0ir@-(_L1JD}!ReuVn&akPH)B2-mvR0b)N
zM>#H%cbVFizct>yhlOQ3?K{-7ODMqOJBG7R5?jVE07;@1k7`uL7I}YE>MIR3Y(ZUf
z_I)h855LcknDR@nZ|kvTPpLnhAQ{>-UgwA9<_l40s#+JpL1}53iH(>dZ1=EO7+gNb
zHzZZq(F#t%%L^eoNQc+yo#ILvky4fZryDwBpM!>XcdO2(Oq0fCxOGTr4Q**}86rY=
znxI#n<}tqaR+RJH?(=RkSHRX3FfDno*tmO(W>eIt)#_>zUj`ubkGuCU9g?lJq0zx7lFkSc~7qlEU2aP
zc)Jd)vQ(BvRWzr-y_PQW@pDLs#@hCJ_^djD`=f*%{3
z72kgUU6swlhVS>ik}9XXVk)-OM;DMWy&5>D&?*uiH#O{3+OQD6G;|edA(RDHjYsx)
z0HrKXZe_x9@(Fmj(2X4pP(|*amNx(Z!fiX}kFBR^d26=OdDba$)wbg6OKDg&b!*;A
zN+Arbsbj#4TR&w$xVVJf_9G5l7sOCWI-6?fBCwd{FjJc#w+ApMa
znXP`-@ZQ}XboQn~v%abJ5*>%obe5r)PX%xUEF~pXuQOSjwf|MVs@fuC
z829Ogg)0+tmg$vcrWsI6hWkx2Kcdf8Qqve}(&Qp3-_KF}q!UbYf54`CvgW;>6J{UD
znjDUCk(xw5oyhilWLlgZQq|0d2&^kMl(0!8u&9V_r$Z1PPjKb$fe*lK9!cNeLXJ~K<2LJCEd%N(r4Q=@da4-IpFt^L=?iZLD@_B
zVSCAiB=9xZ$K~DmXUz#NI4HF#f^2pUi3-pii1uPre5T|?R_W(lg{o@x;SwEr60Y&J
ze1`y*ee_^HOI;mwN;s6J?+#K850PL-?cFY&ODn+w=!UBBJd0y-pF(PcAR;Ge=}`0#nN?R_ypL(Xm)77w&od6LzlH@!^@r8C==0d_6?M)1CJJ!>3}
zv1w$oA`fuOJr=BS+-_9jI9+Vc+fk^y&a~DTKP?(h-;?UsdD1*P3;*$q6&?!cL}G{N
z0szRh)^l%BBby{Z_08~~4^QQRs7I^oQ1!(>PhI}C9{H~VyWdige@S@;lkSTX%rui%AO}K(oh~sR)&_E
zy)La>J6RJSQC_fL%FW#LH1#%KVs${g|z)Vs@&o
zL^vQvp_ji9zd&^4Db@GcY%GsudX`}&l`}Qx+K$GF*XgyP=R~NNS(I6#3je
zJ=o@I#=1*PSVMr2fm(oBU6?5=)E6b}s$@vxyk|Ri=>>AOK1QVl-DNXo@H9#sQ{rAU;*>WZ+9e!Curmj~Q
zQ@>~CzH?QW1##ABmW|T
zLQ9h{2l*X0W3H)!udj?NIvZU)_mvbhx6;dbDuOM*8*j&mv*1%7^RsHhMwTaoHd|K;
zoMJII(HJ=jLZsqKW`gbCh}cHYv3x38LJqgC%q10n;bXyeCPWfDYIs>*@Lu3`R5yVd
zjx?1=6(h3P9X2xq-QxcG5A~^~n`h#LNguxSRw7S2&>yce?d#v}-|YEV0m|DWPDSvZ
z)TS(5B-F)-KYA%PCBL1_+jf}Cog*cdUcAI_sx*71yvDDoz+w}x1k?6{xw>GkgYXu%
zl70Z#i@n~EEKFH#OuTtjThYI@O9t0t#T{vuam^_3s*6SI#bDz(ic32I>CwiuamPtc
zz(9#Z-xr?enI>FB_`g=BZ>+AHskvJ`W3{+7N<8qr=pge!-JGpIQ}d)+e_k7Ii!;d2
zD*;c3{nRt3)kT5#wAZ7&TTu^OKUs)hq@iP7v9Xb76>Y0JqO2AiM~!vRtfvD$0eV=YAPc*Ih(385sA{!WplzbGD)8Q
z+AOgO(b;z;*2WF3gW!KoeBhsY+w5@!sz#6eryX^Tq~W&F3_@)urv2GGCvf6;^(F0t
zkT@;(&-g|)t8_h@&e2V)T2XK3$&bmkfL(-C=&SX@Ob&tV|k3QWHmFn;@fTqft!aD87bNJ9HX*3%E0VPkU+nP$)X
z?LIU+17k#UP578vA_jtJPGD~br&$iASP-uF40wB0Fpq6mjh`7ZM(DJ>np-|KoZ9`3
z!;~DoFSNPA?FT^2X^BN4TFbu~x&tSoEqD*tI15>55eUCG&6I6fWF(CFK~YJ94#cz-
zZn>bJSqagdDfY
zJ*Z71*3_zo{y{QaiME*aQt9|>ibD(jxap7|lLMizTqtie5iqH|NE1l2Jvha@VPmVC
zUXBPGdx4xX>K>f7XlfvS`@4JZ+=JVylw&4D&a*iPH8x7lLLE?-;_%^v-8Ol>X5BW~
z{56GY8aj)Gl?(aG;_6n-nq4)u^r<9>VKwo_Fym4b(IFydA|9?v;Uwx55{sw@j)*_W
zl`S$gaeBm5cuHyrEvjc}iw#b&rfK=gO$MBZgIfeoUz(TcFtSy2aFjnCV-eme=q8tO
zs#NAPo#PH?c03!I?!70TT;=!X@Xg&-EFX@fO7z9)t`-eX;M-69Or(8fO03lwqqH#C
zI5XMp5FDZ4WQ*+FT##7-bh3Te9V)n#9;UcDtXIpJLnVvo_e
zP$*A6vieY?!&XMXsqtKQN0UU>VyFCAJwj20psd_cRYFwMiKkQ?bT4w)Jrz9nd||xM
zH5no|%5-Hpo9h8b1mg%w!*76zYf3{7=fDUXg3{1+!L&
z0d1OD684%~1mLhQ{J==KE~9mMI8|XmYQ|hD)5Dn;DlXHuyR$;x>~H1!UYQ?JvsM}Q
zK}go%{^bR14&fY_=F?GLACTxQ_~N`YL67p%^P}8lT1B~;bk7q>q=Dez_FIjV;fWO-j~6|H*eRh5vO0^S97Mtsn&OH!
z{xVW_aLLp5E-vCtEq$$_(!}xl#l^P0nn3SfbLa1a0p`M$!~X7tGn~9%hrZ(!Em%iP
zRk_^LKIXTZX*Y~oa-lFzj`Difm$rEMY2W8%{P2Zbl+K!3nM5*IQCC~>KqzB7`5)
zVRj8odVvbdm6XP+QuvC+myg!!vyAkz1KH^YV6PVrJi3(f?%KDX_k3Xg9D-YNwaJCo
z%@f5upr1Py*X8e6ne?nTwrFCh!1dTW+y~1Bfn(TwlQMZ;&whR`81P8m;}P1%+UnGS
z_a_@`uhCaa-$lbey3lr}2Zr^&!C94{SrRCVK%(q<_b7x)x6yGcRyPF2LwB})@dv;c
zt-NDcj%Uc>5IQ_KnX(9MpfnJ;!1Lg{R`Ydr{`a>8UD|e%ttoG=igG5
z_}WvfBL{kSjxI4se_|=}Ity%R?0V1J`J2S>QNlx;zO0VYTX0bqWZDCtkfF*qU8Ib>
zckYI!vh&7xh*1T%N4Tb*vQ%!$vJobHELR^GYnQP5n1GP9m|K`+LYcBd$gq*$q&v{z
z)XM2n<+8YiI=+FqZ3MH7W1YlLC_@WQ6VVWJ;OT}mNdUgafB=%!{-yW9(l@|Ozf
zj_RDK(&tl(WQ(vpeD$blhz*TH-2|r+%+{%hlfk&QqJCv}^^ldd6gZ^QuQ%Nct}a<+
zj5DU5JsspS+pij7nR4oFsyepqOXB9HM8!XWI1mwN6;tRz>kqL@OWO7P^FVT29HqT<
zjUzHxT-@BB-WOzfX(vU>GPa7$k*pBWFlwu^o5;I$CUbR6*hIC3;J5jYe&xgU!(cOo
zx_!cV*=UFF@2M#banKp-jM`p54t$=yWB3RN3*#FbTAk_LjHDa6+krC1%4BUO>P+1~
zojB0vqC7t>=-Rif8oo;`CNFC_oH`VeV$$Lw%X%Ca49(P9-?Tg-5Rhk1(xdb2tpq*X
zJ@=K@RDM1(9H7X;OV-b2+9MLtZ`s{Z>*82#(A_Jgp|&zglIvs*8XZ)SP#{yky_>o~
zr!G>VZIKoQjasnGXem3>(AhnmoHRmN7$NX4ckpQZY8RnJgKfxU;ZZ2L6f(-0)uLV*
zt}*m7(5CX9oT{ElZpp>Sz0qvC^pyiqP4ii(AAPAk@TdK5-Y
z=EK-Qti)O5>bjXddA-iY`fRbny}TPI{1^pfZ$|iJboP&<;XWX?N|Ia!5M|Afve=xe
zrN7H_J=SDl7JK37R1_gH4C)pqJchx;9?u|>5E9=DJ=`o->GUs#N5vaYSV=-RiMTdJ
z1Qb0jx5t&;GOHRLs0Pj7aZ=!Z+zYt<2~AkRkVja;Sk^l}N!=WS7z2NX6HQf9ghf+A
z`qCTF7AMr}f6uWjqF+kNt$q9vuKG}?ikpP~+RWa_u4SJcx0K4uEKk+|SMP~LSX|o!
zB>N%JEMzTPOZ@Wyy2FZ%&@GFi8D7OB+{t*n?PIum^&(J7^>*$UGQ?tM@y8qwRTEOb$c4tx
z^XH3eLbOk_?s9tgu;YFd5>B8Ts|g0%Hj5)-VoY40tC!*dgw`ZHyyctOUDZt&gmp#H
z@6a~iaG2YEtB)D8tWsU5Ij?-K+Ab#{q3KjKMOSsGT)JypQMh@LkfB!S$kUTkRpm=e
zvfgu%98t=EZ!+p>vSr(IY|Bl$m`LSghs<11q*>z0A9w(zFzFL=9^nvz*
zr9`Li3e7pSD)j`Q!^;$4Cr9MdXvg1ZZm
z1XuI7KynZeniH$AwRc%gWFSUs$LRvT6>^cj+HYm1vnUPD)1t9jF2YsY~@rjnNUzWJ)_JcIC?_pF|fEz?9doTzJ3&tYt-cW1Aqj|
zL9~fKoxaE}RCkfj$?2wxT9esI!lXUk`%p2^NR+c$F*Gc$wUy-EAOCeBYPdROnC=IF
za78ag#MYU;YG7f@Nl8~l+q5*{o<@yV*O}iQ-vubbvHXP3?PY2eh^b(t1k|FcJhPF*
zyh)XJzMJMmq?9x)XyaEji<;4$|G6sxQ|}G>LYsbWF{|ZsjgpajgX*&oa1Ill5hIIp
zuDL;UG+u?gJFGhRA|9eg#xK7xmqNb+(iA%!$J6DJn%E|C#~zubTn+_HS-5(p{EJl2jC^wQOx;uTRFhms&=Ugj1&@=zL0#8W0(ir*Obz9j+lC2
zmloD*#x`23##t*(xyHHj`jhS2JHOXcQD{W==+n;p52sl159-rZICn5TcgOw9;MRi}
zap)0VJy1$rQXRn#ov%L~*1~^qSZDfZYj*{bs30L)4Z2(W>6|$dy_yPcar0;vJ2rS~
zB(79xTopQv*t1a2ee|O=sEg*_tSY#lel@?cF(~Z_BD#B$z0v-s|)f8FJOzP;OV`58ScIPwH$f1fWrHOQZe}P!mfV7Xe7RR<1JBC)Au9ijc
zma!Ud!g?Y!X;QRD*wm**kyXG0fb4?)sZt;iNX5gm8(GW3tCZyT7Ry?BphBN(&!ojM
zsU!R)NzM3TFb)Xcu4Pam#K=esBU~ZS9PqAaI@!K1FeJYMG$YxW!jo98uKHCcUWQwt
z(hk#LqOOD8Zo2Hgt{aTce0u;FvHgM7`x8a-vo`qeD3ae`A%9@?nmRYm6OM2D1&>@G
ze!XcYQH?eHgrgwV$4Xj%{pVly1aeN=7ecT{NuQ)YOB>}`snd;^t#6utcdjG(_5d1K
zQ2xjJe`734N@^7--#Co{BE)eH3K#P0*EQY!Pj
z{e&(kB@vh&wcmlXN&s74
zVmXj&k(^<<322d3QQEmshP788@QP>ol5jJd&h5mc;t
zJ(c@tNnpNwYRR=ywVG2|YhH^M_b8?f9az;8o79e%&T0oC#z@-9t5lg<@K}UTQ$mqfmv-SyK+Hq@${3_Ih=sTKB_|%8iIv!vHWJT^B5#<6>Bcovpgb^Rly`EQN)gB
zsb`}x#f5`d38FHzE$HJOmLgr;0d!eO8pTK>5LbK+(H?
zN^{EO^{{@v+AaPe`Y~~W#cy~Pr5G)gWfF?
zwsk0C3Pu2$)xM5v$;dohpJIRD-0XsbwU#JTyr8>fQaAiG{z$G{UHwsX&U*)*8W)^V
z%!Fy*GqP@Ry7u@qQ)n+PU22I*s{O8{q}0Q}f6FpOP^JC_;Psz^ME^^8=(SVvx9tW<
zH1*%nmjbWpp&=;ScSHgAol%l)e5{ogksY>Ky>%t94k}mVLKOUWD64#e(55>UZ#TB4CHj3zIY_kC**T~M<;)Og=i9Q}
zNB`Pwgn~J}sL;0*G)M?9553*jYA!dDubygrhG}{-IZL0-vo9fSVp;yKl^Dix(8&>@
z5E?r5ZaN0bp5KhIl0(=9lav+W!nOdgUaEmMTTOdKxyzj@35{&-3|E}%pBM6@8ykD3
zQ9(2Ob`3;mODL)Yd#o>O1GYy4$i4l#Du+Aom6Z*tb?ZPro=9?uhMG~~y=1?on0O}I
zPg$1CZ>htFoS2HNoutFtr$aX?_bE>;*1MdEq+{DRGp1fpn