From db35ec2c7927b67590e673736ad18ea9d6e02fb6 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Wed, 26 Jun 2024 16:03:39 -0400 Subject: [PATCH 01/30] Initial connections tab UI redesign --- forms/connectionslistitem.ui | 92 ++++++ forms/mainwindow.ui | 465 +++++++++++-------------------- include/editor.h | 5 +- include/ui/connectionslistitem.h | 26 ++ porymap.pro | 3 + resources/icons/map_go.ico | Bin 0 -> 1993 bytes resources/images.qrc | 1 + src/editor.cpp | 95 +++---- src/mainwindow.cpp | 8 +- src/ui/connectionslistitem.cpp | 37 +++ 10 files changed, 365 insertions(+), 367 deletions(-) create mode 100644 forms/connectionslistitem.ui create mode 100644 include/ui/connectionslistitem.h create mode 100755 resources/icons/map_go.ico create mode 100644 src/ui/connectionslistitem.cpp diff --git a/forms/connectionslistitem.ui b/forms/connectionslistitem.ui new file mode 100644 index 000000000..f35c509ed --- /dev/null +++ b/forms/connectionslistitem.ui @@ -0,0 +1,92 @@ + + + ConnectionsListItem + + + + 0 + 0 + 176 + 153 + + + + + 0 + 0 + + + + + + + + 0 + 0 + + + + Map + + + + + + + + 0 + 0 + + + + Offset + + + + + + + + 0 + 0 + + + + Direction + + + + + + + ... + + + + :/icons/delete.ico:/icons/delete.ico + + + + + + + + + + + + + + + + + NoScrollComboBox + QComboBox +
noscrollcombobox.h
+
+
+ + + + +
diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui index a28f1db9c..02f1a690a 100644 --- a/forms/mainwindow.ui +++ b/forms/mainwindow.ui @@ -260,7 +260,7 @@ - 0 + 2 false @@ -769,8 +769,8 @@ 0 0 - 423 - 79 + 256 + 74 @@ -888,8 +888,8 @@ 0 0 - 423 - 79 + 256 + 74 @@ -990,10 +990,10 @@ - 8 + 0 0 - 411 - 446 + 98 + 74 @@ -1193,8 +1193,8 @@ 0 0 - 427 - 594 + 98 + 512 @@ -1413,8 +1413,8 @@ 0 0 - 382 - 699 + 98 + 444 @@ -1715,7 +1715,7 @@ 0 0 100 - 16 + 30 @@ -1809,7 +1809,7 @@ 0 0 100 - 16 + 30 @@ -1903,7 +1903,7 @@ 0 0 100 - 16 + 30 @@ -2003,7 +2003,7 @@ 0 0 100 - 16 + 30 @@ -2097,7 +2097,7 @@ 0 0 100 - 16 + 30 @@ -2541,7 +2541,7 @@ 0 - + 0 @@ -2554,24 +2554,9 @@ QFrame::Raised - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - + + + 0 @@ -2590,10 +2575,7 @@ QFrame::Raised - - - 4 - + 4 @@ -2606,64 +2588,11 @@ 4 - - - - - 0 - 0 - - - - <html><head/><body><p>Add a new connection.</p></body></html> - - - - - - - :/icons/add.ico - - - - - - - - <html><head/><body><p>Remove the currently-selected connection.</p></body></html> - - - - - - - :/icons/delete.ico - - - - - - - - Number of Connections: - - - - - - - - - - - - + + Qt::Horizontal - - QSizePolicy::Expanding - 40 @@ -2672,16 +2601,10 @@ - + - - - 0 - 0 - - - <html><head/><body><p>If enabled, connections will automatically be updated on the connected map.</p></body></html> + If enabled, connections will automatically be updated on the connected map. Mirror to Connecting Maps @@ -2691,237 +2614,179 @@ - - - - - - - - 0 - 0 - - - - false - - - false - - - Qt::ScrollBarAsNeeded - - - Qt::ScrollBarAsNeeded - - - QAbstractScrollArea::AdjustIgnored - - - QGraphicsView::NoDrag - - - QGraphicsView::AnchorUnderMouse - - - QGraphicsView::AnchorUnderMouse - - - - - - - - 0 - 0 - - - - - 0 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - 6 - - - 4 - - - 4 - - - 4 - - - 4 - - - + + - Map + Emerge Map - - + + + + Dive Map + + + + + - <html><head/><body><p>The destination map name of the connection.</p></body></html> + <html><head/><body><p>Destination map name when using <span style=" font-weight:600;">Dive</span>. If empty, no such connection will exist.</p></body></html> true - - - - Offset + + + + <html><head/><body><p>Destination map name when emerging using <span style=" font-weight:600;">Dive</span>. If empty, no such connection will exist.</p></body></html> + + + true - - + + - <html><head/><body><p>The number of metatiles to offset the connection.</p></body></html> + Open the selected Dive Map - - -999 + + ... - - 999 + + + :/icons/map_go.ico:/icons/map_go.ico - - + + - <html><head/><body><p>The direction of the connection.</p></body></html> + Open the selected Emerge Map - - - up - - - - - right - - - - - down - - - - - left - - - - - - - - Qt::Horizontal + + ... - - - 40 - 20 - + + + :/icons/map_go.ico:/icons/map_go.ico - + - - - - - 0 - 0 - - - - QFrame::StyledPanel - - - QFrame::Raised + + + + Qt::Horizontal - - - 4 + + + + 0 + 0 + - - 4 + + false - - 4 + + false - - 4 + + Qt::ScrollBarAsNeeded - - 4 + + Qt::ScrollBarAsNeeded - - - - Dive Map - - - - - - - <html><head/><body><p>Destination map name when using <span style=" font-weight:600;">Dive</span>. If empty, no such connection will exist.</p></body></html> - - - true - - - - - - - Emerge Map - - - - - - - <html><head/><body><p>Destination map name when emerging using <span style=" font-weight:600;">Dive</span>. If empty, no such connection will exist.</p></body></html> - - - true - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - + + QAbstractScrollArea::AdjustIgnored + + + QGraphicsView::NoDrag + + + QGraphicsView::AnchorUnderMouse + + + QGraphicsView::AnchorUnderMouse + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Add Connection + + + + :/icons/add.ico:/icons/add.ico + + + + + + + QFrame::NoFrame + + + true + + + + + 0 + 0 + 365 + 658 + + + + + 8 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + diff --git a/include/editor.h b/include/editor.h index f684b4919..e9588cae1 100644 --- a/include/editor.h +++ b/include/editor.h @@ -171,11 +171,10 @@ public slots: void setConnectionItemsVisible(bool); void setBorderItemsVisible(bool, qreal = 1); void setConnectionEditControlValues(MapConnection*); - void setConnectionEditControlsEnabled(bool); void setConnectionsEditable(bool); void createConnectionItem(MapConnection* connection); - void populateConnectionMapPickers(); - void setDiveEmergeControls(); + void populateConnectionsList(); + void addConnectionToList(const MapConnection * connection); void updateDiveEmergeMap(QString mapName, QString direction); void onConnectionOffsetChanged(int newOffset); void removeMirroredConnection(MapConnection*); diff --git a/include/ui/connectionslistitem.h b/include/ui/connectionslistitem.h new file mode 100644 index 000000000..0c4ee9239 --- /dev/null +++ b/include/ui/connectionslistitem.h @@ -0,0 +1,26 @@ +#ifndef CONNECTIONSLISTITEM_H +#define CONNECTIONSLISTITEM_H + +#include "mapconnection.h" + +#include + +namespace Ui { +class ConnectionsListItem; +} + +class ConnectionsListItem : public QFrame +{ + Q_OBJECT + +public: + explicit ConnectionsListItem(QWidget *parent, const QStringList &mapNames); + ~ConnectionsListItem(); + + void populate(const MapConnection * connection); + +public: + Ui::ConnectionsListItem *ui; +}; + +#endif // CONNECTIONSLISTITEM_H diff --git a/porymap.pro b/porymap.pro index dfc3306ee..5c898302f 100644 --- a/porymap.pro +++ b/porymap.pro @@ -46,6 +46,7 @@ SOURCES += src/core/block.cpp \ src/scriptapi/apiutility.cpp \ src/scriptapi/scripting.cpp \ src/ui/aboutporymap.cpp \ + src/ui/connectionslistitem.cpp \ src/ui/customscriptseditor.cpp \ src/ui/customscriptslistitem.cpp \ src/ui/draggablepixmapitem.cpp \ @@ -139,6 +140,7 @@ HEADERS += include/core/block.h \ include/lib/orderedmap.h \ include/lib/orderedjson.h \ include/ui/aboutporymap.h \ + include/ui/connectionslistitem.h \ include/ui/customscriptseditor.h \ include/ui/customscriptslistitem.h \ include/ui/draggablepixmapitem.h \ @@ -205,6 +207,7 @@ HEADERS += include/core/block.h \ include/ui/updatepromoter.h FORMS += forms/mainwindow.ui \ + forms/connectionslistitem.ui \ forms/prefabcreationdialog.ui \ forms/prefabframe.ui \ forms/tileseteditor.ui \ diff --git a/resources/icons/map_go.ico b/resources/icons/map_go.ico new file mode 100755 index 0000000000000000000000000000000000000000..8ca93206b6b0c8e9fbf149cc42c0667ff67fa908 GIT binary patch literal 1993 zcmV;)2R8VLP)R~7#5y)(1B_S&1o zc5KIq$%9luq7Mk7{AdaSS_Cnu{*eMd8Wa_wmMTOljYLr!tEE&?RkcVUM2ke4q<|Vw zRgt<;LI_C#wRI9`X$nekn#7N-z3WZusPQ=Zu9dYZRpUXLMQD}frNyN9|q-o=Gd}5 zu>bTW2)h=r9Y_zs)V_wNOK?$SY&=-PgG1*Puf?>}T^YIZnpyRIz~x29x)y}CqMQ>I z2Snv%$BCn7(82dN0DJ!hj9&m++W=1j_eFlrr+r*Xrtm=R6NsTeCp3f*7#nyWiRG)I zwO=+ZWOdEg8bvN|ZWs$4(-rTk5vUGZ+E5C}F9Vu-9Zba(EM-Fr!X+6sQKU0b+!7f^ zue$^hMnTfKBC(As6Rq&<)7E@HJe(ABGDFUE08kA3TR#MHtrkyWL2@eTAca%h*#zIl zL-ogC^W>hi0&9YsOWsR*6HH!DUo%m%)ZEmxFbzG6PGO}f&;C-M#lx99FgkD!jVo3|R5?&Ko@iS| z4)}10ppw~ZL!d->2*PltQ(@h&a|pK75=z@R?C-&tKSE&XH=U}N6ZmPOax4fBy;BEgAttCT0`5y*e9MQ@qE1DzZ?dVPG}2@R2Dy4 zdJ?S`ozQ$n3(StSxl{`wp&^QKRPqf!W>D0)W#qBE&7C%S`Vspe8TZ-2L9!K+@29a*9YvHmyf3qYk}InuoGKB5Rc+UHARu8Y9pH%_M_?o)(D$1J z8vm=|w%c$R@=TwPAc;xuqQ=HW*f10=(K~O!2 z>z>x~vobPI7R=TP;Tu_G^Hc}--3O8Hd4#yLkC;ec;@wUti|8^^5ywKzj^bkU1Q1yq z%($}%K{ey})@|FdqJ9{^I(!eKxnzDFC=*bZ+acvbWbTB2_C7X_M-aLBdE|$4NVNVF z7ysG?w<(2J&%T7?@3Cg+FcUQ^W`(@ruaLFqSicE>e&0Yj?nkorfBz;WJUBhS|EU+KDrV9>9sx3wY@V&ttT>KMd&1_RK&ibpzh} z;1Brf`g@?9y=Z)#!PtRKMm4P2U0egZp}H85=zA9Fi6R=l+yxcOk{`9iGr}y^k~K-L|>KYI5=Oz*X3G+_IKEIO6ii?4iY3(Lo@PW2>SIrw9AURfdXl;Z#F zf@}99zvfX^-V8jKV&eG}6xKuEW7*}ksqyh-5cjN?EOT#;$tJ2=vnUNXlldJ!`-xAQ z`wl)4vu4}3`@V|A8)9;LZrDLE z0)2zPks~;I>?v&Hl53R}P=4s|oqKP;8_(?Chq<;e#tSt5oo|=P(ANk2sb?cjJk|XW zSBM*OfdjQlPb9hy)VajjU*MOSX)+YGI$~|*0k#KyO;Y#%4|w&> zFQLEm1V0eEjVxX&*G|AF#wyOmxH^mhRMF&i~ z%AOj7*WrtFvH8&X`|B8|@y^i3SZMPK&RmaSqPj9X=m4i_9NgL3b3F%D05#!tcD8Xd b{x84)t}!rl^*H;f00000NkvXXu0mjfXHKz& literal 0 HcmV?d00001 diff --git a/resources/images.qrc b/resources/images.qrc index 86d56cb20..bdac1a474 100644 --- a/resources/images.qrc +++ b/resources/images.qrc @@ -65,5 +65,6 @@ images/Entities_16x16.png images/pokemon_icon_placeholder.png icons/clipboard.ico + icons/map_go.ico diff --git a/src/editor.cpp b/src/editor.cpp index 014fa489b..39e2718db 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -2,7 +2,7 @@ #include "draggablepixmapitem.h" #include "imageproviders.h" #include "log.h" -#include "mapconnection.h" +#include "connectionslistitem.h" #include "currentselectedmetatilespixmapitem.h" #include "mapsceneeventfilter.h" #include "metatile.h" @@ -178,11 +178,7 @@ void Editor::setEditingConnections() { map_item->paintingMode = MapPixmapItem::PaintMode::Disabled; map_item->draw(); map_item->setVisible(true); - populateConnectionMapPickers(); - ui->label_NumConnections->setText(QString::number(map->connections.length())); - setDiveEmergeControls(); - bool controlsEnabled = selected_connection_item != nullptr; - setConnectionEditControlsEnabled(controlsEnabled); + populateConnectionsList(); if (selected_connection_item) { onConnectionOffsetChanged(selected_connection_item->connection->offset); setConnectionMap(selected_connection_item->connection->map_name); @@ -739,11 +735,18 @@ void Editor::updateEncounterFields(EncounterFields newFields) { project->wildMonFields = newFields; } -void Editor::setDiveEmergeControls() { - ui->comboBox_DiveMap->blockSignals(true); - ui->comboBox_EmergeMap->blockSignals(true); +void Editor::populateConnectionsList() { + const QSignalBlocker blocker1(ui->comboBox_DiveMap); + const QSignalBlocker blocker2(ui->comboBox_EmergeMap); + + ui->comboBox_DiveMap->clear(); + ui->comboBox_DiveMap->addItems(project->mapNames); ui->comboBox_DiveMap->setCurrentText(""); + + ui->comboBox_EmergeMap->clear(); + ui->comboBox_EmergeMap->addItems(project->mapNames); ui->comboBox_EmergeMap->setCurrentText(""); + for (MapConnection* connection : map->connections) { if (connection->direction == "dive") { ui->comboBox_DiveMap->setCurrentText(connection->map_name); @@ -751,25 +754,20 @@ void Editor::setDiveEmergeControls() { ui->comboBox_EmergeMap->setCurrentText(connection->map_name); } } - ui->comboBox_DiveMap->blockSignals(false); - ui->comboBox_EmergeMap->blockSignals(false); -} -void Editor::populateConnectionMapPickers() { - ui->comboBox_ConnectedMap->blockSignals(true); - ui->comboBox_DiveMap->blockSignals(true); - ui->comboBox_EmergeMap->blockSignals(true); + // Clear any existing connections in list + for (auto w : ui->scrollAreaContents_ConnectionsList->findChildren()) + w->deleteLater(); - ui->comboBox_ConnectedMap->clear(); - ui->comboBox_ConnectedMap->addItems(project->mapNames); - ui->comboBox_DiveMap->clear(); - ui->comboBox_DiveMap->addItems(project->mapNames); - ui->comboBox_EmergeMap->clear(); - ui->comboBox_EmergeMap->addItems(project->mapNames); + for (auto item :connection_items) + addConnectionToList(item->connection); +} - ui->comboBox_ConnectedMap->blockSignals(false); - ui->comboBox_DiveMap->blockSignals(true); - ui->comboBox_EmergeMap->blockSignals(true); +// TODO: Vertical scrolling +void Editor::addConnectionToList(const MapConnection * connection) { + ConnectionsListItem *listItem = new ConnectionsListItem(ui->scrollAreaContents_ConnectionsList, project->mapNames); + listItem->populate(connection); + ui->layout_ConnectionsList->insertWidget(ui->layout_ConnectionsList->count() - 1, listItem); // Insert above the vertical spacer } void Editor::setConnectionItemsVisible(bool visible) { @@ -848,38 +846,15 @@ void Editor::onConnectionMoved(MapConnection* connection) { } void Editor::onConnectionOffsetChanged(int newOffset) { - ui->spinBox_ConnectionOffset->blockSignals(true); + // Connections TODO: Change offset spin box for selected connection + /*ui->spinBox_ConnectionOffset->blockSignals(true); ui->spinBox_ConnectionOffset->setValue(newOffset); ui->spinBox_ConnectionOffset->blockSignals(false); - + */ } void Editor::setConnectionEditControlValues(MapConnection* connection) { - QString mapName = connection ? connection->map_name : ""; - QString direction = connection ? connection->direction : ""; - int offset = connection ? connection->offset : 0; - - ui->comboBox_ConnectedMap->blockSignals(true); - ui->comboBox_ConnectionDirection->blockSignals(true); - ui->spinBox_ConnectionOffset->blockSignals(true); - - ui->comboBox_ConnectedMap->setCurrentText(mapName); - ui->comboBox_ConnectionDirection->setCurrentText(direction); - ui->spinBox_ConnectionOffset->setValue(offset); - - ui->comboBox_ConnectedMap->blockSignals(false); - ui->comboBox_ConnectionDirection->blockSignals(false); - ui->spinBox_ConnectionOffset->blockSignals(false); -} - -void Editor::setConnectionEditControlsEnabled(bool enabled) { - ui->comboBox_ConnectionDirection->setEnabled(enabled); - ui->comboBox_ConnectedMap->setEnabled(enabled); - ui->spinBox_ConnectionOffset->setEnabled(enabled); - - if (!enabled) { - setConnectionEditControlValues(nullptr); - } + // Connections TODO: Highlight selected connection } void Editor::setConnectionsEditable(bool editable) { @@ -896,10 +871,11 @@ void Editor::onConnectionItemSelected(ConnectionPixmapItem* connectionItem) { selected_connection_item = connectionItem; for (ConnectionPixmapItem* item : connection_items) item->updateHighlight(item == selected_connection_item); - setConnectionEditControlsEnabled(true); setConnectionEditControlValues(selected_connection_item->connection); + /* // Connections TODO: ui->spinBox_ConnectionOffset->setMaximum(selected_connection_item->getMaxOffset()); ui->spinBox_ConnectionOffset->setMinimum(selected_connection_item->getMinOffset()); + */ onConnectionOffsetChanged(selected_connection_item->connection->offset); } @@ -918,9 +894,11 @@ void Editor::onConnectionItemDoubleClicked(ConnectionPixmapItem* connectionItem) } void Editor::onConnectionDirectionChanged(QString newDirection) { + /* // Connections TODO: ui->comboBox_ConnectionDirection->blockSignals(true); ui->comboBox_ConnectionDirection->setCurrentText(newDirection); ui->comboBox_ConnectionDirection->blockSignals(false); + */ } void Editor::onBorderMetatilesChanged() { @@ -1746,13 +1724,12 @@ void Editor::setConnectionMap(QString mapName) { } QString originalMapName = selected_connection_item->connection->map_name; - setConnectionEditControlsEnabled(true); selected_connection_item->connection->map_name = mapName; setCurrentConnectionDirection(selected_connection_item->connection->direction); // New map may have a different minimum offset than the last one. The maximum will be the same. int min = selected_connection_item->getMinOffset(); - ui->spinBox_ConnectionOffset->setMinimum(min); + //ui->spinBox_ConnectionOffset->setMinimum(min); // Connections TODO: onConnectionOffsetChanged(qMax(min, selected_connection_item->connection->offset)); updateMirroredConnectionMap(selected_connection_item->connection, originalMapName); @@ -1786,8 +1763,8 @@ void Editor::addNewConnection() { newConnection->map_name = defaultMapName; map->connections.append(newConnection); createConnectionItem(newConnection); + addConnectionToList(newConnection); onConnectionItemSelected(connection_items.last()); - ui->label_NumConnections->setText(QString::number(map->connections.length())); updateMirroredConnection(newConnection, newConnection->direction, newConnection->map_name); } @@ -1867,9 +1844,7 @@ void Editor::removeCurrentConnection() { } selected_connection_item = nullptr; - setConnectionEditControlsEnabled(false); - ui->spinBox_ConnectionOffset->setValue(0); - ui->label_NumConnections->setText(QString::number(map->connections.length())); + //ui->spinBox_ConnectionOffset->setValue(0); // Connections TODO: if (connection_items.length() > 0) { onConnectionItemSelected(connection_items.last()); @@ -1918,8 +1893,6 @@ void Editor::updateDiveEmergeMap(QString mapName, QString direction) { updateMirroredConnectionMap(connection, originalMapName); } } - - ui->label_NumConnections->setText(QString::number(map->connections.length())); } void Editor::updatePrimaryTileset(QString tilesetLabel, bool forceLoad) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 98b602eef..814e60fa0 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2546,18 +2546,19 @@ void MainWindow::showExportMapImageWindow(ImageExporterMode mode) { openSubWindow(this->mapImageExporter); } +// TODO: Move responsibility to list item void MainWindow::on_comboBox_ConnectionDirection_currentTextChanged(const QString &direction) { editor->updateCurrentConnectionDirection(direction); markMapEdited(); } - +// TODO: Move responsibility to list item void MainWindow::on_spinBox_ConnectionOffset_valueChanged(int offset) { editor->updateConnectionOffset(offset); markMapEdited(); } - +// TODO: Move responsibility to list item void MainWindow::on_comboBox_ConnectedMap_currentTextChanged(const QString &mapName) { if (mapName.isEmpty() || editor->project->mapNames.contains(mapName)) { @@ -2568,10 +2569,11 @@ void MainWindow::on_comboBox_ConnectedMap_currentTextChanged(const QString &mapN void MainWindow::on_pushButton_AddConnection_clicked() { + // TODO: Bring up a prompt for information. Mark the current map *AND* the connected map as edited editor->addNewConnection(); markMapEdited(); } - +// TODO: Move responsibility to list item void MainWindow::on_pushButton_RemoveConnection_clicked() { editor->removeCurrentConnection(); diff --git a/src/ui/connectionslistitem.cpp b/src/ui/connectionslistitem.cpp new file mode 100644 index 000000000..47589a120 --- /dev/null +++ b/src/ui/connectionslistitem.cpp @@ -0,0 +1,37 @@ +#include "connectionslistitem.h" +#include "ui_connectionslistitem.h" + +static const QStringList directions = {"up", "down", "left", "right"}; + +ConnectionsListItem::ConnectionsListItem(QWidget *parent, const QStringList &mapNames) : + QFrame(parent), + ui(new Ui::ConnectionsListItem) +{ + ui->setupUi(this); + + const QSignalBlocker blocker1(ui->comboBox_Direction); + const QSignalBlocker blocker2(ui->comboBox_Map); + const QSignalBlocker blocker3(ui->spinBox_Offset); + + ui->comboBox_Direction->setEditable(false); + ui->comboBox_Direction->setMinimumContentsLength(0); + ui->comboBox_Direction->addItems(directions); + + ui->comboBox_Map->setMinimumContentsLength(6); + ui->comboBox_Map->addItems(mapNames); +} + +void ConnectionsListItem::populate(const MapConnection * connection) { + const QSignalBlocker blocker1(ui->comboBox_Direction); + const QSignalBlocker blocker2(ui->comboBox_Map); + const QSignalBlocker blocker3(ui->spinBox_Offset); + + ui->comboBox_Direction->setTextItem(connection->direction); + ui->comboBox_Map->setTextItem(connection->map_name); + ui->spinBox_Offset->setValue(connection->offset); +} + +ConnectionsListItem::~ConnectionsListItem() +{ + delete ui; +} From 391285aee89e211fb05426701f8833822a79e74e Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 28 Jun 2024 22:01:13 -0400 Subject: [PATCH 02/30] Add buttons to open Dive/Emerge maps --- forms/mainwindow.ui | 86 ++++++++++++++++++++++---------------------- include/mainwindow.h | 3 ++ include/project.h | 1 + src/editor.cpp | 2 +- src/mainwindow.cpp | 71 ++++++++++++++++++------------------ src/project.cpp | 4 +++ 6 files changed, 88 insertions(+), 79 deletions(-) diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui index 02f1a690a..75ceeb2ec 100644 --- a/forms/mainwindow.ui +++ b/forms/mainwindow.ui @@ -992,7 +992,7 @@ 0 0 - 98 + 91 74 @@ -1193,7 +1193,7 @@ 0 0 - 98 + 91 512 @@ -1413,8 +1413,8 @@ 0 0 - 98 - 444 + 93 + 460 @@ -1715,7 +1715,7 @@ 0 0 100 - 30 + 16 @@ -1809,7 +1809,7 @@ 0 0 100 - 30 + 16 @@ -1903,7 +1903,7 @@ 0 0 100 - 30 + 16 @@ -2003,7 +2003,7 @@ 0 0 100 - 30 + 16 @@ -2097,7 +2097,7 @@ 0 0 100 - 30 + 16 @@ -2588,7 +2588,7 @@ 4 - + Qt::Horizontal @@ -2601,7 +2601,7 @@ - + If enabled, connections will automatically be updated on the connected map. @@ -2614,21 +2614,49 @@ - + + + + Open the selected Dive Map + + + ... + + + + :/icons/map_go.ico:/icons/map_go.ico + + + + + + + Open the selected Emerge Map + + + ... + + + + :/icons/map_go.ico:/icons/map_go.ico + + + + Emerge Map - + Dive Map - + <html><head/><body><p>Destination map name when using <span style=" font-weight:600;">Dive</span>. If empty, no such connection will exist.</p></body></html> @@ -2638,7 +2666,7 @@ - + <html><head/><body><p>Destination map name when emerging using <span style=" font-weight:600;">Dive</span>. If empty, no such connection will exist.</p></body></html> @@ -2648,34 +2676,6 @@ - - - - Open the selected Dive Map - - - ... - - - - :/icons/map_go.ico:/icons/map_go.ico - - - - - - - Open the selected Emerge Map - - - ... - - - - :/icons/map_go.ico:/icons/map_go.ico - - - diff --git a/include/mainwindow.h b/include/mainwindow.h index 7fda1b09e..6bcef815c 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -248,6 +248,8 @@ private slots: void on_comboBox_ConnectedMap_currentTextChanged(const QString &mapName); void on_pushButton_AddConnection_clicked(); void on_pushButton_RemoveConnection_clicked(); + void on_button_OpenDiveMap_clicked(); + void on_button_OpenEmergeMap_clicked(); void on_comboBox_DiveMap_currentTextChanged(const QString &mapName); void on_comboBox_EmergeMap_currentTextChanged(const QString &mapName); void on_comboBox_PrimaryTileset_currentTextChanged(const QString &arg1); @@ -342,6 +344,7 @@ private slots: bool tilesetNeedsRedraw = false; + bool userSetMap(QString, bool scrollTreeView = false); bool setMap(QString, bool scrollTreeView = false); void redrawMapScene(); void refreshMapScene(); diff --git a/include/project.h b/include/project.h index 643f74da0..49c0aaa8a 100644 --- a/include/project.h +++ b/include/project.h @@ -119,6 +119,7 @@ class Project : public QObject bool readMapGroups(); Map* addNewMapToGroup(QString, int, Map*, bool, bool); QString getNewMapName(); + bool isExistingMapName(const QString&); QString getProjectTitle(); QString readMapLayoutId(QString map_name); diff --git a/src/editor.cpp b/src/editor.cpp index 39e2718db..ee314c194 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -763,7 +763,7 @@ void Editor::populateConnectionsList() { addConnectionToList(item->connection); } -// TODO: Vertical scrolling +// TODO: Don't allow splitter resizing to shrink list items to the point where horizontal scroll is needed void Editor::addConnectionToList(const MapConnection * connection) { ConnectionsListItem *listItem = new ConnectionsListItem(ui->scrollAreaContents_ConnectionsList, project->mapNames); listItem->populate(connection); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 814e60fa0..20a489909 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -718,6 +718,21 @@ void MainWindow::on_action_Reload_Project_triggered() { openProject(editor->project->root); } +// setMap, but with a visible error message in case of failure. +// Use when the user is specifically requesting a map to open. +bool MainWindow::userSetMap(QString map_name, bool scrollTreeView) { + if (!setMap(map_name, scrollTreeView)) { + QMessageBox msgBox(this); + QString errorMsg = QString("There was an error opening map %1. Please see %2 for full error details.\n\n%3") + .arg(map_name) + .arg(getLogPath()) + .arg(getMostRecentError()); + msgBox.critical(nullptr, "Error Opening Map", errorMsg); + return false; + } + return true; +} + bool MainWindow::setMap(QString map_name, bool scrollTreeView) { logInfo(QString("Setting map to '%1'").arg(map_name)); if (map_name.isEmpty()) { @@ -810,15 +825,8 @@ void MainWindow::openWarpMap(QString map_name, int event_id, Event::Group event_ } // Open the destination map. - if (!setMap(map_name, true)) { - QMessageBox msgBox(this); - QString errorMsg = QString("There was an error opening map %1. Please see %2 for full error details.\n\n%3") - .arg(map_name) - .arg(getLogPath()) - .arg(getMostRecentError()); - msgBox.critical(nullptr, "Error Opening Map", errorMsg); + if (!userSetMap(map_name, true)) return; - } // Select the target event. int index = event_id - Event::getIndexOffset(event_group); @@ -1468,17 +1476,8 @@ void MainWindow::currentMetatilesSelectionChanged() { void MainWindow::on_mapList_activated(const QModelIndex &index) { QVariant data = index.data(Qt::UserRole); - if (index.data(MapListUserRoles::TypeRole) == "map_name" && !data.isNull()) { - QString mapName = data.toString(); - if (!setMap(mapName)) { - QMessageBox msgBox(this); - QString errorMsg = QString("There was an error opening map %1. Please see %2 for full error details.\n\n%3") - .arg(mapName) - .arg(getLogPath()) - .arg(getMostRecentError()); - msgBox.critical(nullptr, "Error Opening Map", errorMsg); - } - } + if (index.data(MapListUserRoles::TypeRole) == "map_name" && !data.isNull()) + userSetMap(data.toString()); } void MainWindow::drawMapListIcons(QAbstractItemModel *model) { @@ -2421,16 +2420,8 @@ void MainWindow::clickToolButtonFromEditMode(QString editMode) { } void MainWindow::onLoadMapRequested(QString mapName, QString fromMapName) { - if (!setMap(mapName, true)) { - QMessageBox msgBox(this); - QString errorMsg = QString("There was an error opening map %1. Please see %2 for full error details.\n\n%3") - .arg(mapName) - .arg(getLogPath()) - .arg(getMostRecentError()); - msgBox.critical(nullptr, "Error Opening Map", errorMsg); - return; - } - editor->setSelectedConnectionFromMap(fromMapName); + if (userSetMap(mapName, true)) + editor->setSelectedConnectionFromMap(fromMapName); } void MainWindow::onMapChanged(Map *) { @@ -2592,17 +2583,27 @@ void MainWindow::on_pushButton_ConfigureEncountersJSON_clicked() { editor->configureEncounterJSON(this); } -void MainWindow::on_comboBox_DiveMap_currentTextChanged(const QString &mapName) -{ - if (mapName.isEmpty() || editor->project->mapNames.contains(mapName)) { +void MainWindow::on_button_OpenDiveMap_clicked() { + const QString mapName = ui->comboBox_DiveMap->currentText(); + if (editor->project->isExistingMapName(mapName)) + userSetMap(mapName, true); +} + +void MainWindow::on_button_OpenEmergeMap_clicked() { + const QString mapName = ui->comboBox_EmergeMap->currentText(); + if (editor->project->isExistingMapName(mapName)) + userSetMap(mapName, true); +} + +void MainWindow::on_comboBox_DiveMap_currentTextChanged(const QString &mapName) { + if (editor->project->isExistingMapName(mapName)) { editor->updateDiveMap(mapName); markMapEdited(); } } -void MainWindow::on_comboBox_EmergeMap_currentTextChanged(const QString &mapName) -{ - if (mapName.isEmpty() || editor->project->mapNames.contains(mapName)) { +void MainWindow::on_comboBox_EmergeMap_currentTextChanged(const QString &mapName) { + if (editor->project->isExistingMapName(mapName)) { editor->updateEmergeMap(mapName); markMapEdited(); } diff --git a/src/project.cpp b/src/project.cpp index c6550c6ad..c1c8f5c7d 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -1800,6 +1800,10 @@ QString Project::getNewMapName() { return newMapName; } +bool Project::isExistingMapName(const QString &mapName) { + return !mapName.isEmpty() && mapName != DYNAMIC_MAP_NAME && this->mapNames.contains(mapName); +} + Project::DataQualifiers Project::getDataQualifiers(QString text, QString label) { Project::DataQualifiers qualifiers; From 2fa3a9b3982d7ba89caf48f66566c90f208e2bfe Mon Sep 17 00:00:00 2001 From: GriffinR Date: Mon, 1 Jul 2024 13:58:58 -0400 Subject: [PATCH 03/30] Connection reorganization --- include/editor.h | 5 +- include/mainwindow.h | 4 - include/ui/connectionslistitem.h | 6 ++ src/editor.cpp | 167 +++++++++++++------------------ src/mainwindow.cpp | 28 +----- src/ui/connectionslistitem.cpp | 41 ++++++++ 6 files changed, 119 insertions(+), 132 deletions(-) diff --git a/include/editor.h b/include/editor.h index e9588cae1..37f60b6ae 100644 --- a/include/editor.h +++ b/include/editor.h @@ -74,11 +74,8 @@ class Editor : public QObject void setEditingObjects(); void setEditingConnections(); void setMapEditingButtonsEnabled(bool enabled); - void setCurrentConnectionDirection(QString curDirection); - void updateCurrentConnectionDirection(QString curDirection); void setConnectionsVisibility(bool visible); void updateConnectionOffset(int offset); - void setConnectionMap(QString mapName); void addNewConnection(); void removeCurrentConnection(); void addNewWildMonGroup(QWidget *window); @@ -170,8 +167,8 @@ public slots: void setConnectionItemsVisible(bool); void setBorderItemsVisible(bool, qreal = 1); - void setConnectionEditControlValues(MapConnection*); void setConnectionsEditable(bool); + void redrawConnection(ConnectionPixmapItem* connectionItem); void createConnectionItem(MapConnection* connection); void populateConnectionsList(); void addConnectionToList(const MapConnection * connection); diff --git a/include/mainwindow.h b/include/mainwindow.h index 6bcef815c..51bfecc32 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -243,11 +243,7 @@ private slots: void on_actionExport_Map_Timelapse_Image_triggered(); void on_actionImport_Map_from_Advance_Map_1_92_triggered(); - void on_comboBox_ConnectionDirection_currentTextChanged(const QString &arg1); - void on_spinBox_ConnectionOffset_valueChanged(int offset); - void on_comboBox_ConnectedMap_currentTextChanged(const QString &mapName); void on_pushButton_AddConnection_clicked(); - void on_pushButton_RemoveConnection_clicked(); void on_button_OpenDiveMap_clicked(); void on_button_OpenEmergeMap_clicked(); void on_comboBox_DiveMap_currentTextChanged(const QString &mapName); diff --git a/include/ui/connectionslistitem.h b/include/ui/connectionslistitem.h index 0c4ee9239..a9dab7ca4 100644 --- a/include/ui/connectionslistitem.h +++ b/include/ui/connectionslistitem.h @@ -21,6 +21,12 @@ class ConnectionsListItem : public QFrame public: Ui::ConnectionsListItem *ui; + +private slots: + void on_comboBox_Direction_currentTextChanged(const QString &direction); + void on_comboBox_Map_currentTextChanged(const QString &mapName); + void on_spinBox_Offset_valueChanged(int offset); + void on_button_Delete_clicked(); }; #endif // CONNECTIONSLISTITEM_H diff --git a/src/editor.cpp b/src/editor.cpp index ee314c194..ec3e7f0ba 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -180,9 +180,8 @@ void Editor::setEditingConnections() { map_item->setVisible(true); populateConnectionsList(); if (selected_connection_item) { - onConnectionOffsetChanged(selected_connection_item->connection->offset); - setConnectionMap(selected_connection_item->connection->map_name); - setCurrentConnectionDirection(selected_connection_item->connection->direction); + // TODO: Do we need additional handling here again + redrawConnection(selected_connection_item); } maskNonVisibleConnectionTiles(); } @@ -784,77 +783,99 @@ void Editor::setBorderItemsVisible(bool visible, qreal opacity) { } } -void Editor::setCurrentConnectionDirection(QString curDirection) { - if (!selected_connection_item) +void Editor::redrawConnection(ConnectionPixmapItem* connectionItem) { + if (!connectionItem || !connectionItem->connection) return; - Map *connected_map = project->getMap(selected_connection_item->connection->map_name); - if (!connected_map) { + + const QString mapName = connectionItem->connection->map_name; + if (mapName.isEmpty()) + return; + + // TODO: What happens if a connection is saved with an empty name + if (mapName == DYNAMIC_MAP_NAME || !project->mapNames.contains(mapName)) { + logError(QString("Invalid map name '%1' specified for connection.").arg(mapName)); return; } - selected_connection_item->connection->direction = curDirection; + Map *connectedMap = project->getMap(mapName); + if (!connectedMap) + return; + + QPixmap pixmap = connectedMap->renderConnection(*connectionItem->connection, map->layout); - QPixmap pixmap = connected_map->renderConnection(*selected_connection_item->connection, map->layout); - int offset = selected_connection_item->connection->offset; - selected_connection_item->initialOffset = offset; + int offset = connectionItem->connection->offset; + connectionItem->initialOffset = offset; int x = 0, y = 0; - if (selected_connection_item->connection->direction == "up") { + if (connectionItem->connection->direction == "up") { x = offset * 16; y = -pixmap.height(); - } else if (selected_connection_item->connection->direction == "down") { + } else if (connectionItem->connection->direction == "down") { x = offset * 16; y = map->getHeight() * 16; - } else if (selected_connection_item->connection->direction == "left") { + } else if (connectionItem->connection->direction == "left") { x = -pixmap.width(); y = offset * 16; - } else if (selected_connection_item->connection->direction == "right") { + } else if (connectionItem->connection->direction == "right") { x = map->getWidth() * 16; y = offset * 16; } - selected_connection_item->basePixmap = pixmap; - QPainter painter(&pixmap); - painter.setPen(QColor(255, 0, 255)); - painter.drawRect(0, 0, pixmap.width() - 1, pixmap.height() - 1); - painter.end(); - selected_connection_item->setPixmap(pixmap); - selected_connection_item->initialX = x; - selected_connection_item->initialY = y; - selected_connection_item->blockSignals(true); - selected_connection_item->setX(x); - selected_connection_item->setY(y); - selected_connection_item->setZValue(-1); - selected_connection_item->blockSignals(false); + connectionItem->basePixmap = pixmap; - setConnectionEditControlValues(selected_connection_item->connection); + // TODO: Make sure offset limiting is correct (and updated) + // New map may have a different minimum offset than the last one. The maximum will be the same. + /*int min = selected_connection_item->getMinOffset(); + //ui->spinBox_ConnectionOffset->setMinimum(min); // Connections TODO: + onConnectionOffsetChanged(qMax(min, selected_connection_item->connection->offset));*/ + + if (connectionItem == selected_connection_item) { + QPainter painter(&pixmap); + painter.setPen(QColor(255, 0, 255)); + painter.drawRect(0, 0, pixmap.width() - 1, pixmap.height() - 1); + painter.end(); + } + connectionItem->setPixmap(pixmap); + connectionItem->initialX = x; + connectionItem->initialY = y; + connectionItem->blockSignals(true); + connectionItem->setX(x); + connectionItem->setY(y); + connectionItem->setZValue(-1); + connectionItem->blockSignals(false); + + // TODO: + //updateMirroredConnectionMap(selected_connection_item->connection, originalMapName); + + maskNonVisibleConnectionTiles(); } -void Editor::updateCurrentConnectionDirection(QString curDirection) { +// TODO: Generalize +void Editor::updateConnectionOffset(int offset) { if (!selected_connection_item) return; - QString originalDirection = selected_connection_item->connection->direction; - setCurrentConnectionDirection(curDirection); - updateMirroredConnectionDirection(selected_connection_item->connection, originalDirection); + selected_connection_item->blockSignals(true); + offset = qMin(offset, selected_connection_item->getMaxOffset()); + offset = qMax(offset, selected_connection_item->getMinOffset()); + selected_connection_item->connection->offset = offset; + if (selected_connection_item->connection->direction == "up" || selected_connection_item->connection->direction == "down") { + selected_connection_item->setX(selected_connection_item->initialX + (offset - selected_connection_item->initialOffset) * 16); + } else if (selected_connection_item->connection->direction == "left" || selected_connection_item->connection->direction == "right") { + selected_connection_item->setY(selected_connection_item->initialY + (offset - selected_connection_item->initialOffset) * 16); + } + selected_connection_item->blockSignals(false); + updateMirroredConnectionOffset(selected_connection_item->connection); maskNonVisibleConnectionTiles(); } void Editor::onConnectionMoved(MapConnection* connection) { - updateMirroredConnectionOffset(connection); - onConnectionOffsetChanged(connection->offset); - maskNonVisibleConnectionTiles(); -} - -void Editor::onConnectionOffsetChanged(int newOffset) { - // Connections TODO: Change offset spin box for selected connection - /*ui->spinBox_ConnectionOffset->blockSignals(true); - ui->spinBox_ConnectionOffset->setValue(newOffset); - ui->spinBox_ConnectionOffset->blockSignals(false); - */ -} + // TODO: + //updateMirroredConnectionOffset(connection); + + // TODO: Sync change to correct offset spin box -void Editor::setConnectionEditControlValues(MapConnection* connection) { - // Connections TODO: Highlight selected connection + // TODO: This is likely the source of the visual masking bug while dragging (this happens after the move) + maskNonVisibleConnectionTiles(); } void Editor::setConnectionsEditable(bool editable) { @@ -871,12 +892,8 @@ void Editor::onConnectionItemSelected(ConnectionPixmapItem* connectionItem) { selected_connection_item = connectionItem; for (ConnectionPixmapItem* item : connection_items) item->updateHighlight(item == selected_connection_item); - setConnectionEditControlValues(selected_connection_item->connection); - /* // Connections TODO: - ui->spinBox_ConnectionOffset->setMaximum(selected_connection_item->getMaxOffset()); - ui->spinBox_ConnectionOffset->setMinimum(selected_connection_item->getMinOffset()); - */ - onConnectionOffsetChanged(selected_connection_item->connection->offset); + + // TODO: Handle the highlight done in redrawConnection? } void Editor::setSelectedConnectionFromMap(QString mapName) { @@ -1692,50 +1709,6 @@ void Editor::displayMapGrid() { connect(ui->checkBox_ToggleGrid, &QCheckBox::toggled, this, &Editor::onToggleGridClicked); } -void Editor::updateConnectionOffset(int offset) { - if (!selected_connection_item) - return; - - selected_connection_item->blockSignals(true); - offset = qMin(offset, selected_connection_item->getMaxOffset()); - offset = qMax(offset, selected_connection_item->getMinOffset()); - selected_connection_item->connection->offset = offset; - if (selected_connection_item->connection->direction == "up" || selected_connection_item->connection->direction == "down") { - selected_connection_item->setX(selected_connection_item->initialX + (offset - selected_connection_item->initialOffset) * 16); - } else if (selected_connection_item->connection->direction == "left" || selected_connection_item->connection->direction == "right") { - selected_connection_item->setY(selected_connection_item->initialY + (offset - selected_connection_item->initialOffset) * 16); - } - selected_connection_item->blockSignals(false); - updateMirroredConnectionOffset(selected_connection_item->connection); - maskNonVisibleConnectionTiles(); -} - -void Editor::setConnectionMap(QString mapName) { - if (!mapName.isEmpty() && !project->mapNames.contains(mapName)) { - logError(QString("Invalid map name '%1' specified for connection.").arg(mapName)); - return; - } - if (!selected_connection_item) - return; - - if (mapName.isEmpty() || mapName == DYNAMIC_MAP_NAME) { - removeCurrentConnection(); - return; - } - - QString originalMapName = selected_connection_item->connection->map_name; - selected_connection_item->connection->map_name = mapName; - setCurrentConnectionDirection(selected_connection_item->connection->direction); - - // New map may have a different minimum offset than the last one. The maximum will be the same. - int min = selected_connection_item->getMinOffset(); - //ui->spinBox_ConnectionOffset->setMinimum(min); // Connections TODO: - onConnectionOffsetChanged(qMax(min, selected_connection_item->connection->offset)); - - updateMirroredConnectionMap(selected_connection_item->connection, originalMapName); - maskNonVisibleConnectionTiles(); -} - void Editor::addNewConnection() { // Find direction with least number of connections. QMap directionCounts = QMap({{"up", 0}, {"right", 0}, {"down", 0}, {"left", 0}}); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 20a489909..c51427991 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2537,39 +2537,12 @@ void MainWindow::showExportMapImageWindow(ImageExporterMode mode) { openSubWindow(this->mapImageExporter); } -// TODO: Move responsibility to list item -void MainWindow::on_comboBox_ConnectionDirection_currentTextChanged(const QString &direction) -{ - editor->updateCurrentConnectionDirection(direction); - markMapEdited(); -} -// TODO: Move responsibility to list item -void MainWindow::on_spinBox_ConnectionOffset_valueChanged(int offset) -{ - editor->updateConnectionOffset(offset); - markMapEdited(); -} -// TODO: Move responsibility to list item -void MainWindow::on_comboBox_ConnectedMap_currentTextChanged(const QString &mapName) -{ - if (mapName.isEmpty() || editor->project->mapNames.contains(mapName)) { - editor->setConnectionMap(mapName); - markMapEdited(); - } -} - void MainWindow::on_pushButton_AddConnection_clicked() { // TODO: Bring up a prompt for information. Mark the current map *AND* the connected map as edited editor->addNewConnection(); markMapEdited(); } -// TODO: Move responsibility to list item -void MainWindow::on_pushButton_RemoveConnection_clicked() -{ - editor->removeCurrentConnection(); - markMapEdited(); -} void MainWindow::on_pushButton_NewWildMonGroup_clicked() { editor->addNewWildMonGroup(this); @@ -2595,6 +2568,7 @@ void MainWindow::on_button_OpenEmergeMap_clicked() { userSetMap(mapName, true); } +// TODO: Mirror change to/from other maps void MainWindow::on_comboBox_DiveMap_currentTextChanged(const QString &mapName) { if (editor->project->isExistingMapName(mapName)) { editor->updateDiveMap(mapName); diff --git a/src/ui/connectionslistitem.cpp b/src/ui/connectionslistitem.cpp index 47589a120..810b9a56f 100644 --- a/src/ui/connectionslistitem.cpp +++ b/src/ui/connectionslistitem.cpp @@ -19,6 +19,14 @@ ConnectionsListItem::ConnectionsListItem(QWidget *parent, const QStringList &map ui->comboBox_Map->setMinimumContentsLength(6); ui->comboBox_Map->addItems(mapNames); + + /* TODO: Spin box limits + ui->spinBox_ConnectionOffset->setMaximum(selected_connection_item->getMaxOffset()); + ui->spinBox_ConnectionOffset->setMinimum(selected_connection_item->getMinOffset()); + */ + + // TODO: + //connect(ui->button_Delete, &QAbstractButton::clicked, [this](bool) { this->d;}); } void ConnectionsListItem::populate(const MapConnection * connection) { @@ -35,3 +43,36 @@ ConnectionsListItem::~ConnectionsListItem() { delete ui; } + +// TODO +void ConnectionsListItem::on_comboBox_Direction_currentTextChanged(const QString &direction) +{ + /*editor->updateCurrentConnectionDirection(direction); + markMapEdited();*/ +} + +// TODO +void ConnectionsListItem::on_comboBox_Map_currentTextChanged(const QString &mapName) +{ + /*if (mapName.isEmpty() || editor->project->mapNames.contains(mapName)) { + editor->setConnectionMap(mapName); + markMapEdited(); + }*/ +} + +// TODO +void ConnectionsListItem::on_spinBox_Offset_valueChanged(int offset) +{ + /*editor->updateConnectionOffset(offset); + markMapEdited();*/ +} + +// TODO +void ConnectionsListItem::on_button_Delete_clicked() +{ + /* + editor->removeCurrentConnection(); + markMapEdited(); + */ +} + From 1f78fb9c4f6066380187bb8aad7b46ad3c4522e5 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Mon, 1 Jul 2024 14:10:55 -0400 Subject: [PATCH 04/30] Remove strict offset limitations --- include/ui/connectionpixmapitem.h | 2 -- src/editor.cpp | 8 -------- src/ui/connectionpixmapitem.cpp | 18 ------------------ src/ui/connectionslistitem.cpp | 6 ++---- 4 files changed, 2 insertions(+), 32 deletions(-) diff --git a/include/ui/connectionpixmapitem.h b/include/ui/connectionpixmapitem.h index c3d98cff4..fd1042fd5 100644 --- a/include/ui/connectionpixmapitem.h +++ b/include/ui/connectionpixmapitem.h @@ -27,8 +27,6 @@ class ConnectionPixmapItem : public QObject, public QGraphicsPixmapItem { int baseMapWidth; int baseMapHeight; void render(qreal opacity = 1); - int getMinOffset(); - int getMaxOffset(); void setEditable(bool editable); bool getEditable(); void updateHighlight(bool selected); diff --git a/src/editor.cpp b/src/editor.cpp index ec3e7f0ba..bd217f81b 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -822,12 +822,6 @@ void Editor::redrawConnection(ConnectionPixmapItem* connectionItem) { connectionItem->basePixmap = pixmap; - // TODO: Make sure offset limiting is correct (and updated) - // New map may have a different minimum offset than the last one. The maximum will be the same. - /*int min = selected_connection_item->getMinOffset(); - //ui->spinBox_ConnectionOffset->setMinimum(min); // Connections TODO: - onConnectionOffsetChanged(qMax(min, selected_connection_item->connection->offset));*/ - if (connectionItem == selected_connection_item) { QPainter painter(&pixmap); painter.setPen(QColor(255, 0, 255)); @@ -855,8 +849,6 @@ void Editor::updateConnectionOffset(int offset) { return; selected_connection_item->blockSignals(true); - offset = qMin(offset, selected_connection_item->getMaxOffset()); - offset = qMax(offset, selected_connection_item->getMinOffset()); selected_connection_item->connection->offset = offset; if (selected_connection_item->connection->direction == "up" || selected_connection_item->connection->direction == "down") { selected_connection_item->setX(selected_connection_item->initialX + (offset - selected_connection_item->initialOffset) * 16); diff --git a/src/ui/connectionpixmapitem.cpp b/src/ui/connectionpixmapitem.cpp index 256c556a0..659074908 100644 --- a/src/ui/connectionpixmapitem.cpp +++ b/src/ui/connectionpixmapitem.cpp @@ -13,20 +13,6 @@ void ConnectionPixmapItem::render(qreal opacity) { this->setPixmap(newPixmap); } -int ConnectionPixmapItem::getMinOffset() { - if (this->connection->direction == "up" || this->connection->direction == "down") - return -(this->pixmap().width() / 16) - 6; - else - return -(this->pixmap().height() / 16) - 6; -} - -int ConnectionPixmapItem::getMaxOffset() { - if (this->connection->direction == "up" || this->connection->direction == "down") - return this->baseMapWidth + 6; - else - return this->baseMapHeight + 6; -} - QVariant ConnectionPixmapItem::itemChange(GraphicsItemChange change, const QVariant &value) { if (change == ItemPositionChange) { @@ -37,8 +23,6 @@ QVariant ConnectionPixmapItem::itemChange(GraphicsItemChange change, const QVari if (this->connection->direction == "up" || this->connection->direction == "down") { x = round(newPos.x() / 16) * 16; newOffset += (x - initialX) / 16; - newOffset = qMin(newOffset, this->getMaxOffset()); - newOffset = qMax(newOffset, this->getMinOffset()); x = newOffset * 16; } else { @@ -48,8 +32,6 @@ QVariant ConnectionPixmapItem::itemChange(GraphicsItemChange change, const QVari if (this->connection->direction == "right" || this->connection->direction == "left") { y = round(newPos.y() / 16) * 16; newOffset += (y - this->initialY) / 16; - newOffset = qMin(newOffset, this->getMaxOffset()); - newOffset = qMax(newOffset, this->getMinOffset()); y = newOffset * 16; } else { diff --git a/src/ui/connectionslistitem.cpp b/src/ui/connectionslistitem.cpp index 810b9a56f..4980bff3e 100644 --- a/src/ui/connectionslistitem.cpp +++ b/src/ui/connectionslistitem.cpp @@ -20,10 +20,8 @@ ConnectionsListItem::ConnectionsListItem(QWidget *parent, const QStringList &map ui->comboBox_Map->setMinimumContentsLength(6); ui->comboBox_Map->addItems(mapNames); - /* TODO: Spin box limits - ui->spinBox_ConnectionOffset->setMaximum(selected_connection_item->getMaxOffset()); - ui->spinBox_ConnectionOffset->setMinimum(selected_connection_item->getMinOffset()); - */ + ui->spinBox_Offset->setMinimum(INT_MIN); + ui->spinBox_Offset->setMaximum(INT_MAX); // TODO: //connect(ui->button_Delete, &QAbstractButton::clicked, [this](bool) { this->d;}); From 367198f98f1d2aa10f5c55e44b69cf4d470abdc8 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Tue, 2 Jul 2024 14:05:54 -0400 Subject: [PATCH 05/30] Sync changes between connection list and map --- forms/connectionslistitem.ui | 2 +- include/editor.h | 5 +- include/ui/connectionpixmapitem.h | 8 +- include/ui/connectionslistitem.h | 15 +++- src/editor.cpp | 142 +++++++++++++++--------------- src/ui/connectionslistitem.cpp | 53 +++++------ 6 files changed, 117 insertions(+), 108 deletions(-) diff --git a/forms/connectionslistitem.ui b/forms/connectionslistitem.ui index f35c509ed..a55c8d901 100644 --- a/forms/connectionslistitem.ui +++ b/forms/connectionslistitem.ui @@ -57,7 +57,7 @@ - + ... diff --git a/include/editor.h b/include/editor.h index 37f60b6ae..5b3ed90e7 100644 --- a/include/editor.h +++ b/include/editor.h @@ -77,7 +77,7 @@ class Editor : public QObject void setConnectionsVisibility(bool visible); void updateConnectionOffset(int offset); void addNewConnection(); - void removeCurrentConnection(); + void removeConnection(ConnectionPixmapItem* connectionItem); void addNewWildMonGroup(QWidget *window); void deleteWildMonGroup(); void updateDiveMap(QString mapName); @@ -168,10 +168,11 @@ public slots: void setConnectionItemsVisible(bool); void setBorderItemsVisible(bool, qreal = 1); void setConnectionsEditable(bool); + QPoint calculateConnectionPosition(const MapConnection *connection, const QPixmap &pixmap); void redrawConnection(ConnectionPixmapItem* connectionItem); void createConnectionItem(MapConnection* connection); void populateConnectionsList(); - void addConnectionToList(const MapConnection * connection); + void addConnectionToList(ConnectionPixmapItem* connection); void updateDiveEmergeMap(QString mapName, QString direction); void onConnectionOffsetChanged(int newOffset); void removeMirroredConnection(MapConnection*); diff --git a/include/ui/connectionpixmapitem.h b/include/ui/connectionpixmapitem.h index fd1042fd5..c9b792265 100644 --- a/include/ui/connectionpixmapitem.h +++ b/include/ui/connectionpixmapitem.h @@ -8,9 +8,11 @@ class ConnectionPixmapItem : public QObject, public QGraphicsPixmapItem { Q_OBJECT public: - ConnectionPixmapItem(QPixmap pixmap, MapConnection* connection, int x, int y, int baseMapWidth, int baseMapHeight): QGraphicsPixmapItem(pixmap) { + ConnectionPixmapItem(QPixmap pixmap, MapConnection* connection, int x, int y, int baseMapWidth, int baseMapHeight) + : QGraphicsPixmapItem(pixmap), + connection(connection) + { this->basePixmap = pixmap; - this->connection = connection; setFlag(ItemIsMovable); setFlag(ItemSendsGeometryChanges); this->initialX = x; @@ -20,7 +22,7 @@ class ConnectionPixmapItem : public QObject, public QGraphicsPixmapItem { this->baseMapHeight = baseMapHeight; } QPixmap basePixmap; - MapConnection* connection; + MapConnection* const connection; int initialX; int initialY; int initialOffset; diff --git a/include/ui/connectionslistitem.h b/include/ui/connectionslistitem.h index a9dab7ca4..ffa9ddcaa 100644 --- a/include/ui/connectionslistitem.h +++ b/include/ui/connectionslistitem.h @@ -9,18 +9,27 @@ namespace Ui { class ConnectionsListItem; } +// We show the data for each map connection in the panel on the right side of the Connections tab. +// An instance of this class is used for each item in that list. +// It communicates with the ConnectionPixmapItem on the map through a shared MapConnection pointer, +// and the two classes should signal one another when they change this data. class ConnectionsListItem : public QFrame { Q_OBJECT public: - explicit ConnectionsListItem(QWidget *parent, const QStringList &mapNames); + explicit ConnectionsListItem(QWidget *parent, MapConnection * connection, const QStringList &mapNames); ~ConnectionsListItem(); - void populate(const MapConnection * connection); + void updateUI(); -public: +private: Ui::ConnectionsListItem *ui; + MapConnection * const connection; + +signals: + void edited(); + void deleted(); private slots: void on_comboBox_Direction_currentTextChanged(const QString &direction); diff --git a/src/editor.cpp b/src/editor.cpp index bd217f81b..39de3a8ab 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -759,14 +759,49 @@ void Editor::populateConnectionsList() { w->deleteLater(); for (auto item :connection_items) - addConnectionToList(item->connection); + addConnectionToList(item); } // TODO: Don't allow splitter resizing to shrink list items to the point where horizontal scroll is needed -void Editor::addConnectionToList(const MapConnection * connection) { - ConnectionsListItem *listItem = new ConnectionsListItem(ui->scrollAreaContents_ConnectionsList, project->mapNames); - listItem->populate(connection); +void Editor::addConnectionToList(ConnectionPixmapItem * connectionItem) { + ConnectionsListItem *listItem = new ConnectionsListItem(ui->scrollAreaContents_ConnectionsList, connectionItem->connection, project->mapNames); ui->layout_ConnectionsList->insertWidget(ui->layout_ConnectionsList->count() - 1, listItem); // Insert above the vertical spacer + + connect(connectionItem, &ConnectionPixmapItem::connectionMoved, listItem, &ConnectionsListItem::updateUI); + + // TODO: This is probably slower than necessary (we don't need a full redraw if we're just moving it) + // TODO: Handle mirroring + connect(listItem, &ConnectionsListItem::edited, [this, connectionItem] { + redrawConnection(connectionItem); + emit editedMapData(); + }); + + connect(listItem, &ConnectionsListItem::deleted, [this, connectionItem] { + removeConnection(connectionItem); + }); +} + +// TODO: Connect to Delete key for selected connection +void Editor::removeConnection(ConnectionPixmapItem* connectionItem) { + if (!connectionItem) + return; + + map->connections.removeOne(connectionItem->connection); + connection_items.removeOne(connectionItem); + //removeMirroredConnection(connectionItem->connection); // TODO + + if (connectionItem->scene()) + connectionItem->scene()->removeItem(connectionItem); + + if (connectionItem == selected_connection_item) { + selected_connection_item = nullptr; + if (!connection_items.isEmpty()) + onConnectionItemSelected(connection_items.first()); + } + + delete connectionItem->connection; + delete connectionItem; + emit editedMapData(); } void Editor::setConnectionItemsVisible(bool visible) { @@ -783,6 +818,25 @@ void Editor::setBorderItemsVisible(bool visible, qreal opacity) { } } +QPoint Editor::calculateConnectionPosition(const MapConnection *connection, const QPixmap &pixmap) { + int x = 0, y = 0; + const int mWidth = 16, mHeight = 16; + if (connection->direction == "up") { + x = connection->offset * mWidth; + y = -pixmap.height(); + } else if (connection->direction == "down") { + x = connection->offset * mWidth; + y = map->getHeight() * mHeight; + } else if (connection->direction == "left") { + x = -pixmap.width(); + y = connection->offset * mHeight; + } else if (connection->direction == "right") { + x = map->getWidth() * mWidth; + y = connection->offset * mHeight; + } + return QPoint(x, y); +} + void Editor::redrawConnection(ConnectionPixmapItem* connectionItem) { if (!connectionItem || !connectionItem->connection) return; @@ -802,25 +856,9 @@ void Editor::redrawConnection(ConnectionPixmapItem* connectionItem) { return; QPixmap pixmap = connectedMap->renderConnection(*connectionItem->connection, map->layout); - - int offset = connectionItem->connection->offset; - connectionItem->initialOffset = offset; - int x = 0, y = 0; - if (connectionItem->connection->direction == "up") { - x = offset * 16; - y = -pixmap.height(); - } else if (connectionItem->connection->direction == "down") { - x = offset * 16; - y = map->getHeight() * 16; - } else if (connectionItem->connection->direction == "left") { - x = -pixmap.width(); - y = offset * 16; - } else if (connectionItem->connection->direction == "right") { - x = map->getWidth() * 16; - y = offset * 16; - } - + connectionItem->initialOffset = connectionItem->connection->offset; connectionItem->basePixmap = pixmap; + QPoint pos = calculateConnectionPosition(connectionItem->connection, pixmap); if (connectionItem == selected_connection_item) { QPainter painter(&pixmap); @@ -829,11 +867,11 @@ void Editor::redrawConnection(ConnectionPixmapItem* connectionItem) { painter.end(); } connectionItem->setPixmap(pixmap); - connectionItem->initialX = x; - connectionItem->initialY = y; + connectionItem->initialX = pos.x(); + connectionItem->initialY = pos.y(); connectionItem->blockSignals(true); - connectionItem->setX(x); - connectionItem->setY(y); + connectionItem->setX(pos.x()); + connectionItem->setY(pos.y()); connectionItem->setZValue(-1); connectionItem->blockSignals(false); @@ -843,7 +881,7 @@ void Editor::redrawConnection(ConnectionPixmapItem* connectionItem) { maskNonVisibleConnectionTiles(); } -// TODO: Generalize +// TODO: Generalize, maybe use in addConnectionToList connection instead of full render void Editor::updateConnectionOffset(int offset) { if (!selected_connection_item) return; @@ -863,11 +901,10 @@ void Editor::updateConnectionOffset(int offset) { void Editor::onConnectionMoved(MapConnection* connection) { // TODO: //updateMirroredConnectionOffset(connection); - - // TODO: Sync change to correct offset spin box // TODO: This is likely the source of the visual masking bug while dragging (this happens after the move) maskNonVisibleConnectionTiles(); + emit editedMapData(); } void Editor::setConnectionsEditable(bool editable) { @@ -1559,30 +1596,18 @@ void Editor::createConnectionItem(MapConnection* connection) { } QPixmap pixmap = connected_map->renderConnection(*connection, map->layout); - int offset = connection->offset; - int x = 0, y = 0; - if (connection->direction == "up") { - x = offset * 16; - y = -pixmap.height(); - } else if (connection->direction == "down") { - x = offset * 16; - y = map->getHeight() * 16; - } else if (connection->direction == "left") { - x = -pixmap.width(); - y = offset * 16; - } else if (connection->direction == "right") { - x = map->getWidth() * 16; - y = offset * 16; - } + QPoint pos = calculateConnectionPosition(connection, pixmap); - ConnectionPixmapItem *item = new ConnectionPixmapItem(pixmap, connection, x, y, map->getWidth(), map->getHeight()); - item->setX(x); - item->setY(y); + ConnectionPixmapItem *item = new ConnectionPixmapItem(pixmap, connection, pos.x(), pos.y(), map->getWidth(), map->getHeight()); + item->setX(pos.x()); + item->setY(pos.y()); item->setZValue(-1); scene->addItem(item); + connect(item, &ConnectionPixmapItem::connectionMoved, this, &Editor::onConnectionMoved); connect(item, &ConnectionPixmapItem::connectionItemSelected, this, &Editor::onConnectionItemSelected); connect(item, &ConnectionPixmapItem::connectionItemDoubleClicked, this, &Editor::onConnectionItemDoubleClicked); + connection_items.append(item); } @@ -1728,7 +1753,7 @@ void Editor::addNewConnection() { newConnection->map_name = defaultMapName; map->connections.append(newConnection); createConnectionItem(newConnection); - addConnectionToList(newConnection); + addConnectionToList(connection_items.last()); onConnectionItemSelected(connection_items.last()); updateMirroredConnection(newConnection, newConnection->direction, newConnection->map_name); @@ -1795,27 +1820,6 @@ void Editor::updateMirroredConnection(MapConnection* connection, QString origina mirrorConnection->offset = -connection->offset; } -void Editor::removeCurrentConnection() { - if (!selected_connection_item) - return; - - map->connections.removeOne(selected_connection_item->connection); - connection_items.removeOne(selected_connection_item); - removeMirroredConnection(selected_connection_item->connection); - - if (selected_connection_item && selected_connection_item->scene()) { - selected_connection_item->scene()->removeItem(selected_connection_item); - delete selected_connection_item; - } - - selected_connection_item = nullptr; - //ui->spinBox_ConnectionOffset->setValue(0); // Connections TODO: - - if (connection_items.length() > 0) { - onConnectionItemSelected(connection_items.last()); - } -} - void Editor::updateDiveMap(QString mapName) { updateDiveEmergeMap(mapName, "dive"); } diff --git a/src/ui/connectionslistitem.cpp b/src/ui/connectionslistitem.cpp index 4980bff3e..246e83f4e 100644 --- a/src/ui/connectionslistitem.cpp +++ b/src/ui/connectionslistitem.cpp @@ -3,9 +3,10 @@ static const QStringList directions = {"up", "down", "left", "right"}; -ConnectionsListItem::ConnectionsListItem(QWidget *parent, const QStringList &mapNames) : +ConnectionsListItem::ConnectionsListItem(QWidget *parent, MapConnection * connection, const QStringList &mapNames) : QFrame(parent), - ui(new Ui::ConnectionsListItem) + ui(new Ui::ConnectionsListItem), + connection(connection) { ui->setupUi(this); @@ -23,54 +24,46 @@ ConnectionsListItem::ConnectionsListItem(QWidget *parent, const QStringList &map ui->spinBox_Offset->setMinimum(INT_MIN); ui->spinBox_Offset->setMaximum(INT_MAX); - // TODO: - //connect(ui->button_Delete, &QAbstractButton::clicked, [this](bool) { this->d;}); + this->updateUI(); } -void ConnectionsListItem::populate(const MapConnection * connection) { +ConnectionsListItem::~ConnectionsListItem() +{ + delete ui; +} + +void ConnectionsListItem::updateUI() { const QSignalBlocker blocker1(ui->comboBox_Direction); const QSignalBlocker blocker2(ui->comboBox_Map); const QSignalBlocker blocker3(ui->spinBox_Offset); - ui->comboBox_Direction->setTextItem(connection->direction); - ui->comboBox_Map->setTextItem(connection->map_name); - ui->spinBox_Offset->setValue(connection->offset); + ui->comboBox_Direction->setTextItem(this->connection->direction); + ui->comboBox_Map->setTextItem(this->connection->map_name); + ui->spinBox_Offset->setValue(this->connection->offset); } -ConnectionsListItem::~ConnectionsListItem() -{ - delete ui; -} - -// TODO void ConnectionsListItem::on_comboBox_Direction_currentTextChanged(const QString &direction) { - /*editor->updateCurrentConnectionDirection(direction); - markMapEdited();*/ + this->connection->direction = direction; + emit this->edited(); } -// TODO void ConnectionsListItem::on_comboBox_Map_currentTextChanged(const QString &mapName) { - /*if (mapName.isEmpty() || editor->project->mapNames.contains(mapName)) { - editor->setConnectionMap(mapName); - markMapEdited(); - }*/ + if (ui->comboBox_Map->findText(mapName) >= 0) { + this->connection->map_name = mapName; + emit this->edited(); + } } -// TODO void ConnectionsListItem::on_spinBox_Offset_valueChanged(int offset) { - /*editor->updateConnectionOffset(offset); - markMapEdited();*/ + this->connection->offset = offset; + emit this->edited(); } -// TODO void ConnectionsListItem::on_button_Delete_clicked() { - /* - editor->removeCurrentConnection(); - markMapEdited(); - */ + this->deleteLater(); + emit this->deleted(); } - From 6b0034e52384cd3d1053d6fb5afeed5c41c01a5f Mon Sep 17 00:00:00 2001 From: GriffinR Date: Wed, 3 Jul 2024 11:34:27 -0400 Subject: [PATCH 06/30] Fix border visibility in API --- include/editor.h | 8 +--- include/mainwindow.h | 2 +- src/editor.cpp | 88 ++++++++++++++---------------------- src/mainwindow.cpp | 9 ++-- src/scriptapi/apiutility.cpp | 2 +- 5 files changed, 41 insertions(+), 68 deletions(-) diff --git a/include/editor.h b/include/editor.h index 5b3ed90e7..4906a4e10 100644 --- a/include/editor.h +++ b/include/editor.h @@ -165,9 +165,7 @@ public slots: const QImage collisionPlaceholder = QImage(":/images/collisions_unknown.png"); QPixmap collisionSheetPixmap; - void setConnectionItemsVisible(bool); - void setBorderItemsVisible(bool, qreal = 1); - void setConnectionsEditable(bool); + void updateBorderVisibility(); QPoint calculateConnectionPosition(const MapConnection *connection, const QPixmap &pixmap); void redrawConnection(ConnectionPixmapItem* connectionItem); void createConnectionItem(MapConnection* connection); @@ -197,8 +195,6 @@ private slots: void mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixmapItem *item); void onConnectionMoved(MapConnection*); void onConnectionItemSelected(ConnectionPixmapItem* connectionItem); - void onConnectionItemDoubleClicked(ConnectionPixmapItem* connectionItem); - void onConnectionDirectionChanged(QString newDirection); void onHoveredMovementPermissionChanged(uint16_t, uint16_t); void onHoveredMovementPermissionCleared(); void onHoveredMetatileSelectionChanged(uint16_t); @@ -213,7 +209,7 @@ private slots: signals: void objectsChanged(); - void loadMapRequested(QString, QString); + void connectionItemDoubleClicked(QString, QString); void wildMonDataChanged(); void warpEventDoubleClicked(QString, int, Event::Group); void currentMetatilesSelectionChanged(); diff --git a/include/mainwindow.h b/include/mainwindow.h index 51bfecc32..72067d5c0 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -177,7 +177,7 @@ private slots: void copy(); void paste(); - void onLoadMapRequested(QString, QString); + void onConnectionItemDoubleClicked(QString, QString); void onMapChanged(Map *map); void onMapNeedsRedrawing(); void onTilesetsSaved(QString, QString); diff --git a/src/editor.cpp b/src/editor.cpp index 39de3a8ab..d5a0dbd21 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -99,9 +99,7 @@ void Editor::setEditingMap() { if (events_group) { events_group->setVisible(false); } - setBorderItemsVisible(ui->checkBox_ToggleBorder->isChecked()); - setConnectionItemsVisible(ui->checkBox_ToggleBorder->isChecked()); - setConnectionsEditable(false); + updateBorderVisibility(); this->cursorMapTileRect->stopSingleTileMode(); this->cursorMapTileRect->setActive(true); @@ -123,9 +121,7 @@ void Editor::setEditingCollision() { if (events_group) { events_group->setVisible(false); } - setBorderItemsVisible(ui->checkBox_ToggleBorder->isChecked()); - setConnectionItemsVisible(ui->checkBox_ToggleBorder->isChecked()); - setConnectionsEditable(false); + updateBorderVisibility(); this->cursorMapTileRect->setSingleTileMode(); this->cursorMapTileRect->setActive(true); @@ -146,9 +142,7 @@ void Editor::setEditingObjects() { if (collision_item) { collision_item->setVisible(false); } - setBorderItemsVisible(ui->checkBox_ToggleBorder->isChecked()); - setConnectionItemsVisible(ui->checkBox_ToggleBorder->isChecked()); - setConnectionsEditable(false); + updateBorderVisibility(); this->cursorMapTileRect->setSingleTileMode(); this->cursorMapTileRect->setActive(false); updateWarpEventWarnings(); @@ -179,10 +173,6 @@ void Editor::setEditingConnections() { map_item->draw(); map_item->setVisible(true); populateConnectionsList(); - if (selected_connection_item) { - // TODO: Do we need additional handling here again - redrawConnection(selected_connection_item); - } maskNonVisibleConnectionTiles(); } if (collision_item) { @@ -191,9 +181,7 @@ void Editor::setEditingConnections() { if (events_group) { events_group->setVisible(false); } - setBorderItemsVisible(true, 0.4); - setConnectionItemsVisible(true); - setConnectionsEditable(true); + updateBorderVisibility(); this->cursorMapTileRect->setSingleTileMode(); this->cursorMapTileRect->setActive(false); } @@ -804,20 +792,6 @@ void Editor::removeConnection(ConnectionPixmapItem* connectionItem) { emit editedMapData(); } -void Editor::setConnectionItemsVisible(bool visible) { - for (ConnectionPixmapItem* item : connection_items) { - item->setVisible(visible); - item->setEnabled(visible); - } -} - -void Editor::setBorderItemsVisible(bool visible, qreal opacity) { - for (QGraphicsPixmapItem* item : borderItems) { - item->setVisible(visible); - item->setOpacity(opacity); - } -} - QPoint Editor::calculateConnectionPosition(const MapConnection *connection, const QPixmap &pixmap) { int x = 0, y = 0; const int mWidth = 16, mHeight = 16; @@ -883,7 +857,7 @@ void Editor::redrawConnection(ConnectionPixmapItem* connectionItem) { // TODO: Generalize, maybe use in addConnectionToList connection instead of full render void Editor::updateConnectionOffset(int offset) { - if (!selected_connection_item) + /*if (!selected_connection_item) return; selected_connection_item->blockSignals(true); @@ -895,7 +869,7 @@ void Editor::updateConnectionOffset(int offset) { } selected_connection_item->blockSignals(false); updateMirroredConnectionOffset(selected_connection_item->connection); - maskNonVisibleConnectionTiles(); + maskNonVisibleConnectionTiles();*/ } void Editor::onConnectionMoved(MapConnection* connection) { @@ -907,13 +881,6 @@ void Editor::onConnectionMoved(MapConnection* connection) { emit editedMapData(); } -void Editor::setConnectionsEditable(bool editable) { - for (ConnectionPixmapItem* item : connection_items) { - item->setEditable(editable); - item->updateHighlight(item == selected_connection_item); - } -} - void Editor::onConnectionItemSelected(ConnectionPixmapItem* connectionItem) { if (!connectionItem) return; @@ -925,6 +892,7 @@ void Editor::onConnectionItemSelected(ConnectionPixmapItem* connectionItem) { // TODO: Handle the highlight done in redrawConnection? } +// TODO: Inaccurate if there are multiple connections from the same map void Editor::setSelectedConnectionFromMap(QString mapName) { // Search for the first connection that connects to the given map map. for (ConnectionPixmapItem* item : connection_items) { @@ -935,21 +903,9 @@ void Editor::setSelectedConnectionFromMap(QString mapName) { } } -void Editor::onConnectionItemDoubleClicked(ConnectionPixmapItem* connectionItem) { - emit loadMapRequested(connectionItem->connection->map_name, map->name); -} - -void Editor::onConnectionDirectionChanged(QString newDirection) { - /* // Connections TODO: - ui->comboBox_ConnectionDirection->blockSignals(true); - ui->comboBox_ConnectionDirection->setCurrentText(newDirection); - ui->comboBox_ConnectionDirection->blockSignals(false); - */ -} - void Editor::onBorderMetatilesChanged() { displayMapBorder(); - setBorderItemsVisible(ui->checkBox_ToggleBorder->isChecked()); + updateBorderVisibility(); // TODO: Why do we need to call this here } void Editor::onHoveredMovementPermissionChanged(uint16_t collision, uint16_t elevation) { @@ -1606,7 +1562,9 @@ void Editor::createConnectionItem(MapConnection* connection) { connect(item, &ConnectionPixmapItem::connectionMoved, this, &Editor::onConnectionMoved); connect(item, &ConnectionPixmapItem::connectionItemSelected, this, &Editor::onConnectionItemSelected); - connect(item, &ConnectionPixmapItem::connectionItemDoubleClicked, this, &Editor::onConnectionItemDoubleClicked); + connect(item, &ConnectionPixmapItem::connectionItemDoubleClicked, [this, item] { + emit this->connectionItemDoubleClicked(item->connection->map_name, map->name); + }); connection_items.append(item); } @@ -1886,13 +1844,33 @@ void Editor::updateSecondaryTileset(QString tilesetLabel, bool forceLoad) void Editor::toggleBorderVisibility(bool visible, bool enableScriptCallback) { - this->setBorderItemsVisible(visible); - this->setConnectionItemsVisible(visible); porymapConfig.setShowBorder(visible); + updateBorderVisibility(); if (enableScriptCallback) Scripting::cb_BorderVisibilityToggled(visible); } +void Editor::updateBorderVisibility() { + // On the connections tab, the border is always visible, and the connections can be edited. + bool editingConnections = (ui->mainTabBar->currentIndex() == 3); + bool visible = (editingConnections || ui->checkBox_ToggleBorder->isChecked()); + + // Update border + const qreal borderOpacity = editingConnections ? 0.4 : 1; + for (QGraphicsPixmapItem* item : borderItems) { + item->setVisible(visible); + item->setOpacity(borderOpacity); + } + + // Update map connections + for (ConnectionPixmapItem* item : connection_items) { + item->setVisible(visible); + item->setEditable(editingConnections); + item->setEnabled(visible); + item->updateHighlight(item == selected_connection_item); + } +} + void Editor::updateCustomMapHeaderValues(QTableWidget *table) { map->customHeaders = CustomAttributesTable::getAttributes(table); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index c51427991..b90f95233 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -298,7 +298,7 @@ void MainWindow::checkForUpdates(bool) {} void MainWindow::initEditor() { this->editor = new Editor(ui); connect(this->editor, &Editor::objectsChanged, this, &MainWindow::updateObjects); - connect(this->editor, &Editor::loadMapRequested, this, &MainWindow::onLoadMapRequested); + connect(this->editor, &Editor::connectionItemDoubleClicked, this, &MainWindow::onConnectionItemDoubleClicked); connect(this->editor, &Editor::warpEventDoubleClicked, this, &MainWindow::openWarpMap); connect(this->editor, &Editor::currentMetatilesSelectionChanged, this, &MainWindow::currentMetatilesSelectionChanged); connect(this->editor, &Editor::wildMonDataChanged, this, &MainWindow::onWildMonDataChanged); @@ -2419,8 +2419,8 @@ void MainWindow::clickToolButtonFromEditMode(QString editMode) { } } -void MainWindow::onLoadMapRequested(QString mapName, QString fromMapName) { - if (userSetMap(mapName, true)) +void MainWindow::onConnectionItemDoubleClicked(QString mapName, QString fromMapName) { + if (mapName != fromMapName && userSetMap(mapName, true)) editor->setSelectedConnectionFromMap(fromMapName); } @@ -2706,8 +2706,7 @@ void MainWindow::on_checkBox_smartPaths_stateChanged(int selected) void MainWindow::on_checkBox_ToggleBorder_stateChanged(int selected) { - bool visible = selected != 0; - editor->toggleBorderVisibility(visible); + editor->toggleBorderVisibility(selected != 0); } void MainWindow::on_actionTileset_Editor_triggered() diff --git a/src/scriptapi/apiutility.cpp b/src/scriptapi/apiutility.cpp index 38ff3e398..1e44b1b7e 100644 --- a/src/scriptapi/apiutility.cpp +++ b/src/scriptapi/apiutility.cpp @@ -168,7 +168,7 @@ bool ScriptUtility::getGridVisibility() { } void ScriptUtility::setBorderVisibility(bool visible) { - window->editor->toggleBorderVisibility(visible, false); + window->ui->checkBox_ToggleBorder->setChecked(visible); } bool ScriptUtility::getBorderVisibility() { From 0aa7ddf27d082047a80123376424aaddbeeb7ff8 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Wed, 3 Jul 2024 13:41:00 -0400 Subject: [PATCH 07/30] Add tab enums --- include/mainwindow.h | 19 +++++++++ src/editor.cpp | 2 +- src/mainwindow.cpp | 79 ++++++++++++++++++++---------------- src/scriptapi/apiutility.cpp | 5 ++- 4 files changed, 69 insertions(+), 36 deletions(-) diff --git a/include/mainwindow.h b/include/mainwindow.h index 72067d5c0..121fe1cdb 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -411,4 +411,23 @@ enum MapListUserRoles { TypeRole2, // Used for various extra data needed. }; +// These are namespaced in a struct to avoid colliding with e.g. class Map. +struct MainTab { + enum { + Map, + Events, + Header, + Connections, + WildPokemon, + }; +}; + +struct MapViewTab { + enum { + Metatiles, + Collision, + Prefabs, + }; +}; + #endif // MAINWINDOW_H diff --git a/src/editor.cpp b/src/editor.cpp index d5a0dbd21..099223725 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -1852,7 +1852,7 @@ void Editor::toggleBorderVisibility(bool visible, bool enableScriptCallback) void Editor::updateBorderVisibility() { // On the connections tab, the border is always visible, and the connections can be edited. - bool editingConnections = (ui->mainTabBar->currentIndex() == 3); + bool editingConnections = (ui->mainTabBar->currentIndex() == MainTab::Connections); bool visible = (editingConnections || ui->checkBox_ToggleBorder->isChecked()); // Update border diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index b90f95233..cfea8e85f 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -208,16 +208,23 @@ void MainWindow::applyUserShortcuts() { shortcut->setKeys(shortcutsConfig.userShortcuts(shortcut)); } +static const QMap mainTabNames = { + {MainTab::Map, "Map"}, + {MainTab::Events, "Events"}, + {MainTab::Header, "Header"}, + {MainTab::Connections, "Connections"}, + {MainTab::WildPokemon, "Wild Pokemon"}, +}; + void MainWindow::initCustomUI() { // Set up the tab bar while (ui->mainTabBar->count()) ui->mainTabBar->removeTab(0); - ui->mainTabBar->addTab("Map"); - ui->mainTabBar->setTabIcon(0, QIcon(QStringLiteral(":/icons/map.ico"))); - ui->mainTabBar->addTab("Events"); - ui->mainTabBar->addTab("Header"); - ui->mainTabBar->addTab("Connections"); - ui->mainTabBar->addTab("Wild Pokemon"); - ui->mainTabBar->setTabIcon(4, QIcon(QStringLiteral(":/icons/tall_grass.ico"))); + + for (int i = 0; i < mainTabNames.count(); i++) + ui->mainTabBar->addTab(mainTabNames.value(i)); + + ui->mainTabBar->setTabIcon(MainTab::Map, QIcon(QStringLiteral(":/icons/map.ico"))); + ui->mainTabBar->setTabIcon(MainTab::WildPokemon, QIcon(QStringLiteral(":/icons/tall_grass.ico"))); } void MainWindow::initExtraSignals() { @@ -416,8 +423,7 @@ void MainWindow::markMapEdited() { void MainWindow::setProjectSpecificUI() { // Wild Encounters tab - // TODO: This index should come from an enum - ui->mainTabBar->setTabEnabled(4, editor->project->wildEncountersLoaded); + ui->mainTabBar->setTabEnabled(MainTab::WildPokemon, editor->project->wildEncountersLoaded); bool hasFlags = projectConfig.getMapAllowFlagsEnabled(); ui->checkBox_AllowRunning->setVisible(hasFlags); @@ -1569,7 +1575,7 @@ void MainWindow::copy() { { default: break; - case 0: + case MainTab::Map: { // copy the map image QPixmap pixmap = editor->map ? editor->map->render(true) : QPixmap(); @@ -1577,7 +1583,7 @@ void MainWindow::copy() { logInfo("Copied current map image to clipboard"); break; } - case 1: + case MainTab::Events: { if (!editor || !editor->project) break; @@ -1617,7 +1623,7 @@ void MainWindow::copy() { } } } - else if (this->ui->mainTabBar->currentIndex() == 4) { + else if (this->ui->mainTabBar->currentIndex() == MainTab::WildPokemon) { QWidget *w = this->ui->stackedWidget_WildMons->currentWidget(); if (w) { MonTabWidget *mtw = static_cast(w); @@ -1648,7 +1654,7 @@ void MainWindow::paste() { QClipboard *clipboard = QGuiApplication::clipboard(); QString clipboardText(clipboard->text()); - if (ui->mainTabBar->currentIndex() == 4) { + if (ui->mainTabBar->currentIndex() == MainTab::WildPokemon) { QWidget *w = this->ui->stackedWidget_WildMons->currentWidget(); if (w) { w->setFocus(); @@ -1676,7 +1682,7 @@ void MainWindow::paste() { { default: break; - case 0: + case MainTab::Map: { // can only paste currently selected metatiles on this tab if (pasteObject["object"].toString() != "metatile_selection") { @@ -1785,11 +1791,11 @@ void MainWindow::on_mapViewTab_tabBarClicked(int index) if (index != oldIndex) Scripting::cb_MapViewTabChanged(oldIndex, index); - if (index == 0) { + if (index == MapViewTab::Metatiles) { editor->setEditingMap(); - } else if (index == 1) { + } else if (index == MapViewTab::Collision) { editor->setEditingCollision(); - } else if (index == 2) { + } else if (index == MapViewTab::Prefabs) { editor->setEditingMap(); if (projectConfig.getPrefabFilepath().isEmpty() && !projectConfig.getPrefabImportPrompted()) { // User hasn't set up prefabs and hasn't been prompted before. @@ -1813,25 +1819,31 @@ void MainWindow::on_mainTabBar_tabBarClicked(int index) if (index != oldIndex) Scripting::cb_MainTabChanged(oldIndex, index); - int tabIndexToStackIndex[5] = {0, 0, 1, 2, 3}; - ui->mainStackedWidget->setCurrentIndex(tabIndexToStackIndex[index]); + static const QMap tabIndexToStackIndex = { + {MainTab::Map, 0}, + {MainTab::Events, 0}, + {MainTab::Header, 1}, + {MainTab::Connections, 2}, + {MainTab::WildPokemon, 3}, + }; + ui->mainStackedWidget->setCurrentIndex(tabIndexToStackIndex.value(index)); - if (index == 0) { + if (index == MainTab::Map) { ui->stackedWidget_MapEvents->setCurrentIndex(0); on_mapViewTab_tabBarClicked(ui->mapViewTab->currentIndex()); clickToolButtonFromEditMode(editor->map_edit_mode); - } else if (index == 1) { + } else if (index == MainTab::Events) { ui->stackedWidget_MapEvents->setCurrentIndex(1); editor->setEditingObjects(); clickToolButtonFromEditMode(editor->obj_edit_mode); - } else if (index == 3) { + } else if (index == MainTab::Connections) { editor->setEditingConnections(); } - if (index != 4) { + if (index != MainTab::WildPokemon) { if (editor->project && editor->project->wildEncountersLoaded) editor->saveEncounterTabData(); } - if (index != 1) { + if (index != MainTab::Events) { editor->map_ruler->setEnabled(false); } } @@ -2218,7 +2230,7 @@ void MainWindow::on_horizontalSlider_CollisionTransparency_valueChanged(int valu } void MainWindow::on_toolButton_deleteObject_clicked() { - if (ui->mainTabBar->currentIndex() != 1) { + if (ui->mainTabBar->currentIndex() != MainTab::Events) { // do not delete an event when not on event tab return; } @@ -2268,15 +2280,14 @@ void MainWindow::on_toolButton_deleteObject_clicked() { void MainWindow::on_toolButton_Paint_clicked() { - if (ui->mainTabBar->currentIndex() == 0) + if (ui->mainTabBar->currentIndex() == MainTab::Map) editor->map_edit_mode = "paint"; else editor->obj_edit_mode = "paint"; editor->settings->mapCursor = QCursor(QPixmap(":/icons/pencil_cursor.ico"), 10, 10); - // do not stop single tile mode when editing collision - if (ui->mapViewTab->currentIndex() != 1) + if (ui->mapViewTab->currentIndex() != MapViewTab::Collision) editor->cursorMapTileRect->stopSingleTileMode(); ui->graphicsView_Map->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); @@ -2290,7 +2301,7 @@ void MainWindow::on_toolButton_Paint_clicked() void MainWindow::on_toolButton_Select_clicked() { - if (ui->mainTabBar->currentIndex() == 0) + if (ui->mainTabBar->currentIndex() == MainTab::Map) editor->map_edit_mode = "select"; else editor->obj_edit_mode = "select"; @@ -2309,7 +2320,7 @@ void MainWindow::on_toolButton_Select_clicked() void MainWindow::on_toolButton_Fill_clicked() { - if (ui->mainTabBar->currentIndex() == 0) + if (ui->mainTabBar->currentIndex() == MainTab::Map) editor->map_edit_mode = "fill"; else editor->obj_edit_mode = "fill"; @@ -2328,7 +2339,7 @@ void MainWindow::on_toolButton_Fill_clicked() void MainWindow::on_toolButton_Dropper_clicked() { - if (ui->mainTabBar->currentIndex() == 0) + if (ui->mainTabBar->currentIndex() == MainTab::Map) editor->map_edit_mode = "pick"; else editor->obj_edit_mode = "pick"; @@ -2347,7 +2358,7 @@ void MainWindow::on_toolButton_Dropper_clicked() void MainWindow::on_toolButton_Move_clicked() { - if (ui->mainTabBar->currentIndex() == 0) + if (ui->mainTabBar->currentIndex() == MainTab::Map) editor->map_edit_mode = "move"; else editor->obj_edit_mode = "move"; @@ -2366,7 +2377,7 @@ void MainWindow::on_toolButton_Move_clicked() void MainWindow::on_toolButton_Shift_clicked() { - if (ui->mainTabBar->currentIndex() == 0) + if (ui->mainTabBar->currentIndex() == MainTab::Map) editor->map_edit_mode = "shift"; else editor->obj_edit_mode = "shift"; @@ -2385,7 +2396,7 @@ void MainWindow::on_toolButton_Shift_clicked() void MainWindow::checkToolButtons() { QString edit_mode; - if (ui->mainTabBar->currentIndex() == 0) { + if (ui->mainTabBar->currentIndex() == MainTab::Map) { edit_mode = editor->map_edit_mode; } else { edit_mode = editor->obj_edit_mode; diff --git a/src/scriptapi/apiutility.cpp b/src/scriptapi/apiutility.cpp index 1e44b1b7e..61b6e9787 100644 --- a/src/scriptapi/apiutility.cpp +++ b/src/scriptapi/apiutility.cpp @@ -154,7 +154,10 @@ int ScriptUtility::getMapViewTab() { } void ScriptUtility::setMapViewTab(int index) { - if (this->getMainTab() != 0 || !window->ui->mapViewTab || index < 0 || index >= window->ui->mapViewTab->count()) + if (this->getMainTab() != MainTab::Map || !window->ui->mapViewTab || index < 0 || index >= window->ui->mapViewTab->count()) + return; + // Can't select tab if it's disabled + if (!window->ui->mapViewTab->isTabEnabled(index)) return; window->on_mapViewTab_tabBarClicked(index); } From 7c6b33da1b33cf21934b3a5f2f4735ab8ee12ed8 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Wed, 3 Jul 2024 16:01:52 -0400 Subject: [PATCH 08/30] Add selection highlight to connections list --- forms/connectionslistitem.ui | 7 +++++-- forms/mainwindow.ui | 24 ++++++++++----------- include/project.h | 1 - include/ui/connectionpixmapitem.h | 4 ++++ include/ui/connectionslistitem.h | 7 +++++++ src/editor.cpp | 35 ++++++++++++++++++------------- src/mainwindow.cpp | 9 ++++---- src/project.cpp | 4 ---- src/ui/connectionpixmapitem.cpp | 27 ++++++++++++++++++------ src/ui/connectionslistitem.cpp | 18 ++++++++++++++++ 10 files changed, 93 insertions(+), 43 deletions(-) diff --git a/forms/connectionslistitem.ui b/forms/connectionslistitem.ui index a55c8d901..80e6beb54 100644 --- a/forms/connectionslistitem.ui +++ b/forms/connectionslistitem.ui @@ -6,8 +6,8 @@ 0 0 - 176 - 153 + 178 + 157 @@ -16,6 +16,9 @@ 0 + + QFrame::StyledPanel + diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui index 75ceeb2ec..c8bd50442 100644 --- a/forms/mainwindow.ui +++ b/forms/mainwindow.ui @@ -260,7 +260,7 @@ - 2 + 0 false @@ -769,8 +769,8 @@ 0 0 - 256 - 74 + 423 + 79 @@ -888,8 +888,8 @@ 0 0 - 256 - 74 + 423 + 79 @@ -990,10 +990,10 @@ - 0 + 8 0 - 91 - 74 + 411 + 446 @@ -1193,8 +1193,8 @@ 0 0 - 91 - 512 + 427 + 594 @@ -1413,8 +1413,8 @@ 0 0 - 93 - 460 + 382 + 699 diff --git a/include/project.h b/include/project.h index 49c0aaa8a..643f74da0 100644 --- a/include/project.h +++ b/include/project.h @@ -119,7 +119,6 @@ class Project : public QObject bool readMapGroups(); Map* addNewMapToGroup(QString, int, Map*, bool, bool); QString getNewMapName(); - bool isExistingMapName(const QString&); QString getProjectTitle(); QString readMapLayoutId(QString map_name); diff --git a/include/ui/connectionpixmapitem.h b/include/ui/connectionpixmapitem.h index c9b792265..419950035 100644 --- a/include/ui/connectionpixmapitem.h +++ b/include/ui/connectionpixmapitem.h @@ -33,6 +33,9 @@ class ConnectionPixmapItem : public QObject, public QGraphicsPixmapItem { bool getEditable(); void updateHighlight(bool selected); +private: + bool highlighted = false; + protected: QVariant itemChange(GraphicsItemChange change, const QVariant &value); void mousePressEvent(QGraphicsSceneMouseEvent*); @@ -42,6 +45,7 @@ class ConnectionPixmapItem : public QObject, public QGraphicsPixmapItem { void connectionItemSelected(ConnectionPixmapItem* connectionItem); void connectionItemDoubleClicked(ConnectionPixmapItem* connectionItem); void connectionMoved(MapConnection*); + void highlightChanged(bool highlighted); }; #endif // CONNECTIONPIXMAPITEM_H diff --git a/include/ui/connectionslistitem.h b/include/ui/connectionslistitem.h index ffa9ddcaa..75f7ba5f0 100644 --- a/include/ui/connectionslistitem.h +++ b/include/ui/connectionslistitem.h @@ -4,6 +4,7 @@ #include "mapconnection.h" #include +#include namespace Ui { class ConnectionsListItem; @@ -22,14 +23,20 @@ class ConnectionsListItem : public QFrame ~ConnectionsListItem(); void updateUI(); + void setSelected(bool selected); private: Ui::ConnectionsListItem *ui; MapConnection * const connection; + bool isSelected = false; + +protected: + void mousePressEvent(QMouseEvent *); signals: void edited(); void deleted(); + void selected(); private slots: void on_comboBox_Direction_currentTextChanged(const QString &direction); diff --git a/src/editor.cpp b/src/editor.cpp index 099223725..102493633 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -755,15 +755,29 @@ void Editor::addConnectionToList(ConnectionPixmapItem * connectionItem) { ConnectionsListItem *listItem = new ConnectionsListItem(ui->scrollAreaContents_ConnectionsList, connectionItem->connection, project->mapNames); ui->layout_ConnectionsList->insertWidget(ui->layout_ConnectionsList->count() - 1, listItem); // Insert above the vertical spacer + // Connect the pixmap item to the list item connect(connectionItem, &ConnectionPixmapItem::connectionMoved, listItem, &ConnectionsListItem::updateUI); - - // TODO: This is probably slower than necessary (we don't need a full redraw if we're just moving it) - // TODO: Handle mirroring + connect(connectionItem, &ConnectionPixmapItem::highlightChanged, listItem, &ConnectionsListItem::setSelected); + if (connectionItem == selected_connection_item) + listItem->setSelected(true); + + // Connect the list item to the pixmap item + connect(listItem, &ConnectionsListItem::selected, [this, connectionItem] { + if (connectionItem == selected_connection_item) { + // Already selected, no change + return; + } + // Deselect old connection and select new connection + if (selected_connection_item) selected_connection_item->updateHighlight(false); + selected_connection_item = connectionItem; + selected_connection_item->updateHighlight(true); + }); connect(listItem, &ConnectionsListItem::edited, [this, connectionItem] { + // TODO: This is probably slower than necessary (we don't need a full redraw if we're just moving it) + // TODO: Handle mirroring redrawConnection(connectionItem); emit editedMapData(); }); - connect(listItem, &ConnectionsListItem::deleted, [this, connectionItem] { removeConnection(connectionItem); }); @@ -834,16 +848,11 @@ void Editor::redrawConnection(ConnectionPixmapItem* connectionItem) { connectionItem->basePixmap = pixmap; QPoint pos = calculateConnectionPosition(connectionItem->connection, pixmap); - if (connectionItem == selected_connection_item) { - QPainter painter(&pixmap); - painter.setPen(QColor(255, 0, 255)); - painter.drawRect(0, 0, pixmap.width() - 1, pixmap.height() - 1); - painter.end(); - } + connectionItem->blockSignals(true); connectionItem->setPixmap(pixmap); + connectionItem->updateHighlight(connectionItem == selected_connection_item); connectionItem->initialX = pos.x(); connectionItem->initialY = pos.y(); - connectionItem->blockSignals(true); connectionItem->setX(pos.x()); connectionItem->setY(pos.y()); connectionItem->setZValue(-1); @@ -888,8 +897,6 @@ void Editor::onConnectionItemSelected(ConnectionPixmapItem* connectionItem) { selected_connection_item = connectionItem; for (ConnectionPixmapItem* item : connection_items) item->updateHighlight(item == selected_connection_item); - - // TODO: Handle the highlight done in redrawConnection? } // TODO: Inaccurate if there are multiple connections from the same map @@ -1851,7 +1858,7 @@ void Editor::toggleBorderVisibility(bool visible, bool enableScriptCallback) } void Editor::updateBorderVisibility() { - // On the connections tab, the border is always visible, and the connections can be edited. + // On the connections tab the border is always visible, and the connections can be edited. bool editingConnections = (ui->mainTabBar->currentIndex() == MainTab::Connections); bool visible = (editingConnections || ui->checkBox_ToggleBorder->isChecked()); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index cfea8e85f..77df41fa8 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2569,26 +2569,27 @@ void MainWindow::on_pushButton_ConfigureEncountersJSON_clicked() { void MainWindow::on_button_OpenDiveMap_clicked() { const QString mapName = ui->comboBox_DiveMap->currentText(); - if (editor->project->isExistingMapName(mapName)) + if (mapName != DYNAMIC_MAP_NAME && editor->project->mapNames.contains(mapName)) userSetMap(mapName, true); } void MainWindow::on_button_OpenEmergeMap_clicked() { const QString mapName = ui->comboBox_EmergeMap->currentText(); - if (editor->project->isExistingMapName(mapName)) + if (mapName != DYNAMIC_MAP_NAME && editor->project->mapNames.contains(mapName)) userSetMap(mapName, true); } // TODO: Mirror change to/from other maps void MainWindow::on_comboBox_DiveMap_currentTextChanged(const QString &mapName) { - if (editor->project->isExistingMapName(mapName)) { + // Include empty names as an update (user is deleting the connection) + if (mapName.isEmpty() || editor->project->mapNames.contains(mapName)) { editor->updateDiveMap(mapName); markMapEdited(); } } void MainWindow::on_comboBox_EmergeMap_currentTextChanged(const QString &mapName) { - if (editor->project->isExistingMapName(mapName)) { + if (mapName.isEmpty() || editor->project->mapNames.contains(mapName)) { editor->updateEmergeMap(mapName); markMapEdited(); } diff --git a/src/project.cpp b/src/project.cpp index c1c8f5c7d..c6550c6ad 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -1800,10 +1800,6 @@ QString Project::getNewMapName() { return newMapName; } -bool Project::isExistingMapName(const QString &mapName) { - return !mapName.isEmpty() && mapName != DYNAMIC_MAP_NAME && this->mapNames.contains(mapName); -} - Project::DataQualifiers Project::getDataQualifiers(QString text, QString label) { Project::DataQualifiers qualifiers; diff --git a/src/ui/connectionpixmapitem.cpp b/src/ui/connectionpixmapitem.cpp index 659074908..301fcfb64 100644 --- a/src/ui/connectionpixmapitem.cpp +++ b/src/ui/connectionpixmapitem.cpp @@ -56,13 +56,23 @@ bool ConnectionPixmapItem::getEditable() { return (this->flags() & ItemIsMovable) != 0; } +// TODO: Consider whether it still makes sense to highlight the "current" connection (given you can edit them at any point now) void ConnectionPixmapItem::updateHighlight(bool selected) { - bool editable = this->getEditable(); - int zValue = (selected || !editable) ? -1 : -2; - qreal opacity = (selected || !editable) ? 1 : 0.75; - this->setZValue(zValue); - this->render(opacity); - if (editable && selected) { + const int normalZ = -1; + const qreal normalOpacity = 1.0; + + // When editing is inactive the current selection is ignored, all connections should appear normal. + if (!this->getEditable()) { + this->setZValue(normalZ); + this->render(normalOpacity); + return; + } + + this->setZValue(selected ? normalZ : -2); + this->render(selected ? normalOpacity : 0.75); + + if (selected) { + // Draw highlight QPixmap pixmap = this->pixmap(); QPainter painter(&pixmap); painter.setPen(QColor(255, 0, 255)); @@ -70,6 +80,11 @@ void ConnectionPixmapItem::updateHighlight(bool selected) { painter.end(); this->setPixmap(pixmap); } + + // Let the list UI know if the selection highlight changes so it can update accordingly + if (this->highlighted != selected) + emit highlightChanged(selected); + this->highlighted = selected; } void ConnectionPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *) { diff --git a/src/ui/connectionslistitem.cpp b/src/ui/connectionslistitem.cpp index 246e83f4e..096407b6a 100644 --- a/src/ui/connectionslistitem.cpp +++ b/src/ui/connectionslistitem.cpp @@ -42,9 +42,25 @@ void ConnectionsListItem::updateUI() { ui->spinBox_Offset->setValue(this->connection->offset); } +// TODO: Frame shifts slightly when style changes +void ConnectionsListItem::setSelected(bool selected) { + if (selected == this->isSelected) + return; + this->isSelected = selected; + + this->setStyleSheet(selected ? ".ConnectionsListItem { border: 1px solid rgb(255, 0, 255); }" : ""); + if (selected) + emit this->selected(); +} + +void ConnectionsListItem::mousePressEvent(QMouseEvent *) { + this->setSelected(true); +} + void ConnectionsListItem::on_comboBox_Direction_currentTextChanged(const QString &direction) { this->connection->direction = direction; + this->setSelected(true); emit this->edited(); } @@ -52,6 +68,7 @@ void ConnectionsListItem::on_comboBox_Map_currentTextChanged(const QString &mapN { if (ui->comboBox_Map->findText(mapName) >= 0) { this->connection->map_name = mapName; + this->setSelected(true); emit this->edited(); } } @@ -59,6 +76,7 @@ void ConnectionsListItem::on_comboBox_Map_currentTextChanged(const QString &mapN void ConnectionsListItem::on_spinBox_Offset_valueChanged(int offset) { this->connection->offset = offset; + this->setSelected(true); emit this->edited(); } From f1cfc3c78ec43eae70f06892005e7b908588b32b Mon Sep 17 00:00:00 2001 From: GriffinR Date: Mon, 8 Jul 2024 11:44:23 -0400 Subject: [PATCH 09/30] Connections tab UI adjustments --- forms/connectionslistitem.ui | 26 ++++++++++-- forms/mainwindow.ui | 71 ++++++++++++++++++-------------- include/editor.h | 1 + include/mainwindow.h | 1 + include/ui/connectionslistitem.h | 4 +- src/editor.cpp | 20 +++++++-- src/mainwindow.cpp | 17 +++++--- src/ui/connectionslistitem.cpp | 7 +++- 8 files changed, 100 insertions(+), 47 deletions(-) diff --git a/forms/connectionslistitem.ui b/forms/connectionslistitem.ui index 80e6beb54..434c5a297 100644 --- a/forms/connectionslistitem.ui +++ b/forms/connectionslistitem.ui @@ -61,6 +61,9 @@ + + Remove this connection + ... @@ -71,13 +74,25 @@ - + + + Where the connected map should be positioned relative to the current map + + - + + + The name of the map to connect to the current map + + - + + + The number of spaces to move the connected map perpendicular to its connected direction + + @@ -87,6 +102,11 @@ QComboBox
noscrollcombobox.h
+ + NoScrollSpinBox + QSpinBox +
noscrollspinbox.h
+
diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui index c8bd50442..cdb4dcb89 100644 --- a/forms/mainwindow.ui +++ b/forms/mainwindow.ui @@ -2588,6 +2588,16 @@ 4 + + + + <html><head/><body><p>Destination map name when using <span style=" font-weight:600;">Dive</span>. If empty, no such connection will exist.</p></body></html> + + + true + + + @@ -2601,6 +2611,20 @@ + + + + Open the selected Emerge Map + + + ... + + + + :/icons/map_go.ico:/icons/map_go.ico + + + @@ -2628,27 +2652,6 @@ - - - - Open the selected Emerge Map - - - ... - - - - :/icons/map_go.ico:/icons/map_go.ico - - - - - - - Emerge Map - - - @@ -2656,16 +2659,6 @@ - - - - <html><head/><body><p>Destination map name when using <span style=" font-weight:600;">Dive</span>. If empty, no such connection will exist.</p></body></html> - - - true - - - @@ -2676,6 +2669,13 @@ + + + + Emerge Map + + +
@@ -2717,6 +2717,12 @@ + + + 230 + 0 + + QFrame::StyledPanel @@ -2740,6 +2746,9 @@ QFrame::NoFrame + + Qt::ScrollBarAlwaysOff + true diff --git a/include/editor.h b/include/editor.h index 4906a4e10..f9bbe0511 100644 --- a/include/editor.h +++ b/include/editor.h @@ -78,6 +78,7 @@ class Editor : public QObject void updateConnectionOffset(int offset); void addNewConnection(); void removeConnection(ConnectionPixmapItem* connectionItem); + void removeSelectedConnection(); void addNewWildMonGroup(QWidget *window); void deleteWildMonGroup(); void updateDiveMap(QString mapName); diff --git a/include/mainwindow.h b/include/mainwindow.h index 121fe1cdb..16eee651f 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -217,6 +217,7 @@ private slots: void on_actionMove_triggered(); void on_actionMap_Shift_triggered(); + void onDeleteKeyPressed(); void on_toolButton_deleteObject_clicked(); void addNewEvent(Event::Type type); diff --git a/include/ui/connectionslistitem.h b/include/ui/connectionslistitem.h index 75f7ba5f0..ce8a01635 100644 --- a/include/ui/connectionslistitem.h +++ b/include/ui/connectionslistitem.h @@ -32,11 +32,13 @@ class ConnectionsListItem : public QFrame protected: void mousePressEvent(QMouseEvent *); + void mouseDoubleClickEvent(QMouseEvent *); signals: void edited(); - void deleted(); + void deleteRequested(); void selected(); + void doubleClicked(); private slots: void on_comboBox_Direction_currentTextChanged(const QString &direction); diff --git a/src/editor.cpp b/src/editor.cpp index 102493633..98dca0463 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -729,10 +729,12 @@ void Editor::populateConnectionsList() { ui->comboBox_DiveMap->clear(); ui->comboBox_DiveMap->addItems(project->mapNames); ui->comboBox_DiveMap->setCurrentText(""); + ui->comboBox_DiveMap->lineEdit()->setClearButtonEnabled(true); ui->comboBox_EmergeMap->clear(); ui->comboBox_EmergeMap->addItems(project->mapNames); ui->comboBox_EmergeMap->setCurrentText(""); + ui->comboBox_EmergeMap->lineEdit()->setClearButtonEnabled(true); for (MapConnection* connection : map->connections) { if (connection->direction == "dive") { @@ -750,7 +752,6 @@ void Editor::populateConnectionsList() { addConnectionToList(item); } -// TODO: Don't allow splitter resizing to shrink list items to the point where horizontal scroll is needed void Editor::addConnectionToList(ConnectionPixmapItem * connectionItem) { ConnectionsListItem *listItem = new ConnectionsListItem(ui->scrollAreaContents_ConnectionsList, connectionItem->connection, project->mapNames); ui->layout_ConnectionsList->insertWidget(ui->layout_ConnectionsList->count() - 1, listItem); // Insert above the vertical spacer @@ -758,11 +759,12 @@ void Editor::addConnectionToList(ConnectionPixmapItem * connectionItem) { // Connect the pixmap item to the list item connect(connectionItem, &ConnectionPixmapItem::connectionMoved, listItem, &ConnectionsListItem::updateUI); connect(connectionItem, &ConnectionPixmapItem::highlightChanged, listItem, &ConnectionsListItem::setSelected); + connect(connectionItem, &ConnectionPixmapItem::destroyed, listItem, &ConnectionsListItem::deleteLater); if (connectionItem == selected_connection_item) listItem->setSelected(true); - // Connect the list item to the pixmap item connect(listItem, &ConnectionsListItem::selected, [this, connectionItem] { + // When the list item is selected, select the pixmap too if (connectionItem == selected_connection_item) { // Already selected, no change return; @@ -773,17 +775,23 @@ void Editor::addConnectionToList(ConnectionPixmapItem * connectionItem) { selected_connection_item->updateHighlight(true); }); connect(listItem, &ConnectionsListItem::edited, [this, connectionItem] { + // When the list item is edited update the pixmap // TODO: This is probably slower than necessary (we don't need a full redraw if we're just moving it) // TODO: Handle mirroring redrawConnection(connectionItem); emit editedMapData(); }); - connect(listItem, &ConnectionsListItem::deleted, [this, connectionItem] { + connect(listItem, &ConnectionsListItem::deleteRequested, [this, connectionItem] { + // 'Remove' button has been clicked. Delete the pixmap. + // The list item will be deleted via the earlier connection to the pixmap's 'destroyed' signal. removeConnection(connectionItem); }); + connect(listItem, &ConnectionsListItem::doubleClicked, [this, connectionItem] { + // Double clicking the list item opens the connected map + emit connectionItemDoubleClicked(connectionItem->connection->map_name, map->name); + }); } -// TODO: Connect to Delete key for selected connection void Editor::removeConnection(ConnectionPixmapItem* connectionItem) { if (!connectionItem) return; @@ -806,6 +814,10 @@ void Editor::removeConnection(ConnectionPixmapItem* connectionItem) { emit editedMapData(); } +void Editor::removeSelectedConnection() { + removeConnection(selected_connection_item); +} + QPoint Editor::calculateConnectionPosition(const MapConnection *connection, const QPixmap &pixmap) { int x = 0, y = 0; const int mWidth = 16, mHeight = 16; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 77df41fa8..7de1c54b5 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -150,9 +150,9 @@ void MainWindow::initExtraShortcuts() { shortcutDuplicate_Events->setWhatsThis("Duplicate Selected Event(s)"); auto *shortcutDelete_Object = new Shortcut( - {QKeySequence("Del"), QKeySequence("Backspace")}, this, SLOT(on_toolButton_deleteObject_clicked())); + {QKeySequence("Del"), QKeySequence("Backspace")}, this, SLOT(onDeleteKeyPressed())); shortcutDelete_Object->setObjectName("shortcutDelete_Object"); - shortcutDelete_Object->setWhatsThis("Delete Selected Event(s)"); + shortcutDelete_Object->setWhatsThis("Delete Selected Item(s)"); auto *shortcutToggle_Border = new Shortcut(QKeySequence(), ui->checkBox_ToggleBorder, SLOT(toggle())); shortcutToggle_Border->setObjectName("shortcutToggle_Border"); @@ -2229,11 +2229,16 @@ void MainWindow::on_horizontalSlider_CollisionTransparency_valueChanged(int valu this->editor->collision_item->draw(true); } -void MainWindow::on_toolButton_deleteObject_clicked() { - if (ui->mainTabBar->currentIndex() != MainTab::Events) { - // do not delete an event when not on event tab - return; +void MainWindow::onDeleteKeyPressed() { + auto tab = ui->mainTabBar->currentIndex(); + if (tab == MainTab::Events) { + on_toolButton_deleteObject_clicked(); + } else if (tab == MainTab::Connections) { + if (editor) editor->removeSelectedConnection(); } +} + +void MainWindow::on_toolButton_deleteObject_clicked() { if (editor && editor->selected_events) { if (editor->selected_events->length()) { DraggablePixmapItem *nextSelectedEvent = nullptr; diff --git a/src/ui/connectionslistitem.cpp b/src/ui/connectionslistitem.cpp index 096407b6a..b9f456a39 100644 --- a/src/ui/connectionslistitem.cpp +++ b/src/ui/connectionslistitem.cpp @@ -57,6 +57,10 @@ void ConnectionsListItem::mousePressEvent(QMouseEvent *) { this->setSelected(true); } +void ConnectionsListItem::mouseDoubleClickEvent(QMouseEvent *) { + emit doubleClicked(); +} + void ConnectionsListItem::on_comboBox_Direction_currentTextChanged(const QString &direction) { this->connection->direction = direction; @@ -82,6 +86,5 @@ void ConnectionsListItem::on_spinBox_Offset_valueChanged(int offset) void ConnectionsListItem::on_button_Delete_clicked() { - this->deleteLater(); - emit this->deleted(); + emit this->deleteRequested(); } From 1e09d08c9cdeaebad47914afc32477f946fe2a38 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Mon, 8 Jul 2024 16:01:30 -0400 Subject: [PATCH 10/30] Reimplement connection mirroring --- include/core/map.h | 1 - include/core/mapconnection.h | 15 +- include/editor.h | 24 +- include/mainwindow.h | 2 +- include/ui/connectionpixmapitem.h | 2 +- include/ui/connectionslistitem.h | 13 +- src/core/map.cpp | 4 +- src/core/mapconnection.cpp | 43 +++ src/editor.cpp | 490 ++++++++++++++++++------------ src/mainwindow.cpp | 34 +-- src/ui/connectionpixmapitem.cpp | 4 +- src/ui/connectionslistitem.cpp | 24 +- 12 files changed, 405 insertions(+), 251 deletions(-) create mode 100644 src/core/mapconnection.cpp diff --git a/include/core/map.h b/include/core/map.h index c214fbb76..a6f6fa1ca 100644 --- a/include/core/map.h +++ b/include/core/map.h @@ -128,7 +128,6 @@ class Map : public QObject void setNewBorderDimensionsBlockdata(int newWidth, int newHeight); signals: - void mapChanged(Map *map); void modified(); void mapDimensionsChanged(const QSize &size); void mapNeedsRedrawing(); diff --git a/include/core/mapconnection.h b/include/core/mapconnection.h index 11aa0e595..474be5b10 100644 --- a/include/core/mapconnection.h +++ b/include/core/mapconnection.h @@ -5,6 +5,8 @@ #include #include +class Map; + class MapConnection { public: QString direction; @@ -12,12 +14,15 @@ class MapConnection { QString map_name; }; -inline bool operator==(const MapConnection &c1, const MapConnection &c2) { - return c1.map_name == c2.map_name; -} +struct MapConnectionMirror { + MapConnection * connection = nullptr; + Map * map = nullptr; +}; -inline uint qHash(const MapConnection &key) { - return qHash(key.map_name); +inline bool operator==(const MapConnection &c1, const MapConnection &c2) { + return c1.direction == c2.direction && + c1.offset == c2.offset && + c1.map_name == c2.map_name; } #endif // MAPCONNECTION_H diff --git a/include/editor.h b/include/editor.h index f9bbe0511..f0b54b699 100644 --- a/include/editor.h +++ b/include/editor.h @@ -75,9 +75,10 @@ class Editor : public QObject void setEditingConnections(); void setMapEditingButtonsEnabled(bool enabled); void setConnectionsVisibility(bool visible); - void updateConnectionOffset(int offset); void addNewConnection(); - void removeConnection(ConnectionPixmapItem* connectionItem); + void addConnection(Map* map, MapConnection* connection); + void removeConnection(Map* map, MapConnection* connection); + void removeConnectionItem(ConnectionPixmapItem* connectionItem, bool removeMirror = true); void removeSelectedConnection(); void addNewWildMonGroup(QWidget *window); void deleteWildMonGroup(); @@ -168,17 +169,16 @@ public slots: void updateBorderVisibility(); QPoint calculateConnectionPosition(const MapConnection *connection, const QPixmap &pixmap); - void redrawConnection(ConnectionPixmapItem* connectionItem); + void updateConnectionItem(ConnectionPixmapItem* connectionItem); + void updateConnectionItemPos(ConnectionPixmapItem* connectionItem); void createConnectionItem(MapConnection* connection); void populateConnectionsList(); void addConnectionToList(ConnectionPixmapItem* connection); void updateDiveEmergeMap(QString mapName, QString direction); - void onConnectionOffsetChanged(int newOffset); - void removeMirroredConnection(MapConnection*); - void updateMirroredConnectionOffset(MapConnection*); - void updateMirroredConnectionDirection(MapConnection*, QString); - void updateMirroredConnectionMap(MapConnection*, QString); - void updateMirroredConnection(MapConnection*, QString, QString, bool isDelete = false); + bool shouldMirrorConnection(const MapConnection &source); + MapConnectionMirror getMirroredConnection(const MapConnection&); + void addMirroredConnection(const MapConnection&); + void removeMirroredConnection(const MapConnection&); void updateEncounterFields(EncounterFields newFields); QString getMovementPermissionText(uint16_t collision, uint16_t elevation); QString getMetatileDisplayMessage(uint16_t metatileId); @@ -194,7 +194,9 @@ private slots: void setStraightPathCursorMode(QGraphicsSceneMouseEvent *event); void mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item); void mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixmapItem *item); - void onConnectionMoved(MapConnection*); + void setConnectionOffset(MapConnection *connection, int offset); + void setConnectionMap(MapConnection *connection, const QString &mapName); + void setConnectionDirection(MapConnection *connection, const QString &direction); void onConnectionItemSelected(ConnectionPixmapItem* connectionItem); void onHoveredMovementPermissionChanged(uint16_t, uint16_t); void onHoveredMovementPermissionCleared(); @@ -215,7 +217,7 @@ private slots: void warpEventDoubleClicked(QString, int, Event::Group); void currentMetatilesSelectionChanged(); void mapRulerStatusChanged(const QString &); - void editedMapData(); + void editedMapData(Map*); void tilesetUpdated(QString); }; diff --git a/include/mainwindow.h b/include/mainwindow.h index 16eee651f..14a5e9cdb 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -178,7 +178,6 @@ private slots: void paste(); void onConnectionItemDoubleClicked(QString, QString); - void onMapChanged(Map *map); void onMapNeedsRedrawing(); void onTilesetsSaved(QString, QString); void onWildMonDataChanged(); @@ -366,6 +365,7 @@ private slots: void clickToolButtonFromEditMode(QString editMode); void markMapEdited(); + void markMapEdited(Map*); void showWindowTitle(); void initWindow(); diff --git a/include/ui/connectionpixmapitem.h b/include/ui/connectionpixmapitem.h index 419950035..f0e00ae14 100644 --- a/include/ui/connectionpixmapitem.h +++ b/include/ui/connectionpixmapitem.h @@ -44,7 +44,7 @@ class ConnectionPixmapItem : public QObject, public QGraphicsPixmapItem { signals: void connectionItemSelected(ConnectionPixmapItem* connectionItem); void connectionItemDoubleClicked(ConnectionPixmapItem* connectionItem); - void connectionMoved(MapConnection*); + void connectionMoved(MapConnection *, int newOffset); void highlightChanged(bool highlighted); }; diff --git a/include/ui/connectionslistitem.h b/include/ui/connectionslistitem.h index ce8a01635..a2ce2c169 100644 --- a/include/ui/connectionslistitem.h +++ b/include/ui/connectionslistitem.h @@ -19,15 +19,16 @@ class ConnectionsListItem : public QFrame Q_OBJECT public: - explicit ConnectionsListItem(QWidget *parent, MapConnection * connection, const QStringList &mapNames); + explicit ConnectionsListItem(QWidget *parent, MapConnection *connection, const QStringList &mapNames); ~ConnectionsListItem(); void updateUI(); void setSelected(bool selected); + MapConnection * connection; + private: Ui::ConnectionsListItem *ui; - MapConnection * const connection; bool isSelected = false; protected: @@ -35,10 +36,12 @@ class ConnectionsListItem : public QFrame void mouseDoubleClickEvent(QMouseEvent *); signals: - void edited(); - void deleteRequested(); + void editedOffset(MapConnection *connection, int newOffset); + void editedDirection(MapConnection *connection, const QString &direction); + void editedMapName(MapConnection *connection, const QString &mapName); + void removed(); void selected(); - void doubleClicked(); + void doubleClicked(const QString &mapName); private slots: void on_comboBox_Direction_currentTextChanged(const QString &direction); diff --git a/src/core/map.cpp b/src/core/map.cpp index a0ecf404e..463b9341b 100644 --- a/src/core/map.cpp +++ b/src/core/map.cpp @@ -304,8 +304,8 @@ void Map::setDimensions(int newWidth, int newHeight, bool setNewBlockdata, bool Scripting::cb_MapResized(oldWidth, oldHeight, newWidth, newHeight); } - emit mapChanged(this); emit mapDimensionsChanged(QSize(getWidth(), getHeight())); + modify(); } void Map::setBorderDimensions(int newWidth, int newHeight, bool setNewBlockdata, bool enableScriptCallback) { @@ -322,7 +322,7 @@ void Map::setBorderDimensions(int newWidth, int newHeight, bool setNewBlockdata, Scripting::cb_BorderResized(oldWidth, oldHeight, newWidth, newHeight); } - emit mapChanged(this); + modify(); } void Map::openScript(QString label) { diff --git a/src/core/mapconnection.cpp b/src/core/mapconnection.cpp new file mode 100644 index 000000000..ebf485929 --- /dev/null +++ b/src/core/mapconnection.cpp @@ -0,0 +1,43 @@ +#include "mapconnection.h" +#include "map.h" + +void MapConnection::setDirection(const QString & direction) { + if (direction == m_direction) + return; + auto before = m_direction; + m_direction = direction; + emit directionChanged(before, m_direction); +} + +void MapConnection::setOffset(int offset) { + if (offset == m_offset) + return; + auto before = m_offset; + m_offset = offset; + emit offsetChanged(before, m_offset); +} + +void MapConnection::setMapName(const QString &mapName) { + if (mapName == m_mapName) + return; + auto before = m_mapName; + m_mapName = mapName; + emit mapNameChanged(before, m_mapName); +} +/* +static QString MapConnection::oppositeDirection(const QString &direction) { + static const QMap oppositeDirections = { + {"up", "down"}, {"down", "up"}, + {"right", "left"}, {"left", "right"}, + {"dive", "emerge"}, {"emerge", "dive"} + }; + return oppositeDirections.value(direction); +} + +static MapConnection* MapConnection::getMirror(const MapConnection*, const Map*) { + +} + +static MapConnection* MapConnection::newMirror(const MapConnection*) { + +}*/ diff --git a/src/editor.cpp b/src/editor.cpp index 98dca0463..b88ac4cf8 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -726,14 +726,14 @@ void Editor::populateConnectionsList() { const QSignalBlocker blocker1(ui->comboBox_DiveMap); const QSignalBlocker blocker2(ui->comboBox_EmergeMap); + // TODO: We should probably just be doing this once, and updating the items when new maps are created. ui->comboBox_DiveMap->clear(); - ui->comboBox_DiveMap->addItems(project->mapNames); - ui->comboBox_DiveMap->setCurrentText(""); - ui->comboBox_DiveMap->lineEdit()->setClearButtonEnabled(true); - ui->comboBox_EmergeMap->clear(); + ui->comboBox_DiveMap->addItems(project->mapNames); ui->comboBox_EmergeMap->addItems(project->mapNames); + ui->comboBox_DiveMap->setCurrentText(""); ui->comboBox_EmergeMap->setCurrentText(""); + ui->comboBox_DiveMap->lineEdit()->setClearButtonEnabled(true); ui->comboBox_EmergeMap->lineEdit()->setClearButtonEnabled(true); for (MapConnection* connection : map->connections) { @@ -745,24 +745,22 @@ void Editor::populateConnectionsList() { } // Clear any existing connections in list - for (auto w : ui->scrollAreaContents_ConnectionsList->findChildren()) - w->deleteLater(); + for (auto listItem : ui->scrollAreaContents_ConnectionsList->findChildren()) + listItem->deleteLater(); for (auto item :connection_items) addConnectionToList(item); } +// TODO: When connecting a map to itself the new mirror is shaded incorrectly +// TODO: Set default focus to the selected connection, right now it defaults to the dive combo box + void Editor::addConnectionToList(ConnectionPixmapItem * connectionItem) { ConnectionsListItem *listItem = new ConnectionsListItem(ui->scrollAreaContents_ConnectionsList, connectionItem->connection, project->mapNames); ui->layout_ConnectionsList->insertWidget(ui->layout_ConnectionsList->count() - 1, listItem); // Insert above the vertical spacer - // Connect the pixmap item to the list item - connect(connectionItem, &ConnectionPixmapItem::connectionMoved, listItem, &ConnectionsListItem::updateUI); + // Sync the selection highlight between the list UI and the graphical map connection connect(connectionItem, &ConnectionPixmapItem::highlightChanged, listItem, &ConnectionsListItem::setSelected); - connect(connectionItem, &ConnectionPixmapItem::destroyed, listItem, &ConnectionsListItem::deleteLater); - if (connectionItem == selected_connection_item) - listItem->setSelected(true); - connect(listItem, &ConnectionsListItem::selected, [this, connectionItem] { // When the list item is selected, select the pixmap too if (connectionItem == selected_connection_item) { @@ -774,32 +772,113 @@ void Editor::addConnectionToList(ConnectionPixmapItem * connectionItem) { selected_connection_item = connectionItem; selected_connection_item->updateHighlight(true); }); - connect(listItem, &ConnectionsListItem::edited, [this, connectionItem] { - // When the list item is edited update the pixmap - // TODO: This is probably slower than necessary (we don't need a full redraw if we're just moving it) - // TODO: Handle mirroring - redrawConnection(connectionItem); - emit editedMapData(); + if (connectionItem == selected_connection_item) + listItem->setSelected(true); + + // Sync edits to 'offset' between the list UI and the graphical map connection + connect(connectionItem, &ConnectionPixmapItem::connectionMoved, [this, listItem](MapConnection* connection, int offset) { + setConnectionOffset(connection, offset); + listItem->updateUI(); + }); + connect (listItem, &ConnectionsListItem::editedOffset, [this, connectionItem](MapConnection* connection, int offset) { + setConnectionOffset(connection, offset); + updateConnectionItemPos(connectionItem); + }); + + // Sync edits to 'direction' or 'map' between the list UI and the graphical map connection. + // These are 1-way because the direction and map cannot be edited graphically, only via the list UI. + connect(listItem, &ConnectionsListItem::editedDirection, [this, connectionItem](MapConnection* connection, QString direction) { + setConnectionDirection(connection, direction); + updateConnectionItem(connectionItem); // TODO: Simplify? }); - connect(listItem, &ConnectionsListItem::deleteRequested, [this, connectionItem] { + connect(listItem, &ConnectionsListItem::editedMapName, [this, connectionItem](MapConnection* connection, QString mapName) { + setConnectionMap(connection, mapName); + updateConnectionItem(connectionItem); + }); + + // Sync deleting the map connection + connect(connectionItem, &ConnectionPixmapItem::destroyed, listItem, &ConnectionsListItem::deleteLater); + connect(listItem, &ConnectionsListItem::removed, [this, connectionItem] { // 'Remove' button has been clicked. Delete the pixmap. - // The list item will be deleted via the earlier connection to the pixmap's 'destroyed' signal. - removeConnection(connectionItem); + // The list item will be deleted via the above connection to the pixmap's 'destroyed' signal. + removeConnectionItem(connectionItem); }); - connect(listItem, &ConnectionsListItem::doubleClicked, [this, connectionItem] { - // Double clicking the list item opens the connected map - emit connectionItemDoubleClicked(connectionItem->connection->map_name, map->name); + + // Double clicking the list item opens the connected map + connect(listItem, &ConnectionsListItem::doubleClicked, [this](QString connectedMapName) { + emit connectionItemDoubleClicked(connectedMapName, map->name); }); } -void Editor::removeConnection(ConnectionPixmapItem* connectionItem) { + +void Editor::addNewConnection() { + // Find direction with least number of connections. + QMap directionCounts = QMap({{"up", 0}, {"right", 0}, {"down", 0}, {"left", 0}}); + for (MapConnection* connection : map->connections) { + directionCounts[connection->direction]++; + } + QString minDirection = "up"; + int minCount = INT_MAX; + for (QString direction : directionCounts.keys()) { + if (directionCounts[direction] < minCount) { + minDirection = direction; + minCount = directionCounts[direction]; + } + } + + // Prefer not to connect the map to itself (we have to if it's the only map). + // TODO: Is this more or less sensible than a connection with no map name + QString defaultMapName = project->mapNames.first(); + if (defaultMapName == map->name && project->mapNames.length() > 1) { + defaultMapName = project->mapNames.at(1); + } + + MapConnection* newConnection = new MapConnection; + newConnection->direction = minDirection; + newConnection->offset = 0; + newConnection->map_name = defaultMapName; + addConnection(map, newConnection); + onConnectionItemSelected(connection_items.last()); + addMirroredConnection(*newConnection); +} + +void Editor::addConnection(Map* map, MapConnection * connection) { + map->connections.append(connection); + if (map == this->map) { + // Adding a connection to the current map, we need to display it visually. + // Note that for the Dive/Emerge combo boxes this is normally redundant + // as the user can only create these by having already set the text, + // *except* in the case where they're connecting a map to itself. + if (connection->direction == "dive") { + const QSignalBlocker blocker(ui->comboBox_DiveMap); + ui->comboBox_DiveMap->setCurrentText(connection->map_name); + } else if (connection->direction == "emerge") { + const QSignalBlocker blocker(ui->comboBox_EmergeMap); + ui->comboBox_EmergeMap->setCurrentText(connection->map_name); + } else { + createConnectionItem(connection); + addConnectionToList(connection_items.last()); + } + } + emit editedMapData(map); +} + +void Editor::removeConnectionItem(ConnectionPixmapItem* connectionItem, bool removeMirror) { if (!connectionItem) return; - map->connections.removeOne(connectionItem->connection); - connection_items.removeOne(connectionItem); - //removeMirroredConnection(connectionItem->connection); // TODO + if (connectionItem->connection) { + if (removeMirror) { + // If a map is connected to itself and we delete the connection then this function + // will be called twice, once for the target of the delete and once for its mirror. + // We only want to try deleting the mirror once, on the first call (because the mirror + // of the mirror is the original target again, and we already deleted it). + removeMirroredConnection(*connectionItem->connection); + } + removeConnection(map, connectionItem->connection); + } + connection_items.removeOne(connectionItem); if (connectionItem->scene()) connectionItem->scene()->removeItem(connectionItem); @@ -808,14 +887,136 @@ void Editor::removeConnection(ConnectionPixmapItem* connectionItem) { if (!connection_items.isEmpty()) onConnectionItemSelected(connection_items.first()); } - - delete connectionItem->connection; delete connectionItem; - emit editedMapData(); +} + +void Editor::removeConnection(Map* map, MapConnection* connection) { + if (!map) + return; + map->connections.removeOne(connection); + delete connection; + emit editedMapData(map); } void Editor::removeSelectedConnection() { - removeConnection(selected_connection_item); + removeConnectionItem(selected_connection_item); +} + +static const QMap oppositeDirections = { + {"up", "down"}, {"down", "up"}, + {"right", "left"}, {"left", "right"}, + {"dive", "emerge"}, {"emerge", "dive"} +}; + +bool Editor::shouldMirrorConnection(const MapConnection &source) { + // The current map's connections are not mirrored if the user has disabled this setting, + // unless it's a connection to itself (which is mirrored by definition). + // TODO: Confirm in-game representation of the above fact is accurate. + return ui->checkBox_MirrorConnections->isChecked() || (map && map->name == source.map_name); +} + +MapConnectionMirror Editor::getMirroredConnection(const MapConnection &source) { + MapConnectionMirror mirror; + if (!map || !shouldMirrorConnection(source)) + return mirror; + + // Note: It's possible (and ok) for mirror.map == this->map + mirror.map = project->getMap(source.map_name); + if (!mirror.map) + return mirror; + + MapConnection target; + target.direction = oppositeDirections.value(source.direction); + target.map_name = map->name; + target.offset = -source.offset; + + // Find the matching connection in the connected map. + for (auto connection : mirror.map->connections) { + if (*connection == target) { + mirror.connection = connection; + break; + } + } + return mirror; +} + +void Editor::addMirroredConnection(const MapConnection &source) { + MapConnectionMirror mirror = getMirroredConnection(source); + if (!mirror.map) + return; + + mirror.connection = new MapConnection; + mirror.connection->direction = oppositeDirections.value(source.direction); + mirror.connection->map_name = map->name; + mirror.connection->offset = -source.offset; + + addConnection(mirror.map, mirror.connection); +} + +void Editor::removeMirroredConnection(const MapConnection &source) { + MapConnectionMirror mirror = getMirroredConnection(source); + if (!mirror.map || !mirror.connection) + return; + + if (map == mirror.map) { + // The connection to delete is displayed on the currently-opened map, we need to delete it visually as well. + if (source.direction == "dive") { + const QSignalBlocker blocker(ui->comboBox_DiveMap); + ui->comboBox_DiveMap->setCurrentText(""); + } else if (source.direction == "emerge") { + const QSignalBlocker blocker(ui->comboBox_EmergeMap); + ui->comboBox_EmergeMap->setCurrentText(""); + } else { + // Find and delete the matching connection graphics + for (auto item :connection_items) { + if (item->connection == mirror.connection) { + removeConnectionItem(item, false); + return; + } + } + } + } + removeConnection(mirror.map, mirror.connection); +} + +void Editor::updateDiveMap(QString mapName) { + updateDiveEmergeMap(mapName, "dive"); +} + +void Editor::updateEmergeMap(QString mapName) { + updateDiveEmergeMap(mapName, "emerge"); +} + +void Editor::updateDiveEmergeMap(QString mapName, QString direction) { + if (!mapName.isEmpty() && !project->mapNamesToMapConstants.contains(mapName)) { + logError(QString("Invalid %1 connection map name: '%2'").arg(direction).arg(mapName)); + return; + } + + // TODO: How does the game handle having multiple Dive/Emerge maps. Should we support this? + MapConnection* connection = nullptr; + for (MapConnection* conn : map->connections) { + if (conn->direction == direction) { + connection = conn; + break; + } + } + + // We (lazily) always update the connection by deleting the old one and creating a new one. + // Unlike the displayed connections which can be updated rapidly by click+drag, this isn't + // really an issue for Dive/Emerge maps. + if (connection) { + removeMirroredConnection(*connection); + removeConnection(map, connection); + } + if (!mapName.isEmpty() && mapName != DYNAMIC_MAP_NAME) { + connection = new MapConnection; + connection->direction = direction; + connection->offset = 0; + connection->map_name = mapName; + addConnection(map, connection); + addMirroredConnection(*connection); + } } QPoint Editor::calculateConnectionPosition(const MapConnection *connection, const QPixmap &pixmap) { @@ -837,7 +1038,7 @@ QPoint Editor::calculateConnectionPosition(const MapConnection *connection, cons return QPoint(x, y); } -void Editor::redrawConnection(ConnectionPixmapItem* connectionItem) { +void Editor::updateConnectionItem(ConnectionPixmapItem* connectionItem) { if (!connectionItem || !connectionItem->connection) return; @@ -870,36 +1071,80 @@ void Editor::redrawConnection(ConnectionPixmapItem* connectionItem) { connectionItem->setZValue(-1); connectionItem->blockSignals(false); - // TODO: - //updateMirroredConnectionMap(selected_connection_item->connection, originalMapName); - maskNonVisibleConnectionTiles(); } -// TODO: Generalize, maybe use in addConnectionToList connection instead of full render -void Editor::updateConnectionOffset(int offset) { - /*if (!selected_connection_item) +void Editor::updateConnectionItemPos(ConnectionPixmapItem* connectionItem) { + if (!connectionItem || !connectionItem->connection) return; - selected_connection_item->blockSignals(true); - selected_connection_item->connection->offset = offset; - if (selected_connection_item->connection->direction == "up" || selected_connection_item->connection->direction == "down") { - selected_connection_item->setX(selected_connection_item->initialX + (offset - selected_connection_item->initialOffset) * 16); - } else if (selected_connection_item->connection->direction == "left" || selected_connection_item->connection->direction == "right") { - selected_connection_item->setY(selected_connection_item->initialY + (offset - selected_connection_item->initialOffset) * 16); + MapConnection *connection = connectionItem->connection; + connectionItem->blockSignals(true); + if (connection->direction == "up" || connection->direction == "down") { + connectionItem->setX(connectionItem->initialX + (connection->offset - connectionItem->initialOffset) * 16); + } else if (connection->direction == "left" || connection->direction == "right") { + connectionItem->setY(connectionItem->initialY + (connection->offset - connectionItem->initialOffset) * 16); } - selected_connection_item->blockSignals(false); - updateMirroredConnectionOffset(selected_connection_item->connection); - maskNonVisibleConnectionTiles();*/ + connectionItem->blockSignals(false); + maskNonVisibleConnectionTiles(); } -void Editor::onConnectionMoved(MapConnection* connection) { - // TODO: - //updateMirroredConnectionOffset(connection); +void Editor::setConnectionOffset(MapConnection *connection, int offset) { + if (!connection || !map || connection->offset == offset) + return; + + MapConnectionMirror mirror = getMirroredConnection(*connection); + if (mirror.connection && mirror.map) { + mirror.connection->offset = -offset; + if (mirror.map != map) { + emit editedMapData(mirror.map); + } else { + // The mirror is displayed on the current map, update its graphics + for (auto item :connection_items) { + if (item->connection == mirror.connection) { + updateConnectionItemPos(item); + break; + } + } + // TODO: We should be signaling to the list item from the pixmap item, rather than searching for it. + for (auto listItem : ui->scrollAreaContents_ConnectionsList->findChildren()) { + if (listItem->connection == mirror.connection){ + listItem->updateUI(); + break; + } + } + } + } + // TODO: If there's no mirror but there should be we're not creating one + + connection->offset = offset; + emit editedMapData(map); // TODO: This is likely the source of the visual masking bug while dragging (this happens after the move) maskNonVisibleConnectionTiles(); - emit editedMapData(); +} + +void Editor::setConnectionMap(MapConnection *connection, const QString &mapName) { + if (!connection || !map || connection->map_name == mapName) + return; + + removeMirroredConnection(*connection); + connection->map_name = mapName; + addMirroredConnection(*connection); + + emit editedMapData(map); +} + +void Editor::setConnectionDirection(MapConnection *connection, const QString &direction) { + if (!connection || !map || connection->direction == direction) + return; + + // TODO: Lazy + removeMirroredConnection(*connection); + connection->direction = direction; + addMirroredConnection(*connection); + + emit editedMapData(map); } void Editor::onConnectionItemSelected(ConnectionPixmapItem* connectionItem) { @@ -1579,7 +1824,6 @@ void Editor::createConnectionItem(MapConnection* connection) { item->setZValue(-1); scene->addItem(item); - connect(item, &ConnectionPixmapItem::connectionMoved, this, &Editor::onConnectionMoved); connect(item, &ConnectionPixmapItem::connectionItemSelected, this, &Editor::onConnectionItemSelected); connect(item, &ConnectionPixmapItem::connectionItemDoubleClicked, [this, item] { emit this->connectionItemDoubleClicked(item->connection->map_name, map->name); @@ -1703,144 +1947,6 @@ void Editor::displayMapGrid() { connect(ui->checkBox_ToggleGrid, &QCheckBox::toggled, this, &Editor::onToggleGridClicked); } -void Editor::addNewConnection() { - // Find direction with least number of connections. - QMap directionCounts = QMap({{"up", 0}, {"right", 0}, {"down", 0}, {"left", 0}}); - for (MapConnection* connection : map->connections) { - directionCounts[connection->direction]++; - } - QString minDirection = "up"; - int minCount = INT_MAX; - for (QString direction : directionCounts.keys()) { - if (directionCounts[direction] < minCount) { - minDirection = direction; - minCount = directionCounts[direction]; - } - } - - // Don't connect the map to itself. - QString defaultMapName = project->mapNames.first(); - if (defaultMapName == map->name) { - defaultMapName = project->mapNames.value(1); - } - - MapConnection* newConnection = new MapConnection; - newConnection->direction = minDirection; - newConnection->offset = 0; - newConnection->map_name = defaultMapName; - map->connections.append(newConnection); - createConnectionItem(newConnection); - addConnectionToList(connection_items.last()); - onConnectionItemSelected(connection_items.last()); - - updateMirroredConnection(newConnection, newConnection->direction, newConnection->map_name); -} - -void Editor::updateMirroredConnectionOffset(MapConnection* connection) { - updateMirroredConnection(connection, connection->direction, connection->map_name); -} -void Editor::updateMirroredConnectionDirection(MapConnection* connection, QString originalDirection) { - updateMirroredConnection(connection, originalDirection, connection->map_name); -} -void Editor::updateMirroredConnectionMap(MapConnection* connection, QString originalMapName) { - updateMirroredConnection(connection, connection->direction, originalMapName); -} -void Editor::removeMirroredConnection(MapConnection* connection) { - updateMirroredConnection(connection, connection->direction, connection->map_name, true); -} -void Editor::updateMirroredConnection(MapConnection* connection, QString originalDirection, QString originalMapName, bool isDelete) { - if (!ui->checkBox_MirrorConnections->isChecked()) - return; - Map* otherMap = project->getMap(originalMapName); - if (!otherMap) - return; - - static QMap oppositeDirections = QMap({ - {"up", "down"}, {"right", "left"}, - {"down", "up"}, {"left", "right"}, - {"dive", "emerge"},{"emerge", "dive"}}); - QString oppositeDirection = oppositeDirections.value(originalDirection); - - // Find the matching connection in the connected map. - MapConnection* mirrorConnection = nullptr; - for (MapConnection* conn : otherMap->connections) { - if (conn->direction == oppositeDirection && conn->map_name == map->name) { - mirrorConnection = conn; - } - } - - if (isDelete) { - if (mirrorConnection) { - otherMap->connections.removeOne(mirrorConnection); - delete mirrorConnection; - } - return; - } - - if (connection->direction != originalDirection || connection->map_name != originalMapName) { - if (mirrorConnection) { - otherMap->connections.removeOne(mirrorConnection); - delete mirrorConnection; - mirrorConnection = nullptr; - otherMap = project->getMap(connection->map_name); - } - } - - // Create a new mirrored connection, if a matching one doesn't already exist. - if (!mirrorConnection) { - mirrorConnection = new MapConnection; - mirrorConnection->direction = oppositeDirections.value(connection->direction); - mirrorConnection->map_name = map->name; - otherMap->connections.append(mirrorConnection); - } - - mirrorConnection->offset = -connection->offset; -} - -void Editor::updateDiveMap(QString mapName) { - updateDiveEmergeMap(mapName, "dive"); -} - -void Editor::updateEmergeMap(QString mapName) { - updateDiveEmergeMap(mapName, "emerge"); -} - -void Editor::updateDiveEmergeMap(QString mapName, QString direction) { - if (!mapName.isEmpty() && !project->mapNamesToMapConstants.contains(mapName)) { - logError(QString("Invalid %1 connection map name: '%2'").arg(direction).arg(mapName)); - return; - } - - MapConnection* connection = nullptr; - for (MapConnection* conn : map->connections) { - if (conn->direction == direction) { - connection = conn; - break; - } - } - - if (mapName.isEmpty() || mapName == DYNAMIC_MAP_NAME) { - // Remove dive/emerge connection - if (connection) { - map->connections.removeOne(connection); - removeMirroredConnection(connection); - } - } else { - if (!connection) { - connection = new MapConnection; - connection->direction = direction; - connection->offset = 0; - connection->map_name = mapName; - map->connections.append(connection); - updateMirroredConnection(connection, connection->direction, connection->map_name); - } else { - QString originalMapName = connection->map_name; - connection->map_name = mapName; - updateMirroredConnectionMap(connection, originalMapName); - } - } -} - void Editor::updatePrimaryTileset(QString tilesetLabel, bool forceLoad) { if (map->layout->tileset_primary_label != tilesetLabel || forceLoad) @@ -1893,7 +1999,7 @@ void Editor::updateBorderVisibility() { void Editor::updateCustomMapHeaderValues(QTableWidget *table) { map->customHeaders = CustomAttributesTable::getAttributes(table); - emit editedMapData(); + emit editedMapData(map); } Tileset* Editor::getCurrentMapPrimaryTileset() diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 7de1c54b5..38af29d23 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -310,7 +310,7 @@ void MainWindow::initEditor() { connect(this->editor, &Editor::currentMetatilesSelectionChanged, this, &MainWindow::currentMetatilesSelectionChanged); connect(this->editor, &Editor::wildMonDataChanged, this, &MainWindow::onWildMonDataChanged); connect(this->editor, &Editor::mapRulerStatusChanged, this, &MainWindow::onMapRulerStatusChanged); - connect(this->editor, &Editor::editedMapData, this, &MainWindow::markMapEdited); + connect(this->editor, &Editor::editedMapData, [this](Map* map) { this->markMapEdited(map); }); connect(this->editor, &Editor::tilesetUpdated, this, &Scripting::cb_TilesetUpdated); connect(ui->toolButton_Open_Scripts, &QToolButton::pressed, this->editor, &Editor::openMapScripts); connect(ui->actionOpen_Project_in_Text_Editor, &QAction::triggered, this->editor, &Editor::openProjectInTextEditor); @@ -413,10 +413,19 @@ void MainWindow::showWindowTitle() { } void MainWindow::markMapEdited() { - if (editor && editor->map) { - editor->map->hasUnsavedDataChanges = true; + if (editor) markMapEdited(editor->map); +} + +void MainWindow::markMapEdited(Map* map) { + if (!map) + return; + map->hasUnsavedDataChanges = true; + + // TODO: Only update the necessary list icon + updateMapList(); + + if (editor && editor->map == map) showWindowTitle(); - } } // Update the UI using information we've read from the user's project files. @@ -769,7 +778,6 @@ bool MainWindow::setMap(QString map_name, bool scrollTreeView) { showWindowTitle(); - connect(editor->map, &Map::mapChanged, this, &MainWindow::onMapChanged); connect(editor->map, &Map::mapNeedsRedrawing, this, &MainWindow::onMapNeedsRedrawing); connect(editor->map, &Map::modified, [this](){ this->markMapEdited(); }); @@ -2440,10 +2448,6 @@ void MainWindow::onConnectionItemDoubleClicked(QString mapName, QString fromMapN editor->setSelectedConnectionFromMap(fromMapName); } -void MainWindow::onMapChanged(Map *) { - updateMapList(); -} - void MainWindow::onMapNeedsRedrawing() { redrawMapScene(); } @@ -2555,9 +2559,8 @@ void MainWindow::showExportMapImageWindow(ImageExporterMode mode) { void MainWindow::on_pushButton_AddConnection_clicked() { - // TODO: Bring up a prompt for information. Mark the current map *AND* the connected map as edited + // TODO: Bring up a prompt for information? editor->addNewConnection(); - markMapEdited(); } void MainWindow::on_pushButton_NewWildMonGroup_clicked() { @@ -2584,20 +2587,15 @@ void MainWindow::on_button_OpenEmergeMap_clicked() { userSetMap(mapName, true); } -// TODO: Mirror change to/from other maps void MainWindow::on_comboBox_DiveMap_currentTextChanged(const QString &mapName) { // Include empty names as an update (user is deleting the connection) - if (mapName.isEmpty() || editor->project->mapNames.contains(mapName)) { + if (mapName.isEmpty() || editor->project->mapNames.contains(mapName)) editor->updateDiveMap(mapName); - markMapEdited(); - } } void MainWindow::on_comboBox_EmergeMap_currentTextChanged(const QString &mapName) { - if (mapName.isEmpty() || editor->project->mapNames.contains(mapName)) { + if (mapName.isEmpty() || editor->project->mapNames.contains(mapName)) editor->updateEmergeMap(mapName); - markMapEdited(); - } } void MainWindow::on_comboBox_PrimaryTileset_currentTextChanged(const QString &tilesetLabel) diff --git a/src/ui/connectionpixmapitem.cpp b/src/ui/connectionpixmapitem.cpp index 301fcfb64..060f084fb 100644 --- a/src/ui/connectionpixmapitem.cpp +++ b/src/ui/connectionpixmapitem.cpp @@ -38,8 +38,8 @@ QVariant ConnectionPixmapItem::itemChange(GraphicsItemChange change, const QVari y = this->initialY; } - this->connection->offset = newOffset; - emit connectionMoved(this->connection); + if (this->connection->offset != newOffset) + emit connectionMoved(this->connection, newOffset); return QPointF(x, y); } else { diff --git a/src/ui/connectionslistitem.cpp b/src/ui/connectionslistitem.cpp index b9f456a39..f40ae57f0 100644 --- a/src/ui/connectionslistitem.cpp +++ b/src/ui/connectionslistitem.cpp @@ -5,8 +5,7 @@ static const QStringList directions = {"up", "down", "left", "right"}; ConnectionsListItem::ConnectionsListItem(QWidget *parent, MapConnection * connection, const QStringList &mapNames) : QFrame(parent), - ui(new Ui::ConnectionsListItem), - connection(connection) + ui(new Ui::ConnectionsListItem) { ui->setupUi(this); @@ -24,6 +23,7 @@ ConnectionsListItem::ConnectionsListItem(QWidget *parent, MapConnection * connec ui->spinBox_Offset->setMinimum(INT_MIN); ui->spinBox_Offset->setMaximum(INT_MAX); + this->connection = connection; this->updateUI(); } @@ -58,33 +58,31 @@ void ConnectionsListItem::mousePressEvent(QMouseEvent *) { } void ConnectionsListItem::mouseDoubleClickEvent(QMouseEvent *) { - emit doubleClicked(); + emit doubleClicked(this->connection->map_name); } void ConnectionsListItem::on_comboBox_Direction_currentTextChanged(const QString &direction) { - this->connection->direction = direction; this->setSelected(true); - emit this->edited(); + if (this->connection->direction != direction) + emit this->editedDirection(this->connection, direction); } void ConnectionsListItem::on_comboBox_Map_currentTextChanged(const QString &mapName) { - if (ui->comboBox_Map->findText(mapName) >= 0) { - this->connection->map_name = mapName; - this->setSelected(true); - emit this->edited(); - } + this->setSelected(true); + if (ui->comboBox_Map->findText(mapName) >= 0 && this->connection->map_name != mapName) + emit this->editedMapName(this->connection, mapName); } void ConnectionsListItem::on_spinBox_Offset_valueChanged(int offset) { - this->connection->offset = offset; this->setSelected(true); - emit this->edited(); + if (this->connection->offset != offset) + emit editedOffset(this->connection, offset); } void ConnectionsListItem::on_button_Delete_clicked() { - emit this->deleteRequested(); + emit this->removed(); } From 96b5fb161711824386f2f14055121f02eac90350 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 12 Jul 2024 14:05:37 -0400 Subject: [PATCH 11/30] Performance & bug clean up --- forms/mainwindow.ui | 20 ++- include/core/map.h | 2 +- include/core/mapconnection.h | 6 + include/editor.h | 7 +- include/ui/connectionpixmapitem.h | 10 +- include/ui/noscrollcombobox.h | 1 + porymap.pro | 1 + src/core/map.cpp | 23 +-- src/core/mapconnection.cpp | 50 +++--- src/editor.cpp | 250 +++++++++++++----------------- src/mainwindow.cpp | 19 ++- src/project.cpp | 3 + src/ui/connectionpixmapitem.cpp | 68 ++++---- src/ui/connectionslistitem.cpp | 4 +- src/ui/noscrollcombobox.cpp | 6 + 15 files changed, 214 insertions(+), 256 deletions(-) diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui index cdb4dcb89..c2f0647cc 100644 --- a/forms/mainwindow.ui +++ b/forms/mainwindow.ui @@ -1715,7 +1715,7 @@ 0 0 100 - 16 + 30 @@ -1809,7 +1809,7 @@ 0 0 100 - 16 + 30 @@ -1903,7 +1903,7 @@ 0 0 100 - 16 + 30 @@ -2003,7 +2003,7 @@ 0 0 100 - 16 + 30 @@ -2097,7 +2097,7 @@ 0 0 100 - 16 + 30 @@ -2596,6 +2596,9 @@ true + + true + @@ -2667,6 +2670,9 @@ true + + true + @@ -2757,8 +2763,8 @@ 0 0 - 365 - 658 + 100 + 30 diff --git a/include/core/map.h b/include/core/map.h index a6f6fa1ca..83f9a9d11 100644 --- a/include/core/map.h +++ b/include/core/map.h @@ -98,7 +98,7 @@ class Map : public QObject QStringList getScriptLabels(Event::Group group = Event::Group::None); void removeEvent(Event *); void addEvent(Event *); - QPixmap renderConnection(MapConnection, MapLayout *); + QPixmap renderConnection(const MapConnection&, MapLayout *); QPixmap renderBorder(bool ignoreCache = false); void setDimensions(int newWidth, int newHeight, bool setNewBlockdata = true, bool enableScriptCallback = false); void setBorderDimensions(int newWidth, int newHeight, bool setNewBlockdata = true, bool enableScriptCallback = false); diff --git a/include/core/mapconnection.h b/include/core/mapconnection.h index 474be5b10..a70778133 100644 --- a/include/core/mapconnection.h +++ b/include/core/mapconnection.h @@ -12,6 +12,12 @@ class MapConnection { QString direction; int offset; QString map_name; + + static const QStringList cardinalDirections; + static bool isCardinal(const QString &direction); + static bool isHorizontal(const QString &direction); + static bool isVertical(const QString &direction); + static MapConnection mirror(const MapConnection &source, const QString &mapName); }; struct MapConnectionMirror { diff --git a/include/editor.h b/include/editor.h index f0b54b699..7c878023f 100644 --- a/include/editor.h +++ b/include/editor.h @@ -168,14 +168,13 @@ public slots: QPixmap collisionSheetPixmap; void updateBorderVisibility(); - QPoint calculateConnectionPosition(const MapConnection *connection, const QPixmap &pixmap); + QPoint calculateConnectionPosition(const MapConnection &connection, const QPixmap &pixmap); + QPixmap getConnectionPixmap(const MapConnection &connection); void updateConnectionItem(ConnectionPixmapItem* connectionItem); void updateConnectionItemPos(ConnectionPixmapItem* connectionItem); void createConnectionItem(MapConnection* connection); - void populateConnectionsList(); void addConnectionToList(ConnectionPixmapItem* connection); void updateDiveEmergeMap(QString mapName, QString direction); - bool shouldMirrorConnection(const MapConnection &source); MapConnectionMirror getMirroredConnection(const MapConnection&); void addMirroredConnection(const MapConnection&); void removeMirroredConnection(const MapConnection&); @@ -197,7 +196,7 @@ private slots: void setConnectionOffset(MapConnection *connection, int offset); void setConnectionMap(MapConnection *connection, const QString &mapName); void setConnectionDirection(MapConnection *connection, const QString &direction); - void onConnectionItemSelected(ConnectionPixmapItem* connectionItem); + void setSelectedConnection(ConnectionPixmapItem* connectionItem); void onHoveredMovementPermissionChanged(uint16_t, uint16_t); void onHoveredMovementPermissionCleared(); void onHoveredMetatileSelectionChanged(uint16_t); diff --git a/include/ui/connectionpixmapitem.h b/include/ui/connectionpixmapitem.h index f0e00ae14..4f18b649e 100644 --- a/include/ui/connectionpixmapitem.h +++ b/include/ui/connectionpixmapitem.h @@ -28,13 +28,14 @@ class ConnectionPixmapItem : public QObject, public QGraphicsPixmapItem { int initialOffset; int baseMapWidth; int baseMapHeight; - void render(qreal opacity = 1); + void setEditable(bool editable); bool getEditable(); - void updateHighlight(bool selected); + void setSelected(bool selected); + void render(); private: - bool highlighted = false; + bool selected = false; protected: QVariant itemChange(GraphicsItemChange change, const QVariant &value); @@ -42,10 +43,9 @@ class ConnectionPixmapItem : public QObject, public QGraphicsPixmapItem { void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*); signals: - void connectionItemSelected(ConnectionPixmapItem* connectionItem); void connectionItemDoubleClicked(ConnectionPixmapItem* connectionItem); void connectionMoved(MapConnection *, int newOffset); - void highlightChanged(bool highlighted); + void selectionChanged(bool selected); }; #endif // CONNECTIONPIXMAPITEM_H diff --git a/include/ui/noscrollcombobox.h b/include/ui/noscrollcombobox.h index 59c680a37..43db9deb5 100644 --- a/include/ui/noscrollcombobox.h +++ b/include/ui/noscrollcombobox.h @@ -13,6 +13,7 @@ class NoScrollComboBox : public QComboBox void setTextItem(const QString &text); void setNumberItem(int value); void setHexItem(uint32_t value); + void setClearButtonEnabled(bool enabled); private: void setItem(int index, const QString &text); diff --git a/porymap.pro b/porymap.pro index 5c898302f..8afc99a5b 100644 --- a/porymap.pro +++ b/porymap.pro @@ -24,6 +24,7 @@ SOURCES += src/core/block.cpp \ src/core/heallocation.cpp \ src/core/imageexport.cpp \ src/core/map.cpp \ + src/core/mapconnection.cpp \ src/core/maplayout.cpp \ src/core/mapparser.cpp \ src/core/metatile.cpp \ diff --git a/src/core/map.cpp b/src/core/map.cpp index 463b9341b..fad4683a8 100644 --- a/src/core/map.cpp +++ b/src/core/map.cpp @@ -217,34 +217,21 @@ QPixmap Map::renderBorder(bool ignoreCache) { return layout->border_pixmap; } -QPixmap Map::renderConnection(MapConnection connection, MapLayout * fromLayout) { - int x, y, w, h; +QPixmap Map::renderConnection(const MapConnection &connection, MapLayout * fromLayout) { + if (!MapConnection::isCardinal(connection.direction)) + return QPixmap(); + + int x = 0, y = 0, w = getWidth(), h = getHeight(); if (connection.direction == "up") { - x = 0; y = getHeight() - BORDER_DISTANCE; - w = getWidth(); h = BORDER_DISTANCE; } else if (connection.direction == "down") { - x = 0; - y = 0; - w = getWidth(); h = BORDER_DISTANCE; } else if (connection.direction == "left") { x = getWidth() - BORDER_DISTANCE; - y = 0; w = BORDER_DISTANCE; - h = getHeight(); } else if (connection.direction == "right") { - x = 0; - y = 0; w = BORDER_DISTANCE; - h = getHeight(); - } else { - // this should not happen - x = 0; - y = 0; - w = getWidth(); - h = getHeight(); } render(true, fromLayout, QRect(x, y, w, h)); diff --git a/src/core/mapconnection.cpp b/src/core/mapconnection.cpp index ebf485929..82a0b71e4 100644 --- a/src/core/mapconnection.cpp +++ b/src/core/mapconnection.cpp @@ -1,43 +1,35 @@ #include "mapconnection.h" #include "map.h" -void MapConnection::setDirection(const QString & direction) { - if (direction == m_direction) - return; - auto before = m_direction; - m_direction = direction; - emit directionChanged(before, m_direction); -} - -void MapConnection::setOffset(int offset) { - if (offset == m_offset) - return; - auto before = m_offset; - m_offset = offset; - emit offsetChanged(before, m_offset); -} +const QStringList MapConnection::cardinalDirections = { + "up", "down", "left", "right" +}; -void MapConnection::setMapName(const QString &mapName) { - if (mapName == m_mapName) - return; - auto before = m_mapName; - m_mapName = mapName; - emit mapNameChanged(before, m_mapName); -} -/* -static QString MapConnection::oppositeDirection(const QString &direction) { +MapConnection MapConnection::mirror(const MapConnection &source, const QString &mapName) { static const QMap oppositeDirections = { {"up", "down"}, {"down", "up"}, {"right", "left"}, {"left", "right"}, {"dive", "emerge"}, {"emerge", "dive"} }; - return oppositeDirections.value(direction); -} -static MapConnection* MapConnection::getMirror(const MapConnection*, const Map*) { + // TODO: Allowing editing unknown directions is a can of worms. + // Specifically a self-connection with an empty direction and an offset of 0 can be identified as its own mirror + MapConnection mirror; + mirror.direction = oppositeDirections.value(source.direction/*, source.direction*/); + mirror.map_name = mapName; + mirror.offset = -source.offset; + return mirror; } -static MapConnection* MapConnection::newMirror(const MapConnection*) { +bool MapConnection::isHorizontal(const QString &direction) { + return direction == "left" || direction == "right"; +} + +bool MapConnection::isVertical(const QString &direction) { + return direction == "up" || direction == "down"; +} -}*/ +bool MapConnection::isCardinal(const QString &direction) { + return cardinalDirections.contains(direction); +} diff --git a/src/editor.cpp b/src/editor.cpp index b88ac4cf8..0f23f3319 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -89,7 +89,6 @@ void Editor::setEditingMap() { current_view = map_item; if (map_item) { map_item->paintingMode = MapPixmapItem::PaintMode::Metatiles; - displayMapConnections(); map_item->draw(); map_item->setVisible(true); } @@ -109,7 +108,6 @@ void Editor::setEditingMap() { void Editor::setEditingCollision() { current_view = collision_item; if (collision_item) { - displayMapConnections(); collision_item->draw(); collision_item->setVisible(true); } @@ -135,7 +133,6 @@ void Editor::setEditingObjects() { } if (map_item) { map_item->paintingMode = MapPixmapItem::PaintMode::EventObjects; - displayMapConnections(); map_item->draw(); map_item->setVisible(true); } @@ -172,8 +169,6 @@ void Editor::setEditingConnections() { map_item->paintingMode = MapPixmapItem::PaintMode::Disabled; map_item->draw(); map_item->setVisible(true); - populateConnectionsList(); - maskNonVisibleConnectionTiles(); } if (collision_item) { collision_item->setVisible(false); @@ -722,58 +717,15 @@ void Editor::updateEncounterFields(EncounterFields newFields) { project->wildMonFields = newFields; } -void Editor::populateConnectionsList() { - const QSignalBlocker blocker1(ui->comboBox_DiveMap); - const QSignalBlocker blocker2(ui->comboBox_EmergeMap); - - // TODO: We should probably just be doing this once, and updating the items when new maps are created. - ui->comboBox_DiveMap->clear(); - ui->comboBox_EmergeMap->clear(); - ui->comboBox_DiveMap->addItems(project->mapNames); - ui->comboBox_EmergeMap->addItems(project->mapNames); - ui->comboBox_DiveMap->setCurrentText(""); - ui->comboBox_EmergeMap->setCurrentText(""); - ui->comboBox_DiveMap->lineEdit()->setClearButtonEnabled(true); - ui->comboBox_EmergeMap->lineEdit()->setClearButtonEnabled(true); - - for (MapConnection* connection : map->connections) { - if (connection->direction == "dive") { - ui->comboBox_DiveMap->setCurrentText(connection->map_name); - } else if (connection->direction == "emerge") { - ui->comboBox_EmergeMap->setCurrentText(connection->map_name); - } - } - - // Clear any existing connections in list - for (auto listItem : ui->scrollAreaContents_ConnectionsList->findChildren()) - listItem->deleteLater(); - - for (auto item :connection_items) - addConnectionToList(item); -} - -// TODO: When connecting a map to itself the new mirror is shaded incorrectly -// TODO: Set default focus to the selected connection, right now it defaults to the dive combo box - void Editor::addConnectionToList(ConnectionPixmapItem * connectionItem) { ConnectionsListItem *listItem = new ConnectionsListItem(ui->scrollAreaContents_ConnectionsList, connectionItem->connection, project->mapNames); ui->layout_ConnectionsList->insertWidget(ui->layout_ConnectionsList->count() - 1, listItem); // Insert above the vertical spacer // Sync the selection highlight between the list UI and the graphical map connection - connect(connectionItem, &ConnectionPixmapItem::highlightChanged, listItem, &ConnectionsListItem::setSelected); + connect(connectionItem, &ConnectionPixmapItem::selectionChanged, listItem, &ConnectionsListItem::setSelected); connect(listItem, &ConnectionsListItem::selected, [this, connectionItem] { - // When the list item is selected, select the pixmap too - if (connectionItem == selected_connection_item) { - // Already selected, no change - return; - } - // Deselect old connection and select new connection - if (selected_connection_item) selected_connection_item->updateHighlight(false); - selected_connection_item = connectionItem; - selected_connection_item->updateHighlight(true); + setSelectedConnection(connectionItem); }); - if (connectionItem == selected_connection_item) - listItem->setSelected(true); // Sync edits to 'offset' between the list UI and the graphical map connection connect(connectionItem, &ConnectionPixmapItem::connectionMoved, [this, listItem](MapConnection* connection, int offset) { @@ -787,9 +739,10 @@ void Editor::addConnectionToList(ConnectionPixmapItem * connectionItem) { // Sync edits to 'direction' or 'map' between the list UI and the graphical map connection. // These are 1-way because the direction and map cannot be edited graphically, only via the list UI. - connect(listItem, &ConnectionsListItem::editedDirection, [this, connectionItem](MapConnection* connection, QString direction) { + connect(listItem, &ConnectionsListItem::editedDirection, [this, connectionItem, listItem](MapConnection* connection, QString direction) { setConnectionDirection(connection, direction); - updateConnectionItem(connectionItem); // TODO: Simplify? + updateConnectionItem(connectionItem); // TODO: Simplify + listItem->updateUI(); // Changing direction may have changed our offset too }); connect(listItem, &ConnectionsListItem::editedMapName, [this, connectionItem](MapConnection* connection, QString mapName) { setConnectionMap(connection, mapName); @@ -813,13 +766,13 @@ void Editor::addConnectionToList(ConnectionPixmapItem * connectionItem) { void Editor::addNewConnection() { // Find direction with least number of connections. - QMap directionCounts = QMap({{"up", 0}, {"right", 0}, {"down", 0}, {"left", 0}}); + QMap directionCounts; for (MapConnection* connection : map->connections) { directionCounts[connection->direction]++; } QString minDirection = "up"; int minCount = INT_MAX; - for (QString direction : directionCounts.keys()) { + for (QString direction : MapConnection::cardinalDirections) { if (directionCounts[direction] < minCount) { minDirection = direction; minCount = directionCounts[direction]; @@ -827,7 +780,6 @@ void Editor::addNewConnection() { } // Prefer not to connect the map to itself (we have to if it's the only map). - // TODO: Is this more or less sensible than a connection with no map name QString defaultMapName = project->mapNames.first(); if (defaultMapName == map->name && project->mapNames.length() > 1) { defaultMapName = project->mapNames.at(1); @@ -838,11 +790,14 @@ void Editor::addNewConnection() { newConnection->offset = 0; newConnection->map_name = defaultMapName; addConnection(map, newConnection); - onConnectionItemSelected(connection_items.last()); + setSelectedConnection(connection_items.last()); addMirroredConnection(*newConnection); } void Editor::addConnection(Map* map, MapConnection * connection) { + if (!map || !connection) + return; + map->connections.append(connection); if (map == this->map) { // Adding a connection to the current map, we need to display it visually. @@ -857,7 +812,6 @@ void Editor::addConnection(Map* map, MapConnection * connection) { ui->comboBox_EmergeMap->setCurrentText(connection->map_name); } else { createConnectionItem(connection); - addConnectionToList(connection_items.last()); } } emit editedMapData(map); @@ -885,7 +839,7 @@ void Editor::removeConnectionItem(ConnectionPixmapItem* connectionItem, bool rem if (connectionItem == selected_connection_item) { selected_connection_item = nullptr; if (!connection_items.isEmpty()) - onConnectionItemSelected(connection_items.first()); + setSelectedConnection(connection_items.first()); } delete connectionItem; } @@ -902,22 +856,9 @@ void Editor::removeSelectedConnection() { removeConnectionItem(selected_connection_item); } -static const QMap oppositeDirections = { - {"up", "down"}, {"down", "up"}, - {"right", "left"}, {"left", "right"}, - {"dive", "emerge"}, {"emerge", "dive"} -}; - -bool Editor::shouldMirrorConnection(const MapConnection &source) { - // The current map's connections are not mirrored if the user has disabled this setting, - // unless it's a connection to itself (which is mirrored by definition). - // TODO: Confirm in-game representation of the above fact is accurate. - return ui->checkBox_MirrorConnections->isChecked() || (map && map->name == source.map_name); -} - MapConnectionMirror Editor::getMirroredConnection(const MapConnection &source) { MapConnectionMirror mirror; - if (!map || !shouldMirrorConnection(source)) + if (!map || !ui->checkBox_MirrorConnections->isChecked()) return mirror; // Note: It's possible (and ok) for mirror.map == this->map @@ -925,12 +866,10 @@ MapConnectionMirror Editor::getMirroredConnection(const MapConnection &source) { if (!mirror.map) return mirror; - MapConnection target; - target.direction = oppositeDirections.value(source.direction); - target.map_name = map->name; - target.offset = -source.offset; - // Find the matching connection in the connected map. + // Note: There is no strict source -> mirror pairing, i.e. we are not guaranteed + // to always get the same MapConnection if there are multiple identical copies. + MapConnection target = MapConnection::mirror(source, map->name); for (auto connection : mirror.map->connections) { if (*connection == target) { mirror.connection = connection; @@ -946,10 +885,7 @@ void Editor::addMirroredConnection(const MapConnection &source) { return; mirror.connection = new MapConnection; - mirror.connection->direction = oppositeDirections.value(source.direction); - mirror.connection->map_name = map->name; - mirror.connection->offset = -source.offset; - + *mirror.connection = MapConnection::mirror(source, map->name); addConnection(mirror.map, mirror.connection); } @@ -993,7 +929,7 @@ void Editor::updateDiveEmergeMap(QString mapName, QString direction) { return; } - // TODO: How does the game handle having multiple Dive/Emerge maps. Should we support this? + // Only the first Dive/Emerge map (if present) is considered, as in-game. MapConnection* connection = nullptr; for (MapConnection* conn : map->connections) { if (conn->direction == direction) { @@ -1002,14 +938,18 @@ void Editor::updateDiveEmergeMap(QString mapName, QString direction) { } } - // We (lazily) always update the connection by deleting the old one and creating a new one. - // Unlike the displayed connections which can be updated rapidly by click+drag, this isn't - // really an issue for Dive/Emerge maps. + // Dive/Emerge maps aren't represented visually (aside from their combo boxes), + // so we have less to do here than a normal connection. if (connection) { - removeMirroredConnection(*connection); - removeConnection(map, connection); - } - if (!mapName.isEmpty() && mapName != DYNAMIC_MAP_NAME) { + // Update existing connection + if (mapName.isEmpty()) { + removeMirroredConnection(*connection); + removeConnection(map, connection); + } else { + setConnectionMap(connection, mapName); + } + } else if (!mapName.isEmpty()) { + // Create new connection connection = new MapConnection; connection->direction = direction; connection->offset = 0; @@ -1019,25 +959,36 @@ void Editor::updateDiveEmergeMap(QString mapName, QString direction) { } } -QPoint Editor::calculateConnectionPosition(const MapConnection *connection, const QPixmap &pixmap) { +QPoint Editor::calculateConnectionPosition(const MapConnection &connection, const QPixmap &pixmap) { int x = 0, y = 0; const int mWidth = 16, mHeight = 16; - if (connection->direction == "up") { - x = connection->offset * mWidth; + if (connection.direction == "up") { + x = connection.offset * mWidth; y = -pixmap.height(); - } else if (connection->direction == "down") { - x = connection->offset * mWidth; + } else if (connection.direction == "down") { + x = connection.offset * mWidth; y = map->getHeight() * mHeight; - } else if (connection->direction == "left") { + } else if (connection.direction == "left") { x = -pixmap.width(); - y = connection->offset * mHeight; - } else if (connection->direction == "right") { + y = connection.offset * mHeight; + } else if (connection.direction == "right") { x = map->getWidth() * mWidth; - y = connection->offset * mHeight; + y = connection.offset * mHeight; } return QPoint(x, y); } +QPixmap Editor::getConnectionPixmap(const MapConnection &connection) { + Map *connectedMap = project->getMap(connection.map_name); + + // connectedMap will be null for MAP_DYNAMIC and any map that fails to load. + // The connection will be editable from the list, but no image will be displayed on the map. + if (!connectedMap) + return QPixmap(); + + return connectedMap->renderConnection(connection, map->layout); +} + void Editor::updateConnectionItem(ConnectionPixmapItem* connectionItem) { if (!connectionItem || !connectionItem->connection) return; @@ -1046,29 +997,22 @@ void Editor::updateConnectionItem(ConnectionPixmapItem* connectionItem) { if (mapName.isEmpty()) return; - // TODO: What happens if a connection is saved with an empty name - if (mapName == DYNAMIC_MAP_NAME || !project->mapNames.contains(mapName)) { + if (!project->mapNames.contains(mapName)) { logError(QString("Invalid map name '%1' specified for connection.").arg(mapName)); return; } - Map *connectedMap = project->getMap(mapName); - if (!connectedMap) - return; - - QPixmap pixmap = connectedMap->renderConnection(*connectionItem->connection, map->layout); connectionItem->initialOffset = connectionItem->connection->offset; - connectionItem->basePixmap = pixmap; - QPoint pos = calculateConnectionPosition(connectionItem->connection, pixmap); + connectionItem->basePixmap = getConnectionPixmap(*connectionItem->connection); + QPoint pos = calculateConnectionPosition(*connectionItem->connection, connectionItem->basePixmap); connectionItem->blockSignals(true); - connectionItem->setPixmap(pixmap); - connectionItem->updateHighlight(connectionItem == selected_connection_item); + connectionItem->setPixmap(connectionItem->basePixmap); connectionItem->initialX = pos.x(); connectionItem->initialY = pos.y(); connectionItem->setX(pos.x()); connectionItem->setY(pos.y()); - connectionItem->setZValue(-1); + connectionItem->render(); connectionItem->blockSignals(false); maskNonVisibleConnectionTiles(); @@ -1080,9 +1024,9 @@ void Editor::updateConnectionItemPos(ConnectionPixmapItem* connectionItem) { MapConnection *connection = connectionItem->connection; connectionItem->blockSignals(true); - if (connection->direction == "up" || connection->direction == "down") { + if (MapConnection::isVertical(connection->direction)) { connectionItem->setX(connectionItem->initialX + (connection->offset - connectionItem->initialOffset) * 16); - } else if (connection->direction == "left" || connection->direction == "right") { + } else if (MapConnection::isHorizontal(connection->direction)) { connectionItem->setY(connectionItem->initialY + (connection->offset - connectionItem->initialOffset) * 16); } connectionItem->blockSignals(false); @@ -1115,7 +1059,6 @@ void Editor::setConnectionOffset(MapConnection *connection, int offset) { } } } - // TODO: If there's no mirror but there should be we're not creating one connection->offset = offset; emit editedMapData(map); @@ -1141,19 +1084,26 @@ void Editor::setConnectionDirection(MapConnection *connection, const QString &di // TODO: Lazy removeMirroredConnection(*connection); + + if (MapConnection::isHorizontal(connection->direction) != MapConnection::isHorizontal(direction) + || MapConnection::isVertical(connection->direction) != MapConnection::isVertical(direction)) { + // If the direction has changed between vertical/horizontal then the old offset may not make sense, so we reset it + setConnectionOffset(connection, 0); + } connection->direction = direction; + addMirroredConnection(*connection); emit editedMapData(map); } -void Editor::onConnectionItemSelected(ConnectionPixmapItem* connectionItem) { - if (!connectionItem) +void Editor::setSelectedConnection(ConnectionPixmapItem* connectionItem) { + if (!connectionItem || connectionItem == selected_connection_item) return; + if (selected_connection_item) selected_connection_item->setSelected(false); selected_connection_item = connectionItem; - for (ConnectionPixmapItem* item : connection_items) - item->updateHighlight(item == selected_connection_item); + selected_connection_item->setSelected(true); } // TODO: Inaccurate if there are multiple connections from the same map @@ -1161,7 +1111,7 @@ void Editor::setSelectedConnectionFromMap(QString mapName) { // Search for the first connection that connects to the given map map. for (ConnectionPixmapItem* item : connection_items) { if (item->connection->map_name == mapName) { - onConnectionItemSelected(item); + setSelectedConnection(item); break; } } @@ -1606,6 +1556,7 @@ bool Editor::displayMap() { displayMapBorder(); displayMapGrid(); displayWildMonTables(); + maskNonVisibleConnectionTiles(); this->map_ruler->setZValue(1000); scene->addItem(this->map_ruler); @@ -1795,41 +1746,56 @@ void Editor::displayMapConnections() { selected_connection_item = nullptr; connection_items.clear(); + const QSignalBlocker blocker1(ui->comboBox_DiveMap); + const QSignalBlocker blocker2(ui->comboBox_EmergeMap); + ui->comboBox_DiveMap->clear(); + ui->comboBox_EmergeMap->clear(); + ui->comboBox_DiveMap->addItems(project->mapNames); + ui->comboBox_EmergeMap->addItems(project->mapNames); + ui->comboBox_DiveMap->setCurrentText(""); + ui->comboBox_EmergeMap->setCurrentText(""); + + // Note: We only support editing 1 Dive and Emerge connection per map. + // In a vanilla game only the first Dive/Emerge connection is considered, so allowing + // users to have multiple is likely to lead to confusion. In case users have changed + // this we won't delete extra diving connections, but we'll only display the first one. for (MapConnection *connection : map->connections) { - if (connection->direction == "dive" || connection->direction == "emerge") { - continue; + if (connection->direction == "dive") { + if (ui->comboBox_DiveMap->currentText().isEmpty()) + ui->comboBox_DiveMap->setCurrentText(connection->map_name); + } else if (connection->direction == "emerge") { + if (ui->comboBox_EmergeMap->currentText().isEmpty()) + ui->comboBox_EmergeMap->setCurrentText(connection->map_name); + } else { + // We allow any unknown direction names here. They'll be editable from the list menu. + createConnectionItem(connection); } - createConnectionItem(connection); } - if (!connection_items.empty()) { - onConnectionItemSelected(connection_items.first()); - } - - maskNonVisibleConnectionTiles(); + if (!connection_items.empty()) + setSelectedConnection(connection_items.first()); } void Editor::createConnectionItem(MapConnection* connection) { - Map *connected_map = project->getMap(connection->map_name); - if (!connected_map) { + if (!connection) return; - } - - QPixmap pixmap = connected_map->renderConnection(*connection, map->layout); - QPoint pos = calculateConnectionPosition(connection, pixmap); - + QPixmap pixmap = getConnectionPixmap(*connection); + QPoint pos = calculateConnectionPosition(*connection, pixmap); ConnectionPixmapItem *item = new ConnectionPixmapItem(pixmap, connection, pos.x(), pos.y(), map->getWidth(), map->getHeight()); item->setX(pos.x()); item->setY(pos.y()); - item->setZValue(-1); + item->render(); scene->addItem(item); - connect(item, &ConnectionPixmapItem::connectionItemSelected, this, &Editor::onConnectionItemSelected); + connect(item, &ConnectionPixmapItem::selectionChanged, [this, item](bool selected) { + if (selected) setSelectedConnection(item); + }); connect(item, &ConnectionPixmapItem::connectionItemDoubleClicked, [this, item] { emit this->connectionItemDoubleClicked(item->connection->map_name, map->name); }); connection_items.append(item); + addConnectionToList(item); } // Hides connected map tiles that cannot be seen from the current map (beyond BORDER_DISTANCE). @@ -1891,14 +1857,12 @@ void Editor::updateMapBorder() { } void Editor::updateMapConnections() { - for (int i = 0; i < connection_items.size(); i++) { - Map *connected_map = project->getMap(connection_items[i]->connection->map_name); - if (!connected_map) + for (auto item : connection_items) { + if (!item->connection) continue; - - QPixmap pixmap = connected_map->renderConnection(*(connection_items[i]->connection), map->layout); - connection_items[i]->basePixmap = pixmap; - connection_items[i]->setPixmap(pixmap); + QPixmap pixmap = getConnectionPixmap(*item->connection); + item->basePixmap = pixmap; + item->setPixmap(pixmap); } maskNonVisibleConnectionTiles(); @@ -1992,7 +1956,7 @@ void Editor::updateBorderVisibility() { item->setVisible(visible); item->setEditable(editingConnections); item->setEnabled(visible); - item->updateHighlight(item == selected_connection_item); + item->render(); } } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 38af29d23..19377a49c 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -736,6 +736,13 @@ void MainWindow::on_action_Reload_Project_triggered() { // setMap, but with a visible error message in case of failure. // Use when the user is specifically requesting a map to open. bool MainWindow::userSetMap(QString map_name, bool scrollTreeView) { + if (map_name == DYNAMIC_MAP_NAME) { + QMessageBox msgBox(this); + QString errorMsg = QString("The map '%1' can't be opened, it's a placeholder to indicate the specified map will be set programmatically.").arg(map_name); + msgBox.critical(nullptr, "Error Opening Map", errorMsg); + return false; + } + if (!setMap(map_name, scrollTreeView)) { QMessageBox msgBox(this); QString errorMsg = QString("There was an error opening map %1. Please see %2 for full error details.\n\n%3") @@ -750,7 +757,7 @@ bool MainWindow::userSetMap(QString map_name, bool scrollTreeView) { bool MainWindow::setMap(QString map_name, bool scrollTreeView) { logInfo(QString("Setting map to '%1'").arg(map_name)); - if (map_name.isEmpty()) { + if (map_name.isEmpty() || map_name == DYNAMIC_MAP_NAME) { return false; } @@ -828,10 +835,6 @@ void MainWindow::refreshMapScene() } void MainWindow::openWarpMap(QString map_name, int event_id, Event::Group event_group) { - // Can't warp to dynamic maps - if (map_name == DYNAMIC_MAP_NAME) - return; - // Ensure valid destination map name. if (!editor->project->mapNames.contains(map_name)) { logError(QString("Invalid map name '%1'").arg(map_name)); @@ -1846,6 +1849,8 @@ void MainWindow::on_mainTabBar_tabBarClicked(int index) clickToolButtonFromEditMode(editor->obj_edit_mode); } else if (index == MainTab::Connections) { editor->setEditingConnections(); + // Stop the Dive/Emerge combo boxes from getting the initial focus + ui->graphicsView_Map->setFocus(); } if (index != MainTab::WildPokemon) { if (editor->project && editor->project->wildEncountersLoaded) @@ -2577,13 +2582,13 @@ void MainWindow::on_pushButton_ConfigureEncountersJSON_clicked() { void MainWindow::on_button_OpenDiveMap_clicked() { const QString mapName = ui->comboBox_DiveMap->currentText(); - if (mapName != DYNAMIC_MAP_NAME && editor->project->mapNames.contains(mapName)) + if (editor->project->mapNames.contains(mapName)) userSetMap(mapName, true); } void MainWindow::on_button_OpenEmergeMap_clicked() { const QString mapName = ui->comboBox_EmergeMap->currentText(); - if (mapName != DYNAMIC_MAP_NAME && editor->project->mapNames.contains(mapName)) + if (editor->project->mapNames.contains(mapName)) userSetMap(mapName, true); } diff --git a/src/project.cpp b/src/project.cpp index c6550c6ad..06382168d 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -117,6 +117,9 @@ void Project::clearTilesetCache() { } Map* Project::loadMap(QString map_name) { + if (map_name == DYNAMIC_MAP_NAME) + return nullptr; + Map *map; if (mapCache.contains(map_name)) { map = mapCache.value(map_name); diff --git a/src/ui/connectionpixmapitem.cpp b/src/ui/connectionpixmapitem.cpp index 060f084fb..1b7743f9b 100644 --- a/src/ui/connectionpixmapitem.cpp +++ b/src/ui/connectionpixmapitem.cpp @@ -2,15 +2,28 @@ #include -void ConnectionPixmapItem::render(qreal opacity) { - QPixmap newPixmap = this->basePixmap.copy(0, 0, this->basePixmap.width(), this->basePixmap.height()); - if (opacity < 1) { - QPainter painter(&newPixmap); - int alpha = static_cast(255 * (1 - opacity)); - painter.fillRect(0, 0, newPixmap.width(), newPixmap.height(), QColor(0, 0, 0, alpha)); - painter.end(); +void ConnectionPixmapItem::render() { + QPixmap pixmap = this->basePixmap.copy(0, 0, this->basePixmap.width(), this->basePixmap.height()); + this->setZValue(-1); + + // When editing is inactive the current selection is ignored, all connections should appear normal. + if (this->getEditable()) { + if (this->selected) { + // Draw highlight + QPainter painter(&pixmap); + painter.setPen(QColor(255, 0, 255)); + painter.drawRect(0, 0, pixmap.width() - 1, pixmap.height() - 1); + painter.end(); + } else { + // Darken the image + this->setZValue(-2); + QPainter painter(&pixmap); + int alpha = static_cast(255 * 0.25); + painter.fillRect(0, 0, pixmap.width(), pixmap.height(), QColor(0, 0, 0, alpha)); + painter.end(); + } } - this->setPixmap(newPixmap); + this->setPixmap(pixmap); } QVariant ConnectionPixmapItem::itemChange(GraphicsItemChange change, const QVariant &value) @@ -20,7 +33,7 @@ QVariant ConnectionPixmapItem::itemChange(GraphicsItemChange change, const QVari qreal x, y; int newOffset = this->initialOffset; - if (this->connection->direction == "up" || this->connection->direction == "down") { + if (MapConnection::isVertical(this->connection->direction)) { x = round(newPos.x() / 16) * 16; newOffset += (x - initialX) / 16; x = newOffset * 16; @@ -29,7 +42,7 @@ QVariant ConnectionPixmapItem::itemChange(GraphicsItemChange change, const QVari x = this->initialX; } - if (this->connection->direction == "right" || this->connection->direction == "left") { + if (MapConnection::isHorizontal(this->connection->direction)) { y = round(newPos.y() / 16) * 16; newOffset += (y - this->initialY) / 16; y = newOffset * 16; @@ -56,41 +69,18 @@ bool ConnectionPixmapItem::getEditable() { return (this->flags() & ItemIsMovable) != 0; } -// TODO: Consider whether it still makes sense to highlight the "current" connection (given you can edit them at any point now) -void ConnectionPixmapItem::updateHighlight(bool selected) { - const int normalZ = -1; - const qreal normalOpacity = 1.0; - - // When editing is inactive the current selection is ignored, all connections should appear normal. - if (!this->getEditable()) { - this->setZValue(normalZ); - this->render(normalOpacity); +void ConnectionPixmapItem::setSelected(bool selected) { + if (this->selected == selected) return; - } - - this->setZValue(selected ? normalZ : -2); - this->render(selected ? normalOpacity : 0.75); - - if (selected) { - // Draw highlight - QPixmap pixmap = this->pixmap(); - QPainter painter(&pixmap); - painter.setPen(QColor(255, 0, 255)); - painter.drawRect(0, 0, pixmap.width() - 1, pixmap.height() - 1); - painter.end(); - this->setPixmap(pixmap); - } - - // Let the list UI know if the selection highlight changes so it can update accordingly - if (this->highlighted != selected) - emit highlightChanged(selected); - this->highlighted = selected; + this->selected = selected; + this->render(); + emit selectionChanged(selected); } void ConnectionPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *) { if (!this->getEditable()) return; - emit connectionItemSelected(this); + this->setSelected(true); } void ConnectionPixmapItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *) { diff --git a/src/ui/connectionslistitem.cpp b/src/ui/connectionslistitem.cpp index f40ae57f0..cf6e30206 100644 --- a/src/ui/connectionslistitem.cpp +++ b/src/ui/connectionslistitem.cpp @@ -1,8 +1,6 @@ #include "connectionslistitem.h" #include "ui_connectionslistitem.h" -static const QStringList directions = {"up", "down", "left", "right"}; - ConnectionsListItem::ConnectionsListItem(QWidget *parent, MapConnection * connection, const QStringList &mapNames) : QFrame(parent), ui(new Ui::ConnectionsListItem) @@ -15,7 +13,7 @@ ConnectionsListItem::ConnectionsListItem(QWidget *parent, MapConnection * connec ui->comboBox_Direction->setEditable(false); ui->comboBox_Direction->setMinimumContentsLength(0); - ui->comboBox_Direction->addItems(directions); + ui->comboBox_Direction->addItems(MapConnection::cardinalDirections); ui->comboBox_Map->setMinimumContentsLength(6); ui->comboBox_Map->addItems(mapNames); diff --git a/src/ui/noscrollcombobox.cpp b/src/ui/noscrollcombobox.cpp index ee778df5e..fcb662c76 100644 --- a/src/ui/noscrollcombobox.cpp +++ b/src/ui/noscrollcombobox.cpp @@ -1,6 +1,7 @@ #include "noscrollcombobox.h" #include +#include NoScrollComboBox::NoScrollComboBox(QWidget *parent) : QComboBox(parent) @@ -61,3 +62,8 @@ void NoScrollComboBox::setHexItem(uint32_t value) { this->setItem(this->findData(value), "0x" + QString::number(value, 16).toUpper()); } + +void NoScrollComboBox::setClearButtonEnabled(bool enabled) { + if (this->lineEdit()) + this->lineEdit()->setClearButtonEnabled(enabled); +} From 9ca5f6bc15745e286539012225b4bd96a7362edd Mon Sep 17 00:00:00 2001 From: GriffinR Date: Thu, 18 Jul 2024 13:30:56 -0400 Subject: [PATCH 12/30] More map connection bug fixes --- include/editor.h | 6 +-- include/ui/connectionpixmapitem.h | 8 ++-- src/core/mapconnection.cpp | 2 - src/editor.cpp | 61 ++++++++++++++----------------- 4 files changed, 34 insertions(+), 43 deletions(-) diff --git a/include/editor.h b/include/editor.h index 7c878023f..f1ddb9bff 100644 --- a/include/editor.h +++ b/include/editor.h @@ -175,9 +175,9 @@ public slots: void createConnectionItem(MapConnection* connection); void addConnectionToList(ConnectionPixmapItem* connection); void updateDiveEmergeMap(QString mapName, QString direction); - MapConnectionMirror getMirroredConnection(const MapConnection&); - void addMirroredConnection(const MapConnection&); - void removeMirroredConnection(const MapConnection&); + MapConnectionMirror getMirroredConnection(MapConnection*); + void addMirroredConnection(MapConnection*); + void removeMirroredConnection(MapConnection*); void updateEncounterFields(EncounterFields newFields); QString getMovementPermissionText(uint16_t collision, uint16_t elevation); QString getMetatileDisplayMessage(uint16_t metatileId); diff --git a/include/ui/connectionpixmapitem.h b/include/ui/connectionpixmapitem.h index 4f18b649e..a856eb453 100644 --- a/include/ui/connectionpixmapitem.h +++ b/include/ui/connectionpixmapitem.h @@ -8,7 +8,7 @@ class ConnectionPixmapItem : public QObject, public QGraphicsPixmapItem { Q_OBJECT public: - ConnectionPixmapItem(QPixmap pixmap, MapConnection* connection, int x, int y, int baseMapWidth, int baseMapHeight) + ConnectionPixmapItem(QPixmap pixmap, MapConnection* connection, int x, int y) : QGraphicsPixmapItem(pixmap), connection(connection) { @@ -18,16 +18,14 @@ class ConnectionPixmapItem : public QObject, public QGraphicsPixmapItem { this->initialX = x; this->initialY = y; this->initialOffset = connection->offset; - this->baseMapWidth = baseMapWidth; - this->baseMapHeight = baseMapHeight; + this->setX(x); + this->setY(y); } QPixmap basePixmap; MapConnection* const connection; int initialX; int initialY; int initialOffset; - int baseMapWidth; - int baseMapHeight; void setEditable(bool editable); bool getEditable(); diff --git a/src/core/mapconnection.cpp b/src/core/mapconnection.cpp index 82a0b71e4..b249ef566 100644 --- a/src/core/mapconnection.cpp +++ b/src/core/mapconnection.cpp @@ -12,8 +12,6 @@ MapConnection MapConnection::mirror(const MapConnection &source, const QString & {"dive", "emerge"}, {"emerge", "dive"} }; - // TODO: Allowing editing unknown directions is a can of worms. - // Specifically a self-connection with an empty direction and an offset of 0 can be identified as its own mirror MapConnection mirror; mirror.direction = oppositeDirections.value(source.direction/*, source.direction*/); mirror.map_name = mapName; diff --git a/src/editor.cpp b/src/editor.cpp index 0f23f3319..67d5690ab 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -791,7 +791,7 @@ void Editor::addNewConnection() { newConnection->map_name = defaultMapName; addConnection(map, newConnection); setSelectedConnection(connection_items.last()); - addMirroredConnection(*newConnection); + addMirroredConnection(newConnection); } void Editor::addConnection(Map* map, MapConnection * connection) { @@ -821,16 +821,14 @@ void Editor::removeConnectionItem(ConnectionPixmapItem* connectionItem, bool rem if (!connectionItem) return; - if (connectionItem->connection) { - if (removeMirror) { - // If a map is connected to itself and we delete the connection then this function - // will be called twice, once for the target of the delete and once for its mirror. - // We only want to try deleting the mirror once, on the first call (because the mirror - // of the mirror is the original target again, and we already deleted it). - removeMirroredConnection(*connectionItem->connection); - } - removeConnection(map, connectionItem->connection); + if (removeMirror) { + // If a map is connected to itself and we delete the connection then this function + // will be called twice, once for the target of the delete and once for its mirror. + // We only want to try deleting the mirror once, on the first call (because the mirror + // of the mirror is the original target again, and we already deleted it). + removeMirroredConnection(connectionItem->connection); } + removeConnection(map, connectionItem->connection); connection_items.removeOne(connectionItem); if (connectionItem->scene()) @@ -856,22 +854,22 @@ void Editor::removeSelectedConnection() { removeConnectionItem(selected_connection_item); } -MapConnectionMirror Editor::getMirroredConnection(const MapConnection &source) { +MapConnectionMirror Editor::getMirroredConnection(MapConnection* source) { MapConnectionMirror mirror; - if (!map || !ui->checkBox_MirrorConnections->isChecked()) + if (!map || !source || !ui->checkBox_MirrorConnections->isChecked()) return mirror; // Note: It's possible (and ok) for mirror.map == this->map - mirror.map = project->getMap(source.map_name); + mirror.map = project->getMap(source->map_name); if (!mirror.map) return mirror; // Find the matching connection in the connected map. // Note: There is no strict source -> mirror pairing, i.e. we are not guaranteed // to always get the same MapConnection if there are multiple identical copies. - MapConnection target = MapConnection::mirror(source, map->name); + MapConnection target = MapConnection::mirror(*source, map->name); for (auto connection : mirror.map->connections) { - if (*connection == target) { + if (*connection == target && connection != source) { mirror.connection = connection; break; } @@ -879,27 +877,27 @@ MapConnectionMirror Editor::getMirroredConnection(const MapConnection &source) { return mirror; } -void Editor::addMirroredConnection(const MapConnection &source) { +void Editor::addMirroredConnection(MapConnection* source) { MapConnectionMirror mirror = getMirroredConnection(source); if (!mirror.map) return; mirror.connection = new MapConnection; - *mirror.connection = MapConnection::mirror(source, map->name); + *mirror.connection = MapConnection::mirror(*source, map->name); addConnection(mirror.map, mirror.connection); } -void Editor::removeMirroredConnection(const MapConnection &source) { +void Editor::removeMirroredConnection(MapConnection* source) { MapConnectionMirror mirror = getMirroredConnection(source); if (!mirror.map || !mirror.connection) return; if (map == mirror.map) { // The connection to delete is displayed on the currently-opened map, we need to delete it visually as well. - if (source.direction == "dive") { + if (source->direction == "dive") { const QSignalBlocker blocker(ui->comboBox_DiveMap); ui->comboBox_DiveMap->setCurrentText(""); - } else if (source.direction == "emerge") { + } else if (source->direction == "emerge") { const QSignalBlocker blocker(ui->comboBox_EmergeMap); ui->comboBox_EmergeMap->setCurrentText(""); } else { @@ -943,7 +941,7 @@ void Editor::updateDiveEmergeMap(QString mapName, QString direction) { if (connection) { // Update existing connection if (mapName.isEmpty()) { - removeMirroredConnection(*connection); + removeMirroredConnection(connection); removeConnection(map, connection); } else { setConnectionMap(connection, mapName); @@ -955,7 +953,7 @@ void Editor::updateDiveEmergeMap(QString mapName, QString direction) { connection->offset = 0; connection->map_name = mapName; addConnection(map, connection); - addMirroredConnection(*connection); + addMirroredConnection(connection); } } @@ -1037,7 +1035,7 @@ void Editor::setConnectionOffset(MapConnection *connection, int offset) { if (!connection || !map || connection->offset == offset) return; - MapConnectionMirror mirror = getMirroredConnection(*connection); + MapConnectionMirror mirror = getMirroredConnection(connection); if (mirror.connection && mirror.map) { mirror.connection->offset = -offset; if (mirror.map != map) { @@ -1071,9 +1069,9 @@ void Editor::setConnectionMap(MapConnection *connection, const QString &mapName) if (!connection || !map || connection->map_name == mapName) return; - removeMirroredConnection(*connection); + removeMirroredConnection(connection); connection->map_name = mapName; - addMirroredConnection(*connection); + addMirroredConnection(connection); emit editedMapData(map); } @@ -1083,7 +1081,7 @@ void Editor::setConnectionDirection(MapConnection *connection, const QString &di return; // TODO: Lazy - removeMirroredConnection(*connection); + removeMirroredConnection(connection); if (MapConnection::isHorizontal(connection->direction) != MapConnection::isHorizontal(direction) || MapConnection::isVertical(connection->direction) != MapConnection::isVertical(direction)) { @@ -1092,7 +1090,7 @@ void Editor::setConnectionDirection(MapConnection *connection, const QString &di } connection->direction = direction; - addMirroredConnection(*connection); + addMirroredConnection(connection); emit editedMapData(map); } @@ -1781,9 +1779,7 @@ void Editor::createConnectionItem(MapConnection* connection) { return; QPixmap pixmap = getConnectionPixmap(*connection); QPoint pos = calculateConnectionPosition(*connection, pixmap); - ConnectionPixmapItem *item = new ConnectionPixmapItem(pixmap, connection, pos.x(), pos.y(), map->getWidth(), map->getHeight()); - item->setX(pos.x()); - item->setY(pos.y()); + ConnectionPixmapItem *item = new ConnectionPixmapItem(pixmap, connection, pos.x(), pos.y()); item->render(); scene->addItem(item); @@ -1860,9 +1856,8 @@ void Editor::updateMapConnections() { for (auto item : connection_items) { if (!item->connection) continue; - QPixmap pixmap = getConnectionPixmap(*item->connection); - item->basePixmap = pixmap; - item->setPixmap(pixmap); + item->basePixmap = getConnectionPixmap(*item->connection); + item->render(); } maskNonVisibleConnectionTiles(); From c8434c85b31d55182d121a94da7269f1c2f5700f Mon Sep 17 00:00:00 2001 From: GriffinR Date: Wed, 24 Jul 2024 13:52:46 -0400 Subject: [PATCH 13/30] Clean up project close for connections tab --- CHANGELOG.md | 1 + include/editor.h | 3 ++- src/editor.cpp | 27 ++++++++++++++------------- src/mainwindow.cpp | 20 ++++++++++++++++++++ src/project.cpp | 18 +++++++++++------- 5 files changed, 48 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 67e9a0b33..2a687aadf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ The **"Breaking Changes"** listed below are changes that have been made in the d - Fix config files being written before the project is opened successfully. - Fix the map and other project info still displaying if a new project fails to open. - Fix unsaved changes being ignored when quitting (such as with Cmd+Q on macOS). +- New maps are now always inserted in map dropdowns at the correct position, rather than at the bottom of the list until the project is reloaded. ## [5.4.1] - 2024-03-21 ### Fixed diff --git a/include/editor.h b/include/editor.h index 6d1f88d4f..2c566abc0 100644 --- a/include/editor.h +++ b/include/editor.h @@ -174,7 +174,8 @@ public slots: void clearBorderMetatiles(); void clearCurrentMetatilesSelection(); void clearMapEvents(); - //void clearMapConnections(); + void clearMapConnections(); + void clearConnectionMask(); void clearMapBorder(); void clearMapGrid(); void clearWildMonTables(); diff --git a/src/editor.cpp b/src/editor.cpp index de28ebe0d..f427676bb 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -1546,16 +1546,13 @@ void Editor::clearMap() { clearBorderMetatiles(); clearCurrentMetatilesSelection(); clearMapEvents(); - //clearMapConnections(); + clearMapConnections(); clearMapBorder(); clearMapGrid(); clearWildMonTables(); + clearConnectionMask(); - // TODO: Handle connections after redesign PR. - selected_connection_item = nullptr; - connection_items.clear(); - connection_mask = nullptr; - + // Clear pointers to objects deleted elsewhere current_view = nullptr; map = nullptr; @@ -1804,7 +1801,7 @@ DraggablePixmapItem *Editor::addMapEvent(Event *event) { return object; } -void Editor::displayMapConnections() { +void Editor::clearMapConnections() { for (ConnectionPixmapItem* item : connection_items) { if (item->scene()) { item->scene()->removeItem(item); @@ -1813,13 +1810,13 @@ void Editor::displayMapConnections() { } selected_connection_item = nullptr; connection_items.clear(); +} + +void Editor::displayMapConnections() { + clearMapConnections(); const QSignalBlocker blocker1(ui->comboBox_DiveMap); const QSignalBlocker blocker2(ui->comboBox_EmergeMap); - ui->comboBox_DiveMap->clear(); - ui->comboBox_EmergeMap->clear(); - ui->comboBox_DiveMap->addItems(project->mapNames); - ui->comboBox_EmergeMap->addItems(project->mapNames); ui->comboBox_DiveMap->setCurrentText(""); ui->comboBox_EmergeMap->setCurrentText(""); @@ -1864,8 +1861,7 @@ void Editor::createConnectionItem(MapConnection* connection) { addConnectionToList(item); } -// Hides connected map tiles that cannot be seen from the current map (beyond BORDER_DISTANCE). -void Editor::maskNonVisibleConnectionTiles() { +void Editor::clearConnectionMask() { if (connection_mask) { if (connection_mask->scene()) { connection_mask->scene()->removeItem(connection_mask); @@ -1873,6 +1869,11 @@ void Editor::maskNonVisibleConnectionTiles() { delete connection_mask; connection_mask = nullptr; } +} + +// Hides connected map tiles that cannot be seen from the current map (beyond BORDER_DISTANCE). +void Editor::maskNonVisibleConnectionTiles() { + clearConnectionMask(); QPainterPath mask; mask.addRect(scene->itemsBoundingRect().toRect()); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index f08ce4b38..fc7c72f3c 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1031,6 +1031,8 @@ bool MainWindow::setProjectUI() { const QSignalBlocker blocker5(ui->comboBox_Weather); const QSignalBlocker blocker6(ui->comboBox_BattleScene); const QSignalBlocker blocker7(ui->comboBox_Type); + const QSignalBlocker blocker8(ui->comboBox_DiveMap); + const QSignalBlocker blocker9(ui->comboBox_EmergeMap); // Set up project comboboxes ui->comboBox_Song->clear(); @@ -1047,6 +1049,10 @@ bool MainWindow::setProjectUI() { ui->comboBox_BattleScene->addItems(project->mapBattleScenes); ui->comboBox_Type->clear(); ui->comboBox_Type->addItems(project->mapTypes); + ui->comboBox_DiveMap->clear(); + ui->comboBox_DiveMap->addItems(project->mapNames); + ui->comboBox_EmergeMap->clear(); + ui->comboBox_EmergeMap->addItems(project->mapNames); sortMapList(); @@ -1088,6 +1094,8 @@ void MainWindow::clearProjectUI() { const QSignalBlocker blocker5(ui->comboBox_Weather); const QSignalBlocker blocker6(ui->comboBox_BattleScene); const QSignalBlocker blocker7(ui->comboBox_Type); + const QSignalBlocker blocker8(ui->comboBox_DiveMap); + const QSignalBlocker blocker9(ui->comboBox_EmergeMap); ui->comboBox_Song->clear(); ui->comboBox_Location->clear(); @@ -1096,6 +1104,8 @@ void MainWindow::clearProjectUI() { ui->comboBox_Weather->clear(); ui->comboBox_BattleScene->clear(); ui->comboBox_Type->clear(); + ui->comboBox_DiveMap->clear(); + ui->comboBox_EmergeMap->clear(); // Clear map list mapListModel->clear(); @@ -1301,6 +1311,16 @@ void MainWindow::onNewMapCreated() { sortMapList(); setMap(newMapName, true); + // Refresh any combo box that displays map names and persists between maps + // (others combo boxes like for warp destinations are repopulated when the map changes). + int index = this->editor->project->mapNames.indexOf(newMapName); + if (index >= 0) { + const QSignalBlocker blocker1(ui->comboBox_DiveMap); + const QSignalBlocker blocker2(ui->comboBox_EmergeMap); + ui->comboBox_DiveMap->insertItem(index, newMapName); + ui->comboBox_EmergeMap->insertItem(index, newMapName); + } + if (newMap->needsHealLocation) { addNewEvent(Event::Type::HealLocation); editor->project->saveHealLocations(newMap); diff --git a/src/project.cpp b/src/project.cpp index 6764839b0..424872690 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -1819,18 +1819,22 @@ bool Project::readMapGroups() { } Map* Project::addNewMapToGroup(QString mapName, int groupNum, Map *newMap, bool existingLayout, bool importedMap) { - mapNames.append(mapName); - mapGroups.insert(mapName, groupNum); - groupedMapNames[groupNum].append(mapName); + int mapNamePos = 0; + for (int i = 0; i <= groupNum; i++) + mapNamePos += this->groupedMapNames.value(i).length(); + + this->mapNames.insert(mapNamePos, mapName); + this->mapGroups.insert(mapName, groupNum); + this->groupedMapNames[groupNum].append(mapName); newMap->isPersistedToFile = false; newMap->setName(mapName); - mapConstantsToMapNames.insert(newMap->constantName, newMap->name); - mapNamesToMapConstants.insert(newMap->name, newMap->constantName); + this->mapConstantsToMapNames.insert(newMap->constantName, newMap->name); + this->mapNamesToMapConstants.insert(newMap->name, newMap->constantName); if (!existingLayout) { - mapLayouts.insert(newMap->layoutId, newMap->layout); - mapLayoutsTable.append(newMap->layoutId); + this->mapLayouts.insert(newMap->layoutId, newMap->layout); + this->mapLayoutsTable.append(newMap->layoutId); if (!importedMap) { setNewMapBlockdata(newMap); } From 13252f98f37015009beaf95cec1f9184b5041bd3 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Wed, 24 Jul 2024 15:46:20 -0400 Subject: [PATCH 14/30] Add dive/emerge map overlay --- forms/mainwindow.ui | 211 ++++++++++++++++++++------ include/config.h | 8 + include/editor.h | 14 +- include/mainwindow.h | 4 + include/ui/connectionpixmapitem.h | 6 +- src/config.cpp | 12 ++ src/editor.cpp | 236 +++++++++++++++++++----------- src/mainwindow.cpp | 50 ++++++- 8 files changed, 398 insertions(+), 143 deletions(-) diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui index 9e1fabe46..2428b6194 100644 --- a/forms/mainwindow.ui +++ b/forms/mainwindow.ui @@ -1715,7 +1715,7 @@ 0 0 100 - 30 + 16 @@ -1809,7 +1809,7 @@ 0 0 100 - 30 + 16 @@ -1903,7 +1903,7 @@ 0 0 100 - 30 + 16 @@ -2003,7 +2003,7 @@ 0 0 100 - 30 + 16 @@ -2097,7 +2097,7 @@ 0 0 100 - 30 + 16 @@ -2601,46 +2601,59 @@ - - - - Qt::Horizontal + + + + If enabled, connections will automatically be updated on the connected map. - - - 40 - 20 - + + Mirror to Connecting Maps - - - - - - Open the selected Emerge Map + + true + + + + - ... + Dive Map - - - :/icons/map_go.ico:/icons/map_go.ico + + + + + + Emerge Map - - + + - If enabled, connections will automatically be updated on the connected map. + <html><head/><body><p>Destination map name when emerging using <span style=" font-weight:600;">Dive</span>. If empty, no such connection will exist.</p></body></html> - - Mirror to Connecting Maps + + true - + true + + + + Qt::Horizontal + + + + 40 + 20 + + + + @@ -2655,30 +2668,134 @@ - - - - Dive Map + + + + Show Emerge/Dive Maps - - - - - - <html><head/><body><p>Destination map name when emerging using <span style=" font-weight:600;">Dive</span>. If empty, no such connection will exist.</p></body></html> + + true - + true - + true + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 1 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 10 + + + 90 + + + 30 + + + Qt::Horizontal + + + + + + + 10 + + + 90 + + + 30 + + + Qt::Horizontal + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 10 + + + 90 + + + 30 + + + Qt::Horizontal + + + + + + + + - - + + + + Open the selected Emerge Map + - Emerge Map + ... + + + + :/icons/map_go.ico:/icons/map_go.ico @@ -2763,8 +2880,8 @@ 0 0 - 100 - 30 + 365 + 651 diff --git a/include/config.h b/include/config.h index 3f77aa906..a039e4eb4 100644 --- a/include/config.h +++ b/include/config.h @@ -58,6 +58,10 @@ class PorymapConfig: public KeyValueConfigBase this->reopenOnLaunch = true; this->mapSortOrder = MapSortOrder::Group; this->prettyCursors = true; + this->showDiveEmergeMaps = false; + this->diveEmergeMapOpacity = 30; + this->diveMapOpacity = 15; + this->emergeMapOpacity = 15; this->collisionOpacity = 50; this->collisionZoom = 30; this->metatilesZoom = 30; @@ -103,6 +107,10 @@ class PorymapConfig: public KeyValueConfigBase bool projectManuallyClosed; MapSortOrder mapSortOrder; bool prettyCursors; + bool showDiveEmergeMaps; + int diveEmergeMapOpacity; + int diveMapOpacity; + int emergeMapOpacity; int collisionOpacity; int collisionZoom; int metatilesZoom; diff --git a/include/editor.h b/include/editor.h index 2c566abc0..d4dd0e850 100644 --- a/include/editor.h +++ b/include/editor.h @@ -75,10 +75,11 @@ class Editor : public QObject void setEditingConnections(); void setMapEditingButtonsEnabled(bool enabled); void setConnectionsVisibility(bool visible); + void updateDiveEmergeVisibility(); void addNewConnection(); - void addConnection(Map* map, MapConnection* connection); - void removeConnection(Map* map, MapConnection* connection); - void removeConnectionItem(ConnectionPixmapItem* connectionItem, bool removeMirror = true); + void addConnection(Map* map, MapConnection* connection, bool addMirror = true); + void removeConnection(Map* map, MapConnection* connection, bool removeMirror = true); + void removeConnectionItem(ConnectionPixmapItem* connectionItem); void removeSelectedConnection(); void addNewWildMonGroup(QWidget *window); void deleteWildMonGroup(); @@ -111,6 +112,8 @@ class Editor : public QObject QPointer map_item = nullptr; ConnectionPixmapItem* selected_connection_item = nullptr; QList connection_items; + QGraphicsPixmapItem *dive_map_overlay = nullptr; + QGraphicsPixmapItem *emerge_map_overlay = nullptr; QGraphicsPathItem *connection_mask = nullptr; QPointer collision_item = nullptr; QGraphicsItemGroup *events_group = nullptr; @@ -175,6 +178,8 @@ public slots: void clearCurrentMetatilesSelection(); void clearMapEvents(); void clearMapConnections(); + void clearDiveMap(); + void clearEmergeMap(); void clearConnectionMask(); void clearMapBorder(); void clearMapGrid(); @@ -186,7 +191,8 @@ public slots: void updateConnectionItemPos(ConnectionPixmapItem* connectionItem); void createConnectionItem(MapConnection* connection); void addConnectionToList(ConnectionPixmapItem* connection); - void updateDiveEmergeMap(QString mapName, QString direction); + void createDiveEmergeConnection(MapConnection* connection); + void setDiveEmergeMapName(QString mapName, QString direction); MapConnectionMirror getMirroredConnection(MapConnection*); void addMirroredConnection(MapConnection*); void removeMirroredConnection(MapConnection*); diff --git a/include/mainwindow.h b/include/mainwindow.h index f859ded95..20d3965fc 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -269,6 +269,10 @@ private slots: void eventTabChanged(int index); + void on_groupBox_DiveMapOpacity_toggled(bool on); + void on_slider_DiveEmergeMapOpacity_valueChanged(int value); + void on_slider_DiveMapOpacity_valueChanged(int value); + void on_slider_EmergeMapOpacity_valueChanged(int value); void on_horizontalSlider_CollisionTransparency_valueChanged(int value); void on_toolButton_ExpandAll_clicked(); void on_toolButton_CollapseAll_clicked(); diff --git a/include/ui/connectionpixmapitem.h b/include/ui/connectionpixmapitem.h index a856eb453..e5577d2f5 100644 --- a/include/ui/connectionpixmapitem.h +++ b/include/ui/connectionpixmapitem.h @@ -9,10 +9,10 @@ class ConnectionPixmapItem : public QObject, public QGraphicsPixmapItem { Q_OBJECT public: ConnectionPixmapItem(QPixmap pixmap, MapConnection* connection, int x, int y) - : QGraphicsPixmapItem(pixmap), - connection(connection) + : QGraphicsPixmapItem(pixmap) { this->basePixmap = pixmap; + this->connection = connection; setFlag(ItemIsMovable); setFlag(ItemSendsGeometryChanges); this->initialX = x; @@ -22,7 +22,7 @@ class ConnectionPixmapItem : public QObject, public QGraphicsPixmapItem { this->setY(y); } QPixmap basePixmap; - MapConnection* const connection; + MapConnection* connection; int initialX; int initialY; int initialOffset; diff --git a/src/config.cpp b/src/config.cpp index 16853e8f9..eb87adf23 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -330,6 +330,14 @@ void PorymapConfig::parseConfigKeyValue(QString key, QString value) { this->mainSplitterState = bytesFromString(value); } else if (key == "metatiles_splitter_state") { this->metatilesSplitterState = bytesFromString(value); + } else if (key == "show_dive_emerge_maps") { + this->showDiveEmergeMaps = getConfigBool(key, value); + } else if (key == "dive_emerge_map_opacity") { + this->diveEmergeMapOpacity = getConfigInteger(key, value, 10, 90, 30); + } else if (key == "dive_map_opacity") { + this->diveMapOpacity = getConfigInteger(key, value, 10, 90, 15); + } else if (key == "emerge_map_opacity") { + this->emergeMapOpacity = getConfigInteger(key, value, 10, 90, 15); } else if (key == "collision_opacity") { this->collisionOpacity = getConfigInteger(key, value, 0, 100, 50); } else if (key == "tileset_editor_geometry") { @@ -439,6 +447,10 @@ QMap PorymapConfig::getKeyValueMap() { map.insert("project_settings_editor_state", stringFromByteArray(this->projectSettingsEditorState)); map.insert("custom_scripts_editor_geometry", stringFromByteArray(this->customScriptsEditorGeometry)); map.insert("custom_scripts_editor_state", stringFromByteArray(this->customScriptsEditorState)); + map.insert("show_dive_emerge_maps", this->showDiveEmergeMaps ? "1" : "0"); + map.insert("dive_emerge_map_opacity", QString::number(this->diveEmergeMapOpacity)); + map.insert("dive_map_opacity", QString::number(this->diveMapOpacity)); + map.insert("emerge_map_opacity", QString::number(this->emergeMapOpacity)); map.insert("collision_opacity", QString::number(this->collisionOpacity)); map.insert("collision_zoom", QString::number(this->collisionZoom)); map.insert("metatiles_zoom", QString::number(this->metatilesZoom)); diff --git a/src/editor.cpp b/src/editor.cpp index f427676bb..ba079f501 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -725,6 +725,26 @@ void Editor::updateEncounterFields(EncounterFields newFields) { project->wildMonFields = newFields; } +void Editor::createConnectionItem(MapConnection* connection) { + if (!connection) + return; + QPixmap pixmap = getConnectionPixmap(*connection); + QPoint pos = calculateConnectionPosition(*connection, pixmap); + ConnectionPixmapItem *item = new ConnectionPixmapItem(pixmap, connection, pos.x(), pos.y()); + item->render(); + scene->addItem(item); + + connect(item, &ConnectionPixmapItem::selectionChanged, [this, item](bool selected) { + if (selected) setSelectedConnection(item); + }); + connect(item, &ConnectionPixmapItem::connectionItemDoubleClicked, [this, item] { + emit this->connectionItemDoubleClicked(item->connection->map_name, map->name); + }); + + connection_items.append(item); + addConnectionToList(item); +} + void Editor::addConnectionToList(ConnectionPixmapItem * connectionItem) { ConnectionsListItem *listItem = new ConnectionsListItem(ui->scrollAreaContents_ConnectionsList, connectionItem->connection, project->mapNames); ui->layout_ConnectionsList->insertWidget(ui->layout_ConnectionsList->count() - 1, listItem); // Insert above the vertical spacer @@ -799,25 +819,20 @@ void Editor::addNewConnection() { newConnection->map_name = defaultMapName; addConnection(map, newConnection); setSelectedConnection(connection_items.last()); - addMirroredConnection(newConnection); } -void Editor::addConnection(Map* map, MapConnection * connection) { +void Editor::addConnection(Map* map, MapConnection * connection, bool addMirror) { if (!map || !connection) return; + if (addMirror) + addMirroredConnection(connection); + map->connections.append(connection); if (map == this->map) { // Adding a connection to the current map, we need to display it visually. - // Note that for the Dive/Emerge combo boxes this is normally redundant - // as the user can only create these by having already set the text, - // *except* in the case where they're connecting a map to itself. - if (connection->direction == "dive") { - const QSignalBlocker blocker(ui->comboBox_DiveMap); - ui->comboBox_DiveMap->setCurrentText(connection->map_name); - } else if (connection->direction == "emerge") { - const QSignalBlocker blocker(ui->comboBox_EmergeMap); - ui->comboBox_EmergeMap->setCurrentText(connection->map_name); + if (connection->direction == "dive" || connection->direction == "emerge") { + createDiveEmergeConnection(connection); } else { createConnectionItem(connection); } @@ -825,19 +840,10 @@ void Editor::addConnection(Map* map, MapConnection * connection) { emit editedMapData(map); } -void Editor::removeConnectionItem(ConnectionPixmapItem* connectionItem, bool removeMirror) { +void Editor::removeConnectionItem(ConnectionPixmapItem* connectionItem) { if (!connectionItem) return; - if (removeMirror) { - // If a map is connected to itself and we delete the connection then this function - // will be called twice, once for the target of the delete and once for its mirror. - // We only want to try deleting the mirror once, on the first call (because the mirror - // of the mirror is the original target again, and we already deleted it). - removeMirroredConnection(connectionItem->connection); - } - removeConnection(map, connectionItem->connection); - connection_items.removeOne(connectionItem); if (connectionItem->scene()) connectionItem->scene()->removeItem(connectionItem); @@ -847,21 +853,48 @@ void Editor::removeConnectionItem(ConnectionPixmapItem* connectionItem, bool rem if (!connection_items.isEmpty()) setSelectedConnection(connection_items.first()); } + + removeConnection(map, connectionItem->connection); + delete connectionItem; } -void Editor::removeConnection(Map* map, MapConnection* connection) { - if (!map) +void Editor::removeSelectedConnection() { + removeConnectionItem(selected_connection_item); +} + +void Editor::removeConnection(Map* map, MapConnection* connection, bool removeMirror) { + if (!map || !connection) return; + + if (removeMirror) + removeMirroredConnection(connection); + + if (map == this->map) { + // The connection to delete is displayed on the currently-opened map, we need to delete it visually as well. + if (connection->direction == "dive") { + clearDiveMap(); + } else if (connection->direction == "emerge") { + clearEmergeMap(); + } else { + // Find and delete the matching connection graphics. + // If this was called via removeConnectionItem we rely on + // the item having already been removed from this list. + for (auto item :connection_items) { + if (item->connection == connection) { + item->connection = nullptr; + removeConnectionItem(item); + break; + } + } + } + } + map->connections.removeOne(connection); delete connection; emit editedMapData(map); } -void Editor::removeSelectedConnection() { - removeConnectionItem(selected_connection_item); -} - MapConnectionMirror Editor::getMirroredConnection(MapConnection* source) { MapConnectionMirror mirror; if (!map || !source || !ui->checkBox_MirrorConnections->isChecked()) @@ -890,46 +923,58 @@ void Editor::addMirroredConnection(MapConnection* source) { if (!mirror.map) return; - mirror.connection = new MapConnection; + mirror.connection = new MapConnection; // TODO: Are we leaking memory here if mirror.connection != nullptr *mirror.connection = MapConnection::mirror(*source, map->name); - addConnection(mirror.map, mirror.connection); + addConnection(mirror.map, mirror.connection, false); } void Editor::removeMirroredConnection(MapConnection* source) { MapConnectionMirror mirror = getMirroredConnection(source); - if (!mirror.map || !mirror.connection) + removeConnection(mirror.map, mirror.connection, false); +} + +void Editor::createDiveEmergeConnection(MapConnection* connection) { + if (!connection) return; + + QGraphicsPixmapItem *item; + Map *connectedMap = project->getMap(connection->map_name); + if (!connectedMap || connectedMap == this->map) { + // There's no point in rendering a map on top of itself. + // We create an empty image anyway to allow for changes later. + item = new QGraphicsPixmapItem(QPixmap()); + } else { + item = new QGraphicsPixmapItem(connectedMap->render()); + } + // TODO: Set pos. In-game, how are diving coordinates converted if the maps are different sizes? + scene->addItem(item); - if (map == mirror.map) { - // The connection to delete is displayed on the currently-opened map, we need to delete it visually as well. - if (source->direction == "dive") { - const QSignalBlocker blocker(ui->comboBox_DiveMap); - ui->comboBox_DiveMap->setCurrentText(""); - } else if (source->direction == "emerge") { - const QSignalBlocker blocker(ui->comboBox_EmergeMap); - ui->comboBox_EmergeMap->setCurrentText(""); - } else { - // Find and delete the matching connection graphics - for (auto item :connection_items) { - if (item->connection == mirror.connection) { - removeConnectionItem(item, false); - return; - } - } - } + if (connection->direction == "dive") { + clearDiveMap(); + dive_map_overlay = item; + const QSignalBlocker blocker(ui->comboBox_DiveMap); + ui->comboBox_DiveMap->setCurrentText(connection->map_name); + } else if (connection->direction == "emerge") { + clearEmergeMap(); + emerge_map_overlay = item; + const QSignalBlocker blocker(ui->comboBox_EmergeMap); + ui->comboBox_EmergeMap->setCurrentText(connection->map_name); + } else { + // Shouldn't happen + scene->removeItem(item); + delete item; } - removeConnection(mirror.map, mirror.connection); } void Editor::updateDiveMap(QString mapName) { - updateDiveEmergeMap(mapName, "dive"); + setDiveEmergeMapName(mapName, "dive"); } void Editor::updateEmergeMap(QString mapName) { - updateDiveEmergeMap(mapName, "emerge"); + setDiveEmergeMapName(mapName, "emerge"); } -void Editor::updateDiveEmergeMap(QString mapName, QString direction) { +void Editor::setDiveEmergeMapName(QString mapName, QString direction) { if (!mapName.isEmpty() && !project->mapNamesToMapConstants.contains(mapName)) { logError(QString("Invalid %1 connection map name: '%2'").arg(direction).arg(mapName)); return; @@ -944,12 +989,12 @@ void Editor::updateDiveEmergeMap(QString mapName, QString direction) { } } - // Dive/Emerge maps aren't represented visually (aside from their combo boxes), - // so we have less to do here than a normal connection. if (connection) { + if (connection->map_name == mapName) + return; + // Update existing connection if (mapName.isEmpty()) { - removeMirroredConnection(connection); removeConnection(map, connection); } else { setConnectionMap(connection, mapName); @@ -961,7 +1006,24 @@ void Editor::updateDiveEmergeMap(QString mapName, QString direction) { connection->offset = 0; connection->map_name = mapName; addConnection(map, connection); - addMirroredConnection(connection); + } + updateDiveEmergeVisibility(); +} + +void Editor::updateDiveEmergeVisibility() { + if (dive_map_overlay && emerge_map_overlay) { + // Both connections in use, use separate sliders + ui->stackedWidget_DiveMapOpacity->setCurrentIndex(0); + dive_map_overlay->setOpacity(!porymapConfig.showDiveEmergeMaps ? 0 : static_cast(porymapConfig.diveMapOpacity) / 100); + emerge_map_overlay->setOpacity(!porymapConfig.showDiveEmergeMaps ? 0 : static_cast(porymapConfig.emergeMapOpacity) / 100); + } else { + // One connection in use (or none), use single slider + ui->stackedWidget_DiveMapOpacity->setCurrentIndex(1); + qreal opacity = !porymapConfig.showDiveEmergeMaps ? 0 : static_cast(porymapConfig.diveEmergeMapOpacity) / 100; + if (dive_map_overlay) + dive_map_overlay->setOpacity(opacity); + else if (emerge_map_overlay) + emerge_map_overlay->setOpacity(opacity); } } @@ -1040,7 +1102,7 @@ void Editor::updateConnectionItemPos(ConnectionPixmapItem* connectionItem) { } void Editor::setConnectionOffset(MapConnection *connection, int offset) { - if (!connection || !map || connection->offset == offset) + if (!connection || !map || connection->offset == offset || !MapConnection::isCardinal(connection->direction)) return; MapConnectionMirror mirror = getMirroredConnection(connection); @@ -1808,29 +1870,55 @@ void Editor::clearMapConnections() { } delete item; } - selected_connection_item = nullptr; connection_items.clear(); -} -void Editor::displayMapConnections() { - clearMapConnections(); + clearDiveMap(); + clearEmergeMap(); + + selected_connection_item = nullptr; +} - const QSignalBlocker blocker1(ui->comboBox_DiveMap); - const QSignalBlocker blocker2(ui->comboBox_EmergeMap); +void Editor::clearDiveMap() { + const QSignalBlocker blocker(ui->comboBox_DiveMap); ui->comboBox_DiveMap->setCurrentText(""); + + if (dive_map_overlay) { + if (dive_map_overlay->scene()){ + dive_map_overlay->scene()->removeItem(dive_map_overlay); + } + delete dive_map_overlay; + dive_map_overlay = nullptr; + } +} + +void Editor::clearEmergeMap() { + const QSignalBlocker blocker(ui->comboBox_EmergeMap); ui->comboBox_EmergeMap->setCurrentText(""); + if (emerge_map_overlay) { + if (emerge_map_overlay->scene()){ + emerge_map_overlay->scene()->removeItem(emerge_map_overlay); + } + delete emerge_map_overlay; + emerge_map_overlay = nullptr; + } +} + +void Editor::displayMapConnections() { + clearMapConnections(); + // Note: We only support editing 1 Dive and Emerge connection per map. // In a vanilla game only the first Dive/Emerge connection is considered, so allowing // users to have multiple is likely to lead to confusion. In case users have changed // this we won't delete extra diving connections, but we'll only display the first one. + // TODO: Move text check to inside createDiveEmergeConnection? for (MapConnection *connection : map->connections) { if (connection->direction == "dive") { if (ui->comboBox_DiveMap->currentText().isEmpty()) - ui->comboBox_DiveMap->setCurrentText(connection->map_name); + createDiveEmergeConnection(connection); } else if (connection->direction == "emerge") { if (ui->comboBox_EmergeMap->currentText().isEmpty()) - ui->comboBox_EmergeMap->setCurrentText(connection->map_name); + createDiveEmergeConnection(connection); } else { // We allow any unknown direction names here. They'll be editable from the list menu. createConnectionItem(connection); @@ -1839,26 +1927,8 @@ void Editor::displayMapConnections() { if (!connection_items.empty()) setSelectedConnection(connection_items.first()); -} - -void Editor::createConnectionItem(MapConnection* connection) { - if (!connection) - return; - QPixmap pixmap = getConnectionPixmap(*connection); - QPoint pos = calculateConnectionPosition(*connection, pixmap); - ConnectionPixmapItem *item = new ConnectionPixmapItem(pixmap, connection, pos.x(), pos.y()); - item->render(); - scene->addItem(item); - - connect(item, &ConnectionPixmapItem::selectionChanged, [this, item](bool selected) { - if (selected) setSelectedConnection(item); - }); - connect(item, &ConnectionPixmapItem::connectionItemDoubleClicked, [this, item] { - emit this->connectionItemDoubleClicked(item->connection->map_name, map->name); - }); - connection_items.append(item); - addConnectionToList(item); + updateDiveEmergeVisibility(); } void Editor::clearConnectionMask() { diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index fc7c72f3c..07a21fbcc 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -471,6 +471,13 @@ void MainWindow::applyMapListFilter(QString filterText) } void MainWindow::loadUserSettings() { + const QSignalBlocker blocker1(ui->horizontalSlider_CollisionTransparency); + const QSignalBlocker blocker2(ui->slider_DiveEmergeMapOpacity); + const QSignalBlocker blocker3(ui->slider_DiveMapOpacity); + const QSignalBlocker blocker4(ui->slider_EmergeMapOpacity); + const QSignalBlocker blocker5(ui->horizontalSlider_MetatileZoom); + const QSignalBlocker blocker6(ui->horizontalSlider_CollisionZoom); + ui->actionBetter_Cursors->setChecked(porymapConfig.prettyCursors); this->editor->settings->betterCursors = porymapConfig.prettyCursors; ui->actionPlayer_View_Rectangle->setChecked(porymapConfig.showPlayerView); @@ -479,17 +486,17 @@ void MainWindow::loadUserSettings() { this->editor->settings->cursorTileRectEnabled = porymapConfig.showCursorTile; ui->checkBox_ToggleBorder->setChecked(porymapConfig.showBorder); ui->checkBox_ToggleGrid->setChecked(porymapConfig.showGrid); + ui->groupBox_DiveMapOpacity->setChecked(porymapConfig.showDiveEmergeMaps); mapSortOrder = porymapConfig.mapSortOrder; - ui->horizontalSlider_CollisionTransparency->blockSignals(true); + this->editor->collisionOpacity = static_cast(porymapConfig.collisionOpacity) / 100; ui->horizontalSlider_CollisionTransparency->setValue(porymapConfig.collisionOpacity); - ui->horizontalSlider_CollisionTransparency->blockSignals(false); - ui->horizontalSlider_MetatileZoom->blockSignals(true); + ui->slider_DiveEmergeMapOpacity->setValue(porymapConfig.diveEmergeMapOpacity); + ui->slider_DiveMapOpacity->setValue(porymapConfig.diveMapOpacity); + ui->slider_EmergeMapOpacity->setValue(porymapConfig.emergeMapOpacity); ui->horizontalSlider_MetatileZoom->setValue(porymapConfig.metatilesZoom); - ui->horizontalSlider_MetatileZoom->blockSignals(false); - ui->horizontalSlider_CollisionZoom->blockSignals(true); ui->horizontalSlider_CollisionZoom->setValue(porymapConfig.collisionZoom); - ui->horizontalSlider_CollisionZoom->blockSignals(false); + setTheme(porymapConfig.theme); } @@ -2263,6 +2270,37 @@ void MainWindow::eventTabChanged(int index) { isProgrammaticEventTabChange = false; } +void MainWindow::on_groupBox_DiveMapOpacity_toggled(bool on) { + // Qt doesn't change the style of disabled sliders, so we do it ourselves + QString stylesheet = on ? "" : "QSlider::groove:horizontal {border: 1px solid #999999; border-radius: 3px; height: 2px; background: #B1B1B1;}" + "QSlider::handle:horizontal {border: 1px solid #444444; border-radius: 3px; width: 10px; height: 9px; margin: -5px -1px; background: #5C5C5C; }"; + ui->slider_DiveEmergeMapOpacity->setStyleSheet(stylesheet); + ui->slider_DiveMapOpacity->setStyleSheet(stylesheet); + ui->slider_EmergeMapOpacity->setStyleSheet(stylesheet); + + porymapConfig.showDiveEmergeMaps = on; + this->editor->updateDiveEmergeVisibility(); +} + +// Normally a map only has either a Dive map connection or an Emerge map connection, +// in which case we only show a single opacity slider to modify the one in use. +// If a user has both connections we show two separate opacity sliders so they can +// modify them independently. +void MainWindow::on_slider_DiveEmergeMapOpacity_valueChanged(int value) { + porymapConfig.diveEmergeMapOpacity = value; + this->editor->updateDiveEmergeVisibility(); +} + +void MainWindow::on_slider_DiveMapOpacity_valueChanged(int value) { + porymapConfig.diveMapOpacity = value; + this->editor->updateDiveEmergeVisibility(); +} + +void MainWindow::on_slider_EmergeMapOpacity_valueChanged(int value) { + porymapConfig.emergeMapOpacity = value; + this->editor->updateDiveEmergeVisibility(); +} + void MainWindow::on_horizontalSlider_CollisionTransparency_valueChanged(int value) { this->editor->collisionOpacity = static_cast(value) / 100; porymapConfig.collisionOpacity = value; From a07517be83a5a576fcf71315b58fc07bb241f3aa Mon Sep 17 00:00:00 2001 From: GriffinR Date: Thu, 25 Jul 2024 15:15:02 -0400 Subject: [PATCH 15/30] Preserve selection when deleting connections --- src/editor.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/editor.cpp b/src/editor.cpp index ba079f501..944119c86 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -844,16 +844,21 @@ void Editor::removeConnectionItem(ConnectionPixmapItem* connectionItem) { if (!connectionItem) return; - connection_items.removeOne(connectionItem); + int index = connection_items.indexOf(connectionItem); + if (index >= 0) { + connection_items.removeAt(index); + if (connectionItem == selected_connection_item) { + // This was the selected connection, select the next one up in the list. + selected_connection_item = nullptr; + if (index != 0) index--; + if (connection_items.length() > index) + setSelectedConnection(connection_items.at(index)); + } + } + if (connectionItem->scene()) connectionItem->scene()->removeItem(connectionItem); - if (connectionItem == selected_connection_item) { - selected_connection_item = nullptr; - if (!connection_items.isEmpty()) - setSelectedConnection(connection_items.first()); - } - removeConnection(map, connectionItem->connection); delete connectionItem; From 2bb01a99882b9b0b2ed3e9a09527e199175a35cf Mon Sep 17 00:00:00 2001 From: GriffinR Date: Thu, 25 Jul 2024 16:32:26 -0400 Subject: [PATCH 16/30] Add dive map toggle under View --- forms/mainwindow.ui | 32 +++++++++++++++++++------------- include/mainwindow.h | 2 ++ src/editor.cpp | 4 ---- src/mainwindow.cpp | 28 ++++++++++++++++++++-------- 4 files changed, 41 insertions(+), 25 deletions(-) diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui index 2428b6194..ff12136e0 100644 --- a/forms/mainwindow.ui +++ b/forms/mainwindow.ui @@ -1715,7 +1715,7 @@ 0 0 100 - 16 + 30 @@ -1809,7 +1809,7 @@ 0 0 100 - 16 + 30 @@ -1903,7 +1903,7 @@ 0 0 100 - 16 + 30 @@ -2003,7 +2003,7 @@ 0 0 100 - 16 + 30 @@ -2097,7 +2097,7 @@ 0 0 100 - 16 + 30 @@ -2596,9 +2596,6 @@ true - - true - @@ -2636,9 +2633,6 @@ true - - true - @@ -2880,8 +2874,8 @@ 0 0 - 365 - 651 + 100 + 30 @@ -3082,6 +3076,7 @@ + @@ -3421,6 +3416,17 @@ Ctrl+W + + + true + + + true + + + Dive/Emerge Map + + diff --git a/include/mainwindow.h b/include/mainwindow.h index 20d3965fc..eb6f4be14 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -269,6 +269,7 @@ private slots: void eventTabChanged(int index); + void on_actionDive_Emerge_Map_triggered(); void on_groupBox_DiveMapOpacity_toggled(bool on); void on_slider_DiveEmergeMapOpacity_valueChanged(int value); void on_slider_DiveMapOpacity_valueChanged(int value); @@ -409,6 +410,7 @@ private slots: int insertTilesetLabel(QStringList * list, QString label); void checkForUpdates(bool requestedByUser); + void setDiveEmergeMapVisible(bool visible); }; enum MapListUserRoles { diff --git a/src/editor.cpp b/src/editor.cpp index 944119c86..b3eefda77 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -951,7 +951,6 @@ void Editor::createDiveEmergeConnection(MapConnection* connection) { } else { item = new QGraphicsPixmapItem(connectedMap->render()); } - // TODO: Set pos. In-game, how are diving coordinates converted if the maps are different sizes? scene->addItem(item); if (connection->direction == "dive") { @@ -995,9 +994,6 @@ void Editor::setDiveEmergeMapName(QString mapName, QString direction) { } if (connection) { - if (connection->map_name == mapName) - return; - // Update existing connection if (mapName.isEmpty()) { removeConnection(map, connection); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 07a21fbcc..519fee165 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -486,7 +486,6 @@ void MainWindow::loadUserSettings() { this->editor->settings->cursorTileRectEnabled = porymapConfig.showCursorTile; ui->checkBox_ToggleBorder->setChecked(porymapConfig.showBorder); ui->checkBox_ToggleGrid->setChecked(porymapConfig.showGrid); - ui->groupBox_DiveMapOpacity->setChecked(porymapConfig.showDiveEmergeMaps); mapSortOrder = porymapConfig.mapSortOrder; this->editor->collisionOpacity = static_cast(porymapConfig.collisionOpacity) / 100; @@ -498,6 +497,7 @@ void MainWindow::loadUserSettings() { ui->horizontalSlider_CollisionZoom->setValue(porymapConfig.collisionZoom); setTheme(porymapConfig.theme); + setDiveEmergeMapVisible(porymapConfig.showDiveEmergeMaps); } void MainWindow::restoreWindowState() { @@ -910,12 +910,8 @@ void MainWindow::displayMapProperties() { ui->frame_3->setEnabled(true); Map *map = editor->map; - ui->comboBox_PrimaryTileset->blockSignals(true); - ui->comboBox_SecondaryTileset->blockSignals(true); ui->comboBox_PrimaryTileset->setCurrentText(map->layout->tileset_primary_label); ui->comboBox_SecondaryTileset->setCurrentText(map->layout->tileset_secondary_label); - ui->comboBox_PrimaryTileset->blockSignals(false); - ui->comboBox_SecondaryTileset->blockSignals(false); ui->comboBox_Song->setCurrentText(map->song); ui->comboBox_Location->setCurrentText(map->location); @@ -1058,8 +1054,10 @@ bool MainWindow::setProjectUI() { ui->comboBox_Type->addItems(project->mapTypes); ui->comboBox_DiveMap->clear(); ui->comboBox_DiveMap->addItems(project->mapNames); + ui->comboBox_DiveMap->setClearButtonEnabled(true); ui->comboBox_EmergeMap->clear(); ui->comboBox_EmergeMap->addItems(project->mapNames); + ui->comboBox_EmergeMap->setClearButtonEnabled(true); sortMapList(); @@ -2270,15 +2268,29 @@ void MainWindow::eventTabChanged(int index) { isProgrammaticEventTabChange = false; } +void MainWindow::on_actionDive_Emerge_Map_triggered() { + setDiveEmergeMapVisible(ui->actionDive_Emerge_Map->isChecked()); +} + void MainWindow::on_groupBox_DiveMapOpacity_toggled(bool on) { + setDiveEmergeMapVisible(on); +} + +void MainWindow::setDiveEmergeMapVisible(bool visible) { // Qt doesn't change the style of disabled sliders, so we do it ourselves - QString stylesheet = on ? "" : "QSlider::groove:horizontal {border: 1px solid #999999; border-radius: 3px; height: 2px; background: #B1B1B1;}" - "QSlider::handle:horizontal {border: 1px solid #444444; border-radius: 3px; width: 10px; height: 9px; margin: -5px -1px; background: #5C5C5C; }"; + QString stylesheet = visible ? "" : "QSlider::groove:horizontal {border: 1px solid #999999; border-radius: 3px; height: 2px; background: #B1B1B1;}" + "QSlider::handle:horizontal {border: 1px solid #444444; border-radius: 3px; width: 10px; height: 9px; margin: -5px -1px; background: #5C5C5C; }"; ui->slider_DiveEmergeMapOpacity->setStyleSheet(stylesheet); ui->slider_DiveMapOpacity->setStyleSheet(stylesheet); ui->slider_EmergeMapOpacity->setStyleSheet(stylesheet); - porymapConfig.showDiveEmergeMaps = on; + // Sync UI toggle elements + const QSignalBlocker blocker1(ui->groupBox_DiveMapOpacity); + const QSignalBlocker blocker2(ui->actionDive_Emerge_Map); + ui->groupBox_DiveMapOpacity->setChecked(visible); + ui->actionDive_Emerge_Map->setChecked(visible); + + porymapConfig.showDiveEmergeMaps = visible; this->editor->updateDiveEmergeVisibility(); } From 7eb3c17f4a029dd6a1f1f86778f5abe2524acdaf Mon Sep 17 00:00:00 2001 From: GriffinR Date: Sat, 3 Aug 2024 20:52:10 -0400 Subject: [PATCH 17/30] Some connection TODO cleanup --- include/editor.h | 1 - src/core/mapconnection.cpp | 2 +- src/editor.cpp | 55 +++++++++++++++++++++----------------- 3 files changed, 32 insertions(+), 26 deletions(-) diff --git a/include/editor.h b/include/editor.h index d4dd0e850..ed8be27c2 100644 --- a/include/editor.h +++ b/include/editor.h @@ -190,7 +190,6 @@ public slots: void updateConnectionItem(ConnectionPixmapItem* connectionItem); void updateConnectionItemPos(ConnectionPixmapItem* connectionItem); void createConnectionItem(MapConnection* connection); - void addConnectionToList(ConnectionPixmapItem* connection); void createDiveEmergeConnection(MapConnection* connection); void setDiveEmergeMapName(QString mapName, QString direction); MapConnectionMirror getMirroredConnection(MapConnection*); diff --git a/src/core/mapconnection.cpp b/src/core/mapconnection.cpp index b249ef566..668a01a1d 100644 --- a/src/core/mapconnection.cpp +++ b/src/core/mapconnection.cpp @@ -13,7 +13,7 @@ MapConnection MapConnection::mirror(const MapConnection &source, const QString & }; MapConnection mirror; - mirror.direction = oppositeDirections.value(source.direction/*, source.direction*/); + mirror.direction = oppositeDirections.value(source.direction, source.direction); mirror.map_name = mapName; mirror.offset = -source.offset; diff --git a/src/editor.cpp b/src/editor.cpp index b3eefda77..13ddd8267 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -728,27 +728,25 @@ void Editor::updateEncounterFields(EncounterFields newFields) { void Editor::createConnectionItem(MapConnection* connection) { if (!connection) return; + + // Create connection image QPixmap pixmap = getConnectionPixmap(*connection); QPoint pos = calculateConnectionPosition(*connection, pixmap); - ConnectionPixmapItem *item = new ConnectionPixmapItem(pixmap, connection, pos.x(), pos.y()); - item->render(); - scene->addItem(item); - - connect(item, &ConnectionPixmapItem::selectionChanged, [this, item](bool selected) { - if (selected) setSelectedConnection(item); - }); - connect(item, &ConnectionPixmapItem::connectionItemDoubleClicked, [this, item] { - emit this->connectionItemDoubleClicked(item->connection->map_name, map->name); - }); - - connection_items.append(item); - addConnectionToList(item); -} + ConnectionPixmapItem *connectionItem = new ConnectionPixmapItem(pixmap, connection, pos.x(), pos.y()); + connectionItem->render(); + scene->addItem(connectionItem); -void Editor::addConnectionToList(ConnectionPixmapItem * connectionItem) { + // Create item for the list panel ConnectionsListItem *listItem = new ConnectionsListItem(ui->scrollAreaContents_ConnectionsList, connectionItem->connection, project->mapNames); ui->layout_ConnectionsList->insertWidget(ui->layout_ConnectionsList->count() - 1, listItem); // Insert above the vertical spacer + connect(connectionItem, &ConnectionPixmapItem::selectionChanged, [this, connectionItem](bool selected) { + if (selected) setSelectedConnection(connectionItem); + }); + connect(connectionItem, &ConnectionPixmapItem::connectionItemDoubleClicked, [this, connectionItem] { + emit this->connectionItemDoubleClicked(connectionItem->connection->map_name, map->name); + }); + // Sync the selection highlight between the list UI and the graphical map connection connect(connectionItem, &ConnectionPixmapItem::selectionChanged, listItem, &ConnectionsListItem::setSelected); connect(listItem, &ConnectionsListItem::selected, [this, connectionItem] { @@ -789,6 +787,8 @@ void Editor::addConnectionToList(ConnectionPixmapItem * connectionItem) { connect(listItem, &ConnectionsListItem::doubleClicked, [this](QString connectedMapName) { emit connectionItemDoubleClicked(connectedMapName, map->name); }); + + connection_items.append(connectionItem); } @@ -924,13 +924,17 @@ MapConnectionMirror Editor::getMirroredConnection(MapConnection* source) { } void Editor::addMirroredConnection(MapConnection* source) { - MapConnectionMirror mirror = getMirroredConnection(source); - if (!mirror.map) + if (!map || !source || !ui->checkBox_MirrorConnections->isChecked()) + return; + + // Note: It's possible (and ok) for connectedMap == this->map + Map* connectedMap = project->getMap(source->map_name); + if (!connectedMap) return; - mirror.connection = new MapConnection; // TODO: Are we leaking memory here if mirror.connection != nullptr - *mirror.connection = MapConnection::mirror(*source, map->name); - addConnection(mirror.map, mirror.connection, false); + MapConnection *mirror = new MapConnection; + *mirror = MapConnection::mirror(*source, map->name); + addConnection(connectedMap, mirror, false); } void Editor::removeMirroredConnection(MapConnection* source) { @@ -938,19 +942,22 @@ void Editor::removeMirroredConnection(MapConnection* source) { removeConnection(mirror.map, mirror.connection, false); } +// TODO: Self-connecting a Dive/Emerge map connection will not actually replace any existing Dive/Emerge connection, if there is one. void Editor::createDiveEmergeConnection(MapConnection* connection) { if (!connection) return; - QGraphicsPixmapItem *item; + // Create image of Dive/Emerge map + QPixmap pixmap; Map *connectedMap = project->getMap(connection->map_name); if (!connectedMap || connectedMap == this->map) { // There's no point in rendering a map on top of itself. // We create an empty image anyway to allow for changes later. - item = new QGraphicsPixmapItem(QPixmap()); + pixmap = QPixmap(); } else { - item = new QGraphicsPixmapItem(connectedMap->render()); + pixmap = connectedMap->render(); } + QGraphicsPixmapItem *item = new QGraphicsPixmapItem(pixmap); scene->addItem(item); if (connection->direction == "dive") { @@ -1986,7 +1993,7 @@ void Editor::displayMapBorder() { item->setX(x * 16); item->setY(y * 16); item->setZValue(-3); - scene->addItem(item); // TODO: If the scene is taking ownership here is a double-free possible? + scene->addItem(item); borderItems.append(item); } } From 4e04e57c05d70f67cc66bb81c0b0db02ef2ec42f Mon Sep 17 00:00:00 2001 From: GriffinR Date: Sun, 4 Aug 2024 16:08:16 -0400 Subject: [PATCH 18/30] MapConnection to QObject --- include/core/map.h | 2 +- include/core/mapconnection.h | 49 +++++--- include/editor.h | 10 +- include/ui/connectionpixmapitem.h | 2 +- src/core/map.cpp | 12 +- src/core/mapconnection.cpp | 77 +++++++++--- src/editor.cpp | 196 ++++++++++++++---------------- src/project.cpp | 20 +-- src/ui/connectionpixmapitem.cpp | 6 +- src/ui/connectionslistitem.cpp | 26 ++-- src/ui/mapimageexporter.cpp | 20 +-- 11 files changed, 236 insertions(+), 184 deletions(-) diff --git a/include/core/map.h b/include/core/map.h index 83f9a9d11..eabe0a8a2 100644 --- a/include/core/map.h +++ b/include/core/map.h @@ -98,7 +98,7 @@ class Map : public QObject QStringList getScriptLabels(Event::Group group = Event::Group::None); void removeEvent(Event *); void addEvent(Event *); - QPixmap renderConnection(const MapConnection&, MapLayout *); + QPixmap renderConnection(const QString &, MapLayout *); QPixmap renderBorder(bool ignoreCache = false); void setDimensions(int newWidth, int newHeight, bool setNewBlockdata = true, bool enableScriptCallback = false); void setBorderDimensions(int newWidth, int newHeight, bool setNewBlockdata = true, bool enableScriptCallback = false); diff --git a/include/core/mapconnection.h b/include/core/mapconnection.h index a70778133..1da62efab 100644 --- a/include/core/mapconnection.h +++ b/include/core/mapconnection.h @@ -3,32 +3,45 @@ #define MAPCONNECTION_H #include -#include +#include -class Map; - -class MapConnection { +class MapConnection : public QObject +{ + Q_OBJECT public: - QString direction; - int offset; - QString map_name; + MapConnection(const QString &direction, const QString &hostMapName, const QString &targetMapName, int offset = 0); + + QString direction() const { return m_direction; } + void setDirection(const QString &direction); + + QString hostMapName() const { return m_hostMapName; } + void setHostMapName(const QString &hostMapName); + + QString targetMapName() const { return m_targetMapName; } + void setTargetMapName(const QString &targetMapName); + + int offset() const { return m_offset; } + void setOffset(int offset); + + MapConnection * createMirror(); + bool isMirror(const MapConnection*); static const QStringList cardinalDirections; static bool isCardinal(const QString &direction); static bool isHorizontal(const QString &direction); static bool isVertical(const QString &direction); - static MapConnection mirror(const MapConnection &source, const QString &mapName); -}; -struct MapConnectionMirror { - MapConnection * connection = nullptr; - Map * map = nullptr; -}; +private: + QString m_direction; + QString m_hostMapName; + QString m_targetMapName; + int m_offset; -inline bool operator==(const MapConnection &c1, const MapConnection &c2) { - return c1.direction == c2.direction && - c1.offset == c2.offset && - c1.map_name == c2.map_name; -} +signals: + void directionChanged(const QString &before, const QString &after); + void targetMapNameChanged(const QString &before, const QString &after); + void hostMapNameChanged(const QString &before, const QString &after); + void offsetChanged(int before, int after); +}; #endif // MAPCONNECTION_H diff --git a/include/editor.h b/include/editor.h index ed8be27c2..982e8f77c 100644 --- a/include/editor.h +++ b/include/editor.h @@ -77,8 +77,8 @@ class Editor : public QObject void setConnectionsVisibility(bool visible); void updateDiveEmergeVisibility(); void addNewConnection(); - void addConnection(Map* map, MapConnection* connection, bool addMirror = true); - void removeConnection(Map* map, MapConnection* connection, bool removeMirror = true); + void addConnection(MapConnection* connection, bool addMirror = true); + void removeConnection(MapConnection* connection, bool removeMirror = true); void removeConnectionItem(ConnectionPixmapItem* connectionItem); void removeSelectedConnection(); void addNewWildMonGroup(QWidget *window); @@ -185,14 +185,14 @@ public slots: void clearMapGrid(); void clearWildMonTables(); void updateBorderVisibility(); - QPoint calculateConnectionPosition(const MapConnection &connection, const QPixmap &pixmap); - QPixmap getConnectionPixmap(const MapConnection &connection); + QPoint calculateConnectionPosition(MapConnection *connection, const QPixmap &pixmap); + QPixmap getConnectionPixmap(MapConnection *connection); void updateConnectionItem(ConnectionPixmapItem* connectionItem); void updateConnectionItemPos(ConnectionPixmapItem* connectionItem); void createConnectionItem(MapConnection* connection); void createDiveEmergeConnection(MapConnection* connection); void setDiveEmergeMapName(QString mapName, QString direction); - MapConnectionMirror getMirroredConnection(MapConnection*); + MapConnection* getMirroredConnection(MapConnection*); void addMirroredConnection(MapConnection*); void removeMirroredConnection(MapConnection*); void updateEncounterFields(EncounterFields newFields); diff --git a/include/ui/connectionpixmapitem.h b/include/ui/connectionpixmapitem.h index e5577d2f5..cd1d66227 100644 --- a/include/ui/connectionpixmapitem.h +++ b/include/ui/connectionpixmapitem.h @@ -17,7 +17,7 @@ class ConnectionPixmapItem : public QObject, public QGraphicsPixmapItem { setFlag(ItemSendsGeometryChanges); this->initialX = x; this->initialY = y; - this->initialOffset = connection->offset; + this->initialOffset = connection->offset(); this->setX(x); this->setY(y); } diff --git a/src/core/map.cpp b/src/core/map.cpp index 40ee9de5d..494ff273a 100644 --- a/src/core/map.cpp +++ b/src/core/map.cpp @@ -217,20 +217,20 @@ QPixmap Map::renderBorder(bool ignoreCache) { return layout->border_pixmap; } -QPixmap Map::renderConnection(const MapConnection &connection, MapLayout * fromLayout) { - if (!MapConnection::isCardinal(connection.direction)) +QPixmap Map::renderConnection(const QString &direction, MapLayout * fromLayout) { + if (!MapConnection::isCardinal(direction)) return QPixmap(); int x = 0, y = 0, w = getWidth(), h = getHeight(); - if (connection.direction == "up") { + if (direction == "up") { y = getHeight() - BORDER_DISTANCE; h = BORDER_DISTANCE; - } else if (connection.direction == "down") { + } else if (direction == "down") { h = BORDER_DISTANCE; - } else if (connection.direction == "left") { + } else if (direction == "left") { x = getWidth() - BORDER_DISTANCE; w = BORDER_DISTANCE; - } else if (connection.direction == "right") { + } else if (direction == "right") { w = BORDER_DISTANCE; } diff --git a/src/core/mapconnection.cpp b/src/core/mapconnection.cpp index 668a01a1d..4e4434bad 100644 --- a/src/core/mapconnection.cpp +++ b/src/core/mapconnection.cpp @@ -1,25 +1,74 @@ +#include #include "mapconnection.h" -#include "map.h" -const QStringList MapConnection::cardinalDirections = { - "up", "down", "left", "right" +const QMap oppositeDirections = { + {"up", "down"}, {"down", "up"}, + {"right", "left"}, {"left", "right"}, + {"dive", "emerge"}, {"emerge", "dive"} }; -MapConnection MapConnection::mirror(const MapConnection &source, const QString &mapName) { - static const QMap oppositeDirections = { - {"up", "down"}, {"down", "up"}, - {"right", "left"}, {"left", "right"}, - {"dive", "emerge"}, {"emerge", "dive"} - }; +MapConnection::MapConnection(const QString &direction, const QString &hostMapName, const QString &targetMapName, int offset) { + m_direction = direction; + m_hostMapName = hostMapName; + m_targetMapName = targetMapName; + m_offset = offset; +} + +void MapConnection::setDirection(const QString &direction) { + if (direction == m_direction) + return; + + auto before = m_direction; + m_direction = direction; + emit directionChanged(before, m_direction); +} + +void MapConnection::setHostMapName(const QString &hostMapName) { + if (hostMapName == m_hostMapName) + return; + + auto before = m_hostMapName; + m_hostMapName = hostMapName; + emit hostMapNameChanged(before, m_hostMapName); + +} + +void MapConnection::setTargetMapName(const QString &targetMapName) { + if (targetMapName == m_targetMapName) + return; - MapConnection mirror; - mirror.direction = oppositeDirections.value(source.direction, source.direction); - mirror.map_name = mapName; - mirror.offset = -source.offset; + auto before = m_targetMapName; + m_targetMapName = targetMapName; + emit targetMapNameChanged(before, m_targetMapName); +} + +void MapConnection::setOffset(int offset) { + if (offset == m_offset) + return; + + auto before = m_offset; + m_offset = offset; + emit offsetChanged(before, m_offset); +} - return mirror; +MapConnection * MapConnection::createMirror() { + return new MapConnection(oppositeDirections.value(m_direction, m_direction), m_targetMapName, m_hostMapName, -m_offset); } +bool MapConnection::isMirror(const MapConnection* other) { + if (!other) + return false; + + return m_hostMapName == other->m_targetMapName + && m_targetMapName == other->m_hostMapName + && m_offset == -other->m_offset + && m_direction == oppositeDirections.value(other->m_direction, other->m_direction); +} + +const QStringList MapConnection::cardinalDirections = { + "up", "down", "left", "right" +}; + bool MapConnection::isHorizontal(const QString &direction) { return direction == "left" || direction == "right"; } diff --git a/src/editor.cpp b/src/editor.cpp index 13ddd8267..817e02eba 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -730,8 +730,8 @@ void Editor::createConnectionItem(MapConnection* connection) { return; // Create connection image - QPixmap pixmap = getConnectionPixmap(*connection); - QPoint pos = calculateConnectionPosition(*connection, pixmap); + QPixmap pixmap = getConnectionPixmap(connection); + QPoint pos = calculateConnectionPosition(connection, pixmap); ConnectionPixmapItem *connectionItem = new ConnectionPixmapItem(pixmap, connection, pos.x(), pos.y()); connectionItem->render(); scene->addItem(connectionItem); @@ -744,7 +744,7 @@ void Editor::createConnectionItem(MapConnection* connection) { if (selected) setSelectedConnection(connectionItem); }); connect(connectionItem, &ConnectionPixmapItem::connectionItemDoubleClicked, [this, connectionItem] { - emit this->connectionItemDoubleClicked(connectionItem->connection->map_name, map->name); + emit this->connectionItemDoubleClicked(connectionItem->connection->targetMapName(), map->name); }); // Sync the selection highlight between the list UI and the graphical map connection @@ -796,7 +796,7 @@ void Editor::addNewConnection() { // Find direction with least number of connections. QMap directionCounts; for (MapConnection* connection : map->connections) { - directionCounts[connection->direction]++; + directionCounts[connection->direction()]++; } QString minDirection = "up"; int minCount = INT_MAX; @@ -813,25 +813,25 @@ void Editor::addNewConnection() { defaultMapName = project->mapNames.at(1); } - MapConnection* newConnection = new MapConnection; - newConnection->direction = minDirection; - newConnection->offset = 0; - newConnection->map_name = defaultMapName; - addConnection(map, newConnection); + addConnection(new MapConnection(minDirection, map->name, defaultMapName)); setSelectedConnection(connection_items.last()); } -void Editor::addConnection(Map* map, MapConnection * connection, bool addMirror) { - if (!map || !connection) +void Editor::addConnection(MapConnection * connection, bool addMirror) { + if (!connection) return; if (addMirror) addMirroredConnection(connection); + Map *map = project->getMap(connection->hostMapName()); + if (!map) + return; + map->connections.append(connection); if (map == this->map) { // Adding a connection to the current map, we need to display it visually. - if (connection->direction == "dive" || connection->direction == "emerge") { + if (connection->direction() == "dive" || connection->direction() == "emerge") { createDiveEmergeConnection(connection); } else { createConnectionItem(connection); @@ -859,7 +859,7 @@ void Editor::removeConnectionItem(ConnectionPixmapItem* connectionItem) { if (connectionItem->scene()) connectionItem->scene()->removeItem(connectionItem); - removeConnection(map, connectionItem->connection); + removeConnection(connectionItem->connection); delete connectionItem; } @@ -868,18 +868,22 @@ void Editor::removeSelectedConnection() { removeConnectionItem(selected_connection_item); } -void Editor::removeConnection(Map* map, MapConnection* connection, bool removeMirror) { - if (!map || !connection) +void Editor::removeConnection(MapConnection* connection, bool removeMirror) { + if (!connection) return; if (removeMirror) removeMirroredConnection(connection); + Map* map = project->getMap(connection->hostMapName()); + if (!map) + return; + if (map == this->map) { // The connection to delete is displayed on the currently-opened map, we need to delete it visually as well. - if (connection->direction == "dive") { + if (connection->direction() == "dive") { clearDiveMap(); - } else if (connection->direction == "emerge") { + } else if (connection->direction() == "emerge") { clearEmergeMap(); } else { // Find and delete the matching connection graphics. @@ -900,46 +904,34 @@ void Editor::removeConnection(Map* map, MapConnection* connection, bool removeMi emit editedMapData(map); } -MapConnectionMirror Editor::getMirroredConnection(MapConnection* source) { - MapConnectionMirror mirror; - if (!map || !source || !ui->checkBox_MirrorConnections->isChecked()) - return mirror; +MapConnection* Editor::getMirroredConnection(MapConnection* source) { + if (!source || !ui->checkBox_MirrorConnections->isChecked()) + return nullptr; - // Note: It's possible (and ok) for mirror.map == this->map - mirror.map = project->getMap(source->map_name); - if (!mirror.map) - return mirror; + // Note: It's possible (and ok) for connectedMap == this->map + Map *connectedMap = project->getMap(source->targetMapName()); + if (!connectedMap) + return nullptr; // Find the matching connection in the connected map. // Note: There is no strict source -> mirror pairing, i.e. we are not guaranteed // to always get the same MapConnection if there are multiple identical copies. - MapConnection target = MapConnection::mirror(*source, map->name); - for (auto connection : mirror.map->connections) { - if (*connection == target && connection != source) { - mirror.connection = connection; - break; - } + for (auto connection : connectedMap->connections) { + if (connection != source && connection->isMirror(source)) + return connection; } - return mirror; + + return nullptr; } void Editor::addMirroredConnection(MapConnection* source) { - if (!map || !source || !ui->checkBox_MirrorConnections->isChecked()) - return; - - // Note: It's possible (and ok) for connectedMap == this->map - Map* connectedMap = project->getMap(source->map_name); - if (!connectedMap) + if (!source || !ui->checkBox_MirrorConnections->isChecked()) return; - - MapConnection *mirror = new MapConnection; - *mirror = MapConnection::mirror(*source, map->name); - addConnection(connectedMap, mirror, false); + addConnection(source->createMirror(), false); } void Editor::removeMirroredConnection(MapConnection* source) { - MapConnectionMirror mirror = getMirroredConnection(source); - removeConnection(mirror.map, mirror.connection, false); + removeConnection(getMirroredConnection(source), false); } // TODO: Self-connecting a Dive/Emerge map connection will not actually replace any existing Dive/Emerge connection, if there is one. @@ -949,7 +941,7 @@ void Editor::createDiveEmergeConnection(MapConnection* connection) { // Create image of Dive/Emerge map QPixmap pixmap; - Map *connectedMap = project->getMap(connection->map_name); + Map *connectedMap = project->getMap(connection->targetMapName()); if (!connectedMap || connectedMap == this->map) { // There's no point in rendering a map on top of itself. // We create an empty image anyway to allow for changes later. @@ -960,16 +952,16 @@ void Editor::createDiveEmergeConnection(MapConnection* connection) { QGraphicsPixmapItem *item = new QGraphicsPixmapItem(pixmap); scene->addItem(item); - if (connection->direction == "dive") { + if (connection->direction() == "dive") { clearDiveMap(); dive_map_overlay = item; const QSignalBlocker blocker(ui->comboBox_DiveMap); - ui->comboBox_DiveMap->setCurrentText(connection->map_name); - } else if (connection->direction == "emerge") { + ui->comboBox_DiveMap->setCurrentText(connection->targetMapName()); + } else if (connection->direction() == "emerge") { clearEmergeMap(); emerge_map_overlay = item; const QSignalBlocker blocker(ui->comboBox_EmergeMap); - ui->comboBox_EmergeMap->setCurrentText(connection->map_name); + ui->comboBox_EmergeMap->setCurrentText(connection->targetMapName()); } else { // Shouldn't happen scene->removeItem(item); @@ -994,7 +986,7 @@ void Editor::setDiveEmergeMapName(QString mapName, QString direction) { // Only the first Dive/Emerge map (if present) is considered, as in-game. MapConnection* connection = nullptr; for (MapConnection* conn : map->connections) { - if (conn->direction == direction) { + if (conn->direction() == direction) { connection = conn; break; } @@ -1003,17 +995,14 @@ void Editor::setDiveEmergeMapName(QString mapName, QString direction) { if (connection) { // Update existing connection if (mapName.isEmpty()) { - removeConnection(map, connection); + removeConnection(connection); } else { setConnectionMap(connection, mapName); } } else if (!mapName.isEmpty()) { // Create new connection - connection = new MapConnection; - connection->direction = direction; - connection->offset = 0; - connection->map_name = mapName; - addConnection(map, connection); + connection = new MapConnection(direction, map->name, mapName); + addConnection(connection); } updateDiveEmergeVisibility(); } @@ -1035,41 +1024,43 @@ void Editor::updateDiveEmergeVisibility() { } } -QPoint Editor::calculateConnectionPosition(const MapConnection &connection, const QPixmap &pixmap) { +QPoint Editor::calculateConnectionPosition(MapConnection *connection, const QPixmap &pixmap) { + const QString direction = connection->direction(); + int offset = connection->offset(); int x = 0, y = 0; const int mWidth = 16, mHeight = 16; - if (connection.direction == "up") { - x = connection.offset * mWidth; + if (direction == "up") { + x = offset * mWidth; y = -pixmap.height(); - } else if (connection.direction == "down") { - x = connection.offset * mWidth; + } else if (direction == "down") { + x = offset * mWidth; y = map->getHeight() * mHeight; - } else if (connection.direction == "left") { + } else if (direction == "left") { x = -pixmap.width(); - y = connection.offset * mHeight; - } else if (connection.direction == "right") { + y = offset * mHeight; + } else if (direction == "right") { x = map->getWidth() * mWidth; - y = connection.offset * mHeight; + y = offset * mHeight; } return QPoint(x, y); } -QPixmap Editor::getConnectionPixmap(const MapConnection &connection) { - Map *connectedMap = project->getMap(connection.map_name); +QPixmap Editor::getConnectionPixmap(MapConnection *connection) { + Map *connectedMap = project->getMap(connection->targetMapName()); // connectedMap will be null for MAP_DYNAMIC and any map that fails to load. // The connection will be editable from the list, but no image will be displayed on the map. if (!connectedMap) return QPixmap(); - return connectedMap->renderConnection(connection, map->layout); + return connectedMap->renderConnection(connection->direction(), this->map->layout); } void Editor::updateConnectionItem(ConnectionPixmapItem* connectionItem) { if (!connectionItem || !connectionItem->connection) return; - const QString mapName = connectionItem->connection->map_name; + const QString mapName = connectionItem->connection->targetMapName(); if (mapName.isEmpty()) return; @@ -1078,18 +1069,17 @@ void Editor::updateConnectionItem(ConnectionPixmapItem* connectionItem) { return; } - connectionItem->initialOffset = connectionItem->connection->offset; - connectionItem->basePixmap = getConnectionPixmap(*connectionItem->connection); - QPoint pos = calculateConnectionPosition(*connectionItem->connection, connectionItem->basePixmap); + connectionItem->initialOffset = connectionItem->connection->offset(); + connectionItem->basePixmap = getConnectionPixmap(connectionItem->connection); + QPoint pos = calculateConnectionPosition(connectionItem->connection, connectionItem->basePixmap); - connectionItem->blockSignals(true); + const QSignalBlocker blocker(connectionItem); connectionItem->setPixmap(connectionItem->basePixmap); connectionItem->initialX = pos.x(); connectionItem->initialY = pos.y(); connectionItem->setX(pos.x()); connectionItem->setY(pos.y()); connectionItem->render(); - connectionItem->blockSignals(false); maskNonVisibleConnectionTiles(); } @@ -1098,37 +1088,39 @@ void Editor::updateConnectionItemPos(ConnectionPixmapItem* connectionItem) { if (!connectionItem || !connectionItem->connection) return; + const QSignalBlocker blocker(connectionItem); MapConnection *connection = connectionItem->connection; - connectionItem->blockSignals(true); - if (MapConnection::isVertical(connection->direction)) { - connectionItem->setX(connectionItem->initialX + (connection->offset - connectionItem->initialOffset) * 16); - } else if (MapConnection::isHorizontal(connection->direction)) { - connectionItem->setY(connectionItem->initialY + (connection->offset - connectionItem->initialOffset) * 16); + if (MapConnection::isVertical(connection->direction())) { + connectionItem->setX(connectionItem->initialX + (connection->offset() - connectionItem->initialOffset) * 16); + } else if (MapConnection::isHorizontal(connection->direction())) { + connectionItem->setY(connectionItem->initialY + (connection->offset() - connectionItem->initialOffset) * 16); } - connectionItem->blockSignals(false); maskNonVisibleConnectionTiles(); } void Editor::setConnectionOffset(MapConnection *connection, int offset) { - if (!connection || !map || connection->offset == offset || !MapConnection::isCardinal(connection->direction)) + if (!connection || !this->map || connection->offset() == offset || !MapConnection::isCardinal(connection->direction())) return; - MapConnectionMirror mirror = getMirroredConnection(connection); - if (mirror.connection && mirror.map) { - mirror.connection->offset = -offset; - if (mirror.map != map) { - emit editedMapData(mirror.map); + MapConnection *mirror = getMirroredConnection(connection); + if (mirror) { + mirror->setOffset(-offset); + + Map *connectedMap = project->getMap(mirror->hostMapName()); + if (connectedMap != this->map) { + emit editedMapData(connectedMap); } else { + // TODO: Remove, this will be handled by connecting to the MapConnection + // The mirror is displayed on the current map, update its graphics for (auto item :connection_items) { - if (item->connection == mirror.connection) { + if (item->connection == mirror) { updateConnectionItemPos(item); break; } } - // TODO: We should be signaling to the list item from the pixmap item, rather than searching for it. for (auto listItem : ui->scrollAreaContents_ConnectionsList->findChildren()) { - if (listItem->connection == mirror.connection){ + if (listItem->connection == mirror){ listItem->updateUI(); break; } @@ -1136,37 +1128,37 @@ void Editor::setConnectionOffset(MapConnection *connection, int offset) { } } - connection->offset = offset; - emit editedMapData(map); + connection->setOffset(offset); + emit editedMapData(this->map); // TODO: This is likely the source of the visual masking bug while dragging (this happens after the move) maskNonVisibleConnectionTiles(); } void Editor::setConnectionMap(MapConnection *connection, const QString &mapName) { - if (!connection || !map || connection->map_name == mapName) + if (!connection || !map || connection->targetMapName() == mapName) return; removeMirroredConnection(connection); - connection->map_name = mapName; + connection->setTargetMapName(mapName); addMirroredConnection(connection); emit editedMapData(map); } void Editor::setConnectionDirection(MapConnection *connection, const QString &direction) { - if (!connection || !map || connection->direction == direction) + if (!connection || !map || connection->direction() == direction) return; // TODO: Lazy removeMirroredConnection(connection); - if (MapConnection::isHorizontal(connection->direction) != MapConnection::isHorizontal(direction) - || MapConnection::isVertical(connection->direction) != MapConnection::isVertical(direction)) { + if (MapConnection::isHorizontal(connection->direction()) != MapConnection::isHorizontal(direction) + || MapConnection::isVertical(connection->direction()) != MapConnection::isVertical(direction)) { // If the direction has changed between vertical/horizontal then the old offset may not make sense, so we reset it setConnectionOffset(connection, 0); } - connection->direction = direction; + connection->setDirection(direction); addMirroredConnection(connection); @@ -1184,9 +1176,9 @@ void Editor::setSelectedConnection(ConnectionPixmapItem* connectionItem) { // TODO: Inaccurate if there are multiple connections from the same map void Editor::setSelectedConnectionFromMap(QString mapName) { - // Search for the first connection that connects to the given map map. + // Search for the first connection that connects to the given map. for (ConnectionPixmapItem* item : connection_items) { - if (item->connection->map_name == mapName) { + if (item->connection->targetMapName() == mapName) { setSelectedConnection(item); break; } @@ -1921,10 +1913,10 @@ void Editor::displayMapConnections() { // this we won't delete extra diving connections, but we'll only display the first one. // TODO: Move text check to inside createDiveEmergeConnection? for (MapConnection *connection : map->connections) { - if (connection->direction == "dive") { + if (connection->direction() == "dive") { if (ui->comboBox_DiveMap->currentText().isEmpty()) createDiveEmergeConnection(connection); - } else if (connection->direction == "emerge") { + } else if (connection->direction() == "emerge") { if (ui->comboBox_EmergeMap->currentText().isEmpty()) createDiveEmergeConnection(connection); } else { @@ -2009,7 +2001,7 @@ void Editor::updateMapConnections() { for (auto item : connection_items) { if (!item->connection) continue; - item->basePixmap = getConnectionPixmap(*item->connection); + item->basePixmap = getConnectionPixmap(item->connection); item->render(); } diff --git a/src/project.cpp b/src/project.cpp index 424872690..60d8ef877 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -370,12 +370,12 @@ bool Project::loadMapData(Map* map) { if (!connectionsArr.isEmpty()) { for (int i = 0; i < connectionsArr.size(); i++) { QJsonObject connectionObj = connectionsArr[i].toObject(); - MapConnection *connection = new MapConnection; - connection->direction = ParseUtil::jsonToQString(connectionObj["direction"]); - connection->offset = ParseUtil::jsonToInt(connectionObj["offset"]); - QString mapConstant = ParseUtil::jsonToQString(connectionObj["map"]); + const QString direction = ParseUtil::jsonToQString(connectionObj["direction"]); + int offset = ParseUtil::jsonToInt(connectionObj["offset"]); + const QString mapConstant = ParseUtil::jsonToQString(connectionObj["map"]); if (mapConstantsToMapNames.contains(mapConstant)) { - connection->map_name = mapConstantsToMapNames.value(mapConstant); + // Successully read map connection + MapConnection *connection = new MapConnection(direction, map->name, mapConstantsToMapNames.value(mapConstant), offset); map->connections.append(connection); } else { logError(QString("Failed to find connected map for map constant '%1'").arg(mapConstant)); @@ -1280,14 +1280,14 @@ void Project::saveMap(Map *map) { if (map->connections.length() > 0) { OrderedJson::array connectionsArr; for (MapConnection* connection : map->connections) { - if (mapNamesToMapConstants.contains(connection->map_name)) { + if (mapNamesToMapConstants.contains(connection->targetMapName())) { OrderedJson::object connectionObj; - connectionObj["map"] = this->mapNamesToMapConstants.value(connection->map_name); - connectionObj["offset"] = connection->offset; - connectionObj["direction"] = connection->direction; + connectionObj["map"] = this->mapNamesToMapConstants.value(connection->targetMapName()); + connectionObj["offset"] = connection->offset(); + connectionObj["direction"] = connection->direction(); connectionsArr.append(connectionObj); } else { - logError(QString("Failed to write map connection. '%1' is not a valid map name").arg(connection->map_name)); + logError(QString("Failed to write map connection. '%1' is not a valid map name").arg(connection->targetMapName())); } } mapObj["connections"] = connectionsArr; diff --git a/src/ui/connectionpixmapitem.cpp b/src/ui/connectionpixmapitem.cpp index 1b7743f9b..14a463581 100644 --- a/src/ui/connectionpixmapitem.cpp +++ b/src/ui/connectionpixmapitem.cpp @@ -33,7 +33,7 @@ QVariant ConnectionPixmapItem::itemChange(GraphicsItemChange change, const QVari qreal x, y; int newOffset = this->initialOffset; - if (MapConnection::isVertical(this->connection->direction)) { + if (MapConnection::isVertical(this->connection->direction())) { x = round(newPos.x() / 16) * 16; newOffset += (x - initialX) / 16; x = newOffset * 16; @@ -42,7 +42,7 @@ QVariant ConnectionPixmapItem::itemChange(GraphicsItemChange change, const QVari x = this->initialX; } - if (MapConnection::isHorizontal(this->connection->direction)) { + if (MapConnection::isHorizontal(this->connection->direction())) { y = round(newPos.y() / 16) * 16; newOffset += (y - this->initialY) / 16; y = newOffset * 16; @@ -51,7 +51,7 @@ QVariant ConnectionPixmapItem::itemChange(GraphicsItemChange change, const QVari y = this->initialY; } - if (this->connection->offset != newOffset) + if (this->connection->offset() != newOffset) emit connectionMoved(this->connection, newOffset); return QPointF(x, y); } diff --git a/src/ui/connectionslistitem.cpp b/src/ui/connectionslistitem.cpp index cf6e30206..b735559a3 100644 --- a/src/ui/connectionslistitem.cpp +++ b/src/ui/connectionslistitem.cpp @@ -35,9 +35,9 @@ void ConnectionsListItem::updateUI() { const QSignalBlocker blocker2(ui->comboBox_Map); const QSignalBlocker blocker3(ui->spinBox_Offset); - ui->comboBox_Direction->setTextItem(this->connection->direction); - ui->comboBox_Map->setTextItem(this->connection->map_name); - ui->spinBox_Offset->setValue(this->connection->offset); + ui->comboBox_Direction->setTextItem(this->connection->direction()); + ui->comboBox_Map->setTextItem(this->connection->targetMapName()); + ui->spinBox_Offset->setValue(this->connection->offset()); } // TODO: Frame shifts slightly when style changes @@ -56,31 +56,27 @@ void ConnectionsListItem::mousePressEvent(QMouseEvent *) { } void ConnectionsListItem::mouseDoubleClickEvent(QMouseEvent *) { - emit doubleClicked(this->connection->map_name); + emit doubleClicked(this->connection->targetMapName()); } -void ConnectionsListItem::on_comboBox_Direction_currentTextChanged(const QString &direction) -{ +void ConnectionsListItem::on_comboBox_Direction_currentTextChanged(const QString &direction) { this->setSelected(true); - if (this->connection->direction != direction) + if (this->connection->direction() != direction) emit this->editedDirection(this->connection, direction); } -void ConnectionsListItem::on_comboBox_Map_currentTextChanged(const QString &mapName) -{ +void ConnectionsListItem::on_comboBox_Map_currentTextChanged(const QString &mapName) { this->setSelected(true); - if (ui->comboBox_Map->findText(mapName) >= 0 && this->connection->map_name != mapName) + if (ui->comboBox_Map->findText(mapName) >= 0 && this->connection->targetMapName() != mapName) emit this->editedMapName(this->connection, mapName); } -void ConnectionsListItem::on_spinBox_Offset_valueChanged(int offset) -{ +void ConnectionsListItem::on_spinBox_Offset_valueChanged(int offset) { this->setSelected(true); - if (this->connection->offset != offset) + if (this->connection->offset() != offset) emit editedOffset(this->connection, offset); } -void ConnectionsListItem::on_button_Delete_clicked() -{ +void ConnectionsListItem::on_button_Delete_clicked() { emit this->removed(); } diff --git a/src/ui/mapimageexporter.cpp b/src/ui/mapimageexporter.cpp index e36d96068..f26a05a30 100644 --- a/src/ui/mapimageexporter.cpp +++ b/src/ui/mapimageexporter.cpp @@ -239,24 +239,26 @@ QPixmap MapImageExporter::getStitchedImage(QProgressDialog *progress, bool inclu stitchedMaps.append(cur); for (MapConnection *connection : cur.map->connections) { - if (connection->direction == "dive" || connection->direction == "emerge") - continue; + const QString direction = connection->direction(); int x = cur.x; int y = cur.y; - int offset = connection->offset; - Map *connectionMap = this->editor->project->loadMap(connection->map_name); - if (connection->direction == "up") { + int offset = connection->offset(); + Map *connectionMap = this->editor->project->loadMap(connection->targetMapName()); + if (direction == "up") { x += offset; y -= connectionMap->getHeight(); - } else if (connection->direction == "down") { + } else if (direction == "down") { x += offset; y += cur.map->getHeight(); - } else if (connection->direction == "left") { + } else if (direction == "left") { x -= connectionMap->getWidth(); y += offset; - } else if (connection->direction == "right") { + } else if (direction == "right") { x += cur.map->getWidth(); y += offset; + } else { + // Ignore Dive/Emerge connections and unrecognized directions + continue; } unvisited.append(StitchedMap{x, y, connectionMap}); } @@ -397,7 +399,7 @@ QPixmap MapImageExporter::getFormattedMapPixmap(Map *map, bool ignoreBorder) { // if showing connections, draw on outside of image QPainter connectionPainter(&pixmap); for (auto connectionItem : editor->connection_items) { - QString direction = connectionItem->connection->direction; + const QString direction = connectionItem->connection->direction(); if ((showUpConnections && direction == "up") || (showDownConnections && direction == "down") || (showLeftConnections && direction == "left") From b5c7f9f86b4d1deebe3d6191d5b67bd18970a612 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Sun, 4 Aug 2024 17:39:56 -0400 Subject: [PATCH 19/30] Save mirroring in config --- include/config.h | 2 ++ include/mainwindow.h | 1 + src/config.cpp | 3 +++ src/editor.cpp | 4 ++-- src/mainwindow.cpp | 6 ++++++ 5 files changed, 14 insertions(+), 2 deletions(-) diff --git a/include/config.h b/include/config.h index a039e4eb4..7486919fc 100644 --- a/include/config.h +++ b/include/config.h @@ -58,6 +58,7 @@ class PorymapConfig: public KeyValueConfigBase this->reopenOnLaunch = true; this->mapSortOrder = MapSortOrder::Group; this->prettyCursors = true; + this->mirrorConnectingMaps = true; this->showDiveEmergeMaps = false; this->diveEmergeMapOpacity = 30; this->diveMapOpacity = 15; @@ -107,6 +108,7 @@ class PorymapConfig: public KeyValueConfigBase bool projectManuallyClosed; MapSortOrder mapSortOrder; bool prettyCursors; + bool mirrorConnectingMaps; bool showDiveEmergeMaps; int diveEmergeMapOpacity; int diveMapOpacity; diff --git a/include/mainwindow.h b/include/mainwindow.h index eb6f4be14..e37c2c564 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -269,6 +269,7 @@ private slots: void eventTabChanged(int index); + void on_checkBox_MirrorConnections_stateChanged(int selected); void on_actionDive_Emerge_Map_triggered(); void on_groupBox_DiveMapOpacity_toggled(bool on); void on_slider_DiveEmergeMapOpacity_valueChanged(int value); diff --git a/src/config.cpp b/src/config.cpp index eb87adf23..818dd714a 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -330,6 +330,8 @@ void PorymapConfig::parseConfigKeyValue(QString key, QString value) { this->mainSplitterState = bytesFromString(value); } else if (key == "metatiles_splitter_state") { this->metatilesSplitterState = bytesFromString(value); + } else if (key == "mirror_connecting_maps") { + this->mirrorConnectingMaps = getConfigBool(key, value); } else if (key == "show_dive_emerge_maps") { this->showDiveEmergeMaps = getConfigBool(key, value); } else if (key == "dive_emerge_map_opacity") { @@ -447,6 +449,7 @@ QMap PorymapConfig::getKeyValueMap() { map.insert("project_settings_editor_state", stringFromByteArray(this->projectSettingsEditorState)); map.insert("custom_scripts_editor_geometry", stringFromByteArray(this->customScriptsEditorGeometry)); map.insert("custom_scripts_editor_state", stringFromByteArray(this->customScriptsEditorState)); + map.insert("mirror_connecting_maps", this->mirrorConnectingMaps ? "1" : "0"); map.insert("show_dive_emerge_maps", this->showDiveEmergeMaps ? "1" : "0"); map.insert("dive_emerge_map_opacity", QString::number(this->diveEmergeMapOpacity)); map.insert("dive_map_opacity", QString::number(this->diveMapOpacity)); diff --git a/src/editor.cpp b/src/editor.cpp index 817e02eba..8fc3b842f 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -905,7 +905,7 @@ void Editor::removeConnection(MapConnection* connection, bool removeMirror) { } MapConnection* Editor::getMirroredConnection(MapConnection* source) { - if (!source || !ui->checkBox_MirrorConnections->isChecked()) + if (!source || !porymapConfig.mirrorConnectingMaps) return nullptr; // Note: It's possible (and ok) for connectedMap == this->map @@ -925,7 +925,7 @@ MapConnection* Editor::getMirroredConnection(MapConnection* source) { } void Editor::addMirroredConnection(MapConnection* source) { - if (!source || !ui->checkBox_MirrorConnections->isChecked()) + if (!source || !porymapConfig.mirrorConnectingMaps) return; addConnection(source->createMirror(), false); } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 519fee165..588547f21 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -486,6 +486,7 @@ void MainWindow::loadUserSettings() { this->editor->settings->cursorTileRectEnabled = porymapConfig.showCursorTile; ui->checkBox_ToggleBorder->setChecked(porymapConfig.showBorder); ui->checkBox_ToggleGrid->setChecked(porymapConfig.showGrid); + ui->checkBox_MirrorConnections->setChecked(porymapConfig.mirrorConnectingMaps); mapSortOrder = porymapConfig.mapSortOrder; this->editor->collisionOpacity = static_cast(porymapConfig.collisionOpacity) / 100; @@ -2807,6 +2808,11 @@ void MainWindow::on_checkBox_ToggleBorder_stateChanged(int selected) editor->toggleBorderVisibility(selected != 0); } +void MainWindow::on_checkBox_MirrorConnections_stateChanged(int selected) +{ + porymapConfig.mirrorConnectingMaps = (selected == Qt::Checked); +} + void MainWindow::on_actionTileset_Editor_triggered() { if (!this->tilesetEditor) { From 4af1c4d463b846efe9bfe6e72269adf15b90bba6 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Sun, 4 Aug 2024 19:11:29 -0400 Subject: [PATCH 20/30] Take advantage of MapConnection as QObject --- include/core/map.h | 3 + include/core/mapconnection.h | 18 +- include/editor.h | 24 +- include/mainwindow.h | 3 +- include/project.h | 1 + include/ui/connectionpixmapitem.h | 9 +- include/ui/connectionslistitem.h | 10 +- src/core/map.cpp | 19 ++ src/core/mapconnection.cpp | 121 ++++++++- src/editor.cpp | 434 ++++++++++-------------------- src/mainwindow.cpp | 22 +- src/project.cpp | 5 +- src/ui/connectionpixmapitem.cpp | 5 +- src/ui/connectionslistitem.cpp | 14 +- 14 files changed, 340 insertions(+), 348 deletions(-) diff --git a/include/core/map.h b/include/core/map.h index eabe0a8a2..1dfc881e7 100644 --- a/include/core/map.h +++ b/include/core/map.h @@ -98,6 +98,8 @@ class Map : public QObject QStringList getScriptLabels(Event::Group group = Event::Group::None); void removeEvent(Event *); void addEvent(Event *); + bool removeConnection(MapConnection *); + void addConnection(MapConnection *); QPixmap renderConnection(const QString &, MapLayout *); QPixmap renderBorder(bool ignoreCache = false); void setDimensions(int newWidth, int newHeight, bool setNewBlockdata = true, bool enableScriptCallback = false); @@ -132,6 +134,7 @@ class Map : public QObject void mapDimensionsChanged(const QSize &size); void mapNeedsRedrawing(); void openScriptRequested(QString label); + void connectionAdded(MapConnection*); }; #endif // MAP_H diff --git a/include/core/mapconnection.h b/include/core/mapconnection.h index 1da62efab..d934b388e 100644 --- a/include/core/mapconnection.h +++ b/include/core/mapconnection.h @@ -4,6 +4,9 @@ #include #include +#include + +class Project; class MapConnection : public QObject { @@ -23,19 +26,32 @@ class MapConnection : public QObject int offset() const { return m_offset; } void setOffset(int offset); - MapConnection * createMirror(); bool isMirror(const MapConnection*); + MapConnection* findMirror(); + MapConnection* createMirror(); + + QPixmap getPixmap(); + static QPointer project; + static const QMap oppositeDirections; static const QStringList cardinalDirections; static bool isCardinal(const QString &direction); static bool isHorizontal(const QString &direction); static bool isVertical(const QString &direction); + static QString oppositeDirection(const QString &direction) { return oppositeDirections.value(direction, direction); } private: QString m_direction; QString m_hostMapName; QString m_targetMapName; int m_offset; + bool m_ignoreMirror; + + void mirrorDirection(const QString &direction); + void mirrorHostMapName(const QString &hostMapName); + void mirrorTargetMapName(const QString &targetMapName); + void mirrorOffset(int offset); + void markMapEdited(); signals: void directionChanged(const QString &before, const QString &after); diff --git a/include/editor.h b/include/editor.h index 982e8f77c..e1a24de66 100644 --- a/include/editor.h +++ b/include/editor.h @@ -46,6 +46,7 @@ class Editor : public QObject QPointer project = nullptr; Map *map = nullptr; Settings *settings; + void setProject(Project * project); void saveProject(); void save(); void closeProject(); @@ -78,8 +79,8 @@ class Editor : public QObject void updateDiveEmergeVisibility(); void addNewConnection(); void addConnection(MapConnection* connection, bool addMirror = true); - void removeConnection(MapConnection* connection, bool removeMirror = true); - void removeConnectionItem(ConnectionPixmapItem* connectionItem); + void removeConnection(MapConnection* connection, bool addMirror = true); + void removeConnectionPixmap(ConnectionPixmapItem* connectionItem); void removeSelectedConnection(); void addNewWildMonGroup(QWidget *window); void deleteWildMonGroup(); @@ -186,15 +187,11 @@ public slots: void clearWildMonTables(); void updateBorderVisibility(); QPoint calculateConnectionPosition(MapConnection *connection, const QPixmap &pixmap); - QPixmap getConnectionPixmap(MapConnection *connection); - void updateConnectionItem(ConnectionPixmapItem* connectionItem); - void updateConnectionItemPos(ConnectionPixmapItem* connectionItem); - void createConnectionItem(MapConnection* connection); - void createDiveEmergeConnection(MapConnection* connection); + void updateConnectionPixmap(ConnectionPixmapItem* connectionItem); + void updateConnectionPixmapPos(ConnectionPixmapItem* connectionItem); + void displayConnection(MapConnection* connection); + void displayDiveEmergeConnection(MapConnection* connection); void setDiveEmergeMapName(QString mapName, QString direction); - MapConnection* getMirroredConnection(MapConnection*); - void addMirroredConnection(MapConnection*); - void removeMirroredConnection(MapConnection*); void updateEncounterFields(EncounterFields newFields); QString getMovementPermissionText(uint16_t collision, uint16_t elevation); QString getMetatileDisplayMessage(uint16_t metatileId); @@ -210,9 +207,6 @@ private slots: void setStraightPathCursorMode(QGraphicsSceneMouseEvent *event); void mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item); void mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixmapItem *item); - void setConnectionOffset(MapConnection *connection, int offset); - void setConnectionMap(MapConnection *connection, const QString &mapName); - void setConnectionDirection(MapConnection *connection, const QString &direction); void setSelectedConnection(ConnectionPixmapItem* connectionItem); void onHoveredMovementPermissionChanged(uint16_t, uint16_t); void onHoveredMovementPermissionCleared(); @@ -225,15 +219,15 @@ private slots: void onSelectedMetatilesChanged(); void onWheelZoom(int); void onToggleGridClicked(bool); + void onMapConnectionDoubleClicked(MapConnection*); signals: void objectsChanged(); - void connectionItemDoubleClicked(QString, QString); + void openConnectedMap(QString, QString); void wildMonDataChanged(); void warpEventDoubleClicked(QString, int, Event::Group); void currentMetatilesSelectionChanged(); void mapRulerStatusChanged(const QString &); - void editedMapData(Map*); void tilesetUpdated(QString); }; diff --git a/include/mainwindow.h b/include/mainwindow.h index e37c2c564..619ee5444 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -178,13 +178,14 @@ private slots: void copy(); void paste(); - void onConnectionItemDoubleClicked(QString, QString); + void onOpenConnectedMap(QString, QString); void onMapNeedsRedrawing(); void onTilesetsSaved(QString, QString); void onWildMonDataChanged(); void openNewMapPopupWindow(); void onNewMapCreated(); void onMapCacheCleared(); + void onMapLoaded(Map *map); void importMapFromAdvanceMap1_92(); void onMapRulerStatusChanged(const QString &); void applyUserShortcuts(); diff --git a/include/project.h b/include/project.h index c9a1a0c08..8c08e5085 100644 --- a/include/project.h +++ b/include/project.h @@ -257,6 +257,7 @@ class Project : public QObject void reloadProject(); void uncheckMonitorFilesAction(); void mapCacheCleared(); + void mapLoaded(Map *map); }; #endif // PROJECT_H diff --git a/include/ui/connectionpixmapitem.h b/include/ui/connectionpixmapitem.h index cd1d66227..969fa6c1b 100644 --- a/include/ui/connectionpixmapitem.h +++ b/include/ui/connectionpixmapitem.h @@ -4,6 +4,7 @@ #include "mapconnection.h" #include #include +#include class ConnectionPixmapItem : public QObject, public QGraphicsPixmapItem { Q_OBJECT @@ -18,11 +19,10 @@ class ConnectionPixmapItem : public QObject, public QGraphicsPixmapItem { this->initialX = x; this->initialY = y; this->initialOffset = connection->offset(); - this->setX(x); - this->setY(y); + this->setPos(x, y); } QPixmap basePixmap; - MapConnection* connection; + QPointer connection; int initialX; int initialY; int initialOffset; @@ -41,8 +41,7 @@ class ConnectionPixmapItem : public QObject, public QGraphicsPixmapItem { void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*); signals: - void connectionItemDoubleClicked(ConnectionPixmapItem* connectionItem); - void connectionMoved(MapConnection *, int newOffset); + void connectionItemDoubleClicked(MapConnection*); void selectionChanged(bool selected); }; diff --git a/include/ui/connectionslistitem.h b/include/ui/connectionslistitem.h index a2ce2c169..9cac56895 100644 --- a/include/ui/connectionslistitem.h +++ b/include/ui/connectionslistitem.h @@ -5,6 +5,7 @@ #include #include +#include namespace Ui { class ConnectionsListItem; @@ -25,7 +26,7 @@ class ConnectionsListItem : public QFrame void updateUI(); void setSelected(bool selected); - MapConnection * connection; + QPointer connection; private: Ui::ConnectionsListItem *ui; @@ -36,12 +37,9 @@ class ConnectionsListItem : public QFrame void mouseDoubleClickEvent(QMouseEvent *); signals: - void editedOffset(MapConnection *connection, int newOffset); - void editedDirection(MapConnection *connection, const QString &direction); - void editedMapName(MapConnection *connection, const QString &mapName); - void removed(); + void removed(MapConnection*); void selected(); - void doubleClicked(const QString &mapName); + void doubleClicked(MapConnection*); private slots: void on_comboBox_Direction_currentTextChanged(const QString &direction); diff --git a/src/core/map.cpp b/src/core/map.cpp index 494ff273a..75191a2dc 100644 --- a/src/core/map.cpp +++ b/src/core/map.cpp @@ -218,6 +218,9 @@ QPixmap Map::renderBorder(bool ignoreCache) { } QPixmap Map::renderConnection(const QString &direction, MapLayout * fromLayout) { + if (direction == "dive" || direction == "emerge") + return render(); + if (!MapConnection::isCardinal(direction)) return QPixmap(); @@ -510,6 +513,22 @@ void Map::addEvent(Event *event) { if (!ownedEvents.contains(event)) ownedEvents.append(event); } +bool Map::removeConnection(MapConnection *connection) { + if (connections.removeOne(connection)) { + modify(); + return true; + } + return false; +} + +void Map::addConnection(MapConnection *connection) { + if (!connection || connections.contains(connection)) + return; + connections.append(connection); + modify(); + emit connectionAdded(connection); +} + void Map::modify() { emit modified(); } diff --git a/src/core/mapconnection.cpp b/src/core/mapconnection.cpp index 4e4434bad..5139d8108 100644 --- a/src/core/mapconnection.cpp +++ b/src/core/mapconnection.cpp @@ -1,7 +1,9 @@ -#include #include "mapconnection.h" +#include "project.h" -const QMap oppositeDirections = { +QPointer MapConnection::project = nullptr; + +const QMap MapConnection::oppositeDirections = { {"up", "down"}, {"down", "up"}, {"right", "left"}, {"left", "right"}, {"dive", "emerge"}, {"emerge", "dive"} @@ -12,57 +14,148 @@ MapConnection::MapConnection(const QString &direction, const QString &hostMapNam m_hostMapName = hostMapName; m_targetMapName = targetMapName; m_offset = offset; + m_ignoreMirror = false; +} + +bool MapConnection::isMirror(const MapConnection* other) { + if (!other) + return false; + + return m_hostMapName == other->m_targetMapName + && m_targetMapName == other->m_hostMapName + && m_offset == -other->m_offset + && m_direction == oppositeDirection(other->m_direction); +} + +MapConnection* MapConnection::findMirror() { + if (!porymapConfig.mirrorConnectingMaps || !project || m_ignoreMirror) + return nullptr; + + Map *connectedMap = project->getMap(m_targetMapName); + if (!connectedMap) + return nullptr; + + // Find the matching connection in the connected map. + // Note: There is no strict source -> mirror pairing, i.e. we are not guaranteed + // to always get the same MapConnection if there are multiple identical copies. + for (auto connection : connectedMap->connections) { + if (this != connection && this->isMirror(connection)) + return connection; + } + return nullptr; +} + +MapConnection * MapConnection::createMirror() { + if (!porymapConfig.mirrorConnectingMaps) + return nullptr; + return new MapConnection(oppositeDirection(m_direction), m_targetMapName, m_hostMapName, -m_offset); +} + +void MapConnection::markMapEdited() { + if (project) { + Map * map = project->getMap(m_hostMapName); + if (map) map->modify(); + } +} + +QPixmap MapConnection::getPixmap() { + if (!project) + return QPixmap(); + + Map *hostMap = project->getMap(m_hostMapName); + Map *targetMap = project->getMap(m_targetMapName); + if (!hostMap || !targetMap) + return QPixmap(); + + return targetMap->renderConnection(m_direction, hostMap->layout); } void MapConnection::setDirection(const QString &direction) { if (direction == m_direction) return; + mirrorDirection(direction); auto before = m_direction; m_direction = direction; emit directionChanged(before, m_direction); + markMapEdited(); +} + +void MapConnection::mirrorDirection(const QString &direction) { + MapConnection * mirror = findMirror(); + if (!mirror) + return; + mirror->m_ignoreMirror = true; + mirror->setDirection(oppositeDirection(direction)); + mirror->m_ignoreMirror = false; } void MapConnection::setHostMapName(const QString &hostMapName) { if (hostMapName == m_hostMapName) return; + mirrorHostMapName(hostMapName); auto before = m_hostMapName; m_hostMapName = hostMapName; + + if (project) { + // TODO: This is probably unexpected design, esp because creating a MapConnection doesn't insert to host map + // Reassign connection to new host map + Map * oldMap = project->getMap(before); + Map * newMap = project->getMap(m_hostMapName); + if (oldMap) oldMap->removeConnection(this); + if (newMap) newMap->addConnection(this); + } emit hostMapNameChanged(before, m_hostMapName); +} +void MapConnection::mirrorHostMapName(const QString &hostMapName) { + MapConnection * mirror = findMirror(); + if (!mirror) + return; + mirror->m_ignoreMirror = true; + mirror->setTargetMapName(hostMapName); + mirror->m_ignoreMirror = false; } void MapConnection::setTargetMapName(const QString &targetMapName) { if (targetMapName == m_targetMapName) return; + mirrorTargetMapName(targetMapName); auto before = m_targetMapName; m_targetMapName = targetMapName; emit targetMapNameChanged(before, m_targetMapName); + markMapEdited(); +} + +void MapConnection::mirrorTargetMapName(const QString &targetMapName) { + MapConnection * mirror = findMirror(); + if (!mirror) + return; + mirror->m_ignoreMirror = true; + mirror->setHostMapName(targetMapName); + mirror->m_ignoreMirror = false; } void MapConnection::setOffset(int offset) { if (offset == m_offset) return; + mirrorOffset(offset); auto before = m_offset; m_offset = offset; emit offsetChanged(before, m_offset); + markMapEdited(); } -MapConnection * MapConnection::createMirror() { - return new MapConnection(oppositeDirections.value(m_direction, m_direction), m_targetMapName, m_hostMapName, -m_offset); -} - -bool MapConnection::isMirror(const MapConnection* other) { - if (!other) - return false; - - return m_hostMapName == other->m_targetMapName - && m_targetMapName == other->m_hostMapName - && m_offset == -other->m_offset - && m_direction == oppositeDirections.value(other->m_direction, other->m_direction); +void MapConnection::mirrorOffset(int offset) { + MapConnection * mirror = findMirror(); + if (!mirror) + return; + mirror->m_ignoreMirror = true; + mirror->setOffset(-offset); + mirror->m_ignoreMirror = false; } const QStringList MapConnection::cardinalDirections = { diff --git a/src/editor.cpp b/src/editor.cpp index 8fc3b842f..c9d1f196c 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -78,6 +78,14 @@ void Editor::saveUiFields() { saveEncounterTabData(); } +void Editor::setProject(Project * project) { + if (this->project) { + closeProject(); + } + this->project = project; + MapConnection::project = project; +} + void Editor::closeProject() { if (!this->project) return; @@ -725,70 +733,83 @@ void Editor::updateEncounterFields(EncounterFields newFields) { project->wildMonFields = newFields; } -void Editor::createConnectionItem(MapConnection* connection) { +void Editor::displayConnection(MapConnection* connection) { if (!connection) return; + // It's possible for a map connection to be displayed repeatedly if it's being + // updated by mirroring and the target map is changing to/from the current map. + connection->disconnect(); + + if (connection->direction() == "dive" || connection->direction() == "emerge") { + displayDiveEmergeConnection(connection); + return; + } + // Create connection image - QPixmap pixmap = getConnectionPixmap(connection); + QPixmap pixmap = connection->getPixmap(); QPoint pos = calculateConnectionPosition(connection, pixmap); - ConnectionPixmapItem *connectionItem = new ConnectionPixmapItem(pixmap, connection, pos.x(), pos.y()); - connectionItem->render(); - scene->addItem(connectionItem); + ConnectionPixmapItem *pixmapItem = new ConnectionPixmapItem(pixmap, connection, pos.x(), pos.y()); + pixmapItem->render(); + scene->addItem(pixmapItem); // Create item for the list panel - ConnectionsListItem *listItem = new ConnectionsListItem(ui->scrollAreaContents_ConnectionsList, connectionItem->connection, project->mapNames); + ConnectionsListItem *listItem = new ConnectionsListItem(ui->scrollAreaContents_ConnectionsList, pixmapItem->connection, project->mapNames); ui->layout_ConnectionsList->insertWidget(ui->layout_ConnectionsList->count() - 1, listItem); // Insert above the vertical spacer - connect(connectionItem, &ConnectionPixmapItem::selectionChanged, [this, connectionItem](bool selected) { - if (selected) setSelectedConnection(connectionItem); + // Double clicking the list item or pixmap opens the connected map + connect(listItem, &ConnectionsListItem::doubleClicked, this, &Editor::onMapConnectionDoubleClicked); + connect(pixmapItem, &ConnectionPixmapItem::connectionItemDoubleClicked, this, &Editor::onMapConnectionDoubleClicked); + + // Sync the selection highlight between the list UI and the pixmap + connect(pixmapItem, &ConnectionPixmapItem::selectionChanged, [this, listItem, pixmapItem](bool selected) { + listItem->setSelected(selected); + if (selected) setSelectedConnection(pixmapItem); }); - connect(connectionItem, &ConnectionPixmapItem::connectionItemDoubleClicked, [this, connectionItem] { - emit this->connectionItemDoubleClicked(connectionItem->connection->targetMapName(), map->name); + connect(listItem, &ConnectionsListItem::selected, [this, pixmapItem] { + setSelectedConnection(pixmapItem); }); - // Sync the selection highlight between the list UI and the graphical map connection - connect(connectionItem, &ConnectionPixmapItem::selectionChanged, listItem, &ConnectionsListItem::setSelected); - connect(listItem, &ConnectionsListItem::selected, [this, connectionItem] { - setSelectedConnection(connectionItem); + // Sync edits to 'offset' between the list UI and the pixmap + connect(connection, &MapConnection::offsetChanged, [this, listItem, pixmapItem](int, int) { + listItem->updateUI(); + updateConnectionPixmapPos(pixmapItem); }); - // Sync edits to 'offset' between the list UI and the graphical map connection - connect(connectionItem, &ConnectionPixmapItem::connectionMoved, [this, listItem](MapConnection* connection, int offset) { - setConnectionOffset(connection, offset); + // Sync edits to 'direction' between the list UI and the pixmap + connect(connection, &MapConnection::directionChanged, [this, listItem, pixmapItem](QString before, QString after) { + if (MapConnection::isHorizontal(before) != MapConnection::isHorizontal(after) + || MapConnection::isVertical(before) != MapConnection::isVertical(after)) { + // If the direction has changed between vertical/horizontal then the old offset may not make sense, so we reset it + pixmapItem->connection->setOffset(0); + } listItem->updateUI(); - }); - connect (listItem, &ConnectionsListItem::editedOffset, [this, connectionItem](MapConnection* connection, int offset) { - setConnectionOffset(connection, offset); - updateConnectionItemPos(connectionItem); + updateConnectionPixmap(pixmapItem); }); - // Sync edits to 'direction' or 'map' between the list UI and the graphical map connection. - // These are 1-way because the direction and map cannot be edited graphically, only via the list UI. - connect(listItem, &ConnectionsListItem::editedDirection, [this, connectionItem, listItem](MapConnection* connection, QString direction) { - setConnectionDirection(connection, direction); - updateConnectionItem(connectionItem); // TODO: Simplify - listItem->updateUI(); // Changing direction may have changed our offset too - }); - connect(listItem, &ConnectionsListItem::editedMapName, [this, connectionItem](MapConnection* connection, QString mapName) { - setConnectionMap(connection, mapName); - updateConnectionItem(connectionItem); + // Sync edits to 'map' between the list UI and the pixmap + connect(connection, &MapConnection::targetMapNameChanged, [this, listItem, pixmapItem](QString, QString) { + listItem->updateUI(); + updateConnectionPixmap(pixmapItem); }); - // Sync deleting the map connection - connect(connectionItem, &ConnectionPixmapItem::destroyed, listItem, &ConnectionsListItem::deleteLater); - connect(listItem, &ConnectionsListItem::removed, [this, connectionItem] { - // 'Remove' button has been clicked. Delete the pixmap. - // The list item will be deleted via the above connection to the pixmap's 'destroyed' signal. - removeConnectionItem(connectionItem); + connect(connection, &MapConnection::hostMapNameChanged, [this, pixmapItem](QString before, QString) { + // A connection was removed from the current map by reassignment. We're deleting the UI elements, + // but not the associated connection (it still exists, but now it belongs to a different map). + // At the moment this is only possible when updating the mirror for a map connected to itself, + // users have no other way (or need) to relocate a map connection like this. + if (before == this->map->name) + removeConnectionPixmap(pixmapItem); }); - // Double clicking the list item opens the connected map - connect(listItem, &ConnectionsListItem::doubleClicked, [this](QString connectedMapName) { - emit connectionItemDoubleClicked(connectedMapName, map->name); - }); + // User manually deleting connection via the remove button + connect(listItem, &ConnectionsListItem::removed, [this](MapConnection* connection) { removeConnection(connection); }); - connection_items.append(connectionItem); + // Sync removing the UI elements. They may be removed when deleting connections or when displaying a new map. + connect(connection, &MapConnection::destroyed, [this, pixmapItem] { removeConnectionPixmap(pixmapItem); }); + connect(pixmapItem, &ConnectionPixmapItem::destroyed, listItem, &ConnectionsListItem::deleteLater); + + connection_items.append(pixmapItem); } @@ -821,33 +842,38 @@ void Editor::addConnection(MapConnection * connection, bool addMirror) { if (!connection) return; - if (addMirror) - addMirroredConnection(connection); + if (addMirror) addConnection(connection->createMirror(), false); Map *map = project->getMap(connection->hostMapName()); - if (!map) + if (map) map->addConnection(connection); + // TODO: Edit history +} + +void Editor::removeConnection(MapConnection* connection, bool removeMirror) { + if (!connection) return; - map->connections.append(connection); - if (map == this->map) { - // Adding a connection to the current map, we need to display it visually. - if (connection->direction() == "dive" || connection->direction() == "emerge") { - createDiveEmergeConnection(connection); - } else { - createConnectionItem(connection); - } - } - emit editedMapData(map); + if (removeMirror) removeConnection(connection->findMirror(), false); + + Map* map = project->getMap(connection->hostMapName()); + if (map) map->removeConnection(connection); + delete connection; + // TODO: Edit history +} + +void Editor::removeSelectedConnection() { + if (selected_connection_item) + removeConnection(selected_connection_item->connection); } -void Editor::removeConnectionItem(ConnectionPixmapItem* connectionItem) { - if (!connectionItem) +void Editor::removeConnectionPixmap(ConnectionPixmapItem* pixmapItem) { + if (!pixmapItem) return; - int index = connection_items.indexOf(connectionItem); + int index = connection_items.indexOf(pixmapItem); if (index >= 0) { connection_items.removeAt(index); - if (connectionItem == selected_connection_item) { + if (pixmapItem == selected_connection_item) { // This was the selected connection, select the next one up in the list. selected_connection_item = nullptr; if (index != 0) index--; @@ -856,117 +882,53 @@ void Editor::removeConnectionItem(ConnectionPixmapItem* connectionItem) { } } - if (connectionItem->scene()) - connectionItem->scene()->removeItem(connectionItem); + if (pixmapItem->scene()) + pixmapItem->scene()->removeItem(pixmapItem); - removeConnection(connectionItem->connection); - - delete connectionItem; -} - -void Editor::removeSelectedConnection() { - removeConnectionItem(selected_connection_item); + delete pixmapItem; } -void Editor::removeConnection(MapConnection* connection, bool removeMirror) { +// TODO: Self-connecting a Dive/Emerge map connection will not actually replace any existing Dive/Emerge connection, if there is one. +void Editor::displayDiveEmergeConnection(MapConnection* connection) { if (!connection) return; - if (removeMirror) - removeMirroredConnection(connection); - - Map* map = project->getMap(connection->hostMapName()); - if (!map) + // Note: We only support editing 1 Dive and Emerge connection per map. + // In a vanilla game only the first Dive/Emerge connection is considered, so allowing + // users to have multiple is likely to lead to confusion. In case users have changed + // this we won't delete extra diving connections, but we'll only display the first one. + if (connection->direction() == "dive") { + if (dive_map_overlay) return; + } else if (connection->direction() == "emerge") { + if (emerge_map_overlay) return; + } else { + // Invalid direction return; - - if (map == this->map) { - // The connection to delete is displayed on the currently-opened map, we need to delete it visually as well. - if (connection->direction() == "dive") { - clearDiveMap(); - } else if (connection->direction() == "emerge") { - clearEmergeMap(); - } else { - // Find and delete the matching connection graphics. - // If this was called via removeConnectionItem we rely on - // the item having already been removed from this list. - for (auto item :connection_items) { - if (item->connection == connection) { - item->connection = nullptr; - removeConnectionItem(item); - break; - } - } - } - } - - map->connections.removeOne(connection); - delete connection; - emit editedMapData(map); -} - -MapConnection* Editor::getMirroredConnection(MapConnection* source) { - if (!source || !porymapConfig.mirrorConnectingMaps) - return nullptr; - - // Note: It's possible (and ok) for connectedMap == this->map - Map *connectedMap = project->getMap(source->targetMapName()); - if (!connectedMap) - return nullptr; - - // Find the matching connection in the connected map. - // Note: There is no strict source -> mirror pairing, i.e. we are not guaranteed - // to always get the same MapConnection if there are multiple identical copies. - for (auto connection : connectedMap->connections) { - if (connection != source && connection->isMirror(source)) - return connection; } - return nullptr; -} - -void Editor::addMirroredConnection(MapConnection* source) { - if (!source || !porymapConfig.mirrorConnectingMaps) - return; - addConnection(source->createMirror(), false); -} - -void Editor::removeMirroredConnection(MapConnection* source) { - removeConnection(getMirroredConnection(source), false); -} - -// TODO: Self-connecting a Dive/Emerge map connection will not actually replace any existing Dive/Emerge connection, if there is one. -void Editor::createDiveEmergeConnection(MapConnection* connection) { - if (!connection) - return; - - // Create image of Dive/Emerge map - QPixmap pixmap; - Map *connectedMap = project->getMap(connection->targetMapName()); - if (!connectedMap || connectedMap == this->map) { - // There's no point in rendering a map on top of itself. - // We create an empty image anyway to allow for changes later. - pixmap = QPixmap(); - } else { - pixmap = connectedMap->render(); - } + // Create image of Dive/Emerge map (unless we'd be rendering the current map on top of itself) + QPixmap pixmap = (connection->targetMapName() == this->map->name) ? QPixmap() : connection->getPixmap(); QGraphicsPixmapItem *item = new QGraphicsPixmapItem(pixmap); scene->addItem(item); if (connection->direction() == "dive") { - clearDiveMap(); dive_map_overlay = item; const QSignalBlocker blocker(ui->comboBox_DiveMap); ui->comboBox_DiveMap->setCurrentText(connection->targetMapName()); - } else if (connection->direction() == "emerge") { - clearEmergeMap(); + connect(connection, &MapConnection::destroyed, this, &Editor::clearDiveMap); + connect(connection, &MapConnection::hostMapNameChanged, this, &Editor::clearDiveMap); + } else { emerge_map_overlay = item; const QSignalBlocker blocker(ui->comboBox_EmergeMap); ui->comboBox_EmergeMap->setCurrentText(connection->targetMapName()); - } else { - // Shouldn't happen - scene->removeItem(item); - delete item; + connect(connection, &MapConnection::destroyed, this, &Editor::clearEmergeMap); + connect(connection, &MapConnection::hostMapNameChanged, this, &Editor::clearEmergeMap); } + + // Update pixmap if the connected map is swapped + connect(connection, &MapConnection::targetMapNameChanged, [this, item, connection] { + item->setPixmap((connection->targetMapName() == this->map->name) ? QPixmap() : connection->getPixmap()); + }); } void Editor::updateDiveMap(QString mapName) { @@ -978,11 +940,6 @@ void Editor::updateEmergeMap(QString mapName) { } void Editor::setDiveEmergeMapName(QString mapName, QString direction) { - if (!mapName.isEmpty() && !project->mapNamesToMapConstants.contains(mapName)) { - logError(QString("Invalid %1 connection map name: '%2'").arg(direction).arg(mapName)); - return; - } - // Only the first Dive/Emerge map (if present) is considered, as in-game. MapConnection* connection = nullptr; for (MapConnection* conn : map->connections) { @@ -996,13 +953,13 @@ void Editor::setDiveEmergeMapName(QString mapName, QString direction) { // Update existing connection if (mapName.isEmpty()) { removeConnection(connection); + // TODO: Queue up another Dive/Emerge map if there is one } else { - setConnectionMap(connection, mapName); + connection->setTargetMapName(mapName); } } else if (!mapName.isEmpty()) { // Create new connection - connection = new MapConnection(direction, map->name, mapName); - addConnection(connection); + addConnection(new MapConnection(direction, map->name, mapName)); } updateDiveEmergeVisibility(); } @@ -1024,6 +981,7 @@ void Editor::updateDiveEmergeVisibility() { } } +// TODO: Fold into PixmapItem QPoint Editor::calculateConnectionPosition(MapConnection *connection, const QPixmap &pixmap) { const QString direction = connection->direction(); int offset = connection->offset(); @@ -1045,132 +1003,46 @@ QPoint Editor::calculateConnectionPosition(MapConnection *connection, const QPix return QPoint(x, y); } -QPixmap Editor::getConnectionPixmap(MapConnection *connection) { - Map *connectedMap = project->getMap(connection->targetMapName()); - - // connectedMap will be null for MAP_DYNAMIC and any map that fails to load. - // The connection will be editable from the list, but no image will be displayed on the map. - if (!connectedMap) - return QPixmap(); - - return connectedMap->renderConnection(connection->direction(), this->map->layout); -} - -void Editor::updateConnectionItem(ConnectionPixmapItem* connectionItem) { - if (!connectionItem || !connectionItem->connection) - return; - - const QString mapName = connectionItem->connection->targetMapName(); - if (mapName.isEmpty()) +void Editor::updateConnectionPixmap(ConnectionPixmapItem* pixmapItem) { + if (!pixmapItem || !pixmapItem->connection) return; - if (!project->mapNames.contains(mapName)) { - logError(QString("Invalid map name '%1' specified for connection.").arg(mapName)); - return; - } + pixmapItem->initialOffset = pixmapItem->connection->offset(); + pixmapItem->basePixmap = pixmapItem->connection->getPixmap(); + QPoint pos = calculateConnectionPosition(pixmapItem->connection, pixmapItem->basePixmap); - connectionItem->initialOffset = connectionItem->connection->offset(); - connectionItem->basePixmap = getConnectionPixmap(connectionItem->connection); - QPoint pos = calculateConnectionPosition(connectionItem->connection, connectionItem->basePixmap); - - const QSignalBlocker blocker(connectionItem); - connectionItem->setPixmap(connectionItem->basePixmap); - connectionItem->initialX = pos.x(); - connectionItem->initialY = pos.y(); - connectionItem->setX(pos.x()); - connectionItem->setY(pos.y()); - connectionItem->render(); + const QSignalBlocker blocker(pixmapItem); + pixmapItem->setPixmap(pixmapItem->basePixmap); + pixmapItem->initialX = pos.x(); + pixmapItem->initialY = pos.y(); + pixmapItem->setPos(pos); + pixmapItem->render(); maskNonVisibleConnectionTiles(); } -void Editor::updateConnectionItemPos(ConnectionPixmapItem* connectionItem) { - if (!connectionItem || !connectionItem->connection) +void Editor::updateConnectionPixmapPos(ConnectionPixmapItem* pixmapItem) { + if (!pixmapItem || !pixmapItem->connection) return; - const QSignalBlocker blocker(connectionItem); - MapConnection *connection = connectionItem->connection; + const QSignalBlocker blocker(pixmapItem); + MapConnection *connection = pixmapItem->connection; if (MapConnection::isVertical(connection->direction())) { - connectionItem->setX(connectionItem->initialX + (connection->offset() - connectionItem->initialOffset) * 16); + qreal x = pixmapItem->initialX + (connection->offset() - pixmapItem->initialOffset) * 16; + if (x != pixmapItem->x()) pixmapItem->setX(x); } else if (MapConnection::isHorizontal(connection->direction())) { - connectionItem->setY(connectionItem->initialY + (connection->offset() - connectionItem->initialOffset) * 16); + qreal y = pixmapItem->initialY + (connection->offset() - pixmapItem->initialOffset) * 16; + if (y != pixmapItem->y()) pixmapItem->setY(y); } maskNonVisibleConnectionTiles(); } -void Editor::setConnectionOffset(MapConnection *connection, int offset) { - if (!connection || !this->map || connection->offset() == offset || !MapConnection::isCardinal(connection->direction())) - return; - - MapConnection *mirror = getMirroredConnection(connection); - if (mirror) { - mirror->setOffset(-offset); - - Map *connectedMap = project->getMap(mirror->hostMapName()); - if (connectedMap != this->map) { - emit editedMapData(connectedMap); - } else { - // TODO: Remove, this will be handled by connecting to the MapConnection - - // The mirror is displayed on the current map, update its graphics - for (auto item :connection_items) { - if (item->connection == mirror) { - updateConnectionItemPos(item); - break; - } - } - for (auto listItem : ui->scrollAreaContents_ConnectionsList->findChildren()) { - if (listItem->connection == mirror){ - listItem->updateUI(); - break; - } - } - } - } - - connection->setOffset(offset); - emit editedMapData(this->map); - - // TODO: This is likely the source of the visual masking bug while dragging (this happens after the move) - maskNonVisibleConnectionTiles(); -} - -void Editor::setConnectionMap(MapConnection *connection, const QString &mapName) { - if (!connection || !map || connection->targetMapName() == mapName) - return; - - removeMirroredConnection(connection); - connection->setTargetMapName(mapName); - addMirroredConnection(connection); - - emit editedMapData(map); -} - -void Editor::setConnectionDirection(MapConnection *connection, const QString &direction) { - if (!connection || !map || connection->direction() == direction) - return; - - // TODO: Lazy - removeMirroredConnection(connection); - - if (MapConnection::isHorizontal(connection->direction()) != MapConnection::isHorizontal(direction) - || MapConnection::isVertical(connection->direction()) != MapConnection::isVertical(direction)) { - // If the direction has changed between vertical/horizontal then the old offset may not make sense, so we reset it - setConnectionOffset(connection, 0); - } - connection->setDirection(direction); - - addMirroredConnection(connection); - - emit editedMapData(map); -} - -void Editor::setSelectedConnection(ConnectionPixmapItem* connectionItem) { - if (!connectionItem || connectionItem == selected_connection_item) +void Editor::setSelectedConnection(ConnectionPixmapItem* pixmapItem) { + if (!pixmapItem || pixmapItem == selected_connection_item) return; if (selected_connection_item) selected_connection_item->setSelected(false); - selected_connection_item = connectionItem; + selected_connection_item = pixmapItem; selected_connection_item->setSelected(true); } @@ -1185,6 +1057,10 @@ void Editor::setSelectedConnectionFromMap(QString mapName) { } } +void Editor::onMapConnectionDoubleClicked(MapConnection* connection) { + emit openConnectedMap(connection->targetMapName(), connection->hostMapName()); +} + void Editor::onBorderMetatilesChanged() { displayMapBorder(); updateBorderVisibility(); // TODO: Why do we need to call this here @@ -1368,6 +1244,8 @@ bool Editor::setMap(QString map_name) { // multiple times if set again in the future if (map) { map->disconnect(this); + for (auto connection : map->connections) + connection->disconnect(); } if (project) { @@ -1387,6 +1265,7 @@ bool Editor::setMap(QString map_name) { map_ruler->setMapDimensions(QSize(map->getWidth(), map->getHeight())); connect(map, &Map::mapDimensionsChanged, map_ruler, &MapRuler::setMapDimensions); connect(map, &Map::openScriptRequested, this, &Editor::openScript); + connect(map, &Map::connectionAdded, this, &Editor::displayConnection); updateSelectedEvents(); } @@ -1907,23 +1786,8 @@ void Editor::clearEmergeMap() { void Editor::displayMapConnections() { clearMapConnections(); - // Note: We only support editing 1 Dive and Emerge connection per map. - // In a vanilla game only the first Dive/Emerge connection is considered, so allowing - // users to have multiple is likely to lead to confusion. In case users have changed - // this we won't delete extra diving connections, but we'll only display the first one. - // TODO: Move text check to inside createDiveEmergeConnection? - for (MapConnection *connection : map->connections) { - if (connection->direction() == "dive") { - if (ui->comboBox_DiveMap->currentText().isEmpty()) - createDiveEmergeConnection(connection); - } else if (connection->direction() == "emerge") { - if (ui->comboBox_EmergeMap->currentText().isEmpty()) - createDiveEmergeConnection(connection); - } else { - // We allow any unknown direction names here. They'll be editable from the list menu. - createConnectionItem(connection); - } - } + for (MapConnection *connection : map->connections) + displayConnection(connection); if (!connection_items.empty()) setSelectedConnection(connection_items.first()); @@ -2001,7 +1865,7 @@ void Editor::updateMapConnections() { for (auto item : connection_items) { if (!item->connection) continue; - item->basePixmap = getConnectionPixmap(item->connection); + item->basePixmap = item->connection->getPixmap(); item->render(); } @@ -2107,7 +1971,7 @@ void Editor::updateBorderVisibility() { void Editor::updateCustomMapHeaderValues(QTableWidget *table) { map->customHeaders = CustomAttributesTable::getAttributes(table); - emit editedMapData(map); + map->modify(); } Tileset* Editor::getCurrentMapPrimaryTileset() diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 588547f21..e47284655 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -306,12 +306,11 @@ void MainWindow::checkForUpdates(bool) {} void MainWindow::initEditor() { this->editor = new Editor(ui); connect(this->editor, &Editor::objectsChanged, this, &MainWindow::updateObjects); - connect(this->editor, &Editor::connectionItemDoubleClicked, this, &MainWindow::onConnectionItemDoubleClicked); + connect(this->editor, &Editor::openConnectedMap, this, &MainWindow::onOpenConnectedMap); connect(this->editor, &Editor::warpEventDoubleClicked, this, &MainWindow::openWarpMap); connect(this->editor, &Editor::currentMetatilesSelectionChanged, this, &MainWindow::currentMetatilesSelectionChanged); connect(this->editor, &Editor::wildMonDataChanged, this, &MainWindow::onWildMonDataChanged); connect(this->editor, &Editor::mapRulerStatusChanged, this, &MainWindow::onMapRulerStatusChanged); - connect(this->editor, &Editor::editedMapData, [this](Map* map) { this->markMapEdited(map); }); connect(this->editor, &Editor::tilesetUpdated, this, &Scripting::cb_TilesetUpdated); connect(ui->toolButton_Open_Scripts, &QToolButton::pressed, this->editor, &Editor::openMapScripts); connect(ui->actionOpen_Project_in_Text_Editor, &QAction::triggered, this->editor, &Editor::openProjectInTextEditor); @@ -569,15 +568,17 @@ bool MainWindow::openProject(QString dir, bool initial) { Scripting::init(this); // Create the project - this->editor->project = new Project(this); - QObject::connect(this->editor->project, &Project::reloadProject, this, &MainWindow::on_action_Reload_Project_triggered); - QObject::connect(this->editor->project, &Project::mapCacheCleared, this, &MainWindow::onMapCacheCleared); - QObject::connect(this->editor->project, &Project::uncheckMonitorFilesAction, [this]() { + auto project = new Project(this); + project->set_root(dir); + QObject::connect(project, &Project::reloadProject, this, &MainWindow::on_action_Reload_Project_triggered); + QObject::connect(project, &Project::mapCacheCleared, this, &MainWindow::onMapCacheCleared); + QObject::connect(project, &Project::mapLoaded, this, &MainWindow::onMapLoaded); + QObject::connect(project, &Project::uncheckMonitorFilesAction, [this]() { porymapConfig.monitorFiles = false; if (this->preferenceEditor) this->preferenceEditor->updateFields(); }); - this->editor->project->set_root(dir); + this->editor->setProject(project); // Make sure project looks reasonable before attempting to load it if (!checkProjectSanity()) { @@ -805,7 +806,6 @@ bool MainWindow::setMap(QString map_name, bool scrollTreeView) { showWindowTitle(); connect(editor->map, &Map::mapNeedsRedrawing, this, &MainWindow::onMapNeedsRedrawing); - connect(editor->map, &Map::modified, [this](){ this->markMapEdited(); }); userConfig.recentMap = map_name; updateMapList(); @@ -2526,7 +2526,7 @@ void MainWindow::clickToolButtonFromEditMode(QString editMode) { } } -void MainWindow::onConnectionItemDoubleClicked(QString mapName, QString fromMapName) { +void MainWindow::onOpenConnectedMap(QString mapName, QString fromMapName) { if (mapName != fromMapName && userSetMap(mapName, true)) editor->setSelectedConnectionFromMap(fromMapName); } @@ -2539,6 +2539,10 @@ void MainWindow::onMapCacheCleared() { editor->map = nullptr; } +void MainWindow::onMapLoaded(Map *map) { + connect(map, &Map::modified, [this, map] { this->markMapEdited(map); }); +} + void MainWindow::onTilesetsSaved(QString primaryTilesetLabel, QString secondaryTilesetLabel) { // If saved tilesets are currently in-use, update them and redraw // Otherwise overwrite the cache for the saved tileset diff --git a/src/project.cpp b/src/project.cpp index 60d8ef877..d60c8a096 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -186,10 +186,13 @@ Map* Project::loadMap(QString map_name) { map->setName(map_name); } - if (!(loadMapData(map) && loadMapLayout(map))) + if (!(loadMapData(map) && loadMapLayout(map))){ + delete map; return nullptr; + } mapCache.insert(map_name, map); + emit mapLoaded(map); return map; } diff --git a/src/ui/connectionpixmapitem.cpp b/src/ui/connectionpixmapitem.cpp index 14a463581..c98d3ba78 100644 --- a/src/ui/connectionpixmapitem.cpp +++ b/src/ui/connectionpixmapitem.cpp @@ -51,8 +51,7 @@ QVariant ConnectionPixmapItem::itemChange(GraphicsItemChange change, const QVari y = this->initialY; } - if (this->connection->offset() != newOffset) - emit connectionMoved(this->connection, newOffset); + this->connection->setOffset(newOffset); return QPointF(x, y); } else { @@ -84,5 +83,5 @@ void ConnectionPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *) { } void ConnectionPixmapItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *) { - emit connectionItemDoubleClicked(this); + emit connectionItemDoubleClicked(this->connection); } diff --git a/src/ui/connectionslistitem.cpp b/src/ui/connectionslistitem.cpp index b735559a3..fd2532bff 100644 --- a/src/ui/connectionslistitem.cpp +++ b/src/ui/connectionslistitem.cpp @@ -56,27 +56,25 @@ void ConnectionsListItem::mousePressEvent(QMouseEvent *) { } void ConnectionsListItem::mouseDoubleClickEvent(QMouseEvent *) { - emit doubleClicked(this->connection->targetMapName()); + emit doubleClicked(this->connection); } void ConnectionsListItem::on_comboBox_Direction_currentTextChanged(const QString &direction) { this->setSelected(true); - if (this->connection->direction() != direction) - emit this->editedDirection(this->connection, direction); + this->connection->setDirection(direction); } void ConnectionsListItem::on_comboBox_Map_currentTextChanged(const QString &mapName) { this->setSelected(true); - if (ui->comboBox_Map->findText(mapName) >= 0 && this->connection->targetMapName() != mapName) - emit this->editedMapName(this->connection, mapName); + if (ui->comboBox_Map->findText(mapName) >= 0) + this->connection->setTargetMapName(mapName); } void ConnectionsListItem::on_spinBox_Offset_valueChanged(int offset) { this->setSelected(true); - if (this->connection->offset() != offset) - emit editedOffset(this->connection, offset); + this->connection->setOffset(offset); } void ConnectionsListItem::on_button_Delete_clicked() { - emit this->removed(); + emit this->removed(this->connection); } From edb4a6799462d2b923d1f276896cef5f181a7fb7 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Thu, 8 Aug 2024 17:26:42 -0400 Subject: [PATCH 21/30] Simplify map list icon updating --- include/mainwindow.h | 3 +- src/editor.cpp | 1 - src/mainwindow.cpp | 75 +++++++++++++++++++++++++------------------- 3 files changed, 44 insertions(+), 35 deletions(-) diff --git a/include/mainwindow.h b/include/mainwindow.h index 619ee5444..ebc0ea162 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -340,7 +340,6 @@ private slots: QMap lastSelectedEvent; bool isProgrammaticEventTabChange; - bool projectHasUnsavedChanges; bool newMapDefaultsSet = false; MapSortOrder mapSortOrder; @@ -366,7 +365,7 @@ private slots: QStandardItem* createMapItem(QString mapName, int groupNum, int inGroupNum); void refreshRecentProjectsMenu(); - void drawMapListIcons(QAbstractItemModel *model); + void updateMapListIcon(const QString &mapName); void updateMapList(); void displayMapProperties(); diff --git a/src/editor.cpp b/src/editor.cpp index c9d1f196c..64ba76d37 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -981,7 +981,6 @@ void Editor::updateDiveEmergeVisibility() { } } -// TODO: Fold into PixmapItem QPoint Editor::calculateConnectionPosition(MapConnection *connection, const QPixmap &pixmap) { const QString direction = connection->direction(); int offset = connection->offset(); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index e47284655..5f6e3573d 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -421,9 +421,7 @@ void MainWindow::markMapEdited(Map* map) { return; map->hasUnsavedDataChanges = true; - // TODO: Only update the necessary list icon - updateMapList(); - + updateMapListIcon(map->name); if (editor && editor->map == map) showWindowTitle(); } @@ -807,8 +805,10 @@ bool MainWindow::setMap(QString map_name, bool scrollTreeView) { connect(editor->map, &Map::mapNeedsRedrawing, this, &MainWindow::onMapNeedsRedrawing); + // Swap the "currently-open" icon from the old map to the new map + updateMapListIcon(userConfig.recentMap); userConfig.recentMap = map_name; - updateMapList(); + updateMapListIcon(userConfig.recentMap); Scripting::cb_MapOpened(map_name); prefab.updatePrefabUi(editor->map); @@ -1535,46 +1535,54 @@ void MainWindow::on_mapList_activated(const QModelIndex &index) userSetMap(data.toString()); } -void MainWindow::drawMapListIcons(QAbstractItemModel *model) { - projectHasUnsavedChanges = false; +void MainWindow::updateMapListIcon(const QString &mapName) { + if (!editor->project || !editor->project->mapCache.contains(mapName)) + return; + + QStandardItem *item = mapListModel->itemFromIndex(mapListIndexes.value(mapName)); + if (!item) + return; + + if (editor->map && editor->map->name == mapName) { + item->setIcon(*mapOpenedIcon); + } else if (editor->project->mapCache.value(mapName)->hasUnsavedChanges()) { + item->setIcon(*mapEditedIcon); + } else { + item->setIcon(*mapIcon); + } +} + +void MainWindow::updateMapList() { QList list; list.append(QModelIndex()); while (list.length()) { QModelIndex parent = list.takeFirst(); - for (int i = 0; i < model->rowCount(parent); i++) { - QModelIndex index = model->index(i, 0, parent); - if (model->hasChildren(index)) { + for (int i = 0; i < mapListModel->rowCount(parent); i++) { + QModelIndex index = mapListModel->index(i, 0, parent); + if (mapListModel->hasChildren(index)) { list.append(index); } QVariant data = index.data(Qt::UserRole); if (!data.isNull()) { - QString map_name = data.toString(); - if (editor->project && editor->project->mapCache.contains(map_name)) { - QStandardItem *map = mapListModel->itemFromIndex(mapListIndexes.value(map_name)); - map->setIcon(*mapIcon); - if (editor->project->mapCache.value(map_name)->hasUnsavedChanges()) { - map->setIcon(*mapEditedIcon); - projectHasUnsavedChanges = true; - } - if (editor->map->name == map_name) { - map->setIcon(*mapOpenedIcon); - } - } + updateMapListIcon(data.toString()); } } } } -void MainWindow::updateMapList() { - drawMapListIcons(mapListModel); -} - void MainWindow::on_action_Save_Project_triggered() { editor->saveProject(); updateMapList(); showWindowTitle(); } +void MainWindow::on_action_Save_triggered() { + editor->save(); + if (editor->map) + updateMapListIcon(editor->map->name); + showWindowTitle(); +} + void MainWindow::duplicate() { editor->duplicateSelectedEvents(); } @@ -1827,12 +1835,6 @@ void MainWindow::paste() { } } -void MainWindow::on_action_Save_triggered() { - editor->save(); - updateMapList(); - showWindowTitle(); -} - void MainWindow::on_mapViewTab_tabBarClicked(int index) { int oldIndex = ui->mapViewTab->currentIndex(); @@ -3128,7 +3130,16 @@ bool MainWindow::closeProject() { if (!isProjectOpen()) return true; - if (projectHasUnsavedChanges || (editor->map && editor->map->hasUnsavedChanges())) { + // Check loaded maps for unsaved changes + bool unsavedChanges = false; + for (auto map : editor->project->mapCache.values()) { + if (map && map->hasUnsavedChanges()) { + unsavedChanges = true; + break; + } + } + + if (unsavedChanges) { QMessageBox::StandardButton result = QMessageBox::question( this, "porymap", "The project has been modified, save changes?", QMessageBox::No | QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes); From 6fbc6d8d8604cdc6d2adf23627eeb29b5c72da0d Mon Sep 17 00:00:00 2001 From: GriffinR Date: Thu, 8 Aug 2024 21:24:15 -0400 Subject: [PATCH 22/30] Prompt for new map connections --- forms/newmapconnectiondialog.ui | 95 +++++++++++++++++++++++++++++ include/editor.h | 2 +- include/ui/newmapconnectiondialog.h | 29 +++++++++ porymap.pro | 3 + src/editor.cpp | 31 ++-------- src/mainwindow.cpp | 8 ++- src/ui/newmapconnectiondialog.cpp | 62 +++++++++++++++++++ 7 files changed, 201 insertions(+), 29 deletions(-) create mode 100644 forms/newmapconnectiondialog.ui create mode 100644 include/ui/newmapconnectiondialog.h create mode 100644 src/ui/newmapconnectiondialog.cpp diff --git a/forms/newmapconnectiondialog.ui b/forms/newmapconnectiondialog.ui new file mode 100644 index 000000000..da1096047 --- /dev/null +++ b/forms/newmapconnectiondialog.ui @@ -0,0 +1,95 @@ + + + NewMapConnectionDialog + + + + 0 + 0 + 234 + 120 + + + + Add New Map Connection + + + + + + QFrame::NoFrame + + + QFrame::Plain + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Map + + + + + + + + + + Direction + + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + NoScrollComboBox + QComboBox +
noscrollcombobox.h
+
+
+ + + + buttonBox + accepted() + NewMapConnectionDialog + accept() + + + buttonBox + rejected() + NewMapConnectionDialog + reject() + + +
diff --git a/include/editor.h b/include/editor.h index e1a24de66..db07fd874 100644 --- a/include/editor.h +++ b/include/editor.h @@ -77,7 +77,6 @@ class Editor : public QObject void setMapEditingButtonsEnabled(bool enabled); void setConnectionsVisibility(bool visible); void updateDiveEmergeVisibility(); - void addNewConnection(); void addConnection(MapConnection* connection, bool addMirror = true); void removeConnection(MapConnection* connection, bool addMirror = true); void removeConnectionPixmap(ConnectionPixmapItem* connectionItem); @@ -86,6 +85,7 @@ class Editor : public QObject void deleteWildMonGroup(); void updateDiveMap(QString mapName); void updateEmergeMap(QString mapName); + void selectLastConnection(); void setSelectedConnectionFromMap(QString mapName); void updatePrimaryTileset(QString tilesetLabel, bool forceLoad = false); void updateSecondaryTileset(QString tilesetLabel, bool forceLoad = false); diff --git a/include/ui/newmapconnectiondialog.h b/include/ui/newmapconnectiondialog.h new file mode 100644 index 000000000..8d0535153 --- /dev/null +++ b/include/ui/newmapconnectiondialog.h @@ -0,0 +1,29 @@ +#ifndef NEWMAPCONNECTIONDIALOG_H +#define NEWMAPCONNECTIONDIALOG_H + +#include +#include "map.h" +#include "mapconnection.h" + +namespace Ui { +class NewMapConnectionDialog; +} + +class NewMapConnectionDialog : public QDialog +{ + Q_OBJECT + +public: + explicit NewMapConnectionDialog(QWidget *parent, Map* map, const QStringList &mapNames); + ~NewMapConnectionDialog(); + + MapConnection *result; + + virtual void accept() override; + +private: + Ui::NewMapConnectionDialog *ui; + Map *map; +}; + +#endif // NEWMAPCONNECTIONDIALOG_H diff --git a/porymap.pro b/porymap.pro index 8afc99a5b..8f7855412 100644 --- a/porymap.pro +++ b/porymap.pro @@ -55,6 +55,7 @@ SOURCES += src/core/block.cpp \ src/ui/collisionpixmapitem.cpp \ src/ui/connectionpixmapitem.cpp \ src/ui/currentselectedmetatilespixmapitem.cpp \ + src/ui/newmapconnectiondialog.cpp \ src/ui/overlay.cpp \ src/ui/prefab.cpp \ src/ui/projectsettingseditor.cpp \ @@ -149,6 +150,7 @@ HEADERS += include/core/block.h \ include/ui/collisionpixmapitem.h \ include/ui/connectionpixmapitem.h \ include/ui/currentselectedmetatilespixmapitem.h \ + include/ui/newmapconnectiondialog.h \ include/ui/prefabframe.h \ include/ui/projectsettingseditor.h \ include/ui/regionmaplayoutpixmapitem.h \ @@ -209,6 +211,7 @@ HEADERS += include/core/block.h \ FORMS += forms/mainwindow.ui \ forms/connectionslistitem.ui \ + forms/newmapconnectiondialog.ui \ forms/prefabcreationdialog.ui \ forms/prefabframe.ui \ forms/tileseteditor.ui \ diff --git a/src/editor.cpp b/src/editor.cpp index 64ba76d37..db93600cb 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -752,6 +752,7 @@ void Editor::displayConnection(MapConnection* connection) { ConnectionPixmapItem *pixmapItem = new ConnectionPixmapItem(pixmap, connection, pos.x(), pos.y()); pixmapItem->render(); scene->addItem(pixmapItem); + maskNonVisibleConnectionTiles(); // Create item for the list panel ConnectionsListItem *listItem = new ConnectionsListItem(ui->scrollAreaContents_ConnectionsList, pixmapItem->connection, project->mapNames); @@ -812,32 +813,6 @@ void Editor::displayConnection(MapConnection* connection) { connection_items.append(pixmapItem); } - -void Editor::addNewConnection() { - // Find direction with least number of connections. - QMap directionCounts; - for (MapConnection* connection : map->connections) { - directionCounts[connection->direction()]++; - } - QString minDirection = "up"; - int minCount = INT_MAX; - for (QString direction : MapConnection::cardinalDirections) { - if (directionCounts[direction] < minCount) { - minDirection = direction; - minCount = directionCounts[direction]; - } - } - - // Prefer not to connect the map to itself (we have to if it's the only map). - QString defaultMapName = project->mapNames.first(); - if (defaultMapName == map->name && project->mapNames.length() > 1) { - defaultMapName = project->mapNames.at(1); - } - - addConnection(new MapConnection(minDirection, map->name, defaultMapName)); - setSelectedConnection(connection_items.last()); -} - void Editor::addConnection(MapConnection * connection, bool addMirror) { if (!connection) return; @@ -1056,6 +1031,10 @@ void Editor::setSelectedConnectionFromMap(QString mapName) { } } +void Editor::selectLastConnection() { + setSelectedConnection(connection_items.last()); +} + void Editor::onMapConnectionDoubleClicked(MapConnection* connection) { emit openConnectedMap(connection->targetMapName(), connection->hostMapName()); } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 5f6e3573d..81e19609a 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -19,6 +19,7 @@ #include "prefab.h" #include "montabwidget.h" #include "imageexport.h" +#include "newmapconnectiondialog.h" #include #include @@ -2649,8 +2650,11 @@ void MainWindow::showExportMapImageWindow(ImageExporterMode mode) { void MainWindow::on_pushButton_AddConnection_clicked() { - // TODO: Bring up a prompt for information? - editor->addNewConnection(); + auto dialog = new NewMapConnectionDialog(this, this->editor->map, this->editor->project->mapNames); + if(dialog->exec() == QDialog::Accepted) { + this->editor->addConnection(dialog->result); + this->editor->selectLastConnection(); + } } void MainWindow::on_pushButton_NewWildMonGroup_clicked() { diff --git a/src/ui/newmapconnectiondialog.cpp b/src/ui/newmapconnectiondialog.cpp new file mode 100644 index 000000000..3a7aa4819 --- /dev/null +++ b/src/ui/newmapconnectiondialog.cpp @@ -0,0 +1,62 @@ +#include "newmapconnectiondialog.h" +#include "ui_newmapconnectiondialog.h" + +NewMapConnectionDialog::NewMapConnectionDialog(QWidget *parent, Map* map, const QStringList &mapNames) : + QDialog(parent), + ui(new Ui::NewMapConnectionDialog) +{ + ui->setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); + + this->map = map; + this->result = nullptr; + + ui->comboBox_Direction->setEditable(false); + ui->comboBox_Direction->setMinimumContentsLength(0); + ui->comboBox_Direction->addItems(MapConnection::cardinalDirections); + + ui->comboBox_Map->setMinimumContentsLength(6); + ui->comboBox_Map->addItems(mapNames); + + // Choose default direction + QMap directionCounts; + for (auto connection : map->connections) { + directionCounts[connection->direction()]++; + } + QString defaultDirection; + int minCount = INT_MAX; + for (auto direction : MapConnection::cardinalDirections) { + if (directionCounts[direction] < minCount) { + defaultDirection = direction; + minCount = directionCounts[direction]; + } + } + ui->comboBox_Direction->setTextItem(defaultDirection); + + // Choose default map + QString defaultMapName; + if (mapNames.isEmpty()) { + defaultMapName = QString(); + } else if (mapNames.first() == map->name && mapNames.length() > 1) { + // Prefer not to connect the map to itself + defaultMapName = mapNames.at(1); + } else { + defaultMapName = mapNames.first(); + } + ui->comboBox_Map->setTextItem(defaultMapName); +} + +NewMapConnectionDialog::~NewMapConnectionDialog() +{ + delete ui; +} + +void NewMapConnectionDialog::accept() { + QString direction = ui->comboBox_Direction->currentText(); + QString hostMapName = this->map ? this->map->name : QString(); + QString targetMapName = ui->comboBox_Map->currentText(); + + this->result = new MapConnection(direction, this->map->name, targetMapName); + + QDialog::accept(); +} From 168616771459e16a899b986d37d9a15565d987db Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 9 Aug 2024 01:29:28 -0400 Subject: [PATCH 23/30] Fix more minor map connection issues --- forms/connectionslistitem.ui | 3 + include/core/map.h | 9 +- include/core/mapconnection.h | 34 ++-- include/editor.h | 30 ++-- include/mainwindow.h | 8 +- include/ui/divingmappixmapitem.h | 35 ++++ include/ui/newmapconnectiondialog.h | 1 - porymap.pro | 1 + src/core/map.cpp | 59 +++++-- src/core/mapconnection.cpp | 162 ++++++++--------- src/editor.cpp | 264 +++++++++++++++------------- src/mainwindow.cpp | 55 +++--- src/project.cpp | 15 +- src/ui/connectionslistitem.cpp | 4 +- src/ui/mapimageexporter.cpp | 2 +- src/ui/newmapconnectiondialog.cpp | 10 +- 16 files changed, 379 insertions(+), 313 deletions(-) create mode 100644 include/ui/divingmappixmapitem.h diff --git a/forms/connectionslistitem.ui b/forms/connectionslistitem.ui index 434c5a297..c39c86d01 100644 --- a/forms/connectionslistitem.ui +++ b/forms/connectionslistitem.ui @@ -16,6 +16,9 @@ 0 + + .ConnectionsListItem { border-width: 1px; } + QFrame::StyledPanel diff --git a/include/core/map.h b/include/core/map.h index 1dfc881e7..9f039a6fb 100644 --- a/include/core/map.h +++ b/include/core/map.h @@ -69,7 +69,6 @@ class Map : public QObject QMap> events; QList ownedEvents; // for memory management - QList connections; QList metatileLayerOrder; QList metatileLayerOpacity; @@ -98,8 +97,11 @@ class Map : public QObject QStringList getScriptLabels(Event::Group group = Event::Group::None); void removeEvent(Event *); void addEvent(Event *); - bool removeConnection(MapConnection *); + void deleteConnections(); + QList getConnections() const; + void removeConnection(MapConnection *); void addConnection(MapConnection *); + void loadConnection(MapConnection *); QPixmap renderConnection(const QString &, MapLayout *); QPixmap renderBorder(bool ignoreCache = false); void setDimensions(int newWidth, int newHeight, bool setNewBlockdata = true, bool enableScriptCallback = false); @@ -129,12 +131,15 @@ class Map : public QObject void setNewDimensionsBlockdata(int newWidth, int newHeight); void setNewBorderDimensionsBlockdata(int newWidth, int newHeight); + QList connections; + signals: void modified(); void mapDimensionsChanged(const QSize &size); void mapNeedsRedrawing(); void openScriptRequested(QString label); void connectionAdded(MapConnection*); + void connectionRemoved(MapConnection*); }; #endif // MAP_H diff --git a/include/core/mapconnection.h b/include/core/mapconnection.h index d934b388e..956574dc7 100644 --- a/include/core/mapconnection.h +++ b/include/core/mapconnection.h @@ -7,24 +7,27 @@ #include class Project; +class Map; class MapConnection : public QObject { Q_OBJECT public: - MapConnection(const QString &direction, const QString &hostMapName, const QString &targetMapName, int offset = 0); + MapConnection(const QString &targetMapName, const QString &direction, int offset = 0); - QString direction() const { return m_direction; } - void setDirection(const QString &direction); - - QString hostMapName() const { return m_hostMapName; } - void setHostMapName(const QString &hostMapName); + Map* parentMap() const { return m_parentMap; } + QString parentMapName() const; + void setParentMap(Map* map, bool mirror = true); + Map* targetMap() const; QString targetMapName() const { return m_targetMapName; } - void setTargetMapName(const QString &targetMapName); + void setTargetMapName(const QString &targetMapName, bool mirror = true); + + QString direction() const { return m_direction; } + void setDirection(const QString &direction, bool mirror = true); int offset() const { return m_offset; } - void setOffset(int offset); + void setOffset(int offset, bool mirror = true); bool isMirror(const MapConnection*); MapConnection* findMirror(); @@ -38,25 +41,22 @@ class MapConnection : public QObject static bool isCardinal(const QString &direction); static bool isHorizontal(const QString &direction); static bool isVertical(const QString &direction); + static bool isDiving(const QString &direction); static QString oppositeDirection(const QString &direction) { return oppositeDirections.value(direction, direction); } private: - QString m_direction; - QString m_hostMapName; + Map* m_parentMap; QString m_targetMapName; + QString m_direction; int m_offset; - bool m_ignoreMirror; - void mirrorDirection(const QString &direction); - void mirrorHostMapName(const QString &hostMapName); - void mirrorTargetMapName(const QString &targetMapName); - void mirrorOffset(int offset); void markMapEdited(); + Map* getMap(const QString& mapName) const; signals: - void directionChanged(const QString &before, const QString &after); + void parentMapChanged(Map* before, Map* after); void targetMapNameChanged(const QString &before, const QString &after); - void hostMapNameChanged(const QString &before, const QString &after); + void directionChanged(const QString &before, const QString &after); void offsetChanged(int before, int after); }; diff --git a/include/editor.h b/include/editor.h index db07fd874..86d5bfdbb 100644 --- a/include/editor.h +++ b/include/editor.h @@ -18,6 +18,7 @@ #include "ui_mainwindow.h" #include "bordermetatilespixmapitem.h" #include "connectionpixmapitem.h" +#include "divingmappixmapitem.h" #include "currentselectedmetatilespixmapitem.h" #include "collisionpixmapitem.h" #include "mappixmapitem.h" @@ -76,17 +77,15 @@ class Editor : public QObject void setEditingConnections(); void setMapEditingButtonsEnabled(bool enabled); void setConnectionsVisibility(bool visible); - void updateDiveEmergeVisibility(); - void addConnection(MapConnection* connection, bool addMirror = true); - void removeConnection(MapConnection* connection, bool addMirror = true); - void removeConnectionPixmap(ConnectionPixmapItem* connectionItem); + void updateDivingMapsVisibility(); + void addConnection(MapConnection* connection); + void removeConnection(MapConnection* connection); void removeSelectedConnection(); void addNewWildMonGroup(QWidget *window); void deleteWildMonGroup(); void updateDiveMap(QString mapName); void updateEmergeMap(QString mapName); - void selectLastConnection(); - void setSelectedConnectionFromMap(QString mapName); + void setSelectedConnection(MapConnection *connection); void updatePrimaryTileset(QString tilesetLabel, bool forceLoad = false); void updateSecondaryTileset(QString tilesetLabel, bool forceLoad = false); void toggleBorderVisibility(bool visible, bool enableScriptCallback = true); @@ -111,10 +110,9 @@ class Editor : public QObject QPointer scene = nullptr; QGraphicsPixmapItem *current_view = nullptr; QPointer map_item = nullptr; - ConnectionPixmapItem* selected_connection_item = nullptr; - QList connection_items; - QGraphicsPixmapItem *dive_map_overlay = nullptr; - QGraphicsPixmapItem *emerge_map_overlay = nullptr; + QPointer selected_connection_item = nullptr; + QList> connection_items; + QMap> diving_map_items; QGraphicsPathItem *connection_mask = nullptr; QPointer collision_item = nullptr; QGraphicsItemGroup *events_group = nullptr; @@ -179,19 +177,19 @@ public slots: void clearCurrentMetatilesSelection(); void clearMapEvents(); void clearMapConnections(); - void clearDiveMap(); - void clearEmergeMap(); void clearConnectionMask(); void clearMapBorder(); void clearMapGrid(); void clearWildMonTables(); void updateBorderVisibility(); QPoint calculateConnectionPosition(MapConnection *connection, const QPixmap &pixmap); + void removeConnectionPixmap(MapConnection* connection); void updateConnectionPixmap(ConnectionPixmapItem* connectionItem); void updateConnectionPixmapPos(ConnectionPixmapItem* connectionItem); void displayConnection(MapConnection* connection); - void displayDiveEmergeConnection(MapConnection* connection); - void setDiveEmergeMapName(QString mapName, QString direction); + void displayDivingConnection(MapConnection* connection); + void setDivingMapName(QString mapName, QString direction); + void removeDivingMapPixmap(MapConnection* connection); void updateEncounterFields(EncounterFields newFields); QString getMovementPermissionText(uint16_t collision, uint16_t elevation); QString getMetatileDisplayMessage(uint16_t metatileId); @@ -207,7 +205,7 @@ private slots: void setStraightPathCursorMode(QGraphicsSceneMouseEvent *event); void mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item); void mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixmapItem *item); - void setSelectedConnection(ConnectionPixmapItem* connectionItem); + void setSelectedConnectionItem(ConnectionPixmapItem* connectionItem); void onHoveredMovementPermissionChanged(uint16_t, uint16_t); void onHoveredMovementPermissionCleared(); void onHoveredMetatileSelectionChanged(uint16_t); @@ -223,7 +221,7 @@ private slots: signals: void objectsChanged(); - void openConnectedMap(QString, QString); + void openConnectedMap(MapConnection*); void wildMonDataChanged(); void warpEventDoubleClicked(QString, int, Event::Group); void currentMetatilesSelectionChanged(); diff --git a/include/mainwindow.h b/include/mainwindow.h index ebc0ea162..644cafd40 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -178,7 +178,7 @@ private slots: void copy(); void paste(); - void onOpenConnectedMap(QString, QString); + void onOpenConnectedMap(MapConnection*); void onMapNeedsRedrawing(); void onTilesetsSaved(QString, QString); void onWildMonDataChanged(); @@ -321,9 +321,7 @@ private slots: QStandardItemModel *mapListModel; QList *mapGroupItemsList; QMap mapListIndexes; - QIcon* mapIcon; - QIcon* mapEditedIcon; - QIcon* mapOpenedIcon; + QIcon mapIcon; QAction *undoAction = nullptr; QAction *redoAction = nullptr; @@ -411,7 +409,7 @@ private slots: int insertTilesetLabel(QStringList * list, QString label); void checkForUpdates(bool requestedByUser); - void setDiveEmergeMapVisible(bool visible); + void setDivingMapsVisible(bool visible); }; enum MapListUserRoles { diff --git a/include/ui/divingmappixmapitem.h b/include/ui/divingmappixmapitem.h new file mode 100644 index 000000000..96b47e479 --- /dev/null +++ b/include/ui/divingmappixmapitem.h @@ -0,0 +1,35 @@ +#ifndef DIVINGMAPPIXMAPITEM_H +#define DIVINGMAPPIXMAPITEM_H + +#include "mapconnection.h" + +#include +#include + +class DivingMapPixmapItem : public QObject, public QGraphicsPixmapItem { + Q_OBJECT +public: + DivingMapPixmapItem(MapConnection* connection) + : QGraphicsPixmapItem(getBasePixmap(connection)) + { + m_connection = connection; + setZValue(2); + + // Update pixmap if the connected map is swapped. + connect(m_connection, &MapConnection::targetMapNameChanged, this, &DivingMapPixmapItem::updatePixmap); + } + MapConnection* connection() const { return m_connection; } + +private: + QPointer m_connection; + + static QPixmap getBasePixmap(MapConnection* connection) { + // If the map is connected to itself then rendering is pointless. + if (!connection || connection->targetMapName() == connection->parentMapName()) + return QPixmap(); + return connection->getPixmap(); + } + void updatePixmap() { setPixmap(getBasePixmap(m_connection)); } +}; + +#endif // DIVINGMAPPIXMAPITEM_H diff --git a/include/ui/newmapconnectiondialog.h b/include/ui/newmapconnectiondialog.h index 8d0535153..3b37c4544 100644 --- a/include/ui/newmapconnectiondialog.h +++ b/include/ui/newmapconnectiondialog.h @@ -23,7 +23,6 @@ class NewMapConnectionDialog : public QDialog private: Ui::NewMapConnectionDialog *ui; - Map *map; }; #endif // NEWMAPCONNECTIONDIALOG_H diff --git a/porymap.pro b/porymap.pro index 8f7855412..e5cad6dda 100644 --- a/porymap.pro +++ b/porymap.pro @@ -145,6 +145,7 @@ HEADERS += include/core/block.h \ include/ui/connectionslistitem.h \ include/ui/customscriptseditor.h \ include/ui/customscriptslistitem.h \ + include/ui/divingmappixmapitem.h \ include/ui/draggablepixmapitem.h \ include/ui/bordermetatilespixmapitem.h \ include/ui/collisionpixmapitem.h \ diff --git a/src/core/map.cpp b/src/core/map.cpp index 75191a2dc..b0abe1258 100644 --- a/src/core/map.cpp +++ b/src/core/map.cpp @@ -17,11 +17,9 @@ Map::Map(QObject *parent) : QObject(parent) } Map::~Map() { - // delete all associated events - while (!ownedEvents.isEmpty()) { - Event *last = ownedEvents.takeLast(); - if (last) delete last; - } + qDeleteAll(ownedEvents); + ownedEvents.clear(); + deleteConnections(); } void Map::setName(QString mapName) { @@ -219,7 +217,7 @@ QPixmap Map::renderBorder(bool ignoreCache) { QPixmap Map::renderConnection(const QString &direction, MapLayout * fromLayout) { if (direction == "dive" || direction == "emerge") - return render(); + return render(true); if (!MapConnection::isCardinal(direction)) return QPixmap(); @@ -513,22 +511,57 @@ void Map::addEvent(Event *event) { if (!ownedEvents.contains(event)) ownedEvents.append(event); } -bool Map::removeConnection(MapConnection *connection) { - if (connections.removeOne(connection)) { - modify(); - return true; - } - return false; +void Map::deleteConnections() { + qDeleteAll(connections); + connections.clear(); +} + +QList Map::getConnections() const { + return connections; } void Map::addConnection(MapConnection *connection) { if (!connection || connections.contains(connection)) return; - connections.append(connection); + + // Adding new Dive/Emerge maps replaces an existing one. + if (MapConnection::isDiving(connection->direction())) { + for (auto connectionToReplace : connections) { + if (connectionToReplace->direction() != connection->direction()) + continue; + if (porymapConfig.mirrorConnectingMaps) { + auto mirror = connectionToReplace->findMirror(); + if (mirror && mirror->parentMap()) + mirror->parentMap()->removeConnection(mirror); + delete mirror; + } + removeConnection(connectionToReplace); + delete connectionToReplace; + break; + } + } + + loadConnection(connection); modify(); emit connectionAdded(connection); } +void Map::loadConnection(MapConnection *connection) { + if (!connection) + return; + connections.append(connection); + connection->setParentMap(this, false); +} + +// Caller takes ownership of connection +void Map::removeConnection(MapConnection *connection) { + if (!connections.removeOne(connection)) + return; + connection->setParentMap(nullptr, false); + modify(); + emit connectionRemoved(connection); +} + void Map::modify() { emit modified(); } diff --git a/src/core/mapconnection.cpp b/src/core/mapconnection.cpp index 5139d8108..5fe2e730c 100644 --- a/src/core/mapconnection.cpp +++ b/src/core/mapconnection.cpp @@ -9,36 +9,32 @@ const QMap MapConnection::oppositeDirections = { {"dive", "emerge"}, {"emerge", "dive"} }; -MapConnection::MapConnection(const QString &direction, const QString &hostMapName, const QString &targetMapName, int offset) { - m_direction = direction; - m_hostMapName = hostMapName; +MapConnection::MapConnection(const QString &targetMapName, const QString &direction, int offset) { + m_parentMap = nullptr; m_targetMapName = targetMapName; + m_direction = direction; m_offset = offset; - m_ignoreMirror = false; } bool MapConnection::isMirror(const MapConnection* other) { - if (!other) + if (!other || !other->m_parentMap) return false; - return m_hostMapName == other->m_targetMapName - && m_targetMapName == other->m_hostMapName + return parentMapName() == other->m_targetMapName + && m_targetMapName == other->parentMapName() && m_offset == -other->m_offset && m_direction == oppositeDirection(other->m_direction); } MapConnection* MapConnection::findMirror() { - if (!porymapConfig.mirrorConnectingMaps || !project || m_ignoreMirror) - return nullptr; - - Map *connectedMap = project->getMap(m_targetMapName); - if (!connectedMap) + auto map = targetMap(); + if (!map) return nullptr; // Find the matching connection in the connected map. // Note: There is no strict source -> mirror pairing, i.e. we are not guaranteed // to always get the same MapConnection if there are multiple identical copies. - for (auto connection : connectedMap->connections) { + for (auto connection : map->getConnections()) { if (this != connection && this->isMirror(connection)) return connection; } @@ -46,122 +42,114 @@ MapConnection* MapConnection::findMirror() { } MapConnection * MapConnection::createMirror() { - if (!porymapConfig.mirrorConnectingMaps) - return nullptr; - return new MapConnection(oppositeDirection(m_direction), m_targetMapName, m_hostMapName, -m_offset); + auto mirror = new MapConnection(parentMapName(), oppositeDirection(m_direction), -m_offset); + mirror->setParentMap(targetMap(), false); + return mirror; } void MapConnection::markMapEdited() { - if (project) { - Map * map = project->getMap(m_hostMapName); - if (map) map->modify(); - } + if (m_parentMap) + m_parentMap->modify(); } -QPixmap MapConnection::getPixmap() { - if (!project) - return QPixmap(); +Map* MapConnection::getMap(const QString& mapName) const { + return project ? project->getMap(mapName) : nullptr; +} - Map *hostMap = project->getMap(m_hostMapName); - Map *targetMap = project->getMap(m_targetMapName); - if (!hostMap || !targetMap) +Map* MapConnection::targetMap() const { + return getMap(m_targetMapName); +} + +QPixmap MapConnection::getPixmap() { + auto map = targetMap(); + if (!map) return QPixmap(); - return targetMap->renderConnection(m_direction, hostMap->layout); + return map->renderConnection(m_direction, m_parentMap ? m_parentMap->layout : nullptr); } -void MapConnection::setDirection(const QString &direction) { - if (direction == m_direction) +void MapConnection::setParentMap(Map* map, bool mirror) { + if (map == m_parentMap) return; - mirrorDirection(direction); - auto before = m_direction; - m_direction = direction; - emit directionChanged(before, m_direction); - markMapEdited(); -} + if (mirror && porymapConfig.mirrorConnectingMaps) { + auto connection = findMirror(); + if (connection) + connection->setTargetMapName(map ? map->name : QString(), false); + } -void MapConnection::mirrorDirection(const QString &direction) { - MapConnection * mirror = findMirror(); - if (!mirror) - return; - mirror->m_ignoreMirror = true; - mirror->setDirection(oppositeDirection(direction)); - mirror->m_ignoreMirror = false; -} + if (m_parentMap) + m_parentMap->removeConnection(this); -void MapConnection::setHostMapName(const QString &hostMapName) { - if (hostMapName == m_hostMapName) - return; + auto before = m_parentMap; + m_parentMap = map; - mirrorHostMapName(hostMapName); - auto before = m_hostMapName; - m_hostMapName = hostMapName; - - if (project) { - // TODO: This is probably unexpected design, esp because creating a MapConnection doesn't insert to host map - // Reassign connection to new host map - Map * oldMap = project->getMap(before); - Map * newMap = project->getMap(m_hostMapName); - if (oldMap) oldMap->removeConnection(this); - if (newMap) newMap->addConnection(this); - } - emit hostMapNameChanged(before, m_hostMapName); + if (m_parentMap) + m_parentMap->addConnection(this); + + emit parentMapChanged(before, m_parentMap); } -void MapConnection::mirrorHostMapName(const QString &hostMapName) { - MapConnection * mirror = findMirror(); - if (!mirror) - return; - mirror->m_ignoreMirror = true; - mirror->setTargetMapName(hostMapName); - mirror->m_ignoreMirror = false; +QString MapConnection::parentMapName() const { + return m_parentMap ? m_parentMap->name : QString(); } -void MapConnection::setTargetMapName(const QString &targetMapName) { +void MapConnection::setTargetMapName(const QString &targetMapName, bool mirror) { if (targetMapName == m_targetMapName) return; - mirrorTargetMapName(targetMapName); + if (mirror && porymapConfig.mirrorConnectingMaps) { + auto connection = findMirror(); + if (connection) + connection->setParentMap(getMap(targetMapName), false); + } + auto before = m_targetMapName; m_targetMapName = targetMapName; emit targetMapNameChanged(before, m_targetMapName); markMapEdited(); } -void MapConnection::mirrorTargetMapName(const QString &targetMapName) { - MapConnection * mirror = findMirror(); - if (!mirror) +void MapConnection::setDirection(const QString &direction, bool mirror) { + if (direction == m_direction) return; - mirror->m_ignoreMirror = true; - mirror->setHostMapName(targetMapName); - mirror->m_ignoreMirror = false; + + if (mirror && porymapConfig.mirrorConnectingMaps) { + auto connection = findMirror(); + if (connection) + connection->setDirection(oppositeDirection(direction), false); + } + + auto before = m_direction; + m_direction = direction; + emit directionChanged(before, m_direction); + markMapEdited(); } -void MapConnection::setOffset(int offset) { +void MapConnection::setOffset(int offset, bool mirror) { if (offset == m_offset) return; - mirrorOffset(offset); + if (mirror && porymapConfig.mirrorConnectingMaps) { + auto connection = findMirror(); + if (connection) + connection->setOffset(-offset, false); + } + auto before = m_offset; m_offset = offset; emit offsetChanged(before, m_offset); markMapEdited(); } -void MapConnection::mirrorOffset(int offset) { - MapConnection * mirror = findMirror(); - if (!mirror) - return; - mirror->m_ignoreMirror = true; - mirror->setOffset(-offset); - mirror->m_ignoreMirror = false; -} - const QStringList MapConnection::cardinalDirections = { "up", "down", "left", "right" }; +bool MapConnection::isCardinal(const QString &direction) { + return cardinalDirections.contains(direction); +} + bool MapConnection::isHorizontal(const QString &direction) { return direction == "left" || direction == "right"; } @@ -170,6 +158,6 @@ bool MapConnection::isVertical(const QString &direction) { return direction == "up" || direction == "down"; } -bool MapConnection::isCardinal(const QString &direction) { - return cardinalDirections.contains(direction); +bool MapConnection::isDiving(const QString &direction) { + return direction == "dive" || direction == "emerge"; } diff --git a/src/editor.cpp b/src/editor.cpp index db93600cb..981fbd57f 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -741,8 +741,8 @@ void Editor::displayConnection(MapConnection* connection) { // updated by mirroring and the target map is changing to/from the current map. connection->disconnect(); - if (connection->direction() == "dive" || connection->direction() == "emerge") { - displayDiveEmergeConnection(connection); + if (MapConnection::isDiving(connection->direction())) { + displayDivingConnection(connection); return; } @@ -765,10 +765,10 @@ void Editor::displayConnection(MapConnection* connection) { // Sync the selection highlight between the list UI and the pixmap connect(pixmapItem, &ConnectionPixmapItem::selectionChanged, [this, listItem, pixmapItem](bool selected) { listItem->setSelected(selected); - if (selected) setSelectedConnection(pixmapItem); + if (selected) setSelectedConnectionItem(pixmapItem); }); connect(listItem, &ConnectionsListItem::selected, [this, pixmapItem] { - setSelectedConnection(pixmapItem); + setSelectedConnectionItem(pixmapItem); }); // Sync edits to 'offset' between the list UI and the pixmap @@ -790,49 +790,47 @@ void Editor::displayConnection(MapConnection* connection) { // Sync edits to 'map' between the list UI and the pixmap connect(connection, &MapConnection::targetMapNameChanged, [this, listItem, pixmapItem](QString, QString) { + // The old offset may not make sense, so we reset it + pixmapItem->connection->setOffset(0); listItem->updateUI(); updateConnectionPixmap(pixmapItem); }); - connect(connection, &MapConnection::hostMapNameChanged, [this, pixmapItem](QString before, QString) { - // A connection was removed from the current map by reassignment. We're deleting the UI elements, - // but not the associated connection (it still exists, but now it belongs to a different map). - // At the moment this is only possible when updating the mirror for a map connected to itself, - // users have no other way (or need) to relocate a map connection like this. - if (before == this->map->name) - removeConnectionPixmap(pixmapItem); - }); - // User manually deleting connection via the remove button connect(listItem, &ConnectionsListItem::removed, [this](MapConnection* connection) { removeConnection(connection); }); - // Sync removing the UI elements. They may be removed when deleting connections or when displaying a new map. - connect(connection, &MapConnection::destroyed, [this, pixmapItem] { removeConnectionPixmap(pixmapItem); }); + // When the pixmap is deleted, remove its associated list item connect(pixmapItem, &ConnectionPixmapItem::destroyed, listItem, &ConnectionsListItem::deleteLater); connection_items.append(pixmapItem); } -void Editor::addConnection(MapConnection * connection, bool addMirror) { +void Editor::addConnection(MapConnection * connection) { if (!connection) return; - if (addMirror) addConnection(connection->createMirror(), false); + this->map->addConnection(connection); + if (porymapConfig.mirrorConnectingMaps) + connection->createMirror(); - Map *map = project->getMap(connection->hostMapName()); - if (map) map->addConnection(connection); // TODO: Edit history } -void Editor::removeConnection(MapConnection* connection, bool removeMirror) { +void Editor::removeConnection(MapConnection* connection) { if (!connection) return; - if (removeMirror) removeConnection(connection->findMirror(), false); + if (porymapConfig.mirrorConnectingMaps) { + auto mirror = connection->findMirror(); + if (mirror && mirror->parentMap()) + mirror->parentMap()->removeConnection(mirror); + delete mirror; + } - Map* map = project->getMap(connection->hostMapName()); - if (map) map->removeConnection(connection); + if (connection->parentMap()) + connection->parentMap()->removeConnection(connection); delete connection; + // TODO: Edit history } @@ -841,20 +839,30 @@ void Editor::removeSelectedConnection() { removeConnection(selected_connection_item->connection); } -void Editor::removeConnectionPixmap(ConnectionPixmapItem* pixmapItem) { - if (!pixmapItem) +void Editor::removeConnectionPixmap(MapConnection* connection) { + if (!connection) return; - int index = connection_items.indexOf(pixmapItem); - if (index >= 0) { - connection_items.removeAt(index); - if (pixmapItem == selected_connection_item) { - // This was the selected connection, select the next one up in the list. - selected_connection_item = nullptr; - if (index != 0) index--; - if (connection_items.length() > index) - setSelectedConnection(connection_items.at(index)); - } + if (MapConnection::isDiving(connection->direction())) { + removeDivingMapPixmap(connection); + return; + } + + int i; + for (i = 0; i < connection_items.length(); i++) { + if (connection_items.at(i)->connection == connection) + break; + } + if (i == connection_items.length()) + return; // Connection is not displayed, nothing to do. + + auto pixmapItem = connection_items.takeAt(i); + if (pixmapItem == selected_connection_item) { + // This was the selected connection, select the next one up in the list. + selected_connection_item = nullptr; + if (i != 0) i--; + if (connection_items.length() > i) + setSelectedConnectionItem(connection_items.at(i)); } if (pixmapItem->scene()) @@ -863,63 +871,82 @@ void Editor::removeConnectionPixmap(ConnectionPixmapItem* pixmapItem) { delete pixmapItem; } -// TODO: Self-connecting a Dive/Emerge map connection will not actually replace any existing Dive/Emerge connection, if there is one. -void Editor::displayDiveEmergeConnection(MapConnection* connection) { +void Editor::displayDivingConnection(MapConnection* connection) { if (!connection) return; + const QString direction = connection->direction(); + if (!MapConnection::isDiving(direction)) + return; + // Note: We only support editing 1 Dive and Emerge connection per map. // In a vanilla game only the first Dive/Emerge connection is considered, so allowing // users to have multiple is likely to lead to confusion. In case users have changed // this we won't delete extra diving connections, but we'll only display the first one. - if (connection->direction() == "dive") { - if (dive_map_overlay) return; - } else if (connection->direction() == "emerge") { - if (emerge_map_overlay) return; - } else { - // Invalid direction + if (diving_map_items.value(direction)) return; - } - // Create image of Dive/Emerge map (unless we'd be rendering the current map on top of itself) - QPixmap pixmap = (connection->targetMapName() == this->map->name) ? QPixmap() : connection->getPixmap(); - QGraphicsPixmapItem *item = new QGraphicsPixmapItem(pixmap); + // Create map image + auto item = new DivingMapPixmapItem(connection); scene->addItem(item); + diving_map_items.insert(direction, item); + maskNonVisibleConnectionTiles(); - if (connection->direction() == "dive") { - dive_map_overlay = item; - const QSignalBlocker blocker(ui->comboBox_DiveMap); - ui->comboBox_DiveMap->setCurrentText(connection->targetMapName()); - connect(connection, &MapConnection::destroyed, this, &Editor::clearDiveMap); - connect(connection, &MapConnection::hostMapNameChanged, this, &Editor::clearDiveMap); - } else { - emerge_map_overlay = item; - const QSignalBlocker blocker(ui->comboBox_EmergeMap); - ui->comboBox_EmergeMap->setCurrentText(connection->targetMapName()); - connect(connection, &MapConnection::destroyed, this, &Editor::clearEmergeMap); - connect(connection, &MapConnection::hostMapNameChanged, this, &Editor::clearEmergeMap); - } + // Display map name in combo box + auto comboBox = (direction == "dive") ? ui->comboBox_DiveMap : ui->comboBox_EmergeMap; + const QSignalBlocker blocker(comboBox); + comboBox->setCurrentText(connection->targetMapName()); +} - // Update pixmap if the connected map is swapped - connect(connection, &MapConnection::targetMapNameChanged, [this, item, connection] { - item->setPixmap((connection->targetMapName() == this->map->name) ? QPixmap() : connection->getPixmap()); - }); +void Editor::removeDivingMapPixmap(MapConnection *connection) { + if (!connection) + return; + + const QString direction = connection->direction(); + if (!diving_map_items.contains(direction)) + return; + + // If the diving map being displayed is different than the one being removed we don't need to do anything. + if (diving_map_items.value(direction)->connection() != connection) + return; + + // Delete map image + auto pixmapItem = diving_map_items.take(direction); + if (pixmapItem->scene()) + pixmapItem->scene()->removeItem(pixmapItem); + delete pixmapItem; + + // Clear map name from combo box + auto comboBox = (direction == "dive") ? ui->comboBox_DiveMap : ui->comboBox_EmergeMap; + const QSignalBlocker blocker(comboBox); + comboBox->setCurrentText(""); + + // Reveal any previously-hidden connection (because we only ever display one diving map of each type). + // Note: When this occurs as a result of the user clicking the 'X' clear button it seems the QComboBox + // doesn't expect the line edit to be immediately repopulated, and the 'X' doesn't reappear. + // As a workaround we wait before displaying the new text. The wait time is essentially arbitrary. + for (auto i : map->getConnections()) { + if (i->direction() == direction) { + QTimer::singleShot(10, Qt::CoarseTimer, [this, i]() { displayDivingConnection(i); }); + break; + } + } } void Editor::updateDiveMap(QString mapName) { - setDiveEmergeMapName(mapName, "dive"); + setDivingMapName(mapName, "dive"); } void Editor::updateEmergeMap(QString mapName) { - setDiveEmergeMapName(mapName, "emerge"); + setDivingMapName(mapName, "emerge"); } -void Editor::setDiveEmergeMapName(QString mapName, QString direction) { +void Editor::setDivingMapName(QString mapName, QString direction) { // Only the first Dive/Emerge map (if present) is considered, as in-game. MapConnection* connection = nullptr; - for (MapConnection* conn : map->connections) { - if (conn->direction() == direction) { - connection = conn; + for (auto i : map->getConnections()) { + if (i->direction() == direction) { + connection = i; break; } } @@ -928,31 +955,32 @@ void Editor::setDiveEmergeMapName(QString mapName, QString direction) { // Update existing connection if (mapName.isEmpty()) { removeConnection(connection); - // TODO: Queue up another Dive/Emerge map if there is one } else { connection->setTargetMapName(mapName); } } else if (!mapName.isEmpty()) { // Create new connection - addConnection(new MapConnection(direction, map->name, mapName)); + addConnection(new MapConnection(mapName, direction)); } - updateDiveEmergeVisibility(); + updateDivingMapsVisibility(); + maskNonVisibleConnectionTiles(); } -void Editor::updateDiveEmergeVisibility() { - if (dive_map_overlay && emerge_map_overlay) { +void Editor::updateDivingMapsVisibility() { + auto dive = diving_map_items.value("dive"); + auto emerge = diving_map_items.value("emerge"); + + if (dive && emerge) { // Both connections in use, use separate sliders ui->stackedWidget_DiveMapOpacity->setCurrentIndex(0); - dive_map_overlay->setOpacity(!porymapConfig.showDiveEmergeMaps ? 0 : static_cast(porymapConfig.diveMapOpacity) / 100); - emerge_map_overlay->setOpacity(!porymapConfig.showDiveEmergeMaps ? 0 : static_cast(porymapConfig.emergeMapOpacity) / 100); + dive->setOpacity(!porymapConfig.showDiveEmergeMaps ? 0 : static_cast(porymapConfig.diveMapOpacity) / 100); + emerge->setOpacity(!porymapConfig.showDiveEmergeMaps ? 0 : static_cast(porymapConfig.emergeMapOpacity) / 100); } else { // One connection in use (or none), use single slider ui->stackedWidget_DiveMapOpacity->setCurrentIndex(1); qreal opacity = !porymapConfig.showDiveEmergeMaps ? 0 : static_cast(porymapConfig.diveEmergeMapOpacity) / 100; - if (dive_map_overlay) - dive_map_overlay->setOpacity(opacity); - else if (emerge_map_overlay) - emerge_map_overlay->setOpacity(opacity); + if (dive) dive->setOpacity(opacity); + else if (emerge) emerge->setOpacity(opacity); } } @@ -1011,7 +1039,7 @@ void Editor::updateConnectionPixmapPos(ConnectionPixmapItem* pixmapItem) { maskNonVisibleConnectionTiles(); } -void Editor::setSelectedConnection(ConnectionPixmapItem* pixmapItem) { +void Editor::setSelectedConnectionItem(ConnectionPixmapItem* pixmapItem) { if (!pixmapItem || pixmapItem == selected_connection_item) return; @@ -1020,23 +1048,21 @@ void Editor::setSelectedConnection(ConnectionPixmapItem* pixmapItem) { selected_connection_item->setSelected(true); } -// TODO: Inaccurate if there are multiple connections from the same map -void Editor::setSelectedConnectionFromMap(QString mapName) { - // Search for the first connection that connects to the given map. - for (ConnectionPixmapItem* item : connection_items) { - if (item->connection->targetMapName() == mapName) { - setSelectedConnection(item); +void Editor::setSelectedConnection(MapConnection *connection) { + if (!connection) + return; + + for (auto item : connection_items) { + if (item->connection == connection) { + setSelectedConnectionItem(item); break; } } } -void Editor::selectLastConnection() { - setSelectedConnection(connection_items.last()); -} - void Editor::onMapConnectionDoubleClicked(MapConnection* connection) { - emit openConnectedMap(connection->targetMapName(), connection->hostMapName()); + if (connection) + emit openConnectedMap(connection); } void Editor::onBorderMetatilesChanged() { @@ -1222,7 +1248,7 @@ bool Editor::setMap(QString map_name) { // multiple times if set again in the future if (map) { map->disconnect(this); - for (auto connection : map->connections) + for (auto connection : map->getConnections()) connection->disconnect(); } @@ -1244,6 +1270,7 @@ bool Editor::setMap(QString map_name) { connect(map, &Map::mapDimensionsChanged, map_ruler, &MapRuler::setMapDimensions); connect(map, &Map::openScriptRequested, this, &Editor::openScript); connect(map, &Map::connectionAdded, this, &Editor::displayConnection); + connect(map, &Map::connectionRemoved, this, &Editor::removeConnectionPixmap); updateSelectedEvents(); } @@ -1721,56 +1748,38 @@ DraggablePixmapItem *Editor::addMapEvent(Event *event) { } void Editor::clearMapConnections() { - for (ConnectionPixmapItem* item : connection_items) { - if (item->scene()) { + for (auto item : connection_items) { + if (item->scene()) item->scene()->removeItem(item); - } delete item; } connection_items.clear(); - clearDiveMap(); - clearEmergeMap(); - - selected_connection_item = nullptr; -} - -void Editor::clearDiveMap() { - const QSignalBlocker blocker(ui->comboBox_DiveMap); + const QSignalBlocker blocker1(ui->comboBox_DiveMap); + const QSignalBlocker blocker2(ui->comboBox_EmergeMap); ui->comboBox_DiveMap->setCurrentText(""); - - if (dive_map_overlay) { - if (dive_map_overlay->scene()){ - dive_map_overlay->scene()->removeItem(dive_map_overlay); - } - delete dive_map_overlay; - dive_map_overlay = nullptr; - } -} - -void Editor::clearEmergeMap() { - const QSignalBlocker blocker(ui->comboBox_EmergeMap); ui->comboBox_EmergeMap->setCurrentText(""); - if (emerge_map_overlay) { - if (emerge_map_overlay->scene()){ - emerge_map_overlay->scene()->removeItem(emerge_map_overlay); - } - delete emerge_map_overlay; - emerge_map_overlay = nullptr; + for (auto item : diving_map_items.values()) { + if (item->scene()) + item->scene()->removeItem(item); + delete item; } + diving_map_items.clear(); + + selected_connection_item = nullptr; } void Editor::displayMapConnections() { clearMapConnections(); - for (MapConnection *connection : map->connections) + for (MapConnection *connection : map->getConnections()) displayConnection(connection); - if (!connection_items.empty()) - setSelectedConnection(connection_items.first()); + if (!connection_items.isEmpty()) + setSelectedConnectionItem(connection_items.first()); - updateDiveEmergeVisibility(); + updateDivingMapsVisibility(); } void Editor::clearConnectionMask() { @@ -1801,6 +1810,7 @@ void Editor::maskNonVisibleConnectionTiles() { QBrush brush(ui->graphicsView_Map->palette().color(QPalette::Active, QPalette::Base)); connection_mask = scene->addPath(mask, pen, brush); + connection_mask->setZValue(3); // Above diving maps } void Editor::clearMapBorder() { diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 81e19609a..48dc65642 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -363,9 +363,7 @@ void MainWindow::initEditor() { } void MainWindow::initMiscHeapObjects() { - mapIcon = new QIcon(QStringLiteral(":/icons/map.ico")); - mapEditedIcon = new QIcon(QStringLiteral(":/icons/map_edited.ico")); - mapOpenedIcon = new QIcon(QStringLiteral(":/icons/map_opened.ico")); + mapIcon = QIcon(QStringLiteral(":/icons/map.ico")); mapListModel = new QStandardItemModel; mapGroupItemsList = new QList; @@ -496,7 +494,7 @@ void MainWindow::loadUserSettings() { ui->horizontalSlider_CollisionZoom->setValue(porymapConfig.collisionZoom); setTheme(porymapConfig.theme); - setDiveEmergeMapVisible(porymapConfig.showDiveEmergeMaps); + setDivingMapsVisible(porymapConfig.showDiveEmergeMaps); } void MainWindow::restoreWindowState() { @@ -755,6 +753,9 @@ void MainWindow::on_action_Close_Project_triggered() { // setMap, but with a visible error message in case of failure. // Use when the user is specifically requesting a map to open. bool MainWindow::userSetMap(QString map_name, bool scrollTreeView) { + if (editor->map && editor->map->name == map_name) + return true; // Already set + if (map_name == DYNAMIC_MAP_NAME) { QMessageBox msgBox(this); QString errorMsg = QString("The map '%1' can't be opened, it's a placeholder to indicate the specified map will be set programmatically.").arg(map_name); @@ -807,7 +808,8 @@ bool MainWindow::setMap(QString map_name, bool scrollTreeView) { connect(editor->map, &Map::mapNeedsRedrawing, this, &MainWindow::onMapNeedsRedrawing); // Swap the "currently-open" icon from the old map to the new map - updateMapListIcon(userConfig.recentMap); + if (!userConfig.recentMap.isEmpty() && userConfig.recentMap != map_name) + updateMapListIcon(userConfig.recentMap); userConfig.recentMap = map_name; updateMapListIcon(userConfig.recentMap); @@ -1230,7 +1232,7 @@ void MainWindow::sortMapList() { QStandardItem* MainWindow::createMapItem(QString mapName, int groupNum, int inGroupNum) { QStandardItem *map = new QStandardItem; map->setText(QString("[%1.%2] ").arg(groupNum).arg(inGroupNum, 2, 10, QLatin1Char('0')) + mapName); - map->setIcon(*mapIcon); + map->setIcon(mapIcon); map->setEditable(false); map->setData(mapName, Qt::UserRole); map->setData("map_name", MapListUserRoles::TypeRole); @@ -1319,7 +1321,7 @@ void MainWindow::onNewMapCreated() { setMap(newMapName, true); // Refresh any combo box that displays map names and persists between maps - // (others combo boxes like for warp destinations are repopulated when the map changes). + // (other combo boxes like for warp destinations are repopulated when the map changes). int index = this->editor->project->mapNames.indexOf(newMapName); if (index >= 0) { const QSignalBlocker blocker1(ui->comboBox_DiveMap); @@ -1544,12 +1546,15 @@ void MainWindow::updateMapListIcon(const QString &mapName) { if (!item) return; + static const QIcon mapEditedIcon = QIcon(QStringLiteral(":/icons/map_edited.ico")); + static const QIcon mapOpenedIcon = QIcon(QStringLiteral(":/icons/map_opened.ico")); + if (editor->map && editor->map->name == mapName) { - item->setIcon(*mapOpenedIcon); + item->setIcon(mapOpenedIcon); } else if (editor->project->mapCache.value(mapName)->hasUnsavedChanges()) { - item->setIcon(*mapEditedIcon); + item->setIcon(mapEditedIcon); } else { - item->setIcon(*mapIcon); + item->setIcon(mapIcon); } } @@ -2273,14 +2278,14 @@ void MainWindow::eventTabChanged(int index) { } void MainWindow::on_actionDive_Emerge_Map_triggered() { - setDiveEmergeMapVisible(ui->actionDive_Emerge_Map->isChecked()); + setDivingMapsVisible(ui->actionDive_Emerge_Map->isChecked()); } void MainWindow::on_groupBox_DiveMapOpacity_toggled(bool on) { - setDiveEmergeMapVisible(on); + setDivingMapsVisible(on); } -void MainWindow::setDiveEmergeMapVisible(bool visible) { +void MainWindow::setDivingMapsVisible(bool visible) { // Qt doesn't change the style of disabled sliders, so we do it ourselves QString stylesheet = visible ? "" : "QSlider::groove:horizontal {border: 1px solid #999999; border-radius: 3px; height: 2px; background: #B1B1B1;}" "QSlider::handle:horizontal {border: 1px solid #444444; border-radius: 3px; width: 10px; height: 9px; margin: -5px -1px; background: #5C5C5C; }"; @@ -2295,7 +2300,7 @@ void MainWindow::setDiveEmergeMapVisible(bool visible) { ui->actionDive_Emerge_Map->setChecked(visible); porymapConfig.showDiveEmergeMaps = visible; - this->editor->updateDiveEmergeVisibility(); + this->editor->updateDivingMapsVisibility(); } // Normally a map only has either a Dive map connection or an Emerge map connection, @@ -2304,17 +2309,17 @@ void MainWindow::setDiveEmergeMapVisible(bool visible) { // modify them independently. void MainWindow::on_slider_DiveEmergeMapOpacity_valueChanged(int value) { porymapConfig.diveEmergeMapOpacity = value; - this->editor->updateDiveEmergeVisibility(); + this->editor->updateDivingMapsVisibility(); } void MainWindow::on_slider_DiveMapOpacity_valueChanged(int value) { porymapConfig.diveMapOpacity = value; - this->editor->updateDiveEmergeVisibility(); + this->editor->updateDivingMapsVisibility(); } void MainWindow::on_slider_EmergeMapOpacity_valueChanged(int value) { porymapConfig.emergeMapOpacity = value; - this->editor->updateDiveEmergeVisibility(); + this->editor->updateDivingMapsVisibility(); } void MainWindow::on_horizontalSlider_CollisionTransparency_valueChanged(int value) { @@ -2529,9 +2534,9 @@ void MainWindow::clickToolButtonFromEditMode(QString editMode) { } } -void MainWindow::onOpenConnectedMap(QString mapName, QString fromMapName) { - if (mapName != fromMapName && userSetMap(mapName, true)) - editor->setSelectedConnectionFromMap(fromMapName); +void MainWindow::onOpenConnectedMap(MapConnection *connection) { + if (userSetMap(connection->targetMapName(), true)) + editor->setSelectedConnection(connection->findMirror()); } void MainWindow::onMapNeedsRedrawing() { @@ -2648,12 +2653,14 @@ void MainWindow::showExportMapImageWindow(ImageExporterMode mode) { openSubWindow(this->mapImageExporter); } -void MainWindow::on_pushButton_AddConnection_clicked() -{ +void MainWindow::on_pushButton_AddConnection_clicked() { + if (!this->editor || !this->editor->map) + return; + auto dialog = new NewMapConnectionDialog(this, this->editor->map, this->editor->project->mapNames); - if(dialog->exec() == QDialog::Accepted) { + if (dialog->exec() == QDialog::Accepted) { this->editor->addConnection(dialog->result); - this->editor->selectLastConnection(); + this->editor->setSelectedConnection(dialog->result); } } diff --git a/src/project.cpp b/src/project.cpp index d60c8a096..10ace3961 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -196,10 +196,6 @@ Map* Project::loadMap(QString map_name) { return map; } -void Project::setNewMapConnections(Map *map) { - map->connections.clear(); -} - const QSet defaultTopLevelMapFields = { "id", "name", @@ -368,7 +364,7 @@ bool Project::loadMapData(Map* map) { } } - map->connections.clear(); + map->deleteConnections(); QJsonArray connectionsArr = mapObj["connections"].toArray(); if (!connectionsArr.isEmpty()) { for (int i = 0; i < connectionsArr.size(); i++) { @@ -378,8 +374,7 @@ bool Project::loadMapData(Map* map) { const QString mapConstant = ParseUtil::jsonToQString(connectionObj["map"]); if (mapConstantsToMapNames.contains(mapConstant)) { // Successully read map connection - MapConnection *connection = new MapConnection(direction, map->name, mapConstantsToMapNames.value(mapConstant), offset); - map->connections.append(connection); + map->loadConnection(new MapConnection(mapConstantsToMapNames.value(mapConstant), direction, offset)); } else { logError(QString("Failed to find connected map for map constant '%1'").arg(mapConstant)); } @@ -1280,9 +1275,10 @@ void Project::saveMap(Map *map) { mapObj["battle_scene"] = map->battle_scene; // Connections - if (map->connections.length() > 0) { + auto connections = map->getConnections(); + if (connections.length() > 0) { OrderedJson::array connectionsArr; - for (MapConnection* connection : map->connections) { + for (auto connection : connections) { if (mapNamesToMapConstants.contains(connection->targetMapName())) { OrderedJson::object connectionObj; connectionObj["map"] = this->mapNamesToMapConstants.value(connection->targetMapName()); @@ -1848,7 +1844,6 @@ Map* Project::addNewMapToGroup(QString mapName, int groupNum, Map *newMap, bool loadLayoutTilesets(newMap->layout); setNewMapEvents(newMap); - setNewMapConnections(newMap); return newMap; } diff --git a/src/ui/connectionslistitem.cpp b/src/ui/connectionslistitem.cpp index fd2532bff..2501d2d4f 100644 --- a/src/ui/connectionslistitem.cpp +++ b/src/ui/connectionslistitem.cpp @@ -40,13 +40,13 @@ void ConnectionsListItem::updateUI() { ui->spinBox_Offset->setValue(this->connection->offset()); } -// TODO: Frame shifts slightly when style changes void ConnectionsListItem::setSelected(bool selected) { if (selected == this->isSelected) return; this->isSelected = selected; - this->setStyleSheet(selected ? ".ConnectionsListItem { border: 1px solid rgb(255, 0, 255); }" : ""); + this->setStyleSheet(selected ? ".ConnectionsListItem { border: 1px solid rgb(255, 0, 255); }" + : ".ConnectionsListItem { border-width: 1px; }"); if (selected) emit this->selected(); } diff --git a/src/ui/mapimageexporter.cpp b/src/ui/mapimageexporter.cpp index f26a05a30..03cbc2b80 100644 --- a/src/ui/mapimageexporter.cpp +++ b/src/ui/mapimageexporter.cpp @@ -238,7 +238,7 @@ QPixmap MapImageExporter::getStitchedImage(QProgressDialog *progress, bool inclu visited.insert(cur.map->name); stitchedMaps.append(cur); - for (MapConnection *connection : cur.map->connections) { + for (MapConnection *connection : cur.map->getConnections()) { const QString direction = connection->direction(); int x = cur.x; int y = cur.y; diff --git a/src/ui/newmapconnectiondialog.cpp b/src/ui/newmapconnectiondialog.cpp index 3a7aa4819..aa7c05cf1 100644 --- a/src/ui/newmapconnectiondialog.cpp +++ b/src/ui/newmapconnectiondialog.cpp @@ -8,7 +8,6 @@ NewMapConnectionDialog::NewMapConnectionDialog(QWidget *parent, Map* map, const ui->setupUi(this); setAttribute(Qt::WA_DeleteOnClose); - this->map = map; this->result = nullptr; ui->comboBox_Direction->setEditable(false); @@ -20,7 +19,7 @@ NewMapConnectionDialog::NewMapConnectionDialog(QWidget *parent, Map* map, const // Choose default direction QMap directionCounts; - for (auto connection : map->connections) { + for (auto connection : map->getConnections()) { directionCounts[connection->direction()]++; } QString defaultDirection; @@ -52,11 +51,6 @@ NewMapConnectionDialog::~NewMapConnectionDialog() } void NewMapConnectionDialog::accept() { - QString direction = ui->comboBox_Direction->currentText(); - QString hostMapName = this->map ? this->map->name : QString(); - QString targetMapName = ui->comboBox_Map->currentText(); - - this->result = new MapConnection(direction, this->map->name, targetMapName); - + this->result = new MapConnection(ui->comboBox_Map->currentText(), ui->comboBox_Direction->currentText()); QDialog::accept(); } From 63b77a1fdc66fb58ab22db4eb325261e5f893985 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Tue, 13 Aug 2024 21:43:23 -0400 Subject: [PATCH 24/30] Ignore scrolling for connection map combo boxes --- include/ui/noscrollcombobox.h | 3 +++ src/mainwindow.cpp | 2 ++ src/ui/connectionslistitem.cpp | 1 + src/ui/noscrollcombobox.cpp | 10 ++++++++-- 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/include/ui/noscrollcombobox.h b/include/ui/noscrollcombobox.h index 7b6f75223..32966b3a5 100644 --- a/include/ui/noscrollcombobox.h +++ b/include/ui/noscrollcombobox.h @@ -16,9 +16,12 @@ class NoScrollComboBox : public QComboBox void setClearButtonEnabled(bool enabled); void setEditable(bool editable); void setLineEdit(QLineEdit *edit); + void setFocusedScrollingEnabled(bool enabled); private: void setItem(int index, const QString &text); + + bool focusedScrollingEnabled = true; }; #endif // NOSCROLLCOMBOBOX_H diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 48dc65642..c6b8c3c0e 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1059,9 +1059,11 @@ bool MainWindow::setProjectUI() { ui->comboBox_DiveMap->clear(); ui->comboBox_DiveMap->addItems(project->mapNames); ui->comboBox_DiveMap->setClearButtonEnabled(true); + ui->comboBox_DiveMap->setFocusedScrollingEnabled(false); ui->comboBox_EmergeMap->clear(); ui->comboBox_EmergeMap->addItems(project->mapNames); ui->comboBox_EmergeMap->setClearButtonEnabled(true); + ui->comboBox_EmergeMap->setFocusedScrollingEnabled(false); sortMapList(); diff --git a/src/ui/connectionslistitem.cpp b/src/ui/connectionslistitem.cpp index 2501d2d4f..049bb17d0 100644 --- a/src/ui/connectionslistitem.cpp +++ b/src/ui/connectionslistitem.cpp @@ -17,6 +17,7 @@ ConnectionsListItem::ConnectionsListItem(QWidget *parent, MapConnection * connec ui->comboBox_Map->setMinimumContentsLength(6); ui->comboBox_Map->addItems(mapNames); + ui->comboBox_Map->setFocusedScrollingEnabled(false); // Scrolling could cause rapid changes to many different maps ui->spinBox_Offset->setMinimum(INT_MIN); ui->spinBox_Offset->setMaximum(INT_MAX); diff --git a/src/ui/noscrollcombobox.cpp b/src/ui/noscrollcombobox.cpp index 5288ad970..3db2a9567 100644 --- a/src/ui/noscrollcombobox.cpp +++ b/src/ui/noscrollcombobox.cpp @@ -37,11 +37,17 @@ void NoScrollComboBox::setLineEdit(QLineEdit *edit) { void NoScrollComboBox::wheelEvent(QWheelEvent *event) { - // Only allow scrolling to modify contents when it explicitly has focus. - if (hasFocus()) + // By default NoScrollComboBoxes will allow scrolling to modify its contents only when it explicitly has focus. + // If focusedScrollingEnabled is false it won't allow scrolling even with focus. + if (this->focusedScrollingEnabled && hasFocus()) QComboBox::wheelEvent(event); } +void NoScrollComboBox::setFocusedScrollingEnabled(bool enabled) +{ + this->focusedScrollingEnabled = enabled; +} + void NoScrollComboBox::setItem(int index, const QString &text) { if (index >= 0) { From 0b800c12011c0430fb01f1073a4540244bb8ff38 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Tue, 13 Aug 2024 22:18:40 -0400 Subject: [PATCH 25/30] Skip unnecessary dive map rendering, fix rendering small connections --- include/editor.h | 1 + include/ui/divingmappixmapitem.h | 1 - src/core/map.cpp | 30 ++++++++++++++++++------------ src/editor.cpp | 23 ++++++++++++++++------- src/mainwindow.cpp | 6 ++++++ 5 files changed, 41 insertions(+), 20 deletions(-) diff --git a/include/editor.h b/include/editor.h index 86d5bfdbb..464323471 100644 --- a/include/editor.h +++ b/include/editor.h @@ -78,6 +78,7 @@ class Editor : public QObject void setMapEditingButtonsEnabled(bool enabled); void setConnectionsVisibility(bool visible); void updateDivingMapsVisibility(); + void displayDivingConnections(); void addConnection(MapConnection* connection); void removeConnection(MapConnection* connection); void removeSelectedConnection(); diff --git a/include/ui/divingmappixmapitem.h b/include/ui/divingmappixmapitem.h index 96b47e479..7596aeafa 100644 --- a/include/ui/divingmappixmapitem.h +++ b/include/ui/divingmappixmapitem.h @@ -13,7 +13,6 @@ class DivingMapPixmapItem : public QObject, public QGraphicsPixmapItem { : QGraphicsPixmapItem(getBasePixmap(connection)) { m_connection = connection; - setZValue(2); // Update pixmap if the connected map is swapped. connect(m_connection, &MapConnection::targetMapNameChanged, this, &DivingMapPixmapItem::updatePixmap); diff --git a/src/core/map.cpp b/src/core/map.cpp index b0abe1258..ed011ec57 100644 --- a/src/core/map.cpp +++ b/src/core/map.cpp @@ -216,23 +216,29 @@ QPixmap Map::renderBorder(bool ignoreCache) { } QPixmap Map::renderConnection(const QString &direction, MapLayout * fromLayout) { - if (direction == "dive" || direction == "emerge") - return render(true); - - if (!MapConnection::isCardinal(direction)) - return QPixmap(); - + // Cardinal connections are rendered within the bounds of the border draw distance, + // and we need to render the nearest segment of the map. + // Dive/Emerge maps are rendered normally, but within the bounds of their parent map. int x = 0, y = 0, w = getWidth(), h = getHeight(); if (direction == "up") { - y = getHeight() - BORDER_DISTANCE; - h = BORDER_DISTANCE; + h = qMin(h, BORDER_DISTANCE); + y = getHeight() - h; } else if (direction == "down") { - h = BORDER_DISTANCE; + h = qMin(h, BORDER_DISTANCE); } else if (direction == "left") { - x = getWidth() - BORDER_DISTANCE; - w = BORDER_DISTANCE; + w = qMin(w, BORDER_DISTANCE); + x = getWidth() - w; } else if (direction == "right") { - w = BORDER_DISTANCE; + w = qMin(w, BORDER_DISTANCE); + } else if (MapConnection::isDiving(direction)) { + if (fromLayout) { + w = qMin(w, fromLayout->getWidth()); + h = qMin(h, fromLayout->getHeight()); + fromLayout = nullptr; // This would be used for palettes later, but we want our own palettes, not the parent's. + } + } else { + // Unknown direction + return QPixmap(); } render(true, fromLayout, QRect(x, y, w, h)); diff --git a/src/editor.cpp b/src/editor.cpp index 981fbd57f..e20936652 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -737,10 +737,6 @@ void Editor::displayConnection(MapConnection* connection) { if (!connection) return; - // It's possible for a map connection to be displayed repeatedly if it's being - // updated by mirroring and the target map is changing to/from the current map. - connection->disconnect(); - if (MapConnection::isDiving(connection->direction())) { displayDivingConnection(connection); return; @@ -758,6 +754,10 @@ void Editor::displayConnection(MapConnection* connection) { ConnectionsListItem *listItem = new ConnectionsListItem(ui->scrollAreaContents_ConnectionsList, pixmapItem->connection, project->mapNames); ui->layout_ConnectionsList->insertWidget(ui->layout_ConnectionsList->count() - 1, listItem); // Insert above the vertical spacer + // It's possible for a map connection to be displayed repeatedly if it's being + // updated by mirroring and the target map is changing to/from the current map. + connection->disconnect(); + // Double clicking the list item or pixmap opens the connected map connect(listItem, &ConnectionsListItem::doubleClicked, this, &Editor::onMapConnectionDoubleClicked); connect(pixmapItem, &ConnectionPixmapItem::connectionItemDoubleClicked, this, &Editor::onMapConnectionDoubleClicked); @@ -871,6 +871,14 @@ void Editor::removeConnectionPixmap(MapConnection* connection) { delete pixmapItem; } +void Editor::displayDivingConnections() { + if (!this->map) + return; + + for (auto connection : this->map->getConnections()) + displayDivingConnection(connection); +} + void Editor::displayDivingConnection(MapConnection* connection) { if (!connection) return; @@ -879,6 +887,10 @@ void Editor::displayDivingConnection(MapConnection* connection) { if (!MapConnection::isDiving(direction)) return; + // Save some rendering time if it won't be displayed + if (!porymapConfig.showDiveEmergeMaps) + return; + // Note: We only support editing 1 Dive and Emerge connection per map. // In a vanilla game only the first Dive/Emerge connection is considered, so allowing // users to have multiple is likely to lead to confusion. In case users have changed @@ -890,7 +902,6 @@ void Editor::displayDivingConnection(MapConnection* connection) { auto item = new DivingMapPixmapItem(connection); scene->addItem(item); diving_map_items.insert(direction, item); - maskNonVisibleConnectionTiles(); // Display map name in combo box auto comboBox = (direction == "dive") ? ui->comboBox_DiveMap : ui->comboBox_EmergeMap; @@ -963,7 +974,6 @@ void Editor::setDivingMapName(QString mapName, QString direction) { addConnection(new MapConnection(mapName, direction)); } updateDivingMapsVisibility(); - maskNonVisibleConnectionTiles(); } void Editor::updateDivingMapsVisibility() { @@ -1810,7 +1820,6 @@ void Editor::maskNonVisibleConnectionTiles() { QBrush brush(ui->graphicsView_Map->palette().color(QPalette::Active, QPalette::Base)); connection_mask = scene->addPath(mask, pen, brush); - connection_mask->setZValue(3); // Above diving maps } void Editor::clearMapBorder() { diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index c6b8c3c0e..0f1b83dfd 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2302,6 +2302,12 @@ void MainWindow::setDivingMapsVisible(bool visible) { ui->actionDive_Emerge_Map->setChecked(visible); porymapConfig.showDiveEmergeMaps = visible; + + if (visible) { + // We skip rendering diving maps if this setting is not enabled, + // so when we enable it we need to make sure they've rendered. + this->editor->displayDivingConnections(); + } this->editor->updateDivingMapsVisibility(); } From cbd75dc20b072b67290e535b3d32b8d33b328c80 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Wed, 14 Aug 2024 22:22:54 -0400 Subject: [PATCH 26/30] Map connection edit history --- include/core/editcommands.h | 116 ++++++++++++++++ include/core/map.h | 11 +- include/core/mapconnection.h | 2 +- include/editor.h | 7 +- include/ui/connectionpixmapitem.h | 43 +++--- include/ui/connectionslistitem.h | 7 +- include/ui/divingmappixmapitem.h | 26 ++-- include/ui/newmapconnectiondialog.h | 5 +- porymap.pro | 1 + src/core/editcommands.cpp | 202 ++++++++++++++++++++++++++++ src/core/map.cpp | 106 ++++++++++----- src/core/mapconnection.cpp | 24 ++-- src/editor.cpp | 191 +++++++++++--------------- src/mainwindow.cpp | 10 +- src/ui/connectionpixmapitem.cpp | 82 ++++++++--- src/ui/connectionslistitem.cpp | 33 ++++- src/ui/divingmappixmapitem.cpp | 46 +++++++ src/ui/mapimageexporter.cpp | 11 +- src/ui/newmapconnectiondialog.cpp | 10 +- 19 files changed, 692 insertions(+), 241 deletions(-) create mode 100644 src/ui/divingmappixmapitem.cpp diff --git a/include/core/editcommands.h b/include/core/editcommands.h index ea66b7229..40f0cd62e 100644 --- a/include/core/editcommands.h +++ b/include/core/editcommands.h @@ -3,9 +3,11 @@ #define EDITCOMMANDS_H #include "blockdata.h" +#include "mapconnection.h" #include #include +#include class MapPixmapItem; class Map; @@ -31,6 +33,11 @@ enum CommandId { ID_EventDelete, ID_EventDuplicate, ID_EventPaste, + ID_MapConnectionMove, + ID_MapConnectionChangeDirection, + ID_MapConnectionChangeMap, + ID_MapConnectionAdd, + ID_MapConnectionRemove, }; #define IDMask_EventType_Object (1 << 8) @@ -379,4 +386,113 @@ class ScriptEditMap : public QUndoCommand { int newBorderHeight; }; + + +/// Implements a command to commit Map Connectien move actions. +/// Actions are merged into one until the mouse is released when editing by click-and-drag, +/// or when the offset spin box loses focus when editing with the list UI. +class MapConnectionMove : public QUndoCommand { +public: + MapConnectionMove(MapConnection *connection, int newOffset, unsigned actionId, + QUndoCommand *parent = nullptr); + + void undo() override; + void redo() override; + + bool mergeWith(const QUndoCommand *command) override; + int id() const override { return CommandId::ID_MapConnectionMove; } + +private: + MapConnection *connection; + int newOffset; + int oldOffset; + bool mirrored; + unsigned actionId; +}; + + + +/// Implements a command to commit changes to a Map Connectien's 'direction' field. +class MapConnectionChangeDirection : public QUndoCommand { +public: + MapConnectionChangeDirection(MapConnection *connection, QString newDirection, + QUndoCommand *parent = nullptr); + + void undo() override; + void redo() override; + + int id() const override { return CommandId::ID_MapConnectionChangeDirection; } + +private: + QPointer connection; + QString newDirection; + QString oldDirection; + int oldOffset; + int newOffset; + bool mirrored; +}; + + + +/// Implements a command to commit changes to a Map Connectien's 'map' field. +class MapConnectionChangeMap : public QUndoCommand { +public: + MapConnectionChangeMap(MapConnection *connection, QString newMapName, + QUndoCommand *parent = nullptr); + + void undo() override; + void redo() override; + + int id() const override { return CommandId::ID_MapConnectionChangeMap; } + +private: + QPointer connection; + QString newMapName; + QString oldMapName; + int oldOffset; + int newOffset; + bool mirrored; +}; + + + +/// Implements a command to commit adding a Map Connection to a map. +class MapConnectionAdd : public QUndoCommand { +public: + MapConnectionAdd(Map *map, MapConnection *connection, + QUndoCommand *parent = nullptr); + + void undo() override; + void redo() override; + + int id() const override { return CommandId::ID_MapConnectionAdd; } + +private: + Map *map = nullptr; + Map *mirrorMap = nullptr; + QPointer connection = nullptr; + QPointer mirror = nullptr; +}; + + + +/// Implements a command to commit removing a Map Connection from a map. +class MapConnectionRemove : public QUndoCommand { +public: + MapConnectionRemove(Map *map, MapConnection *connection, + QUndoCommand *parent = nullptr); + + void undo() override; + void redo() override; + + int id() const override { return CommandId::ID_MapConnectionRemove; } + +private: + Map *map = nullptr; + Map *mirrorMap = nullptr; + QPointer connection = nullptr; + QPointer mirror = nullptr; +}; + + #endif // EDITCOMMANDS_H diff --git a/include/core/map.h b/include/core/map.h index 9f039a6fb..270202362 100644 --- a/include/core/map.h +++ b/include/core/map.h @@ -99,10 +99,12 @@ class Map : public QObject void addEvent(Event *); void deleteConnections(); QList getConnections() const; - void removeConnection(MapConnection *); - void addConnection(MapConnection *); + bool takeConnection(MapConnection *); + bool removeConnection(MapConnection *); + bool addConnection(MapConnection *); void loadConnection(MapConnection *); - QPixmap renderConnection(const QString &, MapLayout *); + QRect getConnectionRect(const QString &direction, MapLayout *fromLayout = nullptr); + QPixmap renderConnection(const QString &direction, MapLayout *fromLayout = nullptr); QPixmap renderBorder(bool ignoreCache = false); void setDimensions(int newWidth, int newHeight, bool setNewBlockdata = true, bool enableScriptCallback = false); void setBorderDimensions(int newWidth, int newHeight, bool setNewBlockdata = true, bool enableScriptCallback = false); @@ -126,12 +128,15 @@ class Map : public QObject QUndoStack editHistory; void modify(); void clean(); + void pruneEditHistory(); private: void setNewDimensionsBlockdata(int newWidth, int newHeight); void setNewBorderDimensionsBlockdata(int newWidth, int newHeight); + // MapConnections in 'ownedConnections' but not 'connections' persist in the edit history. QList connections; + QSet ownedConnections; signals: void modified(); diff --git a/include/core/mapconnection.h b/include/core/mapconnection.h index 956574dc7..6ffa85b79 100644 --- a/include/core/mapconnection.h +++ b/include/core/mapconnection.h @@ -29,7 +29,6 @@ class MapConnection : public QObject int offset() const { return m_offset; } void setOffset(int offset, bool mirror = true); - bool isMirror(const MapConnection*); MapConnection* findMirror(); MapConnection* createMirror(); @@ -43,6 +42,7 @@ class MapConnection : public QObject static bool isVertical(const QString &direction); static bool isDiving(const QString &direction); static QString oppositeDirection(const QString &direction) { return oppositeDirections.value(direction, direction); } + static bool areMirrored(const MapConnection*, const MapConnection*); private: Map* m_parentMap; diff --git a/include/editor.h b/include/editor.h index 464323471..3b2c9ae64 100644 --- a/include/editor.h +++ b/include/editor.h @@ -79,6 +79,7 @@ class Editor : public QObject void setConnectionsVisibility(bool visible); void updateDivingMapsVisibility(); void displayDivingConnections(); + void renderDivingConnections(); void addConnection(MapConnection* connection); void removeConnection(MapConnection* connection); void removeSelectedConnection(); @@ -111,7 +112,6 @@ class Editor : public QObject QPointer scene = nullptr; QGraphicsPixmapItem *current_view = nullptr; QPointer map_item = nullptr; - QPointer selected_connection_item = nullptr; QList> connection_items; QMap> diving_map_items; QGraphicsPathItem *connection_mask = nullptr; @@ -134,6 +134,8 @@ class Editor : public QObject QPointer movement_permissions_selector_item = nullptr; QList *selected_events = nullptr; + QPointer selected_connection_item = nullptr; + QPointer connection_to_select = nullptr; QString map_edit_mode = "paint"; QString obj_edit_mode = "select"; @@ -183,10 +185,9 @@ public slots: void clearMapGrid(); void clearWildMonTables(); void updateBorderVisibility(); - QPoint calculateConnectionPosition(MapConnection *connection, const QPixmap &pixmap); + QPoint getConnectionOrigin(MapConnection *connection); void removeConnectionPixmap(MapConnection* connection); void updateConnectionPixmap(ConnectionPixmapItem* connectionItem); - void updateConnectionPixmapPos(ConnectionPixmapItem* connectionItem); void displayConnection(MapConnection* connection); void displayDivingConnection(MapConnection* connection); void setDivingMapName(QString mapName, QString direction); diff --git a/include/ui/connectionpixmapitem.h b/include/ui/connectionpixmapitem.h index 969fa6c1b..62eda6fe4 100644 --- a/include/ui/connectionpixmapitem.h +++ b/include/ui/connectionpixmapitem.h @@ -9,36 +9,37 @@ class ConnectionPixmapItem : public QObject, public QGraphicsPixmapItem { Q_OBJECT public: - ConnectionPixmapItem(QPixmap pixmap, MapConnection* connection, int x, int y) - : QGraphicsPixmapItem(pixmap) - { - this->basePixmap = pixmap; - this->connection = connection; - setFlag(ItemIsMovable); - setFlag(ItemSendsGeometryChanges); - this->initialX = x; - this->initialY = y; - this->initialOffset = connection->offset(); - this->setPos(x, y); - } - QPixmap basePixmap; - QPointer connection; - int initialX; - int initialY; - int initialOffset; + ConnectionPixmapItem(MapConnection* connection, int originX, int originY); + ConnectionPixmapItem(MapConnection* connection, QPoint origin); + + const QPointer connection; + + void setOrigin(int x, int y); + void setOrigin(QPoint pos); void setEditable(bool editable); bool getEditable(); + void setSelected(bool selected); - void render(); + + void updatePos(); + void render(bool ignoreCache = false); private: + QPixmap basePixmap; + qreal originX; + qreal originY; bool selected = false; + unsigned actionId = 0; + + static const int mWidth = 16; + static const int mHeight = 16; protected: - QVariant itemChange(GraphicsItemChange change, const QVariant &value); - void mousePressEvent(QGraphicsSceneMouseEvent*); - void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*); + QVariant itemChange(GraphicsItemChange change, const QVariant &value) override; + void mousePressEvent(QGraphicsSceneMouseEvent*) override; + void mouseReleaseEvent(QGraphicsSceneMouseEvent*) override; + void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*) override; signals: void connectionItemDoubleClicked(MapConnection*); diff --git a/include/ui/connectionslistitem.h b/include/ui/connectionslistitem.h index 9cac56895..87051c375 100644 --- a/include/ui/connectionslistitem.h +++ b/include/ui/connectionslistitem.h @@ -2,6 +2,7 @@ #define CONNECTIONSLISTITEM_H #include "mapconnection.h" +#include "map.h" #include #include @@ -30,11 +31,13 @@ class ConnectionsListItem : public QFrame private: Ui::ConnectionsListItem *ui; + Map *map; bool isSelected = false; + unsigned actionId = 0; protected: - void mousePressEvent(QMouseEvent *); - void mouseDoubleClickEvent(QMouseEvent *); + void mousePressEvent(QMouseEvent*) override; + void mouseDoubleClickEvent(QMouseEvent*) override; signals: void removed(MapConnection*); diff --git a/include/ui/divingmappixmapitem.h b/include/ui/divingmappixmapitem.h index 7596aeafa..7eceba070 100644 --- a/include/ui/divingmappixmapitem.h +++ b/include/ui/divingmappixmapitem.h @@ -5,30 +5,26 @@ #include #include +#include class DivingMapPixmapItem : public QObject, public QGraphicsPixmapItem { Q_OBJECT public: - DivingMapPixmapItem(MapConnection* connection) - : QGraphicsPixmapItem(getBasePixmap(connection)) - { - m_connection = connection; - - // Update pixmap if the connected map is swapped. - connect(m_connection, &MapConnection::targetMapNameChanged, this, &DivingMapPixmapItem::updatePixmap); - } + DivingMapPixmapItem(MapConnection *connection, QComboBox *combo); + ~DivingMapPixmapItem(); + MapConnection* connection() const { return m_connection; } + void updatePixmap(); private: QPointer m_connection; + QPointer m_combo; + + void setComboText(const QString &text); + static QPixmap getBasePixmap(MapConnection* connection); - static QPixmap getBasePixmap(MapConnection* connection) { - // If the map is connected to itself then rendering is pointless. - if (!connection || connection->targetMapName() == connection->parentMapName()) - return QPixmap(); - return connection->getPixmap(); - } - void updatePixmap() { setPixmap(getBasePixmap(m_connection)); } +private slots: + void onTargetMapChanged(); }; #endif // DIVINGMAPPIXMAPITEM_H diff --git a/include/ui/newmapconnectiondialog.h b/include/ui/newmapconnectiondialog.h index 3b37c4544..2e0ba28e9 100644 --- a/include/ui/newmapconnectiondialog.h +++ b/include/ui/newmapconnectiondialog.h @@ -17,10 +17,11 @@ class NewMapConnectionDialog : public QDialog explicit NewMapConnectionDialog(QWidget *parent, Map* map, const QStringList &mapNames); ~NewMapConnectionDialog(); - MapConnection *result; - virtual void accept() override; +signals: + void accepted(MapConnection *result); + private: Ui::NewMapConnectionDialog *ui; }; diff --git a/porymap.pro b/porymap.pro index e5cad6dda..744edaef1 100644 --- a/porymap.pro +++ b/porymap.pro @@ -50,6 +50,7 @@ SOURCES += src/core/block.cpp \ src/ui/connectionslistitem.cpp \ src/ui/customscriptseditor.cpp \ src/ui/customscriptslistitem.cpp \ + src/ui/divingmappixmapitem.cpp \ src/ui/draggablepixmapitem.cpp \ src/ui/bordermetatilespixmapitem.cpp \ src/ui/collisionpixmapitem.cpp \ diff --git a/src/core/editcommands.cpp b/src/core/editcommands.cpp index 394c51cbc..640cb43fc 100644 --- a/src/core/editcommands.cpp +++ b/src/core/editcommands.cpp @@ -569,3 +569,205 @@ void ScriptEditMap::undo() { QUndoCommand::undo(); } + +/****************************************************************************** + ************************************************************************ + ******************************************************************************/ + +MapConnectionMove::MapConnectionMove(MapConnection *connection, int newOffset, unsigned actionId, + QUndoCommand *parent) : QUndoCommand(parent) { + setText("Move Map Connection"); + + this->connection = connection; + this->oldOffset = connection->offset(); + this->newOffset = newOffset; + + this->mirrored = porymapConfig.mirrorConnectingMaps; + + this->actionId = actionId; +} + +void MapConnectionMove::redo() { + QUndoCommand::redo(); + if (this->connection) + this->connection->setOffset(this->newOffset, this->mirrored); +} + +void MapConnectionMove::undo() { + if (this->connection) + this->connection->setOffset(this->oldOffset, this->mirrored); + QUndoCommand::undo(); +} + +bool MapConnectionMove::mergeWith(const QUndoCommand *command) { + if (this->id() != command->id()) + return false; + + const MapConnectionMove *other = static_cast(command); + if (this->connection != other->connection) + return false; + if (this->actionId != other->actionId) + return false; + + this->newOffset = other->newOffset; + return true; +} + +/****************************************************************************** + ************************************************************************ + ******************************************************************************/ + +MapConnectionChangeDirection::MapConnectionChangeDirection(MapConnection *connection, QString newDirection, + QUndoCommand *parent) : QUndoCommand(parent) { + setText("Change Map Connection Direction"); + + this->connection = connection; + + this->oldDirection = connection->direction(); + this->newDirection = newDirection; + + this->oldOffset = connection->offset(); + + // If the direction changes between vertical/horizontal then the old offset may not make sense, so we reset it. + if (MapConnection::isHorizontal(this->oldDirection) != MapConnection::isHorizontal(this->newDirection) + || MapConnection::isVertical(this->oldDirection) != MapConnection::isVertical(this->newDirection)) { + this->newOffset = 0; + } else { + this->newOffset = oldOffset; + } + + this->mirrored = porymapConfig.mirrorConnectingMaps; +} + +void MapConnectionChangeDirection::redo() { + QUndoCommand::redo(); + if (this->connection) { + this->connection->setDirection(this->newDirection, this->mirrored); + this->connection->setOffset(this->newOffset, this->mirrored); + } +} + +void MapConnectionChangeDirection::undo() { + if (this->connection) { + this->connection->setDirection(this->oldDirection, this->mirrored); + this->connection->setOffset(this->oldOffset, this->mirrored); + } + QUndoCommand::undo(); +} + +/****************************************************************************** + ************************************************************************ + ******************************************************************************/ + +MapConnectionChangeMap::MapConnectionChangeMap(MapConnection *connection, QString newMapName, + QUndoCommand *parent) : QUndoCommand(parent) { + setText("Change Map Connection Map"); + + this->connection = connection; + + this->oldMapName = connection->targetMapName(); + this->newMapName = newMapName; + + this->oldOffset = connection->offset(); + this->newOffset = 0; // The old offset may not make sense, so we reset it + + this->mirrored = porymapConfig.mirrorConnectingMaps; +} + +void MapConnectionChangeMap::redo() { + QUndoCommand::redo(); + if (this->connection) { + this->connection->setTargetMapName(this->newMapName, this->mirrored); + this->connection->setOffset(this->newOffset, this->mirrored); + } +} + +void MapConnectionChangeMap::undo() { + if (this->connection) { + this->connection->setTargetMapName(this->oldMapName, this->mirrored); + this->connection->setOffset(this->oldOffset, this->mirrored); + } + QUndoCommand::undo(); +} + +/****************************************************************************** + ************************************************************************ + ******************************************************************************/ + +MapConnectionAdd::MapConnectionAdd(Map *map, MapConnection *connection, + QUndoCommand *parent) : QUndoCommand(parent) { + setText("Add Map Connection"); + + this->map = map; + this->connection = connection; + + // Set this now because it's needed to create a mirror below. + // It would otherwise be set by Map::addConnection. + this->connection->setParentMap(this->map, false); + + if (porymapConfig.mirrorConnectingMaps) { + this->mirror = this->connection->createMirror(); + this->mirrorMap = this->connection->targetMap(); + } +} + +void MapConnectionAdd::redo() { + QUndoCommand::redo(); + + this->map->addConnection(this->connection); + if (this->mirrorMap) + this->mirrorMap->addConnection(this->mirror); +} + +void MapConnectionAdd::undo() { + if (this->mirrorMap) { + // We can't guarantee that the mirror we created earlier is still our connection's + // mirror because there is no strict source->mirror pairing for map connections + // (a different identical map connection can take its place during any mirrored change). + if (!MapConnection::areMirrored(this->connection, this->mirror)) + this->mirror = this->connection->findMirror(); + + this->mirrorMap->removeConnection(this->mirror); + } + this->map->removeConnection(this->connection); + + QUndoCommand::undo(); +} + +/****************************************************************************** + ************************************************************************ + ******************************************************************************/ + +MapConnectionRemove::MapConnectionRemove(Map *map, MapConnection *connection, + QUndoCommand *parent) : QUndoCommand(parent) { + setText("Remove Map Connection"); + + this->map = map; + this->connection = connection; + + if (porymapConfig.mirrorConnectingMaps) { + this->mirror = this->connection->findMirror(); + this->mirrorMap = this->connection->targetMap(); + } +} + +void MapConnectionRemove::redo() { + QUndoCommand::redo(); + + if (this->mirrorMap) { + // See comment in MapConnectionAdd::undo + if (!MapConnection::areMirrored(this->connection, this->mirror)) + this->mirror = this->connection->findMirror(); + + this->mirrorMap->removeConnection(this->mirror); + } + this->map->removeConnection(this->connection); +} + +void MapConnectionRemove::undo() { + this->map->addConnection(this->connection); + if (this->mirrorMap) + this->mirrorMap->addConnection(this->mirror); + + QUndoCommand::undo(); +} diff --git a/src/core/map.cpp b/src/core/map.cpp index ed011ec57..91e196fe5 100644 --- a/src/core/map.cpp +++ b/src/core/map.cpp @@ -215,11 +215,13 @@ QPixmap Map::renderBorder(bool ignoreCache) { return layout->border_pixmap; } -QPixmap Map::renderConnection(const QString &direction, MapLayout * fromLayout) { - // Cardinal connections are rendered within the bounds of the border draw distance, - // and we need to render the nearest segment of the map. - // Dive/Emerge maps are rendered normally, but within the bounds of their parent map. - int x = 0, y = 0, w = getWidth(), h = getHeight(); +// Get the portion of the map that can be rendered when rendered as a map connection. +// Cardinal connections render the nearest segment of their map and within the bounds of the border draw distance, +// Dive/Emerge connections are rendered normally within the bounds of their parent map. +QRect Map::getConnectionRect(const QString &direction, MapLayout * fromLayout) { + int x = 0, y = 0; + int w = getWidth(), h = getHeight(); + if (direction == "up") { h = qMin(h, BORDER_DISTANCE); y = getHeight() - h; @@ -234,15 +236,26 @@ QPixmap Map::renderConnection(const QString &direction, MapLayout * fromLayout) if (fromLayout) { w = qMin(w, fromLayout->getWidth()); h = qMin(h, fromLayout->getHeight()); - fromLayout = nullptr; // This would be used for palettes later, but we want our own palettes, not the parent's. } } else { // Unknown direction - return QPixmap(); + return QRect(); } + return QRect(x, y, w, h); +} - render(true, fromLayout, QRect(x, y, w, h)); - QImage connection_image = image.copy(x * 16, y * 16, w * 16, h * 16); +QPixmap Map::renderConnection(const QString &direction, MapLayout * fromLayout) { + QRect bounds = getConnectionRect(direction, fromLayout); + if (!bounds.isValid()) + return QPixmap(); + + // 'fromLayout' will be used in 'render' to get the palettes from the parent map. + // Dive/Emerge connections render normally with their own palettes, so we ignore this. + if (MapConnection::isDiving(direction)) + fromLayout = nullptr; + + render(true, fromLayout, bounds); + QImage connection_image = image.copy(bounds.x() * 16, bounds.y() * 16, bounds.width() * 16, bounds.height() * 16); return QPixmap::fromImage(connection_image); } @@ -518,54 +531,62 @@ void Map::addEvent(Event *event) { } void Map::deleteConnections() { - qDeleteAll(connections); - connections.clear(); + qDeleteAll(this->ownedConnections); + this->ownedConnections.clear(); + this->connections.clear(); } QList Map::getConnections() const { return connections; } -void Map::addConnection(MapConnection *connection) { - if (!connection || connections.contains(connection)) - return; +bool Map::addConnection(MapConnection *connection) { + if (!connection || this->connections.contains(connection)) + return false; - // Adding new Dive/Emerge maps replaces an existing one. + // Maps should only have one Dive/Emerge connection at a time. + // (Users can technically have more by editing their data manually, but we will only display one at a time) + // Any additional connections being added (this can happen via mirroring) are tracked for deleting but otherwise ignored. if (MapConnection::isDiving(connection->direction())) { - for (auto connectionToReplace : connections) { - if (connectionToReplace->direction() != connection->direction()) - continue; - if (porymapConfig.mirrorConnectingMaps) { - auto mirror = connectionToReplace->findMirror(); - if (mirror && mirror->parentMap()) - mirror->parentMap()->removeConnection(mirror); - delete mirror; + for (auto i : this->connections) { + if (i->direction() == connection->direction()) { + this->ownedConnections.insert(connection); + connection->setParentMap(this, false); + return true; } - removeConnection(connectionToReplace); - delete connectionToReplace; - break; } } loadConnection(connection); modify(); emit connectionAdded(connection); + return true; } void Map::loadConnection(MapConnection *connection) { if (!connection) return; - connections.append(connection); + this->connections.append(connection); + this->ownedConnections.insert(connection); connection->setParentMap(this, false); } -// Caller takes ownership of connection -void Map::removeConnection(MapConnection *connection) { - if (!connections.removeOne(connection)) - return; - connection->setParentMap(nullptr, false); +// connection should not be deleted here, a pointer to it is allowed to persist in the edit history +bool Map::removeConnection(MapConnection *connection) { + if (!this->connections.removeOne(connection)) + return false; modify(); emit connectionRemoved(connection); + return true; +} + +// Same as Map::removeConnection but caller takes ownership of connection. +bool Map::takeConnection(MapConnection *connection) { + if (!this->removeConnection(connection)) + return false; + connection->setParentMap(nullptr, false); + this->ownedConnections.remove(connection); + return true; } void Map::modify() { @@ -580,6 +601,27 @@ bool Map::hasUnsavedChanges() { return !editHistory.isClean() || hasUnsavedDataChanges || !isPersistedToFile; } +void Map::pruneEditHistory() { + // Edit history for map connections gets messy because edits on other maps can affect the current map. + // To avoid complications we clear MapConnection edit history when the user opens a different map. + // No other edits within a single map depend on MapConnections so they can be pruned safely. + static const QSet mapConnectionIds = { + ID_MapConnectionMove, + ID_MapConnectionChangeDirection, + ID_MapConnectionChangeMap, + ID_MapConnectionAdd, + ID_MapConnectionRemove + }; + for (int i = 0; i < this->editHistory.count(); i++) { + // Qt really doesn't expect editing commands in the stack to be valid (fair). + // A better future design might be to have separate edit histories per map tab, + // and dumping the entire Connections tab history with QUndoStack::clear. + auto command = const_cast(this->editHistory.command(i)); + if (mapConnectionIds.contains(command->id())) + command->setObsolete(true); + } +} + bool Map::isWithinBounds(int x, int y) { return (x >= 0 && x < this->getWidth() && y >= 0 && y < this->getHeight()); } diff --git a/src/core/mapconnection.cpp b/src/core/mapconnection.cpp index 5fe2e730c..022158a02 100644 --- a/src/core/mapconnection.cpp +++ b/src/core/mapconnection.cpp @@ -16,14 +16,14 @@ MapConnection::MapConnection(const QString &targetMapName, const QString &direct m_offset = offset; } -bool MapConnection::isMirror(const MapConnection* other) { - if (!other || !other->m_parentMap) +bool MapConnection::areMirrored(const MapConnection* a, const MapConnection* b) { + if (!a || !b || !a->m_parentMap || !b->m_parentMap) return false; - return parentMapName() == other->m_targetMapName - && m_targetMapName == other->parentMapName() - && m_offset == -other->m_offset - && m_direction == oppositeDirection(other->m_direction); + return a->parentMapName() == b->m_targetMapName + && a->m_targetMapName == b->parentMapName() + && a->m_offset == -b->m_offset + && a->m_direction == oppositeDirection(b->m_direction); } MapConnection* MapConnection::findMirror() { @@ -35,7 +35,7 @@ MapConnection* MapConnection::findMirror() { // Note: There is no strict source -> mirror pairing, i.e. we are not guaranteed // to always get the same MapConnection if there are multiple identical copies. for (auto connection : map->getConnections()) { - if (this != connection && this->isMirror(connection)) + if (this != connection && areMirrored(this, connection)) return connection; } return nullptr; @@ -72,14 +72,14 @@ void MapConnection::setParentMap(Map* map, bool mirror) { if (map == m_parentMap) return; - if (mirror && porymapConfig.mirrorConnectingMaps) { + if (mirror) { auto connection = findMirror(); if (connection) connection->setTargetMapName(map ? map->name : QString(), false); } if (m_parentMap) - m_parentMap->removeConnection(this); + m_parentMap->takeConnection(this); auto before = m_parentMap; m_parentMap = map; @@ -98,7 +98,7 @@ void MapConnection::setTargetMapName(const QString &targetMapName, bool mirror) if (targetMapName == m_targetMapName) return; - if (mirror && porymapConfig.mirrorConnectingMaps) { + if (mirror) { auto connection = findMirror(); if (connection) connection->setParentMap(getMap(targetMapName), false); @@ -114,7 +114,7 @@ void MapConnection::setDirection(const QString &direction, bool mirror) { if (direction == m_direction) return; - if (mirror && porymapConfig.mirrorConnectingMaps) { + if (mirror) { auto connection = findMirror(); if (connection) connection->setDirection(oppositeDirection(direction), false); @@ -130,7 +130,7 @@ void MapConnection::setOffset(int offset, bool mirror) { if (offset == m_offset) return; - if (mirror && porymapConfig.mirrorConnectingMaps) { + if (mirror) { auto connection = findMirror(); if (connection) connection->setOffset(-offset, false); diff --git a/src/editor.cpp b/src/editor.cpp index e20936652..c7acdea0e 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -743,9 +743,7 @@ void Editor::displayConnection(MapConnection* connection) { } // Create connection image - QPixmap pixmap = connection->getPixmap(); - QPoint pos = calculateConnectionPosition(connection, pixmap); - ConnectionPixmapItem *pixmapItem = new ConnectionPixmapItem(pixmap, connection, pos.x(), pos.y()); + ConnectionPixmapItem *pixmapItem = new ConnectionPixmapItem(connection, getConnectionOrigin(connection)); pixmapItem->render(); scene->addItem(pixmapItem); maskNonVisibleConnectionTiles(); @@ -756,82 +754,70 @@ void Editor::displayConnection(MapConnection* connection) { // It's possible for a map connection to be displayed repeatedly if it's being // updated by mirroring and the target map is changing to/from the current map. - connection->disconnect(); + QObject::disconnect(connection, &MapConnection::targetMapNameChanged, nullptr, nullptr); + QObject::disconnect(connection, &MapConnection::directionChanged, nullptr, nullptr); + QObject::disconnect(connection, &MapConnection::offsetChanged, nullptr, nullptr); // Double clicking the list item or pixmap opens the connected map connect(listItem, &ConnectionsListItem::doubleClicked, this, &Editor::onMapConnectionDoubleClicked); connect(pixmapItem, &ConnectionPixmapItem::connectionItemDoubleClicked, this, &Editor::onMapConnectionDoubleClicked); // Sync the selection highlight between the list UI and the pixmap - connect(pixmapItem, &ConnectionPixmapItem::selectionChanged, [this, listItem, pixmapItem](bool selected) { + connect(pixmapItem, &ConnectionPixmapItem::selectionChanged, [=](bool selected) { listItem->setSelected(selected); if (selected) setSelectedConnectionItem(pixmapItem); }); - connect(listItem, &ConnectionsListItem::selected, [this, pixmapItem] { + connect(listItem, &ConnectionsListItem::selected, [=] { setSelectedConnectionItem(pixmapItem); }); // Sync edits to 'offset' between the list UI and the pixmap - connect(connection, &MapConnection::offsetChanged, [this, listItem, pixmapItem](int, int) { + connect(connection, &MapConnection::offsetChanged, [=](int, int) { listItem->updateUI(); - updateConnectionPixmapPos(pixmapItem); + pixmapItem->updatePos(); + maskNonVisibleConnectionTiles(); }); // Sync edits to 'direction' between the list UI and the pixmap - connect(connection, &MapConnection::directionChanged, [this, listItem, pixmapItem](QString before, QString after) { - if (MapConnection::isHorizontal(before) != MapConnection::isHorizontal(after) - || MapConnection::isVertical(before) != MapConnection::isVertical(after)) { - // If the direction has changed between vertical/horizontal then the old offset may not make sense, so we reset it - pixmapItem->connection->setOffset(0); - } + connect(connection, &MapConnection::directionChanged, [=](QString, QString) { listItem->updateUI(); updateConnectionPixmap(pixmapItem); }); // Sync edits to 'map' between the list UI and the pixmap - connect(connection, &MapConnection::targetMapNameChanged, [this, listItem, pixmapItem](QString, QString) { - // The old offset may not make sense, so we reset it - pixmapItem->connection->setOffset(0); + connect(connection, &MapConnection::targetMapNameChanged, [=](QString, QString) { listItem->updateUI(); updateConnectionPixmap(pixmapItem); }); - // User manually deleting connection via the remove button - connect(listItem, &ConnectionsListItem::removed, [this](MapConnection* connection) { removeConnection(connection); }); - // When the pixmap is deleted, remove its associated list item connect(pixmapItem, &ConnectionPixmapItem::destroyed, listItem, &ConnectionsListItem::deleteLater); connection_items.append(pixmapItem); + + // If this was a recent addition from the user we should select it. + // We intentionally exclude connections added programmatically, e.g. by mirroring. + if (connection_to_select == connection) { + connection_to_select = nullptr; + setSelectedConnectionItem(pixmapItem); + } } -void Editor::addConnection(MapConnection * connection) { +void Editor::addConnection(MapConnection* connection) { if (!connection) return; - this->map->addConnection(connection); - if (porymapConfig.mirrorConnectingMaps) - connection->createMirror(); + // Mark this connection to be selected once its display elements have been created. + // It's possible this is a Dive/Emerge connection, but that's ok (no selection will occur). + connection_to_select = connection; - // TODO: Edit history + this->map->editHistory.push(new MapConnectionAdd(this->map, connection)); } void Editor::removeConnection(MapConnection* connection) { if (!connection) return; - - if (porymapConfig.mirrorConnectingMaps) { - auto mirror = connection->findMirror(); - if (mirror && mirror->parentMap()) - mirror->parentMap()->removeConnection(mirror); - delete mirror; - } - - if (connection->parentMap()) - connection->parentMap()->removeConnection(connection); - delete connection; - - // TODO: Edit history + this->map->editHistory.push(new MapConnectionRemove(this->map, connection)); } void Editor::removeSelectedConnection() { @@ -887,10 +873,6 @@ void Editor::displayDivingConnection(MapConnection* connection) { if (!MapConnection::isDiving(direction)) return; - // Save some rendering time if it won't be displayed - if (!porymapConfig.showDiveEmergeMaps) - return; - // Note: We only support editing 1 Dive and Emerge connection per map. // In a vanilla game only the first Dive/Emerge connection is considered, so allowing // users to have multiple is likely to lead to confusion. In case users have changed @@ -898,15 +880,18 @@ void Editor::displayDivingConnection(MapConnection* connection) { if (diving_map_items.value(direction)) return; - // Create map image - auto item = new DivingMapPixmapItem(connection); + // Create map display + auto comboBox = (direction == "dive") ? ui->comboBox_DiveMap : ui->comboBox_EmergeMap; + auto item = new DivingMapPixmapItem(connection, comboBox); scene->addItem(item); diving_map_items.insert(direction, item); - // Display map name in combo box - auto comboBox = (direction == "dive") ? ui->comboBox_DiveMap : ui->comboBox_EmergeMap; - const QSignalBlocker blocker(comboBox); - comboBox->setCurrentText(connection->targetMapName()); + updateDivingMapsVisibility(); +} + +void Editor::renderDivingConnections() { + for (auto item : diving_map_items.values()) + item->updatePixmap(); } void Editor::removeDivingMapPixmap(MapConnection *connection) { @@ -917,7 +902,7 @@ void Editor::removeDivingMapPixmap(MapConnection *connection) { if (!diving_map_items.contains(direction)) return; - // If the diving map being displayed is different than the one being removed we don't need to do anything. + // If the diving map being removed is different than the one that's currently displayed we don't need to do anything. if (diving_map_items.value(direction)->connection() != connection) return; @@ -927,11 +912,6 @@ void Editor::removeDivingMapPixmap(MapConnection *connection) { pixmapItem->scene()->removeItem(pixmapItem); delete pixmapItem; - // Clear map name from combo box - auto comboBox = (direction == "dive") ? ui->comboBox_DiveMap : ui->comboBox_EmergeMap; - const QSignalBlocker blocker(comboBox); - comboBox->setCurrentText(""); - // Reveal any previously-hidden connection (because we only ever display one diving map of each type). // Note: When this occurs as a result of the user clicking the 'X' clear button it seems the QComboBox // doesn't expect the line edit to be immediately repopulated, and the 'X' doesn't reappear. @@ -942,6 +922,7 @@ void Editor::removeDivingMapPixmap(MapConnection *connection) { break; } } + updateDivingMapsVisibility(); } void Editor::updateDiveMap(QString mapName) { @@ -953,27 +934,24 @@ void Editor::updateEmergeMap(QString mapName) { } void Editor::setDivingMapName(QString mapName, QString direction) { - // Only the first Dive/Emerge map (if present) is considered, as in-game. - MapConnection* connection = nullptr; - for (auto i : map->getConnections()) { - if (i->direction() == direction) { - connection = i; - break; - } - } + auto pixmapItem = diving_map_items.value(direction); + MapConnection *connection = pixmapItem ? pixmapItem->connection() : nullptr; + // TODO: Test edit history if (connection) { + if (mapName == connection->targetMapName()) + return; // No change + // Update existing connection if (mapName.isEmpty()) { removeConnection(connection); } else { - connection->setTargetMapName(mapName); + map->editHistory.push(new MapConnectionChangeMap(connection, mapName)); } } else if (!mapName.isEmpty()) { // Create new connection addConnection(new MapConnection(mapName, direction)); } - updateDivingMapsVisibility(); } void Editor::updateDivingMapsVisibility() { @@ -994,58 +972,36 @@ void Editor::updateDivingMapsVisibility() { } } -QPoint Editor::calculateConnectionPosition(MapConnection *connection, const QPixmap &pixmap) { +// Get the 'origin' point for the connection's pixmap, i.e. where it should be positioned in the editor when connection->offset() == 0. +// This differs depending on the connection's direction and the dimensions of its target map or parent map. +QPoint Editor::getConnectionOrigin(MapConnection *connection) { + if (!connection) + return QPoint(0, 0); + + Map *parentMap = connection->parentMap(); + Map *targetMap = connection->targetMap(); const QString direction = connection->direction(); - int offset = connection->offset(); int x = 0, y = 0; - const int mWidth = 16, mHeight = 16; - if (direction == "up") { - x = offset * mWidth; - y = -pixmap.height(); + + if (direction == "right") { + if (parentMap) x = parentMap->getWidth(); } else if (direction == "down") { - x = offset * mWidth; - y = map->getHeight() * mHeight; + if (parentMap) y = parentMap->getHeight(); } else if (direction == "left") { - x = -pixmap.width(); - y = offset * mHeight; - } else if (direction == "right") { - x = map->getWidth() * mWidth; - y = offset * mHeight; + if (targetMap) x = -targetMap->getConnectionRect(direction).width(); + } else if (direction == "up") { + if (targetMap) y = -targetMap->getConnectionRect(direction).height(); } - return QPoint(x, y); + return QPoint(x * 16, y * 16); } void Editor::updateConnectionPixmap(ConnectionPixmapItem* pixmapItem) { - if (!pixmapItem || !pixmapItem->connection) + if (!pixmapItem) return; - pixmapItem->initialOffset = pixmapItem->connection->offset(); - pixmapItem->basePixmap = pixmapItem->connection->getPixmap(); - QPoint pos = calculateConnectionPosition(pixmapItem->connection, pixmapItem->basePixmap); - - const QSignalBlocker blocker(pixmapItem); - pixmapItem->setPixmap(pixmapItem->basePixmap); - pixmapItem->initialX = pos.x(); - pixmapItem->initialY = pos.y(); - pixmapItem->setPos(pos); - pixmapItem->render(); - - maskNonVisibleConnectionTiles(); -} - -void Editor::updateConnectionPixmapPos(ConnectionPixmapItem* pixmapItem) { - if (!pixmapItem || !pixmapItem->connection) - return; + pixmapItem->setOrigin(getConnectionOrigin(pixmapItem->connection)); + pixmapItem->render(true); // Full render to reflect map changes - const QSignalBlocker blocker(pixmapItem); - MapConnection *connection = pixmapItem->connection; - if (MapConnection::isVertical(connection->direction())) { - qreal x = pixmapItem->initialX + (connection->offset() - pixmapItem->initialOffset) * 16; - if (x != pixmapItem->x()) pixmapItem->setX(x); - } else if (MapConnection::isHorizontal(connection->direction())) { - qreal y = pixmapItem->initialY + (connection->offset() - pixmapItem->initialOffset) * 16; - if (y != pixmapItem->y()) pixmapItem->setY(y); - } maskNonVisibleConnectionTiles(); } @@ -1257,9 +1213,14 @@ bool Editor::setMap(QString map_name) { // disconnect previous map's signals so they are not firing // multiple times if set again in the future if (map) { + map->pruneEditHistory(); map->disconnect(this); - for (auto connection : map->getConnections()) - connection->disconnect(); + for (auto connection : map->getConnections()) { + // Disconnect signals used by the display + QObject::disconnect(connection, &MapConnection::targetMapNameChanged, nullptr, nullptr); + QObject::disconnect(connection, &MapConnection::directionChanged, nullptr, nullptr); + QObject::disconnect(connection, &MapConnection::offsetChanged, nullptr, nullptr); + } } if (project) { @@ -1777,19 +1738,20 @@ void Editor::clearMapConnections() { } diving_map_items.clear(); + // Reset to single opacity slider + ui->stackedWidget_DiveMapOpacity->setCurrentIndex(1); + selected_connection_item = nullptr; } void Editor::displayMapConnections() { clearMapConnections(); - for (MapConnection *connection : map->getConnections()) + for (auto connection : map->getConnections()) displayConnection(connection); if (!connection_items.isEmpty()) setSelectedConnectionItem(connection_items.first()); - - updateDivingMapsVisibility(); } void Editor::clearConnectionMask() { @@ -1859,16 +1821,13 @@ void Editor::updateMapBorder() { } void Editor::updateMapConnections() { - for (auto item : connection_items) { - if (!item->connection) - continue; - item->basePixmap = item->connection->getPixmap(); - item->render(); - } + for (auto item : connection_items) + item->render(true); maskNonVisibleConnectionTiles(); } +// TODO: Check first condition, move to Map int Editor::getBorderDrawDistance(int dimension) { // Draw sufficient border blocks to fill the player's view (BORDER_DISTANCE) if (dimension >= BORDER_DISTANCE) { diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 0f1b83dfd..e95b3bb05 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2306,7 +2306,7 @@ void MainWindow::setDivingMapsVisible(bool visible) { if (visible) { // We skip rendering diving maps if this setting is not enabled, // so when we enable it we need to make sure they've rendered. - this->editor->displayDivingConnections(); + this->editor->renderDivingConnections(); } this->editor->updateDivingMapsVisibility(); } @@ -2662,14 +2662,12 @@ void MainWindow::showExportMapImageWindow(ImageExporterMode mode) { } void MainWindow::on_pushButton_AddConnection_clicked() { - if (!this->editor || !this->editor->map) + if (!this->editor || !this->editor->map || !this->editor->project) return; auto dialog = new NewMapConnectionDialog(this, this->editor->map, this->editor->project->mapNames); - if (dialog->exec() == QDialog::Accepted) { - this->editor->addConnection(dialog->result); - this->editor->setSelectedConnection(dialog->result); - } + connect(dialog, &NewMapConnectionDialog::accepted, this->editor, &Editor::addConnection); + dialog->exec(); } void MainWindow::on_pushButton_NewWildMonGroup_clicked() { diff --git a/src/ui/connectionpixmapitem.cpp b/src/ui/connectionpixmapitem.cpp index c98d3ba78..f84120128 100644 --- a/src/ui/connectionpixmapitem.cpp +++ b/src/ui/connectionpixmapitem.cpp @@ -1,8 +1,27 @@ #include "connectionpixmapitem.h" +#include "editcommands.h" +#include "map.h" #include -void ConnectionPixmapItem::render() { +ConnectionPixmapItem::ConnectionPixmapItem(MapConnection* connection, int x, int y) + : QGraphicsPixmapItem(connection->getPixmap()), + connection(connection) +{ + this->setEditable(true); + this->basePixmap = pixmap(); + this->setOrigin(x, y); +} + +ConnectionPixmapItem::ConnectionPixmapItem(MapConnection* connection, QPoint pos) + : ConnectionPixmapItem(connection, pos.x(), pos.y()) +{} + +// Render additional visual effects on top of the base map image. +void ConnectionPixmapItem::render(bool ignoreCache) { + if (ignoreCache) + this->basePixmap = this->connection->getPixmap(); + QPixmap pixmap = this->basePixmap.copy(0, 0, this->basePixmap.width(), this->basePixmap.height()); this->setZValue(-1); @@ -31,27 +50,23 @@ QVariant ConnectionPixmapItem::itemChange(GraphicsItemChange change, const QVari if (change == ItemPositionChange) { QPointF newPos = value.toPointF(); - qreal x, y; - int newOffset = this->initialOffset; + qreal x = this->originX; + qreal y = this->originY; + int newOffset = this->connection->offset(); + + // Restrict movement to the metatile grid and perpendicular to the connection direction. if (MapConnection::isVertical(this->connection->direction())) { - x = round(newPos.x() / 16) * 16; - newOffset += (x - initialX) / 16; - x = newOffset * 16; - } - else { - x = this->initialX; + x = (round(newPos.x() / this->mWidth) * this->mWidth) - this->originX; + newOffset = x / this->mWidth; + } else if (MapConnection::isHorizontal(this->connection->direction())) { + y = (round(newPos.y() / this->mHeight) * this->mHeight) - this->originY; + newOffset = y / this->mHeight; } - if (MapConnection::isHorizontal(this->connection->direction())) { - y = round(newPos.y() / 16) * 16; - newOffset += (y - this->initialY) / 16; - y = newOffset * 16; - } - else { - y = this->initialY; - } + // This is convoluted because of how our edit history works; this would otherwise just be 'this->connection->setOffset(newOffset);' + if (this->connection->parentMap() && newOffset != this->connection->offset()) + this->connection->parentMap()->editHistory.push(new MapConnectionMove(this->connection, newOffset, this->actionId)); - this->connection->setOffset(newOffset); return QPointF(x, y); } else { @@ -59,6 +74,32 @@ QVariant ConnectionPixmapItem::itemChange(GraphicsItemChange change, const QVari } } +// If connection->offset changed externally we call this to correct our position. +void ConnectionPixmapItem::updatePos() { + const QSignalBlocker blocker(this); + + qreal x = this->originX; + qreal y = this->originY; + + if (MapConnection::isVertical(this->connection->direction())) { + x += this->connection->offset() * this->mWidth; + } else if (MapConnection::isHorizontal(this->connection->direction())) { + y += this->connection->offset() * this->mHeight; + } + + this->setPos(x, y); +} + +// Set the pixmap's external origin point, i.e. the pixmap's position when connection->offset == 0 +void ConnectionPixmapItem::setOrigin(int x, int y) { + this->originX = x; + this->originY = y; + updatePos(); +} +void ConnectionPixmapItem::setOrigin(QPoint pos) { + this->setOrigin(pos.x(), pos.y()); +} + void ConnectionPixmapItem::setEditable(bool editable) { setFlag(ItemIsMovable, editable); setFlag(ItemSendsGeometryChanges, editable); @@ -82,6 +123,11 @@ void ConnectionPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *) { this->setSelected(true); } +void ConnectionPixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { + this->actionId++; // Distinguish between move actions for the edit history + QGraphicsPixmapItem::mouseReleaseEvent(event); +} + void ConnectionPixmapItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *) { emit connectionItemDoubleClicked(this->connection); } diff --git a/src/ui/connectionslistitem.cpp b/src/ui/connectionslistitem.cpp index 049bb17d0..eb7f94a65 100644 --- a/src/ui/connectionslistitem.cpp +++ b/src/ui/connectionslistitem.cpp @@ -1,5 +1,9 @@ #include "connectionslistitem.h" #include "ui_connectionslistitem.h" +#include "editcommands.h" +#include "map.h" + +#include ConnectionsListItem::ConnectionsListItem(QWidget *parent, MapConnection * connection, const QStringList &mapNames) : QFrame(parent), @@ -18,11 +22,23 @@ ConnectionsListItem::ConnectionsListItem(QWidget *parent, MapConnection * connec ui->comboBox_Map->setMinimumContentsLength(6); ui->comboBox_Map->addItems(mapNames); ui->comboBox_Map->setFocusedScrollingEnabled(false); // Scrolling could cause rapid changes to many different maps + ui->comboBox_Map->setInsertPolicy(QComboBox::NoInsert); ui->spinBox_Offset->setMinimum(INT_MIN); ui->spinBox_Offset->setMaximum(INT_MAX); + // Invalid map names are not considered a change. If editing finishes with an invalid name, restore the previous name. + connect(ui->comboBox_Map->lineEdit(), &QLineEdit::editingFinished, [this] { + const QSignalBlocker blocker(ui->comboBox_Map); + if (ui->comboBox_Map->findText(ui->comboBox_Map->currentText()) < 0) + ui->comboBox_Map->setTextItem(this->connection->targetMapName()); + }); + + // Distinguish between move actions for the edit history + connect(ui->spinBox_Offset, &QSpinBox::editingFinished, [this] { this->actionId++; }); + this->connection = connection; + this->map = connection->parentMap(); this->updateUI(); } @@ -32,6 +48,9 @@ ConnectionsListItem::~ConnectionsListItem() } void ConnectionsListItem::updateUI() { + if (!this->connection) + return; + const QSignalBlocker blocker1(ui->comboBox_Direction); const QSignalBlocker blocker2(ui->comboBox_Map); const QSignalBlocker blocker3(ui->spinBox_Offset); @@ -56,26 +75,30 @@ void ConnectionsListItem::mousePressEvent(QMouseEvent *) { this->setSelected(true); } +// TODO: This happens by accident a lot. Convert to button? void ConnectionsListItem::mouseDoubleClickEvent(QMouseEvent *) { emit doubleClicked(this->connection); } void ConnectionsListItem::on_comboBox_Direction_currentTextChanged(const QString &direction) { this->setSelected(true); - this->connection->setDirection(direction); + if (this->map) + this->map->editHistory.push(new MapConnectionChangeDirection(this->connection, direction)); } void ConnectionsListItem::on_comboBox_Map_currentTextChanged(const QString &mapName) { this->setSelected(true); - if (ui->comboBox_Map->findText(mapName) >= 0) - this->connection->setTargetMapName(mapName); + if (this->map && ui->comboBox_Map->findText(mapName) >= 0) + this->map->editHistory.push(new MapConnectionChangeMap(this->connection, mapName)); } void ConnectionsListItem::on_spinBox_Offset_valueChanged(int offset) { this->setSelected(true); - this->connection->setOffset(offset); + if (this->map) + this->map->editHistory.push(new MapConnectionMove(this->connection, offset, this->actionId)); } void ConnectionsListItem::on_button_Delete_clicked() { - emit this->removed(this->connection); + if (this->map) + this->map->editHistory.push(new MapConnectionRemove(this->map, this->connection)); } diff --git a/src/ui/divingmappixmapitem.cpp b/src/ui/divingmappixmapitem.cpp new file mode 100644 index 000000000..70a611fa0 --- /dev/null +++ b/src/ui/divingmappixmapitem.cpp @@ -0,0 +1,46 @@ +#include "divingmappixmapitem.h" +#include "config.h" + +DivingMapPixmapItem::DivingMapPixmapItem(MapConnection *connection, QComboBox *combo) + : QGraphicsPixmapItem(getBasePixmap(connection)) +{ + m_connection = connection; + m_combo = combo; + + setComboText(connection->targetMapName()); + + // Update display if the connected map is swapped. + connect(m_connection, &MapConnection::targetMapNameChanged, this, &DivingMapPixmapItem::onTargetMapChanged); +} + +DivingMapPixmapItem::~DivingMapPixmapItem() { + // Clear map name from combo box + setComboText(""); +} + +QPixmap DivingMapPixmapItem::getBasePixmap(MapConnection* connection) { + if (!connection) + return QPixmap(); + if (!porymapConfig.showDiveEmergeMaps) + return QPixmap(); // Save some rendering time if it won't be displayed + if (connection->targetMapName() == connection->parentMapName()) + return QPixmap(); // If the map is connected to itself then rendering is pointless. + return connection->getPixmap(); +} + +void DivingMapPixmapItem::updatePixmap() { + setPixmap(getBasePixmap(m_connection)); +} + +void DivingMapPixmapItem::onTargetMapChanged() { + updatePixmap(); + setComboText(m_connection->targetMapName()); +} + +void DivingMapPixmapItem::setComboText(const QString &text) { + if (!m_combo) + return; + + const QSignalBlocker blocker(m_combo); + m_combo->setCurrentText(text); +} diff --git a/src/ui/mapimageexporter.cpp b/src/ui/mapimageexporter.cpp index 03cbc2b80..b61d3738c 100644 --- a/src/ui/mapimageexporter.cpp +++ b/src/ui/mapimageexporter.cpp @@ -192,6 +192,12 @@ bool MapImageExporter::historyItemAppliesToFrame(const QUndoCommand *command) { return this->showCollision; case CommandId::ID_PaintBorder: return this->showBorder; + case CommandId::ID_MapConnectionMove: + case CommandId::ID_MapConnectionChangeDirection: + case CommandId::ID_MapConnectionChangeMap: + case CommandId::ID_MapConnectionAdd: + case CommandId::ID_MapConnectionRemove: + return this->showUpConnections || this->showDownConnections || this->showLeftConnections || this->showRightConnections; case CommandId::ID_EventMove: case CommandId::ID_EventShift: case CommandId::ID_EventCreate: @@ -398,14 +404,15 @@ QPixmap MapImageExporter::getFormattedMapPixmap(Map *map, bool ignoreBorder) { if (!this->mode) { // if showing connections, draw on outside of image QPainter connectionPainter(&pixmap); + // TODO: Is this still the most sensible way to do this (esp. rendering pixmap) for (auto connectionItem : editor->connection_items) { const QString direction = connectionItem->connection->direction(); if ((showUpConnections && direction == "up") || (showDownConnections && direction == "down") || (showLeftConnections && direction == "left") || (showRightConnections && direction == "right")) - connectionPainter.drawImage(connectionItem->initialX + borderWidth, connectionItem->initialY + borderHeight, - connectionItem->basePixmap.toImage()); + connectionPainter.drawImage(connectionItem->x() + borderWidth, connectionItem->y() + borderHeight, + connectionItem->connection->getPixmap().toImage()); } connectionPainter.end(); } diff --git a/src/ui/newmapconnectiondialog.cpp b/src/ui/newmapconnectiondialog.cpp index aa7c05cf1..254b4b6e9 100644 --- a/src/ui/newmapconnectiondialog.cpp +++ b/src/ui/newmapconnectiondialog.cpp @@ -8,14 +8,13 @@ NewMapConnectionDialog::NewMapConnectionDialog(QWidget *parent, Map* map, const ui->setupUi(this); setAttribute(Qt::WA_DeleteOnClose); - this->result = nullptr; - ui->comboBox_Direction->setEditable(false); ui->comboBox_Direction->setMinimumContentsLength(0); ui->comboBox_Direction->addItems(MapConnection::cardinalDirections); ui->comboBox_Map->setMinimumContentsLength(6); ui->comboBox_Map->addItems(mapNames); + ui->comboBox_Map->setInsertPolicy(QComboBox::NoInsert); // Choose default direction QMap directionCounts; @@ -51,6 +50,11 @@ NewMapConnectionDialog::~NewMapConnectionDialog() } void NewMapConnectionDialog::accept() { - this->result = new MapConnection(ui->comboBox_Map->currentText(), ui->comboBox_Direction->currentText()); + // Invalid map names are not allowed + if (ui->comboBox_Map->findText(ui->comboBox_Map->currentText()) < 0) { + // TODO: Display error message + return; + } + emit accepted(new MapConnection(ui->comboBox_Map->currentText(), ui->comboBox_Direction->currentText())); QDialog::accept(); } From 7a0ae5314346a1bbb164810cece24e45e21412cc Mon Sep 17 00:00:00 2001 From: GriffinR Date: Mon, 19 Aug 2024 18:49:57 -0400 Subject: [PATCH 27/30] Final MapConnection UI updates --- forms/connectionslistitem.ui | 22 +++++++++++--- forms/mainwindow.ui | 7 +++-- forms/newmapconnectiondialog.ui | 47 +++++++++++++++++++++++++++-- include/ui/connectionslistitem.h | 12 +++----- include/ui/newmapconnectiondialog.h | 3 ++ src/editor.cpp | 15 ++++----- src/ui/connectionslistitem.cpp | 9 +++--- src/ui/newmapconnectiondialog.cpp | 22 +++++++++++--- 8 files changed, 104 insertions(+), 33 deletions(-) diff --git a/forms/connectionslistitem.ui b/forms/connectionslistitem.ui index c39c86d01..bf04e8be1 100644 --- a/forms/connectionslistitem.ui +++ b/forms/connectionslistitem.ui @@ -65,7 +65,7 @@ - Remove this connection + Remove this connection. ... @@ -79,21 +79,35 @@ - Where the connected map should be positioned relative to the current map + Where the connected map should be positioned relative to the current map. - The name of the map to connect to the current map + The name of the map to connect to the current map. - The number of spaces to move the connected map perpendicular to its connected direction + The number of spaces to move the connected map perpendicular to its connected direction. + + + + + + + Open the connected map. + + + ... + + + + :/icons/map_go.ico:/icons/map_go.ico diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui index ff12136e0..8c9059bb4 100644 --- a/forms/mainwindow.ui +++ b/forms/mainwindow.ui @@ -2664,6 +2664,9 @@ + + If enabled, the connected Emerge and/or Dive maps will be displayed with an opacity set using the slider. + Show Emerge/Dive Maps @@ -2874,8 +2877,8 @@ 0 0 - 100 - 30 + 365 + 651 diff --git a/forms/newmapconnectiondialog.ui b/forms/newmapconnectiondialog.ui index da1096047..9b3a3b6e9 100644 --- a/forms/newmapconnectiondialog.ui +++ b/forms/newmapconnectiondialog.ui @@ -7,7 +7,7 @@ 0 0 234 - 120 + 162 @@ -43,7 +43,11 @@ - + + + The name of the map to connect to the current map. + + @@ -53,7 +57,24 @@ - + + + Where the connected map should be positioned relative to the current map. + + + + + + + color: rgb(255, 0, 0) + + + 'Map' must be the name of an existing map. + + + true + +
@@ -84,12 +105,32 @@ accepted() NewMapConnectionDialog accept() + + + 20 + 20 + + + 20 + 20 + + buttonBox rejected() NewMapConnectionDialog reject() + + + 20 + 20 + + + 20 + 20 + + diff --git a/include/ui/connectionslistitem.h b/include/ui/connectionslistitem.h index 87051c375..18c3434c8 100644 --- a/include/ui/connectionslistitem.h +++ b/include/ui/connectionslistitem.h @@ -14,8 +14,7 @@ class ConnectionsListItem; // We show the data for each map connection in the panel on the right side of the Connections tab. // An instance of this class is used for each item in that list. -// It communicates with the ConnectionPixmapItem on the map through a shared MapConnection pointer, -// and the two classes should signal one another when they change this data. +// It communicates with the ConnectionPixmapItem on the map through a shared MapConnection pointer. class ConnectionsListItem : public QFrame { Q_OBJECT @@ -27,28 +26,27 @@ class ConnectionsListItem : public QFrame void updateUI(); void setSelected(bool selected); - QPointer connection; - private: Ui::ConnectionsListItem *ui; + QPointer connection; Map *map; bool isSelected = false; unsigned actionId = 0; protected: void mousePressEvent(QMouseEvent*) override; - void mouseDoubleClickEvent(QMouseEvent*) override; signals: - void removed(MapConnection*); void selected(); - void doubleClicked(MapConnection*); + void removed(MapConnection*); + void openMapClicked(MapConnection*); private slots: void on_comboBox_Direction_currentTextChanged(const QString &direction); void on_comboBox_Map_currentTextChanged(const QString &mapName); void on_spinBox_Offset_valueChanged(int offset); void on_button_Delete_clicked(); + void on_button_OpenMap_clicked(); }; #endif // CONNECTIONSLISTITEM_H diff --git a/include/ui/newmapconnectiondialog.h b/include/ui/newmapconnectiondialog.h index 2e0ba28e9..4781c9719 100644 --- a/include/ui/newmapconnectiondialog.h +++ b/include/ui/newmapconnectiondialog.h @@ -24,6 +24,9 @@ class NewMapConnectionDialog : public QDialog private: Ui::NewMapConnectionDialog *ui; + + bool mapNameIsValid(); + void setWarningVisible(bool visible); }; #endif // NEWMAPCONNECTIONDIALOG_H diff --git a/src/editor.cpp b/src/editor.cpp index c7acdea0e..de1caa9a8 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -758,8 +758,8 @@ void Editor::displayConnection(MapConnection* connection) { QObject::disconnect(connection, &MapConnection::directionChanged, nullptr, nullptr); QObject::disconnect(connection, &MapConnection::offsetChanged, nullptr, nullptr); - // Double clicking the list item or pixmap opens the connected map - connect(listItem, &ConnectionsListItem::doubleClicked, this, &Editor::onMapConnectionDoubleClicked); + // Double clicking the pixmap or clicking the list item's map button opens the connected map + connect(listItem, &ConnectionsListItem::openMapClicked, this, &Editor::onMapConnectionDoubleClicked); connect(pixmapItem, &ConnectionPixmapItem::connectionItemDoubleClicked, this, &Editor::onMapConnectionDoubleClicked); // Sync the selection highlight between the list UI and the pixmap @@ -937,7 +937,6 @@ void Editor::setDivingMapName(QString mapName, QString direction) { auto pixmapItem = diving_map_items.value(direction); MapConnection *connection = pixmapItem ? pixmapItem->connection() : nullptr; - // TODO: Test edit history if (connection) { if (mapName == connection->targetMapName()) return; // No change @@ -1823,11 +1822,8 @@ void Editor::updateMapBorder() { void Editor::updateMapConnections() { for (auto item : connection_items) item->render(true); - - maskNonVisibleConnectionTiles(); } -// TODO: Check first condition, move to Map int Editor::getBorderDrawDistance(int dimension) { // Draw sufficient border blocks to fill the player's view (BORDER_DISTANCE) if (dimension >= BORDER_DISTANCE) { @@ -1920,7 +1916,12 @@ void Editor::updateBorderVisibility() { item->setVisible(visible); item->setEditable(editingConnections); item->setEnabled(visible); - item->render(); + + // When connecting a map to itself we don't bother to re-render the map connections in real-time, + // i.e. if the user paints a new metatile on the map this isn't immediately reflected in the connection. + // We're rendering them now, so we take the opportunity to do a full re-render for self-connections. + bool fullRender = (this->map && item->connection && this->map->name == item->connection->targetMapName()); + item->render(fullRender); } } diff --git a/src/ui/connectionslistitem.cpp b/src/ui/connectionslistitem.cpp index eb7f94a65..337623b42 100644 --- a/src/ui/connectionslistitem.cpp +++ b/src/ui/connectionslistitem.cpp @@ -75,11 +75,6 @@ void ConnectionsListItem::mousePressEvent(QMouseEvent *) { this->setSelected(true); } -// TODO: This happens by accident a lot. Convert to button? -void ConnectionsListItem::mouseDoubleClickEvent(QMouseEvent *) { - emit doubleClicked(this->connection); -} - void ConnectionsListItem::on_comboBox_Direction_currentTextChanged(const QString &direction) { this->setSelected(true); if (this->map) @@ -102,3 +97,7 @@ void ConnectionsListItem::on_button_Delete_clicked() { if (this->map) this->map->editHistory.push(new MapConnectionRemove(this->map, this->connection)); } + +void ConnectionsListItem::on_button_OpenMap_clicked() { + emit openMapClicked(this->connection); +} diff --git a/src/ui/newmapconnectiondialog.cpp b/src/ui/newmapconnectiondialog.cpp index 254b4b6e9..af06789fa 100644 --- a/src/ui/newmapconnectiondialog.cpp +++ b/src/ui/newmapconnectiondialog.cpp @@ -9,10 +9,8 @@ NewMapConnectionDialog::NewMapConnectionDialog(QWidget *parent, Map* map, const setAttribute(Qt::WA_DeleteOnClose); ui->comboBox_Direction->setEditable(false); - ui->comboBox_Direction->setMinimumContentsLength(0); ui->comboBox_Direction->addItems(MapConnection::cardinalDirections); - ui->comboBox_Map->setMinimumContentsLength(6); ui->comboBox_Map->addItems(mapNames); ui->comboBox_Map->setInsertPolicy(QComboBox::NoInsert); @@ -42,6 +40,12 @@ NewMapConnectionDialog::NewMapConnectionDialog(QWidget *parent, Map* map, const defaultMapName = mapNames.first(); } ui->comboBox_Map->setTextItem(defaultMapName); + + connect(ui->comboBox_Map, &QComboBox::currentTextChanged, [this] { + if (ui->label_Warning->isVisible() && mapNameIsValid()) + setWarningVisible(false); + }); + setWarningVisible(false); } NewMapConnectionDialog::~NewMapConnectionDialog() @@ -49,10 +53,18 @@ NewMapConnectionDialog::~NewMapConnectionDialog() delete ui; } +bool NewMapConnectionDialog::mapNameIsValid() { + return ui->comboBox_Map->findText(ui->comboBox_Map->currentText()) >= 0; +} + +void NewMapConnectionDialog::setWarningVisible(bool visible) { + ui->label_Warning->setVisible(visible); + adjustSize(); +} + void NewMapConnectionDialog::accept() { - // Invalid map names are not allowed - if (ui->comboBox_Map->findText(ui->comboBox_Map->currentText()) < 0) { - // TODO: Display error message + if (!mapNameIsValid()) { + setWarningVisible(true); return; } emit accepted(new MapConnection(ui->comboBox_Map->currentText(), ui->comboBox_Direction->currentText())); From f70e77ab66bf6dfb93a2a1ac1ae5af905b2df4d2 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Mon, 19 Aug 2024 21:31:36 -0400 Subject: [PATCH 28/30] Final MapConnection testing fixes --- include/core/map.h | 6 ++-- include/core/mapconnection.h | 4 +-- include/editor.h | 15 ++++----- include/ui/connectionslistitem.h | 4 +-- include/ui/mapimageexporter.h | 3 +- src/core/map.cpp | 51 ++++++++++++++++------------ src/core/mapconnection.cpp | 2 +- src/editor.cpp | 57 ++++++++++++-------------------- src/mainwindow.cpp | 4 ++- src/ui/connectionslistitem.cpp | 4 +-- src/ui/mapimageexporter.cpp | 41 +++++++++++++++++------ 11 files changed, 103 insertions(+), 88 deletions(-) diff --git a/include/core/map.h b/include/core/map.h index 270202362..2333c862a 100644 --- a/include/core/map.h +++ b/include/core/map.h @@ -99,9 +99,8 @@ class Map : public QObject void addEvent(Event *); void deleteConnections(); QList getConnections() const; - bool takeConnection(MapConnection *); - bool removeConnection(MapConnection *); - bool addConnection(MapConnection *); + void removeConnection(MapConnection *); + void addConnection(MapConnection *); void loadConnection(MapConnection *); QRect getConnectionRect(const QString &direction, MapLayout *fromLayout = nullptr); QPixmap renderConnection(const QString &direction, MapLayout *fromLayout = nullptr); @@ -133,6 +132,7 @@ class Map : public QObject private: void setNewDimensionsBlockdata(int newWidth, int newHeight); void setNewBorderDimensionsBlockdata(int newWidth, int newHeight); + void trackConnection(MapConnection*); // MapConnections in 'ownedConnections' but not 'connections' persist in the edit history. QList connections; diff --git a/include/core/mapconnection.h b/include/core/mapconnection.h index 6ffa85b79..21c00ac6e 100644 --- a/include/core/mapconnection.h +++ b/include/core/mapconnection.h @@ -55,8 +55,8 @@ class MapConnection : public QObject signals: void parentMapChanged(Map* before, Map* after); - void targetMapNameChanged(const QString &before, const QString &after); - void directionChanged(const QString &before, const QString &after); + void targetMapNameChanged(QString before, QString after); + void directionChanged(QString before, QString after); void offsetChanged(int before, int after); }; diff --git a/include/editor.h b/include/editor.h index 3b2c9ae64..89b6ccb59 100644 --- a/include/editor.h +++ b/include/editor.h @@ -78,7 +78,6 @@ class Editor : public QObject void setMapEditingButtonsEnabled(bool enabled); void setConnectionsVisibility(bool visible); void updateDivingMapsVisibility(); - void displayDivingConnections(); void renderDivingConnections(); void addConnection(MapConnection* connection); void removeConnection(MapConnection* connection); @@ -185,13 +184,14 @@ public slots: void clearMapGrid(); void clearWildMonTables(); void updateBorderVisibility(); + void disconnectMapConnection(MapConnection *connection); QPoint getConnectionOrigin(MapConnection *connection); - void removeConnectionPixmap(MapConnection* connection); - void updateConnectionPixmap(ConnectionPixmapItem* connectionItem); - void displayConnection(MapConnection* connection); - void displayDivingConnection(MapConnection* connection); + void removeConnectionPixmap(MapConnection *connection); + void updateConnectionPixmap(ConnectionPixmapItem *connectionItem); + void displayConnection(MapConnection *connection); + void displayDivingConnection(MapConnection *connection); void setDivingMapName(QString mapName, QString direction); - void removeDivingMapPixmap(MapConnection* connection); + void removeDivingMapPixmap(MapConnection *connection); void updateEncounterFields(EncounterFields newFields); QString getMovementPermissionText(uint16_t collision, uint16_t elevation); QString getMetatileDisplayMessage(uint16_t metatileId); @@ -207,7 +207,7 @@ private slots: void setStraightPathCursorMode(QGraphicsSceneMouseEvent *event); void mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item); void mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixmapItem *item); - void setSelectedConnectionItem(ConnectionPixmapItem* connectionItem); + void setSelectedConnectionItem(ConnectionPixmapItem *connectionItem); void onHoveredMovementPermissionChanged(uint16_t, uint16_t); void onHoveredMovementPermissionCleared(); void onHoveredMetatileSelectionChanged(uint16_t); @@ -219,7 +219,6 @@ private slots: void onSelectedMetatilesChanged(); void onWheelZoom(int); void onToggleGridClicked(bool); - void onMapConnectionDoubleClicked(MapConnection*); signals: void objectsChanged(); diff --git a/include/ui/connectionslistitem.h b/include/ui/connectionslistitem.h index 18c3434c8..bbe0f2d31 100644 --- a/include/ui/connectionslistitem.h +++ b/include/ui/connectionslistitem.h @@ -42,8 +42,8 @@ class ConnectionsListItem : public QFrame void openMapClicked(MapConnection*); private slots: - void on_comboBox_Direction_currentTextChanged(const QString &direction); - void on_comboBox_Map_currentTextChanged(const QString &mapName); + void on_comboBox_Direction_currentTextChanged(QString direction); + void on_comboBox_Map_currentTextChanged(QString mapName); void on_spinBox_Offset_valueChanged(int offset); void on_button_Delete_clicked(); void on_button_OpenMap_clicked(); diff --git a/include/ui/mapimageexporter.h b/include/ui/mapimageexporter.h index 6d8ae643d..b9cc20bda 100644 --- a/include/ui/mapimageexporter.h +++ b/include/ui/mapimageexporter.h @@ -50,9 +50,10 @@ class MapImageExporter : public QDialog ImageExporterMode mode = ImageExporterMode::Normal; void updatePreview(); + void updateShowBorderState(); void saveImage(); QPixmap getStitchedImage(QProgressDialog *progress, bool includeBorder); - QPixmap getFormattedMapPixmap(Map *map, bool ignoreBorder); + QPixmap getFormattedMapPixmap(Map *map, bool ignoreBorder = false); bool historyItemAppliesToFrame(const QUndoCommand *command); private slots: diff --git a/src/core/map.cpp b/src/core/map.cpp index 91e196fe5..86df7947c 100644 --- a/src/core/map.cpp +++ b/src/core/map.cpp @@ -537,12 +537,12 @@ void Map::deleteConnections() { } QList Map::getConnections() const { - return connections; + return this->connections; } -bool Map::addConnection(MapConnection *connection) { +void Map::addConnection(MapConnection *connection) { if (!connection || this->connections.contains(connection)) - return false; + return; // Maps should only have one Dive/Emerge connection at a time. // (Users can technically have more by editing their data manually, but we will only display one at a time) @@ -550,9 +550,8 @@ bool Map::addConnection(MapConnection *connection) { if (MapConnection::isDiving(connection->direction())) { for (auto i : this->connections) { if (i->direction() == connection->direction()) { - this->ownedConnections.insert(connection); - connection->setParentMap(this, false); - return true; + trackConnection(connection); + return; } } } @@ -560,33 +559,41 @@ bool Map::addConnection(MapConnection *connection) { loadConnection(connection); modify(); emit connectionAdded(connection); - return true; + return; } void Map::loadConnection(MapConnection *connection) { if (!connection) return; - this->connections.append(connection); - this->ownedConnections.insert(connection); + + if (!this->connections.contains(connection)) + this->connections.append(connection); + + trackConnection(connection); +} + +void Map::trackConnection(MapConnection *connection) { connection->setParentMap(this, false); + + if (!this->ownedConnections.contains(connection)) { + this->ownedConnections.insert(connection); + connect(connection, &MapConnection::parentMapChanged, [=](Map *, Map *after) { + if (after != this && after != nullptr) { + // MapConnection's parent has been reassigned, it's no longer our responsibility + this->ownedConnections.remove(connection); + QObject::disconnect(connection, &MapConnection::parentMapChanged, this, nullptr); + } + }); + } } -// connection should not be deleted here, a pointer to it is allowed to persist in the edit history -bool Map::removeConnection(MapConnection *connection) { +// We retain ownership of this MapConnection until it's assigned to a new parent map. +void Map::removeConnection(MapConnection *connection) { if (!this->connections.removeOne(connection)) - return false; + return; + connection->setParentMap(nullptr, false); modify(); emit connectionRemoved(connection); - return true; -} - -// Same as Map::removeConnection but caller takes ownership of connection. -bool Map::takeConnection(MapConnection *connection) { - if (!this->removeConnection(connection)) - return false; - connection->setParentMap(nullptr, false); - this->ownedConnections.remove(connection); - return true; } void Map::modify() { diff --git a/src/core/mapconnection.cpp b/src/core/mapconnection.cpp index 022158a02..b80b8d097 100644 --- a/src/core/mapconnection.cpp +++ b/src/core/mapconnection.cpp @@ -79,7 +79,7 @@ void MapConnection::setParentMap(Map* map, bool mirror) { } if (m_parentMap) - m_parentMap->takeConnection(this); + m_parentMap->removeConnection(this); auto before = m_parentMap; m_parentMap = map; diff --git a/src/editor.cpp b/src/editor.cpp index de1caa9a8..586765f4b 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -733,7 +733,15 @@ void Editor::updateEncounterFields(EncounterFields newFields) { project->wildMonFields = newFields; } -void Editor::displayConnection(MapConnection* connection) { +void Editor::disconnectMapConnection(MapConnection *connection) { + // Disconnect MapConnection's signals used by the display. + // It'd be nice if we could just 'connection->disconnect(this)' but that doesn't account for lambda functions. + QObject::disconnect(connection, &MapConnection::targetMapNameChanged, nullptr, nullptr); + QObject::disconnect(connection, &MapConnection::directionChanged, nullptr, nullptr); + QObject::disconnect(connection, &MapConnection::offsetChanged, nullptr, nullptr); +} + +void Editor::displayConnection(MapConnection *connection) { if (!connection) return; @@ -752,15 +760,9 @@ void Editor::displayConnection(MapConnection* connection) { ConnectionsListItem *listItem = new ConnectionsListItem(ui->scrollAreaContents_ConnectionsList, pixmapItem->connection, project->mapNames); ui->layout_ConnectionsList->insertWidget(ui->layout_ConnectionsList->count() - 1, listItem); // Insert above the vertical spacer - // It's possible for a map connection to be displayed repeatedly if it's being - // updated by mirroring and the target map is changing to/from the current map. - QObject::disconnect(connection, &MapConnection::targetMapNameChanged, nullptr, nullptr); - QObject::disconnect(connection, &MapConnection::directionChanged, nullptr, nullptr); - QObject::disconnect(connection, &MapConnection::offsetChanged, nullptr, nullptr); - // Double clicking the pixmap or clicking the list item's map button opens the connected map - connect(listItem, &ConnectionsListItem::openMapClicked, this, &Editor::onMapConnectionDoubleClicked); - connect(pixmapItem, &ConnectionPixmapItem::connectionItemDoubleClicked, this, &Editor::onMapConnectionDoubleClicked); + connect(listItem, &ConnectionsListItem::openMapClicked, this, &Editor::openConnectedMap); + connect(pixmapItem, &ConnectionPixmapItem::connectionItemDoubleClicked, this, &Editor::openConnectedMap); // Sync the selection highlight between the list UI and the pixmap connect(pixmapItem, &ConnectionPixmapItem::selectionChanged, [=](bool selected) { @@ -803,7 +805,7 @@ void Editor::displayConnection(MapConnection* connection) { } } -void Editor::addConnection(MapConnection* connection) { +void Editor::addConnection(MapConnection *connection) { if (!connection) return; @@ -814,7 +816,7 @@ void Editor::addConnection(MapConnection* connection) { this->map->editHistory.push(new MapConnectionAdd(this->map, connection)); } -void Editor::removeConnection(MapConnection* connection) { +void Editor::removeConnection(MapConnection *connection) { if (!connection) return; this->map->editHistory.push(new MapConnectionRemove(this->map, connection)); @@ -825,10 +827,12 @@ void Editor::removeSelectedConnection() { removeConnection(selected_connection_item->connection); } -void Editor::removeConnectionPixmap(MapConnection* connection) { +void Editor::removeConnectionPixmap(MapConnection *connection) { if (!connection) return; + disconnectMapConnection(connection); + if (MapConnection::isDiving(connection->direction())) { removeDivingMapPixmap(connection); return; @@ -857,15 +861,7 @@ void Editor::removeConnectionPixmap(MapConnection* connection) { delete pixmapItem; } -void Editor::displayDivingConnections() { - if (!this->map) - return; - - for (auto connection : this->map->getConnections()) - displayDivingConnection(connection); -} - -void Editor::displayDivingConnection(MapConnection* connection) { +void Editor::displayDivingConnection(MapConnection *connection) { if (!connection) return; @@ -994,7 +990,7 @@ QPoint Editor::getConnectionOrigin(MapConnection *connection) { return QPoint(x * 16, y * 16); } -void Editor::updateConnectionPixmap(ConnectionPixmapItem* pixmapItem) { +void Editor::updateConnectionPixmap(ConnectionPixmapItem *pixmapItem) { if (!pixmapItem) return; @@ -1004,7 +1000,7 @@ void Editor::updateConnectionPixmap(ConnectionPixmapItem* pixmapItem) { maskNonVisibleConnectionTiles(); } -void Editor::setSelectedConnectionItem(ConnectionPixmapItem* pixmapItem) { +void Editor::setSelectedConnectionItem(ConnectionPixmapItem *pixmapItem) { if (!pixmapItem || pixmapItem == selected_connection_item) return; @@ -1025,14 +1021,9 @@ void Editor::setSelectedConnection(MapConnection *connection) { } } -void Editor::onMapConnectionDoubleClicked(MapConnection* connection) { - if (connection) - emit openConnectedMap(connection); -} - void Editor::onBorderMetatilesChanged() { displayMapBorder(); - updateBorderVisibility(); // TODO: Why do we need to call this here + updateBorderVisibility(); } void Editor::onHoveredMovementPermissionChanged(uint16_t collision, uint16_t elevation) { @@ -1214,12 +1205,8 @@ bool Editor::setMap(QString map_name) { if (map) { map->pruneEditHistory(); map->disconnect(this); - for (auto connection : map->getConnections()) { - // Disconnect signals used by the display - QObject::disconnect(connection, &MapConnection::targetMapNameChanged, nullptr, nullptr); - QObject::disconnect(connection, &MapConnection::directionChanged, nullptr, nullptr); - QObject::disconnect(connection, &MapConnection::offsetChanged, nullptr, nullptr); - } + for (auto connection : map->getConnections()) + disconnectMapConnection(connection); } if (project) { diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index cc2b5f7f6..1d60c9ad2 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1892,7 +1892,7 @@ void MainWindow::on_mainTabBar_tabBarClicked(int index) } else if (index == MainTab::Connections) { editor->setEditingConnections(); // Stop the Dive/Emerge combo boxes from getting the initial focus - ui->graphicsView_Map->setFocus(); + ui->graphicsView_Connections->setFocus(); } if (index != MainTab::WildPokemon) { if (editor->project && editor->project->wildEncountersLoaded) @@ -2542,6 +2542,8 @@ void MainWindow::clickToolButtonFromEditMode(QString editMode) { } void MainWindow::onOpenConnectedMap(MapConnection *connection) { + if (!connection) + return; if (userSetMap(connection->targetMapName(), true)) editor->setSelectedConnection(connection->findMirror()); } diff --git a/src/ui/connectionslistitem.cpp b/src/ui/connectionslistitem.cpp index 337623b42..a5b8759a3 100644 --- a/src/ui/connectionslistitem.cpp +++ b/src/ui/connectionslistitem.cpp @@ -75,13 +75,13 @@ void ConnectionsListItem::mousePressEvent(QMouseEvent *) { this->setSelected(true); } -void ConnectionsListItem::on_comboBox_Direction_currentTextChanged(const QString &direction) { +void ConnectionsListItem::on_comboBox_Direction_currentTextChanged(QString direction) { this->setSelected(true); if (this->map) this->map->editHistory.push(new MapConnectionChangeDirection(this->connection, direction)); } -void ConnectionsListItem::on_comboBox_Map_currentTextChanged(const QString &mapName) { +void ConnectionsListItem::on_comboBox_Map_currentTextChanged(QString mapName) { this->setSelected(true); if (this->map && ui->comboBox_Map->findText(mapName) >= 0) this->map->editHistory.push(new MapConnectionChangeMap(this->connection, mapName)); diff --git a/src/ui/mapimageexporter.cpp b/src/ui/mapimageexporter.cpp index b61d3738c..65811474c 100644 --- a/src/ui/mapimageexporter.cpp +++ b/src/ui/mapimageexporter.cpp @@ -33,7 +33,7 @@ MapImageExporter::MapImageExporter(QWidget *parent_, Editor *editor_, ImageExpor this->editor = editor_; this->mode = mode; this->setWindowTitle(getTitle(this->mode)); - this->ui->groupBox_Connections->setVisible(this->mode == ImageExporterMode::Normal); + this->ui->groupBox_Connections->setVisible(this->mode != ImageExporterMode::Stitch); this->ui->groupBox_Timelapse->setVisible(this->mode == ImageExporterMode::Timelapse); this->ui->comboBox_MapSelection->addItems(editor->project->mapNames); @@ -144,7 +144,7 @@ void MapImageExporter::saveImage() { this->map->editHistory.redo(); } progress.setValue(progress.maximum() - i); - QPixmap pixmap = this->getFormattedMapPixmap(this->map, !this->showBorder); + QPixmap pixmap = this->getFormattedMapPixmap(this->map); if (pixmap.width() < maxWidth || pixmap.height() < maxHeight) { QPixmap pixmap2 = QPixmap(maxWidth, maxHeight); QPainter painter(&pixmap2); @@ -167,7 +167,7 @@ void MapImageExporter::saveImage() { } } // The latest map state is the last animated frame. - QPixmap pixmap = this->getFormattedMapPixmap(this->map, !this->showBorder); + QPixmap pixmap = this->getFormattedMapPixmap(this->map); timelapseImg.addFrame(pixmap.toImage()); timelapseImg.save(filepath); progress.close(); @@ -178,6 +178,9 @@ void MapImageExporter::saveImage() { } bool MapImageExporter::historyItemAppliesToFrame(const QUndoCommand *command) { + if (command->isObsolete()) + return false; + switch (command->id() & 0xFF) { case CommandId::ID_PaintMetatile: case CommandId::ID_BucketFillMetatile: @@ -249,7 +252,9 @@ QPixmap MapImageExporter::getStitchedImage(QProgressDialog *progress, bool inclu int x = cur.x; int y = cur.y; int offset = connection->offset(); - Map *connectionMap = this->editor->project->loadMap(connection->targetMapName()); + Map *connectionMap = connection->targetMap(); + if (!connectionMap) + continue; if (direction == "up") { x += offset; y -= connectionMap->getHeight(); @@ -318,7 +323,7 @@ QPixmap MapImageExporter::getStitchedImage(QProgressDialog *progress, bool inclu pixelX -= STITCH_MODE_BORDER_DISTANCE * 16; pixelY -= STITCH_MODE_BORDER_DISTANCE * 16; } - QPixmap pixmap = this->getFormattedMapPixmap(map.map, false); + QPixmap pixmap = this->getFormattedMapPixmap(map.map); painter.drawPixmap(pixelX, pixelY, pixmap); } @@ -353,7 +358,7 @@ void MapImageExporter::updatePreview() { scene = nullptr; } - preview = getFormattedMapPixmap(this->map, false); + preview = getFormattedMapPixmap(this->map); scene = new QGraphicsScene; scene->addPixmap(preview); this->scene->setSceneRect(this->scene->itemsBoundingRect()); @@ -381,8 +386,7 @@ QPixmap MapImageExporter::getFormattedMapPixmap(Map *map, bool ignoreBorder) { // draw map border // note: this will break when allowing map to be selected from drop down maybe int borderHeight = 0, borderWidth = 0; - bool forceDrawBorder = showUpConnections || showDownConnections || showLeftConnections || showRightConnections; - if (!ignoreBorder && (showBorder || forceDrawBorder)) { + if (!ignoreBorder && this->showBorder) { int borderDistance = this->mode ? STITCH_MODE_BORDER_DISTANCE : BORDER_DISTANCE; map->renderBorder(); int borderHorzDist = editor->getBorderDrawDistance(map->getBorderWidth()); @@ -401,10 +405,9 @@ QPixmap MapImageExporter::getFormattedMapPixmap(Map *map, bool ignoreBorder) { pixmap = newPixmap; } - if (!this->mode) { + if (!ignoreBorder && (this->showUpConnections || this->showDownConnections || this->showLeftConnections || this->showRightConnections)) { // if showing connections, draw on outside of image QPainter connectionPainter(&pixmap); - // TODO: Is this still the most sensible way to do this (esp. rendering pixmap) for (auto connectionItem : editor->connection_items) { const QString direction = connectionItem->connection->direction(); if ((showUpConnections && direction == "up") @@ -421,7 +424,7 @@ QPixmap MapImageExporter::getFormattedMapPixmap(Map *map, bool ignoreBorder) { QPainter eventPainter(&pixmap); QList events = map->getAllEvents(); int pixelOffset = 0; - if (!ignoreBorder && showBorder) { + if (!ignoreBorder && this->showBorder) { pixelOffset = this->mode == ImageExporterMode::Normal ? BORDER_DISTANCE * 16 : STITCH_MODE_BORDER_DISTANCE * 16; } for (Event *event : events) { @@ -459,6 +462,18 @@ QPixmap MapImageExporter::getFormattedMapPixmap(Map *map, bool ignoreBorder) { return pixmap; } +void MapImageExporter::updateShowBorderState() { + // If any of the Connections settings are enabled then this setting is locked (it's implicitly enabled) + const QSignalBlocker blocker(ui->checkBox_Border); + if (showUpConnections || showDownConnections || showLeftConnections || showRightConnections) { + ui->checkBox_Border->setChecked(true); + ui->checkBox_Border->setDisabled(true); + showBorder = true; + } else { + ui->checkBox_Border->setDisabled(false); + } +} + void MapImageExporter::on_checkBox_Elevation_stateChanged(int state) { showCollision = (state == Qt::Checked); updatePreview(); @@ -501,21 +516,25 @@ void MapImageExporter::on_checkBox_HealSpots_stateChanged(int state) { void MapImageExporter::on_checkBox_ConnectionUp_stateChanged(int state) { showUpConnections = (state == Qt::Checked); + updateShowBorderState(); updatePreview(); } void MapImageExporter::on_checkBox_ConnectionDown_stateChanged(int state) { showDownConnections = (state == Qt::Checked); + updateShowBorderState(); updatePreview(); } void MapImageExporter::on_checkBox_ConnectionLeft_stateChanged(int state) { showLeftConnections = (state == Qt::Checked); + updateShowBorderState(); updatePreview(); } void MapImageExporter::on_checkBox_ConnectionRight_stateChanged(int state) { showRightConnections = (state == Qt::Checked); + updateShowBorderState(); updatePreview(); } From 9927d66389541d69845e85860b947b32727e5ff7 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Tue, 20 Aug 2024 14:47:02 -0400 Subject: [PATCH 29/30] Update changelog and manual --- CHANGELOG.md | 10 +++++++++ docsrc/manual/editing-map-connections.rst | 21 +++++++++++------- .../add-connection-button.png | Bin 890 -> 10387 bytes .../map-connections.png | Bin 116336 -> 441334 bytes .../open-connection-button.png | Bin 0 -> 5606 bytes 5 files changed, 23 insertions(+), 8 deletions(-) create mode 100644 docsrc/manual/images/editing-map-connections/open-connection-button.png diff --git a/CHANGELOG.md b/CHANGELOG.md index 90ea613c2..62f525078 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,10 +8,14 @@ The **"Breaking Changes"** listed below are changes that have been made in the d ## [Unreleased] ### Added +- Redesigned the Connections tab, adding a number of new features including the option to open or display diving maps and a list UI for easier edit access. - Add a `Close Project` option - An alert will be displayed when attempting to open a seemingly invalid project. ### Changed +- Edits to map connections now have Undo/Redo and can be viewed in exported timelapses. +- Changes to the "Mirror to Connecting Maps" setting will now be saved between sessions. +- A notice will be displayed when attempting to open the "Dyamic" map, rather than nothing happening. - The base game version is now auto-detected if the project name contains only one of "emerald", "firered/leafgreen", or "ruby/sapphire". - It's now possible to cancel quitting if there are unsaved changes in sub-windows. @@ -25,6 +29,12 @@ The **"Breaking Changes"** listed below are changes that have been made in the d - Fix `About porymap` opening a new window each time it's activated. - Fix the `Edit History` window not raising to the front when reactivated. - New maps are now always inserted in map dropdowns at the correct position, rather than at the bottom of the list until the project is reloaded. +- Fix changes to map connections not marking connected maps as unsaved. +- Fix numerous issues related to connecting a map to itself. +- Fix incorrect map connections getting selected when opening a map by double-clicking a map connection. +- Fix a visual issue when quickly dragging map connections around. +- Fix map connections rendering incorrectly if their direction name was unknown. +- Fix map connections rendering incorrectly if their dimensions were smaller than the border draw distance. ## [5.4.1] - 2024-03-21 ### Fixed diff --git a/docsrc/manual/editing-map-connections.rst b/docsrc/manual/editing-map-connections.rst index 88194cee8..46af01208 100644 --- a/docsrc/manual/editing-map-connections.rst +++ b/docsrc/manual/editing-map-connections.rst @@ -2,35 +2,40 @@ Editing Map Connections *********************** -Maps can be connected together so that the player can seamlessly walk between them. These connections can be edited in the Connections tab. +Maps can be connected together so that the player can seamlessly walk between them. These connections can be edited in the Connections tab. .. figure:: images/editing-map-connections/map-connections.png :alt: Map Connections View Map Connections View -A connection has a direction, offset, and destination map. To add new connection, press the plus button |add-connection-button|. To delete a connection, select it and press the delete button |remove-connection-button|. +A connection has a direction, offset, and destination map. To add a new connection, press the |add-connection-button| button. To delete a connection you can either press the |remove-connection-button| button on its entry in the list, or select the connection and press the delete key. + +The |open-connection-button| button will open the destination map. You may also open the destination map by double-clicking the connection itself (this can be done from the ``Map`` and ``Events`` tabs as well). .. |add-connection-button| image:: images/editing-map-connections/add-connection-button.png + :height: 24 .. |remove-connection-button| image:: images/editing-map-connections/remove-connection-button.png + :height: 24 + +.. |open-connection-button| + image:: images/editing-map-connections/open-connection-button.png + :height: 24 To change the connection's vertical or horizontal offset, it's easiest to click and drag the connection to the desired offset. Dive & Emerge Warps ------------------- -Dive & emerge warps are used for the HM move Dive. They don't have offsets or directions--only a destination map. To add a dive or emerge warp, simply add a value in the Dive Map and/or Emerge Map dropdown menus. +Dive & emerge warps are used for the HM move Dive. They don't have offsets or directions--only a destination map. To add a dive or emerge warp, simply add a value in the Dive Map and/or Emerge Map dropdown menus. + +You can select the ``Show Emerge/Dive Maps`` checkbox to view your connected dive/emerge maps overlaid on the current map. The slider will change the opacity of this overlay. If you have both an emerge and a dive map connected you will see two sliders; the top slider is for the emerge map's opacity, and the bottom slider is for the dive map's opacity. Mirror Connections ------------------ An extremely useful feature is the *Mirror to Connecting Maps* checkbox in the top-right corner. Connections are one-way, which means that you must keep the two connections in sync between the two maps. For example, Petalburg City has a west connection to Route 104, and Route 104 has an east connection to Petalburg City. If *Mirror to Connecting Maps* is enabled, then Porymap will automatically update both sides of the connection. Be sure to *File -> Save All* (``Ctrl+Shift+S``) when saving, since you will need to save both maps' connections. - -Follow Connections ------------------- - -Double-clicking on a connection will open the destination map. This is very useful for navigating through your maps, similar to double-clicking on :ref:`Warp Events `. diff --git a/docsrc/manual/images/editing-map-connections/add-connection-button.png b/docsrc/manual/images/editing-map-connections/add-connection-button.png index a0419ed3ee43471f526469623dabcf6ec4997ac9..fe897bc6c9956b94deb803b8bdeb0922497055d8 100644 GIT binary patch literal 10387 zcmZX)1ymeM&^EldySuwf2<{r(HMjMuXP|$RWu9{qhk`F&3nyff7NyGt$XFW>;78y!~O^W zL^z5YS+Dv5;1cS!l`#RZRC7U0ohZH67e^Xyu4V+V{SsL_x zS$Q*(${kL20*Dq;lsePo5D$by{P@gA=}Za;H7xs>n@AU|5UL8P$bpPrpBcl2eZsoU z4I?vPzhw$ZQ3?r?v}ouf0F(`EneMrAg2+-`22jOoMB%?9)T4!u?}@)6djXZkfCCj; z3Dr|w*U6V?`8HI-izhJ{T04|@#pFSfDWiE00cqO-@=DD>PgM1VGGAw%7-lQo)%ud~ z;S9uw9Cj8?#Cq5rTgaLf!+zz5sk(cLCp2O?@+tyjK%m<96OhxuV}fGnVj_lwcRo-I z9*MI`h>&i;tdF6;(BSeWgW}B^LK%}-V8jmW%bKZJ&dszIFtAT69RJ~@0h~aVUKW96 zKaNK&DXtadtDJ;GBy4`&kwAveXGfLRKVTa6#s@pqN5O$eG{P*ynS-}Ch*w7$&Py3j zhF5|gt+-pa3qBMb+mTD64BOth3J%8cGLaHAc~*JW`AW}5ZaLuJPA}j+Kx(^X5k7Q7 zo3Kp%0PZn+y4o;R--(7&H3a5R@)&R>3kmCCKsi8Biju=aDv*C=K~aFq6rGsUUq=dH z@D>LUMTo&}K(tegUPMTG#iI+GiBa4mVWP=O_rnbMc#)GGb;nraC<`R8o{y%-4?rqY z><2m}pajV87KKtZ&;-({P~F?OqsDw7;?Z4K<}W#_i^EqyrVPW7h?r|7Jqz*K#JD(w z%ceSu^FjXoXEg63WkSqTvQ_DTdL@sR9`g;I4@&`%%if<*a5B|3j@lAv`1t~`Li8Bk z7ir@a+)000Z z2>^?0wF`P{>^naEzgjO8)0dG0Wf(LpeW$^jq`(^nz>UW`u%vdg-U#&v*gZ}or*>kq z9u7h!knvd!7(}tsUS%vD_XEchLIfSTKZG6~F6pO+j+L-MsVO_u2rQB)0zK65&o6bP zcCgDoSnKeJq5psoa-gk#N==~FgtR+V1B38DXdO^c@WBb_gyJ$l460sYuoN+dM=uf>S{&(xj9^1GYO@Q3VUCQX41ZMfCacObU|xf@Dvl2b_|&4zTPH@}O}kA``?i#ONtBFx}DP(8qo_mPTL1$x?Ghq)C3fKc&IqifoA3 z?Tzhy>9sV4yW{}pOHv*t*~zVaqsPonkzu5$raGm_CI3v}mMBcmz(l~n$M}`Lm>wZD zDuprCory%dt?)*{Ca_AHht4OdXu#k~;fnLh-G%Cb^LwS_gx3ioy`&klv8+ z5W$ep5Rrw21(pTcZsZW;?!%C6DjI#hx_{YoVue^!0jwIGdhty0Ozw>3k^K=7VXURt zby4xem9@Ohheq{AxJEQaAdU}C8ltvE-lx=0xkEUq=@sUhu9^X}R(koZyj(fyIYJDpZ_S}nOavs}02yLN+OgR;EDur8BWrD)}+;|wi2C^H>)ofx}* z&VI3elzuvUDEk2Wyj#puza{O)_2ZbS%jwO-l%tdR?={zQ>E%RK*~RVRErxepq%~GW zA5|U0)@VDqygQ4yWxQgyVi-x>oMuS;G}fg>qyy4kd0ylnUtq&v3t%Zj++a(Qy-^6l z{KGQCDv{%fZt*8$ePf`dD`S-Kg{;1CykstpG>uG;2%GtBvzwJ)YHjmuLtx1#dnQvR zztG+(GL)Q^9F|ln=qo&p#Ej5pjPg`|Xg5>h@%Xr(UCZJ4A;8hZCea!^P`FmOtoA#} zLf2Z?)@wY;nEGV}Ekza&mf>Yy29tzi#MmsB75X+4fsEZaa2a_zc_<`El8& z(xVh@nr_xATDi0q%(mRJbeEW4PB!ltzRne3`=;{F`!&BMyms%qq5^XZD|p)*+Yr}xjwk-Cx5 z%=3oAdUs0{OFGN*an&KYQ9i~QbV~$f<&Qar?41(kOpF+Ad)|9BW2ac*(H^qsgV=Hs zd9;G&MoD^d0g1vRcZ0PQYO8<;yRt)zLCTu1G@jiTjt+d^1~%>|1@6Gt&dt+6T?Ea=#&2zK9JvK4gCq?M&a z$UCrJ={0(Bbm`Q!+DA?&xyg5>xyZAn@TF*``LXV&7~Q*_)Y=A+7-V%d+GifuD-K5v ze;szLy7&yP6z?po+qxV=U^>>~&`z!KZued~x=tNS&7N18lbr|F#Of^9joGbUx#iDa z&l}YumMwLQ1@t7LoPTurXt=o3VzX`;GHQ`6Vvk|>z3Btc_H&bz+b+*m^RvBj3!R7KyjOkh||9!^+}!Cd>Il!j`P8)yMYq*}|r&r97eJyT)^rrRBPDhxNIam=_DU z9}tH@``x9l{@cd)Khq@6!f#1 zzzu_~pmd&=+U$tl%MmZ%tjV0OUk2AXLbh-L6 zG21Y&GtX)m-?8RQ_1a&Zo$TnowzYQDmFxF3oBJ#P<*~m`wZha{>)w48^cr#$p!;SU zP-?pm4i`gX6N>T!-f`?-M$;wH<+n%WPvvO|b9rk`pDwJ*5>6JbeKCD0zO=oc_X*((388GxU=cwyt}8e^1azz+09Xj}NR}W#3Ti8(JHhm4 z$u5v@kvMlBzqdlxO``?gKL8|ua1GHej8Ld=>bpb7Uqh88Ps`DkFWw(4a%?nofI5l_{AP~!tS07;rWUN8_D=8G0Dzz;|9jWo z0%$_+X>aG?%I_&e`Hu$wd;hPPjgtHy6`-vUrH-NsxrC#O1^EY7ZdP_mVMKCrazPh! zOMW#;>HpyG--IZwfj}pIHZ~6r4^|H@R!0{rHV!^MJ~nnvHcn2KcMTR-F9)EBCyRqC z)xSpmKRc2Zu4XPaPCy$+2lBsmO-vo#fI^g%e~JF*_}5PhPn-W`a&Y}GtoH!f{*JJ5 zu(GrLkL`D;;9n`fijAj*osOi9y@iA8JBKhg2an)C`v1R?|7H9?NZtQMe&GDS!2dJw zA5f6(umArio_~||kMuoT!ia)w|C4!P#4IDCs`tqtwvklUcyA&9&dmEk_F;jFvg55NIK$%JuWH<7syyQ5$n}@>G@vpj0exv( zH+EH(NH|(mhVoxj5JfOizZuOvA}i~QHx$Kf1Yy<15j8U4bxAPdRl_88==ifZ9J>9l z!}#z`@KtmJ&g1X0?+o7_?{5~?U)@CdwKO#~$3@{V$RQ;I;n9Qe6hJr#6G*g5eHajw zqR8-K2TejRHQ9zM?u+}LMhD`8lIuly9T;ob8|Kh?)WydU?Lg>E`rP0wT3rnUw|;SUMkfs7`kU_! z9I6Rph%A0L##(+UQMP8dYM8Qveg-gE%xoPldH2V)O=a0YLpu>wn|C5!B~eUJRTcA@ zod;S3^ni2gnCFQgNzZC`=PjFqRjgP3@<$=R?|!D9KkWZVptLMy>8}{J`A06F*HpCn zJ;gdXq$^@xZ{h*}^%@fT-ExppStTO1sGDkm&pW}h2!?eX0HHgSoVXEszGF2XXiCcl zdj5UA;-G2nOG-crs0xRhv;Hbda zQoAz<5}O+fX&v*oTXhVB{OPwWprNSfk9*5lTlBdFKyMizX110lMF6}j_c$v`CL6i#&H4;ZhZI^eV7G*23 z(oX{Ho=5c^tq_U2p;aw5z!VAPn15sX73x6coMv(T&_XDQc7CD~CRL7s|NVrW{od8O zEBc+;RMlG%V~WTAM?DKOS*4lNgkW#Y1NyX#50_kFkuJi4Jp1n#`;!m2^{-X1@-IZw zMWcH1Lo0HSD7YX7^^%K1dPtX~RuYe<<_HlvUctEK9a)YkK25^W+JKqW-MI^{#hYn76Ni0O--$)f*SH=?jd~weX=YOitqEM~?x@i0kS0|!eYABEnwfK)X4HxR z)~|S@1IJbtY+nsyXIe+;XIp;v(%4?qq`NuVfNetQv{EAoPC7iv8W^DKWg7a{(xDF~ z3M4vE+^NVhL3^j$X|$qC9f}vkbX|mFgUE*AQNhJdjPTx(kQ&V*xIM3JP0h(6xLfDL zR>m1tbb?hCKOSoDOuY)Z$*cy0=fqxS)ov>OfRy9VjVB#Kf72722;b5YdD|0=?HYZx zJuiSKU7Jr_VX#M{_*>|LUYw4YQlg{N4bE_MmoedYcyH<@d8D(?Z8vKO(UAH0cm8S6 zdeWlV#qhGoz8h20K%aY+g&x4C;e4kjfq8O=?H<=w`xUwPs_&oKUGt0Y;tKO~vWpQR zXDqlw?UJuT;Rjah1HEfB#GxBAyx@vKoWFzMWs{Kt&KcO1nkkeA`wk>1Mi6UasBcKTa2bSVv1O71uv!yo*SxZ-ct!36b$_t7}EW1u6bT>A^@ zr2sVdO-#=(eQPaEhEO*gufeIYYhsnIi488mP7pFbN)%ga!5-d^rVuzmIM1S50sV2) zkg5Dk078T56Qp@yNfo|D7UA9rV!VUl#qD9A5wCR>AlFa?gThuy6G5Io_GR+*b{QlT z8|fH&(F}#8dbKX;Is2XBTZrBtA;v~DFT)xV{-3r#&~IF7xj5v_0&5XK~P@%mXKfm+^%Ch&VCo9BScUI}Upc zSL(jhiou=wK^gqPy9`o>KR=!g|5WE`jwk314LliHV*P&6cv5ogxUuP=45}KoR~k#J zIvDc$yAbN?*bND#M8_m*nZnEU{f8ZE6Kgk`TR9W;g~;Fojbb6jw@VA}ev74HOq5#n z34z@E2Y%05FB86T7%}0!Xq@CiYz`P)G~5?pSh?MrB4=jy3t9|xdSKVIi(_;=61QuC z>S$qvrvRqOEf6pSOc;V9vwM-u?r5B8cQWE=0q}fu431PojF6nxh;>O)4*mvF8`CQkEdcd!MMN<@y{?7^=lQjfP<> z$G=f9nseAy3<~bpzQro1hc2*ca$e>xd`Niuwv%o;k?9!|--O7K*-d%KJ0}whw#(+~ zQfpYqQ&@_kXI5&cZmJbTAQ)7=02e`g9JexFyMJ(N*8aIf)DqD&A0eyVh#~}OR;*@! zqBnOgAM;Z4DY++rBRlS%cGKM-yUOC?t7~&P%c@gaAhoDW9Q^dyeg}*Uj!kpnD(}P1<0f>z1o6 z#MHWA94Ls39QBD7tpTko;i1AwNp>R;kck#?g-tVsjiRHLY`MoQo=}Jbri9H|zZJ{< zWum3Z1L`llu zPA;Yx?;Ci2_p8PDK1n^b!D!^xlf_=gu?xq!2hQ-a(SSgVBK>WqGQA<@ejB60T@K~@ zH2@I>Wfw*jdI#IFeN4S2YI<1NvSWOD#XDi}w5sK7`H#&&2+3Ddb6}Byf}bwS(g;jj zSnKjPj+K$HC(zyf%fSfKJ@YrVCts{fhmbne*2;TK&B0BcfDm;*f38P`h;9F03>4~- zUgyY`!z{4Y!%7sar_f=WL}Ud2-oZjMMB8lEJ~+Q5|TNK zZe7d$@L9^92!N`RsxXgSOM#3@O|?w zwO9%u(R(-i<@BdL5KT6mI$ zYWEdzIL)(YAa+ee(F*!yOhc>%mFC%S)?kxh7C+6VO;I>`uBG41@$&1lqM}^} zH~euc{GijxBSK7KuoM!8s;JjTf;qi=32EwQ+z5Mx=P-mu=ye1ml4wI8Smq5U^UAo* zUOKZX(L?9wB8~`IoSAjJ%(p=aSvC`)>MR6pvScTk24PK|JBFG20egBiuef1nDLgcj zwqIxs{L5JW>gzf;`|>-?v$=N37;g$u_1A-?>t|-Tk9ZL>w)Mm7=0SEIcvZ3U-#%f_xSzPzV7E( z7CvbHNU*ci9nh^pPD>k>Ci13`eJJ$iL;|Tke_Px?RhVB;{N0L%#pLzat5F7S{LyV;M(;=2?IXUHTK6s0A+4c}6*lo@#}}}>w=PH^%Cl_w zQPyc&XEqR2e+6IE{TcF5Z0Ede*PY?Ns?6pP8OgpS;OXC<#4G3FA+wb_ar$7trEfI( z@iRq?h3gOW)X~Z{e4a6y=9c6xPhW?nKy(Ij%|my>R1VgKpt%mY3XbMEZ1Rgsif$u90D{ge|<>R~Vs}N3`qfPB(_QeqU{i zelQtQt?YAGAFz%^s{jh~;l)fatSu$U2{eG}C`xU0Gi)6E41IIf!4${3(&$k087*LS zScCOV6ltoTKHZaxhxVT8^F8U|)ucuitTdT<^_K;R_3%BFPEEM11YzkTXZ$IH5a_qd zl(H){9*S7Z1eo@z-zK-x^(XubZWGd{kI)B(w5SJbqVnag(A3A|&}1{(R6|CwE5tHi z^zqg_OCNJ~);}WKX@0zr4bAqQ|Zlreewo}oKZl0|VK~P|S z3D!64>&0r`<@VpUtfHcnprjBf${8Yv`Gp+!aVw#NOM171r?$gIp&+db4P_^FY-W4VJ{#}7Xy;N z<-?+T3{`x;1F{sueMqaBuy!F!sfPL^&s(nEj*==d2_uZ7OKsz{LkuEuDn7!_GLL(> zSd)3m<(f1k+Y>SE<=Gzf=$9DPc$U60? zOnGjEqb$ow+B_bJ*kw$hLgr#hX+UZU3moh{Dkann7$+kuLE+;PwjfdRZ%(NdotT-` z(ECV5Pyi)6G`&~9aoMow9Nqvbh?V&6t>F7YE>!QF76`(>w!Eb&)km>d(3+L4FpN;h z_=@gG(eI*wkoC#W@uPG-mojpOXrzIRY?~zY;TZ)v6Qj1m&z)K5hJ@7nJ*PHbJI1~W zT}CJU=Prmv)vX3*MVRn7B}|o;trK*}T6YqNQUvR%Z*o9xCDG4tpGU>#+P7^Q+TU-u z58-B3Cak&4T(>%PMB{Ceop0128m~f2RtfH3T%~4|#CCPlP80fQohQsdM~{#>vje8c zQswaD=y`DfuT(2`Wp9K6`ozWtuB~8+-jXGU?3lz){h%cbb7VR$a&eNKpf^A-S2{<) zlj@G7trVT7rMSsGJTslItd{)=pBsFl@Xj1-e-m}TZbfDm*p4Q6iy)D0)fF*QBlA%H zmB|cGI+0B(#+_5|w4U<&WC90$-Kx`#z5-EAGno8Qi%BfXfRyxP7tx{v!;4p)Q#rLG ztHOQjrR{v;X^g^?hmR0a<3{bi=tJq%ofu#KkniMyLgvgV75J$D+FAbp%AJB9q+hKl943VeHRO)(Ku&I&mi^H(3<6fCJT z=7n4icuF=C4&9w}0p_c;FwWlCs8a7>l3hq!n}tZRqCLb>ZX|wha;)3qZ!i{2+vweT z_^Ad%FwsqoPd4T2F=A%81Ds5EzL9uTv+g&z#Qv@nw3eJny)h{Fx79XV*@3;`G}{>6 zahzCbN%&kOrlIAq-LXS% zh#0Wv_?DF5uiv4G5aFBNhGI47Vc3TJUTyUJ{8^|&T<^Jcv?^=U^7KP?!h?_!#5Vir z?~~eQO2M@#CWVOlfr_EE^V*-Q`5SC-N2Ef{VVSjMbXBoG(laTTvl#LZ;W51Eo7i#-pidW zCIF#fM)f%dPuJOhX6#4)6Z~h(%eU*CL@>X}@I;|URUI|VD?)SIKQulj1Uk}xQm=zk z0Mn3E%lF9w1`(4}XHLF1nTJH`XNpN7B?CO)C^9kK?J@YaC!M{2pLK=n8R9-dF5|h= zHDlbNXK_!c+Z6*66CyP=RW&;6Z}H+$)R^oY%~m#AefA<`L0La9+s5O-LsLr^FM6S9oxZ>AWPkwz%z7G^&7JOSK;ocGU2T{2+d&))egXu+= z&!@D!_E?`>OBTp<8E|)a!1B`YlOxoUR8G~o3fe%J<+N#fUw7Su?ikD9DLYGtG+%S9sC;aCT!oow>crq-)x?GEWXPEri=) ztd4NroM<55e+MEh@$6pI5C)bs!UiUwKOsJ@xY%WWeB4vbiceUz$No$oGToeL#+xRD z6xB~90OnLC{2w2kt;rOP~1qaj4BL)aqf#FPP5`W z3sW>;nfTzl`b6%a=Y;9Y`WdR8a}4-MSuvPF&fNySuOP~4aPnbPjon&I#ny*`Ass3! zZnb$}63UpeqG(3`<26O}CHyP+nQdTg^M~RGuOk;2 zmY1i7nEpz%Ve4Kp^l9NuiAN|L?HbPSY0(O-K)|qXNqBW({rj8WdZoKn9TUzh<6^W% zp^ek+>Ml_mUh5Cp#@zaw3cpWPTlwvM>?nv=jZ3U!Q3(ADK~TB z>~1(Hii?@f9!+YlB;d{P`=$Hm_ad>^PrEdbj|WBZ)}dK4PC0=q*C?$*@B>0RSE{^_ z#6ddHb=RGS0|KD3Qsa3ZS4`jw-eR$}r4~oBuM%8PThKdewMca2cUz+}+we}%EAfHT z&^J5D%4+AHusdsVNrp<+HZ}!NM&GAi*PX7ft_odVUr)|qc;A|{eYUrXoT1V$KO{gYyt(d?#}{#(1BiJkKqJBb4z#hnH^`7=HnAKTZP!B}Man zuMkkQ|9Sxw@Fnq#c^?4C{P2V4RTNcKRozjnB;C2A6`6ip*{39ne0O}~-9vwScz9n* z=TGn35Gb{Zuo|B~$J)-bc} z1Wny>tFNvu5x|a(jSX#NWW+1oKZQGirS(c@$ zYFW%iqftqcLZOfVz%6W6HT;^I4Zy`iD0D2C+o6tEVIS z?mh%dP%r|<55mweiF=+^7uE8VZoWGxWEEn=~EMYX5lLEoKAkB%JJa;}K$ zLg`o{st=UrX}isKs$~D+h4?36VW0x+Ha__uiY%ZEN;AB_lZP+0}ErY26NO z+PHKWt~wH1aR&+xQ>AkVSLgc(XqgpTC9x% zAvqDZJgEy&vKX=!+ShXcr=F8rgj4~y0LDP%=-N?wMfKW&_+UV)o-;RXv+o|=F31wZ z3XG2-GeyhiMT!Jc*ovmQw*KM7n87#`L=n>0vn7cTMc5V+35uur_PVwrZ7f8juJQT% z=9jVCt3Co5~CE0^M?7&k=2cVeb8lD-ld-C>NWd^9!^Y>C(emR z0dS7YG{w`rVSe*2^@J?TKN0`vp!@y)J?h#1k>1B2F6zdM+%) z6h+AopQ0$buIJQC1Y=Cs^_(>2{zEiPOQllDWU@rpilQir5({LI|$G-Q5W=xVyW{010lFyzlwXJ!^eA z|GKk!X7==M*I4B-SGu*k~DSOqEPe_4l#H^^T=fST@+l7T{` z3jIQ6B8`I$K&HnjKP(NmV+v%XH|c3axOu70$tjP5C8T%w2GQ!h?sKr_vj5t(+TwDs zo_>EY3XwxFh7(b%!Uf^{#cMld62d~&87X1*9l9vAx)GG^5>dpU2tPlRD8B!z+WK1H zymIC8kni*AtD$7(NP;7TXfAn?6IBM$U>Ib#J|Be>3B(tJVxG)+n$PlIRG<{tP|#~r zqdDH6GVgH0N)Os?n?R8lLFGu8*Y)E=6c28j?7Oh%kS010qJFFtMQA~+MGKqQ|M-I9 z<*GRDI#{atwPL#SSHdM)wl$^j(rGk?<}L+p0a=j5_pz+|fTW!OImJd-PgJ$VVqYgf zG^3^VT5Vz2ND9(@1}hUgQZ3vr5UO(30Hkz3U42LXh(;t!R*r835vba7n&UY5@Kxc< zQapyZcebk-0y2BK5CP4gX+Iq(SMTz73i+!Qq!K2Pz^HAFFLSCw2`9sPz~BM3a2(fZ zUCme0NjsziL9SmrDXbMp>1Som35TvKKwtMFBFnjPy(gt)Gd5xYPLvRf73zy_SkSOtlFwI zMD4C|k5$j8n%t^|hg1%ve^PY~B42GQHrn?-3hNb_utJZ* zA&Vl?LXY&=RFl}kt#mV2;}XGK=OAXlSoTOxqE-gCIaas^;pU*VLqj8c{)$fUQQ8%Q zvX7`nk_f}24<1p9;w#<&o1Rrd> zTsr#-bs|^wD(z@phIx{{B#KfVV%Z{Q!QhZbd=*O(qa|0zbVrXxAMbW3in@rE`M@5Y zB*AlcMuo)@Q5U|~7t{CLXJG<=$ySpsL2>lWR(3s~7Bl_3G(C9*4x6rD6>~;8bbU3T6vt zGiNQ1?T!fvVl2dddUp&OiU`~#!B zXO4D$vC!$$4jXY^`ZV+r(Zk0F_Xm9MWNMWe)r5l7679kktvZD|B{}gCZ3eM2(Xvk` zDVj9UrT|tzv@M7oBnEm1qOpUv3$V+&!94R@)~eq)iJrck**f}ue7ew5`Aasrgs?ol zpzULm!EGl=rDYzEibLo+bq9xcM;@oNSIl-aJ+YhPEU};ZhLng@K++5Mv)scoTqxWR zIEr95xFQtqcle?Hp{b!|C~<^0cvCUH(J)eF(TaFNmNsn9sY{~`qcfwzrhYrDrX`n} zJKQ^vSaJ!T2^0y>)VB(Bh3ADwg=O-(@{gm@qtq#5++|#Cri$DiJO}AjYz|xj4#w8; zRyBjU>$xkc1K-TGt+at&6Ok5sz(k;io!eNN)tP;!dB;@i8eD@@&DM(gl3t^voxUAx zBcYvu6qb}vG)`sj^M z);S=iW@i8=#*XN5c?uN21K9H%i`aj^%{fuhbCg(D!7<^L@QVqzbp$3^l9`FwP;X7I zzw%MfXLWQ{b&b1u&2_;w&Yi_WvBv14`gN^y@v(?Dq>Y)fV zCXJL*dDzR%B9T2~m%1Ldl zINfj7VJ7A*jzmXAZZ7@lHGfmKjK)pDJynnW9`t^M4pwbkX)ZlY=z5WJ&id3kOck*t zqNGhtq%Lo9?(~IIb2+qLSdq-~-2v=ETwCNy@2`E0i>v~lBCUK6OHa%4(Zj9BD~9`y z&!RovJ!PZSqhqPyy4+fKi+2_@7T^h$Vc9W0`dM@fL?tDj3Cee-D?lXTH*@_hRb=R5#m2%zSf`>r8T%WBJbaT_eel`QW?Zo!e;@Fo0Mu zt+U=P^`ur|Bw{3F#G(8`zozVCM{f1@IwUe`RC|obNFt^qo9MXq8I-iqr09Y@$;}7Vs4T4Ere$oYhqQNy2`37!;Ph{tCLQy zPg6-!RUpcM#n+m;q2`j~l=&L-0lI;xIJ7KU!Kn>Kn{%O5rz@wC`lPm^Z;JW?LYJ;9 zsTUjvL`0VS^uTLp6?y#bHUekCj=RVRsebDJkuJgpAyoo@as)1+&!oBHEzLAM2@ zt|F%ohc7kPYTHGY&>X@E!d1^E&jpvjy9J+MzTjYr#uO$IB%|sdM@JCt>xd9c_*ulu zkU8?It7E&LY0nd!pkix-l;6aGmz-&f&IyxHdY;Go>u`aGaa30W~e_@Yb6Kh%=DegF-x>I?1 z=Wy%vX^vN}<;`m=6Gke-O zzLkc65cK4KyR%gB5xnG|9-z+L+`LNo2t`8K!`%fN{Fd@LY`(Kd%mB$2N}X3c|ymV zNJvPq;VI|oQ8?F;ebz%s%9Wy%&_T&Xp!oc;4->KnPNEuVnnIaXBN7%7N#_n%Sw$>{ zNtqc3J)Yv7buLW8x9->URG~VKy1MkSbLuukupnCMO3Tam5?`;^!J}f#>gp=TrWDi% z(f`+^LaiJO<^Ekaa47)-@$3IvI)tG$s-yh3utZ`vn#faNFg#jrP7XwWf4>S7G6zi% zfK0hak$ASskaR4aX8;yg4;@+31Yaf)=6_8&(+JAlm7KGq;s2EBmfc)&=<3fB@^Rcp z(W-N--Qq)>Emnc9&}sOXK&^lf{J*yp2s2Iq^}c!{tm7{yHf5OC)sYQXE`hSS4u>w1TctfWO1D|idp|6Pvg z#BZJC^=7twdy`tXw$di)>m7V7u|O!HLpw&YzB@iAP|f~rBH$p$7=reHY(}wkitd17 zoYveHFy8(Di8=!tX83)zQkGyuo^;%HUj)`9IoIisAV{E*jdVK?gy_G|oBK$8vE z83kX`vg3CnR|%pBFy%Xi-V>F4sN7|OY~ z*2}dyIv`GYrhs8q2c!PzXE?IV!aQ+bA zz;#OUt!JX&qaiRR-vYh6Y~H3*J}EAQ;y?R+%L$UfykIZ_;?%c!fampF4SX;AAC{xu zTFQ@FkeRN6v$p=MW^GMZ-(VX@Dq^o#2~4m(<(bO~3ND9w6#JSpeq}W7|1CMW2u8g+_l%L&t@B)e%?RdS5uB8muR3tDMGfHk0iZGgG6CO=c{N7VzHB&&%}H?TfNm( z?y5B_)ZgKuP6g!;d-^71@I%_dGK}ooTKLUxoj|iJV*eor!HSf-IF9hsr%yS4cR6;a zJdu-2HI^d00?T}>I{c3jjc|>PD&45bj5}J=Zx5iW3!M%&ovSI(rop^W>gKbz0WU45 zEiM=abiB&6i~k+=bAf?|kdJi}!ZT$>+D}#q#qX=i#DH4L*t5H7`}4}$>a`o{=%;v! zNzY`VgfyX%7H2eX%Wg(a3Q{1HAY3v6|If(%9&da}qf+OM#bk1>5C8)T*I8?gb}PdS z5H9}<6ll?D)w(Pp|B-17(7Gmj;@>5M!MC&j8rHU>)780wfmpc6rI*_YnhA}#hfnbQ6h^QCfuQ0{Yf zZ7K9EE+#Qh?($qp1=yj_In&BoN73pcKLYg&(&Iy_jNVp110HJvO%T0=XiWP1>N4fL zn&Q7IUSo{#w7`zzsMkZ-*Ud6tKf~Ol`AQWjzwzS7{h(H(4Ildj{(??(e2ra7E4$o3M9|l!v_aqRxecQml=j@ zAfFmm66Ys_>ah zG{9}*hZkw3qt6Xp3=A0q7X;UWM}_hM(jsYYO*Ms02kagg6q^}T%~tM44Wro6^mrRpnGbTE{|9uzH$13zqh{fY z|54-rk<{&=RIsY0yNm%wRhec0qt~0@E&d^7=4R!M1wpkHG9OTNfpBozc|H)Yaq+-Y zzEUasKAYq`j1=kj^G+u2;bW)TJLFSbZ~<(iz~DtC{~u9@4b+u_EJTV+nY3E=G@rjf zx$ik!+G|9K*2CDEYoFy8FqVaZ^-4BADYP%)^jQZzj})yC-a6RZpNa?L4c*IgJ1Uj5UbzDU6GSi#iw@($1X;v zO4%hp47IRYEywYa7WVl*3Ee84Jg)8x{C+l-MZWeUjf1_>(=j>`q<9|St9erk(_hM@ zyiegZ@-lPvKg}s+K;0b8fPS?(4{LpX3V0>-5`k*y-;%D-xptgVBK%=rF+7ynf)Mm% zhvy=V#<+|q?`tZM)gDZuTK>FE6bDRg04^LS3%DNUfaN}YD(|6iU)}4~_SWIB?^xhc zFgLESFKwuDi6xn3@q4PN!QmE6ny0iVR~55+yjMb-~v^i6HZj7@$qI75*w$ z8;Li$a@mYpY4-m!hO`Qdj`k(A+<{K|z48ZHSC~_Z-S$U#xiOZ{?(8} zZ-dEYHnQ|#tj@mI70Fbs&;czk9C*%mh7Ldx?zceB3_v{+^-}2mV5Z}m|LI?tZVWk_ zjkAcP5OSJ{1$>)p7?)9+VSi;v1$A$flcbI)hu!%3LU707V!k4*nQDt{slVzGl>3yy zDBdFKOw)J$jp!z4*8N5tb9gg^E|{CHN2LAAjo{WXA9BA@V%`l5_SZZBmo%Zt%rQ?GLr%>t4zUKXhmfH4EO9k78 z!bX1%sh88yv}nkLy1@J?z-yTF0UAy>vjEdPq-xnu~~ zQ}*S?yGefev^#FcA2995xG6WDx0^I1$hSuGSS;Iy2T&W?@}eN*`JqX6_DYkcH~C>R z8Ks|L(m0MRDw4pSkEVQHXBuaq{NNBKN2c?<`C+`DrBF%y*1~)csvxY|@h6I})0K~& znfUHoD{N8VncbABZnDuSSU6s*#>J^f@WkiQYaaL9FqnqAivgo+ zAjW#a)H9iSU7}q2N-y)e4}8Ib=%F1~#Aa}v;4c)MydIdq0!Vc_rOaxg>qs` z?7@ZC`U#1VFw07zVss}{PRgWv_BQCw)pmk}ej>xD(Zp7t_g&ZH_6I#fH^nTN@eUL_ zhm#Nkp_L!TUtsq$<>2H}8{%mY8Jv^IE!1BvfWQi&3}KBmJ8WYJnd6g}wEkwjj+ala%( zt*%p$fJeZMYC^Ts`@HdbW?1ZUUxCNbE@0w?%9r*`M(d;{5fx7X7Zn|tbyRk7H923i zxO>Bn4Sug;9>`n@qap2cnj)z7oPPy#iuvUB3HQl2Nwp}bPJufc6pDYb(H|9MSBco^e{=U3|YK;0|B z)4|iThbd#Ram;!`P7SoARwFEGw}mg~f{drhUk+{$li5t4QBl;X7n2SgX-x;R%AF2* zwDT|XQFa;S5S@uwB<43I094?r3e)>N$`mAx zOIDlJ{6PJF!f*XFe>3V4(*7(tWo;UThMXSV^+lSGlFViESb^ga4WF>96I5BZrCt*n zC1E8GA5NSOw+BqhqM6aJSA1%vhWnc22S@sD-Ba&w3}=dQv8PVq#Uk2_BhgjJZRuQ; z-J(B{znRv@G>Ozk2lgKaaGs3^7jBJue}q_VbO)r0q)p*=2>FAgU)bO|zOD7wVzoS8 zPIPQ+?$R+;EEfkHC0ey@>o5eUkrM+D69;1+B^^3I^n1B(g zp6;%Y%tsn-Tc5}!1!wBYc$?y$wI=GIw{N@s`Hu5|%tn72iC9;+yoqUI>&?H^ik0t6 zAQ2Ka@3X>xje1Axmahs6&lXTqi@U%)BAt}JOF2Rv&(>cUXqOY4*!5>(i5ZxFI{&AM z^p>N}8AOY;`1rfEBFi>$zaI6anlz zh|2dgUFkP7j4DRa@IPaE^u8z0{Wzz(pL2|t_%Vq^ZBFTX;98LqsSxCzSe|c5A~C<^ zRPfj`*R;=Wp*ZKpZ;A)NZ4N`?UIAt;0e_J5Q!?`37|GF?aRUlr83u6v zbfhu(9^9GiIx~`RxlqNne6Jz)o)>67zR`uxA$=XD>n4Df9)X*M9|VN*h1k*oqchV( zK4yBXPnrJlX*QC-hi@A~rq?#RQ?CiWnyyea+%(j7H?DohDw1sc)ye<5Q@1i}jQ(g+ zp1ul~=L#!;ed3|?5xGb)y$L%wA@tC`Q{yxK65o~oCMPj7`pCX}sJY9Nr*Dc7QH%ym zfX|2vFFlm|1peaXm8c=`YTFd>YZ?%p`5K{ewYxMpbV`~Z($qCfurTHkXY&GSVT4rU zqV>lOGA&X7VE)x^ilh>SY(weP{Gkp@TyrQcxK1_cYDvefC?~aS5=Z(;$OHoUbowLF z{R3I-?sKv3)?DQR`k0PE4CsK*(lQ3~I}UD6PW5}PlZ>#31N=hC5U;RmuyWR7VdAE= zUSQG!D6cbWF1}Pe|MpFvq+l@%VKXzmckka$>fHCT!h=wD5+i}BVXb6|_FMUJkpgSP;ch#O^ z)E@^5-9yXqF98_I-k-E38a{wts!++mkEH$ewcN*Cwx7#%?+S^JZnTd2eMM-)5LB|b zHLn+LLcF9MFD5ab0M4KMCmNuwM{2-;pe~J>`ebOU3^y3j@NkjeuHA=Z0^E2 zwG0>*RMiWYLqlkXYZR15JzEcRXlP8XxCu$lF)za@2Cw+-+0!8*BPr|YU>$IkSKSKb zbq@R%_S60uW3^ABq9m{?QktzE8|ViWC86vmkE;&uDReM=H%xUGv8q=ShZDTj`mRr> zHA#E#+iC@#vxY-CS5-5q;7bt;>pg1Q-i;#0w8JIB(Rt16+&JL&TF13MJb$ZiPIZmi zYeQ3N-OsYJ_k@za^dsKms-5RW>56ZNyAQ3^Nl4r|9*tH-J8@9GT3Fz74#HwuxQNTl z0$%)Kg=0N$@~L4=lmn3ogXhV7MU6|5vq;q%L4@6gP#Ew#c?*;4t|G0`indO&d1{9- z{DVMyDbWf$a%SjQlcY0ty1CFvd~H_4jl2RuHr0uC(=Sl`ft5iJH)uZI119Q%cy>{R z-t^J_>7)&Oec5E(YhksXTl3<})xYW7iq6AS4ef0-)QedoxR6|iO2&Nxj(F?3d&Qdo`wWk?@$ zG5S=JcBg)^UjA6OI!w`DZ82kov*JjU<@j2cPr07OPLfb3IL~82a4BQ>n?2Os+QOh@ z5cK==%C0w^v*vhr4h`mxL1n6_NP%T=v9GC40DGrbM zXpIAl)Eq_Xr1_VM>h~zSfUJ;pv@Y8mX<+$k9ez{4SHD9Mf{^Y0CwaV8d?$*p2LW}^ z$keXAu5s+^d^=SDfz}QhCa+lDKJZnaP>l-)bK4%9l8)cyW0#`jE1_<9*%ig<#*Jn4 z@pH9x;&YqbhH-VtXjV77@ojaH{9$^KLR}aITP0+qB2j-)nStbMSjS07SsZkvVg@>g z-e%N>NccL|2j>%%)5Vm~D9({B9XBU`eKf3^Zg<@3y#5vhu&_JgxxQIW+FeoHh2zA0 zEASU)3HY&#Fv>^ho$Ca+X=_f*pK*Rn6B(RS3-b?!gzMTD$X5wF&gZS%bza}h%~W#` zJq0dnsLBKy(}1i=x$o>reYRnN5&GU{lsay5GgzNen;`K!D!@Diixi}&s58Pur+iR5 zERRqVzzNRe+lHT++A>6}+DZfW|1yZyQJjN;n!JZ15 z#mIebEN^P;k28pzi*x1NSRE0fmL-_?D0sKS{4?6X`av4b8!k(P(!z4*^5v3tu?1D> z9p0Xcp%0pm*RnEiryZ+F*v}qzO$#%Jk0WuGl;)*H(@CET@>%-7{2-<@xwn^{cQ5|K zvv4yC{*@&!2E8$9$y3b+kOHuEmOLN;MtZ}T<>$$7<0Ppvr$tI1BCQ&VnG6WHwP9=w zA$=a@g5$4pwK!`(YzetK!CNcRgKj09gKum2MKS3(YUA0I)utHST@=gvO9S=4*1?>? zDa;v11L%`}6Z4HnNBdtbJ`$*2|zKU{+lFyiC0iRimO;RyefU+|oZl=|4fT5{6O2z9llmz2y)Z zyC^n#8_X_&@MRH%zR>X8=T;HrYG*27>W2!q-04UQO49E7$-4J4hqLVR?K_OG$T8UgK30$laCzt82v)?A7!5eto zJ9bZVYa*W>I^mo+O$?xB7M#uNERPqfGbfpk{v0QbLSMKhkM0bHY6M9lPQ6h9(9*1B z<~)bo^K{770(ot8DY?JV3mcAu`c<>CuGTrOBX8rs=XO+S4`}cu+F8!aprn*98Qy+J zTQX?$8?=aB7^f0ooRBZl@TfsJftCc^zCOiCt3HwV=E4?}K?*oLek=k1(z!PB^H1Kl z8z|0yPx?a(&FY@Rqz6uLeeFR^lnmLn&2!D=Np+O)9J@-KAR(WT+DEQs6;*mdW?(=` zF=Ru_(92<++cf!37Zp$eIJYC3PLD)3{slhOX#ZDGkbwW;`#vZV(2XttHJI`sC;G zSl6H4lKD-hCW}BuR~UQu`6^R!+(L%R{%*UDXYUzfn-$T%T00hRlj3Y?}hv? z*MTzlCr-eV>O&UvsUMlru9F0QPoFiKtJD}~D>Odu82W`D6r7be8Yn`pJo-+X-1ePf zD{bGLq{(J8gMP5ova#*Sx_sNXA-YWcuJjRT_CE0ajdtR|1p_N`8mH9_Oz45 z_sc>UpM>c<{jV$IlD84ajy1GNc1N*0GM(*7a-+W5&<{ux1e0;51D8X}J?#{(hELZk z3sdVQ{&F_y91pp#w$@VJR>@2!7IHNUaEKbP)q+}CZ%U`pDk zklwCx5DC7Cpsy;EJFhV> zvzIOrlWy8GaYVZlI#Tk^(|d%eX3U{~eRtVX`KZ6}YBFR=h|1l}d2a0qPD1e=y5*zm zL=pb}j2`v*NX`;p3CsXJZ^wMl7t}h}(|Q`qu&3LUx);+=W3;7exca1?F#2hpur?hs zUb=m`E-Cg?3G_*935-c>jk3Z{arZx(IXspzNSAn#*QQaX82w#wYDsGVhR664H*qc| z73{FKD(>;$XSwxvCr<5XuZ*gQVKPH~vo|kds<6;?lP~GAgeAe(@fC->ys6_t@ z`aS?_k8Pp zM-vs2hl$=cgj!!C@*;(OwA`01E^gVrFe>g#F}eKTll&iU@yr2mp90p;jwY5{mv{O? zn#s#PnD*buf8ejZ!J)X4F3qNee2f)1pX5-Hlab&Yz~XD}I;v<5OlNhc;#NBUp^KX= zg672XtnQKDUMq)^YPo6DxWK=hI$ya^-%z>neS|`t)F9TKL}8(wgshWi6qz^UIna9R ztm9n7!2!=<^_xRq>qG00uc~>!7B`HaDx7K!$~*cRfFof76KH)dY5sOeEeK@=o#Mg8 zRYF|gR9&xjk3AWz>K*$;71f8=4OH*>?pWr7F%E~G%n9rI=nAm7lCkJQW%CaOInK6r zmBIN(`i`s9#K7nCHV`H)F~93%Ua}P_n?|=LHjHgmfs^2Vgv`>)FQ@gF#DxA3_atQ% zQXA|+cA~T2=Dgd|jNi~u+wl4rC)ArR7l|A)KiBM~S`!N(^_j{E#0}tlnCQM44H6z1 zIepK95B)tE#j+K0Ws1V+5&!l2(8OG5y1q6E4eUM`=E07D9bWd^okZ(MCN+j=#OLeq z&EkCWq;)uXH~$8<0?z&;Fe{o*Hj7OfGdRv!33_mxMad(3onUi*1>=i`oC zP}UJcUs?FGDbWeR;d~7{BWjZS!oz%N2FiqVOeC3++eTKWi9o34q*3V~`_SM<@UQ3B z#p^J+G)Ax1*^2IVt>k*quU#v@e{opa;62WO47Nnx#hEu)zB?r-dWUS6v4a=@YK|i) zx~An40vd_D*4_U8)oEN6#AI?1n>^Jz$-r1Nn#6_osH@M6V-h339y6y-UX%3v!H0Kz zB_V|S*%#JUgXQ({8E>IBnVD6aMy}yvUbZv(lqkPX_bg03QnM^)YOx-S;Ynm%27$3A z@Xy}KoJY^?v65EY1Xm%Lq~kuqnCjn99%G#e!L`soOYPj?zo|~!K=Ix-v0)Vy$$iX^wqN!o7Ec=*p4vz}g*~I`J zpxd)Em7W$Z3NzCVB59qrJ%VOut1R!~a)4;-Ck$M;8B6brcbl2Cn>Bg<+@NGbQ6C8| zkK*Cp)GsB|V7#Eg$GJ;(&{@PUO52%KhSA6UOqpZ}2^3Rc}IC>3JR1W>67HZyp-j&qM=pmu%(u zR^=tAM*1eq+7s?BEq&)T205Ew`(tBc;wwSD9|>a}15Vq1;s|ca_PFC)z8g87g-zex z5k4COQT#591YXL90-an=`w+a~z4Zd%ul&CkYul`JtXSQrIc4lrT&JdXe(F=}O$feS zgGgyI=J94oaMY#h>+q86?eIEe?i<+YrRsHZl4binfol`N^CcIG=*d?oE79EMyMWyZ zz=$E;b6drvtHSC6>3NcO2wrp8IBw|UD89t*f7Fq z+0Foz$wLYVdvTt3okKlMG*CNVKM^{CyWMfh02sIMQ6oxrpoJ}|)sw7Qfi0%GTAY*P z52JwJ)%7hiP>R$EzeIkr#+6wC(^Jp(O!O-vPv0d3Wth_yHZ;47ObQ8gx;&d}6Z-vr z_SoD%(an?mH8Oc2IKWsvTn}|Kbp}t#df1A5DRLW2*6@sY@ho!j;M|%eQ#2yF= z=ViUd+p#d8YMI8ES4Iwide@^ozo1}wV>;nsF4ckL=~ZQd+8Lk(2ir&4+2^S1>+ z1i3;HzD@2M|43B%o_TMB@dySzzQNVS01HyrgKK?3zx#&f@RMFZZdKRGymxa*4dP-Z z7zE9t$>F6T6xruui2D(>I|G z5xDS*y;Nq{18)#)t8{73bh%bGNy(faYbK6<_ywwwkhn_V&=aFf3uw{+(1?4lgq@~! zfw9f}meAj7fd4b<#GV*3G}k?9zZ?wbIfT+8&>1( zzN;)~cZn!(t6+lNeh*^udL+^L;X5NGKm1(8O^W-(^(Q=%sby;={CY;#sTnG(x>Q&d_y1t2O>sc`=FU{pn zC#mn%7czaoW+hGo8S1||hKjb+w-|F%TXBy%{xOM8qfd!VLJWlCZzj`*4u7O$dcjJD zKVA%N3+p{{_l&RBT3CGD{MPpom}>olOL28P%8DSTW3tdzgu zY^T4$YB|L)FF>HI2}1X4cxIo!$i=}DSv$9sH3>I!dT@P-4j8fC>oNUy2?FMQdT@4cePJJz>Bf4@kp9kau@UpS z-`T`nD_(PsxyS0p4gsPe#SseYv~0@fHPV>SF7@)Ho^$5DXWh?lI`>(>NwbeherW35 z;j&H6`A6U3Hh8wyyskZ*aytA01AEiUIA86N6&{&x2K&7lNk{DJypbhM;fbM$r@Xu4 z?Ci}LYw^p-shGev-0j1%VEWkt&$ob?eo<|cG8bN^k}*OtlDFtroNB$Kg`^aN*?+35%u<;z7dPalUNVQy3yFrR1uHo=BT%8I$x_n zA0iy~56r+r8v<`|R+(TjwX~)Lw|S)y>CM#dmFi}dQSr6k^Z%6CRR4zqhDeb8D+jEO z_!fyXVnuz6SZC^4Vo1|oj5slTT?H_bPjZXqx~G?&&oJ26c3Bqce3UR$RaMf%^I#^> zccnYV4G6l|4pozRLzN1^d8NLSUQRBau`bv$$bl#ar=ybAsBADK$FalFN zd6fF?vlJw4reJE+ep5^@We4%wM9B}^$fnvIV^U8F>9Qfk8I6E$YrJM20qr_`@2^8A z=g$o&fF5lvB{!i+VA}o1AanNRmo}uLm@}aE3CvEyWZhB-Z<7k8-g2{Wr>9frK!2IX z_S*6Wdmj>iK?CUsKrXeyZ;gOdc1XtB$vzMy5V4vt#%8}v2_iW3pGNsAD&bJ#uc{5z z*of*%sSUrp2#UnM*$vcOY|%CBoAVINgIDrA*7xQ7k>}qo$LQ}c#Z(rAE6g7akGc9J z6A&B?w_x0eBmU*QO5#v+B8nYWKVq9Dy6eQdM=(IIH(bUyAfpD3_iYThz*@s8jf#r$ zzb|Y z8ZWmF4gIP%-RDaAKw4rg%=~)Yzy08i|HQ9LMwOs+ zsxx-0S1B_P*PE-wCRp%@J?%-hvrGbnDb1_M zmi6Tj5s7~4P)ZM}u8;R9M@a|I;gMw4Q@JSICRR}*c1b=hiynv`u^DzLIPgU`Yee2@oK%=VRc&=H=vPNdU9N}C? zJ18d%5#Awy?wSByRsU_}EuSz@AhfCO;3zGr)oRN~L2a$_u;VT0fXZmZqy}(lL=;-) z7V|jXE%L$&mAr6WVLdf9=2<_NsVo+7d!(`&5Q8yE{l&u{$*??alk$s0z?s%Om+|Vq2o~B~TQdnct0xwT#05KqSk{}j z2~40HyMJLGO(OEsDsNJAJ+TXaypBT^fiJS?0^SEV?-}QHDxSF430|1?oJn`b;vD2c zGoX9yI1(R0Ba8GS2WNnhTT+%bZ3K%#svV~()w{E;5EqB99`@4*7Htw;ei!@OSNc^j zmWl{lAs5XzyI20G*nYlTvb(w16RPuN<@Hvq4Kp4}adr9;4c4 zygN1-UMK0}WvH{rH?}h>FNdl5xUaWKXnP$6H9n$MJ}wy572wGIwy-`q!%M_-yF0q& z-*|hnR0gZHRkLfgWoEqu2_G;xy26nbjh(CO+cs+0Q&^Ey@qGRX@r0(x`+JBd-9KuV zxr*1kNj}J2e|a|=w)wn{Q+{sL+w2>gG&O!AQ-P0flw^4Arh8JJkpNti+*Ad3M?!%V znaejNMd_%-8_F{Re$$bb=5br==J8o-7LoWNxh7?14Dr_83_z40B;nx71Ln8TcG~Mi zG|0wRf~7NW(MK3^^L040-;Hf6>y$X3o?Vftj2g=emJH{oUDrOz#VFC*%yTkjj@?{w z(3KTn(MEe!p&+v?Tn$P(2yto6VV^Mb|Ixs?OSc}_I)pv}J31SSOn$vu@0U6qSyg{a zE-+1C(2WdogIX)ZT9T6+>l?DUIxX~5mR72oRp_5pS8P6Y&GI0_>!yL$kY39kA~36c zZqF+YydLT;5hEgLgAit(s}w@7AefK^OmDKYyNT_p(4%%SGkD$6(>0m;C@1hu$~C`y zsR;lT7Ww2PX=h=Ur{Aez1kZ)E)m&sw9r~J!e}D4C1G8j&t|^SO)_#3RH*fAS$?rI6 z;B+NmIP%DfahMl`7-34x0g$$ZU3#oV)55>}{7z&LlWmY}1LtQXg(F2pllx}CgS#yO z+(L7%G0)xG6Kn$apOh9cZ9N+a{n=K~ySOY^Dzd^!5Np@H*TvdjK}6A+6(#G-H|WCm z6RvtYAt5ZdD4+@@g4@SfKSZU~8Io%oo<1%u@ACSnPKo7$rejj%(YqDM{I#6Z)Vx0J zVGh7>o(<S0J%`JbX92)`gYo!zEk1S-YCdXVH$S5Mnf!yeRZ;{zu+vVE+@37kHY zlOmVoko{I+38HV$m|k|NGI4*4(0B_$64!>-Eh5v@+vz)NyIB)+{=}|nd1OdN27DZG zB&fq7)j4PoJWhS1TuF{i$6ResKDrX*YI`q*NY!;by;&+-&>?K#9sqdeyk0GRkdzkd zUPr`Lo*IZaVu4ky6&{!gK$X*{jL3PFsv`x^lt1GvvQM2p>4z+X);D-JEfCM#JjxP> z`7iBpjineD0|(kxL^5cF>oK~H>Okw!c9K{C3wg25n5KU&R2MZz{y0B-?&-QBWYd`EI{~} zBxF?OGNjUebI~yAdMmo}Q>n9urLsouipHI3U@w!TMp`Z<2%5AIzp_aw+{m|u9B&2I zHUg7sJd8(>B_pdYdFepD?;#)x05<6XV{t|!Co&l&)9H~usckOP%AKaCw}q3r&pc ze(_5eEV6t?vQC4?wR0&1>ir+`-ZCi8u4xwyZXsB3OK^Ah1ouF2m*DPh!JXg^3GVLh z?(XjHG7Ov{&-3n6wLf;%yZ@c4Q#C(QcO^6T>b_R5?p}Rexw)E?zqRdQj;7|V{7};9 zLX#VlZ7!K@9&uJ=TiL5S{^Mjt)J=If-bwh3yK7Mj~(2h#yH zP_xVq6wkRQ>PUXjc)+ieJ{C~0h@L;6O)<_~`FLm3{XAwO{G!woHoeMOp_ByfC~wLI zt-Xev_oT4v^->g$YjqTi;YfJmYP=*=?AVhb-0c3b+{TtV+rWh>ShnY9Qk#(86ljd# zoX}Bi5nG&Gi79Iuzjprw31i77JN-sQ9sS`8}UmySES&Kg9*rrC}<5otoxl}lIRV|ROp4jXNhD=m3KJ8i9{Bn1(+mES>Vp6(7 zUSCOdsFog_DNzX+^{bNaUOdO^5#f44;$!l~=YY8{^Ot6a44k6a5&Bt{)r7X? z8B=ZGV24$5$F><9nvdXXW)tyFitNi<9G`EbutL)91b~1F=-Z{3M+NwN?!1<)J!SyG zUUIxoRh>+t>KrtS9{MLUYi_CAppgN+mS~d-t%=V2P;FPC*|HP1VPcxb*v~GI^0K3S zdP(=yvhix<5AuvemejjtY}?`q3Q=@)y@8F5SWXD|kF21S9aLI$#4fJ+)qEGgqi+rX zY$>|KB6!U}G?MSXOENVR{vdtLWzG&|$RAUwChtRLd4kcL9=0`QKzsVTS8X{b@Lb*& zsd>K*cmJ1s59=dIpqag_Daw*?72!N6fGZSyTXrPJv203fqvjP6voKeMnPFXW4#QeO zxzg64aXK*zGwrx5P73hUuW>t7mzRLQtg5^=@>j=?G*=C>?0P@sb@y?*us-8OsCau= z%Vc9cK6lNY$X@U!CLeY_ohvrAzh`v?5aouNuieHblU^8JpR2q+$bq@DVAT>D<;H?Z zS|fBzOZ8<1I(&TnN#YwDFrK^~m;5r4s4YMK`8UL2dZY;Aa<+Y4HO&p}#dMve^$jg0 z)lc^gqTpF3N6P^~i{U^WDrZ7!zvyW&QA@MDI*aLa`=-pQl`gR(u^KpAENM+f@^p)` zN4Y-Iw``i~p`bE7|2mA?o|_sHEaT(a(8AU+9Yq3*GpE;N!lO5$lQ%Jb9x1d0ZXv>r zC};2Uj~04gd+)n<>K}pKhb80?O9_;cMr%=?Ww8VuopLMh>G3=vdh{J{ZLcHi+>994 zBsF?zVIysr;&E!1+Jl5s&Ydy4_@%`3qhm+t-DDeppdxYxo`ekqxye({K8XQkT9{4t zFxCEXq*rnUw|zj^n+(}+H6SuCT~&#L}IgdT=DF~ORbQCo>@tA)$LaCM)xXQ zZsg1EE8Lib109_U2hJ0p1@gkQz54>4I(Ka>7?ccQVvK?q_{MumvRYSfE#@n&F+_OF zqLK*>Z1X1Ov^MFxPRQ61l~e=!zfWj5EZUgeaWF5cl{ z&XV&aK4Le*-fY%gDurilZ_9TZ1>1Q&fnW5f*TGy)`l#%knaY_e=LcYVZ0{}F?)WUt za3UM_;!|BKCwYhDRr$`y9K%$OhWJ3%#d*K>AAJPCc6CV<3Rkcp|M^;P{9y3X{lF%h z7N913SSvE@nU;oqM)zS!#cnUH%JB1KkDeOquXHte_+4IJF#e*ti7ms~JI+jh?)WO` zHf$CQB|+YiWVfg0JjP-p-eF^dVxx@DW{G+8a|q*AlsqJamBWbv4~8%k^bi*V^0_e9 zR(G?vHx;3G2!UE$fnkc3mPJ<`yTMv=+%vL&K#V_yl|(u?p%BoheLG2ADD_b+W(_?o zMCjzDUymfy=nN&CU{&6aa$OfGwFHggg{&KhM8~RB)tF|>rO1hIbTk<#Vy7^V@EvX zuB@wFD~m@zeWgpXp^s!>c6bbl_zX}D0Mt9sn%>>?3$E*!IJN2L2y@)w_J*=<6aTHv zus;*OU7In!((e+UGCp5zyBig2X}T_|03U~w`jLw_R6jQDa`u|ev-e=by<94lA>$>b zcFN||e?o%F(Muph@R@6<|2%3}EVn=0Q5{kdl9=P)&#hHVE>9${xD`NG^=s6R$oUj> zjbIGM{Zkl;mU6@6xCwl^P#se*DCp{^aospmWgivo?4nAQUU6`8DKPsZluMtmOdNxJ zIoFs!+3cse^NK19pz;NK4we6=bQg%0hno3 ze2cp+p>NZjBXbNrY*13Meh<|{Fto_E7svea4o>tw{*?hq{62m_ksACpRfCc(`Bg$w z9Y< zFR*ec_Za!L3eaSu4tRsx4ThRe02*9V?r^jRby_u$K*75PG&DHOtyE>iA2bsmTw+_` z`3Le?tHt#Iis$4Zin3N>XfjH`9+m>k4fuHD3dZ%9XIEX8`==blR0X#Ok>v@%Uw?6g z?#<)Kx)vEkAN081mrJv;w6x4Ax17%Zl`gBHp^>w#{3{8>{ugVM;>H6Xg;VnENB%H! zh^u^q20uSj7p_`$4%eOReNsF@pJ8d$WY4CqwIp!v2TA4q56ShN2HBfo2s!4JV)}KKi4B6)m-v zs26CE4`dwA6rn80W0;9dt(!}QSH|az8FzgBC2V)2x26k8A{t!O--T4szu6d0r3Eb` zgO*maq>Rj8IyScU&7d=!q6pOZNxasKqDiC0;0ZtAL;0f5>WVutgDdXlk}#n zg8~s4{Cpg26PMA>D-BmOO?}C0Wgh9NY6G7h?3G910XV5UVwcU}J3;IwM&%fS0}Up$ z+^tTD+y6s7h)v!3q2htc0f2pF1>Y{r-4-*xVV%^HS1E(C)<@GcL~^OISvpjWmYMEF zWo?ffQJprp2z3X99?x$pYSns&S&sv^CrdZ)L6CfJl&e+)#{qThc(Qnaz6ns7u~d#v zhy3~(#CQFNEdDK8_s#Yt2-HlFKQYQ>)3_83sCs@X@%b#)m>ne*2D6gtRIMp^stYlT z-ufC(mT|eflAN0ktFa~39w0$?9eB#rZM2ERa6%~{SIoGvK^+^{!Ct+|W6C!M2jw}m zYSrUI?Ql~emLY{{t;s4&AZY+Cl-rcTmGs~7>A+74wnoZ4GqQXyPj)Sv)$M#uiy1YD z5#Ass`$2BXb&xwDLIk1UF98RlzpIi4YvQV*JNo)o9=9%%DFxQ#a<%KqBa_&;vBfGZ zAYF{l_RnzU(x2mW`u%zUW93+@& z_&rC)b8N%fQfxF1YKoEEad8T{7+IM=n0Wndzm+W2T$V1H_-p)W(GZs6$kwz z;6YwSJa!V;n_v6(!%QAXP|RItcNPHS{wCB$c?tc0@uM8D6vT%DTr5!LFf8eB9=313 zu24ECk?3bO2zk>XZ$A8t3^E=#%l|=B??-%bU0BR?|j$`@1jh;7N?9(MEREwrlekXZroo^n)us$FQBWE(g z|JTkG*nY(%&-Yxhx1z<{iw6f;__Kii$G6%hZ@#Ke|LY!b$(8!`-!C2#WMM(?UWzwi z@#e!{X8q7{x6)5E|dw<6+(}$oD71<(I#eRzY9}8RofOoS=o%;Qxne9 zPOoI3`EP-ddII?qC9zBQqtxTa@~+RrZ_9(c0m5(6u#m(If!}9zCiA@UKj`+7zPTU% z=R+UUub;4dI8zIuWB8zstzntz{@Zs|Km+f99o|r2O}wVm2^37U`ETQ1W->CYh|Y(+ z!j5cNFmAlgus5|`-iiP-egX{Ob{vX`WFGMI8_0$l|LtDLC;MyH0#k;A?;!OQhOPfL zdV+VgVhvZea83z#a}0H5{y9-Nx+p&hqoQVVfGiD z5X6bsMPc5+E+qc-^$uSO3JL)m8ygM{DjLf)E{AVzo*pb#t9Y0i)?fU0y8Og5E8!IU z*R&0obv^&r`?W%X6t{dbp0>%27b;2V8n#i_-tE+bD!dSkcxvhlTZObQZ^Q7D>0bm; zYA_rq!+`<*mn_?GlC`sfnuf(@sbZ1RxCV+Xu}`5)W+CvokjpAQ<6me0{5+od1%g+_ z)6~xbo|omyaUGd5uG+x*_bqu1B|X*&~SxNCm5NLtfVgr1)~}@c5c;$HvG10jW$?cb76OO4T#Ls(5)V zW?Qzn-XIsXwGFO!@cespd{TlnUu)H*AGD}j!JrnN96}km(*;Q^9WPXUJ-UAeoE?E6 zU;1rWD)lYoW`_K;7pXe339rC!`JXS4@VFh{gDwLFstiXuH{?ugknp)65k3DEeN$9x z1!>z6Necj}EI z6}_5IStxxwEv4^7t=u->yBFIFj%%zstbGx>)hr8*vr$4}ZNphid~l!WN+|9o-l5ip zkyz^=OupEtv~<`vxFclD^|NeL0d7XGEu@+vApS2)@cxZJk_W0rO6gCY^0MfDgbor2O$ zdj5M)NjKWM3hMft5a=Xqx56s?H;goE)H#$<&#Ze;%Pu(?Tn!(c=LQR$O>eZO6Z+>? z_+ezP8z)IW(*IM<{J%+nz|BAAI{9m^V?W5P43UrkTDks%CiC*$#yomCf-qha(%sm^kNx%~zn!JyP34IM zqIb9BQ0;tE>^cX&?2s~H>gk;vHZ_z zRq?93_G2-(nXcO@m}6cM4Tg6qlQF5j%nOF4rJSvm|4Fu3H8GeIqv#ll=n_$ZXl;Q) z$4R0m@wQbyfAdcNIdcEvd}?3o1A;1gf*U*d1JSBhNobu16T7~N=}$;Re9@gb_fFyOgzYd3+ic*UszY z2I^4J=a^awAM%m zH3$}zfunTv3;pZ%%&)K8l}8oH7g95^}7DNGupiH}9qs8svU601;-lW+HsL#=gr zf40gwp))SRt!wo(8KCyRU=1kWO|4A3@u!!=HhS!C zo=*b8o{c4ok+n;;BjoO6ui+Qq#&qs>yrYt#>q3brz#)Gr3x<7;sM>G!=^-Y1g5 z%KrB?5uL>~u$6V{8d!0J7<#}}^FH*Td$I0d&IyBc z`YzB+EB8z?H1yh|gzHv34t4AXho7-@%|(@#clnHe9AgqZ_qIiA4FEtp^-F8B2gNC> z7*Opqm_5?`AEUT~lKX_ngtqaW%67UZRKe1Hu#qU%bDUYxizN{YhVNtc?;W>uiDkGQ z(aI$+ZFJ7s&R6cpZ4MPIx-}QzX;U6UHeKaw`TaS{&DcK>@)u~Ac%1qhdn%fBvobud zZ6d1ud|Gyo?e}*@#M$84vuMaV&7i+Kg04R!SWAiFs%%8gXx*UZaTa8_Vbn|bxJ&%f zhdN#8#D|lb2h<+U-*Zyqt>LPT=31nZ^XmfK!Umo>cw%b1u%af%(>7ob@OrPnAZ>v} zW!Bo4Jq8ts3>KSkU6bgVQBS&27a~f82CLCvB0TBE=X(7y*+t!lI0RYZ>l^eO=+K3- zpr7Y}bg~ccZF|?U)ICGloJ@G>5tkxly5d|rXgbaFq-?0u4>t*xgS4Xo*y-jo2%+KM z!(8lOCYz30=Fr+po`fd@Wgz$U)4L@?vQNpkvoUa3OxJbD5?D*Qb7Y6CzATw)V+AUe zsCVW`9yvh(E2ih(vwiUll*MWjyh;XUZl5m&N#YqcVTrZV4fBSTwep1#%BC?rYEA9d z?+$XTxgJm!uBpe_~YOe3Km)l^i^mm;0xHQ2MYvz6Z;0j$>tTHVK$%6u-3~ z*CJK402+^*sP;%EFz?iM+zO_1w5dBEQnnF}41NSo?{M}X8#p0YgcBaC&1}HVYqutc z5uh1V7*>2-y}j;n&fNk&!a&TrMyQr!A3&f*z3ePGSNAbw0N{Lc^#>4;I%lX|CctQ9 z2z_lrNs;<;djNvFzQzaRaV-Xe-MbU~9p76BZYpJ?9CF#sj-+taCpKus+Ro@`R(Hhk z(#mzZz%^cGKH5v6VO~c#8}1_y8ug;Xxd5|I>%BVY=I1iY=x6y(K2j}6S72l%IWYuexI52vsZFe~4) zR9a*E316l6q_NL?8AU~ENAGN5(mIr!wnUb-uK;^pN>+GxrU9kb9n_jQ6ff-Hq;55N^n7uK2=>4a zx2UIe`Rh5S<_1WABr|pQLdEh-%!$N5Hzu2LU)EY?_r=4b?D^x%w@kuWjOM0LT#P$GcWesG*llR+eQ3R zMoA=Qs(wg>H`+W^{(-f$otkTqt5bW3tCOxXnLNJ%L9~6fMr9U@P+0^>k_Ts(x8*BJ z?&|-8*=fvY#-XW^e6|NE*uiFf8s@Xx9nbP|zu9;Eaw&|@b;fH;^(|WrgmUr*R!es% zpIr(B#XeNH8#a;x80bogF^2r%7A`9~Mm={&fl_DaeoFB&D1Xthb7aP?~L^o z4JZo&PTvtZpCNZF=~bOjraM_!>b$q@ruISY;g4ZEQxr+LOG*#VL0SZqlItd<)wTNO z(hGzlO)`8x+Vsu#YSTMgGu-~8>6~w(++uZ|)C#+DXE-SOp=q5MB)s)yPRS{5q1R40 zyLIf*y!`1Fko}>PI~3xkQ^EY63yodH(`+^pQXvTq6}8+fK~YGyYqo2Or_BvL#O>c4 zI0(<@RfL(tc3W&4^?j5)Nb1@8ASVGDwnP1&v=UwXZ_WMWE8aE;JMXmOkTBYr0d*_L zZ&tKcW()>!N^v}Th$Yo|*`fEE=(^dT5L~-Lf>QwXsmqJ>iYkWx`4%GtFlpzOn^|@J z(#An>ZcyHpSly1{G)qm`2%Zd9viKM_(A}TmBv^!zkmXbMVu3z9uP#Kh^_6@WC`lI0 zUHfrvbrT*ibjL8EC-)Q<6qO}~BL71;w5FQEKe5%F@AT}~CmYEqHy!TX$b&%6D z{Z%1LS0_%2j^2V5n>##|M)z5k(Vphg5{91XcKM12YqDlZCCrTz8)-)K3KC+B3GJc9 z0SswrI*`yk7{JWtGl3KhG41zHHzd5e6VPGDb`Xa_MK>o_Knx(kOt$k`eDVV(kBgNk zOChyo6Tfyzl(cBrZKvTwbjW5q(T&D9c?C^Mbr(O?iuYg6w?9>z+owDC@`WIV=B__e#z$-s zlLTt<31=B6sK_|Y(B!2N;;KyE4k-83o<&-whOjw}P0*{Yw5QPE9pE{;p)MjZFB*2# zc7ZAnudx-1&a;)q^CfaSi1^&q%sh(|YPAN;;*6iI>>8AWavwL^Z|fLxGv*dOPG`G_ z-~l$0I@GNo9PV27X4mhCHLFvrgRd@EpsZ{uWSom|HG5K_p3NN=`MV&zq)ke^q=81@ zDy#`H0|A)07xK(&-SuE~K}*k#6qJKKw>4K2^dmaCKrM5#aKO{;4tb*vFTsJEFAw{t zwzU#x-Fy}0qBXrmTfDT{p{tSb1iCghgyloM7KC2NIV$qB+BWtep zAD__}HM^hL~SdA!!B_YI`e**~za9qV@-JN1fm2>LPJKjFH#sLAYC|j(cD!2RiWYhz@s^B8C6Ce*^d#A| zoo-X^v>r~u2q&ckn2Xl1?HjSOahpTRfuJ#XCk;NfbNI$lcSVi8R^vH6l&-#m1YeZ$ zUoVW&Wv6*wJUW;j;ju`~w5MG+^q-4?T7#s7emsRok7+_2S_i~*X7PP1J-iL8n!ud>p># zl49u+uei^2m60K#=GqXZqVKId6dPBO2<1t`rPOg|BSqfN9o$Gh^fz|iLgkS&3-OY&V&e1SWwpcWIJ|iBjx#C#hHaO_C^=u;k=Rkx7Bc*XV zUFIY@c#z!oMdBN`Qmp=VO7Erh&(-w1*QWOdsOdc;((VaThNiyX(Z<4kw+QZso$9$16THM?`x&|gd?HvJx^DJlXjIP_-3kWa6v+NLuj@GJ~WQ?rF+knte z=13H$g{+{YXr|FcmGkd=_)y6RplLNZ9AVhi1Wm)Fnf^S!U9u`0=L#Uvag$JxPYi`< zdI`25wCHR^w>yux(1ucX*$WZA@)-QHK%}R-LIEPG*6bYVSsYY9SBDIY6~Dk|Epo-G z#|4o_%INVns?`zPl*%n1U{@Rx8Y7Q(I^gg@)SuEp2XwOIb1>Q1&# zo=aBP*)g(0=SPE+b z@$6?zHEAuE*6_&9STZij3JGVRpPS&E+%yE#{f8H;l{vM3C=y4x^72%u7r@a zmzy2i)bon22PN`OMV_a)Yvc)k-0_}w`8hl<-Jb3}z~E)l+k?@_&&Ou27)8C1IUe(N zoJa&sv^~yVA@r@QpIvt!a}k78k6ky!>0Gbx8a3UXxY)oVt4Z^MPd9fTJGVJgBc8vx6Giz6%z%gY^9dSE!{} z6)Z<_M^+M{#(l%A+HqjpdXaaB%8?h1;S?(E^W)+nxk;r1Zykljw1uinq@|nhqwNl^ zi*yat!|ul*xx(CTQrLM)8{BnBSnqeQpLtYoZ;MdU(-ooC*8?y#2GmgTrRrCh;tK7PT z<4+kiRp|FxVzf>aS-{cu8+r7p&Q?biK80JFSBh5->0{5ssq-Iu`q{0pjHJs+5o6KTcX zl@d;uBAF=s%O4q%8E)?qQE)IWjVd2cF1ue(()w%|uBQ)IZS6z<*fNgJ(v z?&N?Z>85|&vtgxNGPJ-GKv)*L#|=|cQ*m~pNfgN}#{HsuC*{(7yNzhO<)-;Y?LH`e^X(2!)krF4L(mTIAgP)iSk} zr`0hW224iu=>>Y)50+YaTtwF#KeGLaIqZn$0IZWFW<={jPHghC^A8#(pYcu9+EE62 z?W_i7v#Nh+cw^W#nqAPCMX0cHnz`wKP*ZqsqCRgsskP1ukNqFSR9jq2f22MKm}F|L z8ZJ%RMwd37F{&}R{(h_{=4#19x2|eQIu}>Fcv_SQ4c_5#18XL)7=sfPk zZ*INAk}M0mi*3-9tT_KHx@V_wDTN(ZENeVY*Q*Pb z9b3v%9Ql;RU-Th=1U6S_i)uKbtN-hQbBRx?V|(c6=qz5X&L2n{PimKphvI2t<8q8d zKT8}xXt?a^G!5W(vBsOAJeMxa2{133!8)#Ul(=nDx^B5UH3EJM$9i!Z_CiHW6qZFI z8mysor)f*F<7c{TO;M{1H?Sw{4PGQWTu+BueY;C-GMQ+0AF@ikc00puLx++jR3uyw zd{8|l<6<%2gX^erAniNpUKp}lTP##$2d~1^{u|faF1H7w{aL}?4zARM?9~zGhfZhw zERPT;VUBC9*68R-F?=kZbTCAoNJ$rQbZ2|JFB@U%j$&=PxL&5eHNqH*)9 zS&axy!BHIjN{7isA4hhNa?_^i+J4z1wmfmS2hH^yU48r<31Ml8xTTu%YHRDosy?}` zWd3f!*?7Kr)z~4cNY%weR_r#HNxE!o`4ZBR%BU^J+7%D_KGH#&*{;~P91lAts> z4X6EQY`pKf?s08u_foi8HL1JKz7NGSfQ5{|x-#%&)E%GRDi%|1H9tLpor!AK}>CC{9+q&EAx1nnPJ1%c3R0)}-Q7od4SE!pi>nTfW$QKK2kB7eh|s;12c zWrGGbv~m|{FNm>qrwseCA$4d6VmK^c%*UEP5(L(XyA11@m?6%_KfUoqeDVL?mhXJB zk&z*|LD!{{AtgU>#7F%`r^DL$RDSgl<*@0YHjI`h>8b2*O}SQ+Qxe6Ct1v6Frt?c1 z)Snic(^e+`5qe;orODf9whwov-4;89+NzfNewaKbY;bfi`;sP|gI7@$5&{aY9FoOo z$JD95WDqQugSK~kYHwhSd$#+Hksa{uilUBt+IG8+jQjnBkA+b}_slH1?Y4Lg zER^ppU4s>7syG#E#y1~!%6J5Jrovjg4JX9VUAn~GrMk~@dw^cj#Cf52S*@+rEJZ-M zwJG5vRp+$h`zH4OJK<)g`_^txY#^&gK>g;1Lo;;4acV|kk)84Gu)$<1C)MIBR?*IW zi$ttPTpM@^f0kAwoBjbhk{^yk#XpL=p!z=#C;+lVJZV;JVqt!qNEEPkdlHxE?b-&L zKQGTC@~N4vV?heMd;Oq(j(QKK9^Q(h{+<+&LvHSF`Xgg?(tWV?VmFAD`seYKnP}ux;BnPCCE#jK&XIqlAbywZlu&NW zGijRIc38lUiS8xVQ}`Ii7qgd?cjS*vZzHDpyo@TbQHqQ@jO=tME#Am?uRlJcn)L#h zboM!53v-j0cv-GLr7;hwTcN>HAXMeG>QyE@v7X1kLJsgRe`c_B@4MhA%mGwS5?0+ zo=oVvjvi@S$zx}edJYaDsz0qEV;BtOPVfBkq9IrYKl_uo9Ixj z*R@1N-QnFQ*4g&meK0K~S~vUshvv+%2=l})lc|xi-WK#!JvB5I#SLDb@~*ZK8S5WE z*%TKw5@P#Rf0dTH_mN#vPkizTXt_S`r~F-gsWGQF6za86y%IrGevytELzqe?#!k2- zIMgSTS7<#)By7Y^6JfDky?nI*p9e+1NnmBjJID9f@swU0nW_859Rp$W>o+Ifq|W`a z2j*@zsfnH65hAdIw>L9)HJaVdk}D#E15=Z~MbOI|R9});6!`Ro`hCW8ZTLrU_$Z%R zek1ilJL`$pCaQGO^UK0hL?%kD2o*5}PDseLvl7c;(f=EBf+D?@!Iq@2YtAXs_w2G@ zdSBLh8%V-8F6+&{Gb1$`US|(`_QvRx=OlGAWn=TYeQ(p^v83%Yikx&iyK;Uof}R?| zE1?Z2U5RIY+LfZV@NDI228A$cL1NF2^pS><}*7n*H;rz$IjKM zI^J#Mqf~2X%YN?K>G$4kgmlQ%oW(^CVxpyP$Q1_MeOfR4uG;%H!-ad^=7w=46(JO< zsc5hHIBi44nkD2h;c^+=JpWRju!K`XKG0~=DHFrx#H~@d(tS%^dC21BdGUb&jP}yC z(_55vRK-rd!O*F+8B2|?ty&}19uMxxEsM5kFdBnw!026$;?FkjR_Jk3l!zrK zIrDKho*g#P{pSVdeU>=q%SibgsawN%H=k#%mb7mmrKx7-a2cd_FqGwYejb@D zMDcK*XNiPjnLW%*Po+}0bcZM11#|>;ptXK9o|i?ZCiop^dWzN( zQWi9;%=0BiRK;+`jw|7-3@-iIMJt;986d^vF-bHXc}uJ?)&C~f)}5I;ulI1vgpGY@wlmoCRfPXRV_Ue;4r zJJpVg8>^V#TyA_>Y`T#xzL8reKR->DnYb1ZpnU2D7b@IjR6~>nXM3rxm5QcOQxSi8 zx@(vwCl))KIr&2R4q)#uGnree8eXa#9xZ~zC_C#IJ zOrWu_XKe$%OZIc_Ku+bLDvJPpk1wHp?XTzSC$DcirCdN7E4zZn_A-|f!K-0IWg01n zsATcHe5WI~MQtT%Bx!;U@kih54t1|Trlh>J8N^FN7DP+vd4f$MUc_F$P{!POHW``* z(;?f2+G{GJTGIv*DFk@~e2nSV$shQ&g_)(>bZO6IcRUK}Qq`LS2ws#35D&$#Z#Oir z&xeIK*6hhTGL8bO=&g66S=9%;#-w8h2DV09-D1;S4sFyFNImg$jb`Z&IG+FMBxFN@ zm4Vl?KDvUkpX)oXmpc>>*>vx;RK{iNTs&=TdSPbrRKth!#;>Etoi8wU*QO^Lg+Y;LAxzqO7rDGiUoHxeMb9rK#gHcxdfxZD0< z%Q&Z;8l7Beo*oMF>}?QoXE9wm#orZMha*Bw)GkebnBJ52Vr7lnOF1Fi%<8OYzC}iK zGk}s-`{5FR`5b4FV_?^tL|)@sP~9&f#6yud?JGMCz(Yc-U!v&ZS>&Pavh*y@2 z=)9DRxCPeLfCehvFDxV64nZP5=k(CCPI)~LDDs!8n3 zH4EkF;d2DeC3_&UbVX}#e0nj8CVU+0{*6<1)9lMO42L)w{FTw2$!{NHvGtxWSrhxB z#9%4bML>c&I?Ahd_9mvcg@URm`$&tDjFYgPvC-#<(rg^v+O_w>D)uTtUUM5~{?M!1 z)sAh6l}3K-+l!ODGsbgxXAay za7V1g>e?5si>-RL&ekLKmRd_gme%<$UQmch*}|W%&flMyZO58zbbRQNujXCy@uffy zTZ51&JcIR7X4aYCbwHFg&y<_}g14i}xp@bU1h44s!7}iEOzw%Yh;uMTG2Ex)ygl4k zHlW~>Y%h>cwzq^yhSCknAZ5Q}waIwWz17l)8tmmg*t}>;#B{WWwa-Pm{IbpJ&RR$f zf3hf_L8?6caRk&$Kyr%UZ_;%Gh4TpuJM-^`2u+A?_q@ECUSkKes_*$S2E<(3ztdXJ9w*)(`we4igfEH z=KiEBgK;nD*KfeNKY3llJ@c!1J-yGUb5z2k{*$s~+mQ=oaZ5}O?-|W^EcIh%q?Kc4 zq#VO`teG~lXgb<8%IZfwWOnG}6G>JaJ+Hz=D9n-1EjJ934^eegPv(%M&KTNXh$LPQ zC!~P`VEJY(x}Q$sS6igJ0f|jDZ6;#HC231eF()Fj&{=xF{n-&_cMa;FwDZg8tJ#x` zt25=Vwz^xbX};4x;4PeiRdQ!+U7Ow=OEX<+w0csy{%)}IiHdGEJtK{5D&(=39myvk+y#d%^=M}qD`>}j0yqyhh z9ty$aPL?1WMRld%;hykdO@i!~c-3ydZ%LbTV(*6$l3%rMdu_ZzJ-@+QH>InMdYqFE zh3psa!I4Fw6jZCiP6-(k#i91^2{V498pKD6KSkVMj^)^j))!23Jj09D#t* z6ZrZb`D6o(Xp3KTMF^sdn?t^on_`ehFfRd-m{GN#>s~HP$oqbXUG6~HDvM?m9pydC z1fdh3bj)=PPqE1}k@F?Z(;&{{D3F*XqVH}Z=4I?7{1^m9X>Kq2!v-K9aA1f4wuDF; z3-(X%&}T?c;QjIT?r!f)J#ySlaC`+-2we7skk-+yJ(#)`c?Db=C5}&tQ{@AP#lwPZ zzB4KR_ChOse(|Fl3$>RYXO8kZmZ)`P4pk{}I_+GtXX;_V`-?HQkmOJ(oDa4b8G#m+ z_trx9xqbasBSG0IyCoIS)^z+umcj1nit@UEdrn(f@UdUJ3WE|`ADT>Kot$Y+jy{R! zmtLfF>sm{?D6y596|=8)GS6pZ_u!FQrLn0i$jczPAK^YN4d6N84Uw-@wp#GDW~2kl z_V(|rJO!qUFg2NtIi#Ckv~aeD{^;|3b}mjtHYeASgt&Nca+jnGrz_peARj%Vx}xW- z$}HwKU3|>XPyFsVM)T+5IB#l*7U8BYEd?wte#`A(AScwMh7vxtWnC<*vIj}XGd>kB zb}#&S(JKJQWMx@z@nO`Y@$s45re;y+3vZjH^E9C&6w9!xVsgPWH&FI_&h| z!JT5IE@O_Eo_&^Bc`bqGOT&JrrP|}Zc_sAx#{{b!VNXdR+5RRnnTzM^wkPTm49*4V zG7Yu*+}KuLkJPSct=vwIe>%PIeEi@z;O4!6N7^P6e}wHp6W`;F4oBuEO`sAxju&BG z9KQ=4jYjYYQaydGb5D?Wl$LJqnCfnl)#KiUciy+Ms(Qiubda?wh?|6Dv+_$seTgPl zjJs+}b;YJp`nGtKo|IZM&DP|gU4Y|?=dos!;T1bpCdTI^cl)5-4|9;${_02*U0Hys z2if4ptE*x*@Y4>_6vOcEz1xC&MnAIbuX&O9)HolXst*q28&43L@yyDTwA?m~SafSk zH9w9=JR-7)WSk%5lsYTz!3|%zfLA&1#4Ai5o-L0_mR25iwt+_YsTeC4)R>I1+rq0G z5$4WvVGu0W#W9NW@c0Gz>C;eWf5H!%nfPj>i9*n(mL#H~5UTMfWDPgyKGWLl`&)f~ zk$nhoI*@7k%DL5bra9!s|Fu0L5Zwm4V0dHklKr@LOk1Yy-V+6J+Al0gGMI zCHK-|?X2Qb8#GdSw%W_s^>9>$tqTpP-B_r}G@2Vx>4%X}kl_*?(4XU049=E^E&FW< zj(J*r@3@~;)+10PsQTQ8Z1Jv$TzX<=CJ={`Umehm9TV4J3nt6-JYfEi_NmeduH_hI zcBr~eS`Tf^AtALERI21PT8=hVAc1kuK$*8r@ew2*pIP_GURlk-n6l%T0Hw6!cc+~u z{U|Lyjlu8HtJ#qqi)h_hg08F6C|iCq!nSJ*g)_nYM++dU)>re3ma-*J88x|Af7Sg; ze&`xmM(S+&x^Yye?r&pQLd8=zpIp^HZ6%brBjB|#FL?8&dEqYt+X+wn8kwr9Xxo^+ zs!_Ay6hNJg2AeL0MHXuHXP6&!gqbZzg9i^Wd-;3qZUwPZ5s85VL1EY7r1qIMaEP-t zwrH|49j#liBj0D|V$vZar!FtDOlq338>(;i*>H>?f9;R>|( zc`vQ6iZnG_e2FUq#HXGm+|FTk(Mjg-OH!?vYt`S zOcPY0_l`p8gEcy0(zimzbLGk4OOp*Ts}mAAVi+$(Bq%RV+V9(jK;spy?%C^R+n>8( z`vz2-1EMjcLq3yqdq{Z!mjftU+wnLNf$8oFz;!7FM^))ai|v8@-z1w}9bk~i$+^+47bBCg!q2AF2+C9C*apWu+$3>COHh_TDO--syHGJ{V;42Hj^S#!^S@s*&$Ny#&S(kf8Y(UhdMPZgd zF(x*&&P!#I_Zwdoeyh1G?xoxw zNFlHd2HhO8Bz*fW+!E9y;Y2|JWcCL9f1lnKH7;ts`-Re6M5?V(6X2m;@wm35b#`&_t!9vS!w{7FX@c9=XnStW%VQ) zmlYA-sr>vN_2jv+T*9Kp5a14uP=UvefHV#mq_Zxq zwN^ZfG#TL~iiVx)O$N+GzjF(am3dDL%hAlPoAOp?>wL!Dv*Lfidle_Yj4|IpErO7P)K0HZ=3D; zvK91%6Wm9e;8JQK$C+EY+2LNk(jnRsG@Z^8M>@T7sLb6TtmH@;HO_ ziyo#0q4_-@@iS}m^+&Bi!zsBo5~H%~1S+KM%|{!P;fC&Kwjt+b9J#{#+234?duK64 z6z9i|mMx4u(ZcLtN30VrOUiXPlpMSX-9T*>p9h;T=%<}N<9r)Z*ed$n;J_snS(1FT zcG`YUak$_?X8-&e{B`!`w;;#qJTAxKz6yu)3Eh?6)KKyhrwCl$M|}$$f~BNd@oeeu zSFO+8KU8g9l*5s}Cf26qDnh>J6KWB_)0_rRnISoo!|7{$91TF+SG_zu7(~d0)~lUP zXYAL3n@IN;zHU|n!#r3t>_*-dbfpp_3Sr7VRQdg3ph?{6mq}F^({~%O1WqYY_lj`B z=sLPMaP`L_k_7FIJ$xdg>63548JyN1^3CAmYF*&M<}5dM$GcY1RUh8V!fzeF(WWrOD$l z^E~z6_&mGlbvdWBV0QAR(J+j6722jh%NOvS+318O{LgC_2HL24au%=ZF*OHm{fg3z zN{xfZxX!aq8Zr`AqJ~C|d*C+=&A|!kE5k>Uk(L@Q2E9%-`U=#A3T7A@zQU114e9I2 z%Oc0bH4hAa_NxHk?Y$!tzY_0(I;1b01ktD`&aBn zX1xU_L}u@!hbGKquZdV+!2)Kzw{04j-;ltv*Le87;G$1oSVNy}0C{n}xynRq_VQ=k zgETCK2#uDsah6W%AKympDjW&6y-SddrXw4K1ixGo=zWQhDvuJMOomqSbj`Oi<2_vW z7lg4wiR$;BI@TKJ;CR-3$Si+&f*n~9v0C`%(5`Cxx+-$1+~zcBDdL(#&>RgRF?gzb zHgZX+qCjQ-MzQd`n9H5SLC8F)E|(xu(nXw5?Z$Q|PuRm5$dL%iVCYOWVw9s|Rp#}? zro>BWrObzXF}vzwaG@^6x`t3`p^8+4OpG#hm%TFFlC5a`*)g)|x;IUxE(naC#}{U5%Cv{U{`iQAk~+R6wnx%sZ?N@iQL1iPC4t`MSX` z)cMHU^DvKqH9O3vdhFHn2qp^Q==Gt@Hkz-S_dufuAT!CvTo3x`cfwmAeaD*gi{VUl zkQvd%C_(ggYE+bkZ!)^7$VZMg$id`bT>&6|*DA^}aZ!)3; zabeWFH28FxAGP)%HPk2$;hrVSNq@c2W@BL~ihBLIH*Q{x*3Iu~Ow&04aO-g}T(1&u z&JvFRKnqz;R|h7G+?bgCUFR`ucehsu`U7@l6QfytX-Ka3bZ80b_4Rhs|l^PL@ z`}8n1Dmd~(9UDR6)Je-=j2Uiv!>ifNKr^)%Ikas!Lzb^9S1$N@Q7sajetnpQkv+Ii zT<97nM$o39&hY6^Gxw1`R<>D)JwZTRG1bcy_(A$uZM-;4k`vaS)#*^?Q>ZcSB7 zT_O-T2YLLJeu_{nziGp>VR<>Y5!oWBHbWD<5=evMIm$%9u~Tm*tO>YJmO%8oZjy;Y z+Q%HdtA(!Uss6<$C2?G5nbm|v7JU*LHfaZZuu^!_UV;0Qk9GZX$3cbcJtmmnLUYPp zUC$o0m?*ZBKRaS|tx~i!)7oIMB-UWcA|iNSr7FQ_cs3|cB%V^j(aqFE(T=Nw4zX(= z|C6D)AR>ZVe>ZtP*s3Qa;vhG84Qcxi*}ygA7_1ChoV5ayvd6Qmj^8N-3#z@JK!w zz$Db(!*Mh#`ufwB7~M3DJN87D?Bcv-U%^N*Vv~Afy`S?p;;k<1=SKu$xRi^V1I8PH zxr^D;rWeiouxMQ9_D5wezjMJ%)tcLW(5>thD4Tia^vt6et0vA_juAgRC-7;_GiPNW zn-yT(mKxNXe}LV>$|&LF5lK#98i~xAgJLCDge6EP8I_7fmU)=dSFZOYvC7nQP6l>_ zBjPF|BGh)qHE7^dhv3X6H4ff}PTpz8qTN(|R)phR`8SU2W=A7Mo$SC!E6DA&M?)%O3Nsj;dbikGG)ENN9p))wOTTV^}ySk{`%v)aDWT<^Vx2PCHrv+eGE=v z#KXzMONPm-LFt@nx`hUtfJV)e z1v$s-%pvpODN1|P(5Zr+$q%Ql=HoO$HTFZJO{fp6I~Mt)VV6!C6KlG*!bVV1D@aus?Kv>_<68eX&z7k<8e zgOno@z2_rr#M!>d`3)_97h)^Q-GfIqqLM0KS{KD*rAO{G(V$Nh-q-&|t> zrOPkQ4Ug^29xvA$5bg8GG9j*>x$#7wuGy-KvsyIoQSgyeNNA6p#ovHCp$A%*n zTvH{#pA^K1C^T2c)u+d;IB34`~A@~3yFfbWCs&{!F|iG4<_V8(O^rx72HjVJ}ujR zh@C41+kbT2{+3)th5P9DpcN_?em(+W!nnxTjT<{kEJHZ{P|Tt9aloM|oisgV_xF_J z$o7*GvoX2r_=(>YPCx}H*6<{y)6$RS;<;gK|I+oWEijgYKuo(Wz!h;E9YQv%I*%4k zs_lP+czhg|ZOF}%7rzyC!0_y`cq}e%GCL8fmQu!-a33U0ru-O(jPPuaH;4x@@G6rr z@Gc+E(I))eF}AZPx8M!sntsdgE7;kg_QX|5Dlv-+PmL)z9MPaLTf^BeT}EADdovs1 z-mL1y+okS3L1Pg;<1Lq*C_a<I|>*4dEK$mL7(JnWi5m(5RF4J4m-!`fHAP;ZK zx}o=2`S(XoCBo&}tkn9rjo7a4lv>#w>BI42)f`XQED>WE#f>P)YbDd?jLNyy6UtlT zXR>W3n3P+(-%h+xrl?KQa9*}!f``jKd1q%_VKbYCu;LWLM;bNwbDw1$%>}0_;AS2g zHxP7Y@ocJqhK=W4N7d6dnqvGFF~>FE7y1>0oqo>JmmV|jDx8|LGmj)%3}Q6xO8Kn) z+OvB{iHXX7M80Jb_F4o-P04eVCW-x%<-P2EXMn2}9cVirr^*f75(7rio-D2%&d-qsNQ znUNO;k3Uz^JEE&;MfS3d88hAEwr(?LKj&JUJBql~c8s`HI73r-v(qn9g>vF1Xzpz6 zITkh`jD^Vfu%`Xc)yd?ko61GufkXT1T*#F40b_7EDeFLsj3A{zto_^$?WuW^uVtO~`qn&p66%1N`K;T?wK_v@ z$uM)C@5AeAXZ2qIsShDy%}(#h=vW09^o4Df z7<@QS8=3dU3u9EYVu%#Skxr}U1}RoJlAE!*H$;&^s%)FCy<;logcix`g^GV-%%`|5 zx$m4D!?v+n)7WYxtvJ`NTg7bEe4&ra_}QmC&@E4P1?z5B^q}qsdJ=X*bzfDB$=bff z@&Iu{DvGz zgV!J9byub?rS^OeR2)}i+|RLqj0B<2H_CI>aj|L-dhev>R!eVQY29V%RbhhTgu*#j_Aat=^e26^cO(*HI1YaP>w;Wq9dO92SGg{lr_GB0-$Ms~D**(3$ zy5v%&*zbf6w=nN&^M|Nj_sqZaTo3(53B= zor?v?V0~>jQI0tYl#{(m4j+=M6^iG{KAjH-zDugjI`4)f=3$KUp6!k;pUt`!4i_9s zGO`s)$8&UjxVf5is^XqG@XVfUkx*URonhl4@3Zgd-*Jm%;*D%O+#MVp-x-xsQ&20+ zLmTJ50it}x6pZnACDv47EJAGCwa4LduG{!#u5in|&o3BNo%!Ff5MIkpxUe&CWhVs> zl}+#%6AbZW#=WWjVUd>VyB;dX*&h6JZnb@$W-+W-nJ*UX9t)O=A}yQ(dhKq)a7gXd z#2TK$>v3J^1+ouTE$?x3Mnk9+^L@w6-kYdY{P3%A{G#}=h6iW2ZD1pOA=|sb1|zxghNU4A7-viS-L~|ARZ$ zwM7S+!FY+je>-Kcq{5sz^8S6u)|(F$&R)~3YBxZK|BSp7O8D=6m&)dj{tgY6fBW`h*9!`N;JfeP^cZPqMubwsRF#WAV)dM26_rB?3PD2a;3 z3aaeOS~8TKls*c2o66n6Ka)$ojxPP4J)YD`_zr2sswq?6*#O)K9@J9AT1?(?p{9JcdNBS>^HQhRS0BaNH(k!SXXzwO8Tlb&*PHsm$R# zVOC%F*^R&M|FTkLabwOeg#**PTPjeX0h?4g1Of5h{-k2pZG}S^ek;Jn#;{(m*w4vE z>cY6-y73iF4ib+hEz z`4B1;`+v63_JC{)5=UJ!Un( zQr40AqQg#6q7)iNlv zO|5fmuJ{)D&nJr8j3)H``F_!A*R5PIbIxT7W&7ZTakiZ*4Ggy6XXi_Bf7RalJu4;d z?iUlZn`v;f$$owni?2TUZzb8d*Y0^@(S^TtPq+@+(U-O(70o6a0yB7uLupad6HOV> zL^(Di9>Ywfw6%j!ce9_VO22Q6P{kAdqD+@L(Uo&VQD$cT%1ooqw-sfyK_jf|2gT$e zk<1X9+3eFQVdU(i#0IHF()uT1=Y(K@0SUWnzV1om!Eo~OYC%ytK&GYRFjG4Ipou1B zhceNHwD0Pmr)C-aVI|bsx$8KFC^~v2nxPto8&s2#A(9|Y2U4qun4F3L8nFo4zf*H% zi4t{g863h$fS<;kD$IX>`#Rh=)FYqGQRQ+7FUSDzv8;juliWkmD}$qNJ#uG3@_PM) z(?YAC;!w%Z(+HzghWoB>N*uVz5XY_N1$6HD#83hBL3=eq&D>~+b%r^E7tOg#Yzeqo z{=Q0omnnilH>3rb!gX)7y`-dpi6h03PRIpvtRs|^4#@Y<&DP8Et z1p)#xsl6!O_so)b@&v2uj$uX-VtNlQyysXiBVRLJus<48y7>fCzj&Z&V2Eep$;!j? zUQXmoh4z$s9Q44HydCP>q@-4(>}6*&>FQ;QwD^tn>6wXls2W~5 z9T{Ei!Xb_`Je;>lcDlDrb-&C68EO)hR*cfdNm@)V22R6>W^JdmdXARA&jUelG zH6xD6eEuE*riNvDnAaVc_G^K12)Qe|0o{PVJRiWBqV384EoXeh3?OvKVv~0h5KV#M zV$cTjNY1RycBZ}6jHW_23tAriB0P+DO zwQ}u^{4}k~e%4Xcyrj5zNhyuT?_`in`Y8ItHam#(xsOl*%Z`fl&&RNz-nc0jKl1*Tg#1cw*f0vO6d7eHGw@ufCe3#J}(WSK0<;W_5wZrzY^%ROU4}; zf~6l_&U5(CA@Or>&EXD8-;$uhOr42TB+}BCrZf9|&HZpp6`6x}8FPR@Ng@i)%aGr9 z>e8Xqobsumdw9&?gbh5rwVEE`9t`T6YKY@X z0&k%Cc+Zo!zkvQta_;fmGG~Y55#^zG${Hh+J&inw9*ug${qhyw)(2m8%j4AKr5ZFt z`a1fDPVF2tNTl93<9fU5DQa<2+Q}!^@NI}_gLPVqeDQz|B!Yc%Fn`b+emL-lO9wf$ zoZK_)cX?FlJ$AvYmlCw=$rD5E=G+(UgWE@vkl+*3Nx^{WI>x|6@zi3~U0Qq)n9~(4 zS?wb&oGR0W1w(=3+CX0tPX zI+?N&xwngZq3!KNzq`f{o@i_IRows9qsO z9Cvtn=g!=HeG$$F@s5d+R(R>v|EQDj%Lb8E~A#`*1WT|Ax**-K~sU#)Jy+zBj7 z=@%G!ByKO)d1GoDjRLBhcxT!oHJ#qF!T?e#_ETRC12}%Av;ow6r>R+n4{_3qDKj4=m%3o02r3BlF zf@Y)Ja=7x^<=LU_YP`L?$U~on16pihQ;k}jYj`hyr?chAY~b!WTVUwCzk-7&pDGaM z#z$13NZ*AYfa``1;cO2OVS~ycu`sk7VgL`e;vS%I2ZwGXgSqV?0bF87mU_da-InA+*;cuX(scMsc~ zr0e;SQ9y<^7Tn}#j|3Q&0IVa2oe5fuyU85)VM-4~Rz_IGv6RI}2RR>fV0XGarZOd_GRh z`)CHR||>0wAT{Uf7ZMjID?)O#@qzjb|e(Zv8>A0!{C ze&h~4jU+*=-$z3-dN;t$0rVBVjXV7o2)2axpTGSB0t`!lE7uEvtPY7bG9oGFMSjI> z3X?%^J4;cWhf#j@hn~%P*NefjF-`yW&CySfYs|#?`aFmqeiIFNERwDODfR$N0jE~2q;g1fFe2zguiDQL2l_;HfQhy-pM3p0`xbNe{E*wMk~55FH6Uw# zSYj2A5&ce|u-xnU2XG;8f1Pg@o`wM{f?w}GG=(n0cK~HP9)eEjl>kPyH^SuEN1sh-!HF(-@&?*YwARq(M&&8kJDw;pbc!rVQz69idU*dl$ z@kg=$FD3p5l;Es-&!|x?6w79j!R>s~FG}S4q+%a{D#%Jpqe?}+^xUajLWm~tqZ27r!#+S|DHDPg#l=)qZbcgIJtN6YVQ#i_nPEA+%#f$k*QG44iwp9 z2xo=z4}}dV^7H^mlA0B-+j--=IqPpa1d& zpbhDe`pbi^qmslc$wxiVd5_sPtGx-2wQ3!Lfy5TMuqny6Imgxbge|BRxMFy$t6>AJWYc}ELUu^SrzYIpN3Pc{H0 zn)V7%jn6Y)9`P?Z6k1eD^n=l(n?HkI{UF9=3>HwIP6Sw~{|gFU zhz=$zK;Xge0J)iKjVy8hBDXp^V03FGZSz-**5jHphH4!ObmMCs8RIv^vK(^+r@QtQ>Swa3Z!#1o&iud zF(Sb746SPZQ21kLZduXS#{H z$hAFKdRq+)@1v%q^x^sa%d2bt;pD$;G6Y@h9gLd&VWImKtsfB?ECOm8o<*%3FTq{H z8y{J)5iI0|3>-QkV9rkv(MSGe^r0LIc$bv`%Bymx)vXhG+!$_6if!hF@VsKc11bGx zzev2GYU1y7Aiy2|s($DM2(E9fG>+ov^7;<%;_SARZI*hwhZxTDQRIP*_az4j6+ zpqkp1w~iYjj8hkVML#rHVdR?3Gk;AgJ=v|o3FLDB^g*%QiZ|XQUu~0%$YeP=IgVcqYI3i*eI%Z#_nas{044 zzJDLZ3Y^KpM_{xLa3;0W4#V)C9|4sWPZt9Dqp>xjasqjECDCyO*YVW^#&`$Lhj{0H zo&vzLCpyKbgZgQJ_QT!*x%}-%joyYS3*NU5p+Aemwx-OkvqHl4o&aT4olxY~S4W;P zKjw?X^_&TJ?JYYwGbaLwzcKz({-gkC)Iip6`0!rVFrg2CF(iOIg4;rM7#h$+HzbF8 zSV(l;_c)ciVhZ2aTOZVF0$SH*Kmzy?=~2rhHlRDUH^3=OciYryNG9FDIs8pxy=uvUWp(w^IXP#Q`A7kbG!!#H>J@=A!z z;j^im2XR*jn9I1m#e1`vkSr`2w8bHp;7)IuKFw-dC1TFYP4s>0+Ya}V(hb(*_}yVC zPTsSa$Byf(g|#FVUAs3Sn#15tyT;y8D(O#rcvyg$YHb|Azvq``{-o4L<5t81aug89 zL;VhtiKYgIkHCZ#PbNS&BanHpKsd)yMD716Y8?1b?s`gf2Uc4TVHf_bTca8NZBn(- zE#;TUlyhjFFP7RO0M<5>1k3>*tfo>zw^Y>k=I zfSanP$Bf$!xf2MK4K*V<(@4Kz{-RI5;H~k|yB!2{)fmtAR_VgMKv*;J;5e*JS$*W4 z`Av}zPV|*Kee^-)r&5+O#sqHqpqkTl+KThUL!$WLns_Hy5p$xeOW~?3cN48hAWeb^ zdtGV+9QM>1ipc35D-Xu-iDE%&Y}Z3ZPdBaEd2LoCCu~iGwUw2XwF(N7H2{O$CHV`m zmf?hPJoy2+kDoKIy>|Y*@=qE8D~0gizAeFRN+IF3-tA}v?$ZLf11A&Yaha==EK|w| zk8PHP=B@xy4RkRafR8#zkvQ*Z_1y({tI)nuZq?5oGlaV|=Ww8Get;~-(+CcKlcnP> zT+P6{*cNF_VAI5c+_<_MbZkxX+D1+V?Nkexi|S94SN!BKnqqrh5Z)%k7Vv$Fkh@gO zjNUC)ObhQ~=$rY$IaX>Z;5)-y$uv6lz8L87{KY2vBDEX`LeyYUxm`Da;9ZM4 zKJi@U*V25Be2lEBa9GXvlPf0}l5MJj>K+LY^Tt^D(VT z1#`xZ24Fgb@#slGKWU-+8%fT~$Qe89Ogs3k2iy7Y1(p$1*ETdse8Qw8B#@7v|F%C` zF2Y*d;WSVE5sjK-n-sXBzdEoYJCn|G%xs~^+ajN{^)O5S?5E<@!;7C1LGEV9q0EjD z!9-K_f~n#-!kLqY$IG2;z3NiP2MAMPP1!=wu<-Nqjr-V?Zweh91lH8loMOfir9J=L zYc^Hhq3YWh2&+l^#1+WntQ+uN;Oc$+*zW-Y%O$FF@2v@c_^@BmaAj6~*vqN*!z2o@ z)?x@yA7Gy0hv?rvKq8b@Zn+{Tw z;`X0VOR>ob&%RX6Fxn~A*MjX4>p(Z%*`?drWyp`L50O%=`RG#0fH(H3&B$uhFz0c6 z2mO@P)QX|ee1O2XL>OQNg*uW6@3mSf55NNXeU;p$#BRJj@tl!7fa8SgdDX(`7Ayo; z_9k$Zd@GLEJ)t*_ovdZ^-uK;BK@Vy}2m=hb7(K8RX%+?Zs(JW zRHJ5vs9H<4=og%7m!Ayu8Ry&XwerPV_`{>E^%eGhT)o8Gmp(I0%lng|Z0%-;RY}vD zkMlk2HX^PM9F~z)I}b*2AZ*1+oV+jAaIho$S-7jtY%XQY=Q5tsuqlW|Mz{qRem1UP zBuNx*L1iXLog;7wt=6C6TNL?dqNlK9ft-CsPLmXKj0Rh`d9%nl3wnxqE#@|?9hsr~aLy=`Si%u0{?N5qNxblXxep^<#;NQokk z(m9@WNtQKHempDlm!aTeV(m6QoK-!bgaZ=%1Di1vgsN(EFsGsTW#IX?g}cPU*-o<` zRvNO5dCh3L#M91>4w6?S^MRZ@d`o3&mQ)C!?I@3HZfhVfH_^rK^{{MlHpS$xUG!Ta zLjA^m%eyYvS^JWY$GaD0fZfv?Bn583Ov-niN#DgjIIl8~dBXLdhbZZFEHcfMA#Nv5 zCrxPVU*;aT#3GGXEh{$kScDR)SM&eK@H)EEIa5q0kiVP5u~Nf@ZJL~+k2=%4_BQ&8 znc_!;eh9|O^jNoB@SsEc6Zn|eH9CY8gQG3cD<{3R%%4*ct&6rt`47*3e|j?#Ui=U( zHF+Weea~{;kTY0-c|d?;u+$?gLFgGGt7&FlaEa7vD$+Q;6pG@%&#-xDAosD)_Y;hM zb9~?0MC?VuD`TUDYhdz6m)0-s-+lcMJeMc%i5-Qu+<E5K<0*MLGi^56D>E260^P093v;tMs7=+gwt zki}$hG?iKW51JPS>tE*-#*=yPZQC#zo#@MPMH)++rpkd^y>8K?6yMZR8)4hBjo%`L zD+x0UZqw4FYK8SBCxcnHXI4wZ-NRq&0g9DUoN)gZHW)pDzzM_I4@sm^;u4@`iw!9- zp+Ea-=-PtC?D(18{0bQ05CicwTP;Y&Qadm_JS8e#FATb!KJtwy&taw>Orl*;c;PpD zr)^6aLHmf~DXV_ITnnj7jf)n0V5)!UU#pX?UK?_vNJh4Qh3qVCK)HL{xhymIh~j5KQG>R%I8rsNx0 zksGT@Q{C_akl+Qz-u39g#Exu$aGKZ*1so24*fGCw58e{(PzoF;e2Tj|ZS6p?EQuIC zVe6Y(Eg14f)TM9P*P{H{@;f2UK&AdD$(nKf8e^dGOi}6W7|@bW+j2f9yqT@D4a|#N zccGURwJA|~zcTZw_?Y=Rz#1oN(_yaoA$Ul$6OXk;ti*hbD^aav7p_NE@$@B|77X_B zoN#OpM^(pHpi4cxZ!fyHED{#*qnD*qi0;G_u8>t`hVw%k<=#Zvj@acpVQv;o~M3D9*TwAA|46TALypZ zf8~BgL36cX7S?k85LW7_Ena3Q?Lz>rN=o<7>C&8(62-$|d&AFS!M%2;R~v6*l*qIR|CxoT|-9v@e%8!EH zd*R-dfjozS^fag44m{UiWpU4sn9%gUQD49nm`t0ON5vl)*J{D>R-e0Cyd~V}bcZ^q z=F8}-ozsiMgWn64{LiOk%Gx(D>M}YPJvGYg;JirIkJ~QTIu2zd&$6ele^v2zn&lvk zdsfqQ_R@yew>*JV4f9Jk#4`?AJcaPpk-U)Y+NgbS^a>}qP26)zxz_I_?-}EmpLzC_ z7`vlt&cSVQ`IA-hqjL(rJLu;JdC#C66_?%$jKt%?)=_i_GSI*L^RDGq3{EE&-l$Fl z>)jJnvYsoJ;YuAEvzTzH!>UhJE*>WZw3(|i38@LNyXk}Mi==RNf?15oumKW=mSSGO zAcHDB+mBOmzQ>g)81c?EmIxyZ&r&(Zp&*p0o_rzEyP#o`#8U{~)RQ#EcU!m?ryMAe zJaV|LJzP)%>He!Z-J`qu@m(%0N%xkVB#Y3*9hg+R0^$*m<>NuXRqtIa^0e!8OhB5f zp6@N$taX%`6a?$1;HD9l|11if(<#K!nRPe4i9|uHS?7ZGRPL-anbkWl^9c;+6aG4T zM?z5#WRhu_i|1WNS(wv#1!r}ZZE~tFGbrEnbdnSeSEw|Wmt#4)xGbta=hmViT|I7O z`#c7#48L_SiM4cUghkqo^Ioh^mqerTZS9FeXwgY!mHIh=WtE~(p~;I=My8?;V(sJ$H~lr4hCXpI5;%fw)8qJB!0B&==ElRjd>e$1}21N4_h zOaa3@e7ACWa`R!YmcP9_xNL)wdZkf%DDAk_RWE41*~dj%!CUDJnO41dVbIu%Zab5K z9;DnzA)gXOZ`6ERuy8a_>kX&Tl(L06sMMg8nrma!lOZ1{R(6fN1TQKjI$H6j)u;F;)ji)nsECjl(?uL#cUt|$b{9{H690PFi1SSm zgA;e53=$o;s*{HPlx`nd$njL90LT`;i|TUUV0xQpd*Im&B^y?S^wK@!ux%G6>4Zjf zochN;SxEV{PoK_QUHSF&$$rF;Po(v^rQ>L6f~~}x&S=_7r)BFaGaHdgDicaRHidWd z=rq_IPWw>+H|=W99-H>rpJ8tKX%jft1&04{q?*`@XA@R7jnO=4K$!dnQFC3|B4< zrv`PW4HE%pvZC+etL9(zz1tuV$g>VfH`Y7sr}%ZCY5n%+(qwt(->6ws63SJ-FgP-K z(ml3ZezB?EdQg-HG8bl)3ztc%~pHa znEFeskP8Fh%0n2nrdS@=Y7j=vzZ}$TK4KLRxcDLj;0+;d%8UBO+YskPEMW0IVtI4_ z9iO1wRt*!XfvRB*H{!UIGnK`-ZBFQJ#0O0#Ct-)4H3+&1rM7}cd3R67LXUdzkS|-f zOvY6lk4uOcQG%MtF%VD5^$nVTKVe90-IPCMnUe>6tW5R816FK10ysnR=hGEX^;a1Y zVSt)Bk|J)!!cx#qDWzFaSeWrHa~d61&giT3Ua3qp8Z2b7)3 zFV+VW`KLWNsD-h@SU5=D_|(lTDZl?Tt`hevK{-diJF48c*N(H=qs}Cf)gRqNyGF$4 z6O{?JKm63EN<=%LlI2|Ij=yWA~cb|namwiu8nJ}ETd3`OB= z($*NE>qPcu+Qb-`|1un}{r%Iz8#1yNFLR%6p9EazV2r1vk)U5>S9AF2_o`E%gpDN- zH^|6rnQ3WZLujGxEfs`P=D#5gpWrX_=sMNpJ$$P6!@W5J2S2?^{tiy1*(Jzqi3Z%1 zI9<6LD*tnEy5zgTtq0W2Lt9^d0O=~IK0y@*az{SZGi!8E-IIn71jy9(62H*zBj!85 z^@TT-m=c2KTY`gNI87Q+?K);F#!}tYC z)pj<#rh>>*`ty?y5Pz<@%nI;)WZ4Z(kdMnXebx4h8%!hG4_F$P%(kSZj;Gu8*1P4j zZ0*}wI`&bIZVk~#_DHtycfF+ansKo}_xPGA+12{lO;V?Z>Y!zhr+N<0o=NAbUCM|u z&`E~8yIeZ2AT()t)w14<#~$zSvG#RgnMRB-Q?3BKYm1`BKK=9XA)il~GJ`~#c^MP_ zAGuyX^?fpAcNnae+AxY}y1=|TB~fAo4wuWVJV(!O?_-sIlSYh&KP5JyYv&omZtfIE zaZxbul)1il_>Q?m@$_BPR|;+a%__zEW2=}qw&(*@6-HwUXhSJ9@$L-B*Hff$?sBv< zT0rXO3bo1oj;T(d`CaGwnl-#zrh;Z&vfYDzk^Ie60ze)#&R3%@5LyFOP;4xS2^UN@ zojJd*pqwK~svXiEu5&v1(V$ur$cw`w1NYQ&rv+C>hZq3a7&t z%~gIxG6l>qC%Js8&@tj{bgWN_C#2VH5{SiU5^4l~48z%D{%rcLYymKw@11_iue*^0x^C=A~PF7636S{HPPqc-`UNz|eQPze!`i->_NgpeQ((FheZdFU@;GVJz0i8&QaOPw7J1=W zOH~RMRkq+E`qGMxx2o#ZF?q%2a&OtW_wp_Jed%moR910s1`lXmC{72Inw!7cc3EZC zaJ>mF1@}_*G$>UA7}SjZK=c+emr1dVZqXac;RwWmuT4zu+srICTvd6Wn|c> z^NR6nhI7#lQ7mzPMP7G60)aVZS$^L^$NJ@fti=wM{qrlRo9a0XEx5DnBG>)}s(~rI zjngMBZ(Y{QOP7wO=bkge!!P<0IqW)-bA785T@L)XPP^E4Bc}YKWjeR%$4uNl7QZ(+ z1)!|P#>Pv_&7_cRx=jo-Q=g5CNG}f;x~WLYT9={h1&{roEx}jy1$|h&l4!h!nv+w?ddwl-1z8?4{ zgn)WBmIeTf zy*>nGlx;k^u_e-SS|^{7Ou?YcUnbl7#0PDWXcI)%yU)obnL&Y)@!e3bvSRxJDgQQ9 zt%d%P#N*|^5_iPhx9aW)Kp+6KQ?wkHu{qqYxn_VO9)K?(aZF3`%|{zWLh$-QTnC^& zhU=W|tARXW-LxQ3VeS&=ySbE#=U}-!tI0!6{*%Rh;Q107LISsd&o6e>g>J3tAdW{~ z1g5w`>Fo=>)4-Oe^3mTr7QfxG#cg@{Y9qIBup^YRWA$(VKr@q*#ntf{ZC4AZy947* zvI`0VflHjl*k&DcP1ukwZg`#NKpDbT85bCG17x)N#2))!s`-U9+D2Xl@_ie~d!+dZ zPcWr}P*|NY)*nL|i=2X_wOK;FWI(;8MD*=9p685mSQc^v^Hh%b%3fb3;9A}gCoMKD z7>c~nh^)xC*lfsfUb$Iqt-U$ycF}mJH8XpiQ(ZlKUG2vgMB=e;4_uSpRZz1tse263 zCgp?keSkp>5=t^be0DH-iORLtSfIBBzpa|@!>=9m>{V0wbF`8Zfv4}`p?~Fp7{=Gg zRcqmvpP#Q3NXR`YeoY4bDLTx*7Sh%xll`Jykl~}(xqAwC0^oW+0t4$l)YEgjT{_^h z7%Mg$!?Cbg&(0 zP?zeteV=leU&muwkx#W;ihw)ORTEzvo;TN>OiF;KtwiISUt&D7M0{Mj&-UwqzL(!E zT|5v?GY}=CUMA-pLsYz?<`8&)^V3322klwV-L}sWK+v&#W`fYN9&HuEAa5_S8vi|6 z?@5y*eESXrdYwe*aOE&R96m7scaO}vU6@@+Z5ey4XV$b|L%#Uh!sK2Y2 zClbFzZ`DeC@KgNHo1l9>2CeY-=9f>3pG@1x;4;Z~$a7ZM0}i~q z&@*{=sDBQI&w}LkOz45$AiqTvpR4lvo+$=tPpP zv%BN84xseZKxyih_?sBMd_lx~pc+wa zz2w`MHYWqVo9cf>_V+tIlSK?8iOOA!Q) zjDPU|wiPU{LUp&w6H+LaSB;>(x|#!T7Dx>tAIf|FlTV@Kx(?#Q{ZtjB8AhE5Pz90c z|DX!@rw2$|gr4Evx6jTIdC<)A0%oo7{1>PF8>#=(BC$vyJ;W8`YSj!E%<&Q8?%IEB=~h+z$IagT#LgQwPdjVRMx$A(bi7X(lpB3h0h?A6vt9s>{^CVif#{59j>|ObLvo!8U(wA5kQqP|$pAd!}K8 zZ1?|?DX5R3FNn{*bj|!d>BYT7d>2ll9UC(3wN8G$e9G>r0brvF*oH~}AM)Y}`B|)U=j64^gbjz#EZTnSR`QlOM?=y*g28l}e{x2?^81K{E9sb^o*P1E}Ub ztmHOsDMa_-x}TxM4Q@ zDnNSHd8GDRr$_eOsUR~?k;753(pAt1mOo=w!+vdSQgE(L-uH13HE-YV+&GZuhnV|kUZg&+)vXpniws`pUmU=6=X??kzi=*L>PJ6`4J{%W_`QkBm(Z0n z4x7-6cfR-dA>W(01F>>Dv#x@eCq+>Q1NuVz?d0;ZD8dI0$qtFH*Lc?-Gsr#A>J6|- z1ED*}+7tW)SevFLGD;!n_ca%T2<|fwiz!iM%V7S^D@wCb)(;%sR^~_-b1JuQb1&C> z293UtCp@vZ^!*wompCEByplUJL13CMQ&f1_bq&$$tjWFi`qZWlW-B*>b;~Q=bNT?> zl{HINh>iNIrLPqIjfB7>Iv$Y{z)MzSlZA#i>n#j`SowhuOLit`Jtadaq!;$@58X9MX-`Kr39(UkSS z$mTlo5Aw(}+6&9U<

nKDgE|z2F)a^9d`s#BPB+B^hU_{yWNh4jF=^O8`4OV9e~D z-`=l*l+^15k!6P*7VCv)(}hBlXbl~H1qH_y@ zj~SIH2S_EO7>8jAT=ciidm9ddMY*!C!M(G2CXE`_fHz zlGjxq?~t@+`4k*$#*6pl&b+WXYRP<)ek71DD4&Mu7mMVc=l$rZqk85{79SWsxi+IlAMZGAJAKf(Hvue8 zh-#!mG$yH?P1@tOcA=IGPa09Kg@GxQt)*{~rn$@wkB~~(-7Fbiv`pob#f))~G?M__ zjhE*y`jHu~je*-6v<)DLly96m{Vxbaqr?8-;NOSzMVSNGH8#XpY{!=-Ra%Em&vB_k zf93A2gonpptGd8Dt<-IJBru8lsN19`NWt~u7!DE)LBbd!>;rTshRATD@FGdN_2fIL zrzE-QHwDxCGpw4gT%=ZVDY?~bBiKOOV>9ZYzxi*@z@jqo#9bmN&S_{0loi4_BEzv< zsk@o+U&_I0{b9N$-7gRe9LpVxI&vNBPk%mb%e&nE+1)}Cn)8$Tld#?%0evt4>`QYO z0c+XdcB_<}=ZFLLu`&G3`O{9a2I_WssoLwX&P8#&JH0Z2=z6*ly%FJYO3qvOI(~y) z649*#Yc;@pkrd$%)a>2J9j~1|AX;a4?d9STO1kUReliBQ-x;-ZCBN4|BzV#sU71O@ z3KjTln0pD0{2skov201yvKF>s3c^+%bC>~6w3$v9<$b^U*n)NAE`D)`5LvcE_`1aiHx zL*{DQ#0&YL z4YdC?HKEqBzK`!08-B%!Oy)LD=+ehVPbW3A{EFAc!nk8Fe_k*ct+=nO4D^H0a$Rt zQLN;f+QslH@zS9jf;5j)qEzX5se}KWy?-eG#}9}2$Iw;-vUL^CvAmopiC$S3LtkNT zyAN!z-1<0%S60enm^E7c3mDkW*DhXV@Gk66`F`+E`PO2_u;i41Xp(3{=G&v;94WZd zXy@gpEb<(d4s22$K{>d~s>IM*tj@Fge$JhtbD?6t8NLxXWovvS?gm54v;bblm!2k7 zI`m=Vzv%z}L1x(?%b=S<;E}A(vgcrE_xhyi(avV3q8}_1KlDP*2-+sa7S7_x2)RGGJZzF0MG{3VemGN0pQ3i2inJ!$jlY?()74!Z7%Kns7U^wdFdi|I zZ7k1y;qA3}<-^Y3{6Knt~XCh46O2Tj};w%T6g zBn`DT!AL*6`|x7#zU^H^h$ypAfWcBFCp`ehMT9f{Qz(A?BjX%TJ&PI;AjF#q-#qDH zGW$#`f*aR*3cWhy)DN z4(^RI?Z=E0ClgS8s4{W;X*Gt11e?$X)vOfVL&7ShCgVj3$4eM=0ST%)^vHAJBaYeN zjU<;=5>_`7kFsVs=(M+QQTs`#5zSiqB8_aqhjxXP43%)>!>f2Qx188rR$`2qHCz{A z(*F|An<9U}&XY5M(goz=dl1q?W;Kfd{-rspp>6s$Zl1MR>1Q$|x~2F{iHby+_N-Xi z;X97u3M;xiKq-)n!^8ZimWOzNDt1&9hjxhxp4mfq<96c3U3Pxt33h7+k`~L&C(ut4 zEkQZ$PXcKNTM1v7nQCPCC%&*mu^hZE!C$x{?#0^^wQEp~_F+t%M2B>W_&?}!9EHAtLHH0!ib$5C^LB1Rhm&d5o})fzRMnO#F14T`HnVLMI+Ot#6ZAynDlhpu;0dYNkBX4X;W}$qJAlgU8R*p0fFEH=fO^ z?5v^W>rJgU>eU)N!8p(2X&p6PyXSwp!jpgG&FBBi z1G>FW+J;y@O8B2i ztPT=>zWz0JVirz;ua+ICL&;A}Tq*??*C$!+z~JRqC=ld$VBHsu)zrQ<_ZfGjN8YM? zJ1KJ2=`wz}Y0hhR*HZJY+a;m8Bs>*P`Ahfitzyw-tWGp>Vp?k-U~`eUJ^JBqMlnnCr(B0}M zKf?U9A}PDjo4#u5B6B)mvKUv))}Rl4NO|dN>h&Vadbi_u z3fn)Idq_qrx|J$*A7`#*(jSbT(wHoL;bKKpzQnw7@0{7&e7DK(Zrh+Q%WANouul5c zL7Q^i55F+Q73|pO8CCjtm~83U!xLb~`B3T~)-^>f7$Zx^oh@d_9W!6EAAhFkF-=V; zp$N~C8W~eGlM(24BU*6{)oq1AGHwSmycaqVeeSjeY$BNdiu3;^SRBTl1!O4PQOqSM zLn{)!bN5d;LLjrOJSrZFf+u6RAub0Jz1+fXlld!Be!bj<)7*tZe$qMrVXK~RHLSAx zl4xhU0laHC{F*j%I*YtZi@~A3V=@XF-p^3sou^{Q$kB()dT8e3AgB=lTI~M=TDbp1 zvrL#Zv~58E=4q=qwV}(OGose-{6KCU7kM9pFM*X_u_UrT49+{reH%Kn{zI>v@?dyQ zLU_Ah;~P|>xn>E>Qq5pR7F*B7Bv4u_VBxeYy-N2xNx|w|m?uExyKggtp?skZ`Rq$u zu)s?3jSYQ~4ki3+OWd%LD9EpCDvARirGPoqh4PK1LO?X^mnvhx7#(7d8IX%J%uER= zYzxW8lhg7!po`Qbb?#x^VFOhmn^atQu=5dTQ~$#sceHJR)fduMY9_3K7N5#VO;}K_ zjUl$d6X;B>rnzpW{>O~P)PpkryHwe1$|~!%XvYqT!-ps}wexl8PHvbpcno(P9NRk6 zr@XG-)5})-WCmS)K^kqsJV9U)we50q`J=*}6trY`)7+P}0NMvY_>rsJc!n;EvWo|x z8@t#&SSBn;oDa$BtMHuByI1S+=F+80uNOXC$|OGAetYzV!ETQYUE+G0+}Fy6tID5v znf_^eEgVCO>qK^02d$h2W?3By0>_QzfZ|)@l2USr@j2ODvW_6NB@5x@Q=akLlL1BW zqBl2915Jo-c+t=LHP-{|JIkja-DN&20Yzl3#B{Py-yA+?^4govbI;dwbxtFLeSJqJ$rkn&V>b8yj z9jYnt8uab0csa(k>*Ia(RrfHJRlaU*_erTC4>ReMDtVb|Ppg{L(Jlu@06qTO0NuGU zsb{04Kmsxk2p^#Zr^ zwY~0+e_(b+Zif4Y%ai){ukUAB%b?%oRfcOJ&XO)~I^WXAW|qe{LD~Wi&~&m@&A;jK=~TIcSmw2KH0iVqQZ9 zFx*$fy-*w$C!_a80n%)>+PHONG(yC$OLHJD^dtv!y@u!F0WAg>dawcfxx_?uiscQ_ zm)iTEO7%$>hqRyY>=dzYj)6N3=0Az;nN!eFBwq9tfBVl}VUg0!S7r9Cr`_3J^-zX=>`f|Q5hR3{`|1T%wfr23&`e^$vESF&cheo4~ibM!I`p3pku2cYCgA#kUB)pD(n=^W#l{&gq6H0hL>KRf=Grt zK-(|0-b;^F96<+1>(|zh^n-jfCNGr0v#K zr7J88R>2Eo3IMh4F$XQG>-Qc?rN;Ovf^3IZxb(Tra$qOfMY|d8)G*s$5YzEc5xsy! zb*rdfD1F?5S=`2ftTu#o?p?LJ@$90{2zH|OwyH$e#@f8&Bwx@>cn;P_Xiwa?p2r)w zCmdZOwonuS$YCytQmah5_q!Rd!b*^i%%TGGv769Yb6H)c|h$bQWc~4#P=pW{p@*?ZB|-5abw6shY_I<|;ad zn`M=rPq>y0$r!^KjUH7|Wc$tfUJZaD*)qx{s9!2~0lAQb3Jk?}Hqy6%gvepd2%xD@ z6un5x5Uxv1pWB=u7dwHo<7_zjipsi0Er`akZe*pEIfT74yj~#b*2P=XGA7Egyf_5J z|0UP?|8>Kv*vCQ}_E|2#OF!%WJ-1fEQvKxpEW2yb>(=#P-AYRI`OPyOD(`(Yt)Q*C ze+OAQ(*_W8e1-5}&=nGAG#}v%_6#E0dchg9`S#%QXPbaapq;mr*W)IXxe3yheg#osG^z#8o zE{m~zbLya?~4%V%{ zIV2m6VAdIGI!iS>$MW{iu+D#44L4<33~cd#8Q$gLaM=lmN9*yHOO9v;DLQne3BAl2WA&9JaTVjcrM00SH=} zBoa&z-+!X^!UECyMWx0x^ymFsp)Ukd$`01ehbId4)TpCB*O9vQ(ig9^ONe&=ysEq@ zDPm_Zi-+RNLd9%WAq3-Z@*L2Xn|JtE^eUwj`9$+KHVO)vjp`-q3*c{tv#kE5Af@x7Z7&2(j{$d)2<`1dXB{J1+9$;9G znGVv&Bjr00M1+!#$*H`(qjFvh1^!vP^RvafKt2wIxfUej}En`F{vG zpvIfNg)^~Tvb>Ho+DFcY-R}Z72|-7;;P3r^!j7%v<9qb{!k@wSf_vWQx(Zm_s2je9 zwC!{w-28joboHmBNwIJE&N}yJm%qP9GH-@;wMMdRF2T3@q|aqq46%lXl-QCc`nI1y6?_;bF3Gwe?ND-7H2+16J2AR`*m~~v<0A1XMaXR><@4t7!dD- z?3yG|)UI?_T}}qDtT2L6rc^iHzvD%oo@IcU9=pS*OR37s_s5VGgSQlEzZ4RHi*$(~xGa#R32e6{$uvk-PDv zJz@PvTfEA8@Y6N|i;BmS8nnZ@6#6kh7GU%fvEcfI{}RhA`NxA0cZJaFE4EeB~`kJ=H6dAZ^+zG zllTY@q|EK(hehxuPV=By~NXeNDA(1XOpGR}T#?frPHeX4(9i)G(l}uk4jn>^{aY)XGTA8)F;pUx=VTzn{h;MTz1&CB4~D2l3IueMlm1Jes!gJebNCOhY7 zXGPViM|PKr_$A&Ny?fifIymw<-(&io;9Q~t-SR=V@Lqp|eDX#( zR;ZHcJrnajunsDZYk=N(B<=k!KjkjmH3jtEi%E9HpM))9&)?w}>fc}_60?;gdsv!N{B%D_c zk%<@er@wUJ=t>NahWMZQIPh|orm%*J4_T+z5TTRO0Ay~cP^(RI0s&BciAe1E0&Yw; z(#)Gn-ebr|C4AzKA%ENaniSRLV0gjoyi1bzlK;Zr=x_KOsi-Xf^e#;^!yeK8q~bZh zyH!<}ddP@cqrUx}d|~paW4D|dBe|q2CTcb5=Ewp046`dL`L@3B8SG|i@J`u@y(c>U zeUCBK$q{BTfWOz8a%e!=ulDiphcs`DSz%m_A1wLdw$zEgp1TWv<{J3y-s=WCigDKc z@T@dpN$^M5(o_p4peP0rSa!O-7My^rsg)-(pc8-=qj0Ffe~KdQK~Xnz@E~;DZu2LE z-)|rmC~pv_qIgA*(SYs3`6yo>Zg7&(8JM48NWi@?8NgjdP$?yIL$;>^I567nY||Wk z*4ia*K7MUdylLxQVa+?W2}>njIqaWat-IcB&w~@Xt~S&NC5c1@O3GH-p}lVLP$Q5( zq7R7?2afC7NBklcmy;-K%9|J5)aYsqyEvh*dx#*bd2-2SB;18{ z%fO{M0t&niuVj7r!bW-no9SChE7_#Onir?4lR*;o&uu?MT91q->%ScKurnm%m%)Hp zDNckN;UN}v4i_T&8@G#_ zZRUkeHlcEpEC*<--c6UbV}XeSv2F$_xFdH=lW}5bJ1%i`YlF!L9h}S=j=cZG3-g~g zEKjMMI9ivvhX4wtp>f(40CmBT5DtJk@=#Qc3w+=nNwVQ5NJy1_`><9wp(R;rhS&i8 znv0HAKk|$CcYyDAvv=oYmNlhH(+{Y@zZfXShdjh>x-Pwc*`$Zw;GzH-Zaina!?^Yc z*!N{-*SPMEHJxVmP_Ffbm5$g(HNxpm-dOhRb9muEbzqDf^2tY+x|vWfb6TI3Z0-n% z8JH>n^@21W-39vY^^^fU>hgRybaLG`Ql?BgL#NJoHPuhdk}QjTONwlRt*TrHC2i0^r#(F2QQM*vu^{}f8}BFn*ptv*uJuc z4jJ?8yhm6>TYaT|!en~yf3HrYVtuy`GHw+qA54GRzZikVuRbH*=nk~C;Rd@9k>_=4 zJOUxg8SbjFjkO1GS;nKDv!rY8Ni3rvz)_^m( zSE|zrX3KAbQ)GKJ`cfv!5W(7^A%Uqm%f%mBb`ZYBsNHsmS6~wb2Mtc->VSp;o(}n) z?$AJ6JmIe=D`*jCDEpIq0I3)}?UFh)nVGY=+XjGQ)h?b7+GJI>0#K|N+F=>Za)P6< zw{a3ARcc^+^0pXSWiTPS9L%2#C~J!a194)9SVoBDk3)qA$>`q)EEQCI$__)SRM)`P zIrg(FQj3pJWYTp@1L}mmOH)7`#B}xdy%0UUy!IkiG;tz?HlS@gg0JcFX4GB%P5<1L zHky!ZrCA=e43h{D_1At9DlJ|bZ|0VTb4yP<-TyT?ttO?{qWeQqLl1PO^IEb+{dHT! z=6K$0#+s@rl^_dEvdJCdU29v?pZ#EkDGL$Y6Wkj@*~mAT9f(l^0|GX-HkY34yl+2W zGj8q2=xV;`cU5;TzuE8J1U0R33xEFM?gzeVglp0H&DQG*J);o0o8_JDG+_YT-c3=l zAW+lN=l0TVj^BRBTpBm-@HTFut~ZRO9-B8S8H7o{HTscWU6TIOy{ae8wZ992L3HGh zV%H8*f)^9P-5P6BV2PE)ZIOG0Zv1s~$`_wpjhh@MQ>6Ot6$*WV{u8Z`l4rvce)1Bf zcIURz>)g$O_KLf>GuUn=h8w(?LG<0FR58-3hGnnm2icRw5ZjYeTwqINa+@TCMR|R2 z;x$iB|N26F083u0c|9fyu*=;AoUFf#MTv}VYKkkSQeSylD<~sxf8D769SCveNfs~o zUOvX>ZbFA3QRItu4y^b))H>h;iI^fg9zQzh+c(4?nAnyMcL#4gS7|44-{IxD(BC6* zXv+BkIW*9ieG|(KYrKXzbYrdLpZ;T)1rZTD&#%XE_c7X-B2vpp z{4YF0T4kHbzU5~`=GvF8gf47QYudG2{&;110WUF0qZl;~;tW|#KK#;9y&~n-E*aA8m>RY8j|AA#FSP)Jt(SLRmf7gz6D_@s-?y}8; zUu#}lYV^1^4B8LE)VbTbufR)cw!LIcSm^W!%+BsIe<5bZl^E`h$s-5)-c* zX>6u6)9Qo0OKQv0M-7qhVKfT(A&kAt^4CiFLPtrDouhT;^_Ri);5tvrMEBTtZu@J^ z(;L{XU)`XFriV$v@QtUw=kFHQ$y^u*D66+UQieXp?oH=KS?!=SRs79sX{qYuQ0Y z^t&XE0MwmvsZ3&&Nz)ktDDAy)K=X!fKmC!lXG!qRGUnmFsj>C3+~5={6$Q6w_6ceJ zDd1=+u43(79f$Ggl6~d&;+}ray)vv)3cYX7e$WQ|ojOl?u${kk%lSsAjM^HJy4Ac( zJvq4kZq_q0#;nUGN8RF5{BM#f@qSPA6TTy8U>$?`vg3S#wq~&(x@`agz)$GYVN(n{ z!2(_JZGFvPvo3AC%c~lEo-)5-ramtkU1ft~hy>IhG}@>?l9b z5RDT_#7UwZiD9mWlP84@Y?E=9{Ive4t{{FwBSQtSh@9mgs-GzLtB!#+0Z&p zywt46SARvC2+7$ZM}BmcFz%$u}qRN2m{s- zOopAc4||1kv+yi2`b8R=ems*X>8p54+Qd?hGfrEOefiQG^_eJ44_WDYBfoG?OH9W<}%ZWWhn2_5YkQ&bee*VBm+P1{A&S!kOzD^jz#`}GFtd*-@ zHNJoPGxou}Th#F%a2=>Q{k9W}z)EJt0`;X=Mu2OOBlfFV*Wg69D^@V4qv7wg?Esss z7vr|wn#uuUQ}f#(j*xKgcdSaq=K#@br<{#)@TCuQA3Lp~XJqE~y)$C`eyT!i6LU*Yl&h2!m8qSJixpG5s$_anL^!r`ys(cn2* z%);Q}m0KcLVMSqSfa6MbVJkjZb#0fG0x!8Vnm@dwto7yESnX75^VDdOH77JiOgQOe z$?jG20_SP&z(lb#d_03F$=g3_bZ&{VYb-=j&YHO7JAef207tzjAg-)TxLSG~G?)c? z)3+vyDPdB*C7*}$ql}SXlqA#`jvG?|#I2dKQ)r|+ie5b`zuV4=NBA=Fd*jHtLGNIA z>?-=QkbbSEC(T{FCCmjE1!N2+p2?QOoN=fm(`@=D7)iJjFO^+iUDgP+Ezq}FNkEYE zR$T0C_P0-(Hdn8n05kx9_q%t$n&kN9{3?<2{{q`DPpQeOY6g~dDXG=bGgAFB4=1Jx z&hB?EX9<@iy1S`dDZW&uNa=B?v?j{up9hceIH8S6IOG&@%(Cb zaC~8-f-y4ki8mWb&_=<5hh83!J=jP!%wC1f9=m?E5H+uUQfbkqY5r>6L0Z6OgvpH; zD@LL=q1TGx#1ya7yZgWVyQuEa@3)?8URxQ`f6u-gqcoQgAlRKhOJ2|!wU{%(?w1*< z&;4D3FkVHiJaS@z{hUoDd(FgM@EUfv`kvz0pW=-5%39889Be8gKdd8_d(U2~ZS2pG zaSrwTTeZe%*=RM^Ezq)A)it+W0~YXYzsIE81Pi;o?LTtar2CtajI{eT_Y|^g%w~PT z+%}e$pYcSYo_JJ^F)5N?Wc7gHH_CDFOV9>YFMKdJ+xThgm!oRtjZL%Lhk6&Krtb&< zx^5$ND-Ve+n<9tH!^d!=*C_yaca=+k2#w(k`e9?Zg+1=LOTSg60rbsTotPB-^lM8C zTkXY1SD3x?zl5sPC-aXEnUgE8X_H&J3FH^`|0TCyT!R>DZ#%y?`+P5XVHVj z3gE9u0?htKZ0JnsQVRilqzrGHQm9-BZF;K?Z-_`q%ueC@l&{WZuU4Rf7pDeP&L{lHg3enwO{*7zf*WkdkdUNx+9 zAzELk`~zGKZo)oeK|ofiZa>?GHkHvADX%B$kZVjiTb4Y>b$J3m((MG^kFp*Mw5^fz z;l7*GS2qmU0vAZTmU_qedZLi;pwE^LB9XoWUe6m2oWL$)wYDImhXO9_;?^W5Ov7uH z5%BwBQx8Yqyx8@e@I)J}?>9Lyj|Ow@0heH6+vRgsY0$f|v*nj`knf$lMA?$> zJnBku4iy(@=&>o-NA{f`q|zMDQObO8O~=qZi7~&YT5>97br){r?6cLajfHK-y9V6k zp^pkIJO3Eky^~S{8g<&-eU}%2QxaVflI5ovT7&T|Zx5S(eCV zsn#=yfZrNDG%-nA`{)`+uTj2n%xw>|qOENaiTB~qplo|3IeUl}x;+)-&YSpj%w=!!$xl%zjThhOO z3PPoG%YOe%nd`*XX?1kjSOv8*&g=dTzN&e7>l#Gqywg@mvU1I7n#kSv*f+wyiEiGi z_4)zS26zA3IQ8_Eyf#+bGRU?~iTYHe9MZIS zQC&m6+Xm5^s?nfE+T#W$cV7_4N;hX_j&+!b4LjsC zH;+?CyKaG9?ksO{JAVxwZTO}puX8PBx5&`?}3wj!RLq8ZG zD19H=juIt5bZ$R;hFC`~Jf0MGR+#=yf4`Mmt=ns2ZIw))V!eTKzOb-sR`;y75VCS2 z+5itJi)QnT@JRXr@#`vyDXIEA_UwYo>_@Z0$iUzR@@E#EdW0=woLjCRMX|_ixd9k} z|4KmZJpcR9CDt~UC=A5)X$drU@dUe|p*1jhV}j$@^`xaVO-uuljE$0BEq%vbVu}WS z-&;6K%l#6zgZ*W;=op_LhMT9k10VsQ{XX}A_Px=oOJ{j&#k}H;L^HSYXPyrxv1RW4 zU!xnED|L#L0&kAX&yfpnqFfB6N}X9A=VzEO2;;eQhZ+4Mz5R8D<6O{JfAqJKki3*N z>UxCe_^iYMV~vItr#yCE%W9lEA#XHP0EHHI9UouuWeyM#;$&R7- z#y(ih2-hIri#natpweIWBakig10)x9{RZLJ<&I$4fMtEG{bdE4MBWMNIH5U?iw|P( z?brp)^WyJO$7SBj^5vXSm$ne3nfqyurEF$boi}}ov0)euc78og&5&5U!a6E(jki8^ z!_doL!~L((XLRwC`9X_xiM+JaBbJN7X~i`%9>XEFwNF?)zDc63F26|S#4*1qmcMuA zG@czWKxY})2Ehz$9l66;{8+(mwqBqiA(lT;FT?6K`DnhAcapU@;u)lN49D&8wv|cL zb_V1!EcaKjA*~w?rw*w*%#0B=A+`6QXA3*v_eSezk%S#)Z9iJMz|yUf3_s=aT-6l`{NXx?@MzV{iUKQ zIiaCRUfQa(Z}F_py0M?pdLceZ{LNN~S!#!m{l?<*ao@iQ()B|(G>kQ0^yMWmh^XI* z@b@9NDRA0(n|Y(34bFi)MjaFrkkWfxC4X90mIbq04+9uc-LFyX21F~ zxoXd-&D?-V48;Qw-LAe!jqXhOR=2tF&Do@~eUpT|^ET#>2iLasGl(xYC_;GO{ms{G z(HvA%PiU%&o1ICiw`)Ok0j)u1-<$GfW6dafEBA}Ia;OiiLxjj!4l`<`*9DxSw2&C5 zIFI5Ht3SV%auzeHt8Rvyo$;nQZ*&!z)Y5%xJ!sCJ17LYV*R1I9USRe!tE0z9G*?Y6Fdj}KgU41b(f_g$O1{^pR`cv?0))IoDE-vx~@#b3}jK*o^ znb0WCqk^bB7x}E{_Q%A=N0K z@_!0o&zHy_TtlvCP*0_v9qVfdDYNtnR~xe0^-aO8-p*?YSpE zVXH7A1xEq1ENm3B`|uNZWZZ0BOVci9L69e+#<&4HrLg=Mu0quVq(BOIaK(^rmk0P@ zf}e6I+es}ygAm4W%9O;0W}a4VmoQK$5~sC$1QQ|UM;q9{VZiG^rFP&%3h@2ueP=)l zt#(PAf4+BWSmZE>$NbW4X&+onV8z9JzQoe+-lw|d5fwnR~D#rZXvU@#@(<liQNfZ^LjuEQt90)aqYE~-y0wvX8aOw>F);Mx(x;n(OD zmbOX_2ai$pYwy$6uaht23B-a=ri4Y`I5lc>sU+EC&3dsVTnZHw^z6n~ zdpjgxE=Nf=c|sQ2aMukLTIAC7vv?CzAaZ^x?Dj`Wd!JKj)b^ecUZX1AQ<+9Ac@J!# z+YBuJ=UR8b>SsK4{NpglLWM1y((AeUEMi*%?6PqAa@|*xAU#QVu)~P{W0S{7a}sh^ zUp@NaN=p&^Lu~i=#WSMhH_&kLDjC0ZoGBm&9?@&&n2{#538n>@*h!r^Im8L=8Zf(B zPB{Rk?;w!=iu13qg&gNA_-k<~C+)`jjNac78>YXwRuF|#i?S%FOTIdXj`zzG?cxD1 z%b3Ym-TG__cYgQVJVH}hk9Qd2M0kzg7|>T&Hoe63US;z6|2cxPThAeT@TdmJ{loEj z0{aR=F5<$2!r9%OlE*tA+UG?@z`Pd_cGlAe=^;m+ZlThio-LQm=GlMN)Y8Wr3Cz)x zV*WUc9|5l2PBLJL|371zz<_Oa41s#RQxZJvXrAs#Ls zl{EI!)S|sQZGtjre3AOv`&nPj8a*XA;M!@-wDP^(6os$11XTeke2eoQxxyqiFE~Xx zc*WzTXZFMDIg+8M!p)Eumt$w+;0Yd54Z(U)T2H@JqcL1};r%}J)I%P7^|D=``RE&? zJ^s>!&=#i~v}U=zxtGboBd{%tJ;LRSbb>pfHlg}-&c;NJgv_b_-C6$;g;%pnCMK1g zQ#PCR+e(_tqURFZgXk-q>fJZ0h|8Ib7qCl-oedJ`Y{K8UQ^M*UVfV#>WuJ0^xeozj z=Aav_`~Wm~3)g1}dJDMhI9!wfPYp1w>cDnrta}fPDb5^@r4A{-Q8`z3<>O2e+afR_ zb-)2kL;y~QUh@{1#iaxv^$x)fNXN<6#Nel4U=JaSNl@Wx%W+Ly8yoU)s_n4(EV4aM zQ{Zq(%EM@m;N-V))rvn3CT98%hSPpouu$@`nWpvN{s~)Ho_iV9Or=S>V719gCIH`a zpyZeAT}U~c=XcMWoCj&oWNi!q^&^v}uW?tchY6dy}Jzxz%YPAWHgIT7?AU>$ej zoyO%)6JT~qmHeR<7|R;>XOV9|@0s3rOpeDaV3kHF9umkEtKZ`C8Y zR^6;gXwAPhgThK2*D7Ys@Y&*QE6SE56M;H82ekN26G1vbCg=1wXZaM*h0X4$e9sbr zqlreer7ExQ#DcE%H!I~!CYY|Dxo~{IxJ;c14fCjuy6Y*DZP>Mv;;-IYV3O**rf$P? zs;(&5V+Ye^u*L#izLDLp*;bcFhJE5=7AswASkttSfCCsZsoeTE!g}$E)#pCDRC+O z>ajpx{gKbHq($l#+ZiVIU{0$VP)_fKtV+#R_;Bc**Y7&-23hL3wzBWMONlD5a>;wf zMyWuR+BI!NaqBixkIhZq#fUG1?IE%1*2Ez@7lWnXXgswHn14_T#9|zun*(FWFni>e z^>0rzSnP?{562|pwhFfZwV`uFkOb~WtRP%DDd|ASi(VawYax%W{FQ@UqM?2 z(MPl0nP$FkPn!aK@d~awSqxRi$)M(Zk_!;MfSbqAmbhHo!ME19m2iHe zo~^&!Ya`R&e6L27{xmgD&%M$MnSH#RR$7?5JnAaz+FD;FPm530S#HU-P`+2U!y{uJ zK;cV>8+(-Lnq@!5NZq7$G|gV@`8)J(jx#NiR_yEe%T#mQ^%tpK)I7E1H|1^cj6iWw z{{;22Q`XUomuy=9AKK0`EXpo=_b{|0452g(4N5E0-B^G{H;787NDUp*NT?u<7zjgy z)JO{oNT;-Pcg)P$gYWyVbI!MOK6s5N*T6jcdG=a+t^5A1y!+b85>D0MsB@&KpQCqo zD&8@2XZUFrido z_-o$>vd40W=IY;8+ z3EvW?mbDKH89vMssJJzHyR;%04s^j`6zqfCn3eWkVYtxU0)Cl!-iib$L&T7b)1ihdW=&MiN31}LaA== z9XZ|9hl~JFq8VF%yIXD z-EQq{Aj>o4`e|G0<9yjKGJQW1wm)IU6cC1OQn5GEmQ)=0F?_>6(22%FGezt7-**mH znQ#>N&vG97ItYKSv0|JL<62nJpcX#da@=&Jk(B8_m*)Ci@Fo6~&nI7}ZZ+4FUp}>)k8>3}_P-O5q?!sW zVyfqS{e_oL-!yCrPkI-L{kTaPncidC&anQzkm0YsEd$+h_L3LKSF3OPevvEJ#o#zU z`{h4Z&mK-3g}J}iT@E-&5o^%8*kf`>v!Lv)73HwBS#N(v7yCDsB_}Tum}{}bxl1O1 zg}F$Lb%c*KqlMH?nSpg!6IQ$?^h9_sw{LEA{ltps)bkxM;1m+CefpCzl7JbO(C#QN ztigodmLx0(upW=;)hj!7Z7&*kdS5x<-JYW+O$+$xCe} z=|??MU9RO^3pXmssT{gd+E#x3d;gI9?Y8J;Lj``?vHpbhRhxy*A;RJL!R2+1@fhYS zHZyk)C6+6q1$<0jy&OyQe^VwYCRJd9&R=B_k$hh9D(#~@>Dm-}<9TH`Fv`Ygm-~lG z{@XnOfGM^FHXsDQi1Ui2va;jSk;h}Ke+9q5F}6Tlgu6zl8~dwpoXcZ~NAW>BYs9ax zx#qtp7xKU5U;>1hQEv3t#)%smqKKK8{jR z=q=9CTT+4@>#V=zfT{Aeah*CP{K|MDi+wgH|5$-&yByoeG(z7_Kg^7U_vk13hjKYX z9CiMjrOL{g{sit>HSlL#GyKXn0ET5&5K#_`L<`--IU=;vq8nm4f8e+YPi1CKHes|B zh0jIrQW8Hh#tu26Z$XUa;g}hC;Zui+rH0mvGP!FEgek&ij!^%P3s?BzKI^uR8cH{w z^3S+95PVngvfh+F!(+N(Q-BldE~@jNhA&n)T)tHNBKDy;4}%4C zGVvpcq?S22b*GR&Oo$}(ygV(+58yuM>Z|&-Ko%e1+cunLfWq#tOGWt_!nWhbb{V&& zW`})D?Sk}Io3GP)kM+}^9PxOPYDBCWOa1Pr3vut*gz1=d0GV}K&i=2)54_?RhB8_s zhOhPcf4KaD1LpyXft0U3uC>e<=JUst^7we|NFIi~qiD`Bed3@*%kRcI`sM-Eq{4b+ zQGe8l+0dL}6?`V;eo=*B-6|&2=uNGzpZKlm>9&VX@i}SLGnX6j{~Cla>O3KwOv5#< zzVef%Nx>(|@`G_%i*r;%3)u=dUm2WhZxkyH)j}!!De2yY^}8e*M)}5P%XVXF6VoRle45<|#U`z8gn_ItpRGnZR^Zy}RIw-C z8BKM0`&4mfCGIV&t_iSfN$tly%86x0ctqciVVaWPj{!{$wy*{&NovHqiNtq$?!Qhg zm!C~gNQw0_5!z7-+mXZ?Xu5hrv)H7t-*FawA}DP~p4O{GCvvCKjy#)_5w5q+(n5a5 zS6EzB>X^Q4yPE#>biU5Ji*QD+Joxys1?SEBgPG@5c*+edICy1D24I{lOWNoB*7dm} zqpG6*dttEWnZ}GVo`r+sAi0trwB^7NoU)2>MRzRvaGa-?ptj8x0uA~4HDrsPLm5)r zz|j;K(e}9un7~1~6u?LhI-Mzp-o^thE~$4w1d~UIi%P85Z&WRBkBb#WI$IzenJ@KG z8;?0Jy#(?VTTLKM780DCx@Tupq-17^E7gdHxyc#Zj8HK!=Z7u)#>M8gr!hT>k?zxl zEUwpq>=&4@|CqjT_ z`>XMM@Wq7$RAv198m*#|D~1!C>>yv*kCxU!0ZB`y8C(oxoc95lFY?kiiWKq*HA}WC=(|i7i#x z1{W6D`1)|k1~S%JPS#C6;d_2UUpwZcQ?uD1tRn!%b(EFKN4&1)`{i_M5R;9@5&Oh- zeaz?79}bYyI$Hk{)|{wr>kDQT-_a@hjnv()##i+hj9O9i?kI37A#n*%_91{RLV7PygaRx$h zj;p7!S!whsZC`8haT8264-D9N{(#xYPeJT_Wi|&S_|Evwr1?=f$C@4ym zxGybs=A#K1d7ok_NWiZdFRiTR8NL^fqESj_pNLH^X%VJ#SAgZD#`P&SpzXWT z6C7j64<~_oF`sa7)=wZK!%Y8|kQunajt4mnBwkkYU@;zB{c`tK&s!U$7U52GQScfwqDXN5~~lX63-B; z6XP9BeajYSyiT7FQQH;jQ=tVPqMg{rwL?~d%w z!DZxB`nwZIJZtAJ2_J6?1=_f#9CxwTr)IL&#Gv;yK6Grvv$}q8^^jhZuq|l7%M0H* z!|#kdw{ES&dnL6_pG)$|{0thPx>_oe7tZ|27}SS;j(!xzTh5k61h`r*_x2>;ItA<8 zhhd@Uyj#ZR5%O}4VwpYss$M~}znkX@RMDHS2cDI#FTLlsz_ZRCD5wl!qE*)Vi?OOu z1m^{~kGWlrPUgUfL~*uW5*(;jN~yv$Zjg>lvy&5XXBX#ir#4O-{mN!t5Pio#>?5># zMEU3#=i;^~_*oIoW=REOXoiJUVjf@LS$2|WCw17P$ruJsstR85P7Ud%_>N+-Regnc zVIHev@l=f2i>2?CtJ+1z&lWz}V&elL5?nP*anX-7@J?7nH~3P`rm9yjaywbO%;lAZ zJAWe|r=5e9f8wn2oT{_{X<_g>7YTAP9sNG}UVE>$+Gw+}|5#%fAJdna@|ADQ1}!J0E;?30L6iy{Ow>oasB zQRFJTKBNC=Ufw4Aw`AM7G4Jt-D_R4@>j=(R%H5cay~BDpt2b2tLI7{FnHTX^zn49l z4i+boL*Bw0zMRYfTcZz*kk&NsA-I&xO=cf;D}m)9u{Kvq9HFO8OLbr}I*dnWme@3K z@kT(mhj^%>v*@@+fQY`PLTa4}`O_xb_~p7r;cwA45*J+u^BT zMuHxN%$f)TaF~b2a8*{ahW({NWPuE#IL06N%w=~vI7|13jJiPV=%m#(>~XICGu+#& zBdx7>sVnJU% zWoFAQ`ze^@#-$45k@QF_OaX}}B1X9}J{FUO#xVhS*jc@U zzhKW5S(2v?eon!mmPe(FUs}kussr(L3@w{S+d1I_%Kl4g;*W2wevHwyAIOmxR0^`VaE~kSZxe;zD11SABG1VY>UYgJdus?hT@~*z45VXqrWY;-9># z0()x>Qpw$uMb@L~eITQ_E{*f`RavE6nmNf_MOeZ9;uY{#kC6Tn3CaHY!>3~N!OuEi zKw}{&_SnQw!MigHO?=?iBggAhw;i@tfB5?vnC`YJN|KiSFAKQWgz!hRj-a66&e?8H zSGfEh`zTn&TB8SIW(+}6Z);SQaqJl%HZAj75+bn@s0;!AZHUh<+m;sa?ZK?ZHF224 zo)LUp(r>$l$K+x`(2e_0R^0{c@CPdXOW=Q%2`p>6Bok01)^`(8J+s-$$m{3D$mpkA z_!I!tvK9by-ok)4@vpy^HdPnvHvk>H9N(6>~Udd~>AX2lI2U_u6ux&VF~L4b!q{5YXJG`Czxn*FfuFnks@+H6UKGT2nm&`c815 z|L2Y_tGFZ8#s;xtM`LH>1*ZR`qYm=7ZpX0g$S=_o*Mgq!0DRxu}i{>;{; zZ|+_&-CAMVLFmrEbknalr@v(cnQ-K!9eiA;ZdD5N{%RoK`D-7Crfd^`f;Hhpie@xb ztEx)07qF)CQCvI!@v%kWb2z3hF^<_(5?l&H(wpo;cN3wWzAHpC90oHOTM?QO;-XT|I1mhp%N*k!5w6+0R~GTE&rA`U@Qn-{*crKC^)Bri!W|NWbEY9 zWCGLH9puYv4#9wc8s04n1~~u$E$zQH&`e$^CeYf>g}hGhLf~c%8rjpX1VGJ>gRQRbJ)qz0~>o!%Bo~u+ncIEjOzg?W%=m3ywCJ56MYU8fP9oD+pub)}Rb#wX< zP?>U)skcKJzan5S0h&}(V}!T4nSL}V{2GV5d`JSt$Ij63>#}dM!<@`GeRrzWnGG45 z@o#R`ftWQr15TV=dn-)s?46x}o!YQKE}L_L86SPql!&*YBs)fM?s*DX)+xE?V+pIo zw41V1#BW`_64G4te!uPQnB;|%UKQykQ})A8qa&Yn6JQG=7tZke01WkV9FxR<0jX|Z zxRF_ky8BrUsiJc?c+4^Ko)`v8KauRtYey)ld|xu3=9##ebzk3Fca-b z9r3@@JOPk{Mm@UX%9f(g8lp@2Gn_L|*I}#hAfxXjZLqg?uSIG@q^~i`F%3Ex-6Bz3 zJ4WGUX?x)o1cg6k9G8LpS&kJfFt%eiIQesxKhwDOfr@o=U`MZnI_au$wM*Z!G^@pY zxcq;y==jZr>4nEmcvla881K}=33YjrQpyq9^A@s}zU=A5UCix$9f$}tKX9R{W5-ym^TVb{bX{x1wz+;=pKMXzZyjVya!_D=s+v|rtEDUlGIl%HbD0a~>ebBvc- zLL!f9BN+jy38rxqXa8n`&i@O1K%xHr#&MlVjiZz!M`5C}QTWWV(NsgMBN3U6h2L3C z4G^WtZ+p96Sb~X;5p(q07va{+o;=k|~_8{|HmbwsJ7`X)zsd=QyzT9x zlEP!8W(xNXrrJISrwa6Ge7$PB_>0ql%*J3`O!)UN2RcN@DEzy(6Of({7n!_*LoUXNklqHZ#aEnxe(#8^ z-8eyrw_Q&^=UdZ$`^&eUCVtf8WX_Q8ra)b7pm|9b^drACYs@G^G6@?*FH#=?_!`I& zL95XmP@j(QNZ`}G;ucN7T!6-z3z7vAT>gDjPbB`5t#!`hbC21YY*t0M`;W4(jOMpZ zlcHQfh2@)t8X1RP(xTg5+AtsYtZ2;qhrh5+qBdD%#iFQlFIoe!eP;!*dd%cWCw2XlUuhN#vx`9b%5;>DEh~;+z#Rjw+u#iIabF=eLFeZIa^>P(8U}Ib^+&F*9?w{>Tr+e$G#cX0Ep*{th1y4oeo}cO(usSq>Mr7{3G5;FwWIUSWo25FW>tTXL?I^_ zb^ej0CQysS4dPd5{t)|PM^VM@{>sd4Zlf=VP8#rVuwwID9|>@zLMw_RV##yo_FA^^ z1_C@%^ZyJt!sie{{tW=R=Rws6cXVT4V4h zE)43%2($+gkT-zuJXFmt|A-U-8=JR#j)lclZ_6$ssuEz)UTA)=fbe02?N#n#1th;I zmcMaFews!GuN#;js31b4Be9gj3bat%WQJw>OUInJzi1h$nH2&aVL=bxe{$|Fo(G$~ zJRAsV%J8u$aUcUhI#{Il5hBD&Ut9)S!~lbaA;LQiEYwe?k#hWlR&x8VmMrB^bHiq&(5i&08yZH&lOFz72IIjP88aqBmke~ z91U58M_n9NFvhloMMN%w`zW*AZ?E+Pa8gb#Zv9Ib{x9IWDJL>}FLgMwx!Tb}CkYV4 z`Ja2b+4MM34voEH*bdF;ed6(BmyvZy&08~k0CY-aqo`sIa^TVz^YDxoElo;T;!_XSY{$MLMA)yh7z!Uw%B^x1me5lR*Mfa+yCKg_B5(N zJSp_e{}VR~`0B+D?=2<8i}odBmzR}2tzkgxb zS99^WN^@!VS`tSS<#YXk>+<>Gr3EXUJIkD}s zg);^*XFtDmtIz?><=vmA>_u1UhweF9jkSr_Uh*RK(f)H{ky*Bl(@MI-GrJb=MPW5$ zOFYy8aBX`D+-`2Hy?Q^(K8XT-rW-I$ug$1c{Zs>5$#C1}MQ1#5ahnK%##jw*V3b%_ zm6olZiH!A{78yB#L2Ca1#tqWcar^E&Id23LqB)$2v5`tw!d*KJ_>crso7)$6j(0Ao zS#zo^u9oP1`1sNlZH{G81|VD#T-X&Q#EG5PLr|-kq3q8m%S*TcO3O(JVnL-6y_(7D z9a;#HwQV=XN`+KofRGQTnZkiEz!x-4Y=&4+3#oO?8>cHLhj<^FvFGG-`&>}yT)cof)jAi;!T@92rC0xkYK+|=A8sn)4H z5_}ANacG~SS3nG*Cz;Rt3;zyBxJt1&l&Bs4m$Ew6j+G_rFlrzolF z9<%I6+gKUdSH|;!y##)E{yelRUBh#0LMWME z_a5uW6N!^R%e$<@5i0y?Z;MLr(RArtn0kFc^;T1mLqCC{=Lve<{tjwo=NCm%Za+Br z35}^nLbhL1#xAhu?w#Fp z{{h&~*ftab)iL|ZG z34F0Kk+~5cqp>G%Fa_KWF~ zn1v(wS99ZTge3O+O7I3io1PVnor0#!&T&r&&D|$s*O3;1lQb>Ll`Q?*e@m-BBNeq9 zY(MF1Zj!D%?A$D)9bu%W9=QTw2!fPcNZS=2%jWZ14L<*8He=K*m6l`LnBgTE)@%b$z%8S;XUCzi^{cUZZHQ@EPGu zn?SCI?7Wqbz$Xv+mc<>l4dF+b+fzrnI;v%ZjcCkzB?gJw@N&u}Z?8<;SRtgHw&bY# zEI^5S*Mqs~dSdXdg$kLCx`Zp(KUpShsDn%)=l4c+kko6b=uD#yOKhW^KyQUVd9bg| zzbt?q^ddkjpJvWw+K*2k#my!8jQ(g)mR` z(m#CxA>4GvuK0&t;6?s!%$TyVSt#LwER+oA+aIm`Ms!=qoY8L@!b2xghK7LaJ`Z_6 zNF-#QgL^kY^CA8$UD~A+#&ZbKyJ?b(X94Wv63%Bm+l{|SVzE+~o&)HX+u797_W7ua zCuZ*d)K*IXC&^JDqe1MBd3!g?k?E4*1&J|briI*zFe6L5uIWpGm93nzv~6Y84hED5 zff4y-+Tj`wEU{0jMQ0iJvEMoizAO#BNac+3aHIXP9u>T2tT-jSlG$b#_3Yi0k^X02 zQ;KbQj=iPpb@fCqu2vrY_*@91UHWN=Ezqv{F^jaUPkUW>T4scLa-@9sYrfS{lB(fQ zDDBf#!-7wXM*ORfjPiumih0arZ>ekMkwy zzCz6T&u~e0+@&CmK32vpO}AYrj&Vl-q1-QlL0+P6&3*zW6eLT)`IY}gC}i%6-@k-U zCsGsebT0t8txFeggn5nc6BUfQ48NLI~Jv#_6nAcr;~9P8SE!h*k^{q8VzR0Zgo=|2}Z9*`q($I8ke)7 zPV_j-kI(uA2eVWL5NtEXm53;UQ-uTUXxO(y_!L$hE{T~r5*`j0XL zb;UUCvtMfrDcWn@kGqmv@EufWY-U>`OZ{qP`h->=qu*!nq{nofMD=}B_B>9 z%xD3V)~Y?WV#XVblsD0StkLJ4s6Uc$YWdHU$q_lqrSFH)FErkoB_BS0-dlLjzcDtJ zLc&!?Z)urMveW75Q!1@CIxgh+8Vy_Ey0gxTzLX|JrbU}(oAeb*=+Tw)y2Iln1M62H z|Az0eB@pr8{;A9xXHl*EMRNWH8Z=_5N7Uix_saqF99Zoa@k2O^p9{H5SoN(feu4{` z&HeAAW&lFvq>8p7%}B|0q*ZFTjhH}X#e&$*Q>m8riDUk8hrYd`?V&-7q$>O7w^&zE(qF$&ah2rTC)(i?jEBCFX|6BjJEUS*Yc)?qMO~henF_@*+u|g3lxxRA zr`GOF0~-n5@a}O@rtPb8*_CkLf4cTX!o_g|*iteDWEEzDiC>3kwP<81;v*+9#g&Wg zl_Ni?yp=w3*r>+dJ*0X5kRs?Iuf5H_(hKLVc>{!o;*y}}@!92UXy{FoFH>&;Zgc?a zK67&>f^EEUH8W7dzCE%ObMbg4<$D>{3Tx{gibhnoN>3qtvDq*|*ZtFXo7gQC+89{7 z0yFkf1!s%PS^GBJ{aZCNmewi3R6L`{^2wRaP7E`)iu{c#bS>87gi7T0zmvAYsn`PR zn<;7Oz$~>pI!e)rC>C*oZ7HiDP>Hb(1=1KVy=oU!o_>X*pu-E8>P|~& z7zG`L`L^-(~JE z?)H2LZ`r%NJ%AW?I`Zs3a2gCp!%q>pqzxupXxnk3lRHeB7z?1BnF6s|k?vEq_t_(E z?MLd1iy)LW7W%iG@VB^urOW(9hs{_#8WxAgBGR1B&OO=(lUfRYb3!o+fJupIzQzZX zHqUU_nq?wVH#ISmo3F@{sM<9T4R9TPLigAwccF@3g@yNVecySvg+x?k?^yzkR}=y7 z)=!B*30THS4@^Ir6^SlGGs$g1$GMQ?%)ekk_Le(wIOY11@?|}m-iJHZHtzoCPvZ%G z4x`J_H1YO1G ze^M1w>Ilt0ET7-8n|);aLDM=|a%j}AIt2OK=Y5&iVanb|Zt0y|`I^)409W?n93Kbt z_~w+O)5FZbnA2gXM?`zjyWcxh%igOB0uyX3Q0Y?7cQH*ZmydOdGN%im#~pF*Au}9} zroFL)0P*Q40AJmt73j(!a9-GjU*s#ig??_-R*EjeUMCMiHyTy9oI=r8rw}s?HA||2 zuqNj~uGvoN*eRlR2FYTpLWpSo@582jE!+zp=vZCg0cNnq(%Bl@>5&SVzyinlJ> zX9PNoWdOf}}MiLtQS73YL{-{=1^)o|uYNPg!&P&Hu$Ba@~Fpmei#xZHd{P#Xv zlLRW$=giGb)Rur3{5j$2HgVOUcvFmPg$=-Nu1+^R7S3>bWjHKQ>i9-YtTT{XT);a) z+sM#PYCc@H$=TvX{m!(D__LO*-~?+Eefl{J0x$&GSocjUEn;Gv>anLop=zQV!|JqX zf|>O9>~K{-{|>c?(N5RplvO^nn*v|uGM+Xh_cuH%dzSw83&!s8guP1uk*9qVB;Dx1 z-KbHn$}u#CvHHaqk1n2p4j2asjq7|r^oAkDF?*bd@$CtT4Ve~o@-a6vE(1D3feplQ z+n|zchym8Ji4njxP2MBdo=ZOucmH$^W4fzA?jB$u&O$z%rX zUAh^auPGucFY!X;$xjNiNjq4mwCbFK;a2A)SD zXZ+7DP<>+U^9ad0-7HRhE*M4V7T*ucl($Z z>)dmH6beQk?Z5PbbrCCrz8h!HV%U?=Z-;(&iK%Ax~|$R*?v0QPoe)?om}Y>qLo3dI3B+r#6UG!r{HJCN3qfU zsS!-A^s9c|>u|LDSk-_oB~{6qx))lgufGrNyOmNapki1EeR0Qp+I}J~8uL22Sy^b_ zguO!WkTQ(Ps6+K@Mm2|NZDC_t@6PdkY?(vw`jmmGt*9tQAKQWv=AIwH$|TR6_RIzx zG#w(2@Cn)#Rtx=|!ERctOBjotOn@#4JIsOY*FRJQoZ((7%;U+YV?*JN1a#}Jn6BgE zUy&K!zF=Yx0bBRA9t=R7diM=Z_Nr84L<5+E6m;D9{z@I3ZhFHsot#DkZfXh zMYhBaGNp{fhc8Hy9vIifY04pWh)bfK-$tKsFp)kAaT`{VGG*KU;OcgKPZVs*r?_Nk zyl{V*5Ik}h>daq|MJc!V%o0(3gw}v0H7JmG%{+nRcwkogYU7Xr$A_+?vWHZ0r{9!W zH+X1!D1NKgBFZ6(?`>Z#v?YG3;PX}<RX|t+ zB7Dt3jCah#^M{p@Kh&cuam>TkR@!N#d91;MQ`hmy6h~yhknJOtjkni@o|{sB(bOax zzO`9--qNW(sk0$ zN|nb>mSeOtUEioZY4v{oe${RD5#BdcD};h**Hog_p2cF1mXMFwBE-_OTB}o-pntZ}8g>M0 zWHNmUyVF!-H*Ao)3A!Q5t_f&1%VZv;F zKi*9G)&B$+-*jf^KSc$U)cIqM7j3{~$9PezwhsBzHBR*DVR2e`Bq#_+oUQ0Nt}kz5 zF`GV@ncuy8SL(h0?8Qtd-Mld3_}s*M&Ds2j-RQZ~YeLWG3H;x|4I`+^$8D-*USMkm zjyD6aMm6u(hR}zgT43&m-_A!)hpY~;0moQndIT) z1}wx}1q18tjZ_C=Pqjd*tzFxTnjyKEj%5s;K6^g=6ZCreAu>xz418+l%YFGff6|;f zOWIlao5RRo?XM1}{>jDzfxA8x)mHXme^9S=D+i~!iDtZU;g`&OBI-B$(d-+hJLYo& zR{BG;ok*mbzL7bnKc>^ui-68n$tuc;YvoIW1v^Vw-GQxHfvtgEO{u%FgeS{?-mJP1QT?zH4gm_RAU@WlB#46C<{bq86@6=5+U6JTj4@N(X7RrqSYA7>De{A zkQs3!^x|FTp5qz`W|uO{+_G{)R%enT-(TJ(txU7~5NcX|tCUn5+A*8uYR5I{4p@!C zd!s!^dzPoUiY?|!P$<15Gzp~D;TzT_D+=S_RC|DMjJj1$4#G5DX~`k=R?{h&k?iWB zwSjbJqzTC}d;8&(E0hSAUel{hAN9m+N@6@hKxr%%HGkG#-!6rnJA+vj6m}h(_58$A zyb?FWUDEN1C1IuM)W)-Xxn1wE@~7o>Lf>9~S5@TP>d(YH@J=HV-}t3(sQ?syrNgE^ z-&-PSsOnXO$ktebgfrd{9+cxTQ}*T?#rM=t{fVNQ=6gU>1L_#pxRC8eY@j#?mLKx( z@_QMhu7l+_My=Km)d>u-WmyqQSOanNt%(s5JX9nIC%(DRvw%Rj2)*2Sjp^F~$>|OO zaWH|x^z_-((zha9hZL=Tyo3>L;s!O~uaQG`yvMuE|W^Luc1=>-z^aO?! z6zQt_9a$9$A%Q}w14p$ktB%vtTK|lgAa3zKi@+FUk;3c@BrcuEbG{*7yR)x8YbR-; zf0?wPb?F30Lrgj84SxJtp^_3|pFCdb*PJOqz_A)sjY@fsSsMaBBvRj5pKFv{-e`QU_7zQ1RKRhfDC`pJVlWhW(K?QJv9YAPIl%Q(`V@9$0wt59I zEr-Q+GNnJ;oLr(b53ua=zSzr| zb$0q@7Y-$px5ft{UkXC!3G-;>TOJqBIq#K(79fdgP;LVEiMaP@hTMr2tu0 z<4Sg?w<36k{}9T5rZYxOL)0I^J=-Aa2i{w_ynx7r)R@|ff`ZyB(D0o8cPR*m>#}cG zgbcGB2YM<&o?AbXt0TGw_-`|3B1_s7UC>L5|GSBDWv%)9%C%%n_e-xcBx**6%;r|qz#t;xBh8@*Hinas9h)hm;IHgZA5 zmy1cDMYr)aeS~qIgb{l9NA>6<6C-o0*)SruX#zSZ2dSNugUjMVSRVAt$JUHWRRWg< zy1ZKgr#g;FU zPhwHMhJ6{yG)*u(*MgZ+ZaOrpP8OH~5Arm~$l?7;OD-lw@H?F4%x3WlsMxIYflB-Ad85{`E(T&=9UA-p_p5|7{QgHOG32?ZCZ?x=!p9wv} zRi;35$2%*MjKBtNU?_KfDcyD3vyAznm47gE6!L}hlquSdx&s6u?gHTR3gh0Ah= zdghv*_DH;$uy2u3?JwE|Ue{+)4-xP78ulM~%ggN}F|nw*UG3OPz7t)n;8lC9W7ORP z#2U72k`N?(%3{cGr%W@~Kup*0BH*2F-`19#ngvA>vwn3+jP`R5@DP|hUUJ3QZcm>{ zOx%=zkT^zCmySI+JA2-_^t9A@M){4TOOE|i!=(Jn!nFM~RhsTL8?@ST1cB5R=5(_w zM=ff_QR~^xYj|w6dv+VviD7NaWVobgJG882k`~lcYS(jZT0J4S6B3E*<)9ZDMUV2& zOzi?q)D=_l@23FSq#vQuK+sXB*zBov;OEuQlW%Hr70k1z-e^$y&&=9zv_x~&4G zb8?10BekPjI1+5>FUxSF?H%qZGq6e-<~syQUe#}0dZ#<2CMyu*wooPPx$`m91@vdz z)ylcWH)xiT(?cNw-9hST_Tot)nyRPxKE*D!2q!toFK~gWMpxjI%D%gXP%TG%k4Pi72&(6(Z3%_bCx-IpZVX2!amIk|HW1K7k_fkOuuF6c9v@J?O;TWAp;wOWKC zA-Dsm%)e5Zv?_mPYCRDEy}An8kp@~SScGkTt0dW4{1XyiE@WVco0j>MeV~_p@+lG| zbIS}J#;7vygftN4duE!5WTU_-K)K5bdUFQ`O$Ln&lH0vxbIQWi0Y8cCb73`yb~K=T z!@Si@Lfi!N65uL1438!8KMM$lZ_%3saEmLL&yw6;Vk$Jv+oU`1Vw8H9@GDGn;PTc& zp+2)%a7(yGd*8F{8vkswe{z>W#N5dB4Xm@bSzZ9`vlApxn|)qHO@B!Gho#04#4Lfp zFM;^k==`DYO84FniHD4j7gw1&FvPec+T0nl1+y&xCp7`SjEo+#wY7t;l)Ac0ced|4 zvxLk%%*vP0BLZj^T?KzD-R_*n5a(k)1a87@j7cyEFD6L=c%r}mVFGaQa z<+Ab-@2gjjuE3yci@)_P*!62YBR%$;u5Nv6B5m?!Cx`Ayv+iiNH@)OR?LmwUaI-V# zysIgioJ(|GMxId-OopU@Tu(w;84c?(-CyTH2jI`>pZ0IZYn-aqTA#wmoDUG}_`2^k zq*+dg{DL#sFQ%dqPa?Z;-H-PU&S%Zrale2>N)jUqQmk}rzEM&Es-+Ds%_?c>8{|UP z-pGtqmWUpYp2PlAtLYXeIJrgnLEYRbK|@GR?+JSp; zphw22o)s{tOi^daYhFp3?4m7$7N|l{jD@+RC7>+OcBEU!y9DyNTIdPx?uD^JtWa!%X0{Msc;2$Ape&``$IvADU!3G=J4{f?NDI)m~HGLxH?zW)tYcD~-eY z<~`W@GQ6T^qLVlHI`hYiGc7{JwpRsU&H)>@H9`B^?sx>l z7w6TDBP{r?fgd}wTY$0kh*-}=H~tFOM^LSrl}cNmm0)h3gE;)}E~?a}#7&wN%Hs~a zHXae6g#g;zB^ZvOMr)6bBP(=r?C`NWJvzNR+)EH%+o&dq z*HQ{EOp1HEyD;i8|`z`1{?7QhcWJzumRhf~D@T#ORa zIomJgGDmi;u{{`t&nj!!Q7n^R#6DdKhWoQh8+;WYR1&xYC%qu28zHC$Hg2Ta-4tHE z32rN5hVoUcbOt)(qQb&WVRu($^C>mR_}nieSrZ;)LHDblFkjsrru$Bbq0fzlUdiJ7 zWEYMcm`K&pt?@MM4fXI6dRm%G++a_J^Km5C9*X_;pP@J&c>U)0%8P+$hSEKakL+e4 zC{uJxzH5hVu?JncsP+(cD=IMg;Ip=`QJCMsh13l5deLuRqnrGfH+HRC+--a0JXW@M zrh^-i$KZTQ@3W%-Iy%`#t;*hiGb1Zdj(l?*>fyjNz}RvwXuz5;^dCqYEe=k-WU|#H zkw_+g(q*r&Ua;3m&)t2?Xn696ojTQ8fPQ}HT ztIBBG)1CvqHS8t)POwz0FBGN_>^xp(pakbKbHsbb#{Gac7AuLl(+>YMwdEb;1*Za% z2Ur~5%$e^FEeo;7I_tIUHo&$sa~Mb=V`M2@5l4R9a-7oT}v}6+-)Au z9lecy|L(hjJ{;9Pm=e~0mv-;jwNu_}MR|9e8o9@b_flJ@GOzG5(k$!hb-qMkg+~uTe+a8wRqICgs(6?Pg1B3JHi)Mn7-kSf_WX|7ylwS^WGsar5=&fHjgsqXk4w< zr)VM&be1vm(Wf|R`N5XY8i;mmw=1rK7pJb|g9z)&3Q9{2N$Jq}L%BB(s+Dt47 zq#z#sU9PJOW+}T)M{2Bpbg$3P9Aod?Wyv2Mn?GBpN!+cvlcFop*~U$GNuSHsTGplR z%IG5>b4Mcw#7th{zLtRj=4he7DOotvtKs#n&_-R?Iqi)EsQh)=2>+S)G}I8E_=#HU zjC85aq$DZ+i75@9u5su>2mw#cj+~<;$xZA8(+A5P80r8bBLx%TVI63k&IG!ngSt zHl&rUdGOKF4&i&eezvQYk;$Bn!M6tqL?N(!#rn?5-v7nkTZcvY_U*nhw4FyY5=@3v_6i{ja=^8;vB}8D5E@_ZvU}9f4KF_<}cdfm4tYhu} z_8%U2a16|FU-x}o-#E|DH<)dEhK8X31WENdt>*|~^@;Cdb_>sj<+0ZdkBoD;9|#$;XO8 z>IkbnRYz_b`I*DAC|NpdCE;!0+0nT+2lRBZ!Dyzs{jT#a4w?R6vhkD8T)JQNk^M4M zHFNY|H^5HboJwBZ@V^#cg-o#NYTPvDd#J$C92n?({LE!G5yc}aD z_p>}i5ObH6#`@i7lSNc(Hc9sF9k1=%S8@51wYNBGbDr2A5B~_=E*PGh|AUXe;>t-* z=8=+?wUhL?i)AL9+j7alM@frQs@>w|UW#cC=_332{DRyykNHZ5x5vXFOOu~=by=jq za5Qc+dAer+iO(pYdlj3Y&OyI3k~#IEAnWSyvK3k;Of82ns)&C666)buUgUbvQzn?? zaQO{QkmtIR@QzW`2GM6B+sWB%>bl8=M9i#@ssE}2`mGh2orJ9*ft<}4jiMQ-U+Qum zlBiT0xQ+JFN-4wc^jXsVhU(citRtmqppLmA4LdHjbxdj@EC|(YY|UTEzNu}}VEyvk zMQKNWonFNo+$oIZNoAP=NkmHrWwDmDDdk4X+`AV8>d)ODF}RtS&Qy|E8HWps^WEy* zvHr34ZZ|=o$KY5|Wl=hk1OM59*cH< z2;b9AoYE>Tq;=B$spi!lQ!!uvTKxG^z>m5GVT0YWkte;q9DIu2cyjEw`$>Jcm88}^ zt7^Mnm(=bA?&14-E>#X46s}qgxtb=C61JHWhv&|3-1N<44Q$d8k?OuaReF&S_+n(4+9Yf}`pc0&y;B!m~~Xs(H1>|e-^*MH1@_TI%CE2G18E)O)V##4b-WZFkzYH!ExWl9JBx#k+sOqJmNYNn>^fM#m@TaK5iuWtg$+gzY{iHkra=^WZTfQpKZp9fC?_gEj zGc@tETN*0T@)pN6ojImIa+U*5;}cWV<+eM1(3kbxR;X>3+lL4%ld#L6Y8VvaI!X-n zdY7BQQBJJA^f2!%5nM%Av5)gY`Y9EKek?n$wx?lHgTrI|-VQ`)1L zgcHjxJKnsjSFH3hxn1hO?aqLpXmC$-XJ1{>aKHJ%BW2Hkn#FHfX=i~kyFvJh)w}VX zh63wtB`y}*h35VFq3y_J$#>!hJ!5(_sRqagd{egM%NLzdvckVbkbZ1O-{3>O%v+iec z+h)7Qy|r

JVO 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

M_1qtTT)h)b6D2K<_ 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%0D6c|OAH2Gr=zL!G5pY}b{Udcbu`Vu< z|F}2fd}3v~cq+iBzfRfY!qs3MO0_iNs?iM#=j-von)`E#{R@=)Br4&#eeo1`q;3JP zT7<{Z_Y6q;VLjN`@zMhg4&e^;lUF9Nh>4%nXdzs|X<>kRaK6qbXXLDAk|2=pSf;&j zqlSKQzz}uQCPA7@YP&pVxYU?gpMLhQl?*FwYVq(GUK%jT!1}V_6gXVg;!-9pYTRIm zsg63^sFlSh(W5cWz3qlOw=W=@=#w$pmC2&|sK-ZxFTHA+cG7TLtu>P`v^b+hpA^O+ zAOx)UYhV|sFR0`#D?4qWe8TwQg-XhsvjHPMpWE`Sl_iN0=9RCx8(9K2d8XINe<)wg zlL4!YC{cIp^ZP<>f^YfGH24_)693*Nh50y`+qakD6YQtZKqG4I8GG2FYSEFr@fmV@ zW5UA8wpFQGF-1{r&jmSOus4fR<1g%2a+;_XcKsdGMq^m;dx6;UevXf;u*R7^#an6p zwP;nO1AK8*j|jrLC88>h95E&XfrBQV5ttWHmw+pxxDbKArX(pTseeFaL{pUR z#!Zs`W23qF%SQ7C#D><0Vx#Xi=ZPvj;N~XJSQACqmt#PAA+z-J>!ty>^EMsaN5Ho! zcBH5bcyPIWL4Ehv%})wBEYnRX|CVQ80~Sktru?kH71zfIMIlzhJ}w~Z_}Yh|!Y~~r z1Q8@UP5(JKn=jt}LY3;f%5$GUhVFU9MdvKat)=FOf&74llPNJb`!MLWrB`S3yWk7@ zXDiCwu^U+JgP%_@qzYA#{+c^5IZv1qub0B{Z42RmSoMV^svP#<65_{+l_cG4=Hw*t zZk)}$DQ1Zx`i7cTnL0&3|C~|tL?Lj`tJMwdXCc9TT+Lk)U+NX!Y9qq3!4`Q$M~iK1 z89@Sft)RRGP~~x#oaP7)*1H6E7Q2aW@kfG!(Qyy^rKW3Wp9VMz76c(k zZ=*1gKPZ10_+t7apSxk8`$fvUL`vQaq)o||wUJYiU{d;$!oKrwnh zHHXOTOm=_}*mg+pl`6e8E+=&K@s-7{ZY<&Vz5L)L5xj?XYsx>{UL^?tHI_5Qh3bc! z!nzp-y8L-fj~CO(NNX%~?f6G#{#`Ujf?-6Y34dScY*Sx-W$)5b38$*uSDy1dS8x4h z0kHiV`oH>R!!>!bX~P}3f11O;%JTBkJt--;?>B+D;DA%R)g0}Aw++)fK|#`UrC#7w zJ%w6G1{-?|I3F~Ey96xj#m9X31eQ9PcOHD2<$%S40I3IKp!(?N6U=KYfX+PB;mlOZ zQ7~yX-lKuJli6c#L&{PGO#z zsJpe0eVgCoJ2VR(FWR{_8iqZAGD54dYIwaOfjfSsgL1h(QbP!*#`G)hlDA)D64r%h z5X+BkQQC9bg>7CVg_+kTI8UjKw7h=cI^j<5Sm%3Thz%Glbw7o|AW0V%BfcziP~PF& z(AYeTkz#4qYCreDa>6tyWK#OIn0?jsT}P3w5YK)ma54fwo5F`O(|C1{ys?O(0;8IdpZv%-qK;(FT^xk3y0(~)W)Mfs1m5o0^H57mDnPr6|b?aqc8 z{tUEsPO(Gw2#RjF!JCp*dRuW3FS4}@#d`8fKD$xdDT7XB@Ru#gJ%4%UuOvf<8Pm2m z-R9q<6`Vt9=Wl4EzH7~2#;6s1to-6#vcnX6Z!Zr4pQ{QPznkH{EIE(9=*8@~Qi)7E zDX#u3fq0(SG@IQ7KDQWH$gG1B?WgZTfFzz$P5CN6MZW7)Onubvv)YtHhE8y>JT0Fa zv&s+;jKCIElFT!j<3nQ&QrN&$aLKxdd?DMJ-;s%$zxM~}Sb|6of=z}UJ1Nl~f?$nr zm9_bC>xa&9f*$tU9x&i)8gQu^%@T235tQhOs?ph7>pKA>vWT}I09k45F?*0L$I?f< zC@LSU0M&%`L83MindSgO&yOP(nO-hB|Utw!O;9aD=kj#KMMwMoG8qC zUwCM%dwsPjXO2hj1SU7qz}NVdN+~zIQJ$p#QuKP&`wJn@l8`@)QHZoSNM9p=G=UiU@8noIkC6lwovFHq_y*6``-}bVn13XD9 zDasT9xuMpkA7&wP>ZWBIRIaF{Cq)BoNqaw#k|Qe&d4{>uLCL&8L_JP>eajs2F1{o- zK>;m?c`vavqVePBtcDkD4>|+-iqID&@C*C);&1$nXjEP1+V(Zw+}Vkl zd+6;PevkFqlA2c{oE>gYUcZ%nH`h(kWoM2vx;G{wEn;XZeDzk9d86S_YjnoD5L{W- zNa4s{;L=gd?DgKhcIsn)QC4kh>SSbJv->p1w}%T$NOkGP$yU zK8ovmFwFC4P{y6iNCt^XgKOOjp|yYhA(_ZrJ;t=~+4J^7rV|6r^onT3PR9;$jv!tr z)n*FyKC_4k?RR?84h$l$5Q4;M>8K$5kfIcU+b1!qS+9180_Y}P|2gxY0qqdbfWQe! z4G09+eAT92xz9@jIBlGh!DLg&$9XDXO5AcmXf(x#W_Vl&^K;$Rt#Q7sYa#A-;sYpbJffs}P!Atb zu2baBvEA@ms|sr=h51YEatrv;tk(OK_9uwd8k0Cp1zO1ZqbtcOX11AilPXIxNxm&K z)QnPdUs8tzPHkkjH`=8YJSmIeMB_&SZ?p>m46ekIKY=OKCQAKofZ_WA*cIUHh;935 zZ7UjXgzB#UD)^wZFHeY6BrBLnpCc=9AGgeCQ$b%hVP7Kw`7hB`aTI z+em~w1P^k~#4^aMYFdl6t_T4X9%${{ft_R$U%wpM>=GP0&X$j{T*o>Lg2(i~o}0?g z0mJ z&mfNtI(W&YFfcfi>wx4`F1^UyiVnrCjWC|cJ5;eJ_`duQt;(=Dm54#(TQYZ~(e+tQ zTRlTolIOe(cx`U$h@BWH7MMCgy01_OEH!P=#ML|-*wwcF^__4Xxgra=GsKSZacNoW z_zimAeqFGr+T@TMtBL@9#IntW!dr;@{kcY^9Xr?mA9H^m5B2`{kK@_0bZTrxn~Aa) zS}a*+kfkWQBn&FaQb^f`nMB!=lu$z1ml)a0GC~nCC9>}%yD^zDX8S&0I-T>muJ?8Q zZlB-n`_K2E^T#>W$;|8Zd_ErcRV21S%n#;?c;V1rN;{zz3mS=Y>?3Od62j}rGZ3>j zetv78dp}82{($ge=ynC!_O;I28eVuTlWw_q_5+Ph8o`)4J8V zlq|TMJA`%+B8c@;QGNc)+`VuXT^Ibkl{3oJ;K1dx&&I)X9B;(8 z=ByrdmRE2d+l{vFWkLmQcLOY4{9QO>Gqek3}DUQpaCrlPegGu2b zm=pl6F|Q_qFa2dfXiW3L&7(2L4@9V5>4A=}8AyXqh! zxo)D@!&Mpz!UD|gmM`RoS_E9`QC)ylXx;#D)^hR> ze5J^G){o62{?Q|zg$r)m6|BWq+?Go~Y-mS&Wc_-k$UcbosB+8A5!wdNz!k^qM;V%sjscD^&b{~nOuM2&&h#T@K_uA7>w^Vubk?#1ClVRC)*Ym?%v65~kN zm+<;hrQ#Olv>20|Jn%jrhbhQad8*?zzyN94dvMy9`JAQrodyFDj?Ts`EJZoRhSfef zdOvR(iR7zvlvF@pdP0ydGGCZ5WPqPKqZYAVDQgGp6#l3A60?g>vS_BBAC6A=oTs6M zzK?NWVg^{{--J5bVTkQ#7JP>DUrL$gu2Hc!=OR)+DX(}W9Rw-MvFv{si@#HrJu-tr zH><{I#Wslz;8<7O0M)S{ys}L!z!@M04tAi>zJDj#njH|WaqqPn^GX?UaBJuT;W;kQ zcL0f!2gAYoM%UY7i{2*ycGxApw0GvN8 z{3j6K9a<{5Lpwye=94-jzP{J%G#yK>riv##ZylQfff(raZ8?mlu+7X7>aj=a_+Z_j z$wZfvWqS?-1=x97Syb%?^1&0ISXQZVq~ZoN5+cWj)B~>e=F&h91c#muIPtD-1xEoo zvr?#YZR`N%q1%atlUa@seGc0~INnSORw#iO^@4HEd!D(W4$x_$WD+?uW^GOID!W-g^8qowZ6$g9y9Es zh+isZ6<29^)94HmeBIJT4G7A&_UtdUjF|a&M?BTwoD-#nn>>E8*21DYSu7L;iiuep zm`@gC2RQw@`;yp-TlCXe>wZGTMl|sfHz;_d9UrW31*ZMX)+9FEBZJ+k@&(HSnq}l4 z`HyyDaSg>T=*w8v@Y+~};9l%pc5q`~0;qb%)k=-nRg9)t7JO&%_n}TQsJ&$S)s^C+ zyw&eD#J0ov!4C>erj>pEC%u{i7oeBGL}%Amjf8sVkiy{DpW(K2mE#QGENd2pA)J7k zJ>@`{w~0W<(dQq;+nSDBD`3FRAXmw60MQvO2b**!r5>Ss`gf}?fhP+PG9=cgP7oOB zkDA6kgl>I|@*a0^7NuVM`6uv78&WO}>o|E~u0|*J+&{9|Uh>mI=E);lVT4}hg=u}M z=vm3!^%Wye)B&nuv24;!i?#8H4~qR_!u_^edD^qE$5X~E*r>-OcYbxpk7qHfBztyO zVd%Mu{J4R2$I&vy7`r1WB`W@Q;}&ujDBn6anCBx1)NtzhjX;!2s+8@Nnrk;67fwow z9UB@|lJxr;c*<$TJ`73N8~$cpGTrqfogOCmd`6vB+Y-3Tc3^R5Z;ee==IdP5%hNaT z(F;0B{1Kui0xe(9JUrSkGH4ZgQ|&g!h0>5F%zQz4S$QpLs&x8%2rm)yw0ms8tKM9` zq@{wJT;9UUnxk;4ke*fuku^<_6bNIWg}c(o8az5f1M6-w(XiC@)Vu*Yw`So020A#l zA;2JKB^0OoTxl2H((42K@pQBY^f?Iko?)GRc8&^kU7x8hn}5{ei5sJnf}rK0kWt6$ zq0P}EJhJXgG$zkHSVPXl9xsHl{4}B@A=FxRHE?Ghwh=!GwBOTgWFO9 z>i+^(UKTa^r<&;6Ix+w&pMas6AMXP=WQ7K8zf7;Yj8MBAm>V9BS%ONSP+p0@v4_r& zo7h9-=vBtGiS1k?wFs8>mE3pD@~&=*gv(PNsEy<%r)@j?08M5=A_UsXGHYwuH3~f0 z*ilij>}b~K>@Vt(qi*9!g~;8G38osnXi&A0urT6ffp($=ac_5YD1CaP6+6Doj+b5X z*ECxClm*_%y=`6|MpvL$wL@%SfTT1X)GoL_RoENHouor)xEidaAf?63bwI8M zv8M#mK5QJf-&$&SWUuSz$+x)7hWh#-g#^1Es%g(C_5^cY?vZq4`xF500|=3s&nbw57J~F);Y@6KWyP-X7L{CGz1v~ zJ2j8cXCut*K8j51S_zWDC=o0N4i*hAzjXLYWW#qlK1A`wuisS~gOkMtP^yvNvOlZB zvC}wo7`TPOAixjZdVuaYP}0wlB6;8m-;a5NE7V&k`(v+{T+xSDvy~m4PF>S+dZRkA zcz#)Nd7gq1h`ti#)drkGJO)_Qx-TZ5yffRU$KU(4b9HNk7AULMayHKb|8pU2rwi=pcFxn(XS&romip3-)i6Yvo*`YPg8HD}&>OYLo0x@MX2^LN7yewd@9kHr0Y(;LwS1&DANS~DE3`*67j7`8kZEyvTH_KL722kzeWp#Urx|1p@XZ1_zI z@d_DJZ%-dUUq;dyF#}=TFn3o%T2Wm9QR2|;fzC<4OBzGFdjp5$Q>!nxc-|(=5Yl`7 z{QQgrKy>`z&)GlCS=y=qKG1iX$z*4L&g&n|18^#s=s?)VIM_!RN3_UNZJt1AozP1n zgkxN7-sBvhwY5^rm;oFWDj83Fw#T0hxB!B(_`#hvdRh>~!(Rv;=;odJ5$i1{+n7w% z!_?m}zUPb_8$TtBpVplVR*REp4_2oD4E5y~Zn_^JV( zEN`O}cOILXb~W15Mijb%3?(-oq?Wkj1-i%L?bh%*@n$kgo$ux0={F?VyUd+%j2Z`j z0Iu7V)rr~_Nwe+2L8*%Z2mfY$6B};4co_9LXc%P=u#PC<0q$2NG6W=le>q`LICLs~ zbTwErjz6BEpt_eRmKd9}7}&pNpUhD3MKvjiqx23v>70FNG=45nKXD_!SN=_IEYipg z_sB%xoBrYvBg(YJZ&8OSvqB*HbcnYS*o)_-C$mKrD#@o9(&ry?({7C>jAZhia>9CU z_udv7ObgQ29dXM_~K72K!it&een@|8kUJ`7gDq^?U!c!V>vU*`V%R?_709`^pVMzL^BY_0i$`*1 zDjY6zA0%h{h7?n-(XzvzHGuT7_eK~`l*z7f#yhFc>&m4fMYc7yf_o<}F2?z=`+JK& zI5HQffLz1g$pXTG5>%)|1rba8k`Q&yAMdumZ{(V(3BHAY&aHym&-8*Ys2yzJD!W99LueTu)G5dNu-$D=pEdkkmJ0E>=oy2 zk_gTpOu*FvaI9d2IgMnDDj^Q69=KtyL?b3zs87xS@4<}G?AbGmPy1wWb?F3CQM+3R z2h6j(gUk1d$SLeK?hKeSV`ZsA$*T75o@wPto?srJv2||K4`nFEVfU8ukM02ddH3Y5VJxqNy;z_6eP@V-lfkSC#2adMzW`~1aIhM!MAQJlSNRSwwi2+$Crhefd z!XD-&(8m~8ehqL^y8^L&`c5nfZF9A_wk;$KW`wW!v*Vdw?uEVDLJQ?1Ag+~Z(g0F0 z0H?1FTD}z`o(ltYKJyQtvjW|3I!+vdLWsuvs8IkK*=y<;)(^eQZdwiSZxHDV=3RPB z%6{>zx>#kRPLiSbfc^qGE>TEM5#0Nt0TjXYu)<=o;5sMBVcgeGeRJP9!S0s4y)_TNuSpjX{<_Cx&Y_f#_mPs zR1FtCcj1BDk?3Vd)R}Yj3CB`yd6{1lGR5GAF!V3yKes;ZXXmHJ$nW~kz|@` ziqONI;@*?rd)=))0Kkr9KYWnj~V&9M7;+rk7H22G)B9VjLEXc)#lW82MWfO))WSl$E;}_3H9mk2`ynY8%Rt% zL5&NJ1VnuexuLjk-4X9*r02bQels%%qKWv}^*PCqbjXTO=PPv~p?Be49reB}f4|Uk z$tyK!rn{!7xnHY=Zx5I7wdR$8J+<{J!GnI)I&k~@&w&`$w_}5D?+4}q< z_3{)h*mj@ym28GZJJw+|r%V??L3ikJzJ*2Wn&l<<^Sd|A*!xurMrnlC_E=QtA{HC0 zLECpSxA}$wm&p+*b(BjA>b$G8&raK;xyD;Ig z`{@-W@W1TY0uYt@zaU?HZ+bC4veyw41!u~6k0-XS9S$Z zdC)Gcc(h{iv z!8s^YA>j?O*U%;FKJT~8B|)oJYZR~|fBJ*HSBlBgXwu-K;fY9=Qr0({Ofr(jZrYG9 z121UYN7wFr!1`O>p)r3ZX-k90h*rXVcbGsr!GaS&XA^X$XvvIn)L!C5P#jH9gPhk* z!AkCG)g(~R|2KCvn4(pYWs2wf+Xqa?es*^2Jq)1#iAh<|NwyH1rXJ%GbjD)3mnVtR zsialD8!Yz9ynX2=)NVtq@Hg)GI+?s6mMXGu`>Bal*Q&6hxph}wpJEt(Q%3k_TG4az z>h{!s7RF(@;lqr*fBmZuwkM&|x`ve->6vJDMB>tgGZ8a9tD#rp!u0>??=7m zuG?ALB>1U&{>YjjHaRc-S7{xt;^%2^g7@-lRpuJdv!H39*iJaNguPu*!Kn zJ6L<2dCo6V(nl9rm}~N;n!&eJfn>JIKAkG|%{JUdH?xFHoRZ$}Qf}jo=DKZu5|O%^ z9~Z=PxlS-eGOLH_PDW0$Z#&8WlZdV``ZDd8u=6=h<^#n>*fMHc#3G~v`Hu*;PQyY- z!Q*NAg+o}c&Qw|qDX=~hDp48?@wtiJzzMS*_Rmye=ekCt0izb>fJo@@-lPnmLDlE^ zFbgOc$&KF{GJ(G5tjcBnC%b@I5OaJe8Jcx&z&Hi^#&71i@%l9Bu>Lq+1HhEy&)jAMjbABFV;)dr0Rgr1#!v?mGkw5Af4tes0YADVhrx=Ql)d!+6NUnWsY z21e1Jl)Q-n*&EV5>DJ4vA6kRHGB!@50Z8rVjq>+!%iPG$Sw-lVddtCyBgore+4}NZ zAyUd6a$X6dX=)ywhk68#-_;ff4f*l1>Mm&rU70j_zH;sQbUOCA>V()D!C%wyDp4k1 z@%wc}yEOS4OhlblLQ} zLYnp2C)f+d3{_;wP9Fr-#?m0s+R1SsV2{ao|C5_W?zq2--?5|3=my!4Sv5U~(N7Pf z&2+UHh!Q-cgK*mB~3gkXWx@zyWU zV{;X#ntgWrAJzkF^=xp%Db_Ji$bLOiiO@@Dow|RzWK2-Ml7oZE1o2IWHXolj@c2OE z>UFiBe*k|rphsH}5r+iUax06O$FkPdS+e(oN@?hRYU6 zy+df>vPLcpW1uK;al0e3l`P{=iJvc=(T%rGWqD%@-Dyc;@cT?WtNBMLwg!8A&m{-G z?`Qk>oxHsj1fKLA9+7v~D65R~y;szpL=#9iZ05$mmhE-Y-iBOe=&Egucu0pamOLt- zh7LG(FkOGWEHOCQQN8}_JHeZG7ubysJsy>Rb4EJNyXFPZ9s$q87KEErA2O#G^pjsdw!)%_*wFe&ZUKR()SXk@V??T^Xy_UgHb1&gT43LVXo99M1 zsOaV1W@RGt!87#(?|k+_ATtKaB?p&FK%rbHfg$q$TOKmpr*`$Hl26ndx&20U4O1Vo zY#Pjzgsv?cisBVM2=KaG*Ny7dw@*4kpyo5)WISNzz#7DXAzN$8?z1=?17Rf3dwe&eSnTI+3Jr3!-~UG zDy-xVmPzxUJbzl^ful&;p@fR#WLo+~-F?$HNBI^c_6Zs-C`^MZBkC8(Lh<`j4CIa@ zaY{Xm_aF;J#-oS1nT2A+61jbF@}tnm)MeSA#*vJ%8!bRg_tpFljNY&Ss1;C}g)q{0 zs!=5PUfIxCQPiZz@H8^HZuUq)E(RFD<`@o+tB|O}4~RPUQ}pq8R+;V?*f#Wkp5}S- zLdGZDa%gbY3=ikmJ`mGja#_7Cp?$O*rd;gRcYbT;;hOYPz!`t!*8GeIh%elUay)Uc zp21|ABi3gqjsksbdjzWI|B44|H1grfPYtC>PK-HP&q+i)>lS#rHnF))Z<7f-E%Tce zI)(Qc_SFZycGpHlLeld{7vdCUTIZJFa=Rpa7glO4kg+fxaZm+))bLSopqj={IqCM6 zz(6cE?L`s=n0)hZO@zFiYWgw#wvPK#gyW4K=Duj}M;8K}>>1cK?#f;fdH5H?3t`3? zO-3tqEaF4D&jUDhrG4?iFV>F%!|{aYOX|b6Bdw-ud0|i20`6iHa9x{!!%V%Gkqro6 zZ$+!BT2Etr3;((soLxPOFkN9vVAtDpT0j?Y?+;K|-GNj;@A}}@A5ord&R#B!GGw01 zpG-x!#TzBB%5YC?G#3bn$UG&Q%4VENPjG=PHE~$VB^4zB$w;^0#8^^e%tk{jpmW3D zw7G`HH{Q%G=LQ_a5%(a*RMeMp^!muXYd}aBvv)ds3NJ z;(oLBinI$<4_8mg2a7$f@1MY=MDh7Vqc{0J#u$1@{%Y{aDO0Lt8pt%E@?N%_rrtbY zMr9m8l6V>!1I1KBmE|$SXKFSE9+~?B)VHA%-P2iE*U1_VyiliiDYg zP%Nh2He4|d`ic_5J~%EScOLjeq%c7A3dV>56Yp?)^?Iqo_4Z&(%M2mB&9^+b@khN*6O5qSCnHn@8QMl)NqkHpfb50r3ust z0TAcCDTFnoB(wInqyzxQ@@6?0lO`vl+<^KBK@tQwpB5L}_E*L%onM0F=Hp;wdvNaQ zOgjYQ1a5c!Os`247{%1{jjT^of3acje4PBS3?}HkCqdTAK_0gWP<^(#=hB`RC1c87 zoCwYni-0LRUGCWF0rNDt_YYtL!AVPpN`}Sy&NiUl?}Q&^BMJ%Co|Yb3bMe*D#l*b4N0z(Eizq3jKp`Y+$S`wK5QoTjqJf8*| zgAJ`rvT-){4bgzC=N|qiPf~=^g9X429uiHx=}7s*XDrlD+PvK z1=; z<8{V26kDV<%vgKb=6yaj?LfxakVaz0f~aMK@6X?+r_+XCRbW-mgJc2l9mCDl0jc5i z5yIq5mqvJ9gO~POmiLTCKE>Kqa(NaNP_SvN;HnMDjF2GrPuJ+ttCKT})Z7mK4{2W! zAzvHq2oG9yLou!{2Tus>yQbK7ec4c*ITClP?c6klm|%!;RG5x`h^HLfk9CBB`uWw< z0N)jxT}LCkh?KQQOCTNT*8luVGAs3am#d3e=2e$bZS7cWX<)mBAN+!b05XX(n6{Yf zhYhU65=zy%ROB_M)?9a9V|u~w->$=-zO^NQI#olAmO8brj|QF_C2nLhh7&IA3$O36&!1u6Z&5Gf3cTEVmG6WjzY@cT=Y#J1)-M)REYCSj%`R(|Qp{{QtU{l^E1aMviB$969! zC#~LO2StmwpV1hrjGtIS@Vg&)Vxp~>A_j2gU^{cv0RF?8CHTQ;AiC~$wHNGG=Uk}DV$>iawx-F75pX{MK{rEQI6HQ)*s zk-_WwcgBETV&}qYm}!{4d5Sy;Wr@SeaP`!x2dSZ!OI9tqs)H&WY`#|f^HR0bMJNO(# zHkpD{m=*H<{baIGU}UT2WrN5WXMb(XDm6-D$vU+GxB?)pK8QOn-ty0t)D+SHDx1m= z0@K#nJdsy+x7oGs#Q{qHSl9;X*_OVVC)-blmGCOkiT!bhf*ce;X* zL#~Oc<(Aobo@Ll740JP`D))X&K91zt&GPUkpNhH2ouii(cmZf5b)luu_7oU?M)DTJ zEfH!ZJFlv-44NWGCAd_WF+r?|1_ObRSM>%@!cxmG#b-YeU&(kPE1)f#(&m_e%7{Mb z5Zy+ZVH zHxtD3TqH$J+~E}G+9i%>7u+bG z#iIXwleTf&*V$5d7QQ|VFxA`W3VGKEn90jmtS0XerGQ?};4)M~Oulw#yBd;0TFv{M z6ncgL-ex;kmT=!MQA5s8@=CwW!y5>be|to;1i-yQ*f+E-x0z39 zZ91DDg{p)F++Z~k`HSaBguIQyYf(cPL48eCK?!aPs0lmAbrI z=XS+5eBN5zyWx7xM*aaHwvF@cUn%Lu7KlY&##N8hz1#0{vTiqS-%&YzGElwnEo489 z{ZbDJU&NFv;~L1{f>tn6%$AOcTWR;_Er_N~UOD!MZ= zZ&WG90bd>RZreS5zzRxYY*t}|S}#81g}{_aqw>6Qt7AbSwl!M(g+^nBBF;bx4fHts zn{*`hH#fjbwtG4(Zdy!T>9pjPsaO%V4blqSAf4_ayoODL`!Q~{j zISRO=l&D1MG^N?UgDonM=TU{M#rD2MxWo2?QxKj4_~VwUCEsbzm}75V3qq~dh)qQC zz#r(}vvxIT5$*|FxH>HC4xXmCn!+p~ni})5niJ8g}oGKDZXPzdgMp?wN?Aqn5}-;Rel+WmCa0j)R?Il^NpTSKfAY z%ctVe_!KP@>*{gZ@uY(voo)LR}~ zEfCs~s`CdttDJv>NXObQ#dC}E$cSb{E1l<5IsM>!kc4k}wn$PA5Wx9A6vQ%ou?K)V zH{^mO2nlX&*@5?9)@d(2+CP@WrOZNZZ~)mn8KDQA@||{P1lVE~Aw}K4j-E^4oTtgK zr_@t~RHUvcVCtNO5Q!P9LaNc1XRkH(0mDQ_PJQc=#ib_#DQb!=$&k62fN0rYrrnw3 zLe}8ryoLXs|B-N#o12`WjNeffmg+JXLue671P2nda3!B$ZxZaYlU{gG7{r2GW8Wmn zz(1NRaPD-DlxrMG!@3h*Wm^0NWV5h}yqOiJYAqMp+}Ejo3>ShWCMIgjWSkFyn+rfD zyN+eLua)#7o0UmwSd?b3(DKgy?ZUlkS4fjr0?(nB^rN)aHoR)RT+@cmBa5O*pH(|pjUUKdCRic$6o_EGaXye70AF(!XOrKlmR`mO0&e9Kx<~S=0Am@Y@ zVD|n6Tr1c5N(e~Eq{+Dp*fb%bwi1*Vo%&ccO!$%wcurbhQoWRsW8inHaz+~Q7z(Vv zk=T35?<>M-h0&>43<<0ra6uH^NE|Jq zZfA0Ll9iLCS3fDML1GYufD|&=*w(PMxAru}5($D6(BSvDK%Lo3S$OAFk;b{N790Ye z1`q!R(`?ymeALfRe4m#-WvMb+qGbRcj9jF-5>nZ-$$M47q(y77O>@)$-17I9cgAx<(-b4J^U101x| z0SPidvLOmxNGQtbN8YbSs$epu#J zO+xpA&*G1;5iiP|pVh)FB-=ps2ahdOB|JaRIG5XSmFf5924UR%;0BLp#R9c{34_0e zTxL7LQoIn_Ii9q@u8MGFFj~f&6m>26cD72q@9XQw4gPS!d zn#ojnFs(zgpqCA#ad$KC!bEqKv+$JXMa{n;35Ia(-2tH?nWEjQGK?tc2amywZrmj_ z+NsE;BJ*$c_}`A`xbu;7-Qh}4Ejj(P?~5FeO%CwU3F<*PMK+*zIQ-X_ZS#QEbJCy- z3$t$v-!wujjvodtq`X1|D;q+N?0>s!dBMaUw3*_L{qu#10Vo{AzK9)ZT6D5*# z)?WNXNbKW=7rnyP|AtSVmS?-V%J% z55=$Rzh$AhBo?oD#Ov@bWzaF7ZsNnMrAO2hp+jK9@Xq|~_b7w>&-%Sy=HmL)w@k(5 z;T`(>yIFQtS8OG3le$_srcZ^Q{Q-nDj9&SYr1L6``9-Ob*ebQrQa@V$^_{;wS!phx zeh}&z^_rNOT?`7LD#hD+fK|m{Wqpcw=oGF(eL5Rl{QBX|HJ$)2Wd+ok)YT^VJV_wk z4CPy2-W2g^>3UmSKn3ef#A|=G9$Y=#5>s!L9tS2Hxc&(vkA!aFn2hHoRqMI*)6#GZ zq@&on^PdCkZ+{BT0C1f)7xvvg#Ew^0|7}@KyZ|^Uw3;k*-}Xaq+jqkdCR69E_RIA& z1&Nonc$mm^M8kl_iMs}zm4;@{;!5gZNZOkSv?u(#fJ5|Zq3+nnBFxSLBN~YBog;M~ zjC7Cm>WbVW2sn<>0)4x6-rg$N6GZA?MPcin2gJ{A zbLN$uFsuwe!F9E=a6f;Kt%gmKXWVdIPe}VKGWWiB-oDjRVRNi4+ZBIWs>Oo&)5h5b z+1a;_8&%t2N^n)qn{h#x>~79zo`okh{*7r}RY z^(|Ypx17<_u@cV-WxESLx-tWMxTDI4iShT|ZHA+rrOrK$=jh_eyQN3%E03UfE)$Kj zCzDD|DGPziCOIqTs5?L8BFttf8~9=O`vqGiA29-h^i{%@F*0#fZ`Xk}Ulb~|Zlr{Y zoNXGQbu64jrZ|RiK<_pDt5{!g=2Zp-J7pYML&i=PT8jVh8vVp$no#-dF}Yh6BiaQ| z-{`t|mFPgVfBVTvH)@{IQpsIem{+*p9WQ?3AcN3FOuObcoXjo$vJNYUASCY}>)nC* z?+S^4TmKgd3FF9riGw`3O&quv%0%@V-6G8Z?Npv<9gq%LfW*63@h4-!S6_ozAaSSw zq!%OcsPN2z<9sg?)gQI}vhnz2bisMQjFQy!jJ|k=S^N-84Hm%A{}RpuOL+VZCNf z?b8jui0sz`IHngY0f-bqmsWbeSn%(G+psrtbQ?5ni)~KZ;?N@zJ7A(V7#4QHxu;e5 z2E}IaR2qO-411o+98>J>&5!_DD{5#-KY@6)!|{f7BfFm3B`meitJ+&(%!BZ2fvk+x zn68jO#{HN!MWf{^#Ihs!5APIlqe_!$!I>9%?~oK~xK-AYDwRh&NijtR00-m}r)$59dTwgTVjte-mz8@x~>Sh^cw7k~k6IAEUnA3`tQibzrKO*t;?7Y%KSk)a3pNdEn@ zZn_R?#O6uN<(sg5`w|-fw*TeSi5%fd{aFrwr^GjT^o(0Q$bFm7O_kx7tVDiSF-SO3 zIx}~##C1e3V6!Ou`{e%-f00B)^^pB50F5Rpcv1I-{3&qsZ2r|Y9WcE7eMhG%_88x% zW*-b>dv?*NaFlo7+N$Jgxp3bL?(>VPA8dPQSel_t(<1rUCLklM1nMavs z?z}`dAVjI|uYLcj-xK#k^B7Hun_WP1?ZZad*iF{QBfcLL3D>y!8yC2Suh~ay=Ac-y zluVLi8(GFt<7;$h*=PgVa!_!rA4Aso38>D7;*DiT>p>Wln}*~)6(jkSp*9clE0F&s zzv77=S0UM^hGlNRnxw`x1+3HO13pMa-VpAUDcP-u7?H;jn=0qg>ok%7iL{Z9n9CFH zt7qR#n7FJ9ib(qeLH-B-X8wmF7+n3driJ?yl&Nf!uHdEA`)QDYhRqSDPoA-@_!dv!IBK}!aW}q`dpJ8X~&wlIVJSAS%mm^ zT1DlRN~BkPHI!CyFvzEnJSf6CXgL9ZWJgx$;z=wm{>c7_)z|I}5SfVjsqBxI*UD-j ztM2(*8Mz@@0(h97QV~Dn8C6}&f*_XSoM9S_$RXX>1l6phN$&zuf@5o+_(B798yw;J zz7&isu&-i=dXa0T+`l%mNqSr{m!1b6X!9T!e0(d9Nb!GJ`w^Dy2S(vYKELyG6jFfj zkFTG|0)6gBxV%7`M1X^1MIb+A4M<)^N1-r@$tER)*^7rST06*DwHULR-*mC;KIDLbB+axekExfMUO2324!v(&N zgDYvci!CSL%4pqYHa}r~kJ@S; zpZa|bTjL^s;8mVMXet3#7AP4#{xd6%NBAi>5D;v*vGaK&ajvKbj(C-p_y;>o$qiD^ zXj+uOkM|tojY+Ki2aapxE+a4KzWAs;v{T?YHLdST@UP^9WzSYOT3Dpz%=H%7xmg9R<00Q%Zda6Y4kT1k7md0vj>kSqq`Vmrv`NgM>uM zaINuJOY@U5)q_mn4SfC&k@3a}QnJf8k+GSKQV z1j11V-?{g}M8)NRFyIu{g7d2VeBqJH zR%YGE`64idPYP^G7c?a%fRXsOn|Bj%w}MiQ_H&ZGP@V>ibfF~kg+lFqk;Gu<&ZO@M zdV!wC>MY`OOlPBFsl$5!Ii?qrUE9zR2X)q1yI=CCR7~7~M)*46Guzvb5-o8lT@m{hDI1pZiC7Qk+i3>Q~HZN3|6CQExpjP&2$q=i=Aj`FQlaT+q|Bm3Y=~i#EEN`^M z{lXlX&TW%Sy=jTbqIk$6trcbyK$2fbcOq=}hUCggugzW zYHd&?dlU8F3W5J%^RMcMp3_i6!gEHISyh3SBLr@f_;b2f8MN(q!Bo@qZW_$g3GI>( z%O#&)vY2{D7Lf&=Y{j*H)BJ}EtI0FVO$iZev!KWk$!iuuO~Tzd+^0X!LZQ!B?VXzx zFE>X4JtL-><03kL6Wxk>p_NFjREAI1;z8NYb>lP94P^f< zn+K%`c!%vw*Jx}aoF85?KKp|2S4ZFhDKO)xNm0*fX))c$DWzDJ8w6FUPZMDo{y5I4n|VRDkO}vsd$E4Hi&~&UJJgK(_4l$4i+7In z0`NRU^T=UIo;*?Weh4&eh7n{s`UhiavHWE^~pnu5y%+BZG<;S9NfZ|KEQ!K zKd{5Om8xAXu++P;Y60IcE2gAdG13~Y-Ybe(bA2(O?N{hRAW_qLxIj>WwZ+;fUf%-{ z78#ejrXwe=cZ5jINTCTNVhU`b-a6O=q57(T-z4ID4!jOu^293Z=vfVl^^0*WA=9x zvKvf5o&pqjjJl@mf4%l-ni)tR+b#iJZy+}4Z)H0O#q^cx+t^D?1Bp{XRe5q0)<{u0 zY5|bvX4I^tYiXz$>$1&g0g&=C%u@T-oz|NrGTox+0)YLC46sI(Uov*brADT=TLxrL z00VDC0fD^y%=iol;9%*eu(G@hjc97sZ11Ms96&pgq`6d1|Jz6O8wn`}PPXZzoF_Od zc<4kZMs_hmmy=AVJI$R1hgl@}2CoOK(3J{ceU}oXMSun2d;Q`hytZ#+Sj)iS&>zB?Q^*!oihIaa$f%_+{Cq?iGup|K$@sl}O43@G3Ezbus zN)HDP;RI>xrE8>do#mj9!>Arb`ru{Hi<5*nui}FfZ__OFRC;BZ`SVYI>3~i>yPnN# zt^l*(ka~KEu5M`R9IWk?;|Z4IYYLpdPqs0U$pYLEj+xYg-)`QH#Rz-ijqJ(IQt37q zGy6WoZ4jj&=m&Xw3?@GS}CbhL!EbtEe-fQka`7GR_ z4(;`iQ21Mjm(6+~g_8OGF-qB}D-#hCPrciYy&pkpM%tU94C56!@=5K|S*kZ|6OXIt zGyyu^9jg*=!-^mtD<(Sn@e=jn5SzsP!j7A;uyKo(-Qag;b3FJA#k+ZR`!&85+t*Au z8f!q#2vA173A=C2pmOgkSqOO^u~$Uxugb5rZk0Z=(aWkz3xX5;elq7m82Ym#_)%|j zs{SnF`wRnGZYk4idllsHGIgUHwOHss)YoE~^ruC#VHe@l=#PvtX#=aFPvi?ya7xX# zHRX)E`$aGG){OhLL$g%tf^U?HDLqr?h!Y0N>D} ze+ICWL1i21*z2T-2!GtYS0Hx5CPVy5TZCoq>T|WfIrhzkvVjgpCa`BFfqy`=@Da}; zxHmAU!ubUHNTjg*a;c& zeg}7IAA|t3_jV7KfyEd6lAO!3Fc?t4eNDet@?sZMZTO?^Im^_K37G^!z%~X5r+9Jp z8lmm`|Jcg%pr$Jj%GE(Q`?YkSL~=!Rmjj=R;IWv-XV-)aYg_e>b|ek02TH041+YFS zGZUT^z>tSApU5v;JCA8!kYc3tb0+b%CduYUo~Lb>Uc)c)c2=)VA}hiJdVqE9IVgN<9c!_2Bk;$#o%F*r<=BI@| zPWaCit=A{Z7n@&k-EC$s%{cC&GJQEeLTM&UFoneYIFF4pE z`tk3q7pj$~-8#A^*3tSZ==<29dDr*ZyjV8zytg(z9k}UDg~8x{ zEAXXyVvGlYZT^3Yd=eu_A1WE-i4vuwM1EbxPhk$u-2`Ig1@3yEiIYW-8P zS~Hv$t5D?XhkWSW)#Og3tyQInUs_to?qaY@k&b@#QJULS4#_b7CXs=ZM8mAO$4n~G z8r-t`-{(RHozSL`_AOfaMXU`9#|RU^cf1pT0}`1;=O%JEcUTnPaslx4zO8n74fW1# zPo85t+l@f%cWE7nRX7X1Ciit4us@aDx%}p)%nY7%hTLDNUaakQOl%O_qnNuHeIRTL zhM|H=Jke2Fcas}-L#DJNO}EnIf)hgZAV#MNtEmIJe)OjUgGm)83(!6 zL>5h?%!Go}l!f`x4HGqcq#GgBo#hoORT?wGk|Bcbh>z%d%6#si69QBTfzAQeWoieo zVZMYsOPlBTznn3+G)wqHk-MSA7ShwxdXAhnga!==OP*xz`Nd%nDG6}NG(O%?eW(_2 zO@i|F%$l3+W>{WGHg);R4?K@31a96K-3BB85QAjghdHST?0=qr?0-GKlNG@ZdzkH+ zm6BtXR&lVpqQY(qN|{!U-CpE&bD4beE5}2f6&D~{_%YlLPl@qv6&!7*Wfz;ZZjc(& zNyZg8nN$#=@(7NsV4c6C%NRw|PyI)(fv2oVF?`{F3pS_#z+@mZtomy9{?Xf-rUHNH z-L`o^?;bo{D@dbTqIc}?No&i`etNRQ#}4Sb_T4#-J}x9y<#3Cxb##%K#TY{># ze39dtZGzRHVPd9^2}HUxbFo_jdw}|5fQhF~*#5-gw5Qee{y!c;psw#dDZ_3DS1ND0 z%QCx5Y*HJ)hmMAvdwdXE`>%HB`(+@Or@}<_o#I@lP93mN*8_F}yB>TW)WB5(0O+LJ zC)JY8;F4zOaFR3AICyk#nDd?my@99jr@A+EN`5lHIZmktDiX>^{WpKE@qgS}2ArJN zdskYe(lDkv!V3I;Q>Tue)6^52t!+3|ixrhuGDnqV+0^^rP83%}T6UT3m^me?`@BS2 zEUKk|VPFW66XHiTZd`EiyQe&-BN|YkFl`BN#5l|w;R9}fB%X(wB933$ zlniV#SFzuY##`eCV`@57&xTq7Ff;m-aOfh47+}r>hDR>=zwM8tlz5)FPB6yg`pi(? z`OMmgyZ338#6)U#(>a<}H{{La^O`xIf-#%bti6~1*CB{;ggjQrQElP_>64^_oMV9RAj1ZEg1(jt) zQi&Pav&@80%2dKw#}X69*v*Vte(!hO-S_|hJpbo;&U@bTo-@aNj&$euy?)>8`dpvu zx<1!m31c-#7|m|I#)Q;ukk2o3xr8{nP9ij-zW+@(5=_0!z}~E|S`3PBuq5CSQcCDn z0g1R%%P-o2#KKmkGALylNUANrQloZ&X))wZ(VGp``HGc+dP~o%nvqCkL6e#Sm<2B< zKW-heO6AfygM%6GyWxV!s-Y;5$W;#39X^XAhkuRcH?2tRp2k;Tmj8#EmQ$V$FUl4l z`kpitQw=l(6ysnbunh?!VXMN;yLmOR)qeGg*wGw1fZutW=dzU+^B-Cmf%oF#UyMNr zP%Hg6#^8TBA9y)fz9AbqAS&q#W$1y;!hOeT$Dv1AyseTxlz4NI6H<)jLnFBngdr9f zLH=K*ehr5nNuL$^e3f8cSG7$cgLOqPhb)$%n_}gB1pNS>k^bmt5dQI{mdZA*lBZQ6 z$jR;5yDEN%y=VXA@}1~h-AX|CpoJ^c1AV^F_LNM}^#7Eq71PgH78>J18*-0>hgL&_ zF`ciP9sm(4^S~1r#;2pwQiLQPlblZ8Sgs0yrv&3cxR;UryD0ruX?(%YIIrL&72S^s$Lr3h8V0pwkS!~X+;I9V!@CN6|(@$<&xvr|S z?QE(P_@8zLg_VKWt&3Hj2R7US@c|&h|9kF#bA$P{ z+S|d{>!+Rv-$@Fq{+i}`jQOyoMxdUs9D0l5dEtO$OkrY>*9lA0N68E7j+Z+l9Ja`0 z5-d4**tQSihTI;3P^PV1-uxRquI?am-L#pHLgd^Yu%*Jxl$Uf|6^eW(xSapqSlwr^ zsOyn;kpB|aRLG&6g-k@gg7n3svH`SkSrN{y0ub-b-7G9pOQ@%HwB55ajU`Ho(lT+8(j z`M1jDLsq7FW$i4a{H7}{r#|c2IM+C9;y9fJ|0vJ#3drDCe`(0_cnx3g`_Fj(`S(2n zZR?ePley*jW@5*y?rPD<+aTLbLgLl{xiS^pX0fb_8$jTN+CGTwyxmZuBIwz_GFcAd zJsh?%?Y}F&$VFypW@5uGNt@sOR36CH+`0mWhBnB??3<88?^HMu)~$F(xWe|bTx3{d z+MECXhVQal1aaw@5h6``UeM(-s=doO?=Jfd{PxWl{2;ay`M%&AjZER}1 z@yx)5c-uXbbn~;K?r|4C_aW}v)+8<+808=N==xCd2*`%Iw6L3P@oY-Q@N5ebfAAcxse8|*szSDTkCR(6)f9{u zqy_=`po>4Oyi4i(=dh?YZRO%+;cM?#+z+uZJ}IcGgQg9+Wy{>xK`!eerWyaSGokzc z#m|G%g%FVw3u(`+nd-Yrb;ME8FuTU-t5A=02N>^CLIE3%$q+d%f%4Z?UEFR$lw&tB2{4AZ=2| z0Xq1Jj;Mg?1I#HPD&3(@HE~#l-4Gt0Eu#8+IIreI$e4Dc7TL`(VfN%TnJ$xT_KUpx z%c7px9Gx941=c1@RuUJ18eM60+3MJ;qpR{uatQro+$Ap$jI-(GQ6fWy4LX6mNjfh7 z(}t#1e=AqMg8q>9h7Q-*b%t@~LxFU%%XeN|=B*P>|B12=86DXM6zD1+U>9Wh%eM%Y ztG^8=xq%)`)jf_uc0AlYj-Qq?m;lzL>Nm#d@{;jTr8t6k`jOM8;{Hqmh4ZR~Hvk#@)ujkvzTFCO$HzXHSn+UEzOW z4`$xq$p+oVu@@AGau`Ig!!YLM8RU;Cy#ioRTgw|M*P@SwC` zRy}ZP3HJ`-M+aHb%ZwLsHR_H9{z$q73uVy zDKQ&~>KsR*dix|KbJi_=9&-%Nns!?6Ots01Esc7-r?-U_W^zBbm!dkzDyGBa-GbNVLC>*W_K5O4dzJ??7p_%TVcUjr;i z;Ek~}F8(vd&iAjCBkJH(<#y>X=2^-;0v0r9sNjltYLWvdWWeIj zRkeG>)T@ga6lmS}6xV(IJPams?eWi}x0bol;U=JYOG?Z#<6!K;uf!x)@Vz*-taV2t zUbu5Xlb$g&#v8AwQCiKp{*N(si*I`l`AZYor#zCcZag+|_;&IAPb%!D)Ogm{|9ONx z+AmudafY=QXzb{zoE`lnk-5_`V6|G%>ce_4U3X!13*WM-7j1d)<~dPn(?RPpV0mk^ z92cM)j0I9&!~N;)UV;wbDl3RYJ`5Xdi-@&yW*K8^MoKB^KWBF9etQj1;18Yn^+{4F zQdrqm&pcSu;hZy&Q~2y9ntu+3w*D-N--Ps@uaZn&nz+*V%TkK;BD9U2!Z@K-R(KW} zx~rQVCOl+zrIa=Q;~s}r;vNiIE;qUSsVTpsAxnaX$Taf(WA^EH_FLXc zz=1pevNi3M%*FfZ5c&Za?W|jSbat*H&R~&i@|L}OP*EZ|T_O|=BydfroNyA0H(GRY zW~NaSI%mWT59!&(Th?WIK_!!KC)XxJwE?<{e^xY>LBRMU+Ej*S} ze@o5%#iRp)QhmLo&4!YJyU*tzc`f%uVIj2n@R<2CxVs`fdaSJGM%vXag_`Vze&)@b|z;O%{~eU ztM4K}Gk$g5#HQ!cJc*JD7Jrj!^nO$Qi!?Rk$fEijkX+8V36D|J zAMk%)>Jj=Y((H5bTWrC@zp7@Nw0K3Or%|ELxnoyUYYm=;3@jh4ea|@*H)3KLVnc&8 zo*O?{FHXI6n&DXY;o{{_@T2wXz#_YBF#SD5DYCsx{t<{rVLsUWj=wXFG-%R?4xsKosm<3cPL_}@ocQT!Ja(J2$6z72TUV{`N+gF(F zkNDN73pzbBNqz4NGk3x%sp;toXI!$0PYy(9A4qr+VX!d94{AwjuMvaMg=n`Q=AAJorD_ZyPSP( z*;Ej;icB|d1hHJ?pVZhVIhDg14YU$m_7>b0tt@z{U%vdAh_}?x^zO)p-sI$W7m@8E zk1%s)pc&yvv-H5w{d3NaF(Xbc<%Ei^wKJuP$8h94nZ~Rv1T-t>HLO zz+@P~0CfgBieiK=Qd`!Vm_(4~js!oJ*nPS>Q(}TKYF10-jlhIfk&(yDI>+%waNruG z_zv-8%=PHec|e{%@0-;#5J7p^Kk_5kmIllQIMVI$j%rGuhOG|T>424mmyfRPsGW;A zckX+%&h3cJ1aeEDRBlgjFy83xvb;<&bUW;wz!F{xrDKYoQFuFx+L!wgJ=wWlPxzmxd1T@8R@qSjiJeWycNmvn z_Ur*!@7u{rvfHrB%mLGV+;wtz%05?Fpyvyc;fP_p9mDponU@;f>=*~M`mcK;PAKx~ zFWBH5JiRxE{gr+8q{m~tNvL7~vkubl(iQBUsSDU+R}R^WJF(DQ>Lk8(%7zcJ-5u~V z6?Ke7#?W6i>^xx+JY9!n{!c631C!5#02r_8YJ4U;Wobh5qilo?#8YqiOC4x+5Oh@? zD7WRGNoW}bEk3%BDrgoyAtjs4!law)S+wY+E!e4m5RNj?_PUfSeYx|Ao8X6|E zM`OGK9k>Jd)LR_6FckBxtZFt4~+{`dSV7yG5c(5}XcN;#ggI0};w&mV9d zCQ1?|#jmwOpC^oqKbM6`Nv?j5gTGG~q{=z#l7DSpTU~g2yU0_K^le^i?V>ByaM9gU z4N(f6RRtby6o2#c#8M*r6LDTbuA&H<|LQS#5H~6A!8jKj-(tet9DE{x6p|f2ZfP=S zRJ4K`Ar5{%QS7XRkUEj<52}sVfOqIxAE^mrO?*6G|LbP=Xa4=&C~jCa(qfvR7BQVZ zM{{_7iMa{=kt}j6%B$1QE?C?7~-x=?O`FcOR6-&{*lg4PnNA%%13he@d z;rBb{99i(s(`-~VdcEaj_~zvBLCk3QQz~xBi1h^%HWF-4hcsas>`99oMkK4m(9e1S z&MlW$|By`zP7K8(a5q74SzXsZZ^@-L5WkF!?kLbZp=QhoHAnQx4SdjDv6QT zX-nh{xDW0+Y}DlK3su!2O9PIJr^s4jY1RnrhfiK$ugrNt)1g;VPd4C?0n@2rCu%Q_ zP@jgDvc5c>=OdoNFCPpjMH82Z`A|V^;LYHrWvjIjb0Nm4;H63iJaK3TbXSDL)hp#3 zfOI(@9cLhNEu*MEMauhnXRYDpKu(vRj3?sayXH}JQ1mFR!HoRbGraGa->)NFy9OWd zL<{TPa_6*1;p`V*LbXxBF$Rn;`CLt}GHXPUs)>);GFWN6kbq~bpjt09B7@S61|k)# zy0upgq{Kg!jON{(E1KAe9%r{&=bI* zE{f;76am3N zDUjNNp8stjaIJ)>y2j@>Mb3Ucyv^u3Q#xt8GbO1(8=ExJ`CzA!F^akU_9oJM>3EPk z^hc5UlFkP$www+D^F8{*+Ng$-rm6lkl!l`NH1>()#ch_`bHq7h;cSKP7$l%uf3odU zT2_1^ttmiwna@N4yk}-{gvV&kH#&Ex%jy1LP7^lO%hkouA-Vu~yI3ci`??2+R$`9X z_*n#1_7hq<*e59#?s z3XbZJu4J!m*?{#eT}T~@ok3#*1jK18#!c>!?aeFSRihaI*f2qJypdxdLnsi6!uoGvap1$8s z1jYeT5HHs_*YZ$;wh1#k1ZiclY6dFH@^X#`aJ(c()8CGv_BQUWTuELMSC3#kdZ&2U zfE{c5{q+0a64}vi9hD{6Fjo7>$j5{PF*%)`wEpTxQ7aXwO#VkTGu=q%jY;I!)&)O? zN0z7i5{in7K92THwOixM4DcswUx%%e`zuaFJ_240*zZY)$j@lO=kJ&9-4^l?qMB|N zqGBm&rIWntUNFwmE>X+;?;Z2w7I^aBi+9*`?$I~qW6FRGbDci%IGTsiu zO*0J+{2Q@nu0D^9DX8?+AxD0ic!t0on0eEE;;wZ7mbrmE?=JWj8ZPX3F3+aOjsU@B zu>;qNd5-Nm-4+t?h@YcFEd;2HZ=5!&SIeheZX`-)eoQQ zfBuP)GN&>()72bij2bRrNCdVX%kI~nISyY)Ma}E_xOq+|FYoGR!8ruSHt1^t`Lj$A zrEC2w+)q8BFU?86pM5$Pl(M>n7^K1FA)8FNp|Fjkzf2@AcPNi!5K4x_+f3=^L=aUZHZxT zL$ndD>N_qzk|y1B*gkoWqE3E~>)nuhv&owfe94e~WO1^Ly;*b$707jAEhcO(NDXww zoZ+H|&FELR>NxEnH@sAEsyiQ`R?i}N4VV91Sx?Q!{nq4H@fH*@UrTaq=t$TTagnm0 zt2IL~dCozK^$h)iDNls?wZy8_7rAEIM1Riccq;sgh?>wB)DH4-=jg2VA=_IFJ^w^F z=jNSe7$tsU)@$3SYm!PW z*CRM{Enh7>16&tQhOn(e0$rnWL8v>(`{)V7cyGC$gVY;YTG#ePvJ22B_SzD%-8ovW9sGB@ z6iEN=kiolswoDsVTH+mC5qf*eA>H?G%T*3@vsgsoiEr<$&}z;*&9oHfN_H!7(~zo% zj0MD&Vo-k4y1nO(*!p!`UCto=_5&h&!nfpi&*=jn5|1;yLYSJ}zSzMpN8MWXk2Ssj z16Tff*(vSf_@dCI8^Qj+3YMdH;PY)*|&yuYw_)+QH^W~^{ zzPfXpMLwO~=CXNxwlzZvd!^t9h_vdoCflyY0!^+Y?;CCS20TR^9ZZs*4Q4|#YC@E;7mIkW+fBOgzaef}U zMR?c{20vV?R25>6{ie>r)(BDO@A(T+$NYZS0*i2fC!tMVOQs{E*9uXGqt@?=ILW8V zdpz5N)`ZjjR)lhn_SBJ=E6G=`uS8f+OrStSdNsWj+%Vg_X3uS5fgf#OAIVSKB_BgN zZ#4g**^e<}P1qh>_H*F`79~WrTlhFFP93ZI{ddq4CAA4sEplq`4U zSBl;DA$R<{P-sM)dgeLr{pwo7L(+__G{uCZC&VPY%-K2jm&0-X!x1lpPyzvHe>RS7lvPAwyU0_y>3Vd9JLZ8+4J?_jXx0S%NCt`}|N5i<8`zb(1N< zmM8J`_Jn#GJxm@%3`~=b0y!d*8I8HL6>Jfnc`TC!X*i{mUtAZd{?|jaxk%bSTA_5# z`4srQYM#6-?0=s;k6l|MFtVMJD97#lFR{mM@fKttq!viVqH1?;#akCxVzY2~CE?KN$ z|EPe661FqaIM>a{YAZ^m`faeN|mq zoTl(8utuO}X~$c}WNUh{^Oj8H%f`CNN_g=6Gjn9va^u$G%i8!QOx$fdwizLUyEMPP zs(K!ZlygxiYhh@61iDHLeOCr(^BB+fS?X5IcRJSu-16?E5YzShYeR~STK9HyQGB1B z3?vU{8?%~}(i?kWMh2fM8W-da*|5i4@V7|ZlQqBHZf|PI7=*rXxFDcHjbrcH3Hs>k z@*)+rhqut*@ar^aGmXQ>FN)i~n{m`ayqjvDPCa|eOca5u_WXQEuhwu&<=BjK;vj5; zPhoy_Pb@cN#A*c!+xh)@7g|aw{_-T`bq{_z{7t(58xWr9Atqpqz?d3 zi26u>1&dJ#G78$@^17V|2vh}^K=>j_0uvrNI$Z)uyrxh0`@!7FLNgoeBZL-Bh2TJV z@J@uwJ5346FE)hy;&Je8Y6JSg8Kz~U7aDU8CdVa~v-5x@+)pw@eeCc4{mhG$J>haN|uR!BoVanEb6i5I%Tc@|R zH=Rnqd-wnk1e_-FB8;8B;7dVjvQy}liS5V*2g@sv9NFa#r56$q$JQI~_z<&j2_!PI zB@Fo2qzgf@tD*m5@w68W0OvF~j3tZ=)(?!SJ^M65s>T+U?niAhDOMmk3a5FwfQS=2 z`?+hLSi|kv%*ntob)QNg*`H<;Pm2sts{l!`?H<>MvVRUY0c5AcTfAHa;{JX_J;BxB zqh=#2%1N= zvoVF}HjYp6m@PqP-5CInEzHjlbf!Njkc5OGUVH){C6yfXfHaPXnkb30^zm9BcuXg` zY&!IySh}#ugQ;RIXL@y8qt_)D6I*QVYflbf9qx4VqLOs-Rwegoyn}r{z0YhYYfh7cfXm_ z%V~`|^M zlenJkFqa+rh8m|l?@Y9O&#`ZFi9S8sr^PJ_DF=HB>hp>2 z%x*D|%@><2Gx^BpZoMN|8byouTUTs1*L2!RpN+lOI9$L;>Ay>JD4t&S4 zuTVHAuz-D84OA~D0nVn|Fj!q3SNbDEJvqp+V^u*^&XG()RFH^5mBYqE^Er&zl2(){1KT{Gp|5bX zhSYWXxRf65M9c4)-<02SGPs0UQ495>1Y5$(V+l6kwkqzq^!qG9apd`_KTvd>$0Au0 zxXoE|YnEIBv&F*#w-)Ny)%%r)jnbc%QhY~#4}L1y`f>KRbMRsLJ=wkS(v8}v$_105 zxQ-QQ)0xYCA)^O>>C$duB6b%fAaHBF%F`b;Lj^kNF;7noCyF?@-}SQCgdXq>W4ta1 z(UC|Ng9)~EG2NgoC*@e_HPa{>$GaNo!_}zuR+uxK!#l_?l(XCL{^IRjkhjrxDAsG_ z9{b4_6p1TQ0A;W^UY=vg`~m$JwhR<`ZA%XL^+F9-r|%1SDHZZObn@k>qzTQ@|x&QN898yl^E~r~CnV;OtJla@7q=WjM?2lJTCgARNs}9B6dpadu;o8-=JOe!Y$&G{O=lSJ7V1mBon(EU)m{ zPH`nLFW>UhyjzNSS+M6VwRSJwYas2ijDP?$iPBlXckzCETY}il zjmIgiUO;s?xZ~UT0~|?1oxR^8*Xq(1D9D!KlX^Nv#gAXfX}(Mr3oM%Yh_N;8z8x_( zb%0KUnDEOEoEnAaFGe@)gs$YYcCC=%5S}UT(#rS<7-R2ruxbMWY#6!TBy@c6(CdPL zOEm(aeBBQax!ygKx^u``F1@5Xx%LZ3+MfH|+tN5nihhc1Y0sIlAzY>Se^jRun(|C(DmZ05DNOo9?fnIha&&847H)C#(3?@PV(r^E7kUqgy7Uv7D1hRJ(`c-meaQc+H z)zp)+-W2Vj_Bvo9I-O4rJLue1K>cV5l3gq@{gKYlQroknF+6+5cjUza^kQul=e@%i z<3*|qEHu@g9G{1F3UDPZ!PY#<0VM0+cl(JP$RdnkEOxqLTRE|Ce8l4Nt3w8!JIU)3 z5VuF86ByPNsYyZ^ucwrtuIPvon}7|f{kJ*4ZZc!BBmv9W4~as^DO6Psd1Njf$u+-Q zTrN6_EhpU0LE&>N_{txhHaark~x2bW+CRoI~G>#trz?!3BvqB>hKh zq>jT1%t)dJs$+j~$lTHQdIj-&rINi+48fQc3ZY}}5;z+Xv`yTuu>^4r?2fj2c9A zq|Y*@C%ck<9<6MAmeu`2m0TsA0XV+I?cx0o26hNf*jJ>s&!;PNTQBhycR{KLA7~@q zNkf24N+J^!bMlV-@l0LdwFWPH41YjR@E3kTF;!7Utkw|7ndGDSmuHV1*p4pBKo_GC zUa&yg64C>NdeKdyn>c#kH(XlrNmHo&!HaQf^}8(N`!6a+;rVF?a$3`DCs}-z5;*n4 zTj?vY{L4AP=fPL+g8c-IA$TTW3)dI^P4TVr@48aBr?cJhp0*fku{D6I*xACK6>wj( zZfNa_uf${9H4s3E>0Lt z`C1C99VIQX$?WAQcji?yCbNYJamPWaMEgUUA!jK3O4v%Q7v#TexM1mZwWd3(ih6Ln zQ~&j^Nlqg^5hJ6`?-o{iiQ(Hqjl-bpcixTJbUQ+YGik!=v+D20Ty*TBBp4SU;T8yD z6uS5d>j`$;`%{&=yIPg1t8##STuareu0}+X`vjd~p^Wt&(MmK0k;7Juc>XODah5Cp zAI@m7U&y=-*&ivcTctZ<@>*ioH_vOjkM(;=Ng^PW9_M*&b+sm8hwJL13{ghBm zU|qbh3Bh}hqU#xgg@^ObRfjAw61D!5E=T+bh^0ED72Ut-=V&zl@&;IjZG!PqHSyQ` z%jyAPKMv@ev7Xabel**~FFS0vaUc2ph5DETq_k~6scWe-W&s;kXUehbnKNZ;xH@p> zqj5`srF8);neP~KIs}^*;no>(70a~zi0NZGVEx9p-XzYfV z13BSN?kD$R4#1UnDwbv#cyfyYq}kvEf8_TiOdQI44|$usT_BH1%-sbjEDj!4n2u^Kys!R**(qz&Z8)m#YFwRRQ2I0r96p#R-K8Q5&nRaI@u;hkFjW zeC%(>{<)}dR&vx0=vN;4HM)oLg#RV~RgA<|ts#^3GCez7)AijHmIa~(zEvu$T0?ry z+J1Ihdz%dI(A8_J38AXEH86l;#Q~?kBkx)ec~|RV+{I|8qmvV)wwZuH3n= zkEnRs`fey-CN@@VosUX~J#M?p{PnElAiI(MZH-A(9oU^Kd%5{4)Q8Blg`o*kfBv4I>7Z}5R#_xO0JNtV*f=) zAzeE!LgMzp_e4k%=Ws`R4A7K_H*@Z>`#g8fDKdX=u6tX^#L#8&; z97v3XN$)l<{RCwYa)@Zbm)zP`ISM`Zo?*K)qk>w( zp~#v!!%Qem-zrj~i;3#lY(!s5UI0sRUpB$(Io)U6T=Tr;0)K9(roE*FoNVzrFFj+) zU4WGDrbM?l5%uD+Srj`g*Mp&3yJ+cb{rPy zC2^4Fyy$)3ock=1w+z+l_>1{He;vE6HM9e098>-KgMUh- zo?&7G0G+t9ICE8ZNP&M+SR$omKstq}_0#CUvXI2P386o$xP;E1ezze0fc|mKgf$73*lD^f% zobgtVxalnJ{DqhW1xidJp?%*jBVr^TI2b(24k|20u?yiGUyJ$Pa{UvAICmZH(SU`- z8~mdd9s$QehTf9(efQuw1In$e*u^H6Cp~fOCbX zpZFC3_elOjceo0G6FW~R-gkw+>)FtTxg2$GksCTg?Kfezuo@}>4V7Wj_)Hm(Z{=e) zq_kG1X3uK&oy1R2Z2#Oc%nf?kRK48jhG6-!EQzW%!N)iuzXd>{sY)aBkHKMi+azAyFx@ru;~XcbiK9Dax$83l%wn zW+bCIO)jYc`nFs%Sk3&`sB%+2<-LQ#RdzJtDu5)%j1r1b_Yl~d448r)SLGM6oGTG` zY`?ss$J3jTgk&0dPS^2x*BnX;^lCk}+;RY7S#rj$ga!=i4JYU1C~n!rqg~A4AZhvG zcBoCjXlQpgi~Lm!`B}2ocWTX<%L(2s`md)d3v2ACtz1v~*P9!F!TNU_(Q4Hc(-gX@ z3df9w`+72y6}p?S-Esk!q}#j?31DpG!Qvp*6;RrnQPr@a&2b5ngTyi3EqkW zSkJgWvRua3xLX`1)E_KX<%@-)JX1tTLf@-(h8ooYohu>t&;~>sOQTuX8o29mBZJpG zuBD*YX%!NPNq@%kFQZ(H>g!CVE&qU4Q`flFd>V+>wCpilil24&6DL3{>FJhX~-jcfY9S&D7np` z3DAq9&|Y_9hw1ruA||YX>RT&?n<;f8vEC<8ZTg#-i~Om9KRI5t;wz(F7F13bzyl2& z$0>NkOgge?@fU?rAo9ew1}c&MzEa7xhATtq_&piiM=XRV&8#XpguUC}cDnNR%4bLacXXX$0;)tG8g*NB(?fAO5=+f zelcTZC`{VB&4`eL4mTWq z&Lg$rydQ(|WPoP~_fKJxa7;M|U1v&oxn?xFsC@Q=c&*_BF|vpn()q(ye2i0Ljljm) zptHtzA4!NAQ3BPIsMM@ z2H>(IJvhjBkKqXdzo1ks*VSik=c6UVV|m0fM#6~C=M3+h581*(>jeG&7!$P; zCgd>#c`Nrs)kE|J8e9wHYFAA(T$eLGw$F8qg}p@=qBG)n-D-6m2X<~0C6PaQmkBaV z&ewp%PHPBtiLXx$39M=S>Ljm6h4;Zpfe5NAjjIv5!y`D>?U>^Mh%14M>Sz1o+xP{B zck<0oYOu}7==T+=QOEdi)7S5wPn5Quzv-mTrFv{0BkJR|QFr%r?PVNAc~^2{5hcT# z3{$SEYjS<0@m_AFpojO(o-{&J`;8yv0d~^$E}>`J;cY$>KWz7G%j3>PFXAagl;@eT zH2k7N?S!l65>lyAaq9#9Z38!@ z%l9NM?sl=*5Mv$?2Rxu>eRv|&NRPFRbKtJ~`YPfrbf*nA58Wh&H!6_!nf`MNMON#Y zsc%H?*Q)FnEf=jaA*8f!2!=&2?*Qmc?w1Vi;*{ z$};MDTjhU%fc4cML?bhpdbt7jrs6;zhw(q znADbGb4;RjYli@vS5bXE-Q|VW8ln_aH3Y${K-=;+SF+lXuu3PVtDk?WQ5kKhc4zli z)Ei8^p6AZPyDdjlUCX1Ro)!1O;%fZ4zb(Uxlc(;9@mZlWKdaw;grtlbRh6XSYx%ut zOQ;EYeY)lxdumMnl`jQ3?S|iYXriaoa@{+Fw+f`FM;-`04%>Isr9b`_03hA7nLaRD z7e{wR8pBehe;lm``-v!q^qVsk9AYBM7Y{jb-${4QLCpR!5|`o+m2mpF){U4@h+e2q z#<1{OUiF!`WN7aw%PyQ|KZ;b~;nGIKl}Fj$0moVt`hA3#&YA4aWFLT2J|re0N-#zX z54K)r7D1-bdA}eOyAxY2ka73*pZ3Yf^`Ha;Lj74AfXqdyn#wA7RnPEg92W9?%O4>% z3z`PR>}K8Y%br3nIN9lb84=uS?Hn^$$2{@W!MG($#2~h=ZyBl2)f`$kgX)56SKt6r zbktp?@xL6y(0Mg9U;_9#0x|?(f5dL$-@RoX8~+zWj(&2AwpS^is z<8{JJ`B9c51xYX1f5Wh9G1byNP|F0%eG~tlU08#-=H#`QJdxWsuZy~3P-R+cztr)D zSltcf+tMzJOo>yUE?{hD6g!h9TFKQIGPj#$c|*F0`@R$35+E~E+OM07GM5`D@?*3x zil%O+st=-)YQXt=pyE5U>nj)veTO{U%hG?tJB|iwDR6g3OaXuyKW)ivgPLA%bg^gO zGrDgSi~Wv#nLs;l$aZ6QEtP*(g|Z;}fqmWF8MqEU^Sqdu&)?vlbswfxe&FJN7;yc9}y#aVqYBK0~xRFKI6aI zW+WpM|FX}C^BZ@JGzfF^qD2`;jsvtd`rV!Y_;npug-Y~3`U24(mT1v7PjonVfVQj) zjekV~T@p)rZdXvr_LSRDL&dn(cML&diOrt5ZNF9HR+~GKkF&7H8!~p@~GIkmB&rcr5V%9VnC zQllsI3)u};$fx_@05ySJI?#^FgnVXBRQN;FEt|JunT$3jehMCseGB!omcN>lZOPhG zhBI|5Edqwgf_2U99nUoGmhOGOkc@b9^F1wxh7+H-VZ<(MnN^BttfDE+Wi|g#cAp*Ey zVTFoD;=MbD+8qd4p`4awKN6@3@q&>WZM8(kQWE+?TpYH$ulPhh+7lt;9UB)Nd|$#_ z4i+r(BdLuEeQyW(FKF4Evi|Ebg%*(M$NzvqJ)wV6-~7QRv$WEUJx|SU2e_6>Mj>d? zZo@{+jZO<0y^)|p_!d=g>uE=a33WD)F=+jnw*)PH$$4!X7bRVFsOFQ9kxB*i**p{q z6^fJ^JtdB*&JLOEgoV;5F6B_Z;_}zV{bQIhczr`41^umNNgmuHbh%?&M5RawvsSJcPbZ~_z?w3>RVYbgq(@Of>7 zC$&j&y4E=@KnUL@?(z9h^~?Im(?&mhCTE%z#s%L3=x}TYtqJ1>8j!HP*Y2zT;l!p^ zTQUQ#I9YmUQmc?yLXo;!&3H+ zA0*7=i{fAAv;QwRV6{cIqU=XdZoSUd0I`E}pIkRcV_&jP_V{cWU5MU2VL!}h2|E#6 z#PpZ`7Q*dHnl9e@!eyUYabDO?)ZP0buNnTrCE2giH^EUqDjVjKnGeMs7Wz_FpoSL6 zz{SwZBqy`Ph=D1aw|4PSj-9vc(J&~nM$o<`&Aps=+HW*o^O};}uz9Q?VhGOFJ{7j| z-3q^1TJbC-Z`tVo@%E4<8}#I=N0jZyyU|eg-Lh>~*veDiM3cF@QT_Yz>$M;sIue}8 zqh6>H)4G=t&BOHjIXkK@eweCak?kxU<(3TI54PvYCZWEhhv70?0H02n73?Rx?mhAz zx?LX7t; z9-hA8e)Q+`Sbntzr~YAcrc{{Rfc_gE5p5$MxJSSKmhtC;Q*zk!umdiq8?ZnD}ofGPN>vus%Grq`bU5C@gd!crtw> z#Wr3)HF@|Cn)Cj#np6)C`{~b-=QPaxmDeac!Vm(DO@b>S~-NM)>$f7OC@l%E# zU%ifO^ac$)QQ9rqN*^$F_Ci$UOH)6%cfo?8Tjc`w2a}n{^eG2uLQP%%-;*~uV=EV~ z#h9Ufm^myU#<`XLP9<9%XTXsIZ`*9Y6a|5@M(Y5+0P^Ec;ze_$_g>V^uTA z2L+CDMvA~~eqa5!P3+p;nBiz;pF08kUPC9!O$b)cTZLQ7xX;l}Z(z@#ojjD%>;hv= zuUp@+&*0*RQ!tc2a6$6RyrG3vw#Apnwuq62Uab;@DKm8 zR?ob6=Y+vrNoIkp^QaK)S&VptT&Aw0`+5msYs&UoH8EzhcQJWB5Zn5~#E|bp!AOq+ z+D$8yq3SpqowX1Xq7q)l`?;55%nCv3cmIIRWuIGu?T0f_k7stLW2OeNXw&Mlz}SN_ z-;Nngyz`n%2=R#V_0J3Ijz&4cyOHlL+Aval@Yx2>5Dq*La${+k-*KtH2j55i*8gqx z79w8O_=RT^O{S;k7oB*fMg(zL>UOML zot=_nMMFIDvp%hAEbOAN{zP7uq3-a0r&j&DzMQ-%>K>)q@ot3_OYjhRVcN)VGKj{N zzv!~iR{noz-{rsPvXp)19?3WOTZC|Y!~9)F8*wtY8Bbxo>0_aRA{sfeY$}SPnWNzv z$cY`r@S6sGd)rxKvDPfQdr_IZ$rIX3$Dl4~VRM6ubSz0WB9x*O) z`(eu`GADLl1&a+zC zUk5c$nN0ozEoSJ477OyYrSR8*=Im@+ldbtK9b8+0l1u`J7vk`o<8^K$^xFAhjXHL+ z5De58`x<|ngBKH)@b z;`l50`lLxEJbn{d^K18{%dLAQepd^9F z@NuaRPHhw@*N(j5NfG{8Jx`pM6CAgPS_Yt2eDDGha5Dc7ckdn!W%q^+8`30&5-OWf zD)kWB+MA*$ZRvU1P&PyAp&cXHRJcbfw4o9zH0@PlP%+uf*iNOWls$u?$==wE88dUQ zZ{1U#_t)=z-{bg>_dCAtkMEzRaoo&3>t1VJ=XGA^c`a4hfB^*7l#{^d31CVSFE^zG z`?kL2f2d%*P1JrIh(E%28)3!v7)75df6)`85wv;8ysfG`;oBpZv7lG`7;PoAQyu*c z#e6?xO_WV2=y88hQHmK1RP5gYn)SqNMufG`1&gT+9aF19w$jjT{}1?bt2;7Adp4F2 z#OVLUQcXkWIbFsaq|RZzTWko=HDg?vqu+Bga>=nkMYhtNRD24Ot@xs zw)8m4{=S=zaa#o)F~YrRNm`cVF!8OeJ^JU z7NiwJLbGUL;FYCQAPg2Jp{~aUj6L&g)qT6@P^V7iLZSkMZ-KnV)7wV8tMArC`Qwtv z>RCB6-I;DEHO9Gol^tHAZR%>6_UL01QZn<9&hK_9SGRX?mm#w!$ z>GE&0T9y7%D$<#C`d4PQHn}Wk%(x5rYWb>O zB6elF3cZCjP2iKc*0~F$L)s!j=?Nqjv~OWspaVgjt986XuNElpv+#xBr{$48QS7hU z_VaEA1Z*Dh>y|oU&2a5TSRk@S^Ct$9-<%eAG$XBk%f{)0~QW39HfsNNL>r0Ly}80`;w<$BzXr;D>~P~G=I`^2pKH|Qr`-nMnT3f%JSgdf73`q zxS0j3W<9G?yU>zWo#f~LzqNa`T*CW^fBmx;MT8vf z8j`W12Bf1to?s+8%^CRzKjIlNFL>UyVTMaV50`2Q3_;-#gVl<5vkQgZP#^V7`6S8_ z8}pdLpQ9|3M>s!8nb#+U7HCIGy)~y`QObi{4<|!znA~zt2s`BezQxr7t@i@Z0 zPO4cy^UlN6r>=y=)S8Uc+VaaC0-rAk zKk7?8T5k+T4~L)qm?Us>PecU0WZhgeip>n~q`ANS^dSKZpG*DXAGKB@Cy|%huDEBy z$teb)J))b+m1v*@ClOaX;&)g461=&SOo5?z>_XLxQAVYb>-W@ZBm2JZ zaB_`dcXx@A*Fs=w9B!b;hgu4b#Sh`yU=P!vP4$mTc59nPnSXF2yjiHc2JQMo z-{--?l=3VsGv!D~Q0Q!UF(q}SNW zrImRoC1m{y&QF5BO{oFCL&Z%I0cSbm^~2u5Y3y`woAon$&t|D=Fy1MMUuVn>tQd_S ziXcW5bqX<{XHM^GZ%QM5C^k@R(7y=`yNn{X(DXKVbjy#az9;JP(KXqWP}@F07ZI9C zMSRU6mf1NGoUV;+XoKvAwPn?&f2+M*q8#0z9 zh-SZw3c7aRZ|8#X<$2JqR6#t4KnF!cqVAK16gk_n(Q9_e*8n@ z=)4mibAtE=COaSd6|KH?`PMea!o<{V3?nWAL&o;YGBr>27k9vOY3$!Tc$@;Ky{-~H zIK>>+KuhK<_9C5?Ns^(HhxiR3$0WQ3o)pU;>D|NJ#oY1X zUTW#wkoy#kL8{EW6Me-Chx9T+RxxhH4u|m>OX3pG-56lUd>$}4Tx zm73m{+PBMM+)ix2#a8cB%L@Lpdc&_d=e!-xxg>>#R@sW8`s(g&BJLUkqno=bu3ngR zE<1`p`?$lW#=p#+pZ2^zJ=n&6zsi_;HvLhSctO-0U+uf`m6J6p6&LcNo9`FdT0xsu z+_6d!+2(oGWY(;e5qE|qO^F+dj&Reo@cfxIGCv^sS@l|6PdWJP@W#`JJDye@ZvC~! z7F`2Hr^sEne_n-uULAhMWL`%pLQDJbts@0sa{M1)* zEu($rFjs3^vBDDkm4D5zwy_~blS61S%_@u8+?^$sU(^Rn0k70jf9<|mn6L^;nxXn_ zc(-@pSL{Jh-%UirC&54a&^F{!J*=Q_I@Kz_BePDv>$H(Bi?2v{(!cRFGIAXm?IKvc zM4@5=yCK}=ocD-OStD`3kg?a}NDf>28z45;eEF^CKLs}?%z@j&G0*{II&*^z19E29;IZm%=ge_$4kO@^3r2i zQRQY?CsCF^N=x!nfqD>wb?@C4FPdh3mLIe6MOjmXHMBc<)z%P$(f#OYHsW=*EnVc> z%n&D=f)_|1gUvNzd$yf#7SM)88ilGCTKVA6}YVU7W61fF1hcC)}hg^+i~Pu7)LESA6-}y zc1;ZYXhq*mvqbmKPRY16rKQuL_$T)3A~>?H%#?blj^m$xis)ixo`Rz2okVGPB@lF7 zXmEvli~87+Du!w%Ri=~@JE%3uV>=vRVH;JL@A7t98r-McoS(xAYU>b9<;Ce?T%K$Y zVd=l3m2fz;(CMUoq#}>TNw=IsIY7J7+$XEfJ-moRUzX*HuY;wWz_FHIkj&s+*r5P* z%^Bis$!PDu!=_a`&z4ui+8LMH&A5|X>iRogk-K{g7yy{iQb{6vCR*ay_K{OlmkxVR zw0D2V1r0G_uFxf>WXLW?KZPlGB>V?;ud{aJZ#1rfhiS~2U6xrK1*r&Ae_mFN(w$0w z#Vr9uhBRB6ZtjHZrZ+PNYWSvHzP|KRha~lUVhx0Gsb`9QLl=)KgwP0>Ci%5>Q)bM< zjGGD#T*g>~ingmudQpxqFMH(uYWLGyP9EP*zpBWBhNXeb%YDqd1y-St>$(GA7nk!+ z$Akv+3Ur*og1dW#pgS(fubMIT&*{KFEaSM9z|H)%_7rfRk)pf zX`*E}IIQAF;}Vv%MRBsK98u%qNkXE#Ti0l7u|i~gx#_`SrbS-p`OK zlFpLb$0T-_IY+^8T=-#MOzb&O1J$RoVxq^QDxtEQm}vn5&}RMfqkyv?&@s@y5SsOm zHR{l>HHXFLlj<>J5*Xyr((A7|RWS|gj59^Ky$FN^D#D1{7 zh08N&0h1Cq&WJR=8f;Hx>eNgN%2b3?>vhk-85v@9xh-*UMf2PzDkfXmm(nP1#T#cj z>{W3eFS%>9hi9ckb7awBG+>Xi36lkHf6Q;}*vycbAu;iI{<3NEJMIXWe|RVj z5v!4l6Vz>qds*f-%;ZIvm95S_RL(L+MjKj&VCDwdg}7Zm3oFS5@&6?$l$7?>e7|EE z94F+shuv;6fs&(sI3=c@UCJi6w|nY01o+VZ#jk;ge3CVL-uRF6Oe zuiXU!*^uh@EGTmNXqsitbrr^uYbV#Q7wC?)`|h9i42o1|G^XEW1iGyRfyPKbTVKT9 zx6u+T_Zf1^>ROx8XZdu}ue(O5!9#b;B@&#`lMMOPKpKFRuXYox@}&WL1;7o!u?@)= zzJsTiJw#iD$~)ILhajiWJl8BON^ZF)%<1(HnACW~v|Dpj8Dpq#`qMxW zr7Y&Xn}6qYSCnj`?7q&;h19a7#O`obSge1^RyFcsr9={LjlV6Lg#UN~RI#_LHb>j8 z;X~$SMFq=X(*N@4XWBh@OirrYeAj3S^-Y7b5)w!yO&?IpLnm@bdC4b;mUkpVL|Ey&OW6Muqcb0>&}J!w_&Lo;GPzkF(c$p zPHWzGqoJ6SJpZ6zkBBi**8Nc_g=l0IFl95c?j2$Ai3fH)q?~QJy(8ynnS&`jN(@QT zts82s1Mj(c;ysOM|D8JE`5HhORU$IMTP;B!-P1hK>^Xs))dnWT3Q2FWP}uQBK`=+C z3!LVywJXb!457<%qienjh_R4`P9$cjHT#{i$BAAaJM7&P@BKdZ`w!nRy^tk8MBNU@{D4Bi)l-Q zHu($eh#*zU^uF{VVJA$gal z`@R2O7mRb(`q)tVajy0aB-1QI|40Cy<8wx&dESqO*^-0jFyF=V(u>& z&}XCT56G?g?&7!talyR9q>X+1!h4hCzdyTB@yu55rk=_i#7*cYjFPQt=_Q2gBwir( zy$8=uvihi(2xVTAfqkHJd~Hb`;|EjKeIFphP%Ljj0YbY0Vf)K9#pG7 zJec{4^A&z4^#<5nNa@)d1x&Z-uW0Q|7~aeLi@Ei~fjktsG;p18#pAoR(GyPD9A`u1<8DL!DJ+Y>rl$nS|db`HTAm!JkNn5_hnJwE!fx zp5EAbOsg3hF6jx?JQ{~xt}(d#x@8M%I2c~3VYH-Akmpjf|`RDl93 z;6Prf0|Kq^-t=37)vJPV_3|y{mn}MW#tsm~%QI6E0Y^4dk#6~77|+oZj*C@8HeBUrhIlh2c|}yA6V}U|D{5AN!fAn!1>8;s0j57$0zgNUjl0 ze_dVOS37Z2yMfIZk2BXo7UxYrem)-c^A($%Z3VS`jSf4XZXs0tnQ!)2+)vxlGG7?w z98<1=Tx9a%p&srJMnBwLM1>TCHt_!3ssVY|tXG5~5R1&!*8=9~PODoBlhVw3G+5)0 z0>s35y^9^>i;kqEVqePDACgc}HhTLj1Fo>Kuh}yyn`s8jCxtb}hSjifne2b@MecM; zx9q-NS_o{pQ<&qWX!WCN|8T|Caa`<3kGuxijk)tgsl2NOxkocT5SM2~{~?>JOn$<@ zN4Zb=JfuV0~Jsb{n&&=b_!m(dD_Y6W#L3%U@#p3s255twa6ZT$^pf2Y2D^r-35%5A;~C6yG;$?1(Tur>wZ3|CaDJ{vxeCMzyi-{DshW zX@NGFsl-s(a&`VRL+AAzlCiCl(92xew~9p0L91-l3lp&E6@6#`T%1@S0^N%H$QQ#O z1;SQTi6I|Fwcg=fnb> ztdE>NGJE8`)%1S<2lfxlIy`l^nuvEi`)9b>Um%|Vu4RL+-*qT&yAAqY|5@r1w(6J-I z9>#hF|86vu(&T>VQ?0`B%2I_Fstu`|vje)O@w;|<1Ro6+y+w`7Jb^bb_0dQz!=$Ny zdD3j3E1L*qYID$XJUx_Rz$?W!gi==Wm_J{1(NM}qe8XIQzQv$xH_iq+o|{fh@%NLk zc~q-H1CmECjJ8Zmmb+*A-u9na`qtmjiB{9~eyI}E#>)|Aif0VlhyQp-X!}EM?-#Ej z#w2lc5iO*QI4I*CVeYQMdt>A7KaaEXLOg6R_(=b5Hwc#wSmCPfy|8?0L z{=rd%3t|*A5juK3BrCR$z{oP=D)sL%|97oM{)EG)4$C$jXxDw9>I}oFtItZA5>*Wo zSLPO1GOkSiN_k`;{C|B#jfg$$5|xeM^@pJ2Mpa`m(T6x(4k0BdmzVxTxe$nCya$!r zxN<29c!I|`uC82;&~9Cf4}q+$+*Fpz{0GX?VKcR-~VB&eF57 zTsG{zD2lwygzi^7u^U=DxU*@eGT6R-2fvAFN&4@%ei(1xe63PjLx;yYfaYwNt@G^w zke?|et+=k_0R@y*`i;o3SmW~|?b;7t&0^KC58qCzH2Gd`W(TRvFQKRe;=EAP0oHbmq;6|V; z*u%V-@td|+EzACRAdV%UGH1n&C`B`Qbq(_LF*5dpO*1sIT$#PWvy9pkoOEi9>ilsu z5=qMvK1005^g13XqKwC;sK){=u+)}JjnrxbMPTA|hajymCX(MF*Uthn1+wdpfBjFI z8;;z5db;XJOzO%#0mnKwo8?yasc-1a^Jt8CTfJr(EZGfol%;WdkGIi>X3_@P-W6%Z;`R(wE^(Hy19WCH+j8Uuks}z44O^LYoMJ4nuD9* zgp&|oCp0)56qQ^J6u%Ugs129wOVI*{w_uTV`=$+VG2CLxE8#IXpghuywl%!RY3N~v z`6Vuf6zs1?#BiF{LXfPp;n9B;2e$3OK!(GiXt}T%=ZL=jU(cVMS0mptD@KuS)V^#n zo#Jx0JQ&w3-~Uy|6~+ro9uwlaNMp~>VCU65S7tDdQKJ#NfKjGQXdl5D(XYRdPIP=W zbxU|p6yiT1c5ID{-p?@yHP_4l5fw6I*JtdWYBh!RR}9kk0Nt9jD@Ru&SsI7L0+QHL zVa={+InD3J^t2bFL@p8*%Or3aWq5)#q7IY`p{N!Rg+FS4%W?+?|4%y+2F2GJdC)1J z^`jK$ANGz@G&5=+YrcRf8JF77DX(F@P!gmSrwz=|o&cx|ZhX!=OL#51g(vKV0l$RW(C zkn%Ri?jm`F`)#8j&V7-nw$I$>6=ibsZQW~rEvIe6Gy2M@scsL&!tZ(AHM=U$OlSO1 z9)vwF7RlW`7biAWWJ1)^YZBrKG~Dl>0Muuz@`i**MIdq_Nq(TOp8fW(&gz%YDiCqe(w)GKL(BD3 z`Yu`0R|2xE%>}Pnc+&86?-pm+T0wOq3bp*rS>PoEX~U>#Xkb9;5{dKtm6=6~hAmXO z@o7K^w`{;3cev$cj%Abf!19Y6M=Jwfm|`THw|e^nRUT3#-HAiC7{#4Hvy#Hd|~x?#G8bj8Df0#|jp zoW`&lG@+4kYQ4b|gUY8E7kWa5=gO0FJCmBP$>)Z4xG2hAkg-|IgRp50u3xuj^P^zZ}YM_@x8o2cV}50^j&l!Y_K z%x}iJNcLi$faGwaCuPJ+KQ~gk6~+pLDK&ydu+-+&+&zOP?;d0z zeT0CUU{sPbnk0CLYabt(xwzCmH?Sxb(YjVSmdGfhp7HHi5Yg9C2Zq(IjR29{lLmAE z%w5zEL+4VR5D+Ym4`~k&&KbWZ`E>mnN@%eG4UJV3CeBAeP_+o?NZ>eR8tmFT+O)r2$1uI0KOIvOFvR+e4;>ULQq`BX>gEDpV zc*lFH*@p|{p9z-ab}K6;trRa4XTSu-d3e5i6=)^hhmmRez;QsFeo3-l#JG|y0c8DH z2(*zmo;zmj*_|3YfeeAL*m9AXFN+w9Oj^azR4(er0zPKl?#=OHAq&)`yZ^^BjClAE zwcsj(-5%w)+k?iDCl(R@vhnXs9xCiu3iuIFUoe7b;+heLOT%ckv|7yUFBQCEqSbmgg>VjU~U5co+I4*{S4_ z7Br6MshNtv z(^m3#XA|^nF!lI(4qY2^8_-H)F*u~LWa z9(;H5afNVi=gw{~`mae0iASu~6l^vi6OO;!_IaxgbK+8uoYn}k0k1W}=wE&qcf$YN zvf;1(xg&@SUP)*S!ToX2S`8O_%R1c`pBz0pwhowvQjV-}-%IYLTn?EViYDB{AU7My2(}M$Xm8gjjQVZ)Fn)RK7PhFL{5Da7t~vLzWx-{KUa^(WxlMU4BsIIZ?MTAcgBsp7H`=7Vw^;tVWoZU z73WT;cE`Fup)9+MJ;$+N)(o035Z_fhQy*PU5-P8)cn{9mwfCqz(ypI3G=sLnws@5m z8XMAdcmwvSy3~DUJbU4L=ou}jzdW<@dd?glMTaUbnddYh)^ApWa(gy3^20mw%& zYZq;?%v{kn$9?ztP%ksFHt*GM-y{LRZz47}n|4=eW0U_*UhMFl#a)_Z9YfJ+Zqv`# zi}U41j$BYhZqmf~I|ser0!N$4SC&~(hM%VNlgFgJ-T6vez0D}CE5!Wk-NxkeG2dk# z-t{`#xg})hT=+G1Y_M1T_}llWS1|lE&j2VYMWoqX3v%6Es8{%822|(^EIW@R;X2ka z1}UKjI?4&%1|Z^zv+(~9Bi&l8BY*tUzl}yPX;G_2*0Ve{e9o+tE$ees<#MUQ3R3k} zj3M?uE4k`7JI7GF9)TY&DNcNx8fMl zNn%(c%f!%tK8#kQC^du`$NS(Twmt6=LnySTq2Fg)u5u5wL|5!OFAAQ_qxbx1oFwL5XdL2es}q7KSXeM$@_jACrK`KU5zi*-{%vh(Xzj%iAdHd~WzO-71{7&A)51wZ0 z_I{iQztcKFl299SbpO&YnVx-CX<19EMo;u#wW`KD4B;Un{g1N6X%U!My-GG(YcL9xY{$U!MEgryQNCL#v`<|}F-jEEF*`KXV zy?EEsh#Z7r-0V`w15nH5xUiHvS6QIV5_4N3sl%ELdno_bYkzhe-S#a(Bj1(z>{hp& z2Ki#hv?S>F7sSlPvVz+o?Xpi4Z^ht$zF`iTshgMw=fomq=|^2`VUHG@6TQhtu@7Z2 zVi8r%pVT2)no%=(L%cW`c2!mXC(0!Mv#mOA_xc&P4PCDtXQ(#Zx$AVlqa=1FY=N1r zs}{c>&AO(6JNhOA;8u??3|nxQ1`tHiS&b+n-dkRWBGIgyRU*>n<@~BS>oLk^jXuAT z!AyI*W(a8mb4{UDnwi#Q+>z}VzS;eTcJ5tosxaQsDh@{X7|jvHPj=bBv)t`g{6-tE zf+d#6t!r#X^{F8`5D5|e%lHhN0TM2`ZQFk)+OP#+bcRE_E3_(-Wr;^M3(g2+%4Bpj z$f1<`jx#idU76cM$vD3-_2J2Zc!)k?!D`5&eufh8STNnp91g9=cTLMZTPM z#ZHEW(aP$IgH%pD8nzXuY4UmsXJSW;OiVkz%=z`C^EHoq=LQy-i+t1{F~FYp)w46_X%c%=Ovw0oP1J2L0w zM>5kf{Wk=oB&tO$q79bWn4y8J^OS9c^glIN|Lsyr-^ail^%KNawWyF>{MakCbWPc9H^O0Ht{h+Rwea~Uim*vlMT z^X0e79n4RSNuq~GN_>wlwo6r|1+ZciY1KkzO&irKr8upD@rGxIozihlLw~bW^PNJx zC>3QxWTfEt^GuIiaam0AI4J%wOXw$Z+%%P*awS+|sRd5iF5|4KbfW8d{LgxEZMcpj z7rwLjHGmkw4go$3#6b2ACf7RUY|mIon{;_=Xc)V@y3)y>{@m)+(B9$!LK?GcP&6Kw zbb%Ax`}Nr=Iz3FpKX~leF`j^*Kl;^pWi@TC-yejsU+UoYN06R`T^h=cs2lF5l<&Oq zQxWc~VdBO-zwli?rAPLk&IrX@Mjp#_=>Pc!-hq*aQgua063@VQ@#~+5fLOx&Ra|!? z@Ylk|ig|L<6|bxXbR+^;e*Q17`ius@!kpa!p19}5+b+#NA0?kjMTX_fr_&Z+R&-hd zSrmFUu`tk@fHKmEw@zq%id7%k5`DtesrCBKLUL<}({`JXa>02#f(c;WzXcVQg)8e0M-DOqOLfYriXnY3DH?st3bes&PX&&abn$PLHJ0v# zg;P5rHeiv00C9m0ha}(s)}eK3rK4Cz2}xvA^^sCr`I3hh3_FA898kR_nE8ePsxneK zzn>*$>^HXb8QjoOnC{Na`H&1ZI<>y__%A?l5~eF(d_OY(<&7{ ztUj4hJMEvw@x4TWAuw1H85ylSXmkT6n8fz&+$;&hSg%9Qs=GM~6C6F;hy~-oyy(Z9 zu@fs)^tXk@tgy}^RAmTnO*0edH8Q113I)vVVViTc?xvw-oQ{XA5T)+_lUB3(H2SdJV^?_j?#7a^M~vFgA+)vYjjg2c8EI+S^i zRArtZoQ25WP-79)h@C9|9ale@`8>vi(j5YQJq~tFddw0KI3K`sHTK#4rb~v}zkimg zzBc2PF%rHgxNfdgNKvI@AJAtK(L6ADr<6K?I5oI3EmC>eko#)RxZeO)w2uq#Q_?8) zTsy0M%u(F;4>4*iY67u5ZnRo@6fau_4|Z+;@n81m|7fD49_L51 zbd-GQ6#oIeWZC zCr=3#oUMqMJKj3~t?Cu)S57nh&sE31FWL0ifZGH5BF&#bz3iGfUC2exufF;GwMUMF z1&f#UuPp2bN=s27sb%8(6K>27}s?#byuyC0R~`tjxvFVQWO0!;sXD>=F#! za=)*&+@dp^!#H=1!?+SDoxL*xw4mQ7Df1IDB`m`ni)vXK4jw7YM-IngRd4O_g%hkB z4h{-8j&V8IBWR_V%T$A{f>&>u={(c9;I%rzV-%NbL-Z{U-oT~|dFO{&^|I8+incT9 z3-D6ne2x}mYv69;<|~g*u{FznR`k3oS_}71KLw9_NOnTY<%^Wth_3CE9T|O*+oOBP zFPRq6h2UtH_{9F9esD3Q0V)If*tfhG5zQiSRFci1 zj!a)<)(t_Fv8!{1g_J_?6d@9y|zbV-gC1nuZ z4~qehBwELaXw^^sm%#ejmeBM_uWX{CbBvaeN5*>3=d<6*znCSj7__6%KQbPxjg(wC zHJ|4^tW7T4IJ)?J{Y5$gZ62fYnLhZ(%s4 zZ*&n~ldcUif`})@rV^Pn*&s&6=_y%sGOY0P=gerhKC{qbNRD_G=>EVkX@Lvv@8&+4 zyB`+3)u~s~%9J}MtV);5K!lFTTk80JASuKHFvNQww1Is2>cMZ+7=v_iAxOGl$Re^{ z%9)@1%A;}^kSFw*7a29u%K}e=VnfmnpwP z!$eizm3a#Hl5P4E*+gP62m1qV@TY46I%G6VI_g&U2_`&(?%5y5{;FdNRu^EfO{K*R zSeS;uj6rG_m{dYl$i4Kbs>(;$U8X?agKg%feth${yxw#BLjqktq`f8wOx|66y@=<2 zo2ez(lv$7&Vx8tUE4a%Us;W*dDd+}&J8!<53ubK%-MhrB5v(N9b0JHe)D%5|upqY^ z3zR|@v3Y(EzWv||*g{9@JgmFMxNuioD%iU`$eN5Mb@-#E;0;*lr^>a>NNz^F1f)n zw|7V(oTj8Y2kgZWN&tq!D7APqRpU_Ui*oD;&Htd0Vl)m!Wr2ZFALj>bmrg>*W(qqMU+)$)zO|MAYAQ0vg1!d$xAEF!sP zTIPCmKu$`L`@w>SA7C?#1z1Vvu+3T>6^elkvrBFVc@fn0jNmfMBk3Fq;Q)UWx1Qj! zU3{zQ`hZ-h4HLFwSjdTQ)$!QF)X{zVpCx42eN`K85!jLWS318- zb(LtoPHTo!|CQ-ui#X23bk#){T~ObS)mU$T(uoqI5!3t<`|vmp*F<++*+fj%^Lo}$Lis{E{H03K7px<8T#yy z^GOw!skC^1Crgz$B4x~%wr&|eDJ~Fl*a6DnrP>V%pLM3rD#a-649dW?%(Dskstq0K z%Tl2-iaoIY`?T=UpVBA;+83;HFfkXfwqy-mS{vQzM+ z!DhU3C}k1j;UY5O5Y}AVJ%Bj+G_YjuABS5b%!V{zHUzhfny6>6x4KlMdIl3piL{Qi(xAeTu?BU5$tUZ#2k$T|Z3EOeQoZFj;`Zna@Q5Q%-p>jedr zqL-9Z@+b~QHwUO$yskTU!7Z)5`0F0xk|8HXHR zLc0^Ay5M;NxyAVl3+LuaUV_5@r(Pu|doA8F%w-tidiI{3)#LHBZh}J>Q#F+ARZ=ra zn7MGJPNYj!?w5BU$Aeg5M}93qWR~Y-D5~(01x4Yc&CX9{H*6V|u9Y@|Zan!HR$ z_HK8#31|<#RmRgld8~AsSr7PLsr<5DLM*yF)qmdq{_09SYo5Q?etM1=b~!l@+05gK3uy-(gtszPFU$=FZA+?i@zqCF7^FI1QZd)RIGuP%ch{cKjWgOE>G_77`@ zz#dw|Rn^u~F6%^@yp_iAWY{CcknWOo8YW>BV)m zs(fo`QpT<^d!~*;GL(Q8h|=s*peJi5lzLdgVoPP;_R1z0Ro~(WBCz<-Is2+Jz@YRT7F;FkI|a1eHS5HM`n3K*#|u?x3YO@T{V$+XLNylp>|eooK$Oc z-X~Xs3nKaFBEzRoEc*!CzCBx)F+&UnQc0J!?au%g|6$*oYW;C@mLF=oAg{_T~4 zckw|_<5P2P{3snNp}im4xTHEY%+q;JdFeR~w->ACCx$FC(VY_+t*#mLJ^1eP$+~Bg zLG@#|v%Ac_zt`&St)~u}b8Fep&-9+o7j2M{RiQ9DRCFmBGW__cc=uExUlOcAyXSse zKl0;jH|;LR<5kybXC9xaXh_aO*Q-gsHzqyr{hLG|oD7yEAQnACHo_BaD;e@>CyT+$ z^XK~F&|_4epdUb(aQg}(H2pJJJ8A(4(9P@Fb|gtS^iL;K94Aq=Wuj&1PPucEC5!}1@A766Z+VX6_%%(nOO@~#I<8UNxsbCiG>xJtk@%^Cv^kRK(@Eq}QL`jM%f%wb|gZbja*xi~+0SRcJRwiGwJ4 zn1F64g*CtnybU_KyPw$4{v^jo!YeW+r^8`V8+#adJLE`M<)kqvSL|ckFke1V?(uoF zMw=G&0_+D->e!&o(C&W-INr6ERuS47QL}%33-Si(h-IGqCVQ%@eV3hjRtr<*zWW+t|ZW+r5h^Gf{B5p$^9HAhM4?0w%sw@lQjbCO7SCJz(cuS9u9^#GpWf_fIn z0=D=Dq=lJW8JXO|)YPI!2uJ)pmQl2~9g2jHM+P@TOC2ZMuv5k*$w6sb_pt-+*_Mrd z_C4QhPBuI(x_fKa8}*UrNw{=zJ-hgm@3!%-tL{f!kb)Plp2Mn-l9Tp}nump2U)~pR zc6M(QqKz93bk=oGde8g8*tR(6EBkBB-uZW=)``hWY-rfVwAPZgb<;UE-V_p(_nF6~_(|^q} zm7lZBwj$!HoMn0Y#o}oXPIf0`u3YXtKyF{Q#Ek6Ueo=+o{@s%2@4;clq7*qze9#XW zd{Fo~W9L`RcZx2^5%A&Z8Ut0~NjCI|%bN5@SGVj3FHvP}f!UnH+0U$?sE78^{^MUCy&4B+_YyAc?~$OB?UQ~d z>VvwiP7Z6gzS*08kfrh9`B$z}_{we(*QqQfUhsw!1vfK0y)iJdLD*EdWFqShCb5Jiy{n1U6 zo|0y^fH_GWN5)j^Kom4nktZZQpC8)S7M-1VQd?WQw&nGa0z$%dzp5t5<1-1Zbbq~| zwD|b=9v+8PdsdS%+N54BbZg2;jXHx(5V&XW)!QJGEW_Vbi>=vLoy>^q)c%r)NV&8D z4Qwu6&>?$h-<3-rU=_!~#anw+R)iPnk5S-`TOX^4P0agvxU(?U8jv_Rc@%ru}*Q=q6()ADRp^f%^+xQ2y z$d+H>|NM^mE^3$jx#~X0yFWr7);v3D-MG$@5k8tcMBOzRs7^H22+l-?-d=O4z)QUG zCK4jUVn@D*_@$H28dU$thwu8|86Ua_N8;0Z9Uq?F*8Kt4S520p@8*`G+qGJ%cLUzZ zaZBu;Kb@1^-@uR<3}?emRu7RZ)Kj8r@u?CXDNgdakDmWJK}W;5)yAh~U9_*y`!y$Z zf6mFj6CxvI(3j=q+6iVRZzA;0cjWKFmtynu6-BOq@p+rXZd6feht{nxn;w~&_i3i2K779UbOUGr+w(sOA|!DV0^Ac>a9Wb(YEd?GlZ@rf_tT{-SjEgx zc3ReU8Bu!A%Xb?02AQ88Yn!j$lNsd8eC`^%+I)mfPta~+u^j(aMMhreINjZ_yNyUi zi<8oeddJ_06?}^kh75`GW4zO#t@B0U-){+O3Sj}t-2Gy zRnGDW|58{kW`iITzB1pjxu&IfH)A((g4T_ZQ0mft@r}uv|h$;T7nZ1M8s1R z?EeaaR2!7;Sp9tV9yJQsX6Lr_lAH$KH+rL@eDJ4j%TIniQ}q6u65bcV z=g`}kl@ZzpnApgjqF~Dvu3sA^@h6;8sFvWq9Q#mGdgvkK?3<=4n<1SY@;xQnWzIGmH%>*5nbPRdY@B zRUbPQwz)nYu49+kpTPoPtNf66aBcCcg_k6sL%O@eQ@HD@h5mm`@E_KgPTE{St{@o~ z=Y#qGZ(sL0Q6^}Y$JE!vg5^Xu=P5oUo7`}rCSmaA@^{=L>iWL zHghV{;ZmO*4f`1I0T~MNDSvEmW!5MXcV0;3%^&y1f=X_g30MQ7uxow7kF1*~dMIqF zl9<&TyF1F+GdN&R^&1PrzTkn`tI$>G1?hF6((8EdrPrnWkL&oJVm*p=!KHc94M%1g z|E>(K|AI`=x=&r##`RP8+RzKpnH#MAGrrS`Zflq3A=gNrL1SnBulC+N9_s$z|HoKD zM&*jimNtcGC);#sp%i7$Hq%O!Es=FhC6|;*k`_#ogqRVcEHkAjm9fOwM@g0$i7|uO z-oMv-@Ht(d^E>B!Z{Oefe$V;cZs+>v3NvqSulH+tJ|BbynyGt>k(vNoZSdNn?={5PuNVv4=j_= zD9+L3_z#Kk2yEM-U8)SSFz4c=-0|^y*;(ur4EmL8Y%F$n215pt5#k@q@=-5+uh-g- z8Lh=y2@NFLFDF=So}0*c(L^>&)|NL?4%q*PUSANs{EdA1(LwqjjnFVO2`Pxzl1)uF z2~Q!p=vRk(n|BBGby(USt;NVAC#(!EZK-IPxX zpE70qFx7n3yRw+F)k-{3Oe%(}S-DHBLKZ_+3stGSx?1My&&RY&A)`x;eRBFI1D(cp zIoBLjV(V5yd-_~_BK?J#X@9b*HZ*Po~u}k7+ z@G}M%uBV8#c0R1(Q~7kCw}XKLMOYHnHGNw5O12V{eBK<_W8u+RC$x5egN)9fI6;Eo z!DPSbOFVDZcpDN3SvA`>Lsp99b8hg-Id}n?jO>K;#xwg5|dDfi_w(1_(6%g z1>UBMvQ0(*vRQ!Pka2m@7GkMleqFZZIM$hjem+m~m(o^=X~|z*4K-YdTL6JEFpG(r zJDZMye8NMbT{CLpYh$26T(E~xs?FKK_~2zmKgm#TqfnW=F0S zI|2!Z42wTbHI8Rd-Z4!hp(_Vz*%P`Z(doe+l~wf@_)k3tqCM4fN;2>a!p%>?x`z)m zk*&T5FDg$9d<-v}H=JGlwDyvn zr}&Jp+ua8(uVd%mP`lQj7^IGxdws#+3BiNeTUrk7S(S4gYlgq|V0cLG23GMWc9U87 zr1z`PvEJbD@cY$)4_@$&ET4JttOuRv+;KzI@OY^4&Ykx(P|>DUW#cBqb6?Zw**%?M zPvd3-X!q^l6p_XFZ@(c6FRydeY=|jnlIiCS;`utM=Y#&=Of>^ZoBM!#xy(ZLs!0g9e%{|=U{8#0mjU=L@(MQg_LGU zTcUjl;`eCFNsRZQW@$!hVEzz+sF1nnHbQ~-a++js@lOE zv&ZNB4u$3sE!)GYJh|z^C270Z?8sA=gUeg<1{LxMAoRCQ7t5`?kq za)wanH>GoKzIeI4C%0PT7`Vsb&?hZH60I~=ih8=21CdkAdW6mVuz~xZeT$yE1*meK zxh-Z&XQj++K+zsCI~DeZD=4&&rqY??f~`n5?~v>FKXtx2!e%crA<}%sjorNOC_Syt zATozcv%*UW>8VoB8o&P`@IpRm(P-XL_Qa%>wwhV#X&`6_cC~pZdM2#vBdyUPo|6XK zcJ77lT^=rpEBRb7Y{On@rjA$C_XCjDfI+&N`pobu8!%kCaBGA+>2(jPud3Q z$kRaz3#Vt^(QgL`UJCyd6KJci7faq-Bp`?(4M}HPNhB{p9os?-FXs95s+fj&Wuv&b zsl>%h#5p;u&k~1yFu9#>n+<;r8IsO<^r!jsb{>Oz3cWkk%e*>Ym4MscWQA&w=PB|G zBrgdQ;lJbr?nA!fk8~OGi>1OH#&Q#BfmEz8;mh|rBAt0ZS}>Y$ zo6L@*=QtqaM<_$ChRZjWTPG#jCxlmacD$MB9%b%dQ4J+6(tqL(F~$CbcJ^69Ui<{y zrE$UxF@4irs0eGJ2$B?XCZc1!H5&gW`%p+!ZcCt#E8f|J30>J2GV^k0k#Ok1;DOi+{hm)r+1EQQExs%FX31YNBn1`lVh1DHF0p zN`Cq%-KaQ5b(yiLQ9wB^bEzcKRPAD>jM_zBKgE}q!+~>)TR;u^vNpuJ2r{;TQ_F&t zBB=v@g4oQ<9)w-^7e$U0+q`myFLCyp7%ZkJAGDhb6=3PHN0L-Z$xF3G$}T@pPm?}n z$<}c;(M|nYc-p`FRdNU+nq`_D9{Xs7?ep$tU3q>6o zdm8y`YFZffb=5(4?4+jaLujio7P$;!`LC2oXuk_SO-tNs#REu&<+G8f@G+6vRiEnf z12Qx@-j3~f?U`BLdz+|GpE#U1(o_%sMXtjbkj!7zAYqHJyJgzR@Ju`hXMW8V2Toz{ zdmJ78TsXciE97$jalvk}uFRyl1DlDOonQw7`@T^Mj{l`@$WIwtac+z2`ls%r&(vgg zAkXe!W2e?`MA|K5L<+>jAp?K}f>ige0hyGWtJN^2@L7lt?P7A0V5d={>cw(gPRc?C zx{X|*F;f1m--`BhxtD|aGJhB7xiDqVs#Ai983qXP3RZQ@-GG`jxPi4Xf+lUvLK$Y8 z^71F|PtNxO*z)R!kMl%zKvVvC&`-+AClCbdSQgVdJ<~dWHC1I_eQ1HY7z~|{`8e@bfU_s`pz+U3s^SYDh4P%sj zY|p~VMB0o)VdaSBK%R46$XYxQ9JJ5uxi+^_;ADALNFssUeYZ??)d3##TA=vE60dP+ z>Sxab8(Z5Jf?rDrN@q3wPASitty2-$zmI97t*zbCUx&|`+7Ufix-pGaQQ~Hz$exS2 z^Y_Jw?GR@cJQ*O}M%aawE=$Sx%1N7bX4T90O4@GQ}&y%3|Us+F@-Img)A!h`o?#x7F|?rtN$< zlK=RN1^Y)IcR0N(H`a6Sk3?PdLT8x`#L16?b!VnD@x4~LswG=3Gms9()9&o}v!%t< zf^YXnOm%*7^2&m$Q8d&V5Yy#P4?$J^t~Ij#=;#agFRnku_Y%r)+ywTwD@YO)9=DD| zG>g|bKu(_3&p|mpQkXVHN5j7(-rSlG7DLTkM`!69BWjuq`)GiwRvXC+Q70?IX zUV|$`Ax+6UHsA%c6PrzB;KM=oZ7`f-sJ@!t{J>%XuN3xZ@>0cK zz;d=a0b!skHYAWC-KmvNIR?I3v#~r~yQ1df+O*Q}QdaP&5z)CiO$JC}b!(T-L``59 zQ#@Z;-2M|*)I~Qf;;nhzz0VOf{k-K9&NvRzXy971~>-;fP?Szc}5BrK5Jv*JiS=E`QX?VoLWmM!tXWv<*BXK zAg@JAlm%6K|Jgs&L{}}f4^!B5!{*@xsOKctJxy=O`hvILNk=6$UQkx{Fi45;95q!h zwckmD?yYufzz2^SYm~Bzxq*3>Q2do(eZA)VdNX23Mq+2Knji~H`*b||3$aQQ-#N2i zVAR?IDao?WA3K6|d^y!}F!H#Rdnq?viBOYro1q+8ohgVuaz z?G4o;lk~K-gLq9;MsL@2I_*V3!&tN5sOgv8vs1osh3MQWyI&hae{ST9m-@6tT{$2= zLD}chW2w~nKc9a}ukRIkKQtDwaO)&=YTG3AcCWzw<`=Z%&oHp6zSs;*V%5swzunt? zD)8*Tb;oHS^a%Z|_rp@q$s2!~P5@8COn^!{j8ai%JOATp2nfQl`$s?FxusM6M@&$; znmOTI?5fOYeZ3K)&QxV*7?4zgxKQXABuVnP@O{oY;n@P~L>2?latJomM4=(N==ei2 zCx@@|3kLF_2nJMh*U||L!j%}I($%Bn4T3Y< zGa>Cgt|a`$&BCfj&QF*Bx|g^d+N$+~{1!K($Rq|D;(R7@F2M zNs#{V()x8x_Y#YsEm}3ijrs#TmKz9xA$r-7VW*q#cL$iNf$86W8%kd z2%Atq;N2=*Oi2jbW&7fj8fYLF2Q9#?wUQ()z@)djmE&%xw!21wEz_E-FwJ@VK+s`i zBW9?yD&~O^2^bA3z*Qwjb5P<;)1|*qa}oPZ5V8A7v`2rfj?PecHO7^E;W^WftTOat zBMS`(nxUGn@%Em`w!(3Xee$7>g6TG><)_UCFcg{=e?s(8g@q$!lTdW!2_S-O5^jY` zm5TAI^;@B_9U3Q~?}iKZ+rv?M^BesQ;DbD{Ly|mf*~}Bph6>z%)(#HVf9yCkWeT74 zjAhR|#shbUF`=H?eh(&u<+c*16_`%J%()4Oj1ld*yYGFYyumF6c1CH}rQDD;YA&*| zY9X!{bq#D_S7X0?(l<&CjyCeTPGKOhZ*+&|=r@XQ7|$HYg=lXHo`0FpiKoaxTWCet z_P?0;b_I?;HiGB_xE`YS6hR>m@Fb|szi&-U566fzZ@B##BgUCpLRPBpjOrbt2TZMv{c3`jP2!p zD)q(;%H%l-t3N1vlD2;Cu2gts>Z+nhQW4(tN6Q~ZF|kbOacpY2P%EaO_n%^K#a1r( zZR03W4&p5#vkv(w7GZmhx%#Gh!KkVKJffxxaWIw-VOtdC)c7d zQXew4q;j=`riJcUnpJ%kv{$d#f{V5IM!fcib}ji--S&PI3q84bPO+t1hkQQ)U43?1 zm4jjsoc@5LkJ9j`yl0TkwXLBp&|1@H5SJi*^Rx@}lgf-w@;q4J)ZgMVLtIoldKG3Y_tO9oN(LRq~Yp>CY}&75Q#0sE|35sKo<@-jvq%2 zAKOH>(*1;u>bnF!+x?h9)pcN^_NaBXV+T@3mNa7`-+=Tm6%N&FxCX%#ZYu16s0tPN znwe63O?NbNk84+5NfW9Cb>bm54NhcTYe;q4G zc4>$kCydiy9Zo$3(h6Ux&2la?{LvYXTG1Fg!waOnis^8uXf<*bn3?wPNThy_0=&B3 z@3H+>VGge?m8(gvR|FB$oH5Y5_k&WqV-s`Ew?JMNZ7q6z_4!|pQaHr>C&j4}!e?i$ zOYy%N^!0PUQ9crzPr_qVX95%*G6+Pd{5n3(=aQ@%XN?znZo#p_0Sbn zmvWqT@WUIbcgu16U0n`DMX4BW0ukh@y~}4u2}1^9FOWo&6?4kQ$PWtd(C-yEGe+#{ zzY_WBCZVMj_IXm%Vd#SFWZpRN03A}An+6?UdMUynj%2p`VIoMClrAV-tryU5BHS$^*h;94C zr~6>~NtPzaUWnjP!#hHLTxnDpoz@uv!WZEF(S1&CL+7gTu)aV8@Jp%ryG?Kdn13NF z3PcI2mdNijzM18jh+m&@Xkcd?_#sGU*|8pWp}WR{4tCYz>p%)y(OTzS>9iBcEI^o) z2O{JRH^m|Urpg#wvQFQA_hcgNgy8&p1_&YTHvcZu0mGU2gu1S3iyiU)c5G-%0K~HDjnz3>AInzW3KcDv>oI;Kin0yoR4R@D2~MoNfDzmCKG8 z8zTi?af18EcPT=w+j=`!^+iCxm+8lbbo=m~$j8AXOF-JyC46z)fdijJmEUF^SgHw= z5ZUoomLUhbPM^UBtHECC(5Z83x1PXq#^YEkM&wn&1CmG?SVV$Ywzb}#FOduah`#y^ zNiFN&W9Ro7E!dk6sbZ-igxux7Hair>c!_HoKLjyf%f-VI!L--7q-y_};YE{pVH31t z(>`cWI&nyGd*9M~pV!HRHk^ZK(;pPnx+z7DQicK7{q~$$zHt$sHb1f;M&& zW2W^2+7u!<5QDaBY;Szc%1&LPL!vI6o^Hbl zhoKd!t6Gh6#uLEaM{bQRdBaadoE|aw_Q*jH2ggO*aNw*}HFhcfn04r^AB|zegoOK~ z25%1+oIeeAK<$z@+&DJA_PW(6>WAnP;5#|+MYw}JG{ip}9;Z!OyK7z=!U1UrB&gF5 zY$bmYLV8?~Fz7?t&#;PKuxj_m$KO>u6^VBHu+j$G zvFdw;Pn3hIW9<8y4Q9NxvO<2A+r7*Q@{R&~QQ-mG-r(2=pN3eiQZva06I!8(c6pqi zl&`!&y7VA73mRHK2}Q1st4%Qd>#TqGVb2Zy^yjNBBbNah&faw21{NBr2dDKVQIb3Z zR9MfJctI2Yioi|6t{pnM#rszNp5=k?8aw$RuJu@Ga1I*t zS&bjEk$olZ+R|T1t9RRes^s(wmpWA6RNv?l?3wO0IrYURw^MQ2qqYZrg^)uBZK9;sBd!Rr&&BE{|p zq()L30U~Bg!j=)Q`h3)JILBYN&F=(A4bNQv>kklU6I&4?rRFu_Me|=jl9H-2Lk_h1 zc~g%;@{R|HSpuj}D8rWy$&uJHw@wAxqIK#xd|?}g0W6hYg228wjjQsW63fno=JJC6 zcp4)nZAiMJyZ{Kqa_aBLt;7<) zD8;TfU4GVYXk;b!xLaamt8S}qZEq#JEO*F|TJ7MN%6)TzMrIKCE&H)kAN*N9J z5q#v7q1U%W9*#O*q#v&cU8)k$1^?$j#z z^?jAjXq1BE5Bs4Q_ypY$+@~t~()(Lwh_+!s0iCi}tjkh$;|MpyQ@RyAzpnizYIP7Bd%;33nrcnA%S-xxQL2?h&O?DC8O`M_PUky*a5e{dX3 zEg%6yEM31=LoiIlhnfW+-&!-awqZfchpT1cRy>axkiOdZ=Dqlu^ga;tE(RnG4zW6zghyVV zcJGAcYSI?SK*s2?5-iCyN^qz_Vh071a5h;2XPzp+b?BGw-KNp~UAniAqVOpdi`WXb zg;l?A3n1@%6&!R}2i-Dpt>;6u$pIoKsb=3O`|Xwb(wojz3ta}tLQZUmeV(@e;22_*w_uKFv%h9PgzBBMOYqNoP*W8m}+zTIl#46 zZw%hR05y|rw6=U3woFN}jXZO8ZG2Xz*E2}zR@5YR3FVIK?=&P(ckj6d_VrQj#jlbJ z=sT%r6kr_IM|q7?x9itglCs}1jbDJ zzaEj@V;1&A>S3a@E7e}EG94B8sGlD(le{bvVwMNnG}wk^`_fLdB?3g@AtZG4nS}U~ zTY!!`(N@RqFtU@YRPV<^Z!^nh${YAJRQ!9eA!|mxaR~^+D=`Q|dORLxE+=K?od}jv7&W#+wn zZSFdaGKtPeynu)bc{3qrj!n5$mW-fbeJft*4kle58)_(UU20Oj$T8cTJmI^6jv}wH zNqb9GN5Ly|MJAN0-E{4;h2Y7P>sVPSFm^gsdHClwAmq3U;6VKwX?4Q=Y9uHqMg`b$ zWcBr6jpB@onz(ysN^b*_ob0r^S&=~(*2=U&&!8*mrjzZRymmdYTn^G_}ckZ9lf3CCSyuqfCQJF#a_HOeN1@u9F|hW&sJK$>P^@pRbB z^7DcS%d5dU=0hlxm|DS0# zkLUJp#B4B}lBc#1#Bpoa{e1cs2ZCFzg|t}XMesb$lu~OK+;AGvypM)Gn%nDEy%Tw` z0n3q}rYkzPnID5C@^#$}H9+7%H^$+nMv?zX`_xr z>VRzkOTd$wUSUa8L60kY4WtAKc-o6$+lwpRuh|cN;S3Rb;ryofLy1jkCfJz0tmGeS zfrnpq83wXCqknMHx#`>_TE6?}7wTi=kQiMIkOoZqU!1)u83s}X& z>KT-f#(DiR!bT*c>l{%lHwxIj&~<(JWhaZItTu*YVTe%x&*bJiDUf$D8zn>|hk%zW za1wukxCI%|*G~b4+`0<)fz`aOkFB1Zm&_nI>0ftdwH>?ycFU~rYO7sLq)jgw{OeHv zL6B#72|jWSzmODR6R|7$!|&`btQt0*yh&U>!Y((lykIzbo4zD?x2OCSlTd7HDJpv6 zOg+AnQKrlIbAZ1c9kP!=g8@R80Q=ykkzrtJ?={|o6snaUq%WkM-jc2zW zX5wpg4W{}{iGdAx`!QPoXT$ACuRyZtTj1pW`d4*x=ubXnr}LlQ9k4$qYH{HAjw zLsp9OHDnDptnjC5-uIoDfEo?Ov_#aqQ$>C<3-n z>Yk#u!iS3bRZ)};Ub~NFouApR`I+YVvo6e&m8O{!WdcAoo=1?@j1_Z`S! z(8&@@1lXnxvGB72)*3Jw0aQF|GLm4+8-fkQP8W!cdY9$AD1oY{UO)p8qQf(Yr#j(| znnwM?t~t~PeegK3EhD^c!_02jMALBJb8SvijW{Tp$oEW-0uRXg5k@?fSG&}c^4S=A z5(8AJ9LRscCgH$W+_=H{MyNS<;*Q2G1l2seev1&m;96FLlTh`8zpT-&=O?j#n1bW& z%m9Re;jb6rebT4>Fi5ii1Z#j!IVe`4ey{y^>l-ADKguimwyW*j6s%pPT;fY?JYu4r zgD(!3d9@<3`PS&qgOezz$Jzs5`~b%di^_Fglqk- zLxN!xE#@YID4US*G$xvpEO-2(D(Lg($+7 z@#8q(lh6{1pQYIE3Nr{|@*I>m>0xdyD{PW@at&L285aHNiylH{HE&){$zqmJ&hG8U ztsfBm>w<+?F{I$YR+1=}4Csn}qmX9nrZz~|jv?G#Owo>^hiJ4xG=G7uSjDLLKV)>E zbupJvghR=SafuN-A2Z&()D!C|dSqP~!Y_z!eZSNt#TlqDIcz;TJ1 zQu?O{zw)$CzS2)YcZ@S0Gro;F7WM-gV-C}Fhi0+JYr?&&axPN_uCE5w*mh*5mY?VH zqqSZ2H^#9^&gw+DU4yydDJHb#Q*Vy4Tn4E8!KXnPF?a8 znG>mIACaOvHfUc}FQ_yIdE!=~`r0*Hd*p80)uNK#Z|Fx;v%a4;KF+tEd&4&Uu!t1K z^pV-upD_c~V*f9srn5IcA^^Jldws>^jjoa&eEs{fQ=>w=s(Qcf^2HS`A3l7ToF4BV zuDU@FJ10NL*B@oe`UG;)&u;m_rh1j70h#JN`% z@)te&Z$E;Naa)Eo1#!wl(7*>&EqU9v^`u9E7P-N8bqanM*YA!98>uvwLsflx{zYBK z2pF5)tyBsHA|AZ5A}paW!!QuX^nhO*{w}1n{IfOk^WcWh*1ets#?e5XK@k(}U8&B& zrWJlZPj3rRiz#=OS-w1MhMuw!vEHg-~Sm7adO27 z^txv%OrpYBeCJ$1(K|~@=r;R$Q~b#M)A%t$V7o=}i7zMHloRuaaWIoA-`HVM{C6l- z5A$Ejkp9N_hTu1X$aSQ^stLNpH%JK7_Fa_cYhYE20%VtoF zR`Ma^UWb7QX&h&^(!*;K%ksmRgzIm9i~(qKI`Sv`n>+f{8Gp6ou!HbfR2qT23sm0S zGM(E9TcIgbkCu7HwbWGV^j9cwPm~7FfK@IHGmoC!@AJXdoIFX zXafBFiljtN7H*_dz`6S$7KOnEmx+)akV%yKOTXG+&mTias&b4y>qJGW$(rQoVqY%1 z%)n0ArWsAJ+qotWk>%TSvZPOcud&U>k#Qd{`H$zzinY&73oR|m?*<8q5t4$z7)=3T z+(25c7W;!7@&*F}aamCka}{~A&Y5Q>m%5{aoo!Q>d&bOjlmscQ=olFM@s?}(KFD?Q zi;Ca*Z`a{`ArAv9z`z3o*(=OeKEw9DWPRL$9PW+0oBR?W0REnzQ9& zK$V7zI^;k8cSkub#du$9;#%<0lUW-w5~D{;X7O0o=x=SPKUJRJp<4FyaSsfU<$7j54HqasnqZeb8Lcd>+@WXUV>oSEOs`k1TG2=a zdY_Ia->e$zS-wDtHhWCZI`@3l_pev&02RY-lzX*5px2eIAAM_{_p@G1WZ$2GJ|`~Y zphHN`>kADBd@nyg@hUI8BnU1)bTSsPfil0bfxA>eGD|6N(;Hl*< z5I_pN=TkcvO@Tu|J2fPQ;0J!VcUW zWjkY%Zhm^__TG~xu}I(rY54V>Sz81AWdHm)xfbK*TiyrMMrdg05?lu85l$&s`!RC$W4T2)31-IQnNHPk%vo)w!k;lVhx z4@+lMxreC}IXcds?5vdV?9zzo*2_pf(mlcxwHme3(N+ zII~-TTYUYo4Kj}>d^YPiSJ{>7hN;~(+O+nDRp7tkI%nZ+N}2O8g(5#FJM#H8yTzo; zUcTzuCv|6IcObxc4yRJ_Ek98jRY`V+-d>5O>Q94zy&O^M@bMzJz1!Xz=Fm6l=r5uM ztfU2l&f`r`L|y4srCKt7WZU@R`e`a3=mYS63bdpu>`fJ*$+{n#)FPppW!_z zs1AOhWSP=#oHJ1pB;q=OIphLpP#35OByH2R+)!*AS@CBzRjFP7@VshnCbBj-?vIQD z!q@$H`UdBycBxiMMgv(nWHifliWWBDcM<+rwTsc`>@;}9y5k{8*i~Qh*RTW(xX&`4 zKx&2ocR>19pg0ENXPvd@5mF%tjH>s@l@LjGfQFRBv0h5yM{^WJ?aqNSx+& zsj$CTo789@o(v5Yq*-gDbxg*>TC39%#>ka1{apG%xhCC7SY45P4RT}jlf-vdX8eCi zKKbGC1KQj3iCHq>#A;>*Ir4(m!CKnOr$2}{YlW|cvLN-sKzcV+bZWp?`&|P}Y(wHw zt&M!yK7+%Zfu6+3or=J|#aru4@V-N&tr~> z7q2Oda;4}+RlBY;%Yv>w?g})oPu&OG7&)o8G9miGHNf+SI9hNmMUxhMuIt*rJuWJ< zSaP+i|G7z(yN+u5VV6`lR~vw?26@^))dm^o72v_vFQ{g!Rq146cRetg3=f1WJi>#u&jWK+r^f_15kHL`_^+bd2vN zi`gXf%4HfsR?ZiyPYUy`LOK_F4L+G@+7BlaaL#%}B|b=$yK2HZWPwH`q|8C@d!8jY zGLu`?wfP^61GZ?E?iC~qHLP*>SBUIj!ROK1{Xi;}pw89DUf4(N32`16;h_%q3PF=g>*#o_XX zq(FpQKAuR9+D{gzX9O3cRO@8>PFqL@D9MP_^#$z^jVi>8acbfeb2J4*mcvWGg<&FJ zLWGQrHYH&XUC=W*Gf1!!K?=;rOotO!nTFf^Z7{H9KFgRHf;M|J$7obLe-kt#UWm$_kYE31j&1bio7-YRRH(a=dFwb(5aVn}Q0N1HAHs9hyW9LvKvNuj z4wj05QN%>82kM%Jx9f!TbEduTgisDzkS9$7v7hFP=?cM)1qIhUK0d1I6xN{lHLx<1 zF3}=M+IxSlheM+%4X<$ClUxJaEZ<`gzGYJOqsB(0C2~8NCBK|J(*iJGDYuk?e-MWt zwq6FLYComxoO$Ov9Bl%aF>vb$NeIp`sR5?%~v6qG$7@V{&CkCxk^d&6SX(zw&VtCTmo8C0c6k`TywJ=p{hD*`h~ zl7Rbv8zVg;#v6l#V>#rR2ju-Z{)jKlo^Crj@h|dxr?L(XfI+-H-v}d6G(8ntS^xQr zDO3v7DC#-mPCRw_g>xd6EvZ^soOuNY%_Y2RSpMb2OFm1@j6rz+6)ani)f@0am7-5_!;ow|S;sDI8FWXT2Db`mvJ}+` zf*wQ$9Z7hB>ht@cLhBjU^#}|@(?&9X77O#&H*_Bpr2Yaeey}Tc-9IL%z`{<4-QPOJ zfJPUs*ANJqeM@&&Tt;MNZ|<$bCAGu0e9@Qv0ewsYBB#m*uH6JRSmrG3-oPJ77WNHX ziBJAwD^e3wgx}2!1A-7asDR`$ju1(@3=*YZ~1NAP=w{7l44< zUq%`H|4FuK|sfJQ{E}KXCkoQ zjO!aZMew?XrmyYE^9W7DUl;n{Q_OcVr1t^$`p@6pYmjAEWZJ8TUbcRjU-JXt9F39v zP9Xsodu;&-s#$g1>vUsRynr{8yucH5l1Q}ff2v2r8pfqFXsmC!Ul?Y1VJdd@ZK1z> zxNP2I^Xkn)w(aqqnxLHnmSN#>2Xs;(E`7TmGr%ev>^lFpnii1(n>N89bu?I&s|o{u zOKaXFb{UFf7$vj#F)keZdMw-LvzRmXwTnE~J+sypBmv|T1 z=N3$16+hXm{40(egJ&cl08f$(kCFNqoFKWHO`EecS?GLOzdo1fZ|(lO#v?y&;#Bpr zx+!lI^fHzFFfbp311v7=+a24$W_xsl#xfD{f6TKt0>Iw5i8F1@(|W5RzgMo&UN1Zg z@~t<-ktafbcDMet$yM$fj4Hij^RrG<6LrM#fF;3sAbhX4Aj7uWs%{*fMOX3?mb9n( z-Ll#NWdiH6e+Z!LBdQgT&7)^YPA^~w`LZ{!AUZbi(Vk5&12OM7mQ2E2HA9SmhPsy* zxb*@+Q{hY)JZddU}sXX``;xE8j{>B=8cSMRnfeI%P4KK7Km^L$yrz-=*!3P*(Oi{ z;D@!if@+fW2y)0H@l4nBxQKV-F1ta~sl!!Wz{nWF}`u#mNJ}U9E2OIwn1R)>iT1o^94$&CXkn ze!rmX|0igwi$H;iH|IW;E?Roq22u9|Mdc;ani9occ+W#$5-=neC;v$!+>Xzx4`;a?(xwn0I!1q5*zW!qzxE4vVF=gcqBgx@cy0SI&b zKQ<>cQ^JopDHub1fyV$`jOezm2z8%8!dmZ= zXrv$3%SJ)^9=#{{L@+*WWe=(CwE#qrK_z4A36UGxqKt65t zj|rnL8ci?Tl_Z$7-i?&MsQfDvq5R7^R9uq=lj_VDK<|e;Bf$rDSKy!G)b$BBR4=j~ z#BI4T3W@3+GNrLg?B%{n@AJdlR&F@(5|^xMv>SBi-xHP!d^$RD@Zz@YP$)W2!j zJcBq`kVLuV&5QnOaL^%#L4_F&x84KrQ|P$dNJ`k2_NdI9%aN~F?{;DzU|%aT^cS4d z;eIYQaBR&EiXlvmadn~KW_r{_SEXCDyv;x)kH8~PH57ke?a;~xn< z(Dr^OVkg&_Y?&is`L#b-1ZdUL4~tTF+alGf4otvAZ0jr$E0FzFCnhHM$NoKkIsiKM zqCKEv^<|3Z=-9-6myX>Aiii;eK*v76^{?pIj9EI?SmR&lSU*6=`mc9si3{G=d@s@2 zM1&v7i-J$kUKAP^QBR2pHS^T{N>Lc){L)92bFM{HIiH><+4;1f%9-D31$(NmG?%#3#WW(t?8eV!sEyRbYz0N`3GI69d=7^Bt zkM=gq4xiXZ3@#w|IJvfh-qa@b7f9y#2{|j>u|&%h-2tALOzFihw;6;Z4^6lvu4Tts-Ge}H!%v_y?$37AK$)+#b}mbvgEl$)WyU2I^fTm& z@yOT-2je64aEU}oWA-!f86<6>Z>S5@V`J(9{ZMUNljuW$TV8@8+%M+l^SAXPN%Hb} z2O2)|m;HZeV2c00(ZDoEjN|5CwO#OC8?}FQ=@q9Hv7P>xo2uzAe5blX z05i65KF6RkN@$aynxy_!VXLYEc zKcX)y30xAO(Mv?@XhG^rSP6oiGh6Jq3btq&#ScLnKiY*U88c{&IQpH+k_;*Fn$x>? zVeV1#!|gxli%+Q963op!xGqHQQXOu9HTJ=lS;AqqInG?U+}!#AEk^e)V15gzLq#oq zt~Q(Q(Bdijtl_;Ey^-b&eyTF1`n}4xW&hqK{^i0(2f+$gWW5^CoztXd>Co9M3hw4S z+frlxyY4%|%Zc4<2ju6Dp?~`MKi%v9Tz%H3{`(-pgY-Wm^FJfA;Q#n)qVJ4}8u;s1 z?7zQC=a+e(oowY)Z$u3l+dtfrlVe?aE!v><$XqBe|Drkc^3{u_f4WA%5s4aYl0mpd;{2BQZ(e-vo$gmazMpWo|9^3FyEqK;Cvx!Pv_=2cWc&La z=>x!@v-fG>Tv7FZbT^g3U^7G;+u1Dmx3``hNhOh$Q3m(N zz#kaBPohGghv$E6*Zh^hnb$UAs`eldEy?qLD3@HY6L1pNL0n20cJn1JDke$X0vjc8 z3fn8($dh%0VHT=sOw;8@ZQ%xirb1`FI2@_IjzHgsot3y0()ftr{9nC=hc$^H=c99E znSA`s-hAGL>6jr9~yp}$a>Ljt`l?4o^STRLRIj0P38{JUw{1XrQ$F((A zGjW#Ks#U{xt^_=Fbyr%)Gcyx2Kickov<_l~_UOI;)zr=EdmXO*NdS(>fH=BKkk2HA zqRVSS0S!2THX!7E(gDl;#vp{r_)YQ?lvlGqvVa(?Br_6JrfHhQaco`^vH)CWFu8vo z2SVSM-v1mKyqv^(14ZZscX55bixnw%9%SC6LF=)Bmfrs5)mxW2I3oXVx)liU@HXA3 ziJxH>jG*JF*T=<2PPA|9SG{mSva+)6g2F&6QX*K;iu*B-MuQC$q36Z8<9V-j^Qp*C z8V_#z{V$6A-*;^UEBf~>FRG2rQFh&rw=muP&3AN%FN}H5v71kOak(V{gZpjBAuZP{ zU9nWkHg|{hT}IWKY}VWuq3aiWlkBc%q;__8dB6VcDPM-^D~YC2Q#$N-U})GYLfQ>B z{7JfI$;p9&ucb`n>p=)HMQj(*&Kj$D>Rf`z3(1*Q(> z_;g&9P}3O(2b48VX~Bw1tKG_NxcYQ?La=$PIQW$uunX?z%MZ#sHY5TyKk9 zVD^E&h-UMHTXCR`pj;|jUP$jq*>qch^qjiag31j-JFH-{DygvW?m;ZMtCPgDf7<(N zM3Qsn?bys&1?j}ub0SxEA#!Cg-~y)VRVG|vqRd&at#!&OtVSR+x+X#+(vkvqm30U~ z^P#uH#*eIZ-tFi{&O^=lCTKDZb_y-BEPAlmy+R={22AlsX8c+aX_$@W0~cU(yZ_1q z54Uq{nqMQrD=4!cwgI)p=Tj8FMzDu}W+Yf>inW`Pc^vMzbD{PJa+=BAbY5(KbmRc_ z(I+@cnpXnbPp_Z*o0oEcmjhKSB3BEa+WvZ@S4Wu@WP-HV7qqS~logLstu4&##?ly! z2z29mPG5fYP4_f&!8L&mWjJn5yGx(O>FZ=k)bO=cE?92Znv>g{L`VBAUXYpLS(eV-?a{IB&SD(?c1Ufxgq4)wsyStj{!g zaJw~gnO*2Euy(=MyJfSQnAzeZ0eLm(q z9%2SAJ%(hhds^yf?=Jg4gzQRh*AW?&rQPQ`ddMb5~hbr7ORCvoO2Q zL{GBm4BH)`e5`B`dS_a&rz7v-EcIX!Yu801W7c``1P;%l3o!1y9eA#IGI7`0>emet ztDX>kAP3+kYr7y00&CzqUA`G?DST7e`Vbi^y@53E5;<{C?hT$vpCp>1T@A=0482UB zJf;uZZkXC^m26ffte_9>I68x>bqi|Jp;=qZ74?bTQh~dPsY8tm^q~cr3oE!pVVLs1 zdy$k`0{${DW2*heM^CdFLBb&Qc^|7XkB{jML>1r@YKO0zy==gN%0j^L_jY*t|(u@dFA}r6|`J-u^RN`yU}#m6utRwCbBveep0nlA>7cth^d-i z-hi0_2kwl&DERGpiOm?deN8!ZY;)YVZ~vw()auf6VALU|&#?IeDCD8t_jJT@jAT%5 zi(w_NPJDJgKhOJlAf(CUYW7|6v|2swftaTq?PMuWYpA^UI&g&W8lCO8kv5Oemh-TL z8o<>6_(ihXarLw=M(!_Fcakt}x4b1_vj_uezN5u2J57r=aDihprC9g=c>4-rC!Pgh zdl=)9m`qEpfX{fJS>}xQZC6!z^UXPF_p-0J+GjDarHs_c#`17~yG7}HfKIFl{BBul zvuRgBpwDh8{(woPbh#t+YFOPs23HaNo6=;nvFC)T*`@5lo;qd38Bmu#*-0Tc$%@3m$$d{ z*=Y+M$K@*5#4{*h(2L@u-|>;c+$$o-I4H7=hPC0?mh74am!TQw70+h7FN!Oq zN4b(0fFXD@wCRDac9%Og7hh3U&PmQsa$UilRXeSIS(bxDzv6hD(P69HGQa(Lz!SUT zSPp~`*6XgExy~7BrS02di@quH5sRIE%je#$r~2da++dJq5!=XB6%E<6sm{|h1SG}X zh60$n8E`n3DOf4v4VerQ$m{*k+f_LF<@nbz%}>@Ef)bunG6T>c3Se^OLL zdh6Por@8OOeGBv1+lUf7W|o#D5BSL$aN$RPJFUIdUXyE7iok<{KuWYsw>zF6lOdWl zsEQUQsYVP+=!?3a(~;~m?g=p{KhfX^%n(CE0Kp;={2G5B9it6$(Rp#K&Pae|TzYyV zea`*dphT_K41UrJjWKh0A6j*6Xyz(<%kvqV$VcK)8B6v5GHmFGj%XdV0_#(x1EZ zM`j|)vxkR=Z{Iw9j}aPv(6xEGc7J=0CjH;bB3YwpJfSMoOiX_2x#kAy|6KSMBgO0! zmN;iV{?z6Ch~jytj@-yi8qbk8%D2*FxAa(Rd@KIXdJZM+j-MPQBL2R;tlquZBjj31}WfsT1lAG*;T%lc5|uOJAHHHzI}BE9fo^vzc!&tPR|rvrnF4EPM); zyH8zCs2&=WNde4G)B^^x)`bL?G)+#nYI^+%0IwY+o7P!@p)hPMr=%~AAD!>xf3R&9 z9}x7$7W-i}%!O7HHV3W-dPf>R^#ta6-@ckEyS1HQwO~~rfIwTn8auz1(K|(x(d`}D zYjC-kZMY!xZl7j4CNW+q?Y|9Ov|T(K?Nao>Y+?=eL2Z`_o46pm>*P&IuCESphU2Irb z4puFG#Bo-%;y*D@UcYms06PK;X%KQ6EaO4EXO2m$(LR*Oq+4(A2LGK`WIFk~Vh!A7 zOE{XhSr?f1{)N}oUEt|9;ghyT1eD@+_sOqi2H;yfu{YmH4K4MDhF7qwrUC`WhdGD2 zS%hAX$v2_X-d}McqiY*<-f!kCY$TJR+(($_?5%uwjB)TLjX(gfemu)>$b5o-)VtIs zy1!?WpOK-;6p4vrC60MrS|`DdhX{NW>ME-NhiK$=y_z?cQ&8}CUU3bC^)r|eqR<~L zeckhNSyI2YpmUK>?xQBHMd}C00L%J#87S1s;y(81~&E-lMyQ#_Q~! zc(G?O%+VorIPJZ#zyybYX*GQw&XDoOu>uf}MOQY+cDYU_V;mo1^bs`S5<5A$c+ zX=38I5eEqon|%CaRe_HPi#P8uzt1pyaf-l_rNDt0Fbaf*{+u1awYrhKPM}jb>|xR& zQ~4s-$vO}zi(-d%xrLxHmnV_%+K0mXWZns5#&Ic!s{X^%Yp++%D<1wMwd-c+4X9AG zqMM7F5ibOleFv3&6RXSC@>JV{uf0>_#2hX*BctrMWhyjVUn;9pY(HkbwfDB|+!%ia z99hKE5$z16BR|}1PF=LTqqOpZj~-F~DxLMVM@2zrn())Q3heJl6BsVkU>)$4uE5LU zw?$(sT3^3N?xpUFoO;>fU1c}8p?b{#LE`&a7vUqapP%2&V%vlIP!fyzFNEfI1-nI| zPZ<6KzBvds>NUJ6O$2~*gdmJ7w1>}u@u2d~Ekc2N2})+XXl0c$ zRwc1Zi}2|anilMv87rUqCfs}hK1?V5dj0wd*;mq;a3`!8bwdLesY3DfP;~KymWP7s z^4J3b%WcHeLT?VIldg0#AzIXNfzoPi@yKIgE_YqH3+UImIw&D>;f{zp-Z`%grKC2J zzg~$=Q@&i3Rh?cs>t{3t6i9~m)}W{jqM}`ic<{zI zEZ<_xnHN@DEmka&eSQ@Bi~G| zlg_B$ePytb+QX|~ZAQ;r0l#N;U^0?~HIjzSlL@tE^GvF<=zUIwJ{_T~4Lj6QpEv{c z_ui!3o{;<+N(xVrS%Mcm(qOlAPJ@`GUYNV&QwL5}-2EHTZzNzRtd}bnl zNweQhTxl*FuYtYg;Ov~;(13NlWIvkl#aK&0$8-LrS9SCQ+k=Ah(oMuA(`%NjnhI=O zH<1VC8VOTv@L&n>_I`rbhVRSRoD&sXk2|JU)_7Jdw|+&aD9* z6KAgy!QQ+hmTsu{U=Nf}pN^iBJW8ktlxKT3!q{2fp_4|F!)yHGi}uPr@u76^6OO{* zSWVlD9|tu^XIlZE(K+!Jc9i89AaYs0X6T$no663IYR)G6rhKNE(1@1<$6F{@z?OP- zB|0E74!bz+chhQ~d?fnPkh0p0&VliA)8JBTp;-2^3Lra=a7hD26}6qdjuFczym!<- zjXzh_t2{rbyi~v>_EK>l(*lJttMT1cy+WpR$iNw>bC?43Bh$vcykwi36W#kg8E*ks zS67Uy_dTohJ){GxT>%6&ksEAYcK3NmJH=NWnfEYVi{H+AMrQN^FBDivnyqAF*sDs;;gsU`#0OZDWI+`BX_5#q;#;RXXI; zlAAdJ9+MGY!*2f=@``sGQYQG33okiMs6)HdZ*ouaKhQ7P`(f6*XCRhJeqsA$y-Q!> z{QahwIvL*G49P@HfI$?H1qq?Gr0vB8rs=fLYgX%*op2uqzweBnKg!+jUtHU4{9d&4 zNFRpr*v})ov0LA4IHyxut6Q}Cv@l{a!7;StvKg*&(yrF5e$qyKzaVoG$o3HAl5Gzs2fjMz_3P;1?=qLpN2_0PD~_{b_##IT`WVi(67)>_Tt>G#(+TfaYf#^F zI{m)=+B4dkB|q&I!z3A<<%(qbfB z1d%4pA;4Esmht(i=P|(%bq@ta?QU%7;eoyII&_d99v(KU&}ie|0-t9t^B=PE%t=5? zj|>y(_o+4>J&Pvt$Fku} zO<*y{P%2UB@as5tRBPOdQ~#En9Ljav98E|~WN?f*NcSVl9w|)fa)^#dEzB z9aqQ6$vHMX{S_E1&ImQm0MKZ2f4cZa=4lTsmFUH(dWS*ePmTi(4c%~e^y4-dfO%C0 zKT+?2?49TU!bKx%x4%MGW4$^r8OC+D5LhZDi zMnx{*^L~00{5_M~{mMcOEdPjzB4CpBn#dqUiaC6~d+zw)mWk}oeD&urjP;_OuR)G}B^Fp&px+VU z0GQb_x`mJHHtcIQ?6UJlrye0mCa3J~SJbVSrPi5kZG^y*-ptgulG&&9S%e9$_AEPl zV`fIp-1T5crt{)Y=F9ZOX;)C83gk5e(>k)R(LYqxC~~e*TH@XMb0`UftLRpDkP}jk zVKwz$DdkkPS-LD$c;OPn-<`3Sco{De)OXbB;YGeClJD-;JkbAD?q0~;gBS>%8xSpu z`*GGWGn3+r80nWh#`E*35vp8ME~KIztjiR(vqp;8&2k)*4wdklb^BmCyzS~c!kc|R z%>poke`Y38a|IvUis^6M&Ek(NMhXYs_4ag z2UJbUUdW3|-#u5Q`7otP4yzn{nWDb7{CtW%0~Q`0o)7r;ey3AUIPkTJ&N3S>kGi#2 z2_}^YhgtP?njwIHC14A4ilWR|gOZR;PUGqzX6V*)-$?i6i-cta!YOG=g$xTxcFcA7~O80 z`YZD%CJ#-DTs(IdD$VcpS)NU&&6`-g{nCS}0kOG`^Hqe>5;UR&MKVqDv3*tf5Si!-y2O2tmLMMH1u! z5nX{AE=_pvBW!t#&YdnlBwmx-lUtA3i^La@r_AGxl|&{6AX*KjxYD)aPGpU#hotvf zpL%-e0_U2q2~WJA4kvF8tai|QX*DhF zmY;Uqnba3(-Uw0zdl2xhp0mFTT^F1Fz}SCR{L6|Od!{Vj%HvNmYBv_IN?L!smbQw^fzT11W-nhX z>oZpMPHw+Rd@8}-X7rFrYE(i8Us6tBFO8^po&3l@LA+YCHX7~yJzvf6K)nLW?_MEGekEjVRYmPCnqO44d!qs6S% zaiGnMVtnfdv`jY0P*ktrGcCCi_nUj0l0#I+uh=6oTie@NO-*jymm-3;8Q8D_iu5l7 z1c4i91P&>`ypoE7O9HlWAoPK(?*ospPdyaR;ogH5rUE{H$;bKPx3+=S4fdmRk!`ET zZ15kMlSdRja}IHgS0==5nx^jqEd~4G;ZoPJ^t>WpleF(yPU{l(8?=PuVW?2>c<)a0SQ^r`P=AJv% z#|=fU7t?kez+^?42mOliM9NRo_WfG-&gF3m#p8JDT%~dh#?q^B*d#m_in0qS9k>W7 zk#8NYKIIMn_gw&q+AyHcMT;(+McSJ*@K=(6L){?B!F@as#zI=>_6%0*b&JydkkJf@ ze~#Y9M2A@Qz&nN7Y}nj^M%aQmLjF6GR$zE!#uq%=8-7(u1@@m@*ul@sV)wW7>{3&&UW3>q4mn+?piei{F7A9~lj0xK=%t7>Wt z>lepoW&+O6&cx3jt39pm;=OM%xlh`m0}O#o446a#%E-$jC(?Gw*ig5&KK>Ti6ARRf2&Uv2+T16g}FqkTG$} z;%A-_O-)Ubq<`Qf&pct4^*8`PKI?W0WgR!4OFK9^t}C}e-i@U349Wz2`_O$*-sUxI zIW$9Y(r`Y)MKSH34!2YHtc7H2&2HIsY}sWtG_db+0!WkH>z@5fht5RPWOVR&Gf-$x ztRPoQNdO>I5yQJtOXp=rOt1=oc*0Wyef|ND|ANhDT=k3_|AmhRsL}KlvXaJPf1oH_ zWkA$_Q0c!7v9+lWgv!-wLqr4q=?UL{fQe-MAMBX}Cj}7j=kq{y;LqhSI*!>vTpqwa z7#J9vtKX_#`~Jw#0JyI<8tx2vN998AazyHXvLudH`UodPjPeYVf1mnG5=G#11-KtI zQqWjB{5UBT^)+G$TQn#w#50`Q~HkK@+lRU84a&vDeMUseIM$&C!O5O6ul3C1{K zB_)!NSE25;e>IxwkDSJ33JjH09sJTC8R+79yeEP0UjZ*QAdwUK?@0f1{r(x0ciQi` zba4JVfWSY%PL?3n67u#R_1J;N9ocMZAwJyf8S6F7)B*S{O@%tHuFqt|8&UKF4n=2h z@Q$=V|4UwHEu=8o)Gi?TU429kLUYc9j=du>`B*IA?v8WSsqPz6#>pHoAgh>RI_2oP zZb(SsAGQ(5mkR*T)yJ#)(;e^=hwk#yl7`2_fp*~Fmc;sfPRbKG&hsG2_Z!bS-(NaJ zeEC>&&74tOhC+lAjL4ETB^T_%or4g&(HIm5kK6I#KZ0VxauS*z>*5NJ#`b}2rM&2rW{!^oJ#i>7i$lJCRdo*Olio)LbXnz%qM* z?`6XUsG_Mxz;{#??#uc8-zGe>Pk?&DWCq|>DDOc!b%*V3(|4h$qV>G$j zMNDaVyVbIA{o#Rtpd~gkXD}@w=bmoLtAzWQwT9E^c=lM8P?d$z46i`s!Q>bXLm_i{KTsez$sdtf z{b{%6u*-_238-`&dBat)c6!w8v{qdfz%g&~nS}k*sl?962h%JB4qre^3(ojSO!~RP z3A)J%TD|y}rvURMbB1}UFzO2YI^UJ^`o`7Fwb3N@r zUp#u|wBQ^zmcvWkh019bi~eP&D9e`KB}k&}m= zhW`};hNc`_y6h6l^3WzibNFtkRJ7)p32Mvn8tn@ zIp+W&@VPTm;eTWMze#|U#q04reG`a2w*|AK>qI1f+A)uT<8Ma~W=e5waYg<~8~u)h zt)6!k)~mdJnO=vrv;TG^Zj@2_nO)2Muofkpd6MIw0XY7ITppaR`61S%3_< z;d86U(b@ZLY3COp2!yk;fz&G{!Z82}bbh}50wjH%3Jrl&x?Fz7JAl`>4aR-&^jold zue;dX{QV^Y(^Nk1Wuc7czI-|)aqMY_W;Ca#Z^5E2re55fQ?$?Z5cJyqAaPTKeU&P_ z+AQR&I0iY(?ra_Y2w&iN%Pu=%9Lxe!9}P>c+@&jOnCY_MVl<8plm2q+rU%ygSvh$L z389ja%6QEJW*2K--OHlw#z8;Od#-r%Bs9P3GlM=wuH4-mPz7Mz#kJ`o;;b*M@z(m% z7XQ4j=48s}XrPk#AM3!lkV3n?39_39FW~d?1=RgjeOqi~wrJ#rbK4!h*Y%Ip^tgo&|?1a556@;}NEjHIM@F*tJ>}rVvGpX*V@VRp{%eZ{keC1O&UN;p} z7t_sOfb(IC?mQyUMbu~z;t-G0MfD_GmZp;CHsA_1$;d=I?3dF^>IE^Q2H_nZXIJFR z4qm)Nqz>20QJYtk3F&N@`CRU(3+&7DB;}~X%8?_Xo>&cba%LCst=0`VIscvFsnHs* zq9u>>VSrjcf81JbmUeh42nXZo`i#MMsvcL>={-Qbt-@jN^Q~Br7LfJ&fcRp2vev<{ z6Nks+hJFpU0V^GOODAdQx*?e2hP=MGSvu{n{w}SnawNkXQTq74^H!_D9Xdfy!HWKv zIJfH?ZDx*Kft==in%hv(cGANbcA$wQu+ zw-RGK&6SlgJ$P3u3=fBpl7|CGL?ilHl}goOS2)L&VAK-yB1dV$D^N9w1OcY=jpHsbL*-q*)w4a4B=0%2Y#Czjx5J zR>IA9+lkI;o%`2<6nL>>x1l;W&7(Dr5H}TXbHG06wjVriRbVIgB_&C{zMV8A<$!39u9~1QT|$B!bC@*A(c9!{!?#%PHrm_pvo?f0dB{efN$h(;HBPwld4@20 z>r==Fwt{kPt??eNRSv;4Iq%i?-*!4TP}wlz8yMPh=!v|=TX145_bfxzS^n$n>5%!c zQF2qMoqlh_P)XxC$UY(mmW)y{eXb!~c8Okps*_^wu-;ur1ZOCqn$OFkS9}P+``P zCY9und|~Q&b$BIeYFV*$aI!*s)sVWtqE_Tkl#*0_kuht>HZv*}TJruC zQ^)|Cl!NtqSI&MDshXavb&qmgIl$*6&<^3-{GR=5k<6{HdO+%PIbx(^z!qa|mwIjX zN(gpJY#_&^k=*mE1^+CavBFdSsE4uHFQH;n+>iS{{M8>=MAL`M`$(qMF6Ni&=4FdM zU@^JzBtT`nTVQ2U^Xa1Dhu=cd*Xe6$;UMHrIi4PBnKkf_MqpNmCtGCe;d_fx~O8%{S)x~PZ)0-!H1 zvmsXc6Yi1oK;jQ{|=4{Aq82xNU}CS-v{v+e3q@oF=cHw}bKXGP)VjB>3_C z)09tflq<2hviGaU~WyE52lrExV(`MRKm95THtFiWmrg3)=MnO1EhO=T%ZIJ6H2 z|IuYeza}Zd0X)x~<}cdsHuQ`C{#!hY9LQ05w!zLd(wj9 z*yonWAoeSWx=Qnc%8qQ9m*W-(TAku~(vT(aim4s=-`p{k@0E91E$%kS@q)jd*qB|n zu8lN6jcJk#RV#XtD)+>|%He%bI19@ORh}Ism@>SGzSAh+ELt?VugP;f#lr#VLM=am z)YQ8K4uR!G8QI2YxHJ2Mgw$bBm!pYt8X9fOW>NXi!`RQvjBJJFgs;fR{&fUk66VK8 zQBBh=3{7O3iDADb5L(i%8nI3|B3a7tioe#un}gNq&BIqSM0^_YzksbqIYM;qL#UW# z+IZDbv6%c>rLM#ks>9btAT}cB1Aa&=ML{j$g#!fv#UyJHKc=GizOqI409~2r=-OS- zMYm}8i{M-FGYs*xPa~?0TOYdA0b7q7`?96bCKazgjWF%1$`nHj;&E+zSB`<`!pD}VPTmh zRH;g3*+__DGkHqYrwCos6n{C9(M9^tq+n@xM?^<*aJ8?Ne6={Oe6el6m}R>PpY++A6jdO^bKpZmH+>PJtM@9AJ(L?;I~_7}?Z? z0u}wNR+MTMZFw!|YmGcl7i68^9s$XurS;5w3Q2wcZEEv(cLZhs{JRmdFe9nm-veQM zXA%|Vg!#U@qVogAKSu~sjt=5o#s6~h#3>*ngbNi<%25c}_~zs-AYV%94GmkWnmVP- zW;JxGxNSF}j9lZ8+cP99@KNPb5V!Mtvlsdz?zoTJ@=_y|7)Pj^8L2-3;EDqwFH`4HUAuAG8hNGb6^faS%dIt@9FoIGO*^0uNv z|J>U)$!yu|=FfwA`_@rTSpXXOvfKjY&=m^g7#Jolxr_i?e>P`Pj5#EA( znxCoTDdDTQ9y%CDX0p3=V)C`5>g~7dHOc(tU6KdJ(KX4t|6&Grn!H8U9Zq$j)M=9v zvk75zl_^u!`b?#ElS^2H5AXQB=Txd2jpPL$t8ftF0HjbXZ*8pJ_B4>;gxR5pd~Bek zY`@W{2#dd6B-0X}2Fbnm(d3R1qz3;>0*eh6>mL#C- z#Y6C62BEUhvJzaBI2zEpkeGsbN6$`$^o(PN1ocE&okh;84DfkIzjmm)!XWJQ@WQ_z zt-$%8Au$c#z*8%P(U#;5!O&;-n3VA_wNfM0dJJa`rS?N(;H-PlyrDKenjG9NJ$3yR zv%b&A`|^w3w=_<{EKa|yTSvZ6wJJa`GnX$ZPk696D1LoqChFIy5Eii+**kJL@ZlT2 zTC0(qQ7^zKG8h2c?DK}R{z9n@k1M_uxJ{P4h`Jc^&|lY@q(jH4#)ucMQMK6wv5v!6dGIDx z2ydKB{VT*^&!#hys|o2(Ls=`qZ^2Gt9LAyOytn;~*|IMRFgpYz1(q7Kn7K`R3M}PH zE8q;xr*R_W7{{XOTO79Sx0;G2>7?vMP`tyt&}b;tEC$K5Sq}(Wy8MWdRYvPYS&&H>H>hBKTPc> z;nVoP5Un~yzEddlUMG>FAvuw(H(k%JJ}JQV>~E6+eWJ_tM6 zN$2PAQOTZl*EPaH+7E6@E)9eCVfUzPXXi@+#oXik0LSoc^`h2lLGR=2I%6H&<2}R( zbwPyRP%*}GbtQvAC|>;d*9J+PNuP=`VYsa2oTE!QW|1V2DSP~0afT*6VSs7kP<2yD~*Sf0$g8%slM4*j& z(HQ9uoF71d846lZSJwz?4mzdPNFxJX&nz7J2k<-9Nvppjx|+8{f{AV#*GM4X9-@{u z<&vAS;WZpI9Tqsl0iP`nju83>2=RBi0CmHr6C_ycXEEi!n#E|4C7>X#0JrorBrbY>HWCUG@`QRy*!;YsvmK z?>#Z^!d98-UqLhG5p3;B zZn(NIJ^dl;Nxwvzo|uAc{OS6}ssB>g z@oiVlJV@;Us&pYR>-ycbgeo?v#^ZEDl$4Q9>@4a~actD38@!PcmI^}!!y=^2RJuz{ zaokrp-(icxun&E(J2oAQ!M&*(wru*-76ia~*bCnlFHFy81plA7*8fq{b{iV$>I~Y5|Z}qo$a?ix)XE?XjJ50a+4g4 zrQR;ftV>tzjILBY*j}QzhY*PR8Ef!v*!CioS-y0?=KevvagQ59W`erI3}#Jp5X;KNG`nGEG?HoDQgnI(E+c8haBUkou(9!8Bjib2|h$1 zmF7qrnj&Ya#8@nrk3=%xV9Hs&I|-c-;_5oq0sP?9DR||y#4dWOxJy4(w^8!&MCq`g zUQdX~;cx7<|8$XfEE%3+!eS{Xj89K_mNI=gwOf6A>5`)s%A3515ipSwNn^y};4US? zJkJMqRAsa;#!|^#KSIdBU3qz)BJO$lacoIWxDU-$n0Qo7Q>F#N)J9v54un_xMZJ&G ze?JTWdKWuF?%|Uf#V~4EB9Wt|H1bBf^2R4jZHT**ezO*gl76L0QjXgK(dL+?~Z|RX##vevVPW}dns$RJiCAdZc)6g_>2wS$QRCpD#7BZ;mm18GMA<4L@`(FKV`d? zzi`~{w%CPMOT?_r3A<&51L3(p&`{6BX0i_c`!0ZJTT#7&P(F)w@it51GtT(s^?!~% z&;I2XADP5dnMm|v5f^sB(!@Rd*ME4t3nLpRa(8bM4tDqv!LC$4HY-yMVT_2=AO4?e z=}Cj)ZPnbhr)*{>idQE1<1EEy4`10+%BnmjE2>f4^MR7`!{0kS!YfYf&VWkLed8U6 zPxrlv{Vi*CRGGVp`CjJcklAPr7Z>f%A=XS4t!dbGfCeOvG zB`@sok4=VWQxM`V^9sHZt-HJ{hbNvmkJG&;vZuGg`NyyWKsg8OxK;j!@Ze@4 zq`iat8eau}uV_V2Zm=JVvueV0ixaZuV_<2=;idR4NhjaPa;YbSRE7*m8 zcQg}B6|pzQTufL%g_HW9{U(zrRx^+FDZ4-+sUn0D7a-l%wFxFdSi1%R>IuqnMEZ31 zjNt;|XA(5I@aaw7#NW$sR6ur4o&SGi?7|!zpa9eU+_G8ypzooMLh~GsO2W?8pmh&A z!1u>_#sHYMUa}9(mw7((tDe1tv*K)FZ-hY5_QIde$BnCJ%D2ZM{eRI8xhdQDWm>px zwD~)!E4Q#H!|C@(XpTzRl||y1ayoMP^GgA0P}$Rj%sC1`jZc4g`?+#3XvVApR1Qj| zTT(3_0G)0@^QAI>bF`}FaPW>2zC%JW?|* z=R9MNm^y+a`v3QYy@GLq1O<*&wM`Ws!H*(nQwXF!to^%Q+vho!0%@us-gngKqD zS@JCF7foneDVO$(W&(~mI(3LR!zya!em@COoeU#Fe!t&e>@^)35znzC%us+^oV zYLPQ+G}la>$e@tdih+}*_cg>76~nPTjdL?oMMf%W+owtMjkL2A4M>IGqyOH z)WWtGm^KF|WCv%d2bO}lbuv*#X0zJuws~7DR-WS#b{XO?!S|G~dxcD-MNE`Q+ORbW zp+Lp829VlA=0~6TbGZ|9!l#~H_D7T7OJyl9<}^4>K=Jg(3)Fw@#;^k! z4zyB4mulv*76Q{0o(^KujOi!&ab%|JLb5Fb1LdFDKz8D)Yc)$*27V8tyW(_E%w?ce z^(@xUMgEZova-p#Y=4q*l@&kzU!1*lR8()WUri+c zvrL?BSxvK~`L(Hz&AU~7x$Q>nA0wj?GP{iy`HqWMFBr*ay)Kdo6_@bvcOu!F1b$LU zO!eTUUY>}-^`>QYy@H~QnK?p$2Kx1@A?n`^Twl^4M}S#BK9%UIJyCeHLoNyBrK`;* zkM2Vx46g<^AAwBvRX_)l zEscD0KKEWaA}5*2 zRV}hO;zB=Jhn>IV;KdO8%tWuCUS7ornEkp8XW((5nJgL(COllRdTnY+DCF13x2-h5 zy)6|h(V*UwdezbDb#8Ik^uKognl^KT_ZKo?AQBJtCnboC%WFwVV+oMymc(&H=1}{P zqF?|@ysmQXX*j_8pm8~+?sSy zGtN3g{q4J6NeOylTlEZfO14LB60b0Jj*Sk8Q=v2(d;ZT)!_{+W`WUGx9 zNIS$P>6na^HU z#c)8Qk2ng(XU5^yoD<3m3%M}xIE+;@auXN!lcyyI4QEA~eH5Cz&N{m%<0D2iQ5V7M zcEmOG;p{JqzHb8nsjo0jagV&t@XoujpAk8}NH>tQ^CTKX&@3Q?Y}NEVprv}D;~->YYMus;y+;lJw7iRJ7K`n zQ|Qao&K|AgY_@aTJzD;7q2Fv_I&Y>g?V@C^`DC0RtHqlC?a*t|9fp}nGPfs;-$qMU z*_4O)b^#$nfP(CQOKJA96~I`y;_kLuCVvQ|ci zxR9TgEzMc(yMgn$ExzD{{7vp5F4isp2;npwAwA;a`zm6&Lr{rx*5NfMX8z(j<*Ta zfkVasVGB#65?YI{BvyXEZII zX-1mAV$iXW2_K#JGKc8x4*tu+ug1b9Kpp%Zs`^K|=z@HfZ+e;_k79+~MDgdw;(UBC@o=Nl!CZzvU{d1B3a-Q$8=o9;eJ3vIa4`WTU*aEiQ;1 z-9GeN3`{fTdwuoN%B(kRM3sJIW^xJ;d3!|Dd~?6Kcddw2vkzk?Ejmq1tzRgxKKYzF zJ{9f%iSVzDv%hT-TCGycTg_}3iz4?US}@6hk75TfEtoTN9xAxui?fNF{=ySR^>n07 zQ)Q&LQV1F=W&RiBAiDfj9cdjS{T>fVZ=wuTLBQTxPc0sBL_bDELx9b&$=q+i0DdNH z(fr*dd}=(Z$nds6Cn%~T*BR>{YRs;MOJzbeaC*zZjD3EFai~7g4B+S$O6>BAAS^fOlrl~?E)z+ER5WE*d2W%BB4!%2dMaMKN- z8IDCC|H9_j*KrbrcFAfZG;i|1#TwNP5k+mwG?0+j4g^P-AI%3$zIenZ`1q_4(6@6} zD0l7Kn`<`er*!N?PQxzlT}k`e5WFHZal<^32*92MQW9vm6Vv7zl4a|Log^zeEiRbZ zdPE|Py!0_mg!_BFRz}lmwWrpVRp@y)*Y6Dp|1zeSfW(SE{phai_!u$!Ra^fXzz=sN zG_|)MRH#~OBJI{fzX>{P{@DNa2NTJN!cHiL;|NV{+NUM}>HtJi1h_uG^B+!%06fS9 zMt@#AzpDac9gAL`;J6jPhx@;z{(tnByZBJ4)W{0{Foj&qqL4~s3ZGl;@KBjRKV|d! zATS9D??ngKFP3qZvT^l+1H4?z?-L~H_y76V zfZ)fuXQVoze-#?hOUbyLnyz<%w##2Nb*e7rm1dh_BY>_S->H%Pb5j#v!%9p5i}N&~ zWMJ@f9yuABHqI*cb>~NZ;!fvZf>~5N3l|Yt&WdMgR=1sdwJWvgiTwpa=_?*Mb+YS- zO*~fT7%AZ==Y_+NqHfI;nPw~w$Ibi1=3hJgenb*_JQ%FT3lFLEECDp2uKZ%_wr&?} z6i&2B@Mb+HZgDcMT6`ReQS!&PyI$fSS-$Ja#;0poXt`dZ-K!q}*uHnxpVRy-lt2RV zdP=_GorNguW$B0eJjAjpum|~d8gHm{-(3F9ngN9K$(`uk(G0oJckNNLvR-mMZQN6C zH4A|!MJcX;dFGZfWS39Et$+LSwSx2rjo_qh=}de~Yq3ngdjqez-SN4Z$)i@@`~_)8 zk}lED6BB8k_7g9Izwc@|WaooE{nIPe8_iT_Y7nfSx<;+~DhQk_!l@BaJ<%q`Q?5+4 zyk!r@1lspg`uUeo-IQN|tz)$H4+ zdutAdBb)49W`prjwgTKQw*LVDBvaQTZ1y(eaoFj_3H^*rT=icneSL)H4#bB6y+O}Z zpIn6iSDSur_d_eNEjmBQbuw@%ELOti8qOHo_F@BWD|0i6&o~K+qQnSIZWw+!hKaHK z_0TZCN`6+V?wi3yAoiP$E$OXNm|(6tZr|9foGzZ@3y1Nz{xHvUqDscmsEagB^i%le zg?H5EPiUU#d{?=p^B(bB*|79!db#blm5&vl#qHUk9BX1xN>k3_If(}5KHL-aMyXh8 z;z9H$KjP&IlUW>9f(3HQOSRH-f9%b+&=4Gv9bHPx)xMv}EQT3!e%gtIydEQvAHeY-}QpgqA6MIuWOt2}x47H+lbCwD#=+R`!wB*5Vqx20Xu z0e%)$rKj5$^32+IQzEGFO=)_EsK08s-D5$Ic=R{qek28LS$rs^KGa=cl_RqqjQaOVkqP?W3 zZyzIlI2tz<#H3aHVGjKG3pn&(A=i6)F$5#OIwm?-9K-)foPpM3rpkd!jR{aaW-KSi z!mnr$D$_H@DxQJppFiZY{NPkyLSOTsJp8aJ^;?n&$xMk!Pni(cCx;2O(yeu9b3o1V%A_58D-hWn>sQZ9^J#v$YZJEsHTbQM_Taml5~TECk05%PDOIcn zM>_WLMV!+V5`xKhUryz?B(#H6)?82A_(8SOs84xfkXii@*S6!(AsLFBkO3Fvgi@0% zV%z~{Z#hQz*-WO0=U+?fa6C)_vPk=^;@V7NGV0F5XO5YNXQ&xO$?Exx`%<1%idQ?+ z3V9{#z{GyOM|&ChgXeESd-+7ioCm+?#PqkB$KM9^DLhO((uj+W-Dp~|n;#1s4uCu{ z;L2Rn=TT_LOQ@V5hxZ$<+lZ^NVG*5~A))s#M_NGR+n^=79TS7nkj1EPVZZs_v#FkCqq-FzV-R$8F$))-ZZ(i#1~|?S z(Azr9D~wT!wOZ(R*KXy7w{}Un8)$`peQw$%=srh*U-9ltO}8QVyOROM9h>0E1)?%- z29Z(cC(15_G#_(~KtF7KbhKtLlsAo&b%&Tj9BRj#5M3fR2M`QVseopd4*j2P28}a8HCcpF4Bn?kGeHtHt<}5` zWocz^eX8zhnl&3at{^eQHj^tjP{D$sA=Gks_n-afaC{b~!kB+$(s+@e{wbqP?rE$P zQvKaU>MK7x!P&X5`_dGdbri7rtM78A%Tk}>r*E6{SmD4wuW~mYej0nyceOebE|^gZea2b= z?wul8f`zxj!a+%c@8PgsNm4G~Bkv{A(U%f;FjENPvL%`V3I?%3hr*+eKht=u95=tf zF*jU@9>x%Mn!kXk9X4`nkb$&W|1@C;t^8nut`7fWo$b=2pR_Np76SX+>C0^m!kWwp zX27y^RZ>P)#@Y4|3l1la(Fw$VuX6F2`56gg9tK^E6c)3B^h=x_0d>Rv3KQrNE7PK{ z#(wLPCll4{YAb%aI&2x;yzsKECs4C7;T+X@K}*u!vj_;+ql{4x?E&30j1}_@Ax>7h8!_sl@2E^VihO z*qXDg4zf5s*Q3y=`c(ioF6{|3?e5*oEjx>n3?3#lRgehSMjw zo>DSZ`e;n(mIj7bhk=<5khKvytslh4xSogRc5v;Mw7mJ>gdEi|S-y8hep9sqK-bm}*(dkU$~MRu82Z{_xS ze}cJm0F}ZlSN)Hj6^IyuA~dQEC1iPE#K1i}H@tcSe-0+@iYcg4xp;8$ggH&GcctKw zW(dPD3~>?+6?q~&3a`b)&nQ;`%RnS0ZZztc`MNDH@~BfWa#Ny}wD1nVK_Tu2+r6MY z8T-e6j5wmjU!$&w!4fKv^RvCf|MnS4E*Rt`6?2#roTV)36msSJ)<>%jJ6BK}G-0a2 zy5F?67ty{YH9Yvf^a_coW4qq{_miTLUUpc)oL{||=X-g!fT4b-vbTMq<_i6h*{TWs zB^sWx%i(s`b17VM?8YM;y38%VuiP$M|7Wsi(nHjQ%lKn8=WO^HAIP&}5#^fv)=!%o zEINB{hrW6`UG)n9CWz+~?aR@RLN^n6cY#d5ZX=isfDv&Pp(ndKy)_zkV8b{s4r|4n zPd5UmfrvK`C`A10MeZVK%i&i}66~mDY56FbivfSFatYTnjQ?Z-j?X?q&z;pOT{V6^ zLR#)e&s_G}muS~`62e~yd~n762Z!&SMwRiQrT$bqLr&7#3b(L^&|W+l88vE2nq`{h zV}BBxs(DtSTM#m1*-Y}y`Qya4ZVPSYt&9RP^#jPl?H`c#r+04QB2dQHf*f^-I>^{_ z(=aaR;)!zUm`qmt>OwDmU@5Po38mBvin3>HJppOpG)*gP8CTMg%55I`%Ul6fv~+D42?>&y;hU*Ip&Zly8RdgE{Cvr;RhG#VMf^fUQa6Vsp6P=OpEN@zQ1#P2q4YYS?`$^%zf-dw zx@VlYkpkMKi0szNJF9bRb4QhRuxtur7;^F96e9o}R~27N#13BIa?F;hTB6uU_;4KJ z?uZrpX8Pz!6F~76m)#UgXa3=P(I`8SEw{S|1!rzKip&B$R3S^#C}Ig zYDadiogBXwwZLba_`agnusc1Wvf4T+BYdLardOJ7XIqD)F+{ohezT{1bqcFRwqw9vL6+)yA*wqW#gcW9fTn?3j^Dy z2vLSY-3OQC%qmNb>RNQ_V8*h(=R#rQ z#!J||>`zKcbXFP?h(A8rifp}`3)j7}#HLP--P``}txGz zb%9+B?tham$C@d<2!^Pzv^8Vc8V#9VazA=F`M3)8n>`%3Mw@?(aOg!A=YXn9Wv`33 zhFMHOQDL(|*bBDaEZQIUy+&tvw@rPKAeBG?Mep+oXFXo++HD;lR^+kBh2G2c1WMl8 zf0}0{zqdwf~hZZX_zt66|j_QkYT(vTnJ(BfQMHdTxHF>8-Gia&j29g)}@Zq8rKoFE!FL?WaEE(92p#O>~L4Y z;`0tiLTUULN0A_1U_8njcgMGGS{hWuHqT2t4A~Qp_oYRrVDzR=d5fzt_C;ntwk_v? zGOK1AY(;{*hw*-}GEV0+w;Q$83nv9=+BeoF9caUc9u$QEMW^=#5}5LF{WPG1n#cM>zk~OL#P?c zPxp9ogiZOYR$2#ay6i(H6@w^ZpY~eAArrojlpKZ~{6_EeZeQ``F1zuxF>a=h4bHF# z=mApC9yD?o2~rFFFnmGJp_f$P9BzA| zaM?FXO6mDS_W*VO=qMZk-K+E6iy$Sf^!xTCLxZ?5rdBw}qw53d9Ivf83w|>919o*k z>5Z1@TJv@{sea{_7<>T`$JiQ4m?tW|o9LrleGbjUEYq>O{qX1fu!fuesvW}w5}@Ut z&wU4fT?7m1Tvw+a~Rqb=$k)4A;5d#4^-yvn-ruls>aDPpn=zyb0$ z_?0~OW{=&E$hl9sl&Hg|`u_$JwJzwmH3#Xvmr{n6_w)Y9lpH87#K_8-furpSMsMCh zi$)S?t?nUT#06$2p3U}n5%6csrg?UYR1!F@?Out=#D=uAMTQto%^^Ta7^}}mDajsw zl9Xh7-ZL@SJr8sWI1-K`ZRW{HdV&-!!CG;NI!{IB@?;89k2e)1^9*}}sCyAvh zmuPWHJAlohgHt^{Fd%F28C90op@94Sz)5yEYk@JF@VXt0%nWF!3bqbtqT6B-7#5SS zTH;0Y&NQUl4>lJLnGTGkRZO(%|6q~Hpw_dSqUmcvdAW2H|zPKyWV?#o-cllFj>lGrh`3e}1}JLda(Y_oO&hU&{+?OBtqy#+=~X zb$3XfA4RuMg-iNR(VWU>JZpIt+Yg9#VT?iKiA;_@f)`2l)fLhCVi%e_Y)lFStdPp! zczRSF&;;?v`_bmt-~yjGT{6mUiJUoM-KQL{uxx~p_y!HP2qYHAN9wfPbrr37%zy3! zKR~_T`jW8MI&dV}W@}^((g!xwC9A~dJsj{10qngRCxB6#_vUqF*EuQXw`NX2AVMvw zalg7f@;D$D*$DLH%JOBA*hcAyleoyslQ#$WWk0t&(UUt~(4v=-pj*h$BMDhNji&Y7Ta#!}%7N zb)XX)_-bkrQC`?Ic=gL@hnW?nPK(durH&$4Hy|C=-N~~u#hesx&gpz`0KL3Xz`XBI z5kLViHJwt_pYFbgEZQ#%J%bvEsjrhDZVO~UIB2! z0*vXIk=eZ4%GG%I+J#Y1^Z{1Tz+t+e)p0OR>zvzWeXC?_p#8Di%GSoU3uofHG7`lx zo5-FFRRd(B))Sl|83UHG*j?-F8Oyv2b_s_snkhqFYA*g~QDyXK8AP~JT99q`;4M2j ztt-pKUUb$CG>w(mZBkRd*|&7$lh z;N5G7X(ct{KEPT1YR}-X+tZ3`F0Qr90Lew-;ml^saMu7CQW^n7 z+48lm6vHKjT3EnrVjn}VDt$Ce#3c(o<>yIjB7&%Rs>irl@R={f_xHxryUj9*wxfEr z)4QX3K46CRTHK(IaxUDW%wH|pcV0fYFMB$ycj%5rLu)!Pk`84>j?FndAKkJ@08+MD zT;SXf#v^sMhYJm14j?tGhe&G0fn)63%_BBTkq$Q)4+iZWLgz+#kYNtk(t+uTg7Ac0 z$zBjA0@ocM#qM605jnZE(J~t7xI{Dphf95_BQ-h02X&6CNOtZg4gXl;L43Qrc7bQs zyq<17DvMx%LRMtd%cKW zUa~E;-3tGW9YF@_P69D?zi5GkyEr{ckKi+puk5uS23gb>#`Kb<(MvhC#+)r|fSX-apy=OL^u6H-MH{T*FgnBff z!ROkWd*DT1T?gZMUrC%6Lx2S=kFUvC+{^_(QsC5aln#@cCMdIL?x`y{aIM=yocZ)D z&Izsw;i=02Wwv(ajzS|ON#@%_H!KuYFs8K+5T%u)BXJV8lEOvOOrgND?kX}nF+0Rt zbyGkR0=|+Zba(1IU?|gI*MY{pL3d?Hi^f-W*y~V`UkCD^-b)m--s-XIpY17?kQ<-l zD0;4t{Uyxr-x}VlifX z;(Y02<*hABbxQ=kx02HGBA z_cZaE=k?hbp2+sBKC?mk^~LqA0nQskv{W+2nMF^G-e%^DydW3#8C#?|L(M*99EX_} zKN6^7jN(hPMgrYhPHDrc5DpN$7lVV7V+ZXuYR>4e3J3Ky1tGw0x0pPR2*{2t5Jv3pJROfl45>pzhT)*314g*pTR*QwTqE zxiSP<9FtXI@S+aik29C)#Upn|ZZe&=L0tqS#_#Dx-hud}Ql^FXtcS!K;&+3UMtUz` zi-P;2buQw*z~DXsH^%;t#Mo`ppbKWit^>5&WX~I=3WV?4XIGrjZ=)gmi{!@X&ss8U zAn7MVe4@^8E-Y)<-&uk)VvkTes!o0?JjPC7+^HP|_&z@cac@}k5H4b;*LFegjhuO6 zN>Pm3OVwyqpDWvV3=YHz%{@^m!v?AAMzP#ryxv;fL_Dhh|E^i8&vu^c8K|3fSFDV!*O{VfKwY;g@!_QlR=!Z=%9aXS!LtuQbpSitq0qCUWnWe-zo&SicfGnHUBn zYPaP)W`Smh1>jW#+kw3rS)ts{LD~x-Ek{`=@5EP2B@QaH2%rUQ-lVoPPVJR;mtV;p zX%-#3XPZuIKTU8Dt15T=D(~XsZEy|UbHWW5+A@ar@~)A^kd8ZL$#q4ada({C9rbFE zj~~1$NKfy%Tl_U%Q9$gzc;eQx?2=_VSBom7@Ol{~86$gbcGRZEtcTg$=keT*_Ta1c ztRhSY!+lI;lwJ4gE8|85Tbx1Oaa0@G+<2`3C`P;Eiyp9FckcCGC74*$+K*8i8Ubbz zcA9Bh$^9aS#)G)a6PuP+`TU28ONAaiwj6UpIS1Af#ZebhUyy&hc9G{|_y@3%!Na*P z*K{<0vMU)Cx(d+wM}Cu{MMjEbVp8bdu6bUkv%mBnAa5dXhLmM{b8gpA!Dt`{9L;;> z7M_S+;`#1>q}zerDLX+&*0RvqeBt)dk|epy!x~6(#G<~hb;aRJw4cMi zt6Gs^uj0K#lr=$5-A5y2gN2CShk5%YwUdZybc>_lUidSV3 ze3$>j(vl-54OU_$2dDI;$ZkpZc5DvGA}=U1PcCk-x^^eOFKy|>(64NVj6 z)=#^Pn}fbj9B$?7TzBR>EHxjQLd8@0#i_L0t4ulG2is)EJEZ2`FCr1`DXSAm@IW^XW6%xm*Kje zK}35$AmFtt7Jk?FT?^xthN|SflT;5l$1ChFN2@Gb3mI&edWi}0IkKG0Ucfk<)<#Zz zztUrXCnmbI=5eV44a_^pT-(bdSQ*rpV-8^===gsZrIlU(&!V)X`~MeFI@JoCLj)L$ zdtF;jl!%$N{m$D@6RlznG*V0ES5jMGc*@a{~n0KW63&$xT-{N&^+& zscjQ#-6_V4^20Z4OI6hA~e7mEcwQ;VW}dEa(N*mX$Wp#XEAp5OD}g<<>}gXlf^BN8t|FM&Z(W(_m3SoCB4$t`k-W^4Zi$oCCi~t9u{g>2 z@g>MALUr!aX!($m|9PDd^*6NRSMTMUdUQI&^gv1%7H=KXJ!2%|(LLbMU2R-i3{K`+ zK--V!Y9UP0;ZtX)Jh|O3PgM8afvGE>KDt+77hsUFQTB!ddS{5zZ>qc<#GetRB&)48 zxfYKpc?2|=v+}l>F)hneqaKG>ry<;h51oN^Z0cEH3EUl+XWMpSt96g-dk=@QX>}}v zAdLEj+iO>!NiK5QOWAZzUM!;V>dc(pT5>x~L5LIAo0v)oU3aybYSeoS?Df>aJFt7< zkV1Nw8{y9&5sN%IS>(7778rYOT8Oe#BKFCAeQN>XvR11Np=Lg31q6g2w5PABy-g|W zX!1gTdqW7`$*eowcwa<#9yXA8))@Glw?1yY>KSebcdgeCvLjh;z!Mt|ey``Bb2=W% z;T9i4MIwPrC=^;{-I_pefk*o@)Ldc|jJQkmt)XYFyot166$&MuVR#@1`b(9#~4(^$HjG~pL@jlt=qtH#tB(V-q1I6PkH{Wle{>=yk`8MO_5<2uspBw<+5sW@tst85nk@O~itUz|$Y}bv01@V)w$n$n>E|SAu>|LZ{u`=yi zhC8)CAYMK4e0s`8$RWFde5Q#~=E11IR>LQ{v!W~dEg&+wr-!}QW6|SW_3j`}?fRA* zP<|X}9$cD^y}7W0#8NZY?AkQp9=x6lB$<0$H%#QG?UOYGQzCjDYv0xsT}7-_pwuLJ zsYu!zf@vnyVRd}o^@8)TShg;k=JPJf&P9l4DW2TGOFGdf5_=jBH7t|-5K_6TcD)N{ z>rj2jlNuua&sSWK+B%k0pssrRs8}7o4FE=x+0M7Ucu=3gAIJrUxdQ6BCH{k?W-OQM+1s zkRF_6y(lUazmg)e6`fkj+*#ebPi)Y7_{+J|#{hW*F>?ZWFHH=Fgt?#heqX(4FEBT7 zDvM{*c*(nw#7!o9Cv-Dz;%l5!XaYoyY`t6J)mOaz_GjMeDQs}L2>e)G>2=0oF@fwv>7AYRFsLvT435 zV5^1;BpCJBRgrFrdyoE0SB{P+Oc$oL*?EXC4W8A03hJfSeGyp3*FfN-+*v`wkmVFO5^8_aCBH~}Fk0bU z@$Mki_xgh2CPy{IuJsTOX&!!r*#7+MdePlRSP!qV%K01Y5tVwAvWUzF{ z?lgGaXCLME?w3jA`1_NEXq5^DN{z0D;Aq|r!Yw=Ry0q;Gf{%HkO!R?pD%S>zixsGtn-mJ%Zkx5=c1 zr_1hGM`G^MeJe!U!V@TGyjO6X`L|W;?l;})V?a$AyVa?kx|A=w;_B`d+L-69q zJ}5dZ27gR+7?e!BubTk_&uA|0JL2vb)jn<8O#=kFdc~APRAxvNsBSx04hEz}Idb5p z0A2KxH$0YpRF;z?i$)K4%>^Y?2FK_Q&OomDJ=$OZ^L^3=Psu`4xM=jouKT+0O1*nw zN!nDJpbf~8>O|rr@*n&|V-_(Sk$bm&Zhy1&zHyd0081noQZZA}qXPFB?LCt2)fw)N zm3rcQ*C@YMueXfE4i}kAv?MP> zig|$ShNwFSVq7=yX+cb3fmhQm;2yjSjc|T7sAU4=H@Xro0A8R&sX|vJAgM>2jS1Dg z2Hjjmn{FLjsxRErloaP6ust_(G8ov(KrQ^11lcCmoro&Hn0=y4_uA6Kdjj<|pTpbP zpR4a2H9?_r1dIvQ|H^&B0^7Bw0YDZ8_%FX~V@_T8Ts~RSCLz=CYN3fnokE^|)!H#8ehbr*tCMj% zZ&ij+_b^}E))x7=02AIGmD(%M)s=(hT(>VRbV*j+*Wn%4rvS=UG{ib=-$zxMAN9LS zy^CNIJyudOIi2*ZTlv{ne2ap#y}jYCTq)e#Ec(yF?NSV_DEv+=#JWh9%2Ei^2QLzn z2c7*xUwpy>U^Ku)UYL0u);&;rDTiZLn$ok__u}nme0h6r)+(F5f2BJWGT_=Des(ri z+|G4oNG`*LnJZr%4AGY95g0F^vPJ)1HPw3b2#}A7GJ~lmks3V^>66SU2xxNlL2sz< zb>@xKO$qJOu@^eLN@kILZ@EsNkDS;Xt9&eL!cTaC68r8+LhMg{T}zXCIt)?AE!&6f z?W*v*y&mSwb)cVH0%{QSoDbWTH+AvEYSTW;LNH8l+g2(;5>@Ku3skp04ngihVB( z2p^6#+qXSO)*uZ#^o$zrFax zDwzkuiXlrG5(7M=l;;QAUo4*e{&Ee994~<;XnF`sL`HT;G?Fq?wT@~{lVBx@I~=Qc zEsm>VGZOgWbtn%z&oO-rdBYCi%htO`U)Q=0^(z7aSw6o+>dC#981?_?LP!!a=-)c+ zj~98`LzXWh3s}Qf8vz4IsOglTeAw1B(r!l27azT)0RFXuh7ahOBIkBp~|kCuq_`2m>#$CS87u{0rrU;Cu(Zbg#x*^FQZ-ObxXv%9I>)UtI#izK-`r!?mzifrK}0R4M5tg+{|qU zTjWLnB3e$?eF)_T(mhHJZT^FjvmMFhBo9;D0qO5?{8G?6AKEzeu#`;ofbVQSTAzPj zuThM0R`n(0JF%DwQrV#txq*@&vqtS{G})B~SrF#!KrMbK$3CkeuJ>xWl0I{+!lP(= zO4!kg@)=$L_`8{|_*TzcQ(X=PewOW{k#;!SH>%n#h2%QCtXC56G@3i5Qp zQx%8>Q@d&07<8vRKdLoj0tVqHn77g+)_5^vtJtyUZH_RFj*qtd!p zw(Uf9wpTBhR#|M9iO1v=p3$@+Nx6ObT(ON^#751=L(;2SvPCSdWBoc%s3-=AF2pVx zenq(l+=Ew37Z76efp`7$KfgvQH_x8WzxSf`7@4CGj-EqLBWm_0??ZjQDk^Gym0e?^CGW_W5Y0zxJ)lLEgv_7ndRJ_^KnA2@ec~1tp{ixWnpycLeS5u% zBsaeNT%1mkWOFW%3OHG3LKE9J4F(3D9MUILoRs5EgCpaOY|b6=G!MiX4c9x^Vo%9< zG~EHcXQo1ijjyZFiqG;%hmEC=muGPki0I9~5WCKAXc^`kYdWG!$zkL5b@ns(`xqYO zFRioh1eiA{vvzwK8*Pv`57Q3eoUo_<%Sem%F;)&11HOBa*R_x(ONnBjA(ods;23<> zyuW^Zeb!FnfORSdFEPSY;4!H`+WC-k}M!~9J$M8C9M{Jd^!?vL$y7Xm#Pw&g`M=OXUATt zsjSdCWrX53LvoGCr=96%#ET`*!Iw|BrZPhnfv~=P4hBPPN2t2mqt_M5&$JEYBY_7V z777&cjm7}Vk|f=y$i51Hf=OT)de1)o>!v6b5 z8w@8iU!H42Y+D*KPY);4y93S43%+ALCV6;{F_APZ6WZo{D#!t3KR{%6R;Gth;Tv37 z7*iL{P@!e`6z<_ zCCQr|kb?OnWBS(Z(~ecF9hnMr$hO{dPHKd(>jYNK3$k!2FiSwk|Db$=L1<;j5VQu> z+j;&iNp!YM_d~DV9V7b>Y?~ERlwEdMikG}v2OaA_7z(TM1Gf4mnjr+`l zP%%SjMzdU>2@j0lITf}Xw~d;(rYOa2b3$2A<}W9h^1|wY%7s5eFuB@n=iOqS<(vaK zTun3UU>5}l%q)BR#qTvPGfB%>B5~D6@t|2=4f`a|9=!0l(%kI+OubqFwcDMcz1Qnt}>ssoFa<*4LIi&vW z5fBSSUXux(ESAdLghzroUuSUXKJvr!M;Y&J88|-=CKAr@e-Rk1v#CKg=R{XvPo{A2 zCj$O0N@)Uq8YQW&z`yVl2ob1N>MQ&xlMcO&vSB_Xe%6SZT#;^H^Y0W>gsn3jAj}J$ z*ZnsY{aDaNN*^qxhC8bfW$jsEGc{2oQ*%ds!!~Hl*h*FYVt#r`G-sOIVo>*X?ixq1cXDI%|uY&AxL&{_2?gY z>@up%#n+^IhqaMw(KFLQ%$hpxp^_Ki8Ti>v!Bir`^1RP3w(!?3^o4F-uVfUVPnv}A z&H?;o-4;>!pKY5BY+LA*+cH?fw#X>tH!4O8l4ktf&y(}5|2H*W_ItY}zmuK2w%D-1 z9ZSqMz$9!Pq)?O@&b=$yQE6iIP{05ys))pYD{+IO_?wGkf#_j~Kk>?sG_!`bL}W>A z2$iI|zYnwa2Y|5Pz2#v3jKRUhQ%C{TaRC-TDc;jWG13qfy@(aA4~@bWxgX$Hal}EqC`wW9E12^inuRCh+BGPo`Wd z$5+XJN5R`kXPbF%zqLkf%_oEfMm*uqhHG)f8QK@X0=m*U#@qFLM;n z&0phqiTRC)I#Ssztv=D%QS!Km0)s*6jgDrG-lUF^N)*5AXoXf{@4P1tkXo52S_xJCJnWbE9E1*c;ahve$NW-q-F z-vN%*&6t*0UVo|;6N+$85~g%V4?gs0LeL@I0J%cBE!+@>wW)C)2r=@BDLvwPz?`^Ha`K@jnW$_ ziTVJd_r*0xtYwB)9qlLfxebQAX6oW+l zQ9D1Z`Oop|GqlG@cE2j#-SIm7txO0a(F#;N;K5_hyI_`y%<#HNo&F zF6l3-Xg$ZEg)2gQj+^ZF03@PEq;`@T_&zRUYuWM4(fgN-V5!x{;$GTzVq3jV9guxC z&T}Yy|K$jaDxyl8N>E+lg)jXD!V1VXPexrxpwWm)?NPm`Ni6%1bhlcY(JV}d8sYlh zZq%3a(}9*ESSy?2Kl(T5#vcI+#=R2Q$uUF7yI6yMoOz{QA4JDr5B`g)N5@o{ zmL#I2`Bo%reJb_!nX#^HJtIqLbzyY+P_Ll5-p2XN(ocR{V5u=s^5u?e`9f;0{$REM z$yG%;54va-VPXOTWu3~CD;GBJD5`4cBC)mfZo0>wE`*%Z!3iSR9?N=>lb$C~c0ctm z@(`I<%+EiTWQ$d3eEW>aC#&>%X7>whbQ?;t9iT*eAM1$?kJRDT=jik3@jHI}u~iZK zGJYU4>-U#QggOTW6}>6dP|1%ilJ~Vo+#nFZW}W@Zpr0>J>Y^ht{9YD)xx{}6)w}{m zKB6m?jZnuwiK1fDeXXHRIw6MPHQT#n4Q@wWog7_hv-c(xgqjc#z>LKE4l;#_)LM zU&n;Xz3iw|ainVi&WkAD*x23)SiF?AR)Y9_++>T8o-k=i`@bX7)viAxz58fl1#-e+ zPgp2w(2IF9^pW8?tT+6xu%68R31Fg$S0{fq^?RkgM19^c!hukUvBagA*^A>oj8(e_ zkkhrj;V~5bOn9j;TUhp9No~e=k++VdBp(`89ohehTwr=dYwcPkEBX&@|Cxi(1nu4H zqed)SlF^m4Y+z{V#pXPZ;QCxiaWa#!Jt!UixZG14v}smYh(hohUU^B8Izf5@KTO0C zhYL93a{! zfcs5tvFDZrV%p^YW(r-_iaQzA8VQA8^{?NKe;bZvOnMY5#L`Pn?eT1EH>S@yjI~`l z%8WWoVI!K>>Gvdh4b6<-HF}YaZ;+X~JIla4X$XA2uRSwd@l+yA&lz}EemWznn0)++ zC9C#xtGp2Yqm0Qa@M7r5<_|DJrRm30;Mj{F&Oc{MrI?d7F&AL{D`F7im?rH4L`X#q z@pPqBe8Wq=q*xp>7Gi07))Zr8_4*0`pXGqEJ~N6lrG^WT$}f#!Ox0ZaTcfLugR^=| zoyYqx1>6XVle>Y`GaJF08}^-Y7HV9a&m)YVAaB(0@V#b>58=riM?cM2=;gG?DN><0 zVTR=f_R{DrC9Ewj{!6e@Q{+B&+RlNZhM07Yk{**=s?q{OPxa+_BUuF^SUld6tPqV> zRv*&2z&xJOK3%%G4OBh)L@~h1GEf0r_BT}mrP`Xc|1)C`_{e@fBEG^l1Dzf}X=RBw z(-L;ms_ErE-hX-N>T2dF3x8YCFS?eo$$>bfKJ)lhu?Ap?_HH+N)#Y`+lED(gBNasZ zBmguhi@p$EGfoEgSeuI2v-$0t7)diTpiQ|jdgy%@xtEpcq66Ht!QX0hmd~Wb!nff{ z7Y@sn5|HYFm?4^FC3ClVNW4ZDa>>B?2h}u_+cMRvk3gFq#KZzkr%0*C{-}7tpKi+d zC(tDrcV%Hv_p=kg6W>pxzu4W5i{9!LHkl^wzkx5Mj0W%C=ii~ed|7$9>^19oA_$l= zXrUu%xKEt2HAOu{GqepEwzPBobbX%jyTJKKK8D9gFSrzU@A<@asa`FUUX+ z)Ib_4;uMd<1DXxiM@$-<()N8jAIa&Qz<F3&*^9tF zPGu%iv+-iT1{UHLg?8ne4-8h%RSe-lJX|m>ZypmBIQ#uI`p5URWf@DaV1KPQwQNKO zVST9X%ywMoo8Hr)#tg|3E6UqHD_Q`YBy$wP(m{#Xn*Fs22>!p?fS>zourWj0aZop&sf!_$50|C;(3W{pyL z-%6e$WUAirpUjY|hw+qi+1Qu63C%OT-e2T!x9OzcqWMA#)5bBRM4`{<4 z1pzbi!ItK8<$}Jkm)jmm9rw2`YQMt?k)Zgfgj_Uit*!gQeU|?a`YE9O=l><=PvD4= zc-)Yv-x%OoZdDJV=;zLdrE~fvo^+`96n565a^uIF(q9ktkpVcqp53 z0(#!WfT0D5>q{PNL4y9jviF)bOO~wt#TK@%NoKaKU-%i#e$`SCbWBkqJwt0Carv)c zf}!b`9lDQSdSPjm^i)?6^32aSiu%8X9Wu-K2-$n9US7A`JxDC{suN^wGGbalmkY9} zSkMXMS8)1>TMng^t+)Z(OH~-e^YJGjH1n3>$XT{}M_Ko(h|`!{hfxeV{xzzXFiUUvZV*t$bjEI; z0WRa2FVtt2r&3|!fBe?rtjAp?)OhSxw!K8ZVe39e2-vWmBLphBDSJ0X9B{FJjv_l(|~R-qLI<_-nPjIqu4DupE;L}n>cS4vC35cnVXQ`Jyi3cKB1 zL_UEREYDbdB47XpA&d2gF9E{E-`GJoCl{fuC=uneg}{- zrE7}hUH)T;`Mxzyrl(U5`%YL}32*czFTn@zZ*YL}(rZYA*7cb&no7cb0pgXXmV?YR zEMP5EH+LVWYFbAcJ9qRw8o;bTcxwJsqq4B|DHK6CLg4!QVc~d_kr=KP%C~(23PHLy zsg?^h5I*P4pv1*#@?G>$f)yk_?7mx0Ovj)Y*@yf+Y<(smJ4c9Eq8y)L!kiuaRwG_@ z;{9xd_Vm2;tC=nH$&JsUWmS=;!UUDIKjtYJ{)lu%^#3|welHtOBKo%{qi8zmzk4!1 z4@O~_QbcLxe3LbWWY)FxTpb(v4IAcLzs>u1O@>;S?dc%=~ z8P`!oNS8csZ9zE88%i;TbSE)c(*)+lI8~reBP%h-V9YlMb~KWfLxuRJd*Z3v0ZI+K z`&Q~iE*{1JaV+4#HqUVpaVlMfjfX&;w0fYbsdR>|j~K}y*l1K0Lob6gOu#Q%g_1JE z@JW8&iF$tXZ3bAuS$JpEg;=u_rez6)9C?MF3n!WrYm6{{MIZ9Kny| zQYc@5Okw=O;70-)Sqb?bltaKO8m^y_))$o3<~Tt>Ov~V;2P7yNP3q$Lo~@!}<63aZ zSl7fexb?C*C_bw3@QyCR{k6SayoENd0x@vbB!=z)2q?MH3DBLNLXrt&f*q{O9k9lY z-HLd^_sGn4A-%}N(#Gkb4wWBusu!|TZOv}M4hYe<=;8X)J5cc?&#*2g&(}fEbxR~& zdrMUiaOfB4^0+-AZXd72Fc7Ga+yxwTK)4i^(u>Em7#z7B7ZqE~weYKLzVb(P5QU76 zvKUJB#tMz+TaG3Gpa{zQ%m*<-g<=e9!Xt11*)vA5Dr|Nm+0h5+hw^9xvRCdj1{t*g zHJ$dGbi1+pnct@eY=Z}p|DpHgj9Di{hGduX=Q8jI*!FaF%4K=wW4R%LLlQ1Ih!)>G zYyD)@MX`e$93^-dL%-PV?Dp(LKg$qpZ(3Axn$O_Ilj5^hJ%6OAp(_4Kw{yBy$wa~_ zWqpNzatv5ck+T_B_r#A%L zqM{T5S`jqk4S|+ZC;6N)Pzyb%K~$@6H!$b((qSi2E>y>@7Al{GUut0sye{_Jph^;(XjY>e=MBY^0E6QoX z(#lExo~AI*1}hWYyZX_pGOd%8oLZYXzeP#w8w1>#DfmrG3-iig`% zwB<{k z2us#yS?$#?Rhq*^FuHg00r(G?G;(&Lzmz67@QA|mA-_~2y=R!2AywFPM}fr@(oczI zsiQm}SUCTu>HfO`05KxOITpBzYG|pqXS^$66O%e|1GSf;sv4%m;IxKV6G+YOC_ZP+ zeRyP6^^ZzetO7hj9a6*vw{$@YHO%jE>UPMH*^S26h4gMFo|Ov#X`sl;#DtM&JvcI~ zcz(Y+nJn&lmu-OaeZZ|8A&en*M0RWJ?A8Oo7w*mdb-oMW+Gfujl_HKlJSb7<0@(TO zF@f4jUw|5a^=OqLu_1pd>A)=q{GD;{=JCCsU^E$zpRJ;?c}X0Aq<{o8W-QYODk_JQ z!oLRnJcrCo2^XwF)%yNH`{z<0s^Bi`(@+XT*{sIgugPjpzm8%?Oq>aVSP>{kxf7`n9|^tjSfp?0JIuDS?6J-S*94( zX{t`)@Di90%aQwB!xS&cNq=VQst3+K2gaRj#MqUIA3Qt=INyjPA%(K}xAFWO?DvSlq#y4r z9L+f3I~5Q);tDC7Mcm5zfM-`B{?w&%crYOQ3R3e$ zRe@cv<9FButuzecDt{&HA!wip^|#}<@Q!n=?4~ofcL4kDeJ82|pqzyb9jDE?R`l(a zVMYl@i|{{np*FVpMZbL*O9*6L^O^+VGcx*~JnqFump)fkZ?E+|^aAteFTrd^f--~# zHv4Rs-w-@_q!0lE@&EENQKWxp4}WaUagfd_5yIY7qz=*&KL?6+!faD{94~Qfel9Wo zv47(|%%+63k7KCb1AXU~`ym^iRY83;$9Q z8U1=#MW%su)MDq=audwuK4u`McmKemPGVGyrtFv&Mk>r*;~te{jsY;!k=OhmywXR; z%cW|X%HQp{s#U5*@BV3f`cp?50{C$%Ba~h>lUbr;>Nb2|;-sS^wz24;gdUg3ALooO^65ArmJl-;bRFFtQR>^1BI2CLhjInZtF zr_gNCtl%#Q)b?~6U?J&T2H!(0 z{dJ?@M&^Rf$cG@PiRjgcqtTL;^o7T^c*Yf^*vFEW+kgJ9V}w*|aZViuVl?$?FG4I2 zCu0`?MPZwmM)3m~=fbq%0Rnxa;Z*072y4+pDg>%xR;N;a;&M1X0_{7t36r3_6vN?u zF3Q;bN-N|TDcyHCq|yyq}u3SLgZ(_RzTu5I{pdrKeEN&7vl zM*PlM5^+sHk@~JCLl~JW+NT5{j?A=>yF^}DVRsXY&iWrHe31wS=9&2ai3te)d7}bE z=Vm3b@5RY(p%0ol+knXaUor*m?Kf|wFA-rG-_g&t$Z4bgA2f<#iW7l0+Si6aE0A13 zS*Zr5CWNkM>IERF@R)FM1rqxMn|OuG6@bHiy9lZ!-rkeVLyQ@h!fHN&XY7^AE*mz8 z78vhJgoT3@GIrC8Qq(%8y-tA2kM*Mk3dQT1BY((crMgcl(it=w8(2j4+%d>+Ml47^ zt*c@en-ZO5J)cWJRJZ1cTM11lL55r+J4MB$kzr76QT}|ETB^ae-JdN`n2$=EIN4Z< z-R(;WLE2;pV#~f|r+Fk``wEDg`x`F!JQ#zm<=<=LaC4uX!bDpEc%Zs~ekmaLki&!V z+%H8+;|-z+?sH0_tnFEdpD>Q1h@rIw6H)UmUPkH3Q%7(@bPvkAlo;+y?;!_KOWhl- zr03Q&jtw}kUnjI;x7M|?ja~71msESFD&F6YQVeBvMc^E#MzW#-!p7p)m5mkya88TC zwohtqfvjzqLlxILK3lAS0?Pa4GZxP9?TDz|E9vPHrA0oY@cW4p#nvemIlJ~T-hkr_6ddr}l{bAtfB?A<%PUk=pg}838p+m@xmTYk;tB<$i0jz**)F z7;?jUOkB0b@7gI4_J4R(VuswDRmEEpXJm+lD%RkK^63A%%tqeKTI!tkTR1qa96A3? z(z7GHzjy)QYy_lJS2&`fRuj$r7%BV^ic1>gmwqQ-w*aeBJbm`P7Z5a{j}?_jz$rwv zSxe1%4jM$}xkp}EFW7@XW%_S{B1Ko=Fj5E?+OPZaJv9DJixyl8?Nc?3JnD~BHXQ~% zdH6)!W8N}m73v%m33>GGsYs$3TzWi}xv}H{#A$&JWJs0Idw%Gb_T17ZmyM5~{C8}r z`garSbRcU+fqET``F7yfY$W38oQiO3zLVWow=Os08N1he`0(dU^Ktp-9+HWHeOAIx z%HyNA+52wCsp$6CKJRlv1;Rvh5`zitdFf_d%gTlS^v;}phB%2Hd*;3?@aUjF2c+!V zb-;wu|5lIfCOhxBd3*q2y@F#&X^ zc$5{?*Q4gN9N?7skIU?zgp|^gWbHBjA&b0=i7y>tFk#jr^&s@q;Z^gRDNVIBT9ZMo zEZFC&#oHr#e|mchuM(liNwKm%23~YJ)2VM+W!}OZP~h0De_U^7ob{~mEfYS~O3r_L z0KK}4ZdO3P;{_+0gI2AJCOhSjwyoUWYk^W=82hh?LXL7z1CWaPHBWOM z;!Wn067n3(Iq1>|)F@itjNZAvDr%Zh^pf4-d5I}xMULx2`f0`1=x5YuIX|Fu{dk8_ ze67A_YoF_#6<872yHFqP!sHmX3V&X6)VfdO3WazfcfGflk8EV0<`1vdQ6r7?q57v7o%XRAmj(C#XrqUt?3`*!scdjMjV^Km<>mHS5 zo!f86T9J7TGz;z_s8zYYXunSukR5jDX~NgltH572M9efD0cVz-2f^TA@$6ztbnli~ zxHLvrKVO7M^OhOBe7Ml?eg5_CTc#@kh4!6j2uekmiv7~eZ9 zbZXDY2_kg7V$i?8j{-c4%IbvxjU}Ri%B6F5yP?R=y1vg(P(Cj16BCFq#Ei;L!6snhOx?TDL+5DBMI$`3`>zaXW0@|i+Pc(ql#(fz|QFWj4zi# zsi+H@-P+;# z7+bSv&YF0gc5fa8LZ)c7>C&MlKNS|PW*hO0we<8b#qauvKuj2$4XGmKWo1Cn^1=y< z=HI5t)_5;uI7<09T9Hg}@NCt*n85k@#W4$Ms)#vCqYc#N%dBh;=r$oVFa0I4fmj2k z?Vyrb1T}JitY%HaTR@g96nBddOGeYZ0ih^2qV;FMpl}pq`%<9k6SEdiyyDd_`FGYL zr05>uIy9%n{8RR}xI`h|`2An6^heUM=&&+CS{3HD>qZfnokB`MT?1NuTrWk>zhgzz zc@+WoSg)W5Hx@Din#tY5PL+jP2@+NvHEjwSq?3^vJ zOpgDwp|4x0pUCyoGHQstK_)=otrZvp`H^-gCkq}zI2DkHXgOCCBN~T4{bXv!0kkRU z6HB3nO07Gg{eA%?ugY$=$uJ~2y7b}jMXs326>ER6TICJ=V%%~nTWT4^y%nXXN$ub( zD`i5K|3_X!d7X0&L+Y>q*Dbjp(;g!V|9_HqDk(mo0(M8c&kP_bc6Sbz*LX zEcyDb)!8WGaxGkdPYqp%$n~6^?)I9uUhUPla+s6KWcnA_)M_jRX)L{F;IwUK;|}TW z6~+RCqPzuUiG^fiNmS8L{f~i{v-9Q0^Lt}>1CVTPJH+>qT%rcgA3mnEDxDSi|DX(I zEzokp!LRb4p^d@B)NY4uQH=xT$8~N=&$x8lmCF(Xi<-%c$yk96dP8u-M4OCERS1Y* zqy$*#;(0s1jIXBddqlR23O6H(4Ef7+dp{CRPshsM>{JU+O%MGQk{F5DnnH|gM#4*! zyf_A||BbL(Z!~e>#VmmPTR{={th^2X%Fh&mE{u!?mEZ3wendGr^>Cq2fx2(0h{&;O z1P^!r8Qb29pO7F5`ee!2x(*H^!)hgLQvtO}AGeYA^*9!cL~m zozWbZR->hYw-(_)9q1jcyF*>`igZv%1k1g~gvK{9Y{M>k!+~U%JPJbmMqAlX~e{9s64B#(oE81iOmZU_M#sf3c{M-G~R}poD=-dAa zl*H5$x|K>JI$REPHsiP(i%w=80nMM(T3zF8xmmAl$TP@5f5oUi8Fi=M|67`*oDe+j zTB#O7cPrZy-OjBo&@b2hO>n_#0pk2pAw==p@1Muk!;N}sHeH#)!A-(XtUW*#P#Osk z1M(oycloH2A(N2zF0X0g14+enx#Xlqc<{ zV$Cx*Kw76JGR)B3VXHsu@@_i9BKGoRxkoF;;Qfx%Fy6V3U6<_4&yW&HHGINuKx zv0A&?MKvWzS6|K>olxa(jPC(#?wx<7^ zKEsI!V#13+bhkli62?*7KiGeywG>B+fkcfUCB-rR$l$$_i(N*OOYxJNhMNYl->&(T zpi9#}^nR*w2ddDOwo3c4DQ)@xNX zte%c$jGaNQnHL+q6hXg)!FMb{NLSFMP!!Of-*Bh_ZwO1%UTymwEhWC7K!AbJ130*~ zV1X3n)i9w`rHu)yN2O^$Av=teC>*W7Z=rXBL zP7Sk(`tINn>sHN*L|@@-OaGc?pE?9wnFgbw@Jy#8;1@ z%$uSb!A|0W;@Q~OE0#P`ax+ofI4|SzymvPjUvXZTu%sSp69{iJ)(bUUGA{-$L61yxPILXE%LUp##{=`5D{#>TU7g*qlw# zcF<$EriYoB!)$z7&OBRd72Z!D!D8)c8NA>AkxnNdwuOWH6WeAZz5jqQRQq+&8lGwt zmq9G80Mq^B`9pV|aLR=BMCvaRbsT&fsrE!#zA&ro@iB}P_Gp7>fpMdic96}zr=ERI zH@1zdDwsW&k~cvq#OWeXUXiBq78^AJy!0a}YB)nPIbGhk_z%ed-x^WrWQLJxrWW<4 z8&f>ZXfIvuXm6b@rl*M(HCeWVFO>XLn*F@FIek{2|!xoiXUD|Th67cZ^}Nm_CVs^n*>2A9|I`1NN*E|y}5&=uD}^}QLI9#fqIdh4xf`U=ol+PlcOWX;R6;>63Nf4>bG{jf z?DFjM!^~EE3Z_#e$7m6N`31a}h^!rVrLn@1HIF}G#!2Xt{bJ7!{f4(bjDGu)QcpF~ z_m$l@{DR)@1p;<*+Ih}$&M$94j%YKd!8m-e7ls}UK}7cQTU2EHCZ;ha4~;}Eml2N@ z8DPyTLOpsb+KbF|Uk*alA0K)s;LIm>fR(r+oYB#>8os@LO0)86wLF6h!G81^hiP{1l`om-%{Q(*Ik*sBljl)8?_y>a2z!+H1GtWk?X`V*9<)x;(Uq z-8UKdW%zCSJRPs{BUsGqmygo*|5=(s!-mLxT~DAzK?fyxNbQ zfqRB7{NrV$sL1u56P+o1V;&<6x8)}UlKqvaBaCcX?NR;Cp$XWb7V4_&&*~^76~ZR& zD-Yr(E`tLCgAe%cOy$kQE5LdpMX*(o?vuCqIiv42?>c>FM}?X09R=(;G8MLl?IqgN zX`80pceVXey|TL7z%Ywq>)~93xU8i{^9UYY5Plq?4%%16uoG00V#L12aY#I?Eow+2 zZuIWdR?^vjn z5>fqiHHDvkD-sO+HdGbDg?G+p?;@GYByLXk&*{I~x_{pFj0|e|UQwNU;9xj1-bE@c zy2z^jQtxVc8f;AZ?kRc*tR0Yz1w(Rb*|}ztm+DjPMLtZ4zHaaDTpZGvMwdX^JCM&Hz9m4U%xm#i$QFgi|U}9 z+1d%tPXrY@+oD*6H9fL!p%S-e$t`f1n2P`Yq-f~d>Fn0G4=eEH9A?L=&!}qiBlMQr$Ti>4<(!rSx@%4vpMW(ZeP!(-d8=YTQ)r@` zaplFjFu7yZu7fZZ&#o(^jw+qOXnwyA6f+Jq`IX;>YtjFY7XZ=geYQY%q-UR(&y(og zpO1X%EM<2sJ!!ZEB2Ig~kHCUr^CMv*SZJgH)s#g8n;vEg1bDx0D$DsqPLF*s{NO>0 zttYG>i3mSeU;NY-S`}Cg;v)jD>x{fB6vz&ZXnNikQdK1N5n=pltMNXs^--VbWM%#s z_i0*gpt&&)u=x5lx#G6Nz#dC+mH>$r<7 z=)qnbZ3Ax1bZyXi`8Y%r)HEb8V6+H+zmc-8Z@g!~M&q&x$wTf8zk7g82@{+tHN6-u zA`Ah6guxpYH%>`DV(wPq$49eaiZj?6OnMQ{;i0_ySKaX=Ax;ha#u9-}E0gZ;OQtfz zo0WxVF9>iV!!#I@lMS@7?6Z5T^pYxnW~IOm)Eyqh3U>Gy3Lox});-!m$Yv&X(k*d# z>{P%1GN;RbJf3{qS-QAP{!K>ie*tWc)o;GJj%w&e^OO!v>WrKqDmo`$u7vplz{zm| zSLC}Gf771-wh_@%+mq}5C@cHG&M?p3Z$IP}5Q7R>${p$fC($WQ4$3&7-x8_7&7?Xu zy-gjnP<5ctzd801xaz@P_sTiKfD2P#(iOAImeqaP@L9@cE|6PV?Y%y~mvZU`dQ$tN z|55x0CS5FS(2HIvdXsN221a0MzI4H%fz0!EuV_FFNVE|$G@!wcUqfucw3|Dmc|MtL z0t1(R%)!o_awZys8$|IfxpD0VAWKDad5=PpuWcnNg7$P#Q!#d@;-Pv^k-NoyoY#E} z8u0t6J6$j}Le>{8kM-K%M71xS5Hio4NVK{Y_E@dt$cqOKPj~q1woAMQi0`}4$g6#i zRTXeAk<~=bfx}ilb)zHJ%b+uvq3x!$J?toyi5PvSK(}>wZoDYI@T&zJF<34K@sJUZ zj6)9f`8vTN-lf&hLCEQt_I&)4_FL}F;4Q5oe1hZ@iXnMS4#~>~-E_EFXO-?2J39LI zt{PHcSN|h426c4ezk5AG{%3ZM|2CwXH(>o|;J5mLHKMeZCrOosdP*0MES)ioYUqz~ zjbK+$$2x@Zcl%L5@KFGcyAZO-^&NDfPMBw+}v zEZx?uB@Vu0#Q-R$T-Wb;0o`=7fN>WvwD|VJ6A4*Y_E1!lGo?F#|}wHF>dNJtaIL5>4vwK9}r5g)kRd8C@J4H`X_Cr8O-fj6%N zfVKfv9R7Rst(2*Q4{x@tnB(v5XR>A1h!AXXfwRfo`0|p?M$#J!Fi_s0ZyX;$Q?HN| zHgGpxaLg8mJw#`m3znD9-ND&bPr?|XwAxG=4e0829l#S=$6rA|_%+f$GK^2qdAVz~ zc>Kh^ga(4K!NO4Deh|iM0fRM41RK^1N7;5{kg`~Y&^h4mcw~0~y z?$M`U|H-U|gNsME-Z(Xr6%k4;x*xw(=OXUxB{IBn%*wX%=6}`Xef58N0M#iJR`|?q zW?>S~M`x(L9v*e~@P74l?^%Z3xQ0Z*)rm)gJg!5ms>c))^&CLIO5#pWSF?Vljz*s{#R~BO9^5FQM|sARsVv5@P^nl!y6_kwi6QJnWZvU( zkb|PLV{@y#J(2gjDz*~6JsL%4&CBv{PQClGon5{p8XrS4saq1$d%vo`+S$ABYQskO zU}n7s?D3z`tLYT2*S%tVvjOx0ET^W#S9|RiOX4JnYK~l$wtUy}JMTUOmPM1Zz!2QF zjA8JQ9&qOgt4Rs}hA0}ZVMY109i0sDO0Cmziq5KL+qi|s%D{JMnCqhUP|QJg2~5A zw5SATD5gQ(hR-tYe#0%f@<6>;dT{Os^0hwniSzBe+M}O-DBVJHb>;>^>8)75fk~~%aDXLx3x?{cf=MwJ(}b>7#I;)+r@h;E$W}|JKj!XNP+pYAQ*G)*Y~0B1zK2ke)-N_A`6qnTI959 zW27zEc&-okoZ@Q$oYrX7Q2bM5+_EXJ9|Bnwc3#{Y*DL0gP0YII`FHlp?TQ&gPBy#i zpp^JgQegZl>e@T|m)7Qo5cv2at9HojawY$So0A82_=U|($Hi6KTe>stO41xs*T*;q zB~%eV{l?=Pi?PpY-accu+D$vyxI!*qsaMIsK?9uVTM!P4YEw)Q`y_2@o4#wbS6>U- z33rO7u)L4e$4{?!ND1&!lm@#L z|5#sjYlEcay**#{I$3K5U+OWnHzR;Z(&sujX9N(#cP(#pGFm3P$~S!L%?;p{A~9%A z84{5QZuyXM#Vg(lv@@agI_XaQJWy&n3aa_Z$aKE|t`67(YvR=PF1TZ42)AGB&n2~v zUFMKr*frnPR^hr*;PB)RZOklie_*oc7jU-HNwW6J-5JfmThU-CGd>Sk`&myJ>yZ^< zwlIjz+`Bo$e*)KzfIWQ}kvv0KZ6GInc((&;A|X?+4bSA72=mQudZ<=mc!#sEd;)FO z14p_)nLIjNbmKpDr-K_FpRNL*KIF9FE^FfMFnXB@vUP|f^|zKe7QnSf-9P?>+JZVv zDEl2wt}!TWpH4=ecJe+SlZYc^8NI2s(|J1=LWATlzuA~K{1B-4LzX_BlfKGRfxWiROVWNw*MZeh<$Mss| zt$_nqA8SWTfnul~cy1AEG;g{}ojV;|e#DKM>A!r2{BQgxj!?wo$7POZt#5sBZiW%_ z5{uyCG_ha-0jz7C1{s!Rj&^CE2ERHjMM@5wm!`an+&^DYrB7&rKD;Sy_XOz)vA}g` z3hO==3=3C1+DAUnFE>BMg4}Am-fZ$1lDezH$lS$)sB#ygfblhVDOVEF*AkTh{7-8Kwv#p!|XbcwQ zFz}Hqs^5Dn{G>mdU)O7({pK>ghVt^FJlBG7J4oSE6N{ibb8PvKNoS&QPTY|-q_JD} z7$56?NRr!(P2^l})AGJioZU=2@`jRo7XPElRFn`ktgIP(`pV+b&J3~$1`4fm+D<#| z^a;iz-H~LurcVTf553=}=0gz??E@!S>6 zY)URdvd19yfq2VcV+(ytGlyi~#;u;t=v~-kFiC_?o+9w`=MMWfGT&DiKyLAd(uJP% z7c@NH2hfC(?Y)k+6I87EblaxpCjkoc%5q_bDXwAp&6LJb@p<@+(@uBLWJ8-oZl{Qa zMBS?0g;lTotxn;=OW2Bv{fwCp!VyJ}HC|6kF`ghnp_Tp}O4g^z8bwe{OX0bBqonwB zf{6KT^$G&quY!e>Sm($z%8V5y?s@J0O@RLfI&X{Z@OluNDO!3S+11cjD*6kz3W$)Z z&TotIXUX-F%0IM+!tGTY{i&|3p{JFj0B?&DGV|R$EYulTcQ7Uon7ltVo7vcV`R1m% zlX4NcS1&(DzX}I-@I3#a^$2fMeUu}Xo0N;O%2#+2+%8vo_2(FJVEQ<9u;NJ5tGNPh zOa5SJV<4Em54s{2imDqq06FL6RC90RW z_1hF{$1n@|wfs(M9^%5?YjGs(8fQb zdFt?CJ10Do<&eX$bRoFIQ`&S*z{IU%cNStlE<`#6dn6}v_b@d0`&aW1fez8T+GO7E zXD@$~9B9wP{qgnM{<)Qu%EwdO-DDK5$Y-v=jNqle4`bNYtfyAD>`~YjVb**%L|ADc z2lhK4wTzZ(`FJEXs{RI1y|B0D`WD^t5xv-#?T3h`c^^!TGgFdNH2TPsNs3HI3&^mP z5u(@(Sz*BdOH_Px$i&<9d0g-BAdOOePbArXfq!g5+VDJ3I8XBCpZ<;_3Ir9HMsUqY zEJ4Toc9|KYJtMqcG|xLUnhtTsNM~!BfRa|YZZnnX%@a~W!p@A34kdIO)`soqstp`` z2T-}+dN^+;)6oia-x9~s3v%9fZHT-UKAfBMfztSiH&KqZ>)oqaNK^{NNNxE`^m^L^`GJ4;1zkM)0N&X1_X^-{G=!(wjWOKo3iwLEp6Q-Rtsz z%L!R5Qi8ie>p;LZ)Hn1T%t80mRrTXC*&V=7^45& z2!;kni zgUU56?`i{Era%Qel@3l-XKRIWy)Y-)8xWew3y;Z{dj*y>Uyj{lrqf^=EOD&i=y2o2 z(UV!6j-K&mH%uzUCi#h;{-&QQg6YhN{_7nchplCUib&t^V7ax0QBSvNh#9kiJig$Q z7SEu@1>(z&p$7X^0#NXF2KeKZP9Yfhlq(J20LPLo$*Oio5GeK#$42e@hvh04v(|U- zMF~HvvIVEz#q;R=s2jaNYJ@fuykC*OpL+-o-uv~5V(BQ2{d{hCe^#iOZsb54_J?p~ zNFFpqqCL5^4Ro|Xjg~F{{m;!sq45DkF?6SWyj#tl4#WDi7alw2LBpX7ZvYN;6940UjPsSYEvmOpd<@>j%T|4prt;ruN5QpH0l?#J2V&XwB*ZzDTwu zq6}d9srhRp@YKD9l`9XiCS^1R=}qPvB{Ii$%AiqA^hglm4z~mo71@xheHVNZ*EqT5 zwrQWcOG-~e5rJDXKg-&B=$TCh(TY<}mvC35yL}6Mr^eHNp=xqnp;y5w&%S#(nwx-E z;kuyMS;Go$L+Mc0;PUpoJ)}9;GBk6M0qvpx=|Y=;(*t*Bfj3JzCpb9hwjJN2X8xko z^F-~i$-TYJM}?4{QGu;D6+b^!hf)M)fWG-zz%6A6ubs=S_=NF0Oqh@gU#Wd1aS~Y@ zT?w`CCcbX_y~?(K6^bGb;kJO~hn3IfN=AYGQPkILwgq6)bq)Y-zU%448F7Yj=RSXt z7y&9Tr~Ak%IFnGm2b!}GT;9=NK+1lh&sEP_PDqz{^odWE8(-a`Sl9YMOII`fvLeJG zecv-M^x@%0?dXC?YZ7gvAc7|?6^V|Aj`&VCX+c|!;-2a@OvPsHn2)06;IbJM(24l{Pu7<&Gl9|3Z5R9Ki}YA^Qn^rm)R(VjG|EHAWP&<-KWG5SIwXJY?1_xgCuw#9(+*2 z(4e;>8)?ng_4ij-6+dMooH_R@3x#GfK?#`bd!e}o`?yw(D zsQxf2T0~SWMV1h%fb46ID@zVH4~R^o!ET2hOAh!SK^WL!DfLA^-k{R>X~p8iCjB`I zD1RB44vz7$c+C+MDw6T3ZK-Czaql&T1G7(CWywdCK~#D#tjo&R0D&h)D)-LYCn3s+ zsng-0C@zEl9ycb{1Z zh>cK0J%cF!D2AAqUQkMre*dNCDfjyLzH31?^9<0WV0nP4iTL_N=pupec1e$j|0-xA ziU^y?#EVwPbgCou5fQmAx}FG^ogZ5n2i5pYs(^ zc*%|E34QP|knZ3AjkrCU(LcR4IAFoeCfLZydC5I+mw{VfnUNy?dh5?R7l?B5mgRA& z=n(@$*8QQNIuxF+>UsP4(ebmZ$$^){5bJN0y#LjVbGnd2|t`fxNp_gpDls~ zB3pIpoQOKWH_@YE2W{u`3p~7RJJsZJlSkLueCd^}ag&t=ie6Fgx&r53Jo5l2(J8-G zpZr9Wt<ZJ=l<@Vz{8i6d2>O6kd-lUaw$js*o$#jZ|3%naM@9KX z{i8F~(1@Ubq#_|8NJ*EVG>CvG(v5WY03smLEj1uWcO%{1-Q7cX&CGr9`@X-s?)~H5 zwOlNPS#r*K&N+L3V(%wTl2@3OT=PxLPWG|bWO&tg5tNtfaslW;jmKUN)@>vXm-aRI}aTP zl;6LhtRj^|Oq>D;zVQ83`OodLR+}$NOYKa|C5+@_Ah2DhWS;Db7cztkKe)mz3M-cO zPe6S!=6CKD&uLG$32hLU>4+bkj?Tou#aqR$d(k1K$_$AOhBq~BHst`SNis@Qm>DNR zIxQTuGO!>5#!^-cF}(W|a2y>5xrjX!T2am3Gv|5GPq+a3G#y1HEeNazhS<}SEpslR+&U*@SICT9C8n&&HyWA4oLY*->$(rkdNA~gjrPA8?d+q~R?jSzJSPjkCVJRi)K1X#pj*++o+t=no)b`OS&-@q7touGu4EUPhsJ1j)B!kj}fSv zc_o?w{4q2gh|q>I5K}ttMy)ct5%MZw#jln;s1e|*|J~a#qNHAYZCWZZ}X*c z0WYV|`bieKxJgLJ)<6;#-paL(X3lOY_`B%&-lHLtU|^_|r&4*VpTB5lF^PAG1aXER z*iLy@&k^+??@m{3+_{2IKN15mgx}^7r$|CO@Xd5Bu~3xCR5-)@bvS4}_b+E;r&R(yJ6}|1bM@|hi6NGCG`dWd5$LtTvf{C9YsAmGen{%%3QGvGsY+|{gP)vE z@HsK1{PncD5kaV-^mnFaKTVqF#Qg?>TVAoO72T_Be3ON2 zo7^%_odX~ntlu4`n6So|H{?ye3t%xw?ZO3jmUbknuF-W9DQ75CT%j?LMfrohQQ*$sx{{!k~ws zW$OY;vD~0(9hLu-yyV0ryCT_*gel+(4J4F;DDEz-kE{#q!vU;{y)5Sqir^emfAz&? z=7$waMETalob6WWkY&}^R497(8L`bITbTPlm}b{=8^^v4bxbYdE9y^WGwJN+srdT} zSGWj>-qU=FM6sXf#ouA^&i+{$DaP#nCOo3ziEMk1688`u-LFdR!NWTF`!Z%q_pvux zv&_;!E(7rQccRt)J$Uctp*QcF#z3_(y;sfL%H0_jIJCdmGr2^-qre3fPD_1yujsL? zy@77rCb=F!bTqqJ7Lqo{&O0Bqb>(}0HPEsw0s#1{ObbdpzbEc|ZaiS7Y_CSbl6;+hxTI;k)mZ8{srv#0 zgUwR9%07F!fxhzpK^NC_Vf>!1PD-cof{if&#HP$Cr_aE(;-M!a9k^GF+7PaCKAo

|7h#|m*=^kP+J)B4bPcwP%^Po@VQU}9zKk+5;OMPezH z$Cdv=coEOsJwB!x7Dlbw$1>gY)(i(jG}$&B!M90 zl^${Wa)3~`_(|-c%})m^e)~h#%U&ATXVMoX8J6DqcaCE<=aYqBUg4vA->uP7B842c zA1r!ZYTJc!n+~2y&mJmm-@2xUGKitdTIsb$6i5r7{rsqMSBzFn)eNxmn@*Cl0u?#R zhB|!T1E)u`(7dIy_ce-i3L2k6a8NH*DTcn(l8dj~gSpBp=&%Y);9{0unuGD?-FqpX zs<{d3C|mc5c9g2akmlo!rWA8)BqgRp7(e#(HGm1=M3S8bhxcNRp`le@r&h6`wdY1bZ5Oib+Mi8W)?g!1Mv8)(tcEV)HL#g?DdNdFq(WkN}U{_I$&2 zMG0(vV9fXw)WD^^pjOM3LMpDAIVKBwx#Tc?x>N|a5CyqKTYVGisLzK@>ypX1gPwEH zYfE-`+QDx$*Y^WoXya{doAzw+?Z!PFW+Ad>Ih5eudNH4|7*KDrXM-BR4VjT7#PMwG z-EDz9Ql=uKH1hmR3IvP+ijzt+&@)2C-Uk%ME8=-%C%IN@Uwg&bMhZ~Y0EW=nNqZIc zsWmdCQaJ2S_S22T~dKvfRFT}-*>|fe{lzT1u(mErm=Hc$$ zCCBCbbGkYY^^$J!Os24SUj-Uzg(dZ*({&4C&^g1?pd19seZ~9xpU}TmM>1{?ch1~m|l9XEjhnW#ATh{Gp43O$=QT{tZ=QCGw^oK zNsW&DkU`7fWeEMJMe@hzTeOuoht9W8(+X-)Q{rcINg28tdLgO__dDeBs6U1roa! zl`3EdC9kq?9`7}X1`ScN`G;c=u+YF1+)DIq7V_Sc&X~l&54AX14HW(UP}Atm1T&Am zE@!x|LE*a~y7rkSiAJmCZpr8PVnJ0gy%lF&#yiPRks!VNZODkD0{dLg(h7Ju)9V=D z^~r(GfVa_Un_rX|0dL2-T+)h>K;}_nUVTv>zkV6TKM-k1Gh}<_hlTYtg!*~4-2??W zsl3KF@kYImeJ_fLd6uObkj(oIFO`k*g`4f45tOyeJX%F^*Pqi?r+#XJA^;eT zBE$92>9!#T)+sf$)?(S-M-9I{pF-I$p6;1v=+dbZy)=|9HH1}LyXDHKV|{RMq}TDT zESq$C_J}82VQmU8{crH?(9yW}Jk$W8c_U=u1~~BW=jwg;zhMIB;sXo)8zDhiJ2H#{ zi+t&F(^}tsm&J#<#g#5P#qP@LYF4D3bRC2q z^?>x`Cq)2JYba5+Ah|k9BLy^ANjnYYD^P^&E^MK*6zXwvR|l%*d60wkASzekyzmP# z?dEk80f;*D1}~k|LZi2efjsIG1N$q%1yMqtHBy&d9#)BwrIRZ~0N>dPrhIQFB@ zig?i~SK--v^=W!Cl?jWFyTUi8(k=L+3`FG4rTeZ!-7%AbY+?a9=Pa@3Bk;Vm{^xl$ z7G>6={V@*Pde_X!F&1R$F9Fh=`T)DO0R$q3h zYJ*Zw(WP{hz|UWV`1*}^g@<)q1mZ|_3By*lA#SXoDk%mc<`YWyVb0eP-IUy$PV_~< zn}_0f(Tox|z;VU$@+ZL6HSZlzja<7RflrO;YHJf=jP4_e$v5e)PpVLSI*V1FphVF* zgerJ@V!~;NJ588Cbf@*MYaiQ79Fgj?9ug7D zXI)a!%&MvK$-kT+RQ`?nY;IVQnvRMp(f)|V_sJ9Tx72+=0uAhuV;_OXBn@R{_N8oq%F?cqJ>C``Z(4NKB%TE;4=Yt|cI&=G*H|^F?C`YSilR zMFg!D0RT*oTm9=lRQNSll%H)}R$yc4|Hoo;E!q`_J#n+B? zK7fJ*lG$%z2l4AEWBp`-8pWlxqw^T+gQ6_Wh@9s`L%@L*bgKIi8f@H0oY=yA@3QI))y4mYI8q>T=$P9wG1I|1RL z!uUX(TXvelQ|Gm>^0a+76T@oj3XMRR;|IyrRIxTO?~50p<>l^-7T6~Z zLev;D(zXO5EQot|0q!J9ZSfoN#&W*Q+k)OU=bz0%$SJPT3B!b0EUBp6NSWTfi@b|2 zmYPLUSf!iK-y|*FVRePm+Q@AU|CX$A*b2KsQ7&D*bK!d2+v@fzX(5sduy80FR}~2F zewLXYOmb$lQ*vwk@$8{9)}z9U<~e3mFDBA9MY^Mp(A zBOVWL87b{$YD&hF`64H`DmEF(soel|X^Y z%df4cDu=9wH*0}oA}@#w5QTb5SzlAb&*#P<$pcU~m)sXJEQv3$qBMjIvBAHGnKp zJ91roaA;@spo4n3eRC1&+QjIC;WPB^5+lM=y&Egr^*_ChE8LiSvG-Gxh?gjcvh(3d z4)v%Cko_&lXFF{v)|)+|L?0gAY`wbn@WlZ?n_->K<4LTiKM?c#f?AjlA+Ju|u4tm8 zvkIgdDAg`0xz11rJ*aRz_brbe^*FwMq@cXR3+A~Tj+UMs%}P_25Fq+!0v%qic&-M-Q6<1Cd%$M=xs;`yYktp?rql^P+;)eBR!jG4o_qDF6fb~%@>VH zPPdjE0qK!sX&-@jKL4$m{x98DS{?U(gTn&>77YvbKX7k@JU)6L@U#NI-`3)?_NWT2 z8DI`q+yKgIZS$N8cH5GEx*#IG0a{*f*BXFBWYzXKLQ-i6VP+>^+4iq-L2jn zHgvv;6&_OyJA-in%v$awRd@Nem-DTaky6~zJ-G&u&7Hsuh-B_p8`J0htG{VnZ=}wq zkt|5XS`t$)!@6l|R7LrW1G!R9o_x(^l&NNKfVBXwdtCT|m6D}Kn&;=uJPGy1VLaH; zz!E<;YHWGO!=QiZXk#t!_4v?DDEmy`ndyLB1hUbb@a&$*6dBplF}qn1w$K+w5@v}O zO?w>%ZR&k$s>gxf84M_+joxew1PG6u2*=3o0{m&(940ZkVsk?MC`Qa*NMij^8KJ-9 z1J}XlPL`T;tt2l!jA@1PR{o=*Sq*$}_@gx9e4br4M_sB<{*J&x3lFEBh+s`e1*-Zyz%`Tzyo$4!@aT0vSOwTDX(q#F6dA2P+0!5)qN2!vm)wqdlm3yDME4i8* z5BHRxdbz$o0ZmUMBV5x9Q5Na~uBWm=-cf~~-RFo+#n8sC{Tl~6CcUX%D_DSjsXJmz$ynGM+e`3aO-&TpmyelTrY*9PihwW z>%{+6$cJa&)EMc7<3nXWtq_(%4R7k%jfotae1DdlM<=oi`{{2>Bd(0|V!ET%!==J>{a(|W=NP`kqVv=zi7sxa*@ zrU|}5OrL+i-vW09_fhp$&^^zMH@Lpl=<)>68HDwTDu{=G4<@}~Ft}amjc?`Zk0*U` z&Zb-R!RlkQ8_)If8(*Xf@Q$Q4eI#_&QN0hH+IVH?PplNx{%+U9g`4=k2q;T*P}kDa zVMy}$G-=gHF^&0&V1BFMx3CGc;W+K%2EFYWR>HZ?nc($BV!dBJC0|eJ+)^?lC*e=!IroNK>)f%JIiBZ2lUZ@^*Q>yfy<3(+s~E(LR=e~z8nW!XRd5t~bNL%>IG;?zmyDOR@AcWqn^a7k*Pt0#o z`)7DI3PxIb3NRz0oVcO34P`z@@E?DTB!uWm zyMaMHE?V){J*`|)7idRD9>p|)&hnpU=@;=7hEGx{qA?=OnoT&}e3+47C?HJn*UVH$m?k!#tD|@n+!jPXp7N!XXNX`oOcs^D)5CViM8b`&Zgv5 zz}qJk0X;DXzbi;!#+{fA&KJ+v=WEu_Kh*6}#^go>^A$Z2)!Ct-r+-Z*3U%z4++h^X z55cC~xD&w>b$pR`{{#=tDu)Ly=roSPoS4L4CcSEt1DK-}U;oz`yjP#Xj>#MwRv z7AG@x-dU%+3NH?OKZglOE=mE*;2Ximsk$w9!F}2`UA1x87{f8&>g*@L&3U2UY0^Yu z!MIsN+%KECIJ&+E{sf5wHgHB&!T)7h1wijBBL~rWm^ytIL{d#Z`n=T%!y$?V`LuBd z!$_x9D#durn>I4LG)WcmLSJ$cZ7=Vt@&_uk86U2HnKdJS9d2Jh3nxnaw>VT<_Ti2h zdNr|4Ip*Hc*8YyEt%nVVI$|n>$VaDiV2o|Da{V;4PCn%R8%ROMe#H9of}U^o^JSR5m{4epaX{D{D6D^?8->!xgjEF zC*Q|a82L^EC;XgCvNwwk!uQ+tsZ;U&(BWa+t^@6TJfzb3cV z>S&rbT-0zmr8G@^u&C-npVB3ne^mREtIk75lkYMSM&Qg9s)ezSn!-cT^C&x-36JnZ z=qghD$Q0QjgPGBc5(6juth#;e@CXmQqfb18{?gA3tN8sSfy>0E@T1Ez&>vwOS*iU%ob)DAlR)hBPe0wnA*v`%_s4k7 zqDmDH<=N2bRH(f#`GN^VQpXM4mk*nS3waAUgx=+N0jZuHuknw896(orot~vUv{soh ziN3C|M|FnQRyBMb*6>!+LFO)}L{sxF^*2#(B4B8aws*5tHI;F=6KGvG=N4 z#T67vajLk7`MvPGpCpV)011xsK+*5@>{B- zn=z*K8N6kG{TDxc$;5wRa-TreA#N>;GGweSg`vR(A|XmJ20msfB2TYJx#2 z>Lk&uUtdXWT?9|?Ogn~dq{2Ld2cq(|lD-srKjJkT z`kVRNdGi&W9eo;5Q+*K|v$$$q z^71$$U8zEhrO6WOJ8!Q~qIelw9v6GWM=OQrb+k16Lk9p{$lLGxKX&a(&hWi=3(#K= zpLC@B+)MRqefPrE75MFaK(>WIx|6z`9GgJ4?&Hh3&>8_%)p0z?vDlbF-;g&S9PB5C zdLW|Bw0h{VfQ-@kD)3wq^A8+n2l5A;&2O36{S=3V?z6It7#+duj;CE0ZP6Ux&9#(- zzQA8rOu7kFv3|WzNS^$z31*1<)Jmp4dkCdQ4Hg=SkUHfx>A0r)t=Fp;+};A;xrHKg ztD~le_QU-?FR+6^Y*xKQiFjFp{gQ--?|alb|1y^Up2H;VtAg~K6FGxH7xX01;ha@z z6C61;@krWg+JvL&VVb?wi?-XyYFdE@151wTYJ8kTjt)17qr0!14(-6D7Ah-bH_8=C zO`VTvbmMg=QXSQ?F88iytsh17WfvieCt&Vm?@muP1bL{e5Bz*w@RCG9*^>0GNb-|@6NSwBVFf2Z}XILHGJLvfWeNfYN_7q zFTqi5@y5uHAwF*?REQP1%`f&?tf@tCY2X2Kto8&@XwJEL+}4JXCX(jFFy}IqDpcol zVNUKbgXEG0%+?FElf*!ulmtwmg3=`G39b}M<6H6?8)G7f$F2DuBLg!=mIU}*EeDtqo$J*tC>agi@>+d>!L&N@m&R+oH;q-~3Ql>2Tuei@dj2ThHT~ z@~?z1eHg>f{>HKu6<&0m-e;l$+;Ca=fCee0TMu42f*7RxKd#+j0GpB=7~@mIu8Fb? zkbdEjejceCOR~Z}+=djMj^mFh?(VTE@qr;e$&lBOM6XA+<^1=gzcvO`YfLGo=e-t3 zoF8lt^YLkt$~fG<+sru$x1;NcDO|74&(AMqjhWx=YBW8BG$GH6`J5tw_oq%>ZRRhv z+YD_SUAKTi%cp+mEkd7P#NPj_(eaEKsBuGvuPyllbo8O%Y-G%pPF@T^vcKIL4f_L# zM2&_6+xIKz&=q9t&ZOIJPEWA!ic2q}cc_Hpu*5x2xbBJrt&ML>5yHF!DE6s~CXaKR zyR}uw?UblP*tB1m+0eU~d64&+{oi5{BnAs)Bhkn7&ae8Y zWolG}!W+KBQP{xnhJUYGUdF4=9oaqgP@QOMj=?OOcL-Ilu%XkD@r6CkYbvU^#eY!! zKpm}Eg*{H>Vtt7oReU3oYm;qzXAh=T2t?hzNL~XLNIB{Dq`SMhLJTy`ym=(G%U>n` zwjYiKyxVvB*8br}lN!hj+yj_>9P~oXHHt4 zNckNa&~oM6;Yt#HxWN|E>Yg?v3Pg%|o^)jJ^Pe!kdxr!G@49|nT51UO_Bz3MM@!wJ zVN0G0aQ?7F(H*qyYUiD{m7@ao#O`GR z-{I>v4Vq;lUAJXO5xS8WxBLHx7GT;Y06h4jEPP<&1AmU=+>D94xY*xKQWj}Cx>@leNp!QWSB;IE)$5jyY6gN@_+0#6KYoFUFxY!|?CW3)I|*YQSEi{mBr+C~MW&Q&w% z$W?de#$LfT0s(w3Ir&!`K;`7?KjuXOr^oiH-JD9)PIH^+8{*aaFi?QFCN?-YxH`a> zpI`zMARh8KMP4p?5G^6{4-KvtUT%~rFy?v)iZ>W1IiGKw2z&Z2a^?E1pAg0l0HkV3 z6|4g&`Q~eH*-`r=T^mrUcFA|-Fz;M_?|P|sy;vw4vf_Jo%la93H%>sLgs9D%F`nt7 zEky^2`4?icZ1X3MUj2xDMz*Htwr$gV;}1JVm3w(R`uo$Lc}0vbf{nwAJPS8cq$Gy|vI*mh z^%qKn|7~Sm_+|2d*Ux*46SCG8)$q$3yi8L5Ua3 z7C69S_VfwtL0r>nN1&92O}_#~gn^RYM@~OQqxiktfZT(ksqSf?5YDm7BFpQuE+=;e zyITvyWuOS^1JDt4W)NzW{sh({eysSI_HLf&u|K5tu}>9kLNj0n2B!fr=6Y182{=Op z9%R);#W-oXf~eLjiuza3P7Rac^R|evZ`&nqA?k1R@$2bFlFR_&q}UVq;wm4zr1L_E z7%{16F=v>x)D;)o1@zvDiwtOiiZ=PaWToY=Nm(lXWeX}Ae?8*ZD}(t=BjvV>P8WBXa!D(i`bEv0~l;?FA}RD3L2TV=2V!Czr> zx*knpd)M*Jr~kKy`6rO5{^=p{I<58IYjP7|svj@AOf=oPJxcqo)uZN~p-V32XZl#D z6Ufr7wRKNH@6l30M{Ny!v9M){sl!S~hUARNFU~JHzR=t3{JY#2jVUL6&B%%ps-;X5 zKWiS*#5-;a0{-3wcDfa3=%U-kSw=%i6M~QR6VxT&^n$=p_V1t9hO=l=5U>h`)MK9F zYDdeh#I1Tcn+NCWbcrze_h!=7vo`M$PPM3xn}MCF-X~KyPlN}rT8gtZKOCMTTIYL|`rMzuqhpH#9NPDbE0<^|?}QRYj{)~u2fV+C*n@d$RKq& zm)i7Ib8FL_(CCOf83Yi$=bpQB7 z1#%FJQ22288$qD!xqt1Y$7*u}GB6(<0A-SU%l{O7ys_gMYUdGgmb(|Deg4BN5laz$ zuTNl`Z1A!KVa@YsX)zc{32)oV%y%jHyh7QqYj<(Ec4~pOZ2-}hg+Lcs3@FUSl?^c) z6qz4YH_e`U|2i$UQ#<|s_<;}OdtvAYlICAwky{DO^VT{;`giN;%-#+zLkreoU#p0ROpqSLjl|sEwBHS411<`8&RIHqiY4 zT2ZXNqVJnQ2&4i=FfZk%!g%w;3dP(4B*JO5%ZuJLzT=r+yZ3Agv7D^ zAbPqXNc&5iV|EJAbEj4`K+^j zntD*8bf|%}Y$nJytOijz0)3P0Jtj-A@r5?{Js|*+sjET{ZP096d9d;OR;a1e&_C>* z9l(x0oRaUVI&cGgK9kP|5V-Y|JdE9#F?>JJJOqP^b-i$a$urMzVaba1+lB%5q02Ww zI~oI^iBFx@+H226H>oZ?n{0sVwhM9LpK!YR5CJqlNEv_6HaA?Z;chL4N_EEgaZrh9 zZ)H#bj95!9^&?X7$9~(L;yj>jlw8|}8vlO$E=L?PLPsT}2gGP;&c}FD1|vMbv>9ZY z#To%F%b`A+$vX>k)nUksZ~Fv5#o0+U>pzRW$M^GAwVbHYVSL)R=)4AG~sp|Q>>UP zejO0NJd^D{4egVHcIBdL%U`Yfk8yKHVo7%-yD(i$hN5i_DM_F-kT|R%H}GsEr8>f) zgDniha&Na{T+W%e6LCn#Uy*Yc?DdK7Ib(vljnF|QWY$GFKj-?kw`p4XWG=T6CIYfQHI zaGkrGl-I3As&b2w1|B!6_~B2`{IMs90X0q7fCyOd&M49irua>92&3}QWbHf$7$Sc6 z+l}j<<#N^ZlaKL$75OV%TE+^2y>T8-Icl!{q#?cr!Hc?WgQ280h55#obA#;kT!zro zz@UT9*5l~JA6A<)IO|kgd`WPJo=w?pw>-u!v+|(vpE`&i?9>q^seZ zf}T($C)fEzJCLO{oYqc}2shtIg45M0hSvkE;|j%xBR5oMs`)~~71_xpifD3BgG1$p#f<*MuUO)EEz=Eq!)S!G~0y@24` zo!h(%CZ?4sf0+u+fHeye@`<7Kzi$eobf~`j!349b3})ub$XB&NQM%#^lyOnM27ktbH)9`#LlSD zJWR5owl8tyE5!efBLy*acnB?4Cn%#f$ZUYiT2{| zcEmSy$UceY0zdQUlgX6)KKiizUyuMVAHBGcZ||3>DGU%paiIcj*V@m&fi6Ij7Zvu+ ztnsN2N8S6a#W4Kk#+iF z*gtk|et||yc^J>?3&Qtdl}no9g8$;j3`uv(yNtdadjYG_960rQ-;TbR7=@ZMu8ac* zHx8gV?fLIs&)}iS#u#M3;J9 z*Y6~u1dmQ3{@m}`ID-J~vc}0v5u^mej6i>nmVF=T@d=c9oYJ)x3!EPZjj2rZ@c$O{ z(y&r`Z>Rj>GZBsl_Js!0o}_c{_xnR{r<=oeMuA7lj#Pt@r_@Pr!L9<1606XeyJ#Hmb%I zgh+UAyQO=yw0&i3_(>Ja1T=qKvYt((?%pS5{?*-MlON%{SvDBW`s*1x3)?O0G(G}Z zSS<%L9{vy#^tJc?G=wk-?%m+kp*n8{qi((}BpH#d3kaK`0+NxfB zlr-4XTfW{r&`|^_(&&Krd%|+LFbMOZ)tPH_g3;q%p^d~e@`96jqM%RZ9B+nnj-7F% zzU6vSV&3J7$EGmRiT3_$1k3l`n0Cf?Kl}G`P#C???oYi9P>G*h&N&%yZqLsHqO|{Y zCem5Q#PCsLTmy6c4qM7Zh|?|XW{Dn%#I*@<`4jw7m0!HhF9FM|R4pt4*A&nu@SzU? z2;faipWG+PyE5X}wg6Bd(X$Eec+Q^lu|uJ+Mci`I(T3eg^=5`-rqb9>cLAY0FR14*SswuQ>7I>v z41V_FCVY!)2BY_wqY1581(YA@d=6r4L5lZV{leQ@Y@i8tWt?!Mbi(Z6h;5tyNo2k( zd)JcR6By_#C>AaCbfX#|E?9tv@1e>W52Gfu&9bA9`cG52P0;vMYZ951x+L|RpD8Ex zPQCIX4|&6m(9r({fw>`_&NH!s0CyC37C|4&i=BNRen!o(AXr&>$==VjzjN*^6kidQ zb0`DE#kqxXC|rugMCo&9F_{$iN?kpejBsJkxeD4{b;3!+cM3qWti+ zlFED!NV6}wV>0$Uz#x6?Vrm+JXX8lJHT2JQ-Q>?F_#-b2R7xtee=OMdo8}=etQSx5 z8M^X~h+_!zx*BXzVuFa9v6hJfPu3NZW}Kw7bE=j$UUN;Ey&D=exbeE^W6#WAB?*a_ zj81fNd{3Niuj_YQ)tQ_^_O*hw2b{j6Z|`Jt{hqoH&y&S+4;VhxwUX#ZFqNbpc)N4q zymWXBDDT+&+m4oHxICv#n#Mx=zLQ+0Kxtjb9PnZUF%k_oL=N~;ZNlOTM_@OA;(PqL6e)?f0E#efU-?S!HQ|H--?<(_(YT`Q|toUr#S zII5Hk@IBNN!P{-wYT7SxEWzmca zMh8Yh3c9HyLG+1Nga?@$dMEzJ+^+g}A!$G9iHca9F1YbHf=@6$K|cTgGoSHr!B8yFEO z(m%ZMc3I3BL%kzKQKd=>MFIB4M~Mj3`KN_{QUg3>|(2#emApM zu74y>8boYD=2ULcJ#UZK2E_t>rXF6tDHKceY29rqh2jE)bIABMQ|j#NMqw^AP!3g0 zX_H3#76h{T>1AY}8euO$d~$M$h8+_vwgMb#pgZbn2Ym49?cHq?(nTf|ba_PJxi9~^ z-@B~T<&Gbkc%%8n8+0@_K6PZ%cL@RodG|}yMN7Nc&*H7~Y4})tCh}oia7L+t+?|}L zCz*`RvctRfiwBmJyJQbY%cdQ=8m+@q#csDBBd^PqkINzIRJk@mdxRZiu5H=XLsV=xJ8x74-~X-c4xfV*MKy24AI=-=86eC8$>LHhv3q=+pcSiFqB{8+ zM`l9(J^yA>5XJ8)TD{f1j$`5I>88#le!)EYlKVIR$4seiB>uw^Z5zq{K^5KPnqwAa z$LVvvgi*?FIivWv@Hmy*T_;vOYhNf2JJ^)oftl19l zb+m%jKocCzuQU$fOS28^NUuAybN_IzyW=A)fG&_S!w7!~MeNECFS;$De*}<2j=19k zB4%FK#vnN;x|MpWO~eV0qq;O&#Q(@-f-(Hr+mjrOhJtm8jIEd0{81bm104A0Pgv8yO_R)@o> zZfz?la)jl`!zdj$OI@72d8L{dJDF&Swiuq$Sm{9xI3a~;GzV1*0c^mO^~ot2PFM?g z2{LuacQA?IMtQrTz!ICS`%?c948x&YX>Tz8*YoGcO_EFv!Ht*x%wgcI^4BmW{4C03 zH72J>M(wGtn{-6L3;@plr;Cr#`uE47Xi4;mo4<)O3@gQz>62<(U7;BFK6V;hx&`ci z(e_jfWck@`+~W=GINGCPj$BMkKr{ElyvXz;aZQ{w?FeD$6@Ce1`3Ps|dafq4?Xv55 zW?N@qNj!<-?^N7sz{Vd23{kJ#a&5uCe0vMNleABi9UBOh?BXS~!uNNhr3)W}z&<}s zs=SI>h-_o_Ra+x|C1h}xCIkk2@D5ynwjMO8Om4x%1?aW7VG>I8li1rUu;!9f-3Jj_ zcE%AX&^YEWfaIGHJgsg^g~!qLBb6W?pW5Y`5iTuYuL8(Q5cb)129JxPdDB={X;8Zv zD4jzu7UKarB6q2Xb~2drPkqfW<_oQw)qIv;I3x}ZN zo!s^4G>dCVK_B=3qX^>AE%bxRa+HI~a}8#S(1@GM+a?WZvsy(xh3v2AvOQB(s+I4CIU}rx zqxCiP6n0ArKIo3?a{o8sTmQH*5<^2Yt@kF??;3o$Uj6{=W7s7#Rxl?S-GXUFV6$)EF3nHUqzTOcxWoACg*=Pd7z_4>we&6zW5U; z&@SkobDzTJp*TrSz5kS*{K#g~d7AtaD#(d|VJ}Fh+kQGZA2jmz) zk_N;q5S?g-HDHy>8HIMOJ|e{BAJG1_pRI!`oC1=m$#Zjolx7HoGL${LZ=*ssgME4B z9`-arXr(iS$;fcpwe5cZDbVR0=97DDTZ30gg3MB zNF`RF@ab!Gadw;5{x1frE{l&%frfj!f8{vw$mI!+Wj-j7hKD9jg;wpsoh7~}cRL%I z_~pzp{S?xc*XtcjPaAj^ht*usPD1T`o6GyROZfj{>n)(7?Ao^B0R)s*x-kgpl7;~V z5d=n5x*McJni-IrPC-JtQR(h(knV2jh9QQT`7gYm=l|Ysz2904iv?>jd-k>WK9BP_ zj`Q3ji{o3g4Pwky@vGLV;TQ8~dz7;ax`bVJ3#hpUn8!XT!>)D#X?T^Tz7dDz?K7a; zP3l##@_pjZPispk3~_$ZjY=W7r%x3?iOD3Dj`zf@o-QeLy#UTxOKHI<$P;2gE^ur@ zILmd_1?M~7yYAM7MHX^(DFeFFXso-AuUW4qv~O0o*tw9~piyms54)}e?B^-&%- zoQ(&P&I#(A13Ur~B^&nrAb9LT^;0cMpuO(#bwPK9=fF_W?(|#NQ7h3bD-jEGM=r^E z*Tpl78K6C#f!jHIA?+k$WO%prT=C3o_YK*+0nZWmYg$nOcsavo^0P>-&+Rr9gZQry z2VzIvWNRuqXCJ6O&WOy-FlS>pP)&>>rnb_+lBnUUZai$+iBDIJlK!%-os7ZFIc#hz z8K%2LCcV-g@wVOnPv@HfP%8$0yimYD4dDXc$G$4;0+r#CWFmCHr6Xe1mCuQ5sa_+T zwushIXX5d=Ox@J@w4gCN2|*B3Zh$rnFyGqnSTTS|uxEMV%XFzaHn3kwID3rQ{1cQg ztyORXz$dz&9g`g6QB~}frs@5r4nx0<>v*ReX8btEVLlA8+`)DiDBP@;dY@N+t@=+2 zX(^uduYLMX(dztdo)Ke*_o#&)DNnr;CsU#%$BLy%^r>Si;pe7lwBi<^o?x{O()9NK zQ^XkPojH%QL1h_3{nQ`uZyQ_#-!Otc>cj&-aEQy2?+ln9`Sd;>9ulxHna012IS^A$EGHkE89)(+s)D z&)6#p4UJ7EHRsbmw}d~AVfsdTBJdHY`API~#zc%1#!Tsjg8skCPI2CvIS7unIP!T# zS641EYH;C-c%Hx>ZByTe|6woWyNbV<^;YITL2t`yTNUbXD?2)R-v##b6Z0e9YS1hN z0XNR84UWYmE)Y|}#K3bf384;%RQgShF7F!z|@`n&HK50*?LaV!K>yC?tI2CE#n z`c>sowh%wu+U<@2<30a|r{G9@->f@=l(l&6^}@2Gy|g#sL0jC#9eA*pYmYD#=k zyMyKG-r3Pq<8eRWqJPg9%haI3bwExAm(e^t=OQ0Z7AQjK%>Pn+qA@5z-G7pz+HLdM zix?Zpy_~ME6^0-s;njLb0_q8^-tPa#42q#Z1Qf>qKo*W}FsNrkGkjf!6=rcp!udFx zwWV2B_gEF-@}k7e!Er`gY(@@diz25i?jQGxO@AvwXKC-(dchr#hbw_@+|^d zk*V|sO!PJAb%GoPCqxS#j&TkC4|~CP%a)+42NZUc-fe;ymM>5b2-r4#<3>p z1GWnfHtYo@s*ilpb5T-`UO}Q!&h0lJu(GZ{6-|N8zl6zTd=k`kOd{;~CSs4@e3G66 zaZLa5!q;h3&2wBJF%J24&LX_6oO6hB@k@*h>(lHNtp9oedY=^=@IVA@fd|HY{C&Ve z4-w_%#bfW1nDQdZ9vq^Fq-c-Ez~6B*$fsoh*;e|gXCI0U*%)DXQj836_+ah)Xj!hs z++jNAv=crn=sm#4A0Z*Gq=6keMCKr1Q#VMK^N9E9FPT9r!bHLqnoh|eE~GL7vlVzc zdh;;=_sKDil|^ey+6^a6=4$mAB;Y(VWlicu#-#UpbsM~zrjZ`S!7(PVw6dk1Jn-Tj z5Z1#=@j79@{Dyou&-zPfK#{ehgQ-15q08GiGg2jMn&&sE@<}HYSb8@G`$6ff+TMD5 z!bUi1ZaF^dyW@N3Y|=T)FR4zYav&jk#v(!8{4-LeG8c27g{P0;etw}9i}#%}2u5Hh z2fszItTeW}#~@d3Gu6BxE{c4`vn%o51kxiI9g?w?o_iHnvkQ%!5sI0>UEu33Df7^O z96hX&F4385U8BoMP3CE&)f2MI`g}|3YQ^7vV3VIg(z8>z`Sx_chkm1CSgIom4e!xJ zyD$PD{o7Q$N3w`xSS)zunf!yL7gDpdi+DCNJ*)F{{O8{BnX}ayYKOT)%_kLN6tJeR zmgviQ8c2*lQ6y{1Qv>!~8eZW7wc%?1Pu?eGCkd&hJx3T0wcR4e=f1eO4uM^CQCi6js22OV@*}CtOd}S?dwlcibpw+w%(QC3tw6@NDUc6AwNUFA7m|YQbgtgq{ zwH4rmD)a|kR9hscr+n^euMHWWAO?e)94($+tlN)mT4jr#_=wcE^kMw$jlpQ$dHp5tlT! z>|-$WxPplrcrwJFGA!xesIqkjGB<_lMdNCt;Abkt>z4x*Ts8}{tp^P?k_-=m;|$w1y!1?7@#QYgk|feR6fY_#uiiGI9naIVc1{R@+B$}9)x9tUZ<4jI4}Om= zGivvU+?bLQv<8*9)Fs7EK@gQ!}j z_l$b**#Udy>_yE%z!EKuK}IlLZ^YW%J6H>+Z&%hI{2Yw)bFv=nwx&o%fPcs)$e6t1 zU|j;b(nJXmyF^QMF~#;W7j+r@6&(`KjiVrq^1f&G2RKzGET-I4TN8Ex^C=TwB0qg!N`)Ue6rAU=Ql0b(O_fcAG& zi^~1(pee_!oALD!S1N2-9%^M&`4tA{T65fdEp+rC^J(&1YwMrYV4{|m;`xAAg7K=- zVqbzEBsQMAeVHyf%n2#lcXJRoS*@JyZa-LgmR))r;%HxDFBm;wQI@$`_Q}41^O6j^ z_dHB@K6{$Gx*F2(Q77J0`%c;xv%KfhBBBQtE&OhAis;Lve=9uwbf@HY1FpGz*7Q{5QS9~&gn{)$e4;S;;%DNSY4{ z!?@FfeJnjDhmPsy#-qwPd2EJHZK{_rpiz*Ahyl-a0O*!GL@O09hsZzTV=(`z7T z(ZA9q_SsOeYly#$NLPsoQuj{f{_+*7pF4mk$Cexkdn5Ga5kBr$pw{h4G{c0zQdD?* z;QfrA2wV@k?q!iPY57q`3x;jB8?vzd)8nNYEnWxPG>wPfBwIJ0t7wCtQ?o~ zwUXU1+%c(PJ_!8w{Kia7xD1g%pCUBx8vH7039nM6=SzNq@9!TQ)&uSOLx-0;cBJNe zWOFt|Nfbp%X;#&BDt4PT-AZtW`cUBu#V1O8SII8laniP#M4c?RaIlNAN78B1EUA?O zo8sXh&}q&j%@53GY3YS17WAhgzu%{NoEw4(@*>J`dy{F>D5+gkMbsQGSH)5IO=YOn z=Zw7yiJ!bXdqG|l<>3Cuh-^A_Mt9bK=$}8ZrLQPx_$|mhkdIRbXT@f(QoD7Zb2&=-`%LjUs|Mpk zN;``es7~ihcdNPA(%SdX>#k^&G^lXB7fX`e=X;V0PTd4*ysiMW@>82i1GXkpDN%N& zpqF8Eb{1Uca-VnNnKYC8qA5>ud3vKy+{c;pZG0NefiGrSBRzzb^~GS_-&u@4ifq~FO?yo9bNY$90fC3ELJF4m7BmD{nq6CA zB#A1gD4&}gQMkm2MG@o_7)k4b+U=k3o6k3uSA+>bJ(G-81TR>Unrc2_v7hFNmLwn> zKN-{JpFL_aKP~ulA~LjWKC2R_J?1h2QP#f^vxOJYifi6pyv{=Myx;_))9Xc9>(zRT z@E?hm_DX^Q&Ai>E=ubkkCk<9BGFCXCQvJ)o^};0OeM^s_$6S~b5k$#}t_Jqror&A} z66KB;9lyG}xVq@%z?SJut&@AOT(H)SV-JK5`D2S4>ZV=P{8Do06czD^bTO>QL;Kup zWdz&)t;C@JE-N)DGPMFkASfEfAOMb{s#2@D)a_!H0DVDSVt}p-eb$RC!}_6L z;Dp&mUTTzr4LMaY$6m6ak+2eqM=el(LkjR3Jc8&IclstH=8xDB?#m*BuO6m|3vIbc z;;egNPgOaF0&I`4Tfd=9_j>5Tj_28F2&Sbo)#VnMCubs;dl&R>Na7+B20KR=SS(uk zf!_qm;m9^&sPsHGCewersQtZL4E!uGL<#fs9^={ztoo8nxoDXZV@qESMBj|X(5r~6 ztT+O=FJ$*dE^Z#kkmiMpAsCapcIr~~G7u(fiLRDd>+ps{o7HEd>Okq&$wUoPQk>9}NVrIUyKl0Nq| z0S1k8uRMs$G8uI5b_UPVaJ;5GJ={k*c~e?jK`?W9z}uJ^ij;jQS!YaFwmq9m>;YxX z)H_V(%(Cb^as%c?ZfM46+rVDkv-y<8N{6Me{vovs@hby`db5;nM)EJ;jr6KxbB+u~ z1@>@7%or@bR(Q~y!#qxd?Y$xf8+>^&R^CqA)x8v9IBXj15M0}Z5C+3jTdkMw{p@|R zr^p0=)h`;s&&$BvEiIc8Bx+xb>@#Z}*FqTbPdGfCgvEYiy_0+Bw_95?;1et7tv4SP zqz|PP`~l^GR4(r!L`pUglNvF0)cGg!pqt9k6~|G9poqKq)6)ptx{Rmw1B$xRZCv+i*`wyA=g-PJt4t@K=XMgzrM=Zgf^E) zNa1iCrGjjb3-~ewD?_;=?&>1eFaP!g>j(e4)PLY?e4|bJ^Zf@-HX9i?8zJgTM$C$y zSf?4~7Yd6l&zjmv2!XG=F*>6JyZALtmabxtG4*4cUL@l@EJa!^KX8p99mq|I34w#Cps}r^`-wMG!S0~w3 zBL+90uX0$WuXs8W&07whedDE)hwVxWDo@D7l;L@=@d%#Mfr4R|CMJ*b>u{iR`vbzz zN62Z-*UV(_$2VWPsg=7|Z$f~MMqzwCP=192BVY=oFET>pRL_Y|%~FJDB&^ukqocci z(PHhf`{btQpa@J1@$0Q`FZ&+`zjPE1MF=a&GW@ZcVukQA8eIcUEt1`KiHUD>U20|RIf`Utmlvl>{ZtJ^4Z8{{*yALRH}U9b7#SvX#Dv|q-# zj*q&m0&lBw31!sX>g*Jf$%rr|HBj55}5q*W-p7@Yphd=f-;@e|}Gg9tb%~ z6)z~Jd47=)S6rcY?o|aTASdXq+(HUq(LC#(+3f@Nr0ztg#}_eBQ0G4Gg5qb1pa?AbDa(I^m zQA_!<;=+@_reHxgg(ya*CW%pt!Kbu&z(u_G7-UOFjyOJJ@?`%xQM*wDM>b0g&3;)T zbqHIfQ&?(gJwKDa9Lv`ic$%&T^9S}fICsn$XD+J+&3Z8^^mH#!-pq7s;f@IR&Wyg0ZFJ91KIiOQG>LG zF=0DNF|jYjdspyz`=_v>RPi7P82OEHeRr~;gLo_2&n#c7tzgfr@mGSLK7Z1Na1Fb3 zksmN(W9Nc)gAd~y5HuExPz^gBK{O#4Q~)ejDHDP`vwGjk7(>1yA{U={R`SU4s}q1% z(UwXH^1z(mOx(^0a0E^lgT(t zV+rRjic7rYL?PsK!g8B^npUmg6Qt_EyAIK9@}R_h^K#?Mi*nwdHk2v@zPgQX*{BJlY@(sxj5$JsGMRO*uT<_pe1IfrEAz}4di>mfupO2%H%q)bE3JdsjyNTM@Y z4hG}g^w&OhB>0O@jc1Q?j+U*q{21JjIi^4OM#EZ`j=%B5n+QAry?aE~<%}t9WjouX zHjCi8bZu*9bDwR8#a@Lj1hhFRH>mr1)w|mBK7ZFAbngjJvA5vDPeu!hfr4$^VJqq{!~F>W*MM$_4hVYLk=W+S@qby`K48H}~=r3WUqS zUq-C~aK_QZEe={&0V`kLLCfJE!o#%qf7jL1}~*9DEuIZb=9C@rjQ470knHB{HB zt`w+^fl%3prHjhhC4uXi zkNukAJ?e0I`(<95(79sB|DeERXXknw)`%|)s1wa;b!a^xu0Hvb?U7&IZer=LYS<{( zn%EbMH(m}y#>+L?KQH)vn#FFD2M*aBSd&(plC*K=BWA@$={aI)R!6jy9Hnf21gb|j_AOUHAfY7bfH=8DqR&$hTBec?>Mu{hLLY84wjpwt*$}F z=~`K86;Axr)O%YP9TcWlgCAtcncX<1+8PP6bKg1or^o(rK_*cLuD9HoU6Q%iF=OZT z16Nqps+IP2-$9x!QmIqMXSeHVLo~j9R5p)i7P1xg@hGLS1P@=8Kg4&|o^Aj{1A;r< zXfCu!+cRtcz$LJn1L=PA0V7Lbz)f}WkRK1EvXFN?r^lkk^>*k&;auT*Aa9;`Q z`(}e4C|Vs6w}G%v;=)eDCDG$qInKtx8`zXBVO)W7?Id;5JOove8b}O{6+i&~sNYbA zlY3NSIq<%|=~4P8jRT9xLtz{VjL5^-j@=+eIZhSU#r1<+mYY6y(nW zFPAJ=ES?+wC22{3v(u};4P+P6C%h02;`29> zqx>L}@0h-a9G|`ha`akvUpmGVe2KJjURrunvDR-v%(mlhW;; z4o<9NsJnYttrPe-YfcTJRUKwqPUK@@esCMaq}cH6$e=ZqWUEJLGz?d3r)NAJ4$u?iitaf=GRLoPfzjrx>jtdMy42vmsd4gMgw+~ z7^RzW)yx_GVKyQ)YWiHIP!*p~c9N15AD3|OIP7VJXQ970b*g%p*JX1x=l-TkvvO4d zyuyYO%`!!gIe>f3Kh5|LsVCW`eIm&Wsh<%Tz*IfsU~B46W#moX#e0iRjfOI5pO&~= zoLsA~$wOCOE{QxYc7B}SMk3K}Rc`;Wx$7n$5dw$pWDAAY_cay%GS1YwWvAe7Qr%Dp z5Ep&siUcOFUOzz@ix`@FIY??-t#U_45oM`r@0HChbsvNy-|2e9w5iXUZ&7uUHmOw) zXBwn!cO->$W#JSR2Ay_B#>jh4bgAElsy&;90a*&GssU$pmV1hP3HU{q`tMU^%Q&y% zKJAnRy+Y6vk?2r)z)T={RQ4>{!@@9sQi{FrG94ti;_#Z|z3R7$5(faM!mOT9;kd15~vCb z)6MkVi@?JjQ-B))>4Cx|+7EPPIzkzM`@Q-(vJE)gj?yOm^c<7F$PaFk$4ZzpH~F$- z;Pm0MdM=tu>6(E(5Wpb|9;Fo2jK>}*&p_O!DTFifm6-!8+^BbK@bhpr(o08jKI=`1 z)FebXEp9m~7$80FawJZj)ilcjyQ^|aS?odM!i(wn%~M&{#lKUchTe%~k%CRp{P0Zc z^)Ecfold7Av5mLSs`n|`L;eEztWOi_~}T!BqSbxH6cYgfwvJd4l8LeYI88pug+QG)rs*Ro%6N3^jT?SbmCU+G!I+2iDugNIC8KIF}M!5 z`Y2HeZFQ$|95beRLuGG2hSa!Ggwb4(6Q8@Bz9CLcH7O{az}A8;@mle3kv2A_6X1>b z5OR4MZvNIX15+b@e-9@&I5&Jb9mOzo&q*(n@>M<5W#4D~{>2>22qKEIn`|5Pr=ZnD z6EBd-;TpMQ9Mmu&Au-xK4Qa%A)eJQ@ufM;7hzOZ7cb-{XY&BYJ9~vT3PgdSI)dDzU z$re6=0l#xC#S$szuBWsw${a@Aw=DaW@ZEBS)Lmar0)c z@p2g$$?cHoE&6U3(Vfjnlo?V3Uhub#ZC2@F8Gp5@Dry|E^LgYpL)D^z_1{!Dd+0`0J-r ztiLWNd04d5$dK-aT@RcA$Xq4A`t=}}CmzW#(Xl^W!z(S-K}EdzrXGEV$itviQ76R1 z0^iIRhqs{a(Q#0FTo(&$3*V##hoG!EvmfChNPJ}c zjRf8A6X>;+nu3@2w$2`2K8P*-?ZnWHg-ZgogldmXAs~CZ1xUxofAO3$aUe(cAY{QT_G}){u~;oB zT0H&Jan*r5M~a*PP`i>eF?qAbmVJe1?ML>6dtV%?SsIcV;W$1!yuR24pY-BzNv&;% zrCHWJF#@OURGYmnwq*0lirv5a|FOl(9EHB_(f$(oir_Tpd;W>em)aZKuRs3R3s9!& zUECKs5_;_OV(~c^;f#L4%cu5U-FT6d1)$d9@9do$k9+|}GKLM2T?60`@-aT(wjzum z#ux82x!pXnE?!XGC*IjE#Yq~fkSLj*F4=MS^TOOV#;9-pGrK^%wIirFCQ*LR=6TL5 z&d5h@jt@UJnx)*7oR4So{4pD;u*|;^TCUdiv{>7}>@e|m@lHqkSfOY@E2|dh0DCXw zCR+TX!EE|_62cidFpVwg#Rt;C>Pc)T->}CkQ}wYA?Gk^8#StrdVqh;a+$QTB^Wp_B zL9WR;2?6{LlA#!$I|VDD*4k-?N`0^r zbN197kZe+wF?Wsk*U8F!>afV8N%YH!?aODrl&5_t4&?bZZFjX7$`MrLh4M(onpG%6 zUstF<%L~q4N4W0|a)5kepW;W+OM7@giJTMmy)G6n(fGJA{V4Z=mO9siIavSJ+0`@* zsnLAGgIeRc5$m;wA#`ppykHS9&1+U0;exB=1v$FvB+W6GTWVN$-(|U_L2a-ue7IE( zA%D|pxfYs++mP6SZR&7phCjVDk&3b3Xx!NA8%Dswk>#`c;>ONvsf>TmzQRqvNwg7xe z&u*%U3Wh*}bwjckAqYW;O99VYQ}4fyE_ z=^+G%qviLA-B;_*ZqX&p9)ZBCyKNJHIJIZ=#OL<#vIpdgKDxrcJxb8;#0S^H;5<*`vGH>4g|)dC{(nyb#h%nfg25$ z7}l+{x2ge1bnT4~3&Mnj!f?^_QjusYX3fQ=Gdh4V0g~J`5KjH%NpE+t$98>Y9CBly z=6P7TnWgOx3 z%*3eehjK6&<}%7JL)gNf5T2FvTHI!S4mU`Xz(nlMZ2B?RNq~cTE(;hCQAZke3F`Nv zL9NYV-ITDKr!}g!FLak?D(4}JLq5lCxXbYaW)hy~!S>$Qn+XW9UW;^}Kt}XIRN2)Y zA>`VMulfyLD_PhCuaZ>aTkCbwcW`Rh}gYt4i3FTTK~i2l_t+$~K)+ z<~zTWpm4zRqV^A})8-8j1!Ni#zOU=PVUj8t)L`1Rc4MV~i zmmEl;td&)s0yj3H zByM4znO-dN;#OitqsRTQi-X}fNgXlZtZ~y_Brh*N@|k`aim=@nzT4wF`RS)7x=o&+ zYxzc@Scy1hGSgSB8*R5k{ZT(^e$9KaZM$8g)UsE_aHjb_2`wi5CG^z1-X&Nc6~TOfAjEUtTZ` zEn6Mni!?)VO9;qbnwO(VpZ;KN^&pk(4^ zGN@kAdgB2k*=MgilH(go2x=J`<7ZXvE^7UKO(np&wnG%am?M-a?oPH8lbFsP&Nt7! znON$d{cQ36H5JKWV1?q^Yb|!F;Bj_<_3u?`L$-yEirvjln$krl3LZ*<_o+!t$M_;T+$9mW1!YB zN_~*;$9eQ{fOSZKGXcG*28^{{&x^D5h~d8~96HFr`Y zahMmE9m&Yt_Jm#2#LStbE0K)h3QOL@=J& zK3O>zCt4N);{vOr(S0=l7-)$GRE!=l>sgbkcKZ5+3Ou?b)qpv9x#e1xpf*fCJpaVU zpfk(Z%wBP5_B zz7)^^?nstV$oefS%S6b(Eso!(l+>ng`@{iWK<#-1JL9}3RDTwt8OTVg$C;5c&p1I- zjG`OeyQ>SPFh(~7Ou#)|LPoD{I)AJ`i;;7iE`ujMr2Hj5H@)l zclUqA)w{5AHX6U=v z@wQ7gD3}o<*f)0Z$kl1Q?P-Ar&QgJvD%pIH!xHp@|GBXb0>}X>(B0%8HAEKbHW$27K=O>Dofp;($5G6KT&29XzQVNfKs}7T$oq^MPN@XK+Ocxgz#9zrb$`(e zmv(wnrt8CDH;-g|5xgahQ4WNzRX{>3fQ_EXoC6A(n3tRGY(evTGUJd?>}ka)VndI= zMCw^`-l$L<^4YP`qQtb&E3YOZ6WBZ)<&x+p0A1kF;9SV zuy2j+_tM?h2Dwd06fyhKlOSh;3N)THq~xBS&iC*B@Xr{t&r{LRv)}E)lX{e1|C9um zHJ&+hLpX4wPoWr2*V-ZeQ$RR=ABdN=iJ?^Rj&EeynN$pG_Jwbk&!8d`+C|3 zxRR}}XJL!81}4;MMZ8~v@re{U$w)nEY{$E1**$UnL6Ddmz~Xh(>J)d%ors|04O<2s z3(aVz!p3gOS+(yqsCI~NAlpS69u$U!1UMp=XB#?58@}a$-caH%ob3yvgApo-Tb@Av zXbFm#6>j_`HI4letY>GF^`MBrD-* zj6QJBOL1J$S<9AMM0t85K((rbU#g8^DZTwo2YtEn+PjLOilm+G0w`qgOxiqhlte$f z=;~}Y0+wum-#@AggbirLv8QXd>vL%_*9p=~>j*XC;gd~k=4R!4Aq#u#e!mCKoEuAn z?{n|KAV2;oPY))DW1UkQ?Xh&Xdp2xH$&NYti=+zYm$YR(mxnkI$bU@HNO1pT?=;En zL)q@XH1OgX{nt!Knm4IxME?+YxFZ)@marXcrP$w38xqECd2&ICM~_jm+zBIHZ~&?tpJ7e=5(r!pbRnDz-|LsDl?qp9eQQt(8f z-5_G_`|h$oU#9zjk#m%FLeYnK|BRzgS}*8D)w&0;mcY{7b(c$|$_I zKAz0rdv<{D~IM6s5nCl%L@|9EnG#g6Qoj9Lq+-aUl> z_~z~u^BCA5`*e=LU8z}3nSkFH{v{5VrBe9Ifs!#okcVna3SGbEhV8JurTTe?WaZqX zD*DyqZ^*Lf%=Zgrm+A+&kBe~pe;8XzzbA<4Jz(4I6C2|LW)0LDW8U&IZ!F!a!hUh4 zZLLK3(E;qIQJbI+?{1#Gab{NS+4}|6ZG4m8uN=2nt^TO0_(Q2Q&Uvr0<@zN~++_sa zkZIu2d9%~a=BCl0WNNzNGHC~eRW#sSi`XAp- z!8QM&JEo_C8jI>jcrJ}8bsisJ#WARsQIKw#?cl{z7Gm9D1boS>?}-j_nw{Q-F!Sbb9jPq*YmTZ!oqmd z%3V{m51|guo6L~kz~Cw&@vnY>HOn&}&#?c$nPToEeGyGoBO#_^M3or+b*S13TZZEF|#1(E6Sfg(L(;V8C z)HjE59(z`~0r_mR!NSwUig`;s+6(Bur2B)33^#Y5)w<;$0#1vU8vArjT|{m_>)f;Q zzXNdTa_T5flg&PgbZu1wE`E3&3pf;*B>HAdyWT-6+3LLGdlX_Vrb}!W<~OU;h8IgM zE~u+}nxLOh0VS-HlyBgVL`5NE`68wOyKp_EMfXuj_n2T#y950q?ADWcC9l-}xR`M8 z7hvJj^%n&w&t%aM)Q2+iu949mpEZyr<)q%d;j{&A0d_WI-vlef<>QeP-2;y5M>S|C z{^az34xV~t^;s7*WnNdSrkvE)ATFMhfmkM_dN1Cd-Ok^!%{|RxI3OVF^^(bE1oPYC zpN)vk1G%oA5RhP9twCT)O~8aK>o&L^fH%)PZueSH9LrafuoFt4W~QbE$%VRUYUy^J zb*-u4(cLGi)b7w=J&PiM*$D&0m;2ny$IkRzaNLZk?P|$5-3y3LuNgWV9uT(h8qqGd zQ9-agtlP>cHvHZS)^y6Ks%Q6X4tCq|VY+yDro|13M%JBV-!%T>h|3Y+N=mu*YxV-ZIknp%I`ud&HGXY&4`UBD4s>B;i(=9v6iD+Fl>8;Ze>xb z?*LXxPlP^hI=iZXPY~{Mmmk)oyPXrvBkG|L9m_2=@kRw_)tSB2K=k#|@=6QrtV;57 z@HPYg9P`(%(EUZ{h!Tg@c658icSZ-= zVRNW2B~PR8J{oTS!4}P)d_-G=I&^F4=nA7mjETA((gBr9Z&7FiVNUL%$gURFT~I3q9jd z>Jt6qC4UWQ9XMl7GI2jzJp=hDBj|1Mu@;fvkPMY*$=oT>J=e&H$YD`yPKkCy%z2Gb zS2WI(r?T&tu@uM7AY*6f@v~I!u6d1~1(RKTCbXsaw?AnOcqt(FA#O^3x6>!b3t?B7 z2IrMLa~T`;cO(RWdO|q(Z9rJkK`*YP89w#~UTG`b*@XafNJXgT!kneq&f&$5Tnr0x zdrY}>=eagGmqqxk{}_Y3cvZLWwt$M2eU9LYk9b`M@-{`+l`pp)ga?e9)8g0or>n;5 zdgnHeN^_@o1;+RMn%zg?m|$ignt`2$WjJ2s1Eg4im~Vit8v&$5&v4VgbhJ;pbmk5q z*un7{|NO^;s0ervQ^*Z6jY{s(VsH7q2dyMjFm*l~1yKwf{Fh<}B>s~(e_e>6e(bL7 z6el0d>J5+hrhb3Li8Zbc5tt|Hd@aQFgg`vaQXGRvkGk)!bR^Z2bSCD?)z@Wt8ZrpG zTD?B3WsWMmqcJ4BU(qzzVWx;MOxKallX~%Qxf^bQ=nylM#$O&t$509#!0#-GLOUMW zwx@V6y_v#++GS+ zMHLV@A%U>{5aMK2?Yo>(>F=rG2oq!}S45l)tM zsfH5;P-ALLo=s&@%*yf=wx0(a#ZK&!j^oXo3%=;=nMqj|ynaR18kgqp1{lh6c5cN7 z;Wee-+|gYQku)5y6rw^D+1_MZRamwUba437o_ua#Tv5G=E#L`s4mPY!e@EnDP@RG6 zS=JXwHT19sjrG7o8oX;ax6LaaSj&(n(srP|L<>G}7kxe@6mnGSIQj`y;}K(Ea&~u? z?ZNDL#FZvs<0n^d|uDRix8=n?%$x^QS

o=t7K518KH$R&;IZ&SS#j5BsRQrSt($bu$ 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 LS2g#d+0*|3!+i1l diff --git a/docsrc/manual/images/editing-map-connections/open-connection-button.png b/docsrc/manual/images/editing-map-connections/open-connection-button.png new file mode 100644 index 0000000000000000000000000000000000000000..e16007030383a3274a6fc4e3928534d8c581b2f9 GIT binary patch literal 5606 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 mldp}xP1$1D?hLaEN Date: Tue, 20 Aug 2024 15:31:40 -0400 Subject: [PATCH 30/30] Fix 'Dynamic' typo --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62f525078..bfd00cf10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ The **"Breaking Changes"** listed below are changes that have been made in the d ### Changed - Edits to map connections now have Undo/Redo and can be viewed in exported timelapses. - Changes to the "Mirror to Connecting Maps" setting will now be saved between sessions. -- A notice will be displayed when attempting to open the "Dyamic" map, rather than nothing happening. +- A notice will be displayed when attempting to open the "Dynamic" map, rather than nothing happening. - The base game version is now auto-detected if the project name contains only one of "emerald", "firered/leafgreen", or "ruby/sapphire". - It's now possible to cancel quitting if there are unsaved changes in sub-windows.

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%0A5de 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%0AbODA#*g9chZVToNw8X_Oqw zlWS%~-Gp#TBK%?T?z7e8*E_zTOfUqU{s=m?bzLM)aAi-COpVoL5rwaimL?sAw}C#H*!=L)AU; zy+j}M(_3$ePSfvvtKRS!(owV%_bYW4ZKa@5*tgGa>x6F`{cxe#ls2{l+OzPu&E#+M z++^{=7}bSQ+b7sjK*CO1dK@_sNQi#q6n zb+n{(iw(-!a)#qfjuvh*atIK)&CZ>ybVx4n5e8bd!VedsmToV%IQgmANeF+Hi&1B) z6Y+$;=kJd354F9*5&BuyEenC^pHLLnF%ZA(NlAh0It$AlU4kRuPbi7f*&N@2E(!~$ z0`DUwg+EMH{D5kaopIpH{aFdZY>>K+AA*fAm}zah-ci-6kpZEG+Cj1L}OJ=rB9QXPzn%{z_VAAI^?8T!v` zi*QM-Y7ht52XRoA1^+Hw;(*>yvEzvEnCE$Y(`I7pWTQSZO+<+Z^+1%mJneI4i5ZpT z{m|0WEb&|>z{_vlC{(Mxu``8yD57kzYjm=649aPx!!#^YNn;(>=ib)@2&u1M-M8Cd zpN20dR=0c%#hrO|ywhK~Tyj^W%1saqeyaO$g&mNf)SJyaV5WJJ*!vza2fQR>r_#X&Rlt5eGx4OFsvc)TIoVg;Q{(>2dA6=^4|{!iza8;#j_*%S z{&t96skhtyJn44&+L?|i|KC`H*>rkSWZQaOoc;G5+-qtB>b84Y3f|vg_Q(B<0nJ(9 zaX}td$ow)|dQ6Jmf|cL6u^zKO&*QiZc*t}7jq=&|U#Lg=o}={7hi`49eZvnm^NSu7 zY38QWDlbs?zWenM-MMR|<7`uFMf`n|*sIVTci~b(YROyLqxdO?NN1bymKls-@jX-c z%HD!XZs;;Lyo^PxM>U&c+->v;@R&@?$zb$CK|rQ@KNh4_4kSr*-Vu2^Yi^wK>jL=~r+x z*zSv%&B$|qp<@^LLLPN^ym6(s_S>C-2!)mTZTyR@;K{8h0ZQoDN)A`W+sU_l=Nkp! z#bPNT?X7o%=h#H$Ah)@PLN~ltI@NRi%$@ZA+eA zaD_D#U5pv9tW0_48Hy_8Jdj(*_vknxxNjf!iQIojpSdk-OZ+tyv8U$srkoV&4QD?w z1b@tebZ(~^RXJaPMe`bRS8;{QW)urcF%R}@r%W(W!Ss}hke-jJlBWW|V)k`v>@isk7`?Rxx&1knTR+Q}nc`ErDCEU8Wn1~9uyN{5 z9aUGuxd`LGu$1nShF!#6X;AMad#FhDmVzOYd~mkgb|z&!hMK3i)NcInq*6ORLc{F1Sqj3tcYP1IR?MJe7_BK+_*3FzJS+CQI?MHaTj z0;sOnT4sc(mC*Hd<)6O58E8tEhdARcC0w*=oB2}ML5=C&3$|s3e z)ccEM$153HJ+TGJ66u2eq6z6r5{I1>eymY`yw(gTa)XLAa)VbnPFLo{B}A2L97}e# z*dP)+%3m2q#wvo%#%)=JOBg9|szG~EXbdbY#?ngmcz2ei|5bmM2EIu11s&z}IPnY^IlW0B|?1j9+Lb?dygUYX) znX`5!+_mFsKIA-_b6NYO)JcW*8p^%SLN(LWTY@o|Ch5Nxo_e9+IZ<-9D#tLIMWzF+ zZtdoK6V+Lf)+$~LdRC+Vc!*Hqs%uyxmEK(z9=e@$5vC`@Q*C7Twi1EhN*}InU=R0} zogxphtLLjWe3A4XOmS205c>27Yu?@}KzLK3Ci~s70Vk*KUp6zCBJ%V;9lSO(+)(!$ z?a5r`*X#4~ErE&apU#v=YS@=Amn8beI<*DVn-~_S7K{n!9)F6tX~NjFFq~OKJg{jJ zj&%HXFdiwrgPlL#!Kpf*C*0=u`{uXWJ}uj&QEL(O^46hDX?S@jr*fAVgVb=Y)ouiC zT>HB5>-rx$t(D=UH5OB)2S@>E&90X}VL;#w;AOFSCcp##(!#Agb#k*!mte;9CDO91 zI!0%(mG{FGO1M{v7QWllh?3?QP~=f9-bmY@R!hv;Ug zCdo4~fe;>#QxeskI^~qKA9|Z$FF>%#EA9z{H`Y(*kZ8~B;%OuIL&!U<5Pz_f{z0UF zNJ>4?)`8)scMUZ;97;UWh6S?x);(g~|F9~1lEu8=M2Z*pzK$ExZ6XsaL>A5NML1ky zZ%~fOuOm($vKUY+c~MV1BMvDpQh*xx>Rv`-e9F+vynSZtvcQU0$Q+48PkeHyig!j- z@KRV2dEIWo^!AMnK618|J@O&yg9MvEyoP!B>YcNh#E)5QqFo%A30l){IP^2-#r5E- zNB!s43G1cR6FG04#y9D%$F9CZ;`Zj#Av4ZN4-Guhn~aw)*2m|uQRAi{H>cbcxQ803 zR)W5i$0BorX8FEcUM&0=&h3}JJP%D{62d!V#nTM=nu&oJXG@AdnGK3bE9Vn<8GnBB zi{Q#KEVw04LCJTQ93zoScskiim_O2y`}L^*>uqINSeD}OK_X`HMXLqjVri>E>drX| z90M9`hV?HwxpJFAgBF%_Z_}c8LlqBLSq^nDiAOh(#}Ul$@4NtO<(`3t7T5G$UavgWvZWcA^6}}!vAVsKP0us8zC>iE^+OtP}dv;1l3;Sa;K;V9hXCM zXQ|p709}1X0n=Ek9uc3M=KWTIw zu0*r;d_e5J=}?NqT+MY<@o~dvXvoXW3ruY+vzNPvn%0e)Hah5f?dH`a_pdhitoXsS zk4A4i=!3k-IG17|@%S0M0f+rEHw6jv%~IxG;|f|7m;0PoE6xjV`~CZi*cZrTPYm91 zA_56PrxU|R)T`J*|6q_Cjg}vw<(8_Ue>81V39p-F z_l{?xbI%1S#kOK1Pa1@KqV6`};`=ZD_{nxmGI)_ybZnYqE^G`545Am^kHfOm#fLgy zggJ8?nk{95b%+QR8y4bE4A2lHc!lzbcBj#M)$n&3+1)x1+V0~o-IwZeiKEvL?|NUS zOmr3?=W55=-aXQ?9<54+Ad?a$k}|<<<}kyBLVR8rU%fm;>sxO1I(1?s;vZr=m3gkD zMNbbp@RH$!jnK|?M{MoTL~f2qdxj9N7h$JuCjm|Z{%;5gI|qd<#2UPGl{l9De#G3> zLsMPxWwHlB@!HGAUmbU9eou5tX`>&f|I+vUOi3Pm-a7*&dSY2b%pCI8 zi(5THxhDRZWb709;}(!%-7q%mLe((0X7%%k5vuZY<+!D%#lNC;w7fSzPAg?>FTJhY z$WZNivdt64zKv|!!QxMm+3-~n`*(Yfzs9MSQmZ(+^Rn>QRNhNLS@3LPxyl2(1J*~A z(kX`G$wF!eNmAt7ts7gjSyvzDnCil^pLdZ(tB}ENgDvDx-+8^2%jQq(@qZqvcZ#6F zwh0@2B3VdJWkA#|#|4?n&+nIBq~0(Trr>Qcrx4#lRv+wtYS9#1SINfV>iZ)Th} zGgcW<3hmHR_R!z^i>Z0<%o5@(3LSA>bhg_5{lA~lz2SF{c{KXk8N5LeXJKs$X5IMb zuB5Ixuwc*z=R9tN) z6f5wuAE4@PRJxI%M-n7{#oLt9v9(QP znVxxfxy#bYcH~Bduioo<%rA}hEorL^@@@%23YY&Ta>w{2MXT3`V0q%+4a|BDZQOO_ z$xD61f63@>DqY1M)M>sMp7-V9gur7Vqnjdy_d1&BhqnqzMy)0fHcqNKEYR_U*hIc$ zDj}t~gw%YaPL#S#q^8g?c8cUzEPm134ExGbUiNQ`bWIVag3Z~{mg~E}yrP-J(WALm zvJ?9KsBH9@)Y9}>@-qca}fwH;@| zQ>U22Jm21IdqKNKdn#KfwyhKA(U%hnHhRoRH}dJc#%LWGTh#s`-t&U>xm9aM3ntXc z*QMOF*U-9p3$n~(Lx;*~v&@cM%;!4#W>EU{{r6@%WgcA0N0VDW?am-$yZ-$eSt0cU zZM&KSKihd699|W_8YNwcAO#Tz+)2tovD4F7^t>!t&Guc-TEV)UCPrI*abW`HZo^s~ zuD^K=K8LqRUpBTe2(2-8up~V>p?&6jdkrBB-_Uzwde3f$8s`K-ZS{-#Bzeq)7qH*% zww43vF2?a|^)2)(%XUG@E%~5uLg5^`abHT?p91f|wTbI$KgkhvT;D9=7k6W5_kUX% z8a%u@MD>JN=8mO{kTwvAs0K`NwN7keHCc-hMg4`nKH;6?SP$xB#IJhjTg$;kana{&|BeMHd(i<7N zv`I+7@3`uEdYKNJAJft^A_rb!=D1+&SxK+OZ<|bzT=Bqt9ptB`Am3GIl%j*E*;(vnus1yQeiuw0cj^Y%s}eQtBvbcWvh^ zaxp~JvZV_i40h(SY()kwYM?aD-d2Og)L@G}O4Yp%z)FLTk-wzItKc);Vq&ScDEuXjpE`gjkWYh6rtK5sugK1y| zdz6&(^L|BTYwccba4+JqszFEH@3`BEiCA0hRdKLc(~Nm6lPy_0t@D zMpmG0BhU<)NESru-*%2XbGY0Qb2f5Jw9gCj;NEmgCdRkro58WGw%9MKAtZ1R|cU z&yJ73(%YWECgW^zt@R(BP!@|7;x*&&B(jh}7N==z7afe-;7_GL%YM}!-R9Nuk9F>Z z5d!ntw_pC4h;mgPVPoigdFFLI&82gA&g7CFQ6Hmcp2=Kue)e%6g7DFnXo8Cs*YSm& zHl^zuX#;6Bo|BimC0fJ6R6ZL#L;oRd3!<0E^;4dIxJ0Z-=GtzQH1ePEY_iHhRXzCo zQfzTe;oj&%cpqcGm#*xFRO&7mecGZrD;MqqW2YmoirPv9h`pLhi^>{YVoX!SKtZ>N zY9Mf_-=&|+X8+{ylvNK?B;wG78#Tzc-Z$!UBNpBg? zust=9QOM_Ulpu>Tfh>co6=3jNYKT7*cW>KM-(F>uxcP`|$N9jV)&4}A`uyeUsVh8x zP6ZftK_Rf89%NOM`?qLcA=||wUu;;1W*bL}1Qt&ExH4X0r=bfoggCKqE1oU{pRtdgc39zu~-+4Rj#Xn;p9M zj6VX9EkhO(j9Dp_djNFkx=ri2XHL9M+f6R;s$Kudy@ATUEq9JPo5{|789gK$eUlq* zTq7It#n)US+UnAE(6CJ*;K7vqFqre27MhfGk6FvuVPnrMsJxHo-9GGLgKbQZH=XyLBl@;Z zHCNXcW_YzT3!0D<2Q~&iZ&Xc#pO%~vWQut$@zN)W!8N`Q1%a3ijC>nO$3-4JnY>ee z_Qmk;qx`Sg(j>-gImP}#n$ zQn3%#m@~Wup;j%?4bSDx*c++d{Gv3>B`hgvq6_^M0|Mh8?4r8gg2q*y@D4NEpk{Uq z{zTYdjW6dUvZ@{9D>p;c1jaz)sTZ}y4hm#*kGY@w-);$?>fuD`c$r<(*st(ApwfG{ zM7OJZ)!~{dGg+2z%1lZzc9|+kukj&Rz&us6T901j(O!9+`rSG{&B#%@1-JTfK1(Ed zF~xBHhD>{1eddYqPbty&M@1rb#QpE)^a5fn#maItbF)I|rsQ3gx5> zWO#VGaT=%Wpm2sCszLMV`FyIpBo3`Oi>D*&RTzs@wVS0&7T|z{=}O1^P{%t=d-NL8 zJ^z~pK#mAv?p1YPu4I}#@2kBQV9)I7ozu;*ewte<;`CPWmkCP2Yf{S>n z+p>=JGJjp_{Ye(v`yF< zCuSIx%l4^*b~5_s$~P;@L|M2 zD@BBk_-V$x;-9nsgzY?H`Sz77gRN*ozJ7)^mF+N0kQ<&DuH(j2`AWqOQSGFs;who; zoPkqb5p2u--d-6j*${OBmUgPH9JO~7p#=5MHx?6sv(8_H(KDU}>NBKkNA?(3mcxwV zsk-)CVagW+1bk#sKLl2Q-{L#@v)sjLFDlE>ecU&Oelx#j5CmF9ZZ(Gjt?jE3d zE8gX{ycn$#&kG7DwyX1L_9x;?2d^(}*#BIYpK%)kb(EmXbAd8H02WU*Zbh7@UvTWL zpzT1u3M_2*tj~K(^px?`?f1};(Dw+t_U}2Xkfj@Ihsz=9y|3a;(l`0H;w4O@dp#%N z$F#7(jVqHM*jH`atsp_f9yIyew<6(-(v1WvjLZZn)rut5_1qwnPsSSSX6}o*4JHk< zzVw)n{^>I-1-qZA9e?j|4@cKWx83#-;y2==Go`rp0qwJuN{i;!JES9;rRiq#ltxI4 zLiZ@m4`E^P7K|KMgyC(F!X|Bp8@zC;h_Et21G;Z$3B`Ini1%IAb8?>+HEr=Jx(M#P zPZ4cJ4duf3?Rx6ydb_E1(qlNMg(P;aOa{!C_#DRQCnx48@|oQajkl65DK6_%5I2SJ zv`r(p$NDbp-_!~-$s27ixLY{eK-4!sUN`tAbG2XcddQ5f!cB@Prn7u-9jc0Q>P;sZ zS^jtrKkdlN{QFD+`(wM!)2TNq{D`$T>7HuptH>oi=ulz5|5|`)a#?nO`<` zS=Be-nj0sN=sc#r9cd_!rT_umIboo_&$~|sCXAT5QA+PZrq>aqFoHn)*zsxAxL!lw z_!f7KrMY!))cCw9u38|uts>4PaU)P-vp9#=I#G80*Kqgl2KT;5a023w#Q^`6;O5I%{s- z2w$3|B`*a|6M{*C=P{(ySC)VFXrhwtbF+T7(gHgm1(q3zA3t|Ks9}D)`f%E;DAjX4 zTICs#vJzKi5UkRj|59tGqG|=jXP|*%|J?P!+GH&D+34~KjVaLVhpctV7P9+J(X!9Z zIy1!97MSmYeu_q(`Jqh62|!Xn6DNJ^pUkMMQGb9Jh0SvxBS|*Rgxb&0G112Zdc^+; z7u-~SDH{j)5r3y!fCVi^*3(^mOnUy6dK0(-Q>`7ohfq*xyhRclriYT=b|`&v`4*u} zY-Z23T37Nw9}i^<6hn(tY~xRcb_fq3|CG1(Dfq%k7tX5XiGn&Wy<^mb#-oj;GTd-< zc7t<=`qKb8`hY^Ozp{VK-j+Cb&-?R1nE=A(*pe~HA`Z-+4oxXdMWq% zv0r96G@^LvFl%#C*9GKnD-(T>vUv(Fw?yXsL<@D8;1jJ^AXj5k_mVDWJNz=x!h0KD zfijEnA6b4RwH>rENI%RCsGXPblJ_Hyd6n(YTbs%$BPplLHoOWpY-?*|%3dfHlvEm* zfz&;#Jb%(tIo7S*PEwy(tBPq9Q*t&CBH_u{M>m_Zw*&fs#e_vrBop4CC~^U0?c;yK ztpOjeE}ZZo<1Q1*;z&E#X0tiLGkhf#IsS5Wgfn1Xac{tK7BbIys$7$pZVfYpAm{jy!13Do1os5>Bt{l<5*r(ApP$!+6-mL zGFeAh0mpz@zB*3=?x`~?d}Lvr_Poz7f$L-1kgU~K6z#=%yjor{LG6(c8+8$ey92JN zj7eQMvO-f);xrj;Bn8-mmqFXzP?8K0ewvGbIiM9-QD7t2;j|&|NMD(EQfPN{-KRyH z@KguAn$0u*ZfQJOEc&=jKD%lh42MZ%o?LW-&N!R(bHwR;=> zhMpcqx|$3td`g3fx%V|pH(9pA^dPwU*I$2gci-xZ!RRfgG!PGRYk0w)%FG~StKm%= zZ1LEtGU0m&=?lzTK+$5t_P4tU0g%?XR}~N9l)_)~`JOv|`%?Z`W-2Y*P=c__FgehX zi<2r1*Ry*zpJ!cX5yrIwSuwUt1hsl1e`op}{Prt{9rsw(6Sz+L!}>_!Bl)hJfcCG# zl{A~Fw&vqM@~!HB2$T8onXx`^gQr_>OqDP%Lr%$Rgq%pjMv-90bfTgH!}!^0a-d;a zROES+irkhPC5U6UVA%)rq@XQjiuy!2+A8DFxxo>0YDKv!wf!?))w1L=3+0WY+RW;<@xb?GhPW>_@{r13RW{gzlxcZjWVR}P86!mCXPYowi?7|=M5W9cK6ljB2A5o`hg3H$+rB%lT zkNCWEaCQAee53Y&3*aXPU|~6}7Z)O^217jfsDV8Y{4ythZz16Krt3oNVm3pa?sdOr zU`_c)(rxtPpFq^t*Qb&48n}bv>gDB3s2VPRiH^aIjO<@p1=J~b`JKoVhwp4Iy})GL zG!gk|q*1UEdtmpPsrS&GQaZ%(gX3x!3-O2M5vVPw%txi}6yr;nQ7Z);k!~*R`U-!9 zD*fskIhm%XzOcOR6J(t^AEDgW0JP{?h=5x$gC>)Z*$T(}LJ4`lW*IAcQXQFPdg&VF zIw*a1O1wOA`kw zly`vjvj2%E{}raL&93;%nMW^pTYx>~E_$@0=}8dE>yP|SiighQ%9CizeAtO~{Eh1` zCT^g2v-(p0gq8j-U@x8@xOOs!H;H~&&{)JFREa;P`YQC)Q;HI|R7Y-)cNN^~`9E^@ zBLfQS_~=~;Vt#f)D8IN^LD6d3nnuu{~j zUUTv-`xO3LF5QU~m)~V80-t2VXU8BU_SE7M5F&RYF#sk5wQm>&|GL=*g0J?;37ZV* zH1}q1Bush$4_mJ9sFr#i0>QNe)HqO6aWk&w9Qi#WelPTB)uaPBG1VXWP1%#f-O9#dS1@7wP(=3IB%zXrQ_ zU(21szjg&kbHBwUU4C&js#l6kff6n+$ObU^V625VsGot^#NVgv2I0BV`w-bqtV;2z zjGZnK2+2>ixGbw`e5cM-aMRmYQQq<(h!#I`_!L5YtIFrVDwB zpIVzH&pb(;ve>Pxg>2cn6Ecvi;c_9WPeR^TPOop1A}nX`=ayM@5MuF$z`{7RyOFG2 zCp_yCtwqS(>Ef>~Li#^dv8!R(Yu3{@%G7Xd$Rx|e4MKcEQQmF7!45vJ9FUrJ_|+{c=&5YwA+FLLbjR+Rbc4OeCZ|y_fsMN2E?$c|9 z7&?q?%On`I$Bb%wY(RrLu33EnG0-SJ<7CM?oH&2XqkbbrZ1C~I{_ zJdYi9EjL*d_T951h4~|Wl(?j7%O zI@GuHi8Zd%jvOG#PD9-AOZN)81a82?fvH#6eh+DicKqy4UnP{_el#2dx&Ek|BGZTp zs^Q@Bbr3l7Ow`U`nuja$^Lc_ct9l$O+i=NX`ozzfAEGp?7B}3YFbAlrM?Gw4c_Y`E zz4e5aFZYR^ag6FX`jS+n_(Y5Rx145f;FwOHaJ!XoZx3UeNqQoUcV=C%s~gq z^>c$Q2POJ`PS`H7In|6;p5N4{D>etf%fF2oyctei^XZ83!?JyMviJDaCGmzB&$=zM z5gF<4eLJybG@B#92>PUXWR}kCGAL(Wx}U)7sp_Z6*(jwOKMGeF-Bx?v@S77=%ZQdD zxJyw=Z*^1)N^5&O9c-oo@;vA!Os~Z#+WDaam=v+{eU;&~af~TyQ8TN>1mn)XKHS>! z;i{hcYuuX|d3HxunTSTO_2)n`8pmE*NOtx8z9(FM`nck}NSO++a2*1`hkRNd$$mb3 zu2dP;XA|nDVCeAnH3w-mtmErJLP&_~X@T@T!C|`hNcrGT5U?Mdn+75wCW@T!W4EKD zA*lFRk>1;m8dcbt8f7&ky{i`m4Ojl&!2!@tTdq9u3dv;mN7+jSd}5|vwUAFLB!KX! zBQi-|wsy8&?Yvd20`;Yx!vI$hV*Pcfi^7p$#DLgA-VeIi$2Sz!oCm$E!cI*<+z)Is znMudv@>Uk($KXfbvBH!T1FG5YfH0d)S$>SqLyq&a!O9t`;5@@YfK1M2A8Upp=N3hg*Y9ZVjEkfm7YYULL=^iGiv4^QhWEHK?g73)Ox>O zsI~UoX14$9rTl9~{m)BjM7?#WB%%_0bG!m|aY^E{;qMuWz$`%tU^iT2u7LmrL$KzE_ z;ZXVm{EQ#p$oBHQ2U!yUJ-`2x8`fLCkYTgfKLB+z4p~7etG+x<34-J7y`LN8{z}`~ z#Iu#aNV5*)1q`U;8HrPKXpHujcT_qyVdg^(?uy0v@>eQ%;s|eZPws~Am)b^!I5hZJ zmOlX{)PiOnd~M%y{@5hwpk>~g1uZ4z#PfW&yt`iYNK6f6u1cGwp9c=D*O2j8Lve3Q zs$?2!&KcBO`MDPPzURCTMapU&)Qa8FQu~jL%otxk(Ln!0^u~MIFl*!=@^Vm0+s{Im zsuqksAaS+vp_@nM$rAp5{`J9mHzR(iB6!5#QvsN#6Z_Y#nXs+AoIP=rn@)Vj3BTXv zY74b2BwD1?8yExWwcn@z&vco6uv|;C^R(oMeBNdv z#R=^39js1IOMyrs-5_XoVh0y#>tBwa&BITY!A(pGkmqc(^%XM9kv6v$AZLDUOmj+W ziBti^d=HojwHbP~?GD)Ap9~k3y8D=+ssma!-Ybz-u!Npd^VVPlY`!()ofUn+rWVJJ zHAhf>FVU@bP3rw*K?YoZq7Q^tp|bNmxWe?={3!*{_qST+YA^s3!8BodC}5);vJyg# zydxDM>-jt5*RsHE0;gd|{euc-!u`&DT`LX82IJuIpo4#-GE>^+-qVhCjeS)2F(6A> zOv(QNmD`c8{Nkspd~gY)=gr)w<)%LD;=Ldxl4X=iw2J!`m?y9|ewh|M$y6f#D>gi2 zgAH)xO9F7`6!>%6lJN&H9>)`vm0b zlo3#r$(Zn12g(7{=Mt++&);u)m26*?8^j_V>vF^JetMM7hqgfXv$Ywm7O?&ZHoE7{ zy7Ljd;TGO{ihUlVbs*i;;l=<9JT_&##KJHDPD^hA#4FCJst*|yPo$DAR+TOLK{#+| zJ{vrv34zbTGS+Gd1RvrvlSu0cn$6ZBQtN)MQXr_DJU7}R18a75jcsIF!piR>1l}|$ zi*NhTls}$s`rzg9?%}-h5%MLra&muzm|(jGam5OkOWA+IuJK=h(4+Pg^x_h@XzWwA zJB!WR1mz;1SU^U@_KSooza^5jJX}4ytb&KPPUeDE9@)u{I6yW*GQltJ(2 z`;LrUB83IMAlL+z6MVxvP_?*}Lvl${R>6A7&b{q$G@>6sl zPF+j(#Y)Gkx)vml>@c40ps?p-bny1`#kNTN$qf@%Jk5(wu z$FAU&a~v>v>-P^Ozt@qj)MB~_d#KvE#LVzXQON(``oZ|9_Ty?m6=gXaIV@|2m(R@2 zY)~JX#g(78rHP$Nz{I=eM#0DL3hkC?d(h~+(RtdmK8pDTFmfr?v+5C> z_F4RV2)YQ~Z`|H2JF@@xZg7!_{d4|>%GACwe&eY{cm*Q(+v7g1{>0p&BJ{-m27hOr z&!nkAOXpbbL&ji9DY=V?TGdgE`-xwW+fg0jQZc%i$m~wK>vHkyjKt%Ib^zXob6xOk z8~RzW{WS}kf#eM7Z5@W~3m1zCezIc9hYfv4wr=>{iM!CkyY&X= z^^PExUX=cIeeUIsMQvN4HkBt`spO#MQS-hSZU)9`M4GGRF#$(5j@kMfUMOTxVk=zC z$aOB9Bq+~CfdLt}N5Hi4Ig+t%!uOSNEsGS*&p3Qy{976-3oX45bF`U(x$1Fx@<(+( zcyzjdlz7!;g~C~ouZ$ec-3b9Sj%=hjr?r?L-ozoL&>RmG{EqWL2ESM9u7;Uyl^8_) z`jw6@@2(#7Xx#LpL?xOS%zw_TTVk`|9iQ*zZ)dX(N7>_t{=J0U>3=UF?Vr;e2F~7T z?dn}I35+*y`|NqES&8GA!rZCEL;oGn?0)4ty1GSqiNfMCB_Et8^dKjBM#Osghq(PQ z$W3hjP(J|G0d)9{hDy-@zV>7R5Z)O2K4%FYPYRrzr?w`S>g#c;>!4b+))Jki|8r`l z4pX)p0@Lt8G5W0kw9)gGH3`FWR|&EJ$^a(Rx6;HY@R}gO7yS)WxkA>M7HpA!lEx1o zd%oYsjqVaU3X`~}Rh$)gemA_q)Fh7V*ty{WNCkR9GC4s{0s{xyWaybKmW-~Yrwnlh zCaLzP+x8g8nK+E;j~YF7S2dB~iAK~jGd38VeS~lMTJS}9gcB-MT@db{=x3|qwLSOS z=k6~5k#9t(ed1-ymNBm-Rw%HfSdiLuV%I{6w+8vwTw-!a5HialD937ZiD~brz2nmU zfom0}gz^uq(RM{7$P)Wsr-A>Pa{x!X!u`YJlhLJ(D5!-}`(7~61BKL7zPxE;OQqq< z$&-Ya;DS_Lrdi81c|KlhlaXSg9B%%k?az=!F3vsm*u~2~Bx?+kR;_OgG-fL)4dtH! zVzQghnXrJ(dQL#Q%gxv3vr?zsRL$LiPz!GMk%#_&!(DzgEa)~kf!Wl!4)ICy=^UtP z>)sBXN#JtZ3!9+V>%AeD2stkfO+rXU)scs#5>eK|Mk>ntS@FszVfjD702xwe14&F# zap_}09F5qnP>4>S%g*M##ozy#j(DzWX?_`)o9Il0)>x>{9CN7}OM-brm(t}2Nq_sU z(t;n%{~qIM(9{1n=$W1dJ&!gj|3NOhFvd#`i7bC0${e<;cL8+bek^$!h}h0S92dyX ztp?fHEU4tIW2MDrZcyAWKgH~BeAbXQ<8BZ(F*KWC{UiId@UrquLEr0Nr=kqz8-VRn zP7M8bfQH2X4bUjD;exMi9sN5u!^NP;qY!*ml|_Uim2!Lt&fv7v{>(i~i46kjCOB z1m?Sq@9i&Lw%~N!<;zM%MmH7>t2JL*y!m!^YK>{K%16Pt0;weocatIHT|L&5^&-R| zZ7@m=RH1Wg&^i22kYRcG{;}ngww2Pla6QNW$Jl$tHQjaHqM=Dsil`thC<-D9h*G2l zQK& z`L8w07-NnZl`@AH<6qI;Oi~Xjzy3o+&2;VRv=MC8_~u4;%^Tm5S39}qksUi@&n~^E zfvT`auFu`2h_a_`Q4*IKGuf#dFf@WTA_*-)u}5~bqD5Z9Jc{HRB|gB;uD{i;1w5EZ zNdEbW==sum$El!%{p7pMV6sBbpw#oO);puzIv3!0J_5D0{E5}9?+G~7>_aYnBa7fh zf>`(Q-&hAa#pJ5T(866)TlM=mu|3MEssP71_5yP zjDwa8t;wmA%KY&Vkt*Q-EiDAlMjZ6)2;09$U5?@3%sJ)!cGolvWwG~BAL97O;3mZA zODyLzlWJb1U%uscH7#YVTwupbzQVm#3D#eLT_1-oy7NNI|D#FguD!tGOV#$I<9&-j z@Ry5paXJTY^`6UUh2&5C`O@#dI$MWBPGxJ|fBBpa-@W|C3KO`~Egn(m+OX!Eq#GW$ zeDZ!6w2~!qpVWIq=p88Rt|3bUEZ;26pujt7^^4!wb9T^WCA@`guMqD-HI_;I2_-%< z2Ze`-^XE}ayk-;;A2)0eZIkl_&SV z$fc9>9!P7N;!!RY)U}S9uf$!?jhEV05js<`iiPhBhou8Z^H}YDc_hI8rD#|%pz>m5 zh=XRJbWqQ!?hAzc2Lkg$3h%uxU49cTDpbYQgT(AnH^SPs0$A{hg)4_uyuDPtcfqH+ zI;OBC9C%#33_T!QlLI2p{0LmlMl$6ainVrNkA;OUMd5RFRR1}Q?w7Mz9<(|)eDY1C z)R)g6W(75n*O7;e#g4P6e+`7_8whg=mTwjQAR7od^UQw#I*$2nju!tn5(Kfmq{v`#h zgg~X%6W-Lhw>rq9CLvQ3h-N;*{5NGsG1y!RcKn@wzQgq*HP6+oQ_-BJEojqA>IBiF zk+)Az7u0;qQ8C@6D}ADQC6Spbzia8YRBwBu9Wp<;0%cSc1T>og408QrG`+pS?`9&wj#w9Ue(|RB0z9 z3S9^yFPBpi>6JPO_vFxwO%W9l1(qD6`)Z=aJmoS{xTg+YM}dU$6y1=GPRvV^SAD$t zWpfProvT;v&t4Hz>xaIcFfDz!2h?;@>X|-g>Bv^DOWshR;(b3pno|)h?57mXVB9 zR_e<_f9)EImg>2v?JP!T{h|BAxM9o~ zAO}b*m5)m#89MKIhTZLjiW6q~q-1&ZURji_s~nPY0!u~tXdN!%s3Pf~Sv&%|W{WF7 z7Y2n>g)V#gYg9cvLDQ%FdP%)lf~BP8Q`$qeZm-vFY0f9^jsXkoPIt&P-r83_y8s=H z!3%JPPK$4tZvcx8Q$b_%Die}uzP69+6$%2>*Y8-2hB2tEuqU+@fb4q& z1h>^vfW#1hs|!<|D*w~sDgWEzDgLL$1I!T9xfGQPsXPx;x2c)`NU0fjcy=`>@?6nBi?J==YMvtlli_Io_+k*XD!uyut;O#L@GRaA{AzM9wE4~x#`|= znJgm~g_qcij)IEwG9H~n|2lHAAhMn~oB5?s{I+1rex(JC-33sf`dw(BP5)g}@Y|;W%L%MyVDuy@u0xZ(%GR#S0SIopGu8~SBqK;su=RXzpFJl1XV{qOi zn(*NNWPHBLO!2)~yDLdB)6g(o_6iSAq!91MNszA|=%1)UgUG#(lpw8lX=Vk_LXxCe z6*Sj@@3G0B3e-1H0K0yzd;?aQ65_d$i*0+#-k}om&BvgBK`>HlhA|spU?xE zLyjBbv;~_ovvvER^eL2F_|bht0C3Weu@g~-(hUdc5c?D3qnFYRsA z$p@9zi`}-0vH9L(@Vd{f?N82x7@oMawh`eM2%BK7%&_=Ca z0v1h0b%3)f)UqyRLzNp0F)db}4v9E>M>LiAHdcsVMD2(@YM9lfWiPdrhL_caNTqkQ zM|~Q$JIgt7?%^%O)x`&dmz;=aYajNe>aIT;An)tK+6q>&XO8`f^P6X~V@JjGYz9-? zGDM2K{PXGz7umXUszx@@Rvpc2o_w3p|5D!TuX^hgRj>)r7OWqg#j_>-+HT~yE{t&y zIwxOFA(ApF_TTm(O{L>l*Z&mbtnP|GCfLKT#bl#1-w6ek-3V}F-IxD)*Rg&-9AQvH zUs0IsKdVca49DR@_r1%_WajW{2U~{v@Yan^-^W`!z0aK2M_h2d)9ZMZOd70o&E7N7 zWDV#|tYa%`T|`j&$JF++(jqpxfjrZ?^|C2uylfBI9jqUQ&xuKr*3l?1TgW~5bk`$L ze>_ZLh5HeXb&+5MMi;po$@co}&)w`R zA&l;s=X+-8XGQz@hYvrqHjWbU9g%#K_f90LQx+w9mWjGJLHvg~M(pki>rRc?uGLN@ zS@-m%_d5q7BhDn-O%2YruroY1BYDQRF4Bt_75!S~Mo>|)@B#-f?)WJgcJ(>v`YWmMF3i@5nHn3${oV8TLHTI81?{FtzUOK65E$C;1{ zm6?Buq-nz5vP{|3{rmTy9A2{p!2WJ6=2$24?$Y;~YsDupDqYo$4H@dAB@dO4dqhYk z;|=Z6H3@OC2-K!-V#0>%38t#F4rkjS(Z6^4hK00%#5v}cJJQLp?(o^srQr_s2i8CF z4^#D!>DRnYI`&4u>QR79@#h7SLwU?xZ%~JkYw5}8R*>NHoiODS;!^n5+`%d6^vlcq zu5*mbxRcI6hDIPKj+JcyxLDK+zB%=rJFy5T7!lql_`c`mB!Vr_`3r3C59)UIBFP?i z0eQ9La+ycOW7Cmy7I)%;I$dbOZSRAt@dhIfKjal#}1a>Fw^sH&g-L z;apu^)f`9(%J`g?SkI18Blp}Y19u95r-nQpsu*DPJ^wP*)Gk8p7ga7-&lF^Fp zj6xXDAr;e02Uz-OYh1?-o=EImCPeJc6w*)w3yy1r*(Rbzd-x+L?=F#)#_06UM32e% zo!NGiiWzah8Wvp@%_CB-5rx%f+LSft`!%fPpQs&^J80hsaJ1na-v^M_x*zR4A(0K9 zBrUh{o!IK|-rIE294&d5z)ImQ#6j(BGJ0>R`|B<1zcy`FCo-bPXQ;s9r%+KeB<~1jLTduNpV!#ieRQ-9?sH)efruhE_D~g# zaafeWl7KJeJ+{xS$a@7dG7c$Mw7^tIw@ z6?aI&8}*>k8GZk+BF@vFBa!bVCrjT1w#z=GyYrk3JW83?eG%jLglPGL_WS#`@=AL; z7F=~sJ}Dn{nl_x%guqJKX0@``RoH1+<2H{L1u*V{#f}x|WlO-?S|+KQhO3S{TAfi) zX#^mfe<}8TX8i!Oa$>xc5tAwVJVs^W;Bw;vRSan~ntr7CL*m?++5&O=zB}MTGfe7z z%3T`&(kx05t{I6Ii==>ayX*L{q7b^UXKdM^vr5^GV{R%aJ@~hcC8pqK|8XUIGz=XP zwW>#73^%^Ca~%bdEkiNsISxqHv=i-lFLllBiPyMBD7I`+$p@&|1|YDz349ingEx~D zs)jfIw0B&v4}ha{DFBm`mBNzJ_<-N7_sh<3F(0+Pubu@wd2Yeb)k6+Iw({xv{ldQT zLXgU#gdH^QQ^CAQl&87a;%5t2`SE#77FKthKp%1ju|7P3*{aC8^zl_$p=-d3rW~Q@ z@T<;ul7FEy2#g1dmBcfYCNnF9glm!gUgq!;2KBr$JTQ=~#y9I{0V^EPb>0D9ZUobP z0+?l@boE17!`IU@$s)Hr*}Roh#AkVFw@-d9<(_-n=8B{igQmI8KXXLwEqS@FTlR(S z|DCVDwB*rFy6Jsg?r-C@>k2p8E${rR1u^aAWRCg>f}7yHb#|CCSkQw~+UvTFeQM)y z7p$pqT>(1EimM%9I6T9^0y+bb4y5)@y|NT_t%3!fx;5>M`h=Wv^Ic775m!ilh>z7f z9stYD>u&*KDnLbj9s~6f+8$)MlR`b=L$M~w<7h4rmrLVU{zPHJg#0zaw{eT;ooF@0 z$=4Ryh!^BTnzI5Q<6U+1;uHQ=Tt%89CEg2Yn359j+S6u%&Lx%e#iM!#Pf)_rd+*@H z<@o%PMK8^K&2;2#fY!G31kfTlg;a(~f?VkP7^0I~Dq|^F&*B4Zr_L|G`(7i`s*g&$^=dCnrPr z<3qphFS+|4Jc(*YM)-W@ukTvLU61V;cg9%7nJB0fBDKs|^%0M&G{)VZd9lkF&ebWL~wr;jR zhpQ)U-ZvHxNu_7o7j#8?(JXu^G1`@Pb0ZN4QTP*_TR2wJE?HUKVXkZ?gu0|1zDlX5U`T3*pC((bN)p8hXK;#uk^kEg9^a>__gKVV$nNsr24{8*|oF zbQDY_);we2=XcUj^V8y2k|yP@U00Dbjl=_0 zt92rnaW>E!@LXWzr>Ly{v-a|X$npD zI2E^h5jL8#vkOFwt(x;HSbU8D!Sk?N46_{$ESo2Dh6GUwGAd3-;w2^P5*R#0L_ zFzY9rRj3T8=VtG8`n3{90h{o&&|9A$eX+^RmBDdheP`JR)~IWb0Sc8Nqg=Yyyhabl zeBI?r;#7xd7;?AyilQ#}`2tV!Y)UMKLfUKt6RnAIID&WtDuYt|C7$8j@SDLrHNX7Q zKR5$prA0tbndMW<_fQ5{Sd#Kff@;j$RUYP1*n6JNF(-2`8}b5FQzlZtj{jt(0bow^ zcFLy9#DF8FU81|{!-&9@AK@yLYLDd?J(aEeza@u$r-&4VU+Pr(RN2Kp%4Xkv`EhUr zr!iYri_aQO;?~0th$4D=!6F&zhfPEVyx~>QTJ>b0UVM^Y1Py!w`%TwN1p=uZ0R(F) z_FsyF1La7Q@4MT3R~zpc1Neb+Nwc;Kwv@|0x>)&X zu5K%O8LE9!Ppgh*qF#`!pT~hU5Qf@$|JND_F|Y>0Zw(+@;N`tR@;Yj8PsVlh!XHW? zP~Is%M2PMN95tHb13JI&tHy_4>Z4*XxDV%S!-DotV*PkEGeyi;15i3z!jDYZN7qBl z$0M9>-B5fc{>Pi7@?lL+7N`n#4y|?sliZ>$R6b$q{z>dv3w-m{;>pi9e{_diLwUyZ z5bPtYyDiq23NG2a7xycQIJ=GA)Ihw4iWWRY{%*!XHA`1teX8xi&J;t6cLw-s37 zxzoCamE9RVeCUbXy)U>)Z{qhr$tj;eUsoUgTS_>aE)p`Hcfuqs$7lQ68*E;mD{_{Bg16FmcQN8788LKT`Clo;ELZ5^vzMFGTr#53Q!3-Hdj%(S3iL#N$R;4_d~1+&`zi!>_G~+PditoMXmDR1CIhhT19A4 zuxtIzMpu&<CBw18)DiUl#73JvZcX)P+GdWg z&o4hS=3~$I*Kj7eDD0W|tgK>yelpncL_ZnD)oNTxGZ*4{L$=7qVVa0RM(P_D`2F1o z!ER83D(|*&i7#(D2xVRN{) zJDG?zKeK47NZBr|%r66PG03mob`}&`IKSmRM}t5xc!qmbZyycR`<5d+pfIZhYaT}T z9kxE~_wLI79FbuS+zCrDy(GG|2PSD0dMVCiQuEf09%S;7A7!Wgz7ns{ac5`m{1>oO z&q!2*QMfKN*f9Ca$^H=?zZOu@aq7xlXuOsegPzCK>3)|yX%3POU)Y@#J&%6;M;H0O zZCC#l={kJ)zbE_`P}ssoF&-J0=+(i&_w#@-xPf>pmqP&Hj6A}vvP+&IIrim;yUY~j zjoFHxrfa|g_uc1IHcOAH9S9e94GBSU0X=4Myd2;EHK(BU_greqUHEuFZxK$n)|@6} z_wwGcIg!8mzG2{zS_zs;xP3S_`Nl)DfMZdfKW9aSihPuArkHwGnc;#RY?R?!Obkx> zD1`fzWxKpiotSq6*^y_F1PhEh?Tj>Oa2tF7s?%C;;I5+$8k21P1=jPDK1?|Q%xjxJ zV+#D$__@t-H~sVIWE#IODk&=i)e}dZ@c!pb@oVqUtZTopzNC3h(+9um;bF>y2)X1U zvDm{h(!$_3l3w6A4e#-R5=u?0*ie%fNZECx9&x#xKPj;e=ES_nl>}y9!J^>{r)U-} zJ%KTx0UYQy@w?^$HlE0(1}9qYjZcvV)M%f;z{Wjw8Q{?3P^tp>H#;bCE#LsagFZc2%QO?WqcU zYtl25G^_VvVKvJrJjo+c;dr>P=CLvL(ZlK&Q9fEkd}Z`&xYG_*<~*p=s9i?AzHi zObf6BWwM95=g0Jqi~sL^Cz`L$je%LR6Z-qbmLIW~`RTDrxZh(*DAnX`@%cS!n3U`L z$eW97KaMqwc5v~OqyeP1+3kjgJ!n;KIS$a7wFrj1Jf_YvJQ1Iv(-|ve&hbzViYpba zFjR4=={G+BdIvSL1D2{Um9Epja@F4m`#>*-1q^Yd83LX2(HA!19yNreZ($*0v?Id< zv@Qbr7&Dl&9LItUyx`5Sf@Q7BkDsa7&f?T5?`br=O9||S8oTc< z9?Yh7f~FbKP$b?syv1O69GK(2541ypR+flnqz#D>G%3U-DCS^2oiB7pD>{q&S#+<`;vKSFlJAX0wh^#3=Fn#oCepPt_)^?Czb-=--yrny zUthkZrk6dG|G-|t@cMPs!QwuR?s-E}vLE5PakXbbRqlQFtF^XM`JA1`XwH|*O_)2? z%i&lXd{Lg<$Eg#Kcm}cw%2GU*bJOIRMZ3b`FEa()1I9WV0+G{ZwrmNTbh})B-74VN zh%uyo^@ClT9+Id$`ujsenMDJs{o<b`ETUsxl4$%SgRuh%sICLW!_eHUAkZ67lTQ;a8>K=+h zZ2zWjzM~IceiX71pu8NCd@=34{ao>(Bh13>-U1L|8%Pu1*}A=jpOOLG7SqO^KvaMD zZNiS$2~lxM#7=&LE)ryEv+CsAAko4MhG|7+4|5>x7*b61S;mew?|LM zgP4%cL4=@XwGrSQ#aTh@6zw=e`OIju^wpL8DfvYZVQ_n^3D?123!J9 zV2?OJo5(}C>sx%%Iw-&MGdtVS@?=%}0j1*Vjj z`U~-}A@Hwkbrs4!_EHfz+_!C1t40p3cKetU7RpKz%(kM%Q?`#@?O4-25c`s8aa_V% z;WIl*J{{7d0>46C%e~9(+3|05=_zs+1%qZgYn(FntjWz&`RiE&ujVdtZ6WPVx&(t`Q+$;WKl42;*@}JL zS@j^cio@28TEC}U={pd5(%y+5^1tv--!VPsjlCal;5#3g3FBVm){Q8Z@e|95k>mbZ z2TRiGtCFzl%~W*gHr-ty$u|WGz%Q^7hHXr1(<8tDjEV;sVgh|$*+z=? z@EhM<-BTOWt_EU;v(I+6n7xp>2MRO(UB{m|Yr2&v@#e5)%4qv$;EY25vi4M~pfH^S zZ#B6{*t-+xfg|&m-BI+A>P)P7hv4TQkQ`Ty&tj`vh^f{m( zjOL>7*M81-*{>F-$*KRlN9WHW*uKQN&eu47eyIpJcjjLF&LI7qoB;e}sORHpLQSc! z?(h6KYhu%ohrwTs`}X$?E3RGYYZQBBCyv+e$}=HSR`KsIGa*0aQu8}0+O-$+22dudeJVV@?rBi*{`r>dhZ^yUcvQ-mvul!E4Z=_Te3-9N9lre3vz)iJ~A1qBsZQ;Rtw4mw&;Llrn>ZuQJAvNrPTK}&96<7FS< z6!^0QER4GqG&;Q7q%YG^tDt^bv=$}=8}(}By%@XI4(|_B=D7?i1f5&vTbs&o&Tm)5 zNpb%jhRfCe`Q$kpCF^@0t6KxTFaNU$RKukQWrHUbcG8o-GL+%5Yl*BIDxlZRSChE- zV$$z3U5M0=TKU!Qw|+5lCq;P9U20>H8Gix;YUhg~Q!f{u68eMUk8T6+H^#CT9AKU) z1^6C1Nm*jg?VE$8OZmM$mNE$!^91@sRqXcKL;1jzX4JA04^?J=bb^@EA&( zsAn$AC=%<;4jVYv?!)PA&50p9l0yf;CF$=?Z9c=ZBpK)NJ7Xob%)e0Ia6$uLJ!s>s7GhcMZ0?=D4ox)p3c!wC_Ne)-~SxlGRSh z&8!d2ZBnK_?PK&jp-B(gRFY0)D1uSXFTCAvyZSLPKAoiKy*|35TK$~6yoJ$A?_^wR zky3nc6K-f=R8vd$>)}QFTk5$S8xK6_pv8K6Y}&LDjBHSeTL&E7xPLezmaJ5Hw;1BN z`r|%+;^NS|twQ>82gB*{=R4%R#udFUE*!#TtZdL~`))QKz5DX-q}f*j9JYub^sz&0 z=F0}d**W^TjfK5A?RtjCW_rdQsjn5!6soIJ zS9vlBFD0*i3oT8qcY75g^O^l4k1xavE+NSO#ab?4Cuyo`Un5FnA4^WH76?fd=X7{C0xoziz`YAZXdBo_`tF~1LUAqYj9CF;dKzfd=!iyhfsB#*JV z(_V#&iIJ1K(rbs2H;DZhq zp0<+Ij(BYOlmpgoI%9R~vCT2Dqs05nHcK$6`TZ;m=8Mv#;m8~X&U$D3@Lqr$g>%v& zeHVY!xN-oqnm~3J-}a0(z1ZfOa5LjP)jy(tnduU(bel!beu0SbHNCIStXXv8asR}5 z&XY=j(|v$kIs1?D-6urM;nju1y+nqi;2m*@cNYX-dXU|$lagtU#0rY%>LUBngaW46 zJ^L*+eXqn#I7rc9 z*x4wz^WHMKMbTlNFHaH?hm_Yuyv_0e^Eih9MJ z&ukWzic^00A8jHZPxj2XD(X`gMcszrWysq`I09o2eqmRb|K$x<2rBum$BVf$G&B=q z@sk9OQ{FvXqtx)PcbgPt)nsoS7#!RS8s(Aw)qJK7GOAUk#m$G}gw&qDZ>jYWX$g<} zQc3@e8XoIqaXuDO#7$RKLZwa(H$6q);Oa<+vd5nej^TtvNN4tYb|K4h^+u@5GN%VB z$V0VCW`2HgNXVo^5S8`-bMQtN)kWCTP1F_f?f7(##_+1Q(PSNP2bKo}6SczKM)iyr z_gJZlB53GPh=j;1DPjAn4EEucm^drV1gPoUb>BDY6z zDR7Z3R<|CWty~Q7)3N+zLEgN2o$c%vGN;UoaHl)EfVM{~Z{;kTVj=B=6#pqr zTwi&nuV2Ck^ziOmOCz4?u^)ev5!J-Wu~VpN^7`&sE{dP?t2HmyZv%0q)dyF^sOI-z zKbI!=oJ3yMtvzd0O;Yq`mF3Hs4v_5Ze)=4OH^mMS1a%*?AcCgNb#v(pWxwIxLq_u) zulx*A5P;xkk}if_QuJjBZ4GOOm7ZSz1ub(kHGC2q_QGQDjX|c2+rH|@zk~aI_Hu7- z%eX+MAusj$+AmSTL)-sx)2&&gnQ=~W;-?izmds|?>1|S#6&9K2UKR1EtsPYOwEKND z5jy1`O86UN8jZJR-Wl1lJio%^k|;3Q@j$iU8#(x*{Imki!R6VVsJT9!E*|b=-=k{p zpO>XqiAgji&h3L1NUXV11>4^XbLV`E38L7Ym%SwyDBsGZA@T*@>3>m?xm50p^F7!l zt?vGFkh5!NQu}x9_tq3C17eN+%P^d4y_d`J?3&)zj__VDh69IhZ1hb3MY0L;o;WV- zrtlbjuUBeyIWz740iU_j?hE($aCi3wcGT39YVw$=srrc9M81b*_C1Eu$8>Lb^MgYm zxp-xP`E#i*bPCkxp`2rNWzlL8eQ$?>rq=mjb1Ek{S4%tb zC4FS^{j9HQXOS8UTOk!zy^X5P9X&nC7Su(JJhbo>6Y3%;6Ae7JLO|S^r(wCUuq^+8 z{e|h)PHb+t(PXNQY*Ap!w&J%%qh9}IM_r>RCt?8+{`gD7*=@uds%deN;z~}xb?0;i z%hQHiyVM@9lDLBNE%bd7Z>a{&qBZ#fj&+A?OqFu*bu2SJk&saY^4-XHen_yQ_1}*z zJny!$VnmJBO5TJdd7P@)I5jT)(`nUNX1mQ2;^f;Dvw7whWOV6KY#sF>HC*>H%|zkc zy)*nIfeW+mVW?UDq14OLB9IC^8$@MItcENj7yRes$_{@1TqFjm@Rk5%1hxX>I+VOt zv0p|~O`#0Ia3j^Y@Z9ix3dly4>6ypk5NQRwU)@LqRUfMK4DtSiUV{ojDzF|@MdgAJ1M4f)ZmP1wR%%!6!riEf=ujEfLXV-eAe>CF z{GumDGY00+5_LSXdRPPr?PmoEk6B({xwx-bpyc&tj5^U4&U%XWh->s5%FtoMIWu>! zaZMt<8?)b8sK19R9`LDL0=ZRsE|9GZnw? zAB$e`5LDZ6!{2Tyek%#7VLG)xXFDEEQ}DU>W~pmm>>gC&^lfgI4CjYrS@{WPSZs2b zAhM%HRgsA=s9lUwAAdic(c}NRMEZ@=1*~N5{5s-^?@74B zzdGf%PAi!ikw_KknI*HIHSh#cKGrHl$+^jicaKSlAw+pcI7sc~7Rqovdu={>7R$7| zIKnyVzN6l&Q9~~B)|$dJC*F&gz3I_Pm$46VYUv<_3RByf?TJh5v4uQoFov!$`)g3h z)NYC{#Ql2#_VW(Q_iCObCbhKArxb5+l%>e{6b^o|evWM`VVyj<%y7`ym;GpsEWB~l zI9kaj9LclW^OCQ`5z4tuo4PESt;VXT(%N{-KUZTl%;=XOp(G~(265~WE52Q%5psUx z6P|}vgThQBPs@?`DD&QMLuNyMPRIHqmcof%K!~v0qLK+~Wj7cF8?`Jxg1h`rM zGNwNGlKqe8kU-w%H*oWcnoFqRR9q@I?*=n?n<)%DS(QxvwA3s3HnN zKo-hWdFa+SkwfQJB1!3g3G%CO1ygXuCH8Cc+?0^GaE9pJL8?#vQuYK8S_Wy1sb=U< ze?PjVA02&c$kNF>2MGi(v3o90lOSsXaqPKY{!;la1iS3GOl>rQ6F2g!c4+@dW+QZAw zj;PjGW6gg4Jv|V-F;SUy5VU^EYvb+`$*J{@K|Ou@?OeTfs!{pj-X-0~&{|yFlR;P> z|JbgmloZ=h(VZlp*WCgSh^8uB|-nH10Xs*Xx|H_95q+ z`)L1Q_8^-0_ZAa9gf7U;RAP^2$G~O%*6DMR)!G}1Nt37_eEVT6UE;rJ;JR`B@92Zi zBuW0bJHw5Cw+wOXNX;M&2EJ6-4d?3!VbO>i{crK@XN{b8l`nIY*qjxXb4d-i6h+G*_DEY@BMcYujD@dot3f5X7M>V8;VW_HVcZ6>zw`>A@`i8 zso8+T=c%svT;S%XHIRqyN|Jdpj;G&wi%&zpVoy{(#yLXOQt=+e-BQN_~fL0yQ7d>V`_N;r5aF$AMpO29OfaX zk1*L|9oEeyl`SLF3T0L-)oaMUvzy;$;TGcNwvgWyhD*QCpACyvtUn%qwRzg(udMC! z`Gb_$q%K(Rd0dscBRS3aNkbgx{sENU%ynZb&m28avt0M+aNx5smG6hYC{^fVA!$$? zQ^Kk#?r3Mo=u4R^&M>ag!mZH^?W+8;T-(&23KGSG&*5qOpJb1Ss98bwU+HC*M9f77 z9500$-g*WeE3mE&GqjFs97>po#q52rvGtaCcRbfznXTb*`e0ncO${yNHT#*2nb4zJ zCnwVn{SY=Uz;e{(6R=lL9qNTqA=dIicpv0OZEg|VMUo~WS1WUHnB%gajd!FAk2Bm$oQ;#TAmx{z0x;ISr@Ngpw>B-aSLdCqJo>{tp{?0$1?ifl9#Dnk;NTE<(} zD%EHl+s>#iHdo%>Qp`^E6{tHoBS~fsRK=kvM`3ZQB0lj$3M~qMly+Sk;xsQtRTO(s zZ6-uWl^sG2jsV1mTj$HuEXW#YmyE8!*IKDS4V*yly=~pBfVvkdFy(#;BF#G&Yftlx zJbtB655jobiRlJ&@RYM04fguTQC7{wA8PnftG@~4$@m^fdbe4w?Sa%rA*q{aIg)>v zKS4+YpQc>7d6&W*tf<(B16NUmh9~AcB;c&s>{n`dR3DiQVhSPczW@A}`84>dS>f_Q z#G#-Ry}_m9KJ4^PN|nykZZ-08E5Cy386JGWIC0lw?YAu@&!wjKhhjpbeq-4a#r$-e$+WFodb;L;e;j7TNRF+BI>`MO>ebG(QKQ&~f((uE5Q>Y&1c%R<9 zGihzs&w4oV$jpnhm@}Uco6W((lkM#?^%Ft)z~Z%v3llXP?=(>?CR`XcROLgiO{6>- zERadpX(Y0Ebqni05e%!y5}aW1yxo=gjtLGHHmc*|pfTg*+1jBBOY!#A2CC@DJ&&F^nXw~?o$UGipM62oMh9Any2I%Ql0cyPZyIwkr= z9OhJ>_J-z#2kmh!rXFhrbj2ATce*G?e>)F(nRx`q*gegdxd(gQMuTK(YdSqZ^HM{u z#rlJUt}y5RX;;=@pN(s7kB9JuarRuXp39-5A!hr6tC{#scfhXWBb27}SA2Ibw>@mx zi6TG)j;0)5zmGI&Rib>p^$W|&<95bF=Q%=vAMrZ5>`_f16a0tbxo4UVj^@!u`M+@U z1NyZ^5b0RUAvdPzfYa+ee}u3_dx{PZ2Q;^OI+xr_J~9ky7=F zJ=v4smqgjtHThB?YNnXQXO8^D0>LjBdwBH?G5*e+&NoJ9&dVF!cnHk7q!oLbz7du^ z(lW0oQtDoRXBNRwe%jU}kW^KwmBH<&L5h7Fk|c(5rYY*z-Ac6DEZh#Dnf-3bWmJrz zR5i*x=C?82q!e)ZWE2eWAa9?Z91T%8c;ryV^J<@me7hLKRexR&L0IEKBn`HWp@%+N zTSQGyK&l52t4O=9ArBHb-=B2`NB1-NzZYhhvjqEWJBb_b7ZEG9bhe#;N1R)PNLL)F zCJNs)edlW8kswEYt@y}QJZWq0)o}Uhg+;;OgM%#BZ^6q6ZmJc%h^SZC=H6`Glo|Sr zN?5HKpEq&&fa|W&yw>Th*3-=s(9h7D+`-3@#73jUJf&GDD#Wy8`NnSw9|SJn;H#Ej zf8_5)v~wx+?DCVzhTW*u)80k~JssD0=PR(x&p-p0*FH`2ob{B2ydOjGhVO3*=P3bB zNWjpHYeOpzF6s{Htk*jSshyHxrbT&QTqrPt%rFN#^L{y`;XSNJ!^A)~)z&w>M?pbY z$5Yi}{OF3VNwg3`#`PfYt>GSohi5>Gng?3Ka2^dwN;4sQ+R)Q{wjCp9}YT%P7WghZqPaY>jS zE^qB0&})LjiFX@S79vLUL@7G;W>bwT9~{;`Bep9i`)G<_?&1D~0_M=(FJd%BoQn98 z8k@ky_k)FvRjO0R<*r#1NcH{|{b4VkE`5scZ+iy=fge7#CIJ}qFv+h{bo?J(vwC%N z_c4kAloyM^^WwIQ15$_sB)<+v#OlY5SS>pzqY)O767e*u(c$u~ql{4=SOA%-;N9`2E)-a+}QBp_)>0IrO5W+do}S352@!uysmp%U z1AGh(vLC~d$zr_N?JYV~k5Di${MD)j$sHzBxK_SLGZOA!2zz<3*2|4rF+C6)xVOKK zeak$_$Nfp*ms!y^cgoeCCi1%Np6B7d>%~*)2S>@|p6&F=d+v>ytIRj-qmUw)K-hWQ z0V@%iVi}k888S(owfMcE3DqM_!*d*V^G|E{8q|~h!v?wr6DwcfLMx>~ z9*#p<`eMn*VVM8-ox7ulu;nUahmG-ahmL3w2RK}L*+{IjFiBlaoK>`uUyNJQxtd;cH!1ir5|2XSa;hBF{`O zW+^yNqU9?OveA{e+#gqq{4*U4>G@@^^9s~>)Q;Er<#LZt=6P=#I4p$F=LFGEZFO*O zt&0aO-=+JeIq-Afip(V(ZIQ?Px$G=o0V-AlaL519hm2Z*Dj**+8p%mQRzHV>OFR}o zfvNn*C7tg)iUV?VdBX}a0x~|2oxqNXLJjvJkbdL@Zr_AdV1l^p>=l)Dcu<f;bL37Fs5>)tIRBo&S zDLt8aEi|baI2w3_?+Pdt6t9B!g;Ik*W#c0QkDww81XK<3pEgsHex9EKA%ioBR{aRO z2<{A&(59xsxf(nw%Q0bPKJgvh#s$ImBJj8QuAE*^yj8S(TtO3bQFAVgCzw9SgDdW_ z{2R5HX&O7RwChwi#dw$un#FFwr$C$fwafl?mwb-?3^zd^!uioy!q$qOF<^+(Tb*8B z_X&mVl*sz^UH3t%mtlNYI`#%`N}Ima4=8MKQ4!;xy<-_ozq+_w(JY!`otHUDrpt`K zePy*SZ9a7EyRM-!Po#T##Cz>|#U-hBdIw5T@*+^K2MapmOr-!S=joy9{Xs8wvaz;K5x!p1&SwN8S6$#9X z-lDHdo2ESPbYmK&&Z1+}40ymbN`S-DFiy(S^_U-WOMHk%0ZS4&Sm$beW175s|DpdB zMGtZmHF3Ih|J~=X{zqP$A7_}9qh#R{LOIr&|NTCm{gujx4S$ASiO8%e!$_gjeQ=4m{+3`!g0GSY}=S8uY@=z6t zD#nPOlBOHDo-oh)JHo&O!o=@MaD19^^|aY+h?3?)#pz6$R0EJheA$$xNQ}zdv*1W` z3P@~mFH)T%@_gxG%`uuHzd=(CnL?aOpF(Z3el%_?QX%iXphKwy$;O=vz5=Nj)1bm+ z`m*sDsv+NM3j@UVg7$!)xoGg$7y@f>JWU2WYoWXMyC_qka&l@iXjVC9ZOlNcX&+US zbC`p{4ZHnh4zf*$x^SujiDU0xqM|Bt=KtcmqpSeH>!1;1yFXuN1*#z^#Nljsd5lC6 zPhyB-+q1R@(dTDajI|Wh>6IgFcm+azb>>c;TNMdDllsl&{b_;NC9Mz(Zr1wCmL1pV z`qa3()OFMI%~}Fh)f?{cZ{%iWCQ!}QlO~xLn*TI6T*gFC^xi7cv(z#Cn4&`&i-so) zDvn3ECAx3ahipkMxC_;AZc3s*M=sIVo6LM0ffC-tRP4WNrQwH|TJ0^b=Qs;@)8m@z zGIt)LMLrF`Btsyoy{PFL&ombY-PJ&m|EB`coA@m zVX!87@7BhyqqEP*fE1CWJAs)bhWhJ40=nf&Ej$Y(p9yvtDb^p;#mNK%t<@MSa zEqhA3gHhC${1z8IYTHl4>sDXxQ(7Pf(Pet`^CrjwoF`cTu^8+$s`nnp(rCKk!Lo@s zGizK+NrOl`iw{%H@XJm*Ngc1{>K;9E`zA&0J|flR{%RB1 zpLg$%{!Acb&6;!OIQ}#1*k)&&UFSrbqQ18HkctrRthN6yl;VuMaqz1m+WSMX-0d5n z*n+8h%b7qktzbYM0(mve z#L4$rN!2HHT16Xz$M_;UuUmIN%&qT}k?_^Y*m31PeZS zXr27&n2cm=ICw{^?!Bv5T$kt-ON!T{aWMpPZyE!apV#KP*zp*)!{0!BK*VeMcdg4s}Bam|adiaa?9s>~Pcj z*GKkmjkCznRv$2_6tX#HTg4+JG?n>Lpx@zN%ha*Y&{THQ%E;ES%;VQ;xN7uOBMI(8 zU2%Xjjg*Q-=c=xVlW{i{Rgg)d*&nDVoYo%I=+8ItsPL~e5I&l4<|$yjF!aTkhfC*| zOXu16$oohXIk4F$!r$M*T$)#AaeRUu9%ITEhD99IK1dKc8A%S14CiQ}Z}igiKkF^+ zH>$6TpBdVAD%vCJ4nJZ(F+k%Sky1L~izR-k{y^qk>fQaGsyxieG3kTxWQ#XUaoLDg zrLMAz^9;vw;=V7iJ#}l``cAGIXf1r=da+Wx^VQRh20p(4@t1ZXZKu`7I#Wz>#8VI0yDI^lF1RioC)PuUyg}9GzJg zpeDur=@CE>s46$Rc9_M%>AKDk0QJo>{IZb*rjo2^IMjFlG48YlCBb^z-HXwvu??9f5b;P};iaCJu74xY2 zmc5a(+#i3^%`-u)Ox@}jmfod#GkN@NXt zW(1bUqdlH+n-nMeJd)}-!^hLtGsd1UhOb%*r#DzVgi=h|1TLjd`%<`UphUZce< zDz361)j=BxUFy2C51EvNvSyz8Ub)1<|Ew_CAeLKh1DxbBzQm2K zNW%vSDc?xvx4z!wy_esE&__&Vbh@(H@w%ok^bKuERz7wA*uDfqSXaE*0ItqIcXut1 z6Zg?_-b~KgKpu^CQTJo{J&j=lFlz+hm3gkbp!o7Yorsh}+{EH)~XDcM>Hs$mZ`~I}+syh$e`^-avv;>965vyuq z|2bK@UsZm(z_ItWwDg_>*c=zmEv>=tv+(6kCQ7Q6fy8$^pI~l22k4JbIN%@0uHSz$ z1diW0F1EP#H{>jc#t)2T2asWFvWmUdBHuz~;m`q^27(~rD9A_(7NNZI!5Vd~qL%3~ zDFuTd6EcA8n`f|R=2N{SMeMfB$fmfz$6nzj=Xu0kR9KTn1$-D9+#vjI`Gf+h`|vxd z`|u#gN)RNgF9)xaN*o5e4(lnu4`$;|yDmSr&%IGFgypc(+xfa{$~Rs!({_7_Ju&C) zPlR|;2ki1cPN(8borL_yUx<8)7SasXZ5;?g;QQ+YPZUJq9zhEqMLBKbTY#70YH|~L zl^^x$DQ{U?90~`n?HKws7Xo`kz4U6Zm(FXi$*u&<8uB%#cP^W~cvTZ$u%pu9p~BiL z^#gj`eIJBRP9YO!S(w*(6i-@e1#*Y`>CtT9C4@C zK5QJMXjTb+LHG3_&ZEKcdm6QATuqqh5%@{U(y?38v5V0@Wre~fNf9h*oIW(pV%U=P zF@i8VFgufg3ipSZp`=|1ztl81vT`NBYmxQbnHWL#M@0=Esz)VuV||2W7tSD!%B?I? zT>`k{u@7p|lPCW3k@?hKcxu@Y%k^H-^c;c0AqL6z@J5fRto#(s|3KgQ5oj`Y>qRC= z2vL?O`N0i6x7+Rv|+lRbDI z9CBzEDx?PF!il)Fe2h)0K&PA&bPO-pMZ620ae%dV7>+Ag$mfolC1AXg;16;qdys>Q zr0+thghP`xDNURnpbWd^4`S*wuJ!qctz8lNiA;-aw7wq+4nGc(t1>9D6uv=fRnWHh z+&}l9(ZzmHSo#h&S{0+66Z*ufHePwJx5$wb`?|9@eOB?F$9d7tt(D;EJ=E^85CJsn zI#2F?Bve~+ED_`}BzEH5h#}u>M$NH%x zwS;|iv&GB_d{$tDr`9WRuIi!``8}Q=Q$@Nx@eAQ!eU8a4l>1iE-=J1?!)eCRZD28* z&At_7eJr6Ddt0cIp-*#9xO6^e^9N0ASB3QEttAJJuo;8U`}v-XILu3S6b`!;@gm&! zQ*1c6^Ll88r3aWKY7uhXyI=15*z<>N$Ok6n2s~ku?YJjuNl9|Q?vLX-{%K(KaJTB* zcGEm%dg{q-+}$MAxm|VcKD!?B>{++G`*S(_xw>NBvkOIdsd)7mJ4m^IJ1qvp+F83; z{RXq#$rH&j;`8~^$39VM2Z3a3Z#8s;Ohd8RM?7BGuHQkf^Mu(R{uIMpd4d#6P+H@1 z^^i?dA@PLS_f>@1^^90P5)#mgLGu6o{3CmWPV=-=mJhV|0=avgc_@uLydF^mi@jUB zX1O>wwN_F+{@@w(0n~HmIxrfPpd7`BSGacTTbCKMa2kDHd(avc1;R(iK0lQExFNLQ z*mh--6Z&cZVrjwU$(3ryB67B2$YlqdDdODrnX~w3zP7RYR5QDBEs;r9{6tugErKsB zwXzkosqKLp`|-(boLZEs`&Gj8IEQ)S-xO2`i( z^acK)hOJC)mU;4U@XtmIe0wjH!m6o!a=|#+4t|r!T6Co$__|pC=9b5-Cr6Y=s6M)I z!19_!DEN^hQhQ9UKZ=}aNV(cBk;hZ+#boI4V7$TA_Y?T~hD-}zL5yRHpsM4U$t32A z713$jer!#({z=BK>-Tkf z<6ne(Hr8rH^u%{Iyh-lJpmxAqypvKtR*C*USiw2_q{KLs9w-R<4a|gkh`>g4gh`M& zA*Gig>KQG&$Rk~mNDm-oCiX$bhy&``7WmNYv0u^X9l`&(0F0!ReQnzS1yX%-G7IZ> z5iz6~xLs!1x5mp)0+8P0J^q~_GG<{S?k4Rwq%lOx+L`;}&&BNKuU6cD~D zcJprlJ!c+YSL1@@uh|$h63rod`vAsAVv6-1NL0m#0{x#M#F;=e)Gwb?Hojm1W%I4< zXYTZTrhYjED4nSoIJI2Xf*58r*PV_)a`N-E!+Qx0h~g|leJg+0m~29=M8J3R5zc8n=}G`yo}9 zQoaoN40tKBs9oUd2e#!odmG{grv7@ljtj+X>%C7jc9 z;~YW7XSU2E!wQ6FwCSAHd4aLJYxKN411>`LpmM8xdE`F{Z(I2Q6BKdN@Yq@#8$P_y^UQj@kHn$x ztJe+Rh%*n}toSf_LZwA+aZO+R`qO~L?}3PBiKi+`MwM1t=j~^$mEGicBLZ|2OJ_pD z{i-q;{Ew>TU8*=3?qcKF=LyJAhibx;bs+OvVf9SPZ)Cq))bx2QT>QkNI0?hmAM*kw zEdNG*LLpdop@tB=bhQZZCzAn>*?sc;L*r+U&!H4KI#O^qtNZ8VbIBM`#>gJ$Ugb)C zELje;JDJfHEOgbZg=+)DfI{#me(VJ02gG^MhDG7XDWkKfdWEzZdo zpeKMf2@LjzxBtyAK$!U(H>dusjlG<2Y%rfL2@r-h4^5n4c;{{OtkYRO24Q-z<(iQq z4{Eq2ilO8*GYKfLQ#I@*m14UTaqqo#4y?JqYX{Tuqg8Mwbrw2pU;rLf1pkry9|Zk=Oz97*>K4Hc&d-g;|DHK z;kvWx4@%SC&Ajjb=E8UPf!70Ru4?^_Bb7FlP`Q`tryN|+GYiJ{QX*Y`u}z z(!~JI(f)Al)QyA=M`gw`YBzfUjj zUfmfFIOp}QeF`^F&0ayf!L-?<5YKqGDs#e=KVsX^{U?dzoDRcxB>NJg|B^ANH=a+> zO0BnWxk(-~+#C=miJz<4ZP!)Ds!zXO=9@}ZQBy{ij=eq8$C3?*S6F&H3NrX4UIB8^o7cbnZ{80mN%{*dp|Y zEx&_yn?rxFi~X!QkU(}p>EIE>loySEeT2ja9x(?5#j`ewb%!5`J*|1mB$PBqNPktR zUKaZzoUPoW-NV_Vkr{x!p0SI|l|64AdUvTgQGs!uNaFZsr~BoTf$xV^`|YXEt$$`{ z$m8v1WUm5!S}$OE>3ZSO?1s82%1lp^V=l0g9M*g9;=pfj!x>R|!7h7N^Zk{514(4h zA}fQYKR51(8N#=+=>iPjEx6Au2`(t1YcQqcdmXDKWM*iybV&Gb<#C7G6sg_>mjZOU(#X0{D%=L6I|Wv+u()7$oW1MaX> za_hb0!{lL>ub@r3{Gz5Ei(>?U!u`$a&VF zGbOs|9n<AMDwp|TaAug^_!U$% z3iWlsnoR7dpvOlVw#|rt82{hobCYQNWbgHi^!SiiGv@C?pFe*5QGUDP$?{zj6O;EP zOCIP}k@D|PI(FunnnM0l3m)nC8&mSC^q5+bM)7<|cR*o3sB}Bb7Op|*Nj8`PA!zet z*(Gq|v>XG1^Z zIgKRMET@9H%+0sw-|Az}r>?|*J6BZ3$lCxH*fta_;y?@J7XiO*9Moau=w{6_kTjlX zWZ1M^V$TRC%hPu##t%~sG-x^9y`9KfS9QsZ0V(hmRgqs=qE^>&X zCeR0d*Fg5G_(R^tpct7RILPTdJT#bRGBV2JE9>G@=*3uB;g>$k6Mx1|yJ1tP_Hx$d zi{t>^{hzFvxxP6nb=qRUrOfX?TlExC<(cTn&1{_BU)o%K(X18s`_Vp|7tRtDqH7KP z{ds0(8yEP30JJmr!c(HGrcP77fux}bL-8OPil(_y6+h>M;eb`TbJk|D|jlsWo@& zSshK^y&mA|Y83Fmns%;~^w+1Vptx|~9LLyMi)WwhjCo|JRYw)je(X+%F@9CQKhlG1 zt{||1JR^xJ_(nokbW`&BhaN1+>0{33m;Y+sD(QJ-c3aPh*uyElyb*Nkl)b_Qlbec= z{U4OD$9<-fuN@N4tHkP9J>YwfnKpsobMLOiyJa(nZ{iY49yg|BC~y^T{9IEgQHt}T z;R(Lxk(U&c;0s)N#@;*;mrft%g@ndye%JT+vS950So_T;2Z$~9(mu=x%;F~Exfs6rsNOMdzYf%`uCi0iSzdT=l zdb}>{gt}ozRySS*Crt_Zc@tb5n|D9BEDZKVG}>(8?oMGS$LT#b7i-{E1018;lX}hD zkO`oEnm{*Zq(7lrI?g!3}f-Bc&+8>@-Gb%1qxHL zN&lE*)A?nm#0J8BZ4_tBsnO)kzyOuy(kV9ON`jhzF-c(Ln1dr^c?npLV_K1(66v%3 z{V^9EnnLP@a4{h+@6>M!djLV_4|D(Nb%Di?cc-eTM;Z$dSM?L0zs2dFAD?*eAg$WG zjij+-ZaK1tu~$-1vLPa3)^_(qMb`z^V=Uwc$IDl_WtA7nR$V;E44o8J5&PJjf_Y;H z|K$x`a;k~p9brU0&Xg?fwXBTQcGLEj^EogSXBn42jh@o+L;to=^8qLFL+IxrTit(psHTo7GD5@P@Wv_p zkS)UKjb0DJc)xMlur>1l>NoFKsIOj~53f@@rUx}caX|mG8jlVypmoiKe^_kWkB^nb z$Hc*QVw|&So0zqacdqU1FcAPh?En>vRrjohy4mD|?kQd5)9V7jgi}A}m5S!tErO&a z>Noog;3-?$>D8oj^ssBy;)IAaIu^1jMS$1hi67`HA3Gb{Hs^Aft*)-_99TJe6RaI_ z*04L>eFzlOYjXi<`5_>co%T!mE8x&6$x&~~ESm=N`S!FpJ!*hlK`lec1r;}_AIRbQ zD6O}Cx}_tv$m4GrnS2^;5%w8PwtKzJ7mVD!*%rQY&YneLHKKc&zS8VXY(4(W_E+Aq>Xz-1n2r)Z8Sa$G>o_g&uW=!FWf2CNkSx8Xb?|s5AB_(8;JT5N7vhGRCvE;4MG@l@;c$Fz~yXLMByVc!2^`i}8 zSz{*+g7$03=!UGk+^0h=+vIbt@ija47hY0xo?x^p^$8RXrce9%LM62qe1UA*6(y+N z_3WR+7fvg?&D_YZC~*7YI(?l?SN`1Rdp?>}czk?)UGZu{pTXSmkD+v~D2jaJBR$mw z>nH4jGse5@14^O{0R~z|r5UiLd;BNp&i}z;y3|*Uaezd}2_F@`a-o~ujCT@`=h8G~ zGAR!j?%TA1OW(p))B^gaFE>vKInea7x>U-q?aY2AGGLdv0|QO|!4D_Uozx`#zaCtx z7VzJinWx8g>RzlOnuU8+QXfyl&C+cj#EeR26p33^%fq*B1gDCZ_CU~yYgaE{yq!;@ zOk?b#ESnP~=lU!nTby+>ZRzTGit_RK_fVhv4ugP-chODVYXSdU6Zr>if4p*p?Y)M$ zz~TgjM=mPd|39?d2P-q6YDIYI4yIl>JeY%0I9xfhXy*1w!QzmTz_~?9wm_Pt+`E^C zcO?>(D*RTD?q@8i3G=9R(6Ns+2k!FZ@gdd~vtQDcDoo{eJ-)LoyDz0ysO1ao5~>Hj zwH&T%5XM_YRV9wot`redT!8*!+Due!3SBPF?h5C2Z zcUR}l^2!ZoXS*}WHuz4pR@UzlJj?rMTY8^MWe#i@tNbj`*?1*ID5vps56tB-w~|tP zlFCu%=BQ@tp?(A6IdVyR1H@d@x%FF&?;0fZsxDsu*-GxM)Tb)9rJx3a@T{`ZGam$v z)jRl0!|^9An<=XI%>01AW{Cch%FX$2MAC6Oq>?J0B1hZ_S6$y7a&5a~U}-wfn7vSI z{s6P_OZ}(9VIKhCSW3G5TS?n);XjAaYZ{X`m~a}zxHy3q1cgng^=)BU7j0hp%oL10 zK)rNoiuqf)*VFB?%$Vin>@sTVJt&kxeW)zm!yIw)kI000|0*-a^(H0tGrX<{m#^N; zcmA5^JbAN%Fdqr>T)GteIvE}+yW*J+)C&8JqG&*@%ridv+v-26hPKJfE1-oyk^KKe zYi@A%E%X<*a2i}!74ZCxFzK}E%$m%ozo|=?spjdo3$*Z+q3_nc^Ifh_rG)0m5Tbc7 zEiRJrA6k}LH1osSC@F`7=$qsA)(O2o%QSXVdajmry|OUg3u8Dk;2*~7EnC9;P$=>& zHQHkjfwh~uu+Wr%aR2jj^!5|+P$p8Q`I#S!1!FA-p3Uw5 z=D1!Xb?NQ{4Xtt>0JE9k{1UM|LoijsVEwdws5VCJZRM9jG%c}0u0QMIcFYz)nxkby zpb<{li--I~nu!$J?H<-2^dvP`s z>I>iyokQN17h2rRX2)7Gs+~QHPu$#oz1B&kzTTuXC~AS%_(y^nrKuOAqU|yUxDFFs z#~P4{9xbup{h~eg`L%N@-c9H(5z4?e{s4sAx?Ta+o8W<^FM@JX_id z9b#$xWFtYkZK^0yuI1xW?1bqr&rj*2xncGX`MOd66ce}7l-$`x+N7Lx?kaz{U#Zg| z#D_Y6x|X|TU!g%cIf%cbruB7~xQ>!2;HKW2n))v>0&ptYgM=mn55I2kWIX~RrnSHt zHW++P+@{CyB=o8s<`X)&N`3_u?0V-QC4Qlcgcgofmw3org9itGeAnKi;`K~>iJzNs zih8qU>dN0FQ{Rh-%~#Q!jh?3`Lj~E_rHpj)XQd{hmG*$IyUsJ#eJv3VmxOZ`pY+LH zgOMahh1$14VVjR%N%_f@CXDL7^&1-FLk`v_OeORd`5$R4k^CB+lEXRv`qgR9olfbW z2d_`|n7PlqqfMPM?ASXqBp~>9AOwjDKIEqOUrPFm&W`c^-#7&f(4-qDa{I z(rGCyyXcVce40<{w&w6&5@(UI{Dgc0(=`MEIea33e$eeh_4TN~aUVTwqG(O!g!P+< zFhQXM+x+ZsarG1J(5nyPnmXd6_2Cltoa(-UB}_3T-z+JeFJfmGXYB_NPtez$1rNR= zOR%!pRA+7`NRZpuz)fNA6B1{XL4~eB_N+p@$yWjlpM}J-5qOW%6EL&^h+zKb{uM>N zsq|?}{N$En=3OV~V*wK_s*JMSCQ~U4?3q7daUaAFSX$DM@22oJbr!+SbnL3fhk6k5 zSwY8;^?EQ?&n}zLryAO%!8{!X(gIu~*9V5*)gPFd@CNW_{cDi@`nN!6dkg^v?k13p zXRt_Tf%T2x?zWjGZ)BgG9_HAcm8+Gv4~SqVMAeRfd<>qkK*$a0l7t9yl+JAT+qa>; znS4K^>BGlJ*B_{`A)#BC+v!$<@DM{^x4fbK{4zq6#9wd?vVEK-^J=VyeS`2yb(=Mb z!vnBU%<2^navncCa#OgQCL_%`!vkcpk)nJ1JR1Vp3>|jg1=g$QH^wuppN^C$i%z*_ zRQ`OcBii?%nJ9j7Qk0W@46*;A%;of-JP0UE30cv6`}}ug(7IZB8(gGxVQ$v~SyaCH z{d?KeTD&tTSm>jWsgG~DOFL&3&)pX0|dJT)Uzg^H2DS z_YXp|-S$LsxSd<~X=KH?YKwy!!2a}^Wbw9FxC*c*I%)fyo9IlK+0U{oUe9X6H*OF7 zyiyq-@ke_?AAafmmHYTeQ(KjqsqxgSoXum1X@Bh4APmvY4i8+3GP&jWg%r5GW^dG&DpwIL$R>`N7wl za9*&ZSiJIPWgG+6POgzIq}NH^JWAUnfoRjl5bU~-M0P6XAl?8|;^qV&aSaxHKA0&>4e+DwOwWI8kR)JS z>;F+ywSo3pHB&n$`=ABTqTCqNO?p(a(EZZ)UyqXoa2YMRA&t8&809?i*Gz;h%-E45 z+@}%PhH`W;0*@3uEG5CZW5q-=eX?x7STZ@$%xeaG7%R@&cx=SjMWKZQ0;T(2$64&U zSgEF=OEw4-8Ddp2qgf`s!&W7SGW?5nA_r~_$EhyU%-rVqh9BAwkCtzrNM&6ir7?JJ z8Z7E#i6V8zcQUd`GP(y|y7s=YGpRH&?=jBCN*w&2AFSu1WH08Ho}br~k8Ik#)l6niPdBBafU?;T*xxJ}sgG$a zO6dC_GH3o;UTE-9$oBUpYMa1;)*nS&ece*|`fVvK!TNIMw1>kPX~VFLnRlV%Rzm!4 zu`!Nlj!whXoX&$x&DBmWTqS%0qNVnm<0lVuk`%xPJyuU1>72IhL@mhO)dtoNQO@HU zCs*6iiPE7D3p|^a7k3Lz`1NlCU4sT~PG|8zdrFbZnS0YKqr6#TCDIz!)b00H)?T+? zM~kzm7|%Z;(k_Z6C5717Y!6-=vtKY#-|88YOC=EFM(-E4&%}wBNkG*%PBTWo75{Bs+uH(RQp_+#9Y`3DjS)u?-hPShVm-ou#ib^B zD;iIkNlu%kBkwaDXIEUT(n^G-;HsMAoL{`udQzS9V#wJE^C%6?s$Ec>dJc&*lB#bj zWsEaEBqk|~Inkv*I&|vENYY!TTaOdWgf^vRSS3lDmY|_tXY@jqkl(vsba9m(TF@*ue#Nkb5y%1Vo!dV)}pO;-q~!LNr?Y*E6Z_S6 zLL<>*D;IZlUfjt?y{V^|=>{Ub%OYy7503(n-06(K%>O`g!_=JUx<)CD9LzWC?6Os? z{Z`5&D6du{E~O%t`Y&QgSAdr9o^OnR%f2l^wbF%Zz(!W3Z5R zJp?t{G?Tp`AzoJLwDCoe@=3I$Y%JUbLSe7| z2|AMT)r(YuuHFd8b-HtxION1xG*oLgmEIk7nwydOl(Z=|pJ8h&HMZeO`uq%8@g#{W z{!7*925V8Z*SeiywNk;Ardr|(E{uQY2$UqBkr7PK%EJDl14y=?E3uoLNYVi)NyqnI z?5bJVsvaT?kYzI;jzLM@bu&e<`6(dn5~YtxIIVnRt`E`8Vn3d3qDn?lo;z>fGJSUt z>gPV}0*{$F%~PpDknCMyp?@v-f1orKXaJ+LX$@r!AIJy{0N*A!X?mgi`2%_kziTZu zrnc!fg~;xn)KezX6lglT%bnR4aEkMn`BN|8tG45L-4tY@z4syL4v%l(IEh023mo+I z)W$Dwe>$Hz0&SY763-LdA;N?)3XJRp#Qwt#2uKykXWQBJ7}H$JF(falY~^>3AwQW} zo%d^abU5>X>tNQ27jai5@qR%uN6w5Y|2ho!T2X=+36j^VuZGo?M?&(VdFD zWkG91H3Qd%3CyNHXv2iP{$TXHb6M;Ut4(N#$^91;Y~-@`OcbGZ>jYIbX4PzA)og>- zp#0-6K_=PeFb{D?`hL3>!|Ze3tnbGzQg6qyeLA%Wle{coFR1GN3enN)mgxNq_;+LT z0xdsmu!n9j$zCgx%u)byDM{vMaW|{SW9a7r0R}0^=+Nfsh zzv%s!mwP|?o0f0LB)hhbx84Uu1v|cGbJqP2OP2#ZH~C%q_dn-?@I3RH^Fa&8t6XfG z1$KV9*jm05!sMH>eE8yDWZKBlA(~xJiAITugwiExkh+Vlc%i*PyEhv*Y|vlx<23Wp zzt+S#1>Q}XDzT$i+NpUxyEiPq!9LpohD5ujcEio8!dp$lOWb{>x)*e6^Jzo&2K22h zk$+EJ_YFKdiAL?uo*8(%vV-ezX;`Z$;`8*Wh{oO)Ej&L*x`=7^-e2$0$x@idL0pkm z>=szseiL_Cz+YK{6Qt|mL-ce#NKR5#yE={7ADp{QtOlcOyh3eS+&D5n&VM-@WJq z7?^dK0$Nm!(Q}K~HN54%E*6PfSnmJ%hFS1ch7}sn!d%IX2G9Th7vy#=9Xj3K-FVJ}c}N#auA=(z^&| zbI%*c?oOlMG9J6Be!Rp#htneIuKrIsHilKA*8!~t=57Uu*F&C__v<%<&W##|Zz}3r z3?9!zmNf3Yjjd012zP4?5oI1Ds4L11d2GtO>OE^ooAjY|e+`nS(!ln$%eo=Cfzhbe z-&1o94r8Gk-PgF`9W>m%DOcR)L)XAu*ONB&I=+6!NWsaH!bD;%l@{Tn3RG4G5?u>3 z$sAc?E@Eq{W9pP!+U#3H7A8o2Q2?P@o7ng3BN!vShkE05Q_&Kej=3TJv(nKaH8-c@ z%fsl8hk)mh;;>}U_iG(6l~XbU(%B9L)y9RJ_YB9`tm`JuVQ2Om$=t#o97}ocgHWnd zf08a*!ZTe`uc7#-Ha5_?PcWI6<2TPEt70DPY*4A}{Bawi0+N>&O@j{_o1c`3tmYUEzn=V{2Q`0#LDMZS~$f{6HqFB9+b|l`@=; z`Vlzg06V0zf@R(`M`-kE#@?*m(<~z@~8bxp=XC(HXj(aTyt{Z$B|D9}QTHCn`GI46;YHC+mt2QhL##}z(YNtf! zBUg`XDT#g-$SH1WqU4mAm@j5h1931!GWE{yM>w>6Rb3n)fXc|fc2m>X1Iq<6@meXO zoxm!pFjbO^Heb*0=3ukmK+e@l=4W5$$_#zu)6XE}l$1VMxfDS<3+6|c8k}*A$ywv$ zHu7#6n*RUuDcyfoqUAo_Y0$BjTuLocnco-pQf^K zkb{5KSbkj4e0uIknJVxc`PT!eY_4n1sbQGEAl{|FARet9F{x~oB4zoK;kO}uAW~7m z+w1<0`wiu95XTX7*2f%#nq%W~trDaboEvx6M$~X{Ko!hYTZzVPc{Di81vPQ>6l8vX zCbz{qMJ{TG(`vgVTs1bQN|}mi%SJ%?5S<9I@#_2}5?*94h!(-7v&PU5-*+o$0z;pG zq&OiqKG-AY{!oZ(LB~#??%SzqwbN%`p!HGk%|%l!XSA zvFrGl*Mk<6+TLvtEC$xL;oMC_M-6)fCTR+st^mW(KHim&a3J{7X2?|4%wx^deHRCf(} z_p9`GF;45FJ(vWTP^$>3e2O7AcoOvMakU6R}0?_80J5T2FmS=}QS>6Yg$i%5U zH!PpX_qx`z&bm})OkYB;L++GL=SS(h4g;M8r!NvcOwoNc`MU7Yi%fuVr3{mVF|*e`Ht!*cI#%d~jU zT74>)Fj!(U!2h?c>}p4rkXK$r@=TF4EZ~s5?h2>MtVw^2=Y=@KYVr@%tZ#6*e`K6V zn{xi-RgAQbz2S5E0-S3>^jbP^!$?VLukWNocQNyN%MJItRkdNDoUMjugP&7t!M z@AOrULmu(~Z-qk;3E+{0NP^A9>yyIQ!9(l`dH9!BBC$)adpEH#d*@gS%!hB;VFfc8XeW}iQ=N}TiDz4sabHKf=ZvFl zOn|Nnc(6zhd_@2*qUx6($Ql)Q!waIv{vS+HbQDKprb)q}RBF=yms0$>3s4j3DS}1R zXCm+&ZLj91?A{VdT;n{KkWB_j+2QSb6aerG)AHZg4*a;Y(<<}GbX>>AmN`qBUC#*B zRB2k~9Gy4!=6vUM_so79Yl~DsyC~gXyNV^OJ_&=x#a3XD>$#GI5xxA%^P)!xauYoi3XyZ@98T*{yjgq`yY zvakD&zW-Vzh^#0cBDW4^Z6qs&^KnUZZ1#6OJQw_i?A)mO$Yi+tVNX8{ZUlbZH}y!S zshGO|opK*P(mvvaf8cM;f*+blGCeZ0c17ccbu}3cOx-=D{1KX71)S+C-L?v;EJJa) z3-@dpj_>%Lm>9*-LaS+$ezeY=MS;a@;Ce!@fJvaQ`tvAcG?gknwL&%8AdBQ~0{hu) zhrad(`3CA^L-LX&%`ewFp^-_UTWmkB6z_Z+Y0&`COaJIf9<)u9CUyGK8C<%HSO4=Q zoyC6MgapoBSO8tkQ1KAfeUo9C4iFX}=VQIkqJ8U-UTbRIkVm${VAi;f^nmrQuayFW%UpX;(03P?Y~eJ;swo7ST~_ z-;tHfgrM!WqU`HmOZN~Cd~q*Yrq4-|Hz2N!+{HroF9410IAmoS2===~oC{-cH*T3or6& zzljfjie+!%(-m0xIgWE`bojF(jdn-bVxuNd6F-y05de5y_ya8rSFooapsq}&I(5aD zwn$ly6#SH6(q!ZNT&r2Rb5$&axD{`>B;%VDH`m5#yVKQr)DT@ZijQj?p5*`ZICoKz zGMqeL?E9s6=3c5-cF$~ssSo#~G?1O7{|ZU^DryM(uV~d`=j!w0QSr^oUx}C*6~oa< zsr)MbbImSR`4JTdo?ca{vwQ&e=H$;7;S`1_=)K=hjTqLi0WrQ7%kf#Kk#z3QGJSrL zqu=gKb$4>*?mfbyQRXgk{*Tu3-T}u7IFLW~0{=MoZyxd$ zr4O{y@ciS=LRwi}<`Y0u4Dv z2j2!&72=$71>D|wwU52XW>VaHMO)J7U5Sijqe$;HI5D?cwK zVz!uk3G4@~p?*KnV|LB#T=I2G+TFY8>w|IkGg?z$oe27T+bbEj?oRVtSX(!zcq~V* z$Bc$PIVX0szBu=v-SknS{8L4EYMxR!eaDtsv?-f>)~Ny4-i8ZpE9x}Fy?j2nbFXXD z`{Rz?qJ!ccQ?ea(zAaIjcrYK1RB@Bic|Sos@>s!r?nRXUMtcJBi2$9qe#o zg-3UvNMG`0oln?mO@2JQ7mxFnct}|zdd-MU7->5B7;QMyC_7PbA!e_TvFgwzH5Qft z{exP$A^Fw2w$4-(Jdw||GfLfNemVr^>s_g%FKGfqNx?5I7=MfVy?JJ^BY`$g+%b$= z2JSSbajSA#CDZhD?;r0zID8h?ec6!A3@aTch<(z9N!~Q@z>v+I!;FU`<$qsH$QGAB zbJf@=^74@MUPPRAj+Gbcxu?W4k;r!%m`}H3QkR zZMCUqnO3*rl40^A9hrF(?bR(GJLz$w+^+4rpG7^_dN>!9RVGzFk{jr+>q-57A2%1i zYt*9~4u5aB7kEn>d+YTnwJQ$;n|&KU)yd=*@AFuGzx{M-GI#qa#^dfK%3a|+X=e4U z#|OH(4_4u<9{%dxGK)A>KzZ*{a?x}^upoD*+T_cqQM@U~r+Xv5wQr7e6u%h!yy4(< z`NXu(6U%2J&rCHgFIO$r)~x*mtJ+_j!+kJ*FEe2he@ zY@dfK;=ut~;&v#JD;UKP{DpF1-)25#OVEyt!5sdxwY=>ewfwx&eR&bHvKdvqN)=#P zYgI}c$Iy1*V;#$T(eZ)Jo^vBDQFCNRind48ixzk~dCYp!1ilvqZ#MXU!b0ZjA-L@j zLGY^(=u^+|2e^;{UEa^CpU`@_}YkT+W|+Hbj<%vs!U|7s$~2 zI`_ku9(H|J6>LQ+;~mZ(3Tll0 zlzJnR_URS#*@k!&=S$Ch4{AOHJe!L|xjn-bgC|NmU@_&vD-qQ+c0vl5^R0u9z3dWZa@Ed@j0WIcjUKcKOGL=;tGDX{H;d)R~-X z139C_PtUsxJ9qNei6dcWN~e^`J+U#>Lw00iuu|s>Pf^#-=+ZjQ`JASLr5 z-FJB{E&i<-!$|h1Lk^dms-XYx=(0?nEx$fjxFNgb>b-E1;~Xu2(=Sz!U?WF;hiizl zAexy(ZY7G_*XsqRi;N#Rk>J*?XLa~uII$vrX^Qa5*HT*J;dJz1?6qMjse^q*N&dg5 zXqn^L?SE5Ry7*$H;P4*`9LQ<$T`+OU);k{eni1Yr%0pw6cR?2zXM)xtJ8}a^)RBG zR0w(@Pf5q@rblJ6*hfVlVYq}f-gk3ekT&YO-r~G%2LJJmlB2c3DveuJa;Evz6%;%l zMGHt)3T(zGLT--|=Jx*M8sdV%igjX;@8@P2>&8L;?txAC#G~EX(Z<(L= z&pX9Z&MtBWm@xj>FYDlk*MDyptJ4L0sE`f^nAjNJlkK25^-@Zaq6~v4Zi?rEFMr3( zsVF3OP?fgsLd#~Ei}Ck-I5+v6lo!I;0;1ooWs8dTx_~>^Y0OQod3yy?-b(UF!99DIcto$h^ksba ztb^vlalSWi$>~#R8{e61qqCZskju=JcFjk9zl3|fsbmK~2ckZ`QylBe7g2EaQ;s-Y ztLv2mb#wa!ebT}lKS7Mv@%N&#iBLCt-FeoB-A^lBAnK9w;#ij@+{4-o8535`4cb9O z5s5dQTUWmtcgWyY57cr>Q5w)*2OO9Agx`V*I^2}O3!KFcZYball5ibwlI_JRKj~y8+G_B1EbD}_SRi)Tg$&d;3JC4c#H7%6;u*~M57f#-EQb= zf#rJG15qR*uRgRR&cLyeSZMg8jrZ4D!9*K6mK-{@UPz(+@82`+u4GQIBhA)~1vw)5 zcfWhn?s*v(R?PQU^j@Rh=@G^CwnnU(R~fDoXFE$&=b&^b;ygG$V@wXhs!SM4A*T#x zC>C!wUNs83inX`UYiM%)iUe`8xD9p6@gR&o`zcK)|5TuNx;w#Upnnpiz8r0baZ)Rv z_w{)NgA`D1u0}3UwQuP)r$vWa`U$d~J+9f9oBz!;8fPb*^b8(u_C9x^p=|jB<3(mf zo7%GkAC2{&KaG{$BMlRLkEFrm9*-NVEF^wV7hYY)$Zb%W;qQp9Z=Ly=C0B_HlnX89 zaXrGqjn=b!+3dpkS@eD9Rvettf^-NiTB#(gR^HN~Lg`O5@i;!GjW1nY z!|Hd{o9UBqcw8jpS?+?^%pXDXc4qyJcZZ+5_zTEvyNe89_Soq646=JG?p6CSZa7pO=QP?L;B^nE(7Y6bSviLHm<|EH&g-?eZ$VI0s;{b%u zR>sJdXowqu_W4xya1#9kX}Q+z90Ml2I^vLWHAmDm@L5)qVsUW+`-V2l=&i<%KC@}> zNK$-!sAk?yZ=UxmC#0$W1yS!MTjt6+KOc~kf(Y6;<-i=-X4+Drv~n{4IDhrfG8u$dYop3Sp#1 z8*1j@`q4WVvx30gnvS7ZXTCAm%W7N5``YA&eP*(i?tR7^KWfvbbLAMFGm*)&;bw-c zpaY5pa+-dBN63?HhW&zq%C=nyymlSeKI@>&8lG25i5`{V9~(UXs4d@wN-X$X@f2C~ zxo}6!OYmVmDdl8C102T&b>Hxb&He_H!NP5;up2Dw>^>bnn?B3;+l!%NcfX|u9r_mW zZvT;tov(Su91Hm54t~O;lExPVY774qI*>@lwFXSIzm|o2gm}%pbGU#)KG*QQl%W*8 zr!vTLp}+rPx>|&}YH;r0r`^0yyWA3Q>dVN*h8@eZAi04#JbwvND*Fh?v-+qh<=Vf5 z31X7?e9>dvN^mPYUy(MEzgiEU+8gU&1L7OvQ^<}M(&SeXf=wLAn+NY3B=BB#3jhHM zcFw?KFoQqdXE?pg&ty(|!6_H{>=G-QLq#uuM15X6ZNf+GSi06LTpmzTX`@XNt;x$#s{aPQWuH#)l zWZuHMndt+kC&%h=ymg*cP7S4sMHW~`hCIggu+Ghs_=o|W=eeuv^f~80N6Nqg=#g@) z-YAY|Iy09&9HQh=T}K`=;Jxc)yG!w8@pfAhUWd8aw$~iQFul84Gbe6YXbdHKr8bvG z^Ru`a-`*_B4f!wewh4Wh{fqnZh@K%*IeUjUo0!g=I#+SCq z|3;WoXpM6=Gczo!m2{((gvjZ!_(0muF?5VJc9hc*Q&f+ZlWRkRbD8(Gy$pxb3@kOa z-~&Cb9<{vXrfGD8dSu-0X}h}2Ny96)fwF$?oF{oZJl(07E)dNgw3vJyAl*S{HD?f! z_d=oWI}$%nBhIewwk8Dt-_BqQGngqiweZ9ICLf8fk({&qj^Iw1vl zNTRMT?Q$d3P0M+?zM=)A5{c7MNO@E%TVXG|#vdCTMROQ^pqnJNEuq$&d35{hWG~0X zVWaa@(Wp&L32ot}K1SW*FhNK5S_)xW`Lrf2dXcyk5clz9 zXF2KIYavBjdoFnyb~-vm!{M{sOMnHE6pQ#{7+%H_j6Vk>!UBGX5YyAs#eQlZ+t2X% zrbO1z(7-yZ_LKc*gO;kWDBdti2V-W51*GbxGMIitN3=H##Qc4B%H4Ep1lXtXA2W>5 zP`sg1k%7F~&7r306Y@n91V!x%7H}Ntm;1!xN5X4K z;;+^u=m}R8E}sl_a1_ITm&S9)k}xbDyO95$JZQ@{#w{9SQ6Lz_8DF`*zcqqxY>#6k z4br*a2f233-79ELJ$i8lAZ0)2lzs)secdncc7Mu2;nksrh|A5g+P(*x{HP+>bK_mH zEzu=XxHL0(2L<<{;ud))F++D%ebjJLhkDHDCPDyXRI{w+xuLl$gsQYHjeQb@* zUKk!CAc~aiNMy`{lO1Zhs8fr7L5+S~&#!k&VRcKR+-SZ7=XK*iKX~+p42%uKh|CDo zBE?o~kwW!vrv`9dR|L(6%3@u?!?rCvdEO$6;%%nRT-8wF{cvym3pX+S?oi4^afJ_f zFke-yEbC*qLog((cQcYzF1x5Mhnx8S^C!^cHr(8cXVv93vN>0@tNoq0tA*?c0<>cI z$P6=+>D2WBcO2|3kB7Ab$KZ-L6A0Q88E?&&>>p#TG1`)i-Ya-tK1EBK)|kSOPj8%Q zP%I7rk#v}>#h1^URw5}op}5mVX9^nzg%E|xp$<~vk+{XQn79gfpFL{NxS=D}wN@CaR|B$qvz5JKals4y^l40?luQ@NbS}aEsP^h^(Dwg{Iw!X6# zUr-pzExfeEpQ$RWluTc%)TX^WIM1dP4$?JFLRgH;ZoWmIM9!}LsqVxFYEUs5!x*_O1dA5AO+k9<)gm}7sMB<}xf zhEfV7&LfJ3Hx@JQt<-ah8IM-(|1;SzfAC$4y=uJntC(r4^PvOm204FvzKlQJ z9Xa8y!)yO9e=L(Wj#@r_3S{4hi)n@YbNOeuT?$W#p3k=ewZPCZp+yhF3$NXZ?<1%o zZlNrF`WJm;)&L+6r+j^&_jzj~IMPCTNfG7{v@$v%*tZXn#YuC0rO~_;@@&Ak7Iqde zmo0wZkGxw@0y`y2H-Y@oPyRUrzwPI%ldHFd!TF@hGe5}!G zG{o*`Ox#uE9$OvehA7CLns@zjv`n-dX!8l)lOycPCuP-@Td%1g5*G}vlqji>x}}ws zrE0U%VhrptdmGe5XQ*2W6WZk{GGvK<+>POeR|o>sO>Jl!YPL#|&HWm$_AoCUL;U-i z9U=j0+1zL13PsbibyEO4x z$TTsT8%P6lJ z77}n=(sfgHEm3e@ul_4*)H!k(plPk zbIbc6>V7Sc-$U=s)kvnH>~IMVd~f$(tMj`<36UAhe91TgaxuhS&K6FYUy-^`gmShO zZ^1KXl-=D`}-%yPdu z5bLD$WQ*q4cyu3;xF_nJHZ7vH5cBPT&ja1`K@%qKJ#5av@i3z~9o%|atU0xyDz$(* znu_u-a3?Y2I&D|qPsZVLZTxGXR*{W&8dGOh;@?&bJ55{oyEeWH zPM}@EBJ*gZNqhdm{U$#L%>dAisJ*diTU?$f$fU+UnDYSD6)wq78UAosmw8#z9_0Of z!q_Jz_Cka`Y1*OZj@`E$cD@VQ zlIzVqk4-9{ma`!&XcX`T`QD&*=z5nStwKi#960!VLBoUFi|e_QGmsNxRF>q;Elolv z#18a7zW<7>Gb=F^SEwpE%1-ql72EKs-rSaVM|T;^fLnGSMmMUxBKmr&9#JlnRF5Iq z4T>c39JE;B!PJ@CXwk{^Xs(k~WNoH?^)8^PKK4{6tKek4}^AEDber>nGkGJbU`y zPVpo`@Ogg1z+U34S&(`4(->1aYe32YVw5b=YjEu|#1j=Me!3-N#pYgro zJ6GZKz0w%U6wa^y=qr3`sD_UT{o8!^^3wjml?+zxjSnV30g@N&&zn%Z3S{n>RZ9ra zHu_{K10hygwJiLlo>Hh=#I=&ivvNO<^gJr>0h(FB2-t*j@8VLAoHpt6Zhs~P#+Y1+ zvn3>$_t4^9RY=)v8oQXK?!Kx~pfidQ%uWs|EV$uIMnvyNnxSCEzOnQ9Ig^$|EAC?# z4I10I0_3+WZe{y3$zv}n%s!Xf@w+f^%CKNj4Wyj+S?3I=yu7C;?nx6*K@@H9jS1ef zd!I0>W}^L}(<*=f`SUMHtbOXzH9KruTh>YrY1wq> ztfysVhgdr&X__O!D`~)$mfV;>+2?mGpZ4=TiEpM@$R1~~D<(ZzoR-yPTj8XjGz4}F zUM42zlp{5amgD@X!N|u(MhQ_kuMc6(59(}vYhFOmw|Zi5Kw{Euo%7>q`(C6|MCj-PGI`R_?GGQGwcRJG33!T%pvQ>EI^m#U516YHQVr-WcS; zP6xmjsG6N_SP&0a2eg-gaNG*@u<)^l(cNOlxI&NI zF>hZ zVYRZ79WJBZT-zY7?Iz-U{+J9{WnGcA1t-tjzDay>lVRu>ayssri6lM{4S%(F7jQ*_ za4KIH1X3mVf3tfT_fHbJs&D`XVH}gm>f}98Dk7q#qD0)1-*#h`Alg-0Gf1mOvQIhv za>IZ*#hfPeXev6U$Gwi^EL=4`?2z!T95$jkxbp#!9rE}i^IE$8onF06^n2Wb8f0uc z{sI9PTYzF}nQ-&4v4{d{5clAWw6$RKBWHZ63#m~gW5?k^MH4WwaD=c_b;dr6;j4;; z&T?=HT|nixSn2IY@hweCjE|m_3OBo7D(UAQe%&>p)1uG@Hd=f&dO9){_FymKvqC9g z&`V#)A-o4I341O+IVGth*%>e-l^z+q`$T_4wYlNV%*Ae6kG>zh=IL~C^-8SVx(f!K z;xU`>E%uZt(kDXY;XO*4d>kV)#TvqrrySoZ{7+C_^BX|C5CDkA?RD#~Pm5^FE{E5G zezi@pU<-F=U9s)@wTX|tL=;8%?&;YG#=2T(Y+1*DpIFyj>##-U53)TLyj!2nL^&uA1qA^nks`WgvFI(EwQj0 zpWF!oxh8XM)jiU#qADGpTootaSh^38Q+JMMBQcH0S<9e3P}5b@8Y0jEB|#ZF+jVkeMyoyN5rrD+SL^4q(aDeY%Ra*DISiur4y-ZySTc0T!pe%36bhuY*ye`0VxwsrKPb#$Lr5EZ_u_PPzVaIB9 z;BIj#Fz{)=Jg(PjnFslTa47ro_CM2&zaf@&VokI~*FU?ocTcXUuVInFt2UNU29%Bf zbRuFr^BhyGh*q^PG9@5Px^ws>2OHF35$zOe55gsW3VJKZZ+wftHW(z@uS>(^lHYT( z1#ef)6T@ps2`B8sy?+E;(Hn|@oy@9n?u6CWoT~+KEOfmupX$y)MB(X7G1CA3?}rX__}J2<5u`fmG&n=!)`kPXraBA ztKfUnN?1PH=VHilqDv{^wYwJ*p*QF;_Gz~ZG~j(B<1w8t28^yq__);dk=*uJH2>Q48u`tIg@}?)u4wC*NEeLkB?;($8_D z;Y~aE#B@d~`3Hxz*iFVt?!Po4bNo)$UB+0;nZZ}m+B2%FlXcZ~!-tT5;64Krax9N; z?>cO4Z8zX86s{)WAm`n$9(v}|$!m0ZxqgEHXx!J$1yck>(&BY_VBhWW3w~Q;RgM3o z!d$aa3!Tw?mly=6G>C>Fiin3zSN@Eokug}}hV=JA+-#m?Au6IIm3-X@!@b)VN!t5m#}d^e}M~wDEgw5>jm_Cuv8qSf!x*>Tsu(qH-=uJ z{w2J{bM2j~x7v;$KSfm6w{}?!#FBf-AyY2`jghe@R|Z7Z%bxyGuNc-5tzw0HNf7mE zTv;FGUWYPt?2<$8Z(eSb@Lv~>LbDx#52fuO~3nZ^Xl$xv~>vs!NBicVXoO~;J*ubs1Mi~S!^`UBI ze%C@tu^-a%x?<7iOqn02M~<$j%|wr?VH*63013C$hqq@AXTB#kxpI)a+RP6>0s1kr zeljA_ha4dgOG=;^pu=T~gS4vEAyL;dKpufj_gwY}v-?b*_{Wf!SLvAKb)j-sqY3p`=Vg|%;tjQ)fgTIf*J>sNyv zAUq%UNqLGo#wX~^|7GYX^75bE48=bL+Y}I&n<|q+_V*27PZIrtj~uB}x$!sx#6)N* zls4MN7^P?+Z@%=`@zxW`xa0gAo;**xFWQSxmtQ43%EDAo!ozz<#xY%_%B{K6 zH9RK+U=37=svm1TdBQTHHfmgvATEiQ2{#%8EYCyN*FTUqGx}g;A)U}e$zT>EIMiy*g zUr?GwkcB_zvC40XoPMbpcQTrA_Bwb%xe(({t)M6859gc)PsaHPUdnuBWROujc;aR; z&+Q*Yr8l-^9Rg2sW%kYKoXo}L?N%A!DYf@hWgI_F7L|H3Xlc(Zm-o6*#kryYmy57& zGbayDzvmTbymzK~Hj?(oe7^%>l`6gtH%aj!PR8UpU0&zb>HC_XzTi*0j+*32D<`gq#E z)`Y420cBYm2rFMh#K2MG@b$*P;Da8jmbfa}SK+n$TYcdaI4o>!^mFuNL{=|a@Y|WL zd!Lzrfr=QI$~*@I2lmmer_#Xdh8U&=7_mU^j)+}?*WXmIv%%oh1VuK83tsQAIJnSHxh0)N`}2F=^aPw--oWSOb#hdV>W|_wT0)KO z_|KyCZ3;=c`dmWvYINkd&Gx7AL}anT$)tV}Y=2Cw?C|Q?D5UezwybDvHC?3 zwd&Z*D6Gz!-C*!}Kh|qR2&gJ7>X(WB3nG<@0KaJ8?xI{B-wK}r5p7KKg5x@F={oBk zIXSm|J9z5CNxTb{6T_HwZfr~&)im&8JbUNw=&uVc6%txqoha+;pJbCkEd{QlkkpLj zS{JZUNvqM_N(~C;gFCW2qFRwmgFU`ulNPC(+lssA(b_vs%3>!*!eqyCx5dnPD;8>! zTHUI*9lyh+XReo#LIm58H?UvdkNo=ZeCvX{LD@cn@%bdLN|_ZuqxssIpUK8goNj2z z1?-iUp~$r5Cfk&sU~_sXg|o>hi(AM3j+rt@8GDeI(loJm(8zLp^lgathyJ)P(@kxM zABp%xr#M&BHtru>c1XIDM=O;g1Bw3g~Mx`^nLw`FhZ z065(k-*u5+?UTbB5*f*FnXJ)OfxEXCM+l6hW!(CQvO=y9Ya`UDq_`VC`)&J}@^#f~&EkZKL|M!4;UHJ=JSV zmpw$C`^q63SrmS$Kn9=ek|`06H29XmIp!Z-nL% z(}CHD{8_twolY9^Wji^3d5QC;u@IQ_1@)wHNn{XGYtefb4@sJsr}e!qRGpt)F^qQj z58C)|M&w{KG{}gMC8fx)-;48892S?E^#A&m&e^m<#2W#_ta;DFkeN77^-K%dnB@J+ z5zg{Iz&v?3mp2&Mrz)M(jK0(g>WLu5WwY0@mRIi%P!Ch7s#2jZq!(i2Q|&%g8wdJT zb~%NFmu2Gki~frT3@ml9I(wRw7AQu?EKv8I)K(V{`^0_RpYRMi65CO!r@igpAJhcL z&M;Uvw)e{UF90`D9w?W?8z7oIpO->k$L`+Zs0FUvnEmiz0}wjuTFrf0A`*9#rO2gmP)s?vFfxK(ZWy-bM6rWm&vHvZv-LHM~i(;^vZubv7pAzc4 zg3^5}as8WMYr=st;u$PI9|m9is{g+^l>fci$pF|1@n+Z_w}se)&JKc4a4+cBFQ(1% z4IIfRJu;SMkn7;y~-#4J!K-}rwt*8^-u@9dpIY5Fu?eP-g)l-7HT&cx> z$68Ski$owSfUC-!MvQJM!$3}3V|*(cal-K$zv>LY%D%Y; za5?v$TiL}YUi~d}>RQ4M<=Z!)ZZiA%_nwgDrSO}Cz8!{ls^8m=GdP50e~U749oGS3p@DxB0LAx#%h>YeOc%lA-h0(L4{DfS6~*-Z5D`Ke9C2DZ zQEUvvxgZzWOL@{CtRO*XNO|(ElfT(fu-J1P_@cXEwKtAie;1(!A)YLl%*J|7Sd11k zuH{rusqwFA{=fO}R{RjMwZ23KH{6=N?;q9ggd-f@4o z+&lIcB%%i)Sp3weoX$UgZcGlWehK-ayZaiNDETeRYcBV81*4TZH-{aZ)sxl8pcG=v zGUNs}y`73?ICcE;g`-fgBA?koxrZr?XN>rjCr?Z4ah7~HGVZ4uXVtYnuK;y~e}sQS zlTV*jB&CipusO6ruX`o#WCz)^fn$``10#~?d{Mt29lmxA+9sy9Gs~6Rl%2oyHM!+3 zb-w4nXj>VNlq8RXoEz2w-0H2T-E}7KosERh;_OJb^tfVur7+}5T5hv5fnQ2n=)H05 zQV=g&K0K>cG3#LI)3C|C1h40#qs50~I?ATa3F#(r;b9(#cj1(QW9&0~Dlj(RR0C+8 zUlh2_Nf=1wou9Y$PBe`{+?w{Si2h8>-V=J=UREpgd7j&n8|T_l9(LUcO35?+zPgrGJA=5K%Z~8fJGB7< zwjpfJcg-$gY_-D~_)UO251T+{uGwp!N>2U-JQp}6j4p9qF@5k(vfPi}avCs69$!K# z3ljr)*gal>n-6ZnKPI*)Mb;EtOMXj}49X&`-t7-f3Fx#MEp5Z~3v~4xxc#SNYp=~P z)1e$ycvN@9<_(JiueR>6?myO?JfvUHhpZ8=aHH zPG`DRx+YYdj6~Z%jv3g~7}+$_%tZMrI3f8rMW51cbt->;|Iy#_XyoAgQEe=zxHZNc z-e2;8;ExneVvWaiUlTiPc6?WIldJ9CLMH?Mvf@JGViued*S603ko*qQ%ru}bMvO8a zPsrg6>|@7bySx>P7z^b{^~l#sJ^bLuGLjo?56o3uycW_jh>|S0&^A&B(2cnxL}-Z z31xy2$tM9L7mTY%V6P5%xq>(K%jN!Ge^{N*)ae);fUCqc={;*IO% zagt#y?N-uk`h~maopLhfZ7NW@J6@;)>=n2t3k>sL)Y_5g6VHGuVJI1?`yW5m3i7Y?DnX~}A&zX(84Sh5EL6LCg zsb9#>VmPU@B9OBJar}-B!;arwUzo9&gPQr?DDoxaR{oT+fO}r*;6z|gS|c%uZ@X4B zsElaOZYHLxfWNIGM|>zTj21bL_*uizrB^UZu;AyE%NSgX-VyG;diLmd7Hu$xyGRE_ ze^$7b8#7dm{WI&e9dpg}>) z*ycZm50nAvV;!T9V~vS;nKB()b7loip!N@K+={oWPjzY5sm;Aupsdw{vK2lh7@^9I z9qrwIc0JK!gKpz;!=S*|j*NS3Yo#oV#irficYOt1n8?*;l%@(gnh-^+w@?0RNGiL& zL!d6})qC�}NyUPWK3|^=Le^M`1r?66o4--s5Pa?zO{p1Weciw_lc0Q6Q>7jP zLsrf`1B%^+ezU5q=wP58-(Yxg6L#o9UFl)fyWJHDpN(5pgp=6e^}7R?e=7bg+PB;_ z<9Xe-fHax8tLXFiU&>WcuYTFE= zcOB>Et7skPMSC6pojw=(jqGQsTS$N3cD!4yHt2U<^?cA+v*i4lCz>%%ibc z0p zP@3c~+$E$?bQ6r6F7eaCTw6!|qH8mf)y1*ruvgWZmqTprG(Gs0Gv!P#84vRI zr1H_RT`f!)30t~KpLr*G+hST;l7Cw&_q8&bj@p{Gt27i*?EW!4fQ85`uJB)oSyphL z?nvS&s;=sXGy3fN)faZ$r3ad^fgJR64mhdzI8374=1!xXFnHxL-4ieU>s5WM(K_O& zw0xw0EWd6qH{MOn{nWRiC}N?hB5>7kAQRsH$NnCJ{9~bj$`tWmg{&TKIZ;>n_oKH(_-1Cu=r*li(NUhpOr(tYFA8qY)18BJT0fm zO>f0dKNf==b!nY?MtftohmSe=La;p?ZGvXqv8N3lre zgr*vybNu0$yjAOzsgp-F)U8UC6(L#k_sMGD$z}*Oq)FkY4GhN9E!f}MrPG=(ASb^@ z8vp1=o8Y)q8~t@mhhfYOM+HqmK(1O-EdH;224E5h$SblGJ6!N<9y&o6?BjsouOg-2 zSBEnvrg--#qL$^_{tJG(#{b2t{=X|m6x1tbr`-8-7Qp{f>*#vQ&c168m4-i`e{TV- z#zGQP*mFg&P{TIR3X_#aqE+W3jSEOW+56QimhW>Lbqw$0@-2a}(my|3Sk-3TpsM z{wsVX?%BJH_=p{NGkzEdL@D3|p$jmf0+MnMi#F%yz?Xj;3t^32lopqm{CaG(GoYWk zI&#-zR_09fc$;cMA7-!2;@%TFF%&^B^W-(iLdB5mXQY1IW~(dfZ0PR1GkUQ<;}r*= zkAKcf0i~I-PVq9j*WOt0CDaapTx*$qjQ`wbW#!xrv*exU+t)xkyo&**qU#e4-ptOAxYk?IeYN4OJDK$0)8NUpevH7= z9cbknl0Ydja~7motvd?Dmxh<9CN~xsO;eqnA}`eM?brhEO#|YYiEUJX(n2Du6PCmq z7$wi0c_Q{q{pkyi_S@1kIXlma`|Zfv3!mt_kWeno&Z{Qd11H+~k?mw3Xc>1XeiENa z^eh_&mkYt=txQTd(heo~D78Bn^G^+W+kYJKZ|jEwZM&jK?!#rW$WV#v@D_Bwsz zpGm$Q4S?@oyNfC>k4oH3D|8_4*gbZ5^$~_nPR<_?*&n9K@qv667y$nv89Q@)TG2X^aC@myEE-RuiU7s%VRF@Ya{dA^Kto~Im{B1_2_*3uY0?j5LHV2niM zmzYd(wNP76=FLVs+>?Kc&3ZXc+nsFU=87st7MU4V5Q{ZN0%i*y&)skTf^c3MVEueW zdb<>V{?HdW6(`PnQzdb7KiUoEX3=p5)y)rkBH&1xHvi7VYky^8S-%vo;XZ3&?~y2{ zzk2xd&^vI7C!*zxNU3L=X#8(@h4)beiLig!o5@B)d_046rS*48mJwzBfza||zS9hx z_Tk0dba0c3tX^btW@a^jH%@8;VYQnr3;^8a@C+t~Hf(%U%L>{Rrv~{Q${d4$zfS~x zy~NkdPM;mt-#4^BV{~etIaU+!&Jnn$!N1wBc(Z#Q?vgOJ;}gHmHTU%??dOSGVjMlK z{z1R*@xjEPQlj}}e&F{bBy60kiug+(jll1xv?RIg5*5$n;nz_5ng&p1c`H)~QS8kx z3xue@yMRdYZnDLlN58XgYDs1{qwK&h ztH<(os$uHG=-OUY=dx{$b_*x@l!&T(MC~iQ|Ivng6{+S{b6>?oC%#3g)YOK1M?I$T z7!f<^v03%AjrvssAK6N~?CyPv5_q$!Nl}j(hxef$*oY{a&a?SLDQY=jy0KB~=~9 z-j4BN<2`50|EUnYuPXz2&srS{JW)X-%h~ghLy5?j)0xFDu=I|X{lnX_G*Q0t6-w8z zTF>UGiq2=L$llE#D6XRZ{rY~K^f}W>3#QKPsXbO6s>J!h@-rdL7kUQEXw$&Qk*_5Z zi^8uJ?7+8lgEscxUFQR2H=+@QMJ5FveJ+3-&$nK)6HfSGaHS29A0PR?RW^_c6;w?C z$QUF*y9CW!8!})0PZ+}>xkm)Dsr0l!qlP=#;hqUb zI0`#<;uy6={N8cHoe{O=O%lsuydT7v2e;n{z#qhO4sgfjrlll<`FZs zCeXIK!MSawK4wsvk_`^SjZ+P_ep&>l?Aoo6>pI*fQkIMz+O(f`wud2&g`pQLctwn~ zX3W}~wbY@XKaFb2D!__%o_6n7HU8JX6TKSk15!TT3-BMTd$JbQHuLT00`!nA!Aw#` z)f5!Y>{mY5^p>S=cVPejq5tYGQ}aC7m6tPJ;UkM5_P+6r1``NX7kXfxW?JEpa)W|h zH$aX5*Ac~z*z%w(CBuzaf6iIhbY@Ll>FCYqeHyc%h&X>ocqG!xnt{2Qg?*g)L3i2i=7sAYAmgDvXW zJ0lX~mdGA5#M@NVO| z1Ig$4B@e~I&8yrDjuSQ-qhfaY={nUjLa~pS3S(1jZ(u3i5WRfyJ#U8@)4_-S2 zN(x^pyI1iUV;U=$FcGzDW8S=6WQX9!;-U11s9pPnwNBpzBx!>Zh~ZUOuyZU<{3pv@ z1MbY)V{y5iE>dWk`9e9hSAQk$w4wd&;iiGp%foA9k7y*OB|SAG!#uf7pRYg$*)EUe zbx1qp&UEk;Rp&QxxT^COk48{DgU9ka#cjES(}Io@!pg&ux*g6?_fFaQ!&Ao*xP#)l z%kJnr>xOZO1o8(I)IEq*r}KbI?|SFqI0{AQ28 zo20>PaVkhPCd%`@$v5%vmyhn0b5o@uMVU&3Fy~IOPxi#@CMQmMzg{3n+og^D>HYW= z))`rxa=O~ zFPpk~3fNmQpvKZO_{=q(eN&uq|0J4QklKXCQ<`cg@O*Q`Nhzc_9V^%Esmvcyh{S0f4gi{9aK#L0 zE1-Vt`%=Mh>1ZT~y8WnIG1D1G`CoJ4UM8Mdc{hISox%f$m}MZpGR9-c<@`e-b`H}C z2l8~vcnj;irpTNg&UN$6CzDB30%@yUXUH~I^fa^3$?40{_=hHg{ojI;iz>&<^8$^AW>7fVAI zmQVeR?Zk33?Q@j|BkD5(mHQSsr+S>2W<71p!vrxW;wzorO`RoA?Jn?J-SgIlMei$w zICnk99zswz#u00zm)IpP^=0lPGb)rWsqV0T9|@FW-BX{QjzRt%K+G-&KNPg=D-F^v!6=9G&$tj_3Hkb zqWU%JW-TaU?SXzy$*_Lnyk7r2gI^m0B z+jbyMJ@7p{_&3k6keIT|*FDkS(2;aD*c{@slegj3q69c5NaZLFq@mrP^->!X)9J0Yn3px)1|*29(WjI#iD0L_zF zb|Mz}Ot{xHxA|}}8w7_5IrDVn%&!OWsfTc-JOjv$qc}7@PqO2yZ<*PNT80*-oQ2LI z%6gjJKLD>%f11FeG+kNPCv;jz9O+C8WfT2#%Om`&O>X>ypahG<9u&m%vE7Li#tor9 zky7FA)SliWG&KVs+tr_C*t5MTaInuyLIMp9yPJfeVib!&&XB;fd0ImoTodg5%N;-1 z_g;HTKDt8pOrCwfrLQ=$=h1R7@Z-W9nlIqeW{Kme($-JQx$)~aZA))X#f`R@%w>jg zg~;il1{X^*HH?0s-{+(S#;Qc)m?$JKA*EB6Vl|%s?=qMTzkJxXFPEe%W!$UqGL@<3 zb>%ETN)EpQ>h&6Pi1oMQdXRxT&}F|1xFbL^C_Gj1ZA^dK>HZ zg2tFk!_T8^VCMuxXYC3e9|d6Fr5uE|G=2)%{> zkrW($M-Mb_wDQ9QMJn>%g7t^hYjQr>3lzUYRzV#!G&5Strm7^UhIs10NS@WlXwFD@|k6S#;8G8bCsiQ~Ww=l-6>zY9Vq*c=l*|a$Qez zGf&>8L=CccUjxz{90{<&Dh8d=6N}k3`Ya)Wkd|H(*+P4OP!%0gTFl3B9Nm~Bwx*gr z4x4aVYOTl$>)<;}*(Nu)98%rc|CVPy#bNZyy#l*mC0g#6Wbtk$4-;=JmO00`rG&By zIy*n!Kybz(q`xWc%bmf0kDn(k`v!DORw~Z!d5~gar`Aa}+B#e>Ui%wZ$v-CgTTCDK zJ7}-=6L)E)9zWy_F zlyZTPAtmSb|?j)3yz3aQwhIxha_-tuU@rI2;T9skr%ndMv;+VFe${kkiAf zLqKzRr`XnwY_NrtK(c6j*e`gS+#vM=t9wT)z(Eg+l#UHQi@SC4NHKZwIZx5-P+qi; zddaH&^~CrLWs#qz^vNKqN&T90OzG9K=(Td2S7|pHHqbfR;SN2|NRk>`74gQ_^yDe~YP5bq;S0 z_ir`_8o*6wWc+-yD{#4V{i|U)D{}E?IS@CpGvH*ts)f`$%Dhmt$uU%ZXKQJ-7krLm zYBrufYP5`4xNcU1yXVeEe%Verf_ z$1iLeR3DzArv!3@W;{28;e}Sees?JdKBxHu*OeQ2?>^8{su!Jfk;u;%ngX@K$BL970QB28W8fh5;>Js&UrE7#OL$+($weB+r<^Z7+0!9Q53eTG)WLKGVZ>Rzs<808& zpvSj9O`1OutSlJxUR~+sMw=UJpWD>dok?uY>DC?iRvB@YtiWOZcqMaCkxJ1wn~$fbIqqq!W%7?LaM zfj}9?Y)V1Ld4>vWHra1q;tjNFsYyce^n$0tGtiwGud_5HcpN;HYVcHO-{PAntb#>G z|D@W9=vlG1r&p=5-pwHZu15$Is#ncVg=2>f4N?8 zyDA|HwC$hxB0M&||H`q_r<%DztOVbb)m#07fK}d@2rAXp70#i9q3)!?_yPVNxQtW# zyVW)aZ_;E=Tb3U7!K5W)5=x#0l#uGkeT2m?FoqetV)x|jc!*0FXZjGgO36`hdON5+ zz+0#1eo3~oBEwU)l-}t~E19SdzSU2$*^*%qJpTS*=&|)LheK^*jv*ShnJF`wCVxLE z_Ax*+ce13_2IvW?X!vZ4w7YZ)MZmz_e#$nn6pQ=$qdk1LNrqL^LO5OhD1O2wb(}yIwe@d+14Sx3H$%o*9tvye@B~KJ?r8SD&J&m(|vzkXa zxmupjJR)3$pEslFl(g@cXz^$PPf(nZ_^Pxup^4qOfqkzsYb#cpg-5I@HR{NdHWuZ+ z^oplIIudmS*K)1Tvd0=R(p|h*VHXd&AmngrtjKXv!bf#&`@W^&B|5j%rH|r8rip_K zMzN-XiJh6l2vtg}t%)y}CpDM8C^5>vllf-+uKWeq7XPr)o16)iAlp1Ejb$DNLsYdN zs~k&OVmvd&Tw)8V<>v&(ey7D$(gH&D*_0x$>RsDfhYai;fCz`4VUbq+QI4+g1!D*t z>@LAg$F`Y2oG`9bK&zZV45C(bZSPX6{TS_gJ3*A1$>5x9lul^Z)0n>I0B{0tWtQH* zWX9LVp#M_Vw}onT#0qV>>dkgQX{Fsi8hO!5?^T+UTIOXPw=xw2Y}fk>um>U+F4@o=G|qKNyBilEN|@T^_`E^YWg4DZCauNjsx3V_`JOBy zp8x2+x6|6(%ERsk^|r_a(n6u|#_JrDI__Da5m~%eh->bVsG_d|>*p}{S;I`jnPJ^W*uAT@#v9$0wR#0SZs*!?F=1*l4ixANf$Wb zs#*u&jv#6afr#xJU#?z10PVh4Zb=UGvK} zRU9`HK0{zt$F7@f+*XbD{!CRH1F!wYf3b1l?T$Ee!()m)>G=X{Ffb7UkevI@J|Ioi5fGRQSsFfF?)@7N}h*#c5*V{c)l9>qs zwh~@`HLFqpkv+FeM6CAy{Z08pX^kdhI<|VZWH0Tx#hneN>VD=BF1Ayi1Vf(LK52ma za&>76{cYCoae#V6@Hldl?J(k*{hs?_xq8Tp zPd-u3&ao~OZgXfB9v0LS*>hXlgs7_oK6lDP!E?N+Yb{eVh&>U}gW%4QGr^AULZAV$ zqt4=srtBLG=lgzjucQMtszJ;^sc4o|ID z7}&IX^fUCY5}^ll(~UoTEf5=h<*|nWT%rgGAIYU;@<*@Fc%@?OA2Nj5q_645FxkQ= z9`N{iFrM)>>?rdiX8w{L}mlQgp_s;4n6q-niYvl9|Tos*h%`FHd)-*}3g&`!-Qmj1cY+ zR6Eo6vcjP`j&8Ty6f0O;R#t`!smN3vMn&@ji<&SFF7_dBi`0zMIsbu*IYSHnBNKfH z8xg#9^gFAKFt9QO)D(oEr{sz$8&D5*1-D9p@kfYKed`6LT`Yv!3d6T9D7Bu+u)#Htu>%yS@xxS~-Lp zy>KOC*(yWe^1aM%jYEck8f8Y<`C3lTg(##{MtfPMv{m;)hEa(2T?a(P@}uJ>kqx@t zf|w6LV5n?;g*d(Wo(!s|9|*{ys+w6^guX*?Vs+*SY}p;0omZ15IMr(IQXN;Dng+(6 z=`Ro|(a>0vW^j6Nn|g5It(CJS(esW_IKJst*!Q|{!hqmEVm$j%{9RAq(ns-{)sz=N zU#`Skoi}5%oEtE@Ig;rA>hf!>Vc>e5Rrb{9rC(R=B5~!5zDAThgW>LeVf4w`ie_K8 zkp;jT$Y2DY(<0zKVDJmxhiUZgY6iaQ_k+ie^&M9pM>-nM2QSZe?6^#k8OlVz0@tS3 zd|Bt7gK@ax++CCZ3e6Ew4Z5IRZmmF&rSQ7;FS$bZTd%`@^O!MtOyjiu4X6D!vJ>Xz zmi8YwGsf06Ss?&ip29a4EAR(CTsj3P4H5sw4G*@X%90N&guroR^GnBp!?BvHUbb`o zXfF@|nn3~5DIj`*NfGClC{mBvemE|~9U;~QaA$S8`2DI2fNKv$alUK?rHW6P+)vQQ zbOiq()YR2$QL31!W&t2~(haE`;tADSqU+7a?1K*jk1oOf|H3nW*!D`$)pD1O!zJ0= zXzjDZ)kV!so03K{UQmKBbHwP{E3nfAODx1dv%@tjcguFhAq8@zGSb?gXpD-+-F~_uzJc z$SYuU!SMbQt{}mkSC68!ZQ+2hrp2>%GTw|f`U4K`%d}WA!y_X986K)z~spmQ>HhI}BOzmqtuep;3e#crSXQTm`ZvM?g6eCh_*)z;BVs8dG9ZQa0B% z7!>L?3tWEb+7Ft2rigr|494jZiF-$Pg5KbJR|A*i4aE%UyRFr>c>Ff!jWW`h@|+}Z zxs8B{)bRl?An~S3L}^~zbcHfD!#8@DGv5*}oe5$rTGvoARW%1C9u6kQ z9bPGl3ek(h$Y!gC*H00BxO@xSp=UJs%$kK&jvNR6OCak-SJ5#P+xs(5QjtvAK_eb^c|`XNlvFASY)nUMO>$dLQcbRzOr53=+I+4l ztC%wjoQDtvXD;_tL2bQ5PQxxvW2a7Ami3xyKUQz?4|%(BG6{TVSSn{ae*14vlb#^433c%8$_k6LOc95LF-XY7#|$+d48L5H9Ivq2k>$QJ4kZQMe#uI9#aR*e~`EZ?MrW=RyBTRGGz5qA_z+*1) zoRdpDEn#_0vS7AP9^;(7^&f~_QxzQF+Wny!M=vk4#|kR6LAjXPbWkM>#{*sO&KK`E zXZu_n=s&pFT_p;?t*&xt96BHpcxFk_gBT@yYz?ufKGM!<&$MSm0onQGqv|{(!57o1 z?~Eh83w8}$ryTym;AV1VmUExk$Zetew@%9~ zpWN|izSgJEx9)uLETK@HvB$PwAA>*re109Zp>xoR@k;NAyp3*>Q70-;%qud1J>FmT zkVJb+b5|eml5{7mMoV`u4Aa}CtOM85zKg(polHq+TDVFgy42rV964l2X=rkKV}7b4 zb0Z_6o8Rj!788RCtG)(%@x|nJS!VBdzLxO%CdEX|gs$yG_e%gVcf*-3N@euygfnR6 zrx4iM>C(egdN+=-Eqm8@JfNcq5k!?v>R2lnAZYmtzgB=b=rtgiUoYmI6Jy+V^p96B z&H&<%Bn)tnipm6z7j;r1SB}fM8uNa0U#tx#aHytv({8J~wpl{u5D)Yh^d<5kYxy5) z%GTFv*Oc&EB|*K`>Hwukz$EH+y{9W*qg^T#nPYkmZ}W3Z|NrorQL%KUHPkHH< zavA+sj?6loOb2Cf`i&CNv#ISNxmyrr&Istfot~>}Yxxoj9(5!a(ub2^AQRjsRz%1F zCPe?stc31k89tz(Y|q@XVD|F4<|(rWGCkxiz!-o{L$A6BDDeWjo{wrl;#r<-6_T1? z;DqM+)p#LNf-Y8n!J*y9xT$~yCn=9-LZlh;OQC~hbgd7ILGpFCyIIYqcbo8FM8$4D z(|lg9fsM9#gc*r}4*YU(a)PUI2>?ZxPipSQrrb?67vC%m5mn_ zQRc;Jr3LjsNm)QX?>(T7%-d=#$e*xDsxMEh`wboB!2qNSG^u3h3&J@$an+lJGZk~x z{z_TMb*eZ!338vV3R)hC0djawx-_%NjsM%^T2<4-Tj;s@mHxEsl+6A0!!7r8CGZXx z+mVSswQmgvw`EDoW0x{K|KFndn-WFKv{{LFoQUL)Y7LUw$6bFzj;ISOGC+BiDaL z^YR$*M_{@mbao^h+XVs{Pg#{5_bN;4iPtGf0_*FA9WEJa10qr8wVEo}y|2XY&!>C- zDECwcl?Ye76GV^A@4^{tFUuJStp{{8S*!0*y$DfGaC6iag3^rP99YVsr2ohiu=vB$eBynDTT0evOv;-Vrm}pj7O`6nXnX+!fL-TIirmpQ$(3Rz zf&JMa96&d0crr8(W4@iGU*2~vuip6feyg|z3)Z=<*Pr6;~Lqw>&* z!UCHEteTF<*t=a4g(W})OjM90~*uOgS+0p47=KcJTfckZuJK&@{aC z7(_8X!oIMV}!A29)pGX-JRK$;M7RbdlwSpe9(ns$iZAq;#c`v!%74L{_xU(pH* zFX?Q?z2qJMYm&64(#e6eP?aW-f>h|@KXddzqdUFuU$aeS0}WoW_7m){iKaLz05u-v z!@L~7K_hoqS#f=qSorlOyJ&f+#UnCS7SG!o_;o>4`kv9(kvOVaR)A)8OQ%FjNlXTp z?&Xd8rH%SGt4t&vSqbx_7$*{Udr`SslYcWBZD8lmXUK^>%4Q_1Oz@4zNF)}4yK*RW z|AWz2K!VZT=)!VVX>DtzyP<_3J#jerLcn$vDz{wuuzoA%4vH}a6%RA+Guhx@M|y&R zB1^<7z%yQA)81^&8w_g{)|3&!++ZzQgQ3O(CAgzmj^`A}9eNx1$mN{8mpRlHz+JdZ zbZ}_HaNnD2gQu6vSm7^|l~{%a3#~*>(0>9;5NOW~Y7n*PGW(%fgkklSQL@fZE%bQ0 zQw6T5f!@GvDm>jOApSU`g;0|)pe5_FnVito?!}l>?REwDG@L&8Xu18Jb1P$g$xvCJ^e=1YTuF%62f&={J$% z2FGJO$zYWdKKcR9$mPfdG${ps_H4SApslb8n1R)Fjlz&NW_a7v1E ztIcrq5W##BZqu>6Xb0;FQK~BgAiKXbkBH~RXj@w*)U@DS^=xy* zGZ%4a;Fz)*x^cN>5SU?DjgW$=;e@7#K0+&z3xSkZDm)n6#=(n$GMA2*$1-CEhe$rW zghtB?qFq??m1b3UK_hU&80|CYxcZNX%tzuy5#oilYf-@fkb?b`17?}K*VWr@e@}Z5 z{5-uh2}t0$?9xv~)XvAF(xSJk(hfOC#xE)WC5#Ei|3pD2fVvp)do(1RX*;s!_si}V z-qiK$0==g3_Om+m<|P26;-FxZ;cRaZ_XIqDaks2G&GQ62WB@YEF>3|F_%&tbRAhr9 z#!{U|MC5UR&n?6Njo2CsP=W`rKi7z0BL^LT*-t8mYT@uBZsJJ-{&M0+X{E=Z_q{!JNAd;@;j?;7!5m4pjT%v} zLBtWPE%t6I^{zKGO+A72?gk6+9y;mQ{zJ+mw^$TOt6JPutJv`r*P+6t(D4O)u zg&HZw3Vy%McY>^&<`>Aehqm^6(h~Jb%f#4nizn9%(0vV* zc>3x?{mby$JNROAS|?a^bRYM|)Hm+16EnxeRWXBvwcCwp)F8w=yrSFN4Itrq>FQ5X zf(`c#_k@CqftI))Rxiz0^=I*6ktP}aRShJngI z`SDu|Zk|ky3d>mN{u!8OgCZ%F)49zu^)r8nb=O8&5Eh?AhqC!uY;|vF*%rz}N_GPu z1`DoWS;S>04lHZ+zNDo|-~pbXg0MYM--^HaOhkT{ybX<0+AAx@cEOcx6My=-*q*k<8Pz z4r^}pZ;(UA91T^^hZ*Gw=fnFhSKTs3FEc#Zl(c=jwe__e`FjW?(E@dKvKFjF-}851 zh}08RbXu5M?JUv0NiIk{;9>Q14uHQ|C%tWg-OUAd^lIJ`bfUH`9xR}KdJ?!zu^cn_ zD+p}awoX$;>?^rAyR~1o5-guNtJ$N-V#KE8@)+Q8k@azeXN__E+H1ixyTo}g7cO6% z1;cj$FEQt-%^+M~I1~LQkL0Z+F-)Q`i+|&ZsuE+i2bA5DRSp{W@C~3d5Y{&P-^r&Z zrw1iUR`mleGvYsM05)~<5Q4W?^m(fO7yyWCgZk!K%kxBx7TfNr!~=Fuf@Z?vpZ;L2 zp1_q_5g7ACWi7@Kw9cL8LX8h`l^H_@6;)QuteK2tU5DB}Y|>8_OAtqb@s!j-RWjJN z>%LiQxJ%i1DXz636aEFY>$;aDpdRPZ`FUpNHy{C?iaWk#_UM>l5ud9#{4AP8SfGK% zR58)wp=h;o1zYn(OleWK+nD0o1Wqy^96YNl_17xYlE=< z7QzU;k(FH9G(vf#wDmE2J|5~8Mo{|&*lbE0q7<%~U z-?%!zOP5E5XRe?F!h<1qJO>UjCAZ;6VsB@_?=YN8m{(D^|FS+8&(CyGU3>3hs21Sf zSw>2|VXh^C0-qAQxY0_Vtcvn-^QhMVlJDs=>H0%zecK2Q&lxdf;MtbS0`Ef-60IT@ zLCUjMc_PQ;ygi@&U``WWM9!-{IjSWS^}1{AWW;Tt=GXG*FIV-99PSW-eF@(YvBES0 zI6G94cVzca8Qq(XeYrD&2_8G5!3C8=bdjAa_@oWpxjZE-LS-t zs7k~vSsS#^eEAi zy%({U_wq&Qw_0AU5b=)+ho+Dn?G7&DS?J?-@ zhOipeT1j57!h-9%%9Jst?|hNPlrK{E3fQIwh29%P!9Uxu$v-TU%L$=10(6N_&(3^9 zf#ahU3WUCH03iA8OemRKQJ`j9->+QgSyYqB zL!00l4`=H812=E-<*M3KJgQgX)6E%qycn%T@vJGDG$2qYq-ez}DLEXM9n}Kd!sEx= zx%GK4dQkUwm}%#8yTN5u|>8f9!&X*NAchjRx|5BM&wr~EQwI5ap}G$R7fE=fO% z3Xtj*K()LQuKvsm$K=e{!bomsL!9w9p0f=NY<5dGfSqOy1JUlQYM+h*KVk2k9lNC> zkC*dc%u=7fCW{y8#nybpnN=g*?*Nrc%-%)uHEf&$PFZ784Ji@P|$U7A1F z?gNA!3?AP(mp?$t%?B{6^tg>x)sdSl6$F~gB2TD-Ad8DR*jeV6zA26*u^7Xpz_g%q zt9dz|bHN^{U?v;n1tfSol5aH$$!{Ak6po$&KImQt@(6hv7RAt|d|A9KZINIbpV^u~Z3&a>oIrmhnYXuEnIOMNhz< z3m_%L3r!UVlk1umFlz=X3vLW`7Qx^udAi=Uim*UxL%a{wTH|HRNG zHWN1Tx6T>XQ`#GHa*O-sva>f>8owfj4)t1D!PDNzd(vn(8EKc^E>1w^!TWwp7DuFA zQeJ#oTT$f530)Ae;D;UKN?+0);hnw>rztJMGXo&W(GzC?pG9xLj0xiOZG$);LG|w!)6k{&L+sf@ zdsSsBNXrgKF1(OgE}0!Ee|)ZmvLnw=BfD)y zWU^qbF&3K_% zU-|pqao8+46&Fsx=}QjI*Q8ow^4~<|?_1!k!yN*LwJ|J0KuU=iMBos-O~c(0t=kHs z89~3_hfBw0GVGr2UU^-9kp63n-NhTEFb;}Sq7q;A;yw?qoInJe8?z28O7s2I`t6ET zp0oYSRRRfqhvaxMMMcrd%e$n&vYWT+>0wH?(U^B0vtn;T1`t ziy4fXZg`jFIwawq#m6R*+V#5+qCA$*Z_+ZhXmLU?WKO1hP@%9oZ}p7}ps1Vb{sn6n z?yS5tom!9_`7uVUmltiV?l-%tr|$IIT0Q8vUsiGFSYwBQJT$kPqW)Pl?5H}gYF>`8 zY950!u>7{|!+1n?^-jsBh_aH6kJxSiJ-!MJxqm<5Qqbnw)Kxbw59inahG|E(6V-&k zxu?94>pq_FPw$syLVMAm13l32gwtbb-wPuU%RH~=ZL;)~deyejgqq2ldbH9H;}#P4 zDZo!JeXiqiAd0SSYa!^*gBiGAY);f*T(B8sXuh{f1ttwRypA|hFBQYx#@+C0@qS>C zrEw~GBkSL9e4EX0$9LWuqUM;qqt=iflfB`?{%=}RZ_iAWIxK0~$ks1TdsbLui`TXG zhnRkyT@^X@^y&y`R~0yA->D}@d4@izT&YWM!p-OEjYkxh>3PprC~N6XO!Qb|$?fhV zMUPaR9PwLl3MI=&cu^f+L04EJ#DC{)X>PWY^O#Shc4hZMH9w14 zNG%=v=0r4|nsJbW1aVB3+rq=q*5RlhSZp75I4!7mQx}?c+erPz#zK^Oeg{D(1B_mb zVf^KfE?k5qUb0Z+6HKpu;dsngh7W2TwKO7|mR=1S9X9ADIl=MjqOD>v@rJ50dL4Q?~@~ z)O~*%bf2J+>C)tBX*U+-YEI?it=f1D=CJqKe*Z;M>g@rWqgvCpgujrshNjpl&0V)d z;kcCDm0j;*U7UQ}{(1peqO2Ncf-^J1A()evbI!J^Hrg|be=HBMx7DW-1?58Gpo)?Ow0z>2;T+Iw%w+g?bhk9+F_zylE-p*{{%pXPjYvcvxy{ zoi+UN&;T)>@_0OAGZ%##SO30Ac^vpXIK%7?>gAbtX>H-U-GLQJzhY6Zj%)aMO8MCo zqP|K0T8__e|Fu=^OVDL^8o0V}aH(Vvnu=LC6!J)&T0574#?~U0&qEC?Rpm20L(o&7 zQ_GOx1bcq$t6i(jHKex03z|2~V$JU`%3+_`*AE%8SR5f25k=YQ^{oS}aL z3J3M^^87A#)8az5J#sH7gP>mh^)wO0lO5afM5x>gX{ci!63RJkrOv2=(NDoDxz!q`wfGqv_%8&0N}>p- zJz+3eOgEQ5bVP(DP-WT*#3he{i~ksf(MqvvZw#n% z3)I=TB5NW+fI{u9zM5zPY)B35=8T-4*Rw}vT&je>2s8?r+P5HCOAiR$FZ|;2+iuR% z+Hf!Qt&j4B)f%XRiIVV*fpx8E((13Ap_4Z|8~UVNBfF04svl!*bz7QPhebRUL6x-+Har; z5#9$qbVKvN*t4leGM%@Kgj)F3Ku4h9w_)P8ajL z+?b#1rtO_VS1;=Afw+6O=aLUIsuuHWPg}&omveqCd&?sW8CtJX92bI8G0^y>p@dVw zF><<#BwLjd*r|e}SZ%0^CWU6af#eo2eOGzKb@h6;$BoIf$KwE>S$dG%2PPr2xJ(_}@y&{L|ctYnK9?P4w| zU*u^ipD$+Lqt#+k&I|26puUI<8_Tv{{lUR2Y(3^ENgkV@%Wd`&UID|$Pyax^TTJhL z5SCY1ao2|Xxvp>jV${cnLOm1rIz_&Bk_5($5t7qjnO`@2z+4N2YtEc!a@?Rv5>Yx! zFzNONE*@^(L=*u9IS7dXwL<`4lX!cmTN{)iQh>({G1y_8h2FLfE%?6&y$9KHgid71hC; zoiPmF>cR42*?%TY#D1Bcnz#G8l1-X5oR3XHHn03@DtRk15MQPM8-1_!;TDvv`LWKM zhQJDAc3gbnFrnfyf%0=XFV`7pYR0al{|Drf6ISbZV-+GDeD>0`BGj&;j-&iSE2x05 z)^IclzUg58@m!Y)5Dz}NH-;UHlk^APal1) zJ55!Gc=Dhf;P5v~k7yJW33yI0=oN)^NdweE26^VKSl`7&JN3b?jr_aE8Y#^TBBSdK zbq2j^ZYS(R*pv?AA3v(ftT$EL^a=4nGOmCK5L8&3UqSzpSte)1uMDa9c-* z$iL)k1!;KnD%lrgdgZ!Zxxd`O*-CT0PGl7~+;P;~ zD{&^-(`J2hhF$-}K?wJc?-07}+a-XFysZ3rj8uFVG)EabtrOgMFjb6!)Xzln&Uk+j z;KLj5wwV1xud_K4$fM68vrI&GkBD=JEP&!;zRFvwZA(F`SlL+4AYTOg9h5I7b}Sm?TMG)XJSCPJh7M=D zgS;k>^bS5uwp{=N4+ha+L{Fg|tV{uIhw!0&EMU&*f<%<5Xv8UqC@KGFI~cEg`J;nP zA%xXsV*EV>F6bZJf1Sn^zV)6?bBS6Y=7k=)c;QU9DB?UHHqE<1XSq?&=H`RCo9p!j z^ZeDIxI77r(TA>j$OrZq`bFO%OBKFd_j=yOwZ$hB7Hb?K0 z*6Y*>V1B}YaQ%R?%O}opgeyXAO$(~l6&n=kbjmy&{ASelRU7eYwJ_Ds`PcOqo~jQn z=b&2CVe5Lz3UhO<$IBaJNa?Ag?wdrLkh`s@aXAS6&gJwx?Z4!f`f*U813bjN#J5)j zNxeT6zOi%fs^QmpF09VxPDA*1>Q5W`3Fel25z^kEXwg_Zf&vW zN5uwZk`nQaivIYeS0?6E`WUme2YfjG@PGZ@u0P_6;LmDXuL|fBB}tX2HF`FJGQFtC<1Wo>*SREcra9bsB(_Zze3oe zyXf5jh(sjkLPD-*l-u=Uk~k8@dOn-?dtEnE*V~)>&fxDf`C;sKA!a1?N$4C5a|1%y zmvLoc2EsO1ukYmrJ2DX9C*lzyCx6bXn(>K&+Awd)Lz6Zy!O-2nFo-r zm`=jtCBud*Hq2(uLV<0ujU!|Z(&s|E@!AH;F$Il1#VYs#0F$4`8ky6htEnjqU{ienc7kZ-BWetAcPUw7ZO23-)n%yp`%~a4yxcWjL_!3NHgE;nxAcI56hO$;lZycG6%u z;GRnVAyR*as{a`xaUKZN=yduRv=FbFL*H-ne|*-9|8#ZUG^OB6-MG?yN)Y4;D5UhK zauRonXX8u+zEe=_M;!6u$X)@~_|DAg;WWY2)+T4__l=2RJFc6N3$7#tk=1+rarCI5 zDxNRx8JS}#^5?xg25U3qSG>90!`D~5bFnR-KKx9fYuOGbac%X&pV6tK&BvTyNQ&kD zpG5Cz{d}3Q5me5%M0rK=qxE=aDtM~HS1oUzf^Af5Z#1J%q9urtsOS?Fl41|c&scZd z4T9Rf?74au_`u(cvgx)lKs?u?Q23P$jVM7hMd0r_nem8gVHEKcZ{-f?+0(t3+=|v_ zVJ)_Gq#FrFRuAcpmz7DT6+#W01M5FB(P)NPop%8JNCgLCr0eRL(S2wwn;D1-vmqj; z_>2X*ARg9q*Ly9j2NZnrvsEZgbH2-$Ker4g*MsdacBdp%rHfrR8W9&hA0HAFoG2$( zHQ_-+AaOwEN^$04AL z2!)Wt0<{xZ!TKa*sUB8jrRLThB_?Wf1Xx3K0QCe2w+B8M1u>>HWLOlXE(ZvoQ(laA znwL)cj!(S07$Uzy2tFC?nS5vNvD+FEaI%Ik$+#7>Z03`5T+NlRagx`6To0-QtYR0P#9?<0;e<4*$I$9+|dR@E5Cw zeA2gX?UA|=nO5Nu>1Ml;yryi(@2n+ZjCH!xSAeD&>w@KZd%C*`Xldd^r$QkeSDR3D zO_%gR0Aqcu5O#YSwFJj;BCPPFjU1eROvrthpMP-v=5?VT<-odNpGVq|TRTp8$RS)w z`i_D^nzO@$(j3w)+NbwkO=U9?^dPADaFG0au>!GA`9h?Ir z$)gXX7IlGDSr%x~GRTCA)vUfD48G8emKNt*z_d&sWby7A=QpAhZScdK|0|o2Jpg)8 zX;I{i)9Xd93&|`qRMAhlF7X64*3B+j$M5MJ5hwXV5vTCpuC1(^ubW~K3W?+h;(HQ4 z6K?g>gQBy@cq#IXKSGIB^=WhQZ;|n6$%Y{ccIjkl8_4;7ZcVZkb!S42rWHS7_Ib>! zfAv5k(8dFMLp8)~qtcxSs;NxoLHi*7GmR&7^gyW9q2=<$s{M27E!7a`|?U>r(&q!Ew{--rBPyUo5__lvCg(DmWF7F=(Uix}DaL*L2|5d)bxH=TQk8c37o;sQW)W8_ zP?A1a#W;Tsi<%id3k(*Y3N8LvYsyct=u5#172(ViAYOwa1)}l z;iGy`n?80pX5phsz+w$-nE3V!J)-vXHwWt`26?^EIcL(zcHN1J77=n*SrBS~LSF!E z-^01UQ2-R#l<{vrz6=fce^2Ic_ilz-<7=-^`vynd`I1bcL+MvA(U~xVGr(fWa@E%s zN>GO*4QV0CZcMKRtg#Hej2}95vdE>>9~OPbdmWg$SFKO~`of&K8UoclQkvA0vx@h* zEA74<&UKi>GAclkc2$NIYEI+|{<3fihF^jo_HVQLg|FDKX7@Ygu<4E814n^oYYJZR z5gS$lAc7S2x(LJ3pybJq85QeFTjkl~5$d(y$|6zn$V)o^r;a9rsCMh35R32=Yc^N_ zPYNF{i*j@WGkk30CXES{XkG`aCa#=9Gozno-V&|Zenc_RsatPqPJE0fLVJ<0ms-aI zdX{yZTKWL!mNGG3rJcYR61Aj0mi!x^m=J z0dsJ?XyJ`!eD}w|D{RHaqRM(@LG2{~0k9I%yZv{r{F)yeq7-fn^{hj}0pm8fXqNXW zQ^-#fSeoD#8&;qH65uy~c=gfbgdT({$V zjf(NG95$D6?uMri3uNVejK@W~-|p4AI7YN({NrLX4b*QhSM?+;tKjjilVAd!mU5Z> zbp;2&P9dD>(jw1d4$FlBJ+1p@5N&+u%3!V_o)fBXUG-JK_XSGfQ#uI`w`!~~oGo^F zGYm!#o z$5T7af&>O<(+uK8m!QFh0RFA!*8Firi|^@YhWT-hmrhNA(6 za8kt~D0Me5puGFvne#R{xC_v4E5umGwy@^spY*lWM?L93kr3#ahS_&p-hmi{RbAJ5 z*=}d-xNthO6NecVv2I^zZD`7@+{lUf9m)1PxiTAPV0~XrHEKOToQTCjXL9Hft1vZ} z2^-(tt4<=!rrO1Hb5@1Ui`WEro(a~8f_<#}z8f5BZe9&}^zh*$8_Ws(-b%T38$;W$ zbK25Q#xII8mVM?0E|T0tG(^*sU}GI;LGYf2TEH2;LLzsitS+a-K;$!4qp!{t<(*oM z2syRXKGUsW8Yx)7xT4?_WpndI;8k`HiwR>!64)#^X|I~hEz+Lu1@8T%blld*evlX} zi1C?^gb>8pVOl)QKNfBSFkKaao?-qU_^FuoQhDTR`~o!i{$o(0^u_#`L2aoh(3ax8 zdXK-fR*f+Mhw#gY6op%>y^ zfJ3TqQkBT{OJm4z6&%weWr){40LxbDfB5EvLj<_sqCD*&2;60eBg?`Af+fvlz#imh zrfr|ySzZze|2{6r*a}E@mJEU>+k=++C04*mPrEJmm%(o91G2c4=r+1x?sYL(R$Vba z##6qq^~AJVYr@Bv1}_H%YjK(GN+}8d{vF>3%kX;}&d?JZ-gRth9#1$|Yfr`&r(&p& z%LFPm8squ7RFC_4!TaHF+a|v><1H`Ocr%;pI$4d2ds6M79AXmZk^(!&T)8|FW^=Cc zU{d1s3_arIskhgBeH9(8A;Y@`L_%sAmu+ve4D)8<7K*jkpOT1~u4dlD@60I98`<|u z0xVesscCJl3|h*?!YdQX;2rO~Cr7;Ci}Rctf(pVHzAa`Tz&;)cq{v8yhwEydNO*0* z1-TEM^&jhULGT%2EYZZjXp$z!j;lWHHyL-Nuc^5P;l_}kptgMsehYZ86dS)VRlFB$ zxi6>p=C1^6+>t}*`8K-~Oe#^<3?B?7?a+?*F9C3Ik#RKql&8EawGPL)74`mL|IwtE z<2DjzxpVKEBI?g9n#CF<PyKk+u7~x7}o5)#5k^yTNR;1Kgd|P zx~{~8Up@X8$^f~(d+;{jYoK1^+PkGI8dZM)%+yp-yXM~R1clIqBtHSBxhoXdi(aie z$kTDKEc`6Vs?4~tYzAzL=h+JeGF`EHc3jt(lllpn_jj(a`PIAL*sZPmwQwB*j^g81 z$37+$D?j48-)`hEI2D0gZ1N5kQZAtYM3bMq`EPVz2e^!*;-QQC6(Jr!hxd8@E*FNT z1$rtxFKSoF(@X93GrqT=0h@98b-$Efi6kooBlg9weI5r!0MOJ<43;R$C#e2_7TmJK zvAb0;VoG2|iFk(=ALYGLTG>t65JB zc|vgMjh&#Q)sW(=3!uk5MkUt4wqr zu5c1}tc)Rx zjS$KEHTyv1agmce!=ifE2AmE`?CG1e42+*=QeM;Yc3QAh$R9CwW3m*R^YgKvnR#J| zuch(a5)1fHjXeJgu=+)_DH&=GXBU}5Z2uqH-aD+xZR;0Z0!u(qsv;s)0SiSzinO4h zs5Au>kuFW?sMG*40-{vuB2`g(F9D?lrFW5%&;=9_LWz(NNJ#E{vFyFq+2@}7eD~fz z)JH{3GT%Ap7{4}fh9ATK5p~@fPb}A^U6;cA!I*eXOqe zNL`354DIM>i2O2dW~EO@UJm}t7!(Ro4NuqzqFhM>CthPv8@NI~ARr$JQ8AT}{PJxo zFwN81-m;3YAuwlTggQVQ30w8LWdgqqhZ|s)((PSk@(cO!!<@-oj!$`|pBrBoJ6g2y z(b{*FvfA+EX$QBwr0q8y86Cjpj`Co2TGOeZ=TiJ;OA2k+&vf205L005;O7J$0*vQw z&;HHUP3@DTp_5hQ$v4&g0Kdl@8A&=&z{L&o-&PL9jk*R)oM|XNi3|hEh8(<*?#{*U zk*e*nZnGZq-Ldm5iZCSQ>FMg^m`$4UZ##>pQCPG81Db!5^|LfLEjR@Rb3me-u~oO# z{|8VDq-Dz%${1E3;21j;+7J+T-U`19=Ei|Uzyd$+kaKN-dg(rJbQnqx+*O&iVF60W z@*a-*TRseDe7_cqa`r00)>G1fRPm|pB-0THVX|VydCRfvKJoaWJ{`9(V(GSzA6(Tr zK5BWg!}QFu&bICdEzA90;$Z=xh)mG(JG4LGCUJ>sPoAu(&0)CTPaW~pAxqJX3J({I z#i@k|9zc%4Ac&#dQK#^?Zw{!+AWpa2yq3sVw9#nu8L71?vi4G>Zmlj~6WM4J2=BSOt^*k2b>3!nn6B9!N zJnhG);%&^WLoC)q1y-QIgaJ_i z^&ffoC!b)a(FXNm_f61KHu|z0Vkhm2Nl=BV6KT*OMw#8q%Yo)+MX(gM2wd~$P)+gu zVO7nK1gVge5A@ZBBB7(AIR^OrH0}UE6S6XI>3#uF5p?N{@hpJRNrcspw*^+45U!6p zE8cAE0$RvbFI^*W#^6?kBs5kEnEk-hGJ)|I{shLNF5Wwe{;ki>f=18pJPQ4RH81T! zkz$D|tmP(Phr=Bg*0jIZH5PQ(-BC9+Q5sE?miAD!_B={AupF$jTQCW;fT*1#9E!}` z6W0GaoHn7?XdWX+U*kGM`*N&SZJ5_AFu@B>qahcWV|g|&yogXvYUD=VM@o= zUiu~@$Ey}yx2@DZa$wnBfBAYv>mgk0)+iCh=UXYC%t#*|eGtv%GBm+~ZSi*vbC!BF zD*ODz^b-Iv(7&uh3O#Jk5nUTO)vwnZ8E(WI!s0a2d;2qDOUqBIOJA==$`*i#S09HZ zu;~fiD5{!??x=0qTkWMnQ%LuT_OGFJ?_Ks+i9#i?t(*#QCXfL`lk!ej<}liZs;_JN zS8Vh?c9t`=Vgxm+>u&-{{Uj9!f%pG10`4#)P&omu=h|%s>ha7zw!AMfdN2CU_p^f0 zITk%^Tu5j8xE(~tANII2;8UP9T5p&&N5hi-x~PH1>6QextonRnZZ**lw2ya6alA-+ zq~kMNCbOs#l!ol_5#J8BCvv(N2I1{&^m^mbED5WH;VChZ4*-$alY768j}@FH3O5Ru zMz@PkN|q%HBqgk==b9+5O?$(^WfF0!iw{-4<(CA=$Hmv8f^7ra5fjGeU;%?Nq zqhb{7cE?L@0&g;2KOJc1QWKNHCa!AT`aEIhBCs6%_PE4(%k6!a=KL$xs4wzvo!_0Y zCGhmCu-q^{CLE^qw3zxMFel8Pm&VGUZnG^mqewU7ah?ZzkUc&OGAqGM_io%9DVy6W zj6mzhx7V8?%y)zO;^^}|e@j=^iInfndK=<^Af{p8W*j(~KOMrSV*p@}6?uxc^xy=U z%!y{&X_;v`T@Hn?$J-^Y|4q^L57=Zw5~XivC=zLoZ1{ zWe?mB2Ka_oOI4cJ)KgSRUp*HLPkt}1M`XsBnOt&C^)i|3A7HH>6e+5b44I4&Gx?@v zoIMM2Qw)}p5FujtNfDAxB@|#ll!Fcg9sJtJbqj99h>*b&G={Q{53wjVI59GMKTicu z+un$B?gwN2awKIHGo=U9x-4sKe&hsT-XH-Q=FIlbR529L8uBfy-YB5?O4owUfeuxe;*BZ6By^tz*{A@^oN!td!EU zyh&mYDF+IBtj}la_!F~nH0>@_tsu;wI!eF!FvXkyE$J23$9Dw&quGkYwlcM)YZn7F zb(5qkUqe|Xs$p2^mH`2C>goKvWMqVZ9!i!vm)^v1VGxkWC3P&$E49ul)oM+*w<|hq zEJwrF?lmVTSlnDL<-rbca;LNdnSE!&rImKnZ2BDR#^g;({Ul9a0ltM=-JoPIB#H#| zi!`Y`K6vLKrIy8UUFTa_)5cQ+R&HtUc1m+kzGhTYr1a;l%!#WbCh+13N7uzdSbjFH z8NYBZ1pG}|7|CLZ>btuBz5he}DWlyGSCq?Ti}%hsk`U(6JR_~*G1rsI%fH{e&Q}&Y zIVs?`LV(W=pr<o?c7M9*io@!7tsJT)@ff4nBW3= zyZC#G#X-7vi%?LQ9Gx@!JoqkDGq$$o=oMjzF8jyB1*Ze)31?vQMa9k+^8laJVm>Ro z<@aphday`Ldr2jsLX)-BLB?BR*Yh9N1dX54N_RxeoH-P?x=H*`@ga)#Ss2 z#R$}j2by^74Q*i5?0qeh9@h|=QYWdswUJIRs#3n^r}Z_(f^R7renhpad`{+`Xazwt zsX9(Cg#^5{Jzm#|4MihTI8i>@`y?zVm3tLAUxt4*Zndo)iJ{anA$53Y>*a-Aj+EQy zzEjGn3khNolNhpvS&9nz3Lea;EVLLP=`cHm?G0KcHhV9Y-?O!p((+?++M=36T;X9 zp{KjJUcZpmX9&3U5uCVf8sK`17y9=)RmX08x{@8~Pkcd$ZvYb3^oZLY5*pKh#I=hk zqLFTjN{zD!xZT_^bUAkdw9GX}Fh0e>C4h1YK+A4Fsx96?qh>eWY@}c5wZ1+R){yq_ zt2#N0p1(pr z5aiP~Ez6~h+w*x}n%_v5Xg<0e_gjMC>_r$~DxfY0XDlynbJH!hhX`?|b}gEmntE^Z z{kv9G*IE_VApUBN(QG56A9717`AFF-&5Bs6=c>=X4_IlM9ML?yPu2OUt?Cp;S zg*m4Iu=zqrxa6JwtU+i)nv>~P0F7P+bSs_V#t7(JbTt$Kh_lV=-kK`3$KR3v*r|4u zZ`@2y(&v{}@r{vN_h=15oRQwv4D-hg9we)1>&(vHvXhe{YV!0YJQv+B4FVIC)~z+1 zivx5B5=u5CU+i-lOB3&XOe3F~}m#m?0t*g7EGF6*M*a~c@-|)n) zz0@|dwG1&vIWfp#divJ5hlO}b229!~#Rl}qE3j$7Y(9_-*;JW??FT6e-X3pNV8wNn z`7e=6o5>Xu9N*RyY5H2B>M6RRj7i_c3srN`c}vD0>y}s#qdnR6#NYeUqebGLQClg^k5@td-8}*==g~cDlx=7@r8ft0SY@PU`~( zsDQgs7R{`uM0Gf6#hwU&o}vRA84XqXR-p2W8h>nf9jf@w-12~B zfNc61dmsRA^gnE>0Zwb($WB-_UG_aKEp0fyAeG69HMbh{8sV+Ai6FC+R|q@6CHu2g{LdZg31RseQd8D*-m{4{n~OokrrpjVr&YjbCdFI>2SSql~2;r*+AUEbeW! zqBAeLY&)<*0;64yTqnNU+=*hxoPb469AyIu2UnMn5qwKbnCeM|Yc!c-PNG`{tuO$) zTC~uBq@b%yd!$PgNat5`EFq&DH!HuLgq&2f#u1marJ%ahd{sok64fNWp{RyYhLlD* zW3!b;gI!9F$jmuDSkDu{w&Ka^WLd?7Wt5^58XW|rMr%l$@jLG`fna+cym06U7)W+Q zBtQjm!vEy{r4lz&taFX~Ll zjE_xfU{)CMftMYS9@a0a!>13fOcu>-5U8!S^M`5m0H~z)W2`Q|0SsjtI=r)hX{^50 zp4r`P;~4y=$wyvtoPcz3X~=2a%0_d%tKGEyiE4I# z{Q)bJPpR$P#MT1~5L6j|`vR~4++hdtZ8M9)Hx^DI8wnstkwU*8Wci%3R|RuE#dt#i ze5O`d%y1tA7LxB$h9jLB!+k7$^5TcsPK}JP2I3`S!tZ`?mK!`Wf76YQ(vR}0k^`fp z2A4QuhkCZkn?!u2=nsHw?s838sUPFv=Uj{L&UknA=A?FqXYt^FczP|{pL9%5U&(ou zojtK7!Y{ocKeDD6wPKr>PgCPQ1`lqn3_Nqhjzsb6Dj#{{{A`k5+1Av{2r~yacje3yc%0|Kwx_I-aLKt_9DZ9HOrsB zt%n2{nq3&PE7Kk6HQeoKMstop3|8|;n^o4~vcevv7TcJQ`g|TTzJ-2Is|Db}LC1dABp@%{Z?IkGB zfk5dbOk8xRKmrs~K#2W9a}~e=|Bz_fpLPDVb>$5_S{Otbn8iLB(Y-B(mPi%H22dlx zo!j_~15uqjO=e;Zw0+?g7FWR@z8uyt(fMdzk-lcx19K3mFAG!!d6zw`0pIKtt-nG4 z1C*LCdxnfB5jY>9;bq5q+T_P)U(5(oOXEYD%6%?}xbR`79NpiONBp3{SaftXg|8}k zu(gi_Ua(k^>C#9Odwtj2&Y%-YMAOZutvfXUR6Mo2kMH#U zy&PDnv{aiK0ap8c~otd&=l!An*l10w0&!19#tohDqeiwhnb_@b*l31Zdt=} z4JqF3Yob6ik@oOl-XE5Ic*l-POg5IcrsJHB=6sX^dhi|p7QaLxV05(9${<>xIR3R= zx|FqvV>k*0c%40ypN%dY19a)Tb^pT8AL=<2z7<%FYjKKJQ-V%Qz&5$xF5@JA!R56*dL^5srbeo{$eBFzH(cEmd57-#bR z&`-_#pQ+e>JtX8L6Lm)8=CQI?Cc2TMoIIFQ7}XAODKjQ5bS`ZLX)4OoTZ#`WnBXcw z7;r|mjP$mXR#X(bb)VPGkrk;%2m$GG;{M3jua534f%wTo(53>OKI5?b71N%tBcph8 zte5)7sf=RGAYYhi_0Er9Q@t;CQ+>#q(>)(v)pxB*D#JZ1JSRCs*mJLOx%B9{W;!mz-6o zcU`xqSyhOj6DG>-_ce)vtq)02KUupjfgdv&RRC%E|MUxb7*7qRt&xo7hKII`olSwq zzAwtSc>|1c)sUMDUMHqpN_W_CA{>BGBFo^BfzYtbED7V7WQB=|QNV4i9RWLKG*jYF zoIw_d^Z^CcOgSKf8=BZw4<2VH2?b)OV-oiT9Fzj`K9bqn z$;}H2QJ`ftp5RwnyMsoJ-~E1Lr1Y$#xf~;q9vbgsnC`LJ##N~H@h>n!Wf*HhG=jw($UdZkQoTq+AlW>zlsv9W4R|PFD^iSHTck%b; zvN()VA@5-y*Cqx=)4WNfV2Pd36LwbC@V5iHgl$JHmZ~?7_Jgq5L&w!$LwR4Oqlk?z;NTO3=fHqyVH0m&r8tHv>SB zr*?zMKt6}D@M&Z8F%bjm) zB1(TL>14J$*_M-)5~Dj?>73AdZ(abw#u%4uXF0dDp`GQ>xK=(FjCivJ`}j_%{>xo= z6cj_)VxcN&cvcw(H?LNobw9k-8Wmwp?%l&+!rD0TPO}xCNFrVTVl>lp}dB(@7!d|A+bN0zR&L|1aG`s2lM_YiiOn2x=R zb26NjuG}zIFSkoT!8E&4Vocj^-GsymmM6@aSQhfHGO-r>U$u~pv`_ruN;nxpJ~$(y z9Mrlxve4M-ThHRWm11vAk@3tK`s58E24Fthu(s^aE&5v4espl_kZeyU-e+= zu;K$ctB1S6LWarI1S!+UMeRMXkC|T!_ho+)^!dW%A|V$MdIz2hO7YLkDkq0rKF>jb z(b!p4AS3i1N_$(?9#^?_FA-cgX%2g7hFP+31DPVZqse#@X!~qLZ)|*Ou>d;C2D^%X zaz}IJ@hro&A36Hs9t8Fwh4NHhn=uf{?Dx+he_UW7vc0J1xC``6ofm>%f`yPX(OONB z?iJbC1Y(9{cW3rCGfvVCDFJW+>4R3GYw=JjUO%+DRHDG&%)cW5dLy9%M=kMX->|nC zh;K-5R-H!C5p(ed?scBdgL;S2E^tSSN-&|yuLEGP@!yJs_Mz|&W86@3|#Lq=Gf z+9W^mC2t52`ePs+1N`<}zdSnOOOgle0D2;X**Pj|bw!@)+?#z7Z$GyUd}ptwfILaX zG*6XQON<@Lo~{BX?HqGySilfN@pMQRj*BXu8j;#vBKpr@0UH4Tf<`;>#86OhQo31$g$m&Z5J z#~FMDn7>Z9dG&$Y{J)6~;OAn8o4Inf=*K*RcP4Dxy+r?b1~|I-ABB;cV7$P(U`^f zREgn9`Wmi;2}9khmXmdC84HU9j2zM#L_2Y^-yt=ZbLMw+I0z7J#0EKwA`$^@W9~VK&lz zp7r_*+#yqgyKgd<7tUGq$2uHF1H>A#1LQ2_1+^V@d))uF! zcS$yB0Htkh;<|muexn8D>Hm}lx%>6fRryTc-M4k~^?iBXAg+1l)%{zNLkGYVO30Go z;;rCKSQxZKAP}o{n3Yrm+7qd{eC%7wen*QXb}FY16FG=KUcvv z?-<-r5&SI5NfNGK=3^8lu zcOSb+R#T5`7V9Je z?$b{+F;BQ*ySb(~qcz<=q`s&LJ;$vQ0AL(vt!Yk-!@6QH#x;n(MjoaKZVBMv??S**Ac|(-P=wy3s%YO7cnacuD1PlMP zaBmOq5ptF;T-$vUTwb8+njjw@)A-T~#Y_Umqf*FN0BmKeZ($VmLiV8ebeKShNGuFo zKahpXo}Hgd{Cb!Eycy>zu~xz24bXZp#jr980erQUlyeLUbIA#PBy!hTX&odR>Zch_ zPp*ZfDS&s662U(^MWA*y-z0?INPn$xHa7)Z%WPGuw`U>H$Onr*iDRy zpyAoP z_bUpO0Qdu1@pUSKnjcjz`J6`w;q>He($Ku~ZaLehmQObk+iM6Lot$iyvM5Mzz4c!f z>ALeX*M+(S5D9Ff@g;pn#-)aR+CX$UmRG!EpVS|p1JVeV23w&|-A-;{AQtcy2%?V+ zbNH15#}A6x-WDKUA119|9MzfMn9IpmOMGUl3Sx!mpig+dRT15#Ljp8HhcW>DI%xaSLEc@tRomZRYLVU60LDBhF)Zh*C8GLZ zf_M`n9CF*Ax)J?V(S!)eDCSY!4XRsbTTansUlWXd?=b83>Yir~xbXJ(x3H#sfbI0` zjbMu4(k8ig`CSD1C;jU>Gb+*~f&bEc{SPiu&i2LUKJDYIvE4gK0;OYLYM>#UOeuHK zhfMg{Bb>BJ1Pv?K-QgLvpr0vo(qO5*t5VBzMtaAkFmft@^oWnrUO|*DP)R8j1G?l_ zpu$UjHr`4C@dyY0xoneNLp+=>5)S!15T44BVhCN5|7N=aO3UZ3Bta6V)D8xAbig4% ztq~lJJ9M{;x;VH=*{|096}98%uT={HJ3%G#mBX)GBxoK<>!BZ%14y%akK3VtMfDw# zdOOm~i=2Q~)Zu@(qR>=u;ilCJnVeJre@iiZWcOR(0MyfY$+jY%CATAs{%@Rhr$|A^ErR^I~A0& zD!Y)*A&FA=i+{7ytdT^8u46n^;vQGuIqa59as|GTy;{Ngy6yIwLPwQ)$8=@YT$vbp zk^?L~JtQXfYHhDzfBVZr_ z7vB4*-{n5c;>wp9x5-L4bd6r*8MF4Nk)jW%x=B|rl@_eB)XJjM45Zw~5hGP$>Bw_Z zk7W+T+F8ypo&$9g>E21P2-jygu4u&*(NhGOZ}M*;URe*&#Q80FoIcgS7YwN1ilfEV zI~?hi{093U{I%~g8CyjV`g_jIgVkx;C_Yw|mIuD~%NEzGmZNKrK8@EOq84ewz?-BT zJpi+@!88ld@g5Pnk0xg(8^>pdJZ(-R0(J{-1|9h_H#!hk^-?ZI0_HkNkf&9;nw59Ham#jAsoXI2h`a_W1xy_5O?Bfso;^y&7SORxds$ zJ~qje25+&LJ#XMF_*Kf|_W$_zh76u3#M`g3W4oEgj+GqP2THXKrUg~Dw#HXWWxzIY z%G^}?PaKQp&z>0g=aX*TkjWb5*9`c}2Yx=b-Bgx7dF?1?4Y1Gm(6>)ydahh1z{Ha< ziFm}1Mw8(0gA1ZTD`-LB9YT^a~(Ei67}dWBHa#-lYBW zu=v~5jwVzR2G}>a9QVSMRLzI&EX&tDA^*mKNe)cE=w+ODmtxvo;w1H#eJZBqFh^0f>Qi(gyVFh z6GDbXAY#ZVFrmFcZUpI1ecIrXsJ09yw9hQX1M=Ah=(5##dxDCX&azj(M7%_dn<1u7 zoUQ>lRO>BJ7`_(qB|OPGlS(=;K1Vi{U35AP)v4w@}t{~;wp6H`Tie^(VjLevF8CH zbU#8=#O+|cG|Lj)_hMwLQDA< zfq#pI0k`%+$}K_061gOyslWWPgJC>FHoAdi z;DQMHlyq$Euu@z_RT6eSH`{6Z6F(X>GlR>;@yPC==l}4frs~}QZRqM+`!(ekpBY(z zI;RbqrJ&R50iAmn3Z@thK}*WR$X;w{&omhT|>@Ai&_i2D_{4&XnFse{GCR`veAbpT9F#Au72WP|3Zr zek!BP8~z>sHPjK&k|lo3m(ZX?0eDlq2bN(#>yXoJaQ}rYur8Un2V7 zQLBsL8*6d(3YTnKE6@n5a&49Q9e@zhvGd*3*dm%tZSK8XE`03(+Js_!A;o>;n3jvl zNA6!_u^J$Y1Ck(M$nbv!hHd}^oHAvzs`}+FdFOci4BU&8j~{;e3w*@8DnJ(rQdGsp zUqiR!jC+9z@T^6?U@~OSX$IOZ4@CwC_L=F@BJ{8+f~^b80jtg4-jxgz=_)t=V{0{w z6-NGCb2TP$Xz&Km>#XQ{WnMqJrkE$rb#qAFPKHN`@~M>L4{aivcuMZ!KeiHU(`U2v{$A&btL~{R;TXhoow5h*8zmEFZgaFdsv)0*X zxCKafOk3f07lXD3y}vQQQ~zlmj~*QKmZ}1Z^6%inEULmJOGu3pz-AFc__@zI39G*l z$(O)u)p^kMImkR4RPCuP3QKPuobK_yZUL?=T;W&6yMV;vZ9N6i#akaQksh%M2UhdH zLe@)MF_q%?o%ZpZU%X0z2lUNg%GE85pw^5Z{U41fCZ4oGdEHw49}TI82vr3=k6#>q zReTD+vUxGe0;rMAo*{ar01@`T`IaaV0gi#~M}cdzev6Vq%Y@9rxu42GKPH@^a(-2i zRMLp&GiOKp?Xwal=um+GO`T9!(%?keASx~VE|Z%y$i^px%Qu~|wMn0*jWX7Z&?h7R ziwhk@4VQKoKA}<2#93>ABVNk|>akU7F9>#UBcX&K@F<1><)@P>UuG zfK%SaoIVcN-6mo?A*CrXB9NrGzA6~|lEp&m0Txvils^)}{pe?x3u-WU0C(jC$8gvP zYbuzy2ff@bZaTJA;C5g0K$R;cXYpXmmDDf3)MRL@o*fg61gz1}yjXlE8<=I8?WW z-CunMm&(3Ybhn|Tx=Qt~6!Y=4=B_oMlh4;7UL>iF-KUan&>GGA0q9GlS+ux!6uSom5xk$0{$5%-(9&4%1Zb+|aYI*r1Rz=fY5 zoaH&T94H&V7j`Y}hF??z3axjDWwk%h6BD*%#~o0IgQ$U|3RuK900 z1T^LYn0x^u*QWgB(UXjWNSGOFIu2a~yN*9j<4X%XJaDf*q|Tmw{D+<0CbHSLV}N#b&ZyCU_N%vI_1o1Oep9fNqc0KfsrnnC_vXm~w9*$pj=V~n zd!}jQMWD=3?D%NO7WKy-iVBJ5QhJLU4@$+2#_*pnAmPbMQ|Q{Yl`rXtGu~V4-@kOk zp9<{n@5g;U`9ID?Q-L(_>#H9gGf^UNs*L<&>mxr~#XfNW8;I_}22=FUcdovJNVD2y zyKTDBfHv$6K&>?!f1*^cFeGdhvobv~ic%GvpJQYo_M8BV#?j%|AWBER!|)vH8=INW zbhCn?KHSkm{}F!%Xm6E6OZ)1!rz)Megno!4HD^ot99AwWdJ=<02seMw18|k{H;Dcm znovTgJg<8IJNxbk(^Ww57g9r1p2<@CL9A6Gn*|YKHD++{l@%k=O>0H^nb6eMJj|Ny>2(MR0D1(ghD5*!&5S97G%Tc6dqwCV&0NL0LbKC7(!zj15 zy)|-BG${pGthv5=yjmos^uE!0s($PFy$}nVt5IeKNk7s*%SUL{fVPhxreg~_uF12K zOHeaNIU9e1cEZ2ExcPEK2se&dg`1Gi=rSFaOX&UXpq@@%;+gk3Zp3Ky|%( zthVPiW$~n{*3($_I{z~iv;7MF!mF!MhLqD%!3e}`I6E{*RvnbGsai*m$UpFRpDkT~ zLK|7Qx_e;3K~OS%DM)IWyhSNxkV^ui7I1U8+Y{!1yZW3~w!Tpyjau5&J&gX&G0k>} z-`%RWe5q_YT?dPbs3M3_f@yBL^INP4z2Qack#9xCu&vgiU2(=2CX`^VtWF?39JKHY zE#*X=8Ffn&gh!`%ol1VVGdv(vpa?M~kQU+@pj|U&13av0#GJN29}N+73ZOAazX7yq zF~h>E_G^%L_E9+#j&kr#;BK(ck%_hW+_(aM#Zs z;=!D$oSi&uJLe$|XnDh}wH|(MvvZ1l7RLWBK$Y^LH7!hjzd%OlF`fdCnX*=ouQ-pX z8LxnYd6(c;b6b5AlMCn;SUP8LAZiXOKxI}~>#?0S7IUzglq-J&1J^Vf zIF^7ffZO^&RK6-L)Okc%x7igaF?)FK9M~?92|56ymRutB%BhnJHpS?YYyNdt{1OAm zmxGZmPl7>7zy@H|MphGctgFj;#XM-_*rD?G0?$Fkk6+XRotpAzP)aHPDw>d