From b612fb23e4e633ea1ec0a7e7bd3f4669bbd24ae8 Mon Sep 17 00:00:00 2001 From: mumu <42829555+ZhuLinsen@users.noreply.github.com> Date: Thu, 4 Jun 2026 13:40:42 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E7=BB=93=E6=9E=84=E5=8C=96=E5=A4=A7?= =?UTF-8?q?=E7=9B=98=E5=A4=8D=E7=9B=98=E6=8A=A5=E5=91=8A=E5=B1=95=E7=A4=BA?= =?UTF-8?q?=20(#1576)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: add dedicated market review report view * fix(review-feedback-1576): Use localized labels for English market reviews * fix: structure market review payload rendering * fix(review-feedback-1576): preserve market labels when rendering combined reviews and Use the * fix(review-feedback-1576): Render structured data for every combined market and Localize * fix: dedupe market review rendering * test: align market review language prompt expectation * fix(review-feedback-1576): 澄清并补足 LLM/运行时配置相关检测命中的兼容性证据 * fix(review-feedback-1576): 解决冲突并重新确认 CI * fix(review-feedback-1576): docs/CHANGELOG.md:[Unreleased] 新增内容中除 1555 大盘复盘展示外,还包含 Agent * fix(review-feedback-1576): 修复 * fix(review-feedback-1576): 修复美股中文大盘复盘仍混入英文策略/市场标签的问题,并补齐对应回归测试 --- api/v1/endpoints/analysis.py | 18 + api/v1/schemas/analysis.py | 4 + .../report/MarketReviewReportView.tsx | 553 ++++++++++++++++++ .../components/report/ReportMarkdownBody.tsx | 40 ++ .../components/report/ReportMarkdownPanel.tsx | 26 +- .../src/components/report/ReportSummary.tsx | 11 + .../__tests__/MarketReviewReportView.test.tsx | 177 ++++++ apps/dsa-web/src/components/report/index.ts | 2 + apps/dsa-web/src/index.css | 7 + apps/dsa-web/src/pages/HomePage.tsx | 74 ++- .../src/pages/__tests__/HomePage.test.tsx | 228 +++++++- apps/dsa-web/src/types/analysis.ts | 53 +- docs/CHANGELOG.md | 7 + docs/assets/issue-1555-market-review.png | Bin 0 -> 172267 bytes docs/full-guide.md | 2 + docs/full-guide_EN.md | 2 + src/core/market_review.py | 166 +++++- src/market_analyzer.py | 193 +++++- tests/test_analysis_api_contract.py | 8 +- tests/test_market_analyzer_generate_text.py | 104 +++- tests/test_market_review.py | 41 +- tests/test_market_strategy.py | 15 +- 22 files changed, 1618 insertions(+), 113 deletions(-) create mode 100644 apps/dsa-web/src/components/report/MarketReviewReportView.tsx create mode 100644 apps/dsa-web/src/components/report/ReportMarkdownBody.tsx create mode 100644 apps/dsa-web/src/components/report/__tests__/MarketReviewReportView.test.tsx create mode 100644 docs/assets/issue-1555-market-review.png diff --git a/api/v1/endpoints/analysis.py b/api/v1/endpoints/analysis.py index 9a53c5c32..741fa3d2e 100644 --- a/api/v1/endpoints/analysis.py +++ b/api/v1/endpoints/analysis.py @@ -148,12 +148,18 @@ def _run_market_review_background( "search_service": search_service, "send_notification": send_notification, "override_region": override_region, + "return_structured": True, } if query_id: review_kwargs["query_id"] = query_id report = run_market_review(**review_kwargs) if not report: raise RuntimeError("大盘复盘未返回可持久化报告") + if hasattr(report, "report"): + return { + "result": report.report, + "market_review_payload": getattr(report, "market_review_payload", None), + } return {"result": report} finally: _release_market_review_lock(lock_token) @@ -849,12 +855,16 @@ def get_analysis_status(task_id: str) -> TaskStatus: if task: result: Optional[AnalysisResultResponse] = None market_review_report = None + market_review_payload = None if task.status == TaskStatusEnum.COMPLETED and isinstance(task.result, dict): if task.stock_code == "market_review": report_text = task.result.get("result") if isinstance(report_text, str) and report_text.strip(): market_review_report = report_text + payload = task.result.get("market_review_payload") + if isinstance(payload, dict): + market_review_payload = payload else: try: result = _build_task_analysis_result(task) @@ -871,6 +881,7 @@ def get_analysis_status(task_id: str) -> TaskStatus: progress=task.progress, result=result, market_review_report=market_review_report, + market_review_payload=market_review_payload, error=task.error, stock_name=task.stock_name, original_query=task.original_query, @@ -890,6 +901,12 @@ def get_analysis_status(task_id: str) -> TaskStatus: raw_result = parse_json_field(record.raw_result) if getattr(record, "report_type", None) == "market_review": market_review_report = None + context_snapshot = parse_json_field(getattr(record, "context_snapshot", None)) + market_review_payload = None + if isinstance(context_snapshot, dict): + payload = context_snapshot.get("market_review_payload") + if isinstance(payload, dict): + market_review_payload = payload if isinstance(raw_result, dict): report_text = raw_result.get("raw_response") or raw_result.get("market_review_report") if isinstance(report_text, str) and report_text.strip(): @@ -904,6 +921,7 @@ def get_analysis_status(task_id: str) -> TaskStatus: progress=100, result=None, market_review_report=market_review_report, + market_review_payload=market_review_payload, error=None, stock_name=record.name, ) diff --git a/api/v1/schemas/analysis.py b/api/v1/schemas/analysis.py index ecc3f063c..4add4250a 100644 --- a/api/v1/schemas/analysis.py +++ b/api/v1/schemas/analysis.py @@ -271,6 +271,10 @@ class TaskStatus(BaseModel): None, description="大盘复盘任务返回的报告文本(仅大盘复盘任务)", ) + market_review_payload: Optional[Any] = Field( + None, + description="Structured market-review payload for API/Web consumers.", + ) error: Optional[str] = Field( None, description="错误信息(仅在 failed 时存在)" diff --git a/apps/dsa-web/src/components/report/MarketReviewReportView.tsx b/apps/dsa-web/src/components/report/MarketReviewReportView.tsx new file mode 100644 index 000000000..56de9679f --- /dev/null +++ b/apps/dsa-web/src/components/report/MarketReviewReportView.tsx @@ -0,0 +1,553 @@ +import type React from 'react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; +import { BarChart3, Clipboard, FileText, Gauge, Layers, ShieldAlert, TrendingUp, WalletCards } from 'lucide-react'; +import { historyApi } from '../../api/history'; +import type { + AnalysisReport, + MarketReviewPayload, + MarketReviewPayloadSection, + ReportLanguage, +} from '../../types/analysis'; +import { markdownToPlainText } from '../../utils/markdown'; +import { getReportText, normalizeReportLanguage } from '../../utils/reportLanguage'; +import { Card } from '../common'; +import { Tooltip } from '../common/Tooltip'; +import { ReportMarkdownBody } from './ReportMarkdownBody'; + +interface MarketReviewReportViewProps { + report?: AnalysisReport; + recordId?: number; + content?: string; + payload?: MarketReviewPayload | null; + reportLanguage?: ReportLanguage; + className?: string; +} + +type CopyType = 'markdown' | 'text'; +type LoadedMarkdown = { + recordId: number; + content: string; +}; +type LoadError = { + recordId: number; + message: string; +}; +type MarketReviewSection = { + id: string; + title: string; + content: string; + icon: typeof FileText; +}; +type StructuredMarketData = { + id: string; + title?: string; + breadth?: MarketReviewPayload['breadth']; + indices: NonNullable; +}; + +const isMarketReviewPayload = (value: unknown): value is MarketReviewPayload => + Boolean(value && typeof value === 'object'); + +const TOP_HEADING_PATTERN = /^\s*#\s+(.+?)\s*(?:\n+|$)/; +const SECTION_HEADING_PATTERN = /^(#{2,3})\s+(.+?)\s*$/gm; + +const normalizeHeading = (value: string): string => + value.trim().replace(/\s+/g, ' ').toLowerCase(); + +const stripTopHeading = (markdown: string, title?: string): string => { + const match = markdown.match(TOP_HEADING_PATTERN); + if (!match) { + return markdown.trim(); + } + + const heading = normalizeHeading(match[1]); + const reportTitle = normalizeHeading(title || ''); + const genericTitles = new Set([ + 'market review', + '大盘复盘', + '大盘复盘详情', + 'a股市场复盘', + 'a 股市场复盘', + ]); + + if (heading === reportTitle || genericTitles.has(heading)) { + return markdown.slice(match[0].length).trim(); + } + + return markdown.trim(); +}; + +const getSectionIcon = (title: string): typeof FileText => { + const normalized = normalizeHeading(title); + if (/指数|index|overview|大盘/.test(normalized)) { + return BarChart3; + } + if (/情绪|赚钱|sentiment|breadth|temperature/.test(normalized)) { + return Gauge; + } + if (/行业|板块|主题|轮动|sector|theme|rotation/.test(normalized)) { + return TrendingUp; + } + if (/资金|成交|量能|flow|turnover|volume|capital/.test(normalized)) { + return WalletCards; + } + if (/风险|机会|观察|risk|watch|next/.test(normalized)) { + return ShieldAlert; + } + return FileText; +}; + +const splitMarketReviewSections = (markdown: string): MarketReviewSection[] => { + const matches = Array.from(markdown.matchAll(SECTION_HEADING_PATTERN)); + if (matches.length === 0) { + return [{ + id: 'full-review', + title: '复盘正文', + content: markdown, + icon: FileText, + }]; + } + + const intro = markdown.slice(0, matches[0].index).trim(); + const sections: MarketReviewSection[] = intro + ? [{ + id: 'overview', + title: '复盘概览', + content: intro, + icon: FileText, + }] + : []; + + matches.forEach((match, index) => { + const start = (match.index ?? 0) + match[0].length; + const end = index + 1 < matches.length ? matches[index + 1].index ?? markdown.length : markdown.length; + const title = match[2].trim(); + const content = markdown.slice(start, end).trim(); + if (!content) { + return; + } + sections.push({ + id: `${index}-${normalizeHeading(title).replace(/[^a-z0-9\u4e00-\u9fa5]+/g, '-').replace(/^-|-$/g, '') || 'section'}`, + title, + content, + icon: getSectionIcon(title), + }); + }); + + return sections; +}; + +const getPayloadSections = (payload?: MarketReviewPayload | null): MarketReviewSection[] => { + if (!payload) { + return []; + } + + if (payload.markets) { + return Object.entries(payload.markets).flatMap(([region, marketPayload]) => { + const marketTitle = marketPayload.title || region.toUpperCase(); + return getPayloadSections(marketPayload).map((section) => ({ + ...section, + id: `${region}-${section.id}`, + title: `${marketTitle} / ${section.title}`, + })); + }); + } + + const payloadTitle = normalizeHeading(payload.title || ''); + return (payload.sections || []) + .filter((section: MarketReviewPayloadSection) => section.markdown?.trim()) + .filter((section: MarketReviewPayloadSection) => normalizeHeading(section.title || '') !== payloadTitle) + .map((section, index) => ({ + id: `${section.key || index}-${normalizeHeading(section.title).replace(/[^a-z0-9\u4e00-\u9fa5]+/g, '-') || 'section'}`, + title: section.title || 'Review', + content: section.markdown, + icon: getSectionIcon(section.title || ''), + })); +}; + +const hasStructuredMarketData = (payload?: MarketReviewPayload | null): boolean => + Boolean(payload?.breadth || payload?.indices?.length); + +const getStructuredMarketData = (payload?: MarketReviewPayload | null): StructuredMarketData[] => { + if (!payload) { + return []; + } + + if (payload.markets) { + return Object.entries(payload.markets) + .filter(([, marketPayload]) => hasStructuredMarketData(marketPayload)) + .map(([region, marketPayload]) => ({ + id: region, + title: marketPayload.title || region.toUpperCase(), + breadth: marketPayload.breadth, + indices: marketPayload.indices || [], + })); + } + + if (!hasStructuredMarketData(payload)) { + return []; + } + + return [{ + id: payload.region || 'market', + title: payload.title, + breadth: payload.breadth, + indices: payload.indices || [], + }]; +}; + +const MARKET_REVIEW_TEXT: Record = { + zh: { + reviewSummary: '复盘摘要', + noReviewSummary: '暂无摘要', + noSentimentScore: '暂无评分', + rotationAndFunds: '轮动与资金', + noRotationView: '暂无轮动观点', + riskAndWatch: '风险与观察', + noRiskWatch: '暂无观察重点', + structuredMarketData: '结构化大盘数据', + noBreadthData: '暂无数据', + advancers: '上涨家数', + decliners: '下跌家数', + limitUpDown: '涨停/跌停', + turnover: '成交额', + index: '指数', + last: '最新', + change: '涨跌幅', + highLow: '高/低', + }, + en: { + reviewSummary: 'Review Summary', + noReviewSummary: 'No review summary yet', + noSentimentScore: 'No score yet', + rotationAndFunds: 'Rotation & Funds', + noRotationView: 'No rotation view yet', + riskAndWatch: 'Risks & Watchlist', + noRiskWatch: 'No key observations yet', + structuredMarketData: 'Structured Market Data', + noBreadthData: 'No data', + advancers: 'Advancers', + decliners: 'Decliners', + limitUpDown: 'Limit Up/Down', + turnover: 'Turnover', + index: 'Index', + last: 'Last', + change: 'Change', + highLow: 'High/Low', + }, +}; + +export const MarketReviewReportView: React.FC = ({ + report, + recordId, + content: providedContent, + payload: providedPayload, + reportLanguage = 'zh', + className = '', +}) => { + const normalizedReportLanguage = normalizeReportLanguage(reportLanguage); + const text = getReportText(normalizedReportLanguage); + const marketReviewText = MARKET_REVIEW_TEXT[normalizedReportLanguage]; + const [loadedMarkdown, setLoadedMarkdown] = useState(null); + const [loadError, setLoadError] = useState(null); + const [copiedType, setCopiedType] = useState(null); + const summary = report?.summary; + const meta = report?.meta; + const contextPayload = report?.details?.contextSnapshot?.marketReviewPayload; + const marketReviewPayload = providedPayload ?? (isMarketReviewPayload(contextPayload) ? contextPayload : null); + const loadedContent = loadedMarkdown && loadedMarkdown.recordId === recordId ? loadedMarkdown.content : ''; + const content = providedContent ?? marketReviewPayload?.markdownReport ?? loadedContent; + const error = loadError && loadError.recordId === recordId ? loadError.message : null; + const hasStructuredContent = Boolean(marketReviewPayload?.sections?.length || marketReviewPayload?.markets); + const isLoading = Boolean(recordId && !providedContent && !hasStructuredContent && loadedMarkdown?.recordId !== recordId && !error); + const displayTitle = marketReviewPayload?.rootTitle || marketReviewPayload?.title || meta?.stockName || 'Market Review'; + const structuredContent = useMemo( + () => stripTopHeading(content, displayTitle), + [content, displayTitle], + ); + const sections = useMemo( + () => { + const payloadSections = getPayloadSections(marketReviewPayload); + return payloadSections.length > 0 ? payloadSections : splitMarketReviewSections(structuredContent); + }, + [marketReviewPayload, structuredContent], + ); + const structuredMarketData = useMemo( + () => getStructuredMarketData(marketReviewPayload), + [marketReviewPayload], + ); + const showStructuredMarketTitles = Boolean(marketReviewPayload?.markets); + + useEffect(() => { + if (!recordId || providedContent || hasStructuredContent) { + return undefined; + } + + let isMounted = true; + + historyApi.getMarkdown(recordId) + .then((markdownContent) => { + if (isMounted) { + setLoadedMarkdown({ recordId, content: markdownContent }); + setLoadError(null); + } + }) + .catch((err: unknown) => { + if (isMounted) { + setLoadError({ + recordId, + message: err instanceof Error ? err.message : text.loadReportFailed, + }); + } + }); + + return () => { + isMounted = false; + }; + }, [hasStructuredContent, providedContent, recordId, text.loadReportFailed]); + + const handleCopy = useCallback(async (type: CopyType) => { + if (!content) { + return; + } + try { + const value = type === 'markdown' ? content : markdownToPlainText(content); + await navigator.clipboard.writeText(value); + setCopiedType(type); + window.setTimeout(() => setCopiedType(null), 2000); + } catch (err) { + console.error('Copy failed:', err); + } + }, [content]); + + const insightCards = useMemo(() => [ + { + icon: FileText, + label: marketReviewText.reviewSummary, + value: summary?.analysisSummary || marketReviewText.noReviewSummary, + }, + { + icon: Gauge, + label: text.marketSentiment, + value: summary?.sentimentScore !== undefined + ? `${summary.sentimentScore} / 100` + : marketReviewText.noSentimentScore, + }, + { + icon: Layers, + label: marketReviewText.rotationAndFunds, + value: summary?.operationAdvice || marketReviewText.noRotationView, + }, + { + icon: ShieldAlert, + label: marketReviewText.riskAndWatch, + value: summary?.trendPrediction || marketReviewText.noRiskWatch, + }, + ], [marketReviewText, summary, text.marketSentiment]); + + return ( +
+ +
+
+
+
+

+ {displayTitle} +

+
+ {meta?.stockCode ? ( + {meta.stockCode} + ) : null} + {meta?.createdAt ? {new Date(meta.createdAt).toLocaleString()} : null} +
+
+ +
+ + + + + + + + + + +
+
+
+ + {summary ? ( +
+ {insightCards.map(({ icon: Icon, label, value }) => ( + +
+
+
+
+

{label}

+

{value}

+
+
+
+ ))} +
+ ) : null} + + {structuredMarketData.length > 0 ? ( + +
+ + +

{marketReviewText.structuredMarketData}

+
+
+ {structuredMarketData.map((marketData) => ( +
+ {showStructuredMarketTitles ? ( +

{marketData.title}

+ ) : null} + {marketData.breadth ? ( +
+
+

{marketReviewText.advancers}

+

{marketData.breadth.upCount ?? '-'}

+
+
+

{marketReviewText.decliners}

+

{marketData.breadth.downCount ?? '-'}

+
+
+

{marketReviewText.limitUpDown}

+

+ {marketData.breadth.limitUpCount ?? '-'} / {marketData.breadth.limitDownCount ?? '-'} +

+
+
+

{marketReviewText.turnover}

+

+ {marketData.breadth.totalAmount ?? '-'} {marketData.breadth.turnoverUnit || ''} +

+
+
+ ) : ( +

{marketReviewText.noBreadthData}

+ )} + {marketData.indices.length > 0 ? ( +
+ + + + + + + + + + + {marketData.indices.map((index) => ( + + + + + + + ))} + +
{marketReviewText.index}{marketReviewText.last}{marketReviewText.change}{marketReviewText.highLow}
{index.name}{index.current ?? '-'}{index.changePct !== undefined ? `${index.changePct}%` : '-'}{index.high ?? '-'} / {index.low ?? '-'}
+
+ ) : null} +
+ ))} +
+
+ ) : null} + + {isLoading ? ( + +
+
+

{text.loadingReport}

+
+ + ) : error ? ( + +
+
+
+

{error}

+
+
+ ) : ( +
+ {sections.map(({ id, title, content: sectionContent, icon: Icon }) => ( + +
+ + +

{title}

+
+ +
+ ))} +
+ )} +
+ ); +}; diff --git a/apps/dsa-web/src/components/report/ReportMarkdownBody.tsx b/apps/dsa-web/src/components/report/ReportMarkdownBody.tsx new file mode 100644 index 000000000..26cfe31b4 --- /dev/null +++ b/apps/dsa-web/src/components/report/ReportMarkdownBody.tsx @@ -0,0 +1,40 @@ +import type React from 'react'; +import Markdown from 'react-markdown'; +import remarkGfm from 'remark-gfm'; + +interface ReportMarkdownBodyProps { + content: string; + className?: string; + testId?: string; +} + +export const ReportMarkdownBody: React.FC = ({ + content, + className = '', + testId, +}) => ( +
+ + {content} + +
+); diff --git a/apps/dsa-web/src/components/report/ReportMarkdownPanel.tsx b/apps/dsa-web/src/components/report/ReportMarkdownPanel.tsx index fd5aaab4e..29e3fd358 100644 --- a/apps/dsa-web/src/components/report/ReportMarkdownPanel.tsx +++ b/apps/dsa-web/src/components/report/ReportMarkdownPanel.tsx @@ -1,12 +1,11 @@ import type React from 'react'; import { useCallback, useEffect, useState } from 'react'; -import Markdown from 'react-markdown'; -import remarkGfm from 'remark-gfm'; import { historyApi } from '../../api/history'; import type { ReportLanguage } from '../../types/analysis'; import { markdownToPlainText } from '../../utils/markdown'; import { getReportText, normalizeReportLanguage } from '../../utils/reportLanguage'; import { Tooltip } from '../common/Tooltip'; +import { ReportMarkdownBody } from './ReportMarkdownBody'; export interface ReportMarkdownPanelProps { recordId: number; @@ -166,28 +165,7 @@ export const ReportMarkdownPanel: React.FC = ({
) : ( -
- - {content} - -
+ )}
diff --git a/apps/dsa-web/src/components/report/ReportSummary.tsx b/apps/dsa-web/src/components/report/ReportSummary.tsx index 101605343..5ba0df0d7 100644 --- a/apps/dsa-web/src/components/report/ReportSummary.tsx +++ b/apps/dsa-web/src/components/report/ReportSummary.tsx @@ -6,6 +6,7 @@ import { ReportNews } from './ReportNews'; import { ReportDetails } from './ReportDetails'; import { ReportDiagnostics } from './ReportDiagnostics'; import { AnalysisContextSummary } from './AnalysisContextSummary'; +import { MarketReviewReportView } from './MarketReviewReportView'; import { getReportText, normalizeReportLanguage } from '../../utils/reportLanguage'; interface ReportSummaryProps { @@ -43,6 +44,16 @@ export const ReportSummary: React.FC = ({ modelUsed && !['unknown', 'error', 'none', 'null', 'n/a'].includes(modelUsed.toLowerCase()), ); + if (meta.reportType === 'market_review') { + return ( + + ); + } + return (
{/* 概览区(首屏) */} diff --git a/apps/dsa-web/src/components/report/__tests__/MarketReviewReportView.test.tsx b/apps/dsa-web/src/components/report/__tests__/MarketReviewReportView.test.tsx new file mode 100644 index 000000000..f1147a64c --- /dev/null +++ b/apps/dsa-web/src/components/report/__tests__/MarketReviewReportView.test.tsx @@ -0,0 +1,177 @@ +import { render, screen } from '@testing-library/react'; +import { describe, expect, it, vi } from 'vitest'; +import type { AnalysisReport, MarketReviewPayload } from '../../../types/analysis'; +import { MarketReviewReportView } from '../MarketReviewReportView'; + +vi.mock('../../../api/history', () => ({ + historyApi: { + getMarkdown: vi.fn(), + }, +})); + +const englishMarketReviewReport: AnalysisReport = { + meta: { + queryId: 'market-review-q-1', + stockCode: 'MARKET', + stockName: 'Market Review', + reportType: 'market_review', + reportLanguage: 'en', + createdAt: '2026-03-18T08:00:00Z', + }, + summary: { + analysisSummary: '', + operationAdvice: '', + trendPrediction: '', + sentimentScore: undefined as unknown as number, + }, +}; + +const combinedMarketReviewPayload: MarketReviewPayload = { + version: 1, + kind: 'market_review', + region: 'cn,hk', + language: 'zh', + rootTitle: '大盘复盘', + markets: { + cn: { + title: 'A股市场', + breadth: { + upCount: 3120, + downCount: 1420, + limitUpCount: 72, + limitDownCount: 4, + totalAmount: 9600, + turnoverUnit: '亿元', + }, + indices: [{ + code: '000300', + name: '沪深300', + current: 3920.2, + changePct: 1.2, + high: 3940.5, + low: 3860.1, + }], + }, + hk: { + title: '港股市场', + breadth: { + upCount: 680, + downCount: 410, + limitUpCount: 0, + limitDownCount: 0, + totalAmount: 1180, + turnoverUnit: '亿港元', + }, + indices: [{ + code: 'HSI', + name: '恒生指数', + current: 18920.4, + changePct: -0.5, + high: 19050.2, + low: 18780.3, + }], + }, + }, +}; + +const noBreadthMarketReviewPayload: MarketReviewPayload = { + version: 1, + kind: 'market_review', + region: 'us', + language: 'en', + title: 'Market Review', + rootTitle: 'Market Review', + indices: [{ + code: 'SPX', + name: 'S&P 500', + current: 5200, + changePct: 0.68, + high: 5235.2, + low: 5170.4, + }], + sectors: { + top: [{ name: 'Technology', changePct: 1.9 }], + bottom: [{ name: 'Energy', changePct: -0.8 }], + }, + news: [], + sections: [], +}; + +describe('MarketReviewReportView', () => { + it('uses localized summary card labels and fallbacks for English reports', () => { + render( + , + ); + + expect(screen.getByText('Review Summary')).toBeInTheDocument(); + expect(screen.getByText('No review summary yet')).toBeInTheDocument(); + expect(screen.getByText('Market Sentiment')).toBeInTheDocument(); + expect(screen.getByText('No score yet')).toBeInTheDocument(); + expect(screen.getByText('Rotation & Funds')).toBeInTheDocument(); + expect(screen.getByText('No rotation view yet')).toBeInTheDocument(); + expect(screen.getByText('Risks & Watchlist')).toBeInTheDocument(); + expect(screen.getByText('No key observations yet')).toBeInTheDocument(); + expect(screen.queryByText('复盘摘要')).not.toBeInTheDocument(); + expect(screen.queryByText('暂无摘要')).not.toBeInTheDocument(); + }); + + it('renders structured data for every market in a combined market review payload', () => { + render( + , + ); + + expect(screen.getByText('A股市场')).toBeInTheDocument(); + expect(screen.getByText('港股市场')).toBeInTheDocument(); + expect(screen.getByText('沪深300')).toBeInTheDocument(); + expect(screen.getByText('恒生指数')).toBeInTheDocument(); + expect(screen.getByText('3120')).toBeInTheDocument(); + expect(screen.getByText('680')).toBeInTheDocument(); + }); + + it('localizes structured market data labels for Chinese reports', () => { + render( + , + ); + + expect(screen.getByText('结构化大盘数据')).toBeInTheDocument(); + expect(screen.getAllByText('上涨家数')).toHaveLength(2); + expect(screen.getAllByText('下跌家数')).toHaveLength(2); + expect(screen.getAllByText('涨停/跌停')).toHaveLength(2); + expect(screen.getAllByText('成交额')).toHaveLength(2); + expect(screen.getAllByText('指数')).toHaveLength(2); + expect(screen.getAllByText('最新')).toHaveLength(2); + expect(screen.getAllByText('涨跌幅')).toHaveLength(2); + expect(screen.getAllByText('高/低')).toHaveLength(2); + expect(screen.queryByText('Structured Market Data')).not.toBeInTheDocument(); + expect(screen.queryByText('Advancers')).not.toBeInTheDocument(); + expect(screen.queryByText('Index')).not.toBeInTheDocument(); + }); + + it('shows "No data" when breadth is not available for a market review payload', () => { + render( + , + ); + + expect(screen.getByText('Structured Market Data')).toBeInTheDocument(); + expect(screen.getByText('No data')).toBeInTheDocument(); + expect(screen.getByText('S&P 500')).toBeInTheDocument(); + expect(screen.queryByText('Advancers')).not.toBeInTheDocument(); + expect(screen.queryByText('Decliners')).not.toBeInTheDocument(); + }); +}); diff --git a/apps/dsa-web/src/components/report/index.ts b/apps/dsa-web/src/components/report/index.ts index b409c8fee..9c7d90d18 100644 --- a/apps/dsa-web/src/components/report/index.ts +++ b/apps/dsa-web/src/components/report/index.ts @@ -6,3 +6,5 @@ export * from './ReportStrategy'; export * from './ReportNews'; export * from './ReportDetails'; export * from './ReportMarkdown'; +export * from './ReportMarkdownBody'; +export * from './MarketReviewReportView'; diff --git a/apps/dsa-web/src/index.css b/apps/dsa-web/src/index.css index 7f04d135d..cacf83cd1 100644 --- a/apps/dsa-web/src/index.css +++ b/apps/dsa-web/src/index.css @@ -1913,6 +1913,13 @@ textarea { padding: 4px 6px; } +.home-markdown-prose :where(table) { + display: block; + width: 100%; + overflow-x: auto; + white-space: nowrap; +} + .home-markdown-prose :where(th) { background: hsl(var(--elevated) / 0.92); color: hsl(var(--foreground)); diff --git a/apps/dsa-web/src/pages/HomePage.tsx b/apps/dsa-web/src/pages/HomePage.tsx index ca68b135b..8ff536cd5 100644 --- a/apps/dsa-web/src/pages/HomePage.tsx +++ b/apps/dsa-web/src/pages/HomePage.tsx @@ -12,12 +12,14 @@ import { DashboardStateBlock } from '../components/dashboard'; import { StockAutocomplete } from '../components/StockAutocomplete'; import { StockHistoryTrendDrawer, StockBar } from '../components/history'; import { ReportMarkdownDrawer } from '../components/report/ReportMarkdownDrawer'; +import { MarketReviewReportView } from '../components/report/MarketReviewReportView'; import { ReportSummary } from '../components/report/ReportSummary'; import { TaskPanel } from '../components/tasks'; import { useDashboardLifecycle, useHomeDashboardState } from '../hooks'; import { useWatchlist } from '../hooks/useWatchlist'; import type { SetupStatusResponse } from '../types/systemConfig'; import { getReportText, normalizeReportLanguage } from '../utils/reportLanguage'; +import type { MarketReviewPayload } from '../types/analysis'; type MarketReviewNotice = { variant: 'success' | 'warning' | 'danger'; @@ -32,7 +34,7 @@ const HomePage: React.FC = () => { const [marketReviewNotice, setMarketReviewNotice] = useState(null); const [marketReviewError, setMarketReviewError] = useState(null); const [marketReviewReport, setMarketReviewReport] = useState(null); - const [marketReviewReportCopied, setMarketReviewReportCopied] = useState(false); + const [marketReviewPayload, setMarketReviewPayload] = useState(null); const [analysisSkills, setAnalysisSkills] = useState([]); const [selectedStrategyId, setSelectedStrategyId] = useState(''); const [strategyMenuOpen, setStrategyMenuOpen] = useState(false); @@ -176,6 +178,7 @@ const HomePage: React.FC = () => { }, [analysisSkills, selectedStrategyId]); const reportLanguage = normalizeReportLanguage(selectedReport?.meta.reportLanguage); + const liveMarketReviewLanguage = normalizeReportLanguage(marketReviewPayload?.language); const reportText = getReportText(reportLanguage); const isMarketReviewHistoryReport = selectedReport?.meta.reportType === 'market_review'; const isHistoryTrendUnavailable = !selectedReport || selectedReport.meta.reportType === 'market_review' @@ -316,10 +319,19 @@ const HomePage: React.FC = () => { const watchlistState = useWatchlist(); + const clearMarketReviewState = useCallback(() => { + stopMarketReviewPolling(); + setMarketReviewReport(null); + setMarketReviewPayload(null); + setMarketReviewNotice(null); + setMarketReviewError(null); + }, [stopMarketReviewPolling]); + const handleHistoryItemClick = useCallback((recordId: number) => { + clearMarketReviewState(); void selectHistoryItem(recordId); setSidebarOpen(false); - }, [selectHistoryItem]); + }, [clearMarketReviewState, selectHistoryItem]); const [isDeletingStock, setIsDeletingStock] = useState(false); const handleDeleteStock = useCallback(async (stockCode: string) => { @@ -391,6 +403,7 @@ const HomePage: React.FC = () => { if (attempts >= maxAttempts) { stopMarketReviewPolling(); setMarketReviewReport(null); + setMarketReviewPayload(null); setMarketReviewNotice({ variant: 'danger', title: '大盘复盘已超时', @@ -406,6 +419,7 @@ const HomePage: React.FC = () => { const status = await analysisApi.getStatus(taskId); if (status.status === 'pending' || status.status === 'processing') { setMarketReviewReport(null); + setMarketReviewPayload(null); const progress = typeof status.progress === 'number' ? `${status.progress}%` : '进行中'; @@ -423,6 +437,7 @@ const HomePage: React.FC = () => { ? status.marketReviewReport : ''; setMarketReviewReport(marketReviewText ? marketReviewText.trim() : null); + setMarketReviewPayload(status.marketReviewPayload ?? null); setMarketReviewNotice({ variant: 'success', title: '大盘复盘已完成', @@ -436,6 +451,7 @@ const HomePage: React.FC = () => { if (status.status === 'failed') { stopMarketReviewPolling(); setMarketReviewReport(null); + setMarketReviewPayload(null); setMarketReviewError( getParsedApiError({ response: { @@ -454,6 +470,7 @@ const HomePage: React.FC = () => { stopMarketReviewPolling(); setMarketReviewReport(null); + setMarketReviewPayload(null); setMarketReviewNotice({ variant: 'danger', title: '大盘复盘状态异常', @@ -466,6 +483,7 @@ const HomePage: React.FC = () => { if (attempts >= maxAttempts) { stopMarketReviewPolling(); setMarketReviewReport(null); + setMarketReviewPayload(null); setMarketReviewError(parsed); setMarketReviewNotice(null); scrollMarketReviewFeedbackIntoView(); @@ -495,6 +513,7 @@ const HomePage: React.FC = () => { setMarketReviewNotice(null); setMarketReviewError(null); setMarketReviewReport(null); + setMarketReviewPayload(null); scrollMarketReviewFeedbackIntoView(); try { const result = await analysisApi.triggerMarketReview({ sendNotification: notify }); @@ -517,22 +536,6 @@ const HomePage: React.FC = () => { } }, [notify, pollMarketReviewStatus, scrollMarketReviewFeedbackIntoView]); - const handleCopyMarketReviewReport = useCallback(() => { - if (!marketReviewReport) { - return; - } - - void navigator.clipboard.writeText(marketReviewReport).then( - () => { - setMarketReviewReportCopied(true); - setTimeout(() => setMarketReviewReportCopied(false), 2000); - }, - (err) => { - console.error('复制失败:', err); - }, - ); - }, [marketReviewReport]); - const sidebarContent = useMemo( () => (
@@ -778,25 +781,12 @@ const HomePage: React.FC = () => { ) : null} {marketReviewReport ? ( -
-
-

大盘复盘报告

- -
-
-                  {marketReviewReport}
-                
-
+ ) : null} {error ? ( @@ -806,12 +796,13 @@ const HomePage: React.FC = () => { onDismiss={clearError} /> ) : null} - {isLoadingReport ? ( + {!marketReviewReport && isLoadingReport ? (
- ) : selectedReport ? ( + ) : !marketReviewReport && selectedReport ? (
+ {!isMarketReviewHistoryReport ? (
+ ) : null} {isHistoryTrendOpen ? ( { /> )}
- ) : ( + ) : !marketReviewReport ? (
{ )} />
- )} + ) : null}
diff --git a/apps/dsa-web/src/pages/__tests__/HomePage.test.tsx b/apps/dsa-web/src/pages/__tests__/HomePage.test.tsx index 66cf9147f..d9f17ebc4 100644 --- a/apps/dsa-web/src/pages/__tests__/HomePage.test.tsx +++ b/apps/dsa-web/src/pages/__tests__/HomePage.test.tsx @@ -290,6 +290,51 @@ describe('HomePage', () => { expect(analysisApi.getStatus).toHaveBeenCalledWith('task-1'); }); + it('uses the payload language for live market review controls', async () => { + vi.mocked(historyApi.getList).mockResolvedValue({ + total: 0, + page: 1, + limit: 20, + items: [], + }); + vi.mocked(analysisApi.triggerMarketReview).mockResolvedValue({ + status: 'accepted', + sendNotification: true, + message: 'Market review task submitted', + taskId: 'task-1', + }); + vi.mocked(analysisApi.getStatus).mockResolvedValue({ + taskId: 'task-1', + status: 'completed', + marketReviewReport: '# US Market Recap\n\n## Summary\n\nUS market review body', + marketReviewPayload: { + kind: 'market_review', + region: 'us', + language: 'en', + title: 'US Market Recap', + sections: [ + { + key: 'summary', + title: 'Summary', + markdown: 'US market review body', + }, + ], + }, + }); + + render( + + + , + ); + + fireEvent.click(await screen.findByRole('button', { name: '大盘复盘' })); + + expect(await screen.findByRole('button', { name: 'Copy Markdown Source' })).toBeInTheDocument(); + expect(screen.getByRole('button', { name: 'Copy Plain Text' })).toBeInTheDocument(); + expect(screen.queryByRole('button', { name: '复制 Markdown 源码' })).not.toBeInTheDocument(); + }); + it('scrolls the dashboard to market review feedback after toolbar clicks', async () => { vi.mocked(historyApi.getList).mockResolvedValue({ total: 1, @@ -354,7 +399,56 @@ describe('HomePage', () => { vi.mocked(analysisApi.getStatus).mockResolvedValue({ taskId: 'task-1', status: 'completed', - marketReviewReport: Array.from({ length: 30 }, (_, index) => `第 ${index + 1} 行复盘内容`).join('\n'), + marketReviewReport: [ + '# A股市场复盘', + '', + '> 市场情绪修复', + '', + '## 指数概览', + '', + '| 指数 | 表现 |', + '| --- | --- |', + '| 上证指数 | 震荡走强 |', + '', + '## 风险提示', + '', + '- 资金回流核心资产', + ].join('\n'), + marketReviewPayload: { + kind: 'market_review', + region: 'cn', + title: 'A股市场复盘', + breadth: { + upCount: 3200, + downCount: 1700, + limitUpCount: 60, + limitDownCount: 8, + totalAmount: 9800, + turnoverUnit: '亿', + }, + indices: [ + { + code: '000001', + name: '上证指数', + current: 3150.2, + changePct: 0.62, + high: 3168.4, + low: 3120.8, + }, + ], + sections: [ + { + key: 'index_overview', + title: '指数概览', + markdown: '| 指数 | 表现 |\n| --- | --- |\n| 上证指数 | 震荡走强 |', + }, + { + key: 'risk', + title: '风险提示', + markdown: '- 资金回流核心资产', + }, + ], + }, }); render( @@ -370,7 +464,15 @@ describe('HomePage', () => { expect(dashboardScroll).toContainElement(marketReviewReport); expect(marketReviewReport.className).not.toContain('max-h-64'); expect(marketReviewReport.className).not.toContain('overflow-y-auto'); - expect(await screen.findByText('开始分析')).toBeInTheDocument(); + expect(screen.getByRole('heading', { name: '结构化大盘数据' })).toBeInTheDocument(); + expect(screen.getByText('3200')).toBeInTheDocument(); + expect(screen.getByText('3150.2')).toBeInTheDocument(); + expect(marketReviewReport.querySelector('h2, h3')?.textContent).not.toBe('A股市场复盘'); + expect(screen.getByRole('heading', { name: '指数概览' })).toBeInTheDocument(); + expect(screen.getByRole('heading', { name: '风险提示' })).toBeInTheDocument(); + expect(screen.getAllByRole('table').length).toBeGreaterThanOrEqual(2); + expect(screen.queryByText('# A股市场复盘')).not.toBeInTheDocument(); + expect(screen.queryByText('开始分析')).not.toBeInTheDocument(); }); it('shows first-run setup gaps and links to settings', async () => { @@ -701,7 +803,7 @@ describe('HomePage', () => { expect(trigger).toHaveFocus(); }); - it('disables stock reanalysis and follow-up for market review history reports', async () => { + it('renders market review history reports with a dedicated markdown view', async () => { vi.mocked(historyApi.getList).mockResolvedValue({ total: 1, page: 1, @@ -709,6 +811,19 @@ describe('HomePage', () => { items: [marketReviewHistoryItem], }); vi.mocked(historyApi.getDetail).mockResolvedValue(marketReviewHistoryReport); + vi.mocked(historyApi.getMarkdown).mockResolvedValue([ + '# 大盘复盘详情', + '', + '## 市场情绪与赚钱效应', + '', + '**赚钱效应** 改善', + '', + '## 行业/主题轮动', + '', + '| 方向 | 状态 |', + '| --- | --- |', + '| 半导体 | 轮动增强 |', + ].join('\n')); render( @@ -717,16 +832,107 @@ describe('HomePage', () => { ); await screen.findByText('大盘复盘摘要'); - const reanalyzeButton = screen.getByRole('button', { name: '重新分析' }); - const followUpButton = screen.getByRole('button', { name: '追问 AI' }); - - expect(reanalyzeButton).toBeDisabled(); - expect(followUpButton).toBeDisabled(); - - fireEvent.click(reanalyzeButton); - fireEvent.click(followUpButton); + expect(screen.queryByRole('heading', { name: '大盘复盘详情' })).not.toBeInTheDocument(); + expect(await screen.findByRole('heading', { name: '市场情绪与赚钱效应' })).toBeInTheDocument(); + expect(screen.getByRole('heading', { name: '行业/主题轮动' })).toBeInTheDocument(); + expect(screen.getByText('赚钱效应')).toBeInTheDocument(); + expect(screen.getByRole('table')).toBeInTheDocument(); + expect(screen.queryByRole('button', { name: '重新分析' })).not.toBeInTheDocument(); + expect(screen.queryByRole('button', { name: '追问 AI' })).not.toBeInTheDocument(); + expect(screen.queryByRole('button', { name: '历史趋势' })).not.toBeInTheDocument(); + expect(historyApi.getMarkdown).toHaveBeenCalledWith(marketReviewHistoryReport.meta.id); expect(analysisApi.analyzeAsync).not.toHaveBeenCalled(); expect(navigateMock).not.toHaveBeenCalled(); }); + + it('clears live market review output when switching to a history report', async () => { + vi.mocked(historyApi.getList).mockResolvedValue({ + total: 1, + page: 1, + limit: 20, + items: [historyItem], + }); + vi.mocked(historyApi.getStockBarList).mockResolvedValue({ + total: 2, + items: [ + { + id: 2, + stockCode: 'MARKET', + stockName: '大盘复盘', + sentimentScore: 50, + operationAdvice: '查看复盘', + analysisCount: 1, + lastAnalysisTime: '2026-03-18T08:30:00Z', + reportType: 'market_review', + }, + { + id: 1, + stockCode: '600519', + stockName: '贵州茅台', + sentimentScore: 82, + operationAdvice: '买入', + analysisCount: 1, + lastAnalysisTime: '2026-03-18T08:00:00Z', + reportType: 'detailed', + }, + ], + }); + vi.mocked(historyApi.getDetail).mockImplementation((recordId: number) => { + if (recordId === 2) { + return Promise.resolve(marketReviewHistoryReport); + } + return Promise.resolve(historyReport); + }); + vi.mocked(historyApi.getMarkdown).mockResolvedValue([ + '# 大盘复盘详情', + '', + '## 市场情绪与赚钱效应', + '', + '**赚钱效应** 改善', + '', + '## 行业/主题轮动', + '', + '| 方向 | 状态 |', + '| --- | --- |', + '| 半导体 | 轮动增强 |', + ].join('\n')); + vi.mocked(analysisApi.triggerMarketReview).mockResolvedValue({ + status: 'accepted', + sendNotification: true, + message: '大盘复盘任务已提交', + taskId: 'task-1', + }); + vi.mocked(analysisApi.getStatus).mockResolvedValue({ + taskId: 'task-1', + status: 'completed', + marketReviewReport: '市场复盘报告示例文本', + }); + + render( + + + , + ); + + await screen.findByText('趋势维持强势'); + + fireEvent.click(screen.getByRole('button', { name: '大盘复盘' })); + + await waitFor(() => { + expect(screen.getByText('大盘复盘已完成')).toBeInTheDocument(); + expect(screen.getByText('市场复盘报告示例文本')).toBeInTheDocument(); + }); + + const marketHistoryButton = screen.getByRole('button', { name: /MARKET/ }); + fireEvent.click(marketHistoryButton); + + await waitFor(() => { + expect(screen.queryByText('市场复盘报告示例文本')).not.toBeInTheDocument(); + expect(screen.queryByText('大盘复盘已完成')).not.toBeInTheDocument(); + }); + expect(await screen.findByText('大盘复盘摘要')).toBeInTheDocument(); + expect(screen.getByRole('heading', { name: '市场情绪与赚钱效应' })).toBeInTheDocument(); + expect(vi.mocked(historyApi.getDetail)).toHaveBeenCalledWith(2); + }); }); diff --git a/apps/dsa-web/src/types/analysis.ts b/apps/dsa-web/src/types/analysis.ts index 80b6129dc..79b0b3a2b 100644 --- a/apps/dsa-web/src/types/analysis.ts +++ b/apps/dsa-web/src/types/analysis.ts @@ -125,6 +125,56 @@ export interface SectorRankings { bottom?: SectorRankingItem[]; } +export interface MarketReviewPayloadSection { + key?: string; + title: string; + markdown: string; +} + +export interface MarketReviewIndex { + code: string; + name: string; + current?: number; + change?: number; + changePct?: number; + open?: number; + high?: number; + low?: number; + volume?: number; + amount?: number; + amplitude?: number; +} + +export interface MarketReviewBreadth { + upCount?: number; + downCount?: number; + flatCount?: number; + limitUpCount?: number; + limitDownCount?: number; + totalAmount?: number; + turnoverUnit?: string; +} + +export interface MarketReviewPayload { + version?: number; + kind?: 'market_review' | string; + region?: string; + language?: ReportLanguage | string; + title?: string; + rootTitle?: string; + generatedAt?: string; + date?: string; + marketScope?: string; + marketLight?: Record; + breadth?: MarketReviewBreadth; + indices?: MarketReviewIndex[]; + sectors?: SectorRankings; + news?: Array>; + sections?: MarketReviewPayloadSection[]; + markets?: Record; + markdownReport?: string; +} + export type AnalysisContextPackBlockStatus = | 'available' | 'missing' @@ -190,7 +240,7 @@ export interface AnalysisContextPackOverview { export interface ReportDetails { newsContent?: string; rawResult?: Record; - contextSnapshot?: Record; + contextSnapshot?: Record & { marketReviewPayload?: MarketReviewPayload }; analysisContextPackOverview?: AnalysisContextPackOverview | null; financialReport?: Record; dividendMetrics?: Record; @@ -292,6 +342,7 @@ export interface TaskStatus { progress?: number; result?: AnalysisResult; marketReviewReport?: string; + marketReviewPayload?: MarketReviewPayload; error?: string; stockName?: string; originalQuery?: string; diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index ff163626c..38250ca96 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -10,6 +10,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/). ## [Unreleased] - [修复] Web/桌面端左侧导航选中态改用 border 实现,避免蓝色竖条指示器溢出侧栏边界;侧栏展开宽度 116px → 136px,新增 rail 紧凑模式。 +- [修复] Agent 分析路径生成 AnalysisContextPack overview 前复用已落库日线分析上下文,避免日线已抓取成功仍显示 `daily_bars_missing`。 +- [新功能] Web 大盘复盘报告新增专用展示视图,历史入口和首页即时结果统一使用 Markdown/GFM 渲染并隐藏个股专属模块。 +- [新功能] 大盘复盘新增结构化 `market_review_payload`,Web、历史详情和推送统一基于结构化数据渲染,并保留 Markdown 兼容展示。 +- [文档] 本次迭代仅重构大盘复盘展示链路(统一 Markdown/GFM 渲染与结构化 payload 渲染),不涉及 `LITELLM_*`、`LLM_*`、`provider/model/base_url` 等运行时配置语义;如需回退采用常规发布回滚。 +- [修复] 修正大盘复盘结构化 `breadth` 的可用性判断:当市场不支持/抓取失败(如美股、港股或 A 股 breadth 不可用)时不下发 `breadth`,前端展示“暂无数据”,避免误导性 0 值。 +- [修复] 明确大盘复盘语言行为调整为遵循全局 `report_language`,并在回退场景保持原语种提示(如美股/港股默认会按配置语言展示);兼容性变化说明见该条款,无需额外改动 provider/model/base_url。 +- [修复] 美股中文场景下,市场标签与策略蓝图(`Strategy Blueprint/Strategy Framework`)已本地化为中文显示,避免 `report_language=zh` 下混入英文策略段落与市场标签;与 Issue #1555 的历史/即时结果一致。 diff --git a/docs/assets/issue-1555-market-review.png b/docs/assets/issue-1555-market-review.png new file mode 100644 index 0000000000000000000000000000000000000000..d2e4af785e324ee1b137d953632d22cb4188c3f3 GIT binary patch literal 172267 zcmZ5{V|1iV*KQ_OCz%)>O`J@uj%{P&iEZ1qZDV3jY}>Xb6Whtj^F8mo&UeoJr`PJL zuBwgus=cqhJ4{|y3;>S{4+aJXkPsJE1OtQ01p|Yufd&8k#^1ob1`G@ZOhQ;d*){X@ zCyXv|U?F?O;%~gw$d7Y?WdOne+k*0(3F$j+Kiy-C5MIZ`z;3l!|uO8pB za}2C-E6a5<_LaJYA`7mM)5+u&caIXTC(@3oqnWkldK(iH6BmK7o)|N1c}H46us<=IhwF zBmw^-W9XL=W~s;NyZ67Q@xurmeoou>mh0y)j=K~l^+WQ&%dp>0L)r%YuW8e9v2gwn z9-9*JeD7d=>1?~dgLp2nm%Us>|33i`XQga)kv+tjLX3#Wj2n`*x}y(43VUDIDYGE> z9l(aZ{NF`=qx~Ge0zq-UhR@Vl?lX`!$udHck#a;G7T9o)r!y+8DWBGgIeFN#MT-`-C5`Nz zP(x41fd~NEd`+QQt>C}2FzF2btS=`LU+S;+ck)}l7eaidMEArP_WQ^z><*3d7j}L z7X&8=@{9?i#qcLue`Rgm^b;f1MlBCQB^~;z&HngKg%;74hrf0?IRV1F+xFiTb}+;m znnB`&yUhLvCBVR@t7az6byn6TA)O(%KRtF8za0e#w+skjq)LSaKjwkG`zu!l__&_{ z&05-^aAlHxu`I!FG~zt<;#uvih?keG@QhUxHjA!AogjXy{EdbUSpBr`5*vE=m@_ML0&h2zU6cOZ z$&|UUUOy=+sln2M%pdRi3zRGI7bYkd|GuaV`NNI|BlhsNIK6^53_Q<;wsB{MItMt3 zvi{}vq)@;_oEH#Aq`kqU-IGD18GdQ$PZ{I4I2y6yO$2R%?b8=hQXdi?EwX=g24+e^ z`YXLqk#VGIRQkT*AGuz@w8edIyMwmHlQ(pIYL+{IcZ9ghj~zs;8?{%q*~c|mjq^e+ zwO)iciP>h+5TkaXB0uv3#CB;^1h`lz+ixI66L#A!0Y5?&J+n)wDQnX@tOvkUeIzOtpq7|5bYSw! z0Z3d{+wsv_gcqKV#t(5ScEpFGr~;TS3) zvHy|&RX>v}5oLkAfCF7tG@B{V3iXX!INY0ml-k-1zT$(Mf9TUhkA(%{3T8slcJk(3#v(nSEav zu0GB9D;c;fH5-`j-L`nr2JC(=Bid`m5`5#!gh%b!FnZQ}D1o=-ZE3=;7ff6)s-l)Z zxWF5WySTg*b5;3((~DP921G;`e1%paIjkKoZo5nHLWU3pe4S~9q+RoJcfd4zgk1wv z+N@z$)LM5;-~F1y_A=nq%49c&}sW}6X}EFpqcvHtnVH$Go^-ULxc;8nf=U`!n8Gkv>tPrmfweCdeIcp7A#AsuA+u+XydQN*zcmVn_7gubA771ImL7e_ z)iNbf#qhiCSXv6p+ttO@jM%pv9d@g`RowsZ$p`ciKY|*p30!(8LOLW@TM-xiZfzst^}@#7vz5x zMI}>)MV8KUo{_` z2`pb-!>c0kBKh~Ij;N$7431$(i>8(*zZAr5zHuIv&{W5r|Dv9}q|XX-2;HA_Y;bD% zF$oVT*3=uly}cUy>O~@*R~9OXc1uW&GSg*|K~kTqh^HL-aJ+PxLeWo5@*~1|69-Pn zdpism-tjClD0^G|lbB_mCam9?N+44Rrfv@uyOY}l8Ql<@Pe+;xLDH9cLL3Fc$kX$g0zX_>?K_xO z-lh#n-ni^wPxe~VGqtWNzFpK&PaLHy`Otd! z+_4!- zJ}KCBGnmC>!~~zT;|&WdVzWYt%=GjLMRX}Hqnyp(!_7IT(aqUcT0sFLV*S5KnEq1w zfy4;FTQ)MWNSJrV+3B^$E(K(EhgzWT?#Mq7+ShI*=g9qQcXa?e-$K5rSr~Jo~qN}d`pfOMZ3qmbPgwPfaVq;#f@Eg3!p^FB!}`134g)EdW6_>&_GFPOOGVW6m1fZ>*Tb9 z&68J0LP8=Xo{pm>&zJAd!wbs4GJtjat9>Vk64lVqxWA|_E2|6}+7qu-S#hObYr`_E zVG}P;$FcfmoPozAx&C;ciC6Yh{e(HgRfXI|`_y_&5pw}E(~Ee*b>;_Z+zvRR_!nSL z4=dG1>d!%ISbLvFdS6M&Kw7?G1>iD3ooL`^FP1hHp)BYE5t&43JR6^GlWLq|%E z1`a|4V^$)yca{MoUVFRc3f7&Rd%*!Q!K^IfZ9Sq{*n7IsfS$jeKn^!rlQ+_bI|>Z* zzJ5DOGv$Ol4|g^CS1^#>wwkhO1;xOI_yj=(Px&M;1U^2`MKf4k;xxDB0~;L+>*0b= z_hPf-WXVSOKa%(g=Q_32M7FlJW^pMrTmMAnb=_~W(zGx)SA#rVNb36&>|3kjKScrM z{attLi-a-}v+|mB6LKV>wX`s5#GDVh;&S=@N6WBba`OoC_i1M;6QW=U zt5p1RHKFkNVcLn`MR4r%dq0zU?`ajA*@?)uUwgB!b(+kawz>l^A**lezNsn1bqaYV zlC1pbX|Y+Z!TSW^^Ol&nDf%rwO}ai1MQNu7yyEIZKdMYlSl^^Ei{kAIjjcn0cjAsM z9r-Rfkj$ODrVFNjhjOuAC(~H#0J_i%Pgy$*qE>uSjI+h1m6l1umh_Pz)%oFkp{>GW z<#0mt7z_75w;Y(FASF63sK#gE{8v_+^R;``uIZZm{Es~O*rr*t3?=I~DPnW{y1;D) zfnsYzaIwo7XD1M_R#+mxI@%tmIi-y4 z*zkvk`}PVaqG}XS=|5TKOczDI(Z2KN=GKtP zUdU+Sm>Jm-)?rczeV;YaJ-vExTxa zcF_mQ9fK8o$;iKp+Wdo??Xp`C9?k*YVlaq*y4-G(Om2W|gibz6z0~sUH-r=nZRDsV^*?m< zwX^JI_*6ys!a8M8)Ls1Guok4wV@i#FTt0DT477oC&47zgoL$8fm=craFxE*D0g+;# zuUevUMVir!8988Cl!@f-WT%V8?Cme9ahuGanU0}so`s2tONsxeLL8Y=rncE#=iz)q z#yulAKYTZSH~o$E$`x0Otzy_anuH)?W{jSSitVE2H}Q=d_UK5#+2!CfCpd)SEKGV@ z6u>EwV{~LsPmpY>XWsurZWT%>#JqV@XSl!ew*KE zYNBf-x=U2{o06iMKiDQwsu?vBG%~)Wt*v|$WzW|L><~ZQK0#`xN`A@K5oc)vmQRaIn9~Gj&?~aD^xfG5jd1B*7 zi}%t!;jzuh;X-}a>!WH{tE5y<5nqSvd;1g(jn8_chr_`=VUFitKF{Y(w+A0C7pr&k zdkQG1CrXI!d~s$KneR-9%8Y1W+L@p__(etI51wg9GBUEpMuxxt(hp!n6S?2PDviqM z;3gZTg#|eT%myJgTnfDIN{YU!r7Qo43=tG?i=e`{sBd`++Oc)evOFWL0MqQ>s}(Qg zpqS$J>rdWb7*%-(R|g^VyZN|YZA_!9-S7R;z$NrR2Y2<& zZJh!6PU&o5_*<>I@#|XJ2IyvZyD@6Gs0ec4AI<5}N;keJ{EWI;&mUw!nMUg_5!=|* zQM!4DA?$csY}@kgGVb>EcG-9e@!`34`Nj9JUjKeu!k7GT#%%N6%U;q|Z#Ytydn(ss zJ6c8oz+rM-s@ga>IKa|&;jNV+bJxsaI!CWJYO0PV{wF~I<8KwP zQ2!~(vgG0s4PgL83`*BbKXW!FVd9CbyBu^g! zzt6Z;i4JhggY1E9Bp$h#+Hc3B%rinj*1x0CBj1~O9Jb465&aSi=FL^)nGiOLjnfY4 z${TQb)sp&a2$GMxKPv_$s!nAX5g3yC(tT0d`jlr9Nung|m71`^B>FeJiHXnmEBk@8 zgTt6qb$h4oyFT^Dt4YeH-AiRjw*794(j)<=qpg7VyBOir^MX^?OqJrz2k5v^!p+U? zqKn;NwB;x=$F(1UzCDr&vBDu{U8nbeP4YvE8-fs8(>Z`NGBYJ(Z5F)V=06xwNZ62^ zq%)nNw5$x8l&kIkAY*7!)2h~86ICU)cRoVYfrWc1v}ESQ&4N>#l=H(61S<1Vt!#zQXmE z*pT?rke)N@4Ym4>)bRGKnxY4-ZnLGyh0L|%9ex`)4*TgBIuMKPlIGG^O7V<>kbN3Z7u8{+Bvc`!sz+mC<|}O`LZQA3=mkzF6g(VC0Y& zZ&A+j2pR_@q*w+KYFMz~Gk7BREt|5P>a0s>=Qm2lj40Voye4-%AAlhi42Qdq>)i%X z@MF4mWW>Rn2wNLjH;(@vK@z2+FD(nK=%D}&EKWPeBkZCZJK|}uGXnl%5Lxls_ziA9 zNB>|VkyOjlV%@;P!a`ywEft;T)qv{JgywvK*n>%q+iqXlg><@O1?EdH!W1Ek>Gty- zUgzU$d85UW%f-yw@?Nwk4!E;Q8qjq0O9j?m*hX&ccfz0lu_?bhKWyAzjYEy1Jl?~b zmtDKXHQ~&RSbV%gXB4tv(g!b}ntTZ`VUI1pfL2I>A4mq}i$5cafT{jgXo6?WYZj?xj25*j&Bo;n z)7{6gY^VM12?>$lqKxv)Swp2ZoWZJ}$~KsYow@yEeR}%#hNkNM*dU@WkGGW#*0kV*^owl^A_L*ynqZD*v+anV0zn>uY(mdtq=7#N_f06-W zhoB#B5W%jv2mQIC%|(8L16J zdqusx{MyIEY#YtZHcmyWCTwro6>z%SBf!uk6K^#;_HrL4{Ef>+rFPTs!1L`FkA1KYK=JpyB&T%8jdF9@dki2tCACvmq!RCfZ?bbhp}N89xG2eA#u z)z?r)ZAkV-DKR!yTx`IMWB|u_n;y|xO>gZnMNNmI=fr|)B!QQ>$iV#r?_=!N&3wXC zHv7TpIZrDx?sAvhmOXXFi{4xFmesDJyiF2tMhv$AcyW`pO zYDF45=AVig82{pz@~o+3cx;_=6?AM(i@edh)7{u(HKjdXSIgcT69j!4S$y(DNU-7;Yx3y9}{%|gjn4`X&h_!_Sm zX`WxSFL5?oWX#>~PiZPQ!oI)4CQuk&2h8Pf5pe0(FjJ?HSIdC9)yaU`Ny6qa%dg;wLfK(O(uzj8zTje{s}( zf|8ES8;Hb6DO_J)&(ZNdCd10&^IVRNBSHFAZsU4=eB`6mwUY;P!E=~e(5cfwjv9uD zJ?%5S?Psx6rTKK`a+Jk4aCGDKyn=<8+CeO2TjZ+S`C(0?X(%}srN|Op#4y|p~?5xy}+{k;~dB9;~xIYmkX7ucW(?M zcIUJ8>?+HpKdHBM3}^Va=ZJidC=a_<;RdS>2YD5e^c49qYqbfoY3wh|zr{XnKh3M# zX9rRxqs5EUd8gCn6>lEYun?VwjVt%b*^{=-wcH0O|8|-$3fag7-OVSM@oWj(-X70+ z3`J+*XuhlT1Yu=*d_X*)qobRqvu}9@#auq0*vMwNhcrE9WK>-&lvBJ}ZFTkxoW8mt z;FQN#ycO>B+QE9GiBY&LJDfsG&R?!SlW2eNT)_+nN>HMZisktKJ-Mv13Y-PLK|4^@ zkV*u*UbmE9@LTfz?1a@6AbBuGEblnks<@h zjK_?N5eqHm(GuDP&2;Qk53>ZWBgFL>BZT0kA~7v1%Xsl;TV>Mg18VulB+e8Sxerd~ zj^R%5a68kPFLYwKYhO<=995m}-m88}P4b>NN}4n@G*qZPO+X;OZu!2yA>n%szrV3Y zVA0N?wwcbvOVM|f>U?xkD(T7shiAed)N>5I*(D(4VvUzOQ)(Sf(YN;A`D2@g7AxN- z3kxSIlg6+fPWXPex92n-M{_&CH*~Q7jjfd~c7$_q23gPUcfLWJ+L@NWXCz6*t)p{4 zFDJyZn~Evi(p`u}T~x0Oq58~HnJD`EGC?WlrW6-#nfq)Ym$xM)CnY77b zlf6Lf#S#IeXgy2G6szwCMM-ik?_nw}O+owv5^Q}{N74aS$Z0ZUN=EFK&O!I5*w?#n zCsi%u%03~dp-N=>|bDf##;y*|~O zc{)E5TE8g85QMM!fPmgtEhWj{)pNB!nLW?UyAZ<8o9nUax0{>~(KHwXoX+QK18R#Z zoXCvrPg2qSCbc$%_w}-1u9(L^-cRgBqHhxl&Y|L$Gwy%608*$e?mByzb?t=U{8|F~ zSLs#GW1#Y?((L0K>fF`NiR;c$p(e5hV^aS4MvzITpMl~5%*C&6dOm7d&c5z=%I)tK z1m7$-0srK6X;_4=wxqtIw%9p>LzB+*R>lEnA-C1V>52ETO~UzDxN(}PA+^N$<1&tC zi;t_8L7k`)dkGh228tTzk0CdsRKtZmjV}iddV3b4@mSxrIIVlbLTxP;?TyYqir=KN z-2+&woCx%8^Tg7t9C}`ZLZZgjNeghf?T>~FVnp$J3tpgM&b5oitxbi6j%z7qlDkCt zfljw@iA1@yuYJHoeY0^d8zsE`yDIPU-Je(5+cWBRa=RsRv5W4l zd_yBFTsfkGNIv6EF*J&+a8VzVFdW~R@784CP?;X%zDi_PkgPeRn94|HSyd`N%a6eW z9F4y#OG)5%a4cKde>+vXSHzuEZjeSN&9OQ4vpR_S^jBYJK+s-|4cTAY$|O!8sx`-B z7~kR9I_F=VE_J5|8p=4A!N9PgK>s}Uj|b``DhB~}95jJ4fTX8|Drs% z-K(M+)aeh*K0iNG+hUoOESU_v(Yo5uuBAfl`chHK}qs9d|GZI_>| zhe`d_$Qku|kUy~KsN+HiuArpadT;>(;*=?f*yat!*?SO6XC@| zvOwUHtdSrwV`DEfHFfqG3%D{L;}0cs_Z%J4m3~V_g%(68g%yA` zmZEM={$o69X7FC~WY*x6@0kW`Yg4#UZ7%0E#u1Czj`nD|$EP#p4<&?MQ)0T4 zOkAgQ(@@-ue)AOul@^AD)XSytnk3(Q7QcWjZvj#i2~=eLv(l9ST<+72X6>RU2_rP9 z!}-}ojrj&zD-UO9j(J`4?{cC&DG7!lrPByg6JvW1v+en}-#V5Tr_KZ=$lT4JK}w6` zY-`8_9IY*7apbOd4+2WpEQ$dK+%gogpP&Oq6u^3#2|`+XPW=g`jFX&y9?u@a^MN&L zEx%A4VbjFp^6>?teXMG zsT|wgGP$>hnc2Eo?T*nL?`yuq`Numzm&m=_u84(B(gX_kqk#-#zXi5sI~CgC7CRGy{Q##xpTgFym` z1hFyFHK*4?rGlB#vrN`iC{8!q%U2{CFy$Iv^+-B1o}r%K?H64?WvhcWz0fK}=d_fy zdha=-goU&w=N=hEU_X6%cpDTQc*T8jd~-Fn(HZAS)0E{Pv(Y2AOwi;sc9`MqMTVCz z$WGt>r^H6a=d2IsLNR`K*+A~Gt7~g$$n!StL+CF*#%QG0`%O84$88SlOVQszv+(eZ zHs|*nLSzER=}_j$Ou?Yt-Q6*7XCot#fy%Cq?DLMpR=hYD+jBgiIQgJ@+g_rQT;1ff zUQm*wt^vPFb!rABU?US3EJ!L^h8IY5TM`vxuE7E$s|j_j-8wKXYhpbih`^f!?S>W>qv7 z%jQy+%b_)0uLSMa^s0pC%a3QANV47bhGQCWn=j=v63oWHP=f3};`IV31bEBj=*VxI zC~=O}ApMz!#i|sM)a;!x4J7z&5;H4Z6vE(wJ>llpL}51d$pudq49yx&4^s2Qp6MHx z^{5j{6qu-Mrn4Ho+#X|vVb>`XASz}!ByQ&V{*8@4H3YKQ98WaXaWt$*-?fWLSe2K?>tSPpZx-Vz;S z=rC_O31QtL;JEtDw2~$ZQIL>HUaa>{)c|RpV#XC#z2G&n=r+oQoic?ee5_xWF8dE-%5cg4ID=x}2u+qlx!Ow$_SzifLm!GN{f5 z3sXiI6iJldw_rC8whZvTY=^8$i-WXe-ye}|*NCYbwDI6lUSVPU1z z;Lt6*0U}*P~JlsECcIQJ=0eHzQf}N-I~yY-kSb{t(M#av|>iMqcGEj*MYz7VkCF zN@6M9hmFTuo(JDciuWJWqE=BwNOyfEstK}8HFjB`OGk!@0Zyz(|G5#Yu5IRK7==uy z*z#%1)GkO?U3D!|)p1vh7&OKxN)hz&1UDt#DIiY6v9r&XgpI-#Vu~`g_tu+2y4lRv z!iX|+x|-JQ_@{+-`nZR~4%CFY;HpxoRZjTat0Sd4PN&{xxmVPMcYn$g7<;GngsDVcvC^oMdtrGQ;?yxxACxKkx@BS#7$rtUv9 zKhx_fxci|#z&Yskd|Oqq9zE;#$puF)hPNd-7YGM9O(JN1AWfw02A}wx7%mpTh>hMS zd{K4J(jCLsO{j*%>S~~PKBzP%`PrIw8kVyCIH*>ECC@;wPhUl|CaVLesbeuFk5|8ap4JO} zI!#)s`NES?d$J$aw)vU70TS;%$;xo6Q3%qhcgff9$p!aIR8N>;1V%$5f& z3C9xAaA3^BHk!4kyUAk-hK@(y*S7B}rWgc2vho>VnAJ|HrkEH&_Gr7MyFWY1!$(@1 zE@b)yf9;s$&#c?t zFHt5&&1EuK@(|f>efkerFl0au+Ue|`vJ9y5{kmM z1d`}z81Ol%9dr1jMo9~Z@~{!mDPDs&vd}08jYMPCfqsr&dY7$*M{)wAIDtNswBeSV zSk9M}j05auzNg}lU1N{vB(QZj06m(u(tsT47@!xtRXR4%k3o|IYV8VL)*WUGuvtlo z3OAV+hDv17j;jIFRwi11I?Ixi)juPz!Tqe(Czny|cRxKFZFCVb*W~rn3V>%R2#174 zfdpUyw<5n1f=E^EVzck@+Cc?G)_ibx{Fe)0g?)x-fC4!_!p><^#5{Yy!OTHW<#p3k zR_ZKrF0jcEke%$;d`59BZT&R?WvogWTaIvxZiJ6cENZ(2Gn5l){PMWF0%#IAXwGmf zNJi|Y7w+b0a+gtRY(TTKzc%r8{A)+$T_!@yC^8T-a5A=5@%4Uc0`$r87H|@bDw)yA zPvnv`^3=4pfApFHwAy`jVh1o+)kv+hkgaZ*bFf5n6n=?FVZY7b$<(70Hy=dF1i`e> zsTn|Z920had^%tSQLVm^5cSQT{A1WpQ+-NxgLLym`euR+t4}w{MeE(}k7KB^OO!kt zzB;LDyU3-u=)JxUJ*jS`&{`eZ2xNl^DgK0(ZM#K|BL!5$JC`j*`#@{imo+aWuK!RrLIl}w!2t)n$Nf0-xPG$RazC?fK7f!1UVx_Yz zy&{@Y2dM@zbw+f!xVX|0g``G&ZlsO^-!NB_H~2;01>fi9eGL>8su`{Hy)#R5fsHH#)xUNCVPepe?@E z@>;Dy8Ob=z~tEw&A&qP-EZ>4drgT?LU$g^r-$utN(6ZGdmNy%~p zb5v5iFD`zE{4--dIy^ATXb`XAGChcCh@)Cn!>G)Xz9BBNVNz)w_)0iojEz~P04O1B7Q)DggwJr9zrn!)QI%&VE9 zDgMGFp6w*k7Q0A4ity%Ev0 z@2mQV)Ziyy&+8e)wa*tlZ#(C_v&&-1`WA%^|F|q+>JzH_Xy|!7UVi#;JSC23X_aVi z7S25XvOKuQw^(}bHl()P>P&#wY_gPM<4K&%Egbxnw56E8L+f^orb!WPDDVV3Y9ajX z>!|+ea_8K>+y7*v*vlWEvAoTLoBV)_&(D=iC%2o0hNCUJez6KdD5NXWvkI9b|HcOc6VH`E(_~c~qO|DCR_clj z8*`3_NXN5d8I8C$Kra)EmmmBL*>S(HRW;A{)I`Hq=gU@aFjJZgu_~Omnod6qVd}iF zuy|UwIsl8*e^+jCwyDBtXNqtzyZF86XZ$x@X-gWzA351SuDR+2BC>7Bz>egdu8zk5_y-qOPjtR56usO^TC-~h7S)&kk;!oq* z$!m^9p2`ipB_i((3REAdY;c}-c^4@ExnL~gBGF)cQtPBo--Tk{-w(xbgMs-pNk6k~ zdxBEZgG*0W8~5ha3GtnmU7tPPS3b=9eqg5}!&VM4ofmZGd4CeTFE>BCO4^ox)q3vN zPja|SZxj1?T+%ChpCuj9wO`it_WJW}yb-ne+JY=SCg9>fRU4Ixjr>>$y*ipyF3bD$ zy?8z_gdjaRlF`g|)T&vo2r`f@aKCmayZyt@<1>aPI=GW8oe(2P6J$nWg=%c_ zdV!X79?#~nnJqL3==qGYyVA0I$R+xA`}Lq0>+purC+7DPD^FKsnqG+{AVSg&X8FiA z&^b`}dBzk5M7>NL3QivsLj48y_i1sRnrn1tT?t9fBPOkJ6Gp&!mjqg8-JFeX$Bnc4jOI#f4H!Yv;e)Or|zJDTFAq zQihv=2WdO&-^VV2lQ^uJcxUba<)}RlIQJ z$NRM;9{1bVi@g{I)#ysiChnJ0w64ybW;tFvt|X~e$CgiumOpG~H_UQ1izWHHw);_* zPwM+(`T2~t+woms#6TS!lk_=8V*F{oxnG;! z9nLEyg&%zKUkU_)gThv@L$hP&FjE%484ywv(nbbFUk5xIR0K@p&e@lDuX<{UlksAj zC4UId`h?>5n4Iv%PrC$wO~s*5_rwtuJPxI{@u-dIp8)!P8N~1o3zk-nc>K*9+**&Y zznNvY2%d3)U|&4wxKEv4k8~v@eT%t+4{Hf69P%M{Ac9-34jsZW$7^H%y3fQb5+j`H zOop(it^b*CMU4amG?vQH=+71#e}>K`KJT?<#KP=md#|6R#aU}lQJNYYmaOOQ74*m? zXXez|LttY8?OuMC%d!B8j3h;>#%g<)FB@XXh@K~=CQ-mFPr8`IKojliHKse(+o>w$ z3_l0H8C5dr(S@N}!!}L75q(BX-)g=w8l~w;SdErZxq<5!qXN^%!ILQ^zj(<=5{3zY zfKA{XfBH{LVr;f?KbJH;D4{V?Z&D~)Wfsj;yMz=#h73emV0y}n>%1KWV^v7{^Y$A% ztCE75`wf%(w+kQ)PZnDa)P#dZa;Z_e?4h0^zVYscUSJYhXRO-H=z?v0>*n>fx5xmQ zr4bvIEXE<4v()R$>2f&gmv}qMCS0eyu1Y zN`|z>CO0dIv_{QU@y3Bm@XGgh>%4h=v5?nE$j*ZuPfRU{?1xQ z!S?$W+uN?O-6bqcbl)adpI7z8(1rb$m%6F-Yy<)^TiCu&Fn+Wq3@#>9Z$*s}4U>r8 zG(F5qGN zu#zYt=b{QmxwWTxatFO>-7HPz0JK_t&Yvu}3x{8JG8$P998<8Sz^!Ic2AOK+|0y&i zM(mWq9B%4c^cZy@r>rPi;_awF6Yu!F_R^4l1}0IP!tOq1yB$-qy-b1eT%j4DghRMC zrB~(j1|SpWRD`;cifKEx#cLZdH6z93r-C?yj%<9Zc1gwJ^-Y^i@>-T`iLRC@dTQ!F z#Z#8$d6tfzhXLv5gn`pv(k3X*nW8l1b%3a-7~W^dw>)J%d_jGvjF^CUqJNlmG687< z9PMr1mcjWlmqKpHV%8cPiW!~XB0tn0!Sn4g)lRZi4>xibRLruLf;H?PuS^>_6+KR% zcO2eU2l`?}4j@{T?2oE9C|2;jDM#t$xehD8CR}gCR+o{Cv!e2?%*_C<;r3qkBI)F30pi&(_C;CSP^#6jScb&Z zZhHFck8$j5uhPlS)|3W*z%Eqn;+;#R+50qIUOng$02?iol~$S-w&_a<8sx2z6OO z+}f>6n0n?tA8xnX!9XmasuJrIS&vwL!o)*EksvFC#4}@8 zQIbv}F!zcp*qS2(JKA#{W1*Egl)dU@3$Wl-(8zO;-B2QR6fM2FrQD<+n0@}eDkuX# zrPFc2rI^xe%`Zae(K2kOmWRJm><-j3j5#C| z9h|005ldky;!y1UWM<}E7BvZU@h6#i7!*$Wx-V>n)=wrQ(J^xSHH7f~%%%M6KWh4X zh#)|>v2kOaY@i;q1)W8Xw3Hk|YqQV4-WpX!up zkR`DFkgmVVgtUx0SA#`^eVJXyQas!!su zW)Ps^ToxquA0%6KAfp*-tm2b6tIY^D(i<}Vr5{sxd3=>dSI{-RURTRT431?s=L z@Qp^&7z-cJFK#70d@in?=OK7_dIR?81)25muHQGFvuVRmA3Y2#*Fi5|J*u(n-aHxT zhewP;a0})JF=H;US&5awwowR_>%mp$6W&7g*<*QDp2k98HMuX&xkXi zOPY6Z^TS`l_{Sw1KY#><0&0vph8Ou~fI}kQn}CQ1NXdRsD)0!fi8<~9(emVi{atg? zddwP@H%}k!>{JX)6;>sQHzyc6yF)Or4TjoE_cC?*K|foa;Svd+EN>R=Iurle_p3DQ z;ZQ0HZE=Oz>Tgt%wjMO>b%`XQ$N9fu#Kx$QD_V8x)fvDH&&v$N;bUvU9P7XuQr9d5NX(ITFgJcXk2Qf84Z!XooNWVkN))j9@>9*&`Fm3t+vB>FUZlukxtBP*n_CsgZ3-lp;|s%zs4nd(f$8E zZ?YCFSycK3z<0pHI@xXLdeUTlb|8IOy6!Q5CWP+qeDKAvwCGE^4GeD%ob(v~M8Au= zFyo5|USes{26}spZ+5(OFzU-di3tCqRuIT$ic~WBNT&(T?NyBtlqqT zG!qNp&BEsXQR_cHe+~~Sn96Vffb|`tgor-6awwq5wGFrVHz3+2nY0l4jIkB*8OsxD(h$jPcG)_BaxpjG|MP z>$9gaaVYT`ya}D4xx9^!T8Kw0N}xP_eSNjHY5u>ght1A3(A_#zTUS7tp`oFt zARjdwO-V#q#58!>b#mXSp{IwlE}z*uwd<1kuNKHAWm8`FT_8TEENA;`dRu})UV6tO zY5}j_Crqf;-ONuHOA*{VxW1Ka_guJil6l~iob`Y{ zsoC+MF@X@-C3<@v=XltK8|j*-V}u^mWSLl705^n0!|*IwYGVnuxvl3US=4~JC)x;L z&yJo>1f3#AO-&=!?L0GW8J>{*zphtS2%V<0rIzv5D1>KPGDF3xnhH8bnycn7IKRB! z;^JZpe|Z(DmS%PiE)FbAx4xbDY(b+wO(nIBjRoN*t_sM|qv5{~mbY;T6mXmj;_?bh z?qbK>DkfYBY`^zVcDg$uiMzr~nRRP4UxG+IgCI)+?ToR%Lu*LbM`GZmqC8!0^e^FP z_|Z4EM!JTYgDbaL3)TA|4=8rdhZMEIak0Q21C7(;77if$9WssHy{Pm!o4@b*!t4QK z<%W-Z#7e6NIsy_W{nr1~gtDOkGeC>>r&i!w>AH;UO$Qz{Y&Qc z^<{?sDy4U`vHwQy!HSUv$$HuDGh>EjFv zHu{IBrgYHmsm2)c5Hu8@Hy%z@(ojjz$t)Z(-f+7WqEe6`I$fc7=3lmS zg&~Z@*(RkNV7tG+hBkLCE?pH7<^y}6!q>Q@LoRhgcEIt5)HZW0sdR z-f2wHCkhIfC=Q7ximsuPXHoYb4B4?FIXM?c3QuvXNiVkXeXc1Rn!{K8%U3K(Xz72n zds0&=S})$!Pxb5;Th_48_PgVVPtk>N&1{6|W;*&3ZndkIuh3tt2ZPa&&XVx%iTk5+ ziqP!tE8B}G<#5+ubrytbxwIyH@-X)yuoQScrcc@UDratR{fgz~mT=nGIXV^o_$adR z@qR|?tl~F1QF;hL)M|HJue++LsIa!TIa{tX)Yi5J0Q5~wRk;aD^H!Gpo&PgOz<4RF zFnCdK!bN#rUp?ymp|d@Pd|ls7C?|l?x^0l6Isc9?%JhrmZpI zW!h|I=+Pr(n>s4HyE!MKXA4$+yiCTaG)RBGGxT}8zn?g~ z20`iufLn*)_XQ$FUjt*p8kEpCBgK@YiblN~^1ZE%t8cK;KS{PNACbf#!n1Hd`?GHa znY3kBLdM144tE$u08Wk|dk^Glhr^186TwXq%^_UsSkY9U`$;|dGIdUa@jzHmP=8@z ze^OE*DrH|Vc;0mQfBz*I*5H1#2qBVGfAZQ&vy+RMShsJNg2tpB9cuUyx3vUYPIF~s z-R6lIptvlgc^KiR3d%{b5?ow}fi7)HU%U#7AaVLEK@huRL?T`gXEyw~8GNdq+X16D zov!tPKsB?cu_GxbpY6?kymPQBJK4bOESx#R+@vFc)i6cLeN+FeFzIyU;h-nJHI0K> z+x!Rd(^vo(&Hpwopm>*+5kzVsJE(awDd)j||G{ufnM$}dtL zu=$GE4v~|p)8$LK#v^(jh~!UTq-hU$_T(+V=rl_NBZTXM4R3(5(jCm*nrVj&e6@!| zs2~ju0vS4gJE1m7#F%>xx=E7RWhi7M*?1a#CI(=W|EJYZj&%hsg;kT0n~o9Vl%t-+ z!eSjAkUV_3woNjaCg%#Z$Ty1Qtol#{{0{<149@f&r#3IYG@fdM$@&NgqV_`xtEf*` z^zi4{j(&4e7z|LU;tNJzqbB1t!ncCOM?{eDI9WASj=BV)-|t|SQKjzFpw3kw4Nf*1 zkK3p7bHDV_)NUtNA%go0ZUQ}>}tXvT=g9o3u)=y5GxsO z|Gvg@KK>2ed#dNuc2f6Md?2)@hb(7MoaeSYIiY)*+cn~VwsZyDU zmXH(!H|jlXTFOW5X50t1Z6XSF#7P-1iA*5B&|b}@C?QV=(5;>J-1w#`FeC0rVzz*@ zinRG{w;HVs@tXPO4n_gvPa3x}p-(nh`HaCi=K}<%)FLc1YcK)9o zR2cH7TiJ7m4usnPW|{+~O?YQcW_sLX5{cr23=AofKUIwo)6Wi3OaA^>k8ovLqRTaW zaT^zUU29}mn*ng5T5vvlZk?Z$mU9VN^&vp;kiZ>jX5It`jm!u*a}DLZgO=T*i!dgi z{*1eR;yaVZxlv4OcvEfE2I++IB;<7NUg&BXN9pv)-kD9Vm*;N6&fNzn)Wgg*u!8uq zB8?)X*XUN*pC{G3^6^PK-0ZSzPMkWnzdREE)ApI2n*KyP!l{0HkJj{RA|u4Mo(_td zKYUIrj#?{T7FcZSR>+z*196dLSda!ATpI`u{kWhs*zb%)1bW+T?cnl=86Aw(jTTX~ zFJ^HA*C_wqkQv;*F%{M^54_j zQ5dKW)5$ZV4^x)D!3B4>0Bhee|CGb6y$G(*Wf7n+Zo(xqR2!C?urEAnJ*7-O8HlWx zqgIzsE`@@4eGw*+b@NyJ?SLG7jdUZtTlckD|Wr&dg zQNOQ74q!7A$kCvjT7QqArj5rx(#VjA@J>ZSX$K#?8OdjXqiqSKj}M-*cRc3IaP=`K zu%cFgB{ERnGHD@Y9(Q`?>U|TXvUc7R{t*XB3ag2ntl{2s0rdROV!R}_Ny`C;>ns%re_H^1(rIw30-kNUhOJct?ne+u0uz4I!8V@84X5hYRMf4_;I1KS z3LUGhA_2llvDOdm*xFNqyBb3Rp1>WBR7)TJPYb9jAFZF@1Ok|+MDYsu(muFjhzOD& z{}!Ua7xG_HdoQ9d#s_N|tRj~HK?o4`VPz`LIQ&%Zr;9MJjDY4qinp^>Uk-XX4&VyZ z0yR1Ne>3ug&v%6Z`NgY9b#zLoBW8aJ=hX}UcvYlT(mR)|v3f zc~%TLSi9c-)3F4?I3BSf3ov&;dr-JR@cXZ>G=g=xwD~RqCcI5sSQNFBeWEEFc@oq} zU^czC5$~V-7I^d)DxCp)BPztqE!or1H$PZOXQ*({lbhEc3I>pQ)ttE)SF%A-hkVH~ zUAVs4jvoC0UP8UKj};a+x;n+2?4#pi+{;S7}ErEQ-I0?Mwk=7n^#bBSM<&MGp5|zf*a* z_VcaAdYAHk!S4kY$+?R#spr_ifL24;5UQYHd;w7cZe$8?W24Bmzm3GOC?bVI#fEyq z{Ox0@jXRO>ZP*d7HPJ}k7s%(-7cj<%lf_Sd0y`w5^EVPwUP19juUZs+P9zTO;VgJR zp5CS&)c-TQ37p(F&3~05V=2C#moYq&?c~C$h%VDsqtFGYL5k zl4pxH3s_^^wkdLIb3t)^a~ZfMTw}=v$C_fm^pJfIlb=KON=obIM<9-0)$f)ChfJC4 z#Gn;wn~=?2uhIIrXKh{->qy3t+^t~)*`n%J)!RAWrZP7w45OvMfl}2Tu)(Eg z;;9O`#-T#NjXLc#stXhwJK851Zj?wqMkj3{%$n<5e}psP&ep2d9z%w@kko}B_pa?5 z?wq#gs&hWzP6&N+`@;Eywzbp&jrm_G&pP~=$aTa6%LcM!23EnYtw9%)QZgJs%&Ur_ zAmu?^Zo+J_%bn1$ja*=6g}n6#fIc6gcGV5p5|~ZHlg!>}tm*|o`DuZYuTSb41ZiC( zXtFVUCr)_ep`}k7N*8XIqgPv^8?}#ApvXVPEnjJ%1Ie>AW@nguVI)p4&NYv z5Oa_x3`)dnfr5nmXGQHG#W+N1WSS&By7tl|L^p*#Q=?))Q|@XqkE?kAMQgTfBD9-< zvKl*kDEs+IbfC1V5#I?5R%EH>{^)P1$O}Dj5X^>d^qTTeFN_`T!QR?hX-@IaIqP|g zZ8DRNI99jYrE{*;t5Ju6DV~*QqH4b(qJQk%FD(`42``48T&jsuuS*-egw4mb4fj_+ znq|r~lq_3!AV#0Z_M!`mz}|d*jwT(xbdThDi>#+f`?%gu=HqmdGs|V?tr=A1sfc=> zmJdSr<#R=-G{{uCJA=DR*&H4uH$^P>vgBy9vIS9&>DBg_NK@Exucs9w`MTlRhf45A zb+YawOxrNiRZnPHycO_P>jZXj28jznnS!?k+25Pdg*0O7+6#>9j*|UDn)e#=O_`KY z)n$g=h=oZyUm%Dou*k}VF{Yg>_*cv*uuCmTzGSUf6UZFPG~=GE7)71}7)&vvL}HIi zmc6r8SfZQejvBX=y6|e5i%3z6RLO+*9&w)T*?m2%6`cexF+00m^){F{Rbc9MSp7|% zC)>k2`*E;#vZ_k2;;WbJGEwZ#oyLMBJsUlkZlPW$Xs%V65tU6yLzQAnRd^d|>UHV` z%~*F3lNd*Np-)R|uIMKe{pK!}Eb69DraYctCf6}8J}x%jp4`l{kp|_Z?CGs_P5$pl zq}2A;ly1$%t!aNsT8oeS;2$hQwXJ`J2K}$^j8ReaT$l^&P4Cg^2L5CTZ!ifiDuU4g zi^s`UG%@!T>bd3umftju$8g({=#AdpImWq8kyQdy)oF~eP;FacD56r}wExg6OOm1y zP>k{K1tR$o;6<3vkJ{egh44S7k2~$@ch2tnyjKAfEOjTZ%`Uv5*3HARVc<*JcG%^ zGnHK`p^6=WGLO;-s|^$7Dgx?49@RZjE6WMKCTO!}mlMt^t0_Mh(ZH)7)muy$G|^Vd zbY`u1Ed88}yQwAni`|%NDYEuJ_$;s-h6@VCZZio@dG>R8by}gVPQN=X3)WEK|2kic?Ft%i>4O zdF&NRt)v^P>{MySU|v}1A;AJP2D)>PP6gs#d%fg=rGkJM#p=!%yr#;=p4G@l)Xs5| z$l57775jL!q`~l+%_IVoDumSos#e8lMpIJ?)9+DLpBd!oHKxzSCFgs(D0Xyf$>fjm zqdgo>t?OkH$+lWDl0)jjHu9=paTt})6)k2Q%da}!qby}MTwQZ1q|Dj~&>FWX91zc& zs^Z$y%Ld8Zf&ePw?GiBC7JVJIn2}Q^toV_fDg&9$QD@sl8==3*$V3EVUFx9Y895B1 zx-}G>NNFa6xo&Eu=G0ugX>NMdv5#FSh@e}9|)o5nRYBdxu?HGKGhjZUIV%jB@#q&;tf8r9C;hk*97U{6fusckD*;{jz( zZwU#kmLJIz1Dz#$vhkbW3qmxLt-I$U8Xhyt_3Bf=IP;UaWXw83XS<4ls1tR zCz%~ZW;TDO^Yt3*uGce6+7A(cNmK19FKEg7n_btwlrBC@Qhvk7AQotFx-DxbW!ZV= zV&}XGoxP9lyThTC>PWHe71}9V2%9bw!22+T`rocEprlAe^-MszMJqFINcS%z`{_^3 zWn8&KT_YZop!0~v(Hgv6PU}!t3{Blg>Al?I!m`yIVdWt-%yNPDi+dVRU=g9@N32BG-Y1Z zn1y-YzMQrcTPln2saj{y_WoMDs_5 z4i5Pe<)Ka|hY5;}@2wP^Xc-e#V}mCI}HjeL&9F-yiBS0{nvyB5A%{5LyA#RG`?rn0T!-rJgpM z@!XZq9-W>NMkK6*$e-R)HL`AaFw?vSslu5w!ZtjM9^+E$Uc5Q%MFucYsHmgiBdudB zMNyn$E$yMtUtihO9xOd3;%5Oj6+E0dt>a@>&Vp};evoO=ciEwn)%IlFIw%qu&%sVH z!MRx7R+@oxg}5FYd)wlIwk5irY``JU-C`=Cj8}yoEn$aml8unnnz+dsKgBs_#Vf$g z?lCIX{~4pZ!NhxYQrashf%|*o-2r|wd+Hit(&snrPkX=lPeln7KHyhr z+^-Ut6VJ`iS?lv*)KdII1j{nwGYKv{kHHW}0Q{L?4np0zw*7VftG&;FG2dY0V-};B zEa(JFs@SHYa_bTp%0`TdEr|Q(o?&wA&3fvW1?eL?YVZXVxBFUkaAO57zgh zWa^~Ki3^fr7oLNxvpSLb(~bo@a<8%D`;bmXjjcbXEZEz6Ke|)4=#yBUUMZm#I?};6 zI9UMXotINF8Vnfc-&-do2JG=esPc$=p5i^Wb2oawrg~kwIYf;XO?;LYC*8lQUgP|u z6a_Kg9`vgO)@ggkn1X?wy}IQ9o4XFAEYD-)s3K%y>~AnwjJlCvG{Gk*BrHPFlF;7p zWBhLR27*Yo(;b+a>M)x0YWv2A)Q?Oi4g#B<^9U0;<4SiIqiCSS0>m8w$We;XH+AYd zYF=lPD->DL_V(RWi^q%x=+<>IxA$K;e>LQ8U*T1L{0;*h&ZHqT4D5~wk)l=5B~E3w zCt;0tRg<`jEz=81ix^uFy7Z#!bT&>8MfEI#mQn(Uvx47cc$=7x<#`62S&^3N`&lYp z1KJ6U+@+WY&0fP8+*1!J8YXqcfREi5tZ-@Q0;OKt@>u-(Eh}ft85>QdxU0pur|mYA zxMqg-iSmM3_kFUbt{vDkVRI^8HT5KuM+yI??zRuJ5u|(;I?dhHm|9GKbFnf~Gjj(>ap@f9}d=zhc zgQ>56``cRccEzupA<{FyWQ57Um@;)06M45Jg3v=1umCwxJ)UL%4^R2PexD7Hwu@nJ ztWQo4ok4d8LOOmfyw^|IQ_HT~a4;l@*e|mlfQJ=Xp?a>LS`{RbNJQ(3?s|jqpOgSy@EfjCojFX&vYI*(hK6*7Pl_>Ho{jv zq*45!ql#pkJrmuekCz84Nnm;VQ7P@pi5dg z!vEb6K365AYE8>vonRg{pvZ$P3g<{rQ6SIHjkCaFSuJ-i2fM7cNb-a)IxxdG4MNwQ zb>CmE{=PqInr!<@dBBfxS0{6jj%tOIB2yH+4NDoym%RG?bU-E1rlttfj3Z|fVp>8+ z+V*hSB6l}E9Ht8$mUck}3`o0>B>&BVSf@;U-~WCi3f|1ICu;#uWk~S(@tEC}T{5q1l9`6`nBB=X`@xY0zq9J#oK59+yIR$Bp4`+$ul)+1nUQFXJUomn+d<{UX= zpJc!$vpQw;0l_qg8xhLZcc;UA9v8k&)4TVvGVAps&W$%_f4S>R&da{I?#wH(F=FwRM977OamROU4< zW{3e{^vz;ioSiG*kr1o(Le6bt^+M3)VK*ujd97Ab~}Six;k2S6gu%|*D` z+0dNpsYUgjrq&|KH%x*jBXmGc}(|Pe{gk`INO+)BX^> zMS`L2r5a1E4k@uI;1?q2X|or?34_e|ceL)soH#v`yuzjRf}CyZpYgX_+7F`%(?O?K z)P4kRoQc1-o8RO9@MB+2*RC#bBVYNEUS4JGQ6WRimZxAG)GzB&1v)gDqP zXxRf~$ak+2lVl^tO^)ZX7F=7DrC*Uq8MSDwL8N4tiK$3PF~{_PhN9fdC?tH`uSG)9 zAq&0EJo}_t^I!A5*4_U5I?1#MhJ-zx zp+#WYeSry(ByBnLS`S;^LoBQwP*!dWe%>XqBV7+I+z^(kQHuYldq^W%G#ArHDGvuL zr9K+MUMMcxsfx$rNT>;2JOYV{le38P;s>-C@)cEz2}&ZC(978zBoQZw|p|~lZd*N>6Er-JO(bGGnd2) zget3TtsHqApL4t6638OV5!WwgT>FHn>0f+1X+z$0^yRBr;9285lNd~cM?Jq8A5zI{ z$H{~0##|y4w?{5qMx$fi9OI04q<|__Fmp<=4JQjGH(v`Yovk_xd^1bn3;M@Wbh+CEQtRp+itcS=cj?%z>U?Qb4TN5{Go zk88we&`ZKK3%xfs#R`xdyL$<_>-b*^2e=Zqmeh35_V1M zbm&g_yP18CQ8<#xhH2dDYQlFS0$3;-4@W(ZrGtj>7_HY$JSb`G<|)KU+<`yq*VuS( z-)?FQ3a%E$WMu6w2?N@5RtUg#(eryT{DtXO zFR-UWfPd1GrlA#j1t*r8xB6kAoZP#_fnk)S%^%kp?0_=?$%SlXObd{5+m$6>&M^;_ zmhRP=c9NawP~%RVCo+;>^*DOU zVq*OrVr8A2>{~l~Dv_8--H=v-5s!}f(^z?!Zu|><&-ptgKU3q{@+wl6sqzmQhc~fy zhElcp2>g-0#oc;c!a6o^e(tN*D^^cOC7XSr=YQ?)(^oFo4D+e!pU2&8-S-#%*;+|) z;7>6H55e4y1kx^tGj50wagVskO}`i|a#L*Pnn&LZy)(sDcV*mg_Nm6@QKx0VNW`q{ z$tX9WON9C%j#?_Bh6xFpk0VHyCPykwQ&AuCuW`Ia!DrgKw^Ref&Da!3uG6wT#S$OuJ4t{)q97gL@@{8>`tV0m0p63$B70N*`5dVMJ138V~nT&->ZcHP+X4 zWVoUCvsj0$DHpY$`?HwZ{lT~czt1&c@`Z4~fiMB)N^_RV=53&u)25%Ks#d0@BrKxI zI6dmTpo#kFQnugJ-<#m=z^@kecbRdPC#TRk{bp~O1svz_$cK|LVj0^A5tKLNf^Y&b z-}Q5SQIl_ItPifTiOsDn*ixA_U~~mF@&|U>?88zpQpm;Z1cdY?eBG)akfmw8=D3Ya zo2Vl`32r14w}>0cI#-eQPc0u(X9A*cIYW0k_38RWtfrw@=*5%9#?(Ts)goRGsm|uo z@j8N$na+a52j?cs5nTsD&a`c*8%{m0VLt$US(TbH(wiW}~fddN@zi2TF8 zP)WY0S4gV|atI+y5CZ!cCZ$&gKq?!>kA&DPfkxl*nroN~(O+J6_z+;QIJ3;~P>V>m z+LUfOb{lm~_)!W~oj1NDB*7b7=A+;VP3l+}gJ|a3;?+oz52^S`>)~U`KE*m>AFJB$ z2sDe#RJP8^-wwcz1kmQJ4JQut$p<-)Iq<|Rs8@0%DoT)W%>i{LhVAb%_(V>ZW+Cc~ z!V6|Sm@NjaYg{RE)v0n~G!nJT={tgCw(SxzDW(#?SE*JmT8cL+TP>H0X6ZFUnz4U0~5&N3WcgNcTZzz{T+PObU9Tw65mAb+u*i&~o zlp1-$MLKH$#QY+i{3L-yRGE;T7Q6}aK9J03A=i+?ouLOLHVh4MB`Z0b2~uEm918zY z1=m@{&o-dEA}|etheW)}m*)Ay3s-}xxh7%~jFy7UrcY=lHZJh*yc$fr06KSr#&zZz z$YvNAPVW4R>?8n299qO|a~EpvlX>FCq>2HUBf}q|FOeRLs!{GEE221m8mT6dl+k+`tJ}n$@ zGmIj3C$JJ_?aoFn6z0L@-@+|R2QVo``awK3NKaPh!Wqn{sLzH}vx)en15*=Uro?wk zb|GZdUZfL|ZTrUr$oy$mfn!-F9j_fU&SyV-?*gRmZG~L-%-*o2EC$_#XY{L>yPpyE z+VSy=5u+xnr!hII4r9dC&E1J-h9ovzV7m7i#koW#wD6;-#7Pm35VR5zo=F~yYACYO&SJIL z`6{`H@?9U41CXl)?Qnw&V$Bzf&Fo4th?R=OVE6LO#q>-}Hk(uDuaunA~3d8KFXakNT>%=2sE)8E%>I3}aZ@8gA>*yCm^ zSHQb|vTfVzdD_3{`t!LA1(!G78kAc9T2xMmXW+Y7m!YSj!)p$dSgR#mcb^$R155a( z#T9+HtJD)mKp(7%sq6_BOA(&GLsoHL%&QeuiF+WmdDtS+hpBxz-jd`oZzqPP}X>Wb2 zWbf)W;Ee#fIo#ddB|pFgi5KCh_D{?{L^Sgc?ax|OS5#DhEb@H>`-*mCoXI*_EC|99 zI`GJs!>A@pvUm{f+X{)EAP#{Wg5A>THNP0YteP*M*9<90Y6WFiVy0xj%-sJQ&G_PP zv}DIH+>GV=dYchL5kY6U9ml<%ZqCN-yNolu>f6am&2nDsW|M3GjUAxhbTQ9AVFvj4nle2 zL3<%#z0SP2N3`N z7u_YN)lLA&c>Qoj9tL>@v+lg6R`5f{JxZ7@%?#udGRNt zkCh84LR>&ul`qRo-DQuBPT#){(brjcKd)=NO}?0$bD-;YW< ze+jN>p5tl^Mc&<#Gy}Hwa4=qU>LM1im(g}ZU-Ve)h=~459ZZh<(0XtB%+-kZOnHBRf+<}FZh$x5q}M1 z4Hy|5m?K@p(2%o6fbYaNRJ$2+rr$;D{>JvzLU)Kp=lm!N>tqI?VhLW5to&<|2vRufIryxsNnH|KSl z_4+E|k#auFjQay9+m&mozK2Y8@8^d9J_b4*UR*XoXpx6D$6fReY;aywh`ztKRN0cD zsTQ7-reZv;=H%$_1~?{JmuMmAC<;z{$SKwUvrh4KX-OjQ6}09~yF=h14FMwSXhss> zv3l@^h?&_!RSWsjrfsC6nYI$L`ZL+*p}jknD{XLV2XAqKymKSNbO~_Kql{p$>0R`I zfA^t~b|31vF%`-^qj(?BGmCrHv!u6VvxAWHYNjYIli9zoU#OvBrIFCgR8>fmo~UlC z&EN3xt45a&i(XIkkxGvDDbvB=S{!M zzb}6jJ(tN8%N$qm5?Qaut8PmNj!g+%49QF|UjD+wljA1A(P<_e@0E~{M3!OdpQv;N zyErL1VnSJu(w`qb45YZ83+1y9{8bu^$B&fy9Schf32K0#Z_c)d7mB2#Iciw?`=j72 z56_NH9@$bqImv0aWPf$J=WnXt;dcCo;s+Q zqlt_*pV!Jf121K2sy}99%ZrQNrVW35zjQeoFP`6JWo6@e&qf8iy%n;ati((qMSrIG zh}6*fz8>1?EcSjh%8K$73`M71ZpzMM+}n>xaJHDK#ojXA>b#$;p(^41^#V7K6T>`3 zX=?Xjj}R~A#}zU>4auXT8pLCXafYRUG@hj@uUZ z1pu`$?oP<#H(if6LC~JFaJKEE>3~C~`6Kx(WMZycp?`jIYvN{Og_OVJ_#X3(!*hL? zUVq(>l8=1HIwJOc2+3gEwm{oi_Vlyal$fs%vWN>-VP-5Jk%7)*z_s;)h&ZL{O^c)~ zwG%nrn`QqwKC0k<&*0B(euqo54uyNL^gl|IWpuTsP=p3zpBJ`dDe+-w#5y`MSziQ+QqKEiH7` zgf9v+K>=yhj+9jS4CgSW9si?OO*6NFMdUn`4jrP@z?9gxu#U1^KTamDUuP9mZgdRa zq58H;H?^$}8n4WcbKFz6kG;=Mv8}vR{-~6Y%PcN0FALosG?pwmTPGwt@g(D-7PotYt>Lb1M2f*Y zYip>VJ>%ehk$vGC$(6|$Vz?&xKg@cw6L8!yU%_2=Mr`^26MOUC9kM){`uEX}ZGfKq znp*N~VQsw%RFA#~seQJHSoB|qOtrW|#vdV(QX0}Lv)$DXU$9s0_fy`e`ST)|(0x{e z~y(UP;v>^CUEaqEhsC)UdLH+^3K#K( z_*)J-^rT_Z3<%)n&DE{v|nlc|4b)Gwg!FRNR*>5|VEQc!?_I@AL;87V?`a@lo z#JTM)<}cG_`h2ySge!*|?^l`0?*q~90^N7j+tQZG4Ts}pPx61<^m0jcTYWswd$;E1 z-1;4IVr->2YCf*3`>UqTn~dM|75z%|mPNR>?yHPDw?FpN#J(zj?Duc;+i^eExB&lo z4gI}z*!mb0J=F_6-g2KVE<~Cu{k6riEO6KKm1WqoZ&;<$!<3^3dTHj-HA{}EZgYe` zE;2s5R)_Kozk&|XA~0zPOI!{5#ATzf?cN5QEB3AAwm$DOA2z*FJ|!JrY#FN$b2`-n zeo7}3^$$HWn#Mn;{T`Q*jRz^CVMzGLOj>rthRtokujh;7^?uh|zSjf$@j@2;F9X<& zdX1LT23Zd)CH2kC52NJB?@pg#p7+>f$y0OhPwUrtj{Qy;KL|w5KS0Hkk{Yf5bv4=j z)!>A*<@?SGM-CRRfl6Sf6~%fco-E1|ClNTfFCBqvqH+~HS`8aH-W?`R=LTo7XXRk! z9T)7f%*BF>C9sPb`GWYQ?X)X2&AqQDD>DK8gsrJ3KLC$W;wi?|b0GRw)DL3e_D`h|eSZRNSxg0eZCyI)CDN<}*{7(#&fscVn*A z{r9HI)^<$bvox*9ciNa&>$Ai2>Pps&hum{@gduaD*8B1S#B%F+Yq=JD?6VlNnV+g$ z;rjOyWJC3JfP!&*;osAPS#Y#D__rQ7ocH1AeHFomH0(b8`ffX(-lu;q1rYE)31Bgu z)ucNx4JYO)r`C8Ko5Nxk{|Pgz@VSe1dN|jGxF}!SKj8h1=Np4woYE8;q>ObJk=T#? z&}cL~-eM`{RxyKX-tOm;`xCzDl%O7gbBQ7Y$N2bH^xXP`rVccgiI&+T&B_)OzFR`6 zY@#Z!y^pKLlLoiywwKh0o#eTA^kJ^jvif|-(V0HacAh4|Pd!jz^8|g>kx)ye=aWNM z%mO+X{J&n0zYz;|wNq{=89FG$Q-a=qB?iKNp1vOZR#b+$y3lMo*7xX3-W>?%;A&e~ zUM?FKM5*3_GudtlO>A*8wJjGbS`<@D=Kq22-v?6$D%Op~HCTWL^qR>NpRFi{5eaaM z!u$beHMx2rgTR7CGVvLs96?zNiyEHibGqV(J?zl)`jkLgUbP6XW_sF zcFGEJ2-N*b^+L~TbLFC?C#EqRbs88qU3||(gpIq9;Q9=Iz7A{s$K1y8T+(z-3M=d{ z{5YKJ8NTJ+Zd1Ep{gUg5Wms{FTD|DIkUaH&T7cKLI%n8-Al9%>RE*!b0?k;6!OmF% zz|%ksdHv~co3+=s?;88QeFR8*c2b@DZ<}1HP_;JIj#0_EVp84rS22S; z7x|iaB2%~9UgzBnrjo8SG>O@rzuTtIUBem9DNpsVoP#ug%Ew~oaL5`uhoGwFv0{-U zER?JEgjC^)Q# zA9=Mp4ImhP?62QpYNeTCBSe8oVSh75;;Qq$G%INFf0t0d5alL|nJtbZd5?6v6%5kY zYxi<2-RJLnOJ{-~6VACjS6*kfNWr~N6Y_xpbl(nv&{?{`aAM73LfQClSWmcX-Y1HR zeC&1RBbi7t=n%e)oo0Flht-yb+tYcWoqhwW09A9AuOgET9G6`#T~kl75n{$M-yg`Q zSnC~o-RU%?XR(DuE#9ZYzJDyYoz(a}Jf?SQCGxK0T+co0iFd`kU5DP?ssXo24xp=_ zF;-Z_KHr5Hy@V^GI;$?qrkzZ9#aAVi(*sw?njEDz7W#h9-nCKElH6hOq$nd&sKih> zq2Q6fgACgPc?#^Vm@E)J4RSCY(*F6}-=RyuYl0Mn2)goAQPcAoOx!nk-`1_zA}oH~ z_!C~&{gs;b;6Ys?9a^yYw_7pd2e?PGA2Kq9IV~kU6wuyi^4~HTNZ6xebBb^zUgKMH z&W{SmxJ4`8!%qJcIcScy5!^OvDH)fS@B6oLt%2U49t8K-cX!u;qxuynH*a zyWGrj>nt>eMe@Gs>)r5s&%;;)|K-8Xu{fP|PxCuoz>gJa+ixFQuz#ykUrh`ixx;-c zTYHr4n*y*@fKzv{0Mn#pFC5KYACNm4`XlRfu4Me{^S!l<62_0s{j$7D zGEd`WH(Ea)cLDHT$@3VjFbq82;_`b5SUFnORCzs*o&0}Xy=7EfO|Uf#2~KdA;O;Jg z!QC}La0~7P*Wm6D+%32Thv4pRA-F>rbkO(Y$-UpY>-#@z%{iyLtEy}7+B+?VuWLw} z^!)Rp)8(Hrd!kqs*SjaY3vU-yJ^n8>eW=o3Hpep?lq=X|Rtx%SAWK_I(=p7P)!w@< zFQ)*iONfWF^E~NyJNrhekR$0 zFvBZ0_v7r%^J?MGMz2Atx#He9XKUAe?lYAB&i$f0GmC+st7C@lwJqvRGJv9UOOUv@ z*7JS*=}r9!VO>|&VIUgpjz>)8J4N^D(N+tGhoerG;i;&h?Fq%0b!;~lt+3ItN5CNP z3vx)`)>+D0M^;5wSI@=W-oe3wBV!YP5$)pq@}Yf|uGL*)BBmLPIiugbv7L*0Ve|Do ztwLOyie1yP#-G~W7l2dHF$Y!3U=k)72?PJR2qS?OT@rjvTR_LWOkA3&s?eV`bUsHh zBo&(?T|?KWot(=74S%Euu@gPqIV$rlnBa@0lJ1w0MXJ=%be_zg5l1WCXwS-s!$I>I zq7nKT>zXN9)fme3;AA>9naTMI>!a;ya#lf5{m}Znk-A^(|{Sw!;HMbd$N-w##i^ z=NT1^Sfl=?!ky@kM$t9i9*O_%ZxNOU2&M9K7WMP=9I}u{zJUxcYlsuUfx{6 z^Rl2{pBfn^8J<#HJ|B<>A3aqJGI?8@a|+;r+?r*KJ#wc$UYc^A;ifBf|MOa6Zf53MgVq!T8Mj>>NShzz$C7Z-E8XI1pAO!7otr}HfvFOI%H zj+RM+59`;P7K|Q)92VYDU9Wf_D@Zw0D^c(*a}lpbGDPp7v%hK7l0h@x=SNLEZXme7 zwTYVi(c;M*lti0r8m+AHyb^)RC2_y9*KO9@e$f>N70~!|O#Q1JRcYC3nA+na4K<}^ zb=kU`+SZXwRizOKnhH^1(;s}+l^K@f?`3~pf@Z;+gr(8>dMXYt)ja93JJAHbjlXi} zFj^i7IqdYh5xl(N%uVOK&Pkf;e)^-y%D@`j=AQFnGCZHelIyj-_}H~xDnX^_?QU!6 z(B{Tm^>=xNeLhdddn*auf%~)=1`EHeEnTRv<_yNM>NM|torBMH6gtM(058yf5-L;O zRRJ|w`%kWpUICctLjcLl8L7YG&Qptkmj+}+ysh9n4zjMN;fL10i|L(Or&^O@vFJvv zV*qY)H~g_zONKx}4$p&Pm8eMFL)CoaDW0z~MY7Rt_zc3^EP1!PcMwO&-KKRR+MlAUG5PzeRpLjk8~XuUN&Wj10Y5aRI!s(YAwq+Y*>CyAia#-Rsj| z&+QJ~F0BPKrl^IdgK@$ywN^WDipr`g+OFg5L%iJF23{+y&w%+anzak173ctX>C%kgfq82GIG2Dzsyira6G-_hh`)J=E6E*N=mA3=r zS0w-|M=A43Ic2d38mbEVN4APAbAiO8e6&C#%2hLl4G57wWSlC+=Jsr@t`KtsFsCV7 z@2<%hUGT0jI~J&WAG{*J|0qdxOcQ-U^n95O%f5FdrmX5XSO)E}1aDZihLN`8VA$k4 z3JJ?$Kizn(nuAM=Z{rn$oF5v#_v>jT^?44;;!xo6y&qpEch7d6yy@0<+Pvbn4Ls^QceDg;=p~hdHtn`YOZnT-m&c5uP@xj3MRRg>t3S+ zSc3(J`~1lB1YjKG*#p&wB;D2aDK`2?(=YAr7tuTW#kv(!{P`D98karIvnyJ@x}Gbr zzK<~9@tEvqA4mTN{#bORYVU-g^~v5ve{~K*qzqE&A0@S*&_I#AuCB@Z368YDg6-|i zm-E|#0+WxIW#uccE0yW1zeqsdb0(Ze!AXbJbCZG=fDWpSwXG|^sknI1=7lsWH8VcK z{K69XlJjzvE`7|O^EHRl^}1};`Nsx*5F$#W#u7<{u>qCzx1VDcV#}4%_rqrA%E#OEUD}M$JDAAn@bCaHQ$$7jG;Tg z?YiC|rs#F+3|3b<*Jpf+=2csMIV;C(lW1xZ-|a3$dgEd2%UuTreuCZ^`eq zKl}AX^usqg65Lc*hCy>3_Lr+UvmKCfi|;XFeLC}n;o~0*F1f43y|qbF9t1o6x?vCf zdTv=dk}of$(nqBRQ7V0jijPXCi*{NAv)_nc*Rmg3-Y++J&CSBqK+wE&LAy|g4azm0 zd+2wAbG_GDcRvm2lj@&h0gBg3vcsAF#TBxq_iYTzum169&~k$)fYzUdg??AST`>BhPdcY0?MQY-J1ulQa!X9nrBYR{HaUE zGt$h)8&@*lm&3PRrk)N)ZS0GP;mNnRL$20cjNBJUfQoJgOUxEN2S0Elo9_edLLhRa z*LSlZKV+2mUZZMKn8rObn2AbRj@FJVS~5rbnDMh!B}jzJbT|~wUn@_qu^joxo%z|W_gK+6VkEYWKo9-N4_s)@iam{iYJdP^u8m(xf9ZKoclX$$wzq* zDc~&ZVdB1Ee?GEn*egSQ7qO*TBhfF|F3S59D8hzst(e=VIz-I7w~oxf@Pm9qex62; z&0#WfZ%j=H`5!Q~LQK(=y=WkoJdi_k#(1jxE36*MyW+03Kiy|lr!>cn<_s2aaXW~h z&E+v0cFf%@)x_GqTn3^YVBOUr9cR$peKyq~1c|@9s0{_RxtB66+@1-X&doLJ$xZ#T z#zQX6c0yI0-6UzrED3Wq$msHp%W2+(q?ya(vFLP6U!Z0APC_=kZ(kmR003ko+u5rl zc*c?oHwIli1T_;*q!uo3gNwLd8~#+!?i}dfi6(#M#@svA^zovu{nYp)6o-;8{>O_d zZBfz(jz%=`2Wathr~nBvmRy$XcE{hhXK3~FiYW%L$`5;EsX)v|BXz6ou#e2kiTGxg z_1$+mNC@`thRWY7^^(C=kp+Uf4LeKo?T;>{nB%wY#tHGln#Yr2i-GqiD`4 z&!do1J!d0-JG->)#6^%O>H<#`p;Y;|_-a|Hgp9cQxX|JtbOKyynxFQrGDbI`5WuEy zO$_qj9er3d^K^r5y{Cr;sGH?ZJ=`}a3(2j#`5#P?YuCGb&5*8{&G=*NVpxLAG6=OI zm?|Se>Jmg7@nlmlQ${5)AQ~|jWR9RcJT}&TcI%xER(5}?22^NPH!lR9!Y>0w;u)^4 zkYoAX)J#na+nX$@dM7iTNk$hwM6VQ^cCAV=;qWJFOw{xhYQlu&8z^wSuQN~Gjdvu< zW^WgG+v5IlRe=H+`bFBFBsA5h8%ut@jIK_@biXcW;c-ahpLC?hWy`rX=V?)v8X(K^u^J_8xIiVvzJq~+T1CRA^+?A; zBLz+P1_2WHKH|QE|2+w(7gdZP_Nw6|-ytld4~d$#(8~;r-^8p1)AU`?JG^|| z#@Da8mI<1EUBsp(snLl= zj7I-b`Aob+`Nc1?G0mswA(X9CkBFib0`c#7&N2D&{0XJ$OOwC%Z<1n;6bLb=#vH=M zmy-{2uq9hEcs)H(yRbiDvQl;UgBKqNprPKAEbqZ)8Tmw_APAq}{M#YuAHqhXi4dwW z#8@P<4nowcO`yjdn?r3uG+9%b>mcrI`DztzULL=8YtI^kJtWDz&=j1tPZ^om+kJgH znEL_V;d&Lm2vX&Il-V%wP)5k>av5(0`Je*E#gFKxKfDW{P0G8r3V7!Xp8$N{(8OFG zod<*As(z)!BsK38gBsu!%ZDUxSfZEr{SaMwtSi{Jso{WZSVMy7p&L(DE- z-s?GfS$P=R@eMk00FT%x7rX}?P^-Yy9bBCame#f=7ok;Lr-b~6)1r&nEO#x*$__O( ze6&0mhmIo$V}@~~>)E_t#YaK2P%xr3ZZ$u;MC{6aImMFBv40Wvn z*0mrY7-DlL#LGtne^1;Ycp#KYSSRPVlN(AiogOW;hoi`U zJS59^0u4){X<4GFZr&EClB)0Ef@Un|K{RTDe3<>0iOu;cbRhmTQht ze~g1B(S)BI`!S@+&;X<|%V*z{vD={0b1p8UzEZjdsLXS(7Ah^NoUiL>s|>qK$hz}d z55haY=}iLq7$faB30C2k6csPFwJF5x65(H?#b?#2;IS%m&c9?>xCicw6K6c*4D>Nlx-deXb& z1G>3$3`6uuQ)S;*&rBLBE8$~)_`eF>)n}yTHrIG{tB=GD7I1;i={F4nmo-$F+9Dn?~X19LdP|pmbozW26#DoN4l|^C~Nu^k?v) z>&&*Yf}}}Sr|s>hc2D`_Z64Yvn8KC zK7XxgEnX?#ZRTo*k(1w0f0-D?Db4ZsBRKJK%l5ZzwbR z+7IYTKUZ#`(rymF07ly^`dk*?dy5&*k6c>FKhltZWNkEVyp!%S^ixz^5m1=P(dP2M z#n_3{`C%rsaSi|0bSSp;R0`NS8(GiP(XmGe2u9A|Hk$=;FCs4?{9;Yvzfgtyng=!3BI8Z%iqhJaJ-hLBq$=6h z0;`*;*Tu*Yw6P=9pJce6e){?|FrTRE>7A+x+1xIjR#YdV?hWN=Z}ZMwaX0g&JUMEw zj!B{M>i{0YT%e87wlwUt7QG|DA$egz6VWBFTvASz(PdV}Mc$e)c2Y3_st0=5%aQY4 zInq~DbUGKO;ruYwE&P?@uk^|SI~^BY`dtt0DYV&MZaO+~5Er2x0u&NkBjn8Na8GMX za+ga>Ys+a06%E@B1yA(B(AxM*vH&J&Ug$6?mbbYCy~!JNKX*d~`^Mb#6)I_fh@wm> z^eGAkErdw1>}(dkL1y!lWJn{eQUXBCz5Nalb3w^I1x*>+Kc8;MhEN+xtYUP=?dWnX zW=U$Izz8=eD4w1W6cm*6%e(Ux{my12&%lQ4uTNhe9^jI4;^;?@M$+bXa=^zR&Fcel zZhL-_xjB{1@Y%#ZXT(1|C}F@5SI8+fpYs)X^zk-Hb`pk6rm}K*aeY1*>OE#^3BeDW zN-KxJapT#D(xv%xZwO>4K|xbx(75M`bvXb7@S=6wiBcBE_Z(hcfBJgG`qC<;M&=og zl(-VPV(9lYnaR3BC=A#`f2(!4$U*z{NXo6dSh!ScOo{&cCwcg^C%K_RuEwv}!~=p( z8Z9pi)H}wD;@pFKw?WxuXQL*WUZMHTuw1(tAFlp4(Lgv6iV1I@uWy4XMk$}W{xOBZ ze%ow$K!yP9mhQj1#hnLqav7RswdBQAuHGmZ15d0-kpo^ptE>@$wJH$;cW z1Mr3+j6u?uAMg{iWq)Q8WgmGTA)g+}wCCN~T;?oZ zT4H-qr~nM@?8&z~{U}1}Tv+@CD5}Qyvi>0v_vdSSCC2m{-ZCysHdtRd+@oQyx*Sbp ze+Cr>8IzLVNZ{j%^gRn1_*+%i6VU8t$HoAzpE6x(mll@-y0&iZ8O= z6$fT3QYrn~5WTgr*Z(X30(< z?A$ABLAJ6JG^#ieQ=023w2>uzz=;Y zozlT?=)Gks@u_joEjl_Z10N({$&&|(zS9J7hPP%9mW49o{uz?BpZE@^i+W__wc}E} zF;H~o%JCfhy6%0Wx@W6w-@W7Dzdw1P?4JiJB0VQNY*35S7Jzl(ApK#G%RiO}-&vRw zZg%mj6S&;Q4VePhFstTVtWiX`uk97z=U;|ls5cXHxDEo6bBrAC&KWujmKYv0a73Jk zrM`;4PcPV<&*}8W!$}2XPT5|18|fueLIT*{gf-4PT7h((+ewPGy6VLfoj9XN`;7C^tmVAm; z_^~j7iz?(WGlQu{vqa^+?5I{(-DysQWC>?e6tXitpbgMs>+*sD*Lk&Q{u+ zz3(`3Hn;g7I=zU=R%>J8R4V=0;7-T zxr4j9epify;7pX8FLbikNsy@093Nl?p+-`+05F~D?G=NulrM_tE^_$!QL14UYZV=b zDozdY{w-HE>>y)W6j7^L^{Em^zo?iiWa_dJ`?j zZjjGGC>niK1AVj(vqSIY3?rWWdnt2gT(PjUL*cX(qm4e@`5%7oJXgI;~s~{M1~tVM;)`f%Dnamh?S|M#STp)o^vWR4g4Ww zLGP$ZcTs7jDQENr+*49hadB`KmRu^JORSS_L-4St_wj)~4xTAiA_HW`(zP@zXS={8 zgCs)EawFvdhEyJnyP}q;s^x>ykMgzjrc~_@OLGx3s0gtogP{Z$ogmx$9{Bfy1$ni# z)=Nr$oUmWT-mabO72U6J(5pm*M44zG z4gq(e`yOgkpbF$aD_#%A0vQXcJ`>dl1ts=>^)zG)RGjTmUfAMjr6-#^q|d7r%$HJm z(T=`0exSDfy^Mr6%~uKs>sf%}iKXf+k$AW@^&{K@CZrCUT;GqFZ!de&XmdDO+`Et; zUipRF>j|;F@Lb5*?6X=TU1JvWTZ`70V%Q~R2KD#sJPA~j+b9D;ldX?Oe+D`In)wPn zi^EdfpLWuF?)0iBdYpFD(}#Kgjduu$;N$Hy!n5BX$ZGs=FMw6J#%8H{%dw@koS$Y; zt(KDcTVf_20_=(P2_YfT2L&(NzT^&q}USwiBTrBp%a zw6@Rt`p}-p`0o6BNy%qI6lf@hP)P7z9iKTxEE0miHdS!36*nC(`#Ni7R7CQ3BaWC6 z9?$I{`!4KMn&0@Wq_MlAjE~{HmOj|B2k1D7t9Ro!WK5itRfuQkgzON)r~bLr`#m%T zK0X(ES(rR^vmt$=^FQ!f331yjVxg$Oq4RiAgVs zTRuVmUCe9yf&r=GWH~wphU3{LMsgD>;)ub5I&DGRs1NTYx9(t{{QTK|qrn8ZHst5m zd2I^WaY;+d#qqn|PNoz>5&zw4r#<@Jqax&Op@ z6HknfQb*1LuEr&m43|vT&J9{>Ac#yO{Fc~ z1W7JZSx?g7`Avn(u^NI3hyxIbaq%t{?~>T$qFF za3>1PRcV&u(qeuW{!pm$0$+4u--la}*)=``*YMkBg-p9p7X3D%r^BSDc-+W=sD0tb z`5lCK_Mcd&P*lN>rin}t@}ab@n#4*!oAj(?192yPU&%X;V(J{1KmBX$Uc>0!7dNI{ zeudwiy~~!_0?q3I*@Ns;Gppvf34@Z6Wzog&pCK4g)TpZ*dH}zj#PtDoQW^7 zdH-taVS;Ik2%&Y%5@E9(PBC|-+69a1-LT@_Mh|7gnknsAYWR1B>Kcu4vQig-DScV3 zQ(qhqf=d*WJ^#2kK3$~XDTAI*rAZ;(z{N&@%u5-1qi*z7cJpS- zewy&cpB*o%8djo+VAhsHT8*yrrS6rw!mksX(8I(C9*$5@BNTzc@J<_JUBR<=DQF8M za5Y|qD`#_B=QGVxvE7+*I(|ERF>lL0ad%?s&K9k7?C$Luc6v?~Ck>*USJx5A=qQ+h zZ_xa~Bb`G8v!=aHuO3JFxiNDkeF!5*yx9t!)jO|OWK;Hee~z_kW|vVkUar#c{J_gM zv~hEvE|>_!2MwQoN7rn&`zD&eQ;QWmH4^_E%H^wzGbW53ZK?sgjn;Tr^$f*rI7V_O z;DPR6z;_pdIV-L1=aIOR!|_2i93=w@@DsXIO|s@p?SHC}w!989b1DNCR7TwDdD zvp8F#1w_ky`j0Z65uZY|>@w=8BEadk|9#rf|M|4KqbV1R&edWqXJ`Fqr9eOrFSy@| zcJJ0{q9C@f0|Gjr|2S$`yUEO}KSYCW4)nW_V1gcRPq)xK!4dvw#C+c{DKtWR=Exc#VT~2M?bHGvZ2gEh?w&Ld9+w zM;PcxJdc8uNe_}kr^9tw2{Acz22+zphDffK-%IzRVT zEOrP`0(dm3| zQ_PY;QU1knP?c6BQ>$oP_Vtv2@}BMz4yQxM?f}xj=ZiJc%nzz}qzGD79tS-{_N`l? zR-8PCg)~vL22OXETracA7UNm$ru&f$FT~y-hvgnJo9I;i2-UR&w{L5l~1TT|g*UllbGzf|^aA z_g&jNB)u|{MoFKhM-{VDX1lb?-Ry}p>_13uifS=Ju97ewy4qqIEWDVKj_4MELE9Iz z|1wasGJ%e86BO(4F+ZQPvolM_Zarme*0;2@G&b-rkmlp}yMm8-n*q?x>s|tx;;wyh zC-l!wN6P+nMm>6?mI~iI6!?g%Yihh7AWMhUHhvIww_(zYmV+l`mOyh8PNaWdU*<%; z;D*X5%geG3GIP!CuB5i4CQ3Q<)P~mTB0#gl`o2^ZQPZZhJ7fgrq)w(O`j{b2(0l0Y zZoF)MihHL}YbNugNtVJHPOVxh4jMrG}4UQe%&z!RH6L`CvzUB!&VwW*SnSV zyy(=Jxr_S^TV@oj(j1V|ono0j*V($ffeGiw@o#mdmXJ*vdRGz1a>XQ7!=~rqp!<>P z>(lYL(+5SB?yXSW60dPtb#UZZ7`AQ=gC6_iOojigNwM4fy{=+Jmh)xQ+FmEAPi^zz zNmz?SPT+x$0!eNw_<@~}QC0AMxnU%VbolbopkF{uquS?G-*&A*BECSG#sBlR#gcu? zvC%?EspX#{&Oa`s>H>pK?C*S~^kk=9u9-})CEay-s(h-O%yIq`eiB1yV37#GPKbel zufRVz*n2%kb4MZOvs{|YUi)G16cyJ$TD6ADoDL;6E# z2la-87)nH}=!QO_tFrPgz}H+ov5Ln+u}pF~(9p(o*m{@m_LS5K5Gvd)_=qc3 z{Vy}-3={W+c9aP=e24GVrBmHV1L0k5HIVd|8MlxbN>OefElxo>w<@^&x4p8!7v~cVJWYobr9dI5RL7 zwa8d#I@-o%oCTg1cB6#<{SqFso(4O;Hw16l}*fT#(Mq zGTq@t^O~Cam}U(K=%oFX9#R3X6~B|g(2;cvpG8keQUb+<0$t*fR|9`U=nw1x-7rub zFlSp7gZtmF%@w=h;d`PCKdCy&88*=iIQJ_0Ubbt+EWi<+>Tvp&_!yYER9d%AtuzaJ zj6twMvG>SmgCpf4s?tQqBBx4Nl%~Zo37v-c#XaDIrCI&l1W5gz-E$P^f$4#^$RT1( zwZ#LDuLe#0$ooEOm?3n~&Y@YJ&&)P>hTv=K^D^}@g$TXw3I2pM$|odphY4-(wIYs% zu_B*8A)S}o?}PQ&6LsHy?%VcfavtU_N=@IrvRL7?VW7QZUP{&?e>%PATySDfAu?Ps zaE+^9Xnrz_PK!DCjK5L)5VDx2`R`gnKHfHcoi1sMtEP?0!(Q)%8Vl0Y)NQuSzqtIjvKn*|*09D3PA2uC-nPKsXxTPg1Eh87Q_KL!cHF%pJGEV~`tA;5Juqm)r3is$1Q580`1_YsCm_bNvycTHiX& z?=6ExXV<4(2TrctZSP#6NpydQY-662)YRIY8W!S3@Q`Do8F(%uA-K}_)%jN?|xd@5YFO-fW<>eeNzC9K7waJaQP$l9IUPGZ`JR#@!gePHDYr015|Sk{w8~$ zGC4o`TpcG$45i{a2T4<4JnQ+|cUvmdU5=()e?wU*Ucs~&nTP*u`+FTda%dAg#rRNm zDXiU?t*hE(dAf(D2#%+{fompl7<>8OUO*@~!T)@RTQ~vMI;(Z5qa~cEjH38zf^oTy zlPN-Qa;z1%vqjAvnVwJ(qUIa8ysF7bq8#r~HIm!y6g7aGMygZ2J{e<^lXQW=8(M6; zj-Mh_zQ*^s1H7`$f3K|kKd-Eu%Bv=NywDx{wbFnF7b;%l(@ipiv?)uYbR;VV)X%p} z=J-VJ@yXpL8QEO^)I&8`N<|xu+4M_xfo@QpMOsgXiG)MV`i&V zSusAB#?i^3<7R=gdwy{!W!Cd-46pOP;Rr$4SZSAWQ$C`yQcu99DS24MDL28IqSb}j z*Hdzj|JWyYLz=i!6-SeC)04%iD?j-vOt6m`cTFohpwMJ46Q_QHz=rYFNzWbfAu6n_ zqOH;P)1__wUPDtcp;`P|DM0JwNPfDdrNn)c_!rJTmHz%jt@=2%f%2vSdYErl?DLBf zhM%zN7rx>*5g?M#vndCQX$@hS53Y@^&*zdAtnaOi_!zW0I=C+D99~qM5&-o;r91W{ zf1b}AYnF(GS@9FC9eQbYSu4%!>^9e94^Z*bEfqPCgY7wg-pq5~yW63u*Ig2Op7?FB zQ_|>AK4+<;lr=BmB>4DL(OsFi&odAE<~_ybdm>!gQCWHLeJ2juFYxhYt{%5q`)$2! zvmnn=718G;_Y04wr?@jr&sg?^5kz*El}O4I;{ zhFw;xM8s7b4p9w}h1tNTMJ7n*s*K;|&KN%m;?8*2!@15AR}O#BRM%tv&Yme_ z?&FHp-FQ{4Y$SB33rJ{!?Nl<(Og2u|t-i8<#cvA4iGo#m3)%~mjw|+O%(+RHx${|5?{>8lR@+AJ8)7cnI{1)y}2zSttZM9@JgE+3Ls^x`HxHB zos@zi0*3nfHvUJcR2`^)ZrDg=&X#wxR8sbmxR#HVWG=vjmU z!ep@wRDC5e2lmkc|36pUdMECEqtc8qZk32853TAoT{r2iMAqCTdDYf8<7=f^LQS(m zLT+STzm=O%adHwm!F3#C_NTdzY}TsAvxH?&^N(ZNjm^Q|x{{ z-t06Q&n<4wahy5hT>N+xAJ^lg8;D#=qe^fn-$Tn__f85dPL#?!gcxbdee4}vn4-}a zQfC~=gZK4b5=RXnk@IWspm;pSCS!LLRaO4-hiB0Rqv17LLXDC08|gmt(QvSO&{&s5 zfGg!+F5+creVG~GnD58sg;|zOvYSwJZWWW`yF~mKI=ASy-K_=Eu7$&2okO<*FG;*N zrHH1Ve!bO3wlx!H^6-UPh3g0OCY|CnXU67IALoR3eZUHu3-%keFM~=C8|PTTMr=ir z66>PCZKmsg`)PkqDw#CJRtw!IL&3RhD`>eDii9}8HZ09zZrI-FR&R_@aqzqC10pWU z)9`$mBSY1oa* zc0GLsWgPh!)fOWe50S(64HN;i@)%{N*hHGK>}PDjk0ztU@Pj1E32?Q_%pAdyS9pLH z&g5S$oUlYRFMzw{0PmH&_+7vBFHOld%)3F!3-;RzO3WL{wmjR6Lo_p?x3$Cp*J2Q! z@{UljmN^SLk58wz)uMZ%8DFexs{YLwLv}*h6h4s6+zI5khqKlH;vxshYyKnfMF;@V zVg)sgHp@H6n7h`I_)|DL;$Hr`-ZmO~ZU9W~^-e4t6bC{Tc9hdYpA*JVL0Kz7SY~{A zFxEf?;O~eX`KWbIBB9D8Ui2K_`Je-+pwF|k{+^3x281{N^CzcyX(WE* zl09I5@!@N2FKKLd3}hr(QFi)cvB*eOHmXpuVNww&5h6-loL*yW#GN)my=GG0c|?>i zEk9B@NcE^=?#nZzI<;`f&$ArM}b2zn%} zeIgxW03~jv=~sG7J_WVKBUm0SS3QtvkH=hwZRfY2Sw= zyG$Ql-ru2KJJ8W%(j^c+jvS?I-#!WRCqTYuV+@$g|KHCp1@}J-EEX&QaYjr3~XGsOteuRtA!2R^=6|S8r>H0xI9w z+k-Xjr4(aY+zc(xnVhEoc;rGi9%djlw3bnxVf?nscNL?-NRLAyGB0{q3m~~Z`-H|1 zcon*ei-VZ&_Q^26(pkaDT(@qycXz0O8{(% z3xt1FI6Mg82V1m~2=b}H0c(5U((2l-51YC*j^(*CVIssbrERr3M!_gxWzwQ$Zkz7p2NWLa)he740vrh0ehFdHXntOmwLDo1e^zU7hWYTwiVOX5J`( zk(($cVzk+bdxcT=r3;(NXKdh(XW4c6!Z>=tZw83EdMKtcQD_4z}Rb5z4nFTKUUCiTsvi>6j|z?NVqFK zj`dv{TpJJ9DGz?aDS8ObmOsKbRFNMdWxpu*@wNxOK1Ev@f0QpzIbx%n*uy&kA$~j2 zWDEYAx#oeL)#dV+ySvGMa|Ve-XjD}D%b~0cd&*NkjN?yzH5I1{sTiK39iZ;gPocml ztoyvjRsbd(j@_JY6mfw<<#KF+jc_t{r>3VX2wBlk+QScLefktQKv(5>swo2ehrr+L z_<#SyF@w=P8{Q8F%8Y+^NdFDbQv!^w>*i1GYj{~YUJb3yS+xq{sMf+dae?@%;oyb2 z9^_(|LYqLoJlzgHc%1$4d@^h5UJQ**iuoVEnHPGyLi@Aor&U-V-kMyzG_pM=7sy4gj4o_r-kDiZ|?aP1HTC@n4DS*usbfxH_C1jJ|}#k@05o ztw&2>zy_%q56Unm>%B8G=VX&}iO{rxt3pvF!#|rdJk>Es-C>H3U;~r>IaF6 zT_v+ckgmw=ef-qBz}#8!iK1&mAUJYDOfWUI;vY=-w-6ndDAO>98hML=Dsn4+-oSG` z0k-3>IRpJI{ZJAy z(tBx+-#vjb%N5Who4U5kIALFxkN~A z^epFUYOX5AGi9^0A%2D}Em8hw4CI(fkT#LcuK!aUOnHH7iRj<%|4n!G9RYms1oDN1am^RruWC1wH8On_k~R# zZOpP+aQ3@>525M*QoUDD6Ynt&EKyrU53yjxBsA$0 z@SOY5O{L7rs1P$JL^PV|)@U)kU;RbGq?g_RSlsDJ75SZIoc>4UJ|Y9=-4rZ%=~q8d z@oJyL0cnZDI3#%tOX38D?JO|DmLoa+oPF!8 z`+w7+1YFU(KmV=9R-EKV9=4jap(^?(xQ{C+qIv!B1@mEXk0Y5H5%|x6F(l*xlR?lM z{TnD<+Uv|pPWBx(U7c5wF7Gz4KS5J-`>iu)aaDyQDM=MLX=q*$Y3v{O=ld?Ic!x9m zZ!h3oaV}$W>QIkOAoc#+Y!iAzo&E*P#DtyBhrMLiBSNcBFB`|&dI~E_t9vc@uMe3E z#h3d=vUszlo6yQ=!*&cn5CZ5MW&pO_jJ1NYtZnrcA82p^Rpx|iWJh$H_WjXL(q8HJ zMCLaid4H38%Nc<|V0%$0Y-cpeTC&K#bz@`Wf8#7_*RW!%AEol?x11xJrDTTh3EewC z;^jY%@veTGw#V=z!3C^jw@1Pyd=>-s3srSVt$!Z5PX=RzO;n5g9q&*vV?G-r{ioIa z*Y{wO_|1Pg(iUE+vah7uRs;Ft!Te8W%7i+ig(S*Z-*40!KHh91M&7BJJjo#i%s+I{?Oj@7HxtzBES>L8FPDXz~+ zGR+(t|9phLO^o#gvroq28*jo{nhMKId9wMARw~_&Se+J#{>%Uy$@bnjd$-*<(tqIf zHg|>jZcE)6FMs(gcOj;VrR6X&&+I@sW^O9lHfQA~?yl}Wp_|zre>hQnYC9<+Zpk1D z$?wuecyQK0uwm@tqObdYvx^hH3~^JVhy)+M_|E@y#=($5Tnnwsw^Hz7k=oWMS;g#6in+;DZ3h~89e`aiD$f}UI7 z<*ns-3wDU#}NeaLk^o2id^?~zk+?}vh}qfeVn4@z(t@$?@nDmqA&=AK4v zrdV}24z4+sB%zSE3r@#&A}Qhe+xC;dm`)N78?PqYzYp_$O&plfI$PN8uDAmkRJp&2y=N_g*=qiIOJfOvw}%MXJJ*nDFX3@@45v5xtPger`O+O8k_o3n-I@fd!Fc7l*@Oi;)E+Q#D?Dq}9f%m>~p5!EsrMcr311b4#o$l38+ZTCC#v~<^q ze6M47IvR%igJ|#l2$l@po-YJQAJ@73AcUJsdOHD^R%Te;gU^Ud8#62NLNLif9_pxG z({HZ;g7&nD&>JrFo~_?4N2zPSK7E7C8yfn6Yo_K%aSr!mcsC=V$e~W9>^L&SZz3Fr z;8T5wpZ1VWPMK{>>yhY%f1diBtx|8g&Y_I%FV__cd^rxzfCDBs$Zj%KEP{`Iy%%uv zeY*U9@zPwbn7KGt@-pJ$AZg;P=B%dH!QEqR7XgJzSB?}FPiRWytvPYqw`KT5 z4EddBE!oX2ynTSRH5L7R^|BY@T~prK>8~%x5oIBg=H(S`rBOHIHss0p!DxdtXwfR? z&wFj^v12Xv-M!m62U@b4jBzwPj51cEnB>JUpSzu-qB9eK~M$I@& z&CV@uV`b`TLX-WKl|*LJto;cUj69v;J*W}cm4f{`&MHR{QB*6xOv_N^^)){g^#q8 zCvev~^*UTrH~e-tsAibja~9no?RGo^lwW+f)( z1Abzwn>dHYGd}m5bDnst?b;>ucB`I${0Q+6Xm2D8_b=wp0Hi=V`l+d@yJ)ZK`kmfA zh4tmrlaL&<4~tgK2gN&9;uVFpu0%l|0FH!d2YMN00Y<7D(x;~9FS zATNC3+TF#$#M~4QMOBZ%7kWlG`qW~d3(pCIm58<6XoHPuE9AGi5fC&}BrF~hEBtV= zWL|47vF6nVJ30XxGCb# zPwpUj`2F%zs%_oWf9ADZTmjlvucX!zCnKNKMB=jTln+A?eP847ZDsXmm!^&nKc|;|Ym; z_qvsLA*{ngF4$4O^vL(AB^HX?v`|wg=NN2Nw1DcmMp&P|wwBvqkFe-=^K@!>KRh@k zbnbvGbth8blj(0SZHgftMt)mjWof9vl#uyf1x33YoQ3go8Om=?`9C(~kJ)^&M{^qLK8Ud!tShU-BGUjSv(bHZ9qQexT zKYs`$zV7z^XWL_q;HCR8;VF2^E3|bOQxw+yn#^yc4ay&qUW-MzOKQ!I=aDdAN%hSg z=Jx4yNk*=*FVnuECDjl-ODBofi)m>=rUFe;^_QMv_@&5%>^aC)QfsL{Plz^1fT;+l`{@Q0s(Lr_krT9;4E;=v*=< zD`oSwzoqJ3cYFNR&l2*nGBw?CStxADo))tKap{<8m_ey8!f!X`Yq`3fuK1lo7Plvw z=Gi=HZ{z%0y$QC{^)JV7do!klf0p@OPgY~XR@jX1C%pVtYIm2<1lwlBJGJjx99>(R zHV&$y({!;v(9$;6$2MtYCV}5Pf1bqnHn3EL3%YV;z7}6BUX&KumWixU{0U6h23|ZTR0V8>iPi-cP%u1sYeCAB8&a7jDI~=&bV>&k4doe=&=dN!w0) z1n}{!7-*`#WjrRGnOmEZnqX#b8V~6*h<>wccJ$j>u}jQ)oXPrWGPTlDbH}WU#d=8OQlD!!N#`a zxtw~_)KL?Ud->KgvR;%R@nZWj?nm`v?p(rJn&@v~c+ z>@o1JxqUni`#m^V_2@iy!0Lt^q~GEB?7Fqn^_mQ+GC2BC`< zd)`iRG4K(8ArkO?zAFF7(n4uASIYVJxc}DCu_J6Lj$m`Y*GA%c;_f_6kw`7rejpsV z?y>KK-*>j^1?7kabv*g9QvSN5>iEc*xxiIp^Y)s0zWj#LkoGdNe%Ai?HjCd4sy^pO z;&Cr})b*`yZZ43@O{|Z>xx)$}g!I)UoF+mXM|{=qG$C zEf_q#hovlNm8wnu?w4UIDP1a+vHOXE=%Sy_gBWeJf^L+ew_;hKXWF+5bwxOY+u#gH$vC<}J#lytZ z($taOy{HE3*b+gi-f&oi?kKN_6WLxlzF#PtIgJy%?OdjI@Se|^yn7ds{U~8Ba6^d0 zZq*hWU@y5$#q!0aryLk-bbN>U}Wv}MHLaPo!VlwaX;I~ zvY)B1>R{dO?bYDzDs^yVl;J=WntK@zDiTFRj4O{qAmoo-XD$$K``{PJv zXNeC~u0w6TfBo(Cs4}Z9-z3jMJ||^`nOFGDzRNciy}8zJf1Iez`Ox`!(GDs(`q^bE z#}ZZ0>(*JoRA!0v2)X5?R*t!&z|BkpN8us9@10(oiy{GEfyp3n_Wt;WK-p=qil&dR zq4IdS=GD;1JaW{jvgZ;_$#`5~x?n}z+DBtD;Zv2dgLD;1(lI4fT1^@r+1w4xXnZd&$G0@RB zcPvM$=sRnE?{nAV`0zwsaN@0{8$18$<7J2O8uHEH-!#&57KUvalazhtB#JRkq= ziSx=Q9iOh}WdpQZGhv&>1sivChQ~u)E#0a{@Q2Iu-s&{YkAJG-&y7nu@)~eRw%6k= zA@rTs_9_&3u>V)Qx1wO)^WcYyINR4-t^V=}iy@fzYcPKBA|_^g?FqBP_q9Hrw;9jk zKc2row6M7Sa;Oj@{dS+~fG#9Ygcr&F7Ofkz@rlPC$;Ikq?IypvytJ}l@YijZ7zj2U zx01byzbI^LyBjs8uVYqkDBLY5@BRc5gm{I3M$F^8A_!GvfmC1em#W;xbiH*VlHf0N zcs1d&vZ|=4n3*N8S9W&3K6|*Rt9<+R>4rjGU7gX(@7>M!>w`IVYU);luGx0+meS|} zg~8WabWLT=ffI;d+rwUl@3WBwly4*^Cg$zE;`i3}1zUEpY28=YP~^=TQQzn6qy?8r z`}y22;{b19ZN5S$ow(L|AsZ@oRcB|FQ#wL_)bsGLzoKK?V!2pNHv6O1QkfR89sNY{ z=v<3-pz3rb=I+5sU)H#I6751H5gflr>*dX1wO;!w<8a@J9WTY5p{4rAWxP%--%4c5 zUhHcfc?k`S2h;Z7eVL{+MG(fDV?}|5an9^ggcGzt-(40+au65P3NMK4O@U~!o(rh_ z{T#tVYYQ{Cf_3-Eb+j$xzB2)Gk8(hRBKRD06unIAcdzLzxU#B_yq){5R4Y13-*&2D zUbg%oYG3YdMc?J9tV^eswWJ9+q`WIcjLmDSJZXJs%cnK!_6O3q`i0r25<|;|XZk?{ z=K{d0?_8m<&2w@;dPm;&a1K`jGxxx#3E!f^;mU5RiFDc@llwz{n`hvHYOB{n?do)$ z{3m*Vj!5Cb&QRanP$-yp0vSP}&9T&}OrJo+Su2N z*RL=tD(1HTzCqJGT~UQqGSzmKc;A|@^EI}M4vw$3OSg{GVkW96`)S`VrPn#RJMf@s zu9C^nSTxfv-Rct;=st#z=d9(?cHfx^B1gRhy(GGzq~_p%B0Ch0@HM4sdh=syGTtP~y{yN*Y#%jm z`%y5MrZ1}`ArX=loWr}j(~6~|v;DM^Hl^7~Mbl+)y*g#k`P8}p;-+Xml9-WFbHkXR zqqY5HHO8evBDy(|W7GQD6ZM3dQFgU!(M9e|rz2Re9^K`9SDU$+csyWKo- z^9L||C@^z05|z7f`NzmfSp4OV-c`4-Y?HsCZdDb?dm8W(YMY>3L)F-kuVE z-3{HOD4v0bNk>>5Yitwmr~JU1!>_0kPl_`Oc6|oAarz=Kl3xJTKpILATfEAFOVIPb)K3e|%r=FV~qn>hFqG znkwEr`=~n9imOb|Rvuj2qH(RV_+2tNp9=fJP*NCu7g)2Ypb~L^$GG*m8BaqAs`!7n zeP5g;;~1a#>NmwzGZxLQ-{pMSR`%7e)A~+{!j3=`yUynL7Rvr(7~I?6&mc~y^B9G) zPyPG`&x@DMppw{LzDqhB!kNx@umR$kT`Vg5c3r z@2VBHjhZjp)CGKtaDt69OFBo=c8gVk56G+muA&3KY~Y08rRTb?Uf~h+Nc{)Z;eN?oBM13AXHM?jMu0e=ljBy zDreS!*H@OMpz7OP9{q)y=*Sql{p6d%wp2gn6FDxQ&h%5J)gLYLPxg`m?+h3jCI_m1 zh3VyQwl7`7PdiNvCL5hPm{F!{d@u4+RyNBSW$xJgZ8RZ#cg@m8$m3F4ZL`e9yybBQNljR$ zQhO8oO+wT0IC9LM?fIO7$sJ9|nb+D1y-Hyfdhj2&B0)zE%}1p$+smu`ew{PC%I95o zMpo-W+-O}!Q+~KJV?9BYL;~)HQ2nUamo8k~It_tFyO+zoP0;6|P_%Wt7@xxdEx)Iy zzcFFTUB4?RY=yjTPZ}$Pm2-ydy0V&Ymu_30?ns7(0|BqWcP+DVi0@o4w|p02jD>N@B0HM#$cd}GVAG&rbJ!ir;TY#fh> zVQoLjeAo2$SLufy7W{?6nk|wemtD)z2-(P<)5N&?Joen#64aT-4EkOTTb)8-=0e3o z+h;y9@!Yo0IomaED?-0jczqt(XC6Rw0VfT|hv>Y6{O9dTe%fPb+$*I+cd=fJmvMe? zPM9xr8E&ty#PH2L7p=sOS#s@_kfheH1muX(PJ&WA&l_v4qg6FDAzBfN;SPjo;K4i3 z;L}sSxMEyP;WzNgzTSH>v46@ zGf|yf+ZC7gawz(ZP_~A2=vnA$V%ONwR94w6x&#P;Z|tF>T7Sa$;h=j`ec;0tNU?(f z1_B9=HS#;Qj>##=!`2;_qx+5){N9f#vnZ>pzZReX5T(p}@2s=xzwt-Oq+o{9bT@cZ6<8E1W#^ z4D??sJ?zGgVyn6w+=~?To(gW2zI*|qn5@IsLqL*}Aw`OrL;7vzGj8iCDJd%s`#(an z!yXu=R``y_JgPjm3Wi=C(OxWLE6OUEnCK+^sm0+O9pJpl0V04NuW21!BJuX<_PvFrjDRAeYX!o}Oy8!PAPRxZtn-OC#Bf#5D;k+?Q<&%SWs?b?PZPiiCBU4808v z{XMm^<0y~*3w=ZY!OtYuKN0s3D?7<3c-kB6vXQPOrAq#8MRJw}%Xbi*@;O&8%T67t z%?<{5!yi@iXzD)i)6M9i_JgA$ta4U*99ZPlFA+)0V8wu+JWyyfNTn8enu8AVXv}H0 z@e65sK5t49Bk0C zm@(KE+#dVUo@-`|?M(f?`!Z=88m7g3?)Q$rx*XNRUlz{~pTqsThX|6>5HottYYTh0^` z8@}G~0DFgk_=V3z-J+SM4p`}0Bp5^8YjvG4VKRv62S^iQ0tSYMYGzQ74xwo?94T}{ zf`IpfN7O6)J+V)MqV!2hifLAnlal{Pb_y^SiBu`Qs}Dia+pD1EbJHItY(ja zHWDlc(#8gWLwx8JnKH!jK_srGe6m%bdk_Zc1DJlij3V>tDC@+Sv&4AQ9kph8Hyb{M z0E%tH8-hAIggq#N>9a7cX~x*^*H8WpSfbQVM6vHB;SV&SoP3;McMpGNCx&;KSM2>2 za|E|B?Jwi?^~ZaiLK!2_0DLwS|2&ZP_Ume9VmvA~w&)RMf5PQ({`B&2qJLmO?IpK8 zsH%gl&a7-+?U!JS&{O2;a+9)LY0($@>o12)d3ra8BTfSY=n68i5fNDFy)#7;pyJ$v zH43wXnoazme)cNioI%|;1e*#=H`#-KqeB}MH+17eDVmgqtPZoOaaEnLgN?3iGUQ1(jsQmQeK~<*}OL| z>Ynrqs8d4(5;|^dRP`o2N@LvFf)$PypguU-(aMvNlbH1?271Ujem4X(=a5r#oxK$P zd2sAgpeTv;ZzZm5zFJavdrE%<7XLcmg)6@6nWDBixR@#OeL5OdYN(;2Zi=;>+Uk9% zTL2RNiry^BT0T@cU2@aD++5byd?)BNktBEbTpzSVxcK&0^Lkbjt=)V>`A9rBY%+%@ zA1ulnv2=alA!|A8(H8=}Kd-D)aUanks{c}=IIYL)t?di^*6Cc^ZalJ@nB@~7A*;i@gEA;19;f6PyP^amISG5qD zkQF}G8iOvF$X7cUD?(@)u~cs<=Qm=HEoJzGdA<=EBpuS|v-BnVdByk6K6)L^!RzaS(A*H?y-Q#- zkIGQ5K%(It^|(mcqGyJJ+BW?S^R%@H`lI3O|G2+A;u>5#qB+uYkxY&^G0e|_a2N;Q zMX0GH_ydDF@-c;6gHmutz$`HQ+zn-Q>QSR{*+MR*a!t1C_m&GW43+Ka$g6EP&sU=w z>OWs2Q!2F8a`m2Wo!0Ix6comu*4 z(bu0>8)Q(4h{ox0v|M0(B2A1+m<%YA$H+iOQ*BJ};|NFEm^UT(xZmwOUQFp_`*ut= z{B+0N>aYYYeo|o&o0FTv6+UcRUtXS&(D(yld<+erN$+1VJs%$lcb+P@_y3jO{D*a+ zfImM!U$eR2uJubt4bGa%cxh1_0JOIUz!LR8ZEF01qu=)>ACos42wja~!Zq#bAGgT= z<}TYS9l(kfkLW|%viNu_fn+pLgEy|T1e#M}4F2vusk{Tze(ud`4&PXo`=i-I3{ zY!7b=Hd#Mtv6R)++Nk!QFe%QV`XZVGgPX|)`7p{U^*?hc==Y9$ptu!4b4cJt+Axh;c_hw#)=piIaU{Srbo|Fxn)O&wK6 z-gcdRclynzO))%-xa?2Xl$2N&3zC171_4<#Q3&lXr$h4+<*=V)=6yVjj8O}1GFKm= zce+)N{D02eez&!iPu!sVM^2t5%nIOFF#wjtGo^KW%bR6$7ceEyn=8yk5c0sItWL=w z1%-@(rjgyeFd#Iwas^ST=l`W@3E|knDV!? z@(zhWwaFmY(Tzy7xQB<9PX|=~V52vR52<+H80w)1M8Zd|u9mbdn-N_!f~AA`my|R4 z)flCW2$^^&If(dNF`Z=PO^VCQG1OeX(*otc*h&+TyEM$M>Z++|F`twqlDA5t*j#;o zo<-jhcqq18XIOGO5I75vmR^5S-mhH!$J>*$O&d~>JNV@7!M-?t&L-UGwN{dsjNK~I zDy-~W8}BR@yQfRSg&QJ8%tv(tm>NQXz;J)z)Egm3kU=#8%N));%a6$aqyih8OV*aH zi61}J)&-$Y8pfdRZC68Ne}wc)Qat9vuI|L3Q~q|4DI!mo;Q+_V9V|B)oMq?qQ{(VC z9}tqzFac_Oo^X#aKRHeC4CqHK{J1$1*u429xYt=;IC`MOD0D<-Wo0#q8}F5c_EEma`q$C;V2@T!Jr&1&{olYyzPD2{3L!D;xw0> zY;25zc6@Z)pZ?QW=G~1$e zq1|OsZ13e$llo(8u#9d_F>fE-LiRA1E73a@rs~oeMu-AqyKru2XSNyoS44`zY(%J7 zv&{AX6hEX#k~%2XYeJt%w8}u=DJ9E9@_WojFyLb3zDpCX?|)XcBf;cGW|#^1fWr1& zVkedWvwNYqV~@JsM(|@H0kfK}DU4Q;2dM;*QV!8^G&H?@8fncWEcK0AOjXtKa@(ml zJBQM*AM3B2x-TxS_ReIW&1u`59%u8*QWdi1i>9fEOX%47V@z$OEir2{5j?cQHmDxjmgY0g5n^P#b}B~(5vgvBmr7H zk1xzePL^3c!E&KOrT$7LBbr!p$P0ByKQo#v76+B;eAC)XYV~<44o=p*1O@gtW(+Vz zMT4ZEqsmg<3MMWtE-|io&9|M$Pygku|AXF>3ISKqe`(WAmP%cDcJzJ{5B(@Y*#&28 zc2U(5MDbnU${W_+9-h3rC)b~kCxSQw`!$dq5%JF9Ga}+v?!bJF^=h*CQq@?e{bsSf zDL6@cmLiId2GuwVSVPAv6gbqgiA|gRZsO%#%-MU9ZBa&}o0rPUt`p?F4IYOi503s+ z-*3g2wx5Uy{eVxtEoz8}VvaB|@wq8|rEN+&OBAMz7a`gPfHMux1kP$v2rAjARPI3*;4+pdKw-bO_jviKjgQ}#&cR)*kHMDgKHe}7O zxl4Q!AbchVhhSBfRyIfcSg9a0VMNvjBcPZz_Cht4rWN!ofZEM*5gZMIDJj-iU_2)g ze-NJmpnWQPD7N-b*LTm`Gf{AKMTJFKrO_$f*=je!dFZdp!W&ysYyzif?zRky4F-B> z-cEML_G<@91L{~)RWm_p`o_4)V8AT5U|y`u z{t{^}k2f3!4=K}@ik@I0D@C1eY|zhu_ZC@m6*2tac@%Ope4!=qmcAHh^9AeK zX>{=iD&xL zo9c?xMWhWS<~-dBz2cbAasr;unSy6$+P}jm9Bpp2N9y~=627jM{z9n+NYchdAx&To z?Qn%K^d1e%og45Gr?KBu*RD^)?8hU|C$I4Fx?IJ4Hl8D}@z!{m=n4-~67uZ#;=c~0 z!%v$B^q6&WH4pxnbi3d9FsCyE4J$&(B&p;7eL?`>9!PCM_eUbS#3KlPw2EPmdc1?+ zH`5&pRlhs<;cOBXno$P;xwSHi2jJN&OMZVGhw!;IkvuUmGDe_nVE|DoGWs~M;49I( z2N1)Ry62J`&r-FJ{qjxc&m1(RTL=#dVkWwe_}KXv@=ozcRrPz8#Q!K+oo$O;ebnK= zX`hmTH_ryvh@#FTJ>&o9iJ)!jiol*i1Gth(wBQvFZe2oVMNw2Q3|4FWG$7Oan_DdC zBZ(r~wEXnIG+7;i*VNn`!SYgXy29PO#I^R2j5jUjVUee9H9~*R2lxvsueVq%wvg+X zeyA+%=G16soB0~|dsri#37wwZ4#D9&O(~BQ8Tyt8vo~QcGTtMr{PfPoVH^dQEN-AS z!M{)Bf4(uSJ_hy8MUS73H zDe;R=x3_vDd`)&fSD=oH7zK4004xDzXJLi7rmjjTIk^MGLr$y27Y1122g5re;ez(* zDspW#w@gQYz#mu^oi4BLu(ge0A_NYika`3N{4Omy=35A77))z|%Os8VUk-I7?V=H3 z5N-yT!rh~ZaQUlYRJk<+QmA*aK31ZY%P+bduZpCr_| zCucjG?cPnE*{wkr@fm@X;3w-OIz*&W%I0%}9`P=HLm0+1Nrl9Lvtz`5nH}I$cMl8_ z&~Q6F=y6(-ak99{ zceKjmNP6;zuCbj~4h_CRThzdB%E*;j!2tu63lViGiK;T6zHmoiRVge_`jB0Zq3+aIoKQiq1!5v6*PfkEft+t>UMh^gxXju20T|RQ{Zg*`vU#$?q5@1)ln@N{j&;6aKFk zfI}Ra^~0I&#~=5pm>M>@NYlcbnNL|nwM-l^a716&SDVh^CLa-bV22Pc2>d~SI_WD;`)_h6${`tXwPpIu81yLg%Uz_8IkRc` zNX5rzb#B3+S((s*l)EwzhvVjE?&hY!)tI6`6aWwo{KiO29w8yQT)`xpA@N0V6vE!9 zpPHawV)W3Z9ijMbWVEn`;OGL4TuG5EVH=KYRRV_*&l4W>Lwd^?BP@^f$e0kGH=`^t z&PW5@MFU84CzeQQ>I{`4C3OSP$oO~D{QDyAu>U!7oO15-tryOt*YKgY$?WH$<|haZ zHQ2HtF28NV?1Hy2(76A7k=$z(0`n4#nI7XS6hap0?eAvIuiUyCirQ53s2wehjq_K_ z@fW>n@eMAUoDG|Che-UR-;-M+_I-}xtk%Y&k#Z>h*Suk-TtZ< zZPQR(8PmFPqUW`!s@kVWTt|36tm+7(sUdR$Ma?E~i%EOy&CxoEr{Yw*bIB+X#v(cl z2?4WNc64@s50X)dHl-JXaUwmJ-Cb7?orlR4Z+{GK$g;oN(3By(IBUTmZ#o75CjMj3 zjpp!Mr^Ne+p8}F`R{I{|1+4NoCV?;{DV7^AEG0;GQyd z?PTgut94W4&+`SBBFni@(J}N`M9PRUOxL>D4B9qe#@`MheIO2iT1S58xT;Rrk(Iqi z$?lGWt}C%-(pCgAqk>!wMVsp^!ZiB2Ju=G?3y2Nex3RrZr?OK{NwPaV7=S9y8#gsZ zM$oK4>(B}3Wddw2j$5`^6qf`1?D>z+&~cJ7$^J1t^m|jJ5;wLOr$|7=uF!hT7`5#b`ypy(=yJ!P@P4%P z!IrSIJ=zu-Nza#A==xa(;p9|_($^T4J@zWTGA*B++^{PKYDHx>Z@*By&si`-a~ zjX0ZWvH?2PCgMds;QkLOi9ZnG3)uDhGN4|{=2lF71`N=TlTv4>UQCCwhV1^Q976lvU+BhywGnCi=__jp=k(Yr!~{Rf~*zYR1-xBJ-zZCc}~3X@UczU zNy218ew6gSkbf!>0@{F4^P$^56Oc&^>+#uM6u)sX`mfDn4mv;-wLZWS($);jyB&kxt)}oXUZ*B3sWA!&AO@oVS{6yCAI12}N0nVlQV6UE0C zRKY=A;+*qnFLB0K;6kW%(%LYNN#J0Ugz=Pc@Jc$mN=QmdNe@a$1e<_zyJcMcMHb7& zdo!+r7mtsR%B)MRt*p%WTJ2UMm89Pjdzmt-BqlP^^9hh=-s&2W62zemA&|wP^^#H( z)GX6to2E5Jjrd*j zKDcqBI%FP#Yg#j-JoITf{1L{0s};+Le~XO3a`+k-B`;Y}Fnv)=h9K>Pwk+*!I?n_ z9}gYo0y#<@ev<$*k2xZ9;veD<++gMDa_U&6QvaHinv`8bm@`~?{LQ}lR0Hcve2<$`q|&qDk=i( zf*QdcU$`Lpa$J^Gzt=Fj6y%u71->f2&&$sn0wP!)9!PN9NmOSnndsflPRTwvx1Q-6 z5oK}Q;-c~DO(kRK*q~AADA?FYRwpq1{KD1J^uyq@==A;;PBiV^`vl>yEN7{0Nw$qY18%)Gw#*bC#s#Jp%WAC1`#}R76&D;hAj!$DkJn%|VT)XqaUYC=K% zJ!{Ss^}56`M;qXnm|sTnk+?B!XGC|CuRg;2XRASgT$m!}FNNvTF&lB#0Gco)xPfmm z`t;zQL8CjEhie}rzr|$EtRx{1RTVl(w7;s)Rb?^K*ux} zKNjL9F3x3&fNICy(}XaH#*JpTkn3YYNC-u^dwD;yJ2+f2gGT-xty(?p0E5Ex-sV>{ zrT>Fb!n-AAp#2Uhy@5j7Mu#7So<=#5CM7-c-+?2nYKGajy7m4+BbuwvG*O9(3B^b9 z3KbO#yD3|0_eC~FUl3zHkb`DL7XOH;8yG}7=-KE=z7vvb>)qN;(CK$>R`wL2{v|2z zEI*aT9*pEzqToH_1~5xqlPA+5UxlrOf%t6Mk!NySOfCsha4tehvW^U=rDUzRfJ>N%~oVDM}QTHK?SQcY9 z8MsgdSM$w_J64j<4ThW1$PBd!z$m<{fD8QouFnunZ9U9*kCFS+b^m|_&R_GipjdH^ z(StYeMfJ{3LHg0sbmOV4yToFZ@MR2j$#M6mKq2RAT=lOi-?V(V$SO^Id^kmMh?ZzR zLM7Gbmg9b-k}W{QIGzeB?7uWpk`f%~#gBb8utBU1=%gF|s;}}*!)G3Up$7PcYm%E4 zLRdQGngnWy0wsv|LnDV0SJud()IoP(ARg2VDiMu2h(}X9W?B_8po{?3hX@$W4lX+~ z7aLN4;mvmPo>CI=^+Tqc0RATkCv57e>!I`pqHxZux|QYqFN)kg^g~VJWJ2`Hc7ma_ zWwBwxq52tFKcxACg0xu>mnD<~Cu!zlnW{e&(~JH#l5X}bDzJBHGc^JA5o2Z=(O))iag0FRXncT$5fRT%h;RS6V|i$duJQfIf0EqM{*Yrt&39?jAFXZ&K{`h-ebi9JFL|?pDCMYH!H&dnlfufm+(8$Or z+S{Fz^GFxR%se9SoU5GVZW4MMV$M=Z2v+QQ$Pi>p;?dk^5CLUO3J%!~-+ z@LTcZjw@c)J)O_$Zi$7n-Y@;Oz1`PGG0`YP%9(7`u0?%?AB@2lilZ^Gxv3Id4~{C2 zj*Vn6Vfagz#Ksip!XXciL_tCCn#`jrDS@pOJ$Mhn2oDFB!$JQo35XZj6{4JVFRZh4ZLKT0S8J$o;MYAl~iGc(s z{K2#g9{Ru}wUVl}b1)E6&{mu-tspU8eD{!fgSJFp%!AOq?W%I7w&w+hC z@jsIO2#tHQ#=Y#O@8_iHYv|E&jgF2mjErJ*=a3ScsYG$kC}4;!El83>Ye9)8+mb1$ zB%s2R+V_$v3?^PPxU}9+9y_b{*>d3a)FGX5Z$fVi1Oe!Umrc_+8<6ahQtD&Lc;J}2DGHSrZ{pAPUvr1CZZg65n-Yb?US999WyG)Q? z0O;pk(5u++<^22^^x$x(WnWO^swEYhMr!EKglkbKFK(mNT>3}_l#>(@A>j`|;Bs*yeK?KBh?es0aDEZL z2+A20R`MpKrkusl_{Ee`CZd#f?u_nG{IMp1`x-xQH9`qo6%jKyK%?x^kU-8$oo$>) z+-JtCJsDQr+1S}y`$$+LIWRcLE=J(V4atC+w`>jw1!<7E&xovls)g9ZJN)wsHJz26 zt$9b~tGMq>;X0~rwpg|l7|oR}$}p)2cG1O__Ohxuta~lF+=J6kl_fFCdoZyHB3Wai z!zC2}N7etq4%KL#edeQp&bjx;v-NIYRr?nRnHU(LOwIGZ6Y}TN6$G&G^!*uRquak7 zMV|-ws9f#Bnesp~bZ=F9#TzkU<#nVBhiuJ@vWh7$xK2FYYRWYe?IdP5W z*B9I;0!&O5oA=U%`(r?w^z`H*{9Wabx1?bax@u|xGT%(qn;$Ltnfl_iX`N~%9c%UC z(7;v*+}Nh11VbxrlJZ5zu1Ocx4gm*p(rpM53b9p(OKUbI);nVC(EC&M2Q54XaWT1w)ImOkStZ z(59$oJuQ#4Ra-Y}13fjD@(m>DMWqcO^N3GXo8SPru&7Qqfvp_nTw&>;1^u*ez-u5$ zJ9@4j51dNL4l(T8w}a7fHcV4$8Fu~u{#!KiPj&m!O5;RB71 z00n_TpZH$t=bj}r1vvDdy#JtL)pOy7_kY|$V0e$rT( zM26fnLfc~Q!4u?oSY-Xac^1j>pb^F9;h)mkaZGIFz)gHgIA~7ti$cfQ6t>4A4i%b< z5s4K-C=4&zh+$NsrxT(Th)7H6<}>I%Tb_s9lg4!G1#OS3W)$B2xGru^=iz? z%}JC?Lvtg7+Ez~=Y%S+IXa!+CZ(6ru54CoDytG4=pso6h6p(~Vs-Z%Vf*jW!Hjx+x zOvli7EiG9{02VxwjUkE@0MN~O-4fh<D}f|k85MgWK9s@H%dAU@ z-=UV~^S(loG2E8SZ(aV&r{&)A@ZVOs#kBl2+ecRFT4%DEq=-p>7XCPTpMfX5x0KRY zN<%n;tf)MVBSV9Jnf_&FH8OMiZ)Uls+lr_kiuhXnyloE zjl*YYDO7i2$Ql<-wBzQ(Z;NS(gTU)R$GDMtPAO*&3bF8h{pe{bNIMT*cuZrHl{jr= z^#(^godvbDR67qJ4fUwy#zp9UwwZKJ(7LpzgYJ!1?sea8S+A^{4Pt-8& z`+KAO^@pJ?1>XDA(51_Q`df|)9)Gxh8hp;d#pjrS?^uQ%2g>|c_-bcVaeV2SVY9zu z#uzP4BERWORXTz&#l@=I;%+pmV`6#A1lQudsbW#K|wzLi42pt@z za7_geN@-IkfMs?-_HoCPSUtnIn8@fTL$3c1Pj4L-#rOUXgD9YsgdickbVzr13(_gD zfWXqdq=?d8(v8xvbc@u|-6`FVJ~>* z&|}I{f@Z5xzvD>to|4#;@M1>_usn^G82x!G2mjv>Yybg2@VBugL52VaKc3eLav5P_ z6t>%6=D|YZ=9ru2?^B9@Sk87Z3s3d2qbXl%Z*+S}V6*56D|YhRFR5wo^=&PM>T*vf zMS{{mm~g^HaA$`UFT-4*2`cQ%K^0`X-h{Z~Z(r3sk7A-1qpH3wb~Ey;e>clBsQ3yO z>Es!?1^$5#sjaO_V7^v$$YM%B)%dRID5(W+J}-+QcV)t_gekuKDI}5D&Oe8ztVUTF z8v%)%!%7#y-DzKBUyD)ik~mYV*1cz!e*v~l0@Dxz^VBaM*d{b5e5-%f$L!(h$AXuq zG#Q6Q{M|-gF}^3A%LpCiAL@?wT^R$Z;fqIOS5e;AkSO{pR-N(r55?c#Av8ktYbgKX z>R#A>mRfUrOKch)<>bzWjv|nt`z@BVB9$4|DD;BHz!Rki_)cvwjW{p*1L3nd$^@xD za#n989oC)ZOEpT=JAY%*x1fCfr_BBR^)=A>+At747v!04QW*~Sq=+%xP5u5OdiS@! z$Q_=dYbpLQDmClE)OF>wfI~9oYk;he{}0dt1qmsTY}VJp>T_sg74?0y zM{cT|{7gZ1G7sw?!m3#_+&4vgIjg1@zQjCNg=y)B5cTjzwP1=tp4k%4*2)H54dX3N zEE2DcgVL%cY=7sc5?hgKdhmwJfb12^wd-27Ny;1|BmH8wAb3mcRG)3;st@i1`NY9B z-RrVnO%b&lnocbyEXUPvDTZo|$h!on*l3Z1U~NM9QTF{aCw!GPedS539`_w+Bv zsU$gg+t2;Td?VJDlG!*jX?c?8pxk(=?0%by?UJ?Q;HH2Xh4$3s3C8g=TaN5^>JrDw54&o zIBR55xH~Ur)1@K$z0{R>y&;gPF8Y1@w=$a{SXuSDg3+2<)LDs;dkF&-wt*9IucNVonC7LsT_3=9zcio(sCNsQEs-#_$a5!pBP3b>PdZ<}NU z-6`vBSMzpJJT@T`O=(mK?e)D)i#1ka7MY8g%_+#pgdEZQJQO7YQ4mCw zc2YC>krU}2mf(mI>f|3H#4e7JFlgM zX|7z`Ska9UU!n0$gn7*%@mJMx(XiN&mr3rV4+l~vt!I8H@It8ahmL4520wg>Vq=yx zC0j?%dLtY=T9MismeGV1WJ&VyqKaqLJ2C9e=A|P$~5=KvOWBfssgcwx8XUq_ehPL$i_+0 zYdrPZ&z(T=*vq_sh_kS(V^{WHZ)#LS2wrdDaXR(Cwe7&MjhVq=hF_dv zUGdEo%c^C!VFI4xiz)iptX3;V0s3Lw_#6Gn{?gRuM{!>=9uG0H+P#b&EhY8NzPgJ; z(2Nl^)@)Aq+ysQ|wLj~DqzO9F2%QfirE;a7LBuy!S<GGF>KWWcjamVUaGU|TxK;)^>`{nugf zIH|+fBkko}C3o!;bpmAb$#Z6zPC(e-f1^n)Z@MMewzx>tXI_NILsVL%v9|NLh9D!t z-^`FkiFeMxbIF8AO}Ml7+t{uB?-UWmQho0r!4D%ceHFp>=4~%I;DK6sDI?VDQda?x zx$5H)*{*F)NAZ|_KD4meVqzsycTt5L$FHr zk98DA->^pdjTQ3iG2N07avh!yvGv#$BA#T@6DyRe3ynw+3a=FA*G`lPlAg#3fsg*u|V%#TH4{QLTH>gvDBdssvS1-#vFo%RNHtmjo|jqt`ULeBgg+DzUd zINaybhilGlm?K^MEqe^)BjEfu-eVT|mjoC72SY!-X7Hoqt#y0HIM&gljQx#-H4K9n z5NOGedVG3b-90F0U2ml<Bb+J5&$xvKe?7=H^CT7Np z#o7ay`>E^v7vy2P;2{hCSz+2Cz8s^Kk(~NrL;4od61tbi-)*wyK~)=rR9%Aa>)Rf> z>R5^?E)=(PX|H69Pd%)eze60!vD4#tVjh69$SC}Bsl2sXNBc;d(%@r!S^04y56(T~ z+Wr&=#Un;?;@e9NE4grwm9Se^g`rmBNtXN7k-v>Xq^i7o_mVHH&{zgYDz}5{Cau&@ z7}>ophuX3dJsm_J7Vs;!15zu>&MwdKf%== zd(&n|6SxL^ia$dm^KuGug`wTlEI47(!##yw>af#&YbEBPSzCIM)(cx^(&Fj(#)FYP zC4ujCtxyBz;kpcXaCJA+1*7*)Ty!S}tO}RR?y6KUCPWeY;X8iCrV6^m`(16tshzv0 z>wL8>-6UG(l7?vV;hA(nG4BjV^y_Hh2B%X>D_*t?l3U-sq#F)t%$F}g02lvn6+~{V zWjLFc5mz4se}@fCfpaGD{wbIb`mFCMJu^>pnIEO)?~|n8%L3&&_&w6lP`P&eG?tmh zk1>aK9y5UWyb&kz9hc1K9ah=UbZKurxz#=$!Dx9-TGpsrq$2E+5YEriO0V0Va(&<= zm9BgsE40v<19+UpUNH~>e z{bJ<)KJ`;G^}(dmR~6s8;o5dm9icO08%qJNK@QXnjyZeM(MUpDD~8_DzS3S3bBmcY zpc`Iv+PJLVVn|FdLh4HIW?Hr-*}Y01L<;ijAH0gJw@wfwQp^84y;4o>gt|{_(qlGE zWb24om|*D#_WFd|?`zj14I-?&(g(8yi?nZlVKJ|*{#^k|yHwUJOxpAx>AJY68W9fc zj-yI#{e=sTKN#_O+9Q$1NU}EfN^E+o;+fli85aWW*R8pGM9jg7h3O40Q$;$ncEoP= zHDM2T<{?8f`;#ex`eBi~%D&Ly+4A6X3}_AO&0pmwrD31PySNbGzr71%)iCxz-{3osPhlEk*U2TJ-%-&+xIrLC1vmQGk?AMD-_#8P#{S6DumT^_?HHkyGGZggL#98R7t(Zf%fSj zDJx+cK`ZCPa--Fd5l%0gPf-P(*$LgqHpnI-&Nd)3_8z#Map^Qu*J9l!1>n6J&@ z?)jn4h^)CB2@A2i|Ealw1u{`Fg|rA`GMR2%Vu>y`6hU~|)9gCN3z)1^F6C}s`45Gv zlE+|~JcsEGzoEb19Zvo0F}-+-bYT{ByiC&gI02`4l)IWX@%9}G;kZCSU3am{UCE%h zxv){vk}-$VWwKutRym26vII<{K*lIqC$#gF z%PVk%yb{PQ|1M*78dD@dT3T-DvRE^HulHxJ)_-Dl#gv~6UMcyv9#t8@wxS|Mm|t-# z$|J&bf4FBPgY&Emn=-Vr(VXl4=HM6H>1v#%2?l;O*lK$m#z~2eG4X>4o$2#7Nt1L> zufOc+BeoT>V=|10@w8yq$ty>*LK^(HDa=Oshqe)l4l@MFYcZa_uL%lGozaswWfa7{ zJ2RR5xO3ISpY+LYCcfnT)huz>@|A9U>JVJU%*aFYZ2#&m<|ypPP%6%k^t&dYgQ5-V zxKSI-@Yy~okX<-BL(CPW?jWxu8c6ezyrW~-Y-h0jG8Cs`%8)4f?}e}N(#R@K3mcwu}!^Ri>-((?Tcjl9qsQ@lf8n*!JY)bOM_1QDK|Ht}ZiDjNoUNd~*j1 z?`-}2{RbCZa@%yZ`M{n-$43=DQ2UFbbwq2|a`{Jq)$JYhrgI+Pn`~fus8G*pHD?rE z`ULakxkJA7aqvFsl_@-yUBg%#2Q=sCQZ1Q@PILo zfxde87jtyCF+)*2`-XCONM4qoWM>#xZ-jLWf6^@h#k#B!Q;Q)_z6<-+3f63v=v|C( z;QGbzh_B~)3aEwQ^1vR=FXV=V>=Bgqmo^H_C@ zSv&rR_|?&B_qo+4_LZ^s3$B-qD-#vp%5xz%h zN`VfYRabuqZamnWU{TEnu~Ky8gjTbY*0JKdO_m@wO$Xy}dgX)3yT_H3(PObpFkwI} zK`qU3Z2= z)6Fh4%BPe*O+C)7WwX}&&UM-N3)>-A!1y`Rq54TCB=6UL-C8fju%U}x1y#{!ljIfV zCDcJLry^ZZvOLY@p%aCUA62(g#=e; ztbs&l9ADAXFTOQIMteF|Jy{iQ@mrSk=2Z9v-@cQ5pJ}2_>nHR8V@O2>g@#F7T%h_M z*75}%FW}zo;S08wWlHz%L}`IX;FfX2!)img6lDx^)u0(FniD?c1b+gf0SNYSq49gS z$$Ab|(LkvMclNP#+m+l11lfF7R-D`6u^0Ov*7sfJqNMxwrc#hBd~NmdJ56-0 z;};_IGK4u%%n>KJ8{z2BIaxi7AEvZBc;~1n%v5Ix)i5?XDw{`xgGD75fc7-W-7PqF zIFRM7%O1fPJI7nrQYA_k*8clwhM`}<-^z-;L!r3$x}rOAThBN&U6e?!d_%M({fy%5 z^_T86l8#E0=J>WXm~ao|dGnhYyUNse{+B(Vem@Q{7K}ayS-APw_TA*)+(}h?+_Hr$1mbf0Z=2NZq+56eUZfw0iM(96E=!cE; zuL$hkAsrT*ohvpF`&K~~KElW@n9_3N{NvnZAB^+Im{=+2%_-NQ0$Qas8JYU&A$2#) z@#EDSQbT7knM-}2(7l8PT`OeZ&Oe*}P|tv?2YQB8i^VdGD&e0)N7Cs+`!27a16GdQ zXfKDhj&XZCDSdiywm-JrULQTQ>MIGl_%SUx_#j{Q>X_{i@` z)!(WrRG!ztasCersHb-;Zrtxk^`5XLzgGg_pcqi8`=sx$Iy&d|ZFO7GN`j0U`dX>s zem=E6I!WX^oo4HmT26_g)wEhgOoM9jl{nCX%Nc=B^{;I%rNWR4iFTkl@HfkJ&+zu~ zMGD!vOv(0uc0s%@g=LSk1;BSOi`V!k4k|9Iu%8z71|#FrKcb>>ppQ{B%x8>YLkf1v zlh5{S?(%2F*gihDsqMpWI^QdGan?s9=_wtd6T%v?s=T9+)1UQ%YU1TIZJ_-e8t0h^D5ESg zUfBy`ZtAn%Nc2_PNn;oM<+{x9ajfK?PkSxi_sD%XLGUl&B2lH>JDTpi884i6Upody z#v8*P<@@L&bR;Bxxe{Fbv8WN%EK!R(eA_28G!gZT5MA)$aE2hETT{frJ+>Dn9;up{ zKL3Kj*={uJmZ%-0u)63rN@sZkJw;9ZzNWwf#WcqZzYv*@)>;_nbM&{b*Gg|=eoVF* zQ3wg%EjZA-_DI_X`l#~ay)kM+r0qm==81ZbbpM?)ryq;**r%}PUcvxla6hM;+q=X3 zEwyaCMrsohug-XS411kE%)7YYkgEH?=qEt)FBXlzTWoSI=No-AwkJ@p5@ z=QUhO;L{QC@9fxf+H7IBYn`d;>oyJ)Cf*Aou`7PK7rPowc~AsRZGBXC0a31~9$sQA zo{l!sTq@Qa%jA|>j0(J}LR9;vt7Nl+CCc#1dZUN^gEaWijizXZ#%Cpp&_Q^g3AmQm z{qj1I)N(NEDWw0{M^Evs7f6eNR`|=J=MvxlmQm?DDQ3L%>67Q<6hYU~S;#Y2wxgb| zDE2yGM{FNNs55hAbVpxPzst-=2DkSOH=4#;NDDJJ`zqJ(g2*AELy=u^(Wm%*1e?HguOV$_8L#*l^0v6IjJ zFf^K4OSGQMQ}^B%sr3;}C|Lc3823^qoo-MTj$xIzP%BZdUp;um`hRdo7-^PP*sw1d zxwg~WP~8nWqUhx^Wu}4mcbwlsRR-l!)c3`zJPz1ARCXi>s(h5@UVur&s?HzP)FzN% z{@}oaBS=g)SJO>81S|Oqq(g!Cc4STOyfqYVSyUDY+=O53NmEzv#MSWH9DdgM0ODMF z*s0l}SzKg4aNEIN*0J)jz-HZxl`@q*d&4u28f$nfCRSbcOFQG$F%iqv^&exIhm5U^MA;=S{NvZI z*QT8G)tC6F7xhr-=FH&?P%RJnJn2Pk?aqN-on>qC_6y(DofqMO0T4Gg@w!!d(wEqP z9%UL6ZdnhAYmVt*UWSo@ww<_@a0Xx?pNr@o?&N?FYHk-VRP>G+{jBTE#L! zmEOR5SV19bhKPAlF(q#rsrPMr?x6Eg=_HHoqL+ldh8`5n(fX@O@3Lt;avebYyOT1p zn}SP#M+gm;BTh$}02zva6r%74Kq&dXL}Xx@THVo72H^j%NYlW717BH5g3I&V`9)~$ z8^&|*N|GeXA}(Ye-MZ1r+;sQE_!D`ucPcEV41<#I4Z<=f7hYH8-9nY@uyVzgDW-q8 zeDSHWD1~RbitvEuavfa>s)Cfjc|weH2kzi?a7hUYpzHRL1DJNn5J-*5Y$qLK4AzEh ze-tR~b7j?QsNWJ5oQy0~p^uw|jY&En269x}d-@8g3|JXUkYV3m&7s$MckwU)S}&Hlkc=ZF zfZWH?)66@lkYsv(LICs)2?+~p^BxqL!6w0@a41N#umCO8+Z$cJwG zp|S!w&$%%rDpBRkoX-Z6pE&N5V!LHzR!X02*1x-Tf9vLpZa6%yHc?YnmJHa!hA$xn zpq=>2c8q`0IW6MEaF{oZG@g}b6&wA!oPG7m5l~TnYOVMAnudCdy5G(GYdatf6*_`= ztDwR%wit&9K&3&KbyWUw-OFo-FXrR0>#^cj#^BI$GktpX^fxv%e!Jz8^BK3Tr$Gi1 zQcegRoQ_&iAVG-O()?6r!Q>(E&(O+b~G?mfeGs_5~9r@lTRLKUc!WM``e@pDk5tw%HR2OC~#db;q}_fZOnCO25}= zAJ*QoK0L;lYl9OX11PSHYQpZ@8OLA`RpVU;FUL#Gf!iHZi+vRYj8pxEO`B}nZt2d$5 zqrqoXY%;0*0+-`q(=n7tdwOBTWj9&)IZGc(OkWzDP0QcY8gA4^mbj9CjC4(ns_yZf-x41#)Ar7ZW0lKRB~<&_AQerFC_MgoNPJM+tH9 zJFV6K`0-=9Y=P3@1X0cPZA9`$9GysXN--?RCw{th#3-pxdHprv{% zEy0#w@ZsxhhrV17k#95($ig)XmlHQ>#$RwYH-WO3^a9(@j=ifdR>nR+{bW9TW zT3k!DA~w>uBB3U=FRAf(9bhU8iP3R_1Y$iMSt zI9{y^3ibJ)T>o+)=b{WlK+l?bR`o_fp2g8-v-s)XSA{HAtvm}>H3t~=dX12%_yu+^P>;G z*0t~qW&d1`Oujqt{(JnnCp1=Rh5)*B|#{C>7G!4Z6A@ zP62`_fB1>Af)y3Z1~eyDC@mhn`qpXT zxW8ZV^1fywr6Y4m=vRjdjlGnyqz`KM`zWa!U^>R0$s``I&*ZB$nB1_MTw;ry>|fYY zWO1fI1%cqI)uqq+;zy`RiybqK(#6^q^)Fvi>!I$yxOElX$F%y|q~?E~WYc*o*?0yo zjNJp#aQ~fX-#T9TKP&(x?h#Qaz@j>xJlqr);*%h}B^mkULi_Xwg;DKxOtR1qjnij{sNNpilu6>O6qC`&VYDSY^#s`6r{n2Htr5 zwF)FXAve{`CVxxaxMh31w68}oE~ra0^nFIWB2ceKsx^|)>Qlrh3&8&FgkxICx*zpOFHMSbU7UoP!wU#8i-L9pkbIQsQjDO z0-e(A@)1whbhFoQQxsI6Sn-cMP~my?p4#ypnN&sd>G;5Hx#6RPn_DecT7Q4PnyCJA z#Y%vL)OV`ms=bLs{q1kptq)oLK(^bfufQDPycPvYP~wLBAy&NJFDW2B96P2N8OeiE zbeMiTPZ$n1C#&v1qp5b()TSG?vnqC#<&NtEv;e_|EQE??%jjAHFXf)158-p&gnK(vQ=w+nH4HAb1m$L}sU+g$+ z+5=ta{asAP>xizGiP~}r-<7Ce_N#0c?XW7m>nyO7C1uNDMTAXWhYCqgNuRLfxtD{|}UrTvX`Rn_+;O*%n zVCRc@P9aJp3FL>=uhJSof9A)Twd`3fldxqUu4B$+^1?8Rwh#eEYkyOFxSqan(=OvH zug?g7$T--@DVY;nJvPAKNfVpXz%K)J-whtpM<{B-+^zfVn8!h!wE3;d#0-l0YcmwvTtB6MwJG8tltIUei7z*?8ydS?$l>S&dZU3;S!&Jz&<{~ka4*6_-**2cQd^7Yj zlc(mXq?F!cQ#~22x^E{vB+Snohuc>=PQxe(LDp!K3s^>t^|e{a!RurB+ihx1tS_Z> zTUoT+YdFUX}&s}Or{vKeQT4c5b;#Gy7KWjpcixvBA- z&mX6#(yG50ybH?=hw>R8lxTJ-m=`^%3OXoK&}J}vQsNE31?;nx`UcBF zM;$2bM=NbSy|tT3Lo3_wgx^1Y3C71Oh0g#+1_wEukae6kTnr>6HnvJNTZuT<=l547M9cK4w54>o6DqU#h5ISStMX0 zS#A;VNu2s@34h&MpPrbtH&RxVMHsdV%^$lPEnDheT(sIfOU4)ad5%!_c21QNjOF1- z%%ZoQk57psFWMa;;e#MF*w~GlD<)HC<;IgC-lnthl9{*5b#V#E4n;FNo~=!HC)0&h z3I@wfLh=3hvX?5^So}`QgJb*Wp2CoW(e=8 z${2L^^(_%x;n$|{Dwpu+Ny z(>~r6c;Mtoo86WkJb+5maW4x5*fF!{4u1MJe2YBdhdu0yW4C){!4 zrPqj9=FZ7-BxN)5tPy5OR8*~4C+bc}V1#*c$gIe$#Dy`Et8Fzjw)|)c8R?En z6`A9Yy&m#M)QM_u4O2FDuT`D(w(cvaTVTeQ3_y&nsFpHJPfrwl9MtLAXT${bNdmhT zk5WQD@)=AH^dK1OV|HVcXh}q{&Zbu~3Kaa8={pNw!hC;pqUOj?-S(Suf$=m%hR_3p zUi!*8<2k2gB&6>ti!<6G;tCKOW!rgs_Ya1`>~ly_=%YORg02T|@$t=T>rx*l&+Q}E z*YWjhK980A_KuI^O+No;sBP7NrX4W}``Y}kOI9$F3Oall*hya35q7;*+BXOte$M+r z!-qjF4n?=ZFc2}5J+dPyl!z6|snmW=yVG1G_W7 zH!Q^%n0L`O?O^HVtiaiilxD_m@yS22NT`RA+F9<73mk5_heX2KqTQ53kLUt74Oqw3 znjfazK zBj|_qOpGbha5+^zF4)}HFA(mS>F#W(+e^%;$39bbSHY7rl=HE1>mJW7oa5UXR% zd9(WR(ducMW2pSOb|_%}LV8M|WY9dD>~K2yUD51uxZ~fQcsO70VGF5W@Ho8Ycp63C z0Lex-Mgu15%}oo`p}MlPcVf&!j;k?1MyPlI9U9mH5WZEaxxA$MWBNxB|2=kL%ui#( zKv$}9EqHR0S43?)1!%+0iNJQkaiFyuRR3mVSLDbpn4jq0^n<#wU%%Y|1qi|(PUYl# zHcH%6Z57o_8{Y52OGF5vUivOlxFY1{DKy`R*g5-Jed(ik8|h_m^kdC?W!`n8Zmpdj z$4GKhPHc&b`K9#)OZUm=pR`Ugx>L5~DW#@KJ}nAon6w$b{^|y46B(#sL6=&G=?6~6Uu<`wE4j^I`d-t@Mz z>u>ISRvH3dZ*}ow&3A+8VKAv_8fuS#5?*|53Lg%RW&-!W$y6inUvhWgf?euR>5@Am0u39VPf?&8av)HtxsY`}PbFDlJ`kULz0 zi+|_7s|M3Nmv!VOKo*qgwyb{e{!1E9FS65ziEDG|{{)RE4{Qlq;Nd60BoUr;Vjch2 z;|b`U@%*!m_~pN)Y<(@I<)^AMROE`!Uu7-H)!CGYa`$j&CfYviX9p9Zi=_E5@2(iP z<6uFZFQlc?Yj)i!Zo#vaX*vW|t;$ccM=c3eX+%3CLQiQ!8tFAD!>Xl`+hbZQrNgUd z3+-=;jJP#kS+7_U%}==bgvQ7f&`}mB^$YIcoXZH~Yl{h>+ufXS9MVP-=1zEjU`RK?~ zCuJ4(PT&xv3dO#YoLEcLQaDM}tY)*7m~A~-&Jq2=9FmzJJsk0-z98Y~&W2G!smCWV z%Xx(lqhTm8SY_l59_RixWD9K2Pd60F%wK5}nCowg?~T~?Q3+BmHw_;vE|8F%@5B?B z&=E-j)PzEjpBhJ<7^v=O^_9Y}UV0rRG7c-Mho;Me=vfUE-{6g#^DWK9tC)V4zgMch z%Bi8(5iV}O^sV_pauz@!M$=x0Xht9T6X@tdPa03Lkm&G^li?ed|7)n|&pZdSzBa(l z>f_qupd`a12y=KguB|ZM*$olcsOc3|A-WYP(R*14il%?Q{(MJ>S}MUgt+(*k<#+Si zu9$(5`nmA|MMjm9T_;8e@2jMe?lyl<%EXFqU2A=2b^*k~;R0$nZc}d{smDL9I-UUM z5>RDsxvEfIkLOBOPfVFy_vg;xIl`0ZhW!4+b3fI9HWHHl`jPcni7x;oR;=^N*75l{ zI(F&d@>s;`Zy&;X?&P4zW#%QAGwI>q4zs05rCW&LgW2C*qHYzq!I<6K<&(45HJdMZ zH?ONqvkcvCyHQF$95-8?6rss&G{A_a*7>i)bYm*GK2+O+H$XANC)a z(RNRI)W1u=SlgY5w)4t)TAITlh{89oRysdZ+)Su$JnGgVOc!Ov>ncoVcxR|vP4@K? zDue&Jh^F;ir>@y+Z|OmUkEq4x7Ctau>l-KRDm%UNxG^D8tx6QJPOl&PQIM@K&re;b zs@b2g)N9LHjQ-WI->`LO6MkLhj_ziX#=~-MmtMa#{Vn_&kEzL=YqrVPrP{E!g0v%t zo<41p7ON*k@c!GdSUXFPW?ClmwG?FFZHAOn zzRXRg+(f&Iyj+2Q=~sq`Il{?-UxbkyG178Z7K>&=kf^g9rgo+w>xgGIflJ28k#H8D zl)f{8!me1rJ%GM=!Tzh+{RwlPxYDe_CsOJ7Xh|-uo0fAQUCqetrn&HDpRuxiw0l8( zwIRq|y1#^kFLvWegCtzOCMz_xq|v~6Gz3n;N8KI(<;(PaJbodEJrS5~TW??eczHh- z*!e3Z_cAr@r0&8{ldG%-4@<)ma)OrMK)5Lm)64>mJxJ(&5FZ!EE__Dj zg(BJoxV0n~NXcs+TIwoKYC6eFAHuN|+0IBbhsW<7da)0O=}q*jx4pHyskJ-sbCvNE z!K1;YnbEDhwY_oV@$R9mF$IXOzKK9n`Qj{Tl>!hc2MwuH+}lM=`z;^QcSToAN&%YU zb#xOWORiAqQ;fAd9C0R-xH4ajR~;bny4OOuAo9x;&r1_ zYR!%HhEO!ke*nm+vN}~)+ezfig4@pL`h{@SEJ*mK zX!$(&_ijA>?`B+^-!ZMoNKb(tBBslc0r{`3!2p_Gw%m+M27vV_b3VVaI7*G4nz^Ln zFjdOwfzR#~aA^2RzEHY2B1yjfcP!58gim0>ETGWD z4`+>ICHE)>U}5|80~z4z{_~#vKQ!N3*0i>G{(@GG7L^#RW}#g9Q~S|bc7t`cL&S1; z9M&q*zW`qH=VyFKtEl82OkOC)yLg$%p|U_Xho!yH`c2+{1i%jnT)_~00k*NSK2QT$HYQE|dk!#Kb@r)&Q{w=<-0s9}9 zP^9HGsJr~Z0=U)RjO%w%|M4=4YUluquq*}@rTI57PYDpXISe`CzkEpKMgVO@Gug(Y zmQ&1EiIKQe)K0Vq0udXXU>;fO|598WQ~ae~z)@lTioAew97*=y(4Pb>0?#YTsgr02 zwZ@!Fpp}wu|V(2D_B0 znbiJtJU4V%quMY&Ry!M6dCz7Iw3%Is3s&8>`-Rk;MV<^nlKbB<@Bpe$kCQ{2g-Ihx zX{~{MpCb{fTyu#;2?|Fjf%q=ftkh2+HV&X{aS*>wPqRPJg;pTmD)O>l=&yO@I;0|g z#EG@KP%{a}g7zO$$XAm7--&kua3oNW?Efwp{%OwCeZvgJk$>HH&Ija+hpcpH#W(n^ z6@Pt^wmq`IvU^pksB=JHD(I=nd&IzJk8mnv7t>{!gJiNJ5Dd6e>a}9=nOCc4H#NZ@ zOR@mCskB3T(uGWmbBHz*PwuX@WL!@tjzbm7M)EZQV&92ynfuLR?$qWJxvmkz zbJ#7(d&EbX`Hk-({fi1y42oe-jyUhD+Ks;!v7^i&1LQ1o>U|#2->n;LCy%&3EUMO<~)s z#j5bXP=Nv&jRMSqs+8u&4+>usEJbCVbNQ1ZH3S-{jru->9qezfQ2|@||7r{}MIf-& z{zllXa{*er>9Id0?x*JUiTR6)X`crzANgd~-wP$} z=@9%B>036wu6k)rb4phDcRpaS;Y|ni5K>@opeL&92=zg0TV<-iZjq_SW zL+(9~6|5k_n`~&8N%2R%llP{E8Ipd7Qp<+gS?O2u%#p*Qdb4yxJkj!vr@RyYtTqdPE9_OgjW_VeYpAd7Qu3S0*&II@{w)YNFj#) zsqDrqtVwUKK$;(Ymb6Hg%aKGAVSu}#I6t>WZ?KhZDKeogJ^kUXK!YEyy&OyF2$i3P)5)64o4BNfbTs=Om)C1hIPQHbd%= zYpsQ%nz4T#4%Qbg|4|Ti0vEs0V<+t+JftQDz-s3i3!V-a338ph|INXjfWd#SP6u0w zWw`=ZnopA4?=ZfUW%0URYf`B#B?iX{{!|*uZg~^ux7Tc-RH{&f+-F@iSI;TC>=$jUh%;FIhilzX0WlXw; zSy@z$^gk8^HPJ2m#!)nj*3(ikCe97E7waetqfG=o)Zn|YG5@o(X9w)cUKD8+|1}VtD>r?t+-8oVCGHq8#uZru7TXpn7 zQGzG!dE3}TzNfC-Z9`Z3_NFJ|lxC^X9uK%r9`%X33x(7L&*Sa3aOBk$g@d@{Dh8@A z-=&a0qpewx`U=5*F5eECN^LjWaRoFYoO@*rHf_q8EpD%h$cm{N|41r+1MO#RTS+KF z`+qs|lrAVpi_ z?DK{LzimFgG`Bb@qi&wCddDtl6=g*Xp>tD}oUTcJRp8S4!_s1ivDcNF=K=l2VD;+9 zDUtncOk;pP2cIWH;7g4%1u$XL3kmhLckhy^A#6&pB*IO>p7@n*%1@fMjX(FdANgrs^Xn)e_DTO&}J(%e`s0Wj{8-t1j2zJ5XT&t=g zs}4aCq3{yVn9$|7(MK)i6G;*!%em`%#Y1hmc*ZxJaaS!i$mapHn|>lt`s3y7Oag?G z`?L((|6h<&NRdvE+6EbFCXmjVwD)u=C8$3h_mt)z(DKsqFe;w?2zu9pL7yHjD)o9;%sJEWz%8wn}t?(UTC=3CqMJ?C7%&%eaW&02fT zHRqb+8TWVwOU6VRmUi54!UVN38}6iwE_E4K}$S6wu1cYt3dYQ8XpXT2 z-%2{gv+$p5;!zojKdCHyW{;G&o6%>UC{V7#fs6)nE6L~sk6$dXiQ;DZ%wI}R#Ms%`C*GJ4mr~>_33EG7N zD6h#lbN9X$xykBtFrrwxC;k3SWj0YWWY0b5bx?0OS8=={w4&!~8OC8sp0igsB2Y;V3|T}vF` zcI@@n=0=6h5uh7;Pme@hu&49bJ+{B2i~yXh^o;YK&pj3#!V_20$s*~{@6+zgofGRV zq+{p7cY2%MZ*WXFN5ouZekL~+N_4>-g+AO^OpKPaGiWuhBsSEXeIijdd* z%wM1slFJ{a6dSC)U1$=9kz08lT~S&ZpIPdVlF)qO>dK&fL6w^B0=%+J`~OadB7fDZ zR36Ejcajv{^s%{)A4Pa|t43Sgb@c}L?Y4sn=om2Y4TM8O%cF~DYuV_Px;vGmZ#92^ zOf%}=(5&QYm(`K@iHSTn zVnBODELd1|F3#91GMf4asnF5;%Uyg5CXh%xsG(>URN`|>zd22nXQ8ESy8KoEMt%te zC`)^ayoizqBhRnvWBaWhI4S zZ2a7?K@p#0vBHNpl2>t+v#}B1V>cQk=Q5vf=!s60k-%6MK%>eNoI-&@i}vBcx#{fwE?#*c6>?X%UqM62HTU z!?89PAdH}3g^*0l$#buwQ9$CZ=30Vhgzr~>pU}=j{S5%upkZsFpc+msIoE|Rk%%e# z>9mN*g3vF2IG0oR31>o1(GinC(75-MXVMDTF96Z1yn<;&^C{(DXPRGcd7*rGZ@J@6 zwXgS`gxJ`#6YOy<{CkO&RpPxByYjEM-agAd|6sXl=~AqEhLpkJQWdBdKS zQ!_X+0HW$=NVJB}e;pVDiM+&4P-cAq2sC#k%vlb&cl;cje?ABVhK(Np=MR#$tIHav zI1o^#BF46zFYt?>)zv1hrAg;PsQ0UpGu1pxq*`@hC6ZM4-l>dCT zcnO%$HkQA{Y~jsDIwoKl_Iq#rs(|I6vo?_o)GtOpB91?n@#jdAhDdH>KPTKZt$<5G z<|2Bp6$-dC%52vkc|-I))X0^j%ci?}MSu}tVPSa%E%bJ+0}g5l=7BxuG!% zA-$Fn`|h&m06d=npUa~G;sxSU0FJu=Li=EwcZI*^&ZqSC_og4-R!N4%Zx60KT&FrB zp&R%}n*Q@TsmzLz@-K}D{ERS9ui3Ew))+({ArIA;MGoB5btga{#a0x)O2mz!7hrKCdCH(Dbz^AJQ26uMfy5fH7C*&fCsEs-$1)-|_((2cg^C6-bPe zgvejd9|?Az8|>OE*HH~StT|$x%X>N(23Rj?Os^JTjbUjQHk<>LXcU)PnpzCzo(@2qH z^z)`zj~6EIBO1Obyym9>PKMujeRJ}gLjx@rs6vN>D<$xVZm)28K}0HhRw^ z+ZX7&PUf76)x{NdUW*7Y6Uye3FcSV8JVW-t6@4fjF=f&>aj8?a804TVrONx;n2c8Pv zV?6ug!+Aq^_+hhwV2AW*30nU+qn zDpt2EF^8qZJ(mU6zQ~%KA}tfc8fU5Y4bfu5ZcF+d^AC{5;=f z<^jlR^5aW>VnTvhD{hm!*TGUAJqOU!u0`;9o2APEmnEg^M=l20r?}5WI?zx)%D~ft ze$3p_VhC;a@kew%EFH-e=4~1>(*?`)h5Cz*ibHKMT5uj76EWjRGWEQDs)MM!5p713 zcIb7v-tZNVz2@VEQEIlKN=}AFTPy@m)L^gYlo7UcTnZ{lrPM*JxlG&9+t2Jhi%tyuUvk6HlYWg~V z0TU+K{;cUZ(^*fw@xZ$QN24)WJvs!&`NQs&M`_Nw*PCdHUVGZuLxbaLmMP}yxVvS? z-4!~-f|RNGD>28qbVj~fmi^aKk8&e}NJT0E3kM160TWf=dy^X4Gd{?AfqqJ!0}xuh z^rwv)dH(C$_1}-P{d||G z@m=`NaCy#drMHW4a6Jd_Zgz%V6l$g^kmzD6{iF6|o~erbUujA~S(fE6j3 zgL4m5sZ__>+u~&vIX5p0$${WesuIqc0D+=E=h+=K4MTC4Q`6DiS7vM)Vcs4FBNszd zv}VR~6a1GEFgbY^_R>n_8Pw^{9k6Dme|VK$Cv6C{Vx|%Ze`a$Z^<%|px)nNa64m5K9Sn5CPPcu8j_JZa8{?17nUMs4_eUoa;CDJXzezxICY?!Fg3AG ztI)9?;8#D|+8_PH(RMo*w%8#+IvqUk z26*lIoY5X4rPT>EW8m1T~sS#)3{DX-kmYG(mzCVT+KKLRaf5(UW1_P`gM~;S6RNF1u2W*<$FZ? z-G}F%5FsPv#)CbbizRj^e(DvJ@q=Q$5?vw~R^STL1jwe{Oq81i zP0`GGwcK1-jmc@XX`cgax|F6rRk&2$PFX9n@&uZG2DMa8kFyD})cYnf*nUpleAs!I zM}vZVl%$dmYEce5$81H_YxlG#rvttN?;Df^K*(f@Ptj2qQ*;{mg0sbTk|Svk)!&Eq zzQulI>Am;(Z9XIU>vD3{s5Ik;;7K^4t9c!_5h8DNoc)BvK*^zPn9F0>u~udh>ld$J z0KgZAJH{hmveC?Ji;}rF{4--&sH3j_FulMm_;QFjMFL)J%X2g^&{}XDD9|giFzhbN zx!yh=Pbs^1FuG2%c+=~&Kf`Ev{tj?Dgu)?iD}}$C`kJj$g`4vwM)Vv@bHe0Fjh*+* zC0`mJPkzT*wB{`#n94~`NR&6Jcz1x2>3xz5Pfa`X!@8mRc*bbaMLAGbkuGLQDLLek+z4AKwZ4<@Kq(QQ&qzV#{6Vm~h5%2R; zOY+`~O0DBa?H6i%^JmbYhHbDc9R>~UThV4IB3Z28ca=EF>K)zVE8Sw*Gh0mI(=}m{ z!)lt#Nk2RnE{^H5RhI;UxF0Aq6$ct~dN$+9r9%tt1=;qbc}D*x;U+p*&caWGjCA&!_U6B;)rp z1gdSx2A^DA-@^dmT^P#YWR_gZC{zud8pAOmdse(#h8=0Kn=>bz{BbuPCn)V}P2@1*giN*6RhWF?9H|_ASdj?d+ll*=xPyDdswqEvqPhrOFFt1v| z{X$fe9f#CHNuN?~hyJsuP(I;_xOhZbeB}L)r3P%XC={vc7-PA5hl6DaozyuayvdC;)F{@glsVCF%Is+gj>J&m){+^Z1b{6CXylFoXQ>}yX` zCyML^tGZ#n2LkTsZh8?g1Q=t=D)(3IcK6Dovfc--M<+!ldf6)xvL4QD1ECy%!!_9jM-#Bsbu22cQo4vU9wxGZe-%7T94`l%8I5g_p>!O`aLHX_QY&Rwj;-h)LE$8F-GBC zCr97s0wI>qUQDb>D%(6e&n$b;fpo~_G(9$M$rWa}z zE6*UgL?&L}6d2kNmn$|*&?;qZH5n8NdS^Zw7G19tx2c(y9(J2T^4T$ye~kQZei~+> zWBlgaD@kwW20+10y=hySvwi}tlKo}Z_m$bh!y_-L45kE{ge@%@uM`w!e*;lgNDqh8 z$pQuj#vP=Z2^mP?!a$PK&Zm}4q%FQ!hVSFi&9;1|FQ&+c_ukmI(j|czn-6gH@4St* z#(P_jwKh!s3Q*;B^wK!P78IoGe`vkd-W57bZ)2-amwKCu#yl_I6vAkyhMQ5)_8%>P zVuMdDt%23=fUWn+&B|he8>4H}lu_HSi{fcRvbZ|-nbNu7k&$|zh<3!*)OAC4GB>B2 zWrx+S#Twk^S#fr#{Q(fn>?WS#N4X7yQ?%|E2XTgOj+;ofdXOSX0P!DIg!naRu-Tp8 z^C{%vJM*{ga!1c#j4Hx>-ur`hMh)(x05jJJP3F-H!pxW`5s%lx%2RbBzLL&r1b zW@g?BoD%GL>Y?ssMesXwS$X%2Dy`z3x!z8K5y)gIZ)iHqZqtV%j4Bl`r@3aS{YR%F zVvWc|3VWHT{%|frO`$D?4f+QZdFeE$Vz|B8NI5uA%`9hNW^UczS-iiL)IFU^Yjt-b zXZ}q19ul+ZQVhTl03DD&ZWisvF4hU!ZP|o<$E9nGDEO!LEapVPeOT6I(T%B?UfMQB zS(nH?oc(_;1AdkFZxp*OP_C1dA)?n|8}-4=%80=zttN zfy$|OIF5&N0Rz(<)A;RrK~Tf*quc*VPlSEJ+uXKnXgxiFoeB4p-NoU-1$qt9r1<`_ zBAhTFWS-EgBa%C|6MB0JlC&`X!%Jezq1@*5-0 z`YTd>-e3DMSGOsCFYFTywFLoSJ@~E_T%;>;>1gYYQnL8A^Sh0`BVL zAkI;{t3vc7tMEgJ%tpc`c3sX44PjG2Rj*9ZA-bT0|6DaU)Tb{{7aT3FqJvxz=t3vL)=0pY ztYpbjFM}h&_m6l5MEO9smAOI%37AwF_4uYpG2elTB)d<99Dq?quKK!? zVIh*5Rumuu0`=OPJc|GP*plXhsPNZO%bt(@O1^9!8Q(Gp|@3YOugvfyQ=-vvnlE4J? zzf}o-Kz9YWpy!1UJ{XA1H{q@v0Tb>6Fbm&MA!==7P*lyU#6{!Ce?G{M!ElZQxjQL9 zplj8?0{;3SDh~&ET)~6`(&NYfCiHG7`Z&szMt$E@_p%DD45$u=DP=>KRjcA!vr~GzC8ZY zu)iAUr%&Zz)p|l#U||5xW}vS`&au&qgi8qW5w7{;X$aK={3!OpHwWV%j>Wg8auN= ze7(fNrc5LM?x!jjHl4zz6}XB^IGtjS92Pxnj+tQk?KKxZRJaV{Kl3n?ohAna0=DOW zMdmftoKc^<-sF&pWFL<7H^o35Ht%$pE@Y0x(LfftdP_vI^;eyG<(@(tZJL$veLKRf z9u2-!PfF%bc6wWo+B-=82MUU0FH0pz0QwL6T27nn$M;CDzC3kv1VvhFemJWU?hOr# zN?*TF@P7i$tTx8}xhe1eE)u|qyyb!o&i&n)aVAP+hsF`TdrulKwTZF2-1w== zB(EemC<1-`ELbTeF}rtrLY1~EAmYqz`YpGiQJad8)b7=b{h2wOI9rKW6>d9;s`n}r z`ZY3V2G8ZViFSODLFvwIG@@B$ln|Yqgj48QxGP&&0F=yLHS*|w*Mp$&?|eX` zLDW}XNU4a&@rM%AswwCmBTL-xZh`SGoF&vUxej%82@M5C2 z<+B`8e1OOArMC2Bis^Y=TG+hIV4AZ-~%8D>;DX(K(qu-SH`9+Un7m_t#U^%DMP_kO7{c%zE+<=Z6R?n>!K|}I>e@!}I?I2mEwqeSYa_S=30n#@z{L&sPb}K5`_d^de zJLCC}6#Wlz4RRBMH{k=w700Tv7x|_7cDoD0GgI1krpV^NKa9NTy_g^`lk^ODil+@T zW3x~x=CD5U47*(sbuJ&2ZnA^Ma0)4UEF3Cg!#-ozh`T>^!In>N7Dz7wy(;{T^ivZ&)!htH`Qo)MCxxk$=LLbEv0VYpNdQt)l>Muc?pGxSu3RvG0$;z?%+(v;#ZKr;%9$R#c_V)i z>mM4)sJPkB$dtwSp|qAxW<=DTIf;DXPand(obf$S(6q4X7;YA7=3@O?>X0@0I%Q?f zi3e|#-J_6EOc}vhFLG{dhV2ggfl*D&MuCT8TuUjfB*WsYifkc1v+!~Sy^R00uSu3G z!Ehp&1Tl2!u%9XctyqsX-GMUogL0H^XIPA6Hib-+8&l^+x!gkgb@}pP587nX$M~O4 zA%^|?xwQ_e69?ej^iqfI8Z?o4Znoh8Jt~ym3IBw5M@btogIrFng|jY2BK&%MZ8#U- zfAlzCrzEF-j5DhrYBdGwB2qp3ja?e;IOxnj-epyq$pZ4)RuC2OAB|y2w1fd=YXe6z zUZ<0k{sntdGWA}oS2@ujyCe}62R`Mb=eB&>?zvZr2{o9LQaUO(#5j2iW%Q&5bXXr@#uBNETvw!0We(DyBx>LeFj zHfkvcKaMtbo8|7V-NTSEz3E|rtOIBBPex*m#l$Eq{qCcJrM{rsWBK&-pHzN?()ixs zJqCUS_UByxFJuJtz-=D8Dt>IFXsyM%9fcu}Y6YrS01`&j>KY_$KFc*Jf1E~}__5pucAfNn!@MCzX770kVox(7H$^8bwQuy%QTC<6iO^renO zsQ7#~j#BkiQ+d$D5v)-T-&UCF5z2JhrGn_= zRPW~~BS$iARxx>~C?sGw$Eyrj6eQxFJ@aX&^l~zW>~!X8-D|7&_eSsurT)R zYX~9KFG7zrX{1gm{t@-IPCTCIt9PzVdqr%$qwk1!OM+Iou}UHwN@Mb@2smSMxh**x zn2qTZubM4F@)g%zR(g8J*5;KSOdsaCUjm6LE#GGsY~+Kq_nhWG-vOix4y&79E% z73RiZ-Isq#EINGUj{}D&TaBVDtZ>5@wQ`+b;SsC+62Jj0)bZhfU7MH&L_VAWo($q^ zz{(qbM>#ajEAZCBhQzSH{&pne-hkpPpH_+Q5Njm#x?*_Cb_bihgu}Ymf%4he&c!w1 zWgO(0HX_wI^mArAZ%KNx#_^k-ecg4-VTv2Mc7sPQRR#p>F>WNQ=lzg+ibC zX}qS=%IR)m&Mn%n;15yBYDO3rId_UCM~W*>#eO{E0OEKd&LDA`AxFWNm~y$T96_X% z^GFg-;;lWFuhD()Lg*xaQxocUE4ehO;DoV{HP6|!K7QGD+qTSA+t_HhLWw_9e7@BK zi=wIZwD(tIwd=JBA#SeE1klYp-h7sZYFEvHLWESb*ctbvm{303w_etEds1m3vzm%* zMd4%onk{VIp=z<@$Jy@CeLL86q41ui(3M04l|ovVGUqO5kP&5+3-_UaKRP~MN5D;L zdC^-KAohXMTvv6+j+=mh0>bMrNBUp|vZhT@+Lyc4tt}C4@D1DDVxHTlSMaqdzb53h z>`jd)7DoIE5L`a`X)`}3&kxq2iCHdCi2CPrb{ceipqQ4=&IjsG{vtMS{y}W2)GOvg zEQ-+HNo+V**IA|#5Q(L5%>TecdB@K<-wE{fEdp)Q`yff$SC*1|%)|C_w?#((>r+ME zT}=Un4)sM>zJ)WsMBB4hXzc(VMlgL?Zxrt_HyOxoeX0-3%BQEE-Nx?lyyybQx zX7h>TwOe~U7z)v!9E#-E-^dIta|csz`>m{rFFS`yEUY^7a+r_2NzE)~sX*io&}A3# z&3yO6XEv(E+)>nFnVJFhm>b1K(#dacaKulR@dy+m0P`m|=3>QvJ9$AoIUZ5eS`8>1 zsR~uCe+`D69M*BqO%V83FQ-TJ49Z>opuq3@Cd|3C)Q>=^{UbVJ-i7;`5D3LLL6Dk` zU+=Jhrc0lm|8@3YSc|AkdjX10@aH$bEK({ zgA6GPA>5gM1qC(sYY@D#f=jQ4E;LuE;EP->`4ecw%*h!K1w{X5!o%7CKh&9zw%n!s zQvvobPj@&F0elY5BUu)S%;~3WC}xdpp5bRgwpRe}GPY<*gjxX)IV&UFe;Ho{Gyt>~ z09HYQT#)#$h-rHGiTddbZgy5hqm!&D{6mGK>U&a1@y3d8*MTKx8(d2@rkRu-zzzY1 zZ)j50ESc~?C@)*#tX>Vh^iPEeq;(yo$4{k*VLg3)eGF_2CO0&ZBp4vnrqO1=mLk0u z{wuMNaN#7!maPDi$2@Vh`hPH8zAq?%`atNBDt+i=P*RQ*6^uoQoGlFv)TzXGb#_`_ z`Bx(WvI7uzFX?PmR(|-20>t@(po)J3b|9eqjCSaN#`1Ut=jiCztw%VWt=b1vRxgpv zGi?C{uHdf>LMWuEgjQ6Lau?WGu%ZJ13RM$t6`C?jalYynd94XKblv`fIGueHze)~D z(6hAERRM{BK&9|O7awsjIWgb)y{V?QbJ1{d0I4`yG6EU{&@UNMlajghK^hm}$pjO? zEqG;T;o!B=e=$cJYbYqIZ=NZNrUjoxKqB*ZIV`UvgPo~@rEoye%LC&q<3P>!dd#|G z-S2X0aJ`BQ(DT?u#AUw;27tX#NVGLwH8n(lUkzMIo1Jlf078Eif#@%Q3Y34fmv8^n zeh8!%UTZi-o-U}ug8tyl%Sdtd)~DLS{(#tuL!;TK!2qI0m`-*HEj?Yy zhQX%PC{C^UV%SWXIs6;ezL9Nz7Yk8U9wRwX(L7`)o><0uQE-0~V8#~RN~$g7YNV+H zW&plJK6NS`tqm>K-TxX~j(#*r=wJ?iTBbjhKUyP2e!j!xLX1RwHii)GFp zUve2<;#$%@VR7q@ME_ej1L{jc5>C$gEumK|XOfsT$p=)RoS@#Go_`5NsOaH=eq(@d z1LUcE#(Amq=;1PiA7l)ybaIItCo#BYi-Q_)%?RwPdsA$OTNrSs9ALtqo2%z_c+1PZ z&4LJD?reF!S*O8!*?;W*{d-#1F5;*FXs-xm6Y0OT;+WS9z#{2~y$kJ;c_A}zEuJS{ zoP>&ti-G(wiHfS8Q@O0cNnf8vYT1l&h2hT-0>nO2s-S?Nx?oETOhRQv&G(aJzYVI! z#9DM`=_WbaFD;SC#QooWCet=j4a2TNQU$(*8Yl$J!h(ebnJG16kOklt13Y|j z1IHzb8@}Kb(kZvFjt-1qD8wL`gSEo;%LO-JJA`5ycR@r{v(P=$XEJS6P*xTewh;1g zoNj7fNSU#8qw019wkA}xu+BLlcOs-JHfdiHa5<@^dq6;dxTvVOxM)vLkGQB9(9T!M z$iqX&NLAG+?^0Kzh(}CgG(Mj(h!79!ka=8LDY`r*t}KrutNEZ*ratmhy#l2+JGr)q zgC!wkW2eHWpC=>FKER#-@b^dU+C_7f82sJkPg%QbNaBEy{EwAySE`PXj_b$m^wRf1 zclu-pJt=rv7@1KaSto#1a9#WK)YMmL5C{~uXKJAWVyO2w>};lRX@J9b?-wF-)Ij$m zk{%yuN?k-xU-^v9PqY;Kv{?l>m>2yXGHS{ZNqYOFm~w$P@!JUK|MUHgJE76t&im2M zn*}3$FaH_~6@yI_Q`rTeF;`l$G`2ndmd%T-(jL&n^Xh<7`)BKj8gr>-eRFUy(l`~b z`!U~m>7oHiQt-g5X`PrOnIoQs2s|8|{(iL+%<3W>=`=wk20@q%I-(k$c>)^$aIX2H zJlgrfk#fBV?P^lt1qU-5DNb1a+y)NOlSuHPOg>1MO2n=aZKVHq%`3$h(uF$923rA) z5OB9mN$0#xyWOsF$>5HWI zC|Osju;7PXdIhs*eH-&rFzY8B*W!pv7`rj6R7N)_X_%g!9dFAoPBHh7UNRRm z=S?-8RvJwR1dE7sW=Ep{YB3!h{rs=xLQ~>c6dFX(1^&G6f$alNEpLpjKQ=XK^pOF7 zHwg-CA*iIVu(Z4ks8eP|U5)O`w`@taN_OY72}W7{^m%;^2^slhs%fw)2fh|v#0MP? zP}YHpH0maQnh3TgCKV5Y0UzxQVzUIDE_0*#A+zay#q`%qGVL9PDd^7Toi1cpBXgDF z7ZM@DH8K$cg!8!)-@u;%NIQDi8VWEMeMBIRll3K^pF$}B-c#ahAGtd_I|HK{%K*xN z-z{H6MC5R#X>;|(0~T5cT>%ViUTc<20 z%9t^-6V1eJpJgaMk$mK4YN|ciWXmY8sCe1+ZE|-y!Q*!#Q1!YwLfEo+L%XoZ z_=~lY;x1C0pU|QD5Ki%Zz&=zyO^6-j)xaSi|MmRP1`8WJH^~|Sf%6g%6=3o{8KsVN zf*=YKp{p*p;0vTd%8ze`k?|3vBVTom0qb>(c7l7BMfD!Ao^Zv}y z+5Tv$egh|v@j~2kr@uM9FNNH6BiK3%vOB*}` zqB?Qx19otiuZG6^=`8+q>@fvobaXD>;4pC`F`hb2vKTIpKuf`K*1toD>$!&8mW@9ED9JkG`u~+R$wFbhlIi1xL`F_Rbb}o{3DU!@Fm=+hoohu^G ziBUG9iU>kB`0tv#4FuosrMYqqmBkdykRtA^MYkI}oM8~Ym+Zo>szP`wClqW0JOu^V z*T*52f`i}5w?+K$G==XDe)7oR|rcj^LY zzFP~Q7Xq#bVMH{YriN){-h5E$$3e^e>d)dJD5aSE;>eEStrI=GrT`eEqy6uuGQj7T z@P{79n0(e~7#bEf0DK=GxZLdIyi^CUx|`II`do*5c((gn#7EHEbc(NF=>Kz9(cr-LY(q)mH;5;JCS6=YPF}BH zvm*jWC|6s>bu4u~%%2;=bokd9k4Lwm+b6WCv&%MGgE)lS1O!QK?4yjH_|_W;}ox{1)XCr_bt`3Mft;{JGpv9EuHYNnNGw;W*X(*mEs% zHEQObl^}-mFffr(`{?m2?>R!GvYZYxs}v!bnc1unlh$5iiFnkzgWFHy=NLaipkaX| zC)$@G>I^0hx`vu={b5ojJQIocCVwd8vSovkNgEkqaX&767o_#n4wq%1b}}%gMD6Wf z{~(-{x6TdjSYX@=1uvM&l=*<6fxh>@Ag|R&xQ+gjuw?13ZmDbMuNwnHa9MmFex1HB zZ}hzrJRj%A|5!ISdG^YUfZxW&_6nW`+3${cT}>wyhA0A|kCu{Dz_{V@pjI;&@X-}` zauJmqxk2M&&pN#{J0NfcR_#oM_MZazLVt=MNQh8;J`L}CGzuoPrpilVhY{uv=rs%s z{38TAQxg`5Nq&5B`FKo(&T?dHx6nmPVc=x5*}vl=2f!Mp|9$dsiP2fjkj;i$sqrl{ z`d9T>xS(*?#*t8`)#on|zjXqi40W~GVcPn3_IS&yIEGifKTX-tC zAL>gg#sF7NJ=)e2?^6tlQSJA@?tW!EH9g%15a&@???{H#RZ>QJzt!;=ge!L zLN+0aX5{|wL-6C4%^`nqL z)@Oz14&Sc3uV2@JV~viRX6A@)^A7QV_TzPX7&5Y=vacJHR)g8a`h&D}+jc!*9~xi> zylF2BIC88a0gq=fA1c@_C8%Hgc(Kwh_Ti=<(fKZHC4`+E>i{E#w+~d7KA)g%>$htq zt?p6RP9vajK=vQ=ByU)Kd^CqqAJo6A^7-`{)|^dmluXak zJd*Rmw$BS4T%}PubKBV1n3B@0^|LHnlpw@f6^AgwaP#QvI=25&aAh<)az&q+smXMu zXbj_=!EC=>FoRRK5ijzqYD0=6%4(EE5JN9X&_;`vrX;K<^Jk4n@l>Lxc@#4RkSyK@ zr$nNx0v2*)F^1e>oZO^4I4v)EjYZX%riiIMTQ}W6g|-G<{A0HD2uF%upRG%D4ofG4 zsyz_rN&>*Wb{YZN{9G;TZ#%xw@HyV1claB<)w_EXL@0=b;FuG^q*uIj;XyKqn~FyJ zR?73nd}^4X@xgQP>=JxijDkk-+%q1{@|K?s;=;2U$R?H)SzJQ;CY`I6GU-A6Y=r~n zh-KVWZVa5=Imj_TFL5V*ss#97GFt_qqqDhhU)GD^byem>;{zJeW8f1u6~EnlMvuS! z#O~5nkQ=dbFJ+pE%-&L6y8T zj{$vzV~px^l5~QfCK~1*QF3YSPKoK$I*bV?dj+Pv)!On)tTkCB`?kJNldaoJ_H zV9TRMCbSx|l=o+914G*>NO|^76n3%PD{Yv(5%tmo^V$i0@^&9rKA;Tf`$n3j(`C?U zVQc7OF7S`1O)}G@vuAnZ@b?tu+KZ~sbV!Z(y_EFEA$xxe;oFMI%=OT`vprwiqOLTD z9}PyQ5`2~d>NPQna$l-d&ck^m>7=di6D=$ZCI56pp?NrbI(pFXm@6u+bH6!G=XHMG z>q1+#HlHaYYF4At6H?5uXShq7)PElu82-lLn($tRCM%cw9p&9w@54*ek*wmz90zUh zcfxSgMro+=*so3$KVeB}z0Qvu7C3<_grrcQY8VR(i`eUSy*x@=^`*nWx(4i~epoDc z_{*!xyPds&Mz&effvHQNy{7jh?YF#aL0s<%=sum#tAM?Yt1Uq;xtI9@3{==;s>953&ia+#0=~96fZu$ZUM?{4s2ZGv0qSrDoMUvAt~gTyXCU&G@oRj?P}!b}Vk> z^Q7Pxvq{0|e&!3J8@189Xlt*QeF7P8z4ZoreXQunT)wl5Ggat)i2=;jDWmj{j>i;e zf0pio$p_r=b#G;fTa0vWB6-W5?d_HAFNprAobg*B)>+Nb6-JOx)5@~GguXU&DlPKHGG`4$&X_wIO3eRMuON@)w!3M2lBLcdi{vXltV{Z6t*1Y8 zS|R5yi2iV`*~OH{*20+;(9O)R?=M>r4v>|T%*d&K@9olP&S606=hA7b*PjkQ;s%eF zn=a3jmW$^Z-3WZ%B*!A|YJK}jadD#gx?&S~!d@^oi*nyoGlmN?@ z)_c_vReZfkfBP08knE)nB+h`?$%!PK#zQ(HFC^5#h5vPHJtGS5`q;g}z2P8AaHU{t zMcyOZS=g|vmza3!h`ek@_xlYMY^0vH`cNgSwj>Pubo~8m*qM+Faku@U8UWNdNuwwNIhQ?}XFxWNN>X9JOSjp(3x? zL^atig(Ly~m{uK@M!cB;L9eiJ4XnBT9MSSaU70?VN9WeW!cJ0Mp-%k+A zVKYyb_fT9g3Sd&$b$pI@T(bMr@NMMJBSt*_NAcyU7W>s_v`B`NR_~W@E2{jk*8L>T zrfW2`6cO-Hgt4W{pR{KsJONMVaLnb~_Uh_RQ!caPW%a}5#r<^Mffh~sdx9}jcDx9& zobmBJv};ZxAkovL?5s#dPv6|cW%#^U^Fy2KVn&V{2DOR9<}~t?49z&~=Lq;dp<^7* zxAyg;}N^)Lllcc-{XtbKZvKgd^l46Kb}!BFP)i5q|;cSJIqYsS%Zo zozAN-CQ$?OUYFxR;>63#o={S=ze$Z|R{Q7`4-p~{yHbIcjKn3ZdUheWIT8`RD5s*e zwW%LJIl}iz1)9HY?DJN<^nQ_6q%vwK*G(OaI(!^qs`Acswb;G<5X{bxc6)ozXU51t zn6UIyj%O3`p$y)e8UCtVdE^$ljqcW65CDSkqshmVr$q;+)UTF$gl737;S3*2^A*cje-rzC@28Z^ zW(OXFmv2#MsJINzbzPH)MtXje5j($_byr&j!{|J3GNSB$%b)Y_im~rMjOq=%*LNL3 zi8&uuQ@E!!Vcrg};M)zX9F0H|SaNjep++O%8_R16b2r>EYlj`dk6B4a`dG~zt$*mDuWN>|Z0x)+#O1}PHR78{mAVEiC4pQ182Wc`oaUbO7{ethbeCp$8O1JfJ-}a z(Q(vfpgs5Tu=gn^DkYci@w5x|hWMk!xBqAXEioJICVt@#A6r^Vo-L9R+J|yaIc??| zer4bmYXfEDgDI<+=!A&w*XH~-pEz3$Jued)FP|iZ+=vxKQfM&7f!1e*In6}4A0B@R zCL%*g$ZuD1JlwR^IiKiNB$r_cUj6KO*49+K``mDxz26FSz+Pf6wXngn^sKCy;prA{ zU_K&R6`F`q+zr~CAgv4C@Q8~{gwJf4xuZfeOa2j-n_%yOEJ+<}pYx0F$7V%B--*T` z)AsU5$B(xih{TOI=EjR+8~=~3ua1lA`N9SP=|<@WDG>vtySqU^L6j8fZUjl`lsu(oO{lhInQ%uZbFYjcw-O?p`+#o)9s}A z+0hElXksFc$~)Z@7}V7a1L0{Wv94rFts%F_!j~uTmkgiXvmI}CE}md+NuoV{#&JQl zal&af+Lsvar{6fvJmfMQs>DVstW5r~$mIe;YhuX!7Pr3^O9(0i`Mkboh@NSWQDk5t zis9koJ*#oKiP6IC`skDD;}vg}BA?0N;cq46>kVVX&(jT!#CK;)m5bFfD@eaKi6*#l zehq@5d2DR^&qx9~WMGXr`OA{(Q5&P@m_T~zt!-uv@QU<53BW2iaVLy%Wn7dfi1dwhzD*NmY<(i56U<6S+u^8 z_Q;wn>?w4f5xOH=8V_U1@6#{BBnVrD8@4_PV}5Md3V#@(LnHFBI>S+wcv#E`N2$^6 z*0QAW9ad*EU)8reW6c%EIfptg=gU3MQ}*_2&mcSDeRoZSe6td%{RE)E*)GaH*0+Jb zt;FFlu0xgl**)pA%F0S$2Iok+3Q?6H3cnqF1b+Onbh~ff)=KpJ87eWbMe|v{!V|eT z>)E={(ssfCjk0zas>J@jenMouTv6Y9bAqPvNqt(S!-(>?@;JOgnB0}MJVUO9hmlH@ zdCrrIp#1lqAkC2Vr>D_4z$Zx`INJKlPYHlie>Llp(m}*g?!~hUX55ahV~wq}nzwmd zDWc~ps3p-s@$ILfXQW3JqfJ-a_DM7-3q`^Lr<66TyyU8T62_vMdT#ug2qbXIx-0LL zrNBnpM+*MArnuTH$ZmOwHAK1*{RHrR&f@Aax8%zqwzWODYx+9x_YhL@c{1(U6~Ek& zwN~Ri+9g@-!tLqDpJ{3w7Tza(+ihIAXswI^VGCRWCkGrpXS(Xw<_f?wOYSb zDg(a!X-Z$^tBE4v#TipNgXJ8?*uw*3QOA`P=UF2AdPMkF`9kt1k~u zPw-U3tC%lI4hlE=nF@F~EPcQ{nTOodM}^KH4nQ4NyvS|OA%akLOP|SefYJ$9QVN@rC&ASr#O z1&WfR(!_OZJdI6{azEoB67yKz2Vs@HzPPKp2Gh*KGI`mOUY9QW`@-=sI`=~w_H#FL zE%4p$!bG19acD&Q++*aK+*wK@^!p?q@B=$C{-6-)qf9QoVWD=8SeEMr6~+toTD_Ds zyZ<8y^P7=9-MX-Z1S*YyUrq`1O;nho`og=Om08pv`M>_!`}14VQu@wR}A0HWj!AA^C3ufTAk3x z3Y$tIPiqtLXR!ov_gXw!UeNQTawBO>qV;uJ?i(QlK{Qn*bw85*qwP6pc;W(&uCNW! z?`D!}vEs-V^00YpYT=C=o_ycJ49zlbfOXca!qJzdZOmhW+ROS8`!$-8AdEizKuv3L zm-{-H^ZWr;Jypp)k=X0v#xUE|Lp%F0Ev9;+=o0VFOMdtqxT z|J8b-M@xz*%r z)igGewv%z)lkh9qK9;$6H9(}Cnqn~L{YAL$?@Gg9~=?KEtqXJ%lQBc{Y)b+b!?foQ9LiVevUU={>r50B{wR4iYJGN2XOY~WV7 zCXMH=c<_q-Eq?nxakn=v&?J9PhC_Q~X;llC-`*y*U1dX)>7Vwm!U-qv?wHrSRZj?D zAfR!->`>3pIQed44&xWfntPRanZqR7H(F9a@@c6!V}sM`n^bH~rOl|OysN0jlkKH? z9vonLG>;)Y@jp75Z}%RRkDCWS9&ar8v{X}L)VNC5-sjfF0l*I^Ikp=U_3q{8IU7Nu zihg01pBwyrgqITw_jO|vn#A=sUK!-uoPc;H+kN)dv*-!washi>$gQ^t*1V6|3Qx2# zN%l_Hc{wWmWe-1fHOIwA=#uD80MyLRL`4_3WuLyh7#SnUikuIos$#l zU(S1%ZT52eh(DAzSuHe$p0!QXD_oKiqOYLEl9Z;>mE60Jx3%!DCZsWO+hy;4g6^c9 zxwrU38qMjF2l6xmro$cTG(2uQ+jXw(Z;$UP5Onef#-a{!b28}3C{P+`3FgT=9MPZb z3jy1V%)U}~d}bSPf|3WT9M7q1HF|9k)5ya)XU>XLMk6C){uUD!C}qdKq}Fp-?MJd^ z$cef`XmTPk4X1_|-Iq*oDyHKz|9&^yt)uCKi5RhI@uQ;{OgvGKxAx;_4>ey=wE9$A z+P{Xw3F%5t{9ckNOwG)Q1o3L=I|LSx3iRh2(Tw1^C{s<|HLt*4-%3}e|Rj%3| zro0NC$zH(SzbPNKa6{h*Za;H&5HPx|kPZG$nMy zZ?-K)Tb*XkYv5E-w?0SojJ7N`&?#mw372YrP+-;Tb%Dqmw1irq%MV!7S9vS`_Wc|l z=%H6vRa~C3jdt{1z68-#Vmk1>AJm|yEgSs)#;nuWL7;;K>*C9;DZVIR>op1k?F3e| zg=nC30d+^5aN*Oy{94Mg#AICSE2RkgcTO_`+uin}b8=s%6|-GmnP0%e8ymO$<(|mP zx{uelt{ZX?@aTuqo4&8nwj9yaz$6U2;&wvH%ds1tgwv)A@qu{^38z04lB9;}EI;vK zwsMMy9@Sa?3T*lLCRya{LLaC#;ohFO3rpU>HH-G!kuJ9v?92!#wf;5`^dLQx3=E6O z@;Va_-TY>RcO8+?`=11*(^vAaTz#NBol_s$ z<#@2kbNj_fDEmS9AANx`UM0>vNg8;EF3F7>Zn^iRc>iU$Eve%DhcT()^~0CLUe()I z?(g?`9GPtkNjzfB&L>dRwUfh0k`hsoCh7$Nc*?~c-P9g;y_NJZs<>oc_HAVHuDSUE zR@qVNh;ndGn|t3krgvMjf``47WE!6o>TBS`ztU%#ebw;sO4;O6b26K6Y`~-GNc1Az zUJSgKfC)NG?YNU}nfY`BzVR!)ZhOWOv7==y`11MA9Jt&{Xw7>lxVLzPpO+U#Dk}T> zYPI^}!=JI3;DD6#SeZ*yJ5L_VbBb!ME-1{d-k!T%zN|1I`593lmggO<(NcsXtdwT# zRhYsx6c;}Tejh(^P~hJjYw=B{FKfV4A8TH!VFI6ctR=T?D=j;bgsF2cs$c+{aeDhI zQ93xX0R#9*w5gsDTwg~j*h1*yq#jFCZ28ILSxT1QS(upJp(LZx{_@k9y~rnW_$6iR z0AUaA*bpYC1aKI@qDv!p0m!2B*WfAy-Ml< z$jWnPs{VU+hvjqaopXI4;!Ps5F{!ZG@1{RUGKgt!^V%{pntzNOZ@>J)on14UdKTzr z+;mZ4L}!#sE_yV+>;pgBly(&woFGTQwJm^%*nAMzb*r+VVL}u+%)JJGbUBT=IbX9j zSt7E8>9v82q)zmYt20?y@%qvYD!Sb*zLkub^=amfxoi92rtEl#{|K6pw|)E5wY)CB z7x0hK4T#V7xSsIQ!Mi(Go8D&?#U@6!<_DFP%-D1`wT`%fJT?iSz~$C?%RYRVQ^FJURE8+>-MUL^`& z#Y`${XGZTE&5N@dQ%Emqv}WGAL+bE7 z)>VSOg3-_n)_*~K8XD&}6!81}rhVV?3nh}T?*!~PvWN58{@58g%5=G3Rnh)Z#$=?) zvwwBK$c;C=50wAL60!S%DbDFEjM_&2h>U~XabnK@vg!%vH_!l~y5JT#i}cm(3-zH= zTK=3i&ssHGOJ(!yCvRXG&dT*~O87Hw+gL;uWv)WFCC|v`ugXB{li4HMA$1krP9fIW zu9JsIeQ!5a&st;O!|1!2T?leV_bXU2S|AIJqSTst?UTd+o|e<4h~z=6kz zljehW#r{qm!yn&{C7KxlGYRU@JDLW>J55t* zg7FhBGs0R_Vu8prX12R#jFUz9jF2Ckn_O7k)wqL=w8T3TukPJo0RqQmN{U7K(pMNg za&`4Gn-*JGs|yc*o{7hR--vvIi&mcCje=JKiC=VqT!&_Nr;_h{@;-5giunHAu*`g7 zH!E1|f9_abxRCdOr1Y3pV}ElSmSz0ni4_DUI(fA@9cuAHDCaqEWz&^7a?7)m{tDb^ zY&cp7%mYhunT6Wa@C{EnX63Wtp;?dbP{h{P+CfjdV&h8dIoJ`T3VH7#Qi^c@w5rl* zk{YRpIL`p(nRnMBF9u9D3-e*1k)O{;KZsNDZ_{LcEx}!_ypz|zFf{Ac@_fHr-xcId z(6sKtl}Rl}II%;$MTe+mGk4}P$@Cm3QTlvXg%o@{CXhK;jr0U{{9GDAdImKevR=ul zd<&=@ntWt4L^b>^W1ygB^=&P$*r@){%bK%hXsEc*`#0ot5QZ8g3v~Leue+v`0gFid{RwUyQ}4oYGGotMilvrpOM{ zIQ95RHM^uap?r;h&E5N%pgata{MkT$d0O!LlgpVDiYQ|DNV@wnOUiKM_f~GMHv5xJ z#!2zLBix}XXpP@iAMW{^*0#1{w)*-ZpTku)H;;zA*FLN6li8Y#C$^q@=_zxKqeozm zG(XHjr!j7xEq(FLt;UKrpXz8s%|`-)_ST2?g>!`;5NtAs<>H9Tjg%|D;^w0d%x~VG zh4l9y>z(sF7aLRZi`C+RA}Z)UL)?4x2Z*^QQ-gTiK&KzrE;(?ISJVkhc@ZaPv-GY6 zu0l_`bt&aia9+pQn-q2@=^WEq)|vU7X!9k#>Q7LoqJ~Yuwa0csoq(>qgAG$0&3fq~1GN$T)8GVb9Q!opQY!Fl}VD_1+u7)iwGxwIa?;=U99 z86Ps46~ER&7>sAtp@^WaOEY?GA(Ip@=d=|A58?4Szus>7%yVInF9DMEzm7m? zUJGOerToY3AWBQkgkmnZ&j0(NB(uhQ)1tUS)e)h||^rx8$c5qz2nP<`E4aRIbub7Wll0j;j!t7$a%@yz3P za*-KZzg?qI#Qj^qw(H_$=+vjOi$kOeiLd?-k=8XzeIzXD!w~~9+Zj3NxKjRBJk)d4 zxk`;nC~qj1C)-cj705#VGACwE zXp15?dr}?79g#<&tyvd5o(Q}~TDiNYL$$;!>7AX8$Gkt!QmoxHJl)4%dkk4xdMa&& zC>iqSxWqdrSX{~r%i^H)DAc{K_)%WQhZ*Wb>;G{8UU+h_!(&IB_o^#QOzN%YK5%Hr z6XCi%DWvrjcuHkW+dX@tJ0VuZ3hKtU_26P6yK$Rz1?@rR@o>_reZ5GdHu9(9cnR!> zNPoDA?}+;9~n@RehY!MJ%4go?px?#C!eq8cZ5v$Y#;>>or!zC zoY2oWbr-2O9uj(d)S`~hL4KhpelC7IU-^>**`TIA!Fb!mtjN0X$?^iY5EkJJw2G+-ZpVweX^3hgI6+I zJGnCkrh&i%Esg!o&(`#RG?&Dr?tcOOa(MyYg^$8a+SRKb@9b9T zi=RU+yya8Uc*Lp^_2iL9*;Phohy9`SM!VmU-=1tm{zMDG-(jLMK40RwDqJq`nb{$< zo3b2O`HVOtk909MLjHhv)Llx;C?Dn&*?S(YTGE4%ir#Ye4PWvG02R)8gy`uxP;O!1sOqNbN} z@)DLL?2imqBDJB)$H&@46i-%Ep-)Qr&kCk@li>Ud@21 z-QPUk`jsEIFyHLuOyhaeIYL^v%0urO=8>4un!Bh&t2`FoghJ>O5BEyw!xOT4W@W9j za8;Fdx|#a4=<5^qd7l?#Mlvrd!Xo;7W%PSFJSGlk@bB>EFh44iHprePv-z+)aV3b= zSB+ygS8ZDeskaNOvt_Y1PsCA8P z1>2mv<8}xGgFH;uvk0?$@YG*Z*MR=kFD}?vdY|fykcyg7Xq^~()aqWvilXoad;h|7 zi#~6x$61D)ssunVt)#FKW5unz0nrT~dz`fx&h&sFw9WS&6+vufPkH#!z56#U+2$WF zrH~L2tXaMiWnJe{8DdL)_&925Zwk`b;;u))<)EcZIk0%IAh0n9g6K~XNl;2JOw^>- zn|6~9_D5zwv{6f2{YTZ?b8qQztm)f>wYU4?!wFGC zC9o~ggO2EBuN0^91rzs>_3^6WMa*$7!(gc%9#xZjq>h!oZr>?;6O-P1Hk4Tz^6M~7 z@rJtsa>Pc-2?xbDL3y%l0@prZ{~HUt7_$IQ2b_zu<)wL<%AC8AxD#rsDz z54K)%DhoO4yeftFKDBx#zwkXGOof{Si3w9oYb$G&(x6LPv(KueE~U?7xl8J!1&l5Cq-KQC8A4P9Sh^G`&@Em%X+8JG-Yi72oY`dm>ME|aJdm8wiF-{MH`Sr=2X zFw~czM`hOVys6>9ToL15`C~gKXI_-`g_4pj(9sp^zc%u#RU(2!#)Av*f2md0jtJ;p z3Al&dY9Q_JB;IPQ@hjYs4x%Wb< zpyD?d33WKag`yHHBKFjw_DTfpDup(v8mmaH(|8gNOs#uWi&u#!ZpJI#`BhF%wZ)rI z;v`q^K7)Z#ow(1|oreY%hCfGgLeR_@&vA2M7gLAdSXlqL9%A3A&;CrcO&;>Vno6_K zh-kU@{Td}xu1t%8;4CkRX2o|RxCs#i4tzXpSK++);4&pX@JOX3?vXr#V)y&#Zmklp zAG?Xc%4AC%@WFsCt5dnRk8cqfMd&G${mVf~4~bl0M?qGVtUpdds82Y1LjrSp2GKx; z+LkLsly)6Shw?4fy<^`xXab9&1*)9to0bkDV*Uc}`!2p$gAQA7(BBt0$CfHjAbZcP$m>+1 zx8Vg#sl82&b6Eu6-=Yb%VYk{S!frbmKCyICdzk%RHzHB7kW*%&2p?&gYVPTxkXo-Y zO`x0Mi@vTP<45ZPLMx~S6D7)9?nAw{Dwnsy*osg8mcqr*<`{@!MAtA%PeKhZ2g^O5?*dn!ODJv1+?LlX`R1VG0MW{cl$o|L?nIaDjQ3on_pF)j`Fy>z7SSy)Ha3p zOnC0P`EJ&OPu2m^@&;q|GG_=weUlaUy&I46VZq3skt}nRM++qHaFO7PciBHn@zv5h zoq(oWoIiAj6G`Qn<5V+^lC-M*P2|#8peeLy3(?P=;nO;y^TSLds#BprzE%v zv$bk7^>$scAL|=Y64A@X5nLouk$>li^*oyupAaIK!Ml=YSv{5U$#$JGkXI%w*(s3k zrl|-@q4?<6U()46H#PNFEHHo6EZ*-CHBG8Z>$9#b37gr&&*f@H33w~>T-_|y0lc6+ zPb~YJQ;Cuz*R;XNW$$NPa3H=Z~m)yFov(_##6=sSv3zAjm@Zl5K6a zb-1;*!>IqIU@1n$GeeDb)M>g}Q%$dP(t^X4{QrcxEv--!y-=;dVP3vhIHR#hfyx!J zzzQLiJ-ZxJWDWZ6&QhFY>X>Dw#NqK(If;e?+NHaB-YgSI#j*4(g(44_l1psDkIff$ z)b~Pe6yo&Tf%#|p3!%r&kqgxt8=@P0I@9B$_u~e|?PXSsI)#;(%yZ;7g)k8Prupw| zSauZbSYv-F&ETu$l7(B=;!3oIwIrA5ZQ;tBn2)wG|Hs~-XG1kP0%+tNo;_Q+A0)DI zMno~x$}%8DNyfkTQ;EweVQn6dOVm(%c-ulmb`CzGr5z{5czvWb|+xZ-Qd zhV8~#hJcRXY!oKlg!FL*^(qanp}fVjWKYRBD@@z>5jX^~!Rt2I&JH<$78~?Tm3Q9f z#R7LHp7BIgrYNkL9FVXcNUfZ}Vp%_0&|1Qu6sGu_qM&^2>EQ|TLJu7c&ADmWwglsS z!QOSlXpEx|MsUp|k}jXoe~a>($t2lmWN{8p?Em$Pku@p^g%bu4H@CU&JW%iX2~mVWT_Sg!)s&(VIh}8ER>w#(*EBY zQYP>jD@+YhV#C+V!|SSQq?%xX_x@vRM|`v;*&`kWGGnh?_A^G%YTmx;XMQ(~tRYS; z7m4rj6qfy7_H^g=CclJR-X}H-^}xBtfWP`=Crlf}_T5c+U(TW67hTa?{$KC9pA=gj zNDaQHfe@zpv<(iqO|&qUKv9~B97R8S-@(HETV{j`Lit5(9|khtVU>zB*ATqKr8|$C z0cSu6Q|2g4bw8e9j8iiRYwFvotKa(Pvy4KH_Ckue_S%-T%gMuONtD zf=nms(h?rW-g#7RW*w=}$9XJ9e6z?SNkObd%fw`7+{XFd+*8!4CgI}a=TbjuBh zUDwyKT3UbT@b8|pBEs^y@mv=AyPG#mJy%B2K}>gX=T0rJ>t`IR>}T>sC^-%V z$3s5kyfPkRaotLDhdDR$5H|Z+7O98jy0`FdVj}s99>&Fm>p4kAk*w$$yLM20y1I~) znlGw#OO-k!7A5q30RsInf^K*y_7|?Uuscf8UAm~hlr1W?^=jCYLRS|GEnx5J;W?G*8=;OpSoHb1 z=wCw@20ciqx!jBBBotS=2p;Sh;RNjd{^6@M!C$xK(NVM>RaFodSs-u`nI|-LRsLvy z5&>FR>PEgho|?+L?T)d+yxG7LFfbOD;@WejX7w?ZA;*#&O*E9pBr7SkHJvj4fs{f* z<@UxKb7J^^qOEnvNGSb$rEWdl+d29JF(oBG*+Qbeg9vU~^g3*^rs07+l-MM8u86vS zH=8U4I~U6TnJ*vQd2!EtO-C=$81~ zh@|bTBCXpq^3??amSteiShPp>j}6x$jOoWt@3gTQxJD*OGSlV~V$Y+k2tb~$?&pu% z82|cxKgH9`J_2zDaU5s*!nK8$=<*&B*@?~BAbL>UL~v0XP?z`wG*`SM}ObF zvO-EQC*r8G0f3}Fz9W;8HjdvxL-Ut(d2iae z=j^af#y}If5b#s_>UK{^WL*}8wc_dm!{7MnJ`0{WW~dtK?}kNzhTqBn|HtKwCcG@n z&UQP0a3d|9(Ds-&<|y8%fP_$Tu9#)tQ-mv$ma|D>#Wnsv)i^)6*wt$V5z`R)C!z#A z?J9AyzF5EQ_qtAD>#_7ixqU5)J!QLzF zbuC;+dF8s*tE-c^Uk^?vlSz^d2QmAVq^^JKcnt96DLNh<_9QD1X=2D-jXWr@vN1lmG&WMDDBkK{Ri* zD4+UFf*UK}a)4`I$ErZ9m$}%aIjV{-bnjE)Gc)dgC$tx3LPx%20Ah08pug2ubl@e| zvy222U3bm!X7WsSqc|7qQ@SN}ZEK>urnk&kA%?H+6$Q>?4G5Cmm<}s_*&gHjYnAi{ z9%N-yfUs@+l2 zDL+2)T;agawolC3QEwV7yU(<{LR4tK1JWDZRem&kdN=K9?&;Zx3E5#p#yUuu z_7#PH)9PW&DWsEysBE4!?NGG{4g_`GgNaUv4zvQEz+W89w1|CR5) zCHx&kMA9&%5kkm#?I@c%dB36%^1^R)mvWNl^QU@lHjE(t>_$1ujH7X3(8%kRrB|~UY*sVR-H!ns zNu%$ca~*23jZw>9>8}-zmMETBnp*oNyBgvWIFoU-L+dz-9B5?*Kl+6Qb2~Q9o@?98 zl&$mw9C_r26wUy;JmOvV}Lwl5Bc2%a2786{IPQpt1Y}(=ydvb0? zT?3sS`XLkI7PC-YMG;(E`l&li^3H(k;G>#f0^V!N(5IEWq~4Ry8#ig4KhL{ow);WT z1b?Uu8}fS#Iy=VFO0i~#+0~4H_>&B z@p!7crcEqb`PJ{v;qmo|82xxbv}!P7U)xx8xp}S+N&Mcsx?#C0{?5I1aQ>{(e0LB7 z{-aHT=MMB3FJph1#hPB0z%tGo;jJ_zsx@>ksSP>vMf+pc?78ysN?fA=Td%_wi=!K~ z7RID#WV!$kP!OUH+Dc1TH}Pv|H(ax06$qADFHJfLr#iBInY27L5M#gT{%)bgXd%+PZlzKE_%I>q6>gQaFB_gX2Bhs_;%0 z4GQuLqpI$GHhC07Y1tlHC1^T3%r{z(wDSEH#^YxmOE-l`*B6JtSM)b7PVp|rVNC70 zuouUd4W!@ae22)t(Ypx6fIYkR!pYfwWj@?h{x!7gM*2ia2XE8V4!-uGQa;Ch$Ej)a z%w7I@F4U>YsJXe>tK^Bvm(%c|uJR8%6H)JG{PJH@ooze5lUg)dlVhS$1K<5HVMe;7 z?g*J=74I+{X?2HsH@s>(`@(UQE;(dRN?(acO3HzK@f{L$DD7sqp}TA~fM@L-Jv-*w zdiFC^C1Skl?Rg25W3Ymr^d26$t2+17wFU=0@U-B&omU&54T?P{Z*5E+jfblew$2JN zM)~s`QH-ghXTMJSmfom)L~U(xx;%QJ8^(M)!;Y?1Qdcysv0W>LJ*r%^FmAQ&*v@_T zjk>HugKM!S!N9quPfMdU1D`#@mrT-if|LHmN5rAH=0^*f)`z~`Osb|{hYt~(j-tl( z?#scMUe7M6GOo$fySq^Y5m+s^{?S z=R)A4;{&VGt%D5k-_xZyEoE!eOEgq-qnR2lCzfVltKl0#iAD9z62^g0@K zyd6cOp@|Hf<0>C@$*zhF!E0rk>XA4k7A=z{p=@Z~(Y$Css<)@wsHpRjOsV+%WV^_} z*0S{un*8(yEds(-wceISBKb@fwP{nYBPUrxwk*>Z<16(4NU zyz?G)NtD(4&T)3+?X)qG$t#QGRMJHb%0&**MUEXj?DPH(kD40c!ee3=Lo>Wtl?ZIK zb3tL7-OTE&p_JK`Pfecb>y8;`KVfsiON)J05T)9=u6Lvew6&-NZo*EGlUuzr(Xrj2 z(c7KV>`XDwi`Yyvvg7`lw1K>ap&3=Ks6=F^wo>1yCADryGTUU3Lhj=% zQSvb$qo1l(GeqkeDI8 z_U5*~KrqMU8rbOL*NE4(zy44u!pvTv62A2l&1{4jvng}+39r)SsCZBD>n4fQGdTCNU4LQIgm@&m7oPFyzA)6tSQ_1B^0>H^g6AgJP6k5(AqhNnJ13Z*GJf43GRJ>8O=2Ao(AooZvO zSBVUnGof5N`_Y<7p3^o{KQX;NfH0EXQnV;s6pmfWkHm^hyfozlEWMe-YZxTd+4_k8|~NjR?VPgXKvL|RD|%m z(5f)LgRbF)pyKQw zmGDE^mk3q8NwBkQRBFzO5q8A=m7Hu%?WMO5vwXbXs`)`XvP`?qGjTVr}=vcMNDBwYqdSGhRKJ}2P!KW zvQ+-25gEAJ=(HwV?pjB^mrM4S_pFL##Guq1YSS%uV~4QAyS7b}JT-)|JCW z&|^RF97Y0jb-}S1IP1e=-W!{)R&m-x-9#C|k0TS$4yiuMy7alq@xTo&k1n{<-wTVr zOOGC5-BNpPns{QsRHm?;8$f(9U{tZ#^d4;~jFj%5Nk~g)tnM(F#GKFg(*? z6^h}Zlc?h7Be1uY2f^5+862A0jp-AF(WDSS) zC?BfwKb@+)t**7wAK41M$Nz`djm`OLlbSt z%#P!ULcaA&MUZQULU$<^Q}LnajQ7A`BK>MAB?ZR|A%ByEk3&*I!PePGj^O4l?T>=n z{nb^^ZL`^0QW+XAmks=bwhSG_ju#Ro*VG&i+#0ksNI#7pZdjSuVX@fjXH(w^hZXLd z@HMQ6vt`<&X+E5S^A{>vL}t5-McvlhTIpKe$s3`SV1qKR6dlt~3jkOt5G!9s;7I5( zRk0{3%45NmGHVHXbnm^GWB?^mjO`#4-aYeKvp=8R$9MnIcF25d17c89vRh#<2+oV| zcO&&WzJkK|cd}&YX0zq7Bke)dk9X~cs!Gh%Ow9J6v-dzEhjtg;k5}j01Q;^$!C(YG zlO_QuiYi8ee502vh2_BQYDs@crS0G)&=ODZYD>4t)p{VE;+cUjvX*qWp?k)^Zf79o z@rodaG6MbTdgk2?Xx;fSChn*ElIJ|o09*#iKjLxHdqe>J^{spm^mYCN|5l@*wIPgF z0C5-tHt)blbUTs2O$$e0|j6W)%54+52+TFDupt1X|oKbGUWCP9c z?0Dn~c8rehbGwy(hCO=}XrPY`e?NP&emJ8>Vf|po-6eSDyTOQEdO75`>S#aBXjj)X=l)fhcfpwGSt63-iW9xaRH$E~490^?8jbVO+Yp?aO;Z zpw?6PEfmOT)zEqoA^-05v0ER>#uZnBis=jKBnM36kNy{W^o`}Pm&cpVyT{`f(Iu1? z2d#ADPhNo0K$GHvE1{em^p`4#_gi)wwLh&ea(u4QrGnwCLEUnfSp(j-P8ddxQeE@_JztK0Xjj>oR%gJyj+vQD=TWBErC9gjbS!W-vqMy%S>Q-pxF+ZkZ7kb$4FG%tpjFwD zdk|8u3reT|PYveMIUw!^Wfh!oFMqmz0K=?r;&Il)za64`1CUe^yn&tYXsbcs%sUj6 zuXFN`Fy;T?Xi3z-r!#m1nV$oPOQWDL!ip$5G_ih1^S~CXDUMwlnzNAWD?|r&5yUjV zB_#~Jpjg_e+spz-g?cN?Y{l^pTyF*#y%pLT17Q|O%=y62^7}C;1OYVcTB3?sTSi5x zXwQo%I~bo7{oRNZ19iN56PsXig9QLUmDa}7=$?yDN*KQbL?^U5(QswEk3`p90J?2Z zNj<9_{Qes7q{#WhH{-0E_K04eQyCEJuD!ZM2-o@j8fb4@p_;Ls8^*6IYItrf>)hb6 z>RgBZNma>i)R^zzU4v8~-=i^b5l@o9%Q%DQdH^u3JR9XNU7=IYi%jvHm#3_xu5{TC z3AwIbaxLnnG=(*NgINSRB`?ff2wHXd4_^+s23HlYVzcaUW3NZBo$Cg$l$&pU;bkao zTJ8yM_<|3DZeV*VzorXzKs&L3O^YaX{t>RkV>>iTr6To~zJJk0lJUMVPLoQg*8V-r zvuh<4*SSWTeeSqa)mT6S6FoO&q;3$)vcghx5M0NLfWY1YiIcu$;5;oNUZB6G0e6A*@27hZm7&S(1^n96 z)t33;nc{aheI^0nxze*HElFTm0lInJg4);;h3>B^mBVPO+t7p?&~d~1a6%!tB}VJ< zqQpE9Y3+w@;>SjXRRxBZR}eAI)2gz(|3jv|2yD@%C1Zr;A6;<#=pd$|5@6W9CKH5- zO)z|&9Xz181FAL^_sDM~GFFLc)HyGoI;}={5ON!szwm}{^(ZZmcL`&L!rO;u>*_yI z-k`l%Vn3%zPQ?1g+`MA>fzi#zjoAU>GgjR;#!~kWR2Us1TK0x0Zv2x5Y!C4c?E-lG zwR!xG52x{CGsDWm`EaB$ejH~)fE(CIl>QSR>?dfXg|Vxn`Zrj7Ey3AbCp0s*UtX`G zzG8Xt=#K1u`k$c@!^txFH<&jQQZ;uHJ7WWT$W?JSn>k>+T}M2xCQ#2#Ez zj#{3JSwO1u8c%jpA0wCC@FwTA=f2@GmDw&&CHk}4TcakTs^MyW-2DI%N(E^8Z$6%J zvpnbE#{w^3&sv?%z~O9Pr5k4d+Xl@vs{rr={LPor6H+kJ%B>?a+G0{FJ{p+hnzD@QyG2C3Xaz4_1S}2bC z$2n2G@Zsjh{Q6sgSOE#zM!2eu>l?KGyFRDaq6@%m*XE?)CyVi$oI5<<1R*(qbC3S8 zA&p57Mggc^5U9ew$uIFVk8a&8I#y*@y&8)9?O!rQo;^?S!{6k_^;E$`*O^;Y(|d(| z;+^|X9#Y_1!*V15POU@1@0^0dx)upg@aH=3)1)hz4V&j zdI5C8AIQv@3OjndzM-qI^FLZqRCUey|5kP20n8A?U;l3fo@=!L#Bibk2FQcMzA_*w z;--_|CjT~nt-p2L=jUZSHHyBtH(6r8wjR?;2>=HEn{HGpxYh*Ln-q^lMl9KKN-1{W z^651jDOU%uleiV*3IAm+6y*YhF)HA)K8K#;$0n7?JFu6|W}%zH+1BAw!NsAdH>t7W zUf>(OcqoAj2s>sWR;fi4d(evD%DBYc4D+8Y9r>jaFw$JRG|k_Z0`PNF-Z>(^xV<;t zNz4x*hXH&0{pMRyYnYhZ@zUBcA)}44G&e-w5_!KR0g%|};^C=}N~8~*G-6ZyTJ5J1 z*!X(4d5bS_@Dd!pJC{%+(#)KjWtT_|6%LBqng;h|8KosMMXqKMfwF5R0LFd_X>i7 zfQW!}1?fWQHN^^o6p`K%rAm#|NJ~_D2^~U@)BvFffj|f{ z&g}i(uf2DSla$pxF|mC#oF+ogb(b~K^_>T9J-w?Lyl{<6I=0``tl+;zC0gC_WcBG?V4U}KuNcNyABb#- zyEj-dnA|tobK|!aFwNZq$_`|0R={gLI6~YuD{uG#&fEb1ygcE5hDB;xSXBiurAp?2 z8b^L=)p$5+@$WrZxf!FLHt9KMI`g654LyNSxRPrK<(l6Nqlr*mo@L5H@Hh# zoaF9@%*A307&42kTkBRhtVYsu&SIxFUhPrG_Sa@(pQ}>-!G5^9jSdcEElN0lqinVP zYr=~h;~BRPyK8dgLW+&yMb<+nv#jqAB1NJ~veS$C$WkhDb|#nW&}?0CnajszsxR)D z!5z8}Q}PD?_9stT6lb*$a>aM)y#dUb@g2kTSP8+LhC@%+F+{|&srY|O6q%?!lWbK@2L$M(JH zL`XBsM^|ku@%OChLZ%2SLl5e&^>wpHB`Y)(m?*5sdc;Q{b6`dFiezcqior2B`jurx z`rBFNb}7gT3?{XO!cS$YtCmu439A*t*4Ek)qx1wG*c2wRhS4XsxzuaMA3&?XxNj`Q zSZ_&-MODv9=ic|1l{AsSS|p5bes5yC*;rR$qedFq=gYoQm(}^YZ&Tg~<26^ZTC_vo z5uaF}ndGWx)FmFPv8kS33*j&cDaR16?8>!zWm{YbM*2hz+Sk4gFJk_wA&^hIb` z6;lSo!bAk-n!KS`H;rM|p8_pF6!R9d5PH0$nBb~oY$-(Cj5kZHvQW3|U?veWtUYHIV7u+tuwe=aVR^mv=X%kH~g$6#5& zn6?08s;_q&rT#A~LO$SrBT6btW%Id#DTdTGWz2kXTH6HS`L!zw$MAfi4rzX+5#&el zAm$Uek;8bV_cT?xfR`900R1Wu8zNNWKmE=z;j%Re8i?H{N~u1|a)MKTlxp<^b`NJt zaxdaTqm@YydTQsA`6kw9C-Kp%#=@G@Ig!z#vu@1FYO5PQ3lOhtYAX{}a`W{fS2VJ6 zir;^|b^O&(>7pZTcIeSyj{Ifl-0B-#t)qK29#b=G32Dn)y$A9M!3UCRU^j+PC(MOzY@h~R({Qyo5!_E4 zwNp1^bcPE7iLtA-rEB@kLKfA!ak#YgcrW1zGjDwUmgd%EV)RPz=8!@77H(&KZG4ll zb0mMs;fzo%^O264h1!tgj$-Z31>s82$I-J5YhsYm2ye>8eU}=ZRm&<*+%v|jkz!|S zY^akUo6n2!9Hy#_mlX@`oTh%GSab!a8rtOzL#Q3PRV16zmU>=d$>4x& z-K&rIPimT!Uz`ZaX7_c)lIHDX9sjz1;BnSw!yW9>jZerL>IXDvCotCc^Qzafbe5R~Dl*=c(k zq+=@B<N6@NTARpDmAc|_p8m8v0FfxI1_08=X~Tqkjx zZl+w=LIjP)*y6-V7MhINU)C@l4gt8CXZxn22Hqap!}Gc_B`I(C_9dA53#pFpqleCe zBl+-FBe$8V9^Hviv1~Nzedf*pYaE(YEkWMy8g4&gqqYirOsFl#~PSb z#lj*?NOc}h<=;Zbw=B{Mch1?STwF0z_FoZ4zR?^FWjqVs?Bdw8?OsEqdGvo}G=m>( zbrfeK#vp4vVrjVPhZQmXZ!ByM88LQ^$>Z{E`+jQy+uO?{xnXB7*Jk|XseKQ#x0Guc zAaITzz73VS|2hq9b3?z{9W38oWh^7tiHx{db=B{kr;Wc(E zw<@%TU`{d9eUYoZQb{{^F^JOO`bAZxbXc7|h7C|Et(jd=B+ zwicAO8K@<-3k3lJ63af;TUvRUg??3AE+q_W1FAP>I)9~(pY2j0cOVU*j|Ud1o%^)l z0Z-l>nk^|R zgaVp*>M@X&kU#_UYL^D7pA8;3HHuh)wGp_FK#@=yO~R_ibW3UER;@iyS{Izx*gD!w z8tgaN_StOtsvS<8wkWd&^M8@Eg7KtYC-O_2Mz{7(7TeT}q&g#J)* z*iV~m*%al%G5OvXAj7f%4@;~qXlg_FpaK2{d?fZF=v3wOXWaoC1k7h8pPJCA&B;p< z;-U&!lE3I~!c{tg7p2sL$p~zE4JWT6qt+l=u_Dn4Ogt+bRWy6T?YyO(DC~ znInRRSHV+b)A!cP{QD^Wbmz&YacqW#FZK{U*p~~if>cSlt(@-WbFCzCCZ1X})v_*W zOHAQFDllrrm}#{ORL&RV#wcc+IB`jnvDPGBygHm{I;iGLw{zv&;va@>eCtM?E{q)O66_nr$U*_I)d|&Km%w!|h-uPw& zY41+#{bK`b6Z};dADrKU{P=erV)eP?OliZ2E`SBD<(4m=`y$-@`KURwgR^ovSo`E} z*94=WX7E#sl@0n^+n-g+OL*is|9G`8?UO|tAV>gz7u3c9ffBIjfzRsBgzvwdNN&^7 zqc5KW2A*rjael-Y2?>;@>g_uXP=dhU^|ghdexM7;K@OH=+#PbLJE!H#fB6!PxK6f% z`+%=Chm&EEJaw_>nIk-t+xJ4sXhuH&8u33DS5U2n6^KRcYZn3nc%rO_v zJHqUJEB5qmgrmFZ)}*CLe6yh-+n)g%Qk&sm#c+ZCcyHrhvnc^N(>TP_ z-%^mx6QQ5V-+e$>X_<=j={+R=bK7w8;d5zzrt;|MPoebk$w&FTvlQ_^N8sK(8fFlsly?#XkG9tgf{S7s~bmP0EtuX;OhkM?S8}%ROZ(G)QTl^cO zZZm7F{ZIT-X0fT z{drI-HixSN>NS4pK7Jy_qHPocSxmuP=g*x?QFP3XzI<6y-@zAO`v8dgA6?QB+3Tv*-I+!m0sq z&G)tdpx8)*C8O_Zl{)?V(z65>8GkP)Y zihj1w^9l6+n31lxjcj|K{!Ibz9#$@u{33JD?^&o*KG5*FG(YR-ajn452`T>kxoS|Q z=dHaT-U9|COW@=Kq91@n15{^7lijmt`{1S(kQt|INR&Iee4QmZ57qCH0PfdHx8nd; z{7BbBj6li@&OLjqy_l>al=8HR{{G$l(q)#~as8S@O~xHS{)zoR2ee&V$+^Lr2CUdv zs%=!HjK-E#w@L+T4;M!3_Bi=CFPaRrjo)_yPR9x=IN5cS#F#jdB`(AxPxoB2n)-K+=xB|XJf03&cAbM5T|a(kZTG5;60bhr9fI9o@s1lVp08!+ z6+QB>=^e)?3Yn&U^Lo!`FoQSqZ6r*Wps!;s=e%;y+pxc@DOHj^U^Gs@RFYP@snL1OzSJ)D1mV1q;KZV_?Y3Ht z?gO8vsB2>B;2jLEvsG}jmWMr|c=+>MlhR`^sgi&Imi-ZUxW{(K2at-NT_A=9LVO9| zuLPgaTvX0T2Ja1hHx|;zkRo3i z*K_=F>&g-0BYAr?1wY4~x1aCz-6=$TNc{)Cx&Ga5=h;|FjlQkvHBpUG|>P zBPA9NyBAe>wW=mAZtW4pLT@UwL!Z>0d^Gs*v)pF>-18fynE%wNu%c}KZ7&P(UPYE1iym~Oe zya74VaaF*U805Xv^wBWaL6O6l=E+*FiLzi6VqHdfsP z$*^rn#NH{k*%`toxKB74K4jD-}txW*I zdxeo|)IjnUw5*%nK|>7G9K(~OwKtNX`R@1!m>(YuO{Ms(ga@(etF=NY9NMN*Lkhmz zpGXXg4qDy?XJ~a05f#F@Xkk~rId;|F1E%_5E?3-?(_IAx@%~OQcNwq=T31t4-=Z%6M)=@w}x6x z2|HVHG4UDp14v2qcJACDZO3DBy;VcY06yV3QStBcQzGHP)dI)MX6vu^nuro0uvbZ# zxsJV7YC~QFvbe)7(cSoufT4H(Ol5B)-)SJeGsX(q-#q1f^k|Lx*8+Pf`U6az8&wgQH6pjr@n|mxR(DYMwrI>IGJ_IK8U$ z_I(6xwy#>IC@pZg_8ouSBSR*=*?QE`K-NWHs@iTADYUNj*~c=n$KgJPI%pqN_MIYu z)iNaa->h2C?ZWX?JEW}*S*k*k)*7raQ#kg9tbeP^L+@C-pJI^n>LXwDWIu1!Z7dSU z9dhN3DhM5zuRN0ZYN~{Qe{v$jVQ9cMTrHcg@^X2T^8E-}=gup38#5BMDUz=+p=Le& z={YHWW4E}Ks8g7O{IALb>js+6`4!{GJ>tEV)$f`Z#R_uw0rFU3avvu&F*f>(u+Bb3O8Jw}9M+5@Tu(?}!AFgjH!lK}e> z7)y=lU(GGFpc>ghNV$%wCRjQn4X5gviaMBtf|5>Y97wyeB5K&z=+yooqYJHwbfc`s z)Vu1Z_S`GdU7);Dnu-e~fdtKl?=ySD8*I&_s`!aAi-+a$aQ*o~wvY3oaERtcZp3A$M~?=@l{dms#gR3+212s3QB zR3!5VZM7sy+Aj_+mf@Kz+wqXViLeEeP}07hvc(S$%>B)8)Tvl??={vS8lke8;tH!S%n(`r ze2{iuD1j+c96ykm=G$a7gwc5oi9{lg>H5nhCEva?8%%$wO4p(%+JiqCTcw<6~z~MEiO@yC|7_RTS!R}U#TTS-US8uLA;F>BZ|biLOgX- zm@XbE8tIF)=!=u7JR??i=8F5*x~(S?Lg2Xz_#=o&EN!Es25QrEtRX}qt zRX+*kFsUoPm;$6S5sjF{k_yF{Z0cBWLWj+oxh^6mGh{<166K3IN-%J#D)6oSbcL<-7NJXS7Z`LZGFsQ*;e+GJSE!>+Z5BkujR=PeS zUd*h|Z^~(7WOk|Ifo`3RD-sd-PoJQd2OqW*SKRN3&B?+t?!DKZd=vj~86DU9dHG^7H-(CjnG6#-uWqyVWg|4!?epQh&!zIu197j*kY%zAN zlT)<@U>vzNxzM3(e_ZNJM4$Qp_A0e4fuv)%`D##3@*slxc)QR4**s- z%HuVe&~Uo=rA|=Zxll7Opz=X~ZMdirg}+}u2b@h77D3t+D z*zK8ZI;*$_@_xb0u9Noj?RI|ZIDa+%x>6mR1MK+*ko)?5-HscX#$unLz)L;Noz zHT!}Q;PbvhguVJ{riPcp11A1Dh2FYRM?b;?`JW3h&4{nb>;8?2i1%3UR|P#g3?!>h zKtm$XEJsff%5qYtb!x&z>K#(_3PI0Ez~xC_VMqy#+wcP>vboDtmRK3c~)a zuj}ob6`MW-1q}DYSq_1!l|BL&Z3}hxs9T|L399_=(RmMFas>|el3@)vYUgt-ctVf; z$FcQ9eebRp$ws%C<3?2Ki!3S!+yc&yRligWX?kRifu5c1Zu;Ok+FGS|MzSAYq;vNu zV2dcenrk_Fkd38*v0{aM*MLM@YnynU!+$Dg$Z=q+6oLG72#~VEg79X}DnzgsxX&E> zPqN~@2Drk%HMEVo;*z<|w|FJz$pb*x`u;{}K!LP#DFN+%8+-61bf3n4=xtrxR z4zjUiQ-EnHJ-%>VD|^YtuqV;9K>e%G|G*3^#)GAkUZ;umw!e=fBR`&_a{a;BeuE;v zk*S+Efti~8ugm{RN#%#NJYKR`j$jrL7IPfnQXJk(l~QfRf5RMZS&^YWfS|;})>Xp+ z%!R|aK~bUh!yV5*(q!faO9ElZ%q$Fsg9iv1Ju+zcFlN1fa>3$1)+YlwKgq!k4DT-M zbC>mq1P->L(U;29zXBWw_k5RmV1h> zUe1<&J_QPy22>EAQj+Dz0T z@ii6N4EiUgGUE1w6gKryR`)uAYkozwe;2y(EUQo!vumWkZKD?n2Pz1k)RXKnkVge5b$7xX7j8qifryPzR6fWBWq!3t{S?^Y1+g+8o(fxDyyKo$63v zX|V$0qgBHtX%ykEu7@QnCN)tV_-h{PmD$pDifQ*ZGb%Pd=!PN!8ZM1+K%kab^3UtVU_Ic@F+Iw$>ndH|NjX9sKxD9~40l+)gzrq|D~ zQk_XEqid_Qoo(Hff$G5k-m#7Dq1Ea&q<}Jcq@h~Gm8ymROu3VR^V$g(L-@>9#LQtH zm~%Z!2|Mfb5>qqNc}g!{HB_(-Qhx3J*hc0Z>6p z+Hvgyd+5&cB+@O3Jf;zOLo%=(A7_X^)^g&$wCA&`!7eF2qpI1j(nx8eq)gYbFW!Px zr2;}{Wq1WRi+~mVYioJ$W;j^zey+k~SSSs8z$kQ`!|dvew9#MFMD4FW3$LFnboFzd zc_RsrRZ|CUR#t?rch*v=kANw87}DeI9%(91OIWp>i?G7ct4)-GB3g;j{XxAY&BZl= z52kWf5jGl}At(rm&TEhTTH+HD)0M1?ACs-pdY#f5v@m7n$B0yWtgK!$kp#0x&n^l6 z+b%RxcJJI&mnHB0qZLgPMS+i9Y-{|GzAn%NYIae4HjAau#b})+^voSG6v{ z%a!(;t$W*4NhIeH;%~*JN(w3KWp<4FoM>*85SNDp*O)REIBY1RtGr3075LCzM&Ws_ zv=L1;$IE3=6_TN;P4~mwq}{I#>ZHh@v!ftEPAB$-c6sc4RTWRgsa2tGZ!8gKU~@ls zOPn|TvD?*0VmnL3fdL@qNJr>JSGAfl_7dVfrgGt3w>Q6)6$hdhD9Rf=vrStOxmUWL z?KjH(?E6)v%`ZhA=eU$!J@!|WF4c>SLuO0yP?BZ3KN4fdtLMZG3atM|h_&$&PQ8^k z0IvorH}Z#h=bF*LqdNZ36b4R|SHj2@f$oYVMQcs}L%tgRBw<`_wouto`^Cp4#Rs^H zv=*fWJgV&9`}aApCI&3+PMQjkZwFZsq?m}wJuNJvaEmYLgKtrVK=jdB8)ZMn>1m2v zqAVsvjIpHafF8OpJ)B~5R#5#>2`U7(UKSI`^mXWP>zj?>>hReZ@(^2+8eF@AL+W7nyJqG-M@IaX?^ zE|R`&&6eiUfekL{-)`GfZk3y@WK}7Gzs(yO$mCE(Z zuSDp>+2z4mWA_OM%N~+5vG!W$b-4HrlN#gq;|D}C`R z)3!*o4Sd({#_?phnzj1mk+it^7ZuYTRoe|vdGv+O?HJi$gum7F)kY^N4{9iuL73Ti zwKiX(HtvU%X->l{kj+Oip!M|jRPj)_cXrLn8|k7z)s?z!=jnw4XG(|eN*}S4vC}sg z%x0o=AXQLhb}G1N11UiJe%i4=OxBNn(pw_E)4!S5z*Dx~kvB*Ok*_(iQWsDw(EP16 z*OWMx0wO-3Aml(djb^`x8IdkJen6Z^S6hCBB(FHCNYv2O1_!7`hv_qObC3F7Oc$-~ zU##K03@U9Nv0R84LiHl(6r(wiSJzvfM1*icR}vUmF&-=?H8RtwG})D^PyfKBt}d1h zF3iTZ6O^Ql?xZu5pIOWy0*mU3(_@i=ItH{>Z|nJ;v8pGytY>7Ca&^+WVSH0_10zb_ zOUDo`^n~;3x0Ov@(w(-y9yAZ|5=9oca!nsS6jn3_YT( zM6g*Tm(E7JqCks|6E%H<@Ungc3Pv=$$m>5uT=Yk)*k}LMrAj!$ebMoARf=I)+O*ed zqxAUnyQ;L!lvFsmGxe+{bzKJKl?#D)R0YIzez_wZRdQ;w-za;|ay=^*<=VVxnaltx zmdl!-rrudg^EId;+*z;O7?ZD#+WAQ6s|$)|7Rz($?1%F)yqn6TE}~ELKpZoA=I;#@ z{lcSn#kcb#E*Zg`aeQsJHY@DL8IxAJ4uMl0=?+oZTEj5^5Um0dD@$_`qN#TLnaK6@TCB5fY1f`)#m zPu~3UUOKKfTX?&+^HrUU8YlRg7AE|YMAgZbu`h$gh&?xDjGw2ml{KjI% z1O$P0d9${yESuetU8Bo@bghn|as0@&?u?bvb>&fZ)#o)!IwAt zL|NqH(Yas-5NFJo94?VI|%H~`y=&jGu$0{o#^`2XE z64BnHJjf5Dkjh$@$gfrYjxQ8V>_7In+pAQkt}SPJ*s0U}m1-#)vx-)Nnkl3!it5~m zk9{DIIj+`fcNZlQ!z+U6C)Mo~3ywG+h<9A{^z0knc&HAm>qhz{V@8#3cc8%ZpqQ=N zwgm;K|4t-pyGpa`Y_*lE+g$75%8JhES;=%*b&^Rj3=JCejao>9rMRiWW!QkcGY;js znZVtlHjrl17XC?|$K2C=J&<}y74m_hHgIc4QJJqWhWp|gZlQSEK;L)plv%GltySA< zjr4uF*tI`8-AI+uPl{OCX!14T7Y47n>E1Hv3X9jzc-*mF!39)ypeI1F2k~QE)ts0| z1b%r21fkx@Yj9P>>F7b^V3mOFOyyHA@*D}>`bN$;qRJgwRO(%^@YP7FN?unGJp0c} zb@ghgaeX{ENa(6~F8DAgEst=d=!x~#Oxn|FTC^5DL)%S9NqX~SG^uXdAG{#17Wj@4 zsPBkAQIB)PeK{^&yRb6`_MTA_S0_ugKcFla#Vf2#c>jZ0$AEI72h_S0YBnOSBp{pD zkMNf?2=)n&WxnSt`m0lX^0xZ-+QSpY%%Ss*81fx&_|eS6{pM)JjD{#9*Oh=2pCv=F zGF4r!g__L!rE%U~be%lyRzlb&h7VPF!@B>^8axAERCvCGq^Qn{HYd8&be zf@=w@1R{>PLZ;2K(t1&CYB^fzvf70T3lrZCYzCf@qy(G3 zr^@jGZkFlQADu9W^d7d}z#JER5{p*)vF@DAH z^nQlbp>$?;>;bu=qypNHT$S1lg9?4>xABA@PGz#W$g-6>c3(SeMHqw3qg#Z>wA7`I zpLL@4b%I-f-Wr0*Qycm)?7E{ws!TUf^hZw-?7wmt1a%QghH7P}qA45hogU6bsXqK% zlzwTwiJ6_IwzyEF9t`ZLURQY=)$-Zys)K}dA4*WFsOnb4wX68MKXQ-+dxakN=__Rq z=fK~yA~{EC;!yNV@3Wv%&LXUhZ~DjfhE{{A&&rsn<5Mck;+Q90!Wx%4%uLhPZ7Oaa zDdd@tTKExp+#~9FdX)0%FFNWAfB}+CsR*MRJ4dB^ZTT;B#7!4?KOpf;JGsEx&f=1l z;jit|Cmobb8LevdtJ&-WsrbB9Rs3;53!y|qPzMcoy4r4?#jYACO$`K(9m+T(!Ct!?U57o}GAbp35_ z+ZRxilVxIES9FF_R_$<~j5*!cmNHX??5xI9yhkMo{((YXRwq5GE3zXzN})8kceTI82fCMU-@k7nhqO`~fC#KwN-$LaxNKqNhXD6i#;AO4Gl6{UUIBt)U zd7$qoqatL=r-ctURhPe|sd%*SSWoAgjkewI%nS5(%pR_MVxj}TIRfb+aS?6OJkf0K z#HzNARCkQ`Tw#^IT9J)mj0lBaU(tGN*{AD#T`mWSR^>bVFYT&26e~ZqdU4d`4H7$amz1aE-~v={=s=`T3?dXD^Q8!TLbb zQ@;Aujrs(X-*S+$eb@#g{&vnqptCMv?b}Z9m{^efriwFuB>P)11Z&1A=+jHBj+`8f z%#(vGhOUye(&PQC~vSXWvtR?c}Lz|dW4~0H8b&4p)5g> zP1PjO9Yno5U9TG0_b2A;xcpC?m=X)obiu`2TSd2A9 zAkJ^~nXjIvm`+Ys``0wE@LB;+-0kL`6dzB1ohmRO#{oUblX-U2)wVPL-t$=Vrn#Pv z>9h4(cAa^N< zu+UeAB2)Ifg*%Cd-6N~ZJI9~+PXnz7RjBU*Q=hq(yEOLr+!851_kRf0#1YOKEtcx& z&l3ORUyFw+vuWS`PXi4wUz5J{6UsAZU5lrLCm>zx_c~K~{u4Mi?UOh6{si4_0=0_d z;$D}-vpT*C_x>-rN0feAcWgWP0Z@76;a@Y?vrgUQ#9x6SI?{$mcZ#kh*R0?%2uG`D zk|D);3yuO8+p;7!4~cDL@^^nAE>WvF0wIZjP5y4+9zL|E>G%m2vB=8wI^isP8~#FL zE*s@OUWsvUApz3DSz2`KAk_6iJPUWyZQ`Rw$5(F(U6GRj0*CQEYb|aY)Zv3HQZ*RJfVzAVneu>sD9S`IeS$j>U_(Jt=nEzEU9nyL zZ}f)J?x|S7CjSke{c*(!|NqCW|2&SBMqV!4%R#3fnK&kdISEdiMFq*s9OB>yRv2Q+>hI0{rn7nVh03nOl~(Nz ze>e5KnboAc_m-Vr9jSOcDBNBjr#&%5ZaQn@N?NWQuSz%RGPg|tE2}t)^aJw3 zP{mwKUSKiJJ9GYY*Cn5t(FFQf|KPKhAgH-nk;L-!E3M2?tzdy&xRnef>6YHBb;*z_ zy=IUeIL^~PF){ebl~!yux`9C@?u?abd87=Uh&9vQtZsMMpH&4mK~t8Vj$9JTeS(s$ zU3=)ZLqa-B&0f9-v6|aEt1=rCIm(+rzvGhziB5E{@#2EJ9s0TkS_CT$P)kjo&ywa`#yS8a10< z+Txb0x@vi8AZ5(;0xF5RrKeVcTeHiJ2P?8fubuB27JM7=ga7>_Ij|s@L4_C*k!b**>yGLT6MxZWm6erGQSQ* zbB=A`jdOu~Slb6g^30gWrE-O;&lsoA%{4nMOLK9wSs2o*qT& ztfjQoN#kCeFv80J;O3dsv%7S2HYwF_xwP4H27~cjr_a6*5wutc14X?r(QN`_n^QX@ z>^n2EygpjJeb6p#5Drg$I9#X+-6-kHya^a}a`iA7RZ1bfk1x!PgFLIUGJE;?jw?YD zl+Pce@AeIG&C}^-Uv=(k#nil+e%fC$;TPru7BpfnSP*x>^y9=jZdddnRfCuD&*9Oc zo)?OaE9s{&G}8Pq;8P7L%y0Ssu;(Z=w-o+UcA2@UowHbM9ZDbO-ph#J^>k{S^mBX;=vV7^ zT(d!b9+1|mZw-@AQ>ApyV)se;5>|hN1nIwQof4K#ht|!>M^!BgQUCQM&u|eydHf`M zlJE>M+EQ8PGRAkQp;c_rEi7ji#T#Q#JLCU>EU%Bw<$sw{0$$%!W_Y_9L2XfY=c{ID z6+CdaG?X0<81nARORjYtD(DosIyWaT2)E64RxzIN)0zgm#u%Cy$DSbR1)x6Gj&i7^ zNH4kZaE78H-IGA)hd_n{Sy$uHK2uhmBHf6(kHvXjKN`%Nk+NOnSKdd8gyzIdB``e` zcnU|Rd$96$t*mkNI{y_w9hH6+DrX#pcEeSU=EMEeqN-P7kQSq?vQrJCiP$4UNVE1z z+NGB0!OI`x{q`$PUy}wI308F${?k|JE8e{0RQI~_)(av| z=&r~KrLF=J=rTg|=-4&bl5C~=^0V2d%$A0WQN_vIEpa2-Ig!U#D!(n;MQnb#t*?#h zaq!#;OYFEx2f{Rl?W<`|qAw;v7Bci~zaR9syhB>&W7?%;`%cG53x4opG(6L52l1<8 z^_i$SWvLgUgANK&t=dKbQ8^_(gQqet$rGGW@Qj|zp#Vb6 zs16~egv90RO+G&@fKPcdGxTAlGR5a`4&1vn18e*JlNmYC>150H>c~YKX>!vkJ^cw6 zAw|dcTVqMIcf(I+(n9_9;cl~m0wShhhht^?p(MntQ>Hqs@A`+4f%h zm5{1*gtw%1`Ec=BDk=T!ffQ0vd9?SLNG%i_KnVOal^V|hb&Bpb@_d~X;C{<`e8%{Z za-s{bUuUPC1xDKDKIL1f85HJZoGlpr9(KE7M>Qt3%%;UbZ@`Tmilr3U9A-!kPJU-OM@JFuvQ zkatp8{Ve?0r@`3HktR_Ct76EEke^km<@BhD27Rd?(ogtc_|I3GT6zABBRkJinIWTE zrqzM^N}MD`Ee>TUVK^M{D#bb|J89$*QP+;B?rHf0=A@zqq9uSVESmw+603N`Zk3)_ zEo@2){_3(p@3V5%g|#LA+5znG*Wvjecm^xf#K4maeFu-O_StcOF&}MT>504dV}xy) zCc5#8;a?{PmjpQS0!bl{fNe|ZxV1EyO>19wE;f+AaD7Y#ZzNg`ZnBQmP--33;TMPT zA3r08QEA4c^{wERZW2>F@b?UDjTMsMVV zLLH5xym{oorVOnFNVg_bes-I$26QsPF%d6?oaAWVzI6*QWfc-Gd;08_k7mNoo4*$0 zkkGp7Rzb=&S50h=SbB+}a2G3Mi0rzGI?b|^ewnJ!J)vH-V=sph?|~{%Qovg(GK%<& zi+Mj)PJrnBjoY1?FwMTa;b?QM9c-8l(ukc#j*ri56z0s42<_;*6+44`iS1W$=Bwn~ zEFlNj^h|I&VS=TYMOC?@B}u`NY`DF1smF)=l4Wh54waj4l_K4o^7*f==@@{$CF4UX z{Hn~(9xwFW?B)>@2>rgn7PXz+EOgI!II2yZ4qY(4u>s1vlMd8S?7QST!KGM({ujeF z8Oba=zAv`vq{71e&E!QTjUbbt-mQe_TZvsWZrQDb5v{JPdisuoy|*3q8`>2If0ENv zszC5OiOx-u1;6jf@|sF?$elCF!sgym;tVDG5WaWkj&^&$KoQkBU1=M45a^Zw{+ol- z@P(a?C0u!x_)EbuX}g9m5=ba2vP%Q7qoY=S&7G3a+dwmg4gP>hPr|iWUNHE00A# z%W{(r{62Rxv7>71U2aDn55^&fG%CQ6QR;GcFO5$MZ=u%L#AqBgDtqR%dxyH6lY7s!V(5*wN<@9t*S&zhz9zB{tocDT1^);qPj_csW0e8q{gV zmfbRiVT)3wU!3dIz?;um7KJS@0)qdOWODOtm~Cc1KByoHVKDDLs{0SEhnpG!r686sq`21eBmd>TDYBe@K#>70OesC zIKjlLnW;cppMXerJW`U&DQ_+b;)mLb9CX7~@eK_j>iT^KmtYvZE_a20T|LJi(BE8= zw;=hSQ7zG%OJ$}CQi49xBNJC~xP{vnn!#NG-RW|JJL&8I7Bre~V)HIZ_F?Emh(BsS}85Xr|N*z+PwV5 z0eVX;evFc_=jq0MA^Gik2x#@c`iw>?TyaVo*E=xHkc=(1=A%0v<6e^+5=o|GmYeVY z6&o0EJA#r_(pC-VZY3_tu~0PKwXtHzkI2yjMRjZaZyddko+ARY4ddoC9tn6lsY-9O zGS3dw6;Q>i2sX@->{V=szL@ST)&Ai<+tyJx&x^+ly0&RasYH1h!%r^Ud^r=gbqEik@iIR`4WRyCqPj{v!$olXjVr4 z8?wGET`9TR`0zJLf#WtU&|2gTJL5>w&27`kPTlNI$2bWd zH{RC>$a?`=Fh?S`Z$#(q>j3`~0epwSkTVDD&7AX$?{WKG1?D2N2!LC-ii?l$-nQ`p zy9bD^AtK4S=$p_jeLWY`4ky zV1V)(nsSeuO>JAgNwJC^Ro@MuY%kda!#hhoH=-dzRaJI|HuH8gN{W8ruO%Wu_iAic zqLX0F<2dE%Y1wy7a{%s;IuD)~U&pbs7j|6je@wYhX4pGGvJ6p+HuQ4d4N*RSpBs{o z%_Uq___ErMiN5{+_`YEWft~}{h{Y0(T}TTr=lrsbXywP#27o-+8Y5J{XWN&Sk7F(d z0C^R2gnwOQ47Upz2oMW^5XtvS02NkNbFw4!`p-J0-8lzu;kas z)joEV|51v?{R`p`OCvXv*o1)h6CBrKuh|&P3?c2W=joTvIOV^GME)e?jN_nx6Ov^3WJZz)^goNsS1;oL_=)4bY z|H`*m42wRe2WWG$O`1LLY@t2p)UGH)UHJBmC}nNuY}*JRMIO7(s^;Gf&m-ZqE8--5 z0|myO4HJ{?uqwRUQ7gD{o72a4M46Lw;~5h%Y}N|Wy4*l1OXr;Onb1 z1F(kK#Ag><+QQVNu0!$1?VEt-OIWt;k@a@2wxQvcrs8Dx(oIZP;^5Pyotyd#^D9@3 z&QAPZC8x59u)V9~)DoRDBnf%q+y5CxA))OxY)w63V8&#he2uz>3;XxxOIsBARcbRe^wxrbcl|U0Kx~>2|EKcl42sp(*XK z8WR^k5Uk@D<#vR_ag;4rrjS!lZy~WY7D}cIIJseEZp4IjI{lvWD0qddk}d0?3Yo}E zr%GmglPY|$`!7!MPql@N#=^oKA~U_>D@TJ)oPyWn_Q2R6e8QpZFpiV&OCxW^Cosn= z_gw(Q6}Cn(qw2x-)r4E1vE9Lzcqkqq-KqdY;R%m!rl{u(bR``Pt%gZ;|E1a&GN3lq zFjqJ;tOCeC02+e8hll-(kH7;)s{V=SZrj=%c7hRZSLNA+X+Y_fqx{}iKxc4P_nxbo zj~qKxe6;|N`vgRcuj&P->Yv$Ga}OZ%kBzp^0@J-!OX>}@)NM7p*4m@mOQtX14;hp{ zYsJmIp;XYprmt^bYfy(d@@sV5UDzh_jN4`W|J#DBI>dLtAOtpA!Ee^Z@`=a?Ve|yn z>E1@QDZv@x@!Wt$CLsI<@VT9y)QQUb$^ax9T;i7n>^PT@Ymb5`%}q*9Pr3a8dWJ^G z^-lgKvk$X_-Uwvp97qdZ zPtKg{Em_$S>Rn;q{E@yPRIJMbT@6kL^dVjey?5Q|cjy_7_r(Iw95zKZI49$tt=rX= z#a)0HT%{h}8I-5S7K3BX=n9VaI|i4*ewXtn_GKp*l|RMRc#?xy%=dfaQ-|Ad%M7RQ z>8YSVq zkXBZsQhHk>UEAQd`rg%?2sU`oaPhx%oxE^V;bUPc^&y)kQ;BKo$N%Q%S$ieV^OAzU_5P< zS4!>*+GVH`878TW9(#&%9!}0?6?#9zZ;DanF$~VQ-{sk730_z3z4BW@zPW>weAKtn zrD;~Gr{sN#4!y0<3M@alAXz1E!;Kyk0}FLHwY~eUD`m7o^Be{7+AlvqhXOa_y@c|W z4+ncjiLAv@w3K<}6r_Xths!QfWq!dGx3{2T&Obd$xnKoyvI)Kr!K(bdG~7fWEY);r zMcRAiul%|;jx~4CG!*xaXQ-xgdrwOh>Cy^%kwZ6dD|GjIib7SC zF}2OBY5jwWR-vyav>OPGOXYwBbcLOmW$p}3OFS8db~MD*8BrK*B8fPp=EFE=yl&N% zKX+@1I5gbwWU$Jxm>kS=IEc{u(sI@p|E@o`zu-m9Jj(Z%3Bs$Zb7aZ8JVyB|()4|N zHb%;+wBlceTI|~l`O@@bnw+G5!OoGcyXlJ^-nKMK{v;uNx;l5?oRZUhOH{!(>>fo+ zrD=OsyFaTnGMBiogYoMc-sR?FxULFp!Us$n5XZtGEv&mBN^)gowm!FObN7m_@N+9z zJdnX{EaZqz9c>nhjh)02`ydw&nKjmK>Vs8~jra?{sn(RzsG0EItrt#J9nq)v{)Yx5YI$?Wy0AKSn2NBl(WChYU4EELI1FohXpe zhBdz>qG`k6oJa1>x81Nh6Y%*|Cju))LDw(#jTnqJ8>~E9ndnuDeum3TMmKRy&CKE=oyW%J76c(4K_MQ}Qo4qnzp>*K0uH5;OAzV-i1>JWsSd}5pOPn}0 zn&%;Hxg&3Ks!naHj0tExnxP-O#Flhbj&w6elc^>DXxV~$UpA3zkuD^AYzl*#h(_JF zVTOmbIybhouJl7=sl|(9;jtC{)W{8CwhD4n@jHihnVpV+b|~QZ7EZ{ zahHdf86w-jg$ zeW73Nn9~ZCMGR21O!gSb^zrx*iR3qsxHJrX$=V^x&uEL0uV|`XP|=0_a=R*5@8z*% zHXWO-s{px&t#g%=>Ag&xeeuPstt$#0cFv#x_WidsO?N_iD2kAQp#y0wUB?o8hxw4{ z%DA2dN%*>dPo6>S?Y+I~N3k#OpXxaiUpsgn5fV!(q7tRN3i2Fv#}n#J^vt||l{wD0 zun>mfC!YS;J3u~*HEBa8cAgqZfbQ}&d9r~85Geog3JRJa1v}2hxjeYpM2;F`di*cMC~l( zcbz+8Mo%P()JGs1`uSDKeRGius-l1{(MW+wg0X4hFChPS$w57jJNoa(pe!=5mg{4q z;f`}G2E$b@F`+V5D0Essx=5(ad`=sS zXS?*db|E`B)%q&jbl0+lH2a3*(Kw_lqpayN-HrGy5Ae!14hN^E^E93LtvJbSU;frO zOhRhImyhqv3gtNIUzmIpdu=-L51Rji@|FhLQPsAI)npPN0B>q|`&84xdA5%2@ z+_M_3$X0TT_muIzCk31k%qqz84Vzh=XTfY9EkJjAtn1%%`_+LPCbz$Ww)we4M3fHO zZVu0Hs&Wed_P3n#Ko;Al>fu+I=PSmdvBsmen@av6BIN{I?^kRvVV-U1TAi)c7E)WW zm7ns*2VZ>y{##IQ-@o%!@eR}4;f%yTWQk3cu6$ruXGiGFuv5XZRhU#b{S@A)E8Je! zXHV(B0Z2cx5B0y;EUUA>jX%k7a&Cx%TbR5BzJcr$JsHq<19B_a`P*=FOFwjlzxnH^ zRVxQ@6xTRBtHg|?hk$HdG)v6m&{ytR%Jnl_2Tw1joqj!o+ct>=vR{Fm$F~+)Kss{D zgAF$rz{pnPH`qt%I~-T70q#}fidwl^^=4wiAQ>F zAfxop%^QSFhwbV>Tsxx2%t?E=yB8bbDWNBnC(KYyHe z|3~G)VV{OPBeVBDZux`yhl+F?v~S@*+JLHaK2|`F?&zo(+fLKy(A4zbGlt}Tn$S_! zbhWT`P{Vg;+I-sy)~qDxk5_Y!essyG3IgM7KQ z8?dvJKqeWH(2zs8%zJnTmyMICd+}Kr?CVn&TmZU}0}#`q8Z`aK9-h-X3)-r2Z1})| zy;lJ6=p!J>m-y7rKMhmmIL_<5RU@+9H#O-g@Ros-uXmhK>)_@!v(ou#l6y?PV>YHV^j^QHF`31Y`5B$q+%@YTX5wQiw$35wL+*Gf< zpIQ7{&0o>ZVgELElP;BQTi}JHg;{e|HoNbFvZLKsi%5C?nFb)o#5Ukb`|V$?+=#7C zGT9;Jlu&K5N!rt#n|^jhzDE5O0Ib;oZ%cnTTo=EYnIKBDpZhSE9nhx^BOpzT)IlEJ zbXjejEofAJYbW!qn!Vcbk)7{a^ewwi$f0b-Hla6T@w!{_#-aK15*O58?Ps?H`f4TI zI{b4HXZS|35_d6C-`xO6pVj`^)u8)K!yo7^GuNtBc}t6Lra%As>RbGVxIQMn*YwXb zN|jFhvhSdm^iUCz19>rFNYU~jAybU3Wf0nk6-0F>q4$z2sL zzUAkSEXwLk&}~=#%T`jCc++@JvMovt7=7g%F#hfl2?L&HvE5n#yJ1^`n3- zEVFGvz1yd*EL%X|*v$yEHQrH?XMA4+eHI4#teSlMG_rB<60wj;-5F|`u!W#1CW7Q^ zuD=4d;S|9WA|1hp+~EJzjQWj!B@{U0JlL$ z$v3=tx}Ow&g>qN-Y>fu#=iu&rz~WK~w14F_5gN>^A8U`d!fkcdUFMjO#YuKbiVm)i zJQAIb$+n9*)kEHrn*>X4E(>6a*Zz;XaZHFTwEfI_v2t%Lz5rYbu=}Y2^t1Srl|xx- zyASuKQFgS1o%Vd$gPJ?Gj!V9yCY1WNqk zZhgqty5)4))*^mV^~&J@Tj)}{YTLr0$#eG?_W&|Py6soS_%^AxqU0_QW6KY67Xb^H zV_Se;)_!iH*P8@|zw|qE6Wb3d>Q%D4?YO#BA6Pjw05daMzU6v-T7DL4{Z3A1^Er(m zd0%M4wZmgluw;7fLn0oJM`hyUbqDy6!l@>5Zj`x!PQ`HY2pQVn-BmIBItjaILCaQp z*RGZeqy}}#;l?GL(Vdx@#TTExOXr77;``^XR`(N1jp8$}A>jX-WO*(^MyKH^0(XGP+2Y&F9F0m6RjHpKJ4g(x|(bRgi%R}t6uRqgBI zd-j!?^v$AO_4nB8pKUye4bt*52S4kcyH1cjbKXNSst?w$y%_l}E8TRp310bAnPox& zF8J#hOW`|?#FG55q!M(4YIBDUp}sFhHJMAbbmhCRLOyJ zXokeOzbI*exT@G8G7U#%`>`>kCb54WB)DZVm@SbBsN;5VeXgn3f8^`2SR3*$YRRap1I3fBM z0-5tdQB$0g1aciZtu)`2JhzPesA*$QVALI66xbcdPr|n>7@eFh<2!$R0zTd7*iV?R zeLmhaKMI3>;zSo>n=Rb03J*gtFr2~9aRV7?LiGzp%+7qyo<(w%@E=pb+*a9Y=}|O( zB<$WkE6b|cIIvH&QOFrjhP|h;icNb}Uh#hiO9aLzJd37p)M~#g@-CrfDNDMPT%0Gz z_J}2@M)lJvf;lbw+m`bldD1VEmh*$a`5nH_Z?OK9vJu(W(*%@(dWaj_D_Y556i4#i z1ukrWb$$GbJjVj>qM(Fux z5Ln@`5-Dr!$Z^uX3OU3ShW`=>{{-WT|1pOg%a5)aFn|64bQ;~&|HP~2q5Dp<{mk$K z)&tVf#FP9V>St(r#{B?&AjBo0D)>m(ry#kKOqX+2*tkOD2(KIjwZ9+xnRJv>PKlbe z6iYN+sl!@RjOpGv(kTRtsjUb$Ede)7$yJwrA=u}0|<&GjG~{t zK{~AE)_{5ZvEQ6OWTo?=CeJHV%dv`kds*2zq>H|N-?4Qe4f-&yxRKk%%@N*4okCPQ+e)K)L*!{uXsl^r=l1%}djB0aU_l7e<8h*wLctO2x5 zUXM8qVUU7;M1uqtkGlkBwIX|+S}ctUQt}{Hz<)dRGBL&$gHriAmTmi)OO~H3^$tgj0hPrYJz*FJY0V?x%E-_RP)$U z1@lcKVu5P^V-zmC{3`3S1oJDgS=62M@_Y9`N*T6%HbCFL_^@aq4ee^64z3qW`ZvUFuQ$XjVH7J+}>=7VK*E@$*68`NLIccJDRl_KEdwMw+9DH~f1nMVTD zk7m+DjwW7uTfyJvxTgz>>+bwj)UmwstOxyXCcyZq3>cT~ae*Q`Z6h8rKhE!=K9F|% zPrmFpk3!kV>{Z6@GWJ3S^OQ4U{N;9fqq1P9k%l-9jAn>IDWfC*k<#(dAMxJ1NuNk&GdEsn#uX~R?I=8T`KOYS3VLcB)Uf512k-sWh z#^%ZNPns7fOc&&F)q?waMSTZ;z!?`m8IBc^9gnG}%n$QqP%=Z$e{D)rA>xGIitN)?#w5>nU%x!tlr9Z5oX%rql?=YOth}h zv|)(>RFw3hVD9h{Bka=y{7q+Po%@HEbO$RR5hIv)T@KsR!~@5j z?p1+KLyM#15N#ges9s1PB+C*@4YsQ#1ra7~X{E};$FrsLd9!)mx{H(e&&TB)Dix;Z;|OM%s+1Lv`hcgEKdGvs!^o^eOqN8f zG$ib^RK7YjNcww--Rhowh`xs|$+7B;Yub427&+5vaf&m34z3|niEo$Wy(}p^_91BS zCW2ag{Q<1{gNLp9z7g%6B@Uv;8wnCV{LGBQCEGhoHohktyXgwTma55qqZ^{3Ib6B=QCxlhx9<=aF?gJGQvri{JH`c?T2NBzL z@3g+gyArACz-5|E)bj^nbo}|-Ltr1#Mbrgl#{xIOq~H8iFazfILiOfFtMS+g1J=>| zN9d>pJ=Acv<#SIH*O^cM3Syen^9&O+W=#_URhwau9MAq>-st{p>4;GQJvs$5siM)- zYKl!rPXM8HO1>I=W=M$$hBAG!w&hma^}Ffd?5uGZ$;+1Z(}ZFf|2#6u0JvrQHYG#p z|29~Ct@ZvO%`NzhjS8N!t3<_|rdXwri}xlr18GQQwPLMQ#F5rHFEG0P)|Kp|kmB}u z9TT^0ySK635rJX0Cu{9+Yo+ZyUn;b}(!1$#Ke)T|p-r9OepF6Tx?>V*&Sx&x(rw}F zn?7Tw>Rt_1MCZ#cSv&6!m=+V^1AX!6>AYC)Hr{|1MX2X*v|Ipg_66kq#l@iqO%wmk zn6!Yd6o1!khJ5onqVg=p4pW32KHCrf6J_SjwNJ^Qp9D3|o{|wv54Q5L?a9X)(?1bs zVWjLku@c`H!6Gqz@87@la=D0C4h4x&axyLA4}w`aVNGSF$^{KeSbTEi!JjWAm5C5N zO^X})%@E;VrQZtDoifdAhQ|}XVL~3EypzgdzRF;i7B`il9C63C=N%PYZTZtEgo3&T3E}Tp0XeB097hEtPW&pq@eIJ^>I>5>p^fFTAC3bd`2s<~#$tys zW*pbA0w;~&*5zFdTE)kNT18sobk99dE7NU&mRv&bxt`bY>)$+ohw+FP|FnmXE1j1) z*c`ii>RFV_KaAx#m;8 zD{Fv>4zP)jIF4zfS94d4iVz37MTOA!Ri9d7rACTQ_AU4+`cfq>XpKzmk~Wmj{WSep zC$^}2AisB~9&t*$RW5|#sUaF0MW;a~MUOuwQvr)2)#9Rlzx^=`hpq!B{6rot!d>+eWQZg-bJq-=$)UI`{Oi4!{@)5 za${(GM<_>Icr8k%(nhLewS@~k&BreCm`anWEsl^JllIS!X;<>)sL$U64Mb3 zuURl+&?voBNI?_Wrs4@-0B0f1oQ^E)tAyn{rQ%M@%1S;O7qt5x;>LF7HFLXK%{V@2 zW*>(K19`81j*K|=i1bzv^|x`9M=Mj`gr(!vUjDiILp+88mH2n>v}jQ5Hb9GpXZ-G5 zek_wIsMKv{kn(lCTr^QoP`LS2j7MlD0v(%KR&uN!^YBES&*G;)%hk7~Ain=-UC=P> z+54*Ofu5cc@BH0mx+Hx?S`&bS?|=l{oI?4xe~tBnEN&k zzpQ>JZ>F^|8x{`$4@Eg5%d8Dim>*CuK0F8hSa zaSX_3V{2=x84AF%A;3(=d7rY|<+mugIbesDL6-H;{Fg#gfN6fs#ur8HZfvjP&`y4Q zoa~K_)4fCt*_`GxOT3M5?i~OS9S#xXTL4(@w*TX>3P}gQGU#J@k!+ zi-4WO`egYNPgfCV)AyOF7L`5PBPozpS47yxz! z+U}*LPdn&HDY!uC02R3zE!2X0`7VPn#?178+T%uQ_PSU5C#wZp|CxB6s`r^E*1 zZfyY8kLcUqJAcX8&mC%Ie{FG#aQI-k@%6oLyEy9vN_J@;2jJWN0EWBX;KXCdG^Byn zL{9ZVZZ=39SbTZUfe+{W{KuX+Oc;E}yYJc>L)xCMH5#@vo#jf1AMD5T8H`bcA1l@J2$d_hkz9mL)6q)?Q9jB z@3VN^omTF&`$~5x#C{8Ud_gdd*m3*xbEy*~=blIH2e}D1XPz z>+G(@A3b|j^%U4gy$fWR9h;lIZ(h2jZU9D&qm7<|s?3q!&SGID5PY-jBFYE>HEC}j z>o#9;99=|7oWIGa#qo5gk@rYAD&721^-g_N8h1D`vugTkDBBYK4s*Zqx}kh0Fg6SL z>JkUud~>#_`h%K^k2;qle1C-O(a~>1tLaeBtk1EUAcfZ=;$O_kH8TCP7?Sg<;MEl` z+T;hUbs)J6uotVI5E6o7)6Xx6> zhaR9ni8$($Y@@bQDQB#?R7}#cW^-uqF?yN&m`8Mdo*T;F%EczKIc=L=$@X>ywtJRB z=JArlD9;>-k$9?h1`$J=AkKV~_pUqi~lB|%G3&nF+W zn%ihW(Yd|$5GXmMrzRjsv~OA{6vbfl=X#hD`V$M`9>Ne10DAVH)T&@Si_^9d|7@SM zfd!y*Tis{y$`VCz;~-I&V68bfx&X`NH%2N>SWi>s`#lc=?ofIf~$bYV?$Y&+;FI_j-76+eepEHE|U2nnD&+&Be3wkhw!}DftwMIGa9h$s5jJ8op z|M|?MACp)0&S;Ekw&*xa`eCH@(8M$@XL{0fOod36?7nQAez(VR_9hi`UK)NgCpLa2 zeB6}4@=T03*hGtj=E&2Rzqtkp}#Mc-pM!>0xf|sfgRI?v9SaKP#p$U$aP~MLm9!{Bv(GsL73L9Bhx#8Z>M=Y!-!*YnA(nL$y zs|~u{EeyQ zF3lC`p%d0G>ux$m1wB54JFZ0gq-WA%DWeljLE4tMCE@Mjui&2h^aU*B>RFF%BW3<~ z;}2~KLNryzL;CvMD81v}vpKttRqu(LP7QJ1onkVxNNP9CrKtX!AYehN^;V(*6QjdA zhZKn|YR>DDuU$AT(RT%rH>mByO;|b+m`CZFO>(>1ZlH<(0bF@%iPo~HG7@Sxep6jgZ^;`~vAzGZ6Mr-jNTZQKaphu~533Kh zdK&Zj%UXEtCYBNHElRt*T&%s#z*$W>UDHi5H-~FbKUT`M!O(0;Vdp6dv$f!<@q;DT zJj#-fk=7TuGSNjhqCgYULPpu+?;v`{6D+}Kgqzh1BJHY(z-x~C*l!m~+#6I(Tci@+ z7kC!YFz_)l?V-&u<{8ed zRiujc+doH>Akl^|#u-Hdo_(=$6H}&GP~P2C10+gSZ=%MtYUzwC(LDr<#21o6ioh(F zE21fcrRQRd-`DF!+4pnIZwnxalXcIwC9OH=dcQ&PGHnCbEvmG}Wb>qaqeK6t1qAVY z9K)Af1m=JtAX3^=K39#mYpxAQ%Qgv$h8I+zS{PR^HpOSEii=!R$khw0$?V;|?e5~& z#G^wTEsOWNJ)H%~mfi)DU!uMxV2unTS3b6yQH28Z?oaMduz#AY|? z{p)-cp1J8G2x9|A39yesq#&_=m? z%@G&g6q%jk;)<>pM)rKaniLNkHk#;IM23U*nY2|zsGr^LrOo)&R!vh7-`RF8q1kE zP-K{jkK7m9N;8Xek-1`Gg)M*HS{#IOCy1vU2?{!Ilgp*66x9|g4$6~3hdnkJx5T+J zAdA*nF%)A$RDpMi+*crJ>g@MlkMeAv<)zX<9rzCZr|IP=G~=x8$#-wF7?~BHP|kP+peuWm}?TYohrS2NuQ7mkEak)vMszj`~6qW2AQO@uxxIg-}to~32VJccZ z3p)BZPABj6{-Zrc9j8trJ#NOEa&{}{aV-iAFlF%Bd>!30U0?g$Go51IFhmV6Qx)gz|+upZlE;JqlwI44k*EUoeWp(nExlU!E8~(n3e@U5b$D zIw7IO@NQN3sW&Y75;1PISbone_wzju)Wpw(h@a$4r@8LN3a||FiAPJRxj}?CsXh{B^jB@h! z0u7bqD^`R=ras42`%ff2-FQ`jUeOC-Vd+1#;RqW);Iz*1YT?SWPIyL!y!YUj@{47G z&KXZRLoyEU1P)N}TR_~F`ksZOEhc9-xf4cOSJv*gR|zlSgOX3x4&J%FUW|S`K!AK- z0Z!;DY35GxF2BIorwK-zBo+UXvlls6;m%cJh3)a6bJKc@yRyO&#v52qbg{kd?tj>) zbAVA(n3DNl@>r|b2C=az83gc|*qjT1PY^Dm&86g~THT4?1RB&lz*vAgvPR5;zFJ7h zwurinIPs#Ht)H}3G>7d3jtLE|vncLakHqU6rmAdFU_x{PiUF?EDubeITVr5llPv~i zuv@%yGc3h1$xvUr=Z=`kGW;?ZVjQ|{mP5Y=F+;vV3sV@MpSln|R z=eT+)$^N4?VF$2~G7bYd-m1Coaop!VY}P9LITe&RXsZoG*RK_+)I?dK)i2#DyNV-O z=v)j#6EV*B|9Ni!FYEBt?j1LA7A>B+Kui86AT`=>1t+mFW;R8O=3eaKag$9(0xL(P_YOOUms&|%KuSBdOTY;r_yF+48nX)jj}-(UUv0ECx;V1k z$Vc?zYFhw44ZAIKMn39)M;IG}b)~-x3IIq8`CA<~KyGTl4t_)!da7RI59Zq%6@bxv zW~cP}yV$@{drIqIdk#px`9agUt)2}}KMOjKXHR$mn{vc+Y%=7VY|>m|;Zm#E%PnyA z5EYMdt>m}eY4FCB&uO`IRUlfLqVsu)f}9ZziiFZCfc=U0}GH@49*_o z?asygWh3L+e)=bbjAxgfc3w5TeO3(nFusD=rt}ZTNLm%F@xMt+P9EWgmp2!gx&Pcf z;}X4NvT5+Ma=EIR)3vFVs9Ei9uQv=GoVPgJgH*(p{R`z#2wwat^NU8ejlK-%IC6q;c*zRr6$!{PrFz)X*lDsrg$sPCj}K>)#kZ$Sywx&yTs?TV^-O z#x&WiO3(|g;6_LG6Xiko^Q%Miu3!fbAit#@c{27DIe%d*i2V?IBiPOchM%0^u^udE2FCIc48&PN3ojKs%rM$VWY}Qh|4^ z&IFHP7(h>E?=jMa8mF)Bzhv(#um$PA(>cv16L0?hJ+NYr3GwCt@Z$!q{~$6~Na@`= zQoK45NBXBP zmaUKY{uOKAN!ycpQV7^$a)5>RCZyd-eZj@ON>o)ta=g0c@A`29X@7)_GGNyJMP^;- zO5;gd<)R*7qq@SUV@R4Ww?5&iSa!qMi?J41h;Q$iNmu#WImnxAespu{gL8FG%K#T2 zY!ma;zyKE?>UAkMMxl?2IAccTJsOx25^`?vX(+g?_yU%UC?4o!(EO9IBdc= zM$SQoKVIiF=YK76yJ%doFr_>Y=} zaMO?>M$KyxhDBS=Nf6>dur_JCJol1i=K2575B){Gdzv&( z+=%evX*0BQdI~UafuUce<^teyOuI8+zLdFXxQ6pR@I13hMa7f6R2dMpy1R{ z-7JVOj5*E^bHjmHFD|&LoP9fsu%(^R>mCbJE&WsZxPOw=qTV(XFdv0;_%30z;=oAp zM}{bq5eQd?l{#it&3lrc2xJZSuDLoD;`vZSctS+l<3YplUfMrPo8vW3hjqO=wfZpv zoEs6OFu*R%Rl8oac>ZFp=hBy|5r?*Y*kZJpeoOOglbQ+P(xTSy76RYHkn}UuQdTGU z=zLI0K6(X^o@%R{unhZd!Wr-^9V-_!17n4z=<}*p%>Q7Lf&Z=m z*yZ#z*%DelQ+XlOV;*jAyb@d_F7Yk@BYiy@D5M;k-f{gX;1RERC%vw3%Wxmc znP0$-x6Lv!rnS#jz$ytU33E}pp$|h6zXZ4yF8wKCJtG_Dqn_N!ohnG+hyOvdzTF;~ z_!+}0W4>!McdfGR`L7~>Wo29rePjYYoBUIRK^Gir{`^q1Th>z%UNjX&XBy2;6ImX; zT;n1zAmR6o#hxhb%d+xFVrsfQKC(~ktDVoM)pA8QbIKOg->3v=&N>IZukpTj|V=N)!VIV+AvwNK`&?HjuL4eHg_nVx;Wm zFE(WAkKC(7I4*mHPPnOqIbbB5%WEs#e`^B{|*h}9qC zL^C4=RlQ;QSx)_3CJ5AvFSeau|79h5&dq2>nu07lpQVT-FkQwIc!$%$%vAW(Xy-i7 zz@8{mH&VGDjP5mV;&-zpT)b+TXPj%kZ*BLF*PJf&U30P7eyBvB<8R=4%x$hB;Yx_q zF~XnTac1Z8VX!{oQtF*bdgB;>-vAwP3BejsAYGCAGK_%Jp*yaxR4jlMpiy!Ct zy*{dBWyo;$JmJ16d9vy3{u$=?TI}otqM}UIbiTFui{2;m%hme2s;ta+Qg>Ma3WVcM zkp(SPHVGBe8Ir+FI`q3jzB$aiCsYkjx}!VhI7=X{tfBrYKiHh21@&J3dm zlc)boyRy^8{u@ivn>1xKjDubBct!{#e3r8`SnRY(q$y1+8>A^>;H9pn66kX`5N)yY{U@g*tSIqVK;9Tq=(HyVG*+oLvoUX1*_k`fwAQR?4k zLodmnQNCzveevn6u`5ngB=!=1;S8xo4(|Z#8EUQPNB1RKqV?2VVW~%7E`nXp!?AO? zADZ;@{5a#$=c09VPICp@DGCJzeV>(Otgee16gnAPIlm;F&7f0e`fWfL7RyXo^AKJ1 z%UgkoE+o{r2kp*#Dec6^JGWa8d@H7#G$GL?#U|hHWZBmLG^Dey|^zJ&9oO^7-0Cuj+qFuHUt-qQF1XjbB7Ko_M^n ze7k1qr(k@7%vA4Uc3#Tk=9`GTM+;L?HY~=-2SznB(WB!qSZ#L!g;FTm8nYl0&nJv$ zX=b1S5<$An+fSx{~C6Z)tW%>5BWw35E?^hm#m{A{MgH>*F7W+1^A@hiW{ zEWldrKZns$Y&?4dYxAM7nWP;F6z;f7F0B7vHCtW|p11*rU-NWsd|gkO@mOKXF$+lK z?AFAhk%2k5ETI6}4`+Qxdm`?V{28aTbeVtVNm5lWh6>xf7YY|`aNnMcooQ2c4mx7- zbB0$XmiJ}JM_Ii!8VfhdckRr%<}saVMMU`r7G5RfX?_)fkNy;Kt`a}nOzQ)i|M@wX z{X6+X9h0dJ$1+D!39NKOZvQOc>Bcq?rFT46Vl%GPu!P^y-L#NE3i8G9xT#$MX&+Ll!OZjT0n@|!F87FrCKX9 zYaDfi6|bDQakJ;B*$e^Q_Hq0!OKJz%{2|pO$!hv%-OVF?Pzu^{k>xQWJ*}vhY)iA^ zH=CaJ+d=2qb6<&(t*`8-755D=u)19I z+PwSn{>m6}YaLA4FWj0g0rM-UoX@?KD*r+)^VL2XvB|aUMOek*Q>6$slDo(t&YHcQ zkFYp$-^VUc8M)LH-?`K(Ps!S!Pt&5zSUuk*yoyf(88pNq1kd5wCtAY<-LTH^&1BD*_~!1Gt6e-8uzZXK*O^M+=~T zw^Bu9GHQQk#I%~~t-VkE=-=b@_@NGZCs_b%vy!Lgv)(T4bXThh82bz6m$GENClH^?W$?hE|{>I?|Ey z<5ntVM+}qZylrSC%UrYdYXi2D_hzb%)am$eb&KkAb{}JH4({fiY$$XY3?K{weD)^ zqd#_bfgA{^;!<>X1V8Akuj0e(=U#-v129ANNaX4}l5B=Zxzhc&y4v%i z4|v4++9LY>Ts&YQ*DIS+-z=z~C`AAKmrMJw{rf5CfEL?TSJu5w0dI?EFCULQa5T_V zW65+@L7L%O7Enz9&JkPwlIj+M`{Q*_c=C?`@S7J?3JCZk=77boY8^iY;W$xzDJeyz z!gdY5x9bD2t~qd$0DUht8m42{yO;c!RyGioA;`~H^3Gb)Q0ABlqZ=GOzX z*3G}wYg%96-O^L1@1Or8C(ulvbaVnnqp?_%U3Yk6=$-}pCfXEsrz&6k zN4lFfaXlw`issJfCrQ&W-6y$^ac*QXoS3L?T z0)~$5z&KbB7zb^dL$daefK%PQ^yI(5>&0K?fti9wfx$0+E2}`q^sM)bt1d#X1VCHq z=)O5wPY%Ug(JZFdyz|@s8Y>zpMfsNxbsP3L@Gk$>UhYNJJMYzl_a4!@eZxzUvUE2C zP>N0fVknKHlu>Xg_&4967U41-;BTl2m7<%yt+!6#M}d*DKf~szo`^{~uAy#w`i( zJ~JQs-@o>8qj|Z71TGlkes+WY_2{0iD>P*Zq}8o{s}2GeS9tgo|6|bAnt*OFoul=D zHu5&aH)~ysz_Bic{Nq$l2Zmn|7!rUP=2!;ZAA9kKE8J=9rm5oxMJq-Yz~v5@!~<7G zp|bmJ;tEf1fqpPC9=d#G2OZG!jr*`|zg8A0Tus z?w`K)Jf`Im0Ip^)J#6_mv$Oxe+ALS$51xg}U-;W%+!p5SABQx0hKJT-f`|Vd(hGH= z&d2}M@uV{pfm+8L2M~SpuZ}+Wj*V6!qfvx@fV8?&JD?2zd3AjYGE_3R?8&mM?A9WI z-|jT=`6xh)>iVeXcM%F2$kT&mzNWU-*3?u)ZNz?egq09d6Nr-gex=**(}qhODZ^{a zp35v0=6J%Za8MicW%Ht11)7>;R(}?+wWFQk9(Hn7WBqOx14KDuT3lOAE z?E8@4@`*+3h7({ppV>wwNq+oRQt4dl?HRlzO>j2{EbFv=_&bB5sD8rF!Z>^G&XMcl zDx{C)s5yt!salUOS>Ircct?8gq;jm$3%sM;)wi$eLi>KCWQdZ6InQ45^tG6by<3{V zxnaJ3N(?p~eNBTfD`~q~ZRmD3&V+f@_YC5_q9*(N2ml{nRd`4W=vbGbNtRr2{)o*??W0Z(Hd2DNPH3#NP`gjWnhkbP9Bi6zPQ5?!RwF~R zaNu|O>Oaovw@P>@R@mJDmbz%U)m3f-Fsx`c#2oL%fhD0z!kTB4tanS^p4P< zscNw{^cZ!-O?heDz<%}6O7JeSMaRMSE3AFWA$c>#kv%qEI0L=CCU2vz{yJ253d*5{eS|UIn26_1tPUdCHt@bZ2&}B-z%yb=)rirf6*a9nD;I89w>}9f9Wko*=?8(im*D!6;Fo2~_T*AE za<9phcST`ixkIWhrn=6bIajP3bqQpYkF_Ej%-l6B-LyXKI%Y#k$_r;*05VYm|Ld$S z2D6`hv3Ik#@;+4;{k6Uuc5c6{zs7n*k*CQzEQr&4BlqP>?GqXES^^U{=fcpuW$F9; z_1;C-p9a;BWD#<@AF2dnE`hwidS&ijs9C83piHfT$BiOkX0lz<;6q)BPjG!z*E2e` zAb{r#c=G|`X^+9xla6H=#~AptN9H}0>|C$K@8LOOb;NuTp(Pd0($RReE?>q zM6ZsYIrrHMJ3{R6))^>$t_hjK>Ww-0hnkA!$2$Uk?A?Zo(u zR~MW5MNm;n9)_4supH8u!Z_AJNFv#IjxCvnmG)J*TLWHN02dvI=XM`6MOSu#Bt1Li zyo>bQz_v96m#O?QKOGnjX?PO9G7q)!>Wz?XagdUE`#=VpnK4|kGvn#twlV1QV{Aj| zbo~atX9zIjhKE_dgd~kT6zLGFx51R{)D;$hrBwa9N(k~SbD@&$(5DN)De)kZge{c; z`+4EjRv?r7uLo5TgB7| zje4%MCm3~Ik=ZMm&yh#>jY7+ZrWn?E0(}gjx#g*80}{o}Pk%BoMigPROOkU7EnWMW zd+9N+VvT~bp|<*S-mU$uuxhyR9I>&3a4-B^MoxmquyuiPDr~znlR(j_Mn6mI+}IK0 zxqXeH*~e;59Mj^z8sXV9cwt3mG09;!|5`;(_2=88Vo>w#2arZJXgI$x%6V!!B5oEF z<>=Ng>1&{&o6x4UVhi1s@X80!WV6|F?w*sFGf?D^O=FNw?(Bm6-i2w5<#irVN*UWr z0Jv%Z;!6H@NVuhBD+Y?cw@ z!X%7JhY}oWo=*N)A9%6S9wynM_hpP1?DK90Pjv#0s!R=Wi$)nUSPY_7u@|^_qI-%n zBoz(2stc*=7MoD5(lReEYtONcv$6=(baECd%_zavn}C%ec+0h6ENnk!M%GyR@gPSW zH{yO3l>St?`kb#m!UyY2olY8qeI{nUdk6wc2}!z>bzDA{C&-c9Rb1XxQP1u73oadh zPvoK~@s|vwwN%xzjq!f0v+-M`wC-*=toMBylX*1q5R)w$=|6U8qBThBiZ^L3(}Vg* z*$}k6A(E%8T3T#sX&TT7D`J9+AFAn(3iOV7(v#<=kJ7Hy-h8< zI8JyXt3g4ai*=!F56w(e(XZ?5!`~(=Q;O!mX7(Z7BrR^{_}zmnx3_+GSLMV}EC*M+gt6?osPPcASq+ z8gwpn7|HGaj}~CqyjGgfe1%*QG5aC!;oiTR1^kkNnl;ej*aTv2ion+b4Ad+y=SsUgG>! zY?+w6t?Qb)&E4TslQ!RYeuRR-b&ac%hwL%K+mz0}xfl>kLS;_E)u;62hTrW^0!vD@dv9xN+loh)$Rc{C z`N~E}Q$*jsZt6Ip&$eKSf^4;m)MTJ^+TSuN3SF?-gd~qrm)whLd$vLZ+Ka_e!}6B9 zyR9B(+apgSGv0?&$sXIomr90PN1a(J%a zuKi2{JSO(&T>ECxeIvVHb2lcy?*R1ST|p7zF2Ebm$hQLr6ktD^08UY?nq)VUpkF$m z(J~q8!w)S-!*2^AA%0bDWA_*6K0Bv(XvssCeHQc;86ff$!iLPE;s$i(#pX?@!@!il zL%3*%VsAOFV+pp*LPcOaLXupG@c1R=N&{@E!yf6bfk>{LcFky4L6jo<`&2KVVwo41 zH>PCXt5T|3CkPhNPT>8@Wj8-f#+?Rb0SV;L(?AePe%Ss#_tNZW<=m^Fxk?vDA{ZhQ z<8BM7_Mzk}I&Icur?FcBg=CP2a*%c5xP$elv>$yR28w~G39c{vIq0?NG@`Zxa=56g zI?i-;kyqNYDY5zNnpac@p{>U9i+MG5Iet9O>LmWv-50jOWa-80?$M>SRg3S7YuP8H zXMc$(S`Y2;$LHe;IvA>)2B=WU0(n*NiK(`iyWdSRK93_`_=L?jz+CMsk&f|{PAm71`cAGa&uwO-eXwU zv&6F&MnC4Qf=ie2tHmL(CXQ60X0Ov~ue^n|(2Dj^UV2T&k0~LoO@`@ssx6ZJ4eFJP znJrQ8Fqpx`%t&YibCMf!N3M#Pn(Ws6*JfqDxx0Utr81-*9#g;mIcfEgjAus`8(liXdbz5u{vWr#nw>5`7%WzprvLr7SN>*&P$R`ol#l1+Ko}+wh7(cAz zk%r(Wq@-2$89W;H?AB)970p}KrXY9esi$*eO&h?2glXktC8alJ5c}9Ztpbw3OCdTX+8b!UR>VicI-(XfZ;+SCuErD^t!kF?I}e6;i3q2{b{nko00 zKrImLucdH5x~H+dF6p(@UK~oY#+fpFLm4|91!k$hZ^sy^(CW<} zG^U%!?~nEx`BV-x z8_z#$*DAd-DwF3TF)ahh-AllJR_m%<#|fxNK4?FhIRx=v6w8t{;ymTyFs#I_Upw9RC(BpRx57-LT&n9 z{Duj0msFeVWuA^&e1@ZJgyCj~{s{SmKYVcS99;h@e$E$h3;GotL>aP*S`M0DIklO% z*We9ZK9ylz_o~?12P>ncv%kk8UzPm0@YLi8~rZp2{*Y0s=e3CggjhhDDA3E?&O3AJ_QODl!M@_}KS>cR!y z#cP@Vkv5({8ce$+q}XCjZH`yTBZt`VD_@#mkG2gctpn}>J?F`HO^w79f`{<(1o*{q zryc9D@a3^CPkXzqNs^=I1;^`~<+*p=s&KE%YqyJTQgl4KDq$-sM&w?*5y~(dm+;Et z7^oA;uff*T)pp9wwU!z35xY}9pmYvg)m5W5?okx=v#NV^{-eo>M`nV#X~soo0HJV2 zZvHv7bS*Y}i9RE(Ft$cRDZzS|uf^T0O7T(J13v?DQ^4%d=w?Juzc^5K9m;c5!0VJw zyx&}5>%>bDh@*qT>gNx0RdyW#A0eh?3?Tbz($DXJ;lN#KYNg##ACP;*|0NeAxj_pUhH*AP4!_G0gCM^NU|_YZ z`Ruhna5(G3B8x4+ zz%)(DB1a?*<}s7qHa>o<*D#u;JV=}L6)Ed%eu^KD49fQi>^vJovqvAj3Zz>Cyj6Ne zPbOBYViXoMxLT^*R)SYno$^DlQX^?rx~-Sb;tu@Gzg_+uBA5E2t(+b{giY)DK#Jv` zNgOkiuAMHHH|i|p0P%{zW+NtgtqvePtsIOhC0{>7S^`q4n;$=-2Z@Vnf(n{1eyQn%YthFv+Jl|EDz)g8t4A00z?jiDNChWXXCm7 zc9)i)sSI&G0D!MI1Op)fjUF}Je6m>Va5kd=Y1tFbj-_JW z{~W0k*j^kJU zaU9+i=%Y}l-`!uu|5E$8U*c}2jP=hid0wUnzwt-qPm@l+*t<}cwy|qId-^`zpOJZH z=Uy&B`V05-m)1zn(({hQ+&6v0-*Pw>NSC3eW581i+2Ie#cZV9<#w6UNub4ZzwaU>D zX;oXQaIl5XG%9(`C3;bQi_;9!y9FnpsyEj`l7E7sAxvl?eL)TdT?CLP36w#ASO<$G zVD~ctu;U6d%QHQWqo2{>RopFuHW5 zIjnFI>{SwlA7a|YI;hhyIsnuJiV$}0I)dDM_5NG(eM>^Ay10lu(CB7Y;vy=BDscSj zR?R=Sw2}+Rsv~i4F9s`X5$Vgen)nWO35yP;DFl^6ICPas9fw z7c>|_|7pX-K6tU%Leuck2K;LRCl-WvMOg3OW;slw$g{GtDu97{?Ry$tFIaN>_VrE) zdV1YRUhvAV3D3n#+Hqpe!O^n*fBlB<&8$FvyOkNu5s?BApRHdEY2V)7H$C3zeXGaD zq(z>^;15x&(%tvcV&fC)p3L`3)MX%of$S2$&G2XUI{CS~yYIMpKharUwP+@nN!A>? zeK0t2_4+#W4Bvh})J&}xv^>@PZLruvFKvm}Am;Q-XWO5Ns)^`!NNC6e6^HVtcl;B+Cp8P z64Ac8;EMRCt^2rvelCN1M~)!!G>pi#{tAQ=UKh#|ddSNk*}h{s9(<4za)2oVeFu)E zi6%x_B3Qj*D?Mu{NFAq_reZArY_}(a;nbOOtSp&I6_{V>6C&&eNc@QvJwf6KQD3f1 z?mO}_-7kSaAZQ_E;JQ87>hjkH3dva^(KMHjr^Z0=(c^c&9Qh&R?xd9JH`iUAp%FgN zON2SS!hhL`)J@!q){n!^rUVQRCi`C_4*V%K1W@AQ;$*S1Q%#Y|eoNmIr7W(9UBSaP z&88A0CVu*>9%K4Xa!zg!2P@zFS>UD-!Xc7LCe;TpxYQH^Hw|f6ki(dJ=YB!Lb<>B2 z;e`bS3q-KjV(cT&0nO`Iop-l<5Id2nJPIC*{mvlJQ}jsgiN8w`_O@5k4Ie(_at;qw ze@>de(x~J&`F&nLBd;k;)rDlU9}+Y0*6PWvI23g@Y|emW=f54xIpU1T3U62KEJbD9Setcd2z zxIMAz3QVBmPXAwYbS!0e)o(uJU$T+$utYzHQrxvhnr$4ecHph}mUF-f9=4LUK8^;R zO#P4ICCi8IclOLyByVda&i2ec8sPs+$y(XIK(}UWf2iDSnEKK@v!V#PBAYdWi@bjl zS$J^@!nlp}H87d^ntUcv$$ocZp=XviY`G8R4tiW?8)-DMeEqMm*`*Xs!aY;j3o66D zMVbi1moJ~8<*ngg+^eZ;c@axf(y*cpN6AQiEnZDaB&4EGNdqf~J;H5&qM~nQzidui zVa|r_+@NZ^PbbWH*bb5TLfM^CseKjyabUR==w{uQDeOjFf3bC0r}9Ptp)G^_4HI7m z%Y0!&$RAQBZJ1jrZh3Wh6uJ{JDP>q)Bf=ZF)=Q`;*O|u_-Tf6sBI-g{^SLehF#Tz( z&>FD`+<;FhByZ8XwA|U_)Ij;Nt-H&q0V&k5ivDbQZkL)+^c_T>6;-vMaO9@H1DEV$ z3eU8)R@25!2$DYjxb2V?W%3@Oq;sQ~QhtZQuPc#UZ9)!#JyA_Xr>;mPgRNEUH(pj3 zg%M;XZ~+_E8|yYZ=F1dCi!@Dl@d%Gd=ip`WEtT0_e0y` zT)5&F_)t*~FzN3~AklgsolEN*JyoBpIlTPgh1a457mm(P`TO+^Cj4$zFMJS{1D4`lHZ8En25NC9O9a zb2>wu6{_eLvwS8k{n0gI&}|R%`*|9p;hey2{jK0JJ=Eg1-PlR%%FD3>V&n3b>hkBo zwDRFRGxYWDX?g7$sjz%@dQ9ILkIxlk@xPLAb{FTaG}e)=iZrIZueu5Yt-OBrK5hRD zIXKi>S;rH$8CP>=wYu*-t^SoEg+37luW7u1Gq_S;@Yh|w23O&Mj*+itdcQvB^A?mP z+^#qaG;n_Q^jYg);MhCK8+6mn<|n)ST1unjr(;i1>JXjykg+=C^COu^Wn)sF!oHm2^!|cK? zYfZi-6JoPo_xseh&OMS3iV;C|ze*Ep~iMc7_D($D&m+wAG4omjkmssS?W>>zeO$!8%sipI}e0>rw^GRyH;!0w= z;=a>L-AYNu(0GBDNkX}Em_5)6SA->uFY`6TZa4kpW`Y=k?bxmcVs4iK7`|)FPX`ZA zzc}7#`8Dw!xJj@dUBhu0Rk~!8W@b5b!@}+e(1&a4tnzm=KJ&i$&ID@4Cw=?{HF$GS z2|Wdv#Cn+g@4fhSA)@{{pG&9yetZ2=^HQTBX3T~*aL?X8>KE%OvNVauqe}Ktt3uLN z)1Ekf^^|q-Zx^DKEiVEX-Gk`|vH`xSp`vn4>^ASj12+3pAk!?spI@_U$B-;J1hFIAEoV7FV}Tc zI%|dTS&c2v`=@B(Ic}%U3;ggOx*yMAxYn$oel70Sbhx3VTo|GYSl7>vPc4vdC4tvT zD!gYYPE5e|4K^YKU;A2i;zTDY&rgIo2S2@{nf{Cga&q*;Av(IJmg#db#>kWGV_Xvp zyg;@&^N}ruqfxA&j%%&_ouZ;mf+g=1j~==Uv`xng!l6mKMA41b)7K6{)B`xc z&q>Lnz}p$$f>4FGqXnb}+jzaudYP3}+EQT(YJt*QD5nn{w*J|2wsI?HwSr>Wu5dfHLKm2-OI z#n%9PEjM9+k)W;in5IN%sB^Fyu-*Hdd6qAOXw7krpO!yq>J+Mxjy*Nj!gT1sB5vN1 zaPkcQ$;(bN;Wx~VjoP)g10(ucCgpjF0+V+P=V#t3Km-J4bC)k!=`U?4rfIfPuidk% z9eo4rr=J}f0*hyVP=!R!GaOu8wKon=XJpU6y&EkReG{(Pid>_&;G%7a&@C1pOEotO zr-KW5BK25Hhf!};sk3cn$C;6*Iruv@SVLo znzL_dTOgeL3w?%tSTrh-4)AJQy;fmfO_MJ}64Lf*-+t3NioVP~Cdx<4{G!b;&DAoW zZgHtyc~>N8OrTwn>8w?I{OttG^bb<+=NHNV3sv-+5K#wz_8`T>Y`}YIfH@(H8t()x zzEBpGrYhSFzrz-Cq~)$qw1WFitkh$5bsOOAM!@IAJN);zhvB?}17G@3ci{Qi+1dyo zTFUB{m$F5->gkDZ20h2Hi*=L-)mg#zS;N+1c4#TnhHz z71bG?9Lm&{XiMKaX_|M++5wuAgV-83a* zeSPOjNkfpwUv#gTo5Hw#Nb?LKp=~h;-4NCzosqOo&>cfxiW8tY*XF%ZXfy=(eQ?pa zIb!qn7KokBnyx9;1(@1SiIDd8IHb1a25RITrB#8y`q}Y1@iudhZ8Kb$?)m#mr%Wc7 zO1qSteLtbB8hnV*pPRB63EA7z zH)KplK%pW`boU<`8NpRk`DHx9*r)EqjMDZGoiK0~USn49UP|mfC8En;$OFpqUQ#%8 zZ89e}H#a~34gs}_FP>^XSoT{m;<=k)0bTIb0ayE-oEQ-xfDl-}io@uaQ1u_JG0n%m z-O0?#^47*Ca)|6`hVzf%Hu>{RXse;4-C12z;(Wp)oixHSJa#LmnpunAFi->N+-U_!l#9e`xmI58+0a}38XmKFisoz&EH0*A1 zA|eEorJprS_hdAssDh$&;b-ZrmCl?wBkg?4@A6VH@Cf&kv4BY3)J2SO2>>T3@Zp;H zb@d7xw1e*5il1WO?i?`Z0r*gQ-Bcye`Nbx^-XM>X{lT0!evMN1>h7KGVh($cR(oJ< zY%FElZ_}vgu{)UE#xy0M8OaZFo(vpr7kv81};1ecC0 zPweaJbNfc$WRy2-LhU*10;(Vr57W)1kn+X0Ux8FLwkiT^#m!g43qx_9=vf9UN@aed z?51e`vh>K$#rh3i(SoTp5@N2Va!#mSu|z9f?deKR@y7%o&pIYId8Z#*0Q|I3){NdgV*@5?`+m;*o1)8?;7=z^lDLem<8Wwgfc-quwwRD1f@{{Rf`u;Ks! literal 0 HcmV?d00001 diff --git a/docs/full-guide.md b/docs/full-guide.md index 5df7f1a0d..e6b3fba3e 100644 --- a/docs/full-guide.md +++ b/docs/full-guide.md @@ -1347,6 +1347,8 @@ FastAPI 提供 RESTful API 服务,支持配置管理和触发分析。 > 说明:`POST /api/v1/analysis/market-review` 采用后端与 CLI/Bot 共用的配置路径(`GeminiAnalyzer(config=...)` 与同样的搜索/提示词构造入口)。Provider 兼容路由会优先识别并使用 `litellm_model`、`llm_model_list`,若未配置则回退 legacy `GEMINI_*`、`OPENAI_*`、`ANTHROPIC_*`、`DEEPSEEK_*` 键;不会新增/调整 provider、Base URL 或 LiteLLM 路由语义。 > 审计依据:优先级与回退语义以 `src/config.py` 的 `Config._load_from_env()` 为准(`LITELLM_CONFIG` > `LLM_CHANNELS` > legacy)。配套回归见 `tests/test_llm_channel_config.py`(配置源解析)与 `tests/test_market_review_runtime.py`(共享装配路径)。该接口当前仅提供单进程/单机级防重复能力,若为多实例部署需通过外部任务队列或分布式锁补齐全局幂等。 > 说明:`POST /api/v1/analysis/market-review` 触发后,报告会以 `report_type=market_review` 写入历史库;你可直接查询 `/api/v1/history` 或 `/api/v1/history/{record_id}` 获取历史 Markdown,避免再次触发分析重算。 +> 说明:`POST /api/v1/analysis/market-review` 的返回与历史持久化都会包含 `market_review_payload`:`market_scope`、`sections`、`sectors`、`news`、`market_light`、`indices` 等结构化字段。Web 端 Markdown 渲染与历史详情会复用该结构化字段;若结构化字段为空则回退到原始 Markdown。 +> 说明:`market_review_payload` 中的 `breadth` 仅在行情宽度数据真实可用时下发;当美股/港股或接口暂不可用时不下发该字段。前端显示层需按“字段缺失”降级为“暂无数据”而不是展示 0。 > 说明:该端点若返回 `task_id`,WebUI 会轮询 `GET /api/v1/analysis/status/{task_id}` 展示状态。状态为 `completed` 时给出完成提示(报告已生成并按配置推送),状态为 `failed` 时在前端错误区域显示 `error` 原因。 > 说明:`GET /api/v1/history/{record_id}/diagnostics` 支持历史记录主键 ID 或 `query_id`,返回 `normal/degraded/failed/unknown` 摘要、关键链路组件和可复制的脱敏 `copy_text`;旧报告缺少诊断快照时返回 `unknown`,不影响报告读取。 > 说明:`GET /api/v1/history` 的列表摘要可按 `stock_code` 分页查询同一股票历史,并返回趋势判断、分析摘要、模型名与分析时价格/涨跌幅等可选字段;旧记录缺少快照字段时返回空值。Web 报告页的“历史趋势”抽屉复用该接口加载同股历史。 diff --git a/docs/full-guide_EN.md b/docs/full-guide_EN.md index 223a93957..b5d7b223e 100644 --- a/docs/full-guide_EN.md +++ b/docs/full-guide_EN.md @@ -1179,6 +1179,8 @@ FastAPI provides RESTful API service for configuration management and triggering > Note: `POST /api/v1/analysis/market-review` follows the same runtime configuration path as CLI/Bot market review (`GeminiAnalyzer(config=...)`, search setup, and prompt/rendering pipeline). The provider compatibility path prioritizes `litellm_model` and `llm_model_list`, then falls back to existing legacy keys (`GEMINI_*`, `OPENAI_*`, `ANTHROPIC_*`, `DEEPSEEK_*`) when those are not set; provider names, Base URL, and LiteLLM routing semantics are otherwise unchanged. > Audit note: priority and fallback are defined by `Config._load_from_env()` in `src/config.py` (`LITELLM_CONFIG` > `LLM_CHANNELS` > legacy). Regression coverage is in `tests/test_llm_channel_config.py` (configuration source parsing) and `tests/test_market_review_runtime.py` (shared runtime assembly). The endpoint lock is process/host-level only; multi-instance deployments still need external distributed idempotency controls. > Note: Once `/api/v1/analysis/market-review` completes, the report is persisted with `report_type=market_review`; open `/api/v1/history` and `/api/v1/history/{record_id}` (or Markdown history endpoints) to view it directly without re-running analysis. +> Note: `/api/v1/analysis/market-review` responses and persisted history include a structured `market_review_payload` with fields like `market_scope`, `sections`, `sectors`, `news`, `market_light`, `indices`, etc. Web rendering and history detail use the same structure and fall back to raw `markdown_report` only if the structure is unavailable. +> Note: `market_review_payload.breadth` is emitted only when breadth data is truly available. For markets/feeds without usable breadth, the field is omitted and UI should display `No data` (not a misleading zero value). > Note: when `/api/v1/analysis/market-review` returns a `task_id`, the WebUI polls `GET /api/v1/analysis/status/{task_id}`. The UI renders clear `pending/processing` progress, shows completion feedback when status becomes `completed`, and surfaces `error` content on `failed`. > Note: `GET /api/v1/history/{record_id}/diagnostics` accepts either the history primary key ID or `query_id`, and returns a `normal/degraded/failed/unknown` summary, key pipeline components, and sanitized `copy_text`. Older reports without `context_snapshot.diagnostics` return `unknown` without affecting normal report reads. > Note: `GET /api/v1/history` list summaries can be paginated by `stock_code` for same-stock history and now include optional trend, summary, model, and analysis-time price/change fields. Older rows without persisted snapshots return empty values. The Web report page's "History Trend" drawer reuses this endpoint. diff --git a/src/core/market_review.py b/src/core/market_review.py index 5eb08c508..f9ad560d3 100644 --- a/src/core/market_review.py +++ b/src/core/market_review.py @@ -11,6 +11,7 @@ """ import logging +from dataclasses import dataclass, field from datetime import datetime from typing import Any, Dict, Optional import uuid @@ -36,6 +37,14 @@ _MARKET_REVIEW_REGION_ORDER = tuple(market for market, _, _ in _MARKET_REVIEW_MA _VALID_MARKET_REVIEW_REGIONS = frozenset(_MARKET_REVIEW_REGION_ORDER) +@dataclass +class MarketReviewRunResult: + """Structured result for API/Web consumers while keeping Markdown compatibility.""" + + report: str + market_review_payload: Dict[str, Any] = field(default_factory=dict) + + def _get_market_review_text(language: str) -> dict[str, str]: normalized = normalize_report_language(language) if normalized == "en": @@ -83,7 +92,8 @@ def run_market_review( merge_notification: bool = False, override_region: Optional[str] = None, query_id: Optional[str] = None, -) -> Optional[str]: + return_structured: bool = False, +) -> Optional[str] | Optional[MarketReviewRunResult]: """ 执行大盘复盘分析 @@ -115,6 +125,7 @@ def run_market_review( # 多市场顺序执行,合并报告 parts = [] market_light_snapshots: Dict[str, Dict[str, Any]] = {} + market_review_payloads: Dict[str, Dict[str, Any]] = {} for mkt, title_key, label in _MARKET_REVIEW_MARKETS: if mkt not in run_markets: continue @@ -125,6 +136,11 @@ def run_market_review( review_result = mkt_analyzer.run_daily_review_with_snapshot() mkt_report = review_result.report market_light_snapshots[mkt] = review_result.market_light_snapshot + market_review_payloads[mkt] = _coerce_market_review_payload( + review_result, + region=mkt, + report=mkt_report, + ) if mkt_report: parts.append(f"{review_text[title_key]}\n\n{mkt_report}") if parts: @@ -141,24 +157,43 @@ def run_market_review( review_result = market_analyzer.run_daily_review_with_snapshot() review_report = review_result.report market_light_snapshots = {run_region: review_result.market_light_snapshot} + market_review_payloads = { + run_region: _coerce_market_review_payload( + review_result, + region=run_region, + report=review_report, + ) + } if review_report: + market_review_payload = _build_combined_market_review_payload( + review_report=review_report, + payloads=market_review_payloads, + region=persist_region, + language=getattr(config, "report_language", "zh"), + root_title=review_text["root_title"], + ) + markdown_report = _render_market_review_payload_markdown( + market_review_payload, + wrapper_title=review_text["root_title"], + ) # 保存报告到文件 date_str = datetime.now().strftime('%Y%m%d') report_filename = f"market_review_{date_str}.md" filepath = notifier.save_report_to_file( - f"{review_text['root_title']}\n\n{review_report}", + markdown_report, report_filename ) logger.info(f"大盘复盘报告已保存: {filepath}") _persist_market_review_history( review_report=review_report, - markdown_report=f"{review_text['root_title']}\n\n{review_report}", + markdown_report=markdown_report, region=persist_region, config=config, query_id=query_id, market_light_snapshots=market_light_snapshots, + market_review_payload=market_review_payload, ) # 推送通知(合并模式下跳过,由 main 层统一发送) @@ -166,7 +201,10 @@ def run_market_review( logger.info("合并推送模式:跳过大盘复盘单独推送,将在个股+大盘复盘后统一发送") elif send_notification and notifier.is_available(): # 添加标题 - report_content = f"{review_text['push_title']}\n\n{review_report}" + report_content = _render_market_review_payload_markdown( + market_review_payload, + wrapper_title=review_text["push_title"], + ) success = notifier.send(report_content, email_send_to_all=True, route_type="report") if success: @@ -176,6 +214,11 @@ def run_market_review( elif not send_notification: logger.info("已跳过推送通知 (--no-notify)") + if return_structured: + return MarketReviewRunResult( + report=review_report, + market_review_payload=market_review_payload, + ) return review_report except Exception as e: @@ -184,6 +227,118 @@ def run_market_review( return None +def _coerce_market_review_payload( + review_result: Any, + *, + region: str, + report: Optional[str], +) -> Dict[str, Any]: + payload = getattr(review_result, "structured_payload", None) + if isinstance(payload, dict) and payload: + return payload + return { + "version": 1, + "kind": MARKET_REVIEW_REPORT_TYPE, + "region": region, + "title": "", + "sections": [{"key": "full_review", "title": "Review", "markdown": report or ""}], + "markdown_report": report or "", + } + + +def _build_combined_market_review_payload( + *, + review_report: str, + payloads: Dict[str, Dict[str, Any]], + region: str, + language: str, + root_title: str, +) -> Dict[str, Any]: + normalized_language = normalize_report_language(language) + title = root_title.lstrip("#").strip() + if len(payloads) == 1: + payload = dict(next(iter(payloads.values()))) + payload["version"] = payload.get("version") or 1 + payload["kind"] = MARKET_REVIEW_REPORT_TYPE + payload["region"] = region + payload["language"] = payload.get("language") or normalized_language + payload["root_title"] = title + payload["markdown_report"] = review_report + return payload + return { + "version": 1, + "kind": MARKET_REVIEW_REPORT_TYPE, + "region": region, + "language": normalized_language, + "title": title, + "root_title": title, + "markets": payloads, + "markdown_report": review_report, + } + + +def _render_market_review_payload_markdown( + payload: Dict[str, Any], + *, + wrapper_title: Optional[str] = None, +) -> str: + """Render Markdown from the structured market-review payload for file/push compatibility.""" + body = _render_market_review_payload_body(payload) + if wrapper_title: + return f"{wrapper_title}\n\n{body}".strip() + return body.strip() + + +def _render_market_review_payload_body(payload: Dict[str, Any]) -> str: + markets = payload.get("markets") + if isinstance(markets, dict) and markets: + markdown_report = payload.get("markdown_report") + if isinstance(markdown_report, str) and markdown_report.strip(): + return markdown_report.strip() + parts = [] + for market in _MARKET_REVIEW_REGION_ORDER: + market_payload = markets.get(market) + if isinstance(market_payload, dict): + parts.append(_render_single_market_review_payload(market_payload)) + return "\n\n---\n\n".join(part for part in parts if part).strip() + return _render_single_market_review_payload(payload) + + +def _render_single_market_review_payload(payload: Dict[str, Any]) -> str: + sections = payload.get("sections") + if not isinstance(sections, list) or not sections: + markdown = payload.get("markdown_report") + return markdown if isinstance(markdown, str) else "" + + title = payload.get("title") + normalized_title = _normalize_market_review_heading(title) + lines = [] + if isinstance(title, str) and title.strip(): + lines.extend([f"## {title.strip()}", ""]) + for section in sections: + if not isinstance(section, dict): + continue + section_title = str(section.get("title") or "").strip() + markdown = str(section.get("markdown") or "").strip() + if not markdown: + continue + should_render_section_title = ( + section_title + and section.get("key") != "overview" + and _normalize_market_review_heading(section_title) != normalized_title + ) + if should_render_section_title: + lines.extend([f"### {section_title}", ""]) + lines.extend([markdown, ""]) + return "\n".join(lines).strip() + + +def _normalize_market_review_heading(value: Any) -> str: + if not isinstance(value, str): + return "" + return " ".join(value.lstrip("#").strip().lower().split()) + + def _persist_market_review_history( *, review_report: str, @@ -192,6 +347,7 @@ def _persist_market_review_history( config: object, query_id: Optional[str] = None, market_light_snapshots: Optional[Dict[str, Dict[str, Any]]] = None, + market_review_payload: Optional[Dict[str, Any]] = None, ) -> int: """Persist market review output into the existing analysis history table.""" try: @@ -229,6 +385,8 @@ def _persist_market_review_history( } if market_light_snapshots: context_snapshot["market_light_snapshots"] = market_light_snapshots + if market_review_payload: + context_snapshot["market_review_payload"] = market_review_payload saved = DatabaseManager.get_instance().save_analysis_history( result=result, diff --git a/src/market_analyzer.py b/src/market_analyzer.py index 939b7803c..f54e1f22e 100644 --- a/src/market_analyzer.py +++ b/src/market_analyzer.py @@ -11,6 +11,7 @@ """ import logging +import re import time from dataclasses import dataclass, field from datetime import datetime @@ -101,6 +102,7 @@ class MarketLightReviewResult: overview: MarketOverview report: str market_light_snapshot: Dict[str, Any] + structured_payload: Dict[str, Any] = field(default_factory=dict) class MarketAnalyzer: @@ -138,12 +140,9 @@ class MarketAnalyzer: self.strategy = get_market_strategy_blueprint(self.region) def _get_review_language(self) -> str: - configured = normalize_report_language( + return normalize_report_language( getattr(getattr(self, "config", None), "report_language", "zh") ) - if self.region == "us": - return "en" - return configured def _get_template_review_language(self) -> str: return normalize_report_language( @@ -153,7 +152,7 @@ class MarketAnalyzer: def _get_market_scope_name(self, review_language: str | None = None) -> str: review_language = review_language or self._get_review_language() if self.region == "us": - return "US market" + return "US market" if review_language == "en" else "美股市场" if self.region == "hk": return "Hong Kong market" if review_language == "en" else "港股市场" if review_language == "en": @@ -230,6 +229,24 @@ Focus on HSI trend, southbound flow dynamics, and sector rotation to define next - Risk-on: broad index breakout with expanding southbound participation. - Neutral: mixed index signals; focus on selective relative strength. - Risk-off: failed breakouts and rising volatility; prioritize capital preservation.""" + if self.region == "us" and self._get_review_language() == "zh": + return """## 美股市场三段式复盘策略 +聚焦指数趋势、宏观叙事与板块轮动,给出次日风控与仓位框架。 + +### 策略原则 +- 先看标普500、纳斯达克、道琼斯是否同向,确认主线是否一致。 +- 结合宏观与流动性指标,识别风险偏好是修复还是转弱。 +- 将复盘输出映射为“进攻/均衡/防守”动作建议,并给出明确触发失效条件。 + +### 分析维度 +- 趋势结构:明确市场处于上冲、震荡还是防守转向,判断是否存在关键支撑位背离。 +- 资金与情绪:区分宏观政策、货币面与波动率对权益风险的影响。 +- 主题线索:识别持续性最强的主题与板块轮动是否形成可交易主线。 + +### 行动框架 +- 进攻:主板块联动上行且量能/风险位同步改善。 +- 均衡:指数分化或量能未明显放大,仓位保守执行。 +- 防守:突破失守且波动率抬升时,优先减码并保留反弹可交易性。""" if not (self.region == "cn" and self._get_review_language() == "en"): return self.strategy.to_prompt_block() return """## Strategy Blueprint: A-share Three-Phase Recap Strategy @@ -266,6 +283,12 @@ Focus on index trend, liquidity, and sector rotation to shape the next-session t - **Trend Regime**: Classify the market as momentum, range, or risk-off based on HSI/HSTECH/HSCEI alignment. - **Capital Flows**: Track southbound flow direction and macro narrative for risk appetite signals. - **Sector Themes**: Focus on tech/internet platform persistence and financials/property policy sensitivity. +""" + if self.region == "us" and review_language == "zh": + return """### 六、策略框架 +- **趋势结构**:判断市场在进攻、震荡与防守中的状态是否一致。 +- **资金与情绪**:结合波动率、宽度和主题轮动评估风险偏好。 +- **主题主线**:识别可延续和可放大的行业主线与防守线索。 """ if not (self.region == "cn" and review_language == "en"): return self.strategy.to_markdown_block() @@ -435,12 +458,17 @@ Focus on index trend, liquidity, and sector rotation to shape the next-session t # 按 region 使用不同的新闻搜索词 search_queries = self.profile.news_queries + review_language = self._get_review_language() + market_names = { + "cn": "大盘" if review_language == "zh" else "A-share market", + "us": "美股市场" if review_language == "zh" else "US market", + "hk": "港股市场" if review_language == "zh" else "HK market", + } try: logger.info("[大盘] 开始搜索市场新闻...") # 根据 region 设置搜索上下文名称,避免美股搜索被解读为 A 股语境 - market_names = {"cn": "大盘", "us": "US market", "hk": "HK market"} market_name = market_names.get(self.region, "大盘") for query in search_queries: response = self.search_service.search_stock_news( @@ -474,21 +502,141 @@ Focus on index trend, liquidity, and sector rotation to shape the next-session t if not self.analyzer or not self.analyzer.is_available(): logger.warning("[大盘] AI分析器未配置或不可用,使用模板生成报告") return self._generate_template_review(overview, news) - + # 构建 Prompt prompt = self._build_review_prompt(overview, news) - + logger.info("[大盘] 调用大模型生成复盘报告...") - # Use the public generate_text() entry point — never access private analyzer attributes. + # Use the public generate_text() entry point - never access private analyzer attributes. review = self.analyzer.generate_text(prompt, max_tokens=8192, temperature=0.7) if review: logger.info("[大盘] 复盘报告生成成功,长度: %d 字符", len(review)) # Inject structured data tables into LLM prose sections return self._inject_data_into_review(review, overview, news) - else: - logger.warning("[大盘] 大模型返回为空,使用模板报告") - return self._generate_template_review(overview, news) + + logger.warning("[大盘] 大模型返回为空,使用模板报告") + return self._generate_template_review(overview, news) + + def build_market_review_payload( + self, + overview: MarketOverview, + news: List, + report: str, + market_light_snapshot: Optional[Dict[str, Any]] = None, + ) -> Dict[str, Any]: + """Build the structured market-review contract consumed by API, Web, and notifications.""" + language = self._get_review_language() + sections = self._split_report_sections(report) + title = self._extract_report_title(report) or self._get_review_title(overview.date).lstrip("# ").strip() + light = market_light_snapshot or self.build_market_light_snapshot(overview) + breadth_dimensions = None + if isinstance(light, dict): + dimensions = light.get("dimensions") + if isinstance(dimensions, dict): + breadth_dimensions = dimensions.get("breadth") + + breadth_supported = bool(self.profile.has_market_stats) + if breadth_supported and isinstance(breadth_dimensions, dict) and "available" in breadth_dimensions: + breadth_supported = bool(breadth_dimensions.get("available")) + + has_breadth_data = False + if breadth_supported: + if isinstance(breadth_dimensions, dict) and "available" in breadth_dimensions: + has_breadth_data = bool(breadth_dimensions.get("available")) + else: + breadth_available = overview.up_count + overview.down_count + overview.flat_count > 0 + limit_available = overview.limit_up_count + overview.limit_down_count > 0 + has_breadth_data = bool(breadth_available or limit_available) + + payload = { + "version": 1, + "kind": "market_review", + "region": self.region, + "language": language, + "title": title, + "generated_at": datetime.now().isoformat(), + "date": overview.date, + "market_scope": self._get_market_scope_name(language), + "market_light": light, + "indices": [idx.to_dict() for idx in overview.indices], + "sectors": { + "top": list(overview.top_sectors or []), + "bottom": list(overview.bottom_sectors or []), + }, + "news": [self._normalize_news_item(item) for item in (news or [])[:8]], + "sections": sections, + "markdown_report": report, + } + + if has_breadth_data: + payload["breadth"] = { + "up_count": overview.up_count, + "down_count": overview.down_count, + "flat_count": overview.flat_count, + "limit_up_count": overview.limit_up_count, + "limit_down_count": overview.limit_down_count, + "total_amount": overview.total_amount, + "turnover_unit": self._get_turnover_unit_label(), + } + + return payload + + @staticmethod + def _extract_report_title(report: str) -> str: + for line in (report or "").splitlines(): + stripped = line.strip() + if stripped.startswith("#"): + return stripped.lstrip("#").strip() + return "" + + @classmethod + def _split_report_sections(cls, report: str) -> List[Dict[str, str]]: + text = (report or "").strip() + if not text: + return [] + matches = list(re.finditer(r"^(#{2,3})\s+(.+?)\s*$", text, flags=re.MULTILINE)) + if not matches: + return [{"key": "full_review", "title": "Review", "markdown": text}] + + sections: List[Dict[str, str]] = [] + first_match = matches[0] + starts_with_report_title = first_match.start() == 0 and first_match.group(1) == "##" + content_start_index = 1 if starts_with_report_title else 0 + intro_start = first_match.end() if starts_with_report_title else 0 + intro_end = ( + matches[1].start() + if starts_with_report_title and len(matches) > 1 + else (len(text) if starts_with_report_title else matches[0].start()) + ) + intro = text[intro_start:intro_end].strip() + if intro: + sections.append({"key": "overview", "title": "Overview", "markdown": intro}) + + for index, match in enumerate(matches[content_start_index:], start=content_start_index): + start = match.end() + end = matches[index + 1].start() if index + 1 < len(matches) else len(text) + title = match.group(2).strip() + markdown = text[start:end].strip() + if not markdown: + continue + key = re.sub(r"[^0-9a-zA-Z\u4e00-\u9fff]+", "_", title).strip("_").lower() + sections.append({ + "key": key or f"section_{index + 1}", + "title": title, + "markdown": markdown, + }) + return sections + + @classmethod + def _normalize_news_item(cls, item: Any) -> Dict[str, str]: + return { + "title": cls._compact_news_text(cls._get_news_field(item, "title"), limit=120), + "snippet": cls._compact_news_text(cls._get_news_field(item, "snippet"), limit=260), + "source": cls._compact_news_text(cls._get_news_field(item, "source"), limit=80), + "published_date": cls._compact_news_text(cls._get_news_field(item, "published_date"), limit=40), + "url": cls._compact_news_text(cls._get_news_field(item, "url"), limit=240), + } def _inject_data_into_review( self, @@ -501,7 +649,6 @@ Focus on index trend, liquidity, and sector rotation to shape the next-session t stats_block = self._build_stats_block(overview) indices_block = self._build_indices_block(overview) sector_block = self._build_sector_block(overview) - news_block = self._build_news_block(news or []) patterns = ( _ENGLISH_SECTION_PATTERNS if self._get_review_language() == "en" @@ -529,13 +676,6 @@ Focus on index trend, liquidity, and sector rotation to shape the next-session t sector_block, ) - if news_block and "news_catalysts" in patterns: - review = self._insert_after_section( - review, - patterns["news_catalysts"], - news_block, - ) - return review @staticmethod @@ -1221,11 +1361,7 @@ Market conditions can change quickly. The data above is for reference only and d ### 五、消息催化 - 暂无可用新闻时,应降低对题材持续性的确定性判断。 -### 六、明日交易计划 -- **结论**:均衡观察。 -- **仓位**:控制在中性区间,等待指数与主线共振。 -- **关注方向**:{top_text or "强于指数的主线板块"}。 -- **回避方向**:{bottom_text or "连续走弱且缺少修复信号的方向"}。 +{self._get_strategy_markdown_block(template_language)} ### 七、风险提示 - 市场有风险,投资需谨慎。以上数据仅供参考,不构成投资建议。 @@ -1247,6 +1383,12 @@ Market conditions can change quickly. The data above is for reference only and d # 3. 生成复盘报告 report = self.generate_market_review(overview, news) snapshot = self.build_market_light_snapshot(overview) + structured_payload = self.build_market_review_payload( + overview, + news, + report, + snapshot, + ) logger.info("========== 大盘复盘分析完成 ==========") @@ -1254,6 +1396,7 @@ Market conditions can change quickly. The data above is for reference only and d overview=overview, report=report, market_light_snapshot=snapshot, + structured_payload=structured_payload, ) def run_daily_review(self) -> str: diff --git a/tests/test_analysis_api_contract.py b/tests/test_analysis_api_contract.py index f3344cab2..a58cec45c 100644 --- a/tests/test_analysis_api_contract.py +++ b/tests/test_analysis_api_contract.py @@ -280,6 +280,7 @@ class AnalysisApiContractTestCase(unittest.TestCase): search_service=runtime_search, send_notification=False, override_region="cn,us", + return_structured=True, ) def test_market_review_runtime_initializes_analyzer_for_litellm_provider(self) -> None: @@ -331,6 +332,7 @@ class AnalysisApiContractTestCase(unittest.TestCase): search_service=runtime_search, send_notification=False, override_region="cn", + return_structured=True, ) def test_get_analysis_status_returns_market_review_report_from_queue(self) -> None: @@ -344,7 +346,10 @@ class AnalysisApiContractTestCase(unittest.TestCase): stock_name="大盘复盘", status=analysis_endpoint_module.TaskStatusEnum.COMPLETED, progress=100, - result={"result": "市场复盘报告示例文本"}, + result={ + "result": "市场复盘报告示例文本", + "market_review_payload": {"kind": "market_review", "sections": []}, + }, error=None, original_query=None, selection_source=None, @@ -356,6 +361,7 @@ class AnalysisApiContractTestCase(unittest.TestCase): self.assertEqual(status.status, "completed") self.assertEqual(status.market_review_report, "市场复盘报告示例文本") + self.assertEqual(status.market_review_payload["kind"], "market_review") self.assertIsNone(status.result) def test_get_analysis_status_normalizes_completed_queue_result_contract(self) -> None: diff --git a/tests/test_market_analyzer_generate_text.py b/tests/test_market_analyzer_generate_text.py index 4500b2ae1..c48f6e8ab 100644 --- a/tests/test_market_analyzer_generate_text.py +++ b/tests/test_market_analyzer_generate_text.py @@ -1022,6 +1022,8 @@ class TestMarketAnalyzerBypassFix: assert "## 2026-03-05 大盘复盘" in result assert "### 一、盘面总览" in result assert "今日美股市场整体呈现**小幅下跌**态势" in result + assert "### 6. Strategy Framework" not in result + assert "### 六、策略框架" in result assert "### 1. Market Summary" not in result assert "US Market Recap" not in result @@ -1141,10 +1143,27 @@ Sector text. assert "| 上证指数 | 3300.00 | 🟢 +0.36% | 3288.00 | 3312.00 | 3276.00 | 1.10% | 1450 |" in result assert "#### 领涨板块 Top 5" in result assert "| 1 | AI算力 | +3.25% |" in result - assert "#### 近三日市场线索" in result - assert "AI算力板块走强" in result + assert "#### 近三日市场线索" not in result + assert "AI算力板块走强" not in result + assert "新闻。" in result assert "算力产业链延续活跃" not in result + def test_market_review_payload_sections_skip_top_report_title(self): + from src.market_analyzer import MarketAnalyzer + + ma = MarketAnalyzer.__new__(MarketAnalyzer) + sections = ma._split_report_sections("""## 2026-06-03 大盘复盘 + +> 今日指数分化。 + +### 一、盘面总览 +正文 +""") + + assert sections[0]["key"] == "overview" + assert "今日指数分化" in sections[0]["markdown"] + assert all(section["title"] != "2026-06-03 大盘复盘" for section in sections) + def test_news_block_renders_title_source_and_link_only(self): from src.market_analyzer import MarketAnalyzer @@ -1322,6 +1341,87 @@ Sector text. assert snapshot["dimensions"]["index"]["available"] is True assert snapshot["dimensions"]["limit"] == {"score": 50, "available": False} + def test_market_review_payload_omits_breadth_for_markets_without_stats(self): + from src.core.market_profile import US_PROFILE + from src.market_analyzer import MarketIndex, MarketOverview + + ma = self._make_market_analyzer_with_mock_generate_text(return_value="复盘结果") + ma.region = "us" + ma.profile = US_PROFILE + + payload = ma.build_market_review_payload( + MarketOverview( + date="2026-03-18", + indices=[ + MarketIndex(code="SPX", name="S&P 500", current=5200.0, change_pct=0.6), + ], + up_count=1000, + down_count=400, + limit_up_count=10, + limit_down_count=0, + total_amount=9800.0, + ), + [], + "美股复盘报告", + market_light_snapshot={"dimensions": {"breadth": {"score": 60, "available": True}}}, + ) + + assert "breadth" not in payload + assert payload["indices"][0]["code"] == "SPX" + + def test_market_review_payload_omits_breadth_for_cn_market_without_available_stats(self): + from src.market_analyzer import MarketIndex, MarketOverview + + ma = self._make_market_analyzer_with_mock_generate_text(return_value="复盘结果") + payload = ma.build_market_review_payload( + MarketOverview( + date="2026-03-18", + indices=[ + MarketIndex(code="000001", name="上证指数", current=3200.0, change_pct=0.6), + ], + up_count=0, + down_count=0, + flat_count=0, + limit_up_count=0, + limit_down_count=0, + total_amount=0.0, + ), + [], + "A股复盘报告", + market_light_snapshot={"dimensions": {"breadth": {"score": 55, "available": False}}}, + ) + + assert "breadth" not in payload + assert payload["indices"][0]["name"] == "上证指数" + + def test_market_review_payload_includes_breadth_only_when_stats_available(self): + from src.market_analyzer import MarketIndex, MarketOverview + + ma = self._make_market_analyzer_with_mock_generate_text(return_value="复盘结果") + payload = ma.build_market_review_payload( + MarketOverview( + date="2026-03-18", + indices=[ + MarketIndex(code="000001", name="上证指数", current=3200.0, change_pct=0.6), + ], + up_count=1200, + down_count=900, + flat_count=60, + limit_up_count=12, + limit_down_count=4, + total_amount=12345.0, + ), + [], + "A股复盘报告", + market_light_snapshot={"dimensions": {"breadth": {"score": 62, "available": True}}}, + ) + + assert payload["breadth"] is not None + assert payload["breadth"]["up_count"] == 1200 + assert payload["breadth"]["down_count"] == 900 + assert payload["breadth"]["limit_up_count"] == 12 + assert payload["breadth"]["total_amount"] == 12345.0 + def test_us_english_indices_do_not_label_turnover_as_cny(self): from src.core.market_profile import US_PROFILE from src.core.market_strategy import get_market_strategy_blueprint diff --git a/tests/test_market_review.py b/tests/test_market_review.py index 0d8c36e72..40001f044 100644 --- a/tests/test_market_review.py +++ b/tests/test_market_review.py @@ -128,8 +128,8 @@ class MarketReviewLocalizationTestCase(unittest.TestCase): market_review_module, "MarketAnalyzer", side_effect=[cn_analyzer, hk_analyzer, us_analyzer], - ), patch.object(market_review_module, "_persist_market_review_history"): - result = run_market_review(notifier, send_notification=False) + ), patch.object(market_review_module, "_persist_market_review_history") as persist_history: + result = run_market_review(notifier, send_notification=True) self.assertIn("# A-share Market Recap\n\nCN body", result) self.assertIn("# HK Market Recap\n\nHK body", result) @@ -137,7 +137,17 @@ class MarketReviewLocalizationTestCase(unittest.TestCase): self.assertIn("# US Market Recap\n\nUS body", result) saved_content = notifier.save_report_to_file.call_args.args[0] self.assertTrue(saved_content.startswith("# 🎯 Market Review\n\n")) - notifier.send.assert_not_called() + self.assertIn("# A-share Market Recap\n\nCN body", saved_content) + self.assertIn("> Next market recap follows", saved_content) + self.assertIn("# HK Market Recap\n\nHK body", saved_content) + self.assertIn("# US Market Recap\n\nUS body", saved_content) + self.assertIn( + "# A-share Market Recap\n\nCN body", + persist_history.call_args.kwargs["markdown_report"], + ) + sent_content = notifier.send.call_args.args[0] + self.assertTrue(sent_content.startswith("🎯 Market Review\n\n")) + self.assertIn("# US Market Recap\n\nUS body", sent_content) def test_run_market_review_comma_joined_subset_cn_us(self) -> None: """Regression: compute_effective_region("both", {"cn","us"}) -> "cn,us" @@ -300,6 +310,24 @@ class MarketReviewLocalizationTestCase(unittest.TestCase): snapshots = persist_history.call_args.kwargs["market_light_snapshots"] self.assertEqual(set(snapshots), {"cn"}) + def test_render_market_review_payload_markdown_does_not_repeat_title(self) -> None: + markdown = market_review_module._render_market_review_payload_markdown( + { + "title": "2026-06-03 大盘复盘", + "sections": [ + { + "key": "daily_review", + "title": "2026-06-03 大盘复盘", + "markdown": "> 今日指数强弱分化。\n\n### 一、盘面总览\n正文", + } + ], + }, + wrapper_title="🎯 大盘复盘", + ) + + self.assertEqual(markdown.count("2026-06-03 大盘复盘"), 1) + self.assertTrue(markdown.startswith("🎯 大盘复盘\n\n## 2026-06-03 大盘复盘")) + def test_persist_market_review_history_saves_markdown_report(self) -> None: with tempfile.TemporaryDirectory() as temp_dir: old_db_path = os.environ.get("DATABASE_PATH") @@ -331,6 +359,12 @@ class MarketReviewLocalizationTestCase(unittest.TestCase): "data_quality": "ok", } }, + market_review_payload={ + "version": 1, + "kind": "market_review", + "region": "cn", + "sections": [{"title": "今日大盘", "markdown": "复盘正文"}], + }, ) self.assertEqual(saved, 1) @@ -346,6 +380,7 @@ class MarketReviewLocalizationTestCase(unittest.TestCase): self.assertEqual(row.news_content, "## 今日大盘\n\n复盘正文") self.assertIn("# 🎯 大盘复盘", row.raw_result) self.assertIn('"market_light_snapshots"', row.context_snapshot) + self.assertIn('"market_review_payload"', row.context_snapshot) self.assertIn('"trade_date": "2026-03-06"', row.context_snapshot) finally: DatabaseManager.reset_instance() diff --git a/tests/test_market_strategy.py b/tests/test_market_strategy.py index 0f9167c70..0148d5549 100644 --- a/tests/test_market_strategy.py +++ b/tests/test_market_strategy.py @@ -40,12 +40,25 @@ class TestMarketAnalyzerStrategyPrompt(unittest.TestCase): self.assertIn("A股市场三段式复盘策略", prompt) def test_us_prompt_contains_strategy_plan_section(self): - analyzer = MarketAnalyzer(region="us") + with patch("src.market_analyzer.get_config", return_value=SimpleNamespace(report_language="en")): + analyzer = MarketAnalyzer(region="us") + prompt = analyzer._build_review_prompt(MarketOverview(date="2026-02-24"), []) self.assertIn("Strategy Plan", prompt) self.assertIn("US Market Regime Strategy", prompt) + def test_us_prompt_localizes_strategy_markdown_when_report_language_is_zh(self): + with patch("src.market_analyzer.get_config", return_value=SimpleNamespace(report_language="zh")): + analyzer = MarketAnalyzer(region="us") + + prompt = analyzer._build_review_prompt(MarketOverview(date="2026-02-24"), []) + + self.assertIn("美股市场", prompt) + self.assertNotIn("US Market Regime Strategy", prompt) + self.assertNotIn("Strategy Blueprint", prompt) + self.assertIn("风险偏好", prompt) + def test_cn_prompt_uses_english_shell_when_report_language_is_en(self): with patch("src.market_analyzer.get_config", return_value=SimpleNamespace(report_language="en")): analyzer = MarketAnalyzer(region="cn")