From 4d9144eca5fb5fcd3ca7f7adeab99b24b29ade83 Mon Sep 17 00:00:00 2001
From: "Michael S. Molina" <70410625+michael-s-molina@users.noreply.github.com>
Date: Thu, 18 Jan 2024 11:59:08 -0300
Subject: [PATCH] refactor: Migrates legacy Sunburst charts to ECharts and
removes legacy code (#26350)
---
.../cypress/e2e/dashboard/utils.ts | 2 +-
.../explore/visualizations/sunburst.test.js | 31 +-
superset-frontend/package-lock.json | 27 -
superset-frontend/package.json | 1 -
.../test/chart/fixtures/formData.ts | 4 +-
.../packages/superset-ui-demo/package.json | 1 -
.../legacy-plugin-chart-sunburst/Stories.tsx | 63 ---
.../legacy-plugin-chart-sunburst/data.ts | 32 --
.../ChartDataProviderStories.tsx | 3 -
.../legacy-plugin-chart-sunburst/CHANGELOG.md | 35 --
.../legacy-plugin-chart-sunburst/README.md | 52 --
.../legacy-plugin-chart-sunburst/package.json | 37 --
.../src/ReactSunburst.jsx | 66 ---
.../src/Sunburst.js | 531 ------------------
.../src/controlPanel.ts | 108 ----
.../src/images/example.png | Bin 141954 -> 0 bytes
.../src/images/thumbnail.png | Bin 21011 -> 0 bytes
.../src/images/thumbnailLarge.png | Bin 51408 -> 0 bytes
.../legacy-plugin-chart-sunburst/src/index.js | 47 --
.../src/transformProps.js | 45 --
.../src/utils/wrapSvgText.js | 71 ---
.../tsconfig.json | 25 -
.../src/Sunburst/index.ts | 2 +-
.../spec/fixtures/mockSliceEntities.js | 2 +-
.../SliceHeaderControls.test.tsx | 8 +-
.../VizTypeControl/VizTypeGallery.tsx | 1 -
.../src/visualizations/presets/MainPreset.js | 2 -
...Vaccine_Candidates_per_Country__Stage.yaml | 10 +-
.../examples/supported_charts_dashboard.py | 6 +-
superset/examples/world_bank.py | 6 +-
...-41_a32e0c4d8646_migrate_sunburst_chart.py | 44 ++
superset/viz.py | 49 --
32 files changed, 82 insertions(+), 1229 deletions(-)
delete mode 100644 superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-sunburst/Stories.tsx
delete mode 100644 superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-sunburst/data.ts
delete mode 100644 superset-frontend/plugins/legacy-plugin-chart-sunburst/CHANGELOG.md
delete mode 100644 superset-frontend/plugins/legacy-plugin-chart-sunburst/README.md
delete mode 100644 superset-frontend/plugins/legacy-plugin-chart-sunburst/package.json
delete mode 100644 superset-frontend/plugins/legacy-plugin-chart-sunburst/src/ReactSunburst.jsx
delete mode 100644 superset-frontend/plugins/legacy-plugin-chart-sunburst/src/Sunburst.js
delete mode 100644 superset-frontend/plugins/legacy-plugin-chart-sunburst/src/controlPanel.ts
delete mode 100644 superset-frontend/plugins/legacy-plugin-chart-sunburst/src/images/example.png
delete mode 100644 superset-frontend/plugins/legacy-plugin-chart-sunburst/src/images/thumbnail.png
delete mode 100644 superset-frontend/plugins/legacy-plugin-chart-sunburst/src/images/thumbnailLarge.png
delete mode 100644 superset-frontend/plugins/legacy-plugin-chart-sunburst/src/index.js
delete mode 100644 superset-frontend/plugins/legacy-plugin-chart-sunburst/src/transformProps.js
delete mode 100644 superset-frontend/plugins/legacy-plugin-chart-sunburst/src/utils/wrapSvgText.js
delete mode 100644 superset-frontend/plugins/legacy-plugin-chart-sunburst/tsconfig.json
create mode 100644 superset/migrations/versions/2024-01-18_14-41_a32e0c4d8646_migrate_sunburst_chart.py
diff --git a/superset-frontend/cypress-base/cypress/e2e/dashboard/utils.ts b/superset-frontend/cypress-base/cypress/e2e/dashboard/utils.ts
index c63df51d10..ebcd7d6d0d 100644
--- a/superset-frontend/cypress-base/cypress/e2e/dashboard/utils.ts
+++ b/superset-frontend/cypress-base/cypress/e2e/dashboard/utils.ts
@@ -25,7 +25,7 @@ export const WORLD_HEALTH_CHARTS = [
{ name: 'Most Populated Countries', viz: 'table' },
{ name: "World's Population", viz: 'big_number' },
{ name: 'Growth Rate', viz: 'line' },
- { name: 'Rural Breakdown', viz: 'sunburst' },
+ { name: 'Rural Breakdown', viz: 'sunburst_v2' },
{ name: "World's Pop Growth", viz: 'area' },
{ name: 'Life Expectancy VS Rural %', viz: 'bubble' },
{ name: 'Treemap', viz: 'treemap_v2' },
diff --git a/superset-frontend/cypress-base/cypress/e2e/explore/visualizations/sunburst.test.js b/superset-frontend/cypress-base/cypress/e2e/explore/visualizations/sunburst.test.js
index 03090db9c4..4d55d592c8 100644
--- a/superset-frontend/cypress-base/cypress/e2e/explore/visualizations/sunburst.test.js
+++ b/superset-frontend/cypress-base/cypress/e2e/explore/visualizations/sunburst.test.js
@@ -18,17 +18,17 @@
*/
describe('Visualization > Sunburst', () => {
beforeEach(() => {
- cy.intercept('POST', '/superset/explore_json/**').as('getJson');
+ cy.intercept('POST', '/api/v1/chart/data**').as('chartData');
});
const SUNBURST_FORM_DATA = {
datasource: '2__table',
- viz_type: 'sunburst',
+ viz_type: 'sunburst_v2',
slice_id: 47,
granularity_sqla: 'year',
time_grain_sqla: 'P1D',
time_range: 'No filter',
- groupby: ['region'],
+ columns: ['region'],
metric: 'sum__SP_POP_TOTL',
adhoc_filters: [],
row_limit: 50000,
@@ -37,32 +37,35 @@ describe('Visualization > Sunburst', () => {
function verify(formData) {
cy.visitChartByParams(formData);
- cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
+ cy.verifySliceSuccess({ waitAlias: '@chartData' });
}
- it('should work without secondary metric', () => {
+ // requires the ability to render charts using SVG only for tests
+ it.skip('should work without secondary metric', () => {
verify(SUNBURST_FORM_DATA);
- // There should be 7 visible arcs + 1 hidden
- cy.get('.chart-container svg g#arcs path').should('have.length', 8);
+ cy.get('.chart-container svg g path').should('have.length', 7);
});
- it('should work with secondary metric', () => {
+ // requires the ability to render charts using SVG only for tests
+ it.skip('should work with secondary metric', () => {
verify({
...SUNBURST_FORM_DATA,
secondary_metric: 'sum__SP_RUR_TOTL',
});
- cy.get('.chart-container svg g#arcs path').should('have.length', 8);
+ cy.get('.chart-container svg g path').should('have.length', 7);
});
- it('should work with multiple groupbys', () => {
+ // requires the ability to render charts using SVG only for tests
+ it.skip('should work with multiple columns', () => {
verify({
...SUNBURST_FORM_DATA,
- groupby: ['region', 'country_name'],
+ columns: ['region', 'country_name'],
});
- cy.get('.chart-container svg g#arcs path').should('have.length', 117);
+ cy.get('.chart-container svg g path').should('have.length', 221);
});
- it('should work with filter', () => {
+ // requires the ability to render charts using SVG only for tests
+ it.skip('should work with filter', () => {
verify({
...SUNBURST_FORM_DATA,
adhoc_filters: [
@@ -77,7 +80,7 @@ describe('Visualization > Sunburst', () => {
},
],
});
- cy.get('.chart-container svg g#arcs path').should('have.length', 3);
+ cy.get('.chart-container svg g path').should('have.length', 2);
});
it('should allow type to search color schemes', () => {
diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json
index 35f211effb..e4af285544 100644
--- a/superset-frontend/package-lock.json
+++ b/superset-frontend/package-lock.json
@@ -39,7 +39,6 @@
"@superset-ui/legacy-plugin-chart-rose": "file:./plugins/legacy-plugin-chart-rose",
"@superset-ui/legacy-plugin-chart-sankey": "file:./plugins/legacy-plugin-chart-sankey",
"@superset-ui/legacy-plugin-chart-sankey-loop": "file:./plugins/legacy-plugin-chart-sankey-loop",
- "@superset-ui/legacy-plugin-chart-sunburst": "file:./plugins/legacy-plugin-chart-sunburst",
"@superset-ui/legacy-plugin-chart-world-map": "file:./plugins/legacy-plugin-chart-world-map",
"@superset-ui/legacy-preset-chart-deckgl": "file:./plugins/legacy-preset-chart-deckgl",
"@superset-ui/legacy-preset-chart-nvd3": "file:./plugins/legacy-preset-chart-nvd3",
@@ -18338,10 +18337,6 @@
"resolved": "plugins/legacy-plugin-chart-sankey-loop",
"link": true
},
- "node_modules/@superset-ui/legacy-plugin-chart-sunburst": {
- "resolved": "plugins/legacy-plugin-chart-sunburst",
- "link": true
- },
"node_modules/@superset-ui/legacy-plugin-chart-world-map": {
"resolved": "plugins/legacy-plugin-chart-world-map",
"link": true
@@ -62257,7 +62252,6 @@
"@superset-ui/legacy-plugin-chart-rose": "*",
"@superset-ui/legacy-plugin-chart-sankey": "*",
"@superset-ui/legacy-plugin-chart-sankey-loop": "*",
- "@superset-ui/legacy-plugin-chart-sunburst": "*",
"@superset-ui/legacy-plugin-chart-time-table": "*",
"@superset-ui/legacy-plugin-chart-world-map": "*",
"@superset-ui/legacy-preset-chart-deckgl": "*",
@@ -63291,20 +63285,6 @@
"react": "^16.13.1"
}
},
- "plugins/legacy-plugin-chart-sunburst": {
- "name": "@superset-ui/legacy-plugin-chart-sunburst",
- "version": "0.18.25",
- "license": "Apache-2.0",
- "dependencies": {
- "d3": "^3.5.17",
- "prop-types": "^15.8.1"
- },
- "peerDependencies": {
- "@superset-ui/chart-controls": "*",
- "@superset-ui/core": "*",
- "react": "^16.13.1"
- }
- },
"plugins/legacy-plugin-chart-time-table": {
"name": "@superset-ui/legacy-plugin-chart-time-table",
"version": "0.0.1",
@@ -78157,13 +78137,6 @@
"prop-types": "^15.8.1"
}
},
- "@superset-ui/legacy-plugin-chart-sunburst": {
- "version": "file:plugins/legacy-plugin-chart-sunburst",
- "requires": {
- "d3": "^3.5.17",
- "prop-types": "^15.8.1"
- }
- },
"@superset-ui/legacy-plugin-chart-world-map": {
"version": "file:plugins/legacy-plugin-chart-world-map",
"requires": {
diff --git a/superset-frontend/package.json b/superset-frontend/package.json
index 4aeb85c6e1..4cbff6e5e9 100644
--- a/superset-frontend/package.json
+++ b/superset-frontend/package.json
@@ -105,7 +105,6 @@
"@superset-ui/legacy-plugin-chart-rose": "file:./plugins/legacy-plugin-chart-rose",
"@superset-ui/legacy-plugin-chart-sankey": "file:./plugins/legacy-plugin-chart-sankey",
"@superset-ui/legacy-plugin-chart-sankey-loop": "file:./plugins/legacy-plugin-chart-sankey-loop",
- "@superset-ui/legacy-plugin-chart-sunburst": "file:./plugins/legacy-plugin-chart-sunburst",
"@superset-ui/legacy-plugin-chart-world-map": "file:./plugins/legacy-plugin-chart-world-map",
"@superset-ui/legacy-preset-chart-deckgl": "file:./plugins/legacy-preset-chart-deckgl",
"@superset-ui/legacy-preset-chart-nvd3": "file:./plugins/legacy-preset-chart-nvd3",
diff --git a/superset-frontend/packages/superset-ui-core/test/chart/fixtures/formData.ts b/superset-frontend/packages/superset-ui-core/test/chart/fixtures/formData.ts
index 9d926f4613..88a78c6017 100644
--- a/superset-frontend/packages/superset-ui-core/test/chart/fixtures/formData.ts
+++ b/superset-frontend/packages/superset-ui-core/test/chart/fixtures/formData.ts
@@ -56,13 +56,13 @@ export const wordCloudFormData = {
export const sunburstFormData = {
datasource: '2__table',
- viz_type: 'sunburst',
+ viz_type: 'sunburst_v2',
slice_id: 47,
url_params: {},
granularity_sqla: 'year',
time_grain_sqla: 'P1D',
time_range: '2011-01-01 : 2011-01-01',
- groupby: ['region', 'country_name'],
+ columns: ['region', 'country_name'],
metric: 'sum__SP_POP_TOTL',
secondary_metric: 'sum__SP_RUR_TOTL',
adhoc_filters: [],
diff --git a/superset-frontend/packages/superset-ui-demo/package.json b/superset-frontend/packages/superset-ui-demo/package.json
index 883165a532..7c04c590a3 100644
--- a/superset-frontend/packages/superset-ui-demo/package.json
+++ b/superset-frontend/packages/superset-ui-demo/package.json
@@ -80,7 +80,6 @@
"@superset-ui/legacy-plugin-chart-rose": "*",
"@superset-ui/legacy-plugin-chart-sankey": "*",
"@superset-ui/legacy-plugin-chart-sankey-loop": "*",
- "@superset-ui/legacy-plugin-chart-sunburst": "*",
"@superset-ui/legacy-plugin-chart-time-table": "*",
"@superset-ui/legacy-plugin-chart-world-map": "*",
"@superset-ui/legacy-preset-chart-deckgl": "*",
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-sunburst/Stories.tsx b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-sunburst/Stories.tsx
deleted file mode 100644
index 35b6388be7..0000000000
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-sunburst/Stories.tsx
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.
- */
-
-/* eslint-disable no-magic-numbers */
-import React from 'react';
-import { SuperChart } from '@superset-ui/core';
-import SunburstChartPlugin from '@superset-ui/legacy-plugin-chart-sunburst';
-import ResizableChartDemo from '../../../shared/components/ResizableChartDemo';
-import data from './data';
-
-new SunburstChartPlugin().configure({ key: 'sunburst' }).register();
-
-export default {
- title: 'Legacy Chart Plugins/legacy-plugin-chart-sunburst',
-};
-
-export const basic = () => (
-
-);
-
-export const resizable = () => (
-
- {({ width, height }) => (
-
- )}
-
-);
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-sunburst/data.ts b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-sunburst/data.ts
deleted file mode 100644
index 69df74de4d..0000000000
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-sunburst/data.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.
- */
-
-/* eslint-disable sort-keys, no-magic-numbers */
-export default [
- ['East Asia & Pacific', 'China', 1344130000.0, 664363135.0],
- ['South Asia', 'India', 1247446011.0, 857294797.0],
- ['North America', 'United States', 311721632.0, 59414143.0],
- ['East Asia & Pacific', 'Indonesia', 244808254.0, 120661092.0],
- ['Latin America & Caribbean', 'Brazil', 200517584.0, 30833589.0],
- ['South Asia', 'Pakistan', 173669648.0, 109399721.0],
- ['Sub-Saharan Africa', 'Nigeria', 163770669.0, 91118725.0],
- ['South Asia', 'Bangladesh', 153405612.0, 105504710.0],
- ['Europe & Central Asia', 'Russian Federation', 142960868.0, 37552961.0],
- ['East Asia & Pacific', 'Japan', 127817277.0, 11186568.0],
-];
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/superset-ui-chart/ChartDataProviderStories.tsx b/superset-frontend/packages/superset-ui-demo/storybook/stories/superset-ui-chart/ChartDataProviderStories.tsx
index ddf21df792..1abc9ee65c 100644
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/superset-ui-chart/ChartDataProviderStories.tsx
+++ b/superset-frontend/packages/superset-ui-demo/storybook/stories/superset-ui-chart/ChartDataProviderStories.tsx
@@ -27,7 +27,6 @@ import {
} from '@superset-ui/core';
import { BigNumberChartPlugin } from '@superset-ui/plugin-chart-echarts';
import LegacySankeyPlugin from '@superset-ui/legacy-plugin-chart-sankey';
-import LegacySunburstPlugin from '@superset-ui/legacy-plugin-chart-sunburst';
import { WordCloudChartPlugin } from '@superset-ui/plugin-chart-word-cloud';
import {
@@ -50,8 +49,6 @@ new BigNumberChartPlugin().configure({ key: BIG_NUMBER }).register();
// eslint-disable-next-line
new LegacySankeyPlugin().configure({ key: SANKEY }).register();
// eslint-disable-next-line
-new LegacySunburstPlugin().configure({ key: SUNBURST }).register();
-// eslint-disable-next-line
new WordCloudChartPlugin().configure({ key: WORD_CLOUD }).register();
const VIS_TYPES = [BIG_NUMBER, SANKEY, SUNBURST, WORD_CLOUD, WORD_CLOUD_LEGACY];
diff --git a/superset-frontend/plugins/legacy-plugin-chart-sunburst/CHANGELOG.md b/superset-frontend/plugins/legacy-plugin-chart-sunburst/CHANGELOG.md
deleted file mode 100644
index 01a75d202c..0000000000
--- a/superset-frontend/plugins/legacy-plugin-chart-sunburst/CHANGELOG.md
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-# Change Log
-
-All notable changes to this project will be documented in this file.
-See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
-
-# [0.18.0](https://github.com/apache-superset/superset-ui/compare/v0.17.87...v0.18.0) (2021-08-30)
-
-**Note:** Version bump only for package @superset-ui/legacy-plugin-chart-sunburst
-
-
-
-
-
-## [0.17.61](https://github.com/apache-superset/superset-ui/compare/v0.17.60...v0.17.61) (2021-07-02)
-
-**Note:** Version bump only for package @superset-ui/legacy-plugin-chart-sunburst
diff --git a/superset-frontend/plugins/legacy-plugin-chart-sunburst/README.md b/superset-frontend/plugins/legacy-plugin-chart-sunburst/README.md
deleted file mode 100644
index 20bfb8a483..0000000000
--- a/superset-frontend/plugins/legacy-plugin-chart-sunburst/README.md
+++ /dev/null
@@ -1,52 +0,0 @@
-
-
-## @superset-ui/legacy-plugin-chart-sunburst
-
-[![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-sunburst.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-sunburst)
-[![David (path)](https://img.shields.io/david/apache-superset/superset-ui-plugins.svg?path=packages%2Fsuperset-ui-legacy-plugin-chart-sunburst&style=flat-square)](https://david-dm.org/apache-superset/superset-ui-plugins?path=packages/superset-ui-legacy-plugin-chart-sunburst)
-
-This plugin provides Sunburst for Superset.
-
-### Usage
-
-Configure `key`, which can be any `string`, and register the plugin. This `key` will be used to
-lookup this chart throughout the app.
-
-```js
-import SunburstChartPlugin from '@superset-ui/legacy-plugin-chart-sunburst';
-
-new SunburstChartPlugin().configure({ key: 'sunburst' }).register();
-```
-
-Then use it via `SuperChart`. See
-[storybook](https://apache-superset.github.io/superset-ui-plugins/?selectedKind=plugin-chart-sunburst)
-for more details.
-
-```js
-
-```
diff --git a/superset-frontend/plugins/legacy-plugin-chart-sunburst/package.json b/superset-frontend/plugins/legacy-plugin-chart-sunburst/package.json
deleted file mode 100644
index fd2a5405a3..0000000000
--- a/superset-frontend/plugins/legacy-plugin-chart-sunburst/package.json
+++ /dev/null
@@ -1,37 +0,0 @@
-{
- "name": "@superset-ui/legacy-plugin-chart-sunburst",
- "version": "0.18.25",
- "description": "Superset Legacy Chart - Sunburst",
- "keywords": [
- "superset"
- ],
- "homepage": "https://github.com/apache/superset/tree/master/superset-frontend/plugins/legacy-plugin-chart-sunburst#readme",
- "bugs": {
- "url": "https://github.com/apache/superset/issues"
- },
- "repository": {
- "type": "git",
- "url": "https://github.com/apache/superset.git",
- "directory": "superset-frontend/plugins/legacy-plugin-chart-sunburst"
- },
- "license": "Apache-2.0",
- "author": "Superset",
- "main": "lib/index.js",
- "module": "esm/index.js",
- "files": [
- "esm",
- "lib"
- ],
- "dependencies": {
- "d3": "^3.5.17",
- "prop-types": "^15.8.1"
- },
- "peerDependencies": {
- "@superset-ui/chart-controls": "*",
- "@superset-ui/core": "*",
- "react": "^16.13.1"
- },
- "publishConfig": {
- "access": "public"
- }
-}
diff --git a/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/ReactSunburst.jsx b/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/ReactSunburst.jsx
deleted file mode 100644
index 10e959285b..0000000000
--- a/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/ReactSunburst.jsx
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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 { reactify, styled } from '@superset-ui/core';
-import Component from './Sunburst';
-
-const ReactComponent = reactify(Component);
-
-const Sunburst = ({ className, ...otherProps }) => (
-
-
-
-);
-
-export default styled(Sunburst)`
- ${({ theme }) => `
- .superset-legacy-chart-sunburst text {
- text-rendering: optimizeLegibility;
- }
- .superset-legacy-chart-sunburst path {
- stroke: ${theme.colors.grayscale.light2};
- stroke-width: 0.5px;
- }
- .superset-legacy-chart-sunburst .center-label {
- text-anchor: middle;
- fill: ${theme.colors.grayscale.dark1};
- pointer-events: none;
- }
- .superset-legacy-chart-sunburst .path-abs-percent {
- font-size: ${theme.typography.sizes.m}px;
- font-weight: ${theme.typography.weights.bold};
- }
- .superset-legacy-chart-sunburst .path-cond-percent {
- font-size: ${theme.typography.sizes.s}px;
- }
- .superset-legacy-chart-sunburst .path-metrics {
- color: ${theme.colors.grayscale.base};
- }
- .superset-legacy-chart-sunburst .path-ratio {
- color: ${theme.colors.grayscale.base};
- }
-
- .superset-legacy-chart-sunburst .breadcrumbs text {
- font-weight: ${theme.typography.weights.bold};
- font-size: ${theme.typography.sizes.m}px;
- text-anchor: middle;
- fill: ${theme.colors.grayscale.dark1};
- }
- `}
-`;
diff --git a/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/Sunburst.js b/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/Sunburst.js
deleted file mode 100644
index 138788495c..0000000000
--- a/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/Sunburst.js
+++ /dev/null
@@ -1,531 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.
- */
-/* eslint-disable no-param-reassign, react/sort-prop-types */
-import d3 from 'd3';
-import PropTypes from 'prop-types';
-import {
- getNumberFormatter,
- NumberFormats,
- CategoricalColorNamespace,
- getSequentialSchemeRegistry,
- t,
-} from '@superset-ui/core';
-import wrapSvgText from './utils/wrapSvgText';
-
-const propTypes = {
- // Each row is an array of [hierarchy-lvl1, hierarchy-lvl2, metric1, metric2]
- // hierarchy-lvls are string. metrics are number
- data: PropTypes.arrayOf(PropTypes.array),
- width: PropTypes.number,
- height: PropTypes.number,
- colorScheme: PropTypes.string,
- linearColorScheme: PropTypes.string,
- numberFormat: PropTypes.string,
- metrics: PropTypes.arrayOf(
- PropTypes.oneOfType([
- PropTypes.string,
- PropTypes.object, // The metric object
- ]),
- ),
-};
-
-function metricLabel(metric) {
- return typeof metric === 'string' || metric instanceof String
- ? metric
- : metric.label;
-}
-
-// Given a node in a partition layout, return an array of all of its ancestor
-// nodes, highest first, but excluding the root.
-function getAncestors(node) {
- const path = [];
- let current = node;
- while (current.parent) {
- path.unshift(current);
- current = current.parent;
- }
-
- return path;
-}
-
-function buildHierarchy(rows) {
- const root = {
- name: 'root',
- children: [],
- };
-
- // each record [groupby1val, groupby2val, ( or 0)n, m1, m2]
- rows.forEach(row => {
- const m1 = Number(row[row.length - 2]);
- const m2 = Number(row[row.length - 1]);
- const levels = row.slice(0, -2);
- if (Number.isNaN(m1)) {
- // e.g. if this is a header row
- return;
- }
- let currentNode = root;
- for (let level = 0; level < levels.length; level += 1) {
- const children = currentNode.children || [];
- const node = levels[level];
- const nodeName = node ? node.toString() : t('N/A');
- // If the next node has the name '0', it will
- const isLeafNode = level >= levels.length - 1 || levels[level + 1] === 0;
- let childNode;
-
- if (!isLeafNode) {
- childNode = children.find(
- child => child.name === nodeName && child.level === level,
- );
-
- if (!childNode) {
- childNode = {
- name: nodeName,
- children: [],
- level,
- };
- children.push(childNode);
- }
- currentNode = childNode;
- } else if (nodeName !== 0) {
- // Reached the end of the sequence; create a leaf node.
- childNode = {
- name: nodeName,
- m1,
- m2,
- };
- children.push(childNode);
- }
- }
- });
-
- function recurse(node) {
- if (node.children) {
- let sums;
- let m1 = 0;
- let m2 = 0;
- for (let i = 0; i < node.children.length; i += 1) {
- sums = recurse(node.children[i]);
- m1 += sums[0];
- m2 += sums[1];
- }
- node.m1 = m1;
- node.m2 = m2;
- }
-
- return [node.m1, node.m2];
- }
-
- recurse(root);
-
- return root;
-}
-
-function getResponsiveContainerClass(width) {
- if (width > 500) {
- return 'l';
- }
-
- if (width > 200 && width <= 500) {
- return 'm';
- }
-
- return 's';
-}
-
-function getYOffset(width) {
- if (width > 500) {
- return ['0', '20', '40', '60'];
- }
-
- if (width > 200 && width <= 500) {
- return ['0', '15', '30', '45'];
- }
-
- return ['0', '10', '20', '30'];
-}
-
-// Modified from http://bl.ocks.org/kerryrodden/7090426
-function Sunburst(element, props) {
- const container = d3.select(element);
- const {
- data,
- width,
- height,
- colorScheme,
- linearColorScheme,
- metrics,
- numberFormat,
- sliceId,
- } = props;
- const responsiveClass = getResponsiveContainerClass(width);
- const isSmallWidth = responsiveClass === 's';
- container.attr('class', `superset-legacy-chart-sunburst ${responsiveClass}`);
- // vars with shared scope within this function
- const margin = { top: 10, right: 5, bottom: 10, left: 5 };
- const containerWidth = width;
- const containerHeight = height;
- const breadcrumbHeight = containerHeight * 0.085;
- const visWidth = containerWidth - margin.left - margin.right;
- const visHeight =
- containerHeight - margin.top - margin.bottom - breadcrumbHeight;
- const radius = Math.min(visWidth, visHeight) / 2;
-
- let colorByCategory = true; // color by category if primary/secondary metrics match
- let maxBreadcrumbs;
- let breadcrumbDims; // set based on data
- let totalSize; // total size of all segments; set after loading the data.
- let breadcrumbs;
- let vis;
- let arcs;
- let gMiddleText; // dom handles
-
- const categoricalColorScale = CategoricalColorNamespace.getScale(colorScheme);
- let linearColorScale;
-
- // Helper + path gen functions
- const partition = d3.layout
- .partition()
- .size([2 * Math.PI, radius * radius])
- .value(d => d.m1);
-
- const arc = d3.svg
- .arc()
- .startAngle(d => d.x)
- .endAngle(d => d.x + d.dx)
- .innerRadius(d => Math.sqrt(d.y))
- .outerRadius(d => Math.sqrt(d.y + d.dy));
-
- const formatNum = getNumberFormatter(
- numberFormat || NumberFormats.SI_3_DIGIT,
- );
- const formatPerc = getNumberFormatter(NumberFormats.PERCENT_3_POINT);
-
- container.select('svg').remove();
-
- const svg = container
- .append('svg:svg')
- .attr('width', containerWidth)
- .attr('height', containerHeight);
-
- function createBreadcrumbs(firstRowData) {
- // -2 bc row contains 2x metrics, +extra for %label and buffer
- maxBreadcrumbs = firstRowData.length - 2 + 1;
- breadcrumbDims = {
- width: visWidth / maxBreadcrumbs,
- height: breadcrumbHeight * 0.8, // more margin
- spacing: 3,
- tipTailWidth: 10,
- };
-
- breadcrumbs = svg
- .append('svg:g')
- .attr('class', 'breadcrumbs')
- .attr('transform', `translate(${margin.left},${margin.top})`);
-
- breadcrumbs.append('svg:text').attr('class', 'end-label');
- }
-
- // Generate a string that describes the points of a breadcrumb polygon.
- function breadcrumbPoints(d, i) {
- const points = [];
- if (isSmallWidth) {
- points.push('0,0');
- points.push(`${width},0`);
- points.push(`${width},0`);
- points.push(`${width},${breadcrumbDims.height}`);
- points.push(`0,${breadcrumbDims.height}`);
- if (i > 0) {
- // Leftmost breadcrumb; don't include 6th vertex.
- // points.push(`${breadcrumbDims.tipTailWidth},${breadcrumbDims.height / 2}`);
- }
- } else {
- points.push('0,0');
- points.push(`${breadcrumbDims.width},0`);
- points.push(
- `${breadcrumbDims.width + breadcrumbDims.tipTailWidth},${
- breadcrumbDims.height / 2
- }`,
- );
- points.push(`${breadcrumbDims.width},${breadcrumbDims.height}`);
- points.push(`0,${breadcrumbDims.height}`);
- if (i > 0) {
- // Leftmost breadcrumb; don't include 6th vertex.
- points.push(
- `${breadcrumbDims.tipTailWidth},${breadcrumbDims.height / 2}`,
- );
- }
- }
-
- return points.join(' ');
- }
-
- function updateBreadcrumbs(sequenceArray, percentageString) {
- const breadcrumbWidth = isSmallWidth ? width : breadcrumbDims.width;
- const g = breadcrumbs
- .selectAll('g')
- .data(sequenceArray, d => d.name + d.depth);
-
- // Add breadcrumb and label for entering nodes.
- const entering = g.enter().append('svg:g');
-
- entering
- .append('svg:polygon')
- .attr('points', breadcrumbPoints)
- .style('fill', d =>
- colorByCategory
- ? categoricalColorScale(d.name, sliceId)
- : linearColorScale(d.m2 / d.m1),
- );
-
- entering
- .append('svg:text')
- .attr('x', (breadcrumbWidth + breadcrumbDims.tipTailWidth) / 2)
- .attr('y', breadcrumbDims.height / 4)
- .attr('dy', '0.35em')
- .style('fill', d => {
- // Make text white or black based on the lightness of the background
- const col = d3.hsl(
- colorByCategory
- ? categoricalColorScale(d.name, sliceId)
- : linearColorScale(d.m2 / d.m1),
- );
-
- return col.l < 0.5 ? 'white' : 'black';
- })
- .attr('class', 'step-label')
- .text(d => d.name.replace(/_/g, ' '))
- .call(wrapSvgText, breadcrumbWidth, breadcrumbDims.height / 2);
-
- // Set position for entering and updating nodes.
- g.attr('transform', (d, i) => {
- if (isSmallWidth) {
- return `translate(0, ${
- i * (breadcrumbDims.height + breadcrumbDims.spacing)
- })`;
- }
- return `translate(${
- i * (breadcrumbDims.width + breadcrumbDims.spacing)
- }, 0)`;
- });
-
- // Remove exiting nodes.
- g.exit().remove();
-
- // Now move and update the percentage at the end.
- breadcrumbs
- .select('.end-label')
- .attr('x', () => {
- if (isSmallWidth) {
- return (breadcrumbWidth + breadcrumbDims.tipTailWidth) / 2;
- }
-
- return (
- (sequenceArray.length + 0.5) *
- (breadcrumbDims.width + breadcrumbDims.spacing)
- );
- })
- .attr('y', () => {
- if (isSmallWidth) {
- return (sequenceArray.length + 1) * breadcrumbDims.height;
- }
-
- return breadcrumbDims.height / 2;
- })
- .attr('dy', '0.35em')
- .text(percentageString);
-
- // Make the breadcrumb trail visible, if it's hidden.
- breadcrumbs.style('visibility', null);
- }
-
- // Fade all but the current sequence, and show it in the breadcrumb trail.
- function mouseenter(d) {
- const sequenceArray = getAncestors(d);
- const parentOfD = sequenceArray[sequenceArray.length - 2] || null;
-
- const absolutePercentage = (d.m1 / totalSize).toPrecision(3);
- const conditionalPercentage = parentOfD
- ? (d.m1 / parentOfD.m1).toPrecision(3)
- : null;
-
- const absolutePercString = formatPerc(absolutePercentage);
- const conditionalPercString = parentOfD
- ? formatPerc(conditionalPercentage)
- : '';
-
- // 3 levels of text if inner-most level, 4 otherwise
- const yOffsets = getYOffset(width);
- let offsetIndex = 0;
-
- // If metrics match, assume we are coloring by category
- const metricsMatch = Math.abs(d.m1 - d.m2) < 0.00001;
-
- gMiddleText.selectAll('*').remove();
-
- offsetIndex += 1;
- gMiddleText
- .append('text')
- .attr('class', 'path-abs-percent')
- .attr('y', yOffsets[offsetIndex])
- // eslint-disable-next-line prefer-template
- .text(absolutePercString + ' ' + t('of total'));
-
- const OF_PARENT_TEXT = t('of parent');
-
- if (conditionalPercString) {
- offsetIndex += 1;
- gMiddleText
- .append('text')
- .attr('class', 'path-cond-percent')
- .attr('y', yOffsets[offsetIndex])
- .text(`${conditionalPercString} ${OF_PARENT_TEXT}`);
- }
-
- offsetIndex += 1;
- gMiddleText
- .append('text')
- .attr('class', 'path-metrics')
- .attr('y', yOffsets[offsetIndex])
- .text(
- `${metricLabel(metrics[0])}: ${formatNum(d.m1)}${
- metricsMatch ? '' : `, ${metricLabel(metrics[1])}: ${formatNum(d.m2)}`
- }`,
- );
-
- offsetIndex += 1;
- gMiddleText
- .append('text')
- .attr('class', 'path-ratio')
- .attr('y', yOffsets[offsetIndex])
- .text(
- metricsMatch
- ? ''
- : `${metricLabel(metrics[1])}/${metricLabel(
- metrics[0],
- )}: ${formatPerc(d.m2 / d.m1)}`,
- );
-
- // Reset and fade all the segments.
- arcs
- .selectAll('path')
- .style('stroke-width', null)
- .style('stroke', null)
- .style('opacity', 0.3);
-
- // Then highlight only those that are an ancestor of the current segment.
- arcs
- .selectAll('path')
- .filter(node => sequenceArray.includes(node))
- .style('opacity', 1)
- .style('stroke', '#aaa');
-
- updateBreadcrumbs(sequenceArray, absolutePercString);
- }
-
- // Restore everything to full opacity when moving off the visualization.
- function mouseleave() {
- // Hide the breadcrumb trail
- breadcrumbs.style('visibility', 'hidden');
-
- gMiddleText.selectAll('*').remove();
-
- // Deactivate all segments during transition.
- arcs.selectAll('path').on('mouseenter', null);
-
- // Transition each segment to full opacity and then reactivate it.
- arcs
- .selectAll('path')
- .transition()
- .duration(200)
- .style('opacity', 1)
- .style('stroke', null)
- .style('stroke-width', null)
- .each('end', function end() {
- d3.select(this).on('mouseenter', mouseenter);
- });
- }
-
- // Main function to draw and set up the visualization, once we have the data.
- function createVisualization(rows) {
- const root = buildHierarchy(rows);
- maxBreadcrumbs = rows[0].length - 2;
- vis = svg
- .append('svg:g')
- .attr('class', 'sunburst-vis')
- .attr(
- 'transform',
- 'translate(' +
- `${margin.left + visWidth / 2},` +
- `${
- margin.top +
- (isSmallWidth
- ? breadcrumbHeight * maxBreadcrumbs
- : breadcrumbHeight) +
- visHeight / 2
- }` +
- ')',
- )
- .on('mouseleave', mouseleave);
-
- arcs = vis.append('svg:g').attr('id', 'arcs');
-
- gMiddleText = vis.append('svg:g').attr('class', 'center-label');
-
- // Bounding circle underneath the sunburst, to make it easier to detect
- // when the mouse leaves the parent g.
- arcs.append('svg:circle').attr('r', radius).style('opacity', 0);
-
- // For efficiency, filter nodes to keep only those large enough to see.
- const nodes = partition.nodes(root).filter(d => d.dx > 0.005); // 0.005 radians = 0.29 degrees
-
- if (metrics[0] !== metrics[1] && metrics[1]) {
- colorByCategory = false;
- const ext = d3.extent(nodes, d => d.m2 / d.m1);
- linearColorScale = getSequentialSchemeRegistry()
- .get(linearColorScheme)
- .createLinearScale(ext);
- }
-
- arcs
- .selectAll('path')
- .data(nodes)
- .enter()
- .append('svg:path')
- .attr('display', d => (d.depth ? null : 'none'))
- .attr('d', arc)
- .attr('fill-rule', 'evenodd')
- .style('fill', d =>
- colorByCategory
- ? categoricalColorScale(d.name, sliceId)
- : linearColorScale(d.m2 / d.m1),
- )
- .style('opacity', 1)
- .on('mouseenter', mouseenter);
-
- // Get total size of the tree = value of root node from partition.
- totalSize = root.value;
- }
- createBreadcrumbs(data[0]);
- createVisualization(data);
-}
-
-Sunburst.displayName = 'Sunburst';
-Sunburst.propTypes = propTypes;
-
-export default Sunburst;
diff --git a/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/controlPanel.ts b/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/controlPanel.ts
deleted file mode 100644
index 32b56fb9e4..0000000000
--- a/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/controlPanel.ts
+++ /dev/null
@@ -1,108 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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 { t } from '@superset-ui/core';
-import {
- ControlPanelConfig,
- ControlPanelsContainerProps,
- getStandardizedControls,
- sections,
-} from '@superset-ui/chart-controls';
-
-const config: ControlPanelConfig = {
- controlPanelSections: [
- sections.legacyRegularTime,
- {
- label: t('Query'),
- expanded: true,
- controlSetRows: [
- ['groupby'],
- ['metric'],
- ['secondary_metric'],
- ['adhoc_filters'],
- ['row_limit'],
- [
- {
- name: 'sort_by_metric',
- config: {
- type: 'CheckboxControl',
- label: t('Sort by metric'),
- description: t(
- 'Whether to sort results by the selected metric in descending order.',
- ),
- },
- },
- ],
- ],
- },
- {
- label: t('Chart Options'),
- expanded: true,
- controlSetRows: [['color_scheme'], ['linear_color_scheme']],
- },
- ],
- controlOverrides: {
- metric: {
- label: t('Primary Metric'),
- description: t(
- 'The primary metric is used to define the arc segment sizes',
- ),
- },
- secondary_metric: {
- label: t('Secondary Metric'),
- default: null,
- description: t(
- '[optional] this secondary metric is used to ' +
- 'define the color as a ratio against the primary metric. ' +
- 'When omitted, the color is categorical and based on labels',
- ),
- },
- color_scheme: {
- description: t(
- 'When only a primary metric is provided, a categorical color scale is used.',
- ),
- visibility: ({ controls }: ControlPanelsContainerProps) =>
- Boolean(
- !controls?.secondary_metric?.value ||
- controls?.secondary_metric?.value === controls?.metric.value,
- ),
- },
- linear_color_scheme: {
- description: t(
- 'When a secondary metric is provided, a linear color scale is used.',
- ),
- visibility: ({ controls }: ControlPanelsContainerProps) =>
- Boolean(
- controls?.secondary_metric?.value &&
- controls?.secondary_metric?.value !== controls?.metric.value,
- ),
- },
- groupby: {
- label: t('Hierarchy'),
- description: t('This defines the level of the hierarchy'),
- },
- },
- formDataOverrides: formData => ({
- ...formData,
- groupby: getStandardizedControls().popAllColumns(),
- metric: getStandardizedControls().shiftMetric(),
- secondary_metric: getStandardizedControls().shiftMetric(),
- }),
-};
-
-export default config;
diff --git a/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/images/example.png b/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/images/example.png
deleted file mode 100644
index 003d00e966074ceca14e5c988353b21ca646e558..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 141954
zcmeFYby!s0yEjgZv{DL44lPKhbju(q(jcAE&CneN-3UktN{57WcXvp4cgMSjM}5BM
zJ?Fiy-|zp!bq%xE+I#JLt-II#SreilC;1SK5Dg9v?x7S!ToDcqL_J0WVGSnSRZfZXFu*xQo|_rAx1(u
zzG4Z^P{vVeNUxCto}VRYj#M#Ut6qaj?^N7H{7UQ~-6g=~5cIPw*cI=l0E#}n6WPIMG%UYqv
zR*X8cd#Xlr={>TGrsstpBx>Mq$0Zh99tVGe(;X3&vcqVZ!XkQRhnqga6|Wo-PsFZE
zsoIviSm6`T82Qpa=c4$S0qRoIrX5>I(1HIPTiS({Q0p~V?xWH;@-*H2S-UmJHW|_-
zML3U5*Y*-~nc{Ik;5Ykr4T&Kt*}93h>LQRDW2*`VW;uhfCgDkMaKlZ5y70ZsaLm#s4Uq&dF{oeSG>3#%qLKz*Ee-BJ
z#Yp1oYx6)(ztNX>5jUlrq17TU!?lu$e%xIjV#Hw@biI)Hk-ff;pu+F7whIa=+$1@B
zUyH0a`Y!5?%|3X268&9OVx@9b>8)&v-&1#G`%fgTF}{j{3chrY=K4mQhE53$Un?JP
zUFI0{66eu7+bnC|%@l4j_A>kU8P-y-#j?q<`WaK+;H9WIsXvgj7om^J;v+
zyW;%T#g05|na|7ple{wZlLF3y>B=CNN
z4tfPm(+J8X1)W=eL3EC0z1CJoM2?T(+ef+u6ZreQ2IEorDzU(isbh?n63f7|H)ts!
zbTzOQ5#}K#HQ*H?UL&0Py4qk7KcH<;w}ID!ub98wfa@3Lc0qK-29c9H`1=r0;srA<
zeypUlpu$2GOOJ4&deSLef=!n$ZVWyOXES_I@@Vp-5@kIFa(G6ES?0qkpBXXUh`0{q
z$6{tV@b3br(kKYV1d{`#1~^?{{iYMKB+Lm3N=
zaY&V}#m5h=`etf)H0{QES!z5g0i*h#_T%dOe;B--aQht0ZiBarFm6MY;*Y-HdCuU@
zTK8zqXMBP2ocfw{_LCRQ0P0tei7%OtB!P4XjSP7-Ru}3t$`xw+g4HIth8!nECS70<
zdAChT|B)@PEvqe}Eq8Iq#7lSKZSn|68!
zWHPaw9Hn$;>$2UU+@ao~#G!#5vqYS}^g%|8qJOkmbXIhJ^vf>jE99)W?~*^VkrZ&h
z@r+cBpuJ-}d2zyZ5)&I68xvbNM!*;{Mx2k9FQAcKwrf_Ky)pdRR7-
c{NS)rHp(q7rU1EdAL!+7ud#|lOYhU;=}w1UzNa+?PezP!nN
zQ&1|uRwEb3Brz@*m)kv_oTd5AP53O)DvVUDUzS;gS;x9~R<3r~RsLA&(&IU}YOgHJLr+ZdKumb8{u
z+D_V>Wo&S1qgZL)$Z#bRb8is7V;S+v(KX!|s1>tLO#dqP_2BEUY(;zu`wlBR_Xn1!
zgnUju<1wQ?4ot3oRvjbHiJD-a+-DA)^F(n?MP?0)V9)w!|YSXQ>WM$
z);3l|F9}xpWO(!5O>p8TqPJ%aWVNl#+N|!cFSIsq1qqSqu~S&K9AeW-x;vfN_1gd1
zbnTX%vy9d(*36iecBXaqam%_g!u%;&*=`Yr6o#MDmqOA1DP_EtKs%$>bN}7x%zIYTc+EpTfUprk7ZaBk(C?=Dv@H5Y~Og)X?X;ycrPqpnRdO8J}stf
z>mzpK8l_T>oC<&WN?L9@c8s0LVrJ8pWJ7y{dPB8+IxLm<_81g}3dMaSJCe|mTFLAe
z9uZm0zCzl~?}z#P=?-`J$wB=_3eG+^CUMR@Fe9_=Lja@@Z+=NoPHA^dt-P4)6n&_He7t7ZluMrhJ%nHhkA}=z(MNJv@mEfpf8P<2^
z(mHo%EKffU)~`uVYk(u2?WZG&Mvp#2Lqva$J|`=cQeypmR%v6ze)#iO#>CUgXEp0<
z8|My<$E#0c*;o52xue+aj~EP9R`XUT$4b}wcjIwcP1?0KXJ)Fr9#`WPKJye{Hqu^l
zFTJo|6;i`0{_<74T3p+12lK;F_Y|MgrS-$ze&@hX)_}uh&lv
zTEje~OJd8IPPBj8KDAA7m>gXZ>2}T=(0pCC*w{7rd`qQRC8of&)^%}ncqL^eX-r}K
z*?5_%xGG295A|w`op#4XM^$<;dgns!xAmqs(+`^-;&UTe=lwD)|7I~9lu9M^c8<8X
zs-UajyF0qA^g^tpW>iJWb;6DP30IV*(X^mtoR#$)c6~FijS*XPgmPv~d_jmYM172uCo
zaA$Irkq|h3sT!=ez1wT{n)4hu)LkKO7L&$&gV`@Malv6&Bd5kNW8}+?X$F-WioxA3(u$%nZe8)A9
zK5ni3+JOnKlAZn5FCQeC1GIT<6Pz!$W8$A%szw!P*T;J1-~8Oaj3R<^YtJy$OuCu(
zSvKtq@%?n}+Dn|xzZ^d3|Ftu_6SNyJ%jYb#aGQ_pi`-92PwKfHe;0h4b6woJv`M=w
z|HvuOS=)to*Q}j=vUIi}vi|s1<8Ef*!rBY@&ZEH1!nqy&;zM2B2c4(&Q@2w`j`s3e
z{lB;`tX=0~>)1UjmISVDIx*?UNYCUhAeU+fod<80)^hqQt`4s*4c&R_@1A)#1{xc|
z@7wY5(`F(xRKoRRE{!XQ
zCHO*0>L*M2o&nRD6aV3?3(DT*rFH_m@H^0aR83)_vzX2tt&3!<72E)ay2rQ@D)#I{
zPc)UZ=P#Rh=80a)(hcI~FH&-ReVWVMB;65i)Im|hC?ITM2K^Um(k
zlP4-zBC7CDJkFk|jr;rlL=t|0A4j!&iKgA0t519^hN?+IPS>*N#Qp!f*0_h5Fbht(Z8hs
zodp)v`J?}7ZZ-%gIEa#c{{O=az>s~C|7$6*_vy}qu&9tiKckZW`}RMR5e}c{`|rKp
z4GpMZ2nI0^uIPW~jyJf``M>wV`S{=phZDT8qw)W*%)EcQi0|J2(2Iab>kVeLS(ZWh
zm-l}s;|rSmA9_JZa&RL0^BoCT|4nLeFu@@H4{Z5g!Thga{vQ@YOdzuO_Kd&73a015
zoId)zbj+UTgN#oZZbptOwzF{oEfdy4Sxz}d=oDP(t7M3Cggr@s3K$_}u`B^9prT*6
z5p)E&$-{V+c7Il$I+I0S>Rdai3X#AxaZy}%+i?$@HY#j5QvEsL7{H3>Jq~m
zwb&grxOH*j^a~EZDz9VrunM(zHnS1`A!=BEIT`8JCcRXmH3p*tJ_O8|qF#akW-Yqb
zAW{z(8B#vJS;sdw>|XRggghnx68&=RQBNLnsPs9uM+0W`;<0eP;)WGS%`mgy4ij#&
z9g)_TJN#xi4%c0OZFitj;BYbw52L{ZVsqwyd)NT<0)~j2aTh&+HONr-uU4DwGUIm$p(i&&
zgW1(9Sy0-Q6
zas%eov1kzj@UMe2t#1-vFed!C*H{c7esowo2!sWSbuu68nuBm+=Cz+RIk&U@(nm*L
z)4yd?i3K6$rOw*(H2=HQ_b{=RBO1V1aU9g}IncsAD$vTpYPSih4xP^Baz1(rn@=9f
za_ZGhBy{%xIjJl|?{i{njOF>!J
z-z!@Gtke*;Qsd_=AlRF|PN-gkj1Eh=%jQlbFXLnAW|;}
z#X9}3Bb>H7)`H-Zup6u2H1);65s?SucXAf7-J&p)!AJr!fg)$`i~B~rFnMw`zR-2f
z3(cPD<6-8<2Q!R)12Dw~lY;Ez-RlffFC$$TVwLYb3mYI&a%;HZdre02Y3~i~CJAc)
z`L*EgCMfGP!rA$^p~`{Uw9m9{*{c5N0s$H@GELV+5jOQ^>ToHVWr>RZ5EAZ+m5OW0
zgU#He>I)1QQ7%wPm|N^}-GNcDIx~6zpjj*ofW#R-nxM^HH(I+>tl>_PJiG
z@>!?tdlNIgCa~8QQz+ct&P9uxv8k9F7sH-Lk_E!?KuZE9Orqi_YL8I6sr7iMxhi6G
zpaGTLaooSv$O6T1*ClZ|^=NYx5?`(b>KQ`5WfW_$f4HA71emX1X0I0PHU(tyYiWT
zsZH!HS9$;3^BCudk$iLvAV2}u{aE|lRch{V^bc-xFs7dG@4ZUn
zXPUDam#*&9Y!8|{MW+buh)Ox5xM)b4dp0Z?)?INkKvZ7igq3`E9_K}m>As+|e9(WZ
z!sEUeZ9N=gZ?ar{yQP`=vt+w)ZLD2D+sbPO7fDZUZnfyg^;lTFlYGtHb?u%alJw!s
z-bG{GWNU*T<^D$^4nhpVW0c+|t=_*bL7
zwnwMJez{2rI?b&Vbf59cjl+>UUJsh|cM7cGue62<(!B}z=)QM%8(m+Q>N!Rt(5tKE
zc^tMI!AEAVxa+$8EoFCdC*5m|b?C?HY$$rL$ESbx<&T1Sp&*{`Csws3vi
z>t?*7*2T(7uI?hKzG~|_TkwSLVyphvoX71n&wW(YBZhyCr$553%DvaosjuK-5x@Q!
zSLj=l!d^=wBZ=L*tKCmq7I_(xg^bcys$M6mw`yE{$Zw}^-Ioerwr@j*vsTujEx_q;Bd1!;w@BKj?%w=wdr@yD0*^(%1X
z4t1Mng4BCABR7Y4p5swjQ>LA7_ip&SMp{#^$5LK;-H^>vTHm$AElY9tb&%a=7w&DO
z{94?>+SP!MRaY8IaqV&M|;PMd2V5kfnqwMzzn{BqoL
zo4ev_o8nImdE_*k_{)09(rB%Xs>Y`Q3ubljyl>v`>Ft|bc3&oMp6oxIyDc#fkCzl*
zs}l0+=UX}7(P35E^OF-<#FjtjEk-`$JfU$}Jkoxadbd2+m4k-EeAN|Ym*nbnz0W69
zS&Zzq@(En*v)fPuo$55JvP~cOk@BP3OPTQOS^}oo6#F@;SGZ7{VtVII<~!$a$PEJY
z3fJ+ji1FDi0)=kI@@+`I;w*u`441AyqCM%Rcc?ilXzwnqU!2leaV30_`GNOANVdRs
z(e+e&J(Y9L#Nl$%PqEPQ#G#f%oi`$j1p=<27Mv;rL166g7ZdF*6XbODmpjOA5qVac
z2&+3qRg;MIQ0|)R73MRYM(B~N%dUOu^DITF+4DB;%M>&kg7_dms8IYfz1|x7zGS|&
zIrAGDnTeB_R}zBP3z*g}!l3a4RsY(%Cj2_Ewa1p`&5=_wXX(Ol>TTKeiq35ob7;-o
z&EDAq)T3CI!Db6KH*PoObM7N#P@p&vJ|Oc;f|m0S^k%VFsRt*y+~gf@-&>#E^d;Tp
z-eGxM%$QZ#t(Ng`R59;c-<=2D#nqe#d1-ka=-e66SB~{1+35DR_{pz3I;C==KZW)T
z-__oEW(#ql-+RFQJw=J5S{6;wuyTiRCL8lqaPwU6@#f};i;zeJl>n;y|7Q|iHPbK==e)O9(?0xZ6
zvh*}EH
zFu|LJMwY{%RDmrwO8%|qtIHnF0wO)b^QryJ7ipNM!d5%GaURKD?uC8$$H_`QTQTzP
zYW<{yTn%z()_7DY`K07wiAmw9&{Go6`1b(@{9C6ybLGfNpP%+;aayb_2L_iYceEj*
zE9=-4Z{-VIE!fxf-Uj7*#qS?TrV6cjm9Xku_$P6TV}U~C6p^nyb`zN6whf%`Dw-R=
zHf(T9$LC|XyN5rKlKh$vP)|{oFp@}!uqX
zhh*1FpMs{rhV!iQS1+L_%(q|VvyW7-=NIa6lL8#ot_G&P8u3wl`5!g@aGDjR^X*SQ
zo4SfKBMlZVns8@2uTc*#3OZ$WKis=!3DBL>Lm;_m*+Dw*Et>6@!kXQ>;q+oIgmP*bc4IY?2^mFl-=dZd`v
zZ(i$Hl>d6+Gmq`h8;`Yrz^s#G-qb{c0B?B2Por|Y*jhAwlk^}YtBDzbh`Zl1
z6|p~bK2g|alBuWF;vpzDf9#zBlDTL&3*mvOTmh9qA=H^4ubbYPN*D9`bZVPKk2_&N
zR}W{kR=3F?${(NIq{2hRC69xGF7l$y=?Fwl$n`Y@*C$-hJ_)5bPsmsOZcF=&SCo@W
zY}NjEmcD2b9Dr1Fw>C@FKcF-1M~u|iY@H1mxbPOX>3f)L2b
zUG^X4p^`Qrl9R8`?Gk*%Mcp6+jT{YL2;g)Gy)$~a^j qLiydJm@F0*bgKdo;K7FWNy&XtCcMYE`c%*1&Evfw;A
zZj!)@G0Ay(6pU10r?GzqF2_^*@z70S4`aH>=ApUuZPbYZg4^8105Lz<`jnyQJ8?BC
zPGj@60jKyX)KijAIOk&^`NYSF@&6(cI9ZMR0_+4Ty(w-eA6Fv6^qh
z`iQGV_R*kSu3W^+M5n=`^poe4$F+_8@<4>TDd3DxGAKiF-x)-Ow)Ff+Xy|Ra)T!5b
zN2Y^$7ZTg5hD&9R;rRnI7=$_R_JpcOY`!z`d~m9L1h=WJ*tqK1_5#04_?`^SQy1aa=-@tx
z&gO4DGhX+9>LLO1SY6R2#~VZF4+8sBRvMRrv5%1@k3w1YFmTxzW|pomj_R_-ZBi&f
z>B4X#6lm3021LF(=R0Xv$7@1cLA(>p7qQOdrpcHcIn#tiE&zM#Q=r$QuxNq
zl;`O8{)G
z0!5N}xKTj$IY}sbvuJpV#TN_Q3?fZ5KX@$UaJhPt8btxes^@6-TBElu(DIZf;gyt`
z{&!lDrX~*K(B%CieTVlLjbcAnOpB_xDl|D!S5$6%2==?luGSthKdR>Ls0BQBBPZUN
zZFQ)S{jvWZonGg2#L!00tAlWq-G^;c7S$fJufiv`G%5(=>K1U~`%IRB&EW={Z}=xB
zs)$XLCKN8AkI3Y>NwrAj?1ETaytx*iKQmmCA|;=J7R9oI#0N~y5+$2fjY(12TR-NF
zXeP;bM%Y<3Z&AGR6$k685p+aZCm!IM&a(3D(w>WluTQn9IbfAwf3Tc&itt%$behF>
zT5@U`#ziS
zdD2iU0zB9zJi=u5Ap)N7{EJX#JhcJ@^zn5IH*6|iG4#Bj{xO&jTi|gi^4Qw#3uziT
zY!`!4FF-oc6PtRq!-3lTR2HP&psxfNEIhkAi{7H|&hc0D8ZF?&Hj~R>hU|?FguW3v
zK(3QLGwpb(tEsTkOm8-m5hLz-N|_oZmxK_3AfjKL%wKs!^@G3CZMwUQw;O8J*R8Al
z@O0j~w}~T<*c1>S`0>ObKNW(AUa4>qkY?C2`ZpiSgQx{9L&3JI#{D6ERXe=71K7b&
zSF5m5NSs2EeDq*Q$>}4OyO-%N#Re1R*@TBL25R1Ryqq`F!|d!oKaC3!s6^Jo@Bw4H
z;PJ~Jkc@>czu-z;I!};v6p7^!Yx*P;6tO;H@4bw=1VR5YQ+(B=yebTu1#fqAG05
zs1j(3K=vRWdf$OWIgzG`9g}=b)@*ARQ0U{*!|fzY=cmGx{eVJmqlhD*=N1jc#9lQv
zJ@h3;rFl7XVDGi~0Vftb6e(zB1$Zhoh#xArn^!(ua&fmmIi|u)zq28*_sG$6cJo%}
zswM846V%Dk{FsV?Rs!rx@PW+ZQnf=rpIqoWwd|*um74SQIOYrGSG@gqA6Ls*Gyzp~
zW+vUEyLuYtF>4hw4V47xJrVH?2G{!qK;n`8NMyZPY{~acS@fE^yfsjQNb*~u*&LO|U3<*7sH+{Vqor1hTP31|zY4_VaP<55f4{AUtNSsE}9hd?oM+jU>;
zBx$X;xQo|3HZAoHkn&3p+l@tdVFDg#%%982>GlwZ0jF;MYqum)EK
zYrWc4A5=FL%W?p=P}2#Pz^@^Ya`CMAW@nR#l-PrYjAGs67ht8oBDxY!ns!C}vXX
z$!F~}aUlww!57}}Q0_E~UsG|Ua~)KFlrSlfT;pfHecOP9OUdxmbU^Uxj4V#2
zmd4rrrXKz0^^*3OYwss_0(u`@!sfe=pxgNiZ*Lg`N2jTdjl
zdXPNGBUzH~uA%9Bpo7EOr}dgXQSsO@LLw<9zWzzE+h6oD{6%UpQS`z5CUFX%`rLLr
z)^1`88$|_tjTdN5V#k(qCP|WA$`#g0oI_cVyG{)|GR+Go$Rng)yjYvCY?_&F(#7F_0esqA?d*hvH@$Jem`j2
zXRga`%Fh#w;P6PF6n)G(?TJXKn~VdCNMjRq`Op5oNlqHB_zv9^oMZ!#!Q@~;Y1~_b
z!alqS69bF7Ig8Q*Mt;Misy5wyN`)kPFtSf
zyrtFXoZANup}UaYU+#f0{DKG}Bmq~^^Mbj}xR&8DtdRe=zNt$F7~d)UC(VKn4YELe
zbo1Lr0qfM-UQAcDXHIVFBUp{tmO{a0VT;R`0ucQ3BeNAj?ut>&Yi_e&R|)^lpwpn@)drszFV~h)8my9wBmwL-6*3c$VfAZ&
z)EQm?XCh18EGar^sPEWx^Q`%oc+HkHF4o?hjM(D~lo
z@&70YAJ^Blh;dfFS6uco%mHg`wKD+NzXBK
zP9_=rMqYFkV3lNvMCg4bIox|GxaRycLlHt-ou_&6iR|&&5aQb#2UxK<7~SXCGAyp?
zNNSVlPemApprr7y!)our7(S9@q*3jCq0W=T=i8D-J7;v(;|~G>K7&<2U2{j>k@38Q
zxtyhHu*LaN0XPU`s^=cE5CySy`q!K<*hk7y{mj$2h*1r$cCY%wCGzm9C9_DczTCgX
z?`JTt>YFTe4~3*QERC=)J~|1XnAuFdc=PS%fbU`a0IJwxV*M>J83#(vqe{}QEU;%W
zA#Qrz>3#E9{`H4XxIV?>wW^nz4<+~-~b~zhkyZ41hc3i=y>VBBIQ!wPAog+CJVo8
z_pJEMq+;@LNay*M7cE!!KRWok-qCP0IQc
z(9EyD@Sn}0(bKEOJM6fXl6$}<0_+XO4zX-NfeHAA)}|~v#$?u^(ww63CslX-`Ov>O
z$ZoB{t1v)R*JnIcfFQWe#TQCS1
z39&$Y2~+NMW*?I|cQqg{c^jqVwYQdaaZ-Y)*xl9697%&&kwn1OOobJ_J}eh2pdi
zE3DB(YjY$nl457~(|rCkfLVGaxp3<@So9fyLiQ;m>rTuU%M8cvL1;EWcPUDr5Fh}s
z*%u*D-O8AHLRVHbl8(onJY=i;ZsIR{A*9uBU(H=a{n0Su;a7Ylb2G-uK!~7{|U_cOV0;X^h@zXZ4#Cp?vllvCNTf2
z^ora9FW=7vvi!DiVGh8;#qD*9&|t3B5!Yo|M!jxzU3~ln0B*ekz^!lp3U#B}Qzg
zf2rN|q`uk-n;ZO>$zF5TkaYehf1uq60NTZ#%x`3YslOYo!q9s{=AkY^%^xcj?m;dm
zn=0As_ud&DVY1M(d^zP{NG&f$0_Hji9srWfD3YFlox=Dci6GCSLH{XYz;7A3;8dl#q`g%a1UB14G||`M|sl?6LtkO4W!D|8K{i
zd;fbb3lP}<<8a$s&=7i*utFgxHy=Mms3t4{xgHh
zS6|*J6`eJ9E5B|eot4$vzfwYC2@$@_*hNPOeGhU~Y$-UJ8XCL(>e=(d{8D{SDzn9G
zZ0t$Mve=%$oyS|rp$|KWD$T}&aa<(kOSN-@H-_EG1OI@q33{ArJSks=bzi_>E
zd&0GCiVze+8;V9GwKbgK`6x6cd2W4pYy0!W30DXj;TAFp{lW(#8by$(#D3k8Y25H1
z+a%xz98@E_$;*E%wIQ%_z^dW~*>v1eh>9f#X$B(>f;&N+shH)WpT_HsLw>
zraGEe+gUe_SBw+o!#v;cF{Shl8X5Zn$47zc;cWCT$_w9@iV|qJtTF?T582F88`2VZ
zubrIw@cE84aJgj~_H~>J-xIA$4biEA_Nr+!V5u#Pg+5#4-e6mS<4XL0I*J~`A8E13
z2YxaDzgR!P8`DieCtR9GN0YOcC4T4}?qq*sir`mwR!dy|)QkC-HvMz+EcGW;yK~)^
zZgpHZzAY*FV?;_hEQQ#E3b@S0OxiA;ADQ*l>Y<_W+US28e13iD9F
zku@O4Z~Kr7O9cVfCFs+)k9t@892qx~ZGf{aZ
zZo=A>iAPq0Z_=_e}?Emcg`9MR{bt??v;QgC&R@HL+z%A5Av~6^W;+
z>`EB}R_xyzeAEwuLLTFjYW2Sz%zgldY$N7TkBtzMo#OBrqt}@(sEQ6Q;1E92UliXj
z0VVxDAl)DWQyvAUNXPr2Ba9D^UZLjoBU8I@t2vqG*+_0;B1g$C*KsZF!wNccLj7Xx
z7e{I2Y;v!@&U}u>BXh~I_n%XywGO{Nd@58ZQ6CGGwkXsemQG^P+ew_{beKEFl%*;S
zVk;;!q30a9C
z+p1+oDa|AP1HX9)jiBo-V0|!zAE~=ZMTIT-Rld>f9_hq1JB`c!HK
z`jO>vWq&@A%0c$eAjJxuxY(KgZm-B>Uea~RH0~H`(?KUyY$u_pQD8qZJvG7FIf6$$
z+5Q7a3D-5#v$O?rkM(%yN;YNnIyrhjh#tMBDx~QzJNqME7TE4EO3)s5?93aGt~A%i
zn#cb0w;Y@snGfXS&j$u<{Gd|tYkn1HMSh9);&>diE$?UN%!!=Q*y_sZ6Mh6}TZe2r
z{wU^=8hw7Lv61u%1;;~-sH>rF&3`o=>*1LVTRCU+TFE`+GLDDzw-@%a@Goo{A>lRe_R0<5WN6+>)}0V3}0`ku-c)NoBD+;E|o_9&&O}16La;H1;8Ab;$(?izyY3S
zE~ZLpfv^V+M4>F+b3hf3B~{-pX))o#6rzke`bD)_2w`0}822BbjROBz-?K
z@e`s4eO7?>m_{xhKOlxQ3zincoSrnWVXI%RgdNd?1C>)_pQM9Z&ZLjA=
zN10I5{aWMFaT7>YT}G-}}k?L%eZTT?46vwd01?OLCGbemIS{rGF^a8RekiQSxx
zX!ttOR0qa3`eW#mX9cbbd23$=v>wMYypcd7yyvK}E;G#Ai+(V_w1^e23
z9355urbJ&-Uham|nUG+Xz+id^DfFtJOhTrZZu8Kshwo
zBmYV>ieQx<|H_!vSA1^ZrIRjmhS5vqFE;thrfignF`|kIdCUq5t&}CxfqJl2QiuVY
zJ~mAsa#-VKkavI{Xcp6l+aDDZFYtAtxt?sjxXIoYU0gStKtyc%=iQsH9$J$&G)A37
ze=bon!JwJLSZch_&T*;mY0pv2e)%gL<-Bb`W<&4QMd74z(BR8m>Tc??6zjbAuigi7PDT;*O>Mb1;w!|Dm;6qyF20bY;2QqQnugfXNleh2F?uj
zJ8bgyK`Y7Nvlfvl(=pfv`M-pBVp9Yf
zHV_XOfxHPvk%@uf{0Zx2)wx)Zu^~kT#Z&e5H4cr-BN|x?^{Bw{O*7JbYH-l!5|ycQ
zJNa?R6AJE_IE{_)$9QDxNg*&d;x>zEin4kjw@Dx<`GPT_M7oRbUg*Dk$3
z@~Vl0A`WO615eh9x0<##p7bj-55IQ?1_o@LvC--FUkl%;Bpa~p(PVC(?1r#zeUyGp
zwoFp-OLh8^r;?gDFSJ+6cHy>8)($U54zYD_g$#ea)Y2Ds67q@bKL(>PZT?Y)RKz
zAQwjZ&re{4F;Fe=$Qj79VwOIqreX>_&QPr}`^1T4$`&R(pl%~3OHX~O3cg0u>_?oOp5UXRC$TcO*jT$
zJNRq|Dw0nCOFn?@Sm$a@RsfaiL5WAv8)d%6Nlqk6|C)mJ;ll?{v%Z`!Mf^BMy_6B_
z2Baae(HzAqdR5CRuG**3DpSu?<9-aaDfXX}+lcUnFTgFOdW4;k(8IlvFOdkojRbh$fGnZ95
z6@vI>-*3cx<)kxi#9VS(eh4?4nu=a=($PJb;YSH@0$)n&>Fwpu_XK|2I
zY+4G0`2&pYI~g4@s#0gFR(}2MYc}*y!^|K(|AI00GHEWI)}UZ1ee@d<$F~);-hjc>
z888aYcrnk+Pg(?@7lVCxBlZ+&DY*WQ+o)iCSgZ?%RdItYK*q3Cqf#5eht@v?D;Bc}
z=gpLPw8l%X1AaS~pL4vGIK8Qcege!bF|BNp|8-o*ILZZ
z%6DrE5JmJ0TPg)H5Ui|ZYD!$?GLKa4k?4gRVZfMp1MJfWz1n(UIq(;2P##rw
zDz0d*!Gs%nD*-3AKKtjT_OMrzP+`R9mq!B@N28ycOXgRNTDJtGRon{R`wocxo8$RXQ3L8XXP;gFDAZCp=98IM#Yy{48B
zf0dmt|4?@T0xJjJtNTe$j>_!qm)0xNF1H8E3K2|%~mH%
zGeHvTKU<+aSa9t7$Omg3#|UFZ>ghcVae9L@Dq%|>_d_Y8Vx{KO;ztJPQy~k3ZuFN$
z_5xuoH-Mc@a&M_FNB6ifesinseQi_1Hamm{?l!qHep8QJ5NAR?s1;S_Ds`Me4mtLt
zH#iOOUP*c;cX2^elNpOioteQL|Mb4DZ3U2bqHKY}6cUj_7r`GY=90)Uh}o%D_e>76
z6Z!2;`|;)kE02e9nY5yleu{vdS{vI@WbCans(O^Vx&nFj;z=wn1tVQAZ^U>@?3r^S
zuj1ZTmY9ZK23^9B*1CyL;6eO6j42ZYPl%*cuETOW$49YRnzAWOW!_7S*75wSD{u6B>R@O8qm6pe~kXNmk
zrJGlCLbQ>yXf2hi30G45$WSWbtCCL@UFA^{%i*}>U9Hk_r+ng>yWJ~xcBaN!M-cZaYo~;n;%$-`z_VXG4t-&usKuL`#&Ppp
zYO3PFRzt7v&m2Cf&Vti5H(&5z|1X1W9~{Wn@$R5^PhYQnXYmB2zm}GI0zgVia^beT*wQ+jhr`AuO1DF@|*}%UVeeH({f;-s3<}~o?pjkB4rix
zVK?#;RW)v`$7hvn4r^=ax#G%X)Qj-IUI0l=L
z_#OGjw2zTQDC{&tMf7kKSo=rONMg+?B1UXN%V?TMC?5i%2eMOnAUnO=u7sf~fLrL1
zP8+pY&&`qo5qVbiwP<+J6MJ^m@JPNDRbGrw
z(ahu9ntw(NpDAn>;394yH+NfV9fh@=sC2cldR=9w2;qx%AErss|L9rNO{4@u*~-kt
zkv4x`!qjc)v;*Tt`z@J6@P2*p(`3xPJi>b*I;SQE@M|%>x*c
zcR!c`c}!#17i^mOtfR$GWGej`>6z|@AskXHlr=i>z%Elf42XQkr=SmjPGD2b(|#K%
z!Vr=&T6s_PT|;G%q~=+X%9vv8k8%dalW`&g1x*J)38RzUIK#xNnctLWK6^f!r?tsi
zoJAQ5Y>thA{Xp}AZ$?e$lZrt5#haOf7d(Hox9YY`NB&_M@BMy9bE;9
zgcZR`Pqdlm(ZvF>86(jv$58BP;U3`kHAt@jHTY7QfPsMZ0tIw^jYWtvXu(B2m~%iARL~~Swv=*w@lcOqO
zHcD@qXJurUdBx9oQN;^Ye06j~m;D}$y|L3?36Hza_Q1A%#9TDYEVmEH-P-~V%6=RW)FvtzBb&+OjH
z8L^Yc_q(g@{FJVPB7XY+JoggdF`TN7`X|^X;n%gF5$mORT|?LLYr9!J@w9~lV8d_STt}fSK7flo>_A{<*H&1^I7P8!zEt0ON
z48C|;F2J9scmMN
zwQ+;Xy1(}Rgt@cB6NA`~--+8*Mj_+}G$K>uMvWZ3m}>nCqayJMDOLtHtvsr1WR%6r
z?fCsw*W$0^>}Awi(pY4lcYSKf!_JW
z15fn0rIH2UwwlS&4+ywt{JJUysCiTi-w|+2RV)T?#3!VTrbtU87GIps%p@wjJcvI~
zCx>WHr7xU4ZCSrcj^)V>7=
z?JR@neZ!I%3`)gafhhosUjx3GSLI1e1{@GAIvs+C6ibvHVY=7Of4Sz*8M8@JnclPi
z2jX>dvB!|!ME?mRB#1113K8%3m8OOTJ3-z-a$4`|<$zNkamrMl7ctN8`eX(JgG_#^
zmT)bk^(>t4nK-pu!E+)!bfdY>0W;DmEPhB{FMVv?zHcbR$p#Ws)a
zCMGU!S*o+}r@A-p20P3^H!Y>DQ*$YrD7_g0=m^`$Vasc6)Wv3BY-Ps|6yNf1B^DN}
zaS!k8hV)fLQKTqbhA*w@k4M_)+B*Zn4NL|%@weEZn-Q`f(tV0QVVPQ0kjk&(4_%H^
zEU-A))~dPvf1$Zm&LdqKi2;39`nt|sS2kueB!W=dUsw8Pw2Xk4xSG-jP(V62^SOf*
zlab^1K-tQAPA$VYH~WhoFPk5OutEa(wQ3{2xarn?Sxo>6=R_m+gwCQcb1puYNlu61
z8Lb3Otw1U;gNy{MO|6mf{2?Z0c1yq!641;2R%t{z`TM%xme~n7bb#qxZjz+0^7cl1tL-QdNYuoh*;4x;fUHsrtz~U
zV+77(A*kreQk%aM{d)4r$=>n{3(mF$YcC@t)6%}$l7~IJHccsK!n?V$mtREQi=GNA{OkM=|Ip&hsc>^y{9
zO@=#WA@PAgi^`Od9FC}#tyEBDYGD-cxPyOt9Y2VmrW%ZXHI1HWtnu$(g0!iu!(?Cb
zX!@MX@6!aJJe{E7yx)%dvB+R8^?}v=lde8^)m;b%mmUegX%6kSFbN{Vn_u5}48-^#
zpa_(5n&tq;e0QU|TX7~6%_Krll4H2Ik7H1kLmG6BiI^#DvJ%XwNEbnOH?4D-jFf^4
z`k21(6$b5;!3N?zHu2O<^PXUH3haz-AI)RFi3~l0T5h80&0Z-nN*y~kF}xy
znjAbmT1(qCFrwpEV
zY-jFfIr9sTtu)tPQqgHc0HH5-*v27a9lTrqr=LkrnQH+q-5)qmX45=OIw66t1$JKv
zu><4US7w;Nk)c-KKGUlFPs>rDMQZ36XU4_o>RQKjbaT)Ufw`xyA6`pc=Q8=L@){wa
z8tc5BMp_dN)q2sG$tvq0;2Vg69TwXe`TTL9AM}LBF;>tS!BX(p#55bH<-va$9-#A0
z3ofu2r2_gd_vPOxfY#~o{kddytM-a6Vs*d0I
zt*0a59{FRac7^HZ>Ka`Czb-p-Mvm0-%>e3dxlyE=#|1Cm_{DbzAy{75y$%sJdRBP!
z%Mq&K$bvduPVtlnN}mfCiv^74GrDK(}fGjD1DUr_qpc_M7k!Zc`ZRPO)Tt3wke
zke9?Ocm6vfzaK7L*pe=4TIst`g#&FI^OQjk2*}PC>U{3l@Exvk>9KG
zb*+;&t5EiW?T=IGxY9~ZDpZHhe0sx*+HAVf+?V_rf2;_
zs%4$+(rr2QT@vpcO#fA-S#Hwar$V=FBg1#iSyG-d7Z(j1)L=wVfH9NXS&7x0yl59F
zjGd;2l?W|x;X%!^nq2o5jQA9gU9CoOveLK{rt^k9Y-#uAjLg3FV6K6Sw$zM%Yb9iI
ztV@+G#oUI4wh-|F>c%$OyH(r9R7noif0=*Z1lgF0Xui!q>k;2tOA;
zCx?=vydDR}QLP&)`tBKwv5Rkx#x1^i9?~5MV1v$-jd7Ay&^blYgjf
zbcvFK8l-pqcEyTU1F56J3CCmeZc8yBiz}3z`l{!p^>Y6+3mco%RHsqo8-F_`VVDw-
zy}a2|j`z|Zn4Oi13eS%1l2k>7E7}_qWvS!S&HX;v;mVR{YHdw6)EzHkJ|e0LnqL5#
z-kg@u6*Yht0*1GNk0V*y)LjY(`;w(II2qY8v2Hgyvk%LE(8HR%
z887xJfm3Cn7};rdcm^_1~1AeD~%P!I}K?Xkl(~$_Gqiv++j-Av!MQ+YRF6>M8rz
z^XG_)D2Jea@cK#$Bx#s*Yjc}ft?J{kNi}=$mFM&VFmn(mBQpsR^$0HK8VvVPWAp6r
zW4ElBk}@|^i&|rHJ#;ShYw@+eNi{3mkDEEHY`3nG0wkw$;Rlo)B%qa>RAVNdT-p@w
zMKW`^^tl7J`tqghR6BJ=qNPHZ8iP6DPAQvoaV>t>8s(Izt->vLvuIHIKYU|
zfNbMD9vUFZOzANt{ug5(9&a#-Gb018nKb&r2Jw4m5=~jQ{i>x(r+4!n85s$NpcS+K
z=^5<)kUup{xGe2GlSu?R$2@ER*!++2DadW$b+>&&Pmialjgg*UqM>JRrxkx$R&dba
z6?oCg=JLOL4g#qWTgOaDSlM!o*gl4pOjOdA0Y
z0gre}S-LW(ORtYig=>^=wEn`j36XwbTNrhi_f&@^L}WYt>u`HY@+@%KEHdg9d~_Mv
zgm7A4-I7#myfh5Ap~9BJ5Cv^KMmeLcj^diiPm&Tbw#e4`x*Ijx49AA8)EeL}iYmF7Ire}^_0
z$7q}#cZ-@dcXY0Hw&I(nrWdrV^9z!AGh#=ru6X{6u-V`j-yRa_j%`CNdL^h8(j%V)
z?&6)OEneD?kqn5xj@~^cdKP+
zv*p=4lV`pJV|Kb)YVTY&)S9u2f_vPzP&;u$ELP-UP6^!Ux1%lz29sn^MaSQL$v>1-
z2g;e_Ap-OgUHrVRKcxOrcn1Q&I>#)8|A*SSa)S1I_a?CE@9-z5H
zDd0}=!81NSKr`#~l@*oN{H@7n1}Z6+xPL=D2POOW3ho})a=p*bn6)8&X~S(}@9S$&
zG?Im%al&k%vE5A9=vJ`*i`+$H%7E<0SmTz2fA{gcf4wHk#zH<`{{>$YCOPzWiE|*N
zdl%<~OVYZWBTmMWHeoFO!o{ueg*+8t1VG#SWxN1~p9ny%wY1peP5*9w(b0IWU89wi
z)ZfY+5wW3VKm;18xO?~eBzL%TE3QP4yLLB;r)B#njI~Zls%WJi=!41nYO8#r-HTvY
zm+?dF*)2ykZ=Q8aDZ)HfjNz4$Y`26oKharRCUqNo%55Po-_Y+wOXtcIul*3r@
z_N`rX04m7$4}@33aAx+)ikp#5KQSYcB?q`zF{`Eu;7B$!(Y@^%=gG*Feb%@H1T|-C
z#1|KUop@kyuY;1rshpf3I+u|}I}tK$*(rTYvdq{cO4@Xe--Mtkg_B@W0kbaRF+K9I
zi}r#{Cp_2Icn$GQ3(*>Lc3b{Ut374EZjbs5ihp9Mo5rJMj
zM{DAt`BftkuVi_VB*JlE3J|v4mp~qC_79DG6sUu9(m_2p^S+~oZn(cLuaL*I=BSya
z7KjcJWs)qBZx=$h<5J08Y1ub?JXszxw|-pmVOGIqtU6FINy_rh`Y>#c$#rTCDwj~6
zZmY0L#)1jxgT>e1;>r}gZbEv?o4H)yd$rTPm^-Q^0Utg*+tWGeOaqMN%~(>LkM3VNIdWNF{?J5@-vV*ko64+D>-3WmM#!bsiXLS
z@ZxzaTK*9zRC!$_XUg@&B@(_z1u$PnV{UFmgP8E>x6gXwD=H=L3Gc=*bthPpo3!Kr>Ub^Dz?=u#u2tkXl|lGhHkB5b$aMdg>_m=^a{?(z(egP<
z^;`@xJ564fM+?*eOpUs{s`CWfDR(nj)$?SF!F#!(w(`ryLurozD}=G8z-UsczQ(Mi
z?^wJpG`kKj;5m>;tt|DT(rRbKTGm;8zmTD|lxkO8(Cp?tZ=3HFxQ$g)Mj1_*g$ky`
z4aw|(3XXh%#wU8@BVVA-IOdZ^`l`1EAR)jHOrI44F&O<>aCfUVLXiw8%v0x~p`Mat
zkx{=)2(ku#YYjvX?{TNonDs67^&u6K^wXuO4UR$cqeHc>a%`<_5iYWq6DQ{~Uq4d3
znTq*UqLejNn{C+-;iPyTgb;NP=cID#hNL$2^{L`sCJ$|4ZYA@tFOQv3R;K|6Z9(lD
zDi#Sz)kf4U>P!%*76wU?bzuN_rMZ70Q<9u{L2_4?w5h_m%nD)as=P~tfr~az<-=vR
zoXyW`J`pQ1dX~$+yC0y5H91^q5Q}IdU&22KLa1?-r$~?{1OnN~6UPZNUEkDqys9UT
zt_dN;o2dyGd%$yE19(o~?{KSK3E6zQVP%_^DH#!af4Wj-XJ9s=CvMviQ-9x9zB
zMH!_TO^AkAR1>{V!MXe>~avl>glLw|JvAaq5
z^8mFci0c%gzR${epuHhu?GFLuA3(SOaHEwDb6^}OF5stEC(g#}gZO6OF8)fO5ckMP
zO^BmcVVxN6(Nj-O$-h@wg}A!7s1?cSZBuUvL9r~=%IzXY+x35CIE?-_r)U46N5{v9
zPKDV}lOJEkDqn`16%hQfFWDILVV1@Z=R{4{xmXF6FkaS#P$C;#9AsDl@4I>jd+PKaTYz@sz2QbUXIQFz7rsje9!ai{6bIgXLfyr
z^#jqs3vS+LoMcl1K3(f1d7-<96ih}0g#2d~%(`HZHw{q7+RGbwNsivW?s1(xvUmSX
zLVym`v6`{XC9+B$6Q6LBUN2Tz4#rTV)ZUbftRH0sxUjpk4_EpZV%?+peI!-Ct`_-0
zP+0Hu{e|}BePXe@4E)IxzqEjFTBqICP4(=#F?ZKfcdbvGi0aIGw$KP3^GtUXXTNG<
z)pG6!f#+Re8>u>PO%Xj^N>wK@bToD-u=e-HBZ2<{`7NqAgO!?X$-|UuxUlwkIv{58oPSp)r_-j
z5qJEsMgChTF94BH0c{%?0_zo{+y}8Zn|FNfvY6ANH3?(>MRCmowv*`g7d9?wFn6~8
z?UJ(moHOw#-&Gm_DkS}8UTE9tJ3AyYI~bB=iOd{NS>WNRrFTtyh+W&B63*m}`+@{1
zhdiF|dyGe_M*K=*n^5{)#jiSy7tuQ*r}5W|cj3#y9p&todRBaz8cvsb1jL7EqPh1)
zzvGv_H=ZA)Jh`uXOJ(SOV5I-%mkf78Vt>b)=cRW7t=p694+m$1*OtaVPPSvCCYTVg
zS+N9R1-hCYd9uzW6Z8;fh;g^dDO{fL8GJy(4@Gz|18hGZA$I@U_8Qr|m}lndH4+>>
zHD|&MatAucn#W{H;_Ep$I_y6e6SsPZWh@J&`gH{4OyXU1}9Kz4>Nr?enpT4C}myUl4-b_0T;k
z4F66(B}wf#rrwYD6mGmjVQLy#)xDej(%aNjGH+D_J3jPSGF}C(*C@JtP5iFGo9ZE-
zJxA*j+C?Tk8~Z~Gr+G&d3LNi0YG8xxb}OL3Ny_T1=2|u*zcK7doZDx7Sm+(l5`~O-
z`EyLQ@>%Z=^WAv@j3;SnOjhKOb99WV*BREjZlkrkzp@rwmKbHN-veZ$!6(-q#WKEN
z4D8NtIX%H4lFjL#a_!fiGl`Ux2YGYs_SQ-XFVs1;RpteUV;YU(`H9R~{y0HCrb%G5
zW<#06_oGgF^z(pTuJvHYK6hr`cwaY8wNn=BuMCrg;Llwn;y(rKI;lF77aFh?opeCc)8%IdD)UfsG<7Gq0CF)VkaL%6#MpzZYT&f|S5hpGuu!Vs$Am!Snq
z?+Hk`nBMF%7j{iI&G?B^_>T2{QLo8eofqH}?^NKV9ge4I01|~h
z=i*Arls)Gpb-8|$Y7KQ^o@7tsNFTE|s8Dt6s)FxM+Wm*YbZ@(Mt8A=?rY-Y~Ir9>t
zvZbj3w150)?Rnm?o%a0-p(2ydbm9Qn1+N-Sv|$RZ_BX>
zVOM}DmZ((m7?)H#;kdfy0;wh!@1(v}*=IkspkB!8&ASiGKoIR_co-)xTUV~pr%D|@92yg8RX+^e-93+NL_;)5w`
z4pMBe2~&@e+m+RC9_eZpeC?&)pkJQ3Az)HSRf)TZVbUrg!~$*tI51#)dJ^ZwFg~oD
zHm5QO=K+_+0%ClAjj|2|P$1M_XfI0Te?IzN9&e)oQ_uWN1abCDRr(~F!N~u9$8TOMCWlF{7JYlt;8$T
zwgP(KB-MJdMS-xpjs!nfyj&WY3_ywG0V99Z`+`V6oZUb%^$%(Gr9^QVqQB@(^k0e6
z{ROnuc9G*%OTsJ(@}XkgOrjceN+W69mT={=g{tj}pK<)&uVebg>zc1oR-3^|J$7xn
z)`Bm+b7`qwZ^0EjODe-OUYGtP$CGPR&Whb{7ff8i5v=-?TQ{r$clj9KDkKCW&*NI~
zxFY@RrDk>^n4%d+U6~g`JI$jUuA!cQ`wt%Ck3B5Uxe#U27)Q5m9_|m8Rx5WhtJRZ3
z0q&0Yzt7iJbEA#68aF+o>k1#Zz5Z5z_jYpTo`~-?m5Iq|ps=XSFCiMsA2Qu%GAtEy
z=H}+Vk#;`fCBo`LDdj=V(psZ
z+p@G}VPjD)sqMVzTx;CMecHG9)W3`M8uLAvtYPXe!cIKQ{1AAIE=&q$ueaDNlSC_)
zqxXg5Z02}ij)o=Q#xF@9a^o)D+rPd=(N!Ov@WYW#Zg_dm(BlB@J#Jbh@G#wBRJRmC
z)U1~*OXhLwA`?tU_shyz%V$@&2feLcT6{&p;MPsys85T1$vn`Jh4rKl9NQA9o2rdk
z?u#nD^7}e12UeT^hI#J&&80{wUz7lMMPgb_Jto2enVER_rO8tPFU2M)rkW%Op#!UW
zHApt`%VVwGOLcd2($h=2gMO-$zlKdsCGkREv;2`JX4fCxg1tD
zc2|=&W^t>{W*Ou7GB&r1rpmfjR`F`TqKt2nT!Q_oP0P_&fuyB&COPkx*?rGSN`iMO
z*F-#a;h4|D@pq+=b}JKVCf*-h!6IxsP7R>sF_vqS!UWWqxK
zM_Uav`5_OaU-EB3#O`n1&w$WW!FT9@)1=G4^lf}uDIrqx$>d2yZiBB<`ZTv%2ia;Y
z);sl#QLB24puTUN^i)cAPy;Pj)ve1eyep61GbPwTc|2zz+*n-37^TjI|DaLck*H-N
zQ=(%}Bh%!Uviwoa^Wp)~tRAg66~n2)a^N7{8*2
z!N}5?WUO9<=}qI!V+|%e#ty4?-?<*-45Thz!xI<_i&wBheWV*vC?7N^%Pq`R%*hd_
z3A{Fp}|D0_Q;?hNM
zDv1}Pj##lYmp624D3G!y+fnZRxCSSt{r+qwqGviW?K&IjuGkT#bz?&wO}eU5aW`!e
z+KlUT{*I)_SwTM7f)R_PY0R?Y|9zbhq8rY$l+3<4a;q2a)YWAppf>9Z-Sd{5vfWDX
zM6n%T!E=hj)KbzRX~qUC4!!BoO5VClfKEaj*&(R1+3-=vD@85!IX(e3&
zfvN6Tb&3&xe6rLs!TWBELMj<#P|b00!3vD~0Oi8VZl=kNFbjQ|Rd
z1CS7wwY_q7qL~&DUz6=0BGmH;pc}0o;${cAQ?37us5Z_U>$uwNXfx>eXU&&1?F$_&
zsP>&>CvE!o$^b3U7NVmRKRZ>CAwue~{W8LXf|N8NaT}?E+cV-oSMmI3^|_cq+l}xC
z7i@}nJ!V!_rSEF|1y`jhvgL|H16h239<9DLmy%~v(g{*H&yvw~Q5X|7k#DH9hgy^JysppbmHBJ`nO-G*g>Z5$T5$b9>
zo^J;a_#uJ6fGn##wB2v6tKZgXtQxEm8FWX(Q4XPetzT~Zq*u4Jgb-1G&Sp1g;o8N=
z$#!WcyN~<1J}z5Ue$<(j(24;IfP^?+yvJeY)SJ;Z!ZV`-^yS_=g`@>`%OQ=0G-f)QSw25cX4ow+*+l61(JREt%xi1pd^=%O
zjF$}tW~A1w({_@RpN^Fpqig1|0CrPp`9DIqdNzAv@-(
zj4fB4TV+?vBX>g%!bmbS_OxV8R@#5-duu`-7)&AyqDL5i+byo=)sR@MlFb!HI4`4}
zyFV4riY?K{jPAGW-j!v1YG;zE$AP{0GtZg0t!w%B;x
z&gC+u+Mxnxa?d@OQ-v)aY}UBJ!j}%Z@x^75l36{IywU$2hA3h3ZXWY1+)?kbPl
zv6n#Q?*`2}Yw420y?N~>(UnnHxOqk7q67q#c^b*Cm~H4_}2Jc?!%{hmX&ey)x40(o(B$jO52%W$mpchtyj-G^cCB>&i={
z839Y}vICa7J2Q8Cu+*&ar+qz1N|XE8Pof
z<{31*nZN6|W*xN-W1QZ{GReZpqed)&B4!UpU)OMcL3LVFh%(tSN7o;0cv2#xsMM9h
z@_lM#AJ}}za}Ws&y!6Gzl6?qtE?(=r*MDJ%4;y6$WPer^_*+3jvP1h9Q7(5k
ze=pB6fEP)EkXF{?iAg&=j^K3VZa_(EqgY;#JO22?f)4j~0Sp6D3Q!KbOAFDKCa=sZ
z=i=t7e0yA!N*1!F;-{m%RliYk$bnXRkoEM@*Bhi;NkoO2y>qG$yoZfoXvecqF?D80
zJ&SQ)(legVM)KuYxn4kK0Myw9^Dpl|T&+oTIJ3yl8J;|0xUGq*68&3gqS{X$XUKVB9+)bs{^NDa4>_!S1Kg9Zv&NE_MX8Roj`Cw
zCWjHk)kZ%&Zp*pB9EW+Vn8yE879ERPOgvBgQ-5jWN3j5QXWiWh=QBrKWRun+w4A!Q=8jme0nW*8b-{)~4RAq1}jY^c3hr{;?_Tb{sv$#~>GJ5Xm$^Io?1{vQj
z>zfV@^s<~yFykw>n*_I{rQ91j4Y_Ai57rq6X%rxvA3L{`kFg!Jt7ho`0IS4Wtt315
zDAJzHw!64cUC$0KvG!7sZ}d`SOgSps@bM{G)qxTp;V$~API6x>6uv9LAZ|}+*=Otf
z;7Kz*QM2Br{VUzUcJnB``kukUB{H^T_2s-beB`-nfiE2npGnRpp86Y`4#NyGa6#{5
zA@_3`h#@h5UECu`g6W&)*S66AXbgJpfc~j*H
z=cavc*T=2}dN@PR1(gTER8qT~M;dVCx6i2uhJ8D*D&yfpIT+&*e=SNt_#*dHtLMKz
zP0He%Xpj$Dh_?aY9yATX$D)b|MSdn5Y6w$0)<@dFVu(&MD6t(s(K2tQW(%e
z19;{yw}2$gi)~H
zi#J*fRf6IPAUfSPELgfkZ)U+7*}DUCN^YX23x&Yi7%=y-;(9i!(Fa2pU7L6C
zawsQngtstk5R~i(kaIbE_e>wD87mukW!eG5i<~ZO(J&8&L9GdPHF@?j3Hk!B;c?Zh
z#suB#H0hfusiPFp=i!+?%0(2v)mfzE2PaA@2#=g!Y0
z9$N@~2sd$*RvX15q)V|Iql|sq1@}SLKcA76=0TPv=9Z#fHOfJ@l6cv;Wl#FM94bGU
zMNrTOkxtn1VL)wZ%$~_ZIh=2_vc?0aawiouW{}szQs|mEG9UjjV7A88=CCOQ>%OcH
z7hX>tqXC@4%V&UiKDJvzSNVJg^XyF7mcMtln1{3zhX!kde)9ACN~MA<%YiEuc&dg)
z^@nK(O1MGJI85Ij3>%c*{8!ZXM6-^;#iTY;#Zj(|6?b2}AnQp)rO?8oSa_ZZL@*P{OrGuh8nr^+5bqLq#N
zj7xtY?WhvFerfa!-A}<3^v>cHv@+k9?ro54cG#Ok1&^IrfyZGUsxN2UbzasBE{`XD
zmI1smeBF}-!hkLpiBeJQ<(Jf*sP3T3<7DCn-LCqGhM_y;pPlJO1aQ3?3juquv>r>K
zx~k*6fZqTP>Cv3_^Uek;j7wJfm}T6E{rc(=kJgWn-|==ci#h0+?l9?6)l
z(`=F>_i+l(`c%DqobaSe
zg{AC#iVJti*%kMy<&7BCt%mB-POjeZX)bCo?!cB*EoS1;^Q8~J?86cdY_;8io
zNJ&kRNqU)K{x)bO3VA>H^oMI9uFTyK7GCnOYB=g;D)}tq3OOCkoI?vFFkL1dS
zz-b2I{&%*oiZu4fg6^_PtRUC2_-$A%I2#VK7>zFPY2L_tyu@tYT${QzJXP1u8wUP2
zD#9RKm;-Tq07dRCt*XW9kWvYjpt|{^3#zP5sny_`J2@PxlTvPP7tDNFxK_p_Az1Td
zq!71EVCm1sXa@HNz=cqW!(IB-vYW!==KF|Of>DJ#J^Z!s2hVU(ZCGr27IG~aCWmUy
z61!;CsiDu(vP54bqSaF^n(flNkN6OGP=7sCOtHJE9?Jk_{%6AwXpd0vM5PXeKs0u~
z{kYQlX0!XU!E|ZwM67l)i=XW?Z#cAaL7mO?Jz#b%%Rz2IF|jaQkrAeSzT!ON4@ceM
zgvNQT5u&T!v}ccERTnPe_2p35r?3j@mAjKc|m_2ja<|l1tItL
zOrx+)gD-#fgTu6pS~3l0<|O(+YW#NI3T|g43_g>4Z4?XQe2fwckL
zFhjo(G{rMULvvBCocBFT^G!l{X2~S=nl2<-S6aa7?INi7k?r7(-CB
zC$E327^ZCfvTeB~nzg|S&5x+FABqe@R9=N7ls*g0G7@Jhd5Nb3gPx-I;slZ$Rd$AKXCN^r?g)I75
zVy&!nT;0c_^ny=bDi1=*=v+=>Qc=@tlp`Dxp885kBa=phFgT(=G!HBfYzmVq0#04VP7a9}~rmiE*ki`PS
zWaEpii3pD=r3~iZN{yukF)5cKAjj7a_DIQOu|)F8O~CSSX^@zJ&W+H6SS#-k=v
z!5wXKq)nH&1sX>##|!a$cDL+W7qKPV=7X{X3f*G48LK={d2UKMgRPjLk8eF*!D78>
zP|&KgebP`9x7bH1E1JLuw6>lb{5}Tz63~oON&Ug6@qcDDju$8R@^a`FwnMfYl0x&0
zfB+}7Gz5q8tybw@2GY?vFZ4a$yUc~&CCw$GcBCvTFzoi{^DKi*MMw-iU*w~G>aemA
zlg;l@k4<_o{w(I2=6rqO_9!(g$jvJ2kL)JqebiCTS0#+yHJ?
zJmbIp7iffXYcIdDV->i1;?PCnkc->Fs;L9NzLIM{PmhB#pZx$RivLaZgbM5BM9xva&z13Cs_{HaE0kvZr<0NRGlFS?W)+n#XT!t-p`>{91y@;cO>K!3I#8
z#Ux^hD$F^At%3M2G`0d3xue+U
z0~R;bxqUyQJieaK
zvZNPmuGCK`Q->}<;gPZYZ4oH3G#y^3PNJBLC#Coy@E}Y~4C44v5D4@dpG2=*HC6|c
zLfL@|&D^&ofz){O*2$ZVPSmyDDP`19Ep&qHl$?fkr10xnISe>exofgED7tY!SV}5!
z)Oh+_E$1auvd&PUy~OA`cJ356^pyziPmYTA+@CU}SMR57Wjs_c<_=|@I*fSWapzZ8
ztYLBg$R*75i-A=?l26!k2ciL|%F)5|j>4MkXC94rP!#ATt(dB*s+!Q}Fc5__9DPv{{q$sw=lpTMRdY*9I0_sWZpu(6mz4EI3TU>5p8ACiEOQA;Feaz-
zc+4Zeh2~ITKwmH7D&6>w&xiPlM@)rgbUWxsw_151mwX
z`oIW|Hb3Y77v&zC&)En&Y}ny32HCv}6+B{-fZ+rm`bUbg?qvIZ8#B$fY@%W7C^bHv
zTD1=x<|x?zT_%SNo$fB}mpLj~YzE0KOprj(IfAy@W2EbsAM$C0_RAl_C^DIxUmyl4
zjkeyFY>oWMPqI-p9n^71!AHLw5E@?@cE?C$P>hxMXyKkD3A@*LM;
zqR|;Wty|gj-+S^ro4?wm6dxARG;KoVCOI6OI($vM2WoFTZ+y{*545>@MMGc}(o3P-
za8D#NlnZWpw{r@HGNg7Jl6=f6c3P;52=cM?u!qIANQ8M9)xoSt`I>@l^C&03C>~G6
zt2Yn)D+zd;(S`SFC){opS7x1_lk}A=g+G+UrhXoH*CX<&i5?@Q69z|pgBMs=$B98e
z@iZDsVEeG5_qedGd=yGfB}LWn7)lFFbQ&D
z;w>P>mO{K1jyWyQs;>+)@S+x~!3C)~vJ79zheM+lSe4EgfjgK*-TRYN@gdOt6~C|+
zlvCpMmgxM{9#cm8#>L{-a>8*|<)
zh+MzPws7oxm`pxC|6Q8zXX!$$>Dm4zu0HI!Hqz0=C|=_RgXJPfb9Lr-C7J@qKU1Hm
z^r%fpHi~}dF#ag~uYlO}&az@)9+g5@d;r2^+xlC^X>CWbwr)ruac!uLOalLVP+ES<1(%g$BU
zsrFr9$rE~DPs)qXz{1yuMPzcU&`U;`1yQjarzdp9d36Y@NtFJi@tZ!&j8hXMzu-Is
zb7MVT1kf;q*&hv12Y06&?js@(CRTNvFtzq#jMgPIVOIsdXp9IA1h@)(yRTQTUUXK!
zerA0GjsHPYkdg+Sn8QO0f0Rp_?)foU!ScXMkHb74wfdF
zZLMv?-=d93rYb%gEww^(b+YxKa&v>1O@&rn!rDuXVpSLiZwYxTG#F&uE?l;1NfF&W
z1|C!jIwvVkj+*tL{9E9^J4w@QYR~oR?_NrVMSa_$Ja|B}*u=Ap1p+yq({_9z)Jyzr
zW=kH}cN7uB6P|UJAa)r=y)2=DbPnOlDkhY4AM2EPYmdI@$$%@uF+M(zhc=frH0xHh)ga!p(Mj5xiK|4$3lsS2{SCl*Ys8lD1u5bEz;ff`vsl#8gB|U(K)TUiJ
zBOUw%V)P`67DqC!Z<>@-`JN_Tlj3YeC-!yPAG;f9;TU@2V_`#EsW`!Lb)HCDgk%N>
zlPPPeP>UP-aJGN^^6yKWuh-Jae^iLPK{Zljr#akNm@D^K%mKEt*+_C`K|U)W#4`uu`?gZ`9cxFYhMHPwo6KKUmDmCT1F@hg7Aa+jlBfwerYK_R{zkk2}+vQ9se^0GS+IB!zPsf=M%`5KNRI(bB?VV
zlbxt%L{1P#s^u@_bwep4kN%oIHcA?LHLz(s13XwGt;60~-*>uiY(PY%dX5=AeLxl{
zVeT0=p}e+*xUiaQxpe)~Mf?9tSJ#flTgEUITwrm6z@OElxI-#SBfkM{TP}>YJDI5^kkMl?#~4G=ZByk;4#8>%$Zm
z5FYvMv+6hocB2ChDl->^^U8Zfd9yQI&cQ%H2)|%(#|W2Xq_Z|oEFZG|Li72%(c!`U
zF|XBE>S}*7C2?tBBz}s{XRs46nz?y1Hl7nEHsQ9owdY@O!3*J}=olF3;SLb7lE(_?
z5`oN|?(n?$GAiIKGIqFd_h*;CPkh(=AhAcHVbAwFe9m=`BAI_v%B`Z@-50|yUE@|M
zV{a}RkLAA^5QH?uYoC406xiZ9~0z9|x7~9o2J~9H2`&YJVv{
zk`sJ^1ze(dU_qum*TWVNd<9MUHjK#lPT;o=`8Or>x=QW%qULuIwOLD$NM?E-Zu_4~
z9v+&fql8ce9L9}a)!Lq&$hR*3eLZad0B#=Yb?Db@zgoap=hYI4?3ZjLjLM58qKB
zem^zMzkW&z(RhH*G`9qf4A52aWrNPL28z3WEX;~hPGs_%JNtFp}FO=~#N04<&_Q0nlGe#&PRqm+fJ
zcH-{reL!FqV`hAjSdyZ=aEG}Mno5NcHIr*#s&WhVu9E%gEpB8@IoNv>=&ziYxjMpZ
zuOlq+6&HAv3m0nG1#7u;z*S)+6ZHJhKqa%lfITuNjGnfd;CW2%OeX!@cg>V0Q1K!2
z$S#rDvIVxc|5Ql&?Mr`s=zVl5lw%0uT7`CX(FfILYk^PE2K2u-bvMF-OAGzQ)klw8
zPJUb94V`STd!3g7n=LAjXfOwg{HyK0#e{A-kX!rrywF)gg6M;ZlAbTSGf85+e+p(u
zbIEq)oqdFpAKRaZ@H+3~!_u2=S+nY}IpJ*rCSDUSk5AR*rw&J?cj8xX`(eRWn_Wmuk%}tE=Z$(l~jM`
z^KiIFfr9v)F}&ssHuo$C!g7%Oy|rNWAjN_?xCW@%+28VC=BXj7%6^V&>#PMHMl>{K
z{#Xe1L4AZ2A7Bpf-V{csT`F)(JY23uH@AFUbC}cfm4r_IubC^7u;Sn)V6mw1d@KKU
zJnft3$wTb~V{b|yY3O8hM}c5-82`^D|NA*5vb&!j+Ked53-5I1^&DM%XwhM{`
zXF3TAbV0rfM9Y-N>*nl#sPrFE61P1Bkszg<(GRK0imO%C5}ROO>Z$gn@ds)?jN^^|3%$H4czdNV5nb;|9y?{fd-a2cG2yC`|d
zsWha{#)r4_g_p}!zY#`H^)>{JC)!x4raqzXk5tUQ<;)7yn|c1i42MkH43^l8G>l2g
z_4zPi6_(Mbyqurc^N8Hng&tyE&+#ofUGV(xmxA5WU$ZjxmJTYiR(dTDiJ`*bK?Jf^
zMha?Y>5UC&ypmP3xra%ap
zM)n^YF_GrCyeo^Mq5P2Y3EmNrlhVm&B`O|d9@ds*-qW)2D*#SuRA_2CDv?r^jBvxZBdII!f|d+hL?Xa)a#+&Pzcm+J(@GB|G2ACvarY=>R%i*7Zr!gYMKv&I&C5#(CcGhh|iH55Fk*ZG|IvYX>)UawpF_ydgkTB
zBGT~jS3XQqF;>GxbI|~#w0QQb`Aetus7p`I7}d(X=u>G0w0!Cf-S
zLE!sLpYY6~lwIike`G_v=QquybrB3HF74#oT*+!x1zan2yJ!FrLX6#%
z{tq|B(#ZE<%+%L+i0bd6#|XH+2$sR?XEB}{r@zQtwAG)qPHXbG0tEVp_BDSPVuM$FfYH52ZRf52|$Q2B$1b?&V3a#yV
z`Y6L7(Xk7^_HFa`(8PNw$fLjUhuK7!oN?kq*b??1{;
zBs$YVFrJUBJy#EHD+ukapR(gznAI5!;!29$GiMGCfm#<8phI~wbBus1-d@WOVc}px
z8d4V%QEX6S2L+zlSTl3pM?wh_^bvUPCZ%IzYproD!0n6T#k^p;6`T
zeIXMzrVHw{Fo$tyKDkx}EwIvXd%r{jmoteux
zO%;OffMD=n=E*0ab|G8FV~m8nIrgk0Jg(ZGT|)OMQ+~H7dM>hSE!*$XG*%wnA@z7?
zyH|1UY>)oEv+}=qWk+4-_Y?B%81GHeb6h6otm<(I84UFmi_e=mc4`6Xat9r$GI;g@TZ-M3Ucz3quMy>9~V57I_H?~0C$
z1*aiUvQ|)INl)ou@{xhI{b=7KzA>i28>nQV4p@+iY8V%<(B^C$KEtQ5#*vW;*P$bT
zN!T4E=jVOX%Rcj$g0Q$QuXE5E=>On%(#STwl6Z&EiH{DhMFii6&4#`Udt(nJp%53o
z8kyz=WtK2q-5_|?dA-o@Y7#pNfw0W28r8>xwh&dY?h#qCcNx9^C>KxU4a!zrke(qj
z)7nZ@ImQR^;fh6WklgfKWwPJ@*fQWs1w;a__)zzsHYY-zLs`-ZFEHsIlw8?@R;=&I)g_gVtMr+Irq#dM2Lq(r
z-ub72l~-tkVFC1AziZwoL#1+GzY1>u9D=Ix0&vw+I{hU8-Y5Y3X&eTR&s0O4#-a>}
z)`VU&|LSs>#llP_&mAap`-Encm5%+rk5C0I*Q4d{s*A})RJ};jrv~JWuL$FCXnMVR
z>HF)az{2)%MR_mpf}({7Ot1RB
zW@blGn0RL?%-_%Rd#2K09yzny;QZV~tMe|w6V^E{h9AWCZ_$o5Ima*XKrPkR5eh{g
z&1dB!;T+Q7?R}Ygm)kG-zsQsW{F0TFiwFK%cLQn`%mbUG(!qEQS*z~1y+4)nallR=
zEcrBga?Bz(%WP0
zPPOzt4#vMgOeQ~bk~809uveZ9f)tgu*AERdb`Sdfe-yk5Ys6ys)pFw
zSFs}MfmXQxUH^i&gy_Vi87cKL>MDBp=iX>Iqy*Q3?4tVG6i#bJE
ztH)N7xj>BI04bd&!Ye>{PYEFQWeBgol+|?c0dSt#5vFv2Ls!n?+2@j{T67YnIQ~sJ
z7NRm}G#|TxbNxCJ#?TX4OiK`8n_6C~vho8+2Hb)rd;>ydXX6o&9+}qE?R2Ui`$t_J
zkMukn7?nFL<3jGL1YT$Y3I>i#8MAQ^V+s4ARC?)6Zd|-VgakXz
zj))gD+x!0x>c>R|OZIQS4GHfeFmQAFJ%O%+9%5?h!!?(2tyLwat7cBnx1Yh_YMwD`
zUrURrhwo_(|Mim(hmyXy&BG)6TE)S%u1;p7Z0Y&@r(Fyu9V@s6jJLhxg?3*TYj!gM
zk)4oMmH#81F9`V6zII!470BdZAWkPUCFC9W-h%W*j1~%H5m3RX%x{O?gO_lPMdpExSe?pxt(^L+ElOANwIS-W}7iqaI|{bF~O{Qmfge9pmHO
zd@#hUoX-N<9;pxGe@nz`6mK=I^TSX`M1Wh0Bz{UCOqwfXD%F5BaQoFmm74#91WXn~
zs0!y_d3MN?|8K9Mne-`A+P*O(|3bGg;-bET(P9KSet;2vKa_p@Y2SXMDOlf
zW-Pcpf3QgkB%w`K3xm7Ax;Qy;6KB1~oCb2f(yVL;IO1I)CodB2!@1l)CBYjnUQxg2
z#M>F9xn@bj?kgf-PGC$C@%81doe++9)7By8tdT8IUWbt=$D-8b7*z9nz!W(at4#(~
zn}P2)54Pk6d!gL=3V%1cdRy%aZVU?}3KOC!&ZP7Ual-JC#%0U42{3$@JEwpra5lN!b`6p=k6wP~8xbxMF+^9%xl42vO13PUUB2yTx
zq3rqWLlP^67(O8koco~TP5zZOQWG5c0RmGgKu3|b>y`P$Fy%1^`vI@DsoQ5XC1wn-
zW00s>)4X&KL+aQ5$nvOLF>C{Vse6<*OfAB3|x{maaxtuiPF`yL+>J
zil&=>>=7j~hP7u*yZ@8z=Y*COeOivxjIIF};?eplHW+fHpN8w^jp_-7KOlt#=f(Jx
z%}^X6bb%KOAm!v&ppX^l_E62&)}a`v0we^=7RO+H&S`-jIlGt0e}A2h$yOr6Vag5W
zQPa!twGx5)?UL9cYBriEOgcYNRWXx$lA4_?=rOndF-grFB+7O$Rz
zWf6jn))k7qm!C!s5+%|gW3ZQzBwx?8hYabk%rgnhOrl;Yn5V9miB`Rnye^CWqzJuLi#vY27=CvZlO^YndOl
zIy!bbp{?m66!g!HJzeUE!j#i;tvIf8kh9PM#IifZs`Dh+d-i1>FDN3B0SbHr;m4e@#Lvw
zV6bn6V$fD({D%sGJj3faWeug$qI4_yNdCev0c1{VF&4U8%wF;m&7^;_EDK^6tx}_c
zA&_U1_k(33<48XFl7rRUL|>}Cl|I}rVgnaua0>W^=5h9hmeXr2n~nq~gDyCi>n$#PK*S
zn+FGj4F3G*K+@ouAMz0xT5k*M7dEwxjNw0!Nj8t%_X8-qR^*s+jC1j`1tpXu1SZ2U(5{mI9NZS4t&Q1l3QDk+O|&<1Kh=ZQ<#a++_s%fBDN*b0<1Zno+ZW%DDwfG5!(
zOS=#}j|(YFA=K~Vum4GaCEFh+TLNdY_y3IbkFM|^Sf6}7RJ_37MSrqK1n@AmyJlOQ
zgUwj0XKzYoYX^_;)*!vGAlIylCd+1qB8KRqCvS5B34|?|s955hC+EeK(ij`%TiO)n
zj~a*<5%7~!QfgTASGR@FzG-8!du#%kQ7`?>6ipj@|Ze#GnA740RRwed}F
z-cndf{nC9*Ip^yzD@fl?E}`0s3gCa*dY7)1+4ut#c5tN+YCmeCj!ni+Un#tZiLa@4%
zwhs7KnG}-q@Mvo62-K59dO!(3UMTa2;`_g5x)@e@nl^diW!<0oRyKxTaDjrDLs8hK
zoB2$IrC)DqInZGs#Zg4dM*I2iz4eVpJbfeAj9WxH?|D|OpU9znHQ342DWs?ul{7xd
zDXEF34`!%Y#IR#vOYd8`^s|f3cTLQ^9wO-JqhkK`1m}UDN&r-neV_D*X*m8wj9r73
z|4rY*Ghfte$WTOIA+uapm@62FQ($GTgl}O1@MsrWU4g$jJd!UH(h3$027+{ucTvq2
zQZ@>0i^@978c9Ut0RP4h4GTWC;x`cJepJMy#*b~V4!m?`)YVw{`BL`o8h}eAM@kGv
zD@Z7X&`KHaZecvxpBgi>%RuZG@xth|fL1(>mVxOm975?b}1O#YBB9IvwHa(e*(
z3tp(2qPD2bOl~e44(8ol-LF*AHrU*qD?mT+ZB4naua-9
zW)`a7n-n4kBy~sUZlGOQq|=!Sf;=k#?oIbudcd>7fm&)3u9Ovl&3G5h@|VCVSfxjq
zki%S0SdkO^@t@sR%k0H*u>QmE*u}0s4QvO$n@lhKbG31>G*;KzqloyR*kVDmS%7B^
z?Q!Z-ka;;#Zcn+dkY~!{DM?b1hH_{sD?5~P@=>H}DKh(GOD^sgq?=DY5VT{riSzHr
zhswL7Pi5dx$$Vd0+*oQF<~mLMqMikjbg7PTkSlRBSy0kUAb{2ZZ9*L@$`Ot`MRfIY
zn$2fF`f}j5!hZzr=b43Lm+G>GWAmq1>r;y{)_%-izqRMeBveg@ph~HM)fbxTiOHzY
ziPqq-hf}N5yw;EYE|V82x@|b@VNfH)w+O9*4EA7`)7+uUVb%kLde3QB7$^OJBFGuR
zAC}j{uA)QySBlg1lczV?KjFFCBC6H`4b^A1G)s33#5VP!--DNsC2uHQhFyybFUo3p6@_Vx8xdk+1Rh)w;au
zIZxXx3|5HfFvf^Uw5>}&)rcb^Hv|T$w`DKp>{q{)gK8s@!y*0JDcxhNlVUj0lnPD{B=3qY)t3?XzIcIn)z@jlV4OUawsY4e7*u&7g+
z2&&fZNu11|15$pTc*Wb3seZVDNL}Pc)J|LG%~o$K2D!Yl(`IBdv_GQ76qE;MLS{`0
zLpb=~>sy5-+OBp8-5q40Ma7(dg@iBgH%9QgN93g-bBlUsb`&ir<ahl|5xmvY~?yIwr5Q0O9#^zD?=7F6LT5{bbk9?Lia&F$nctzQobSidr|O>|UUA
z#NVH6j5A_|<|fm&nxh)%`K19OE-$)uLR`<<0OI@R07-I2gyl7XhLQ;|AxGB0tKj9^
z0PM)X$*c}oA&beaB3+irv|rxj`gqPvAyNIY@c0j{G_s*Po6WcI{1|TRWy;-&Wpu*+
zS3`49qEHGXB#f+QmTQTvVqY^=rj~pRH+VDh5X(Sp`h9z=eex5UkJFaw
zlKm%eA+_ibr$*l#f|^(X#PZ!1w4*pch#YtgIp&OIE<`Q=`s333V^U&;p;B*yt$;Z^
z^kW-%oUtMxmZUfMQ1t(O@^Fr&i}kkF&mXs^jeSQ!oKSmj*0fAkTn+B`3z0u!=?ixh
zce=IY43^4NCP@CFmlt93!f1uR4uV{o0D+nB3_cPjhQQNF*?A9uB=v}Fw(HgEJuCF>
zk&$|`PNmn<`}M8%9?w_8Up^eOE{?{Aps_`tFOl2nMZzfEZgZ+Nk0cEZ+879lS%gfg
zw`g@XL?>T58Q|;l0(S?uRCvbyuxI%?*0u%l)sIM}8CRVJelF#Fb5}2L8!HIqUKBU=r=X%PA7M1YUxtQ`z1`(0a;6%
za(*>)hXuUAOy1my&0d?dI*Y>MFJhs^{T_rS#mfF?U>OX4#d_J_m?HTx*pmIJq`(%L
z&f5EMJ?7w-a3AG0$lipwT&a7VN72(yoIn>qbF}y9eJkcWD5Zp#QMQ)|+Xlsx!fE%O
z4=BV>7T-1sT|W7BJSc;X?r!Wm4sw7LmqzQyQo7m2X?JJ+GM)M@C!{!h&BAYRJu`fv
zvc65tzV=);?9&$6SWI+yElcoyG7B1|Xt4&QT5WaQ>x}->O6e}G!nV>$p3c@ILBWZ%
zvz1Y9>?Xm^;cR7D;BG-RY9!yW?<>ZO#(`(g-XpQXnzj0>dV`29$HfZMp6WNKgtOyh
zbrl=l`s-dy3hNK?n=xQ4v#h#fv$m;Am^beM*@)ooGnEnRd5G9&in4*SFC?Axz=~%v
zVqHX?3tAx*d!pg5x828cjM%Z8x&`yqlIItoK%2d<>3gDnuFcA5&sD!*UU&%47oqmR
zd&rPB7|t{2*WS|OY<1CUW0k5$;j(^_?*8mQ+}P`PzaNyJ7?D#dgNBj$G0g@&J?mx}
z`LPxrr!}!cGX3x~m7$(S*(T&uDQE{7mmIZrx(#Z#Q6_@|@L{?PACnP))-%j=@`pAz
zH%Zptr^51G(KcJOGH!rIMMv)TKu1`AnZ4$DktN{UD}xvmz5OpnWuZFWY}){I_&ecN
zr>>V?4sm?rRDh5M@H8J*zGGfM^n~6$MFsG|HS)sAfus*Oq7Gks)5S4*OAin
zGUPdyrJomynzT6U)iIV^h8cO_E5;Z~rNU0<9|g~C78~-8fso`A))Bg0qPi>|OQvG{
z@(`x#?=S)0yJFGyUE2W~dr_^JPurjCd|Rk=;Po>_&%KGnGVgT8HcKh~k+6$iys^^s
zW8#fn3RwSZWlc(o}IyA@tgAW>zqgu)vx?gLb
z3P|6sonxOn*nmTB+KSWIUMA>^;t?+pgE)