From 1ca4baa111a97d6a55dc0524eae83bf56c856666 Mon Sep 17 00:00:00 2001 From: dreamsourcelabTAI Date: Sun, 28 Apr 2024 10:23:43 +0800 Subject: [PATCH 01/47] fix: The shadow not displayed at a right position in windows 10 --- DSView/pv/mainframe.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/DSView/pv/mainframe.cpp b/DSView/pv/mainframe.cpp index d4605d97..9f702324 100644 --- a/DSView/pv/mainframe.cpp +++ b/DSView/pv/mainframe.cpp @@ -778,6 +778,11 @@ void MainFrame::AttachNativeWindow() nativeWindow->SetBorderColor(QColor(0x80, 0x80, 0x80)); _parentNativeWidget = nativeWindow; + //Make sure the shadow displayed at a right position fisrt time for windows 10. + QTimer::singleShot(100, this, [this](){ + _parentNativeWidget->ResizeChild(); + }); + #endif } From a6a0484e013e3d2771a0689677911e1348c747c9 Mon Sep 17 00:00:00 2001 From: dreamsourcelabTAI Date: Sun, 28 Apr 2024 15:14:49 +0800 Subject: [PATCH 02/47] fix: The mouse scroll wheel cannot be used in Windows 7 --- DSView/pv/mainframe.cpp | 10 ++++++- DSView/pv/winnativewidget.cpp | 51 ++++++++++++++++++++++++++++------- DSView/pv/winnativewidget.h | 5 ++-- 3 files changed, 54 insertions(+), 12 deletions(-) diff --git a/DSView/pv/mainframe.cpp b/DSView/pv/mainframe.cpp index 9f702324..c972e7c6 100644 --- a/DSView/pv/mainframe.cpp +++ b/DSView/pv/mainframe.cpp @@ -759,8 +759,16 @@ void MainFrame::AttachNativeWindow() _titleBar->EnableAbleDrag(false); setWindowFlags(Qt::FramelessWindowHint); + + if (nativeWindow->IsWin7()){ + SetWindowLong((HWND)winId(), GWL_STYLE, WS_CLIPCHILDREN | WS_CLIPSIBLINGS); + } + else{ + SetWindowLong((HWND)winId(), GWL_STYLE, WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); + } + + SetWindowLong((HWND)winId(), GWL_STYLE, WS_CLIPCHILDREN | WS_CLIPSIBLINGS); - SetWindowLong((HWND)winId(), GWL_STYLE, WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); SetParent((HWND)winId(), nativeWindow->Handle()); setVisible(true); diff --git a/DSView/pv/winnativewidget.cpp b/DSView/pv/winnativewidget.cpp index b5fc4b9d..160bc597 100644 --- a/DSView/pv/winnativewidget.cpp +++ b/DSView/pv/winnativewidget.cpp @@ -726,9 +726,15 @@ void WinNativeWidget::hideBorder() } } -bool WinNativeWidget::isWinXOrGreater(DWORD major_version, DWORD minor_version, DWORD build_number) -{ - bool is_win_x_or_greater = false; +bool WinNativeWidget::getWinSysVersion(DWORD *major_version, DWORD *minor_version, DWORD *build_number) +{ + assert(major_version); + assert(minor_version); + assert(build_number); + + *major_version = 0; + *minor_version = 0; + *build_number = 0; typedef NTSTATUS(WINAPI *tRtlGetVersion)(LPOSVERSIONINFOEXW); tRtlGetVersion pRtlGetVersion = tRtlGetVersion(QLibrary::resolve("ntdll", "RtlGetVersion")); @@ -739,20 +745,47 @@ bool WinNativeWidget::isWinXOrGreater(DWORD major_version, DWORD minor_version, memset(&os_info, 0, sizeof(OSVERSIONINFOEXW)); os_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW); NTSTATUS status = pRtlGetVersion(&os_info); + if (status == 0) - { - is_win_x_or_greater = (os_info.dwMajorVersion >= major_version && - os_info.dwMinorVersion >= minor_version && - os_info.dwBuildNumber >= build_number); + { + *major_version = os_info.dwMajorVersion; + *minor_version = os_info.dwMinorVersion; + *build_number = os_info.dwBuildNumber; + return true; } } - return is_win_x_or_greater; + return false; } bool WinNativeWidget::IsWin11OrGreater() { - return isWinXOrGreater(10, 0, 22000); + DWORD major_version = 0; + DWORD minor_version = 0; + DWORD build_number = 0; + + if (getWinSysVersion(&major_version, &minor_version, &build_number)){ + if (major_version >= 10 && build_number >= 22000){ + return true; + } + } + + return false; +} + +bool WinNativeWidget::IsWin7() +{ + DWORD major_version = 0; + DWORD minor_version = 0; + DWORD build_number = 0; + + if (getWinSysVersion(&major_version, &minor_version, &build_number)){ + if (major_version == 6 && minor_version == 1){ + return true; + } + } + + return false; } int WinNativeWidget::GetDevicePixelRatio() diff --git a/DSView/pv/winnativewidget.h b/DSView/pv/winnativewidget.h index df316f46..99e8d67a 100644 --- a/DSView/pv/winnativewidget.h +++ b/DSView/pv/winnativewidget.h @@ -86,6 +86,7 @@ class WinNativeWidget: public IShadowCallback void SetBorderColor(QColor color); bool IsWin11OrGreater(); + bool IsWin7(); inline void SetTitleBarWidget(QWidget *w){ _titleBarWidget = w; @@ -99,8 +100,8 @@ class WinNativeWidget: public IShadowCallback static void EnalbeNoClientArea(bool bEnabled); private: - QScreen* screenFromCurrentMonitorHandle(); - bool isWinXOrGreater(DWORD major_version, DWORD minor_version, DWORD build_number); + QScreen* screenFromCurrentMonitorHandle(); + bool getWinSysVersion(DWORD *major_version, DWORD *minor_version, DWORD *build_number); void showBorder(); void hideBorder(); static RECT GetMonitorArea(HMONITOR hMonitor, bool isPhysics); From 162efcf2fa6d2cbde06cb72f3e25b658885c2a49 Mon Sep 17 00:00:00 2001 From: dreamsourcelabTAI Date: Sun, 28 Apr 2024 17:53:43 +0800 Subject: [PATCH 03/47] Enable the mouse wheel for windows 7 --- DSView/pv/mainframe.cpp | 11 +---------- DSView/pv/winnativewidget.cpp | 16 ++++++++++++---- DSView/pv/winnativewidget.h | 5 +++-- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/DSView/pv/mainframe.cpp b/DSView/pv/mainframe.cpp index c972e7c6..f9e91588 100644 --- a/DSView/pv/mainframe.cpp +++ b/DSView/pv/mainframe.cpp @@ -759,16 +759,7 @@ void MainFrame::AttachNativeWindow() _titleBar->EnableAbleDrag(false); setWindowFlags(Qt::FramelessWindowHint); - - if (nativeWindow->IsWin7()){ - SetWindowLong((HWND)winId(), GWL_STYLE, WS_CLIPCHILDREN | WS_CLIPSIBLINGS); - } - else{ - SetWindowLong((HWND)winId(), GWL_STYLE, WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); - } - - SetWindowLong((HWND)winId(), GWL_STYLE, WS_CLIPCHILDREN | WS_CLIPSIBLINGS); - + SetWindowLong((HWND)winId(), GWL_STYLE, WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); SetParent((HWND)winId(), nativeWindow->Handle()); setVisible(true); diff --git a/DSView/pv/winnativewidget.cpp b/DSView/pv/winnativewidget.cpp index 160bc597..3a551267 100644 --- a/DSView/pv/winnativewidget.cpp +++ b/DSView/pv/winnativewidget.cpp @@ -65,11 +65,13 @@ WinNativeWidget::WinNativeWidget(const int x, const int y, const int width, _hWnd = NULL; _event_callback = NULL; _is_lose_foreground = false; - - _titleBarWidget = NULL; - _is_native_border = IsWin11OrGreater(); _hCurrentMonitor = NULL; _shadow = NULL; + _titleBarWidget = NULL; + + _is_native_border = IsWin11OrGreater(); + _is_win7 = IsWin7(); + _border_color = QColor(0x80,0x80,0x80); int r = backColor.red(); int g = backColor.green(); @@ -77,7 +79,6 @@ WinNativeWidget::WinNativeWidget(const int x, const int y, const int width, HINSTANCE hInstance = GetModuleHandle(nullptr); WNDCLASSEX wcx; - memset(&wcx, 0, sizeof(WNDCLASSEXW)); wcx.cbSize = sizeof(WNDCLASSEX); @@ -365,6 +366,13 @@ LRESULT CALLBACK WinNativeWidget::WndProc(HWND hWnd, UINT message, WPARAM wParam } break; } + case WM_MOUSEWHEEL: + { + if (self->_is_win7 && self->_childWindow != NULL){ + return SendMessage(self->_childWindow, message, wParam, lParam); + } + break; + } } return DefWindowProc(hWnd, message, wParam, lParam); diff --git a/DSView/pv/winnativewidget.h b/DSView/pv/winnativewidget.h index 99e8d67a..dcc63224 100644 --- a/DSView/pv/winnativewidget.h +++ b/DSView/pv/winnativewidget.h @@ -85,8 +85,8 @@ class WinNativeWidget: public IShadowCallback bool isActiveWindow(); void SetBorderColor(QColor color); - bool IsWin11OrGreater(); - bool IsWin7(); + static bool IsWin11OrGreater(); + static bool IsWin7(); inline void SetTitleBarWidget(QWidget *w){ _titleBarWidget = w; @@ -126,6 +126,7 @@ class WinNativeWidget: public IShadowCallback WinShadow *_shadow; QColor _border_color; bool _is_lose_foreground; + bool _is_win7; }; } From e75c068443d66fef269764cb733b52023a439990 Mon Sep 17 00:00:00 2001 From: dreamsourcelabTAI Date: Sun, 28 Apr 2024 18:04:54 +0800 Subject: [PATCH 04/47] fix: can't compile in windows --- DSView/pv/winnativewidget.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/DSView/pv/winnativewidget.h b/DSView/pv/winnativewidget.h index dcc63224..537798d5 100644 --- a/DSView/pv/winnativewidget.h +++ b/DSView/pv/winnativewidget.h @@ -87,6 +87,7 @@ class WinNativeWidget: public IShadowCallback void SetBorderColor(QColor color); static bool IsWin11OrGreater(); static bool IsWin7(); + static bool getWinSysVersion(DWORD *major_version, DWORD *minor_version, DWORD *build_number); inline void SetTitleBarWidget(QWidget *w){ _titleBarWidget = w; @@ -101,7 +102,7 @@ class WinNativeWidget: public IShadowCallback private: QScreen* screenFromCurrentMonitorHandle(); - bool getWinSysVersion(DWORD *major_version, DWORD *minor_version, DWORD *build_number); + void showBorder(); void hideBorder(); static RECT GetMonitorArea(HMONITOR hMonitor, bool isPhysics); From 42368463a39f121b8c40399bf13b79d2225b3c14 Mon Sep 17 00:00:00 2001 From: dreamsourcelabTAI Date: Mon, 29 Apr 2024 14:40:00 +0800 Subject: [PATCH 05/47] fix: the last cache have not clear when the language be changed, so maybe the UI used an error text --- DSView/pv/mainwindow.cpp | 1 - DSView/pv/ui/langresource.cpp | 10 +++++----- DSView/pv/view/viewport.cpp | 20 +++++--------------- DSView/pv/view/viewport.h | 4 +--- 4 files changed, 11 insertions(+), 24 deletions(-) diff --git a/DSView/pv/mainwindow.cpp b/DSView/pv/mainwindow.cpp index f36f868b..f4b013bc 100644 --- a/DSView/pv/mainwindow.cpp +++ b/DSView/pv/mainwindow.cpp @@ -338,7 +338,6 @@ namespace pv _protocol_dock->setWindowTitle(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_PROTOCOL_DOCK_TITLE), "Decode Protocol")); _measure_dock->setWindowTitle(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_MEASURE_DOCK_TITLE), "Measurement")); _search_dock->setWindowTitle(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_SEARCH_DOCK_TITLE), "Search...")); - _view->get_time_view()->update_lang(); } void MainWindow::on_load_file(QString file_name) diff --git a/DSView/pv/ui/langresource.cpp b/DSView/pv/ui/langresource.cpp index 957e3ac1..b0ce66a8 100644 --- a/DSView/pv/ui/langresource.cpp +++ b/DSView/pv/ui/langresource.cpp @@ -98,11 +98,9 @@ bool LangResource::Load(int lang) } _cur_lang = lang; - _query_decoders.clear(); - - release_self(); - + release_self(); + num = sizeof(lange_page_keys) / sizeof(lang_page_item); for (int i = 0; i < num; i++) @@ -131,6 +129,7 @@ void LangResource::release_self() delete p; } _pages.clear(); + _current_page = NULL; } void LangResource::load_page(Lang_resource_page &p) @@ -225,8 +224,9 @@ const char* LangResource::get_lang_text(int page_id, const char *str_id, const c return default_str; } - if (_current_page->_loaded == false) + if (_current_page->_loaded == false){ load_page(*_current_page); + } std::string key(str_id); diff --git a/DSView/pv/view/viewport.cpp b/DSView/pv/view/viewport.cpp index 7edfc48d..dea3b912 100644 --- a/DSView/pv/view/viewport.cpp +++ b/DSView/pv/view/viewport.cpp @@ -108,7 +108,6 @@ Viewport::Viewport(View &parent, View_type type) : _xAction = xAction; setContextMenuPolicy(Qt::CustomContextMenu); - this->update_font(); connect(&_trigger_timer, SIGNAL(timeout()),this, SLOT(on_trigger_timer())); connect(&_drag_timer, SIGNAL(timeout()),this, SLOT(on_drag_timer())); @@ -2144,31 +2143,22 @@ void Viewport::add_cursor_x() _view.show_xcursors(true); } -void Viewport::update_font() -{ - QFont font = this->font(); - font.setPointSizeF(AppConfig::Instance().appOptions.fontSize); - _yAction->setFont(font); - _xAction->setFont(font); -} - -void Viewport::update_lang() +void Viewport::UpdateLanguage() { _yAction->setText(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_ADD_Y_CURSOR), "Add Y-cursor")); _xAction->setText(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_ADD_X_CURSOR), "Add X-cursor")); } -void Viewport::UpdateLanguage() -{ -} - void Viewport::UpdateTheme() { } void Viewport::UpdateFont() { - update_font(); + QFont font = this->font(); + font.setPointSizeF(AppConfig::Instance().appOptions.fontSize); + _yAction->setFont(font); + _xAction->setFont(font); } } // namespace view diff --git a/DSView/pv/view/viewport.h b/DSView/pv/view/viewport.h index a5da560f..6760c950 100644 --- a/DSView/pv/view/viewport.h +++ b/DSView/pv/view/viewport.h @@ -118,9 +118,7 @@ class Viewport : public QWidget, public IUiWindow void set_receive_len(quint64 length); void unshow_wait_trigger(); void show_wait_trigger(); - - void update_lang(); - void update_font(); + void measure(); void update(int event); From 2a1a6bd70108908a292916aba6fc75722dadbecc Mon Sep 17 00:00:00 2001 From: dreamsourcelabTAI Date: Mon, 29 Apr 2024 14:48:00 +0800 Subject: [PATCH 06/47] Send the message WM_MOUSEWHEEL to focus window --- DSView/pv/winnativewidget.cpp | 4 ++-- DSView/pv/winnativewidget.h | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/DSView/pv/winnativewidget.cpp b/DSView/pv/winnativewidget.cpp index 3a551267..7b866301 100644 --- a/DSView/pv/winnativewidget.cpp +++ b/DSView/pv/winnativewidget.cpp @@ -70,7 +70,6 @@ WinNativeWidget::WinNativeWidget(const int x, const int y, const int width, _titleBarWidget = NULL; _is_native_border = IsWin11OrGreater(); - _is_win7 = IsWin7(); _border_color = QColor(0x80,0x80,0x80); int r = backColor.red(); @@ -368,7 +367,8 @@ LRESULT CALLBACK WinNativeWidget::WndProc(HWND hWnd, UINT message, WPARAM wParam } case WM_MOUSEWHEEL: { - if (self->_is_win7 && self->_childWindow != NULL){ + // If system not send this message to the focus window, the native window will be received it. + if (self->_childWindow != NULL){ return SendMessage(self->_childWindow, message, wParam, lParam); } break; diff --git a/DSView/pv/winnativewidget.h b/DSView/pv/winnativewidget.h index 537798d5..d13f56f2 100644 --- a/DSView/pv/winnativewidget.h +++ b/DSView/pv/winnativewidget.h @@ -127,7 +127,6 @@ class WinNativeWidget: public IShadowCallback WinShadow *_shadow; QColor _border_color; bool _is_lose_foreground; - bool _is_win7; }; } From 03131dd261f08f84262c0172fd051b16cc3bb586 Mon Sep 17 00:00:00 2001 From: DreamSourceLab Date: Fri, 10 May 2024 20:47:23 -0700 Subject: [PATCH 07/47] add support of new hardware models --- libsigrok4DSL/hardware/DSL/dsl.h | 55 ++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/libsigrok4DSL/hardware/DSL/dsl.h b/libsigrok4DSL/hardware/DSL/dsl.h index cfb5355a..b06dab64 100644 --- a/libsigrok4DSL/hardware/DSL/dsl.h +++ b/libsigrok4DSL/hardware/DSL/dsl.h @@ -775,6 +775,61 @@ static const struct DSL_profile supported_DSLogic[] = { SR_MHZ(400)} }, + {0x2A0E, 0x0034, LIBUSB_SPEED_HIGH, "DreamSourceLab", "DSLogic PLus", NULL, + "DSLogicPlus-pgl12-2.fw", + "DSLogicPlus-pgl12-2.bin", + "DSLogicPlus-pgl12-2.bin", + {CAPS_MODE_LOGIC, + CAPS_FEATURE_VTH | CAPS_FEATURE_BUF | CAPS_FEATURE_MAX25_VTH | CAPS_FEATURE_SECURITY, + (1 << DSL_STREAM20x16) | (1 << DSL_STREAM25x12) | (1 << DSL_STREAM50x6) | (1 << DSL_STREAM100x3) | + (1 << DSL_BUFFER100x16) | (1 << DSL_BUFFER200x8) | (1 << DSL_BUFFER400x4), + 16, + SR_MB(256), + 0, + DSL_BUFFER100x16, + 0, + samplerates400, + 0, + DSL_STREAM20x16, + SR_MHZ(1), + SR_Mn(1), + 0, + 0, + 0, + 0, + 0, + SR_MHZ(200), + SR_MHZ(400)} + }, + + {0x2A0E, 0x0035, LIBUSB_SPEED_HIGH, "DreamSourceLab", "DSLogic U2Basic", NULL, + "DSLogicU2Basic-pgl12-2.fw", + "DSLogicU2Basic-pgl12-2.bin", + "DSLogicU2Basic-pgl12-2.bin", + {CAPS_MODE_LOGIC, + CAPS_FEATURE_VTH | CAPS_FEATURE_BUF | CAPS_FEATURE_MAX25_VTH | CAPS_FEATURE_SECURITY, + (1 << DSL_STREAM20x16) | (1 << DSL_STREAM25x12) | (1 << DSL_STREAM50x6) | (1 << DSL_STREAM100x3) | + (1 << DSL_BUFFER100x16), + 16, + SR_MB(64), + 0, + DSL_BUFFER100x16, + 0, + samplerates100, + 0, + DSL_STREAM20x16, + SR_MHZ(1), + SR_Mn(1), + 0, + 0, + 0, + 0, + 0, + SR_MHZ(200), + SR_MHZ(400)} + }, + + { 0, 0, LIBUSB_SPEED_UNKNOWN, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}} }; From 7e053bec6faecf30c4ba421ce9ce6e69b459ad14 Mon Sep 17 00:00:00 2001 From: dreamsourcelabTAI Date: Sat, 11 May 2024 19:54:01 +0800 Subject: [PATCH 08/47] fix: the decoded data exporting dialog can't close in MAC os --- DSView/pv/dialogs/protocolexp.cpp | 67 +++++++++++++++++++------------ DSView/pv/dialogs/protocolexp.h | 12 ++++-- 2 files changed, 51 insertions(+), 28 deletions(-) diff --git a/DSView/pv/dialogs/protocolexp.cpp b/DSView/pv/dialogs/protocolexp.cpp index 7b712c5f..e3f0cb9b 100644 --- a/DSView/pv/dialogs/protocolexp.cpp +++ b/DSView/pv/dialogs/protocolexp.cpp @@ -59,6 +59,8 @@ ProtocolExp::ProtocolExp(QWidget *parent, SigSession *session) : Qt::Horizontal, this), _export_cancel(false) { + _bAbleClose = false; + _format_combobox = new DsComboBox(this); //tr _format_combobox->addItem("Comma-Separated Values (*.csv)"); @@ -102,27 +104,51 @@ ProtocolExp::ProtocolExp(QWidget *parent, SigSession *session) : layout()->addLayout(_layout); setTitle(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_PROTOCOL_EXPORT), "Protocol Export")); - connect(&_button_box, SIGNAL(accepted()), this, SLOT(accept())); - connect(&_button_box, SIGNAL(rejected()), this, SLOT(reject())); - connect(_session->device_event_object(), SIGNAL(device_updated()), this, SLOT(reject())); + connect(&_button_box, SIGNAL(accepted()), this, SLOT(onAccept())); + connect(&_button_box, SIGNAL(rejected()), this, SLOT(onReject())); + connect(_session->device_event_object(), SIGNAL(device_updated()), this, SLOT(onReject())); + + connect(&m_timer, &QTimer::timeout, this, &ProtocolExp::on_timeout); + m_timer.setInterval(200); } -void ProtocolExp::accept() -{ - if (_session->have_decoded_result() == false) - { - QString errMsg = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_NO_DECODED_RESULT), "No data to export"); - MsgBox::Show(errMsg); - return; +void ProtocolExp::on_timeout() +{ + if (_bAbleClose){ + closeSelf(); } +} + +void ProtocolExp::onReject() +{ + using namespace Qt; + + QDialog::reject(); + this->deleteLater(); +} - QDialog::accept(); +void ProtocolExp::cancel_export() +{ + _export_cancel = true; +} - if (_row_sel_list.empty()){ +void ProtocolExp::closeSelf() +{ + close(); + this->deleteLater(); +} + +void ProtocolExp::onAccept() +{ + if (_session->have_decoded_result() == false + || _row_sel_list.empty()) + { + QString errMsg = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_NO_DECODED_RESULT), "No data to export"); + MsgBox::Show(errMsg); return; } - + QList supportedFormats; for (int i = _format_combobox->count() - 1; i >= 0; i--) { @@ -170,6 +196,7 @@ void ProtocolExp::accept() QFuture future; future = QtConcurrent::run([&]{ save_proc(); + _bAbleClose = true; }); Qt::WindowFlags flags = Qt::CustomizeWindowHint; @@ -186,6 +213,8 @@ void ProtocolExp::accept() connect(this, SIGNAL(export_progress(int)), &dlg, SLOT(setValue(int))); connect(&dlg, SIGNAL(canceled()), this, SLOT(cancel_export())); + m_timer.start(); + this->hide(); watcher.setFuture(future); dlg.exec(); @@ -335,17 +364,5 @@ bool ProtocolExp::compare_ann_index(const data::decode::Annotation *a, return a->start_sample() < b->start_sample(); } -void ProtocolExp::reject() -{ - using namespace Qt; - - QDialog::reject(); -} - -void ProtocolExp::cancel_export() -{ - _export_cancel = true; -} - } // namespace dialogs } // namespace pv diff --git a/DSView/pv/dialogs/protocolexp.h b/DSView/pv/dialogs/protocolexp.h index f8afc844..7e8dd986 100644 --- a/DSView/pv/dialogs/protocolexp.h +++ b/DSView/pv/dialogs/protocolexp.h @@ -29,6 +29,7 @@ #include #include #include +#include #include "../prop/binding/deviceoptions.h" #include "../toolbars/titlebar.h" @@ -64,18 +65,21 @@ class ProtocolExp : public DSDialog public: ProtocolExp(QWidget *parent, SigSession *session); -protected: - void accept(); - void reject(); +protected: void save_proc(); static bool compare_ann_index(const data::decode::Annotation *a, const data::decode::Annotation *b); + void closeSelf(); + signals: void export_progress(int percent); private slots: void cancel_export(); + void onAccept(); + void onReject(); + void on_timeout(); private: SigSession *_session; @@ -90,6 +94,8 @@ private slots: bool _export_cancel; QString _fileName; + QTimer m_timer; + bool _bAbleClose; }; } // namespace dialogs From df4f8b15acb5e8fcdee1df9e09b60f28e83d157b Mon Sep 17 00:00:00 2001 From: yunyaobaihong <896458252@qq.com> Date: Thu, 16 May 2024 10:56:25 +0800 Subject: [PATCH 09/47] decoder update : qspi and smart qspi --- libsigrokdecode4DSL/decoders/qspi/pd.py | 537 ++------------ .../decoders/smart qspi/__init__.py | 31 + libsigrokdecode4DSL/decoders/smart qspi/pd.py | 659 ++++++++++++++++++ 3 files changed, 742 insertions(+), 485 deletions(-) create mode 100644 libsigrokdecode4DSL/decoders/smart qspi/__init__.py create mode 100644 libsigrokdecode4DSL/decoders/smart qspi/pd.py diff --git a/libsigrokdecode4DSL/decoders/qspi/pd.py b/libsigrokdecode4DSL/decoders/qspi/pd.py index 552901ec..2723842b 100644 --- a/libsigrokdecode4DSL/decoders/qspi/pd.py +++ b/libsigrokdecode4DSL/decoders/qspi/pd.py @@ -1,9 +1,7 @@ -## +### ## This file is part of the libsigrokdecode project. ## -## Copyright (C) 2011 Gareth McMullin -## Copyright (C) 2012-2014 Uwe Hermann -## Copyright (C) 2024 DreamSourceLab +## Copyright (C) 2020 DreamSourceLab ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -21,13 +19,9 @@ import sigrokdecode as srd from collections import namedtuple -from math import floor, ceil -from enum import Enum + Data = namedtuple('Data', ['ss', 'es', 'val']) -## -## 2023/4/8 DreamSourceLab : add flash module -## # Key: (CPOL, CPHA). Value: SPI mode. # Clock polarity (CPOL) = 0/1: Clock is low/high when inactive. @@ -39,155 +33,22 @@ (1, 1): 3, # Mode 3 } -class process_enum(Enum): - COMMAND = 0 - WRITE_BYTE = 1 - READ_BYTE = 2 - READ_BYTE_CONTINUOUS = 3 - CONTINUOUS_READ_MODE_BITS = 4 - ADDRESS_BY_MODE = 5 - ADDRESS_24BIT = 6 - ADDRESS_32BIT = 7 - DUMMY_BY_MODE = 8 - DUMMY_8BIT = 9 - DUMMY_32BIT = 10 - DUMMY_40BIT = 11 - -process_text = { - process_enum.COMMAND : ['Command' , 'CMD'] , - process_enum.WRITE_BYTE : ['Write Data' , 'WD'] , - process_enum.READ_BYTE : ['Read Data' , 'RD'] , - process_enum.READ_BYTE_CONTINUOUS : ['Read Data' , 'RD'] , - process_enum.ADDRESS_24BIT : ['24-Bit Address' , 'AD'] , - process_enum.ADDRESS_32BIT : ['32-Bit Address' , 'AD'] , - process_enum.CONTINUOUS_READ_MODE_BITS : ['Continuous Read Mode bits' , 'M'] , -} - -class process_mode(Enum): - SINGLE = 0 - DUAL = 1 - QUAD = 2 - -class process_info: - def __init__(self, enum, mode): - self.enum = enum - self.mode = mode - - def __eq__(self, other): - if isinstance(other, self.__class__): - return self.enum == other.enum and self.mode == other.mode - return False - -#read adress(address mode、24BIT,32BIT) -READ_ADDRESS = process_info(process_enum.ADDRESS_BY_MODE , process_mode.SINGLE) -READ_3B_ADDRESS = process_info(process_enum.ADDRESS_24BIT , process_mode.SINGLE) -READ_4B_ADDRESS = process_info(process_enum.ADDRESS_32BIT , process_mode.SINGLE) - -#read DUAL Adress -READ_ADDRESS_DUAL = process_info(process_enum.ADDRESS_BY_MODE , process_mode.DUAL) -READ_3B_ADDRESS_DUAL = process_info(process_enum.ADDRESS_24BIT , process_mode.DUAL) -READ_4B_ADDRESS_DUAL = process_info(process_enum.ADDRESS_32BIT , process_mode.DUAL) - -#read QUAD Adress -READ_ADDRESS_QUAD = process_info(process_enum.ADDRESS_BY_MODE , process_mode.QUAD) -READ_3B_ADDRESS_QUAD = process_info(process_enum.ADDRESS_24BIT , process_mode.DUAL) -READ_4B_ADDRESS_QUAD = process_info(process_enum.ADDRESS_32BIT , process_mode.QUAD) - -#Read Byte(IO1, DUAL,QUAD) -READ_BYTE_SINGLE = process_info(process_enum.READ_BYTE , process_mode.SINGLE) -READ_BYTE_DUAL = process_info(process_enum.READ_BYTE , process_mode.DUAL) -READ_BYTE_QUAD = process_info(process_enum.READ_BYTE , process_mode.QUAD) - -READ_BYTE_SINGLE_CONTINUOUS = process_info(process_enum.READ_BYTE_CONTINUOUS , process_mode.SINGLE) -READ_BYTE_DUAL_CONTINUOUS = process_info(process_enum.READ_BYTE_CONTINUOUS , process_mode.DUAL) -READ_BYTE_QUAD_CONTINUOUS = process_info(process_enum.READ_BYTE_CONTINUOUS , process_mode.QUAD) - -#read m7-m0(DUAL,QUAD) -READ_MODE_BITS_DUAL = process_info(process_enum.CONTINUOUS_READ_MODE_BITS , process_mode.DUAL) -READ_MODE_BITS_QUAD = process_info(process_enum.CONTINUOUS_READ_MODE_BITS , process_mode.QUAD) - -#write (io0) -WRITE_BYTE_SINGLE = process_info(process_enum.WRITE_BYTE , process_mode.SINGLE) - -#DUMMY -DUMMY_CYCLE = process_info(process_enum.DUMMY_BY_MODE , process_mode.SINGLE) -DUMMY_CYCLE_8BIT = process_info(process_enum.DUMMY_8BIT , process_mode.SINGLE) -DUMMY_CYCLE_8BIT_QUAD = process_info(process_enum.DUMMY_8BIT , process_mode.QUAD) - -#Command list(command、name、abb、data after command) -command = { - 0x06 : ['Write Enable' , 'WREN' , []], - 0x04 : ['Write Disable' , 'WRDI' , []], - 0x50 : ['Write Enable for Volatile Status Register' , 'WRENFVSR' , []], - 0x05 : ['Read Status Register' , 'RDSR' , [READ_BYTE_SINGLE]], - 0x35 : ['Read Status Register' , 'RDSR' , [READ_BYTE_SINGLE]], - 0x15 : ['Read Status Register' , 'RDSR' , [READ_BYTE_SINGLE]], - 0x01 : ['Write Status Register' , 'WRSR' , [WRITE_BYTE_SINGLE]], - 0x31 : ['Write Status Register' , 'WRSR' , [WRITE_BYTE_SINGLE]], - 0x11 : ['Write Status Register' , 'WRSR' , [WRITE_BYTE_SINGLE]], - 0xC8 : ['Read Extended Register' , 'RER' , [READ_BYTE_SINGLE]], - 0xC5 : ['Write Extended Register' , 'WER' , [WRITE_BYTE_SINGLE]], - 0x03 : ['Read Data Bytes' , 'READ' , [READ_ADDRESS , READ_BYTE_SINGLE_CONTINUOUS]], - 0x13 : ['Read Data Bytes' , '4READ' , [READ_4B_ADDRESS , READ_BYTE_SINGLE_CONTINUOUS]], - 0x0B : ['Read Data Bytes at Higher Speed' , 'Fast Read' , [READ_ADDRESS , DUMMY_CYCLE_8BIT , READ_BYTE_SINGLE_CONTINUOUS]], - 0x0C : ['Read Data Bytes at Higher Speed' , '4Fast Read', [READ_4B_ADDRESS , DUMMY_CYCLE_8BIT , READ_BYTE_SINGLE_CONTINUOUS]], - 0x3B : ['Dual Output Fast Read' , 'DOFR' , [READ_ADDRESS ,DUMMY_CYCLE_8BIT , READ_BYTE_DUAL_CONTINUOUS]], - 0x3C : ['Dual Output Fast Read' , '4DOFR' , [READ_4B_ADDRESS ,DUMMY_CYCLE_8BIT , READ_BYTE_DUAL_CONTINUOUS]], - 0x6B : ['Quad Output Fast Read' , 'QOFR' , [READ_ADDRESS ,DUMMY_CYCLE_8BIT , READ_BYTE_QUAD_CONTINUOUS]], - 0x6C : ['Quad Output Fast Read' , '4QOFR' , [READ_4B_ADDRESS ,DUMMY_CYCLE_8BIT , READ_BYTE_QUAD_CONTINUOUS]], - 0xBB : ['Dual I/O Fast Read' , 'DIOFR' , [READ_ADDRESS_DUAL ,READ_MODE_BITS_DUAL , READ_BYTE_DUAL_CONTINUOUS]], - 0xBC : ['Dual I/O Fast Read' , '4DIOFR' , [READ_4B_ADDRESS_DUAL , READ_MODE_BITS_DUAL , READ_BYTE_DUAL_CONTINUOUS]], - 0xEB : ['Quad I/O Fast Read' , 'QIOFR' , [READ_ADDRESS_QUAD , READ_MODE_BITS_QUAD , DUMMY_CYCLE_8BIT_QUAD , DUMMY_CYCLE_8BIT_QUAD , READ_BYTE_QUAD_CONTINUOUS]], - 0xEC : ['Quad I/O Fast Read' , '4QIOFR' , [READ_4B_ADDRESS_QUAD , READ_MODE_BITS_QUAD , DUMMY_CYCLE_8BIT_QUAD , DUMMY_CYCLE_8BIT_QUAD , READ_BYTE_QUAD_CONTINUOUS]], - 0x77 : ['Set Burst with Wrap' , 'SBWW' , [DUMMY_CYCLE_8BIT_QUAD , DUMMY_CYCLE_8BIT_QUAD , DUMMY_CYCLE_8BIT_QUAD , READ_BYTE_QUAD_CONTINUOUS]], - 0x02 : ['Page Program' , 'PP' , [READ_ADDRESS] + [WRITE_BYTE_SINGLE] * 256], - 0x12 : ['Page Program' , '4PP' , [READ_4B_ADDRESS] + [WRITE_BYTE_SINGLE] * 256], - 0x32 : ['Quad Page Program' , 'QPP' , [READ_ADDRESS] + [READ_BYTE_QUAD_CONTINUOUS]], - 0x34 : ['Quad Page Program' , '4QPP' , [READ_4B_ADDRESS] + [READ_BYTE_QUAD_CONTINUOUS]], - 0x20 : ['Sector Erase' , 'SE' , [READ_ADDRESS]], - 0x21 : ['Sector Erase' , '4SE', [READ_4B_ADDRESS]], - 0x52 : ['32KB Block Erase' , 'BE32' , [READ_ADDRESS]], - 0x5C : ['32KB Block Erase' , '4BE32' , [READ_4B_ADDRESS]], - 0xD8 : ['64KB Block Erase' , 'BE64', [READ_ADDRESS]], - 0xDC : ['64KB Block Erase' , '4BE64', [READ_4B_ADDRESS]], - 0x60 : ['Chip Erase' , 'CE' , []], - 0xC7 : ['Chip Erase' , 'CE' , []], - 0xB9 : ['Deep Power-Down' , 'DP' , []], - 0x4B : ['Read Unique ID' , 'RUID', [DUMMY_CYCLE , READ_BYTE_SINGLE_CONTINUOUS]], - 0xB7 : ['Enter 4-Byte Address Mode' , 'EN4BADM' , []], - 0xE9 : ['Exit 4-Byte Address Mode' , 'EX4BADM' , []], - 0x30 : ['Clear SR Flags' , 'CLSRF' , []], - 0xAB : ['Release from Deep Power-Down and Read Device ID' , 'RDI' , []], - 0x90 : ['Read Manufacture ID/ Device ID' , 'REMS' , [READ_3B_ADDRESS , READ_BYTE_SINGLE , READ_BYTE_SINGLE]], - 0x92 : ['Read Manufacture ID/ Device ID Dual I/O' , 'REMS' , [READ_3B_ADDRESS_DUAL , READ_MODE_BITS_DUAL ,READ_BYTE_DUAL_CONTINUOUS]], - 0x94 : ['Read Manufacture ID/ Device ID Quad I/O' , 'REMS' , [READ_3B_ADDRESS_QUAD , READ_MODE_BITS_QUAD , DUMMY_CYCLE_8BIT_QUAD , DUMMY_CYCLE_8BIT_QUAD , READ_BYTE_QUAD_CONTINUOUS]], - 0x9F : ['Read Identification' , 'RDID', [READ_BYTE_SINGLE_CONTINUOUS]], - 0x75 : ['Program/Erase Suspend' , 'PES' , []], - 0x7A : ['Program/Erase Resume' , 'PER' , []], - 0x44 : ['Erase Security Registers' , 'ESR' , [READ_ADDRESS]], - 0x42 : ['Program Security Registers' , 'PSR' , [READ_ADDRESS] + [WRITE_BYTE_SINGLE] * 256], - 0x48 : ['Read Security Registers' , 'RSR' , [READ_ADDRESS , DUMMY_CYCLE_8BIT , READ_BYTE_SINGLE_CONTINUOUS]], - 0x66 : ['Enable Reset' , 'ENRE' , []], - 0x99 : ['Reset' , 'RE' , []], - 0x5A : ['Read Serial Flash Discoverable Parameter' , 'RSFDP', [READ_3B_ADDRESS , DUMMY_CYCLE_8BIT , READ_BYTE_SINGLE_CONTINUOUS]], -} - class ChannelError(Exception): pass class Decoder(srd.Decoder): api_version = 3 - id = 'smart_qspi' - name = 'Smart QSPI' + id = 'qspi' + name = 'QSPI' longname = 'Quad Serial Peripheral Interface' - desc = 'Full-duplex, synchronous, serial bus.compatible with Dual SPI and Quad SPI interfaces.' + desc = 'Full-duplex, synchronous, serial bus.' license = 'gplv2+' inputs = ['logic'] outputs = ['spi'] tags = ['Embedded/industrial'] channels = ( {'id': 'clk', 'type': 0, 'name': 'CLK', 'desc': 'Clock', 'idn':'dec_qspi_chan_clk'}, - {'id': 'io0', 'type': 109, 'name': 'IO0', 'desc': 'Data i/o 0', 'idn':'dec_qspi_chan_io0'}, + {'id': 'io0', 'type': 107, 'name': 'IO0', 'desc': 'Data i/o 0', 'idn':'dec_qspi_chan_io0'}, ) optional_channels = ( {'id': 'io1', 'type': 107, 'name': 'IO1', 'desc': 'Data i/o 1', 'idn':'dec_qspi_opt_chan_io1'}, @@ -204,35 +65,13 @@ class Decoder(srd.Decoder): 'values': (0, 1), 'idn':'dec_qspi_opt_cpha'}, {'id': 'bitorder', 'desc': 'Bit order', 'default': 'msb-first', 'values': ('msb-first', 'lsb-first'), 'idn':'dec_qspi_opt_bitorder'}, - {'id': 'ads', 'desc': 'Adress Mode', 'default': '24-Bit Address', - 'values': ('32-Bit Address', '24-Bit Address'), 'idn':'dec_qspi_adress_mode'}, - {'id': 'frame', 'desc': 'Frame Decoder', 'default': 'no', - 'values': ('yes', 'no'), 'idn':'dec_qspi_opt_frame'}, - {'id': 'twolinesmode', 'desc': 'TwoLinesMode', 'default':'spi', - 'values':('spi','dspi','qspi'), 'idn':'dec_qspi_two_lines_mode'}, - {'id': 'invalidlevel', 'desc': 'Keep high or low as invalid', 'default':'both', - 'values':('both','low','high'), 'idn':'dec_qspi_invalidlevel'}, - + {'id': 'wordsize', 'desc': 'Word size', 'default': 8, 'idn':'dec_qspi_opt_wordsize'}, ) annotations = ( - ('6', 'data-transfer', 'data transfer'), - ('108', 'Quad data', 'Q-Data'), - ('108', 'Dual data', 'D-Data'), - ('106', 'd0', 'IO0 data'), - ('106', 'd1', 'IO1 data'), - ('106', 'd2', 'IO2 data'), - ('106', 'd3', 'IO3 data'), - ('1000', 'other', 'Human-readable warnings'), + ('106', 'data', 'data'), ) annotation_rows = ( - ('data-transfer', 'data transfer', (0,)), - ('Quad data', 'Q-Data', (1,)), - ('Dual data', 'D-Data', (2,)), - ('d0', 'D0', (3,)), - ('d1', 'D1', (4,)), - ('d2', 'D2', (5,)), - ('d3', 'D3', (6,)), - ('Other', 'Other',(7,)), + ('data', 'data', (0,)), ) def __init__(self): @@ -243,29 +82,6 @@ def reset(self): self.bitcount = 0 self.data = 0 self.bits = [] - self.io0bits=[] - self.io1bits=[] - self.io2bits=[] - self.io3bits=[] - self.io0bytes=[] - self.io1bytes=[] - self.io2bytes=[] - self.io3bytes=[] - self.io0data=0 - self.io1data=0 - self.io2data=0 - self.io3data=0 - - self.command = 0 - - self.state_count = 0 - self.ads = False - self.diagram = [] - - self.ss = 0 - self.count = 0 - self.bits_data = 0 - self.ss_block = -1 self.samplenum = -1 self.ss_transfer = -1 @@ -273,332 +89,93 @@ def reset(self): self.have_cs = self.have_io1 = self.have_io3 = None def start(self): - self.out_python = self.register(srd.OUTPUT_PYTHON) self.out_ann = self.register(srd.OUTPUT_ANN) - self.out_binary = self.register(srd.OUTPUT_BINARY) - self.out_bitrate = self.register(srd.OUTPUT_META, - meta=(int, 'Bitrate', 'Bitrate during transfers')) - self.bw = (8 + 7) // 8 - self.spiModeSet=self.options['twolinesmode'].lower() - self.invalidlevelSet = 0XFF if self.options['invalidlevel'] == 'high' else 0 - - self.ads = False if self.options['ads'] == '24-Bit Address' else True + self.bw = (self.options['wordsize'] + 7) // 8 def metadata(self, key, value): if key == srd.SRD_CONF_SAMPLERATE: self.samplerate = value - self.bit_width = float(self.samplerate) / float(115200) def putw(self, data): self.put(self.ss_block, self.samplenum, self.out_ann, data) - def putgse(self, ss, es, data): - self.put(ss, es, self.out_ann, data) - - def putg(self, data): - s, halfbit = self.samplenum, self.bit_width / 2.0 - self.put(s - floor(halfbit), s + ceil(halfbit), self.out_ann, data) - - def puttext(self, ss, es, state, data): - self.put(ss, es, self.out_ann, [0, ['%s : 0x%02x' % (process_text[state][0] , data), - '%s : 0x%02x' % (process_text[state][1] , data), - '0x%02X' % data]]) - - def putdummy(self, ss, es): - self.put(ss, es, self.out_ann, [0, ['Dummy Cycles','Dummy','D']]) - - def putcmd(self, ss, es): - self.put(ss, es, self.out_ann, [0, ['%s : %s' % (process_text[process_enum.COMMAND][0] , command[self.io0data][0]), - '%s : %s' % (process_text[process_enum.COMMAND][1] , command[self.io0data][1]), - '%s' % command[self.io0data][1]]]) - - def checkinvalidlevel(self,data): # if data line is keep high or keep low,data is invalid then return true - if self.options['invalidlevel']=='both' : - return data==0xff or data ==0 - elif self.options['invalidlevel']=='high': - return data==0xff - else : - return data==0 - - - def putdata(self, frame): - data0 = self.io0data - data1 = self.io1data - data2 = self.io2data if self.have_io3 else None - data3 = self.io3data if self.have_io3 else None - - ss,es = self.io0bits[-1][1], self.io0bits[0][2] - if frame: - if self.have_io3: - self.io2bytes.append(Data(ss = ss, es = es, val = data2)) - self.io3bytes.append(Data(ss = ss, es = es, val = data3)) - if self.have_io1: - self.io1bytes.append(Data(ss = ss, es = es, val = data1)) - self.io0bytes.append(Data(ss = ss, es = es, val = data0)) - - bo = self.options['bitorder'] + def putdata(self): + # Pass bits and then data to the next PD up the stack. + ss, es = self.bits[-1][1], self.bits[0][2] - if(((self.checkinvalidlevel(data2) or self.checkinvalidlevel(data3)) and self.have_io3) or (self.checkinvalidlevel(data1) and self.have_io1)): - spiMode = self.spiModeSet - elif self.have_io3: - spiMode='qspi' - else : - spiMode='spi' - - self.putgse(ss,es,[7, ['%s' %spiMode.upper()]]) - self.put(ss, es, self.out_ann, [3, ['@%02X' % self.io0data]]) - if self.have_io1: - self.put(ss, es, self.out_ann, [4, ['@%02X' % self.io1data]]) - if self.have_io3: - self.put(ss, es, self.out_ann, [5, ['@%02X' % self.io2data]]) - self.put(ss, es, self.out_ann, [6, ['@%02X' % self.io3data]]) - - if spiMode == 'qspi' or spiMode == 'dspi': - - qdata = [] - ddata = [] - if self.have_io1 and self.have_io3: - for i in range(4): - self.data = 0 - for j in range(2): - self.data |= self.io3bits[-1 - i * 2 - j][0] - self.data = self.data << 1 - self.data |= self.io2bits[-1 - i * 2 - j][0] - self.data = self.data << 1 - self.data |= self.io1bits[-1 - i * 2 - j][0] - self.data = self.data << 1 - self.data |= self.io0bits[-1 - i * 2 - j][0] - if j < 1: - self.data = self.data << 1 - - qss,qes = self.io0bits[-1 - i * 2][1], self.io0bits[-2 - i * 2][2] - - if not bo == 'msb-first': - dataTemp = (0xF0 & self.data) >> 4|(0x0f & self.data) << 4 - self.data = dataTemp - - qdata.append([self.data, qss, qes]) - self.put(qss, qes, self.out_ann, [1, ['@%02X' % self.data]]) - if self.have_io1: - for i in range(2): - self.data = 0 - for j in range(4): - self.data |= self.io1bits[-1 - i * 4 - j][0] - self.data = self.data << 1 - self.data |= self.io0bits[-1 - i * 4 - j][0] - if j < 3: - self.data = self.data << 1 - dss,des = self.io0bits[-1 - i * 4][1], self.io0bits[-4 - i * 4][2] - if not bo == 'msb-first': - dataTemp = (0xF0 & self.data) >> 4|(0x0f & self.data) << 4 - self.data = dataTemp - - ddata.append([self.data, dss, des]) - self.put(dss, des, self.out_ann, [2, ['@%02X' % self.data]]) - - if self.command == 0 and self.io0data in command: - self.putcmd(ss, es) - #update adress mode - if self.io0data == 0xB7: - self.ads = True - elif self.io0data == 0xE9: - self.ads = False - - if len(command[self.io0data][2]) != 0: - self.command = self.io0data - self.diagram = command[self.command][2] - - elif self.command != 0: - cur_state = self.diagram[self.state_count] - - i, size = 0, 1 - if cur_state.mode == process_mode.DUAL: - size = 2 - elif cur_state.mode == process_mode.QUAD: - size = 4 - - while i < size: - if size == 1: - if cur_state.enum == process_enum.READ_BYTE and self.have_io1: - origin_data = [self.io1data & 0xFF , ss, es] - else: - origin_data = [self.io0data & 0xFF , ss, es] - elif size == 2: - origin_data = ddata[i] - origin_data[0] = origin_data[0] & 0xFF - elif size == 4: - origin_data = qdata[i] - origin_data[0] = origin_data[0] & 0xFF - i = i + 1 - - if cur_state.enum == process_enum.ADDRESS_BY_MODE or \ - cur_state.enum == process_enum.ADDRESS_24BIT or \ - cur_state.enum == process_enum.ADDRESS_32BIT or \ - cur_state.enum == process_enum.DUMMY_BY_MODE or \ - cur_state.enum == process_enum.DUMMY_8BIT: - - if cur_state.enum == process_enum.ADDRESS_BY_MODE: - cur_state.enum = process_enum.ADDRESS_24BIT if self.ads == False else process_enum.ADDRESS_32BIT - elif cur_state.enum == process_enum.DUMMY_BY_MODE: - cur_state.enum = process_enum.DUMMY_32BIT if self.ads == False else process_enum.DUMMY_40BIT - - if self.count == 0: - self.ss = ss - self.bits_data |= origin_data[0] - self.count = self.count + 1 - - if (cur_state.enum == process_enum.ADDRESS_24BIT and self.count == 3) or \ - (cur_state.enum == process_enum.ADDRESS_32BIT and self.count == 4) or \ - (cur_state.enum == process_enum.DUMMY_8BIT and self.count == 1) or \ - (cur_state.enum == process_enum.DUMMY_32BIT and self.count == 4) or \ - (cur_state.enum == process_enum.DUMMY_40BIT and self.count == 5): - - if cur_state.enum == process_enum.ADDRESS_24BIT or \ - cur_state.enum == process_enum.ADDRESS_32BIT: - self.puttext(self.ss , origin_data[2] , cur_state.enum , self.bits_data) - else: - self.putdummy(self.ss, origin_data[2]) - - self.ss = 0 - self.count = 0 - self.bits_data = 0 - self.state_count += 1 - - if self.state_count < len(self.diagram): - cur_state = self.diagram[self.state_count] - else: - self.bits_data = self.bits_data << 8 - - elif cur_state.enum == process_enum.WRITE_BYTE or \ - cur_state.enum == process_enum.READ_BYTE or \ - cur_state.enum == process_enum.READ_BYTE_CONTINUOUS or \ - cur_state.enum == process_enum.CONTINUOUS_READ_MODE_BITS: - - self.puttext(origin_data[1] , origin_data[2] , cur_state.enum , origin_data[0]) - - if cur_state.enum != process_enum.READ_BYTE_CONTINUOUS: - self.state_count += 1 - - if self.state_count < len(self.diagram): - cur_state = self.diagram[self.state_count] - - if self.state_count >= len(self.diagram): - self.command = 0 - self.diagram = [] - self.state_count = 0 - break + # Dataword annotations. + self.put(ss, es, self.out_ann, [0, ['%02X' % self.data]]) def reset_decoder_state(self): - - self.io0data = 0 - self.io1data = 0 if self.have_io1 else None - self.io2data=0 if self.have_io3 else None - self.io3data=0 if self.have_io3 else None - - self.io0bits=[] - self.io1bits=[] if self.have_io1 else None - self.io2bits=[] if self.have_io3 else None - self.io3bits=[] if self.have_io3 else None + self.data = 0 + self.bits = [] self.bitcount = 0 def cs_asserted(self, cs): active_low = (self.options['cs_polarity'] == 'active-low') return (cs == 0) if active_low else (cs == 1) - def handle_bit(self, datapins, clk, cs, frame): + def handle_bit(self, datapins, clk, cs): # If this is the first bit of a dataword, save its sample number. if self.bitcount == 0: self.ss_block = self.samplenum self.cs_was_deasserted = \ not self.cs_asserted(cs) if self.have_cs else False - ws = 8 bo = self.options['bitorder'] - - if bo == 'msb-first': - self.io0data |= datapins[3] << (ws - 1 - self.bitcount) + ws = self.options['wordsize'] + if self.have_io3: + nibws = ws >> 2 + elif self.have_io1: + nibws = ws >> 1 else: - self.io0data |= datapins[3] << self.bitcount - if self.have_io1: - if bo == 'msb-first': - self.io1data |= datapins[2] << (ws - 1 - self.bitcount) - else: - self.io1data |= datapins[2] << self.bitcount + nibws = ws + # Receive bit into our shift register. if self.have_io3: + for i in range(4): + if bo == 'msb-first': + self.data |= datapins[i] << (ws - 1 - self.bitcount*4 - i) + else: + self.data |= datapins[3-i] << (self.bitcount*4 + i) + elif self.have_io1: + for i in range(2): + if bo == 'msb-first': + self.data |= datapins[i+2] << (ws - 1 - self.bitcount*2 - i) + else: + self.data |= datapins[3-i] << (self.bitcount*2 + i) + else: if bo == 'msb-first': - self.io2data |= datapins[1] << (ws - 1 - self.bitcount) - self.io3data |= datapins[0] << (ws - 1 - self.bitcount) + self.data |= datapins[3] << (ws - 1 - self.bitcount) else: - self.io2data |= datapins[1] << self.bitcount - self.io3data |= datapins[0] << self.bitcount + self.data |= datapins[3] << self.bitcount # Guesstimate the endsample for this bit (can be overridden below). es = self.samplenum if self.bitcount > 0: - es += self.samplenum - self.io0bits[0][1] + es += self.samplenum - self.bits[0][1] - self.io0bits.insert(0, [datapins[3], self.samplenum, es]) - if self.have_io1: - self.io1bits.insert(0, [datapins[2], self.samplenum, es]) - if self.have_io3: - self.io2bits.insert(0, [datapins[1], self.samplenum, es]) - self.io3bits.insert(0, [datapins[0], self.samplenum, es]) + self.bits.insert(0, [datapins[3], self.samplenum, es]) if self.bitcount > 0: - self.io0bits[1][2] = self.samplenum - if self.have_io1: - self.io1bits[1][2] = self.samplenum - if self.have_io3: - self.io2bits[1][2] = self.samplenum - self.io3bits[1][2] = self.samplenum + self.bits[1][2] = self.samplenum self.bitcount += 1 # Continue to receive if not enough bits were received, yet. - if self.bitcount != ws: + if self.bitcount != nibws: return - self.putdata(frame) - if self.samplerate: - elapsed = 1 / float(self.samplerate) - elapsed *= (self.samplenum - self.ss_block + 1) - bitrate = int(1 / elapsed * ws) - self.put(self.ss_block, self.samplenum, self.out_bitrate, bitrate) - - if self.have_cs and self.cs_was_deasserted: - self.putw([6, ['CS# was deasserted during this data word!']]) + self.putdata() self.reset_decoder_state() - def find_clk_edge(self, datapins, clk, cs, first,frame): - + def find_clk_edge(self, datapins, clk, cs, first): if self.have_cs and (first or (self.matched & (0b1 << self.have_cs))): # Send all CS# pin value changes. oldcs = None if first else 1 - cs - self.put(self.samplenum, self.samplenum, self.out_python, - ['CS-CHANGE', oldcs, cs]) - - if frame: - if self.cs_asserted(cs): - self.ss_transfer = self.samplenum - self.io0bytes = [] - self.io1bytes = [] - self.io2bytes = [] - self.io3bytes = [] - - elif self.ss_transfer != -1: - self.put(self.ss_transfer, self.samplenum, self.out_python, - ['TRANSFER', self.io0bytes, self.io1bytes, self.io2bytes,self.io3bytes]) - # Reset decoder state when CS# changes (and the CS# pin is used). - self.command = 0 - self.diagram = [] - self.state_count = 0 - - self.ss = 0 - self.count = 0 - self.bits_data = 0 + # Reset decoder state when CS# changes (and the CS# pin is used). self.reset_decoder_state() # We only care about samples if CS# is asserted. @@ -610,25 +187,17 @@ def find_clk_edge(self, datapins, clk, cs, first,frame): return # Found the correct clock edge, now get the SPI bit(s). - self.handle_bit(datapins, clk, cs,frame) + self.handle_bit(datapins, clk, cs) def decode(self): # The CLK & IO0 input is mandatory. Other signals are (individually) # optional. Tell stacked decoders when we don't have a CS# signal. if not self.has_channel(0): raise ChannelError('CLK pin required.') - if not self.has_channel(1): - raise ChannelError('io0 pin required.') - self.have_io1 = self.has_channel(2) self.have_io3 = self.has_channel(3) & self.has_channel(4) self.have_cs = self.has_channel(5) - if not self.have_cs: - self.put(0, 0, self.out_python, ['CS-CHANGE', None, None]) - - frame = self.options['frame'] == 'yes' - # We want all CLK changes. We want all CS changes if CS is used. # Map 'have_cs' from boolean to an integer index. This simplifies # evaluation in other locations. @@ -648,12 +217,10 @@ def decode(self): # previous implementation did this by seeding old values with # None, which led to an immediate "change" in comparison. (clk, d0, d1, d2, d3, cs) = self.wait({}) - d = (d3, d2, d1, d0) - self.find_clk_edge(d, clk, cs, True ,frame) + d = (d3, d2, d1, d0); + self.find_clk_edge(d, clk, cs, True) while True: (clk, d0, d1, d2, d3, cs) = self.wait(wait_cond) - d = (d3, d2, d1, d0) - self.find_clk_edge(d, clk, cs, False,frame)# - - + d = (d3, d2, d1, d0); + self.find_clk_edge(d, clk, cs, False)# diff --git a/libsigrokdecode4DSL/decoders/smart qspi/__init__.py b/libsigrokdecode4DSL/decoders/smart qspi/__init__.py new file mode 100644 index 00000000..10b74234 --- /dev/null +++ b/libsigrokdecode4DSL/decoders/smart qspi/__init__.py @@ -0,0 +1,31 @@ +## +## This file is part of the libsigrokdecode project. +## +## Copyright (C) 2016 fenugrec +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, see . +## + +''' +This protocol decoder decodes the AUD (Advanced User Debugger) interface +of certain Renesas / Hitachi microcontrollers, when set in Branch Trace mode. + +AUD has two modes, this PD currently only supports "Branch Trace" mode. + +Details: +http://www.renesas.eu/products/mpumcu/superh/sh7050/sh7058/Documentation.jsp +("rej09b0046 - SH7058 Hardware manual") +''' + +from .pd import Decoder diff --git a/libsigrokdecode4DSL/decoders/smart qspi/pd.py b/libsigrokdecode4DSL/decoders/smart qspi/pd.py new file mode 100644 index 00000000..75ed0189 --- /dev/null +++ b/libsigrokdecode4DSL/decoders/smart qspi/pd.py @@ -0,0 +1,659 @@ +## +## This file is part of the libsigrokdecode project. +## +## Copyright (C) 2011 Gareth McMullin +## Copyright (C) 2012-2014 Uwe Hermann +## Copyright (C) 2024 DreamSourceLab +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, see . +## + +import sigrokdecode as srd +from collections import namedtuple +from math import floor, ceil +from enum import Enum +Data = namedtuple('Data', ['ss', 'es', 'val']) + +## +## 2023/4/8 DreamSourceLab : add flash module +## + +# Key: (CPOL, CPHA). Value: SPI mode. +# Clock polarity (CPOL) = 0/1: Clock is low/high when inactive. +# Clock phase (CPHA) = 0/1: Data is valid on the leading/trailing clock edge. +spi_mode = { + (0, 0): 0, # Mode 0 + (0, 1): 1, # Mode 1 + (1, 0): 2, # Mode 2 + (1, 1): 3, # Mode 3 +} + +class process_enum(Enum): + COMMAND = 0 + WRITE_BYTE = 1 + READ_BYTE = 2 + READ_BYTE_CONTINUOUS = 3 + CONTINUOUS_READ_MODE_BITS = 4 + ADDRESS_BY_MODE = 5 + ADDRESS_24BIT = 6 + ADDRESS_32BIT = 7 + DUMMY_BY_MODE = 8 + DUMMY_8BIT = 9 + DUMMY_32BIT = 10 + DUMMY_40BIT = 11 + +process_text = { + process_enum.COMMAND : ['Command' , 'CMD'] , + process_enum.WRITE_BYTE : ['Write Data' , 'WD'] , + process_enum.READ_BYTE : ['Read Data' , 'RD'] , + process_enum.READ_BYTE_CONTINUOUS : ['Read Data' , 'RD'] , + process_enum.ADDRESS_24BIT : ['24-Bit Address' , 'AD'] , + process_enum.ADDRESS_32BIT : ['32-Bit Address' , 'AD'] , + process_enum.CONTINUOUS_READ_MODE_BITS : ['Continuous Read Mode bits' , 'M'] , +} + +class process_mode(Enum): + SINGLE = 0 + DUAL = 1 + QUAD = 2 + +class process_info: + def __init__(self, enum, mode): + self.enum = enum + self.mode = mode + + def __eq__(self, other): + if isinstance(other, self.__class__): + return self.enum == other.enum and self.mode == other.mode + return False + +#read adress(address mode、24BIT,32BIT) +READ_ADDRESS = process_info(process_enum.ADDRESS_BY_MODE , process_mode.SINGLE) +READ_3B_ADDRESS = process_info(process_enum.ADDRESS_24BIT , process_mode.SINGLE) +READ_4B_ADDRESS = process_info(process_enum.ADDRESS_32BIT , process_mode.SINGLE) + +#read DUAL Adress +READ_ADDRESS_DUAL = process_info(process_enum.ADDRESS_BY_MODE , process_mode.DUAL) +READ_3B_ADDRESS_DUAL = process_info(process_enum.ADDRESS_24BIT , process_mode.DUAL) +READ_4B_ADDRESS_DUAL = process_info(process_enum.ADDRESS_32BIT , process_mode.DUAL) + +#read QUAD Adress +READ_ADDRESS_QUAD = process_info(process_enum.ADDRESS_BY_MODE , process_mode.QUAD) +READ_3B_ADDRESS_QUAD = process_info(process_enum.ADDRESS_24BIT , process_mode.DUAL) +READ_4B_ADDRESS_QUAD = process_info(process_enum.ADDRESS_32BIT , process_mode.QUAD) + +#Read Byte(IO1, DUAL,QUAD) +READ_BYTE_SINGLE = process_info(process_enum.READ_BYTE , process_mode.SINGLE) +READ_BYTE_DUAL = process_info(process_enum.READ_BYTE , process_mode.DUAL) +READ_BYTE_QUAD = process_info(process_enum.READ_BYTE , process_mode.QUAD) + +READ_BYTE_SINGLE_CONTINUOUS = process_info(process_enum.READ_BYTE_CONTINUOUS , process_mode.SINGLE) +READ_BYTE_DUAL_CONTINUOUS = process_info(process_enum.READ_BYTE_CONTINUOUS , process_mode.DUAL) +READ_BYTE_QUAD_CONTINUOUS = process_info(process_enum.READ_BYTE_CONTINUOUS , process_mode.QUAD) + +#read m7-m0(DUAL,QUAD) +READ_MODE_BITS_DUAL = process_info(process_enum.CONTINUOUS_READ_MODE_BITS , process_mode.DUAL) +READ_MODE_BITS_QUAD = process_info(process_enum.CONTINUOUS_READ_MODE_BITS , process_mode.QUAD) + +#write (io0) +WRITE_BYTE_SINGLE = process_info(process_enum.WRITE_BYTE , process_mode.SINGLE) + +#DUMMY +DUMMY_CYCLE = process_info(process_enum.DUMMY_BY_MODE , process_mode.SINGLE) +DUMMY_CYCLE_8BIT = process_info(process_enum.DUMMY_8BIT , process_mode.SINGLE) +DUMMY_CYCLE_8BIT_QUAD = process_info(process_enum.DUMMY_8BIT , process_mode.QUAD) + +#Command list(command、name、abb、data after command) +command = { + 0x06 : ['Write Enable' , 'WREN' , []], + 0x04 : ['Write Disable' , 'WRDI' , []], + 0x50 : ['Write Enable for Volatile Status Register' , 'WRENFVSR' , []], + 0x05 : ['Read Status Register' , 'RDSR' , [READ_BYTE_SINGLE]], + 0x35 : ['Read Status Register' , 'RDSR' , [READ_BYTE_SINGLE]], + 0x15 : ['Read Status Register' , 'RDSR' , [READ_BYTE_SINGLE]], + 0x01 : ['Write Status Register' , 'WRSR' , [WRITE_BYTE_SINGLE]], + 0x31 : ['Write Status Register' , 'WRSR' , [WRITE_BYTE_SINGLE]], + 0x11 : ['Write Status Register' , 'WRSR' , [WRITE_BYTE_SINGLE]], + 0xC8 : ['Read Extended Register' , 'RER' , [READ_BYTE_SINGLE]], + 0xC5 : ['Write Extended Register' , 'WER' , [WRITE_BYTE_SINGLE]], + 0x03 : ['Read Data Bytes' , 'READ' , [READ_ADDRESS , READ_BYTE_SINGLE_CONTINUOUS]], + 0x13 : ['Read Data Bytes' , '4READ' , [READ_4B_ADDRESS , READ_BYTE_SINGLE_CONTINUOUS]], + 0x0B : ['Read Data Bytes at Higher Speed' , 'Fast Read' , [READ_ADDRESS , DUMMY_CYCLE_8BIT , READ_BYTE_SINGLE_CONTINUOUS]], + 0x0C : ['Read Data Bytes at Higher Speed' , '4Fast Read', [READ_4B_ADDRESS , DUMMY_CYCLE_8BIT , READ_BYTE_SINGLE_CONTINUOUS]], + 0x3B : ['Dual Output Fast Read' , 'DOFR' , [READ_ADDRESS ,DUMMY_CYCLE_8BIT , READ_BYTE_DUAL_CONTINUOUS]], + 0x3C : ['Dual Output Fast Read' , '4DOFR' , [READ_4B_ADDRESS ,DUMMY_CYCLE_8BIT , READ_BYTE_DUAL_CONTINUOUS]], + 0x6B : ['Quad Output Fast Read' , 'QOFR' , [READ_ADDRESS ,DUMMY_CYCLE_8BIT , READ_BYTE_QUAD_CONTINUOUS]], + 0x6C : ['Quad Output Fast Read' , '4QOFR' , [READ_4B_ADDRESS ,DUMMY_CYCLE_8BIT , READ_BYTE_QUAD_CONTINUOUS]], + 0xBB : ['Dual I/O Fast Read' , 'DIOFR' , [READ_ADDRESS_DUAL ,READ_MODE_BITS_DUAL , READ_BYTE_DUAL_CONTINUOUS]], + 0xBC : ['Dual I/O Fast Read' , '4DIOFR' , [READ_4B_ADDRESS_DUAL , READ_MODE_BITS_DUAL , READ_BYTE_DUAL_CONTINUOUS]], + 0xEB : ['Quad I/O Fast Read' , 'QIOFR' , [READ_ADDRESS_QUAD , READ_MODE_BITS_QUAD , DUMMY_CYCLE_8BIT_QUAD , DUMMY_CYCLE_8BIT_QUAD , READ_BYTE_QUAD_CONTINUOUS]], + 0xEC : ['Quad I/O Fast Read' , '4QIOFR' , [READ_4B_ADDRESS_QUAD , READ_MODE_BITS_QUAD , DUMMY_CYCLE_8BIT_QUAD , DUMMY_CYCLE_8BIT_QUAD , READ_BYTE_QUAD_CONTINUOUS]], + 0x77 : ['Set Burst with Wrap' , 'SBWW' , [DUMMY_CYCLE_8BIT_QUAD , DUMMY_CYCLE_8BIT_QUAD , DUMMY_CYCLE_8BIT_QUAD , READ_BYTE_QUAD_CONTINUOUS]], + 0x02 : ['Page Program' , 'PP' , [READ_ADDRESS] + [WRITE_BYTE_SINGLE] * 256], + 0x12 : ['Page Program' , '4PP' , [READ_4B_ADDRESS] + [WRITE_BYTE_SINGLE] * 256], + 0x32 : ['Quad Page Program' , 'QPP' , [READ_ADDRESS] + [READ_BYTE_QUAD_CONTINUOUS]], + 0x34 : ['Quad Page Program' , '4QPP' , [READ_4B_ADDRESS] + [READ_BYTE_QUAD_CONTINUOUS]], + 0x20 : ['Sector Erase' , 'SE' , [READ_ADDRESS]], + 0x21 : ['Sector Erase' , '4SE', [READ_4B_ADDRESS]], + 0x52 : ['32KB Block Erase' , 'BE32' , [READ_ADDRESS]], + 0x5C : ['32KB Block Erase' , '4BE32' , [READ_4B_ADDRESS]], + 0xD8 : ['64KB Block Erase' , 'BE64', [READ_ADDRESS]], + 0xDC : ['64KB Block Erase' , '4BE64', [READ_4B_ADDRESS]], + 0x60 : ['Chip Erase' , 'CE' , []], + 0xC7 : ['Chip Erase' , 'CE' , []], + 0xB9 : ['Deep Power-Down' , 'DP' , []], + 0x4B : ['Read Unique ID' , 'RUID', [DUMMY_CYCLE , READ_BYTE_SINGLE_CONTINUOUS]], + 0xB7 : ['Enter 4-Byte Address Mode' , 'EN4BADM' , []], + 0xE9 : ['Exit 4-Byte Address Mode' , 'EX4BADM' , []], + 0x30 : ['Clear SR Flags' , 'CLSRF' , []], + 0xAB : ['Release from Deep Power-Down and Read Device ID' , 'RDI' , []], + 0x90 : ['Read Manufacture ID/ Device ID' , 'REMS' , [READ_3B_ADDRESS , READ_BYTE_SINGLE , READ_BYTE_SINGLE]], + 0x92 : ['Read Manufacture ID/ Device ID Dual I/O' , 'REMS' , [READ_3B_ADDRESS_DUAL , READ_MODE_BITS_DUAL ,READ_BYTE_DUAL_CONTINUOUS]], + 0x94 : ['Read Manufacture ID/ Device ID Quad I/O' , 'REMS' , [READ_3B_ADDRESS_QUAD , READ_MODE_BITS_QUAD , DUMMY_CYCLE_8BIT_QUAD , DUMMY_CYCLE_8BIT_QUAD , READ_BYTE_QUAD_CONTINUOUS]], + 0x9F : ['Read Identification' , 'RDID', [READ_BYTE_SINGLE_CONTINUOUS]], + 0x75 : ['Program/Erase Suspend' , 'PES' , []], + 0x7A : ['Program/Erase Resume' , 'PER' , []], + 0x44 : ['Erase Security Registers' , 'ESR' , [READ_ADDRESS]], + 0x42 : ['Program Security Registers' , 'PSR' , [READ_ADDRESS] + [WRITE_BYTE_SINGLE] * 256], + 0x48 : ['Read Security Registers' , 'RSR' , [READ_ADDRESS , DUMMY_CYCLE_8BIT , READ_BYTE_SINGLE_CONTINUOUS]], + 0x66 : ['Enable Reset' , 'ENRE' , []], + 0x99 : ['Reset' , 'RE' , []], + 0x5A : ['Read Serial Flash Discoverable Parameter' , 'RSFDP', [READ_3B_ADDRESS , DUMMY_CYCLE_8BIT , READ_BYTE_SINGLE_CONTINUOUS]], +} + +class ChannelError(Exception): + pass + +class Decoder(srd.Decoder): + api_version = 3 + id = 'smart_qspi' + name = 'Smart QSPI' + longname = 'Quad Serial Peripheral Interface' + desc = 'Full-duplex, synchronous, serial bus.compatible with Dual SPI and Quad SPI interfaces.' + license = 'gplv2+' + inputs = ['logic'] + outputs = ['spi'] + tags = ['Embedded/industrial'] + channels = ( + {'id': 'clk', 'type': 0, 'name': 'CLK', 'desc': 'Clock', 'idn':'dec_qspi_chan_clk'}, + {'id': 'io0', 'type': 109, 'name': 'IO0', 'desc': 'Data i/o 0', 'idn':'dec_qspi_chan_io0'}, + ) + optional_channels = ( + {'id': 'io1', 'type': 107, 'name': 'IO1', 'desc': 'Data i/o 1', 'idn':'dec_qspi_opt_chan_io1'}, + {'id': 'io2', 'type': 107, 'name': 'IO2', 'desc': 'Data i/o 2', 'idn':'dec_qspi_opt_chan_io2'}, + {'id': 'io3', 'type': 107, 'name': 'IO3', 'desc': 'Data i/o 3', 'idn':'dec_qspi_opt_chan_io3'}, + {'id': 'cs', 'type': -1, 'name': 'CS#', 'desc': 'Chip-select', 'idn':'dec_qspi_opt_chan_cs'}, + ) + options = ( + {'id': 'cs_polarity', 'desc': 'CS# polarity', 'default': 'active-low', + 'values': ('active-low', 'active-high'), 'idn':'dec_qspi_opt_cs_polarity'}, + {'id': 'cpol', 'desc': 'Clock polarity (CPOL)', 'default': 0, + 'values': (0, 1), 'idn':'dec_qspi_opt_cpol'}, + {'id': 'cpha', 'desc': 'Clock phase (CPHA)', 'default': 0, + 'values': (0, 1), 'idn':'dec_qspi_opt_cpha'}, + {'id': 'bitorder', 'desc': 'Bit order', + 'default': 'msb-first', 'values': ('msb-first', 'lsb-first'), 'idn':'dec_qspi_opt_bitorder'}, + {'id': 'ads', 'desc': 'Adress Mode', 'default': '24-Bit Address', + 'values': ('32-Bit Address', '24-Bit Address'), 'idn':'dec_qspi_adress_mode'}, + {'id': 'frame', 'desc': 'Frame Decoder', 'default': 'no', + 'values': ('yes', 'no'), 'idn':'dec_qspi_opt_frame'}, + {'id': 'twolinesmode', 'desc': 'TwoLinesMode', 'default':'spi', + 'values':('spi','dspi','qspi'), 'idn':'dec_qspi_two_lines_mode'}, + {'id': 'invalidlevel', 'desc': 'Keep high or low as invalid', 'default':'both', + 'values':('both','low','high'), 'idn':'dec_qspi_invalidlevel'}, + + ) + annotations = ( + ('6', 'data-transfer', 'data transfer'), + ('108', 'Quad data', 'Q-Data'), + ('108', 'Dual data', 'D-Data'), + ('106', 'd0', 'IO0 data'), + ('106', 'd1', 'IO1 data'), + ('106', 'd2', 'IO2 data'), + ('106', 'd3', 'IO3 data'), + ('1000', 'other', 'Human-readable warnings'), + ) + annotation_rows = ( + ('data-transfer', 'data transfer', (0,)), + ('Quad data', 'Q-Data', (1,)), + ('Dual data', 'D-Data', (2,)), + ('d0', 'D0', (3,)), + ('d1', 'D1', (4,)), + ('d2', 'D2', (5,)), + ('d3', 'D3', (6,)), + ('Other', 'Other',(7,)), + ) + + def __init__(self): + self.reset() + + def reset(self): + self.samplerate = None + self.bitcount = 0 + self.data = 0 + self.bits = [] + self.io0bits=[] + self.io1bits=[] + self.io2bits=[] + self.io3bits=[] + self.io0bytes=[] + self.io1bytes=[] + self.io2bytes=[] + self.io3bytes=[] + self.io0data=0 + self.io1data=0 + self.io2data=0 + self.io3data=0 + + self.command = 0 + + self.state_count = 0 + self.ads = False + self.diagram = [] + + self.ss = 0 + self.count = 0 + self.bits_data = 0 + + self.ss_block = -1 + self.samplenum = -1 + self.ss_transfer = -1 + self.cs_was_deasserted = False + self.have_cs = self.have_io1 = self.have_io3 = None + + def start(self): + self.out_python = self.register(srd.OUTPUT_PYTHON) + self.out_ann = self.register(srd.OUTPUT_ANN) + self.out_binary = self.register(srd.OUTPUT_BINARY) + self.out_bitrate = self.register(srd.OUTPUT_META, + meta=(int, 'Bitrate', 'Bitrate during transfers')) + self.bw = (8 + 7) // 8 + self.spiModeSet=self.options['twolinesmode'].lower() + self.invalidlevelSet = 0XFF if self.options['invalidlevel'] == 'high' else 0 + + self.ads = False if self.options['ads'] == '24-Bit Address' else True + + def metadata(self, key, value): + if key == srd.SRD_CONF_SAMPLERATE: + self.samplerate = value + self.bit_width = float(self.samplerate) / float(115200) + + def putw(self, data): + self.put(self.ss_block, self.samplenum, self.out_ann, data) + + def putgse(self, ss, es, data): + self.put(ss, es, self.out_ann, data) + + def putg(self, data): + s, halfbit = self.samplenum, self.bit_width / 2.0 + self.put(s - floor(halfbit), s + ceil(halfbit), self.out_ann, data) + + def puttext(self, ss, es, state, data): + self.put(ss, es, self.out_ann, [0, ['%s : 0x%02x' % (process_text[state][0] , data), + '%s : 0x%02x' % (process_text[state][1] , data), + '0x%02X' % data]]) + + def putdummy(self, ss, es): + self.put(ss, es, self.out_ann, [0, ['Dummy Cycles','Dummy','D']]) + + def putcmd(self, ss, es): + self.put(ss, es, self.out_ann, [0, ['%s(0x%02x)' % (command[self.io0data][0] , self.io0data), + '%s(0x%02x)' % (command[self.io0data][1] , self.io0data), + '%s' % command[self.io0data][1]]]) + + def checkinvalidlevel(self,data): # if data line is keep high or keep low,data is invalid then return true + if self.options['invalidlevel']=='both' : + return data==0xff or data ==0 + elif self.options['invalidlevel']=='high': + return data==0xff + else : + return data==0 + + + def putdata(self, frame): + data0 = self.io0data + data1 = self.io1data + data2 = self.io2data if self.have_io3 else None + data3 = self.io3data if self.have_io3 else None + + ss,es = self.io0bits[-1][1], self.io0bits[0][2] + if frame: + if self.have_io3: + self.io2bytes.append(Data(ss = ss, es = es, val = data2)) + self.io3bytes.append(Data(ss = ss, es = es, val = data3)) + if self.have_io1: + self.io1bytes.append(Data(ss = ss, es = es, val = data1)) + self.io0bytes.append(Data(ss = ss, es = es, val = data0)) + + bo = self.options['bitorder'] + + if(((self.checkinvalidlevel(data2) or self.checkinvalidlevel(data3)) and self.have_io3) or (self.checkinvalidlevel(data1) and self.have_io1)): + spiMode = self.spiModeSet + elif self.have_io3: + spiMode='qspi' + else : + spiMode='spi' + + #self.putgse(ss,es,[7, ['%s' %spiMode.upper()]]) + #self.put(ss, es, self.out_ann, [3, ['@%02X' % self.io0data]]) + #if self.have_io1: + # self.put(ss, es, self.out_ann, [4, ['@%02X' % self.io1data]]) + #if self.have_io3: + # self.put(ss, es, self.out_ann, [5, ['@%02X' % self.io2data]]) + # self.put(ss, es, self.out_ann, [6, ['@%02X' % self.io3data]]) + + if spiMode == 'qspi' or spiMode == 'dspi': + + qdata = [] + ddata = [] + if self.have_io1 and self.have_io3: + for i in range(4): + self.data = 0 + for j in range(2): + self.data |= self.io3bits[-1 - i * 2 - j][0] + self.data = self.data << 1 + self.data |= self.io2bits[-1 - i * 2 - j][0] + self.data = self.data << 1 + self.data |= self.io1bits[-1 - i * 2 - j][0] + self.data = self.data << 1 + self.data |= self.io0bits[-1 - i * 2 - j][0] + if j < 1: + self.data = self.data << 1 + + qss,qes = self.io0bits[-1 - i * 2][1], self.io0bits[-2 - i * 2][2] + + if not bo == 'msb-first': + dataTemp = (0xF0 & self.data) >> 4|(0x0f & self.data) << 4 + self.data = dataTemp + + qdata.append([self.data, qss, qes]) + self.put(qss, qes, self.out_ann, [1, ['@%02X' % self.data]]) + if self.have_io1: + for i in range(2): + self.data = 0 + for j in range(4): + self.data |= self.io1bits[-1 - i * 4 - j][0] + self.data = self.data << 1 + self.data |= self.io0bits[-1 - i * 4 - j][0] + if j < 3: + self.data = self.data << 1 + dss,des = self.io0bits[-1 - i * 4][1], self.io0bits[-4 - i * 4][2] + if not bo == 'msb-first': + dataTemp = (0xF0 & self.data) >> 4|(0x0f & self.data) << 4 + self.data = dataTemp + + ddata.append([self.data, dss, des]) + self.put(dss, des, self.out_ann, [2, ['@%02X' % self.data]]) + + if self.command == 0 and self.io0data in command: + self.putcmd(ss, es) + #update adress mode + if self.io0data == 0xB7: + self.ads = True + elif self.io0data == 0xE9: + self.ads = False + + if len(command[self.io0data][2]) != 0: + self.command = self.io0data + self.diagram = command[self.command][2] + + elif self.command != 0: + cur_state = self.diagram[self.state_count] + + i, size = 0, 1 + if cur_state.mode == process_mode.DUAL: + size = 2 + elif cur_state.mode == process_mode.QUAD: + size = 4 + + while i < size: + if size == 1: + if cur_state.enum == process_enum.READ_BYTE and self.have_io1: + origin_data = [self.io1data & 0xFF , ss, es] + else: + origin_data = [self.io0data & 0xFF , ss, es] + elif size == 2: + origin_data = ddata[i] + origin_data[0] = origin_data[0] & 0xFF + elif size == 4: + origin_data = qdata[i] + origin_data[0] = origin_data[0] & 0xFF + i = i + 1 + + if cur_state.enum == process_enum.ADDRESS_BY_MODE or \ + cur_state.enum == process_enum.ADDRESS_24BIT or \ + cur_state.enum == process_enum.ADDRESS_32BIT or \ + cur_state.enum == process_enum.DUMMY_BY_MODE or \ + cur_state.enum == process_enum.DUMMY_8BIT: + + if cur_state.enum == process_enum.ADDRESS_BY_MODE: + cur_state.enum = process_enum.ADDRESS_24BIT if self.ads == False else process_enum.ADDRESS_32BIT + elif cur_state.enum == process_enum.DUMMY_BY_MODE: + cur_state.enum = process_enum.DUMMY_32BIT if self.ads == False else process_enum.DUMMY_40BIT + + if self.count == 0: + self.ss = ss + self.bits_data |= origin_data[0] + self.count = self.count + 1 + + if (cur_state.enum == process_enum.ADDRESS_24BIT and self.count == 3) or \ + (cur_state.enum == process_enum.ADDRESS_32BIT and self.count == 4) or \ + (cur_state.enum == process_enum.DUMMY_8BIT and self.count == 1) or \ + (cur_state.enum == process_enum.DUMMY_32BIT and self.count == 4) or \ + (cur_state.enum == process_enum.DUMMY_40BIT and self.count == 5): + + if cur_state.enum == process_enum.ADDRESS_24BIT or \ + cur_state.enum == process_enum.ADDRESS_32BIT: + self.puttext(self.ss , origin_data[2] , cur_state.enum , self.bits_data) + else: + self.putdummy(self.ss, origin_data[2]) + + self.ss = 0 + self.count = 0 + self.bits_data = 0 + self.state_count += 1 + + if self.state_count < len(self.diagram): + cur_state = self.diagram[self.state_count] + else: + self.bits_data = self.bits_data << 8 + + elif cur_state.enum == process_enum.WRITE_BYTE or \ + cur_state.enum == process_enum.READ_BYTE or \ + cur_state.enum == process_enum.READ_BYTE_CONTINUOUS or \ + cur_state.enum == process_enum.CONTINUOUS_READ_MODE_BITS: + + self.puttext(origin_data[1] , origin_data[2] , cur_state.enum , origin_data[0]) + + if cur_state.enum != process_enum.READ_BYTE_CONTINUOUS: + self.state_count += 1 + + if self.state_count < len(self.diagram): + cur_state = self.diagram[self.state_count] + + if self.state_count >= len(self.diagram): + self.command = 0 + self.diagram = [] + self.state_count = 0 + break + + def reset_decoder_state(self): + + self.io0data = 0 + self.io1data = 0 if self.have_io1 else None + self.io2data=0 if self.have_io3 else None + self.io3data=0 if self.have_io3 else None + + self.io0bits=[] + self.io1bits=[] if self.have_io1 else None + self.io2bits=[] if self.have_io3 else None + self.io3bits=[] if self.have_io3 else None + self.bitcount = 0 + + def cs_asserted(self, cs): + active_low = (self.options['cs_polarity'] == 'active-low') + return (cs == 0) if active_low else (cs == 1) + + def handle_bit(self, datapins, clk, cs, frame): + # If this is the first bit of a dataword, save its sample number. + if self.bitcount == 0: + self.ss_block = self.samplenum + self.cs_was_deasserted = \ + not self.cs_asserted(cs) if self.have_cs else False + + ws = 8 + bo = self.options['bitorder'] + + if bo == 'msb-first': + self.io0data |= datapins[3] << (ws - 1 - self.bitcount) + else: + self.io0data |= datapins[3] << self.bitcount + if self.have_io1: + if bo == 'msb-first': + self.io1data |= datapins[2] << (ws - 1 - self.bitcount) + else: + self.io1data |= datapins[2] << self.bitcount + + if self.have_io3: + if bo == 'msb-first': + self.io2data |= datapins[1] << (ws - 1 - self.bitcount) + self.io3data |= datapins[0] << (ws - 1 - self.bitcount) + else: + self.io2data |= datapins[1] << self.bitcount + self.io3data |= datapins[0] << self.bitcount + + # Guesstimate the endsample for this bit (can be overridden below). + es = self.samplenum + if self.bitcount > 0: + es += self.samplenum - self.io0bits[0][1] + + self.io0bits.insert(0, [datapins[3], self.samplenum, es]) + if self.have_io1: + self.io1bits.insert(0, [datapins[2], self.samplenum, es]) + if self.have_io3: + self.io2bits.insert(0, [datapins[1], self.samplenum, es]) + self.io3bits.insert(0, [datapins[0], self.samplenum, es]) + + if self.bitcount > 0: + self.io0bits[1][2] = self.samplenum + if self.have_io1: + self.io1bits[1][2] = self.samplenum + if self.have_io3: + self.io2bits[1][2] = self.samplenum + self.io3bits[1][2] = self.samplenum + + self.bitcount += 1 + + # Continue to receive if not enough bits were received, yet. + if self.bitcount != ws: + return + + self.putdata(frame) + if self.samplerate: + elapsed = 1 / float(self.samplerate) + elapsed *= (self.samplenum - self.ss_block + 1) + bitrate = int(1 / elapsed * ws) + self.put(self.ss_block, self.samplenum, self.out_bitrate, bitrate) + + if self.have_cs and self.cs_was_deasserted: + self.putw([6, ['CS# was deasserted during this data word!']]) + + self.reset_decoder_state() + + def find_clk_edge(self, datapins, clk, cs, first,frame): + + if self.have_cs and (first or (self.matched & (0b1 << self.have_cs))): + # Send all CS# pin value changes. + oldcs = None if first else 1 - cs + self.put(self.samplenum, self.samplenum, self.out_python, + ['CS-CHANGE', oldcs, cs]) + + if frame: + if self.cs_asserted(cs): + self.ss_transfer = self.samplenum + self.io0bytes = [] + self.io1bytes = [] + self.io2bytes = [] + self.io3bytes = [] + + elif self.ss_transfer != -1: + self.put(self.ss_transfer, self.samplenum, self.out_python, + ['TRANSFER', self.io0bytes, self.io1bytes, self.io2bytes,self.io3bytes]) + # Reset decoder state when CS# changes (and the CS# pin is used). + self.command = 0 + self.diagram = [] + self.state_count = 0 + + self.ss = 0 + self.count = 0 + self.bits_data = 0 + + self.reset_decoder_state() + + # We only care about samples if CS# is asserted. + if self.have_cs and not self.cs_asserted(cs): + return + + # Ignore sample if the clock pin hasn't changed. + if first or not (self.matched & (0b1 << 0)): + return + + # Found the correct clock edge, now get the SPI bit(s). + self.handle_bit(datapins, clk, cs,frame) + + def decode(self): + # The CLK & IO0 input is mandatory. Other signals are (individually) + # optional. Tell stacked decoders when we don't have a CS# signal. + if not self.has_channel(0): + raise ChannelError('CLK pin required.') + if not self.has_channel(1): + raise ChannelError('io0 pin required.') + + self.have_io1 = self.has_channel(2) + self.have_io3 = self.has_channel(3) & self.has_channel(4) + self.have_cs = self.has_channel(5) + + if not self.have_cs: + self.put(0, 0, self.out_python, ['CS-CHANGE', None, None]) + + frame = self.options['frame'] == 'yes' + + # We want all CLK changes. We want all CS changes if CS is used. + # Map 'have_cs' from boolean to an integer index. This simplifies + # evaluation in other locations. + # Sample data on rising/falling clock edge (depends on mode). + mode = spi_mode[self.options['cpol'], self.options['cpha']] + if mode == 0 or mode == 3: # Sample on rising clock edge + wait_cond = [{0: 'r'}] + else: # Sample on falling clock edge + wait_cond = [{0: 'f'}] + + if self.have_cs: + self.have_cs = len(wait_cond) + wait_cond.append({5: 'e'}) + + # "Pixel compatibility" with the v2 implementation. Grab and + # process the very first sample before checking for edges. The + # previous implementation did this by seeding old values with + # None, which led to an immediate "change" in comparison. + (clk, d0, d1, d2, d3, cs) = self.wait({}) + d = (d3, d2, d1, d0) + self.find_clk_edge(d, clk, cs, True ,frame) + + while True: + (clk, d0, d1, d2, d3, cs) = self.wait(wait_cond) + d = (d3, d2, d1, d0) + self.find_clk_edge(d, clk, cs, False,frame)# + + From 2d930308334760a530532a0466fe42c7932ff0f1 Mon Sep 17 00:00:00 2001 From: dreamsourcelabTAI Date: Fri, 17 May 2024 14:25:00 +0800 Subject: [PATCH 10/47] fix: mybe stored an error data file of logic data on loop mode --- DSView/pv/data/decode/decoder.cpp | 12 --- DSView/pv/data/logicsnapshot.cpp | 125 +++++++++++++++++++----------- DSView/pv/data/logicsnapshot.h | 2 +- DSView/pv/data/snapshot.h | 6 +- DSView/pv/sigsession.cpp | 7 ++ DSView/pv/sigsession.h | 1 + 6 files changed, 90 insertions(+), 63 deletions(-) diff --git a/DSView/pv/data/decode/decoder.cpp b/DSView/pv/data/decode/decoder.cpp index dfabf09f..2a1bdeb9 100644 --- a/DSView/pv/data/decode/decoder.cpp +++ b/DSView/pv/data/decode/decoder.cpp @@ -135,18 +135,6 @@ std::vector Decoder::binded_probe_list() bool Decoder::have_required_probes() { - dsv_info("decoder:%p", this); - - for (GSList *l = _decoder->channels; l; l = l->next) { - const srd_channel *const pdch = (const srd_channel*)l->data; - dsv_info("base decoder:%p", (void*)pdch); - } - - for (auto it = _probes.begin(); it != _probes.end(); ++it){ - const srd_channel *const pdch = (const srd_channel*)(*it).first; - dsv_info("got decoder:%p", (void*)pdch); - } - for (GSList *l = _decoder->channels; l; l = l->next) { const srd_channel *const pdch = (const srd_channel*)l->data; assert(pdch); diff --git a/DSView/pv/data/logicsnapshot.cpp b/DSView/pv/data/logicsnapshot.cpp index 7db9032b..26ecca28 100644 --- a/DSView/pv/data/logicsnapshot.cpp +++ b/DSView/pv/data/logicsnapshot.cpp @@ -29,9 +29,12 @@ #include "../dsvdef.h" #include "../log.h" #include "../utility/array.h" +#include "../log.h" using namespace std; +int _free_count = 0; + namespace pv { namespace data { @@ -109,6 +112,8 @@ void LogicSnapshot::clear() std::lock_guard lock(_mutex); free_data(); init_all(); + + _free_count = 0; } void LogicSnapshot::first_payload(const sr_datafeed_logic &logic, uint64_t total_sample_count, GSList *channels, bool able_free) @@ -239,15 +244,15 @@ void LogicSnapshot::append_cross_payload(const sr_datafeed_logic &logic) _sample_count = _total_sample_count; } - //dsv_info("_loop_offset:%llu, _total_sample_count:%llu, _ring_sample_count:%llu, cur samples:%llu", - // _loop_offset, _total_sample_count, _ring_sample_count, samples); - if (_is_loop) { - if (_loop_offset >= LeafBlockSamples * Scale){ + if (_loop_offset >= LeafBlockSamples * Scale){ move_first_node_to_last(); _loop_offset -= LeafBlockSamples * Scale; _lst_free_block_index = 0; + + + dsv_info("free a node %d", ++_free_count); } else{ int free_count = _loop_offset / LeafBlockSamples; @@ -262,8 +267,7 @@ void LogicSnapshot::append_cross_payload(const sr_datafeed_logic &logic) // bit align while ((_ch_fraction != 0 || _byte_fraction != 0) && len > 0) { - if (_dest_ptr == NULL) - assert(false); + assert(_dest_ptr); do{ *_dest_ptr++ = *data_src_ptr++; @@ -277,6 +281,7 @@ void LogicSnapshot::append_cross_payload(const sr_datafeed_logic &logic) index1 = (_ring_sample_count / LeafBlockSamples) % RootScale; offset = (_ring_sample_count % LeafBlockSamples) / 8; + //switch to the next channel. _ch_fraction = (_ch_fraction + 1) % _channel_num; lbp = _ch_data[_ch_fraction][index0].lbp[index1]; @@ -292,7 +297,7 @@ void LogicSnapshot::append_cross_payload(const sr_datafeed_logic &logic) _dest_ptr = (uint8_t*)lbp + offset; - // To the last channel. + // The last channel is read end, so the channel index switch to first. if (_ch_fraction == 0){ _ring_sample_count += Scale; @@ -300,7 +305,7 @@ void LogicSnapshot::append_cross_payload(const sr_datafeed_logic &logic) calc_mipmap(_channel_num - 1, index0, index1, LeafBlockSamples, true); } break; - } + } } } @@ -321,8 +326,8 @@ void LogicSnapshot::append_cross_payload(const sr_datafeed_logic &logic) chans_read_addr[i] = (uint64_t*)data_src_ptr + i; } - uint16_t fill_chan = _ch_fraction; - uint16_t last_chan = _ch_fraction; + uint16_t fill_chan_index = 0; + uint16_t last_chan_index = 0; index0 = align_sample_count / LeafBlockSamples / RootScale; index1 = (align_sample_count / LeafBlockSamples) % RootScale; offset = align_sample_count % LeafBlockSamples; @@ -331,14 +336,14 @@ void LogicSnapshot::append_cross_payload(const sr_datafeed_logic &logic) assert(false); } - lbp = _ch_data[fill_chan][index0].lbp[index1]; + lbp = _ch_data[fill_chan_index][index0].lbp[index1]; if (lbp == NULL){ lbp = malloc(LeafBlockSpace); if (lbp == NULL){ dsv_err("LogicSnapshot::append_cross_payload, Malloc memory failed!"); return; } - _ch_data[fill_chan][index0].lbp[index1] = lbp; + _ch_data[fill_chan_index][index0].lbp[index1] = lbp; memset(lbp, 0, LeafBlockSpace); } @@ -351,20 +356,22 @@ void LogicSnapshot::append_cross_payload(const sr_datafeed_logic &logic) len -= 8; filled_sample += Scale; - last_chan++; - if (last_chan == _channel_num){ - last_chan = 0; + last_chan_index++; + if (last_chan_index == _channel_num){ + last_chan_index = 0; } if (filled_sample == LeafBlockSamples) { - calc_mipmap(fill_chan, index0, index1, LeafBlockSamples, true); + calc_mipmap(fill_chan_index, index0, index1, LeafBlockSamples, true); - chans_read_addr[fill_chan] = read_ptr; - fill_chan = (fill_chan + 1) % _channel_num; - - if (fill_chan == 0) + chans_read_addr[fill_chan_index] = read_ptr; //Save the current read position. + fill_chan_index = (fill_chan_index + 1) % _channel_num; //Switch to the next channel index. + + //The last channel's data read ends, update the align sample count. + if (fill_chan_index == 0){ align_sample_count += (filled_sample - old_filled_sample); + } index0 = align_sample_count / LeafBlockSamples / RootScale; index1 = (align_sample_count / LeafBlockSamples) % RootScale; @@ -372,28 +379,29 @@ void LogicSnapshot::append_cross_payload(const sr_datafeed_logic &logic) filled_sample = align_sample_count % LeafBlockSamples; old_filled_sample = filled_sample; - lbp = _ch_data[fill_chan][index0].lbp[index1]; + lbp = _ch_data[fill_chan_index][index0].lbp[index1]; if (lbp == NULL){ lbp = malloc(LeafBlockSpace); if (lbp == NULL){ dsv_err("LogicSnapshot::append_cross_payload, Malloc memory failed!"); return; } - _ch_data[fill_chan][index0].lbp[index1] = lbp; + _ch_data[fill_chan_index][index0].lbp[index1] = lbp; memset(lbp, 0, LeafBlockSpace); } write_ptr = (uint64_t*)lbp + offset / Scale; - read_ptr = chans_read_addr[fill_chan]; + read_ptr = chans_read_addr[fill_chan_index]; } else if (read_ptr >= end_read_ptr) { - calc_mipmap(fill_chan, index0, index1, filled_sample, false); + calc_mipmap(fill_chan_index, index0, index1, filled_sample, false); - fill_chan = (fill_chan + 1) % _channel_num; + fill_chan_index = (fill_chan_index + 1) % _channel_num; - if (fill_chan == 0) + if (fill_chan_index == 0){ align_sample_count += (filled_sample - old_filled_sample); + } index0 = align_sample_count / LeafBlockSamples / RootScale; index1 = (align_sample_count / LeafBlockSamples) % RootScale; @@ -401,19 +409,19 @@ void LogicSnapshot::append_cross_payload(const sr_datafeed_logic &logic) filled_sample = align_sample_count % LeafBlockSamples; old_filled_sample = filled_sample; - lbp = _ch_data[fill_chan][index0].lbp[index1]; + lbp = _ch_data[fill_chan_index][index0].lbp[index1]; if (lbp == NULL){ lbp = malloc(LeafBlockSpace); if (lbp == NULL){ dsv_err("LogicSnapshot::append_cross_payload, Malloc memory failed!"); return; } - _ch_data[fill_chan][index0].lbp[index1] = lbp; + _ch_data[fill_chan_index][index0].lbp[index1] = lbp; memset(lbp, 0, LeafBlockSpace); } write_ptr = (uint64_t*)lbp + offset / Scale; - read_ptr = chans_read_addr[fill_chan]; + read_ptr = chans_read_addr[fill_chan_index]; } } @@ -425,7 +433,7 @@ void LogicSnapshot::append_cross_payload(const sr_datafeed_logic &logic) _ring_sample_count = _total_sample_count; } - _ch_fraction = last_chan; + _ch_fraction = last_chan_index; lbp = _ch_data[_ch_fraction][index0].lbp[index1]; if (lbp == NULL){ @@ -1353,51 +1361,73 @@ bool LogicSnapshot::has_data(int sig_index) } int LogicSnapshot::get_block_num() -{ - int block = ceil((_ring_sample_count+_loop_offset) * 1.0 / LeafBlockSamples) - - floor(_loop_offset * 1.0 / LeafBlockSamples); - return block; +{ + auto align_sample_count = get_ring_sample_count(); + int block = align_sample_count / LeafBlockSamples; + + if (align_sample_count % LeafBlockSamples != 0){ + block++; + } + + if (_loop_offset > 0){ + uint64_t diff1 = align_sample_count % LeafBlockSamples; + uint64_t diff2 = _loop_offset % LeafBlockSamples; + + if ((diff1 == 0 && diff2 != 0) || + (diff1 != 0 && diff1 + diff2 > LeafBlockSamples)){ + block++; + } + } + + return block; } uint64_t LogicSnapshot::get_block_size(int block_index) { int block_num = get_block_num(); - uint64_t samples = 0; - assert(block_index < block_num); + auto align_sample_count = get_ring_sample_count(); + if (_loop_offset > 0) { if (block_index > 0 && block_index < block_num - 1) { return LeafBlockSamples / 8; } else if (block_index == 0){ - samples = min(_ring_sample_count + (_loop_offset % (uint64_t)LeafBlockSamples), - (uint64_t)LeafBlockSamples) - (_loop_offset % (uint64_t)LeafBlockSamples); - return samples/8; + if (align_sample_count + _loop_offset <= LeafBlockSamples){ + return align_sample_count / 8; + } + else{ + return (LeafBlockSamples - _loop_offset % LeafBlockSamples) / 8; + } } else{ - samples = (_ring_sample_count + _loop_offset) - (_ring_sample_count + _loop_offset - 1) - / LeafBlockSamples * LeafBlockSamples; - return samples/8; + uint64_t sum_sample_count = align_sample_count + _loop_offset; + + if (sum_sample_count % LeafBlockSamples == 0) + return LeafBlockSamples / 8; + else + return (sum_sample_count % LeafBlockSamples) / 8; } } else{ if (block_index < block_num - 1) { return LeafBlockSamples / 8; } - else { - if (_ring_sample_count % LeafBlockSamples == 0) + else { // The data length of last block. + if (align_sample_count % LeafBlockSamples == 0) return LeafBlockSamples / 8; else - return (_ring_sample_count % LeafBlockSamples) / 8; + return (align_sample_count % LeafBlockSamples) / 8; } } } uint8_t *LogicSnapshot::get_block_buf(int block_index, int sig_index, bool &sample) { - assert(block_index < get_block_num()); + int block_num = get_block_num(); + assert(block_index < block_num); int order = get_ch_order(sig_index); if (order == -1) { @@ -1412,8 +1442,9 @@ uint8_t *LogicSnapshot::get_block_buf(int block_index, int sig_index, bool &samp uint8_t pos = block_index % RootScale; uint8_t *lbp = (uint8_t*)_ch_data[order][index].lbp[pos]; - if (lbp == NULL) + if (lbp == NULL){ sample = (_ch_data[order][index].first & 1ULL << pos) != 0; + } if (lbp != NULL && _loop_offset > 0 && block_index0 == 0) { diff --git a/DSView/pv/data/logicsnapshot.h b/DSView/pv/data/logicsnapshot.h index 32b7f635..96c79a85 100644 --- a/DSView/pv/data/logicsnapshot.h +++ b/DSView/pv/data/logicsnapshot.h @@ -249,7 +249,7 @@ class LogicSnapshot : public Snapshot uint64_t _last_sample[CHANNEL_MAX_COUNT]; uint64_t _last_calc_count[CHANNEL_MAX_COUNT]; bool _is_loop; - uint64_t _loop_offset; + volatile uint64_t _loop_offset; bool _able_free; std::vector _free_block_list; struct BlockIndex _cur_ref_block_indexs[CHANNEL_MAX_COUNT]; diff --git a/DSView/pv/data/snapshot.h b/DSView/pv/data/snapshot.h index fa7bce4b..1f24e470 100644 --- a/DSView/pv/data/snapshot.h +++ b/DSView/pv/data/snapshot.h @@ -98,9 +98,9 @@ class Snapshot uint64_t _capacity; unsigned int _channel_num; - uint64_t _sample_count; - uint64_t _total_sample_count; - uint64_t _ring_sample_count; + volatile uint64_t _sample_count; + volatile uint64_t _total_sample_count; + volatile uint64_t _ring_sample_count; int _unit_size; uint8_t _unit_bytes; uint16_t _unit_pitch; diff --git a/DSView/pv/sigsession.cpp b/DSView/pv/sigsession.cpp index d8236f53..eb654c1a 100644 --- a/DSView/pv/sigsession.cpp +++ b/DSView/pv/sigsession.cpp @@ -103,6 +103,7 @@ namespace pv _decoder_pannel = NULL; _is_triged = false; _dso_status_valid = false; + _is_task_end = false; _data_list.push_back(new SessionData()); _data_list.push_back(new SessionData()); @@ -708,6 +709,8 @@ namespace pv capture_init(); + _is_task_end = false; + if (_device_agent.start() == false){ dsv_err("Start collect error!"); return false; @@ -1415,16 +1418,19 @@ namespace pv case SR_DF_LOGIC: assert(packet->payload); + assert(!_is_task_end); feed_in_logic(*(const sr_datafeed_logic *)packet->payload); break; case SR_DF_DSO: assert(packet->payload); + assert(!_is_task_end); feed_in_dso(*(const sr_datafeed_dso *)packet->payload); break; case SR_DF_ANALOG: assert(packet->payload); + assert(!_is_task_end); feed_in_analog(*(const sr_datafeed_analog *)packet->payload); break; @@ -1444,6 +1450,7 @@ namespace pv _capture_data->get_logic()->capture_ended(); _capture_data->get_dso()->capture_ended(); _capture_data->get_analog()->capture_ended(); + _is_task_end = true; if (packet->status != SR_PKT_OK) { diff --git a/DSView/pv/sigsession.h b/DSView/pv/sigsession.h index adef4f69..9a2344cf 100644 --- a/DSView/pv/sigsession.h +++ b/DSView/pv/sigsession.h @@ -608,6 +608,7 @@ class SigSession: bool _is_action; uint64_t _dso_packet_count; + bool _is_task_end; ISessionCallback *_callback; From 3358e899486405f0cb368fdf01ca94c57e761498 Mon Sep 17 00:00:00 2001 From: dreamsourcelabTAI Date: Fri, 17 May 2024 15:38:57 +0800 Subject: [PATCH 11/47] Do not add decode task when the collect task is not end --- DSView/pv/data/decoderstack.cpp | 5 +++++ DSView/pv/sigsession.cpp | 13 ++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/DSView/pv/data/decoderstack.cpp b/DSView/pv/data/decoderstack.cpp index a2bf1658..1311363b 100644 --- a/DSView/pv/data/decoderstack.cpp +++ b/DSView/pv/data/decoderstack.cpp @@ -560,6 +560,11 @@ void DecoderStack::decode_data(const uint64_t decode_start, const uint64_t decod uint64_t align_sample_count = _snapshot->get_ring_sample_count(); + if (align_sample_count == 0){ + dsv_info("Have no data to decode."); + return; + } + if (end_index >= align_sample_count){ end_index = align_sample_count - 1; dsv_info("Reset the decode end sample, new:%llu, old:%llu", diff --git a/DSView/pv/sigsession.cpp b/DSView/pv/sigsession.cpp index eb654c1a..02ef29af 100644 --- a/DSView/pv/sigsession.cpp +++ b/DSView/pv/sigsession.cpp @@ -1688,7 +1688,15 @@ namespace pv { auto trace = get_decoder_trace(index); - if (trace && trace->create_popup(false)) + if (trace == NULL){ + return; + } + + if (!trace->create_popup(false)){ + return; + } + + if (have_view_data() && !is_working()) { remove_decode_task(trace); // remove old task trace->decoder()->clear(); @@ -1868,8 +1876,7 @@ namespace pv std::lock_guard lock(_decode_task_mutex); _decode_tasks.push_back(trace); - if (!_is_decoding) - { + if (!_is_decoding){ if (_decode_thread.joinable()) _decode_thread.join(); From 4c66fc22911ab3255a54e567e96c6b41e7ea87d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ladislav=20L=C3=A1ska?= Date: Sun, 19 May 2024 10:08:12 +0800 Subject: [PATCH 12/47] Fixed syntax error (extra closing bracket) in sdcard_spi decoder. This error prevents the module from loading. Fixes issue #768. --- libsigrokdecode4DSL/decoders/sdcard_spi/pd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsigrokdecode4DSL/decoders/sdcard_spi/pd.py b/libsigrokdecode4DSL/decoders/sdcard_spi/pd.py index 72702677..1a363812 100644 --- a/libsigrokdecode4DSL/decoders/sdcard_spi/pd.py +++ b/libsigrokdecode4DSL/decoders/sdcard_spi/pd.py @@ -231,7 +231,7 @@ def handle_cmd17(self): def handle_cmd24(self): # CMD24: WRITE_BLOCK - self.putc(Ann.CMD24, 'Write a block to address {$}', self.arg)) + self.putc(Ann.CMD24, 'Write a block to address {$}', self.arg) self.is_cmd24 = True self.state = 'GET RESPONSE R1' From 72517899168f4db5a60533a55f1130340979af11 Mon Sep 17 00:00:00 2001 From: dreamsourcelabTAI Date: Wed, 22 May 2024 16:27:49 +0800 Subject: [PATCH 13/47] fix: got an error data to decode on loop mode, the data offset is error --- DSView/pv/data/decoderstack.cpp | 59 ++++++++++----------- DSView/pv/data/logicsnapshot.cpp | 91 +++++++++++++++++++++++--------- DSView/pv/data/logicsnapshot.h | 3 ++ 3 files changed, 99 insertions(+), 54 deletions(-) diff --git a/DSView/pv/data/decoderstack.cpp b/DSView/pv/data/decoderstack.cpp index 1311363b..cb6b0b9a 100644 --- a/DSView/pv/data/decoderstack.cpp +++ b/DSView/pv/data/decoderstack.cpp @@ -521,12 +521,10 @@ void DecoderStack::decode_data(const uint64_t decode_start, const uint64_t decod assert(logic_di); - uint64_t entry_cnt = 0; uint64_t i = decode_start; char *error = NULL; bool bError = false; bool bEndTime = false; - //struct srd_push_param push_param; if( i >= decode_end){ dsv_info("decode data index have been to end"); @@ -534,12 +532,11 @@ void DecoderStack::decode_data(const uint64_t decode_start, const uint64_t decod std::vector chunk; std::vector chunk_const; - bool bCheckEnd = false; uint64_t end_index = decode_end; + uint64_t decoded_sample_count = 0; _progress = 0; - uint64_t sended_len = 0; _is_decoding = true; void* lbp_array[35]; @@ -547,8 +544,8 @@ void DecoderStack::decode_data(const uint64_t decode_start, const uint64_t decod for (int j =0 ; j < logic_di->dec_num_channels; j++){ lbp_array[j] = NULL; } - - while(i < end_index && !_no_memory && !status->_bStop) + + while(i <= end_index && !_no_memory && !status->_bStop) { chunk.clear(); chunk_const.clear(); @@ -567,7 +564,7 @@ void DecoderStack::decode_data(const uint64_t decode_start, const uint64_t decod if (end_index >= align_sample_count){ end_index = align_sample_count - 1; - dsv_info("Reset the decode end sample, new:%llu, old:%llu", + dsv_info("Reset the decode end sample index, new:%llu, old:%llu", (u64_t)end_index, (u64_t)decode_end); } @@ -580,14 +577,10 @@ void DecoderStack::decode_data(const uint64_t decode_start, const uint64_t decod else if (i >= _snapshot->get_ring_sample_count()) { // Wait the data is ready. - std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); continue; } - - if (_is_capture_end && i == _snapshot->get_ring_sample_count()){ - break; - } - + uint64_t chunk_end = end_index; for (int j =0 ; j < logic_di->dec_num_channels; j++) { @@ -601,8 +594,9 @@ void DecoderStack::decode_data(const uint64_t decode_start, const uint64_t decod else { if (_snapshot->has_data(sig_index)) { const uint8_t *data_ptr = _snapshot->get_samples(i, chunk_end, sig_index, &lbp); + bool flag = _snapshot->get_sample(i, sig_index); chunk.push_back(data_ptr); - chunk_const.push_back(_snapshot->get_sample(i, sig_index)); + chunk_const.push_back(flag); if (_snapshot->is_able_free() == false) { @@ -621,12 +615,18 @@ void DecoderStack::decode_data(const uint64_t decode_start, const uint64_t decod } } - if (chunk_end > end_index) - chunk_end = end_index; + if (i > end_index){ + bEndTime = true; + dsv_info("Decoding data to end."); + break; + } + + if (chunk_end >= end_index) + chunk_end = end_index + 1; if (chunk_end - i > MaxChunkSize) chunk_end = i + MaxChunkSize; - bEndTime = (chunk_end == end_index); + bEndTime = (chunk_end > end_index); if (srd_session_send( session, @@ -639,7 +639,7 @@ void DecoderStack::decode_data(const uint64_t decode_start, const uint64_t decod if (error){ _error_message = QString::fromLocal8Bit(error); - dsv_err("Failed to call srd_session_send:%s", error); + dsv_err("ERROR: Failed to call srd_session_send:%s", error); g_free(error); error = NULL; } @@ -648,11 +648,10 @@ void DecoderStack::decode_data(const uint64_t decode_start, const uint64_t decod break; } - sended_len += chunk_end - i; - _progress = (int)(sended_len * 100 / end_index); - - i = chunk_end; - + decoded_sample_count += chunk_end - i; + _progress = (int)(decoded_sample_count * 100 / end_index); + i = chunk_end; + //use mutex { std::lock_guard lock(_output_mutex); @@ -663,8 +662,6 @@ void DecoderStack::decode_data(const uint64_t decode_start, const uint64_t decod last_cnt = i; new_decode_data(); } - - entry_cnt++; } _progress = 100; @@ -681,14 +678,16 @@ void DecoderStack::decode_data(const uint64_t decode_start, const uint64_t decod dsv_err("Failed to call srd_session_end:%s", error); } } - - dsv_info("%s%llu", "send to decoder times: ", (u64_t)entry_cnt); - if (error != NULL) + if (error != NULL){ g_free(error); + } - if (!_session->is_closed()) + if (!_session->is_closed()){ decode_done(); + } + + dsv_info("Decoded sample count:%llu", decoded_sample_count); } void DecoderStack::execute_decode_stack() @@ -738,7 +737,7 @@ void DecoderStack::execute_decode_stack() decode_end = max(dec->decode_end(), decode_end); } - dsv_info("decoder start sample:%llu, end sample:%llu, count:%llu", + dsv_info("Decode start sample index:%llu, end sample index:%llu, count:%llu", (u64_t)decode_start, (u64_t)decode_end, (u64_t)(decode_end - decode_start + 1)); // Start the session diff --git a/DSView/pv/data/logicsnapshot.cpp b/DSView/pv/data/logicsnapshot.cpp index 26ecca28..e61ba7a1 100644 --- a/DSView/pv/data/logicsnapshot.cpp +++ b/DSView/pv/data/logicsnapshot.cpp @@ -600,45 +600,70 @@ void LogicSnapshot::calc_mipmap(unsigned int order, uint8_t index0, uint8_t inde } const uint8_t *LogicSnapshot::get_samples(uint64_t start_sample, uint64_t &end_sample, int sig_index, void **lbp) -{ +{ std::lock_guard lock(_mutex); uint64_t sample_count = _ring_sample_count; - assert(start_sample < sample_count); - if (end_sample >= sample_count) - end_sample = sample_count - 1; + uint64_t logic_sample_index = start_sample + _loop_offset; - assert(end_sample <= sample_count); - assert(start_sample <= end_sample); + int order = get_ch_order(sig_index); + // uint64_t index0 = logic_sample_index >> (LeafBlockPower + RootScalePower); + // uint64_t index1 = (logic_sample_index & RootMask) >> LeafBlockPower; + // uint64_t offset = (start_sample & LeafMask) / 8; - start_sample += _loop_offset; - _ring_sample_count += _loop_offset; + uint64_t index0 = logic_sample_index / LeafBlockSamples / RootScale; + uint64_t index1 = (logic_sample_index / LeafBlockSamples) % RootScale; + uint64_t offset = (start_sample % LeafBlockSamples) / 8; - int order = get_ch_order(sig_index); - uint64_t index0 = start_sample >> (LeafBlockPower + RootScalePower); - uint64_t index1 = (start_sample & RootMask) >> LeafBlockPower; - uint64_t offset = (start_sample & LeafMask) / 8; + uint8_t *block_buffer = (uint8_t*)_ch_data[order][index0].lbp[index1]; + + int block_num = get_block_num_unlock(); + + if (_is_loop && _loop_offset > 0) + { + uint64_t block0_sample = get_block_size_unlock(0) * 8; + bool flag = false; + + if (start_sample < block0_sample){ + block_buffer = get_block_buf_unlock(0, sig_index, flag); + end_sample = block0_sample; + offset = start_sample / 8; + } + else{ + uint64_t last_block_sample = get_block_size_unlock(block_num - 1) * 8; + offset = ((start_sample - block0_sample) % LeafBlockSamples) / 8; - end_sample = (index0 << (LeafBlockPower + RootScalePower)) + + if (start_sample >= sample_count - last_block_sample){ + end_sample = sample_count; + } + else{ + int mid_block_num = (start_sample - block0_sample) / LeafBlockSamples + 1; + end_sample = mid_block_num * LeafBlockSamples + block0_sample; + } + } + } + else{ + end_sample = (index0 << (LeafBlockPower + RootScalePower)) + (index1 << LeafBlockPower) + ~(~0ULL << LeafBlockPower); - end_sample = min(end_sample + 1, sample_count); - - _ring_sample_count -= _loop_offset; + end_sample = min(end_sample + 1, sample_count); + } - if (order == -1 || _ch_data[order][index0].lbp[index1] == NULL) + if (order == -1 || block_buffer == NULL){ return NULL; + } else{ - if (lbp != NULL) + if (lbp != NULL){ *lbp = _ch_data[order][index0].lbp[index1]; + } _cur_ref_block_indexs[order].root_index = index0; _cur_ref_block_indexs[order].lbp_index = index1; - return (uint8_t*)_ch_data[order][index0].lbp[index1] + offset; + return block_buffer + offset; } } @@ -1361,8 +1386,14 @@ bool LogicSnapshot::has_data(int sig_index) } int LogicSnapshot::get_block_num() +{ + std::lock_guard lock(_mutex); + return get_block_num_unlock(); +} + +int LogicSnapshot::get_block_num_unlock() { - auto align_sample_count = get_ring_sample_count(); + auto align_sample_count = _ring_sample_count; int block = align_sample_count / LeafBlockSamples; if (align_sample_count % LeafBlockSamples != 0){ @@ -1375,7 +1406,7 @@ int LogicSnapshot::get_block_num() if ((diff1 == 0 && diff2 != 0) || (diff1 != 0 && diff1 + diff2 > LeafBlockSamples)){ - block++; + block++; } } @@ -1384,10 +1415,16 @@ int LogicSnapshot::get_block_num() uint64_t LogicSnapshot::get_block_size(int block_index) { - int block_num = get_block_num(); + std::lock_guard lock(_mutex); + return get_block_size_unlock(block_index); +} + +uint64_t LogicSnapshot::get_block_size_unlock(int block_index) +{ + int block_num = get_block_num_unlock(); assert(block_index < block_num); - auto align_sample_count = get_ring_sample_count(); + auto align_sample_count = _ring_sample_count; if (_loop_offset > 0) { @@ -1426,7 +1463,13 @@ uint64_t LogicSnapshot::get_block_size(int block_index) uint8_t *LogicSnapshot::get_block_buf(int block_index, int sig_index, bool &sample) { - int block_num = get_block_num(); + std::lock_guard lock(_mutex); + return get_block_buf_unlock(block_index, sig_index, sample); +} + +uint8_t *LogicSnapshot::get_block_buf_unlock(int block_index, int sig_index, bool &sample) +{ + int block_num = get_block_num_unlock(); assert(block_index < block_num); int order = get_ch_order(sig_index); diff --git a/DSView/pv/data/logicsnapshot.h b/DSView/pv/data/logicsnapshot.h index 96c79a85..49b5d762 100644 --- a/DSView/pv/data/logicsnapshot.h +++ b/DSView/pv/data/logicsnapshot.h @@ -124,8 +124,11 @@ class LogicSnapshot : public Snapshot bool has_data(int sig_index); int get_block_num(); + int get_block_num_unlock(); uint64_t get_block_size(int block_index); + uint64_t get_block_size_unlock(int block_index); uint8_t *get_block_buf(int block_index, int sig_index, bool &sample); + uint8_t *get_block_buf_unlock(int block_index, int sig_index, bool &sample); bool pattern_search(int64_t start, int64_t end, int64_t& index, std::map &pattern, bool isNext); From 2018baf0e1add4f9971dd02271ee8e6773cebfac Mon Sep 17 00:00:00 2001 From: Lutz Freitag Date: Wed, 22 May 2024 21:29:54 +0200 Subject: [PATCH 14/47] added missing includes and a define to compile it for recent machines I use arch btw --- CMakeLists.txt | 2 ++ libsigrok4DSL/input/in_wav.c | 1 + libsigrok4DSL/strutil.c | 1 + 3 files changed, 4 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index d12bd0db..7b8cf57d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -668,6 +668,8 @@ install(FILES DSView/icons/logo.svg DESTINATION share/pixmaps RENAME dsview.svg) if(CMAKE_SYSTEM_NAME MATCHES "Linux") install(FILES DSView/DSView.desktop DESTINATION /usr/share/applications RENAME dsview.desktop) + add_compile_definitions(_DEFAULT_SOURCE) + if(IS_DIRECTORY /usr/lib/udev/rules.d) install(FILES DSView/DreamSourceLab.rules DESTINATION /usr/lib/udev/rules.d RENAME 60-dreamsourcelab.rules) elseif(IS_DIRECTORY /lib/udev/rules.d) diff --git a/libsigrok4DSL/input/in_wav.c b/libsigrok4DSL/input/in_wav.c index de16e513..7a130496 100644 --- a/libsigrok4DSL/input/in_wav.c +++ b/libsigrok4DSL/input/in_wav.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "../log.h" #include diff --git a/libsigrok4DSL/strutil.c b/libsigrok4DSL/strutil.c index 52cb01d8..6c02c6df 100644 --- a/libsigrok4DSL/strutil.c +++ b/libsigrok4DSL/strutil.c @@ -21,6 +21,7 @@ #include "libsigrok-internal.h" #include #include +#include #include #include "log.h" From bce4a8e6a4acb442f29501784774bb20aa36aa22 Mon Sep 17 00:00:00 2001 From: dreamsourcelabTAI Date: Thu, 23 May 2024 15:58:26 +0800 Subject: [PATCH 15/47] fix: Save the logic data with a range, but the data is error --- DSView/pv/data/logicsnapshot.cpp | 32 +++++-- DSView/pv/data/logicsnapshot.h | 12 +-- DSView/pv/storesession.cpp | 147 ++++++++++++++++--------------- 3 files changed, 109 insertions(+), 82 deletions(-) diff --git a/DSView/pv/data/logicsnapshot.cpp b/DSView/pv/data/logicsnapshot.cpp index e61ba7a1..b860bc1f 100644 --- a/DSView/pv/data/logicsnapshot.cpp +++ b/DSView/pv/data/logicsnapshot.cpp @@ -1581,13 +1581,35 @@ void LogicSnapshot::free_head_blocks(int count) _lst_free_block_index = count; } -int LogicSnapshot::get_block_with_sample(uint64_t index, uint64_t *out_offset) +int LogicSnapshot::get_block_index_with_sample(uint64_t sample_index, uint64_t *out_offset) { - assert(out_offset); + std::lock_guard lock(_mutex); - int block = index / LeafBlockSamples; - *out_offset = index % LeafBlockSamples; - return block; + int block_index = 0; + uint64_t offset = 0; + + if (_is_loop && _loop_offset > 0){ + uint64_t block_sample0 = get_block_size_unlock(0) * 8; + + if (sample_index < block_sample0){ + block_index = 0; + offset = sample_index; + } + else{ + block_index = (sample_index - block_sample0) / LeafBlockSamples + 1; + offset = (sample_index - block_sample0) % LeafBlockSamples; + } + } + else{ + block_index = sample_index / LeafBlockSamples; + offset = sample_index % LeafBlockSamples; + } + + if (out_offset != NULL){ + *out_offset = offset; + } + + return block_index; } } // namespace data diff --git a/DSView/pv/data/logicsnapshot.h b/DSView/pv/data/logicsnapshot.h index 49b5d762..e64f63d1 100644 --- a/DSView/pv/data/logicsnapshot.h +++ b/DSView/pv/data/logicsnapshot.h @@ -124,12 +124,9 @@ class LogicSnapshot : public Snapshot bool has_data(int sig_index); int get_block_num(); - int get_block_num_unlock(); + uint8_t *get_block_buf(int block_index, int sig_index, bool &sample); uint64_t get_block_size(int block_index); - uint64_t get_block_size_unlock(int block_index); - uint8_t *get_block_buf(int block_index, int sig_index, bool &sample); - uint8_t *get_block_buf_unlock(int block_index, int sig_index, bool &sample); - + bool pattern_search(int64_t start, int64_t end, int64_t& index, std::map &pattern, bool isNext); @@ -153,9 +150,12 @@ class LogicSnapshot : public Snapshot return _loop_offset; } - static int get_block_with_sample(uint64_t index, uint64_t *out_offset); + int get_block_index_with_sample(uint64_t sample_index, uint64_t *out_offset); private: + int get_block_num_unlock(); + uint64_t get_block_size_unlock(int block_index); + uint8_t *get_block_buf_unlock(int block_index, int sig_index, bool &sample); bool get_sample_unlock(uint64_t index, int sig_index); bool get_sample_self(uint64_t index, int sig_index); diff --git a/DSView/pv/storesession.cpp b/DSView/pv/storesession.cpp index 24887a9b..6cd9073c 100644 --- a/DSView/pv/storesession.cpp +++ b/DSView/pv/storesession.cpp @@ -221,9 +221,6 @@ void StoreSession::save_logic(pv::data::LogicSnapshot *logic_snapshot) { char chunk_name[20] = {0}; uint16_t to_save_probes = 0; - bool sample; - int ret = SR_ERR; - int num; for(auto s : _session->get_signals()) { if (s->enabled() && logic_snapshot->has_data(s->get_index())) @@ -231,7 +228,7 @@ void StoreSession::save_logic(pv::data::LogicSnapshot *logic_snapshot) } _unit_count = logic_snapshot->get_ring_sample_count() / 8 * to_save_probes; - num = logic_snapshot->get_block_num(); + int block_count = logic_snapshot->get_block_num(); uint64_t start_index = _start_index; uint64_t end_index = _end_index; @@ -252,7 +249,7 @@ void StoreSession::save_logic(pv::data::LogicSnapshot *logic_snapshot) if (start_index > 0){ start_index -= start_index % 64; - start_block = LogicSnapshot::get_block_with_sample(start_index, &start_offset); + start_block = logic_snapshot->get_block_index_with_sample(start_index, &start_offset); } if (end_index > 0){ if (end_index % 64 != 0){ @@ -263,7 +260,7 @@ void StoreSession::save_logic(pv::data::LogicSnapshot *logic_snapshot) end_index = 0; } else{ - end_block = LogicSnapshot::get_block_with_sample(end_index, &end_offset); + end_block = logic_snapshot->get_block_index_with_sample(end_index, &end_offset); } } @@ -278,81 +275,93 @@ void StoreSession::save_logic(pv::data::LogicSnapshot *logic_snapshot) } for(auto s : _session->get_signals()) - { + { int ch_type = s->get_type(); - if (ch_type == SR_CHANNEL_LOGIC) { - int ch_index = s->get_index(); - if (!s->enabled() || !logic_snapshot->has_data(ch_index)) - continue; + if (ch_type != SR_CHANNEL_LOGIC){ + continue; + } - for (int i = 0; !_canceled && i < num; i++) - { - if (i < start_block){ - continue; - } - if (i > end_block && end_block > 0){ - break; - } + int ch_index = s->get_index(); + if (!s->enabled() || !logic_snapshot->has_data(ch_index)){ + continue; + } - uint8_t *buf = logic_snapshot->get_block_buf(i, ch_index, sample); - uint64_t size = logic_snapshot->get_block_size(i); - bool need_malloc = (buf == NULL); + for (int i = 0; !_canceled && i < block_count; i++) + { + if (i < start_block){ + continue; + } + if (i > end_block && end_block > 0){ + break; + } - if (i == end_block && end_offset / 8 < size && end_offset > 0){ - size = end_offset / 8; - } + bool flag = false; + uint8_t *block_buf = logic_snapshot->get_block_buf(i, ch_index, flag); + uint64_t block_size = logic_snapshot->get_block_size(i); + bool need_malloc = (block_buf == NULL); - if (i == start_block && start_offset > 0){ - if (buf != NULL){ - buf += start_offset / 8; - } - size -= start_offset / 8; + if (i == end_block && end_offset / 8 < block_size && end_offset > 0){ + block_size = end_offset / 8; + } + + if (i == start_block && start_offset > 0){ + if (block_buf != NULL){ + block_buf += start_offset / 8; } + block_size -= start_offset / 8; + } - if (need_malloc) { - buf = (uint8_t *)malloc(size); - if (buf == NULL) { - _has_error = true; - _error = L_S(STR_PAGE_DLG, S_ID(IDS_MSG_STORESESS_SAVEPROC_ERROR1), - "Failed to create zip file. Malloc error."); - } else { - memset(buf, sample ? 0xff : 0x0, size); - } + if (need_malloc) { + block_buf = (uint8_t *)malloc(block_size); + if (block_buf == NULL) { + _has_error = true; + _error = L_S(STR_PAGE_DLG, S_ID(IDS_MSG_STORESESS_SAVEPROC_ERROR1), + "Failed to create zip file. Malloc error."); } - - MakeChunkName(chunk_name, i - start_block, ch_index, ch_type, HEADER_FORMAT_VERSION); - ret = m_zipDoc.AddFromBuffer(chunk_name, (const char*)buf, size) ? SR_OK : -1; + else { + memset(block_buf, flag ? 0xff : 0x0, block_size); + } + } + + MakeChunkName(chunk_name, i - start_block, ch_index, ch_type, HEADER_FORMAT_VERSION); + int ret = m_zipDoc.AddFromBuffer(chunk_name, (const char*)block_buf, block_size) ? SR_OK : -1; - if (ret != SR_OK) { - if (!_has_error) { - _has_error = true; - _error = L_S(STR_PAGE_DLG, S_ID(IDS_MSG_STORESESS_SAVEPROC_ERROR2), - "Failed to create zip file. Please check write permission of this path."); - } - progress_updated(); - if (_has_error) - QFile::remove(_file_name); - return; + if (ret != SR_OK) { + if (!_has_error) { + _has_error = true; + _error = L_S(STR_PAGE_DLG, S_ID(IDS_MSG_STORESESS_SAVEPROC_ERROR2), + "Failed to create zip file. Please check write permission of this path."); } - _units_stored += size; + progress_updated(); - if (_units_stored > _unit_count - && start_index == 0 - && end_index == 0){ - dsv_err("Read block data error!"); - assert(false); + if (_has_error){ + QFile::remove(_file_name); + } + if (need_malloc){ + free(block_buf); } - if (need_malloc) - free(buf); - progress_updated(); + return; } - } + _units_stored += block_size; + + if (_units_stored > _unit_count + && start_index == 0 + && end_index == 0){ + dsv_err("Read block data error!"); + assert(false); + } + + if (need_malloc){ + free(block_buf); + } + progress_updated(); + } } progress_updated(); - if (_canceled || num == 0){ + if (_canceled || block_count == 0){ QFile::remove(_file_name); } else { @@ -580,8 +589,6 @@ bool StoreSession::meta_gen(data::Snapshot *snapshot, std::string &str) uint64_t start_index = _start_index; uint64_t end_index = _end_index; - uint64_t start_offset = 0; - uint64_t end_offset = 0; int start_block = 0; int end_block = 0; @@ -589,10 +596,10 @@ bool StoreSession::meta_gen(data::Snapshot *snapshot, std::string &str) end_index = 0; } if (start_index > 0){ - start_block = LogicSnapshot::get_block_with_sample(start_index, &start_offset); + start_block = logic_snapshot->get_block_index_with_sample(start_index, NULL); } if (end_index > 0){ - end_block = LogicSnapshot::get_block_with_sample(end_index, &end_offset); + end_block = logic_snapshot->get_block_index_with_sample(end_index, NULL); } if (start_index > 0 && end_index > 0){ @@ -986,8 +993,6 @@ void StoreSession::export_exec(data::Snapshot *snapshot) uint64_t start_index = _start_index; uint64_t end_index = _end_index; - uint64_t start_offset = 0; - uint64_t end_offset = 0; int start_block = 0; int end_block = 0; @@ -1002,10 +1007,10 @@ void StoreSession::export_exec(data::Snapshot *snapshot) } if (start_index > 0){ - start_block = LogicSnapshot::get_block_with_sample(start_index, &start_offset); + start_block = logic_snapshot->get_block_index_with_sample(start_index, NULL); } if (end_index > 0){ - end_block = LogicSnapshot::get_block_with_sample(end_index, &end_offset); + end_block = logic_snapshot->get_block_index_with_sample(end_index, NULL); } if (start_index > 0 && end_index > 0){ From 169617e7b0d837a8fb0c73d491bcd55084a2f765 Mon Sep 17 00:00:00 2001 From: dreamsourcelabTAI Date: Fri, 24 May 2024 14:55:50 +0800 Subject: [PATCH 16/47] fix: The layout of calibration dialog displayed error when change vdiv by mouse whell event --- DSView/pv/dialogs/calibration.cpp | 250 ++++++++++++++++-------------- DSView/pv/dialogs/calibration.h | 22 ++- 2 files changed, 155 insertions(+), 117 deletions(-) diff --git a/DSView/pv/dialogs/calibration.cpp b/DSView/pv/dialogs/calibration.cpp index 14949b9d..9ddd066c 100644 --- a/DSView/pv/dialogs/calibration.cpp +++ b/DSView/pv/dialogs/calibration.cpp @@ -59,7 +59,7 @@ Calibration::Calibration(QWidget *parent) : _reset_btn = NULL; _exit_btn = NULL; _flayout = NULL; - + _is_setting = false; #ifdef Q_OS_DARWIN Qt::WindowFlags flags = windowFlags(); @@ -98,6 +98,8 @@ Calibration::Calibration(QWidget *parent) : layout()->addLayout(glayout); + BuildUI(); + connect(_save_btn, SIGNAL(clicked()), this, SLOT(on_save())); connect(_abort_btn, SIGNAL(clicked()), this, SLOT(on_abort())); connect(_reset_btn, SIGNAL(clicked()), this, SLOT(on_reset())); @@ -127,33 +129,82 @@ void Calibration::retranslateUi() setTitle(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_MANUAL_CALIBRATION), "Manual Calibration")); } -void Calibration::update_device_info() -{ +void Calibration::BuildUI() +{ if (_device_agent->have_instance() == false){ assert(false); } + assert(_params.empty()); - for(std::list::const_iterator i = _slider_list.begin(); - i != _slider_list.end(); i++) { - (*i)->setParent(NULL); - _flayout->removeWidget((*i)); - delete (*i); - } + _flayout->setSpacing(15); + + for (const GSList *l = _device_agent->get_channels(); l; l = l->next) { + sr_channel *const probe = (sr_channel*)l->data; + assert(probe); + + QSlider *gain_slider = new QSlider(Qt::Horizontal, this); + QLabel *gain_label = new QLabel("gain", this); + gain_label->setAlignment(Qt::AlignVCenter); + _flayout->addRow(gain_label, gain_slider); + + QSlider *off_slider = new QSlider(Qt::Horizontal, this); + QLabel *off_label = new QLabel("off", this); + off_label->setAlignment(Qt::AlignVCenter); + _flayout->addRow(off_label, off_slider); + + QSlider *comp_slider = NULL; + QLabel *comp_label = NULL; + + bool comb_comp_en = false; + _device_agent->get_config_bool(SR_CONF_PROBE_COMB_COMP_EN, comb_comp_en); + + if (comb_comp_en){ + comp_slider = new QSlider(Qt::Horizontal, this); + comp_label = new QLabel("comp", this); + comp_label->setAlignment(Qt::AlignVCenter); + _flayout->addRow(comp_label, comp_slider); + } + + channel_param_widget form; + form.gain.lable = gain_label; + form.gain.slider = gain_slider; + form.off.lable = off_label; + form.off.slider = off_slider; + form.comp.lable = comp_label; + form.comp.slider = comp_slider; + form.probe = probe; + + _params.push_back(form); + + connect(gain_slider, SIGNAL(valueChanged(int)), this, SLOT(set_value(int))); + connect(off_slider, SIGNAL(valueChanged(int)), this, SLOT(set_value(int))); - _slider_list.clear(); - for(std::list::const_iterator i = _label_list.begin(); - i != _label_list.end(); i++) { - (*i)->setParent(NULL); - _flayout->removeWidget((*i)); - delete (*i); + if (comp_slider != NULL){ + connect(comp_slider, SIGNAL(valueChanged(int)), this, SLOT(set_value(int))); + } } - _label_list.clear(); - _flayout->setSpacing(15); + QWidget *spaceLine = new QWidget(); + spaceLine->setFixedHeight(10); + _flayout->addRow(spaceLine); +} +void Calibration::update_device_info() +{ + if (_device_agent->have_instance() == false){ + assert(false); + } + + int dex = -1; + _is_setting = true; + for (const GSList *l = _device_agent->get_channels(); l; l = l->next) { sr_channel *const probe = (sr_channel*)l->data; - assert(probe); + dex++; + assert(dex < _params.size()); + auto *form = &_params[dex]; + + assert(form->probe == probe); uint64_t vgain = 0, vgain_default = 0; int vgain_range = 0; @@ -161,20 +212,10 @@ void Calibration::update_device_info() _device_agent->get_config_uint64(SR_CONF_PROBE_VGAIN, vgain, probe, NULL); _device_agent->get_config_uint64(SR_CONF_PROBE_VGAIN_DEFAULT, vgain_default, probe, NULL); _device_agent->get_config_uint16(SR_CONF_PROBE_VGAIN_RANGE, vgain_range, probe, NULL); - - QSlider *gain_slider = new QSlider(Qt::Horizontal, this); - gain_slider->setRange(-vgain_range/2, vgain_range/2); - gain_slider->setValue(vgain - vgain_default); - gain_slider->setObjectName(VGAIN+probe->index); - QString gain_string = CHANNEL_LABEL + QString::number(probe->index) + VGAIN; - QLabel *gain_label = new QLabel(gain_string, this); - ui::adjust_label_size(gain_label, ui::ADJUST_HEIGHT); - gain_slider->setFixedHeight(gain_label->size().height()); - gain_label->setAlignment(Qt::AlignVCenter); - _flayout->addRow(gain_label, gain_slider); - _slider_list.push_back(gain_slider); - _label_list.push_back(gain_label); - + + form->gain.slider->setRange(-vgain_range/2, vgain_range/2); + form->gain.slider->setValue(vgain - vgain_default); + uint64_t voff = 0; uint16_t voff_range = 0; int v; @@ -185,51 +226,22 @@ void Calibration::update_device_info() if (_device_agent->get_config_uint16(SR_CONF_PROBE_PREOFF_MARGIN, v, probe, NULL)) { voff_range = (uint16_t)v; } - - QSlider *off_slider = new QSlider(Qt::Horizontal, this); - off_slider->setRange(0, voff_range); - off_slider->setValue(voff); - off_slider->setObjectName(VOFF+probe->index); - QString off_string = CHANNEL_LABEL + QString::number(probe->index) + VOFF; - QLabel *off_label = new QLabel(off_string, this); - ui::adjust_label_size(off_label, ui::ADJUST_HEIGHT); - off_slider->setFixedHeight(off_label->size().height()); - off_label->setAlignment(Qt::AlignVCenter); - _flayout->addRow(off_label, off_slider); - _slider_list.push_back(off_slider); - _label_list.push_back(off_label); - - bool comb_comp_en = false; - _device_agent->get_config_bool(SR_CONF_PROBE_COMB_COMP_EN, comb_comp_en); - - if (comb_comp_en) { + + form->off.slider->setRange(0, voff_range); + form->off.slider->setValue(voff); + + if (form->comp.slider != NULL) { int comb_comp = 0; _device_agent->get_config_int16(SR_CONF_PROBE_COMB_COMP, comb_comp, probe, NULL); - QSlider *comp_slider = new QSlider(Qt::Horizontal, this); - comp_slider->setRange(-127, 127); - comp_slider->setValue(comb_comp); - comp_slider->setObjectName(VCOMB+probe->index); - QString comp_string = CHANNEL_LABEL + QString::number(probe->index) + VCOMB; - QLabel *comp_label = new QLabel(comp_string, this); - ui::adjust_label_size(comp_label, ui::ADJUST_HEIGHT); - comp_slider->setFixedHeight(comp_label->size().height()); - comp_label->setAlignment(Qt::AlignVCenter); - _flayout->addRow(comp_label, comp_slider); - _slider_list.push_back(comp_slider); - _label_list.push_back(comp_label); - connect(comp_slider, SIGNAL(valueChanged(int)), this, SLOT(set_value(int))); - } - - connect(gain_slider, SIGNAL(valueChanged(int)), this, SLOT(set_value(int))); - connect(off_slider, SIGNAL(valueChanged(int)), this, SLOT(set_value(int))); + form->comp.slider->setRange(-127, 127); + form->comp.slider->setValue(comb_comp); + } } - - QWidget *spaceLine = new QWidget(); - spaceLine->setFixedHeight(10); - _flayout->addRow(spaceLine); - + update(); + + _is_setting = false; } void Calibration::reject() @@ -251,26 +263,26 @@ void Calibration::keyPressEvent(QKeyEvent *event) void Calibration::set_value(int value) { - QSlider* sc = dynamic_cast(sender()); + if (_is_setting){ + return; + } - for (const GSList *l = _device_agent->get_channels(); l; l = l->next) { - sr_channel *const probe = (sr_channel*)l->data; - assert(probe); - if (sc->objectName() == VGAIN+probe->index) { + const QSlider* sc = dynamic_cast(sender()); + + for (auto &form : _params) + { + if (form.gain.slider == sc){ uint64_t vgain_default; - if (_device_agent->get_config_uint64(SR_CONF_PROBE_VGAIN_DEFAULT, vgain_default, probe)) - { - _device_agent->set_config_uint64(SR_CONF_PROBE_VGAIN, value+vgain_default, probe); + if (_device_agent->get_config_uint64(SR_CONF_PROBE_VGAIN_DEFAULT, vgain_default, form.probe)){ + _device_agent->set_config_uint64(SR_CONF_PROBE_VGAIN, value+vgain_default, form.probe); } - break; } - else if (sc->objectName() == VOFF+probe->index) { - _device_agent->set_config_uint16(SR_CONF_PROBE_PREOFF, value, probe); - break; - } else if (sc->objectName() == VCOMB+probe->index) { - _device_agent->set_config_int16(SR_CONF_PROBE_COMB_COMP, value, probe); - break; + else if (form.off.slider == sc){ + _device_agent->set_config_uint16(SR_CONF_PROBE_PREOFF, value, form.probe); } + else if (form.comp.slider == sc){ + _device_agent->set_config_int16(SR_CONF_PROBE_COMB_COMP, value, form.probe); + } } } @@ -330,33 +342,7 @@ void Calibration::on_abort() void Calibration::reload_value() { - for (const GSList *l = _device_agent->get_channels(); l; l = l->next) { - sr_channel *const probe = (sr_channel*)l->data; - assert(probe); - - uint64_t vgain = 0, vgain_default = 0; - int vgain_range = 0; - _device_agent->get_config_uint64(SR_CONF_PROBE_VGAIN, vgain, probe, NULL); - _device_agent->get_config_uint64(SR_CONF_PROBE_VGAIN_DEFAULT, vgain_default, probe, NULL); - _device_agent->get_config_uint16(SR_CONF_PROBE_VGAIN_RANGE, vgain_range, probe, NULL); - - int voff = 0; - int voff_range = 0; - - _device_agent->get_config_uint16(SR_CONF_PROBE_PREOFF, voff, probe, NULL); - _device_agent->get_config_uint16(SR_CONF_PROBE_PREOFF_MARGIN, voff_range, probe, NULL); - - for(std::list::iterator i = _slider_list.begin(); - i != _slider_list.end(); i++) { - if ((*i)->objectName() == VGAIN+probe->index) { - (*i)->setRange(-vgain_range/2, vgain_range/2); - (*i)->setValue(vgain - vgain_default); - } else if ((*i)->objectName() == VOFF+probe->index) { - (*i)->setRange(0, voff_range); - (*i)->setValue(voff); - } - } - } + update_device_info(); } void Calibration::on_reset() @@ -377,6 +363,42 @@ void Calibration::updateLangText() VOFF = sp + L_S(STR_PAGE_DLG, S_ID(IDS_CALIB_VOFF), "VOFF"); VCOMB = sp + L_S(STR_PAGE_DLG, S_ID(IDS_CALIB_VCOMB), "VCOMB"); CHANNEL_LABEL = L_S(STR_PAGE_DLG, S_ID(IDS_DLG_CHANNEL), "Channel"); + + for(auto &form : _params) + { + QString gain_string = CHANNEL_LABEL + QString::number(form.probe->index) + VGAIN; + QString off_string = CHANNEL_LABEL + QString::number(form.probe->index) + VOFF; + QString comp_string = CHANNEL_LABEL + QString::number(form.probe->index) + VCOMB; + + form.gain.lable->setText(gain_string); + form.off.lable->setText(off_string); + + if (form.comp.lable != NULL){ + form.comp.lable->setText(comp_string); + } + + { + auto lable = form.gain.lable; + auto slider = form.gain.slider; + ui::adjust_label_size(lable, ui::ADJUST_HEIGHT); + slider->setFixedHeight(lable->size().height()); + } + + { + auto lable = form.off.lable; + auto slider = form.off.slider; + ui::adjust_label_size(lable, ui::ADJUST_HEIGHT); + slider->setFixedHeight(lable->size().height()); + } + + if (form.comp.lable != NULL) + { + auto lable = form.comp.lable; + auto slider = form.comp.slider; + ui::adjust_label_size(lable, ui::ADJUST_HEIGHT); + slider->setFixedHeight(lable->size().height()); + } + } } void Calibration::UpdateLanguage() diff --git a/DSView/pv/dialogs/calibration.h b/DSView/pv/dialogs/calibration.h index 3a9bbfd3..d831ba40 100644 --- a/DSView/pv/dialogs/calibration.h +++ b/DSView/pv/dialogs/calibration.h @@ -28,13 +28,14 @@ #include #include #include -#include +#include #include #include "../toolbars/titlebar.h" #include "dsdialog.h" #include "../ui/uimanager.h" class DeviceAgent; +struct sr_channel; namespace pv { @@ -44,6 +45,20 @@ class Calibration : public DSDialog, public IUiWindow { Q_OBJECT + struct ui_param_info + { + QLabel *lable; + QSlider *slider; + }; + + struct channel_param_widget + { + ui_param_info gain; + ui_param_info off; + ui_param_info comp; + sr_channel *probe; + }; + public: Calibration(QWidget *parent); ~Calibration(); @@ -64,6 +79,7 @@ class Calibration : public DSDialog, public IUiWindow void UpdateFont() override; void updateLangText(); + void BuildUI(); private slots: void set_value(int value); @@ -78,10 +94,10 @@ private slots: QPushButton *_reset_btn; QPushButton *_exit_btn; QFormLayout *_flayout; - std::list _slider_list; - std::list _label_list; + std::vector _params; DeviceAgent *_device_agent; + bool _is_setting; }; } // namespace dialogs From 88965967b9dbfa653bff08eb2750f725b9344c72 Mon Sep 17 00:00:00 2001 From: dreamsourcelabTAI Date: Fri, 24 May 2024 15:56:03 +0800 Subject: [PATCH 17/47] fix: unable to display the new store file path after changed it in windows 10 --- DSView/pv/dialogs/storeprogress.cpp | 11 ++++++++++- DSView/pv/dialogs/storeprogress.h | 3 ++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/DSView/pv/dialogs/storeprogress.cpp b/DSView/pv/dialogs/storeprogress.cpp index ef71479e..8cb179ad 100644 --- a/DSView/pv/dialogs/storeprogress.cpp +++ b/DSView/pv/dialogs/storeprogress.cpp @@ -390,8 +390,17 @@ void StoreProgress::on_change_file() else file = _store_session->MakeSaveFile(true); - if (file != ""){ + if (file != "") + { +#ifdef _WIN32 + _file_path = file; + + QTimer::singleShot(0, this, [this](){ + _fileLab->setText(_file_path); + }); +#else _fileLab->setText(file); +#endif if (_ckOrigin != NULL){ bool bFlag = file.endsWith(".csv"); diff --git a/DSView/pv/dialogs/storeprogress.h b/DSView/pv/dialogs/storeprogress.h index e82a45c5..974039ef 100644 --- a/DSView/pv/dialogs/storeprogress.h +++ b/DSView/pv/dialogs/storeprogress.h @@ -93,7 +93,8 @@ private slots: QComboBox *_end_cursor; view::View *_view; bool _is_done; - QTimer m_timer; + QTimer m_timer; + QString _file_path; }; } // dialogs From 349a31d7006dcdaa35bd5e9c3f7d241d96ba2186 Mon Sep 17 00:00:00 2001 From: dreamsourcelabTAI Date: Fri, 24 May 2024 16:28:07 +0800 Subject: [PATCH 18/47] fix: if the sample count is large, can't save data with cursor --- DSView/pv/dialogs/storeprogress.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DSView/pv/dialogs/storeprogress.cpp b/DSView/pv/dialogs/storeprogress.cpp index 8cb179ad..cfc118b1 100644 --- a/DSView/pv/dialogs/storeprogress.cpp +++ b/DSView/pv/dialogs/storeprogress.cpp @@ -203,7 +203,7 @@ void StoreProgress::accept() return; } - int total_count = _view->session().get_ring_sample_count(); + uint64_t total_count = _view->session().get_ring_sample_count(); if (start_index > total_count && end_index > total_count) { @@ -394,7 +394,7 @@ void StoreProgress::on_change_file() { #ifdef _WIN32 _file_path = file; - + QTimer::singleShot(0, this, [this](){ _fileLab->setText(_file_path); }); From a641d44e5a21b49693aff18d1080ddb5eee6f6de Mon Sep 17 00:00:00 2001 From: dreamsourcelabTAI Date: Mon, 27 May 2024 15:38:19 +0800 Subject: [PATCH 19/47] fix: export an error logic data with csv type on loop mode --- DSView/pv/storesession.cpp | 67 ++++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 21 deletions(-) diff --git a/DSView/pv/storesession.cpp b/DSView/pv/storesession.cpp index 6cd9073c..9f49bb10 100644 --- a/DSView/pv/storesession.cpp +++ b/DSView/pv/storesession.cpp @@ -986,8 +986,7 @@ void StoreSession::export_exec(data::Snapshot *snapshot) if (channel_type == SR_CHANNEL_LOGIC) { _unit_count = logic_snapshot->get_ring_sample_count(); - int blk_num = logic_snapshot->get_block_num(); - bool sample; + int blk_num = logic_snapshot->get_block_num(); std::vector buf_vec; std::vector buf_sample; @@ -995,6 +994,8 @@ void StoreSession::export_exec(data::Snapshot *snapshot) uint64_t end_index = _end_index; int start_block = 0; int end_block = 0; + uint64_t start_offset = 0; + uint64_t end_offset = 0; if (start_index > logic_snapshot->get_ring_sample_count()){ dsv_err("ERROR:the start curosr is invalid!"); @@ -1007,10 +1008,10 @@ void StoreSession::export_exec(data::Snapshot *snapshot) } if (start_index > 0){ - start_block = logic_snapshot->get_block_index_with_sample(start_index, NULL); + start_block = logic_snapshot->get_block_index_with_sample(start_index, &start_offset); } if (end_index > 0){ - end_block = logic_snapshot->get_block_index_with_sample(end_index, NULL); + end_block = logic_snapshot->get_block_index_with_sample(end_index, &end_offset); } if (start_index > 0 && end_index > 0){ @@ -1023,8 +1024,7 @@ void StoreSession::export_exec(data::Snapshot *snapshot) _unit_count = end_index; } - for (int blk = 0; !_canceled && blk < blk_num; blk++) { - uint64_t buf_sample_num = logic_snapshot->get_block_size(blk) * 8; + for (int blk = 0; !_canceled && blk < blk_num; blk++) { buf_vec.clear(); buf_sample.clear(); @@ -1033,32 +1033,54 @@ void StoreSession::export_exec(data::Snapshot *snapshot) if (blk > end_block && end_block > 0) break; + uint64_t block_size = logic_snapshot->get_block_size(blk); + + if (blk == end_block && end_offset / 8 < block_size && end_offset > 0){ + block_size = end_offset / 8; + } + if (blk == start_block && start_offset > 0){ + block_size -= start_offset / 8; + } + for(auto s : _session->get_signals()) { int ch_type = s->get_type(); if (ch_type == SR_CHANNEL_LOGIC) { int ch_index = s->get_index(); - if (!logic_snapshot->has_data(ch_index)) + + if (!logic_snapshot->has_data(ch_index)){ continue; - uint8_t *buf = logic_snapshot->get_block_buf(blk, ch_index, sample); - buf_vec.push_back(buf); - buf_sample.push_back(sample); + } + + bool flag = false; + uint8_t *block_buf = logic_snapshot->get_block_buf(blk, ch_index, flag); + + if (start_block == blk && start_offset > 0 && block_buf != NULL){ + block_buf += start_offset / 8; + } + + buf_vec.push_back(block_buf); + buf_sample.push_back(flag); } } - uint16_t unitsize = ceil(buf_vec.size() / 8.0); + const uint16_t unitsize = ceil(buf_vec.size() / 8.0); unsigned int usize = 8192; unsigned int size = usize; + const uint64_t buf_sample_num = block_size * 8; struct sr_datafeed_logic lp; + uint8_t *xbuf = (uint8_t *)malloc(size * unitsize); + if (xbuf == NULL) { + _has_error = true; + _error = L_S(STR_PAGE_DLG, S_ID(IDS_MSG_STORESESS_EXPORTPROC_ERROR2), "xbuffer malloc failed."); + return; + } + for(uint64_t i = 0; !_canceled && i < buf_sample_num; i+=usize){ - if(buf_sample_num - i < usize) + if(buf_sample_num - i < usize){ size = buf_sample_num - i; - uint8_t *xbuf = (uint8_t *)malloc(size * unitsize); - if (xbuf == NULL) { - _has_error = true; - _error = L_S(STR_PAGE_DLG, S_ID(IDS_MSG_STORESESS_EXPORTPROC_ERROR2), "xbuffer malloc failed."); - return; - } + } + memset(xbuf, 0, size * unitsize); for (uint64_t j = 0; j < size; j++) { @@ -1084,11 +1106,14 @@ void StoreSession::export_exec(data::Snapshot *snapshot) g_string_free(data_out,TRUE); } - _units_stored += size; - if (xbuf) - free(xbuf); + _units_stored += size; progress_updated(); } + + if (xbuf){ + free(xbuf); + xbuf = NULL; + } } } else if (channel_type == SR_CHANNEL_DSO) { From 1801609c06e0af981dff5db6ab21138b0c688fec Mon Sep 17 00:00:00 2001 From: dreamsourcelabTAI Date: Thu, 6 Jun 2024 15:03:33 +0800 Subject: [PATCH 20/47] fix: the PageUp and PageDown key is disabled --- DSView/pv/mainwindow.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/DSView/pv/mainwindow.cpp b/DSView/pv/mainwindow.cpp index f4b013bc..791d2549 100644 --- a/DSView/pv/mainwindow.cpp +++ b/DSView/pv/mainwindow.cpp @@ -1274,20 +1274,32 @@ namespace pv break; case Qt::Key_PageUp: +#ifdef _WIN32 + case 33: +#endif _view->set_scale_offset(_view->scale(), _view->offset() - _view->get_view_width()); break; case Qt::Key_PageDown: +#ifdef _WIN32 + case 34: +#endif _view->set_scale_offset(_view->scale(), _view->offset() + _view->get_view_width()); break; case Qt::Key_Left: +#ifdef _WIN32 + case 37: +#endif _view->zoom(1); break; case Qt::Key_Right: +#ifdef _WIN32 + case 39: +#endif _view->zoom(-1); break; From 643a26f8730f67eff6bce857711a119137b5836d Mon Sep 17 00:00:00 2001 From: yunyaobaihong <896458252@qq.com> Date: Fri, 7 Jun 2024 17:34:21 +0800 Subject: [PATCH 21/47] Decoder Fixed: Number and State bit 16 decode error --- .../decoders/numbers_and_state/pd.py | 63 +++++++++++-------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/libsigrokdecode4DSL/decoders/numbers_and_state/pd.py b/libsigrokdecode4DSL/decoders/numbers_and_state/pd.py index 9a716c8b..b90eb770 100644 --- a/libsigrokdecode4DSL/decoders/numbers_and_state/pd.py +++ b/libsigrokdecode4DSL/decoders/numbers_and_state/pd.py @@ -35,7 +35,8 @@ # severely limited in its number of input channels, and dramatically # widening the parallel decoder may be undesirable. -# update: 2022.9.8, the wait() function returns variables is error. +## 2022/9/8 DreamSourceLab : the wait() function returns variables is error +## 2024/6/4 DreamSourceLab : Fixed the fifteenth bit of data being unable to decode when the total bit count is set to 16. from common.srdhelper import bitpack import json @@ -124,7 +125,8 @@ class Decoder(srd.Decoder): options = ( {'id': 'clkedge', 'desc': 'Clock edge', 'default': 'rising', 'values': ('rising', 'falling', 'either'), 'idn':'dec_numbers_and_state_opt_clkedge'}, - {'id': 'count', 'desc': 'Total bits count', 'default': 0, 'idn':'dec_numbers_and_state_opt_count'}, + {'id': 'count', 'desc': 'Total bits count', 'default': 1, + 'values': tuple(range(0,129,1)), 'idn':'dec_numbers_and_state_opt_count'}, {'id': 'interp', 'desc': 'Interpretation', 'default': 'unsigned', 'values': ('unsigned', 'signed', 'fixpoint', 'fixsigned', 'ieee754', 'enum'), 'idn':'dec_numbers_and_state_opt_interp'}, {'id': 'fracbits', 'desc': 'Fraction bits count', 'default': 0, 'idn':'dec_numbers_and_state_opt_fracbits'}, @@ -328,43 +330,54 @@ def format_hex(self, ss, es, value): return [self.format_string.format(value)] def decode(self): - channels = [ch for ch in range(_max_channels) if self.has_channel(ch)] + #channels + channels = [] + for ch in range(1,_max_channels + 1): + if self.has_channel(ch): + channels.append(ch) + + #clk have_clk = Pin.CLK in channels if have_clk: channels.remove(Pin.CLK) if not channels: raise ChannelError("Need at least one bit channel.") + + #wait cond if have_clk: - clkedge = { - 'rising': 'r', - 'falling': 'f', - 'either': 'e', - }.get(self.options['clkedge']) + clk = {'rising': 'r', + 'falling': 'f', + 'either': 'e',} + clkedge = clk.get(self.options['clkedge']) wait_cond = {Pin.CLK: clkedge} else: - wait_cond = [{ch: 'e'} for ch in channels] + wait_cond = [] + for ch in channels: + wait_cond.append({ch: 'e'}) + #bitcount bitcount = self.options['count'] if not bitcount: - bitcount = channels[-1] - Pin.BIT_0 + 1 + bitcount = len(channels) self.bitcount = bitcount - self.interpreter = { - 'unsigned': self.interp_unsigned, - 'signed': self.interp_signed, - 'fixpoint': self.interp_fixpoint, - 'fixsigned': self.interp_fixpoint, - 'ieee754': self.interp_ieee754, - 'enum': self.interp_enum, - }.get(self.options['interp']) + #interpreter + interpreter = {'unsigned': self.interp_unsigned, + 'signed': self.interp_signed, + 'fixpoint': self.interp_fixpoint, + 'fixsigned': self.interp_fixpoint, + 'ieee754': self.interp_ieee754, + 'enum': self.interp_enum,} + self.interpreter = interpreter.get(self.options['interp']) self.interp_state = {} - self.formatter = { - '-': self.format_native, - 'bin': self.format_bin, - 'oct': self.format_oct, - 'dec': self.format_dec, - 'hex': self.format_hex, - }.get(self.options['format']) + + formatter = {'-': self.format_native, + 'bin': self.format_bin, + 'oct': self.format_oct, + 'dec': self.format_dec, + 'hex': self.format_hex,} + + self.formatter =formatter.get(self.options['format']) self.format_string = None bFirst = True From 254d35ad2d8071399a7ba75dfea3b91cc937a82b Mon Sep 17 00:00:00 2001 From: dreamsourcelabTAI Date: Tue, 11 Jun 2024 15:09:10 +0800 Subject: [PATCH 22/47] Reload device list when machine awaked --- DSView/pv/mainwindow.cpp | 7 ++++- DSView/pv/mainwindow.h | 2 ++ DSView/pv/sigsession.cpp | 12 +++++++++ DSView/pv/sigsession.h | 2 ++ DSView/pv/winnativewidget.cpp | 23 ++++++++++++++++ libsigrok4DSL/lib_main.c | 49 +++++++++++++++++++++++++++++++---- libsigrok4DSL/libsigrok.h | 2 ++ 7 files changed, 91 insertions(+), 6 deletions(-) diff --git a/DSView/pv/mainwindow.cpp b/DSView/pv/mainwindow.cpp index 791d2549..a6c5021c 100644 --- a/DSView/pv/mainwindow.cpp +++ b/DSView/pv/mainwindow.cpp @@ -2221,6 +2221,11 @@ namespace pv QWidget* MainWindow::GetBodyView() { return _view; - } + } + + void MainWindow::OnWindowsPowerEvent(bool bEnterSleep) + { + _session->ProcessPowerEvent(bEnterSleep); + } } // namespace pv diff --git a/DSView/pv/mainwindow.h b/DSView/pv/mainwindow.h index 0415c1b2..a43e0427 100644 --- a/DSView/pv/mainwindow.h +++ b/DSView/pv/mainwindow.h @@ -134,6 +134,8 @@ private slots: void switchLanguage(int language) override; bool able_to_close(); QWidget* GetBodyView(); + + void OnWindowsPowerEvent(bool bEnterSleep); private: void setup_ui(); diff --git a/DSView/pv/sigsession.cpp b/DSView/pv/sigsession.cpp index 02ef29af..c82a6d24 100644 --- a/DSView/pv/sigsession.cpp +++ b/DSView/pv/sigsession.cpp @@ -2586,4 +2586,16 @@ namespace pv on_load_config_end(); } + void SigSession::ProcessPowerEvent(bool bEnterSleep) + { + if (bEnterSleep){ + if (_is_working && _device_agent.is_hardware()){ + stop_capture(); + } + } + else{ + ds_reload_device_list(); + } + } + } // namespace pv diff --git a/DSView/pv/sigsession.h b/DSView/pv/sigsession.h index 9a2344cf..bfbba655 100644 --- a/DSView/pv/sigsession.h +++ b/DSView/pv/sigsession.h @@ -453,6 +453,8 @@ class SigSession: void apply_samplerate(); + void ProcessPowerEvent(bool bEnterSleep); + private: void set_cur_samplelimits(uint64_t samplelimits); void set_cur_snap_samplerate(uint64_t samplerate); diff --git a/DSView/pv/winnativewidget.cpp b/DSView/pv/winnativewidget.cpp index 7b866301..02e3c332 100644 --- a/DSView/pv/winnativewidget.cpp +++ b/DSView/pv/winnativewidget.cpp @@ -40,6 +40,7 @@ #include "mainframe.h" #include "dsvdef.h" #include "appcontrol.h" +#include "mainwindow.h" #define FIXED_WIDTH(widget) (widget->minimumWidth() >= widget->maximumWidth()) #define FIXED_HEIGHT(widget) (widget->minimumHeight() >= widget->maximumHeight()) @@ -373,6 +374,28 @@ LRESULT CALLBACK WinNativeWidget::WndProc(HWND hWnd, UINT message, WPARAM wParam } break; } + case WM_POWERBROADCAST: + { + if (self->_childWidget != NULL) + { + dsv::MainFrame *frame = dynamic_cast(self->_childWidget); + dsv::MainWindow *mainWnd = dynamic_cast(frame->GetMainWindow()); + switch (wParam) + { + case PBT_APMQUERYSUSPEND: + dsv_info("Windows enters sleep.") + mainWnd->OnWindowsPowerEvent(true); + break; + + case PBT_APMRESUMESUSPEND: + case PBT_APMRESUMECRITICAL: + dsv_info("Windows be awaked.") + mainWnd->OnWindowsPowerEvent(false); + break; + } + } + break; + } } return DefWindowProc(hWnd, message, wParam, lParam); diff --git a/libsigrok4DSL/lib_main.c b/libsigrok4DSL/lib_main.c index f09fa4e6..743829f0 100644 --- a/libsigrok4DSL/lib_main.c +++ b/libsigrok4DSL/lib_main.c @@ -68,6 +68,7 @@ struct sr_lib_context int transaction_id; int transaction_command; int last_error; + int is_reloading_list; }; static void hotplug_event_listen_callback(struct libusb_context *ctx, struct libusb_device *dev, int event); @@ -104,6 +105,7 @@ static struct sr_lib_context lib_ctx = { .transaction_id = 0, .transaction_command = DEV_TRANS_NONE, .last_error = SR_OK, + .is_reloading_list = 0, }; /** @@ -1111,6 +1113,10 @@ SR_PRIV int sr_usb_device_is_exists(libusb_device *usb_dev) struct sr_dev_inst *dev; int bFind = 0; + if (lib_ctx.is_reloading_list){ + return 0; + } + if (usb_dev == NULL) { sr_err("sr_usb_device_is_exists(), @usb_dev is null."); @@ -1320,8 +1326,12 @@ static void process_attach_event(int isEvent) struct sr_dev_driver **drivers; GSList *dev_list; GSList *l; + GSList *l_check; struct sr_dev_driver *dr; + struct sr_dev_inst *sdi; + struct sr_dev_inst *new_sdi; int num = 0; + int bFind; if (isEvent){ sr_info("Process device attach event."); @@ -1336,14 +1346,32 @@ static void process_attach_event(int isEvent) if (dr->driver_type == DRIVER_TYPE_HARDWARE) { dev_list = dr->scan(NULL); - if (dev_list != NULL) - { - pthread_mutex_lock(&lib_ctx.mutext); + if (dev_list != NULL){ + pthread_mutex_lock(&lib_ctx.mutext); + for (l = dev_list; l; l = l->next) { - lib_ctx.device_list = g_slist_append(lib_ctx.device_list, l->data); - num++; + bFind = 0; + new_sdi = l->data; + + for (l_check = lib_ctx.device_list; l_check; l_check = l_check->next) + { + sdi = l_check->data; + if (sdi->handle == new_sdi->handle){ + bFind = 1; + break; + } + } + + if (!bFind){ + lib_ctx.device_list = g_slist_append(lib_ctx.device_list, l->data); + num++; + } + else{ + sr_info("A device not appent to list, handle:%p", (void*)new_sdi->handle); + sr_dev_inst_free(new_sdi); //Not append to list, so free it. + } } pthread_mutex_unlock(&lib_ctx.mutext); g_slist_free(dev_list); @@ -1708,3 +1736,14 @@ SR_API int ds_get_last_error() { return lib_ctx.last_error; } + +SR_API int ds_reload_device_list() +{ + sr_info("Reload device list."); + + lib_ctx.is_reloading_list = 1; + process_attach_event(0); + lib_ctx.is_reloading_list = 0; + + return SR_OK; +} diff --git a/libsigrok4DSL/libsigrok.h b/libsigrok4DSL/libsigrok.h index e8f6b15d..175305fa 100644 --- a/libsigrok4DSL/libsigrok.h +++ b/libsigrok4DSL/libsigrok.h @@ -1478,6 +1478,8 @@ SR_API int ds_release_actived_device(); SR_API int ds_get_last_error(); +SR_API int ds_reload_device_list(); + /*---config -----------------------------------------------*/ SR_API int ds_get_actived_device_config(const struct sr_channel *ch, const struct sr_channel_group *cg, From 4213f8d6b75f66a1b2c993ee3d8ca143c7ea0dc9 Mon Sep 17 00:00:00 2001 From: dreamsourcelabTAI Date: Thu, 13 Jun 2024 16:31:18 +0800 Subject: [PATCH 23/47] Capture the power event in windows --- DSView/pv/sigsession.cpp | 1 + DSView/pv/winnativewidget.cpp | 95 +++++++++++++++++++++++++++++------ libsigrok4DSL/lib_main.c | 23 ++++++++- libsigrok4DSL/libsigrok.h | 2 + 4 files changed, 106 insertions(+), 15 deletions(-) diff --git a/DSView/pv/sigsession.cpp b/DSView/pv/sigsession.cpp index c82a6d24..63931863 100644 --- a/DSView/pv/sigsession.cpp +++ b/DSView/pv/sigsession.cpp @@ -2592,6 +2592,7 @@ namespace pv if (_is_working && _device_agent.is_hardware()){ stop_capture(); } + ds_close_all_device(); } else{ ds_reload_device_list(); diff --git a/DSView/pv/winnativewidget.cpp b/DSView/pv/winnativewidget.cpp index 02e3c332..9b523669 100644 --- a/DSView/pv/winnativewidget.cpp +++ b/DSView/pv/winnativewidget.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include "log.h" #include "mainframe.h" @@ -50,11 +51,71 @@ #define WINDOW_STATUS_NORMAL 2 #define WINDOW_STATUS_MIN 3 +typedef HPOWERNOTIFY(WINAPI* PFN_REGISTER_SUSPEND_RESUME_NOTIFICATION)(HANDLE, DWORD); +typedef BOOL(WINAPI* PFN_UNREGISTER_SUSPEND_RESUME_NOTIFICATION)(HPOWERNOTIFY); + namespace pv { namespace { bool g_enable_ncclient = true; + HPOWERNOTIFY g_hPowerNotification = NULL; + HMODULE g_hUser32 = NULL; + PFN_REGISTER_SUSPEND_RESUME_NOTIFICATION fnRegisterSuspendResumeNotification = NULL; + PFN_UNREGISTER_SUSPEND_RESUME_NOTIFICATION fnUnregisterSuspendResumeNotification = NULL; +} + +static bool InitCapturePowerEvent(HWND hWnd) +{ + g_hUser32 = LoadLibrary(L"user32.dll"); + if (g_hUser32 == NULL) { + dsv_info("ERROR: Failed to load user32.dll"); + return false; + } + + fnRegisterSuspendResumeNotification = (PFN_REGISTER_SUSPEND_RESUME_NOTIFICATION)GetProcAddress(g_hUser32, + "RegisterSuspendResumeNotification"); + + if (fnRegisterSuspendResumeNotification == NULL){ + dsv_info("ERROR: failed to get RegisterSuspendResumeNotification address"); + FreeLibrary(g_hUser32); + g_hUser32 = NULL; + return false; + } + + fnUnregisterSuspendResumeNotification = (PFN_UNREGISTER_SUSPEND_RESUME_NOTIFICATION)GetProcAddress(g_hUser32, + "UnregisterSuspendResumeNotification"); + + if (fnUnregisterSuspendResumeNotification == NULL){ + dsv_info("ERROR: failed to get UnregisterSuspendResumeNotification address"); + FreeLibrary(g_hUser32); + g_hUser32 = NULL; + return false; + } + + g_hPowerNotification = fnRegisterSuspendResumeNotification(hWnd, DEVICE_NOTIFY_WINDOW_HANDLE); + + if (g_hPowerNotification == NULL){ + dsv_info("ERROR: failed to call RegisterSuspendResumeNotification()."); + FreeLibrary(g_hUser32); + g_hUser32 = NULL; + return false; + } + + return true; +} + +static void UninitCapturePowerEvent() +{ + if (g_hPowerNotification != NULL){ + fnUnregisterSuspendResumeNotification(g_hPowerNotification); + g_hPowerNotification = NULL; + } + + if (g_hUser32 != NULL){ + FreeLibrary(g_hUser32); + g_hUser32 = NULL; + } } //-----------------------------WinNativeWidget @@ -118,6 +179,8 @@ WinNativeWidget::WinNativeWidget(const int x, const int y, const int width, _shadow->createWinId(); _shadow->SetCallback(this); } + + InitCapturePowerEvent(_hWnd); } WinNativeWidget::~WinNativeWidget() @@ -139,6 +202,8 @@ void WinNativeWidget::SetChildWidget(MainFrame *w) else if (_shadow != NULL){ _shadow->hideShadow(); _shadow->close(); //Set null, the applictoin will exit. + + UninitCapturePowerEvent(); } } @@ -164,7 +229,7 @@ LRESULT CALLBACK WinNativeWidget::WndProc(HWND hWnd, UINT message, WPARAM wParam } switch (message) - { + { case WM_SYSCOMMAND: { if (wParam == SC_KEYMENU) @@ -375,25 +440,27 @@ LRESULT CALLBACK WinNativeWidget::WndProc(HWND hWnd, UINT message, WPARAM wParam break; } case WM_POWERBROADCAST: - { + { if (self->_childWidget != NULL) { - dsv::MainFrame *frame = dynamic_cast(self->_childWidget); - dsv::MainWindow *mainWnd = dynamic_cast(frame->GetMainWindow()); + pv::MainFrame *frame = dynamic_cast(self->_childWidget); + pv::MainWindow *mainWnd = dynamic_cast(frame->GetMainWindow()); + switch (wParam) { - case PBT_APMQUERYSUSPEND: - dsv_info("Windows enters sleep.") - mainWnd->OnWindowsPowerEvent(true); - break; - - case PBT_APMRESUMESUSPEND: - case PBT_APMRESUMECRITICAL: - dsv_info("Windows be awaked.") - mainWnd->OnWindowsPowerEvent(false); - break; + case PBT_APMSUSPEND:{ + dsv_info("WM_POWERBROADCAST: windows enters sleep."); + mainWnd->OnWindowsPowerEvent(true); + break; + } + case PBT_APMRESUMEAUTOMATIC:{ + dsv_info("WM_POWERBROADCAST: windows be awaked."); + mainWnd->OnWindowsPowerEvent(false); + break; + } } } + break; } } diff --git a/libsigrok4DSL/lib_main.c b/libsigrok4DSL/lib_main.c index 743829f0..332c1f54 100644 --- a/libsigrok4DSL/lib_main.c +++ b/libsigrok4DSL/lib_main.c @@ -1369,7 +1369,6 @@ static void process_attach_event(int isEvent) num++; } else{ - sr_info("A device not appent to list, handle:%p", (void*)new_sdi->handle); sr_dev_inst_free(new_sdi); //Not append to list, so free it. } } @@ -1747,3 +1746,25 @@ SR_API int ds_reload_device_list() return SR_OK; } + +SR_API int ds_close_all_device() +{ + sr_info("Close all device."); + + GSList *l; + struct sr_dev_inst *dev; + + pthread_mutex_lock(&lib_ctx.mutext); + + for (l = lib_ctx.device_list; l; l = l->next) + { + dev = l->data; + if (dev->dev_type == DEV_TYPE_USB){ + close_device_instance(dev); + } + } + + pthread_mutex_unlock(&lib_ctx.mutext); + + return SR_OK; +} diff --git a/libsigrok4DSL/libsigrok.h b/libsigrok4DSL/libsigrok.h index 175305fa..4487aea2 100644 --- a/libsigrok4DSL/libsigrok.h +++ b/libsigrok4DSL/libsigrok.h @@ -1480,6 +1480,8 @@ SR_API int ds_get_last_error(); SR_API int ds_reload_device_list(); +SR_API int ds_close_all_device(); + /*---config -----------------------------------------------*/ SR_API int ds_get_actived_device_config(const struct sr_channel *ch, const struct sr_channel_group *cg, From 831fbe5466dcd8c49ddf3af5c4f55dc81013776e Mon Sep 17 00:00:00 2001 From: dreamsourcelabTAI Date: Thu, 13 Jun 2024 17:37:34 +0800 Subject: [PATCH 24/47] Update the firmware of U2Pro16 --- DSView/res/DSLogicU2Pro16.bin | Bin 465304 -> 465304 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/DSView/res/DSLogicU2Pro16.bin b/DSView/res/DSLogicU2Pro16.bin index 8fcd6713d607118a3f4477560ad150494fefdadf..3329fc319717791b2fe3049495ba21eb6738d130 100644 GIT binary patch literal 465304 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
NINzSFF$=Wg5B@Y%)sP zQeE6Ij%Gkhznw5+^fee^k8!O{8tjH+q^xYAI4B;R+rb+3P1f6$$=V9q8ngpU%+zKr zqoAgWX~BN-+|IxjR0HzWj(vlOe(q(CcC#f|MEkeo7X}MZjB;XJKrY=CFvn^~i!7qo zEJ{7g_#8dofMQFVnE;HeA8lz^$IciHV2PG%a$305X*!zawj1Ych*bF1Y?M|BVvLVZ zYU^E0$ivjr(wwdf3!*75Xk(6147WdVED{DwS6lXh0L(YU`<7I31n_iJUb$8TpCg=z zk!=W*27lwf*BTDX42q93K z=4Dk?<1viP1qV}kU7Ta&&kdU{SxL88Cnf#JqNr>}_F$O10w?4Xb*ihl^b6+^6Y4xIoPS8U5Q`uO;aEyaXi4) z*57m`ceFGyM-7)(7b(ioIWun86X+oDgRn8w+k*aUJ++GnYv60Ib^mz@UvUnb7^HHT zeL~abFgt;PQx%XdNe-~ofG~V(#*-D>4;mtjys3H)+UW!ic>mycPLPi;Mral**v*DC zU9+cPOfaDu=V{2N<#?XE$-06~%@t_VX8F>V%vJZ7RyyraDsf0%<1nI8S!;&iUtTRG$nFxgQPGSpY5s>QmDWJ zAF9%`CuLYQsBZ?)(#mku%xY#>Kc7wJzMY{!aDYymh84`vPHz%%@o%x%u6vo^8L zb8%W@<|B^GQ9mC&GaXC`9eBLF14%{pSVd)gQS<6m_-n%jXeTSH)gn8#+|95aj){(Fk|iloM&nTx9=(|FQkVxktd=s%+n!uba68^RC} zFMe79q^!lam0 zUvh6hZ9eoNozlK|Q4p92fzE*UM%?fh&+P1ovX>@x@wmCn`n*o0i+(h4;h(&?_Y>wP z;LDniAA&%d+Mhgg5fpV0br5v?!@l&t8aB*dxWBu*Fptq_e&2mCz9UW4LwAvL-{OWp z{fW&d?*ElfJ$&Z&i??sUGS;2qyBzN(9a`CSF8jZ{@vAquXX_O;Su(#*E}nex@qhls zr+WV`{Pn)n!?t!LR3ah>dr`|B5QyX5r@8p`wiP$rd}8+#{(T?#@R@Tjo)g5<#SR1{ z6UDx>^ZfHVbq~g&=sE~4E-t?4{|wG;AU}S0u_h@ z{zYD*ed?Yq1I?JdynB3Gl7Fa_=DK;@n9n}?k$<~-!n}nS!-<;zZ1s_g^0PR3e?t6m z)8Cf1dHRVbq{$F@3x|yMQ{Ub=oojykbC)<1!M%9#q%|#+PV!#ocvqIR^7VT0M8Wno zh+5aV_vfFN=EJKfKDygW9?S zo#R~zs=e0@C<=DJd@^WHX=kTxb=#j#L+r;La&SIkC-z0J<}WDZxZb>e=Sq->sz10HT&X*w9i9tszZG}9lJ`uW zQroHd?yapCKAJ5~J{T+SZei!jG~Gu2q+B;`brP`CUE zdu*pyaC)l|Pef1whn65>06uA;h?Cw7SkzX)Jm^Se?h79{6F5+deyJ{v0P)cYtyIqB zO=pf%(R7rH(%mCR1+GQU+8}p%3$Wr-!^ns8%Sgy7C&GzZqH&=2sL5G>vEpYV!$EPP zY$~^jr86?tdxL8101+|-6tG%cco3zdcz(Jl{em|`U2ZwBox9AHo~0Px%&cJXX_@G% zCZRs-=$xaq9`*rkXp6eB>{yU1wN2s@VCRgxo&@J|$u5CgJ!>b2s zVYoZ%S+-Z;rWKV276&3Yx5HH_Pc>~}?7FOZBP(#hAxj6{Cy`P5Rrw=Jnwo`wMon(~ z*wm@OY+~zL1($m8)SqJ%z)LriG@Ggvz3b7o(R1R_W^G4%CL)PQf0$< zk~4@Py#_!d>(yFCTtJXS!-;bxiuS9O&Hp#bH)W<79evn1u^A} zmki_hO-&hSvi1YKEseortR5KQC(owb)jXh8er;fI+DY0-PB2X=wJaS;j+llWJ{ml3 z7psQPjzf+e_>&dw(wv*X`jg_Ub{%siv~Jx%<}Gk39y4ovZDO0ZEliY?f0Sp-W_p+^ zrJVg!uHFn3$2FTP=<23u-72Z9o##!OR4|U&p46<6W@~+A&<(-d?2R*%CHWBpBXd}p z9CYV=EAtj5kTsgR!FJ9r;fkgW+br=WHNGY7gbB5;c;9xsaj97`;~;xJTLwpW*XVF0 zFr)BQF>DZ6bLlWf4y=ceHV9M2nt!+Scvf_e1o$~h}-163> z3-rM)nULuQUJSGFZC$4=`4b@KXPUYl*qJ^*-Jc+3r@%0h7zj#0#yB)$9s-V-$~xot zvQ~^A3TTJy2d>Pzq3KP__{~sJH$*SMHq)TuZV25>uK}UbDc{>UbiJ>rrDjxD<3&;@ zh7E-_^=x4DNa6k3>%Qnd@icJ^(4VcAxlko0TxDS;d|I zU&PzKc1?1-@{8Nuug3mKH^{f$~V9K^4XU;(+$&bV^Z-{V?2yXamS;3YwyC^*2&zc z(W;Ayj8RJCK5}umZ{50ZLH5gMkweFR^}SztlQ`nHp0A#d84f*eLi=u>yI|h?rgx`0 z<9+kypS%+aoLkmA2z1I^+PsuS^s;Oqh#ey;W^1+(=sxmTGo0QI0_4zv;G6IMaw?Aa zt(|J8&$4endiMQEgYVIEJ_)k?G3Xn1v84Cy)C z-C6J4baqT?^o|@ex2or#Hy6#tTNlvu&zOT^+m-(HS3mM6UJ?|NOW3C?Q9iJtwdXf? z-+fTbv(U5eCdY{QlE6)s&;nRL;`}QNha@k z>b;1KQ{yw63(uLs;F)J`K5_F2(UUQ!loATxdxs$qRV|wK>eZ$}{^7hh-1ZGW{x>xi zlrY!`!=kGdym;C3sHZ7)m?CNGy z@dAGB5~0TYupmI(LOSFQ%6W#)6Alz2K^57$z2TaT+TrTWX=|}Q?zL@uEP8?89Sf5;ejsAFkIzOQj6((v zUj(ZGy)5sDY%<(@f%w}l-R12}u4=S)m1!wlv??ExoTulFE2HyD?K|pk9k$4D*ks|j2iN2V;f9yxa z0FU_IR^lBwbyO%@a&S4AB3pitAJM?+W66;!b3duXG_m~LF&iCJb-0-eTpm}3MqqEPWRpcdLjZvu1_QUWRoB(W5AtXj2A1Tml)0j$WdG!k01NmaVm zYB@-HD5{k94xr%hlQDI50hFCgeAi+h;p#_{Qk`N{m3BP@yJWvDphqNA6ro+qViii+ zb%z`n7oP?~HUf7rXuI$}_OS1y+cS(zj+l9d4XG|vx4_)+H{!bF*0UEfZaF9{gJ!e> zOB)nwC^JJwITnb! zN{x>=Pz3ud{7S0a448er8FB^!Ou{n>Y+>nRNm4#-rIpb7 z4X||}IgWZL+_Jrv4z!`Jx`TpPVRY8fXS46s$G9`fQwNi}z@jL0VJDxly@!G;+-i)B zNj zo};u4zSGUvt8&M3ot2^=yFr__628)2x^3#l13Ox97|wBZh@zOFq3zkvMP01JIq3=p zTd@<7i4(m&(nyG{!1bD@nbbh;3XXnr^Nw-3Nf1w5A?(VQbn4Rv@KESda&D3pBE#CJ z1v1111YVA8B@Oi%1Po%^{PQ5S2(}IpuTe7%+Zt{tP7!Wg(HK^|S(O7g+u(_Jg;f#0kK!GSfd?D zIZiX>G_U64j3e`zNDS*76fRrb-hpQ)M$&8n<`uTcI zipnauw4;`tk#;z(4WrnQ9fvnLbKh_}Fx6zRTJTabu_S3dOv}xljVj%K)Mg!*I!kdvq>sbe^5gQ&R6H=^_QVD94iimefvnEB8z-#NX z#{7pLiAUzuFo+U9BS}(K=q88D$QgW;rp?QSv{c6v$yiuu)oPx>4MTiBQC*5)h%oNp z+m@wj8gj32vf`A*WH@nTZ*5ZLt+97}8PMNkQ}04LvL(BCfp;)({em;d%vGyppbE!O zFo>jE?)M92=87zL!Io}adVrvFto5Zc^R#tU=3G&E6hThIgjWd@KnF{%5ahYDDf+0Z zku&Bhame0$#hiVlkJ#GRJNv9;X^B5DR}4wjCtJHPk31sD*t1u8MDE=|+M_OMX436B z-JM3eHy-}*r#_$*oMn@`ru{wi&D(Fh{WE7CdPvfzul|!?e$$6GAKKMTN(MRF7th?j zec$!ZJbC6x1XwqcW|c-M^iAD(_*1`fze?NObz@(~PX5CNi z#dDSok;?-JKK*tB1YFni(A(bj(m(zm2OoO+L-8ghZU9E^@Z32dxOj$Jk1o`(kOIzRTPZ0@e1HYf#U`jYkhWz|qkgp!3Ct+J|nVKI z8BSr|SS((A@!a)uKwv&C?NKVx{p8rVe6LHYvp=3ZOFY~@O86pn1%FU6HGD&CjyzpV9+!V#!!w@KP0wRi?6c2q zcHfSQ@K-mlzI^$?j;AR}SH&Siy6Ml7%13-6=Y~3)eQ0~M&|HjXueJZLg z>eAim+4Gnc|Ln6*8;1SOZ@uuXy{zmY&>i23yJvIH=0Og6%YD>H`cp$f=dz`ZTd}bH z&_4CEFJ0p#^3l{sea}7j{7%m)|LjYjd*$JG{n|UlZ?CGSGtP)2!TZD$jL4X&zh(Kt zg|B_>pcIE{vfd{>XFAuq$LU~&z2$e_@szlIlFRPX9JeoB5(FKmeDJex{MaXd@_?$WEYZeO;AxsA$vzKUsPcR}j6Y zx3h+-ypz}K#AdqGTQP=I9L?q?^O6|#GfyN+i;U#cSo<#0Nz0U|#-Vki1|~42x&zO{ zKY-~>y|sI*5BH#QY?Y~`4V4$}=*zZ%Gvkudr+U{wE{kVYVvAjgN0o->tKq>WLVU}1X@l8B&I?2l8c9tNTWXnrtv6o#ths#o0yVxMJjrA4dD@%V(g%D+4nAy9 ze_PujkqfLCcjPdMQOeHh$_I%4rtG6q*k$NDGVFsu{A7 z9=g7Owq+~KLgXUpY4m$-16dYl(j*}rq>n|Zl$jLk@oZfuO~O0?E@gP~>X|gJ>tw~t zFsBZ^6oj-QG`ZBAG^A>wxuQvi_+q)8|LAjnKoro-v&7NRrd-p3!ucHCKZ6CMXi=@p zS=*xaq4lOJ{Jb)&Q9=8vVU@ULHbZg}Y%!51RZDF-lNqx|>Idaob8;(s?r6oaDMr=w z;p{lBbIa=&vc_?Bowd`@z^Vw5@)D7Pz`546G0Rm&F%Xr5 ziL0hfwlL1HVc?c)J8ecY=gbtEea+k7EZnSI%-DBegD=l*Wo(IvXUeb`4)rNL&Fqgz zVn^ncUDC^D$xB|RD^n$OtVLIp-m&SN-I~eNuN+${XoAl*7rXfarGUIm zGIJVbEVtn097p9lvaGuB<4>yV4YM!X~)Zz{FZgE?|;QJ)XcJB7UcS z3{L^7IE*X4z-P@k%D0vxy!kivBbx3pJo-Yh31wC>Z&u8HiY~{NdRNSAn``Hq+^9b^=L@;%C>dsp23=#k;fpKeG}Drs^0$j^W4Ro$K>8eP(y_uTW~gXg|_ z^`6U@rO!t4sPFrkUwjzNwp^)l$3^-+SfWnz$1Y(We6U-EZ#pSSL7;nAu0FOIyfS!2 zHzZxUls~5PuJ%p8^?BW%)ajs-uBx&W1UoxXpADL-(jR>1dqrab!0Un_eNa#R&O6@1 z^+o9Ty=EkFsdIfYk{aH7b?+mh3SM~dg-fD{Z{0%M5Ne?imfaQ24WWeQrl-F2JCDb^ zlaT0?rm0Jpc6YyaNgAg+sw)4<6`Y%Xok zzH{Ni%U92$77Afm?sd9GsXFodjvso|FQ9i!3MCwUM15(&5au%mJF z?z_)#zWvF6^FNr|uOL6HyN`5Y^tns-T)5}f|A}0)HLub?q8s}&o=PPe`h&Y4L^`@@ zpcgxmQxOMdaeS)QXzZhZ5(tDlb~J#%?EUi}|KFXt-F;sKLEAoe>FkBGwCd^Uls*1GXg>I~Ai#SX1bhe+Pu#xgwH@F8YoC00vw_janPu%0TtoC%i8LN!Vtf8S zedXW%(OTgeE4x3s`zhX-3srd-2TFNVo;c<`czDkzJw5Q_>a`uacmBw`I7+KQ#C^}V zE>KfU_tB3EFEZ!P|L$jhBPd*Ffk7AH@Fu_k>evsPBl5(DBbfX-2gDNes&0(uTS zgRYzMq%EQ5r}X-m$9OLt$_91|^qN^FO*~Yd=PhNHFhlJfw#d)hvrR~Em#aPE*myZTCMj?J!`o6CALpMEFu|-gAbxO z5@`g@HZjEH4KEqatj&$bAvZh`Co9t<7U`qo#DfE!Rh0Ft$wy8;^({cKLLq4zlZyMgm`dd-e$BlTml-+8W7&sew z9K;H9{FOkjBd{zzeChE!2Z6&f-HD&8SSSMQyefI_x78S55-v7OY&cKhL@7=)ErFuZ zXjN*vQ^E{uy>B$zlao#v*@_ec)6jk`S!?p}wyK|%24cSBXu+&vL)jT&2b#wBYDFg7%>TzHrU(7jMoK)j!0E-3v)c`sZ`*?NyuU( zbTL7yHjO6PaZJq>yfwkWBkVoBO)G2m58SW?kcP}HFHjA=U=XlP5i{k!Fc!`&I3mc? z`qDZM0;e<9wXu-0VPyF6px`oJfRUIh`vUg|!S94%C!s~u^F zRTm2fQX?c9Ty#>zZ0ZNLB`_Z^ob@p_?ih5_uCmTzt_D|^Bc^$c$AoT}tYckcxUB*I zBr7wOGGWn8dBN5c%mxLN(Zpmy@m~I^>Wf`FpR9x4jL`&cASF~Vz>Nt3YESWDs2V(A zZ!r+);@HtwQy@$BeyDbRUb<)m1*vwT8{%VYw@O(hgZC6ktT z?CRj#muRw>2%-?oq*|F!f$nUUPDV?Ut+_Fr9mPo*VtiVsCZxfHNk}JE6XRP(>!c(< zh7v5Xq(B+*FtbZyT-x%23f}#A(gpf(YtojERtf6vl=&1h;UZtX&=bNm=rX-YxaV^p zW+Fc(fmRm3=tIo zQ{Y#8=4z#Sby{;Ek#hXVRtT3do&&i{rQ4PuxgfS#$CThq8(W?kKUp1#uku70wnk7U zbkHPO%(*pgGD{}QENv-0fuaWx5+`Y6hY4pt+mhfs&(a}%9OEaI;vMx;f>~z+MzopC zR%uZYqY_BL7cR{eze;0#0z-V+10c|4QhFj?g_gb3$$%*r^$O^aW|Bl#dde(m84GzT zbb4OV;Lt)5V^%d&Ut zE+ce2K_kEU$|GC5i@S2Av)_FE^!PV#<5fbR^N}k$x4IwGm#`myP^(;L_e(e${vVg` z^Z)v_+WS9!^7Z14dCe5z*IuWD)cljb+x8&*&u`eecKVR)|M~l`7jI54A?=Fr*}uMi zxP)%>_r-7RgvE^(IZM`FOakM?IAeT_^f=SRGIw}huwV)Z2E&lnjTSP*B(k|a&p0QS z&IJ|)X-O}?*{1B=r#{*9+J;A)GMRrB;`z0_J_-6*2ywBB;6f8Dr8;7xiMfbWn%>kv zY;9j|A9^R7x%Cv2oEm0n*RdENK5CdjS>=4MhVy8c4i+)7jB$h%gk*<`vV3_Q*{rCLC}ajbyX{CkzwLCeUH106CBiPmCL z@l7{kwt2#x@Z|urA&JI|i?$x^zN>Q-(aI8oFc)Pfc$2~+DM%^S#i8U%#~doiYTFVI zsLbC)Gwv9Nc5dc;yR&93&tIW>W?cgja!Wc)X zrL&3SP0%>UMa;s27EE+yr7m#mAy!w!hNh+pM2%#D=81i}W22fg~LO#hM6GQZseQl#wh~g>}jjA=oa@Wa{ z%Y{wE!im-u+})at^7Uf0($Y%X27$_0fr4hMYoU_7NriojWF_EK8lz2Vg9nb)yK8Qk%T1(GsSw(Z*=j_j$=N)~2_pVo{9m(94%)lr)_(r}9q?3fd-ZirTs zkwXEn)gq2=D(g}OmQI#qDg{&qp@>Hd=V4KSHrm4F(!?{Q;~$tl&9r1;6u8)54)TbF zQRQL6IwqH3;!jCN)T=P)Kwq(vXbncALB^Rt8lOau-Vs<#3S03r{PcH6LyH-4HlL%C z2o?f*j%Rg=uH*d-*# zcQhg00?u7N3kFcRV{M z<)=wP@dKUkDA)lEe^o2gB~bI?bFzRCwL^dR2LD#Tr6C#c_lDEJD%2 zOy{mX9LTm~bi)p~HB`O8Uwn-Z1JMU$ z;J~Ftp0>fJo}oAoT#Q_~n6^(emXs*F?j-VnR!ftFh;X(sug%gYHu+uXUQUQ z$wDIhBPB5H3{)e1?S*bSWRMKeoi$z}%WspKI3>G-0R*y)7t48TXqGSF?LtGP-2mb; zsMed=Y??J}EBK~nB&?D-TLej?e9<^PyWzJVW~OPow#ih}hs+%z;N(YM@*P}^UEM;g zHdAPL`V!p*{y9J;V))|PL$ppgP(b*n&E!4yjAH%l<<$$ktZ<+oWhs`+1*DxIj*SK z4hzb5iV??7lD3yGKXm23`?%Qx?KK@2FK+TjR$1Ke=OO#mZ@%~4(jqH~T-gUj?(UvL zQV!k-_a}b(#+mE8=HkUO*R`wk+D7-ZO42sV9=dY<`t5U)@m1+EJ+n?V%gFx9m*131 zvRHS$NVjf`*gnpkL-ZK+q36$k`o?e}2vVPf!zuo1x)H;@ef_@c+>pET{15)>J08}( zu6rA__eLXGTs6J3xzywQ_3MB3XVO9|&R}%MbTGS|9EeMQ@y4fr?&p5t7w8MJHH~Q$ z{#phx+*W#1u3Xu9esuqT^7nPGt2uvX2qYKGC9u1a#$^~h*_EAy)XVkh`2hrQh|cHT zHl(6n+h}HclpizSzRlIUJLade_P=Vs@HfH-v-bDe3p>coo7yy;4%>5oZ}pPRjcFde z`mNQ%=J})M7TftG#)#J{EN(irvHjqS zqY<60yAQ+JGH}JeJy54~Jh+Q!^y!N2xwP>1I<6eSs8Dj*xx^~Pab8@P%ecey)ZX3` zdnOg9joIkcc=b(8_Ke#YLD1C!fN@xK5IhoR4JA7r0v3@wex&%r{7CutO`7gI_qc3E z4UT2SYPu+Cyg}3LH(uKNLwbMr?mhF^W3V6p`~8duj<1@p9(W85)PH9_ed7;)tatae z?;QIe>~Y!508Zyq8-U)x^V}Lizyk3b>ZOjqc=hT&2eePr*@xgh8X+9~*dH7Z+xJHf zV&@YLw8AO7n@IhBvhE|qkllw_A+eJW(%^DOe5a*2mcSn>k*L=ALkSk!@>r1_)Etxm z|B1pIg`EOZ48HRt+%ZZ^x5IyTO!yZTarFBo((vftUsy%oMM2FrO?9$Yx8M4>e255- z1Hq9Y*ZLsZ(K5~k9Qy5JQtrbOK=do9g_LR`kn~p{+muL{^JHpzo;Zn%7OiZ-5E@el zY^ng*ZfwL<3Y!MYlOK!3?Vo~AF*&0xWfiJU&@g9@m-Y;4k+chGcgtgog=>Mo*)O5% zG(G#D!|gat7qC@3fMKS3U_yMp=A%PmOj7e~PfZ+4?ql#QdN;UJh3ta_p(j=z6T5AS zBRRKWy(P|RjWrrV1F=a;^JOLB;x95YC!bZYjqkWTiY#NVmd92_P%qf{k_X z!hf+2Yfb`A84fEhA=gqlC3vyaD92C$HpCiM3i~Q;4TEsluGs$)VB4x78#&|2q9`L^ z!muS@#gDaEqJeq`!`oMSUlx6|li0LNo&1HFL_`+Q2UDs(|41jN%&O1b_ z4>gE`DTZk3t^rFDn%=U5#nr&-1VzVgN#!_fGSFKN#;y-5X=KVJ#`5Qy8fCC^$JS6f zZ5>-k<Cw-# z3zwbnnp!_+oUW5JP4Rn^XIlv5i3KH8l%`2rCKKIFqb~-9;aDau-zUk45#(|MtLM}uK=N6`+se5}Cl zdoi`@ zPU#{12i>tP~ zvQ8Fqx8+`6lJw9b{C5HZ-IJ;NS|w4ub2-o3#Uu5(uO2-w7s;6prbDp39t6+tJonsV zmz&Ey1c>17>E_MYa5Y{L&@tcn{g?jLvluR2jWW89;Ab9w`j7u&2QfP zhNupV3p=eSwmZ^HqCDB|Ld$R+aKOB(9DlQ0sljyvCTh=wkYLj zu3l((13KBdpsC%Q<83=y$!yD)eW{gL>>zMZqpsg^19A&GR1$G zF}+{!omv%fyPxX7;SQX~TzATGEZKoK>730$$Prh2#D`~_{*({UHs(Z*<0TyTyW;^{ z|F#dp@o3itoCyDJhuZP-djI}=-Un=Ly(gy`cUoW!yHk!kW_X>5EoNUQ)#2#xJ;&kP z-*1OEXraO`#QUDYS1;O{kje?B--(tp6VeZQ)I9}KwTr%$(qeXrqKy^Iq7J%i%O z!bar@^Sy>M6z@>diK0&goHzr#P4T^kvk!Wd{yb6BkpMQS{-ZZX5c22poU%;%bCvV| z=S-D5eZTns(>6`b2Tmz}YTj~6=$(T8+Cc$|QF$~%Y?27w=8IAK)5bps zFLesblOsmW9D~eG9C-o*vdIJ_AUIlXZQs6&dj%uD zFHndq5LeP>}u2ZLe{41h%r+AMR$Z608iz=HF1)^V>8BV9ws)MGfSVN%s zGQBm;g&1-uM1MtAaSXEDO~YAh@%%8wxl|mFR$of*GF`~_Ec=h%o$=>hF^8Xirx07E z#61oZ<7E_R<*<)7Jz|SKbwx{T*(o!Z1Vw8&GFye*#{g$K7h}|r);T{->^0(1abrKA z*1G2?v7u)yJDw`hNGbIS`|5L`yiHjU@+e%uJ!?e6qnN+1&!rlP_=&@_*|F0JCtfRF ztghj;j5Z2W@ne~f)sqt3&ni~J?_6*6b1*;=5KQ6+MWG~U9Df#)6}*~7$*7B!;i86U~>!gKFG=|}I7TFj|`p8P3_ z2$#*#`_zc18MMZ!Xazm1Es|{?Gr7*5(Vr!MS)Kd_pIXf5-)7Vz<>+He>FG?D(OssN z6XV$U)T8IW*C@&iR7j57ZdsFJVvn8LRKy+PQ;(jar|fwHGd?gHJmnJ&tww+1X!m$z zCIs-$Ae?iDGjD1uxw!T_`La~wLil;yWLFIS-Cl86=4bu{Xm5C6g+zqQraU8iDVY5b zqb2&MEfZMpFpqu??VR;(W1Oe-6XWKKGunSpw(IZsQ!FSj=CXO2pMCgc|Ff8vL*6dN zdH;|iWtYv%v_d=#$7PrOV?E3Bk&uv3e_wz5C)=`W{;s=hrs!wSvi{*LgznL<%IssF z;U?R^uK(ru$sNA_Hva$dTl-TY|C%wv*N6O%^2U1B*j_c)NAuS(F9UelTlv#H5OevK zF|J0+k5amtl^5}E{MNtu+kXwbPyF`Z{=#|la@0NEW&g97mqYdxe}DgeM7eBUj=2xN z>>vBTM?LX*yBHVz*HgAb+%n<#qWK8H5$_TI)0me-_7r~~|Gjji;Spkim!BfeYMJO|Ce6%z3Y+Jo9Oa; zEB`af|5`RJP+coVlpdoE$K?c^N+p3xQCF2Z#qj$wjbWLFHNbup=S(qDf?haVR-|4= zzcX-HMT+I$@p-;*@kjuXX0*lv$F0%kd2nM(3}fX4+^O)LI3|9YH&FF2g9%i3Ah*GV znk8+N1b*^~KMXhusFztR8p~ws@X>D%>0l-o93IfygKV)Vw16Vz6wwSK@E1^}3$Nvu zBr%xCo$(~$@l(r_e=4LdVj;wsEms%8d>|&j^B_zgJs@$KTtzY|=@>+o@?e7OYX8F2 zVr&k1&g-n+io!Yumz>wcDdL-NVvkF5PQmFE_>qnW#q;NMr=0U-C}(Z0=_=9bsp!654cpRj@3J?< z1wwrCPyx-vqucvLGf;Sy!l+HzmzWgi!1EG>Gq>=;mM9$5X0&&I5CwtdP-uk%b-i(c zzXsGscfbv7lZkxARYx{w2Qp~R4r-AciO|=s?BUQwUmkl1K0q?;o!I>T9T1Tef0Q_^eL!>$I_@Khhk zZjaC^qGBh0$Y`)7y&^k;c&TXOdr%>OR~C+lke(Y$JBfm!4|^nPXK8#Joh_M?)UvJ0 z>X=!ismCX4 z_PQ%&fJhwimTkK&*Uu#{ailKLTDaigQB^-DnGLqh4btDzGxb7odETOYI;*+cda3)M zXY;bH?8Z$ewKX-pBd3l~@^u(=h92nzen7y5a~5K$fMKc$k+{O9S)Fo##OA;yw?G32 zmRH}nRlqLs4I0W|1E@C16?)FpM% zluH*2he|ReJ}A{`q&8%m8M~&o_>*tV>*z2Tl53BBj;PGP1)uumOo}1qLCFe=Wl^;p zMxI>sSX3*oW4ULmo0aP}<0v~{dM~8$fE?{QSe9idtLci3Q(=-jCh4hJy>eU=qJELSe#kkTWV%VDtG578}SJ)Pzf|`w#Z?H*vXC6-O-~W$( z^!`6!wKKPa?awCO-x&1TYX=XN(%$`n51hoc+wv1!f&IzB;V-kK`)Qr|JOVbYTGnoe zcf8{t|6}=H<$j}m@ZS9L?mkPwkM2hfFmCI1u<>l-{f$9IvFCu(Rsc?ZPV3i4BI`8` z<;G9_@=tL}`3KKdN}qDTZisO|L)x#rPkV3PYloX=H{3Vo{{Ng-TL1d5bB7x6>Z{+l zF7xfKHtMe`^g2bV`Jacoha8l?yC%N`%I?w8OE2jKV_yP0Be-`e1)Y2DcDJ8m7sBo) z`^vSuTtUD7>n9Q8#*M_muHW_1}nx^Z)jn*WKPAg!B6H+S!U3l2WleolDW8R2(c z)(en7n}tconJUj_U(H^8!n0%lmwt6+KHEQg>y!O&o6nkOjdt>DH^R3!zfDi@tl?Z1 zNXQI-_71i$(Q04#Y59CI?r6{s2kz;MEaPZ}?d_^a!bBs1C<2eib z`CAc>-5iIvkGRxpbSW-=FPU>Sg8M;QXAjz8VU!|gg~uo6DF>XeA2~=ZZF2M4DUGMD z-@0}1&jrt8(?^WJ*QQ6^Q49NffcE(cLVUjc zBX%zYTYkCFq5zJ{&ML(7lLm+38==yRgXL=DLx#=q+drdq^hx&p)9)>BW5$j`d=C8d z)$L^{(V*m<93zOyGhpn+fJ)2>FUG(YrS55uTLUP8SQR+3k_8556kf(N!$&de_-7oS zP$w$sCwXUP^;G6(;OYdkHK7&1Jp}C`#izzYU#c`78h7R5?)jC(O>qKl>k<}5aHyTA-FzYUK_;~*Mh~?v`LTQk{ z#xukpBBj0o4OV&{3d6TAIsm|x}Ty9dlf_{Rb54)4OXQ#{5 zYp9yGgi3R|uOza>I7@Lf_(_EvTXdhu@I>OS#}M|BTN?xPzCoi3BN`_rLpNT_R7H$} z(yvTFIPRexY6qfzhI%00pyxh8YShUsrUdYeM29FcDB;9Z3ehuUde)xY_hh968;}Ay zwFEfp5#@8(Xv}JsGoWm^MA<>N%Zl20u(QS~8tmoGU=Tm5oGqq~7lC`2*!c@72r}qa za)Bu&2Az)b&ZtgOsW)>@##6h=0}To|Vrm%OxC5rV+MIqCU|_6*Z$ zQ()$7Q@0G(%U}bYobHS^>w;sf?A*G6hGCag1Mx+%E=m%kRLa_WqJrcsNw>zKFPy_2 z76$^U3e=H7Sx{QX>nU#?8_r>v=Z?>-g5o7BZ93E;Fpvl0i6C(&`yuYuJk{TV)p0ptl1J)S4@*8aK^!D1Pm< z3AiYmeyU1ZRvf&?8T~OAjUU3mJFqU7iz&VXo2tu&GfjY!K%%aQz{FJb?m~f&!zocz z&tbx~LL6+Edv;)Z=SiJZm>mhJPnb_A2;Vp%tMghGWVW1CJx6An!ugELx`)Cnn)!5- zwQI67&A5p!0C~2d-B%mevet(*^0MZR^5vvA?4&QV4U0&!6}@gTaIEy2SqI-TLx#A{ zvDQe)88S0MeUAjJvT0$eT^(v=siBv}x>@ek?iO`xQ=hOMn^2#`5a9H4c2k__CZ09**fQ0;OE^xn0aa4F!>M z8jEogk7&s05bHS%`fO1&%WXa!FZwm@WRn#`%fWLTT)?yf)0munrKt@hS>N*BZn;#l zffR+lBptY82S|V4S)!fkm$30F#jDxJq$J1&I z(b0hy9HQUTCdQIR^&S8Pw-#c^@y)be`uv#~niA zg+dN``8myfw(#ofwD_mMLmfOZf=zE9?k>zYmmz*f0%#frh?MC}9ZY*k!o6}UO16Kt zNoIG2GDIRaSDuksn`a{a6(zyH;F)N9W;7Ax8X6b=DTcZ8OsAO7n31x%awn#6=b1<` zk}$veqwEbn+TH)rpSgdZBlD2n{-@6>WOpOUAn$(n?*8G&52v`IJSlgIspmD4<1(rU zI#o^?VlgW?mek_tY@1JP@K|KG<=RW(~;o&>q z`FmI1u+LF8_y7L=zjSi)pU1NNxt~iXvr#I$AOFyge~3fJl4Qsw$0M(?w#<(j^MgNl zgz${Ovb%Zn&c~0A?oylS#6R8N{fU#O_c6>r86G}V>=Q1(HoG_9OdNdXGveS2yC+5t zQdx3-Uo7|a?jI!%#(9V{kH(yxXny?<5GyLpzovR*Kf;-hqrJDf`I zeHMON7b4YqW+918-{@Ub5jQI;2y2x|Vd^ZWkyz$__y(fH0x++8254j&& zXFc4YT;+b}JI6cEkzh|w9^5h$W=mc*H*VjSJo&MYrPC{g$t21T$P~Q!ruWeTZI$U$ z*I#>Ww|nR9ud?6ISV zM+dh*aQg!?=`a$<=IAqzzE{up4H8BqcJECyRHDYaeWFqn2Tzmo)vHHF zrZ|q_a6nvHnc_+unA>m1!JmSCA;ze(0MGXa2e%I{a$w$jHVda1sUFSR#TfC?Gh%c4 zxYta0*Q5VrNFQUKgj|5()OBW)yqJJtACU8NvP3As{oHYOLA3_zA*oaB4r3K-Os6$8f&1%(jB4RWU3n1#<`Xy-MEIt7Jva}ve3t?0mPIwjsXfiC}c_W z#zjY)Rz=JA?Lco3GJ96HWw#s0&07JP4yXP; z+7i3TGak`&8m{99l@TtmiWgJIDx{_yjCq*I%N5krLi(JXQmcE&L(Dr@;;taUc~JF0 zkfVBNEp=8q8iYhihwo4fI8-}2UCL9L(8+Ppqm+e{%(v>>VnG6po7vzu+zr?CO*YL< z4`#KTv~@e}rk$ha>_9c4k}OmL*nMTon#SV9F?`dGkX}%*4x9~N=B?}T?r9@yrqE

o|Oo*0e5b8vU}L`PvuGgGQAvIck5yC1o+1qB?9nrYdF$599@Dg~Xbc zM&s2OW2?yOcy?foEE^g%(waVlACm-}=PW%CFX0Fz9F~1ny9w`Z*f6a3P1|xeaP19O zl%bR#8=q9M%LfeQK@z#O?HA?GS3Rq%_LeKR&@eAcNzn2lpL)T`Yu^NQCE z%-T;E%5gQVU5qfNZOx&;S9&||83E`PNtAq#XYNs*^=cOS%&PL4Sq2D za8#FsZ>JpjIk@pv%H1{tVWcqGV>H7yQYhD1wI0A2Ce9A|&{|XF+m<;BejDQD?Xse@ zNS>RW5U;tL%(O%6=ep@>OJUIzj-|ki;oMo4!kKPmHiUH%=Geh0SwxN(g;NYWXHFdo z8#C|BggJ?L2Q!q1?ZE7WZg@i9NAEKqh?UjGP#ANnBjl7-2$MPQ74iAR1~X|Kyegb$ z8%!I*axp-6Zgt8&;R?BgQOuhT3c@gEu8uD(jiZqn8%(qH#dOOZWE;C0HodVlK-$$j zwk@GoTbjeEo64rFaBoe7dE=O8gJMcIc_xfKg>Ak)Pm%b>c&3bwiAluC)&po5ynL!aCHBYzT4y&S| z9dH|91&NK}#sSAYUyxXlyff`FHG@0e1h!`RNS1L+-j<~e;Iu>5ZV0cY8HEB-XlL2d z;h1MVoSC-I;1LQf4H*n-TkPkWH)K_lbIM?vmM%lirG5Ew z8gBwq1=Njk`NVRgwld;^C;XVn#|iXfxQ1HX6y^+Ne~OVWe54QpJz8y6uC>83VbgMJ zyI+P$HO(vCrj`%Z=XGclGoGD4n$JYN^!Gmzo#s(9-M)S0Qux0Lg;|u=xsxoK^`1gX z=>O->?|ILc`G0*=m?-=QwB5G@ZW4R!=Z7)WpWPIek6x33pue`FG~g^j_*DWU&ELL08Nvn$+aW^^g`4(I0B>61kvma%wuct z!%i2qhb*#a_s+e^=Uc#xV?yo2ew3fIgn95L54z2Z!A{`i2YD}J#F%<0wGk$mdBoDP zD;sd0Lb}#Ua!e+_Py`vCFC2ea&C}tooTQRE{yF-R+O?*vD!z%#O6P$vIx+CXMU5#N z;z3MRDJLG~uQgX>2Wa#Fm>#F39nW~IJX(;bfC=PH!6B=A>b9pYI%m3SVY+Ts&u6S# zbjyk{8H=evQ+g2CkKr}uFFRd7LZEZvWLaz`h^4u$5kMAbriv<9+cs%9U`WGJP)J66 zMLQ05_I5LfM_q0sfuNq(w1q}&+J+BCJ}{z~2IkaDOI5U>R`oGOG1`?frB^jn<9g<3 z6V=k8sR(&ko7_3e@Dt6*M!Z+8=Wv8V7o#`-EeVn(*9 zeYRE|XN){fi&gkQjF+s1;?RN&)mxhYX3R?rEO4i0qEu_yGc%ZKwO@1#!|-RU%Pp-o zF!`S9G#HAPOOc#d?(&l1l3<9>_;4djlwfE1V=X3MLYBm$SD0-`Ca(8IPVrpH%7Q?& zb=-N>EMcU95En#w?(#9dA2bBc84s$>EUO9R?7(6%v#GL8wp}i#Q?Us&Tdbz%IhL+Trl^#&@kbOVX|#`Rz*F<|2-6rRTw zoRbGY`DCHqFwC-Br`i4ng@Y;AkRObySFN(A$g9%D5>eZrV3&+BjnN&f=;iv7DrGqw zi?5AEj6_pcn6l@W6fT~t@GAIPoqiAhK5_ygg8Iao)$>a1HdV_z!t&)g9$pM2~)LFE}M}V7Ey9r&6E||dF z%!*lUPZ5x)Y>j9{yRn>IO;#9o!+l5?-Q0BjdP3^uq_<_>ct2Upa?g@LFnk~nuvYUV z9V7)hh6%LFVpYzIt+75a#WapJwBJH{05qErgsa*%SfBiJOh1BUun_B0#pNQb=OQQw1dUXWnp{^S&C|5 zYH2#kKdZ`RKbg+y*LXKtu^`BZHy_F#qNuqbh-@hiN;@zh?TwT2mI3U5&JccSG$8UO zQ`&IRgHh-4+DP7d8Wd#`+JL19s5gnAGsZzTl%3|fOnscr91o=A@KocS=FS8&adiF& zBiE+CKk}sGJ>6xRBjff?IviN3)9T$Cya5yn1GB=27;M6tGnvU zX;m;m#U(<8^9_gkdsL28R9;s7xprW7 zc2+@|GF&3_i1Hc&Fy58z#Ir2j*z_@&%!@FifloHRs*6S$ME#6}7c>Z%8P;rQP9{j1 zSjAT@*g#X5OuBC62M7mdPeL6+&>{hkdk9j9Qbob=G&a~{MnBPN>LAsxK9mZK!?2bw z2ZCOA<(a4jG|xmg+QK`@o!0KstBvkjr3CQc|LPs|jr*9R*^XwSc$HPeF$I$-G^dpJ z@pezA+5E|5vU{58eNh+eUON2uWTF|^-Tq5Qf10|!ai+6S$mAfc(v|%qhaZU=j^B9x zo6k$1vZsSC$=rI9wSONy`l#>@4!->5Xri8w$uh%HFQ8JLoTjcY(+75;5 zekSqIG~b|+q;!7p2hr|P2ai84><15Cy0&}y1d#&#=Xra=qpy`4O*>B$_w<8D2w@wlN@Q1}g0!{jg z18Neub?c>TKXvF?e*p*o^twwp`)A@nt0F)5IaJF(ZpuT}0^c|PNNqEw`q}Q*CpRJL z;C^=Vf>{_&2H$*@SN+-i+t~}ufBZM*li7d4B_xL1w{FmapQUGifi=2c();q$BJ=Fk zpUuLV`D@*u|LCSQ@93Ys^$RkI@o@5j5R=w#zh;*=^C1*tUT=Kr#;1hwfe$1dtJG|A zzxLXw$?D}wb*8e3t{0D9yngf)wWyn;4i8zWdvx#Q9WUSBJ-GVt;rm~|_7%$dge#0DuM%Z&;RoWR}T*C zm&C!Lx%JVv;K10#kdoK`t>5__G;PsupTAoVyq8A<$b9&)ACY-yOe`K&D4)c2;tH3R zJ?ZoQljf~AEyb?Y(* zdv?#LseK;smjG?$ZP}XUBXDs2`q5EZ-FyALKmP~^SFhf@Vc-9y*Y_OIS<-_twBr%V zfVdI*fP-yNJmd`^ttHF(XKnncuS)@yj6k=3%n#skZq#LoPv`*xizv*Agz^3H2Ekk6mtApe*3~&M^uSs zasH9fzsVd@ZcjV`J=(dH_*k2z>(;Caq;~t>1cGf$yO z5;L9&h;(Gu1xMV-t>h$u=0BPqa|>RDx=9i?G8RDtKO%|IjIo??zR-M0#n2-w25ARf zW9F{2j=~*`v)ni92DVk&nKj-y#RhD!kZ_1(7Aeclj~Va|Frl?ugYrB!X@ml7tg3R% z2B9moEHjJHCPREEQG=LftZDWIsxhX?i0MK?)IbTyJzAg$xo5Zt29YRQ^m~-DsHtMq zhseeu0eNGXk&U!84lNK9EMY*CjI*bM3Bv~++fK}fFIk|jBII80}_xS7CJ7VC3$PISo58wbVdl#oD5DTg>Eu_5YjUO ziU3$29nkAw+#7r9p(@G1$jkyi{MT|RSC|p6-}7sr>J+vI)diXFd7;uSffNt`Y|FW1 zsY!9n8@^#~MA7xO#HJZd&r>p4n;+ZIFy}WC=N_TlPNSYFsF2KRm^K?@gP|4RY!C>1 zKJi#1m&=x|*0ccO_VQd>Z?UZEyzg83vaB1?>ws_%T9&T#Y1kJ6UpwQVM=;eDtl3+-A zt*RH$!W5}t8AS;5nzw3(Pe4e8hs`KM3vnHm;rN)jK|+9F+;M)qTCCP9zu=1V;2ok5 zw5W=LJPx*A7c~8Ljy&z@mhG&er)v09Y&=7`!dQ1SSAAWhcd&#xz65r@oiL4c%vxfx zqCWuCWYZ4T#t0FgVP%*>$>Bfu)25lMNTQFq@`SRRQ*nY1ye;aF8kRt-8akxQYS`F? zIz7ry1xUpaMzhF!7R4gv(i9}crZ1ueL0y3g%oDbBDBiI5t2tFTu&A27(#E0&+c2%c zwcS(|6K9it*?LWJ^h;%Q!vgBIwO!9Abs)BYX_d%=DSFRLz(7uW1n*%<>S{i%kOUbm zjrxwMMh}0ySS>ag-y{c@2|5`a+-795+tftQby`%7cfujNA(&ZkJQD;HQrN0k9?zOB z$2igACcT-gxIP{95zjC!MHTbv=~awyyj)E;6Ka%1N53si!L0bic_t>h+%qA#UJ%ys z6JDI^s_)S4J2FSZQ3kI>ZJ)XIOq6(y*i{AJx*|N9DE0_A^pE|SXU3Qjqi(N^ltzl} zGl_y>JTCN8{6xXrisZ(}!-t=LxOabN_x|_Gen5kJ{0U=z`OarP^WFTf{FQz9UB>Tc zu;bq09OrY-?d8Q3rZu}ip~eJoEi_x3oCn&kiGS9rvbnfXDj#eM(l(ie$cZ^f`?w5DFhurS{ z;&;CDoroVfIGcGm^>^0a zIpqM{gM&LCU$6h++UOpyHSfmXH9vu=owQ%uNQ(c@O&8bVj#7Gg#e6&a6?%(jq4EN+ z^M3!V*64mM!^d3t#ETh5Z*D!@sK0ymYVv>9d^Jk%&mOoeFwLMnyMYuGegj64zTa^> zm0el>%Y9$MhD_#{4o`OXxN)j@ElGhe{-*Nyt&>lj$dojhVEGT0|KRDs&g~=JpQatO zX?7|{w{ZP>#Iahtd;4Q44o4@p@_m7I!MfAxj04TWC5Rj#o{EG0tdGiBp_*@rSQj{u zEPI~|-Oh6moUcX>2-umA-DaDtpv{AfPv`+$`}3p$|Ll`RqD`Qkw7OAz_nPTH0Lb^~ zGl%aUgQM|NyJqCUS9}GSib(Q#n(NqO_P2tUJ>K8-RGK4UJJ2A%J&1$Xi2Vo$nqh&1 zeHo;^x%*hg{M0zVKxggv?2CgxT`&`Mk%Oy6uI53>Y4gEhEPd~NIHNOuBdT*g`|rk? zqkpZQmivw zd@eL%B-s0>cqzwq`bLfz(NK-)2Y|_XLoAHk6DV%f5+o<$5^X7Ak8u>h2#A$S9+zF5!tIMmSf$3p>`+9CC=Ph08uHe4qBR_@`Pr?z;;+??~nDs_ZPQIdfGR`xK+ za=wE10W!7Hl!65MeQhVZyy6SBuNHYk7)NJgNy%$p)x5 zCjsS>_rTWuX+8{gLT9~lQshpU?4B;H%8z^vyhj>t_b66aT34$=1{&eu$+NdLt;7ys zLQ_*q6jL{aj|j1F#8Y>^QAUnpI6ayhi%{*?N6)u-jC5cu7AuSaYUV!Lc(|piDB*Dw zlX3*~rx#ara)JT4PHD;R*y^^v(L@A4~)Ez`8Ac3&2B&{GH09$UZI)<yumdnAs$R1Y9@)`N@qBiFJ^V*%~jwWLSQSk$OQ?2Q-ke4&a!^y&@Z`A325 z8V%fy!-tFyMDHl}fj}Bu&+%FTM{t~nTb65|J7;03aLl{YCQD0d-Wyj-LCw&X)q}Ou zve!)X0t`{NQnX^{oyi=&0s3SocY}jJd)ZAhviR=BCu><&Tk$iCr=#&RwVk6#W0>nu5V)|Oq?WBPgLdWs{r)_GG9Ug~aR``Ym@=I@Q!$G>G zajX!@ryMOqOUT27qk`DUh)HX(t1wp*c|aq`mR+;zbbpjH&Py(*(~F_h^J?Y6^n8;; zu#uH*P+;Kg6k;&!f8e=-8NUqc)ttkQOE;ro%=&?%Jzf`ToSb@;G56AJ7j9!}QYw^b zGZ=(uf(KJj#S>FgY5GWvKv$lv7TXo2YBIEWd===EsDRSiYT%4d+xPtv1+I7Kk5LPH zjvMkGWhpeNfsEBo*mMjVe_2)>_q}IsD`QnmtZ1Q;J+ytw4E_7m*GorVwuf%D+_r`{ zh=wJKh3CL4dhaPqtSv9qbl})tWvp&E%V*j5B-Ug_3qHS$f}Blj<0&)dVHZ_{c8^`w z1MY_HE3|^xg|e}D>UwK!SWSj`9~MN%WyQtuq(?J61la*19nWe8 z{?wlXkwUcL#`jjz1}1G^ZN8t4fQ0^8+?Xx1=O@E%_l$Az_pjIy(IVT!`p|qp5)k( zYd630j{p8oyv+Rlm(Mtm{k;1e2QQnjGp~eiawhAWyZjsn!MjQ;dShxlZXMi;9NZ{w zL=GMU6n6FMlTXS#;uxY^Pu{pOxi^d-syR$^pH>KRG#h?doSgD@?)5pZ{Bb)0toVdk-EyIFS44zwxP0Xr1cQ zf8%}ck^8}eTeoyl$ExWrk;mZ~t&rPB1_D!(V+u-Hjmdd)B$`TWTK_Hood4?r4e2)iF{w0O=)*x zYb8V^@d|0xv)sn~Us{Wt@9uGk?D-V&eEPf_+BZk{We#+FE*!j%e#DN+D=npTo&)y^ zoyG3;H$DDl_w*5qYEAh%jt37o#`*r6Z~n$_yqDu?&L~{uV7GhmMHsjczIX4f8H&` zy*rwRG3rTto<86Jk|PH(>*n=;aq_}R_Fc34u4?IZaWFCO;cdA0@ZJIEZk@)BmQ2r_ zUn*RNY5WCw(rYJEVFka0rEnk~9hc%rGD#SGhzUvOi#!CPE^T z?5EFiwE59I*Z59x&Ma#_WCGUt#BW|&9hOpwT|Z&k5F{YOq$v7b9W$@&WAO^yLvM`3 zK61GCje~+y2NusS@Mjs9m>gT_BaZwGKR@^wsuEQxSUy9+X;_;|lkXaM5!`4R!xt*q z#hrd{1tVuug^RAfu_jcX7^7(X5R1{_*Yk61;qjOhX3$g1%2c$L(O4J!v@;HeCyphAu@41+kJMq#(72>rK$XHG=U_smaY~A%tl%TTWb=HAJXLkxQ|ppfT+AKE&%}gG#p1O( zV0TJSwYi*nI6^jT$P@KfDRfry%!q9lHkb|UROKRr;fm&fY+Mb_Is%%AzJ;hBI~=;hBYFBRkSzyS5YW%Noym*;>wEuLGAU0unr?(Kt7ypZ9y*m==qQLy z7`z;MKWT}SL9e)g(uuc?H0o6+y|$+Y1&rbI%xth{G4EJF!fsmMSG{YSWz8hiy!5>i zu3^HJXqL;O99q}*lysr8v7}0BlxFM5PB3A>e}Iml)j2Ob^(zY`E1yUI{UdfN<#gJl z`d|hJ>G%`^MI6bqcUw!{+23vRqM0r0<7HK{(h_;ZaRpDPgSC!Kuh_rZ8QzxW7!4sZ z8G<-PWTwYe-mom2TRyz9co}q5Nb=|HIzv#WBv&o`=)JP+)?`cOs;JnF%kIw&YEYqw-IfTt<>t<0KAVxH|Hz@HoP z%;8&@xgAy>!EaU~SlXWZaF^_L&Y5UL*FSK?@Osj2S(I5Ky7fb!<%=ad5{XJx#fl1Q zPZuE8qzNSL={0B-^Z0g*IEq(Q6XpkU9V}g0j$S9h|J`oE}ZyIm|AwH}LA;(crd6@adRzTwoAyCtFs!T%!KMM%^ zi?Z;+n{F{D20=E^njoi*y<#ffFcbn(oO&_#=FHy%yXPxVkHexm{ z#ZP6O0h19-;A>_W;4?yBXUk#gS1hO~IXQYYYgh&A^^WJBbx$jGz3nhS&vx8a%-UzZ zoAm0)*2crC8rB6EQ}cMjK^%R{E2St*eWU=3SiUg1Ghu_E?z0)+W#(C^o=vr)-?Ma! zWP+2UXB#Gw49&2L2P0Jz!ng6}4$`L~y7(6xLaghmln>us*2Ox?i~`HS3`!Lnd6tDv zg{8BDU*pbs8>`As>v>1AEPJ*cT?qU4D^3%@)-N#SvJgy}CJKt|S_*as*VhS*y7|p#~@kQy10?y%)PK0OT z^L~DRbe|cqs7EJ5=?kNGc}pHmD^GWKpNp$tnYTH{_(6+bk%^e5urq#E5UcT`77al*lYYsp3 zBj1+`>*Ldp$9nzUFDAD*72LdXBNpA^kC{CO(f|MBM`r!^NP%^MX}_!1qMqV?;ZEG= zdayg-oZ7QBto!gAuikj|kNxex_Fdd3yOS?`;m+^L)N0t>UG7N%?w;H|k@@xE>uElL z7;-tt;_=AG;X%1S2Vp)5)5-h3vP^xiA3 zpy#fd%?q|b7I)ci#rAq8rE8Ho6c1us%Fg?TGyi=!<{ixo2sCw(Z0UK(jEiiO$%j9D z-hXeu_LVPx`5XQIv}MW8??j~Dd5DaXYAmn(yGXM5YD|5W_D$u6^a;;EV%Frb_8$DBEwE-OCjzRJ&J{@*%9fneXU(ULi^Rk>bDUFynjz z&L8-5AG<{SvNLrHXMOVJaQc{&Z=Ia{k@p=Qo_y})qS!Y}F^-Q*_G*q6M_^Iz6;kB z<#Mgz5p9K#0q>)c9yvkAxZuasnZXwQz#owFJ6-%e@nDEKdg%E; zLcOJYyb1U#C#dHVgwd3d?6qb@6jfYeCSUA=oYK}H(?%ENQAuP=eB@g^1HXohAh%)5 z9WqF7tn9?nEppbwXk(o2q7@VRY+Aeme`x!J2o%YP&j~tAJMh_Or0YE?6EkQGY>emE z^DE7Oy`SW>V-{mB+`#I86bw%1mUceRRsF4}HO$fi;j$aPIV^nM5owHw%UjqjZgL%ns# z3e(Qdr{#9&8Gi-_@HEsM4)((a@1+jTMd(b%z>-@&*%-U8w-~m~QY`jA zvYV4(Ie41gd4Gh76k~ z@#t;EhBQtKB0&{AM{G?XRC%XjbK{L*=cY91^-(k;5%Ls-tDodo^rV_rCRrCACGr-O{u=zaZio$x)Z0 z4&=}hy-;JUoP*@lQFjzT>5%D-N&-zzK8O*mkfnxu{7Bw(P3(4tMypwK4@D+D{L(e3 z71d_6jG}DY0x<|OJu21~E^|kl;ZPMzBUyG;&7fKnhrYM%yvtc53jq!m)X6(FTjnBHX z9nDJx>}z9@Es!kMwJTk~%Pr{zo$WM2ri@_#wKADM1CBg8b3_}h!6&aQppNBKBMwqp zvPl=t%SloV1{v+-gQY23R-2TD#=8Q%q33)2T0GgstiZdxjjtWk34&^TL{ zV!52O3B=M{GV#!v)wAhju^g7$<0ZROT{*RO2+kFj%y5u&$?O4B3PbLSy39Gdx|-Dz zIQ1!Eeq@gNjneXV)iC)HrcFMhO;VqE;fzIi%1G!DKu0IpyIiqN9E5yp7iB(h59Y@8 zbcp?W#X60e6b$ExvA7^BRx?!Xx-h0)FOkulGD^3BbXsT;N>LSy0YAI6c7bn0H>C~| z$Y@Pj;v&|6stVrJ9%-vm0CmCTIX$an+TwVg`vwl^=p3i0d6JqgyFpWL zNTRWYXhIb=YQtAz+w(nSR=^JQG}V$`3&Jry`jAO!5$5nnz?+7{PJ;|{cI5Jz1^?9bal`vz1w3t|2S% zCg(fe)1)|+T(xdZhyn2tLg;YQ!{fQ-wJDZeKc99>PgdIbY`#M5+j?W1pXLJ!-I90L zu~I7MG&WmI=LEru=NEzrGZGI$(riqeex0HZs>YUgntH$~Xp^C5MT;+&s)d2p#(b&W zbTc-;Po~~aj#u#A`C)bprk$=hCws-YfE|Z^u^eG2y;G)Jih%fb7`PXFnc03=GM8g4 zUvtipBEy^u#YacSVS#oA$x+ey(46)4W9ux7BiK{Q_@d`9J#IQH*31D+eMWrK73Hij z&T%&|%vRN++W75y6A6k|;Y&`FsyG6&XPROd>|}}bz8MH3cE&3);TXKh83UBtjH(QA zi@leB0~h6hP$71X{i0aRX61Cj#`;=C$4Zv2rYoN0TsrG#rVEyjxDJ|1b>QrLvtThr zm(Qq$))eyvPx>O#(Kh7-oHZMzar4CJAtP4UGta0WVU);2che+yeHtF|!Mv*P3+A3; z^xr@5kAx$|g!jxo44V31^ScP=B{YR_v*XeG|DA8YuG=ehyXMs=uRi(gZ+z*SC@6Kp z%)Q&(Q}L0HNV|RiBfF32=8mT(Pu*0^KleKydqw88=U;kWW>GvJ&ArsdE4eLv#$F18nuU~)aDf>e|`Pb+*Z%%GXf|t%QYPUaf1PA7R zGif3RIMN^8FTM0?JRj@9tp~RhevivA zbs7+vy_V)CkWY^ue&gYFX|jd&;O5ns^2@*Zw|F0PuFt{2!-o&9zWJfw{XV&0>tE|- z?vC!upws8uZ}Uv{x8k5}#ld&Wr=HSzJ8+;agzUbQ20hJ9=r+{h8^d*JvR``X+O-Ea zuHF!}&%f|DgUsi9>A4?V{nn3sF_&AEWd1Wira@LVFVG1}W6s3M2EZC$?ZpjI2 z1WV)5fWOEp1|(S&!bGZwsng0hk_!lWT!JY19)4fs;P9|0+7=GXWA`3jAFdm#gQi3$ zJ|ZoyHI{>`er`Q=3l0vLL`ZNFcg5~rRvk*BMFBj zCogaTuxQShVCtFij0I;-ez;*(Gt!DGmnZ+C?-?iX=f|Yo0ER%AL6*y4@yOs6`Iz4x zG`Kvj89&P-C^2{%u!S*Gjdw%}<5;P-pxI`_vo(EFIWO5tpgcq(Mg`4!HF^46&oeW* z^rTK}16h_L<~3E}aw*^QYU&%$X0DvMPw5{v`hN#@fP7ow3NpoR`$~e|$x?Tr~>YT=d@>-{6gGUWp#;Q!twK>gj%>>4Pu&a{bz0a#jKV@#k zljN~>8^i0y)jdlzmW8i-GRSzB%u;BYU{kiC8J|v1jZP5^%(2R(w@ANGK)_)I<^~n! zg0kv(xd)2Wo3?28ozH;Bx^| zYhYNexe>^MqwpFT9pM0Z5YU`Z7P`p!&{#NBtTNXlv(`yx%3-!_mF*m%@=i;cm>S7- zZt}FIfSA@=@+W|q?m}3{(y5=4zvoMYFqw`w_ zGhH^hXVwNqTbMa)q1aakzj0td7@s#(X5P5P?eELV=3T`HgDYmOXhw$wtIO`26V?-+5y24?_s z4+x7z=p1-!d9<0NHDo1bbEDFe`X>qAXkIYSPbJ54ZKE!Hkm)aQU_1pIsIV&M7FvYE z;8yE-&AHb3abHeoI|HIz&J^KvvmqCAu28kMS^5C^s))iAb-REp42DH$F(phL=eBA} zU-P!GV0lezn1v7)n3n->0}svy7Vi(ov!U#()nXvAMb!msj9t5GF)&{lJP8@Rg6XJ^ zvJAY>B`fj*l|O}}0I6wE5;~v=L9epR$Mj6YXPYI7YwNOIY?{`rSM5UcCdQJYYP-z%x@5FD;xem3>u9C<9+SYNj(}y> zt4)B>W00qdP)=!FG#|g5acS(}V(8TLtarO>aY zi+th;+^%!mGJO#yp$)laDUPR;iKhWMJMjfyh-2g6VL9bMK;B_3c+e+h2)5tWL;M1? zO5+Z>k@+alTAz?Fva`8Us|BmKy_00=%jgP>7?;dQTY+~{cykuc&6OvtlztBL{-qP1 zgtUj9;{c(*e)q2Q*}M1NeXsP+Nw+PH_g>2_?2mt8`URPH?;aka29e1EZ&akeH|e&e|K4l4Mfu~8Ph$!?rw2ti zXE+~5nd9dUe@?+>e^!*@+=Wu~`~!WkP=25eDE}`H>vcM@X)nE>pT$5a{?`#Sc29iz ziBC&v5z~)<{Z(|?ckcY&?|u5tr{n2SU;En8?l1nYzwq7f``r({srdwjedpjiQSZDz zvFPC8$3L#v43{2=zVDlf1LVoK;6QkLfP=qm-0qEG;6B*r(n(>DfBnV{_@H9n zb?03p2j;%t{_OvrfAL4Y^`8O?yK-StB?ap;QNK;qpwXS9Cs$K|)%eTXn=Qst?67@VIsdO?`Ac=g7U*PeVyCp$~Nzbur>U7GL4 z)eOeHavCm*`_#f{xpDLSdCbWZv?FU?-@PAGvbTISTZHomApHux2(v6#uU&7%GbA(3lxwFTrK@LD;?Qqx2ht${i`v&pux~Fa37H|L%YH zu|I}Te<=C>%U^Cd?%GDeJM+4eMS5ovW9A19`QiIw9wNe}2OMxBS2~UAe2}E{AO9eC zzB=VhF3sP)^iq6Z;!McD{I$PW9A`ZCx2^8n(y{zCT%Dxn1z@rb1 z`Lew?`N-A1Y5=RTK0Q8-EFVnoXoeoYnsDWo@Lsx|nnAtQ^3BfD#F$vFob3tMI&$2K z!P7W4_CYtFf!7onBbtlg<%F~#=%E4CoVXH%bL=F~UnZQq^~TF>e2YK$!H@=nBt56j z~fl@${o7z|h#*0T1I8X3G&c9cU-8RtHJpgCpLD9!ktg>D)?2a@Sv z^q6`3$QnE2nl5r@nVsioAMR>EF4urhE2`1K45ss3&&kT)j;K_|%-O*+z0U20>uHS? z*Ls&{9Q?av%uBqCbOl+6hKK`wtR@XE8F`^m_NWV5MiNWEu3Pk>aez_7ux)3EUzMv` z*4}ltm@&3$JPovO(0IcvdI++;@XNesVCvAudve`7IQE)ZNl=XDnW6EG8&oC?X`^@3 zYjQ^UjUp6vD%HIk95QfmTox)pwAu&(>>{Kzv_hjAYDQ5~CUM;q`6f56a8oALyR)R; z#^xxSR62UDQrhqI-!WO>^9p%ypn0}+Y@!n`w&Ha&&T%u?M*rD!8EL9XD4Ss z>_Q}4@^(17qoM9K$;V618C$cCCcCzNv8;Sk(hPdf;MipJOq&18wv{6-52N0=HJe&Z zKEPOKTV4tfl!G*hd9eT>uXaE&2nn39hOM?~1IkUZP)&P$*|E_?ee$Goq@vjih@%-V z`o>kTrm?uUW}s|n4;5=UCR8ai5N1*-3ns*(l5WtH|d1Mi=I@{;IX%I&|qRW&+w^t<_xRcUu(k$)3MBHST>{w>q z!nUEiftc^#MY(s3R;FPilEK4)9F z_sj#(%FQHPIg_;^bTtvX_>|P%BrmWNJd=#?-@DC+qYX@fVsx^|4b43T%=!*qn1t}5 zM3)}%@H76y563aCTxVbz>)!s!+n>^nE4OYv`Q%4|i?^(t;%2*-wYya3z{<~|yJnH> zP9tmiOHckM7%aaNP`Lc}I%v7g?#0_L?%pt!s7Pjb_~7AHX(wO*)Ia?Xg~#IY8!R0TGUXQR zQ%0`2C-(&oejwdc^YGy?NRxQ&!L?h`dJFF&h~1|t|9dYQb_ z`+vnL#!D}?t=uvr1?{|kf$~g}uaAD?`+;5l^e_C*^w@XIZ$%$GFF>Lo%rSkd*Da+o}%r8DMUl{tXrf$|L|pay9mmeqcxt~+Z{_N2KK1l#FaB@6!qU=(!`t`%`Mvir6Y;bpTD5b9HBU`${>HET#;+JZNiUT=M>zV> z(fbW+zNw!hNygEeH6Q!%izXbTI<)C5X!o8!`Mz&|`>S6SR$RKkYLZmv$k0))+)J6X zk5@U7U~=>3MT$xOR5`pz14HrswvsRPe#Cxu0MgDPF^_j}8OA0b*kfpa0m+ zSvUzNAvU1*EK!mrN^_rY^~}qclqfs7iw_65-gmmX>*rHXJzZT-Jx@Jl&2#&0`Oe+n zx!aVN_MbP9ypFgW#&_pY2uw)cgul^e-$Vz&H@kW^Z;aLz%*9jPE_9;Q>eHw1Jbe!k zM0m}w|8~#Z{cBb_EuZ{9KAC^x>Z@P?9jH31^T8_tU_3*7< z3Yhl~Z-l_y^XzT^g@OlA;NQsc`6YeFjdb^t54-hWO00gm^7V)*Ew2b;p6BDN8|}MG zxZ^X3Iu@Tz>jGglNtCBCzNy&vWm@GXrdJKKq~;^1atp#XPVuw#Lv0dX6AI>8>7-vJ zmjair3YSY97bePp)LIEbNnBAVe52(x3&6}IB4JPI`pZ&yGO!!b<_$N#5g)Vf{Qlj+ zn?NyEMMbyqc>sv+DX5{i&{J9_(an&Sp$6y!p@8G+hP#Fb*uBsjq%G4a*aVL7Wa7lH z84!2PbrWYVd;qHc+>$0XF$KZw5T>C>5Y;Dojur8(^GtgQDUB8`IGcwj&DwE}zbF_E zE#NLfZ{kAPRHTk>(s{Z{Y4}Fh7~#N9Iy%Wx54?pR4-A|LB3(!Nv^OSWX=+!yUZ`!; zZ*0pXthTk~U=Y)U8ZZ%g+s1e%i(W)m7oL6T1x9(*b^1H#^wiR-7CD;Qm2}U}Xoi|1 zO`N3-gwbnyjo?p{DELITfvj_^B}T&xXOa%aJ?>Hqv%t!C87KXNNfB)V&DOcjS)mePL0KZ z5|V>Lz^9H#?TsnS^U&r9_$i0Q1(@eynq>W)RgHn0rDa{TTG7C$wuDuVZd0AOi7s7r zQpKR5JWI&Sf)9xIZd#)VQG3>5GMeE0!1s)EcEWNU^Zz9pl4gXwnMrJKIATKT4C@nc z=7TzG{Rjb>^&Az8fo%^5pO$94bSNQk%%>?iD@#2NI2+d?o~KqJL6_N({_9f$><;5Z z&(4z3(l~TXi6=!5u^r9tJ7KhTKDIJg-kuiO($qN^TEoH#YStt5XG;zf=BSLqM8%yG zR6=+}y>8czUIYuVn}`F3fnBgKFw<0uUkHv*e!hSwVW819&>| z0Ep)3vhd>8V7b`G(Cg=Ei4>QFB_-{)`ve_s-}&caU*D46&dc6U|6f+xiQT| zQ*yaZ+qvlAt+8g%SnsG5y!qJC5G@Q;)k2XJy{y|IyKV`q;#ycN;|-TyO6fhzQLVwD z_Mi4R0jA7R6&{QcDZ)y#=#noqsP?jeHV(4;5kyiVO!p4RG9<2SXK73s2xnEr5B+#n zjxSj)pn$aXdLt1ygbH&PA>X230M}2dpqAoZO7c&%m{)XlOmVnhe-!Kou3Ema$1%EZVAsg{uVQFhWA5ELM(&Wb;Hh5qgXGSIV+bnb_;_HRV zOd*IRYl`K3Fz?yrY)(l9WSFr+SN0p{ZUzB#0Kp!tVp%R7opH;P+xTK>4 z7H!%gqxq!Kz}!qLj(4j@y=j%?qvgQ*DI>yy6@WoPQ4=V_uBiazBWrIO&L3V*X0EpL z*`TV%L*FzBeKIWK3znGCP3oumiKqbjOD0so-g_QNJgLSyD2iPgeam9eQlnCmIO3Xd zk($afUTIrj!gtF~45$JqN^6W6LAvR9$qS#16N=_#ZCa7|OV_>7hnuj(LLX{2{~jApAt7-7!!T-@pTGOJV+tDb7gsw zbk3Yy#}oVJ?z~6R{pm9Z+28-bYVU|Sg9!cV*{i!h_G7CDICbf^&)xgE+oGRxvvb?*-r4SV`8&IN_F$Sfz29FAK<2JV#I*}q!`}G%C-6?-Wr32nG(P?@7p}s&v26) z)}(raC!h-4UE6n^xOC-Gv)Z9PPf!OQG194jR>dHK&j z)Z^s#(>K;Gr9?S+K|UZ0F+R*ChE2xDz!tuzH2^?SCB{<%-@tKjdp%Dc@3r=CfGB zQ2mjgS#qnrk70X44UvmvtUQDbMRxzr0o1kW}`d`6LI=&RNck_HQ1Rmk1?1DMPtiW)4A#M{p{NEhOYm!bLDCd?Fy&-!R_4U2D%#$tG@Rq7%H&j)6s^fb z3w&%v8%Pb2uDZvlB7RRoS4ZGzl-LFm3a8 zQ01bDY12{^0?xE8wRlpMgVJS7GYk~bV>$!<%BMW~M1gMo6XT*8dFRA3tMbx>O0}2# z>Va!4={2FunRS7K)*$U-=|TOG65@<2owFF{@ipp-iyTerlIF~^#1<{O_sCp5%tfHB zMURC8N`u2Oxyo<7EG2XZZS>4f&K9sI!UM1`@^PLyT0pz4Itp4j_E*4Z9f}6RosYf+~p3QC~uagrcD+--=2>ogPd|AT?H89Bdiff6?fn8su)= z$Xfq6LA=}!(cQ=#%CRgd2Yu&~9xv6fwqTNRf!B~1pk$7{ z05i6<9_4m+U;EsIW{@mV8zCENx@qhB5QMZwK%A;0VgNCjnm-Ze3=MoL1{p#`gI^KD z4p=WbNb71zVy3}tv^6zJnE7I-W6-DNUV}`0^%8jn&y2LV6_oUY~@ff}1?P`rDXOpvtpv3JM(rfxH zqD(Zs-GBvJOqUg{1#76;V)+}Bh0dF1kk4A)6*sYEKlltL5eO`0fSeqW`7rY+*YFwe z482k$Au6t|65@2iS3mRy(Po@yz(qA;Xxsu-nLwY6=jBWaA?TenZZa9p9OJ_rc0xVr z;J)WzX4bM-ob`a-lz{;C@&pVE8zSz6|0GTDbQ^zIMQ=**&-juIV#w6m0W4R`t3Rp7 z38&`vk|lXOMJy4YmcuFgsCn#Tz`RD$U1Je$4w4sj0vGCpN7cf1kfgw$0Sa_5NwMzM z8xf;C(x`{Jke$;vtWBxk5#a&@n-S7!uZ3&FN(5%mF$swwyfNG(shX@B%?s1in95sb z2A%KeqVc>>^aFfgud<5~o#xt6>Wv9y;oH6yxR5NP0=t>#BS@c@dDt&WU_uBGTrhdS z2%i})QlGPEk}g`WhNWrA>C6KRqZM?#avA#}%Tu<0AvW3?Z^J{EgN?R?_l zy`c;Ch_S4&q=v*p(6egZV}jMNh&LVQ=v(CN1oSc3TjC-4YFcxXH!4R(qu;h!xYh#=VsDT7-893}PV{Npz#9Uxb&~%Do8{^6_?FANw45!W4ER=-d z(z69|%FtEwKJwX{55|toE0}S#6(X0^G1d*!aNm9A9Vd<1W&X!Mm;3xXu(y6vn5ay_ zUl-13!GM3Ai|J!X7t^KC1>GYoZdMt4hCanr#I)d3e26Y(>YUYL2%2?*3O*@+jmUUP<218@--jd z>|jT_DVtBoBV)=7?|;8|q&&ZJCBJy|sO0v^=$-$T1qI~yz{CD^rK9GRIG9)e;zKmbj?6w_w=pmie`@|Rj!^7Hvt~CPfJeU8_>LJ9!W)Dl+ryp580*~>^;RwO0Q>QL} z%Urnht+)S(Ab1V6feRnLaQHLt``YMR$0_w71g9T0C>HO;9q!^$jP!`bWh+z=?3sri z67-+_SEHaE=-QR8n&dyU_Yl(GoePgXdciz$`4Iz`wT=Gy3yX)%*mN>@lmE}MyZ-Z8 zTee5HWh4@bdeQ*G{k*k7KAbXo>-Z)&-`#`l!E>1F$IgTA*P%}f7d*`F5zK@ zd8M1J%OLoma|a$aq^MR(dt6bs-pZyA>3)j_r6=)GX?!T=W5523++4VD^cyEmJpahQ z*p_92RcHM?#w*R<3M^nPLHFi8gD0bZ!^ItV-azmy5Nvp5^hly*cb-{a0fG;1V$%1% z>!W*c#Yex9W#9SE-FKTyWqeVHe|1wReES7+c@4ox_ix9_J1M@cLmqHP}c)vvV$ zl&;%juKn|CJVa2pu3ouvse1l-;b8T|>49D<(Fxw|v2-}s=RWY%kHbMnoLste_^$n0 z-{R)Pi4UAOuPj)S-y~D75JaFf<3EU+f?^l}@=MkBws3Ia3Fdzv`zXB^DVU|VPRlj z3+{-gsLrqTAg3C+@=14;Wq`S5Cv{h+rR&1cu8g_)nwFMH zr3(blxHhvuqL3&_p-Xf&Y5BPEIqjZe2|nI;HISoKKH6bHs@%-Zzy?hVlfb9j5DPB7 zEqRW&;pYAfz6u?SL3 zZJeJO7l42-{s2t^Y{3w#3``}0$p-=8oJnEbP#>SnTky+-tjBr@o$5K)sIor5+>xbW zdgW14ZmDU(^ned36FvHswyMN2-B+gY5plJ~iDyICQPYhuShNoQFw-(X%B-wmCQ*}x zC5J+0l$mM>e3%^1^pWv3Yg3M}@@AQvhJBTOOk?sE(5u2EZs@>RnuI(gCINgoR(W8< zbmw)U9)8~Qz71B{p4w3Y1;n;iVnZVT+$tO8r ziohUfUCzS9z_8GLbq&**I_#Ud)R~~!7cFFdLcv9)>Z1d*&14#`Wd^iw}GO zTmX%oG0&tg+#nsnrVWMeqD@h==LFwgQjT*LZ`^p4Wge3Oh~(6Zpv|UGSe;98f)e0O zSoMhox}bJ@3$!HmAeNQ{FgutPHDWHpEejY>i-8*$u-f2(#?b1T{*<_#Tr5^h0_Q%l z>NGfsPb946f6STh#N zu$^BE5Bz4dIRcadFZT?GG^wt?Y20rJ=B3R?bj!hEU zUf)fI0}ngfA6uk6HS>3^&j377*+mt4wpX?+H9%8T0R>#=gasM~erOvh5>{Ij5>akO z#yS=#U~n93FEwxH)QyMm%EPvyz`=}3{&+CqJ)1EonzZe)k0PZBj;*fn$1R)@lk-u3 zG#^nI!tH*+N{K^!#!vyt<1;-s!3c8$eC=4lHh!LBHjZ$3^n#VZP&mDN<#0ZmO=rDw zG?EtySG>gIda!_JF7p~Obw9I9`7@X$z3uQ};Kj5s z`+l78X;Ps6ID0B7&4>_?O(+P{Cz2SdCM#=oXs)yJ>8Ut&5&&|~$IXoVaH=r?)tr3E zR^YammZK$vQ%xNN06)cf3riMGs*<-DEsz>^A7;IxHMye$Ku?B!#|#5wBUhT-A*JkR z#-VH@oeBV;lr)S1O#t#L2Do5jSvxA6K`0KhSS`l=v~hEXB{6Jnx69dZ>I=3}j7J&` z`+hn1?C|K79R1FxbBvumdZzAGlX1vODp&ubsSrVMW19v(`skgr2%?t{7LCt_=Pv}l z1rWN18JP8A3|W*QA{ZMyeirgD8r5ktg880#*@}Y(QsrMZ1i2d}k)`v5XX^Vp*x6@VKHzHM#FwiZ$d{&GBRZ|9Td|@ zCL^kyY{>8cG4j6CP{E{sE?k3!t%pZW+vynkYRl1JAxt+Va`z?GR2)dKOvZJUv4EGr zvSNkNVC-?}#+l7imj$T6WNzft5js0Z-&GmZm+}cq4u<8X9MVfwB`r4K0+cx8d{#I@ zdaTw~m?6NVJLEW|k69S;!y!XX+h*f1wqw+opmJ@DPs^sa%qP8K7)lPh8x;(yW}hb( z2fX`^lks`?KsXIQS?ihKskQ%cd^xh<6vK)lIh{F4&^wH|ZyjEBDfATG;doUbcjUV< zzDuR+`ISdHjePp`c(l>A2=26RSaR%6^8Ja`C*nN$D_?o$n3COl_TIjBmTOP9q~gy! zbL`mpPv8EoBdas;k1rlNv3>R|v1cVuKYQZr_H{)ccn}xBKKEai{~Vgd2c2f$vg_SR zzCUsK6ESjYtApUSv$yrNvs@B-{l2pGm95{s``rWN_d8o#f?#*|@nikIWU{*_cDJKk z+SUK;I{!`N*9Rf^0o_M#1Pq|}KUi~xSEc5RQ`=;_`~g^bc8{ODdhZ?xIdtg77kAHI zWi$EJd*^@hwU^G^v${vJa<=}je)(TM_3D{3NU|}){^Ea#u*yH8_&T69{1<^b2fA60Eugrt^tbCdWkyAgNL^-v2(mZ?sHn{uvyzj5M z_{gR6mWoTaT>m}3_NCv*wd;9TC17>#?&eP!2jTzuJOtID^`Z;ky726+r@s-oxvi_+ z`F02DkGDE$PdAeK%HP_OWjO4i@h+@SMeD6rm#V8*r7^#UQudJ}Z~MR_kE||ZhvD?q ztKT{v*OJKjo=^S3H(!6@?e@;A;yjJH^UkfS7mf>pqiYD>Y<~iyKFdBzFR8D*qu)5n zv+S|aUr&5-=RJbtrAt-YN@HHUt$6209zib7mh86u7PkMo8hbzYdw;RIa@cG=)IF=T z3l}dur1ZMKnLDz&^G>Y@T_3-<_rl(fk@Ho(vslu5{`pJQ&S}gU=o#zguYKx|Z@I8q zpB{*iZDn86j>6WB(d@@vmKHn`*sY^6p zHH{-km&eQXyYu2U2r5k=m_4pv2G-qycSk5=~+lET+Q(fnbim&0;XP(29qW| zKWARy=3VIes-k1@hExq{s3jQYE0y5TB-~kU zG`XY%HK)hC!Bq~&;y!bbS?U_fK(CicICB)zRP!o_-C|s_p{9uFnabaHHPd{t zra0&$nb+$hlgi8w7qMOk5DfsrvB1+S)nHUtf~bdfnx@am#2V)Gu}u}BC=s-nBEzZrNNi3s6y*lLL!a6(os6>nOo8)i-%n=aalJ!4yp)3MVse zz%oW18tloD-sOJM=6Nz)xS6-!YWWE3k?{Pk=EZLftQ9>y0(T%!%RN0wu~Xx`nK>4Y zj0Xo}=K~HucZ!Zh^^BR#U?zMffShQQ0nCu|%^S7LHE|Y;##p2W%B)?FaM~N{dUTXx}5CwT;R6epD_?Sjv&b zH@Xj4-^_V5<%wQme{MnH?4CB9?rnOm;DAE*@+OmoOw&yhpDvneJelS>BOkBg1S4Qg z4)_k4i>>(g@UiniUGSq%uXj=&=oNiiJ8wA2ob`m3ac)Yw z8M@4AfDkidO&g}pvuH476^CQrMo73TwAGj1@%H$+mUr{AYFxGC4aXW|W3~T$jvhkE zg2B+uWurW$u5f+zJf#3&9Vd!=Uf*ed>H%Op_0T~eJ>5J z5!LT}jKARm1PRV8n<=#0$L>xF(@9p5q9!a@tCfB^q4PxzAvT;VgQ96&#uP0$)_GYj&jz+}v*6QZ>(a4GfSM{iaqTD9zP#&Q z8RKKvz62Z`C}218`xEYXJQRyE>yl#n7*6A_b6t%D?OwTZ_?7?oAK(A}uRV3DIeg)b zI-J+CvHSe=>93o?bDe={otLb?efP0n{PpvCklwCjZlC<8FT8#li{=mh@yoB>^2eWg z?cCvWcj>o%V$Ba}zb>-sJb&fzH>%_3PBmY9s&^dQ?Kg3fb^^gW#U05`bM#l72(|Ch zcfB|2R!eVJGB^A7Kl*|=l-@1B^r_y1zx49)!^iK^4{Kbflu5F48I(J_d$IZV|K;A^ zNgOAOKe1on4L3A5uvZ*Lnq#P_{|guX@WSdj4PSB>F0jM=a%a8#-0>?{R!0y8UNFeW zA9`qyjm}rD5PI&)@mGKMu@61>)VH66tv;>&&rkfxV-N416$D3)oWvX)5FkT+bGI_* zW6eVR`IU>Z`HrJjdfCX^!GgN(&mC`?5945&VSpk8rfCR0*Bt-aFZ}Dl2Y&p0?w$+x z#Qo2=zw<{2>3@^#nmlm}4Ug z?|9^ncMgmS@YTQfHCSnJ%H)y0`OZ$$bPzm>Qy2h5u3z_N z>&VvX>I#jKE`1EU$>k+z09)lN$m$9TC2LMs`w)Q7%3Ok|OkB3?u#1-#-0!*lKY#O} zHixjMk^tiUswnd8t*K7&rrf0B{a}>`oUcMw4GJY|2u|H~>MqImQK#P#l^M8fap!8& z73?<*{@z!=c2Ju`*i%Uz9++fxQ;bb5jP+I%0XbJgNOoY729j!$1$u3kq0c6cNmgNs z1!;OQVWGuk;u7b@JIQI%SujC#6vO;ku{?W*M+#@*+`$Y`S?9v$24DA%pWGPkL-GXY z@Ku&%4Sb|@)sXCgmWdKCiA#(=P*enWB}sr`5nb`~KnYmnB{hzev4JsWGSToDXl^(4&rCJGkV;jF_2GpR5b zS4%TfFixI0e`A`Uwxxqc4{@q3RLzW!e_~@O9c%~^O$KKJH&mD$&xCilu=ygwmsgm6 z0oGI)l&n+^R!s+Uc|@*d4C!L?l9p7)1V@^}sh~R3v|P`|HwJ~^K-+_943n{h8Su;- z3uEBm7S&$Wo`b;DgCm~-Gv8+VI1rBXyK)T zP+^?}y1|ik?Uwio&|guye3~*-Hp>E%QwuYqdA215Lh@s9;gSC@w5CvcW@YdtNP5SG z!v|IH44CL2wfDMdTm1nl^=nDiKs6!TnBc8?rGtqqry3XmO%%avj zWqu%$0}rDdj?@)MU>M=`BnvUQO5c4C|1*foX* zX(zYA`3lIqb=IXSw)SbnQw^Eh)TVIyV9iX}`PyUg2c=dzA4+9%&J-_TTZ_%v?1pT$ z$^j_BEb2h9zy|;>36K-uSa4ujt3l5NB@^)qEUFm^rJ-$&6uo@53|h@GCZTg{{IX}l zs9gk!a~ym<_z2=Bd!9)3LuMP4bCP+HR;7V9z(XSud_!Wi0$d%8hM3AA+n?EZe4OPK zO?}xm4a^W-hUx2;20Io*-~dchLZoHtoJ*Z?)PlUqqz$4r$8PJ%q+#TA4t;OlQA$qh z#3TS0hk-PyfVv$96Cl$-3fk^~lLVw<%qu7i-%yJnJ$! zqmkNe#vlr&wIFM03f>eg2G9sz)ZT;w0{zhEI%6AmU9!N?FwJ&mJ|~O@f_M{ilV|*=CplG@x5u8CR3lLQ*>a;WImtvrLM)G zYK4}BBonr}AQViI`7t~-EHhbTsNS#|!1rT5sg{tDf!rG<7k?{Bc$Oq!B_U+M&m)|! zrn9D)jQf2ysnpuZ;prucN|1S{#cXLxY!}XXKbEuUIGd4+A(bnIx0Bw~H>M;+Ooy4PiZO*YO-q0B?m!9|$XoW8h_jb{S1rOwlppGL z1TFUrEjIyNhL(3)Wmy7io;7+Q@ot+@#$jo`GElLJ)eSpIr5_h!F!8XpAQAA zswP=LIaQOeXWPI&ud6UYIAGWq3>Mg!^?=}l#(xi8x=jibUhZW z0^@$+7{s-4LyPgfR5Ar02K9o*^|EE@+ez9FV0<~wmpa?dTj35J>lxT;Bx1 zBWJo&HYbU1oU{5>P&z$*{UxjrM*YWh~X(iZL zYybJr+;Lvd$BsSz_&@*6mtSAKN-Dd0?dR|K%=taCKLAsuaC2mD^?)ScxYa)}<~M)! z-~Eq*;N*RGeD>-Ff>?u69B@E@>ibIC5$uCjT~A+*5XiQ=()qhT_S^C$ckjLZfA|CA z^t4*}kKO&-d*~pTd(PaWaP8+eXMmuSWQT>g_W#w4oBK~a+@MWI__xi!HUUYvg_H*y z-`o$?Pbm_8c6e~PYg{{{VSJ7;*j4YW%WYDwCEx4x;@%@SkFfjP>UUP#uYBl3ukblM z`uP>c;U3+I-0hW@SPg-O;6Gn`4V!#wNyprFy>sG(7;Xl^zzkh~_agqV$cZq0>9 zs@(apo#(#&f%j?c?3Ht;&Yd`sU%7PYl~b_utQ7zNI8bJ31#I$fd_nN=-4TM<&mUoP z36AyAO8W)GW1m-@8(ci6bJ{kps~H=I*ho~$r=I+Ar?sk=@RA2yIB@?ax2i*b-X#06-B*ssSdfq5)NPoq z8u1TuNPmJ4vyk!;^p#;c1Ks0#lte6lVk?%hh!N#Cgvtps2c73rsOQ=QuKLke{3BwZ zg#okcdkZ|WKv(z8vhpY}5Sh@4Db=Z!Z{Icgz9uS%JwKCZTZb zB2w2<9wq8ntD+(`VI~<9x!}I)VM=Kr2A&=Oi}H+_&@KyP!UF?4Kd%WX@)#KZzU$9O zLyI(7lr4Fb{WLwThdp02p>2j_mmrl@1*A=Im@OyaBF@NXS>^j#6%cGY49VrbnEN?{ zyEhP}qlkmfhxp{yVLWk5$)Y|SeJpx0fm7A;gqsN{0Hwl%T(>Gik8LW5p`sP~+?b^u2Nxtpu5D7&%RZ&+ zD&KRJBOYo1RLROkUj>asB3|<<)+O&ruHD$+DW~ma<4MPAk7+=A3)9eO{*F06PUdCr zqE^8=1hFrf_BX<}sgb)T&IU_9lP6A4MKa<7W$20aRt2R(MU$*9BAd!gSW6Pd+X9Ij zW(Nink{EW5n>rA}A7;NzN`(l@L==t+ypRoE5TWztf_$&?QN947H9G3F%%r{nXEjs) zTI_e*x{{<0>*NTav`FFV{!p#Vu~Z0qTlHqkF)1oLb3?~0pK8V`)iBrIcVYjI8!88s z=yZ6!9Q_Q#7~~6t4p9?hQ7pG+?!1o_%%T~5u97l(sH06T-&mi5Bpl4WnK%b0VoWey z(F*TeKgg%VK;+sDSk5qcIS3&bPbh0V4yBrgSFGpeWrku2tO9r~HKt0TWd{E|o)nAV zmof%#&|LVYQi^wJ9cC*6JFjV63#4EK+%RWBhq!? zpG_NhE2vK||23y#DZQrJDXd;KT>u4dAY-y8wCCyVtc}E@HAf`jb-`&9-Z+@b7HeY; zWDRK++*XP8cc??(A~~4uBHjdJ0xKfi*CN7T0=?8ZZ~W4g12@QWwq*_a1DlqErfy@Z z1zK9ggpBOLPDR3u2BaE&3&3IzRC3KlBCx)daUVSJ#p(gr_72r`#|5?u4s2d-v=R&LqfpNT=WFF4h z&z7UcL*!=E=5uTcLhz$x2t0HUD^^7^soaSD?@&!@ob!oey^o_B67TA&c5}X`8agt? zQi=gMxrFsnV~wBKrG*aovTYpWroiBscl9c7-NZMH05N((gpJV~!Y05^IbbarVj?7m z`7QKaCKMBcvy27Jwm}<0A$}jvA(q7(ryIHfpT91Y5cY7};lP=YnPnW|xLqB-#> z;X_G`FD!p#X{j8sRg0{yhJHy`lpw{i2fT0d9NTu)ayTzN^f*|0mnr?mF^)zj?)}vI zes}F(^X@allQ;6}2XiVV&qI}fe|U|>12*4w4GpS_{n@|xk!M%W?)?7mpFS;n>(4&haWdZz1n5*>*jP;0dDq%A+}WSnShM~;AXuZo zw46MCf(`xE^VRl;k9;^bOa99r`t#nim!E~R;k0z@tv~zhN#nOxm7P0rPQ3KasLw6KNBo;zkBevQ++YJi ze9c7TYp(nC&wTQq`%_z|Ita=WrFdy`xr0FKD4P;CewMW@s|2gEy5qC*H{lzfwUEf4 zJ^?R%1Z8pb0lxjzlf+u3xN_y1&VA%);kp&RSwGnOsnt)N|G>X|FRCh$mwxc&KYmT| z2i-4z{_B5z{)rPO?)Yq3-MjNf2%Z2YdO`=otvTQiyzj>yB}538AN<&RHl?j)>#?T& z^@E=}@>9R_6L&jQRbqJWmu~r#Z5)}cFI=i}7-OTyI2(&p&~?rcuRqq~*C`$G-LGIc z_WUd}0ykJ^8(4T`21j@e$84FpjD;&KV|39a%A;pp_w+rkH_WK^Q(u?6hp6Sr;3g0pLd_MuN?+UtY-<9eulQ-}^%%vH8@Ku3+ zQk+zXes6FyLK;I+U91pWkUr+K5zP}MTZHyoE-)!7Cu?GA_-V0hauP;W+_zly+qiaf zv-WFc95z1k01+#VQWvdYH%=ER+{1_iAy938HFxWlM!$m%u^nx)g*QmDV`>Xq#+(&c z>LF^{%bk^ZYZ>P$KyXD%|)LpwL?z?|tDSz#v z)ueb2`1lly^RWzN;LpdP7$r&)P4HvSB90Qth?-3<>&n$VyF7Km8ZE3v z0ex2hPaD_j=0GU7;Kp?N)a>V1bW50r+z9p)nN-iH3d)B-VP~t{N)B!vcgC{%W-Lr2 zi#Z6bXY4qJNFhp8O8fReJrw&x_d^W)5CcENzz;F-Lkxg{?&H9h?%Lvdz&5WOy3GlBJ2)kRKWQ%>B~=o;3=Na5BwHl84Pqob-g zk8ny)VcOBj;ueX$VvJ$QP@WH7UcsH_4!ZB!5+uorrNl6An5t2bk5BuTG~QLZ>J!W- zxxstG_cIU}-L(R#j7qh@+BqB6$e~h&Rbd_@P*IJ~!Xqvo9%x*Q(nUO1i{F4%hwoSc zWyy=X4m56}<4M(Nim{$|G*qs9ROULYNBNPO;rOxG>D3N4NU~bpITt-Gvvsc7^m{i~ z+&tL>GaDtW*3Ur?9_UK^1~?qQepqNV5;T8^XA*Kws3>I`4`wM{ z^Le>EUJqUbV4UHbydh0%D|jRYq)bBr*|Rwi@lpfui1O^hU>}7@k3^~lsMPi5&B&x} zWc6rBo|FmOxtRCc7S7aD(%RL)@%^~55>W@J*nsO4gh<;Yf!62^h;58MKx-^gn-d?y zC0kR<=#t>pZ5IX{oIt=grn~A+hlOl%B$HUbG`9*03lH8c|OV3dhxy zi5mwrP+=2mM`bwzZ?6`%6j+$LhQLA%fz_^N->3ycyuDmoP*#=RnY0-;z1EY-wa%N$ zjf+Yp-_%)R1c5-|m?V$3BjC9}KnR@HlNFE;tNJYw{9Ro*Etb_zb+)G zABrWGpNG&QWhF#NOXgTn)r5Mg?$30UhjlhA&N$Ke>}wJA#dNb z=%pwl`b$b(9wR*djYq#F&O2S5g<{ zaj^2DMRm2xi!qymHh$RL9P}Mh>LPQf=CZeY5GcWNz=9)*Mpo$+jIzZXt>VCb00=P+ zE;yD%M5I^_EDG#^7Y(-TvId=vdEW3M53x3;5^iw!8FR7=ilgiGu~0*lwM8>f@7Ryq zq(n-0UqvX-hwh`GE}R?+MCyj+W@Cy?_Z>tTU%#$Kk^grPNWI@k$3+@^69(Z zrA{|z*vy9hoZ+A+Wi=Rp-ulERF6;LHC+^sHAOEg2PX#Wjva6_-I(UGCpjN2P-tyo6 zyVnk_wtiE+aOlNDFW$R-@AJ}}efvlM^7Xx+Ui~zuChzS&{@uqpAnM-LnZ2Fc?)~m} z+h?vmbMQ=~?}dnCyN~Zm`*saMrra_V;cxIwxZCtrifqL{k8sspX}^{OYW>v@4VCO$=~R-0|ENEO|zC*qbYmwqT;__ zw@ovzKL6k!qRRaSDWJX{sWE@`SAV6_9>={|sek_?pMT=b!oT0Jt<@1A_~bA2-xLCs zLj4^C0P$v}Chr{m+c$>mYnbtqudCNqr)2Ai^^bcMF~$rVG>$Zx!^-^(Qj66oIZD=A*H@a_q34I4L$2(0nW zIA+C)GR7qhTuhPJ{jz)vwm!%=RlMr5pFmb_^tX2Ff;Nvg^8;-s&J{N%;JqeJKWb2t z5R;^yTg_4UhI!WIxhf<&p-_KvO_yD_o3Efr^>omcJVajFU!R&BO;;NUXvn%Pmg*{# z1X4Tx0-=vmwl|nP=POC@`k(>Q?Hup9bpT8szQRhSOYP0s;}z-vmzDJ z$AZ)>^|msBKO99wU(cRmV!;%Ux~{dNJ;VOH3L+ZhZ2=~!USU)OJ3y0$n3rZ|l$OTV zj#}1a+yt{|#TQwUc669SDUHBbvK`Mj@BGN4>4#la&8!?L6RuOhfHQLBtL$)=Qv}S1 zi()yNld@UVo03vg0^7d|wKh%C%9FD6fRrdQ_tXS)oiiMxTf1PM?SK;jOvOiUP$ z6PJWG%&ZCgjaU?L_>>=k8PVvu;O&8@7GL)rUW8^GxtOyxx}~Hv3n_W)D@mfIh#b#ElI&_#yp77oea~(@`WY=h z5UxtZ#Unr(>x&ksyYFmm>(JC_a@DnMH8&&*XgGx`Etzg}j^?Jqpor_7qqsnbe%*_& zmy=0%&60tz!AVPL1en39W%vR@Pcz|WYp*P96%0wfOg(p)PWF=m;^8P>2#{Jms30}6 zK@y`=!+-_-mL^}&m|~jui>}3>frX*KpH|3Ff+d;I=h2tuoVG@qxTS+iS*v0vXPwr5 z0RQSM?CKQaT;I%W@mL9b`a9&|i2$mj#qZ*Yf_>HHDjcZ`)6)qQxaRkd% z@v3BsNY+m=krD!9jOqgV>v$={0}osiYd;gg!K#my!hFM@99I-IL{1dI5`(FH=_c^u zh?Yq#*IjkTqE9g>M?Pytt{6K&npX&yu}$S22E8#|oh>k!J$4*z-RPJlKOF^j(s?%@ zW^6|<8c5ou-ee;ekU;u^rl(FP4@VRLykmbwk}S}GCaH+z zy>wDwAr)&e5ta@TxcBLh9nw`&jF!`7E2VWm1GjxttJ%4kR^B6jM&#TtG-cP4etutXBrWzE3B5mp?W)77sot6+!O zjyYH?F`YLu@X&d=?B&aBo-V6q(hNhfoHsL+wP(v=vmCR-lT*?-y~j{;(J%Psk5Zd@ zUaT?wCPW8L4mN>-p=6i@01<%W#A1f87PyTC+jav16vG(GS=Ais+x8k-Gt7&{tSp!C zh|Z&TnY*%pBzkOVA2e+>@@eoz+Ga&z=d#|UWzd}Vp{|J;qkQBCye15HRT_J9WSm}e z(M3X~G*M2sYsVdr!pLIaJhL#YW?zD#xiKlsO zjwtNvRcy?%ZgAnk=O2t1e`Mzoo$Y$!;)zBa+#4ada6u5Pp1-<>;i68-bsq!9s8;b^ zf~3>Z75}TVjkmX7Ijq-I zPeP)dDEBA3=27F#{pQ~!fhzAeFC-5~UmWf=x8|XV-wYRe+**!sfOQO?i3 z`rw1nHq<8h+L{!*LNQ8qXJ-d3W+cIew~o)hXMPU|*4e}ZzvLKYl6AnFdKnqJ@?V8+ zF$rb_!HM_2_k?UiZL)~K1><>q?3_it?bly_=_SQ)cxD9rl_0omC zh8?R19D1oI4m_e;{Q4`>l>N|0WM}FMls;H>yFPbrUEQjkwqo;F-R{$$TAdGZf9k7$ z@$#P^EJgRy95-JzU%eiJ>H<-x4yHYN^yuvepLYyYN&|rm2m~#g=>{tvdMz^*#?g;n%r2nT8dE?yrbD-fsABJlm2OpDk6IgJ{*C__*()#_| zcoSF`-jd;09{=a>2@y4vxfgtz_IUlcF);L34ya{>3U5q&ZIg_2Wlc3Re_eK2Hca`_n zVUP=ve7zc_QP*B`?%FNip8bbn^X*&vHv07XzB|x)go&q&`Dd`WN>k~=m*3e>*5yXLc1mK=d#UPaeTq`0Cj?PmpDg>%TSr&~!PbB@!0lTI=JSq<+vuguDg!}>Lx=)l87l@vrn&e5z*ScAd2OO8`eWk zdm>{UA1(avAfISYvHG`E@(HJ*8gy!@j6Desp5>VI>1a4Ipk(BjiHV2%LAYQ>lfdE@zftfhi+ezTeYu$# zmEi{f0IeJ?=6VAmceb}OoQ?p7h2+lvy9a?DA1yHR#oNikz!E~N&}EP&O(E|Kom;R*?QDs>^yN3Toi*7pazz`cGOr?-7G=tSRdVmAJ| z;4WL(gdX(M;Pg4Y&e2dByaCb~cU`O=v^mZJezG4|9!SIFB6N)?)I>SvL0tK5roj0c z^g$JDFl(3YH-`X)h8Pe`Xh?sZ(`;}?fi9*~RC`^#VfyL`nb9AqH@XeInot^+coGKy z;GXY?)S1#)%(Y60iLM;Ptcqm@SSq&(K6bMAK4Q+snrpsEgzvkCbbP5;YmO6HPz6DG zdRj=sfFlUBn8i#;CMkyg(skxIh(|o3(xos)*Vq|e^Fwj~F@6qEi*txLw70lwc z)ylmH8R+EHK4*mk-Hj=LC0xp$W(pDsG*LdvH2CK#=Oz}x< z7yMH6z2J}ru58AH6_u1=#kZ8TC0OZZD#CL^y3o+dnx{rlKBv6aq~4aTTEi(QE$!`* zf>gTe8qYN)yVy9F2(5a;Av!gQiUcc35H96N(K(Dvb@yxQJ!@cMWFQ>`oK*2?U;-fP zszUO3RVQMO6Y5p5bD>5!7Y%fMiE-n5~bIN>OUp-9;+hh-WA45xaUP?*s6vQb_Zh0~b8+E4KK(nhzG(+vmX`FOB| z*yaHtPOyP_53s=@`Ux^VYmwj}y@KN|!=P{jT8qUr^7b(PVuJyv{BU-fju)bYB#qB5 zR#RmO9ZHg<4}C$bRtlJ%Lj)6V=DoT<<%L5C3mqnDl1Q_c6JIdkiO+UcR4YlDh}4n< z1uNenU)zNIvO!%^N>+s2(fEu9 zJ&y`5@=cpnO^#%5!9*YIff{G>ps^{((pgR4kEe|B&IJ^3fo|G3N(c>yGI`)zO0j=f zPO`?ac)>Btu4h|lAhc{l_J-kQ9xIagK7?keDsgD0>p7ST>OlJD(%?-2ljB2XTv_%d zG@5EL1vG&EWlos0A@h@IB*uap2Mi&l7iHBJnj|6h*xbKRBL5KsKH3ts#4Mgy4O{? z4D^^qi#K3~DNhR@pqQox=l!gQIGtD2c$<2P(C0&H)3h_h%2bLG{Y8yhZlTWT>WdS>VB<7baO_knM}PbaG? z-A2~3_b)F0!RdGYl#_X>iOcMutr;+tRj+>s3g zXE9iN+ikQ931t8A{;{Wi{7HB3y(dp9-D-74l^8)F|NnCbG*POv_BV2qPCBv$@jvsn zXP${rKHdqWHaIkwANWtS=j9bG?c8ldy~f{Qz-cA)(QNj`FYc_Kep+X@cBjC0nv?q_ zblKhlg4Ie89J9xc#iXl;AC`Y?^+Jck=fC@^F)zOiuKRqxaWAXr2mznDXt|j7Tz>j# z(SlBa-RK*?PAaAM{L(Vv{rEZmhhP4Mu&96TzfQlL?3()LJiaskru3Y?>acbzY2mM! z|Anzc@NC6e6_uvQ(pFDAA%ATX%Doo}@C#3VOLE9} zcIE5bnxj~w>|g?vYY&Ds3+#%rTCOZ1EbV%%;4wA6^3MH3(wLM4a4y`_ZFIqlj46%5XcDveM12!aCQ7KsWFJc zlLj)W`N1+UqSk~j_=zkWzv~^Jycna{F1|RBAgu4@XYpPi$^8_}qseCzl{?T!kGVZ8 zBZrVPm`4tZ-FUMIrsG-he?uqjOq`8xUcCJqUP4SC{uWgOu5$fta$W~xhgs_h+jK3deZtW_NM1Fns3nf#B)5%VzC zbS&`A>+kXyx>q;~u@Y`7e!8|$o@dTj;Uha?o|1;z{om}pf2<_gb>DZZx_a3?8S?d8 ztU&!CQ?~>e7)zu%fr@G#xUl4@- z0zxnWBCb}%AQ%hUjj(?t0==x}0FfgqSp8vRgZK|Ih=DNNKQuBq47Hlw&gXk>Rd>HP zZ+4f;id0~p?y7t5x#ymH?vJXv=l&!T--NE{sJjg`UDX$Dz&<82@0jh{mEz&zqDiJ? zZ1iI%60E5z;-!P`1RXNddO_i(eakB{cObabcU4S0ZqH2J7OCVT8YL^~?ov5(+==ao z2H>M1si*P}T%N1q5>#17CT1(y{Y-V8CL!^AD4Cyvi)S%PYfzRiOg_<)8j4Ll34lD6 zpGh2ZJbcRrl*hugCH9UEIDTUd)`}z9{BtD2C?1u1tyyWdvi4%$@h!XY}s z*m-i&)EDwEhmd0Q=nJ- z+PdS?Z-AX`z&y$f8c81o>Ex1U&KAk1lak_Qe7(}7;#gF3#>Jv1M~cX@+8Nu71}SWs zt(`!nF@gn$ri{kphzTM_lZt&%$K~WOj4J1u`Y{AS-&r0XA5U9bv`Dfh@XrX=U|*v0 z=#JAhCk1n$n=o$CN|lf5E5ln^heaepCIfvdbFD*ZGIya&MAn5eRH#HQKS5D7VQrlS ze(OOdmn}19+cC2tDB3*G@8`=fS-N6UcB{#{KFRWCl}(CCCZ&miY-286dg4_`h z?Ue*QJqz-Q$mbFsN@hxLBR;}2PFvCQmqYKC{xmQXS9LhFbL4BfB8=GvwV0P}Je-YuOCFu75`-m@It9v! z3M*&(jE{ZGGzxm5gr_brzU5ARalD+!?`3l9aXNSw`jQ-tybEA3Vpw(e2b<* zJNNkKZtmCKV#>HD$O=w7KVFY1CAjS2N14ZMjJ)HBSzlD-?rL<>vN<`kkk@&!oUa+M zZ8NG&12bav(XnF$;y z3HLr$OP>bi-C~kb$LNiVVr4nTo43$ z*568-7;U=2zi$njGtDrhP5hCMY;+x5d-^%3H%HH2drkxg%tIZ*Sxb8}9&g6(?u}R6 z!IcjVKH5uGGkmop?d{+C-9H-eX0ns#_dI?7{%F*71OD2z);(pJs|GerZ0{&17<0L! z8_!<;d1SnC@U-a12Ors!0EDP0P-a8!Nubyz#pTN{zg)ckC;k(K9Dtq%<{9erm0ikn zJTv$2aS5{QD|dE%7?6GL?yH>A`o`vge5EPKWIE%9Il6HZIjIFL;WfB+hSyCet7=bG z&F+1b-{A4FJ0H7q@Kg7$qUlPJ-4^X2fzhFONdl^u0d(zG|McE#ocl`O2}wp>NFC{a02m6l2qc@395* z?fj;D!J!-f&70Dh+uMIz=J5($xqU(IWV&95CW^s!8+&|&TRO8~`#!>coB5$j!)|X+ zkSKFRB>&v!K1Y$0o0m=VedEDPN6+EA`NlWCA${?#d-cwxOJDqA3VikI@BEJXcIdV= z4$_@DPDx&_H}UlyhIOw`eDC*~I}%gdwwHSeoZoC-V=LNcCBc;| zSH|GKdhbtPyR`YD@ptYjimf^N$`U1HAg_ikfSh#?Ppwr7lu`=g)u{e$1%(x34h9O%fZ zTU!bGJi7ezm#v@SIko^!q?(O$wEUmFzCcloYKj z1}%48zBe(xwUGU}M>o8726I0`<(=;l<-Uj6&u0E!K0ieHC`79Gy|2pU44jcDRjctC z0=4YYP~txNkri;CsJAz?#H`Zc*4dt&nGIjq&efIl=LPMR4zpvlc()|df-9nEwmp5! z+-LHl)7#Kg!k*T0l9=I3>yTtirzzZcDSsu}+vnY5*YGj~7Ci5Lv|KPX0M2C47CRJK z1=V?wUcL|F`4dw&XWcp$q5_(L zN;!3B>vl2jFn2-&Ad1Y^oko`C=A1(=@!}^ z4w%_4vq2@v>{=_(saMaQKrMTNkQl1|^q{u>9-MLP;ghwyOZl z>qp?-W4E^2_BR>TUs&>qyLDlqPTadL#Oq7;uKzne!ta|%X6R`L^P33zj+3g*bP+rX z&lj@r{-O}y!F@|}z+ZJ)xH!f?Lk)dYkVoNZG(RHpN1!j3)UYx6#okP=-ThH`8dkTq z?YAAd*@o8KIrJGPoe}@m!b3Z7hi|J0d^FvE{SIWoUw&IWtS$DgMEa)5 zp2Tmu*)}LqkN7B<{;ZfE^A;L)V@9SAxlruDr9U5r%WAB5# zi6M^XVAwVL9QxbtJfCUj-ET+0;d#24_FNC##YFE6_L~=89ce22UHLv#6W&Vxi=S{r z2|d?EpSZz%XVUu4acLgSYL_jKra9-+_U^%?>+528xUhyGqTjd6Eoklj&fi#X>s)kI zq*E?Bw|q(!d6+BA9z4Pw-6|T@ zd4EZfmf@I5(`DyQGk_!eKr85A8k^xp-m>;Nxs+j#c6V+C!FhiR$!;^o!c1&Cch=)~ z5hUC0uHw@geB(Ut=C~>93)}=*&D)3kT@bIf)x9@)@3oROrwvVh2+VAEZbSArN}c0| zi7_%4YaUe#Mi;uFUtQpz*hIJpwq_m8J>0hVv*^Lw{WvSJlOvgrc0XoxXZ`Ccg?;Si zmZ4d0-Ae9ZO2^>dqk3%5{_VBK*?RNum6I<-7ih zjjiv@E8iuKJNH?Ci|w7e6=LQ4=K9+(MgES$#JemqNb`2hcQo?9Ak6rzsSMoPHUC`1 zzWP7@rTtj;0N>1MTl=R)9KG80p70pkhu0Z?P29Uk4xUX>fZt` z4z~*=|6uhd^}M7HN46t)3)|bLd=w*b&}2eEvTvsALSH3?>Pi zYHI2Zc0N0t@s3`x4A9$#%%yQ2_yKCBFR>2I^%C1Gc@ccjrc*|WUQCNU#$q%;WftS4 z{)-TuFN89@0!6vJ(=5^oEGdhDNv{IM9r-B(xaXnQ zbsAh+0U`Edu5HIgXO8o?vvuK&Z;@PC(aBOU-`RAO*}8!Dm~}j`S1Hx_Qv7kqwhEUz zO_%_XmN6*!AV#w9-wTOCIyf*L( zUGTo}tyVDL-Bcp(tOgKXA$r)i3l(T1ryx1AUEG+b%3|=2l@YtL%=+Lv!ydnA?kGD; zd0p1Kd#dC*KOwC5+!=#NX;lPrdy9?GeXJeUC07sewD4M+tFn*Tx?GlV@S(j#VhS&} z^2sc6oB{bH=mtwFW4XL*TFYHNrzP%A&t(;`6Izd=HYUYMYKyf zg^RN6V3=^S!|ZIzMM35~v!}5uW4PiWn~Jjxz8;0dPYKsE#3UShghrDXv_gX8o+|So zR0svK0Deyf0y2FmX$V8E8&Q9Ym_hbf`VM0qKD)x75B^!GMWDA=OlW7Vzk7K{5 z2R;+FI_cQ5B!doG<7`#SOB1&5Y=<_^`5wSJ8|t?OCMP-K(gl) z+YhpPEg;9(21qH+Qih(DJ#RkiIN-qZ@OitLt(PhhpmX!d3 zI>PKPwvkwOcu+BOD^c#qpoKR(NJX7w+F_F|`SsWZqLP2Jux4|RNsX&z>BXE4Q7Df% zqR6#OX#^+D0h`;FBGdpqi6GKmG0H;f9UH(v5{yu04{Y*qm=Z8xV7&)1*{K60DYB0Q zn{-ejjeG1SS$4}Jeylfl!D=Sz);RHh%&=9;U>wQ4BgIDd#u@j%8Z~@Kl}VHjwk-b6aPZ-7ceF^^X4%OTtcY}@>xd(hpxm(pNxa|q>sbNom(T`MtRR@L9M{G)?|(KQioHZQ+? zbi_{WFJ+%+kM!*sS3mc2DNjdi^_}Q+7jSgcnHu=|>ksGtSAO6tKk(l7l8;ZMHUCF< zIN0lGbK~Tn{FPt$Kaqg!-%7w5{mVy3ms!A)eO{|+h8q5JKj+wSL6A=4+Qo9dykCF) z{{2L`yAKk)>a^ycW8UuEb1b^BI(?Tl_Zt?$uwv*V3h@CzrefZ_ym|Sj0J(qa#!sbZ zU~~Oxxp(m3_d3g!9p+)1xTN{a2L`yEY-f{5fIc8ggbiAPvro<;7-G|HfI0e~-bIxyR_Bia(?9+li1Eqxq zr6lvc($9cEGc2V;uf8_CYvNxgR+4_%SnaT2FYqy&A?%cizwR)pNMA( zOV)Fb zrK=D>vV~O$AOV))^2=zUB)1W}u#}57bdN-Xl1+@rt89|mXoIIr)qr(OHrka9B#52kmPro>EX?N=cCw6O%AHSjG6E-$QjO)T9K=^=>4 zxNsinvy~5{87HrH^dzvVng&Y{HLE%nsxpYfn}8+Yv|UHtWHzCcM#p>nT4JNV1eJI# zyrOr6#VwJgbF1u~r*}Y}(@^-z2y@j})RR2q<;X95uFVAmv6-4#6&?xIs^@?qP-9|O z5}Qy^E@R69nURH87FkC$st%=;a{-nfBAi+{&2eJ~Uy9a+hDGY5vg#0}qh|^3U}0Br zL^XM`u=>zZVU!jCnObU|$J%nw;IqP%yX(WMft{c!F{83`%^eOzCoXnPJE4G%1v-{@ z*kk_$^u?XhWmLkLFo#ieVoSM4WNBQ1YmK`HUS+p<5N6r$SMT*ghZiJrc_n*bRW_M^m<%y18U0Gs7;PHK z2fG0=aVvdf!;qJGAM06zP8R-MmMWr^Y9Rkq@+XVHx~-)+R10ePVv*UmIty_e>*!&$ zwue!lra&rGM9YYj9__jCgv*tsVEF@NBRhPWb?-(5V!&6%J`2&F*c>+2M2LOhQ4ExT zb+<@kt6X^OCQNSKax!HFo^rQTn;4Hy8t>z`r19Q#)%E1IQ?`czgA#M|j_hketpoPO#l=YHwvmyR}H z-+VnUf}hL^PyK9l9sRSTf3`0hso4DEH~#S(`?$0Z+E;;(0$ZP_HtcbD7B(Nf`;_ah zNm)H&?@srtzuK?ej_!LT0S^tmTyd7gJoEy%^Ae!{TqMDteB&EeuYUEb4*1f%NXNT!kU)DZn&z*E1IYTF{?hr~#Mo=r2kt{h8+ICyOrrb1(Fg2(A^Q$Q zOg~m1hP1Ic#uYX=qz~jCF+HKWD{70ZKY83jUqPgI{~Pn`U+27`l#6F2Xn74Sd!qg?m!Z}k!|eB(FuFVVKGK*Y0Ghavkr$QKK2AsvNWirVK!;()YBfc zYnOApXU~9rdkvFs@wCRaunWIKU4YwqzO`jvrnjcPkRtjE(L(aM<^#r4_%L)r&DgM< zH}+d3A@971`NZ1YZo8b?;V!Vz0P0(=p3wS97;V`tphr48WvAZA8zQ-NPt6ZQ47b#> z#g&rch0g|8GTC~G!k@` zpszr=t8w%Y(DKx<5;n-_fjsI`PH6+9k!o|rwt!=jCQuW#>VIsgMc^uDFQh^^u^Rkj z>O5&-i4I6UG82@&sfH2tM1q|MA6=5o+w;^~A_gMm3B75;#Ui>$mf&~<#7E#0TA}rO z7$RbU*XV!4?tDnvR+Lrcxz$^8Pu>KwT^e}H=r^4_Y~s-2&jxoXy(5pSL*~HF<&dWW z2X`L)!*wH(=lM$Ycj`te*%~Vm1;;jS$Vk;(^3u^B6ngz2ubv2elgs&5G=kx!V{Lh- z4?49Xa6_hm;3|hu3|r-CQweq0y?Gvjr4lG4XvsviYGRFcS06*ixe-*`(}|VAK*H7*d&BcBhIy47(UejJnN+ zbetzunF(r>U{0-=S8C@oQMJxh8r3Ms&3Q^tng9BnKk<*EYtu_;kD_KHv&4bO*^_Mr zm&8FKTwIU3xj0Wom5ny6Nu$jgpP$s46+Rkw)2>Eu%IHPO7R$B7WKMTCpAP<6@6Y`0 z8Kb3weF_xdEd{3;7ds9poreS$tU^e(RDGl=D()=4kP|i1Oo*eItN7shXM*hjH=_EKkhch z#hi)d^ELGZ_na806LT)Xyh1d&gE?Ug$h}VPt$(7A{e$x+6sH4+6oMFLih3JkR2&)Q zs63z`FxMo$?j=}uHCXv43F`T{P5z0VQ@#TPXD9{^iK5H(jPA!U&CYPBYp)sO0W77S z)oW&rHJb;^z;P8Rb~#)<*_TUIv6zort&P4Q=$YSNZs;GiCWL_zHNVoq6G48hfv zI4BDIJ?YEXA~5Gc%$3F%BAaE-^XViH_$zw?4Kxn)pl;wsp*R1)6r$uGd7n{_wiMC# z9OxkJITSSWa!y9G80d1z6~i)UUb@9V54RU@Y3YMmQU#xKm$vQ!KbY*ycY*&I4i{4F zVz_16`_7#>|J!|kt8={G%HO%SqIfI++y80T7eUya<7G7u^yokQyKm)>0{Rvl-uH<& zi{X8rQ1r##)#xE8bjR!=&ql7nuB$Lyy7TJp!Mlh}?Q6Zk)XGab&3GV?k8|zT*;{%( zXVBIti@N(Ap0}82F&+WgK;7rwww3+}`T?C`3Fbg4&h=9Y-U1XTK{;5=BtL>IS&-TD zk=@*Q45o;%dzt$9Y#Bx}Qopm1@;QJUS}Dqm1U1IC9E37n-qIiC=G!{UO57g0nNBCc zl-#nfWI9jVjP`ovN1m^mi%YPjreV6aSfRnBkrAiOsbUk0brFlG0x6(g7cifCr|Myy z_4MUu!AG^e)TJ)jTE`SNlF45{z^o9SV~QGHl=LfiXjoQgA{Oi` zaO14x^%{$)u51P{BFce>gST)crnh>EJCJe*FieUSsEFUE98_*(YLGI?Zmd~f0##9E z8xiiH?5)Na`z#E81p$-=qPE&?9$t5vRp#JkH8x|fS>>s&z77**UgkwU%_}726e86- zg)%dv-+8F(tpbq}rX=nQ29gwT=|?)YAgm+(31PGUl*e0%65c|rpi*0C4C7d|a%pJ6 zWeNA- zHn9*s8f{-%;sAK*b^3d`G%%cMNL2ZX8;OW6ddxlqOWV7mb)81G&=&>0kF3QAPF{)Y z=Lrf4_~@vB-t1!PO0#k^mpDXW8U-~!AQ7-sUufdDQzLGTWCNfW-4)7^VdSEc8*RtBpi}J8^-29i1JmR9L1s z*YetvHJf%~4E|IP7>G`H%z}Ulo}+rKMS*z2BS2B%^f;FRi~)5UMm1?$5YeR5;|{q( zF^1F;DlwpL)3qF!3rxjhmgn3^TB>A?a?&p5ov}kUR57_Txm9;Uq^z9x!FprtBTz(& zRsMphO+AQ2&LLgosr1s7Q=x0dy$+&NUX#^a`p@MRBN7-ngMcoNAlQi7Kt&Px&*{km ztol}F^62H$C3n1g;*y#*4MamSTTA*x!xrz#8$d*vXR+N>wqDPlrlSgclY`N~0wD@}$Ri)U1I7~5QOPL0`Kf$6xq0~-9f=9? zuyT*pxVem9&DT`!TQ(Yqr3X5cguf{|`2$9uY!6}jmrOsQ*C=ldG4y7c%%<;WS6_R& z?jCK1nUcm`H+BTq$O5~CSDZ_9d30l>4*DK!ckh0LLSrfFx7TdaWHR@1qf2<18fB2* z;MNRPgPjDBJS2hPj*gN94<4MCK(it5-W8uDfksUfi{Py#Fi8oUWZ7)ABlxvzXXm>P zGX5U$>Z@P=a-U%LO=oFz4wpw74@)8Mbz1u{&65o56$h3WC; z+21s?lGBqeNrKk^p>cAT1WL0oO7#%)V7{3I3iIo~n|*CG%+Y-@3+}f2R2F$~Z(sk^ zinfesdiaz*M~#c}hmQKrZ?IwJyu@tQug&tc6Tg`4iwPd{-_P2tF!#;uQ|7*z{l?!2 zaB!O+{L>$lDY!vyOujhzqUNU_9K7#+3CkTNDDYw#fIQK#9l52GteA3pCu@aNYImJ*%TTHV(+)0BJn1 zxOVN;S6{vItnHNU+-vUN?c+(t-Md$>$#%tBa0xd^kn&(p0^V!~lHkG7OHAE02@Y-? z>`R~x*Lw*b96ggHaAzeLL$VK5g#@(z@~q)Ap^?4FCn)l5=c3?uP+;}R$>}t-E{o_3 zpDH4LMI>wj-S#;1oO zbM`stX>pwa5@W!J>jEGy*T?6J76+waL(8&@)s`Lkp%pNiN0uO&b8`$-Dbvg~JjTAR z2H!qlZ-ku_g4ka|M)Oe~`TjBl6lLbYMRTHfxDuPUuONxo124O`JI#&KXlPdo3n-La zD|2bUSIxon>riJK!kQQNCif0E7r)9EW#Nluk$KABN(r3hAT`u=zKf#N7qN}r6|u$D z;-(Gf!E>dOAJVo|t>f1gN{xP6G*(&{?6@6I#(eHsZr03}{8TxXe3GZpD(xyeZjL#9 zxl~%{-ch<{^O4NrxI})R3lAi!>T43;x~Ekfk93j zE^W33Gyh1fry_biACL+p`&&U&TP=$NnG|S1Ze4=T?z{cRaH=%OK!jI2olf8^W|4+? z>>{ncsP6%Ou2tX@ci4_dsDgO!I|jIEX&0eW|o&fpfs~P=wCqNQNd&JptBS`8YsEtzgY*9@;?P0>u&JPecn89mJ*e zc#6FdI;SQBS(*8)sJ%t$p|B()b)i{6Iod*OOA!(uF*a3)wez!4uw+n@mi;YGN^R!H zxJflhBbp9L1tw*5s|8~xv$*oSRq|=kR-$AkXQk0BV#GaTydfhlq$oJL3ejnB7s0qV zBsETQK@{z7W{;5(g*U+5)(}JFt}wIkghma?dN(0Fh%$x5PcHF^mANXp0A%AQ(I5Rf`S+QBwD(WuVPYDeF<5j&e8dcyp79 z&8(27GWB@~gAAvq-D0_P1xJKYtz6fl*kdY*lR!3Y`?x9>W>hzxmX)diuWx-uPN)O( zC4(|l41?*it_@3OW;*X`>yAOOK`G1YkcG*L zpi&i4-&_{NDL1(ofI)ZeC|Bt&C)tUfzNC&r#!2JMC8bA*(&oG)YQmZqbB#oce6~Ks zzn#sq7NJUp`GjX4sAVwOOE8!rfs3(-aYTxVoT4EKm?JKMIwRC?gnX>X%vGJqX)jDD zm~oE6%c0|oI4vS+TO;+D>a?$id^9uj$=#>~QfHdn_GM1FRx-QT|b)=ylX^foGC6sQKdwatD}QyZkWCZL;YL74jbl8`ClNgl<(=v<%}=zlwwO%E zNT9De0hot}-e)lt#MEg52h)S;L8-&q3Q`j?G=sNAUMfj9I;I9N6nEm((dV)gW zxm?r0m(0()B}ZmqHj6xS9n)kx4S}w*`cxes4L&QrMIFV^p2D`EdMS~5OfwIqV0gukHGRW}zX5gSG++_WX)gSoJ=7)u{o(wwV8I^$Jh)|UCf|KSV;@E12 zlfytMP;g8S&zk6wjT4oKlS%o3~fqBp3+iMJEAgPo$x@@Lx@801zn@@jQ-2&2^ zFgAa3?;Frc*ZvbgsrUlmzIu7{)BNOCh?~Io11dCy{o`Nxl|O#nJ&<<~7MtvEO9Cys z{5tTMyNs-oKodPb0f@yH?tbB};&m_Z1MWSz_rKk|`OCljBJiQ3j9Jo0N1uGpdp`MK zPlD|V+bWCFtvPM`YpWOSwC!Q#ExPtk^(%2JY45=eJ9e`ciL;WRb%Bgn13lcS?S0^U|gK=;ADodi0!TXdQwC*W-Amt~p+ zH|{vJ@u%hf{{QQFi$+O>8Uno%8B|jcCwn;i#xwX{?NlA*JnPXyrLU{6Sy~*ze@O{ zgFyntp;XA9_gr`9-kpae&@(^|+ML~;1i~aZI=Xf(m~~GAcjvd<<*S>2_z&grna@1e z6Z16n5?Fx!o9fO0Z5V7aX=d?8--B@&9Mb*wVAk7dk_pP*iIK<#f4SP7=gxK(neRNX z=}RC;Slx%%`8uT^xJD%Zzl6pA7paGw-SOCA)JvqFv~@i!YN+Y6K9tHf4CQR?0!@vy zkMf>KI#I4*tz%O8)e<)-`j!OTR3b@J3^u~0Co@g81#fdW6OC$x)r@XemJHBB+E#9i zr^HZ;!9$>E&=>gipgmL^ZA2ng3Z`oG5z>w-Tg*7*32Z?1GEP1OR*+iAdeqT=snx0& zs%0<_)kOudrUrrc(kzeUjm1Or<^Xf6k=E)I=~%qHYzde^Ebz{6x%O_1K0`5;{)<5= zelxIkmJvLXvK_)B#bDi;CDvZH94jf>0Xc3km?97iW^!F{Hv)0)>x$Wo%fQMocBA~M z3w|=D1gEVFhq()Qm_9QNYD3$i%#NAcg}la0BM*)vc?;v!S`^DEJjNP+Wr_vG(0T4~ zTa?Sg*0spfsP^>v+y#7hqBTQ7820Vl&J^YlK*+t^G_>4(5iJHfGp)3?MW*?~Zvl1h zKbSl6R#qZkdaCkaOLQr!f;98&fK?7J&%A!sU?*qg^&R+54tysEzLNvr$${_Wz}v|I zeKbm!IloV=Z{HTWrFi)jp*DpfkA0_pBv0%yTec z26N{v2FB$4S5L?yax=*Kd)>QNGU@0#2TFey=r(a~q z2uKYh4?j}4*GfX$D+xlcV2aHnjVq2}c?>#ps}>`YJ0t6aOhQMpgSC3xi!%2GsZV{C zhhEgcBGQa!vqBncM3?1FgRNMCjm+#ZAeu8kx&?6&mD-aWNj(-!C<}Vh$Ics#u>IZ) z=5Ex>Qbe#8#P`V)|H4?9WmeK|%A60%!R=}`6}jRekYeIDG~{IS5j2oRH`vR4>AQ&SHY+# zar#2?VW9;ri013SP7ANdd+^ksNGg5lGVBzLB=L5~)_6F!&<6f9jp*w1T(RMr1S&Ef z=ET_AiYyMU1*8E-X9#Y#*d$*gU6(33p>vP3kv2JPd{=dfebRWQ*!hMxgSkNwm|udp zl(}Sjno~Ept^|RcUbvMnhb&%N!aRI|NZ!U|(_MjJ1ja{l9#c#^%n=hN#a56bx2LS?X=GbRv`#8JYCAFvd>rI?+}G*M#9>lj?&<)f;qN@o={Wq8NFC3#?%QS23*7I<|vORJcHfqTiY9GkvChP#yLBu>VX+w_pCVq)3t zB+GcY(F32#s+g|kuFgU@Y?(cf<;8S5Wn0@$mBcSlk~|S^Kzcy>LY|Mg#lkPBE)5EfASJ?{R z6E|jjlYu>V3aiQ;yOS}`4Ie5pmSjw)^!oy;Dk>i9U=ZHPAGhcXgp8vxDH&du$5UUmU0!q)i5qw0ChMj((_e}#7aIZHQQAI>GUkm#Zgq6O@doP<&@CCI z?Xv6ybAd?NlKR&XktLZjpLAX`V#xxNi`)(^^TJu#XM&a|t5C5gB0c=(o}RFKnVZhZ zS7s|m@>T)>Au2Z*F;{_lH=2agsG2b2DR&gZD3IG^+APT6vbr$!WY*Grzy>b7VjdO3 zRm|?-VXO;RdP=_Hwa@c7XYw=;;-Y4y-BZrp1$sDe&TakgcJlGuElao=5uU?fYq*8A?-u7 zX;$oi^fY5b%#hWkS+XN$QVwnyx_f_+!VMC<^2%4QN~*Unfdn`&0drnu1lKTi z$^F&dE;j-+_AoLs=3c<15wjRu_g}f+$kM#m*w3UL#@^1Dd^~?Qv)yU)+gTX>h70X& z_ph@TTyVF$PyKNG>!a>>yO00S(#)Uv;WoLizOZvMT$r++$eE7)^BT#y@yfFshAzLL z8JO&b;~0lR(%=4VMxL&_-{yC>qDp`G!&k3gy-u(m?tS^rovTOMtvSJi&1HA#;AyL2 z&p!M5=E=>E^qf+;f0=Qlqa*f?MFPf~ESzS9+det11akCxnJ>>y)^T&Xld!YQM%=~RP zpZnb4rqr*oEsl+J3wP%$aIyK+iM!}+49+ANLNO9(5+wJ*!HpY|fWbYUPJWCV>Pb-k z?A$}xe|m?vBcq6eyXzEcUjo-%*?jPWB=0_se)^XTtJTv-euU%R5h2Em@*D8;1~Up_79zPME-ZH@ner*yo(77 zZ`^{$H!kzWk9Yk5ecWSnd+uC5VhX(7hg)f3`T9FP~?skH59yZgEn;> zGTK`yX}8D@jmQ}Ew;9bE$6Q($>X0HPpm;+o(7Hrds1;U6K8~>>Ct&W{KqT5_hQLBG4A6&w&)_sDY(b200eSjQdzMCLOc0o zAthzzX`-1nUyxk2_K2+{_r}?XcSt_*^j4Jf0FDqq!39H-XtKe2rQ;?zv8JPeml8`= zEKw=kB0Y2gcBH?Zw1iczbdyHQJ+b48(mGKaU_2}8yi*53-M|<9ocYkmgEm0^jzb;@ zYwji|HPeM}aklws@UxuxqNqc8aMVag+`jdqMO09*3v&7-s&rX8GPYf8`LJYpK-2rdtBSAsh301aqzky+!gVDo1% zi|9@*O26>R32*gX%fS|$(~--hF4UNM`7TCvXmT;7AB$I97pmD<$?}2h3&=~oh|9we zaUN0)4@WE4Ekl0FB+I0j(UV8}+c{}RMTjt-Pm36NRqB~*^ft+DrX3WPw}?tg2obf* zmShIThbM%jZy*QD+aW(`g^pI7E{@T~#I7ooSv)CpS&V|qy!g<}o~$!6gL$vnsWb`> zg6U}3vpY`a3lV@bNaOFWphkqOb8fZFYW5=aRK6LrI=f=lbmZmY1YeY$pl3o*EZ9q! za+S21qRN!VvI#N>HBWME>P^~7S861mHoX}NJyog$#N}@zr1fSSXV=?AsKzUYT>)Q!RZmd@UTF*5nI=4jG z#!%dI>L^BpHlnv4mZ5Vfc^&LjlK3%um0nJy#xaW#46s68>~3xU=-Amv(V@XRY2~hp zaZT-%(2mzY;it=%tQMCOdYvZiET?aDv1r|L4m~gQ1$oqUhtrw2xu+S`lxoeR!*`tN zv}T#_NogxAslinphls4ED% zVf|`1>2lAPbL*~v6%89HvW}DC}Q{ssOibAoW=Fj;Fc30zq3rG7q&7czxW@vu&(;sEos^K&{_U>Kn zs(Ezuw*lJBnXZc@5YzJ#Xb;Wv5=g(=Nnml33Q3UScP>dF?N%u`IM|mU+fWO*B@W-- zyV7C0Gx=t7R=1|+x&G*rKlXHby7!1xr_7N3c*_jgU$5xyPODMT+ADN$_n9mrgZ7|pd0|L5zv_gy^|0oH z*3N>D+k|Y)WSy&-hJXBacE$}IZsYJv?ghdFFVnMLt zT7`5^{+7qG9NoF|$JsqTIrq`;uU-B8>>xY%{5|(?@+SZhP{%hfv8wuA9~@4(*=%0F z7dZkZon3SFSB|zCt>~TYw#)OiV-}Kau8UTn?wx41odi0IM*8|7!RJ4(zLNxM zSqu{Jo!CB#-lM$e z4ZQ9--vz!xYPhz1uQ;#9J0HnSE+D-rC)wCslqS-FOU)G;XVfHtnn43x_#Wc>u?GXm zv2anrsp;@7edC-56Fq7{(TA`&eD5fIVQ%{0h4GE2a~(?}))u{E(lm%G5-n{VB2;>F zVn`$2ZQ(`G`{rgJZbRgQyN^K5h`ngH9%dQA^pVg|67nv$6w%V`vNFR4c-^c;FH3^? zVA(Uv)Mg5XQa*HMOE(sd>X(WvfSdK61zAS-0aHp{L4OQd)v4M6!3VOLxP4x_;C#nT z!&CYpOcvlCWe3O(_FZ>Lhd49;qXmn;6XTknFZ`+VncM~K+e4pnpB{_M!Ms?wV+clauLT(Yp1jo1U^bK3f-RGr?fAnk`3d zQTt=gt8J+h6glI~2vG9{DQ3P?A+;39AULD$)B*}*I`X(Yc}gU1lzHxW_-P(U z76ndK-~qy%;FCMgGoe?w3!Mh}7vpf^;mKxLWp(IXJf-m9HJXzhJbz?&7hN$*5 z9Hy`{vx01%QAo>>+0l@)^57EY449$8o%auOWOLSUTd$Lx{|v@jGDTL;cl5pcr4(=#LV(cNUDUv z<4+Cd{z}7y+uf6fcZU|U^f77KrimZ8&1XNWQzAB)(jv6#j`3doFo*D)S2q98V3+CJ zt>0%k=!Whh_v3+$urIsIs41I+2+jV5({xeV{k;Uzn>Yj#Y?44D%NI!?E`mXV&RqKv zeAY!DSmplXJWqbYV#{tgexoPd8q$1^&?C@+Q7{H#@)MfM}EY_Uz9S1 z|D8KmrRLqEM1wTe_pmlmZg`-_-MRC9&V8Scv+#YC-S?}=Bmue?ke$24d~NIAZTI7&R_^>4c}IlD z{&RQJyK;$x*NU$dB1Z#0(%w?ilv8{Mql3}&?)isw<(@g*cxnhWxCc`;^EocL zCBfZ}WxS+8`(J5~IITBT3=bY~wk;CeclRwQdqh3Bimh#5e9;!B@-$y|Qv9SVU)ntR zq{yOfK;*i1^!%Mchn8CqxrqFYK>{^QdI&Pjr7tEf9lk+#t8d7G1ut{`u<}A4v8Tnn z#G3JC;HTGpi`_f@)SxT6hC3gTJ@B&g9P9&8>>%!}*m_svnmEQT#Re_NNW>%$MT_B2 zytCiJmmU$wk0}U6RB|W3kbQtm7N6WTR%|m2T}qf<_g9U>EqFxH(C60zwba-tvndz|n|7zwGX z@MyhpE_=WUJ&gq{J%rvI$=4jr;2Q;EoqI{@^Y+>R&7iC;Al5xuDn+ zih)`cwU54MfOij2w&?3}DUjEvizd3nLu$#b5-!v{B;saFCMReZG5jAd3bL{ZtN3&^G%CqC~9enB}V-vH&*cqTTIFM{dZS zSHcJ~a0|42g3iFI25@SMD;7T2nu0PL)lAt0KP5AHgD})AC7+^gJ@?$vZ0yD-V#V>0 zFd3D>g_0*Z(ARKSoUT0EHH8{vTZbkO%XMBBMcyrxib+R5i`3Osw-O74LHJT7-f4u} zFO>xocuOalWvGB_6nD!(@)0Z&I5dW)(2&^<@T}Q;)`f=fa0u|AG3ZObqrtW)lhZOV zU{^{<1rcbbFl{f~WR0Wi$&1q#`~vsV`AW#O^WNpb_0WuH{Zr*gpC^M|9(_zn>k1e7 zxki*;HzMN6K(wd=BE^EFvC4Kx&dB72a?02z)P*@oYewp8NIRm3Z;`ny;->_Vh0aAx z@6diZq@;^H)ws#4D$ZLx#}U;>8CyY0S$(E zVH0H({)7SN-d{blwjZ;|_{R~C`#gukf@)^HwlM~k_#A)cqt9k@4aBnJ2^`Gd9hS^; zFUyFoN(_3iweZ99n`k!yhLAN^LLHNeNzX`odeUmd8+8zW3W)3^AaBS8E$nr-US&+; zuG&?*R^ipfaj92NQQ$gRl^q8Hcc&?&%i5Oj%_xkRXH~C{DHd`QcH3)2Pn@0@;RJMe zA%us}oVlTNM@R(VIh@vOw_*@^F>XTZ3id(Dw3sA}4}HapkACWMnN#toeL-C2Cnw7$ zn@p;vso_$SsGzsH5~qF0NAuR6M7b;BgEBf|;#RkaY6|x;A22&WI?hjd@6J4RQUM~} zAO$T952xr0$mc~dQIW#L@j-B-uJN(tG4EhJDZnN`9MhF=nTe~1$9gys4G?RhyThh8OxyKUTIan(sv!{%MyD4||lhWt3+pkQuU)6+_DYvdq ze|qN@U5ZsBrq6uOVBeWnnTYJ5QYc;D{jZW+rg6eg_JO{gc$*y#Yn@PM&z}vT#agWxv`8b2w^L!gtlKsdQI zj&HeVZYw2t4yUyartq30PRGLLpDdXie;KYlN4dr2UwwBnMI-+qM)uJ%7~JMCerF{R z{_fo&K|{=gneb;N*r@b+iDXKGR5(cjrBCi_*BJR`9J=3k`Nd%`sO0YPHc$Q6U(S9p zdy)N^(>bm*67wisoY<4Tk5BihA4>DohxzHly!GU+x+ku>zpi=gKk`Fq-ulNie|<>T zVE*Rwzu8KQms?}5&wk+94_v;S&OZL>pJoPo53gK#Otcm_+TA_-Y})Tjt{!EkNq`nF_&a~cZP-TnipJpO ze$RU@k|4dQW0VB0b#08=^GOm&hNB}%;M|Y=h&T)ou^<5ZI6Y^n81OPT5AHosIJ0x( znYw%J+L6({^uAq6{?Py7Chfb#R?5$?OBH#*n-UmC!tcCx=aTB@Fkf991)iUPdSGCV zz1soGIK2%Pqi)QfP{YP*;S;-Ex7{Cl@A{pe0<|H!$X->~KQ#Uj5>T}C7f1pzkXEnx z>O&-wAmSkUUVAq^wC(*n%#3R?o#lK=1%azBxMexF$PuEnv}tD)_*dqw%0w4Be9>l% zhMUVxqc7p6uY!f`gvZD3aA>i3bDX^eoX0}RB7r93am13tjBgxs)ck%pwbBJ@Qzh{W zj|I~Hx5WoT4}(QX4#^k6>v{wXd{Q)p=>5=Q-w)CiRK%iaTGo=0A3byg!=c!eYei~0 zw|w%q;B#L(gawqDNvV}ffDestMH&gCLWvScjg4hLq=waV0gMxK(aq3mvN=t2Rynka z+t+*$)mTYCNCQ{NWx$lW70*!6)VjQD0y1|*Pc`uj)PLVz}7+46f?^O5)<-qh)v3eampNYn5>|Z5phN! z!XG33Brg$XJkDpOL$G?Bm1tz+a_q<6^0vj_pmJcC=j@KdlGHKg$7{hC@S+h(##*6} z1JtBLw7W7=E(%+=RACxvE)u~4a#0st{nSf}g<6)6*lNl)0>;PHrT{iBj2Q(h3uJXw z0~@Bq0*%&(7ARG#Q$}A2sVRrF-r-uY7nRZDb}(aL3YG47&AWA|0z#u1Td zaxd0Pb;r0FW>Jw-3Z{fq6fbUMPV+c<&=-~khk4+uN4YWtNEHeWO_Pe_Vn-HJom_TI z6;oT!dUjf=*<&71PoGamL=lRP$mxKBj=}aYCKpGuk-3Sn)3HQkpK_2<${NcuYH$tG z0@35CBm2l=gQDexm>fxpvZWT()c)2|(NXGM*;D1}dNb*qZ%KIWX+6_q20~PCMH6MG z40z-l*$(Msr~)yC*6OL=u=Hcat|RSX!9ZnWBDCa?i%7>^Hv?4_Wg-+v<`@taf|aXT zBxl+&O06Ek6B$)YDvMctm{*Ic3$?3*Dxub`CQv>g@yvPJ^V7pnja@v}gBp{+YC%A{ z3TJeld!PrcUFH_)Kx1a-CMYj_Of+Shva4K-l%H{mAtqW&3#f7kYL?n6{EEVJS%&cH zX(Qqun5&C+1Rl9`hp6>y=X>v+QFRPQR^kB}Dl|6~%FY!Nbp=>XFDxY#mvOS7kOfyP z+hRptWgU}&G8OWehZ3(uLLu@oWYBw&EzrVwt(5JyD+iL8=wOr+R4?Q}CYNBd;M%sx zu{EN}Wb?8>>GS{_5YZfq)G-BPg*NZ8S`j;Z%j!W{|>z9J>-6M9r zu9Vuyo8C@C+6kz%Cdh+DX0-{7Iw+P?&h{Kd9_gj^CdYA%iCFjGH88g(l+ze?7h+dT z4%a(^!8SwIS)?UUu+^U7uL>ik<+Qy zzS$?!RWZgA0SyU62-NTroZ3CvX*1T{h2)yQT68F-crJOc+qZg zW?@w8vU{*OdT?!XuwDComZW-icPff}M*S|yXQ{L^tuV@aHmo(f+!}9{Ie?nzgWXIN z3rWD9@OQPc_Cna~N$>*1R!rAE^rUGzU%b0f%bym$=?{z_YTW%iJo|x9T#=7L4HSbpq(C zo!goyJYUu`_iIOY++AKMz=aZwKk)nq{=wCMaMiUp(lGdr&jq$CSHAq^gSVF8f{^>D z_=SDfo7;c5jInjgzZ?G6KmW`BJMZJkmG47gIi!_fpOGuy-3RwndhepD+ZHrBr^YZb|=Y5FA6$ECrIvA=xzXB>c zrle$IfA~dBqgGR$2f&6~>{o$91?8-FB(l%M%m`Dm{u%Ns|cBLn~3-+b_zMpkf?Pb zws{x`CN!Vy2urE!$PA?}WKs+U8p5<8T)Z^jZs9xfqjRm7j^4S_E?P*0XbGWRjY8jc z$uad4L`h7x)2^8Xlwm2p=xnF3B^N-OAEv0pShdTFt*E0KWBFvwGF8Wvq^b<~c$bkN zKzS!pwX}c<9sG(7wH|C9a;%7+(OxG1HBhBd7Q$dxoF(hVnJn2b#M1=LKS2{8Wqwvo zy!o$AmXogOrg6dC#?`VZ$JODi3WXwv3GGIvSQ2%+Ty>LW3-%DUF%Sn89W5aewPHk? z|ChbDkD25+4?CakuBLi6D{YUkIx28%RT~CE=uYwGHa2AACAXTE&(a?kuL3QEEG+CA zcV>=(0TF>M=n&B?cK6UT_5qr~*~Bq+4mApBC@aGx4C7!i5>>+&C&JMJyg(;VhahLc zGIE9qSg*CDX;aIc`#se&?=F|5XeamIsor zh}}eh4I6M#M>lPP%%rw_o4ZBRHi6@yV6)o>eb4y-y^I*A%-zsbrm8!WPwdo9hH1+> zDS`#dGjfGXkZPXD*gy`tp2fJp6*AZ~7qSKbK1p;xw02n=1fe=El;{dibR&6eZE179 zKnMr3L>q+VkCB80C=yDND`^l_!?H7$R_nZ?o^n?>C44H7MESM#C&MR{pPrD=BA$h( zCjh!h(FBk-bCrb`Q;tr&IoSJP$6j^lq{;I`iDu(-@b}OGEFdedM!o`Me}oM?*=2OqEk0Pp5*EhU6lWjV><;meUE@nA#1w>p?Ztdd%le3qsLCM(t}S4v<`6!)Y&yB(H~c z!S!&?v{P$Z{6}6-AajCj_%)fyYM)e}~1@==ft6G=xRmdz{^wzVrcO0Oh* zT6YtJ2AA|r3$ScpX>D!Ec5hat1C)m07N0B=*`$y---IrRfyu&dUCq4H>L7|KA|ulr zMX<6{k9p=&uZ+}-%IjnA7W~n}`tb|)myzUsO}0{)-%%P^yh_ zumy|+CJl2F0!oQdo_HsvS%9|=EI@g&QG4diT8j_jz(FezVw4P94+bzCx#t&aB`X)E z_C19*3kN3#oe{&EX{+9Ec<@JNJiJ9@uC*L0*k8T)II)Wpd@X^$xs-ed+oi5^g1cZjJgusyol6`y7^Vz3lR9vwxi#xD zu2FIDWgw{>jS8AWW~5s$FOObK zH+1X)2f#qkBS^n@JdZ6A`=czK7~Kdgc6V9sB^9}2Cu?s%_|D7v1>d*o-)JJqBpQJ? z4w1U!p>rR94W)AL_K%L~4~?wyJN4Lm>Rx8`e`9ms-`$=&L_{{y?tk#3Zyak!r4V?} zJ$KykO9%J8Hrg}t&09Tghv3$**T3KQccoAWo;-2{K6YEuuaEzq?(+;&o7mxJZ?|tx zF@-m~c-S|?RrV^#4nMK|#3w$nNANy4H9Jpx8$A+6Av;IxfBDOQ@fZ7uZ(>8Tz5C&J zKl~=4JMU5Yd*;k1J^@KMLg2){@i(u9;Ep?f^i6Ab_dO6)tN$fCFo)lH;}q$LN%r0< zRsVoINvx6D4?Au^xp%Am_x%S|a{i6K|72UF@Xs@X$-5qT?@{}C`K;RR$8Or?BZ6$5 zFCO8{I7T6Ebo%4$chNO^#QgW1`o`2gn%7bCJOAq_Yj00)6W?GT_hZMsfP1Ck0hkxx zw%etFdU?X$gWHE5(%5hR^rt_q_Pf4zF8M#nQ}0_k{ru^a;;Bn=M#I$r!3|o{XxwOd zEadhl<+O|tc!ri_QgW$Lyc9%kfk3$ANKL299EITRZ&&+WUz4addKz#^zbyM1SlesBBq{{7tcM^uU7g6^Vt zVSCs1`gOgP{B}c%GzaxP|MMdRp7-Y>d+;xvxWsG5Z!|!VxPw3-K%f{L16~V(oMv?A zpB^SZazX6`f!qaV`SJ~oO^tti7L1%$T>8_i_XzEf9IH<^B8ge~Jm}MRd1UfT-{e7a*Cm8f zbesspS1eQOrPI$BdMW3!8IVg4YgSI)OfoyLQ;xYjnqqA=Qo@ZAQpo{cFq)-h#zOq4 zR+x$=P(lY05P=NXr}@-+19BaiKXM3G5Y<*X)$+#w)w zm0Md6i)U#Owu`rwt-7I^tOhn4K*fiWlj7ONI&bT04W*N443cajgdo(+1ch9r%b6Fi zsMivOCXp+YmxAj8tE6mHyen`cljB#_GwM{oUO9+H$HLjH+}e0sTD>Tg#5xXL-mOW`O*GNGg&C(<2dT#7jyGQTX&*7Vas**oAvDpAg;>(Ch3*$dT_5zC z%0cJ2ytU}40I^|g0J}EVuzWc+bLUxERvCxQZ7tG7Erkyv+Tmei~_4Z%}=fHGO~`Fw)PaHfIANtP8rU?Pu27)GRzLM{-Ro_X-OQn3k8V!mx;0 zzR5P?vW(*JFDmI?n>Boix!r_y2dP0@wS<5$s*!vli^>!q={%p%qWgT+EvbdBb0lpi z^ElM&EG~NZS0-!tF0+E^YEC6n&QQl!nbu`MgL$JvF5@r}P$#2HAT`fAXBMJ7VpuKtLXma8$=nArth8iHd(P;7Vyqa(|;y|+vuu0l->NgWBvsMXk=Rv&CMubeL+lox+S_@wmHH{P29DKnQ7iQCjl*eNA zBYAGAWyaF_=EN@I@5S2`hvFby&%Bb8;##spjXZjzOy_rjh)=B6XXS51*g)s)h2B4zQ1nRLY zL#yM>+2v4Mv}HIWeQJwp9Yfu%iM8m|zfB#Ov5&DSGw{m$Y+yj`W0*~I?lY!-*JKjO zB4of|vSPMe5k zzy9e>>|k#g5=~#j9&Tq#ctOI&(+icf7-PxQvj;^{xg0AW~K%vWnDPr_9L(g@p8=)f{Xom&UD3?ytpfohBM0<1}xl0e7+$K4SJdKX~_pcWbT(58gaS?K)~1 zFTVKl%TGT&+8TbVc>xjlsdBrc0^=6F^;e)5kJ}~#2Cd{$c(Btm>t4EWJ!yg8dEwml z?z``PzkMjAw!Zh@r+o5bf9JRb>dEWIyzOn=8=UNYoV}g!Ssv{mkaO>Pmz8|Ig-YeyWlRF3sdH?$rf>AYI{UKy026)P5p9|RIhOeYOeu631Lza(0; zgji+~Qo!P04Gv?|8;=!7sxslxjQ3u-!>PG29imX02JQh_rj91Nkd$A}WUVqd2MM>~ zEn_|4h%X!o>%26ifa&<@^1q>Idk7frmEsl8lDa00#hgpo2O_6Zs!eRjAJ)aGgXwJP z(pp4hleffj{B4-iBRJg<+ev`mURU|tl(A!WjI2jA8aXVKzs~+&hrGk;tfupJLx@+H zm_x0qLyE@7cV{cQMI}_4g67t+!c>_z*qL))jcg!Jb2@ubcVIk_4zUm#K%^jxEvID* zTr>Foq(rX7rFuQZ@g$*wPyD@@sFZg%bdFz!B!5{t2jjgI2|(&J7Bm+tpeeEI4yK2i z&`)OdnwO0MWL2c#&x6c@J;%Q5W)LDJY5_tD&0NPS1G)(J(2}Yw9I3h`87K(=uZ9YO z08;U_Bhj@Meng3Z^v1!4^q7EQd+u}za5ZalTZ3_}_bLpzi9PBTI(FDy4Ae& z?ELGImar`ox{~z*n2t#xv4k=j4fG4aK2b6Gu&wCL%s~H zoAe|BYK=h;aMktY!c=9;30G!j!_+N}-=JFQiZ*Y8^KH9?oVP4W^_Xl|aC;L~Hz_BX zpKQ3L$YehA8}Kw}MR}*~K#`6CgK8CsorS?%i2SU4h<~XKq-%S9u4H z>j@gqkiS)tt3aPD9L>u{kTip!5r|6;!lH&V4{0RWywmi2y%7o2cg==ovBPp$D{Ce* z`OtdCB_BL=%A{R~nniyIjTri8h|9^)ty=HEsdE`;kp~Y8lp!nlI5Um6O+Q)BdlK)> z%n#%>@7uM=01sNl&&navX5siFP77UQd0EyBb&dtR_yz)O%1FmXgiRKtHaQFyn@I@~ z1MIa~&DJYxw5OS_p|RGshy@x6Wj9%^YK8@y6Kq^g62_4BB#)`8%g%`>Gpa2az@iwF zj&?DhFvw0JLWqyF%V5hCpM_Q%ud~Fut z1?cexj8Je1=^_=EZ$YWB+kD~{^A*iz+HE+hZX)Y^leMx2fXRHrc-bz|v?1p<_R9@C z!AXXc8=odX@=vCmGhQrP8XI)D1lS?HFq9b2990DNPe=o*d?07`lGiXHY6~(T(}wXh z^QxcpQp}1O==VrE2hit1J-W?Q$(j)2_jOko3BGq$iuH`PUQ}91{c^P?BQ2?T<0ne2 z)h+!O#u0U(CrapW%^)bH8_J>R8@Qi-i4dM4oMED;t&;tUAAcn2vCEXD$B$OSGZaoi zAP*gpVGv9tv}Bn+Ylhag z(r;$f%u@H+rY`eISWoC23~iG*MFXbYKtsbht-34&26|9m0v?>qg|(Lbi{9%73)I#X z-@@bz4+H$`t#mM2VGi{DCU5g~I&pLi<47EaxC(UJ;4u_09i zl(lD*I(c}@N9MGhjP06 z)yY-LqxR|UE7=ddd#~}SU;RzZ!|y&i<>Keh9DjFedsKg`{+7CLg&>7@U%LBDe6G-( znfZ(DFKu;~ z_|>bAJ{q@jZvQps?g7D0>Up2scS>8t_S@SV97q4|Er1;sCzpRUxkDj1!allIoQ&80 z698Z?c(+{s_|N~mp8785fMI81+ADr){Ao=#Z?2^Wm75X{?y~OYU2Vc22lczR5-T_qvn*x_;IEdG~GP;E9euhx?-+D>%0O z6nv8_S6;d>Qm}ds+Lb4+{C46wZNzgX_<05sU;gs@p3odTKR$hh)7!TH;NZ0o{M_Te z^|(Sn6pnV|DatoV5Zu^ae~8Z%f^*x0Ev%HQ?;;C@;M@Taa64MLgWv$&{43$gZ~w@T zlrL!-$L7pY>Lc4%fshOy#OyDWOWCoJUCVYa=J1fOcBiKw9i5?h!u~qBJ-e0Sqs8a8 zAKexNCrs+uh?g&KFDobG()MQ()c@_N2RW4f#*Is83w-Bq{blttKXdXrTmFBWE9gcD zXeA0k`M&afuYmwI3psD^J#}y5m5q=e9$dQ)k-t?4&eB9re(dD$eDtG5q5PzC;N;S& zmyQwya5B!z9)gx}*EtE+j;X*&9bc#c{-UpR9bo|~VcY2J8 zMd%Qi+XUwujj1oJ?{tHn8!Tx$(sCn_Eervy>fA8&&a%X}(z`6q^zbQCbd~~GP@w@q zVQVr{GawyUmOPok(sO*I_kj(F2^vZgsRJc~p&KPfM4$)kXzrHPyM>U8&<{DJl9Prt zd^=w*oOfiG+tRZySb>K`?fAaTQ1)9lESJe&CE+NysZ4|9$5MkqvS3kT$GXiN0eJAS zt6495oZ_%NPZmG1biygYEc2Y!QY6{DF++z4YRxj#SyVPuH*O%r*# z0?pIT29mJTxobAC4WR9#c7i^_lH#&vPS?sNdN>&UHsis1*kf7Jz{Dbqnc9v#bJ?H* zOTS~SI(NCrEzlJCB;%}t+S-OXEr#5-*ocrUJqbmTT z)(6RE)WnKPad_vRhDS^32#8cxH|>x}b|zZll87}^TUmiZnYN*a(}FU( zCb`%K&XkT2OB#jU40Kjb)`NhfF;hCxo=F!WnDNbu1?ym$A0}H-au`3*juCU;%mY11>t!GbiVh!gGd;DvPo z0#cU!UQ`$^y&qO0o(d;*&Dq=ZvU7W)V7jjK0p#=ol{%fadXX~MAgj2)R5LcaCETQF=j%S!mimLy)J&zxdg|NJBS^Q= zO38u*TgF@h6^&j8V07p}kPF~t=yzGjbPh7WVl<-kz!4R^WoAj8epK3S(K_2@YgvTp zB&Pv%4F3%J2vk==$B2+aE?I3ZFhDAkx3CsT!=-|00aF!VgL+TCR0Y@tPwFPzdv%U( z@iSf_?M!LCFB}b{E`1*1P%>vg8As-J5D$tyUNBau9lqswG#WE0F^bS5P%_s-YD$`L znd%dptcj!@B4sHiMG!-hijpF^=`|$@G9@*h7}EBwVeDSc^uPo3*UMP?-T^dB%_c5; zT4Jc2rr1p9OL#m=$VZP&lIjmfv3Ir=2J($6mY9xX?-`g!lZmAb!TlVaiaIseR97|_ z3m)lmmLUW#deyOWL5jc~^@dFbq9aVXM(7=H3$iC#^xW;`GLE;(CC04AdqWf{D}%nA+DW#CUu-}rJyP4uu-XX-9Ryiw&R3~}gM0()KER=o;O zAH?*tR;X&;Vk}pAQ`L+0nl2)szg#;)3fhT_Oio^^=um>6(N3uRzM`~_mf`7&smbeb zm`t)8ibsRrd5v1>>KOgi{mf6u2Od_h{dc@6y{|sI?=(a`_A#&@-luSR^iMHUICKdo zt0{f3xA&)bC7J<$bt7p@ankx**Wl^*#1pDjsyAz^gj;XO<^rU{^Ov3o7Y?o*UcX)x z2d55?_V$sUW_F6h(m6vKYT-!Z>id{8X(kBN-b0}8n$sSFz56Bm5}{i`ifg1Z;9ftseDnPE*s<ziEloO*?(ZJ&O6pYz_< zoYlOMeLDoFk{ojTN%`a}PoF=%FXFXpCr@7BWO#)@b9(N%GiTJT5U5+@DP&qJFT8O2 zG+N_UxU1|I+h+srHlr^j|B&3zX5Yy4WVfHqE@!{M$!@=#1^Kl!|n?7J$8V=RZIs z{yBU8K)?L-_S2t!>QB$aOAnno_myv+2xCm8WKX|{xkR3d z5T(Q+y#+Dzxl?F0=lM_kgodjr(m2wCkiAKt3M6~kXYLsw;COPSk-Kfz{o>co#0wn! ze$N+91f?4v0y2f*412}(d-U6Zz_~pH=LPS-W415*Z~8Mf<#0jy3Af@veQ(t!*K+9Y zg~Q@dPiw>!+eki8uD`S0Uc870oB@RZ8duREaAgjE@CUa)s1kAZpr5*35-xxE?Dpl& z%idbz>nONkv?^L1Pi~qWRX=*%0s-wB2nt$zg5c!u{L;TafLHOv6@@@GQO<79o_!9b z`Vj)@4lck*xJ?pnNtVHv$yFCBXe{DZ)kDo~H$4p^p83!iQ`Mz%_f0GSv=%2r5M~vf z_@k~XkOL#i;0srGq}Byp#pf21SF#jWp~!SBwi*xP(=x&7 zt3GNSs6BtnT#EFCN+LHpp961JZ9I!{X}$FYUkSy#aYkeT!v%L#imU?HK5n)HfT%Llzd%qzkDN;EKUb&+nmi~$j2=p zA>UM4jo7|!B4``(DEQAZtJEwoZF*{}Z!_Q4Su3`)*~CzF2rk#s*up@#K@d~m%w|+N8yyP0V@hVz zvQv5_(a*4#MNuinLK&GrXfa(q&8CV0UP1vB3rk#A`sZNXxoaOv^}dz{^sp`Zc!TMGO4i0 zT6D9rNH_Y@_X$(u*3uuWUr(3Oy+B9~Sr@5Z`vm@zx>5hpt^7g7P7LV^Sn9VR;| z&8A!zYu_=?cicCQQbm>bt|1)OqUDM@y~z~WG3Q9glQ?X zg1RW`X;oNo5d9Eo@jy+TEds!ke8(?$^KLRTp;2I!6L|xAiX*Xi$&Ol8D5 z^;5$R?WlHFK?du~a&T%>1$C3pfM8~p^|~^`Tw1lEn9@Awjj0fIZzN1n-w5dd1JeW2 zTHHdZ^hOh1kx^hn)zXq4Ede!p3^=6~=-bY)M~C6R;9CUh6xVuMJ4J_W;T3Dp%H`m@ zp)>uID)73npQ02}^xfKuE0_(%q88E)eHUy8!A$Feh1e(}$&aGnOZmp!(!}u2v;x^> zuhuU7#Jyg%#ifCE?mlp$7dj-7q)K7{X7rvA=kLtB4P-5QCnlC5qyR=S){ zJGa%o^&RKV92`9Mw;!X2yzhOi)Fpo3*9(@;NBhv%+YArTW!Dd4QZQxs{g1^z(bc@J ztKZ1nn(M9aH{;%SO8z#3gnaRbj4IqB6ux$J?M+hCuK=L^i~DZ;5?hzgsCx&&LkR+p z2fq)@f3@K4Kg;ap)~}a*@00aF4PV#o-M8B*+@^4fu5xGS>h#kc*oTL=#{c|dU)p~B z=K^q*7 z%i=$zvh;6cPkvbS*&opMHJZ~GZan?U72QQ~iZjg*F6{kBTU+u4*(+_2)cc?P*#|z5 zy_)ZIw!w)?zPCS&3V3hce!QJ<~eFs7Dx%j7d zEKeosULklp5NNTL6Qs%QAwW`2>wD_V>Fs;Ahnr{O58SN7U9O|GmFIXFX=k}87tfy$ zA%!S&hyn<7^yfZTo`3eMr;u!Orhjq32%@zALx7iJlJ~1GCEfJx(fR1MpW=*k3_aoG zQ)htS^n2b@uqOP0G4ku4w?c6Bs$BfY|L|+H0}gdZOCUjz72D5kpZ#iiULnvC>D;O7 z=r-JhAp6N1PXUZVL&YAppZXO1KwWN78M-?4S}B>uoqTYpyU9FHjp3P33dUtU(P~l| znl|AqG7&QIZkcABF{~)!n&k#TQzV+q3Y@oVA)VG;AdZG>j=BO>E;Z3|oWhiAbwN6M zsn406Y+2ZJZmStEu$T>vO$J9H(%mUty3SxUVzzE%o1cR8?0Mr@+! zhxqA(Sjmt-Q-<5K6Wq?5aQ>Dlmi3axu@sb}Y%9!|qsdt!w6Ouuc3|dKTYPTCX$JG< zWKzX^Li)^yOP*PJj-MXCriF)64WqxuQf2`>gb5!g#E`{PgFjfuWYTzP6f)d7%bkUg z@7ihxhEm#8Kuf8S?9~uOg}iKoR*V1x~^FGCD)`Pz9zSBRY;(a z39y9c-Qa}qgG{7J*@Idl!9Jms4H=gvuQ|hckglCk%GeLAKgk8MX9a|aPaq)-n&X4b z%ScmjdDD~#!@$8Lt2=9*SdMwIWQW~KW;pt-X-g$ zT04i)lh|iengm*ZZ+qT4&`RWv6m4!18B;Md*b)1p6({AI`)xgm1012;?HhS2$+jJOd%OVmW2({+RV(*u9hX$-k=A+_*Z5U(&Pr|7yVF!4vB;?@Nls34HPf~G0;VDFv z9n2a8tszvwbTKoi?-z}Uw7Llk_I1o!Hau{k9%>>CRQcL8u$?3pEjTSKhJ0%~o+h%% zJ!Q3k$4}cRXxH}2v<-2~;4cpPy`4K}2y|$-=+R)-pidH^>~m0BRgtx|Y78$+X(8{C z>JFPF^g!ttS51=MDGsI-C?icQpE9b{9t)c>{xzb;2>@yB*)pgC2W>zD+Ac3Vu^nf< zbp}0Yqbd+6l2ZWCyRn(midH(*EcxCT1EEZlrFuI@IeO)01H9kplZ{FR@nM3 z1m-!OZ8#8q%uKcLVb0;ZHj9?}*-5q&YRE}KYeE6iB^#TrWz0bKQPnv+z}Nr*G`wTKgg!e%%}+1&dn@mLJ^vVwTS1bS2as2JIJaJxH&2;j##71 zBp5PkAo7D72L#+rzRa*O5xJ-%1*`a;S!eoslP&59BL;>{HEA{j6DYbIVd$z2+^l@# zvKbea_t2p0CSw;aSJHC>C8Hh90Te?@(Rrc8aOEHwTdTilz402}3BKNQDwi!A!e%n{ z8iNPSWDi|l=;5Mv>fpp|*r5?tfW>AI4rd5KN~mOqV*A?mC42H)+uIGF3M%S6__vZ{?VW$ zg7Lci1D*|lqS{4>ZiR59Exn%*-$^^A9T>L`bk~82 zuUea|M>B&?$*z|5pi7tDO*kpe#kFignW2M|&oWC2qsh8r&07r(-jDSFuF4WG(2kX> zY6>hBMZc%TK%Ij%WlK^`-s`LCTvuOft)&Ewv`ky+bdhQ1Yr%%h)sGDnzpE~oW@v|R& zHUIU0@%R-@_UM&s-#HO-uj^vfO;zdMujKi!5S@RKt5@~T@?Sio?>mG4tq`d1tq>f$ zc^M&q$^imR@7$LTo<8$b{L|{?kA3FC#h?49UL#*Qd?EKI!b3oyx~Y5lqC(*64}U}< z_{B3L1PYRtOl>{GT-W{I&E`V5gO6aI|39ApKQ$}Re)^~1gADPL8yf#K=VvDf{@^!%>fe3;FDPa|{F9FEem?ms1S75dA@`YQKfDaXhkg?K zf$)3S?S~N)e&{DPJkivLStyjY{^jg)@oUDFoWstLjtO_j1A#r?(85n9pGW?Y(#j=n zrJ;TKNPbzA>NcOEI|I)npSmpn8uuf#!Y2hzz@c1vP(*j!pZu7@M9sE0IT+jR7edK- z?A%R8;k1URC+h#o3rE+eH2x2MeEW*lGnDN}+-6!0$eS_$n4Eb1L-E>fPNN}!KF1RW z=g!{8E@aG)efhup&1as;^AmTm`y8bRbe%t@{^xF1lzbroL3#Jx&)>y~X9|Jd!majQ zM`wQfWbv;Q0y%Mx_V$ytd)FTv9R8?eJMHnd{fYbUR|sw>7Yo_?_UONS;e{8jgo86T zA^5Q`M~u?S+ozs->OJpy4{w+qZLP02uD^10;nIT->APNeueO@)^(%k!mCaW+RQ7Xn zN)KT#pTIL-j~Y+0lw$Gt_{T@gUOoHVb^4EyUy=8YEncCc(K2Kxt*l46gQnL(@HA(z zBeXxK>D>x}#A67q$dLak<}J0vf-n|dth0-#zQ~G+--sEEvDmEQEZ_3e z1*E3Zr0-aHl93%V`YunU;qo*~<>OlZX54bvy~iEE4mUs7X&G3t>g0k!u%*+WDQt3T zu0g%|sr@>WyObZY!Pf;5Lg{syO`SQFL?hv!x4Kx;65m9rF2K}SYoIE4QMd%IH+?ed zD_`sjk({?bl=+Ow^)UdgbK{$;nyR;coC0~Ok7GvUH$s=fQjQWG)$H(42x_&{XRLm# zzJsS*%UX6?gZh^Y4TSeNI`q8mTweoUboyfX!ys)`@fTqz?3Q@3sm_f!tOL8!h}8zx zsYHc_BR}15T4F=8@QY(&lyR4A0!bBfBR(U@yo?B?@eG6$>L@ibMlC@%$;+-r>O`-K zWmgQ9<49fzf=Q0Fch1$<_!U9(X%Jw*yg~lT;y2+$t5k79awBT2zJz)y4qI3DtUw^Q z)t4eS7NHXUHb`()6Y{wtf!6QfQUnun7J5cWTF7K-J_jhoETT&7d0|mppR+LN_#mGW zqBN^j890zxWPCEQQxKCYY=br|64er7tUi{!D@e-%fNjpHVg{+FqCRrFbJse=v4~6B zWdjQ6iZQo^1MQquWMM?maoI`;raL^5wC2WQ=YzVE*_ATAmpebK{XhW#6cbYem>PX* z&)4q^_joC*gYR_X0^9?GP*!PFi}0Uska4pt;-{>TRJkIm5R**G8S*la*ACgx8DrS) zNoLmauJ~y9kx|s5Gpx*8MP`K*yJDp+Ha2r~>Dg}X1UdMewt=T1bTS~?9!R4@CsMoO zAZS8pJ_?womVU5Vc)P{8Tiz)z(fO(8I2OVf8B`5-s_h7YD-{=E*(|Lx5r>H-B)Ylc z3ovOv`ZYwQ+JQU`(TIadXaKu8WiO!YtGTvt?KWZ@=-1LyejP@j!g#`)u{1AK7rF-0 z9H~{1xf|LJZcZ@41-#V6(s^^lg;2^@C?vUDfO^;7ym#)RRGdhp$jj>FM{B&wO_HS7VaHRuK z1mIE7r$i|%6C|2qbsl5yGA}mMl_AFE%!pBZ)TIP&o7>!}zFlHQ>1sqL;{A$+DN`40 z!bjr@Nk2(OC-LOSEkcq;H-v#Xk1w+^bNmvCVzmw#=^HXPc0f55$&fFJp_*SveS{4_ zu)GBJ8xH{FDB6^hy3+cmQ^Y2tsA07?8Z9WRLp4#X&!qKSh*C8~u=q{!>GGy-(N8R^ zcAfdwbiOQC>>J7kH-NCn@}pyEFt7*D^9kT!Qh~DE2CM0GK6-Z3aG(wA7?xV_?z|S8 z1&E9v@rA~-VRScxuP51>2!`d&5F-Kv$~b@y@f;LltGrsQ41$yjHLr5P9!y6@V5A94 zz8X_ULs8Z;HZq07riI{5HxZMuJ3GTxVI^*AL7!;EsgH-Q;nYyQ8A;vjR212;chW&D zavzCq_M{k|&neGX_z|ZW5!E|AgD%$jd~Y&uiDfNrO2wNItqxn+)v)Lrgu06vYcj34 z)(&OUuF#W3ffmiNVZJndR;*z9vZ=OZYo@c{yz-etr`WAYCgnrzP}!(+l9A!nNw9`? zmJFnp8--u$w2lYxQT|Qe(3Sy*^`u2iNZXi11Z&-3m$shO8NG%YU@3^Lnvbek? z{R;VycYIaBi4Lu*K1ZQ&Z1rU&OG-}Y69GHmw`-9!z084xx;ChP(HtQLpqx3=H^8;7 zD7VCoptnmY^1OG!T80KhS&<8=1-V<>8rhiAL!#8V4>bZ4vI@x3C=WtOBYi@MS7$;D zrBs`e>`gxUg9viL+iPeB?ib?bj#v(vT=Jb;_PDL*bJZOq>axfnEs0hQ(a}RBT3My< z`ACfwZ#^PE8|y{xbNULU(C$Xfs&YVtKcCj=_~a_*W8I&d^cfo37Mh5D?AJE*@i|`)h8?k1%#6VY3{VyqtvLSmPx&4B%ypPMo{dA^ zK!a+4q$4>}Rm_oz?`3dJQ_qXaw2(laf!|vEu~V*vfCH3IRfjd7l_+C&QrOmWzLQ18 zlBD{1u_$2sb0sf*A+RmadmZfh8ETQlKwWQC+bhzMMZOqHw3^{ycxxR3$%RbG5D`|9 z=}53dAu%J_C5{|_tDgL=S{lxZGB)g?x7pnF)e0K01X0tWbQ|_3_YO%9lM%;ERisfB z-6C5o7hPX4T(I97eL?Kf(Y7f%Y0{j?gUf3&`a(;txG_30@IoZ2UY!|X*cokVnW@g{ zdTyq6g?A~_Ogy)#Ws|&M&>7fP*evGs&4@f_C9SNbBpCoOy)+rz1e7>AJG$Q3J|(Hi zGOjVypnj@5IGx%GAo$wZPUyh6MWsKcC~X;H=|OO%a?##V31!clo&m%qKuGPN)~9TZ zpK&&j!yiTQzNRX2#BGgM6_wht71R|P%AfZ#ZG!ZHF3@;XY3CA}MtaY+@eCk^SAQZ7 z3fI~fZJ;Rw0x=3SE=fSpAIN)vbbZ%S`;}`0+SvFA2Nux|_`2gqT15Z^xCo{N1X3lH zN|jSlW#$NEC+n<=rDJN&`Up^p`aGlEVn=K?EE}#rVkA@D77iAha3g|EFhJES6RK(MGRLuGE7x$)UC+$T zMPi^smG#StCQl7#0lrsV2atxqneRy3(dUT;vYA|J&~K4QtD7Pz!jxA)JOph;yK#zO zx}c%k(iI8U{T;r@U0=g4m`;|+UK8poYG13M;!mq?1sbI3>(*0&{N?Qj<()?4gZzn+ zJ9c(*>vCr2?$pNJP$?=YYp@u(l6^<=IiVgJLORE?Hew`yY+~*G+grm$9=~`Wn=`lA z+rvj6-Exu)zq8k`kM{ORZNj$~AD8;eP8~jXB-ak#BGz%RLcrG3twM1B z{f|9%_Uz%ILU8u%(b3hj+aq;z;V|L%@%!sRaBxm_b&s?7|M+FEA-lKVTvK)*;|=X* z_}K)Q9o)HdSI>U@3jo{`j?PSI?@g;rhNkJWG9`D*V?lhleV6 zd8>&3&wba9G|mWtwt%BkR(}h;{Bh0jr|wNE&ukvc>g5%|8MXA{CSr&WdC)#1L@`&Q8#Z# zA|yOAYRVFGe@4_zn{aMN`eXU81*zYO2joeSZ`G=_`kf?SdheC@UQxW9Jo(&nYTs&L z77|m>TCS?YYqa!idjlumo#2u&HHZyqe=l8l8lzIZ^I!ey`Ty$u{WDumer6Nuhu_QT z$3K1P(j`q*HD)gl619Oa~`?jShvD#&4!w+A1m?XCU<_a3ohlhd;?u?#8 zuBTZad~*AWd}fsVeeG+Jj7Rg=g+Kw-FBF11Pv80c(U~iE6-A6FK;QkAUG@k<_cX4ByZ2?Iplhp^}#3Qyu5czh4Y=yjrq%Ne6>0&B*RFpD_V#d&yyd9 zr2+c1%n4Z(D*?AyrZ-|ZLUko#c+)v1Vh^FWcxM{sG<{~R^hzu>wqv1%<srW|vqSUITSym6ImScy&_f z^d!!);k#Y2cV2kl)r~GYTH~|UsA#^VrxUBSg|Yba)JHPVATF}DcjA&ef_2fIY6@9d zDyqgmg@#fo+@2rR8+fYGY!V#m@adOeCYDK5x33|+9LJ!tK++gFYj~C$GUF&r2uk=g z0wIFGrm8rI5*yM<*yWhjl<5ex6|LCD7NRRA-rzQnBvCx?R^5*JsLRL@riM+&g>a&- zW1+B=jwm47_0c)U;ya&A8-b~mJJwX(TGBTdv*j8Eg4Vw!6;AtqwK0$2v5juyt0D8mt;04 zeaM7VaS+k4Q;3tU^O>3`!whN^6>X4O=z1vU5T^=x<63Xh%^_5*Hht$aKMkuXO~yh( zXyy^~DnC z;*(4>bz4^dTno}`I-rC6NYj>0}Tf4Nj~K;GGZ(_$(Qsk>bou)5zDSs2h*bi zB^?f`P8p7jG%*ii^MS7mXQGKIx*`E2(-Wd6HVIJToH2xU9{@X5x-2G89tQM5TQhuF z&BoT2mS8FA&al~5g_2~1E}XU^urQ%tkmg8`!|2iUz`U`Za8C?}3sp*Xp)Q8$X2KP; z1lYpjJDSkXCmV_}XOCV7DZ&-GJS<<9zVYqC0^Ei#^0xOgzw&Du*b>~rdPTF|drvZ! zCIpsYhhf2Z@GT>+cEpG?%hWTI)oRm(3EIu--1+KToZCi8EBH_jy?cVYjO6*MDNzFK zxUV*9i^8Kv!dnatU(;B~Z890M7##ys8vW759W!fk2dP^wnD;n;kPji`38}Jfj*`E{ zJt#zbLsDUm16*@Va2=K?;|I49sCV53PIGgi&1qsoD@EJDsxoWt&C23H&M?oaq0GW8 zcagK}T-&;NmW!k9lx3YJNDkQ|E!z~W*GacqtYMf)*;w)%4VvMywicD;Kr>och95s! z#}=5Tc2f>*gG#0!$`!nfd2eV-eo2xQlLzg1&BU;TsPn#|TqxzF{_dwfZ8;ZC9rth| zL4s>x*m*yhO#7Cx{<=_Pl7qLq$bv&ScQMihn&_5VedX{}>ybgR{xvL%DB8X8b1_1et4Y(5|0 z;dCI8%Cl4q3=yu0i-xF5wFjE_jAm5f?lL-pnO9Rca6FhE^+*q=!&(xYI}4%Q0YNcG z<(KV1>995uF#}UwYsoghwH@G6ZRvTDn|_k<^>PyGWdH~Dd|vhQ>3Wk5wE9hmwK6g| z@f$`(&Q{yJnVFac(=k+bVge;zkow%>*4aXG-+DTW&L_%HWUI1Y$jUPZ6xJ#rqjBDG zsx;TA&&tr)DGE89U(MhpvhXlzHx1Flsu`A0?o}DeD804Ot{Retw+0g9!V}x;^y_$$ ziS-NzUb@}wM|i3EAa%*^)O(Yo6FGlJIwndHyuZs>=b99LOvQul6hA#KkFO)uF7og$ zq*0qh?$x;1^6<{yg+m?7U8k9$(Olbp=L$M_s*`x|;JJr(5#-{(_@{}QdCxb#)%77Fk4wTBy))e;c zF$aYJY)E&PuFBc@wpE=(4wJgHhv34m|J>vHUVrP!pDtf{;{545U-*+#34#YN9LPN< z?m1D&o!p80tuP>%)l*sGEQz)2`Iv?aA3#+tYt0?j`>a{l+$ zzy2XQpyu;o^jFQVN$1r;`^7vWm$Tnz;P@>$pZVl|Ql3oqkpyf~_(!TKTb9JsknE8Y zYL6PSzlVO*BiUuy+rKutv(fhOf890iAmZ4tgbPhiF|WH#_5F6kPDaUp;+}_2aS}Ou zAz%FS_S-aQrIA6v;VT%WSmo_t5-@5wY>iGc zJex;*q*$; z&p`*OG;XB{ArWbY0xvq`xM@?c3@S&lY&Vbc@QtKTp7fwzj|QU zly+>4cpCP=66&T2H(zgu+DTbwMC_Bl6Bk#?ks&msZ!452Btr*H@9iX=1OKW>wQHg-vn*K;aJ)PTnZTu=P>s*SxE12A z;aLvqj|vR@8Mp}!yqfe4V?shVh(zPJ0s1LRXDzY21xb^P^wp!Ht&kja5FDjU&QsF>Oi&#+==&@)J@4OEb`Aq~#EYS+zZ0JDQZi5lOxo-%uy5z;VE zYXud!Hz4!2aO7v?JcbJ;RFhKJ>{CcF@?DIX=5k98TwJsd*Z8pCsII<~$l(NC)^$y> zDcw2>q!aW`XEtDA3@=i6G2LWl-R;9|)ckib+7x3`Y_dQMqG$>+9;Yzofb4Ul;p9O4 zArMZ5bP8mre7=6!_5IMvWRvwMFi4*f7PZPs{H&e3!yuQrwI|3Z1(>#w{t7 zeB?TJoWcxumQw{@A%J({WlfB}+>k?ICC8u2A!H249mL0eHYfzNMGYtTH8B?6yMD$d z{Not@HQ~|wSx@&!;l@i&4#0pjnZ9i|VsVqW8U-wc6Gshq|7^53?ZY9))mu|Ijsg6D zbu-2rgqxe;oqnHDk0S(KzZS}myHBlj0MBE10tNrp-5TC)!f^`6F-U>B*rm|*@%9v6 z6FzK6pf9tIN|(;jH2TQ)Xc~#SJF!`2@yJ33gq_oLZwaSIz}O??IEG~1=GGWFZ85X< zIGh|_6W)Qnj6=nGpTF~ef4B1g^Iv?caFMr)@mAsg>pzJ*5ZwRtw%yyAeD_lP$N%xI!bRRH##@Dx zSEdbLR~l+y&522V$%)3%G;8!VYn3Ak4WctJ%k3;Mx9Lo4v&NXJMNXiSKeSSuiMb_i z%gmYiET0r+MINIu&V&X&qu;r$+6+JBd29lMFMF@{ZWyEKm0?)_T9V$#8a11yL6e4{ z48fB1F4s(eqOz5p{AaNPg*;cl_8{K zk)aYNDmL-LHG7sy+`uAK)3G7i&Vao}mwA z2g<$4Bh;euw5?P&gWt??1guW8*`@{JJn}gSdE?W3=7c{jQ$u=K13xv1NFfHO8X@Iq zTn$ajYr@@>%%FoymZY=={H;o_n9?lI40mm&sO>Hsg{v;Y z?+8V=Q0p`rYV3!h2))F9I~ydMlP^Y63_cm*NaQhI?UKr~++2KAS8# zRHA8BaB3%UIf0oQNO6EX=ae23%joGmZA5mBm+AOuHo)Em3MD7h>@1Psc~@+a3+yqN z_EOl!^n3>zNwp^bmQ^~~SmbSHUj(Tg5Pa6`uZ(t=(w z&K7#^4g{~GEpVx=vUd0%N?TcD7FMFMc@R?u+nRc@iMjE%rBG&RkPSC;D49VMpVK@k zYNQ)Da>dy66g>B+;e5@?w)|*<`4rT6*#u8S>N0GMapH1FXFiNmYs<3trLhz1R}wXkJBOM~Na7mo@5&4dS4pDW*j`MduR&i^fG(7{-v)D^U>DEth4o z)nD6*;z0^Z+a^9z;YfkZiiurVyPD6~Y#SJuib;?)O^-WXR!azJQcj33bSa5}F-AHF zP6l;p#qXX98{=V?JUB~srD(ye+6&K~ex#L-s z^#{b?bleG*nVGbW!l5J^jDzy?>0P$9dmb@7wRY=w9z>x^*ikz$sF-!-Mx?DcXdhp)-cs zdPypgfXE&O-ZMhT*)iZOjsOGca+Z%dnBLmA-(Gj;jJW6G6HLT8y<=HEXQh}t9djp3 z^73sjVmT)Vj4d1d!vui%)Kfp+ zdg>=vn)WJMD!X^Hbazp+<<(5dfUqVz+-^#XT84CuON>rFiyz);X=ab~o$B3>Ji3O40l{B|RIk17OTTyrcj2rY8Kt8f#pnV9XXH)$U0aw#p_ji6_e` z+F2*8sH|#sM6g+2Wz!_Am@!|{%$l0!uMUgXqReua*Q-lA8$(rTxs1G=l?_{((`4$Z zhO6p#X)KFj;%Iy&%dJBe%Eb1XzsUZ8o%Gj0w(uJVeTF%ex8|gbaV1BtZQ0cHKU2s4 zjB>=RO0RIcHNzJ^n^fglna)$SnlanLaVP@R zy9kB*e%OitN^!f58#GP%pTzMat)uRv(QP=Lt{HjR^%Jma)U6Ukhp1lNcBnJXOUc^8MzZ+ktzqSNEHXe>C)We>X0ypMC`XDCc1v zYE2i{wL%m3>Ymwr-}$2$j5&XPbMteH&kjDlAT*0&51qfh`poJxpZW63T6PsyfiRyZ zwsaLjSDqvKJ_vw>n^PdK0}4)WZr_B0z4LpUpI+P@DA?qkm50usFvnKMjwP=#8;?G! z+hGJpDZuFx>xuu%dkk$7xS!R-`?r&ydyo6YXYPM!_iKOWo#=nG`^1Am|L_w(>gxY> z>t}Xn_9HjmYFl4=Alzol3a0dFuz$kncH6x~pHxyZPrOTa0PXE^_YZgeV1Kt$y5^ln z_U49K6MQ=5prhC{m!o5OO7+Z`cmMr&UK)MMgm+uJ{ik}9=IN_i@NKy~+kG9p4?Li~ zx*Ge1IElZ?t#SG9P>B|zGD4hLU6^{>K;|L5v2 zT;2SGpZXupb`-2uEDCS6b$=hvIt8&9IxmL37(G9&fN0nnVT@+^F#xB>uK6jXY%TCD zaJVyc&8k7Y!;z*$!D9%`-B*O&CCot_;dE{Eqnhw)yd)&+;KDeKk6mz#swj)&y4KzI znv_v4V;W<<+mD_SZisEsy6n@wAL2HK1b_Vkc&Uk#8o+ltM0-M|(O#it9wor-k`#IR z3DWQv&7G?FwzFU$O9v=h4@T|A^3$9~2OerP(qj>(a|-r-%OOKeLEaR+a>I|IgiJC! z*-;&;<)?GGR-a%RMi`Ph9?EezF%dfR362pOX+z7nkk3~5tL1Vlh{?gq5TI02N}z?x z8BgV6LZWn*QB1XL$U@_qp|y;JkfNsJoVg?<=?qG>Y{Wiq;cUFAQjvR0AjQNcNY2bx z>2j2%N! z){Gc*L#_>HN@I%;(e{$)&?BC zzGdD9+8AAP)-&s6KF`@D$A_;DAu>zywj?uEVN&>0G-e#4Ml~35v9Nxa7~>h|j;FXL z<0UV)sE*V65rF2o@j335VyF%IQP1iU>E044)e_70D+IXOyP7yG1ctqOgkvKhKMD{) zj}Tj*s!?ppvn(Lia$aagGbAIHE3K(3Td)ss;Q+iUS9>(ct1Rf2oU<#_Mb9A?LuQsS z@`eKh=okI0tT@eP2Y98{(s%VkAvU+Fj{CF`U2+{jtOUkT0ewbJ%*4snV8)h}#-|uy zhE;u4{E>IK4r`1+0%HlCF(+UWkI^e+3q7i@pwnCD8AtQ{u+K%S0@d(=Z>U?levGLw zGZy991_-V?XY8(h@jbd>Dz2X~jWZie=lvod}%vopvc_|sw^Sei1a%{th^B-l&vIGgUyhUH+f zWT$Of*|{denq-(*g<#5Imp|mX6v?`uGN)!NrEh2piB;vB&Qh*e-W^w9s#vL{Os8}W z00L|%iB6ZBj=1(qH*kJRO<*d=Eoq5M$`+;+#+Dw5F<%gpZ#Yd(m6!+RYCEn?UZu-y z$SGe2FAMgCSfB3#|e>uhbTtH<+#s}SrI4^DG0c6>2j z?(&TqSmq3L0F~*Wd=^rs7!K*7k;rKx1z)D4xyiO(Vs2(Ndrs;_-ON&MPggtzatg+u zGu&`HO*p|icT}dFcBg9|(rh+%O~z)Gu^TM%so~B?dW#v;RSsf$W3+!|Z5BTVfM@Z*PjWK90 z%#u!kP4qqla|S{(@2In*sm%s#4D-34o7&V9KIyquQtmNk+W@UT7D{Z0@cb9$vF&D5 z-gi-fkiiRck-7Df0LNP0?7QIF%>yVzK_K*S#`m`@skQ=0Dk9t+wy{)Te@Y+UqsV z1t`#NI_4$=K{%j%d7hcNx|Ng#zf8W+Q-pFL4!7z^? z3hqIGFdy9bkX{M>YHtNUe(=k2FR##q_coOvg7pCvhbY*)cKzjF{h^TeC>trBNrH;9 zdj7b%60RN<1q$(4efjcFm#5xB`kQ8N^SUG$^TEA8KD&2$?>f6-wX-$s90yRYGbjbSrTh_svV zM7w#rmtH=*`s`<81XOCJVu=^h_uXHGK@^1j-)mt(5$5aGoLZwO2rs>0KfdCP-VUgh z7oI$G=7)czcjCgiXU=ubNA-hD9hi)vrvz+JWs|As+tBgJUIaIdeXVgJ)F`;9gO!{u zU6m*czGK`vjOu{DHE8JCJJ2VIFG(Ej@hR${#!&N3VHhJNfNk~l{IyR1F=?-=cHWlY zkoQBOhQWp;B7JelOJC4$1&XzJ+|B}KzQiD6WenBX1FV*08C-`%STy4=LUd^@hqW$9 ztT3Ie4bvQi#U~|6PLnZ*Tw-(lN^Fa?;f1>4xZ+G%l?_cp<-^R73CJ5O9FWYQLJqG4 zs;kNu=>#2l6qAd&46I~fi2-I@D^BrA6;zuzSP*6O8p5Q;;%13Osx7ppKdCC&;msiK zPaIU*vBX_l(t*FY9^|(pqN@v?{U-WBC5hce82+iOs&QavuVLFNc2z8OMXDj{bTC)Z zg~POrYWta^dJvj>j={moTe$9p8@5=91e=Yrm>Dg#?!uERd@O&F_ zmHfNDjriYo)Di)K-=8YHU8%k9zg38u<+4$&^FXv22U{NjDm-4(B z%x3f)MZh1tkJ|BVNKbt1Oqx#KB}UZiPETCp2*bVZOGofQ5>AmD4t-BptToF-_??u) zfFGTy+jqRVT?9m*ov81M0AP1lyZ(c2SaH{dU>xUI81CarI8SWKCXiw{nVu@#O~A`7 zbtnJ^K*R*He(uQ0^(#yR5d z!;N;P^#k~L6#^Z=vXH~fSS#H}-8*d{03ad2r0p$3V+h62dK}RLAJ^P&v?p!sl44cB ziE$x3_sa!)DSc+Ld0D_g>WNTL2Au1bUbU~1gg7@-oLh6n>_D>*3!1YQADmn$jR19h z6P+CtOUG3KJomTU;V>3d@QUz+T{XN3&`etP#E7?3(<1?n+S^J2_k9d0okJ96m!?Pw z%p3MyQ42UHZYDKnv{KH$5E7bhgxB74*zKs@?E7~#^Dx1;ws$_a(huXgg{}R_-NN^q zcTU?V_9jvFrOdSU_@@HNO;U+F8IOAK3FR~DLwlefXuUiAXlR1o9Gtzmdwp}~byr)$ISZ%kym`y{Z6Sp%x)%6;vBk1KWbTv}lQ@U~LsoAb(iScHv8; z9(TXjeWlTw5LqcV10Nl2&{S&C6s#yB*XqyXey{-|o|Ilsza8t)w~JN+$M3rI77}#* zZUGK=-~P}jPk{VElNGMGQ9zDkCsp88B@e*M$j3;!eutn2kA9tF*%|hAp;D^)$v4SS zJo@+sY`B^*WVC7NWIhU(dTs;pCX1Y~*l_`Zs&)`-gq#|L5Znps*pa}-eK`V&;tnuq zgTy#EWjxPRU=neu>!INDAE+aW>*u{;L^#@Lk4sLO1Pua=L8wg6LuH8yA|Ou?*sKlP}`sp zp-opzTWd5o4sC@b54p8I=}N)WiWVTDjBp;y!tQV52uordv7pA-5Cp{s124c$*l8_b zT-~&~G>*6H+F396Xm9mKF6>6)oI>5t^FhI&Jg~?SOvgvKxNepXi?(y)fV7YGmH2~k z+{P3T#{3QwqU(mgaIPVIJGvHABy;lDn9knm)H&Tup#LS9&C z5JgLT)U}~qw}&4lA!1W4Ieeah-eln6{g}H46h`)SUFNxQ{iSgxi)ED22^w#vDjj&r zi6rmv)y_Fh=5Un-rV6_iwfj(Hp^%WLJ&hFv1Beu~=Nq^>`;a}lr{4I1ZfZ-}b5vCg z;eGgVuQ!{c7M7R$T$as^s-uzy#3(1Sx!6zk0F(@+(v&L3!3;l0Rjm++aZSJ3T?Sb- z+Bli6ZPhQW#~OCeAclSFq2hEr7m6J^w7N#<%oDP%1~0#fFrkDB!i zk4DuixOe)9eO<`n!_MC6WTkDz)D*727$TRqWm|(F+|`m*;c#IS5K37u{B+-ybPEGN z0}E+H{Th)Tt0A;|G}rUI>?+o`7;45B?Ww_rA9Veb7c zjNCqOtTcb2)my*les3AA;#YvEmlw^kZP{l*moeCpp%3W_A}A{}+Lobcvo!d_A(N#g%!nls!Ib3&dL1i*EeF1bhYz|`Z@);cvTP~dbPi}nO#?>6KD0zQ>V@9 z_n!Z~h&!sRCu7)4-h21YgtPygmd@p~T5;#JU0JO+$B+l=t4%#b4Ds8&{lWbF5eh

bAdN8!XdSFzp{Cyy=@};uAcb==6%Pr4PDjV!XuAtp6Se=`1B_} z-I=r5zw^oKNA^|}Tswa4`0KP5HyEu>y{1?ZvHR}7u_fG5M$jzWElyQ=~Jl>l~9Q@8d-Iy)W`*$9&LxzwPH() zql5=k{*bFbh^-X)t+{kYe~>Q@trD!}uY=g8`o`jb-_U`f(O*+}hnw7E{0dXOMtqGO z@bcF>P=q>D0kn{HddQa$gn>OD-L*g(xmnQo7&s;-?jaU?Ef{b+T~>}lYz_`+ky9rO zOC$qMjoGxYrgS2p;lizkQ_2a4qBD?z(uPAXHTaWk1`*cSF>0Mk6wIto2$u7QF0;o< zY1Kgsd1deVLgINC2-fILFr}*QwzAe58~CFOw87_uPPAtMHA6@*Z*uE3S_?_|zNxrJ zmWw5NBkwYT*W6)+uKT)EtN~%rgW{zo;zQ7bCVXD5U=dauU6WmlYpg^OliZ zT9tWeS=AZVxO9h_6T_Wic|$Q&h0XC01eBy*a}pNjzyrA?{c5-FEq5yj8F>=$b-3Ws z(gqFz1n{)7=V5N-CX=~wZJa7i&gj_~zvHVShOfl>LLXrU`O~^r!kq|CTFs9J=uy2` zte^h%tF84^TVospaF2fgE@EjRG5H{Kl8LH7eCynA2+_A$-i6!OT_fB9$Tc@dM6=pA zlA&W3Mq{WT{o#0@6hD9j=6sNE*f9XN3E+84-uwQf z;k-Tkata*cg;<{F+HoA@{2UpyJ!^KXOPf%edEJXpsndl7RJ`GU4$~65raCB!jExO5e<9jjBZ$<=TqPxCdXf!brlYO@-edsuXu+?mhcB=TpY9Cd$m?D(a+w3|-zc-ZIC2%iN)d!I31yd(O8dlQ*?F5Vu< z&e3o4{O0*LzVYT1{QRT85bm_@(ujI1q6FN>m@71hZWochzW(Ufe@ztZ5lj@Qpw=nC z*(VW2r&EnH7oGkr)$6O%d)Ik=+2|qky%jeI=*GRPfutK{?!Qq#J-zyySATZz&VT>0 z5M*W@!HfmAXC*^ZjW$-7&msvw_SpA-|M#Cb{oeP!m;7JjMe5bl zr=AXT79v&+Znc_RorFUAz^7jRiRh}+@?Q#f0CZC0=H}Z%lhM5pL*^gCJV7fnn^s@x zvJ9HyD^b8R-(P+D)G1Q!QWAH$;4#?$-t%8uE2Aa^IiTR=8{{AgOiMv0Gk3bC6yiH` zprfzj-p0U+YY#v2$ni(cJ@V|cF`bWcbAeu-3kh_}#{I+3eXg@er!EESDYJP}h6~J{ z@fv)r(AXh*Ef*oExpr-9OYgDChj;II92*MwyY}#@Q^!w1!E>VCn8zM_EWeS0-+%rv z#uL|1pH}FNjW@kX`cVo@#zlZfKp#Rn`Tu~BgR9r#%NH8SM^H*fq1t!&=4t4f&_0S+ zWl)NI*!c~OLrqbmtQYa6R)aZ9lN=IK8=W=uaQrd;LA9?cm0Jc{Abjwr%j6295BxZ& zdcw53JqpRBri&)61TF>5TuJ;J(7x6t>BXbxmDs%*~{1AjewOrQfLfwT3*uVi~om(g`husD~ zieij4QW-&zd|eS36j>0Ml8T}05aI-f4r?6QiUeVme=MUmWQl|59^e}3)bxa@M%HnQ zwPl#8q(^#MDsy~42fURwTDUf^Sw&ct30{KHY_y16U50xs&ZXa&C`(QyHYe^aoXE3qP`;1Dy6bkl-z7$E8nPNcF6 zt>pnW^+$jct;|?CSX8I}%vTZ87NbvVPg$$H2tEggFVyKol6C>V|ZmP6mMjC%Kwe z5svzo(Vxk~Iq{0yB_I9QQeg6Ik~PXBtu$gt&DuL(Rvw+*hv>4yE5RhqccZ@#_S{E3 zSZ=MXV<>o$oyt7H4e+7fGL6X&Y5^~Xv3fn(xA$#{tNbGc3bz~mLk+Kn6ws@HLl~N+ zp)A@Ihtx6c-|mwxuXH5kfIZyU!%JZq1x+t9oN&${ajGXtHk#DZ;`PRqgD!KOo77-3)b12bb@3dJk$g2;Z7%`{g=YHzHyTFtS_R!DT4pOOJQRk z+kU0AqhH#~eE7^FtXIM?cU=l5Wu7I5dhI=(j_}P2_kq20@AQk?H}j9aucRJeyjbWR z?*scQ#rjXh?{@Ea-Om5^e7YTmWB+5*BDvX1VSj7;cK)}g;L_iHr4)YPM_oV>zhLSf z1qDAZLx4DaMK_%Vt0pT2H9c%F94Ho}=TpxQV3G<|-_o9OsCoPAp@;8U&^sjwhA8oe z;B7L|zfH*-mnsS0#X71BizNi109Fx#DsyzHWNe|o-;hgOeCI43G`ssBb5>i{{Khg{ zYb*o(cEe{xE%yV4)UpE6CFM5c7Q9k&SS-=3cp{LlpbftOX}y*z`SV$%|aaW5j&z+b@&2AyA!k`VAT8RKfD*<#eoW~t+XJjbkiqo|Tc^n=sf2kqzcamGdKke_(D zR?3oBKN6+c$TRB0yjC%Z)HN85SqZYWsVYwyleDwWx!N-8SK0*e$Ev#7)HdW5Zw+BR z+H7}JXBNZ4XLYt1q@y00@x0;HtA{0g8ufN7tNHv~xsRkd)_I^B!XRfKY=Tj{d^2lp z?0j>tc@98|$8E%_1Kdq;Cv2gVDY0=zgUO8D8T)ZIX~?^^eoP26hJ*@)CZkLPq)wX8 z{Llmwxlj$zdZS|O7OVr!`*oj7uCXpid14B!PV{&IYnWRlEEuuYnT@%NoSl=d8rsG* zb>B?wXfS7y(xq9kux4&1J8?duy~|OXa_Kpw0G4HTlk%RD;oYao zQct-cd`{=V{!L0cX@iMXtnh|+n4q(nkd0=rlg(Mt8EB0UpE&|WmW)~CE3=wP(=?Mb zO-fVSNm(H!5IrQVWIO&evY4cC^PNH_raD;RO|oW(m22JepEbiN>qN;gD@|6j`E)lU zSeaNP%aU;`OPa$3aigl1mI3WfQj;~y5V&6SCS{W}Y*)yc2O7HBzQDJiC#C55aZ7n+ z(plV-tEx(IQKA#etBlYvgeyEB;Qc7$uws@E#>5%;pP`DXS&@Ufo#I2kb1Qpk_M3L=4pmKwCDn&S)qnSQ&IT z>$zpJi#egvQ=0wKWrU|VV8JqjwxpjSVZ!m@uEVylGfT;q`D_fM21!xoqv>KN*=c&a zOCC>TBMJQ^JyFw;)-EQl$ZuylC_1LAkQ+=x@>Y7!?#!3%?U&F%(qx4$svIq{DhaFo z%u3-@iA2Ed3@sLXS)}KBb~D}KW0sg~TCtm)-jJp8Y)Q4G*`!s~G~WA)e=i&xyGo$n%W8Z~jk8Tpw$XJ%6|#Fr`oYGvFdz1%(yxJ!~bB|5CZ1?E0uE;uK0Q8HZ>R7azd!=8z7}psw27l>t$0vk5 zCK=?|Hnyl^Hx3NPyLH9w5Euo=_}@7k(Y3;|TD{|f=Kk^8h_8CZg~l_R&u?n2BEC1( zutKqdOGLPP3plZPBCHAg=g*jzw1P3|{gW40FTMTkt1qpdBR<#y#x*@)U3Ke>oz5=A zb9@uq{E31CIK7##QSf^whhcHxfPx=+WVL$XY4E;Oe|~T8XTR&C*WUNE8UE9Eo%rjK zf`Cc+5=ifUJ_$}?$e|ns(8`4FbnXJNV96EB*S|kf={G z{)~BMbqx?7Hs8K^E%<>(D_aJp z)vK3DbMxco<9Mt-dF^sYdGqb7aE*`fbgA8rg8rq9j@As*-%OewuV|$O9LnycN@sT@ zkF)A$erUV?E9P~q<^3pYc~F4K^nRYN8hdX)yug0!#6zt1<@qJP&#e0G9@~2Vho5-Y z{<~bf&t(rVzuWO)343%q{n>x_y{FQ5+FUihk6bwOlf5mI{@SPHm$9Pt^wU?b)|bEV1!LataQcxKDHZL}77w0nR{?Ps z0y2G|AEkh@H7BneKi+s_?%LcsL_u8D`gHy2+H9OXcV@Fk75?A~z&1c2b{J%7QCbR4Z8j1MWJfb|@Rzl^0&+Gv?uk zpLinq$k!gw%A7*2-X`DG-hcDY{;%+I-do@N*soq)<+(MdPpflQrdQ3%E3BYfXY6#n zy``1Vj)IdXud(_UnuNIvTGlCm04Ugdcxy`(?0qHHH5~29ldI-?{>w*SR0?lBr7lEW z?CI0i;?TQ(eVqc;Xegt)wUGGO;mbuoeM%jBq6mlGp;OyDLzElA^O5lxLF&VPBV+mK zSez**Abc)^2?fj=B_*zNFlj~*cx7=RCRZ7>>83Q z(i7?AxEVGD(yuElgeRmSk)dPI7s1Iau(IHCT9wQfh}SZ?~4g(#a{^>Wfr;; z2eFz8VbM9S5f^&ID$N)~-mq8ELSp#qm$(UIOyVd3!Bv$FR07r2)`-mqqh|o8hqhKR#mggfYA&mW8^1f zVO=Ywy}Ct8+-A1Ovl-HBx~NjTER0jVhAPSeNsVR;y8<*(iz>pH;emLb0V9{NuB21S zhGj-IK;~(t3MB%Eqfs*9nQO2nO**dVqmn6d@}Rd&*x;OuGah_e=2Om?k|*YTv_rHa zW#vLoFS8MvYB3WoIC8)aJ|N!Eb8^^LUX!92)EE~YM)7c$M5r){IH>wlzAT>NS`6%B z?0flQG&fT_FKbu3((lrvFuIm zPc!IoFuYebhJM3joQV#bd!~zeXJ@o*#`$2%D*&@G{WtZCnlv-&z60&ygEQ+}a+<7B zz;^Xnl{hwAE2+Yj9GEVd)R|;UDjstL0wO>i?V(B8@Y;;w#-efgU^Gn9n!VZ(>t^{l z<4Lz{QI2M_)Hr<@;TUV!JEDNw&%nYDH>(=yu?6tGq2GZ=%xLA-)+FVZRk34-j3&a$y52^Ti$5Y4H0jz#x z9RBb9EsPz&pL=DF`q-2~w&o)iWae^9e%n%zOxUxF9iL;`2^nQ(>~T--R;!!xqB+K1 z-|dSR3yDfE(bCzwi6bufBSoLGbDYImjS=F!<1iqHS|i zFWW{qc5HS2k6-@3ubqGB{6ib7^8v{R0ma$a+d$sAdKE3m#OHx-udXl(M1f$Pf@231 zgp^6?LI@Pz-o74;XU+_NVmRci>FSMdT)k1Loqyl?ZJylTr$Dsci~^$jB%=F|Mh$WY zd64uBlMvfCzwi6b_)f3Y6vn1;X0N&M}4bHxipjYX3~)l3%*lnM>Jye09u6$}PLAJ-U~&ZG%i+U)uV7 zEqj#SweOofyB|KK5S+06gsFEg{f%Gv@Z5X^dv>Sq_Zrju+XTtcr1Xw{NIdiTq$&ihc=dPUF8lF9Q_OAGfo$5T#pPkrSZ9R`{`|O)9pFQ`; z1-Ux+fp@O{#kpt2n2#|RvvGXm9L2cDLuusv@?}ZD&)8?4>3HAkeed^nGV?wakJAcI zoY<$}IL}<2eB+fjZb38@D9>X1Gk&5hS={2*aIe)3Hx-_%jCGS;qB(8Z$iU`Oltwondb5+O;buPi&G9 z@YL${CS;ri zcxGkA4d$qTtNh&rHcp&)&nF-M!U&DlV=`zT_&!6`YZnZ zoF>03c-h)g-sX|7^K6}FB8s#3|LWxvRE~U~0#QvoRAWv)ee&rL@0ApNO(=mD=z?zq zb?`@F92|;6&Q!r$gTt#Z_Go~E1S=}Az9k~)_CSq)RdBcwys9W|paZ5HinTao)5k|y zIO=*N(6?cAYjF=qx_S0vq1>#v){sP_?kPEdSaJ-za1xRhMR3+WzZ8*A_4OZi#)~Y3To!%k@RD?P(yF;wO zA_*Aa9JT$poypmmcr+caBMu`uXX;8_8ks)=^r)Pao(!=2T8hfkN*-#Y3wBY2SiaAyJ(XL^T-K%#Hvmj4(}U+6jvg zDDjD5-p9un`)W6Cj9Zh((VfX~WuSv->Rf`&b$*9*?Ha9N`~V6F&Oke_#;z7i8sn_7 z!x3A1G(8!HqMqRzBvr~+JvQ81P@CF2TvMkjS~6J1$xfijm<5Np8pPvlh>Plu^dq1$ zcg9+I3jsUnh+_9ckpQc5iEajIA#r_@ijV{?^<=^8Z;c1?iQznxuAa0>JzR4`dID4u z;wBD@DdrCy(5jBO!4V5zVkeYW`P#O0Y6Wr%S7)ZG7?82?O>Tx2Ek7VQzOD%_HmFjx zve>DuW2`h(GT#tq-?0b_YB{MPE5TAycI=BIO)6btF-SUqCk#~ki7g7ozlD-C`7C2Y zSehste^e?%Mhet$QKBLOas{k#15s5n)Pia}&1$)h9l<1sshwtH4PDv7%r0WX`cY$a z!$`^E+cc|i;btD<*GAiw2W+3FP(989Kg`o!ZPEhfd&O?Z2ihSBBjuUJ%_cVJ3Z64+ z#);)z&@6nCEu1S%ZjdH$FjHlzgV3&jSwnw!vy=ev^Y|7h-YsEcDDWj~E zq{BYqp}M;<>JjKo=2fzr%xj)cN$7ib*lbKk!s4%?LMO>|P-ztmm#oh$LP~*@J)2Gw zE5=$?`ot!QuqKTxT!XU1`W@wlqY81(q3&j;dD@$UqbUzqi{oz6{vsJ?DT`kHSzUs* zN+6@ZJ4*(`KF1=+kmGI`2cD7Ie_{cq+AQuET+4TSqHA?=~>sL z*={~}>3CeQkD86S^NdSuY0>0KO=~!tG&Os1OYi*H)7+`$cHzfnJb-7cTj_S1*=#aS z-FVE-SeJS`Nt+rrj(g*3zi;ozNNn0~hAf^9`@?!v)JXozelKUsDSS4T_QqYseOEWb zbih{#t|Wupjwj2(#8Pi;V_B@tx#bo!Wo<1~7?$Z~EE+3~ev+^if{HdLDzzk);~^+b z)?{3dJDe|Tb__J>v_Ee&bLCWk2^w2Ls-{1jvKd>lx}knV>=tyQ6Jq(Bjf=&|Lc(M~ zgk ztPKX}^l0nU>vyld!TzE?!_Q>2x+6HS7_|43Hlme8`?(0%Lq$j=Q@R{K=$>i=Q zgZt^zTPIJ7f|FMcQSgjr>bHJpYs;B0@0~gGOc3Kwa|Wf^YW%H$1&Ic>GglQewWCF3$J^fF@N}M`G;@F z-jHd%W3_tz%UxcY=Bhb<916H!Tg^nMxt1ef@hyCpS^JRg}Xn>US81W8$Kugh!C=e)j0OtZn7_D*e|mulGna#+kA$#wa4!_#~48;9;O7KF&%-2A7&rs z>eM4zV@ryE`N)-PC%2M6|AkQV6!hfDM^0|Mb#>t-_Fra(sukc(Z#oyUes%J>-<1Q~ zOh3Rn&dcv-rRRnIFaNSx#dT)+JvV&rxvN*>zHix&!Xu|d!SQoiV-p3}_O|xS8~!lf zIYi(eKl#XyzxB+8GcN`Ty4c*{6DYXnr=Je%Mo&NUv}jHpif-EBUYV|Nun&i?M1e|N zZRz^vbtpNzT3t6MbQ=w*0(|Wod)FUdz098I&V|)O+nGE4=^|3%+qE>R$8(+EiWSG= zN^zyLAJw%pcVpw^mCGv@5xE~HtQusQEf1@Yo#(z@6i*kya<75k+KaDt z8$r8>Ux|V)oKYWNV>?n;*BZ~dk2Usa$iDGJ-w#jduGTr+@nOK=gK1x}t;w}Ik<*Bx zt@MV~HbxkD<9>ipX3rnt4}-&+z$G}PrJj8fAw~$S_Nm?)JYHcm+y;?Zf1bZOj7%aK zcsDIY(hzuVAcVC0&5db!+oHaOCh>gz+bOgDEL7xX9AYs%X(1_O&|a6sw@wF|XS|Rn z*uy5WSQPM}zk3kms7d*ZU|CC{10|MK?v=dd^S8*^=A{t0pbsNfxZTUs1m{ve@k-EV zL^7)xR~zH7&PI%$f&@Er)(?FbS3wnHEWMv+g@dO|-sCf9Y@IVcBxyS;2W(9QLsJlp z(q$0I=Pu!VTSyccx1kX91ul&p2V^GU1Rg=PUZMJsn>wqJ8%QAW8GlA#`3VIu-*FaM zr!pAkXI;tPF+Z7ONk+iw1NgvpG2(u1TY#PRfe1UP_wA% zuvKuRwuoX@GbEK`_?=TOriOsVfpEd*W}Ejj+qX!3S(#A?@SsAZXXIUkvet(pUZSnW_1rTa%C?H9#z{o3Yc74}ZXO-|28SPpTbH4##FT zHH=C<#L3rWGP~J0DRxHeZ4uYZpkQ>n%TRSbTR1rcAQ@5{!-bvR+yoAP3IrNzP=(I^XA2WN#Cf?o-FD1qtTu#1W^#69Au8kiva&rRFo}s% z9cUGBEYFNntZs)|h!4U;IVcpEm##NqK>{^|itFbYW!R@IuQI9K) zv@C+&DoGzMk{v78q4mi$tBkKawnMNpF>_ZM@0-cMss&J=3_BwyjI@hc-_Pc(SWZVZ zXUTgDWu{R+CbTq!qtV#0i`uin(i^W9te$Yv>$!Qaw}bQ)#5co1KXNzp=&DRd0SQnw zn@dZPhsDDQd|~2jHnvmp*&odEDV#%?v28hHLTG^l94sXyxW_fLlgI!IJjHE^Rxa_~ zHOXQ!=h&z8sDaeR^{WvZmnuC~9K)VyI)@|; zsUZnMN0}zQrp#19=5B)UL!KrH?4*;EfsMTgZ=~HvteZ4KvJRSp@ha5e(&meu<&bM+ zJR4+Ty4jgccIVWW-Eux9&Jr3(xIuBM!Nz(@%FXLZzxKl1LyUo?15469u&72;n#0B+ z(AFkIn3U*;z&UUtH(O-2W|ANRZdUL5e)nu@Ab;`!FkOYRqmjZ#%osNcd>>`!tYp6hrE`FzT8WrYD&0PK8a8OMu zuyB?_p9t9NiOG~T{fBpzY76ZwH;!Cu%6Obnr}D-)>pekJM-A{Zq8M6iM%WNP*w>VM zODrXP`Yl5~m_pyie(@gZ_vq+@u6i=Z+WoE}-n~Hu@iy)k*(rMuAxk#T3e!c1;k2oC z%wm6SRe(|P@khTAbZ+m9UtC>Xt=`9Fs%Lr{=--Jj@Zf_R8-MWY=gsQRebM~XJ-Q=y z9ahA8VfDfb&u#Sg<$_Ko_y_^>T=FV=Hi@Q~k{+ZV#u71VTrCPzJo^-|dsZ^eJ$IZp zPd=HZEAsiX4Fa0u~#P>ZKFg}Qk=tUA@ll!gBXU&f@J zrq@sG?fv#|pFjV>4{mSQkD1jSzuy1E4~l(z5!L6uXzvIn`wXtfs35$8^YwiRGyb?w=eSrpvy>rXsk9{+1$=X8wp z=ic?d{gRrUx#JJG#W>!Vd&hS4i{g4-Q>9}A2+r#ibm0#4enlHW<~En!pC#Tf5NO`e zzDe_jzwGbTU9`bnGCLiF;1W&X@u2@C`n0~Z^|cS9n@d|imMs4IHs86=C#UbHC)mn% zt9QNg7ytSF+3wH1`<=g7++Xcx?|x^%v8L!Q+5D&9^4LqCynmSg^Shp3Z9MkaQ%_x8 zz4To#_BURC=Ij+tT%Py`?|Dj5PHJOnfT8)JEg9bOmdmRvtCMEqEgO%?{xb78-Tu_y z{%xLmf$5K)KmVwH@;7U@y9PVTnKP#Y1z-8f``@1=-}pvH!HSoMHeTO5du?lPFMBR~ zt_vUa51jqR^D@2VE#~aC)t1@FH-1`nNv%gIi0MCiKAhLRs!)gF;fGh3mB%x8egA2q zZ*Yt4)xFj8&wu&xFF(FHHum-& zd~oyXM;>^9{|6q}V3x`3Z3W)#N5=5*!)J{scyjpUaFd;~9R;gXPlI=3v-g~_S@zr! z9;{RF)ytJFhXXrbYN44pTXjAjqc-QtS&J8b>VKRi^zS*_swJ6_<`0(UnLN! zJw#IUBxp*&njc|$d|wy*jMd))MQzs!8M;QweAY2{fZH1AXbdpyoc5DTaEa8)bR%et zr@ygDYSJz2*fM0`FRy$E?IBOlW6X@o-_616Ypt|e@CU?nPUx;NRoK`!Vd-ku`sii3 zx4z&jTanvE;ra_OrG7DnJ!9p|88?o-UY{5xOcGo5&!8>C)=Q`<$g;tuVT@@wjFgz7 zpDRep&k-qBrj$jE6xjtAR#%(`R}7YIgV?Ho3aX*0G2X>mC^zsBhux6i9Ls@VK4`{R z5=c=6N>9=N@?xSDkzrDK<;9>1D#m+|;e<;PS4e{ENe1MqpH<9MSVAyDGl)DsT_%{6 zg1`~GkwKz21EFDVY$z(V6{dF@s{vP>ALGWA<;?D2v!-$(FD?v*RMvqHbtuW)7J+8l zSYk6lKn`t9Ev|Cbm{S&@(}joAIzF6N4cP3AQMM!Zu4YK8WoMh(ggggQ#)MG8IP%}m z@C0?(M4To>XQQWPa>WvW#3ml=G7YXb|X!qXns z1n?S@sy0-vVMuQJLv(=EJ(VwFiD&l%&mN_HODW^yEIBMQ1!CxJpoDZ(nuxSC>n-2{e+tS{XjcxN z3efYop;+Oac#~6tvX7ZOFsuqFi#*ga=#LAoOd4cM8)D#kfJYWlLs~6Z%?C6YcSlhc z1Ij=5gKRL!cZ5mLW-<*Nk^ytl_lkY&_R4 z0iqm*88uFua$vH&NZ&ezOtJLMoD_hBnTqia%i?PGGqTz@5(P&?t{gS9;gt15E}lXl zO&1Mcf+@sV{O1`0WI5nP6f0l1+k`|aFtSb^1W1g8btQzkB!?aSWDdh8772|wTrF1a z&UQKFn)33|EUdf|MMc3RmxuM<n=M4-w8?62M~xn z`VbZYiJsYyR54V{bLJeFW!W7dFJkgL9w9Fq+6^WnDfQ%#OyHrnDxD_VW6#h z*3yFyaF4LVHW$w3&c;|Nf6MvSVYwV~`>;!9!#4&6qr%IXXpN>6udx zGLs}Np+eSJ3VGa=r9)@Nk2}+vq5`vHE|0d$j1~nv$(i(_78V@^pjJoMvr976ke6wJ zoX!o$E$&ACWWUb@!i+j#d%L!xQNy45n<52DNV4ZEQ&1LEz+#^Q;zXHgwTkE4q{pA`4(fhN zPuSy|uhFa(zOSDC_{T3iVjtck>?%mXIyw3vpd3dKU6Pez?zacV+;N9&m-k+iy@nO? zPo5SJUg&ErRB7Lu0{Mx84&tpMt3eaTWxKfHN0rwtC@;J#EgcUVhD2Qgd>3Wc?ai&2Ix6dk;Ji zqB9Tl5=VKj1G4MPb8wfLbLBid6s+e~Z+PSz{u}<})31NM97Msp-zk1Ajzt=18DBlY zeOVhD#S6x6-nDtx>P%zu&BsEG4@iQN(H$P9Aac0Zi>1_2;0e7>LB!zIb4O!PRSz^- zs_xd$(bUMtO8jR&?<-mBK55!?`#svo-oo&?gIq>1HwL8UTA*1s~PZ*4Zx{KKz z!YfjMC{0AOiDborJ0!1xWCeBKZ7kn;CD0%V<&|MS_RnJOeEdJAq zHPB(M3r0P|J94grdjd()5GV;6z2ZmQL^fk5#N@9WQ-Vaq6#lvoY@tA`brPMCAR{P# zS(Y`y8M)tMaD4Aa^TK$?_ce1SGt2nV9(psdE`;D4o+0L7VQ3M`nX$GLVY6(f^n{co zWx0VV(A*G-82nOx>H_+t8zVwA0+yF6(Q)e+lY(W^)OuveI>lRqAw}yM?UA?HLe{R< z_MpNg4wnE6Y=~}BV@m31qD}rHrjmjO;;Oa&0dpp6e8C$?yeswG-K(+OCRu4h7iMXgk(b{*83gG zo5`xI^qDU(4|#>Q#xNb_c@1f$qVf)-VbQxbE)bi+%rPmOjCBn-R~TdJN#!hhiE|@+ zNMo4U!YWn-!pqQ`W!aLUHW&LK724S@7}$wzYfEYzU|}agzcCuur*1 zim=>vwBFf=jkGjVcwZx`!o7q`$>)VF2U9lFu&;vLG19FP#{8-n<5aQ_IiRKB66xlNMbk@m!)7^GDj>ExuM1?`$7A#7+X(>be{1xuDH_9Ut1 zy<)aNN*Wh4?mKeMjIFics=-@F95pN4Y-A)_B=ebsxm}_zsyri z5W{vT6|S@{JYfiebSK@XvUB^Iz{jGA=8(LxO!N#UZkc-T2dr?9IPc+S)0siQ>h*g) zM=XbU4teRcY$n777l+zO!H(?EBUB^nlLRhSB%lf=Y6U4INH+w6Ap&8D5O&V!UTd0e zR!ow#U+?UWC#Ki18HjlkLutaKv01>h>H36!_fdnlesOQ=@4y z8sb1OA?DN!N7qbG$X}Y}Bx{|;y(1u0FA5u~#$2W~?-xk7yzZM;HNrMBE)|I0Cvi=I z;7dQ*ubK6-)cYh=HXVq@0T~BHAjM2*JdMf9WnJUxnj}F51J|n&Q1>lc{uC{O_Yj70 zX=stT8`4L62Z79l4d!F(*%#gn9Zj)cS81ObP#6h~>wkh~%n`7Hp%WcWd_h5pQ zV`wW4d3Ne|bm!VyHQ$iuM>){vE8&nBIq;d1LmC6@zmPbb%L#d*=K{ z9ytHdL#w^FzV-k8e-u_@U+#TsO`BIYugdkph4aU>QY(48`$+qye|Pn^Cx3jk`LV_Ov_kmB)pM(6(JW4$divSz@BaFye!|Rug7w0WoIigRNlg-v zW)hTdQU1^-B^7us&WO*Fy``_)H9PU>qwqH9M{|7sp1*6%|KvW4d`E1RB`=qL{i|OW z1^3-Jkwuzy#SS`;#N_BGBd z(FRWZ9z81S*yg>uKRUmZUH`B*W=(oOmVCZf4JEx_*9!PA-gEztC0UUF*{s#h2mD;n zeQV!t^8h@wvPXG3u(cPRer=QQC59`$--rG>?HzVms3TU+# zTM8g9ga}HpDpuw+kN(2%x7)Wv!HSYP`G#k|a1dt2Ox1%ADs|1)h^3i%X~kxk;~fQZ z7X^8q?^Dp-6-CJ#?x&{MHh*0>SHG}2cb0Prr_JBL%)Q8g7S!io{`70!aMxYxG6eYs z%hD~ZR==Y97i=LVOc#LvkG=PgmE^b&{HnXFmoxOEUXQSfXqXnOjYYg5c+pEJA0+$H zTfI8L5)6ZDSnE3oB6fje_Hv0&qA#}KKS*wEPtRiJfWR}zSulZ1R3k+J^P-5f-~bXq zEqk=MNQntk@tq+D`h&d4fDG#ZJ!iEPwcOpw=Ud%9Z{ClkXx|0r0Q|l;UB9co^{wja z`quYbRkYDf?uy;>N4sKE6j%;`^q2;NwzTb~7Ysy(uWsJD)keSmgBSFDoJfAEaqG=J zP52u(p1IMj^EGQ`f&ohf;T)|7gWyl!MZ<;+9N&?;9SZW`b{sQ~CHOgyjiJKv6=Hg5 za2URFOqSazHbXnk7MSbSon1^0jAXD2UmO!kY63m0)Qv4X`8H%>^3eJj%1S+s5Q!Wp zD${&?`72_X9TQ@Bt{|X_Yws%~L8M#SKzR9 zrQzREt;4v9=TucySP=?JUtX@Ju*laa{UAVhN(N7$yl)blK6EBBTV6agiE1 z+3`ze#V9qzuLJV9W3Q|T@G(L^96Wr+AjP-rTl z705-(QYowwlb<%q7=xd5RfCapb)s$w5N0RD3Qp3r5c({3C>@ZpEs-q|1G{Cqm?R`p zo zq;vdAQ)d<7V<#C(LIJ~%${J~dGPrA=p|fSY_wpBj_(i%?H#wV-1|3>V%Usn)UK`HTg-3^5gFAz#2eFE*$iGlhr`S?Mrptz>NVh>EVp*|o z*iu?}`aztkiaEQJ$kf_JaX?dDSx-9orIynMw@GqK2xx9hNwfFv}3l?gO2P z4#c=!$rLh8hmo_!lVHk%nGrn?YJihFU5p}Ip#c+U4j2awZ48IF@*1X*kQA@T$y!30 zN?rocLNZu^X>H^zxkBR}JGCb%Or!19xlw*>(kz?hg&VqQT&mm+dO3?B6nPkA%?N~& zxi@3@OpXVS(}JmsNYt$BrE$Ms4130>*`SvedRQM3$Pav6 zPv(P2SjxIAEOcN%k5n4fb6=AwYb=EcBab7!7vroE(q)5-@Xt%?Fo2TMDQ zSV`&?i5anKL@PHb_MSuKWec}84&DrX`hm;(MV4qymrZleWHUz}8{RL;O~&4V6c#dJ z#f2o6TrgDugQrm_%15JIIS0q;60+cLIKadBMUgwl2P5^wUW3@;$c=E0LpV$2vIV** zCQV0$toX%9Y)8C!Su$b6d(N5eJ~2!%lEm=Zw_LlDmms1==Ftf0`Z%&>jUK+db(X=k zoQ|t{V$n9OYa4r%4fcWba5#UfDi5{#x?JSwy3?V0a~7{MUk}R#C80$WjZ4d}ar#n8 zl4z2nX%V_ZjZ5Cln($~GjVVe`7L4jhh5;fIIv!Q$ z^aNuyp3;kYHp%F`(({!8)0n{^mTl`2TUC*DuKOPG{wmr+a?IUuP}EazjWQ*NWA{1T z8O8O1o70jR7qqcH-NDMnvXVvZTTGn671+7d%zy=8#nLXxben~ zUpS#Ip*{T5r*55H-r_9W5a&^z=*~Bey;QBuBSH0NloAbG__n|^Nzm@DoIm~imhAhM zJ>Ne=Q%dfvy;%w02kh~_x!h29f8*|+MA|sD@zZ~LcKN4pPpfG067~Hf;S4Xm$VyXw zfmTRr#T^O$^8Y4ji|&xo+%+C#1{EtfB` zQ(xVF;`P^);?$Gn_tcKG=&gI6cyQxoju7VlsQd0~ZlyYm#zxpCy^VTz(yS*uyj*&} z^UQmnJr$^S_FHGa^#ZpkU0J@^xZx2yuD#1mFvyHjU$fu*CfS^7Fu3sa>%Au)+}!+? zU-=!*vTkJVU5a&6|3Efs!>?~fZD*xl0RPDs8w~WC)=aM;~2wTsv>DDB}mv=J?4QXQ=Cq-ZO&1Sk!z)9JtZuY2n8f2{urBgseq?~ne{w{E`i z&FUAbKl$c|d-k}^qJQwUcRt1!Rllca96j;NcYW>BrNPv-*{>NNef=-)y-VDgI=|-q z*S0dt46j0y&|>6`RWs;@cSlIf0859KKLLWUG?Q%^*klUKp(*(AIpEDt$Rl3GWi`5; z-nbC=;DZmACdb3z@Twz%A}qY_nDW;^n z*d&r`{HE6TLu?oZ0V*U+Q&Ez?7dx)%=O_ zrCg>%u11nIbq^d_=7Vd>Q$jp(Z9q}zAoH@O<4EX!kiy}PLJcHD;*CfVNUIVlOvMIm zT(Ok$z$=()YQ*ME4NsH7!*!MInYtf~1Kv*)-6G;Zk$NDB_XBJb;OJ(=QBD=)LEa`% z0QFfoqn@otu;5I1j7&WwRvZ;3u~^aUw-E)2!ljC3(p{0Eg{_L`aawDT;NJ@eZ^IvH z4nX9@Lt7Fuy|biN9Hi95#sxN!tC@NcDn$q20$Ee1B|g))L0`2-@ZgGlO z%c?3-iL6RcGrrb%JO0+dV^1xyrH?1F`FEC!4zV}5*~w0K4QSL{G(;3~Qn_E7ZOX_c zHFYgDOy!lYXwflB4Ju}ysg-1=t+Nn$NTx``ESOLuL!UA!bt|URIL_pl>6qJ_d$8e% zPHUPbt}>!>FLP!qMK$|9u;9gHe=LPIAhiPGA}Yj$zaz$6>LXB=JUoAM=nYtvO2GrL z19;^kG3lBJG!4scsFg!A$uq4|8bxjoqfCmUWB1S@5qTlR%&R>Na0|?`8GGiF@hsu} zFZ+u`Q;;68eu4gYp2K!)2KIiyG9;*x!<&SzFov)>SPO>I(-}%o-6+xu32gz&4*y)* zW7t;<>5j;foBkE@Sv~p#T}^c~n59ukZ;(YM{#AsAGE}4rxW>4pUM+CBwb(LW36F%W z4ddHHy2xhpn!I$cmg{yH52y~^3L(1C^)O`A&zlkV_h$8A7AXU^vDTyBIF2A9OJ$LX zVyR_9SkYuqvMdk{Q8F6D6Hl?URak7{J(&oWA)9I})b2@k9Eawg+) z=_6#%P`t_KLMB7Ivltmw@b)^QHHMMFo1wu&M@z%g)?5%s?_wyf5z@2P5y_Wqgl2wR z%U5fV>AF`}kf*G*_TVSYVtHu~z$ow25u@HPW6X@WQ=Ha9GfF-t(#}p86S_;wk1a{D4cB><5v;UkVPT&SM^H?UG7B zQZN8EQvJq#EaVvYd5N(GqK&@0wRK)yWsPa8KL6BH_ul)H_qHPkm$}F!{OVP^mcl${ zj5wFe2TztgXQ(j^d9=`r$2oay#~=M5E*h)vHOtoN@SEy+FCUJNN>;Ge{OkZc}95Q8#i{A z$7OE>aC~|Hl6$@%_##|7YbZPE^@ndQUs(E$<)e}`YQ@tMbp9Cc74AKHZ&wA0+``Q( zH%n!&UcI*Uz3+8e=H<@!kftl8fiB)*a|f?`9zA!i4GA<*C)LU4{f?KN8n>_9-ah{5 z@kixG>XfyW!#OlQ^_7}|OfWck^2cG|_GKa%Jo)4*=LQ3%dV&E#sk{rvp_SZ7oj%;` zOIXjqDvMKo0V2k3u}s4gdQtfWPy8D&C|OnOG ztd-v8D6vDzgAaGmqjj6cT;XY$zK@tL2n|-CouaZe)RM^)ado(@a}~}9l=&7El0Sjw z8LX?v;qP@DWP&Nh1uUXCFHLN;QcXZ5s5tDRIf^f(XP#O%p}6EgWTUwJ)?mmVa>N6K zClTP*o+t_8;!Gp?l2-kYum|S>mQ!}^nra~#%>`*o&AqE!;c=*n53&(Cof~n5PS0iV za%SLjL#%q@-83OX!17yB)#DIhY>%Jx0iOnTB!o-RwaP};k$2!liDIHru9YLMQ;CHF zR53F;&dS)My^6X9&iA|buDrsND7bznP74Hnj0XAl_bG25Y4#MC0v z`3Q4rtg-ZJ2tq)m7KIb3ov@Sv(yW*!8CQ)~2CdPunq~= YW~YfOm3q%b#d(sj^m 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 Hj?&))YsO)Y literal 465304 zcmeFaf6OGwdEZyvUA>xFZ}|3HjsO$GQMGXn&WZxAa8x1_uejAK(xwv`Tp4~v_+Wwi z2eSkL8Ds#`{)eZl?de&~7z8x011LVjhI?ewpjUx-5cG${PivA$0vo;V->O2DeV>l2hL$9v3b_zA-927j0uWJH__l(;zKMa2|UW z|2^LuXy8A*+QJ)1_hzH~n>MI`L+7t>sZX-|=(Q(yF4 zmcc&7pEz{Z>m#e>cVYO5XUX}}?uV=I!t~EZbY{v+1$mV8kHTNd#GKRf?x$MI}M!k5K#$*8zF;O5Z(+PA_<}U#S}eu zdk=e|y#Q5^2od#Hn>wLc#PBH|^<9eZ$u3LLbJ)8-st({h)V#H1M6O5xc8jNUZ9BRY zUuf9#m!%M=ix7)>5glS@45txc+Y)y0L9vg*UmA1DZO`NPLi>ToZeF>4hIzMn>}DT& z?B?CO-yLtvqf(rujlL`A!hZ&XPrmgpA6+KazboFDN2R!o`+y6*=R#u%){F|{F5(|S zuVxY9LW&-J{{G2Rg#AnPsHpyhJ4I|gqwWPuKVN#{(Fdz{@OqN z^}oA^=>yk)^)LL|W%x(Y8}q0bx1GLTlF1g;J|gPh70)pG2u{Cn^$`)E!}0iU8*}R- z!SZtaBk3Q_iSeFM{9+E5W6s*Fiv+r#;f$F??4Qo9@7TKczJE`-Ca_O1m$K7>x?q9} z`H*qwGxj)bZ#&`j+xk}8U2waBH{sW4Ga~1dCvsx~p^7W8?iFl{FOEhI4-n!#-pF(a z6~><8OMC-37gRBP71jx zm*e^_KuOg=LzF!9#IAQP-o^he~;d%uwDF4TqL+~8}(B}lUucdm4>mBD>+N( zh%g|TqQunIIUb6&NgJ_Z^2dY1bV04a+cw0uVC^ZRe$v=VPXpxJjJ5@)LR_EoP)Q=} zBOf(699Z>kWt3k=C5sP3=end0?b51!MpnH%@!oEm7Y((tCNaU2my3THJhDdOWxa^I zb!Gyr9u3J(6noTgQPE$)BlDG4c9<%C zCd3q}Ny^c>Pf$=ZKyX1$^cNOiRJ8OKj3t1|T<$B%U-hLRzSvfS$S;Q`(Ah#mX?*I8 zJ0lFnX-v?xon}a_z%+0hAPgS4g^}oqnFNF}E&di)ehL;r@t4CGwC9hiLxM@+M+CZ2 zkwtRwMHr6}O+nE@SDDcWNn?mnf>hhM(Bp#0df1V8KwaW?q)SYiL=)L8ri?9Zax9s9 z1$HW2LY6r3MhJTOBd87Zam${fj_9t}MfAVnZDiJFJ&NUlX<`;h-L%!QPdt3xZc>YA zGZ2YYo+C6*A0}KN&C-b6Eay=e#V1+3r$W3jEQ~j0m?DBo#Twi=Axn4Av6W;`NK zwN=$vG08>?vltzlpbGFY2erx&#K*(YIPNJ$=xZ}lY;XNIv4iOf?~l!b%<8cjXX7-C z#)T$^enPg{IJPbBTbO7N^*v+B1b8H$^cWwhh3uhNT&xI5y zNS0Ffh{j#-NKV{5@sS{67pgsKp)+05Eo;^PT(Pyn>Pmt(-Y>oNxv9P)yF95Div&Iz z?*whUt68d{jd~=wNo>GMvzn7(*CnmQNKDhFNlSo~$J?}T>||(>+RV&|YA?((^L0_A zfkYmCpFw~s6`dt_5_B}-)QBz%y3+(={R^eWDLCG`G4KYrD^i$7y4w(4xvl@Zb$QoJ zZkwA1+nKP6tndzygn!`fT@OV)Cq<+L72Ug$QzRjWHwOE7AAfRk{d&I1H;0FZ8(}u_ zem?D!P+z~ck3Bm2;up>1Cnx*ZHy=8D!I;BCLw-n*|LBkAc^>mV+O(H2si~XpTqoN| z0`te0pnGT!&7rw}aBvla;{Gqb_Sy^gmGudK)@&6-_=zWwvFk6z9|3YNLLFk;Fq@bE z@jt#8dl9qw;^Q|YfiY2nPoJC|Mxw7heq!!!c?m(AFxM!(F2Vc1_~5ApAE!);=GH z>3ik}|M_1wIVpZRb1{W8&!46g$J;RsiavcQJooAGUm79~4hG+jyG?f=*uieSU%vn4 z`?R76_wV0$*XA>4E%@=r?ZpIOPDhn(?EC-e!yl5@)5#Csa%mq<7608OI6As zN6(zL>HGJ8@zdtV-kbzF-_SFm|DHpyK|nBaEQ~e3zf4^dA{oQV`Io)f_rnQ zZEGpskoxi_wU^{g2)Rdp7Kk$>W84{L>xdj`MN^V9b_st$sT1yLP(%+zOk!HIBMivI5nuKd%U!b$ z3r1W-c@D(YwB*!6(L_p7v~lFve>yv?g(4WnpoV-kA88_`p2huy(FE!dihjc9Io#>qev*f=)!EvF(JX-4pfgI55f>kQhh zH=LmcU$M;UvJG{x!H!K~E2csfTFD`Z8Tc(_k}k=;K{}1CG#zCuKrYJQ5*O!Y7PtQ! z;-gGSBs4@l0!S06<3f_}bO|-lfsum=vD-3s#B4zgEi;^dDMfK2+~K0gLQCGKvi1Iib-mR^+XF|`FmbD1Dv9Q&;LUxy`z4<{7S zDIl?kl7u+494S>9kz&r)peGR7B*{qRtQC&uD~Uf4Z`06*>BTmw(nZk}nX4;BD9aJt zI+IbiqeOX(jwh9MlO&lF--*IDRuTl8G>PpfF0@OtAm{1G&yyu|DKe5aZ%|h^Wq?~0 z6D8e+!sN!}ZkiXf!mOHgPML*@sze`16eM*%^*lpDmN{A;iyA$Tl3GC6;JA;+qd?*; znAFv?CZpsdjIa!Y*fNx-W`f%pC*~2hJVF{wje(q{%XX4ymY!|WQHs6gA?wH=TPaQP zo6M)nxfa}HXCG?`c04|wib5u&z=xsP$1QQ-ZC>nvE@G zMcR~s!lR{nGRwOOoc17}Pga%b+PtYob2I8rBl{MUDyf)|BkMcMzF$C;w0%>g2NcDe zHq+IsdD0rYtXpjRWX^I5l9O~+jgyp?Hfn9rB~r#dOxJ0e$}FAP?>y zJ&L-^M%CN|7f^8=rp6FpEu;Q`tU`u@DzyO(9Q$Lp3|Qk8&p7Bf^HnjNDB2C zuycOpwz;Z(XSrt)cPX7h-0I$jp46tgb$4ziwZne8X&$?+cd<&#o}Pwcj!yx&5IJ3U}wfzjIUW;e*2m2L~r72mEcKZF^?Vd~0LPb9bJ5 zPISA#e0@8Era;lYJ2-jjp;(CO=>GlFS^1FaRDvgd$J_ygzccP<;kyzTZ2FBkl^}>> zLyCdV;6@3aRcOqJAUpTu;Neq)1ow}Q?hllImRuBUHg~SO4W)eB<+N`Mu5WNy6uz zyK_f1Al=A!=gz~2gXBN?lkVlgUKwz*Ri1vj4=r!gy8j}YxFXFD+JA%&R6}U5pVjnkOH8@vA2%_fL)v4`Qj_^^SL; z3&B|_IjU6;t$c8wdg|~2G_P%52+)3|_{vwz=H%cTqi=je6|3|DI!tV@FCG?$o9v7u zQI4_Io4bG0WG{Vj!@7wih-u#Oj(0=}uH~=48WG$i!3VZ_AKWtuZU$vp6zVM-mfm+I zpaNr`l>{()ec))kXRJ-l%kTfdk;cx$&m6YdjeWa&^QB+c?|uC^@GKb&adOWjxV;^0C8KEeC7>fA!~H)n-Sy4KKfcRh-|vj3$~Gcn6Wfpe zE}{NG_FahnRHB>z&vQ|K`S%P3{59_o4B08%s0>Ja<9^u~{wM5~aI{&|Dqx+hC0E zKy)lB&>l#;51slNweLK;c;tlTsJ}M>?s6JGpwH{z(b|*5Zrsue7?CB96N1a6x&bX0 zcH`I?H*xs4;0MneyDHfC;CmYQo(8_Bf$wSHdm8wUO#^NaxHngZP;|AxcnP>iKg5Fx zmn3+Ts7sQLS=_t?LR_f3B*MJe3C3w!>$a0)?N5lU76nF37ZZOT!bY`t2v*Dgyc=2{(&*=-}qQpcatX`FR| zw5Jj012IB%Bxx+J7bd{L?Fv2=LHT>L?o3+PWA^e27B6+uGKyLopwumb79&e|R)nlr za_Nq|^YNT1RKuF5nXs}Owd$;cti&%CPIOSZ^RqW$6O%?}4qt+e(Fw`jMtAqt&$xQL z?t`TrX+lrA>>W6wM`POU6}EWc&OzE14it48a006dtQ94yExqqZ!A#p(svu8Pj+|?N zcrMrXA#_av2)Gatl_?WxS7`sK$wDqsqD$dB2-9a=Bde5%+8B9%JOAys~JpNbd^@@4)mGOLVyy= zR36$&guz8h9lissSs#bO)_r_mG-6k-M;r&aNgq(o__Ym8+hfl~Wlh>B3780O>*BLAa|Ncd*yg6R9y-*kEVlws$2rJT=x9G7YPxe< zWD|@KW_92k~0Ge$=+Hm!IxVh`kA z_Kvow@!bemtIf9SxmWpZkd`9qi(o z2F@(h6oFhi_@RP8<{|z~2??^iAHZqB5whHPc11##PY8$cH1g^j$CgC+c43m1MwYJg z`IPe#k{DngZ>5`I_b64q?X*jcQ-Q>eF{D5c2?HYWP>hQ4LR*Jy^nnA4aWbcO6r=I1 z0Y4g#+2I+6o73ii2H1sZvpkuXMZAXALZ#>n-)D+V)UFKmt3+wSL zHtbmlW$Yi+JELgFQS5QZ8#?x^Y~Vjr%`{#L_K3*Q3r4^ZG*rqoCxn}!cHBT1r3o+P z$(0U8GKk<}Xv)G63*D}oqTMm#`(k1o>R1HgHNINXqyZK>s8NCl!o(^u%_wK$K&J zbY|pGbzqKD;h?bwy4{NL615eHMYx%2b9egmNC0D zpEvVmGOugS6Sc;+Q4HEkUF1c_e&n>1@Cd?z5B`c#r!}29l{IO6JxYo>4Z(K_TZ(En zh&KU8%6h`d8q(F{Djp1~hl~f;<+d!!JRHv|V^faZdgB#WRq~{~xz#aCnxI6^=vZkO zbfgF(<2F6UEoc*n!=7Wvq~KzrmSKXYI_88&gy#@%PYZxKg)7E9hJf$A(x0q-?`g!= z!*1eZ>@(h+G~3<8t&1%DlUf(Pc*CvEhwHmBs@l5f=N#O+^|4z*efe8j{qJ`+jCouN zPrq<9tkxUz>Z>~|``64hrRg!cZ`dKxvVMO(c+iLAjs!S`bt!!DjOE8Z_UgyPja)6; zBys=1If9)|!frOtiYf5wtHSI<9|Hk!nFKLnM*@W}O7QGkpMC3Zb-&eZHZQ-#4$Xmi zU=BC;H}_9qsa+4{Ik-dq4<3Z*g&yf7XVeG$qf4H0`&j&2ytJU0^YByl*|)y(Tff!0 z>xwxrC$F5mE(th%yf49nm@?P>LGRa|5*#H#5UPn+&{ z`*h;=HfML)n@i>T_CLR6SHXF*?w=X#0w&MfxGR|a%6mNx<~Nhu$*=r%kL$C45#96Q z0gw9=q__yGe*NhL^k(zgw@xVzOnz|kfYaO?^WgC3f1bU(lOgWt-x@a(hf z(*GwLbL09m&s_b0Qa{-IjlUuHi(lM4(0Viy3tm0XlGMlD3^uG=3UoJq)=M>*~pEQcBG8S1<*fY3GEqjz7NILFxH-`H_G z(GGbSkQ3a(;P3weLx0I!KT|kyoWf!P7~^<0_c-P)XAtcQ5;#!J@(iyh`EDrsnHB9K z_2^B^)al+op_5Wt8cGM=C9ZUi^K(6ogL2APG1L&GF2*!U&-|I|46Hx(4?ap7)5hC{ zDs3VYP1sGCJ7c^{T+zZB5e)yzV%KNk(1HU*p}5n#e2J~LIE5nE(3tY{p|h4Woa3^P zAsQ31)-n^}YKWoTg|QvSc9@hzPaurX-mQ=4Sy?!}dq->%m>7f2qB~m3b>5M)U<#9*g2&knKIYj>mMc3(mdsV|I8ybu;8PRK=^Q-)n;4I@k`61J zDV7Q7knqyjroy)mvQPjeT!+49O)tl!jM!~#XaeV%7ld%de1OqZZ6F&^avd~`x$^br zKVzhDVbXHn1ByoaDvAN0nOUpcZR=n|l{I{LCK??sPELt}q_$jIXp%fi%~U9D9UM^OZ}-ZA&{?#9Hn8?BN@s z526DqcCtjyW!gFKR;DVB85exjq|A|Plef+QRk|#gkMcSwqv6!dXxQ{5WL}^l*{i9= zlv0(pv}Rrqw4&%dDROi`>D3Olc|&&!RIWb_kQ|je%?6SHHtR>~1n;ub9riJX+ETnR zLG1$Sih(MW&?5{0rsq&96-_bVgskPh2a|L$DrMwl<563&>6$U`uh0l@IyyBE!oHe} zk%Ys5dG52k8a2>QT}L~Zn6Q{GT8g^B`kseTF%K?XkJAx{T3Lq)X)y{MvZnTUbI-df zcYE0@kmM2(cb%m8@?<9AIe@v6=?s3cbycL}#Ef$tQn2kb8LJhdzR4t~F&0fVNgMSy znHOui;Sy5?6DFTCgm26>!iqGo11BOJT7Tw`TRK1I5ak^ zL``_rWqFs3i*Ywu&%5JhEL#ow`G~WrpTqjK&cDe~|qnO8Yj0kj*XllUiLsVeoULz)jL@ zx=Pokb>rDMO`D>a&5wELtRR`DImRjWYD+Dcq?D?eQ zsB=JnqI9U!HJ+N9PFzDbqgp&;t~Z&_te%zGg28cYLsoZYMu(j;sJW4c*%UXk9dAn5 zz^Fup&7vyjt*w_B&}}v<+O*;+Y1bv)`aC>_&8)MySLeNZ<+g0(o5tLZqX^^R){Wtb z>Eq#YYl}CNyIZRo)zw5?F{lt=rJeBIngIVg+t-H`cOL%D?`$?5v+)kg?q7d%vr%~0 z6<)aPm7Yd^*BSR@midD$~?8%-1!hDO(Kh}hdUp-bLT@JI-k43 z;`kCouXF9@JV+wE{I4Lv;Fqy3KL-xCv2TAu68zU=NdW#Slim4Hl0*rfh2&XFEA+#P4Ol4O}ySA^P64`8X=en;Wb=@2t97S9BEpK_t3j^Kd z?q(B!EbI07>{f!%6EkF9KhfK^`9XfLFTo3&7hjA-H_VOBbXy5t!?LF0Zd||q-6VLh z$#bReZDEz-l@oI3mWhLsqEV5$x+nI0r_n{{pn9{ zu3x`?@-;Nb+1!&2%(iEA2TtO?2XVdXOoBu6dN09&))tI;mV|?g3K;kZx28RO{dH3A zNRWI6T}VsUuWyjRJf3ad|NgISz82kqgWO$62{^`mi#uUWpQo)Ur3=MJ~ZDgX}L#GqK|#dUi8JlP`utfR|HRWM%cwq zwguY7^;CY@ySn$4a~6IxKL02pHdIboD|cqsJEStAm?^%mmU z01{4nzylO+@SV9{-uf)O=ku^S4=$aI24xb5yiQG1SFZ_**@HXRFnBX_ualzIB_cw_ zZc1OCT|t&&G+bMjgEI)g2JC>6JMUYAN-PaYk-ZxO=x3`+#_lN99$0=fo+j7kOSy(M1K-oY8);y~lRiS-KmGJsG@d3St@<}HLMMQP?O}KlDx{~* z7PQIWw*EfZ5W|B>UKj5J7hx`gp}%3Uj6 zrd6jM9qr(@)BtCd6VsN=w3wOI9*y;LHMW(;<&15ozR}JzPTDe6Wj&f~*{g)y7zYCr zB+8|rnI7lRB!^YcGoch+=;!0CF(X515X&LgBz49~80N-YnkP1#6&rk_?t_s`I zPM8%2{BQw0tVvxv{QG*aZq1Z*tOzqIeW`7$BDZ$L**;EDXC1FpE-Oz>WrbwVAI{QnW5eQO3BC zgai|!hs<@or#1nK2&h4Byvc(exToo=w-L!dE-G4fwy2CHameJ1S+#g^cfl{(<8+=b znU1%mWS=x6AX-orE!O9j^~{7;}|#wOl2`eEHN;zn3~V!l2aLLx=oxV zBX9v6n*b(wE;XT?{P6=tymL!zX=ljX(9LS=h)F`;wJYr5QRdUsbC7)%i5CvQH;mQ& zN_vbk)>F!UISk*pXpunRp>7*fI^LcnF@@Vk^wIHtoCh|yO7aQXF7VwvpR(P=gy4aB$7x1^8wQUIGz-9QNkEt9b2{}GK)l*ON85wqgf_ezj*?3%)oC$1>bGOJA z#WHVvmvuz#L9Vlm@o%JWmnO|5na{>aQE3f;CWn6FZeLy{i}_lIyX!7ykiaIJOPk^n$hBqS;)*I47#b&O zXu4R`oN=>GrzTXv%$AGsf?d~{ceAl=LdU7i^FSY9KQ`BfWw33#P3vOSgh z`FPweUDtTd^R5)X3kd;6?TR|Qbz}mbuj+iOOCL~Tn zy*Bf4YssiH7Lt8{+bl0KUVI-rHgwf4!iaUSX+34@npQ*uAit2Un%GwApvNv_v-%1( zj|9Q8{O75M@!Z3F&ckT#wd+^0Kgc+^oG-eNhP)W(@u>sN9^5wOCV%B^Gr38`72H~` z@-T*20lR!RWBe_1S7We|vz-d`lvgUm2g85UQz&iZcsK6yHL&HsB6c4}<{PZMvv|%< z&7l_GH#eSTSsvKZ@mbf+ty{NP@_+Ef2S?g3i0kc&-DDXJS*h@-Nt;jH`t4h+ugA0} z>=_XCt)nk&HYuL>lZ#x@?Zaksq*I}MLPxxCk1X&N&WHvP-ZHmtAp*lpc4WTzK=DEg zvP^q-rxJX?d_WR#=Js*LZa)TMkG{bBBbzjR{}HE0a22-;-%dB?*|0Gm*t{I2`_2m| z6!)cr-!Q+i-Q{`sP$y*{ykrivbD*@GqCJs&VEB?r1Q+iQ4hITt6@7)Tqo_phdIveU z8`s&Bd*z)_^eN8nP{qHk1niLVg`9&222 zUO$z9{kDPgAi?1^V=j|`ov@GbHCuMZu6~03cHCjd?CS00c}||(Gq(-yr-c7i^B%=3 z4E^myCu&K--rBG7fa+ahB89$(^D!tD|ATOntG%~NA=ZA3Da_{6_wV2O?e=$%sP3x% z!>`^d_-lXrcfX@Eu5nBGJPW@?C(#-W<;tq+@To>ZoaB=3CZ{de+Vnisd^ zdk$%08xZo-TM1}@dlJO0s9u7o^D_p1>s5-Up4zbEy*YXD#TPcbBv))D(6C|NNP?$- zhsGD-+BLNy^8@AwUichsX8Uzp#SdqK#h;EFC4T(-k3K+;xRz1FNjx!o{j=R4^qh?O zTl~HB;9%RHIT`=uC!ZYl+y zoR}RX5Tzuz!PkZ!Y+l(Y{FN`i{YmY;;oXCbN79_JI3>H>Fs?D*RF`FHoND+=@i{I# z7n+4>5ujCzYm+T2B>*&hM;P4g;JC%AoeywE5&64_ACQ_SM+imlB1IqG27}}S0-^yh z4hr)ao+=Ckt{$b(qafQx4CUCNv)xX>ML!Sl=%S2HrQZgk!>!z23YTf%j?|I!PzuFd z3enPPA+wIM_(0UN8z2Qg=QFSgV%RY^VIFsEnJU_njA5h7 z;1)&jC78jkRGka}PhNm?W5?W^t2Lpi3TL!s<(tYE^U~Oa*rZ^}XF0!0ZfJmGtbU{( z(yh^(H&v2zJS!`zRnax*PH!cbi5N9LwdChWqgwECF2ZQ)QCbpASxy|s&5CmAQL111 z)=>`Igz2cBjC=tLj?q%V6c;r}bLps2JMs-F+T+5j@)PFH>8KmkVOewDk&|I<$sSy3 zLt9EOG{n<(;LXUitT~(mw33274{f$G?vN)pW9$L6eI$Tmlun>uxvRCXUd?h z`*dRGS>A;4xC;T1gE6h+oMz_XxDO5F5t8j-QRi!uBt?_xkR(lQG+r*296le99hr_B zrv1qZq4`hxl>IXBsHrDfwpur8rEsf{lW~(JlX;4%(i*SN+-`ePpYH5l=EsR%Rvq!d z&(S<7`24D;{m(~jr*)xav+U+86`d+w@%&kgSSZ8RHW18IWvatCLM`Z%qtsf7gyncNUXPD;UNqFE2U^3WVYxy@Zx}rNxo2H>@wUhZY zUDl(nnl0zYYGPsLJ_=CRXeD%kgdnTFBgGvEjU^6nWs%n0xL6S zTB2f<;Tiv&R(pcZP*Gln^aiQY`k3xHsvK3^8X{PSQoZfN)!TZD)XcA-hWKA8e7EYu zhP(8n%j4Ko7t4ny*a;oJKE0h*@xF(|Hy5< zi>BWf`4myIf}h>|%;q`s9Pc_Z(cR9>Kk|{y9i@DB^N~1Hf7|G78X^G_M9k(Zo0k;U zZ>T)L#@oD|q%Us%8Tj85{!wu4+DC574!zz%fe4zQ%j$g_e;9{{pZnZqskC3&^4T7u zGrJP>r(d6VLUeHAPj;@tx~^eO>_FJ@|C#c>4Ou6Dk&-|0yQogqy51fftaR0cbgS@3 zp5+{JJb@am7xaJk?$7<4D8BveZ}SG`$;toye|DWH4mYpAe)a0+>V82levP<~zk73# zzyXp#Z9x2n^wMn%;~6CA<8I!3-}|;ycSJEr@axF5D*;`eo_SG%TvmDh*Nyp2Z1CrQ z!hA}$H}ALR_fo=JtNnTNo=@F-`hzWQOT6&;J<%HvSA1CMzK`MC4fo8Kl7D2qAq5n9 za_`o=`|stZALPXBrSROHpZ|HC?R?kO&tE+<|MubM+RwGLV!rRn3eAg~&wS?KK8rOh z*KAjdr1K56vW0`g8?x^?Is4FH>pl+1vVCE@;_|K0x3;}T?^J*B8$+^P_s(-4{;*a* z1_?fK>l3%y)|hX9`*jYSvRd;Qel>{C@3L&9QEhu_^uz=OwEpzEBp}y^>PnBB$FXLO z`J8NDU|3g?|4|ZXy(Pwf|KSa}AOEcKRS*3vU!tX7-`G4W8(k|Ky{*m}RN%=cm6Nol z(1ZFx{rcfnGpsZWI*9MPiU8Pre4}NKi?9_zE${{N!kz?bnIvE(u9u*<)$_MTCal(- zNg#}@^$1AtITirq*ZZy^A}Q0y&sO5LD4qn&(h|pz?07q_G#w*)?VFaTE`Ki3vqDeb z)U=4A=YZ$3)BsODX44w(LsIg9vrMvdv3|_6E-;J-C?h0;N6)}`og(B(eQTp@TyVyj zQaOW(C){X5OGN^ntKrI_X$X18QzHoPUE>mGBxd~cVro3yVGHTtAzsB1SlY}fbf-Q8 z_a5M&Basn&?{KfUeA0&8N7f;$Jvxv+vx;uxo;a>~mQPp_~C z4fyycBEO}SYsVdN#yUqx9@8^c6=?k@Uc4kbQwtW7_gsvnZ7CIk3G0CJ!c>xZZ4y2$l$%?n}RErYGJC9En z=I9Rab(8)FM46t~v(&X_Ei<@kY)A6ZTB5KSKbz-EDt1|>6RO4`1i#hb5R`_+R;@Fb z*Ew=A-EPYU{_U8X_r{kgV&a;_DPvt)ZHN{Oj*8zVS&p2`HK7sn!phd$Wg5LQ%NJ6V zW5WJMR-%YPY62>|bnzuXrihXW4s9%3ZoQ*oGz?BG<+Z^E)1m{uHm1g>-1mU#8jdG}*bA$$3_yrf# zzX+4ZhZ+@ukRGYPsxytI!5HUU!TJH4NKpB7m6hG7 zpkf!Z5|cg2QqR=CZq0JV;sC6TJ*M3jv;!b(>5rzHhql!gX=)s5U*;WcJFf`#|%HxY%=IAea<`jj~WWt!Y|E=^B}Ua}zwji({#0-Q z+se#b^e7yJpHreOAT3pAXip8fV?0p?S~I^v0dty?s~zRCj)f1h13F`ZTmhdCTH?5T zvYfE$P|nwFF|YYlQJXha<87vg6@Ybbi^HYF3ZC**xir zD$jY)Bz$&@V`#FMMtA!ZHUkM_%*e%a5dYsj1z6KM76NfnuI}aG|K4^Oj`1yx>P21 zu@c|9b)N7hhg+>PFG}8JZ23ghthHn8{sjmusd+PMi`Ww&iI5uxbhf1%Z1YAL1x^u! zv1tgcT02Q?SRV7BAl}eGM<{b!dwOS7-^41pvl$vpSS}0B(&S}2rLRn8Wyn_6p?B;V zs)=Q&se^Q;F!exrstOq_e>8bD532DP4SMevMcqy6RqmU1v}y~F@mUx@>hg79jl?u8 zN0||#E;`GXy}YLqT(ihS8;qm%@#{8{vRHcLVyH&GEG&xY)J%DG+U1U#QWD%TB&jDU$ZSNJ{?Vc*+Z?mKBsk|0~s3Xf0!a;qlm@}|R9pZm^G+Gf-w zZqnB5Us&RsHfyrBFf4O18=~4KAYnA(JivxvceS({pC()L)3iagBLOFQXi zc1|uzLe?>5n|MM%!U`!zFU)l9jSCGcmMoZ<5nWF&5wA?J#)ncpw?gL(7@=Ro&6u|2 zlPdTy3X5(9r_r(-b9Q4+uM5W3sM+$xh1N{{%G)K?FwQFDioiO7)pxvHQ2wzi!lg7< zZp)@N*k0zbo48k_bza^zcV(?(gU5IRTfnD+t0j@{?wmbxd^gP%T(5P2n*&Et+%(mD z`!E!d6BGl$N};2JO*Dt^Jol-m^-B?(uWcURbek`TOm8Y~p4mM6OTB?|qS?FoD1X5B z9o)F__~YNtTsg~b+;|E&WJi}T@nG*CK434MsX5=WVW(KQqoacp{h|yT?6?me$e_q` zjG-6V^*+EF0-n3`^rzx)cAOCC_yc%3?K;i@>a&LJ#C-|AkBPZv>!#W~(@UVeH~lt< za@5u*-?BOAalHgGOU@*~s@fQtH~dzP>;&a5yYuaDe>-22y3bd3zWiUk^40(GqcVvV zZ_LAoif6u09Pq8pm*p7q+6%WH*H6BPw|+b4i0@0q@)Jg)!-E64{kMH$n6LaicyM_5 zo%<3Wc@Lj?K{==fVh&hgy`A;@PyX^(uYXiVhvF$xl;Gsmlh>54x2oiOZF7q+EARwenUUa-QWtFSCMB-%>w`qom*WjkZ}V)4E^2?h)JZ+D9Br_S z9eMpi9pC$uWW#T_R0q%S`?^=J4!>N&4rxoV#IqS}>7knZ4MWJcT1 zq?u>>{1W4?{=l9D$<-$h4pcu;f?qncLtaDKhVZU?^|h<79c_*h<*sXUa(MskfAr*& zY~9mP)PG)oUGzh_UyH3&@57#P*=$&?szkZ@!2WN_9R27~{B76g?mUcNmpc04SAX~{ zUGMvWUV`}RIZ@I<0?rTgd-=TthtHh6suX{8|H=E$B92yddSHyq<%_ajWq*AKj`CQO z$(`q(iWdIS59b#oaMmR}(@2%kKv+^Xt#QV+#xur)6$3m3<3>hg@q>I3l+Iap3aDyjM))4EhK|y-?bIL z9|{A`9>iI!rnIF?IAEDfI@LVw)FEHIsHjF$SIScG%#IBsfC|vjG_j`eEf;C9DsBAJ zZ3}Mj;GX*VR*cV3sixHWI@V-anrT}@GKDB`Ih5tB?J(siG8=ttIHr_1wXMlpUJPzi zR!Syw>KBPv1?m_*+?Z^czPEJL4n48yV-iyau{#HR^T`&ORZ}aN0#51??c6)pRH;w0 zQK`8kgB24#7%VzYJ`@<)vu-&%p5?wp2?aB1$JdM4Tx{*QMU$+`gdz~bdHf>Gv&K-A zRcE`#h2mHO6w-He^@faXN?rqCcbYjf<#nkud0>K0dhak;TnC~w=)oZyHWqE5w$7($ z%)uNRqTwj0HyuR4(iaWw%5mb>X*1fPFQ%m4IFl0Xxzw!BzzgT7U$j^>P)u}JL2@*<46D!>=I+pJA;huLTYk<{$3-3JIc?qfP{joMw7>L62mnS)L9BK3q)-+0I_fNwF0M@wrtkrv;6n3U$&9&<`JX*p8A z=0HZ%>bt)j%xKMe-LY~oA1`fioIt73iVkbX*3GaO7yT@SZjQMf$UY6+ z&jANB=mg}Zw$zzAK6WZT*;RsPfNAH&I$yNwgztly$%xYx(B!5{mTvBBs?Sx9YZJ=00YgrzK| zi*oM3XN#HFFM5|sdpayp0GFh8WUFY<~m;k(zl9k ze-nEIn^<8(_-(}By}Q|nPN$dq7^RSZ`E~Z9LDkXtjNwA@AZ`|m^%4awHJHHd{IVcASdbtM)wgQ+W{{Hpl z5`603t&jCP-6mS+=3e);-ETm3d;#i>z7@qVwnOnlU*aoMf35qK9|}jA?Eck1ve^Iq zFTfJEt6<)csj&y01sYyg*u^|ac(`omEV$|vTxq^?9tJefB(tf z?{%37y#>WaFC(jBW%NFw4!wC>#FOoNWEWp%LwBY#SFg5hOdlt~_*jO~+X0ebv&nA- zP-O8P|4}5say>k}u~GiQ_pr6+6&U@Ktpr9Qs8WG{z`t_et`7*c2Tz&*Rf{#|fB(Dx z^hf31YHzi2wc~GIGq3&OSO4&<3JxWeyV<<+#`PCJ+Lv6BJtPkv+#cT^e{1ts`WDB* zPyMp8CGrr;h;1Ta6O(O*ds68VSWmdIWc^SHC^=OmrVPANEZLLX<}+0 zrx?PVG2=lB_;`;u5y{xvL2V;Lt+|cBQw)8tc)_X$3Oq)bep;%j>G{8HYPWSSahChI zfNuJ~eLP|ZD%8wf+7h$is`%`x#em>^Xo3z>e!ksL)_FH&yErpiY?*EK$_f(njJd*7 z0Bm?uQlVNm4^l|No+x+6(ms1>=+4u&M7s-J=Njj_Y+;y;YD=2NW}24$g5xl9YmVMu{CVb%2XvKTv1sUwopd9E?GY7iw2ZK%^kO(BqsQy$xdq#6M0 z(iEjaDP{o@FhV&qa|U@+Dj}a6Ut$ZWNNmIqrGGjX3kZXts}lATC!<^C9w3$o2jWsWq?|O zW!sFkAS~SDWMV7HXj6~2@}PNt77~|0nwXaR4vciX(vR}aj&kjEvu(uIR1+r7PUc?r zTIVKXH&0xbuG?7)v9${q*h9)vwqH$9=5<9%lUNs8U-O~qre(XmoUIKlsBP_(lNB7G zNTfE)wFQ|8KxZ0SjMb9fwp%u|rgp?j$6Z@`+hF%N85P!5jx<`UAq3Ff5D=h`Uoq}yAF9|iAGUcy?`2_G^E}Gb`&dGOisZ#`05<5 zoYt|Ys(O-pNR5jO;(Zpq{cXD7%V(0Q-Rg!aB?il*;d5>nh7}p{ ze;$(lL6V?^gnqM5u$|Gz+{Dd52FQ*B&5G*SOvW*c5s^o{cW3P8(?!BjcR=UeRX0tH zWPiT1Tt0^Sw9&i0sZBG6AVHgQR7%Bh53EHLRY+*TNv=OGX=!(^tCN1$-D?tryka2DtCj|oRqco+Af1b5F(BBAVY$kfbrfy2HbMHm3~~yw3@Qq}g1ab7 zh4Nr=SROLYw7BPBr8OUxN2hwstP?$cmb6Ls=xG3cY^nS%;Rp;(q^6JSBiJn|+H-6a zY?s|?zToZhq@gk?JX4erzqh1-VZ&VGQa-vM0gtna2F7TSc(szL_gK=S6dVvC$CXKg9?n5Ft-NPg z%o-m&Vos+#d%X{=-xy2N$kzOXTj5wtsZnEU+C^*H{6azK%hM22oxWdiWFbwbA{I;9 zUZ6UTsh`SlK*3yqyYcyTOI=6reqY_%+OWckKYjO`{MEUy7}L{>&G%uh@36Z<%A2OT z)w|}sa3Fm1_T9U^)s9Q}64*R^cyPe4zVKe>Cw}|Zt!Lx=n8v)7zX7yc^(3Hoz8?*P zMfmX_{`jlARQK;cc<}CbKm9a2z5Ke%*$L=VnoA@IM4n2(cWOWIDm%8E)qUphNE&?v z{F8suwu*XB{+|DBmqdHb^ZCfKB`5-|xQAeIbTPuK0Z}3f+%s2Tk_<$mGhaRmlB-byQ$Jx&G0GY8t0 zKc8Cr)c#kB_hLiGce!Otui`23TVIpQ>G3b=-R@jx!JjwU@%|V);_o@nM-z*`W!VgR zPkRNM85=p;&V)y`ZIXp8cnAE0$uIX0_VcMXo1cr4#V-UWoA|A2(XccTYfYyZ?w{P} zEOK9o|KR1zYGJUA-}06;jr+$G_vq*wo0lErL&*=%z0I%{r9LM?*y0E0={&}k}E4=KSOvWA_AwmDfIwZ6^5vn!Hefj0S;S?|bA1_Dz z5uE{WKk(|nQNb-d{q(0k_3&Z;>qS~95c&!JU*0&*c^pOSoCWangXS8490&=|tkPI#^w-Z7jYrpUj@5J2 zhd+#0tY+m5@BJmm^dmj-5e6yTHq4WD4~F<%q}ODUb>GrtZeGP0%M{lnWz0Z`GGhCi zAN+|iopD2`m+CA;?4@wYlc|k`VzeFd!-6#96?3;FFo`z9pZMum>NcwolSv-}&&7MD z5|vFj&rO>F){UKaM8W-7j$laAhlCi}nb16+w`C@=M<-=sth}Qu-a83C)5RSsl&dB&>Fi~dpapvYC{9A3w?~F9Do-RilBA2Q{YA3 z6q!3UzSO(iC9Q3f(2UmDtjCUw-O?DxL*JR&LBwmZmgYd?^KJY>%1B5TPi0(-i-_r^xP4XBR((`AKE z;+y##avrNqF(A>=m4l1P*dL5;8}I#%kBoS>@~{_u#mm4WVI3DMc;hASpN})%w2db$ z0+MBlj*zW+>3xb(Zz?S-rDIlL=oHzwnC3OjH5)mIYdbEyr#W#3e9n*ZEXGwea2VXi zBzP0kVk8+|F@N>?-dyUA7ZaM|1lyVl6>SeGLkNu#i3hbPt$-6S(e08n+WlFKNU&Si z$!v#1B;rOBU~hIs?i7&?cRdyK8(h|-mYUQBmfJc>IKgdJwAcYSiC*$0v>d_sI$X5v z$Q*5upU3c@V*g|7E;(Q0T4S3Qxn?W{wCjPx;O4Bm@cZHwX#+SKW=HRxB1cDWn2w7u z;)MwgY=g}M-_KK*Ar=XzE^fB6!JTo01zUH*+x{+dCJX#lG)8o59F!4)srcclrpOm( zh3I2A%4}Sfjr6ia&CmEuxAfSqK7KN+SdJ$A`t_9O#)#U8El)H{*Z65g5yOljFw0%F zq7!9hRaPyL?ShGf<81%LE)b$xl#6sZ$;)wj)|9pqBq&i;z-^rzqdX}=kIG}SO6Gn_ zwXl$~n9>LvGr}U@0-s~yKo$iGwOH_1M^0?S>)2FYmlS`^CNxDeDaSK7){PCG&oq+k z0c~kUQa|RyfD?`E@B`E)a@>}bKBAPjJhrD;GC^Pysd7nzQd{a0?0Hop1(j-&~Q$jP9{`{QgIe3CgvOhHu`NBmo z!I^68oTcDy?C6qAxcK}BCvpnPX5mzE@mHr!(~Kt}^4PsqDsVK)AG>*KUSHkX+=jP$ zwpRS@=r%*rD=|!xEj)JfZhYJPv70>VL0_5ITl;_5d%qj4_<{b+eX#k>&9}b!&2OGz z&U}YIdiaim|Ki}vv;Iaz+OsIl!OoPa)y*YbMw$pmIE4mY%+>F5Bhy| zQ-<^CKZWoewjsa%bqwr1aHf;^{OSE}4k!2VPkj5^BEt~fq~1DR1S?iIbeX)BOM<^A z>-Q&r^5vJ!a`TbM2QsBH$>zfQ&PecU-}uHWdlES4%?(n1(|-HT?K?mHEU!2VWuE9Q z(C_ebOGy|Ny3Pd1+ujcyU#K%_lz@Ei@J;|Yqu*#Uqch7~xCpEpupaO!bI;sP7|G?D z=V@4Hd+_YVC;a+Szk@y``UeFWUx+`M_f9=M{D2j7l5;V~1bX(9Ya*zFFx{%!QBb7-*PcYq%zR%o!wcVbSx zdlHy$UpOgoO8BNcX9Dzt7_V+n1qbGb58rtyXT2$~%lO8Pe%;{OOV?gv?Wh~#Zm1@= z@M902-Tdv|mLE_%?&*1gGh7r!3u9D+rQ#kW_XpLziL*vjH zYWa`h5Lp-&1FWb|p>I&9!E+v1Grg4*sR-wAY27Z36xg?Vj}NhE&yB;og@oLc((xyd zGz#y)wmIxzcD)`uW$0E)h@bb`@OYIe@|CMgj4U!((Tg@_E?bBxhCpD^pIwpq+kZX*KPtnW$L+j zkoTgfF5{tX!oJ6?BzTLU$Alv&)gEMC`(TbT1?OGBF8_bod;ge8j`Pm1y1RNcvtD~= z2pT>FIFy(1o}XzU`$)gJ((zUDn3GYFu{V|2jnwjo3f$M zP2pMLiv;9hl|~!6olH2DjHMsSBOu{btVJYed;cnnIxxLtTO zEE(;Yf|HzSDU9o4E$Fe~*RmZpC3Po8B1G?KliEjMQQb9AB;zH83{mDhWr9ghV97;U z6T))-^whhFCnD0OP2?_N)}f(oSi6w;t5-;Dtx>G5jnz(W7w07yeK`Jt3CHyxljp(C z2_HwRCQ)F^-hSH{M!<~nOwN=NwaD~Ap?uVSjpRq6Ypx57sX5b1hMk7F%&ZMa`_358 zST-$a)8m$QqIE;v)J$%RzStCO011Q?F6U9zO^uodGg>LHPHJ>86?aN+f~nfF-YlES z9!S3c(I)nfe&Vc$ZIk+X>Ahv3Op8O{Sg_C5vjRIAznZHM4w7uE$|aNsM%O!D-M!Brg@)hmpys zs@kyAoct#gf#yg<(8pti|) zQjaW|oF#-a-K7Yp6OXRxT0^rsGo+hxHXO*f;15%&xJW#&wx`J>l5;8pbqiN*RWj@z zn}cM{y1KE;oGs8OKve5ZK1WlbG^SWJrdgM^{@F{*i1nSfAYJ|;{>#);&L$OO+t;*|A`jHKjYI)F%4mkSH zk?rv&ZCi3g#O7eudRj3GAN$|~90Wu&B9EV^jd9tuoP`xqz0Kz-r#h75(5QcNR3^sM znUG2TE6tpzS=&u93A3!ME6xPv@I=^V?>>jG*BqXfmL`zBns$oz-M~g^v!t&0tfG%q zFD;U4IhhnqVk~cIqksfmcjnG>V(XgabzjYGJzCfa=d06nsBRm#WatfqJKm+Nt--Rd z-GQ*pq#4zd$tc06WptB_MzeZiJ#&~d?KlDC>x zOK(Xn^T)OW`j!JqIIX>tE*x6>^l)LskFbHyfw4h-(lTFeD3cI2cAAgFvMKp?vR`7d zoVIoue9KMTOaX@+k_Eko=eHrMJ-861a4tcn7p6#W_wGe?TkhL8*}M89KeD}BK2biA=g&VckKJES#vX0%z0JCFum+sWd-tAi z4qtxx@ZP1naWD55e=nB+!#;qUH%II^){V5r?S_zjdn><~Wv9{Kyz)0lkg9jO&uxDS7G7@2((U`)Akw znam<56Qp7&P0q3TFZQam;J$3OT>laL(OWPa?x6w-Z|3X84 z>O)@xADXA)T0C@d1>Gc1edzCso}?7w8O30JA$ft8_Y|{fEC}HKs@#3d^T8j?X}ELw z`4)KPmF=NCKJ%IFosa+i)ix5PXbk|`y}xrpTl9*%n;k91y!+j+dJB#$Ui-iQD<(Vc znKZVdNQdp$e(l#}-Cle0T$$0_IlAj32c7q4K6A_LbI?U~)VD7mopA6o^!fm|MES_}C>& z;2jo8(eSGned2Ux4p8WE z20R#sFvq|;L;QD*SUIQ@WL#Ko+*t@kIJJ7qoGI0a4~q##mVPRj~~NXdP%5KD}qTvq1zr8aFX(1Qv3$VHL9dor?+iMzL6Z3Oy10zP&-AJSmV86mBlGf=<7l< zafbZhl$u5dT}8vaV&U|;JP=VuA&r~B%35%(?+A6Snm3k~;hj%{Sx&NsOtQ2pJX1Vs zC)8_+O)0KXl%%}HEZMLOU#;_UJCk}RlMpg#b`e}n$=NAQfGvJg>Z#5AIGapDzE+v& zRP6-DH+5U&b>a~6O-jJoDsc%LYFL(1EyJ`iD`uMD4Jl&62)X4Sy>(_>HU|d!VcRm zuY8P?{7`EMX$*<2#Z_1;!kfw?l4>Kk{?fu7$C?IX9dsr_GxE_~_>|T_jkUyuNM#qi zEI@$LQOkiGc)QkNAhI{!@MNhmPZ^`<)>AMxxI(3ur8tcwO~sJV%8-5oqYcwo5QcXU z8Q6QITx92*4ldTFLEsPlYjLj20zRji94+a+?DJ zXLB_t2?DAO=$)PsZ$)3M^>(%?1-n3Fc{Dp1*JGMg)jGH?$$)7fqp8s!Fu^-(Q={zy z2PCzMUKx5C4hi-EvocO0T7oVQ7WK-LeUzY=bP$WYts76+WoFZs*C-K-l&1pOIg$j4 z)wA`%hI2LASwr87ZxWYER|y?O;yDhkr1PYSR0+p|Z72xdy|#j8wJbo6>}pZC1vU0Ji73yRdSS`S$`P4V zO{qSm2$+?ggw-m0gQ}0_2Uek>kPc>8vu0LD6OotLRn;^DLDn%qHEG^n_1(RSvF2Sz zLGLEY%&_AEb9%sp2QOa;a2ON=PE6GY|5T4@f(f^8O0unPU!X6nz;z~=sCAAo-ATg7 zW})v3z~dofZeTl2!O3ks#l=2k=e|IM3Ng@MKq6Em_T87z2w?`E>pilcA!h> zmYp-O@QD~u1Jyt=xOZa^ZV26lyFUw3-F{_)a+Zg1$jT{a+5|{rUQ<_W8wM zZ0~*Xixqb)h#YdCRnr1MKr1X_-(%((Kn$#ck=@*mGn~x^H zeB!1fIPn=MzM6dIgaZFZ_uK;=_@DOXV_m&&Z{58q+pDj>SW&#gY)@xqhrGpe&FUC{p-hBPd*HyB2u7SS(^7igs z-jEwNZp2>aKhyq)j)SXL#X%R34x>|iUCPX{3>?rp*q43tGzXGc#lar};^6w#>sJjN z+~FR-KqTKg`rZ*T_ZAKe2dSfpPk+LKyAm+(GTY~#d%k)3<)8e?Ye#pu4eioB;@F#S z;N-TWt5@j{CmTRBP!s{(47N-8Yd`WM_u6}H{`}wiTf%sL+w1qPsSG}M^>bH+V~Xij z(QPlknrU85xSZ<^zZ$TxBU~I@y3}!Cj>N$Uuz7&8W!?x5gzY%Ebm=q)Y!xvB2ckO6 zTBb5~Ik@0O2fdhpT2Nq=)LFcHq+r;39B2qvZwtrIOD5gC9pF7Z-@6vVha7FWs1 zl_*hhk1>G8AnNO#&}V=c&IRw~;T?Z6`GshSLng@!FpLYP-lU90eMZX8tQ)X}XY9{fXoEaz9QiyKd=NU> z_lsZBhzvaS+k+`tE!aNFWJHV9=EP|lX;}F(n})$9?pPh3=sm+cs2G9Fe8Sq3^3{l3 z{L63Rx{ouZk-Lqv>;`0~x5k_rT5z13h)+ZA5bKpQtMO21sNFdN4g+G=IaxI;aIOy%6R+j3(ln?Q^Mt-kn#8R`BGy9WYGsXY86}w-rdObkp@n%MWjR4o ze6@18H7aKfI$hbhpHc{V6HH9LHk<`#Bx_AvnkeV7{{3}5 zQ?QPy2-bxu3o6cKSRza;qBl{{kOj7@R%~h|63w+jizvu4u0%u297t}RW3`aVFloc7 z0F;l`zZoO@so``aqN0BD5@}2Amlb~!H0U@4i%efrM>dB=_O0fmuz>3bsh(na2UZ*i z-LQX!wNTW&lZ@f3<{5kv35`cFmvl9MV<9!<7saDAnRYR%~JW(S)geJ(}Fam7| zpU}~@jR|XmkI=-?K?@r#_1t#OQK}4a{F!Q0jm>+H&&HLGripFoQ^%#pRYN6eBtKqN z)U8Rq=C`s%>XQK;Rt+b_;t`Z;UC+35Q3-1LdNUdN6YpX=vkVVF7^xZFTB%hLv?a#eEvc^gpRZ>hP zrgb|pwX4P%TH!=s)MCp;buednniMooy03PV zZcO3{?vvtxL^$|5sS?YTYnv`dj?aqOEV+v7RO)gBb|WLeQlF}#tZap(D&lq(m7L8f zqH@U#J;_azI@;72g#tlHCBjQJy4^Sy{=M^I)bI-Bc|cnvn}>p3%Ziv6tsx_;c^aHT z?tyv*RXyT;h)n?7EYgJ7I?6VXjN>@H@rYeAOiqrc8|IhLC(j!=VCu@IEgIUzhSHoH zQ-_?km8wB7JCs(;;Vp@AwOAMPK7|O^%oP5zFOi(Qja-9=T-XJEjJ(yY5zlvWb)zL&VWG>b<_frI#S}@@tz*3;MTjuEj zsChkQR|X+Cg|p5#mU1T&9~4;uS`#(FIPO&owk;2uSkq&6lkCHV?(1M~_h#?^XeV2D z>()0w-tPB|UwAZ1`8OYWv^yEjFq>^2(th;|x3#i;(Ojsy749ws_!Bpks77}hB%E~e z?yecd>nIgSGU%lS%zu96|3qyRU-J@p$t1=+k8I%Ej~yvq`3!If#GTvQS2^qK)vG@b zY~Q4s_TW2nfG?m^)D-Mqxz8DI zy!aK-8`~fK(I{~dgJRJw?ZV%?c1jQt>VY_rj3^FbfUVscOT0gI%)!z2&KsY5W8fg} z*A@p%u;_5NSfOltjvVycnPWu5V@I+bWa3B7Ao>2r2mP=84+*EKPkeLXL)wi#Z=*K( zD8u~a9}YLvgT)nZYdER>7dU}kE8rhVsFU`0Me)I`9-6&b58L zedM#3AO6b2Hy^$U zD;iOXgG-<4I55|;>o9PK9yG#v9Q0nNjVtP&-uiY%o^^u0Jekws$p0s=s|+Gg2JEcw z>}LD^lNIaFanqTuY`b&k9@-8aXCf14+m~ps=fLIv>E$TN9(!FeuN(7yOf#3qC~KP69|z&qfm4JPteCU;S$Fqg7p~s0Sf430a9VT|k-x;$pOjRc1W$5PQ}bO3giYBOJplKH7KtMtt_wN@jJfL^TGu9`psH}eX_TN02cBiLxeg^{!f+Ve zPUx=8`4k7GW*u38o}f(%Mj<6T_1O?&2)z4&no#d7t4iTh`N+9Rnt2mzxYktz@EB?p zpYkOY(umq}vV`7)Ev1R9b&n}wsDx+0>ycM9H;ux4z&HWufDL@MeP$Z6T80W-m$Zoi z!45#A$SIT>xf`>z3x44w566^j5#>}u6$&ut#}q&;R=G8PbJ0BYi1{mHijMNNErYF$ z5y(Lf8HJT})ZN&*j1J8x&@!-#W+i=VN;hSrzTD)YF(xpmjuKY|0~WV@%)~|G)T4E^ zscjRZp4vHcDU3O28w;<&DbYFQuEhqEP6pr;;)D&Vill=Heq7BNL}s3XP8}_FDqWm~ zNJO=SiU2U(k}0w!Y3~Hm#mI#MN!XNj&A@k*gpD_@VcNp3(3OUAp7T_bC67*gXz2}k zS*vJm0AKPaDB?JthHSeeO4~I#bXdJYk8=u7#d!)6+ctga1jjO4GMe~Jk)VLj2$@-g zI+gZ=a>O`&WS6Vf_-5Rg){&!v-0_>B#M_$2n1;X(@hT+UtEzw`$ei>#+8Pl-Mw=ag z`vuI@b>p|ft8%TK&Lw!SJzP`r1?y83NB2jJ=vr!i!1LGV98muO8ucc|}fvb*V%SS?8Wps#HF#0gYm{6n85NiQ4Lur)_F=ecrHg#d<1w~bx;8X!M&EX*Afk29G z57fD-pZBIDBE+|PM*Yn;mgZHI=(RBMp*`hvgM}l-i3^SghptFjYzYHYXx4+W5Mo6P8P5Qz(>niiaZ zZrLh8cgx}E3YbuHCbZ5tTB{@FNwTWq2Pqk~p30vlrQ=Dhab@@hF*?!ld3#W$-fCkv zpjcZHs}h%_*yHOI7Y=BA#mGU`TKqa%ZF682k`i!2aHL#XCF#=HDqGbJ`6W-(1}pff zGgFr`N9x$LjvmS$1m1pA@{~!zWecewNb|wuaBs5KJ59~$E_$%B8YVOwH4SD+C<6rr z)Fukb0_M&X}C>ySkd05H<5rHH;u7A&APWSH}qfLzy=?x z^WAl85I5DcT(~{lZpMl?vNP1x?Py}dk7tj+u;}o_e-5xX#(CLVN!ryx=CkI1{H6E& zjemW3;Zbw>!lQrw%q5nY9ug~Wo3D>UQfc5d}!bit!amdXK>zCWBAH8564__{? z{Q2s_qZck-q8aW3rT({BGLLn^@+#&Dg*K0$xX!m7ZV}RYc#E^VAN%_4zp>gr&L*Th zzr?BS7cM+*#KDp3}FLtPRJQ2c`4uIv=VY;NVL7-oO8(oM$-*VDpQ8_r!d_72J1$j)TU0oVDls zaRBKt+_^LQrB`0Lckd1ttTRt>jE|P*`NA|8kLMzUJ3Rb}!_!3OQWjgspFiGp7XRYT z`;H0j9^Em&^G8i{j5x>AanQErR-O+9cJIx5_kw7jGtW8q-uLbXJ3RcOJr3-8OQIqx@lKQI!;sRhg+M?;0JcJ z6o4ScEOaNU%W^i&00dK^aRx=4oIwZk+>HhsxHD29>ug9a0U&CdB+q zS{4oq#FT^?g?yBoq&04CV9O=W0HSUg;J`x6Kd3Nr6j4A8R9pz_WKP7PU>u+EG51t+ ze~gwqq0z6FpqzTvwhc0yilWOAgIMp%6a{bmt((;Nu=+Hy!Rc14u|r3O*`J9wg>#T3 z;2ZMJAWf8D$V#*wKS(tfsXVEaQ;>v2ZeG(K&1lIP6AT3{a6!+8=zZ{TSx;97R?AL& zWhsuppSM92L)Ni4ey2dK-7FXgwwiMggrxKuxT`Eit?GGH=ZQ;87L;5PR(RCT${)$B zYj)VWg0)52csR%@Ks5oB$UTHfb9!T9m#ZiA~0mR1)1b zni-;3?;Yvoa1pW4MSGO6`iw}TVoHcL@%UpsAV!nauw>B){2byjS~ zYlpmVS_)$i^a*0_qs-cI#p^)2M2!r-GAisaDZprML{xLBg>-<-ruvdN#Vi(OJ6ncP zg&gPD+>(#^ILbX+KG1)8lQS*JWG>x(pjDZ`vj=2#oXg3W zsT}86Y?mxZM!cuYMCMHme{>D>d+dWrLu%&ZHrs@D!hP}$n~v&q>}CXJbvjdsGe9Bh z3!^G3)fg(%RC>=^nzLFJ&3chzSM$zAXh=1ZgCf9U>2PT}4n1_=u*B?=$);MA3A^_5 zMYr_5hElDgk$D>Wce84&^K>i~-@Zv~Ly;^cNSCN4pv50O;&BAgr>aw0SUQ?H%a*i} zolU3NhQ;w@kGy)p-(KD6(jm;eK0L!`3HxmWt zR2~s0vtLgMHM1-r`H1J^lnV20>nL@lK_LPeQryyMD}5hz8*NZbL--3;y|2;gZIAo_kUkp z+xJh&&AL)A6XH z)V^MMrDK%!>0=I_xOJ^xx2CLs(;?s9^{wx49@$Cg7b`U8`?mY~x36?9^3LHmMe*f7 zy4k$Wz2$5}|FGOcOOyRUpnD@uD8q?$$0iQ`cF)0;>h*8S>+06WK}eeB~k?kZr_b*M?+b{0K#J&}Si zjP8((*+gB$g!OrjprdMN1wB*@Og1tXzziEX5dDOeJb^ zL{c3vr0(KrdK{vjBROMvaKjgws2IyIXtkqhTP^W=1YFV)MU~9HAxFUM%8Eq0~ z8zPEKA~zF3TFFmMY~0WoC;4hR8I7QJXs|9YNz+@Wcvj<>eo@0Pzpk7yqFwF|q$;3X zwQ|Ok276{Sw%U#Bt`3Ph9RO59T<#Xc!SO;fSxOM<@v^C*)|O z7zLX5(g5?Ms(J>r#t;W3Xzq!SY`JLeJQ$v@vMJ*_d~}j1V+pH88x}sSZCWU$IY-pw zouvcENGcgOpd+b_LN*6;*qm{wpkon3u1N(1K}*jBS)zMkxH3aGj8GzF3OeN&P*w|Mx)kP6PBLkkrBG@~2Zm?0ZPIeoa^A`~ z2?dozX7K5N>0Zi06_O07!K{=ya?g{4JR{ceBxPJv1hNoudX!F2Ovb6N9IZH*( zE9MDWsUBwX)S?$B?cXulVO5>GG({lcmGo@YtWrwRvr&nYv&yz)xa@N8QCKDJ(y{8r z`pn!-RKQwQlPNF#dZ1W>tUG3780D(C5~uc$e=y)$FeVU1NP?#e!yTwEev~hKK#?0y zsFrF9EPb(r=o-)m)+jta!C)1%@fjb^lQ&;^<6Yi(P;@qpafW|Nu%5I&u0%UZ-?ezN z3)jqfxteBNk|n@-7F)QQ-8<9(Gs}9=ib(aYR#b#9owL>}#>oCC+Io(KYmM<3O7l2=S;k}?T11lS5`!7|H!P}-_RlNj<@OD!d%O=js;?26?KZXhNJXR|hE zWyhys-e|oAW*5puMdh79#qKkYlPhubY6Y27+#`4@$gp^;ARu{DHATv58H#%R%{H?! zN_>#cywp0gb+&Y@>G*&u=M0L1&B&XaF3!v$QbuzVcB?;PSqECSEh4{PE}O-=UCC@4 zBycH0DudGhSR{mJ0hhOt=D$+Mm~fmDin;ZMCct6J2jf*a=boH767cYhs*|KJ`N3vAZw``tlx$W>&dSXw^?sAEsJtqO?lgofD3+8CP(^LRwCGHy z#gSPEmO5kYEwCIH(2qx%c|sA}S;2u$aRD>BOy-HlhB8q2w8qJ-nU2>a|#vdoPm-Hc1VW5c7_=$lqf`0zyii7$8;;ibWV1HS+OvqC1k37$TP3grDiQJ zO}Qz+!yv!RhP4~dv_5Z2;-(4sJgRkq*oBI;rl2v* z_z>smsOA=@<$*_KpIxT2bhB7f?Ms#lLg$?q|VlCdNYeU^`xoIe6^?=M+;fROI2%>flsGTN8m!x>z7fUDt6qF zBtsRZ!8RjPs-bL&el)Zy_*s~7hcyKqSO5*Q3>s55^|LaV#)lcZ%g3Qzx-exI`iNQz zjs;P`Sh`ALI}I1;R;3d=m_>B6g2vfVHz2(bSI~wPHO^PYpAw}ie5X;%zS0hJ`%#%t zMAHl>GvDs;X3^u%v_#FHKlYebVosY{-HLcp8|?SkEqa>&UDx(K?|IKZ{>NK1V}BJk zjrsQW+uuGkUnlMpApGqU*NIIj33kmPRV6vt@5MJHlAiMr2kaw7Gq&SEcg(ze`CA{| zC1s!MUm6BY+QDRRE5jJW=~6?~L7je4`@#M8W-RNyI?%e9R)^##yH48r)Tf3WxA%#2 z`zL?0TTAYxPkwS(H@tDJ03beWdDBJxeh zC4KQNH-o=<@3o^BAO6HAl)&|?-AUfE?}GMz+|v0+m(0cP$g1y4OL`sP$BerP2Tk)N z(dmpQbMtECz#MiQ4C`Ab9B5au&V+ien1ch|49?Bh?AT`A`|5cbqNMY@`Sl-E{2U?` zZ&^koc5?IrWkLJ9dh@DGV%wsp`g|Kt{}x88i}%_qS6*i~DxUYQy~yrfAX3Vr)pzsi z(WOg2|MPOe4wT0HnPS?9=S=g1;J$Y>8eO6)q!BwYFLYEr2dFJy2j9f~#eMk5!S;3H z69?B{y8OI6o*Yu})fc{b=Z(7q2UlLdKL?&Kplj@?Tf^YZP8wfJTmqcKtxnrm{gS{_ zP`eOK!}wGdoiR1RY#4*=!OFNj%;5Bc1(Q#K39d)5aVc15+vp5EG8zeEUM$uYE^;Jf zq6bh%TkfNShX{KJgJsV=#;4>bP107vSm2LOv7#OFTgGr*LP^slojP5;@twg1XHzdp+M4{k=#6(^n%UTA- z-<}kE*~QmC`H)AOBU3ENP+4R&VmiFs$57~y7_C(ySUHwiyf+?!%~*wq)q6}D(;MN$ z3n7@XnII*YqZ(r+LlvyTB4^`ThR9$zEr`=%oOPwkDz3Y*&bh+7w8_2B+Dw;a zS29$ZfLLHswjIdL*x^+5GsaXdLN%t4*R0#rUnUAi7D7pycMuX4TWfCm8 zEXHLuYYr-8Rkq3DiEtycg;6RPx94{nN@E-XC@Vvyw-z2yWJ9uGP>Q`CyWFHupsd=^ z`0%HAl2UXO{0bkUt+>0#Nw%LPxyuvRxRLW^6CiP}^r}ow_NrpyOf!IP`V3$NCT2}0 zVwb`zNOFnVMM+A6wPugl_)AW~&ueX|OVf5t2Sy1^CL3s&zep;RttJ!OusFz|JR}Ts zovB??P39~0X$^FN*(#1z!FC$>=8~mad56x!gGYp&j2wj**8xc!@t0hu8Iw!4QadP( z^)PF-T3k-%7CD)sMs!IWEk-+^Q@ycCIUA{TT4#CDg>n38U0CUK??vP$@!<6WM(`nZ zCiTdw9(OEnOq1(j>_Hi)gXk5MW+L2ZvTPSp%C*zlCw<}NY~^#_Tfa^URB1z`G$!!3 z2R?AoYm6TG62Cxk2x_jy4JctphaNLyDaNJAf^~Tq+g0Hf2TWVRV@?LVX*gACVb^1B zt{r*quJy*!Hau;?+s&B$uH2`zL|KwjQ+z=W!GYgMZGEvyr#e`tt$A^ktVO4^)tOp7 zaNBLcVY=%@)TUe{Tz*r}(VUGWLUp&Cca&Gv@sBm zWuhPTSRzI^uinMrg@$NFBx19?WL3 zYIr9iHGOO9F{eiAj&Jo z37e7oxH>bwc|{pAIc*5!k+}-~x&D@Xv)dWy8sXeXCuB;^PE82xV0GnmEzUS%sXPcP zcaXK^q9`j)#CM~08(OB;Djg-pzJjI89L;63$mWI^`nG^cs-t#MEf%>QEfzDoNLz0x zC%2&!pqtRaN`jVO*9%g!9tponvdL)K#Bb4vnyIU4;taEenH%NQQne{DQRB8vlG9a9 zHr8ZrHJ(>+kPw@G9guKE@1p21Iq8{b;Gmry)XSEZP)!_LQ&V0J{yM1DnutNo3$|EU z_pI789mPq}3-mQgngCbzRasNE2WeF~J1@EP8m8+;om*E3ePkF5nyjbz+xUKjS((!p z9dI%8XtT7f>Lq$~j~Fbd7$;MQ;zQB-a%>5NIxBh|R{3VS&e=&33S8q58YauC$!tC^ z94~Pdx*$AzK;V9e6Q1h9yol6Z!57W)AxP@mNbk5!g?19=?F)}~Ci`5aSql_(#Ps`H z2RVP(|7sQwbuoUR4;jOpdDsufTY-c}JCX4(N28k61!CiOKD@mBL&n9A3}f$J7jLw^ zxYa2=*UY^mh1+gFe)YxeOIrj=;OggS)IWZHeEElu@jATqm;*Mq-WMKzSlWJ__n?a> z?NFW4^Te$;Uz5+ruYUY0?^137w)cGw)ET)^bl0!F{}lc`w~cwvd+_*>d^>o)(K$QP zq>RTdZMSc3Uu(B*+xe2gFLS9))cGYb$q*OigZaqz%{Sk?bm_N#YkTJtpTIqoS{JZ? z>crn&ggBu7cNs7z99)i?v}iq=Z*0HujV>G!-{evoaX>E;Q+|JMK72>+OWWVNWg-W$ zcH}oe^VH2>UN21^%|L-Yb@OY#{(pSXn4d5q3Adyn`;m3jj71VYF`qR^#Eslg-26!L z0`Cg@PDMdXGUrVfGWs8fluW$`+!}TFUv4EHzxnzTZ$8QKyc|Fb{K3&zc)~rp$a_I_ z^H40y?7HssdcL`SeR30;Ye)CK{N?UOuk1Io-_(6e926GMh?2(a-Mdd*A&25%HQtHx z2(NtmBb-R~=Igh9|L=cA99+My6Uweoi)uLMau8z}IAAL{aOcIlZ{57P6)z_H&F%J; zSFV}&!-39-lE&=Kn{e>1cfAX5M=$9`Cpi2<`-O+myyo;V`)bz8b}j6Be3QWSZ|7z6e2n4no3C=lS!^F$<2_%-RL%%l zYSJH+@cezoUNS!yagROyC1xPvJxsB*g*?LnO7>hR)^jy*@Z=L8rs6AL(A6*E8o0!Kx#nOgEi5g?HLj0Bf9AQJC{&&9)h#rx6~2aMqzL-80)^vFT+x%;rj?>ez}wbLQvI0)0m5EDY9C4{|*(Q_2rON=^+&&EeTQFd*jd-h0$ zIJQ#Q%8#$%55Yx;)-tqOO-P_jx*T^LyDrGdKn1r#^72>3Iw*9-*+Is7Vq$#7N4pwx z|0x8L+F+@pR)|wj;NiNWvKocP=yMJ8@rd zEEao>R|P~&1evvU>dc~8@q(t#A+Du(cIAeg>_yu4KZQUHb1U2_N|>xcu?3Cb8q{`& zf6*5Fz#vrnkhfq`+QCY>M>6y@M2B_Yx{ZmEB(iZVmB?&r7TqGY=)1zQ(iYab79mSA z_Q1fRBv4pHb~PxHq4l<=rmsYeIVLCn7_szVq2dp-F32ZLSqf({YPkOs_hM3bQ|nrz zvEr3TTr(kq=<8S5Qb(wW*Rz9BtJUU-hvyd6R9{kmsde%s_6RLcHf+V$%Io#QgJuDx zOf&-gs^Cpw_Jx^AEx&_XF&`m+ONk(9A6J6Ms^9RGjrQI+&+Hj?x?7SejazZCbJZAU zr;bP(qj69FH|7i=4)@ah0sbm%#C`_Xx-Y8C#-4rQpqxoP1aY%4;k)PwfL#H3?!e3- ztZf2C7*g&nML6a(BG{$^HvAp{W+u4FB0xzD9X$@>>+Em$WRnt0t<$PXs%pJ%kuh7k zR7}0)HJ?hG4|bddGn6Y;y5SA|Fr${=A-r;dyE}3*8BX6Kii9Mj^_J z#w4BD^k$r0=X=xT(}~2S_|3WwJ48f$Byie=?Vi0)FfM)~yQk4gnm{oQz=X3E7fuL1 zgwe#xnL0dOjE-wb!8`IM{iHx8$OTyO+=1(y44_!}=y4bhEk?PL9yOS~Q-=>+k^v;^p z6wQPcyaJ3yUEN~Rl7>Yl$#qQJSOzkR0vC~$!jf))BH9z?a=}Sv>0qsar>>>#VB};{ zdX3CoP$7ve&tIuXjN^}l8U1mVV$vsypWBtUe8e@>2Siz7 z8>&fIK_JF6z>oy)SuHYtX7pN-0J-z%^hsFsE|uG~j-?`rS1}F60Kk}_dT= zIO zacYaPQyEZhD`Mr;TgQ{vJ-V!VxgE&DoMsatL|zNd4WrCWK<27d%ypmi5 z@CVR|N0T;gl#a7?r9NljH>|^g8E*_npuucwY!PD;{G}0D5(2p!fpOsmHTg|eP3r`{R|(73c;qNL(ikSI83&NITx7B|(?%g?ETPG* zi?t%G(9NZIlhtfJXU@YNuxe*$B=x~m@7KW`syczVqwhm0XtcI#!yOq*9iM7hs6q2G zfmeqju8Ouz3X?QBYd%D6a&NK{q@CbSp~GxUAfhqay9G;n$-?HXGX`(T>n!zCPQzKb%+#D-N+V*$O`4l-Y^e%vO)@sHDj25YQtpEJ zn!wQ5@DgP#>11#agjoeHoC>p9$xKMy)K1cVO$(PPQ0+z-s)Li2JS&A+>n$2d3pMO% zmQ%OW16uin#W`D!$GGcho{}_k102?idptdWn1&GMX38@3EChd$Ehn>#gJrUY^}@+A zEmzelFX$buEA$>R57s5W^Q6K|Rzq_$3cg;I4cD*8 z-7JzK;TUc{wG&EsR2AMWvxP(aW)1|s{xyfg*3+_qN0Y=oFN&Kcv=6g-L%C!qa1d{u zdb4UMt`S1)%J^iN%xW6&JmtXc1?@?0{O4IVqk+L4#UM3d@tHXdOb%cc7RlE^W$Uy) zKrlY2)qODERC~;Qn1#t?4>WV~kS-@-ZCK@_JcBVI=(z_>j!!||ywI8E_6N*E z)^JAc2iS~Ystq8m$re^oDd)sHsW0yI-eEHdDS)Vw(cI`6SeR7}tu3hWwS_Amf zm$uvZd*AkmklQ=A{(N=k){U=k-+Jqgoyh#tzw_DAum8)Z{?&iG zXFmORo;iy*<{U~w-t?whcg#=Be#P>nAXe%*w%0i0h*J8*C!ToX$FKePwa*-V=14b< zzWCy6jYxm{w_m*~^Up@yzH;klZ+-L1E3e4S%Gcd{Z?S&G*|E<(Cp}c|AbMl_$!@i8 zTWk4s?Un&7ZqJ z2Lm_Wbbn01cYoF;-oanu4%|Q_bL|`cPEc08e-D<){u7@LsYaIaf$E4{h*%uL?}FcT zM7xBafK9iq?Ruu2?=dPI+xX&O-*wB25ezujppeS|I1w6@JH1MD9G0CrHke zoInc!%rFc`xy)>QlA-LznVkIP3ynGW6GSznHI_V)lLS@;EEXym{5I{XUPK?!E9q%l zbnf#i1*uZ8(DE!}+(wK<;VN_8s;Yc7)Kfk>$^x4)Zl_h-q{HPV7)l1fO@k)+BqVaj z0*z*HGWKC8N*iL6m{1gkLAUWcgxI|z9)O6ILR)NN{Q%8FGD4EU_#mKA_ed zUG8jikNDvcOkS(#sOUPMv(V+TdXlWo+SF_-<}yta5QIprjiY{=gof;z^-u+cC2EM! znkl{##2c0dYgX%8;~GT_*L9>s-l_|^PXO^qIk!w^k~|qp5O^i0juvaS!c9i4bznXB z%@ETV5zM58Hw~+ac$BGYNEd0H7_45xsV;#=YQ?&+u#N^Wvl=N)RX?!u5ll)S&EXLS zi*e))7o%_T$*A7N(xJ#mmx3Fm&_er zCvCN7h8H*f%`qfnE1Qm=^4^e>1dzSP-(zCvf$Y|HA+c|gHB{Pe>A-OY@`%Zx(V`2< z6|ThG1&U8S&H=@{r0MX^5J`p0b11`-z?40StzEJznu08=^@~R5<<9YMAyHyo3?#?0 zc+#|^Mx;^jl=R*jH6J=XzmE8`56y3=*DYuybciK&ysYy=%Z{1x?6hUN&er8DqY4Ne zH$03db8R1>>4n0_LxXEO&(O^s`!bX>C1PVp;^hUSMob7H6Mh#;9L&5RvUAjv?s1{2 z;`CbS9c_7LMc@!9Q-cf`X2vN1lM7xp?aPLx14rI?{W!IDwBS}7h(l0?GcU*#m@jqD zvtAKh0(%~4VjQ3#C9|uHRSg&^tVLUuU@*6V?yhVUF2uYjJXI?P2-Qo9-{a&y>?OzG zHhmN_MB16OE!<}yHj|1sUP=@&qhdB%adxzWS>u=|BH>kL)=8Txw(g(C7#T>KgzdL6 zofuQY4Ob0~u|h3CQu{2eYlrC*#}*IYDE2)Fa?iMTj!ek9A-DQ37YD@{W$vPyG|Vv6 z*|JEfM(#v&DqVIj#2MGjI4)00jYHWWv%EeH(JZM36BfY+zA!fEj;P=as9?^(O$v^e z?e^`caa&?)iSPqjcLX2z(PC8Pv2Jc31D?G3w?H=CRIhk2kmb@MjF} z%y{yP495qL*Iv^d9AEkp>s}IjpT2&*e4=w_xUW1sVwc=M_y^zm7K8Y2vYjv4zV*^e zFKvJDk?urR_SGE@F@5C^xeN8yj}!WB;g$sks+{{%yA)e00W^JUZ%Rs<&P|$^X&OT}qS+<$2{{G$#8%a{mxL#Si_EF>h{D z^WVf%Z;$@q=;+TzpZXN)$XB^QG)idgH*}lr_3OIyR$9G^;QICFn?9mb#y0M#WiR6n zR+5{X7xON+0}FDC1D)X`emgpGuq9>5buoEDa{0+O?p{<%c`J*3@U z>dTyF`_^5`2eFZfkf;TXKpM%mFTC)=K;D~^UH9P`o!pLtruhyW?7TZeE4p+kCd-40 z95{#x4RyPl>UXxE-Cs?DfA*cj$oEB>-@~^a`S5v^55M&Aaj~7}e;Ri#2M-YbckVQI z?)&!XjbG5tj#In_2!Vz^&)ZBOD( zNC(?}Vj8^vKVqUZ*mF7*I(4=KNDarXf#MkP4lR6ABXs8A5~_(E$iPWQRbkY!o^&n{ zM2rUX9dT&8&Z`t*54-jO7tOqm;@1w2sE@NdGI->sZ`1HAy4ekE3^Y zWze1!H;beFkxA5AcrfJH<0As`37V0&@cYzlR4ctNYVwB=Am3{r)lig?+?= z{|kryD+pLQNvi*jVQ&8OvnhUheiru~Fh6wGPlc)V6^UqRd`e4DeG>exLPTdWYr5H+j2{%nxF@xWPvh$(wKOWwI8@kyd* z06X|}1bu9A9ZVRnN2KM+e(Z2OE9dYihTiKk~)2#HMP8*r$ zLZpySta*h$#_ZWiF2b&Vk2=ptc961nEo%pP#=09~-?QCEJb*ixFcH~$G8>0N+6Gk0 z@!XJfH3sNx0lkr6QrOru=x`TMQywQ&1NDQOypuuHli*jbm2D45gT^9=$w-CT8I21x zpW|qh^d=9<;1uVO==CM42Wj{MdqT0vb1_)z<2 z?~&+M*ec9|%PBLcFG9=v1f)5|OD24VA@Dw_4JAg0>SZ3g zqwmS1Z9BU4sE+)?Y+7}fFiSD}JkS;_VjR0B=B%N1Cu`ml?HdEn9`hJ3KG??5MS|kL z;=;WTvls|`GMX7H-?riB`msUWY%J^v#F*AIT9cc1SdK44Q>aTpc#055kY~!uxJ;@$ znz;9&Ra+9C{op5l0doFP*zkIuf*{u#0U$$vB0|u!jn6`O_7q1)9|xYj^VkG+3PSJ7 zirx}voe??s^!Q_=$A_%xP`JHpm=UtHGh?}6-8Vbmlc)TtJ2p|+h-{lC>3oNfC$u|w z+QV>l2cct#NKgAgcOrhryzfkOc%qx@B?dUL;aAtSu`N3^)W*=lV#iTxygH_~9ReI@ zBYw(+XZvWzx4MOP)Jn+$dbL4u0|(gNF?gn}gF;nK&*LJEjvZI%5y5b-MZ||{h1ugV zV@tSwyQAATh23Ru@bB>1&i{Haedq0^&LX);$(kNy!{WW(WLwhw{PypH!6NO z34wLNGcbhQ_jsrH{qUVTeEmN7e|SEgoWH{m;p=VsJru7;rRk!%(wm>wKxhx3OU}d7 z7Z7rBZitI9=DmnSpNvk^U;XEQ^RxdobRYZd|MvM^b3f=nw~s#wx$iT?`1bgwC)qdm zLk|A?cs_Y&Q4#Y%_|^DlrO_1*PMc?8m5nUYF+{nExXAvqogY`}|fh=v2M15W(}Vffi-?^y;5RWS+)W#@e#I*oCJiNYL1 ziH)#{HQqSvo*!df0@c`nMtBvY=U4Cx#yV$=lN}IuDLyvDi1==UfY>@@>yY{c7r%&& zsi00OM??@!{Oe*z@TXNbq|6b$jDPf1Uzwc9x<64#^|!?oPfadvTB2$RAw7yt38G=# z+lDm8#J=rVeoD!JQNo_*00}YZZyy}FiUHG@MV#c+DYs4xVy^ds*gZEIzVuca7KR!x z{muo~VFMW`jtR7YUrtKg0oD5vZJHCj4ZN7tLpUK1-2_E9&Zpi3e(Wsg6yeb-^}H#o z3FGa|72dldDO2K(3MzR*5llvo&m8XpZ$sB+@>q++p@fMacT@00&)aF+sW*As$lLg& z<*DP69j54I5_e?RtW(YsL#a3p_3Wrn?qS43PiEAR*qCAv=|X~DY()x{(>M!Na6!ta2(UsdIy`nY}kC_N>NRau)RXD7vC4{$azjjPMt|m zsBlaqu;rkzPWxNPwezLP6XL?ojtKsCp?{4)B^^3M9(o}HREVX;vt@b!{fc0m0VshW za|g&rs=NfX0I^7;W=9O!slbjpz5hOyE||l!#@h0fO)XyTH5f&rGEokQSS66v>}PPC zrv(kgTeCmB3*UwEBg@oFJ({kPj2KG|D<%#`9Xldajb+@QW2la%d%sKGxf6iEq#U$H zx4Uq9vCI^E1h@`Z^rMy;17nFw%VCm{x#28JqHa7}K^ABsXnUNt!F6DoKT$z;FdK2a_;?H{a{1Vnp5!MwKbj+y4R5%0 z5ZB~=#npYe=lqIkyY$@dHTB*~8J#zXZ82pE*R(oAcvA-*0?j^zm;}2NV35L(rwSy} z69=zf2V)e|Q>>dLQYP~0HW#eA<|72JBhhnYHHV0-4mgp1;S;pjIj^8JS(`M5U@=O% zb(62!Nzx?Vx2SlxrIKl>WSL%sK*GL-#3MB{i`aDP13%|PyyZ=wj;7f%850msdyi;%vb9TwP~mTug-i-Ax0Rf6Yw^t zc2yTGJ}WRI4)l=zzqX5LPe~y5SW}C6t|JZ>VAVCN?w~-ADQAX{D&tu6@xp>nrzJjo z&jU@3o#J#XjbEf(9Y9~E2_IDLRSIKT0?~~isRM2$HXhrQ2Ezq`j;Ho5(7ULE(GE1u zE!cD+gN5tBz2AiKd;!O!S?0;3Ta{yo|6lgrKSq+|y7P<7j2u;s+UhKNbR>LhGE%p9 z8pubp?d8fVUN0wd_GE}SpE=aAK^#qb`z&J4wD%-hrexXJA2C^3b5$1Xt2XF`*Vai{ zwALnCGG}#I*gS$7X6@LbEG@7CC}RFFh^0wETxbqZ3(Mh(%Mr_;Z)89xuNN;~y!esv;zdNV-pfJC%26D>ORxiDY%)xy%LPTy->naPP33BlbG1Rmei~=LrSs3JOX2faN zFjR784%(EEh!$oje$w#`x`iq>HvuklA_OjjQZF75n}8Kmp{h8#($LZuVJmGWbrjSy zPLq;@|9uT-=cPsph{M)V=)#jVjkA>}%znhFwMG}w*M>))K>SB+}l z=ZHrt&)o+feDGNHx!zP<{p}M+_MiUXYA@OQvva#!pV!IsJinQn_$eU}m{(5U^Pk9; z;oJjf&iijkJ^b)1*FxY%aE0GzrkuKt`;~w1fp6c4Ck)QSC{9xEeP9<7px_ld;qD9D~q z!PZmoF}9HR6kK@!-&*~x)ggy4$en%WJ6yQ%Bu4;xxOeTGR&w*$>dfBi-1F~PefG1T zU43@7^PQ`&9^QEA#!G#PtTq1n^}2ri^Z(vI(~aIrtJ4SJ2TpSueYH}X+S|LnH+r8j z|MJ$q^EZTX_uTF|*)aaGqb&wh4i=hp6# z=_!ckC7@t+{jh#w^}~Oct^1$8X0DlAx3;!K!LIAK&u?$Pu+2DN&ONksRv6Fi{z$YR zc;JDv=CXMtc_!#Q!XsQtgl!**{pm?gAKKx0xfPo6XdD%*W+s4<*j`ngSnhOvQF_8^FYM#*R$Vla4_n2FT5aob;HY&>0k(Z z|2OAhVx^kZ|F(PQZ5GEZ(eO2@)vfKV(+_i$1M{Vu-B(tI&vRWc#q!!RwgrV}|Lsrx zAo;{^&>bE9$us6$*P}kW{SL+VbtV@*_H`(@@L=|6jNLrmkb-MpyY{t}iHt5Dd#tZh zCAx3^SDw600hvGeT%>@`b)@*)kn+8;dG7kP=M;PT%E=UOKl}Exr*}{9UNJT%{hXL6 z!xZ4f?|bq4dXJu@B44$x&29JF@9kqx;=2t`tM+SOEEFfHuK&Y$>wvC??_&lG4I2tp z7kUbAiGrLFD_Ya>EfS4^=i_uKfQocwS=#ai-UHA zQgJnadVCIBMy~#PG1vRC`ji2G8pHHZ4!udDrKi^O`#%NUhKK-f@aS_^s_Ym-xHdnW zq4%A{NYHHqXyDawY>HzS4yfQiC`gQPxcTu~j2Xmx2NPl-An+Pd{2E%0H#QZStgkKx z$mzf2Dbs0S=xNYXPywl0bHPA`ar8QMgbxxuZBi4anF&*%m`HOTQ#cV54fcHPT$fQ` z5j5HgY@OayMZmEwEU?EM0d)BX|zCP#1U0# zG^5blSh3Yhrje<#AYSn2ocyI*C#VSW#FKrFQ`ul()tJVo0EGk-29B8`0;)oC&hj6( z1#qbnQo@-*ah%`bSNn)9ig1UI0fgB)hO4PUTACIHB5)ur7Hy@L(PYRCq)ziLYVKOw z4P8pvxoXfmwHl7P8b9QlE(6DO&J-y(RHfEth)iS=E5}iB&RDgU!sb=r2dvb&&S(nuoxt~MOa}VXr-7)1dHw$b&AUt6)smYwB9Y9u1@9CIL(g2vP z)&b77vGgX{@|3;_6H_^rT3iJMMQZ4HJkw63F*)yoqn`}& zAr;w~4s8yp%Y$|hinI$9wFH6cFdndIj0II(nBp_9 zR!o62_9q47y>}TSUWF*^Bi|`WI?$(l)efel(`|1lUu^O&AJlF>P1_+i@p%edF>RNi zWI`}jJOmDz(;J_1+W_HNl0s_m!-!XAIUg+R1WsFT zN>AE_h#d16`UAQW7nQ_IE~ZJ_+2z8*5u~OusWX2tlhm503Dp$$N)%lOYSJgmfmyn| z9v--)%Ln7}j0B<(j4+C4zpF`sG^T2nJCd>TR;I|p!@QE13UwJobI?0-OJeMd>l^fm z1J7M^lxdMq16Pd?7F=SN28a#f1mEYTq;m-KWjp33z)8pcfeCV+H);or`rL^DAS-D; zv@EZ|lxb#YNXu@Rr9jbWD%c|u#-q|qTt|PPy$lBVqVsMbvhvzh48%26?Tlk+@iBWO zaSBy?hB}AC%viq;uxXZQn}#Qlah!^7kWd{t54w~BGBhpqK4b;JB=Cu^S#g`A?&;HV zpknmiGW6_mGMY(7?2P4Bjz!zmqssB3=2L!%m8^0t8E3p?)G6c06kHQl9a;IUXKD<+ zp?P$;=+2^+29?H3DLe$u9brhzeY;vl_(~xBVFqo62tJ(-xP+2h9r@_I+Q{5lt%D@o zjtK8z6*YW7*0e9yZ(7sNC$n5%2AgK|6qv>Gm9=0Csqx;CZ$=X+Sd7Sw?>cV+3tpp9 z4MKu)vz}(qMJ?CljHjisyrwD}PaCBXb*Dgs zuxw84N5`>D{19<6Cltl!gIi-K{OY z!9(cR+}HjCMSe~q>*`+f$J?uSJRYawh#kAvuEohYF0Ow&`rYJrlZzKu@!QeggzPm1 zl6H?N&|&Ex{n2lpVz#|6_eIijpJDd+;~$GOKtZ%0-~DMQ5DQn|T>YVfUfq346x_QF z;UeJC{o52EQAY}19QPCmhbZ{}kJ-Alb?e@HfAcpvtgI>(n7P2MQNA9Ih!qsN8-WGk$@WbtZQ8QCKoh5 z`sgkce8>D-^fxHDm)!W?`Nh?}8w!4Y1&t!%Da?j~uYXk(5NJe!Im(gFd#T+#8VA|S zCQ9W4!sG1%mx0pc@>m8Z{Kw=skC@L8CwcxO5yL6u{LgS#0@8f;DTCZkBMGMcUw{dL?5a;QYvCHhO z_5y)2KiU4mPxh|<`6Gv)`>b5&l*Q5NXhXr3FXXwxkNVze%rAaCQc%6;ese#4hAx8< z1v|U%e5WX&OW->^>?uf+AB+^NzHyH_?cVAG%Am)%k=}d%ZE0TL13Nl8bLP61qK?h# z+{@>pM*~MRH-7hb<2S?pf>wI@o@ZQt^bG!#(hx2dv)3(~{DG<-@rognlvDeD@bcQK4W zPZq!-xL_cAy``4a%CCtyn4$OJtub&tb`@s3M6ONW`NT5Mythcz=)COM{E%H?Y=lW& z!~kHfT1Wc{h-jmAnAS1aVBF9dCzWng);oCNh!ugElg!8;+R5;|>7s}SzCY`LGJVe+iL*TXjzpl-TuA+!s+BC2*}>I#(H=zswr zu^xyJEW(ssOdHqR)F2@0glTbuPUYh#W0i#x#~Rdq3e+;qGnOkx_2}2*vvP{L8P~3z z8wTTDSA5Jj4z^=s!ng`BFr;HXr%aRa89CxdWRk4^=#=GU8uMie-fgN7^Z?K%yI&TjOcX^buewjpd9E=j*0*S&2YR_M%a~Ksk#e(itV_}9nKV+_>tUGXV7ATzEpE(7t&i7$mAOT&+PJf171uj_TZc%=H&w;E2w zYxMy0dKi`w!+YvMguJpz^4P^BOUzK0l8;|hvYiPey(@jBjA;ow9LF$K*D8}p{~ z8~f6EGkWcp!cN4qiQ={KCo!N)e;tVLjiIODU(DzC`cl~UiZ|waL42?H%Rk$#S^s)p z3j25e-uH?}aQ)}SupvNnM7NVm0};l?r`oGCZs2&!^LDm)*YSNc3XDXs@mA_$ohHd* zqF<%)ih|gnUmv=82Gj87*K@t8sxJW1ULYjEcug3CSw;^J8~W)$ z+*cO_75_S-Ffk3ek~4qt1+oFFu^z05!SMM3Yp5|H~1xa$T;bl zI1>e?q>-&6I0UI2wqcsSBF3g;TDCMvFu}4c-|u!4 zNK08rxanO=BU6pktSrUN5_)J1a}*^qzaz`e#V})-5>07Z%+{$S^i9(0^4CCKW7=H1 zS23mDYV1wUO~)HQ26(as8a0E@YT(3bLZF z7f7t84BjW9n3gm-goZ z8}Jz}@~+b5lv-V;ovMZa%sjSJi0?;+#I&uGMm0#B5tcTz|xQM+7TG4>rrXCbp;6A!#~NHT)S9+R)2pNN&K1OE6ai`O?!f7{J(O2nA)G6qv(!? zYV$b6O)#+|md%-oPuEu$OUWUy*{?;XG!86I_zWE)l}QKa3|AKqTjkAqNL~but#PMsFvBqSeh~&0I@&l)kX+hTFBqhgS2cx9)(`JV3qqPrGB&KwW8GCSNWVmLtpvgjtB&$&P zFdcVNfE6&tCBD=Ca>n$O324Wssu*4ll8UP2?&+zxPY?*yNU4m$j35?L2qC7{vDg8J zP>0H*1&)@qoGmq(olnfc^gwLD!163O&3g^Jf%P>{Tw`-EG6Alp4BY7d=Yd{r%94+8 z!JyV<)E!G&de{)lPB$eTsi|G6%Xlx2c45liPUnWGh8Jcwov^@EOc<@h?0{&%gOriR zsWrspe2k3GywP^Z0aaDNAJ|D=)UD@zTRKFJ(xer7K1Mv64;=`Nd>DBeI~ZzKLBJHI zIr|BmH3K*0Xpu${K0AievS@jB+mmU1Fh$gzqt-Rvk$}SWT_WHqJwB5cnKaA+VYCS2 zLCIkVnmjyq4)}RfPve#iZD#Q%<;P}u)jFtTX2F5l8){<`Qo-;+Sc__QYMUHFLmFBF z!<*Ln#tJzD1t5R1hK}t`e64q`IdAwM?f3SnePwjgM1A9>s7I_Xl~FSZZyNKa{gY5t z&o7b#e~B3Fs+I0UwpRS5Tin~*!VtOkZ*OsHecJDcGVC-~I00-32rfyXQXiDJa;zijL>Os6&nY zSEOwA#ztERqIRecKf)(yR2Vn3H}{2?cg-GKLG?wot7nwr{XjgAL2I*zS_5vPdBSKf zEqb<9ww-OG`8a#MSNXgm1<&e%$O2-!ZbO06Z77g}M1C1jAoCJN+N-S{X;FKs&P4r} zv{$0w)eHQ++J7PHHU-=hP0dK-hqgvaCuzZW^mlOo5ft#9t}gq;d;BM>_caUqo*z#u zUaGe8>A#(PC9!kCQ9KJk!e+zSbmbidWzvlHGUUEQNQ^M|MfBfa1=(FP{kA4#6F zIeoH?TENTcFEO40x3z)$_!|CKdHF;m;wbFl>C@be&bH-i*UzK>yJ9mSLbf+u501U)uW>apG$UMc;Wfy&+VZ5CdC)O=zYwN z$JUvxGap`k_`~9f!tS5|1~aHf3bs#BU@n+5+b_KLy`n%@y?@Dn$={}6r`Y-IwQF5> zn}Szg{n|a(+|JH@_lW}GeC3tpQn|_eOFy_`dpCXMV<_X-3cGECpZ%^fXmvN$Put+; z@G~xkdm6ghz;=AbARegoqR~#-x4!kv8F^MKbo%WPUvtCVoijV|J==S;z1v?a6T#6LH15cV;x4LdaLBLNApI&L?hhYTEr^6Nqqnt87kiQ zsDO?ru}!&gIr)IN!vuU5!j*xsK}7P}p=T+TGV}b_hRs|tmqx&%@z|`LZj%*V%_VN` z0En-B!KSXotDx5!rR$5hfiDCUA`gfx@l^a==a6+PsKdwfFhU6uP~&9Ba`2iYN#c?+ zAxLG>Uq4>ZSStcGWziI=Kk3$QnKs4|vxbhR`$le5LV2rTnR#Eaqt4Ao6wRyLHkeqe z;#P-@q+N-vS-PHet%@-0Ou=!biT9NhVN(*ZR!QDW7O1&27+17)Ye~~Mh@cSO$fUMr zIR!__lnTQH0_s^yaFX*W5q~@_TfsmIc`}LQ2bv&ukiT1VDak#6|#TF`F<{GIKQ66e6}s0!d)9fgc1J<4FNQp``@O?BRlPQ+VrmzyZsl! zOiDDrriw0cWZ){oDrXi0j@1>5YV25vHb}a~BqzprVbBC<$@=O%VRbk-(*%WK0swQX z=wMp7-trei6Rf@lqeBqlNBpfrdJ7Rp4g@#|8#%*YV*O~U6(}F66&Eo{<(-V&Yx=Rt z-%;L_nq{$=8njLo3A2f6OzLafgxPR898C}`Tt|5nr)Q!{bYe_nC?vbjvaHChDv4d@ zR5^l0TBP0s-Ke541t`X~qcbqbGMESTskOe{;{TuY7d zJ*NDi>_#c)!YZo3r8?jUGqMDbYUxuGIz|D;1*Jhj-34MoUyGVZ%cRZ-yfq6-Ha75s zFs9X}$s8dpzOd%sVvEgMmWccAVhUOt5OkHaMH=^{iy|@&KjqAHJ**w*oOekvth})$ z0%w?t`}De#CUh=(^>m_-lJbWMdSJxX?_!|V_tB&Zpr=(iBzED!gsJsSj1S6yZQWT6 zj%;D~EHZcHnZ6DXv8skmhU{W&LWU|`r$jMMg=8N$dYVBf$5W@-I+7gdh>^6`3^R=Z zsJe5Pk|SqA)&IOJ{Ltm>sh>N6iMin*<#ka~Q!pyhM`34RLRv}&B&PDUZoygIB<+Z6 z)x-oD*Rc>lJ<7&GQX>}(x@O*rS6wWuK2a@`INF}-BI)prl4(|sCY+^IJ6teY9V98k zZX%RCWRIjo!%<@eA=Q(3I788$4#&lC9@@@%6rmJl6y|9?tcJ60 zT+_P|D^dEQ=N%5xx|mKE8b@hAb9Ut>@r@v6fUPl(7@v%WeA1e;#=3baHl#&6ow0^I zOsdH&(bj;JHk!_7sIiA*oJo2>Q3h2#EDuQ0)pn}7EfcF)Dldt6W^lTDXg-|6@ zg^WAk5j~V>Ue~tH+hAO1!OY3nVlW()!DOuT4ws}bbB4w+bb~M~yGds7J>u{df4&*OU&U-nW+UG*shCh7Y0S}IrX+c)Kf>bw%2-X|vn z@(BN?^HjgwGG}n<$JKYq-z3pf{9U`Kk5u>4uV9eB*#D}z_$u!E`1m&;zxbKAeC92pT;Y)d=IQU+{pbk_Vv7II9`pUP#++>#uv6<@>aElI!_l>) zYr97mR~KKo822Oo{lEY9uWv})H$Su5-~XAP>HVj+-+k^BCh*~VH7URwR*)xV0Yw!uIJ|4*vX-akA=ld5v&F9~N~k}xPD1qg3YV9d)s+}AOu z3<6S?rlLT5fH(Mdci)W(N~i5BHJ5ze3JJ7!rmb{GUhyBwarJ2gx&pu4VMWWvefQX|L{X3|9;v)C1y4^9RX) zBgiPFPs}NnDe0;$dw1K2A^rIO_>{?kSGdxBBl#!TnC)FY2_|!R;Z;fR=4fZ%_f{Y|UO!(`qZKSv^)8N#_yL>bvEiUv)2cFYAlvdq;cQ3cp@y zePv)Ce({ObONTEVa#TAC$yyIkJQT?4DUkGjCk0{|6twNp$JRS)w_kYS%Hb8(gf8iu!KoI~-Hao+J(iLV5E8+IcqMi8$X zXl%=fYf3}6;LRX6#%EqwnInRM*9*2x3?qa$WDIAjZ>2dE{yr>?$s;h2wZ}sle<^>) z;d(>EzCPmm@<7VkR2#>!4YhA%{A(iIYeJ3#UMFh0jua8yhSnH(*W{gezlME1t2hxa zcX}7lD5mx?w13_OpkZfYq#5bO^-V~$Jx@rZ7Sj>;9A)HAW( zc(;ZbMl$5VG{V&vvua6X@8&a^l_^6rEkNSTz~f*Hqk?=%j&X@6Vv3?p%Y0x>N3W6w zHj?E<0dS*^ho{lSP^QAhibf1mRavcS;kX%5RtLC?VJSW+jDIoUdp|UI4%f+VLu=!3 zZ;%XQMGrLL(_icl$3yN0?AV4_sA=7C051sK>T;3#*pe%r6c5(+bwVZ>j(SF;iXns4 zqy+ZlMzZ9)%c#aN^YV6hw|4fNqi-G?p^GSwL+)@ugTG1IgA~Cm%R7ZdRjLthA$8b1K77TcQ2jJ^^PJ*l} zi|dAB(pCw)9YtGZaQN6Js>Uc&JE*OqbMsiYhgh8{@NN^)+g4%yc5-x|>|x%FHSlCz z-fYU@il_y=GwEOW{(=L4!GXWvz+Z6SUvv&=&j+hjtd{DH>f?lhr%8A-ql9Mam$0a3 zdD9TGc_HP-b>0NP`d6ekDIkq@nevxSneCwv(F`T9p30?eX!kHq@2j-q2d1n}6Yyz9 z=y+Qxt|f+4n3_xQl?$^D<7iHZ z{`DLFZdW1^8danG>tZhK*fh?Z^^54cV)fq~nkacj}GbWZ|7k=tKpJqHwXp<16P`k0p1M zEWY+5-+J_52F*(aw2X^SlVc$nq#^D7p||?zay_%J9ii1a22RYQ(+4c2uLYgpK!KYN z^L|x0h6FSm!4o&(X3LRDoJq$a&LP(`d8IVd(pdvosZy8DI2_if z;Y48_95S}kmZ*w9c%Xu`5_Le(RirOUN3RQsF#*!qc?X0gnNo^)u;9#%Z_yDruPH5n z(L{R=j1*9;`d7e*WuMRs!s&tO;!_Xw5133_+)12{cf8fiYuCwIyh!vOzN>Q>NPObOoMzf5wFtb z(d&dB6XMg;2&1drWE59LXoO@yQlvU;J5n|_OlcEIn1`k+(R!#iaNiMag-BF}joLt} zjqfrIr1e8WL#rQT9eR+)HN(E?blB5GtK{8T^^o41asw9Y?_YjNVm5|AjpoTo{#4b$Wve{)v(3B8rj9)?W zfcB+Rh=z#LfQYk^IlD4DJ0Fyp%Y2x3qrnvA2@S=M0&<(K4TBG~F+$y}$o+JX&vXq> znsZ++s?Ty%52jh(vJ$Wi!M5hWgn&-1Qqu}yF>=bNuSIsm>Xu@8jK$)YvU;v<(AUU#C;;oI=*Y`2<8Jg? zP`aKqYczPaY0<%vgvuCF5<*mONn*P8~e%7k)$fo z%@>{lDufb1>vh#n+%>rrodAKY~0fK?5!{}#Zwupo@8R+!rk*b(b+d3!)8 z_vk=}>WO=9Y1Z{JRsnuhatqudX>kk6rdDSy4vK|zhn^*((m0h46=*s`XV+S`rqV7d zv3S5$vb8ImE{{^B&;n$pb6P>ydpO=_hm2}nai9^C+iXkr=-_e@RF5JV_ikStObbq= z9vpPdqS4o6go9s?3a#O2I&ZpZGMF{!w&P1yks5TUoD|^o5El-J6l+Xby3s7qap5lj zIky?3g15y%)b0U5T9`9cqcz5js=;{B&E3F;G&mAbjoLY^oiPIw%4QDUGEl7p&k*Eh zF_l>`8j(R95Ncd+TI=R;$M$uqHluyQ*Z%!e`_kpbC_*v&ietPt=8{~csaf3<3l&weH%rUZWu2t(&*F#plz1%wqfM3PxeZo;#<;OT_92m3qr;UAv~eo>CR8 zR=TAn!r^&63i`M#GuzyD*?Iri-eYks{)s2hux#r_TSKKm+6#gN`RVO#`{UX*o9Al^ zxMlbB>4Ev3`+w*Di0uRgTG!uD@X|}GYexV`l_4#Pe&=@B*~n(nAA9Q6|9*A!>%U$l zp4ii;SDg5Gfx@#NcXcgX3s7)V+&OdR+Yj`*0zIXj;I7<1W;^1qX;&gi={zmef}Jah zuvW5R0hqK47R3(su`&hshJru+%(>5Qn+*kMJfPql_wNehL;Qh?{f2vc?|=Un3p|(( zqf%%$B<9A}ngYeGUNr7C6mYAJdB!}Q{#FvQChm;=O7iSO9!=P-B#`KG8rUAva!*dw zy}<{e3dHyOU4hsV25j!Zea1+a*6)b@OXd$4OVPFc^^eE!X6qBle@7R&oa`rOShQ}~ zqx&o)BZljEKOJ|(Y9q1?oY_5E9deQH1sKC$b>lSV0w%_;uFr+GRay7;?xgXa-KW`atnfF#`ImNI zTzwD|Q-F?*uQ=CC!4XTf7{`G=*OL_ZM=xAZS@(Jc=LSIge?NFGhMUzd zaoO@Q1##Wo;Aam$hLNtVXeVM>`T z4!mI-5DURR-hSuUK@uPoW9O+!OfILf0XxKgBd^!vwpnKo2yy(8UQ}DJ^w_3UjLaxR z>vbL^*pRu7T_0IgXiyNd#gKRr9u2RjXlr(>KRt60&5@{i$}hFV!NugGCwG)2t4o3}VjET=S#^@!j;>qXYUnJM#<$zelvokF(bLovr z4{Yr;?NROcz;>e1%uGC`P(!kbv3l2&Shtum`^sr(=2dsbm@A*t->I+YR$jrs=TMl~dzTI@DF2xi~{pr|8Yx5@)9Q z+&TjK-Mu0L6WpA`kTgw`nTZNcSu2k1NP-^D^={TgkQo_%9T!?_|4c@bz}_~%%LY8q zBE#-Yiot}mqlgNiq3LTT!-TBx43j{-6E|R{=92J?t)cTgz=Ozm!~tWLouF0!r9z90 zPd~&`3tu!*z2j)7wsCVK4hZjNY1o0Ex|i* zWZJQEmJ~R6DMs2%i*OIW_@aeZz(Ji;g;X=_>17P0=LG2k9->yN48pi0V}QlREZUmM zb&avzz?sxr?_At^YSW52JzYp8wk>Ct5n(}VnYVYiilS-f!xmbpj?yd^ep)61q5dIM zrEsQf8Oa*&NJs+)4GqmMxbKo`Y?cC}bdEo*91eY^96+5}vNVnMm8Vp&&qjQNl9dRm z0u%f^@zF&wjcF?oRNgd$ZrFNy102xmQ|6720O>q!XxkvvM^b6;!K%TP-dI;dBQlSp zJA(@90v6JA3(R^93`tvOM29q(7zaihLC^d*s zEP><;pL!@ZtlkJ>JakovcE!4YWNJPxgB+HDoGGIjhnDDI#<>GZCdH;hByXZPL=J z#%-G*ScvF@0aZEbbe&7#M#xdMNhuq%^eLmlf$1PK0nR45?5TB}tK|zAgQP8!lEt;0 zm(P&lMaX!xvbp}Y;iD_VC3!Y}p|gY>glI=;2a`HGCX3eC`8b;ctd$M*W(E~TLT_vb z6Ft1)o@I8DCk-b|4`y?YLNcCBsCeF!+y+Yt=?~OH!JgG+monD1W(<~;9k0`TI&8wk ziEff+dDttpJ0 zA~qAo7?XyqrGd@oU}1bQ!LyEMNo+&rxx}feT%~qk$dX3@;W%KIY6UoGr^*T^HV;FF zTG7f)$f)g{o!JUOs7D-^9L~1b3@}O^0xRgol3#Wp>M3NInUX&))-{2dLSO`|(ehVR zA`Pdl`JnJX_Y&3hpdE9%Ic+;TY}xT@x_Rs3_gm&vALn~mQjnlaA;@{y>B?BvT&8Lc z`ixHp0WN82A$-^h&Xy2@p#tZ`bVg$i++BJ$2qSoBKH(j}Z!noM;&D|pH|S^s#d4gt zX-%V=CET`4l3~#R=Gn$N7{g~eKt?lld7eX(inQ&xYuFq-qDG-@-R#CTO0CgU65$j)-%pHKz#OHa=?<2GQY)KPo` zbwfLzbHaMsg&|M_s+IhQK}iEYHo&xbYpZ;WlU`2kEe|X?w&oIV4~PUO*~{!l_dd;t zuy|nfMEvbjsEEHk{2Ie4bLr9=Qul(Dx9t@r znK{N?jX!hiA$ z@B4WB?0bIvq`kne^R7uR-EZvu@HjgW((T7|3Pwxug~5w4v`Rhmc?+#W%_1 zJ;r>&>?ia05q|n33#5H+-o47I%o9MG-R-^Atv}s;KoYF(RMm5Jw2SP$z5TYg6$P#G z@EWpwh8b{EtkTG^Vv}8?b)Pw-wG2t>pE^8yc(i-8dy@s0U;DKr;Y{>Zwa^@+6gp0O z>(-T4Zd(4~6Hk~81qKSvDo0U3U9bgo7kSjI?xa9pK)Ovq+eQkqGov$S_V(U&|L^=C zXGH;q<&M*WOH&Ov<}iNM35O`y+Pc!NSo0DMd{c+k#m?8&1stoZSFh5y505yzd*NZ( ztW4c}8zvr@-90*DiD^d^?Cr%*AF&JF9QA7(Phy1W<(;D=t@W_eo`b;zgx$}z7_BHM zK3jd@1G0bm-~R_6mc6xg&oKo@<|;P{Z;JxLBL$p$&2Ms-EqX6`9)Jq1e6%EE?% z?W5OHz=Sf56g=BL%Oc?&6ny%Z|CfKvJrnd+!`I9h;!C|dOl~^fAVQ6?y~Q&~CzE8I z0vG{K82Ng5Ucyc@q|6bPxWr1xX9XZz3UdjReoS}yE5QwR=Zz+{Dc8Mt$xQ?3wZaI% z$?WmRJiMYnuC#ZUn8qwd+(+ne2O`Np#nMaJ*Z~PN-x3zbpX`LURE^z(M+c7{bJ%!$ z#OqMwH^H(+y8?RKN0Q?_N2oE5AK2z{2YH!9>TeBiog<>_^Rp#xnWDFh>%;MdJ|yX_ zMQ=@IRk0X-Kwpyhu8bM>$(aaeRS#g9beqOl(!@9(fhjT`Fi&#@dO>PIJlcYa19_O1 zeGt^8(UmqKW}Ql5+-5C-bw*Sr2n0laWCd==1MEm8-O!~@D2bQ^c0D3iISHKuC%H(% zOr5I`o$caH7_q*X^8mpgahmEJo4N4?9|wiqHS+l&Cu2wv0jXUw@7CQ%B|B#m!o=^C z7<3DPcqWF%JET62>kgaJ<;=JzV9=a@A_@SI(%OhX_&h4JP=`8)PGm6RSv05-8Hmbf zRoyv9IHfREgfQ-ajlSS=2vjpBt%e@amdyfUl=TuK9d`-h#4Rb`B8aE-7PZM17EOnp zR<0cKEZ65aX+XSBtu#h~>Aon3BUA;YHoi4Bv}3a%&P0fr2~gC@jc{Wr2{U4LKbF=s zt^>&OJ;w{Q+mkyN&H%D1A)5D$dsp&!#zQ+lf^ zfW;NW!ZLmpv&D>#O0!QH_iQ>JvM5rq+q!Z&3oha_ShWGx3PO{1NB2)$hsY%Px^?L8 zEOSXa8O~F#uVLS;fkTeMHe^>jq$ZDy80pBoa#nXshAcbf-m58hU`r6Hm`B5F(=i5! z2eW!Y3v%8-Ja8sREa#}0uS<$-a+uOGc{Pb=fecCv`5LsmAcq?U$wYk|@v%3mIZB`? zOj=Wt0#O1IQqVioCMn^35eTAdGbtd2dzwrVmgt%|C9GHt4+FP^RZGC8dA&p-2^w9x zT&87eIpXG67(s9CCAL}z^3;WnlaP=G)I`~zZf%Mt)Smkfbdl*F>7N8-V6f6^=^YY zbN%k3aj&?ht2C5l2x{aTw7sy&xDsKF<=H$(7f!#FuuHVh&}*B-ba)m5!#+rCl3@FM zvBc`o=^8#{TA0KGiD7ex?1S9e@mvL*m5bKTL6WzYCvw?rs;;?AI-p}3%7>Gm9!(6B z&&GZ#87gTLU_6a-OgWbm&Z8z>(oDN#DDF0_RU@%=w2d6N+UOoAz1KKQ-?12G9Qw>< zA!Vz&A>_96r0a4Pj_iUpL++DXPUqC6=lZVLh7j&qa40A>LYxnUWknI3j0CCH3+CCF zWe?*+Fr$nIXafy58meStD>}{IYzluzt|P+n9PdW9Rz5m-_gbn(4~`sMrVo| zC~X-uW(;yFmO2E`AybD@!S`-K#Q0wx1V*lqLITyP8eM0wvAdomvh4VZD}(^43Jw6I zf$On~lFJRKc-MGXkix!qXWAl6gu_|E0d{%H3FE9XXBbS=c|0s6%ZK{MnuA3>_JYc2-nEgvW~#U12?4@ zty52-ZMZrel;gxxBQ*1bt!0VrSW$8$Y54VP)`ld3?wE?b3~D8(TpL4;;csmilxV!g z_cDML!!7uk!*)(rdj%5@?&9hpme^5I(P2|_#!m~iHdhonaxisS##$KJ4TG{AvOec*;q?G&bkLuXf2cO&Gpb}2(9!uJh6U7^oq-pY{og+;PXennEs{r9702PRU0l+sfWvE4<1!fsP= z5<+VT!hs1a-A4+H*)iuL1(YD@v>bGxtcL>R34va%_0 zEUHibfRkU6P@mJrMId)WtyX6+!nRsjdls`wS1H2E74t6ht_yn?_O8Fu$N$lf{Lzo- zRGwh3)?FuCa@3p(zIgGei=sebcN^s+b6aNHxHc3ZzVskQ6x=vVqZ0*fqyS~__3I}o zSRv6~_{QR&nx}JKqPLsd@j&3}824W;r_x8u*mtf5W+w$@z{8kJXz4{;pvR{^IPX*t(c_8@$ zrQF;8ua16}uhee6&Ad&)+;VjDrtBxby!&M~9GpoXN*|()0r6(@X7l`$&p(e){g9fE zB;VcD(c!}wrI7gn{_Zx%ZRVJQ9^!NEp%;&iKKS(We{kPlrfRmn-+X_J*kNyl9M``5 z(J#|{&q#{L3xrzNnt~Wc!&Q+EpZFdWT-m-F`+~5_pzOaO`}04r+J5qI@5vW``~%5z z&#^XjPN6cF?$z^$fA)ud$e3R^;$;BOuCe1m5U;-a*x3(mfBDPYskL=>y#lt`WAT@N z<8-T(-~ZcxJ|LEt!WS-l+t879Mypg&_Ac}1I< za3BS9MbcA3FfnzsO(MBk#>eM(c|er1HZ~1R*~0V=P{J|wI;>mU$CigrWIVqe?{HEI z8z3L2Oo;DfmHqV$IRJQ|_4p)sK>b}%?Fqk=yQH%8?2SWFwRT2J2&yC)&*aQ?#+j^J zayKMY5ly1{phjQUalH$E$IgS?^D1|-+-)qpwjOrE6X1d69@?qG{NpnO)VDA3|s1TZd&7mCsku> z;E+Qz?hk=QN&_m5cI1=}n*})Mt&{>eSyreU_~Hz6G%&Okx1sDV^37){LjT^ZH94OAEGN&@8Ijy?QL*+(o(lVKwO=cZb z@*eR@(>EaPOYKZzsJP6rcY$n?Y4975B+W8`*UX*n62opF_MnwEBk*_d)WHic_jw4-|HMl7+Q9GjI!0v+O~VM<9lk>W%S4{{$i&bWjhP;}?SFzqG@ z#_6G1-(W~RGY_8*Tl7K|?PbBPhK`F+=3zET!<>3VbH!E4Q?ne|*3-@$7bWXf9$FrP zlP^YdUkCDIF3&UNe${ktEfSvc@v85VJAooa`YI~!W(`77adkvwx;um+E*}DjoL0Bjlc;rvH^?c zlWaI}2w`F9KuyAELYCGDx~w#{c{V6wc;5nPWuXdrFo<{q!9q3ILdZgF;u)=QM9)FY zMBzqfg|GVf)gXj)geH1M0?6Ur5mQqJZB$l4e3Bpy;iUfpk961Zaa2SqlOzgdxaciJ zi^NgDgRUzF#%b)F!({f0&+UOpfp!b$B@{_k<1GUDV3^ho{hW6o8-Io@$fa5qTq4)7 ztkjX$oP_hl=Mcw!V=UvwsYS$0=Jl*dT3R+OkYMB`hQ4-*@Hr>@g9A%jrk-K>ypgQc zDZFq?n=G_Kv!no)K0UUkottLP1=Ox<(Q+f*a>r7ab@bjz$_2_-F+p->n>-!`m^wCYk{twy9QrzClXX)# zKc1l(&dSNbY-;(^)qDvrS$5R>0(1e4G-3}4O+Fe_E{qAKlPIplN<$d?fI~tf?Y3Ey zM8n8BI_sPs<*-Fem`9McX42T4iySTN#iI569K1<0WcsDp}f_fLI10 zWqM$|X^nFSt}~7q4eKw1In5xM(h7KIW|gBwBy0`P+k?X@&`)cn`;F3dIgYvl4$jd(&pMPNbMHaUge1EzKj1EdT72hx`w}Kwxj-5BtS#z zldz#6?lF&vUi-LBf#U9_U=t>4fc&pF6ztx+d#~v!IA!+v`}3H@`i*{jWB+-QeHR!o zZepXnPdzZyyVP5E)|j)w7w+Q4d%xauas&CgwhG?!8&~8zwj^@7H+I}-j|Np*)a`BV zN{?f`ZfIg@kb2#<)4hw`>B6u_PM)Vvi4V!XA0T72@||r{*ICLSigOGUs67L?N-t~W5O4b zJLLI|G{3Qt>Oa9|DbIfOuO#neq`6E^pP^%Jq|J5<`#b!jxLZ!y7Z&f?vXxqx_SbueUG?p=QnqD9;+U!7+fNwL;*(^PVbT5 z;nN>npX9hr!I>Mc{M-owFI zUYNXNG}YBx&@`Q^EE!2Y0>TMU4}$QMF%O%$=xwxci$Bgo_3jrQy@FzxUeSF{DcYei zZr2%GW2Lj!XynPf4S-fn%#ZRCr}%F}*hQ$1P7cY4D6&KG>Qb8o&vRs4kK37~W+%l+U zdIzY5K31wA97HRK2@I3Ujp5DBe2Q6wj`gYjD}LG}jyRY=o8~LbZ@`~G3Vt^l@==ad zu(T2>UqLn%I_j}yN)@Y;SQ_F8zc&(@C}xsPsFPNE90o99kUA7O2v1$=M@ea`03@=* zphRvenW7_A*J(FtfR!1b8f#6l=oFelpNK_K%TsyCzu6&1adNAA@npu<4w(Fw}o$&|3PQq zh^jD}mJ|w3xbK@yrWC)hh~2Oyo!Et$BqNS$)N~}nHY(2CXSgEjl|2}qNygGsRJ#~*g!fr2)a_YHH{O5 zNn15R+665P!br&2Ko&sE$%Tc-(6@ssn+9Z=z(n7hkdS6!qJmjKVGw49xXd_u0maC{ zg^RY5mL)dH9Eo8>AQ6O!z@@I8RB{m_+q zO~w4!vkSra!8FmTf@HAX(3YHB$)Zn)Pf^oZ!xnzSz75l;E2ZhAF=Nf1YH=L11Wetx zfqsuYP1wX$CS=lAF&hc`JX}4^76zG!06H=~s~$MDwASQ^tH?uC^%5>N;9H{l=!hE) zhV&GU2=iSg2FbQk7Ua9^)>ViX^bJVB4VnXa=hLz%r-Qkh3@i(H2ylKtT_i4Tz0Q|& zM@l_rbt{-KiINtHv(khX6tLX1!@$>i!mx$UV_VQ=i_o?%?VwcEues1N;8+_!EDcvZ zAK|j9H)95^0w3Aies(k6ozN;5tmADP;7Y+LvsNAwu@0OVQudeCwz-=M{r_Q*ZHnXaix^DW?_d0)jiW z#@K_NzI1x+Ut?Tj&FQp3@6UQm)2%Q1&?@%gbo>qqgjf{ZZ68z6NBQ3BpE?OF3UoT|sNS)=vagh_IH`e}XQCl)Mf zKiai@c*qH1W!$fLU~i~6nd?b6n|yEG_|Y3bwOTnPyUU1zKmENw{k<3r2`4EK?I$Ua zzo!7`%d|>lU`fCUUrEAd_xO9Xd;A-VUuF0B3&}^M@&4pBw)6gK;(_n?g5Q;Y#1u8% zxz2unV&LEO%VkqFpZbX?Gd~+;XJqVXqcbP|a{2M<*}+d79$u}_KGxUy_VyEzCqmAi z>08$yyZ)Ft^EN4+?fX9YzV~5o>nJ<>DXs|SPIGH(bKalutNc)aBe+qM8`E=~`@P>) zU8|@cMxQLn-iQKrtgmjKZXf>sx1EUyUN)cnq#Rf4tMwaEz(BJ$+n=Y+lJ^}Hg?!XT6oj*(gH*i92z+?uU0~F+n0XHWvgAP>_-r8m`6?fImSRsvA2|OwRjU2#Cj6 zkTPq*mRlx)B1~?x-ftpB3W9U`bv);qooU96ar~G!hBTBhPGK=LrcZ+jF(Be+Azle% zNVg7F#0aRaaE(|(Y+nkd$3;=G5!EYWqwq902i>l!Q7e&YPh6HZDyYk9e2*d4WIHG{NE<5=eBRu}xJIUG(vY-&R?S znuh5u^wB66*nC(BBJ#9~@=;^Fbs9)Alf_G;Y*M+v#NHpEbzErw5%O?LD=|yQ@zV}I zO|sc^(wsSVdG7=w~GMYdt|s$E&Mjsl6LW>KM*WB_69#n=izH0HK&ooO9nE!@Lp zV>b|Z8+%P@T!H#FU3c)VZ;1xIou|38S%G~je0zB2LPd@pTq**K5hK2~MC}FecpfwY zGYE`co>u~4E|feq4nT(qnB|OhraG&!#o| za$AuSA&Ea>U|oq%Gfj2Z7t%NQ_)8RytTq}l;ClCn-C;gP(<#Kn!Cw5^@_f_mL28%kF!?S)A7!bzVexf@ep)W=-pC^4b z1vC)n7Y0dgeqg6Ur-aEY6Lc}+;&njqfWc9tm_oQ-%}Xz6x-PAur`5|GlGNUGtB}_< zMXh)p)Cl}2wM^#ARfU>?MvU{h4_T*|kRKnGo;AOL26n)(Wb`uN=oiF8+cFy=D9vJ# z&()VLf-Rl#yz*-=(;|Tj*ceM+8}AvSwF>2vOH?bk(z@`|ilEvrN!O-)0*=jxF%|0? zEBb`NksWF|Kuq2g31dBW>1wo`=YbFZ_Vgn{FEjoQ9sT8Ks$25lsIMvcE|=}IK*2 zOI{lc!^wOKik1ZvqMg*^cD@L}&ugx1TFZNw*9A*4FA^YVI5?rB=F^#J=O&Dk3W1Wi zi7|1jQRqd~rlW>7rzfat~Hl7RQph3d#;K8 zx0nOKi^l*lU2~0F>6gr<%aGS*?<%}sc1Tb1O%}by20AV9^*V<^X=oohR1%8e8PmS9UlI#e{~6!FHLV7>Yv-@ z!)btQ7C>UohHx(M%{Tpqc}u)i-sMGj`0}7Lj$7v8F@wZ>ticoh%_aUdS2e^){^-$1 zkGN&A)~y0TD4lUfM}coCedS30>({^fRS@`{tiRMe@x;Z8Tq+-0f+WjLrYOWHX1%_L z35VHepW{x*?rUE2noY`K>fF3}>->Z3K?~vW(@!4@0%3Ivfpo*Eh&{gdEN*_(8HfLM zA9&pdfM9)t>w5Z%HxMWp=KT2q0^P~Jr`bRdrwUZ^FbiXEB*}BndD8FfoI=2r3(nrS z+ih+ksBvuGy8qUF-KgK+-*DOM_0dt80 z;yD0Z{Vgy3wY#s~v>SPWk2U{nZ|`I0l|yZnt+wxccIUG=y?~7nU<-obKD*|H%zFLw z(FGtF{DQ#yruoQ61_-j<9tiecv3`XhkX*se&SzDs`J?q8oy`B{p9zB4mF8zQ5UA}t zZ`^sKR_(!zv8K_PNo+5%%oeR%HvU(7b>XcD1ZWd%!y6BN0e>=wCd7?%ljl(VC9hFW zY^zgWWWbanUmdbdEFieF2lggS#O-gbKUt4dyQ4-utv7jM<&MVl^b~bsfW%iO1s*F1 zF>KQWav}P^h_+}Zhf1mzI}XiUDI0<a#X>A*!xK%C{I_c=pHg(Gu>USOjt(2Z$ z=>`+_T1ToC+O`b)A56oIRa?^3c8;A+5ckkD0->Nf3vE>NhK=?BTG_J66*9+yqH^p|#zkjr*#e4V=(TL%TMa4T zLmHZ52r6x1(vTxN*fS>D8M|V59uO3e-&8W~t7T2N&(k@FK`jgzll3#AkvZ3{t!gT| zp%@oMC-j5z8d9mxnyI6ey*I`|&l_3}Jg~b+(GV#5E1JU8No#!770Nt8YCG#4Ghs5J zjm;#j^E&6?EL3i3ioQ2R%$1`4H}9w*pHz)=431zzQ#&^J<6;teYPH6h)R~Dj#yfD& zk6Lp&o^IkFqThi;Lyz~Fg9({ev>hLeGm&w%T>=r5t*srMkd8Q8tJ~TbS38uA0sq7n zuvYacSAaxr!KT$b%ZvHkmOW*)bq*B~YD#t@Fb$J3p+?)#MKHvTR+dt|sp+#^)bNP2 zempO2m@uB(u7`1H$k@UBq5`F(7kfDCeHMLVK2z$sZD8Ata7_}}CRe@5XS9#`U$!hj z;NHxrtr}03=u+xa*C`(A3>Zn*v4jvUEevyqjC40@vJesk^^yfN02Q}sTi2{~#&Y5} z4SXegwxV3VC7fp!bV5T%v|JW1Yx;XKqgCS91=!!c&zrEy)5Nz6h!!|@aPPHZmQYO8 zPj^`Q!xW8B4Jh`|5=NDiDo6eV%=ZA<0B{h+WoFFOyl~dqT(5K~^$c z`5G@=TTnR)<;Ypb>||cGqe5hBhA_1&X9&hvXmp}xHV!{2gR z)DzESDSGvlrUfQJo*l}E9*JH(7N&K5(mJSad@O%0{bG3Xnu&=PP1`0NU&@`J+|VU% zoT-ja*1B|>h>tTo|hNWf!wsoJ~ zbbZ=87RWK9Wsq@VAoEvHze9E7$jrJ;13{Ocnbbq72i6W+Z3QKLQK$KM#mNXL0%bnT z%hDPkKg?M++-i(&KGpzV9q;g#zB$ z3+y4-W-Nh#p|Tp4e5`u8aHCbAq{C#D1VcA~A&QxU`0>&yCF5zSp|zrzWWFd-B*;yx zGI0rOYDWT6HH(tjKc>eqh`2Dw`Qt?`%9qK2ho3T?Bk%4=cdg#UU%PfNd{a5%StVS1`6Z=1XND9z!aw1c z=G&Cl>LJIuO^w&Cot_IEo0~_f{`das_x?)u)`(X8k)7WUQ8yHUzwtXEC`|E}FJHN` zm6)Y-?kVqi+1KCp*k}I5gAeYmU;A3Fu(Mm&|H-D^9Dn21bKE$;Yg;;!`d@g-OJ4Ju z=s!NXDLd=4KKeHg)poDB*WAUQ%rE|TmoIN2_y?E&!DS$00LYv|@P#j!=7>_mx*{({W3FSK6;cD?EGj?1w-4 z(RD24^*49^X#d0afxGqn_wGIUo*R3QhKm>1AHM(S=A$CVichh5)3{(H;c4TbrLImo`9!>ixUNJJ;FM< z@4CR_ym`kyRy5at_xf*Uw;sK+{_y(4dpF+o54SY)edeF+++;xio&J?5%~Mj*)RMo5 zZU|u+K5)ENy6EBY#!v2qO_DPZT)6N;5Ip$15B}!U=O4XtbpQVS8wkv0b02>@D)}h; z3PSF&x-Ctu+V*Y@V^9#pbQ=%^!TLSx%h@Z=Od3r+r0kW%^Sh3^IrRNU2sPIf4iM2^ zn=6;;&Ewa<{@`GJppy6ZZ``iJSX3_Mf_V;pR>8)REu6 ztnWpiq=jQnqbPZR;JI5skZvJhu3_j1#t>$G`HDE{0|Y-YK=5guWblE8(-LFS;c)>) zg*!KQ1i_7q7j||o?%momqK4QuXj3xgC&PLg?a8WRV;Wd=_2&~)ppejc0Fw)X5a{`%Aj}~@UQ)HyzO9V^CV*Uiu4b>r*2>coUPonKR=p*aekSpW zcgjHXK_PFl6O;0;(_L{YCZnoxlsl;`xUqU?jwf~kH)VonJ|+l6kwU5Umf|RmdwDSG z5;JYtTCT#JnoUyW^Tb;i?sHNDmd#6xC^S9Pre@lENQqcPPvaWbABMV7@6qijbAq;N z7ju=K<_N@sz|p2NRB?g3GDuDXEEI?u6VncRSu(-Ui9-!7Mk%%NdgN4p!bfZ-?EeG$ zxTM^hztT;nmdu6vh|l>j>UzDfs4j;AYwfU2p{#l15rY=MROiZ)jjF!)Q%haHfGD)f zRZimNl7&nFvhy6`3j)HxL>t_+HU<77aWMQG$sBtqiiHZKwT>Y}N_vkCA$vnhYv7-DOujk;#VydGN;m}bd_jSZqMQBXczAsNja6?lns@<|r=g20Nuh12L!Wq)kNtd2}6})Y*AuHDJ@WWEfV)l~9*m>cEy7NPo8u zmNPrs1o_)V$}qALsZSVMy+hi8S+x{w`GmpR846vb%T|MI3R0<%BO{<2(?Vv+vKOOv z0odf}K|Oa&4ZTuPVip!GLv#{Jkzt=16O6Mtz9x4?!$?wrmdhYj$#qu~MBiIvmdU^o z&WLOCePOj^2AwxZ@W5lUE1e9Gp%RKy5yrRyM;bz?QLEdWq2Bg+YvBEpnmk>a9d@(S zA&2jL-FeEY7zJ4{DF;ssAM)op$U*3raanO#!Sql0#1TCZc-Y)oRPaH@iS1?G-Yg~&|8qvU%#(U%X+>z8nIod$ zI7H)@)bnXFfpJ}jCZVCs9H~IDN#3Deo3EU8E>U@U(1n^pF?w2tNmy;<<>k$V{PV*H`cREc5uRr z`J#69q^ru2bsDMMbLV0^d8Gs$Ge=<`bG!zGQ3Y*Sp`pzg=Yq6*L33wST^+XEW|~jg z6qL2CC=#&+UpeYQ8&IxsU|Ls*uIEsuaEDo8tG+~g{w!r}9Q6*_sKSEUibb~etdZGa zR*^Gs$diJrRl?|Ba1h+nRb3|^iTX*Cuw?hMuyhM_6$FqKRxA3;aXXzpPmJdR1l`5Y zEI@HD8|oRmZdb-sb62x4EEjoTrA-$7B*-B<~@Q6 z@gr$~HO+(T=V?OAS|Q%J4jGDcggkm7@6;hEGT{t1V=`LXd*f9;FJ(?IIe+yt)BCCM zi|NW+&vA!KQEd;({S?GcH5TTU`3>5|)R@r7X33DD9X{8o$$Y^mD?C{>bV#x>wz+mn z!8WF$ajYZE1MO8Cy0k&!s{1JmPb^Zko-S`r&Jo32n5TP)4jDL zd`a%2{eq9%a=c*5=ZUOZCyxE?deet=>*K4D{ssr@zx?w0`0>Xdk#qesKXdh}Qd~X0 zN*LVaJIv%&Y)S4R@N@S)a$nTOe(=EYx_kV|Z=v}6*uLgVU;C9`xv{>Ayuqzoy4NoA z{1BK81kX|H-Cs7;X0FP8?px<#tyd9R=(;DL9LhL-ZXx)bx$lvik&k}xfY}uU8dC!V za3(Q*KS1zXQPbPcaTk2&0F7>u<1HJS`<>wvrU=(Bzw5V;?}p~yc_+H%pz1G2{xwv7 ze8E8v?JXgsre7b67gUE{EaK)SoNvC*Sjv?}0An8o7LrKR#%bdq3g` z@}tS!yaFTlyD?8c{ndL!;mWW6>_6XsewUO$5T0J2H-cb$2RuT+f~Q4E{A^LUO#=i- zq8lK%94-f9jf5V6KwNUn|L=blDc=2Wa%)`|Glq1ZUF{Hi@dC2=oYq`#);D(7 zSFZdM(Z*8)Xm9m106u)OqQKtFOK=o%hWqKF8JK;{>l z1LASuRJyLp?k!{L>% zH5R&@_%Qe@S@GZjkcGT70+m`dE%%ORf;ePF%afYKfR;Jep_YbS@mLj;!N{h}LvFXx zz9w&)C4r9f3PWEL{$oPMNYfmLS)>H6LHCV9RWbz`H*?Sx*yx20N^19 zjJ(oP8@q1j*t<1(Dr#+FEIVxz@|^uyndc*02OtZio7c$9nilQPvDp-v^Mj~W`%FHE zzOnen(Cf$#YFlDC3PHgdf&3cic2wrN2z{-T@VT%AT*xfRjo(_hSLT|4ib_-4 z!7oRr7$wf>saSGMME)AkL)RNbHXY*DC=6tao+cFppQEG2>WT$A{EkfHN_d&NWMpIG zO>R@FOI;@YVo*`zGHs+q@on07Ys5-!@%f#+Hq4j@6bPy_AtlFg{$gf6++dG6Vte29!#(W>aM^fVCB9@ zle%-oV#YQ*fkvWfq=cDIB`gnq5*RxOVs}vUEng#Y8h+?MhS}SCLlJ-iZjd9#6LD!o z=#2^MCY^1d(bQe8g$-T6WaRcu2@lz7vH}|jM|;*hb%+*plxDLoqk0JYCH+7cZD)Ar z99XfukqLS8v2Rm5Lp)x?ZK?w`OhYnbjn6H!kaQttR7^l%0;|s~1y`|iGY05VaS8JI zxn=N3NxcbD8~`ga2snC&Ag{JVoT5|FgeLLeH<5?tKscEuB=c34XiS+E zx0xW;GI6)5CrO&l(R*n!t!6sc#Pk%zZx!pY@X`Zlqb+Uf6qK$yuG1&3D}xpF-kQ8G z4>@x(3)>_tVhCKL*gz@6bmVAu9u~_o390QJJ-jfTbyZeCP)n_ke@Ae)dG8BX2y7*F@img zY{XkCt;1@DMh2Qc$)M6lUEP6e_Z6UQL6`4p~m3mnBfn+6tvCeP`4!a1l+f#)#mpz8CqUP$DCBQsuJ ztf_u_*cI{kg4qW5n^|HsERmqkM$5_Edq*3s=f%j=d0($eG!hC|e0;$o;SQc#PCB_G z9fPd!z)55Ds=)9nKz5xpv_z(%2))71sdME&h*bI|`H5?qI@)hJi67E! z{Rd=WoI%YSgBvQo-MOqBm(00X5}fZ#8|rbNB`#NHQ&DHo@Z{dqvktOgqrb} z9&^ediFP*V8(SL5PyOcn9{S0Zs?Rn6KxeFR8{_#&v(r8>$iI911fs=*x!=5Q1HsHQ`}_a#KRz06-Fh=dIi-C1+_~c1Wmo)=Zr($| z#CmmyS@7s5IP_b8o<~Og;K(KR8TJi6MfI6euLh#{-FCQe`-#aj$HeX62#k=#)|0eowgU0A)PrT_c7sjf)3`3?Nt>Y;hnE$h!i)$SrsaJ-j)^CkaT@v(M2h!q4HH{fP7 z0F1e!L|^~<*Bwd3$KKz)>pT!Z(bFw_&pnPg&TQ|x>(}r7^?TI=2tflu{5YN9f38>; zK){AIY9;^t=Xc+B8wAg(@@O`kZdz?NbY~L73slgZF%Oyt*I%16XweLAt1Qto)ougKz&|>K%+6nqk~=$ zaI|(&@%zsVXAP-o+=L|D%H>2g9 zRpF0bY_Z{His5JBXIMkXVWIdcF{#InCg<((U8as9ysk{G3@&iXA}W6%+&V(i=}u9yfNpR0*vVLnV?NkF{C_48~%y zG0lY;3Zptp7I-Gf5HI1=8mHsWrx2>V9AgaoZ3i1c@_SThkX_^TFO#SiZ3y{`{`edo zFvUG?2|TJ^l9rc!g>Pe$fj-06!?aMKB~98T+QG&=0UY(zZ9Pp>u}y3nk*qW( z@4Rc&YL|wxOf3Y&3Tlg-a5SB#RMADeb@}VbSm8_OheTggpYHY>+B5_I}n` zQ_*;?;g!LZHn(ja>K?ke=R##(v)=?-m=+~p*mflLh9CO~(u9KYONsU&H%Tzw#8@xp z>C_oEHH`gn#U2BpNTT6mTItTlCG-k7==h$xBRy@&26u}svhV?WFAip~YebwNVayX$ z(btg1wXQ@~_!%Loht%*K+q9&FxbeA%h#V(ujiR2Qz|~uycpx{a=a2yx7&=TSYGWYG z24716yU99+L;KA=!`{g^RtjQxqT;-VYs&5)+9?5sv}ZIjI7{P9Z%ICe1a~?Vz#l*z z0{6KnTnzgvFb|+YSB?V?lu4{v6m)Hmzx5UZ9A-N-bDo0U!qlP*O>MQ~O#1>hk#j{_ zBVAq0ovGNUItuibBU7L(76seoWg3u(9u=ImSUz6vSv1&OLhIHh0IrrMa)7ZA}hN9E}Fs{jz0yIx{9Pik2o=uklB0pK}mIzF>spXq+{+ zZSyH(0Ds;%TULvZw^>>xxfMQI24Yyj3{ zLvrwxf3TGxRjVNh926x{!8jdORbz%>izGwi(L%-bloiv8U9Au?8?%+hc5`$%I=&1& z<#XH~ffD3W;j^zsSuA5EZup@h2z9_W~5is_`@=vj_k zon+nQa57<7vmzpVl#Ewpv2wsfx3j1K$ecy5U??tZl@i`2%Vag;1b4}?pM$JiF(=Wv z&nM01a55M5A?)aUysQ_ztjCkKUN~@(IzQ?Tv#MMMCWJE@vQvh;AJcWqa$z|Mt+~u> z$Bwg<4CKO9XRI9N4lxK=<>+k55md-snbFu{!U-t!xLE7pi|=AjBstu}&u*b;`Nnp+ z;AP(BtCE8?Uron+4Pag~SEiMz3JL<>Wo;{756E9skh`3&v4T^jL4ImN6QCp~EGz2y zu9(7tS9SOt9e~jH3ivZI?N^)!nSu|Cx3yz+Xr>%In!FpKlbo~IywN}jDV;|Xku}qY z9CI_av)-ulr-|`_eokinA)|x?rp99RQ`#`0+FNZ-9%&?k*q z8Sgbu{V1EML%2EO>NFa`%>L({6qN8!Qj7kSvGqt(+o5< z)t=jMwCih;Mn2e|HTtu`&(c9 z&KH05Lx1uiL3F%+@{8FAp8miW|Lqt5M&U;CQ(pL*$I=0oS!<};7<(9yfs z-uBWizfs*`J;2O_#***VimAj9SFBQ-+qE069U z-Sx-j55+^jb$(}O1A(Fh!E=H@=Kxpssrd{9N)Q5V-Yp8bIiR3~BhC!ag}4{T&36>e zF-5HPD>uFpy{C_RzTJF7zQ6x_S;j~(|Lvdt!#`ht@{^xDO=0qT??v6jFJ^y#8wTEQ z78^YPo;TWA2n^Kx76Oeq;V*(S*4f5fO&;M9gD4;#3!?{~qR)e_6-9fDk(vHBT8q_t1awDZUgy36jYa z5`pwKB9DX|(1R<>j*p;;)pNxLW-vZ!X@ccl%?msJ47#_ua~&oogPJf^rG$OT?otlk z>PZS4lGC8r7H`$kV5&BNW?*W_L+xpkM^-G`mz)EH`8Zjz6>fcFTHj8a(u%dDrik4V zI`peUA0jVnir(~W85{25nIaFA7C1|wtDCCvs=u#N3&17&Y{Yg&M_TGD$EL3GbeXcT zY6|vHT+8M>fNczrq63K5S&SMfyu`m0T%r@m<%>M=#=3fL)j{Nlt)LS80BUVokqZx- zH^Yt{R2p`B5SeJtg|ulsW3f<@P|I3EyBG^AZCnJKw``^0qp<6=xiu~E8v~K+tv8OI zbBSee5zdx>G|U^-mw=Ge8%`k(1CcVs3T+f0pT=wCB|`bexE_c0^%IL`VN}=4>u8l6 zJ~mJVSbR(kZx(X(V0adTd(eZ{eEJx098qwxjRoZuF}m&w06hvJz*0>BdI`|{rov&q zla_123^l&4l|U@IyhqO>6hbsbF|LBnHb8O3-g2sHLvAN_3DM`W&{`;sDjCfooO5CV zVCHOf^9nt2RiXi-mMy57p_&w_Z8?!iAOqmy+S;~DQ^9{Kmh;4>rY#djOiOZcs;NPu zpIOff);c=Ab1F>RXN)x_Fi}dxnECvXLNu-zEFCi^`mHIfahCoo00Y1?X;lMCmpVSFu&;giSxD;Zn!Z4*CE$wu2 zM8mO3V14U1-oa`>y_FMK>4rECyzXdh%Auq*WfZ~A&hrK7*p1}0M8 zj0%s3E_Yb6WyuCU$!RSJi8hbK@1}pny@lAe`*b(yeS{eweV>l5ch@HRsyD;{=0ITl5?r(RJ#8Nb>fgtC+@anGEB6 z3fjS(%P6QdD|=Y?rbi$EzaybBAzA87EHK!6^1xC!%uSXsQSh-gbTdvFAZOEN2{8>V z*dzrd5ax17?P~ZqH;c#EdWsW8rD73(!uGfOYr@gGeG*Tv;f5FPNht^YgXKAeZ7ft; z#;J{)nH8EAdSi`WSr!L~VEQHq-HvShk!KmHw~5?i`cj2~OWB4xGFgReZ=qoc_XKRy zDaEwRT3c5Xr&~flrL!C#uVbq)4olZ^4ZfXo&WWG#s72E9he??6(Viy`TWs$j{}dar zEutIp^PA2OmntSi%D6;{a?X`K-qY1T%6v$)IqmntJf+3r`)! z(;D?gH0n&vmdxiKhiqBgQ^-l^eHI2kA)cY7FnY!-%FBn5=#-;n4p=I}G9Ti+wZN@f zH5Ca5D5&=xW3CPS>IOcwkRf2BeQ9HpPX2}ijN9U2jt?Q{4rHHe2fMyTiIi}ur5-~e z=2|S7@2?HF#jiE7Mpboc;OYWOH0+I|E+y@eU+j090&4n%D38Uw=}*j+p}^r82lSbM z<7ZB(HwC}(je~wAoPR?I9=QL3`_EKhe)OR$f?uOGQe$^*$(&813%@o%u%*957f8PS z#TtD!en5aY+q&DWg4cUT$FiRZ*RSKg=jKgou3H$zUxEfXK04O-%ta;2{5LQA#ay;D zu0?xO|JfQ|%zYMu4V8HU!CiM9UkFyWo39%nz#M(<=yUp>IRspUR<)Xk!H*{z3OIC( z+=u)3{?ubXpY@;a-+SRsyNltse(JHep2QoYlt1-Yoo%JS&)Na0@bK_`zbc!WHge}X zU;gdE-!8qz+uq)IK)m?$uM|+aaVp{~csSKS>H!4>?6I>O+1}nKf7E;}c72o-Q2H$d4{2DO zF+U0fl21VQj?ZLs{1&I{U9SXG^PO+6R>?|o>wACq1cLPrtJCItcKYyH%=g_84B@IT zmLDJ7;J)w>A;{66K=6-$bAW*QU#dhGr5FzL(E6p^TmM^S!uCP_JIz2uuy$_Db{#3? zXRYM@tledBhNp~+&*3q)XFSmvw7TmRJ{THrjMbxpZjk-GO?rEjyaFx)ayF{d+c_F{ zT9N#u9?BraZDxF%?@kZPxXhiIhR_#%RwpS=YSA`Jrs0L(N0%ODZB5T?koyHp{{nH2 zHiqwxw+f06Ib?=TwR9FhIoQ~y#-lVb#^F{!LkDl{!A+2H@h7oTs5P)MjE9OM)KW;J z6QdWfgH|0=ZpAPkI!XjH)Rd6HhD0KCv7Cq#E>S`dj>??j7ATS7l@5az?$bzx4?TWxeU@2xW zHWugNc;6HX=}qefQ^or0jW3q1VtTd#8a3LtVJd52pWr}vJ0d~bguHN|qsiw;Rf7Yv zrAn)f(HS%JSBy*Jn09i*IGigrp7?({+9UMDoS?udo$!WGi=1=|Qj!rY`N%n^T`D_; zPPu)sJEb@=G53j2j#&0>Awm&U=Si5`x~v=tzV>sW@mG!y(yHuf_O=tTZ%jtb^@fqCFEoj2yDb z;-a;AG`z=1-Wh*V%Sp72F7%k@iSojK2Mcub3eE?@q>lvV08F2*ZJ8-Y;v1K8D#{l zOxzg`PPUniZw9w8%eJ2L_&G@G(8EWUs?e^9Mzi-{ZZ?7iS);MrdMhP#w(x3J>rq&hJI~H|mU_4s6OKB!hEu~> zsDV<+Y_Xz^X%(`*3KZa6+iw$YijGxz4j{<|kI4^!%^k@NKQCLRE%Z#_UCFj=E`i#^ zyYeOZHhXZosmGUirO}q1((I-&l;5y%l7wqLM1w9|No{ic!!}AN^!U&2h}8*oSs(fc zK|c3($lg^}oI&>WKJj3@PT1j6dS*iB6Kz@r7z$Bn>BJ%hOiUzJ#E&^+I<|b*5(>Fv>XGUpvQ8i!JoOYT`Dx9vA1?)D+7j&nT=cx7-$tDb=o39Yjq^eb~MQw z;inMq%dy9ug3YmaZ2n>JWV+@UxHxx+QWuJW-vtUhw?Qe*nZaxkFCV&()PlhT!}sB6 zU~Ii3n@P-)U-YY(=n^fYke(54d<_#t{$Ua)R+Z5NVCocX7#V?K2%XV`6Jwk~*iH#d zJI>SEdNT>0@H}tYWq`?Siqz3}mhAb`v~Z|fh+b^ddP*jwm>)LAqnXxA_jk#i>khFv z$P-DL_Y=1q_lykVEaiYJ+Y%S>m#dbLO?#lCtz+>-ZkaVTr?SPQg38s=JTwxpYSo+B zyk?x(yaX`NE)uk_Lz|abomO-Y5^-9LIKZDGybGmKjLMKx@)-TxP+_!^I-t2i4nQV# zJ+0?HovFD`HAP~!wuN{b6I()__;NlfvsuV%>lRs2={V>{$;$ zNKHs-IEX;^a=1|zX zO1hHe3&HNbh$vP@vudHvCjc;k(ATbI3N`47;3PIkhv|}ZocXq71F9h z4H@_(tpR1$z^0~=l^3_td$OQp-SXWuMhtAYS=%0ReE^(;0fas+->x;LvRSdrrwdqJ zWSh2GOLxGn)7s85Wk(BSDJRnv)zN9$GLBvzzVMWUz^ee@$}_XUGFJ~XkCgx1FEWd^ zLN1$f^*^6jJIxt#rsWI-j7>&5OY&g8QXw64om_BnG9cqAz8gg^+@v@Ju+X|$hfZs6 z;LS3Al!tLgz2q`1n}W@-QD9kGIo+2o(c{%H(2IV?JQr&(<5f(9P1@7uG+{o{8F^op zE5<8h+a_g?WHz6|E4aKn;ydPtzyg|+oE+U^J}FjHCSex(4(zpE*K@&>tpcSUHoQuj zWR7w&1_Wj6l5(1i@|o!qq~SqM2U|D+38Sn;g0^uj-%6Uhrq?%C_LiX{j@!t z7vs8|)-z;}VX++=;N@O)%crqvRH)GWXL2~xFyv8$HLc*nGoiiufG)^#Q1HlITXq(_spouU%G-wC1NjSYy!R~|2SMP<$*7olrlGn3Ib*tjJER$>NQmF~ z%y*-C#+#F_H<-*~(S6hTjF%Jcni;ByR<{1cG26M+9AI0*WP|8)wd_mLLz-&}lue2l zvz2^3XU@eE;#JbP=Dr-is!_Ny4E7~ujq$2Hn)6Jqb=OHj%mM0aMi>NUzcI>2Pe1$Y zu`yqK{2jlU(@4ow;=AH3|-raZq zz=F3^}9kifgp~arn%KWw1FUg^@>yoM_+^=I6&}ClM8~~V#nMAKMjuDJIq4^XZ(Jn z3IF^?dYD642gU9qo}Hcly^o38ck?@E#t@2@FJErn|NiEKAN=V(!(6@_Tqj9{0tE2*7s4oPdg;# z^6v=*e6#xcR`QuP?;eA+0fOHSwIH}|njassnY=hpfW@aDgJ47cV#~c9%0paY_!tZQ zqEKyL=blR@4v%OI{W;_Eo_&!uHkj11M~#1DrQpjz@+CRDO2-SLVtcsZDiMEDQQG?9 z-N93DUEOOD>=&W^JmGNsOyw$EheH{qb9iL(l&wvlw>Zbn6ol)~ zSeLksT&#nnE{IqZ-4I)HboQRb%n0kenT4-I%1pQzcYb z8pm)WvPd#0l^V7ppK9rSQoH!}1*n22lxz z&4gM$@UV042jfc=lQ*XA4{RVk%S zcD(8t9o(Ozu`71xT?G|8$+a?J`W#7M)4P?;L+3guw|bO9azcURjw6ShQv;++Jw@8M zMof~58mSM!9f3J*&jF+LgO|A68OvQhM(BtG3C20;OzODCqBR9K&zx(ct;0DrIhc0d zhTgcqGUhvw>=>QxxXA~JJ4U8W0}RI;scPamcFA1ESOH@u@j$^(0AakKQ`qyGTphSE z=&8=EG0wS|M`GVb#bWm$u~V|twT7vO$&)3M!bKNg`SY0naMlew8L?4$a2g zj4e`h3V8^93IO$p6--RR0xn}fM*?zmo0WR-=Sfdl5IsVQh|YM~RZb91yW-gfu358e z>tOPBx~dUe9b4llhmNDmEqTjnIZG^@cvXV2h*uj6E~8gvnH5otf8nJ`!Z^$qwoGCv z<&;z|vm60%BAi$KG{OdGOY&6!y)-U$Zf^NJmNmBOAp8YjVhv-+!RBYF!Lwwssj0N- zRif%foe(8LD&s}TJyRy4rt&pNTvmQ%i2+r?fi4i!@h&whBxto7)|C+E_-j?bC|e%- zd1ywq&h2W3a;9utc*purnb7SXg4UU(o7X5Y_dztCrSMGS_2bdlL-l+$y6y{8OJm(an~(d3V7>`m zCH;~Rl(wU+0jwrmGVLua1F5%R5I^}Z4cr-5$=~$Ia=g7i<^>cso3B9Q}fpU=dQ;E!I1Ax2vqX!F|w3Ez{giN5J<=LP?iCL zix(dvW`Eyqg0@;{HeOi~g5rJeqc3Fy0RWhA`3-x2@JY2`Xcym>vFx@~z zP>_Kka|2yC(xp3mlPDIndA#|}>-9cy+pv9p>B1$@d zjpiO>-f$5JK&T+#GrC9L4Z(n!7lYug>F4QuD||Z)Yy!|XM}hAlLQZv@5F=S{bqpR`X|qZZr$tk z6YJA&S#3kwowAErcKlfHx4D1p;*~QH zSc0o<)LEOQUU6Gv@mV%=l4#q$R77dWoXzizW69M!!o@$u$7Qxrc^nl(MEKPigeU=n zaZ{9Bw;90DyCxcnU@u+Qkn(q=BBBP2iiCW9R9~{mJz>#=jeTNylUe&+p(oLQ1BbmM z&j#L;&^zOYh&xlAB>$cca`fLTa!ZJ5CpFNGL&_9OH7R^ZqwdoCliQhk-frkC`tH=| z;DqH%uh6Y&<;dGbuN?sNRUF=V1N|g%*CvOy%AttjYnZsKo%Cq%2*xQNCd4Nk0n^$( zh88DrYy@KLS;*{=p6$uTvF-eH8)1~cQ>*ykP*W3}LGFz63;-#QFVO-F-;jyv8%77p zU8;FqGa6S){XNZDFm6vYz;Ju~#EQa-*zT>8Q=vOqaK{moq68u}K=dSuX_a!@wm4N{ zzzaXrqtVdn!3b{(9qgHsYx)|(6?Zf-dW+=KkRfst?uH54 z(f8UY4!!BH#ov{IA2--Evp2>!9tB%K204cqC&q;VsLeRQ2eqlZ(we$mOv(No5rpSDQCi*J60x{u?Tgie6`V#qxi5F!7xZ8w=AqHj|4$u`x z8(4~`l=#@V%cLP%FZ`I&rPGzCV|<$R5Yb>Y10MXa3T19j0l)Pm1@{W?jGuB+#@N}G zP{a~m@X<_JX{M8=LHE<*uuu4AH&ZNe`0Xm@Jey*4*jN21rhp9Q)3gb*@=OV%JrZhlfBiPLqo%4h!2sLa!J^DdDw`S(SpmB7_unYGVp_nqm_lOPIT9Q2gXf{0r8v zk;EZcG}F3VX}oX!BBU`&G4ux@-JW7alJI|ObN>WVut==@W?dNI$6=$6aQf! z!)jOSHwd%UlQb21hGA|?{UqeNQR6Jh zt%YP!0H!Y!H2$^#b}A=+W%Oc{V9wOD-J8U49(Ve;;orAyZ%Y|Z6gMGi|JV-|$Sv<+4S01m zKCx4`p^BG0UbRUTamC(8c4e$W6_v7~%F0pV@l^O~&_r7~1{`cSril}CiSF`AK^(=( zKgX%JRRGN^4i6JF0Q5D1MI#L5QL>bkvoThV+`;?O}0J1225RUe10AjKqkWv{n z8k}LLNj|1D!|oIlVpvVPtPbaEELT~!ZWf$WO0hMG$*sv9!DRI4y)|@&F|HYp9F)Ko zg^mN;STe~50E8Ffl_0Mi4t&1j_)B;ZejT!-y`e1JnhFs77Q4%=2|kv~XBReqf_#)i zc90?#8QAixh9qY%?&v+J)p@~oJZIxqCv!3B1PD=*`J}-?e%G?g8`r%zgonb?^l{NT zkrH%EFs+XxlIL)kFZhN((H4eq4#S~SBBwK=#L((qBLT3~mSn~hNP9PNaVQ~jPMGP* ziTo`CHsp)Vf}PPn~->8 zd`t~gL+@}#V}K505hj>t-+)iAM!+8p+Zuu)1 ze?hCA50uPDRS|Ty9tFWZbD1PB$MHL?UG&3aqI;Y=0UpnInn5#GW9Dwrk`t1;oM)5T z6}~*osX@9A<02wUa^)5RMq?_nLz{6-hC zr!s-!>3tSS<-=DK3W(BLi-J_w8)S5yqlifZ%N`1Tj`*r%V{JE`%yU;D1P;3okmiV6 zkNedqt+*7wswJZv(be#jgM$GS%$km~iv;24!cCh)vqCT0w5d$R*MNWk;aEg`nrU~) znlNgnbS_-8NaavOlh7Z`;bLkm$n6NPMmEWMI#yLQ30iF|le%y7-f&7VHx(7jbnUP_ zA$E;#jQ;VC-W*R|(vHx^&5)F?98frQvmDV{&~ccr@ZRuXV6>Jk_B0QaIxu5dJ zld8Juj8_}Cn5K3XMih>o8_&Cq=}sch4ZMT#(bC!`*ggHP3AdHR?HLDg0s=vW8(!bk zM4Ls*G5b8-GAixh32|=L)pf;fDhpn>_iqRCZ3>J8LdoYX`eBe>iF0 zY|OQ5j_}%CGuWnii{R4Yb8he}C(Chjhpj{kKed(Ptbb?Yzt-q*eS5&Z8a8_=aPd-@>B-_(eAxn4W?V`{PSgZ~!@+kFXG`P+nnl25OO@IO#BKrrB9 zz5W!U)0jITV9x!2FqHfw6!-@~@B!?v;s1r9w%u0(!G9nO`A$I>)4BfB{lQN?_H&u} zAY4OZr9bCg$zu#XYYwt^=VtRg*IDtAorCPzJZyE-ZvE_k?vT+<|BvKg^X-}M%Qi)b z?JL+0tX4n0ik|p@b9LGmaW)*oMSRbDZrjr&N%y_xVn)OcBg2Bxir_74E-y``hy~2tTb}$)Z8$?0epG z`SKP5=FABMS+=cV3jr_tUbzIpK4u$#y&0I7M|=TR@h|}Qq{Y_aew}&U>l7vp$l^wB zx$E>?1ZQ_$M1HGUtaO9X7kbX$8l?HRux;a>&lVs0!3XzG8VCe$1OWW&>!gnmm<#-! zf#9JH1m<`PL8iUY#)!`dm+@HM?-zo5?m-*y*4VA%1?XmN(NnlxW8mfyqMd9~LKgV2DQGBhs5zK^lO9TV4EblNUFBJ8D+>;EtP>d}J+E86e|%yCEi;jWu|9ZvD>N!R-+; z9qJs?fU~?+nT{tWHMZsnwKsTpk~1GApq#C8r!)o(SoN`w(+XQ*v0FVPNObEF_^E+H zcRsf&+*jmLDEmn=sF#*_*{MPaRRoP&Q35J@+~Ow;KE*~(a_*pwfww~mH6d}h*7-Y_1K zzx2k@Y~&{R60b*O7g~)gd=ON)Fp0r!$qoz9vfEa9XZBYyO)VTmiEqAqtE7PENZZj) zAJOMyIv&Xeom-pb)8`6};p!K;DdglSh$$zAoIEV9GsD@~Sj!OYV=clD2I`AP9s3Oq zg=UTcHaHuKMO+_dQbpzr+QRbW%n!X!BSa6BfGQk;Tq<MbV_&rUWYGlIANL(xUFnIr8_TE2Mvg5k%tb4oexO@DpcUu_3 z!kQ-QW*P5TkX8>X5laM*e04_&R$f5%D9}JzL-fpM1txzurv9)2CE#$1x9=Nt`>%en z;kB??tDa-;3S-6OGD2Vz((tyqi2}sC3=m+o8~;Hk_O1jofL<~rMGqgR_w%jWJ@3tM zMxu9vV$eUG{mFH0-^1T-o8& z6RZbDitA;x?h7xYgvbw*AbY;gxB%zyTO5^ZENI8XFYRYO)_h5buv2|N>`}|sp5RBS z>r)q(E=Q0^`r1y}_Y+l=zp9(>CcaFeNtps*N9QW80dvO~1B_|lnS#|(uoL48x-Wh(qa$_ zaO4H#L03F%aDy1FSy-o@!5|VnGiu??K6FN|7nHU~=rc zKH{PejwG1_<_==2oH~+`eWhm7$AOToqJo#V$wzj%2SfDWfeB->@Z#4aASWSmTqXNc z$^GORkcUUF&z?LhF1~I~T#%0MO$E&O0$lsarq`8e>}G90dA8^BWk0iWm)>*H$93^j z;;hB7T+t01Ne7gX@JjGg78HJ~F}L=*$}Y#dJujdX>UOnCjkr>(=-&zhli~Oky^1UGy(vynqEF}AwU=LZN2!zOH?ckYtYmRlnO9hu*ZRs`E{BIN zpBCJ$3K?HgR%*vF0FmS-U22WN))t&buQF*VlZGX{B0WR_j0 zchkRu4DT!FeEhYuKN~+Af3xSMf1@z}i}~5XL94{zo!KcHx__ekTYp05-S&Fjo!T;M zdwuiN+jw+?%+K#X19qD`JJbQBY_Gr>_uQ_cmE7&&As3tUDwX%Sb1x-(+O^udCrNDN zb+^xLYJckv`&qATJ^Sn`RMHN(cSVM@gBE?c-TU91wE_doZ-+sOE0q+cV;Cg&BMb(E zyJK+jWPkSX3zVCJNgh7w=Uzn}9z%=t0s-uIZpZN~Z*`%UO~UfOBca7!fL znMFw}uA3;l!)WHt_#SkHb3ISi{*BS~zQ^8ot>edFz9VD!jzWDqfwFH0_!ijjJmf9W zta#Pl?WpWkV=EqU+0rW{Zqf4e#vsK~lD?GUwKbF!3J zt>2#iySX2IYHknlefxiW6v*yg%zKXvsj3G|LUKLXS{sBiBmuI~^?g)KC`XG#o2 z_%5XW7vE7Fsm-k__)5EDxF0Y~@c$XribMJ{#_}Is@OTG|%iG+h*rOOzl+1r-MY&c) zQu9tbN7)=uW7k@-?rPBv0J#fBX2Bt4klY02Fo`EEc@#^pq$|E&A&Yv`M=nS1$scL* z4hXT^ZPM2eI?rVdtFv8bF(JQ z?-YBuljFB=i{HZUJNLSsZnxVNv*tQ#-l`WanR&g9s@}$b?XC3sl2k3fQ|jv_(taMq z0q*n|BI$CraEJc3q>_`jKy38P|FT zWqZ}@Q(DN-*C?;L5g@!GxmB@P-cWatf5=*Lu(*@mddQ}})QsJH43A`0zPbeBYj zM7!ED6gA#YkRV@TO!5j7bNsnHBp#j z>aO;@2fE!~Sfq_qy-r0vvP(?rxV^5ACDa?C?WBQjQXp;dweQ}`Dk`_?f!~2H@b9V`I+F#%mEdCONJx!NQ|%$7&W^ONfLRgn2) zOC0IT(6Nk)S4#!yh@L;a$XpA3ggdygJBO@Q^wSWMxlDR z%D7}+y&6H*$>K`brLFaNusLB!_{wb6~m%MUMU62KIOW()nY&4GJ4vd?om>^)$S&`ALPZl7+ z9aOe*BfgM@RIKE4^b|=YiRUg4DyBEDJhs+R3OHoAW&y@Zeqm@WMN)H( zP~fI5U04-*5_94MVj`nyIkb_z>_hG=8w{MMks>;;GhzG7r3@~;Y7mkaXV(bZ0M~Mx zo^l~9In#rl%=!d|6h0W4jC~0ZPmM%X3l}*hHDlklNQ=GbtoI$$o7UDaqgzs zEYB80JE|9)Ix?+jo|GSFI&*E@BE>lzdYCg3ZA*?O++#n`eA?Tm(-|kfb2L46CB|)d zCW5N*D#ZoIC`@QIw$Afuqpo(ulq%=u(@rLPW8Zl6(hq#?f}2pC22*}kheL9$TtmH4 zcb*6y%sy8@v5${!28N^Maa?Ubkglk;e<79dKu2KYl;wD2908&lZRxpkQYA-An*cZE z(K&^9`Ps}l+Q4wOSC$>eOU!4Zg5)Vv9SzZwe}x1Q1Z0LMxQ1YKX`t#wU>^*%jl(p- zLuxV(Rq$aEjH^3XeHFg`;ycy9Xct1sd(M$=N?|ydaeQ~-CLB;X%-Zo}$SrZ%E?fO| zJc8vb)rTz8DVY#_#{Jt|qiDD+Y{)fU<$R$wM?G7A6KC}_iyXPY$#uG3qGV>KRte78 zYfuT5hK35p>{FPwL+I3Sy!ez<*ac@ep?t_WjMPjBN+I&2rb**JZIy9THe)v$(d^jzV>R2LGvXC5iUTNQr}BE}IJIs(uLABl zL=^pNLvfl!47wR&0GgdCDh4U+f=lk?4#E~lQyl_tfTs@A+ibJMDxNVZ0& z5}4);X2QRFrLVzGV0icHEB)@L%=iMqdPt*0u@eLC{}jDGV@^mXx(_Ei`xvC3d;jwN zoYAb4izSVm_|NT)?L)lGefRbIjUO=P0R~Q%4HFnqNcbn+Bq{8(3MoluN$h_sT{7B7 zCpGsm@P7Z5_iu0NF!A3^smuL#44&d3hTvVfM!>wlZA(e@a^UBR9s@b8WvcI_zZC;V zk9*j?{PNRJ$EXw5SK9%&>*#&&`})_nIUjs`TQGkC`nzG^n;iVLt!rCn%QP!vUOjj< zCPY&1wZ}kIkgl}W=C!*{9+%|%1u8t}sgn{cfB$%ho``*X?5q7kj z?cnpwn7=SCt*0FFOcM8JSAkzW_yxC)r%ze7H3n<5>{4qC3@G??(2_B)ADq_xTNlhf zr1e}jKhG|N-u?_zQuVl{*6~!NBTQri(=tppJmrMH*|Lb4*Si8D^ zD@gzKudq)p=^y*${q`sR%DZ2x9vHN>k2&{x>HB-ad@7?cA+W!~5yo@-JloN4T)nis zbm}0>YEq*+ZPYP zM0P>0&&&V)-|u%89dHu3+}SyC3kIi7^{sY|K`$wu_FVLp@FoU*hiA-j3{+R&4ucPV zuuoxgv&Uf7snJb3W5EcX*-186KXsn8MIJ%*F7i!K$@P{O11?r4o$-AT!5t~LihrG+ zd~Ss}f;HioneIC~ZZ)_1-r}WjA^mP~?k(vXcAGncm0MiMf$XaU892>dviIEwZ*2>7 zX6RNBLB3Y6JiYNhLe>H4`jBfVK{~yTpt7}b&ZmR@&Z*(|K!EuK$~YiXS*UALI^;34 z5QZ-&+_vltnzDdN(L3H+oz_qo4k>f^>It~Wmu#WDLX%w$lnlPTisY|{QV9K3o=Q{W zeTC}W6qZ6mswwu?>GRoP(xXb`OqOCa%rJP|T8(-_$mE=5XS z11l-H)tR@x4RPVwkt+tR8Ft*&WyXtqQ0@0T#j4PVN8vgi9gXhMaWdYkNJqB7m=_#) zW`Zv)Yx>Twb4@P8K;Rfs`O6I8T2&YrCsA1v>7v|0u7s=bGWV(=c$K1LXt{EeE_M}~ zWQITreE4HPKmawa+w?-+}T(0n*Kwm z-WAQOtGZR8fq)=E8k)faa55q7v~$?Qcrdk*YRn+Do;qRa)yuej%#6CN>y)5^r?(s4M-`bPW^e#sHB^V{fHbd9LJM{igC&z`@v%pqlYPPds zyyxg33gMyzrtnH`I5yL~;Sj!>t;fbVx$`hblL+F3ZHGfj3%)s-a%mJ1r?=_AX_wL@ z1+r>U4r>XCSC&%0MW)r9(- z+^k&<$E%S^xStkImb3CQm+Y{s0^#X#RfMZBoU+GhesC5Yc^^*2T69F%Hshigi884w zOu@%z*(^33DI#jo?l_K*c!8f`*PY43VZ%+!W3z}j>oj~W0*4RJfh2tz8SI?GQaNDV z#x;|aWMdTaG1mzbV}!=A6Tnf`9Q(xc5dbs8p>vfeM<0~#&}QR1aWDx>(;5zeg$$HE ze~1p(yK6W-A`+De!9a#lsH$=lJPx>oz5pDv8Dr1gczH1JqZa30l{vy~OmKiw>r3|4 zqd+sz*R(8k3ByA@DjQ!5f**r!5Z~*(H+?-IoN;($R4&f9 zW1l=>G?AhLCrf6JN2SG7hSBAHa-X`E?uEhuZ%9M25`V*Y13#tP8E(HOWI~p>tZ5fk zwKu99Dzl%(Vt?Uu0lJylj?)CRm*3D|f(ASFC#rGED5_5#>!hSsWbolLe)5$+?xeQM zJM#2Z$`0q#IrqGg)rjXDJ#RY7yfLwhSvO5*To`6E=c?;4+I>YJyWWp#$Qf*8vWjCy zD97F}!OZwTPV-u+Fn&k`U8QIozg{I;82TunOdyh#nkO=236;Kq!-7K?)1;l?-lC@B zXwzNTC)6Tus&-`q3Ar}laa_kK`J9n&;+1hB2JzX7F`Y|}Zp>4)`S1lYVYp~pc6jO& zifQw)&BwTc%e?u>#f!Jzo{c9X=;fI&n{T*pIBYl7a_N%!t#=zOpIT<};tHRyNZ)c> z(vo`P+J<@Lk)Asd_p^52UT&M8L@l?Ud=eJ^rhD>V8vBiJ42OT?Z+z-gYk28v9%uUt z%S*@I@yU7&9{;Jw|C?KVR-u#}>Np0s!~OfWKl$X=wZHcNJfYi@o?7Sa-@SH?i@S8| z^T7qPeBjHUx$v1k6=rWP-%OkhTyW3fIJqWeb!D(IXU?3-dk5YxJoecO%O`qBtbefN zgtmilu+2#f;%e4#XU=S0^NUaYzp^hs*Sr4f*Zzob%YzFSK7HZBpKfnoFn^ljdFGif ze>p*{xcnYEy?a(h7@WE3nlQMKLW(>6mp8y*8K`tR3+|{Mn48>t{sg^G;>8Cc=@-m1 zN&nPJ|9Nzs?DxkRw{fHYeB$DDGuY3^-X~;%_IjCCs*t~O622dMlmBuS>~3+{{2S~h zHa5jbxKI84IWeNvG}-(?bE>z0=`+$FL@f_)+<0QmU%$66r>iSF4DKbtp}6tu+LrEI z8|=^%8LlPglmYB7Zoatv_m(fM>Y=*Fzr6e=hw8kL65_0ZZKqJzmRrW&us7tgv%NaI0WKQ~xU)~6O?fztlK=Mh zrPL~^t}n=byZU=qZ=`tE7!;@;W<4jg3Q^dV`|TLqf9emO!I3eq~{#f~{9a z@vU9%sHbj>(Svb{Xr+a7@&4`JuX?;oH_!N$;gmlceP7+Mkoc%7J(h0+9AXEVhiSM+u#Wati zxtQZRCoixSZ1aweTTqmTJWtio>t=yMk#xED(5c87qQWzY=VaIq?+1E};ci!?2uxBr z15T1*L{(;Tke9(!c8Vi63!*eFiz_CWilN-J3obC&D^r!PJ*z0FV1i$GmYgz7{D=X* zUq0_dHKw7VHRE9(MLww^izVFPLPX_oA)*b8tx0OwLJry?t5c?Sf()b38E5=(xNn1J zW~UtRX8a!E=K6{vusf+aj>X(f2i_Uu)S`yOG;oH)q}+-?kaf-((bSe;@nOV0a2)&9 z5p)i)r}cL(#|FH3jj~GwNiU%L9^t5eNKS&jX~?NuwY7~0nDs;k12~(66c(z|Y6R4`2erQ=wUTO}1dQ!VO%r4d0Fe%=89JYu6&F;wI^x<<2h;_3 zrB%Evq*43Po7@@a$vYiVQ&V9ekF}*05mb-V+w1pMMP=(Iiy*A4`L0gzHj_b3-87+A z%=m|ue>3TH3~b>fGS3|z z69lxIuE~j7vc$r$!M_ppgUA$%(g8p$0^ zIQ73FTr=eaaP2h?QBHa!#T0y`_dLaC_N`2)Q zI3O-)@d?h#c9X~<>~z2jx`s&+fx%yI{JVezF?|FWbO!qbQcE2{>2SDL<)OAn3Y}AR=t?+p5VRYxXBOwJDqI&*n9ypYHjZ zlyLKzt_;ZVQE6vXL@LM1zkw;|C`T{K9YNFyf@(;JNEOR;&*9ssd|=h+7I~;A9tJy) zHr)hP+PuYHuKbB54^dL&K&3VkaB+c@jzhQvQQm}LTA=S@-Uf?w1K3BzmB0JUQ!Bj> z^6oRY>rcUxr>nq{$J#&f>MNJ0SlPZ4L?6@l-*=+G+uh^!cK&aFQ`ntSJ??gNkC!>R z32Y6(O<*VfPPek%>87xsxxkdo+d{0PyR&ZjtUJ0PE!a3dW&x8FU7BmV{#(|&@ac4z zG>9pyp>x=KSR^p{06H4%RBj5)Gc=L+k?I&{%I5I$bg5Fr6zO{d?tfQ#cUnk$i^S#lk*;_b=ZPwQ?P*9J6zNC}%z zfX)~PI5Z;+0We1!6@?QX6eM-UX~0FrG`-&V*{$Igr#ah>*q&JTWq2lTA~- zsE$V>am1+{%Z2an!$1|jB$!M#7>!?8|zb8H4-Mgl}~h;yYaB- zR~vydTt5VgDJ3Ui&tcV>7E|XKavH|uIw81F(!;v7vFad}-6by}<;-+G(vBU9R6-t_ z=nNG=RM^X^9)*R;z_pi*R81PTkcqVtXU5jHt}7g~+*|>*0Pn`KP)UgmcI(#fR*iLP z@sPH^@UN{4kn9L*TtSkJQ(Z_zw+@8mV|B@{Rnl{}yW1BM@Fc7{fC0ZjKI#HSMdn#Z zP}w=^37UnWLa);h-1)@WI!5X6wgI}aj?pS$;E5^nwM1K$;f6>ai+zf2h8aa%TAxbr zj(45mh>KTZ0WnlZkemur@vs2OgB&6>8n?q?*;>pg$8FQ(EDOP{c4_S&3Cw{9XRak0 zE2TNL!R3@BaUoP$(V+3fO)n!v;lTrWl#LxghU8(8@_83hjT2!A+xnEJ@vtV@0w)i9 z=qiTb?*dydD*UBH~+* zkp6`w9Jt|((X+B6u|ZO$U?#jFRG6e{wKp4xK@$$XN>CRm^zcg(UhG+<2%Mt0O@o$=+kwR6&*Puk9d z!IYhhXbZxqMo3q9V;uO=*jZn*wc9mzHtVK)Jj^Ay9Gdtc^Ihy-WqETS!CB$U4QOW2 z<=hY@aY~k?+&r66r&x2Ga&4OU&*^@is=rZ@D(oaOG11QF9HVVVuB^wqYIHm~U&p%0 z>)Zxk*ESYy?&`*I4b?bb6x;?jHtm2dyPneEMk_8{FtegS3UwCL6pPWKRGN+7T`EKdpc~1Xf)+sy-B_Bv@g@vqv4EZJM(Y=5T{_Nm2@EL6a+N&h7r0|pb%6W zK#3k-GB{Bl>Y|e7xPP(OD`#HIzoYqlM&pe2Vt+Q6b2%FwN2N&`kMJtsTxlL-JrfB` zyWl3tSjT;2q;t4ms=1At-s#i{X9xj69K@ot>4a9fN9aigT~m*)_DTBsXFi!VaWNhF znaTIdrk+o|H&$zY>R5(|Ju~Ij0l8Px5Hh}<9rC)=_33CfTx8x;gJ^HuxjvZs#>8?w z(mHkLC+ab>e9nDc^c8cWpwd&Oi6+DcyX%L0H6h2YE(ZfQ+%H?V2(_Ox<1;14qy*e3 zucwx#hH0?pcIo=dVeQCWsNHli#okQY5*cCmq20jzB+L$>NoEot9F<}cu;d{;Wz2{1 zFy?~l=n0wh9nmZ4_@h@J>GhN5si(x*oLTAWgnAeJQHr6rW2ST)IxHUaYARhY)krspUP)@252m^t8T&p4Kvx z{r#x>?(3z5hrjp}|7@e)xM+XlRy)p}`{XB2ox10qJ7b{SY;ImX#qZkHE!mdm5RK)o zBaWqBa_`d>$??AN+`ss{lA3+?+2sq%FJAc~Ql!_H%j?&dS8Mae$DX79zWJp^IJkDO z^*U<#{GVL;;ul|yzx7+6|NN_8{8v$aDQ0pji9|hG=MzO_mVW*E*|W{HCSmXy6cW1W zU~JY#ww;%dgi3?|AZ<}*pG+*2X0~SuNf75-_Ng|b4PJh+BygY4|ub+N>xzm|f zBa4B^YbFT%*6KJ0a+5u&%Nt$xjG^6}wUI(KNZv|zS9;d#{fz{dX+jg=F8}l^`~BLU z%|ai8=}niZ&BR2=wLR(a^4W5~{m5U*zrvRg+1Ry4E6>=d~VpC$+tOaB%VT zwZ-zyD_5?cWVr~cQSjiuG++2aUlW&GFPi!j{R;G{<^9X$#WzaXMVpOJ9)9xQKC?Wn z+PcGPAcWOxxwS=EP~>$z7~KC;_y5%LrRDiMrEko`7e!N(Z9IIq!8L1d4z)ULEEpVa zP*YP)eB<>Wq=&xxUiq9_o?15M4F()n->W+C$#b7P_ivw}B&e+kgKcOJ^|w^&D-6s} zn*)WtU0wasbH8K!!NHA>|B1i%OZR^1#v{L%pFO{|vxa;1n_qNWXLrDS=PzyjCA0M+ zh$7wlL)43B&9k4r^w7hXE;)Dl;>q*RFQ1DqFMshRt$-HAtFLaFlP5Q6eCN!mQ)kbT z`du(s9xe}6Z(slCum5v%oo2pq&1~)TwZ~G2|J666+uqs+qvej-%HGTpb%X`Y;=q02 zp@%QN|1+mgp5NTO=X?nbhL66WE`X44!JyOU%HfCddeLX1=z8^fiO);$kYlLWvb`ym8_Yu0WAdu!q_kf z#Lrk+HoDiquUDkdhjrN1M!=BpZ=)*t`ve>N?5_eSVvjlahGDDX>Uw{o3>ChLI_K#X zCc%K4o@on$d<#7!!X9~~_Iqvh78940cfQB87z2?wMBF`NCE?HDq!^^+Dt(Y4Hqfpu zE9ZdHctn6uZk5{#y77H3Oy;<~HZa(LT7^sBqsjr86tM!Y@3_8D`$eb=Evp&pG!Jd^ zj_e|&WylolDeHPxX<)M^IAdFpI&-aMY#;`fk6{PPDo#aLUpwq>%zf$%sNK!%r%FY* z2(B$rwWI;oC@>@%1_EYx7_@m3(o{q_MzVwvm&WG9+X5t1JcByP1Dv9x~ zlyQekRQ?%ExtXJ7ILCBBtmbaqA_&SHfiVI9L_`m>5lxKD0Ss*8TDPm9zP7=Goz2Nl zuNWhFne@VKMnVk4df(g&HPyVGEHq3WuD<4UQHAo&-t4&+pYEaagK zRRD9j1{a7>rZt^1of7EpPG5J(NQYrbZz>QsVqGOoXh-U#bVn7i*)Dg;V0q6P%LnlF5W#)4NN?Nk{82 zqggCM&h}H!ZYM&)I#!cWJ*?qI@-e86Ms8GwdSp94v)#C^teuX7b!5jb#7Qy6FX%}u zxFBs!wz<@P7OQf+@VjnQ!>}x6 zJmf-U=7QnT5b*^e2w=&kS2`=C3To%U$iZsC(zrdY{6>bjY`d8onI@Z$hcniEBn7|( zLM>ikt{4#+o-W{tIW5W;Gx+9g;AeR|qR!D9FTgjo>M~)NG5|p?Jbzcq{583pnKPjcH7)D8>&X=X}B%xy3WN>K5D%) zez@qIttriVP)855&z0Wv$D@1?x){RDXrQX;+9=#=Hi>KLxe=NK3;5gGEQSc1Qtmv#DRcN0I z*-*Ebl%%KM9qzGk(Dm~)nVs0-ZcC)|YJ}rr3Q@wsgUm#hj*C?3tVb9P)`L)~;q!Vl?2=^lD%xF)y3KtC6Qo3857#!35~X zuG&C8*=>48j>pu=vsfr8*8Y-S$q##TK{`R7dMeooZLq0Klfo<|h_is8pSVED3dWpR zbLk0$S0C0qK6-p4{{8U_hlk>kKX>ADC!T!IlkeF^g!lRX>5>0z=kcw_zx=?LANbst zKlgxkVk-CxJm2^SKli@JA4jI#y!INLfLM`7mOr+9a!EoPTY}pB+~$c(Pkh)ff71Nq z=T01x$;5B@{No=GjMS4)zUMtOYB1Q?ShD3$_RoFp#0fAk|Lf$(@|_D?7nIV8FQ0he z@y9P*P{5q$pUwW;p)ezFCw8_FIp$*D{`b^pcYhZE^X26O=I4IyumANIH#hJT^!#p z7!2bROIR-nfo}idzxktYK+(rwwvpal-*sl4br+s^;)&0E2Dd-{E^@0q_g{G0FkIi-B!wG*#_$UzFa?Y19# z?BKw??>|?efWdaMGaH~Ee9;9^*xr86lVI?`1OLSzf6czhX9Sh5fjfo)b!H>GoS!lQ zPx0P8x4!1V*Ic|azm)uwJzhS05XHTpFp*^#smnC;Nzzlun-E7_{94-g0-rYE^K}Z6 z{w684Av-s8tFB&0O7h;`-TBAG&`>cEJh*I=u}N=O+v_!;qQD%YrcHHqR&BoZ7y4npEMb zmq^gAXG~TYY`yo&&hqr><$}7Ya zrz^3Sr(QP2ga7!|6ms=?_~NO1FEX?9gZKa7{pKMY^IpdGpdGaD zPjfo35~bWVzb4&)!Rugv>1?tmDj0KdB|ThdGQzz1W(dc*cR>n+?N_&B{)zWqG9tlB z&iLd>nMwK4H3s)CX^5zNKIUwR%KOgA+V&$yKQ#usPjBhodi=1PE`8}RNDb4w0(w2- zOb&Xb9HDoz+@gH4xs@BtnE@5nHKmaVC?w?=JY%ToBk+;mEy~L_KjsvVncuNdUF=Gc znDfb;^5bsiKyDplk>q!`*UitbG*Y(0V3w1Uzxc{{ypQ$^_}I;S#7Z{8vz3@uTL(OS@G?*H)clg{PR;Tu@w7s^fOl z!HU42!uj7y^Q$*D$Z&u2h=)G3+ zRCn^mb-lZCA?_4a>xI7*lpyZ_nxR8W%BcbPTxPF%7+@l1Fl2BK11xtk5J4U;0((Tq zHO1}{MLM*%DleE0_lEUs9m^tt5^_z%k)K8PaAYZ3Kd;zX%8Fwucc0e;OKWp5m$pk) z)jCz#h8W0<^GPCLinM17&QiX|s8ZIClyWOYId{BmTEDd;KPao@>XCU(241T+;gS)w zN}=XfC7m4g5^5@fgp|x(qJ@{So;%)!j3}r&a(P=&;x=+LOB`}}^=MdIW^Xz_g^`}t zxnoE>^w6WN=H3@AasaRvevW84fmdPnf173)w zQwMM!sZ|tIr99#zHJ7>Xf{t)^$xXGQuNSL4V_t#^-7hDpi)(WC+a9hhePfgP=Xp`>M>k#K2$x3ep;+>hY~O&Ueyjr zrz)xXLu(r3D%Nr1qU&?P`XDrsQhiH^CENF3->1O$De!#?e4hf}r@&1LIDO|B8MKVm zSzIw0AD1C+w#Hopp(CY_POgs?51*(HevAH1SBrngJ)AXkJs&VD>XiS(EjIM0!5LKcuyq%CTQkBS15jziKA4ZW8!#=aIrplbxGF^X=Ws1|b z;M$FRuH1nWPpiyIC0VVBOXifPhVu)O%|(~{DG}hwA9~0+G?6*s7`@z7lR9ZsZOwjC$^ z63$JcXJ|Ss?AQ+Wyqs|u%Blfr0j{V=l&R=pexxa>Jg<8l|2yweN#kg5jNzcoH+ z`E1vfwt;|68f$AMq-7DEF()UmGrImXVYDh6GBBxD4 z6isi~a?nwdW3X?G(V*3I3+9jqj#|*wK6r-dMDDspMF@%UWqEWsX*lnksX2-hSn7rw zcm}baMNwmRo$_b(QLr~Z5N^BQ!;xj?7 zywe-yd&g8009M^d#6WKo06DQVf)@HvBIL5Ic1HwL`4doPxG)N?bKibr%*6;J^a~yr|$g(8<)h z(;4~ghMmcTY}pRG;XZr-tDF`rfTZgo221T~&D7alfqBlZ>R9w?*Z`&Vcxtc9=Z&*t z2an}A^`jjRT~`sVZiqm&iiI<)bP;GIFai-6@GEpm5k%Q5G-w!5sbvj9ck zU~V7-T&v4AkB$vle+-XR6Zft)q`(PY5}!NPGgRxkvmJ_h7#%V^0n zbTz&hPx5+ zXlx|*Db7iy&LE>4Ggbs=P2EN+=m_C*`PTy$*yb7Zk$5Cr8)Aytj738~VKp$L@Ti`} zqMT;qW>}2vEE`!4vF&DA4FkVR_l$V-z=LGN+Gkfz=Yz@AvzX`h3bI5J;=cA=W9qC$ zG+JgkwIEZtewwTFv68qbL4GWSG0sGHGX zvhc2A&8;>~Sj?z&CQzuM3t_~rMx-oa5s;{j)`ITWg|C^`L3BGV}TGZ6{Ky70YbZ>bco&>)}1EaD?XEl z!JMwR9(JR#bE9ssAOR$i2kZ`4$5b_}t5tJW5Gl(k@$KzN7>o^D)m6G0mK2Mn-10 za+GUEt~g~E(b9@lLZn+pu4!p`Ia08ewZkbLSDV$q7iQOu1_-M+O+ilmZrq(|LSi<} zI=>hpZ9>WLf#PV~5t}<^1I{%r`Lv{Z#y&d=zw^^}8XM!AOclUn9T?7O`z%$%p^x*d zTkyqD^7sH_GQXQS=mB5)Op6g;Tu zn7~)X7M4Pu1z-u*+BVvL1$ewVN(VhD^rxQcjjM@hbE3tL`x!Z-*B|M1&3FUKs$MN0 zFih$#cDV|!_ZD1rp-T43+;{H2<%63KBCvLD`{O_J%8li@&F%B&Hx5r^+#Vo z2(e5{5}fPG=_OK3+JE{!bKjK*&4UL94D7pp&2I z(h9&2qqG8Y`sBrvNtU+H)|L0ZHyKzDkObuR_QMaSH7D>e2=L;%S)Y3eJuQlu&5b1| z5%p^g*H2zQDGAv({>5{DcN_UwmQ_w8D2u$Tq*GZxxyV|`v)j);z4P>z($Gmp*RP(v zdgK54liypr$=#TDnUm(=nS;prE-__L>o~nS*FzBcU94wp9m9z<3xh?n%E zu+X~6QW&5g-Z=dDI!WozZ+@w_GI(6Nr8AeY!W|Tsb3=uVYu#MlSgnYmr*m*N_{;%& zOp-RO&6#-OuYP(Tv5|QB?5Cqv;Vy6dp?M}jrWlILCWXu-dy9L#{8tkkc9#+3_QP5Q zgBs=rC~#ox*RNbDLH+u32hVUs?GgPBm#?4K^3L+wHLX8M-Fq*Y?A1@3-_#md_Ha>L zF{fES>d!sil;rFq%MWe-)bndd()dy|JLi?;#w)mPKeWAFnwPL535%X;^*0g*TdGm3 z6cAoEuhT5HmshSmYi;j(@4fe~<6U8(g(qP^k)$>9&CUDof8>!5eaO^T6J#LZav6~) zPZ(^U!j+_Xp`mNdZMo!RpY2Dsx3?(A^XokB2+kpy{tHWv>qRBn^m5{|Zl5>*gY*|U zAnWQC1csHNq#i{ycxf)8WF?s;BMJ469F^4Dmv0(Y%J6!_nh%lkn+cN-fx&anod;3D zCPfE_zO_8q5{*A8w__L-Y2nX&^xTVtxPkz;S(OyElb>OfrVy8efea``O_m?#+t!Tp zT#{;hbiA>ShmpDAGsED$6l||5zFsm_#!H_Y;fnG$F5y?eHRSPfra5f_~7baw32uacB1P z&e*n%N|-e&X9~mkD`8^t+7R_B!ODfkWjVoW9_2(+^Ne+kLpl+XEAdR=6`_m``ovNm z=)7^8)YX_Zim@W>O07?@f2YhGfLr_Tgk=-0y<#U{HJq?b!{fdMu0{Fd?G8A zz#F0-bS91#MApH0cAV4Nn#FEL!W~TL98ui4XJ4MG*xuBd;B!Lf5)l;H7`E-Y;5vpk zrYUmx5IfEWgsxi#rbGAzG5&;rvm%$^HJ)%^K|QS2wZCH6<>9!T8L$f%R)HK-65gd1 z8%rzm{m}`hiE}6?)l_?^BvX%C@kun@obxzKCakL9RGmrUHqo zh|cCjP3~LID16{7Qf_#)T8XU(w2;U&%N)jyc@M_Lth`bVaNA`hJVVDKvt3(R?;WzD z2z!}^^;u?PY^=R?j5`e@e-hEToOLX`aaEVswI487H;5x9CLp$he{*@>P3Ofl?305Q zhJRsLZ5zfamR+?^VkpUnRa1{t?I^O{E5czw7?;&W1Y31QE~^mC6m`vlavujI_{?0J zU30F_@a&c2JY1#$yD3vc8lMiMY7XVr=A1S}J;(>q$I3zdcHjcrN8z{a}WK zZl{xk@^b2PPuU@>IQDsGi_CPv2VxGCWpLyN22z=#E_9Y4Y6~`}&>Bx!nkKe;)Z;*5 z)^oZkJEEn~I$?w8t2*P2kZtNnXVwrFs^wXrB6!S2=OJDV^~(9A8@YBcv>m+TB5!jz ztF{`jzB`3IgB~E~qv_nBXou7bXBn)IYpVVf*-?1EL0(Xu+(ZY)XZk1;ofw#*JLq=?cyXDdIZyStN~k!dcU6Sl6S|JWxo*s{JC;>vJN0~@ z+0R&3b54e4263>^38xLb^T<|Z-T1g*rl=s%f^16=w|S; zi`W1;$$VCujBXI3Q&T3s-5X^s1clemXEY>)__Ju6eLu2{Mt03O`ZWeEVjxp`H}sKu?;Fr zEJq84L!Ia~bLIjDdKt6UYs{#pp5i5UDRfznDM`j2cfy{4(R*k7X*Bdp{MHH+Kqt(b zf9rq#A-O&F7(C0rd*r`*@oO7jleFyfzx#n7KRkT=f+T4Xkd$y{3i{3e`YS)6{hvEK zPoBANdEaBkyzc?nQp+QC;_=7l2M2%Z&n#Y8T7Jt{c(xx{K5#VXUSA&}p5}sa=9N$V zGNCnY-rW2@fA3xSiw|r(AZgiu^vsXBjg7}I$SlTvbMrA$Gv<{K{qJ@OzJmc6d^QOY z%6X+uoOpb*>#kjU;g9~{4F={g0f>(-txX&HRxr0>unzg}L;pPna0~(d``gnZXNf?Y zKfCH`lv01qemPUKb}f8x?QWeVv}cQ{1&@X5pF z);7G6bx=yONCEdf?gvU3Ykh$nwtoJ+Hk-VBO)FGY4k-v5gZO zul0Q8E3X_LK0qoDe5x<($CnqNyfF`K3j@jC3cDv0{))j}_}zqoc&RNmDE53m9zC}n z(P>rur0eT{#Kp@UyYc4lC%u=fHJSMNXI3tfmA*{%nkW6p9sl8F`ziA*ea2-f;4>yD zT&8dBwPpXj-Id7pamtFVJQvvzYcqOz=)0e|}R)9|CG&DDeR=L*CWG_hTrY1bx2>1APHPSc^###w z`+bBjzdAKl!%5>H2yy(`UX6{ibfaQf=i^VtLXm*KUKfY>U|!)czR?QomXF# zo0R5|v=8=%(o8AIwNL5PSCOfO24?9mEs-D2Zo!}|Z+!f{m-;z@9)s;|OFt9{FANSM z7-R_pMF|GW>qi(Ag?BmyCwEO|+G;@^ii7A9OH^inM}=Wv*GaROq+?$hl8s8{)!73* zNDz@=9tw(zQXxI~8OdAHE07{xLyDtJgKEB3ww4EjINmh|JTjMnaWGY;)Dr#NMIFgK}rWLv7UW+0`x)bO+8b1*ji%%m0HJ{Kow!|Apv>10*1V0SOgHTOrcBl zZ*XEznidp6KXQdZgip6LxR&FL_z;3qQi_QO-X~#%hsiT64#POsm`WBt>Nx}3)Dz$= zXzNVn$CWI+tmBlRGIOF-uh{#CV(gMsQy0!U@9ZKo&cRCAxifr*8Ka1L#7%ZlvWpUo zQ#|}tIqs^K(Si#D#wVO!YMFfJcDc66T&qJr;pyDajUCHWurC8|a08)ODBZ^7pwp<7 zVV*_Jd4NuZGo4%+>@_17ocG>U6>ptQxgdQOjKnd|NBd)#7ox%(5^o7V)y_Mv8;Roq zTrSKMi=$oJgcyu#3s!z%t~wQS$~`zp4O$QY)m&YvGTR2WWl|q3=rVz@7`cgye&0=0 z*05*<>6pG@FypDP{Zs^_rHq`+M}9b`NQkgvMbM!e;Y5UdVccwuYyd?rL}K*$*Wn|y;vt0-#>jNhqj zl_{L_6)t5QWi=}lbNpFOBK6#vta8{)7}^N429G>1ou8{}jmNtSXQ_-V9s<*Lti#x< z>32X5SPKUoR?l-YYr#g1IiEv94^ul8Jt)7tN^?$CMlnzk+4;iNp zXn>5%L4WEgE1d{qDSLj=aYat(d>5$up{%_GCt^R z$J!WY^ZI!X2gNBn(QuS+Sp#1)kli2Jb|A*S@en+R*v{2c#Fjm!-Bx7F^B%GHl{t&( zS{%9&E)@-K0J&-dIfoP=Q&ClejZ*jXl+h`4Y|MV7&M-ZfYA96_8mqnJ4%)|Ru%BU9 z&sh&kjALcGqnmEa#uKNauTpidoNYk~=Br?1E?zl)9o|V%sZ{@sL-U=PvXn@#VM>=n zzrw;evX)LZS$2e5HS+;8xY|VsF1d&PNF_U8PjX8m8x`Vex8+@^6yctLLj@}VG!ajlvxqfS+`R?`r9HWh))E)v6V@r$xx`#HQF^`J0K z3bLm+-G7U8vHZ)Q4o>`M+-2f6ek*-n1Sw87@@m1Ypwl$-zPdQI@K}j+Z zhZ2uXP=^;aD$A!F&&72qtX5Jfxa~I2=DW`BQiROJ?G{rvV8X)H8S_cZXt9oNnR$rt z;H9H!?`gV(sE17H6vpn&M!TeuN6wPk2Z;sKnFCMNFG@>{#`80-aufx1W{42NlxYjP z8&^2Tx#5eVwSF-y>fJnovMuVm%SVwaH{7)lW-+OEsorqbg&))=&|zurZqDL6H=MHi zKF;gKgo;dm=LfEWx#x=31(TsQH3$x0N}L@*sSIlIi;8oKs?d!J1Rv~(*2>Cv9u|ay zhMp;g+}A}7t6SF<_!G~zRG|~t1@iNAnuoguFmG{hJ~l6n?_M+%s5Q_f+mnrPqJ#x>Nkiu&GR5# zQRbW%wxCMTpNP+HW9j!hyI|fq55ic0dEfvu<6sF-BkK0zeKWI6$ zH>yv|#|RV#&almy%1gWPqXF}TrVf2qKvCp$J;p9(IZbHRwz&sx?45H3-+tsRvb(%j;OUR^94iFfeV0m2amp~8&#L* zwl@zC&z={+O~o?yk3ald&+FW%7hzq*xeqSxTs(R4{6*>F+Tkp?;q?=jE?wetSXlGh z=F~mfImSUU%SY3Ae`m8h_@!TZ;g>Y_{*@Pg$z z_FUeI!REQmbJ;zU|54{gZNR!P&R!1co%-bI^QWb2e6AC%wzsn^Bi)svZn1am(T$Bq zAC-$zP8e*N7k`E8KRC&zTS1zaPrrQn@Ni?}`pLt?>(@`7{QB3~w~IPFe46#=?WOEm z{npu0S5I9>ojiH%8hcK+u3vxo@MYpT+`vRE%d4MHynt4~&z5I7v1xhw#?`}Z<_k8? zlH1O7Krfd+viT!FV&Es1S8rTBYp#=0*F7Ddj@M6aY``*Yef{e%2mwMR42!e-y;fhvyu zibCpEl;>HxH`(&dt5V z_U6^?E7a${HL7-{#J7uwh33Po#jh|p>1ZaFz(q`Byr@bj6rBp*l$rRt8l_?{WzRe4`Wzd{}FGz(17x?TUTg)&c z80+wu;3okzdLGVkUK^PSb#>W z%mQzHfVJX}&mKcGlPwrwFy>{@VTAOg${eFnB~fD?uaH)NXpD1kTV)kZ>sh{ntaIe@ z2Bt0YQ9gEt#TOGHTJ8(8O9XDtQb@)6C}Mb&lqeEh3(r98tbzq^IiI4;y+L&h_dHty z+P#Rhompg(ye7_O?1TtnZ0r}Ej%Tn!rstSObCy)2gi714in~piJNk2~TT4p2ZI|b@ z*=Lf6g~Ej)9qJoYVJ)K~z7|5YfmJ8grCFk;IyMv@BUwO56z?nx2|%|sBs}pfK!XVORE`P3>9o8f{5fgBj(hkz?CT)#$m=% zlWQ<$$(ZD&cysJ1REoeNz~C04X^}e*5sYlx*v51;>N&&LiqFYJ3-E&?w1KdYj|cXp z?hJejyp1LynkrHyJA%7bqxR?9TujPW#Py+=LoY| z0T5?#03w0b8^~^G_q&?O3RVVL(HwL|NopN{tMh|HMywP+16!?VI`tBaOegTU@Q`*6 zHLT^_=z=QNb|V(*ne?elh@)oMxE6L+SRo)^wNx7hrG`_a$DM7Ca)u+$dHK>nK_vl1RR;{AarCknW&47YT@SWd@WgkBQX}`hrGlT zL{DA-g@;C-cgS49s?&_X^)1*Ks89xM6?h~?^1X6su1gu{NVXhTVJ>XV6#AkuRff5C zCbv~(qjjAdC`?kLz$#{-;&KesoKumJq8$vmyOdjDxH4!Ehe2RAP)T%#)Lt`bD~?9* z!n9!_ndV{`u?G*?hg?OPb8J}2jVu*%w}xpjH>#p@!R6d+>)g!IdTR~^c6DCYidRU3 znpZW3t;q_k9PCtP)S@Xja!!YwZ>J9cjbc8^_hp*-A@^;v*`Vq6AR&39j`}81yHmq3 z#l(&$9B4G%cLPMhsR3n^xok{_)5Q+Hn|9MNtWCWIDZ*hfRWt1JthL+$wQsXBPAjc- zM<(rvOhxPyfU6c zw}vd`PloeyKTM}C6nQ%saln}|;s0mv?PDgp?)$!T?>(2g!>qJ3#;SG=Sv=QS#|uS- zwl!tT>?7{EtEf=^V7*GcjqS?WwP8O^5Ly%p%SZx|JiK#fF;f)nj3ERP(zs_7ClNNT zNH}!i5`4L%jlrOGE4yx>Hu-}Dq*g%`fKN?u#7Rxa@Kh1(^3tHONkx2yY2oTWFxyFturCNj;^YdZ^*wjCmVCFEA=%kGN z1sWre@O1BfJ@%-yz+r*`5TXuQ4LOFj3g3qb+r1ZkpcCZG8aYDfz8}HC8tp zZ2xD)U|aWIox@dwe!yngO;f&2sbtB-&Hj6OKhb?$L~38f>(!VI{^{wX)1{ zm=iY}<^*pSZk3heYBb4KW)(qVR?U0bX~+S4#!S39(+cuvW2at5<{WYQP1W0&MN#W{ zmKg^MajUam<{>%Box-8Lf3v?ghL16^jM?X;=bd}=lfUt< z?Th22xBJRZeCwXQRhoVH;U^D&asRB<@r8#kTuip5_MYaE2M>%aOCfi~R1<=@KX)9I z9&UW%#wW~wzrFfn|EX5>=)%5{C(2}d`a+W0z4})_S1D(SV4r&jl5K27-RhL@{{7kM zeR=V4aq;P=&z{};VQK2{z{s-H>C+Eil%U?+5~f&?%c*2RaL3_yK7a9P4ywiNA<*+% z-CO0{867fTW(!z;@ z*P)ls>)clJYsVo!`?H__S!Movzjx#JzCAkp{LlWi&wqY@rmb}2k284PY@K->2srBZ z;ON*pJtXJ`uLq#r?l^ULc>erLFCAc>>LlXf(c$oRC%s`y~njLYKi&R0tB)}(l+B6ptRwM(Ck!H~l#QRC#0 zLX^W<^Xp2{pFO{7|QmSKqGQxO3ZX z!yAhD<}p#!0HLQmX&z=bwjN08vXx%nw-6+CGGp=?^?|aKNsKGuqGbtryUkco7!C`RzAP zU%2uJIDl7FZil+v^R1tFh5mR$*g=Qm{Fw_6UGSGL{j=?Fw`BR``8^I)n%pB;%o45u z;JtdUs^$TPofo;?5L`C}aH&O#OhEE2S0wkf??Mkg_(2tR04o0-x% zw}waPl)a{8Xe)kvGn61Xz69PIpPnnrLYl>wmXe}*;Ki;*nm2qJs3BZ++_*?t zIbU`H0u?lwYg5dWA`d+4XHq&UNbS?RKpF?46Q6)*quEg1i{6YNY)A+T zoppbo=ZJfj^_1{qr?Q6ff*PntPSilgWWm_!it>iPPRnk{5xwQ!wm{NKXTsHpT}_ww z-Zl{t0E&LLXO-O1A;r!gCjZ~`C?$`Yiqz#7aNq1IB_<%Y$5r@F({D8OpRichP#QQbL`u*}rRsDYwX z2B44(oM}*B#Xq?bS0YdtoS@8@utxg9(vsK6ARB`LLosq{Xv8DH=Gn+Oad@qGN7$D^ z{;tGYL9i~0Y0eVA>>)CNs3j|eaB{wgB`VzG8u>OV%7!-aO$}I>d}R}Aoj102O)3rI zw1w&B=(tr)%~A$^NsVX(Q)NBbwG##%+jPgCf-}hOer~F|^*OQ}YFTs8TBl-%&g&vo z^h_e7e(jwdFUuZe^w6MV4^3;@dP!;Q&X_G-28I?z=JU}S3Lg?e_Jb$=#CT^sjFtJw zRYmQwYlSGx7cSetMRbrch>)01${FOU3CkYJ#6%|`qM>QQ9P~S4D%6?#I1b)79A-i% zBy($eq8YlCMT6UcDPp&vre@sWZy7V*la=^6jvqmExfPQh2*}9GC<_Ro3?jfz96ii! zJo)OY4<8}r?oA$nLC=G54;dld7+BR0R8R@XGads!colG-a*7K|KA%Y94-Sb(%g}FV zThIYP!eAPMLpTHAou5OsB6LL`s#RaZ+aUK^`H+@eryO}ydYK%61U4J8U?7a^g0bMK z-(tB~bql{ia!ZmavbGxjRHG7acO;yF3HAJ7XmxrMWCeSM=j#$(mu5AcmJR$AU(XhE zniBN$59-Qs*Ma~9i|oWk3YTR=#&n|eP%YSv&1P-Jv&k5>%WRerXBX=hAj%D)^44(F zUB8~F^LEkEFW9u7&*0r3nEPp5N^b%J3qw{u%e@j+3YJZ2rD zNg8wbTY-m7w^`m&_V8$%Y}H1P)tEKkKyn=0-qL$~9NYPNTEQ!vHydp!YGM=na-TyE zZ?RbyO+WH6*3kt`6m#ReiDncc{Tf~A(ZcaL01K{JjcZeeSnt!H+#xDMx0*s1HN-9I z7@YRdU}&u~i)zKz5%>|ym0!T)oWUX4r>uOi4Drt60cRi-p5D%JSD;{wmI_<sKw8jtD&gFEVNbJC(hP= zJHfa`)-LB$^wP6TAsVH|vp$Gs0{4Yp!jq^>nt-QG{@oy$(^-Mn=!3DYTDl8)xr~{& zWN&>-*KFEu$-DEgX7)K~u~L{U>qi!?1@=*F*s@NseS%Q2*}+0@aOs^(#izz*C+~ZI zX2aU{Yk)JU4#3H&t~~bBjQN=J$Yv2KJtLK#!Jng&gBzpRQ#O1^*yqr4ZbK0@=2n5h zSn(HDt5wHQvWl!BW!p6weBbV!l*!e)DyFg+sP^H0^_F)Y zp~TNz`09V~Z$A9Sl~Y%4CJz?K@4N4>vkGU=Xp(fFzMGAhiMm7lnB~USebVAg@zree&j0n&sY?lh_q>OR z_uu=-Uskvz-J&H9*p91r#E&}&hP(VuoDMlEA1fb|kL2l+hZjZj&-2V2B-{u&oBkl8k<UG7fBu~EklS8AV(05U2isSS)4R?tk`(-z zXZHJz<$J4>tX%Kgql4?uJae;u_No8&zt)cU>({I5+;!B4zj*G8Z`^$9=Ju(99#Px_ z_H!c`1OjvLwO{yx`&aM#SMQU5azG%rkG;KqIqdBZ}$KA@o9MN zULg2FWzNL}LG?1*!oL>dNe;Jbi?jFpFZ~jsqNRU{5jEq^0N^J|cdrw!``g`)7EUoA zC$08=|1N0n_8=u~qk6x!0PRZ)GXzN6Ap5#H6K=9&DuDr8kKrj#_ zKhe-BHV`22Jvg>Ke3FHp1c7=h?pT;FZ!`@)`W5q0`O78RI#Ha%`|D5s%@4i*OTY5s zAT7=xk?-jb474`zv09d^=+xY%S-t3ck%olUO!fc5Y6%z{LlQ;ANl8bFx9yqW`PLN!sp2` zNu>=Kq;=*Fejz)~2En8S&#c_!#o`_bW8_02*YGPfL6>%*79gnjs%ZTtm)p%rJ~`h- z9IFHcC{(YwmM8vpF%=?5+u~S95K;PNNx>AKm=YrHRWQq~rHU7X0=XJ88LotwhOdkw zCKvX1N+b5Zd`j^t#11~J(bFpsq}8xXZ(MRvP&dx3d2;;8dHx&j&S-&_+&EpsEmu7b zzR8nI2W71ZY0UtGLx0tcVSDA)y5QK&o_mm=x6QnUB-7%zlw`>w zx*CcANMn1(AB1PgsHtL(Y#I;~TD`CX&T;{ir7Qc-Sx-}6G!!J`D~M`9(V%Q$gZ0Z` z$FbNr&|7K~f)}prl6TLpRrW{J^i)<(a}8RCwG=6u76iF6Qhe`oaOjKu@Ns9cTaI-xZPkHq_Cv4LNl^0}&Vuji_NlsOg-~ zZQdx#jySPIm{f@L7(7ttWaf~gv3Wbfmoa{AV=p?ackpDGFgSpr zIU6gGJS-^QV5T&^kA*KCH6SJcEUCmM&%(kg5f!F5gK(>1Qz>~$uErjF(-pKLT@g(K zM|Z4&0Ad)IcaAo5UXzJ9Dngp)385B<)izkz6?Er@EyHB4@!(CiSz@0oQfWHri2e4) z=ehG^2N2O@u~yC?6X~9by)$AHm;^HDBNtv<8z)ep4E0e$Bh|G%MbC_Nq*Ryn^9D&L zhmYq|W~ACqP$6*CEwJN*NU+H&w4AK1(OR!m6KxO`z3pW($%{{c2LOU7r>~(sh48pBb!Kctp?VT~!)7nBBqQuq=*m~y_% zmZq!d?pYN(XMJCIluAZjQsxe}WLc@D*hMvR$4wgqE?@tUE;CuszR z4JNo$$J{Z?%zT}%-FjTJH)GRpXhsy$>lw2ZbLMDLlB#99ObOSE78tQxqBE%CuN>)e zJBMNnWY`&G?u^#?!oj*j;%>bUw1OAy>`Y7H4mjvJz!MlRL9HVP!A#GG*XLm2qw{QnBu8FWQN7*}~NPwYCLj*v47y3$q|0A0K)Z`x|Iu=9IW0 zm&7}QT>*~=RhY>f!w#0AH*_Ra-$lJEwgIY~dM4m@1-J604n=0xUc++3hqlo~MK{49 zf}unqh%{7Hlzl$UVE!_*^VwQN_y(-Xs)mVh-S-^r?U;Z^%QeHI6sJI6q|SD5tpg`! zQ5gmi(+xT9ksk~o`El+UseIPd1h77k@tSA`i=PU{6p# zWeBS+`8OZq$NkP`xIfBG124Hf?ag~V_!x6Z4}>e-i6e&;Lz#lb;~e%malcbv2kt3v za&FVfCog{O1AjJYpOfYR+&9i%xbWf!zV>IoeaFq4r+<{)-pJlruiHb&cIB&G>ADY2 z5^p^{_~6y6q8Ikg^p8GjULD_jv`}B9dBMSj%Z+_#Zc7i{A_2KVm_xbjY z?H#}NYrnQV`u5E?uW~>xmELMMxwskZ5&tFRy!RMc;ybvpJ%90~i$H*~0z!Pr)W3f4 zbugyg?6l79RNMX}sU1WlIQ#U~t2({uZ2yh^=;-k92d@6WceMNbJLV0GayU(V@US~N z`ZmWAi87=&9htL-XOZBaKc6(_u?d$AyUn5c$#<%}PYng=J@7l>AIOFr+<;408IJ)FNZ zKtRMZ+oLG2cjzJ~K7sTNwp)+LUEmBZ)qeL5O^;EBd*KTWZqG5<#e8OqtwS^x(3s!L z;`h9cV>^1MhZCL@PpQ8D!i5V%>OG!chwq2aEqW)?4nPn7S;fIr(_B42P(WnX zlpue`J4+v}3wSRHhB#}Gm;zVjSY|;4@WE>xN$B!Ds)DIC@DyICF22S@lVRFRxtFAo z&)_JM9g?VOrqszVs06B78=HGN4nzU#vj~mdD{JXbLUVd}H$KIu2SC8EE~;M#34h0M86mPWv zT?I~+g!Crv41{MT5s`3oLLB==O%t6d+_Y=-PAcfLtm#kzFm)~XfYeFV5{*zok?tCY zTpYUAf!J8%g+FUiR2Ao3fppv=byY3rjs-0Gmq@*bejiBR*(w-g7r@5$zmAnPiA)+{hV+Z9`C>uev%nF1E(! z9^c9>T+2k#sVtW3iQXzTv*6>n)%;QOO!Efy#Ca0{g*=Rkgb~FFV5;_FrcT2=MGDNA zk($BMH>C75910#)9QB*I>1bRkfc-nqIE-cAv>=fT%zT7U)MH~C+E6hJ>*JnH#5rME zX{?8rL!q>9WxcU3Z)%3@*hUAsbL-)0nJ&=8j1X;qj}Y+I+Z=qQNx`GWYrLl?1~nV5 zWTZ8{o+e^o2Q*VOGPGK2sL9gK5S*^J%7crz2K>GncA ze3b|xnvaS_PJgNql7~Fds1;jVW$9vCwjEr6O;gUWkKOpT=&(ZO?RndAAIxbk` z=YAlBVY9WezRr9*S0Pk`M${)JqwVxRXWNH{CKv%jxNL!r2r}ykw}RFrZ6yHFYqptq z1mk*|XEnfP%xo23AxJ3YgrF89WRtjHulBeo`e^3Pp>>Vs3=*YrkJ{;gxe`BR*KiJ#(+6W@0Dn{Y z)u>ovp==u1IRHh>SrQZWrNcAfv*SGa8nV4uPSn8OfNY&Zzl?WMoHOV-b}I5A6+gi5byV{4K)h*;>zO6FlNA) z94Ac2uEUD*OT#9dqR5dB*Rx==6=eH}#-7{C*(G;u3bdY<;zNPXyUO=!M4C6uYiQUH+8$G{ZRB=5!xB96 zC29|&)g)UBTy;29S%~N}N9Tw!tDNgPa>^rZjLuH<<94-bZG>I2i5uUTw%<@`Z*spt zHHhu{6&m_x6M`CmdRIlW%BRe!aOv{WQPC-zz~-e3y@&rkF2iEl=Y1_6|H9@TDxO(k z(v_iujU>(in)9P+8BK^ZQEdWQ?5T6%RWfw$>G76#Bjaz1clFV9pUinq;f8?y)9!v% zF)xy2mrY7REZ*f`r+fP`lj0#)JAL|Y^GdbV>9LCRPrmisE4qL1gGX95Lv!r+0rMim zZER1Mzjk^LGWfB3@kRMa_Wsf5e&t22kF}##D{J}7QoCfQ_POVuKiK}z50!VLx{D}T zL82o?okJaLB{`R$z2_Z2q5B6vNO^L*b#;2yMZ42+lI^o}PtQAw3Wa5R?fqX8jd147 zSCQHeREO#y*{QYfdEOlS&<~k&cRyBMDN}v#=0w>qL8Xy{lfJWL@Xx$_=4F+zz4!FJ z+b6C+adchc!NI-!GBRP}{GUgE`}!jv_*?J$t>4<6G;AJw?815F@X|})Jg42mvXL$c zJpz4_9C5zwL+7?{+*!T(<)^~-jW)1%`9oOTGGB`~%ohZ~^PJB6a*UF}KNHVHm3MTn zx%cuD<_Vo%J(O?QKQ0K6(;r>G{^=k2l>4pU8qmbd950+#4(HE*^Bl-LBOL)jfj}R% zg6k>wH(suUZ1cuLf$P_t4%>Aq>l(kHI}~s*G11Z|@1m)%X6fB%%dCnvdEq#V_lpi|x$ornT{?r%yqaNdX+oLmIy-PaUM=B9>a$KqQ&_wnAbpCmnt}Jf`bA-}w?& z0?%LAjW=`ZE2qBl=2LG5ilXvQp1<)CDWo54FJ0MNMkCo>#q&34m1O-~z~N3`xa)$* zWQ|B^7{Jv@5S;qN%}=D-CPctZx&OcU%C7c9LUZaZ5WMSMKlM{@hA)RR^g-#T8-MVb z8^k?<;LN-2g?C`p{l@Ep;PMq%oykd~Wx|3o>WyB)auTkrHQtR}JvY9WKMu>UbI-kI zt{t4GTjlAIYVm>SiojPI$42Ft1sn5_5rx%>ldq=7Tz1__RPxG7hc%}D3cbv8k0+lz zev$IIMlQyLJ)}yMC9mO<8_(b1V@VO6om+~;g)*S2%+=;57^j7hCSrw{(CR85U3urP zR}gE2sQV0W@2uldnMLgsBrz$*#yI{AVG0r8()|*xa^f5ryO6@=sqArjr(ij)J%S#{ z+gPq-iy%@Wzh>-==^dzX*(^m$*Y6|Br%tm&AP-m9s*?3UhIEKStytMX13@R(#`Y$oi>yfDh=vGs z=Xjtv3tU6r$W1@<2pjXwl4bf#{Ck#jF~#=CG+4)gu&Nd!r~u*y4@t~(WW|OMm&dN1 zmn=K-NHrOWw!@FrOkY4EBCVnnO3z zreKTj93Udp;72d_#(`oQ%t^pwZ0Neq+l@yrm36FfEHE8ofp{!(S_;TsV`N++|K}LfJ9L8Q(Z~Ph;z5f*qx0?5%6%<;t3Z zOyL?&9jPm8S1Um$W4gy*byddX>Ij#g>-AVV#}X0c1>|h130xEK0Xa_uk%)9xOjSXE zFJcLCR7R{8z^Xv2z@o1S-=wNMJQQc4P@}Sqi1Os1GMhlp^u20L*98-kSdZgYIObw8Nj$9DpN9&hrv1d!*`^uya(! z70w$+BRQB`bC(f$!MmZeY^V_>u6;2kvn3mUftv>DnmG~XVOhF{=*FSP+_O5?GtRg4 zV@vwPe)P*x3HmX@M;DC7l3Yy>&cLF@r_lx&XH6x2CMQK-2IN z2yzmAPZznzbBQH3j)dxM)|o8hOER}T*r>`q%?#4;hcbprt+I*Z8JE%EJx$Sr0JhB2 z$1C5~?07d=Y&V_WW7Ez1%6K!RAkjeOJ92LDoO2S?obF{&r(Zz*=2<7gD9$se%x38s znw*zK0hXqrSZkI&O7xzL))~$%`_{Tm%6+=DY=@s@t#Pi{FhbaT-DGo0s!Y?60!NAP zG*QUNfT?4KqT^AsB_q<><*ej5e z`T?OhKyV2}h0+zKfmSg!RIPMq`fQPD+%O%%Q=h=>!tgmiYR9z6tkdUNIiAIFqw#Mt z{+Spdf?dY)#PjM`b2rbI79Igpc%OM%6Ji?%L6hQh!I(PDU<=CxWX5sbLYYDsPciWi zHMgKqXCmvD002$cdlom5!Zu84D$umeoZ%*(3EfqHHK8*`L7;`jp=2g@y?O$A2Q-KV zH!M}nNjxW)2^xB{r}A_1$p>%0>Lb%`Xg7`Nrfd3z4@fKm94Es!YHouqii*h_Q=3)O zn9}%MW2vAdCJkmasO*N#OW{2xszNtfOmq|FBiOCewn zhW){^p?=}P3s-O6{PrCOrw_MmFu$M-9=ysPS}3?@|IR<0KK=BqlJCRq;ZOost*G}u z>AH%%NOwKp_F=jwDWd#{!7gz@kmAUO`uPXXUp;jyL15Tmp3wH-)$`|1AD%wE?+5=} ze)jCG5XjnGO8S<|tq{B=D823>_-}m!Pn}anI~>ZMx~MSOSy$}s5tzX} z_~7{qhbY2t508ii+{mbDup@;H?&+tmerNgZ<+leKPBjx9sJniWT0^02Z`=Ug;C^@? z;^>{Yho2|p=xA?GU6S#X^A3WmSAoD_kPHZjy_KAv2D=4YogP zB=OcfbFybVt-E<2ix)y2G@EI{^MV7p7?A2O*Z}OtTISxY>i*Ja&WJ3r@m@9-)pe1 zChDDY1WblLLW1D7i>&V5fL`4``Q(#7|MNe;eJozTe*fkBFYkAw-x^su`g;HAZ~c`w zbw9N|Gc*n*%GUV#3zsgX*4)`yZ<+yu58^NlK#Bn}r9E+y)`NY{Bs+f|>FzNE``zd# zF%@fo!2agDzO?rz&#(g{@y&E*+0dtupzpX_iYtjY(&u9w=&ZlQIWyZ+FKNuPDd4H6 z#JRYDEq&4Tl7L^n^3Wsul603PzWuxGAnG}BMc&Mke=-=)(}#9DXT+b|$4~g*QSmc2MqH?aW3`{NCJ*%{K7s5-DQby?_>v2&!~DiYdkA%8Bb|#;KK&hg~mGz zB8c6P)tPPcb*{*K4T-v9vEuZKOWtWxhR6(AbeA}I=d#C`uf3!@sV)5y%b-61_=hFOd3vc-Pv5X14LtB!JZKuq{u{8o6bP;mY*QB1xVlZ=OPWklYf#%y?+g7cFY2UFFWi465+bNdC3d^u8 zm-@~*3-!x--%VWYd~97Hk6Fr1OG3Fue^JG1r*O?1)gvF4o*w+Oh9TY*!U8=xWUL)b z5T9zu@(P-56F1n!MsR|N*h7I>K&g7)mm7z;1~JiWE)qW5U}`61wGV1vNGhWp>L-St_Z%@xytZoF25yw}y3NKogr~ z7=*C~D%;&VjkQ!JHk^YcD`6rf6*O(r`VOGT!8k@$&mN4f?-(I9G`b@z1mtK=jyDGS zo$pq|b!dCYupXot6IElXfNcOvQMn~AkJsK2S29tU$r48344fSj-LCoBs)Z4gVN|;BKo5Mu0 z!T2~P1Bw!seeHpV`H0m#)eEGr4O+q8c9W8m3?QgsJk?xnqWe`TK3RUv@0{E`g+XQ8a=eNBc4b$XOfHQo`7n2)W1WAy=GLE zz3nQRz(T7yCRu}vbVm|Lfaqyem_bW)A!0WvV$-`7tWeM4e|@W@}`XShYqx-nowX z30k>dSh0M@H3HWjVQWN|zR6nhkVMw-fQY-*WY@3fHPaKQMPXx{t@;+SFNtxDLsaT) zgUv92GxIsTay^XsS<{9tz$}Hxba0XK@pQRl!+&0mHg+009jlz71K!FcdhJk0hobg; zLl=2t8H`}h1ejj|M24^q=pmUhR8>8hdV*B@G>2W0(7EsQDtRZyEW&qaT++4!2DV_ z9&<{aK`FmovpFWZ-r9wv);$_cwOWrSHABX;gXWJs&=g3UrQEef!rfzgz%#3K8g{bkn8$M74+nMY>>9SIgkYmUs^7&Ho8 zwNL?+x-uQtKEu+10~q6-0~$vOy@?R^89iCP*lY7}SKAd^oH8JoXGCV2f-9#^FYXLq zU^IsEE;i)E-lMkJFad5H>QE++7)vi{HM&B}vS=2jop=t0S*0|5_5;uaN6ga9CTvz= z;glvomjmVeW%6pSGLVV z%|k;BtVuu5hGIn9d)YPA#ewXqU%HZXZ4-n#g4oj9ufF=`YtN*}$!0h@`ilR} z{#>v0qP@^c4%)SxN{1$r*c!?E!CgQ2Zsei|oWlOhnLF8X9+G&U3wHKBG@YymskV_x#fG?*$gQgyRDT z;pkfqY-yjr=)^=jV@O;Y1DD}1Nh+Kq<4LPLgLoTcv6j<&Dw>W(3|WGC&-bQ1YV4_BJOB^sL1APDyIZpqdadghrcS42x| zxB2s1N3T;i8yves_;NkF{a^mfKh+m(*kez1Zk~$q6Q4i}h5Y!3&+`XBU|$i$py?C4 z-ZqJG6Lu1bRD(#I^N7Zcmaj|Hmagl#aa{Ftfb?MxE`U5O>E z_vB{skbFCRhsS!vkG`hM+ns>qk40~tN>h$F-qSU`$WMzDIfpr_ENJ$32oDskhEiN} z&yhq%V(M&)gYERgtoLQpz( z=sFXOOMe}FbsH`3YsCQnA@8Yhi_bh&K6!IVJ%_e|22g>fP(apZp$S=Sg!Y7b`Qns+ zZ5%)aRT-BugBGNctj0Seot^2t>2i+1VF6uuU!X}Y0uDfJ z7?K>tLgA2W7dCv5dt)KB0Sa7AlUlP-E_+iI;p0;BD&c08jDwkqGsCAGJ-dKN73J5l zy7R$IvaXM&hDd=V-{hb$475)RT4e1HaB6a4VoNO==vTmydm|T|F^M=ed0$dZ2o=Dg z)(+x;oRZ0#y5;?l#zi}4RLe>L#+7n@H#`2GGA>`%OgL1b+y(e?6apVe! zDVAd7l?IauilyZh=yx=LVIj$KUNQNp>>d$PPpzSEM-85{(W=6}m|LY&Yk6+TqoMm z_Vgkjya5A*#F?4q`v_p9XCcTaY*v;vq&5N1pmo=vsKcT=NPz#5!=_-#S1so)0!qyX z>T+YZX7xW)+nTc1wQ%H%#;K`$>M;l8!*t-I_c@#(vDqvVC{tCOHiO>rW({>7++QsU1X-ZHu-u z(}&Sgk`+Bv6D#1XSyW3`Q39e^miT?h!XofWzw-gre`KpBnl@!c8+xE}^wuKxy{}MV z&&M;YNM|7$X2gJ!2^vecppkU6CFz+$oP}BCdDnPy-1wz}bOWROd@W6D{%APf1M}0; zkJ)ygM+9ii)Xgvz&BsS;9bTEW)9u2&Hn430O@0Sz?IFaVT2JqmE! z6+N+UVQW-*@0z?}!Ef+lteL3~GgEE?tb-6p4Gd#iF`YrSfrGH5i+I^)$Y%_^&76Lt z!82kYW#r!$rK4(=*&&s;A}KKxv~x+!Jnvz*L5AD8 z)MQ;s*|NvGpZ9*5tw*T!A`*t1x7g5r-MDhAYL!j9YPN34g2*ZeUPm5d{q*Tpj z#?f~41bV^H@HXV|nK(YaNRSx0i4XZ=GMmB?m#WVcPF~}hdJ~K_HAM-`ilXTOp)=eA zRq)&~Lq3ihuovf>(tV({M{ahXFuWn2r}N*T#g{!w~W4d846i7kyT{ zsdr|KVg!e77O0)~I)=?InQnXa&onK~Q^_HHr%cbsV?nm_Mdk@F>1kb8BL%1VQ@jEr zpALY~Q=jAI9NxkfQc#0f~(*P8V@^R)ReJ_y={VF_9F@z2N<6;LlNj9W&*Dyq(4n3roKcR zO=Rf~g=-#tRFtmy7=F0Pqh@#?Ub#LB?Tjk<#pI!sa*1Z9okb&`yyK6TlBDn<=NiBm zPXPYF1KT46-4{fy>P+uPI9WKYkCg-N`M>+z4AbAN!3VeB@2#EQfBy8(9q#?vr~1b) z_~#ct_j7xn?I%C^$?bjHJM^yg@m>P1yH@-1(}MYd2TmIV-D$VBa!>wMQe973{gwCp z$M$%$H$H+=0Z*TO`t1Jn@f0yZ@OQFXAVBnY-+gx^2oysl@9%qh<9NwF1l@Lht7QAF z@3%$1?d9J-<}R6bT+2a|ymaxUhleH*CI+W-z9m)OzaOU4#U;T${LfBeDfIOAjt6gS z;acpR_IZDcgT@mbm?YkN-0Lpcv?SuEPfL=mB$BJ2zjz)9{3FKibhGh4`;D{TkYs(A zty(aZp}pX@LvY7~=CrxN-`=s$oAb`!0)YZ=hv0-NCuqv=8o$8Gh;zZSUuWD)0*;Ni z6Z`ADKTe!~fcE(xTOLT^(wG-NkKRqpUp8M*N@)0{fqKt4E$uJ*FFcoh)^yxI`tfdU zk%&K+T`fM_cuBO?FNgjQ|3mbl-M%6|$>qy0zbyTKwm%$*iWiSYMV^MN*L`q*`(QW$ z?N+M%=6O=EJ>bgrN{T7V|H)3;g@>TtRn}=*0c<>T^QI))I{i#C_zEf>YMwAQR>LPr z5Wq;0>A0P4_xCFu5a_mZdkAi&$`1@MP^-&32%4t2k?f?Mz6?kJMf<1Z?aiBTZpH`i zIe2P|=vlyRxlq+q(%v4U_JwR;6q;mt4Y%*T=|vYyMMRZfhAP+I1q9)z&p8FqH*lq_ zC!!s2W_uSV9*&NF@+V1wd;XOdUngHt;|FgFvggT%`ySiL4kPhoS7NLLz@XdxINeX2 zAW%+%K(-AN1Si3!d?zaPXa}4*1FMhx_x<^iH=ae^-b8)uIsk19AE%7(m_GHWi?L(L zRgQk9^^m$JU!>d)Yb3o4&g~yg?kTpuKS4xk@~`)ygeB*8chEFANGAMLJlx{ImkJ=p zaD2%m5Q8_*jW2p&-9wK#ar-RyKETh}G<DwKcE@6*CH!iTO4PE5f<-s82fkrK~s__WS&@N_)=#k){SZ}_j%+iep1?#-!Uxy}j4H6m zv+7Iy1!(uY?2CxxsP)l$1YESsm_u*Id4t)jh7JR%2RVqO6A-99jwPtj=mr2lWG7!6 zb!~iVem&9|r@WDc!X5vd)WpnB8T{sR0BmRqwiv5_p%0M3G(ys)CAA+1C^T1vu5}(d z71dEz%8*2ZYgt$C9&fp2!*e+HA`i#Q;BNzu+L@@8Z*ophIWo#QBdu#_FaC1xp+`GZ zA&Emxb@X*d52-h;p=TCm!|FIFC8l?1Eu}p>2!f_X;$~$KQ z(P6-3j-|3C7Swx<>(CXxahBzKNq(9~aYJtetqlM;qo(m$gBm<{y11f{9IcN@?n#4B#AgN$ zB6Ci&hHf6iVoA`s1Z7P)`R0Af%=qEPfQpP*W7RtdR?it+5F9>H2Q-jLIguy}c$gBgg|yfiy7_>f1_0>12ahosQ3oZH@EPJ=2^qula7Jl z=|vz;7)cOjcHYNqoq2URAg0G=$Y8St=DWI#)9HagqDF$|ZJ#h-Wjkyv`reUlNXC8V z793iYEhQse&BSvdTtl$MvNfv94O1~44t)>0QE34iT5uMTA6heo%3tx`_f*TOQS-T@ z8Co)sjWTwa0Q<%Qi)p(J0QImXQ11bESZgCx=RAmeiXAo6x;E>(e$j3q&YRJwnz`E1 z{ikcjAl+qJuT8^&U+_NI$WtO1Mj6D&E_+>UFtN8-Q>>6&gEhN`HOd+CAU~j|4ua`4 zsN?f(glbP+mUqfu5`_(owVGoZgleRpopX%2()SG+*0dx-_^1d@Q(%MmU3)X8v&sbh z1<2^&R@&Df0MdVfVGVXTPYDeC3cSMz@{myDIA6_iD-FE^B@we~5F#_XFA^_@1bu*u zGn#Np9dhY0oI(qz9M9Repe`C~pz7Q8I?n0g23QeALp(3Cl9?oj8h3M=c>|^1quGFp z0)2nP&k}R08Qgl9&r9NP03-lKBZl#!+n`=Gnf4tl19;PJ0lTLm`^lordTwARBM(M0 zog{Dl8fxBq@S;5W>8zvDO&=+wXF3DFD0s0;yw|)&VSc^TSB)Ow=5X&QUHjJM2qfpZ z!#;vzoUV#Zw>JG8+nb%J^BhJ()XXo|4*9|dL%YO>ay98@%+h(EBNVY=G;8K74aVGr zpnsSglgX-@nBW4|f@0JD z>1TiE$;ag{E9#PXCd=3IICeL%Fe0jBU-SKapuZGNK2J!(n~?Q9)CD9?Doy8eU1x9i zg*(sR2?QxmgrnDg8>b!HlC9qL?jIbdfCK>uNGX#KmzU1B&&bA!Adug19qvPUDqm^N z0KvaWMd)2F<#CPcKjwG5=i9uH{VpR{H1p@u-55H(xn{0%#h?4*iq9|b$_F4a>`f8fVe4$;g6 ze|VQqN{97<$A9O^XDP2j1iu?U$=(6_^(iYZqFlk>R%eSPzoUVM)@Xj^6?R;I98HVM z=v+K@@PPONa*uEqROw|0fjE5X_a8ce;QM8LVEpbMybJSksU|5tb{n31MO-1wg}hTf zf&h%=ESUbr>n583MtXtfEX1T@d_%T0z zI(cB)-?`mVJ-vOeT>LP@?n?BxmAubqpFww<$H~k52@l7cdTBYI?&8gMOR*y1QM#S{Y>+QLuw?R)%aY@w?`&Q>pUQT*KX-d3%goeEV zHT7KJu&`-uq^w?n>ZJkynf&H5#BqBY`9?#ZOP^61`%$ z^xVM(I}_8BYUE>?QvA{gaBtnv^Jq!z2J zPMiYY?v8WyM31bVuv0|gJu#QY0jpCsbyuY10;D8J1dKfNtQ9p*g+;Iy$pJYO>v4W2 zdW-=nxE9*obskXVGhjs}%L#Tl5p0m~>M8u$p-20n(~&_cbPsz14Ns-J&Funi z^P_X0c=sqSV1wyxZfq%me`+;{_KC)MMg`1_uI_!yAJF@yk2ykWp1l(&2*PxQqeabN z&}e&oG!bkLcoI)@$qV&Tol~<#pPsnvDn5klJ^%Fnrx^HC4E!ku{uBfMzsGjdu15)vkEAu7)=G^VLb3r-VaKdIM%&I`@A||Hx$Hy3{vq9i(O+7E+~%Lbzuae& zhb+%(1@rYpXN?5C$bhqlY(|$ikHc6wvXUbMttwlNJ7a@e=HvMq5C`b zGV#_=3kpO&Zui~n1VH*r0ETElORDHTsqVx|Zf^F~02Qm`6|w;P+BH^hu2J^2aVli* zf?&@IG;+8F`9{+>S)Gqc;}tfs@a;UuN0SGdm%Fr13!~lA5Py;l0xz!|l4IQ|RE#bB zOjN%z$4k&=V&DzOFe`?@_VD+#--JCnwy2{8$j-Q);N(2DELDnJ&o7D3Odgbc?=J|+ zI+WZL$!qC_VIpx4EhBX>D~>y4mH&s^vZWXkeC%=uG@b8Za2*&a7`XdgnK zbXI)NHVaNwb&eC5!6AFNl9(~+vpEv(99(1Y)=`xrV|hu;f-$qPjta!AGw?b=tl=7b zZ7WAI-jGG`P-ngE8xtDWb4--g($zPvw&U1EWMCe9n?Sr=Va%xD%wW4f-lSfOh1{0y zJUh2^&QQEs#gex&u3YXS+h&n?l!aA2gX^rbvmTaoa?S3}E=pp<7)Gwff_q6%7Bz=< zU}V|ZA_0vMbJe&<6oTvxX=m@In#~MCJuV?*$(+Tq&jO2a zN5UFE((KX$ER9S&e#tq?RaZ0~xdxRYFE?FSS1jlTWeMY(y~7=8 zs`^@uso}g2^9p3QSa(G&0MVzm4>m{)Eym4!W7)1sQ>bV5h(XamOe1pKSgMh`nzttB zoM5mCdmhXf{Lnh*9)GR?=W+D^fP2eCHOY=(nr7h6`)jOXGmpmy|GhFUIjRz)}!&vE6z0nmf z+`4F@?>Ak6c*K}mZD71*R1s>}pdZ3yp|=);>wcYg-dKGOTrdqM!1I`!f8ox8j;C4wsbdTWN--;Gi60fFB@kZ=|PGn$4vI13A@Zbvm&;Eq{plw~gOTfd0d zwq|<5BL_jP?+NE$m7P!?ckLQLL=V>S8=AqaF*w&`S!-t5Y7u)P&cI0p(0)C}dyBKip9k2+%EHbU~rs2Tp#xRQ!n%tU*Y**=A*{{N+VS9M)!ve8K zH?L4}c5rqqt%{*J#@z_zU>pfj+Q7^tiI?h|CaLdB60qiD-i{{Z?`0jpb z|8C5qk17Z5AgEEMU3&l6_qBfSpK`9rLGf_M{u&EEb^4v@?4euF8js-|TN94E%if+?W6P_%E&gDE|-Nb)WyG&HsJ%J6FH6%i#zJ zp7`IteR$*G$or3cq}{tKDHdAjrKdaCZQFEGC-N^L0 zR3LckdDgNeHGcP7&-or8KrFZ`!F}3&S|Y|PkG+h=>RTYVqBoo>EEjbd_QlG|wfv7b z{ph)`zVg)+f|YXJ<+QhVcrxbh({~^H@BM~xyWhY1)#9rc6yo0Z=|@tGosIOp+!?b@ zr{q8Ef*l}`m1~9cCl0PTEblKPS#7E#${%-&3nc~cC5TxDoMBYQd z#^eM6`HcCxnv$?u-#yl5RyRGTd&3Ge$YbyDwR+BUaik)R9^dZb+r4h{@%pX|xuqO; zfq5vy?lD-?8_&Y#)^Lg|QsK5GT6!YRcXiZFalWSueD(>{FR=3ZZt+421B_c-NY4o- zcZ+v=^m~t-hdon4e#-rJV3dJ=Kq+TUma-h)l21y%k9OieB-_<}eXIZRv+^ADU5>qs z8yFfxpulWC6tMYYuV%rr*mQZ2@Tz~mxVt!an1;o7I0zVm#b zNzqX`R^KKM$kVK&boo(y$aKZkwl;NJc9ol{Gmf1WW&{<>$gW1HX)|MSPeiRlaY%Di zMS;Y3z24U?bw`Cay5P#Cv5*MX_Y{U<4a|zL%qa|Fo4ghp99yiM(#I^K>FC%5XKN_S z(iOnK0)=IlAkK|*RmxI)E|M+-A&$dhwKisj*oIr%7~l~hE$IT0nv(w@N(-Bk<)NJI z6AtDs?|_CsQd`Ku^@?3%D_}J&&_e1OumE^pWL$-13fy%^D*~S~(h?D0s~-1OCzHfQ z*8?6@)3V9E5JyawuXD2m*K1$qK0tqgjx3t6q@WTiqM=r-#YN3bHy9!rkDEAdOVRLb z1Zz+aQ)`G)uUU1b)1C04CVk2u(PQDri8qRirVQh%anQHCae5P#iwXde7%~q*&_z?{ z8&~IO=;LWOB&38A>8&3N(PWL=b+q2V8=CYcW5XT!*@$fv1(PBOKbbk{T$Hm0&}cC) z#fo3rYpBfGXkAxloRpHI8ot6nc5Qq_b$Ry zxicz?!k7s|PctC>RQ_ES<{Aczfr`gYY#<%w z_`=X4kR@i-Qn`tpuIGV1h^=@euLPs^NIBTn4WSDqDW+3!$Ot#pVlrY=E!K!2YDU7h zDj`;erpByq{meIY@77r}?j4&nxyD34$Gn6=)@H)gMF&tg zj_bVL^oEa2v+(RZ#Bf)(Hf@$=cF|ATMK+4eIa4yB_<~L<;+oE2827U#)+_iOX1xQk z${P3#G;Qza>5N4E zb~CQli|Mouju?cSq5+2``nL7h)#WT-H)S=SqTj!nOd2#0$F*BG8jz(4upKDg2?Xz( zrCUsw8h(wRdr;5FU-sxkHfJ2db6Ph^n6WBZ$u%C~@Y&@C+0hkBk9DgvN|hh(j2{6 z3?tFhJxxM`nxwfxOBz~~)O_9h%rSI0u6#UiKEYwQV)VUBFtgRN< z`tQd@-PBVTIM}c$xLGgbw~Nqj~vu_!FgD)YEgJ7Ji|3i!iFEZ z)ANO6f@ZH0T)Wa>3u4yfG1M0aTDsoN!FLSzt8KbpyvnfPe^14?&7<=j?fvL*H|Eh4 zgY?5a(e>kbNAtJNf81Nx}Mf z{uioO-|-6OY!fAO{juwhDOeD=_x;ERk_A^*_R`7Ix?B6&&iudZy$_5f$9?Bl{cqK8 zHPZGIRu=Ez(A6<*?w)Uq0XJ z*E4TscS-XE|I6t&^Sb{1s_Iw2s;;hI)vu~fUOO4T{afB8zx5Md6)(M0V{T50y1oYm z@Z$1v`3p+#>D386pJR*Onq<*!iUOU|3(nFjiBt6lW#}9z-DM;R?eU-a+4sHtwIBa6 zoxAk>^P8K}lzn9R$dy_9N`Pjo_*#*T3CpE)w(!pSJbne)XK(M1-^Za- zSER`)Y)Q~(VEv3r-rD+wU)Vc!<_s74?CV5cfzE-Fbf)`^?*5Lq+h2Y1OQu6*fC zf7{X{=N~cu>Nnr*6yC=$W^?nUlg}-m!zpRX^CskJ92G7_G#3Rr)#?fqNRyKWLJK%u z^%PLHUwGs$QE+wtlUHEN6Xq+($Ze37xnUUh=aY}$%Iv*V3Mqv7GNkMvBd7BJfeYp{GJizjdkLpcMNgOy7?0l?sIG(ayfl?p2XNuBexqe8>BkzE;Zftj%R3XKg67oa6P{VKgtGH60;8IhfR3k)Xjokw zLi*eok7y*r-;8mAQ8)vY)TC*Gg$56B0wHOn(UfLchfhuLK6o^ijy>|YJDH?VryVXe zSV6+vt}6^3dmhg%iT6X$5H{nParpw=blS(om{s-87b*_n;gODA#<+mdHS1Dk7(yHd z%BEFO$9`FZ8eNJi@X^pi*IJr`XE9g~$UX2_Syt_E&HJcNy%r*CbLeid&ZvW164axL z)dJSER_2gHiMtx!1ng4elb^z6!rbs29;+|AK2VG+RDV+i_1R5H^|3sjEU7iQ`~t8tD0^LX^4WpQUGchf5Q?f&c=2rqg-nX$5z+0 z%#mDZtQ1sb6*yDaVCf&UsG3!cRj6ixVyhVn078?tnrb_>NK)y;JE;biQrEVYrwMvH zrd?@^OYR~R`k6%mtm9{8>%l2xaA3}~q;df5%GQZDR%vw3*_4$y1&EM|F@91h*jGt6 z5v4AvjK|!yN5dCMmki-hnRKvmK03leItxX$bs=XF)9wF!Ci%L6K?vhCkR7O zP;=_>&b%w9NaH3#qKMjJ5y7Cf@bSEhraK`#rn$tsgdfG&oujSMV<1X#e8EBZyyjr1 zZg;nf(yGs)V}txcHPF=}vgR~(Q+M@vQsZ7wg{;nwquF6N4UzD270ygjN~58sYm=^0 zIF7;B2ifUJ_@wKG6l$|eJbEnSJrtBoYI_!m{cKXUqJX`suut9D(eU;l9DLmX4+IPh zd|JN?20J^I!ZsB_WgLX3-dMkDHCaG-Wx$_QUX5(B@Zc%Ke4%Qd;0KT}a3nlk4>uuv zg&|a>00xbFm4awE67Co9J*21rvd{w|b+WLs)sqo2B)n$6MWEyNUoE`VY}9}eY<&uo zgB0q35poFOX;(#k4%9yoQ{z+w1DRd2cYN6<-Gp|>;Zw#?eaOIVabq|FIpH1EYofLz zg^U#NQ3~AYO9}@VE@DDp2v2QP&llZdG9^>+MIGTB)L8in3XEZGo9m(Dxl5=gG05A6 zpWP5X%@4vW3(pY4Q(whvDYQp14#JtUix++oSEETq4&D>j8mpMxCwy)&FY^Y}Ywp2+ zFfRvL`vCt!@BcbdFlCUs4^mj=Jf!pQr}=CD_p6orzyF!n3ODApFkUPC_D8xE3GM@L zSlKp1yTXy&{>W>EBjbI;DWvpHCD}Qn&!a=eu>7TTP5ltb&|FjX3rHb6aapkOF%7=~ za^nZ<$`l4aVi>}_3=R9DkXaPmeKL4yoG#Q-=+;;Wupy$^g)aIA`9n?{ND5@&yNd3D z6^vjhY2n*4j744}M#>jR1+YCqJ$7r_lKyPn z>*mSyBh@~Po*zi~Rl#=fSd~l^DfBpaBQ9D>?$?4Ee}Jq=l0sH8MY|)!#>Yvk0PlE0 zu(;SKpWy+(1Ngp@Oq^=Flb>&}=`Uo**nYc3ma*v=4y4x8v1_e}Ri%T{GY%y=#cg!s z2Hi9(7<_&m$b^(BPZhp14Bo=%y$x>cCSkB3estJt#uOR_I%VzoJn9Zlh>e)Vq#^o_ zzsN&a4-6tmpNC`diz#0)Ek26E2{1fWK5JTBvh#~DR$xgHh~iKZWp_ih;L{S{Vv=X% zF@s~3jw+=lSxX5Rq%tZWH61QfwJHsz<_T>PN|b=IQ!SR5n&r2vx57no6W{`ggj!M- zmd6En=fRvWYT$tKxvw#8RHF+u8dhls8T9{sLqSIP27&+hH^HdekQCA znIdvD1(=pw>!?8=;ZVf`UP2VvdO0KoY`eft=^Pta>`VceT1K2oLF|iI z;MGkqZEHLyA>qdhh8}a0N)#A7$dBx_XebA*G`D2YqOaDVGuf%3r#79z-Nx9GjPS4| zkxC3wS}~+JJ@qWYa(ggqW|0I%)^^6J z(xTjOsh1@>+@pGzr`Fknda0R~IFEqJ7#RnNwy_}uN{wlyGTitmsVNjKLV3qC&$Hs^ zO(tGvWxY*qJ4LGiCG94@vsqpyliH#cn5lH?jB-|tOjb#C8}^T#O?Hvr6h4_uJA}%7 zKIg*Ke6%xVpdZ_!;DnTs4X0^J}{eB!AawimN9rjfoQt)iU3p@JHMWI?pkEm{|q z^GU}oGZ9R2y??}*4%;>;DK9}3b+}aeaQwbjg&XmF0a z6Az`dIf{Yc>b)n$gl36SH?TAJFhQ+6Vo6GE3=-OmayF!!vwcFG?;543Xcki#~z z^)?Hmj>(96mV%T`>uNf6QQOv>FIiJp>mess&Zc%K>cgoW4mZq~4CI;c0r65YFp0L-5t82VZjq#}^$U9SF zuT}BJdkf>7XE{Afbhxx;+``@mXBJ?3FefIHjZ>Buo-?S*IBgRLCRfmo%Q2lXIAhMj z+wn8*g!L0!m8{zPf|X>{|NZ6Fs$DOsK-9{O*uwuw(@QAwmbtDdssEUPz&-@elvR`#ocR;NgeQZeHXTP_00*(hyb$9)CQH0L%~n@DD%Mr?1mq zVsvCLUfkb!@x>Rv`r=pQf9i)%{cs;1^k_eA&UKp)TzKV|zV?eK_=Z{hBr(@}4Bb7` zpR(~Qcw|}cs}+F@7ogz8Q3}Fp2`Eqi>4L4Tmr3!bFa87+oH%jf4JY6%s~{nlV3RH} zuFcI07k>K9Kbb=TH-kKU;kr4uN!ov@1<#A*Gd%g#*pGx0&PD-*5UwHVv zr`{VUCI)>Pw%sVFi-+i2U|a^PZ54TmmWSnp6IR;R4q!6t4$>VI20lXWkEr z;M9BHYd?SYm&JKefG?MD;*I<4+4q|F?wxpX^KATPUY;YM7Lc{HL|Wq=cZh=Q33Eq; z&y!EQ`_bLnyp?st)Of?^^yK$Pn5}eogFow#PZ9eG^Mwc#y!R+P*tD+b%@aoF;I^zk z4(H&q%wwdp`;T|Q%$|7QTU#G=ciW`>5mMN=u=&&vB-|+a+e#+f2*jzrODFcR6vhoP zcU`)4>Fn97?N+$wMOcTh$ALT#J|sQUC3o~Z^GtQ=qsx!(ojmzu;O)I&3=%I1|f z{zqIa%H2MH{NmTc3BTumhIKmDFPAKJDXmk>XO=JB*WYQX8-eKkAAed+I$~W63eKE) z`B!KsgOYZG4~;NH!9H}AW0-<3Be-}W{w z|C)64rY#QtIsc!oD4>YK69r#7!@W*h4+Xc@)(P?C_`xeIx@K4V{^2vveEAvSABXeY zAq5Yl2anG43oktK2nmPNYPni!xqoHj%J~N$dQiML|KRzvN*N9DkP~)#A3qX}vk7h`cr2JdECf(Mf<=j1dp6 z-Y-1enq7=akGPLItiFDLPBiRohv7%#DK{e~ll>&v4<9LmKtx$3(ATR-w1?p|>;tmt zzi_ntdeC_G5bD9&VX?L2$$~GB?YatWuwxw8npSi5*fg7=1RHOpv`B7pe-U?j`}c2>g_M7Hb zt~fqUQD{q(ZL-3L1wIiQvIDcj21&V1EWQD>+UO$09V@Q+zG*VVrX5%li4!G!MT@XZ z@x#`TLS_RWC{LWyH0uNb&62QjRb(9nX{iG>h_Jm4 z!BXI$^;^R|7QFGA@`4tU?!&tLG(~zB8vj5So~wtI8M5)Ry>9S|5xq*Z=nzA494`Z> zp8C*CJkmTXxTzz0r6l6a+fkBRH?hul6&lYiB6&r)Rqz_X!;GzeOaapPXd>g>XDDG- z+uQXBaWb@BJsg2>np(F^UNG@7L9sD5WsHbRSI|`x)55Je^(w}7Na+-Y`r6^r>m3}u zJNPM?LqO<8X&?F8L0rmxBRt{=fj%B@w{g^lN&sDbiohn#c4Q5$oC(M-@1{{ZvMeog zU_ox@9dc_*J*q!!YCDT7aKpP!3dr%;dp1MKAwXwrc7}jSG@s60i0#ht?c5lW&&CdlqWqCl90Iq_%=?R<~ zq-?%JQydag~R@&=aRh9`ZHc5qNP?6`GSsKhE|Kat~7E1h>Ll-3Gv&9!uVZdbGGv#TfETkPh;H6p`IKqiry@c zow~|-w_B&~J%4X-hq$+V{PFXza1+P!!FSyI&a=y_+%dWa_ZwZ)!I*h@{kpt0-j}(e z0C%=d!9jSy3;X>P`(^<94@07jH<=Cd;5#yJTPqD8)gI4U7r@u|tfjsw|{FkTtTXP=J z#>y2JI1BYk8g4`p2Iq@PY75Yt2W}{Ma`~j$dy1xZQxF9~d?pm@vfXTTV(yiviZH<$4D=*?`+1E+}= z-XB5*4YKo7m`@nHGC$GB{^7B9Fo&yLq%a_C$Ozy(% z;R;%$a0RVh;$ff6=+wbHzw8pQ$<9GB41y&TW^Y~uwG3ot==gnH8IIr-5g5N#~1!uM{ zJ>@qIX5T=<43e;@T@=U9UmCx2f8(W>G*6%w`D@o+xyJm>mD|I-K)(lA*pi{a4^pw* zHwU!nLoS=(eI+CqV{@f>j4xRC%6wo#O@-MefN{F}NuMAJalWr<4 z8#^RHN31`fIq-TN7Q3p^SBoN)j^8RDY?j|F^qW{-8{BK7{FT5cpi;j9*6s2u`3-(z z+Rb^p>Pr;??4FA~=8gC_@VE-m^zA)_jAV2YQHIyLKh7033JH#Zy5N4jkD-Bew1!44 zqGZ5KB28$1Ljy!xmu!)!mAo?U^L(|Ohe9#U&!4!cUtg3X1=4z@GnPPxfo3ENK4Ma@ zohtXML(hp<$N9@0y3WYzfK>7P$WZ(sc#2k-=Vexb;)J zkckU1OOy#Kc=V6ZM%LVi)**k15W^d#HZb^;l4@TA#~$R?I8~slBm&TX9%A%f4r7SZ z`y6``=N6z4dyBAtZ@v9rc*$>FVSjqkq8@d+im~2C|MZD`Lzwnh>{o50$8f*t{3Zwf z(s1DS{?btLO+voOf&V{nz#dMjgzpsYKUZ+djqgz~Wf%N;f1j9Z4KNGFO%F}Iupt|kX>gn=GS6=?glCJo$LoEu~OS@~#+=#bWb$6R1vfME`4aQ{0dcavzt zH|{1uxAbbm)JSfH(CP7NaBGsg5RE4-A#iG~MGPsnvRFL?E<6v-m2=$~85hgVu}-XG z(h6Fh4l><3)}OImtxgcXN?0B2MX_Uak0W-v`R&NI_Be*e#@F9f;D$u~d+3_ce z`sWaS#B7haG@o_@kmVX=!f5p)YN6a#NEk z_uwp0?ZD7k0~5ulWD>BD=S_hjt7dUXU~uo2(SXytcX9VN5diG&qFZs))< zD%ww6cc>7co5WuC!$KC%|o_!wc9^RDYQ8yF>AiY=?Z+f3&rq`yKbzrB8ko%Sqt%n@7qilS{ zqdwvi|5XcuA*7~ydv_laFi2*q+sQigH)a8u762Oh7!eg?ZbgCP&1#j}3LHr+1_ve; z+wNjIr5ZS}W`>x=kV(VH7aUSdDQiF-1z5 ziD7T}_usIq{Al8T?ygO8EN+(TnYaFpBibG}y3ee_hmc#D|L-3y-$)K8|IY6&@5lT{ zS6&Kk|E}x7eY4D0<1Bj^mdbil_YiU`^DvFqWy`IJyh#sub8Ghyax3$7W&0P3%%@_V z$8;ZmTK9l?EAtyD*5?2EANCR zEnVnzu7&lw7dpAK{~LmAuvprRH1Wa^LANi2ts}l@d!0#Ue_Mw+fI5-5U>>Yw! z>wiN?k8>1v2)miNp61QM5B>N`8o&Aln?4``YXWK_|^P-XaofYFsVJbn z%eo@`2JnYI>y2XYExNwQE$k4eDc~jW;c3wGBnOQd95~iAUgMJ9?m!`!@LrjsKfdf3 zM}~5P=lR_LN699#R~a36eM~l_;<=Ve2n%WTQRA?%Uh*tM;)9995AmYTXlFwn2_wbd z%aZg75RjG&pQ4+9j(kf|RU|Q%yLCubSR4z`Rq|U4TnORwa&PZ)$v;lY^4|EqgR7n<9Czpx6;V^O8 zTgCTS1~{mL5k8`e{2;`o=-Q(G-D}8FuA($UeS@ev?h2G3Z1C4rRknjGX<}nnHX%{f zePc-uMcXL}q{ga9pgI|(Xvq^Yj|1;Hh!N#S}@n3BogIa5gG#2a))<#o3Ux+Thn?a$jJo4Q2h(CE^SA%q=Q>(APQ@_ zPpre%VwdDRm@BoSN-PLzV3I(~qtBXAzwG$&^Tv0!^I~9;imw){t$40OVCMoK+Ch*j#EJ8>vtZ!E_rNBMd<(2X)z*n0Hb}`G(#i@)-i9CM-HIH>u?_W`{ zw;dhz5w}Sdo#UdYS(T1Zu8v(=BzZP+Y*u$6np&z4)exLFJPOX=j8?wvsz{AAz#9`$ z4N}pm2^u~LgDE5sKq0Pzt0d^Tqxc?@ijrts7XFpHpbO8NJbEEbtfCrHbm@5u^)NfI zB##QSNV%8^An8D6Z!XNv#HH!Bi*_e@k!*9k)}o5GXTnr1qio*jQV2!qDG4Dre|Wrm zS=LhRSiR@WXw>{6A@;OU&JqBQnmHFsjkia$l;gdfbF=M{t76x(ZG^KRiO;Tf-^QYZ zts>zj1EqoEW>BdW=xh={gnHu~Q(>8tN7uK29trm-OpD}D>#}5Ac9N6svGKUxZ=nH1OwwBhu^U>zPQ$5AM+!CezY#}v>O zL-kD~9c7VE!&VEBA}&h|xNcHyPqq829`iQ9j+Qevx+qs@pxCh?!)?1*ePi$$8f1vR z{z!eFB=02L_5;TaRjJmw3hcWvw!8S$;|pR}`8bO8A+p{~sRpY202E7|T3&dcWh8VliJH-fpWR|RNRrg=-iL^|$cOnVb`<8#I+ z#mnq~2q}`NVv@k|0j1JA0BMRJ*T`P{?jQAc6$Lf=u+u==*{k1^U;EXU4d;XFB=Rlx zB@n)R>#u*?(@OG3|BoMi7KQ!g)vI@fQ_Ano?!J1E)iF!_wYx8?eTstP5WVTU-x>UF zNJz8VD|e`?}CK6%Rj%y+!c?w{N^sr~3OJNmOX<{O*^ zu(|Qi%s&g6K29aQR_>euaH0JeX8^=thW93Y531<2y!hSU%}#yJ+C9B#esE{(8r`^jA4e;AHXp4?Lv6EUV4+>vVJd=T>U<{r>gyhv#YwFTipc zUg5#1J^!aquTfBU;Uyfx56uVYEt0dRpRK*x@m+U)-}iA3!;KVx1$6Y2g7b$hEx7f# zhhKZ=f%D4Nm8}8r>=eC+9z}yz&Zk_@$>)c zkWQcT(c8v$z~b11y(~MVK!;4Q591aTY?%F!V|?oGa|%J*avQ)A3a+$l&bkGtv4x|1 zj)bd17?2%2^+lGCu%)@%yL7@>`2Gi99sv}qlmp~&^oj$YCN9)AXKh3 z7}DxZy|)d&*as9Bp0v4EmH{<*1|Q$^95P6MF3uhWNlXIyYoOS}V6L2gWo`#kt_(rO z_gH=Wc9k`QJ1QlVtAZS>ZRB%fD{Q20txSPm`^miqE%r!mug4)YSUW1Z3tn<5uW%S{ zuxmWfc{Lj{3jC0ZpO1{1i6O2HG=U(rz60zRi)Ofbu-bVrn(EMJld9Qe!sfCWn_A4W z=Ald($c&tPNNGw#ojS;=(#mm#Y(e62*|L8ULW(rA7+uR!gUdZ+d+oDT{+>)ku4;5! z2?LcLG+4u581#WLVh^Y~l?q1opfl}^V?f4D+!C-9ZvxQ*<<8(s*w&iZk-n)d4~8lQ zd74Q7T;GC^!iM3W><8c@52`0D2}fI5Rw>vzuILRXY^y3{BP-Q2fV+fWrJ-%G-I$A$ z%(&UkNr8o{G50I`zQUAeVQYLtehm6#_Ps-eZ3S>lNmIz+!7&XTTlE{C{Yf5Q|!}GVi@Z%(Et`qPSzDxJw$_sE3Fh`B1^dj6-*ANSH{7Huy?F()+DJ zvN3IHN^1|sRAUzCdUS`8QEKWR7{gzr^t!0VsoQmpB_{16$sz{H3+SUMWQ>?Axa_DB z!r@lOGm9+G74TyA98lH)l!N>-W(wF{+hlS!YK{yyTZ3iLo`lP zI$k>}jL8gBcbb9V;51WpmO!rkrO3R#+j$L{D-iz=9D^tIN{$|iJ-e4B%B;q^oSEI@ zfYHh3^iF_Rh%MqHupOS2W_g6v3;Wx=P5LWrV^RwSKYbOr&6o^m6BWit0cK*fUEj-% zi@n*Nlfr^OyZhHnlh`!p#0Z$(rPM>Qjl43ds|iQ5I})~mXGBm+9y!Y~{x7)sw@7sd zKo!aa2UkT(5q*(?B(HLhGj-=+jKZ9oq_ED+xKBx@DBK1QP;ky5D397m_F_J3*dwka zi7PMpk|HhyYG#KzJR|BPgey!9PtfTR-fmNtE&NC3jEv|3W}M#v4zg_i}o*I&6LiUK>z$a0_81H!W@CantaHCu)$H^O2*Q z9py>Ev2f$*c!4Ax=ZTxbU(L~xop+ooH}|8|**vbc6PHh^WV8?G+MH7+_i&8Aq+*#74McW9N492g{k(M4hTyvTnqw z3`ocvzrfiOY78{CoEC$n<0Xn^RxXTb@?b=Wb77MT5+-p6_t&xs$bnY^*o9z&m5^Ab(W(U zxLS{~{D@{iLP2JxuMZ~pK~}z%34Xt$e`P8IK^;=U@_@?nxARgrS z@BE$aU@&{vU*wYt;C#GL5wC9QHZ&7X>I-)$ zaZ9#t%D&^%cYInmV5cv?S%(m)I`yjfzx}uG_`l?O<(^mW+0ah<<;9EVzIeS44@d`( z*GYj+>N6j@xD*w-)#<{8Klzi}ZhP#p^yU0(7grQO0Ovnyt2@2LJ^4Kwi1gw_k?Sw z{9n1UwRQU0XP(jBXr#h;@+VtZtgV2?cQYbMcRo|6X>Uvpf#qW)$3cAf^v8^I-CZ z?%jLu3oo4Ayn6NYscW>f)lKBrpLW$GsKgKUCje|hf`e{=HELt*Z$ z4?R3Zz@%IMiTobje{{bOyV+9|WZBuxwq2)Si?cMgIGaRL{KhkNk z_uY5$%q=LOJj(OVTbu=WoSu>fW`k${9Ky?Bk?1w}hvQ=S)aWz7fx!Vvz8j^r;NaQn z8^ZX|<_JH*2lu!wZU1cv5nl6Qk73lf`}oaah(ELjTX0WBLl1ti^ycfy-*o+9TL&rd ziH%bY7!Lp+6CJoHBA@pZAG`x7d>w<4Fl&LYgNQ`QThh>vX3zKEM`f^Uc-fCHl%DMJ z=bU2WLk?AN$C1MF+7Twu?X&ATm%)?Icz}WIl@o)bofyV3rVzBI$z(3%E?dp!j9Q)Y z7q@9_S_W@+)Ny368QIE&gL*m^j9QcGPU8TraUl;0O2+a783dg@A^%zMwG1*<*ZS1= zKmq-s)e*I@xZ@T=EGs<9tZTYaH*Rcabtze+YkO(1F>)-ac(D6hkr>e+-ngl4A#s4d zc(}wxo^-TCT7fka-x}&P?fUk|upLmGqGrvrku#Y<)UN!iP?9R@yK4zs;+dq;(jtBu zM%KJ%8G}mUtOLAQfemIGm@R7?TfJW1lp(<6KA42JeXUz4cc!o~v8xCxaU)prgu6)h zrMPSP2^b!8`B@&6n^~T5 z8iB?fjE7`_PHY@^CT01jwlN|kY!gRxNI9}B(vUuBt8&u@dIJZ3YSZ{^gCpMlr<(pPR2}95g4;oX* zTLHe~SLHB`=Rf(9P**g;j((H{#i##rxdV-`}Z`VafnU#9&7L$b& zMxA#PJ8vu)5jTH1Fgn89Rk)k%(!9274!w^i`KZwmkFN!_X~3V=wN7}Xb`w_l=^%+O zjo&C0$2%}8Fcx4`(-}9`oB1M|v;m{-!`&(c?!cTlVlL1cfL&44z7_?9do!`Hz83p^ zy;JR)WFE&QFTp~ z6J8U#%69VFZ^L9Bag#Y!%F%*lHDwNp6iHXDF^X6jr!knAOW}1x*u*CBbbE)n0Wfe2 zgZ2`|RZM&AU?$DTDkk9_5jl}E@DA#32{FnbWtgt!#LdLG`6NqK_PmP=*i3g5Guc}f zzGIGLQcZl$>v)7`oXca3#*%2f2KAG&4!L%>_kl|LY< z{VnIl!7R`9A#Yik(gweL1Y-y}G=~%hyj2QA7T+{qg#)j3&(}A8Q`oCy9)f=9?{x#p z;Z0(LPx7z-fibUz@mk?@Q#40Eq`5MYJwhYZT35@!gmnr+EPpbwrNKCO@bzO@nb1!W z-r?PuF6BMb7}hqtN;w)LgnL4&wogMzu>L@YwLYZBGeE?%|3xMP<5-5KX^#7>A`S*~ zWJ4Mne;3~3u9c1xN`qaX&cN~O`=$PAjSqi#ufT?vo^q2UU&ajYT@w`{6x}l@9CfBm zl%Zf|T94uTtmM-J12uq0Fl7(mR_37*85{oAefnyOEPU~%ZPnBF7lDYG}VaNpFti9A;Nu#)<5C{yMt3CV0Bq++~J@qSe$6)j$8>G+qfIG zjN&@J6sax71)@QVjKUW>l`d}2IV2PfhfoNVW-d!(#I4DNVnVQGFqRH=aFBJdsMe}r z17QF!OIkXb-ISFh=D|rI{JcpRERIQi_*cnCNI>{>rKQ@s$}vc>F59R8^-&L0Re~qJ2{|iK@DFOD$Yb1`;)WE<0aq zFl4v<=~kC4>Z>loZx-f$O-2pkGJV6!tOoQtMP1`m5{V2xRbDd0t;i-EfQ^kqH<7)$M%bUR~WeM&+W&w>TK zhJ}yD@KNm;XH>Jqk#v{ZxJVjDl1ZI*kTxx6Bb&6um^zk{M$;ta1}5e!)S?hA=4oMD zZeU8wc$C&EFbs@J_-;uWwl;VH)*6)DVukjgMH@hBhNKAnF1U>GF&$B!DyhaXg|0@( zss~Ni&X9V9#$a02V66TvoTP~xB!D~{$BHMQk+2++Hx@f&0C|hR*9p0>-j2C)*|c~U zahH!tWICtn!U1k|($M4Zgr$7O~YOUkH;ks|I5eYg|lH z2f!L4uFy6iBAfFDqwOf#Gskm^s57PWq4~fCy`0Uc6R~QzWt-qbUAGmPVGHemK%ins zD^H~LIHxPgkfFzR)Nt5!-+d_)S`!TpzEoT$RE*2StwBuh>hKjwS=nH%P6&t(yFYQE)pH|(JqR|Eks2#!_o& z-2Xu1p0G;mAW;`+AZ z#fxnVvo?*SQ^fa+usH4k|31fKbSQOM$UXhHmIjw&* zL+wlDFw<-ShT|0)ahco>Zz=Cd?vimn>P9-&e5WX+yUpsePjYK!G{qJgnP14V!n5~M zH5XRPp+ag}J_6l60w35mmFr0))Kg>m0m7v&ZTwOch!} z>SgZQ)Rd&8dKoKjWfE_3Qt6&Ln}jaF8=n{(+JyJH5ARf(+lGVwL9*eM%oCS(`N-4P zXJyF?n#{QEZ9XqeVKYaiLcXS5>y?gfxmq2(Ovaxz<_F08{?D2dEDLJ=@tnDQxnF0j z7&0EZYtV>^k4QE5V+b%WuiT|E7kZuDKKukcTE`=YV}JtS`G?Lw6xOi%nRsK~^v>T6 zy1JZUO{iJkb^flfg7VP89RBIk*RE+5L0Yj_&s@DE{oN~fE$=c{&M&h|S1-NqZME4{JnN9yUNl)NM%@O989x!{`^UEGMq0xP!N6h;*UfqrzN8aeE$4h<}TK8 z*tUA+>B|(}4mdBJk0g zDTUzYpWkFPNcro2El&UD^krb_M}7l_3!)IJG3(M zvE|3mhuyn!?OI*Gbm^rt%d@98miL{#PwPZ4J#gvLE06xGcYpnNzV_Lzt+1BZ=e_nk zdvCeh>a}yQRvnLNIfKu$Dalh{B-+AL_bFIvL?E1$bfA7kEx8FT* z>47tQe-oVhHt*9dN-sTd=FGqS$=`I}_r`bROK4xq_|RG#8$D&rlLnn#&KhTpuJ5nv z^bYwmSNi?CPthN(+(c~B?^lRZOy}UH`+?C5v!sfiHjRU;eye?XjZOw*o4k-8cK@ z_kUkEdG)ZhdF7)~^}A~;V4QtT3nnAFFJNV!BDn`2)H0U*jCmp3Gok=y8@0fH^W?%S zh)hKRHdJcYxp_drN1pu1lSQ#w8x-D6D9Cs_j;}W=bshFElGGAD@rf7Ov**u-)x+Cw zN6Gif@;vK+L3dd#9Xz=9)F*%aX~o>whx!$~B*o=$YI*Ome12>5=qh0EKddtjrhIwl z0uKfXlJm)m0^VK3B0&|{2@PO7o+iBMjI=5iB#3dM^m&dIf zyfIdiHR~_*&YJ5!gjMfw=y5BXBY-wO3q#w~OMNP6lHuJLtv0duD9KBGrkc|5sY`|H zHJVbcGrk}*lj81S^_eveJVF2L!zigbe!e35Ux6h%B}@#UGSN_s;KnPD(N-&Ri`yz= z9|Ec<7;>ANgTC#8{<*^OEAzNvp)k8+nT zd{I>qx8gv^!Lyl_8&KG6F zR?tq|3aK=)&6^Ai(=;t201{&50>62xo@yBZI+#c^$qsx%IYO?+W+ryAKE83LmWWvH zW^rjV38p+Z|_V61Zb z?Nr}!2uQb`f`Z;9uIbpqo1IZZD@J)Q2P0;hh|!&9UOP1ZOo|7bfzJpA1$WIFW?5#H zElt9DM_AzsMX6K>AX<9{Yj`;EI6!1EDpLlB2=zuHIQchLPl(ft)&s9pUM>2BP1Mq+ z7Ha;2+IM{#y)!&pJy)+`Y%C7F4~((+Lq4Jwql`AUv?L~kVpp5gv~gW^ z6uNe%in(wZJmV~i(o_$v!*+?S8@s~<02AJ2>RQHs8RKLVC!>Z&Fr(6_EP(lH89j6r z1fZK7T;7y87*{)SoK-upkXqC(711O&jVp_!X06YWPur@kvXOOZo2RV*R^Vh* z>S)(aEzL7)!L`YZKSs@Hrp^QK$jrc&?cPL0@Wy2sT>$_No8o>#2QCS54@O_ zP-q!ttKrj71*x%wb>e}Q`=AW4Hb92O(-LfOfgkmj@Ps22O9^)TtbP@b0G_!AM@P*Z z$HXLKJML`5(rD?%u0ZvE=Vo4gfHId+`$G_d8c#+KrqSU$kF25cpNng zH>mC)ug!9d_uaXlurf7Gw5ql0@7jk*i#kEm+xWq8d^bEH_RU3&&mGkd@Jv zB80^xW6FfiV>`CV_BhVAQ7u=-o}VZQkTd_+#Q9`ijwT)Vm5*Frxmli++>*^AGIy&v zSet9cB&mvYLepS>!<38l=CC>+FLn{3;H^v3I$HQp{H@o7Gpyd4QVnF= z#8DkpEZ^;zx-wmqIQZ-$SRd7-LzR}s(Ey6ZE@Jdx%V_3yncSqBk>VFS)qF9nscS^m zoe`=D^Ju5loHEmLonzW#hl!{e*;{I=Bf|jooE%M*&xGafIf3EXxRUhtgR@U-&N2|DFWZrQ}zI8HqUxc{>u@BZj>y_8;EIXMg`dW>#Xr!=r~s{S{4F z8%NGtSNM>%Xn=&ghgKlzKfsNQ&Z0}8_3+deXXnLxU(zHru<>I~mP8@trDl$kpG4?~$V!#B4G z;liOEym;cpJMQ@67Y*#**x28H?80Mz((Qloi!W}zcvc#-?|=XG<(+?c_m|I|d+f0f zJ+gd68nt)c{fA%v#sBkDuP8Tj9MJb=%Xq4^BOkknFTUzs1Y|81h>2L_R=9rBJ>8d} zzR$g6+{%67;oC0U1_gKAaboktS!oTw|NUmme*WA4Kse@+i;qa7*na!x|G@v|KmFIz z@#XzHvcJ{T8#elNKDrHE&r|uKS<`Ra;MVswU`kpSMlZGZ(mC&V80kn_@1^<+$9ClQ z?m>1|T7aZ<37nb{k^7ae{MtX2`TXRuF0jdm&{L@mp1pSDdH0)BnVXwkr`e%FSGVgnH<3fBhf9~voH6LYp9FtvV=JVbRA(zF$T~Qz*j!n? zq992$YjNkD8-Y^uw(Dnor6s@z|7@;3Wd1Q2M<7t59l0-m?N^`F4A_y-m4oZO5ZtfRl9S&4HTSzTrssH_s4(iO?fZfht?$T z6}Z6?%-GoQcf|9EBW)QgbcbG41|KS;!KE<{$))eRc%75h)TKtLAtY4pvCOrocLe&u zjwvd_nDkH|}<4MPLIniik+@C+1)zBSNH!T`N3ltYmOK{gBD z@h-S6PZwMMi$WMtKm|ITu30qh7Pi!|HJaEF6#s(TfIjh}0_5XKPLDu*d2pmD#A)?wqmHBA58b zAkQZ7rJRQ2aFBelBi$ubmRdqpqpN9&egG62(QB0@DN}p466#-NkrGCN;Hkmyr+Yzm6 zrH`QOA#jl{mZQa0p_4PO~;DMo3IK33w?9QMg(J zMdT%okMgE}qvLpF?X0vT;xY;N@h!`c+=om5OCOF!&D;3dq{F z2^tx_pY4scr#PlxfP;f!cpHef^2MMu0Yz%^l5oa_FQz`YxpeIGQJ?X2NsPoVcjO@4 z&aur%B69rf(fmWQBb8Wd{`19j#O7erxeGIl(!z;Vo z+MJ15i!@XK3uQ z)&RX~_eqpFiwX#Jix8Kk2~0#;Y9(AL!^r!AUnk#$@Mpv)Y9)F0a+X~7b#7?dYcr(_}xzEC#DY9>Fmp9U0z$w)V)(2^%X zh&ukA=9aH#rr-d8~>+%-ey_B&$lW^m>;?*iDmL%J1H?QI;f*koD0VjH))U-Y_ z%DCl^*l@ffL$lKrxL3eP8XNgjty*oFj#^{_rxQr?0*)zw&WA-Fnv-iwFub!6PHM;$ z%yYC#^8hsDP7TXj%&$Z8bh2w2Pg8;fbYT%pI@iEcLBlV1O*xZeJS!s<3}^s!a)edV z8Q1PV<)Nk7v;}L_+SV%rx)umb04hqRlhAr?w6;ztS#%Ro2b_5#MNFu|&B9*=}dfAUb zD&Cnxc&bkpb&jy51taDH89IZ-1j}btT;2}hssG?JgXq8%a#loz*-dd}0K@@z06^;N> zFc;9!BPB3VEI_M$^si<-+1bUKMTUQTvwF5oe=A-bfzqUPM!P|oAZ_Q1xk=M;l(2S3 zfr{z0*4M0_vQyJoQ?hy`l3Qb)Yv$2tyW2?@V^mD_Wm%Z*@hCfs=pKE0{l_ z4c! zRYR;@>f$-eY^u0|WkVDxOdA^F_8zRUCuaP7>LuY$s-yj-_N3u}46PXCq%x z%v?vG6{GOlX&BVe4k#=(R~H#9*!`(t03N8P(uK@zGK*T* zr+@e?ibbkzysWIxi&17Qw`>hG3sEP6)+oUK%b#EPn;k_f3e1sHS)?(m6K*%IZnPhqe8AuR9dEav`oL5E zBTqsBy1i05)wwuZABBRi8iU^N$^DJCJx+mXHeB=@_&%}m`ABEb8uR(+Z_3Tj^J{qX zpTa!Ul&$GPgvpv(q#jCZYr>E@ti3%&*S+pPg!egsd zGJR$F$dyNgAWd26aQCZo4?J}C>?c04JRiUPM;}*ce-^B4U~XMmKJ-wpyE$lotF3E| z?)*}Erbi*@C*!44ZJ_{LPk|L0G@O6L^c0YE(Ba11GY>qpx%r7tTruX%v(UtMGMoh~ zTcE%^@IX(&p#8139@glt+(?1e(t`dsaaWqK;ne4^E@?yW*m|eJPdFYrTv%zhP4 zX3*-zd~olV z4TDvUc$_%`TEtMdpKH%mO(Y1>ByzsPcOgT1j3e+Hlxbq$f3O0!v2^t*VT^;OCC^|B zDTD7Am$=~PO&q1EBOqxR;l!G!ZrfF%`t%ejO|5MqwkpP!jaHU{hfQY;xFI*QEF_r} zH5S82Tc)2AW#+{(yW$Y#4Sz_MR^Lp8IVH>kLcBijHu%=~F5Gc8n1z?b%)rG@J(44T zm7f^m2xi7+CbICs8yoSZa?}F4n3nJv8b6ZnbauUC3}!2|gGxh48NO+|$XbwQ$4+i0 zI?yAAHl=n5v8+)$_0}zR+8jC>BE^g_Qs~aKrqJf(#<<3EkT|j{Lj*_FS+iX@V?2sU zP(iw0d+L$FOu7@-U5wsv93f29WsF47p+gFPZJsY;sqU;mNl~WCkx%LwYn2l;e3(C= zl`)Tv)P1RYrqEQo4F?DLlpM)jHLMGlwSGcj*2z%6Y+Udin8B9dEJlE)$5T0yU z%Obpca2O)Qvp5=CPOE4tlA-2jc=DPe^u|u~79`l17Cpy`ibF_GJJWVJV$FzX7J=g( z6V$~Rip7add8-+!*-_deQ;S;CZH#qOwJzorENLDB+)f?xXq~y4MJja7IL{DWsNJ2o zD#;Oon6Rs`upKlFTitmlvJ8JmYsfW=VClPJ!qSMne7T)LZrWHTeHLljPBRDZIp>#6 zv&ooA46hbMdI!LeKHudc7kQ){c*!cQlhs=2Z+(fiqYOpanpP&2!SqmgZ8#rjm-gey z5;|OBZD+Sr>BFI32hXPvQUmHgZXB>o^-H^eVo}g1+ChDH67TXKgndr&C0u z4vpIJIHA{YsBh9U>@f7tXFEF``))^zk~YChnEPGY*;w2;3Oh9uJtlG#fNmhN)Pw0P z#hlLcCCQldI~E6(O#kI<}dXFxbX+dun29Bgfk@j|z&;mP+Qm zb~tgSHf$h4qq-*3oE7{j8jPbchoIJ+s5&PlP7PZyfrXF-o8t610ckug7k+!!daAFL z@R(L5vqCgk?&4HOGK#xAUGUyko-a4;AaQ2LI$w_#&2F7c9Mco|yx($&awttV>6qH+ zMqX0jXkQ_nvCKfrPSb zrt@ln+^KJ0KN}LUuNFPMw8+^BIyH3n)R9%IuolA56h<7ME^>i={ zW7w6!!N!dSKYql)QRt->e4c4K#kh;KGkiyN?ugyBmQSQ%PLKDAyd#jNO0@uoCfZ_O zhr-W&Ll0s`91xt+E9bmY1ru2#Ml=;of!(`QDTy)NIu8>o$#j}(|Gcf{%x`s5rv2yu zsVv7q!-exXIx=WOL4Vqy!;+8r8lmK3%F21VsP)`~y(Sx)m$^L1$SV^sYNc)nQ#X3K z4=)ub#0WO_r=C04V=ACeiKGrvtZ{%z3YV)M?{Yvq{&@Vqdgou0#_2Q9Y-~Js?y+;r zyFPT+7th{tR(KjYOIFc2wmm#NdhD@Jf8wq?mfyAYU1wiBd*akZ#KMcGBpWiie)L-LLxeDMy&zla$8#pI6g*}r&k zE9k@C4h$6BcH2AedFMUXzsr2r=8K!6z!*{RGN)z&N@e*tv_pk%3=!V`iH#GVzT?D+ z8?ye!J(#)sMiaT?j!%F3C;s4Pzy1?H`v+f_zUxI!g8i+}eC4Ysm{JB~9zoglp6~t2 zSA{p^wOoGw5B~7WU)cIWz}UZI|BG0^a1qd4fw+d4xp(nVc)U)8`5{(+uPbo-*C_OA})pli!m>zZ}_dxNC&o$cj1x$=TGdn z-+A{J%onc9r@N#3BGxZl{E3S{E#8w4n{1%~!1naUiH#SFzxKX=u(gHzCeWJy{O5OD zeL9ie-$8$42I+l+ju=->e8zyp{cQgQV>CBn(k0@(iSMSRAz&B8 z2sL72Hia^QGH8+ZG5SpR_Wt;NCjEMkw?@acOP4P7;^t8b)T-g>m!&aVC6^MaaBm~q zfPy|VrWamDat#!G8P5opVEM8pP?D7vX&<8x(Ozo8Z=gUtIDej*0C<2D5A5wpcK$kV z^QlvB{#)|7vYL0;*m&j{cz|55xs6w15`&zj`FbvTu>_ODZ#flsYwK#ezpvN=g!Zky zPwee&JhcB%?{oMR58xagM=21k6cAbfwv)>^{p{&ySEUF!FHQPoQNWzmUHx1U89%tk zZeXU)pde_;Dsczc8$-kcQH- zv297ru6h;=M#k6CXM`EcGd4al$h8T>-58q*zXBP=&XWI+xwntG>$oauZVZ97n%H7(t4Itk_w3xc#9Se8 z?{x!N`Xkm{!3yLRWfH1tNP0v|e7)|eus1ju7_bDr4E zP6gK{RzBpRo6rINE4VU~fC1R~-XufWB|5L>x>)$c^p4 zQjm2;7M$vVZ%r83E~)Tizcaz7B3(&*C7ik`X&g^-UYF48hqaRlS))MEO!&Uj>qPgn zfe4I6nu5z*aaCjg|-Q-$>7Q@IXR`50}CS0~!Dkl$y-jJ$`8-ria zY(Wn)ZEa&$&e)~m&{Of31W-JL0`fo;FNK|X$I=bN4Zoy@CN)h!b1Zm>$=OgFTAIT7 zW%NG0H3o$vG&dEkhlU;g5>(gUq_0z$W9+hljuBoazITbKD8U%GkdoUSXjZnbXzDpQ z;AF{+LU`MQte{TU6j(wGJ(#_zon!>;fVgol4NgId{x|P%^s{`UIWeKhvYMXFnsh^& z07@K|ATO;|ImWfxKV}Ff2!c3<;{#7U$vnMV`KfU34`_c(l^60hkQi4)RF&H z0SO#h$VX+FL%En(rZWa6UAMNxV_!YEDMNqi?9yScsBfl=i4&?;wbR}Y4h)Hs(b~os zj88d!vV=WnJXENS4?e9oVyyMFrLR3?MR>T>rK~~7K&s(!hnD0T4-6pa5lf!LN=h6Y zZ_7eT_mvgcVcjAMCVatJxVqRCCITKS@@+|%7W@DpH$6;7x_vI?bG|wX2pfKr%zJX*``$?EIzM_QrCfz>1=~I>+nT1L%i2i+Cv=8SwZ$)@7ikS z-LmPc85y*juHS4LR(moTfPgs(iaInbTok+9B&(|E*E6~wl)31Z2$a|_h6q2ce4Ib3fvZ5Hr1RxJ+MywZ*Dcv%M zMJhxuTV=F?l zh-Az-9C%|FSWz?U9R|0S3r#*o0)RU@a?-0=vH4nUAcxHQMY-x%Z9kt^e3?qyKnh_Q z#t3mYW2RU$X95l0`*N{d6%6o!W4I{9GmBwLW19*(Eu8``4^;;<+%y8%dYRU1(C$@( z7HH8q;FFArHS2chbPk#U%cft7jB{}zd*#a|c=giGYKS#DcdE`wv;lq?@_e;6N!m@5 zp;gmEt|fgfbz{~Ora0fb!Dflxbs%j=TUk5j(53>qc511J>An0*hUB^@KH>l#(7l7c zGI(g=c9B8(X$e^l>AI=Y;F|#zmARR$yqASrG>cb7#UfQ~Sg0&b(9|}7$p;3CGZm9F zE7k)i0F?-uU^*-;Ff`A^3#DBVAtObAl*+8CXf`thJa83L(!Af8^Yx)K!nNz4#)BSf zG*{Jg@m;t#j`w@p@vc`BQ&gR)cd_*`rJ^dO(vTyzY~y=%9*>C4>s`g(@w@k5k|te# zHNPr5IUF*v6Zz5TwqX%!Ct7*ZIjKkA49Z??_cYO>MH|wyr7GZU@)#Qde7H$E^oWW(p4%lDi*B?wS?lS^LJ1|Buo2*F-dW8QlDt@4*< zra0X%f8r0{C1X(Hgenr6u_vSh`eob;$FE<%fkmY)=$OtT5g+@;mwxbtF*Akg>DsBM zp4vYB;bS`2RXlNV!euuo77zBa{qD|p#}u^6E8EwfJaO%s-a$^V_H)5}>+gKdafrys z2~~a=_7Mksi{kGK$Ki$p?u)dlIO5`C-~WbRD8~F0s;6tGjvag9i{9v5SMkKfy_M~x zR|NaZ#$5caxe0;!0lfDUhY!abz+}x6CV=_s-hcklQ{P{I)yyO3`)l}%6F%~_znMHi ziV-vJxjRDT9z9}t;>4H3y6?pp?=fe-x&3~BrqHdN2*4o;p%zzvt4GxLwBF^}7k}sJ z7r%A)k6yo?gP|IuF(3@^^iQ7tgzkmLn1PwUL#sw?&4Wd5L8EE&8(VWDoVa@Os#;In zS=@`_pKslkmOOG@{&94Xvqqj;Tq9C3x6p&AZ%@BO?SFso%I`l%)9k zlq-(B@Jl^`zniCn#{Jkiltc+9@{{?EAH1R1%=>P<8-o-@8;HjsM z9g{T4d$;dJclDH0SF&dC* zG*W&{ryR!@J#Akx<<8C>-w>Cc7I`s-al2+%BOo!h^xJ z6^UKqjpaLLCeAtef+O^)Llh1_^2RUCRv05CPNneCkuP}@7j8oBs)p^hJ`0ww4Td0V zlG$SJ_Nx4TMFg0i+j z`SoE~0=YN1#OW)TYd}*_(oj^zlU4zmj@ZJRE3;|`d_DexO-`^Cu8vQRH$KHZ^&-X6 z^!UmtPm>P1!a*^i(G~_*m}ccMcR?OvLnDVt_Dc@2_w3!W#I4O>T6FsI)C>2_dgIpK zf_iI{>JZK)679bArJZuNPNxOp&wz&tD&fSnXn!dE22DiC0Z5V7q zO4^Vf0kvzI)Ri2~V3UeA$kV#7RsV*-hP)7x1wG`$$%eHA=$IaDdkPU6ux*-s45=VzI!8vOZ+NcYv6R-vfH0jSQ8rsEU_|f(UOQgUFtXN??La_c(o8c z;Gi3yLJugW)R&wYC`b&OHF%q3g<-!Iq-;_cp=QZcVq6(UNZpz?tid9ojf}gc&ZArD zO*MyUnsyutTeiNfJXLDgn%ZF5t!wNL##Re9u{4QOF9@IPsvNYv@yiYGrOljQPMlYc zq$q~z(k5=nn$fu)@%0uzqQMlj8d=m(slcv`X8_TxaDr0!dH6QL)Tn0AqA;#MWBhG{cxDu^1Uw|z}} zn67HcVRXRZ)lM3Q6|xWLuXM=&qq#k`RHQ}Rdc#DrwqG^D)6ouei$6K%Xy!F{{ushM zVBkq(iS{iUmUc@(&n$P$+fhurVdbJV(Z5y(qjTJRZG7j4Imq5L8@U z<-TI&$tUd+nR1$uT3U=Hb46q>sX zUGH3OdNSYVe4>hU@<|w0NkVcpE^x>i6S?&~H^l0u;P4G?Yf?~|CV|tq*pwI%8d4@I z2`Qx2jh^*fX|!_glmciV8kxSsMm+CB3>+`r@FxFFNeZ4UARk23yi>c$G!FJf%WuWK1nO98$-h($J!kJ;=GhlU~ zeQB52n)3Es-~q7!HCu*A{TguX4E8IBwszhXLp`m^71Ibq$+R)YrfyaxlL5?VQo;94 z`Jm-4U1C2xAj3a^&_jottT>dk&yjx5+qPWJu*@Nu>Bi)I-J4+fqV03^S*T1#P!?#Z zP3c*M@UbR9$wq|P^%(}r%M`*>&6sa|u@KO3)R#+;HFRIx$`7L7F5Cvq0+!vDiAzt> zCv`BPg`nnmr@bgAFzD8|%4gN!Wk8~vr?o~)mH64B=L?o}wyBm-E}$PJTD2gJtfzK? zwm+D%GKW6Iz%B;jEZB>95K`!{{H-|!dEnkKyUS+i?Z70_2ay?9`hM1TanK12CZi+w zA;Q5!BU@PvI2LwMARK)6WRfw%8DNx%-2cK)lMM@jU(`LK7pO=T-Ntm-Vb7Ln(t9Wh zNJVYZS(6VNmZfqwkXyT1csTh0HHDK8(eow*0AOlk0>C&LjRTbWa*nC(z?d;MFq<1+ z_EmuX;hAhmpp^@)?0gz#(AFg1HIzLz+RUWfOo~e1JwRgaKwzFOX|6>IC5G`(u{t2+ zg4jsU-I+bd+VuW^#!JNn$7*nMK4Q2HYnaw-V2l3d)ELg&8TmH^G=wzf&|Zw)_ewta zo90JiN-e(1*_^+b!@XE?cILbSewdSer5FGBSO4Z-m~1LxF!?ht-u-8HZQp(Q-CNkp zFMt1!{wbDo;BXy1`kx-X@sEGy4WE7F&?DLlZ_^uKYG5?Q%h-?tX~n&G_qTpj_m6)Z zi6fjWI_bXW4%&*6jj1m!?qYb1PEynFga!VsAN{5~`fl@XGT!+c?|Pjbck9A^zWBP869J~)>2XLo(mDKCyXy;FD9N%ws&B>P_e<2?#*yz@KPufrz3 z{2*qZ1j*m~dx#t$RUk`H!}UiV0kJ=MnYNWgKEc}(9I8BLj>1`l<9+$ta5BY9<t6lzJi1+5QIEpueu5=qS1!F5HZP0L zj}l8OsN~tf$@@qD*0H|BAD@^)_uUw*EKfxLGfB`LPWO1%Y!AE}g(qPBeQ-H3Mz_ya z6yzgXbbC2}9ID9C_kzlb6|NC~3)B4uI3U;|y@Unq?azMb;d4Kr?njTl{%w*MxZ~fx z?UL|W%nM%^ZAI9)j@VV(NIO79Zo#%=>y71`+iXP%0#M8Rah+KT1SmoXLk57i?nS>t z5I~KI5E%ddhkpIJ2*J^#vgchs_m}=u+5~sq_3*=@trW$jOH3OhiHPl4RtelI6wmm% z6koXfFk4YK>1EVlTSgrH<_!M9<>!!Wu&<8kPn~?=@FReV44!QYDX zgZI2|XXotue2nsCLGWq<1OW_NUS;%mTpfS-kKYU*4BzufjFW`c4g}p?r+6kVDSPL6 z^n9=whK?P6>kQv>Vy3k3lD)e&bc(_Eio3q-#4@pDct2y|W*|sjLWtC7(FN{~ji}?R z@2np^dB%|}F84}9&eBUIa^g7FzN*5qhc~`9fuNeA7p%qF+g4-FHU1XGR6=*_zIT`H zAwH~;gDEUs8-C?m#dv%IwFU0jBM#izxhn^p+RNf&dP4|%XbSCP62a*CsU91yy&m=X z!h!ejx9i3xA72JajIf8@z}<3s!K{5|w5u1xD2N(LWFM?ubrrzCBegKq50+fKB8JAs z$l(WdWvJL-!wZd}KB9g^k`t{w9~|i%PulEbjWwBQGsvC{48jSeBOiGC7Mu$|AVuYL z5CbPTP>32HaVt)rYdvzCwnzH7u}jDuu+b+y$Y^WTHp6TPHpjy4dUphn6Rs58a56b? z(zM#Jnpu^31%PcES9#Fj#y2a~ps9S_);;N$rpuk+6MpTCL$^(Wcko0_y{YEf>B!a& zI(a?jchh>3BL@yn!>}=4Uo6JJ&k=8?~#7;;E-h+gCh` zfua8NNT@axojA6Zv{8e4)D`oJd>>x1k)+c0bEzA2n($le4-hFPY<-4k}Ty|H~$FDxDaMI-}gbnw(EhBc|_ z`T{1Pgkq?D0nuc&8%7%Y926c&CIW{o%~wFU2|{sofK`GD==&ZKk3Lb;f_!K?&F?R&SX!5k*Y zz(XNI^PVnAHw~i4tuwV4TM+;*WF=Rsi5w4s5zP?51eIoa-dI>}6UR8=a1lG0WksvR zk)ZX#u#0bDpH;yGD3>`|*GiQjpfM|3gNbplR>%mUHA(H+NP`%o!n?9e+#=wU0-`r*%WzN z(n8--mC^)ai}f}>)8(FJ3n>Uo6gi4A>H`Gvh1b%efvMu~nAI@r%3_0E**rr9IP^ma zWo;nnrXw*9{_Ucwu`Aq}RkiT_FozC<0ouS!1=`-By$tKI0R>Jg&rF>KJIO&LaGv41 zG>IOQB#94+mROHRHPI&}sd}W+i@_9bfp*2X-YI@`F{Me+D2F-TabS_yiHK}~?_>F* z%Ny>rZ)bht6U)bgLY4^>otDYECW~RrNBt>iCa82LNt!q_lp>(bq&2g_+H(#i0p{zb zMsA&}gVLl~EEiTytJT~ujGfh)@5x%^2I$|7?NG@fJn-}U zqQj;h)QL$Mpal`M@gALTG_bMZjNt^E)>%DSHj4$3$Hw1H#|;!Ou&Oa*L!T}rrXJ;E za%?VmL=@7grUuWUTw`(FLO`kAY!Z}#_Yn%sa7a+-QG=Tk01&W8mk7!@)(1Ox4YYw2 ze;0gAr?j_R;h}H)dd4jTHjMc+x>u?t9I`nwH(| z)-YL@t0_|?WYLp#qo|kbb-6@ZBF}RuCTrVItG!~!Nb!v(rfnA?n@tefDUo|0j3aM| zx_@FnPWIpWVvOoM(BY{w&ht{ZL#k51+x0Ws}%3yw+Xw zVb}ficqipvjOalM<)xI->3(V~q2{I%8r^SqV0>(N-?!&^?AY_q|K9ii;MM=+>u-BH zO5B3W?1de?Z#lQSrCD44 zrRV-s@nF2i2bZs`>1If5_#-8F#x0V?e4qIAA0K8)vMPZKk~SE)Z%=9?;+u) z2c2YZR8`j?~nAtrNs%2*vi3#;$TJy-YW>mL1)q^(kCAJF{iVbI4J4V|1^6dJpAEb z_7S@wyZt5I%~M8;LK-|C*s|hFW`63!n3?^SFc{X_A~eY@g;h6=b@c*JJ*M&o)YdQZm~(WPmi(o zU+IL)Ce{vLVnl5Ft#MTDAU%F=yY=#qvfSe4f=XY)G=Q4i?$2lMx$jS%D(?8?@4ou| zH(IxIHxM+<8$a~M4=G(4(W6CH?;=sGbPJS2O{axHs zW4_59S6nDA=pK3UH?e+6T=T-%QM)MocDLOILhg~YIQ(aDvU&W#~ETWB}LxNj^W z%JRoJPe%yfa|?pxFsfWA<10ynguq`0#)J{PkC!YyY$MUp)8Ig+J!Y zb!5@DINGme=X6G-qyl{=azeH`Anp9)+%H zpBPuH-t=q?w0tCdZnfI-99ca?GCe;&-Efu$X9MSR1QU`W?zvptj|LKW5DC(xp|S%H zank7i7rWg}+sz21cf9b6PkNSf@yf*pF4H7PryQZuqIP_W>ZC2Iu@Z^GjnURVI>E#G z7_X`Z2uQ<5W!d1h1dnXF!90MD&2HSmICI9qO(=-Ut{D`M2&i?YMbCD|Q=@r^y9(2X zlzbgNOMZ#i1*Y%t3qV49CS28OK4#4pMWwd{3_vsR(W}V0HVM%kv~tnQP3_mctJxnB zZ9$;(;9Y`!U=s%+p-Ts{c3{8pgXp>8*f^PqPiL0TV!`*eU~5=v2hkg=mJ9qHbOk|9 zo)cYregZBwy746Fa!Wq62_|$4ez=^bbEzLzFqWomsxR^i1R^ys<%42?JovSfd~4cP zRIv}uMxt^`Jhq0OZaM9!=nB|UrKP>u$jSCk$uO!?ODd2y3o1!-NkovkG5o+anJ{c@ zD9~H5cw{bW8WS($Ko92hT-~6boA=&vit5y7wj8G5@G14B6dU($JasT5cwdNT4t`EA zE3i0NZM@VjG%}h7G<)2!Jl*$3gcQ+i3}J zxVp7$q%m`adMb5@j)tPpmZ4$TpIR_VpQX-K19$$W>8i;a4l(hmpR~2_jI3Ulo`HZJ zEYRhoXu!8z(Zd(@>5#G$BR32u5CiCQDpzWEX?r@gf*Rm~wHdS*yUiiG0KCpRO$+9c z!&v%sDf&b8@N&Gk0d%D2%ZAbbc??IT`deDd|``-HA*f7m~ zfZnH48BJ=JapYE{Q;8bIhWS5D=Im#2ZIJ{o+LK*-UUPbMhERsFMFsGRA&1atYT)>J z#ULG{!1G5_@?NP6Qt5beyQlQb_mCE)Umc51>AjrZasx(=u{Zz z7eQ#Kcp3nd+<}8$p%7Ces5)c+UfHyB9qd{{eU~BptA0zF%M+l3Vv$yMo+C@HNmIic zWMrg8-WSM&^ovlbexq|1MQ_(y`d;IJ5j?uA$coS)roQ`r^M({KG>XYY3n2{(-rcZ1 zWb_|q*J?!a*Bj&{FbbCPD$cqAewgw|_Rrn4TxUKTD(f-yR-;H;amsbUJVwUJo07cg z`cPH2XN-lqwzNlmv*_K26$7D9l7#)#P;Qbnqc(<+foT#Nbb(35F3C(1sXd9BdEg3? z)XX`R*0|NeqGZbo=ooZ#C_HpR$q}(+q=t=4T9cB(X+z z@pDkQ9I$#4D=SWhPErVG#llO?2Rv^UWtk!0fGrLUhx)*MZ7P76g3*&^MRt@VV+IM! zWt$EV9Nlc*`4z16AL9l$US2ce z6#p4Mw%5i=?h%ct8R5LPtv)uiETgbo7PMPZGm zVvwZEep1h75a9aFbYn0-$dE-N1PHpC)7Rjub zGoJ5Nf{!Y55`cTrpg^n zmD+wfFm>lC${>ss&zbU$aO-k9)rG98Qch>CP*;PdxSD9LA~$isHO%?OP0ji9!maN$ z=UIQ?thW_+c=C#^FR~o>L$m=m{w0onD+Db5{Fs7xowh7uFpS~jeR^uVpO0A`ygYm2 z=O2{cPl3!toZ-*^_kVrvzj@z}$?xSq`Wvqk@A}Cn@4WM~=8ikqnUAb>^WqkE2(9=+O2-)Rh0*Lv|03eEJXX{%gwVvxh!=NcSJ+w&uYI!L!>VQNR6= zNzH%#{=bqa?)U%cyR7n!=Qx2DNWuI;_WZ{D>feM@4+N4g7OpUPa&o6Q_~O)=2M?K- zUK+K`zxKr2o#Lwwy8r*sZ9!$g&K`X5m#$pC{FXa^`3JxH>h^Wp@7(#)lP}%-h<`{N z^vD!PWBc;*GCXV)>%a5uZ|`h>;a@*|LmY0o2ay4P@GIM|i0{5!zJxn*@~{2j-A`ZM zzFX20@BZ^Yzw=3Pz@tX`!A76~gi7N36O?-J#kcP^h?Moo6{+eMFokAFE_ ze#T(e?8=pIf7@L2n~(mV@w_FSx%3%Me)`I1zM@hzXbv4Zane2U_OF?v??!s!=)2FH z!B?8|(n&w)9yQ-jew(S=n%`p{bGq`8GZ?afju3h7BQ@aD%-CC!^Zz8$1A4{8+MGg+ zmJ;qh31t81k&l|M#rJQr^XVh~VDvweJc0iYacYBeq7y&~dg`|>d{U=VD_U+J{{z%G z@Gpt-bP&yIOfCy+H~!T({!w=F`R8ASr#}0gFFyU)_OZ*w{hz#~7<+mbaHJWdYC*F- z$$8jg>epTcfkv|+XqpS3ycJ{nR1{f{stl1A|G_a#bc+9L^M#O|Ja$YelQ+HneUBY| z%oLZ32tlM55S5zHc^58}Pe7SF(f7AD*cr8aSZej0Pn*cs5d~Q0$NC_bn zQQv|4=u-CY?4WU}E(zNKT$Q*!h+>Y^sgJp6N$0bZthoo`S?>GYu>VCLv;EEq2stvO z9MKJO-o{T$5){H`g6$n2F_$CjKH z9Sk9d;6R#?ab{>RllB=KlF|79fZ}$u$9J{-5&_|94sCh_jo37vXZG&~l}VoHAq1Kg z*@2L)^kDf0D|=GQjR1_#V^hl0O-yLO3ppK@B3f_2+N6E#jq4MOs%410NVSIXR0V7k zWTG&=F}`O-Q%+pj^ns6YsHKOE=Mb(OEI}cyQf_+{XEb4!LDj9a=AAmk%R zQcs;I1nE_{ng!#`5eko~7XQ%=USW(J?@hYkVAA;R;V~;QZQ;VeqvvOezM^pIKR{7& zSpr7~b5$T-bdF^0!Chz>@6i_~5^=~EA_4gz$($|oIR{-K$D9K71arg=^-!T)zIV1T z!rWZuKn2)Adze%$lMA~@mC2lEv(A>C5Kb5dG74;$h?9b9N**CW3<6)a^q4oM|Fg{J z1dS~qz@r0F;Bm&MP8I`G&+Z!sN2XfSTm!A|OrLt&dKxHqS+APHc`vKNQ9L_hzC2LL z3YW4K?P=~tango@kaQ*cP6g#yRs$MZ!Z5Amv)?72{^mzdK?&)w4h7GOrl)a1+w7`? zGhs5OEWWIRL3E-|(;rbkMlRi4mzdazxewT_pJYLNv$kzNcfjP7bfp1>bx20?)5 zxx%f)6J&4dz}isMM978KV0TaL8nRMDc7dE3VQiQiN1}9*INAwT_yU>@u%*h4nV9w^ zv(R|y%A-!Sv<>SFYD`SfD53rcznBz1wTK#Ti1+=M z43r#gZ8!6MnS;9r_`j39cBtsH2v73CLAjW0G7iS7)48P$QxsWCOs7k*9^g{bgsNL& zpNmtops5yS-mE?A66|1zT1D!6nxLB2HLYc)ZtTaKAS`)W)6E@2!3v8vE-AFqt0RRN zk=WB63*)Ej7S83M5s9{WlUN1ok0qzA!4;_oYXs;O1YR;>LdcEd#U~)|4Runp9B@g> zK8n!QdfMh$tJSLU>vh*lt^gx`(+0g>;g?#O$zTqJWkMA> z{Xka4AP8n1NWHj4YsL{MVL=g#q(~Qw+8+RbA@4#ytAo#~4x)a*{vPA zMqxk=e%;Ny-5|xTUhe118RA8O=~7PWP1-K!Xfc>c(C7_lkIk2E6;jyX6}mxuS6RO| z5C}JU?hkYV;DD}MmUX~)E#%sjou!Pwn(``N4~T|uO3Zh=9xI?|Fj#7kr96Zh|5dy5gpH6P9@2=V>}y7PGnqE4M?wYFS)2R5(fLdP8=s zN^&y>8OkCI#EuC$!9@QW5>^j2huX-|Haw%ImqD4LwM7MX> z%bDmy7n3IX|H!R)W6s;4o=^YsJAOhr_=kS>Vd?bl#_EX$i80>R1c3E@jl>e^2{ zQP(g3;V0g;-PywbzJC4c)u)b$gMN|xqxLyE}3ubeo3{KN|< zfZ)UlNzU)lRrW)WJZiq3JQ0NPejjb~lKVH;Ut_&}^vIp-V1yYfT$r&*h=v1a?w>H9 zH;G`P{g{DhmXt{qLB6pS+PoXB(g0 z&0`k>6$CqISex|uzm45A28ll>8vx1dO}}%nv>P`OK_PNi&t5&AWhYNc8sK3KP!uc1c{_$jzCA5-_AHp~ zJ0E}N==&F4_b}xvTg5n?-;?Y9LG!_jQTqJE_9WFLOy?vhM6N&EA2;<=+y8L+iOU$< z)8O0@L}RG<@}pGD@#BIZ-v>e1i*oaRo6o=uPr*sG7t`nOrUQ#$#bwV|mc2Zk*8eiF zk1z>o_-O$4fTn#dp=MpP#Y`%mjJ}gM9i#Yw8-27U-*Pd-TdzE26eQpA8gtwLrgn?Y zq>1Ma62)#)>veR#Nih5?JjKA$45KI4U{WXWmwMuJM@5iPaaK?4F8CR*9T0m~aM^ga zl$eyNhgtRtrWy1mmco$gqlA;47sI!50+119_jF_gwo))M1TMzYOKOs!K$Vxcg{enB z#7s$0^UFT>pFn`1kX;&Ke(;#!&eY%sIW=+G zj1gm|S|4y~8pn@KZ>pHsPz6&N;MUO$-Wg{Hmpa!`H>yo|C6#7&$m9#g6w0Yc@NlFD z{Mb78d7D-si`vAesi&c^$DK8K#}3L^p?x=9ck{^vGIO-|d@w#`{1i3&>mI3d15Se3 zuqlez)NNL@N>oCm2LWjjgl9~qX>FG&a_T;?=~f25>yZ&9BNMV9Tx63EN~RHAfo`Jm z8|V#fblH#@*IO!6$#|}D)Of~opG?_)0D$uzs{~|iQxIE|dXPGq$r`2@Pl7JskcJ(I z>Och8rRI%h$bzQPY_XywP%;yWzk0|RQ?N%94V}F|jRF$MS%$dndlMMMhMd({8l?1d zRQUi@-W{13L#NO;U?Vf2mUC5-yP2z0g@lbS4OJ&>j^KT>Ro_h6h!O%v%eNJk(sq|7 zF|nx9dS@LbiVOaldT^AER)Wu*2Xo*kqoD%PS|G7%+Q2li!kvvRbHi4yvA#Co&P>qM zEi%;m(OEDQz!6t%?m+%hWZnV1>&OJE3jW@gNe}>X3Fr^EkZ7k|){YhfOHP9c#(^X) zp~z8|M^4@Kj;*_gKfWQwkg<=gT2L({NH`G-)Z9Z-S^Ct~rk7Eu0x_0hrTLJ0bZ|3P z5ZJd?3)p%+T@XMmjBR|$k9nh-SvPH9leM$~Cd_jO+UQ)Bu{z9JM%2*fY))Lsnh1msyRQU7KhR0S3` zJJUW?PX1=Hu1sw$q6!*ONSnB6Rn1W=FN+2v*nW}CmzB5O+|{+qT!U9dW46%4AR)~% zbcx|>0v7l%Rdab!b7~8ZTCmrQ&S0)a@bF%?x#iDf+YgEgkFz2ZqpC5x#szQF+E285J6Vzx(^XZG^4jB0GYZ^y?q0dmQ-sGElhJr_CYtU`9|NX3-`K8O?$7lJZs@MHw zM&G-1n9;a-Z`UQgz6@@&+EmVX%yLZqWmU79xgMOjTs6M+88Q~l48@7*YMu2MtnYfyVBsu{!RAGU2=ojH zvXqui=Pk=TpFoCW019Jehdnn{o_Q1agV#-8SYXQu_n`~~6vl6$(rN~vyuC7;WLPwq zRrBhKrmF0k5sMCaouuB*YPieo&?kM@4NwRC65$u;mUO*`H;);BaaJXoQ5}Cxf`U)y zD%R}6_M&@rv{LODFcbAZXwHo42-z}$(59;752W2dAU0z~mF{yf1 zHtP|SV|`X{^QkZur4L3G=3)HMh%(jG%pUBmP1O@4J%B^UazNQ9tFSd{)$Xwc5Czsa3Qsh9Es8;=X~l6&Q>iQdNv-PDinMpclFv zdUYK(j40$h&_`-k*w+ig+B4l!<0b>*Io|j@UFTIE=*WD=>fqQk>uf6VMxDQ|H-JB>H{8m=AoQ!w=H)G0;=_DUSHf*FPf3l_8-shupj!__j`pahg){z5tH$tOAMcIn>BGM&KZSAf zfs@~H2pQ6Be(qmfe(9Ni_itW>iw(9S?)J$;Ctt!!+=B)u-ygmETQ5pS{mv)<{Lg>( z;SZe?$6N0w9=Y;}0mFOa@BZqm%O_u=*G89wg2hdRa?m2h;NGX`;HX1>>)!vCuz6@<@y-+$HXpUnN9}XQ9@w}E zd^C`JaqyHPMy;Go>uv19{iIZ*SmeyzWU`0Uxq-ibI*ItC1ENBHR=$)YeQ#!V+Z^$S3Pf7H|14VPTa_3MxK+4lYC6nDh` z)doNQCwjN9!n+m(_w3wr_#KBYESKX zVJnsJJoH>f7aGe4lFVM?M3FEwDW=ilQ%c?WQ8xaLFM2R)C3TEj;GY%v^Z=_b2U}?) zFa>nY)$xO+L4pc6jcmTrlJRG!33>24=*9-HUKylH1g)Z*^t1|`E;Bd~2GhFM8I;vr ztq3x3J#IJIPz?iqJw0sL(t7&6?b$s{hb;9BhoWuL%%#hUrPfv+j!B;I3H0PF=i8ii zfvZDZ&}zdbR+g9{@3SGLj}Z}WTi~B}*?`3)wiuZS{fuOo38Q&yVTiOUtu8ZSFh<*^ zveswmbnOeboYktq#H}q|?+d?Pxmo3eTo_N`@GFffPkxE5a!_1k3(bo5;%K>qGo(S5 z0JHN=fV4C7U1HR-UMU>Pdv+BTw&$5P4@*G9ANj=I!fZ>Oje~Yd5;XMr($`G}HUZ z@(KqpH+E$wX~kez&uL4l0g6dGuHm7v*JvrBqz0vv+<_b|&L1XmY^OWPO|s9$j0TkxYrfssD|nuK}n5V`1SsG)IoM&&yTB5oUNVAeaP zR11r~>^bO|deU)b*HMY+sJ^WtGn{e2(&d>JZbhr4%ZUS6Bx12bmk`$n8gI>=uAuEZ zN}wHKQ{tbL*tl}ewKTA)jfhc>mBg^ug2N65!N?(G-hv)*zs(iSWD{m!H4O+kPr;xu zLl5jsIJ&7qiW~X@LbLONJYccXTbao`QtbwfA#u0MRp?PRucjCrm`;lgcsk?J08!|w z%-OoL&f7^b^Z_)u^0yTqUpx&n7rfM7y`<41_?L!-&CJ(5G&+taOVkeff&3{vVXmrM zZGv((NeAqL&zRgB)`>o^7`xDu@)pVQML`^yC*e5g84JMym%0gKFde!s2QRN1jC8}P zT~s-0+PPU*6N?naw6V*+oiEq(0kSBTEfDf%{46=9Yh%|*;};z=1WAF4?-Vc?IQ_I) zFN!&Jvd!8Ji1pVXlH}#o8@IV;(OVZX-}sH`gIoK_db1qt;BB{2wiq)c73^Tn27@IY zShLaITS3gZ0JUd;3f^m)z-m7R0C>`Y&#;y6&BQ?ufpOnK>%jnC zSQH&l21vLpABG-mAo?1pZ0mKM2a!)^2LOP4!vN^{(sT*=4Yi>MP1`%aGBXG#%>5RP z>J49vg#TUxVMVXg=SksL&B83qdgzwx3E~AqQLZ`XeONk=wmNIshGQg_39ARjKl$EC z+5_SA1I|rb=F8BRH3Yl_>^;eu+er2BAzB;9io02Yco&5$R)c9B$?aq@fX8E0pF5T! zl7;D$f$_w>$3AJ|Qbsc=pd2R4#^#KI#QQ}LuyH{=07B2`gbWf;2M7qJVf&$2xrPrl zr=)q$z~lHwmV$0FZ;@*tv0HB1b%nS}RxTFB5OUVw*6|_8HpL1VvD6PRRc2U*h0yG5 z$g)k{LtACq@`<|nSs+N?K9Ty2VjNaB zgy74)8SgySXUwUXBMB9LX!ovYuXQOVM{fFp<^9+v?ml;R=YgHiJou@PoxX7T!qLkg z`Mge%k}mML-<3YM1lU31kACuZ@fAhDZO@5)D@;?l{n*`~I45rR5xC~UT%^bTdw=l# zS8tZI?;&_MHqNo_R+6Odp?Cb|@twmv4}RujpArO@k46ZLbb*-*`PHi`QFfpOL2<{= z+#ewl7Y+-~!Zek+d&fh+3DhRyk%Ky-@(xOcemfYc;g56|AJ1660Q*6k!61D zvF*|0xT|OTvp2qU{~NHLeHokDmzDE=C;Y=0U;u)*C;$lheuQ8w9{_-2kIyasAsXfI z*JZ68Bl(wQ*!@dic!R90bE;Np^e$QE#~!G25&W_R%f z1b<@8pB#DY$j*D-v$OLD0AAexg&RkX?A#%V5XpY;hrpbUdhZ42+2erqm8ZelxnDYd z{rJG4W(-ovnZN#Rqj~XHw!-R1i|u1Rw_lfs;`_`97O0XRpgDlxlSiKY)|D5q+o1E@ zm<17c*3)+T{mZXzJ!9f0z*L>+32#=LVIFPg+$VnXp_7<&yZl{77;@(LJDntU`SSNJ z>+}PqKj?PL=R*(yptB+X6hs4>Pz zFg}3>DqmdL47*8!^?aMzkLSQ9ggH^=0&yZ30}rEPhwB(HRxnk8G*p0)ioFFGjS%z$ zE~Y1%S1j%|_cd^AV!XsCqZSZdNZ7J(+9Wn35VPe%ij7zaKL`7Rwi5=jf#pj4gg;~1 zufoRUUF}&W6(9>7KE`{F3dt!G5}_`cIN(Ww#tahWfKk#y$VkPrvIb3Gw!bvrz!e;PG8kDw5;hLx z&d|RDko2}+!7@X}*;4EP7Hq*9HI{k@>SVCNPqAtq&o4T##thANCNlJkoEe=tc6SvZ zECP%|u;&))S}y%(2lhv|4_Oaayz^j|Rm1!@p$6#}T*(|x>%`LC>{1sEYf=uWgJL+1 zuj4=`xQ?J#axPvyS3iQ%GIbC$fN_n&FcYaK?$T3tTFD`AxnBF#oZY8t3~o#_>AWb3 z0k6u0qMcnjYVWBxCpS<^(f2k*eq+|GX&n{oySA)a@%SnBmaBM-O9Dt>-2`V`3Vd2R ze3u&w@6m%!q;ppy_S=WDwq)3No6^o82R2K+DbgBa6y%hk2|i>AGYipiUqP7h5NIqz z5c|{kb9fx{W|-e9eteqc!D47In`SF6@M^uw;a6j+fc|xu9Vlnc<`eAD1()}}2V~}! z&si#%?$fe{bxH@KpX^c?<&)fX;L;%Bvw@SPQRr}R^T`Ks)tLd)@YL~kCxPHaf*-4h z>XGP~`!F*tkHumNNny4uk<@SLGI}9r+R1^j5-~~qYEgnA!}?=1v=Z7)(Kf&+)~cU_ zIj!0M5X(R%Z0EH2Yaqy$OAO;xpj2eKoDG|#XFj-1lk`aTFw%@)f(33id7oecEf;jg zQL=;6h=}jZu9B=csem9;LNr$Xq(CAxAK-+=_yxj*}S;!&4t=+A<6CX>RMDv#C5RUxagzdaq^` z@+e69hiAC~XC;Wkw!r(L&lb8i5u`L1$#%x3p>M`Vjm5^a#*A5{Ca$B;1S5$3fXfKAt zsw*98*U(lyA53uQ)oQsgSQPAwDrb;6tzrl?akSprSG&vbEhrd40EuLXcN1sWNX#s) zrQ4c>z@F9cvP;&AVYN*9!GyJ28_Oyntp-q52I3SHeNwCvPE|v$e4b_*g$}C)XWcGoGj8S#-zL=8+l5w@gAkk_ac0v*9NC!j z@y?VVzfE{B%pDx^-FOGn$9Hh%d(ZR4*R0k*?}rq?ofRzJ58u1@u7LgSV;}p}r#|wL z&wpNim)y9Ky*s=6?vH=``jH#bWelzvV5Tjht-d9OZO@0RH@;i+d-KM+jcIX@6a@FcG!Ou~dHl zpSr~Qzo@*^7a$OD!1K@l{H05rY5k(P@=L$;9h_{er_UUE>C^w_8?Uav^|e=ILH(hB zz?2rq9>T=~v-5CR8XgZ-`Zys^Ib2yE_?aKwLY=hwC$`N+TgmpWzKfw1VTa+Utz zPd)hGn-?SMb{jA%T~OSFfW{I8vaznb!!y74@7yoF=QpKWUjCK8{5Enz;^D-VJMY9i zJVxT-Mcf1d}?gQNi zo;vo{V;8T~U%d9rDZhjM#791I`ohH>nJ>d$*)~C6`r5UTRwE01I~?%`jpXtvc;zyz zt~SsqYFK2~3FOA4H#o$MhjM#K)%zevi2a1Zov_T;y6ywQE#Y{>0~WryAA(ZRfgzqa z2d2(AQ2%qp-(!y*MY01va7qkv7IrE~M*D!A;uafRVj@xM8yt5Ge{K1O8o%d#v7qho z@%N1o2p0JZ7r#gzLna8Gi#WH=`n#o1zn5C)v?BztBTo1pwk|Av z=dPWHV;k(!3$prTeU7$J&U5e7sX~&zBtF_ufZuc?IGJN>qrC z5PIIp6<{3I7f`+PRcx6ULW@utrwVyJ$yrIQB@xgxdboI7gNCg2-UAdjZU0s1ZB7l% z_jcD0gqSD3;=AukmY6K`ZR+Hud_B#@E$GKiGG{MdBmzElk%!X|FoH_-35*w7tlD&r zoE!2}+S?tTKKiINR3%7*K13ff5@@#0a+?m?X7O**=_)lV+r!{!YWR^cs?RIiFdzod zJC}ni3~E3C25~PTJq*5KY&iD4yREicfGS0vY$tHm%;`Vwj=13AT#dNa?7VElol}X+ zBmiOK4WN<+iNPsImSiS2Y_AMY1z5qHusoj`N&eOwe5crT1`jaHu*zF15D6|^g1e5DBj3ZC?2p2Glv)S=2T4xM_FADChTW0L`6q4*(6+64NQ{kEx% z0g+QQQje~RH-!3q0MB;x{{YQ^J}hR2#>28Qy}vBW*|IL-Vxd$jJ59#UNEcupk`rT; zJ$??L37$jaJz~%XYfX8Y5BO+qF}^~(8S1t|I-$q&fD6o#mY7*N=>pBs^PG~@0qDj| zT;^4isjszUr0lAVWsM9xgCDfDaT7b3-dHA@$8rORGlZrk>gxy~ObUpOK%O;*nLxh{ z)M7XQ0Nq3w{VnGLeW13)vbMvU3PWOI@N{lY@QPm#aKtJ@%1c6@nU+yO^(}zOxn2er zaSVk)_t8PgF~$Dq&s3 zxIqu*g*=Ag)l^*pkJ1$Dv@Ox0Sf;DILQKKY6yRtSwZ6qu|WCi=0I1s8MGb`>XtF_s*ZQ4R)k&Q5!J z0DK*cnE1`YcKL?PHx8a^%z|tX${xD;RAMZ%4GZ-WO%)VtkfuR#8hu=qy5GSprlN4> zncN*s763mW0iI4AbeA=3T5+_oRO0%^&$S|Lg7rBBGN1Xd-Kbf#Y*z zx`%=TxmKK>&cvx1(wnfUT-j_Uv#`H(Jxhlnr=b{NlSLWkuJ=?f%&HmSWV3bV?BJSq z0zr^wEC&OPE6n{GHadh_KOmUXvziV=&nV?^E;FlE;GUR?&w>UrbcG3Rk1;yPphH@- zY9DZFyJYU^ua17}781(=>70m>A8q#e9?^^$Vii6enhnDq`E;1nmZ@qQv*9RjEDt2@ ztf%J}X6V_Tz}rRtoGCT{m51!%8>l)UuW8fJ&<9+yG;_R)hM`Ds$Jb{`Doz-OXiBfS zWjA$9b)>r%w6W5&W^r{^D%yz`l>$-*)D_C2IxJ2Z^H}}OY-J4v0CGZltk1g*!W^W% z%}rL=%Jh?f69+tGy+ycT$_Sn2Ovb=>#|6i@MqOuDb3dbBYZEpYv;)Nt{i4l0L|vRW zDV51K4J7iA)hUZ<7OG7}KpxVp@4Ipn6mh?6BCZX>vU?xj&o^e|TepYLc;V*vRx$j% zl5zn%-^J%^b9ltk@6~-bXYPkj-7Mwa5sT-2FZ^cE-oyJhdrzm4DCcNqj%Su$b$->p zOCeGJ`*+^=v`%9lW8Qb)(e25T`PHWmKlOmw2AxtK_rN+CI>tgnRws=sc75{fN!_1+ zK0Eoqu?L>g^M04T|KhB^IQs0IID3LkI_k|k7b9)}rlJsWJd@emzX+@M>=^UD`^@DN zCpazr@G&4T=Qy@GmZp=T73*|7CTSOf>}>YjbK$vT$Fh@$j~#vu1Y?e)4Ji#X@kl@N z5$uenh7(i_d))2KJSwPLN(&!Pl;xJuXdaoiKjki%|m{e2KHa4@V@zkNVq!;0r3_;mE4IcKE~zVcBxB5vDWB_biWn@0q`zf)Kt20wa5APf$K$ zs!6!h6pz}ECSPW4iF|G5-J_>|V}03jKl0J!t3fmOQ-ABD{nz?=^!aA^JUN_6E;Gq= z|Ed*EZA{?r7LILsBRu-|JiXST6MqTZGh)4jI=*6i{OoI|IQff4*dBfCF`Yy{Ce}Dr zh|cFmq~N`>`mYe3a`ryZxC9JV?~7 zg5n}-iafDl@Zs$xr+$2=#*}8G^x{Xp^DBS)4}NY>68`7|(kCEap|HDdyJZ9a^f-$& zB{iWmTV=goobkPQ`|sz@aq2oS??FJ4*dwaV9@efl7rnxmumARY$~{T=JqXM`2srp1 zkodzLPAgt4cVyE$o2SwB@}kMn7-2PBnFd8lySbad+86};cVS<-K_@nvFBjF zaj%3r<09SL*k(6DOlfJCsqu`2T;AUM7z)cK_9CDm8XUd$UG`v;7u!wG){+criqe3h zfCeOrC$@<+D!36FXbn*^ld-NiT;aDUEmuZhUl9wwDRJaqL(++3x95gqBPpEgwa$-T zYEl8N8aXH70zlwdXqW!vgsBQg8GC+khOXfP1n_l86CZUoy+}*|K#A-l35=;+>6}6j zxR~&kUrKhd6ENI6`c7NghZf?hUU`2H!-c?&H8IbMYmchnYF z)rdXmwV57UXw3JAUDMH1T(?~p>wbF=Qn@{+Hq}pF>`UuCe|h3Zmnk$lHuEvs-uu40 zr^fW0r#bu5R!E9E`1+3I5acWz>o!Asx#-}_G74x|B&)gq-|d}ks4U5O->ZAN@6KF~ zyfe!Rlpv()a1o2X_<&YKAqU;+%bKjdtss{qpu|^>a*2bm^hKb=(W-8D&w2&|o`GPv zSc!XNmcZg@7a>9t>{SnIvLB^D{K<*ECc^8W4?6L#yjf|j$?so1ectYyRxfyM*K^Kv zy;nc=ua~Z>r(X2K&otB9d3B4j7~aRRR8DrR3MC03I-Pc`q0joU` zG~<3zKa4%`Qkj*tGI5-~1!Cq+=sROpY=p2Vfg7b9>R}5{Ms63#1@i)qIn}@_Gcy)_ zWZc?qsaT}iImVufuVSWB)W{!MymB^Mm5t+tz}+%b?=r(E750o9xm2tuwu-=dE#)g) zjHecDq=-O7AR-VEhzQ&pfkfYBi@T;FGiMUlnZ#rE*l^%KI=(M_^unkBQ}||T@-lVu zVdiGjc%yT37({TwC7*i3j|r(XQ|~Zzte7qvaYchkH#-@fo*Yy@!zF+dgiNUOA@|A2Motw}q^bj*A4T8}@QP1Dj5BAe3fa<#N~AyDM4 zo+(K!q;mmA4i|EI*MvP%gl~Q8JKLdc%7!jSgUi_KhN&)VV7I z)U$`p*CW>l1ZNW2nKW@Trh)0h5vg8otea-!B00(AuuYS(Ee&UDcal8tdZu3QMhFzC zY>RH4uPMQuvlax7q; zGHOI_(m1o+*lug>e8h-hlp&T{5cVwP7#x2VuD#-gZ3LxFX3KU&SwKRR!+F!v)%21U zwPwT_Sqw-yh(=Md1rq__G-uvEA9K7=TG|qU94oY3IkuK@6XLQlJ8jD-w(8mqvS0@29Wn)A zA0@g}1c{^NoazN4ku00racZYcYSX5yrIq%Fngw6|u=UGc#^bIB7QaKR>k2*(!*gaR3 zS>Bq9w4O1)Q%;s+qy}!}0Nfd5g{+!wwF)+82*S)nRv=#E7^2aZVnGhsoEz*pSc&7} zIJ9Q7=H#Af?br&)#zf0jX-4;3#!C}#Ia>-}wArQQ6G3_@VCQL_B#6)wj>C1N41olo zOE8fj%Mt}GL6S{v6Sjks7-b4BIz+iJMY32U&8V1L;3^(hb234_D0t3V!a5=l8j5F| zw21|bi^NJ@?k`@FwnejSDvlIjs%0`kdfilIYK%48dNG>RL{TM0_-rvsqh_%n+-=fH z*{zaUu{4EU7{?;r8BGg5DLut@-V_tA+GS3z<7glj{SsxBUF3iz*uF?v*P64Am606_ zEX~G_mPp>XW7*k`GO<`W3Wi!1_H|P8JGQZQ-m-Xe-PWEHjz`Al(Hw0n~7`SEp6f18p$n4grP1kxDshW(a7v`r3no~xJX*RkVLz@#9A`4FP+k`L($x8Uvo%GV zl!;m-mML+-zL^ojd2-EqU1+@o^C1))Kc18{O)Ee0ncX1GZYJ%rNK0@eGiIfySH?|$ z^Sm1sZO7SCsj*epYG>=XSY~BW0bd`H&gf)K{Hl=;$ zGn2{HSFc|A#y4KQa%e^-m`AU^s@1GoMXPnJU;hsu{eVuc(dxLXxaozz@f%OGvh~gz zl1N3R+mQ|ryKcwLJ>p;lDL&nGq*IcAeRP`>Yc)HsDSO@4G27eD~egZu8ue_ ziZ_dIh5YsUZ>EwdXmy<2KK>uazxa!n-eh&;p|KPr=*|Ck`}cJc zlx`V9BC(r}ZH8##(<~Hxy+0#Lr!?)3ZXVyb!P-ieOiB)-Rj4=F`zkrx;cHJnty6v_ z)ln=V&D>#hhu{{C&P znAI&wx)tXpD>$V;eC^t`kZE@J9mS#;#2Fd(wDjlb8S^#vvm)KQ{Hf#x%L!2IclAax zJDu<(Dc=>-T4Z%ps8tB59j_}RY2LR+|3x8@;;E(URfV+SEU0J9EBG@xQb1yo`zxat z2zP-f;Z_o{r=Ta;=PF5`yr?uvrneUu^`XK#*B7f7`Mi9E1+&*fsr!zld}b`DMN#QP z49$T}yCdy39^{9=`})go$p3KX_gN;w8}=NK5SpemdB6Ei;6O6H-S~|&-W8+H&(_`A z%6p@enSfjQ%{|N0hgg{YMa)Q?;eh3(a)PqQANt$Mg;UviZ?C8JL~|ljxE1O8caix+ zH;(m0SXjSQ2MtT=C3n+%gE`3mq|?plh!J^J_8pZdtq7K^x%Wlvds+G6)n01P!rCAm z9NY(WxE1O8cYB@>FLFRKkG^)61EHhPx*1(>CfU2=uO1(3MX+SeL(D^(53ly;WFeKj z3kMkmFHpyGYY>MxTl({gVHf8;ksk^*mk6l+-AnM?^QL)I`c*m<2#fpq> z718O7_d3VjCR$x6rZaZx0&s3ko^%!ujAg9CR3n&YoE*Y9;~baYR;968sBASiP;93i z;us1?CdRWIpX#a6>EtOk`h| zl-|r++b}~@>P6m9Jj?e~Kyb4FS}}xSmS)_!S#8~xd%d`uXIAE(>gr3+6d#^*U)xDp zy1ZO$?POcF)+3jvVBJ|Au?i?q&z&KK6i1R?+l|?vr*w78tfL$(7Hu{*Dw=8(r^zf? zb9&Wi)#*D$v}o!|-afOlUjWjF|4gfMa-b5=b^{Cp@hsr4Ih6GF;^|&x>ZfVb*3*&pK@kr#@K2 zby23^<%M6+)u@)`d{LAhY5r)_5x68xcM#VFQ;4;+zGJ&VP4mWKRaSYDS4~YVL$_fz ziqtc4CKGwiD3ek9c+;($4Rd5|(op$ZlZVnk2}(A0X>7YKwRfDdm2eSP)`E#*xj>a= z78C$7N+M-7Ntc_JIa{tQV2F$z1uSFJ2*s2G&p3dJ7KwRWE>*BZRPamkO_AiLbXlh< z1v9F(r`RxVub05JVLdTdlCyG_B1ueE;m#4$uM^HM7rY`?!BSjkj?iZ?Mq}&OOdlGm z;=U%eG{P+qk0@2lwz+D=XUfhA;Ai9@=Rk85dCr`}ic|SG#*0j7tHSzGy(WuN{GF%E zVGMq`d?c)Az5G_Y}~)xU(#ZdetDYMwM9 zhHJgcg(rRe-sYBh_Qf4b5g}PTdi~&God``&`OJDY4raQZ=g&W{J6v}x4%974!;Uu% z`!#mBe*N$N1MTx8A}wM4S@XttrQ)0Z_4(#qK|ej?K6D)X4)-n}t4 zzYXJB<;aD&pyG|z7Yd)#clSD_f3Ot?kMbuD3@o(mao~XEw$F(JZaO*?2Zs!4o;&*7 zCm**O3x+#|`lXd-_bcY}fdk(2UU7i>9RTgt_ z(a1O44{W|P^2W5!JoTmD^vWj2zz!c8BfrAf*#}kUCO^Z%Ay32jjPVMAO7#e8FhBdu zQ;)VS<_lywOoD2E38cQ@t9QNY3Z+3nXoc|camy7{{BdcO#%3gn61m&G_=CQj^t-Q> z3o4mA&MSKS@sEBKf5(SMSC4*>YIW$(K8*4Bsp~&~T^C80*URe{7%)C{4Dv6jsO(a4 zaOKu5aS-mLf`g8x5_(B9CE8njo&$}Yg{~M@^*PG{F~Y$^ryO9u8wZO1EZJaq_6iB# zb44{}M~6qBxc-UjQs3HzN^Cw1YR^B{ zJ|}x|q=XJ(?x#L`MJc@(2OUAnFPJc2G{gc2<}3#X=D_?pGkMClfdj48HM{=ya0jMu7;409tDnbX%lNQy5?)6Q7d|u)^5qQmT!q8 zRE4mtN-927p3mu++(vq*sDD^03?D{%7W`7ej0tb|VN2}zdN>1b8Y7|!L~{h^d}uwN zEGib0^%w6?tEIf$gLK?6 z#Zje=(<>A`vw9YZ9|xS$@tcku43cvGg@&;VA4V%J%VeKz<+c`SV9~%D=Zb*9MxCiy zQ&M76lXsLql|n-~tpwkBVlZMzfOt&XLV_H27SS~{EpM9A^)AwuB(J7jMdJy)bw^pF zlUx`-ooB7xCW>@AF4M}Dc1C}Q+@fpVf?q?-FwVZPLhZ%lZtzKt}W{KlZLM-Zu1(z({bZ7fg+0gIq!wZPY_d7kV}3 zE~HVu{J=?Hq>|SXD+Ay~g@qeivnl1mAAwR*VP$Vj(dyOd zK}c^J?=%2PfdO(WCeBARyzi}>89#7)-uOJ3bUFcaqy6F^msSwx^dFj6tC&X z%H1)G)Sm>PSnf@fFRJsjsvMnsPKM%mW@koQvticAaHO&@&ni>9iamp9J8stQXq1`Y zsaepRB#sFkTFHznaFHC3I@UtWSsGJtwHYJtI%)6y?!m=_KC=+M@@CVvDaRw5hHpaG z(#VunzVOjC_~2L9ezn|i7FaeKw~og#Qb4_;ilt;x}C@KGASl@I+&n|Wg3{TcRVU0|ZCQPQS9 zkd$GYR2+;)jDbzY;D3`EOOst_|0duiHFnliDCXPW0KaBn2PiQC7_}PBE+7vT7-( z_{ggyNsQ$>r^HS8NNkuM>LzYQi4|O$J((m)DunJ!MV)!xzO48TteBW8(u`(_^0&!~ zS)mG+)~W9hL9?`^b{z*VXC-He;iIO~Xlrj~eOsxaDC;fJa46qol;Pf5M(}2S-`Afw zK633=7)w8LqgTySz0)Jt1}~3Xn*|y9pkCU$Fp>`R$hBf2$v5tN!BOvsVTdWJcOvkW ze?qyr7x{nnIb$B=<3aBCihQuY^vhJ7Kw6{DQY({@@!WrX^hyR5*rA*wUWAz^v!Eho&#Y$9Xalv>F;iGW3DW=TxxIp4qWW!Srf1*39k*$6`Su52C8!s*7!;=S5`gAbKk6(r7 z-v8ijP{pNaP&vKbWIQ5<` zlKLC;ViQkB%#(~pix%8?M@J}x4E_UiG>1Jk%p@8c>~a_{8~l?+%pDu!NJ!&DUSJ2i z{56J{L_Rz(J~X#a|2P|`U6$H;t5F5f;f>xo^P>%amF<|9p7NPio;NBYW@f8Vr_z#X zjFwp>)K(+vhD6d!WF3>GoLFZ^8P{ksyx_ASKImYakPAANpYi$XvBAeyA77!M@x0|P zgLA8QtSor9gefUsq>5go4xF7EV|A707JH%1agND2E%}n-2~M(1@#&+ik&Hg&3pt#j zgfS5rARARRD@|Xrr6v|U7@bKkEGV6kKQ;{XOCvl_w3s2a{PxE6sLVw9A{Zc4M6rVH+qIooRi#;1R>r0+rH_WlwB$gO^0uuuzH%bP+Pa4kPl@lH8A3E%DCrqdY8egU(()|#36rR4+o4q3Qu~1D7cuW^~(B`&eVJ}P0O;xcW$v6W!M3tq)|wCrho(?w0x$@5NbM$^m%Cne+f|jAGMVNZ{1Y%dhsR>PY^FucKx5WSXLT~+ z)b81YJEa+%w2Qi(w@CIdTd<0aZ1)=4=v9IZ12Gh{ou;wp5*NHSRdwt82Nc zq)WG}*``jY2}pW!W>XRxH|5~@oaksJ{1V}uCy|qSvQAga)uPr-JO&3(3+EBK(pAs- z5>g2at2hZ$Gc`iZ^IcX^Z5gs7DaAA66w>Brrgp~D-cFYY-O<*_U%ka;Qs91$IP7&c zS=V)%vJ)Zi5GZz@w=BrbIXS-?XA{e1p;P6&;n-cC5*=+2J$9_zE?J+x_Bm_9t8~WA zD$A0aVk}ZrSF>^yhJE8;fQHGJC9A(DYsGVpIF~p{+GWi%NjTOvvCCdcRk{BBf6kkC$At`k}ni?l`9tYd&whmzGI>&4Dh*(KHxV_#WRSWTMH zJg%7ST5a3JsTqLtHJm_Ow`6Y!He6cV_h4juO0(H)y)?P!DqR+Q>l>~cxEL(1eMz=a z0&Gi-VzIWTq$m^o$U9$vEK?(-Q#R_jnVMU)T3SOsf^#lvGR(_;l*Rxn@Ns|wZITt2bs&4c~m^OEUfx^xml{|3s}1^ODqG{ncJvz%e-H)1TfQ z{~1@V9vvMZqB}Uy(#;?IVBFtP@;kfVk)QWJ^!|qwj@f||veO$YR(IYs=7~kG_ObUgJ+OoN&OF{e4vL z1ZC&G{_L|~{VHo5zt259NUL_=cVF*iF(3HAAOEosF>hYN`e@g^C3&N0xBCS0E36#U}k!@;6M&>fUc9FUZGb$r-gK z_e#=I%AQGI@6YxzZ?QJ_GzONqjt(&!V;>L7@Q@s_FHfoghX>urTz&Vu5ml3jWA04l z9ux9F(%-|YLEd=$T)X?8p~UGVo`a*^cX!-XWVrqK;NVdfqRReV?=s;mr}w^>6LpTi z_f(LdQ?ikXKPvb0be;p2VkP3B&kEN5B4pIs(o+tQF1Mj+3eg-KUDgVJR{Os7TL-`O z=w3#D%7IQ?lDv5|Qr+U@o4~=1kvqc#_PbwW2|sy-)bNHeHy%C8CB8J@-~FAV*NzX5 zxdC=&EX@l`0C;F&l}|a3VFcMzf!MWHCMUE=dwB6 zT?Nv>gY3_fI9RP@Cs{wA-^sv1X70v;fhVY%QM%OBns=4To4lF_91KNl5*?j}1ifX9L%+V4lrovDrH4r;U(hLQy;)BM$_sU#_&^8K z+#oyRhtcta0lki>!ml9~Yi!nF-}uf{IeSq@#&_)Cw5~zwhJ13`;CqXY4SqY{j**KI zoKZ%2>XDx4dX3wgHEX4Pet}q%u9Vo&j%(aqV%@?@%1CmY%mY(xwxDM(u*notQ|c@u zRn-F9^NO45RtD12{ZKSO71&Jn(6I_Q1lBBp@~*V1e^y74rWWihwhS~g-fLy%^&+xB zB+0aRDue0#BQq}iDH4}>OLubGG_Lmq55$maj$_<}cXx_ogssJ{M4d8}CvhMS{QL|q z3_-z-OIz{LqhBx_omTU-PemU&(S&{qycGy(;Ms2GHuH1Ka^umq_e4IU^YgLl`-~yP zo~GL@;jqZc%!|%5B;KglWW2?fN%r>4uqYZu^YVILGnTQ;G`QZeI>PR zkDsfs16I2-jYR^zL|j8^nNzW8$#&Zb>s7NZTan0y0h3D&s}>nMIFqe-Jw+o$Vx`yV z4iJrbSsPx-d_sJ!LrlxvvB2rlEY@{~#P`!UQaybKRW4HJW$sua5|}e))7z*7)h*AAQ6&vDH+lIH zP7Jr_lJ)#p2sH06MHAc_(+gYVh`qL z-_YA%GsQlfVmnV7r)XTI-n@F_GD|PJ!5sSFnESr?;6v)5my1HltWXL)#ES0f)vFKF zkKVm|_j`R2cnr&d6lU-n!eTtjf&884KsLdLG?4TI2QuG{1FVnf$-mqD9v`nvz6R2M z!QrQovGig|dc`cW^dY?=kZkpnufa8h!Xo%W9sFF^_DAR=ANd|bKtnutlEMzZ`*EO< zA+nR$Wjf2j*|_h%aN6kNw=2%a4C)lcB!+@qgXQ{PM@&3ieywQlj}1PDah_t~zFjGS z4vzBc-@DA6Evzgb?0WS>C&n;YvFAXR_u}9rK+rshgAaa?-U-xmaBwhv_kaER`4~=3 zhmdA&WRvIS`eTo^E%z2vw7$YBZ#`9n^jFqJ_vb`g} zIg9obgR~nKDfDsm&rm-G4o)3<4rC6DfS}zNqk=alG9l<&gzw{KA~rA&+7YxYruC(XZ5GHcj(H&rlpv*gW>LK z|A|&9P#KX)(wk|kILcrv8@Uc7+37jzxjK328MnLfs}Fv0#!t|8dy8h=knuK{G@=$U z+zCI8v?Vd`f<2?{;5s})$6zo#P(Ae>mO(CT$P7!$5UiuurYx0p^+dF)8rfFR_c*C< z!k`X6?@+oM?x(DF(lSoFEA>J3q%?HFOC^1u+A^g1{?VU{b|_w_>K%E{j1O{6Lh(Zv z2$5O=;B*ZwO_Z?K#ZyskkQv??iBxIt*>F7_*>!pw>|vXH!>MN7;}8 zvf;@wyy$2Fr!x00Lc~%^dLPE&@RKL^laKPRSBy!Y+yTdvg0QzIUwhh{S1041YVY9o z>WR<2`G;19vbitTeh4_&-)TPMVh7isoH|s)pInS@H>N$-Z#P)<9})N~gn;`il$My3 z9|-}w|Jq1(XJQ!a2dh)_sm=_o=%5as--hbsm)?w%26Z4O&0WodOHlDNsAzvw>gV|O z(}QOs+1sDkoSFxnh7qDc?M?T8GFR}|p6-uObd3l^1R??vfrvmvAR-VEhzLXkA_5VC zh(JUjA`lUX2t))T0uh0TKtv!S5D|z7LVC(_}lpOf0<948>u&c>xU^Hga3P}pEP}ZpX_?|UjBYq`?nikvQN*T z_UUv%`Eqz(3D5r?o(4G1(-7`2k!s9)%4A{-2imAii&S z8_M+!@9!+%PnvHg&V0iB=NnJ{xcm)x{3+`yt$qt!DR+;g3A-;4=97mdt0qx3Ap8Jn(xl{Ka;f z*aCrb_@4i$>JZP{P{;rD?`G!h{T)1E{<-;+gSqjSFY%`GD}Qjm_x1 z@?+5MFPzNpzV?3(o^aOu$sUt`f4}7X%g;R+vj_XQ-y4ki3x{N9vgiNf!4usHCimyp zn6Eqlvj_WlPz>(?OuqR)KL{q&pT3+t5R?1W4F7rR)_v;^J|5)$4#4Eecdcnnp5oUH eEz#cG9{h^g9n|L5fiulN{zurpF!;Ee`u_prt1=@1 From 98734a57270faf230d8d4f74703354a9bd30eabf Mon Sep 17 00:00:00 2001 From: dreamsourcelabTAI Date: Fri, 14 Jun 2024 10:39:58 +0800 Subject: [PATCH 25/47] fix: The file save path is not displaying the updated location after it has changed. --- DSView/pv/dialogs/storeprogress.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/DSView/pv/dialogs/storeprogress.cpp b/DSView/pv/dialogs/storeprogress.cpp index cfc118b1..f7fc1a3d 100644 --- a/DSView/pv/dialogs/storeprogress.cpp +++ b/DSView/pv/dialogs/storeprogress.cpp @@ -392,14 +392,14 @@ void StoreProgress::on_change_file() if (file != "") { + _fileLab->setText(file); + #ifdef _WIN32 _file_path = file; - QTimer::singleShot(0, this, [this](){ + QTimer::singleShot(300, this, [this](){ _fileLab->setText(_file_path); - }); -#else - _fileLab->setText(file); + }); #endif if (_ckOrigin != NULL){ From 699743655ae1dfa3276d7b488a09e71d6b421730 Mon Sep 17 00:00:00 2001 From: dreamsourcelabTAI Date: Fri, 14 Jun 2024 11:15:53 +0800 Subject: [PATCH 26/47] fix: The connected device be removed from list when machine awake --- libsigrok4DSL/lib_main.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libsigrok4DSL/lib_main.c b/libsigrok4DSL/lib_main.c index 332c1f54..2d6ca48d 100644 --- a/libsigrok4DSL/lib_main.c +++ b/libsigrok4DSL/lib_main.c @@ -81,6 +81,7 @@ static void post_event_async(int event); static void send_event(int event); static void make_demo_device_to_list(); static void process_attach_event(int isEvent); +static void process_detach_event(); static struct libusb_device* get_new_attached_usb_device(); static struct libusb_device* get_new_detached_usb_device(); @@ -603,13 +604,17 @@ SR_API int ds_remove_device(ds_device_handle handle) if (handle == NULL_HANDLE) return SR_ERR_ARG; - if (lib_ctx.actived_device_instance != NULL && lib_ctx.actived_device_instance->handle == handle && ds_is_collecting()) + if (lib_ctx.actived_device_instance != NULL + && lib_ctx.actived_device_instance->handle == handle + && ds_is_collecting()) { sr_err("Device is collecting, can't remove it."); return SR_ERR_CALL_STATUS; } - if (lib_ctx.actived_device_instance != NULL && lib_ctx.is_delay_destory_actived_device && lib_ctx.actived_device_instance->handle == handle) + if (lib_ctx.actived_device_instance != NULL + && lib_ctx.is_delay_destory_actived_device + && lib_ctx.actived_device_instance->handle == handle) { sr_info("The current device is delayed for destruction, handle:%p", lib_ctx.actived_device_instance->handle); destroy_device_instance(lib_ctx.actived_device_instance); @@ -1741,6 +1746,9 @@ SR_API int ds_reload_device_list() sr_info("Reload device list."); lib_ctx.is_reloading_list = 1; + lib_ctx.is_delay_destory_actived_device = NULL; + lib_ctx.detach_device_handle = NULL; + lib_ctx.detach_event_flag = 0; process_attach_event(0); lib_ctx.is_reloading_list = 0; From 1c7f402f6a60689135b7abfadfcba747763def8b Mon Sep 17 00:00:00 2001 From: dreamsourcelabTAI Date: Fri, 14 Jun 2024 17:57:21 +0800 Subject: [PATCH 27/47] fix: The Up and Down key is disabled on windows 10 --- DSView/pv/mainwindow.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/DSView/pv/mainwindow.cpp b/DSView/pv/mainwindow.cpp index a6c5021c..5ba86a0c 100644 --- a/DSView/pv/mainwindow.cpp +++ b/DSView/pv/mainwindow.cpp @@ -1336,6 +1336,9 @@ namespace pv break; case Qt::Key_Up: +#ifdef _WIN32 + case 38: +#endif for (auto s : sigs) { if (s->signal_type() == SR_CHANNEL_DSO){ @@ -1351,6 +1354,9 @@ namespace pv break; case Qt::Key_Down: +#ifdef _WIN32 + case 40: +#endif for (auto s : sigs) { if (s->signal_type() == SR_CHANNEL_DSO){ From d17440a86259544ba5e48645e74136c892dc0c79 Mon Sep 17 00:00:00 2001 From: dreamsourcelabTAI Date: Mon, 17 Jun 2024 17:16:58 +0800 Subject: [PATCH 28/47] Disable the IME --- DSView/pv/winnativewidget.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/DSView/pv/winnativewidget.cpp b/DSView/pv/winnativewidget.cpp index 9b523669..eb449e66 100644 --- a/DSView/pv/winnativewidget.cpp +++ b/DSView/pv/winnativewidget.cpp @@ -53,6 +53,7 @@ typedef HPOWERNOTIFY(WINAPI* PFN_REGISTER_SUSPEND_RESUME_NOTIFICATION)(HANDLE, DWORD); typedef BOOL(WINAPI* PFN_UNREGISTER_SUSPEND_RESUME_NOTIFICATION)(HPOWERNOTIFY); +typedef HIMC (WINAPI* FN_ImmAssociateContext)(HWND,HIMC); namespace pv { @@ -181,6 +182,17 @@ WinNativeWidget::WinNativeWidget(const int x, const int y, const int width, } InitCapturePowerEvent(_hWnd); + + //Disabled the IMME. + HMODULE hImm32Dll = LoadLibraryW(L"imm32.dll"); + if (hImm32Dll != NULL){ + FN_ImmAssociateContext fnImm = (FN_ImmAssociateContext)GetProcAddress(hImm32Dll, "ImmAssociateContext"); + + if (fnImm){ + fnImm(_hWnd, NULL); + } + FreeLibrary(hImm32Dll); + } } WinNativeWidget::~WinNativeWidget() From 974c336cdbb636ff24bd9e5a29bf2843ef5a02f5 Mon Sep 17 00:00:00 2001 From: yunyaobaihong <896458252@qq.com> Date: Wed, 19 Jun 2024 10:11:49 +0800 Subject: [PATCH 29/47] Decoder Update : can put error when Bit Stuffing error(111111 or 000000) --- libsigrokdecode4DSL/decoders/can/pd.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libsigrokdecode4DSL/decoders/can/pd.py b/libsigrokdecode4DSL/decoders/can/pd.py index 187e759f..8c501c77 100644 --- a/libsigrokdecode4DSL/decoders/can/pd.py +++ b/libsigrokdecode4DSL/decoders/can/pd.py @@ -21,6 +21,7 @@ ## ## 2024/3/28 DreamSourceLab : Display data when zooming out +## 2024/6/18 DreamSourceLab : put error when stuff error ## from common.srdhelper import bitpack_msb @@ -154,6 +155,8 @@ def is_stuff_bit(self): if len(self.bits) > self.last_databit + 17: return False last_6_bits = self.rawbits[-6:] + if last_6_bits in ([1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0]): + self.putx([16, ['Stuff Error' ,'Error','E']]) if last_6_bits not in ([0, 0, 0, 0, 0, 1], [1, 1, 1, 1, 1, 0]): return False From 7b0d79d6c4eacd4a2ff486c7912b1f909c60ea9e Mon Sep 17 00:00:00 2001 From: dreamsourcelabTAI Date: Mon, 24 Jun 2024 18:12:07 +0800 Subject: [PATCH 30/47] Cath the error about driver have not installed --- DSView/pv/sigsession.cpp | 67 +++++++++++++++++++------------- lang/cn/msg.json | 4 ++ lang/en/msg.json | 4 ++ libsigrok4DSL/hardware/DSL/dsl.c | 6 ++- libsigrok4DSL/libsigrok.h | 3 +- 5 files changed, 54 insertions(+), 30 deletions(-) diff --git a/DSView/pv/sigsession.cpp b/DSView/pv/sigsession.cpp index 63931863..1031fa1a 100644 --- a/DSView/pv/sigsession.cpp +++ b/DSView/pv/sigsession.cpp @@ -257,42 +257,53 @@ namespace pv // The current device changed. _callback->trigger_message(DSV_MSG_CURRENT_DEVICE_CHANGED); - if (ds_get_last_error() == SR_ERR_DEVICE_FIRMWARE_VERSION_LOW) - { - QString strMsg = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_TO_RECONNECT_FOR_FIRMWARE), - "Please reconnect the device!"); - _callback->delay_prop_msg(strMsg); - return false; - } + int lastError = ds_get_last_error(); + bool ret = true; - if (ds_get_last_error() == SR_ERR_FIRMWARE_NOT_EXIST) + switch (lastError) { - QString strMsg = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_FIRMWARE_NOT_EXIST), + case SR_ERR_DEVICE_FIRMWARE_VERSION_LOW:{ + QString strMsg = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_TO_RECONNECT_FOR_FIRMWARE), + "Please reconnect the device!"); + _callback->delay_prop_msg(strMsg); + ret = false; + break; + } + case SR_ERR_FIRMWARE_NOT_EXIST:{ + QString strMsg = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_FIRMWARE_NOT_EXIST), "Firmware not exist!"); - _callback->delay_prop_msg(strMsg); - return false; - } - - if (ds_get_last_error() == SR_ERR_DEVICE_USB_IO_ERROR) - { - QString strMsg = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_DEVICE_USB_IO_ERROR), + _callback->delay_prop_msg(strMsg); + ret = false; + break; + } + case SR_ERR_DEVICE_USB_IO_ERROR:{ + QString strMsg = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_DEVICE_USB_IO_ERROR), "USB io error!"); - _callback->delay_prop_msg(strMsg); - return false; - } - - if (ds_get_last_error() == SR_ERR_DEVICE_IS_EXCLUSIVE) - { - QString strMsg = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_DEVICE_BUSY_SWITCH_FAILED), + _callback->delay_prop_msg(strMsg); + ret = false; + break; + } + case SR_ERR_DEVICE_IS_EXCLUSIVE:{ + QString strMsg = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_DEVICE_BUSY_SWITCH_FAILED), "Device is busy!"); - if (old_dev != NULL_HANDLE) - MsgBox::Show(strMsg); - else + if (old_dev != NULL_HANDLE) + MsgBox::Show(strMsg); + else + _callback->delay_prop_msg(strMsg); + ret = false; + break; + } + case SR_ERR_DEVICE_NO_DRIVER: + { + QString strMsg = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_DEVICE_NO_DRIVER), + "No driver!"); _callback->delay_prop_msg(strMsg); - return false; + ret = false; + break; + } } - return true; + return ret; } bool SigSession::set_file(QString name) diff --git a/lang/cn/msg.json b/lang/cn/msg.json index 598f3b44..3ba7ab6a 100644 --- a/lang/cn/msg.json +++ b/lang/cn/msg.json @@ -354,6 +354,10 @@ "id": "IDS_MSG_DEVICE_BUSY_SWITCH_FAILED", "text": "设备被其它程序占用,切换失败!" }, + { + "id": "IDS_MSG_DEVICE_NO_DRIVER", + "text": "设备的驱动可能未安装!" + }, { "id": "IDS_MSG_NO_ENABLED_CHANNEL", "text": "未启用通道!" diff --git a/lang/en/msg.json b/lang/en/msg.json index 83f92942..42610cc5 100644 --- a/lang/en/msg.json +++ b/lang/en/msg.json @@ -355,6 +355,10 @@ "id": "IDS_MSG_DEVICE_BUSY_SWITCH_FAILED", "text": "The device is busy, switch failed!" }, + { + "id": "IDS_MSG_DEVICE_NO_DRIVER", + "text": "The device driver may not be installed!" + }, { "id": "IDS_MSG_NO_ENABLED_CHANNEL", "text": "No channels enabled!" diff --git a/libsigrok4DSL/hardware/DSL/dsl.c b/libsigrok4DSL/hardware/DSL/dsl.c index 38ffde67..319a5387 100644 --- a/libsigrok4DSL/hardware/DSL/dsl.c +++ b/libsigrok4DSL/hardware/DSL/dsl.c @@ -335,7 +335,11 @@ static int hw_dev_open(struct sr_dev_driver *di, struct sr_dev_inst *sdi) if (ret != LIBUSB_SUCCESS){ sr_err("%s:%d, Failed to open device: %s, handle:%p", __func__, __LINE__, libusb_error_name(ret), dev_handel); - ds_set_last_error(SR_ERR_DEVICE_IS_EXCLUSIVE); + + if (ret == LIBUSB_ERROR_NOT_SUPPORTED) + ds_set_last_error(SR_ERR_DEVICE_NO_DRIVER); + else + ds_set_last_error(SR_ERR_DEVICE_IS_EXCLUSIVE); return SR_ERR; } //sr_info("------------Open returns the libusb_device_handle: %p, struct:%p", usb->devhdl, usb); diff --git a/libsigrok4DSL/libsigrok.h b/libsigrok4DSL/libsigrok.h index 4487aea2..7b3550ef 100644 --- a/libsigrok4DSL/libsigrok.h +++ b/libsigrok4DSL/libsigrok.h @@ -80,7 +80,8 @@ enum { SR_ERR_FIRMWARE_NOT_EXIST = 10, /**< The firmware file is not exist.*/ SR_ERR_DEVICE_IS_EXCLUSIVE = 11, /**< The device is exclusive by other process.*/ SR_ERR_DEVICE_FIRMWARE_VERSION_LOW = 12, /**< The firmware version is too low.*/ - SR_ERR_DEVICE_USB_IO_ERROR = 13, /**< THe use io error.*/ + SR_ERR_DEVICE_USB_IO_ERROR = 13, /**< The usb io error.*/ + SR_ERR_DEVICE_NO_DRIVER = 14, /**< The device have no driver.*/ /* * Note: When adding entries here, don't forget to also update the From c428bd66e313aaf64bfe5b96c687858a72fa6ddd Mon Sep 17 00:00:00 2001 From: dreamsource-tai Date: Thu, 11 Jul 2024 15:14:28 +0800 Subject: [PATCH 31/47] fix: unable to complie with qt6 --- DSView/pv/dock/keywordlineedit.cpp | 16 +++++++++++++++- DSView/pv/dock/keywordlineedit.h | 1 + DSView/pv/mainframe.cpp | 8 +++----- DSView/pv/mainframe.h | 11 +++++++++-- libsigrok4DSL/lib_main.c | 2 +- 5 files changed, 29 insertions(+), 9 deletions(-) diff --git a/DSView/pv/dock/keywordlineedit.cpp b/DSView/pv/dock/keywordlineedit.cpp index a74c8c15..aef003ec 100644 --- a/DSView/pv/dock/keywordlineedit.cpp +++ b/DSView/pv/dock/keywordlineedit.cpp @@ -25,6 +25,7 @@ #include "../config/appconfig.h" #include "../ui/langresource.h" #include "../log.h" +#include "../dsvdef.h" namespace{ QTimer *move_timer = NULL; @@ -120,7 +121,20 @@ void KeyLineEdit::wheelEvent(QWheelEvent *event) int v = new_text.toInt(); int old_v = v; - if (event->delta() > 0){ + int delta = 0; + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + int anglex = event->angleDelta().x(); + int angley = event->angleDelta().y(); + + if (anglex == 0 || ABS_VAL(angley) >= ABS_VAL(anglex)){ + delta = angley; + } +#else + delta = event->delta(); +#endif + + if (delta > 0){ v++; } else{ diff --git a/DSView/pv/dock/keywordlineedit.h b/DSView/pv/dock/keywordlineedit.h index 5a32ec51..93b50cb8 100644 --- a/DSView/pv/dock/keywordlineedit.h +++ b/DSView/pv/dock/keywordlineedit.h @@ -28,6 +28,7 @@ #include #include #include +#include class IKeywordActive{ public: diff --git a/DSView/pv/mainframe.cpp b/DSView/pv/mainframe.cpp index f9e91588..9f92d42b 100644 --- a/DSView/pv/mainframe.cpp +++ b/DSView/pv/mainframe.cpp @@ -1106,10 +1106,9 @@ QWidget* MainFrame::GetBodyView() return _mainWindow->GetBodyView(); } -bool MainFrame::nativeEvent(const QByteArray &eventType, void *message, long *result) -{ #ifdef _WIN32 - +bool MainFrame::nativeEvent(const QByteArray &eventType, void *message, MESSAGE_RESULT_PTR result) +{ if (_parentNativeWidget != NULL) { MSG *msg = static_cast(message); @@ -1129,10 +1128,9 @@ bool MainFrame::nativeEvent(const QByteArray &eventType, void *message, long *re } } } - -#endif return QWidget::nativeEvent(eventType, message, result); } +#endif } // namespace pv diff --git a/DSView/pv/mainframe.h b/DSView/pv/mainframe.h index 36674801..0c2ec3ee 100644 --- a/DSView/pv/mainframe.h +++ b/DSView/pv/mainframe.h @@ -37,6 +37,13 @@ #include "toolbars/titlebar.h" + +#if QT_VERSION >= QT_VERSION_CHECK(6,0,0) +typedef qintptr *MESSAGE_RESULT_PTR; +#else +typedef long *MESSAGE_RESULT_PTR; +#endif + namespace pv { class MainWindow; @@ -108,14 +115,14 @@ class MainFrame : void resizeEvent(QResizeEvent *event); void closeEvent(QCloseEvent *event); bool eventFilter(QObject *object, QEvent *event) override; + #ifdef _WIN32 void showEvent(QShowEvent *event); + bool nativeEvent(const QByteArray &eventType, void *message, MESSAGE_RESULT_PTR result) override; #endif void changeEvent(QEvent *event) override; - bool nativeEvent(const QByteArray &eventType, void *message, long *result) override; - signals: void sig_ParentNativeEvent(int msg); diff --git a/libsigrok4DSL/lib_main.c b/libsigrok4DSL/lib_main.c index 2d6ca48d..823c3366 100644 --- a/libsigrok4DSL/lib_main.c +++ b/libsigrok4DSL/lib_main.c @@ -1746,7 +1746,7 @@ SR_API int ds_reload_device_list() sr_info("Reload device list."); lib_ctx.is_reloading_list = 1; - lib_ctx.is_delay_destory_actived_device = NULL; + lib_ctx.is_delay_destory_actived_device = 0; lib_ctx.detach_device_handle = NULL; lib_ctx.detach_event_flag = 0; process_attach_event(0); From 462b4fa10af239b92486242b92bd3f9beed3a4ca Mon Sep 17 00:00:00 2001 From: yunyaobaihong <896458252@qq.com> Date: Mon, 22 Jul 2024 09:32:07 +0800 Subject: [PATCH 32/47] Decoder Update : Fixed C2 Frame Error , WS2812 add default color order and Smart QSPI QPP output update --- lang/cn/dec/p.json | 8 +- libsigrokdecode4DSL/decoders/c2/pd.py | 294 ++++++++++-------- .../decoders/rgb_led_ws281x/pd.py | 146 ++++----- libsigrokdecode4DSL/decoders/smart qspi/pd.py | 42 ++- 4 files changed, 265 insertions(+), 225 deletions(-) diff --git a/lang/cn/dec/p.json b/lang/cn/dec/p.json index fedcbc6a..b85f4061 100644 --- a/lang/cn/dec/p.json +++ b/lang/cn/dec/p.json @@ -112,8 +112,12 @@ "text": "DIN数据线" }, { - "id": "dec_rgb_led_ws281x_opt_colors", - "text": "颜色" + "id": "dec_rgb_led_ws281x_opt_default_color_order", + "text": "默认颜色顺序" + }, + { + "id": "dec_rgb_led_ws281x_opt_view_color_order", + "text": "视图颜色顺序" }, { "id": "dec_rgb_led_ws281x_opt_polarity", diff --git a/libsigrokdecode4DSL/decoders/c2/pd.py b/libsigrokdecode4DSL/decoders/c2/pd.py index 099cf37d..fecd2bdc 100644 --- a/libsigrokdecode4DSL/decoders/c2/pd.py +++ b/libsigrokdecode4DSL/decoders/c2/pd.py @@ -1,3 +1,26 @@ +## +## This file is part of the libsigrokdecode project. +## +## Copyright (C) 2024 DreamSourceLab +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, see . +## + +## +## 2024/7/5 DreamSourceLab : Read data only when the clock line is high +## + import sigrokdecode as srd ''' @@ -39,15 +62,16 @@ def reset(self): self.samplerate = None self.state= 'reset' self.bitcount = 0 - self.c2data = 0 + self.c2_data = 0 self.data=0 - self.c2dbits = [] - self.ss_block = -1 - self.samplenum = -1 self.have_c2ck = self.have_c2d = None self.ins= None - self.dataLen=0 - self.remainData=0 + + self.start_first_sample = 0 + self.data_first_sample = 0 + + self.data_len=0 + self.remain_data=0 def start(self): self.out_ann = self.register(srd.OUTPUT_ANN) @@ -62,143 +86,167 @@ def decode(self): self.have_c2d = self.has_channel(1) if not self.have_c2d: raise ChannelError('C2D pins required.') + # tf=0 tr=0 + while True: - (c2ck,c2d)=self.wait({0:'e'}) - if c2ck == 0: #�½��� - tf=self.samplenum - if self.state == 'dataRead': - if self.bitcount ==0: - ss=tr - self.c2data=0 - self.c2data |= c2d <= 8: - self.put(ss, tf, self.out_ann, [0, ['%02X' % self.c2data]]) - self.bitcount=0 - self.data|=self.c2data<<((self.dataLen-self.remainData)*8) - self.remainData -= 1 - if self.remainData ==0: - self.state = 'end' - elif self.state == 'addressRead': - if self.bitcount ==0: - ss=tr - self.c2data=0 - self.c2data |= c2d <= 8: - self.put(ss, tf, self.out_ann, [0, ['%02X' % self.c2data]]) - self.state = 'end' - elif self.state == 'readWait': - if self.bitcount ==0: - ss=tf - self.bitcount +=1 - if c2d == 1: - self.put(ss, tf, self.out_ann, [0, ['Wait','W']]) - self.bitcount=0 - self.state = 'dataRead' - elif self.state == 'writeWait': - if self.bitcount ==0: - ss=tr - self.bitcount += 1 - if c2d == 1: - self.put(ss, tf, self.out_ann, [0, ['Wait','W']]) - self.state = 'end' - - else: #������ - tr=self.samplenum - interval=(tr-tf)*1000*1000/self.samplerate #us - if interval>20: + (c2ck, c2d) = self.wait({ 0 : 'e' }) + if c2ck == 0: + tf = self.samplenum + else: + tr = self.samplenum + + interval = (tr - tf) * 1000 * 1000 / self.samplerate #us + + if interval > 20: self.put(tf, tr, self.out_ann, [0, [ 'Reset','R']]) - self.state='start' + self.state = 'start' + elif self.state == 'start': self.put(tf, tr, self.out_ann, [0, [ 'Start','S']]) - self.state='ins' - self.bitcount=0 - self.ins=0 - self.data=0 - self.dataLen=0 - ss1=tf + + self.start_first_sample = tf + + self.state = 'ins' + ss = tr + self.ins = 0 + self.bitcount = 0 + elif self.state == 'ins': - if self.bitcount ==0: - ss=tr - self.c2data=0 - self.ins |= c2d <= 2: - (c2ck,c2d)=self.wait({0:'f'}) + self.put(ss, self.samplenum, self.out_ann, [0, [ '%1d'%self.ins]]) + if self.ins == 0 : - self.state = 'dataReadLen' - elif self.ins == 2: - self.state = 'addressRead' + self.state = 'Data Read Len' + self.data_len = 0 + self.remain_data = 0 elif self.ins == 1: - self.state = 'dataWriteLen' - else: - self.state = 'addressWrite' - self.put(ss, self.samplenum, self.out_ann, [0, [ '%1d'%self.ins]]) - self.bitcount=0 - elif self.state == 'addressWrite': - if self.bitcount ==0: - ss=tr - self.c2data=0 - self.c2data |= c2d <= 2: + self.put(ss, self.samplenum, self.out_ann, [0, [ '%01d'%self.c2_data]]) + + self.state = 'Read Wait' + self.data_len = self.c2_data + 1 + self.remain_data = self.data_len + + ss = tr + + elif self.state == 'Read Wait': + self.put(ss, self.samplenum, self.out_ann, [0, ['Wait','W']]) + self.state = 'Data Read' + + self.data = 0 + ss = tr + self.c2_data = 0 + self.bitcount = 0 + + elif self.state == 'Data Read': + self.c2_data |= c2d << self.bitcount self.bitcount += 1 + if self.bitcount >= 8: - (c2ck,c2d)=self.wait({0:'f'}) - tf=self.samplenum - self.put(ss, tf, self.out_ann, [0, ['%02X' % self.c2data]]) - self.bitcount=0 - self.state = 'end' - elif self.state == 'dataReadLen': - if self.bitcount ==0: - ss=tr - self.c2data=0 - self.c2data |= c2d <= 2: - self.dataLen=self.c2data+1 - self.remainData=self.dataLen - #(c2ck,c2d)=self.wait({0:'f'}) - self.put(ss, self.samplenum, self.out_ann, [0, [ '%01d'%self.c2data]]) - self.state='readWait' - self.bitcount=0 - elif self.state == 'dataWriteLen': - if self.bitcount ==0: - ss=tr - self.c2data=0 - self.c2data |= c2d <= 2: - self.dataLen=self.c2data+1 - self.remainData=self.dataLen - (c2ck,c2d)=self.wait({0:'f'}) - self.put(ss, self.samplenum, self.out_ann, [0, ['%01d'%self.c2data]]) - self.state='dataWrite' - self.bitcount=0 - self.c2data=0 - elif self.state == 'dataWrite': - if self.bitcount ==0: - ss=tr - self.c2data=0 - self.c2data |= c2d <= 8: + self.put(ss, tr, self.out_ann, [0, ['%02X' % self.c2_data]]) + + self.data |= self.c2_data << ((self.data_len - self.remain_data) * 8) + + ss = tr + self.c2_data = 0 + self.bitcount = 0 + + self.remain_data -= 1 + + if self.remain_data ==0: + self.state='Write Wait' + elif self.state == 'Write Wait': + self.put(ss, self.samplenum, self.out_ann, [0, ['Wait','W']]) + self.state = 'End' + + ss = tr + + elif self.state == 'Address Write': + self.c2_data |= c2d << self.bitcount self.bitcount += 1 + if self.bitcount >= 8: - self.put(ss, tr, self.out_ann, [0, ['%02X' % self.c2data]]) - self.bitcount=0 - self.data|=self.c2data<<((self.dataLen-self.remainData)*8) - self.remainData -= 1 - if self.remainData ==0: - self.state='writeWait' - elif self.state == 'end': - self.state='start' - self.put(tf, tr, self.out_ann, [0, [ 'End','E']]) + self.put(ss, self.samplenum, self.out_ann, [0, ['%02X' % self.c2_data]]) + + self.state = 'End' + ss = tr + + elif self.state == 'Address Read': + self.c2_data |= c2d << self.bitcount + self.bitcount += 1 + + if self.bitcount >= 8: + self.put(ss, self.samplenum, self.out_ann, [0, ['%02X' % self.c2_data]]) + + self.state = 'End' + ss = tr + + elif self.state == 'End': + self.put(ss, self.samplenum, self.out_ann, [0, [ 'End','E']]) + if self.ins == 0: - self.put(ss1, tr, self.out_ann, [1, [ 'ReadData(%01d)=0x%02X'%(self.dataLen,self.data)]]) + self.put(self.start_first_sample, self.samplenum, self.out_ann, [1, [ 'ReadData(%01d)=0x%02X'%(self.data_len,self.data)]]) elif self.ins == 1: - self.put(ss1, tr, self.out_ann, [1, [ 'WriteData(0x%02X,%01d)'%(self.data,self.dataLen)]]) + self.put(self.start_first_sample, self.samplenum, self.out_ann, [1, [ 'WriteData(0x%02X,%01d)'%(self.data,self.data_len)]]) elif self.ins == 2: - self.put(ss1, tr, self.out_ann, [1, [ 'ReadAddress()=0x%02X'%self.c2data]]) + self.put(self.start_first_sample, self.samplenum, self.out_ann, [1, [ 'ReadAddress()=0x%02X'%self.c2_data]]) elif self.ins == 3: - self.put(ss1, tr, self.out_ann, [1, [ 'WriteAddress(0x%02X)'%self.c2data]]) + self.put(self.start_first_sample, self.samplenum, self.out_ann, [1, [ 'WriteAddress(0x%02X)'%self.c2_data]]) + + self.state = 'start' + diff --git a/libsigrokdecode4DSL/decoders/rgb_led_ws281x/pd.py b/libsigrokdecode4DSL/decoders/rgb_led_ws281x/pd.py index 85bfb85a..57e4ef2e 100644 --- a/libsigrokdecode4DSL/decoders/rgb_led_ws281x/pd.py +++ b/libsigrokdecode4DSL/decoders/rgb_led_ws281x/pd.py @@ -3,7 +3,7 @@ ## ## Copyright (C) 2016 Vladimir Ermakov ## Copyright (C) 2021 Michael Miller -## Copyright (C) 2023 DreamSourceLab +## Copyright (C) 2024 DreamSourceLab ## ## This program is free software; you can redistribute it and/or modify @@ -20,6 +20,10 @@ ## along with this program; if not, see . ## +## +## 2024/7/8 DreamSourceLab : default color order update +## + import sigrokdecode as srd from functools import reduce @@ -40,9 +44,12 @@ class Decoder(srd.Decoder): {'id': 'din', 'name': 'DIN', 'desc': 'DIN data line', 'idn':'dec_rgb_led_ws281x_chan_din'}, ) options = ( - {'id': 'colors', 'desc': 'Colors', 'default': 'GRB', + {'id': 'default_color_order', 'desc': 'Default Color Order', 'default': 'GRB', 'values': ( 'GRB', 'RGB', 'BRG', 'RBG', 'BGR', 'GRBW', 'RGBW', 'WRGB', 'LBGR', 'LGRB', 'LRGB', 'LRBG', 'LGBR', 'LBRG') - , 'idn':'dec_rgb_led_ws281x_opt_colors'}, + , 'idn':'dec_rgb_led_ws281x_opt_default_color_order'}, + {'id': 'view_color_order', 'desc': 'View Color Order', 'default': 'GRB', + 'values': ( 'GRB', 'RGB', 'BRG', 'RBG', 'BGR', 'GRBW', 'RGBW', 'WRGB', 'LBGR', 'LGRB', 'LRGB', 'LRBG', 'LGBR', 'LBRG') + , 'idn':'dec_rgb_led_ws281x_opt_view_color_order'}, {'id': 'polarity', 'desc': 'Polarity', 'default': 'normal', 'values': ('normal', 'inverted'), 'idn':'dec_rgb_led_ws281x_opt_polarity'}, ) @@ -79,79 +86,60 @@ def metadata(self, key, value): def handle_bits(self, samplenum): if len(self.bits) == self.colorsize: - elems = reduce(lambda a, b: (a << 1) | b, self.bits) - if self.colorsize == 24: - if self.options['colors'] == 'GRB': - rgb = (elems & 0xff0000) >> 8 | (elems & 0x00ff00) << 8 | (elems & 0x0000ff) - self.put(self.ss_packet, samplenum, self.out_ann, - [2, ['GRB#%06x' % rgb]]) - elif self.options['colors'] == 'RGB': - rgb = elems - self.put(self.ss_packet, samplenum, self.out_ann, - [2, ['RGB#%06x' % rgb]]) - elif self.options['colors'] == 'BRG': - rgb = (elems & 0xffff00) >> 8 | (elems & 0x0000ff) << 16 - self.put(self.ss_packet, samplenum, self.out_ann, - [2, ['BRG#%06x' % rgb]]) - elif self.options['colors'] == 'RBG': - rgb = (elems & 0xff0000) | (elems & 0x00ff00) >> 8 | (elems & 0x0000ff) << 8 - self.put(self.ss_packet, samplenum, self.out_ann, - [2, ['RBG#%06x' % rgb]]) - elif self.options['colors'] == 'BGR': - rgb = (elems & 0xff0000) >> 16 | (elems & 0x00ff00) | (elems & 0x0000ff) << 16 - self.put(self.ss_packet, samplenum, self.out_ann, - [2, ['BGR#%06x' % rgb]]) - - else: - if self.options['colors'] == 'GRBW': - rgb = (elems & 0xff000000) >> 16 | (elems & 0x00ff0000) | (elems & 0x0000ff00) >> 8 - w = (elems & 0x000000ff) - self.put(self.ss_packet, samplenum, self.out_ann, - [2, ['GRB#%06x W#%02x' % (rgb, w)]]) - elif self.options['colors'] == 'RGBW': - rgb = (elems & 0xffffff00) >> 8 - w = (elems & 0x000000ff) - self.put(self.ss_packet, samplenum, self.out_ann, - [2, ['RGB#%06x W#%02x' % (rgb, w)]]) - elif self.options['colors'] == 'WRGB': - rgb = (elems & 0xffffff00) >> 8 - w = (elems & 0x000000ff) - self.put(self.ss_packet, samplenum, self.out_ann, - [2, ['W#%02x RGB#%06x ' % (w, rgb)]]) - elif self.options['colors'] == 'LBGR': - rgb = (elems & 0x0000ff00) | (elems & 0x00ff0000) >> 16 | (elems & 0x000000ff) << 16 - w = (elems & 0xff000000) >> 24 - self.put(self.ss_packet, samplenum, self.out_ann, - [2, ['L#%02x BGR#%06x ' % (w, rgb)]]) - elif self.options['colors'] == 'LGRB': - rgb = (elems & 0x000000ff) | (elems & 0x00ff0000) >> 8 | (elems & 0x0000ff00) << 8 - w = (elems & 0xff000000) >> 24 - self.put(self.ss_packet, samplenum, self.out_ann, - [2, ['L#%02x GRB#%06x ' % (w, rgb)]]) - elif self.options['colors'] == 'LRGB': - rgb = (elems & 0x00ffffff) - w = (elems & 0xff000000) >> 24 - self.put(self.ss_packet, samplenum, self.out_ann, - [2, ['L#%02x RGB#%06x ' % (w, rgb)]]) - elif self.options['colors'] == 'LRBG': - rgb = (elems & 0x00ff0000) | (elems & 0x0000ff00) >> 8 | (elems & 0x000000ff) << 8 - w = (elems & 0xff000000) >> 24 - self.put(self.ss_packet, samplenum, self.out_ann, - [2, ['L#%02x RBG#%06x ' % (w, rgb)]]) - elif self.options['colors'] == 'LGBR': - rgb = (elems & 0x00ff0000) >> 16 | (elems & 0x0000ffff) << 8 - w = (elems & 0xff000000) >> 24 - self.put(self.ss_packet, samplenum, self.out_ann, - [2, ['L#%02x GRB#%06x ' % (w, rgb)]]) - elif self.options['colors'] == 'LBRG': - rgb = (elems & 0x00ffff00) >> 8 | (elems & 0x000000ff) << 16 - w = (elems & 0xff000000) >> 24 - self.put(self.ss_packet, samplenum, self.out_ann, - [2, ['L#%02x BRG#%06x ' % (w, rgb)]]) - - - self.bits = [] - self.ss_packet = samplenum + + elems = reduce(lambda a, b: (a << 1) | b, self.bits) + + default_val = 0 + view_val = 0 + + if self.colorsize == 24: + for i in range(3): + default_index = self.options['default_color_order'].find(self.options['view_color_order'][i]) + + if default_index == 0: + default_val = (elems & 0xff0000) >> 16 + elif default_index == 1: + default_val = (elems & 0x00ff00) >> 8 + elif default_index == 2: + default_val = (elems & 0x0000ff) + + if i == 0: + view_val = (default_val << 16) | view_val + elif i == 1: + view_val = (default_val << 8) | view_val + elif i == 2: + view_val = default_val | view_val + + self.put(self.ss_packet, samplenum, self.out_ann,[2, ['%s#%06x' % (self.options['view_color_order'] , view_val)]]) + + else: + for i in range(4): + default_index = self.options['default_color_order'].find(self.options['view_color_order'][i]) + + if default_index == 0: + default_val = (elems & 0xff000000) >> 24 + elif default_index == 1: + default_val = (elems & 0x00ff0000) >> 16 + elif default_index == 2: + default_val = (elems & 0x0000ff00) >> 8 + elif default_index == 3: + default_val = (elems & 0x000000ff) + + if i == 0: + view_val = (default_val << 24) | view_val + elif i == 1: + view_val = (default_val << 16) | view_val + elif i == 2: + view_val = (default_val << 8) | view_val + elif i == 3: + view_val = default_val | view_val + + self.put(self.ss_packet, samplenum, self.out_ann,[2, ['%s#%08x' % (self.options['view_color_order'] , view_val)]]) + + + + self.bits = [] + self.ss_packet = samplenum def check_bit_(self, samplenum): period = samplenum - self.ss @@ -175,8 +163,10 @@ def end(self): def decode(self): if not self.samplerate: raise SamplerateError('Cannot decode without samplerate.') - - if len(self.options['colors']) == 4: + if len(self.options['default_color_order']) != len(self.options['view_color_order']): + raise Exception('default color order len must equal to view color order len') + + if len(self.options['default_color_order']) == 4: self.colorsize = 32 else: self.colorsize = 24 diff --git a/libsigrokdecode4DSL/decoders/smart qspi/pd.py b/libsigrokdecode4DSL/decoders/smart qspi/pd.py index 75ed0189..0668b08c 100644 --- a/libsigrokdecode4DSL/decoders/smart qspi/pd.py +++ b/libsigrokdecode4DSL/decoders/smart qspi/pd.py @@ -26,7 +26,8 @@ Data = namedtuple('Data', ['ss', 'es', 'val']) ## -## 2023/4/8 DreamSourceLab : add flash module +## 2024/4/8 DreamSourceLab : add flash module +## 2024/7/5 DreamSourceLab : qpp text update ## # Key: (CPOL, CPHA). Value: SPI mode. @@ -42,20 +43,22 @@ class process_enum(Enum): COMMAND = 0 WRITE_BYTE = 1 - READ_BYTE = 2 - READ_BYTE_CONTINUOUS = 3 - CONTINUOUS_READ_MODE_BITS = 4 - ADDRESS_BY_MODE = 5 - ADDRESS_24BIT = 6 - ADDRESS_32BIT = 7 - DUMMY_BY_MODE = 8 - DUMMY_8BIT = 9 - DUMMY_32BIT = 10 - DUMMY_40BIT = 11 + WRITE_BYTE_CONTINUOUS = 2 + READ_BYTE = 3 + READ_BYTE_CONTINUOUS = 4 + CONTINUOUS_READ_MODE_BITS = 5 + ADDRESS_BY_MODE = 6 + ADDRESS_24BIT = 7 + ADDRESS_32BIT = 8 + DUMMY_BY_MODE = 9 + DUMMY_8BIT = 10 + DUMMY_32BIT = 11 + DUMMY_40BIT = 12 process_text = { process_enum.COMMAND : ['Command' , 'CMD'] , process_enum.WRITE_BYTE : ['Write Data' , 'WD'] , + process_enum.WRITE_BYTE_CONTINUOUS : ['Write Data' , 'WD'] , process_enum.READ_BYTE : ['Read Data' , 'RD'] , process_enum.READ_BYTE_CONTINUOUS : ['Read Data' , 'RD'] , process_enum.ADDRESS_24BIT : ['24-Bit Address' , 'AD'] , @@ -108,6 +111,7 @@ def __eq__(self, other): #write (io0) WRITE_BYTE_SINGLE = process_info(process_enum.WRITE_BYTE , process_mode.SINGLE) +WRITE_BYTE_QUAD_CONTINUOUS = process_info(process_enum.WRITE_BYTE_CONTINUOUS , process_mode.QUAD) #DUMMY DUMMY_CYCLE = process_info(process_enum.DUMMY_BY_MODE , process_mode.SINGLE) @@ -142,8 +146,8 @@ def __eq__(self, other): 0x77 : ['Set Burst with Wrap' , 'SBWW' , [DUMMY_CYCLE_8BIT_QUAD , DUMMY_CYCLE_8BIT_QUAD , DUMMY_CYCLE_8BIT_QUAD , READ_BYTE_QUAD_CONTINUOUS]], 0x02 : ['Page Program' , 'PP' , [READ_ADDRESS] + [WRITE_BYTE_SINGLE] * 256], 0x12 : ['Page Program' , '4PP' , [READ_4B_ADDRESS] + [WRITE_BYTE_SINGLE] * 256], - 0x32 : ['Quad Page Program' , 'QPP' , [READ_ADDRESS] + [READ_BYTE_QUAD_CONTINUOUS]], - 0x34 : ['Quad Page Program' , '4QPP' , [READ_4B_ADDRESS] + [READ_BYTE_QUAD_CONTINUOUS]], + 0x32 : ['Quad Page Program' , 'QPP' , [READ_ADDRESS] + [WRITE_BYTE_QUAD_CONTINUOUS]], + 0x34 : ['Quad Page Program' , '4QPP' , [READ_4B_ADDRESS] + [WRITE_BYTE_QUAD_CONTINUOUS]], 0x20 : ['Sector Erase' , 'SE' , [READ_ADDRESS]], 0x21 : ['Sector Erase' , '4SE', [READ_4B_ADDRESS]], 0x52 : ['32KB Block Erase' , 'BE32' , [READ_ADDRESS]], @@ -345,14 +349,6 @@ def putdata(self, frame): else : spiMode='spi' - #self.putgse(ss,es,[7, ['%s' %spiMode.upper()]]) - #self.put(ss, es, self.out_ann, [3, ['@%02X' % self.io0data]]) - #if self.have_io1: - # self.put(ss, es, self.out_ann, [4, ['@%02X' % self.io1data]]) - #if self.have_io3: - # self.put(ss, es, self.out_ann, [5, ['@%02X' % self.io2data]]) - # self.put(ss, es, self.out_ann, [6, ['@%02X' % self.io3data]]) - if spiMode == 'qspi' or spiMode == 'dspi': qdata = [] @@ -472,11 +468,13 @@ def putdata(self, frame): elif cur_state.enum == process_enum.WRITE_BYTE or \ cur_state.enum == process_enum.READ_BYTE or \ cur_state.enum == process_enum.READ_BYTE_CONTINUOUS or \ + cur_state.enum == process_enum.WRITE_BYTE_CONTINUOUS or \ cur_state.enum == process_enum.CONTINUOUS_READ_MODE_BITS: self.puttext(origin_data[1] , origin_data[2] , cur_state.enum , origin_data[0]) - if cur_state.enum != process_enum.READ_BYTE_CONTINUOUS: + if cur_state.enum != process_enum.READ_BYTE_CONTINUOUS and \ + cur_state.enum != process_enum.WRITE_BYTE_CONTINUOUS: self.state_count += 1 if self.state_count < len(self.diagram): From 499f90aebef9f7e30a046dbeb064a305fb7c721d Mon Sep 17 00:00:00 2001 From: dreamsource-tai Date: Tue, 23 Jul 2024 15:10:12 +0800 Subject: [PATCH 33/47] The time string of csv file header used the session time --- DSView/pv/data/snapshot.cpp | 6 ++++++ DSView/pv/data/snapshot.h | 1 + DSView/pv/sigsession.cpp | 8 ++++++++ DSView/pv/storesession.cpp | 6 +++++- libsigrok4DSL/libsigrok.h | 2 ++ libsigrok4DSL/output/csv.c | 4 ++-- 6 files changed, 24 insertions(+), 3 deletions(-) diff --git a/DSView/pv/data/snapshot.cpp b/DSView/pv/data/snapshot.cpp index 02669025..ede94348 100644 --- a/DSView/pv/data/snapshot.cpp +++ b/DSView/pv/data/snapshot.cpp @@ -71,6 +71,12 @@ uint64_t Snapshot::get_sample_count() return _sample_count; } +uint64_t Snapshot::get_total_sample_count() +{ + std::lock_guard lock(_mutex); + return _total_sample_count; +} + uint64_t Snapshot::get_ring_sample_count() { std::lock_guard lock(_mutex); diff --git a/DSView/pv/data/snapshot.h b/DSView/pv/data/snapshot.h index 1f24e470..87b480da 100644 --- a/DSView/pv/data/snapshot.h +++ b/DSView/pv/data/snapshot.h @@ -40,6 +40,7 @@ class Snapshot virtual void init() = 0; uint64_t get_sample_count(); + uint64_t get_total_sample_count(); uint64_t get_ring_sample_count(); uint64_t get_ring_start(); uint64_t get_ring_end(); diff --git a/DSView/pv/sigsession.cpp b/DSView/pv/sigsession.cpp index 1031fa1a..b16159de 100644 --- a/DSView/pv/sigsession.cpp +++ b/DSView/pv/sigsession.cpp @@ -1474,6 +1474,14 @@ namespace pv // Post a message to start all decode tasks. if (mode == LOGIC){ + auto logic_data = _capture_data->get_logic(); + if (is_loop_mode() && logic_data->get_loop_offset() > 0){ + uint64_t milliseconds = logic_data->get_ring_sample_count() / 1000000; + QDateTime sessionTime = QDateTime::currentDateTime(); + sessionTime = sessionTime.addMSecs(-milliseconds); + set_session_time(sessionTime); + } + _callback->trigger_message(DSV_MSG_REV_END_PACKET); } else{ diff --git a/DSView/pv/storesession.cpp b/DSView/pv/storesession.cpp index 9f49bb10..4edfb234 100644 --- a/DSView/pv/storesession.cpp +++ b/DSView/pv/storesession.cpp @@ -48,6 +48,7 @@ #include #include #include +#include #ifdef _WIN32 #include @@ -919,7 +920,10 @@ void StoreSession::export_exec(data::Snapshot *snapshot) return; } } - + + QString sessionTime = _session->get_session_time().toString("yyyy-MM-dd HH:mm:ss"); + strcpy(output.time_string, sessionTime.toStdString().c_str()); + QFile file(_file_name); file.open(QIODevice::WriteOnly | QIODevice::Text); QTextStream out(&file); diff --git a/libsigrok4DSL/libsigrok.h b/libsigrok4DSL/libsigrok.h index 7b3550ef..bd8f424a 100644 --- a/libsigrok4DSL/libsigrok.h +++ b/libsigrok4DSL/libsigrok.h @@ -533,6 +533,8 @@ struct sr_output { void *priv; uint64_t start_sample_index; + + char time_string[30]; }; /** Generic option struct used by various subsystems. */ diff --git a/libsigrok4DSL/output/csv.c b/libsigrok4DSL/output/csv.c index 82e06f88..b5a05376 100644 --- a/libsigrok4DSL/output/csv.c +++ b/libsigrok4DSL/output/csv.c @@ -154,8 +154,8 @@ static GString *gen_header(const struct sr_output *o) /* Some metadata */ t = time(NULL); - g_string_append_printf(header, "; CSV, generated by %s on %s", - PACKAGE_STRING, ctime(&t)); + g_string_append_printf(header, "; CSV, generated by %s on %s\n", + PACKAGE_STRING, o->time_string); //ctime(&t) /* Columns / channels */ if (ctx->type == SR_CHANNEL_LOGIC) From 66ed68ea1759558082f392de1aa7643046fd39ae Mon Sep 17 00:00:00 2001 From: dreamsource-tai Date: Tue, 23 Jul 2024 16:49:56 +0800 Subject: [PATCH 34/47] fix: Under Windows, DSView cannot be adjusted to a sufficiently large width between two screens. --- DSView/pv/winnativewidget.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/DSView/pv/winnativewidget.cpp b/DSView/pv/winnativewidget.cpp index eb449e66..c6a2aa50 100644 --- a/DSView/pv/winnativewidget.cpp +++ b/DSView/pv/winnativewidget.cpp @@ -427,10 +427,12 @@ LRESULT CALLBACK WinNativeWidget::WndProc(HWND hWnd, UINT message, WPARAM wParam QSize minimum = gw->minimumSize(); QSize sizeHint = gw->minimumSizeHint(); + bool bNormal = self->IsNormalsized(); + MINMAXINFO *mmi = reinterpret_cast(lParam); mmi->ptMinTrackSize.x = qFloor(qMax(minimum.width(), sizeHint.width()) * k); mmi->ptMinTrackSize.y = qFloor(qMax(minimum.height(), sizeHint.height()) * k); - mmi->ptMaxTrackSize.x = maxWidth; + mmi->ptMaxTrackSize.x = bNormal ? maxWidth * 5 : maxWidth; mmi->ptMaxTrackSize.y = maxHeight; } } From c50e8f714aedaa5befdde057ccd810c758afe0f8 Mon Sep 17 00:00:00 2001 From: dreamsource-tai Date: Thu, 25 Jul 2024 10:53:30 +0800 Subject: [PATCH 35/47] replace malloc with g_malloc --- DSView/pv/sigsession.cpp | 2 +- DSView/pv/toolbars/samplingbar.cpp | 2 +- libsigrok4DSL/backend.c | 3 +-- libsigrok4DSL/dsdevice.c | 9 ++++--- libsigrok4DSL/hardware/DSL/dscope.c | 10 ++++---- libsigrok4DSL/hardware/DSL/dsl.c | 12 +++++----- libsigrok4DSL/hardware/DSL/dslogic.c | 14 +++++------ libsigrok4DSL/hardware/demo/demo.c | 36 ++++++++++++++-------------- libsigrok4DSL/hwdriver.c | 2 +- libsigrok4DSL/input/in_binary.c | 2 +- libsigrok4DSL/input/in_vcd.c | 4 ++-- libsigrok4DSL/input/in_wav.c | 2 +- libsigrok4DSL/lib_main.c | 6 +---- libsigrok4DSL/libsigrok-internal.h | 2 +- libsigrok4DSL/libsigrok.h | 2 +- libsigrok4DSL/output/csv.c | 14 +++++------ libsigrok4DSL/output/gnuplot.c | 6 ++--- libsigrok4DSL/output/output.c | 4 ++-- libsigrok4DSL/output/srzip.c | 2 +- libsigrok4DSL/output/vcd.c | 6 ++--- libsigrok4DSL/session.c | 2 +- libsigrok4DSL/session_driver.c | 20 ++++++++-------- libsigrok4DSL/std.c | 2 +- libsigrok4DSL/strutil.c | 20 ++++++++-------- libsigrok4DSL/trigger.c | 2 +- libsigrokdecode4DSL/HACKING | 12 +++++----- libsigrokdecode4DSL/decoder.c | 8 +++---- libsigrokdecode4DSL/instance.c | 6 ++--- libsigrokdecode4DSL/session.c | 4 ++-- libsigrokdecode4DSL/type_decoder.c | 10 ++++---- libsigrokdecode4DSL/util.c | 12 +++++----- 31 files changed, 116 insertions(+), 122 deletions(-) diff --git a/DSView/pv/sigsession.cpp b/DSView/pv/sigsession.cpp index b16159de..e6ed8cb7 100644 --- a/DSView/pv/sigsession.cpp +++ b/DSView/pv/sigsession.cpp @@ -205,7 +205,7 @@ namespace pv struct ds_device_base_info *dev = (array + count - 1); ds_device_handle dev_handle = dev->handle; - free(array); + g_free(array); if (set_device(dev_handle)) { diff --git a/DSView/pv/toolbars/samplingbar.cpp b/DSView/pv/toolbars/samplingbar.cpp index a4022f88..7b3cd6d5 100644 --- a/DSView/pv/toolbars/samplingbar.cpp +++ b/DSView/pv/toolbars/samplingbar.cpp @@ -1142,7 +1142,7 @@ namespace pv if (i == select_index) cur_dev_handle = p->handle; } - free(array); + g_free(array); _device_selector.setCurrentIndex(select_index); diff --git a/libsigrok4DSL/backend.c b/libsigrok4DSL/backend.c index c117c6de..fdd84941 100644 --- a/libsigrok4DSL/backend.c +++ b/libsigrok4DSL/backend.c @@ -317,13 +317,12 @@ SR_PRIV int sr_init(struct sr_context **ctx) } /* + 1 to handle when struct sr_context has no members. */ - context = malloc(sizeof(struct sr_context)); + context = g_try_malloc0(sizeof(struct sr_context)); if (!context) { sr_err("%s,ERROR:failed to alloc memory.", __func__); ret = SR_ERR_MALLOC; goto done; } - memset(context, 0, sizeof(struct sr_context)); ret = libusb_init(&context->libusb_ctx); diff --git a/libsigrok4DSL/dsdevice.c b/libsigrok4DSL/dsdevice.c index 28c98215..f37ea497 100644 --- a/libsigrok4DSL/dsdevice.c +++ b/libsigrok4DSL/dsdevice.c @@ -47,12 +47,11 @@ SR_PRIV struct sr_channel *sr_channel_new(uint16_t index, int type, gboolean ena { struct sr_channel *probe; - probe = malloc(sizeof(struct sr_channel)); + probe = g_try_malloc0(sizeof(struct sr_channel)); if (probe == NULL) { sr_err("%s,ERROR:failed to alloc memory.", __func__); return NULL; } - memset(probe, 0, sizeof(struct sr_channel)); probe->index = index; probe->type = type; @@ -184,7 +183,7 @@ SR_PRIV struct sr_dev_inst *sr_dev_inst_new(int mode, int status, const char *vendor, const char *model, const char *version) { struct sr_dev_inst *sdi; - if (!(sdi = malloc(sizeof(struct sr_dev_inst)))) { + if (!(sdi = g_try_malloc0(sizeof(struct sr_dev_inst)))) { sr_err("%s,ERROR:failed to alloc memory.", __func__); return NULL; } @@ -245,7 +244,7 @@ SR_PRIV void sr_dev_inst_free(struct sr_dev_inst *sdi) SR_PRIV struct sr_usb_dev_inst *sr_usb_dev_inst_new(uint8_t bus, uint8_t address) { struct sr_usb_dev_inst *udi; - if (!(udi = malloc(sizeof(struct sr_usb_dev_inst)))) { + if (!(udi = g_try_malloc0(sizeof(struct sr_usb_dev_inst)))) { sr_err("%s,ERROR:failed to alloc memory.", __func__); return NULL; } @@ -291,7 +290,7 @@ SR_PRIV struct sr_serial_dev_inst *sr_serial_dev_inst_new(const char *port, return NULL; } - if (!(serial = malloc(sizeof(struct sr_serial_dev_inst)))) { + if (!(serial = g_try_malloc0(sizeof(struct sr_serial_dev_inst)))) { sr_err("%s,ERROR:failed to alloc memory.", __func__); return NULL; } diff --git a/libsigrok4DSL/hardware/DSL/dscope.c b/libsigrok4DSL/hardware/DSL/dscope.c index c7bcdd53..591b46ef 100644 --- a/libsigrok4DSL/hardware/DSL/dscope.c +++ b/libsigrok4DSL/hardware/DSL/dscope.c @@ -124,7 +124,7 @@ static struct DSL_context *DSCope_dev_new(const struct DSL_profile *prof) assert(prof); - if (!(devc = malloc(sizeof(struct DSL_context)))) { + if (!(devc = g_try_malloc0(sizeof(struct DSL_context)))) { sr_err("Device context malloc failed."); return NULL; } @@ -329,7 +329,7 @@ static GSList *scan(GSList *options) prof->vendor, prof->model, prof->model_version); if (sdi == NULL) { - free(devc); + g_free(devc); break; } @@ -356,7 +356,7 @@ static GSList *scan(GSList *options) else { char *firmware; char *res_path = DS_RES_PATH; - if (!(firmware = malloc(strlen(res_path)+strlen(prof->firmware) + 5))) { + if (!(firmware = g_try_malloc0(strlen(res_path)+strlen(prof->firmware) + 5))) { sr_err("Firmware path malloc error!"); break; } @@ -2091,7 +2091,7 @@ static int dev_acquisition_start(struct sr_dev_inst *sdi, void *cb_data) lupfd = libusb_get_pollfds(drvc->sr_ctx->libusb_ctx); for (i = 0; lupfd[i]; i++); - if (!(devc->usbfd = malloc(sizeof(struct libusb_pollfd) * (i + 1)))){ + if (!(devc->usbfd = g_try_malloc0(sizeof(struct libusb_pollfd) * (i + 1)))){ sr_err("%s,ERROR:failed to alloc memory.", __func__); return SR_ERR; } @@ -2103,7 +2103,7 @@ static int dev_acquisition_start(struct sr_dev_inst *sdi, void *cb_data) } devc->usbfd[i] = -1; - free(lupfd); + g_free(lupfd); wr_cmd.header.dest = DSL_CTL_START; wr_cmd.header.size = 0; diff --git a/libsigrok4DSL/hardware/DSL/dsl.c b/libsigrok4DSL/hardware/DSL/dsl.c index 319a5387..d80e59b0 100644 --- a/libsigrok4DSL/hardware/DSL/dsl.c +++ b/libsigrok4DSL/hardware/DSL/dsl.c @@ -105,7 +105,7 @@ SR_PRIV void dsl_probe_init(struct sr_dev_inst *sdi) for (i = 0; devc->profile->dev_caps.vdivs[i]; i++){ } - probe->vga_ptr = malloc((i+1)*sizeof(struct DSL_vga)); + probe->vga_ptr = g_try_malloc0((i+1)*sizeof(struct DSL_vga)); if (probe->vga_ptr == NULL){ sr_err("%s,ERROR:failed to alloc memory.", __func__); return; @@ -1324,7 +1324,7 @@ SR_PRIV int dsl_fpga_config(struct libusb_device_handle *hdl, const char *filena filesize = (uint64_t)f_stat.st_size; - if ((buf = malloc(filesize)) == NULL) { + if ((buf = g_try_malloc0(filesize)) == NULL) { sr_err("FPGA configure buf malloc failed."); fclose(fw); return SR_ERR; @@ -1898,7 +1898,7 @@ SR_PRIV int dsl_dev_open(struct sr_dev_driver *di, struct sr_dev_inst *sdi, gboo char *fpga_bit; char *res_path = DS_RES_PATH; - if (!(fpga_bit = malloc(strlen(res_path)+strlen(devc->profile->fpga_bit33) + 5))) { + if (!(fpga_bit = g_try_malloc0(strlen(res_path)+strlen(devc->profile->fpga_bit33) + 5))) { sr_err("fpag_bit path malloc error!"); return SR_ERR_MALLOC; } @@ -2505,12 +2505,12 @@ SR_PRIV int dsl_start_transfers(const struct sr_dev_inst *sdi) size = get_buffer_size(sdi); /* trigger packet transfer */ - if (!(trigger_pos = malloc(dsl_header_size(devc)))) { + if (!(trigger_pos = g_try_malloc0(dsl_header_size(devc)))) { sr_err("%s: USB trigger_pos buffer malloc failed.", __func__); return SR_ERR_MALLOC; } - devc->transfers = malloc(sizeof(*devc->transfers) * (num_transfers + 1)); + devc->transfers = g_try_malloc0(sizeof(*devc->transfers) * (num_transfers + 1)); if (!devc->transfers) { sr_err("%s: USB transfer malloc failed.", __func__); return SR_ERR_MALLOC; @@ -2534,7 +2534,7 @@ SR_PRIV int dsl_start_transfers(const struct sr_dev_inst *sdi) /* data packet transfer */ for (i = 1; i <= num_transfers; i++) { - if (!(buf = malloc(size))) { + if (!(buf = g_try_malloc0(size))) { sr_err("%s: USB transfer buffer malloc failed.", __func__); return SR_ERR_MALLOC; } diff --git a/libsigrok4DSL/hardware/DSL/dslogic.c b/libsigrok4DSL/hardware/DSL/dslogic.c index 3906acc7..777341ad 100644 --- a/libsigrok4DSL/hardware/DSL/dslogic.c +++ b/libsigrok4DSL/hardware/DSL/dslogic.c @@ -204,7 +204,7 @@ static struct DSL_context *DSLogic_dev_new(const struct DSL_profile *prof) assert(prof); - if (!(devc = malloc(sizeof(struct DSL_context)))) { + if (!(devc = g_try_malloc0(sizeof(struct DSL_context)))) { sr_err("Device context malloc failed."); return NULL; } @@ -414,7 +414,7 @@ static GSList *scan(GSList *options) sdi = sr_dev_inst_new(channel_modes[devc->ch_mode].mode, SR_ST_INITIALIZING, prof->vendor, prof->model, prof->model_version); if (sdi == NULL) { - free(devc); + g_free(devc); break; } @@ -441,7 +441,7 @@ static GSList *scan(GSList *options) else { char *firmware; char *res_path = DS_RES_PATH; - if (!(firmware = malloc(strlen(res_path)+strlen(prof->firmware) + 5))) { + if (!(firmware = g_try_malloc0(strlen(res_path)+strlen(prof->firmware) + 5))) { sr_err("Firmware path malloc error!"); break; } @@ -455,7 +455,7 @@ static GSList *scan(GSList *options) sr_err("Firmware upload failed for device %s.", prof->model); } - free(firmware); + g_free(firmware); libusb_unref_device(device_handle); #ifdef _WIN32 @@ -1069,7 +1069,7 @@ static int config_set(int id, GVariant *data, struct sr_dev_inst *sdi, char *fpga_bit; char *res_path = DS_RES_PATH; - if (!(fpga_bit = malloc(strlen(res_path) + strlen(devc->profile->fpga_bit33) + 5))) { + if (!(fpga_bit = g_try_malloc0(strlen(res_path) + strlen(devc->profile->fpga_bit33) + 5))) { sr_err("fpag_bit path malloc error!"); return SR_ERR_MALLOC; } @@ -1489,7 +1489,7 @@ static int dev_acquisition_start(struct sr_dev_inst *sdi, void *cb_data) lupfd = libusb_get_pollfds(drvc->sr_ctx->libusb_ctx); for (i = 0; lupfd[i]; i++); - if (!(devc->usbfd = malloc(sizeof(struct libusb_pollfd) * (i + 1)))){ + if (!(devc->usbfd = g_try_malloc0(sizeof(struct libusb_pollfd) * (i + 1)))){ sr_err("%s,ERROR:failed to alloc memory.", __func__); return SR_ERR; } @@ -1500,7 +1500,7 @@ static int dev_acquisition_start(struct sr_dev_inst *sdi, void *cb_data) devc->usbfd[i] = lupfd[i]->fd; } devc->usbfd[i] = -1; - free(lupfd); + g_free(lupfd); wr_cmd.header.dest = DSL_CTL_START; wr_cmd.header.size = 0; diff --git a/libsigrok4DSL/hardware/demo/demo.c b/libsigrok4DSL/hardware/demo/demo.c index 344611ed..877ae31d 100644 --- a/libsigrok4DSL/hardware/demo/demo.c +++ b/libsigrok4DSL/hardware/demo/demo.c @@ -316,7 +316,7 @@ static int init_analog_random_data(struct session_vdev * vdev) { safe_free(vdev->data_buf); - vdev->data_buf = malloc(DSO_BUF_LEN); + vdev->data_buf = g_try_malloc0(DSO_BUF_LEN); if (vdev->data_buf == NULL) { sr_err("%s: vdev->data_buf malloc failed", __func__); @@ -640,7 +640,7 @@ static GSList *hw_scan(GSList *options) (void)options; devices = NULL; - vdev = malloc(sizeof(struct session_vdev)); + vdev = g_try_malloc0(sizeof(struct session_vdev)); if (vdev == NULL) { sr_err("%s: sdi->priv malloc failed", __func__); @@ -1265,11 +1265,11 @@ static int hw_dev_acquisition_start(struct sr_dev_inst *sdi, if (sdi->mode == LOGIC) { - vdev->data_buf = malloc(LOGIC_BUF_LEN); + vdev->data_buf = g_try_malloc0(LOGIC_BUF_LEN); vdev->data_buf_len = LOGIC_BUF_LEN; } else{ - vdev->data_buf = malloc(DSO_PACKET_LEN); + vdev->data_buf = g_try_malloc0(DSO_PACKET_LEN); vdev->data_buf_len = DSO_PACKET_LEN; } @@ -1341,7 +1341,7 @@ static int hw_dev_acquisition_start(struct sr_dev_inst *sdi, vdev->logci_cur_packet_num = 1; safe_free(logic_post_buf); - logic_post_buf = malloc(vdev->enabled_probes * vdev->packet_len); + logic_post_buf = g_try_malloc0(vdev->enabled_probes * vdev->packet_len); if(logic_post_buf == NULL) { sr_err("%s: logic_post_buf malloc error", __func__); @@ -1571,7 +1571,7 @@ static void free_temp_buffer(struct session_vdev *vdev) for (i = 0; i < SESSION_MAX_CHANNEL_COUNT; i++){ if (pack_buf->block_bufs[i] != NULL) { - free(pack_buf->block_bufs[i]); + g_free(pack_buf->block_bufs[i]); pack_buf->block_bufs[i] = NULL; } else{ @@ -1640,7 +1640,7 @@ static int receive_data_logic_decoder(int fd, int revents, const struct sr_dev_i { vdev->cur_block = 0; - vdev->packet_buffer = malloc(sizeof(struct session_packet_buffer)); + vdev->packet_buffer = g_try_malloc0(sizeof(struct session_packet_buffer)); if (vdev->packet_buffer == NULL) { sr_err("%s: vdev->packet_buffer malloc failed", __func__); @@ -1656,7 +1656,7 @@ static int receive_data_logic_decoder(int fd, int revents, const struct sr_dev_i vdev->packet_buffer->post_buf_len = chan_num * vdev->packet_len; - vdev->packet_buffer->post_buf = malloc(vdev->packet_buffer->post_buf_len + 1); + vdev->packet_buffer->post_buf = g_try_malloc0(vdev->packet_buffer->post_buf_len + 1); if (vdev->packet_buffer->post_buf == NULL) { sr_err("%s: vdev->packet_buffer->post_buf malloc failed", __func__); @@ -1693,7 +1693,7 @@ static int receive_data_logic_decoder(int fd, int revents, const struct sr_dev_i pack_buffer->post_buf_len = chan_num * vdev->packet_len; safe_free(pack_buffer->post_buf); - pack_buffer->post_buf = malloc(pack_buffer->post_buf_len); + pack_buffer->post_buf = g_try_malloc0(pack_buffer->post_buf_len); if (pack_buffer->post_buf == NULL) { sr_err("%s: pack_buffer->post_buf malloc failed", __func__); @@ -1748,7 +1748,7 @@ static int receive_data_logic_decoder(int fd, int revents, const struct sr_dev_i pack_buffer->block_bufs[malloc_chan_index] = NULL; } - pack_buffer->block_bufs[malloc_chan_index] = malloc(pack_buffer->block_data_len + 1); + pack_buffer->block_bufs[malloc_chan_index] = g_try_malloc0(pack_buffer->block_data_len + 1); if (pack_buffer->block_bufs[malloc_chan_index] == NULL) { sr_err("%s: block buffer malloc failed", __func__); @@ -1925,7 +1925,7 @@ static int receive_data_dso(int fd, int revents, const struct sr_dev_inst *sdi) { vdev->cur_block = 0; - vdev->packet_buffer = malloc(sizeof(struct session_packet_buffer)); + vdev->packet_buffer = g_try_malloc0(sizeof(struct session_packet_buffer)); if (vdev->packet_buffer == NULL) { sr_err("%s: vdev->packet_buffer malloc failed", __func__); @@ -1941,7 +1941,7 @@ static int receive_data_dso(int fd, int revents, const struct sr_dev_inst *sdi) vdev->packet_buffer->post_buf_len = chan_num * 10000; - vdev->packet_buffer->post_buf = malloc(vdev->packet_buffer->post_buf_len); + vdev->packet_buffer->post_buf = g_try_malloc0(vdev->packet_buffer->post_buf_len); if (vdev->packet_buffer->post_buf == NULL) { sr_err("%s: vdev->packet_buffer->post_buf malloc failed", __func__); @@ -1961,7 +1961,7 @@ static int receive_data_dso(int fd, int revents, const struct sr_dev_inst *sdi) vdev->packet_buffer->post_buf_len = chan_num * 10000; safe_free(pack_buffer->post_buf); - pack_buffer->post_buf = malloc(pack_buffer->post_buf_len); + pack_buffer->post_buf = g_try_malloc0(pack_buffer->post_buf_len); if (pack_buffer->post_buf == NULL) { sr_err("%s: pack_buffer->post_buf malloc failed", __func__); @@ -2050,7 +2050,7 @@ static int receive_data_dso(int fd, int revents, const struct sr_dev_inst *sdi) pack_buffer->block_bufs[malloc_chan_index] = NULL; } - pack_buffer->block_bufs[malloc_chan_index] = malloc(pack_buffer->block_data_len + 1); + pack_buffer->block_bufs[malloc_chan_index] = g_try_malloc0(pack_buffer->block_data_len + 1); if (pack_buffer->block_bufs[malloc_chan_index] == NULL) { sr_err("%s: block buffer malloc failed", __func__); @@ -2338,7 +2338,7 @@ static int receive_data_analog(int fd, int revents, const struct sr_dev_inst *sd { vdev->data_buf_len = 0; - void* analog_data = malloc(ANALOG_DATA_LEN_PER_CYCLE); + void* analog_data = g_try_malloc0(ANALOG_DATA_LEN_PER_CYCLE); if(analog_data == NULL) { sr_err("%s:analog_data malloc failed",__func__); @@ -2376,7 +2376,7 @@ static int receive_data_analog(int fd, int revents, const struct sr_dev_inst *sd safe_free(vdev->data_buf); - vdev->data_buf = malloc(total_buf_len); + vdev->data_buf = g_try_malloc0(total_buf_len); if (vdev->data_buf == NULL) { sr_err("%s: vdev->data_buf malloc failed", __func__); @@ -2449,7 +2449,7 @@ static int receive_data_analog(int fd, int revents, const struct sr_dev_inst *sd if(vdev->analog_post_buf_len != vdev->packet_len) { safe_free(vdev->analog_post_buf); - vdev->analog_post_buf = malloc(vdev->packet_len); + vdev->analog_post_buf = g_try_malloc0(vdev->packet_len); if(vdev->analog_post_buf == NULL) { sr_err("%s: buf malloc failed", __func__); @@ -2571,7 +2571,7 @@ static int load_virtual_device_session(struct sr_dev_inst *sdi) return SR_ERR; } - if (!(metafile = malloc(fileInfo.uncompressed_size))) + if (!(metafile = g_try_malloc0(fileInfo.uncompressed_size))) { sr_err("%s: metafile malloc failed", __func__); return SR_ERR_MALLOC; diff --git a/libsigrok4DSL/hwdriver.c b/libsigrok4DSL/hwdriver.c index d9d7c32a..73e9c52b 100644 --- a/libsigrok4DSL/hwdriver.c +++ b/libsigrok4DSL/hwdriver.c @@ -173,7 +173,7 @@ SR_PRIV struct sr_config *sr_config_new(int key, GVariant *data) struct sr_config *src; assert(data); - if (!(src = malloc(sizeof(struct sr_config)))){ + if (!(src = g_try_malloc0(sizeof(struct sr_config)))){ sr_err("%s,ERROR:failed to alloc memory.", __func__); return NULL; } diff --git a/libsigrok4DSL/input/in_binary.c b/libsigrok4DSL/input/in_binary.c index 1d659209..2a3d6ef0 100644 --- a/libsigrok4DSL/input/in_binary.c +++ b/libsigrok4DSL/input/in_binary.c @@ -57,7 +57,7 @@ static int init(struct sr_input *in, const char *filename) (void)filename; - if (!(ctx = malloc(sizeof(struct context)))) { + if (!(ctx = g_try_malloc0(sizeof(struct context)))) { sr_err("Input format context malloc failed."); return SR_ERR_MALLOC; } diff --git a/libsigrok4DSL/input/in_vcd.c b/libsigrok4DSL/input/in_vcd.c index f97f902e..efb0cb3a 100644 --- a/libsigrok4DSL/input/in_vcd.c +++ b/libsigrok4DSL/input/in_vcd.c @@ -272,7 +272,7 @@ static gboolean parse_header(FILE *file, struct context *ctx) else { sr_info("Probe %d is '%s' identified by '%s'.", ctx->probecount, parts[3], parts[2]); - probe = malloc(sizeof(struct probe)); + probe = g_try_malloc0(sizeof(struct probe)); if (probe != NULL){ probe->identifier = g_strdup(parts[2]); @@ -331,7 +331,7 @@ static int init(struct sr_input *in, const char *filename) (void)filename; - if (!(ctx = malloc(sizeof(struct context)))) { + if (!(ctx = g_try_malloc0(sizeof(struct context)))) { sr_err("Input format context malloc failed."); return SR_ERR_MALLOC; } diff --git a/libsigrok4DSL/input/in_wav.c b/libsigrok4DSL/input/in_wav.c index 7a130496..c1dc3e2a 100644 --- a/libsigrok4DSL/input/in_wav.c +++ b/libsigrok4DSL/input/in_wav.c @@ -97,7 +97,7 @@ static int init(struct sr_input *in, const char *filename) if (get_wav_header(filename, buf) != SR_OK) return SR_ERR; - if (!(ctx = malloc(sizeof(struct context)))){ + if (!(ctx = g_try_malloc0(sizeof(struct context)))){ sr_err("%s,ERROR:failed to alloc memory.", __func__); return SR_ERR_MALLOC; } diff --git a/libsigrok4DSL/lib_main.c b/libsigrok4DSL/lib_main.c index 823c3366..054cddd9 100644 --- a/libsigrok4DSL/lib_main.c +++ b/libsigrok4DSL/lib_main.c @@ -281,10 +281,6 @@ SR_API void ds_set_datafeed_callback(ds_datafeed_callback_t cb) lib_ctx.data_forward_callback = cb; } -/** - * Get the device list, if the field _handle is 0, the list visited to end. - * User need call free() to release the buffer. If the list is empty, the out_list is null. - */ SR_API int ds_get_device_list(struct ds_device_base_info **out_list, int *out_count) { int num; @@ -308,7 +304,7 @@ SR_API int ds_get_device_list(struct ds_device_base_info **out_list, int *out_co return SR_OK; } - buf = malloc(sizeof(struct ds_device_base_info) * (num + 1)); + buf = g_try_malloc0(sizeof(struct ds_device_base_info) * (num + 1)); if (buf == NULL) { sr_err("%s,ERROR:failed to alloc memory.", __func__); diff --git a/libsigrok4DSL/libsigrok-internal.h b/libsigrok4DSL/libsigrok-internal.h index 67f79bdb..a5534c0c 100644 --- a/libsigrok4DSL/libsigrok-internal.h +++ b/libsigrok4DSL/libsigrok-internal.h @@ -52,7 +52,7 @@ #define USB_EV_HOTPLUG_ATTACH 1 #define USB_EV_HOTPLUG_DETTACH 2 -#define safe_free(p) if((p)) free((p)); ((p)) = NULL; +#define safe_free(p) if((p)) g_free((p)); ((p)) = NULL; #define g_safe_free_list(p) if((p)) g_slist_free((p)); ((p)) = NULL; #define DS_VENDOR_ID 0x2A0E diff --git a/libsigrok4DSL/libsigrok.h b/libsigrok4DSL/libsigrok.h index bd8f424a..28d8a0ca 100644 --- a/libsigrok4DSL/libsigrok.h +++ b/libsigrok4DSL/libsigrok.h @@ -1406,7 +1406,7 @@ SR_API void ds_set_user_data_dir(const char *dir); /** * Get the device list, if the field _handle is 0, the list visited to end. - * User need call free() to release the buffer. If the list is empty, the out_list is null. + * User need call g_free() to release the buffer. If the list is empty, the out_list is null. */ SR_API int ds_get_device_list(struct ds_device_base_info** out_list, int *out_count); diff --git a/libsigrok4DSL/output/csv.c b/libsigrok4DSL/output/csv.c index b5a05376..12e31d24 100644 --- a/libsigrok4DSL/output/csv.c +++ b/libsigrok4DSL/output/csv.c @@ -74,7 +74,7 @@ static int init(struct sr_output *o, GHashTable *options) if (!o || !o->sdi) return SR_ERR_ARG; - ctx = malloc(sizeof(struct context)); + ctx = g_try_malloc0(sizeof(struct context)); if (ctx == NULL){ sr_err("%s,ERROR:failed to alloc memory.", __func__); return SR_ERR; @@ -102,12 +102,12 @@ static int init(struct sr_output *o, GHashTable *options) ctx->num_enabled_channels++; } - ctx->channel_index = malloc(sizeof(int) * ctx->num_enabled_channels); - ctx->channel_unit = malloc(sizeof(int) * ctx->num_enabled_channels); - ctx->channel_scale = malloc(sizeof(float) * ctx->num_enabled_channels); - ctx->channel_offset = malloc(sizeof(uint16_t) * ctx->num_enabled_channels); - ctx->channel_mmax = malloc(sizeof(double) * ctx->num_enabled_channels); - ctx->channel_mmin = malloc(sizeof(double) * ctx->num_enabled_channels); + ctx->channel_index = g_try_malloc0(sizeof(int) * ctx->num_enabled_channels); + ctx->channel_unit = g_try_malloc0(sizeof(int) * ctx->num_enabled_channels); + ctx->channel_scale = g_try_malloc0(sizeof(float) * ctx->num_enabled_channels); + ctx->channel_offset = g_try_malloc0(sizeof(uint16_t) * ctx->num_enabled_channels); + ctx->channel_mmax = g_try_malloc0(sizeof(double) * ctx->num_enabled_channels); + ctx->channel_mmin = g_try_malloc0(sizeof(double) * ctx->num_enabled_channels); if (ctx->channel_index == NULL || ctx->channel_mmin == NULL){ sr_err("%s,ERROR:failed to alloc memory.", __func__); diff --git a/libsigrok4DSL/output/gnuplot.c b/libsigrok4DSL/output/gnuplot.c index 45c2ca2f..2e5de0c4 100644 --- a/libsigrok4DSL/output/gnuplot.c +++ b/libsigrok4DSL/output/gnuplot.c @@ -60,7 +60,7 @@ static int init(struct sr_output *o, GHashTable *options) if (!o || !o->sdi) return SR_ERR_ARG; - ctx = malloc(sizeof(struct context)); + ctx = g_try_malloc0(sizeof(struct context)); if (ctx == NULL){ sr_err("%s,ERROR:failed to alloc memory.", __func__); return SR_ERR; @@ -83,7 +83,7 @@ static int init(struct sr_output *o, GHashTable *options) sr_err("No logic channel enabled."); return SR_ERR; } - ctx->channel_index = malloc(sizeof(int) * ctx->num_enabled_channels); + ctx->channel_index = g_try_malloc0(sizeof(int) * ctx->num_enabled_channels); if (ctx->channel_index == NULL){ sr_err("%s,ERROR:failed to alloc memory.", __func__); @@ -183,7 +183,7 @@ static int receive(const struct sr_output *o, const struct sr_datafeed_packet *p if (!ctx->prevsample) { /* Can't allocate this until we know the stream's unitsize. */ - ctx->prevsample = malloc(logic->unitsize); + ctx->prevsample = g_try_malloc0(logic->unitsize); if (ctx->prevsample == NULL){ sr_err("%s,ERROR:failed to alloc memory.", __func__); diff --git a/libsigrok4DSL/output/output.c b/libsigrok4DSL/output/output.c index c8cc69ad..4a285a1b 100644 --- a/libsigrok4DSL/output/output.c +++ b/libsigrok4DSL/output/output.c @@ -197,7 +197,7 @@ SR_API const struct sr_option **sr_output_options_get(const struct sr_output_mod for (size = 0; mod_opts[size].id; size++); - opts = malloc((size + 1) * sizeof(struct sr_option *)); + opts = g_try_malloc0((size + 1) * sizeof(struct sr_option *)); if (opts == NULL){ sr_err("%s,ERROR:failed to alloc memory.", __func__); return NULL; @@ -261,7 +261,7 @@ SR_API const struct sr_output* sr_output_new(const struct sr_output_module *omod gpointer key, value; int i; - op = malloc(sizeof(struct sr_output)); + op = g_try_malloc0(sizeof(struct sr_output)); if (op == NULL){ sr_err("%s,ERROR:failed to alloc memory.", __func__); return NULL; diff --git a/libsigrok4DSL/output/srzip.c b/libsigrok4DSL/output/srzip.c index 34e9b1ef..1339446c 100755 --- a/libsigrok4DSL/output/srzip.c +++ b/libsigrok4DSL/output/srzip.c @@ -48,7 +48,7 @@ static int init(struct sr_output *o, GHashTable *options) { struct out_context *outc; - outc = malloc(sizeof(struct out_context)); + outc = g_try_malloc0(sizeof(struct out_context)); if (outc == NULL){ sr_err("%s,ERROR:failed to alloc memory.", __func__); return SR_ERR; diff --git a/libsigrok4DSL/output/vcd.c b/libsigrok4DSL/output/vcd.c index d9b825f7..0bb29b34 100644 --- a/libsigrok4DSL/output/vcd.c +++ b/libsigrok4DSL/output/vcd.c @@ -65,7 +65,7 @@ static int init(struct sr_output *o, GHashTable *options) return SR_ERR; } - ctx = malloc(sizeof(struct context)); + ctx = g_try_malloc0(sizeof(struct context)); if (ctx == NULL){ sr_err("%s,ERROR:failed to alloc memory.", __func__); return SR_ERR; @@ -74,7 +74,7 @@ static int init(struct sr_output *o, GHashTable *options) o->priv = ctx; ctx->num_enabled_channels = num_enabled_channels; - ctx->channel_index = malloc(sizeof(int) * ctx->num_enabled_channels); + ctx->channel_index = g_try_malloc0(sizeof(int) * ctx->num_enabled_channels); if (ctx->channel_index == NULL){ sr_err("%s,ERROR:failed to alloc memory.", __func__); @@ -211,7 +211,7 @@ static int receive(const struct sr_output *o, const struct sr_datafeed_packet *p if (!ctx->prevsample) { /* Can't allocate this until we know the stream's unitsize. */ - ctx->prevsample = malloc(logic->unitsize); + ctx->prevsample = g_try_malloc0(logic->unitsize); if (ctx->prevsample == NULL){ sr_err("%s,ERROR:failed to alloc memory.", __func__); diff --git a/libsigrok4DSL/session.c b/libsigrok4DSL/session.c index 23a1864b..1279e2be 100644 --- a/libsigrok4DSL/session.c +++ b/libsigrok4DSL/session.c @@ -75,7 +75,7 @@ SR_PRIV struct sr_session *sr_session_new(void) sr_session_destroy(); // Destory the old. } - session = malloc(sizeof(struct sr_session)); + session = g_try_malloc0(sizeof(struct sr_session)); if (session == NULL) { sr_err("%s,ERROR:failed to alloc memory.", __func__); return NULL; diff --git a/libsigrok4DSL/session_driver.c b/libsigrok4DSL/session_driver.c index e479e2b7..3b298d4d 100644 --- a/libsigrok4DSL/session_driver.c +++ b/libsigrok4DSL/session_driver.c @@ -463,7 +463,7 @@ static int receive_data_logic_dso_v2(int fd, int revents, const struct sr_dev_in if (vdev->packet_buffer == NULL){ vdev->cur_block = 0; - vdev->packet_buffer = malloc(sizeof(struct session_packet_buffer)); + vdev->packet_buffer = g_try_malloc0(sizeof(struct session_packet_buffer)); if (vdev->packet_buffer == NULL){ sr_err("%s: vdev->packet_buffer malloc failed", __func__); return SR_ERR_MALLOC; @@ -479,7 +479,7 @@ static int receive_data_logic_dso_v2(int fd, int revents, const struct sr_dev_in else vdev->packet_buffer->post_buf_len = chan_num * 10000; - vdev->packet_buffer->post_buf = malloc(vdev->packet_buffer->post_buf_len + 1); + vdev->packet_buffer->post_buf = g_try_malloc0(vdev->packet_buffer->post_buf_len + 1); if (vdev->packet_buffer->post_buf == NULL){ sr_err("%s: vdev->packet_buffer->post_buf malloc failed", __func__); return SR_ERR_MALLOC; @@ -567,11 +567,11 @@ static int receive_data_logic_dso_v2(int fd, int revents, const struct sr_dev_in for (malloc_chan_index = 0; malloc_chan_index < chan_num; malloc_chan_index++){ // Release the old buffer. if (pack_buffer->block_bufs[malloc_chan_index] != NULL){ - free(pack_buffer->block_bufs[malloc_chan_index]); + g_free(pack_buffer->block_bufs[malloc_chan_index]); pack_buffer->block_bufs[malloc_chan_index] = NULL; } - pack_buffer->block_bufs[malloc_chan_index] = malloc(pack_buffer->block_data_len + 1); + pack_buffer->block_bufs[malloc_chan_index] = g_try_malloc(pack_buffer->block_data_len + 1); if (pack_buffer->block_bufs[malloc_chan_index] == NULL){ sr_err("%s: block buffer malloc failed", __func__); send_error_packet(sdi, vdev, &packet); @@ -747,7 +747,7 @@ static int dev_open(struct sr_dev_inst *sdi) assert(sdi->priv == NULL); - vdev = malloc(sizeof(struct session_vdev)); + vdev = g_try_malloc(sizeof(struct session_vdev)); if (vdev == NULL) { sr_err("%s: sdi->priv malloc failed", __func__); @@ -763,7 +763,7 @@ static int dev_open(struct sr_dev_inst *sdi) sdi->priv = vdev; sdi->status = SR_ST_ACTIVE; - vdev->buf = malloc(CHUNKSIZE + sizeof(uint64_t)); + vdev->buf = g_try_malloc0(CHUNKSIZE + sizeof(uint64_t)); if (vdev->buf == NULL){ sr_err("%s: vdev->buf malloc failed", __func__); return SR_ERR_MALLOC; @@ -794,7 +794,7 @@ static void free_temp_buffer(struct session_vdev *vdev) for (i = 0; i < SESSION_MAX_CHANNEL_COUNT; i++){ if (pack_buf->block_bufs[i] != NULL){ - free(pack_buf->block_bufs[i]); + g_free(pack_buf->block_bufs[i]); pack_buf->block_bufs[i] = NULL; } else{ @@ -1127,7 +1127,7 @@ static int config_set(int id, GVariant *data, struct sr_dev_inst *sdi, { if (sdi->mode == LOGIC) { - if (!(vdev->logic_buf = malloc(CHUNKSIZE / 16 * vdev->num_probes))) + if (!(vdev->logic_buf = g_try_malloc0(CHUNKSIZE / 16 * vdev->num_probes))) { sr_err("%s: vdev->logic_buf malloc failed", __func__); } @@ -1512,7 +1512,7 @@ SR_PRIV int sr_new_virtual_device(const char *filename, struct sr_dev_inst **out return SR_ERR; } - if (!(metafile = malloc(fileInfo.uncompressed_size))) + if (!(metafile = g_try_malloc0(fileInfo.uncompressed_size))) { sr_err("%s: metafile malloc failed", __func__); return SR_ERR_MALLOC; @@ -1629,7 +1629,7 @@ static int sr_load_virtual_device_session(struct sr_dev_inst *sdi) return SR_ERR; } - if (!(metafile = malloc(fileInfo.uncompressed_size))) + if (!(metafile = g_try_malloc0(fileInfo.uncompressed_size))) { sr_err("%s: metafile malloc failed", __func__); return SR_ERR_MALLOC; diff --git a/libsigrok4DSL/std.c b/libsigrok4DSL/std.c index 8ec46001..04e73f26 100644 --- a/libsigrok4DSL/std.c +++ b/libsigrok4DSL/std.c @@ -48,7 +48,7 @@ SR_PRIV int std_hw_init(struct sr_context *sr_ctx, struct sr_dev_driver *di, return SR_ERR_ARG; } - if (!(drvc = malloc(sizeof(struct drv_context)))) { + if (!(drvc = g_try_malloc0(sizeof(struct drv_context)))) { sr_err("%sDriver context malloc failed.", prefix); return SR_ERR_MALLOC; } diff --git a/libsigrok4DSL/strutil.c b/libsigrok4DSL/strutil.c index 6c02c6df..9512c0f6 100644 --- a/libsigrok4DSL/strutil.c +++ b/libsigrok4DSL/strutil.c @@ -53,7 +53,7 @@ * @param unit The unit to append to the string, or NULL if the string * has no units. * - * @return A malloc()ed string representation of the samplerate value, + * @return A g_try_malloc0()ed string representation of the samplerate value, * or NULL upon errors. The caller is responsible to g_free() the * memory. */ @@ -98,7 +98,7 @@ SR_API char *sr_si_string_u64(uint64_t x, const char *unit) * @param unit The unit to append to the string, or NULL if the string * has no units. * - * @return A malloc()ed string representation of the samplerate value, + * @return A g_try_malloc0()ed string representation of the samplerate value, * or NULL upon errors. The caller is responsible to g_free() the * memory. */ @@ -140,7 +140,7 @@ SR_API char *sr_iec_string_u64(uint64_t x, const char *unit) * * @param samplerate The samplerate in Hz. * - * @return A malloc()ed string representation of the samplerate value, + * @return A g_try_malloc0()ed string representation of the samplerate value, * or NULL upon errors. The caller is responsible to g_free() the * memory. */ @@ -156,7 +156,7 @@ SR_API char *sr_samplerate_string(uint64_t samplerate) * * @param samplecount. * - * @return A malloc()ed string representation of the samplecount value, + * @return A g_try_malloc0()ed string representation of the samplecount value, * or NULL upon errors. The caller is responsible to g_free() the * memory. */ @@ -173,7 +173,7 @@ SR_API char *sr_samplecount_string(uint64_t samplecount) * * @param frequency The frequency in Hz. * - * @return A malloc()ed string representation of the frequency value, + * @return A g_try_malloc0()ed string representation of the frequency value, * or NULL upon errors. The caller is responsible to g_free() the * memory. */ @@ -183,7 +183,7 @@ SR_API char *sr_period_string(uint64_t frequency) int r; /* Allocate enough for a uint64_t as string + " ms". */ - if (!(o = malloc(30 + 1))) { + if (!(o = g_try_malloc0(30 + 1))) { sr_err("%s: o malloc failed", __func__); return NULL; } @@ -214,7 +214,7 @@ SR_API char *sr_period_string(uint64_t frequency) * * @param time The time in ns. * - * @return A malloc()ed string representation of the time value, + * @return A g_try_malloc0()ed string representation of the time value, * or NULL upon errors. The caller is responsible to g_free() the * memory. */ @@ -224,7 +224,7 @@ SR_API char *sr_time_string(uint64_t time) int r; /* Allocate enough for a uint64_t as string + " ms". */ - if (!(o = malloc(30 + 1))) { + if (!(o = g_try_malloc0(30 + 1))) { sr_err("%s: o malloc failed", __func__); return NULL; } @@ -263,7 +263,7 @@ SR_API char *sr_time_string(uint64_t time) * @param v_p The voltage numerator. * @param v_q The voltage denominator. * - * @return A malloc()ed string representation of the voltage value, + * @return A g_try_malloc0()ed string representation of the voltage value, * or NULL upon errors. The caller is responsible to g_free() the * memory. */ @@ -272,7 +272,7 @@ SR_API char *sr_voltage_string(uint64_t v_p, uint64_t v_q) int r; char *o; - if (!(o = malloc(30 + 1))) { + if (!(o = g_try_malloc0(30 + 1))) { sr_err("%s: o malloc failed", __func__); return NULL; } diff --git a/libsigrok4DSL/trigger.c b/libsigrok4DSL/trigger.c index 91ed3dd6..35be1806 100644 --- a/libsigrok4DSL/trigger.c +++ b/libsigrok4DSL/trigger.c @@ -56,7 +56,7 @@ SR_PRIV int ds_trigger_init(void) int i, j; if (!trigger) { - if (!(trigger = malloc(sizeof(struct ds_trigger)))) { + if (!(trigger = g_try_malloc0(sizeof(struct ds_trigger)))) { sr_err("Trigger malloc failed."); return SR_ERR_MALLOC; } diff --git a/libsigrokdecode4DSL/HACKING b/libsigrokdecode4DSL/HACKING index 62c2af49..5dd8e2c1 100644 --- a/libsigrokdecode4DSL/HACKING +++ b/libsigrokdecode4DSL/HACKING @@ -42,19 +42,19 @@ Random notes especially so for complex and/or run-time dependent values. - Consistently use g_*malloc() / g_*malloc0(). Do not use standard - malloc()/calloc() if it can be avoided (sometimes other libs such - as libftdi can return malloc()'d memory, for example). + g_try_malloc0()/calloc() if it can be avoided (sometimes other libs such + as libftdi can return g_try_malloc0()'d memory, for example). - Always properly match allocations with the proper *free() functions. If glib's g_*malloc()/g_*malloc0() was used, use g_free() to free the - memory. Otherwise use standard free(). Never use the wrong function! + memory. Otherwise use standard g_free(). Never use the wrong function! - We assume that "small" memory allocations (< 1MB) will always succeed. - Thus, it's fine to use malloc() or malloc() for allocations of - simple/small structs and such (instead of using malloc()), and + Thus, it's fine to use g_try_malloc0() or g_try_malloc0() for allocations of + simple/small structs and such (instead of using g_try_malloc0()), and there's no need to check the return value. - Do use malloc() or malloc() for large (>= 1MB) allocations + Do use g_try_malloc0() or g_try_malloc0() for large (>= 1MB) allocations and check the return value. - You should never print any messages (neither to stdout nor stderr nor diff --git a/libsigrokdecode4DSL/decoder.c b/libsigrokdecode4DSL/decoder.c index aaca65c2..96f6099b 100644 --- a/libsigrokdecode4DSL/decoder.c +++ b/libsigrokdecode4DSL/decoder.c @@ -227,7 +227,7 @@ static int get_channels(const struct srd_decoder *d, const char *attr, "a list of dict elements.", d->name, attr); goto err_out; } - pdch = malloc(sizeof(struct srd_channel)); + pdch = g_try_malloc0(sizeof(struct srd_channel)); if (pdch == NULL){ srd_err("%s,ERROR:failed to alloc memory.", __func__); goto err_out; @@ -312,7 +312,7 @@ static int get_options(struct srd_decoder *d) goto err_out; } - o = malloc(sizeof(struct srd_decoder_option)); + o = g_try_malloc0(sizeof(struct srd_decoder_option)); if (o == NULL){ srd_err("%s,ERROR:failed to alloc memory.", __func__); goto err_out; @@ -522,7 +522,7 @@ static int get_annotation_rows(struct srd_decoder *dec) dec->name); goto err_out; } - ann_row = malloc(sizeof(struct srd_decoder_annotation_row)); + ann_row = g_try_malloc0(sizeof(struct srd_decoder_annotation_row)); if (ann_row == NULL){ srd_err("%s,ERROR:failed to alloc memory.", __func__); goto err_out; @@ -749,7 +749,7 @@ SRD_API int srd_decoder_load(const char *module_name) return SRD_OK; } - d = malloc(sizeof(struct srd_decoder)); + d = g_try_malloc0(sizeof(struct srd_decoder)); if (d == NULL){ srd_err("%s,ERROR:failed to alloc memory.", __func__); goto err_out; diff --git a/libsigrokdecode4DSL/instance.c b/libsigrokdecode4DSL/instance.c index 24615cfd..68e031ef 100644 --- a/libsigrokdecode4DSL/instance.c +++ b/libsigrokdecode4DSL/instance.c @@ -251,7 +251,7 @@ SRD_API int srd_inst_channel_set_all(struct srd_decoder_inst *di, return SRD_ERR_ARG; } - new_channelmap = malloc(sizeof(int) * di->dec_num_channels); + new_channelmap = g_try_malloc0(sizeof(int) * di->dec_num_channels); if (new_channelmap == NULL){ srd_err("%s,ERROR:failed to alloc memory.", __func__); return SRD_ERR; @@ -355,7 +355,7 @@ SRD_API struct srd_decoder_inst *srd_inst_new(struct srd_session *sess, return NULL; } - di = malloc(sizeof(struct srd_decoder_inst)); + di = g_try_malloc0(sizeof(struct srd_decoder_inst)); if (di == NULL){ srd_err("%s,ERROR:failed to alloc memory.", __func__); return NULL; @@ -392,7 +392,7 @@ SRD_API struct srd_decoder_inst *srd_inst_new(struct srd_session *sess, g_slist_length(di->decoder->opt_channels); if (di->dec_num_channels > 0) { - di->dec_channelmap = malloc(sizeof(int) * di->dec_num_channels); + di->dec_channelmap = g_try_malloc0(sizeof(int) * di->dec_num_channels); if (di->dec_channelmap == NULL){ PyGILState_Release(gstate); diff --git a/libsigrokdecode4DSL/session.c b/libsigrokdecode4DSL/session.c index 76411db3..fb2048ee 100644 --- a/libsigrokdecode4DSL/session.c +++ b/libsigrokdecode4DSL/session.c @@ -68,7 +68,7 @@ SRD_API int srd_session_new(struct srd_session **sess) if (!sess) return SRD_ERR_ARG; - se = malloc(sizeof(struct srd_session)); + se = g_try_malloc0(sizeof(struct srd_session)); if (se == NULL){ srd_err("%s,ERROR:failed to alloc memory.", __func__); return SRD_ERR; @@ -388,7 +388,7 @@ SRD_API int srd_pd_output_callback_add(struct srd_session *sess, srd_dbg("Registering new callback for output type %s.", output_type_name(output_type)); - pd_cb = malloc(sizeof(struct srd_pd_callback)); + pd_cb = g_try_malloc0(sizeof(struct srd_pd_callback)); if (pd_cb == NULL){ srd_err("%s,ERROR:failed to alloc memory.", __func__); return SRD_ERR; diff --git a/libsigrokdecode4DSL/type_decoder.c b/libsigrokdecode4DSL/type_decoder.c index 26685840..b5a9e7f5 100644 --- a/libsigrokdecode4DSL/type_decoder.c +++ b/libsigrokdecode4DSL/type_decoder.c @@ -337,7 +337,7 @@ static int convert_binary(struct srd_decoder_inst *di, PyObject *obj, pdb = pdata->data; pdb->bin_class = bin_class; pdb->size = size; - if (!(pdb->data = malloc(pdb->size))){ + if (!(pdb->data = g_try_malloc0(pdb->size))){ srd_err("%s,ERROR:failed to alloc memory.", __func__); return SRD_ERR_MALLOC; } @@ -675,7 +675,7 @@ static PyObject *Decoder_register(PyObject *self, PyObject *args, return py_new_output_id; } - pdo = malloc(sizeof(struct srd_pd_output)); + pdo = g_try_malloc0(sizeof(struct srd_pd_output)); if (pdo == NULL){ PyGILState_Release(gstate); srd_err("%s,ERROR:failed to alloc memory.", __func__); @@ -826,7 +826,7 @@ static int create_term_list(PyObject *py_dict, GSList **term_list, gboolean cur_ goto err; } - term = malloc(sizeof(struct srd_term)); + term = g_try_malloc0(sizeof(struct srd_term)); if (term != NULL){ memset(term, 0, sizeof(struct srd_term)); term->type = get_term_type(term_str); @@ -845,7 +845,7 @@ static int create_term_list(PyObject *py_dict, GSList **term_list, gboolean cur_ srd_err("Failed to get number of samples to skip."); goto err; } - term = malloc(sizeof(struct srd_term)); + term = g_try_malloc0(sizeof(struct srd_term)); if (term != NULL){ memset(term, 0, sizeof(struct srd_term)); term->type = SRD_TERM_SKIP; @@ -1016,7 +1016,7 @@ static int set_skip_condition(struct srd_decoder_inst *di, uint64_t count) condition_list_free(di); - term = malloc(sizeof(struct srd_term)); + term = g_try_malloc0(sizeof(struct srd_term)); if (term != NULL){ memset(term, 0, sizeof(struct srd_term)); term->type = SRD_TERM_SKIP; diff --git a/libsigrokdecode4DSL/util.c b/libsigrokdecode4DSL/util.c index 6d1958c7..b3d0bbc0 100644 --- a/libsigrokdecode4DSL/util.c +++ b/libsigrokdecode4DSL/util.c @@ -64,7 +64,7 @@ SRD_PRIV PyObject *py_import_by_name(const char *name) * @param[out] outstr ptr to char * storage to be filled in. * * @return SRD_OK upon success, a (negative) error code otherwise. - * The 'outstr' argument points to a malloc()ed string upon success. + * The 'outstr' argument points to a g_try_malloc0()ed string upon success. * * @private */ @@ -108,7 +108,7 @@ SRD_PRIV int py_attr_as_str(PyObject *py_obj, const char *attr, char **outstr) * @param[out] outstrlist ptr to GSList of char * storage to be filled in. * * @return SRD_OK upon success, a (negative) error code otherwise. - * The 'outstrlist' argument points to a GSList of malloc()ed strings + * The 'outstrlist' argument points to a GSList of g_try_malloc0()ed strings * upon success. * * @private @@ -170,7 +170,7 @@ SRD_PRIV int py_attr_as_strlist(PyObject *py_obj, const char *attr, GSList **out * @param[out] outstr Pointer to char * storage to be filled in. * * @return SRD_OK upon success, a (negative) error code otherwise. - * The 'outstr' argument points to a malloc()ed string upon success. + * The 'outstr' argument points to a g_try_malloc0()ed string upon success. * * @private */ @@ -245,7 +245,7 @@ SRD_PRIV int py_dictitem_to_int(PyObject *py_obj, const char *key) * @param[out] outstr Pointer to char * storage to be filled in. * * @return SRD_OK upon success, a (negative) error code otherwise. - * The 'outstr' argument points to a malloc()ed string upon success. + * The 'outstr' argument points to a g_try_malloc0()ed string upon success. * * @private */ @@ -286,7 +286,7 @@ SRD_PRIV int py_listitem_as_str(PyObject *py_obj, int idx, * @param outstr Pointer to char * storage to be filled in. * * @return SRD_OK upon success, a (negative) error code otherwise. - * The 'outstr' argument points to a malloc()ed string upon success. + * The 'outstr' argument points to a g_try_malloc0()ed string upon success. * * @private */ @@ -384,7 +384,7 @@ SRD_PRIV int py_pydictitem_as_long(PyObject *py_obj, PyObject *py_key, uint64_t * @param[out] outstr ptr to char * storage to be filled in. * * @return SRD_OK upon success, a (negative) error code otherwise. - * The 'outstr' argument points to a malloc()ed string upon success. + * The 'outstr' argument points to a g_try_malloc0()ed string upon success. * * @private */ From a716beeef8abf4e2b7dc0188bef78a060f8ea924 Mon Sep 17 00:00:00 2001 From: dreamsource-tai Date: Thu, 25 Jul 2024 11:29:22 +0800 Subject: [PATCH 36/47] fix: Have not free the char buffer formatting from base lib --- DSView/pv/prop/binding/deviceoptions.cpp | 13 +++++++++---- DSView/pv/prop/binding/probeoptions.cpp | 6 +++++- DSView/pv/storesession.cpp | 3 ++- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/DSView/pv/prop/binding/deviceoptions.cpp b/DSView/pv/prop/binding/deviceoptions.cpp index 4fe6b22e..64356602 100644 --- a/DSView/pv/prop/binding/deviceoptions.cpp +++ b/DSView/pv/prop/binding/deviceoptions.cpp @@ -260,8 +260,7 @@ void DeviceOptions::bind_samplerate(const QString &name, const QString label, QString DeviceOptions::print_samplerate(GVariant *const gvar) { - char *const s = sr_samplerate_string( - g_variant_get_uint64(gvar)); + char *const s = sr_samplerate_string(g_variant_get_uint64(gvar)); const QString qstring(s); g_free(s); return qstring; @@ -293,14 +292,20 @@ QString DeviceOptions::print_timebase(GVariant *const gvar) { uint64_t p, q; g_variant_get(gvar, "(tt)", &p, &q); - return QString(sr_period_string(p * q)); + char *pstr = sr_period_string(p * q); + QString qstr(pstr); + g_free(pstr); + return qstr; } QString DeviceOptions::print_vdiv(GVariant *const gvar) { uint64_t p, q; g_variant_get(gvar, "(tt)", &p, &q); - return QString(sr_voltage_string(p, q)); + char *pstr = sr_voltage_string(p, q); + QString qstr(pstr); + g_free(pstr); + return qstr; } void DeviceOptions::bind_bandwidths(const QString &name, const QString label, int key, diff --git a/DSView/pv/prop/binding/probeoptions.cpp b/DSView/pv/prop/binding/probeoptions.cpp index bfd2381a..3d9ac3ef 100644 --- a/DSView/pv/prop/binding/probeoptions.cpp +++ b/DSView/pv/prop/binding/probeoptions.cpp @@ -222,7 +222,11 @@ QString ProbeOptions::print_vdiv(GVariant *const gvar) q = 1; p /= 1000; } - return QString(sr_voltage_string(p, q)); + + char *pstr = sr_voltage_string(p, q); + QString qstr(pstr); + g_free(pstr); + return qstr; } QString ProbeOptions::print_coupling(GVariant *const gvar) diff --git a/DSView/pv/storesession.cpp b/DSView/pv/storesession.cpp index 4edfb234..f7cfe38e 100644 --- a/DSView/pv/storesession.cpp +++ b/DSView/pv/storesession.cpp @@ -618,8 +618,9 @@ bool StoreSession::meta_gen(data::Snapshot *snapshot, std::string &str) } s = sr_samplerate_string(_session->cur_snap_samplerate()); - sprintf(meta, "samplerate = %s\n", s); str += meta; + g_free(s); + s = NULL; uint64_t tmp_u64; int tmp_u8; From 47125dc1ee8649cf998e567de8feaa67996c8077 Mon Sep 17 00:00:00 2001 From: dreamsource-tai Date: Fri, 26 Jul 2024 11:32:46 +0800 Subject: [PATCH 37/47] Resolve the issue of UI garbled formatting in certain regions. --- CMakeLists.txt | 2 ++ DSView/pv/dialogs/deviceoptions.cpp | 2 -- DSView/pv/dialogs/interval.cpp | 5 ++- DSView/pv/dialogs/interval.h | 3 +- DSView/pv/dialogs/protocolexp.cpp | 5 ++- DSView/pv/dock/dsotriggerdock.h | 1 - DSView/pv/dock/keywordlineedit.cpp | 1 + DSView/pv/dock/keywordlineedit.h | 1 - DSView/pv/dock/measuredock.h | 1 - DSView/pv/dock/searchdock.h | 1 - DSView/pv/dock/triggerdock.h | 1 - DSView/pv/mainwindow.cpp | 4 ++- DSView/pv/prop/double.cpp | 7 ++-- DSView/pv/prop/int.cpp | 8 ++--- DSView/pv/prop/string.cpp | 5 +-- DSView/pv/storesession.cpp | 13 ++++--- DSView/pv/ui/xspinbox.cpp | 56 +++++++++++++++++++++++++++++ DSView/pv/ui/xspinbox.h | 43 ++++++++++++++++++++++ DSView/pv/utility/formatting.cpp | 49 +++++++++++++++++++++++++ DSView/pv/utility/formatting.h | 36 +++++++++++++++++++ DSView/pv/view/viewstatus.cpp | 7 ++-- 21 files changed, 217 insertions(+), 34 deletions(-) create mode 100644 DSView/pv/ui/xspinbox.cpp create mode 100644 DSView/pv/ui/xspinbox.h create mode 100644 DSView/pv/utility/formatting.cpp create mode 100644 DSView/pv/utility/formatting.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 7b8cf57d..ab660383 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -351,6 +351,8 @@ set(DSView_SOURCES DSView/pv/ui/xtoolbutton.cpp DSView/pv/ui/uimanager.cpp DSView/pv/ui/popupdlglist.cpp + DSView/pv/ui/xspinbox.cpp + DSView/pv/utility/formatting.cpp ) set(DSView_HEADERS diff --git a/DSView/pv/dialogs/deviceoptions.cpp b/DSView/pv/dialogs/deviceoptions.cpp index 53d843e6..7d4ae1c4 100644 --- a/DSView/pv/dialogs/deviceoptions.cpp +++ b/DSView/pv/dialogs/deviceoptions.cpp @@ -23,8 +23,6 @@ #include "deviceoptions.h" #include -#include -#include #include #include #include diff --git a/DSView/pv/dialogs/interval.cpp b/DSView/pv/dialogs/interval.cpp index f9bdec2d..d4fa7749 100644 --- a/DSView/pv/dialogs/interval.cpp +++ b/DSView/pv/dialogs/interval.cpp @@ -20,10 +20,9 @@ */ #include "interval.h" - #include - #include "../ui/langresource.h" +#include "../ui/xspinbox.h" namespace pv { namespace dialogs { @@ -41,7 +40,7 @@ Interval::Interval(QWidget *parent) : setMinimumWidth(300); _interval_label = new QLabel(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_INTERVAL_S), "Interval(s): "), this); - _interval_spinBox = new QDoubleSpinBox(this); + _interval_spinBox = new XDoubleSpinBox(this); _interval_spinBox->setRange(0.1, 10); _interval_spinBox->setDecimals(1); _interval_spinBox->setButtonSymbols(QAbstractSpinBox::NoButtons); diff --git a/DSView/pv/dialogs/interval.h b/DSView/pv/dialogs/interval.h index 825c0330..05fb7bca 100644 --- a/DSView/pv/dialogs/interval.h +++ b/DSView/pv/dialogs/interval.h @@ -24,7 +24,6 @@ #define DSVIEW_PV_INTERVAL_H #include -#include #include #include @@ -32,6 +31,8 @@ #include "../toolbars/titlebar.h" #include "dsdialog.h" +class QDoubleSpinBox; + namespace pv { namespace dialogs { diff --git a/DSView/pv/dialogs/protocolexp.cpp b/DSView/pv/dialogs/protocolexp.cpp index e3f0cb9b..f65d8e31 100644 --- a/DSView/pv/dialogs/protocolexp.cpp +++ b/DSView/pv/dialogs/protocolexp.cpp @@ -44,6 +44,7 @@ #include "../log.h" #include "../ui/langresource.h" #include "../ui/msgbox.h" + #include "../utility/formatting.h" #define EXPORT_DEC_ROW_COUNT_MAX 20 @@ -166,7 +167,9 @@ void ProtocolExp::onAccept() AppConfig &app = AppConfig::Instance(); QString default_filter = _format_combobox->currentText(); QString default_name = app.userHistory.protocolExportPath + "/" + "decoder-"; - default_name += _session->get_session_time().toString("-yyMMdd-hhmmss"); + + QString dateTimeString = Formatting::DateTimeToString(_session->get_session_time(), TimeStrigFormatType::TIME_STR_FORMAT_SHORT2); + default_name += "-" + dateTimeString; QString file_name = QFileDialog::getSaveFileName( this, diff --git a/DSView/pv/dock/dsotriggerdock.h b/DSView/pv/dock/dsotriggerdock.h index 77c3323d..2ef8a253 100644 --- a/DSView/pv/dock/dsotriggerdock.h +++ b/DSView/pv/dock/dsotriggerdock.h @@ -24,7 +24,6 @@ #include #include -#include #include #include #include diff --git a/DSView/pv/dock/keywordlineedit.cpp b/DSView/pv/dock/keywordlineedit.cpp index aef003ec..2c2e4722 100644 --- a/DSView/pv/dock/keywordlineedit.cpp +++ b/DSView/pv/dock/keywordlineedit.cpp @@ -22,6 +22,7 @@ #include "keywordlineedit.h" #include #include +#include #include "../config/appconfig.h" #include "../ui/langresource.h" #include "../log.h" diff --git a/DSView/pv/dock/keywordlineedit.h b/DSView/pv/dock/keywordlineedit.h index 93b50cb8..414073cc 100644 --- a/DSView/pv/dock/keywordlineedit.h +++ b/DSView/pv/dock/keywordlineedit.h @@ -27,7 +27,6 @@ #include #include #include -#include #include class IKeywordActive{ diff --git a/DSView/pv/dock/measuredock.h b/DSView/pv/dock/measuredock.h index 6a4821ce..4e19a2ae 100644 --- a/DSView/pv/dock/measuredock.h +++ b/DSView/pv/dock/measuredock.h @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include diff --git a/DSView/pv/dock/searchdock.h b/DSView/pv/dock/searchdock.h index ff71acf9..08e1fb40 100644 --- a/DSView/pv/dock/searchdock.h +++ b/DSView/pv/dock/searchdock.h @@ -29,7 +29,6 @@ #include #include #include -#include #include #include diff --git a/DSView/pv/dock/triggerdock.h b/DSView/pv/dock/triggerdock.h index 4248c312..c1e16bd7 100644 --- a/DSView/pv/dock/triggerdock.h +++ b/DSView/pv/dock/triggerdock.h @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include diff --git a/DSView/pv/mainwindow.cpp b/DSView/pv/mainwindow.cpp index 5ba86a0c..74dc348b 100644 --- a/DSView/pv/mainwindow.cpp +++ b/DSView/pv/mainwindow.cpp @@ -43,6 +43,7 @@ #include #include #include +#include "utility/formatting.h" //include with qt5 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) @@ -525,7 +526,8 @@ namespace pv void MainWindow::on_screenShot() { AppConfig &app = AppConfig::Instance(); - QString default_name = app.userHistory.screenShotPath + "/" + APP_NAME + QDateTime::currentDateTime().toString("-yyMMdd-hhmmss"); + QString dateTimeString = Formatting::DateTimeToString(QDateTime::currentDateTime(), TimeStrigFormatType::TIME_STR_FORMAT_SHORT2); + QString default_name = app.userHistory.screenShotPath + "/" + APP_NAME + "-" + dateTimeString; int x = parentWidget()->pos().x(); int y = parentWidget()->pos().y(); diff --git a/DSView/pv/prop/double.cpp b/DSView/pv/prop/double.cpp index b5c7c3d7..2672f87b 100644 --- a/DSView/pv/prop/double.cpp +++ b/DSView/pv/prop/double.cpp @@ -20,11 +20,10 @@ */ +#include "double.h" #include +#include "../ui/xspinbox.h" -#include - -#include "double.h" using namespace std; using namespace boost; @@ -57,7 +56,7 @@ QWidget* Double::get_widget(QWidget *parent, bool auto_commit) if (_spin_box) return _spin_box; - _spin_box = new QDoubleSpinBox(parent); + _spin_box = new XDoubleSpinBox(parent); _spin_box->setDecimals(_decimals); _spin_box->setSuffix(_suffix); if (_range) diff --git a/DSView/pv/prop/int.cpp b/DSView/pv/prop/int.cpp index 3648193d..c6e9f60c 100644 --- a/DSView/pv/prop/int.cpp +++ b/DSView/pv/prop/int.cpp @@ -20,13 +20,11 @@ */ +#include "int.h" #include #include #include - -#include - -#include "int.h" +#include "../ui/xspinbox.h" using boost::optional; using namespace std; @@ -82,7 +80,7 @@ QWidget* Int::get_widget(QWidget *parent, bool auto_commit) if (!_value) return NULL; - _spin_box = new QSpinBox(parent); + _spin_box = new XSpinBox(parent); _spin_box->setSuffix(_suffix); const GVariantType *const type = g_variant_get_type(_value); diff --git a/DSView/pv/prop/string.cpp b/DSView/pv/prop/string.cpp index 04648e68..79c0b255 100644 --- a/DSView/pv/prop/string.cpp +++ b/DSView/pv/prop/string.cpp @@ -19,12 +19,9 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "string.h" #include - #include -#include - -#include "string.h" namespace pv { namespace prop { diff --git a/DSView/pv/storesession.cpp b/DSView/pv/storesession.cpp index f7cfe38e..bad85ce6 100644 --- a/DSView/pv/storesession.cpp +++ b/DSView/pv/storesession.cpp @@ -60,8 +60,8 @@ #include "utility/encoding.h" #include "utility/path.h" #include "log.h" - #include "ui/langresource.h" + #include "utility/formatting.h" #define DEOCDER_CONFIG_VERSION 2 @@ -922,8 +922,8 @@ void StoreSession::export_exec(data::Snapshot *snapshot) } } - QString sessionTime = _session->get_session_time().toString("yyyy-MM-dd HH:mm:ss"); - strcpy(output.time_string, sessionTime.toStdString().c_str()); + QString dateTimeString = Formatting::DateTimeToString(_session->get_session_time(), TimeStrigFormatType::TIME_STR_FORMAT_ALL); + strcpy(output.time_string, dateTimeString.toStdString().c_str()); QFile file(_file_name); file.open(QIODevice::WriteOnly | QIODevice::Text); @@ -1649,7 +1649,8 @@ QString StoreSession::MakeSaveFile(bool bDlg) } } - default_name += _session->get_session_time().toString("-yyMMdd-hhmmss"); + QString dateTimeString = Formatting::DateTimeToString(_session->get_session_time(), TimeStrigFormatType::TIME_STR_FORMAT_SHORT2); + default_name += "-" + dateTimeString; // Show the dialog if (bDlg) @@ -1707,7 +1708,9 @@ QString StoreSession::MakeExportFile(bool bDlg) break; } } - default_name += _session->get_session_time().toString("-yyMMdd-hhmmss"); + + QString dateTimeString = Formatting::DateTimeToString(_session->get_session_time(), TimeStrigFormatType::TIME_STR_FORMAT_SHORT2); + default_name += "-" + dateTimeString; //ext name QList supportedFormats = getSuportedExportFormats(); diff --git a/DSView/pv/ui/xspinbox.cpp b/DSView/pv/ui/xspinbox.cpp new file mode 100644 index 00000000..fd9ef540 --- /dev/null +++ b/DSView/pv/ui/xspinbox.cpp @@ -0,0 +1,56 @@ +/* + * This file is part of the DSView project. + * DSView is based on PulseView. + * + * Copyright (C) 2024 DreamSourceLab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "xspinbox.h" + +XSpinBox::XSpinBox(QWidget *parent) + : QSpinBox(parent) +{ + +} + +XSpinBox::~XSpinBox() +{ + +} + +QString XSpinBox::textFromValue(int val) const +{ + return QString::number(val); +} + +//-------------------XDoubleSpinBox +XDoubleSpinBox::XDoubleSpinBox(QWidget *parent) + : QDoubleSpinBox(parent) +{ + +} + +XDoubleSpinBox::~XDoubleSpinBox() +{ + +} + +QString XDoubleSpinBox::textFromValue(double val) const +{ + int digit = decimals(); + return QString::number(val, 'f', digit); +} \ No newline at end of file diff --git a/DSView/pv/ui/xspinbox.h b/DSView/pv/ui/xspinbox.h new file mode 100644 index 00000000..42aeeca5 --- /dev/null +++ b/DSView/pv/ui/xspinbox.h @@ -0,0 +1,43 @@ +/* + * This file is part of the DSView project. + * DSView is based on PulseView. + * + * Copyright (C) 2024 DreamSourceLab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +class XSpinBox : public QSpinBox +{ +public: + XSpinBox(QWidget *parent); + ~XSpinBox(); + +protected: + QString textFromValue(int val) const override; +}; + +class XDoubleSpinBox : public QDoubleSpinBox +{ +public: + XDoubleSpinBox(QWidget *parent); + ~XDoubleSpinBox(); + +protected: + QString textFromValue(double val) const override; +}; \ No newline at end of file diff --git a/DSView/pv/utility/formatting.cpp b/DSView/pv/utility/formatting.cpp new file mode 100644 index 00000000..b4efe03b --- /dev/null +++ b/DSView/pv/utility/formatting.cpp @@ -0,0 +1,49 @@ +/* + * This file is part of the DSView project. + * DSView is based on PulseView. + * + * Copyright (C) 2024 DreamSourceLab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "formatting.h" +#include +#include +#include + +QString Formatting::DateTimeToString(QDateTime tm, TimeStrigFormatType format) +{ + int year = tm.date().year(); + int month = tm.date().month(); + int day = tm.date().day(); + int hour = tm.time().hour(); + int minute = tm.time().minute(); + int second = tm.time().second(); + + char buffer[20]; + + switch (format) + { + case TimeStrigFormatType::TIME_STR_FORMAT_SHORT2: //"yyMMdd-hhmmss" + sprintf(buffer, "%02d%02d%02d-%02d%02d%02d", year%100, month, day, hour, minute, second); + break; + default: //yyyy-MM-dd hh:mm:ss + sprintf(buffer, "%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second); + break; + } + + return QString(buffer); +} \ No newline at end of file diff --git a/DSView/pv/utility/formatting.h b/DSView/pv/utility/formatting.h new file mode 100644 index 00000000..f936c4cc --- /dev/null +++ b/DSView/pv/utility/formatting.h @@ -0,0 +1,36 @@ +/* + * This file is part of the DSView project. + * DSView is based on PulseView. + * + * Copyright (C) 2024 DreamSourceLab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +class QDateTime; +class QString; + +enum TimeStrigFormatType +{ + TIME_STR_FORMAT_ALL = 0, //"yyyy-MM-dd hh:mm:ss" + TIME_STR_FORMAT_SHORT2, //"yyMMdd-hhmmss" +}; + + +class Formatting +{ +public: + static QString DateTimeToString(QDateTime tm, TimeStrigFormatType format); +}; \ No newline at end of file diff --git a/DSView/pv/view/viewstatus.cpp b/DSView/pv/view/viewstatus.cpp index feff7362..3796b351 100644 --- a/DSView/pv/view/viewstatus.cpp +++ b/DSView/pv/view/viewstatus.cpp @@ -40,6 +40,7 @@ #include "../config/appconfig.h" #include "../appcontrol.h" #include "../ui/fn.h" +#include "../utility/formatting.h" using namespace std; @@ -188,9 +189,9 @@ void ViewStatus::repeat_unshow() } void ViewStatus::set_trig_time(QDateTime time) -{ - _trig_time = L_S(STR_PAGE_DLG, S_ID(IDS_DLG_TRIGGER_TIME), "Trigger Time: ") + time.toString("yyyy-MM-dd hh:mm:ss"); - // assert(0); +{ + QString dateTimeString = Formatting::DateTimeToString(time, TimeStrigFormatType::TIME_STR_FORMAT_ALL); + _trig_time = L_S(STR_PAGE_DLG, S_ID(IDS_DLG_TRIGGER_TIME), "Trigger Time: ") + dateTimeString; } void ViewStatus::set_rle_depth(uint64_t depth) From a4db63b4e4605d2d1aace9e4ee0c6fc58b0ddcb9 Mon Sep 17 00:00:00 2001 From: dreamsource-tai Date: Fri, 26 Jul 2024 14:18:28 +0800 Subject: [PATCH 38/47] custom progressbar --- CMakeLists.txt | 1 + DSView/pv/dialogs/storeprogress.cpp | 16 ++++++------ DSView/pv/dialogs/storeprogress.h | 4 +-- DSView/pv/ui/xprogressbar.cpp | 38 +++++++++++++++++++++++++++++ DSView/pv/ui/xprogressbar.h | 37 ++++++++++++++++++++++++++++ DSView/pv/ui/xspinbox.h | 7 +++++- DSView/pv/utility/formatting.h | 7 +++++- 7 files changed, 99 insertions(+), 11 deletions(-) create mode 100644 DSView/pv/ui/xprogressbar.cpp create mode 100644 DSView/pv/ui/xprogressbar.h diff --git a/CMakeLists.txt b/CMakeLists.txt index ab660383..cc82669f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -352,6 +352,7 @@ set(DSView_SOURCES DSView/pv/ui/uimanager.cpp DSView/pv/ui/popupdlglist.cpp DSView/pv/ui/xspinbox.cpp + DSView/pv/ui/xprogressbar.cpp DSView/pv/utility/formatting.cpp ) diff --git a/DSView/pv/dialogs/storeprogress.cpp b/DSView/pv/dialogs/storeprogress.cpp index f7fc1a3d..bb2685a2 100644 --- a/DSView/pv/dialogs/storeprogress.cpp +++ b/DSView/pv/dialogs/storeprogress.cpp @@ -37,6 +37,7 @@ #include "../view/cursor.h" #include "../ui/langresource.h" #include "../ui/dscombobox.h" +#include "../ui/xprogressbar.h" namespace pv { namespace dialogs { @@ -48,12 +49,13 @@ StoreProgress::StoreProgress(SigSession *session, QWidget *parent) : _ckOrigin = NULL; _store_session = new StoreSession(session); + _progress = new XProgressBar(this); this->setMinimumSize(550, 220); this->setModal(true); - _progress.setValue(0); - _progress.setMaximum(100); + _progress->setValue(0); + _progress->setMaximum(100); _isExport = false; _is_done = false; @@ -83,7 +85,7 @@ StoreProgress::StoreProgress(SigSession *session, QWidget *parent) : _space->setMinimumHeight(80); _space->setVisible(false); - grid->addWidget(&_progress, 0, 0, 1, 4); + grid->addWidget(_progress, 0, 0, 1, 4); grid->addWidget(_fileLab, 1, 0, 1, 3); grid->addWidget(_openButton, 1, 3, 1, 1); grid->addWidget(_space); @@ -102,7 +104,7 @@ StoreProgress::StoreProgress(SigSession *session, QWidget *parent) : connect(_openButton, SIGNAL(clicked()),this, SLOT(on_change_file())); - _progress.setVisible(false); + _progress->setVisible(false); connect(&m_timer, &QTimer::timeout, this, &StoreProgress::on_timeout); m_timer.setInterval(100); @@ -222,7 +224,7 @@ void StoreProgress::accept() _store_session->SetDataRange(start_index, end_index); } - _progress.setVisible(true); + _progress->setVisible(true); _fileLab->setVisible(false); _fileLab->setVisible(false); _openButton->setVisible(false); @@ -370,10 +372,10 @@ void StoreProgress::on_progress_updated() if (writed < total){ int percent = writed * 1.0 / total * 100.0; - _progress.setValue(percent); + _progress->setValue(percent); } else{ - _progress.setValue(100); + _progress->setValue(100); } const QString err = _store_session->error(); diff --git a/DSView/pv/dialogs/storeprogress.h b/DSView/pv/dialogs/storeprogress.h index 974039ef..600b57fe 100644 --- a/DSView/pv/dialogs/storeprogress.h +++ b/DSView/pv/dialogs/storeprogress.h @@ -23,7 +23,6 @@ #ifndef DSVIEW_PV_DIALOGS_SAVEPROGRESS_H #define DSVIEW_PV_DIALOGS_SAVEPROGRESS_H -#include #include #include "../storesession.h" #include "../dialogs/dsdialog.h" @@ -35,6 +34,7 @@ class QGridLayout; class QPushButton; class QWidget; class QComboBox; +class QProgressBar; namespace pv { namespace view { @@ -81,7 +81,7 @@ private slots: private: pv::StoreSession *_store_session; - QProgressBar _progress; + QProgressBar *_progress; bool _isExport; QTextEdit *_fileLab; QRadioButton *_ckOrigin; diff --git a/DSView/pv/ui/xprogressbar.cpp b/DSView/pv/ui/xprogressbar.cpp new file mode 100644 index 00000000..bcbbefd2 --- /dev/null +++ b/DSView/pv/ui/xprogressbar.cpp @@ -0,0 +1,38 @@ +/* + * This file is part of the DSView project. + * DSView is based on PulseView. + * + * Copyright (C) 2024 DreamSourceLab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "xprogressbar.h" + +XProgressBar::XProgressBar(QWidget *parent) + :QProgressBar(parent) +{ + +} + +XProgressBar::~XProgressBar() +{ + +} + +QString XProgressBar::text() const +{ + return QString::number(value()) + "%"; +} \ No newline at end of file diff --git a/DSView/pv/ui/xprogressbar.h b/DSView/pv/ui/xprogressbar.h new file mode 100644 index 00000000..930f8aa6 --- /dev/null +++ b/DSView/pv/ui/xprogressbar.h @@ -0,0 +1,37 @@ +/* + * This file is part of the DSView project. + * DSView is based on PulseView. + * + * Copyright (C) 2024 DreamSourceLab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef XPROGRESS_H +#define XPROGRESS_H + +#include +#include + +class XProgressBar : public QProgressBar +{ +public: + XProgressBar(QWidget *parent); + ~XProgressBar(); + + QString text() const override; +}; + +#endif diff --git a/DSView/pv/ui/xspinbox.h b/DSView/pv/ui/xspinbox.h index 42aeeca5..7b205d94 100644 --- a/DSView/pv/ui/xspinbox.h +++ b/DSView/pv/ui/xspinbox.h @@ -19,6 +19,9 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#ifndef XSPINBOX_H +#define XSPINBOX_H + #include #include @@ -40,4 +43,6 @@ class XDoubleSpinBox : public QDoubleSpinBox protected: QString textFromValue(double val) const override; -}; \ No newline at end of file +}; + +#endif \ No newline at end of file diff --git a/DSView/pv/utility/formatting.h b/DSView/pv/utility/formatting.h index f936c4cc..d32bb764 100644 --- a/DSView/pv/utility/formatting.h +++ b/DSView/pv/utility/formatting.h @@ -19,6 +19,9 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#ifndef FORMATTING_H +#define FORMATTING_H + class QDateTime; class QString; @@ -33,4 +36,6 @@ class Formatting { public: static QString DateTimeToString(QDateTime tm, TimeStrigFormatType format); -}; \ No newline at end of file +}; + +#endif \ No newline at end of file From a137c03ff005cb3e7b7b20a225e34c133b401539 Mon Sep 17 00:00:00 2001 From: dreamsource-tai Date: Fri, 26 Jul 2024 15:08:24 +0800 Subject: [PATCH 39/47] fix: CSV files use commas as decimal separators. --- libsigrok4DSL/output/csv.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/libsigrok4DSL/output/csv.c b/libsigrok4DSL/output/csv.c index 12e31d24..b1a20e5d 100644 --- a/libsigrok4DSL/output/csv.c +++ b/libsigrok4DSL/output/csv.c @@ -26,6 +26,7 @@ #include "../config.h" /* Needed for PACKAGE_STRING and others. */ #include "../log.h" #include +#include #undef LOG_PREFIX #define LOG_PREFIX "csv: " @@ -227,6 +228,21 @@ static int receive(const struct sr_output *o, const struct sr_datafeed_packet *p double tmpv; struct sr_channel *ch; + int bDotLetter = 0; + char tmp_buffer[50]; + char *pFlagCheck = tmp_buffer; + + sprintf(tmp_buffer, "%0.15g", DBL_MAX); + + while (*pFlagCheck) + { + if (*pFlagCheck == '.'){ + bDotLetter = 1; + break; + } + pFlagCheck++; + } + *out = NULL; if (!o || !o->sdi) return SR_ERR_ARG; @@ -266,7 +282,24 @@ static int receive(const struct sr_output *o, const struct sr_datafeed_packet *p } tmpv = (double)(ctx->index-1) / (double)ctx->samplerate; - g_string_append_printf(*out, "%0.15g", tmpv); + + if (bDotLetter){ + g_string_append_printf(*out, "%0.15g", tmpv); + } + else{ + sprintf(tmp_buffer, "%0.15g", tmpv); + pFlagCheck = tmp_buffer; + + while (*pFlagCheck){ + if (*pFlagCheck == ','){ + *pFlagCheck = '.'; + break; + } + pFlagCheck++; + } + + g_string_append_printf(*out, tmp_buffer); + } for (j = 0; j < ctx->num_enabled_channels; j++) { idx = j; From fcc3c0192612dba7611dea777ea7a5cf8fb01298 Mon Sep 17 00:00:00 2001 From: dreamsource-tai Date: Fri, 26 Jul 2024 18:43:32 +0800 Subject: [PATCH 40/47] fix: the thread crashed when searching edge from bit data --- DSView/pv/data/logicsnapshot.cpp | 8 ++- DSView/pv/data/logicsnapshot.h | 5 ++ DSView/pv/dock/searchdock.cpp | 106 +++++++++++++++++++++++++------ DSView/pv/dock/searchdock.h | 3 + 4 files changed, 102 insertions(+), 20 deletions(-) diff --git a/DSView/pv/data/logicsnapshot.cpp b/DSView/pv/data/logicsnapshot.cpp index b860bc1f..b2226cd8 100644 --- a/DSView/pv/data/logicsnapshot.cpp +++ b/DSView/pv/data/logicsnapshot.cpp @@ -59,6 +59,7 @@ LogicSnapshot::LogicSnapshot() : _is_loop = false; _loop_offset = 0; _able_free = true; + _is_search_stop = false; } LogicSnapshot::~LogicSnapshot() @@ -1258,6 +1259,7 @@ bool LogicSnapshot::pattern_search(int64_t start, int64_t end, int64_t& index, { std::lock_guard lock(_mutex); + _is_search_stop = false; start += _loop_offset; end += _loop_offset; index += _loop_offset; @@ -1324,12 +1326,16 @@ bool LogicSnapshot::pattern_search_self(int64_t start, int64_t end, int64_t &ind index = end; } - while (index != to) + while (index != to && !_is_search_stop) { macthed = 0; for (int i = 0; i < count; i++) { + if (_is_search_stop){ + break; + } + val = (char)get_sample_self(index, chanIndexs[i]); if (flagList[i] == '0') diff --git a/DSView/pv/data/logicsnapshot.h b/DSView/pv/data/logicsnapshot.h index e64f63d1..acd36dd0 100644 --- a/DSView/pv/data/logicsnapshot.h +++ b/DSView/pv/data/logicsnapshot.h @@ -150,6 +150,10 @@ class LogicSnapshot : public Snapshot return _loop_offset; } + inline void cancel_search(){ + _is_search_stop = true; + } + int get_block_index_with_sample(uint64_t sample_index, uint64_t *out_offset); private: @@ -257,6 +261,7 @@ class LogicSnapshot : public Snapshot std::vector _free_block_list; struct BlockIndex _cur_ref_block_indexs[CHANNEL_MAX_COUNT]; int _lst_free_block_index; + bool _is_search_stop; friend class LogicSnapshotTest::Pow2; friend class LogicSnapshotTest::Basic; diff --git a/DSView/pv/dock/searchdock.cpp b/DSView/pv/dock/searchdock.cpp index 85471196..17e52268 100644 --- a/DSView/pv/dock/searchdock.cpp +++ b/DSView/pv/dock/searchdock.cpp @@ -38,11 +38,40 @@ #include #include #include +#include #include "../config/appconfig.h" #include "../ui/langresource.h" #include "../ui/msgbox.h" #include "../appcontrol.h" #include "../ui/fn.h" +#include "../log.h" + + +class EdgeSearchProgressDialog : public QProgressDialog +{ +public: + EdgeSearchProgressDialog(QWidget *parent, QString &title, QString &cancelText) + :QProgressDialog(title, cancelText, 0, 0, parent, Qt::CustomizeWindowHint) + { + + } + + ~EdgeSearchProgressDialog(){ + + } + +protected: + void keyPressEvent(QKeyEvent *event) override + { + if (event->key() == Qt::Key_Escape) { + canceled(); + close(); + } + else { + QWidget::keyPressEvent(event); + } + } +}; namespace pv { namespace dock { @@ -55,6 +84,9 @@ SearchDock::SearchDock(QWidget *parent, View &view, SigSession *session) : _session(session), _view(view) { + _is_busy = false; + _is_cancel = false; + _search_button = new QPushButton(this); _search_button->setFixedWidth(_search_button->height()); _search_button->setDisabled(true); @@ -109,14 +141,16 @@ void SearchDock::reStyle() void SearchDock::paintEvent(QPaintEvent *) { -// QStyleOption opt; -// opt.init(this); -// QPainter p(this); -// style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } void SearchDock::on_previous() { + if (_is_busy){ + dsv_info("The searching task is busy,please wait."); + return; + } + + _is_cancel = false; bool ret; int64_t last_pos; bool last_hit; @@ -140,28 +174,35 @@ void SearchDock::on_previous() } else { QFuture future; + future = QtConcurrent::run([&]{ last_pos -= last_hit; + _is_busy = true; ret = logic_snapshot->pattern_search(0, end, last_pos, _pattern, false); + _is_busy = false; }); + Qt::WindowFlags flags = Qt::CustomizeWindowHint; - QProgressDialog dlg(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_SEARCH_PREVIOUS), "Search Previous..."), - L_S(STR_PAGE_DLG, S_ID(IDS_DLG_CANCEL), "Cancel"),0,0,this,flags); + QString title = L_S(STR_PAGE_DLG, S_ID(IDS_DLG_SEARCH_PREVIOUS), "Search Previous..."); + QString cancelText = L_S(STR_PAGE_DLG, S_ID(IDS_DLG_CANCEL), "Cancel"); + EdgeSearchProgressDialog dlg(this, title, cancelText); dlg.setWindowModality(Qt::WindowModal); dlg.setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint); - dlg.setCancelButton(NULL); QFutureWatcher watcher; - connect(&watcher,SIGNAL(finished()),&dlg,SLOT(cancel())); + connect(&watcher, SIGNAL(finished()), &dlg, SLOT(cancel())); + connect(&dlg, SIGNAL(canceled()), SLOT(on_progress_cancel())); watcher.setFuture(future); dlg.exec(); if (!ret) { QString strMsg(L_S(STR_PAGE_MSG, S_ID(IDS_MSG_PATTERN_NOT_FOUND), "Pattern not found!")); - MsgBox::Show(strMsg); - return; - } else { + if (!_is_cancel){ + MsgBox::Show(strMsg); + } + } + else { _view.set_search_pos(last_pos, true); } } @@ -169,6 +210,13 @@ void SearchDock::on_previous() void SearchDock::on_next() { + if (_is_busy){ + dsv_info("The searching task is busy,please wait."); + return; + } + + _is_cancel = false; + bool ret; int64_t last_pos; const auto snapshot = _session->get_snapshot(SR_CHANNEL_LOGIC); @@ -187,34 +235,54 @@ void SearchDock::on_next() QString strMsg(L_S(STR_PAGE_MSG, S_ID(IDS_MSG_SEARCH_AT_END), "Search cursor at the end position!")); MsgBox::Show(strMsg); return; - } else { + } + else { QFuture future; + future = QtConcurrent::run([&]{ + _is_busy = true; ret = logic_snapshot->pattern_search(0, end, last_pos, _pattern, true); + _is_busy = false; }); + Qt::WindowFlags flags = Qt::CustomizeWindowHint; - QProgressDialog dlg(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_SEARCH_NEXT), "Search Next..."), - L_S(STR_PAGE_DLG, S_ID(IDS_DLG_CANCEL), "Cancel"),0,0,this,flags); + QString title = L_S(STR_PAGE_DLG, S_ID(IDS_DLG_SEARCH_NEXT), "Search Next..."); + QString cancelText = L_S(STR_PAGE_DLG, S_ID(IDS_DLG_CANCEL), "Cancel"); + EdgeSearchProgressDialog dlg(this, title, cancelText); dlg.setWindowModality(Qt::WindowModal); dlg.setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint); - dlg.setCancelButton(NULL); QFutureWatcher watcher; - connect(&watcher,SIGNAL(finished()),&dlg,SLOT(cancel())); + connect(&watcher, SIGNAL(finished()), &dlg, SLOT(cancel())); + connect(&dlg, SIGNAL(canceled()), SLOT(on_progress_cancel())); watcher.setFuture(future); dlg.exec(); if (!ret) { QString strMsg(L_S(STR_PAGE_MSG, S_ID(IDS_MSG_PATTERN_NOT_FOUND), "Pattern not found!")); - MsgBox::Show(strMsg); - return; - } else { + if (!_is_cancel){ + MsgBox::Show(strMsg); + } + } + else { _view.set_search_pos(last_pos, true); } } } +void SearchDock::on_progress_cancel() +{ + const auto snapshot = _session->get_snapshot(SR_CHANNEL_LOGIC); + const auto logic_snapshot = dynamic_cast(snapshot); + + _is_cancel = true; + + if (logic_snapshot != NULL){ + logic_snapshot->cancel_search(); + } +} + void SearchDock::on_set() { dialogs::Search dlg(this, _session, _pattern); diff --git a/DSView/pv/dock/searchdock.h b/DSView/pv/dock/searchdock.h index 08e1fb40..c635c366 100644 --- a/DSView/pv/dock/searchdock.h +++ b/DSView/pv/dock/searchdock.h @@ -81,6 +81,7 @@ public slots: void on_previous(); void on_next(); void on_set(); + void on_progress_cancel(); private: SigSession *_session; @@ -91,6 +92,8 @@ public slots: QPushButton _nxt_button; widgets::FakeLineEdit* _search_value; QPushButton *_search_button; + bool _is_busy; + bool _is_cancel; }; } // namespace dock From 734e9935d2e5a01c432b99a4483706b976490125 Mon Sep 17 00:00:00 2001 From: dreamsource-tai Date: Mon, 29 Jul 2024 11:34:58 +0800 Subject: [PATCH 41/47] Updated the declaration regarding g_try_malloc(). --- libsigrokdecode4DSL/HACKING | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libsigrokdecode4DSL/HACKING b/libsigrokdecode4DSL/HACKING index 5dd8e2c1..d295ee52 100644 --- a/libsigrokdecode4DSL/HACKING +++ b/libsigrokdecode4DSL/HACKING @@ -41,8 +41,8 @@ Random notes - Generally avoid assigning values to variables at declaration time, especially so for complex and/or run-time dependent values. - - Consistently use g_*malloc() / g_*malloc0(). Do not use standard - g_try_malloc0()/calloc() if it can be avoided (sometimes other libs such + - Consistently use g_try_malloc0() / g_try_malloc(). Do not use standard + malloc() if it can be avoided (sometimes other libs such as libftdi can return g_try_malloc0()'d memory, for example). - Always properly match allocations with the proper *free() functions. If @@ -50,11 +50,11 @@ Random notes memory. Otherwise use standard g_free(). Never use the wrong function! - We assume that "small" memory allocations (< 1MB) will always succeed. - Thus, it's fine to use g_try_malloc0() or g_try_malloc0() for allocations of - simple/small structs and such (instead of using g_try_malloc0()), and + Thus, it's fine to use g_try_malloc0() or g_try_malloc() for allocations of + simple/small structs and such (instead of using malloc()), and there's no need to check the return value. - Do use g_try_malloc0() or g_try_malloc0() for large (>= 1MB) allocations + Do use g_try_malloc0() or g_try_malloc() for large (>= 1MB) allocations and check the return value. - You should never print any messages (neither to stdout nor stderr nor From e0976ae8e7ab98962ac82d1a6cd12c6cd5e5cb75 Mon Sep 17 00:00:00 2001 From: dreamsource-tai Date: Mon, 29 Jul 2024 16:41:01 +0800 Subject: [PATCH 42/47] write DSView tag at the csv file header --- libsigrok4DSL/output/csv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsigrok4DSL/output/csv.c b/libsigrok4DSL/output/csv.c index b1a20e5d..5e77c6ec 100644 --- a/libsigrok4DSL/output/csv.c +++ b/libsigrok4DSL/output/csv.c @@ -156,7 +156,7 @@ static GString *gen_header(const struct sr_output *o) /* Some metadata */ t = time(NULL); g_string_append_printf(header, "; CSV, generated by %s on %s\n", - PACKAGE_STRING, o->time_string); //ctime(&t) + "DSView", o->time_string); //ctime(&t) /* Columns / channels */ if (ctx->type == SR_CHANNEL_LOGIC) From 9aaebe56cf357cedce5fb7fa73105a1a27206a9c Mon Sep 17 00:00:00 2001 From: dreamsource-tai Date: Mon, 29 Jul 2024 17:10:23 +0800 Subject: [PATCH 43/47] get a right capture time for logic with loop mode --- DSView/pv/sigsession.cpp | 3 ++- DSView/pv/sigsession.h | 5 +++++ DSView/pv/toolbars/samplingbar.cpp | 2 ++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/DSView/pv/sigsession.cpp b/DSView/pv/sigsession.cpp index e6ed8cb7..1ad7cc42 100644 --- a/DSView/pv/sigsession.cpp +++ b/DSView/pv/sigsession.cpp @@ -104,6 +104,7 @@ namespace pv _is_triged = false; _dso_status_valid = false; _is_task_end = false; + _capture_work_time = 0; _data_list.push_back(new SessionData()); _data_list.push_back(new SessionData()); @@ -1476,7 +1477,7 @@ namespace pv if (mode == LOGIC){ auto logic_data = _capture_data->get_logic(); if (is_loop_mode() && logic_data->get_loop_offset() > 0){ - uint64_t milliseconds = logic_data->get_ring_sample_count() / 1000000; + uint64_t milliseconds = _capture_work_time / 1000000; QDateTime sessionTime = QDateTime::currentDateTime(); sessionTime = sessionTime.addMSecs(-milliseconds); set_session_time(sessionTime); diff --git a/DSView/pv/sigsession.h b/DSView/pv/sigsession.h index bfbba655..3f000e31 100644 --- a/DSView/pv/sigsession.h +++ b/DSView/pv/sigsession.h @@ -455,6 +455,10 @@ class SigSession: void ProcessPowerEvent(bool bEnterSleep); + inline void set_capture_work_time(uint64_t tm){ + _capture_work_time = tm; + } + private: void set_cur_samplelimits(uint64_t samplelimits); void set_cur_snap_samplerate(uint64_t samplerate); @@ -623,6 +627,7 @@ class SigSession: IDecoderPannel *_decoder_pannel; sr_status _dso_status; bool _dso_status_valid; + uint64_t _capture_work_time; private: // TODO: This should not be necessary. Multiple concurrent diff --git a/DSView/pv/toolbars/samplingbar.cpp b/DSView/pv/toolbars/samplingbar.cpp index 7b3cd6d5..d82a3b5b 100644 --- a/DSView/pv/toolbars/samplingbar.cpp +++ b/DSView/pv/toolbars/samplingbar.cpp @@ -792,6 +792,8 @@ namespace pv _sample_rate.currentIndex()) .value(); + _session->set_capture_work_time((uint64_t)sample_duration); + if (_device_agent->have_instance()) { if (sample_rate != _device_agent->get_sample_rate()) From 88058f992e3d1fb9cc22a90eda4f56e53f45b9de Mon Sep 17 00:00:00 2001 From: dreamsource-tai Date: Mon, 29 Jul 2024 17:57:58 +0800 Subject: [PATCH 44/47] CSV file head line --- libsigrok4DSL/output/csv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsigrok4DSL/output/csv.c b/libsigrok4DSL/output/csv.c index 5e77c6ec..0bff430b 100644 --- a/libsigrok4DSL/output/csv.c +++ b/libsigrok4DSL/output/csv.c @@ -155,8 +155,8 @@ static GString *gen_header(const struct sr_output *o) /* Some metadata */ t = time(NULL); - g_string_append_printf(header, "; CSV, generated by %s on %s\n", - "DSView", o->time_string); //ctime(&t) + g_string_append_printf(header, "; CSV, generated by DSView, sampled on %s\n", + o->time_string); //ctime(&t) /* Columns / channels */ if (ctx->type == SR_CHANNEL_LOGIC) From 3b027abe705de8048975b0024c1d299297229466 Mon Sep 17 00:00:00 2001 From: yunyaobaihong <896458252@qq.com> Date: Fri, 16 Aug 2024 17:08:55 +0800 Subject: [PATCH 45/47] Decoder Update : cjtag , onewire_link and sbus --- libsigrokdecode4DSL/decoders/cjtag/pd.py | 8 +++ .../decoders/onewire_link/pd.py | 54 +++++++++++++++---- .../decoders/sbus_futaba/pd.py | 6 +++ 3 files changed, 59 insertions(+), 9 deletions(-) diff --git a/libsigrokdecode4DSL/decoders/cjtag/pd.py b/libsigrokdecode4DSL/decoders/cjtag/pd.py index cd4dc4e5..218739aa 100644 --- a/libsigrokdecode4DSL/decoders/cjtag/pd.py +++ b/libsigrokdecode4DSL/decoders/cjtag/pd.py @@ -4,6 +4,7 @@ ## Copyright (C) 2012-2020 Uwe Hermann ## Copyright (C) 2019 Zhiyuan Wan ## Copyright (C) 2019 Kongou Hikari +## Copyright (C) 2024 DreamSourceLab ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -19,6 +20,11 @@ ## along with this program; if not, see . ## +## +## 2024/8/7 DreamSourceLab : Display data when zooming out +## 2024/8/16 DreamSourceLab : Added a filter to remove non-binary data +## + import sigrokdecode as srd from common.srdhelper import SrdStrEnum @@ -257,6 +263,7 @@ def handle_rising_tckc_edge(self, tdi, tdo, tck, tms): t = self.state.value[-2:] + ' TDI' b = ''.join(map(str, self.bits_tdi[1:])) + b = ''.join(filter(lambda x: x in '01', b)) h = ' (0x%x' % int('0b0' + b, 2) + ')' s = t + ': ' + b + h + ', ' + str(len(self.bits_tdi[1:])) + ' bits' self.putx_bs([30, [s]]) @@ -266,6 +273,7 @@ def handle_rising_tckc_edge(self, tdi, tdo, tck, tms): t = self.state.value[-2:] + ' TDO' b = ''.join(map(str, self.bits_tdo[1:])) + b = ''.join(filter(lambda x: x in '01', b)) h = ' (0x%x' % int('0b0' + b, 2) + ')' s = t + ': ' + b + h + ', ' + str(len(self.bits_tdo[1:])) + ' bits' self.putx_bs([31, [s]]) diff --git a/libsigrokdecode4DSL/decoders/onewire_link/pd.py b/libsigrokdecode4DSL/decoders/onewire_link/pd.py index b56e168c..42906f37 100644 --- a/libsigrokdecode4DSL/decoders/onewire_link/pd.py +++ b/libsigrokdecode4DSL/decoders/onewire_link/pd.py @@ -17,6 +17,10 @@ ## along with this program; if not, see . ## +## +## 2024/7/30 DreamSourceLab : Allow adjustment of data structure and pulse width timing for high and low levels +## + import sigrokdecode as srd class SamplerateError(Exception): @@ -60,11 +64,14 @@ class SamplerateError(Exception): True: 24.0, }, }, + #Frame 'SLOT': { + #Frame End 'min': { False: 60.0, True: 6.0, }, + #Frame Mid 'max': { False: 120.0, True: 16.0, @@ -77,10 +84,12 @@ class SamplerateError(Exception): }, }, 'LOWR': { + # if time < min , is too short 'min': { False: 1.0, True: 1.0, }, + # if time > max , bit = 1, else bit = 0 'max': { False: 15.0, True: 2.0, @@ -104,6 +113,12 @@ class Decoder(srd.Decoder): options = ( {'id': 'overdrive', 'desc': 'Start in overdrive speed', 'default': 'no', 'values': ('yes', 'no'), 'idn':'dec_onewire_link_opt_overdrive'}, + {'id': 'min height level pulse time', 'desc': 'min height level pulse time(us)', + 'default': 2.0, 'idn':'dec_onewire_link_opt_min_height_level_pulse_time'}, + {'id': 'min overdrive height level pulse time', 'desc': 'min overdrive height level pulse time(us)', + 'default': 15.0, 'idn':'dec_onewire_link_opt_min_overdrive_height_level_pulse_time'}, + {'id': 'data order', 'desc': 'data order', + 'default': 'bit first', 'values': ('bit first', 'space first'),'idn':'dec_can_opt_data_order'}, ) annotations = ( ('bit', 'Bit'), @@ -129,6 +144,7 @@ def reset(self): self.bit_count = -1 self.command = 0 self.overdrive = False + self.bit_first = True self.fall = 0 self.rise = 0 @@ -136,6 +152,10 @@ def start(self): self.out_python = self.register(srd.OUTPUT_PYTHON) self.out_ann = self.register(srd.OUTPUT_ANN) self.overdrive = (self.options['overdrive'] == 'yes') + self.bit_first = (self.options['data order'] == 'bit first') + timing['LOWR']['max'][False] = float(self.options['min height level pulse time']) + timing['LOWR']['max'][True] = float(self.options['min overdrive height level pulse time']) + self.fall = 0 self.rise = 0 self.bit_count = -1 @@ -188,6 +208,19 @@ def wait_falling_timeout(self, start, t): samples_to_skip = samples_to_skip if (samples_to_skip > 0) else 0 return self.wait([{0: 'f'}, {'skip': samples_to_skip}]) + def MinBitTimeOutput(self, time): + if time < timing['LOWR']['min'][self.overdrive]: + self.putfr([1, ['Low signal not long enough', + 'Low too short', + 'LOW < ' + str(timing['LOWR']['min'][self.overdrive])]]) + + def GetBitValue(self, time): + if time > timing['LOWR']['max'][self.overdrive]: + self.bit = 1 #Long pulse is a 1 bit. + else: + self.bit = 0 #Short pulse is a 0 bit. + + def decode(self): if not self.samplerate: raise SamplerateError('Cannot decode without samplerate.') @@ -237,16 +270,13 @@ def decode(self): # Overdrive reset pulse. self.putfr([2, ['Reset', 'Rst', 'R']]) self.state = 'PRESENCE DETECT HIGH' + #Frame elif time < timing['SLOT']['max'][self.overdrive]: - # Read/write time slot. - if time < timing['LOWR']['min'][self.overdrive]: - self.putfr([1, ['Low signal not long enough', - 'Low too short', - 'LOW < ' + str(timing['LOWR']['min'][self.overdrive])]]) - if time < timing['LOWR']['max'][self.overdrive]: - self.bit = 1 # Short pulse is a 1 bit. - else: - self.bit = 0 # Long pulse is a 0 bit. + if self.bit_first == True: + # Read/write time slot. + self.MinBitTimeOutput(time) + self.GetBitValue(time) + # Wait for end of slot. self.state = 'SLOT' else: @@ -305,6 +335,12 @@ def decode(self): self.state = 'LOW' else: # End of time slot. # Output bit. + if self.bit_first == False: + time = ((self.samplenum - self.rise) / self.samplerate) * 1000000.0 + # Read/write time slot. + self.MinBitTimeOutput(time) + self.GetBitValue(time) + self.putfs([0, ['Bit: %d' % self.bit, '%d' % self.bit]]) self.putpfs(['BIT', self.bit]) # Save command bits. diff --git a/libsigrokdecode4DSL/decoders/sbus_futaba/pd.py b/libsigrokdecode4DSL/decoders/sbus_futaba/pd.py index 75c2cfba..22963c6f 100644 --- a/libsigrokdecode4DSL/decoders/sbus_futaba/pd.py +++ b/libsigrokdecode4DSL/decoders/sbus_futaba/pd.py @@ -2,6 +2,7 @@ ## This file is part of the libsigrokdecode project. ## ## Copyright (C) 2022 Gerhard Sittig +## Copyright (C) 2024 DreamSourceLab ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -17,6 +18,10 @@ ## along with this program; if not, see . ## +## +## 2024/7/5 DreamSourceLab : Fixing the issue of decoding only the first frame +## + """ OUTPUT_PYTHON format: @@ -223,6 +228,7 @@ def flush_accum_bits(self): # spans all unprocessed data, and improves perception. if self.sent_fields >= upto: self.msg_complete = True + self.sent_fields = 0 if self.msg_complete and self.bits_accum: self.failed = ['Excess data bits', 'Excess'] From b430fba3d107cf8d9682ce965a07c74b4c16b416 Mon Sep 17 00:00:00 2001 From: dreamsource-tai Date: Tue, 5 Nov 2024 10:29:49 +0800 Subject: [PATCH 46/47] print the warning than the decoder direcotry not exists --- DSView/pv/config/appconfig.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/DSView/pv/config/appconfig.cpp b/DSView/pv/config/appconfig.cpp index 8f2b541c..8be9ad27 100644 --- a/DSView/pv/config/appconfig.cpp +++ b/DSView/pv/config/appconfig.cpp @@ -540,6 +540,7 @@ QString GetDecodeScriptDir() { return dir.absolutePath(); } + dsv_info("ERROR: the decoder directory is not exists! '../share/libsigrokdecode4DSL/decoders'"); return ""; } From 2e9e2c8e726df4ef5687d39b83d4f797cc44b574 Mon Sep 17 00:00:00 2001 From: dreamsource-tai Date: Tue, 5 Nov 2024 10:43:10 +0800 Subject: [PATCH 47/47] print the warning that the decoder direcotry not exists. --- DSView/pv/config/appconfig.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DSView/pv/config/appconfig.cpp b/DSView/pv/config/appconfig.cpp index 8be9ad27..1e318306 100644 --- a/DSView/pv/config/appconfig.cpp +++ b/DSView/pv/config/appconfig.cpp @@ -540,7 +540,7 @@ QString GetDecodeScriptDir() { return dir.absolutePath(); } - dsv_info("ERROR: the decoder directory is not exists! '../share/libsigrokdecode4DSL/decoders'"); + dsv_info("ERROR: the decoder directory is not exists: ../share/libsigrokdecode4DSL/decoders"); return ""; }