cutechess-20111114+0.4.2+0.0.1/0000775000175000017500000000000011657223322014410 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/.gitignore0000664000175000017500000000120011657223322016371 0ustar oliveroliver# main executables cutechess cutechess-cli cutechess.app/ cutechess.exe cutechess-cli.exe # test executables test_board # libraries *.so *.so.* *.dylib *.dll # qmake generated Makefile Makefile # asciidoc generated man page and xml document docs/cutechess*.6 docs/cutechess*.xml docs/cutechess*.html # doxygen generated api documents docs/api/html/ # temporary directories used by qmake and compiler .rcc/ .moc/ .obj/ # other temporary files *~ *.a ui_*.h # files created by MinGW *.Debug *.Release # files created by KDevelop Doxyfile *.kdevelop *.kdevelop.pcs *.kdevses # files created by Qt Creator *.pro.user* qtc-gdbmacros/ cutechess-20111114+0.4.2+0.0.1/projects/0000775000175000017500000000000011657223322016241 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/projects/projects.pro0000664000175000017500000000007411657223322020615 0ustar oliveroliverCONFIG += ordered TEMPLATE = subdirs SUBDIRS = lib gui cli cutechess-20111114+0.4.2+0.0.1/projects/gui/0000775000175000017500000000000011657223322017025 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/projects/gui/components/0000775000175000017500000000000011657223322021212 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/projects/gui/components/pgnhighlighter/0000775000175000017500000000000011657223322024215 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/projects/gui/components/pgnhighlighter/src/0000775000175000017500000000000011657223322025004 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/projects/gui/components/pgnhighlighter/src/pgnhighlighter.h0000664000175000017500000000346711657223322030172 0ustar oliveroliver/* Copyright (c) 2010 Arto Jonsson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef PGN_HIGHLIGHTER_H #define PGN_HIGHLIGHTER_H #include class QTextDocument; class PgnHighlighter : public QSyntaxHighlighter { Q_OBJECT public: enum Construct { Tag, String, MoveNumber, Result, Comment, LastConstrcut = Comment }; PgnHighlighter(QTextDocument* document); void setFormatFor(Construct construct, const QTextCharFormat& format); QTextCharFormat formatFor(Construct construct) const; protected: enum State { NormalState = -1, InTag, InString, InMoveNumber, InComment }; void highlightBlock(const QString& text); private: QTextCharFormat m_formats[LastConstrcut + 1]; }; #endif // PGN_HIGHLIGHTER_H cutechess-20111114+0.4.2+0.0.1/projects/gui/components/pgnhighlighter/src/pgnhighlighter.cpp0000664000175000017500000001030011657223322030505 0ustar oliveroliver/* Copyright (c) 2010 Arto Jonsson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include "pgnhighlighter.h" PgnHighlighter::PgnHighlighter(QTextDocument* document) : QSyntaxHighlighter(document) { // default text styles QTextCharFormat commentFormat; commentFormat.setForeground(QColor(0, 255, 0)); setFormatFor(Comment, commentFormat); QTextCharFormat tagFormat; tagFormat.setFontWeight(QFont::Bold); setFormatFor(Tag, tagFormat); QTextCharFormat stringFormat; stringFormat.setForeground(QColor(0, 0, 255)); setFormatFor(String, stringFormat); QTextCharFormat moveNumberFormat; moveNumberFormat.setForeground(QColor(255, 0, 0)); setFormatFor(MoveNumber, moveNumberFormat); QTextCharFormat resultFormat; resultFormat.setForeground(QColor(255, 0, 0)); resultFormat.setFontWeight(QFont::Bold); setFormatFor(Result, resultFormat); } void PgnHighlighter::setFormatFor(Construct construct, const QTextCharFormat& format) { m_formats[construct] = format; rehighlight(); } QTextCharFormat PgnHighlighter::formatFor(Construct construct) const { return m_formats[construct]; } void PgnHighlighter::highlightBlock(const QString& text) { int state = previousBlockState(); int len = text.length(); int start = 0; int pos = 0; while (pos < len) { QChar ch = text.at(pos); switch (state) { default: case NormalState: if (pos == 0 && ch == '%') { setFormat(pos, len, m_formats[Comment]); pos = len - 1; // end of line } else if (ch == ';') { setFormat(pos, len - pos, m_formats[Comment]); pos = len - 1; // end of line } else if (ch == '{') { start = pos; state = InComment; } else if (ch == '[') { start = pos; state = InTag; } else if (ch.isDigit()) { start = pos; if (text.mid(pos, 3) == "0-1" || text.mid(pos, 3) == "1-0") { pos += 3; setFormat(start, pos - start, m_formats[Result]); state = NormalState; } else if (text.mid(pos, 7) == "1/2-1/2") { pos += 7; setFormat(start, pos - start, m_formats[Result]); state = NormalState; } else if (ch.digitValue() >= 1) { state = InMoveNumber; } } break; case InComment: if (ch == '}') { setFormat(start, pos + 1 - start, m_formats[Comment]); state = NormalState; } break; case InTag: if (ch == ']') { setFormat(start, pos + 1 - start, m_formats[Tag]); state = NormalState; } else if (ch == '"') { setFormat(start, pos - start, m_formats[Tag]); start = pos; state = InString; } break; case InString: if (ch == '"') { setFormat(start, pos + 1 - start, m_formats[String]); start = pos + 1; state = InTag; } break; case InMoveNumber: if (ch == '.') { setFormat(start, pos + 1 - start, m_formats[MoveNumber]); state = NormalState; } else if (ch.isDigit()) { state = InMoveNumber; } else { state = NormalState; } break; } pos++; } if (state == InComment) setFormat(start, len - start, m_formats[Comment]); else if (state == InTag || state == InString || state == InMoveNumber) state = NormalState; setCurrentBlockState(state); } cutechess-20111114+0.4.2+0.0.1/projects/gui/components/pgnhighlighter/src/PgnHighlighter0000664000175000017500000000003411657223322027627 0ustar oliveroliver#include cutechess-20111114+0.4.2+0.0.1/projects/gui/components/pgnhighlighter/src/pgnhighlighter.pri0000664000175000017500000000013311657223322030520 0ustar oliveroliverINCLUDEPATH += $$PWD HEADERS += $$PWD/pgnhighlighter.h SOURCES += $$PWD/pgnhighlighter.cpp cutechess-20111114+0.4.2+0.0.1/projects/gui/components/hintlineedit/0000775000175000017500000000000011657223322023672 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/projects/gui/components/hintlineedit/src/0000775000175000017500000000000011657223322024461 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/projects/gui/components/hintlineedit/src/hintlineedit.h0000664000175000017500000000316611657223322027320 0ustar oliveroliver/* Copyright (c) 2008 Arto Jonsson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef HINTLINEEDIT_H #define HINTLINEEDIT_H #include #include class QPaintEvent; class HintLineEdit : public QLineEdit { Q_OBJECT Q_PROPERTY(QString hintText READ hintText WRITE setHintText) public: HintLineEdit(QWidget* parent = 0); HintLineEdit(const QString& contents, QWidget* parent = 0); void setHintText(const QString& hint); QString hintText() const; protected: void paintEvent(QPaintEvent* event); private: QString m_hintText; }; #endif // HINTLINEEDIT_H cutechess-20111114+0.4.2+0.0.1/projects/gui/components/hintlineedit/src/hintlineedit.pri0000664000175000017500000000012711657223322027655 0ustar oliveroliverINCLUDEPATH += $$PWD HEADERS += $$PWD/hintlineedit.h SOURCES += $$PWD/hintlineedit.cpp cutechess-20111114+0.4.2+0.0.1/projects/gui/components/hintlineedit/src/hintlineedit.cpp0000664000175000017500000000461311657223322027651 0ustar oliveroliver/* Copyright (c) 2008 Arto Jonsson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include "hintlineedit.h" HintLineEdit::HintLineEdit(QWidget* parent) : QLineEdit(parent) { } HintLineEdit::HintLineEdit(const QString& contents, QWidget* parent) : QLineEdit(contents, parent) { } void HintLineEdit::setHintText(const QString& hint) { m_hintText = hint; } QString HintLineEdit::hintText() const { return m_hintText; } void HintLineEdit::paintEvent(QPaintEvent* event) { QLineEdit::paintEvent(event); if (!hasFocus() && text().isEmpty() && !m_hintText.isEmpty()) { QPainter painter(this); painter.setPen(palette().brush(QPalette::Disabled, QPalette::Text).color()); QStyleOptionFrameV2 option; initStyleOption(&option); QRect contentsRect = style()->subElementRect(QStyle::SE_LineEditContents, &option, this); // Handle right-to-left and left-to-right if (layoutDirection() == Qt::LeftToRight) { contentsRect.setLeft(contentsRect.x() + style()->pixelMetric( QStyle::PM_DefaultFrameWidth, &option, this)); } else { contentsRect.setRight(contentsRect.width() - style()->pixelMetric( QStyle::PM_DefaultFrameWidth, &option, this)); } painter.drawText(contentsRect, QStyle::visualAlignment(layoutDirection(), Qt::AlignLeft | Qt::AlignVCenter), m_hintText); } } cutechess-20111114+0.4.2+0.0.1/projects/gui/components/hintlineedit/src/HintLineEdit0000664000175000017500000000003211657223322026717 0ustar oliveroliver#include "hintlineedit.h" cutechess-20111114+0.4.2+0.0.1/projects/gui/components/hintlineedit/hintlineedit.pro0000664000175000017500000000004411657223322027072 0ustar oliveroliverTEMPLATE = subdirs SUBDIRS = plugin cutechess-20111114+0.4.2+0.0.1/projects/gui/components/hintlineedit/plugin/0000775000175000017500000000000011657223322025170 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/projects/gui/components/hintlineedit/plugin/hintlineeditplugin.h0000664000175000017500000000347411657223322031250 0ustar oliveroliver/* Copyright (c) 2008 Arto Jonsson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef HINTLINEEDITPLUGIN_H #define HINTLINEEDITPLUGIN_H #include class QIcon; class QWidget; class HintLineEditPlugin : public QObject, public QDesignerCustomWidgetInterface { Q_OBJECT Q_INTERFACES(QDesignerCustomWidgetInterface) public: HintLineEditPlugin(QObject* parent = 0); QString name() const; QString group() const; QString toolTip() const; QString whatsThis() const; QString includeFile() const; QIcon icon() const; bool isContainer() const; QWidget* createWidget(QWidget* parent); bool isInitialized() const; void initialize(QDesignerFormEditorInterface* formEditor); private: bool m_initialized; }; #endif // HINTLINEEDITPLUGIN_H cutechess-20111114+0.4.2+0.0.1/projects/gui/components/hintlineedit/plugin/plugin.pro0000664000175000017500000000050311657223322027206 0ustar oliveroliverTEMPLATE = lib TARGET = hintlineedit TARGET = $$qtLibraryTarget($$TARGET) CONFIG += designer plugin QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/designer include(../src/hintlineedit.pri) HEADERS += hintlineeditplugin.h SOURCES += hintlineeditplugin.cpp target.path = $$[QT_INSTALL_PLUGINS]/designer INSTALLS += target cutechess-20111114+0.4.2+0.0.1/projects/gui/components/hintlineedit/plugin/hintlineeditplugin.cpp0000664000175000017500000000422011657223322031571 0ustar oliveroliver/* Copyright (c) 2008 Arto Jonsson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include "hintlineeditplugin.h" HintLineEditPlugin::HintLineEditPlugin(QObject* parent) : QObject(parent) { m_initialized = false; } QString HintLineEditPlugin::name() const { return "HintLineEdit"; } QString HintLineEditPlugin::group() const { return "Input Widgets"; } QString HintLineEditPlugin::toolTip() const { return ""; } QString HintLineEditPlugin::whatsThis() const { return ""; } QString HintLineEditPlugin::includeFile() const { return "HintLineEdit"; } QIcon HintLineEditPlugin::icon() const { return QIcon(); } bool HintLineEditPlugin::isContainer() const { return false; } QWidget* HintLineEditPlugin::createWidget(QWidget* parent) { return new HintLineEdit(parent); } bool HintLineEditPlugin::isInitialized() const { return m_initialized; } void HintLineEditPlugin::initialize(QDesignerFormEditorInterface* formEditor) { if (m_initialized) return; m_initialized = true; } Q_EXPORT_PLUGIN2(hintlineedit, HintLineEditPlugin) cutechess-20111114+0.4.2+0.0.1/projects/gui/src/0000775000175000017500000000000011657223322017614 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/projects/gui/src/plaintextlog.h0000664000175000017500000000272211657223322022502 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef PLAIN_TEXT_LOG_H #define PLAIN_TEXT_LOG_H #include class QContextMenuEvent; class QAction; /*! * \brief Widget that is used to display log messages in plain text. */ class PlainTextLog : public QPlainTextEdit { Q_OBJECT public: /*! Constructs a new plain text log with the given \a parent. */ PlainTextLog(QWidget* parent = 0); /*! * Constructs a new plain text log with the initial text \a text and * given \a parent. */ PlainTextLog(const QString& text, QWidget* parent = 0); signals: /*! * Signals that the user has requested the log to be saved to a * file. */ void saveLogToFileRequest(); protected: // Inherited from QPlainTextEdit virtual void contextMenuEvent(QContextMenuEvent* event); }; #endif // PLAIN_TEXT_LOG_H cutechess-20111114+0.4.2+0.0.1/projects/gui/src/gamedatabasemanager.h0000664000175000017500000000602711657223322023723 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef GAME_DATABASE_MANAGER_H #define GAME_DATABASE_MANAGER_H #include #include class PgnImporter; class PgnDatabase; /*! * \brief Manages chess game databases. * * \sa PgnImporter * \sa PgnDatabase */ class GameDatabaseManager : public QObject { Q_OBJECT public: /*! Constructs an empty GameDatabaseManager with \a parent. */ GameDatabaseManager(QObject* parent = 0); virtual ~GameDatabaseManager(); /*! * Returns the list of currently managed databases. */ QList databases() const; /*! * Writes the state to a file pointed by \a fileName. * * \sa readState */ bool writeState(const QString& fileName); /*! * Reads the state from a file pointed by \a fileName. * * \sa writeState */ bool readState(const QString& fileName); /*! * Imports a game database pointed by \a fileName in PGN format. * * This function is asynchronous and thus returns immediately. * * \sa importStarted */ void importPgnFile(const QString& fileName); /*! Returns true if the current state has been modified. */ bool isModified() const; /*! Sets the state modified flag to \a modified. */ void setModified(bool modified); public slots: /*! Adds \a database to the list of managed databases. */ void addDatabase(PgnDatabase* database); /*! * Remove database at \a index from the list of managed * databases. */ void removeDatabase(int index); /*! * Re-imports database at \a index from the list of managed * databases. */ void importDatabaseAgain(int index); signals: /*! * Emitted when database is added at \a index. * * \sa databases() */ void databaseAdded(int index); /*! * Emitted when a database is about to be removed at \a index. * * \note The index value is valid when this signal is emitted. * * \sa databases() */ void databaseAboutToBeRemoved(int index); /*! * Emitted when all previously queried database information is now * invalid and must be queried again. * * \sa databases() */ void databasesReset(); /*! * Emitted when database import is started using \a importer. * * \sa importPgnFile */ void importStarted(PgnImporter* importer); private: QList m_pgnImporters; QList m_databases; bool m_modified; }; #endif // GAME_DATABASE_MANAGER_H cutechess-20111114+0.4.2+0.0.1/projects/gui/src/gamedatabasedlg.cpp0000664000175000017500000002035511657223322023412 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "gamedatabasedlg.h" #include "ui_gamedatabasedlg.h" #include #include #include #include #include #include "pgndatabasemodel.h" #include "pgngameentrymodel.h" #include "cutechessapp.h" #include "gamedatabasemanager.h" #include "boardview/boardview.h" #include "boardview/boardscene.h" #include "pgndatabase.h" #include "gamedatabasesearchdlg.h" GameDatabaseDialog::GameDatabaseDialog(QWidget* parent) : QDialog(parent, Qt::Window), m_boardView(0), m_boardScene(0), m_pgnDatabaseModel(0), m_pgnGameEntryModel(0), m_selectedDatabase(0), ui(new Ui::GameDatabaseDialog) { ui->setupUi(this); m_pgnDatabaseModel = new PgnDatabaseModel( CuteChessApplication::instance()->gameDatabaseManager(), this); // Setup a filtered model m_pgnGameEntryModel = new PgnGameEntryModel(this); ui->m_databasesListView->setModel(m_pgnDatabaseModel); ui->m_databasesListView->setAlternatingRowColors(true); ui->m_databasesListView->setUniformRowHeights(true); ui->m_gamesListView->setModel(m_pgnGameEntryModel); ui->m_gamesListView->setAlternatingRowColors(true); ui->m_gamesListView->setUniformRowHeights(true); m_boardScene = new BoardScene(this); m_boardView = new BoardView(m_boardScene, this); m_boardView->setEnabled(false); QVBoxLayout* chessboardViewLayout = new QVBoxLayout(); chessboardViewLayout->addWidget(m_boardView); ui->m_chessboardParentWidget->setLayout(chessboardViewLayout); ui->m_nextMoveButton->setIcon(style()->standardIcon(QStyle::SP_ArrowRight)); ui->m_previousMoveButton->setIcon(style()->standardIcon(QStyle::SP_ArrowLeft)); ui->m_skipToFirstMoveButton->setIcon(style()->standardIcon(QStyle::SP_MediaSkipBackward)); ui->m_skipToLastMoveButton->setIcon(style()->standardIcon(QStyle::SP_MediaSkipForward)); connect(ui->m_nextMoveButton, SIGNAL(clicked(bool)), this, SLOT(viewNextMove())); connect(ui->m_previousMoveButton, SIGNAL(clicked(bool)), this, SLOT(viewPreviousMove())); connect(ui->m_skipToFirstMoveButton, SIGNAL(clicked(bool)), this, SLOT(viewFirstMove())); connect(ui->m_skipToLastMoveButton, SIGNAL(clicked(bool)), this, SLOT(viewLastMove())); connect(ui->m_databasesListView->selectionModel(), SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), this, SLOT(databaseSelectionChanged(const QModelIndex&, const QModelIndex&))); connect(ui->m_gamesListView->selectionModel(), SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), this, SLOT(gameSelectionChanged(const QModelIndex&, const QModelIndex&))); connect(ui->m_searchEdit, SIGNAL(textEdited(const QString&)), this, SLOT(updateSearch(const QString&))); connect(ui->m_clearBtn, SIGNAL(clicked()), this, SLOT(updateSearch())); connect(ui->m_advancedSearchBtn, SIGNAL(clicked()), this, SLOT(onAdvancedSearch())); m_searchTimer.setSingleShot(true); connect(&m_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchTimeout())); } GameDatabaseDialog::~GameDatabaseDialog() { delete ui; } void GameDatabaseDialog::databaseSelectionChanged(const QModelIndex& current, const QModelIndex& previous) { Q_UNUSED(previous); if (!current.isValid()) { m_pgnGameEntryModel->setEntries(QList()); return; } m_selectedDatabase = CuteChessApplication::instance()->gameDatabaseManager()->databases().at(current.row()); m_pgnGameEntryModel->setEntries(m_selectedDatabase->entries()); ui->m_advancedSearchBtn->setEnabled(true); } void GameDatabaseDialog::gameSelectionChanged(const QModelIndex& current, const QModelIndex& previous) { Q_UNUSED(previous); const PgnGameEntry* entry = m_pgnGameEntryModel->entryAt(current.row()); PgnGame game; PgnDatabase::PgnDatabaseError error; if ((error = m_selectedDatabase->game(entry, &game)) != PgnDatabase::NoError) { if (error == PgnDatabase::DatabaseDoesNotExist) { // Ask the user if the database should be deleted from the // list QMessageBox msgBox(this); QPushButton* removeDbButton = msgBox.addButton(tr("Remove"), QMessageBox::ActionRole); msgBox.addButton(QMessageBox::Cancel); msgBox.setText("PGN database does not exist."); msgBox.setInformativeText(QString("Remove %1 from the list of databases?").arg(m_selectedDatabase->displayName())); msgBox.setDefaultButton(removeDbButton); msgBox.setIcon(QMessageBox::Warning); msgBox.exec(); if (msgBox.clickedButton() == removeDbButton) { QItemSelectionModel* selection = ui->m_databasesListView->selectionModel(); if (selection->hasSelection()) CuteChessApplication::instance()->gameDatabaseManager()->removeDatabase(selection->currentIndex().row()); } } else { // Ask the user to re-import the database QMessageBox msgBox(this); QPushButton* importDbButton = msgBox.addButton(tr("Import"), QMessageBox::ActionRole); msgBox.addButton(QMessageBox::Cancel); if (error == PgnDatabase::DatabaseModified) { msgBox.setText("PGN database has been modified since the last import."); msgBox.setInformativeText("The database must be imported again to read it."); } else { msgBox.setText("Error occured while trying to read the PGN database."); msgBox.setInformativeText("Importing the database again may fix this problem."); } msgBox.setDefaultButton(importDbButton); msgBox.setIcon(QMessageBox::Warning); msgBox.exec(); if (msgBox.clickedButton() == importDbButton) { QItemSelectionModel* selection = ui->m_databasesListView->selectionModel(); if (selection->hasSelection()) CuteChessApplication::instance()->gameDatabaseManager()->importDatabaseAgain(selection->currentIndex().row()); } } } ui->m_whiteLabel->setText(game.tagValue("White")); ui->m_blackLabel->setText(game.tagValue("Black")); ui->m_siteLabel->setText(game.tagValue("Site")); ui->m_eventLabel->setText(game.tagValue("Event")); ui->m_resultLabel->setText(game.tagValue("Result")); m_boardScene->setBoard(game.createBoard()); m_boardScene->populate(); m_moveIndex = 0; m_moves = game.moves(); ui->m_previousMoveButton->setEnabled(false); ui->m_nextMoveButton->setEnabled(!m_moves.isEmpty()); ui->m_skipToFirstMoveButton->setEnabled(false); ui->m_skipToLastMoveButton->setEnabled(!m_moves.isEmpty()); } void GameDatabaseDialog::viewNextMove() { m_boardScene->makeMove(m_moves.at(m_moveIndex++).move); ui->m_previousMoveButton->setEnabled(true); ui->m_skipToFirstMoveButton->setEnabled(true); if (m_moveIndex >= m_moves.count()) { ui->m_nextMoveButton->setEnabled(false); ui->m_skipToLastMoveButton->setEnabled(false); } } void GameDatabaseDialog::viewPreviousMove() { m_moveIndex--; if (m_moveIndex == 0) { ui->m_previousMoveButton->setEnabled(false); ui->m_skipToFirstMoveButton->setEnabled(false); } m_boardScene->undoMove(); ui->m_nextMoveButton->setEnabled(true); ui->m_skipToLastMoveButton->setEnabled(true); } void GameDatabaseDialog::viewFirstMove() { while (m_moveIndex > 0) viewPreviousMove(); } void GameDatabaseDialog::viewLastMove() { while (m_moveIndex < m_moves.count()) viewNextMove(); } void GameDatabaseDialog::updateSearch(const QString& terms) { ui->m_clearBtn->setEnabled(!terms.isEmpty()); m_searchTerms = terms; m_searchTimer.start(500); } void GameDatabaseDialog::onSearchTimeout() { m_pgnGameEntryModel->setFilter(m_searchTerms); } void GameDatabaseDialog::onAdvancedSearch() { GameDatabaseSearchDialog dlg; if (dlg.exec() != QDialog::Accepted) return; ui->m_searchEdit->clear(); m_pgnGameEntryModel->setFilter(dlg.filter()); ui->m_clearBtn->setEnabled(true); } cutechess-20111114+0.4.2+0.0.1/projects/gui/src/src.pri0000664000175000017500000000237411657223322021125 0ustar oliveroliverinclude(boardview/boardview.pri) DEPENDPATH += $$PWD HEADERS += chessclock.h \ engineconfigurationmodel.h \ engineconfigurationdlg.h \ enginemanagementdlg.h \ mainwindow.h \ plaintextlog.h \ newgamedlg.h \ movelistmodel.h \ cutechessapp.h \ gamepropertiesdlg.h \ autoverticalscroller.h \ gamedatabasedlg.h \ pgnimporter.h \ gamedatabasemanager.h \ importprogressdlg.h \ pgndatabase.h \ pgngameentrymodel.h \ pgndatabasemodel.h \ engineoptiondelegate.h \ engineoptionmodel.h \ gamedatabasesearchdlg.h \ timecontroldlg.h \ engineconfigproxymodel.h SOURCES += main.cpp \ chessclock.cpp \ engineconfigurationmodel.cpp \ engineconfigurationdlg.cpp \ enginemanagementdlg.cpp \ mainwindow.cpp \ plaintextlog.cpp \ newgamedlg.cpp \ movelistmodel.cpp \ cutechessapp.cpp \ gamepropertiesdlg.cpp \ autoverticalscroller.cpp \ gamedatabasedlg.cpp \ pgnimporter.cpp \ gamedatabasemanager.cpp \ importprogressdlg.cpp \ pgndatabase.cpp \ pgngameentrymodel.cpp \ pgndatabasemodel.cpp \ engineoptiondelegate.cpp \ engineoptionmodel.cpp \ gamedatabasesearchdlg.cpp \ timecontroldlg.cpp \ engineconfigproxymodel.cpp cutechess-20111114+0.4.2+0.0.1/projects/gui/src/enginemanagementdlg.cpp0000664000175000017500000000760111657223322024315 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "enginemanagementdlg.h" #include "ui_enginemanagementdlg.h" #include #include #include "cutechessapp.h" #include "engineconfigurationmodel.h" #include "engineconfigurationdlg.h" EngineManagementDialog::EngineManagementDialog(QWidget* parent) : QDialog(parent), m_filteredModel(new QSortFilterProxyModel(this)), ui(new Ui::EngineManagementDialog) { ui->setupUi(this); // Setup a copy of the Engine Manager to manage adding, deleting and // configuring engines _within_ this dialog. m_engineManager = new EngineManager(this); m_engineManager->setEngines( CuteChessApplication::instance()->engineManager()->engines()); // Set up a filtered model m_filteredModel->setSourceModel(new EngineConfigurationModel( m_engineManager, this)); m_filteredModel->setFilterCaseSensitivity(Qt::CaseInsensitive); m_filteredModel->setSortCaseSensitivity(Qt::CaseInsensitive); m_filteredModel->sort(0); m_filteredModel->setDynamicSortFilter(true); ui->m_enginesList->setModel(m_filteredModel); connect(ui->m_searchEngineEdit, SIGNAL(textChanged(QString)), this, SLOT(updateSearch(QString))); // Signals for updating the UI connect(ui->m_enginesList->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), this, SLOT(updateUi())); // Add button connect(ui->m_addBtn, SIGNAL(clicked(bool)), this, SLOT(addEngine())); // Configure button connect(ui->m_configureBtn, SIGNAL(clicked(bool)), this, SLOT(configureEngine())); // Remove button connect(ui->m_removeBtn, SIGNAL(clicked(bool)), this, SLOT(removeEngine())); } EngineManagementDialog::~EngineManagementDialog() { delete ui; } void EngineManagementDialog::updateUi() { // Enable buttons depending on item selections ui->m_configureBtn->setEnabled( ui->m_enginesList->selectionModel()->hasSelection()); ui->m_removeBtn->setEnabled( ui->m_enginesList->selectionModel()->hasSelection()); } void EngineManagementDialog::updateSearch(const QString& terms) { m_filteredModel->setFilterWildcard(terms); ui->m_clearBtn->setEnabled(!terms.isEmpty()); } void EngineManagementDialog::addEngine() { EngineConfigurationDialog dlg(EngineConfigurationDialog::AddEngine, this); if (dlg.exec() == QDialog::Accepted) m_engineManager->addEngine(dlg.engineConfiguration()); } void EngineManagementDialog::configureEngine() { // Map the index from the filtered model to the original model int index = m_filteredModel->mapToSource( ui->m_enginesList->selectionModel()->currentIndex()).row(); EngineConfigurationDialog dlg(EngineConfigurationDialog::ConfigureEngine, this); dlg.applyEngineInformation(m_engineManager->engines().at(index)); if (dlg.exec() == QDialog::Accepted) m_engineManager->updateEngineAt(index, dlg.engineConfiguration()); } void EngineManagementDialog::removeEngine() { const QList selected = ui->m_enginesList->selectionModel()->selectedIndexes(); foreach (const QModelIndex& index, selected) { // Map the index from the filtered model to the original model m_engineManager->removeEngineAt( m_filteredModel->mapToSource(index).row()); } } QList EngineManagementDialog::engines() const { return m_engineManager->engines(); } cutechess-20111114+0.4.2+0.0.1/projects/gui/src/engineoptiondelegate.cpp0000664000175000017500000000642411657223322024517 0ustar oliveroliver#include "engineoptiondelegate.h" #include #include #include EngineOptionDelegate::EngineOptionDelegate(QWidget* parent) : QStyledItemDelegate(parent) { } QWidget* EngineOptionDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const { if (index.data(Qt::EditRole).canConvert(QVariant::Map)) { const QVariantMap map = index.data(Qt::EditRole).toMap(); if (!map.isEmpty()) { const QString optionType = map.value("type").toString(); if (optionType == "combo") { QComboBox* editor = new QComboBox(parent); editor->addItems(map.value("choices").toStringList()); return editor; } else if (optionType == "spin") { QSpinBox* editor = new QSpinBox(parent); bool ok; int minValue = map.value("min").toInt(&ok); if (ok) editor->setMinimum(minValue); int maxValue = map.value("max").toInt(&ok); if (ok) editor->setMaximum(maxValue); return editor; } else if (optionType == "text") { QLineEdit* editor = new QLineEdit(parent); return editor; } } } return QStyledItemDelegate::createEditor(parent, option, index); } void EngineOptionDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const { // TODO: default options if (index.data(Qt::EditRole).canConvert(QVariant::Map)) { const QVariantMap map = index.data(Qt::EditRole).toMap(); if (!map.isEmpty()) { const QString optionType = map.value("type").toString(); if (optionType == "combo") { QComboBox* optionEditor = qobject_cast(editor); optionEditor->setCurrentIndex( map.value("choices").toStringList().indexOf(map.value("value").toString())); } else if (optionType == "spin") { QSpinBox* optionEditor = qobject_cast(editor); bool ok; int intValue = map.value("value").toInt(&ok); if (ok) optionEditor->setValue(intValue); else optionEditor->setValue(0); } else if (optionType == "text") { QLineEdit* optionEditor = qobject_cast(editor); optionEditor->setText(map.value("value").toString()); } } } QStyledItemDelegate::setEditorData(editor, index); } void EngineOptionDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const { if (index.data(Qt::EditRole).canConvert(QVariant::Map)) { const QVariantMap map = index.data(Qt::EditRole).toMap(); if (!map.isEmpty()) { const QString optionType = map.value("type").toString(); if (optionType == "combo") { QComboBox* optionEditor = qobject_cast(editor); model->setData(index, optionEditor->currentText()); } else if (optionType == "spin") { QSpinBox* optionEditor = qobject_cast(editor); optionEditor->interpretText(); model->setData(index, optionEditor->value()); } else if (optionType == "text") { QLineEdit* optionEditor = qobject_cast(editor); model->setData(index, optionEditor->text()); } } } QStyledItemDelegate::setModelData(editor, model, index); } cutechess-20111114+0.4.2+0.0.1/projects/gui/src/engineconfigurationmodel.cpp0000664000175000017500000000611211657223322025376 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "engineconfigurationmodel.h" #include #include static const QStringList s_headers = QStringList() << QObject::tr("Name") << QObject::tr("Command") << QObject::tr("Working Directory") << QObject::tr("Protocol") << QObject::tr("Variants"); EngineConfigurationModel::EngineConfigurationModel(EngineManager* engineManager, QObject* parent) : QAbstractListModel(parent), m_engineManager(engineManager) { Q_ASSERT(m_engineManager != 0); connect(m_engineManager, SIGNAL(engineAdded(int)), this, SLOT(onEngineAdded(int))); connect(m_engineManager, SIGNAL(engineAboutToBeRemoved(int)), this, SLOT(onEngineAboutToBeRemoved(int))); connect(m_engineManager, SIGNAL(engineUpdated(int)), this, SLOT(onEngineUpdated(int))); connect(m_engineManager, SIGNAL(enginesReset()), this, SLOT(onEnginesReset())); } int EngineConfigurationModel::rowCount(const QModelIndex& parent) const { Q_UNUSED(parent) return m_engineManager->engineCount(); } int EngineConfigurationModel::columnCount(const QModelIndex& parent) const { Q_UNUSED(parent) return s_headers.count(); } QVariant EngineConfigurationModel::data(const QModelIndex& index, int role) const { if (!index.isValid()) return QVariant(); if (role == Qt::DisplayRole) { const EngineConfiguration engine(m_engineManager->engineAt(index.row())); switch (index.column()) { case 0: return engine.name(); case 1: return engine.command(); case 2: return engine.workingDirectory(); case 3: return engine.protocol(); case 4: return engine.supportedVariants(); default: return QVariant(); } } return QVariant(); } QVariant EngineConfigurationModel::headerData(int section, Qt::Orientation orientation, int role) const { if (role == Qt::DisplayRole && orientation == Qt::Horizontal) return s_headers.at(section); return QVariant(); } void EngineConfigurationModel::onEngineAdded(int index) { beginInsertRows(QModelIndex(), index, index); endInsertRows(); } void EngineConfigurationModel::onEngineAboutToBeRemoved(int index) { beginRemoveRows(QModelIndex(), index, index); endRemoveRows(); } void EngineConfigurationModel::onEngineUpdated(int index) { QModelIndex indexToUpdate = this->index(index); emit dataChanged(indexToUpdate, indexToUpdate); } void EngineConfigurationModel::onEnginesReset() { reset(); } cutechess-20111114+0.4.2+0.0.1/projects/gui/src/cutechessapp.cpp0000664000175000017500000001357111657223322023016 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "cutechessapp.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "mainwindow.h" #include "gamedatabasedlg.h" #include "gamedatabasemanager.h" #include "importprogressdlg.h" #include "pgnimporter.h" CuteChessApplication::CuteChessApplication(int& argc, char* argv[]) : QApplication(argc, argv), m_engineManager(0), m_gameManager(0), m_gameDatabaseManager(0), m_gameDatabaseDialog(0) { qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); // Set the application icon QIcon icon; icon.addFile(":/icons/cutechess_512x512.png"); icon.addFile(":/icons/cutechess_256x256.png"); icon.addFile(":/icons/cutechess_128x128.png"); icon.addFile(":/icons/cutechess_64x64.png"); icon.addFile(":/icons/cutechess_32x32.png"); icon.addFile(":/icons/cutechess_24x24.png"); icon.addFile(":/icons/cutechess_16x16.png"); setWindowIcon(icon); setQuitOnLastWindowClosed(false); QCoreApplication::setOrganizationName("cutechess"); QCoreApplication::setOrganizationDomain("cutechess.org"); QCoreApplication::setApplicationName("cutechess"); // Use Ini format on all platforms QSettings::setDefaultFormat(QSettings::IniFormat); // Load the engines engineManager()->loadEngines(configPath() + QLatin1String("/engines.json")); // Read the game database state gameDatabaseManager()->readState(configPath() + QLatin1String("/gamedb.bin")); connect(gameManager(), SIGNAL(gameStarted(ChessGame*)), this, SLOT(newGameWindow(ChessGame*))); connect(this, SIGNAL(lastWindowClosed()), this, SLOT(onLastWindowClosed())); connect(this, SIGNAL(aboutToQuit()), this, SLOT(onAboutToQuit())); } CuteChessApplication::~CuteChessApplication() { delete m_gameDatabaseDialog; } CuteChessApplication* CuteChessApplication::instance() { return static_cast(QApplication::instance()); } QString CuteChessApplication::userName() { #ifdef Q_CC_MSVC char* name; size_t len; errno_t err = _dupenv_s(&name, &len, "USERNAME"); if (err) return QString(); QString ret = QString::fromLocal8Bit(name, len); free(name); return ret; #else // not Q_CC_MSVC #ifdef Q_WS_WIN char* name = getenv("USERNAME"); #else char* name = getenv("USER"); #endif if (name != 0) return QString::fromLocal8Bit(name); return QString(); #endif // not Q_CC_MSVC } QString CuteChessApplication::configPath() { // We want to have the exact same config path in "gui" and // "cli" applications so that they can share resources QSettings settings; QFileInfo fi(settings.fileName()); QDir dir(fi.absolutePath()); if (!dir.exists()) dir.mkpath(fi.absolutePath()); return fi.absolutePath(); } EngineManager* CuteChessApplication::engineManager() { if (m_engineManager == 0) m_engineManager = new EngineManager(this); return m_engineManager; } GameManager* CuteChessApplication::gameManager() { if (m_gameManager == 0) m_gameManager = new GameManager(this); return m_gameManager; } QList CuteChessApplication::gameWindows() { m_gameWindows.removeAll(0); QList gameWindowList; foreach (const QPointer& window, m_gameWindows) gameWindowList << window.data(); return gameWindowList; } MainWindow* CuteChessApplication::newGameWindow(ChessGame* game) { MainWindow* mainWindow = new MainWindow(game); m_gameWindows.prepend(mainWindow); mainWindow->show(); return mainWindow; } void CuteChessApplication::newDefaultGame() { // default game is a human versus human game using standard variant and // infinite time control ChessGame* game = new ChessGame(Chess::BoardFactory::create("standard"), new PgnGame()); game->setTimeControl(TimeControl("inf")); game->pause(); gameManager()->newGame(game, new HumanBuilder(userName()), new HumanBuilder(userName())); } void CuteChessApplication::showGameWindow(int index) { MainWindow* gameWindow = m_gameWindows.at(index); gameWindow->activateWindow(); gameWindow->raise(); } GameDatabaseManager* CuteChessApplication::gameDatabaseManager() { if (m_gameDatabaseManager == 0) { m_gameDatabaseManager = new GameDatabaseManager(this); connect(m_gameDatabaseManager, SIGNAL(importStarted(PgnImporter*)), this, SLOT(showImportProgressDialog(PgnImporter*))); } return m_gameDatabaseManager; } void CuteChessApplication::showGameDatabaseDialog() { if (m_gameDatabaseDialog == 0) m_gameDatabaseDialog = new GameDatabaseDialog(); m_gameDatabaseDialog->show(); m_gameDatabaseDialog->raise(); m_gameDatabaseDialog->activateWindow(); } void CuteChessApplication::onLastWindowClosed() { if (m_gameManager != 0) { connect(m_gameManager, SIGNAL(finished()), this, SLOT(quit())); m_gameManager->finish(); } else quit(); } void CuteChessApplication::onAboutToQuit() { if (gameDatabaseManager()->isModified()) gameDatabaseManager()->writeState(configPath() + QLatin1String("/gamedb.bin")); } void CuteChessApplication::showImportProgressDialog(PgnImporter* importer) { ImportProgressDialog* dlg = new ImportProgressDialog(importer); dlg->show(); dlg->raise(); dlg->activateWindow(); } cutechess-20111114+0.4.2+0.0.1/projects/gui/src/plaintextlog.cpp0000664000175000017500000000246011657223322023034 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "plaintextlog.h" #include #include PlainTextLog::PlainTextLog(QWidget* parent) : QPlainTextEdit(parent) { setReadOnly(true); } PlainTextLog::PlainTextLog(const QString& text, QWidget* parent) : QPlainTextEdit(text, parent) { setReadOnly(true); } void PlainTextLog::contextMenuEvent(QContextMenuEvent* event) { QMenu* menu = createStandardContextMenu(); menu->addSeparator(); menu->addAction(tr("Clear Log"), this, SLOT(clear())); menu->addSeparator(); menu->addAction(tr("Save Log to File..."), this, SIGNAL(saveLogToFileRequest())); menu->exec(event->globalPos()); delete menu; } cutechess-20111114+0.4.2+0.0.1/projects/gui/src/gamedatabasemanager.cpp0000664000175000017500000001343311657223322024255 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "gamedatabasemanager.h" #include #include #include "pgndatabase.h" #include "pgnimporter.h" #include #define GAME_DATABASE_STATE_MAGIC 0xDEADD00D #define GAME_DATABASE_STATE_VERSION 1 GameDatabaseManager::GameDatabaseManager(QObject* parent) : QObject(parent), m_modified(false) { } GameDatabaseManager::~GameDatabaseManager() { qDebug() << "Waiting PGN importer threads to finish..."; foreach (PgnImporter* importer, m_pgnImporters) { importer->disconnect(); importer->wait(); } qDeleteAll(m_databases); } QList GameDatabaseManager::databases() const { return m_databases; } bool GameDatabaseManager::writeState(const QString& fileName) { QFile stateFile(fileName); if (!stateFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) return false; qDebug() << "Starting to write game database state file at" << QTime::currentTime().toString("hh:mm:ss"); QDataStream out(&stateFile); out.setVersion(QDataStream::Qt_4_6); // don't change // Write magic number and version out << (quint32)GAME_DATABASE_STATE_MAGIC; out << (quint32)GAME_DATABASE_STATE_VERSION; // Write the number of databases out << (qint32)m_databases.count(); qDebug() << m_databases.count() << "databases"; // Write the contents of the databases foreach (const PgnDatabase* db, m_databases) { out << db->fileName(); out << db->lastModified(); out << db->displayName(); out << (qint32)db->entries().count(); qDebug() << "Writing" << db->entries().count() << "entries"; foreach (const PgnGameEntry* entry, db->entries()) entry->write(out); } qDebug() << "Writing done at" << QTime::currentTime().toString("hh:mm:ss"); m_modified = false; return true; } bool GameDatabaseManager::readState(const QString& fileName) { QFile stateFile(fileName); if (!stateFile.open(QIODevice::ReadOnly)) return false; qDebug() << "Starting to read game database state file at" << QTime::currentTime().toString("hh:mm:ss"); QDataStream in(&stateFile); in.setVersion(QDataStream::Qt_4_6); // don't change // Read and verify the magic value quint32 magic; in >> magic; if (magic != GAME_DATABASE_STATE_MAGIC) { qDebug() << "GameDatabaseManager: bad magic value in state file"; return false; } // Read and verify the version number quint32 version; in >> version; if (version < GAME_DATABASE_STATE_VERSION || version > GAME_DATABASE_STATE_VERSION) { // TODO: Add backward compatibility qDebug() << "GameDatabaseManager: state file version mismatch"; return false; } // Read the number of databases qint32 dbCount; in >> dbCount; qDebug() << dbCount << "databases"; // Read the contents of the databases QString dbFileName; QDateTime dbLastModified; QString dbDisplayName; QList readDatabases; for (int i = 0; i < dbCount; i++) { in >> dbFileName; in >> dbLastModified; in >> dbDisplayName; // Check if the database exists QFileInfo fileInfo(dbFileName); if (!fileInfo.exists()) { qDebug() << "GameDatabaseManager:" << dbDisplayName << "does not exists and will be removed"; m_modified = true; continue; } // Check if the database has been modified if (fileInfo.lastModified() > dbLastModified) { qDebug() << "GameDatabaseManager:" << dbDisplayName << "has been modified and will be re-imported"; m_modified = true; importPgnFile(dbFileName); continue; } qint32 dbEntryCount; in >> dbEntryCount; qDebug() << "Reading" << dbEntryCount << "entries"; // Read the entries QList entries; for (int j = 0; j < dbEntryCount; j++) { PgnGameEntry* entry = new PgnGameEntry; entry->read(in); entries << entry; } PgnDatabase* db = new PgnDatabase(dbFileName); db->setEntries(entries); db->setLastModified(dbLastModified); db->setDisplayName(dbDisplayName); readDatabases << db; } qDebug() << "Reading done at" << QTime::currentTime().toString("hh:mm:ss"); m_modified = false; m_databases = readDatabases; emit databasesReset(); return true; } void GameDatabaseManager::importPgnFile(const QString& fileName) { PgnImporter* pgnImporter = new PgnImporter(fileName, this); m_pgnImporters << pgnImporter; connect(pgnImporter, SIGNAL(databaseRead(PgnDatabase*)), this, SLOT(addDatabase(PgnDatabase*))); emit importStarted(pgnImporter); qDebug() << "Importing started at" << QTime::currentTime().toString("hh:mm:ss"); pgnImporter->start(); } void GameDatabaseManager::addDatabase(PgnDatabase* database) { qDebug() << "Importing finished at" << QTime::currentTime().toString("hh:mm:ss"); m_databases << database; m_modified = true; emit databaseAdded(m_databases.count() - 1); } void GameDatabaseManager::removeDatabase(int index) { emit databaseAboutToBeRemoved(index); m_databases.removeAt(index); m_modified = true; } void GameDatabaseManager::importDatabaseAgain(int index) { const QString fileName = m_databases.at(index)->fileName(); removeDatabase(index); importPgnFile(fileName); } bool GameDatabaseManager::isModified() const { return m_modified; } void GameDatabaseManager::setModified(bool modified) { m_modified = modified; } cutechess-20111114+0.4.2+0.0.1/projects/gui/src/engineconfigurationmodel.h0000664000175000017500000000437211657223322025051 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef ENGINE_CONFIGURATION_MODEL_H #define ENGINE_CONFIGURATION_MODEL_H #include class EngineManager; /*! * \brief The EngineConfigurationModel class represents a chess engine * configuration based model. * * %EngineConfigurationModel is the \e model part in the Model-View * architecture. * * The model contains the data providing view classes access to it. When the * model is updated (either from the view or by calling methods), all the * views are notified about the updates. * * %EngineConfigurationModel is a \e list based model; its items don't have * parent-child relationship. * * Almost all of the method calls are inherited from \e QAbstractItemModel. Refer * to QAbstractItemModel's documentation for better overview of each method. */ class EngineConfigurationModel : public QAbstractListModel { Q_OBJECT public: /*! * Creates an empty model. */ EngineConfigurationModel(EngineManager* engineManager, QObject* parent = 0); // Inherited from QAbstractListModel virtual int rowCount(const QModelIndex& parent = QModelIndex()) const; virtual int columnCount(const QModelIndex& parent = QModelIndex()) const; virtual QVariant data(const QModelIndex& index, int role) const; virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; private slots: void onEngineAdded(int index); void onEngineAboutToBeRemoved(int index); void onEngineUpdated(int index); void onEnginesReset(); private: EngineManager* m_engineManager; }; #endif // ENGINE_CONFIGURATION_MODEL_H cutechess-20111114+0.4.2+0.0.1/projects/gui/src/pgndatabasemodel.cpp0000664000175000017500000000735211657223322023621 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "pgndatabasemodel.h" const QStringList PgnDatabaseModel::s_headers = (QStringList() << tr("Name")); PgnDatabaseModel::PgnDatabaseModel(GameDatabaseManager* gameDatabaseManager, QObject* parent) : QAbstractItemModel(parent), m_gameDatabaseManager(gameDatabaseManager) { Q_ASSERT(m_gameDatabaseManager); connect(m_gameDatabaseManager, SIGNAL(databaseAdded(int)), this, SLOT(onDatabaseAdded(int))); connect(m_gameDatabaseManager, SIGNAL(databaseAboutToBeRemoved(int)), this, SLOT(onDatabaseAboutToBeRemoved(int))); connect(m_gameDatabaseManager, SIGNAL(databasesReset()), this, SLOT(onDatabasesReset())); } void PgnDatabaseModel::onDatabaseAdded(int index) { beginInsertRows(QModelIndex(), index, index); endInsertRows(); } void PgnDatabaseModel::onDatabaseAboutToBeRemoved(int index) { beginRemoveRows(QModelIndex(), index, index); endRemoveRows(); } void PgnDatabaseModel::onDatabasesReset() { reset(); } QModelIndex PgnDatabaseModel::index(int row, int column, const QModelIndex& parent) const { if (!hasIndex(row, column, parent)) return QModelIndex(); return createIndex(row, column); } QModelIndex PgnDatabaseModel::parent(const QModelIndex& index) const { Q_UNUSED(index); return QModelIndex(); } int PgnDatabaseModel::rowCount(const QModelIndex& parent) const { if (parent.isValid()) return 0; return m_gameDatabaseManager->databases().count(); } int PgnDatabaseModel::columnCount(const QModelIndex& parent) const { if (parent.isValid()) return 0; return s_headers.count(); } QVariant PgnDatabaseModel::data(const QModelIndex& index, int role) const { if (!index.isValid()) return QVariant(); const PgnDatabase* db = m_gameDatabaseManager->databases().at(index.row()); if (role == Qt::DisplayRole) { switch (index.column()) { case 0: return db->displayName(); default: return QVariant(); } } else if (role == Qt::EditRole && index.column() == 0) return db->displayName(); return QVariant(); } QVariant PgnDatabaseModel::headerData(int section, Qt::Orientation orientation, int role) const { if (role == Qt::DisplayRole && orientation == Qt::Horizontal) return s_headers.at(section); return QVariant(); } Qt::ItemFlags PgnDatabaseModel::flags(const QModelIndex& index) const { if (!index.isValid()) return Qt::ItemFlags(Qt::NoItemFlags); Qt::ItemFlags defaultFlags = Qt::ItemFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); // database's name is editable if (index.column() == 0) return Qt::ItemFlags(defaultFlags | Qt::ItemIsEditable); return defaultFlags; } bool PgnDatabaseModel::setData(const QModelIndex& index, const QVariant& data, int role) { Q_UNUSED(role); if (!index.isValid()) return false; // only database's name should be editable if (index.column() == 0) { PgnDatabase* db = m_gameDatabaseManager->databases().at(index.row()); db->setDisplayName(data.toString()); m_gameDatabaseManager->setModified(true); return true; } return false; } cutechess-20111114+0.4.2+0.0.1/projects/gui/src/main.cpp0000664000175000017500000000376411657223322021256 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "cutechessapp.h" #include #include #include #include #include #include int main(int argc, char* argv[]) { // Register types for signal / slot connections qRegisterMetaType("Chess::GenericMove"); qRegisterMetaType("Chess::Move"); qRegisterMetaType("Chess::Side"); CuteChessApplication app(argc, argv); QStringList arguments = app.arguments(); arguments.takeFirst(); // application name // Use trivial command-line parsing for now QTextStream out(stdout); while (!arguments.isEmpty()) { if (arguments.first() == QLatin1String("-v") || arguments.first() == QLatin1String("--version")) { out << "Cute Chess " << CUTECHESS_VERSION << endl; out << "Using Qt version " << qVersion() << endl << endl; out << "Copyright (C) 2008-2011 Ilari Pihlajisto and Arto Jonsson" << endl; out << "This is free software; see the source for copying "; out << "conditions. There is NO" << endl << "warranty; not even for "; out << "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."; out << endl << endl; return 0; } else { out << "Unknown argument: " << arguments.first() << endl; } arguments.takeFirst(); } app.newDefaultGame(); return app.exec(); } cutechess-20111114+0.4.2+0.0.1/projects/gui/src/newgamedlg.h0000664000175000017500000000424511657223322022104 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef NEWGAMEDIALOG_H #define NEWGAMEDIALOG_H #include #include #include class EngineConfigurationModel; class EngineConfigurationProxyModel; namespace Ui { class NewGameDialog; } /*! * \brief The NewGameDialog class provides a dialog for creating a new game. */ class NewGameDialog : public QDialog { Q_OBJECT public: /*! Player's type. */ enum PlayerType { /*! Human player. */ Human, /*! Computer controlled player. */ CPU }; /*! * Creates a new game dialog with \a engineConfigurations as the * list of chess engines and given \a parent. */ NewGameDialog(QWidget* parent = 0); /*! Destroys the dialog. */ virtual ~NewGameDialog(); /*! Returns the user selected player type for \a side. */ PlayerType playerType(Chess::Side side) const; /*! * Returns the user selected chess engine for \a side. * * The return value is an index to the list of engines. */ int selectedEngineIndex(Chess::Side side) const; /*! Returns the user-selected chess variant. */ QString selectedVariant() const; /*! Returns the chosen time control. */ TimeControl timeControl() const; private slots: void configureWhiteEngine(); void configureBlackEngine(); void showTimeControlDialog(); void onVariantChanged(const QString& variant); private: EngineConfigurationModel* m_engines; EngineConfigurationProxyModel* m_proxyModel; TimeControl m_timeControl; Ui::NewGameDialog* ui; }; #endif // NEWGAMEDIALOG_H cutechess-20111114+0.4.2+0.0.1/projects/gui/src/engineconfigproxymodel.h0000664000175000017500000000325011657223322024543 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef ENGINECONFIGPROXYMODEL_H #define ENGINECONFIGPROXYMODEL_H #include /*! * \brief A proxy model for sorting and filtering engine configurations. * * In addition to QSortFilterProxyModel's functionality, * EngineConfigurationProxyModel can filter engines based on their * features, eg. the chess variants they support. This is useful when * setting up games or tournaments. */ class EngineConfigurationProxyModel : public QSortFilterProxyModel { Q_OBJECT public: /*! Creates a new EngineConfigurationProxyModel. */ explicit EngineConfigurationProxyModel(QObject *parent = 0); /*! * Sets the chess variant used to filter the contents * of the source model to \a variant. */ void setFilterVariant(const QString& variant); protected: // Reimplemented from QSortFilterProxyModel virtual bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const; private: QString m_filterVariant; }; #endif // ENGINECONFIGPROXYMODEL_H cutechess-20111114+0.4.2+0.0.1/projects/gui/src/movelistmodel.h0000664000175000017500000000371411657223322022655 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef MOVE_LIST_MODEL_H #define MOVE_LIST_MODEL_H #include #include #include class ChessGame; namespace Chess { class GenericMove; } /*! * \brief Supplies chess move information to views. */ class MoveListModel : public QAbstractItemModel { Q_OBJECT public: /*! Constructs a move list model with the given \a parent. */ MoveListModel(QObject* parent = 0); /*! Associates \a game with this model. */ void setGame(ChessGame* game); // Inherited from QAbstractItemModel virtual QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const; virtual QModelIndex parent(const QModelIndex& index) const; virtual int rowCount(const QModelIndex& parent = QModelIndex()) const; virtual int columnCount(const QModelIndex& parent = QModelIndex()) const; virtual QVariant data(const QModelIndex& index, int role) const; virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; private slots: void onMoveMade(const Chess::GenericMove& move, const QString& sanString, const QString& comment); private: static const QStringList m_headers; ChessGame* m_game; QList< QPair > m_moveList; }; #endif // MOVE_LIST_MODEL_H cutechess-20111114+0.4.2+0.0.1/projects/gui/src/gamepropertiesdlg.cpp0000664000175000017500000000345411657223322024043 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "gamepropertiesdlg.h" #include "ui_gamepropertiesdlg.h" GamePropertiesDialog::GamePropertiesDialog(QWidget* parent) : QDialog(parent), ui(new Ui::GamePropertiesDialog) { ui->setupUi(this); } GamePropertiesDialog::~GamePropertiesDialog() { delete ui; } void GamePropertiesDialog::setWhite(const QString& white) { ui->m_whiteEdit->setText(white); } void GamePropertiesDialog::setBlack(const QString& black) { ui->m_blackEdit->setText(black); } void GamePropertiesDialog::setEvent(const QString& event) { ui->m_eventEdit->setText(event); } void GamePropertiesDialog::setSite(const QString& site) { ui->m_siteEdit->setText(site); } void GamePropertiesDialog::setRound(int round) { ui->m_roundSpin->setValue(round); } QString GamePropertiesDialog::white() const { return ui->m_whiteEdit->text(); } QString GamePropertiesDialog::black() const { return ui->m_blackEdit->text(); } QString GamePropertiesDialog::event() const { return ui->m_eventEdit->text(); } QString GamePropertiesDialog::site() const { return ui->m_siteEdit->text(); } int GamePropertiesDialog::round() const { return ui->m_roundSpin->value(); } cutechess-20111114+0.4.2+0.0.1/projects/gui/src/engineoptionmodel.h0000664000175000017500000000227311657223322023510 0ustar oliveroliver#ifndef ENGINE_OPTION_MODEL_H #define ENGINE_OPTION_MODEL_H #include #include class EngineOption; class EngineOptionModel : public QAbstractItemModel { Q_OBJECT public: EngineOptionModel(QObject* parent = 0); EngineOptionModel(QList options, QObject* parent = 0); void setOptions(const QList& options); // Inherited from QAbstractItemModel virtual QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const; virtual QModelIndex parent(const QModelIndex& index) const; virtual int rowCount(const QModelIndex& parent = QModelIndex()) const; virtual int columnCount(const QModelIndex& parent = QModelIndex()) const; virtual QVariant data(const QModelIndex& index, int role) const; virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; virtual Qt::ItemFlags flags(const QModelIndex& index) const; virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole); private: static const QStringList s_headers; QList m_options; }; #endif // ENGINE_OPTION_MODEL_H cutechess-20111114+0.4.2+0.0.1/projects/gui/src/engineoptionmodel.cpp0000664000175000017500000000756011657223322024047 0ustar oliveroliver#include "engineoptionmodel.h" #include #include const QStringList EngineOptionModel::s_headers = (QStringList() << tr("Name") << tr("Value") << tr("Alias")); EngineOptionModel::EngineOptionModel(QObject* parent) : QAbstractItemModel(parent) { } EngineOptionModel::EngineOptionModel(QList options, QObject* parent) : QAbstractItemModel(parent), m_options(options) { } void EngineOptionModel::setOptions(const QList& options) { beginResetModel(); m_options = options; endResetModel(); } QModelIndex EngineOptionModel::index(int row, int column, const QModelIndex& parent) const { if (!hasIndex(row, column, parent)) return QModelIndex(); return createIndex(row, column); } QModelIndex EngineOptionModel::parent(const QModelIndex& index) const { Q_UNUSED(index); return QModelIndex(); } int EngineOptionModel::rowCount(const QModelIndex& parent) const { if (parent.isValid()) return 0; return m_options.count(); } int EngineOptionModel::columnCount(const QModelIndex& parent) const { if (parent.isValid()) return 0; return s_headers.count(); } QVariant EngineOptionModel::data(const QModelIndex& index, int role) const { const EngineOption* option = m_options.at(index.row()); if (role == Qt::DisplayRole) { switch (index.column()) { case 0: return option->name(); case 1: // see Qt::CheckStateRole if (option->value().type() == QVariant::Bool) return QVariant(); return option->value(); case 2: return option->alias(); default: return QVariant(); } } else if (role == Qt::CheckStateRole) { if (index.column() == 1 && option->value().type() == QVariant::Bool) return option->value().toBool() ? Qt::Checked : Qt::Unchecked; return QVariant(); } else if (role == Qt::EditRole) { switch (index.column()) { case 0: return option->name(); case 1: return option->toVariant(); case 2: return option->alias(); default: return QVariant(); } } return QVariant(); } QVariant EngineOptionModel::headerData(int section, Qt::Orientation orientation, int role) const { if (role == Qt::DisplayRole && orientation == Qt::Horizontal) return s_headers.at(section); return QVariant(); } Qt::ItemFlags EngineOptionModel::flags(const QModelIndex& index) const { if (!index.isValid()) return Qt::ItemFlags(Qt::NoItemFlags); Qt::ItemFlags defaultFlags = Qt::ItemFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); if (index.column() == 0) return defaultFlags; if (index.column() == 2) return Qt::ItemFlags(defaultFlags | Qt::ItemIsEditable); if (index.column() == 1) { // option values are editable except button options EngineButtonOption* buttonOption = dynamic_cast(m_options.at(index.row())); if (buttonOption) return defaultFlags; // make check options checkable if (m_options.at(index.row())->value().type() == QVariant::Bool) return Qt::ItemFlags(defaultFlags | Qt::ItemIsUserCheckable); return Qt::ItemFlags(defaultFlags | Qt::ItemIsEditable); } return defaultFlags; } bool EngineOptionModel::setData(const QModelIndex& index, const QVariant& data, int role) { Q_UNUSED(role); if (!index.isValid()) return false; EngineOption* option = m_options.at(index.row()); if (index.column() == 0) { const QString stringData = data.toString(); if (stringData.isEmpty()) return false; option->setName(stringData); return true; } else if (index.column() == 1) { if (role == Qt::CheckStateRole) { option->setValue(data.toInt() == Qt::Checked); return true; } else if (option->isValid(data)) { option->setValue(data); return true; } } else if (index.column() == 2) { option->setAlias(data.toString()); return true; } return false; } cutechess-20111114+0.4.2+0.0.1/projects/gui/src/chessclock.h0000664000175000017500000000247311657223322022114 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef CHESSCLOCK_H #define CHESSCLOCK_H #include #include class QTimerEvent; class QLabel; class ChessClock: public QWidget { Q_OBJECT public: ChessClock(QWidget* parent = 0); public slots: void setPlayerName(const QString& name); void setInfiniteTime(bool infinite); void setTime(int totalTime); void start(int totalTime); void stop(); protected: virtual void timerEvent(QTimerEvent* event); private: void stopTimer(); int m_totalTime; int m_timerId; bool m_infiniteTime; QTime m_time; QLabel* m_nameLabel; QLabel* m_timeLabel; QPalette m_defaultPalette; }; #endif // CHESSCLOCK cutechess-20111114+0.4.2+0.0.1/projects/gui/src/mainwindow.cpp0000664000175000017500000003326011657223322022500 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "mainwindow.h" #include #include #include #include #include #include #include #include #include #include #include #include "cutechessapp.h" #include "boardview/boardscene.h" #include "boardview/boardview.h" #include "movelistmodel.h" #include "newgamedlg.h" #include "chessclock.h" #include "engineconfigurationmodel.h" #include "enginemanagementdlg.h" #include "plaintextlog.h" #include "gamepropertiesdlg.h" #include "autoverticalscroller.h" #include "gamedatabasemanager.h" MainWindow::MainWindow(ChessGame* game) : m_game(game), m_pgn(0) { Q_ASSERT(m_game != 0); setAttribute(Qt::WA_DeleteOnClose, true); QHBoxLayout* clockLayout = new QHBoxLayout(); for (int i = 0; i < 2; i++) { m_chessClock[i] = new ChessClock(); clockLayout->addWidget(m_chessClock[i]); Chess::Side side = Chess::Side::Type(i); m_chessClock[i]->setPlayerName(side.toString()); } clockLayout->insertSpacing(1, 20); m_boardScene = new BoardScene(this); m_boardView = new BoardView(m_boardScene, this); m_moveListModel = new MoveListModel(this); QVBoxLayout* mainLayout = new QVBoxLayout(); mainLayout->addLayout(clockLayout); mainLayout->addWidget(m_boardView); // The content margins look stupid when used with dock widgets. Drop the // margins except from the top so that the chess clocks have spacing mainLayout->setContentsMargins(0, style()->pixelMetric(QStyle::PM_LayoutTopMargin), 0, 0); QWidget* mainWidget = new QWidget(this); mainWidget->setLayout(mainLayout); setCentralWidget(mainWidget); setStatusBar(new QStatusBar()); createActions(); createMenus(); createToolBars(); createDockWindows(); m_game->lockThread(); connect(m_game, SIGNAL(fenChanged(QString)), m_boardScene, SLOT(setFenString(QString))); connect(m_game, SIGNAL(moveMade(Chess::GenericMove, QString, QString)), m_boardScene, SLOT(makeMove(Chess::GenericMove))); connect(m_game, SIGNAL(humanEnabled(bool)), m_boardView, SLOT(setEnabled(bool))); for (int i = 0; i < 2; i++) { ChessPlayer* player(m_game->player(Chess::Side::Type(i))); if (player->isHuman()) connect(m_boardScene, SIGNAL(humanMove(Chess::GenericMove, Chess::Side)), player, SLOT(onHumanMove(Chess::GenericMove, Chess::Side))); connect(player, SIGNAL(debugMessage(QString)), m_engineDebugLog, SLOT(appendPlainText(QString))); ChessClock* clock(m_chessClock[i]); clock->setPlayerName(player->name()); connect(player, SIGNAL(nameChanged(QString)), clock, SLOT(setPlayerName(QString))); clock->setInfiniteTime(player->timeControl()->isInfinite()); if (player->state() == ChessPlayer::Thinking) clock->start(player->timeControl()->activeTimeLeft()); else clock->setTime(player->timeControl()->timeLeft()); connect(player, SIGNAL(startedThinking(int)), clock, SLOT(start(int))); connect(player, SIGNAL(stoppedThinking()), clock, SLOT(stop())); } m_pgn = m_game->pgn(); m_moveListModel->setGame(m_game); m_boardScene->setBoard(m_pgn->createBoard()); m_boardScene->populate(); updateWindowTitle(); m_game->unlockThread(); } MainWindow::~MainWindow() { m_game->deleteLater(); delete m_pgn; } void MainWindow::createActions() { m_newGameAct = new QAction(tr("&New..."), this); m_newGameAct->setShortcut(QKeySequence::New); m_closeGameAct = new QAction(tr("&Close"), this); #ifdef Q_WS_WIN m_closeGameAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_W)); #else m_closeGameAct->setShortcut(QKeySequence::Close); #endif m_saveGameAct = new QAction(tr("&Save"), this); m_saveGameAct->setShortcut(QKeySequence::Save); m_saveGameAsAct = new QAction(tr("Save &As..."), this); m_saveGameAsAct->setShortcut(QKeySequence::SaveAs); m_gamePropertiesAct = new QAction(tr("P&roperties..."), this); m_importGameAct = new QAction(tr("Import..."), this); m_quitGameAct = new QAction(tr("&Quit"), this); #ifdef Q_OS_WIN m_quitGameAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q)); #else m_quitGameAct->setShortcut(QKeySequence::Quit); #endif m_manageEnginesAct = new QAction(tr("Manage..."), this); m_showGameDatabaseWindowAct = new QAction(tr("&Game Database"), this); connect(m_newGameAct, SIGNAL(triggered(bool)), this, SLOT(newGame())); connect(m_closeGameAct, SIGNAL(triggered(bool)), this, SLOT(close())); connect(m_saveGameAct, SIGNAL(triggered(bool)), this, SLOT(save())); connect(m_saveGameAsAct, SIGNAL(triggered(bool)), this, SLOT(saveAs())); connect(m_gamePropertiesAct, SIGNAL(triggered(bool)), this, SLOT(gameProperties())); connect(m_importGameAct, SIGNAL(triggered(bool)), this, SLOT(import())); connect(m_quitGameAct, SIGNAL(triggered(bool)), qApp, SLOT(closeAllWindows())); connect(m_manageEnginesAct, SIGNAL(triggered(bool)), this, SLOT(manageEngines())); connect(m_showGameDatabaseWindowAct, SIGNAL(triggered(bool)), CuteChessApplication::instance(), SLOT(showGameDatabaseDialog())); } void MainWindow::createMenus() { m_gameMenu = menuBar()->addMenu(tr("&Game")); m_gameMenu->addAction(m_newGameAct); m_gameMenu->addSeparator(); m_gameMenu->addAction(m_closeGameAct); m_gameMenu->addAction(m_saveGameAct); m_gameMenu->addAction(m_saveGameAsAct); m_gameMenu->addAction(m_gamePropertiesAct); m_gameMenu->addAction(m_importGameAct); m_gameMenu->addSeparator(); m_gameMenu->addAction(m_quitGameAct); m_viewMenu = menuBar()->addMenu(tr("&View")); m_enginesMenu = menuBar()->addMenu(tr("En&gines")); m_enginesMenu->addAction(m_manageEnginesAct); m_windowMenu = menuBar()->addMenu(tr("&Window")); connect(m_windowMenu, SIGNAL(aboutToShow()), this, SLOT(onWindowMenuAboutToShow())); m_helpMenu = menuBar()->addMenu(tr("&Help")); } void MainWindow::createToolBars() { // Create tool bars here, use actions from createActions() // See: createActions(), QToolBar documentation } void MainWindow::createDockWindows() { // Engine debug QDockWidget* engineDebugDock = new QDockWidget(tr("Engine Debug"), this); m_engineDebugLog = new PlainTextLog(engineDebugDock); connect(m_engineDebugLog, SIGNAL(saveLogToFileRequest()), this, SLOT(saveLogToFile())); engineDebugDock->setWidget(m_engineDebugLog); addDockWidget(Qt::BottomDockWidgetArea, engineDebugDock); // Move list QDockWidget* moveListDock = new QDockWidget(tr("Move List"), this); QTreeView* moveListView = new QTreeView(moveListDock); moveListView->setModel(m_moveListModel); moveListView->setAlternatingRowColors(true); moveListView->setRootIsDecorated(false); moveListView->header()->setResizeMode(0, QHeaderView::ResizeToContents); moveListDock->setWidget(moveListView); AutoVerticalScroller* moveListScroller = new AutoVerticalScroller(moveListView, this); Q_UNUSED(moveListScroller); addDockWidget(Qt::RightDockWidgetArea, moveListDock); // Add toggle view actions to the View menu m_viewMenu->addAction(moveListDock->toggleViewAction()); m_viewMenu->addAction(engineDebugDock->toggleViewAction()); } void MainWindow::newGame() { NewGameDialog dlg(this); if (dlg.exec() != QDialog::Accepted) return; PlayerBuilder* player[2] = { 0, 0 }; ChessGame* game = new ChessGame(Chess::BoardFactory::create(dlg.selectedVariant()), new PgnGame()); game->setTimeControl(dlg.timeControl()); for (int i = 0; i < 2; i++) { Chess::Side side = Chess::Side::Type(i); if (dlg.playerType(side) == NewGameDialog::CPU) { EngineConfiguration config = CuteChessApplication::instance()->engineManager()->engines().at(dlg.selectedEngineIndex(side)); player[i] = new EngineBuilder(config); } else { player[i] = new HumanBuilder(CuteChessApplication::userName()); if (side == Chess::Side::White) game->pause(); } } CuteChessApplication::instance()->gameManager()->newGame(game, player[0], player[1]); } void MainWindow::gameProperties() { GamePropertiesDialog dlg(this); m_game->lockThread(); dlg.setWhite(m_pgn->playerName(Chess::Side::White)); dlg.setBlack(m_pgn->playerName(Chess::Side::Black)); dlg.setEvent(m_pgn->event()); dlg.setSite(m_pgn->site()); dlg.setRound(m_pgn->round()); m_game->unlockThread(); if (dlg.exec() != QDialog::Accepted) return; m_game->lockThread(); m_pgn->setPlayerName(Chess::Side::White, dlg.white()); m_pgn->setPlayerName(Chess::Side::Black, dlg.black()); m_pgn->setEvent(dlg.event()); m_pgn->setSite(dlg.site()); m_pgn->setRound(dlg.round()); updateWindowTitle(); m_game->unlockThread(); setWindowModified(true); } void MainWindow::manageEngines() { EngineManagementDialog dlg(this); if (dlg.exec() == QDialog::Accepted) { CuteChessApplication::instance()->engineManager()->setEngines(dlg.engines()); CuteChessApplication::instance()->engineManager()->saveEngines( CuteChessApplication::instance()->configPath() + QLatin1String("/engines.json")); } } void MainWindow::saveLogToFile() { PlainTextLog* log = qobject_cast(QObject::sender()); Q_ASSERT(log != 0); const QString fileName = QFileDialog::getSaveFileName(this, tr("Save Log"), QString(), tr("Text Files (*.txt);;All Files (*.*)")); if (fileName.isEmpty()) return; QFile file(fileName); if (!file.open(QFile::WriteOnly | QFile::Text)) { QFileInfo fileInfo(file); QMessageBox msgBox; msgBox.setIcon(QMessageBox::Warning); msgBox.setWindowTitle("Cute Chess"); switch (file.error()) { case QFile::OpenError: case QFile::PermissionsError: msgBox.setText( tr("The file \"%1\" could not be saved because " "of insufficient privileges.") .arg(fileInfo.fileName())); msgBox.setInformativeText( tr("Try selecting a location where you have " "the permissions to create files.")); break; case QFile::TimeOutError: msgBox.setText( tr("The file \"%1\" could not be saved because " "the operation timed out.") .arg(fileInfo.fileName())); msgBox.setInformativeText( tr("Try saving the file to a local or another " "network disk.")); break; default: msgBox.setText(tr("The file \"%1\" could not be saved.") .arg(fileInfo.fileName())); msgBox.setInformativeText(file.errorString()); break; } msgBox.exec(); return; } QTextStream out(&file); out << log->toPlainText(); } void MainWindow::onWindowMenuAboutToShow() { m_windowMenu->clear(); m_windowMenu->addAction(m_showGameDatabaseWindowAct); m_windowMenu->addSeparator(); const QList gameWindows = CuteChessApplication::instance()->gameWindows(); for (int i = 0; i < gameWindows.size(); i++) { MainWindow* gameWindow = gameWindows.at(i); QAction* showWindowAction = m_windowMenu->addAction( gameWindow->windowListTitle(), this, SLOT(showGameWindow())); showWindowAction->setData(i); showWindowAction->setCheckable(true); if (gameWindow == this) showWindowAction->setChecked(true); } } void MainWindow::showGameWindow() { if (QAction* action = qobject_cast(sender())) CuteChessApplication::instance()->showGameWindow(action->data().toInt()); } void MainWindow::updateWindowTitle() { // setWindowTitle() requires "[*]" (see docs) setWindowTitle(genericWindowTitle() + QLatin1String("[*]")); } QString MainWindow::windowListTitle() const { #ifndef Q_WS_MAC if (isWindowModified()) return genericWindowTitle() + QLatin1String("*"); #endif return genericWindowTitle(); } QString MainWindow::genericWindowTitle() const { return QString("%1 - %2") .arg(m_pgn->playerName(Chess::Side::White)) .arg(m_pgn->playerName(Chess::Side::Black)); } bool MainWindow::save() { if (m_currentFile.isEmpty()) return saveAs(); return saveGame(m_currentFile); } bool MainWindow::saveAs() { const QString fileName = QFileDialog::getSaveFileName(this, tr("Save Game"), QString(), tr("Portable Game Notation (*.pgn);;All Files (*.*)")); if (fileName.isEmpty()) return false; return saveGame(fileName); } bool MainWindow::saveGame(const QString& fileName) { m_game->lockThread(); bool ok = m_pgn->write(fileName); m_game->unlockThread(); if (!ok) return false; m_currentFile = fileName; setWindowModified(false); return true; } void MainWindow::closeEvent(QCloseEvent* event) { if (askToSave()) { if (m_game->isFinished()) event->accept(); else { connect(m_game, SIGNAL(finished()), this, SLOT(close())); QMetaObject::invokeMethod(m_game, "stop", Qt::QueuedConnection); event->ignore(); } } else event->ignore(); } bool MainWindow::askToSave() { if (isWindowModified()) { QMessageBox::StandardButton result; result = QMessageBox::warning(this, QApplication::applicationName(), tr("The game was modified.\nDo you want to save your changes?"), QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); if (result == QMessageBox::Save) return save(); else if (result == QMessageBox::Cancel) return false; } return true; } void MainWindow::import() { const QString fileName = QFileDialog::getOpenFileName(this, tr("Import Game"), QString(), tr("Portable Game Notation (*.pgn);;All Files (*.*)")); if (fileName.isEmpty()) return; CuteChessApplication::instance()->gameDatabaseManager()->importPgnFile(fileName); } cutechess-20111114+0.4.2+0.0.1/projects/gui/src/newgamedlg.cpp0000664000175000017500000001071011657223322022431 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "newgamedlg.h" #include "ui_newgamedlg.h" #include #include #include #include "cutechessapp.h" #include "engineconfigurationmodel.h" #include "engineconfigproxymodel.h" #include "engineconfigurationdlg.h" #include "timecontroldlg.h" NewGameDialog::NewGameDialog(QWidget* parent) : QDialog(parent), ui(new Ui::NewGameDialog) { ui->setupUi(this); m_engines = new EngineConfigurationModel( CuteChessApplication::instance()->engineManager(), this); connect(ui->m_configureWhiteEngineButton, SIGNAL(clicked(bool)), this, SLOT(configureWhiteEngine())); connect(ui->m_configureBlackEngineButton, SIGNAL(clicked(bool)), this, SLOT(configureBlackEngine())); connect(ui->m_timeControlBtn, SIGNAL(clicked()), this, SLOT(showTimeControlDialog())); m_proxyModel = new EngineConfigurationProxyModel(this); m_proxyModel->setSourceModel(m_engines); m_proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); m_proxyModel->sort(0); m_proxyModel->setDynamicSortFilter(true); ui->m_whiteEngineComboBox->setModel(m_proxyModel); ui->m_blackEngineComboBox->setModel(m_proxyModel); ui->m_variantComboBox->addItems(Chess::BoardFactory::variants()); connect(ui->m_variantComboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(onVariantChanged(QString))); int index = ui->m_variantComboBox->findText("standard"); ui->m_variantComboBox->setCurrentIndex(index); m_timeControl.setMovesPerTc(40); m_timeControl.setTimePerTc(300000); ui->m_timeControlBtn->setText(m_timeControl.toVerboseString()); } NewGameDialog::~NewGameDialog() { delete ui; } NewGameDialog::PlayerType NewGameDialog::playerType(Chess::Side side) const { Q_ASSERT(!side.isNull()); if (side == Chess::Side::White) return (ui->m_whitePlayerHumanRadio->isChecked()) ? Human : CPU; else return (ui->m_blackPlayerHumanRadio->isChecked()) ? Human : CPU; } int NewGameDialog::selectedEngineIndex(Chess::Side side) const { Q_ASSERT(!side.isNull()); int i; if (side == Chess::Side::White) i = ui->m_whiteEngineComboBox->currentIndex(); else i = ui->m_blackEngineComboBox->currentIndex(); return m_proxyModel->mapToSource(m_proxyModel->index(i, 0)).row(); } QString NewGameDialog::selectedVariant() const { return ui->m_variantComboBox->currentText(); } TimeControl NewGameDialog::timeControl() const { return m_timeControl; } void NewGameDialog::configureWhiteEngine() { EngineConfigurationDialog dlg(EngineConfigurationDialog::ConfigureEngine, this); int i = selectedEngineIndex(Chess::Side::White); dlg.applyEngineInformation( CuteChessApplication::instance()->engineManager()->engines().at(i)); if (dlg.exec() == QDialog::Accepted) { CuteChessApplication::instance()->engineManager()->updateEngineAt(i, dlg.engineConfiguration()); } } void NewGameDialog::configureBlackEngine() { EngineConfigurationDialog dlg(EngineConfigurationDialog::ConfigureEngine, this); int i = selectedEngineIndex(Chess::Side::Black); dlg.applyEngineInformation( CuteChessApplication::instance()->engineManager()->engines().at(i)); if (dlg.exec() == QDialog::Accepted) { CuteChessApplication::instance()->engineManager()->updateEngineAt(i, dlg.engineConfiguration()); } } void NewGameDialog::showTimeControlDialog() { TimeControlDialog dlg(m_timeControl); if (dlg.exec() == QDialog::Accepted) { m_timeControl = dlg.timeControl(); ui->m_timeControlBtn->setText(m_timeControl.toVerboseString()); } } void NewGameDialog::onVariantChanged(const QString& variant) { m_proxyModel->setFilterVariant(variant); bool empty = m_proxyModel->rowCount() == 0; if (empty) { ui->m_whitePlayerHumanRadio->setChecked(true); ui->m_blackPlayerHumanRadio->setChecked(true); } ui->m_whitePlayerCpuRadio->setDisabled(empty); ui->m_blackPlayerCpuRadio->setDisabled(empty); } cutechess-20111114+0.4.2+0.0.1/projects/gui/src/pgndatabasemodel.h0000664000175000017500000000425211657223322023262 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef PGN_DATABASE_MODEL_H #define PGN_DATABASE_MODEL_H #include #include #include #include "pgndatabase.h" #include "gamedatabasemanager.h" class GameDatabaseManager; /*! * \brief Supplies PGN database information to views. */ class PgnDatabaseModel : public QAbstractItemModel { Q_OBJECT public: /*! * Constructs a PGN database model with the give \a parent and * \a gameDatabaseManager. */ PgnDatabaseModel(GameDatabaseManager* gameDatabaseManager, QObject* parent = 0); // Inherited from QAbstractItemModel virtual QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const; virtual QModelIndex parent(const QModelIndex& index) const; virtual int rowCount(const QModelIndex& parent = QModelIndex()) const; virtual int columnCount(const QModelIndex& parent = QModelIndex()) const; virtual QVariant data(const QModelIndex& index, int role) const; virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; virtual Qt::ItemFlags flags(const QModelIndex& index) const; virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole); private slots: void onDatabaseAdded(int index); void onDatabaseAboutToBeRemoved(int index); void onDatabasesReset(); private: static const QStringList s_headers; GameDatabaseManager* m_gameDatabaseManager; }; #endif // PGN_DATABASE_MODEL_H cutechess-20111114+0.4.2+0.0.1/projects/gui/src/timecontroldlg.cpp0000664000175000017500000000746211657223322023357 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "timecontroldlg.h" #include "ui_timecontroldlg.h" TimeControlDialog::TimeControlDialog(const TimeControl& tc, QWidget *parent) : QDialog(parent), ui(new Ui::TimeControlDialog) { ui->setupUi(this); connect(ui->m_tournamentRadio, SIGNAL(clicked()), this, SLOT(onTournamentSelected())); connect(ui->m_timePerMoveRadio, SIGNAL(clicked()), this, SLOT(onTimePerMoveSelected())); connect(ui->m_infiniteRadio, SIGNAL(clicked()), this, SLOT(onInfiniteSelected())); if (!tc.isValid()) return; if (tc.isInfinite()) { ui->m_infiniteRadio->setChecked(true); onInfiniteSelected(); } else if (tc.timePerMove() != 0) { ui->m_timePerMoveRadio->setChecked(true); setTime(tc.timePerMove()); onTimePerMoveSelected(); } else { ui->m_tournamentRadio->setChecked(true); ui->m_movesSpin->setValue(tc.movesPerTc()); ui->m_incrementSpin->setValue(double(tc.timeIncrement()) / 1000.0); setTime(tc.timePerTc()); onTournamentSelected(); } ui->m_nodesSpin->setValue(tc.nodeLimit()); ui->m_pliesSpin->setValue(tc.plyLimit()); ui->m_marginSpin->setValue(tc.expiryMargin()); } TimeControlDialog::~TimeControlDialog() { delete ui; } void TimeControlDialog::onTournamentSelected() { ui->m_movesSpin->setEnabled(true); ui->m_timeSpin->setEnabled(true); ui->m_timeUnitCombo->setEnabled(true); ui->m_incrementSpin->setEnabled(true); ui->m_marginSpin->setEnabled(true); } void TimeControlDialog::onTimePerMoveSelected() { ui->m_movesSpin->setEnabled(false); ui->m_timeSpin->setEnabled(true); ui->m_timeUnitCombo->setEnabled(true); ui->m_incrementSpin->setEnabled(false); ui->m_marginSpin->setEnabled(true); } void TimeControlDialog::onInfiniteSelected() { ui->m_movesSpin->setEnabled(false); ui->m_timeSpin->setEnabled(false); ui->m_timeUnitCombo->setEnabled(false); ui->m_incrementSpin->setEnabled(false); ui->m_marginSpin->setEnabled(false); } int TimeControlDialog::timeToMs() const { switch (ui->m_timeUnitCombo->currentIndex()) { case Seconds: return ui->m_timeSpin->value() * 1000.0; case Minutes: return ui->m_timeSpin->value() * 60000.0; case Hours: return ui->m_timeSpin->value() * 3600000.0; default: return 0; } } void TimeControlDialog::setTime(int ms) { Q_ASSERT(ms >= 0); if (ms == 0 || ms % 60000 != 0) { ui->m_timeUnitCombo->setCurrentIndex(Seconds); ui->m_timeSpin->setValue(double(ms) / 1000.0); } else if (ms % 3600000 != 0) { ui->m_timeUnitCombo->setCurrentIndex(Minutes); ui->m_timeSpin->setValue(double(ms) / 60000.0); } else { ui->m_timeUnitCombo->setCurrentIndex(Hours); ui->m_timeSpin->setValue(double(ms) / 3600000.0); } } TimeControl TimeControlDialog::timeControl() const { TimeControl tc; if (ui->m_infiniteRadio->isChecked()) tc.setInfinity(true); else if (ui->m_timePerMoveRadio->isChecked()) tc.setTimePerMove(timeToMs()); else if (ui->m_tournamentRadio->isChecked()) { tc.setMovesPerTc(ui->m_movesSpin->value()); tc.setTimePerTc(timeToMs()); tc.setTimeIncrement(ui->m_incrementSpin->value() * 1000.0); } tc.setNodeLimit(ui->m_nodesSpin->value()); tc.setPlyLimit(ui->m_pliesSpin->value()); tc.setExpiryMargin(ui->m_marginSpin->value()); return tc; } cutechess-20111114+0.4.2+0.0.1/projects/gui/src/gamedatabasesearchdlg.h0000664000175000017500000000257411657223322024250 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef GAMEDATABASESEARCHDIALOG_H #define GAMEDATABASESEARCHDIALOG_H #include #include namespace Ui { class GameDatabaseSearchDialog; } /*! * \brief Dialog for searching and filtering game databases. * * \sa GameDatabaseDialog */ class GameDatabaseSearchDialog : public QDialog { Q_OBJECT public: /*! Constructs a new GameDatabaseSearchDialog. */ GameDatabaseSearchDialog(QWidget* parent = 0); /*! Destroys the dialog. */ virtual ~GameDatabaseSearchDialog(); /*! Returns the PGN filter. */ PgnGameFilter filter() const; private slots: void onResultChanged(int index); private: Ui::GameDatabaseSearchDialog* ui; }; #endif // GAMEDATABASESEARCHDIALOG_H cutechess-20111114+0.4.2+0.0.1/projects/gui/src/engineoptiondelegate.h0000664000175000017500000000115711657223322024162 0ustar oliveroliver#ifndef ENGINE_OPTION_DELEGATE_H #define ENGINE_OPTION_DELEGATE_H #include class EngineOptionDelegate : public QStyledItemDelegate { Q_OBJECT public: EngineOptionDelegate(QWidget* parent = 0); // Inherited from QStyledItemDelegate virtual QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const; virtual void setEditorData(QWidget* editor, const QModelIndex& index) const; virtual void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const; }; #endif // ENGINE_OPTION_DELEGATE_H cutechess-20111114+0.4.2+0.0.1/projects/gui/src/importprogressdlg.cpp0000664000175000017500000000573411657223322024117 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "importprogressdlg.h" #include "ui_importprogressdlg.h" #include "pgnimporter.h" #include ImportProgressDialog::ImportProgressDialog(PgnImporter* pgnImporter, QWidget* parent) : QDialog(parent), m_pgnImporter(pgnImporter), m_lastUpdateSecs(0), m_importError(false), ui(new Ui::ImportProgressDialog) { ui->setupUi(this); setAttribute(Qt::WA_DeleteOnClose, true); QFileInfo info(m_pgnImporter->fileName()); ui->m_fileNameLabel->setText(info.fileName()); ui->m_statusLabel->setText(tr("Importing")); ui->m_totalGamesLabel->setText(tr("0 games imported")); connect(ui->m_buttonBox, SIGNAL(rejected()), m_pgnImporter, SLOT(abort())); connect(m_pgnImporter, SIGNAL(finished()), this, SLOT(onImporterFinished())); connect(m_pgnImporter, SIGNAL(error(int)), this, SLOT(onImportError(int))); connect(m_pgnImporter, SIGNAL(databaseReadStatus(const QTime&, int)), this, SLOT(updateImportStatus(const QTime&, int))); } ImportProgressDialog::~ImportProgressDialog() { delete ui; } void ImportProgressDialog::updateImportStatus(const QTime& startTime, int numReadGames) { int elapsed = startTime.secsTo(QTime::currentTime()); if (elapsed == 0) return; // Update the status once a second if (elapsed <= m_lastUpdateSecs) return; m_lastUpdateSecs = elapsed; ui->m_statusLabel->setText( QString(tr("Importing, %1 games/sec")).arg((int)numReadGames / elapsed)); ui->m_totalGamesLabel->setText( QString(tr("%1 games imported")).arg(numReadGames)); } void ImportProgressDialog::onImporterFinished() { if (!m_importError) accept(); // close the dialog automatically if no error occured } void ImportProgressDialog::onImportError(int error) { m_importError = true; setWindowTitle(tr("Import failed")); switch (error) { case PgnImporter::FileDoesNotExist: ui->m_statusLabel->setText(tr("Import failed: file does not exist")); break; case PgnImporter::IoError: ui->m_statusLabel->setText(tr("Import failed: I/O error")); break; default: ui->m_statusLabel->setText(tr("Import failed: unknown error")); break; } // replace the cancel button with close button because the // the import operation is already finished ui->m_buttonBox->clear(); ui->m_buttonBox->addButton(QDialogButtonBox::Close); } cutechess-20111114+0.4.2+0.0.1/projects/gui/src/engineconfigurationdlg.cpp0000664000175000017500000001655711657223322025062 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "engineconfigurationdlg.h" #include "ui_engineconfigdlg.h" #include #include #include #include #include #include #include #include #include "engineoptionmodel.h" #include "engineoptiondelegate.h" EngineConfigurationDialog::EngineConfigurationDialog( EngineConfigurationDialog::DialogMode mode, QWidget* parent) : QDialog(parent), m_engineOptionModel(new EngineOptionModel(this)), m_engine(0), ui(new Ui::EngineConfigurationDialog) { ui->setupUi(this); if (mode == EngineConfigurationDialog::AddEngine) setWindowTitle(tr("Add Engine")); else setWindowTitle(tr("Configure Engine")); ui->m_progressBar->setRange(0, 0); ui->m_progressBar->hide(); ui->m_protocolCombo->addItems(EngineFactory::protocols()); ui->m_optionsView->setModel(m_engineOptionModel); ui->m_optionsView->setItemDelegate(new EngineOptionDelegate()); m_optionDetectionTimer = new QTimer(this); m_optionDetectionTimer->setSingleShot(true); m_optionDetectionTimer->setInterval(5000); connect(ui->m_browseCmdBtn, SIGNAL(clicked(bool)), this, SLOT(browseCommand())); connect(ui->m_browseWorkingDirBtn, SIGNAL(clicked(bool)), this, SLOT(browseWorkingDir())); connect(ui->m_detectBtn, SIGNAL(clicked()), this, SLOT(detectEngineOptions())); connect(ui->m_restoreBtn, SIGNAL(clicked()), this, SLOT(restoreDefaults())); connect(ui->m_tabs, SIGNAL(currentChanged(int)), this, SLOT(onTabChanged(int))); connect(ui->m_buttonBox, SIGNAL(accepted()), this, SLOT(onAccepted())); } EngineConfigurationDialog::~EngineConfigurationDialog() { qDeleteAll(m_options); delete ui; } void EngineConfigurationDialog::applyEngineInformation( const EngineConfiguration& engine) { ui->m_nameEdit->setText(engine.name()); ui->m_commandEdit->setText(engine.command()); ui->m_workingDirEdit->setText(engine.workingDirectory()); int i = ui->m_protocolCombo->findText(engine.protocol()); ui->m_protocolCombo->setCurrentIndex(i); ui->m_initStringEdit->setPlainText(engine.initStrings().join("\n")); if (engine.whiteEvalPov()) ui->m_whitePovCheck->setCheckState(Qt::Checked); foreach (EngineOption* option, engine.options()) m_options << option->copy(); m_engineOptionModel->setOptions(m_options); ui->m_restoreBtn->setDisabled(m_options.isEmpty()); m_variants = engine.supportedVariants(); m_oldCommand = engine.command(); m_oldPath = engine.workingDirectory(); m_oldProtocol = engine.protocol(); } EngineConfiguration EngineConfigurationDialog::engineConfiguration() { EngineConfiguration engine; engine.setName(ui->m_nameEdit->text()); engine.setCommand(ui->m_commandEdit->text()); engine.setWorkingDirectory(ui->m_workingDirEdit->text()); engine.setProtocol(ui->m_protocolCombo->currentText()); QString initStr(ui->m_initStringEdit->toPlainText()); if (!initStr.isEmpty()) engine.setInitStrings(initStr.split('\n')); engine.setWhiteEvalPov(ui->m_whitePovCheck->checkState() == Qt::Checked); QList optionCopies; foreach (EngineOption* option, m_options) optionCopies << option->copy(); engine.setOptions(optionCopies); engine.setSupportedVariants(m_variants); return engine; } void EngineConfigurationDialog::browseCommand() { // Use file extensions only on Windows #ifdef Q_WS_WIN const QString filter = tr("Executables (*.exe *.bat *.cmd);;All Files (*.*)"); #else const QString filter = tr("All Files (*)"); #endif QString fileName = QFileDialog::getOpenFileName(this, tr("Select Engine Executable"), ui->m_commandEdit->text(), filter); if (fileName.isEmpty()) return; if (ui->m_workingDirEdit->text().isEmpty()) ui->m_workingDirEdit->setText(QDir::toNativeSeparators( QFileInfo(fileName).absolutePath())); if (ui->m_nameEdit->text().isEmpty()) ui->m_nameEdit->setText(QFileInfo(fileName).baseName()); // Paths with spaces must be wrapped in quotes if (fileName.contains(' ')) { fileName.prepend('\"'); fileName.append('\"'); } ui->m_commandEdit->setText(QDir::toNativeSeparators(fileName)); } void EngineConfigurationDialog::browseWorkingDir() { const QString directory = QFileDialog::getExistingDirectory(this, tr("Select Engine Working Directory"), ui->m_workingDirEdit->text()); if (directory.isEmpty()) return; ui->m_workingDirEdit->setText(QDir::toNativeSeparators(directory)); } void EngineConfigurationDialog::detectEngineOptions() { if (m_engine != 0) return; if (QObject::sender() != ui->m_detectBtn && ui->m_commandEdit->text() == m_oldCommand && ui->m_workingDirEdit->text() == m_oldPath && ui->m_protocolCombo->currentText() == m_oldProtocol) { emit detectionFinished(); return; } m_oldCommand = ui->m_commandEdit->text(); m_oldPath = ui->m_workingDirEdit->text(); m_oldProtocol = ui->m_protocolCombo->currentText(); ui->m_detectBtn->setEnabled(false); ui->m_restoreBtn->setEnabled(false); ui->m_progressBar->show(); EngineBuilder builder(engineConfiguration()); m_engine = qobject_cast(builder.create(0, 0, this)); if (m_engine != 0) { connect(m_engine, SIGNAL(ready()), this, SLOT(onEngineReady())); connect(m_engine, SIGNAL(disconnected()), this, SLOT(onEngineQuit())); connect(m_engine, SIGNAL(destroyed()), this, SIGNAL(detectionFinished())); connect(m_optionDetectionTimer, SIGNAL(timeout()), m_engine, SLOT(kill())); m_optionDetectionTimer->start(); } else { ui->m_detectBtn->setEnabled(true); ui->m_restoreBtn->setEnabled(true); ui->m_progressBar->hide(); emit detectionFinished(); } } void EngineConfigurationDialog::onEngineReady() { Q_ASSERT(m_engine != 0); Q_ASSERT(m_engine->state() != ChessPlayer::Disconnected); qDeleteAll(m_options); m_options.clear(); // Make copies of the engine options foreach (const EngineOption* option, m_engine->options()) m_options << option->copy(); m_engineOptionModel->setOptions(m_options); m_variants = m_engine->variants(); m_engine->quit(); } void EngineConfigurationDialog::onEngineQuit() { Q_ASSERT(m_engine != 0); Q_ASSERT(m_engine->state() == ChessPlayer::Disconnected); disconnect(m_optionDetectionTimer, 0, m_engine, 0); m_optionDetectionTimer->stop(); m_engine->deleteLater(); m_engine = 0; ui->m_detectBtn->setEnabled(true); ui->m_restoreBtn->setDisabled(m_options.isEmpty()); ui->m_progressBar->hide(); } void EngineConfigurationDialog::onTabChanged(int index) { if (index == 1) detectEngineOptions(); } void EngineConfigurationDialog::onAccepted() { connect(this, SIGNAL(detectionFinished()), this, SLOT(accept())); detectEngineOptions(); } void EngineConfigurationDialog::restoreDefaults() { foreach (EngineOption* option, m_options) option->setValue(option->defaultValue()); m_engineOptionModel->setOptions(m_options); } cutechess-20111114+0.4.2+0.0.1/projects/gui/src/engineconfigurationdlg.h0000664000175000017500000000451611657223322024517 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef ENGINECONFIGURATIONDIALOG_H #define ENGINECONFIGURATIONDIALOG_H #include #include class QTimer; class EngineOption; class EngineOptionModel; class ChessEngine; namespace Ui { class EngineConfigurationDialog; } /*! * \brief The EngineConfigurationDialog class provides a dialog for chess engine * configuration. */ class EngineConfigurationDialog : public QDialog { Q_OBJECT public: /*! The mode that is used in the dialog. */ enum DialogMode { /*! Mode for adding new engine. */ AddEngine, /*! Mode for configuring existing engine. */ ConfigureEngine }; /*! * Creates a new engine configuration dialog with \a parent as * parent */ EngineConfigurationDialog(DialogMode mode, QWidget* parent = 0); /*! Destroys the dialog. */ virtual ~EngineConfigurationDialog(); /*! * Applies the information of \a engine to the dialog. */ void applyEngineInformation(const EngineConfiguration& engine); /*! * Returns an engine based on the information user selected. */ EngineConfiguration engineConfiguration(); signals: void detectionFinished(); private slots: void browseCommand(); void browseWorkingDir(); void detectEngineOptions(); void restoreDefaults(); void onEngineReady(); void onEngineQuit(); void onTabChanged(int index); void onAccepted(); private: EngineOptionModel* m_engineOptionModel; QString m_oldCommand; QString m_oldPath; QString m_oldProtocol; QList m_options; QStringList m_variants; QTimer* m_optionDetectionTimer; ChessEngine* m_engine; Ui::EngineConfigurationDialog* ui; }; #endif // ENGINECONFIGURATIONDIALOG_H cutechess-20111114+0.4.2+0.0.1/projects/gui/src/enginemanagementdlg.h0000664000175000017500000000317711657223322023766 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef ENGINEMANAGEMENTDIALOG_H #define ENGINEMANAGEMENTDIALOG_H #include #include class EngineManager; class QSortFilterProxyModel; namespace Ui { class EngineManagementDialog; } /*! * \brief The EngineManagementDialog class provides a dialog for chess engine * management. */ class EngineManagementDialog : public QDialog { Q_OBJECT public: /*! * Creates a new engine management window with \a engineConfigurations * and \a parent as parent. */ EngineManagementDialog(QWidget* parent = 0); /*! Destroys the dialog. */ virtual ~EngineManagementDialog(); QList engines() const; private slots: void updateUi(); void updateSearch(const QString& terms); void addEngine(); void configureEngine(); void removeEngine(); private: EngineManager* m_engineManager; QSortFilterProxyModel* m_filteredModel; Ui::EngineManagementDialog* ui; }; #endif // ENGINEMANAGEMENTDIALOG_H cutechess-20111114+0.4.2+0.0.1/projects/gui/src/cutechessapp.h0000664000175000017500000000355111657223322022460 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef CUTE_CHESS_APPLICATION_H #define CUTE_CHESS_APPLICATION_H #include #include class EngineManager; class GameManager; class MainWindow; class GameDatabaseManager; class GameDatabaseDialog; class PgnImporter; class ChessGame; class CuteChessApplication : public QApplication { Q_OBJECT public: CuteChessApplication(int& argc, char* argv[]); virtual ~CuteChessApplication(); QString configPath(); EngineManager* engineManager(); GameManager* gameManager(); QList gameWindows(); void showGameWindow(int index); GameDatabaseManager* gameDatabaseManager(); static CuteChessApplication* instance(); static QString userName(); public slots: MainWindow* newGameWindow(ChessGame* game); void newDefaultGame(); void showGameDatabaseDialog(); private slots: void showImportProgressDialog(PgnImporter* importer); private: EngineManager* m_engineManager; GameManager* m_gameManager; GameDatabaseManager* m_gameDatabaseManager; QList > m_gameWindows; GameDatabaseDialog* m_gameDatabaseDialog; private slots: void onLastWindowClosed(); void onAboutToQuit(); }; #endif // CUTE_CHESS_APPLICATION_H cutechess-20111114+0.4.2+0.0.1/projects/gui/src/pgndatabase.h0000664000175000017500000000650711657223322022246 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef PGN_DATABASE_H #define PGN_DATABASE_H #include #include #include #include #include /*! * \brief PGN database * * \sa PgnGame * \sa PgnGameEntry * \sa PgnImporter */ class PgnDatabase : public QObject { Q_OBJECT public: /*! PGN database processing error. */ enum PgnDatabaseError { NoError, //!< No error occured DatabaseModified, //!< Database was modified externally DatabaseDoesNotExist, //!< Database file does not exist IoDeviceError, //!< Generic I/O device error StreamError //!< Error while processing the PGN data }; /*! * Constructs a new PgnDatabase with \a parent and \a fileName as * the underlying database. */ PgnDatabase(const QString& fileName, QObject* parent = 0); /*! Destroys the database and the game entries it contains. */ virtual ~PgnDatabase(); /*! * Set the game entries found in this database to \a entries. * * The database takes ownership of the PgnGameEntry objects * in \a entries. */ void setEntries(const QList& entries); /*! * Returns the list of game entries in this database. * * Game entries are light-weight "pointers" to the database. The game() * method can be used to read the move information. * * \sa game() */ QList entries() const; /*! Returns the file name of this database. */ QString fileName() const; /*! * Returns the last recorded modification time of this database. * * \note This is recorded information. The underlying database file * may have been modified afterwards. * * \sa setLastModified */ QDateTime lastModified() const; /*! * Sets the modification time of this database. * * \sa lastModified */ void setLastModified(const QDateTime& lastModified); /*! * Returns the display name of this database. * * \sa setDisplayName */ QString displayName() const; /*! * Set the display name of this database to \a displayName. * * \note Display name is meant for GUI and should be editable by the * user. When presenting PGN database information in GUI, display name * should be used. * * \sa displayName */ void setDisplayName(const QString& displayName); /*! * Reads \a game from the database using \a entry. * * \note \a game must be allocated by the caller and must not be NULL. */ PgnDatabaseError game(const PgnGameEntry* entry, PgnGame* game); private: QList m_entries; QString m_fileName; QDateTime m_lastModified; QString m_displayName; }; #endif // PGN_DATABASE_H cutechess-20111114+0.4.2+0.0.1/projects/gui/src/pgngameentrymodel.h0000664000175000017500000000476011657223322023515 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef PGN_GAME_ENTRY_MODEL_H #define PGN_GAME_ENTRY_MODEL_H #include #include #include #include #include class PgnGameEntry; class PgnGameFilter; /*! * \brief Supplies PGN game entry information to views. */ class PgnGameEntryModel : public QAbstractItemModel { Q_OBJECT public: /*! Constructs a PGN game entry model with the given \a parent. */ PgnGameEntryModel(QObject* parent = 0); /*! Returns the PGN entry at \a row. */ const PgnGameEntry* entryAt(int row) const; /*! Associates a list of PGN game entris with this model. */ void setEntries(const QList& entries); // Inherited from QAbstractItemModel virtual QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const; virtual QModelIndex parent(const QModelIndex& index) const; virtual int rowCount(const QModelIndex& parent = QModelIndex()) const; virtual int columnCount(const QModelIndex& parent = QModelIndex()) const; virtual QVariant data(const QModelIndex& index, int role) const; virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; public slots: /*! Sets the filter for filtering the contents of the database. */ void setFilter(const PgnGameFilter& filter); protected: // Inherited from QAbstractItemModel virtual bool canFetchMore(const QModelIndex& parent) const; virtual void fetchMore(const QModelIndex& parent); private slots: void onResultsReady(); private: void applyFilter(const PgnGameFilter& filter); static const QStringList s_headers; QList m_entries; int m_entryCount; QFuture m_filtered; QFutureWatcher m_watcher; }; #endif // PGN_GAME_ENTRY_MODEL_H cutechess-20111114+0.4.2+0.0.1/projects/gui/src/gamepropertiesdlg.h0000664000175000017500000000251511657223322023505 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef GAME_PROPERTIES_DIALOG_H #define GAME_PROPERTIES_DIALOG_H #include namespace Ui { class GamePropertiesDialog; } class GamePropertiesDialog : public QDialog { Q_OBJECT public: GamePropertiesDialog(QWidget* parent = 0); virtual ~GamePropertiesDialog(); void setWhite(const QString& white); void setBlack(const QString& black); void setEvent(const QString& event); void setSite(const QString& site); void setRound(int round); QString white() const; QString black() const; QString event() const; QString site() const; int round() const; private: Ui::GamePropertiesDialog* ui; }; #endif // GAME_PROPERTIES_DIALOG_H cutechess-20111114+0.4.2+0.0.1/projects/gui/src/boardview/0000775000175000017500000000000011657223322021576 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/projects/gui/src/boardview/boardview.h0000664000175000017500000000277211657223322023741 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef BOARDVIEW_H #define BOARDVIEW_H #include #include class QTimer; /*! * \brief A view widget for displaying a QGraphicsScene. * * BoardView is meant for visualizing the contents of a BoardScene. * Unlike a pure QGraphicsView, BoardView doesn't use scrollbars and * always keeps the view fitted to the entire scene. */ class BoardView : public QGraphicsView { Q_OBJECT public: /*! Creates a new BoardView object that displays \a scene. */ explicit BoardView(QGraphicsScene* scene, QWidget* parent = 0); protected: // Inherited from QGraphicsView virtual void resizeEvent(QResizeEvent* event); virtual void paintEvent(QPaintEvent* event); private slots: void fitToRect(); private: bool m_initialized; QTimer* m_resizeTimer; QPixmap m_resizePixmap; }; #endif // BOARDVIEW_H cutechess-20111114+0.4.2+0.0.1/projects/gui/src/boardview/piecechooser.cpp0000664000175000017500000000616111657223322024756 0ustar oliveroliver#include "piecechooser.h" #include #include #include #include #include #include "graphicspiece.h" PieceChooser::PieceChooser(const QList& pieces, qreal squareSize, QGraphicsItem* parent) : QGraphicsObject(parent), m_squareSize(squareSize), m_anim(0) { foreach (GraphicsPiece* piece, pieces) m_pieces[piece->pieceType().side()] << piece; int columns = qMax(m_pieces[0].size(), m_pieces[1].size()); int rows = (!m_pieces[0].isEmpty() && !m_pieces[1].isEmpty()) ? 2 : 1; m_rect.setWidth(m_squareSize * columns); m_rect.setHeight(m_squareSize * rows); m_rect.moveCenter(QPointF(0, 0)); setFlag(QGraphicsItem::ItemDoesntPropagateOpacityToChildren); hide(); } int PieceChooser::type() const { return Type; } QRectF PieceChooser::boundingRect() const { return m_rect; } void PieceChooser::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) { Q_UNUSED(option); Q_UNUSED(widget); painter->setBrush(QColor(Qt::white)); QPen pen(painter->pen()); pen.setWidth(3); painter->setPen(pen); painter->drawRoundedRect(m_rect, 10.0, 10.0); } void PieceChooser::reveal() { QParallelAnimationGroup* group = new QParallelAnimationGroup(this); qreal y = m_rect.top() + m_squareSize / 2; for (int i = 0; i < 2; i++) { if (m_pieces[i].isEmpty()) continue; for (int j = 0; j < m_pieces[i].size(); j++) { GraphicsPiece* piece = m_pieces[i].at(j); piece->setParentItem(this); QPropertyAnimation* posAnim = new QPropertyAnimation(piece, "pos"); qreal x = m_rect.left() + m_squareSize * (0.5 + j); posAnim->setStartValue(QPointF(0, 0)); posAnim->setEndValue(QPointF(x, y)); posAnim->setEasingCurve(QEasingCurve::InOutQuad); posAnim->setDuration(300); group->addAnimation(posAnim); QPropertyAnimation* opAnim = new QPropertyAnimation(piece, "opacity"); opAnim->setStartValue(0.0); opAnim->setEndValue(1.0); opAnim->setEasingCurve(QEasingCurve::InOutQuad); opAnim->setDuration(300); group->addAnimation(opAnim); } y += m_squareSize; } QPropertyAnimation* anim = new QPropertyAnimation(this, "opacity"); anim->setStartValue(0.0); anim->setEndValue(0.6); anim->setEasingCurve(QEasingCurve::InOutQuad); anim->setDuration(300); group->addAnimation(anim); show(); m_anim = group; group->start(); } void PieceChooser::destroy() { if (m_anim == 0) { deleteLater(); return; } connect(m_anim, SIGNAL(finished()), this, SLOT(deleteLater())); m_anim->setDirection(QAbstractAnimation::Backward); m_anim->start(); } void PieceChooser::mousePressEvent(QGraphicsSceneMouseEvent* event) { if (event->button() != Qt::LeftButton) return; event->setAccepted(true); QPointF pos(mapFromScene(event->scenePos())); if (!contains(pos)) { emit pieceChosen(Chess::Piece()); destroy(); return; } QGraphicsItem* item = scene()->itemAt(event->scenePos()); GraphicsPiece* piece = qgraphicsitem_cast(item); if (piece != 0 && piece->parentItem() == this) { emit pieceChosen(piece->pieceType()); destroy(); } } cutechess-20111114+0.4.2+0.0.1/projects/gui/src/boardview/graphicspiecereserve.cpp0000664000175000017500000001071011657223322026503 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "graphicspiecereserve.h" #include #include "graphicspiece.h" GraphicsPieceReserve::GraphicsPieceReserve(qreal squareSize, QGraphicsItem* parent) : QGraphicsItem(parent), m_tileWidth(squareSize * 1.5), m_tileHeight(squareSize), m_rowCount(1) { m_rect.setWidth(m_tileWidth * 2); m_rect.setHeight(m_tileHeight); m_rect.moveCenter(QPointF(0, 0)); setCacheMode(DeviceCoordinateCache); } int GraphicsPieceReserve::type() const { return Type; } QRectF GraphicsPieceReserve::boundingRect() const { return m_rect; } void GraphicsPieceReserve::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) { Q_UNUSED(option); Q_UNUSED(widget); QFont font(painter->font()); font.setPixelSize(m_tileHeight / 2); painter->setFont(font); painter->drawRoundedRect(m_rect, 15.0, 15.0); painter->drawLine(0, m_rect.top(), 0, m_rect.bottom()); for (int i = 0; i < 2; i++) { const QList& list(m_tiles[i]); for (int j = 0; j < list.size(); j++) { int count = m_pieces.count(list.at(j)); if (count < 1) continue; QRectF rect(textRect(Chess::Side::Type(i), j)); painter->drawText(rect, QString::number(count), QTextOption(Qt::AlignCenter)); } } } int GraphicsPieceReserve::pieceCount(const Chess::Piece& piece) const { return m_pieces.count(piece); } GraphicsPiece* GraphicsPieceReserve::piece(const Chess::Piece& piece) const { return m_pieces.value(piece); } GraphicsPiece* GraphicsPieceReserve::takePiece(const Chess::Piece& piece) { GraphicsPiece* gpiece = m_pieces.take(piece); Q_ASSERT(gpiece != 0); if (!m_pieces.contains(piece)) { QList& list = m_tiles[piece.side()]; int index = list.indexOf(piece); if (index == list.size() - 1) { list.removeLast(); while (!list.isEmpty() && list.last().isEmpty()) list.removeLast(); updateTiles(); } else if (index != -1) list[index] = Chess::Piece(); } update(textRect(piece)); gpiece->setParentItem(0); gpiece->setContainer(0); return gpiece; } void GraphicsPieceReserve::addPiece(GraphicsPiece* piece) { Q_ASSERT(piece != 0); Chess::Piece type(piece->pieceType()); GraphicsPiece* old = m_pieces.value(type); m_pieces.insert(type, piece); piece->setContainer(this); piece->setParentItem(this); if (old != 0) piece->setPos(old->pos()); else { QList& list = m_tiles[type.side()]; int index = list.indexOf(Chess::Piece()); if (index == -1) { index = list.size(); list.append(type); updateTiles(); } else list[index] = type; piece->setPos(piecePos(type.side(), index)); } update(textRect(type)); } QPointF GraphicsPieceReserve::piecePos(Chess::Side side, int index) const { QPointF point; if (side == Chess::Side::White) point.setX(-m_tileHeight / 2); else point.setX(m_rect.right() - m_tileHeight / 2); qreal top = m_rect.top() + m_tileHeight / 2; point.setY(top + m_tileHeight * index); return point; } QRectF GraphicsPieceReserve::textRect(Chess::Side side, int index) const { QRectF rect; if (side == Chess::Side::White) rect.setLeft(m_rect.left()); else rect.setLeft(0); rect.setWidth(m_tileWidth / 3); rect.setTop(m_rect.top() + m_tileHeight * index); rect.setHeight(m_tileHeight); return rect; } QRectF GraphicsPieceReserve::textRect(const Chess::Piece& piece) const { int index = m_tiles[piece.side()].indexOf(piece); if (index == -1) return QRectF(); return textRect(piece.side(), index); } void GraphicsPieceReserve::updateTiles() { int count = qMax(m_tiles[0].size(), m_tiles[1].size()); if (count != m_rowCount && count > 0) { prepareGeometryChange(); qreal newHeight = m_tileHeight * count; qreal adjust = (m_rect.height() - newHeight) / 2; m_rect.setHeight(newHeight); m_rowCount = qMax(count, 1); moveBy(0, adjust); } } cutechess-20111114+0.4.2+0.0.1/projects/gui/src/boardview/boardscene.cpp0000664000175000017500000003014411657223322024411 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "boardscene.h" #include #include #include #include #include #include #include "graphicsboard.h" #include "graphicspiecereserve.h" #include "graphicspiece.h" #include "piecechooser.h" static qreal s_squareSize = 50; BoardScene::BoardScene(QObject* parent) : QGraphicsScene(parent), m_board(0), m_direction(Forward), m_squares(0), m_reserve(0), m_chooser(0), m_anim(0), m_renderer(new QSvgRenderer(QString(":/default.svg"), this)), m_highlightPiece(0), m_moveHighlights(0) { } BoardScene::~BoardScene() { delete m_board; } void BoardScene::setBoard(Chess::Board* board) { clear(); m_history.clear(); m_transition.clear(); m_squares = 0; m_reserve = 0; m_chooser = 0; m_highlightPiece = 0; m_moveHighlights = 0; m_board = board; } void BoardScene::populate() { Q_ASSERT(m_board != 0); clear(); m_history.clear(); m_transition.clear(); m_squares = 0; m_reserve = 0; m_chooser = 0; m_highlightPiece = 0; m_moveHighlights = 0; m_squares = new GraphicsBoard(m_board->width(), m_board->height(), s_squareSize); addItem(m_squares); if (m_board->variantHasDrops()) { m_reserve = new GraphicsPieceReserve(s_squareSize); addItem(m_reserve); m_reserve->setX(m_squares->boundingRect().right() + m_reserve->boundingRect().right() + 7); QList types(m_board->reservePieceTypes()); foreach (const Chess::Piece& piece, types) { int count = m_board->reserveCount(piece); for (int i = 0; i < count; i++) m_reserve->addPiece(createPiece(piece)); } } setSceneRect(itemsBoundingRect()); for (int x = 0; x < m_board->width(); x++) { for (int y = 0; y < m_board->height(); y++) { Chess::Square sq(x, y); GraphicsPiece* piece(createPiece(m_board->pieceAt(sq))); if (piece != 0) m_squares->setSquare(sq, piece); } } updateMoves(); } void BoardScene::setFenString(const QString& fenString) { Q_ASSERT(m_board != 0); bool ok = m_board->setFenString(fenString); Q_ASSERT(ok); Q_UNUSED(ok); populate(); } void BoardScene::makeMove(const Chess::Move& move) { stopAnimation(); delete m_moveHighlights; m_moveHighlights = new QGraphicsItemGroup(m_squares, this); m_moveHighlights->setZValue(-1); Chess::BoardTransition transition; m_board->makeMove(move, &transition); m_history << transition; applyTransition(transition, Forward); } void BoardScene::makeMove(const Chess::GenericMove& move) { makeMove(m_board->moveFromGenericMove(move)); } void BoardScene::undoMove() { stopAnimation(); delete m_moveHighlights; m_moveHighlights = 0; m_board->undoMove(); applyTransition(m_history.takeLast(), Backward); } void BoardScene::mouseMoveEvent(QGraphicsSceneMouseEvent* event) { GraphicsPiece* piece = pieceAt(event->scenePos()); if (piece == m_highlightPiece || m_anim != 0 || m_chooser != 0) return QGraphicsScene::mouseMoveEvent(event); if (m_targets.contains(piece)) { m_highlightPiece = piece; m_squares->setHighlights(m_targets.values(piece)); } else { m_highlightPiece = 0; m_squares->clearHighlights(); } QGraphicsScene::mouseMoveEvent(event); } void BoardScene::mousePressEvent(QGraphicsSceneMouseEvent* event) { stopAnimation(); if (m_chooser != 0) { bool ok = sendEvent(m_chooser, event); Q_ASSERT(ok); Q_UNUSED(ok); return; } GraphicsPiece* piece = pieceAt(event->scenePos()); if (piece == 0 || event->button() != Qt::LeftButton) return; if (m_targets.contains(piece)) { piece->setFlag(QGraphicsItem::ItemIsMovable, true); m_sourcePos = piece->scenePos(); piece->setParentItem(0); piece->setPos(m_sourcePos); QGraphicsScene::mousePressEvent(event); } else piece->setFlag(QGraphicsItem::ItemIsMovable, false); } void BoardScene::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) { GraphicsPiece* piece = qgraphicsitem_cast(mouseGrabberItem()); if (piece != 0 && event->button() == Qt::LeftButton) { QPointF targetPos(m_squares->mapFromScene(event->scenePos())); tryMove(piece, targetPos); } QGraphicsScene::mouseReleaseEvent(event); } void BoardScene::onTransitionFinished() { foreach (const Chess::BoardTransition::Move& move, m_transition.moves()) { if (m_direction == Forward) m_squares->movePiece(move.source, move.target); else m_squares->movePiece(move.target, move.source); } foreach (const Chess::BoardTransition::Drop& drop, m_transition.drops()) { if (m_direction == Forward) m_squares->setSquare(drop.target, m_reserve->takePiece(drop.piece)); else m_reserve->addPiece(m_squares->takePieceAt(drop.target)); } foreach (const Chess::Square& square, m_transition.squares()) { Chess::Piece type = m_board->pieceAt(square); if (type != m_squares->pieceTypeAt(square)) m_squares->setSquare(square, createPiece(type)); } foreach (const Chess::Piece& piece, m_transition.reserve()) { int count = m_reserve->pieceCount(piece); int newCount = m_board->reserveCount(piece); while (newCount > count) { m_reserve->addPiece(createPiece(piece)); count++; } while (newCount < count) { delete m_reserve->takePiece(piece); count--; } } m_transition.clear(); updateMoves(); } void BoardScene::onPromotionChosen(const Chess::Piece& promotion) { if (!promotion.isValid()) { GraphicsPiece* piece = m_squares->pieceAt(m_promotionMove.sourceSquare()); m_anim = pieceAnimation(piece, m_sourcePos); m_anim->start(QAbstractAnimation::DeleteWhenStopped); } else { m_promotionMove.setPromotion(promotion.type()); emit humanMove(m_promotionMove, m_board->sideToMove()); } } QPointF BoardScene::squarePos(const Chess::Square& square) const { return m_squares->mapToScene(m_squares->squarePos(square)); } GraphicsPiece* BoardScene::pieceAt(const QPointF& pos) const { foreach (QGraphicsItem* item, items(pos)) { GraphicsPiece* piece = qgraphicsitem_cast(item); if (piece != 0) return piece; } return 0; } GraphicsPiece* BoardScene::createPiece(const Chess::Piece& piece) { Q_ASSERT(m_board != 0); Q_ASSERT(m_renderer != 0); Q_ASSERT(m_squares != 0); if (!piece.isValid()) return 0; return new GraphicsPiece(piece, s_squareSize, m_board->pieceSymbol(piece), m_renderer); } QPropertyAnimation* BoardScene::pieceAnimation(GraphicsPiece* piece, const QPointF& endPoint) const { Q_ASSERT(piece != 0); QPointF startPoint(piece->scenePos()); QPropertyAnimation* anim = new QPropertyAnimation(piece, "pos"); connect(anim, SIGNAL(finished()), piece, SLOT(restoreParent())); anim->setStartValue(startPoint); anim->setEndValue(endPoint); anim->setEasingCurve(QEasingCurve::InOutQuad); anim->setDuration(300); piece->setParentItem(0); piece->setPos(startPoint); return anim; } void BoardScene::stopAnimation() { if (m_anim != 0 && m_anim->state() == QAbstractAnimation::Running) m_anim->setCurrentTime(m_anim->totalDuration()); } void BoardScene::tryMove(GraphicsPiece* piece, const QPointF& targetPos) { Chess::Square target(m_squares->squareAt(targetPos)); // Illegal move if (!m_targets.contains(piece, target)) { m_anim = pieceAnimation(piece, m_sourcePos); m_anim->start(QAbstractAnimation::DeleteWhenStopped); } // Normal move else if (piece->container() == m_squares) { Chess::Square source(m_squares->squareAt(m_squares->mapFromScene(m_sourcePos))); QList promotions; foreach (const Chess::GenericMove& move, m_moves) { if (move.sourceSquare() != source || move.targetSquare() != target) continue; if (move.promotion() != 0) promotions << Chess::Piece(m_board->sideToMove(), move.promotion()); else promotions << Chess::Piece(); } Q_ASSERT(!promotions.isEmpty()); Chess::GenericMove move(source, target, 0); if (promotions.size() > 1) { m_promotionMove = move; selectPiece(promotions, SLOT(onPromotionChosen(Chess::Piece))); } else { move.setPromotion(promotions.first().type()); emit humanMove(move, m_board->sideToMove()); } } // Piece drop else if (piece->container() == m_reserve) { Chess::GenericMove move(Chess::Square(), target, piece->pieceType().type()); emit humanMove(move, m_board->sideToMove()); } m_highlightPiece = 0; m_squares->clearHighlights(); } void BoardScene::selectPiece(const QList& types, const char* member) { QList list; foreach (const Chess::Piece& type, types) list << createPiece(type); m_chooser = new PieceChooser(list, s_squareSize); connect(m_chooser, SIGNAL(pieceChosen(Chess::Piece)), this, member); addItem(m_chooser); m_chooser->reveal(); } void BoardScene::addMoveHighlight(const QPointF& sourcePos, const QPointF& targetPos) { Q_ASSERT(m_moveHighlights != 0); QLineF l1(sourcePos, targetPos); QLineF l2(l1.normalVector()); l2.setLength(s_squareSize / 3.0); l2.translate(l2.dx() / -2.0, l2.dy() / -2.0); QPolygonF polygon; polygon << l2.p1() << l1.p2() << l2.p2(); QGraphicsPolygonItem* item = new QGraphicsPolygonItem(polygon); Qt::GlobalColor penColor = Qt::white; Qt::GlobalColor brushColor = Qt::black; if (m_board->sideToMove() == Chess::Side::Black) qSwap(penColor, brushColor); QLinearGradient gradient(sourcePos, targetPos); gradient.setColorAt(0.0, Qt::transparent); gradient.setColorAt(0.5, brushColor); item->setPen(QPen(penColor, 2)); item->setBrush(gradient); m_moveHighlights->addToGroup(item); } void BoardScene::applyTransition(const Chess::BoardTransition& transition, MoveDirection direction) { m_transition = transition; m_direction = direction; QParallelAnimationGroup* group = new QParallelAnimationGroup; connect(group, SIGNAL(finished()), this, SLOT(onTransitionFinished())); m_anim = group; foreach (const Chess::BoardTransition::Move& move, transition.moves()) { Chess::Square source = move.source; Chess::Square target = move.target; if (direction == Backward) qSwap(source, target); else addMoveHighlight(m_squares->squarePos(source), m_squares->squarePos(target)); GraphicsPiece* piece = m_squares->pieceAt(source); if (piece == 0) { piece = createPiece(m_board->pieceAt(target)); m_squares->setSquare(source, piece); } group->addAnimation(pieceAnimation(piece, squarePos(target))); } foreach (const Chess::BoardTransition::Drop& drop, transition.drops()) { if (direction == Forward) { addMoveHighlight(m_squares->mapFromItem(m_reserve, QPointF()), m_squares->squarePos(drop.target)); GraphicsPiece* piece = m_reserve->piece(drop.piece); group->addAnimation(pieceAnimation(piece, squarePos(drop.target))); } else { GraphicsPiece* piece = m_squares->pieceAt(drop.target); group->addAnimation(pieceAnimation(piece, m_reserve->scenePos())); } } group->start(QAbstractAnimation::DeleteWhenStopped); } void BoardScene::updateMoves() { m_targets.clear(); m_moves.clear(); if (!m_board->result().isNone()) return; QVector moves(m_board->legalMoves()); foreach (const Chess::Move& move, moves) { Chess::GenericMove gmove(m_board->genericMove(move)); m_moves << gmove; GraphicsPiece* piece = 0; if (gmove.sourceSquare().isValid()) piece = m_squares->pieceAt(gmove.sourceSquare()); else { Chess::Piece pieceType(m_board->sideToMove(), gmove.promotion()); piece = m_reserve->piece(pieceType); } Q_ASSERT(piece != 0); Chess::Square target(gmove.targetSquare()); if (!m_targets.contains(piece, target)) m_targets.insert(piece, target); } } cutechess-20111114+0.4.2+0.0.1/projects/gui/src/boardview/graphicspiecereserve.h0000664000175000017500000000532311657223322026154 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef GRAPHICSPIECERESERVE_H #define GRAPHICSPIECERESERVE_H #include #include #include class GraphicsPiece; /*! * \brief A graphical reserve for captured chess pieces. * * Some chess variants like Crazyhouse have a reserve for captured * pieces which can be brought back to the game. This class acts as * a kind of separate chessboard for the piece reserve. */ class GraphicsPieceReserve : public QGraphicsItem { public: /*! The type value returned by type(). */ enum { Type = UserType + 3 }; /*! * Creates a new piece reserve. * * Each "square" has a width and height of \a squareSize, * and squares are automatically added and removed when * needed. */ explicit GraphicsPieceReserve(qreal squareSize, QGraphicsItem* parent = 0); // Inherited from QGraphicsItem virtual int type() const; virtual QRectF boundingRect() const; virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0); /*! Returns the number of pieces of type \a piece. */ int pieceCount(const Chess::Piece& piece) const; /*! * Returns a GraphicsPiece object of type \a piece. * Returns 0 if no pieces of type \a piece exist. */ GraphicsPiece* piece(const Chess::Piece& piece) const; /*! * Removes a GraphicsPiece of type \a piece and returns it. * Returns 0 if no pieces of type \a exist. */ GraphicsPiece* takePiece(const Chess::Piece& piece); /*! * Adds \a piece to the reserve. * This object becomes the parent item and container of \a piece. */ void addPiece(GraphicsPiece* piece); private: QPointF piecePos(Chess::Side side, int index) const; QRectF textRect(Chess::Side side, int index) const; QRectF textRect(const Chess::Piece& piece) const; void updateTiles(); typedef QMultiMap PieceMap; qreal m_tileWidth; qreal m_tileHeight; QRectF m_rect; PieceMap m_pieces; int m_rowCount; QList m_tiles[2]; }; #endif // GRAPHICSPIECERESERVE_H cutechess-20111114+0.4.2+0.0.1/projects/gui/src/boardview/piecechooser.h0000664000175000017500000000503111657223322024416 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef PIECECHOOSER_H #define PIECECHOOSER_H #include #include class GraphicsPiece; class QAbstractAnimation; namespace Chess { class Piece; } /*! * \brief A light-weight QGraphicsObject dialog for selecting a chess piece. * * PieceChooser displays a list of graphical chess pieces in a simple * layout and lets the user to choose a piece type with the mouse. */ class PieceChooser : public QGraphicsObject { Q_OBJECT public: /*! The type value returned by type(). */ enum { Type = UserType + 2 }; /*! * Creates a new piece chooser. * * The user can choose one of the pieces in \a pieces, or * select a null piece by clicking outside of the dialog. * \a squareSize is the width and height of a square on the * chessboard. The pieces shouldn't be bigger than that or * else they'll overlap. * * The created dialog is hidden, and can be displayed by * calling reveal(). */ PieceChooser(const QList& pieces, qreal squareSize, QGraphicsItem* parent = 0); // Inherited from QGraphicsObject virtual int type() const; virtual QRectF boundingRect() const; virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0); public slots: /*! Reveals the dialog with an animation. */ void reveal(); /*! Fades the dialog out and destroys the object. */ void destroy(); signals: /*! * This signal is emitted when the user has chosen a piece. * If the user clicked outside of the dialog, \a piece is null. */ void pieceChosen(const Chess::Piece& piece); protected: // Inherited from QGraphicsObject virtual void mousePressEvent(QGraphicsSceneMouseEvent* event); private: qreal m_squareSize; QRectF m_rect; QList m_pieces[2]; QAbstractAnimation* m_anim; }; #endif // PIECECHOOSER_H cutechess-20111114+0.4.2+0.0.1/projects/gui/src/boardview/graphicspiece.cpp0000664000175000017500000000432311657223322025112 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "graphicspiece.h" #include GraphicsPiece::GraphicsPiece(const Chess::Piece& piece, qreal squareSize, const QString& elementId, QSvgRenderer* renderer, QGraphicsItem* parent) : QGraphicsObject(parent), m_piece(piece), m_rect(-squareSize / 2, -squareSize / 2, squareSize, squareSize), m_elementId(elementId), m_renderer(renderer), m_container(0) { setAcceptedMouseButtons(Qt::LeftButton); setCacheMode(DeviceCoordinateCache); } int GraphicsPiece::type() const { return Type; } QRectF GraphicsPiece::boundingRect() const { return m_rect; } void GraphicsPiece::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) { Q_UNUSED(option); Q_UNUSED(widget); QRectF bounds(m_renderer->boundsOnElement(m_elementId)); qreal ar = bounds.width() / bounds.height(); qreal width = m_rect.width() * 0.8; if (ar > 1.0) { bounds.setWidth(width); bounds.setHeight(width / ar); } else { bounds.setHeight(width); bounds.setWidth(width * ar); } bounds.moveCenter(m_rect.center()); m_renderer->render(painter, m_elementId, bounds); } Chess::Piece GraphicsPiece::pieceType() const { return m_piece; } QGraphicsItem* GraphicsPiece::container() const { return m_container; } void GraphicsPiece::setContainer(QGraphicsItem* item) { m_container = item; } void GraphicsPiece::restoreParent() { if (parentItem() == 0 && m_container != 0) { QPointF point(m_container->mapFromScene(pos())); setParentItem(m_container); setPos(point); } } cutechess-20111114+0.4.2+0.0.1/projects/gui/src/boardview/graphicspiece.h0000664000175000017500000000565311657223322024566 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef GRAPHICSPIECE_H #define GRAPHICSPIECE_H #include #include class QSvgRenderer; /*! * \brief A graphical representation of a chess piece. * * A GraphicsPiece object is a chess piece that can be easily * dragged and animated in a QGraphicsScene. Scalable Vector * Graphics (SVG) are used to ensure that the pieces look good * at any resolution, and a shared SVG renderer is used. * * For convenience reasons the boundingRect() of a piece should * be equal to that of a square on the chessboard. */ class GraphicsPiece : public QGraphicsObject { Q_OBJECT public: /*! The type value returned by type(). */ enum { Type = UserType + 4 }; /*! * Creates a new GraphicsPiece object of type \a piece. * * The painted image is scaled to fit inside a square that is * \a squareSize wide and high. * \a elementId is the XML ID of the piece picture which is * rendered by \a renderer. */ GraphicsPiece(const Chess::Piece& piece, qreal squareSize, const QString& elementId, QSvgRenderer* renderer, QGraphicsItem* parent = 0); // Inherited from QGraphicsObject virtual int type() const; virtual QRectF boundingRect() const; virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0); /*! Returns the type of the chess piece. */ Chess::Piece pieceType() const; /*! * Returns the container of the piece. * * Usually the container is the chessboard or the piece reserve. * A piece can have a container even if it doesn't have a parent * item. */ QGraphicsItem* container() const; /*! Sets the container to \a item. */ void setContainer(QGraphicsItem* item); public slots: /*! * Restores the parent item (container). * * If the piece doesn't have a parent item but does have a container, * this function sets the parent item to the container. Usually this * function is called after an animation or drag operation that had * cleared the parent item to make the piece a top-level item. */ void restoreParent(); private: Chess::Piece m_piece; QRectF m_rect; QString m_elementId; QSvgRenderer* m_renderer; QGraphicsItem* m_container; }; #endif // GRAPHICSPIECE_H cutechess-20111114+0.4.2+0.0.1/projects/gui/src/boardview/graphicsboard.cpp0000664000175000017500000001324411657223322025116 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "graphicsboard.h" #include #include #include #include "graphicspiece.h" class TargetHighlights : public QGraphicsObject { public: TargetHighlights(QGraphicsItem* parentItem = 0) : QGraphicsObject(parentItem) { setFlag(ItemHasNoContents); } virtual QRectF boundingRect() const { return QRectF(); } virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) { Q_UNUSED(painter); Q_UNUSED(option); Q_UNUSED(widget); } }; GraphicsBoard::GraphicsBoard(int files, int ranks, qreal squareSize, QGraphicsItem* parent) : QGraphicsItem(parent), m_files(files), m_ranks(ranks), m_squareSize(squareSize), m_lightColor(QColor("#ffce9e")), m_darkColor(QColor("#d18b47")), m_squares(files * ranks), m_highlightAnim(0) { Q_ASSERT(files > 0); Q_ASSERT(ranks > 0); m_rect.setSize(QSizeF(squareSize * files, squareSize * ranks)); m_rect.moveCenter(QPointF(0, 0)); setCacheMode(DeviceCoordinateCache); } int GraphicsBoard::type() const { return Type; } QRectF GraphicsBoard::boundingRect() const { return m_rect; } void GraphicsBoard::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) { Q_UNUSED(option); Q_UNUSED(widget); QRectF rect(m_rect.topLeft(), QSizeF(m_squareSize, m_squareSize)); const qreal left = rect.left(); for (int y = 0; y < m_ranks; y++) { rect.moveLeft(left); for (int x = 0; x < m_files; x++) { if ((x % 2) == (y % 2)) painter->fillRect(rect, m_lightColor); else painter->fillRect(rect, m_darkColor); rect.moveLeft(rect.left() + m_squareSize); } rect.moveTop(rect.top() + m_squareSize); } } Chess::Square GraphicsBoard::squareAt(const QPointF& point) const { if (!m_rect.contains(point)) return Chess::Square(); int col = (point.x() + m_rect.width() / 2) / m_squareSize; int row = (point.y() + m_rect.height() / 2) / m_squareSize; return Chess::Square(col, m_ranks - row - 1); } QPointF GraphicsBoard::squarePos(const Chess::Square& square) const { if (!square.isValid()) return QPointF(); qreal left = m_rect.left() + m_squareSize / 2; qreal top = m_rect.top() + m_squareSize / 2; qreal x = left + m_squareSize * square.file(); qreal y = top + m_squareSize * (m_ranks - square.rank() - 1); return QPointF(x, y); } Chess::Piece GraphicsBoard::pieceTypeAt(const Chess::Square& square) const { GraphicsPiece* piece = pieceAt(square); if (piece == 0) return Chess::Piece(); return piece->pieceType(); } GraphicsPiece* GraphicsBoard::pieceAt(const Chess::Square& square) const { if (!square.isValid()) return 0; GraphicsPiece* piece = m_squares.at(squareIndex(square)); Q_ASSERT(piece == 0 || piece->container() == this); return piece; } GraphicsPiece* GraphicsBoard::takePieceAt(const Chess::Square& square) { int index = squareIndex(square); if (index == -1) return 0; GraphicsPiece* piece = m_squares.at(index); if (piece == 0) return 0; m_squares[index] = 0; piece->setParentItem(0); piece->setContainer(0); return piece; } void GraphicsBoard::clearSquares() { qDeleteAll(m_squares); m_squares.clear(); } void GraphicsBoard::setSquare(const Chess::Square& square, GraphicsPiece* piece) { Q_ASSERT(square.isValid()); int index = squareIndex(square); delete m_squares[index]; if (piece == 0) m_squares[index] = 0; else { m_squares[index] = piece; piece->setContainer(this); piece->setParentItem(this); piece->setPos(squarePos(square)); } } void GraphicsBoard::movePiece(const Chess::Square& source, const Chess::Square& target) { GraphicsPiece* piece = pieceAt(source); Q_ASSERT(piece != 0); m_squares[squareIndex(source)] = 0; setSquare(target, piece); } int GraphicsBoard::squareIndex(const Chess::Square& square) const { if (!square.isValid()) return -1; return square.rank() * m_files + square.file(); } void GraphicsBoard::clearHighlights() { if (m_highlightAnim != 0) { m_highlightAnim->setDirection(QAbstractAnimation::Backward); m_highlightAnim->start(QAbstractAnimation::DeleteWhenStopped); m_highlightAnim = 0; } } void GraphicsBoard::setHighlights(const QList& squares) { clearHighlights(); if (squares.isEmpty()) return; TargetHighlights* targets = new TargetHighlights(this); QRectF rect; rect.setSize(QSizeF(m_squareSize / 3, m_squareSize / 3)); rect.moveCenter(QPointF(0, 0)); QPen pen(Qt::white, m_squareSize / 20); QBrush brush(Qt::black); foreach (const Chess::Square& sq, squares) { QGraphicsEllipseItem* dot = new QGraphicsEllipseItem(rect, targets); dot->setPen(pen); dot->setBrush(brush); dot->setPos(squarePos(sq)); } m_highlightAnim = new QPropertyAnimation(targets, "opacity"); targets->setParent(m_highlightAnim); m_highlightAnim->setStartValue(0.0); m_highlightAnim->setEndValue(1.0); m_highlightAnim->setDuration(500); m_highlightAnim->setEasingCurve(QEasingCurve::InOutQuad); m_highlightAnim->start(QAbstractAnimation::KeepWhenStopped); } cutechess-20111114+0.4.2+0.0.1/projects/gui/src/boardview/graphicsboard.h0000664000175000017500000000767511657223322024576 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef GRAPHICSBOARD_H #define GRAPHICSBOARD_H #include #include #include #include #include class GraphicsPiece; class QPropertyAnimation; /*! * \brief A graphical chessboard. * * GraphicsBoard is a graphical representation of the squares on a * chessboard. It also has ownership of the chess pieces on the * board, ie. it is the pieces' parent item and container. */ class GraphicsBoard : public QGraphicsItem { public: /*! The type value returned by type(). */ enum { Type = UserType + 1 }; /*! * Creates a new GraphicsBoard object. * * The board will have \a files files/columns and \a ranks * ranks/rows, and the squares' width and height will be * \a squareSize. */ GraphicsBoard(int files, int ranks, qreal squareSize, QGraphicsItem* parent = 0); // Inherited from QGraphicsItem virtual int type() const; virtual QRectF boundingRect() const; virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0); /*! * Returns the chess square at \a point. * * \a point is in item coordinates. * Returns a null square if \a point is not on the board. */ Chess::Square squareAt(const QPointF& point) const; /*! * Returns the position of \a square. * * The returned position is in item coordinates. * Returns a null point if \a square is not on the board. */ QPointF squarePos(const Chess::Square& square) const; /*! * Returns the type of piece at \a square. * * Returns a null piece if \a square is not on the board or * if there's no piece placed on it. */ Chess::Piece pieceTypeAt(const Chess::Square& square) const; /*! * Returns the GraphicsPiece object at \a square. * * Returns 0 if \a square is not on the board or if there's * no piece placed on it. */ GraphicsPiece* pieceAt(const Chess::Square& square) const; /*! * Removes the GraphicsPiece object at \a square and returns it. * * Returns 0 if \a square is not on the board or if there's * no piece placed on it. */ GraphicsPiece* takePieceAt(const Chess::Square& square); /*! Deletes all pieces and removes them from the scene. */ void clearSquares(); /*! * Sets the piece at \a square to \a piece. * * If \a square already contains a piece, it is deleted. * If \a piece is 0, the square becomes empty. */ void setSquare(const Chess::Square& square, GraphicsPiece* piece); /*! * Moves the piece from \a source to \a target. * * If \a target already contains a piece, it is deleted. */ void movePiece(const Chess::Square& source, const Chess::Square& target); /*! Clears all highlights. */ void clearHighlights(); /*! * Highlights squares. * * This function clears all previous highlights and marks the * squares in \a squares as possible target squares of a chess move. */ void setHighlights(const QList& squares); private: int squareIndex(const Chess::Square& square) const; int m_files; int m_ranks; qreal m_squareSize; QRectF m_rect; QColor m_lightColor; QColor m_darkColor; QVector m_squares; QPropertyAnimation* m_highlightAnim; }; #endif // GRAPHICSBOARD_H cutechess-20111114+0.4.2+0.0.1/projects/gui/src/boardview/boardscene.h0000664000175000017500000001071011657223322024053 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef BOARDSCENE_H #define BOARDSCENE_H #include #include #include #include #include #include namespace Chess { class Board; class Move; class Side; class Piece; } class QSvgRenderer; class QAbstractAnimation; class QPropertyAnimation; class GraphicsBoard; class GraphicsPieceReserve; class GraphicsPiece; class PieceChooser; /*! * \brief A graphical surface for displaying a chessgame. * * BoardScene is the top-level container for the board, the * chess pieces, etc. It also manages the deletion and creation * of pieces, visualising moves made in a game, emitting moves * made by a human player, etc. * * BoardScene is that class that connects to the players and game * objects to synchronize the graphical side with the internals. */ class BoardScene : public QGraphicsScene { Q_OBJECT public: /*! Creates a new BoardScene object. */ BoardScene(QObject* parent = 0); /*! Destroys the scene and all its items. */ ~BoardScene(); /*! * Clears the scene and sets \a board as the internal board. * * The scene takes ownership of the board, so it's usually * best to give the scene its own copy of a board. */ void setBoard(Chess::Board* board); public slots: /*! * Clears the scene, creates a new board, and populates * it with chess pieces. * * The scene is populated to match the current FEN string of * the internal board, so the internal board must be fully * initialized before calling this function. */ void populate(); /*! Re-populates the scene according to \a fenString. */ void setFenString(const QString& fenString); /*! Makes the move \a move in the scene. */ void makeMove(const Chess::Move& move); /*! Makes the move \a move in the scene. */ void makeMove(const Chess::GenericMove& move); /*! Reverses the last move that was made in the scene. */ void undoMove(); signals: /*! * This signal is emitted when a human player has made a move. * * The move is guaranteed to be legal. * The move was made by the player on \a side side. */ void humanMove(const Chess::GenericMove& move, const Chess::Side& side); protected: // Inherited from QGraphicsScene virtual void mouseMoveEvent(QGraphicsSceneMouseEvent* event); virtual void mousePressEvent(QGraphicsSceneMouseEvent* event); virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent* event); private slots: void onTransitionFinished(); void onPromotionChosen(const Chess::Piece& promotion); private: enum MoveDirection { Forward, Backward }; QPointF squarePos(const Chess::Square& square) const; GraphicsPiece* pieceAt(const QPointF& pos) const; GraphicsPiece* createPiece(const Chess::Piece& piece); QPropertyAnimation* pieceAnimation(GraphicsPiece* piece, const QPointF& endPoint) const; void stopAnimation(); void tryMove(GraphicsPiece* piece, const QPointF& targetPos); void selectPiece(const QList& types, const char* member); void addMoveHighlight(const QPointF& sourcePos, const QPointF& targetPos); void applyTransition(const Chess::BoardTransition& transition, MoveDirection direction); void updateMoves(); Chess::Board* m_board; MoveDirection m_direction; Chess::BoardTransition m_transition; QList m_history; QPointF m_sourcePos; GraphicsBoard* m_squares; GraphicsPieceReserve* m_reserve; QPointer m_chooser; QPointer m_anim; QSvgRenderer* m_renderer; QMultiMap m_targets; QList m_moves; Chess::GenericMove m_promotionMove; GraphicsPiece* m_highlightPiece; QGraphicsItemGroup* m_moveHighlights; }; #endif // BOARDSCENE_H cutechess-20111114+0.4.2+0.0.1/projects/gui/src/boardview/boardview.cpp0000664000175000017500000000446311657223322024273 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "boardview.h" #include #include #include BoardView::BoardView(QGraphicsScene* scene, QWidget* parent) : QGraphicsView(scene, parent), m_initialized(false), m_resizeTimer(new QTimer(this)) { setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setRenderHint(QPainter::Antialiasing); setMouseTracking(true); m_resizeTimer->setSingleShot(true); m_resizeTimer->setInterval(300); connect(m_resizeTimer, SIGNAL(timeout()), this, SLOT(fitToRect())); connect(scene, SIGNAL(sceneRectChanged(QRectF)), this, SLOT(fitToRect())); } void BoardView::paintEvent(QPaintEvent* event) { if (!m_resizePixmap.isNull()) { QRect rect(viewport()->rect()); qreal srcAr = qreal(m_resizePixmap.width()) / m_resizePixmap.height(); qreal trgAr = qreal(rect.width()) / rect.height(); if (srcAr > trgAr) rect.setHeight(rect.width() / srcAr); else if (srcAr < trgAr) rect.setWidth(rect.height() * srcAr); rect.moveCenter(viewport()->rect().center()); QPainter painter(viewport()); painter.drawPixmap(rect, m_resizePixmap); } else QGraphicsView::paintEvent(event); } void BoardView::resizeEvent(QResizeEvent* event) { QGraphicsView::resizeEvent(event); if (!m_initialized) return; if (m_resizePixmap.isNull()) { m_resizePixmap = QPixmap(sceneRect().toRect().size()); m_resizePixmap.fill(Qt::transparent); QPainter painter(&m_resizePixmap); scene()->render(&painter); } m_resizeTimer->start(); } void BoardView::fitToRect() { m_initialized = true; m_resizePixmap = QPixmap(); fitInView(sceneRect(), Qt::KeepAspectRatio); } cutechess-20111114+0.4.2+0.0.1/projects/gui/src/boardview/boardview.pri0000664000175000017500000000046011657223322024274 0ustar oliveroliverDEPENDPATH += $$PWD HEADERS += boardscene.h \ boardview.h \ graphicsboard.h \ graphicspiece.h \ graphicspiecereserve.h \ piecechooser.h SOURCES += boardscene.cpp \ boardview.cpp \ graphicsboard.cpp \ graphicspiece.cpp \ graphicspiecereserve.cpp \ piecechooser.cpp cutechess-20111114+0.4.2+0.0.1/projects/gui/src/gamedatabasesearchdlg.cpp0000664000175000017500000000427611657223322024604 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "gamedatabasesearchdlg.h" #include "ui_gamedatabasesearchdlg.h" GameDatabaseSearchDialog::GameDatabaseSearchDialog(QWidget* parent) : QDialog(parent, Qt::Window), ui(new Ui::GameDatabaseSearchDialog) { ui->setupUi(this); ui->m_maxDateEdit->setDate(QDate::currentDate()); connect(ui->m_resultCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(onResultChanged(int))); } GameDatabaseSearchDialog::~GameDatabaseSearchDialog() { delete ui; } void GameDatabaseSearchDialog::onResultChanged(int index) { if (index == PgnGameFilter::AnyResult) { ui->m_invertResultCheck->setCheckState(Qt::Unchecked); ui->m_invertResultCheck->setEnabled(false); } else ui->m_invertResultCheck->setEnabled(true); } PgnGameFilter GameDatabaseSearchDialog::filter() const { PgnGameFilter filter; filter.setEvent(ui->m_eventEdit->text()); filter.setSite(ui->m_siteEdit->text()); if (ui->m_minDateCheck->isChecked()) filter.setMinDate(ui->m_minDateEdit->date()); if (ui->m_maxDateCheck->isChecked()) filter.setMaxDate(ui->m_maxDateEdit->date()); filter.setMinRound(ui->m_minRoundSpin->value()); filter.setMaxRound(ui->m_maxRoundSpin->value()); filter.setResult(PgnGameFilter::Result(ui->m_resultCombo->currentIndex())); filter.setResultInverted(ui->m_invertResultCheck->isChecked()); int side = ui->m_playerSideCombo->currentIndex() - 1; if (side == -1) side = Chess::Side::NoSide; filter.setPlayer(ui->m_playerEdit->text(), Chess::Side::Type(side)); filter.setOpponent(ui->m_opponentEdit->text()); return filter; } cutechess-20111114+0.4.2+0.0.1/projects/gui/src/pgnimporter.h0000664000175000017500000000373311657223322022341 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef PGN_IMPORTER_H #define PGN_IMPORTER_H #include #include #include class PgnDatabase; /*! * \brief Reads PGN database in a separate thread. * * \sa PgnDatabase */ class PgnImporter : public QThread { Q_OBJECT public: /*! Import error. */ enum Error { FileDoesNotExist, //!< The PGN file was not found IoError //!< A generic I/O error }; /*! * Constructs a PgnImporter with \a parent and \a fileName as * database to be imported. */ PgnImporter(const QString& fileName, QObject* parent = 0); /*! Returns the file name of the database to be imported. */ QString fileName() const; // Inherited from QThread virtual void run(); public slots: /*! Aborts the import. */ void abort(); signals: /*! Emitted when \a database is read. */ void databaseRead(PgnDatabase* database); /*! * Emitted periodically to give progress information about the import. * * The import was initiated at \a started and so far \a numReadGames have * been read. */ void databaseReadStatus(const QTime& started, int numReadGames); /*! * Emitted when an error is encountered during the import. * * \sa Error */ void error(int error); private: QString m_fileName; bool m_abort; }; #endif // PGN_IMPORTER_H cutechess-20111114+0.4.2+0.0.1/projects/gui/src/pgnimporter.cpp0000664000175000017500000000362311657223322022672 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "pgnimporter.h" #include #include #include #include #include "pgndatabase.h" PgnImporter::PgnImporter(const QString& fileName, QObject* parent) : QThread(parent), m_fileName(fileName) { m_abort = false; } QString PgnImporter::fileName() const { return m_fileName; } void PgnImporter::abort() { m_abort = true; } void PgnImporter::run() { QFile file(m_fileName); QFileInfo fileInfo(m_fileName); const QTime startTime = QTime::currentTime(); static const int updateInterval = 1024; int numReadGames = 0; if (!fileInfo.exists()) { emit error(PgnImporter::FileDoesNotExist); return; } if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { emit error(PgnImporter::IoError); return; } PgnStream pgnStream(&file); QList games; forever { PgnGameEntry* game = new PgnGameEntry; if (m_abort || !game->read(pgnStream)) { delete game; break; } games << game; numReadGames++; if (numReadGames % updateInterval == 0) emit databaseReadStatus(startTime, numReadGames); } PgnDatabase* db = new PgnDatabase(m_fileName); db->setEntries(games); db->setLastModified(fileInfo.lastModified()); emit databaseRead(db); } cutechess-20111114+0.4.2+0.0.1/projects/gui/src/importprogressdlg.h0000664000175000017500000000274411657223322023562 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef IMPORT_PROGRESS_DIALOG_H #define IMPORT_PROGRESS_DIALOG_H #include class PgnImporter; namespace Ui { class ImportProgressDialog; } /*! * \brief Dialog for PGN database import progress. * * \sa PgnImporter */ class ImportProgressDialog : public QDialog { Q_OBJECT public: /*! Constructs a new ImportProgressDialog with \a importer. */ ImportProgressDialog(PgnImporter* pgnImporter, QWidget* parent = 0); /*! Destroys the dialog. */ virtual ~ImportProgressDialog(); private slots: void onImporterFinished(); void onImportError(int error); void updateImportStatus(const QTime& startTime, int numReadGames); private: PgnImporter* m_pgnImporter; int m_lastUpdateSecs; bool m_importError; Ui::ImportProgressDialog* ui; }; #endif // IMPORT_PROGRESS_DIALOG_H cutechess-20111114+0.4.2+0.0.1/projects/gui/src/pgngameentrymodel.cpp0000664000175000017500000000744511657223322024053 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "pgngameentrymodel.h" #include #include #include struct EntryContains { EntryContains(const PgnGameFilter& filter) : m_filter(filter) { } typedef bool result_type; inline bool operator()(const PgnGameEntry* entry) { return entry->match(m_filter); } PgnGameFilter m_filter; }; const QStringList PgnGameEntryModel::s_headers = (QStringList() << tr("Event") << tr("Site") << tr("Date") << tr("Round") << tr("White") << tr("Black") << tr("Result") << tr("Variant")); PgnGameEntryModel::PgnGameEntryModel(QObject* parent) : QAbstractItemModel(parent), m_entryCount(0) { connect(&m_watcher, SIGNAL(resultsReadyAt(int,int)), this, SLOT(onResultsReady())); } const PgnGameEntry* PgnGameEntryModel::entryAt(int row) const { return m_filtered.resultAt(row); } void PgnGameEntryModel::setEntries(const QList& entries) { m_watcher.cancel(); m_watcher.waitForFinished(); m_entries = entries; applyFilter(QString()); } void PgnGameEntryModel::onResultsReady() { if (m_entryCount < 1024) fetchMore(QModelIndex()); } void PgnGameEntryModel::applyFilter(const PgnGameFilter& filter) { beginResetModel(); m_entryCount = 0; m_filtered = QtConcurrent::filtered(m_entries, EntryContains(filter)); m_watcher.setFuture(m_filtered); endResetModel(); } void PgnGameEntryModel::setFilter(const PgnGameFilter& filter) { m_watcher.cancel(); m_watcher.waitForFinished(); applyFilter(filter); } QModelIndex PgnGameEntryModel::index(int row, int column, const QModelIndex& parent) const { if (!hasIndex(row, column, parent)) return QModelIndex(); return createIndex(row, column); } QModelIndex PgnGameEntryModel::parent(const QModelIndex& index) const { Q_UNUSED(index); return QModelIndex(); } int PgnGameEntryModel::rowCount(const QModelIndex& parent) const { if (parent.isValid()) return 0; return m_entryCount; } int PgnGameEntryModel::columnCount(const QModelIndex& parent) const { if (parent.isValid()) return 0; return s_headers.count(); } QVariant PgnGameEntryModel::data(const QModelIndex& index, int role) const { if (index.isValid() && role == Qt::DisplayRole) { PgnGameEntry::TagType tagType = PgnGameEntry::TagType(index.column()); return m_filtered.resultAt(index.row())->tagValue(tagType); } return QVariant(); } QVariant PgnGameEntryModel::headerData(int section, Qt::Orientation orientation, int role) const { if (role == Qt::DisplayRole && orientation == Qt::Horizontal) return s_headers.at(section); return QVariant(); } bool PgnGameEntryModel::canFetchMore(const QModelIndex& parent) const { Q_UNUSED(parent); return m_entryCount < m_filtered.resultCount(); } void PgnGameEntryModel::fetchMore(const QModelIndex& parent) { Q_UNUSED(parent); int remainder = m_filtered.resultCount() - m_entryCount; int entriesToFetch = qMin(1024, remainder); Q_ASSERT(entriesToFetch >= 0); if (entriesToFetch == 0) return; beginInsertRows(QModelIndex(), m_entryCount, m_entryCount + entriesToFetch - 1); m_entryCount += entriesToFetch; endInsertRows(); } cutechess-20111114+0.4.2+0.0.1/projects/gui/src/chessclock.cpp0000664000175000017500000000566011657223322022450 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "chessclock.h" #include #include #include ChessClock::ChessClock(QWidget* parent) : QWidget(parent), m_totalTime(0), m_timerId(-1), m_infiniteTime(false), m_nameLabel(new QLabel()), m_timeLabel(new QLabel()) { m_defaultPalette = m_timeLabel->palette(); m_timeLabel->setAutoFillBackground(true); m_nameLabel->setTextFormat(Qt::RichText); m_nameLabel->setAlignment(Qt::AlignHCenter); m_timeLabel->setTextFormat(Qt::RichText); m_timeLabel->setAlignment(Qt::AlignHCenter); QVBoxLayout* layout = new QVBoxLayout(); layout->addWidget(m_nameLabel); layout->addWidget(m_timeLabel); setLayout(layout); } void ChessClock::setPlayerName(const QString& name) { if (name.isEmpty()) m_nameLabel->clear(); else m_nameLabel->setText(QString("

%1

").arg(name)); } void ChessClock::setInfiniteTime(bool infinite) { m_infiniteTime = infinite; if (!infinite) return; stopTimer(); m_timeLabel->setText(QString("

%1

").arg("inf")); } void ChessClock::setTime(int totalTime) { if (m_infiniteTime) return; QTime timeLeft = QTime().addMSecs(abs(totalTime + 500)); QString format; if (timeLeft.hour() > 0) format = "hh:mm:ss"; else format = "mm:ss"; QString str; if (totalTime <= -500) str.append("-"); str.append(timeLeft.toString(format)); m_timeLabel->setText(QString("

%1

").arg(str)); } void ChessClock::start(int totalTime) { QPalette tmp = m_timeLabel->palette(); tmp.setColor(QPalette::Normal, QPalette::WindowText, m_defaultPalette.color(QPalette::Normal, QPalette::Window)); tmp.setColor(QPalette::Normal, QPalette::Window, m_defaultPalette.color(QPalette::Normal, QPalette::WindowText)); m_timeLabel->setPalette(tmp); if (!m_infiniteTime) { m_time.start(); m_totalTime = totalTime; m_timerId = startTimer(1000); setTime(totalTime); } } void ChessClock::stop() { m_timeLabel->setPalette(m_defaultPalette); stopTimer(); if (!m_infiniteTime) setTime(m_totalTime - m_time.elapsed()); } void ChessClock::timerEvent(QTimerEvent* event) { if (!event) return; if (event->timerId() == m_timerId) setTime(m_totalTime - m_time.elapsed()); } void ChessClock::stopTimer() { if (m_timerId != -1) { killTimer(m_timerId); m_timerId = -1; } } cutechess-20111114+0.4.2+0.0.1/projects/gui/src/gamedatabasedlg.h0000664000175000017500000000406011657223322023052 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef GAME_DATABASE_DIALOG_H #define GAME_DATABASE_DIALOG_H #include #include #include class QModelIndex; class PgnDatabaseModel; class PgnGameEntryModel; class PgnDatabase; class BoardView; class BoardScene; namespace Ui { class GameDatabaseDialog; } /*! * \brief Dialog for viewing game databases. * * \sa GameDatabaseManager */ class GameDatabaseDialog : public QDialog { Q_OBJECT public: /*! Constructs a new GameDatabaseDialog. */ GameDatabaseDialog(QWidget* parent = 0); /*! Destroys the dialog. */ virtual ~GameDatabaseDialog(); private slots: void databaseSelectionChanged(const QModelIndex& current, const QModelIndex& previous); void gameSelectionChanged(const QModelIndex& current, const QModelIndex& previous); void viewNextMove(); void viewPreviousMove(); void viewFirstMove(); void viewLastMove(); void updateSearch(const QString& terms = QString()); void onSearchTimeout(); void onAdvancedSearch(); private: BoardView* m_boardView; BoardScene* m_boardScene; QVector m_moves; int m_moveIndex; PgnDatabaseModel* m_pgnDatabaseModel; PgnGameEntryModel* m_pgnGameEntryModel; PgnDatabase* m_selectedDatabase; QTimer m_searchTimer; QString m_searchTerms; Ui::GameDatabaseDialog* ui; }; #endif // GAME_DATABASE_DIALOG_H cutechess-20111114+0.4.2+0.0.1/projects/gui/src/pgndatabase.cpp0000664000175000017500000000461511657223322022577 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "pgndatabase.h" #include #include #include PgnDatabase::PgnDatabase(const QString& fileName, QObject* parent) : QObject(parent), m_fileName(fileName) { QFileInfo fileInfo(m_fileName); m_displayName = fileInfo.fileName(); } PgnDatabase::~PgnDatabase() { qDeleteAll(m_entries); } void PgnDatabase::setEntries(const QList& entries) { qDeleteAll(m_entries); m_entries = entries; } QList PgnDatabase::entries() const { return m_entries; } QString PgnDatabase::fileName() const { return m_fileName; } QDateTime PgnDatabase::lastModified() const { return m_lastModified; } void PgnDatabase::setLastModified(const QDateTime& lastModified) { m_lastModified = lastModified; } QString PgnDatabase::displayName() const { return m_displayName; } void PgnDatabase::setDisplayName(const QString& displayName) { m_displayName = displayName; } PgnDatabase::PgnDatabaseError PgnDatabase::game(const PgnGameEntry* entry, PgnGame* game) { Q_ASSERT(entry != 0); Q_ASSERT(game != 0); QFile file(m_fileName); QFileInfo fileInfo(m_fileName); if (!fileInfo.exists()) return DatabaseDoesNotExist; if (fileInfo.lastModified() != m_lastModified) return DatabaseModified; if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { qDebug() << "PgnDatabase::game(): QIODevice error:" << file.error(); return IoDeviceError; } PgnStream pgnStream(&file); if (!pgnStream.seek(entry->pos(), entry->lineNumber())) { qDebug() << "PgnDatabase::game(): PgnStream error: seek() failed"; return StreamError; } if (!game->read(pgnStream)) { qDebug() << "PgnDatabase::game(): PgnGame error: read() failed"; return StreamError; } return NoError; } cutechess-20111114+0.4.2+0.0.1/projects/gui/src/engineconfigproxymodel.cpp0000664000175000017500000000266011657223322025102 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "engineconfigproxymodel.h" #include #include EngineConfigurationProxyModel::EngineConfigurationProxyModel(QObject *parent) : QSortFilterProxyModel(parent) { } void EngineConfigurationProxyModel::setFilterVariant(const QString& variant) { m_filterVariant = variant; invalidateFilter(); } bool EngineConfigurationProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const { QModelIndex variantsIndex = sourceModel()->index(sourceRow, 4, sourceParent); QStringList variants(sourceModel()->data(variantsIndex).toStringList()); if (!m_filterVariant.isEmpty() && !variants.contains(m_filterVariant)) return false; return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent); } cutechess-20111114+0.4.2+0.0.1/projects/gui/src/timecontroldlg.h0000664000175000017500000000311111657223322023007 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef TIMECONTROLDIALOG_H #define TIMECONTROLDIALOG_H #include #include namespace Ui { class TimeControlDialog; } /*! * \brief A dialog for setting a chess game's time controls */ class TimeControlDialog : public QDialog { Q_OBJECT public: /*! * Creates a new time control dialog. * * The dialog is initialized according to \a tc. */ explicit TimeControlDialog(const TimeControl& tc, QWidget *parent = 0); /*! Destroys the dialog. */ virtual ~TimeControlDialog(); /*! Returns the time control that was set in the dialog. */ TimeControl timeControl() const; private slots: void onTournamentSelected(); void onTimePerMoveSelected(); void onInfiniteSelected(); private: enum TimeUnit { Seconds, Minutes, Hours }; int timeToMs() const; void setTime(int ms); Ui::TimeControlDialog *ui; }; #endif // TIMECONTROLDIALOG_H cutechess-20111114+0.4.2+0.0.1/projects/gui/src/autoverticalscroller.h0000664000175000017500000000263411657223322024242 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef AUTO_VERTICAL_SCROLLER_H #define AUTO_VERTICAL_SCROLLER_H #include class QAbstractItemView; /*! * \brief Automatically scroll an item view when new items are added. * * AutoVerticalScroller automatically scrolls an item view vertically when * new items are added. Automatic scrolling only happens when the scroll bar * is positioned at the bottom and thus the user has always control of the * behavior. */ class AutoVerticalScroller : QObject { Q_OBJECT public: AutoVerticalScroller(QAbstractItemView* view, QObject* parent = 0); private: QAbstractItemView* m_view; bool m_scrollToBottom; private slots: void onRowsAboutToBeInserted(); void onRowsInserted(); }; #endif // AUTO_VERTICAL_SCROLLER_H cutechess-20111114+0.4.2+0.0.1/projects/gui/src/movelistmodel.cpp0000664000175000017500000000654111657223322023211 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "movelistmodel.h" #include const QStringList MoveListModel::m_headers = (QStringList() << QString("#") << tr("White") << tr("Black")); MoveListModel::MoveListModel(QObject* parent) : QAbstractItemModel(parent), m_game(0) { } void MoveListModel::setGame(ChessGame* game) { Q_ASSERT(game != 0); if (m_game != 0) { disconnect(m_game); m_game->disconnect(this); } m_game = game; m_moveList.clear(); foreach (const PgnGame::MoveData& md, m_game->pgn()->moves()) m_moveList.append(qMakePair(md.moveString, md.comment)); connect(m_game, SIGNAL(moveMade(Chess::GenericMove, QString, QString)), this, SLOT(onMoveMade(Chess::GenericMove, QString, QString))); reset(); } QModelIndex MoveListModel::index(int row, int column, const QModelIndex& parent) const { if (!hasIndex(row, column, parent)) return QModelIndex(); return createIndex(row, column); } QModelIndex MoveListModel::parent(const QModelIndex& index) const { Q_UNUSED(index); return QModelIndex(); } int MoveListModel::rowCount(const QModelIndex& parent) const { if (parent.isValid()) return 0; if (m_game) { int movesCount = m_moveList.size(); if (movesCount % 2 == 0) { return movesCount / 2; } else { return (int)(movesCount / 2) + 1; } } else return 0; } int MoveListModel::columnCount(const QModelIndex& parent) const { if (parent.isValid()) return 0; return m_headers.count(); } QVariant MoveListModel::data(const QModelIndex& index, int role) const { if (index.isValid() && role == Qt::DisplayRole) { if (index.column() == 0) return QString::number(index.row() + 1); if (m_moveList.size() > ((index.row() * 2) + index.column() - 1)) { int i = (index.row() * 2) + index.column() - 1; const QPair pair(m_moveList.at(i)); if (pair.second.isEmpty()) return pair.first; else return pair.first + " {" + pair.second + " }"; } } return QVariant(); } QVariant MoveListModel::headerData(int section, Qt::Orientation orientation, int role) const { if (role == Qt::DisplayRole && orientation == Qt::Horizontal) return m_headers.at(section); return QVariant(); } void MoveListModel::onMoveMade(const Chess::GenericMove& move, const QString& sanString, const QString& comment) { Q_UNUSED(move); m_moveList.append(qMakePair(sanString, comment)); int movesCount = m_moveList.size(); if (movesCount % 2 == 0) { QModelIndex indexToUpdate = index(movesCount / 2, 1); emit dataChanged(indexToUpdate, indexToUpdate); } else { beginInsertRows(QModelIndex(), (int)(movesCount / 2), (int)(movesCount / 2)); endInsertRows(); } } cutechess-20111114+0.4.2+0.0.1/projects/gui/src/mainwindow.h0000664000175000017500000000452711657223322022151 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef MAINWINDOW_H #define MAINWINDOW_H #include #include namespace Chess { class Board; class Move; } class QMenu; class QAction; class QTextEdit; class QCloseEvent; class BoardScene; class QGraphicsView; class MoveListModel; class EngineConfigurationModel; class ChessClock; class PlainTextLog; class ChessGame; class PgnGame; /** * MainWindow */ class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(ChessGame* game); virtual ~MainWindow(); QString windowListTitle() const; protected: virtual void closeEvent(QCloseEvent* event); private slots: void newGame(); void gameProperties(); void manageEngines(); void saveLogToFile(); void onWindowMenuAboutToShow(); void showGameWindow(); void updateWindowTitle(); bool save(); bool saveAs(); void import(); private: void createActions(); void createMenus(); void createToolBars(); void createDockWindows(); void readSettings(); QString genericWindowTitle() const; bool saveGame(const QString& fileName); bool askToSave(); QMenu* m_gameMenu; QMenu* m_viewMenu; QMenu* m_enginesMenu; QMenu* m_windowMenu; QMenu* m_helpMenu; BoardScene* m_boardScene; QGraphicsView* m_boardView; MoveListModel* m_moveListModel; ChessClock* m_chessClock[2]; QAction* m_quitGameAct; QAction* m_gamePropertiesAct; QAction* m_newGameAct; QAction* m_closeGameAct; QAction* m_saveGameAct; QAction* m_saveGameAsAct; QAction* m_importGameAct; QAction* m_manageEnginesAct; QAction* m_showGameDatabaseWindowAct; PlainTextLog* m_engineDebugLog; ChessGame* m_game; PgnGame* m_pgn; QString m_currentFile; }; #endif // MAINWINDOW_H cutechess-20111114+0.4.2+0.0.1/projects/gui/src/autoverticalscroller.cpp0000664000175000017500000000267611657223322024603 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include #include #include "autoverticalscroller.h" AutoVerticalScroller::AutoVerticalScroller(QAbstractItemView* view, QObject* parent) : QObject(parent), m_view(view), m_scrollToBottom(false) { connect(m_view->model(), SIGNAL(rowsAboutToBeInserted(const QModelIndex&, int, int)), this, SLOT(onRowsAboutToBeInserted())); connect(m_view->model(), SIGNAL(rowsInserted(const QModelIndex&, int, int)), this, SLOT(onRowsInserted())); } void AutoVerticalScroller::onRowsAboutToBeInserted() { m_scrollToBottom = m_view->verticalScrollBar()->value() == m_view->verticalScrollBar()->maximum(); } void AutoVerticalScroller::onRowsInserted() { if (m_scrollToBottom) m_view->scrollToBottom(); } cutechess-20111114+0.4.2+0.0.1/projects/gui/res/0000775000175000017500000000000011657223322017616 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/projects/gui/res/chessboard/0000775000175000017500000000000011657223322021733 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/projects/gui/res/chessboard/chessboard.qrc0000664000175000017500000000013411657223322024555 0ustar oliveroliver default.svg cutechess-20111114+0.4.2+0.0.1/projects/gui/res/chessboard/default.svg0000664000175000017500000024437611657223322024120 0ustar oliveroliver image/svg+xml cutechess-20111114+0.4.2+0.0.1/projects/gui/res/icons/0000775000175000017500000000000011657223322020731 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/projects/gui/res/icons/cutechess_win.rc0000664000175000017500000000010511657223322024116 0ustar oliveroliverIDI_ICON1 ICON DISCARDABLE "cutechess_win.ico" cutechess-20111114+0.4.2+0.0.1/projects/gui/res/icons/cutechess_24x24.png0000664000175000017500000000227711657223322024300 0ustar oliveroliver‰PNG  IHDRàw=øsRGB®ÎébKGDÿÿÿ ½§“ pHYs  œtIMEÛ "Ë̀s•tEXtCommentCreated with GIMPWIDATHÇ¥•[l“eÇÿïûơë×ăÚ®v c Ăm™Éâ„ÉĐhD‰L.4îÆ…ÄhbŒ‡[£1$&c²À ¸iÆƯđ€Ö±C»u=mk×ózüö}¯zAˆ¤k}®ŸçÿËs&(b÷bi5Bêl&Ó̃z‹¸ÓªK@­½ßR±pĐbÏnÇ&s`Œ‘w†fä™97bk+L£ÖGº»‚¹ĐRÏë}=ó!Æ`#¤ü9—×_Èd²ˆFÂ,‰ḉÚØØtˆÅ;2Ù,¥”£j^÷ø=a¯k̀7}kÀ(©¬Ÿ €¨yZa¬ª3ÉL¦Œ1I ¯cÅ6ùoơÄSˇ¢eIEND®B`‚cutechess-20111114+0.4.2+0.0.1/projects/gui/res/icons/cutechess_win.ico0000664000175000017500000033337411657223322024305 0ustar oliveroliverhfHÎ ¨  @@(2¾€€(ÈæI î¤( \B\B\B\B\B\B\B\B\B\BtZ1¤w3°ˆJŰáĐ´Å°e8\B\B\B\B\B\B\B\B\B\B\BtZ1¤w3ŰáĐ´e8\BÎÅ·ơëÖ\B\B\B\B\B\B\BäæèûïÜûùö\B°ˆJáĐ´tZ1\B\Bÿÿÿÿÿÿ\B°ˆJáĐ´tZ1\B_][\B°ˆJáĐ´tZ1\B²²w\B°ˆJŰ\BtZ1œ†b{qctZ1\B°ˆJŰ\B +tZ1\B\B\B¤w3°ˆJ¶’[tZ1\B\B°ˆJ°ˆJ\B\B¤w3°ˆJ¸Q°ˆJ°ˆJ°ˆJ¿¡q\BtZ1\B¤w3°ˆJ¸Q°ˆJ°ˆJ¿¡q\BtZ1\BtZ1\B¤w3°ˆJ°ˆJæz\BtZ1\B\B¤w3¤w3\BtZ1tZ1\B\B\BtZ1àààđđø?ø?ø?øđGđđđđøø?(0 bP4†sWkcVbZLe\NrhWVH22*ÿÿÿǺ¤È´•ØÅ¨âͬ·¡~µy¶Ÿ|ì‰ƠÀ ¿®’vbäÙÈăͪ̀ªv¼œk}e?|b:y`:uO Q°`Ï»52-éßĐÚĂ¡̃Ê«̃Ê«´¦’—Œ{›}¿°—Đ½ Ë¶™ØÅ©[WPøñçùñ羟nη‘ɽ«±§µ­¢Ë¾©¨j¾©ˆươèÁ¸ªûøôúöîÿưøÈ©{™xDQ<V>n=ͼ¢₫ùđñêƯÙÜ̃ÿÿÿúơîüøî₫ûơ·‘W¢‚OqW/rY0l;¿¨…Éļo}Ÿ]VKñ́äưøñªB›xCmP"oQ"‰i9ÜÅ¢zxsöîà¥z8›w@mP"oQ"§†SѾ óéÙ®†H¢‚Qv[0|a7Ȧq¡“|ÿÿÿ́̃Ȭ?Œm>aEoDĂŸfsdJÿÿÿáϲ§}<{^3^B¸—a°\`YRzp`xn`%"ÿÿÿÜȧ¯‰Nw_8hAÈ£ip`IVSN˜‚bϬvij˜ÿÿÿØÀ©‚FeL&Ÿ†aáĂ—ƯÅ ªd“r>±‡HåÊ£…{kÿÿÿÖ¾›¹•^±W»–\âÆ™©Z~Z"„_)ª…KÄ¢oå̉µ420ÿÿÿä̉·¯…E¸S°ŒT¨]zV[$^'ŧzåƠ»ùóêÿÿÿö́Ư°‡H²‘^ˆd,‹i4g2zUÁ¤vàęƳ—ÿÿỵ̈å̉ùïâ˱ˆ™wAƒ_'ƒ_%n9À¤x䯷­óæÓΫuŸ|E‹h0]$·—eáÇŸ·±¥ÿíÇÿÿÿ×µ´Wœ{F¦„PßÀ‘Àª‰ÿÿêöëÜƯ–̀«zÙĂ£Ä¸¤’„pÉ­ƒ¾iîßÇäÙÇâͯ϶à̀®ôëÚÿÿÿÿ€ÿ₫₫ü?ü?₫ÿÿÿÿÿÿÿÿÿÿÿ?ÿ?ÿÿÿ?ÿÿÿÿÿÿƒÿÿ‡ÿÿÏÿÿÿÿ( @ A<583+=80=80=80+)(SMC‡oLät¡”‡{f†ye}i~j»¥‚‰qLYK7ÙÊ³Đ¶éØ¾îÚ»½¦ƒ¸x¸x¸Ÿy¶v̉¼™áͯ̉Á¦Àª‡TPKÁ¿¾đáÉáÆœÉ¦pÁœenT+dHcHaF^C—{Q›yF­ŒZϵŒĐIJææäȪ{´TĐ´‹êÜÄụ̂ăỵ̈Ưỵ̈Üỵ̈Üỵ̈ƯôèÖκœ¤ˆ]…b.ăƠÀđèƯ÷ïăụ́åëÜÆÏ¶¬’i( -%-$aT?¡†]̀¹›ñå̉ùñăøêƠ^[Vùóéøđåớß«„H˱‰éÜÈÎĵ̀µ̀ĹâÛÏ̀» Ÿ…]§eùđăùđă¾´¤ùóêäÓĂû÷̣úốÿûöϳ‹²‰Ky`:H1E/ Œm=“uGÛκưøïö́Ưëèá÷îàúơíưøñ³‹N°‡GzVjU3hR0‚V{W!¾¦ƒùóêƯÙÓưùô½›g²ŒQpDkMhK”vHp@ÙÉ®wrlûớ¦|;¦{9pHiKgIqCj9́×´~zuöîà¤z8¦|:‹nBiKgIŒoBº—aÜ˱óèÙ¢v4¥{9ŒoCkM hJ¯•lºK±¨´³¯̣ç׸”\Ÿi†pMz_4w^8ϱ‚̉°|RV[ñêàéÙ¨|7³Z]AaE‚hAÄ™W³–hôđçáΰ©|:Q_C^A°‘`—S}j‡~641ó́ßÙ °…D‹qIbFlS+È b l")º–`ôܺƒzköïåÛŤ½–[‚lIz`9…^̀¨opY431ul_§’sª~:ˬ}ïÙ¶öñèƠ»•¶NiP)iO(¬•păǼÑ©î̉¦¤…U‡d0¶Sª=èѯ¥˜„öïäÓ¹“¾d¨]¸‘T»–^çʛڿ–h5["Z"©‰Wª~;ÁiôƯ¸:72öïä̃Ê«³ŒO¼—_­‚A¸’XƬ„~Z#€\$\%€\$„a,Ø¿™ïâÍöîáụ̂äùợçÖ¼¨{8¾d´‹L¢‚O~O}Y!\%€\$}Y!Ë®„äÄ“À±™ÿÿÿøï௅GĤr™xD€\"…a)™yH[#|X ƪ€åĔʺ¢ö́Ưи‘©‡Sl7‚^$]$’q=‡d/æ{åŕǷ÷îàØºŒh+¤„Q€\!‚^$~Yȯ‡éΣɻ¥óèÖêØº̉ªl¸˜f›u;m7€[!®aăÀ‰̀·™Ù¸„ص~–p5¤…S}Kă¿‰ÖÀâȡԲ|ĐµÔ¾Âµ¡±¡‰ÿÿÿôé×÷í̃®…F¯†G̣ằéƯÊÓº”èØ¿öị́̃ñđđä̉ÿÿÿÿÿøÿÿÀÿÿ€ÿÿ€ÿÿ€ÿÿÿÿÿÿ€ÿÿÀÿÿàÿÿàÿÿàÿÿàÿÿàÿÿàÿÿà=ÿÿà8ÿÿàÿàÿà?ÿàÿàÿÿàÿÿàÿÿàÿÿđÿÿđÿÿđ?ÿÿøÿÿùÿÿÿÿÿÿ(@€><:wpecZLcZLbYKjaRlbTlbTlbSlbTkcSuod*)(~td¸ {·”\‰x\(((' ' (* * (˜‚^–xJ¡nnfXlf^¦“tÁ¡n§A·–bÖÁŸíâÑàĐ·áѸáѸáѸáѸäƠ»éØ¿éØ¿éÙÀë̃ÊÁ­•yN|\*€S˜…hg`VèÛȧ¥¡Ó¼˜ªƒF±Vѹ”́ƯÅùïậåÏÜÎ¹Đ¿¦Ï½¤Î»ŸÎ»ŸÎ»ŸÍ¹œ̀¸›̀¸›Ë¸àÑ»í̃ÈûñàéÙÁÁ¬‘uJ|\*·Ÿy^ZVâÜ̉âÓºçƠ»ùđâóæ̉èÓ³ÛºˆáÅ—­‘f¡Q¡Q¡Q¡Q¢„V¤‡Z¥‡Z¥‡Z¤‡Zư¬…Jµ“^Ó½œ́ƯÇüñàæÖ½Ù͸áƠĂøñèø̣çëØ»Ü½Ø´}ß–̉´‡Ơ¼”y^3nQ%nR%oR%nR%kO$iM#iN$hM"iM#†c¨Œc¶nÁ¢q®‰O´’^Ó¾œíàÍøë×ca]ñëăïàÉ׳{àĂ—Ô·ŒÂ¢p¬‚B«€>³K‹vUdI dI dJ!dI!dJ"dJ"dJ!dI!cI! ˆc[%[$^) ƒV´˜mÁ¡r²VÜÊ®ßÓÀôïçàË¬Ă£r®„D«€?¬@¶TжæÖ»ốßđäÑđä̉đạ̈̉äỊ̈äỊ̈äỊ̈äỊ̈äỊ̈äÎơëÜׯª´ym:€\&[$€]'{Mʶ–üơéÚỜÚÄ¢­‚A¸“[Ó¹“éØ¿÷îßơêØơëÚö́̃÷ê×øéÑøéÑøéÑøéÑøéÑøéÑøèÑøî̃ôèƠơèÖôçÔøíÜẩ¹Áª‰{N‚_*ůŒçßÓôíâớ̃́ßËøí̃ơéØơëÚơêÙøî̃́̃ÈƠ¿«œ„YPBZPBZQBZQBZQBYPBWN?¬Ÿ‹Â®ăƠ¾ùíÛơèÔơèƠơèƠǿÚîâĐđăĐôäËedcñëâ÷ïâùôëụ̀èùóé÷íƯæÖ¾Îµ²W¥{<¢x8~a‘yRvU xW#ˆj;¯vÔ§óçØøñæøđăøđåïßÅÛÑÁ÷đäøñçùñçùñæùñççØĂ£z:¢x8£z9¨€CÁ¤xƠư¨Œ©©®¨Ÿ¯©Ÿ¯©Ÿ®¨ÑƵ¤Œf€`.wU!vT vU!̀¸›÷đäøïá÷îàớƯíàÊêÖ·ơëàúơîøđäøđåùôëñæÖ´“]ζæØÁụ́çúóçúóçíäØƠʹƠʹÑȹÑȹÑǹéà̉ùñăươéüôèàÔ¿¾«™ŨͲơèÖ÷ïâ÷îàùóéĐȽøóëûøóû÷ñúóêùôëưụ̀úốóèØ̃ʬȪ|±‰L¯”iL6L6M7M7L6œƒ[‚`,¢‡^ð’äØÄûöíưøñùñæï̃ĂúôëüøñçăƯưûúúơîûöîùơëø̣èû÷ï¢r«€>«€>«€?®’fM7N8N8N8L7œ‚Z{X!|X"|X"„c0₫øîụ̀èùóèôéÙûöïÔÎÆ̣åÏúơîúơíúöïúơëŸl«€>«€?«€?ªbL6M7M7M7L7œ‚Z|X"|X"|X"„b0ù́ÙùóéúơíùơŸơè×ụ̀éúöîúóèÀj«€?­‚B»˜aưˆsRˆsS‰tSˆsRˆqL½¨‡˜yJ](|Y"ƒb0ùíÙùđấç̃uog¢¤¤ùúüụ̀çÔ»”È©zŧxµ‘Y±–kkN"kN!lO"kO!iM ¤ˆ\‹k<§‹`©d¯–oöéÔÏȽđëåưøñ´’Z¥{:¥{:¥{9¯“hiKiKjLiKiK¡‰cxV!yV!yW"µŸ{÷í̃º³©îéăûôê­†I¥z9¦{:¥z9­•niKiKjLiKiK¡‰exU yV!†g7àɦï̃ÁÀ¸­ñëăúđ᪃E¥{:¦{:¥{9¬–riKjLjLjLiL¡…XyW"yW"¾¢xƠ¹̣áÅzwṛêàơëܨA¥{:¦{:¥{:®’giLjLjLjLiL†`yW"•xKÈ£kÜœîáËóëß̣å̉§~?¥{:¦{:¥{;®’fiKiKjLiKiK‡cyX$ɬ€¹Năͬ­¦™ớà́à˦|<¥{:¦z9¥{:¬aiKiKjLiKiK‚U§fÀ˜YºNđ̃ÂSQO÷îâéÙÁ¥{;¥z9¥{:¦}=¯“hnQ%mQ$lO"lN kN!‡cÍ®ºM¼’R̃̉Á‰wVøñåăÓ¹ª‚DÁ¢pÈ©zÊ«}¸¥‰‘}\’wO”zR”€c•{Tȵ—Ö¹‹Ï¯Â]Ÿ›ëèå÷îàêÜÇÆ¥s°‡H«?Áct\6`D`DaD`DbGίÀ–UĂ›\ä̀¨ !!̣́ăøđăÙŸ«€>«€>«?¾ saF`D`DaE`DzXÈŸ`À–TÀ–Uµ¡ƒ̣éƯö́Ử¸«€>¬€?¬@©iaE`DaE`DaE¾£xÁ—UÀ–TË¥hie`ơîăö́ÜÊ­«€?«€?³LwTaD`DaE`Du]7Ñ®uÀ–TÀ–Tʲ ôîå÷íƯĂ£s«€?«€?Æ¥sdJ!`DaEaE`D­•oÁ—UÀ–TĂZ‘‡xMMMÛλ–GFDôëƯøđăº•^«€>«€?´™o`D`D`DaEdIĐ²Á–UÀ–TÔµ†Ä®ÁŸmíØ¶đÙ´¼±¡ơîâụ́泌P¯…G·U­—vmP%dI!cHbF™„bÅœ[À–TÁ—V¢’y}wm¸‘W«?ßɦể­óܹCB>ơîăùñåÉ«}ƦtÄ¢n¡u‹sO’{V“|Y“zTѼ›×¹ŒÖ·‰̃Á“+**Á¦~«?«€>¸”[îÚ»ể®ÖDZ÷ïå÷í̃¯…G«€?¶ŒL†nJ`D`D`D`D¶›qÁ˜WÂZäÇ™CBAxm²¤èֺȲ‘Ĥt«@¬>¬?ÙÁœêѬîÖ²lgaöïäøí̃¯…G«€?¹’V}gD`D`DaE`D·¤†ØºŒßÅè̉¯ñÛ·ëÏ¢åÇ™åͧŸU€\%­‘f±ˆJ«€>«€>²NíÚ¼ë̉®êÙ½÷ñç÷í̃¯†G«€?¿cx`:aEbFzX¹ráʦåǘäÇ™äÇäÇ™æÉœ×ÀŸi7€[$[#\&Æ©|«€?¬>¬?̉·ể­ëÓ®“‹€ớà÷íƯ®…F«€>ĂŸi~e>¤Œhæxµ‹N­‚AĐ³‡åÇ™åÈ™äÇ™êЦ¼£}€\'[#€\$\#[$¢…X·T«€>«€>®„Dê×¹ë̉®ôàÁơïåớ̃®„E°ˆI׿›Î¯­ƒB­‚A­‚A­‚@ʬåÈäÆ˜çΩ ƒW€\%[#\#€\$€\$[#€\&¦z¬€?«€>«€?ʬ́×µể®¿³ ÷ñéôëƯƦuÊ«~¯†Hɪ{­‚A®ƒA®ƒA­‚@Ä¥vèÊÙ ‹j9[$[#\#€\$\%\%\#[#œ~P½˜`º–`ØÁïăÏ÷ïáö́Ưøïá„zớßûö́º•]«€?«@Ë­­‚A®ƒA®ƒ@­‚AÄ£qË·—]'[#€\$€\$\%€\$€\$€\$\#[#‰g5çƠ¸ơçÓôèƠớ̃ñèÛôïèøóíö́ÜÈ«~«€>¬€?ˬ~­ƒC®‚@­ƒAÁh§\µp]&[#\#\%\%€\$€\$\#[#…c.ÛĂâÀâÁæÏ«rqmÿÿÿø̣éôéÖàͯ«€?«€?Ǩx°‡H­ƒAŤrœ~O‚]%„a*µq\$[#€\$€\$€\$\#[#…b-ÛÄ¡âÀâÁèЬ…ƒZYZö́ƯôèƠ¯…F«€>µQĂ£qÇ©{“sA]$‚^#]$–vD¡‚T\$\#€\$\#€[#‚_*×ÁâÀâÁçÏ©—”8;Aö́̃öêÙÄ¥u«€>°†GƯÉ«Œj6]#‚^$‚^$‚^#‚^$­‘dh4[#€\$[#^(Ó¼˜âÁâÁæ̀¤–…8:?öíàơé×ÜǦº”Zæ{ºo„`(]#‚^$‚^%‚^$]#]$·œr[$[#]'Ó¼™ăÂâÁæ̀¤”‹-,,÷ïâôêØơéÙ³”d’k.•o4µ›s‚^$‚^#‚^%‚^%‚^$]#‹j4¬c](̀µ‘ăÂâÁæÍ¦–’!!ùơíôçÔèÓ±¿¤y’k-’k.ºp…b+]#‚^$‚^$‚^$‚^#]$¡‚RÖĪëѪèϦëÔ°–“ŒßĂơëÜÔ¯sßÀ“›w?‘j-”m1°”g^$‚^#‚^%‚^$]#^%½£{ăÂáÁèΦ¢›‘æĐ­̉¬n̉«n˱‰’k.‘k.´–h†c,]#‚^#‚]#‚^$¯”jäĂ’̃»„åÅ•³¨˜î̃ÆÓ¬q̉«nÜ»‡¦…R‘j-“m0³—i‚^$‚^$‚^$¢…XäŔ߻„ăÁƹ¦ÿÿÿƯ¿̉«n̉«nÔ¹’k/‘j.ºr‰f0]#–xH䯙߻„ཇƠƯæÏ¬Ó«n̉«nÙµ~³•f‘j-“l0µol9âÆœ̃»ƒß»„áÏ´ơëÛƠ°v̉«n̉«nÛ¿•˜s:œx>Æ®‰ăÓºơƯ¹́Ơ²́ظÿÿÿåѲָ̉µ‡Î°„ñăÎ÷ëØôçÑ÷ê× ßˬ¬‚A«?«?βˆđßÅïßÅïßı¨œâÄ•ÿÿÿ¿j«€>«€>®…Gí̃ÇóæÓôçÓøîàd_X׿›¶T̉¹’ëÛĂ÷í̃ôëÛơïåóåÑôêÜ₫ûöùóéúọ̈ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿÿÿøÿÿÿÿđÿÿÿÿàÿÿÿÿÀÿÿÿÿÀÿÿÿÿÀÿÿÿÿ€ÿÿÿÿ€ÿÿÿÿ€ÿÿÿÿ€ÿÿÿÿÿÿÿÿ€ÿÿÿÿÀÿÿÿÿàÿÿÿÿđÿÿÿÿü?ÿÿÿÿ₫ÿÿÿÿ₫ÿÿÿÿ₫ÿÿÿÿ₫ÿÿÿÿüÿÿÿÿÿüÿÿÿÿÿüÿÿÿÿÿüÿÿÿÿÿüÿÿÿÿÿüÿÿÿÿÿüÿÿÿÿÿüÿÿÿÿÿüóÿÿÿÿüàÿÿÿÿøÀÿÿÿÿø€ÿÿÿø ÿÿÿø?ÿÿÿø?ÿÿÿøÿÿÿøÿÿÿüÿÿÿüÿÿÿüÿÿÿüÿÿÿÿüÿÿÿÿüÿÿÿÿüÿÿÿÿüÿÿÿÿ₫?ÿÿÿÿ₫ÿÿÿÿ₫ÿÿÿÿÿ₫ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ÿÿÿÿÿÿ€?ÿÿÿÿÿÿ€?ÿÿÿÿÿÿÀ?ÿÿÿÿÿÿÀÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ(€           EA;©£™íäÖ¯ ¬œ…«œ…«œ…«œ…«œ„ª›„¨›„§›…§›…§›…§›…§›…§›…§›…§›…§›…§…©ˆÑǵƺ§“„„ƒ~ÙǫԼ–²ZƠÁ£?5$5*3)2(2)2(2(1&0%0%0%0%1&1&1&0%1&1&8.¡uoApBűɺ¢…‚{ trpȺ¤ÜÅ¡¸•`«…K¨E«…JÖ¹I>+7-6,4+6,5,4,5,5,5,5,6,8/ 91!:1":1":1":1"B9+©¡•„f6~^,_.‚d6“wKű’»®{xt A@>°¥•àγ¿Ÿm¬‡N©‚F§Cª„H®‰PÂ¥x́ƯÈÎIJȺ¥Çº¤Çº¤Çº¤Çº¤Çº¤Çº¤Çº¤Çº¤Çº¤Çº¦ÓĂªƠÅ«ÖŬÖŬÖŬÖŬ×Ç®íäƠǵ™ƒY…h:€a1}]+_.ƒe6–yKÔ¿ ¸¬›c`[.)"£”Ûɯ̉·Œ®Rª„I¨D©‚G¬ˆPº›iÚǨñäÑ÷íỰäÎ÷ïäîÜÀîƯÁîƯÁîÜÀîÜÀîÜÀîÜÀîÜÀîÜÀîÜÀïƯÂđßÅđàÆđàÆđàÆđàÆđàÆ̣ằơëÛñâËǿÛèÚĂɸœ›€U…h;b1}^,€a0„e6 „ZÈ·¯£‘geble\ỬÀÛÅ£³W«†K¨E©‚F¬‡M¶•`Ô¾œ́̃ÇùïậăỊ́äÎơëÛụ́çÿûơÿûôÿûôÿûôÿụ́₫ụ̀₫ụ̀₫ụ̀₫ụ̀₫ụ̀₫ụ̀₫÷îươêươêươêươêươêươêüö́û÷ñụ̀æóæ̉đàÇđàÇǿÚêƯÈÆ´—‚W…g9€`0~^,€a0„g9©dáѹjdZåßÖØÅ¥®Q©E«†L±Vϸ”èØ¿øïáóæṆ̃ăÍôçÔøñæóè×çѯ̉©¡„Y€SRQ{L™xH™yH™yH™yH™yH™xH™xH™xH™xH™xH™xH˜xG˜xG˜xH¢…Yá̀«ÚǪîáÎûôéóæ̉đàÅñâÊùîƯæ×Áñ––zM„g9€`0ƒe6º§‡öíàơíâçÙ¶•bÈ­ƒẳ·÷îáôèỘăÍóæÑøñæóçÖêØ»ÛºˆØµăÉŸ°—qh6†d0†c/†c/†b/†b/†b/†b/†b/†b/‡d0‡d0‡e1‡e1‡e1‡e1‡d0‡d1ˆf2m=ØÀ›®‹T®R¹—b×¢îẳùñåóæ̉đßÅñàÆùîÜäÖÀð“„\ÔÅ®đ̃€|¾¹²ùñåø̣çöíßöëỤ́ặ̀äĐùñçôêÙëڿܽŒ×´}Ö²zƠ±xƠ±wđáÉÅ«„½¡x¼ u¼ u¼ u¼ u¼ u¼ u¼ u¼ u¼¡wª…©…ª…ª…ª…ª…ª…ª…ª…Å®ŒçÙĹ•^©ƒH©ƒH«„I¬ˆO¸–bÔ¿Ÿ́àÎûôéóæ̉đßÅñàÈụ́æúöïïƯÂöïǻçà÷íßúöîùóêúôëöîá́ÜẪÁ’صÖ²{Ö±xÔ¯táĘèÑ­à̀­èؾnC}`2|^/|].|^/|^/|^/|^/|^/|^/{^/qV+qV+rW,rW,rW,rW,rV+rW,rW,x_7˵•½ªÔ¼–Ơ½˜»™f¨D©ƒH«…J­‰P·•aƠÁ¡îâĐûôêøđäớƯôéỤ̀âʇ…‚…uúôêúơíụ̀èí߯áśص~׳{Ơ±yÔ¯tàĂ–êÖ·̃ȦƧw³‹P³ŒQѵ‰ˆmDeJ cGaFaFbGcGcGbFbFbFbFbFbFbFbFbEaEbFbGgM&ȳ‘‹j9‡e3k7°–nθ•ØÀ˜Ă¥v¨€CªƒH«…K­‰P·•aÓ¼™êÛÄúóéïÜÂôëƯñíåơëƯîàÉÙ·„׳|Ö²yƠ¯tß•êÔ³ăĐ±Èªz²‹O±‰L®„E¬A­ƒC¿™_¡nfK!aE`EaEaEaEaEaEaEaEaEaEaEaEaE`E`EaFbFqV+è…b.€\%]'„a+‡e1‰g5«b̀¸˜Ô»–Ƨw¬…Jª„I«†K¯ŒT϶ơêØ̣âÊ‚}÷ñèụ̀ç̃¿Ơ°wƯ¾ë׸âÍ­̀¯ƒ´Q±‰L®…E¬‚A¬€?«€?¬A¯†G´SÀ±u]8oW0pW0oW0pW0pW0pW0oV0oV0oV1oV1oV1oV1oV1oV1pV1oV1oV0qY4‹vV¼¦ƒi7ƒ_*]&€\%€\%‚]&ƒ`*†d0‡e1¥aʳ׽—̀²Œ®†Jµ”aøóëïƯÂôëÛŵøñåôè×êÖ¶âͭͱ†µR±M®„F¬‚A«€?«@­‚A¯…F²N¶WÇ©{âеó́áäÛ̀äÚ̀äÚ̀äÚ̀äÚ̀äÚ̀äÚ̀èÛÇêÛÆéÜÆêÜÆêÜÆêÜÆêÜÆêÜÆêÜÆêÜÆêÜÆêÜÇ̣éÛèÜÉȶ ƒXn<ˆg4„`+^(€\%€\%]&ƒ`*‡d1‡f4›|KưÚŤñåÔöí̃ÿơå ùơïèÙĂº–`±‰M®†F­‚A¬@«@¬‚A¯…F²‹O·’Ỳ¯‚äƠ¾óèÖ÷ị́̃åĐöí̃ơêỤ́äỊ́äỊ́äỊ́äỊ́äỊ́äỊ́äỊ́äỊ̂äỊ̂äỊ̂äỊ̂äỊ̂äỊ̂äỊ̂äỊ̂äỊ̂äỊ̂äÍøñæ̣äỊ̂äÍ÷́ÛîáÍÑÁ¨®“kqAi7…c.‚^(€\%€\%]&ƒ_)‡d0pAÑÀ¥üú÷ÜƠÈïêâđä̉¶W­‚A¬@­‚B¯†G²‹P¸“[Ͳ‡åÓ¸ö́Üö́ỰäĐôèÖơêÙôêÚöêÚúôëóæ̉ôç̉ôæ̉ôæ̉ôæ̉ôæ̉ôæ̉ôæ̉ôæ̉ôæ̉ôæ̉ôæ̉ôæ̉ôæ̉óæ̉óæ̉ôæ̉øñæơéØơé×ôèÖôèÔóåÑñáÊ÷́ÚôéØÚʰº¥ƒ—xJ‹k:‡e1ƒ_*]&‚^'m=éÚĂö́Ü¡Ÿœvpgûôêụ̀çÆ¦v²N³Qº•]Óº•éÚÂơëÛöëỤ́åĐôè×ôêÙôêÙơëÚơëÚơêÚôêÙôèƠ÷đặáÉñáÇñáÆñáÆñáÆñáÆñáÆñáÆñáÆñáÆñáÆñáÆñàÆñàÆñàÇóăË÷ïäôæ̉ôèÔôèÖơèÖơéÖôèƠôçƠóæÓñăËôæ̉÷́Üæ×ÀƳ—¡ƒVn?Œk:ªdóäËï̃ÄúøơÜØÓöîàớÜæ×¿Ö¿›èÚÂùîàôé×óåÑôé×ôêÙơêÚơëÚơëÚơêÙôéØóæ̉óçÓøïàñæÔđä̉¡–…—Œz—‹y—‹y—‹y—‹y—‹y—‹y—‹y—‹y—‹y—‹y–‹y–y•‹z¸³­Ú̀¸íàÎùîỰăÍñăÍóçÓôèƠơèƠơéÖơèÖôèƠôçỘäỊ̈âËúñăëƯÈÓĂ©áƠĂíÙ»đßÅöëÚ‡…‚øóê÷ïâ÷îáüøôúơîóèÖôé×ơêÙôëÙơëÚơêÚôêÙôé×óåÑôçÔúñä́̃ÈƠ¿½j°VØ»E;,(!&&&&&&&&&%%&+$†s•xL‡j=™~S¿¬ƯĐºøëÙöéỌ̈âÊóåÑôèÔôèÖơéÖơéÖôèƠôçÔơêØøñæû÷ñđàÇđ̃Äï̃Âøơđíèá÷ïâøđăø̣éúóêøđäûöđûöïö́̃ơêÙôèỌ̈åĐöëÛơêÙèØÀĐ¹•´Z¬‡M¨D¥}>¦~AβˆGA7  #Œ~i†d0yX%zY&~^,ƒd5‹n@®—sÏÀ§íáÍøíÜóäỊ̈ăÎôçÔớƯùốụ̀éöíàöíßøñåïßÄđßÄơèÖ~|u÷ñæ÷îá÷ïăû÷ñøđäùñæùñæøđäûöïúôëóçÖà϶Ȭ‚±Tª…K§€B¤|=¤z:£y9£y9¥}?Ç¥oYPA#       ! !  ! ! )"w^-xW#wU!wU xV"yW$|[)€a1…h9U¿¬áÔÁúöïùóê÷îßøïá÷îá÷îáụ̀ệåĐđßÅï̃ÂæàÖäÉ øñç÷đăøđåúơíùñæùñæùñæùđæøđä₫üùÉ®„¬‡N¦~@¤{<¤z9£y9£y9¤z:¥|=§€C¬‡NĤtˆzeOE5LA2LB2LB2LA2NF7UOGUPGWQHWQHWQHWQHWQH]XO¶±©nB‚d4}]+yY&wV#wU!wU!wU!xV#zY&€`0Vüôèøđå÷îá÷îáøïâøïáöíßùôëïßÅđßÅúï̃øñæ÷îàû÷ñøđäùñæùñæùñæùñæúơíøđäÖÀ¨D£y9¤y9¤{;¦~?©ƒF­ˆPµ’\̉½›æ×¿öíßÿüöÿôâÿôäÿôäÿôäÿôäÿơæÿùîÿùîÿùîÿùîÿùîÿùîÿùïÿúđÿûöớƯÛι¼©—zM†h;b1|[)yX$xV!wU!{Z'§fóä̀ụ̀éö́ßøïáøïâøïá÷îà÷ïäơêÚï̃Ăȸï̃ÄùóéøñèûöïùñæùñæùñæùñæøđäûöñớÜẩ»¬‡M§C«…J°ŒTÂ¥xÜ˰ïăÎưøñøïâöîàøđă÷ïâû÷ñ÷îà÷îßøî̃øî̃÷î̃ùđâøđâùđâùđâùđâùđâøïâû÷ñ÷îàøïâ÷íßøïá₫øđïăÑѨ³y‘uI„f8`0‚c3¼ªŒïÜÀñáÊúố÷îà÷îáøïá÷îá÷îàúơíöëÙGC<üúơøóéøđåøđåøđåùñæúốøñç÷íàîẳ¿ q̉½›çÙĂ÷ïàûơë÷íß÷ïâøđă÷îáøïâü÷đóèÖ́ßËɾ«¬Ÿ‹ªˆ©ˆªˆ¡—…¢—…¢—…¢—…¢—…¤‰Äº©ƯĐ»éƯËư÷́ùñåöí̃÷ïá÷ïáöí̃ụ̀æûơêçÛÈͼ£°™uØÊ¶íÚ¼đàÇơëÛøđåøïà÷îá÷îàøñåúơíđëäôé×åË û÷ñưûùûùôûø̣úơîû÷ñùđä÷ïăûöđÿ₫üúố÷îáøïă÷ïă÷îàúơëøđäéÚĂØÁŸÁŸl·’Zȧu–ƒcZF%T?T?T?U?U?U?U?U?ZE$•`¤‰^Œm?”vF¶Ÿ|Óì́âĐûơéùñä÷íß÷ïâøïăụ̀è₫üùưû÷đáÉñ߯đßÇùñçúöïû÷ñüùôüùóêåß ïƯÁøñçû÷̣úơîûöđûöïùñåụ̀èúơîøñåùóéúöđûø̣ớ̃ß̀°Éª|¸’Y³ŒP°‡I®ƒD®„DÄ i‘}]R=M7M7M7M7M7M7M7M7R=zY€R]'[&‚_+†e3k;™{N¸¢Üιưûøúơîùóéøñåøđåùóëđ߯đàÇøñåùôëùôëü÷đƠĐÈôçƠû÷̣úöïüøóøïăûøóø̣çùóèø̣èø̣çû÷̣ÚÅ¥µT®…E¬‚A«?«€?«€?­ƒCĂ h‘|\R=M7N8N8N8N8N8N8M7R={XQ~[&|Y"|Y"|Y#}Z#\&„b/–yNÿûôúốụ̀èùóèụ̀èùóêö́ƯđàÈùốùóéûöï»´ªơëÛụ̀éưüúùôëùôêùóèùóéùóéúöîøñåØÁŸ°‡I«€?¬>¬?¬€>¬€>­ƒBÅ¡k‹vUR<M7N8N8N8N8N8N8M7R<{YQ}[%}X#|X"|X"}X#|Y"~[%qBûñă÷đäụ̀èụ̀èụ̀çụ̀çúöđ̣åĐüøóöñêiaSíÛ¼÷đăûø̣ụ̀éùóèøóéøóèûøóøđăÖ½—¯†H«€>¬€>¬€>¬?«€>­ƒCÉ¥oƒnMQ<M7N8N8N8N8N8N8M7S={XQ~[&|X"|X"{W!{W!}Y#~Z%oAụ̂ăñáÊúơîụ̀èùóêúốùóêüúơóîæ èÉ¡úöđûø̣û÷đû÷ñüú÷øñæøđăÖ½—¯†G«€?¬?¬€>¬?«€?­ƒDÈ¥pƒnMQ<M7M7M7M7M7M7M7N7S=‘{Y€Q[&|Z"|Y"}X#}Y#|X"~Z&oAụ̂ăñâÊóçÓüùơúöïùôíû÷ïëæỤ̈æÔøñæúơîụ̀çüø̣øñæøđâÖ¼—°†H«€?«€?¬@¬@­ƒC±‰LÊ©v‡sTWC"S?S?S?T?T?S?S?S>VB#“^ …Yƒb/\'~Z%}Y"}Y"|Y"~[%oAụ̂ăñáÊôçÔúöïø̣çûöï̃ÖËöíƯúơîüøóøđåøđåÓ¸¯†I­ƒC¯†G°ˆJ°ˆK½˜aƠ½™éԴμ¡º£€¹¢¹¢¹¢¹¢¹¢¹¡~¸¡~¹ y¾¡vÔ¿ØÆ©Â¬‰~O„c0ƒb0‚`-€^)€])qCúïßñáÊóæÑûöï÷óí{wmÿÿÿüûùøïäøñåÔ»•µR¿œfƠº‘̃ǤƯƣ϶·“ZǨx„]tY/pU+pU*pU*pV+pV+pU*pU*oT)rW, ‡`¥‰]‹j7­•pʲȱĮ‹­’jn=•zPöçĐñáỆåĐƯÜÚ+'"ư₫ÿøïăøñæêÛÅÛĂ Ë¯ƒ´X©‚EªƒE©€BªCɪzuOmO"jLjLjLjLjLjLjLiKmP"™~R¦†V~]*}[(_-€_.…d0‚V¬‹ÔÀ¡ùđäñâË÷èÓVWY÷óí÷ïáưûøÉ±‰¬†J¨€@¦}=¦|;¥{:¥{:¨?É©xuNlN!iKjLjLjLjLjLjLiKlN!ŒsL­‘f}[(yW"yW"zW"zX$}\(‰k<Ѫø̣çö́̃öèÑ_`aơïçúơîụ́çÁ¡o¨?¥{:¦{:¦z9¦{:¥{:§?É©xtMkN jLhJhJiKiKhJhJjLkM ‰pH±›y}[(yW"zV!yV!yW"}\(—zLđàÇóæÑôèÖøíÜoonóïé÷đäúó鼘a§~>¥{:¦{:¦{:¦{:¥z9§?Ê­‹rLkN jLhJhJiKiKhJiKjLkN „mF³Ÿ|['yV!yV!zW"zX#‚b2ÛǧƯÆ£ï̃ÂđßÄ÷́Û„}÷ñçö́Üüöî´X¦|<¦z9¦{:¦z9¦{:¥{:¨@͵„mHlN!iKjLjLjLjLjLiKiKlN b6»¢|~](yW"zW"yV!~]+¬“mƠ·ˆåƠºíÚºđßÄǿÙ974ơïåö́Üùđă²W¦}<¦|;¦z9¦z9¦|;¥{:¨@Í´…mHlN!iKjLjLjLjLjLjLjKjN {^0¿¤z}\)yW"yV!{Y$…e5̃Ç£ÂdèÖ¼îÛ¾ï̃ĂߨË÷ñèö́Ư÷ëÙ±U¦|<¦|;¦z9¦z9¦|;¥{:¨@Í´…nHlN!iKjLjLjLjLjLjLjKkMy[,Á¥x~]*yW"yW"€`.¼¥‚É¥mœcíƯĂîƯÀñáÇ›—’iN&øđåớƯóæÓ¯Q¦|;¦{:¦{:¦z9¦|;¥{:¨@Ó¶‰fâʦ¾–XÁ›añäĐđ̃Ăüñá¼·¯ụ̀çơëÜîăÓ®‰N¦{;¦{:¦{:¦z9¦|;¥{:©€AÔ¶‰e9lN!iKjLjLjLjLjLjLjLjMqU)ð‘_,zX#b1Đº˜¿—[¼“SÆ gôæÑîÜÀÉĹ̃ÖÉøđăơëÚêÜÄ®ˆN¦|;¥{:¦{:¦z9¦|;¥{:©€BÔ¶‰e:lN iKjLjLjLiKjLjLiKjMpS&Ķ €_,~\)}OÚ¿“½”U»‘R̀«yôçÓöçÏa`^êæáöí̃ơêÙçÖ¼­†K¦|:¦{:¦{:¦z9¦|;¥{:©€BÔ¶‰d7kM jLhJhJiKjLhJhJjLjLoT*Ƭ…€`/‚c3ßʪ½”UºO¼“SƠ¹ñáÉïæÖđ́åö́Üôè×âÔ½¬„I¦|:¦{:¦{:¦{:¦z9¥z9©€AÖ¸‹{^0jMjLhJhJiKjLhJhJjLjKnS(Ǫ~…g8³œxͪt¼’SºN½”VßÈ¥îÛ½¹µ¯̣ëáö́Ưôé×̃Ë®«„H¥{:¦z9¦{:¦{:¦z9¥{:©CÖ¸{^/jM iKjLjLjLiKjLjLjLjLnS(É«|qEßÇ£½•VºNºM¿–YäÓ¸÷è̉SNGơđçöí̃ôêÙÚÅ£ªƒE¥{:¦z9¦z9¦{:¥|;¥{:ªCÖ¹‹{_1lO"kMjMjLjLjLjLjLiLkMqU*ɲȵ™Åd»‘QºMºN¿˜]ê׺áÖÇ÷ïâ÷îßơêÙƠ¾œª‚C¥{:¥{:¦|:¦|<§~>©‚D®ˆO×¾—„h¬>«€?¬@¯†H˶—jP)aEaEaEaEaEaEaEaE`DfK" Œn̉¯y™XÀ–TÀ–TÁ—TÁ˜Xɤj³¬¡ùơï÷îàö́Ü÷ïă¶V¬A¬>¬?¬?¬€>¬‚A´ŒO¶¤ˆgM$aDaE`DaE`DaEaEaEaEjQ*̉¾ŸÂ\Á—UÁ—UÁ—UÁ—TĂœ]åͨ" ốßớƯöëỤ̂åѵT¬@¬>¬?¬?«€?®„EĐ²ƒ‡nHdHaE`DaEaEaEaEaEaEdI„jCàęÛ[Á—UÁ—UÀ–TÁ˜VÆ è¿«öíßớƯơêÙîàʳŒQ¬@¬?¬>¬@¬@¯‡IƠ¼˜kQ)bFaEaEaEaE`DaEaEaEiO(Á®’Åœ]Á˜WÀ–TÁ—UÀ–TĂZغkhd÷ïăơí̃ôé׿־²‹O¬@¬?¬>¬@¬@¯†Hdz“iO'aE`DaE`DaEaEaE`DcGpV-àÊ¦Ăœ\À—UÁ—UÁ—UÁ—UÅbâе÷ñçơí̃ôèƠâϲ±‰M«?¬?¬?«€?®ƒCÁg ŒlfK!aE`D`DaE`DaEaEaDgM#¦“vΪp™XÀ–TÁ—UÀ–TÁ˜Xͪs™•ùó́ơí̃ôçÓÜÊ®±ˆJ«€?¬?¬?«€?¯†GÚ¿—rX0cGaEaEaE`DaEaE`DbFjQ*ØÀœÂ›\Á—VÁ—TÁ—UÁ—UÄ`æĐ°ƠĐÈ •>=;÷ñæö́̃ơéØƠ½˜¯‡H«€?¬?¬?¬@¯†HÏ·“jP)aE`DaEaEaEaEaE`DeI vTÛ½ÂZÁ—UÁ—UÁ—TÁ—WÇ¢f¿´¤¾¹²ÙỴ̈áÈöåÊôèÔ»³¨kkk ÷đåö́Ưöí̃ͳ¯…E«€>¬?¬€?¬‚AµQ³¢‰gM$aD`DaEaEaEaEaEaEjP)ǵ˜Ă[Á—VÁ—TÁ—UÀ–UĂ›\áÆCA><7/ßɧº—aä̉¶éĐ©êÔ°êÓ¯ïÚ¹úíÚ¼¡vøđäö́ƯùñåÄ¢o®„D«€?«€?«€?®„Eϯ‰qKdIbFaE`D`D`D`DaEcHtY1ßÅÄ›]À—UÁ—UÁ—UÀ—UÅŸc̉Ä­Ø̀º·’Y°‡I¿iôäËể®ëÓ¯êÓ¯êÓ¯º´¬Â²˜øđäö́Ưúô뽘`®ƒC­‚A­‚A­ƒC±‰MÙÀnT-dIbGbFbFbFaEbEbFiN&²¡†É£h™XÀ–TÁ—UÀ–TÂYƠ´ƒtql‰‚ϱ…°‡I¬€@²NƯÈ©éĐªëÓ¯ë̉®êÔ°öåÉ@><Æ¿²øñæö́Ưùñä»™e±N±‰M²‰L¼•XÄ¥u×Ê·vL}^0pT+hN&gN'gM%hN%hN&hO'pX2ßʪÅa˜XÁ—UÀ—UÀ—UÅaßˬàβ³ŒQ¬‚A«€?­ƒC¹•]ôçÓể­ể®ëÓ¯êÓ¯ÖͽÎÔƯùñæơëÛụ̀èàË«ÜÅ ƯÁ–Ûǩӹͱ†ÏǼŸp«•s´ ‚»¬”¼¡x»¢{ºª“º¥„¾£zÍ»î̃ÅØ¼Ê¥kÄœ^Äœ^Ä_ʦl§¢›œ™‘¼™c®„D«€?¬?¬€?±‰L×ÀœêÓ¯ëÓ¯ë̉¯êÓ¯̣̃ÀYYXÜÑÁ÷ïâùôëöëÚ¸”^°ˆK¯‡I¯†G°‡Iº‘S²ŸkQ(fJ!gK"gL#fL#gM%hM%gL$iP*˜]Ú»ŒÔµ„ßÇ¢åÏ­åέăάơăÈ xup̃Å¢²O«?¬>¬?«€?­‚BµṬåĐéĐªë̉¯ë̉®ëÓ°ïẳåØÅû÷̣÷íàôèƠµV¬‚A«€?«€?­ƒBºS¬—xfK"aEaE`D`DaEaEaEeI‘xTظ…Å_Åœ^ÅaÆŸc˦lïÜÁ@?<…‚}¹±¤íƯÄÿøêϼŸ̃Å¡±‰K¬@¬>¬?¬>¬?°‡Iβ‡íÙºêÓ¯ëÓ¯êÓ¯í×µ‹‡ƒîâÍ÷đäöí̃ôèƠµV­‚A«€?«€?­ƒB»“U§’qeJ aE`DaEaEaE`DaEdH‰rNڻÛ\™YĂZÄœ^É¥lơà¾#kif©£×˹ơạ̊̀Ư»éΤåÈ›ï̃ĂªgrBÀªˆ¹“W­„C«€?«€?¬?¬>¬A³ŒQîáÍéϨë̉¯ë̉®ëÔ°ùëÖä×Èøñåöí̃ơèƠ´U¬@¬>«€?­ƒB¿a›ˆkdI`DaEaEaE`D`DaEdI€kJßǡȡfÇ¡eʤkƠ·‰ăέóæ̉éÚĂ÷åÊë̉«æÉæÉåÉåÉèÍ£àϳ•vF‡d0ƒ_*‹j8à˪°ˆJ«@¬>¬?«€?«€>¯…FÅ¥tñßÄể®ëÓ¯ë̉¯ëƠ±®©ŸƯÙÓụ̀èöí̃ôèƠµV­‚A«€?«€?­ƒCĂ l˜…idI`DaE`DaEaEbFdIkR+tRïáÊçÓµëØºïƯÁëÔ°åÈ›åÈæÉåÉœåÈ›åÈäÇ䯗î״Dz‘Œl;ƒ`+€\$€\$†c/»¡x¾d®„D«€?«€?¬?«€>¬@³ŒQç×¾èĐ©ëÓ¯ë̉®ëÔ°úë̉0.+Üßâụ̀éöí̃ôèƠµV­‚A«€?«€?­„CǨz”‚hdIaEaEaEcFfL"iO(‡mFų–̃ȧïÜÀäÇåÈåÈ›åÈäÇäÇ™äÇ™äÇ™åÈ™åÈ›ăĂ“îƯ¬‘i‰h5‚^(€\$€\#[#]&†e2ÜÅ¢°ˆJ¬@¬>¬?¬?«€?¯…E¿œgñáÈể®ëÓ¯ë̉¯êÓ¯ÚĐÁϼùñçöí̃ơèƠµU­‚A«€?«€>®„Dϰ‚‹pGdI bEcHhN%mS*¢sϹ˜̉´ˆ³‹Mº•^đ߯æÉœäÇåÈ™åÈåÈåÈ™åÈåÇåÇç̀¢ăÓ¼—yK†d0\&€[$€\$€\$€\$€\$…b-³™qǧv¯…E«€?¬?¬?¬>¬?²NâÑ·éÑ«ëÓ¯ë̉®êÓ¯óáÄ^[VǬ‚øñæöí̃ơèÔ´U¬@¬>«€?®„Eѳ†‰lAiN%iO'z_8·¦ÚÂÂh°ˆK°‡H®…EµT́Ù»åÈäÇ™åÈåÈåÈåÈäÈ™äÅ–î״ȳ“‹j9ƒ`+€\$[#€\$€\$€\$\#[#]&ˆf3ÖÀœ°‡I¬‚A«€>¬?¬?«€>®ƒDº”ZñâËể­ể¯ë̉®êÔ°́áĐÈ®€øđåö́ƯñçÖ´S¬@¬?«€?¯†GƠ¹ˆlD–[ʷؽ–·U±‰K¯…F®ƒC­‚B­‚B³QéÔ¶åÈ™äÇåÈäÇåÈ™åÈăÅ—ñàÅ­’j‰h5‚^(€[$€\$€\$€\$€\$\#€\$€\$€[$„a,¥‰]б¯†G«€?¬?¬?¬?¬€?±‰KÙĂ¢ëƠ³ëÓ¯ë̉®êÓ¯îØ¸ƒø̣çö́Ưđæ×´R¬@«@¯…E²ŒPâеá̀«Î°‚°‡I°ˆI®„D­‚B­‚A®ƒ@®‚A­ƒB³‹PäѵäǘäÇåÈåÇäÇ›æË¡ẳ·•uE‡d0€\&€[#€\$\#\#€\$€\$\%€\$€\$[#€]%ˆf4ÚÆ¦°ˆI¬‚A¬€>¬?¬?«€?­‚B·Vî̃Æể¬êÓ¯ëÓ®êÔ°öéÔùóëö́Ưđæ×´R­ƒC°ˆJ¾›fäĐ²ØÀœË®²M®„C­ƒA®‚A®ƒB®ƒA®ƒA®ƒA­ƒA²‹OàÊ©äÆ—äÇåÈäÆ˜ïٸ˶–l:„a,€\%[#€[$€\$€\$\#€\$\%\%€\$€\$€\$€[#ƒ`*{KÓ¹°†H¬€?«€?«€?¬@®„E¶VÖ¿œđßÅëƠ³ëÔ²ëƠ²ëƠ³ÉĂ»ùôíö́Üđæ×·’Z³ŒOÙÀ›×¿™´ŒO¶VƯƤ±‰L­‚A®ƒB®ƒA®ƒA®ƒA®ƒA®ƒA­‚A±LƯ˰äÅ•æÉœăÄ”îƯĂ¯•mi7‚^(€\$\#€\$€\$€\$€\$€\$€\$\%\%\%\#€\$€\#€\%‡e2̉¼³‹P­ƒC­ƒC°ˆJ´S¡ñ̀¯óè×ø̣èøñå÷ïâö́ƯôèÖ÷́Û¡–ˆ÷đäö́ƯđçÚ˯ƒăͬ¼™c°ˆK­ƒC±‰L̃Ȥ²M­ƒB®ƒA®ƒA®ƒA®ƒB®ƒ@®ƒA­‚A±ˆIƠ½˜æÊçË¡æÖ¾|M‡e1\&€[$€\$€\$€\$\#€\$\%\%\%\%\%€\$€\$€\$€\$[$‚_)˜yIƯĶ‘X»—aÙÄ£íßÊøđậåÑôèÖơêÙôêÙôèƠôêÙ÷ïăùơîÜÔÈ÷îâö́ƯùóéÔº“±N®„D¬@¬@°‡JƯƤ³‹N®ƒC®ƒA®ƒA®ƒA®ƒA®ƒA®ƒ@­‚A±ˆJÏ´ŒñßÂ͹›Œl<„a+€\$\#€[$€\$€\$\#€\$\%\%\%\%\%€\$€\$\#\#€\$[#]'m<̀¹ễ̀úóèóæ̣̉åĐôçÔôéØôèÖơëÚøñæ÷ñçơîå÷îáøñæưø̣¿i®…E«€?¬>«€?®…EĐ´Áj®…F®‚A®ƒA®ƒ@®ƒA®ƒ@­‚A¯…F³‹ÕÇ¥ÚǬqCƒ_*€[$€\#€\$€\$€\$€\$€\$€\$\%\%\%\%€\$€\$\#€\$[#\#€\%†d0¤ˆ^îÜÀæÉëÔ²đßẠ̊äÏô騸ñåîèßâÛĐ¥”uWSN÷ïäúôíóåĐ×Á °‡I«€?¬?«€?­ƒC¼˜aÔº‘±‡I­ƒA®ƒ@®ƒA®ƒ@®‚A°†G´Pà˪¥ˆZÀ¨‚¤‡[…a-€\$€\$€\$€\$€\$\%\%\%\%\%\%€\$€\$\#€\$€\$€\#€[$†c/UêƠ´áÀâ‘ă‘ăÄ“äÇ™ëÓ­ÜƠËûùơôé×óæ̉ëÛĂ³ŒR¬@¬?¬?¬@±‰K̃È¥²M­ƒB®ƒ@®ƒA®ƒB¯‡HµQăϯ’q=ˆf0ˆg1×À‰e1‚^([#€[$€\$€\$\%\%\%\%\%€\$€\$\#€\$\#€\#€\%†c.›|Mï߯áÀŒâÂâÂăÁăĂ“éϧ×ÑÈøđåóçÔôé×øđâ¼™b­ƒB«€?¬?¬@°ˆK̃Ç£²‹O®ƒB®‚A®ƒB±ˆJ¾cÙÆ©m9†b+‚^%„a)’q>̉½œ‡e1\&\#€\$€\$€\$€\$\%\%€\$€\$\#€\$€\$\$€\$…b.›|Mî̃Åá¿‹ă‘ăÂăÁăĂ“èΦáÚÏÿøÏ÷̣èơé×ơéØôé×̉¸‘¯†H«€?«€?«€?°†HÚÄ¢·S®„E®„C²‰LÄ¢ỏ»–i4„a)‚^$‚^#]$†d-¬b¸u†c0€\%\#€\$\#€\$€\$€\$€\$\#€\$\#\$€[$…b-›{KïßÇáÀă‘ăÂâÁăĂ“çͤæ̃ĐđáÊ÷îâơêØ̣åĐæÖ¾³ŒQ«?¬>«€?®„DƦv̀®€±ˆJ±‰LΰĪ‚‰h3ƒ`)‚^$‚^$‚^#‚^#‚^%ˆg2ʲŒ–wF„`+€\$€\$€\$\#\%€\$\#€\$€\$\$€[$„b,–wHêÛÄá¿‹ă‘ăÂâÁăĂ“çͤëáÓ÷ïăơêØôèÖøíƯ¹“\­‚A«€?«€>¬‚A´‹ÑȨµXؽ“±—mˆg3‚_']#‚^$‚^$‚^$‚^$]#ƒ`(ˆg1ÜǤ‡d1]'[$€[$€\$€\$€\$€\$\#€\$€[$ƒa,‘qAêÛĂá¿‹ăÂâÂăÁăĂ’æÉæƯÏøñæôéÖơé×ơêÙÏ´Œ¯†F«€?«€>­‚A³ŒPá̀«̃Ç¥ª`‰f2‚_&]$‚^$‚^$‚^$‚^$‚^$‚^$‚^$…c+{Jǯ‹‡e2€\%\#€\$€\$€\$€\$€\$[#ƒ`+’rCăѵáÀŒăÂăÂăÁâĂ’æÉéÜÉùôíôèƠơêØ̣äÏåƠ¼²‹P«€?«@¯†H¹”]ö́Ư§‰Yh3‚^%‚]$‚^$‚^$‚^$‚^$‚^$‚^#‚^$‚^#‚^%ˆe0¼¡w¥ˆ\…b-€\#€\$€\$\#€\$€\$ƒ`*n=åÔºăĂ“ăÂâÂăÁăĂ’æÉäØÇùọ̈ôéØơêÙôéÖô騶‘X®„D°ˆKÆ¥tÛÆ§©ˆSʰ‰ˆg2‚^$]$‚^$‚^$‚^$‚^%‚^%‚^$‚^$‚^$]#‚_&ˆf1Ơ¾Œk9‚^)€[$€\$€\$[#ƒ`*o>åƠ»âÂă‘ăÂăÁâÂ’æÈœễÏñæÖ÷îáơêÙôé×ö́Ǜ¯„´RÙ¾•Ĩ~™uƠ¼˜l4„`)]#‚^$‚^#‚^$‚^$‚^%‚^%‚^$‚^$‚^$]$„`)l8Ô½™†e2]&[#€[#ƒ_*Œk:åÔºăÄ”ă‘âÂăÁăĂ’åÈœăØÇ¹…7øđäơêØơêØóåĐçØÀâÍ­¬ŒZ˜t:“l0”n2 }F̉¿¡‰g2‚^%‚^#‚^$‚^#‚^%‚^%‚^%‚^%‚^#‚^$‚^$‚^$†d-§[¼¡x†d0\%ƒ^)l:̃Ï·âĂ’ă‘ăÂăÁâÂ’äÇéßĐ÷îáôéØơêØóæ̉úóé«‹Y™s9“l.’k-’k.˜s:ƠÀ¢”s>„a(]$‚^$‚^#‚^$‚^%‚^%‚^$‚^$‚^#‚^$‚^#‚^%ˆg2È­ƒ˜yK†d0Œl<ÖĦäÄ•ă‘ăÁâÁăÂ’äÇèàÓøñçôèƠôé×÷îááÅ›ÓÁ£™u<’k.’k.‘j-”n1¢~G̀·•ˆf2‚^%‚^#‚^$‚^$‚^%‚^%‚^%‚^%‚^$‚^$]$]$ƒ_(ˆf1׿™’tFƠÁ¥æÈäÄ•ăĂ’ăĂ’ăÄ”åÈ›éáÓÿÿÿúơîôèƠóåÑđáÊØµ€éÑ®¥„O•o3’k-’k.’k.—s:Óº“’r?„`)]#‚^#‚^#‚^$‚^%‚^%‚^$‚^$‚^#‚^$]$^$‡d.¡…Xñå̉ôæ̉îÛ¾îÚ½íÚ¼íØ¸́عđæ×óè×ö́ßøđäÚ¸„Ô¯tÔ®sßͰv?“l.‘j.‘j-”m1w<ϸ”‡f0^$‚^$‚^$‚^$‚^%‚^%‚^$‚^#‚^$‚^#]#‚^&‹j7Dzç̀£âĂ“äÆ™äÆ˜åÇ›çÍ¥ïä̉$÷ïăéƠ¶Ơ±xÓ¬oÔ®täÈ´—j–q6’j-’k.’k.˜r8ȯ‡“r=ƒa(]$‚^$‚^#‚^%‚^%‚^$‚^$‚^$‚^#‚^%h3¶uèͣ཈߼‡ß¼‡ß½‡áÀ́ßÉ83,÷ïăÙ·‚Ó­q̉«nÓ¬oÓ­qå̉µv>“l/‘j-‘j-“m0u;Ȳˆf0^%‚^#‚^$‚^$‚^$‚^$‚^$‚^#‚]$ˆf1¨Œ`́Ơ²ß¼†ß»…̃¼„ß»…à¿‹́ع~wlùôëÚ¹†Ó­qÓ«n̉«nÔ­rƯ¾Å®˜s8’k.’k.’j.—q7ɲŒ–u@„a)]#‚^$‚^$‚^$‚^$‚^#^$‡d. ƒVîڻ߻„ß»…ß¼…ß»„à¾ïÚº‡€äÍ©éÖ¶è̉²Ơ¯v̉¬oÓ¬ỏ¬oÔ®sæĐ­ ~G”m1‘j-‘j-”m0t9Ó»•ˆg2‚^%‚^#‚^$‚^$‚^$‚^$†b+–vCèƠ¸̃»ƒß»…ß»…̃»„à¾éϨ±¨œ̣åĐÖ²{Ó¬pÓ¬n̉«nÔ­qØ´Đ¼œ™t<’k.‘j.’k.—q8ʰ‰xB…a*]$]$‚^$]#„a)o<è׽߼†ß»…̃¼…ß»„ཉèͤËÅ»üđ̃ûøôƯ¾Ô®r̉«nÓ¬ỏ¬oÔ®té̉®©‰V•n3’k-‘j-“l0v>×Ä¥‰g3‚^%‚^#]$ƒ_(Œk8ÜȪà¾ß¼†̃¼„̃»„à½ˆåÆ™×̀¼”†q£=îƯÄƠ±w̉¬nÓ¬ỏ«nÓ¬pÔ­qÛǧv?’l/‘j.‘j.—r8ι—N…b*]#‚_'‹k7͹™ăĂ’à¼‡ß¼„̃¼„ß¼‡âÁ‘éáÔôéÚ×´}Ó¬pÓ¬nÓ¬ỏ«oÔ®tå̀¤´—i—q6’k-‘j-”m0›u<ÖÀŸˆf2ƒ`(‹i5Á©„é͢߼‡ß¼…̃¼„ß¼†áÁéƯÊÿÿÿùôíäˤԮt̉«ỏ«n̉«nÓ¬pÓ­ræÓ¶›w?“l0’k-“l.—r8Ç«Ÿ‚TŒl8¯•léΥ߼ˆß»…̃»„ß¼†à¿ŒñäÏïßÈÖ±yÓ«nÓ¬nÓ«n̉«nÓ­sܼ¨˜t:“l0”m0–p5yCØÁ­•oïÚ»áÀῌΉ࿌âÀïƯ¶¨“øïăÚºˆÔ®sÓ¬qÓ­rÔ­sÔ¯tÖ±yíÛÀ¥ƒO ~K£‚M°Y«ˆäƠ¿ôíăóäÎúîÛÿóá÷êÖêàÑïáÍçäÛ îàÇë׺ۺ‡̃ÀâÆ›èѬèĐ«éÖ¹éÔ´ñèƯơæÎúđâùđă÷́Ưôè×óçÔèáÖ,& ÷ïâØĂ£Ê¬~Ä£p»—a·S²‰M¶‘Yà̀¯íÚ¼ï̃ÄđßÅđßÅïàÅđ߯÷éÓid]ûơë⇱M­„D­ƒB¬A¬@®„D¹”]óæ̉ï̃ÂïßÅđßÅđàÆïàÅïßÅêâÖæÖ½³ŒQ¬@¬€?¬>¬?¬?±‰KÙÄ£ïƯĂđ̃ÄïàÆïàÅïàÅïàẠ̊áɪ¥ụ́ä¿j®„C«€>¬?¬>«€?­ƒC·“YđăÎïƯÁđàÇñàÇđàÇđ߯đ߯ôéØ4-!ªKƯɪ²M«€?«€?«?­‚B¯‡I¸“\ØÂ¡ö́̃ơëÜöîá÷íà÷îâûøñø̣èíæƯöêØ·’Y®„E¯…F³‹P¹”]Ó¸‘éÚĂ÷í̃ôèÖóæÓơëÛ÷đå÷đåäѶ´oéƯÆôçÓÖ¿›¹•^̀®åÔºơèÖôèÔóåÑöíßöîá÷ñèëáĐñæÖôêÛ₫₫ươéØûúö÷ïåüú÷íÙ»÷îßÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿđÿÿÿÿÿÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿÿÿÿÿ₫ÿÿÿÿÿÿÿÿÿÿđÿÿÿÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿÿÿ?ÿÿÿÿÿÿÿÿ₫ÿÿÿÿÿÿÿÿüÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿđÿÿÿÿÿÿÿÿđÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿø?ÿÿÿÿÿÿÿÿüÿÿÿÿÿÿÿÿ₫ÿÿÿÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿÿÿÿđÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿüÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿø?ÿÿÿÿÿÿÿÿÿÿø?ÿÿÿÿÿÿÿÿÿÿø?ÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿđÿÿÿÿÿÿÿÿÿÿÿđÿÿÿÿÿÿÿÿÿÿÿđÿÿÿÿÿÿÿÿÿÿÿđÿÿÿÿÿÿÿÿÿÿÿđÿÿÿÿÿÿÿÿÿÿÿđÿÿÿÿÿÿÿÿÿÿÿđÿÿÿÿÿÿÿÿÿÿÿđÿÿÿÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿÿÿÿà?ÿ?ÿÿÿÿÿÿÿÿÿà?₫ÿÿÿÿÿÿÿÿÿàüÿÿÿÿÿÿÿÿÿàøÿÿÿÿÿÿÿÿÿàøÿÿÿÿÿÿÿÿÿàÿđÿÿÿÿÿÿÿÿàÿàÿÿÿÿÿÿÿÿàÿÀ?ÿÿÿÿÿÿÿÿàü?ÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿÿđÿÿÿÿÿÿÿÿÿđÿÿÿÿÿÿÿÿÿđ?ÿÿÿÿÿÿÿÿÿđÿÿÿÿÿÿÿÿÿđÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿü?ÿÿÿÿÿÿÿÿÿÿüÿÿÿÿÿÿÿÿÿÿüÿÿÿÿÿÿÿÿÿÿÿüÿÿÿÿÿÿÿÿÿÿÿüÿÿÿÿÿÿÿÿÿÿÿ₫ÿÿÿÿÿÿÿÿÿÿÿ₫ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿÿÿÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿÿÿÿÿÿđÿÿÿÿÿÿÿÿÿÿÿÿÿđÿÿÿÿÿÿÿÿÿÿÿÿÿđ?ÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿø?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‰PNG  IHDR\r¨f IDATxœ́w€\e¹ÿ?ï{Ê´mÙlzƒ$@€Đ;̉D½‚ˆˆ¢X®½!×z‹z-ËÅkÆí*U"RDjh Ỉ{¶ï´Ó̃÷÷Ç{Î̀ÙÍ&àư’àùê0»3³sΜ̀Ó¿Ïó@† 2dÈ!C† 2dÈ!C† 2dÈ!C† 2dÈ!C† 2dØu¸ü®å»ú2dȰ³qÍü¬é«M«zá3/tWÍ_7ø̀3‡®ÔZ¿å̃e½oưƯÂÍoÿâíËfü»ß<¾€‹?|ÙË~Îö ˆ]}^úkÁ‚ŸX}đ¤VW:wÎ[ˆ!/¤¿Rt,KĐ–·Ă-C®ÊÉYâ®Iíù{X;(7ù[Î9pÜU»ú3dØư)€Ư‹TDuơĐ¡mEwÁ¯îY€„¡bÆÄ±7gÇïƠκ ƒöC%̣$oKmK)Ú y[R°-jaDÍ /_ƠSùÓYïÿüƒ•¿ü,œ5{¶xaùr½«?c†]‡Ĺ˜¿n൛û̃rëËd¹¢´Æu, ¶Àvó4½‹ö›̀”Îe/dk% Fä-‰æŸXAWÉÑm9[ÔĂH÷V¼Êạ̊åGÎŒ2eđ†ĹÆøá ùĐ™‡°y(Đ_ûĂ<6÷•¬y(¥‘BàØ’œcSp,K2aL {OÏiûOd|kφAKB̃–@i­¥¢=oë×íykå¾ÚoX̃sëÅÇÎx́´sΕ÷̃ú{%„Dkµ«/A†ŒĹæ¸cÉ–/—ṛ_ùç'é©x¢â…DJ)À’Û’¸¶$ïXä‹‚ë2®½ÄÓÇrÜ~SW´ØZ ({!BÂHić-!tgÉc‹›=¼Hẓ̃M7¼óøY«Ñ1¶K÷÷tïÊKa'"S»9VôT»ÿ÷¯KÆ.]×M_Å£î› )RlKâX‚œmS̀Ùt”̣tµ¸2{:gÍÄ`=D(:yGR "”‚HkíEZø̉Û\„bË·zù–Ê 'ïÛơ/í]r ·;9h&¼‚`ïêÈ0:®üóÓŒßuf¤»jS®ù¡#…̉º)B ´F)B)M üĐül[’–¼Íñ³»x|í B€%@#PZc ”K ®$gK±¥ µÖGÎ8fï1—®é­¾uzgqà*¾eJà‚ņøôw~Å_3—§7]ơđó#„F„*~!±ê$ɧ5Zk”(̀ë,)™=©‹z¨ "k !@ i$Y)"À¯Çñ¾¹¾̉ú€‰%ùÀ‚g.:âg "ŒÈÁ¹«O öøÆ'̃É?_·dÖ¤öÂäû¯ —₫tlưæ?:Á$}¯!À¶yצ¥XàŸÉ¢e,)Đ4­1ï¥5Jƒ̉ Fyóº’+EyppÙE§y0hZ€<ÆȾ;¯dÀnÿ8sÖ¿Ü:…ˆ4xAÔHÚ%R—6½IP K \Ç¢%gqÔ¾Óè«m !-#ÅVƒÉ;h„JsĐ”6̃ûáKo†€~`0¾%§ I|† {$2-¾â’kOêlɽăé5ƯÔư?R ‹ 4îÆâK“ ´-A)çĐÑZâmGOcé–*–4Ï a¬ÿ0â¿nÜëñ­.yèñ5×₫ä;>0˜Lº€VŒ`“%‘÷xdÀnˆw=ùÄ'Wn-”«Ú•б›/Œ7.J’uüœ%%yÛđÎ?v]=@ѵ°$$²*v$²"¥Å”’Œ}óÀ₫PÂ|WB T:Æ€DçŸáeDǽ†8pRë—X¹UBJpm‰ëØäl‰k[8–!₫Ø–Ä’¢ÁÈ;-‡I­́5¾ƒ₫zˆ%‰O)Œ$Øpüulư5ăZsÜđ‡?lêï̃\:1V &P\Ö?óöpdÀn†«Y={¨ÎÙÔ3hÊx9×¶L©Oé8soˆyi†=™Ø pÜ7ïâ¼#÷9â’£'?qå+©Z©f́̃Œá›L@+n’ÎÜ<›ûùƯ=ó¬úø¡©ÎI)°„À²$mQpmZó–|é=oàîùÏ3wÖt[Ư-%mr®%ÉÙ’¢cáÚB „hÉI\Kèœc‰VG<4ỉ±§R[”Đ‚dÊ`B¦v<µvàƒ~ø¡¿>ß­Ë^(üHÅqû¶BĬ?p, )á=ÇLă_~~år™¡OFAJRâX’‚ëĐ^°yƠ1G1ÆƠ<:!u2¡]`á†Á¤G=L”“°CÆä£Ă§¶Ñ‘³n3±åŸ0U‚t£P¦öd<€Ư—ưqiḈñ¥ ¬ÔA¤D”*ïW¿9Ơ'iè1Öú̀&ríKđj5*ơÏñĂˆ 27?Tø¾ùYiÍ@hsæáûrÓ½°¹¿Âw®û9ÁôƠ0 •ñBBE5¾¯zQ ~¨xbí C¾zăƒ+zoÅä’‹̀°́1ÈÀ.†Ös÷q >¶́"ˆL½?ư<Œ.üRÚ .M(̣ĐÓ/Pơü0$̉ªÑ5¨ă÷,!±$œtä\Y°˜Á¡2ƯeúËU₫ơ§72wR %Mè¡A©¤ÅØÜüH㇠/Ô¡b̃ê~ft_wçÂƠ×c„?! Y˜ïV¦vsd `CÁ>Û¾ºhĂ •"±₫ a'ü¤ qÿ¥(¥y듹ô·¢£€zDÊxF‚ǰ„aº¹¿?×Ưư(µ b¨Z§¿\¥Z­̣Ù+¯ă sÇc[i¹5-̀M¡ •Q¡‚›oå¨Ù“ÎûÁ/¯½hĂ(™Ø#)€]ˆŸ̃ơA¨_¿|kY†±ÅmŒ̃Iñưa&ùgI˜ĐQds_™̃ë¨zAïaDÇ%c‘³%G2—K–R¯–©û^Ró|Ë5‡*|ăê?ñîă¦/C ¤H1“ó‡˜<…̉¿[´Eœwî›₫çÍ—|đPÛq:É”ÀkWŸÀ?2₫ø¿?âæÅ›¿w¬W-Ù8@=Ô"ˆ;ÿ€aÖLåß² ‰§j¾|ö¾|âwS©Ö¨ÔMâ/)é%Ü_)Mö¿˜s Wä{ï>ÿDa@Ưă¼@r«×ë<µnˆKÏ:˜'×Đl%HJ‘"¦ÇçhUo]|üâó.|®Û»{Å¢G+J©&I(K î¦È<€]Œăöê8ă±U½"RˆPm›@æHăú ¯Ưß¹g)Ae€4| á×Úp¤™́JÁÏ:†ßÜ÷4yUĂóC¸̉`âüˆª0P©±bùs\yû£œ9§ /f&Ôax„*¡RÔC-ªAÄÏvsÍw¿zó«ßú¾ư„í@C6Ë<Ư™Ø…øÁƒk^×UrØ8èi_©Ø ›çFf₫…X×_iÁAS;xèÑ'©x!~Ɖ;=\ø[ÑáN±…sÚ›_Ü₫ơ@…¡L²PÇù„ ©Ô}*>:ŸÍ›·pÚ́NüP5÷ 踗 ¥"¥đB%*~¨ï[̃˯®øê´Öc09Íf¢L ́fÈÀ.Ä9Œ»đög·‚Ö"ô¨®’ø“qL®5\|ôT®`15?¤î…„¡jL Nû†ü#‘À?¿ö(¾}Û ÂÄưÉ€Ñd°¨†X DTj/ä®»“₫ªÇI3;"…Œ¿-‚m•€©(±²·ÆSƯjÚK×ü“hï2°Û!S»íyûÂç6•µÉ¨7§ơŒTIÖ_ (¸6RJX¸Œªà…ac\˜À %iđ‰3ÿm­µÿ̃ÜùÀ<ê~ˆ6­2LÀE /ˆ(×=ªÏO®½‰fïÎ<@<\$>Ϙ,¤I+Íó[+ønÛ¡Y²ö÷˜ïXZ dß¹ƯÙ?Æ.€̉ùkûß±©́K/‰¿d²ˆ >iëoÅÖÿM‡LâÊ?>DƯó©û!a:­ÑqỪÔ_Ç–ØBđ–Sà«¿{ßóđü(ÎĂ:Œ%ª/ªy Uë|ă×7ñÚ9]ä-+=fº9JL M¤ ˆ~¤ylÍ ˜3uÜœ[^ü}̀lŒÈr»2° … -ï|áé :ch»Ơ ë/IêøpĐ”vP!«Ö®§êyøA³́§I[Ó#à:N¾À3§óä‚…Ôƒ? Q©ñâéa:₫]a¤¨ûƒƠơj•ÿäV.9v )’†¤øÜ’Ä`¢ÂÈx3×?µEÈ₫gÿôº?~S,ÑT™Ø •w¾ư—3›̉ñå¿.Û*j¾Â‹tĂ"'ÖŒelKR ï:~o¾~Ă}ô VMÙ/̉(­†ẉI‰%̀dà¢ksÑ™ÇsëăËØ²~%U?$£FÁÈî¿Æo©sPÊx,Ú¯ñẠ̀n₫ă¼£¸oY®eT@³YQ˜aü°,ổ-Î8zî1º8fÙ£÷ưyq¤A6Pd·@ǽœ2{́ék¡Öáö&₫Æc¼́X O˜ƠÉ =ĂÖ­=†ô)T²¼3 ầ¿%Í́ÀªÈqÊǛ_´/"~µC©K+HiBQơ}ú«[6¬æs?¿ƒ ŸD-P Â~2¹4® D?Ô 5w-íÑỵ̈É}÷‚|îÛq’Ù‚™'°Ë‘)€—'°ß¸â§—l"RZ˜Ù~æ™4ơWø&MâïÔ9¹ÿÉÅT=“ÅOÊ~#¥'Ù́Hø̀¹¯ậ›¯Œç ÿH×$Ó>ặ`FTêå:ËW®æ‘EK9ï „‘)¹˜@&® ÷(-ê¡æ₫z¸ê¯ừj?YH™VYóĐ.D¦^fÜ´àºÉ}µpö†´n %ĂË~¤g̀Çu,¦âTư(j–ưù?¦e ÛFäḰ7u< {8^ ¦Ö?=ÎwGüIy0R¦ù§\÷¨ÔøƯ=°dm§ïÛI¤´) Z¢Sï¢ Tøa$z+!·=½Y/₫¹[´Ri”@fe S»™xYá2wjû‡6zʱ¶5ÁỤ̂ưÍ0¼Å/¤Çđảäÿ]’Đ3=ÿRG\öOÇóµ«ÿŒ’–! %c1ŸPcI¤AR®y”k¿úĂí”+fu剔9_ ±³0 4*3ÀtKÙOn¨•_ß}»Rª$„h#[5¶K‘]ô—>®m]¼Ï¸’t¤ƠÎ9|d7ñ¨/đÅeǵËÏî|Âđô=£´yñpÖŸ[ \Û¢­½ÖÖV–­\S~£ÆVá´ơOß|,A²|4© ø¡é ¬Ö}¾{ưœ2³®’k†˜JóNÍ÷2ả¦2à…uưX9$&?±bËíZë†oÊ’̉/32đ2ĂbÚràä6̣¶™̉c¦́4)¿RËà”v6 Öxæ…•¦×?©ß'ÂOÓú[qÓ%%o;ư(®ºư!tlµ#Ơ´₫iŒ3–Xû4̉D!£b@µN¥\æß¹76‘Öœ Äá€64Èø+fÊ@)–uWE[kiÊM÷<ôyŒHʃÙ—™xñ­{^Ø«³d³aÀă„™chË;äl«áÈ”%/{ç6•OÿäDZRé» +R&óŸsl×eÎô‰,|v9^5æ4¼†Qü*!ˆt¨Ô) ̣Áï₫:x<‘̉ñœÂ8|‘Ä73‚!Hº•ï]ÖÇGùÖ«n¾çƒPbøÎÁL ¼ ÈÀËˆĂ¦u¼³hw$kû뜺ß8 g›RŸfѧR7:™ç-ÅÂôë›V_Ö¿ËaËÙP¼ç¼×̣£[î'gÏH¬ºîŸ¶₫°m0ªH˜ZkÂ(¢î Të ôlæ?{9qA¤ÉY‚¼#ÈÛ2¾ r g Ël)¸çùnN?é„çê[ß© Œ\=–a'#S/#œÚZ¬‡‘p¤d ²oW‘öb¼căZÆJÚRR̀Ù:},·J= $ä¸́—X0ÂdIr®n›È±Ó[Y°èi³R<Ơñ'¶cưG"-u#›“a‚DÚ´×¼€¡Ç¦ ëøÙ=‹øÀñS@̣–Ẽ±StÍ­à2¦èĐ·iËÛt•ºJ®~vÓ¾øM¯ừ×~vưE4ì<ø2!»À/#VơTu5P yô"Ǻ®?¼eÜ¢« µâœ¹“¸í‘Å<½|½•:µz`2ÿéÄÆ;–E!gSr-.{ç¹Üx÷Ă<½tƒ•:^h†$öéê§ïG"]Øæ51éHhc[”r.cÛKŒoËó̃·ÏI{µ²iĐöCơpÄûó¯Å-ÆB •B̀è*ñµï]ơ©¯]ú̃›0‰’ÍC#Çgø;"Û ô2bjG>|fsÅv, ˜x9ˆ4Mé`Ɇjb\1Ǹ’Í¢åk¨×|ßXqF~tóŸsl]“Ù«3Ï’gŸÅ µi÷M(¿©¿M ü­Ḥ B C…~ÄQˆĐăç÷­ăäƒöâE=I¹˜û˜³„<a Áó[«|á£ïùv¨tø­Ë̃w«jf¦v"²²ËË„ß/Üô¦ic̣ÖĂÆ—ưƠ€C§´²dÓơ âƯÇÍàGwÎgswƒ5Ÿ ˆFŒùJbqÛ²ÈçlÛáSçŸÊnºî¾ªơæ„ $ƒŸ Ñ-Èv¬ûˆ×nïyØÂ4s¥ 3¸äƠ‡óơŸÿ7Ñ>f GÏÇs[ª&¯¡ăm~6Us¯0ó×ôƠxïÙǾpmß#Ë>ÖM³_ Û?¸“å^rüi9½Í'ëhwÏ%̣¾zÈÓ;˜9®……«·°lÅ*j)ßE±ơ׉럵ض$ïX̀̃kK6ËW®nŒúJ×ưG"ñ^̀ưßö‰æ{Qcy×ÁSđƠ‹_Ă—~y;ƠG÷@…kn½‡Å«6sȤ*=¦”!–|®P©˜[ ñBM-ä¶g{k|Å5g¾íŸÅLÊÓ5…¬gd àeÀ‡ïÅ ÔÅơPÇ9ù¿™Ù×[ 8`b+‡LĂ ,FiÓˆ“¦û&I¼Dí¸áGJÉÇÏ9’ÿ¾éA¢È´û¦ë₫Ûæ¿5ö×ĐPBRli™1ă¶Å'.ú'X¸”̃Íë¨Ôè,Ó;Tå[₫Ħ>T ¥$Œ€@#P:î7PfáÈ@=·?×c]Ơ÷®;í¼ẁ¥9V,c îdôeBk̃Qơ#Àd̉I8)½Ơ€6+¢­˜Ç[€m)±ă!ZˆF¿~:öŸ9} ®”,y₫¼Æ^ƯŒÓăă$ư—R`Í;HªnĂØơŸ:s_:Z‹üö÷âƠzϬÓ_ñ¹úæ;›Ó̀™P"P¡”aóÙLÛq¨5Aưµ?=×çÜü›ŸưàÙädƠ¿32đ2à?Ÿ—[tÆ‘̉‚8‘$ÿ •fZG¿.ëæso9™ “§’w,Jy×–ñĐTŸ€e¬?QÈG^ÿ*¾ù‡q„YƯ•æüÛ&”:Ÿíy;ʲ5\KbÛ’BΡ ¾ư¾³¹âêÛâ1ă&©{!ƒƠ:ƒU/₫́́?ÖfZ{H%Ä"“Ô±'¤h¡V¢¿rÇ̉>熟}ïw~ôsGb& ¥û2%đw@¦^œỗûÔĂÉI¶°ÆZk6…,_·™/̃đo?ù`̃rÖ)äIK!GÁup, ;¦ü&Öÿ€ưfÑ–·yjÑj^H˜ơ7’ơ—¶₫£IΨÍ@éÇ´nKĨuüêóïá¿®¹ o¨ß4*EQ¤Ññ0X­3T®đ±ÿ¹ă§™ÜîÅl̀L”€@G)%P3áÀå_ú×_·OÚ«SH™5ư‘]ÄŒo|ë[œ1«M;–4IüøËŸ”ŔִºK×wÓ_­34Tá¿o™GÁuø̣ûÎ¥¥­ƒÖ‚K1ï4bîœmø!Ÿ9÷.¼â&,;îøSʤËGúbÇ1ÿȸ›°AëÆÑœc“w,̃~öÉÜöÔj.XHƠ÷Mî!2sTc(Hưë¿đî×É{_2y×¥£”Ëâ’3ç?=€¯¥™ó[ÿ‘s₫èíü<ÚïÉc:æH)q-ṢS̉åÛ»O}÷jB?LEheB¡I¡ĂL2­Àußlèç̉ïƯÀ‘3Ú™̉¡èfN€ÑrZôTCñäúJ×âÅ‹Ú÷è“ÛlÇI·g9ÿ#2°‘cO5<Û ÓK?Jḳ¶ä¹ÍCøơ:ơ0J&èP÷C*¾"đ}¾xơ½¬í÷¹êSoÅÊå9fÿ½Y¶¹B8¸¥±TóQ±Ưøm]ÿ„s`J~×µÉÛđ©·Í÷o~˜î-[¨yAc+‘c-öa¢4*®÷×¼€₫J₫¾^>ùƯë8qV'E›ÄqhxŒÈ (£zk¡X°±Z¼ëÖ›n›0­]J9R dø‘]´­5ÿqÅOm×’*̃¤£SÏEJ3¹=ÇüåëͺíHi…çë{AHƠđCż%ËùÑ]‹øå'Îåm§Â].¶†¾¤\8£uù¥cÿѸ₫ÉăV<^¼è:rđ!́7ù{”zƳ ‡»₫#7 -@B¤aQ«%0Đ?ÀûÿûjÎ31%'>¤nœ¤Nœ)L‰0R‘bk9ó7ÖJ/Xx¯29ô¾,'đ7"S;'¼æuG™•ZMñÓ‹í…΢Í̉MCÍ~mD3QAhÊ{^¤Y³¹—ûư|ößẦÉ]4y×1ƒ@,ĂLæøÄö”À¨¾É‘BÎÁ.¶óÙ _Í;¿̣3€Ô¤!¤¦‘Â?̣À‘6J®V¨T© đ¡+®áŒ};×âÆ€n¨ÉäüL²Ô„~¤Ù8äóüÖúØg7̃›¿w‡í8m WY8đ‘)€Œ)­o¬*æđ4DZSt-®"¨×đbº¬ÖM̉ÉèØúe0««Ä—lá YÓø·‹ÏÁrs¦Th;Ø̉đJ`Ê`{e¿m¨¾Mi~ø±7séo¥dW¾z GüaÇk¸±'ĐTC|öÊßs̉́1)æ#M_IÓđœ’mÄa¤ÅÚA_¬èóº-\0oâ¡§¶PYNà%"S;3Æä:†¼(^¥ÄÖ?R ­. VlÂâm½#¤±1OÇIC¥˜;u ËÖlä–GæÉ-!ßûäÛ±œ¥x®€mYH!J`GÁ6q|0×û]Ç&çX¼óơ§ñØóëX¿b©Mˆû·S[H?,£‚HQ­ôWªlÚÚÍ箼‘ó›„%OÍ@̣÷Ñè'B-ÖøâÙ­^ñ¾[oœçŒÖ&LN ­2¼²‹´“ÑS‹̃_"‘dº ÿê¡b|‹Ëâ5ƯÔÂȬÓJ‰LÚ| a¦îFJÑÙ̃Ê3Ëx¡b̃¢¥Üó́&¾óÉwËh-æ iÈ–XR6:₫¶ç ¤a¸ 1ƠW\ǦèÚtŒŸÂ™GÍáû×Ưi÷§J~¬ ú_̣{ú I…@ÅS…ª^@_¹ÊÖ^>ưĂxëá“;̉u#)ØD¬´i&Ú\öå̉¯ôÔS î“@´ IDATÓJµPYNàE)€Œ©í9¢8러ƠÖZcKÁ‚ơCx^ 0-¿èfå -°B˜¦!í8pB₫₫>*ơ€Z¨xpáRn·”^zS§N¥­èP̀¹8¶…´äKöƒ›®¿ltùù ~~Ù[øøo''5u/0‰Ê´ë?Ê$²¡¶ Ô߸ †Të}CUz{{ù₫ïÿŸƜ1ÜKƈ̣̀‘ ƒƠPŒ}~óà}¥‰{ ²œÀ)€ˆÛŸÙú‰²™™ùqíLü?¥-ÇcË7™…‘2uô%<[ÙdGÀ̃Ú¸ó¹nr¶¤FÔü?ŒxfÍf₫ë–'ùŸŸËÔÙĐV°)æ\\Ûjôl/hTª¯%É;B‡|ṇ̃ƒ›¢¼y5ƠøXf¹È(Ö=₫Ư¸êÍRàp¿&ơÙ%  ˆBªO_¹ÆSKç‹¿¹‹÷??4g×T±’Ô需&TJ<¾vH xºkѧ~ø©mYNà¥!S; §¼á­2¥Ơơ…qR+Ńù‘¦­à°bưji] É?L̉2l Á«fç…u›QHÂĐÄÑơ ¢D”Ë>ñËûøÎ»Ï`¿¦”K‰l,)ăäpQLr¤¨¾®cSp-æ̀= G‡üåÁǨûa“jœ”üDÓº'B¶öÛơRHÖ‰)~R­ûôUk,~v_ùíƯ|øUS¨‡qă°Đ±ơO+ÓJ(ˆ´ 7”Å–jT¼çÖÍ›å^²‹²“pß-×Eê½½µ ! ûÏ‚ơ}e†ê¾É₫GM±Löư%Ha†† “»Ú™¿nĐ ƠĐ(æxaDƯđê5>đÓ»y׫ă‚×½bÎ¥¥#çØÆ±HV đ—ü\›1c:ùêÅgđơkïÁG€1ÛodÉo¤uO?—¾Í ĐB#‘ OÀCª5Ÿ₫rg–>Ï̃4Ÿ0Í$…@ʦơ7çm₫«̀B¥yzcEöÔUé©YNॠS;E×F ñß|i#­ßâ0oe/^,XJ7Gw§Ö&₫·¤$.‡Omc ·‡0^'®inâơÂÈL |¾~ăĂLèˇßq>®ëĐRpˆ7 'ÿèI•A ‰#%y×¼æ³ï~3ÿ₫“ñ{©§J~*¦ú†íYú)æl”T8FTê>}eÅóå+7=Á?7• Rq$H”Áp%°`]™rÀØç7̃Ẁr;D¦vö̃ï@.¿kÙ̀’k¹ tƒØǬ%×fƯæêA4ªûŸ YbKÁ”Î₫ºrœ-‰´B7¦äÅsú•ÂL8đ›{çSơ>ÿ̃ °,›¶b¼ë˜2¡L6ú&q¿Àum ¶à„ăcŵ,]¹†z\̣ •j60‰mÏơ¥̣^ZN@ăÇ;{+ Ÿ|œo₫ñq̃ẃTj¡˜Vie(PkñøÚAá)ѵè©„A "í ¤+ ÿĐÈÀNÀÊ¥K8jFç±µPa¼VÑ`ÿEJăZ°¶g/lÎû†Qp‰JV„6£‹µ·  ! Å“3¦\h\öHinyh1‹Wo᦯~¶öÚ9Ăê³’mD[HÇ$ ÷Ưo?>tÖüàÚ;đ‚z47 Ås Gº₫iá̃a¼ÿRr"L•Á#ÊŨJùO<Áå·<Á›B%ˆâœ€ tÊi2á€"TH#]=(†ÚY¾ú·h]Ä I+xd `'Àv]æL(Ö|)µ́HkÚóy¾›0đŚ?bö_:₫7KBM)oê¸v®{RÍ?$ Pª™ô#ţϭæÓ×>ÊUŸyc&L¦­˜£'Ëă~áø̉»^Ç¿đc@Ç]~ñhq1ºë?R ¼^4'€F ³b³́@Q †_Æ0d `'Á ¢ÎMƒ>Ó:rĩ̉ØÖu÷S ¶ß=Üú›V\K :J9Vöûx¡¡7­¿ö·I}#/Wº„ôơơñ¹kâăçÊÅçœF1ŸcLK‘Ö‚Ë9§G[©ÀâSơâ’_¤TßĂ‹ó ‡ăEsb[%P©{ô”ë<đđ<®»1§́ÓI=LÖèæđ­ă¡ ¢8q8oU?ù±“Oæ…Ơ?×Zç…%̀¸q‡Ldø{CiăĐ÷TB&·çâäŸÅ’ơ}DQÔ˜̃ ¤ƒØ›‚÷ßÁ@?Z)B­â2^ó•:uK”ˆj$5^ ¨ù!•¡A®¸éaö>•·½élÆ´äi;7½ê>÷Ă•¶tbrG®ÿHáư[Á‹æ„©€$JÀ BÊ5Ÿ₫J»îŸÇÏ®ä”Yx¡IdÊx±'5ä&Mŵ%‹7 !ZÆøÜ5¿Ô&'̃Cød `'A!PhªADÁ–Ø–`j{û—nÆUÜúÛ|ưHÑÂÔæ¥Lîjgᆡx|vSør Ok'úD è4\Z\uøÉsÀä1œwö«ùÂÛ^Ăwo{Œv×$(£d¨è0¿=vàßú>ih’f#J`¨êÑ_©ñ§{ï§»¿Ÿön'TÇ’äm³´èX‹’cQÊY´ælÆl¦¶çtiö6åÄek7₫ö»¿¹é,Ù:¶sˆ¤<ø¥2°“ 3c̃ ‡<&·¹´lzûúP©’¿ˆYé^0BaÅ/8væxÖoÚB¤†Çÿiû™ª%$Oe¸?̀zƯÑZóĂ; Í•:­¯<@!çw¬˜9ḥIiNëmƯô¹ñÿ?J`daóÍè4/ªy ÖC~xíítç¶R°%“Ú\fwå9lj ¯Ùw gÍéäµûåơtq̣¬1́;®(ÆlÖ Ô)´vûîó_ÿ‹ơ6®_º¾û·/YqêỰD ;ÇOú‡‘‹˜úr£áO ³/TU½569[’³Í„_KZ ³…  cI„ă°®ß'¢Æ4á$₫O0ª"Ḥ)%(EFä-–n©đ¥wÅas÷££T ­d: s0¼™₫[sÍÓÜ–B<́÷Ä£"¥đƒˆªç£¢ˆo_s'J6ï1₫çxå:™ØI°-јưPy[̣ŸËÄñăÉÙ‚’k“w-Kºo RH,KĐ̃̉‚£|¢ nè¿é€áS}̉A¬HƯâ¬Z#©­v¡•E+Ü´x ïƯq¼î5§ÑwÓV¢TpÉÅ̃@LjT3^̀€¿-$Ù<4̣ï̉CF“ó0Y~…ṿ8–àó×ÍăêG^@J›Y]̣¶¤æ›\F2ˆ5-ÇR‚-¥ÊơHlôộZG[)wÁAS:îÚ2äé\Ûgo˜¿áp­5³ö#-ë•Ç$~媶]è µÅaÄÜH›¸Ư±›{ú¹å©uœ{ô,zë_ß÷4ƠJ… Œ¨ÇyH™̣–ëØ´æ5ư¦Œá÷,¢́…x~Ü:¼Ù‰Ø¤Căw­±¤¤”·[tùç³áÙ­U”̉”½ˆc¦·1£«…~çÊưôWëfÓpä£J ¦ØÖZÖ Ø<·Ở;ꔡXñ˜ Å’ÖbÖ¼Ă¿ü}Üôà"*$[¸1íœtàtNœ=–¾ZÈÆAŸP)liX•2>÷dJS²w@i´RJ!ôøG´äl¶–}oÓ`ưÛ¿¿æ×_ûúg?^I]Úÿ›Ë³!óvtjP¦a홌|­^ç»·?É‚åøÊ[OàMÇÎ!hÉ™…NÜÂkK%àÄư&²rƯ&@ ‹ÿGc ôhËfhRt$adXu%×bÁ†2,ïæ§—^À±GFWk‘R|ÎÁ‘RÂ& Œ¦^*v¤ 4:f"‚%À±m ®Í±ÇÅ;`ƠÆ­ôƠÙ2XeË`åº¹î¯ ùø¯䇖†ûŒ+1©ƠTcª"P¦ÂLZj^SR̃M3{°¢½Hç̉öÙưä‡Ë«·}&¾¼’W@åÀ~ñ—dø¿`|‹ËÚ~ŸdC¯ÆPu«^€ç‡<¹lóWlæ‚WÍáŸÆ—~ÿ8V­‚ï °mă³NëjăÊơ3÷_5ăÿí…¥#MS3]˜”ơŒƠó#Í[¸oÅ%Ç̀’¾jȯŸÜÄG^ ÖÉ/㔬Ồ,À(BGæzđ¶ç †YôôưKEúơ¦P7£rM%|ôœcøÂ5¡…ŒW“ïɶB†,AÎñ©Ôê<½z­%ö<3˜̀ØÖ<?dkÙ7’,ͺ–¤àXälI‹k!ø1™hƯ€'5¨!/úp9P" $ª^̣‡Û)€K 'é$.¬ª˜¤q,Åoï[ÄŒ‰]ü×Góôº>~ơ×g±th2ñ¶ËÄ’ª—ăØ¿‘lXø‘ߺ¦À7awĐ Ób,-/RHA#IF BrÍüM̀7oô¾påu¸–¤¯\33  I:¦ T#ăù—¢ ¶ç₫'ǰ¤ˆ­¿Å™'Å- ×Ó70ˆïRˆbK*B-P”½×²ª…lé/³ø…uŒk+ràŒ œ1w*y[Pp,ªADÙ‹đCźá¥Jµ¡Rœ0»KÎ[ ŒkÚ~(p-ÉÊƯ|̣×÷s̃±ûñ½wÄU÷=˪[7¶ƒy«û(å,j¡‰»%ñô s!FFû£ŸK“ah¬h¡§»`IÑ(?ªøµBr6,ï©Ñ_ øÅç/á ÿ{//,}×ö¬yø~Hˆ™d´=æÀÈY;ÂÈ2â0n€NV¢[ä\›Pº¼ù¤CøÏ?qéưÀ>À^Àt`Đ…é0L¶ïQ™Ø)ˆx:BèmCĂËrº1+RÊôñ/ Rđ×…ËYÚ]eƠºơ¼ă´C¹́üS8löĐ‚k²à®T æ^\§×Ăs̉˜ơø1#Đ³Ç©úa¼¯`Äw6-@±Ó³xbí ÏlơùïÇÄé3éj-Đ̃R0UË„‰Ỡ̃Đä^§₫·#%LDvm‹‚kñásOá®§^@+ÓOÑܦ´m̃c$¥È‘̉\77ÇœÉÓ›Ê\RÂxP:9GBç,¡»7®¯^ư“ïö€ñÁïĦđo{ØƯ™Ø ¸₫Ö¯à…Œæÿ§Üïôw$^„Ö RøèQ"*¾æîÇóï_¹œ+®º©%®úÈ9±ïtZ fHÁµÉ;6®#±“}B7Y?Ă×À¸¹ƒ^4üÄÓ‚”¸ĐBă@M =Œ¿{j—_̣̃øú×ÑÙ’§³¥H1ŸĂIÄ‚”‡¶‡DđƠˆ°¹¡@â…“l&.tpüœéÜöädđ6“”·ù<ñó¶•(›7³jØ1ùJë4QH'Âhqè´1âS—ưË  3K i"mØè%üåv :J¾ ‰Oè…+—odâ›ño3₫:Î(…ên¹êS÷#z^XÎ¥Ị̈»…O\x6^x‹Ölå‘ç7±xƠ&®CE‘F)A¿Wºs0!¾Hí-EzÊ鸥+Q¤O*B ÑDZsơüMœ=g<‡M~3ß¼ñ~œ-¨Ô©Ö}“‘:UØ&¾Oy#!0ç”´C»¶…#ÿñö3øöŸ– t8¬¡*qưÓH®icܹ”s6í-Ûg"zv+¶YÚØ̀ŸÄŸQ`¦$OiÏé|hèÖ¯íÇÈJ€ø$̃OnqatÏ+fÀN€P ›¡!0ÙiÙñL4±—­F€ Z÷,×è¯ú¨Ú ßưŵ¼éă_á¦Ûïæü#¦̣‹Oc¿iăˆ¤C‹k\åœmáZ+¦'–_ J9_©aÇơ³¤nÓ\$0$¢;—ọ̈loÄ•~#‡î?›ÎVÓK,,5ë¾E#YùRiÁ‰²‰ơÏ9´›ÀØöVV®] 4l%úÈwñăÉzó¼kÓ’³yƯ³y|uß°1bĂyÆú‡JsØ”6ñæ3Oyăâ+LÍ¿T ¦”Ă\ÆƯ™Ø (æä¨Á`ó;»Úéø;ơ%NbøJƯ§µµ€R ?¨z>ƒå*C5Ÿ°:À¢Å‹øÀ¿›üÛ7Ù¯C̣˽–óN˜‹È·âX˜\m’†&<X–InMïÈSơ£ÑÏo;h¨-a>k *~Ä5ó7ñé ^Íi§J{ÑeLkbÎÁÑK`>Üöß¿2Ä.yBúq—Ë̃vßÿó¢ÆÈ³(„¨…ˆ•êÈ÷ézqCU)çĐ̉>†÷Ϻ+’%‘BHƠ™×WüèªÍqM !üÔ0B?€© b@Ú Ø£…;­n³Ăo4 {.)½HÆ¥ID *q<›?Œ~Ró-\[â?üå5üèúÛ8̣ÀưøÙ?ŸËª?ûëól̃²[ƒÖÈÙaIƵ8„ “/H9¢l9ê¹§Ï/v—…%øÍ“yơÜi\pÔ%|́‡À¶ú±«u*ơx¼˜j†ɇ­ó/ ‹e?›é{ï’-½øÄŸaˆQú"c:*͸sÁ^÷¿ĐGKδ₫›đ'ưW†À•³ûNnđ½«â'"Œå¯ư˜`Zød C•ôû"- P»©ˆ‚m₫}RkÇ´Ä*eÜà Ôư€ºíàz>óä´y2eÚ^\záY¸'ÍeƠ5ܶ` aàQʹ yú}C"J„ 9¦<́XÄU?#È äÁULiËñĂ¿…ïÿá~zf)¶%©Ô|êAH¤"“mGoû¡i~Q„đ*Fà{Œ¢ÉÜăâÈÀ΀˜;©„%å¨ßñ¸X7 éº}óAÉĐà'́ƯÎ’êTĂT:$R̉ḷ2p,› kWó/—ŸbçD^{̣ñ|ùÂđ<Ÿ«|/2yw)dƒG§-† )Ơ#¬ë0ëO¢4DC{¸ḷ¹aáf>óÖÓ¹ñ¡ \wçƒ8¶Í`¥†ˆØë7>SL$’RàÆ¬¿ĂçîÏó[*lØÚÛ´₫ÉƠJB€m®q\=ˆË~¶´xÓQ3y`e?yGÆÎVRHr#ñ&!t0Ø̃văµ} ·₫C¡ïÁ(ALHೇ±ÿ̉ÈÀN@̃̃ñṼ‘ơêä>m}u\ GxÛ,C‡(2å´HEø2Ä Û"́̃̀Í·ÜÂí·ßÆø}áăoƠºÇP¥F¹ÆPµÎ¦ç̣Íÿ¯ỵ̈&Æ”r3£ Ïɳ:™̉7®±RöX‰‰‰eÜGoIÙÖ 5SñÆ2Ç‚Yp‹7•y¡§ÆŸ¸ˆ9ûíø¶í¥‚‰É- KˆaÄ!9Vα)8Çÿ*|f-®ñăY Odæßä›L@Û2Ö¿¥ăâăg±xcÅP©“¸…‘Ö_0©-§ï¿ÿ₫¾;¯ûùfŒP!/Ó´₫¯ˆä_‚̀øûC­ê©Î:>¿]/`‡ß–Ô“¬äU“ºĐjD¶>í–'¬½”YB 4¨HE&W††̣êÚ6ù`ˆµ=CüïĂË µ¤£˜ăà)m̀è(°÷Ø"^¤é­†l)ûl-ûÔCeV”[†o& 5™‚ÍêES!!p-Áº5ưÿú¶Ó¹æ/]Üơđ“8¶ÅPµ̃l/ÿ̀דçå¶đ‰7Ăû®¼›$óŸúÑ\,ä‹–œÍ)ÍdUo…Hil[4H?æ|ͽ‚ R5­MŒ=î«0BÖ?Iüở´₫{lé/ĹZt¤çưC:ëM3”<–úÇh­3wp̀4¡G§„0Ij4VPó}ªuŸHCÅ‹"bsÀ=ƒå8?!h-8̀è,̉ÙZâ¨i­”rh͆AJ û롈’MG éMJơ(aKĂ$üí8éà}8l¿|û7$g úÊ‚à‡fAª”f=¹+á’sNà§VQ´ßlPNr;¬Spm‹¢ë`Ùg<•›o&ç4Ư†®± ,Đûv¸̣ê{{ׯJbúÄúb¬~7F ñ pưd `'@hDJúEĂkñ…6 .̀#f+x_§’pÛÉЧ½´Bh„ ÊÜÂ0D ©‘éEˆcxK˜Qä^2Pñ°¬~Y&iÉÙt” |èô}¸öêkz̃ü¶ »¢6ơWơ>Ol­øÚ)­¸F»5Zs® ³èđ«Ï^̀¥?»gƯjú*ÍR¡%yǦ³s ¯;æ>ú“?Ä+ĐÓ T·Q¬©çl)ă’7Ÿ0—y«ûql³ ›ƠÖ$JR³„pư¾ú‡.:Eüö!ÆÂ—1?Iü `<ŸW€ơ‡,°S ÜÜ›"•×F<—ºäB¤Ö áÉÜ4èŚQ¤øl› vŒÑÊwĹ¢Đ1–g¶ÖÚqqÛµ¸+±ê‡ Ö†j•ø÷J2ÂŽmYQˆGfÍœµàßúïµ+ºeÓI³:Åèâ”}Ʋï„VÚ ¶v-¡K’¾]›²¯øĂ¢MüÇÛ_ĂY¯>…ñí%:ÛJ´ó” 9̣®ÍùgÏ•w/! #‚8y—„Éääa-V¢†; )å]fNÏI³;Ù0à™|Å(×EÆfÿ‰m|ă[ßƯkE³́7ÀđÄ_bư/aW™°3  rƠ Ü×=ơs³‡aNl9.»ˆ·ù¦‰/i ¿=H)Gx æ=“A ZÓXO–dóµR±×`if@8hmY»Âÿéåÿ¶ñ§qÉ»/uÏxÆ9Ǵ7-÷Æ·\4a¤6«Đ5Áí ØØ[Ö[«^¨„Œév·.Ù™‡îÍ̃ÆpƯa`pˆPi„åpØœ½¹æçF Ó ¥‡5è¼ÔÍØß¶$ÛÆ±$ç=›‡VöSpMÙỪ₫§:o ¤?]ơăïoe8Ưw4ëŸ~öزßHd `' ¢­íy¥4ƒơtO§₫?2®@ie6¥ÖÀĂ½aψx߀“Ă#S¸‹3ú‰’¢ù˜•Z±e‹Æ¨¤"8l^¥wKơO×ư¼ö'_ự—VI7ïî½ïÅö™™¿đ’w›=uJnßĂn =X×=¨W÷{Ü÷B¿˜Øêđß½€/ÿæÏ”»7̣ºs̃Èơ,!ïX”ë₫đ̀ÿ¨0®XĂ(åmö™̉E)ï²uC…œm2ÿÉ䤦̉„HkqÔô1úµ¯ă :đ’Ï”Xÿ$ñ—¶₫Iâïaư!S;QđdO%À–‚ö¼Eo5LØ)$K?¥¨hx̉’börƯgRW'‘̉±À6å/hŒT&:î>”q«°”Z&Í@ IDATÛ)׳»%’®8Ó}g¬©ñ6¤hËaúر~ơÚd́Uˆ”„ÆKLƯR~=xáéùơ/ÿø‡ßm$̉²g̀ܧpÉG>1îèfÏ}ơéc ºûëú÷%~ưøưª½ÛÄơÙB¤‘“́àR,û\›s›Ă£«ûq¬”×C¢+’n?AgÉæ‰Çw÷m½ñ‹ ¹'øëĂXÿ„ô³G—ưF"S;‘̉–‚­Ÿ ­f%XO5@ p, Ç–8‘ÙûרáÇ)C¦iö§KazÙáµl¶ùú%2/â?2ù1́9KJ̣®C>çâØ¦‡ à˜ÉBJi"LÍßµ$]­̀›gæÄ1LnË‘³àé˜=&‡±’C4»á4Fؘ­»nü³ßÛ¨È^½ü¹ú?ñÁøÔµUl-|àS_˜p¡s g¿öuăŸxa“î(ºlŒ^¤+¡y@Ù ư8œ0wo6ø‘"ooÛ“!c¬´æø½:˜ưO_¿M€đ4é')ûUx…”ưF"S;U ™́.t•\º?¢àJZr3½62A8JëÆÎ@K ăºÚ6JÃuñT@9fqˆ$‹-H¨¸¤Üw)" L¸*ѸEÑ‘ä´rtµæ×ZàÀÉmËaL^̣ÂÖ2ëz«Ü:} "¤£hv¾å=tưUß[I“ÓÿbÉÁ ËyKVq'7 °£êPôƒÿülí@˸É/<ÿªăî]²Áª-C„o4¢Z’Ä₫ÓíWp,lËâ ‡ïŽËzÈÙÖÈ₫ªÆ¥̉ ÷WWüâÚî>^‰ß.`t¾BùƯăI?£áÅ”l†¿RZV_ÏÖưE¡mñ¦AK "¥™Ú‘£§²hm/ºØ:PayO /0[¼j Ó­g[‚¼caqƠÿcï½ă$»ª{ßï̃'T́4ƯÓ“£FQÎ("‚„@dl’16Œ ø=Œ}/¾—‹q¼¾Ï~`œŸmÀï‚1&ʲA „rN“5Ó3Cå“ö¾́“ª§[qz°™ú}>55ƯUuêTơYk¯½ÖoưÖû¯áUïÿ(aĐêø„¾—: #­n „Ä©Q.)\†Ë;×”)–*¸…å¡5 ô÷1Ô_åâí#8–ÅT+d¶ÖäñÉGfjL6<Ú^€-̀¶!R&2‘RPvÊ¥"¿ö̉-áêÁ₫¯cŒă0ÿ¿6Æà‹ñ­”û9ï°D¤đsøå ¿̣ÛŸ8óO¾r;µ¦GƯó Â8P!¦+›­J¥è°ºZ຋w²ytˆư³™E@†÷¯SçjK¸pµ ÖŒ ߟ³‡1₫éø3ö‡)²ưÿ̀̃?A/8ÎP*"TÚrr¿ö϶©º6‡g›ŒöØ<̉ÇçTq,‹²+9wm™ñÄd/T´ü…¹9,o{å•Tú •¢4¼j…b¡À–U%6÷Û́™˜i…ŒÏ.uh¿|üV½3ö.øLxåµ)àó½-Ûø©×\Åçn}’(đ#EÉE —ƯT\&RÄL=ÍTP°꽿°ú³ưéq²(`c$!feO ;qŒ#(æîóNÂvÿöS6÷̃÷¾oƯ›W=´?D¤4*!Å_hœRÁµ-*®ƒt˼ếü˃Sq»/ä×·DÍ »Öôñ‰ßÿ#ñB²Ơ¿Î±Ư~ é'I~₫H¡çVY/Ci\Ûâà‘ î©whza¥1©i¤íR®Tpm‹‘²ĂÅ›û˜n…%¾ûèa¦:z'Z…„ơYT ¼• ưH¤»â‰Uñ₫7‘“BP*˜™à—ßp‘xa@;ˆbª­JƠ€€Œuù½Pë>$̃ö¶·oû́_ú.ºÛdç0ÆqxO·#H¶‹B)÷»"Pú•ßøÈ÷¾ô•¯¾ñăG¿£½ĐLüñµF(Ê~ ˆiĂ&Ÿñ˯:‡{ר¸2M Bï¯Rè#i7êÑ_ÿå_-.û-îöË—ư’̀ÿzàøCßùTKOëïîñ×0Ruhy!-?¤Ñ LƯ ̃ÏëÀ§¹àăY’N]2;7GµRa÷ØO=ñ0sơçw)áx¡ÊéÿéE%„kṾ ŒDó™o?ÀKN?•ëxÊÈb+†ü‹¡4¦Ư8ˆÄáÉ9^wÍ%ë·qÎà₫G#+ &at¾"`cœA~ö‹BT~pÓׯ₫ư_ÛüK/½à_¿~`”m>·À0ørÑÖ5«Ø4\ááG§MîÄ|ṛ=–‰ß¸`Ó?öæ·îk-̀Et—ự¤Ÿ9~„ø₫O‡pàØ–áÛ,ú½- 2 dÔ[^HÛâ¹>N@­íSïÔ:>7<:ÁÎÓÏ ƠlĐö|mf»M³Ư¡ÙîĐhuh¶=ÚvǧƯñéx/ ítüÏđƒßiyÏ¿̃đ-®Ú¹v ăi¹’NĂ<µ8̉?̉ø‘̉û¦¼å-o;…lïn† f ÑÍk`¢ƒ¤¦> LG1ûë§0ûí}ñm/°8üî·¾₫Ï_¾s5•¾~*EÇ–±ôyR®”‹RÁáơŸÂ­ûæL$'FuBüIX‚”dw?₫hó;ßø̉4Yâ¯M¶ú'|ÿ$ñ÷#¹ïÏ£çV–´¹`,!đ#…í̀¨”6Sk"ezúƒÈ̀¹ó‚/ˆ˜œœä²ÓÖÑR2+†0ŒĂˆ(̀ï̉^g·X9(? #:^@!jñû÷pÁ–á¸j éF>”£/TâÛÖïưÅ^B&‘]¬́Éơ”„üø–̉¬“iêÍ“˜ÂÆ) !&̃÷›ÿó¿î ®CÙµ±c' ¥¤àHªE—‘*[Gª̀µĂTÓ@¤»L¶FN_?È{áƒ0+9¿ÅƯ~ d«ÿÊyÏ=°8Zë¤2[)íTB'Pô )Ù&‘¿†l™IC¥ BEÛ˜lÁ¦u£Ø–DJÖ&´aµDØŸ`)°Ö éDđɾWœ³©ôœ’ç䟉DY|N/¦ZÊưåÿú‰K0Ă1*gà]S ¯>qI=qm2eƯ:ív ˜ĐZứÿü¯ỵ̈è₫±}/>c‹®]Œ¡8–¤ä:Éû_y>ßß7O) ưEÜ™˜µ >muIßzÇ]îø^LÖ»½è½“²_‡ÿÄ2_Ï=°H¸ơ©ư˜6P¡r,„aØư22o!4·́à̀³ÏͦïäÙ~Ë4ºäÏç¢8đ|Ÿpæ0G¥¯¯/'ôq́ëă!( AdzóïØ;Å[^ûÊÓ1«ÿƯĂ2–+//å’¾û6Ù¶!1ÈÆ_qƠGßré)b°¿OTÇ¢è˜ÅËÏ܆ÔfÅ癜s2YǪĈE~́å—Eæ‡x¡æë·̃Ï»/ßR K<}c‘&ă<55φçm:çe¯Ùôc¦æ$[Ä <2_â’üÄ4€¹æÔáƒ_øú_zƠ;è+ÚôúJ.–í𦠷pÛJ1馟ÙrỶ|̃SGûøØÇ?>¿g~ơÏ3₫’²_›1¾ÿÓ¡çV¿đÑ?·%Óéơo:!Ơ₫₫t_ ±,êuO¶Iư{ßdµk7Pp ×Z"x.ĐJD?à₫{ïÁSaÙX–Œˆˆc¶yù1?4å»vÖ₫…Ÿ=ă'PÀ$Ÿëµ•o2J ´,¼ûM¯üôY£…ÆÖơkôpµÈp¥À+ÎÙÊă“M\[coRÄïêµ}.—Ÿ2‘ƒ»[ñçŸ$ëơOÊ~I¤1Ă€Ä÷óAϬ́J¥kơKkôZSt̀° Ktµ¥’=7—x‹Ës¡ydl–§a&îXO?w`9䃢(Â|ÏcïƯ\qÚzĂ«_&˜½B¥è!?Ø?Ă5¯~Ă‹ÀîÇl’( É<_¦i ´²ñKøÀ‡ñ³DÙƠ«‡úyơù[xjÎñ$Rj-„Ʊ„>m´*^|Ê*®;cDÜÓ¿N¼ñÇ~ü‰ë^|É£µÙ©¥%¾“Äß”̉ϳEϬÂo~=”‚\°Ùóû †Êf́âi6KYJh!Ø}x‚Ÿ½ĂŒ—2Ît›´;æ‹Vñ„,¤´6¥Á0âsßø.oAa†º‰4:}mzNJD…âÖ½3üÙßưõăïÇ$ó¹€çệ‘@hi¥æ¿üùÏ̃{ßă{»ú¼¼î‚mz÷dSmÁHÙÖ—n—o_ÅgÁûÔï₫—ưo|ëO<éHqÛ{ßư3où·]đÚ­$ßp̣|ÿ|Ùï¤HüåÑ#hØÓ);rR F»PU}.ˆxƠO’Väö₫tÏ PÚ”¿óè₫ü=WówŸûß8…H"¥Ư.‹sÏ$¢µÑ ́ø>³“GÙ{xœUư}̀ƠêH)Q‘J“’ ̉mFD³*:4£ßsƯƠ;9s}›IßaH2ơ¥k®¼ô#Oû—5}¹ ±®_F·}û;Óû‡Ï̀?pÿ=í£ö¶1Ûâ{•;Î╬Ưwq¯ÿIƒ^°r8Æ̣”Ö¬í/ ”a²¥µ€E+x¾`‚˜iúô¯Û†cÙH!M5!GØ9æ–ØË§ï¡5Q¤đƒˆHi¾}ǽ¼ñ¼ơ&–Ǽ&9¿H¾ÂB£%&|Å̃–ä’Ú Aèùṇù€°5f§ßđú×ÿú'ÿñóߺä ₫iư@ơ+o~Óë¼áË_˜:z`o'~¯dû/7&„¤9L™q2¾Ÿ!KüưÈÈ|=ôÀ ‚` AĂp‹åØxŸùu:®¿KK²çđ$—œ½Ç–Ø–̀ÔĂ;E?/6ääg¥MI°í‡Üuçô• ÚÊx ‚.̉5‹@™{?Rú–Ç̉ưȇ.%‹*jïñÈä‡s̀ßư½o>₫«?û_Øóđ}ÈB÷Nî–/'&ỗi ÙèHî6A¶úŸT‰¿TÁ’ÓosÏïzvV Hva¤‰Ú5Ö¬BVV™j€\~Ù³áè˜.„mßç 7ư€×·º¯RÂQ­˜¼.ƯZÄ̀À0¸ơ‘#ú>ơ—/ĂTv`‘̀¼P'×êKz &s÷‰Á'}1=ưIẢop(~̃,ƯJ?'%z`… º̀µ/…1æ¡’cjù"{ŒeVé„i´,<:Ë;wà:Vl¤K¿ÿRÑÀrˆ"…Đ©ó½ÜÏéG°%ϸM‰´&ÔN¨¸ëÀŒøà»ßq1&́OJ‚ùmÀóE’̀«ơÎb Œ¸wć0ƾ7¾í&3₫Dàă(™ÑIWö[ŒX!Ô;‘v-ñB@'Ь¬`IŚ¢ æ¿•N†zÀ×ï?ÄK.Ø…%̀øëg» XŒ<'@Å̀ÀṆß¾ŸŸ»| ~¨Œý¤–&eư¾×Ö5xÓÏưÊe 1Q@ăoI0ÿu$ɽ$ ˜$[éƒßßvÇ?ˆO îÁIè̉¢çV‰½¤A@ ®[H‡n¦ÇZGfpY×àÄÄW³ƒHº8V¼ Èy‹§¥̣.2àø?)=¸ăÙ÷™§R. ]ûc%_ºç̣?~ûZĐ’, Hä¿^èµ–O&QÀ8Ư-Å{1ˆn£Ox₫yÓDÜô¤FϬz2a´$­©*Ën\́Æ1=)ùÆ$#­”fʬ]·Ç1`¹¿ââñ`Ë=®‰[}ƒ0 ¸ñûyưù[LCM.W±d9ă˜ü0¢ƠnSê_U¾â?}!Æô“1Ÿ®IèÙ"?³/‘ïJôbÂY}¿†qM²‰>ù¿ç~Ø'đ£ ¡Â;ăL‘ZiÊ®•&‹Èë×tY‰©Å¥†&Đܽg‚3NÛc™<Àr£¯ ]m¿Jm/äλïaÓª*h3Ü3Q>æ3æû"Eiưåûó¡Ÿÿé‹1†ßG– °yá×[b´ù|@’ùOôûëƒOʃy£ï₫"ôÀ !RZV\+^aÍ5'€ ̉́\]§áf†%t÷4áÔ1tíƠ¸ïɧxăeg‚8¶!ó½Ç)̣eÀÅ“ƒaQF_kBeúÂæ‹Ûï¹4øA`œD2ÜsQ˱¡öÆMDñ–¢+PF LÆc´m¡9xtơ}’RÁ¥èHFûxéÎQ ’{ÍsĂưøó(Ù tr\D[ü₫ÿøï/}é_}L1(éĂ?©;ñ₫# çVúæûŸøÎ×ÿßơ"KTÊLṇ̉´$ 5AsaëïZàk?x§PdËH•íÖđ¾kÏgƯ`…'ǸwÏ·́›ă¢ ÎçÁîĂsßT „´…R:;À*˜*ƒ öÇåHØ2TdM¬S¨•fxơ”ĐJS]½Ç–”‹éfȯ̃E¨aïø_¸ưIL7°QDqT̉́(3\ZPvCqxÁg×i;Ö”GÖ·ç§kd’aISÎRü§Nz`e ư믽èû¿¦M¸lÅN é©8)³/™Î+"̉¤Ÿ”Qœh“„Q‹=cáÛ÷>F©à28<Ÿ·‘µ#Cœ2ä²qƯGØ0Xdc¿@=€'Ú1ƒfj-B¥î, !4a»E䛩̃¶\ÿÄ‚áHÁø½»qlÉPµLĐnđ¶k.å_{€çÑè¨(¢™ª„R$ËPB[)Íl+`ƯPÅyå5Woụ́??F&’—áîᇄX¤«ÚTĂG&­€Â8Hi„å˜=yFúa’~$΀iÅå6!°,‰Dt:Gøû™)\ḲÁ7\Éùägđó4ê5¢H!,Â(÷Aœ?!­l¿/º+ÁiçBÜẤ:6í₫ µUç°Đ yëÅ[øëï>fZ€Ă(’B3~iHA‘ÖxÇÉHÿöïüΕ_₫âç&ă$mÂ'¥çôÀÊ ½˜;a„m a Êø­5–ecÅʾƯÈoâ¡ĐH!À¾ø¶B¡)».­´ßF^úêHi‘ê:N’Ôº{ÑƠq£R×ÉÇ©à:¦̀Wéăo₫ữúâ³)Ë´¼Z÷óH-̉De2Lt|¡Åö5ƒbÇY§¯qåUA§5M6L´¹£ü¡z8qèV°\|I&ÎBDZSEŸ|Ü›[J6+³Ö ß>!Ṇ̃C<í ¢Ơñh¶;4ÛíÍG³Ó¡íy´;? ítü´½́1Ïđ‚?Œ‚?ñü)úùø¥kÎÀu\zŒ]Vlüé‡ÇYđq-Éá™¶₫ƒ?úŸ“KˆÏ¡#z_üÊA–û¶H6@&hËn₫~ơO₫É~—'ñäs*Ö 4!"Í-Q¤CsK~VêØ[©ô˜Fz̀È„éä9Qˆ¶‹xaÀǛ Oà‚S×cÇ @£G§›( ̉™VÀ@ÑæĐ\G\÷º7 û“<@~ŒX?ô¾øÆ¡…Àrm©óê@ èsMO€%ºëñ‰á/†‰̃Å̉Ú¡¹çÇ]Y‡_rÀÜ-¥ưÆ­Æ]cÊ7 Ó&́–+́lĐ ₫îË7ñêó¶€0LÀDB ós\ë}¼ú‚mØ) 1¿…Oô üH1^p-Á£ă ̃üẂ¤[-èxiöđ<Đû̉WĐ·Ưđ•Dzö̃¬ï~¨háØ!AèdƠƠK:%¾ŒäE’Á×€Y‹C~Ó\Ü%Øư˜9¢H4 •ÀóCZ~Ä×¾û^vúz´]ıD*–8Œd¦a*Z~„%%síP¿é5×Fæ×¡'z`e¡o¿ưöV;P â\»6¬à ̉Hˉ³ûË[|–\â±ü䱈ߟ ë«åĂơ§{ aJ‘ ͺƠCxó“¡IêĐă÷?s=ï¾jBë8 ¹sRZ( Qd„Eµ³­ˆßüø]NTèéüĐĐs+ŒƯ÷ßQ¸ S£2+e)·€"ơ\ ¹—ë~t!Ñ (Ư؃å‰R5̉f¬x«đÀ#aé€-ÖàÚÛJhÅq)0æ ́ŸiĐ_°Đ Ô:¼äK·c¢€²(àxiöđĐs+ xUKß)eÛ a‚JE'ëù–\ÚWhĂø#Ó÷K̃ IBÿÅ¥¡";VT‹2¥ÊHˆ{!ü?_¸‰_|ÙNB-°-™ ‡€I\*¥¨u"#^ªơNÀUW\¾uç9l$‹ëôp‚Đs+ ¨™VPËO ’˜q\׉%Á²<_i?!³m€ˆƠ„„Ö±ÊP÷MÄÆ. ëq0!÷E!è„‹6ôá7æIfúAHÛó˜?̀ç¿ÿ /?s£iÊ9#1Óơ6ƒE›Èh"êÙVÈ›ßög`Vÿ¼\X¯p‚Ñs+1>ß₫éi„AÄR/)b)"MFJÑ B:~Ä7¾{×½ épl‘Î,ÔZiM£ÙƵ%J̣‘…¶~õ/ÛYưó³Vă IDATzƠ€Œ̃—½̣Vc·‘ÛJ~cVÆá²ƒ<.›ö•…F,e*¢ă‰Å? hƠù̉Í÷rƯ¹[±82-QZ³Đ ŒPI|¼v Äy]¸q×¹m"syÑĐ̃uy‚Đû¢WZZ–X[·́Œ*+øQÄ`ÑĂơåWëgù6Ççl—„»À#s?̀¬XÇ\/iû!ÿ|Óí́-S­”äy¼å‰”¦áEDi®Á8“§¦[ú×?üás9ÖôôO z`…¡¢Hß?é¼P¥M3hàËi÷Üs…?–ăoØ‹(Ëæ̃Dm?@ª?ûâwù­×ƒ¯²‘bZk¢(Â!nDÂ8À±'̃ù¶7Ÿ‡1øD($¡÷’'=°̣Đ¿øÛ°×̀'›€8E'à̀Ôc^ôLFª₫h\"ª®Åñđù#¤­"é;è®1DJ!MÏçđ₫'ýđ ;ÖăÚ†˜(LÔ=l+ƠF€öÅ«̃ú®sÈ@¾A¨œôÀ À̀Íÿ8[u#ëÂGƠrѨç&đ³¯˜@SĐ>ƒ¥çÖÙ½œ«HX‹Ù9d¡Â´gÅra‹ß?ŒïÓö#₫đ3_åm—î@!ÍÔ¢x‹3Vóé+Xqk²À’RŒÍµùƯư·«1û₫|‡`/p‚Đû’WàHƯ•±í”ÖFk_Èç½ÿO×âYèÙ¢›¹¿ü“ C9£('ĂNó若¡ü¶ư¯Ơà̃‡çºó·c bÇ&đ;mKvq¦[¾̃±yă@ßȺơtḮqNzà¡å…“¶”©Ơ) E;UÑy¾ĐÇüç¹áé,̀Äà O!«íÇ̉ä£ôH)ü ¤ă‡|îúïsæÆUX–á9hOͶY]qĐ9é0)„h†_₫à/î"s=€ˆ̃¼̣Đ€U¶Ô×+®ÄËï`ÉÊÚos­´ÏÏj5>G‰E•R7ju¿KN· éü3#żN›¸₫ûüÔ•§"…éź„FôG%¯ÉHf[úç̃óK1†_%ă¸ôHA+81°|́£I‚i0Sqâ!Z~&ŕA–s Áèxì₫9ªrʈÏo=t24¤åÜußl,R®ö#…`¾R-X©æ¡s¡R¢`¨²aûikÉzzƠ€„81Đ­·, J›»%Jƒí–âÎ=±́¥×X̉ ,ç–ơƯZ<'0{_₫;–Ä‘: M̃+Í Ä¿L”‰:A€̉O|æßø™ŸJEùô,ĂˆÏYÇÔàV¨åïÿ̃ï]†‰̣Û€̃8ñFÏœèßú_÷ƒªkaÇé~)L ͶmlI<ø™»— i Ër»˜zO§ „@Aú³9®q yỹįl(Pđë$â!(Ưuy­¥”Iv|ÜÏ£ûđ¢›(X‚}3m\™•í@qÆ™g­#›$œlz‚+Œ81Đë6m–¡̉l(˜ÄŸxaDµ\0 :‹2ùƯ¶ôc‰ï9·RYd¹O¯@î±®Àø̣cÉ•¦kO’mt×q’ă‡Qd„CÅço¸™—¾%,f} ¹đ$’¢-Ù5ƒF¨HjE¤ŒrP¤Í°´¥̉b‘·E&²TX/’2\̣óÄcN7Ỵ̈+là©©Zú|ă4Lâ2ƯÏ Œ£Û²°,‰-–maYÅê>5ÇE[Gxd¼A;PKU=,̀5é̉S:!è9€Ü~¹î…ŒÍ·©]~æªDvxܼgɉ ˜l̉j6¨Ø‘„é$^c°I„`ÉÄ&ŸeÉô9 %»miÙ-…Ùè2­â­‰iđI<ˆe™ß¼@jMG JƠ>¶­îắ³Ïạ́SGéZ×jpṕ“éf@Ù±âmƒqç%¾%©ư'7A/X1ôÀ ÀK^ñ*Ѻü=U4–ÙH#’FÙ RÜ₫ؾ|G‡¶–¬í+°~Í(¯}Ñ.^í”9}¾̣È4{åá#5d»†ëZhaÚm ¶ÅBÓ§:´‚cSp¸´—î6b¡OSv[œæ[Ä,]¤8¶MÁ1|~Ƕ(‚ÈQf[¢"iSáSGÙvÚé\µs O-øĐ®ñ{đ'wßË\ÓcÀ…ơĂư\tæN"eƒ2Ưy\{ƯkF¯zù+†¾÷íoÓ3ø†XA|é₫q~́¼µü̃§?»ö́Æ{î4—F¸åGx¡" Æ<Ÿ£³uîyl–T*6ṇ̃³6ñ₫W„!å–Çspb²­°-A¹X ¯\~˜ «,.kN:ư'₫9Wp›RÑeóè0“”]› ±Wmæ-/ÚÊö-›¸tç&î|ªÆÁ½Ọưûăư&:í&Qh’†‘H .̉êñ̀@ÚL5 G©…°ÄÍߺñ²ºáûë̃qƯUŸNϬ0z`…đÀ‘:ç®ïẵC ï?muåÓM?̉Ơbq½]kB…eˆ8´xaZ½Î£û)…](sÉ)#\}ö6^ôº 80ïc16èRk_J'ñ#…ĐÏÎnRz/Æ3)³ơ^àZ%×â” Ă\¸}5¯ºâBNß8̀-»'yäÑGùä—oá¿MS$@ Ăó#E”Uh–m¶ -?d´êđäDÎñÄ~>²Đáí¯|ñÖwÜư“/¹ü²?:”Zëd+ĐĂ  çVOÍÉCóíÇF«îi3Í@D*aÚ™$Ëm—̀”i¨I²ơR˜P\ÆA A¤ZÜöØa~đÄ!₫VĂàĐ*^s₫VÂzMn €PFϱ«0·PpÚÖ!l·ˆmI …-% m₫ñ߿͑ñI : –ÉGDºRD*ˆ©Åf²°éú3¡‡C̉(¤¨:d¥øs&E!GkÎ?ïÜ3&ꟺä’Ë̃ràÑû&ÈJÅ{˜^z`pó̃¹·]´©ï³A¤åLĂO5÷UÜå—\Á‘‚JÁ!£çwj!ˆâd^B±bg`[’¢cÑiÔ8<׿ÈưỤ̈­¨µÚ~€"·ĐÉvàØ¼{¢-(rg¡•B(¸.}•"¯û»˜] 9?‡Ôu?"Œ|"e¶ J™I@Äç®E¶Ç1•Å¥m6ù­%‘R1J̉đ"]²eñ±ûîüçÏó¶ßư™×¾äÏ0„ „,̣!=<ôÀqÂÏpí®avO5°uUñE3Í@+­…”FñïØˆÜe˜¸\ƒ ¤ŒÄpf$—fN_¨LE ‘ị̂ˆvÑhw¨7;øa˜6ùtgÚàR[R!±ˆN¼Eiy͇DÆøădÆ1ó„•èÎ?ä﻾́¦&¡áˆv¨t'¤øS¯¾êăëîÛ·á•çoÿ !¥«•dN  ¼@ôÀqB+w×:ß(Úk'ê~²'2€¤Ñ¹Ïµ×tÿ$ºGuåÇy!¡̉„Q̀ˆ"ü ŒoAÚwŸ/’;.»2ç›…,ËBH‰„†—  «/´Ùßçlï˜|CNÄí¾]Ÿ©ûyƯÙIF"ͽ‘ ĐS «ÎÚú <5uÑ™[7¾Ñ²£V† ‹zày¢ç:R¿xÛpé΢-µ)1RqÑ ä"ă³dîæ~™_(S’Ú4ÚäÂvïđKzđă{aé™[œ|Ë¿G¾“/—å?6!™‡¤R¦=8}$a˜O® qXY “q́‘Oï %G‚v̉©9@Û9mưª ÷MLßûâ—^sÑÔ,ßë´0N Zú¯̉Ă³A/»z0T¶?P´¥i4¼ˆz'¤á…̀wBj¹Ûl+`UÅ6ûe2cK!ơqb0^ߺº—xÿd£ĐÅ $ëÈcqkđR-÷Kư:₫'ĂCSçótç° ưEf^῭-P(ª *±m¤:zÛÍßzôÂ×¾£ê Uz Â/½/îâæ=so(Úïjù‘(ØBDZjˆ’•Yt| ”Æ5U×Ụ̈†ŸŸ˜¨»Ä{r‰¶äGó.:&Ô<}wà Az:·÷Ï5=]ŸÂbḄ¹•†3ÖVhù&§à+•̃:¡¢D´ưˆVâZR˜m‹ÍĂ•ÊÿúO¸î§?¸…̃µü<Đû̉^9Ú¸óªSÿ¹èHæÛ¡î/ÚYÆ]w‡¹I}¿æ…T f祴¦äXq̃Ù]N!ø›´'F1G+ÎZusF/³U1?g««£0œ¯7$eÍ´[1~ưº₫‚!AE*wD‘{½‘M+Ùóí™V€ÖZºÓÿùOÿñ]úO_{P‘´ ÷t#zàyàÆÇ§OŸ¬{;V—.Zh‘F-fZƒ%'•È2ÿ¤{w Ö ®gQ°å¢–]ó<‘ëÊÓ¹ûü:›ü~¡Ùbtt4í}âzg’$_b°IN@ ĐB£cMƒÔ1åÂ“ÑªĂªKËWÙç^́Û4¸¶ Z°8Rë ´¦å+ˆFÇç}oyí_ưûí÷xí® ª¶ă–èIˆ=gôÀ³À­ûçùô-‡xđHư7_vêĐƒ%G®nz‘p,‰‹¸hl)°Å"ĂO₫‹+Ü4ÄÄ¢›¶Ñ LWĐ„&Ç̃éqtV0Ḳëf¯¹_é¿hb́m²ÿ±WJ >5|“ı,˵Í]´%ëú L6đ®¯¾ẩó>ú’KÎÿ”̉̉Zyô˜ƒË¢ç–Á#ăÍ5ăµÎ­Ceç”z'ͤ(H°¥Ä’¦̀åV₫D SkM¤ é›‘Ư³çUÚDơNp̣NÉzD¨AHÉËw­¡¯°f ŸọØØwïŸf¾VCE^́¥\[bǃ̉²̀œ+BˆŒ“÷ù*^â±–4J>¶%–ˆƒ´6ûǶ(Ø%×ű̉rذqne×­œºfÛ¶ñĂz'bºî™)h‡p,AÁ–T FؤéE´‚ˆÑ>‡=Ómöçj¢É6Ci,̉Pi)™̉«où\vѹ»oÿÄuço[sµe;¥( ̣̀ÁÈ¡ç–À]̃qöúêgă¹– W: 5M?$L_€kÑWÔ½dÀ†1ùvÈHƠ1ûx4³­–Å~F3Ù³[R`a®̀vÑđ#”̉ô• \uúz^yÎ&ÂHñđxƒGNđøØ ï¡´É”]©,úÊ%ÂHáXQ¤RCOh»2.6v•&É“yDº·¤ X(P­”(96•¢ËÈ@…Pi,!°%”V­åÓÖsæÎí\°iˆ@ƒ(j^Àl+DÊ0~n÷Ls%¼H³Đ QZSu-Ö(ÙŒ-t˜jXR¤g™ˆn,0ßi ×X– êZ”s~¤hx!;×_6_o>₫_¿å'?ö¼Ơl䙃='£—$Éá›»§èsœk.Ù2đÍZ'$ˆ~dzäămü1L9¥4kú& QÊĐr][0>=Çơ÷î£XíçÂm£œ¹a²kă…µq$2®ä§đ ¡SG¢´¡Å*m"‰’M_ÁæÁñ{ǦØ?¹ÀÈ@•¨]ă¦ë¿J­Ù¦ă]Í@ùë]/™H́†,aáº6ƠR‘k^ûFZ­6cÓ ®ZÅgla×ÖŒ–³MŸùvH¨ŒÔ·e'’ŒÏzL˜¯´ù>][Pvm*dª°çà·í> Úüê[®æưóF2=– ²„f¨ä°e¨ÈØB'í°”I¿D́Í)¨º×¶(Ø‚£5Ÿ¿ûÜ.ưèßµWk½Ø œô ça®åï/;ÖÖ¹v@”ØĐ2Ùơd]°%¶%hx!J™}êpÅæ³·ïă‰ư‡¨w¤6ëđàĐ0/Ú:ÈÖu«9eÍ}‹ù–OĂĐÚ¬¬VBêIV>å"­ă‚¢EÑT&kMæê„)w‰‚°UăYưÙHaBóáƠkÀ-±±ß¡áÈ´:a„…À¶E\̣K_–n-”Ö„±ÁlAµ`c[ïsï¾qî{̣ 8J}a´ÂuFûù÷¿»̀Ruc­Àvá́uUÍ{iô”4IuUâÏ®´B©·®*Göºá¬›ßÉ´Ÿ^rèmRܼo^¬*Yï(9ÖÖ馯W•]1Ó rycI¢N±ºà̉đ̀ï#­)Ø“³5fæ[‘R8R²Đgrz [î¥X.sêH…ë×pÁÖQvŒ”hx!SÍ€ Ô8’¸¨Sg „Ä–&hoø@ —m|mQèÀQƯüüÅp‡V-ÉQXæÄ¢Đ¬­X́›i›-Œ”+ư’&&çE‚HaIA_ÑbU¥ÀØBÀSă“<°œƯ{örhj¿ƯÂ?ÀB´†rÑA#Ÿ]b¢Q|[†JL7‚̀øáXăO‘nÄƯ‡kœ¶~ÍKªë¶ïlƯwXñĂ%_~¡çb¼dû où5ÙđĐÚäÓŸÆöSè¸O¿îE mfZ!‘2Zxơz–Đ̣Â(LÂnAJ\Kà¶<æêçÓ "¼Øèƒ0"Œ¥Ă¤(¥¨–:ŒOÎĐ70ŒQPô,J¤î…©ñç3–iÔ‘;ó¾‚ĂxƯ#Œ43mUúË¿øó÷¾ă ¯úƯ~O/ñ̉“ =Ü?rtfî%G–fÛ`Ë8‹_´¨wL6}914 CeZGë>­ " Mÿ|i´âÔ`ù)ư˜ Ø¡`ÛŒÏ5y|ï₫JÀªáQ®;w#çn¦àX&AèEtˆ²+*Ú́ŸídÔY–¿’%¦´·˜ÏóLˆb¾AàÂêË‘‡ÆT ú 6×âÀl‡‡öñí‡ppߢÀ§Dtü€æ >J¥ÍULj0IGEAÈ .[=J£"œ¶º̀ØB';ï\èŸ|f“f0ÇSúû´[èđ—¿ôÍÀ×0×|ÂÑȸZ'¥è9à¼Q›ƒ³­?œk‡Ú’Ƥ›~ÄPÙ¡̃‰–5₫<0Û ­8¼Đ¡Ưl†QÜ×A+f w™ª€ŸilËi ¶E½=ÆßOŒƒ€jß—2Ê–µĂœ½¾ŸjÉeª­)–ÊÏ‹dAÙy^_Qz”’‹´Ú·ïŸáđSøîĂèÔæĂNÑö²>cƒ×:n6GZœ£H¤ÅB¥™`Uy ­í«JL7ƒT!Ÿéfêôn¤êp¤æéKnÚư_û™·ÿÚϽós˜D`€ÙDñÿ9äÉ€¾öđäyưE{í\Ë qR«̃ ©¸Mÿ™€Àäú £‡ó›4}–ħ窘߿ø-½HiB~h4÷[2L_ïZÎ 7ƠkTÜưÜ»eUZÜøåÏÓñB‚(Œç,R Ce‘È”±|d³øĂÙRâ:.•₫̃₫ÓïæcưÏxíuϧƠ MX†©Ó #ƨëœÁ§=N9̣’fª%ͬƒ©¹\Û¢Z°¨$5gưE÷i¥«º³&‰:Y÷c:¶F€88׿g~̣'̃đkïùÙo¢Ă&èa‚'©°HÏ[$3- â |­²¶¿@Ă¹t&L¶zª°a €}úÊ.­ DJèø ? SJo"¨™9ƒ¤œe8ïBA("T´EˆăKÚ~H»è°EÁÄÁư|â!­6₫1e¿îäXR¾R¦AÓç=›èF˜q_¥r‰₫¾>>đ₫÷qdj† Œh´=ü Œ÷̣‰H(q)s©c‘’§LÔcÈF®cSû´q̃†*‡¼l6bKû|$ï«aÓ`‘'&›iŒŸưĐE[ŸüÀÿ}ù?}̣M I¶9‰™‚=\»kơó-ŸDnĂX¢qBà…¢mxé°´Áä)·׌åº̣̀m ÷¹c÷8Ós5Ï脆ë„F?? “ce÷æÿ %HsÚR -‡¹‰£̀̀ÎQo4ñïwà3©ç±X/p©Ç„„Vhœ¢åp¤%#Đ¹¥Ư¯éL)%e†ƒƒw,\×¥¿¿Ÿ3·oäÜÛÙ¾n„­#UföÎtX×ï²i°ÈB; atL4£uª²$â÷€‘͇êf~B̉)Œ´úá2¿ư‘ß~ÄzĐ!0̀52nÀIôˆÈmùÛN₫…n§µ/s‘iđ#…kK#üéVkÍ@É¢äX̀¶&ê!Jƒ#̉±¨u"¦›&èăm—­Â¿d'ÓµÍñƒ½ằÏÎj—Ç"üĐ8„0̃*¨x«Öö9tµÔ),–äZNơw)<­”×¢cFaDÍy¤S }¤%²çÈX 9nÛ›RÁ¥`KÜbơkÖpÅ9§rÖ¶ ơWp,ÉtĂc¦1x‚-q,Á២0\vXßï2Ó ñB•eüÉr*«Êc >Ó§‘„ ,Ûô,₫ä>1‰‘ëúăû2f;pRjô@kÿÄü?ô½³DY©I@­R-Ú̀·Ăôâë/ZT\‹™fÀxܲẀ@¤Đ± †eV(­9¼à*cÙ\¹k¯óµoÎa®÷"Æè+ñ}^N,<î_Üpô€œÓ7₫V¤£Ÿ>8Ó2œöxÙ‰4«¤!ßT 6U×bºR q Í¢ô´¥%Z&̉^fßjÇJ6JkfZău¥4§máågn¤ÁC'øÖcăLOOỌ́¼0 a&1Œ–v˜kGHaÂj¥Ú2Û“T+ 9•g“å‘_Y¿Ö’–IØÙ¶êP-ºXsÿ®cQtÍ4áJ©ÈàĐ—y çíÚÁ®u,´}Ö<oQt !ªèX™ÁWù ŒÚPr>A¤áhÍGà³~ ÀPÙf²à‡uư.fÛæ»%~m,42ZuEÙµùửAŒ‘[ƒOnùqä'zÀ UûàÄÂîb©¸#ˆ”Đ©hæ;!ëÔ;!÷Ơ±„‘̣’2¹r2Új’ˆ:NºiH”o µé₫s¥E¤5í@ñÈxƒPkÖ®êçC×­fÁŸẫCó<:Å|½‰B-ˆ¤ƒ¤¯Za¤6oª¹sy_D^y²Đ¾X(R©”é£Í)k˜°Íl@…f``ˆ›×qåYÛÙ¼q\ÆæÛL6î~jRlôƒ%»ËèßiܤÈÿ1’/M̉iiœçé6Zk¶—(”"­™k‡$̓‰$Y¤µ̃>\âú›¾SÛ¿û‰fî#éE7 ë#Ÿ4è9€́"PBJçSơ7ưƯüúÿ´ÖÖ–BiÓs^­Z|áÎ}ô—Kœºv€µưEæZ¾ưЦ!H }ä<¹Èu₫Je°Ø:‰̀VÁ‹4{¦Ú„J14ĐǛ׮²N¥̃jóĐ¡î;0MŸƠe›₫‘AZ•a¸2‘k¶•ĐH!q‹EÊ¥ %K0:X¥opgo[Ç‹ÏÜ],S´‡f[LÖÚL×;lIƠ‘ٽ§3OÈŒ¡SÇiÔTüL üX{q}¿ËpµÈTĂcrz’S6Œâ…ʬ¦Ç… ư!…Đ¿ñ}ø æZï`Â|?¾yd„ “®'ảcH̀RFæ̃5O:nn¢sÓƒ4:>‘†J‘]‡9ï” ́)2Y÷«yhm(²V®̃-º.xȤ{̣ûƠ|éÏ„²ZAs¤€₫¢Ăª²Ă`Éæ¾Ă5j0Ñ·2H©ñT§ê4¸àÔÍ öW˜÷"jíñ—3·¥ˆ?{¶5ê2zágÿ‰Û_ị%æ>ˆ´¡=;›‡¬®ºÜu`†ûßÏC{øÊ‡_ù‰×đđxƒkáXÉeÍ[¸éû·×®}ÉÇŸ¢Éüû€½ÀSÀ$&˜TNô"ƒ„7Ûî~ào/½èüÔÚV1P´øîL×[̀·|ÂH3]k16]ăÖ‡P¬ôqåi£\xÊZF+.3­€é¦O¨”aóI‘„ túf[„Ø@¤ÉjKZAÅÆÑô#Jd¦åÓ ”!Æ<›¥ç ѕ٧̉Û?È¡¸Åˆƒ3mliÚ|“.Á´XaĐeôÉÔ`iùNkE2Ú̀8[ăª‹}F*ß{üÿ~×£<üÄ‚N‹NáB †*%n¸w/Wœ¹…ñº#%Ø:TDÁå×’½¿‡‰ZcOnmNâc=AcBÁđÆ®ỵ̈5W\ô¹¶/‚HStmÜw„…v@­åD‘̣±đD+àk üÛƯ»©ö÷sù©kÙµn€uCT¤™mû4|…#³àâ%1É® ́²<‚ñ +6(×’ m&ê>×JË€+Çu„qL‰O©8´|•¾²­Éoẉ«»ÈÑ‚£˜¹(M·–lË.ïq×¾)¾¾{/w?vT@Çhù¾â…J)“"z|7WŸ¿ƒ ̣(ÚWJ6 ¸ú7}wáÉûïlaŒÛÇ8€:†4OÆ èmNzLV¸ w¸̃.ơŸï…®¿ÿ¥0]oQï„q-ZÿÓ̃™GÙy—÷ưó{—»Ï¾j$ÆÚÆ#[–-Ù–6`ƒ±1!†HIƯ@Mh4d)¡§=´ MNÚ†@‚ n 4ä›­`ÀPdƒml#É–µXë́£Ùçî÷¾ë¯ü̃÷̃wF#K²eÇçè~Ïyuï\ÍÜ÷.ï³?Ï÷Q–]×5̀ î7 ¦j|ɤS öµsí†N6ö¶a Ÿñ¬EÅñˆëZÍm®…+ccQ³¡x¾Jz^(c{²Vv|¹!#ÿÖ_“"èØÜ‘âØ\ ]Ó ́º—µ{µ×(¡Æh́ùÇ—X®O:¦±®5Ì4™_äÑ#c91̀øÜnµBƠ“Tª–몕äWk¥ơ¹·¤t¶¤ùëü:‡æmâC=)º̉1Z»zäægÂx¿̀ăÀ0*˜Pà²T  I0‹'̉ £Ç>wƠ®=_t|ƒ|́Eö6˜º˜}®ïc Ͷ‹(ƒ|Åa!WdÿÉ)̉q®nn¿ª—m½-XË|É!WuÏ¡ ÂR˜:[kRg)ØBTS ¯@áJ¥(Ă©˜Àơ|̣–KK `EH ïC­?ß Ö˜W\LŒ+ă$âOáÓ{G˜™&W,Rµl*¶KƠrTCT0Xä…s¬lN¢Ö†üàGyóîíd+]éë7lŒåægÂ.¿ J d%T`™ú0Đe'üĐP+á®mU§S¶ÿçL\—eÛ3Ù†&ˆé©I&?2Ư§T¿Àº#(aBÈ »Pgxb˜i°±¯‹Wtsë–NæK*gP²½‰¦†÷A“KGÚäèL¹6đJy rÙ}ü;™³Ø̉™$WQDáZrO*Z4ÇSÉ˶´IkÂÄÔæo1>6Œïù”-ÅPµåăĂ~8à³üM†›‰4 ]ơHGNóÁ»n`¶¨áù’©œ%?đ[ïkûđ¾'QB^B ư*(¢B‚Ë-¸¡Î†x›:’Ơ¹¢-tMpƠ†>éQ¶œ`¯ú÷=!·Pf̣}|„/p„åz”…À´ÔÖœ˜©‘-[™âÿ7WrèmñÜT®æ$®mñÔéY>4V©iXRn  豺¿´Ÿ¨@ ˜=]”,—û÷îgvf¥b…eG¬¼«¨Ñ|5-}‰uNV†eQ=ȉa„ËE54$v¼™»ẉö[®#oKÍ1:³„&à?₫êNf‹6£KU| Ûz›x÷¿ùÍ}ă+GPơ₫“¨ÚÿJ)”¹̀‰A!ÀÙ=;:÷ÛÛ ŒÅËÎơ-œ/Qr<^dïñy2I“×mZĂï¼qûÆó<úüĂg([.çc{¾iư@ȺWP'₫PĐ<[TmAYwˆ›Ç£Tµ°=Éçü1²’§jÙJ€.ær•Ës[3đB€aè¤q®dóĐvN -U(V́ZL¯ˆOü³Øj=„̀ÇA#‘†IzÀ`Đ̃ÑÁîíW²së:®ëïà_ă¾ö8q·D&ảÑ”äM;·¢k‚óebº†ëKZă+3Ôi¿lê5ÿĐơ¿l… `Uü₫[o8s÷ôâߥRé”,WÆ M¬iMrz®BŸ–ị́đÑY¾spÁ&î¸z-{¶P(ùÖI†Ï̀Qª(ÂN+˜÷w—å êÖÏW…q<ÀơTă@Q’mëN25:ŒDP±l\ß[¡jưz„+₫+Ï"„ f¤S ̉că¼ưö›¹¯P¡T©R®88¾ªƠ«̀}ôïêËD*×¾ÓÔÑ8ÂdëúnîÚ³ƒ+6P®Ú;Ăßüđ¹́ɸ‰àkễÑt̃0ÔÇđbEí.”Đ–ÔåCÿïÑ¥o;¬N^ö‚¢¡Vn˜æxÖúÖíÍ(YÈV]®_ß̀d¶Œëéø2´l75Æ–J ϑַ§¸óơtƯ²•\±̀ÏMñÈóÓ¤= ÇWa‚í©­¿/#Ê đµ¤b¼©…ö£KŸlƠ¡RUûBÔ\h"]†—ËCåç0 µäóØtɲQËà»2 C &!k4`P EuE1f:¦®cŸ²o²mÓZn»áj®ß̉Ç\Ñå»ûNqÿS{)W*µ}Œjß ́B¤Lƒ-ư}$M±¥*1]íaܾ¦I¼é†ß8E}̉OÜơ• `x®#_åL,N꺾Ùơ`C{’₫ö£ó%åx¾²ê[+‚©À3¹2>«è¨›’qîZÇ{^³•gÆùÁÁIƧ¦IÇ Dđq<¿6óïûDÓ4„PɵÜÔ0Çuk5q8Û|IäË̉ Wü´̀ ÀĂq]d>GS\CÓƠƵ)H A„®½¦×cù˜a k …ÁÆ-[xëơ›yóu›ùùÑ ¾s`”û;Œë×—$Û ¤Ẁ`ô87iNŹ}Û;S ;&e{Êà;?úIvvr´J]Ô•@H₫qÙ+†87R ùÊĂzÚ6/•N-Vxûö^ –ÇéùÏNæX,ÙX®ăI?LúQó— ‹óŸÄ“’¾–ïºiC½×̣øñ3<|hÙ…,¶«H?·Î¨k¦&غ¦•Ç<…¤¾}gY ¿Âµ>×ỚËóï¼DĂ€ÀgQ=üv…¡Ÿ¤i`ª²áûZ@ú©ƠˆB„ĐH'b\=4È]7^IWg'sK9~xà_üѦ†ïm¾¬W4AÊPåÓ„i›¬éêàn†Ö¶³¾-ÁcĂIHJĦ oưàïrv«TTø ¡^Úî,ÿwÀ!®i䪒ª;çƯ;û(T=NÏ—99Wb2WÁÖb9¡kO`™…`¦PáÁư“¸¶ve¸çæAâñGÇfxfx–ăÓY„çàí´ºđéîhçàè¼ruĂ“H­̃p°̀9!ÿÅï^ V6EO£i:ĐÈ$ :¶DSG7;´ 4|¤ĐÉ4·pơ–̃~ăfz{{yôđ÷?u±™§1¤‹+ÀrüÚ9Tö_ |\$SIÖ´7³să®ÛØCÊd+¦®qb®BÂĐd[Êà§?Ù›>y¼D}È+\îhÄÿ `uÔ2Ägæjinº¡êJ‘¯ºtgbLl¦r6HØƠßÂuMø¾dßxĂÓreµºÛơ”B_@¢k‚á…"'æ !́nâm7n¥«)Î3ăY<:Æt¶€î»lîLa:y’ñ®ëazíÊ ™Îb#Z —àrÂùÈ©”§3M̉©ùéQ¶lXDZâ"sù2MƯ¼ăµÛÙse?9Ûçù‰yî{äă O“Đ}¤H_bKµ1i¥Đ' ©́ÜØĂÖơ½\?ĐAK̉dd±̀\¡JLSå¾f“‘E5•(AĺLÉwüÑGG©Ïÿ;Ô'£óÿ—uPˆ†8¡§ëÚ'₫́Ï?₫åÏüŦ²Ujd5ij$ ”©1‘­’­(£reO†× ´2[t8:]àÈLËvq|$₫”gàA#ɹÇç %]Í)̃¹çJ6u&ùÙ‰9 ’­ø‰VÜ…á{—F˜}·°1ç/.¨ i˜©ƒë:¹~ưk¹m×Ă‹U¾¿ïÿíS©TTíФÄrỔhDÜ4H¥¿Më{Ù½¥7 văú’Ù‚ÍéÅ ]i—+Ú“LæªTŸ¾æ#KUL]e₫›?{ü…çŸy:´₫ơà"˧ÿXè\ˆNv̀**._"t Ö¶$ÈVǸWĐ…â¼×ÊÏô%¦.XÓ£3ăôB…#ÓFJ”l¯æ8µƯxơé¹°9H"ØÔ•á7w¯ă‡Ï/àK°=Yăx©òĐ½-‰‹ë'8ÇsitMĐ–Đñ=‡oïă‘C#à”-˜P ¦‡¥¦AÜĐI'L:;Úx㶵ܰy &sg̣DU×–¯ÛØ$iªĂ₫ñ<º¦hÀ÷ ´²ơºƯÏP#ÀjøgƠùw:8¢M@áÀe‹†pn„Í#¥Gê³·¾nÏÇ–JÔ„ûÆ–Đ¥Ç@g Ccx¡BÙơ0ƒá€ÉœÍø’EÂÔ¸i •Û;™-Xübt‰É¬…e»¸ëMHNÑàÔ\‘lƠç«ßú¥|–|©íº‘²œ \Ÿ}±jAE²©-đ¢­¦ b¦AS2Λ÷́BO5³ÿùS×ÅöÀó½ZÄ4ôĐÇtA"‘dSO+7 öqU7­ ñl…c3–§:ÿ‚̣a˜d͘:)\ÏăL¶J,f*éơa}k\~ïÇ{s'êóÿË'³Áư0,hx4À¹æ̣=Àÿî÷úáo¸ùc®/Ek̉äÄÄ,Ï>CÙléëd×]léëße<[Åö¥ñƠ®/™̀Yø̉"ihܵ­œ˜/slºÀx¶‚„ạ$†ÇflXǾƒ,ª®ª… {êú½h7NÔ[oë½đóÔO„£@“ t•ëÈtộôđ –«€`ûFÂ0ˆKpm'×ĺăº₫v¦ÆlÑfd¡LƠơ0t ÀĐp=IÁñiKêlêLQ²}NMÍñ…Ç~ÉÄô,™¦>úkoÂr}’¦Îú¶¤Øỡ÷/×cùĐg+€ËỤ́‡h(€s#̀[÷ưƠŸùưđg™¶[t yp"'æ ÊU‡…lư'FÉÄMÖơqëĐv÷·3‘³˜̀VÑ4©)@Û—œ˜/#€¦¸Î›‡ºhMD]׈†™`c_»·®åơ[:q}Ét̃âØlOÊ©¡Ïåx¤L+:’d’1~yl”ÿ₫ĐÏ™>C¡TÆơ<µG°X¡M­“Û|óçæ¦Æ,ế?!ơ×ơà04¸lçÿW¢¡^>à¡¥GÇÆ¿~SoÏ-)S‹ù<¥ªC¾¢zóM]'gX,‡9zj=‘â-×^ÁÎ=4Å…W¡ê"40‚ºvÉö)XĂ‹UZ“ﺶ€S e~1²„íxŒe-îܶ¦d„FÅ2kKB¢e„9…—«uM#7I5µ2e™d’&abè:­Í-Üzu?»ÚI肉l•}ăyª$Đ¢Bl¿*o²®5AOSŒ½‡Çùỗ§85<‚U­P±Ê–ăxøH̉ñ1^ÂĐ…èHqÛ‡?4¼¬Ơ¬³­ÿe/üĐPçƒxRúƠ·Ư¶ç™‚ơÙSE (jbÍơP„”,—¼¡‘(Û<đóçøö‡hmkçÖmëØ5ĐA[:ÁÈb%Ø6¬ø MP´<–Êe•LK¼ÿ¦ơ,–LæÙØ oíZS$oymº n(u×óIÇt6v$Ñuƒ'Çùê“#RåQ<aæ˜:÷_‘Fü¿ p~h¨ưq ă#ŸøÔ;̃s÷[î¹jÛà¶_œ–÷?=BqqN8Yµ]a¹®«€Z/|ÜĐIÄt’¦I*n̉ƠƯÅ]Û×±½¿ƒ|Åf"găù’زmCÊÊ›º =ẻ1_ VÊ.‚¥²ó¢úÔà ̀—lrUWơïU _ 8b¹ ¹¿-¡ëL,æù̃/p̣Ä å2•ª¥hÁ²ÏóUu#øÜLC'3IÆM™4uÑÙ7À­×m‘¯½v›đJKÎođ÷Æ~ú͘C uåîŸFP `˜ ƒ4 ¡Îp‚,…Ú+߬_?´óÚ÷üë{nùЇ>¸Gh:O“{¥ªCƠq°lËóq]¯Îb«©–׸i(e30u=W_Áî-kék‰s&o“¯ªkÔĐF ™í)“˜!89W!êb¾,đâ<[óǺ°¶9íùd«.È€üS*Đ˜!hMÆèm2y~ºÈ:ÄÑă') ”m—eSu\Ç f wKSCC‰˜A4È×’ô*Ơú§\ø‡¾›;úä̃,ơÜUØëÖü³À4Êêp¶ơoÄÿ+ĐP†pœ4̣ÖÀ”GĐ ÄÍmM›7mjº÷óŸÛ|ăîZ9<+Ÿ8:,†§¥ï{¢b95A/ ËBY½X  1ƒ˜©³¦­‰›·m`˺.z̉º®³¬'¿¤ÂŒ2[–»̀ƒ8ß…–»̉&–+±…Á±Ñ)99Á¾ĂÇÉe—°—²]wïƯ¥™bûш›&ɘI¤ۻ¹fÓ:ù¾;ns 9ûûÿ÷Áů~é‹sÇ,QŸâ 3øÑŸ°ëo˜¢®Î ¬û7J+ĐP†h2° èF)u(Đ´,A) ăÿå/7¿÷w¶½fÇPæk—?;v»\Uǧ¬·̣|7H̃ia²KWåµLÜ$ˆñ₫»^Ă×ø‹ *+~‰f€±gº³ÓŒ 8wº!ŒÏ ̉™ ï¼í₫̣+ß&W,‘/U(Uª¶­„̃ơƒ•ƯÔˆ@b¦¡âú˜A,‘”WlØ ~ư= ö·pßß}mîÈ₫́ûߌ²ùD…̃§>Ơ.ø,£¬ÿJŒ£sÔË ë¿  à¡QŸhEYư^THĐ ´¡B„D)‚ ¥{?ïg~å-wtç=ñø¡Ọ́Đđ¤(W,i9¨º.–ă»dĐ¯¯“$ă&¿ư¶×ññư!Ö̉åj†Y†•)ü‹¹̀h†®khhjØ!(ñƒ gÿ‰PăÉ©D‚¦¦4_ùÂgy×Ç?ă¸+¶£–– @ )¼ ƒDÜ$nꤒ zzûä»oƯ%vm]/÷₫ô§ù¿ÿú7¼ïs3(E¾‹•ă¼á$_(ø–—üæQ!À4Jø³Ô‡±ÿ*hô\8ÂÖà*ªÔ6á‡îg¥‚#RÉ̉ôˆưï|[o₫Wÿ¶ÿCï¿§ï_̃s{ëÑ‘i±ïôypxVø®…åúT/pU+¯ÚÊu^XXÄÊ.Q¬”ñ\wE¸”a'Ÿ@YƯ­ư†<·H„P DhBíơ ÿOÔßxtæ@eưSÉ$…J•S(V<×Åq•r›1S)°˜.ˆ¥2lëï‘wÜ|½XÓÑ́;\úâ_|bö¶ÿưÅ…ÚKQÂuïCkzVƒ£‚Jê•Pî}>øüQaÀbđX\欿çCC\8BêuqU¨oœib¹ÈG¨ ?úú—F~ôơ/µ­ßỤ̈/î¾»ăî»̃Ôöï>tg×Çä·Œ‰|vQú˜"ܪ£ ”pđ́*ïá{₫r^À€9Ç÷Ahü³[‚Ïß"́{ "Ó₫R¢i" )Á$_ä/<_‘”Ø‹¶çå[yIDATnÄ0ƒ–^S×HÆ tÓdưú üÚ믕۷m‡÷(}̣ÿiæ»ÜŸÅ­:ÔùùjsÔăú¨¥GzKÔG{ ÁÏá–ß|ä~‘å–¿¡Î†¸xø¨ S¢.̉pălå₫g¨ ¨Âûéàw’Kă'í/ßûÉÜ—ïư¤Ñ½¶?ó[ÿ₫ÖüÑï₫̃†¤đÄcGÇùá¾ă2® ¡é‚ÍM>™¸FŒ º®ă­ V –̀“ơaé¿° œûe$ÄP@Ơ蔈ÇIÄLœÂ­­ÍÄ} ß÷03íÜưúëå]7Ó#ăö—îûû¹Û₫ç'¦ñ́è Ô‰9<ê.~”À#tñCA/FnĂù₫P)T‚£J₫»áöŸ pqå$L(…mh¡âÔA¨ Bá¡W³“cƠ?ưăäÿô?rlđú[:ï½÷̃­ŸzßÓ'æK˜»:VÊy:. ÿƠ52]£Ơ~BZ̃_}êÓg¾úÍïå'́˳¼V¿²lÍà‡Yü0®/²\đ£Ö>ü½¨••H4oĐú DC¼tˆÈmTÁ$Ë•ÁJE Âr¢Úée&S¸n/ë‘ó]È….Ön{SäẺ,ÖúÂι©qÇ.,†É¶đu…‚º÷+“y¡Ëø0¡µ₫¡ĐŸË̉GÏ á¿(4À¥… ₫™F½å„Ê ̣4«+‚Đ[HGåUD¹íC…s)^ë¥@´Éfµ ~4™&̣¢Zû¨{ºøvä¹¢!DCè_" àåÅj!‚ÁÙ!B4yạ0Ặ̃“åJàb¾Ă¨·r©¿{9V³öÑ ~è̃‡Gó‡î}Tè½ÈÑØçw‰ÑP¯ DäĐY=_p¾!'0¹¸%+Ă±â¸ºâ¡đ‡ ½¨;¿̣½¨Đ‡|}¡À‡Gx.! à•G(tQ¯@G)‚JÀCeYq„¹Ë×\]èy£¡Ă¥̃$̀±©gó£åºđ-}˜̀³9[è£E/ àŸ+]ñĐ3‡Qe«…Ñç{¡óEϳ̉x)ˆÆáaYte?½-}TèĂ¢¤׿¢h(€W¢º²†áaRO^¨¯|₫•÷_*¢™ø•ñ˜½–íVZûđ9x…ÑP¯>D…3ª œÁ‹Ưp­Nˆ½TD­v´̃­ÓG[}–₫U‚†xơbµ₫‚h ÿbÜ÷Wª ííoÄô¯b4À««Yë—*À/×÷î•®}Cđh h h h ₫™đÿ$leçÖĐïIEND®B`‚cutechess-20111114+0.4.2+0.0.1/projects/gui/res/icons/cutechess_mac.icns0000664000175000017500000072126311657223322024430 0ustar oliverolivericns¢³TOC His32÷s8mkil32Xl8mkit329dt8mk@ic08Īic09Wâis32÷‚&€&ˆ((&†&(;;h&… (;B;;_&ƒ(;B€;_&ƒ (;J&;;ƒ&;} &€ƒ&;}&&…;¦&f„ÿ;¦&I†ô;¦&ÿ„Í„âÔ„&(}¦,„†„&(;}¦},„†‚G€2Gˆ22cc2G†G2ctt•2G… 2ct|tt2G2ƒ2ct|€t2Gƒ 2ctG22tt2ƒG2t 2G€2ƒG2t 2GG22…2tÅG2¤„ÿ2tÅG2K†÷2tÅG22ÿ„æ„2àë„2Gc ÅR22„†2„2Gct Å R2„†2‚a€JaˆJJ““Ja†aJ“  ¶Ja… J“ ©  ±JaJƒJ“ ©€ ±Jaƒ J“ §aJJ  JƒaJ ¸J a€JƒaJ ¸JaaJJ…J ÚaJ£„ÿJ ÚaJL†úJ ÚaJJÿ„̣„JƯú„Ja“¸ÚnJJ„†J„Ja“ ¸Ú¸nJ„†Js8mkÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿil32X‰Èƒ²×́—Î×89Á¿˜‘j|Œwÿ•rl*C=ƒ¹ÆÇqP|kƆ븃YMr—]&Yj›Đ çµq]5AƒÓg ́Ăhk31~„jt'åĐh}15U†ƒ” ¤á\LK¡ D”âbg[<9‚z—”êfhZ:8[„¿” ̣hg\:8]VÎg“ ÷‰y\<:b\½_ ệöwsfC@nD•đĐđÉơñú£uM$#YaĂöçâđ́çp¡Ô·µ·Ó­qź́¥âëïÔ§BsªßíåIà™{¥Ô‚ïâ¬uO˱ڹ•B7753gey¦·¾§ÏÑ•ŒŒ‹®Â´™? <[“‚hfjk”]:‘.&€*ª‰́Éâôï—ñơŸïă˜ÛÊÅʵ¡ÿ•ĐÏ„“ŒǛ” đåÈ©‰|mÜÁ” ơÏ|“mok¼ă½“ ôŘ{ont¶̃»’ öŸ·‡mr‡liº̃¾÷á—°¥‘‹jnmj¿Ư³ÿôÖ¤®©ºkmnmqÏëôúôɰ—©­áÑwll˜™´ñ,Œô˧VVœÜçê“t§™â”ổ¯ogŒÀl'b–™¿ë đĐ xOY¼µ¬ñp ñÚ˜‹LK µwz)íă—¤JNo·¤” ¥ï©µsgdÄÈA”đ‘”yXUŸ¬¡”ô“•xVTy¬Ô” ú••wVT}wçk“ ü¯¢zXU‚|Đd ơùü¤ }WUŒh°÷Ơ÷ƯúùÿÄ¢f85ỷüôæ÷ọ̈›¿ăĂÁÁÛÁ–÷÷°́ơùæÄœ""NÁí÷öK༥ÅåúÿñĂ“rÜ´́Ú½´[QPNK…‰ÄÅĐÅăꯀ©§ÈÚȳB At¶tsww­vG‘2*€. ªl8mkœ£m ÿ₫ÿÿ–ÿÿÿóûÿÿÿ₫ÿ¤Oÿÿÿÿÿÿÿ‚₫ÿÿÿÿÿÿÿcĐÿÿÿÿÿÿÿ₫ÿWÿÿÿÿÿÿÿÿÿ₫ÿTÿÿÿÿÿÿÿÿÿÿ₫ÿO0ÿÿÿÿÿÿÿÿÿÿÿ₫ÿÁ?:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¥Aÿÿÿÿÿÿÿÿÿ₫ÿÿÿíZHÿÿÿÿÿÿ̃ Íó₫ÿÿ«?ÿÿÿÿÿÿû 0ÿÿä@2ÿÿÿÿÿÿÿy`Ăz(ÿÿÿÿÿÿ₫à ÿÿÿÿÿÿÿÿIÿÿÿÿÿÿÿÿ²Øÿÿÿÿÿÿÿú´ÿÿÿÿÿÿÿÿl¤ÿÿÿÿÿÿÿÿª€ÿÿÿÿÿÿÿÿ₫ÿK«ÿÿÿÿÿÿÿÿÿÿ₫ÿ{¬ÿÿÿÿÿÿÿÿÿÿÿÿÿÿo“ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ»:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿsÿÿÿÿÿÿÿÿÿÿÿÿ₫úP¾ÿ₫ÿÿÿÿÿÿÿÿÿÿϨéÿÿÿÿÿÿÿùä¹]!h´¾ÁÄĹ€<  it329dÿÿÿÿ©ØưÍÓüÏôßơ®ó ºÊMo­ÍËÇØÚăÆñÏI78AL€·×ÍÊÓßߨ]ë›>€2 5:K‘×ÔÚÙÛîăƠë ̃X512125Iĵ€¼ººÏë °A32122<“·¸º€¹¾Œëæu>65436Lȶ¹¹º¹¹Í́ Û“l^PC>I ¯¸€¹ºÊKë¼­vœ«¦ƠÄÛƯƠÎËÍ æƯwb`aabg³?<>Iv²ƯÄÓÚÍÇÂÓå½g]ayo.&&*5Œ]®|{z{}¶âÿé”b^]]_a¨2&$$,mD,Z•wtsu{Åẩk_]^^b”W+$$&/' )r’vtsu}¿ß^¸e]^]_`—2%$$,†>!+ˆvssv€Ëà×ñ~a]^^bŸF($$&1•( ,›yusswˆ®àÆi_]]`m‹/€$,w4!€  /°uttsx”­Ư¨¤d€^ b9&$$&-„' "5ªrttsy™‹Ưæu`]]a|x,€$+z2  $E®sttsy­mÜƯp`]^`§1%$$&/|&‚ &O¤utstz¬YÚƯ¨f^bX+€$,u0 ‚(c“w€v}¾!ØÎØ̃rbb¡2€$&/ƒ&„+~“‚ˆ‡•ÈÖÿềÇ¿nŸ?(€$.‚1 €‚€ $GÈȱ°¯ª¬ÎÖá̀ÎÚ“/€$'9„'‡ &ˆ7•‰„ƒ‹ÉƠÚÏÏÈäH-€$.’1 ‚'q<&/–„€~‰ÉÓ,̃ÏÏÆ³I.&'8‘'€#Jf& -©€~‰ÆÔÍÚÑÎÔrB„l/1‡) … ,ˆ'!-­ƒ€~Œ»Ñ ïÏÑÍÏH65345:A 0&&Œ&‡$=º{~~‚˜¼ỄéÆ:€25P€:434349A›IpJ#%D¦|€€‚ˆÀÉÚàïW72127xX84434348@•5!‰&M³¤¹ÅÏߨÆc=Ä ÛƠä‚?633;”?5‚4 34;z¶/"€…/‰ÁăÈÆËÏÍ̉àáßÄ ̃ỞqR<5=”>5€4 5344:‡‘±=&ˆ :HP“¿ÛÇÍÑÑ̀ÑƯê¼Á éÔÎI@ˆ@F”=45ƒ4 =¡„Œƒ·[+†'‰A55;C\ ÎăßÛƠÍÓuÁæƠÎB5;U¤‹o>54454 @†‰‡ª…-#€ƒ!<:€2 37F‹¹¥¤¤¥­Â"áƠÎB337A§œp::654345A§‡‰‰‘©6&‚(–:41€25Fº Ÿ¡ËÁnßƠÍC3229}5J‰…E<8€5 A¨ˆ‰‰ˆ†¹X)‚€#Lo9‚2<’¥ Ÿ ªpÂpà×ËE3127t3+xW<:7D®ˆˆ…¦‚-"€(‹:412216IÀ Ÿ¡ÆĂ#á×̀E4216p8 `‡v>MºŒ‰ˆˆ‰‰’¯<&‚#_d7€2 12?©œ Ÿ ¸DĂ Ûä×̀F4225hV€ 7…—³‰‹‰ˆ‹‚¶W)'’;31€27V½Ÿ€ ´Ä+Éă×̀F4225ZW!A¿§­µ¡‹Œ‹‰†¦."%fS6€2 13A± Ÿ¡È Ä ¼ß×̀E3125PY€':‘UTZwÈ·¿œ“¥7&!,›;312218b¸Ÿ  £Å Ẫ×̀F4225E_€>yLIJM[±Sˆ«Á®”‹·U4vG5€2 14A™ Ÿ¡Í Å ¹ïÙ̀F4225Cf„CsNMPR[µƒ.j“¸å‘<31212:u­€ §pÆ ´Ûæ̉M<:9:Co€  L{r’½†]’@21225DÆ› Ÿ¡ÈÇƠàÓăœ…™t®]ap‚firh¹ZMMN[‰ˆR6€2=‹ ´FÇ£àỠT?>=Hc©<%!€&›PH€EP‰ £A425LÊŸ  °È ‡̃ƠæO5445>‰#€ tWHDEDIqYˆ os:3?™› Ÿ¡¾.Èd̃Ơß]6€27m;&LER‰¬I:WÀŸ€ œÊ ßƠ×x71224Awƒ ‡KFDEEL/ˆ #—P¨¡ ¬̉Êà×χ:€23:‚ ƒ C~JEEDGU“‰£½¿Ë˜XËç×ÊŸ;29†%€  ‹LFDEEO¡¼ƒ-Ïá×̀£>25VZd^HDEDHa}̃Ư×α@32133:‚€#–LEQ§̃ ØƠÑ¿A32133:‡ € €LGDEDJyQƯØƠÓÇD31€27q9ƒ 4ˆKEEDFT›ƯëÙÔƯF412214@v€ L€EDL™Ü ƠåßÙO521123:† …\gH€DHYÜîÔáô`>953329‡#‚"L€EHW¡ÜÓÙÙ̃±ƒJ=;78R_€xRKLN[¹mÛÀàÙÚy@H†‰‘nDDŒ$€6™f˜–Q^ÍÜ!çÙÔ„50589W‹“¸xulchm„ŒkioÑ‘SHEBTæ ÛÛØÑ‹5€. 016@†/!!  ! *—”J?>?NÀ~Ûá×Ñ“7.--./.5z&€€  }ˆSB>?L­»ÛÚƠΟ:.-..-.5y%€j6“F?>IªÈ7ÚßÔΰ:.--4y%l,fbC?F•°ŸÚÚ×ѯ<€.-/.4w+ s%(›E@C}¾ÍÚ¾Ử¸?/..-/.4w-" ?‚EBgÊÅLÙ#ŸáÔÉ?/..-/.4w, "&‡JCVdz«Ù#ßƠÊA/..-/.3w/ t!1–HPÆ·ÚÚ#ăƠÑE0/--/.3|9"f!$p[R·´¼€ÙßÔƯG0/--/.3{9€%h )“S¯±·ÀÙ$áÔêH0-.-..3|9*j![v­­¸Ñ'Øä̃äP1.-2m<7o'—“¶¸ÓjØ$áêá]2..-..2f=9g=¼ÇÍÔ[Ø éÚöw;30/..2f>…ñç€ăåƠ½çäëŵáïếëßăêßä́ïסjIA:66XK…HB!(.>o«öêäßßæº¼ßæǽ¼ĂÎîøñïêî̃ỨûçÚƯƯÙæ̃·ZIcQ…NM17jÆä̃ØÛƯăøơ¾º¼áëîñđØÁóä€ßàçáÙÈ_·ÙæØÛƯÚÛ́ÍÀ›y€v‚rv™®Àèß×ÚÚ×à当c¨¯¼ÓßÙÚÙßé̃À¸äăëà̃îÔ®>5;Df¡ÄîÛÙƯÛîÙØ€×„ÛîÙÛØÚ́ǘg:,%(z³¿çÙ€ÚÙéÑ.ÀàÙî̃àé̃6--/28@K²ØôÜ̃àƒêëíôƠ«x=.& TÁäØÚÛÚÙ̃̉·ª¿áƯßéà̃ør?30€-.05?bS(&*77‚8>™4(!€%EăßÚÚÛÚØæ¹¹×¿4àÚƯî̃àà̃ëæÍ¨pD<40.--2]2 d# &,D{´ë娀Ú对¶ÍÀÚÛƯäå̃́ë×ÑÍÆÓѳ„I>614v* ‰ V&")2a—ÂÔÅÄËƠçäÙØß¸¸ÍbÁåÛÚñêÍÎÑÑ̉̉ÑÎÇË̃½XF~!ƒ`<0C}¬ÑÍ¿ÇË€Í̀ËÏà¶́ ÉÙÔ²¶ÙÎÇÎÑ€̉ÑÏÈÊÙËÈrg‰fgªÄƠÂÂỀ̀ÍÍ̀ËÅÀƯ½™·®¹̉oÂTåád?AL„¶Ó̉ÆÎÑÑ€̉Ñ̀Ư¾¼‰º¼À̃ÈË€Í̀̀ÊÀÈÔ³†E1-RÀ¸óÄÛÈG4359AJuªÔƠÆÍÑ̉̉æÈàÏÎÍËÇ¿̉Ï¡q;-&!0·ÔÄë·O>843348@Ip±Íׯ×̉„ÇÄĂàÄĂÓ˜Y3+$ &3•ơ¼Ă‰ßΨtB>842348?Gi§Ú„Á»‡º»Ó¾‰G/)"!&(<}”Ë×ß Ăăáe|ªqA=742249C‰+…%…&%(Eq+!!&&O}†z;Pæ¶ÓÄßƠ¾rjgb„¥¢h@=745N\€‡!m$"&)P‡…e;:O‹¼ÛÂÄÓáó€ñ„ïêƒåèîàȼ¼̉½†F,%"%,R«HÉ‚ zB:69@W˜ÇƠÄ̃³µµ„³¶¹‚ºÁÓÀÓ·‹D.&"%*IŒOĐ /ƒ¥[?85:@f½£•†”–œ Ÿ̀ˆH-&!$*n¬¦»ÄĂĂÜ †b¸v€mln|ßÅÇÇÉÜÇÊíæï¿¸³»ª¡»zƒœ™”’­Ö®”‹•‘ˆ ‡†plmlu²ÉÉÇÉÖGDzíçí†vuu‚”¾bKB==<€=F¾Œ…€„Œ¿‰ Ăxnlo‚áÇÇÉÉÂÈ ¢́çñ…onnou²B865 45=‘†ƒ„ƒ‡¤^ˆ v¡slv¼ÅÉÇÊß/È́çíp€lpŸ]855457F¸ˆ„·‰Ás‹ƯÇ€É¥Ê ́çè£qlmlnz‘<44ƒ5>¦‡€„ƒˆ¹2ˆ *½„ÈÅÊÉÑèÊíçă¯sl€mr¨>54‚548b¯‡„¥‰«µÚßâ¤X Ë đèá¾tlmmlr±F6€545545?²‰„‹ÅÅ‹.ÏíèâÄu€mlo‹y:54454554<€™†ƒ„ƒ…™ƒ̃ëèằw‚mr¤=5454€546D¾„ŒÅ̃èçåØx‚ms®?‚54€5 =…ƒ„ƒ‡«UƯççæß{mlp¢Z754ƒ5 8V·‰„„ƒ…±Ựêçë}m lnx“<454545?°‡„ÂÜ æđíë„nllmlmr§>…5 4:yŸ†ƒƒ„…’œÜđçïúvqnmmlrµD6544‚5 6A¸ˆƒ„„†‘ĂÜ!àêếϹ­utqq‰|:554455455>–‡ˆ•¿ÖqÛÔíêê£u~­µ¹zz§D<€;<=<<;=TÀ¿¾·Œ•ÏÜ!ñêç©njmoq‹²»Ơ”¡•““Ÿ““™á¸Œ‚‹ơ Ûëêå°ngghhjnt°UDDCBA€B DCK´¼„||}‡Ú„Û́èå¸ogffghgmªL=<<ƒ; jrJHLLPnœ²́ÛâEÖÿúëí­{«»¹§€—qF€CDDCCBEtvV‚¢¡ZfáÚßÔƠẹ̀ö́́©rortt…¯Ê®’‚‘±ºœjPOMKJ]ëÚàôđdÑàị́ïöí́®rllmmou˜_3„0/2lrOIG€F H[ïÚáôïồνôöơơùí́¯rlmlmlo”[-…).glHGFEFEG[ïÛá÷ôñơàË̉́öï€đö́¯r€lmlo”[-)ƒ*).gkHEEDDFG[ïỤ́ïđñđùê Éæïûññ€đ ôí´slmmllob-)ƒ*)-gkHEFH]í́ïôßöíNÉáơôöëöïđïïơ¸{qnmlloh.)ƒ*).gkH€FGIOeúñïđïđçØñđô¥ÅƠíợôôíị̈íđôöçÀ™xsopj.…).flJHLRWg‘Ăụ́đí́đרíññơÅĂă¿ơú÷ọ̈ớëô₫ñêëëệ́Ñ´–p6…05nvYb¶Ụ̂íèëëïûúÚ××íôơ÷÷ß Áùđ€́íñíèܯĐẹ̈èë́êëơâ×°€‹‚…ˆ¬ÅƠơíèëëèị̈̉®‡¾ÑØǽëêêị́æÀÖđíôí́ôçÈsmqy”¿Üöëếëơ‚êƒ́ëơêëèëöܵ‹aSMPÔÚñêêëêệæ3Àíêớị́́²meegjot¯Îèû‚ṇ̃„÷ùúçĂ˜fUOHECCGzƯïç€ëêëåÖµ¿½ị́́́€í́́ûsjgfeefhls“g526>?‚@F¡ZQJF‚CFMkñ́êêëëèñ××ë¿íêëớíí́ôñáÄ›zqlhfeei”?€|KD€CDHNUkœÊôđêëêêïß×ÖÙÀâë́ïđ́ôôçåâßæåϪ}smij¢2‰kPEFKQZ…³ÚèƯÜáçñïèèí××âiÁđëêọ̈âăåææååăßáíÖ±‹z­-‰ldVjœÅæăÛßââăăâáåíơØÖỌ̈ÂÏêçαÑêăßăååææåăàáëàƯ„yˆxwx¤ÁØêÜÜáââăââáƯÛíƠ¶ËĐ׿rÂ]ñï•vz‚«Ñææßâååææååấ‰Ú€ØÜëà€âăâáàÜàçΤoZW|ƯÖöÄåƯ}nmnrw€¢ÉççƯâ€åñàáŒàíăăââßÚçă¾”dWQLJKYÑçẠ̈ĐƒurnmmnqwŸËâèßèåƯíƯƯçÚ´€]UPKIIJLP\³ùËæíầ¡{vpnlmnqv}˜Åç̉ƒÑ̉̉‡ÔăÔ§oZSMKIIJMPRh ¸ßẹ̀ Ăíï± °ÎŸzuqnllmr{¡JƒEˆDGb•ULJIIJMPQw¤¯¢rđƠæÄéæÙ¨£¢ŸµÊÅ™wupmo†z:5D—OIJNQS{©­–qpry§åÛnÄrṇ̃ï׸¥£¡Ÿ¶̀¼–wx¦Y9655€6…54556<¤VQWƒ©²”loqu‚®̉đÓæÆáèôđñêÔ³¥¢¡Ÿ·ÆÀÏZMKJ„KDDEDEEL¦™®¯†moqu‚´Ûñ́çăÛrÆ«íïèæÜƯíåѯ¤¢¡¡Ú…™˜„™Đ‚ooptƒ±ØñàרïôƠëÈèĐ‚ÈêâÜàíáÏ«¥½…T€PƒNPPQPPRY²xv„µÜíàרề q¸ÖlÈ׸vmr{©ÏëàÜáíâÆµplkkgde†dqÀ»ÚñàÙÛêΡfSMR–èÉRȸ|rmns‚°ÖëÜƯæïúùƒ÷ơƒ̣ôơïàØØçƠ¥nSMKNS{ÆQÉ‹½¨vpmnt‰»ƯèƯëÔƠƠ„ÔƠׂØÜæÛçÑ©lUOKNRq¨’RĐ 1”Ăsnmpu”Ơ·ˆ¬¶‚¸ »Ư¦oUNJLRe±œMÖ _¬¸‚qmqª/!! …!#‚% +SKLQc¡e Ú p»®|´(€ "}[\¡¬o à2’Ư‚ˆ‰ˆŒ»¬zí …  ÿÿÿÿÿÿ¨ÿÿÿÿ©ơưíñ₫̣úơûèó ăñ̀ªÀß̣ñđôôơæñô¨Ÿ¤ªÉăơñđ̣ơơƯ¥ë™Ơ¢€› Ÿ©Ïộôơơúöèë ù±›œœ›΅ë́í€́ñ'ëंœ¡Đë́ëïëúĂ¡œœªđëë́́ëëǻơϾ·­¨¢§Øèë́́ë́ơVëêæ̉ÖÛââăăị́ù÷ơñđâ! æöÑÊÉÉÊỀè”’ µƯñđùÿơåëáåë̀€É ÈÉÔµ†€„‹Ïë€ÚØÛë§âÿ÷ƯÊ€ÈÉÉà‰€€…»yŸă××Öרíâñ΀ÉÈÊߥ…~‰̀upx´ă××Ö×Úăß‚’êËÈÉÈÉỂˆ~~…ĂŒrnoxÂÜØ×Ö×ÛäàûúƠÊÈÉÈÊă˜ƒ~€ˆÎvoonpyÔØ×ÖÖØ̃Îàï̀ÉÉÈÊÏŇ~…¾ˆrnnonq|â××Öרâ¿ƯƯăâËÈÉÈÊà~~ˆÉuƒo s„âÖ××ÖØă¡Ư÷ÑÉÉÈÊƠ¸†€…½„qn‚ontêרëwÜơĐÉÈÉÉ߈€~~€ˆ¼un…o u—ç××ÖרçkÚơăËÉÊƯ¥„€†¼pn†ow§âØ€×Úç*ØđôöÑÊÊ׈€~~‹Ätn†o nox»áÛƯƯßáëÖÿùñđ́Ïă”ƒ€…Éqn†o nntíñêêèèḉÖ öññơÚɇ~‘Áu‡onnpuÎËàƯ€ÜßăƠơṇ̃đù›‡€†Ë‚qnˆou¼†sỳƯÜÜÛÜƯâÓ ªọ̣̈đáÛœ†€Èv‰os–®snpzÖÛ€ÜÛƯăÔíợñôÀ¥Đ·‡ˆË|qn†onq{ÊsnlmpyßÜÜÛÜÜßÜÑ÷ṇ̃ññ§ ¹̉˜¾uon…onouËyo€mlp}ßÛ€ÜÛàåĐ ÷ṇ̃ïߢ››Ÿªô–wˆou®”r€mlmmp|ßÜÜÛÜÜàƯÏöṇ̣̃ÄŸ››¤ÚÖvon„orˆ»tml‚mlpÜÚ€ÜÛàăÎợñöª››œ¥Ö¦Ï¡uononpuÔtnl‚mlmmp~åÚÜÛÜÜàà̀́ợïछœ›¹À¡¡Ă·vp‚ou¾„q€mlnmlmmlmq„åÚÜÜÛÜáæÊÿợ̣ñÈŸ€› Ñ¨¢·Èwqoonsœ©smlmlmlmllmr‰ëÚÜÜÛÜáà̀ öđñö®›œœ Ö¢€ ¡°Đ{soqÈtnlm nnmmlmmlmr‰êÚÜâÚËúñđæ¤œ¡Ö¢€ Ÿ¦ÜuuÎvol€m‚nmmlmlmms‰ëÚÛÛÜÜăÎÊ ơùđΠ›œ›®Ê¡ ¥Ø”³“r‚mƒnmmlm sŒåÚÛÜÜƯæÔÉ ơöü±›œ›Å´ƒŸ¤ÖÑ|p…mnmmlmllms“êàǽïñöêÛ”EÄ ơô÷Ê¡œœ Ơ¤„¡ÄíÂyqml€mlm‚n mmllmlnzÁåùđï€ṇ̃öợÄ ơố¿Ü® ¡Ö¢ƒ¡Ëàáàˆtnmlm‚nm lo†Ơ§­Đèöïṇ̃€ñơ÷ÔÁ ÷ố¨¤ĐÎ¥§Ơ¡ƒ ¡ƠƯàÜêŸwomlƒm€nl€mtȤ ¥µÖđööơôñơÁ ÷ố¥ °ƯÏ¿¢‚ ¢ØƯƯßƯë¿zqml€mlmnnm pˆÉ œ››œ§̀́æ½Âöố¥œ›Ÿ¢ÛÚĂ  ¤€Ưß̃Ưà܃t€m llmmnmmlmuÑ œ ›¨êååæåô Á ¼öôí¥œœ›ŸËu„¾Ï¨¡Ÿ¤ẵƯßỮßÜívo‚ml€mq”ÅŸ›œ¡Đ€æåê|»öộ¥œœ›ÆvVVg¨Ñµ  ¦çßƯßƯƯê¼xpml€mllnù œ›œœ›¬íååæåçĂ#Ä÷ộ¦››ÄxQOPUZ‘ÄȤ¬́àỮßß̃ß̃̃áÜ…sn‚mr¤»Ÿ›œ¢ÛăææåđKĂ Ô÷ôñ¦››»‚Q€NPSVt¸ÖëƯ€ßƯ ̃ßÜêœvommlnsÔ œ›Ÿ±íåææåÑÄƠ÷ôñ¦››¶†QMNMNNOQXwëáæëæßßà€ßƯƯê»ypmms­°››œ›œ¤áâ€æù$Ä Ưöộ¥œœ›±‰QM€N#MMNQm×¼»¾ËÜđăơæààßßâØƒtpxØ ›œœ››Ÿ¸í倿Šêơôñ¦››­–RNM€NMNQvѶµ¶·½̣X™Ị̂ïăßë}³ª››€œ¤êă€æ÷Åßúơñ¦œ››¬œSNNMM€NR~Ï€¸¹¿ë‚1r«èÿÄÖ¡‚œ ĂèåæåèxÆÔơ÷ô© ŸŸ ¬£XSTTSTUTV†ÑÊ×ßßỤ̈ † eÖ¢›œœ›¦ïă€æëÇĂ÷̣÷ØÔỞÉÂÄ›¥­®­¬¬°ÂêϾ€·¾–ˆ ®›œœ¡ÎåææåïGǺöô÷­¡¡¢®·Î}j]UTT€U]׸µ´²²¸×‰ ؤœ›ªñååæå̀ȵöôù¯€¡Đ[QO NOOV£½µ²´²µËaˆ zÄ œ¢Ơăææåô1È®öô÷·€›ÄvQONM NPa×·²´´²¸È‰ Ϩ ±ñåæåå¬ÉơôôŸ›€œ¦¤TNMƒNW»¶€´²¶Ú3ˆ .׬ƯăååëùÊơộËŸ›€œŸÄWNM‚NMRz̉µ´»±‰°Đïôñ­X Ë ÷̣ñÔ¡›œœ›ŸÑ_P€NMNNMOWϵ´·à‰Ë/ÏợñÛ¡›œœ›´SNMMNM€N T•õ²´²´Â‡̃ợñࢂœŸ»VNMNM€NMP]ض²€´¸Û̃ộ̣꤂œŸËXONM€N V´¸´²´²¶ÏXƯṇ̃ô列›ÅtQNMƒN Qqض´´²´¹ÁƯ÷ơôơ§ƒœ¥§TNNMNMNWȵ´¶ßÜ ñ÷öö­››œ›œŸ¿W…N MSȵ²²´´½¤Üôôöüµ¡Ÿœœ›ŸƠ^PNMM‚N PZÖ¶´²´µ¼ÛÜç€ơâÖɬ¡ Ÿ²’SNNMMNNMNNW¬¼€¶¾ÛësÛàöơơ§É̉Ö¿§¤»]UTSST€U SVkƯÅÜÛÔ·½ĐÜ!ùơôĂ™–˜œ°̀Ö訮­¬°±®­¬¯±¸ëƠ·°¯®¶₫ ÛơợË™””••–˜Îq_^^\\€] ^]dÆ×±¬¬­´́‡Ụ̂ôñÑ”€•””™̀hYXƒW VX^½¼¸­¬¬±åÚÛïôñÖ›”•”˜̀hWV€WVW [½zׯ¬¬±ƯơAÚ́ôñÛœ‚•”˜̀hWWUUVWUUWW[»r¤Â®¬¯×ê«Úåộá‚•”˜ÊlXWUUVWUUWW\ºmoׯ¬®ËíëÙÖọ̈å•”€•”˜ÊnYV€WVWWVW]·mkˆÑ¯­ÀñôNÙ®÷̣ê‚•”˜ÊnYV…W ^¶lgnű®¹ñê½ÙVọ̈đŸ‚•”—ÉnYV…W `µlfizÛ°´í́ûÚơôơ¡‚•”—ÂrYV„W Xf´kffm®½µèêí‰Ụ̀ô÷¢‚•”—ÂrYV…W h±jffhrÖµâêë×Ùơôû¥‚•”—ÂqYV‚WVVYl­kfgfkœËßè́ö+Øđơù®–”€•”–¾xXWUUVVUVWXq¤iffggỏƠë́ơqØ̣ùù´—”€•”–½zXWUUVVUUWXv¡jfgffj…́đñö\Øơơü½œ—••””—½zYVƒWVYyjffggjvÆöôôL×üööå̉¿¥˜˜™½zZ„WVZ‡•kjlmrŒµÊ÷íơDÖÿûööʦ±ËÖƠĨ»Œa„]\_”x¾¼·{ƒôíïƠ ƠôùûööÉŸŸ  ¯Ëă샪©ª°Êϵ‹qpomm|ùíđúơhÑïöù÷ûöö̀ ››œœ¡¾tE€ABB€ADplkjjik|úíñùöúÖÎâù€úûöö̀Ÿ›€œ›¼p@„<=A~‹liijjik|úíđûù÷úæË èơú÷÷ööúö̀Ÿ›€œ›½p@<ƒ=;=CC‚EK§wojfdegmˆûöơơööô÷ë́ù¿€ơúö÷÷öúùđØ¼¡–““’’”»G‚Œleddefimrˆ±Úù÷ơöơơ÷ḯëàÀèơööùöúúộñïộâÅ¥œ—”•Ă7‰ysfgkpxÄèöđïṇ̃÷÷ôôöẹ̈́kÁöơơûùđṇ̃ṇ̣̃ññđñùç˯ Ï5‰ sƒt‡±Ơöôïđñṇ̣̃ñṇ̃öú́́ëö Ôộà̀â÷ñđñṇ̃ñđđöí́ˆ… „„ƒ©Ñè÷ïíđñ€̣ ññïïùæÉÚè́ôt cú÷¹¢¤¬Éặôï€ñ€̣ññơï‹íđơ€ṇ̣̃ññđíñơàº{yđëùÄë́§œŸ¢©Âßôôïṇ̃ñôùđñđđñọ̣̈ññđíơñѬ…xtpnozăôÄ÷⬡œ›œŸ¢¨ÀƯđơïộïöïïơêÆ}wrommnpt|ÆûÔøöñåÛ¦¡œ››Ÿ¢§»Ûđ„Ưâåă†åïâ¼zuqnmmnptt‰ºÑíôÿĂơ÷ÖËƠæÛÀ¥¡œœ›œŸ¥³b\]\€]…\]\\^x®wpnmmopst”¾ÎÁ¦öëñÄị́êĐÎ̀Ë×åܼ¢¡œ±SNM‰NMMNO^¶rmnqtv›Áʹœ›ŸẠ̈ïoÄ}ùù÷èÚÏÎËÊØåÖ¹¤¤ÆuRPNNOPP†ONOOT¼xtz Ă϶—›¨ÉåùëñÆçơù÷ùôçÖÏ̀̀ÊÚâØâwj…ih^^„_e¿¯ÊË­—˜›¨Ëêúọ̈ñïtư÷öôôïï÷ñæÔÎ̀ËË́¸¯†®†µ¸áª˜˜›œ©Êçúđ́íùùëôẸ̀á§¼Üơñïđöđå̉ÏÜ w†s…tuzϪÎê÷đ́í÷Ư¶ŒẾmÈßϘ›¡ÄâöđïñöđáÈ€‹ˆˆ‡€†‘ÚÑêúđ́í÷à¶„qmp¬ôÉYỞ¤›—˜œ§Êç÷ïị̈ù‚ÿ„₫ƒüûú÷đ́́ö庋rmkmq˜ÚWÉ"’̉È—˜œ¬Ñíơïơ‡êëƒ́ị̈íö⽉rnjmq¼ŸTĐ 2 Ø±œ˜–µçĂ¼‡»ÉË̀ Î軌rmjlp„Ê©PÖa¼Ô©›—›̀9*)')('()*+, 3™qklo¸­h ÚqĐÊ¢Ë0(‚&%$€% $%%*{{¸½rà5™èŸœ›—‡–™Æºí‡  ÿÿÿÿÿÿ¨t8mk@¹̣¶ƒwC1-ÿÿÿ₫ÿÿÿÿñ”.¡ÿÿÿÿÿÿÿÿÿÿÿá‹ÿÿÿÿÿÿÿÿÿÿÿÿ₫ÿÿä4~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ*î₫ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ»Z8Eÿÿÿÿÿÿÿÿÿÿÿÿÿÿ₫ûª’`) ¹₫ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛ¿Ÿc' ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿúбBÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÔÄ(ê₫ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ₫ù!.ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ₫ö! ¥₫ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ̃" ₫ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ₫× `ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ·Ö₫ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ₫ÿ~‚ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ₫ÿ\áÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ₫ÿQÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ₫ơ7:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ₫đ. vÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ₫́( °ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛ êÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÙ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÙ/ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈ^ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ̀–₫ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÇÏÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÆ2ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿËmÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÆ¥ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿººÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¬Êÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®éÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÑtñÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ₫ÿÿÁXñÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®ñÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿDôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈO1üÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿª\' ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿă¿¢g* ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ₫üƺ‘PÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÚèo1 ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ₫÷Å·JÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÑÁ¡f* 'ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ́ų‚BOÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿĂÏÛè÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ₫ÿ̀¾›]$5ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÄÀ¸¶¹ÂĐàî₫ÿÿ₫ÿÿÿÿÿÿÿÿÿÿÿÿÿăÅ®z9)ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ§Œ…œ¨±¸»ÉÛÿÿÿÿÿÿÿÿÿÿÿÿ₫ưÈ»“TÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿƯ‹XBHWgw‡•¢¬ÜÿÿÿÿÿÿÿÿÿÿÿÿÚèq2 ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿư‚A%2@O_p„ú₫ÿÿÿÿÿÿÿÿ₫öÆ·‹Kÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ­I  -A‘ÿÿÿÿÿÿÿÿÿÿÔÁ¢g* ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ₫ë]% .Ơ₫ÿÿÿÿÿÿÿïųƒBÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ;Pÿ₫ÿÿÿÿÿÿοœ^$ưÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ₫ÖT# ÿÿÿÿîƯËÄ®{<đÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿt1 1ÑƠÎÈÇÅ¿±Sñÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¹JIˆ°º´©˜€Z, ñÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùa) (ZƒŒ~jU>%̣ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŸ@+CE8(×ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿâY! ¿ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ7 ­ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ̀P|ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüm- ^ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ­F9ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿå_%ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‚;ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÂTÓÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿói- ¼ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿœC’₫ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÓ[ kÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüu3 Jÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ§Jÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ₫áb% ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ:ñÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÀQÔÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ₫ïh+±ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ“@ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¾ZÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÆs0 ‰ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿˆ?tÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÍ‘IĂÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿó›J,êÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ₫ûs‡ÿ₫ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ₫ÿ‰Đÿ₫ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿº |ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈ®ÿ₫ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿê'.èÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ₫ÿIoÿ₫ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ₫ÿw Éÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ₫ÿ±Ö₫ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÆJÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿKÚ₫ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÅ:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿm+ Ú₫ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿø„HjÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÚ¢b$ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ₫₫Ăªm* ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿâ¡`";ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ₫Ǹ‰FĐÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿèæk, öÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿø·Jÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ³v2 í₫ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ₫¨m)‰ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿß®r,(ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ₫₫ůs.  Ë₫ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿâĂ£d%kÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ₫Ǹ‹Hùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿâæk,  ¥ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ₫₫Ƹ‹I7Ưÿ₫₫ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÜæk, ?‘Ûüÿ₫ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ₫ÿÿïÛÈÆ¶I *d—°Êêÿÿ₫ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ₫ÿỵ̈ÛÉÇÅ¿´—d* 6_€™ª·ƠóÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿôßËÇÆÀ·©˜`5%h‘ndStCœ¶kWºÍZê6·!H›¦m\Æ$í~°Ù‹o:Åwñ>ù Ùƒo{’ Æaø¬ˆ"Lö"³›4M'S¹÷»ßùî9'çä^ ùqZÓ/USOÅÂüÄäß̣^C+ühM‹†J&G@Ó²yï³óÆltîoß«₫cƠ• đ ¾”5Ä"áY i\ÔtàÖ‰ï15ÂÍLsX§ g8ocáŒ#–f45@ ÂÅB:K¸@8˜iàó ØÎä'&©’.‹<«ER/ådE² öđsƒ̣_°¨”é›­çmNÑ|̃9}pŒæƠÁ?_½A¸pX6ă£5~BÍ$®&½çîti˜íe—Y)%$¼bT®3liæ ‰æÓíôP’°Ÿ4¿43YóăíP•ë1ÅơöKFôº½×Û‘“ă5>§)Ö@₫½÷ơråy’đë´Ơô[’:VÛÛäͦ#ĂÄwQ?HB‚d(à‘B acĪøL"J¤̉itTy²8Ö;(“–íGxÉ_¸^ơ[²¸öàûƯ%×¼…Å·£ØQíµéº²ua¥£ná7¹å›m« Q₫å±H^eÊO‚Q×u6æS—üu Ï2”î%vX º¬đ^ø*l O…—¿ÔÈÎ̃­Ë€q,>«SÍǼ%̉L̉ëd¸¿ơBÆù1CZ¾$Mœ9̣ÚP 'w‚ëæâ\/×»̀]áú¹­.r#ÂơE|!đ¾3¾>_·oˆa§Û¾Ódë£1Zë»Ó‘º¢±z”Û'ö=ª²±¾±~V+´¢cjJ³tO%mN—ó“ï„ |ˆ®-‰«bWO+ o™ ^— I¯HÙ.°;í¶SÖ]æi_s9ó*péưĂë.7U^ÀÑs. 3uä °|^,ëÛ<·€‘;Ûc­=maº‹>V«Ût.[»«ƠŸÏªƠƯçä x£ü©# Ö¡_2 IDATx́]€UÅƠ>ïmyÛ°°´¥ bC±`ï»Æ{Ôh¢FM4&,I₫˜ßXKÄ̃À ˆ¤"]ÚÂË6¶×÷̃î¾ÿûÎÜy{Yƒ Ê☽mî̀Üyósæœ33"^đZÀk¯¼đZÀk¯¼đZÀk¯¼đZÀk¯¼đZÀk¯¼đZÀk¯¼đZÀk¯¼đZÀk¯¼đZÀk¯¼øñZà7–₫x…{%{-àµÀÓÏÈ—Ơ¥u½jÂË—Ö.¹¶bù‚üÊÇ#‘È9o/.9ïéÙ/ºñåÅưÛÖæŸ®Ó['ŸwYÛG̃µ×Ú>¯:F l© -œ0}Ơđéÿ)£D’bÅWÙ–-uaI‰•@¬O2“â *"µÁ–¸„XßÔÜNIO_Sîß\,¹à€îOwŒ/ơjùC¶€G~ÈÖ₫eÍ4Iíו#3R>ñÎL †$ÜÔ,¹=ºÊØưå˜A$¯¼A6”7D‚M-¾Äx¿$ÆÅDâü~_fr,Îư’+uá&©k?¸º¸f̣9—̃0³vá›MƯ{ôđm.(ˆ|‡jy¯́!-à€đCÎ\[ör^Aé9ï̀\æ¯k KK$"qq1’ë—˜@¢ ï×ŨGúvM“*HEƠ!©oj’Ä<÷ùơ }~ŸtKd&ÆùêĂM‘’êÆ×«««;¬Ï—N°/xÄ ô‡YÉ̀ÖÜÉyưÏk³å®s‘M•¡ÈoưHJË«¥¦¾Q"-ñù|' q11’Ư)Múơî.'ïÛKºg$IqM’A£à¥!)h†â Æïóa¸IǸ!+)fỬº>\Vüîăö7êĐ#ư f}Ú"‹ÔM;ù‹¼́v·đÀîö‹´©Ï«_Ü—è¿ûÉ7gHEm£¯>Ø$--À§ø@Dbüạ̀àôñ±1ˆGĐé’‘*Ăûw•#Gô“²RA5¤¦æˆ4A`ˆơù"]Ră}]Săe#ˆEcsËmÓ–n|ư¦ă†®Çc_ZzF¤ºª’I½°¶€GvóuEQí–'̃ÿ¢Óªüb©ªm”t¸†û ́X‚ØŸÄÇÅIb V̉S¥sj‚́·w9wt®”דˆ¤Bi˜ˆ‘%&àó ¡?h µDzgÆïƒ21yAơë'Èùujz†¿¦ª̉jî*xç´(çya7l?½>Oºtïv\S‹tÊ/(‰4›|ÍÍ- ₫(fˆA †¾óØỐƒ’çạ̀±ưSădܰ™¶¦BÁcRú88¼ïGÜó%Tyè+¨ èA$)̃Ÿ{ä.·¬.©=o`vJ/‡Hу1Zœ{¡·€GvĂïß>,w-_äW>ưÉâơµøBPê5à<¾©x„,„¸‘é8<س›Ô‡#Q ©Y U*’››qO$Ø‚¿"è² B̀دWÿĂY Äă D&GU đCupâ…ÛFEÜqë¿GÖüé?Ü,ăŸø¢ïNÉƯ§/øZaÂk‚(@€3(äÉẸ́Ú¢‘ô€Ă€†ÉÉIrñ{ƒTé½ßÁ? F0BPФ›!=4#¦K ø}U嫯?ćTdß 111‘̉€×wĐ=xÀnú >töĐ_¿2c¹uû ṽG.PÂ@}M„É ë/¥µAơPAÈv¬‚öUÍ(â!Đ;@‚€*@è—%ăÏÿÙDÜ̃±‘Àj'â¥9” ¼ĐA[À£â»áwúcss²Ó/^œWÇŸ°„1ö'÷·€=ñ¶'$ ?¹RB¼¤§§ÈuG %µK%!Cáo¤÷73²|>7ÇHNF@₫3åÓ N|>„Ûư{#ö@́Œ˜H)€̀Ă¼ˆ/t̀đ$€Ưđw»zlîa3VlNª®©‹„ §¨ò¿Táá/o:g4ïù1æÄ̉/ V.:rùde™Jô°XUIÀyo›2‚Á×75¦ýÅăçă9_…˜ŒÈ¾BÇ€ÄzÄFD2#<àÄ ¯< `7üÍFåf₫₫ó•›×À´:üÄÔñpü‰ƒ½ŸÚ}ühÿ‡SOÔ€>IIq̉­sº́Ơ£³”A©G‰ÀÁpN#x4Ü?"Ư2åé ÏUW–'âQ"¹~&"uIˆñˆ–ûÛ̀qË ±< `7ûƠ₫:uƠ€ÊÚđàẨJxr NAOï?ù8à¶ç‘Í‚æẹ̀›€qZR@N?|¤¬(¬‘€ôCª”(-¨{­àg2L(Jˆ‰Î¹æäư}‘P£|¹±F«¥ ̃UƠ5nh”’ ªi&<¤¡¹/ÀI?‰ñ̉¿WŒê.SWlÁu¬k44€à'̃¡đ³„$2*7ƯwÅW®/Ư¼Ñ­Ø£ˆO"@‘Ÿ‘ç4*-ÂÑ ¸Z{@₫ˆ=©ê%ƠÁÈcỌ́¤1Í“’G—]é™™(Ùé(ư÷`Đ£óüÉÛ̉ ¡f9¨_')­k†í¿f}˜aF r>F!đn˜ŸøàO¶¯2¸÷€₫ Ü>ˆHíÿĈëœX€c9b"‰›Xà̉ ©< `7ùµî{îCß1‡păú øă‡1›/Ô¢}‘Ê•·I©­̃Ü›ơ{œ”€ AY©Ù/7]|ÍR±¥LR:çH\f'Ix'û—7À©A p₫¡~NB™X`à­æ4¿̣Æ5Xyḍ+O®Ä#₫‹ z*©$đ½™Bh„< `7úm¬̀Y_ùº ÊW×î ±Ÿă}Ă“'ă”v|₫hÇ“Äø1~ää¿?c¸\rÿËâkjp˜Rº&|¢$§eªyđ¨!%˜&éYY2¤k’ô„̉nÁ̀yºK.‚°y}AI°băg-ñIekªc!X„g^ùȉYºøÊËJù “z¡¶ÀÖ¿xü€=¡ÊĂoŸ(§2tÔGöÿà+ Ê·¨÷_3Äwƒ0ûcéúXX¨è;edÙ¼¥B^ÿS©© ê¢!lÿ*æÓr …)đˆÁ»ÿ{ëẠ̊ö̀E˜,4Pf¬Ú¢̉D\t :äK«B fR'á‡Ï1f%JB¬?’ăK÷ÏÊí9üHì£ÀMÜç{ÂϳGƒíS{ôGv„›½¦́ÑÊ`øº©K"µa_®¿fܾmí•ûă6íû4 ̉Tø 8ưüâo¯I]mµÔ7„à:Ü2đ¹h:äp!„9́0É ´ÈçsæÉeg(á¸dY_]ƒßÑîÇ®Ñ=%Ê$6ê—)Y ±oïÛ;ưt<à ƒ©­bĐ#hŒôgíƯ“ëxÅó_e í‘vî¼5î¿Æ_ŸßlD}C§Ư":AÈkéOÙ¯·<3y¾„ê¥+…è=ˆÉCMÍ&r ±0¦7aâưÿkbå´C‡c̀ÿ©”VÔÊ_yC:%ø¤OV2”‡M°0@B±ï©2Ç\7"H'!<Ÿ½¶Bª‚-§M^^̣.ªI€#@µ‚©0N¼°{·€G~ä߇>wß́^Êë;Ơ4†|êöË Nàs†¶à·¢}́₫ôL‘9_}- Ar~®à°nR æAN_J‡=Wjkj¤¢ªFªkëåöÿư·À ¨Ă€fê( †pz1#•…!X°ö t -̣Ùê-P2¦œôú́U¯¡N²B$́[!@#́ÎÁ#?̣¯C`ë•ù?_¬¯l¡̉Ïr-Yàó:zuæ}ộĂúÈÏ,‘æÀi¸¼̉ E°!Lăƒ€̃„$¹́˜ư +ø œ¾Yê°ÄXMm4Ô×ËÍüSÎƯC‡ ­ÍB £lLbiPÓbó ÈKó6ËØa¹gưáo_ˆ„iˆ$D v÷à€ñzhâ,-=œ²ª°ÊO›=½ư,ÿ'àm°„€pT¥~¹nRdSi•Tl^/Á°ûuq×{|_•…PèÑ•xä¨Q̣ùü¯$T_c&Ab†BĐÔKMMÜóøkrÓ1A`đzBzhĂÈYCJ!®%EÅ¿çḷ]zé¥?úÔsFÆtöˆ¾üˆ?̉mg*ÏÏƯxImKz7G(₫«æß°}”ûˆ J³1‘?6Dxùcˆä].¼€TÙßDëN?0‚´Ä%ÉÏ;P₫ñêG eA'@©åa6¬­«— 6ʼ%7ë¯úTñçx *1À=ÊTR±Â­¯-(̣=3áù·:å’Á œ;À¹TÚy8ơÂîÖø‘‘£u>fÆÊ,÷ó½Úü[¹>«¶•€_‹DØ>idÜóæW̉T[ bî…|˜€ç8êap~zư]sÆ̣ØæI|K½®1 KŒ¡L³”ÆöȇD ƠRyđ•åT”AâB¢C]‡9 0D€ïÁÎDM_„¿,”wŸüíQGŸ>ơàä!ö3C‘pâ…Ư§<đ#₫ü`ơI9iQÜÍ' ́JP'ËưƯGú₫Á’‡4>,ØÑYfϘ%ơư1ö₫.đqê(„±\Rª\väyá­©ªÅoFyä₫$\VŒ¶*Cđ#h”ÏgÍ•‚MrÜĐlµ pÁ DiƯD€’ô ¾ZLPxoi‰¼ñô?ERJÔ XIÀ#hŒƯ-xàGüEÎƠưüWÀµ>€‘µƒ~ ú¨èONü‘“±_}D˜ưæ©Y.ˆ•}Íßá₫®ïñƒZ¨£î]uÆár×K3%à3ÊBr•.·®'ˆ4$"scC…°<ǘ›R^Û ăà=ˆu P¾Éœàg]£DE+A³{ Èœ¢æ^Ó¿Zư/¤¦2 ˆđH+' v§à€ñ×ÈJ;Ù¦j,úàPV‚·b¿%D1ûbz0₫˜5ḷ!µ÷GE~‹#ú“a[ÍZZŒƯoˆ|üÉtưĂÎØŸ$CI"ÀWIè7ĐĐ„b1(O<ó"ä÷éß…z=ă|¤'ø£êJ x$í S1ˆoY©ÈÁ@æÈw¾X3 ÉØÇÜDÀës¶wƒ£÷cü?;sÍ–‹7V5ú1~‡íâ? êBĐ3nĂư!Ûç”+ÿụ̂ ÂæÏµ)Ê+Áp€o?kû+÷ç,ÂsO#w<5YBAg_–Çô öè&È“«×A¨«oû{^ÎÚ7ë `GR¼BI€I\Aê-ˆßȬ5¾ưº~₫Ă¹ÿÀ+\[€‘’€§@#́.Á#?Â/ÁñtFRü]_®/€iÄXØĐ‚u²ÜŸ?÷ơƒô/#raakËÆü àÎpÆá8X;D€ïêªAĐüÇ&$ÉÈ!eÉx "½* bƒBXP´t‰q\“4PÁ2@Đ+zQn×W'!ö¹˜ßdƯ¬bĐ&^ˆü{vö;ñ¡'^¸I)Bpi1KZ ÆM/ü8-àŒê~œÂª¥̃ưọ̈~öít߇Ë6c«/ €Q £A,÷gÛP0W>Œåij»₫˜Ạ́»§ß•ÊêZUÖ™q< rĹà Ă.!–€€.8ơ(™ôÙÙ²i Ơ˜DC_ÙƒÑ+æåjúY·H°^¦.-”ÿ½ü™¼´T÷` 5’k]i%ĐŒÍ° &ÖYRP-§qÀ•ÁÈê%ófnÂcV˜ˆx4Á‰~œđ$€¡ƯÚơè uà°‘©â¿¸V)€C¹±îN’-ÿ²@ÊJJÓ̃ÛÊå×r|™"#A_‚œpÀ ỴƠ— 20Ùáuóư†ovU b8ÄúÜ”tKA\û×Wä̉1¹º^уÔ2@,³7Ñ[Đæz˜3àăÊEo/*Üwï½ÿẃùW€][JAÏGà~‹â‘G~ˆṼªŒ}dD÷ÔÛ¾ÚP 1Ú×Á¾rÿ¨è$RÔ¦#'aÇßsæ«¿ØmöÛ*o f0Lỵ̈ë ÇÉïÿkû`)1ˆóf¸€HY·øDŸ" ‰S3”‚TÖÂ"°nm|:÷+¹è °>À2€4Üß dpå¸ ëØ,A&//’×'ü󩘄´îPN¸‰¥P-n;ƠñnïÂđÀ.lÜö²0óî[ê Êë"ÔŸßrF%Ä‘cö;yDwyúư¹°ù‡ÔôGS]TR ˆ"J ±±PÖ%¤È>ưzẸ̀9ÓT)Çq¹å₫LÇÈà–ÁƯç|æ6́ơê#P/“>˜&_®-–öÉ&3æAô$‹ùµæÂ3ê) Pô•Ơ„åƠy#ËV®~”#u´B”Øm•pê…ª<đCµ´–Qư²®ÛPÑĐ‚U|¶éđ–ûóYî›Ê?Ÿda¹®)Ó¿PđÓæO oȉ!.PùçĂ>_¿:œüö‰‰̉•½J J(ÎBÔ}tŸGóf¸à3ă2LG¡ Öh”ç^~]ª1›p`·$Ơ₫³ >[5ö,H|—s‚Zªƒ¾™ùuɋ׾§#*é(d§{}ñC¯ÑĐb•ØK†uOóÇùcVăÛï`Çá₫°DÑ?Åß}gG&N×ñ~H~œ¥øÈơ™Đ9̣4/q߀ÔôtIÏH—uykuơúC:‚‘0edpƯçæ©ùk7å»ÖG ú‚‡Ÿ('é„-È:Tà¢̀µ5/3, Î± :Î>ÜPÖà[Uéë>}yÁûHLÓ }́NCRñCü­²°%w¯JlØ1"7S飑]Íj @;9ê0˜ư6–×ÉÊƠ«Uñ§<¼¿­»¾CÑŸ«ùåü“—'^ÿ Ä”]®@‰¡í;xׄh6Î={Í£‚ùóhˆ€ñ ¨¯­‘‹ï}J.Ó[Wb ơ„>@—G±ø:ÍΘ;±®$‘Eµ¾̀ŒỖœ|'’Xó _°4§^Ø•-à€]Ùºṃ¾ëÍe}²ÓâÈ帽»`xJ:ÖÆT¡FÎOñ¿®±Y.Ó_n₫Ë‹X#À¯"4Ç₫Ñà"ü£>ÿñ> —¬X¾RÇß\c€˜àU"Í ư t÷SE#‰"ó2>M˜8"PS"đo¹đÀª áÅ"¥”0q"ư‹ó>«₫̃’RsØØó₫2áMú0ZI€Ej±8za¶€'ríÂÆm›ơ­w₫ôıƠÁ&̀k–~Ù©²º° 3êZ'qÂÑzæẹ̀̃ñÂ5²&o½.ÚA§ú[N0i€-`‹‹¬ß)Wǘ|yé?aiđ•ZÀqUaˆôVÇÀ÷H¶‡0̃oï¹̃c>¨ƒ*,‘V _sPæ­)–‡~6V¦c?ÂD: p}AK¸¹n=ÆCZYSR+'9:«Ï̃ơÓߟ´„ơB •cQ6̣vQ xÀ.jØö²=¼fÖÔöÅåơa“*éX»Ÿ uÆ)Ç$§ôcùî89x`7™:h̃éÁg…ˆ F8ß?N? Û3dÙW_)÷oqÍøÓFơÿÓ$ J”“se 0…¸»äË_ß#¿>¶ŸrúÔ «co‚€‰Xº,+%^2° i:b—ÔxÉN D`Üpé9·ÿê¡qE!; e€̀‰Åya¶€×À»°qÛf½²¨6RâhX™(æÑ·ÈĐœdyེØ&'Ó4Aƒæ₫¹̣æ'ódÅÊ5RUW\­Æñø)RÇÂ??€¥¾¶Û®»T^ygª¬üz…ÔA<cëLÇ àƠ³G–VÖy'z@ùT’¨Ä€“'Æ›íÈ;§'ȵ?¿RNœ!Êt¿‚*:w€çˆLX‘D}èj?è9irÛïÿ|ë?ÿç¶·;Ù‡¬DàÎÆ;ßI-@O,/ü@-Đ¯sRÓ‚MƠ±ñạ̀”p9ÖçÄ™‘}:Ëâü2Evr‚tK“e+ó$à‡1T B,ÇV$€h÷‡!©K/ƯhỢ%§Î/à€ÁMåƯD ×·<Ñ\I„P₫#‰`Â~#¾pƒüơµrüèÁ2in‘$01½ºăhưXwg†£zƒ¥›±:ñ=¿₫+†CMî¿ư]Ø:LåÍĂø–¿Ñ&÷†;ÚRß3Ư¿go8£6ÔƯ­}^ÇÆkKëåx(ÁÅi¡¿zlyâƯ9è₫MÆé‡³ưlÙ|ÉüP¹s©/o?VîùçDL̀‰uÄÿík₫]Y|ă)ËƯºÄÖ伌íI€0éÜGƯ<øøs2mÚ ™³|½œ8¬‹Ô`‡#îq@=‡.zjá®Él~̉‚ư áÛPV’Wço’ÿưíÍ>èäó÷Cö4z‹‰´6ù.9óÀ.iÖ­3í?l”Œ˜Ûˆ±<8_ÄrN ¤¥“ĐYtK“¹«6ÉÚƠk À3æ»mDr^!đq÷>ưúJOXÖçå9S„©ùoµûo]›íƒºmºm®]ỵ¹kPœ®/øĐ gÉ]¼" ˜B\^U+/½ñ™oáNÅuđgàzdÔ#ĂMxNCJA$ơṂê—Åqï½6áåƒ?k$Ê·B\[ĐÓ lóƒ|ÿø₫mø_sX»t¸yó% đ‰'v‚hyR .­É~½3dtÿ.̣̉Ô/^˜ÛÔ2àđ~r~ß́„zÿƯq̃ạ́§ç§À­ØN÷må₫[¿åÊ࿜̣=7÷çµ:¡´&˜̣±Ôt×_q¡|4g‘ToÔ5+°y%V~ùµIR€ÉKûơN…Ó̀x$éĂHfú3Îơ[©ûu £PE}Ø÷Ú¢˜&¾đê¨#O†bI( X—aœzagµ€GvVK₫—|2’ârkÁƠVÀ§mx‚L‰@MH2b›áˆ¡5û0ïÜ1P̣i p¢{́ŸÛ'Û„ÇȪ•+a-ྭܟDĂ‚XlJ7ù}Ăß¶àgRÍÇÉÎF~&)åôß[²̉SäµI﫵"ˆ¥Ä1g>ƠØ£đ¥Wß”.‰Ú#’‚™áÈBœ|áæâéùƒHy]X̃XX÷ñ»ß8øÄñ#ĐÖGÀ³˜fÛim?ÜizmÛ§₫壄®)ñ°®xo&Ă[=µÿư;'Éä%…rÿU§H—}T´OÄ&q $n¾€'1MO~}₫±̣ûç&ĂæÎ<`.PiÄÂư%ÛÖnÇîX¢ÀuYŸÀßĐ́“Ço;_₫öÔk }¸àˆ: aµ"n:R‹x×ß“Ưâ$7+C‡˜đ?*†At8W"€%ɰB2ͤ¯U7ùß8æ‚«öGÔ ¸ç |ßOÚ±ßĂSyàøÏ;|Đ^eơáîà{ù ømĂ›±z‹äW†eƠú¹åÉå”ñ§Ÿ"Ÿ€Ä€`f£¹ÏhÎ ©ùßkÈ ÉL“å_-R=©3Pæ nê¼ÚÄlư–ÉÁæ§ă~P¯xø-ÈÏ?p«ÜưøD ƠT´.6b¦Sˆ¹}@êjkåêû’£¦JϬœ‡L]8wĐùoˆºOH¨3ĂG₫Ës©ºeAăhũpÀưă~sÛ¿G̃«ßÔ·ÿæ7rÆĐ¬H›<×Áa£S!F`Ñ“.€%ë ¥ḳ×bµŸ±ÙGRB@₫tË¥’”–%ɉñ’ç 8(Üâ0Ơ—^tMà°¸ôx9ë âçµ®à€Ÿia¦f,gGÁÏt6-ßÓw)úă¦},ŸÇñ§'o|¾J–a©±F.NÊ} ~₫w'ư¡4¢ËÁ—¡¾¾N.¹ûqL!Α̃ $|°ÿ¡-Đü×aA:‘VI "u;O×T&Ï_úơTh 3Ú*½đ=ZÀ#ߣñväƠï¿_¾* ƯW ¯–³b©A‚¹:’“™(‹̣°Xª1Ë.³ØSfÈÓS—È?o¿H¬fÂ$̀à° 1/û "ïŸ>¦2_½ñ¸A‡Z P)7ˆw¤LƒªlÔ{•DĐq?€OÑ?³K79ï¸Ceê¨9Ó)ö—c› IG)f×!:&A•±ƒ:KŸN‰“ êŒÄ:À;­Ăn?Ö¯Éf™½¾¦ÓʪR3ºdÄÅéªBṽ€g°M₫øöm_9 Wj-vΡÜSóN®Z~ØĂ! pÿª‚2]í§Û{Óó)Ü´I~ñÈ;rưcåÊñ'`(´d(Ä1¸öŒ1̣Ê[S$ ´Pù]́ĂÅùƯơlàöy{ÏxO½ưp´ë Đäñ<&½ IDATÇËc÷\+×Ư÷˜4‡@¬Tñè,kÈs”’",M6‹Å ud@ñŸÁÜ ÀSB N D ºb‹\sß¿k#Jf ˆ ^aÙQI€ï“€˜©Nï“”Ơ7ùæl¨Múô“g'¥uJǪBm‰‹ö·h|‹Æú.Io¸ûÁXŒÿ³t̀‹N­ØGF-9c.¸àÜeëTÔ5&<ÚËĂ ¹«¯¡Ÿ»h¹üỷ™tßåråIËäésuâ©A¤¶ú6å}}nN·úkŸGo‘¼O­¿ü ø:r,3Ö]̀¡Ä*́¬5àư•ûëÛæ̀á0¥’’DƒD ¦²B.ùícrö¾Ư% ƒL‘%ÀA‰  j"T‡¡f)®ùgcU¡Ù‹–‚µ¨ uÀ.5îé\m¿#§Ø‘Vúi:íÜ€!„Vø)¿Dç¦g`6ü₫WT) ¢ăḥS €Î@”è ±Ø¸¹T~ñ̀ Ù§gºôëƠ 9F0,ˆ!ˆi@üđ²̃&°t†ÖZ\ε>hó‡é8îç"#÷Ç$eȯ=S.¾í/̉Œû¹6!.‘8ÊñÛä£̣̉ª$"ÀMHë«*äg¿{\N‘-ÙiXUyñ›lưxäPAWB{T1w ¾Ó—ùŸ$¥eg`8@뀛°ú^ØđÀ4̉÷I’›qZ=ß94§ÍtzINˆ•9ynàn½Æ]– PÑ—â/.ë2Ë¡Á€®©̣â›dß!ưä̃kÏ|‚$ÂT°Ù£Dïg] ₫xhư¹¦ß“w_!×<đ¢$Æ€ ÀÔ[˜ >,ߨ~ˆ>çç«$Đ¢kÔVUÊ/îÿ·yüV Hg‰+Ê÷ùD‰Ä#̀-đåW}+K:Ï]´lNfßémˆûơ7WÊ”ô“ÿë€]Üöê’˜QÙ sđ“»ÅXÏŒ€̀Y±â?Æú0£Ù₫o«ç‘̃H-²oßβbí™ôé|™S–'î¹^bâ@0ß`åÚǛ{´yÚ#Ña#ï`X €ŸÄ„« s¢Ïg(3–¬•¢µË¸j̣sû[ß¶¹˜¬\÷ bà‰›ÔÔƠI Ü…o|à¹ôĐ\µ*(rñ‡G«71DÀP'€=6”7ú6$}2ơĂ9q)̉Paê¬$àơmư¾ù×HßÜ>ßûiQ]ÓƠ ¡&ôe‹™₫ï‚YpÍ̉óçĂü×nJ}€ùgTØ̉qÁ)³4óuÉÊ”›ª ™³`±¼·p£=ú ¶Q?4,·-ßT —ă°¿ÓâMÓR2²Û @*ă¾^·Yîyé3yúîË%gàpII„·ºS9"€÷·7`‰Z*ÊRW_¤§½ßûÛïn¹J˜0Yê‹ótmê Œ«±©çVÜ]ó¡Aà›ç tœ·MÇOŒµx€À›°º¶^–,Y!7?2Q~ul&̀¼Z‰̣ų™6™J h?ß̀µ¾̣†–Î_,^>·K¿ôp+ÙÏY1/´i´iu¹ïaÇÊ}3âpxª±0¶&ȃàZ™Éñ²vĂf+¬ñ῭©€ưa&P0vHYµn0à‡ë/§₫:N¼©©•+ÿö<}ëÙÂơXª ^ƒœCÀñ¼¢ehBx®D†à<èêËq?×̣ë¿Ïh‰„eÆô™ê“`—W"E(!²n âüz ̀3›Æ̃u9|€Ñ~ØAH%́D¼|Ù×rÛ£“äÎăúêđˆm‡e4Gî@̀À|y‡îÇ ѧÂ7?¿Ú·¹¶)é“?œŸêéÜm½½sÛ϶÷Ü»ÿ[`ጠĐ+KëB:e—µ̃1Úú̉*©ÁâAjÿщm À{‡Àä̉aDI/̀‡ùr}…}IÍXè:ÄTăPc½\ôĐ$¹úÔCǻ3NÁt]¸ ĂBÀñ¼JàJBÀrxDY,OM~P 8îḮ$ßx–üé́â"ăööcb‚ÏÛä`kÏ#scd0GVûEæ ÿrÀ}t8`‰†65؃påårë„r÷ Œbuç–û›z›¿- pª1Ư†n¨ñ×7'ÏY¸̀Ó ´6ơvÏ<°Ư¦ù₫R1¹Ü S€N6Åÿéñ2me‰èN?ªư7€4²®¤c øÎÅ7à‚{Xÿ,©.+ƠwÄÀ÷W[ à?ÜÊ}ÏM•œ®]庫.—8 1™H-èlái­ ´pùn®,̀ăooºBnyèi W—mḳăG´ZsmûФoè;x¬ÏÔcíƒïh¨® Ệ/fȯ.¿:¦MùÙÚZI%[I%˜›W-XcEuÉN í²ƠµG¶js‘Ó«ÜñÆâ~i ±ñ÷̀*ê‚K¥Â±fCA1̀$¶â¿­;»YüĂ'Ư Ѿ·¢\Çÿ͘.ǼL@"PΠ..Ä Ï¿? ›‹„ä®›®÷…rfBŒí©àă$xK%3î‡Í®¾¬åàaGÈÊ5k%/o?ç÷#o+*XW_-Äùcrsßi{Î̉ #£m¥çˆ€:?¡̀zLªÂ¢¥ófÉƯ/L“[ÇơÓµîÈÎäØztL'†N Üר́ëâÊnOn Q³e†ƯymĐŃ!¶s³{Sjç~¿₫ƯdƯ†äâW(Œœ ™´@óV3qÔáØøO¾…« dÊăwIJz¦zZ"@vÊáˆû1\è7x¨Üv.¶›€9₫ Ná&£ơg̃>nÁnAl¯ [k¾m³g­éÛKatƲ›’4È¢¹³åÎç§ËmêP/£`‰¨²%¡4ïCRà¤ø|ßg«+|U!I[°tƠ‹x„èv¾å¼ü“I₫zórâu÷k ̀¸Ÿ :Dđ·#ú["€,|‚Iǯl}·ơ5̃£"’GCI:%sgÊ/̀’Û ’Ve±Q=†f­9¨N…DûFf­­”æÔ®c>[°øq”D)ÀMØÿw´̣­ƯƒÎ<° ~LÎàCḈÙ99N’`×Î"ĐŒq*}̃¬Ü óèÈBeƒÏFLlëMX÷đ½ºIYI!Ws̃1o´ö^–.ÈÎNÄ\®.̀‰7¿ụׇ̈,̀„]zơS-?á~ °p®ÂíW-¿ỵIôA1‰5ưÔƠ„ÄäH¤mÛP†\µó`Û¤®;&}{DÀäÇ¢  Ă…NêÑP'đç‰ŸË Gb8€™’‰&‚­¡: Ü䢣T¬Â…ÙGb8me¹$g÷9DàQ$£$à°nßö#øÎ<°‹~ÆÆPS\U±Ö_‚â™8çÜÿ8tµM%e:₫gçäøŸ—=‘ç 4{éø̣:6 ùº¬QíâäđÍ`ª­̃UàhWÆ$¢?m÷45V–—ÉOL‘_ÿ́¹®½ ’’¬K7îÉHM–¯̀R‚¡&?ü; [k­úüÑJ"ktÓ®×đØ>³D D ’À¬Ï¦ËÓïÏ•c‡uU¡i1J(¨ƒ™+K †&Đ!ÔôUe’"°`Ùªgp›‹‰p¡Q.7ÎåÅL…p̣S ØE¿8í̉́ÄÅ5aÉ…7 ÍT©ü/XW‚q*løˆ–ûS„ß6˜ñ?gùơÉé„Í>ËŒxO ::ûº <µ‘9ñ»m) ( Óm˜NCơƠ•̣Đ Se@ÿ~r̃ygc_ÂIëÜU.<æ ¹ăÏϧØă[g%ß úàº*¢%ÛZư·£ùf¶Q»·)± µơC u€S‰?úxº̀^¸BƯ»+|*@(ÑF4b4£{,r#̉8FÜDzJâq² ¿R|i][¸|ơ³(“’‰€]i˜XØNeđd ØE?,¸7èZˆª)è|́Œ}A>Z\ Ê?rÿ¶ vW…4+ñP èÙ5Kl¨T=BTg€ÄÖ9†ï±çÚ̃ËwZx@->JT?đøÄé2"·‹Œ?óTùưUgɯ~*˜’¯C‡è¢¢&‹vÿZĐZ.mYB`í¾Ú榩èÖù´&Qƒ$JĐÀÊ©— b°³§L™*Å[¶È‘ƒ²T̉‰Ă8&Ă­D˜2““Sá kŒt‚‹4Ö^ˆP*4 ïaKÖä¿xï#Ï›’YÈÇVÍØZ‘=ø̀é*{đ₫HŸ¶¸ jIr nÇâĐkI:`gxÿ]₫÷÷¤´ªâl=Lvk­ƒĂ‚*đG¡÷'ăІÿ§+NGß™%Kªlú‰ç7`²LÆ̉hÉIỊÀ//’ÊH¢¬)®Ó‡Óø,è^ºƒ¢à2ÍvLMˆÑ‰LÜ—”Ôƒ&a–c§ä€T@WT”¿V¼¥âéV”~ơĐ%cK̉3;ù1ßÂƯ¬ßTùừ“vÑÏ•'q‚₫F´¬D'žè˜fK-®´Ă}ư,9%lxMÀ̉Û…ûÖÍåA(8´Îfüo«oáF¬8x!"G Ơ¬CĂ8IKsH¾Ầ¿̃x®Œ1 ë bF!ô œQh<ñ¶D3µ%n{´̃öÉ»ckÏÚ¶ó-½vn± ”PT¯E%wBúÓ““ö8¹éÈ\¹`ÿHY Đ³`·%,°º“„̣Ê`FÜ\#«Jê¤̃Aœ›AB*± ÙểÚHiu£¤¤¦9dÀ”?èÊ/×—½̣欥G±́FgÉ[Wˆö à€]ôcRä'èlÿi€Ëo"†\3Nºæä€øà¯Ï™{4Å‘SmƯÏh󃃥¥¦I|3À]wu=Dz“¯É™EØ7£Dǹ×Ú{q†ÿ|O#Ϥ¸ä ™¿¡Z^œW€ F‘O> ‹”ÄKZZ²ZèBlœ†LN–·º-­ÏôăQ{ÄévƒIă~¿5VƯÔŸ̉ ¯øL‰‡QX%myÍÉc.ᓽ±å:Ûº¾Ñ˜Yù> *£ F_€Vƽ*¬5¸©¼!²´¨.#35ñÜÑ};O-¨lˆ<ưîô;±•J÷½ư\–}O ®&ÙÓ>íGû¶id}YƯ0Úaè£ếơAñyưó<¹àˆ¡Ø´Yyÿ i¨«US'©UÀd\„“û Ư«Ÿ́íĂ'NϾ0¦ä¢SÅî̃́|ª́œ¨88è5̃£_AR"–öÆă7Œ?JÖ*˜jä°™20'].¿çq¬̃[!5ơ ª<¤)₫kD‰Â˜­Eè3̃³i¶~ÎÚ}S°5æÛ”„Ú¤Çc½ús¼Ÿ”˜€½âä÷wÿZ^ûp.\‡k°Ü›0’ï̉)S̃o œKJAơ’ä{q@gL†¦ÏÙ뮾»7²h{mLK}„ĂH%3©#R (› G£)K ±úđƠrÀ£Ơ4˜EF¸P,‡*|7Ú÷Ư%›ó¶Ï,!Ø6e{wœÆjç‘’ê2đŒàå GNZ:àC¥s\nƠ…RQƯ [ªêëeíÆbyñƒ9rÉß'Ë“SaÈ’}º§IÆÔ‚ˆ† Iá¿?; ´e`óf‚G¾•AY¼¹&̉Đ ̉7ó¿̃÷ÛÚU›+oG5´*¬sCÇ pJơ®héY»%ˆ®¢IÁH°q!.½pÅ:¹aUœôùû/N•ß<; €¯ƠJ3a DX¾Û¯[¦üă?X½ÓíÿOж́m z{4µ@–¼e ±¸HºLYQ¦Úr’ rȲڰ<úÙ¹ó¢£åư~]äßoNĂ<]Óß, „ku ëܶ$–‹Û£!G¶vmߨöºơ=ÖÙäÇö R̉÷%¼ó‚£å&ø6D0ßfNJP,!&[’zÆÇåKL/^ºv“dbÓ¾½räôQ}¤kFÔ@ÂjB&=ÚĂj@¥!- hût˜lIđ`f„3Qº„Fú¶T64Ưˆ"D¤‘-ÁÉ úăб‚GvÑïÅE@Ø+¢,BÅg*à`“§H ‘?6¶E^˜Í“{.;Q>[Ø_}ư=́L¸&s;pd‚êk¡–SG3Åm,1°àn­ekm[Ÿ™·¬èÏúiËfẩ¸£•O¯Ç®Ă5JHÙ†ªÅkÖ— É„mbÚ„—ßÅËKêúẹ̀éêr½gå~ ”("ñØ-=ÑwơÅăçăN?Ä D¾¸‘©˜1‡”xí䀳Ư<°Gya'·@̉Q·°—§n'´öâ—„€vùص©å˜üîxê}Y]X%b >´?fđÁé%çÁ$ôPÓ!ƹûó2~½c®ô±óD¸Ac@@=€y¿5.\KrVâ…̉•‘fåK¿ÜrÏM—JÏ^=%3-Kaµ!Ô‡ƒf„:l/X€óh¬¡½vn;3¬`Öà₫øfÎZô'¦É•§•·g-WIº‚›ßoœ¯MzfÁk%Ÿ)••ñ ~ûî•+ëÊ륢D ×nÁn@3%D#9¸«ï’Ÿ]ú²ˆØ±7bbgDN,âÜ;§otœà€]đ[ƠÏ_©jª²Ûª3¸›ƯÑrqr03{sà1f%ø¦}±LƠÊÚơëäç§"w^~²Œ”‹^ 'ÎâH9_€ Q%²ăVŒÄ–YF'LE6"m-®/èSç è¶\¨NoºÙk+dQaPºërÉÎƯ V‚$Iq2»qŒ̣¡b´~“Yëe3˜Ú4¬knê§ Üđ]ûSbáZ…×]p¢¼ưù2ˆï\L•Ë©9â¿æ̉ú"K2¥Ù{œ€!Ú.> ŒƯ[¾ÜX¥ë!°ä(±Nlu2V$”·0?¯~̣ÄÉơ»"f#øYˆ?vk‚Ûbñpwî>¹;׳CƠíÉw̃:§l•[mÍ–FF0ŒgÊ¡p“Ä€Zl* ¹L6· «il‘g.;nÿ<đ·Ç¥w—TyùwbW (¯¸ˆ·íR©ëh±„䤌 Ñâ øY‡fVb<¼U »C @*AÍ8‰ ”îŒs*Û½QưåÙrêÙă1¡(Q̉R’, SRµ«s(â‚íáå´P0h ·´‹€Ư€‰–‹?xFZª”`¹,p˜† ×€ûø&½fƯ´?¼‡Üwóẻ©GoI‡÷` å–æd­̀£-‡ç÷3đè₫gïá­›å₫±XUå̃«N—ß¿ö’˜ÅN ÷'L‘ƒû;‚_lŵà[1„JƒÔ2nŸ̃²ls­ú6hy‘(¯©ÊÈñ;ûtJˆL2¥zÖ§Vâ–;Å÷9æ·IJf'!Ø~ÚêÚaꈾª½Ètqrơé¦jDuÛùMo±éøÚq•@­L[²jİ ;ê6Àÿ½±Zj‚œré­2q̉Ûrј~̣đ §‚tSíx2́×t’‰çđ@$•+£bDá_=“fBjĐ7ͺ½^K(ÛH"Đ‚wYߤx¿¼µ¨D—4Éów_"û $éWëîDœă€´””óÛ¶W©ÿ2 ÿ±É…)UÄCÊIí’#];eH~~¾êL¨Å·Ù±½Z³Đ3Ö‘ ˜‡9”–09KN?t¨L_U¢u3¯0%J‹"Á¼ĂéÛ‡öẸ̈]9₫´¯‘€ă{‚›?H#"M€ô¤Àù¬m5pk÷ÑÏ̃½«Ù±j—œ`8`ÛÆƠNÉOqz®r-Û‹ƯƯˆikÀưS̉’T{Ư„zÜ<£»êROĐP%_/]$Wßz¯\yó]2¸SŒ¼~÷¹röÑ£TQ7~£+pôÜ.Œ&??üæÙMûwJ’:̀„sSk÷­ÏÍs‚…_ẹâ ;J¼êL9âØ$‹¦¦:z6s 4·o€ˆÂ˜Ï9„Àg8!.. w\5^₫2i.ÆêÖeéđnˆªæưĂl؆ÊưéÛåÎÑC̣±P › ~+÷Ç5ËÍœùíŸ₫\ ̀3+6NsA_…HM$n)—'xfÀ]đ[q₫¹Î2ÙÑ[‰«èq öú₫b))̃,1ÈLU’È‹̃n>pƠx*̉5؈c₫sƯˆ>i=±D‚ơ#@iK纇–/'í?@.{³\yÿH;R¹܈ƒ IDAT´n¨©élµ8G.ï¼æ·̣®WḈ±̉£ß€̉/¥eØIœß¬¥@y€e›±í\!z÷˜ơ$±8>pá!̣Á²RH?°ob1₫F¶]ØÊ tàJ€sĐđ>¾ƒîºm=nñ 9?¹>‡4º @×Lc2ÁIG Ø¿ç̉ïh_0GvƠƒ²&ñ̉Ü̉¤‹\(èœ,ơ€^ó B3€á‡=>„áE$„/¿˜+‡ù¹d÷è#¿¾ü, t-kÖ¬–÷æ®Å¤£F8a-@8•5BÀØ—ÄH1äÔØÀ€(¬œ̃U1×)¥iA/¸èi"†cÙ­^‰̣́½?ÇïË’¥œç— ]BÜT”C(Ür…û£™7?÷-÷§ÏÁ_®;Mî}i–ÖIÇưTN2 Ô½Ư,øeSÂmØ÷ÜG%©âê°@5 ´D€’·`cƯF÷ËösÔq«L6NNOOđ—!’Đˆ@”ø³Ù/ÀiÇØù¿“oÿÜTƯ`ƒ=¢Ơ Èd¸ÜÖ…’çnÓsĐq«+Ëe fè­ZÈξơ;L¯ck‰ ̀ Œ0¼Ư蜃5J ̣å¶û’ÄŒnrôQGÈCW]B£<=å+ "-Ù•NJÀ1s"âx¢ á‘ù«ăŒIÀ[ª à‘À'Qbä7E`_Ù\Ơ(Ï~¾I₫tỊ́ï)=äơÿ|¤+S‡†W‘˜¿ù熰Úưñ¡$..7*>|YZP-E%[Z¹¿Öèí~ 79¡Ù/íqá{c̃Ă*3©IM~̀@đó~*ˆ@$XQÜÅÎf°ÜŸ`ç=‚ŸD€Ä€C6C‡ Ø?W›Q\m'o÷3{Î#{›r0vLtb*£\O èd<˜á½Ü(:ÅÀ¿ßoÖô§­¹¼X>xë ™úî›̉iÀ¾rËùGË}‰nÔ0(; ¨ˆÍbưxGÙ«S*E|Ö"*8çä̉J4 ¡L…›‘₫₫qŒØ_½gˆÜ|ÿ?u,_ƒmÀ}÷ ̃!³ g üæËJàé#¿ưùr郓Äï¢Ëo[§ó–ó—€À¶T"‚ßÜÔ>±{0̃GAèû™Ú¼CđÓ›đ„áƯ}'œ|ú>A øÉá)ú»¹?‡ÔpX@ƯÉd„“ ÙïH5îuE'₫^Á¼Œ¿mrq_(Œªp:>Ÿ³SC̃„á@+é6`^‹È¥ÄJW/”~\î₫û,Ÿ•(‡̀”«é!ÇaqÍ^Yđ́ƒá°;¹¨¥J³x füo +ËT€‰ñ>u´á|‚Çï¹^ ïÁIÁđƒ~ º9 ¿zû.I¹?œ=ê°#eê‚5°×cßCJ-–h°røNw{đÜJlÖ“ÜŸV‰†A«‘ˆ›~kˆô8oå₫X{13!̣₫{ïÙú6”’¢=AN°[îÏc‡W₫á4x€m‰wlYY\3 _$P{Ùº;î6Ï]g¯©”1½º¢¯“µvṕ¹œ›¼§ư€¡ßLPsµ_p@W¸ZÖWÈ¿¦.ƒÛ/Xl¿>™° $Ë ®1 ."%˜\ˆå²«@DÀ= ! Øï°;@iA¹¸S.˲\<€Äùå ˜]× ^w†<ùÎç̣ÑôÙêÖ[_ߨӢI¬Éønrm7"Ÿ*wcJ̣Ezx4#åD?R s¥]RDùÄ“ûƒ=j–«ÖoUîÏçæ-«äØŸ‹¦1 Ë—qÈ•ëñ”BÇơ–û[ÅEËưù¬C₫Pïhđ@´)ṽI¸ÅŸÁÎJ²'mŒ_®̃R¬“{»íësykN(² o…ưV9êÓX"`zOuR“Ö”È嵩§¬ƒ' ÁP\’)UƠä¿À¢¦¼xéÓ%E:§§É˜₫ĐcÉ`ÔsÀ\R”7„}°Â Dó×ÇàÀÜƠÇ9×ZqBô ÿœ¶^½Œ>P|â%5!V×ú”Đ»uVoCưP§KÎ'ò^‰¥½°ˆgàG…ơ»p'ïvxH?:FÅ` ¯sî/ÏÏÙiÀA=ë§Ô'¸¥wñÙĂrRä}º‹£Ú1½å₫äöäúœøC@]@‡ưñ <`[b'1 ®ưôÏÛ6èV[ö6ÅXøy[ÍZĐq©Z¶îô –6ïé»Î=û\Ă@ơ™Ïz h))`mĂD¿|¶¦L:§Äˤ‡n’+ÿüªÄǹ“j(• A @%罿\₫à«:îçÄÎöc̃¦¶Zô…Z 8IC%`È£]»?ëúëàO„Krß̃Ư±&`¶<3»CĂç84pC #2¢W'¹í¿)Ä3V“̣N³oÍ~$–û[)é;tđ$€]ñóA¹À_X=§={€»h́E¼§½ ×Đ uBÓ±Ô|æ¾å¶ú̀¼µÍ_:Đ>Èß–j̣àä–‡́üæœqWM{ B>¼¯7xâ;SQ²94ñ©‡ '‚<ƯvË/W%¥g†>#øă¡‡v<&²êÀ6báẺØ«iătâÎY2 ;Iơê"¹™ à¢"óókäđ}ºp³̃ü.5·Ó %̃³Üß¶>nuüÀÆ ;¹Đ½ \@V ë–– Ư°W] fÎA7¥T¼ö8y•8ZnJ§́ơ<5× ¹†]¼„"ܯ×(¸ ‘ Ôơß â;2 ̀°¦lIèóÏnđrº¤'Jvz²́ ?L@:'ùeÅæ*Y_Z+g­”Bl¯•àk’ h﹌ظÓ/Èùè­—Ö!cëCđœRDÀ“P´$|f#%…Øp}mó+ư¹á\üúW¿Z»,¯àà¿\ %¨í€…zTOa|LQh‚êô·a× $ÿYR ¢e–ơ¶ă~} µCv¤T‘¡9©¾ß₫ơñ-›×~Mp3;3·ÇŸuú!÷çó=ûă{l×á©vF ÄÆÆÅ ñ'g.ÙXÑ€Nĺàư:'êVáóÖ–ÈÆ¢r)©€3Ni½Ü “P]µÊÎt`¡‚‹{ÀưF&̃u¦2₫zhê±J4åMá ‚„‚ÚqzÈùâđ±É™º̉O†;ÿ è†-¾’Rô^RVwÉ̀̀¬Œ49|H´û±RgŸRÔciA­l*©̉äÂïSïÀü >£]§]= ›q₫î佺wÎ|mEplF,rÎ 2‚Ÿëä1&º®í}I¶‘N?ïÂw<đØĐû_øHjj±1¼íª¿–­lB¶7Ué” '.ư T\]R¯Ă/&ăèÆøưs8ƒÊ8R-0&Çî™ÓíK¦A w'øiëç7­G\‡¸ ‘ÊAJ:LCjªÅă¸GOØÉ?#m°Vxik ˜è›†¯´nôí–.GNWϼ8©Ü;U*°.ư"L|Ñớ±,Xù–R€Qdü‰GJJF–́’»ôÂ&i˜ß1=YfÅÉ̉-MpР˦̉2i®¯–H°NZ@(BµUØ;å@_¶v©´ë¸|Úw€\yî‰̣ô‡‹¡¨4«ë`S]é‡₫₫Ü5¢ÿ+Đ(QD"\B<"…¡„ØÏ<§Ëû“^#đ­Às‚„R9»¶%lKxä=ûœéyÿÖ+/VÜđ‹›r†`G”¥« Đ–M>uªÂ0%ª́Dƒ¢Y”HQªIq̣Rä́û˳s6cưBÛ­™ÊUl*ïÑ3CîøÍ:°Î–ûó(ѸgûY§m <Û£‚m©=ê£~́Ñ .m*Á¹÷´q¯ßX °7¬àn¿ÚѵB /\69U—Ơê½ÁAđÂ+°XJ́“E륺°p8ÜzkË¥Ħ%T¯Ê<ø–«J=ômRG99®˜\¹{\4N§‡0¨+‘Ë̉c GrNÖár=çÎc&_jów¾Xë»à¢Kú‚pm.«1·J3‚…AÅ{Ư„€wƒç$ –0XbxăM·|ö̃'3N¿ă‰·#œF¬k%’ă£rê8Ås¼H³Ÿ®‡½Åmg(3ó*„Ä”ḮØŸC6‡*₫`WLƒP]Ueó¤×^kkö#ø)Ơ¸~(đI$̀X '{RđÀÎÿ5#ÓWW`O¿,íˆ6{ås`̣ª‡ˆ]î^9̣j÷Öf<ïǺp4đ~i¬öËeeX]'UVm(’‚•‹¤º[‡! Í‹Qnˆ÷é,£ºCÿYäâ™=ez‚‚Óqéđụ̈–àïÎ[£C ÖňüÛösnf 5ù6–Ê9§Ơ='·_Fa~^‹@䨨Ñ `§Ă;î·b¿%n‚`¥ƒäåógLzå…̃§qÔ~o|8 ߌï#øfưdÈo1~b%7§‹ôë& ³›j‘*†äl ß¡:ÉqÇ›W_SÍ:3Z"ævú!! t³G*₫đ]ÑÀÉ ;¹èÎÊîï0Đhîđ9×ÅØ̉9/…=íá0Ô¢Àñ.—ûªÅR`u 50¾»°@† ßWwnøq¯Œ1·Ÿ±³üx/„wƒX}'„÷ĂÈ‹1Ä#·̣Bä¿M(/BH÷₫û“å„‘¹à₫4‰‘C¶U ‚ṃÈ`Ư…¹t‘•EUrâ)§÷Ç#2‚ wJä¥kSç»±qâÄơˆyN\‹ăÄM·^uñc§́.I0Y&b‡^EZMXO*;u²Ú™º‰ñc‡ÊÔå¥jö3U¿·?ø8¾Ăw3’beÉÂu_Î₫”ơ`})úSwa¹¿ơ÷gy÷ă»¢Á#ѦØy'1~.µu f?î }@NF®­ÜÍsUÜE:nFŸü-E›åÈá½¥‘æ:riø̀·P\ç ?c|³FJˆè×ÑÈkrMçÏ9́ aˆk®—wg/•ưúwU«BBĐ6´J¬W‹oÊ—y‘›ï¸ë@¤µKdó£(îÛ₫DÎJI€Ü•ÑjÜ 6r[rY·K‹)M(lD̀G,>çç¿|́SP¼Ú÷uÙsü´’pûôN™i2ú”2lđ¡^`Tä×€¸áÛùmhjX::Ëϯºz=̣&á²ơc,b}X7ËưùÛD¸¹§ûƒí)ß³[|ǦÊ€ƠpUË]1\Ạ̊̃-˜Y—à˜éÈ™Ø1 ­`/ă¯y‹~öX¸³ÉCǼTÈ1¥yËØ³Í;æ»È)Û¦m‚â.ụ̀èó“ä”Ñ{Á¼ˆ‰KЦÛôäø6ØsTÇ©v1j ú kZâ/¼îVTÄdDJ¶O±B̀Èr[7A ‡%ø6‚ăoÍUJxÂĂ~½.ïđ‘#ĐôGPøq‡ #ú›eĐo=ûP™L—_H&û£…Xaåư”höKLưèÓڵ˱,ÖÉÍưmÙ$Jä₫$X|ÎúoÛ°¸¹§Ûj{Ê÷́ß?{ ¢ăyjÄWĐYÉX # ̀­û¯B h×#—O–n’!#÷WE_öh,híÑ̃·Gw~̀W%HÔ%4•o’ü ù’–®6÷ö¤; ˆ)%* g¬Ø,uÚ”CîŸH"À1=¹kkqá üĶD@£¨M‚`‡ µ<öw—êKOO÷%ăÓLJ'&Nđ9N?~ ;ûj=̃LoKJtú¡Ù•ñơĂ*È—~ô2”Áº‘û³L–eE³|F"±ơ„{ZđÀ.øE«êëØ°è=Q ³œ~Û¿3 '·cUïîeöœR€"´Àr°IN:h0:4gæa¸íï‘p{à·ŸÆç6*¢N€¦¿·>#ׄ¡—cÖÛï¬%ẹ‹Ê¤ïˆCzơßïÁ¸†˜‚h‡–D¿ÏÚ ̀̉ƯĀନ¯(ÍêÅ7&|È0I.€b2üücà|ñá{aºo¸¿qúaÆÓTßLđó{÷î‘!·Üz ‡ nîOnO±Ÿ‘ÜŸ̉  ÄÏưñQqç^ØI-pÏo(£WqàL`!ïrŒSÓ2áq‡¾eAË́¤6èµsÏệ‹*¥W¯¾Ø;^E`rjl>özG,+ñ±€è̉/çA¿YxfŒmˆ€Ñ¸&0đ‰R¥Ḳ"¿¼æ̣¡HA`‰¥*·OIđ°`?Ư Pª[/ÿø₫=js{öˆda)³¬”9ö€½Ôg"ÀÙ|ºí‚sä£íé‘qCsdĂê%ơ¯¾ôu ,ƒà¦ˆïvpèAb`Í~? îïưÖ?ßñÂiØDNqqq̃8ÓD°V€1óTˆcMè4_t®Ué¤ÅĂ3ïËu%’3p@ ).¯*Ø₫—z´}l \R¼  ëÁ×Ë–Ê¡Csµ3´7 `>V@ZE3d–…Ù«åôs/¡?ÁÏa€•¬.€Ÿ÷]‚•È«Aơj/¿äâÛï8s´ó"]:eʹ‡î%y¥ ĐüĂs̉i}À=f.F†öH÷74[ÎÙ?Ç7÷íçwÔÊsO8rymUO`[³Ÿ›ûSñG‚@Âđ“á₫øV°vvh˜ÿI˜;›Œs o\‡°· ·)ÚC Ù•êÀ}¿^¿ ]†@¬¥"&:¡ *·,èù˜e22µJp²áF/½9YÆ î¦2ot_?g(`o‡Z'%:6EĂ¾©Ëä̃¿üíXdIđ“PèÖ´÷iH²Ư ƠĂS¶Ÿ±45UNŸú₫—³.YqüACeü¡ƒ#K j0—ß/Ù)q‘#‡äøÆí-{ʃ¾ưúuÇwüªx¿oöí¿úe₫âϧU5Ö×ÔvxA.oÁo~xMbó“Püá;£áÛiѽ“í¶:pAcj¼¿¤-—欻.$hu” 7BØûƯ×$ä¸3m3=À…)‘R•àö¨7û¼×–ĐDŸă„ă₫”•¥…̣ũF¸g¨8­ÆIhÏËÖaØ$†Aø2|•WùÙøSá±%´ Đ©ÇJ8ưÖAé ̃" 0Ƀg{øo†÷ÊjÙ¿ogÔ#Ă7f@Jó†9SJÎ<騕{÷ÏưjŸaC¾ôü³¥_ÍüˆÊ<C(IXđ“˜Đê`Á!*ÿ́ØŸ?ËưqúÓTÖxa×´€ÇZç¸÷Æ̣Û0ÛëvZ–@(x±Ÿ •SÀŒ|/¾ø\c ¥k_iÚ¼NÁH]†ï4sư«Üï3´%L¯û́A¡G]ĂÔé³åâñ'ËSS*Ơ$èthEw+ 0Gº ÓM·ª¦Ö·YöÎ8àđc†~ñÙT„€RÁFĦ8ùA‹Azreríªp]Ơ–ă>â–svÙ)O?̣·’‚u«IhHp¨|´G‚eÚ#Ï­/ ¹>ơ47̣œ÷Hd˜†ï|—ºâµ¶₫…;æ7tˆZßq««°®V|b²]˜ßî7¿¨\ź5b¨ÚÁé`E…¶ào{ƯüöÆJ:qâEó>—ôäD G`¦Äø…iX?‚̃Ÿ@T T8Ÿ"/\ùưï~s>ÂJ4 º¥€mˆáv?xëÄäÎ$(•+}ñơ}·\÷À¿×Vt'w·‘`&ÁP"åˆäöEˆ›]±ç–ûüß•PáƠ<°‹~»|L'HÁT€' ÜD“`À†Me›₫Û4¢lˆœï[¿>sµœ98Ă0€&A d{´Àw_óÜ̃oïSU €2ơ™úÑGrܨ₫ʶ•8/¸‡–(21¤iÄü€u%5¾¡c—˜Ô¯PàæÊ”¶ó•Nß| 0)ØnñœÀ¦ÔA.ÎÈçµạ̊=Íó]‘÷ø>•$”2<€FđÂNjVĐ"G[åúTe`®>­–0°H‹ ~¼8R€U†1ƠæÀœlñ'e©Àîƒ$ÛK¶yàܰ„€6&Á¼9e¦\phlùMÏ@r{’(c₫³ù¸¥Z)Ô1(’©_¬Üq߃G"­$V °À~¢ÍêÛ­OÎNÀøäàåí‘ç|!â&Ä|Äuˆk× æ9q#LGÉ€R…ûăô§< `ưæÀk0i™€çx>‹€ đ? }Êúíå̃xD"à‡ĂË’ü0h/,dÅö̃Ă}B˜á¿IaH̉X#ï99H°¯G$Ø zÆƠÎ5ÁÏç$ $|Ÿù0?æËüYÎO.|Ÿæ'×Xßæƒ«ê›"­‹RâM‰`jE$»S*ÆÙ̀Í“§[#ÍƯ ~¸CØÛsÖÊwÄtdâ¼g9¾zôưÚ³Dl:¹Wzê&|0WnCk~®t@8H ´ú×}-‹×o‘d(éJë–Z‡5&?₫Åk: íđ½4s¥<ñđƒô `¿²R@ç” ¾o_# X)²[)€¢üÄơˆyˆ}>"¥7èÉñ |ê 8Œ`¿«åpơ ß÷Gù 6Ù}2`UẪÅhÆúè¿8áF›temoüîîzîpwđpUD‘›º€¢¬ÜÛ­»˜Ï6”Ă©"‰}{Û7̉Ơ IDAT„Á>gYô ¤Àµß›ö¹œqđ^ÊưƯº ·à¡Äƒóh¬¯¯“ä̀́¤}Æ4 ÏỈI¬€ÓïH\î³ P¬g$AàĐ€:‚ D*I,8Öç;Ôö»E~w“ăÑO/x`ưæ¾–đ¼­{<øPEùd¬ LáßXL˜–€=»¼‰»Óñï2Ǻeeđ`è89H½́ĐÈ£ù´sb‰ñœóư¡Ơ—/¿˜+ư²_ÇE7µg ;3 pæ¨I0yaÖZùåµWP@às`u$ß·¿™ØZ`5ÿ¼ué%ài5h z›N½đ}¯·Óp”ñ§°Í5¸v |ù9„%L¹ö߈î)F©§ÜÛ¯‚¼•™›»˜,‚Us dî…ËÖÊ9Gî‡ÄØ_@ưđ3¢[»m߉ry¼oïé ₫đ™û9áü€æºJ™6{ôéÙÍxj:ûÖ¶G̉¥f(±ˆ‰/oS‰Œwü .=ûöFJJ$$$Ö"€Óïø! ““£ä»¼ôLç°½à€íµ̀÷¸Ÿ”œ;¸GæîPÛ- C`l¢¨&# a‘ÍXL "?tào+{r­UQ=™D±¤ªQ2zí%,ÓCŸ‚Ùư–9ç» èöh¶₫Ơ2pIe × äºS?›'×3DƯ!h ª$íw%r¨ßk‡#kª}ă>z/dI €‘ ¡ ưLđđ[‚› wG̃·§^ø¦ØY?Æ7•ñ“{V_Wù<¯*¦¬.̀¹ó‘ÿß̃yØuTçÿ¼í}WÚ¢]•U×Ê’mI¶,ÛrïÆÛTÓ¡!’`Jà$8¤ ¡0nl0îU–U¬̃vµ’¶÷̣̃Ö÷ÿ~sß́>­WÍ̃5!{G½mî̀Üyó9sæ̀9¥YÚ® „‰½Ơ₫øu«CLçÛÏ±é¯ W!B0Í@Đ8 "”bw<đ¨½û¢“\½¨º.xĐ'ếCÔîÈŒéÓr.ÛÏÔ K‚Ú 5!Â@e†‰hä₫5ù…y$Zà/®º́9٨Ǯ]s«›{miyM“½$ë¹r^‘)]8¶À¥KzÎ÷Ÿ3'xƒYDP´-ÚmÑiç馴öؘb̉¹÷Ü[ÁÏ“––¢˜Äd=øÑG³³Ï©rßkx|¸p…qRˆ%n{®:₫–ë®̣Óˆ@²f ư.ñ/‡á÷Ơ!˜ø–­ }¾“ÛÓ×qƽ£¡Û* 2¬B^iËrDRäÎZÎ@ñˆ½;\\{ăŸĂçí,ëi„ˆHk¯"[Åä•9G"¡ÎÏÓư;c‰÷±œKïYÀ ˆx¨Ö, ¢yôwÿu—],óáŒ₫p+¾ĂP8̣ĂÀ v ‚#,bûÚ"W\{Ư’’9 樸äi\€†D€ă÷ø!Â0ñ-@Ç¿ïcơAÙđ+`Î/́đ×åô2Kz¶+æ—Û) *$ ̀°ÚVèÔ¾|ˆ€³z«–ø‚%¸T ̣œÄ,M!º´dW%ÿ;ví‘2Öđµ‡4ă…àÊ#Á-$§I¾]Áñ\IGW}îo¶û×W»o@IZêG=̉Ex°ÙŸ¡ˆ—4âŒKIéLqUe¹ñiù¹Ẵï•…)=kù^:¯Ó0ü¾Z $“Ọ́|øcŸ¼@̉₫¥ĂqA¾@e–îî|~¯ưvs­¼É©åy+́C¯[aùZ×J³vN nd\1PÎpè²×_r–ưöÁû₫@€@} ÉQøG./̣‰ÉiƯ}Ơ3"y@ùÜù&÷‚â ôGYP¾=öù3U9?·Ơ‹Ế­ç.·Ïo-Ñ!9m¼íªógÿĂßÿí3Êđ§3R§đäµo¤²a˜øˆgçädææç=•“r]³V˜.³#0MËwí-Mv_ơ~ët½<eXƠ¼ ;gÅ"ụ̂gÙÓƠ]¶~û>{©¶]é4/glgP•ƠˆH<Ún.-³á̀"ˈwIx'¶]àe9o¼øËK"c9=̣OƯvc]ñÎoüµ½ÿư°ï>°^ÓƠAơש4gج’»pù,;Ñ4¹ån²o=¸Ùå±(?[‚μ{ï9ó"Ëל·pËs·¨Nȼ.>ê¸"[.ê†ßG „`’Z=ÚÛßßÚ—µ¼Ê<áT@đû !˜¼–ÿú™¿;íMç|1ζ=s$Ü€ơko>ÿk¤í̀û™[÷¶·ÚưO¶Ù½o²4¹ŸSV` +gÙGo8Ç*‹ lsm‹=»uŸ=²½ÉÎ:ë,Û²aơË—x¿vºy:jÂZĂÇw™§dºUX~9ÙptàÏeeù̉ÑÑ9¿’Nû…ù商h$×ܾ¾sÀ>uư*#bÛö7Ù~»Éjd°WZú WFoTJ èn¹P¶Ê²3¥Ø³•§<#§ hfog;j»–ư¦È#:†á5n? “ÓW9ÔÇ7ểˆüơçä®,朗öʱ)DŒU Gg8V‰–£eÎâ‚lûĐ5k¬²4ß̃~í·?úđCÈÖ(²qÇsLÂđ{h˜œFËnT;$µ]áIço%!Ç'{è#̣lăæä¤$À( Ûr ơøI3?0̉ÉëÿúeÇ/ºß¾ÛTï̀}̣WÚ§¿̣ ëïi3¹½væĂ”TÏ”ŸfdçZ‡ &èöêÚXt…ºÇ$ ªĂ1]£T £ä4çØä.Xbÿ~ïúÀ ¦.̃5y"k·L­ă;ĐWˆE£¶óà`ü‹_ùʹùĐKỂë ̀.Aôù¡c^ă Àä4x€"åƯ+_ltÄ È ëR–Ákè ó°0z +OFĂbUùŸ¢—w¤J<¬ùyvF¦uKÆ×(Đ¨È „h‚˜PèÈ5Sïä0RƯÑ› ‚48$×ÜBtV^¡ưëmÙ»¯\c™ÙyâZåÁ½MƯDÜ⪄†Ws°µÛªf—HxúŒ̀́œé}Ñ̃f½…RÓ¶ể=0NEô4 “Ö¢Ơa˜¤ 3§fơƯ‚z5Î%Î,Ab¯ËŸ¨˜#p "°ç ‹ºÉZàB÷ạ́Ô+½ư˜àƒßÁX¬O‚ÅØHä:¦ë>yÿé×ù€¼ùô+"(<<’טgƯÑT¾(!§€ùêwo³›n8ƯY ‚0À@PC8Àï\«µ­}–©9Å̃úø_̃ôY¶ Ă!½AHY†áDZ $'̉Z'–Ögoü×1{nÛF-Ïœàƒ>×Ü&ú{>G827º+oG´‘‡=ư˜ú†wl¸Ï`lj₫₫Øc̣¸.j̣ ¶…%Ÿ–ăiÙRi–‘æ&Û¼÷€¶LÚª¿óTä*«º(m¨Ÿê¤z6kÅbzNºÜxơF̃xă;OÑsØ~öÀ°Kë°ª~!løInơ½­ư©™é©̀Vàw‹2ƒ=Èơ‚Q>¨ˆĂ’î ¶4ÊBVƆ¤ôÁă€0¸d>ä£ă:’®¥ñyê¾'6ÁûÜU¸”l_}§́Øw~r·½Aƒ hpNeY‰u"Ñ̉×2ˆơtXYa¦uI`xÊâÊÜKßô¬Á@²½j0}1éKt†IoLnÇ_ܸùWYx­™‰’F—lÍÍåø¿˜ đdœ:`G’¾á0Í,‘Îˤ*Ăät:?¼ˆ G’`0¤WS‰.-Q̃₫à“vÍÙU"Ä'ˆÀȪ̉Ă¥àI¸¶i@Ä^Øßao¾îuUz̀È`IĐ Ă¾¨Æx­CØè“×âà(₫ä½·mB.@-Øẳœ4 %@ ª0HôÆ#ăU€AªKænÅhN.~LL.ij₫₫xø3² L †4ÏĐ₫ƒ˜d÷ÿæ1»ú´yOÏö8#}‹{KøY%èî“n€Vd!₫·½Y¬Ăđ;ư4 xÙå₫y-Z $“ÛÊñ ë×ơöàX2 h…g,E+H­@÷ñeÏ’(@ ŒKÂ#(Áå?œµ̉íƠå¹HˆÍ*/±₫¶: !̉6́³Ï~ăVûà•+ơiRMv—$Lú8Ôơ’ˆª‹¼x7vÚ>qÓZ]y"À4€Ơ€¤ĐU&½B0ÉM|`÷–Á₫¡$è.©œËR¥gd¹óĂ€9¦>#¯éu”ƒüµOÆÈ …`w Ûs)åU£ˆ<ùŒˆ„œnHÄ`U­>lÙü’¥ ÷[¥4ÓÅâc@4¨†B¡uú'îcGC‡ImXd0^ÓÖk—^t₫eÏ4€m € .ùª«¯<Âpœ-€ăl¨W˜ $ơ¤ÆŸsÎ<=°ÔÅ„lç"ŒQÓñÇUÄX¼$£ ÂCđÍγ÷XøÛ‰º$?s„ˆû‰BFk±üù"f*¡çƒ’°4¨Ù€}í{wÙ_¿~¥$₫Zp²¾'èVJî@GTQ5ƯˆtôöÛUW\>o΂%³UÏ@ ¼00$₫7z !˜ÜF‹Ă Ư} c˜c¹.O¶œ= ƠI§'T37tüˆíç Îÿ€X‡ä£{æAôŒ_NŒ´¿@óøóæYw›ă6¼Á>©·Ơï·ÿ¾ÿ»hƠÍóQ'yA,´iRw.ÖR 'É?̃Ø5`W_ÿ†eJÂè@'ÀúdHÔ¯E Àä·rä@sWu¶Ä₫‚c¤QîP A`¸WÛßưÏxx>ä=^đ Ùóq̉s‹\pHB½¡h0 p2xèQ»~ÍBm>ÊrSÀWA‚(qWw¯³~G@v5­=ñ·\ûºyÊUϰ$è…: ĂkѾç¼eMƠ2"½=»œ ô$(`%¹8 åÚƯư_û"€¤àAs{Fw)¡0ĐÛi?¼÷ »úŒ*'àÔBGØH °C[ÙÛà_ïéœsáù³+VÍQO<€, ́—ACOúß°¡'·‰ăiéé‘Ù9)OgIPúq®4æÖ}’Œ£!çFc1Îè{üU ̣=₫ô'’ôgÚú&-MuÇØ ̃c×ᮺ®øŸ₫Å_®P’±À ÿ—“ÅiĂÿ½iC0É¿<íÄŸ=ËĈƠ­9JCÖ2ṛS‚WR ›­w]Ư$ă'-‰@¹2)V' Đ²`¶9íû¿²¿{ûYp ‡ëAÿaX́NF‚øQU`M[,̣gzÿJ]x4™xƠ`Ot+ “Ù!˜̀Ö ̣ßtÓÿÛ#¶¸=ưÇÏœß~ ÆVĂƒĺư‘kú@*Ÿ)ñZ ŒL%8œ–¨Æ¬ë ĬïĂÎú G¸–±iP·w›mØ[o æ̀, PR ÙÁö¨¦Ô‘hDD¥ t֥לª$o‚ †a[ $“ظ>ë¶÷¶ÊøA]ƒ(w`äå8@`¦Ë§Vắö`@fÅc("?;₫óåé)߉ü0Î>G-‚?Á@…庮H¸§$í [ïzÈV-˜=a™Cÿ«›zå%_#z7x[2‚Hç@Ü̃ù®w-U&x.€ù«iW¯đÏÑ[ lࣷÏD<¥·§æ¦ ÿ*CC¾‚Ư-ÎS@à¹eO4$²;Ñב>.uĂpÆ`—̉'U.qJµ©3 Dú0,‹Ú₫ü>{Ïe§¸)Ó€¨V=nÁ»JÕ;ºâûø'Î̉€ è· Ó?ù¼0LR „`’vL¶©}–^ ¬à ƒđ¬@‚»¡Zùˆ zpX6‰$‡ƯóNJ rù»ïëèzæ¸}^xÁæ•äXv~‘Óvl—o„‚́4§F́êL¾zGE#ÓKsKgÎ.×}¿7 \ mæI= À¤6ïHæñ 5í½ˆd¦Ûa‰3LR3¤ èÜ“‘wFN˜' ă€9̃»ă&VZŸ™/áé¡)ÿŒT1îB,Eù²‚lt/q“ă0ÁÁÇüÍ-?·]ys[fC}̣#–R₫;. ̃=Où›/|ñlƯ… `*à§^8̃×)Y^m „àƠ¶àñ½ÿüW₫íÙB™Êvr½Ă–`”d”ðàˆẠ̀ˆ„±Xå~g¿dî©R¥w@ €å̉êáX[îûä¥y;Ñ…Í>‹à–₫Rl¹Ü—eaT\  {¯‡Ëͽ€€>- ª̃m¶WÛY§,tA¶Öw[f TZ½£̀Ù9Đ«Ơƒ•«N¯ĐMÀï—™@`›_¯³0Lh „`B›óˆ™ÅKgÏKĐ踠8Ë %™¨ÖÏórµ%X ÈL˜?ù3Ôdh¿)j¹:ƒCGŸØ2’‘ÇÉûÔ;© w¸v‡Ä¿ĂßơRÜh₫(ơc8DA?»û™/›¡iÖØÙoAêLÇ“¦€ek—à"M22̉XÇd₫àè¹7ỏuHÔB0Ñ-z„üäg;ÖÔ+g›̣Ä>ѬÍĂ6 ßÊç̃•ü(x<úsÍ»ÉáưˆI™$ƒ79ßqÏG1¯úaû¯'"¼C=!Èz:Zí?8}ˆBŸ|¢XJÓ´âô9yö¼L…¥™yA`̣4à‰À¸U o¾̣xE}ç•7%ßtIËÈr¼6æ±̣%üc$Ähf¦ÎÙ ("¡yÇe2èáG8h—’wÜÉQÿxpŒđI©ö̀%S]²m—–ñ\ưT^@08’"8º¿î&–…e¾\«1qϽ°ÁÍœfû䮨4—ưÈ"v®¶o©ë±qû¶of™á£2g@I®4Ă0-€ l̀£dOI¨Á ²vH¬đ,YÊa¥3̣´UV² œA Œj!Ao‡Q¤Àe?ˆá§]úDP”#k@\ü¹C¬ûëäc¢‘gdŒú¦¼¨K0½ử€ø:B°¨gPü²1`¨ß¾}ûoí +gIH–„ơǿy…¶©®[˃X €°á®ÈÙ€À pÄ`¨—è4‘1ga˜ À„4ă13‰?úă{Ú´Àq¤n–eœY…Ù̉áO‘½tËƠZ{¦Ùr¢ù°3¡î@ïŒ ₫£í`B}$-Ä%ƯưĽ‘4 Âá¡FĂ"TÍÇâBâPÀï2 ê*% ;¢&v_°FG`÷®¶í`³sºfn¡mø{Å ̃„”†\0 èz]Ï\):†a[€Æ ĂkÑѧ~X`a€—0•\;kùB«“çƯu{­±¡QKhƒÚ='IºFO¬é°¬Æ9zɱ́ª/ƒ±2¸đºÀc 2.Á ±ßëAŸt4«¸å”VZM½¬)øwưA%ruHLaRÜ €9Ç…̃RSÓäZl­ÛƯd,­°uó÷Ḥ¯¦H*ÑÂĐ'!¡… ×$“û'$“Û¾/ÏƯ!(€WGtÀª›{,/;Sëå+lH&¶Sú£öà–CÖpè íªï²hw—eK@>,ă,đîÀĐs̀. *¬&ø8 ₫Ñ%;ÏØt4]RU62z˜ádž©Ơ=SOĐe <–:ƒ "Rưª'NDæ”ÚÉ+WÛ…'Ï´Â’™ëî°=Ơ5v°cÀê»úe ·hùwd@.̀ø(jHŸ„2øÈ=u†‰lLdk!¯•gœé_ó₫<oƯ®£KnîR÷KZ₫Ħ]vÇ£½‹§ZYA–Íœ9Ó̃pÁJÎȳU%f?~¾̃víÛoÛ´[Jo»¬ kV.0¦€̉#hïê³¼éå2¼™fé‘‘ÀA¢BŒú P 7¹®Iµâ’©GFî å‡qt•“©) !=ÍÙöaï@-ïe–Ú™U¶`ù »bÅÛÓ“Áƒ6»ëévówŸ¶Iÿ5——Ú¹«e@Tœ?*ÑâÈÎÅ7½ơíeÿüïßœ¶ñ}løä_gRÏC0‰Íû½'÷ÛŸSi7ïỊ̂5 7ÑÓSÁ¾`7¿Wn³0¼)ă!V'Ï; -öâæíx9yMe“ÿÓÚ_¾e–Ûq·nw£=²i¯ƠÖ5[ÀˆD=';ËrÉÇŸLtPíÏ·’Iøwè÷\óø̀¬ ›[Qfơu-K² ü¤MŸgׯ]dK-´‹W.²GvµÚ̃m›́ñg7Øm·ß#×åƯÎè) ç"&Á¢ñ,y’i0ƠeˆAĂº)fî"I=KlX÷ÜÙßüÙ}¹ñêï&êG­Róä¯Ï_I „à•´Úq¼ótu»$ƯEöÄî–2³à[̣/̀N×”ùđ₫ ø”ă鼫 ºŒ¼ưíÖƠÙaÛwíúö毩aW¬^j.-µÍ1áhÈj¤`ÔÙ+oÀØèsƒĂË9r•Ge°¢Lm=n:s÷̀T[2w†¥¹ûë/=ÏV-,·_o:`›6¬·¿ơAû̉¿}_R;¹8rK*›#ÑYR~L˜&DEèffØKµ >„uQ WáƠ-½ö'o¹j̃Ü’Gß~Í•—Íûôtd*päOŸ¼â À+nº£¿¸e_SÊæmZî[R¯e?…ˆ³¬ëÎÔ«ƯH,ÅqkvZ`8º"Đ””¡Äü^DA7†‡źéÍƠöÜ–}ö»´{fz‰]{V• v´Ùœ̀ë‹ô»ơw/°'ïcÇ’$©x[¼°Xf³Ư²$£>Ë“‡Z{́wÿÊëë-#>`C<̣T‰{‡†á:¸AÑQÙs‰ÄNZÜ„ ÿx ^˜¨8îoíµsÖ½́@sÛ-«W¬xs}Í®=£Ÿ_pÙB6Â0A-€ jÈälîỬôÖóưHƒ~J}GŸF?2@N/OŒ~ºf.œŸ°›> öÛơpá+¯§né‚‘Ÿ½qÊ3SàŒuµÛ~ nßiÏüöWÖÚ ”o Ç™céƯíá̉àB¸ïkÁÈM=Ó5ÿÏÍɲ«̃₫Aknnµ̃ö.9À¹ØyÀN}Ư‘ ÈM¯/ s÷½0Nđw1U!'sÔ€/G"ñÜôÔ¬=Û·Üöí;ü»O¼ă¯ëu‚x…}žè†WÙ!x• è_¿ưÅz{ăªrÛ|¨óÙª²œ5 ]ưq$P¸Æ"Ow Œw«ôoåjü\œ+Li9‚ ô8éL`xNR, ³¯ 7³^M‡D4âú0’O"_ßÇ{z2₫†̉˜°Ï_ ơơ‰W₫:‡09¸ ’́}nª>|ÂÈ')ÑËI|Lđ=*Q Ơd=Hk:ë£o»úogÏƯ:ëÍç.ûK)dˆ½áOÆÉơeÅ„7̉!8JăœÈl“Ó IDAT£î₫¥µm½¿••Ỵ̈íŒú̀áƒM>n¬‰ ư1à ¸éûqđdäJ€œxù剪;2j „ƒƒ´I²†§!,̣ ˆ ¨Ùå<}†¾ü!đù%n;ăÏQ̀‹¤(¿ô@/w`̣́£,tD~|R ̣üùtÔcĂX™ÇÈKœ$–ư=̣”{º)?Ôµ«Ö,ưđº]‡V¯>iÁơ²²̃+!§–$xåF+ă3 ÇƠ!8®f:z¢çªÛϨ‘ûœtÚă}CC‘̣‚Lub<#}—%tØƯÁ¤›:.`WræäN1Î=ôàçA‚…' ùă₫‹›p÷¸gp¾äd:‚â^&;_z2™ ùùºb¨Uâ_̃ƠÆ•Oe‚ü\ÁåẸ̈̃ ₫R²/]̀†åJØhq¦CÁ§ïÀ+ôÄ́Ôye§oÛ_¿₫üµkWwÖïKí‹E{ơ" ‰T^i ŒB¯4‡đ=+ÉKÿàoĐz<0ÛÅ»¢äÓ¬c[RäyY>J=4Z€’V0xD$FTÏÅ'đêZÚ§OnöàpL†Uȱ çÚÇä<8?̉}_×±éùH‚ä"”¸7úÈ'=ªçoj<z5t²‚1DÙ7`¹Đ¾«g`8²´¢°́ɧŸ̃ºǿ+̣2³²Ø0ä÷ „ưØ7Ö Æ;Á›ü̃ÍMoÛÿîî¾ÁHVzJ8̣̉u¦Ư_Xx"₫ûô° v\Ă ƒƒ@*,y<9¬éÂc#82{d Jÿ'%$WWê…°O!™«¯p__ÿŒ*!„§WæËsV@„ø˜¦>"h́‘0³G^…ºµ´™)ÖiGCOdqyAî=?ûÁÆ3¯ºq®²H̃0öeßÀ'p íkl̉u5Ï]urÉmlèiîˆ;+¿êƠ„êܾ£ó @’ß*v¶@›ör%Éç¡H…î@2d@'Đ̣B‘†Àù舮—ÈTsf÷×=L¤qw^ưŸ‘‘\YQ/‚+RGÈW@‚:yîƠ`w>̣Fâ]Ơ*Ü>=¯œ–m]ÚÄ@RéÍ *!ç܃HäJ!‰}2#±IÉ̀È(xàgß{₫ ·üè%̣D€F…²†áZ $'ĐX>éí/Ö$O7 'Ï̀]Ư"_ư½R$ «‹_’''XnÈFêQÀèíÄèƯ&IưŒ™×°*®Aưd'€C¿WºˆËCçºvy$>?êâï·ww[Yy…#0·»L&?đ…ø#A•âÜÙ̉èU÷‰î"¨×LÉIfËÔ£¿sŒBOôƠVn C2åS‡"5̉ ]»”^·#½1ûë¼ăÛ·=ôä§+—ä¥gJqaT_Àç4ùđ^BHăüơ¶fûûû÷¸”ÏT·ßtí)¥›r3RK;£C‘L‰«£»„h\6ÿ¤+¯îç:°̃H `' ̣4úƒ‰tå‘.£GFPƯ‡8BÀÑ×sä<1₫JVNü O=áGxø™«@…=àư‘ÚQ/¾—`D·‘HÉ16wz–6E]WÉÄ̉n®íô¤$7S»»œ7eÊcZ¡<ơÈÚzböú ÏüäĂ?ùÔ@_Ÿ̀+j7Ơ¨‹ñ‘&sù‡ÆmŒÛ,‡ßœ.+6Ú¦?WªªëWÍÊûJ{ïPꬾZ/]Ö-úüƠw÷;·ßnάl|‡F¨å[ồ&q¨ÅrŸ“iù̉¹ÏƠ1;Sú÷n/½vØ%ØiÑĐ€Ù¬QB [.hÄF_ U€¤Añ™%ĐÜÓu\ꌣ€‡Ø‚–¡FËỀpụ̂s³­ {Ÿf-æ¾? Xú.ƯƒŒ5£}‰¦{›{K,¶ö!p”ẩÜ=` Ë‹ælj{̣¦ù̃åă…ƒÙ#Ơû¿t.å×ü÷ßƠØŸ]4Ç–«̃·vÎêvÙQDzØP'eƯºÏMÔưƠƯœ0KkóRû·÷Ưp¦gz™,9—)[mcJ7Klđ¹s¤ăRo™]=“Đ wÛưn]_„¤.Ȓ؈Ö£­C‹₫$ºwp9y}Ư“_ßÀ]'ú.FzØxOèư3Úgh¾®]„V2-ßU-q­Ư¡=LûaÓ×Dºvß¡¿Åa9ÎêP{̀];̉'"Đ);ƒÙéYZ â¼T¦V^dr1gÉ_}đÆZ_ÿ­/ưÅ“®‚A ¡4D–Aö: Ăh „`´-;»{S½]wj¹½T×ùÏó§gBl¾4àƠ£ÔádJG ^8­wu­ Û=®-aíç`G̀©¬I+GỆ́°#圱ÄFØÑBÄcØ>|i•̃_f5Í]öÄÎF«kl±½2ÀíéƠÆí±‡ ˆ 8\–ÈT¢›.P§29º^¸NâöqÇsáóL¤å’ogƒR\§,´Ù蓦ïr#¾T‡={²e`fE©-Wi—­oófϰ\qKơ1+‘K4ˆ¡>ÇÙ duD´0h<¨¾-O+%ÏUw¸ïñœ“t«ÜF'’ºoS%ø¨’XlØ₫éo>₫Ë«/Xóùk.9÷‰$́ṢPsP0^ Àx­¢{tÍfß“¥y YË׈ɘ¯ë¿cçQè¡ó†Kà:¦0-éö 3üIgÍ‘ Đjo€t¤]§÷t™q;ØÖç–q~íªÙV”=_ï[mK§mÜ×dÏvY F¿3 ®iº³±çF^ØoMđÈËđJ¥|)K7¨kâ¾»=æ™…ï¡Sep™Ăc¹;!‚e°…§£¬ŒL«́Ôt«¨¬´Ơ‹*́”åUṿ́én/AŸ–đ4e²z܃«l]î•'a5¡̃QÔT!_íĂ³N–üØ1X¤ƒ2 ×3”´&J½U’kû’Ü@i¨_m₫bÆ[ºcvÙk¿ôä¶Ú×s̉œK̉Ó3³ú’5“¿Øî”=ú¾0e`¼dgË;Ö̀+ü‘ú*Ư/‚¯{œW ¼ëƒ5פ¾éB¾¬û¦ ‰íÍ ›Ñc…æø˜Ç̉FYg”Î Ûë,èèèXçDZ̃…fdƒ€Àö0–Y*d'ƯºÚÛ¸ë€m«i°₫˜ê 8(Ÿ…sg[$Úf÷ứûÖƠ£rÊ®¾¹@}H 8ó÷ư¹jëó„g\Q7X÷œœl»êÆ÷Z{‡¶$oÛá´©/!8[N}ÏYVi+O=ÉÎ]X*k@Ú÷/%¶hŸÊWJ“!Q%==øÁẉ­æD̀÷ $û˜ẀôƯlŸ¶ïhèu܆»¡Zi•Ụ̄\×ö="™&ẼE‘ND˜( Y¨t¬/ºÿæŸüúíßøË÷lïí;5ª9è?8È~ ÿơ}a 7Áè§ß±ù¦g\zqUñCŒú€Q›Î 2h¬Ăcºh³5bè`Ëo°Q‡{,_ƠÖ7ÙOn³¬‚ivVƠL;}~‰óÓN₫Œâ°ñn%Đure¡#ÖwQv2uUä̀g#,ÊN·g$ß¾ïí®kµ²i…6ØÛfƯưsëî‰:É›H“w@`ơ£ƒT)2§‹đ`dä̉n´ní8¬k°¢’R»påb[YµĐfåG¤Áskô°ópG’ü!LA‹Ä0h8'MÔ™úh|"ˆÀ’‰°­;÷Ù£[ö[Ê@¯}á×ÛĂZyÉ’bơH“À‘QIi#̃Ê2„ ¢‰Đ ‘¡‚ 5}ÈT[e«ŒÖ˜ưÛ·¾sÖ¿₫ÍŸïQ±D`Ê‚cơ~Å)ºûöÉnÿ<¤ôp̉.¨“×P~¥ÎÆj@§ÔƯ¨&u₫o>´ỢèåU¥·—ÙY‹mqe…4»X`–’‹ØÖ±¿̉qqÄ€y6:ù>|¾ˆÁoë?l±#Y§çˆ h债lë´––v=SJˆ ö£•ï@7Æ=‡(_e°4Y6SFf-˜áT´̉Ñ+¹rtŒÖ¡Ê„äB8<ú…R€bêĐ¯…OnƯoÏ¿´Û¶ï­µnm3Ál?.1ûÚ§?loo”¸+6U)_Ú÷LỸ-(:uBG¿I¢i[ß}…H$5^5#'̣ü–Ư¬9yñ{ơY@Tj Ơ¡ @@¸wks¤47í’>Ï«ë́‹—ågFdÈöơHÁsQ­MO“aÏNº– :3D¡¡©ÍÚº¢Ö©ơjXzüvÆXSc¥=#Î 7וåÛÜÊYvvƠl;¹"×í!¨S¹ư¢$ƯtÀV̉ ¼N±ÁưĂ}V—n}Ă²̃S4Ư2ô`”¥wƠ9́OfÉŒ°ùËü+‚¶êÀRßœ‚TÛZߣY W› Ă@`†…€:8¥(V0˜ëå¤ÉÆa®F́~ÛS{ÀÖí8`;·o³ƒmÖíq½~¹g#ïf‰#`âr@BP¹ºïV—æY¸¬đë9ơ'€_çAî,,É<º§U‰f_W<³ª»åPw(ö$z"¸œz‡$~ó«—•Ä›»û¾ä^́·ú¾cwF[A›dÅ’n7h]¥À!æ˜̣ỀWTsr\eIíÅRcë‚íÈ" íí¶io=ôÔ&YN·̣Y³ị́Uó́ÂÅ%’9 ©Ó÷iN †Ü̉ÄË¢lÍ…˜!đï“P¦'́́½£ß ơ½u”3à‹‘c±ßY¶O,µªî¦$LK°T¬)·û>F́™E™’à§ÊS=¿Ù[¿Ư:Ze÷PDM#?v Çs†@Đˆd/Ó–^4©=Ø KG3·CùxQÊÓ·²ÁåF÷}üD‰à‰@̣w ×JđÈvé†îá́¯₫ó¿|à£ï~«V”áhàGïN¡³èÇ~êà€Ơ64½K,»©;Xöc%G¥ƒu‡pN8¬ZÁ­ÿÛC ß÷ÇÏ\©‘¬¼Y !`a®Ë¾~–ùº4ê‹(¹ØưA›®+³´Ñå§Ûºe,”bĐs‚9u/ôƯÑÊ¡‚ÎOÿÖr_Dvÿbếyë¼=±F{¨³ƯܸĂ]°@̃3»íÁ_ü–ºĐªc B¨Åø)B¾„pE9R?V}HIÑÇú.—›³NŸ‘.uå‚B{ßG₫Â>ưOß•ùo:±ơh/öcXsy,ø!8VưçlY₫$QUÔÁy¢^ªg“„™¨C¨- ¤|q µOÖUø]ÿBÿ î;ồeM]•„´-%ëVdwS}́O?|Ư—ÿê“ ïè ±AI– "àE¾::!$ú­³̉µå&?ôưc©®r̀m«»ĐÙÀfăøs~q¶ÅÅçk# ¶ú´¢¦Q«¸½~FCÏ#"9'–³Ü «G*OÖÿcIÜ5]́1É ¤đfuyîÙếÂ6“_r ¾₫ç€ p¹:÷áx ú YỴ=—kŸ¾I²¦f7º÷Êå3—ç» fT…™º/ß—å*Ú‘ªS^‚È đ́È“̃“îÚÚù…¶WNFœ²•^v¢©=yä¯21LJ¹ Ål<Øéñ“ú@-£F®|Û{×>pë"d~ÀB'@̣‘,u>%BHô3¿qỜîƠX=_— Ñơ2æếôC[ù,a<À¸¹¬{ª=3ú]¶ú$+-ʱ'¶ÔZ³F´)Çô‰Cpz₫ÊË͇)yÀ(Úƒs8îX–‹§fX{ưAivZ+Àààd–ø ø]f hä̃h¯ç¶/ß•™”ÿ~™r`ï‚ƯíR¶›?¬Q¿_Î>-ß#Éå©rUm×vè= 1̃†|6 ¡Bœ››c³ÊË́´•§Z¹6ơH©ÈG¨œ*F̃A]GKåơaä#­&R¸×ùîiè!ë¿À_£›ÓÛưÀ”] €zlKE6l½ù”YÓÿ£E£>̀-?©Wµj×É®¨m“Ÿ:®bÀÈKç.”0,Wj²M·¾x¨S`²• fÊU–ÔzƠ½6KigƯ®z{©ºÎb̉ÖCàå$k€…g¤'/\jĂе=èé÷AdDăw»Ụ̂–™JO].7́úÁmT²™ŒøE­^7€" /S&„@ưI‚ÿ”‹ª*₫«·à?»ƠXgS¢ƒÁV¢^æzçt@ M—T UƯFY«9Đ®QQé3ô]0ú¥jĈŒ”th´øØTsùÊùöƳ–hA¿dÚƒöYg›$éYLÄ‚]€N ª¢üE)a®äư=p¯Ae¤+)“ˆ.'$¸<]qú®¾±́iªŸTu%pë&|«êlJsjÄÙÚ œ!™‘oË—.´‹Ö¬°3–̀t:-²Ô,yIgS¯ÚC~Ê[‰_!Q~|-;H7£N©­ÓZ™9¤ë˜¦JâG ±°î¯ÙWR[ _^–c_ÿÑí¨@̉ßq èsGlxsbÁ¯nL•€à—¦§¤Ÿ¶pÎg†â´Sn¹ñk¯¾ăØÎ^ơª2ơL`&ÿ~nóI½Fü}-Q7âđÄơVßkt™&O¿ñTéú;0“Đ3æïYRbdG– Ụ̂‚r{ư •ƒçw°û7HnĐØ`QͯqúÁî?ḷÓăG̀gwJ‘éÉr}:?!øË™«'Çö.l<Â8–(Ó†{-G̣€”t硘2ØÿŸ!$ăM8';[<Óí́•'Ù™+–ÛʹÅbăcV«¥¹ơû»¥Ó€±¶ kÖMT?€´¥8--—ºú¨}à»ÄÙ~½/+ Ú4”­eˆ, ©}Ô6jw6ö¸©̉,¡½΅D42#yZưøê§?Q£K"€÷ @kˆS.„ øÉékƒÑµ-»rrsIW}.Dˆ;ß́Vciđ‰}mN%•µz”ï\ϨéxNL œ4æ»kKÎ(ºø.6¬ÎM/̀wg€°kƯ₫7˜]6;ôÖ™ÖÚ±=ûÙ³{[¬ú@~]®C³=v0%C ×ÚJ+‰97aË)ƒÀHq#ƠçÁq†D6>;÷­à4 Ó3-K›ƒ %<Ÿ[^dṂL<¬é +(,¶…ógÛE§-µ… æÛ9+Ư§ùÔ!ô±]̣b,M>T¡aÇGFyrWæäïếÎF¿ÁéA@†uÔ9íÅVa–mN̉¼>[ L¡d”Ơ2 À¯¹¿Ø–“Êó́Ö;îî¬;PëƠ)•â’£¿ÇqJ…ŒvYíHK¿ùŸ₫éóßüÇ¿»uk·”‚R#p߸î.,̀´ï<¼U 8¹¶|Ît sdªO£P°̃Œî?Û‚SP¼Ä4Àu3:¹îû‚gPÇ$ˆAzbª€• -‡¤'¯M=%’¼§²L£î)Ö¡ƯxÏï©w‚Äl-_OÓœ6·¨@Ë‚xˤ%l炈›F̃´́¬l·Ơ¶L~̣§•ØÅṣ́Ó«,='_óơˆíḿ²Cm=Úÿßëæ̣ÚÑâ!’´ #¼o ²v#>'´‰ÄMe0BV¸¥è7@yÓkLfæHM:jå¬t™«4üǹӲUt$₫éOƯT£Kú:ëÿ°ùHư‰è°dÀ=>–8¥‚o¯)ơÑă|,ư“‚³‰’¦ÎèÆ¶ØpĂ(ëÛ›tŔßîzVÚy}nY˜—­7ĂÎ\6ßVVäh7^4P‘UBE–M+µƠƠBÇ%(s×à ®@—A‡çD¥@9FUVt¹£f‘v₫•IØU¢-ÁOj“ z €c²z-ùºú&N†z;m8Úa眲ؙøjÖ₫‡6¼ôíLoعÇ(¨Ậ¼í₫'^ÏœG08ĐĂꫀ࿾?°„p Q¨Xcl‘¶#xd{½=»q»mÚQ­=QË‘pñ3z›½ =µ/írÅ̉b»ă¾;ßtÍ•/éSø ¤ưH₫*îUÜ£¸_á ‚@ˆ‚Z}ê÷ûNÏ=â—̉påNBü“_=ü™KÎ?÷#m=ưqí́‹j´½wĂûƯó[´³ç›ä4ŸÇ–F½¬¼B»`¹Œc,¯tZ€r êÔWÔƯ¦¸w@5ưר¨ €GÁk×ơ‡Q[X *è–>A-V„t툆K= \=Fñ€+È9äI3rÄw;À’@ŸÏGzỦ5ß02Êë»Ư7ñ­Œơ¬¶„n@Rüµ9¿ iŨ÷â>{bó^Û²e›tødđDDóh”[(c£^t]rú­ÂÄd3!°´¼¨$Ûh ±rñ²Íµ»·a€Ñ%¿fE@¿WpH¢ÀA¤~j€p  _<èî°‚ƒ÷ựλ̃pÅ…iê‰EXúËÖ6Ơ ;j¬S¶₫º¿:_wJŸÓ`˔퀻ÛÚ́̃'·ˆ-/²ó–ͶS*‹­²´À ïÜ:ö3gỊ́˜O‘̃¯¸ 1ĐÁ?…Đ5£h à#8 -£±ăđ œæK€ælÂà‚tù7.aæH ̃ú‚x•  ƯZºôåS É8ÏƯSºäÑ]Îî÷™·C¼úơĐCP‹ÅÙkC_ÔÛzÈ~±u›­—Íi¹UvVâúœ¥RœŸ"Ö’é¦Í[́µ'‹cˆj"c,"Ró‹3ă?¹ă— đlFw¦Œô,¡ ä5™¨V.ê0uÂ$v?¸F¤- ³D”µyÏû̉s§­B•Wœ¥}₫û[‹¬ööhÙ‰<½Å³ønùK¬/K`,¡3®Î™›ŸkKç”ÙÅå:– Ûæ῭‹)O¤éêôèû|÷C@”/Áî~p‡iÀ2 ´¶j…+Ä”ÿZtWWN¢ Ñ:I×Au?¹<ß6J鉽´Ua½@íø_Gï>Z’€;~yZ XP’§6˰ZYzđÅƯ¶e«Tœe`0&ËFJÛ§•~§đÄ.Böˆp‘íÅ¢i…yö/|È^¨ës«4+gçÙ̀‚,+˜VübW{«Ÿïü&ÅZÅ}pL0>!˜’D äôË'‚ë§:È̀ÊÎmصñ›«Ï¿ü;ưĂéöí_op’eơ?׉ƒî§/ÚyØFÄ–Æ´ư@°,Ö%bÑ*K=ë·ƠhÙ,Ơf”Ï´kN¯´Ó$DŒ*]½ÖÁÛ¤¶:B 4ú{‚B·œ•àHḲ̉dK_l¿@‘ £ÔÂÁ$™¡¤s*¨A¢î¸Ck—CT?øÔàî€ —”iPD³G#7¥ª¦çj©0Ư^·Ư¾|ßÖpè uu‰°ÉfíÇnB›‹’3íÏß ĐöÔƒ{?üÍ‹vƯEk´ÜØïÀO’² ¯åÇ"ÀÈNÓ¦‰ Î2 IDAT8—½S*„àđŸ›~;(×Óơy‹×|Nsÿxwl0Rß"½ÔM–'ơ¼@‡?è~'‘Ûö*¾Ư|(ñDµ”ÖÇS­µk¯U×́wÓ†…s*́ôªYöúS+ @˜ËÆ’0F4±øƒ?éX®ghî¿₫€Ô]ÿ8×e¯ÿ$]‚œP-ÍÀ¥yµSdÅuid¨13: “Ná‰é“ªn%ºä8{}÷?¿Í₫íÅ=v°z—S/ ́Ø À2=mËHÏÇúÑ̃å¸b:˜ĐFÔ›‚Ÿ{Û…Z•Iu§º5Ï{̃9í Ÿù4ó{@Î(è?S)€º)#?¿{̣Gêrj„¼üwf4Z^“ÆY…•SͲg¶ ĐbGaÛYDŸÑØwÖ˜®Ï:¢¹2Ë 8æ¬TcÙÚ›u›}¶m÷~ûŸ̉m…Œ….™3ÓÎ]Z*vX;í´´ˆ3LÀĂ´b‰4Ù6iiĐÍ}ÁÅËëü{¹øF¢†‹\•i¸$́÷Í•ËoFæ¦ön{zĂv{́Åívh­»Ó²JŸæóư ›¢ô`èƯHï3ñUèE U ÊH)j˜ÀA–%åµIíZ ùÁ µ]¶vA¡t‚åٳϻ¸PY ü#B¾^08eÁ¯¶pK_Ă´ØÿĂÏJ­jË=§(Ë*gL·3—α §×>ÿ‡Ö×XFŸ¸IÖ¦Ư¦O ttÿ`çƠ‘ƒ¾¬ÎàúŤÀh₫êV$3xv[Tæ¾ÙO¤Û —-œăä‹¥xtHkƯ°ĐÅ£Ñj&NqÀœy¿¬9¢!ÀN\€Ó‘8]–ÎWè–ẀÉ·º¸ªƯoßúÅÓ2ø¹_fÑ:%±—ÿXÖ^ÄBŸå„y´‘«¡«¤j¨|èU€Û2́,/²©H²qSCRËÎ,˜nW³ÜN_yÍ+/–ƯBƳˆíỖ}sạ̈s× îK®ϨÏ4€s¯àÙƯz!ä^₫›Ç/?uvJ  K‰ |‘6‚§v7 „|Ínßù³¥23µÛa›¤œ3<7 >“y++ˆøàQ„ €̃)·(}FÁ^gøCK;Ơ‡ZíÑu;¬tz½ụ̂Ó́…gµŒ=Ø̣̣ZáNªœæ¦e ₫>ÁAߨ§ØîFÙ9”<à/¾ñkd›rW¯l0Ÿï×Z=;1 ¶?ëĉh8ªah€q€ir·mØ LƯúƒ fÚ•çœlo¿âkë‹Û‹»ÙoÖïQ]öØÍï:_–€´H+Ÿf9$9ăâ«§?ÿđ½ơºà>²Îaư§4øơư!@#Œ ñ;ƯÙô©7–i«‹¥5_»°ØvIúÎúû“;́7/ƠË¡g†]|R¥ƯtĂéöøî6ûÍÆjÍïke C;~”XاÏÚ½7–A?÷,®ïüô@¨Ăc/ *“Û̉/`ơ¡7s~ ¾ñ“{,.Øf/{Sç#_:%€¦Tl"¹°_"[ÚË—/³%§®¶½{vKO¢W6 ¤£¯“gNQIÀ÷ß°"A |]œ…"Ơ 9 £néđ̀Å"°6(Zn^¸!pçp ªËôfũ#éúé³s­qÿ^e€`÷?¹̉\?¨?erü.à•?nËÖ2ܾj»ñúËíù£"Z1A<₫°Vïª\_eâ–Ovơn>Ÿªy½[Jôz>I·ù•åví…kl±öhçà–Ư5vËOÙWÛ´]XÚ( ‹XĐfÊD«+ól{ƒ̀–+_5¯t ̉â?½ë^~_uÔÆGMé€q~~ù“KßÛ½ë¢ÓD†" 9wá4ùêëv‚?ơë‘‘8C½æNÛÛ€#ˈ”̣́º3ZÅëNµÖnûí¦j{lói¨ÉQ¨̃s~ư5ê»Ñq„Ṣ„aZk—!Đÿ~|·`2lƯUŸ́ï±̉0”€̃ œø?áá0jsxƠÚö‰;ªéJOôô]²~́êé̃ ̃ñ ÷B<¶#àdN¯2s–n‹UÚ¥çœnç2Oz₫vû[́çOüÊ¢½¸ S›ëCSµ•!,@O‘°Í¿% æ:› »›ÛÜèA=snQäug¼oÚ%"¤¥&£µ”íV À8¿—œIƯY5÷½í»Ơɉ·Å²N;O‘ÎL ¶`‚½ơú₫‡Z»íÖg5IU»ơ®[µÀ>xÙ {zwƒƯó\µ8 b ?¨ »÷á’ˆƒ–‡àÔO™S`mûåO}#!Á2c@ưáA¤ăå7Ọ ®Ị̈đ20ÊNÄXW‡pØôắ(©¶'ˆ€•gHî¬C„CŸ(9@Í]r’]{Î2{Ă¹§Ø¯_Øcw>³Ën{x½#pªMØáĐ«{3¥ ™'N ?7Ë^Ú\{¶¦Ăí¿Đ'ÆKµăđ‡¿¸³½­©¹>¯éëpD£è†qZ §¡­ç¡Å³K5ă»®±Û̃}f¥SzÙV×iÏW·J30ptÍ| }s}åjÔ½:{£ö£'÷9-¸YỌ́́/³Ó*ϱ‡6ÖØ}/T[SS«F3‰ /PÛ̀èH»#v̉œb{́±íÊ.XQ ~̃̀¹+Çèxóçcäy¤gc’÷%ŸÈèï¦/Ú”³r:»ñĤơ[úTt¥ pöÿ¿F{vfËÀIË—Ûu篰 Yª“E¤_=½Ơ¾ûËgœ¥ă®T_€Đ̣ĐÖg½·•©2²³2¬b†l.©%Ô2·Qè×ÛZU¾SS,ŸShלư±U 'O &º9’Ëøƒ:9€#ÿ\)gWÍú|{tøĂȲ4z1`Ûé̀Âl{ÿyóœÉ¯íÚA8и³v#»‚­•7 ơ=v«ˆÁŸØgKË íưW¬t`ذû€½°ó í>(}•¡~¥VߺRÄÓÉ·V7:ĐĂ2³a€‡$qæ.# îÎèŸÔ1iGŸû̀•‘T ôwæ°ô9̉•₫ÅÆfË+.×4 ÖrÄÔ%.I~NA‘TµÈ̃rÁr›=§RÎCvÙ­"lê“áÙ3Tp ,©( ¸…,ŒŒp”ÁĐ’"[SUig/›cyÚ„Ơ"£*èl–@â%ưyç=u°îOÍÉ”ˆ¸•EI_¤«)B0₫O‡¡“Ä÷ªnúô¢3zµ®̀öÛY² P+¥—ê--+Åy‹‹å¹§H’ÿ¸=®-ºjÛµw©N^€±Oç×u9Fwúh́°ơíØ'UÙ›.8Ơ*²íÙ=Íö¤œl4Èf`êĐ€-«È·´gO‰:R÷‘›Èï¨C¿ÿ¶‘—üWp$$đóñSaD– °ưà.™g»º›­µ³ÇrE ®»hµ]¼r‘ikµŒ¢ÖÙ·Xo‡Ó<]„= ̣ư'çÈópĐg̣­*¶d–´`WU.Á^†í½:ÙÈT;B$æÉp(Ö€0 ¦*FÔfñëÿú¯kT[ú¶_îC€s¬@üo¬Ó©ûI§n3¼́ËNđ¡“ơ[ßsÚ?₫̃ƠͽÙØ›iRÙÅU7₫ê°[ß"c–b¬à”J# SU‚M´t§Ơ¶íöÁæ³.—ç^8X–Ù±¢<»̣är?׫̣óä èŸưº4ƒ%A¦Ab½ô*B\ù u‹ăÎ9Á<álđèËRÜeçŸm¥• ­ ³kÏ?M@íµ;ßl/íÚo1 ñœñNå, ̣ÅØôKHÿ5³‰*[=ˆÊ‚y³íÜ“çÚµ+g;"zPÛ|qGÆö`¬ă& 7iø_ÀúÿÅ8Ë̀û7?Ûù†«/ߢ(„uVp ºWqb"ûÿQ öût:5ư/ /oÚÅï ,®kïyQƒy©›:¬©Ó±%, Vbw%°̉K(±å·r{Ù³œGƯ µmZ%èR§ Ô‡á Ü^~z­º)̀<ÂÆk ÓU-®(°O\²Đn[/E#¥agóczơ« îĂT¿YNU÷Ơä/ê‹̉T‰Œ¤ËJđ­Ó²Ç7́²x?¸–éèXä#èrFoÇ̃K ˜#RRZl¯[5ß.đ••³·¸_ §=14B½ |?î ¾¨?! Œ‘°½ø̣¥%6GûÿŒîÿGëưÿµ{ñ€́€8À ¨bS7„S€#ÿö̀é =÷?ô»[®½ệ›dÅ6.£‘Çv5¹¹ë©ŸæhîÉús– `CÙL¨–‰ê½M2k­zQU‰Ư°²Bụ́1{dg“–£N`P‚2gCq₫Ô»étè]’+ Éöư[a½m̉”¶¡$î^4„hœY€ĐW‚gRĐ=²¤»G=E8—¦Q;OS€Ë.8ÛRs‹´›Z mHF{0éY2ô G:+;ÇTÛù§Ê'ÀâYÚ,”¦­̉=¶ñ@»œ‚º¹½²w@6!dÍ—!’%3̣•÷ –^5 0öbyuAI¶ÛÿŸ¿ÿí’w² ‚৤9±†Ó ÿ×BHÆÿEéD׃ï¾ûî_¿ù+oR'ŒgjTß{Đ^ܹ_V|#ÚÄSngUUØÉó*Ô×l¯:fŸÍßT´ŒôƠÎQ%ÖjŔ-§ÏvÀÛ,µ—4M¨i‘“¡e`HÄẠ̀AÑp›j;ܼúÅ;µ‡^üªfÊ.ñ^qÿƠz!Dà0Àëâ°ëD1₫0Bx\º ¥[vÔ(̀(_:ÛƯuPuDÍXsz\~e ü3‰ddËYÊ ;mé\;gñ g(ô 6î́P[ ùÈnK₫aOˆ±ÔâÜTÙAÈ—c!ÛV}ȾöĐcvàPåIGâË|ƒÊæhú°¨47²æO>Xí ~7æû°!l₫a0–•Ôƒ©Bpä_Ÿè»ûGßÙºå¦O=^XR~²© Ơ­‘fy¯éƠîÀ`¿ÿnËƠh4n¥]¹ª̉.Vç–"‘9¹’!i¹=G^Rg>…²pĂi3eß/Ă­a?#‡ZvÔ´wDïw٪ųmÓ†uv/ºnPä¿z!‰;àêÈàâô$9~•ü$8ʽOúq0̀í£"`—-/µß=³ÁÙA`äFЧ¥gK«¯Lsúùv¶>CäjÅÚo<Øå¦p¤üR»¤B {_U+s_Yö؆ö׿øµ5: .H+-†"wè”Ö!ëư½r°´,Ă¾÷³Û;Ú=¿s{X|F|ÀO„p줇Ү~–nM­€£ÿ̃ÀMÓ€´ÜƯ»÷₫ôâ9sÎS猴uÈןÀß-aĂbsÓ´Å·3-¦ư₫;mÛƯöớ\»ú̀*[{̉y¤I—Ñ̀˜uh³ŒÄ–®?̀]»äêªCVov4ô:SXï[[éj²¥¡ÛƠ~¶ÊV‹ˆ\ÚB±Ø̣]¡÷b}byƯèä|´â®';iºÎ’î¦xơgL7ÆÖøQËÍΟf5ÑLËƠ₫ˆÜH†Ú#Ơ¦Û«Iz¯‘^œœÑc»[E,Äéúƒ́îùÊU¸Ÿ­Ư—÷¬Ûm{ß#¶O{ úbl,̣̉«6Á)Q,Y’ Ö~³½QÓH¤JÂEŸüxM¢~hëyÙ"k”Ç¡§åă›Z;gû+@đ²áÇM‚#lwà^ V}²z6£½›¿ĐfjYÜv£üœ%V–Ñgg­XbËf—تe–-‹&ƠZ!a%‹A(é 3•}q9ZÉËL•ND®@œnO½´Ç¾ơÈÓöüÆ-uÉbR`]i@S¿©ª‡̀îg¥=m ñ3—-±ïưôÎÎú`ƯŸ7úĂ₫ưI;åư' GnÚ©s'ơ“ú§3W¯zç}Ïï°G66¿°Ï]5pî)M>%F¸æv´‰ïÏÊ*rÁ–̀•¼@;W­/”ñÊíZ¿jn‹ù0ŒhøƒQSØ%rv‰ưÿˆÖĂÁ^“V¼²Œ ~8c³‘ 'H d¼âËÉxœ“ät¬ßg!ø”ũœ,M]†D½ ỒÇ‹I|êÓÓdÀc~I– §fÉTÚ{në>{qóVëlmÖöa©k¤O= y…³Ÿ đ3ú£₫[P¿â’ "ï¸ü ;iñ’MơƠ»ø~–÷°óW«¸WqŸ¢·ư‡ö”—ü« FÂñüæ#‰§è xÆ>ßơñÏƯđßøÎƠ§¯\öØKûă·>¶Óº[ê"ØÜèë”aôăƠq ®óUƘG¦F¼¬t±̀’”–—Û r†ÁĐ6ÙØ+Å"„g™bŸT‡¦añ€̉˜©{Èươ?ePn̉ƒcœÊ£±T™œhÈ£~8@Å%7Zp6°,aü“Ớú§‹îmlµ;¤ë¿gÇVÍéÅ̃Ç´{Pœ Û‡u å´›€O»‰€ff¦Çåø#R¼~Wü·ë¶FzÙ ? ¨‘›l–qụ́z %".²³ 2ÿÅ|ùÜÓª́| Éđy‡…4 Îañ¥r…‚­‡4ˆé½Ư…$¼¿RæsÂA¯̀“w¤>­ÁµüT€ơx$øÔµX#ơœ¢ Û §÷<ú¼m߾͢]â‚‘>°ö‹'ä€`P ×FƠF̣5ÏÈHäçåÅÏ9ḉÈÚS—Øêy…Ăÿ̀—êïøñ÷›:êơù}˜÷3ú3Âûuÿ}:'PdƯ™iFNçS>¼‚_~J¶2\@â ÅJÅ…ó —œ¶¶êÏÿê3K/\»&/›₫³G¶Æ·í®‰Ä¢rbŒ@#ÜÈ!ÁÀv3Å‹P–¦ " Ùœ]¶r­YTaeÚ<„ ỤFÓ3* ́‰=í꽂¹®ơ€WU £’‘[‡¨‹kţؕpÏs*³¤̉Œ3ÎûêíÑç7ÙK;«­»¹Î6‰½ï—y°8$Fz÷×c¦L8ƠH¯zˆăÑ>ˆ“O>Ù®?o…åơÄ₫û¿¾Ưrû=÷wÔl}‘ù¼—]‘€†bB x†ơŸÅêÄ1yô‡PLdÓ)»?́ô“ÿaÈ$×₫N§ĂÆ\À,ÅysáJ3³ó ̣Ë+*̣¿₫­o-ºè’‹ ï}₫@üñ ;"Ơ‡¤7‰aă]RdaÔ£'2À3êa,4Só~Œ‚bA¸¼¸Đ.\¹Ø–/˜i³ B“¬ñÎDöàˆà£ư:Ó(()«>øhÁuÍ*dñ7¦ùOŸŒxl”ẽç5§_¿I”d¸ƒ¹¼³(ö~ôAíƯH/)KzÎĂ’d 9ÓËíä%să}ÓE‘Cơ­ưwüüZñ£4ƠVïeô¦J àÉ„#€†¥gi)?s<ưÔ(V+Ö)2úû¹ÿD7Ÿ²₫ĂîwüĂ₫„פö´\ÂÀ|Å2EˆÀlE@©b¡¢s*¢#Ä"íÍứ¢¼í†i—­==ï–6Æ%3°₫Î; ±Œ‹qááÀl˜̉»‘)Ó”Ó(«%¶-~ä-—Ú÷¾ÿ?ÖÖ̉$n‚ôê÷D @ +·t¦ÀÈö‡Àơ9bçĐKΠæô¹ùö®k/°¿»åGZ›ïvóz̀¢ơkä@¯)‚›¨¾¼ă„£zO¬½SNÏʉϿ ̣Ço¸LF‹í_¿ö¦»ï¸½}ăÓ°vO É çĐ~XzÀÏÜŸÑY VÁ×~ù/ưƠcĂă± Ăk‡¿? HíÁ¨_®È”€óiL Ù ‡(íŒ+øûøÚ¼·½åÍe;Ú#¿[·5₫̉®Hoo,.ÿ‘>”pÎóøb~t ˜dI`ø‘_gŸûØû­¿£E3Œ^‚¤1H₫%O„8è=̀m3"#ÀĂ“/ÄÅee'/7]¤2KösóŕΟ₫Ä®ú³¿w6£19/Ñ÷°ŸŸàLx;¢&Đ‹½‡»ÉÎζ̉Ùñw\un伋â¿úåƯßûá­-¿ûåÏ`×!´2 ̣±D «ø=đaû¿Wøa₫Ï€ø! ¤á½1¦;a™K…Mq́ 3̉ ‘$³ÔF¸çÙO:ÈtBƯÓRßÿçïg»b|Íå7T₫ÙŸ¼wæ}ôE¶ï<³c|ó®C‘áÁ˜ÖLJƯ’â¦ôW€Îˆü C¾ûey'Ö§­ÆR>HˆT UZ¸Ú `3(P[o”̃Ÿ$È+à.{̣ ,Đ_`U#KÚ}¶U_Ơ¨O½‘äPFêÏœe ¹¯W¿æ̉ó"sfLÚ»i]Ï7¿ü©Æëî¹¶@i€ŸB<à9̉ĐÓöD@Í´€{ÏïAûĂî“Gˆ¿ ïûë4 É-à…)É÷Âóñ[€Nôî ’ÎEg¤²üd"À̉!у¬ç¼³ú]̃¹¿ lVáÅ—\VüÆ×_9íS_xkéõ¿ă™Ư‘Î6É ¤/Ⱥ9xDy&7EÆ@ÖÈÊÑ-Å;9·"Ú®̀q„8øDÇüÈ/ĐÎ󯇘ä2§'¤¡)©r^¢Ñ¾9¦¥Ë4i*3î©Ùé—ªùừÊöÎ+ϯ9}IdƯăOôüĂg?̃đÄ#·K‰Px€ïÛ–ĐÆ´+Ñô€‘ÀsôœkD~Îóä‘?$jñBHÆk•£ß£“̉1éTtR:'öÀCü‚àÏ!nĐÙx°ÿ®[¿ß¡˜6íc÷Ö?₫`Åç?ó¥¹¹‘ÁÈCëwÛưOmËŒîDlyÑÛU˜®WQ¿ Ô•ÓCĐß!Đ· y ù±đ˜!@‡?C2–4û;¬ ¨Đ2†1ZªM=y%vƯåçÆßrñÊȶí»û¿qË-M×÷­zyVñÔgFûyĐó ¢@däö#½>ḿÏ‘è¹̉x"ïñûy‡á(-€£4Î8î ưèÜDØY"‚B„ÀèF ¼à÷Rr §å¬:cíôùׯ-’›̣´ÆXĂ/½9Ñ£øÛ 뇅¼¬HÚ°«âa·_Ơ…³Ă–¿8#2œ ưí¿Xw×ưu6Ö́„÷ƒ‹¯2€˜ ½¼~Oøx£½O—<Ê{"âóç8¦t' ă¶À;Ѹ©Ă›ăµ€oCÉÄ4€'Ï $=W@:ˆïé¯\ëöÉÔnÀƒs$P̃ñtôHiåÜLXó‘¼åë=rû„N¥3èlkèëî röợ@ôøŒ̉{–Ư³̣­‡x@<1đ ?̉HO™¾,W›. jW× Â&Û´§oÓd®Bgà‰÷Ä ™øsÏ-¸U„Ä{pä oÊáøJCr]_iÉïÄ€´Œ²àź§J€z,àư?™½÷,>DĂçØ}ôåù£…áDZÀwÖy'L{ü-àA:–Œ"@ ÆN¼đû<÷SI28‘ßЧåèÏu:!Á¬É£½¶>€÷‚Às/ăXxĐ{‚£éCÀ«1&"Lt'˜ˆ:ư_̀Ă#àơ1Y^p¬)Óƒd"Qñœ€Nüï̀Ñ¿“\§‰yP~@  6Ñ?ùđ‰É#=ƒ½é9&¢ANá_×¾c„ÍñÚµ€^2WA€+ 2÷÷ÄÀOüN€ç¤ó\ùOH?ïï{Ç“7i<đ,¿—æxOüÑôŸ‘8ôäç£NĂ0-€ÉhƠcçéÛƯÚ “‰ ÷1™đ€̉|~œÆ–Ă5Àßïă½çGe€àçû0Ê{Đ{ö>ôp ́Éùév&³Ơq&³́0ïÑđ@ôÀ ??$÷IDATK ¼đ#Ó/ ôïæ4₫™Oçó÷׌ÿÖñß´~~î§Ü³öôíu+dïi„×:ĐÂđ¿«’Á @=1à˜,ôà=̃ßЧóïñƠ₫ç¯&$Úî Gzÿ̀ö”éßå< ¯q LTx«=%ó¿ G@룿æèÓoƒøô¯äƯc•áAí₫X-ù>÷â5,2,ê[ÀÿF₫Èë¯ÀÉy`u<ÜŸàïùcp7ü¶@Øa „-¶@Øa „-¶@Øa „-¶@Øa „-đµÀÿ®°w ĐŨIEND®B`‚ic09Wâ‰PNG  IHDRôxÔúiCCPICC Profilex…TßkÓP₫Úe°á‹:g >h‘ndStCœ¶kWºÍZê6·!H›¦m\Æ$í~°Ù‹o:Åwñ>ù Ùƒo{’ Æaø¬ˆ"Lö"³›4M'S¹÷»ßùî9'çä^ ùqZÓ/USOÅÂüÄäß̣^C+ühM‹†J&G@Ó²yï³óÆltîoß«₫cƠ• đ ¾”5Ä"áY i\ÔtàÖ‰ï15ÂÍLsX§ g8ocáŒ#–f45@ ÂÅB:K¸@8˜iàó ØÎä'&©’.‹<«ER/ådE² öđsƒ̣_°¨”é›­çmNÑ|̃9}pŒæƠÁ?_½A¸pX6ă£5~BÍ$®&½çîti˜íe—Y)%$¼bT®3liæ ‰æÓíôP’°Ÿ4¿43YóăíP•ë1ÅơöKFôº½×Û‘“ă5>§)Ö@₫½÷ơråy’đë´Ơô[’:VÛÛäͦ#ĂÄwQ?HB‚d(à‘B acĪøL"J¤̉itTy²8Ö;(“–íGxÉ_¸^ơ[²¸öàûƯ%×¼…Å·£ØQíµéº²ua¥£ná7¹å›m« Q₫å±H^eÊO‚Q×u6æS—üu Ï2”î%vX º¬đ^ø*l O…—¿ÔÈÎ̃­Ë€q,>«SÍǼ%̉L̉ëd¸¿ơBÆù1CZ¾$Mœ9̣ÚP 'w‚ëæâ\/×»̀]áú¹­.r#ÂơE|!đ¾3¾>_·oˆa§Û¾Ódë£1Zë»Ó‘º¢±z”Û'ö=ª²±¾±~V+´¢cjJ³tO%mN—ó“ï„ |ˆ®-‰«bWO+ o™ ^— I¯HÙ.°;í¶SÖ]æi_s9ó*péưĂë.7U^ÀÑs. 3uä °|^,ëÛ<·€‘;Ûc­=maº‹>V«Ût.[»«ƠŸÏªƠƯçä x£ü©# Ö¡_2 IDATx́}`\ŵöÙƠ®z—l¹÷n0\轤BM#å‘₫̉ÉKÈK{é=!!…Ÿ’JH(&TÛ`l°Á½án˲$«÷-’öÿ¾3wVW²dËyÆ{çỊ̂­½ß9gÎ̀ˆ¸àp8‡€CÀ!àp8‡€CÀ!àp8‡€CÀ!àp8‡€CÀ!àp8‡€CÀ!àp8‡€CÀ!àp8‡€CÀ!àp8‡€CÀ!àp8‡€CÀ!àp8‡€CÀ!àp8‡€CÀ!àp8‡€CÀ!àp8‡€CÀ!àp8‡€CÀ!àp8‡€CÀ!àp8‡€CÀ!àp8‡€CÀ!àp8‡€CÀ!àp8‡€CÀ!à8<n_RÚïÂá´~—u‡À›@àÍ®ĐƠç8ÑøÀ]k†_uÚĐO¿ă¤âœ'7×J"‘}  ¥ĂM­ñçËj_ûáU'½z(œÂiiFÙ=w8¯ '¼.ØÜKøë}÷Ÿ>,ÑĐÿ-~:7=$ míë́”h¼Søß– Ö„S5Ùi¡²PÄm«Iˆ́oIJ0Ö‰?ZYß¶̣–Ë'-<°…î9ápXâñx÷Lwçp8ú‰€ú ”+æè¿\¸ë7œ>ô;Ëw7j[Ûc 3g˳¯‚êEÿÏÑ*€DoOÿ¥BCJPZƒ"­°4âqç²] ’À£ê渒̃kÿ{UStÙgÎû°¾Đăăí×̃x́¾;Y¥ ‡€Cà 8à đ¸‡₫!p×Ëẹá9Ă¥½½ó—))ÿ₫Ù¿_IT5´:Á̃))a9cÆdyÏŒân•­ØÓ ÍÑIëg¥¦H0(‰ŒÔ”@L?"/S>àKF<pĐ[ ¯́i”5-ñŒŸ½sÆ›}øÿ÷ ø¬gïUwép tü?}¬n|·;—•Éó†Ë–́ùÜ“‹~µ¶¬5ñâêMh¤ =4|4c05S² ËÇÎ%ej_Ḥ+Z¤®%. ÑvjùD^ ¨9€?™é)’‚’©—N ẶR!X)h 0€‹} ¶TµJ¬¹ñÔ›7o…A¾xƯem^1 …Böv˜º‡÷ƯŸº;‡€C`@"à€ùµºAq ~lÚ÷åoe§‡n½wE¹,YµQ"mQ‰¶·K'„₫G ‚¸C`lÜJɈђ*Ÿ¿`´„Ă©’bo‹wÈîº6iuJKÂΈ>`ưßÔº,cg„Í}Z( ô9Ëä‚NÁ¥;êa™(û†>¾3ßÔØXû…+ÏÙïaĂÚmU^ö÷6ߥ‡ÀC@RؘÜpG_>·óm§̀}l₫øÂÎ>°,¸¥¬‹uHæ÷9Ó'?DhđÀé ₫äeÈđ‘2ö@–ôŒ48ú¥ÈèQ#%5-C>>˜®.@RÛ—R8ÆÑ ‰̃Lt›Đ擽àúAçAX™áÀàœTuD„¥ ü¹×j[ZÛ;Ó̃q̉àQ¶ß“¦ÏmÙ°–+“Ơô¸¶E]êp8à8ø’\MHêùÏËi#ÇOŒŒ”øñ#«Uåẻ‚¹ÿV,é£öoïĐU(K̉÷̃&…\[a ‚8%@ ưè/†@@Ât́˜’,xư?Af Ï‘yc̣T`ưÜ4ˆZ:í 3b»̉íĐ “Ñ)*¤…’‘’’Yàt2}§´>±±=éx̣3†¾Ó{3˜––ˆF1ÏÑ=XÁ€µ×ƯK¸;‡€Cà˜A û/̉1Ó-ׇÀñÀoí¼å3çùáÊ•̣Ă–ªi¾5íB@ª9³±‡ÀÄÏy# ˜ÔAü*¨%V¬Hƒ +-Œ½Â’—“#ç2^}üíØ6üÂG„ƒ¶hÁ´Ưaˆë¢íè/…<ă»5µ$“ư"™öÀg`cy‹´·6]yï~₫Ÿ‘¦§üä–O´bo„··€ư=ñ“¿ÿÚvÇ¥‡À1€€ư{ tÅuÁ!pü đÅ_Ü+?ÿ ̣àª̣ÄÅS_¹ïƠ@Ư₫}̉yùÖ¼ÿa ù¿‘Ú?‰Ù±Ÿ¤m‘( !@-¼¦K£Z Ó ™*Ù!ÉÁÔ@qA\vúd9yh¦¼ZÚ¨+èWÀÿà¬? K³±™Lưê#`̣Í*í> _$ûW!Fi„ 3¡ØlZä•£Ö|yw£ú8 ́7iÆ̀™ÙÙ¡Öæf´'áûïư×^u.q8¡£Ơ°k×!p<#@̣ÿÎă›Ï¹̣Ô!²l{u äOÂlÇG'4h’>#ÿ0(჈“ H¶G° ¢ |kü¥̉Ííƒ:I⬠yGeMÉ` ]BíAXñlha¶’ÿ8V7Ç”Èa8P€Ÿp̣cµ8W ¡S ˜dÀ2Aă‹À|ú ¤á…¼ŒƯ–8Œ₫AǼô4i†PĂ@§B%ÁtLC̀Ë,t½pÇwÿ¶øŒ[¯?—§̣÷D›Aj§8P¯×Ú{l£‰€&ú®íă[n{0đ£O_•8{̉ ÅđÆOüăƠJ(Ù‰uÄUëç²?%%weI2z’» Ú4åqÁºHô*€°©Ç'tâĐi{äŒ ,—Éœ©#uĂ ²ºˆî₫‡é|=Dˆơ 8hª×`fÔÉă#^®çv,1¤à‚}(àq*¥/@ÑƠ y°:Đº¢¬°LŸ6ùIGä e­ö—Éá³ZÓ)sí>£€€è®Éă’ÿ¯ƯơƠó&R55aÙ·×ÇA@°m$Kr¶—–ùlS[„ÏV ±ẵx¢Ma|ÎiÂâb™X”./ïnÀÜ~'%¡BI›Z?§ h¿Xªå³)¯m˜ÊđöKO&Ä»§ÈM¬+o lß´î“Èæ<lzP‹ñÀ"Vi…kè6dñ‹gw>’NúÙs»%b½¿Ù́§æw²'82’fưd¹ I[!À¶—ľN¦4Á́î‚}äŸ ÁA/(#ÆM’¯_1A·̃-‚³±77R~eưĐîu₫r™ßAƒ÷Ø¿.£Ñ9êăpê°LnVøđe§¿™ƒ9OEäæ<`ˆ‘×Vóçsÿ\‚­Ù‡ê‹¸àp¼8à­@ƠƠ9 øüct]Üö-›Ơßh₫ ~0¿!ÿ.²%̣ÎЧ/E†%~ºØ^±£ç?§X&©ưcư?7Jùg`ư?÷`™ÅÛêáˆe‚,‹·Y£Z¨ù÷' X+°kA²tïª@ ÇV@¨0{äâH́6ø¯5X̣'w̉Ïœèiÿ`ú 'Ê-—Œ“F,Ñ«Ç YVûgefß[}¿S¾?P àü†=TˆcW”€óà¦Ëgß̉PWC³?Íü$}®)`Úæ]ûM₫„¡¯ÈFù̀‡€Cà#à€# ¸kîøD€äư—½wæà!8IưDzÔ/È_7ü±'₫‘ư½@!€DÎĐ•ÛuméÖ¦¦ Jzïđ]jÿŒ<ÀhÿØ0œ.Ÿ:{„_´µṣÆÛ¿Kû§£^²-w¸$¼Ó—€ó₫™釗nj€àQŒ:ÙuK₫$~F ŒVÀåäÏ)¾ËÚ½på‚CÀ!pDpÀ…Û5v<#pÚ¸¢wƠ¶½­(;#Qºgw€ÛüÆu}£ùëúútf-vÜV à=‹v#_eꀺ 0æøÀgÏœ ™iiz40ÒH…P`½ÿđ<­Ư¼6Đˆ'O°É~K₫j₫Gû¬#{ œ>:/đ̀‹¯Ö|ô=oÿW]U»NÏj₫=½ÿI₫6p9 ?̉€²_`]=C ‡À[ÿ#ºàp/ÿú^}zñä¢ê©%Ụ̀ï[ -1ơø×ỷèKŒTæQ; ¼g$›r~ߟRH°Ñ ö½ ằéÙyrÑÔ!²¯)*˱îŸø¨•í*é÷)—üu ̃¹¤‘¡ 3… äo½g;È_³đÁí)äy‘÷9ˆœ Ÿ®`¤²Á*‰’¸tÁ!à88 ÀÑ@Ưµy\!đÓÏƯ ß~tÓ̀x"đƯ­ƠÙQVƒyÿv8ư"Ĩ̃h¸w¿uo'»Ù|;Xri’àmfÔ¶x9sÿĐÀé pñÉ#dLq6ưÁ~ÿ°>đ¹*ÿàS®â·Újû}kµ}ưåèRa}8ihNàÑÇŸØÿĐßÿZ‹g$|j̣$vZüæ~BÀgvEËĐAel9G₫ÇÀÑFÀYö7àÚ?¦¸èÊhÿ¾zéøŒÓFäŒ(o%ÚbØê¹$x6‰™fz zz¯ÁỀÓ|̃kS:ơuE¾ß ñëœ?H—K₫BđîçÉôüÏÉ+”‰#KdGM›”7Dµ-«ư«>m>´¿¬ÓS̃ơ₫u} *êùYáÙ|ñm±æ†ZÚ;¨Ư3rƯ¿ÿÚî`÷đûô¦ùk ¨Ă‡€Cà( àŸ«; Í»&Ç6;6­•ÛnßÚ\“•–Ç—o ÔÔ×Ç?lúÓN+IĂÇ+ÑsĂḲz­÷Hü¸Vó>S–g?Rhñ3̣ä?j₫éđđOĂÀ N.—2BV—5I3„0Êꉬ˧ư“üljîưiµÎư«đàë̀±ùÅÏ=Wÿ‰]·µÔu¸^j+¦LDဲ‚Ơ₫ià5m>­,ge(¦.8G7p@wM_@ϤËíêÛb‘ƒ|q`Nj"¢…E$Ü‘H1S4Û©¥7æÍ˜;±T—|®eÍ•~’´)(èœ?ôĂXXP £FĐ₫ëĐ8₫e{#_•Ú6ëí-X̉ç³äº½1„!yé̉OÈ3ë÷r$Ôâmḿ: ưPæ}–³ẮyG.8G' Ô]›Ç Ÿûơưá’¼¬/ăàyf]©´µ¶€x¹/¶ư…Âñº`W®‘Wr½™³Èx¸ñhÏ  ¿À,bu`Ï" Ó°¤cÇ?jÿYY™rά©rθ\Yº£^¸'A(¢LÜH+WøóưäÏç¼'ñ3صÿv@'¼æ†åeàˆá¬Ä÷ï~¼ùÿư¡ơ(NÓ>µw¾L̉çµ_ À­>ăˆYS{o6yÈvÁ!à8Z8àh!ïÚ=æ¸́ezçk%¹—|¬-̃‘ˆÓ§NŸ ­˜ˆD¢j₫ßSƯ¢µ`CêÅ$Î8¶æê€çíA4€™ß —¬¹dB^30%13êA?˜óçQ¼éa)̀Ï‘S‡eÉ̃úˆF¤Ơ¡°±$˜Êµ.^zu óLÁ‡%ÿ¶ f%Aoóc—`Y:2b¥₫ü÷7Å¿¾ơ³»đ€äoköWjÉ©5ï3µÑæ3µÂƒ­Ç¦xä‚CÀ!p¤pÀ‘FܵwÜ đŸÜ)ÿjùçÉ“Ưµm™#r@Êù2(kDr kË[u9`EcTÉ•)`gÀÖ†jbØ,èµ́Đ)Í8÷߉éA;ñ¶F¥Uæ‘øUûÇÔB˜º“À÷ywàƒöߠ†9îlª’¨‡₫0øYÙ\›O˲vª@iTÓÇú ø̃Ææ†2aưù$đ¥o|»¢²tg3®©ñÛª˜2’Ô-ÁÛ9~{€M™o[)ƒ¿>“ă>#†€Ô®¡ăđOb8âoÑ–º@MK«jÆÅÙaIASÛÏÎ̀ĐexYaƠâ©ù.̀U"Ÿ…îPCßJê¦Iu>DÿXF­ưxfE¾b©—– –Iô?Èèü´D^ÿë¯ÿo'ñwÂ’¾M©Í[-Ÿ$O§³Ÿ?ö%°+øzƒ\#†€Ô®¡ă }íG?ÿà–Äü±yÔº{ªu׿(zw•wú(,¢&ƒ¥âeFn:L÷$Ơ’́4M333‘¼̀–á»CóRU?̣ø$,ơmí L!`}4B(HÇ.4ó)L×wx&@i}óP£q­‡¤N³} ª ˆœeT@«Ộ¹$‘}ƠƠ)˜‚€d (Ë|ŒU¦”drBàíç^´YVó·ÄÏ”äo’¿Ưئö\̃S°‚ß!ñÛºp©×L]p80öÿưnÖ5ç8ö¸ciéÚ̀q̣ß_)—Meµ̉æ&A“$;‘&OÎqß,́ÓK² —ôŒ={40_—ï!å¾d_.ùËÊÈĐÓö²àâO¿nV‰÷®y¯·O'„S ¬ƒ­XgC–µÎ…FZ¢²§.¢íBf‘fÚùÑ-́6â+*x̀•#»[RdZA`9²̀“rŒVÛoÁ5#æ1¤̃‹u¾kæóy+"Ï  °Àh\ú€ă ‡ÀC€¿.8>κü=%O<œ€3_ È1ă'Ḯ´´¶Â¹/3>Oÿù+’ »‚%₫d÷¿‹‰ÊÊuĐÂƠñÎ8̣™næ&6›‘„§CùÉU'ëôÂ'~ùV@PHM—œÁ#‘d*ÑOÀ¶Ä©xïZ ‡  º÷¶ï7(¾pZbéÖJÈ9 ©lˆaƠC8°jù‹ơ¿ùæg6ÔWU’́Iè$v’|"óü)¯›)°,…’¿ơ ÜÁĐßn™̉îÓ!àxÓpÀ›¥«h !pײ²Ư7œ>tTZÿwÙ‡;0Ló1¬‰çæ?v©ŸÑŸíÈ»₫;Â7Z¹ƠÎï>è5`8ÏØô…uç@d¨F¶†Ê“/^0F>{ß:©ß¹ B–¢Ư¬ªê£I’4…ªđ)ié’S$™Ù¹’‘™§ ‹-ƒ?~æpôƠö=đ&üÙ6-¬ƒÂÓCÔb[6%WîkCŸ8”("ơUû«{üáÿ”m]·jÍ O­ÉÊÉi‘PjK(-³5;7?‘}mƯ«- Uëc°iÏk}è>·C₫¯ëv5;=~÷äùÔ¥§Èƒ«*¶\yjÉÄß,̃-åµñóø_ẓ“ôTèCwơ8Ö Î£7“g₫»Y®%w7B ™–…±Crå3猕˜é?₫Ă»AĐœÛǾ<dm ³³ ·Å0¸Tëó%w”¡CaZFºäÁz›—‡2´([nœ3B-Yđ3À*GiÁÉ‚¬Óöí°O6°>oC<»z:à·dmy‹́kˆèœ›PÓÜPÿ©WW¾ºøö§¶aÏ&  |¯kP¥½åu=uW‡ÀFÀ9¾a] ’ÿ₫±v"È?{SL*A₫Pü•ôi0₫@P̣7ùÂǘgç̃»p©êL:* Ö„$Ûb§7¿î€”Z~ÂÅ»O.QOü›î\®G4—h´Ïý0vDÛ|ŸmR£ç”̃kJ¡HV…:à_Đ +|gÙ6iÛÖi…A³Ndz€üiѹá́)¨?.÷­¬Đ:Ó±-9étBC#rùa6îôaÆĐ,´«#§¯¡¶©/âƒBÇH8:ÎçY@’ÀqÅE-ѼŒ6hă„)'ÿ×Ç/:i)̣ơe_V’Á>óç%º ‡€Cà#à€7¡«a€ pĂW~(÷₫ø«2{\ñƯ˜ƒúĦ¨ÔÁIWÉ×3ư“€ÉJIe7=Yʰ—å0<§Ç=q̣̃5;ư Ù²®84ü“G˨ÂLYU‘†=$­<m‡ơ!îm0„i¯1­$a^\ƒ™G̣§ ­„ăˆíØW –„Îô|ùÀœá²lO‹lX½RîAƯïœ7UN™‹å† ̉€ƠàzV,Íh›í±Isú¡7Vdl(ăô¿ l‡çX ²̉ŒUBûˆx¶Á¸¢̀Ä™ặ¦ ÏOûưmÿYưɯèơ•û€ˆoT̃]²&ZÏgÉBîÂ!àxư8àơcç̃`ügỤ̈Pîé£sƒ4o7´´:=“?µ^Ε“àHÛzi™¸7T3öñ/½<’"µ~́æ› ÜF˜Ëæ/Uåṃ˾ ­8đ‡y4“8¦Úµ/‘|Ó»@¥Æ`ÈŸ×ñ”v¸7}0Cä ’wœ5K²1%đç?.Ѩ¬^»F ̣rå†ycô¼ƒ5{±Z€ƯơèM°û:~M½6} Ûh…° oà=]U€̃kD^ms,Đ‚e—O+>yÚ¸wü'ffe§·¶4kơ¬ÚY;ïX…½Ö ÷áp¼qœđÆ1t5 >|ñiŸÍOÏzyO£Ô6Et9½₫IĐ*¨¾ÚÅG~’ôĂ`É̉汜:Û‘Ëh 0¿¡5dqiáŒQ¹2kT|û¾%RS¶Ađ4ÿ84wZ!”̀Qi‚ƒ8 ÀaAe î! + h´Içt¼1†T9s̉ ¹cEµÔ—ïÖRRb²pér[”&ïxé,™ˆm…_xî)in˜Ø‘Ê ùơưÏẸ́mrứ¡º‚€;̉'K‰ƒF^óÙ‘ïxïñL½Æ̣I^óîY@!`ñ¶ºÄ¹ ϼăÅ]ëA₫MYÙ¹tàQĂTJiáï#ÉŸ©½Ö ÷áp¼~œđú±so ~wëgäKvßTÙÿâæÊV©¬k pÙ)R’(K¼qJø(Oí_#¯ñ'gœ=­D.R$[7®—ºê*u₫kooÇœ}{ù÷ ~ÛöÉ,KįOlÁ$ ÚV-?xn¯́)¯‘¶hLÏ$  ĐÚ•ºªrùÑ¿VÊæª6¹qî0ÉÔƠhÄÍú‘ ƒ…8¬ Á”xq‰d„”vôƠÜû„*D@ ÙTÑX±§9ñÁ9£¦ÿé…ZĂiiĂBÀ ‡—+<ˆ`—?ɹ:åÓ†Wœ);*±îóåÜ-—Z¯9u#Ç%Ú~Ñ]H Ö²săà4Îן:¶HkÛ·w·4WíƠÓƠdṆQ²Iuâ³äïo[¢€a}#à9¹÷?7 ¥àTAl3<$7M~³h—¬ÜY«Sœb €¨g àVÇ‘]«ä3w’ư]&vº‚¾¬…µ WÚ²¿%0K' ÎÊhÍV½âÅ…ûpØK²–Á@oÏ{–w÷‡@8 `\ö‰É?<ñªà÷¾pơÙă‹³̃µ½ª%°­² ‡₫p×?îùϹoăpgXØà̉]³ï++(À?¯u“0)ç˯3V  ï~í§%ÑX‰ÿà(Gó?§ `7§`5êd+½dB#\p  „°™÷ă A#ÆÈµgO–ƠÛ+ä/I°#-œË )d½µ0X⽺̣RÙÍ–›ÎÓ{²c?,% ß ×/jƒh”çđùÚ9́öYó•¶)¤0‡â.ø½ơÑĬ1Åù§Ÿ2uö¦Í[^ܺyÏ ¸¡ođ­>‚×zO]¶CÀ!Đ'~y¾ÏBîC` #đŸ{è–ưmßjŒtÈærnûË-wùß¿rùªßÚẉ“á´¦˜V€“\VFœ;!_î~©L:*0倵ûêøgLÿl›ê5ë̉àƯ+‹’I½g¼L.ÿæ;ÉƯñâ Ñ“dNø{ä¥Ml㩆œ³‡pA†4Œ@ĐÎi§âđ₫ÈkkWÊĂË·Ë¥pPœ‹é:²ïgt<°̃ăư#ó“w^ư÷7Ç¡¾ôàtîÎhˆ]W™(*È-ùÆ÷~ô­pz&æ„Îv:ÀúøW°Ñ®Æqă‚CÀ!ĐøŸÉ‡À ÀWß66Ú ÜQƠœØUƯ §Úµÿª}ÓÔMM×Glư •èYˆ÷©í*A¢₫́̀ ¹é¼±ZÍcϼˆg)̉'4́à»^ܵ4KÉŸûؽè¿Ähû[FH,,¸tÁ!àè ûŸ¦¯ç.ß!0 ˜;yXÆ»g”HUc$PYߢ¤)4dđ.h_cÉß–Sºç® :zư+I"¹ïĂs‡KQfX₫ë̃µ’óÅÑ :äq>9ÉX ™M÷M₫́ jư6¥ƒ!7B3̣à'fi{×Ư¾¦,ÚQÓ?Ú Ù³¤ƒỤGú  ·¦O@$föh.ß&÷₫çEÙU‘Ùc̣uLÆRÑrŒø5a?tB¶cƒbB!ˆSˆV0K±<Đ',ß]X´­N>4t̃]K¶/ô¦¬€̉“]"Èß04Ú-²Iæ¹àp'÷hà"đµß₫]Wב^Ư wÿª”¼ÔIM‰Ñhü,ÔEaÇĂ’¿–"ù“ùơ©BHvÔà<U”%_|`ƒ́]·4iúWíŸọ́ª“ H₫=óH²J¶^jæ₫9ÿŸâm—)³Ï>EJAÖ-¯=úpŒ/´{¸µ%­I+ÑöT(Pa³"B$BÿvlX-ßûÛórÚđlyÇ)Côm;]¡B€×ë À‘û…¾̀ëM€àCˆ‚¾~_³´À2sĂÜqƒï\¸ñoÈ¥Æo)p:ÀN iû{fÉߦxä‚CÀ!Đ₫‡rÁ!pÂ!°dÁC̣§vsí́a7b-z`éÎ:l‹#wA~$:ƠÀA¶4ÙÛ` ×̃ûS?ù«6®4Gí¬f$A¡–kÎ.ƒ̣³ä₫GŸ”¦f˜×9×®æÏóŸÚ¹%~Ùk[=îỚÂ× rÍ*ñ‹3äîÏ^(9©̣Î0Üå‰À¿ôưw?wL^ Fxr]…„¡ª̉3Ę!‘¼¦ơ[´ºkÿ¦ë½«ú3®K° ïMg’muqÙ¶}»´G# îùọ̀j’WíßÖÔ²'³Lg̀C\“ÙºÏưĂNda¹̃c$#Ÿưå1ͱ—?ÉR •íЬ¡äz¨ư³.eKܳ-6Ç2ºZå9}À͉¸G-%¬\¸ư§åo+«åiÅröÄ"œŸ€̣¢Xë²BĐ!WđÛ °̀Ù=s˜(T́­k <²v"%5#ç›_»åóN9oĐôo­àw Ôá°ˆ.8½ à€^@qY{~öÍÎ?/-ưÓ”!Yé 6VĂ WŕÀ´.ç?`êP¢́'VX0ÄGbŰ!7è5(Gr±íï ¯®—}Ơ esàS³ÎÇ“xÙÙ·¯@Âfä’?ÖM§?,ûcJaâ½gM–ÓheX‚]kö Ï,ëëÚđÇlŸƠăN °/*€›Ñ?]ˆú¹2€Ë#8+¡#̉(xÜùJµ¼}:„€I˜>AưĐäQ‹2/ ¹LđPB€œ+Ш_hÇwB|JkÛ/l­NŒ5tü]<₫û¢âb4â·XŸ¿%À₫¾9!€_‰ Øÿ =²Ư­C``#eûB{JECŒvg#(ùÖ³sÿ,±÷†ˆ}N†QÓ?i5².‘\¬Ăÿèü‘²²¼U[·Ëóă:ïo=̣ç¿7'o!û²†×̀åk¿HüºöeCù%2q•c‘¥Ï.Yƒ¤9çO!Q…;0-¥]ơ®ºÖß%áD…€Æ­ƒ¹:À -ụïG—;WTc€!2cdDÑk¨#$®z]-i)@„?̃TN èÈM™¸GÀ®¶ÀË;ê³' ̣‡'W=Œz`Ù•\hi đ[ؤ&/]p8ˆ€Ü¿ƒ óßy­Ás‡·“Øwí¯‡É™ó×*@ÛUÎVL”0û‹%küơ)Ûh íÜĐÙ G¹Ư¿Tê+KAÊF+Wí_‰Ù3º`È„ß[@Vûgs´p>N€4•_qê0yvëûö“¥²o?¶üEƯ~ÿ«]A@uî̃ZѼ̃…Z+̣̀@ă…O@\köËÓÏ<-/•¶âôÀB=xø#0uê46éÓí‚9Ư°wï>Y¾q›œ44Kæ/Pë±UÖöØW4FAÀû£XûÚg¾æé” xßL‘`Ÿ¡„€ăƯ/í“ê–xàYC:?÷ƒÛ?Œ*h ÀođO Øß:;l›â'&”]pœ0Ü₫đ½†G₫;1àÄÖ–b a®ư7ÎxÈäh­&Q)c…%d±é|T>xÆ0Y²e¿<·đy¬•ÂáGñ&- :«û›èÙ¦wO#Ùó°Ÿ bB ×₫geeËUïº\vT·Éí_ ̉T¡sæÚ 8´pl•´ßö¦ï”,É·”-}ưb]xLøÄ³ZµµLB¹Årå¬áÂÅú{j£ªÅ«EÄ£\»·ßgÅZ—iA;b…m–†`W/Ø”̃q£ ÉC²ƒï=ïôÓ; ÇF_ü –W`Ư ỳר=ÓÅî©©Ô ºà8°Rñ‰8v7æ>«vÚœÚ!9ịĐª̣Ëèd¦k₫©á⾇ÜÁñè@ơúWS7yĐpKJ8$×Ï÷̣Ó¾,) j:ÏqéŸ:ä¡-rđ·@–ö̃×l̃{AkÅ3ûI¦Vû§•¡xØpy÷Ô\Y²~—¤tàÀ m©æ ẰưclJ‡Hñ¾e@[ÿÁR–ír Ä5*bdưt ä̃Æ)°]±f¹ëÑååûôáK¦ÁR`¦Lh›ôµßô†×₫`…åm<‚cÚăØ0@«F X>¼º2±¿¹=øå_wÓÿû›—° ˆ„KưSÖ)Đ?t6ê¿Ç­ g8q¾ëz¤ë^z^~úäÖyçN.₫Jm[{ÑKÛ«t)[ d¢„BÇƯ QzhYB÷ƒ—Ô₫‘i¬ e;¼(–È]=o´ŒÇ©yw¼T.kV,S‹Á\n´rnÊCÊc[ñ1)Èø¨Ñîúí;₫…t÷¿€|󦫤)̉.?»‰tÖîR¡Æÿ­Ÿ©­ü0¾Æ©à ư5ư4$í=µ]‡47ɆƯỦ–Q‚#„ƒđ²­²U—äơÄï£àb‰ÖO'BZ 4µ9xưgm±ÎÀ¾†XbHAzẾ“§MÙºkïæm×V Wµ32Øô`×ZĐ}8NœàDù¦Ư8eä ¬9pÀ›´³&’ Vªsă b³öd¬Î†É,É6CLɹ¯pFfºœ5._n{±\₫Ï"PQ™/‡k´rOû·äß[#>ÀôäGâC¤ùŸÿ” ²G,³‡¥Ë₫ùöÀÙß’?«̉¦đq¸Ú¿¿ḱ‡ß@Ëqêä&A°$÷ •£¾B~́ y»^:¥XJ̣Ó±Q™ q³.üî†ÚưmZNæsºm¡ÇÅï‚ûPƠ ,Ú\›ÈÏÏ+¹ơG?ÿùôyNÅÛÔ₫ưÑÀZø»Ç–ljîܧCàBÀ 'Đ—}¢ơC7O‡₫îéÅ£ 3¤¢¾9‹ÁQ䯒E ¡HC]ÈYÁÀWtÛe–ç†?mĐ₫o˜3\2SC²xÑ"‰77$çüÍv¼$-ă•ϺTë·iW3Ư® ñƒđÁœ<íO­ Xß]ŸáGùá9Ă2g̀¥¦¨Z:Éœ¤ÅTÿH;œkî#¨í=³¥Ôù7¼'ÏfĂôÿQ́÷_’“*»Ö,“X4jˆ@’”=Í\ë³äL&´y6àºKû§€§ưĂöCƒüëSgèÜ›ñèK₫…|i«{#¦Û›²·:f¯ßfē§ đ ƒ<<ˆ~uơṂÂ+keZI–¼¥y{ƒ.!€µẵ'XAÀˆ ¸4‘B€ đ¥@«°1÷ wmÊÆ˜¼mZqâ₫W÷.B¥z.´Óí`‡†,ç8đ¿ă~„|~ûä–öÀ‹ă3;×”ÖöĐ «1“r•Ä4í]û'ˆ†ŒAGº»ÈØ2hÜ'gO.’ &’ï=±M6lƯ§çaUµb:ÿ©öOAƒ•1°QDM†÷©¬ÈvLÔù~8ưq׿V:ÛẻéçÉU³GÊ…?xFbÛ`€ƒ ¶CKÆfLå¨ß׆e¹nm½ÖçŒXUrl:Nç$û*÷KY[\7oœ¤§¥Èöª6sp½41$O!ÀR2Éß^=…ŒÂZ²˜)ƒ¯E97V4ËÈ‚ôÀœÑ¹’<%¸ô¹'6`ûe|CÉîÙnÚ´« sƠƠ¨}âR‡ÀDÀYà—ê†Ô¡9©-ƒ¡•o®l n(oqƒ(đÓ¥Ñ?¨<ÙW0ªŸH̀änđnavªœ‚ă~Ûp]¾mÄ[ù_ư)³„ỜûjÈỴ̈l13ưè_`÷ˆ¥dÉm×L—Ơåm ÿ¤3˜Ălh¤æuNÛ3ƒâ§¿÷₫f̃đ5жˆ©i—~툒Gc§ÀöX›<»l­üfá™?&OΟ¯½JZx‡qễ\&è³øûh…® °[[gGnP¤>ø>ï{µ\Ê"‰oêÚ?óư?Ưˆ::qü³°Ë9`}́o¡…ʦ₫æƯµC`@!à,êëtƒé‰ÀÍ¿¾/t̉´É·œ1&ÿ¬wÔÈêV%*l s5Iˬ“÷S$‰½g°Ú8uĐn[₫ª”©#̣Tûÿö?Wˆ-»$Nó7ưÑơø4̓ÍÔL¢´Áßó½{Ûjÿ˜ûWí€ÔyÁùgË;f‘k~üˆt4Ơb¡½kªíÙ„¿>Û̃›œ)^Đ1ñÎEÉ[öCá„££M¶”VIS(_n8c„¾“½öˆV-h*TS¿nLkKñÅ FöĐÊñ®y_{@A9»ë¢ÀfNŸ8­²1²cưw„ 0°0- ¼ö{o*ô?q׆€Øê†Óÿụ́­éyùyOd§…:_ØV —ºn”/« då#¿à×₫I8ÔÂ5Å·áeÈ„IûçM—^Û+<ù¢tD[±ăLÿœ ×ù2ç«}}󑳿ö¸W§?,äQ¿)b}=ÚîÈ(’o_?_íÉ̉§“–àupÙ6ă±N†ä7ö›í/‹ù»Æ₫˜‘ùú{K–íLAÿû¦øÄ8Bívï—´¢¡̣®ƒesU«́oŒbl<ƯĐë­©Đôלú‚œ €5€cƠ ~'¼VôE(oŒ&& Îî9çÔÇ¥«–-̃K€Ø c_ÏØ' ȯƠ ” øËûFw:ï›äzÿ7¶Å@Ä\CN§1c2&dlđ ö)—ü‘_¬)ó°®±C̣dÖèB¹í‰5RS^†º±K ”­³a7ÍŸ±2à="Ûbä’?%̀ûsÓjúW^p\9w²ÜzûRW[§NwÜ]Pü…UƒÄŸ ®µ>½\³<{â6¯—â}f)VlÓ́) ‹Æ̉‘í¥ûḌ‡ÉÛ§ ’̉†¨T7Åד÷Àv¹Ÿ:ÿ‘Đ7bp|ùâñ²£¬R₫̣ØätBû÷vü³ọ́Đ̉µn}‡¯áÎ^³÷ƹĐhÿº́û₫Cå–ë.îÿØw IDAT›' ¶4ÉKK—b!b¶â¥ằFhePíŸơ"øÇbrº²_IÏ`F×û³eyŸ,Ïqq<̃“ +L–¾Êó :Đ÷]µqùđùÓè°'ë÷µÀa§%`œIhp¡Đ°vV‹?†ÚMx Ơ€m¡!½fAfhOÜb¢@eK<1BÀŒÓϼôµ¥¯́Ù²n? Ùy+°â®—yç‚C`#`ÿ à!º¡ÈäggüÄQ “›•䦫é'óÑ„¯¦vr …„i TÉ÷È1ä2Ẹ́x‡BÄ­—OÚæ¸|oÁVIIĐăŸ'ñ™Hç´K₫J$+̣Km1z$HÇ?îùÏHkÅ3‡ËeS‹eÓKÏJ´µYWĐÉP—1jư¬×«÷ªu÷ÑT²=XúST˰<[7íRAuy ph‡I>UÜ# L]éùđ¯áyẹ́áyĂ%+=¬Ó `P ç¹z‚7ßÄøÙ=èh°0éT,=xúµêÄÔ¡ÙÁï₫âwwÎ<ë¢IèªƯ)Đ‚ •"ÅF\ê5S ' ¨¯Ó ¦'˜B×Ă~±W>×çO–'©©4©sYḾœ{6ëëuyŸGÂ$.ƠÉD6đ®ù n—É#‹ơIsK“T¼¶JªẮ¯' ªÇ?£+P&C ₫:“lgÚÑúƠăư¢ €₫q@V~±L˜>S~·d¯¼²½U³?u{aÔc×´Ù­ íeï¦ỠŸ1÷@ºí»,ŸhÿùÇÈ>AḤ ć«"X"ÉX¶}£ü×ï”qErưœ¡*tb ÅàO uª€ïƒB—R_÷¢®`?;QÆ´‰k|I ! )oˆvƠµÉyăó䆛>{unAQ^áÊ ÜÀl7 âï£ưdơ¦!\¸àØÜa,n $y…z=² $ ²›ĂlƒÇùĐS’“ct’Jíëë=[餥Z8 L ßÓ₫A,JFyÓáîæ ÇÈîúˆ|áï«u₫:yĐḶ$¡¤öŸ́ƠÁ/”aĐˆ™đNüc£˜®>uÜ ¹îÔ"Ù½~…´7Viư\j×¥ư“ª»èW‡b«®̉}÷‹uô§\Ïô½B€b‹#c°D±Q7 Úµu‹|ơáM2yP¦\:µH8†\ă ”ä¸"€ßIQé¨}†đÔ½@ ¶ŸÚPÅå ‰/½ÿWưïoï₫D^Ñ`¿àß2˜B‡ÁßH¦Œ 65wîÓ!p#à|ă/Ïu½o¢‘6ùÔ-øđ¹“oi¶Sû“8H`taºd§ÉöưMjÂ'1P›§Æi¨ƒ¿ïÑ ëÆB ÄŒÇ4óÏÙÍ‘÷Ï)-ÛÚ6-$µÎ 4ëĐ÷UÀ%ëĐØ]0`¦27¬)ÄU[Ra Â`C,P”N\1gúôØàiÙ‹₫ư·EXê-d);hW{I‘Ÿà8₫pÀñÿºôÀ×¾÷ă;¦É>yWmḳéø‡]_@´T4Å1w': xŸDKóÓ””¬¤CâqP¥@ÎNà₫–K'Ȳ̉yîÙg1ÇŒ­yA₫Üó¿ƒQ… d…¾ Dä»ç%íûd:ÀqJ‚»ưiùóñđÑäï8I₫¸àeÙ¹y×ăÖñV I¾B³hçP Ū ûeËî;ú.ÇL´V^«dR@^0—½û*¤)œ/çOŸ¨ÔÀ·"VØư=#Ô:×ïÅc¸gF~·^Xly6ï/CŒù=—ÖE…™©‰™ÓÆM‹…rÊ_^ôÔFl@!€ÿlàµöÜføRæ»à8®pÀqươ¹Î ~ö–&¬\ÙÄđ«ỌhAe…eLQ¦¬Ç–±Ô¢íœq’FÉÔ0Uk%áræ/~JJH.?u˜œ<,Wn¹ăiki4ÛưrƯ¿ 韤¬ơà-%@¾í 6eø„Z*ÉŸ„ÇHÍŸ~ Åc¦Ê-ל+µuµ̣“¿>%á÷ưç2FXĐw%ª­“ơùêë²?eüï²¼¡kîÁ¯µ 1Ù7¯¯2̃©̣Né„O@e•d –K§•ª–˜Ô5Ç$ \ÀÛ* Q 2Ë0-ñûSSÆ8wâ(˜²æ+ÈqEi~NcÏ={̃ù áA ¯.Z°2NKÇñÆ*z#Ó.|”î©CàøDÀ¨Çgß]¯E '-Aç~1åb5'Çí¬‰HnzH¦ ÍÓåuià·£@ö~jä&u.#qA›Ô9gäÅ`çç~ÿïÆ©vw¯¬‘æ}đlç xăIÙs₫K²†2óA»©Ñ”ÑT)x‚@›…±V~öˆLùñ‚ÍÖ)qQhIXÍ Ál€ẂÿÁBÊôơ>ëîj­¯R½äs€À‚pèî‹Ȉ-&Æ'€”Niª­–^.…™)rư¬¡˜®IƠrôÓÁ ¶ßư8ˆxÎrù½âÚ8{_ ´(PhẠ̀@´·tg}‚›}ơ3»ùcÿûëÄăÑ8¦üv»`*Kü½d$ .8{œpÜ…n=5~²₫»>cT.Ÿă=ù‡!É  ¦eë/T$Y™™ ‰ j™ºÖoªÖˆr–üI ©2Gư2¼øÂ I³¿.ûù«%Á#f-D¶cdă₫àË£f¬sÿX¯ªG₫AĐzѤ9̣ûë§Im}£¬]¶₫\&gÿèÜfªg¨7ư1ưû»q¤®9zvÑà`„rÁ8u„…Ó(ôÓh­Ư+Ÿ½ư?’—’Ÿ9Bà´I³=Mù*#~gº’ƒxơQ¾Ëüo,-æ;2Ó=t4luăáæúÂ'>̣ơ~åûW¶Çắ2WØe‚öô@₫»bäsqé‚CàøD€̉­ …Àí¯u₫ê©-—ĂĂ>₫†w`DA&ôä—027ïo•ĂrdÆđYº¥ ¤Y/Î¥tØß„C¢̣ïÆ±}̃Ø|™;:O~óâ>)«nP‹@{ó“Ä́F<ÊÅ~4{’¿ÿụ̂̉@'ÆùÏ› àÜx( pH®øéJI `„e½ÚéŸD†ŕkzûºe92× |ÿpë±ï°] =´±ña¬p„PBL…0PUº]>sß:ùíµ'ËGæ“¿¿RñÓ’"gdđ=r:§_cG[Y©!ÉÚwT *½‘î-ÑÄ´!YÏÿ÷ç₫¯¥¾ºá¡?₫| ›è%"Kó9úƠ[Ø¥c'+ß„ëÇ›À¸aù¿C…©¯è©ùSoăœ>ïiF®oëĐeM.Ä\p›́À)ܨÏÈ,øL2%é*+=U& Ë—ûVVÊSÏ,’6â1Ë₫èoú‘˜5xÄl´^“•̀g½@-5€v©ÉRàñ¹9“æÊ??}º4µFeÿg0E‚Ñîmù˹²wX‡­°ÔWºưÏf[¬ïPmúkÔẃ¸1|:C(ø6˜Ơ œJIHơ†äK…ågWN‘O3̉_Ụ:‰w2çà~ÖîVF"náùÀƯëP†¯p¨~ǿµ¿:›×­Zwă8–pÀ±üí¸¾½”g@úí|™7&â÷YŸPH¨P³±EéråŒ!̣óÊ&Iƒi@5küæc]ɉu@)• %Y2Úÿâ—VI[C’¾û'ñGBP™¹¯Àg>TâWÏuÈ't‚S!óÖ©iRŒ¹o .ïüùbIŪ=½°[;f €’Àá˜₫ Á›NTv8uúßQ¤’pQ   E,‰?v dKaOîiÀFNôÁX[ÖáÀÀHan?¾C ÈKVerºƯ³]®iƒ¿{LlùU°ü‹Đk †§̀ œ>"+ñ­Ÿưî@ûÁ§¼{^`Ơ=ư÷åå#I†ƯH>pc 'k߈ëÏB  x°ÔUï— đ₫§ßJ»9m½T7ø£Ï_hÎ÷Óél6ƒ-‚OU(k÷Ô‚lÍ/=·ÿéÜs~Vº̀Ÿ8XÙT)‹6”+É[̣·+wæëüdßínØ ¤*psÚŒAÔ.™"¿ûĐi²¶¢M"Û^D׃jmH¨ŸûÇ8ØF?Kz­ö󷦘öĂĂFûc;¥˜x¦}<Ç^A2c̃ụ̀ơËÆÉ­5̣́=̣Í÷̀”‘Ø1pÁú*́¹€é6ñ³u+"úar)Vøƒ)mÈŸ×|=€e†¨JẲuj,;2+ñŸßvOnqÉ'¼ưÇ‹ñ=Cœe²_>cMƯE† c₫ăuÁ!0`ù'rßö쉃2Âüqçny4ư3€Gº¼úI 5­ü 9gB!<Î3”T̉à]gÔÈ©!^3g”œ2"G^̃°KbƠªưë1¿0 ()ƒ°Ôr` Ù#8­Ø~øópÍ®˜µê\À¶¸Ô ^íÙ2wÊ ÉÂáE_øư˜0ªÓ€w)l(Ăđï˜ÑÙ†ƯÔ²#{hˆ—}7èx©sûø’:ă1É:Q¾yù8ù÷†j¹íÁŲ{ă*ùé‚u88(S̃~̣ Xkx¸“ñ% Œüc₫{Íçj_Ôóhav62·ø §ÀNya{­l(o ̀đƠÿùÆï3.ss:̉$ÑÛ–ÁǘWaSd¹à8v nä‚C`@!pÏßï₫₫¸AYÁlœ̉€¹~£eƒ §ÑÓ$aB@ÍÉđ×¹G@YV’G@$Û¼,́Qú0ÙXZ#¿ÿ÷RH1Xh†‰ÚÓÈi¶NV™¬º0¬ç„ j₫pSÔ5ÿÜüS‰üạ́Í«çÈ­²ôÙÇÍCôKÏ× )l°>„^Z²½è–ö·\·—rĂ1nv?ưNе|():Ơs%3Bn¾áBÙƠĐ!¿¾÷q‘Æ2Ự¸¢b¿TwdÈå'Ă¡N©Bÿ®æÀפäM'©[ËƯßù,ă|ÆhËs *@`LôÀèO00sDNç™ç_<ö‘g—lˆÔ”7@€„¢ ?j́öµÛ{ ‰M‚ {ä8º8 ÀÑÅßµ₫æ" ?ºĐgáÇ>µ®­ƯÓưùÛḶ·yKïp å[xPP}[\&c‰_¶ ¦3 wâăïüMçŒƠÓäî|q§¢]Ú’üI,»°z^{Äl[ë–̣9É_—¢-nûËåm’],ï>ë$™¿„ûỵ̈'Ai4óâ†ø}Âêê˰Å₫”Ó½EÚỌß›₫@'ă9#å¦k/“+¦—È ^’xơ^i‹vJ3œ!£­M²ä…%rÛs[ố„̉¥ϸϵx»£Ớ!¨€‡G* ĐwÀyJ ^Å÷ ¦ƒâx¨ơ ¿ –€wÔË+¥ÁófO?çß̃÷µ‚q§Œƒ$ÆiS{z µP‘̉EH µ…Û¦ÈrÁ!ṕ!à|½ïÄơè "Pnçú¿8ù_‚}¿ĂÖ @V  ’ 7×́=?ep–L‚°Óñθ”f˰¼Tụ̀ƒd˺5:ïˆuH䳤9}öî€îûóѦ5w35›₫p{Ú„\x̉0ùâÅäÏWJee…t‚”èc ~$8”a·Uà8 ‘c7]N2"{i,2œ̣ Ôµë!78ºñ©Xû?Jn}b́Ư¼VÀ « ߉ÅSÛåé§Äw”OŸ;Ç 'dỡÉ„ó˘ÀZơcerM û©oS¼Ëƒ•Ô2@’aBÀƯ ø³gN=ûŸÿø[çû®¹îûƠ;Öî¶ï÷’Â{!h*`½5,ä.G ¤Nt´:àÚu¼Yäæñ`7‘ùc̣ôœÀL¯óỄ¿r&à]Ω̣ŸSu‹ÆR‹­g/ÀNc Ỷ ü¹óF#í­k^1´'‰Ÿ&9&ănÚ??X@[J8$>\«àiÿé9E2tÂt}{ÇÊ…iÁ2Ć=@ox]^Ha£–KpM̉:Tà‡.u¨Zº?·½èO½ÉöÙwŸ}æØ•h±û" qŸZª¬G|Ø.ËAÈN´ cjùè ¾”•iYqr`F€`Ÿ}€Ë 15”8ç¤ÑăFMŸ=øåeK×6ÖVq«iv‡±¯ÀgÉû*ạ̈G7p¤wí½Uđ61ixáG±Bl®Ú6₫#ïÀß^Úei Pû,‰ ÷)`‹6Ơ-q™?._ăÿ>ºYZv¯‡ïädœV×̀o9k'Atûåg&ɤ×À5ç~í?E23²ḍ̀9Zºjë*‰7î7sƠ$=?è̀«¯¯:{mH3½̃ô]à0Ÿ°ư­3Yă5äwAÈIÓ?È_·ó ă@y3å¦y%̣G6ËÊ5ººBIß›a7ƒX®Ç3ŒÓ%¿½4yîñâ»{—|d₫%ưåͺēíQ @À’ÚitˆÙÉ~1AE˜ÉB´ĐGÅ÷´°mpŹL $®¾đŒËâ¿ùSç×>wÓOK·¬¯à› Ú¼÷œĐiK)ï9*0±Ö\C·XÔct́C0Ÿ^’$T&ÉVáɘÿɶĐ÷ñƯi.¼$Ù}½ç"·Öi”³>fj,ŸßVØP̃”¸á̉ùWǘ÷ÿïæ!N7é h©TѲÚÛ”²]p;$ .¹8^?' É‘́´®çÆ®:Ư*:à;‰Á¯Ÿ¡47‚ó ¾wơÅså¼ÓO’@F¤€xU[%y‘¸ is>µ[̀éS ËY‚öˆ_æ!Póí̉₫) !à}Wœ/-9^]¿E:Œ÷?M̃†üµN¥0­Æ™¹›"ˇÀÑEà€ßÄ£Û׺Càơ!0cö<}qLQF„[º̣¨YÚ~ùĂolÀ½ÔkŸă _IvX̣3Ă²»ÏíĂ8k¢\uÉé̀¤{ô‡uÎ:óÖÜÆ'@“W¢#ñ3-¼Ô’¾¿¡ñ’øu\g”Œ—wOÍ“×vWÈSËÖÀ!Ë¡ùv¨CM̃$C>Z§­ßỖççë"́>k;¼₫¶ú€$9vOx¢öŸÀÙÿó±÷ÈƠ'çËY/M•»a„1»*áĂ vµ€µ„@(à鋬Feû¶mrë]OÉ₫º8•’œT]Ö§ß0ä·¢ÿ˜̣Æûzü#Kfă¢Ë`—zB^°–€Ơ{Ẁ?å¢ïÿÛÿN˜5‚IĐü›ñ_ l‚Á¦æÎ}:Î đ(ï}s¨Ü·Wî[¾çí…Ùiÿ ÓzfmS\yŸÄĂŸ[ÿ/.x_ï9÷K9\@qđ –ư¥KNZ<ổYµ¥Lj°ñ̀53KdpÉ ÙT…é¦F]:HÑ:½Ô ơ\Ú@Ø̀iY¡À¾±p/™p N¥ĂÊ‚_}₫}Øu0(ß~xỐÜ€~p̃¹]IÎ:½Ñ À†£áüÇÖu¬¶I“e);]’‚ăi ĐÆÑ‹!,ä Œ˜-?¹öTù¯¿¬‘—=Óx"fÜÔü9×ï³€t!`¾/íÛ@ †N†mll;«å’Ó&È́ÑùzâcS´]Û¥G`€Ö4]Ó”ÿücă5kƠï—µ0?ùƯ"ÅCNcĐ:SÑĂU@æO1öœóÎ nS}ù®¾È`:hR{mt•±÷.uqøßÁ‡Àñ€₫আCă°™KqS¤Fă®Àä$}ü÷V»¦€€±oPooºÆ‰¶µÉÂåk䛾†ÓÓä¾Ï_"W\~±Ó³ƠƯëHf 5ỪD„ơNƒlƒDÁ)™àĂNè©É?K¦—dH{´EÖ,{>¹í¯jÿÜgÀÓ₫•FÑ1pÅ,lS¦?÷³7ơ*¼Ö ‡yn€ O€ơ à? Û,.]p]œàèâïZsP¾û́Í_;}H~ú wˆc  ·_\û‡VhÉ…»À…Ă™Ÿ&ë+[e{i…´Fcºö|U•¼²­RBYºälW{¾”•î…Ri4|2¼vÀûĐ„9üKâ‡ö«äó¾jÀ A׿¿ñ>]wåo_–xƠVgæü¶nûKÂCçH8$AR²^"˜>¢P?N=́£Ưê—B:üÑÏÁÓü¹ä/)«#cüí–wɤ’yÛ¯_–HÙ&µ¾è²?líKó?­jög¥ÄÀĂ“@ ö‹¹ú¡ÏÍ%ư1â-̣Èê2¹áü<ƯO6V4cÇ@n ₫ÅßpƠqáCω@êµÀ5$ëGI-Ë\-gîÙ7~·¬ Ké©ÁÀ¹§N9-sè„–…=´¥Iú¬ÖF\ºà8¶pÀ±ơ}¸̃¼>ô7ú?û¿3²ÓĂẂkŒªÖ§æwüü’ŒºÈ µB,E 8GÏ–ä¦É³¯¾&¥ûë¡UÂëœsÍxŦ4ëöÔH^A|l̃0́Ù?LJ u¶4€X؉A/ ađÑ,y3̃ÿt~S¿HC¦Ï—9F.ûÅ2ĩø¬gúùY³è̉ƒÖo.ûúLí«Àaæ³¾ĐơVE²]ˆĐE‹¦<0ƯÁ³è;Á±ç?|å9uÜPÿr©zå1Ø‚:n³ÖŸB7ï ,3'¸¨7€‰N²x8›"FHà5Ê ]‰6Ƀ+öÊ.œ!§ Ï–MêZ8À1Q(dÊ«ª¯Ơêđ́˜½¦ öÖ€Lƒ ú€ṇ̃ûå>•MQl#J̀Ÿ}Ú9Á́ẨeÏ=¹K+3¦ó¾ wé8pÀ±đ-¸>¼a“¯ư÷Gß÷öôÔĐ95Í8¬Z$ÉÂZü p*ؘu ‘p/x²Áh ¼lw“,ÛT¦å4+G 9*1¡HG´M–n©’e{Zåú3†ËMN‘W²¥¦|/( È)FP̣gû:’Hù‘)Ä!¹ÿK—Js< ÿ|y»´UíVí?®ä!æmƯbXi”Ọ̈·ăC“oJ0ˆô¿*Ơüɨè«₫‘rZ„ËƠê±aùüĐA ØÓ‚©ù“ ‘Âơ]N9c®\3w¼\ơÇ5̉¸Î́k¯ä¯DḤG1í›öTY©¿́Đßrưù‚úS—×CÅ—́©VŒÛÊ₫H¬%c&É/?ó.—ÿÍß“¦ú:%~#øø9x~Wt‘¿ío¯B€÷ǘ½T€©—xM©<¿/(—œ2;;fËNœùĐ„"ulø`‰5ÿ…°úëÑ|x©̃ëó®B̃[Ú&¿kÈ0²§>W˜Ö9ÿ¬s.çí\úܶÀ' „±±ø¡+wÁ!pÄpÀƒÚ5ô! ?ïÿÔ—Ç”äe| ûµÖ·¶›pü¢«Bî5̀‚4àç˜ô‹´®(Ä̉¿œô°<¹r›́)¯Vó?÷¡Q3žôúV«^Ö¥z‘&Yº£Q̣r³å’éCd¸Ñ̉Ø"UµơØ3B_çư©«éÿĐJă¡,ùáûÏ’­uị́ụ̈ỞZ_¥‚ƒÑ‚ RûOÎưc ‡Ă ‡SÖCâ€ÄÛÙ½f°½æư1^zưsµƒÎûă>‘’&ï¾`̀›:R>~Û³R¾m½t`z…;ö^°^ÿ:v~Ĩ÷£y–%°¸a[Z‚̉Z»O^ƯsO)3‡e˺îB€æ?¼tøB@×÷c„€„́®‹Æ¤%Î?ï’Ü“>öà+iiiéØÖ™Ư²ÿM{Œ ·oÆWx`­.Ç!Đ Nè—u\! ?˜?₫̃·Æ—äf|€»ø5̉̀«¹FđÜJÆ‚ÖFÍÏ _p@YS»,\¿Wq7˜‰Â4GÔCyđ¢đ« Æi‘—¶UËỌ̈:9÷äQ̣₫³ÆËú)Å>öa¸›SëçƠ₫aïẠ̈¾ æŸ*ל9En}|”­^h–ƒ¤ ²º¢¶£ŒäÁÁ¯ß({h›o¢ÛS5·“³đ7éï Ö f¿„”pŒ1O¾qíYrÏ“Ëåù… !uÅ+ˆŸÓÔü=í_¿mÁ3Ëwk­ë&)h–ùN”: h s3Û¿æÚJY[“³ÿ?{ߘWqä?Ÿz·,¹È²,w÷†±Á`JH!„„”ƒJ:¹ÔKr9’p¹äBrI₫É%„t G ÍÔ0`±qï²,Y’Ơ{—¾ÿï7óöûdÉ–l‰úV~ßîÛ·;;;ïyfvvwvn¾,‚%`/¦x 47mrm`_[½nE%møètó¢TwJ@,9é áƠË®=cÌ»o_›˜””̉Ơ©^¦†ƒ‹íÎ~£ư¹A: ÀS P†˜ ¸×—qqµ?₫̃·̣>^ _₫M8Æ•óĐœ́Ơù^Jj&æ–0r^zxcX˜—.…eU˜ÿ?¨Â¿Dª̉Ñ?8µ'œµ&«¡˜î6©©m8’vJ̃XùÈ rÚÜỊBAt¶4H<©Ơ‘0Íÿ)Yrå¹Kå•’VY÷ôZi…Oü¹#€sß„\Î ®R` Ë+ŹĐq„ÁÖ5 U’ •"ơö§£oá_|¼Œ—/·å©h́ÿ½çiiª)×9ó̃¦÷NH[ôGĐJ…>{£J”9-á§êóƯ"ÇÚH×W•˦ »<–¼ï]åX€…ôăH¯‘})ü^ü0mưF>̣N DK9%€k̉“âä́“g-3gyÊĂÿÓS°¤x–Å?Ù;Dö~Ü"  À2óÆP€ÂÿS?¼#ẻ¤)Ÿ™–x:…ḶÔt êøEå´øàÅœȆù?ÎÜX,E¥đ5ߥ₫æƠüẢxu¬—¦<Ø(96­-Ͳ~ÛÙWƠ.ï^4Ĩ¿lü³înjKá+ ̣§[V/œ"?s®ÜưZµ́̃ü Lßm*üÍƯ-ç₫—Êap+Xơ[M2 ´^´ [ û·‘?Mÿ<é§2ÊĂ?º¿S>ưË5RY°]û¨§*‚øôØ™^!Pö›="î=˲®{öC³đ£1vCU™¬/ É{–äË’ ẹ́ÜZUFh 8B `d³>Ṅ[xh¢¥ÔB„o§¼¡-œ—™Z6wúÉ£f.‰_ó·¯Ă€~·^pè¹Øåq@a§@  ;‰ƒ†›ÿúLÄ\ü]Ù©qR³|Áç)“ơÇ)¼U‹ŸóâàŸ @j2a^³¹Xêêë1ÿgh–§€ÂÈÜ„2Ä*¡J…Á$ó0¤‡Ö:\)k÷·È98#æĂ§äÉcÅ1̉†9è¤ôQrÚ¥²¥¬E|øéÄöAsdCó?LàT48Í  °¢O¬XË„Á”%6,¯p¬ƒÀÑ?pƠ-˜̣P7Éüt¬4ráụ̀‘eäËY'…ש2¥ó₫4ư£¿´|đ„?ÅÁuơ*üư嬯öëp4¸>zàqKe±_úÜ)RŸ ¯mؤ$mu½h™÷'\Âc¬&ưb£UĐ<₫€‹Nf̃¥k ¼öè-‹:y ư;TnY+WüæeÁ¢Qù̉Y“0Mƒíˆ:ƠĂΰŸ6µà¬ǘx¤ïÖ¬ÑÅÍí3ÚG}ơ+öùèÚäÁ QèÉƯ•<Í0|Ơ•ú·½ùg=&áâ¹¼ü̃=ªjƒ#! À@)XJ© Ü›•¡?̃rÓÈüÑ#>ÇÅ5-°`Ÿ&”—+UaOVªŒÂL‚ÈVÿÇÉßà4æpEµ₫9 æ )Œ̀Q´G°Ûh¦S ´mîèÂÿîçwHÎX>5K̃5w¼<¼£Z₫úàS8î¶B ơøç!Ôk‡p£<_[œ¨óÆë²bÏ*=[ëù¬÷+ëöü÷˜÷́÷‡éëÚC‰̣́®=-̣‘Ÿ>)±U»Aó%Œü!ÍÏ?ûl[ßËq?|çª@¨Ô¶'ÄÙ]öîq6CX§ĐYU(ÇËûá'`!¦^+iÀ¶O;W@­/₫SÉñARa¹{f;úZ»cA Tơl„pKêÚC3G'‡'ÍYtng\ê®Ï©Ÿ¢Çe·Gü: G<2 /àx)Ô{SP }Tǹû®¼ú¤±™iWQøsew,5*…9^L™YÅ–Kó?ƯÿfăÔ¸D¯6–Hc}-ü»GÍÿê”Æ“₫.¨ppüÚËVî .@Œ…Ó›äÄxL TÈî†9sz–àˆÙ^\­ûß»¹½£dR »‡ómÈă÷*¬(HLB8+n}Ô?˜‘-:âG_«Ă®ü×Uÿ0{'¦É̉ƠÈ{äÈùß}@¤èeé¢Àå” §V¨ô ï´Æ(]ùr¼îFÅí`z-Û—àê«Âc§´WÓO@HÎ_8AæÁ´«¢ ß‘¢ ß³¢… úy1ë{è*h¦#y,ÈoE+đ±÷î@'Â-©k œ—Ö=sñ² $eÔ₫ Ï<ÚÛOAơüÍöW&È(0`  À€I|3RàËÿơ«Äq“güy|fr₫¡ºvTîÀ'ù¼H“k*WU-Â÷ÜE+À’¼ 5 ß÷âniDZ²œÿç¾t3S“—?& è1ø(÷ÑǸåÁ7Đ)tÿB\¼ŒÊÊ–UP̉C2úD)€€²̉RÀÆ¡8À‰mh3ë÷"Bd«*PØ'æ{9=˜Öë«₫@ái]"Éâ_,bÎq»y₫˜÷§³Ư•«Ï•_}l±<´³N₫ùà]p»ŒÅºÂmù3…‡£c‡Ó¸L·ú,K8QK@´‡‘”×,g«KekMŒ\¼t’LÍN’}Ø"Øo@ññ¬®ëÄ—$@D2DÓªÇèđ¾C_)*KͰ.ªm -ÉK ÏY¸ä¼ø±Óë_xô—°; ±Ưø¾„¿Y_v (0x  ÀàiÔxóP ô¾]—˜“›û¿ù#“Ăm!́UFñ#9 8[ăù³[ưŸG5y#åÁ-e²s_!̀ÿđù¹âv5SS(›`V%Àƒ‡êÚG„¥Á{F¡£FH,K0?đ0üdÚèùƯ ‡ô¨á3±`¼>¿«‡4D,`yĐ|Q”ÓG Gó­ù₫²^çAÀéÑ&úª¦ĺå~8̣‡·?̀—ÈËÉϯ9K₫¶¹N₫ûw÷J7¶Br‘£Nw¨éßæ₫¶Y…ơq÷ªï̃G•>7ùûNBؽyiª®¢æ89gA>¬"{Ê›́;b]O `}Ơ^̀ú₫w¡ôơkAƠ¢í3EÑP %`̃¸äđ¢ùsÏHœ¸8æÙ€dú `1‚ï/ø›í¯LPà˜€c’((đ&¦@̀—?Cü♓¾Æâ@Â`‘₫ :đWwΨ$Đɉ¡«à[Ÿ9€=ùủ‚¼6Z8ZU3µÁRa¥œßà)÷å=E–Z£Az‹C>ĂÑ~bB¼|ơâ…R‡é‰»×ï“Í» $&>I.…+àE'åËcû;$\wơÜáqDØÚqđí-y£Ễ‚Ç+= HñEIÆ ‘¶T˜¡¿è›ưUÉ¡đ‡‡C‰ …'œ’-ÿ9R/)̣£Ûî’–²₫ÙÚÜ¿›̣@Ă2Ÿb4¬­ aR±2ÈöëH«%"78 ÊËáĂeRÜ çA  %é@U³*r×' ḯdo¬yï,ú]PyĐ-IúÑÂ@gAÓ¡2oỤ́„)§¤êèßë.!ăÿGPÁc×*Üđ·áîN›/]í­̉V‡•àíṃä‹[äë÷í”ùGËmŸ>GḅO†çÀ.ø ˆ×½óÜ?Oïz¨-W×›0Aëî¬G“Gàv"Ôƒü.&¬#+₫'Gµ!ÿ /º@.Y”'»ç©/9 BTWưĂ¢¢+₫u½»à0§x¦€Đá Í6H76˶©Ü¹ƯíđøØÎ̉ÜÔ MO˯ß&çÎ%Ë'gJ3,Büè$HqÇ$ö¤e;Ó½{£J'rƒï›¢bÁ#Ä¥g<¾³’å†Ëν₫Ë¿¼ç«mmmíđÀƯÜ%p´Ưx„€'FÀpbô j¿Àœ}øƯßüçfK¿¨¤¾]GơΠ[ØÛüO ¬nÿ™$?z¼P*ÊK<Âq₫ß̀ÿ\¤f¬]…¹=‚ưöŒ™§Â1Ûæ¸Î÷?ÿM9[VÏÈ–ß­; å••`üÜnÖ-•å²®TäĂKÇÉ*¸§}`W‹„êK` ˆ$¯mÂf̉kX#ï‡J€k%†-Dư¡olsæ´l¸Ó ééÓ‹fäÊO®:[~ưÂayè©¥g%°Ÿ°ªPø“]@—iü wlônä12Ú/ɪ탸Jm}ß,Ơú ä`W–\»j"¼J́¯j̉>«³ ¾~öOû^‘5„_¶B%€?Œ4 áỔ´„.:?SG¥„Í™¾₫È÷¦€ PØ`Z̀º=q´ûÛµ (¨8Ùô-P˜B ’ŸÖ=aö’ C£ ^Y»fÖÄơqv+÷₫f{? î A@8‚$AÆ[₫7Ượ„3fç~‘£§ œÇÅr”—¡y¬Đ¿ÏrHÚ ,dáèß1é‰̣ÔæƒRYU'͘ÿçèOçÿ#ÂêH*8îJ đ¥ƒ……:BÆÂB*#ÇM‘K“G¶áº½Å*(ø9Ái¦)i¸v ¶ºJÆaDÆŒÏ^°H’2²dó¡&‘æôÉ?́aáq¢†x)uK‹8̣8‚èÀ́›Öơ¤Í̃¶¶Á[ñ¯‰xĐDÎ̀—;>»Zî̃tX~üûû%®¾ưÂN£ 6÷r€¥Ö”p¶1p ­¬+o@x7®÷¬ăW4‡„ªAîG>·5Ë3ÛKd̃´ ²rúh9XÓ"öÙ¯̃†}Ô1åí! ẉT₫h„$,-”ålsơ?Ëäg&Ê£»j¥èPœ²@P €m ó™ZU °QuÏÁåÓ Ü„©«ÿ‘6A‰u hôë—,£SăåÎơ¥£¹N§ Ô)m>™¸ÑJA€¶0ÿ(©”½ q̣ÉSÇË̀)äñƯơÛT†¾ÄGÚe‚uµÏÀ·Ñ< ̃x-ÏçÇZ̃ª}§"Âë-¸ç¿­µM¾}ưåƒ'—ï̃%»_~–x„¥®~u-…·m:ej0¦ÿ¨pgÏz÷D{«}‹–;Fçz=æWbuù fK ƒŒù^Ú›dCA9<9æÉ»fçÈ̃Êf©ÅÁN|vÄ1Â>” S©?ú?ºf€DfcbĂÆpQ‘Å7 ß¡åGȤI—§ÏX‘¼ö̃?~”ÁÏPQÀ›`*pœ€¯ È1%3%¾ÂŸ’9&ü™̉@áÉOáO×*Ü––7"AW°—cU>â¹Sü(ø#fj¯z_‘̣ë#À€<̣qNPø̉’0w\ª®hªÂö>//L+±-[f–Ι³Ä5 KÀK7Ë7îß#+§ŒŸ\w„Ç̀Åœ;|À±P„°¹Ë©Œ̀uu:àëŸ"ˆ•&G Úoe«2°Ëg₫W ‡₫2mñ©r₫üñrưß÷Èó̃‡>ĂÏ'ü¹Ă=‹¬øw4Œđ7,ܯ3—ÇØ̣‰'[< uu8úPÂø>øǹO€9/âzŒønh‡¢X~¨X¾yëCr¨ª^>µr‚ä‹$§sÂô –âa—̉`û@Œt¦Î§¯Ÿ.ÛíÖöMQåôס́.o–‡·W„§J‘yßY7|íWŸ€>ÈdàˆT}c(0bd¶6|ÊÄ [8iJè}ÍŒÀ?5(“æ©~ bÙ© ̣Ê¡©lh̉-\O¦ï­VWöJ*¸Áع̀ñ9ÛŒ Mâ yƯ’;i:Fr±̣ËgÂÑ/WĂ;Fo#côøÑEr€EÁÉ´®@~‚öµ×6ÉWîÛ#Ë0 üí.’üY‹UÜÅ«Ă ́ˆă|Û@E@Û§è&Ä…ưˆ 8€Êk=†Z5° ‘«₫uß?„éØÙrăÎÀBÊ8Ù¹®~1GNá¯[₫ »¸›‚C 8"@á?˜@¬=ª¸«¯Ú|F¸,yüJ!~hO%}á¶P ÿV*PêÊKäÓÿsŸT74Ë «&ȸ‘¦”¼p]8¨;¨ ËaÉvüAóñ£ß¿‹d£đ×)Ă²¿¢%䔀O\úîÏñǼV"Vèî³A: @ S=Èܼ(€€̣«îûĐ̉I#/-ªk‹mÁ ~MÉp”¹2Aƈ‚:‚†ñ™ ̣Ra½́.,“f˜²éú·s6/¯¥­ @&½ËḌ±Íư3æü?OÅ£gA®çJÏ-/̀‘?>_$ Ơ•ÊÜ•±s„¬̀̃â<Ô!1 rtÈ §îi×l—«WæË”‰d_S‚4ÖTéHœfö¨§p´ë2Ø*^?z<¶BZOK³q”Ó>¡ …?• çđ‡> FO–o]s±œ==S®üưf)ß¿XQ(øiÁàúÀaÿT°°ùSH$ &J²,/íƠQªEËXåY“w ,Ë?ÅS˜2á “&̃ ñh ¢·5ȃ±r!¼6%Sva¤^‡µ$ª¢¸¾6ÅG÷ÿ-{§Ö+‡ÛPóºfh&*P@>²9@øPĂ¹“gœ!đ°6đàèÄÇO@8~Ú5ß (›¼îËß\ƒvFr®” ɧă51@j ”Ç«PHåbî?«ÿ}i§ª¨ĂóûÆêÛGS.W´Ssب»\ >ç¥ẨFʉ£Àéó§Ẹ̀)Yr?n¨­6³2¤ Ièl'"$Q̃5«CA@ÑA%âúJ¹ çL#_»p¶Tw%È~¬À‚EEñt|° cüR˜0ŸDB°_MÚ½ë4s÷‚ÎûĂœb ₫l̃?“ËΜ/Ÿ8s–\wûfÙöôúæÛ ºåïHÓ?£€Hˆ –fÔc£—Ơp| uÙUGIä dƒ Ø® <ç;‹Ơ%\S$9w”8zÚk¹0à#̣í0Í& Ă”xođYÊ+¤XØ”fsçA3æg„ÇÏXp^wbúÎWŸ}¢È«­5 €K+Gäïh  À;úơ¿%;¯Œ́ăŸùÊơSF¥dUao6÷›0öúĂ¼ñOeØĐÀLC2s¶;1Z{ag‰Ô76©ÿw ¤#s]`ơÉäWmàŒ‘”ï9Ư¹̉úà̀äÜÿß—ï\ºHRăå7÷=\G?áü²*ªĂÖÏ IDAT=D_DR z  ­đ»1%đÊ^X-bRä³ç̀’ÆŒ‰²»àV6b« J­hv¾§0Å3”QE1áG¤ûªÈg?tÛŸgÍP<è'6AFæÏËßs¶¼¼»DzଌoV³¿3ÿs §3(´đ1q'́HKl¥ßĐ_Öée¿ớAỊ̈a>À¶đH=çhhOùˆR}R̀°#"\[,OvËÊÙyr:,…đ¨»P¤Ô ‘Ösơ{ö̀kå£XeâùÖ°0¾.Ú»U P?1ŸNAt¼€ă¥\Pï ¡À¸ “bëkĂß¿é?>‹C€²Ö´b‹₫<¦«|S…‘-́âœ4·²MÆYï[J›dó₫iniUßÿ˜Đ=ë*¸ÈÚ½`ǽ²Ü3ÄNA`̀Q³N`<俤f“‹–L”MẠ̊ü¶‘Ñ¿º¦ D3lÉ,hEçÈM0³'úPŸ[ƒ” l'ÔƯ!»«¥)&Y®_9^ºFæÉkûK¨­NGíJ?ˆ§đhCئܸêsÂÆe ·û™éŸ+₫9"ßúôGå´É)̣ă¿¬‘⃅@‘.l9÷9¬Ÿ “}‹t€xG0đé#:1áï²'l\{¤íö„ëÊ=&¾ZOÁYZ‰Đ|ªÜhK¤#v>Ô•ÊúâY8c‚œA% J@S§·(¨ŒrnơơƠxqSĂXï½6£…‰+µºÄ­ J—¼,ƒŸ€üÀO „ @ œñ‚ª¯?(ü/ºùÁ1ן3ëÓơm]8­…[±0h5fK&ÊnMF·ÎÿHŪí$y­ L¶đđlÿă/0ÎÿsîÚ(]A*oöb–SŒL˜m₫?¤+₫©h$eŒ„ <ùkJmåa4ư»½ñ&$ ¦ÂQ ïZ#t/h£̀g‚mbz¡«]vUKM8Y®ƒ:6O^Ø])¡–j(9Ü&hp\-…Ú˜@‹¥’ ›÷W¿n¿¿.29yÅ©r5ü\wëó²åµÍƒùù'ƯL s%…ÀfôÏ*¦(ô¦2Ÿ &Yßà†áâW<̣[¿DƠ@úa‹`]…l*k“¹pt&¦ÀYPM •à3@?̀5áƯ©ÆÀ4‚½*¥Q[[’—¦~̉§ûôư·?×̀ ¾m¬, @_h¼àæH@x¾ô·z—ÿó¿üÓI£RN¯h́ˆá¹ê¹Fxeó?WUóê–‘) ̉Ô–G_-ª̀ÿCøs ·ª`F9¿@¡èSîäymr₫ŸíÇc^8 9₫虳eñÄ,¹ûƠi¬­̣NPHR´ DØ3D6€ëb1m“¢mÛ¨Èq_]ó°ÿP¥l® ËVO” ùdGY“Ôb…zBB‚á² IAEáhÜG„?ZCY*QªÈ ?:÷ÏÑ?v/$O]!¿Á‘Å{ Kå¼Gâ:[´?¤[7·₫Aê”Z3½æ"|UĐFúË>\I§AÖ7Z¶ÁĂdĂøê³¯“=wmµà¨ç× ,˜‘/«¡lÄN“f,NÅ¡Îư*냬iÅœ™|ñlI x¥x‹$q+ol.}Y4>ṂóÆÍºkͳÏ5>P¥//¢‰y¨*¾=̉̀ñ€ÚĂà÷I›‚Pà-E˜Ü'ÆÂ—ù%‚1‰/ś̀b.nVçĂa@a*8oá‚Àˆ×?'=*ÈÈeȈY’ 8½ R¶=S E¡[¯™øñT€ÄÓ½—` d²ÄŸJE'c܉;”œ®öVÙ¼e‡| 7+[nỵ̈%rƠï•ÎØ$Ư§= ¸¸3‚]}ppƠîy1{@üuîÖ ÿX(2q˜–ˆ›zÜơ¥wAè·Ê¿zX­‡˜¨Âß¶1†=%@ûRôêÛïQIIRb(‚ƒEèNPn´®½~º]ï $éĐÆ-‚8@¨;JíÜ$ß¹ư)ÅÀΜˆ­’1°>áeéjNHk*§Çå;à̀Oï;̀I*…ü´M´-‚´jáHk(³‹êä™}Ơ2#gDú÷ƯñƯüÅ«gCËä ®¯-‚̀'xw!„w:à₫¼µúOæ%c3’Âñ±¶v€Cj₫ø˜©1}đNưëâ4Ôk¬«–Ú*ŒÈÁÀ9rµ‘?™»1xG B#cîÍœùœeưÖeÔ¨ VÔÈÂñ¿#FŒ{7WB@t ‡ ơÀü{ÂäâiAŸ ü¯8^L«@ÁĂ9wOc>OàûđO’ç ›ä3.•Ë.8Sb’ô˜̃8˜đé+€B ú¨Øhß„¾GoƠ¿ZXóÿq°fĐḄđ¿)£qnÂÅ?[/ơ¥ª”Ø>ùÓüOá¯Ó'Ä×ûó^׳D⌇*DaFùqÀæ;Aߨy‹L w…©ŒơRpâcù® răÖI][—|ăÜ)’·ĐTè,Ȧ Éuq©"ÖJs~ º<q°ï9ê'€JÀ–’Æ0”€ĐÜiù îùËo¿=åä3gd®D/f~¤©ôVØT̃Áà„€o (Ăºö‹_ûhΈĩ¥ Xˆ?È5Œ²Œ¡RQ’Y‚íBp†dLZ¶PuÉŸÖ¦Æz,₫ĂÈ#8b!T•±™lá<6È‹ÚqK7f¬ æ€=óq: 9=]ÎĂÖ°'wVI \ ëy*h_GrF : ‘<$˜ ØÄË‚¯‡ˆæ  …×3lØS*í‰̣™w$¥‰ùRTX¡CơAA©va°­¤YỐ>˜s!‘¬¹gË5gN“ƠÿơŒ4m{ƒXÏÏ?Mª@ƒ@‘Mø£¶£‘× ‡yß“) ,ï§n5'? ÛRFPkw`đXVß$± ăƠ Ñ×ï}"p.£…",̀“sffËúuXk‚©*ü©đg|—z”0C"‡àE=Ó|ÇZu"åLAT¼° °R­Záđ²ăr.]>ùÅMÛ·V:Ш€Œ¸LzÈj®?Í ÓZ øygP P̃ïùmÑË””ÔGƠ¿ùÉÍÅ4ÀT "γªs’Œ•£%ộó¤’omíÂÏí(•†ÆUxúŸÎÉ£¬đ< )SẺqEÆ.ÍbQái¦s®9ÿO=dÖ¤y÷ü ²nw¹”–•Œ'·FÜ ‚ "vđ]lOÙđP-ÀÄ‹_?'8ÜïÀâÀØ” ¹áôñR'‡ H¾i˜`üѶ bqÅA pưp*`̀œUrß—VKm[·ü₫¶ß¢8µq₫k[wn-/ÆÓ’Uü—ky.ônÚåñÛ˜đ6~¹o³®Qø“aÅ|ă›ßú$̀Ù3’âé%-â@û‹,¤ó¥`ŒÜ–7+'U^Ú{X^ܺfù0Fÿ˜C5ÁLæ©2Ö+"-£̀ØqFÇpYÔ͛ӬN+ˆóSgÈœñ™̣×Ç_–†æ63Ư{ûÿµ-VöØ®pæ÷LI`![=¨6*̉Ù&›ÖH¬7œ6^cÇIÁÁ"lƒhÁH?VEŸ aló₫&ücaªˆ„‘¹̣¿Ÿ>WZĂq̣á[•.lsSS·7ơÀ©ù+Ư¬#ƒ]ñÏ>˜*BÜ æ _`ÄƠÚRa{Ăaà­j=µôÆ9̣Bơ-"p¦đÔÁn9ñ$Y>1>(Z¤ST)ñC¤!§`x|…Q,™iSçPåO x½§î›(9\ßFDxỚü‰S¡lزs,uŒV±&¼äQïQ Èx{Q P̃^ïóíÜeN7ÿcÛ)‹&e}¼0‹€Rb¥¾Ơüù«#$åêXÓñ<×ïŸ;(Íơµ8Ø¥Ó̀ÿhdÀ¼P^GÚÊ4ƒŸ2É'æs0n›7Ç6@ÎqŸ)§-˜Œ‡±̣Ħiiåm₫a6‡°æ”„)ŒÁøJÛVˆưü  ™¿) ,mí»±÷DpÂg,Ø{í@­´Æ&ÊçÏ̀—–´ñRTV¡ëx†€ ü‰¿*.´^p$G\ªœyÆJùĐ©rơ/“ªëmÁ!ÜưÚè?jÅĐ~ ƒ₫~|]_úéùg“njly8-„¶đ>ºêÊdO}HN9i¢LÍJ͇ñMÀ› Jà²>¢¨~V^L,ÆîƯè·î ¦BÊwRÖІO3>JÀÜ%˦¬Û¸c[ơ¡‚j¬‰íc‹ ‡€r?}å¹gAü6£@ ¼Í^èÛ¸;ʘV}đÚ±+§¾´¥3œM¯kcÓtq[C+ö¨¤´ù₫¹EpæØTIÄëÁwK“:ÿñFÿÊĐøç‚n³ĂM_Đåé7ê. œ‹æâ¹x€„äd9c^¾<‹•Ù»öÂĂN/çADf₫*lÅÓ%´yÂïëŔ¼¶U9̀đ`áÖú³a‘P%  RjĂ ²rú(9kÉI:Úß~°´À\4ç₫ƠÓöü÷PBª̀_vỤ̈Ñạ̊øk…̣øă«£$;¥ĐưùM*¤Út ˆåû×ÊÙh_]k(JÙæ`q'¬£N¦ ́#R‰ ([U‡Kå@}7œM”̀ä9·ÁT8U Đ2€áHÁ*„‹Y î^Èå½~<ø€TÑ@̀×N%€–€2áSOÊ›°̣ô3f>ú̉Öí5Åû*â°5ß!Á:ĐŒâ ¼)(ïÀ—₫í²2ª3.»6wùô1—‚fWó9~ÅŒœKÁ ³0ŸÚá4Gü&b{=̀û\øgóÿ¢fy₫ó͇¥ºªRÿEÿ¡ ăåÑ¡/ÎÇ<—oLÖ˜­Îÿ{æsV_0yŒœ2}œ<ñÊN)ÁaCơs¡¡5̀—×5iL\ơÁw÷.vm³â€Ÿˆà2´°ñŒí  …ù´`ú&¸ îHΔëϘ,e¡‘RX‡A¡.ó FL|‚̀]¾ZFf¤ÉÜö ¶üíî&ø£ư€Vèƒ)äØÿ)ƯcÆ,ϺVÏƠôî˜ơ‡¦Ûµ6-åđôh_XÏơ…iÂæë¶Ă¼ÊÇ¥¨9F.9eª$bÁžäªxœïÍQÀ;!oŸ#}íÛ·ˆ½},ƒL–c:°¹Î º©3ÔK×âÉcrÎ=û¬Y¾¸u[UÑ%©Û‰¤ÿÂmàïPÁÍÛ‡đöy—oçD˜Ñ™—}*— X¶*d¼ÙÂV?¦«[¸÷^0×ß%+&g"§[î|jƒ–áétưËEm:ÿo|ÚèÆÉiÈr£¿¬d¸ Ê Épqéq¹¢)irêâY˜ß É ûqÖËÁ€Yưäs À₫ÊsÑn–×Qé·mïY]T%€=E:R—m8x ̀„B{G›́-®’øôLùÔÊ<Ùß™%å¥E8º âeê)çÊ?0[e³<ơô À ³¸ê_ưù`kÄá¨{ˆôơœ,@d#½è£ÆpdEÛ´Ôñ)„aưđá.±WöV(Ø12/)–}͉̣±•SơJƯGó™ zđ¼wyúù<¿;<´-¨Ñ˜V ü³5(ƒơ1a(É¡“Fç¬:cƠŒg6lßRY´¯Ö‡¥KºOÇƯJ̃û~{ô/ÂŒÎùЧ̣—MϹ²5«±{«á}LóK…çµ&ä5Á2'F&ÉËâRưĂk›₫ƒ‘9€ÜÖ ÑT”¥3/"´•c!çÿƠ€€‰‰²hæ©…̣Ê"L3´ëîÿוó=3†Ïæ˜íÚó§ù¬wP© pCAªöcÈg/íÅ>`,×|v×HfÖHùäñ²£-[Ê‹%3wüúª²¾°^~xï+ÓR£̃₫:¹~Ö Đ*ª¼v¯v"8xÍ4rờÀZ Lûçí°¶imYÊ:çpH³Z•ơÛˆŒøQÓu U•$¸v¤¼¨@vµ¦Ëu«¦èvƠ‚ÊfUÜ̃¹—ĂwÆƯ%œf¢µ‰'MĐGZï!đY†Ï¡D$đ{ä½·-•÷PBíôØ?qLî’å+&ïØwp{wG[GC]­'í¨Àî™v½pq´dz[P€¢‚Pà­@2¡đœ©ă¯†ŒŸ†9₫ƒbª£{öƒ¥ g§“y2́;LS<ü®ĐkÊñĐó×§=—‹îùXï¨'ټؘ‹t&Θ9&U¶×F&™>ai@ă±»÷b×f¯́£̃²ƒË¹cÛQ@ø°wP±¡ưs1ÿ‡_âÜ̃X+¿}d“$Ä,”ï^8EîŸ!aŒđ+Úå{·?-IµØ '1ü*Đ¼z=Ñị́ç(©Ô“®‡=sO°©~ªGÛr­>j¾́H”ơ‡Ë%º±àR%<Ä,ñµ€¤Â1Ñ›^Ư VMV7Î|›ë0(ÇzL¥;7spÓ¦³>¿7­‹4ä»Â£°§1Ÿ^1©¤%ÆI2¶s²\Zb¬Œ†U,7“²“‰mˆÿg–Ï™vê]¿ëÁƒµị́àoÿû=8¸¨.&6¶éÏÿsó.–á…Ư"1ô·€h_4Ÿø  ¼y((ow`rt (óm÷‘!!€áBèÑÀ“3“q|-,³sRôi%L®ä¼dȔšb')́¨hŒBGçt®Ye˺(‹‹ị̂FeÈ̀QỊäË¥̉̉Ô PläOÁ<ô|3‚£‡¤1g[~%ÀLù́7ûËƠÿ]M5̣“û_‘îógËYSÆÈ˜Œ)©ª—¸¦ %%IG¸]G±&TèV–0Ö e<)€vœ@JœH`} ]ƒÅ4aº˜O†3øÛ²©â3˜~¹>ÎD›[>U₫ó÷!˜©ô~ø½ÄÔWÈơ·Ü-?₫̀{¡Œ.hƯ‹éöXÅ.¾Y x*I°$ẨÄú)đ#Să¡Ä`1!„=ÊdÁF*~6̣ƒ§ôÜÔÁ*Å­‡8¡0”%!ÿGF§¤„—ßôïl(Æ·ÚƯỰ̃3–¾¿(œ•¾mÓ«¯₫ö»_ܧ€L}T”<°́ .ßƯñ[đ|iïl”£|‡#* w2_|¹-0 +ÿ¹ơ/ sçáf§·üEq2_øLĂT=ªÁ¢|((ă¶º–ܱ¹lpÚ†å3^̉³ÇJ3œ ×Á=18µN1÷á,Đ*¨àÚä#¶q´Àç,¯1~ÜâÀ̃JMùMvCX„A—Ti•_?ô²\{ñérVÆ(É‘.«Î8K[·N:j¤ ;è"™‹ÍüVĐ½W„(‘G%@q0¬íN úÇƠ ̃HÏ‹­ w°xÔ<®ÆØÅŸ/˜î̀€Å „¨JJá¹¹ĐR%ßüíƒ̣ͽ[®X2NîÇbỞúv©«T¼§tj¾· LgÀÅơ$c°¨•óÿÜåÂWÀơ/î¼= K=c¶ẶÓEœmˆÙ+~‹ǿ‘I-Ăºk%&4&=^fI c¦ ynî{Ùƒ©ˆ÷¾àá÷¿÷¢5µí¡ÔŸ:íY£ÇÄVW”ó¥đbp/ÅƯ[nđû–¢@ ¼¥^×;YåĐ³{/R¹‘)̉ ›ÎĂĐDîƯXœ ̀˜NoÈt5îÆ˜VM1ª8O#óx­@FÎHyËV¼˜iTæ'¼·¥´Aö”6i™ˆ«\”÷sMTŸ‘kÇ=tœµw¾{ΘÏæè&nˆÄ? đ¾ºb¹Ñ ̉çÿê™#!8²«¼Qn_'DY×ú́ïáñ@LGɾ°>@;üù.Ø~üø=ñÛè†uÅÜ+#ÆH½©¡I…ÿ…y“;í0&«³Œl.mÔŤôvÉwå¾»8m xơF‰̣<¾™ÄbÛ®]‘bô}Y~1üÿÀc¦a#€Al u„¨,¤`:arv2\}Ö¬x¹`Î…«ÿư_*̃tèÎkVÏøµ–¯˜Nœ5À²öª́!ïƒđ @äÛx à P@G°~îâç:$O§Çl™˜"_»p–|íCgHRÆXe„\µÏ麿Mƒ¥U€ ¨LĐqzÀ1PăjnmáýƠ˜,₫稀Dn” °@`î¿£™®×©TPB<Y¦ú î ûÁ‹÷¼Ü½?veñ¸ß uQ‰J€AÂ$.ˆO­}}‹ÏhB~¹°NØrXbSäÇ9Ep¬¬$Á́œ’” ÉI‰’ˆyfn¤×C ;EĐÑ mis*~´¿G볇ÅQ#ƒdÖ€(EXÅuâ¨ƠOà¡£[´/ÇŒµ è®Ê€ó(åN(a™É!ù· fÊÂrù̃_Ÿ–Ÿ=µO~¹®XY-ËÏeGȼ4ŒÖMqe0EŒmĐ`#Ï"¦0a7j´¡Â¹ú|J\i¥ 2@KCUc‡l-m íªhÖc¡Ó’ăç‘|æÇO›̣£ÂªæƯk¶WT]ö­ßŒđ§^Ó=yúID,̉ª—öß#+oF €7ă[ pê—c̉BI Uc«_ï@Ñ LÑ“?yrŸ̀7B.œ=Jn|Ï|ù¯{1‚­*UÆÑQ®Mă¸¡¯{²lđ@̣Í>9ZXœ”Ê<«É„©3¥®ˆÿ¹½y€¡Œ`'*ŒI³]à­kNáûzi™>kVeZ‚xsÙ †¯ÛÍ Ô9?üËäC‹sä^ ?É!OЇ‡8ăÓR[.ÿ|i‹üôŸẽ¸TùË §ËU—¼KRÓ3l:‹Ư°hĐYÜk ;2Zg₫f›Ú.c2ZŸYœÍÅÀPÛÚ!%5ÍÀŒL= Å‚̀Ư“>¬LFúá=êƯÇIY®÷3?4>H |ÈNOQaP A¢#ztûÆ1¿üëç¤ù_X=Q¼åF=ẁ´$™5–̉-V÷›ó\£•ZOÈQQP‰Jÿ7.G æ?\³ÿصK ßâjÎ|-đ›â¥ô2Ö;fÑỵ³Î’‚²*9t°PZ¡X5@àÖ7µJuc«lÙ¼Eî|́Eù́ï–GvÎjs² IDATЉ_X¦d%ËÊ)™2®tl)¤·¿Zđ͵C’„Z¸VCÏ»à¼?¦ÀX—‚²]¿MbÆï ô%@ƯøÑ*†ÏA¿÷.Ô‡‹Pau ,Xç‚S Û:º’Ι1*åüÙ£²›°Úđ‘íáG·•ƯFáĂ·”>:7ŸƒKGDvÖ:̀F-ß=³œà÷ ¡@`xCÈ4zÂđ³–Ëyi`J¹àië–­̣áMÛǻesåêSóÀdË {*¤¨`¯´4·bnS`x6ª…%\’–Ón0·h`MXŒâÊÆ8z>9$FÅ6¯«s¼üx¬¿½”?~„ÙWèÍư÷L†?ÏăhÏù̀1|­aàÈh;"à\½–Ÿ­=(c±Eđj8 ºíêS䳯!3ÛÖë(“ Rk;vcbo['³‘.ê0ờÀKĐSÓD–÷,w"ơ ¡ho'̉«kđÙöÉe(ƨHeR§™s`ööQyIL’ÑX‰ßˆùư>¼KGïôV锯Đ—J)ëÆ#ÿo>/÷<;B2Ffɵ§çËØ̀Tơ{‘‘”.[Ëđ­vcË<7‚è¤;·̣;¥UK7lz‹ưÁ·ÍÁ¬ÄQo#qÔ£èĂu#mØÎ°¹¤Ê­H!™:*Ỹ=k_µ§¢éª"ø¸úÊË/xeOiÁ³Ï¿Rú—ﺑƠqŒ×RäYf„×™đ:Ûäå¤IØONéÏö˜ÂÊLÅ´¤'…°o¼C~¿¾D._2V~ù‰ẹÛ'Säù—7Kiéao”«S\ÑêÄ4 qû ×˜ Ld¢ó‚C¯°!6ê¨ă5üGÚO(?Nû!†:e„‡ưxú¢twẸ̀s.–ÿzïtybÇa©?|PáM’6uµ ‘føÓÑ8FæTp˜ŸÄwaÍÖ™|ï›—ËŒ-@ÍJIÑ“1é³;a0*—z(Ø/€ï–k6°]•(ék7ÜŸ .Ûà÷ɠߨÿ#byUPGë‚ÚøE«w'°è«ÅtBJO•ñ#eÚ¨ÔÈ|¸+!CæÏ˜̣3(ŸÏ̀ÊN¨­®â§Á*¼H†̃iË ~_ pñF ¼™)àăđ¿|öËå¤'/å!@*¼KæE.Âñ;¢$Y>±éFWm8[®0Bï‚Oü­ûä±­å’œ.ËqVÀe+¦JM8YöªOnĂÈ #`0D2l àˆdI1Ÿ̀’̀Ø̀FO˜*Í+¾V*»Ö*\O@åÁY#œÁW…±ŸS{Æ4Ÿ10Ïå³= ^7µ©.â ÉI“reÙä‘̣́₫Zµ’P™±€¤uØgc̣Û°µ1̀ư²*Ó¸8…¤ 1¾#₫¥&àHi”eM¤À/7¿ñ™IἬ”åcW¼÷Ư·̃²U驈ø:"톢AN €á¤n{È)0qdR˜Â½î~Ư¨¥¿FÈ49 Đ®d‡Á!˜p¸µN₫̣Ä&y8-Q.8uÜsêx|~{±¬ÛZŸ©­`Ú&)È»°UK9X“ú·³Q,ñfÂưçÎJ˜¶:[9ä1ñëï₫̣ûăŒdÊ₫gL3Ï̃“·kŒ_̉má„ eøT¤¨êDi‰R¸1¥B:/}÷¦Ă²^ă>‡5_»|•ÜöH¼úâsp*ÖQm¦h²î€FhÄÂ,2â ":Jfú8ƒÂA]ƒC Vojg½ª _-§£`¢+ƯUq„"€£ÿNœËđ©ËÎQœÿđR©t4àÛÁw©£ |î±7¨½‚ư>tUEơÛcº§kÚc»ñ vÉÁ¢ƒr¨8eà¼:y”Œ•¥§;==Ṣ2»à¤ª[Ơµc±j§:â6B4 %ß4„6é§¥;‚Fǿ³T€ ø̣CzÚäùA¾}ï6 ¼‘n.8®iÇ<1]̃AxpâY½z,oK1ô`ÛÛ#ÆC\¯†îàq4À)‹fˆÅ4K×è™rÉâ<]Ôw÷¯è"T~§Ưđç·ÆËèEáß]7¦§hàJàÛcâPÊhNÇNT:ºä¹­’T&©É‰²cO†ŒŸ/ù#dY~:S!î̉…|¤Oͤo ®À{̉…€È§÷A¾ùQiæ^˜ß;å½®áG„@σ'eơÍØ>üñ^)øi…£}̣„áơëCOƯÿ÷‹P|$.Vä—Á/‚—~%ˆ‰÷•¸9‘¯RÓÁÏ0P P†¨ÈᣛK²6ÈQëל7à0˜‹çB@º¶%óẵkgÈDÉ́êå¥ ²»¬QB.•¯œ;M®;-O¾óĐ~Ù¾u =¹¬”êä}ÉÑœÛƯƠ)Ó±ª¢ °¶ Ă( n!¢_̣kMă~^R£^¨ú 8MÆ£UŒ&öDŸiÆ*HôôđđsuƠ,Œ2*øYÆc̣ŒiƆôÑQ`5öˆỵ̈Ù"É…‰ù“'Èϯê˜c.غ$ ,…îq̣¢)¬p8¢Å̉+í·‡ø‰*́“_Pt£À‘”‰̉h`)CâX©v¬:Ú—^£ÂI?NÅpôCv¾}ÙRo•Oí*–ζ&ïû¤™ß?¿Wg`›Ú?Ʊí’ï£WˆóđP¸°üV…XLsáÿ$4¿Mújh‡`omi‘—ê%¥¨ZÏ XŸ3Z2²²åây£°µ0Ư¬bèb,ÉØƠ‘ O ô HË€û˜WPƠ¢øq«(ôil…%̉¾7ønø¹Ppờ,*¡¯ư—Ơ/¬¹g?Ôæ ”¤× jÊü¼ĐJ$¤~$M»ÉgA  À05ùæ €[LE%€¦yZÈ\Ér¸÷?¹Ÿ ³êjªäç}\₫8:G¾yébùÑfIøư3åºÛ·Jù8"Gâ€Ù‚9ê¼.îÆNŸ£ưÓúC8¸Åc‚(dn†›±@º€Ö;Ÿ₫8bDkƒd̃=¡ë=̣(.ă3ÆèÔÅ:̀ÿÓ´ëdú~áĂgN àh#ÁvX öÂoüa¾₫ø)ăäÖkÏ”›ïN‘¯`.ƒH£VÀ …:°8B 0¨wÑ₫âˆA¡fgNj—ñ£1¨4•Âa°»^Ó'ƒư! ƒy¬₫>^î…ÙÜÖ`å?`%åÍ“éS&Éw-[^Srp´OÅ–twß,Ûó¿{/–Çe–úNàÙ‘ï•ß4ï;±oŸßr{,̀ïTR;è́ g@Qmi‰“æ–6I)-—Â}ñ’“7A®=-_•éÉÙIZŸm̉•v-ÊÑƯpLù́}|\D¤2_! "¸ï800b9zÆ̀L?¹·.á_,Œ₫UøSđ_TX׌‹‘„á¤@  'uØo8ȤÈHĂ`¦UÜp¥‹ôsÅ‘ï+K‹ä›ùÑ‹%Ûànưè|¹₫v‘êCû± £.ôˆ£\Æ<¥#éƯåMzr[GnÈ÷ø¡Å¸á½á`Oü 4°¿®—}DÄ2G Ú–¿€‡³.ld¦\̉Q†J‘?øÛ§°×…,¡BĂ­k*”ĐO‚‹ª›ác¡PưüÏ'N“µ«ÈOïX#¡²£êt@…`¢¦ë[N Đ @‚ï…[ÖÜÑÂN˜GÊ "áêÚ[pJ…£ăÁBrpú¯kíá¹а@ס\! Zë‚QĐ gEɗΛ®ëMn ëóA[~?ºÎ±ưI^_‚};̀­Ạ́¨\q?̃+²¹_Ÿ]Ũ"€v±>  X|'NL¤‰Jê²lYñÁđˆ•«Vä Ư ?µ»ïß”;ư8´Ă„(YMÜ{¯ÏYŒXŒđXG½ ¢đÂñé8s*zß‚\₫Găâ ư]4;đ¡P! L»`wwA<¤€!%gl¸(ÀÅv<£‚×&3£å±[¥ Ÿ 0Âd!uôÀ0TuuA¸A sZ ±¢H®¾å€äLœ!?ºl¶ǘùRÛ6Wnº{£T.Ñ9S2à“±‹€ ±¶®#/ô¸å ,™¶”jd@xGs¨ÛÇË#ÏÏơÖ#?Gd=ÿ³ ¯!âÆ0"-E8M¿Ê¼#A\ô‹Ó$₫dú½R`̀ ̉¤>Ơ n7ûöƒ{d^²`¬´\vüá̃5RSrP•€¶vSbà=ˆ£₫î0-1®QOÄzˆµ"`=vb#.íÚï+¶rf}8"Ïœ₫đƯă~¸f‚ “NáÛ€ü—́¼i2ù¤9̣ĂÇöÉÆ›t IGÿ̀0§Û蟠=+ ̃a9¡Ï'|?ÑàMpj‹åøVđB9=@—S ñø®=K½ èx|£m° `>¼* ÿÜS%­(}Á‚׿môŒñÇiƯK°»®MZxFaNfJ|èE-¡¸x úhëuµâÿuùQñ-„ê 6L³ —‡d†’0”Ô `  üÉâ1Ơ™Ô@8C„i¢’2Y0F²ns¢“r9fÅ¢§¸(*GüVÚ'¿e¿̀8é$ùÁæc‘à¹ëùd)(­”JœÚvù’9€¹ÑPsø)0Q§p•“Ä×Ä ׃z/bç &û ¨rÔàîç–D!( ˆ//“zÊÑù•–¥"  æç,×¥bº‡Öp›á{挒î÷½[^^ÿœlØ[&±Ue(Gå¨ơ°.óØĐ¶µÖ¾/ȧÄÁ?£–ĂôhXöÿ̀D"Gđ.0EjEsÜ“±•cưcÅÜ’5l̃Jh唀pL¼œ¿d,ÍM–Û₫±Ûû°ßNKA2₫ˆ̃ ơ¢(đ"(†^A¾Uܘ˜z¼X”ê@̃Ă€3èç Ög,;S¡T6¶«ïÿdlå£ ^á"f¿¸¤}]\£¦~Flÿof礆q6Fè³—œvsC}]ª&à¢ÀwW ̉”;N°(₫í-øJx„¡¦@  5ExĂEđ×ÿøôŒÆđôîcoÈÇcÀÁ”±’»á¢€†,Ăè¢ÂG)FM±qÑÓîß+ßü{‡¼ïä<ùÜ»çÀ Z“l)®S¦xç+¥¶¯à¸; “Lÿ«t$ ƒ¦‡{°5¶«ŒmRï°2ZĂ u¨a¬‹yǦÔZaÉ¿rTø£¼SXÈYœÀ‘­ö }ØR\¯£ü99irá'Η¿nª’Ûï}Tb* ! q=F§íđÉ NƒT €EÂÏÓÓ"x‘°*Ä3!L Hsƒăzæâ¾jEŸEëơUỊ̂¢ø!師đÇ· ;IeÂI äœÓO‘ß­Û'ûË´¯¦đưă‚àö>I£óà‘m³bÉ™fEÅ÷„á=U¥jÁÇûѲ|Ÿ,X˜#k[eƒ̉é/UX׫ 8 ÊËÑwäeD¬F€Éé0-‰x\zb8&!)ô«{*nhns«₫Ư蟂Ÿ×đRîđˉ „4› ˜-ñâs̃{ „!¥@  )9`ĂIÎ.®yÆ”'~ç8j{*œú.A¡K₫ªÜ…̀Ù<ÜÛѹ4©ÇÚ·¿ü´¸D^X8ó¸3ea®m£#³OÊÈ– xÇC»l4†‘2ÚĐZ0yÓ$Kî ĐŒ4(—Ă¹áuùÖ3g`/¹×Ä ”ư{C₫¬TnĂ,îê/8áÏçΠi5§đưçÂ3uŸŒûÍđ°¥¤QN2R®X˜- çÉ/ïzB:Köâ¤AîÀ¸kX uÔ‰)üÓ¾̉B£/Æ#ß‹âÎÆ#¸º‘–öSÔŸvÀImæ,đ]ë”óQ r$i¹=gßÄÔYódbFœü|G¶ûµé7 î“Qß₫í» ä9áï÷£#°#-µq1%À_yü6‰×`¼kÑÁ ̣È®jÂáé˜4ßsŸï̃KyĐ¼ˆß°ZμBTnG$ÇÉéS3Cÿܸ»á¦/^óluÅa úL\N %À/üY›àù đÿµ₫ßF̀ÿ’îB2ĂI@Nê°ßP ø™à‘ˆPà{¹Ó$#&ó£ù”!ëÿ0Vºaíî”×¶ï“ïTWÈ̉ÙSå= räS§M†±²£¸J₫øôN鬯Vf̀ErÆT‹²(Øta™»»PRG~ŒÑ e«Ô@¬,yô>*(-ÄrîJä¢G):Hh Àà¬ÚfPøq]#) '1œ{~ñ€y¼pv¶L½öÙ¸§H~÷È+[] A”‚ö±­kÜA*^g4As6¯N8áÍ/PDFá¤^”¢Ñ²ư·-c‚×Ñ´àt•Á8L%™u|ớṇ̃„ÿx‹ä÷ÅÅvTmJÊú¨-ñÛÀs£vßmûŸE1–Ơïñ¡Ơ%Ûi‰:’”)K§Œ’m8Ô‡®‚ù\?Lù"û£})ăÈæ·̀…¥8¥3$tçw•ÜO´Fàââ>§đÍ₫„À‚Ÿó₫nq Ó½§zµ†AR  À’36¼8q~@fç™—?ar4CÁ­x̀k |Âüu,Üï-®±9ăÔ†y÷ḳɹ2clª¼k^®ü₫¹Byq½>¸̀µ„?/´¥‡ a…§2~¶æii4‚{:fë:ÄÎRAp«ÜÓ3í7tđ̃H1êRØœ‰=ÚôâÖ€Ơß*¸½ ,Û»¾ÓTœÀ{ó«`ûÆ]m²±¨Nön’9ăÓäÓgKwR¦Ü~ÿăSSª‹ éÀ¦]· 3Zè8ˆS<¹£Q}W¥Æ(sbïŸưW˜À›i ́±K„^5éw{#m(4«ÇÂC=çƯ₫¹ƠRsû8î7† Q—[S# ß;»́`Ǵ¯Ë¾á¨¢¡–H₫x¼›ÔŒL¹üŒ¹2§₫uC)̃Æ3×{~$ÄĂ₫_đè ¤₫Ñ *̣J†r±dBFè¿̃Ỵ›₫û”¢yŒ#z7â§`g tvŸÏ(đ©pmå¡ó":₫ ·A.  ÀpQ6€;äèho‹2yă¢j‡œF¹8™jÉÑÀh* ƒ‹R c ª[¸(̀Û±đ-ùÜúGî·nÓ.ỵ̃Û%~êJ9kÎXù̀ê©rí*n“[(×ß±UöîØªk(Ó¨„‘Đ÷ôóNáÏ‘.……&Y$[µNZ†1eÅTY£—"æG>3!q,ä„Bí§Âé ¡»Àö)ÄœÀ²ZBß`#x¨h‚4¬oëơu*(>²4ÎcΕû\#1u•:: é”CUÓ³˜P¹ ²Ae€¨)¼‚mÏ2*„e½=²Ïö́È|?¤hRÑÊR²Ơÿœ€Đ̉™óÏ‘|¯U5µRXpg`ÄÑ¿M3áC!Œ(¢xÇưûq`-+₫÷‡L̉Sw ÀrE,3ô8*# .ëaú7§BϾ?̣C!ï¿ |‡" iÂơ>뱕ÏÍH7ƒœÏl/æS₫ïLÄƠ[¨ó™_đS9à‡Ø»²z×Å™ÁÍĐPÀc¥C,€P`8)pê’¹´u…V¶ai³¹—é£5ăL=ô'Ø”³€QFæ[™&æØ2?´9_K7¬ÜÊF·ÂíÜ”€ô¸VW[%e/̃/øåÏåÔÏüLÖï;¬Îr~~ùlyü»WèvBu¥J³0„„»â1Bä¥ÇĂ"Ÿ£5lỹGpêUœW÷đCp=OX?k¿ww™Ư# ëQR¨u7^!æ9á¯}÷ ópzƯP àE%‰ÛÀ¢Í‚¥«€n49Ó@"®‡Ó¡çp]µ|œüă{ÿ"KÏû€¤e¤c.:AR’%)!AʉĂö4 .í;*ëSêP `‹T–¼¿^( ê–Đ ‚{]T ́Ù1-GSâ©ó́nôwƯÓ%ï¹a©V·Ê÷Ú‹c§¡Xâ¹¹{…F9}ŸúnÙjZÛ÷̉‰qá4ƒ₫AĂx(iẹ́₫UseÖ®V·¨¢¤ỡ•₫Naß[ø+jh':úçwE¯céÄ¡§×¬©ùơ÷¾¼ Ơ“qq¾ß]Î À˜yú¼Hd¶ÎØ]Háơ¤@`x=©´ub ·¶`ü lƒœĂX(¼ÑÈÆS] ¯€Ózàh`t¬G¾jV¶9ZĂ¼-¸&üÛéè–íµa;W[k˜ºÙ4Ăå»å3_ü†¤ÍX)á„d¹ë‹çÊ/®œ'óåÇO–ĂR ol-8¥Py/ê…¸XÀІ&ÄvÁ\U A\œ Đs̃1ESôµVÀúŒÇ^‚½6¡w±i£$))YÖÖiŸÔ÷{¤ 2P ` uĩ󅱂̣´1Û^ ‡3Ur)V ï¢Ẹ́íØ eÓÓàyÊ£,¦Cb°Ă£ß„ào–₫çÔ*‚úF ÏH̉Ö/¶q|áxêk»x^×µá̃£ÿP¸Sf®ºDŸ}éÎÍ̉\^œ±@ÊcdôO“]:Á ïïP]Ÿ"ÇÑ?×®`ä?;/SÎÁÁ@¯ƠKÜ9“Ö@G}Đ*Ơœ"@í3ñÚí©d`:!T‰ƒ¹îyn+Mụ́öA°BTØ»Q>Ÿ9¡¯đă(ÀØŸîưÜƯñR P†˜¨a¦€Ÿµ°)• =9‹đ€}ŒQ%ïơrl‡7›aÄ[ÇyôŒÍ”Ä̃˜:ÂA2p̃ÂĐCPÚáå”Mv`“Í̃1pZÔ´÷e˜ç\ơ”L:ùl¹ùỆó&ÂEêTytW½<óêÙZÈ…rỬ̉Ô #e¦CØă@Ă·Y8— €/ >ˆ@’x{bÈÀçÑ̃0Íà±u2{Ô¡yÖizvÁÑÀƯOLáO%€Á)NxÄRÀ@ÁINäa5a¹s9J‘›ÎŸ,·$^$‡¶½ [À—Bc P6üÚpÊ•:\̉‰A[ bç¡¢»è ~Tø£¯ ½Gÿ:̣V ”Ä„̣ûÍ“ ¸1-₫X>PÁÓo /’߃ÆüæSsñăÁ` Öåg®xpä\`†ÉHM–“çLc;ÀmÇaè‚‚fm½U~;üÀh]`Zo‘5#'»ảĂ_ºåOu¿ư¾₫©đE,cåÅạ̀t îùÜ¥»z,ÇÀØ¥5#øz  ÀĐÓ4€8LPæCçY†§¸,2©jX‚UÉŸ-RY£Œc°0p•#ùŸK¹´V€°á4€m´‘,e?M¹ \ÉƯ‰Ñª²O…zâ >3“0·Úđ¸\±é9Yvê yÏé‹$&%C¾ÅJy`{µÔ7·Ë…̣ôẲƠÜ «µáfu0g4D¯.\“kbS`¸uˆ²;¤Ÿ_*­ %ư[ÔX$&÷$̀W5q:6¤HôÙ@SNđ;k€£#-!¬ˆÀåœJy`K9 gJcdüY—Ëüc»<÷ôZ‰mª“VĐŒï‘J(Å”¤úJ\ơ}²ßæk%‡94Ç©˜ÙƯV₫ÓñOwg»\ü₫w+ßûÇNŒ₫‹U ̉¥£Oø›ơæø)¯h }‡ñ™ưmôŸ˜+ăÆfËi“̉åé½ƠR„ňÜâ9¬ å̀o₫÷S.2÷ÏL6¢ø®8µCá_PÛºíæ¯À#Îû{”AÊïù¿”—ön-LórÏü²ă `˜€ (×÷8ÀGS=Ûr‚HÇTZ9}fVo凤&U¯Œæ£0ËCEF :JÅÈ&=ư¯pôî‚z‚Ă‚°8ø@yùéÇeă«›g‘  IDAT$&y„¼0?Ẉ®”Ïœ l'çÈJ¸c}vëAùç¦1̉¼ N­muCpª+c=U€†TȨ‰™¼ów—i­Bøw*˜¢†Pö—b-ëß‘¹öl ¿¤¿SX‡–*ôȾPQqzSØ?~ÑÜ1̣ïÏ–ÿÄù'X+IÍđKÏ­‚P‚è=̃(¬tîđ¨°#üƒdƠw«i¶…¿á Faƒ¯ß†Oøëª₫Ñ×öô‰̣ù³'Ë]¯UJ+N‰$lÛÍÿf`ø©0ßAaîÊó;àô ±â7£g=¨Ù£¬/¡‡¿+VÍ‚²Ơ!Û˼2( £oz9áOY’-0Í«8/Íç.? }üʨ«:̀•üN5'X^~ÁOaÏË¿åÏŸvÊ€«ĂØÁARÓŒƒ0Ä€!&hn)@–ĐOp†€̃́Œ÷t;K̉[8đYo.Oc2Wă€Úª–Å%„ÿ55XH…çy¹ă¤zƒ­æ§ùŸJ× P8³ªN `^[Ï  th¨’¸æjyä©ư’°a¯l^—+³WÉ¢üLùÖ%‹ạ̈åSäWk÷Jqu»”í—d,à¢püD{fº§̀à‰ƒ´BĐnÖ æMưa§udÊ₫” @vj‚ö±¯à̃}=HSXV…ñ‡đ§yă`})°D´Âẓđö  =J¾vÁ,yß‚1̣³{ÖÉ̃]»L€p‹Ñí‚æAPbû%ƒ)́zƒ~!m%†ø—䵦”¾T¢lñ&ßS¬WqĂ%Ë%f÷;[+a÷‹:ü‘}ÿö¢́Ñ>'„ă}ŸÄƒ´å‚RœˆyWFåäÉ œö÷”-~‚ưS\óư;A¯ûúñÚ`3öÿ',i0ăL™̃Ư,¡gº .ê#eœg£y7Â÷ ·ơÏù "àʱëº IC“‰ =`èi@& +Å€Ï)W8V3dp=¦?Ăc₫¬HÏLˆ{5´qăL̀á|?™grJ’ ̣I 6ƯºFÏ”̉ ˜Ä&cæw®îçâ«Î0VºC wÔ—ËúW*$~û~y^ăî8]¾ü©+ä'W,‘Fxékh/_ÀVÂĂ…»0^ÏQ4…‰Mèt”.*ó­Y×ỎÊ]|Ù ‚«Ó·Àj ư¯SœBA:hđ¦¸.ƯV%à¾Í‡%¿8Y­¿¸₫Bùô_ó¥đ•'•v&`Û±³Ó‚˜ b¥S#xœá»̣[z+{'Ú;U,Øÿ©4D ˆuµ=ˆªèÇ`̀tY1{²ǘ™iÁ”%b¬Cêd 8̣›±WE|qÏï e<Ê MySî́rI,ï]¹§É×.œ)ÍØ©Âm«Ü₫Éï‡ ’>Ú'÷N|-÷P €>-ÏUÿX̣"+̣2¸µ0t̃I3·á‘Q»AÔx9Θ̃ {º¦µ€1óø̀Y(üƯåà Ká1Â0P P†¨Èá¡À˜ôxIÁœf['ùĂ௠dœ*à‘Ál?fºg²Jeܬï‡Ă{ (C†ËæyÉéí gb0×Ê9đ®Nq»F¡Ö …@ç4Ôiºyû&¹ñ__“3WÈÔ9KäW-w̃°L «æÉ7îƯ-M5R[Q,úTĐÄĉÎel€µ‹GzÔ1ÿqŒ}ùä‘2fwËQ)G­ ®ÏVsè~@ˆê‘¢"ĂM èü3QÙWÑ,¿{¡X>|̣8ùß.’k°L½øåÇ" u;$úA‰A€*—öƒ#a¾%¿À6YîDá£m̃ôÓưö¾YåÆO\$ss3äÇw=§xñ¨_Zkø®Ü÷áǧçwærŒ4è₫´’ ư8BÁUÿ:ú‡å(®—3’âä®Mez^¿û§ĐíúêÑ*;Jú¡"ë2ŒHŒĂúø0y.-¦0wUßaLANáï¿ú½c¿À:~̃ÿ¾Ô `¸(Àr x<(ÂŒƠ€cZ,§̀ÏŸÑ«²Ÿ†ă8œz€sVfOÉÏ€vu±.†ƒđî¢PVei‘œÔGG88ˆ¨}ë³R±e­œµëBIÂÈÿáo\$·_½`B:¯ü·Ç_ÖÑ%:GÁ4-SĐ=̣8Öª )Ôá¼0Okă(Ñ*V1ç eL%€Á)Œ©Øàxcm4.yPÅäv°ôÑSråÖ+çKø#óå̉ïưMbpD³úH€‰›Âk/Bt#Œăm)jÔˆÖ{Àg›|\Éôq†5½D….Ú'Îé}₫ÇÂäˆw5&-A₫gíA)¯·)".üs£~„Çwe¸ 3÷^9ï €îѲK—¿ ăñ“§ËMM“6L±”Ô¶©ÙøêxŸ¥̉? Å¥øMé»L¶C“züS!üWMÍ ïo ½kö¸Í-ÍÍÚ „H¤»Ñ¿ÙSÈ;Áߌ4/̃û…?ë8@©ƒ{G-'øR ôó i°€oÜ*ø₫ ss—ă<î¾w₫¸…‚ †ryܨ"àF ̉dAOÿ÷X0؉©„vÏÚ̃Öf‹1¼çu@ VmxPÊÖß/sßû¹æ×OIU]Vs§Êÿưëụ̀î3N• ÓN³Çn‡xúÖÇAt:}¡ Ø„…*̉qÈçQ…¾C±âN<}yLrd=Á)„ÎK….´-’…ɺ>öËß_-“fĐç¯ß¸\ÆÏ;Uá0ˆS!)II’HÇAXàÆ9oßó Ut"¯ƒÂË,A~¢b¥R–ø̣¢2…+–h)#Çȧ?z±œ9u„́Û³ï´ Ê§dlôµƒ¥®̉mC»ö#VàBJô÷Ÿ-̃¿zÎÿgï<́:ªó?o{Ñơ^,É–m¹ÉÛc›¸`Ó B$”@€’ĐBÉB ¡%“`là¸ÊƯ²-Y½K»+mï»ïÿưÎÜóöîÓJZɲ¬rGºoæÎræÜ»ós¦-°t?̉’Ëj3ư‹óêívaƯÿX®₫Vdă#mUz…÷ŸXSÛ¾u› Oè 0.ÀßówàÇ䟾\p!À€±„eÍÜÓÅ̀đtq6+÷Pq€Î%é¢HrïĂyá̀*Rz|#;ᨽ©SWØ»?–ÿá jn’Œ€¿zOÓBc<à4”&3>–TC̀±ĂÚ`Hm  "á —ÑÚûĂ=ÿó­pÙ-ÿʦ. oỹ)á’e§„w^zFø—Û&)ß`X¹jUX·£SÛ̀ö™ÖF½a¹Àe[5µ¡º¶Îfƒ÷k\̃:w¨iFV£‡ưˆ¡­Ö* ¼l°$nX89­(+¶w†ưá ̀ Ÿ~í…ás?­«}(lÛÙlüB '­Y´yÍ…`¥|íúb¶QoM|jÖUëUA*ô'Kü9}ñÜđ²¥á+¿ƯÔA;ÔiË₫D ôI ?íFe¿’¡Đß1Ú?Ÿ̃¯†Î^z¢ H̀üoѦ?5”pÆ À_<.|Àö₫Ó¶äÆ+*¡蜠2N˜V—»ơÁ'û_yÍeO´́Ø  ûc₫$ï´ö¸s9đ£ùv¡€g ₫ø”Cu™;LÈ€ĂÄ謃æŒ9YºåmÿP(\%{Ø{5«t̀M¯ÀV½æÅ‹'†{ĐđÓéĐ˜ä'z4Jy®7\J—×¾÷¦Ñ)a^àÅæ,%à!å-)ƠáC h,œN¾´sgêÚ>ÿ¥ß†/M—đ¢sĂ’“Ï gLï¾|AøÆïÖ†»Û¶µơ‡öƯ}Î$(7«j•N£Søx₫% †º¸²â„T,+c~-œ¢^Q‡D p¡Â'>éU€T•,́éđ÷l —4)üÍËÏ œBøäïÛÖ²J ´J`@{pX2!À¸̣h­P jÎÜÓöñºtZă ¨‹9.ÔO¨/¸æ²Đ#{bͦ0ĐÖQe¢ư«n³A ñÑ÷ỏ‚BÈ ±ư€²æ+OUmxù9³B›Núû•v]¬TÍ-€û~Únß̀£Oú†È;Uă₫ ¹Ü>ù[[¶o¡LÛg\—ˆê₫€½¾ ®ưû@('}éö€YÈ2à˜•%}F8Pè­çM¬ ơ¸S[Æ||ô¨«ÜgBzB% û=~±³8uLÈăŒ€×]03|Bf}ÀÀ:ù=ú¬bÀqa@%Yaøƒư°×:àËx-–¸ŒPVYLàaö-«Ă§¿²*Ôκ7̀™=3\qù¥á9'M /¿`aX¾¡]À®đŸwm­;·Ê\)mU+d>¯’&×&P¥j,8zo&ä+vX{R]ĩ<]уIgCªk€ènÑfI?x`[xtÚ„đ̉³¦‡¿₫êđ‘ïÖ†M+î µUL~ÓrBYI*mƠxƒ#đ̣µØ­gr§v¥[F‚=ùưû±¥v*“¿½ „2iÿ“, W,¨ ïÿÁĂá±ơ;¯¶îêB»N^¶ëßaÁµ·ƒÚô¯ä™;\È€ĂÅ鬧̀V`æR/o}™w‰O­èâRïcéE§:_\o?ă9®87½?‹)b*ÏÅ3]fú`˜ơdư¿4[´\Ơ7$3wö)m}û¶¯ë7„¯­]~ZWŸvvøđ›® ÓƠ‡3Ï ·7‡/Ư¶QyƠky"€¦¬*O·€“AơE! Rï}ƒ™ªEæ!|8ß¹û*øÂ¼&:®ÔR¶oß« ‚º₫₫5—„];O ùï¿ĐÉ‚;$°TÙĐGŸ`¶-„`Y„3Ă_ă²jĐCÚŸ´>Ư¾tØ'ïY¬6á y›Ù]ÀXYÿĂç…ơÚ·á±M-âs¯„6 ˆ́U`“3U |NçmL׳¯0éíK¡€„<ÿ_°́0öÏ)ƒƠê²…3í°Ÿmíư& XZàÚœx,fÀß±œo„CªĂî•prm9ÇUän₫Ự¦­;n8[ñƯüö_,¸æïàuÀ̉“—f¦/ƯÚ=~æFdÀÓÈܬèCËSêT¤uˆ‡¶èư–fư"]”œwæñń_O­Ö³y„îÑà\Ồ$1Ñ`™L ™€Ä–ûạ†d (‘`0$0bƯw©† J·Ëô_v́l ¯¹ï7aæ9¿Êe₫ê^NŸ?5<¼¹-ܼ¢Ic¹%̉ ­ÈhTÜa¾÷úĐ›„‰7§8,î-<“ܲ‡s“ÿáBÏ\¤â|‰BΖ¶^;TéÜyơạ́%sĂ—ÿ́÷Ă»¾qg(YwŸ %:»¹´_Ăf HjƒN5‚ï'r™FÓ¾äù¾<½³,èÇæTÈÚ?ăí²ª,¹4̀®+ oÿCëΤøB}zo…:UIÂSø9ªÓdyz×₫M‘`È„O„âÚÚ áêg- ,h 7jÓ´'I‘*kưص”Á0ÖÅ—™3*ĂÙórŸúÖŸÿû÷oHFÁ€÷xÀ @Úôïy)Ç/ˆÄ¹ï²ß§™đ´±6+øXäăºÀÔx½€cfdVâw±·Ug¤'dµ(™%%Bm“Üä34pܬ ̀Đ2B3Mç»ĂÎæ¾°ûÖŸH+,×Ü}c8ưy/ŸxÅYá|í€Ùx½ƒY_6·ơ ¨€×‹F’‘íÜsk”%àE˜8®´0 Û(Ø(]4¿3â‰]’¨bÀï-̉pom#X&Ș{N´Â'†^~«£…7îî oxÖ¬đù?¼4¼û낹ơ*VDÈ$’±0;32Ÿb¬![6 ?ơ¯ØÙ{üơ(‚.t`yAèbö¿ºN} 7¾÷’°½µ+¬|́ ¯đ>xOªđ/́]«é₫ÎáÛ;ç}B‹[ XñÁ;¶ÿ4û¿±¶*¬nî;$$Ù1̀ªÈ†’”sF}öyRÜĐ ÷ÜM©­̀ëă\Gwo~`@ËSFư“' í O›ÿ‹-€¿ûó™»pP¬Q₫̀=dÀS`^–ơøå}%Ú=ؾ\1ø“–6íHc€CÇ«–Ë@ñ\ơÙ3²*è 3AK~‰TnŸ+P*ëÀ ̀Ấ›Ÿ—º]¥ơư_wä­/D‘ŧữ\{ûü‹µ„„̣đÀ g’ûÊÜáà@&.gu´Œ¦ÿ(ˆ”kUG…¬3'Ö†ëÏÔNkd¨ø³NŸwßövÚ_,7yIùñ=ªfItlúÓÜ̃ÿóW^ñ€̉jæ©}†ÅÅGÁ¥kÿhön(Öú‰ç" ”AØËS0s‡›™p¸9Ơw0đ/×öø“ë”[}́áuÔûá¤^‡ªNöË¿Ù>xƠ ¡bấĐß¼₫)Óä€SoJLê9‚=¦ÀS.Âà çÍc"g)a|Đû™ơ'wƬ :¦"ǘ̃íaÓ¶°e[w¬ØªjëĂØâ©5ᢅ áÔ5̉p±† &T•Ú1²äg]ù.­À@ €m̉ hŶŸ€ÂÖ£9ù,±{Jrx[ă3´ûa€,8æàâ¯퇼Đ û‡4̃¡đëUÍ¡UÛ¿`é”ù5áG?ûUؼyK(Ơ~üV¶œÎÍ6$ ~P£ƒ‹8 }‘F+’M¸SÅe:Îù¬s–Y?ưÖ}Ú°LeÉô/‹K4ư‹fÍ;ă]PXR¬åϧ‡•Î+|èßh₫ºXƠqñYK­Èíø‡§ºR5S€±Ô^ÆUºöÏÚJRèå=BûIÓ«íÑǾ̣ư6À Jô˵~|€ƯÍ₫®ơ§}ÿwa?èbđ§́̀fdÀafxVƯAq`ø=ÿú“ÙÚÑôœZ™t9ôp:j«µ5Ö‚ö?V‚ƒ$̉;|+ÍÔd¤ÍtÔ8`ØBú›y˜˜Rkâeö00 %b*£G¼³|J0À̉Ez~¹îö¶ĐƠÂöùpëĂĂ¡±N‡½H³œ<¡2œ¿ À´Æ›—éÎbX½£Ûzï} …Vê^¸¤3¢å¡\7*EF‚ª›%‡8à7†h éáYÚB0Ë“èhñj| {¸̃¬}Kˆ™ùÊ«Ă¯ ?¼í!m#¼A^úJú @`7F€íÎÈ2ä¤̀Øêáà&Óü1««åù©§„ÿ₫i‡Đº›6¥ÂBS!nÍ%Èy%ăđ¡ÈÚA0’{µ“y6 !:Ê9íO﨡qrx₫)áî má m¥ñz¿2ø¢¬’I,l…ưđ Jª±÷°³lö„ün½~ß›S6LÿÅÅkă‚è®á§…~“¶ø½L=ÊÜ3ÁLx&¸ƠyÀÔÂjơWÚư=:z ¨×î§(:¹ư$9T ¯m$ôÔJ§̀4Ø}̉"@Êœ@ËÚhƯ³H‘<’5`¨ MWK Y—h¼¿>¹Ö' ¢4âÚ:Û•»$´́aåÆZMPmÀ?½¾2,ÔѲëëµ¹P™/™ZN™N_Ÿ ]*sÓîÛˆºZ{T;F:­Í[0!EDëm3đW§:Ü0+uBf’Çr+‰(ƠP@¹Ѿ‡·´‡Ơ2…Ÿ?¿!¼ẹ́¥aê´á‹?ü•N®Y-!… ‚,©”¦LvàÁI*/Z/ób]ÄhÜüí´?µc¸nVxñ… moưÏưÏ=¶ cP¦æ0D‚âeĐ6ʈïCe £½.¤!„˜ù_mË_ù2„×]qYVîè²úËÅ‹(Ăøw“bdR¿kÿĐ9ÂgÚ›×AB%:̀¨.´”æ̃ôæ?̃¤,ÅÚ?Íü]píßÁŸ1.ˆ'MZ  .„3÷ p ¦gUè1Ô÷í×YGLo§₫¥Đ)'¹èœ½¼½´g×¹·”±ă)Àkwxû«€ ăp€ˆ;L»O¢©3UC±Ø6Űn¬I×Ü€d âlË<•¢NßÀ/¡•ª°ÆçŒ€ºîé êÆÛÚKªÍĂ21kͽ€t‚Lß3'V…ºúÆĐXS&A 6\¥92Å÷ Œ»ûT¯Ê½c]+†v (̃¶±Iơđ^œM¼*{O&Đ`±Ơ6Áp÷UÈE#¬ Æè±^iø·¯̃ºTÿ N›¦L¸2|寯°iơÊPÚÓatN ØñÂĐº}ÀÛƒ?̀¬ÚË/{ö̉đWל¾}sènÛeíóqønó$TaÊ)ÑK̃·OzQcŒ°ü*~ff¿™₫¥ưK₫ Óf‡e³jµéÏ.³ÄđíÄé>};̣ †h¶˜Kd4Ue₫üÆüz½₫ÿưö¿íHe‰H¬Óàvïàèûå“ÿ.×₫Óå(ú€YD̀"dÀ!bdV̀ÓÍuTª‚½÷Óơ₫j˜Å}z¼¸î¥P—ũ̃‘sCy2µÜÚ¦¨ÈÄtiÀ“P$`5J³á“™ëh­IZ§ü8ù-–¬)‹Ëñ:{zơ¬$t÷äB“–À•W´i›á̉đ€mĐ\‚‰u¶í”Ú ÍÍŸ\-C‹ăDÚº–^ÓĐ–¥ GB,98b̉‰m̉½â£FnOŒ B¼‚$&̃O1Î4`LØŒï? ½vhÓƒesê—₫øđƒûO ßúɯCIë6Ó¦û$éĐÆ~6’ÀÆAM”Ÿ1ÇILºêç†ÅK–X·Üu¿ñ4̣6  'ŒúDx*~¬3D¼¦M"¶î_f₫̣ú©áư/8Ư}d[§öûW¥³wÇV́Q-ôø8ÉJj'­%BÚæÉïe¹ë/½d•EêGN¹¬ÀbÍßÁ ­ù#ø°€ƒ± $Vfáu‘¹ĂËL8¼üÎj;8äú{é]éˆÔkx·ïÂÔ÷ªƒ‹„u·Ï é§Ö+í¥ó<rRœEøÍ>«8¤]C4ĐTơjDù(‚_1Î|QÀcÓúƠù3q-j°¤q`åÙlrÂhîjp‰@̉|í=`æq%fR K´3b?æc•½›{rÏ9q̉ư/yó{f½é½;C8¬ †µv‰fĂ"€ú¦ÇvYÅ»ºú‚”v•/Z¸Z.f³s¼oH£DI ØÀÍ’6Í PÙÛZ{Ăvíw°«»!¼úü¹¡wøÊđ?7̃ÊÚ£%@Vƒ’>M”ÔñÂ%2O +|¢dÚÇÄ?&ƯÁ³œ='ü₫²™á ¿ÛvhơË₫vÀ‡¦H'áH”Ó=BÛ8C*€wKólûa1„Ùư•Œư‹iĂÔỤ́đ“G$đ^"ª“>º(D9ØçàO¹ĐȶÓÔƒÏưü‰Ơa₫¤êÜUW]ưäCwÿ–É8kMâó÷ûØ?àÖ₫] ®X@x ?×A³Fy3w9 ‡™YQỌ—<ë¼³´¹éK¥eI“̀ Ö½£Ûêâ ‰<Îï½—ă0~z­»nG9:Ü'¶tZ]=û”0Đ¢É`1W¡L28H{}£ y7„û,&¢QÈUV‡ÚI3Â#;zæ]Z̃G+ơAĂk׉°ä„Œ1üHĐøÀA$ưËÙœ<‡f:niĐ IDATTóå´¾T…•%… Êïííúîçÿi³.Æ“qñ™¯ŸzÖEWÔO®-Í_²°1\{Jc®¬\»ÍèáVd´rg'‡úä·́îƠÂÍaˆ¤ICOèKP @ăDó/¾5â~j‚ mcÄƯ†`|ûMÏ©Ưí^n¸uyغöñPÖƯ­s¤=k÷@†â¾±­6éNZ7+>ª¦…ù§_₫û¡æpÓm÷†¡₫̃(8‰P&Èw₫A 36ÚÍ₫¬©Èmă₫*§Ồ₫Đ’ Sç,|Á 6jS'&h‚ûÆà5ùÜ‹Áß)ˆœ¿ä£Jʘ¡Í¡l͇ÍÍm̉OB.€ß/@¾üƯüïÏ|Üßµ„ʹï²ßg„™đŒ°=«ôÀ9{FơL±O¿^̀9è‰(΋tŸx@‡ç=a:gOÇ“đøIbËe9c̃TÇn±I¹…dü‹… oG$")ĐëIˆgm½CŒ´1~­ß$Åifxí9S—~»Ñ 6í_me>4D¾%µs/†p—4!6d¿é´¼W.Æ₫ù₫J5¼â[₫r.Ä[/™«¡–²đĂ·›Pƒ•Ç™gs¨½ÔJ2gô›'!¸)*ós«r¯yíëÖ?vÿ]´a¬sAÀµw€­ß/|̉qhÿ¤qKç§™~)Xx]„3÷ p ¦gU8¼#•”à›úëø¼¬â^vqü̃î­³Oe*­NîbOK—ÀîGJ ÀG/TÜÑSSq\,I±"÷,ÛzdưĐ.Ĺî¸åñ«²éÆ“r„ơ ûă¿Ï3’jN)©:G ÀO)qlFU₫î§ßÛ¦kKRïĐKß̣̃E'ŸuÁ„íA°ln}˜s¢ªy‹VÖ*¨²j{·Í)Đ2ÄKB›:À=Ă„/ŸÂc…‘X,ŒcFoếß»oG¸néÔđ·WÏŸªx~xàw·„榦}Z2ÉöÁF¿Jb@ơ„Úđ¬ç\n]Ù~ôëtâ fÜ«L¬đÈÆ₫E‡}…º§‹u)± p¡Î…,,,ưc̣áSÏ“ëµâbPmPăüIϹöe“49=?wB.ÿ¼—¾fÊœ9³Ê—hRA®m ư}}ùξ¡ÏŒhp   p2=ñˆ‰}ưz'?¼9t 6†÷]>/Ü2ûºđ›»—‡ûVm »lŸ‰hPv!ưŒ9 Ă+N«½áÍwèà²ơ²V$淠ĪbƠáÄ[Ü>~ éRàoÚ94ëầ¨ưË×0Îï-4ß/üts’ïN(|qªÉÙ¸g¥|£đƒ̣ Û½x1£®2?³®<÷…ùήGï¾½I©ÀHsàÀ]›üÓ€ïa€ßÁá€ônú§¬ô¥Û̀ È€#á-d4́—ê=J „e—Y_™Û!¤!àp;º±"g].ªâùµ{ûUâxS”ƒÎW ‘êô÷Hđ#Lƒ4zœÑ¢Î^˜I¢÷‡¡º3¸b̀\}t1₫“̃rtbS”^RÑ `ăÔJ(ÛdÍÉd%Ës‘°_€‹‡=¢ ÎÓ‡ƠßÓ¬ `¢àü?¼©múœùUUå%ù¹«sÏz̃u“Ÿ{í5uóµY-û×5÷äĂàÀ@¾­g ×/ÓÿĂ«ë”Ö̀ˆE¥´i†*n[µ;´JX8aJM¸́uW…Ï₫beøÍw†ª¾›ÄȲ¿ÚY'…w¼ẩ°j[k¸ơ¡ơ(µ%”Q뇥"ÿI ÆjˆU¾Ÿ‹ƒ·0₫Ú¦?©Đø?cÿ§Ÿ05œsÂôđà–6£Û–ưiR¦8¯Lzw̉₫GiúÄ"ÔÅ×at̃¿½|¨¯,ÏÏ\›ûỤ̀'¾ơÍo4+‹c‚¿\ówÇ÷In đgiđ'¿_Î÷ơ(sÏ$üe?“4dugØrë6lZs΢é÷jü÷¼mw:M»Ôår}¡­GcÑô˜cº1ú™T̉¨¹Ñé¦"Ç,'FRZºD:i¦` 'æó}•æZ{¢[~§Ănđ'MOº^÷ĂlJ+ªCƠ¤iag{¯ÖÉ‹^ƠƒøDLI*”‘€†·Ñ̉Ái%`dô=¿°ÂçDÂƠ˜4 8 ¸_̀Z2BJñEú’‡ïºaÀI-ù̃oØ5gÁâê µ¡l¨gø}ÿ̉¢“Î8§jbcEXRÂâ™u¡¿w /Í?·Q 7hâœæ†mÚÉpùú¶°zgwxîI“ĂŸ^¹$LÓ8¿¼å·¡¿«Í4üê©óĂsj¸Fek⟪åE€Ÿ‹w<ôm ˆ14ƉSpŸÎ̉%ùHÈ· Mû/Y…P¡ zUƠƠáä³B»ä[×Üc– cNƯ÷]#ï+~½ñ2¿CÍÏ^ܘëkƯÙÿë.[¹{Ç”₫®øDǗïÀxMÿ®ư{Y**sG2àH{#=cq ·qó–’pî)eçmoï “kÊ1]ª·ê“6Td HÀËGÄéüèXéÙ̀·Îod¼ơ€X]ZNYKk§̃ü¹³Ă±6ëhco;V;*FQ÷x‘\1d}zJ$±ªnʸă¾ä^¦ä2 }đ†bS9LHqíŸh₫™¯0> ¯Ây… É$#À§Ä(,&Æå5“d80 đ‹ÆÅ½û¤árG^̃$¾‡Ó÷—ßµck—.¯đ–—_óhEutơ×^ù%×½₫m³₫àí6U{æ„sæVؼmlä‚đ‹'Ă#:‰ưü¯?o^xái/ ŸüùêĐ¬á„¼́İ»£'<üøjÛưM†|́߈M¨>đO7”°ñ5á§à$à¯T+Ê+*Ẳ†93üNÇ ·èÔFNûû㛀ر§—nß„%!m>L̉2B†Ô¾·º5'đÇL$-*¼̃`é ߯´öïqŦ̣Rïç~¼Ë~ŸQdÀ3Ê₫¬̣ñr€Ăiäb§ÀvmđM——°»‹¾&qI_;ÔˆEPŒ-Hb=Ư~MƯóQå°µ¾m¦#¿¼¢Ü:ï¨ù&$’N`KMcơzЇ‹¿Üă§Đà=Œ‘QåÙ?ÀZaßA.®×O´ve£=¶Ÿºe«[vñd‹«EOíÚ(ÎîydơàÇ8Û¦¶T`2irX ­‚¯=m6¦)Ë}æ´Ñ2/É/×,¹wAÀÙä,á5qqïa>îƯ÷gøvíniÂ$]ˆÿâ?|pÍW>₫áµÈuww}́ë7,=óâçƠO©–H9§:¼êœ™hïÔm¯dBMuø»—œ¾rÇæĐX]>đ£'Ơœö8@IMPFœïÆùKAđÓ.ÅkÓ₫%P1ö_©Ă~ÄË0{J}Ø©“WÉZÁ1ÀÖPÆ3 ĂîÈ;ºÎQæ¯Ç±öạ́'†̃áW]r*§ư¥ÁŸ¦ø{rÍ?=ñđw³?>ÏI›6ÿSN₫b‘ê2àH}3]£8  k´&Ü·~‰Ù™³KrUf @ØƠ‰vÄÙ˜´™¥ă j€0‡¹NSn̉çË÷<…€GȧsöÓKw É¼cUáÖÇ<*_©s¤üT±EAêÓ%¨qLWA:1Å«n4ÉR[ʦ„ÈQŒ£ÊkïăA©4_‰9£Oƒ=¸×Đy,C÷•ơ“ ms’¶ÿ­×–ÀW<ÙÊ¢·ç¹üÇ>ÿ¥yçưđë̀ôü÷\úMdĐMÜù/„YZóO›¾yÇz{e¢ÁIñ{|̃ ïÆß@ïÀïBqh₫ÅÚ?ùi¢¿S÷•¹#…™p¤¼‰Œ}qüÛ£ASE¡*L«­´¥YœgŸ ÅhÙØ´0æ–×±fZ®ơḷ̀ç‚~ØÀ‹+¢ƒ¥#}ü›{ïx a&q+\‰íZg9•p¤Äñ9̀0u4å{œ×˽¹B¥«n–Œé*/Sk¥=âWhóxfÀÓ†r­+ÏåK­í,Ù–DdB~Œ+Z7O‘Ơ:ùT¨¯© '…´¥/[ư^¾dR¨Ñä4Læ̀´—{DÛî₫be‹–äơIS·÷^yBîÜ’WFB;†@ 1¢¾ ħ…ªN_ôU€}úâ9ñK<÷ø~ïe.¾x6|Ó·₫u½®uÉó¡7üƠÇOYtÖEơïxᳪ´D.ß0cVn÷¶M&Håt»Kj{?đÓ­nü“¿?WH§ü®ưÛw£oưʵ<¯¾¶*üñE³Gư>°¡ƯLÿ”m'₫)ワ=ü­ØxêeIá³5̣Êso¸ôÔ{y”W¼̃“>@:̀ é\ûwđO¿O=ÎÜ‘ÆL8̉̃HFÏXÈ—–È&ªÎœ^ªØ5©s̀k›Y†8+€MZpk¿ăÙéeaX;Ö!G” ü4îM*’́%›\À“øßÊ¡#5đ§sVyhб³?ô ĐW§ è# ¾ùa„̉8Pv̉WĐ8w»I~’$£î¬·<ÉG₫$áèôJ¹#Ör?Z$€Ï rpP$ỌjZ"ëÙKK+,®VéëẹÔØ ëEY8ï„FkëóêB»øaSsGø¥ÆÍpS›ï;¬™óU Ñ̀|ñ[ËÔ™̃~ɼpưÛ₫j̃÷ÿß߯u€B±6 p(€€A:Ís0Oƒ¿‡Ó¾?éưrà÷2Ü'²ư9a¿ eßøØ_®”?´ù¿rÆ'̃÷æIWœ:3ÿă–æ\Ù`—øÄ»–%@gÈ$sZ“ú¾ô®R¯›̣öp₫<½Ó$ùøÆĺ_uT°üO/ë’óâ~ÿ yuËQ+k‹5€Ÿ½8×₫ á i4ôí«̀9•ù~}ük7tè1|$.xïïÉß• k₫®Áß…8̃¡_”‰s?̃e¿G 2àˆy!ûà@nùƯ¿ë¨|Í5›* ;Â&YN¹¶ñQ)MancU\ÿ­Â„}êPéLµÍ«€i8/ÍV́°:đaiÀtKˆ&đ#GçɃä–åÑ:N(x„6a±2K·‡¯̉-»ÏÙÚE+%)Heñ÷Å=¤Ơ©ŸˆLt̃–1úIy<Ă1ƯKéu eŸwa½ ƠƠUfùÈç4r«(rá¤i5¡²¦̃“Y0 “~M`•'ú=©cuûÔ†îÛîßÔ!!` ́ÔV½Ă}]!êTÙªGr À‰èױÔ»jÓ®°¶yJ₫ï>ô₫Y?ú÷Ï­èn8€ĐPºtù2q€ÇE¦\iÀ/§ï=}Ú.¹ÇO‡a—ÇyßÂ_₫À[ZtÂüsÿü•¿W·­­7ÜzïczçCú†tÔ²Î;8ª…&•úJåƯ§ă=S¸}`¼_»Dß—¾UÓüơ!WÈ̀_S71\ÖÔđđÖp¯V+°]¯åµJ³˜±~T¬êˆu"¯̀©¯ .h̀ưÍ¿|}÷G₫ôMf^$…q9xó.¸ü]ñ¾üƯ癿7̃+yă‡1Befîå8™Ë8pDs \ûÄ/ÿï/´6~é#O˜F¯^ u1öƯÑ7! } ÔL.ÑÑ´åö´J³§'LÔñ´yMpî ƒ=­¶%," H×1׺=Ë8 ₫­ëDé ­£–6-_ë§,₫ùgL +--[qvœ ĐÑ2GÁ‚™Đ UuêRN ÊÖ]4¾;î‰$ ¤ @`¦§ë7°PÜ€@Ùµ$ˆÔM%ƒ•QZ;1”U×ỸÙ³¦ë„7™ÿeJ>aöôđœ“¦È«´C€ơ8Ê€èBûGÈ8are^/ ÷ž£xnøÍåàÏ;pAÍ€±Æ₫ưñNÓ€¿?ØÀ•¹#”|ü™Ë8pDs`@3¸pêUè¤ḈQ¤‡é ú¡°VÇÍ.ÔLt&8½ú¼YÊY:^çĐk{×®îÅ—„_=¡±j-ñÚÔ¢ăh 8…J²vF7ÔÛ†¤áªë´ cèqé8éFå øuÉ–nçẲ'†pñ‰ás7g̣Vl€AÖíGngq9]́ûü”ƯæÊÈuÓ#=ÿJ­?Ïif=ø\-34`Q9ư¢ózµkÑÔjµ *s¡“=R‹T^]J+µø]÷ Đ&éåµmB¨%PS*>åµ™LgØ!m¾£­%liƠ)|2/·÷ ˆ̃—€½F7媆 ¨kƒ 7±%–$”Ê,ŒWâÇæm;UáüÜÛ_ư’Iÿù¹œĐѼµE/`.ç@¢ 9¨æ½s9Чư´'Lîex9é{¯Ă}.ÙºnƠÀ^û¦?øÖ×–^tê, ́ÎUI˜†´²m{ ë™ó!₫ø»¯à…;xe÷…瀿¾\¿M₫“oC6ª¹~ÊL}W á7kZC—†Z.Óe.9Öbø^y‹|‹¼3´ÿ9Ơ¹·½ûÏ·´¶µÁg}6@úư8ø# ùå›±ÀŸü”éå*hd§ï‰ËÜÂ₫H2—qà˜à`×-M!`‰LÛkeÂ^¥đôº0YkÏ[4ƯÚyúü©vÂcØfô\hÖơ=$AAá«Z6$°\³“±_ö\bơjF¹w¶HŒưÂÇêZZYJµŒlx@óT^ͬ%ù55aÎ́XúY¡ŸÊưØK–¨®́0WSYnËI[«ªRicu´hæy Đ”r¸q£Æ̃™sP¶íØZÛÚ̃̃m+mø£\æäªúpͥ煟5+üßCëĂă›Ûí k¯hGĂ´½üEÍ̀̉€Ï=¤Q¿ „cS"%¢‰UƠ™€ÄÛ²’₫đåÛ9B·âmüèI:è6%0VËw! -.®MRR¹Ûߟџy|±À½_éô„ưâ9u¹oñ7ƯđĂŸưúU“ßưÆëg´4·„Û^'M]g¨X`§̣ư™ œx÷ê ü•É̀ÿzÿ̀Ó`ÓŸ̉ “»¯9Mùrá!½'âÊRñºø¥tü½8=²ù¤N’rd°¬=ỵ“»ëî»»úlM á-’ Ÿ K ïŸwÂ…àaOçBåpáư›ưQàCÏ\Æ£ûèú¬œĐ†&ö„ÖL¯zrMX̃ÛzúúĂçÔư²&”ƠËd^Z©3Ơ'(},­F3̃gi₫À¥‹'é¼zÍ(”ûÀ5K̀÷I…Ü8è 4½‡›;cJøƠ×?ii}sVÂ<Ä1‡ÀÏGîtÀMsoøèÍë‚¶³“ QV¯]úd®q»7=¢ö¸ùWg×ï̃&ƒ¾­Smh[+Ï€Zy\«,¨TVTh( ,ü¸»3œ2÷:¾w‚&đí²²N˜ÍÁ ³vÔđ ü)‚Ayû->y†§‡‚ŪGɉl&›!=¾­+_~n.wåóÊ>1bbv!àp-P¡QÜ>L°Éj|ú.üb€øô•̉ñéüNû.éîlïù̃|ăÉW¿æú'̀Ÿ›¿o]K.èÁ¡aÍ÷@p‚ßX má™HVœI"f”S<ߦ9y6WC¼b &~üÉơ aVCe¸Yçđ=±Ï9¢é_E3éÂîͳ̃ ¦¦j´Rqd3ù¤ù‡ÅSkrï|ç;7=x×o8íǼÆDr-f.8Øû¼'̃—ÙPeñθÜ—¹#˜|ä™Ë8p̀p€^ñk4÷Ù•a…Lđƒƒ2që̉^đ¦­ïÜj@¹{Kª3V¾uưôW +Ô£VNk@:ub}©ơÓê˜ë4S₫ƠçÎ ̣OơÙÖăV«³₫Î}ÛlyÓ—Ơ>¶rµzZƒ’ ÊjĐ¿k‹LûÂ-ơÖ}Mëcom¥C‹nÑäÏ4JŒø@¿´rÄÑáS>°›–ËYîǃá°qÍʰzƠªpÁÂÂăë6….L₫ªËí`̉¢›´}»Û‘2)8VÖ« ¿5º‰bÖB€vlCƒx©•m»wä~½zJ˜9g~Í́“Ͼå‰×1(z.€$-Å ,ÓưxèÛ¸¿Oû¶Øw£lÅCË7ïÛÿµ₫]oxÅ‚µ;çïzà±ç `-̉„̉( ‰X=©‚Vîâû‘y^‰ăq¿XJÂÄé³Â{®=ÙvècËbLÿæ´hä §œ e¿6,Ô¦ ª˜T]Û̉•+6µPóƠĂø€¸ dđ₫ÅÚ¿[HÏåù½á(< VDA€YßY.8ăä°pÚ„pçă i—åüi³r˜IƠ'/.N˜ôhâ+â×Bª‡(_84ĐŸ«­kgΟR~Ë]Ë›wmÛ̀d@€Ä5L|€ÇÍË€‹Œ \~Ÿ¾̉FY~9`9°¹O¼?ózư>ừËÚ²úÑR’{Ó‹¯˜_^7±äÉ-"!Ï¿'˜e|Ox¢:̀™öŸÄÊ6î¯ï‡=t^ÍáX0wf¸â¬Åa‚N5¼k]»˜©ï;1áđK **¶ loÏđơ/ y6Ê?{ÑÄÜ-wƯßóñưÅÆ>•¾ƒ?|t¾8ès6{pf²&ÏOÎÊ¡¼tÙºÍÜ‘Î$Á̀e8*8`¡ aöMn¿f×ÙÖơëBo–đ (MP­»Jú«¤Wơ¢­3e£—$ßv´[ë̃KMim­;ĂÖÁđÂ3§†¤ñ{a>`WœPˆ€aàiƠ!¦$®4WCÖ ÿ-’´é„£î¬ ̉Ñé§J¶x€† ‰x(4­{4üêÁƠá­W)„Ö¾Rđ\eEÙÄR-y(ϵ| tmÔ Oư†gä rj/» é= W`OljÊ¿ởÅu—ˆ{ IDAT]rñ”'ï¿s•’Q[ụ́FâSĹu[p¼¿ÈOØËA¡ñ0>÷~qOç÷v߇¸ç2Í_¾àØÂZG*~đÍ/̃ñ–7¾ö´kÎ;uêưëä_ñ¨¬Ú]!Lß C9¼ÿT€iÿº·e²$U(₫\°xF˜;±B›(í°ïW#JÆW̃m|ëø£”bXaxÏäC˜ á¬9ơ¹¶¶ö¡¿ÿè?mïjÓQˆ‘?i;Ÿt\đqÁ íß-.$!(¸pF̃bđWTæđG‘¹ŒG´qRJ牜L1S7%™À¨UGíÙ´n4n]ƒ ́ÂJ 0 Ị̂A|Lú́ ߯Ùí}ºđûmnA>|_ă₫µ SBăÜÅ2û÷[¦ƠS•«¹z4 >B‚üd~sŸAÏ iưøfP9Ñ2 _å¦ăF¬jkb`Éa´lIJ¨ŸvMü̃M¿ -:ánÑ<­JÅ»–|{@¼Pfoàïiđ?„ømÖ% †Ưm9cÑ‚ùu¡¼J{€8 ÚN¯™ párMđñ‹"¹¸©bđrMÖµY©Ö«-¹˜GxwÑ¥Y’‡ïáÖĐƯ¶åo>ô×?îéîêzÍù³såmÅH…4y6ñA³Gđ2@ÖJ AŒ4,'µ”w̃ôúpùéótØO—¶SÖvÖªpwđkÍ¿’˜́fu©À?2ß¼, %ÍîYÛ4|çÍ?Âô¯qż…ŸÎKçá₫ÀŸwÁÇăï ç~¼Ë~hdÀưz2âFs ö-̃ăŒ~ïèúÔ¯êŒú4…k'é7êÆ¦Ñ ”¨8i p¹,Îî£p`s¤ÍbV.k©Mœc^zCS§–êƠ„̣mŒ£ƠêŒÍ ›i_¥f₫Ñf|6ü1ï¸Ñ¢üh’Å ˆ`»_i ! X>n$L¨í-ëÑư¾đ'Ï™†+OQ3M@ÇPd´æj‰ọ̈cÚbE0Ăo.ưØP‡*ƯÚÖîXÓỵ̈×,=ù´3§¨(×È]ăvM2 ’êxƯ€_c iAÀ„b@Ø\(póv±P€@€`àB‡ñ»îúùo»AZúüIUáÔ…smo[¿/“>V!ÆöÑđcçÊ8¢ưÇ]$÷gÓŸJíÛp¼9² ‡ÛD‚8À~ÿÑ¥Ù‘DɃÇ 0‘*ÖÁ7­ư)M” Ø?ü†—?•aÑp^ÂO.ç£óÎy…ï¿ó8øÊùÈïå ɽ¼̀-đ/́h¡7£ó8怀Æ;1¹`Ưd̉Wö¢îË•TT%c̀B€'}Wôc<¿DïyÅtŒóÚx9‚zWÓÀ“pÇÎÚd¥,¼àüEa¨B‡Î'åÓ=PÄê­é°‹ÁÜî•~L@7*•gL_yRÿŒ₫Ô½ü[¹Ô‹( ˦=̣̃Ơß…‰5eáܧ6ÀÑ?¦ø%Œ¤àqäÁüe¸z{{Ặ'·ægOo,¹ú…/;±²¦¶FÅJ˜ØỪ^,¤‰€ ¼T¿\ ơ°[đ]ä̉ç–߈(-Œ%¸Åè­×]üÁÛV·†·<{n~⌹ħ¥|s;sAè%€‰~vú±”pŒgîû>Øi¦ƠWªœa½&lo•öOú¤gßËȽêå,­̃Ú¿ư—§ÛĐ w;¥¶"Û†̃’­kWÑ=1ç|L SÅ@1ø;üÉëị̈¸2wr —v¼’Læ½Ø̃x nÖ:^ÿ°™Æäû±“¤´1×€s”Ék½dq—„¥1A@~«N$ü•´Û)uU*R5¡‘:csV¦€X7ià&ŒĂ7!a§Å©ă½å±2u¯Ööä7–Û­ª[‚€ )¨Ê=¨ûCá]Ï™g«# ÖHWÀÂÜS¦"Óó(wot‘hÏ”¬Nê ë:sk¶w„7¿óƯgO›1«Aå8đûx;¾ ø#/,V ³" aY¼¸w@Jƒá´@Èù倆@àBƒ¾ øcY :Û›·oùä§?ơŸZ^÷—×Êê¦h?“úî2écâC̣y'ú=³?B[4WépŸy',ÖVƒaù¦¸éñ_Ú¿ &Hˆ"çÚ?\P’(4đÆÄxtºJ'6₫ßêöÜ'O^®¬XUœwÎ/øăRZ8B0r^8̉¿óÚùs?̃e¿GøÖ2—qà¨àÀNvi§?:Úô‡;@úµË=‡Ùà¦4°Ùz@EZ:…£™Ô¢­ĂŒ¡ä^# 1t¨'Ư=`jûƯ# ( ­S› Ư¾bk8ñäSĂŒù‹É;}Uh²GA±UIº‰s ø•ºÄÅvŒÎGG| (‹V† ƠœÁ]ëĂ;¾ûˆv, óçϱvÆ™ă¬ÂÇMNz»âEÁJü‚"C# a ·'Ü₫øÖ°xRy¸î5|v9¶ïüJ[x™~nd¤Ê^‡‚øæƠ¥…€´… -ïV  ôđÂbÀ-=7~ñ£?₫÷ßm:¡*œ·pjó%§/J»/×?[æÇP€ÀđçøYöÇÆLœRỷ’¥á—Î ;:Âî®~N0ퟖÓ"­HéH{xo²¶ˆßçÎmȳvOw7“0¼ç“ó*̓â6»u„x–̉ÚZ€ỀÜQÈØc…„g$·±zœÑŸ²÷H•êl§ˆ ¸ëF²:WṣL0Đ½ [o׿B§O-—.™¬~›Î^>Z;ǿºâ¿=+UÇǨǯ †€p¼âĐ…æ)ˆ®Gnưihíg̀mp © qơc–Ê€lóÇgpk ÊçV“æA €ˆ–í ĐÔ֛ϟưÙ²̣r&º`³́u €öÏI>'ÀHÑ=á¯ØĂî[‚T´P§ÀÍ÷Óà瀘¶  ¼ùÙó^}ûê]ù×^²87k̃<Ó₫Ù̓} ÇF‹‘́i€ó¥&èUUU†³çM}Ÿq˪ö§oE…2öŸcgÁ¤‰úøönRïÈ„Úä=ñyN×ÂÉu¹Ư³fđEgμWŹƒ?´àOƒ?O[Ó¿[ˆ+Ö₫á[ׄ3w”r€?°̀e8̉90ª“±̃gTL$ŸÎ£³åÀÜÜ):ö–xÅÑYâ/̃́ă׫ üèb·LOj1¨·rur̃-k:¤9'†*Í §£Fó33®;0[âÔÏ̃âSIöLÓÁ×!_´‹F·dØ0€,˜ç[·†?ÿÎ=áϧU “- ¢奅€ư0FØg¨«‰í‡ ¿µ«7lÚƠ›;Q›+6LîĂ€¾ n H ôS₫ÚưâÚ­ZªN.Î=¯ ó«8ÎÁß…|×’(Í2PV^9đ/}î««KĂơ.̀×ÔƠÛØ>Vvøó­~Ù̉×̀₫HÑÎÅâđ́sNW<9l̉aL}œÀwÊ7£Ú¸́ƯéWa¿,Vy8Ñ̃•½3tFm^;ÿ…?z₫êÖy•n;íơ6ºvï€ :iᇶ“ ‘ßy+UDæNØgvt’Q}¼qÀ5¡t»…)c:ïù˜Áïc±tº\ăq{)V ©T©™¸ÍWo(´ë̉Ă–Ư]aÖ“t{ćÈ̉¤̉t½ă$aüÏW(¾&OØåVŸ àVú)'EÁrÖ|åpß3û½ žƒƒ¥Œ̉˜ú:oưÉwîúùCwŸ©5÷KçO e:Ô)îëwøcNẰ`»_÷©ªmà5+¬ÔQ̀·=¹+Ôh>€YªàÇœ¿è—4ÆktgÿOc¦êĐ«“«sŸÿö 휙´ßA÷ö́´ÅA߇;üŸ4iÓ¿—Cu8|̃KæRdÀQúâG²u°€€³hä'Fú/ 7ßɇesêDê¥ô¥GmI©¬ËÚ¿å)¬/\UsO™ø˜µ¹₫ĐѺ+<÷„Ú0kætmëZ‡dv ³. +y‹ÿ©0 u\ÀÚ§º̉> lzE¨™â™œÇ|™{Ûw…ßnêW,™¦L’Z®tq²+¡Î…£)©5 ²Æ&êÁ–æ¶p÷ÚÖüÛ^ơ¢ù3:G%§-ăœ(÷„8HK_×ăäđ¹̀4pº P°l]¿qçÿûû?Đ0~xÖ’9ùzÉ?ÆùÑöm³ ¾́¢_ñœSơÂĂÛÚµ¯D^Ú?¶œ~tM»K¾ñ-1PMÿ¼kÈæ]åØBØn₫ư³ßÖѶđ¦o—[<̉@¡ J—~âÉïmvíßùC¹^¾‚™;9 Gă[;Nĩ°yëƯe%Ă«*Ô ‚©æÜOƯ%Åߺ§“t,0hmôẠ̀åñ?í<ää/€©¸ÊE»µ±Ys?¾©Efÿ¦M®—g‚›V§¼±J+ɪ(hèN[ºâC6º^j´F0¶ d`ƒoÜđ‹0»¡"\zâDÛßÅ%l‘năÙAФê }̀  º˜ Æ’À0ØnZ±#7M3>đÙ¯^«¢é‡‡ °`!đ‹t‘• "ç¯Ù}ơ0¾  €!À˜̉:¿óùưê?~tóm'ÍlÈ-=i~¾ªJV¶øƠU¡ñ₫Ệrm÷[. $ÔMœ.^8)Ü»±-töèĐ)Ù́º2K•ªÓKơĂĐú¼‡y§ñB8€!¹°hjMh¬¯Í½ëo>Ù´êñG™«€+¦? ₫n₫O?á±̀ÿÅào…'å{8óBdÀQø̉S’KÖoÙÖ¬¶™ÎoL—f'@ÆV¡̣Æ)JNgIǹç'O/™¾b§::çî(XË,¬hZ¹µ5ܽzWXxÆ¡¢ªÆêb x¤Ăö¢ïñ£cíƯˆĐ"ZE°-Ơ“w ”@{Ù¯{dy¸ñÉî0{6*¯24t¢Ơ$"®ñD2 W.è0%Ă–MR·&¹555ó,ÿÚËΨđé¡îÓC₫Z̉¾’rÇÛå¹ïàï ê‚€¦¶Ùmụ̀¿|æ§[7mØô®Ëåfͪ+úåÜWª«Ju_f`₫úKj©^yxx‹–ôh߈¾MÆô ́íû¶¯Ơ¾Y‹ßKû‡¯’©L Đ1¿ù™ Ơa‚ªU+Ÿèíîê„6œkëøĐN<—cöĐŸôçB[?Èïe)Xà á̀Åس7<“‘~ls v‘êÍÑí!wÆqâw¢ X§:vÎÑêeRшpyÍŒ¯NØ:buâÔÔßÑZwí úÜùÚ ̉†è´ÙÎÁ̃h“y—{̣nG• [`’[‡öÖpû-¿Kf5†9“kE—ø BfØ­îØÁå§•y†tÏÖÀ‚ÄæD7<²3W[Q–;ù¢«ÎP†wÜ €ï€±¬zü´;#[µàăđH]p-ÚLæOÜù‹¿ư«V6÷ …gŸ:#_#ÀçªØWË"€5`û;½1üfÍ.ăs\-¢oT=±¾>Ï·ZøftB4ơç5œ k‚–.”Æÿe3ÂKΘ¦•ơ¹ßÜÿhßK—=ñóïm»è¤_wú]hq MszÜß…»éŸvr9ø{™*đ…pæRdÀQúâ2²Çæ@¸èP“®»°XF6| à ÜLü!•îá’¤Ÿ$'Ê €ălÈ¥Ú î&m«ÍÜBứC 3Á¥5›€×ˆó ,j<}2 Íèë mÛÖ…9u¥áÜ%sŬœˆ`ä$Ó₫Hf€AđHÿÅ#øÄ–ÄLĂá7+wiI\yé‡?₫™ËơØ­.øj·đÜ_C±¯GO»£ Ö ùªnpM:ÿ©·¿ä“;Ö®|àù§LÎrÊ)¦ơ×T• :aâäÉáơ—Ÿæé¸ßM»û ́Y`߈ÍÉ8›È€Z̀Ê€J};3ê+óg̀ÖyZfúîÓy¹¼L¯Ă}=ÊܱÀ¤Ç̀e8’9`¸\Y]]²á₫Û:₫öCxvUeåy»ºM›tP§ôNÖC ©dá¶̃r¦L®÷ÉäºyÛN™]9ÎWZ¯-Ô€)é̉(§Ø¥c̉ảÔ‹ 7̃³‹g¼¯m+ ×.›~ưd[صq¥íIèåûÆOêŒÂC¬u¬ú‹éñûƒÍg4C»qF¿"œ8¬L”̉&=ĂUơáÅ- Ë7´…>àIƠoü¯ÜiK@&pºÆ̣i¯µ Œº&äÛ¤L 3àË«jó—<­¬½½­ë¦ÿùñI9€À¦í@ëẳi`J¸™äzz½=>ƒ¤:k’Âî—uïnjß=\Ơ{₫…{̣ŒǘÉu¹};ơƯÎÓ1Âüüórs*s: |ó[ÿỤ̀£ÿ½¹ăË_ưzËÿơ Mÿù¯í¸ë¶_îîjßMÛ}.¯?Ưfxáüđ0|â‚₫€=Ë&¸8äÈĂÄ»e¾;Ͻ¼t}zœ¹c…iỊXiSÖc}=ôO‚Í2ßîöü¡‡¤×Â1ÎʶÀ Y×:-ÎÆ×À̃»RK¹÷z¾½%È™°5,­¶D7˜s¡iÛ–Đ××₫ñÏ /½ơ‡¶%p©4̃!,̀ ­ÆÁÓ Õôữ(oº½æ÷Ö …k¿yNé*µe²<²>¼éÚ₫pö‰³Â­÷¶ÊZ!‹_Ă7íMø‘BöVW:ô¶,¡•‡@4$ ”mßÙ’ÛÚ13œ0[âÉ÷ú̃¦¼ŒÿcÀ@Í₫ pr0,£¸Ăíø4øÔ\88ù6Ѳ¡µü»Ÿ₫ĐOÎ<ë́Sỵ̈µÏ¶îíSº`~}h–5=äcŸử–[ÿç¿ÛzJÖ­YÙ7Đßúzºđ½mJœÈa„b˜²¸pĐà´¤é¡.×úùrÍÀ÷°kÿ ÅàŸ®ÇëS²̀+È€cåM'íHZGDï8–ă¡¡ƒ`–ÇMÓ©Äæ4ƯzƠBf̃¯ÔÅ@,|SO,í^={Yn |óÎÍá½W¨=f…|ë6ÓxMăIèÂöÊCíF~ËÔ£½:Ê }ăF’hđBvê³Ó ™ÈÖÀ̉Æ;wn]­ámÍ·ß»ÂĐÅä%ÑñJx†:¿çÍWZ†JôƒÆvT½­]ƯáÖUÍáÊK.=áy/üưoüö¿5)i1ø¨*¢b.^0$9Âóô¸âz¸wĐuĐT̃₫«·~­¢ô_Ău×]÷́?Ộ‹›~¶æ[ñƯ´}K¾¹©©¤»³ú½möéêçmIû„ÓusÏå;´@ -~úrđG8pÓ¿çơ²¼è#.sÇ 2à|©ÇX“èˆè„Æå ¬È!踣3?“aÀú´˜p,@÷|i,B~Ónyº)¢LƯ':Ë—]ñâp÷^ÖvT½FÀ­ô$·₫ÛDkåx„̉À‘ñ̉Mư³GĂ—ß6+,X07¬Y·IÜb2 h•~Ëô…„dù*ă@̣À&&NÆƯ5 0¬Ü¸=щSr/¾îù‹o¿ù'«4)`Bû/è³Đ´]Sœn*ôô;íơAa§Å…h4K@ÓÖM-|Ëơ_ư»̣Êúëëú8£ºV§!̉>ÚăóÑ3–{Ú‰Ÿ;XS?epA‡ƒ?€›úñÓ‚€kÿ äá"¿×¥à´—¹c„#=ä1̉ ¬à½2÷Æ]…¯åxơ“Í́<ĂÇà^½§§×ơ|ʼnÁA.Y´ÁTKØỔf[WhưwÎÀ_ /cß{–„ `À^\xÑ}Ză7±AO>Içµb¡[h ±A´ñ¼”Çî¹=4·¶…Óæ4Xïµđ‹pô#/d9 tªJăg5 1 0(¦5uôæ̃°+ÿ—¾èÄeç딜höwó¿/DS\]àỊq„‡£8|aü4øºé½»§»»«­mw«¼v?́Àë€ “·Ƚ<|;Xđ^åq¡Ụ̀ŒïûƠsA€tNå@u;đÛk̉½û fîXä@&‹oơnSŸ€ gtªh•Röp Xn…‹{ ùë™~¸KkÔô“±§Œ` ˆöï̃;ûÂÿ»₫Ôk˜cÂç˜À äv0?Pb ‹:‡øÇ\Yl.aµ¤cgøóoß₫àœ¡v̉t+œz^Œô$æÀkU½*AÀ¬úaS ÎЄöö¶Ü4Aư©‹4i#”¹v́~ZpMö=ÓB€ƒ¦x¨] w­ÛMïØ8—ƒºûiÁ€0åøå ïeyÙøîü~±Ga¹ ¸n§ßÛ£¤ú<2wLs é×{L5Î:£‡·¶‡N½[¡µÓi?à+ôXB*Y·0q" ‡°xñc°kÉ-.†FÿF`Ç]¡üô#En>`ªM^tÜÇ~¾Æê¯ih4íŸ ‰>ó@5g&át™ăGwM|LÊö[ Ó$" k€„VH°H}Í=¿ÖDÅÁđ̣sfJ=dû„k üU:ïà€¬Ê¥Ô‰ÅÄæH×Â;ºÂÚ–ü›ÿæ3¿7wñâ©Jæ 5ÀÇÊÓôøq4ÇAÓÍđiĐv°Ç´°Àˆx€bߟ{~̣9ˆ»¶ŸzÀ~·®Öäẫ̉Q?eQ.uü₫é¶>¸S3wtp ÷t¼R¹GĦ)¦ưÓ=áâØ₫ÈgƯƯ7³™P­ímUĂë1á=Lâ*o_½̃XÏ2âÍ'Œv‹z«̣W¬Ú`»¾̣…W†ºcVI%,¤ ¢{´pŒFE¥­A¢(Í̃nG̣FºE°–¨ùs@ûôÛ¡=Íá—«ÛÂuK§„iS§’̀,.@¶‘î’À̃*#²œg#çm>ỖÜ–›£̣YóNQV×₫}ÀXB€“ÂKwnº§°ûö IDAT?Fí‡4fP>B€ ªƒ9 ëàíàï¾ ¾k÷øöi!À̉’ÇëA°@€6×üÓà¯è̀/à's*¤{Ư½†Í˜ơ€́̀ÚEÛ¬j2ü₫1å/Ă hpÓ?´q!¸đB;̉mÑmæedÀ±üvó¶"è ·Y]²ÍÀW¤/åV‹¹G~­çTE7V³èñf­àP ̣zpß,v₫;7 ±”‘›ñ€ZH8Ø6Ä|±¿·:…Æ `5±a€Á̃đĂ₫7ÔƠT„SçN²ñz“_D°m ÷â¶ #Œgˆ•‘W‘_Ld¾†¸ +6wäJ5ÙóCÿü…kU`0–À€´àŒ0Ôcß“̉ùÔüBpÀ-ÅB`ï@íïNØ},¿%ơîî“ï̉.­Q§ă4l³êbnBUÖÖưí¡¡º\–€RY´PÊ1»¸¡µ@uÄ4rGfˆùU3€.ÛÀ&ÆƯ{úÂ?übC8yFmXª¡̀ơ…ax¨+m8Píü¢lí ú»w‡Ÿ<¸ÍtÙơo=OÉö&ï P,Œ~ÉΦñæH¿:Â\i!ĐMOtđ°][w0wOk÷ç>i]hp ‚8đ3Ôàăưi³¿ÏOpàGPÁA3üJ·…ø̀ĂÈ€cøå‹MËcP7u ½Ô¶ö~8SÊ'4˜øvQĐ> "ưˆ0uî­̃d<)B0súoƯN˜?7,9ëlÜÎ'`Ib2Đ!ë ^–ƒx:ëXqéçéđHÚØR;"ó¿ H#×’ÀmüÀ­?Óùô¥á’'¶aHpßtn·¦ Ȥ—e¦ëÙ[NÁ#Ug+'l2 7rË×ím=ƒù¿ưè?]¦[×₫}€{·  s̉_ŸûJ̣´:ƒĂ§î;à ´¸ï?–øÓ Ï<ëø‹µ~úÜWĐh…Õâ2wp ƒ—|Œ41vN¬I€‡;4H® ©;óß”m勨¡<À I|ƯË£¢”€azÂ^¢O‹0̀Ú*uï®mAÇ»‡—5S;íÅ-Y  A€ ªöæÆø‘*ÆcΧ~5Sºt~ëÿE7ơÚj̣̀¶oX>ó‹'ĂÔI ¡¦6N´= T·Y3¨7©z¼+œNU¥j#¿̀ a&n÷´‡ïÜ·-÷œE ù—₫É__ªT¼>\@đ=‡ôÈ5.çuáó¥ú…€Ù=m¨‹-n₫O n!đ=½¾ƒ½ûnê§®´¹ư4đë6˜p¼ºL8^ßüQÚn@̃@#¡ßzZưü₫̃4À |VY¦ƒn*¤ÅrôúÜ5Oăy(/Á2Ó'Ư˜ÎÀ,̉èt¶÷…ÿX̃&Îê¦Íµ̣K$•ĺåó/©ÔÜŸYGQ¤çñḥGxđôä7'|#Kă€¾¾đÀ·…Zí¥°T“‡5́½¶Pyl*Ă AAåØ;ô°̣¡èñMÍúÍ•¼ç­o>-h À…öïó|B œL¸YđuØ\ÂLka]ŸèB ],¸Vï¾›ơ}L? üiĐO> Ïå–~F É/Í9Í~ŸùÇ 2à8yÑÇJ3KKstü¸½vZéÍ€Đª{4°Ls*+Ê#è%-Ä2 1{ÇäQÁă¹#L!RtđØµ À Äâ0À€ÆÔ7ïêSf„†I…}F„€tc•œ®et8 ôÅ‚Àè”cßäöîmc aÄ•:%P3ó×mÚî[×.>yV¨®ƒÅI¶¬Qí&<&SÆ®¶kơébưĂq‹à¡̃®°ª©;œ1oJåå¯|ë%Jȧ‡…ú3¿œ‘îëÑauÖ$ƠđºûP¦ùôª€âåÜs¹ @Ú´ißAß5ư´¶O}û₫ư}æ*"sÇ:2àXĂÇXû6mkúiy.¿MÍr%~Œ¢ă»Ëé̀ù¼­˜¤‰xZÉ#Oă:Ñô¸±zG̉ûsOƒ_p€§nâ…Y[=¿â† -ÛĂ¹3+ÂÙKæ…\YU²!C*Ú(.®¡P̣¸XÜQî¸{́̃ưå¢Ù–èIhÁ0¤#”™ÈØÓÙvmƯ._ÜæÏ*à×¾ *Îe)ˆæk~Ăx':EđʇM˜7ỠưøÁ¦|}]mÅå×½ôTªÓè#¸%ÀçøPÀ¡a¦*x OÀa\+O ¾2À…×́đy>–i? øö.hàS'u§/Ưî gî8ç@&çÀÑÖüÛvl¶u¦A{omp8’6[&¤â<œMÀ‹ä̃<ûñ̃2ÚH|qˆt¤1Ø JôÀ¶¶nX€íáÉ]ƒaÆÄZ­`5“£A3Âw,óàÆóq₫¥bº‹ïG  4 á%p6À¦æiL₫¶å+¬ ¦Ö?ᣠTâ­ùâƒÅÚ÷̃|˜ m´mÇÜư[»Ă•gΩnœµp¾ sàwíß}ö6`¿tâÆÉ¤LÂ| \.¤‡Đâ}Â~đ}_đ}_1à;è«û4©×]Ëüăœ™pœG[óK°›×éëæ·<é m9 ââäµâÅÅí«y¯_œÖéÇ X€æà¶£µ'üæ‰máÄ3Î u“¦ZF&"Ú’:Đ4Å¥¦Ÿí6#₫ÿtI^†ÙU _*¹Y46Ïù<_¿zexbƠʰxÆRa¨Å1_²€9³(²0ÆŸ®dŒ°[ à›]ªÛ¬<úu†Â­O4‡3—2åợ̃³•Œ°ø…¡€«đÊ“°¼=^q‡ËÑ,¾ n¢/yz@̃̃Ó¹Ÿ.ÇAßYè÷ÊnÎăư>ó38üÙî³@Æ# I‡“É:çưbŒñ_æL¬) çÍo0­Ü…ƒ•“MƯ_Y¨Újé ´2Gđ§ 4iÑ¥¸Á₫°»iGxá)áäÝ XbËmS ĐÓ‘Ôˆ†‚ñ9×¼èXơ1÷@–€qjăé2bÛ­&ø„@ºv…¯̃ü`X2µ:̀œ9[ ­hP#ûŒæ½¥2!DĐ'Ê € dûÎáÑm=á¥W\4gÆÂSç+? æï÷>PlH¿.%;¬.²3~"T́(~Zp°/öđñ]Û÷¼ø^¾—«(sŸ¹Œ{å@&́•5Ùƒ#¹®®®aÛà́†ª0ÅøÑx³ơ«̉¦ó®üEÍ”;ĂƠTC ́<̃ŕÀ™¤OïIZïmSƠüq)`œ1ÿ†¶°ªe Lœ{R(«¬ŒÀÉj2:Xk9 ÎAÜnÆñă öÇ‘mïIć(ÀÄ¥€  KPÙôøaû–-áÚ3¦‡R eØÉ†"9RæCŒ³?ç–•"ÑÅv ´ƠÿíHØÓ?Ö́lËŸw₫²é×¾èÅ‹T&`_<Đ­Å€1BØ₫ˆ:ôÏùDiœ‡´v§}üôṣrá<́÷g³ŸŒăá€ÿqŒ'm–&ăÀ3ÊÚ uåÿúΗ<4¡"·™µâ3*ÂÔÚrM /1-›ưéÇré¹̉2‡UqzSâăÇ*×ăHk½±Ê5 Kºf°§ÛƯƠ¶µv…Ϻ TUƠ„-M,Ơ¾€`V +–R¯çéö©3±(–à“̣l(@ö7@çîđø––péÂú0}æL#‰)—£'₫ÂÁ¤eªÓë§n;@RToß`ظµ)ÇÙÀ‹¦7âƠêríđw €Ï0–*B‚å:ô.ù2 û}ø=́Ï<±ß»ïñ™Ÿqà 9 ͺ,ăáæ@Wg_ØÙÙ_²E[ïîÓê$èªĐ2?—ÿh¥îèù™XFÚrnYeµMºwT0œ*‚*ñçV¡¶?]ŒÓB~,È&=Ư¡»«3œ§ïk&ÆI€Œÿƒ"Ä1S¡ưÔt˜È"e¾$°T)¿öóC[woxƯ³d¦OlsFh÷ñưưQ[°$ á<‹K  ¼ï{7w‡‹®zÑ̉ù'6]IÓ“ÓB‚@Ú @©N”ûÄ=“Ïâ@¯g’̃¬îc”#=å1ÚÀ¬YÇÖ·ô˜vºµ­7́èèu•%ancehÔ€it­ŕQϽi§ühlµ“́,~́Ï” ˆư¡Eº+­=×ϰ–̉ KCn 7<°¶)œ9½<4Lœbç°ÀWDâÆ*‰Ö—¶À@Ü,v>íÈ…Ưk ß½gsX6§Nig@‘ÏZ@˜A‹´:°åXkTeÈËÂC½qB`>tvơ…ûÖlÏŸqÚIơϽêÚE¡¼²Fåb Ë Æ/HI¨#˜¹ŒÇ7Æîod­?Â9€†<£^  Đ¦YÀ°µ­_æâ`qLö‹]<–ÔØ×£MöôëT@mTÅf@̉:C“.‚…ô­²Ô5g q–¿P‹×Süö̃N²£:?ƯÓ==qgvfgg³6iµ ‹2’!aˆ`Ï6&ŒÁlcÀæưÏÆØ₫;Û<Û`l‚ 0LQ9ç]I«Íifg'OÇéÿ÷ºçvuOÏl´P5{»êVă\Iâr ¥S¤FƯ~ÁVسds$®ơ À¦ $‹9ù̉7¾§ÇoY׫Úå~tÆçíq̉n<³éj¸br²(îJ́ퟷ₫Æ{/íY²¤YS `»èæcàoZÚÖTp88`€q"ØsÄ]é+dØ£§xPRo¤&`,_̉)V+üùĐpDÊEuœsç‘À<Ç^G¬z¯ wâa BÁcä0!J„æ\A†û₫ X>cî—á‘ù³×ŸOú£…t¤Çí©§$be‘–gƯ  ưK8¨T*b9zRw<^–åƯW¬‘Răb¥Y9–“jƠ ͱjüxÊ3äÁëˆm'äÁP._±iYêÊWÜpf*¶…€₫zÓ>ø[Ÿu–f ‚0[Z"Đ1ª°ơ{üdƒ”ycZŒ–¨(ŒJ²¼­I:› «ÔYĺÂÁb<Û”ª̃¼ˆPÙ‹ï—ÀË8XÑÈ–:p›IÔi)@ĐpMC ½h§Seùüí{Ơ¿eéZJ̃«Đ•`;Z4âI₫‰… +Äs€® 6‡%1"ßW¶éú‹‹6á–@Têåë <<Ñ: ËÄyF óçN¸;w '(è½á=¿wec‹:đ› à ¶Đ4VÚ'J˜ŸGp̀y`Î7á‚«@¢X,̣t´I:ĐÁ1CN »²Đe¶ nYÑ#€¹êÑ‹£̉¶®Q Âv7ÿ^ÙËNÖ}ù:|À,™Ô‰ö(¢¤đLg¤ÚB™Æ+«Nâñƒ£2œ-Êù/z¥@@“;ÈM(ÁQ¦>*ÇÜÓ•g₫¯Ö¶đél?¾/h=Àñ5ÁĐw|ïƠ[/^ ̃GüƒTˆ ¡„æîk˦fOmßÉ]·%̉µó¶ưĂ˜̣Éɺîv¶¥üæ¦6€ào€5û:ºÍønó vàÀ‚â@TsÏưʶ´´f>ñ+×~7L ñLÀ~Pîb‘9¬Ïêµ²›{[°8°Q'¸S )Ä(BÜìɧơƯM đ¸àO ºÁ¬ ܻà sÇ@é´Ïe‚*‰äV±ÈđÈà°s»w$Ó MËDY°]y&hđ}ê£yú…xn†ƠKctzQ«œµéèï¦Đñ8̣„.^T&׿S̃ơï÷J[s£´tv+ºÆ jb̉Ô >è3¬̣8Àƒ¢ƒ¦µŸ ̣÷ëBÊëßơû— Œ€ïƒ?ßùp-ŸZA :SD&p`¡r  µåçh½ÇÇyWÈ`¶ :ŸÀÁĂcÜà ‚d0„+xwăøƯÔƠº›¤5Ó KqfÀÆ¥-˜wç½)}( ¤¡%Hă=¥‚…æA-_=ïJñ–>₫;ƯC·B§ÓPø“#}²mÿ|èÅk¤a1NÔC4Û @¹¬“@Í]ĐÁ¡Ëûh`Ị̂-¾ÙfvY|Ú¤\¥bœẰûpK â<ú³oK?ô1/>s©p)d}́t@¾3/3üÀg}¦azd n´ƒË üÀîæÂ¶ỵШlï/đï?¯µcqíb@€ê[À¾Î‘ăl¼z„ñ-˜ÀÆ ,°ŸƒƠuCÈ áú₫èÁqƠ4ºtâ“™²¼³…²́:’“,¦zqVMC7ñ5¤mî`.Äk„iLJc#„¸qX Đ4PĐ'àv£\ Ê&@9s6Ëà»o~¢Dh±9̉f9ÿđ£ ¯½«øE‚†B¨æÉ[^|óÁÔü}›e³Œê”.†…ùñÍma~:+KyîdàÅJz vè-GÈß|ÿqyå¹+¤½}+¨àÍ|É2É×T€ßñÉ@;RŸ‘†BƯ±Vï­hɬüpkâÔ„¼ûÿơƠ(… Oà·Ç×0ŒZöu&ÀLà@à@Â70—8`ø.8ß¿Yçơ‰0 ˜Ơˆà’ÇÊơ]XÀƒ€h»~™¼áÊ3äW®>G÷,—ö%Ëuu;ăbZAo L76(H§)@3 SÔ@ p¦x£…H p«ø z*V |U§^A4Uë;v혗å}o| ¶Ó~,Üh˜¶›"Êùv"† ~¼iM _ƠP¨à|=„_ PÀ”ÀÁªvå3–I)ѨT¼)?ø ¶Đ ïø¤nT•Ó1 ü´èæô "¹‡|†̉°‘ XäYDdî (¿ëM¯Ú„öc₫f3’M0œsñ¼8°p9@É8˜À9Çm;öưƯ›º?̉ „Îa_ºVWƒ==M µ8/­åsà…— 5§®î•eçÁµ̣•»Ễ è“tyBG¡@áơTus₫ÛáÜ5èFä0á:êػѷ„µlûa,>ü%§0—ưÅ»ÈëÎé‘dk—$²CN U ZoUhªÚ±›]ÎwW¡ß8J¤q&ĂtZ'Ä´Ñ;,WÏh-×@x9øøC̣³Ư×ÊY«:å‡d¤ˆẹ́»‘Ÿ—f«ôè,ƒTHp¸(Ó½»µ(Ûó\²¤K®9³[6,]$X?é€DokªÔ»á̀ Ÿxè1䯵₫z[@éêP Üh†8°`9€Ûôsºâ ơ±ĂŸ´‘¡‡qS*F#NsÙă}£̣…›î—RºEZu`M@«¼ầUrÑ©Ë%•́R.Ê_|æ˜'dÿ­ x(D1“ë ’? ' €Mơ¾óWO¸‘F“äD#áˆ2ÄÀH7)7=̉/ן·LθäyøûŸ×ѲM/¸ú0¦3¾‹€ny êÓ‹ç‡ÏŸñ\n•ư´t«ạ̊p IhX÷Éw~øcyçk^`NÉá,À¼*'y ¨EVÔ|¨!ºĂÈ;Đ'LûáÊg½x`sëyñYKäåg-…¦B\ƒ·îü«;k}̉@tàæW•@Ăq^)b´-q`FF1êêß+;vÈƯpÿç÷̉²tíi‚£äM¯¾b³¾¸‹Ẹ̈/>¹`Lúö́P6)ا#{jàWʃP¢ưh€txió5!†A*´MM ₫œRhÀöÄRû́!h0í$@ÖI.÷K‚ËĂ÷­uSP8!S/éw¥B3±ơuuF½Ky¹ëîûä‘ç_"Ï;cµ|ëVhP HQ+Ă+U0€_ë|øêÖ ¹đB>Đ0ÏDó"hi–ÊÛ.])Ư¶™Ă˜Âù§Ÿí‘ƒYIæG$­]µB¿¡3ñÊ‹6w₫ùWœ¹íÎß,x<đ¨Êăá÷‡B[ÅZÆlx8°°8€…Ỡs¹¶́¨%̉éLæĂ7\₫ï|MñÓKÛ̉éC£́ăa¦ơøV. t+Ùsù‚ä'²2xïíđ¹ë¶¢,Y½³Ç­̣7¯?C2©ÿË[¶(`oí;[>Û~Ù}xTFí”<¦xRîS‡ … ¨i˜œ '‰7,ÏQ@đKB›ÀyqÎóçö¨0đǯÙ"/ÿÙ i>àÖô’xî>rB a•9­œr Ê¨Ç- T’Æ%Qhác£ụ‘•£>bøđ!yä¾»äêËŸ'w>ºG†G¤u,C8âeLÆ¥…| M/tÑ_:#«WöÊ[pÁĐÚ®&ư3î?̃¼[n}l¼-HÓ$éÉ`¡f́½GxPD¥̉́* O7§L &€B‹µiÖ-c6œÁ,,`aµ÷|¨m¹PÈ)¤̃³7ë­îÀ|>¯ÆYûDØ:†‘)„¾% ƠyhP"܈¶ÇéA9,y¦TC̣ܼ6̣¸b‘O₫`‡¼åüniji–ü8R  -˜EŒ éæ„ËC3:†µßíûUb˜oÅfi^Q€Ó8!‚êà"¾„¨₫²©;-›×­”;̃cts-€£Ÿüpê™ x¸´wçñå³zä̉µ2₫¸&ă?îÜ#7̃»7´OÛµb’ĐèºLçSƒá¼ ²^ÜƯƠôÁ|ô¢7_û½GñNiЦhûÓ”ÈTö€Íêó9>Æ"A0ó…A˜/-¹ëA0'¤Ô¯O·vắÄ-lE€ Á?W,È$Ái (¦éè*ùâĐ^œ<·G¾°µ,_¹©SÚ–,Ơ#…_{^¯ÜpA/@Iä”Îu2”?O>sË~™ê“'ö”Ñ¢d¡](å&t¾_ó&ˆáq'r‹¡È}í•«ÖÊ•W^!ßûÊç°û[lD¦~©Bש„úøµfÜú†#v†D¶{᛫k”púôQ®Q:Í)ÊO·G¢̣Vî–¸cûa¹yû€¼söÛwî‘щ¼₫)ÿ”pØ.«{K[k«œµ¢M^²¹ ç5e/Îkø̃Cûäë÷’Ưú±Í/§»Xơ Ô²p²'©Â H!ÂBN5? .è¼ü9;/yéơg̃|ẵ¶ĐN02>œPé6 3ơYªá'p`¾s ó½…çGưØ9³“®28ß?ƒÑhjơNC̣´ IDATGơ4u#Z*äÀŸqƯ5³˜Àh½ˆ{M2q”A²È'.øéÂ<€]qbH†öàßÇzPº–¯Ñm¿t ́–ErŦN9gù Ù7R”{wËÁ¡1î?$?ÚvX‰ÏĂÎco;PˆÛƯ8÷=1 Ç&–Ëÿ»; ê& IÀ?Âơ&<Œ¤y3tÿ*ï‘«bâaøZié©~úNo e 5µïæïl‡“:‚G2ÆuÜïÏ|u„«³}»åöû–÷¾ê2imm–ñRRVâfÜO]Ơ£÷3\}Z—L@غ{ϰ|û¾]àÍ€<¶oH&'F±¾Û0Aï$4:…H â´!n¹œÄ“ à;7:„Å€YYÓÙT^µ¢·ùµ¯zÅZ÷€n~Ú>¦ °Ưdµä6Ÿ`‚°à|^T˜vr×ÁĂ_¸t}çœïP À‰Á]5´Uוa( h—ÀˆàÏĂm¸¿Ư@"stKu·Sý"aa)̀Côs?!öƠ=PáwH{kF6/o“U½K¤cq¶ÅuÉ…Ï[-îÖ²FFGäÖmåÉĂ9?Ơ6à‡ úƠ{È5›zdÅÆ3d`ǃ Ú:r\¼Èµ1BQ:P ÁùØÔ€n¥)iOBˆ p»ÅvŒMn8Ă³꛲¤Ú{U×¢É(”LJăâå̉NëÇÉ4Τ…ç'Ü  OâÜ…Wœ ¦YDÖàF¶O'vüè‰!ùÜÍØa±P¶á4¿‰Ña‚X»¤¢Ú†´sMÛ††ëXyTA×Uê^Ä÷a@‚Ùe]-hˆÅ’'ÈøÓ&øûZ¿?³dVfĂLàÀÂà@F;ϧZ²³æÓ°ÿà¡[D6¼‘àwá~M+2ÄÎ÷Ÿµ¬Eăºà]đĐŒhS ÀHj¨xæb>‚§óуzđâ„؈ék¼SH€º~|PL”åç}@–ÔÉd28#?-ë{ZeņÓdƯ⌼ô9«äÊÓWJ?V´SøÆ}Pyó¢Ñ¼d¥­*qP•‚º›sÿݱçV¸2·Û‘ ̉pLµ-`×"?Xˆ®à™ZÔ# F×hOA=¿jạ̊ªúDỞƒw~ûÅë1=R_èèèEÆ-Œ)K¦­‹øpxy€?µ©MX‹Ç#—×a!ß»†ơ$Æ{v ÈĐÀ€́à9 #Ø:è´*ä /^ûKÅö ôQ*­ˆd®ú8$‚wY0Ư¤̃DíÀ‚Àó/¹bƯK¯{í¦¿ø™APjgøÉ,.´Å€6 ÀJ“|j* Ÿ`æ9‚0ÏxUtŒ]ŸúĐo|ù}×Ươ×¼p`¬ “»Z_¢ÇwQ·N ăhM̉ÍE|4¶0 XÂ7}ezÁOGÑHÄíxævBF¡đO¨ ºøÉáđ¡ơáâßư;ú°h°A¾ñÓNYÜ» ›–¼t½üÎn^ mM)¹áê‹å›=+•Ñlq6ê"9›’ÍM]D8² –ÇåB |ß 3¡+Oü¸Im†tOc>öƯƯ¨c9CVq₫ÿ‰Oè: ]ÓƠ=·ë5gRR9(oñ9}M/@9'w>ô8÷aE.SÑ0ØHA«€ơ´y±ëD7üS;.ïdX.X­ÂÆèS;Àơ ĂIå ×,J±zió•?ŸOí4?V“8° 9PƯS,H„JÏ1Äö¾­w“vóI4çpÔ„€h`Ë̃Ç9uÛaLF`¡PÀ¼ü¸ô§at—„kÙ1÷ÍrSđE9%R (•œŸ㧔ЃƱƯpïC8â6)o~è^iíY%+z»äüS:qѹö9Ë¡%X®eỞ ÑÏß₫|ŸlÅa8?ü¸K€ ïë## Ă«œ“¹É|4Gÿå-•Ëöï`-ü"b7ỢÎ8¾ÄSḍ`ƯÓ¸;¡)Ó(Í͘ïGä‰K×k’ëÏîÑKF÷íUêHùü ÔjÀí„€HøB,W&·rY?¾cåÑ©SÜ& ÷hPxd0ÖS$†p̃ßéç]´ª£{i÷ĐáCÜög£³¹o àĂi~¦`vä–;˜ÀyÏ ̀û&wô;ẹ́½ûFdKoÖƠlŒñŒJ•]ÁèÉŒ\Ÿ_÷¢>8‘Ge]ăTRLÂ2ч£X‚1Ăơ™d̃?ªºu=T×)%&Ó÷ïÄy»eÏăPÿ7]&“ù ùó/ưPJc˜?/ËÈíîÖ=Äu‚ ’O±Q̉a-ç6,st¹J’fëªê~®QZß×ÜSÂ,.è €eû  +00®æ”ˆm{¤đđ¡¯“_ÿôn *ÁẨ–¨îG˜»XÈÀŸ4³DÖƠ•La€d&pv«LƠ²McÀw±Ü¤́î+ÿâk~qưçÿísÿà[_뇷¿€ê{́` ~|˜ ‹̣m¼80¿9€ùƯ¾ó±v®Çw5ăô¸vᘯôâtØÑæ>}¤nĈăÖ%¨Mơ·₫9đ‹r–#N+Nùg^Ơ};®­3ª¤9j̃Hî²×º̣¢Æá,A2Ï‹{pú¢pIÁŸ~ïqùƯkN•ÜxË#h#9̉3 È5Öa8y¼‘“†å"ă¨Kăj焦ËâjeÜê ØH®˜èDö7¾å¬;o₫éΡ#‡9ïoÓ6À>ÏŸ`öö‚` ‚°`zÎW”³a+£pqd<Ïq9ƒ«üƱ¯:£»>]q™ ¥^Ñö>æ‚,5S₫T¢kˆ†ÂO‰Á& Àí ”@£¸l¤Ù9€eRcÄ øç̉Úÿ<$Já,‚œihÄ̃h€yƯX‚&sæ¶@„hm"‚\Í¢̉ÏưCÁˆŒY£•î§bü²™ùáA_QÉT¶.¶tJsK‹|æöưz2à¶ VÉ«Îé•>|PF¬oL|”|̣×ư‹ăQ°¨ Vơ„§j L`JaSo3Î ’A¬xƠơ¯\û'ù@;.ôçÿ©à;íÚ“áZ=‚ ˜Ï0Y{>×1Ôm₫q€XÄ'1‘Ëñà—÷Og,Ä-ưs½¼­̃Çù4èơƯßtéÍ_AJÁi€FN @î 9PÔơ`UWĂæ–5nçÓḈpób‚<í Ü·ûđ¸4´bÅ=.)*à`"RÄc Đäy\qâG¶s»÷"ü((0>HĂ+†ơA¢vÈCfx4oæWÿaù,‡y²,æU⃺”°°!†ïLOá£Ûú#‡åăÿ₫cÙ5T’ŸÙ#Yh=ØóÊ¿èÅü¨:˜É÷üƒ­ #¾̃ºGC!_ çMèƠV¬Yß…¬ôơ4¿Làkf*=„̀;`̃5邪P̣à₫ƒ_eN$°ê×€ ‡@̀yé––&¨ªà ₫Ơ3ßđƯú›»f m*˜0Û(— h ̃ôܾëåIw6 çÈ \í@½A×î*ø* GîŒ-. eg²: 6Ó}<×;đv¿zOફ lÎçk\º‘VË­:2ÇùƯ¿M¾øÓ‡åuĐ\´i9ê@í î:@Ï£»'À6̣b˜îe¤s&£í (daj‡ü㉂̉Œ8¿ó‡̣üØ@›à»/¸†se*%Î~æ?‚0ÿÛx¾ƠĐlObç#w}lÇ!4€(WW—v1öđø¡7ª Çíê¢<„(øX·o ˜~̣´ĐOơ¯ăâ2_÷ÄḄ  ï°ă­o1¤àË´Nk-AqƯ(Û´¤ ÔxÊksƠCv N¥ü¨l2½̣ExíC¶¸ÇO‹2´> «øëÁEˆLá€w-PØyü¡ûäîưy¹üŒe’æÍ‡œHÀ ®”Çà…–EfĐ˜M§₫©/— ‚N+ a4WÔí’˜̉ÛÇó…̣+/Û̉Q*8º÷5µB€?úg_¨Ÿ+AƯ‘3Xó“A˜Ÿíºj¥8qÇ·¿´‡•ÅÑ ×ñ;¿Ï"0Œ¸cß}£@¿ÚxŒ?5n$Dàå`ÍA³Ñ«u}`C& ̣\H{v¼#<~@̃¦¶xÏO3Û¥a½ü§¸]8A—%“A.>QnøS#€_ưë¦#å;·̃+—nè–KÏ̃ˆ…©Hpm€¦‹Đ–—/(æí¦YÈ}ăœÅâPo>“̉‡ƒ”₫íM zÖÀî#Ym±K¯yÍ&$´yüí¡ÓøĂ+˜À…Ă ,œ¶—5-44%¶öë^p.ˆtZW¢Àt8Äơ\Ưc\04µ€î|+¿–GÅǹ,}­?ߣ¬5øUíá¿"³b-~ˆ:̣‡m@M4÷t6+4]˜ù3>V!³I¥—¯Js¸ßˆ–”êÄAGMZG®Èa"sî½ÿaùÉÎ1¹lc—t·eđ€<&đ»öp̣˜ ?¤aøÊª® …(ï̀ö$/)ĹÂ!L˜^ùă¿úû«ˆ£|¿i|!ÀÖđ3±‡Ÿ Ÿ`æ=¦ëç}ÅCç4bgÆXMâ ̀ä°b|Íâ&\'gœöitÄU¡’ÏdüÑ?ÃbsCI·ø¡ 0SïØ=¢·¦tw‡È¡‘œŒå‹‰5‹R%Ig:‘Ä@¿v*À¦¦ÓX•Œ‚`̀`̃4å‚«ˆb@#V•ặ›Eè÷¥‘?Ö]sn½Æø¹5í”ÎfiÄ>u;¬£x¾Û@›~GÁÀR*¯~Ú8£ḮJôº.æáAùê›Úw?̀ÜÊ( 6<ưwc„’ȧŒ0?åi¶úùb„X9HDơ¼nE„:*yœ…(}{”oßư¤\wf·¬Z¶åáaÜ>Zß(;%Kó¶̀ñBƯ œrán€JªFqà‡%̣Xÿ„œ¹²=ù›ưä¥đe_gS¶€àïk‡…Y¿è ß`ǽCŸgƠ Ơ™çˆ1iàĐœ¹ơͤy³Ú,êØÈÁ̀%ØÇ>—h´ ÉÆä:{v₫G3€‚ëˆZQtÚuæh™C¸¸Ă(áÎYơK@Á”¸ÓW¥îK-xÛ{ƯȧÅsezÇ謤s<́Ỷ!í­2qđqƯ²Ÿi€‹t-¶r»àmßÿ––đ›/8EJÍƯÚ*Ôp*€ 3¹;@i«+¨ø¤S Ôêđ¡(Å“9í ,¦g;X^ܵ¤ơƒÿÓ‹Q ƒ(Øcë(ÔÓØ‚à`æ‚0ÿÚt¾×HûwT̉lI§Ó¼Œ/6å—ă‡Çqi>› D0T56Ê1›~ «5ô²̣}C²¼»Cw´)h2̀¨cZæ3ëŒÑ[GëUµî0#§ªç}x8µưđ̃Çä#ß|\~û%ëeùª•ºÅ—%تđ´vO€ÏK䬼"ƒNÈ6,úkϸ{LÄĂÄ¡<}&Ó©´>·̣á;µ₫B@jû׸©è&p`̃p ̉[Λ*…, (´₫à;ß:01:ø\̣T:́áéˆ9WlüĐ®: ÇŸÚ(^/Ăf‡ I›ÑU#a‰!½E}ºlªÏƠ$t^ưØ̀Ơï¸hÀƯHHBÀ·üTp(Óû¯=]͘ówW5ăg] àøàÚÈ/AóÅm] ˆ¼È&’­O™áX X^¿qư¢·¿ç½gáƠ¿V P+đËa–ö= ­€̉ƒ x9`÷3XDÈ:pàáûṿØÈp)%“C5r¬¯öcCAÆDN¥É4âjÚm tœhpüC0aøÓm˜¥UẠ̀vÿ v®@₫âÍ‚g´mñ]­=c"ÖÆ·w̉`tTå3ÄÂ#Za1¾›¯f[¬çxÏô:ahF́”|ư9­§E‹»°’Àï/d9¤ÀlG é¤q—á–G4+ÿi¶vG<\”/Ê‹.»hÅ–‹¯X‡d{[@AÀ„NÔîpD@0óA˜o-ºëóàÏ¿;̉–ø çÓ¶®Qé»éâÇÎă€ySƯ¢ö]p¦kO£djøaqï3ÿz<åXOgÏDíŒiHD´~ơxDÎüO]Ö*K[R†€ƒ?zÂè …ä=µx ‘&€çÜ{ûͲơpA®9g´´¶2'r}†#%*4‘, ư³Œ±\Aö e¥£9%)L#°TêL91-”Ï̃¼aÑ•—=¯A3­`?fvm•LàÀÜç@æ~.ä¸~Ø7ZJeq-,ƒ©³¢_{p|í\üϸ¤Î3Sr€9ĐƠÏÀ)áÉxj3¥„ÁÏ¡`u©~4»Èù~ iT@ ÑS]8³@[†‡,]¼®C‡Óù‘~§›gÊbqª]àè#ÿI] PÄ%9¼·üÑg¿+™´œµ®WJ ̃PÑT„fV1–'Û²À­€X[Àu ¤Ơ)(pw@Yöçé-k×à‚€Ls;œ₫"@sSàïĐ4đ«µáLàÀÜç@æ~.ÄDS©ú`¶\æ‘°nŽ€ÚH‚Tà³¼gÑ«°À̃ªă(/³+YŸ\W\>Q±—G"ưjư§#Tă"/Kă¿O—Fưc¦̀«*°È#ø`(Äưêƒذ©Đ5‘& P]=(w>ü¤ü₫Ë7ËÚ^â³ĐjO¬Ô£dH ç´N±—üĘt·¤¥k ¨qĐ5'‘‡{±đe׿ñ¬óÏîrxûÓµ‹m* eQVÁ ˜7À¼iÊ]‘̣`®”ÅƯóÉd¹À®ÆÿºÙ•9Z$5c˘F#0*8Z_ï’†ßăàÀ± l4Á™Óº3Q#•ï̃z¿́*ɦµ«%…Sơ~®ë@Ӹ鶕8¶%q\Wu‚úc¢¶1…j'H§}F0 pÚ²†̃Î6[H!ÀÜfÓϦl=€~=̀.˜ÀùÄ¿‹œOơ uY04H₫đû?x ”ÿ®ùÅ-²Q  Ë>rơơÀÊś²́N>óÜøüä—ût–q}Ú,w#!€¨ÿ‹œ(âp h¶oRîƯº]̃}å)²låØ\îp HP‹ÚBóÓsà`ÙדÿÚ <đƯ•GreE.záµ[Úµ!À̉¦`àOà7!À%¶L*6¢80·9`}ăÜ®E ~!s€ư|¹PÈsÀWŒúzÇ ¸w|íöÁó. ¿æ4»x{ª2pɵ_ƒg€c,tzrUƯD¥û¬µơº5P§ ;"ÿ~Óƒ²s0/Woéđó’ ¶;ˆK5\›U3FB"à(Ÿ‰Ñ¦Çá>®À4ÀDQçËoÏ»ÎX¹z5o4à·Ñ¿Ùüµül˜…l6¼‚ ˜»°₫pîÖ P¾9àúwôócătûYöÚƒà:_xóÔ/ØĐ©wX\×£WĂ ,'Ë(@Öṿ¯-ùÄ̃)Lñ~_jä§3 ₫à-m=S\—QFúÇï¹Eîyè1y%n ́ê]­‚…[i©Đè=x50—Ă8ª•Ó;ÈKÙÇà6ÓP8ÇÁKïo|ûûÎÏdL`‡™À4üzX¡Z^Á̀}Ôéç~¥B Ê©t:ñÏ|jOgCöæF¬Ï`¨è–‡ñc/- l À ÀƒÓØô²ú#́Y7³€„cåÁ8…Åơ‹:˧ïè—ÁÑ|%©'ÈƯcS\- Äz€ nóûÄ—o—›·ÈkŸ»L̉Mº°“m©=!9k˜[”SăÙIĂ:̀¡ú̉D­Î a7®.•ß̣kÿë4\ĆøÍMÛø3#+²ÖfX0s’A˜“͈ö9P,Ø×'N¦x Ï~g/­Ø¯!•Øô·œ ¥1áQƆq•¸Ï¤ËÊ"€Mkf ›6ѳ@¨%7ëUËÆe¯>Vo¶·rW@a²¨ú$ú¶ÊŸ|ù¹êÔ.yơóÏ”<@`iWZù#_N%8¨OH ÊWÉN…6.₫Á"E#¹¢ôí€öåk7öÀ‹€oº9ú7 €­  Àä|‚ ˜7À¼iÊWƒ³g¾—‡ÑÁW™.›€%ƯºH»túqÀRưä‹É4D́aÚÍ{¶Û\™¯&n¼„#o³ü±PO¤€ăüxBà$–ñÜvŸ|ơ¾>¹áüe²råR\.TÂ蟧²­¸3ÀÙ̀Ë-LJ1ŸÇb¼,kÏè…B,Ï/“íL³ưpVºơđ©¿^ ̣¾`ëL0đg_i-b6¼‚ ˜»ÀÜm»@y5Ê£ùR:G ¶º=~ƠØ}<Æp^M*Óê&wéÏ?„Å]|M̉§úʼ x Ju„€©|Ạ̈ƯO•€“œ̃H¯nÔÓ…p;Ùà'pk ^TÎÉ?ÿ÷Ï”ê·]-@ªSưÛ4À”¦B›Nä‘ưƒÊÊù][gm‘,¦paùơ×<ö¦đÁßê ̀980w9€¹Ûṿ Ø×7Üzû=?*s÷g̉X6VçËfoÍy`öæj"@Pܧ[ÿ,đäØ$\å,Fà1ż g6™£RC¦ư6ævÂṆ€bÍÇ‹˜nO?ăàøëá@“˜ €…€ >ù€¼ç?·ÊsV¶Ëæ5]n u«g”5Z4̣Æ™ÿø&NÀ¨€¡®Ê5;äöŸ{ùKNƒeZzÙcĂøØUS „80G9`ơ%?8Pè ŒN`Ü—Ơ…bn±‡Đ>ơSǬ²ú9:§0“1!…x›* IDATAÁz¦ˆÇfàZ.d́đ>¹`E³\†yoŒc@zÙ=#Që±EỹƠ…₫D¬&°×3L¯À̀uˆÂ‡Î©[ »À—G~ô5iÄ.^+“™Eº P…d¢Dd°,{Lh˜,G;@„ æb&Ù=˜E¹eùÔßÿóUx¥W­€ï&°F”ùĐÍøQÉp80G9ưW£Ô²"¤R©†₫èÛîmk˜¼· ÛÀt„ˆ0öù¾ñ{í%ƯÑ\2c8!€àôLA¬¢‰A2̣¨§¹p1Ÿưߘֺ¤`êeQ´t¯‡wáJ{­#W«V‡¯®ÊÊÊ^êS‚@"=5ăặÆO₫—œ¾¢CÎ\Ơ©[₫ôª`0*É…F ²¡ûĐh·ÿMÊ¢ n{ÔưđŒĐ…€ˆDoÇF`¦A.ÛØ“z₫/Üp6b±/´Ñ¿¿ øÁœ`æ‚0ÿÚt!Ö¨ŒÓäR±¾ÏĂ„*5€̣…?ˈ|ç‚2vÿº ’ü¤ñ1Â₫“ṼS)Èñ¨:̣‘’– bßgsh“¸È¬dü;œÀ „sÏ£‚ơÆ@̃€BÀ₫ÉܹO~ưE›¥{I—fĂ6£&€ûư¹•“†¹eÂCWkÚ‡ü´´J‘ú΃ ¶âäÀÎ~Ç>z)’²~ @A€ào₫‡ơ›Zu¼80'9`̣œ$>½à9àuë÷Áb@̃ €ư4_·7ntôéơ€í™æ®üLUipSíû´¼MaÜ äZų:P¨eèl\úb¥ú‘év₫*#°u· Z€ñq¹ưö;d}W“\{áFI5â"'¬óÔhc—›Ó4”)ÜaQG÷Nü›*²ªL³8+Y«¥I@>ÁŸ‚_0!€_“»b+6¼‚ ˜[˜¦‹œ[•Ô.x²`ÏÇ¡1zLơç­½6¼l¡]GsZăR÷ææxY‹2*î“P°W'–V)Û 8N§ ``‚úuX&Ø( [)UƠcɾ‡Û!ATÀÔ”!@0‰µ>ú¨üÛO•—Ù#+–v꩜.Qí Êw‡ư¢m³c¸ù§ =аhÜi(yV2éfOÎɧ®l₫¥÷~øBD È× ¶0ÊÁđ3Ÿ8PƯCΧ…º,4(äJy¬¤Ç̣úÎ̃¿5îsçj{ ÛĂKá4€“Ă®“T̀É©LTJÄÂiy¨Ú ×Sè"ßM`` Mè® ăKx¸-0;2$7₫änÁI¿rÑæU’â$æ®æ¡ù =ư98.‹[R8Uír ¢Î¸|’Cº‡s…rssSê ¯¼v5“㱑¿Ù¦  @!€q́³J¾à{0s†üƒ ˜/hx`ë߯ñæ°P{ù{“n¤J´€!0Ñ©à J¥­1NÖOL¡Ó[{¯'‹‚ă.'æS:̃)Đb́9~^Ù¡₫ñ%Aº-°¨M¹ư‰ị́‰ÿø™\º¡KNY½BzªẠ̀£ °Ü½Xá¯'BÂí >V[ü±l118Q’åK:2íƯ½Ë § üͦŸiØgẒZAÁ̀`î´U tz2ù$öï?t½̣˜ÿacÀ_é²ád.6ă f¼,åñØ$jª©ï;5̃¬ñ‰xGajñ¢VY}; ƒ¹»¥>ä½5m[ È]ºíT€`²€µw̃#£ĂC̣¯ß¢§ư±­tÛ'éÀé v€Í©³ÿ̀›̀̉́%úX†KG·—›6/ù_¿ñ₫ç &“Ú4mÓP°iÓ0.Ÿ`æ$ü~rNV 8q€ư|ê¯~ëu?Î$Ë»·°¿&p±˜:ă‚IÏ«Ïîåz±ÓŒ‘\` C‰àbÜȧ¬à¯°[—3äi”$ç;ïcPhF¸­Đ]X¨W⃶* ¿úŸG ”eͺuŒçÅÔÜ"xpdḄĐ´5¦ Lx L’X³bÁ`4W*óÁ—^uùª̃5V Ø€ßljL àƒè?Á˜`æ.ÂâæL¼2œ"̃yX1´ưés;~±tj˜µ¶ Đ  ©´|è¿%wï—‹iû4´ơˆL4ù²k0§…©Hsreë/Ë…P¨S“ú+cù’́Ê–¯¾äÜîÍ›6v"¯0đ÷-‰5v™íœ³“A˜í¨:1‡R÷̃÷ĐwĐ¿w·°®6üàÙCóœ gpf¯u8pµ¦̉®̃–¶¾Í4–Μ{¯Ûụ̀P2od-h̀^ø:å±f° ¬e¤iió½^|í™Ú²¼ 'Gé"§-k‘Nè^r#lU¾ƒ`ä¢’Đ ,N…¼s[g3Œ7 7̣˜` ‡¶Ê_}ăv¹úô¹æÂM’f³ hÈm8 €y¦Ñ¶SŒUØ_|ÍO&(rÚ–¥™¦æV8}-€iL°OÉ́)ÅÀÙΨۙídúÊ¢‹>™¦L#ñ%“jS7ëv¿8uÔùÛqÀ:;@?<H†Lăüª°+Îêh¦¥!€ñá; ¬5ô?€ëá²4wtI"M¬‰ŒŸÀ2±0‹ơzvMôøƠ«F¨oDZÑăÊ« Â%>‘OVªÁ´€]ŸÉ̀åY-x9a…\Óuư€·%r* „ÑûGî–ÿy|L^¼¹G–vµëEB̀c([à$4áĐÿr´&€EºÙ j @ƒ̣”Á³ »FÖ.Îè°Åơ‹Óv'@í4רcë˜uÀ„`æ‚0·Ú+P{t`•XCŒ7­™YŒ#Ù×Ó°§æV±±ÎŒ‡YÜÙ®~nä?•4Áá¢zăÓÑÔK Xsøå™ôG³̉€sîy6Ç™ÉAĐ«÷LI£ W©§¥ñ…sOIkL°cª½?ͶñÙ:₫ñº` Œ§€ö+@ÈÊ×p«,mO˧/—"ñ•âœâ₫ ×`¯£~lTv€/XƯ.°i’RJBă@·Q?56 @›aŒ̀äöÀ›¸¸Ø'8f!øñ80_8@DåÆÿ2ƠùƒnaXo{FÓN®ÀêuÏ)˸B…صÀc̀!.3́xqÏÏyùéc7(§V¢"X©O³]KL”½ f?•R=öVƠơÄótÍÊu\ÀƯ% {¡PĐgëC÷ɧnÚ-œ̉%Ë:¹đÇI D£4±£?¶¹"8ë—4 ʃûÇTk£û€ïk(QØ4Àø|‚ ˜SÀœj®@́4¨ÂME¿ï˜Àfèäøθ‘=G÷º%P×`*Á#rçư˵§wË+A(P@?³íËvAơB' ®XÔ,«:›e+ ”Aobb •‘¾/ø£*€Iƒ ˜SÀœj®@lÄđ…Ù‚wöûÚ¡sd—Ă¼ñ̉ÖŒ´¤S 2gÜQÁ\ û×éÇJ]¤Z!À€ÉÀ©f.G?ÜÜbq±Z Êô=\̣¹÷K€Å6¼LÇ¥}¨ß@s#º9%€Ñ?ÀeG“l†ppd¼ ‡qÅ 5@íMÄs‘Û~øí¾‰ñQ: üöømôoB€¿€ñ­5ͦ_0³–A˜µM;¨0 *ßÄĂÙIá¯UX`{¨íŨ#?<´b[™… > ªÑ½O÷Ô¿2₫Œ& ?Z´ẹ́0újíéâ›m|{·đíJ¥Áß“=G&”?LkQÔFåêt×>ô÷ŸéËuí ZLpG…€´ƒ}äÖ‡”sW´Êe=ho×½!…ü±ëCød4?ƒ÷‡8¡ôèǃ‚S0´¢Ç€ßèGđ÷6=p80û9€ÙßFÂăäNt·¾•Ó>Ăb‰ÂNĂÂDîq‹ù(pDeÁÁ2Ơ#Θb‹ ¬ÜP¿üÓO¦´\xJ‡ÆèŒTû>øoï×­—ơ´EHDj Ü ö&đ›mÚLcœÁ̀~`ö·Q đØ8ÀÎW À›v•±ÀÑ\QW‘oÀ(?·•q+ n‚Ó‘bcCJ̉˜+HaÔHmA ïôQíj ŒT[ß} ¼ÖÉsÄcÊ­0  O»Øcz„ÈÑvmM)Ô+Ơ LŸ¼s äm$€)Ÿ¡] ïyNm jVæÀu hï·?t·|îÖٌ̉뀕¢„tC裰GPÁ¿PríÏ„0‘åÜ ̃ øÍæ'ÄpVÏÏF=ĂOàÀlæ@fsëÚ‡Öù¦>úºK¿•J&†4 ̉&Hp*€½5A…|‹£§ ÷Ègđ4bR›êă4@…O ‚ ª1¨Ñ˜Pà ¾0  F‚Ô‚¹g”eu¡uÚ2œÆƠ[]uQÑø‚ úđƯzŒ˜ ôôÉ{ÙŒëzµ ´T@‹¦mô2'WxƯsßCzz ;¸-+Ûä‚52HµF₫₫4…}9$×zÛC€7À7›~₫ŒG·oăƠeMG0³•®‡œ­ÔºNœÚ­›„Ë̃™}2íq́!ïÇÊï^œGđÊueÏöÇ¥€jdÆ¡º¿„5“e<ç Ñ•ç ¨5 á;Ñ·ƠqÔ½ưôô?±¡ÛÑ{©ĂQWí7ưÁ³ÊêVyF/QÜZG1SZ/¿)eúa¨m²©]Zz×˶ưƒ2 á¢`€J˜sĂŸ¿c\²¶M®ÚÔ©ç,½jµÜ¶{Lî̃=„Ơå%Ù±m«́Áe=XDXÈK>—Ăºª®°S!`ÇÔ;bA€á|÷4 tA]dóÜ"b›"Iä †ñ0M@øĐÓëÔó¸YQ¸;KàhPÚ1§qpláÎÇƠanƯ”áøåB™©ÜxÀx¬³ Hå̃᩼q q’NúëèZ¢k6­h—öå¤sù:yÍyËeSWƒàP?°M ç¥@ơæơ ŸøˆX©<µ́J¢Pơ0 7̉fá¾»’Ú…ÇEùÁ80›8€ÙÔ–“Âö̀nqñdRÚ}X~~Ï£RL·H3æ₫/\Û.Ë{ºä¼U°q„đ篖›¡1EèÇ4Ặ³ÇèTÂpßA÷5b!¡ ÀÚ€ûNK•w4ªD®ºx‡A’ ÚO¹̃½KpG@«%chTăíPmgÅCƒ:ùUbÔ¸´ .n4nBëâk3¸ pRêvÔ ‚ªN›d9á‡ơuuµ:²̃|X.ê‰ؽ)‰–Éd2̉¹¤GÖugdăê²ù̀3%… û^²±UîïĂă²ơ‰'å‹ß?$'dd°_…¹+.¿L®?g©æÅ‚8ưẹ´±]HOô°T‰ñq~4D›­cïVϦ_0s‚A˜Íˆ¹íÉA™,pđiNNøEÚÛ[¥¹­´8~Q·†°$‚?®‹bó(¢kéüqU•ßøàGỌ̈̃ªWvâ‡RæÿD±|¯à˜›ÀÜl·@uœÑówƯvKá ·=ùÑÜdy pÚ×¹»dÚåÇ΀•ÉĐæ}ó¼K`<ăeq²¬́Øs@R™X/”ïƯ’‘¥½K¥·» é“̣®Ë7k>—mY§·ÔṛÙ›wÊ.衇†F¤4x; ‹Jƒq2‚`‚+ÛƯ‚6ÿÇs‹¤1Ó,“ă))¥¨Ep´&¡ÏäđU3̉"«~b } ªU¡3¿T¥­‰ê‡iÈQ}|p¬̀§PÀÚ%¹c['đSÔAL‡#|ÖÖ$„Úåöẻ̃Ö.+×nË6.’ËNë•$Fư=ĐÀ´&ä_î‰##răm7I9;,Oî듾¡pú²5+9Ø%àÄĂ=ä  Hà²+BWÏ+f ù"/—ÁÊ†Ă©bWÅ¢Ûß ĐÙuhHÏ xƯû@“´ô¬–Åí-rÉúÅrơiKä+»q÷À¤ a5| ?ô_[î—DnˆGÍ:ơ?·±8!p¸s( `¤ ÚKØ‘àæư¡¡@̉Ă[đ”lƒŸ¬"̃5¨^¸·Æmơ¬ñF~Q¦ŒÀ<-"Á–#Đ™ÂVỈ»¨­EV-í’=»wHr2‡m•ià,n×í ¾ØG;_*JjÑRœÇŸ–s/¸[-Ọ́¿_u† W--ÍØ’)̣ơG†dÇ“rÇ­7I÷8Øù¸ ÙlBW_â‰È!€<Û¢úHb ü,¦yUpZ"üÀó  %ƠF«ÆÅj÷°c |î¹ç.ú₫7¿r̃WoƯ¶ùí/¿ä_«SU"G₫ÇÉñ:¹¯ÀgAx˜|ú8°é̀³eÛC÷•ßùÿ~̃ñ[¯8ûo7ö´¾!Ê]ñP{f¢*ûøÏ̀fâI?ưSÏÑ#·₫Y8ó À¨Äd#K‚ È̃~¨ûûV@¼ïî„üR-]}$Ó­̣ׯ?¸Ù,_øơ ¸9!đC¬øæ‡ä@ÿ ïq <ÓXCàN$„€ZÆZ3T•—|Ó­°xO»>--;∭ !iç½2±ç~Üä7a Û0 <´‰Z4muäƯă[ºZ³}0eB Ô )Đ™IÔđ3 ÀWÎ<$₫œ ™j& “‰‰B¾¼¬»»ñ­/¹¸1yămo|ÛK/ú;2†=.²{÷ƯQ.ǽÀÙËJ/3{i ”LáÀÿ<̉//9}‰üî?₫wCo{ề̃ÎÖû₫’+”Êă¥æî DSRNơĐÑ!F§v¦<ÁŸsÑ\½¯† n=^°¦î¤ũ.×ơ€.qCØÎíO(˜¼́Đ4«6œ!—6Ëï¼x\¹q±¼đ´n]wÀ¼?}Ë>yâа LÀà™”¦f\AŸă5ô€*Œf’E½́†`öL KEÔÑÚÆ?ô§ÆÁ?¥ˆÊĐÉ‘¶’D-¶Üq:#…íËWc9Ĥl9÷B] đû/Y§€K+Ơ0)yÓnÙ)’;n¹YÁ={đIR (ó$@.dz–ï41p¡î¼đ‡Đí¦EœŸ;§ ”?–Đ2¸ ‚Jàă˜Åcåüé€a»̉Ăç+“àØèÄÁ‘¼,mK—ßzís»;¿ë/¿öEÿ­&r?LbÉ|·%8f7‚0»Û'PW‡÷́–sW.’¯Ưwè”®Öô;—w4~`ă’–ÉÑl19-&@D§£kfï̀NŸÆzl÷æ~ |ˆ/h  ع|`›  #G¼èªu PK\̉“0@œ° 3wo{ÈÿüèVéêY&-‹eơâŒüꥫäuç.öJ î&0ÓÚú&\T3¡€Gµ6ƠØNư2êUÀ íƒ£Ÿ…ƒbÇ›±‰œ́ÜwH5ä…Tø)xlYÓ)W̉,rÊỤ̀æ­ —áqåçƯÓ—ÿsăvÙ³wŸd÷>,Éâ„Ă©]€ô­»=àOƒ"₫hƒHwyÁP×V‘ô@p  8èÁMˆyC̃tÁ2Îe¢P††B“Ơü8*[]¶Î:̣ÄÀ}C¥Ä²ö¦̣ơW]´æÑ'w½ÿ½üƒ/̃ôßÿyKnbœIØèöđ]³‰læÆw/W¼80‹8€YÔ”™9đå{ÈkÎY¦àËÁ-è]￾`Đ_>4’ON`ÔΗ£A&GĐ:2Ô‘#B¢î˜;MdU½(à Ë&Æh²l´g$v‚€ÙôBFï* ¼\4@$ü¹"̉Åyù IDATĂx´đè`ŸŒơÉÀ®„¼ó̃dù)ôpó×-–×\°FFÇs²*5,k–cÊ. #bRÅOóï̀8•H¥¥ñüÓÁ§¡¼£*tŒ¸Y?ê&ĐV̉××'Ÿ¿}·ÜzûƯ’Å~S\ë@ĂindXkAÛ€_ƯÊṭß@ß…Ăõñ4"•qhÈgRÅƯµùi»ê8*miQI-…œ"èÙ=˜M,nI•O[»ºçßÿí3ï₫ûÏ\³â÷ßöúOk7£@!€̣‡ J̃Í™¹ˆLàÀ³Á <\e7¾ûh¿\½y‰løÀ÷›îÿø/î/~u ®vŨ_1ê§zØÍÑ#kt·YøđuóÀŸKc×́°‹o ̉yŒ%‘ưÅ₫±Q!@ß"đ‰BÂLHM!@3ø¨q̣ø§  ́ă§ŸdGa@Hµ4ŸF̀UîÛ¥ªóî—¥]]r ?ûù/ë–D.€Ëc¼„…‰ÔH°d¿1ÁOƒCó®“1– Lg$Å{”Ï~]€:đ…¶®¥̣_úEé;< ÿú¥ÿæµ|H₫b†đÀµÙs>ß¾«£Ä`Ïú±äqT.ßé©qŒ¾ÈϽ’û {úÔ¥¯G5ü$*º/¾†±uø¶' œ -KZÓå_û¥^ỬÚ.¿ơÆ—ÿ1¢`^L(Uw®Pä×FĂ ù8âèLàÀ,â@fQcR¦ràË÷`Ôî2ÿÏܶûœsWu|<“n¸fe{Cj([,ă‚⫛녋7vƯ3.dËsơ8¢µ5eälºÙáOgJÎ8¸Ô¸@0— zz‰™ƒfP‚ƒn÷ Èâ™%€g [üj\@ÇTØ1¯;ô†»ÜˆÈجL„è’/H°Ü˜ˆˆÏrÅ{Çî¬ÔmjV§<üƒ{•Ib¸U² àÇ*@ÈPزX^/éÆF)¡.)¢x/UûéS(ó^€©<ëC7ªùY7ưÙ.È…[½#?g9Ϋ†ùxñ5Ñ1üRS£Á¶QNưµÁzÖtC˜94RN,mo,¿ñº—¾ú…rE1wƘĐuÙn,?笳^₫¥OÿÅYß|û»ï|ûµ¼¥¥¥¥sÜ V‚­À,-œî`5àYc}(øh°Å~?Øv¸ïgüíc¹by+´1’ÔÁ>GÙ*°Kå–.t×€¡£e­á~/̀Q$ÿ4ص}´2£\5̀ÀC½‘¾"D½|Œ¤Ê?ă‚\d äÓŸÀƒ? ̀bóéĐä¡à@§>§à ¥[]ă¯ù»úx‘¦8]Mk̉N‰F!đçFµ|'è£ z¦‚Ö l̉ÏUùº¸/**®‡½&Ú; S+;¡*~¸iªJ~¸*Ïc{Q‰2ªUƪ§†Ó “°æD0•hÅ^Æ•=kñù[Ö&¾swñׯ9ï×2MÍí¹¬[äec#mf©ÙFv%XÏ‚đ́đ=”:LíÏ•₫ç¬ho`§{˜£~ÏQ?‡eªbç¸jxx2€½«aIm>nh<‹ĐR§ÑâÀ¶[½‚^X"ó#PÆ çà—£K—9Ç“ÀLOç‚WÁă*r‚&ATUçœÿGDJV·rV¨GÓœ¦.qøti§I§ởp¼*a×Cï đÈ‹tªº€¯[ñ|đư'ä]TplÁÁ2­\}µøGñâpVÀüèöỌ́ư(ÆË¹*K—Œ˜[PkHÚ”!zû#ê‚£ Ù́åÖÆÄu—œuCù[·¾ưeÏư¢p§j̀bèç×Àâ;pà¤q€ßs0Ï:x¯ªư¿rÏ×á6¾2À?ÉÑå₫¡,1¼QàÇîxUù³#'ø³W >†.•Qêáư§KniêÅ¡®)ă!H(HÂÏ AÏF¿>U•#‘Î…8ÿÏ…3ÔñˆYĂ(Pˆlº½‡WOû€ư¸¾[GæÓ¤ơăÅn̉À #ÔV&ÔˆtQz—‚<ejưPOÖ¿²•Mg0A„ÄÔ¾p”ŸÀy úø#~‹§KÓß7Z–ïqwT¶¢z¨l+œw¨kSh}P—h&Tó4XèÇ­’KÛÓå×¾àÜ_ưÆíº·¾k#‚(4âáæC´8àvæ6*LàÀÉå@Đœ\~‡̉¦áÀ ç/“ßù¯m WnêÊ45ÈÍÏ[ßyv3¶ÍÁ"¿\ºCåês5úâ¶Û±KU_úEFƒíål¹«@áåiEÔöØö“+xD™Ñ‚Œ€úÀSpt5Đ:(Ư7I‚+(È2GùøƠ2z}?ßM,ơéaØÑ̉LI :âËĐƒó^ñÏ•₫ô¬±™‚Ëßhf}éQ́-;sjzÖêbV~-œ̉Ø;œuX£Q¦ưáª̀ư½làG¶¹Ï­ ¿º²áĂN”ñ,Ÿ‚đ l¸|Ă'>ùÓs.x̃›?ö®7}19ÈbööPRb´ưb­Fđ&pàäp '‡Ï¡”8`§ú½é¹ËÎÁ sßÜØÓ´,“j(N˜̣—& û±[½%;d×kr{ŸvŸuºMzë)€$˲¢Û³™́-h›ùøäXïîûịÅu/_”GS % ꪗN 3­CM„cIS“$æ¿ú;‚”.¥ô‘DŸ®ô7W”£Eô#3hæjD‰‘Êé·¼âĐ£;XŒ¥i£¯ —«gxHNUï\Éz̉E8 ``Ü]DcvMÔăze±>̃Ö¾×ëÅëùW¡5‘cđ«ñŸîơxă3ŸÚ4*ˆĐBÈûp9mD—‰5Ù^ÆUl¬l˱6/…«mI)ëa'¿4b{&·.Æ}¼̉HóóÓi˜hP_®t#2̉&Ïèi.§^ưʿϴ|kñùe‡m‚ÍØ&È"ù`_§2̀˜Ǽb’\pø xf9€g–¿!÷cäÀÊÎ̀yØúv-¢—q¸O"‡Ø4₫qQ÷H‹W÷²ă¶39Ø›v67` [·&e Û·¦‹ë§=Z‚?AßL=aẠ̀đ¢UÊöX&Gµ™£ŸÛQ̀̃~UX%å§7-@/đÈ}ß]₫'PKêµ1"ơS$©Âæb<<6˜S0niu$Ê)‘Æ̉æ6™q ¾‘Ħ%Íåë_öÂO¤¾ôƒÎ÷¿îªc›`¶ æ¢\Y¬-ô…€(8XÏ<‚đ̀ó8”0~¸í°¼pS·¼àÔ®Ă9,öĂè}|Y²9gRö”j´÷¶—i½âưă“²b®ª… ÀC\¡q9ˆy4œö…+Đ̉˜V€ù±L+Wó·@Ïß̉Wâ9Jbz,#D4p|ª@hetÛ*IởQs àMüVW{·đăµc~º¢ä±`A:0â_ßƠ¬‹qª¤~wv‰PmÖÆµ₫ö=ÉÛq¯µ0‰u]Ṃ«Ÿ÷Aụ̀M™÷¿æijnîÈNLđKæ•Fm&åq®Ê§£/á'pàéæ@.ơé."ä8PŸ_¹÷‚ÿßüdgçƯ»‡”ÂĐ G®b…µH ²WÔ_î5ö› 8:³‡ïÓ=<Ç}h¢€#¤»-­‹ƠH óơ?|vê|àÜÑ #Oc4>ÂØñ×>Ƥ̀‰†ëª̀€Đë¯Åu^îÍÀÏ‹6«„VWÛƯ@&ÅUö ơ³¸´ưÇÚ•¶8S*eªY‚e>ïư¸1oÑđÎÍE}ŒúOëmQ¿#<Èß 7•pŸB½‡SOSh«¨5PÍ mmLJîE؇+0å5Ị́Ú«.~ïŸ|₫{øÂÏvØ~₫“Ë ‚ x¦8À.˜À“Îíÿês–Ê—î:đ¶+Oí>r̃êEÍ9èơq´/NÁ›ä™ëÔèjs @—ˆ>V;jööDư]úùqsOoknÀt„zñµ·Ơfă?~„<đ‚3‚ÿ0¬q9VB<(Œé±8Üéà@Ÿ™W̉̀)×tŒ@mơ@Ÿ:ơ"Àà»ú;Đ7€~IJ†¾!¿£¼ª²Œ¤€Èª¤@$.ù£¿~S9sy«†÷°đÏiä)hy°MЬk3ÁÛ»0̣çw{h´€µ'z EW —Wá̃7¿âß₫Âïÿ·ơgß‹D₫6A Ü&È Z†fĂ+˜Àg†5ÿ£™BB®äoó3Ă‹} _{^ï?œ±¬5‚N®ĂhO`_;aö̉è63Ǿ´ÁÇYMÀHơL„£YÜ Î¹ùùñă|˜qôÂp?eK?2k{GAÿ›hO‹–™ÙÓDd±©)'öŸiGåµ´ÅŒ® ¨ÿnÂß²ùkC0OŸOqVγ‡q˜KbÉÖ@=Ï<ûFøë%GÈ”zxc½ôêôêĂM £Ö×:ïÈÊpW3'=90Ás,:2©̣ —oyÙW¾û“»~ù=¿{.‚(4á1M§dë đ&pàéç@~†ëp€#~^åûÖ½¿ágOiûÑcG¼ø´î†Ô§cù¢vµøë('µ́LqéŒo¦í÷ưH›ÂC½´N`¡ ´–AuïjŒÎ¨]p£9¯w·ˆ°I =ŒáǪ›Úw/›Øé§gÆ"̃ø—†¦‚ §gyUÅs™ûu­3êk#}|¿†½+ă­!|ÛXÇͨ•Î.)Ư­ÂQ9§œ²ù;đÇ÷‡Hª˜‰áÈŒß %n;¥êÿ0TÿĂ9=»q¸› ß1,9<–Kà[—s–·”ßû¡ăÍ¿ù{g#‚¾i|€äú5¤;˜À§••ÿOk¶!³À x¦?Güÿtëîî_}₫êww7§\¶¡£Çû–9R*`Ï5 çP9ïÂWÙ7–×3×;°€êW…‹ạ̊ơƯΧú—áÚ{"-…Ü{̉©hÑĂ[ÏÊTP>P¨v±.̀ÏÍÀÈz`KË2́ñăŸˆ;ûGƤwÅ*ijiƠ:³\U2ĂvǼ)av¦a§3f 4dƠ_ü£¬,KË[‘T{:ªôE–¶5Êf̀ûóxiN1ˆÇë1ø×#‹4ÀĐ²ø₫\ôGƠ?M½üß§öätWoyd:Ü`)ăxÏ…đ¾~ø¿÷ÿ¿+Ö=çbܳ )–iŒ,RbÔøn& &pà)q€Y0Ï(x¦ÿß₫lWû9+}áô¥­¾¹·µuûü†²88à܈S}Øs¥>úRU£s:–s¨< {ù£¾Wé¤ÛzÄé÷Ă œRÎq—ABwøéW{[ü¨€D̀&MÑb5äcç₫3=¤©ö±2|ÚÍÏl;pHi@ûÙưö§₫她\.‹Ë„(PPO yj†æ vàÀSà?²`PíÏ‘ÿ×î?tå5›»> °¿ *x.ôKđơR«éÙñ±èT±€%ïqƠih ấÔ]wí:_sÏT¦àhq<‡©€dAÚS2œv‹™N?ºÓ€SGOÂæ1¼,©µh¯4z˜ñh2/ÚĂKåOq3>ia]-Ơ¡ñ¸xÚ‘9i´N¨È×£€ƯRúUa\Ï0¾oâ[5°©!â7Ä­{ºfó'ö^I›H'dUG®.ÜæÇŦêu4TS~œ^ÇÅἿS”%QBê^̀ñï̀êwÂ3-›!L1°MÓøqû₫  €v`ß"dàÄ’–¤¬ûĐo₫Ù'#P0Ÿ8ÀÛüh₫7>Ü÷#€ÿgÑI^…Nà_L8zĂ—ÇN=^å,đ†¹ #Æd z:î_×>—S4ÖêË1üØü₫´4+:2è¼ƯçÏ‚©4Nø7`ÍA ₫Ü’ÈwÚ¤UW˜s;?×ëƒ"Ö ÁÖk׺]J­a%¡i\½Ơí åÙûñÖ—éfƒ!ߦcL=‘ăQ~4l×K‚T(̣:_϶°öA[9á WDÁ±~i€2N–Œ‹Æ'&«7A˜Lé(àO“¤*“÷i©ƠOÄ|U0ÙRsĐˆơ=Đ(P{µ½?«Ú—…Û@Ȩ\_@CÍkZĐ‹?^r5€­‡˜(oYƠÑö–7\ÿwïøØ_¾ à?‰:̀¤ p™iá'pàÄ94'λ²p®Gû–ÿü;.¾tcç?¹¼í 07«|{<5›(/䪂#9K/–ÁïŵtÀŸ’F>)ÎÉ»îqNÁA?—´èI¶Ưù̀́>¦:´)]đgÛSœ°UÿBzp¶UûÓœ®Á™‚á>Wữ:ñự{â*P­aœC 6`8˘V,jưíwưÊçr#}¯úçO}üGȨÂâ‡̉å>dĂh8pBÀ ±-$ªÇ.öĂ|ù¿î;đµmê~9T÷ Y .æEyđj"#₫Ù¹kÏ¥ƯFQ¨ÚÇ­®³û5×ÉP¹€÷´d’’Ăé~z¸L ơèđưØCQ-ú̃ H"8–½«%…êYŒø›t¥vJx™ I£:¹ĐPÂ*î:q‚?®¿ üS7J ̃+ æJ$8¹¸ZQ%aZP4ÍF>Ưæ=lm–c >æØC æư\úˆ‡¨°̣ ôWÀ‡ƒ€N7ÿ¨¡IaxŸÂhœàßÜÔ(-Í̉ŒiE½«”eÍĐª]§”xÔ¯¢>Ú^qM4Í#èS™`ª mø^ üºÓ}µ½¦5‚ Ë̀9ƒÄïÆ7,ÓŒ*9ŒÅ¼øª¼zqsĂ?ưé}ùÍïx_ăµç¬^?>:J¹bp|r +Àøhi°iª q~á7p`F`Fö„À£qÀæùư üå]CÿoSOË+q™-÷A/uàt[́¹´ÿµ. Ư˜9]hu©Ô¢̣€ vL4B ¥à«êåJB—ˆ™ûáªR†{RæÏ‘Ø(ÖP ¾@€Ă /©úÇ”@£ÿü¤ä!!” (©íN{+C (¨¦@ÀÙÎÍÚĐOAÈå̉}tSæèñŸưÇB±²B¿N•¸?ư¢ÄluäÿœQ>̃•Ÿhñđ©â§Ê¿@£ư @¿9Ó(­-M̉ÖÖ ›Zt×ơÂÎ4¥æ™@ÛÅÚ¦¨|¶LÍ’MÏï†HK…NYuá[Ü…9ÿ~€?›”ae¢½ûÈÔÍ{ha'@o{#N¤L`JÀE‰„€Z¤‡6k^Ỳ…u·44^¾¡³|ă½»·¿ốƠÇÇxx ²FO‚›B@TRD g±– ưW[R®N½d¡†—îj°̉ƯzÛhß;=)­î9ëëî²3£Ó6%E­¹ù9Ë̀dT§!ưH`¼ÂÀĂơT€0Ú‚q_ưÜ¿…ju¢DáçºĐ¿¢Ox,+¦ùQù´¡°«Ơf,ÄÀekxD Í.SA>æN(Ÿ±đñPº¨Íw™t4øNëq±eµí-M¶­£Á*ëZ¬½½Íî¿m›U$^·+´§UOF„7I¢¸7§y¢3çˆèiSa?™<æR¿u²&Éçá̃)ÖºÏC8)Æ…ơäÄŒçĐܬHæ vF’³åƠ×µưYe:ơơ•KºÆ·$»¸”À3ÁŸà‰KÎè R>ŒSµhHh¡ 0 „ ÅN@·^âW·Ÿ¸Ä-„x́ËrùOZPd¦6ah\Ï °ÎÍç,«gZ[4oüªÎcb ×uVÛMk­üº{²/ăvƯçæ²v¢«ßN ÏØøÔœÍLM¨^•éÀ]2Yù€A2tΓíwè^ƒtDˆO„ HAơø?Gˆ$ ȈhO¡rBZJøÑ;o I¯̃‚0WvÓøĂÁƒáÔ]WB)™úäÈ_q ¤Yák.!|[F~Yyµµ¶6[¥læÜºWˆ¾êi’d7;â5›Ñ¡‰”]ôXcmÚLJ—> ăÍú‰rĐg IDATÛ= ÊÅNŸî4Ư’h­‰á4À¼́ “73GbD­Á‚ÀÇ ›ÄÖzL¥gKr²4˜₫ñ\ó¯ßùÂÓ?óƯ/ÿư™¤øX  ¼¯ÜH’½âœ;EàÜ1)†¬2:̃g:̃gÿæ#O4ÿ́›₫Ó•ªß"ämóœNø¥@pÎ¥ Èá‹Y@Ô8àŒưưYqüZL³§×]™–rŸ€k€a¤&8by `ÁŰ("RÅ•ƠåÈ?­²1̣"¼́.*éQ—›bÂ4#nU BE™ (‰Ø€àpd¥*ªU_›¬¾]-3²ĐÚ­®88ºƠ|zÔzF%¦É¸XÑ2AØ2@g 9R ¨Ư·(4^9q†\{)ºè[a I¶Ȱ¤³“&w¡S¦•A1:t1~­đ/%D¯_µ/´­_ ç!…#]ÍmvѾú ÿöơÁ¶LØÇG{ŸÇm1¨ó ä²ê&»̣ª«Äå—Ûư"8˫묱®V'ADè‰`ꓽ}æQél ;±¥Ró„ĐƠÖ+ÂëÓ7äG˜û`›Ÿ¡Êj¸~½̃ÇU?Äi…Ñ:â…EuïÑ̀‚̀§mFÄäá₫ŒŸJaÀ)‡¤Ï¼EÇkP +¬^í̃$DH2".DĐ6Ư ¤̀₫ßû€´‚² <ôæm†̃SÿRœ’ÑMƒ¹ínßóî?₫à§ï½óÑWÎ w &’€XµJs‡ßiJ)ºâœ;EàÜ1)†¬ÇÎL˜®ëµ=Úóú[¶6üÅö¦ªzq×)‰ü%áÎ¥¸%"áx)‚‹Opˆ2qó́•Ë́vbxs)KCe‰#p8«¬I‘?à¾Bc\·¶Ơ•¸™àPR°ÈE,pZp₫œï‡ṇ̃DD°7Q¢Ÿ«c=Á¯™®̀-Œ¢S‹ ä÷®6cD(·¨₫̀ikííVº[¯h·½âL!n &₫ö±^;=2cCÓ–î’á#âd1—v‚ÅA ´HS–_œóeü8ÖV–¢™úÊöăÄú’áÈ”A:Ç{Vø~NÂó–ËY‘Tí¤­êĐ2×yû´ÄđpëÂÍêC‰‹ås)ô:‚¢$¥Pbi²¾ÄđÊPáPZn¶í²íÛ·Ù‹¶7ص›°‹¯¸”·’ö₫è̀œMJJäÈ1rË\Æ«\u‚jåyE¡ơ´UŸÉP0de„Mp8Ö çÖ©Ç+¢R„7G¶ØsD-Ó Gf܈°XkËÈ¿đ60T¸k;j}ưôJ¡S1:̣º ¿ˆd5Xÿ¹E0H± >™óoLÛT,@ú 12¨Ë„dv8÷¢+Z·LôÿÖ»>øÉß{Ï[ßüáªêêꙌ¥’†œù_ÿsÓ-¡ËEW³F Hœ5Å•#àÈǴ›GGïÚÚXñ©í-UDÇ–r:uå  ‰›²“@·â8̣̣”á‡| ÖQ‰Ưur @ @¼€lR@đùbtçø”÷;'ÇD@˜Ư½³Ñ‰ ½àz¤ÀDZ/̀c€ D¡&B ÀAS¯#ŒP‹ÿ’/t˜LÅ¡O„E9AP*Á Az8Ḯ"z²a ízµxkm©ưü[ÈAÊñß¾~̉æ³36ĐÓ¥ü)'zP ưRÙªjQˆÂ5:‘Pá{ܯH¸ëêR  U«¸ÂW‰~.‚h+R ÚâOcpG~Ey…sñåBƠjJ%H_Âx»d@\©¤ä¯nî°Ú{́†­Mö+/̃$$Ç8@X¤lBë{ àˆA¼Aa.úl%…Íæ“y¢M̃.Ís¸ñ°x8y°Ä¼ù”†1ç"Ô· ôΫµRƒ_%b¶ƒ#{BÊÑѦ9‰ëgƠ$:ZúªO†Ê¥._éÉ»>Ïâ₫›ub×­H¨ jÔ-[̃ÁL"­‡ …ä˜ ®UyØÆâkŒuA-K–©2iÓê˜mËüê›₫đ»_ú;?y}çÖtº¢v~̃ÍG½€(NcHxBáEB€!-ºd@q)\ptc™¹ë¤@ơ-%,¤ .…s€)ù88ÛBG̃B·̣›8€ÙMRĐª“ÄM²́OÔ°Üơºư6 Áà¾÷ø›œ™µ¯>¤=Ú¶ÍvæZ»WÛXhéÈdPVÿ$©P¹ ă€(@ăQ€È9Ôå̀˜*¡Ízøû¨onë;Ø¥Bê{{@(*MàD?:?k̉³G)éT ‘›ưÇ{wy{Oí¶¯>5"›ñÓ6=Ô'"‰ËhT”~SB¢ÊÇơǵUº¬¦Zî’0¤¥Đ¶P®GíQy"¢÷R„?O 99à"|ÙÁ‡´¢¶¦̉ơ)ªDÔë ~j1lĐ:¶1*«ª­ªs—uvn²_¸½Ó-1Æ–#ïC±R{ø3P„äÑăR!eGÅæÍ×ÚÀ̉b|"Ăú 'Ä>C†IcÆ+̀Óè½Ƽ\íÂuHƠ(d áJ8Ó÷‰ï÷Ø¡îq[뱦:{ë}/đx”ISJÀ‰æB-qB ´Z…AP¨~Zj+́ŒQiưh‡ÁÛAÛiÎÓÊ÷­"× Ñ˶€Â¬_-J»Q ¶pƒ˜-ưkÛ›₫~Ï3¯»q#W ˘2…¼$ ¦SP¾J̃q± á«ø».G H¬Ëi¿¸NcäGÆüÊdxᶆ%²̀è‚́¸ÅH,Pf.]\ù1Ü {œu²Ó^!å,8%€ẁ)¡À­ :ä›ÎÎÙ”DĂYqúC#íØÁEûä7k­¡¥Ơ¶·ƠÚOƯ°A–áªü8$ h}ĂYfÄ}¹ö>E èSHÄŒ>Tƒß¤sNOîIÀPÏvÁŒE.'®¾ÀáHơO¹˜®˜ú7é₫_xÑF¥Äí¶?Öï„É`ÏÁ°÷,œoơÚïÎ56¸hºjN×" ,büÈûO½«¹ó„Jrđ\:F¢ =,ï• ùs̉¢®¦Ê¥ •²Â×"%½†̣œU‰ËgëâE·\g/¿¢.ß ḿß2—#¬'½°]ÂG,ˆơ¡MïLăŒ\ß·ƒ¼ËÄ$c¢ozËÉ ¢ä…±̉\P ª"(6jq€#…P ™Ù¬}ÿ且:lp ×úN<-d-»’èT‚«ZlR~­/·₫‰YƯÀ•Ơª7!Dˆă‰„·“1RƯ ₫VHÁá“(ćt´1ÿô“²¢CŸ7©5Đ?’ƒ#œXA2¢áÊíh«ïøüc§¾ô›·Ư£äA æ9}8x£¨ôXe¡O|Ñ­Ó(ëtâ/¦ÛùùÚá¡WƯ½«îG§º„Jíæ-³ÅD¹Ñ€)Jvuâzâ¹éP^ö¼ĂÁhQüü¡aic‹È̀:!€~7evÄf&Glàt‰=ôhÊ6lÙ)éB©½ù–N)Ú‰[Ợ̃®Ö*WÈâF6´º¥ÇèuÆy€5H.¢Z gàÅô‡båý¼è[øÀ Ø0Ú‚bû¹2‡lÓBxư“BpỆ@óüM7µûxuª₫œ€|Ö¦¦o»ézËNowÄO¿•q5ØÊ=½­tÄ®ææFźhsµèKSQ.ụ́DQ‘=juc›µVi¤cƒ½̣/µ×^Ư’/fX„×d° iÓú¦ đ¯Z «#P_FS/ú¶c(j™ËçƯç†1V ïàx>k„q‚T ¼Jw¤˜’æji ­́ôÀ˜2-Ø'¾{ÂOqyê°--̀Úâô¨çô¼ÊÇ}UjkMMµ$j ‹OÎé ^Ăg̃§U´›~uHéwF·Bl*ÈÛêD²&Ñ"yóÿÄ´₫7¢æ ,åºÆQ&E2Pb;[ªR×o¬±-5‹Ơ×½äƠ7øæN(Il]ôƒˆ áŒTôơZtëqXEWsF ø=Ø;•»º£fipz®¤µºÜÏÏK‰ ¤íĐ#̃çp ”Eaµầ8&5 ®cXÀ(D́ḿpSªÎöJ ÿ/¾×gûöï·‰é¬Î}kÏ_éQê¢MÂIXĐ4đr»¯¶®̃*kíNWÙµµÓEÙ·ÈF<³Åˆa[e¾ˆL@đÀ}€?eSÿJÉ€7pS<)†Q/ßt‘P7¤BÈPf«¶,¸¢˜cb!₫ó×1Oí·Œhà\l¬~ûܨ{ŒfDø¡·á7Á±ÊÅh…°€Ôè́cª@ÇfúqƠRÊVˆÍQà«PA5•ÚRú¤9® {¦†́Àé{øĐIËdô==́—?Q¾ŸÍל e¢n¶-ÊÓ˜®°ææ{ĂOƯo7v–Û·ù6 Œ¾6$*ѹ=´₫YäF©uw[µù-ÚéѬÖb÷̃°€¼ÖQa/=Ø(ƒTøîüïCeđ7§öy¼ÊD¿=ɹ\]Uyê«ßƯÿ™×̃}Ó¿S”0S(µIß`"xø£̣a“£¨|5RüYW#P”¬«é¾øÎÂưêñ¾ÿ"ä¯Û̀æJ&…Ï6èøƯ„8g¿Nơ9@₫´(Jư/éŸZqʇËq'å p‚]A ‘²É̀ŒDÿ‹–›×̃1ẁ»ñ’‚®ø' ́ÅKaM}|tÔ¦&Æí3½:îu°Ûüa)ʰ5nè°ƯRpGå{½́ÙB M¢\rIAZ¤‡ÓUKÓRưC€£̣Yâ!Ɖ>Óvœ$]„言h¼_¶å9*†s¢A¯ êó°Kù¡”zkûa:đỶ[q̀%’l¤mlṽ†¥ñE{í®k¡÷ÂôĆ1¤…N?ä „ŸÇ&ă ÚLÄ ~T0¸₫¥¤qˆ­}æ Ë3Ăs6¬1=~â›Ô)ŒïKYtx|̉²ăC®ŒÉÁFÇ2ƒ™g¶X Ú¬²9©°X!Î] œÎd¬¯¯×jv́r=ÍOÚë+a2×ô‡D£SmaưôëT H†̉/XuGîŸÇ|$‹îœ0̣WªåïIÈ¿[öéf«Û·5Ûm5  m;fLJ•Ô«–O¶X$~¡4 †ÇÁWtÑ­§(ëi¶/²¯ß>3›ºkKEîÎMoS–œ́â§8„r½¸+ÎLÏ ¦daÈE~d @Ạ̈(;eÊ$u¸—G Úç¢/a|°OD¼¯›S»fe(Øåt”ƒLÍ Á¨­p`ntFˆ#?Hæt„Z[ŸíïsE¶êÚ.!¯RÛ½}‹•UƠÚÏ̃*ñ¼ÊA#D<¢Æ §àÛ"T€ç® §4Øl p‘­×!®… €ß‹Kađ-·¨s†0겄EŸö—1F¹é \ǽY.ùg$9‚Y˜1©¾0è̉̃½€€_xơ₫ÉOëöDúÓ&sÍHQØĂq¡ÎBb‰*é!^—LăM—‰e냱a‚”¨¬¤̀÷ÁQCj"•ûÊ‘q'đº…¨»zúlrJÖúDđÍê"ô'àđưQ»œÛgkÅgj̀U ëÇJÿÉ#öècûmvvVG,O»̉$8-H*´ 9×ăœ>[:R†ás„{ ~ôºx§~=Ny¨­¬¾A₫è/̀ª̀́Ø y‚đŒ >å&I Q_h?Ä"âÿ ¶‘XryäÏPG2!.œ'ơr1!7!Ÿ‡i, ’7‰ÀÂvÀñaî¦cŸ¶®×À¿üî;îühçÖLJ{O÷'E‘µĐ«‰~aºâû:"°&ùRº8, Ơ" ók6lRNùE)‚È\́¨™e¼ uYC[?2—RĂ…ÓÂųÅĐŔ®OH¼t)p–¤üˆ.ëÈN#=<ơ`'ÀÁ'œ·₫Ü¥Đ-@q wí„â§$ ™”¦ülz°b(îRBYiV$\`™|Ø•Ü9Đ`[í'ö6ÛM̉Ø‘ØCÈ‹í“sâhÿ—hX|«B„톸q(¬Ú„eù‹ó‡[^¾-/ ¤eää¿đĐåc#4÷:éº^À=Ë»z9o”í­KiLÏZ§€ơºaQœ0[)Œ¹Đ…©‘_ˆô!àØA‡‡ˆÂ5 Ûn¬“íÿ °§g0F%dʦºùmYiÈ/Hß"eÉ…EN©€đ! ‰Y&ëÄ‘¾Ú备æË}ƠácÅ~¾wøö€Ê ßÉI{´gÆD„@üÅÄ>y°MÀ]9åÚa$ L¶wÇ U ̣ùNº˜÷”wÄQ6.~³÷c›K… ÿ®1ƠC Ú?“]H ÒØm·ß₫²—½ê'¾ơ·₫³iÅÄêb•¤Æ₫ạ́×A1±*â‹nŒ@‘X'}±ƯùîɯÏ..î̀MÍ.¥×W*ă%âĐt́K\:€÷\8Ê¡<4ód—wƒöR!p@(1‚n ö¸$˜rˆ;̉ yä:bvÏ€fˆP01…¥Kt ï%²ï[%ÁP‹›©‡WR:ï€otúû‡́Ø“pˆ̉Ûß~¥ëüö«vÈL,Vë@ú)×vŸ‘ä¶¥EpXày•#o[Ä)Â<Ÿ‘́ ÚëMW@€̉IX’ây”éNuæ¤ßg»Âسc.å+”¢5@Å₫¡=s3¾áØăÖ&ˆ€¬_ºDMS¡“Vœ~…µ́äWUøI”#áÖIü?8%=9;đè÷lvrÈ9à­tD@̣óấÙ“ç:f'„ÍeLK²Úщ­-…{kü₫¬iñ„ÿNPª~¿ËÁë ?Uêœ'i£# Ä¢ÿt3Ū{y8˜ˆ³‘?ÙÏXâ²ï¶Hë„^´đ0̶Ǡt,"÷¯Ñטæt:`Önk®²Ÿ¸ïu÷|íóŸ>9:Ø?H®¤DªK«đæÄfáƯ:"°N&úb»ù{ŸøV¹̀’JÉ9e§Çf8ƽ ¬@E€}Ń÷ÏHÙé¹t d€÷˜ à°—Ü =_Îît#à ¢\€4@ˆăAËïúÜÉ9€wŸ 4!°D̉áçRÙ. Óu' ”‰ílß§]: ©(‘™§ )µ_ß±}·mxóÍ*Dg₫¥( B—2ÜÔ ä¸N鄌ÏḤ°¹QVóT9[S8ü̉9µî²]±è…ṛß«”x¡¸U’_8ˆ1N¨ÊĐ€.,fm«:ẮŸĐ&%Ơ»hj·Qă5Æ‹{ÿê!ÙO˜¶#O’̣Đv»^CèNÁ˾߼è¢|ˆ@Í}².‚ï˜̃× €;ù₫¶ü“Ă¡CL.? Ỳ1OHªqz`ÜîÜƯ*‰¬=%:ªeÀ Ñ?Êœ~â!‰c-³áü ƯÙ_!†¦ïï´Uù"@,º7œÿ?®)Ưä5)EƠ&ËÛ/¾Ïæî½÷•w}躿₫~™S8’Ä¢ñ ¿#Ăb3ÈWtk|ÀŸà‹í^·Î&œk÷́úŸ×o¬»SH/§=Á°®àz!øœé†KC!đ¹–Đ^ªÊh`¾2ç7°M‰È˜¢¤NL¤ø>/€:rxä;Û…v, đŸïĐ<¬ư±a´è( tAD‚zIâ‡méˆÆ=J_§°.¥û‡‡$ºni³ 5|ăÍíÖR_#C2åÚ.÷±ê•A.?¢).r”¬I¶ ~XnælÑÄ>ÿ0êG9Ntœ_œÓ¢ă£̀*§<8îÈI’a¬Љ‡y™Q~blÂ>ñĐIëí:m‹ÙIi꣸>[,èvcH‰h_HÙ9tŽ,ư a‚ÀUëYHß×½ /áwy)Møe͸D‰5¦÷…ÙŒÍN ÉTp»‡aMĂB“‹~úeÍľº $•("Â<<ñiEt´#ÆÅ0_ä§r9Ö†ˆXs(£"ñë—N:Ÿ/‡®«Î¦îº¢̉~î×ëơëÁ®ùyT$óŸäñ) ç&àâ;~Ñ­ñ(k|‚/¶{ ÿO<Ú}å–¦ªk00̉=u€ BO E` œ76ÚÙ‹¬J놳‚À  c@· 9wÅñ@¤åă2Ø"hG[Îr¡™ ¡ƒˆMz´=¤_ÎˈÈ0|³­¡~ê§D ôÛ €:º̣—uAÀ­xÜơ><Øoé‘A{ÿécVU×dMè TÛÍ:¦µµ£ÅḈÈ0' tOêÊpjë¹( 4ơ’Ă `Zöîm…Fá.¹ ç4 |™…´ÎáÙŒă}ëÈ=Ư;nSĂ=636¤º’£yÎѳ͔ˆôưįǹû€ü ¹ü<Ç®2â|̣’wœºf>¬‰ØÁ€̣ù áüÆ”‘¹¤'¶8kÍNÀÉ(7”ÅyDÿ˜œF…íëÄ‹Kü¤<̉Çr‰°Đ®àC8°8è#%ÀWéo IÔ]GÔˆî$s4ĐW âúë3cÙÜ^ó²kÿø†Ûv|ô;G”¤Ï^Z|"À7ïHhBl†^‹n=Œ@‘X³|‘}Ô^÷kZkË_$ –“ˆQGđ@ûî(p!2z" g8ZÎ<+ê9uÔaŸZƠƒ´KnuOúlp˜ÔµüIO;}Ÿß‘lQ€i„0̉âBÈ>" uܯú©l¤¢<à¢|!}Déơ-¨̣Ñ(‘2!m¤pùKc243=f#}%¶ï™*»ï®,³¥Å>đWkƒ}Ư®‘lük¯Zȃ–æ9Vª½DLjĐ5$ñ—öĐî&éèƒ>("ŒX|Ñdx\RI~*BƒÆ¹øÖM;́•÷ÜmưCöè¾'l\̉œ̀ïÎK[í½æ9ÓcoÎ>*vF.Ÿ±‰z̀IáöOèBœÇØ¡0¦abXôÉ¿â`đ| G3:­‡;Ñ3lÂó~o[~„SÈßo+A'¼Ï‹·¢ö"ˆØuµ‘f6bx₫(¯[£Ôß :8m:aÀ‰“a Ê¥áăÂÙ 3œs)ÀK´%ñÛï}ÿ¿ø™{n₫}¥¬Ñ‘¿z' ú‚bđW6¥°xEƯZ"°ÖfôYôG–Åæ@²âfR $ß̉0!‚†¤|̀ơN UË ˆàœ¢Ï¢ …Ytưx́#o¨-w€ˆ9T ’ïÏ'ȶL }KBº8ø%eszư.—¿2½í!]Œ§«då‰Ư^”Âà’S HhˆyR₫Å•H»q›`Năˆ‰Ür)LB ”ÈЬ̃}Y{ú‰‡-Û{Tzá¸D@…5oX̉èØ¤ḲCh3müøcá›"™ÅΖ ²yu„ăBü\o A$sº›·n³û_y·ÙOZ×)'ªf¥‘Ó-{hí ùƒđEµ ±Ÿï3úfm14Áï¡Éa¬–ç3ùÎ÷geߘ»è›w_?|ù {´ÜGÿCRt@Æ´m’ë)Ù ›‚É!)ä‘?è)”6'åRc¨·³á¡ƠI8Q>Âb„ßhưs-°§ºæ–C–ĐwX“”@́uœɽî¥7mºư¯½ơ¡¯|æƒø ŸH ùGBÀ‹×wÑ­ƒ(ë`’/¶‹́±ƒÀàƯMVqiælX@”kt"`RïçI¾J À@Ë0[Ñđ ÇÓB.Ü?_®ưäp{öA¥-¿êUÜ 1"j]F₫•|‡–Ó¯³ÓDXH¸Ể'Iä&i €đ€cƒă]”ª? ľ -’…Eư™év<öÀ¥₫§û d¾xrZœ¯f`e6o§J¿\ĐmT#ơĐjGj¼œÇÅ>Ÿ'ú‚UŸê IA tQ×OJgW/e¹ ¦ÀÀ QÑÿyÍ—+óܘ3Dư†0ÁĂ²<6a ¾½ÔĐQ~ c–»ŸÄă5>´  Á ˆ_æ„e§¡\}Àç¦Æ*ăº{åÔ«6Ô¸.ClưSÇơëcÎ[D₫TE[BÍĬîô¼ä›p5–q 6Ø®ƒT O¤7º H—GUêxbU…mÎKpf̉vnÙ¨¹”'ëv1>ig(ˆ¨ŒE╆6-·Å³å–Û›%y}ï_m¡H¤_l‘Ơ=Ó ú%öưå;q¤wG₫1;"¹éưƯ°±–×ܯưöÜ÷À'?̣°̃«ôDä €¸p>)MÍÔkÑ­µ(kmF/¯?₫‡₫Èá®ÏƯ¾½é§jÊËî.MÍk×ctÀåO'@hL I{Ă2Ù”açC6±¤è@å8˧L ¬pô°YWưî¼²Úz¤dW’ G̣´Ëç@ú́'s¤«oR*!Q1à\â,ă©Ê¾r¢€nR%ºÀ»pJ€ÄÓØNXȤ‘˜Hà¾FJuI/`Qo¢¤ds€oÉ`ƠÆYYœƠ8&Œççç”&́yø©s5R‹. ²øµŸ4"ß–ø²J̉ç4HơÀE£Á"ưôbZ¢₫p ƒ?ÜÙ€”Ä•üÔoö₫ ÷øă 8¡×aƯÅßå‘Ñóă’Rÿi_̃¶€đ£¤në’ ~Ú…ä"-±Î_·VéG]u•®;®v›ÑMhK)U¨=†ªå±Î$(´p9·VÈrÇ´—uZ'‡!%LQ{Ơd¦d–C0JÈ×" …N˜x÷ß²ñO•¤‘dz@üLF…fPAQ  AX¯®H¬×™_Ñï– ©wÿô NüøSß®©(»[—ª¤æuü ¨çöù¤Ëª Zi½¶2Úá^®£ •z°zV¯½V¶Ø ÀÑMÚw½uk¥nï°o·Ă½“Ö}̣W–E½9,ĂùYq#ZXJLÀJ2ŒºÀe 'Ä€ª“º©¾ùÓÂBŸCÛBĂ § ùi?›ÿøŒ’€è‡=nβ#₫:KB„ëư§Œ³\¨ô¬ ³&ấ˜ä‹Q” M]5E <…ú›ÇT1è<…†`!T J‘¾<å뙲ßúb¯ƯƯÖ*ÔSk Ù Ÿ‹°íQ¸ÿĐM½SW̉pÊMZ"¿0&¤ sCêĐÑBDOÊ¢¨æc̃—¶¡;âD ÄÖ  ß¶Đ;¦ Ó:ºYScíMƠÖºy—]½wíi«°=­•>OÔƒT ;ZZù6†VжsĂh}ŒÇựqbÜ4Ñèq›Ê}Í?Ù;½Œü=ŸFB‹+̀[RˆÊØ»¡ZvJSướ· ©€äÏ=ÅC§Ö<#€I°ÿÇ )ÀJ·2„₫åüiˆ'L”5‰èÅ=Ù;å§lx÷¸k„₫̃é3¤ú Ơiö ,ơ¯^vưçåƒ́ẠñGâ JØ  B¶hFlJôTtkqÀZœƠKëäîêË>ơ{ÿ²ëW̃<¹{W3Î9™µMq¹MHt6€&oV,>çôg$©^¬‹Ķ3§ d‰Đî˜ßÀ¬«ùÅ02œDû9;<0%«h ›”mkªp1î/‰Đḿºÿ=c="JFûº́ÛO¸²Ư¤äå$ø„ÛÖW<ƒp)4ơá¨ü¢˜1£DV)'¯ TtØêaqË °¯«À}Ü®̀%nrÿ ÿe§}¼á{ù±ƠÇ-Qa=¼/£Ê•1—đMç’Ù-̀ÅL_Đ­͆Q q‡[®Ø§Ư:Ÿ®́æưFÄỤÇúbƯù…IûÂJöÿ¬kḉ½B磄¿%€«G94rùiƯïPâßóW×[ZÜ₫ö-›́ú­MÖ²q«µ6·ˆ°¬v6xP6ư±ûflÖëÊh {Zvn²x“öç!V9¢—Ó3¨«£9ë×Đ®8Â+»́ư£JË;k4\€„É_¬#NÉđ…HOOÁû™¥ó+§ơwI¤¾ •w£Ú$…ÅÔúÓ¿¨¨¨¨ÖEILHäø#̣g >HPŒÜôiÊÊ&+¨èÖ̉ €µ4›Ï²/ăc^¾‡ßûc»ïøˆ[3vƯ „-Åä=ïyzÁ ‘Zp‘h…>{ñ?ÈE¤æˆ_Ü>gư9‚ñ€¥A” Q,Dlpîw ¨B¬[V.BCMĂ(ÑÓ2=3Væå`¬e[CƠï¾Æ®Ü1­|‹vª[÷Ÿ·±i›–!¡%ö̃)_×É*̃Ï ‹ Xp%B…ë=ˆíI^¦}8Ô.à|„ơù>ÓàÄEΫ‰)Ư>èM@+eñ/º8.ñŸ2Vs«¥]-Ư +¬ÿ¥ñ«å ¡­aLàGơO‹óºï û°¥o¾ÂJµ››r$Ë*ôƯéƯNúÎıdüX7nµ‘ư{!L×Üwäg‡/@>ûù Œ4áJ+kmóÚÛ¯¶WܼCDn™íڶɶԗ¹²é´”Ÿ–)â­¿I=*’/«R Ă7+üôhÖ*µn›«¤#“Ơ­‚’D@t€± †‰×®‡>%¾̃Bù#’ƒ£¯÷OĂ(₫) ÎEÿDø; T^ˆœMºAsƒ‘1ơ¾ßyû!9ûü p§m˜¾Å{É”€¾̣µ ¦%̃½uën»ă¹`«}!k}¸ËF1G{ú¨U‰;“xDï×Ç¢7 B€3×KN$ưa«¯Q*€Wÿåü‡yŸéŸú$¦SœÙ›Ëí cư–B¼ó¼JÄ]lº‹(êY'‰Ä>]ÇyĂ¢m¡¹‘n+©ºÁJË«´á¬@% CÄxéD–ÂPưÑ3 Hü[é"—Hßß%̃"}´÷]‘Oq¤/‚N×·[m]­½́Öḱ;ü4GI7ê*æ^IúÇg¬olÉÍ3—¡Ü…Q¡m mø₫»jÈŸrypœ<˜\t5åó¾-ÀUÈZNÖ+SÇ,c¶è%Œº2z>÷Y;iƯa=m¡f!Öl¯́ ̀êù±$·2qºb!œÇ ÚúÏ©ºtµn¨²ÄüÀx€B" ÿ#̣' D Œ^‹n-@‘X˳{}›”é¡´çu/úqåeÁ̃?°ËÁUÔy8€ûŸˆ?+tˆÙI@/ °S(FT¬°k ñ#îç‚ÄÄ‘¶#ïï“Â÷ÂtƒŸÔ¸w (B  €\@Ôñt¦Ó"‚AḥƠ"P¸¡®AÜßÛîmp@?•ÙeüơÓ6—͘îP§V\)BH’áAâĂÅC@([j¾A =wøñ½gµ ÀÏ/Û¸Ư]’Ü…Ü9eE¤qL+ÓŸ'Ù%Gw¾Lç­“ Oæ:Ÿ—q=?VªáÈPa ÷"| ——ôÓëÖ{@ºQ¤Ï7b}8{…I”ï·6Jj§_®Ç²øä*Ûíú›o‡^f¿øâí IYs]•Ÿ§“(¿glƘÖüb3"H˜1!½¡FJ¡]qXc¸Ø¶đEgéˆLckÁs²Ư.‡Úªµ†” [¤Äˆ•!sààợ‡›çb­bÿ ]£,̣Óײ'gŒ”ÆEÿI[÷M05n£.˜Ú¢; zµ[ñoúÍG{ºOCe‚Đñ ùèó^øÄ4̃eÅE_-§sËÂz/º56E`Mè³è́<€ß|ưö̉îñÿ|Cg]nTwƒ¾Ü‚A. i₫¼J8ÈjÊun#BrÄăˆpVIÛT-+ẩpˆú1m‚UpÀ9GüäS-‚˜B·NđD,)U„₫ç }P>À‘«\s‡(•̣uƒ .f¤u?89ëúnÆXÜÖÎÖ:{÷ë¯ö4Oơ]e_<4b'³̀ô„ʇ@c‚†«g9b”ç]o (RG "‘C»AXBNŒ¦*/!\QyçÈ‘%a(ˆ‹‰(ÿBÎó^(ÁeÄ]NôÅÛÏ\¨NoƯ’Á£©SmKÛưÖÖTcư£BâêSNëÀëaƠE†€<<Œ]¼‚åA¬¯êà’4e+̀¾ZÆS{ë̃‡0xôˆp?rG[“ûÔˆC§V<§` ¨‰Æx¶é^N°€ØQDÅ‘^U:̣ç›®UzÖ%×úBP0(® ßljDrô!rÿX§DÚƠ ›DÑ”¾—.đD$¼_ùTøè³èỌ̈ €µ<»Ï®oåŸøôßvă¯ưôŸ ‘Œ5>~BÇ0=ˆgẀÁÚ]8|¸oéœ\ưÚX•vàFôĐêǴ~¶V%唯Ú,9! ȉ "§má©ǽ:Gø%[<.& FSÔfá{ú" @́(WË(ÍÉáŒ5è8\ÛƠu₫Ø=Ûh†ưIºû‡-3Üíà=+j€sûAyP\ŸÊrÓµÉV-À16(¡•AùvE2XP©o>|×—wsÅ *ù…q@VÔøÜ» ×K}ç¶•öÀÙ;±¦xÔ0„ô¤öêơís¥„·˜>•-Ä+¡ḱƒøÎ>p÷X·/i‚éÑœƠuî°›oºY×ñ¦í̃½-ùA8¢ưs$5]Ú§gÊ@öª.;"|¶µè‚¼/ø¬-iKˆơxd‰0,ñQËŸt̃|$^̃$H!9R­}]ó~™DÀNÁ¢ŸôO¼ËúaAè?R:ưƯ@$ôë¡L/F/ùs₫*©—£t"U7D̀&q₫:‘ Kưß¿ú‹'÷?ô˜^Ôh{øñÑó~ôU’;üø$AEo-@‘X˳û,ú&3®é÷¼ơÍŸøƯ_yÓŸè6¾œÄ¦ À95₫ăÈi À'bdkÁà }c$ˆ+`Ù+uį³úÓzy.# R¶rüB¤üÂw}ºSF' øÀ`L !J̣Ø* ű«€ÁḮ“B@âd)'ÍtµÉ€¹2ëvû¯°f?ơ7l«Ro•B×Mö́²¹éqë>Óe“RŒœÍ ±`pHˆ?HØOäÖ@vJu¦¼u£}åXƾúÔסS‹.ºçå5j£wº°Âÿ0‘¾  üÇ̣Ëùêf}ûCc׉»çÁ9Ç-$®¡’g¼î_qŒb}8}ïKwÄPY]íFyZ6h¿ÎvïÙk¿t§>4nj#HQûÓBüè¬ĐfêCârç¡}̀°2<ü¼'KØ?ÂZ‰âé©Â<>̣N/<½°n¹’w¥c‹‹‡cƒmÚßƠZí̉/n„Äp®CZÿº:-%Uç₫YUøè“„Q—{>Êz ÛWêFB‚Næ:3H ø“"W’CoáƯ[«wâyø^ù((ï óç‹/kgÀÚ™ËgÛ@ Î}©Á/ÿî3=/¹ª}#\½ H b{G)Èß¡ ĐOY9«Ï~7Ñ8DŸˆùe„0ʼn ë¿TcS@¬iB¨#´"¡̉d•!KỒCk€Äy d.ñ6)qB @+x+ơ 'Ç{Ø*BĐÆ2.gÅ}W˨ î­/̃¤vo¶'ûvêBŸŒö¶Sƒ:ª% ÷™YíË:'ë̉¯éưT=(©©OnS^¢Ú¬8XÆÏÇ)Íb‰Æơz̃ Qà–ûZøCz]­₫•U¶ß÷è%¦Ç¢y©Åy—3k«¬MvFÇ•*E€‘׉ˆÎè+ºªÊM ·´4Ù uÖ²ù Û¶e«Ư¶¥Úڴĺâ˜̃ñá¬K›"̉GiR®+ r$̀ëÊđpgµ9 ¡GƯ'R=Ị̈rôEăa¬Ö£<§xI\̣I'̉hIHÚ4ëG ·h¿S»Z«ür¡9QCHÈúuŒ°_[T8¶·àü ÷ư)âÊ óvm—= 9jL}ôCèÿÎW>Û§÷@ms¶#Ưù”¤ÁE?|×Ü €57¥ÏªC+CéG>ôÁߺéƯïú¤ă3‹‚¥$Ú•Ç₫c@₫‚‚ràfÎëX$ÆÜ gmqü˜Nó­IÄ÷iáf=úï>-'/Ü\Ó®ùï)€F¡́Đ€¯'¤5¡åwb€ôJÏ逽Ưª ̃Đ5§‘dWGJbÀU ”•ưeú1°ï̀EÉ0Q™Ï‚‹Û*ƒ1ơ7̃d‡ûgıÍÚèø¸  Ù“=ÁVü¬”¯½‘a´`9ëj«-73néܼUVVÈ@Σ«pÆ9t[ød"ß G¿—]™åƠ[¾…͉•GĪñs«{êFv°¨‡V~nzÄ6HÜÛfYn vÂi ­!å¥́’²rkiï´êªj»iÏV«­̉¥;Wî²[7VÛK3ÚV”đ¾®iĩë¨'¦yísœµÖ“VK‚o1>νÂwBôß»¶‡ˆ ù´₫Éé<2d`[ÇÇĂxñá[ Y;ZẒCÙHÆôß—Ú¢×µÛ®€-\?ÈFúă9U³ªĐ»::”s{Û%­"ä™Sgæ?ơ¹ÿoRï¬́Ø*oF̣ßñăCºÎ{̀§×¢[#P$ÖĂ,ÿà>̣‡Ÿ@OAîcïÿÏû̃ü/æñ{nØyÇê0–˜È.VŸBăÛ>iAß}½ăf'&¬¡±Eû³v­öױ矲;9¢»àå#z{³́ù†¼À>çڨĩ ¸/O~4Ơ đ€=´Ü‰đ¢¡­ùt p ?”«¸§K}JĐv*_¦x}äÀ€ôĐ´84))6×”º8·¥¶ÆÚö4ªïÛ1-éŒû×ö¹u¸‰á>/«De´4ÖY.3(‹,2ÊV[爌›ææÑ)($hûóÀ1N+]gæÂ&ÜÚÈ…@̉ÿY]Ä@½ˆ!5‹f©ªQ’–2»öÊvÛÎknk·*‰û¯n«´i ¡tA•íï´Q…˜d. Ë¥WR)à¨×‘#¾ Dµ…o Ÿz Ơ™v!tˆAo7È_i<Ÿ₫)À=Ч"#D?́׋˜–¸QVé¼ÿŒ4øÓ¾M@:—X¨QÔ‡Kª÷w¾øs@>wC{¸đG¯©|́Pöñï~}@Qh"TS°? øøHƠăđăă¢óáƯ"°Æ'ø2º@dqvvqñËÿï_₫Ñ+nüƯc dXÊ{pÍ b¸i#ÎæÛ̃´—‰˜¿«§ßNö ±8àël®µê¦V»k{ƒƯº¥̃¹k´¥ÏÈ̉[ ]ñsׂ~Âô°çâXµ XÔ¡ŸêbB Â*¥O¤ 2ÀPµN­ æ¿Cˆ'I‡zˆq¥5¥ÙĐ7¶ ÊP ä§ ¶5$qß+}¡m¬/€o·+;[\O`&³Ă<2"$6'B€#Œº:¹º̉ÊờΗڜDă‹̉#đ£…"b;hÑ?wf>ûrkA£́ç§u"Ä·DÔTb„â°Ôªu+â»÷ă/³ûoÛ¦ơRb›ÛeJZbrĂÏ£§çt.Ÿ:rNT‚ô‘.¸äÈçïdI,O--đºđâ;Sï¤Ï‡7¶&¯̀#}̉YiÈúê/¬ v‘Ïzào!"}t[áúC:$"åALnS@ePöóÉå‘ba£“Áy¢Å?sêqßÏÁ·^¹ƯS₫Ô=·Ùk^r“UiB¡Fˆ́΅ë?vzLă¡#–Iya{DÆœdñQ(ß‘>œ1ëÇÔ准(÷YÓwá~>¹j̃}.“6{º$4…ư‹óN'zñ5ùA‘TïK¶‹8m@q$̃g-íÙPe•" ÑđŸµưíís¼ æÜó¢ p¶y™ïk₫ù́ñcư²(ă>€`„đ] \ç·Ë%­§³yçnk'ó¯_Đ©ª”LĐ–tÜ€F=ăạ́0G¸¨$à¾̉“r Ơ¡;D)XiB2yÄî ¼)>ôóà.”Óz ²“$âNrÁđŽ_âơ_ßæVƯ@{‚¦¶§qf¹Đ5ûÆ%KÑ1gñ$€u“•¼iI~° z À˜g×!H¦ „Çäbß—ŸS̃™TưgJư&’=…d>™Wæ\¬yÖ„/×ơru/Úøñ‚ eu÷oŸ±}ûöYv¸_‹Ø”@jÄƯŒ‡́H T©ë†_xËMöoî¹Á¾̣Ô Íh ÛVgKz¨$ÖyXz9IJí–Ͳ̉©¼Ù™™%m™B¬Êö²MèÁÖ÷ḥpToíƠÄĂ´̉sqy™<Ê‹^‹n­@Q°ÖfộûĂz!œ‡9gpêéƒĂß|đ«Ÿ½ùúk^S-€Ä?ö9IîĐA?‚WÖ Mæƒ̉?9Ä fºO€9xlí{z€ zY©ö₫•aRÚÚcOĐ¾°tµ¦Möª=Í2×Ú î©Z_ÿ¾ñ°Fˆơ rW} Ốä%RµÇ¡»5­§;J'ë¨ P—Ác—ô8œYO"¥è—oÓ’PŸxÉ6œ ÷Ÿo½b (ưÁ¸9¢P̀¸ô:t"}‡}]S:&,Ï äÓPT¨AÖˆcy4hËȺƃ±9î̉ZßDÖ„2—º¸†Ỵ¹Äg{ dç¡ đ0~üM¿ g cæQ̀ơr0‰“ùöW_ÔƠ&̉£]ïsà/I:Ê‘Ă [= ²'Yô0o(ºrÚ€²vêhĂnióû ơóĂRƠßÀÁCOÙH÷1̉BỴ̈wO„£¢äæ¸#'CЇỵđ1{âê]¶[ë~ϤêR:ư­¸tË;I»rº„¨TÜ­#Úú÷öæê•QV Cóå³Đ£¸¤^ø€èW"ûX>åDWøĂ₫"°F&̣Yvƒ?̣̀ø! ˆ,}́o₫êà}÷¾̣ wƯzư«9Ï‹ … IDAT6¿'Pé¨!ØdƯ2±:"e¹́¬lú»Ö¶$pH 2†X`fg½¥).¢"3;gccöÁ#f®m²Æ¦&ûÛ.IAÚ®j¯Ñ)‚R?«•4¶¦uăK¤ñ¥́Àv>œL!^ c»ç"~Çâ.‹=&Q’tÎo%ñ‘€Đpr”Ez2á”Úơ 9 ' @t§;û¿:âÅQµĐÚ¤¶ªÀ¤9^}Èư<úơỮ^†cPι&ăØ/Ÿ}ëMơR…\”©[c¢5â₫ḳê…‡½*Đâ@æơÄ”OØüÈÉé€2Èy“…Ăê ßÉ´¯>Ñ%aÉ‚ØqlIq±P›îÀú ₫2Ú́Ÿ̉1Đ#]Ăö¡o³S§NÚầ„Û‹@ÉÀ¼æ{p₫‹ ‹R.ßéI°LǧíÄđ”ưø«èŸR^Éóé—OyÏ•cw•-ơæ»®zD©€ă44>t)J"âásó_|',n 8±¯ọÆrđ‹n @‘XĂ“{]‹đø‚zy²gb¨÷‰̉Ôơ¯2ÎÉ€I=P*@­Qªtëøén›”èÑ­æá{ë¾ĐóH¬+Wª3đˆö‡¢ V¦­2]Ư;;9bïøÈ1)¶Ù¶Ö{Óme:¶Üu®AĐ£­öŒ±;0©O!T•M®{åÀ ¾èá>—‰  ½y P°ûwB€„I¹!G‡Ó °†€PÀÖÈ+§¤ß€q$êZTº2•‹ÄY.H€sœúÆ? ¿é˜t=6kL¸moJBtÄ:Ÿ§FAé'Ó{Ơü(m₫đBƯdöØ€ôưËgÚƒË)¤EZÂz„ôâû<(º!+íÍoo©÷²¾IƯ8=mØßíïµO±™‘>—HA8°&ư₫ù¾(ybA2Ø<@’Ú„Ô)­…€d §drÜú»u'ÅîÿÛ`› ´QéƠỴa&˜m¬V̉ăÿú—Ÿ)<öGr₫fØèGD_Hđ^ˆücz¯Rq¡‘˾‚n-@‘X‹³ú́ûà)(%ß9xºÿæNOw4U׌éXV—€zír>û öî]ä)À‡’›s?H”.p>->)ôI à†(Ôưm ̀‹0K®pỢĂvxtĐ~çØ)«kltC27o©³-mÖ*ÑúM›ëƯ˜ ˆm{®/ÆÄpØ*¢1àʃªn”̣đ- ¯zè¶aĐiƤûÁAD‚`9>¡SŸ]¸ÏM¨P ÙƠ8I* ®%ú°©xOó¼₫ñάèA2&ÈƠÅ8DC:E¢k¦¥+RaGúĂ)|daé¦1óüI!TçUêÇÅùubCéïñ׆ÆñÎlº¯ÅˆÏÚÍÂåCb²®¼I§: ÖÚt½nƒëèÍØCO±ƒăvèô°ơ ØhÖÿ¼¯k¼_•pù®̀¨¶ÄºW]Ñà‘¾¼]´•ơ™Ă>µ\Y™$jºŒê{Ù×í¶m-•vXG$a}°†SÚb£]G1–zÇÏ¿î)/ ü¨T/n‚ü#g‘=œ|LJ0ˆiHÏăC$?:Fœr‹n@‘X£{Ưâ=₫Áó0ˆBú=oÿơ¯¿êå/ùngó•/@>/IaÊ–½z®0=Ö7¦Kt¦%ö”F4\‚ K TT…ơ;2¢Q# Đ“¦,1À»Û‚—t ¬LâÓÁ~›)±'e7b ®RöơÖÚÑaí̉¼¾YÇ ±50%"`%3ù|syŒàº#`À'Û‰~̃óÇ ƠF¶œÛtOṇ̃iëJ©€sîįtǹ·Ö”»èŸ1€(ˆVAR^®g 5¬,ăùôf5üÆv'(;|&]d̀1=,åÎÚ@j„笴±!óB祇e£A+—’¸Q'gŒ­߬½€ÁÀ˜¤̉²tÄ ̉ŸƠúÄê`«Ö.yê¤\‡«\ëùàĐœ}ñÑg\cÿû'FÜĐÓ¼4÷gdÑRÈ9¡é\~²Ï¿¨ờVW!·ï?mP”Åíº*Ë󮘶‘¡è³—ßz•“Ic̉³RÈV-Bd·¸ÿr)₫éaêïüí^±,™;Ơ+O†9{DøQ́R` ‡Xû§Ê¤µz+º5;E`ÍNí³êXø‘;?;öwŸÿʮٱé憪̣æŒ2 ¸ưoX"Ư¯pN ÆÑ?̀â‚ôøâ'@lÀmm*p@"óEAÇ’!Äô"1|«ƒA~¶\CCóĂĂ6®[åNvXmmŸÛQ¿jË«lh²û®iq€Ç€L×è¬_₫31—'¤ ¢³·ḲÇ ƠG=gŸ? jưz ÀØ1‰¾Qø̃íôH0Ú o]²s`)P_¯ÔP÷÷³ó>_¿̣ZÑ…d,“¨`YV"§æmCM…Å™Đ6óÄü¯tÉp9=Åû>#i¤Ïa‰ḮI´¨x‰̣ µï·N*1ë®IÇUoB"y­ën({à脸ûAë;}ÔNè}x̀²)äÁÙ«ï»h?ọ5¬uˆ¾`ñ/YçJïmQ]+×=íơ₫¨Ï¥_„„ÊMÏfíam-Üy#Û%~±m§·\ÈoÑl—ñ¿/ü?ÿ»_È?.@|₫”@葳_)₫/D₫1M̀ËPE·^F H¬—™¾¸~̣Ç +6•BÀ’~ÿ»~ư‹ÿ×/¿á_t4´7£Ø†è“ËM÷Û±“ƯƯÏG“Y.g Eç(À,ä `‰Zâ€.E™wb@ÆsJ¥3À?R…¥u¤0;?făBº#“V)[ûOÄüÑË\₫¹?¶Ô›ë?¬qöÿÉưˆfR=₫ôIë¾F§%ªí®& ]aq”M̃{î{CË'ÿúC} N¬đïä‘ä₫ ‘Ü(ä₫ÉO9ñÑ«¿ăƯ"°F'ö9èV0,–•¥çÇ…,.Ö".jjN6₫ÅYü±!QÄœd““Ǿ%_0Nđ? â˜Åä‘äÛ£̉Æv‹è½iÑ‹;X)‘!H¼ Î^H}F\Ôät© ŒPjo;|Ø6nߥ«X+íơ×·¹d Ñ}21;²¢D°~ u:¡±R2€Æ‚¯8:V†á="ï›bDÔ ©Ö½ .w!}g#™àÅè{m8zx>—ÄÉ£ï>.º×6€.̣¹Bs‚i\Ư4éR‹¦@ˆ^™ÈÎᔀâđ|-é_ÿÏBúÂÉ~LoNµ\Dâ]–suG@±•_yfܾøí}6Öu\ë…Ó²7¡ủG[±₫ΟwídT‹6ØĐÚ"îBkníè }TÛeđß;i¿qïµn‘r[E°àâºå=]Y-I¥ +Oää£$_ˆü!â7¿ 1m,ƒ̣–;¢¢[Û#P$Ööü^Nïzå€ƯR!ÿ±<øä¬ºùN}ç´o:.+n84 É²Á9’b^â†Qx@øĐ‘gé@©*„Óæw¯«LöĐá̀©cä«Vù‘B±é~…,·ê‰ „âđ¥µ=™)µÑ‰vXTË·o´Úæ ö3·vØÎÖJ»®³Ö¥XVă@€z0L£̣œˆưIT±À>@]âàÓQi$ ‡’<4•û>íhF{¸Jƒ| 8€üú…®ŒB ô¦qdåÈ@Æí=`=bÉ·\ô“C\BäËGƠׄè,¿w"rÜŒ³èB?¡ zm“>s‹ô=”ÙøëGúlXÛFG=¡›'à`ï=ơ9©âJ«Bü¬Å(̃÷ư|5´êñ60ÙúïÄ®·Ó›èqámù×¾Ö+Î×»̉‡{ ÔR'"—Ó̉Ủ<ừQ˼t·́ TÛ3CÓv­ê%#JU¥¹÷₫ñÛô©¿ü³äÖN†‡" rÿ…€ÈưCœûW½Ê»Â÷|`ñem@‘X[óù\ơÆa‘ ð»ĂĐ»9À™ömSb°„H«¤=iC}B€²a^"Å*í_¦âÁxr.G†‚Üw€Yˆ xèˆ/tĐRDF „<đ(Q́áC 8A€¡!½C ¸ +bk@ÚÛĂCöîgIW ƠŹ7_¶]¶ØËl¯€,ßÜ27’™ÓÑBI¤̀!€ ú"ô ¢ ơëE£ĂVCƠª ‚P₫;1<£…”<§̉„"ä%/¾¾~è9³çƒ!EçFú›tZbHź³3hM,̉à3nä 9+B¶m ºêÅ ·J¼Ïv÷UŒh›g|r̉>üP¯=öøâî¥e?̃+>pîœáĂáû£w¾×·¯̣Y»^¯à)_“zW½üàáV®ƠÂuL|á7ï¬#¶¾Âz‚Xe+K̉,Ö«âQ|Ù́ëoO{½¬†UD̃!m•<%{ÛkSÜ;QU]S’Édh C‘9ú !„ø¼ñÉwKaE·F H¬ƒI~–] ¦¬̀墻Újët.K|¶7W:'ơ=™!¯««³¥©¬•iµ|QṿË• €&VªăNXAC”¿$́ Bw¤Î·¿Ó¸ê-Í•Ààë ×‹Ä2cÑ"ZA΢ü>zR€*:APß¶t™×ñẦØư»³Iönn´W_ƯªåºÏ ̉÷\O©.₫áDè çG Ơ„´U$‹₫ÅÉbŸ Oܬ·S`UIÜE?ù\§^Æî@Ç;e\§µ.-#R0§Á±.œÓ׳»ËHB­JÛ, UÖ©|½\ ,n¾»È>}bÔ|́iYá;¥¥¡czÊÏU»́±¤wÎæ»²ªp3DÖ×ïÍåûlD¿r]²ÎăÚ ơqưÆw-E=aüáôơ@Œº"«nDDă?­5TR–¶ú–km®—‰ama¨¬¸̃9Ár|XGƠV/â^xÇ‹ëEđAkAê…ˆ>îùGb€0¸ÿHļÑW”—…_të`XcEWó8Ç1öÅ?₫Ü÷̃øÚ;®ư_ •éz¸\ÚÉGtf±* W â“ëÛÇî’Vµ¬ơI».. H¿°‹eçø;`¦83|ư:Pöw}%…@˜(`®~?ăÈuÁụç…µ@‚´qđÅI:N®¡¹EÇù*́êMÖỔæZë[¥áÏ5µ“Èưºâ-+S)eC85.0:5‰[ íH )¬́Ñ•̉±•n• •I₫i¾ÈáWĂïóT-ă6/ØÖ 1]´ưƯ“>ÏXà딡'éq>Ÿ#pÓÆè²Ñ¾;pzDG@{ƒưéñp_ăßÓO¸₫p6? }åƒü•)é/‹÷Ơ  %®±‚ µ7´Ÿ°ˆèăzcƠÂưËן5V(™̣oƠ&µV«ß°Ùvîܪk¤›́̃[¯´ÚjÛÑèWưzƠ ưc#ë‘D Ç6Ú]W4ä%ªN¥¾¦ 8y"ă¥?\đĂ¥?\øĂĂ;—ñpéiWJb×£¯$E·ÖG (Xë3ǘú0âá/mëhƯœ.+«Nê°u¡đÁñÚ¦æ!×R{ơ5[l׿v¿́Ûnùn¯ÍOOXf|Ø5ösBZ‹ÚX’M\ßÓ-äÊT®K QÄ.đ/ B³Bç" đ*ỉ\ü˜Wå˜8!Ø*€b¿Ơ‚øư4AØ&`OV6Vl~pP:%v́̀€ƠÔu»aŸ][;­¼ºÖ̃tC«Ä°•ÎísŒ‹ön–Ưÿ ²uŒü°pƒÊh́©µÀư³%–ÛèÈRŸØb@÷b³tn‘1'ˆEzôU͟ѽO:dĂCC:Ÿ?nSâèçüøÇóP̃ă8ªÏsQ?~ØËÄd@úà5O._S±%qưœ½vËẒa ˆô+‘>ë ¬O8sN‘$¾úÅ?½‹üI+ʃVÓf×\ƒưêK·[®nkjÔI‹:9k‡ơÙIw_Ù́cĂ‘Æ.Y“áMb­uÏ¥vê>‚½7¿¨ơ©Ç¾Û£¦AÀÙó€Ü Ÿ¨H\ûC•̣ĐK\ôĂWñwÍ@‘XóSü¬:A †»v5/´HÙJGÜüÁ5Ôîfq₫Å?Ó7cOt+[²ÇÚÖö?Ïü²k6ÛÍ;;tcIÎ>öh·=rj†»NXÙ’D³Î*ëR?jé²BVÜ®”àub@­QƠ*Mÿx°&.ó˜Âƒđ*½óÏ )K₫x¡@Ú° ¤GP6€6÷¤Óœ·©ñ2ës[åväpZ¶vØ:Mđ’]Í^ :ÿnå´ÿmx®êÄ¢ä£]{đÑưº.xÖºuÁάôJ&§¦,«ï¨¼çœ¾ọ̈ó7́%Úg]@„ùö_8~ư‹ny„uááD//%Gæ„€B  ÷ñăûú ²×·?H 6ơcû¡´Æ6î¹Á̃ö“7ÚƠ’ƠƠÖjÛ(eóh¿Ík;ăàÑÓ̉™™±†ÖNû¹·‰ ¶Ö=¤ÛÁÔÜ-*ÍävL\mc³™Ô+ˆ½ˆ~Qäÿƒ?ÅƯ:"°Î&ü2»ëS6Ñsצk„ ÅƠpOnF"|ÎƯ¶­ÑNirQ窘Ú9pbÈ?‘³/́;c»66Ù;›́—^¼Ư₫ở (½Î̃₫éĂîKÖśˆßú‡¨3/ ›°w |ß (B78`×;1¼kP„BÔđæ{{ÆP à¬Öbké€K àĐƒá!ˆ´µÓ2G̀•ijÜt˜-Ơ n‡ltוv˦:]\ô€ÍvÀ F»…b[©ë‡çRVѶ LqN‰sÂ₫É„Ơ˜æ %M¤-Œm•¸àû_~—Ûăÿèç´¡~’2Ê£ơ”ÍêZíazWgơáø1AöóY A‘¯p¼ăzˆˆ̃}&‚Êåœ,Á|Eb̉S)pÆÄN\!̉¢}ßÓW_ÓÑQ)Œ¶lµÊÊ {Ă«^l¿|g§¦I{ÿ*çcßï·Ï}o¿j”D`¬_iÊe?"m5ÚîÀqá×§†öévMôp~DR-íUØ̃öj{û{₫tï_°í˜¢øƒä‰„@¡‘ô‰£»<á9¼ë³èÖÓ €ơ4Û—×W‡‹då°H¸¡ºDûàúé˜aÏ}ƒ³¶Ê´ê‘̃yI1*đ/â¤I3#¤¹_ïí·¦újÛ¹¡ÖĂ₫Ëë®r 76³Ç~ÿË'lnr̀¥/r‡Ă[\*uÄ,¯±e `¯̣Î6»*È% €?­ ÈàÉ€Ç(]üq!½’9‡Á ù·…­ •)A &ˆ…x@î‹KÜá®kŒK9 .TåëÄáQI2h»Â xhĂYêú!9]N³£/ÿÜưh–#Oˆ*I\ʤCQ’®²g65Ùë®·±ÉiŸ¶9-qÿs<.êר³.n??ïZ>ÆZ₫Æe®Ưă7qQ¡” 5¢p|⼓’wÖpLăßZ!¾oï„¡V·Ú!9úS&…>úVỬ©₫h;ă¶Øïß·‹"}Ư}ï丽ïˇlpT[ơÓƒR¬‘Ùh•S¡|18ÑĂö†[:ü¾:=ámAgÁẸèYˆÚơ‡ïüµC ¢µ¤ˆOD₫ ü†‹ưZü]—#P$Öå´_R§\*GêŸøâgÿđ­o|Ư†ºº{ÊRó¹YTh9/€ºvsƒNd\! Q¥ç»P¬ö:*¸oR·«é³-í¶Cv^{m»ư××ị̂4ß86nß9©-‚3Ç­gD÷¢ Á²gH—½v¤¼ĂơÆ#bËÜ_8Z¨*åbÓ¦ ÑEB |«¤Ơÿsl ¨~‰E åR호®³Îf³36tâˆÄ!Y]I8UÚ Ëơ₫Èư‚>ÿÈë^µB­!K8iׂ׸ ISRåK¾Y«Ô™Ÿ³L&›H[fE,́‰†yP̃cưÓ̀Äàùkx̀¹¾ñôøˆ¾'?„;̉W¢<·¯÷³¾ÚÍ6‘+ó)½#!úêªJ+¯ª²kn¼Å:7n¶Ÿ{A‡µT¥t|4kÇûÇí¿ơ¸=~訥²ăá¨%ù¤ùZT¹¸½c³ƠÔÔz£8Å0*Ưˆ´ Zá‚¢ַ̣Ü´©†?¹ÔĂ|ưÿ tß“’œ9%ó‡ïø‹i¢B‹¿ëfÀº™êËêÚº’¿ûƯ_<ưs¯}ù7k*_Z‘N•Ή;悌”p#ß&Ù0ºWVƯ"HƠ‚4“w ¡Tê÷Àđ”ơ MØ·Ÿê···Ú+t‡,é½ô-J¹Å₫J{£=CcºpÀöÁʶ¾DÀ ÿsTl úp¤ ǼT¹z—ïç–D\$‰è{ÙK HjëÜZ\zQ u_C›ơô ÚÄ@—8Ù´¶t?‚ÄƠaûBíL¿\‘¿¶eEÔư H ÖÓiq÷"JD<ơØ íiëlªƠ‘>mµˆów#>Œ§Äÿ.UÑ* s¦áѼš%,ï"§Ï<ù6ø6̀ÿJßq13©ï ưBÑ>„ñÔ™̉¯oj¶="₫êÚ·Ú7\¯;Jíö­u²:˜‘=‚û“}}ö­'NZvtÀ*¤PÊÑÙœÎù³‘b¥D Ẳ³•&9€7})Uf÷\½A7%ề£ÜC§&%iđW_CX¢`w6Vp*"ỡ¿ü,Ú₫́ „Î-ûdZ-,RôIWtëxÀ:üKézfj’äeoù÷ÿñCOé¿¶ª&}ëôܬ€ÀUM)%µ H^Ơ^k]2_º -m€m¸€j@]b«04¤}XàèÀ©!ÛrDÜT¹Ưy…Îà7ÖÚ­[jíê[Û•rîè·́ô¤:5`ǦlV.P~×8ÉÈÀ É_B !Ù¾öø °QÑ̃v¸ ˆÅ%!H.Qy":Ú Yª"ؘÿ‡ăcđ²9)Ú¯æ"qo¾7­SÏjn}…XÖjÉu¥§ Ϻ́ÂBBmçë ±¬ G®2Å<•kLùæ4ªëVƯd踱ơo–ômÆŸÈ^A¯ÎAú¬= Kf;Y‹„9"×XóÄΰ;§ïëQ¡yN? } ©…VƠÔa7ïî°m7Øî«öÚ}W7Ûñ±ËjÎzºÇ>öà~Ÿ¶Á¾^KƒÖ¥àW©½|Öú-pđ±A¥j¯ß¨€P·ÙÎMm¶­£Í“Œj[mJ[ ü}Ä<¾ÔÖÍ•2qd©ÿđó¯ƯGö€^ä]á{Á åă‹/Åđ(Å…pÑ#PYU]Úơ¿êë_vdž:q6©\Ffø€@ÚđsÜW‹xüÔ¨”%º‡çH.F3—ÜçQïN(J`6z_˜›³́ç3lƠ²8xÛöz«ª¬²[·Öë~» ̃¼Ưöw[.;e¤ÛÆ&¦lqrÔÍøº¡Ú1°(bÀ% bq[À^·ô†²Ÿ7€oåq‰5#‰Ó6†°¢ôĂÂ;e7µI©K€ưCq £hBfóX™Çô >(˜ÏvS7̀c IDATÔ½̉Ö-ȵ2Á?ÓïƠúBS Çó¬¦k<×°ï­>KÉ2­ă ‡{&íñ>¡¶¨D©y sÄ<1:₫›LHA©‰Bg:êïÁw¤ïa¬6<È_o s±¾üÈå;Qàó©Ó ví̃Ưöjé¬0ß/ÛÛaƯÓ9ûÊ₫Sö₫‡í¡';Gß30âǜ ¦Zß~ĂŸæ?¬Ÿd¾é;kÎëG¹T:jG…Öøu;;mc]ÉdSÂׂºH{!"°@¹©±RÆ·̉©û¾«[Ku%0ûü¬°øđçÈĂw|ß1 ~ÑG@'³®89Ù™ )S_Ûẃ“¿ø̣ëo”IÖÚLV@Y°†ăNØÏo—Y×M56 ó̀²’“”,Ä(Q§tôø~‹|]€Ưñ°ƒ:Lí:ÈsÎêO ¸rƠĂGËÜÆ@mµ4ªoÜ „ßbWoï” ù›´~ë´ÍMY©ƒ\iÚu\d,"Ä â%mY8>b*»T€µß÷”i"ÀÍy…w?j;Đ„”–å6ĐQVûƠ”1à Bby·Vº€V†zí*ÿùŸÏ×zṽ~ø†%Ú¶)‘8Eflz:cS²á_ÖĐ©=—C\øMü$,Sœ«•H?|³6*u/dë·ü°ŸN# ëaâ—Êẻº¬̉¶ïÚm¿₫̣]ÖÜØhÛÅ™kYÛŸ~ó”}íÉÇ­»O[Sƒ#nÄJ¦}½7«„@đº4ÊÖ’w ùáơû}Z›åR.­¡[YYieaï¿g<«“5Úḅe@AËë¡­º,'ÂÔg>öá~!J%2>…ˆ¾đ=Æ/D΂Ăwñw@‘Xg₫t·ê-÷̃ü¿n?3₫k;ëjG3ǗâÏêHà˜¾ï¹ªEÊ€º]OH&¬ûy₫ÿö̃À®£ºó®×ûªîV·¶–䖵ز%/²å ÛC–„ɰ†˜d CÈd™$Âö‘1$„aù‚¼Û²,K–µ·–V«»Ơ‹zß̃üç¾Óª~z’µY’Ư·¤êª[÷̃Zέw₫§Nª ‰³yPbɳúåé1yÀ‡0 6iq ÅPÁöèøØÙÀ<7·v†ê0Ws¥·^·(èLÙp¥ö@3đ¯ë„;wˆ/I¶  mö£ừ6À68sP‘Fx¦1`.–z(L{º0ÀMØ-unÑq¶¼3|`»]Ó–)#5²å!yưæ̣¯§ƯÔoäsêügΕëc·¥đ]ë| .^#u·‡îö=áÂ% Ă/4_>¦ưêœæ&Lè=£K‚Œ‡i¤k’ æƠ?ü{!F&`Ÿùè3̣Gµ®G%¸¡ª— W3O»=ÎïzÍ5á-W­̉yƠªĂ—u Đ't¯Íå÷ ±ÁIvú÷U6ö½½Å.¸đèÿ”eFƒêÏÉ’R¾̣gù_EYYX>·:¼je½#ư´Fÿ"‰V$í÷Ñÿ­²i¨.˼ñ–·moß·—ưưqzÊ!û8Íă„ù4¯z₫½ôúELTxÜç©iÆ@¾sçÏ?rÉ;o₫û†’̉.ÍWÂt«6 Đ  q®8Oó£‡Âöư•ëÔß ¸TœÍfQh#%YÖĂà`?. $—Éá; W‚•Ă ¥ÎRô M†̃á>†đÖ®°D{ ,®¯ ¯»dNĐfEbœ+µáĐ₫đè®̃Đºu“æc¥Đèܟѹêđ˜f€¹Yqo_a`O['„W&e;#W]ÔV–ú}èåKeë ëơ6Yxk"drR‡Ï(/̣³Y›ˆ&­°ï¡w]0ĐK–tÄ=ÏÈG¹{Äăg%ÁÛq´ÂisöA‰dDĐ=5 TƠ{ؽae—Fsưu0'¹y=`¤ơ¬yrÊjß̃K®~@̃@W߯–íú9àÇø®¤á<í§ÿ-k- ôÊeê#]¡î¿ń ÿ|ïºĐ»—̉4¥£¾j+:¨<ß& ̉†Ă°;¹ëi mFûŨû•?£₫²̉Û̃¸RgTUU…Å-ç[FfĂ5h¯<=_=ÊîIóŸm—bàÙí»úG%Ci€4ư¾’¦i©›áH€̃N²ù™Áááa˜bSMi¶c`,S"PƠb.í0¡3̀Ă%Úél¶u•Ywø—u¶“̃ni°Ü—*@—ظz¢¢gT˜¨è±í›#4KMÀùK€Èø`ó®®°i×dx`óJX¡)‚ù: (ñ Ÿ¿wؼ§+t́Ư¥̣¥‰Đ? . tÊê{=‚L¬‰¸» 8âÊœ!€w\­-Uœ³ ¬RGRÓ¸l₫=®óÓâWuïD¸3t ®'̣N\ÜóW¬NÚ1VY×Óơe{BoWGxç¿»<üÿ5åa°_tP>æúö¶®4›3‹W–ÑŸ6»0 ô ü5‘Lé_6Ó)«©«¯z‰öÛ¯ ư¥úÉ7߬cv?ño›Ăö­æF•7]àE[„TºC̉7)•ëD;ư¬ªM2­ ªªnv̀oôơ—üZóÏÈ ^6•Rÿß´ú·‘†¬ÈOί=n‰éŸ™MT˜Ùßÿ¤Z_Z^^₫Éßưío¿öåyă¦æ2Y;èX2Â(1’óĂúù —'–Íût’̃º½}¡Sûtè¸-!Á(Oóô& ŒÅđi´¬6·JæF~L`Lˆ €oTun‘¶ ưC£áÿÚçÔÚ¨ïw_Ú̃~Ms¨ºaqh?´*üËúΰcûĐÙ­=æµ´ld˜ù{6Âj?™ÇG°‘<^Ê•³=ƯƠ6cđªUåÜfcèï¾íq1s ṿÿ9XRD4IŒ,ĂôĐ1܉Á?å©X₫œaè³%ºoƠâ#åÜT,JK̉Jë— ®X@ ­' ˆƠ±„û´O•g‚ù#”Y˜€=d—”kM}ehÔæS³[V†[o¾.\Ơ\¦½>ÇĂÿ¸c“â“á—ë¶„l‡ơW̃ăDI:¡ƒ>!ÀÏE­Œ)ÁC#| e@ÓU,ûBŒ`™ë/Ñ5»²»_u]}X³²%̀ª* ¯Ô^ÿ±Æ’Vε„8¦Á$4dvtdŸÙƯ©^ùœŒbÿœ/¤̀L ¤À̀üî'Ûjc*c## bí¾ø¥÷®ùØ|»Iû··ë¸\gîÂCÛpa]±œ×¡#^ËÄÄ8÷ư5jDÓßsȶní<ötÛH]„Á6 35½0ˆÅØù¢¦"8̉2Z‚U¢BÛ©vö˜ÁbøĐ·×‡µv¬ïk¥xư%a¶d}lÏ@X/«óÖíÛÂæưư¶ÙĐˆŒ58³:Øôu@sƘuªĐÆú:cÔ,ùBƠŒÀƒXT ï&î5ơ\Ḥ»€ÊÉ8 €:ÓÎj{¬b 4ÇÓTúF³ä!úÈ÷<^{s6T5- ź¬MY h¼ƒàçwí{˜@@Đ\¾ @«µÇ₫ ­Ñ甽—\½6¼a5£ë±Đ¥?{÷®°­½/lÜÑÆ{Û“)̀³²0¡OßQÿOå Ÿ|´IY*6}}o–ûaÉoưú̉•U„¦új̣KĂªå-a‰ÎÆX®|ª4í%ÁăY¢yP63+çVÙogËêD¾xKIê1OZ6í ùóÿmû/̣ưvÑ5ˆSĐ=¿K<×ú=ukê]â©›ÁH€üñO¥é,Aúú'ÿøçđÿ.]P••1 SfT6¨=MG4®¯, û% Ü·kđ‚j´¶¼Èö1‡ß°´><¢íN4̣Û/Đ̃Ñ5d§¿‹›¡Fkcz†œ*̀iˆÁÊàỜ!£€Ëáb`ukWO¿m¿ú̀¾̃P¥9×+µ¤p•v-¼®¥6¼ăêëĂwŸ’1ÁÄXxbóΰơ€,°û{C‰®FÈÏó¤¾̀!#€7®¬´̀̉eDˆÚØæMC‘{7$ÉÓª—"* €á₫sŒªó̃›v ͦ%œÁ‹£́„ªB[ÑÚØè]}ÅöƒHƠ74?#í–VÏ̉:90#¾¯ª°́”º!₫ñîd¹–¤–•‡KV-./\̃pÅü°»o"lØÙ₫é—ƯÚwÿÙĐÖÉw•e¡ö¨(h³L-aÇÁ7ñ>èS_>ûa#©«©ơMÅ/ĐW;˜ç/Ñ&As›fÛ₫«—. Ÿ7'”«]Ke0zhx,ôÊpgWbäG9ƠÚ¹^'nƠ´å³aP®—Xÿ«̉ư¦Ú²̀¶]{ǾsÇØŒĂẠ́îÑ 'Œă~ŸçƯ+jqÂÔÍ` ¤À ₫ø'Øtgj Œ¥¬uϾû.]°üF˜ØCÚÆ“Ă8°YZ€Zé>À&çrhÔN„>̣1ºçô·«ȸ¡±º°½kØv̉{´µ7`3 L 2̃3ÔÈ a@ïØM=½)a€Œl¤xX̉Xµ(|`hDGïïè6!áê%ua±¦ æjUÁ«/»Î4ĂÚôè[ï¶£»́³íiiÇœ́6GgƠÓ̀́ TÇÏƠˆÀÉYi pEFz»©váÈøT]¡|O5Ï|?nÙQ[¤& Um;`ÀÙG¿DÂÚ@g›N]́Ë—. {Ÿ~Ô@·XË'd/"j«H0c”^^–®¸ÀFƯ¿}Ă…́ÊĂK/]¬íƒC¸ăñƯá3w<ßu0́Ú¯érơ›̀Ä`(S?°o"Z35Å<$‹Ÿæ¢Mđù$&Đ*bF| }́ Jm¤đ‚À[f7Í ¥i:®TüKç½çcôđqëöô©ïb'“äI¿®P¿9O»úqîÅ. ¾ ÊPO@E ‚ª£€¬4l™ïß¹aøÉ~Æ¡9Éü À¦‚7*f5…5Ë„__5GÛ@W„zÍëÏV_ÇqؘtjùêШöŒP̃åä/ cYáJÍ•ƠT”„Í À¡¡£J\‘ÏjĂŸ’°bnef[Ûèü̃»vêÇêtmBïà‡± àïêÑ)GZêf R`~ô“h2 "ÇÖŒñ8™|à'ẃ½ï‘'¿÷~ơÊ×Uˆ¡hnÓàƯX1Á9b•bîlĂj¶æA™óe´µ¡í˜rVë GM-ºj~UhÔ{ÍuåZ{MúH¸oûA&4¢‘ùhn®^6Xô‹ĂÔ§„Ä^ØWªX% c¼2çT„Ja`XpñÈö.c₫oÙV4׫nÅÚg Yjå&›÷¿wKg¸ksw8°·5̀W½pÅ£‰Á—»mpDUXVa¢›°Ç¦ÿ‰-ö¨Ä™p@´F:ªưΠóơøŒüËđ̉d4_$ºcT øóM+æ^sưp‹¶…..­Đ²½²đ½§ºÂ=[»ĂÏØ†¶¶ÎÑaBhp´ç}Ë s1îH ïA@?ÉđKñ!sú‡A 6Ê·²&\°ä¼đ櫆m[]­)%Ôø8ă~l[&•V´OFX=¯6 +½Uư—0Faư©’Vl¡„ܾaÓt%ơS‚*oKU¯ưV~´£/Ó¹¯UûÿL©ÿi¤{€̃=R-AÀC x"<$>U¤â©›°₫8Û6ùø)à}„·Cp„{Uâÿó»ß³úóŸûûÛ™ß< ƒ?ƒ6yá!1̉ófWś •Ŷm¯ni¾_FPZg 2V$Đ'À©ởJƠˆ¹^8/Ùsµ-« îÚÜev»:zÁ“n€„B„ „ªGb'ÀĐ‹=Ø©ăæZh 4SóD0áKî ÍWhI#S”Åt`ơ7wí O>#’`ĂrÀ;$W^|hëYwiOôw…‘î=i&€ud É™q€o¢>—:]4F+SªÑ<Àÿñw¿>\µ̣¼đñm ¿ÿk-ĐØmĐ¹Ÿ=ÛÖoßÚvmµéû¢7@o}Gß©%œƒ¿ă\²?«’VôV•oF|ºN@?Qñ—J 5Ă>V4gÁâđ[WµØ–Ôô/–€ºÛØ> •-:¤JưŒ₫‡‹»MZÊX¯₫¾°®ÂvöÛ£•/lÜË –Î6+-;uB&ô°m©é»Ê‰m°×ªÏMŒOVVU=êe)ôÑ<À.ƒ†0$ û€y–̀…\ă¹Ç3<ë‚k VB0ER7³(p¸Ϭv§­=1 x?!=đ̣•¿ơÖ[W₫Ơß~öGçk>s¯¶1Odt†95¥¡NêLw­ñ́34t6 Nƒk¢7+)₫‘]¥D] Q7̀4vß^'knqä]2đbZ Ùg! ææ’<“¼œƯ%Ú$7„,à/G#aȤ%a’:K }™Î@x…N-ôzXS¹ưpàm{¡8À}DCΌskxló09:ƺ (M¯jó÷&BØÏ=`Ô†̉úË7¤å„¾?`í¡"[²‡"MD¹<ëó+ëç…W/ ¯½¤‰ ̀!\đ;j̃>n–’BcOYÖ¿ôÖüYá‚9Uö> ́ظ aön ³¦ú×]¦8F[»‡—.¯7Aùÿübóø[nX‰`J …7#~€œƯv´}̣±àqN ä>àÏó¼Çûäă„R4u3‘öÓ˜‰ OÛ|Bđ~B#ÍñèÁ+›[fÿƯ?|í½o~å ï”!`¶{x\ăÍÄ™ WVÿ-:ÄD¶Na07/Ú­‘ÿ ,ú&)u«r6«đÜ{ •G0̀+e½ _ÖTeB›»đdŸÎ¸ó™®Đ§3z4M@9c̉`#`›₫ˆqû>ÉN®€‡^•§”1m;•`$#FÔÑ€B‹Îh ú 5+ oưâvа¸ö°ÚĂt…-!T[qÂtöBƠÚ„›F 0 ´,íÖÖ³P5:äL]åÎ~ ́„÷;ß¿`~mxÛçî ƒú®ă}m¢©P‹ï)úÓ₫&Ø¥¾ B~̣¶¤đ0諟å–́¹z?Ù G»̣É̃ ¡¦"ÔÔÖ… Î_n¹j]ĐÛÿ"èÖ&W¯Ñw¦¸ƒ>̣ü”ư‰Åu­­¶Jà0ẃî ‡$ä̃¤¢ÖG±#¸tAuVé'‘y@đ[#+@ÏK€¹₫<£ÿØ₫Œ₫Đđï’Ư“<Ï•nªª¤îLSàđ°́L—œ–÷B¢ŒÂù¡3 ‡1¤Î}»zzçrÍ•k̃ÖX«3Åj\ư S.cëàoÔ2<ö3?¿±ZË¢‚í{̃£i– b0³¦aÀuÇ-†W¨`¦cÚ0eỮ~[Nˆ8²lv•Ùüöåó́•g¤’e7Â~̉Óª‘ è1¯ú•3 `ਛ©Ñ(\" ¨±J`Ê€éY.êB̀^`̃:+°oï1`lÏ“C’†d—0¢Gu@‹mj$°B¨àÿYw¹/·WŸpïsUF´öư\Ê}Ú6Ï=KµQN©,âñ“¢ó¡5³C¿,ê³²:jW»ơ üÇÍ̃´9ú˜ đưbp4&é7ô§üuúJ£́²ª0§AÛđήÑIód̀×g%,Đgå ZˆƯC²1Đ̃9ÂØ»Ñ4 }¥å¯”-@ƒ„‹:M0%0 ¾«$›Bèê×rD£7Ëơ´̃!¯eM•̉Hg₫ú+·̃t{²å÷æß£xÀÜ5|́}´ï€Ï;¼O^±×eêf*R`¦~ù“k7Œ3$Qé×oû̉æÿøÆßúæ̉k×¾5'‡62C½ăđS̉³vÙ¬£T‹Ë5«›—ÎơsEô1e,©{¥Ø®‘;fơl [&Êr1MÑ·‚_µ˜wẠ̊!†Y=<ú´Ù « jesP£¡†TA#V™{}zï¡°_ûtơ xШ´à‚‡ñè°HÊÂÓhƯd͆¹æ¦ùóCÏÇMØñé†q©+WOëµ)gù$è1•–ä]æ¨á yRx̣'’˜8¨gиœ´SÛÈw´|È{¦ÙA»b×À«D‚í§Í•ØCÛ¾ tµ9̣¶̀æz|ØX ¡Đ–ê)ÁĐ ÷Ô7˜×7;uœúÙáªesẲùu¡QË/É ”½_KP{µ/Å ,ôz¥-â| úV‰@_‹úTOJœ©øU}¦#FU¿r=»HVưM5e:±OÛ₫ªÏ>ºo(<̣ÀFi‡´ÉÔ³;tlô ŒfÆĂ¶¥«Ăó›´@QèÓ¸° Q‘:N»ÜFÿïúÀŸ´i³­"í·A‹´ c ôƒ,đ̃ó!O<-#LƯ ¥@*̀ĐÍv†Á«Äa&1C*»ăî_n¸zíÚ=uµ‹ĐN2Êfd$<¶«; 2/?"ú„Öugûú„êÚ6­yÖ:ü­ëÖÚê×Éèê%Kê5êK„Mú sĐP…˜9Œ5¬{$ú‡)€-ĂS¥Đ äêV`±Í†CË€đ|í/Ч¹Ü1 w>Óió¹mƯưR?‹Cª5ÉÁD.HP^Î!á–6nU™ÊáƯ7.¿{¯o(Ăˆª€ ĐÊ—^›æç8-ùy¿H4Ç.Æ9ö#Ǽ[¨mĐ-ÁÜ«|?¾’; ÙIQ[ü„z-“úÔ7’‘>]Œgô´*x`K¯Û~ ¶1̃ôms$VƠë›–†Ë—k₫EZ§_RéÛcC‚ëµư%è+êœ_APFèÔ=åM ©$ßUưC£v¾V·’%YX¢|k¥}̉äWØÑ;¾z÷Sa`p l̃º#<Ømf‘–‹–©>ălµ¯4Q«­¥¡‹#®9àHyr¼ơ‚Ú̉¬ô₫™ïÿŸÛ:r›mQ]ˆ€ÁßGÿ…F₫¤!đ £¼çáƯYI©›éH€™̃N¼ư1!îL©ôŸ>ơÑ~û ¯{üeW]²H*Ó́Èp6SY®m¶ëµÚèèX¢âWˆA£9˜îÈHgèÓh¨½«WÆXZZ÷dIXt₫°B†`¿¡³j́ĐÎØ.U>ëªu·Ä?Å´ø‚1c6%,¶ }P#Ê6iÊeùỬ íƒT­o¹ªÙF˜ÜûѦÎ0¨9üîC‰e7L¹üIí́‡`°%Đ‘H?Ă£#&tœ¯½ƯËê燑ƒû­- Ṣ/Q'äI–¤<×ßÄ’ư¹:Áû4à9«Ẫ̉̀ߨtä;ÓsÔÓ#è̉ x@³ n¾d®F̉¥a¨sŸ¥Ù^ºïU7AÀ†ÜH_À!Ë2‹Ë+CqemXÖÜ̃rm‹­ÏÏ_§¿~ß Œù&eOÀFMœŒ¼Qñ+fS?LA?¯̀A˜\R-í^¨ÎF.Ÿ½{[صs{è=Ø:;Ú%PÈfAû P̣ki© ₫xÿ€µ›÷˜n(1JU~ƒ¶Í¦ßú9$ IDAT–·îloÛÇfÜ<ê£xÀ`?Úè?Vÿó¬¿çùçar•₫qH€÷ÉOKƒ‰À\ÄÊIÁl¾đåüÖ5+?|ECUơ¢>¾q0Àa —±øI­?®y]FS¦fä5*Y<JÅ4µ­pϺ°QëÂ|_IX}é¥áÿ¹væö+Ă↠{gƒæT÷I ́ư) ‹g4’t¶4ăqh d-£®C£ĐñÅ¡N+V®_m»±½óÚEÆ̀ÙỠƠzM @ÙtŒœ¶˜0@›&ĂíO7kI #Í © JÆÙ0FÛ ,h—±^½”æäs,Çó´áŒ»S.Rµ~®Æ‰..¨Ùˆ[#vBÍÚ„¢º0wNc¸g{Ÿ6{̉y¢i±Ô:z¢¢¼ú £}FùLæ÷₫̣†ù²à/¯¿ú|›̣A3“¿Nÿ€Œ6é¦ÁºÖ_hp2¯OîS ¯ 3UZ²’D'_Ix¼la­ƯW²¹ÿư`[xèÑG$À„̃ư­̉l¡Yđăe´8¡₫nZ ƠUå̉àÆ;öi*l,¬ÑyÛú»Ïø/i¬̀îÓ6Ïn߸;%©6àwđ/4úƠÿ>úw €¿O¯¢©›éH€™̃N¬ư0‡ g&„0&úR懷}̣çûư=sg×-ÚÙ™Íj””Áˆ««»G£~1H1E˜#*xF?8ÀQÜHÉDÂÜ‹¥.•eø`;₫‡û~ñ@xđ1S56‡7^Ư®;¿N›Ơ„ƠÍYûé\©û5—Ê4@±²D}[,$b´HîÊÚ†8{±Qá>hÈ₫÷më±ÓÙ0 \ªÑüZmösUK/†Û×wØí‡4úKæ¢@GơÜÚ--€ÂµW\¾§Mykk+KVëjsɤ8» ËW‹#Œröœ=¯»G{¨Đ‹çPZ¾°“_5ë< ¯¾¾»¾/Éê=T4̀ Ơ³çê@¦AØ 20Rç=úköơh¨½@ï‡ëW·„×®¾Nđß©M¦vqʤTơ|Fê<2à'/!̣R7Ă) 3¼œDóQé=B< få j̣̃Í]}¿¥ĂQ´Ïf¾æ5wtôIí© \ô» wmT,ĂK„v(’®}L̀ƒ®Sªcˆ2@Bó´Cφϵ>¾± %”WV†÷̃´DêØJ-Ư*3Kíg;úmnöË₫5*¿åK%'Å̀‹rĂS8&Å™©8n í×g÷A4 h^{éƯ'ă₫ΓívëüÑd`À–ÄŒf´@Ue…³$Âh‰a²ÄF‘  @»|Àï%Ï%Ï;æ¿ëÏÛạMUG[?/Z1oÏȘ‘|• 79G6¤ ü'Ôø/Đ¯Đy:°©ººN*₫†đæµÍâ”áëô±íØ&àç{*3âcÊÖÿé ¯kh Ø£1 +£‰ ü¹Z«±4Cƒ² è—ƯÊæ¶đ…?-ÿ¶01ØF‡úV/"Üâ8±ĐŒ9dHùúgGk+ÑP¡—o»½­SeËæAk₫Ç”„Œ̀–öCÙ­üpÖmæƒÿÉ₫ÉÇ«ä!å¤nS fđÇ?ŦĂDÜÇLªü£üÁ¿½áöo¬¹p^íFN?Ø Ct4Ç£—…çûDlB1EÔ¥‰j–‘vFÏÚEaiÄT<ÊR,ộ₫=;,₫ÁíÏ„yç­°í…ßvíybm´2«T{h5ÀĐxèÑœ>§Ơ<+˜q¢ ơÄ5̉CƠ¬–0̉Ä|£¶g­̉ȬJ-”­uÿ—Ï· ›öÊj|PË ul±•ó6Ù<úPM¨Đ́"7*íóÙ’rd˜˜̀Ṣbp°D̉ˆ¨|@É cZèO½pB`VcÀ6ƒ;ˆopÎ_¸@'·í‘-ˆÖÑ‘À|¯%‹†å ́ä¼…öp¬a¹(ưk—Öéwi>DdtíF|S Ï ²Y¡/ Ị̈BâXâ×Éđp–æó—³[ŸÊÛ¹¿'lÚƯ¾ñà°aẶeđÙסw4%à£}₫è«ÿ2Ú7u¿åK̃Ê\Îö@±/ŸüEhïm³ÊÔKèÑ¡?<œùçøÜzÇ~Å9ôǪ«̀h₫TFÿäŸTH‘Ô¥p ¤€S" O„ưô‚3–Êj*¼´4û́/~øèƒ;{'^W_cô $£æåĐ—ñ 6|Iø‘mc(IŸxÂ$ÁPèØ8ªßL•VÀÖtkÔX¢é„½;6‡º₫èĐ3^¸|QM8¿yn¸NË µ Kà”Á~©ûíd6Û¯ul" 0EkNsʹe…¢îÑæE¬Ÿ%mû¶sÿ å2µ:¿}È}Ù¯¹eYnëhÚ‹ĂİF†h1äÍ€6Ê {1 ­åX³O¹Œ¸+ze¡Îºw.²yA9fí>F­Ñ̀ ơæú…Nm/i™+¤Q(̃xérÈØ$A/.ĐÆ88¬ơîöIµÏÉ~,S9¨÷Y†‡>úM9ÑMb¥ÑAÁ ;ơ]îæk©^€®¶©%mĂÆáđỖpßú­á¡'7kä¯oÙÛiïÈß é諯*ôỠ§)ÊÎAíJ<Æné‹Ägtâ!ơfƯÿ¢ú̀Û2öƯÜÉn~­Ê|u~WxF₫ÇưÇ–ÿÇû¡ơ&5;uÏRàù¢́̀Éw£ÇJ#˜›·̃ơï¯\t˘ôçYûZ^Û ù˜~¶,Q·a,%µ©Ôê¡ĂLY“o€§?&UÄÂÀ„„ª„̃å„¶bæTÅHKGû¥¢»weB¥¶s}jÅÜP_ßæ̀nZ–̀éwèhÖö>i¤è—º˜÷X¦¨A Ù ĐđĂŒÓ„$,+äèbæ‘·v ™æb¿„†ÊrÛÙmy˜0|Ó¯¬Ó— ơ'½K̃ Ú+á9œsẽc?ƒQ¤Ÿœx¢,_|N¤è±o ½q‹µûî¦K–؆NÄ9R·ưĐˆ–o"\±1,9ô>¤¶gŒœơơœ¤ïèY=?ªDTû u–ËAk¥ÙôÓ€ööá°~ă“áÉgw‡Cư:œª}oPVŒđQïKÈPƒ>' €̣5̣7ĐW[íÚ+U¦94Å!;‡̣rMw”ÚrÀ¢á^p0¼låÛôç̃G7 ¯àg”£ªï¿+ưkîŸ{xÀß…Ḅñîå¡’R—RÀ9LJ‰”'N„k çô*\ïU4-Z:ï¯?ÿ•÷¿ăƠ7¾QeÅ´3l;î\¿/ ơJª'4 v£@¡‰±#0Rƒ¡@@½Çù¨Ê÷_G=œ½kteöÆp jT(;ZM \¼¨>4̀o —5Wi×·*³?@xZØŒ<™.`i [­`, &Ù˜2×Jª%D€«’êc)´óÛá=̃¹·_+öôÊ0;©º7[a¼²¥©U’HØø( >~Úi»×Ơ3çĂª;́YsFD¾ă\•îÆ¦GqÛECuû. ?qá¤M!)Ϊ h—¨÷¥/ׇbæùµåX×M+¥}Ú~p,lÖ!>[·l 6m¶£ »:†±4d`¯)'ɰ¨÷m#"Á³Ùªä>å₫S}R}‚8ưZÚ¨ŸÑ¾i½dÛPV&mFQ¨”àQ©½.–¯¼8ü§—]zµ*¥µ­kâ]¯}éÆö½­X̣ăÀ}ÄOºŸøÇ₫₫~ĐÆ‚Äñl< ϳÆ‚€†\oÔƯÔ¥ŕ-¥EJ“¢€c!Ú$¼¤°jö‚Åó^ñ²›.øÿñù/¿´%9 M̀=ûÓM2î́ ­[6…Œ,щßÛ¨—‘–ú‚]LÜ,ï& ^¡2Æ9@3’åab¾bÀv¼¬€4 e@V®ƒ^4̣[t̃¢PVỮs}³î‰Ó‰#lÔQ³,ÊÀO¶üSSˆ”•„”Ă5ŒWeW.+Ë2¶ ;ÁiNWmb‡8øøñ9o™"”PNâ¦îxÂi%„‰ÖX̀Ó¾3夰®”qh‚8Jz@Vơ ´›$¯B³©`Ëe¾ƒ¼bäÅ|6¯¯”¹ú’çÂ¥Í56íij_¬3t÷t… ëư}‡̀¸oDBè¸À~TḲ’¿ú«Sèƒü¬è‚ZŸïíêưB Ïˆá“ÀwaûŒË*«Â‚å«Â¢E‹Ăoềóë²Ơßø— ½áo?ô;;ïÿ×o2÷Ïïˆêâpñêñ‰>G₫:ø3u€Às¾ï{^t"|êR L£ÀüÉO+7½xqP€₫ăNúϰÄG§[W×Đ8w̃â–ó₫ưûØ­ïxưË.^^/ yăª“™?ºcKƠ:êư;7kô¦¹w1]÷‰êơ° pXí*¾f̀?áiĐØ $ 9ÇŒ ̀µ@£¯ †„êUÈ/ZvQXƠ\~ó’ÄÚ_uỢ±¡ĐÚĂ¹í9ƒEFsbÍ$Đœ„”̀Ñó9=‡@Ѩ­Ï×ỳñ¦®0Hw6€Ư¯½÷~ŒU¢¡.°O4#€¾YÜ+ÍQë£̃çèƯ&…¸¯<Ü&;ñđØĂ‡₫í¾'°çÀ&f©}[ºgF}h0BÍÙn₫Ê—ZPO¯«utë I³‘>ưѾ|bبM‚$…Ồ_®¼̣êĐ2»<¼im3YfÜ?,¤. ú₫÷́¹ç;ÿØ>¡90M7ÖÜ'DrÀs<£@è3̣/4ú÷çy×µ¯’R—R`:R5éƠ‰S€Q ưˆ!€i´œôƒPŸóLÆW}đóßy÷‚—.»ơÚY©èÍe§€àïîÚèjË ô÷ €aÔ0fyT³hLS&?ˆ]&»µÁăT ˜³‡h„ÔÉÚñd.ÖŒÿ`Đ ؼÇl`Úeåẫ. o¿j¾?Æ­=Ăá @©K£QÀ•¼²W˜hp&7ÖΜsé ¢ºÊ’đ´´ :˜[…\Áô(1 Bõ4ª@tæ\²Ü³vKó°ËöS ô„¨Ø<Ü‹€¾0ØhĐ«;Ø5*~æơ#héĂ,Ơñи»éëÛĂÆ§7„=[µ9Ϩ-Ùcß }Sï3Ê—7ĐW¦‰¢M˜ú̃§ôÁ,ô‹̀˜OưP¦’bö2Đˆ_tœ5§™vÍ•k3ﻩEµÊf÷tơgÚ=ùÉíß>øƠOüIëđ€ŒQ¼ÁIó¨>àöù~=ư»ú?ư“†v€çđh xŸ|È…O]J#(ccG¤§ )—ô!¼ > 0M  û ‰/™-₫„` SzBÍǾóÈ[—4”f_uẠ̊̉úYµ& ܾ±'ûàcë3û2Ớ0ªÚ)Í€· &£µdsFi9u­2! L¡p ô‰GX˜—Ơ„ÚÆ¹á?¾¤%\¸Y%êäOµ2ĐaË`\"H Pƒk·å¸åM6đ‹½Â 5q¹pÄ$‰¿”pfœ•EO{ —>g¸vIMpbă( ´WÀǸí?t™̀Áçj¡OÊn Ll®,èy­½çPøúC{µï~ghƯ¼!ŒRa¾¦al¤ŸóùổtĐWy¹Q¾7tªïä@Ÿǻ'a &I _laüeå¡~–®¯ËwÑå™ỵ̣̈‹§ wvvw<8₫­¶L|úÿËζ]¨éé*1y½8`̉ÑrƯç₫ưû¨ßC´Çû'oÈ™º”)wÄ‚¤‰)ƒÎÔFæk´nÎÀDE`!Z„ôµµW¾êÍÜrË[̃|ưª¦æ…å³¥GøÖ:íÏ/umëÖge…¯ƒ„´ÿ₫ÈĐ ÍƠc¡mB #9±¼Éhî}J}+Ô¡³3‚săAâ65 ÀΤSg9#ÎÆæiÊÂÿ{ưâPU;+̀̉̉1löH3Đ/µ2‘q\¬₫Km¬%kóªtÈKIØ Ăn>ÈHÖ8¼Øđ¹Î‰ùˆæ)Ä úC'Z¾¹̀™ÿ¿F».rRăÖÎÄyi\4M6Ô‘*‰É|¹f©öLY¤ï#`>t¨?|ư₫-²QßÓO‡‰₫Nï%Ú¡dg¾œ!ŸôIWß´ØÓOøÆ>̉G‚£FøØ_$aú¦Ú7¡17·Ï}mLTZQf7ʘo~m¶aÁ’̀+oXV7†°»½k|ǦơCi;éÏ₫ÍÇÚZ7èèË„œ‘k¹b‡Gåt<Àgô₫yFúü„\ăÓÑ¿ˆº“£@Ü!O.‡ô­™NïC„`£øX OÄBq¦Đß2uP¼êÚ_mYyí¯5­™W<ùÖ÷|`QÓ¬b›G¸ưé®́ØĐ@æ‰-:S}w{È$€­$H„¦Påúnk‰@`đ›€0\_L^<ªÙ¼%9ï©£]&`«Ï``|ƠyuZIQ‘ë@¹Rß-̉̃ sdĐ'}Nh˜ƒ₫î[·%́́8Z[µ÷~w»Íë³çF„‰å~n´/Ÿ}À_ùÆóúúԃ兇GúÉœ>ư 1è£ÏÈ—”‡†¹ •:Vxًܹ̃V_–yÉ¢̉Đ>˜ ?½ă;=›·ïưÁO>đÄƯßïTơs“+éJ”³n‘ é.₫¾­/VưùÆŒúñ€¡Ñ?ù‘?!åÇåê2u) Ä3¥IJ“¡€÷!B<€ØÀµŒúñ ̣±À}v{ÁvÀµE׿úÍKêj*.[¾¸́÷ÿâÏ£:èÏ>Óz sûă{lxW[«ÍË›€˜¼Ys {Ü*¥'û 0Uă…p~¹DĐv±¸½€4cÓŒ₫tÏÖsWT‡¦Ù:‡@ÛÄ.j^~cUb<ÈZơZ«Zz6–Y§ƒHÓ°ÚKà9̀í­ĐśOÿúx@G„¨„<¢QB¦©s‰?aDá…\v–¥ £¼ji]^va£i¶I 0O;ư-Ô»•Úø‰}C¶ÛßÓ› OlÙúu^wÇ~-!6áĐ7CÑỤ̈=:è«₫^ưÜÔơPñ¶lOß˜ĐæómZ¨DVưú溯­tÚă¼°æâåáúÙ¦æ%™µ‹k •¿̣Ơoö#ÿü¹ÇÏăóç₫•4UñÔ¥˜Fû-NKI/R œ8èGîÁ@Ơ>€-€kñ#₫¢à>ZEpà]„̣´¼.½úúúß|Ăç¼üí¿7ÿÆyœç®¡Îgíè:˜ùâ}» ¡÷À>›§Å‚\ù̃ µ$LFƒÊ7QSH‚v9ƒ>Ÿ"ĐˆP`Z §¶éæ~¥®®­ +e'PÓ0',i^¾¢̃Öª³Â.́rÆ4´<mG¹ºa_áS(^]yñSs‡sb?¾Bضƒ£a§Œ·mÛÚøŒNƠ\ºÖéåÖéè³y#}ºơ¾Ïç ÷s.úºJ–W²dáƒ%zÉ(ßmB‰Ơ6†‹V]*u Ñ­7­È6Ï©RÏ₫̉wïxzƯcƒ₫üî¾ëíïïéxq‡”\ó×ßC̉ô] D ÛøèŸ<ưă]ưïÀOˆ=€ƒ?‚Ïó.yx₫₫Ù<Ô­Ô¥˜NBvúéUJ禀÷#Bb-£{Fù€=B@¾Àµ¼ €@EUƠµe5 ³Ë'†ú'?ù/¿¸rÖ¼E%¯_Y­ưøµ!́d6sÿ¶®đ­{ £:xÀgzÀæ€Q³ÀpAmsÁ •¹‡˜÷!Ø©‚¨€ü6E,#d¹WY©öXeEE¸vơrA^øÑ#Ï„{ŸÚah€¥ú$€ªĐ@– Tà¹ârÂÖ́z¨¿$T6HÂ]3Gèpde $ùP”„®|PX¡2â¨Ư·¯ß¶?Üöƒ_„ÁMh´?<( €[§Ïúü©‘~d½ŸÓXđ Ñ\ØÇä$HD-T!¦Âg¤0§Ư1è3 ¾)ö¤•W†%­ÑÜ~cxçơ-aAcm¶\§C=Ñ ­;·́÷ß³ëÙơR=&GûmÅÄ kƯ)—æé„̀„x̃÷¸ƒ7@ÔỤ̀.ú1øsÏÁ¿å¿nO«שK)0'û;–Iz‘R@đ¾d`­kïZ̃…ñ¤»€€wׂ€ûLyeÚ¢̣̣̣’o>qàW´đ.›ưÑÆÎ̀/¶÷†²Ÿ˜Höq7«p=æ„€q%Fa±hrÁ4øT€„©¥`? ©©Ë%”ȯ½äbí_¿$üå§₫WèƯúˆ±±£\²…¬6¶QSZ¤¢çÄ_w|¤ñ@ëÁ\x"%ŸAh–äÀơ„À;ÊÎl À¶/¾hX*Úµ\tyøÈ̃₫âkw‡ÖMëø:ègxLà?bñQúÅKö˜óçó‘­‚Ÿô¨B’2üj‹Ùy0Úçû™đô“uûs[BƯ¬ºđ¦—_^qÑlơ„Læ₫]̉8ˆ øî·ïzü§ßë,.)Í  R`aƯ=é\ûóôúˆŸkùâx7₫óù<î£uđ÷Ñ?yº‹ëèii˜R`Î5§̉HJS¤€3B‘3:F80*F,. âx>ÿ9|¬  ¯N Z À;EĂƒƒc¯\RzOEơ¬̣×ữŸ-ÿà{̃ÑôJ1ñW\<'“yợđgÿ¶-;6:Ù»íÛÓŸß­€ Çt¸Í™á mâÊØ5\³å,GŸÊØŒ ¥²Fƒ0•ª¥Ă ‡5Jíîí}==¦̉V¹ Đ4 8,%)zÎ8ÀŸ%B@&×àp]Ơˆäñü‡9"–{ÇÊ(‹†€o2×ù[7„‰z7ề†ÿơ ¾Êđ·M{r«=¤¦væS|Ÿ ²  j}éG o#~>óû€~‰¼­Ơ_`«<²×]w]æƯ/Y@•³ăcĂÙ§Ú‹>̣çkÿ̃?|bmD‘k åŸ‹ă¼„¤Æ₫{ÛÁߺ ¾ü°Ç#æ Ï;Ÿ—éở­©:O]J‚H€‚dIO‚0PÁ™"L ‡IÁ¬\•ï£x%M1Jg„¨?}À…׸0à‚€ ”Q¢U†¾ñ—ïÛ ?~ËÿËK–\~Cư-kçfÿøU+d›/ăÁ¡•áswoËvØ›éííÓQ¾ĂGN¶!×É‚¨ëQ1'»Ë%†p€v̀YKrQVẺJJÆO†ºúĐ»oGèÚ»=ŒIuÍèĐ Œ‰Éĺ=©&¯Lû³mnÂÖüg¦epj6À·rs£ç\Ă ° Ôå¡àx‹WAhlô ËÀ#»Y³À5IˆZ^9¨ïB¹#ơáü“LƯ @èëAƯ…•"́!øHÿ0èKƯÊ¿DûđWU„Ù5U¡®avvùêµ™÷ÿú2̀´··=¹ñÙɼó‘áÏÿùûv ơh½ịeă–çSŸë|ï`O:qgB¿æwàÀOˆPL¾ïà Œwà÷?i.x>q¹^OơxêR ©ptÚ¤wNÎa~î.±:ăÁæ†wc@¼ "L¸@à‚Eñ?âC”ùỴ̈ïừ7¯X$«̣ß|éUU½yyÙÁeá̃­³{wmÏlØƯm†{ƒ}½60¦‘"d„ÅQƯăs#xåkñü¤´cÚ›>£>FlªÛ̀ ºdŒ¨|°FO0#—AÄSGW{Æ)½{:¢–­¦sä–¼sơÂÅœ@}xĐfzÁ€ơ¿„£2đûú‡B·zLFöó/’aŸíÉsü₫ºÏ?ûDµïû9 MpĐG«lÎ$ơ~UUhj–i­~Ó¢å™×½ổ #)2ÛvïûÙ]w ư|{OøûdoÇ̀­Ó?ñô#w1zŸög؉Ç@Oœ~Í}ÀƯ¯́=tđwÀ"xù»PÀs₫—×I·S—Ràø( ÇG§ô©ă£Œ^ï ‰Đ™$Lç÷IÇûHˆ‘?̀Fçv± àB€‡ôߣ Æ̀?ó̃7>Ês_ºú¦¹¯|Å+êßøúW7\{áªÊÅ—6†»·ö†!ơÎ;Â[{Âpÿ¡01¦½é•ëXIăÀ­ÚŸIDATbaî»ú_à”4-7RĐr)É„: À©ưl‰†ùF¯j*¯á ÛØèÛ-ø̉‘¹ßcG¼ç &xL¨5Ö \è7 „IË“jÁÔqúT"*rÖ÷Đ̉^ËêÔ¿Áđ©Ÿ¶‡këeZR&uTnÖ$å¦ç™Ç7t–? ’i;x'7•À²=Ë»¬24ÎoW/››æg/[sYæ Íí́̀̃óƯ¯woÚÙ6ñ½ïÿ wóĂ÷°A5 Å1<ܘä¾_ÓW‰ă=î́ư˜k{¡Óï]ÈuàöĐÁÜ€|!ÀAßG₫₫N=̃xRyá ă¯•— Ï"0¸‡÷ ĐCJ—"Á÷¦¹Ü=3(´÷́“vy´#Z ˜eă J¶ú‚׋¤UÉeĂܾ«ø~FúfÔ§ôíØXÙØ®[½,¬Ỷç-̀®m©Ëtè3ưÓÿ÷Ơƒ?É~÷;ßéY÷À½½Z/J#W÷q5U3#$!ĐÁ•x>èrí̃ßÁrbO/äÔ ƯóÈû»äéezµ8aêR Rà¸È”>tp&êBŒÑi0/g05^ ₫ôñ4@œæ€ €?qèÛî§„ÖgÖwÈwƯ/xdĂ–aÖy¯XÚRù©¯ưỌ́ÅEơá ²mW/ÉÜvÿ®À̃ÿZ·†rm<. bĐ́% œå4054£2å34:¤ăÇ•®efESi‰̀ — ¹m’Ưá¿ høH,ø̀á§sù&BGœ|²ñ#À;ʈ&Đn¯jø)Eư₫Ô={á‚¶Ù_ËĂR° /­®å5ơa²oHeH›¢‚èDÈÉ´súRí3  {ÅusĂªƠ—…úê’đ¶ë/ȶ̀«Ë0T~º;d>ü™ÿƯ}Ç7¾Ú¹eăSƒ0&‡ú{écÔÚÇ"bϽô‰»§Ïwûo>đ;`zÿö4ú:i\{œ°Đ}O#ộ¼^oƯJÁ"¤îÄ( 'F¯ôéă£€ñíÜ£Äa8qú§“ssàFp wÀç̃Ñ&ü}ÏÓâg×=x@aÑ“ƯW|ï=?ë¾ùMÿi₫~ï/ÿúùơá#¯·}²=ưd₫êÇ;ÂøÈ`è̃·Këµ5­Z`£`½L#j+ÂÍ+g…¯mè ÅÚÓ^#RÔ₫Ü-2#@ y²°Ë¿—Àù÷=O÷0©MR7挄ùM‹\qđ—¶™JŸ•, g&ÇBïö'B髃–w†́°è§§½]v“ÂâÊY¡jááü…óĂưµe¡iVmÈ”eÂÓ!ó“>0üé¿¿µ£mÏÈࡾñÁ₫>ú–»¸VÔ8ö<“|°$x́½ßÆB+ix€Oœ~z!àƯ…̉<ŸB¡—傇×-Ỵ̈Ê&u)Ÿ©pü´JŸ<1 8s‚ñ,9q CctîŒÔà&î@î\;đÇ‚Aœîï¸ÀµçOH¹ÜC(êhÛ;₫ÏŸưë¡o~ñÓ­CƒƒŸ¾ư‘kf-h)çUsÂg̃xiVZ₫̀}Û/ _»ë‰0Ößc@– (µaÙ(C[¹¤€nă4-̀Ê@0́±ÿsK<Hd ‹+r 9ăÄË}̃°ø4z/’ ¿L+JKe¡_V%U‰\¢_‰v|ⓨÉ`°¢¡9̀37ÜúªµáêófeE_ônê z×-ÛŸyè®î¢ẩ̀Èđ÷³đi }Đû$Ïàâ~IŹé“\;è:{_ÚA߀ä ́øă<<߸œ¸l¯iq[â¸n¥.¥ÀñSF˜º”Ïœáº@902̉áđÎ`c ‘> Câ , NèàO¼}€ßçyÇïÇSe“±–íËs]ô¾×^ơ€Ầ­º÷u׿qUƯäơKë‹₫Ư²›Â/wö†wôe÷îØœáœùjíˆÈjªª€Yi(×µ--4•}’è\è=OKÂø‰'×_§¼Ớù£^`©û“yüœ Í€&»v„E³=œ×TºÇ¥Ia•€¯×^zõá-—7A¿́äøHö¡ÖCEøÁÿ¾ço}i¿Zv¸¥cẵÏHóô8ôtBTï¯÷Gˆ=ÜøÜèỰßå̉¼ß烽_R_Bœ·!?n7Ó?)N„0¾Ô¥x>)ĂrG&íŒFë‚ đơ¸ ÄlÀA^–JÅ@ïq~I÷{¼OÜó‹CÊrOƯ²oº|Î]ï[º²á¿~ú—¬j˜ûƠ+WV¬mY\TvÓâđåڲͫ¢=¡¢ª6ÔÍm¶Æ° íWŸ¨ÿ¾ €7íŸ₫ŒËÜC»09®™“œà÷¦¿qö¯́ĂëËưl/…¹\¦­”«µ‚ ‹›féØßeÙ .½"sëµÍVéưmmc?ớä¾ơoư·}êOZĂ`?ư²‹Z•ŒỤ̈4́ ñ€*!}Η¸{x>xS¾úóGø~Í;ÄyŸç=Ï;.Ïă^¯ơ&‡ÄƯÅqOKĂ”ÇMc\Çưtú`JS£@ÜßœÇ!€Ë5!̃8c°v ÷0ä÷₫ùÏpí!ù»Ë¥^ƈo~çûW.YµvÖ«VÖgåU¯j¨Ö!±îưưÙpß®~k€È`Pàœcѧʩêä;.ăĂƒ[×g‹X– Âd nœƒÎ>¶´÷É}ÛÇ¿´<»zơề¯-e7èÄ=³uçÈîm›Gîz¶c̣ ÿđ̃̃¶́…ïưÂ#ŒIK<ßÇêÀ.qygÀÚ} ̃ÄưÚ̃C̉‰;Đûûz̃^u!Íëä!ơ÷¸¢S@~;¹—º”§D~©K)p¦)÷;ĂU P“^Hpv 'î˜3=@èZâk¿O q₫Äcaflơ}ë?~Ñ5-ơ™Ñ†%Ơ4•lvÏ”ñ1ËÖ ¹K̃;M.ɱ¼¢ºhƠK®©‚^ N³F@ªËl~ÏÉ'{` ºª2óØÓ[G¿úå/v́zúQ6è¡‘|ÿ˜n1e‰̣€(鮪>;H;¸;ˆsí´£}üŒçEèåÆÀ×ÉëX¨ ¦×§i©K)pZ(ÿ¨NK†i&)N€̃ÿ<äUâîaü8Bb®˜¬ñØ; ;àsíB€Çă¸û8Ïßøz%ÏYØR;&‹©á‘³=Åu/nÏæ_“vRΑ ¬¼¢hå•7Î;÷­i~̉WX”U‡zºÆ·=ưx¿Œ‹º÷ïf% íßß› <î¡=×ôÄd=ŒÁØăôºà€Nè Ï3ùq̉ü]BÏ7)ßëàa\OƯ6Ê÷v‘îqIK]JÓFÓÆŒN[̉Œf̣û`|Mïàïq®= P&ƒ3à HæÄ㸠ù€§»àïÅyx9„.ª›§é¶9®Ÿ/—…Ê*”ö|Ơçḍ=Zưh›·Ïăqè€Jè K{HÜÛă±ỄAßA>ÿ:zîåç•_V\Sgâ8¸ –˜ûCẓ́¯ă{i<¥ÀISàh?¸“Î0}1¥ÀIR ¿/Æ×'tàC˜k¤¹¼¹Aœ¸ƒ}¾ ùqÏĂóór½lB|\W]NƠ›8ÎÛ”\¹¿g«Üia>àùu 'äøc &Í:Ü ø.8đ;è»đ@è̃…ŒüºNƯñÜĂy½½MIêaçh׆)N^̀à´56ÍèC¸_ÆqÀ5ÀÇyœĐAØ…cj@Ưœ8̃‚X(pđ÷4¿öẉóâïuđºÄuơú+ùy(+vñuŸ9ÛqÆüàtđôx!Đw |ûBiú惾>éÔÅC¯—>×8B̉¼M¤¹‹Óâ¸ßOĂ”ÏÎU&đ¼58ÍøKú*̃™¤_Ç!@˵ƒ®ƒ° ̉úˆ̃…÷́¥!ˆß'O4(/¨i8¯¯Ç-ñ4₫!ÿ£9¿çáÑ;›é₫}ă8̃=@Í5!`́£uđxÄúéû3₫¡çGù Ï5ơ!Œëæuơ4Bœ‡Đ̃Ÿ±韔g‹ç2#8[4IË=·)ßgưïB€Ç Î1h̃1 »P¿ÑP,¸ àïyاlÊđ:ÄuT²9̉çùơạ̈̄Ng–>r&ïpc0œ¨c'ÍÁ½Đ(ߟơ0iÏôư <ŒAßËôzx΅§¿ƒ»×›û8OO®̉¿)Î! 8“8‡ª”V%¥À S ¿ûµƒ]ÆB€ƒ² Ø€· æ>Ú'tï@₫~ñû.`xY^®Ưy}ưúTBÏ+½LÏׯ§¸~ÿl„1p:h:Ø:;0;P:øÇ`ïé¾Ç]x Œ=exyRâ^ÇüP· ½·ƒû©K)pÎQÀ™Ä9W±´B)N‚…ú³§9èzwŸ/̃ù‚à/ä_»Đà‚€çëåÄuQvS£uâ§ê_Ï÷.8XàÇđ=tà÷Ñ¿ ä`‘_’¦€øÉ:oWÆe‘o¡ë“-ïùxÏ”ĐBíXä](ø1Øû{ù O9ÜĂqÏË÷²ưÚˆîíÚÓÓ0¥À ‚Î,^•M+™Rà(à}¦î@èÙù=O'tA€¸k\•ï! OÜAßµr/â<½L=̣¼/ez»<ÍËÓ¹w¶œmwđ÷ĐÜCásÇè]à<<BÏŸ0ërJđ8÷fÄS—RàEAïÔ/ƤH)pˆˆ’qî8tp'ÍÀ̃¿OÈ3„Wœ¿’§À…øÉ:̣tçq/'yƯ3êv¶ơpơ8u›8@ƒ» qz~œü|tO₫¤Çq]N?ô‰ëÁ½Ô¥xÑQ€º”)aI¡Q>ˆ;¸ụ̈qÜïç¿çyº~ƒq>÷râkÚáé'<ÛÀÅ9đÆ!@í£xÂä ]ón ú\;ø+zD¤¹ăÙÔ¥˜pÆ0#›62¥ÀqP ÿ7áׄ€½_wï€_èÚŸ'Äå‡IêÉÿơüâ¼=îeûµƒ\üÎÉ—|ú̃Œëå Mèñ|A Đuü,5ăÏ#¹çôÔ¥˜q8×ÀŒûiƒÏi Ä¿Æqôư~|íÏĐX¿ïqÂÓå¼^Ÿ_ç‡ù÷ưúl‡1烵àI÷xzzü^§m\ç»BiùϤ×)^”pÆđ¢l\Ú¨”§…~#FèqyO;VxªU0 ¯‹ßŒ¯½>~0¾§ŸÍ¸ƒ6uÈçæó¯ưy=üöp?u)f<ÎE0ă?JJ€s–ù¿—ø¸{p¬¸ß'<.®'åå_Ÿ‰:œHĐ̣®ƒz¡0¾—“ÿ~|/§˜ñ8×ÁŒÿ@)ÎY Ä¿8N…ưÚĂ£¥éÆÅơ9ÓeŸHy1pÇï9ø“æÏxèÏ=×µ?—†)f<^( aƨ”ç,̣Cù×ù®ûùÏŸÊu¡² ¥JÏ×»1-NÙÜĂÇíŸç™Ô¥H)P€ñ¦Àí4)¥@J ¿§|đ!­Pú d›>QÀi™Oçè‘4R ¥ÀñP€SêR ¤xqSà…₫;OÁ₫ÅƯ?ÓÖ¥H)R ¥@J”)R ¤H)R ¥@J”)R ¤H)R ¥@J”)R ¤H)R ¥@J”)R ¤H)R ¥@J”)R ¤H)R ¥@J”)R “ÿ¶@̀̃?FÎ IEND®B`‚icnV Ccutechess-20111114+0.4.2+0.0.1/projects/gui/res/icons/cutechess_32x32.png0000664000175000017500000000321511657223322024267 0ustar oliveroliver‰PNG  IHDR szzôsRGB®ÎébKGDÿÿÿ ½§“ pHYs  œtIMEÛ ˆ¿tEXtCommentCreated with GIMPWèIDATXĂ½—kp”WÇç½́n6Ù\6É&@² EB åj E !ÉTKa,:íL±§¢̉O*hÇ h™Ñv¼´E‘´Sf°*EÀ‚r¿ÆHnÍ•$Íe“l6Éfw³—́fß÷ø¡:vœq„fÓçó9ÏùÍsóÿŸ0Z<Râƒl:x¾ơH…;ßZ’ŸYïÔ’G²³2c @ÇX«¦–|åµsưBùƒÏ× 3cĂ’‚bÀó¡TàØíÁWîùB»j’¬4 -æ{'¦~ùâsÛ÷H)âÁRj 0ˆíRT7.\ÅŸÉ̀L"}síc_?z¹½@±óAó)÷»°Ư;ÍùNßvo(®y‡ú±è:ï8í}ƒ¢³ùïŒăxæđ¹†ó°¢ĐA™Ëñxi¶ẼhêÀ••†o*ˆª*\¼Ó„95Œ½ xßëîuy;€”2 Ă9Q“άa‰ÅIËv±~Ơr!HUU9qúma™ Ëʵ«ÿ4à^NV§â ́̃©ù™é˜Óäf¥cÑT ܋ٳk'9v ib’̣¥¿Ô"\h¡cÊܼí±ê/©ªªÏ @S°*‚oz††›Wxçâ)œ2ˆL&Éu:ùÚ _ä£+–’i·É¤Å"à•Ëh¸pÊ÷ÎÍ3†àÎIˆ k–Ư‚#ÍJiÑáümƒcønŸ~·óÚ™««6Ö¬¬[µ®́ÖD8½nƠbaµYyù›»/ !₫đ¿ú྆K&cSÓèzC#ư„¦CT-ZAîºâÆŸ½´·¹±1¶¬tá̉ª½¿nÜ´f9§₫t8 fæÜ6MLgg؈ÆâØ2$ ƒq3èe4†ö¾í2M#̉Ñ7Ôä¶~áŧk¯úá¾W€«)ñ‚xˆ:ÓmH̉r\HÓDÓ4:Zp­­•æ‚å_^’¾µç8đ&0ưµå~ª7?*Yü‘}mCăd:8ˆ!t+ælœoX'¬œ́bśvk[G DJ…è3OlM(BĐ9裩gˆ¨´0á24Äçé§±ÏKơ“Ïí73°ZÔ.MSB ¥Ä0M¤”´w÷âJƒ‚%Ỵ̈ç Ăª÷¨‚”`Q₫󬄢ÑÙÚ„‘­ăÛûŸ7›¦.) 0'ƒ$*¢ (]×°Zt¡Ib3ñÍ)è÷¿÷ßœŒ$¾oH D‰Î8í*y6I23́ ŒNĐÖ;,÷¿tàs­]½§À7ghx’Plö¤”|OW6•¡) ‘1îơôÑÓÛË踟2w!UåÅB×5iÏ]đçïøwṚ)›ÿ>iȉ¤Áî×ÎR³²”ê 7“̃a0M4\.û}ü­¾›ÍÆ₫çŸàÊơ_Ư¹µöçs¢p$6j±Z±Xtö?½…ÛƯ½ÆÉŸ|MבÊ×Tâ^·…Í•+©zx)Å%o½ñ›­q)“¸‘‘½z}đF—g‚ª²"6–/¤Ä•C ù¾$ñh„›-Ư\¹ÛNs÷¿Øó,[*÷?Sº»îµm«ZMkQwú½»ÜÁÍ¿¼I($̉41 ƒGÙHÄÔÈËụ́OËĐÔdèó\P[S<]ßu)ˆƠl[W* En{’È̀{ö.¦É’’"\9YÄÂAÆüâđ¯¶ E4HS¦d2Ê«{bÇÁ´‡*kÊ×?êrúAMÓ —­¥¾ánb¼»iÜÓ|­mØăùđÛ”fÙÎ\đO–fXµO._¿ik4³ëº®₫ÛĐf‚₫HgGÛ-à¯@#™·éø_‡jÿ¥%Æư:àûăŸ„2‘F•7ăûIEND®B`‚cutechess-20111114+0.4.2+0.0.1/projects/gui/res/icons/cutechess_128x128.png0000664000175000017500000003244311657223322024450 0ustar oliveroliver‰PNG  IHDR€€Ă>aËsRGB®ÎébKGDÿÿÿ ½§“ pHYs  œtIMEÛ )*tEXtCommentCreated with GIMPW IDATxÚí½w|œƠïÿ>O›®.Ùªî° ˜̃[HYÈ&YR7 !¹)7›Ư´­¿́¦ífóZ̉óK#$Ù,¤Ü  cƒwcÛ²lɲzif™§œsÿxlCÈë&±etü—ÚÈ9çs¾åóm0³fÖ̀Y3kfͬ™u¬Ă#ö̀&üKœ‰ojoOú!ÓĐ/œ_ßqpĐδU[[G³^¦&anÙx8=rí’Úí3Gà©Cư¤â‰³7¿ĐµëɽGYĐXË…‹UK]•(|_QƠÑă]ü¨o,óíUsêwÍà Z/ ä~đ¯?}âíCă6Bâ–A*f±vaçÎo ¹¶‚¼ëăKEÔÔˆ›ZpÏÎÎ᯾jeKׇ¿ư_¾ưƠ3˜–ë¦{´{₫eÿ£'ö0+”̃¡.4"¦Fm2Ƶ+çrẹ́6¤R˜º@)¡4¨ŒØ,›É₫Å‚¦Úí€ÿJ€q&½™îŸüÅ?}î̃Mä!P€/%>³çÍæhº€¥‹ÿJ(Ưé5q£ùÆë¯Ï•@pu&@;“̃̀₫î¡¿éÍ(ß—‚ĂBµ ^µz>YG¡ B!‘HJ(tMcÓú߬?¼{Ë*`1Ps¦]3ƒY÷ÚgÛûª=)…¡ t] ‡0uD”•ó›P„P(%E ¨P)‘÷̃ư–7뀥@ơ+g̀´ï£-Ơqµz~£·̉›ñ¼‡ă¸$£·¬[Â@Æ!jh%ÓG¡JGÄçÿñơ@Đy¦‹ÿ3OI¼Đ—¹®ÛÖ©©«£Ơ2¨NX(–À•°¬.JZÔÅM Ç“8¯Z>í>±áÉ,0t‡h4æåóg6±tFxGGó_øñs]̀8H©¡©i\¿|wüô·x®‹fè$S)V¶ÔpẠ́ù,œ]Å ­HÅ#X¦IÖÎăæ&öx«Đó·]»nÍ₫#Ư=j§ñÚ|xtàW»z벨uxS̀ªŒaơđĐ–½ạ̈.©kTÄ"¼ù†‹Ùơü^}íÚêG)BĂQ¡ M­mM¹;Ÿ{zé?¿ÿm=c#ĂΙ¨¦µ¨”b8S8§}([ïú2pú”Zè5+ÎcÛ÷“Ë»øJ!•B×—œ»œŸxgöæW<Î́(/qJˆà—B{Âơ%£6Ÿû₫/8·1†D l WJz̉y5o{çwú«÷… 0gp Ö›Ö´p^[ƠŸïÇ•¥‚Û¯ ¦ª‡:“Îæñ¥ BAÄĐyưe+¹÷áàöËĐ&˜âUÏep$Í¿ø-ëæT•ü>!¯Dר­Úν́_?ơù/\‚À˜À)XyW¾Ă“ªtt" đ,­‹̣Àæ=ØÅÛ¯.0  ÅXzÏ÷K7ÿxRD!È\íăÇ÷=̀9M©à©  ×Wbç±´ºđæwư胟ø—Ku]KPÇ3ø3¯¶µmUD !¦&8»¹_oÚÑơBFP„ºßäƠĂ/¼ë¢%¾Hç×bÈäv·wñäægi­¡kØbO_V½í}ÿû¿—­:±iZÉ麗Ọ́Eï뛸Èóç4W’Œ˜AbPcº́9ÜC̃ơ·_×4 Ó$‹0‘ÉàùrRïŸD—T‰\ [÷0|́0Í•’¸Iù$1Dûˆ»ûW>TÙØ6Ç4­ÄtÜÏi÷‚•R̀JE.Éy’á¬ËuËHZ/¨çû>E&ư„·?fé¼éêó¹÷á')8~‰î=§{¼T(lÇcóî¬lŒsù‚ƠÇYTg^m”Ú„%z3~Å“›·<¦¥j›uĂˆM·=vŒ‚̃t₫"ËTÅ"4WÅÈ 0œÎàz~‰2 T"æ˜ÈäđdpûEÙŸ́đ: ¡¡k‚+/:Ÿ̃ñ̃ñ«ÉFªq=0‹€&]cZí–í;î?{άkuĂè÷=/Ï4‰LKàøê"=¤lÓy×ÓÈo}_¾`1,f¼åª5üÏúÍäÜĐï?ÉÉ(¦J…"¥ÜrưÜ÷đ Œeøæ½’ôÆ(bÄ—àù Û‘<Ưă.Ü}¤ï!ßóê ĂŒ2M(ăi€ >û¥k¢¾¨Ç¥‚}džùË«.`^c-ɨ‰.†®‘ŒGQÊ'“Éâû2đûßí?F-ƒe æÍd868B6ï2Èü„ƒ M`‘ ̣®äé^oñĂưx›BDfđ'Xßçºe¾œäư“ûñăÇwqñ¹gsÍÚ³HÆ,’Q‹[.?¯₫üQ́‚[̣ûUÙ—K1id`j‰h”ËÖœÍĂŸ%Wp‘Jâø>c9>ưƯ_°´Z/QÆJ(¤ä=Å–~oñÓ/½O)U©iztäƠR]i»~éà<_̣|×ă¶ĂoƯGÎ×øÀÍWQ_SI:“Eº\)OĐûâ$–¿R M HßuËơÜơ‹ßbÊ]J(xcY›Ï|ç^–Tk(%@JÈ9>{Æô ¶w üZJ?%„™Àq¹’u¾ ̀´‚+éJ“w<\Ï'[py¾³Ÿßlëà ·½†û!„ÆÉœ¾ô>  Aܲ¸îâµlxv»€#%e¹£#èù ¥'ø·oƯẶ=!—I‚œë³mĐ[óô Ư÷)%“¦GfđGZ_](DÉ[:; %‚TPđ$y‡mGyơepö¢¹¤¢4m̉º?̃ơ+~´L¦†ê*́=ÔẼ™Z Ê@Tp=FÆ3üÇ?g~x2LE%AÖñØ›ÖÖ=Ó̃ÿ[)ư”ĐNOI0íàKµJ #†Àơä”»-•À÷|îfkVĂÅ«—’ZèZđ{'ă M`:o~ơUÜưëÇÉæ0Zx¢1_”×§4Íïú4Çp}9) ¤ ëǿö×n?ÔsŸ’2¥é§Ÿ$˜Vx¶śÜâù9¾¤³„lÁAªÀ€®i,m®á…ÆómÙO]c+¯»ú’±–® 4!ˆGL̃rÓUüđÿ<\ʳKƒ/O%/J¡È;>ƒé >ûƯŸqaK‚I›@ îî|Pú§Ÿ$˜6ØW´UG.κD Ư]CØ@'†¦qV[»;ƒ„Ûơyn7Ăyx÷ëo$‹`–@(EÔ2Xµt!ưƒ# áx*ưÅ/~]₫¹*‚ àqlp”Ïßơ+.™['eè<©Íỵ́Öîè$™À¸VG¾ë|)Q(ƒ8¾,R„!Đ5ºç¹øªh™{́fëá!>ö¶×Q•Œ1 4À4tªSI.:g1ë7o\¾²[^₫±üóII @(lÇåhïŸû̃ÏX×–Âñ „ÑœÇ̃1íÂí:ï&È*̀à\U1½^×®¯èœ`l¦˜ TÆ£‰À …ÁMÍ»>džÓüôév>₫®7PS™$µˆZïxƯµ|ư§b\|%§èựƒ?å’@¶ẳÙ;È¿ßùs.[+ƒâ"!„á¬Ë Ùèµ›wîûÿäé‚i€ÑœWƠ° ơ a»₫¤Q¦{7T&Ïáùjjt(¸\ÁåíäCo~-Ëç·ró•ëx́é­xX̣¡̃©u2I ¿‘Ë;tơrÇÉ̉úXÀ!d*!`<ïrL«{ưs{Ú¿C`jÎàåz9_2¿6Î3í}Ap§̀QÓ4Á²–:öwăK¿”ÎUbÿ8O.ị̈ăÇwsÓå²|N}ƒø2°-ÔI,₫â¿—A„J(r‡ƒGû¸ç₫‡YÓ’"1˜WåÜæç·V°¢!FSKË͇ûF6́8Øơá}íÇU¯}ư›fđ̉7¨íJl×cyk=1SÇ4t4“B4jRt‡¡}}æ₫¹¾¤w8MẮYüƠ —Q“±Œ0S‘ ^$°wÂ’4©vÁ¥ăX?u°²̃àü9•¤"z˜d yë́xUí~äm¯íMÛO|ó;w₫Ơ ^êņ¯6±ËÚ¼ưês™S_A"b kM ²BƒDPuᣣ€“1‹öÁ,VMÿö₫73¿¹T,‚~ܶød@8¹‘H£T2‘¨æ‹÷oáïÿû vvôà8.1ƒBÀ]¥`¢à1bû—e<ơ“££¶É~±ùùöF₫ Åi•34̣¯`ßÑ!¶êăƠk#•ä7[14*̀ lĂrª·|7u fWD9æH"†Æ̃Ÿ¿ó/¹ç·Ođ́óIgóx¡ÇQ~¸ê$̀ @ ™lJ¡ À2¹ùꋸïé½LäÀæ'÷³ k+¸rE K[ꩌø |©p}ÅDÁ'ïsóă6}ƒ TƯ<₫DùÓ R¡1ïúdl‡_ñGKmï¾fcơ D ¤ ÓºÅq»'@‚‚ x|)%–¡±§?ÇM×\Á²y-ü÷o60µ)¸Å b15&P§)_+0MƆZr¾ ïúx~à'x¾$WđÏ9ôf¸nees›ÉyÅ?éxæ“ïGXt£!^Ù*ÀS*z-L®àrx Íë·ÑXgy[ç-nÁ̉5¢f²%¬ =ĂĐ{$#ÆR‚£#YơÍüóío¤±®D4¶”9Ñ8^%ÑDˆ[&o¹é Ú~ˆ‚ç…„‘(¯ø28íåsfÓ;áàI…§‚<Äyu n¼ụ́.à2`A«?™§0mđ©_l®–2H¿Vah68ăzØÏ₫₫ ¾u×OØ¿}37¯jâ5ç-¥:#10u-lxB¡›ÛWG‚‚¯82ŸúÀ[¹èœÅT&c{¨Nä$rJˆË´rp0‡”ªÔ¯ \üÄ"¯^3ŸaÛÀ¥å5 ~ùƒou{N¾ [I‚?qÊù´QT¥B)ŒÀ¯.ÓíR*̣‡àÙí»Ù²c7ƠUƠÜrư¥Ô¶,ă¹ö>Œ„úV¢ ÓÔxSIÏJÓ;Mđªk¯dÙ¼fî~đIÆsy _*@⨠1 .¿`5?úçO5<•Ẩu*1–Í™M×X!¼!P³cR₫óÇ?r” ;Ù(Đ¤Ă¯_Ùh©N±²ƒM)KLœçºÜu]\ObúùÎO…iÜxéy¼fơÙŒ¹:›öu˜$,M8ÈP=ˆ)£ÀĐ g̀¦²qŸ₫_ÍÜq÷%—2Œ&Ừ@yGLƒËÖ¬à@o¯tûÅäÿ)ñˆÁÛ.]Ê‘Ñ<†¦…ƪ¢.Ÿû‡tô':€Î₫+^\³ Uºơ N’Ó§Èçó̀«‰…€Œ®¬]`|"Ç/×oäKßø6=ôkn\ZĂkâø f k“<°BWR‰ Ç`ß|â¶7qáÙ‹©LF1€’*ê~!0uÁê³–ñ|g?®çOÍAT ËĐi¬IQ]U‰>µ6Aù£½ù{~üĂA‚₫„]ÀA ø“fO vD´₫¥ `<ï!t£$nEÑèB’/H Âcû!¾~¬›%óçđɽ‡æ¤iDLƒQÛc0ănbXjV¬#ˆ"đ®»¥ó¹çáMŒel a‰ỳ2¹î’󨰧 Ç“¥ äɪåÀè|ÓÅKéµ±t¥nc₫¬*qëƠ×-ư 8̃~ïO¹¯ÓY©¬)%s'́ đ¬ă×§ÚL%̃jW)&́y;Ǿ16èGèæ¶Ú gU°hvéLÎ$*ôÎá ă¶DQôÛÔ4Ïă“ïnä«?ù5#ă8®G,brị̂EÜơè¼°̣¸¼ÆÀ2t4Ö`Eă˜n¡tû…€­=0¼g× A—²Î@a† —™ˆ/̀æ É™Đ(®LÁ£*,ƠN1ÖDY6#£?ă’s\|©Âc"ïpt$CuM W-ơtăœÉ×¼ê†äÚ‹.KÍYzNemS[t4ïÓŸ¶é+˜üóû̃̀ÿêíáºu«øùæư¡‘zB Dа21¸ơ’eÉѵâíW‹*ĺ÷̃v$<́¾Pôw…ªÀŸ@‘øÉÙ=ơ)Fr̃T¹_NùHÄD+;ôR`â÷-+ëKtMC3¨ BC÷ÑÛy(ưío~½ÿÛßüºt4#vÉ¥—T\yơµUKV®­ơk«>ư¿̃ ~½qZ¬R=yx·đ}UºưEĂ2jœ¿¸™á¼"bˆ’ 3u]üü»_é)cư Û!Àùśë´€W°3cyDDĂ‘¨©· ¤RHU<<ˆE-,Ë ­ë"_ BPRÀ24b±]cÑ́JÚj$¢V ”D"f4&Ư¼Ư  og éUl|âñäÆ'Ạ̈ơúæ9oyó­5ç₫Åí QŒ ’á§k‰¨Ékr`ĐÆÔ´"]¬Z“ºéï?v È…çĐRÀrån >̃kh­ŒÙƒ×\°”¬ă‘óµ–¤w₫̃öĐÇƯ¾Đü³µªŸ6Ø3˜k[ƒ›́)xxÛAúÓ¹ĐJ$“qZ«¢¸µ´÷§éîëÀÍMà:y”(=B@"å“ûavv c;a(ªD WŸ½nnˆéo¦‚ N̉UQˆê¿÷=/Ü·íđÇ¿ÿØnc,'…” CרNF¹`I+sJ6‰̣G»ó?ưÉO†B]4ü½áß”38nơLx‚Dt«4²? dÛI“ÍdYÔ\OgGăÙRJẾ¾Đ ƒCJĐ¾o7sVY$'ƯƼ糯?§}đ#]ñµ;¾øtè…ÿróf¨b TƯG~Z»ôªÿ½qo'vÁ#1yơ…́ëÏbꓤOcuRüƯ­óoÿ`¨÷ÿ9ܾiKuŒNÚD¯¨ŒGZXJ¤”x¾ ̣₫Fs´µ6Á¢0Àâ‡Ï \Áàc̃q¸÷·8o~¦¦•øz!/928¦®|ưÛ/êÂÛ®…‡ă„::kÇÂÜư/Ÿø»ï×Û[•ˆ¨XÄ ¹6Åü–YZÑø x…£Û7mÜđxº̀í;¡đç̃×i€/¼ăŘ\Áói®•&‚ơ­'%»:z¸lơrLC/åƯBQæ x¾$oçpÇúJá^Uæ\<)ƴʺˮ¼z5ĐÀ‰ "U¨«ƯPl!DÿÇ>pÛ?¾ö‚¥bvU\½æ¼Et eĂDE×̃sas}ÍSäÛƯ³i/÷v‹F¹|y+z$JÄĐ9Ü;̀óƒ |n\VÇWîú²v>¼ư“?-ÔñAÁˆÄĐuZg×óî÷Üή!VµÖ†êÁaă>*¢&·Ÿ[Ơ³|é’­ù.NÿeÏ[Ø´}(ăàø>®TÄMA¦à1’MsïS@hóg×pĂ¹s‰D¢̀k¨ä-¯»†¤IoVa{ [˜ºÀÄgVLÑG²: ˲XƯœ P(°~w'ÛÁ«yt¥¨Ÿ³¨)ª\›Hóö¦ơ<ÁéÖ,:Ÿsưp$¼"b 6|_âû“éƯ{:û9xl„erĂù˸ïÉ­ŒŒ@1ËW…aâ2cPk S±‹g%Ñ#ä î”Qô/920Îç₫ă WüÍûß»‹ ’—åÏÂ}%SÈç=)΂b₫_hn‡½`¤%%¹B0J&ă*²¶]pÂRjº ÓA^Lø‰ưå g¬[tÙ¼ËƯ<ÊMk`ê뢤®ibéÙkÚ@´†Á´TÓîûæ„.Ô8,Ó¨ßđŸ„æÇ”ɨñ²_nZŒ;“1Ï÷Ÿ ưàê+hB0Qđđ•¤g,ËW¾ùí+C5đû²…fđÇZ¾”G7µRIØK]ê3Ô F`ÀÿkaêxѨ̀\îüΟŒ**\¤Ï—êÂ+¯Y z:ªéi¸hÚ!€„¥#´ ÜJN΃œ" µẽ₫”Ï'K¸ƒË0ФWjî „À÷%¹|g·lcaS-RùxAITÔ5V­½à¡˜vÆàô€ôÚ£FĐñ3†nB©,Hç} +²ÔrIDAT3‚ @ ¡ ¨4́r ¨J˜˜~>ä &£…y×cÓö½̀©²èOç‰Z¸_uÓĐ%œvj`Z@¢‰¸©#TĦvú*« à®̃Kªÿ²ú1M7É{²”P¬(VJ‘s\~|ÿz6ƠR5¨‰Á́‘Á(A¢H1iT̀àO¸,Cs'Ÿê˜NSU”DÄÀ {«pʾ{øÏ %'y!†®3\Öƒ@ˆàûÅÔ±ô8G»:iHD ¬+™H™!!TI(2mÖ´3Zjêg‰„5˜K»Œä\.Y>Y55cOg?ĂăYß/\±‹˜,%ăäcă„&°)Ʋ4M`F @ ™&‹Û9oùBl©ăKÁpÎ%jYäm[#èéU€`„ˆ§B}¬_½®¸Ă; đèîNê*â\¸|µ©J)†ÆÆyîPRJ**«IÅ{ñ];9Ñ`TJ¡ë:±¾¦H¥R\¸b>­­­ $̉÷8ÜƯÏ}¶P›Œ°rÉü`|¬ị̈¯Ÿưüâgv́ÙÖ±àĉô3øc­û¬‘¬ó˜ăSÚl¸¾ÂÎ;Êæé+QĂ U)._̃Fó¬:†ë",˜Ọ́"Ă9à*/L–¶5ˆYĐÊS»̣ø¶}&„xáLK¯¤2j0èÍ£ê›ÚÏmỤ̀ןú̀g^øê|ö¹đG\Ï÷ŒsVS=éü磆öÉ‚¯”¡7ØS1ô Ü—¥¼?€®Á1Ó–ÏÍ̉ñ́£lÛ±Ï+ÓíÇuÿV*èäuñ¥—âZ)ö:J̃ ¦†úeÍ©tMCJ0Bz1G+á(¡ÿÛÿ÷©/¾ưïn8oùü0 S÷<ןÀÿăÚz4gåœç4M¬” ׄ0µ2=.Ê6‡9~B„å߇ăI ®‡]ppƯÏÛ” RÀóÂÇ.xxÊ'’‰Rơ±PS‰„ Å\0JJÉÂy­oï\½°©₫u†aºçÖÉ"§­°₫à0W-©ü„¦‰•¶#É{Rä=ŸtÁ#ѧ:ê8hr4¬8í'}”‰+ч2ü ‚œr#²øG+"L|\?hïz’ƺêk{F&~çyn2‘LÖéă§%f¹fQ-ưă…_̀JZŸ.xRMV‚9û® Æ·G ­”î憄@aƠG4}Yù¥îLxÚäX-8ü¦J Ç á+p¥Ẩs¤â± ̉¹7¼á­ó8kNK8:gÜvû,CÜ\đyW‰˜¡• >”R«¶²pN#µ•¸Äơ$AĐ!¼.a!•bWÏEkQC`hM¡k¨Ë–üûácÍ›¿́‘Ẹ̈öia6z)ëx{3o©ç—µưK‚>O1³ù₫£;ỸZË̉–zZªHX™¼ô »~!¨ˆô¤m²v#‡q¤óhØ.&8~ß±Oxû†®1wî\j©J%™×TGÁñ(x>z˜{è‡]J ]££gˆƒ=́:t”+W/Ūª'aéÔ%Lâ¦Î4V€© ¢††Ë=ƯR_uA¥°{ªĂS.6vŒ²¨>₫ª Û[1ơ)=}̣¡®Ïºư£Ú{‡ÙƠÙGÄ0ˆGL6Ö°nqm³kYP_AÚv‘J2QđHF +£ÔWĂÚUçPnâƉ³ÄW¢2ª3j{ạ̈A#i]Ó¨ŒYt¦Ùw¸‹»ØñB£é ̣‹®ë̀ªN²öÜYèBP3É8₫äL‹Åºđ’«¯¿tă£m%hă¼â%@O:ÀñƠÂê˜!& ₫ ?"†Àv%ïèàî'v‘Í»€@Ó‚[1uâ¦A2ạ̊­,lªcnC³*c åO´¼ïáÅ7D°ô¦s´wơ°ó`'Oî<ÈÈÈ(9Ç%_pq}?(4Q Ë4¸|ÍYÜ₫¦WÓZa‘s|´0S©h´r®¤?ăí̃ÿÔ —­ûAwĐÑSiœr p×3Ư5éd >1S£àMuèmWRŸ´è™ n%ÖÏWà¸>ë“.Ă™AKU Ïó&›M•U G,α<,>ûÜ‹ªç¬ííL4‘8eUƧ}AËHOÚ>(% JÀV²$$„¥3÷¸åÂåœ;o[ơ±«³;_Àv}\ÏÇR´JWè´ïƯÉ₫½Ïăû̃ y›G؈²†’‹FYzÁ• eÉ H©J!uMLz“–Yơ¬;{k—Î'¢I\]àH5¥×PÂÔ9–.¶‡RäÓC…Ñ̃ÎY½BưW$͵s_‘ø×Á EK×p|Ỉ̉QÀhÎÅ 9̃¦†nmiàMJÑ;2ÁÎ>6íëfÂÎc;¨ÆT„Íé|ßÇó₫°½Ơ„ÆøèºAstCĂ2 b–I"eͲ¬]6ÅóÚ¨L&˜°]”RK;ÄLL•äR€«Çuq‹ïí.  ‹¨ ñ+̀™]û½‰ü×ó"ïAm\ &vç'“1„ÂІ¦Ô¬‚êT‚ËÏYÈëÖ-§{xœ½ưléèchl‚H,NÖ‘ÄcQü²¦Ñ'%„T‘ù dƒe™Ä…CK]%iKĐPWĂ%ç,fÅÂ6æ47ăKI¦àaèAªXÄ(̉ƒ÷ö„‹¡ *": Kgo”@¢TSJç??óoư­g!KxÊ¢Ó 0ûuÿ0ƠĐôvO*;<@{ßKkh««Æv]Wa„ ]ƒ˜ˆïL̃!p̃̉6®Zµ€ŒˆíÜ[̃J6—C©?ॄ½×,]Àµói¨«¥²"ÉX¶@P,⢠$¤Iđ(©p}‰'ave”cCivî¦‚¼‘$né̀NFÄW¾tÇÑđ=ÛmâNi·°Ó BDnÿđÇÖ~ú3ŸƯèKÉlå…î!t]ŒFX·¨‘³ç6ĐXD!È9]+M“cDƒqq*¢:=iù¢Ăß_ᦺFc̉`ÄöÑ4JG…A"Ẽ—Dt¸¥Ó=8ʾö#ünÇAú‡q}Ẹ́…m¼÷ 7RpC#fê$¢gÍ©gơ¼Ù,l¬FyËĐÂD µ»:nĐ;^àÄ©Ñ Ô% Æó~É•“€ïqˆª„…ô}^è́a÷Á#<½ûclÇ£àxxaô°¡2Áç>ôVkR<~ÿ½ư·½ó Dn"èÚñöÂ%ñT"¾¸st”˜eŒ|×S\Ÿ‚ë‘¶Çm6ï?F~á¼*Ùç2uxâà ®¯˜W[Ë»µ!½Ï8ÆÎ|¨‡"ù“L$x¾½“₫‘4ăNáö²-€É­!°}Xv ôäi`:†¦qö’ùœ¿|R̉94Î#»ºPJ¢i‚¸e°r~öOÔÔùá7₫«3tûLN“ ¢Ó©ŒI×+gw]yɺÖ%,VµTQ—2ñ|°]Ÿñ¼G×H–Ă£yæ̀ªáÚ•óXÔX& c;DMƠ fó̀–파ŒLáơƒ̉1mJ«Ø{¡R,:Ơ•ạ̈ ×pàÈ1 M#q骥\wñÖ¬>›‚ÔX¿«“ö!†Æ&° úÊ$W¯œÏk/XÆå+ÚèÉ«YIƒ×¿êÚ}!ơ{4¼ư#œâS§“ @ôHïĐe%ÖTÆtá…Å9Ç£s$Çcă gœRÀ“’…ơ)êSpóT'£|ö?dt|_ªr:₫¤wƯË禺‘eZ¢ø­DÔâío|=ù́8±YhB°­½‡¾á ̃¯iX†Fu2Îgµ±r^#M5)œ’ªR¤ ’ß₫èëGÿåÿ¾“ cøáă”7<ỰÔ¢÷=ôػ׬»økPä]‰+ƒ©à†€Y©ă—1›­GÓ¤í \+Ă˜û-«yäÙ=drù²Tî£{¡"f4"<%0dè¬[1Ÿo¯ßÅÀÈXI÷[† ¶"É¥ËZX9o6Íu•ôç™(øèBĐV#fÀî̃, j"ª¹:^ôÿw‡₫ÿ¶Đÿ?¥ÙA§[Z¸÷Ú믺·k8û_‡†Æ­»Öog̃́Ö.jfyKöKÁ•Ô$£¼ym±œË±´ÍÖ®4×goßĂCƒlÚyÇ› ½˜G 4qRzX»‹i‚DĤ²¦–\.Ḱ‚‹'ƒnå1Ë`Å’E¼áêuüà«ÿqèîï~£÷$́_ît¹q§Û̉4M«‘R®˜¿́œ[₫ö£{UóYëæ±ơ§v·+Ûñ„ëKt!ˆY:µ\~Ö\–µÎ"³HÛ. “öaû¤CN<ä Æ2cÑ̉5*£:c¶GU>ø•/Ư1ääsÅY@NxÀăù~ư¡Ï¿'ưc̀Ôü̃凨nâ¡Í@ă—₫ë‹}ü×÷54·Ơ½ï}··ÜtÍæ f]că ó÷dh̉ËR‡pºå "¦¶˜Q¥R3Ï—Í“ˆÅU2¯¹̣jcFaÿæơÿ¶›³ăcÅYnHéN„¯w0 øô…đ{§ÓáŸÎ \B[¡JHôàiÁĐ~¬’_ymóÛßu[ó¥W^3ûơp=”U%c@_âùb®º¡qö²¥ŒOd ‡vo₫æ—¿8p¬«Ó.Úá¡gÂC*;đ̃đë±đçÅ€Ó®\|ºt²ĐÊÀ#èĐ]KĐŸ¯9Ấ ©đ9'oÖ¤›º‹p\øK¶rBà:y%¼_vè…đP‹ăăËoúPèë—úi=5l:v¸ÖBƠeäÔUôè›J…¦¢TàÅ«rµđûÚË܃¢A— Ù»²Cï%ÀD¨ûOûCŸî(íE0UDu¨"êC#2̣"‡¬…†¦₫2ö 8ûÏ.ÓïƒLƒ̀•‰w97ñLX"½ª§²xÁÆâÓOoºBkư¦{Vô½ùw‹¶½ơ ·­˜5̣ç~óØ&.øà¥éELmTé%xiØ@5XxĂăëöŸØêÊçMƠY 1ä… TC̣…c Ú²v¸}ÈÓ•@9KÜ9±={÷ărÛ¿ừ}Ç^™^ÅÔRx‰ÙbQY7t`[̃]ø«»â!A¨˜>a GÍÊÑ{´³qĐcsÑÓ~¨DÖ‘dm©m)E[Î"kKr¶E5Œ¨záek{Ë:ư}Ÿ} ü—Ÿ…³fÏ«V®ÔéUN µ±-Ø8xơ†mưoºåñ²T QZă:9[`»Yö›ÖÍ1s&1¹«@É ÙQ¨…YK"…ù !è.8º-c‹Zé¾²w}©Tº́ĐÙ“4½R0H µ‹ưđE|àÔØ6è¯₫a>ÛúK«Ji¤8¶$ăØä Ç’ŒïlaƤqœ´÷Ƶfé-ûl.úX²¶DJk-¥íY[·¸–hÏZkÖ÷WsÿỄ[.8rú£'y–¼ç–ß+!$Z«ô@jÿJ»}éö/2̣?~ùç'è-{¢́…DJ)À’Û’¸¶$ëXd‹œë2¶½À¾ÓÆpÔœ)ŒÍ[́(”¼!a¤‰´qö–º«àˆ1y‡­E/̉Ÿœ¿rëơo?zÖZ@tŒéÖ½=é"€Ô₫¶º·̉ó]:fÙÆúË5ߤÍ&¥@ mIK±ṃ›B–î—fOăôy)ÖB„€¼c‘u$• B)ˆ´Ö^¤…(=¡ÍE!¶yëVn/_ü^ƯŸhïê–ƒ}=É“¦iÂËÈ́ô¼8í??ŘqƯ§F1k·öêª0R(­'P„Ö(¥Qh"¥ "mK̉’µ9zv7m("X4¥5¶H)±"ïJ2¶ÛKZksäô#ft^²¾¯̣æi]ù©€¨ø–‚@ ©í.ûäw~Åû_5§¶ ]ùĐ̣Í„ #B~!ñÔ É§5Zk”(̀÷YR2{b7µPD×(B€̉œd¥ˆ¿çûæNøJë}&äư Ÿ¾ 舿!Å ÁKÜdz ^|öơ¾÷^»tÖÄöܤû–¬¦—₫t́ưEœ¼éø¦Ó(Ø– ëÚ´äs¼₫°™,̃RÂ’-@£ÑóXZ£4( ZaÀC˜ï+¸R”ÅçŸ|èÀ h²q4¾w̉ µƯeÿuê¬Oܲ`µˆ4xAT'íä(‰x’À’×±hÉX¶×Tú+yÛB@ ÄÈc«A‹ä4B ¥Ùorï₫à%7ûCÀPŒo4aNZ*H#€Ô₫‘váƠK&vµd̃öÔúj~ˆ©ºÇê÷ăñ%!mKPÈ8t´xËáSY¶½‚%Í×…0̃˜ ⟮ßëq­.yđ±ơ×üä;>0˜LºÖ8 °IIä4Híoï<|̉±O¬Ù‘,U´*¡ă0_7nB₫¦“¬ă¯YR’µM_À9GîÉ#ëÉ»–¤~VÅsY ‘̉brAFG¾ñµÇ(Ä ;(ư‹¥@jÿ@Ûwbë_³CBJpm‰ëØdl‰k[8–iü±-‰%E½ ëX´ä&vµ²Ç¸j!–;% v4{ÍØÖ ×ÿá[z¶å€®ØëwÆ@p›¼¤@jÿH»̣áu³‡ªáÜ­½ESÆË8¸¶eJ}JÇ̀½iäIH<Kr®M{ÎåŒĂ沺§BÆ2ÍBÄ̀’>! ˆæĂoƒ¶Œ¥?ÿŸ_ÜŒ!üª€z9"÷O«)¤ö¶÷û9Ç–úí'î+tàóÔÖ2;J>¡RKe‚Ƕ’‡j¼0"̣=ú;’–¬ẰIcÙwB ® Ÿ±PMƠD  tĂ+̃wb‹øØ¥Ÿ\»iơ²fb/A ß|L90íxX½Ȭ¯́ëÿ{lZk,¡Ég\Úr6¶LhË0¦Å%T‚Pk\)—ƒÍE ^qà”úªµPQ #ÂH#¥ R hl)°¤À;MK±`Œ̣fṆD́í= ûßlÖÄ·M@PÁ ­¤@j¯}ÿæ‡Ä±‡̀ûȦ¢O-¨ ̉è¢W÷̃ụ? ëÑ8–$ëØt\ö›Ô‚ˆ<ưƒä;»ŸÏ0½3KÁ¡)ÿ×½ˆ(̉xJ! ̉´e-î¾Qí¢O}qJ±T ®úÁÿ,Ă”₫¶[ăC?ˆ!} !˜Z¤ö²eÛÊzᦽb[I”½ˆ@)êɺH*€ˆ‡Ëx̣KÑ“ưø6DX#Â:ZH7KKk;ùŒĂñ³;q³ZÛÛ™Ù•e|k¥uS•¡ ,€^¶oÙ¾=ÜzŸrr½kËV5 ẴtÔœÆOœ,¶mÙD ¤ÚßaG}ăNÎ>tÏC.<|̉ăWÜ¿†Z ¨‘jäîºé•tZñpễăØÖ_äwwϧXññCS“R` eIÛ"çÚ´f,!øâ»^Ë] –3oÖ4]7€-%m8×’dlĨ±pm¡B´d$®%tƱD«#œ8ñÈ©.Ù—”Z ©ưmöä†Áưđ]̃£K^(üHÅyû(4!â®?p, )á]GLå?¿R©ÄPƠ'£zÊ %H)q,IÎuhÏÙ¼âˆĂèt5,XÄù§OhçX´¹ˆ̀ ‡å$íqóÑÁSÚèÈX7ÍĐ̣zL• yP(—ˆ¥}/»ôË:f+œ»p}Q‘QSyÏ„ú UŸæ)…ñÖ§î3kî_W­R®x~ˆF‘¹ù¡Â÷ÍÇJkC›S̃‹ïy˜me¾síŸèȦu䨄^¨L**ñ}5PÔ‚ˆj đCÅă ùêu¬î»%æ’+u,)¤öMkÍY{wMƯ2XṢD¦̃ßüơ]~)í9—ưÆçyđ©UT¼? ‰´ªO êø1„KH, Ç:‡.¡8T¢g°Ä@©ÂüôæMlÁ±¤I=4(•Œ››iüPá… T̀_7Àô®ü«ïX´îºøđ'BVü̃J €Ô3‚='´}eñæ!*Eâư“†äà'³Iø/…@)Í›™Ä%¿}Ô‚ R&z0'¸₫–0Ư„n&ǹGï͵w=B5ˆªÔ(U¨T*|úkyí¼qØ–‘%j30$Œî@¨ „ nZ²ƒĂfO<û¿¼æ| -L )¤ö<öÓ;Ÿ ơkVî(É0ö¸z„÷o†ü³$Œïȳ­¿Dß–T¼€ ŒLô0bâÇÇ±ÈØ’C˜Ç¥˨UJÔü/©z>ÅR•âP™¯_ơ'̃yÔ4eHM‚Éï‹Béß-̃.Î>ë ÿûÆ ß í8])¼t̀J/Á¿Î₫ø?â¦%Û¾–u¬W,Ư2H-Ô"ˆ'ÿ}ưß,Ë4ñÔBÍ—ÎØ‹₫â.Ê•*å!₫’’^̉û+¥aÿó2y¾÷Γùà÷ÿ@Ôü€0æ’[­VăÉC\rú₫<±aÆ(hLd$ tüDkûjââ Î>ïÙï®Ơ‹)+¥BMB))˜F©fGíÑqÊ£kûD¤¡Ú™@Hú §í=–ïܽŒ ƒeYÀ¶mÛ9iv~¨ûtF[ %”Hàßü¢ A[ÖùÜS›uçĐ*«ë„_Ââ'ù¿€ư&·ƒ Y»aÏĂe?=̀û›×±p²9ö™9'.¢Døaˆj’oÖÓñ¿5FP¬T©U*\ü“[¸đÈÉ&¥ 9 !Ä`ad¢™ëÜ.>`ï3~zíß) @ €¥eÀ}ë/«g4¹ăK]±CT}…éºGN¼âY…Û’TÅ;Á×®¿—₫bÅ”ư"̉jø$Ÿ”XÂ(ç]›óO=[[ÁöMk¨ø!AƠg FNÿ‰úÔ¥LÄ¢ư*÷¯́á¿Î>Œ{WôăZĂ„ơô, ½l{™SŸw„Îw®xä̃?oL2 RA‘4øwµf9yK±JjîJñ7–ñ²ă}̀¬.®điv́è5M?‘B%Ë;“”!f₫-i´+"Ă ó¦³`ñ¼ˆøđ«ç`ËBêˆK_4_½êÏ(i™F¡¤ÅX ÏÓ“ûQWÿ Q#‰”"CJURƠăW¸R¹̀¬î,‘2¿¯æ0ÂÀA¨Œ€éö’/Ø\-,ßÔs›Rª „h#]5–À¿ù¸¶uÁc ̉‘V]œs¸d7±ÔxẩSöâgwù“?iI-nß­{ñ& °0̀Ʊq\—¹Ó&°è™•xATרG » ưô(ïBé¤G d°\£4Täưßư=¯ß‘̉±Naœ¾H⛑ G’iå{VôsÈ!‡¾ùÊ›î~ †ïLA €——4µăíµ@ë¬#Ù0PăÄ9cÉ9‚ŒmJ}É¢O¥4o8p7̀_†…™×7£¾M¡=—7‡-c[8Bñ®³OăG7ßGÆ?ÖH¼sƯ_8a#ӀѠ"éTÔZF5?`°Rc°wÿưÛ;ùĐ±Ó "MÆdAÖ–ñMqKàX¦©É–‚»—÷p̣qÇ|đ;WỰNLU`äê±ÔRxùØ¡SZóµ0” ÖBöêÎÓÏul\ËxI[J̣›§áÏóQ®Ô‚¤y'.ûé†è‡%L£PƵÑm8rZ+ ?eV7Mü ưÂznĈ¯G -‘6#ÄU/`¨ê±uóF~v÷b.:z2AÖ²È:y×Ür.y‡ö¬M[Ö¦»àĐ]pơ3[‡ôo8íS_ưÙuç7¥iyđŸdé₫'ÚÚ̃®ª~½H1»;Çï[èjB­8s̃Dn}x O­\K_¹Fµæ¿™ø‹½±cYä26×ẩ·ŸÅ w=ÄSËVP,×đB“6ĐT]Đ£€́ÂÛ)Äl%:"tl‹BÆeL{qmỸư–s8nV¶=lK0T G<®ùư«ñˆ±h¥Ó» |ơ{W~ü«—¼ûF̀F¢dóPDÚ1¸û8©ôüólJG6|z[Ùv, ˜|9ˆ4ûMî`éæAªbl>ĂØ‚Íâ•ë©Ơ|ßxqF4ưè¦ÿŒc“ïÄ]Y–>ó ^¨Í¸¯̉;̣Ñ@àoµ„OR˜`!ĐQÈÁ‡†=~~ïFßon_ÜKΑ$™K"P a)–,ßQás~×·B¥Ăo^ú[Tă×LA`7ZZvù'Ùïm}ĂÔÎ́yÅZXóƒ` pàäV–n¢D¼ó¨éüèlëé¥Xơ ¢ˆh„̀W’‹Û–E6căØ?çD~tă½ôôR©5‚¤g—»̣î#s₫çmạ‡Âøé\øÊƒùÚÏÇ–-[iḯäđ™cyv{Åđ:)ĐæcS0÷ £/¸¾¿Ê»Ï8̣äEú^±èÑóé₫Á”xéÚGŸÄ¡ÓÚ́XYG‹xz.aÈûk!‡Lë`æØ­ÛÎƠk©z¦|Å̃_'¡r¨¥À¶%YÇböS™P°Y¹f]]꫹î?ÚáƠ/ üg´Đ?₫9#5f‘u<_¹àU|ñ—·Q©zô –¹ú–»Y²vLl¡é1¥Œ„X̣ºB¥ẫjª!·>Óç\óă˯>ơ-ï=£(”¥!5¦¬)¼ôlÑC÷àê‚Z¨c‡ÜØ”RĐWØgB+Líäúû— ´Äin÷M?3$äÚRJ.>óP¾}ăD‘÷m®ûë¿‘üÙUîŸH‡¡µI=¤edÆm‹ÿzî_´Œ¾m›,Wé)–èªpơÍbko?ûO,à… (  Đ”ç ”Y82X ÅmÏöZ×]ù½kO:ûmóhÈ¥Ư‚)¼t­5kO¯ø±¤î0N A_% ÍhËg±ă`[J́X„C QŸ×oÎưgN›Œ+%K—¯Â«ïĐ<½ùó ́£EIơ¡>m‡₫SfîEGkß₫ñ¼ ¢R b]ÁeŸ«nºƒ1ÍÜñ¥hº̃2l^›;µ&ˆ` ̣§gû›~ó³ß₫Ö‹´:ÀKÏ̃₫óùÙ1ygL)løƠM₫6T©Y₫º¢‡Ï¼éxÆOBÖ±(d]\[Æ @›æ,ăư‰B>ôWđ?<€#̀ê®æÿaÛ„^@ˆ¯_(HKbÛ’\Æ¡ ¾ơ3¸üªÛb™q“‚Ô¼b¥F±âñ…Ÿư½ÇØLmÏ©¤±(–‰¢h¡Vb rû²~çúŸ}ïwç}ø3‡b…çRHà¥aç>c¯ÁZ8)I=¬ñÖ-C!+7nă ×?̀[ߟ7~YG̉’ËsËÂ[~ï¿ÏœY´em\¼”ª6iứúkö₫âyBÿQ¿¦<¸-%Y×!Tđ«Ï¾‹ÿ¹úN¼¡3¨ED‘FÇ:U/ X©1T*ó‘ÿ½£§å™ÔîŬk & ĐQTM:pÙÿă×í÷èR¦ĂC)¼´́ëßü&§̀jÓ% ‰¿ù“²˜̉V×bÙ¦*5††Ê|ûæùä\‡/½ç,ZÚ:h͹ä³N=çÎØ̣©³á¼ËoIJă‰?¥ ]>Rêëyr~= H K´®‹Œf›¬cñÖ3çÖ'×±há"*¾o¸‡È診(H,+V®R®Txß7¯âø=»™̉îC)†ƒ€-ES$ ¬Fb₫†¡Â¢%KîÔJuŒ´•À‹Û>yé¥<Û|©́G* }-­!Œ`lk†¥z(Vk>~qĂ_Ÿà7®à;ï{ ûî5‹BƦ%ïRȺ2.ÏÛ“{Vôă l –,i₫[₫Ñ>/:eœ÷ç2ƯcÇñcâö»₫B-̉Ă*'ÖF`4TTư€b¹F­æñ₫oư–#öè`ZGÖT8báQOhJŒÊp5bÁæÊ˜µ=¥»Ú&Lï°m§á„i:À‹×æM(”ªA$E¢'LCŒ̉(M)–o âT½Đ܇°ió>ùë¿đÎWÊ»_s̀(™Qào¶ pÉ÷®çĐéíLnÏÆ‹Ptƒ`4N@‹̃J(ØTî^²dɃ{~|›í8ÍcÄ)'À‹Ï’ĂØ[ ÏđÂæ¥ŸÆO+­ÉÚ’g· á×jÔÂ(QĐ¡æ‡”}Eàû|áª{Ø0àsåÇߌ•ÉrÄ̃3X±­LXÜ^_ª‡?ø ọ̈Ăô;Fäü’ŸÄum²6|ü-gđư›¢gûvª^PßJ¤âÜF‹&AÓD,®÷W½€r•₫>>öƯk9vVy›$p¨G#9e@ ¯…[*ù;o¹ñ¡¶ñSÛ¥”#A µ^<¦µæ¿.ÿ©íZ²KÅ›t7ÿFJ3©=Ă‚•›̀ºíHi…ơơ½ ¤âø¡b₫̉•üèÎÅụ̈£gñ–àÎGc[Ă_R.Ü ˆ¿>Jî?Z¯̣y+–Ï»́s¦ŒåáùP ÂX›pxè?r“°Đ$DZFƠÁÃ÷í«8}îX: Nü”º₫KjƯà”2#ÈA¤ØQ ä‚-ƠÂc Ư£ 'Đ¼o åRxqÙ1¯zơaf¥VăøiŒÇöBEW̃fÙ֡Ƽ¿6G3ˆ 4å=/̉¬ßÖÇç¿€=ǵ0sR7MÖuŒˆeº¿ ÏƠꛈŒä2v¾OŸ÷J̃₫åŸ4) ÑíÑ8̉䪵€Ár…̣à ¸üjNÙ«‹±-n è:Lê¦ß7Q̣#Í–!Ÿå;jcÙR¼';nF‡í8m#@ MRxqØä®Ö×Ơ÷đÔˆ´&ïZ,Ú4DP«âÅí²Z7~t¼²Ûx?³º üqévö›5•Ï_p&–›1¥BÛÁ–¦_@45í ôsđĂZ}›0̉üđ#oä’ßBÁ2¡|=ơ@~đ‡=Ÿh5 †ùô¿ç¸ÙM4b%M=rJ¶‡‘¾XƯïu/^´p₫„Ol)'À‹Ă¦wf:†¼(^¥ûÿXk|«ËÂƠ[ñ£x[ïˆÓX×ăÓ1i¨ó¦t²bưn~ø)Ø̣½½ËÉPˆulËB YçFUËs¶4{3ÅÛ_s.ßȦƠËŒ4Y8"ïßEm¡ùóÉâ~&œ¯Ôʶîèá3WÜÀ9MÄ’Á§FE ùy¨Ï¡›}ñ̀/ï-7̀wÆLm†Ȥœ@ /ë­Fï«‘H˜nOÆƠBŸ—%ë{¨†‘Y§Ơtd†đ £º)EW{+Oo)á…ù‹—q÷3[ùÎÇ̃F&›£5Ÿ5MC¶Ä’²>ñ·«H`§¨ iơױɻ6ă&sêasù₫µ·ăGÚäưM%¿:ëßtè›_ɰgSqdQñúKvôöñÉ^Ï›HXß‘®ë¤ nâ8T\•b[É—Ëz½Â“O.¼W+Ơ>RN €­MiÏ麬kÿÛR°pÓW#̀È/ºi5ø00CCÚɱïøư”kƠPñÀ¢eÜ8?¼ä|¦L™B[̃!Ÿqql iÉ7BYỴ̈óüü̉7qño##55/0Desè/F{SÉ:(́”ˆÆ…¯XÉ IDAT2Q¥!C*µ€₫¡ }}}|ÿ÷ᢣ§à…ª~bÄïX/FfùÈæ¢G%c–o+̃[˜0£=åRxQØmOïøhÉŒf¾hˆaDZ3¹-Ă£+·…‘2uô%<{ÙdGÀŒñmÜñl[R #ª~ˆF<½~ÿsóüïÏbẾ}hËÙä3.®mƠçv• hF´úZ’¬ă tÈ.:Üô ¥më¨ÄÏe–‹ŒâƯă›P]7…ízÔ¡ ‚(¤âùô—ª<¹t9_øÍ¼ïè)øa,ƒV$u3'  •mƒî^¼èÉG¦|b[Ê ¤đ/µ^ûf˜ÜêzBȘԉ=?̉´åVoÚNµ¹‹n”?L22l Á+fcƠÆm($aḥèZQ "J¥2ưå½|ç§0gŸư)d’a"Kʘ€Ô;5‰z½ß´úºMε˜;ï ̣—¥æ‡Vă¤ä'̃=9äbXIrÀ0€‹÷(đĂJͧ¿ReÉ3+ø̣oï⃯˜L-Œ‡…½¿Á h‘ÖbÑæ’Ø^‰̣wßrĂ#™±ÓRN €Ư{ó5D‘zw_5¨…¤ûÏ‚Mư%†j¾aÿ£¦uZño]¹'^†VLêngÁÆ¢ƠĐ(îđˆáƠª\ôÓ»xÇ+âÜW¿’|Æ¥%—!ăØ&1$+Ȇ |Ä%?צ³³‹¯\p _»ænüX<ˆ»ưF–üFz÷æ¯5ßh¡‘Èz$à‡!•ªÏ@©ÆÓË–óß7.àĂÇL5Ä HÙđ₫æ÷6ÿWf!̉<µ¥,{kªđä”Hà_ly×FIă¼bKkƵ8̀_Ó‡,¥̉ƯMk‚êù¿%%t9xJƒ}½„ñ:qMc¯FFE(đùÚ 1¾{ |Û9¸®CKÎ5 o–ơ˜,"•8R’uÍ÷|úoä?r~±ZSÉOÅ­¾£“ˆÏưùÑ@@4 £ÔÓ0¢\óé/y,Yđ_¾ñq̃{Ô‚HÅI3'€ÁpX¸±D)`̣̀mÅ{ó)'À?Ûf̀Ù—Ëî\1³àZ®]ol‰sÖ‚k³q[/µ 5üoÄ­¸‚É]-üuM‘Œ-‰´B«Æ1̉:VÔ‰L:đ›{Pñ>ûîs±,›¶|†¬ë˜2¡ơå"&︮MÎsôQ¬^¿ekÖS‹K~¡R&¡_đáß<7' ñă„}eEO<Æ7₫øï9r ƠPà†ƒA¡Öâ± Eá)ѽøÉ…‡A ¢9H¤°ûlͲ¥6½ëÈj¨0Q«¨wÿEJăZ°¡w/lèưóúMÇ"Y~Đôn6lÙBÖptëbKøôù§ó•ë  ¼ú*²(RÏYï>¯ÿÿÅ 4}-4~Rªyô–=Zđ?¾sï8|2U_5vê&ÑR:U #-"¥™¿vܘI'?ñôy1<àßRØMæQ×Ö¢ÏÔL]Í;P[ÀƪÁỊ̂ƯĂ½¿ŵ¤ £aÍ€và†÷#¤¾‘€ÙßgBéj̉ßßÏg®~‹Ï>‘ Î<‰|6CgK֜˙'E[!Ç’…Qñâ’_¤ê­¾ÏgúoÜÙñ¼œ€ØÊ5̃Rûϵ÷-á„=»¨…ÉÚƯ/Ñ:.Ô(‰ĂùkÈ™ṭÓ«Öư\kB0răN ©ưĂMiĐ÷–C&µgḅÏbé¦~¢(ª«÷ÖcưQI²)xƸĐJj—ñàˆvY0²ÛÚ„Â^ ¨ú!å¡"—ßø{L›Â[̃p-YÚÇŒă ¯8€ÏüđzBe[31ù\¡ÿÈĂû·ÁórñđT^Rªú ”kÜyß|f '̀ê ‘)ăMÄNLj:ÉMŵ%K6!ZÆû́êơ¿Ô†h̃Cøo™¤°»±BS "r¶Ä¶SÚ3Ü·l~¨âÑßᇘái=2î›ÔƯ΢ÍC±|văđ'Í10b»oü"è4½Ơ¸êđ“ÛcŸIœ}Æ+ùÜ[^Åwo}”v×”Q"*ú7†ñ»êü{9DD5¡Ç@¹ÊŸî¹™ÑN¨4%ÉÚf!ĩ±È9Ç¢±hÍØtæl¦´gtiö˜:ùضüö»¿¹ñtÙ:¦=¾üÿ†Ơv̀ŒûfØ2ä1©Í¥=gÓ×ßj*ù‹˜ÈjáM…Ă‘3DZiëv"5<ÿoöŸ#7ù&¡€µf½æ‡h­ùáíÓæJœÚW$—qÈ:VÜ9hø‡¤4§µ~̃|ư Œ|œæWg"#’2Tơ(ÖB~xÍmätƒ§´’³%Û\fwg9hJ ¯Ú«“ÓçvqÚœ1¼fŸnŸƠÉ^có¢3g³q°F®µăÈwó_lÚ¼eÓ²M=¿}héêÿçæÇ»Ư5n¢L µ¿ûÂ&c­‘2ơÿµ}U6[’±Â¯%­úˆ»…ơ@Ç’Çaă€OEu5ᦉùa,Ö0 Hø€&”"#²–@E˶—ùâÛOç ysè(äh+˜‰BÓ9Ø”¼€3­ÿ?÷wÖB<́ßIDDJáÏGEߺúÆl̃~ØDÎܧ›)l!諆ḷØ8à±lG™µ}UzÊ%?"Œ`¨±®¿¢ûË>ùB᜹3¦̃ññ3Zö̀æÁknŸ¿ä$€S?6₫sˆRûÛ̀¶D]û (²¶ä¿Ï=’ ăÆ‘±×&ëZ8–4í¾Í!±,A{K ̣‰‚iÿmN®êӜğ÷ub­ă¾¥°s­,̃RæÆ%Ûyß«âƠ¯:‰Ö¬Cg[BÎ%GqÛP½ñ|ÑÀߌùsÍ"£ÉïaX~…v²8–à³×Î窇W!¥Í¬îY[Rơ —‘±6Ÿc)Á–RH¥Z$¶=½²·ÚÑVÈœ»ßä;·yú×Ưúéël>Xkͬ½æJËzùu§Í»çê̓Ơ%aļH›¼Ư±Ûz¸ùÉœuø,új_ßû•r™ Œ¨Å¼@¤LyËulZ³ûÍÊœÉü₫₫Å”¼ÏG‡w¡ư÷\»ư„ÖXRRÈڌɻ¼÷Œ#xfG¥4%/âˆimLïnáĂß¹̉à•Ù4„†|TMŚ́­G›Ü•g Ó€¾?£P,iÍgiÍ:üçÅïáÆ3X.#ØÆv¶sܾÓ8vöú«![>¡RØ̉tUÊ&uf!•愼E+¥„BkqDKÆfGÉ÷¶kßúưƠ¿₫ê×>}q™QtT̉ µáï×&¡Lkü…JS­ƠøîmO°påf¾üæcxĂ‘sAZ2fá†đÚR` 8vÎÖlÜJ¢"¬›Úw>D»ƒúçe#5É;’02]u×báæ÷¯́á§—œË‘‡DwkB–lÆÁ‘R‚|Ư~°+pĐ1ái pl›œksä‡Ñi¬Ư²ƒ¾¡Û‹¶«¬ÜÜõ]ÄÅ¿~€«\F́9¶ÀÄVS©@™9 £´Ô¸¦-¤4³›F{°¬½HgœÜöéÿøØKëv }d±ÑË r`§Gu÷ظ— ~}C¯Æ´êV¼ÏybÅF¬̃ƹ¯˜Ë×/8‰/₫₫1¬j7̃`Û&fÚƯÆ›ÊF÷_5̣!;¤yøÆ@Ä¢#~¤ÙwB ÷®¤àX€)鯄üú‰­|è5Gđש]üâöù8N‰b¹j´£ÅYŒ®˜x̣Ñî_0€6}¿™ÔơÁ¨ŒcS>ó>wơƒh!ăƠd&z²­!Kq|ÊƠO­ÛJWk=&åÔ}&1¦5KÙÙQ̣ëú‡kIrEÆ–´¸B€7mô¤5äE.̣@„1=¡SH­n–̃¤“„°~¨â& c)~{ïb¦OèæÎ=œ§6öó«¿>ƒ¥CĂÄÛ. 6ªVsÿ:X÷đ»Ẓ!F‚‚ơz)@Z^¤‚:IH|rBrơ‚­̀;o}ø\>wŵ¸–¤¿T5€„ơ$· ƒ‘ùü ƒ]…ÿÉsXRÄ̃ßâÔcăæE›è,âÅ»"ƠX¶ê…P %/Àµ,†ª!ÛJ,Yµ‘±myö>SæM!k rE%ˆ(y~¨Ø8èQö"¼¦Rm¨Ç̀î–3ÇäB̀ÔZW/¾1¨RÛ5¹óa\ÓöCkIÖléác¿¾³œĂ÷̃qW̃û k·́`́˜æ¯ë§±¬†&ï–ÄêAI$ Ÿ7 ̃ah¼h.—¥§`IQ/?ª°„ cĂỄ*Ơ€_|öB>÷÷°jÙ³¸¶G±êáû!!FÉhW#µ_ha$—€NV¢[d\›Pº¼ñ¸øï?…$‚IÀ ±)É<‹&ê:pæ$6 Ö¬™ÑéPk" ¡Û¨c$U˜Ñ%>ôÑKîöö¦ǹ„a²­ø%uøSØMƯÿT„Đ;Cbd¾«“ @Ềñe/ Rđ×E+YÖSaíÆM¼í¤¹ôœ8hödĐœkXp×NªIçn¬Ơjâd¼ ²̀›§â‡ñ¾½3J$(bZ3o(̣ôŸoàl&L›Iwkö–œ©X&µH¼ö®D?ùæœW ("»¶EεøàY'pç“«ĐỀS4¶)í̀{Œl)r¤4×ÍÍđÚCg̣ÔÖR«QJ˜J×ÜBèŒ%tÏ–M•«~̣Ư~`<0.>ø]ñáÏ5₫—\+q »Á®»åËûx!ă†Åÿ¢ùl5¥q‡Ö Røô¨e_s×£KøÏ/_ÆåW^Å”®W~èLÙk-9³$çÚdבØÉ>јŒ~2â¸7“¡èE#\nÓAJBh!b!PSC#ÅïÜÊe¾×½æƠtµdéjÉ“Ïfp¡‘ø %C»æ&̀÷¨is@â…“l&ÎupôÜiÜúÄêD x'%å^OüuÛJ@Äæ ǴÉ–Á*¶L¯47 éäđZ8µS|ü̉O¬:0ZÉÑhb£/¹’`ẾSèhä.>/ÔX™l“M’ÿ6̣o‘¬S ?4­»¥OÍè]µ’ƠËá;v =ï Î;ï8¯ßÁĂË·²díṾ®CE‘F)A?Vóä`̉ø"´·äé-fân”©DÑü濫!M¤5W-ØÊsÇqФ7̣îĂÙ¾…ÁrJÍ7Œ|¤ĐMƠ¿E58ÙŸŒC»¶…#ÿơÖSøÖŸ–"t8l * ưwª†ÄÑŒ7å36í-9Úszf¶YÚØàOâ×(0*É“Û3ú₫ºå†kâ³Ä>É÷ƒ¦ €æ%XL#€ƯQPĂ54†ư—–¿ÁÄ0pÙ±—Z?ŒA¥æS,U¨ø¨j‘ï₫ẫpñ—¹ñ¶»8ç)|ư‚“˜3u,‘thqM¨œ±-\KbÅmƉç„„BÆÆWjA9:cѬU âוw$w,ëă™¾ˆ+>ø:Ü{6]­f– YX*ăÍA YùBÛ‚°‰÷Ï8´ϘöVÖlØ₫hØJt=Z¦i½yÖµiÉØ¼úÙ<¶®˜ŒØđ¾ ăưC¥9hr›xă©'<‡ø Só¯ W’r`ÈK° €Ư`ùŒ5#Cíæü»éMœäđåOkk¥~Pñ|¥ CUŸ°2Èâ%‹¹è?¿ÅEŸÿs:$¿üÀiœ}̀à•øÀ÷½1 ÑèT)¤ æM,`I9ê{\Œ˜ăỌ°̃9R2Tä˜í,]ØX“=Œ+P¥C"%͆ ߀cÙl̃°O\ö}̣]8íø£ù̉yÇày>W=đ,^dxw)d½ ¦-†‰”ễUŒˆ:z¸ḷ¹~Ñ6>ơ擹áÁñ\{Ç8¶M±\Å D Œ̃ö›4I)pă®¿ƒçíỊ́íe6ïèkxÿ&ơÑ@ éHÊ~¶´xĂa3¹ÍYGÆÁVcơz²gÀ¬G:(ö†·̃pMÿï?ú̃qJàólN`7ZÖ~î­¼b”Åï«ăX8"Øihœ:D‘)§E*—!^àØaÏ6nºùfn»íVÆíy¿îhfM› Ê´» $†,ÓÚÍëÉad˜-AĂäú–4#»¿xdMŸÊ廀Oưà\Ûb T¡oJº÷ôÉq·*»® QÈÇ̃t2ïÿÉ]H¥›~†£b£ŒiIëïÈÜ=¨„f_€k‹mºu(­9nϱâMo{×ú&ïïÅ¡³÷ˆ¹€/ña ”Ü!€×›¡~äô¨rưà'%<ƠtH$x„çûTjCå*¥*C•[—/â?₫5_ûåt21½óÇñ³º˜Ü5¡±RơñXçÄ2£·¤¬Ë…Éfö¬‰¿'>˜9G°dk‰U½U.ÿèù̀³'cÛ ´r&'·,,!†5%‹P3Mα8̣èWđÀÓpEˆk%è&é´‘€ÔÜ h[Æû·ä2\pô,–l)›Vê&‘–á̃_0±-£ï»ï¾₫;®ưù¶øPñ!/5yÿ—ù—F»‘XÛ[™=e\v—Q€~₫ÓÀĂë¼bb7ZE»$ëm¯MnM̉ "E® MË«kÛdƒ!6ôñ­$Ô’|†ư'·1½#ÇŒ1y¼HÓW Ù^̣ÙQ̣©…ʬ(·L_¼Qjt êæè¤©ÂáZ‚ƒë<₫ă-'sơ_º¹ó¡'pl‹¡J­1^ÿ˜¯'Ï86Êmᣯ=‚÷\q6 óßtèG ưµ®wf‹–ŒÍ ûÍdm_™Hil[Ô›~¤‘â°©mb̀Qo_‹ ¼Büơ5yÿ—lé/€ƯlÍzÿ#̃¥;VÍCM?àX­UC3đ¹£F₫̃t̉P£±‚€ªïS©ùDÊ^„Ûî.–ê+·[sÓ»̣tµ8lj+…ŒZ³¹èÑ[ô@-QB Ñ’Ù¤¦%li: ûøfÛO3oưædlAIPơüĐ,H•̉¬'w%\xæ1Ü₫äẒ¶¢́› Ê '!‡Uum‹¼ë`Ù§ï?…›–l#ăÈ‘™ˆ8轺s\qƠ }}›Öú#¼1öú=1 ½Bÿvg  u)=êuX¯5jÄZ$ ÿbRJ«$¿n"ávÁĐ7GÍ€PO”¹…aˆ@S "3‹çđV,Eî!ƒeËàá’–ŒMG!ÇÑ“k®ºº÷o9¯; aë@E¯ï÷IJ¯ưH!¢>Ï$E­‹GÖ̉•wøƠ§/à’ŸƯ³qưåF©Đ’‚¬cÓƠƠɫ؇ÿäOñ t5J‰tç ¶”± ‡äÇ̀c₫º[ÆƯ…jk’¥ )ÈXB¸~í石:~ø0öđ¥Øă'Äß`ø/ïŸr» Ǜ"¥G]«#.¹™(³sGàÖ¢O¾{D!uMŸQB₫]Áh©…Ö\Ç̃QC`ÚƒĐÈmWă©ÄR¬ UÊñ¿ËAH1„ Î˼Ï9ká׿ùí k¼yëq³ºÄk÷éæ„=Ç°×øVÚs¶v-¡K̉|Ë»6%_ñ‡Å[ù¯·¾Ó_yăÚ tµhÍg)ä2d]›sN9+îZJF1y—¤‰ṛ°—ƒ¨é².3'ă¸Ù]lô _1Êu‘ñ…Ù{B_ÿæw·ÄH¢h”ưG‰÷÷_̃?v—i‚Œ#E%wÑë>"to®ˆFÇœlêeñ6ßæÆ—f¿K„—rDÄ`3Ñúz²„Í×JÅQƒyN£]MƒÖö «ưŸ^öù-?…ˆ ß±¼Đ5.ś)gv2gjæuo:üø‰mV®{¼Û?°¥¯¤wT¼P ·ÛƯ²t;§8ƒă;¹öö¿0X"Ta94wWÿüÏHa¤´Úơ%Ư”ûÛ–$gÛ8–ä¬Ăgóàr®)û¡Åđ™“ûë¬-₫Ptå¿¿ƒáí¾£yÿ /ñ²_ ÿ‹¢hG{ÖF)M±ÆïK F¬¿Q•VfCbÔ|ÿù¢áóÈñ¾'ƒF±2®ˆ`lx̣9«iÅ–-êRIEp˜^¹o{åO×₫¼ú'_ù̉×J7ëÎØkŸü>{Î̀wá;ÇÎ29³×Áû·„ĺ)êu÷®Z¾ưásù̉o₫L©g ¯>óu\wÿR²E©æg₫G}ºNä¹–E!k³çän Y—›ËdlOÆà¦e¿HkqØ´N}Úk^·J^̣ï?0÷÷^.¹ »‚'z˶´g-ú*ảR_ú)¥@Ez§¬ëͰPªùĹî"R:ØơàK3j4>V÷2–’\k;¥j`v °„¬‹G¶e¢ )Úr˜6¦ElZ·!‘½ ăƒ’tÁ…MQµXʯ«ZP[ơÔùÇ?ün ‘–=}æ¹ ?ôѱ‡ï3;Ö+Oî̀ è¨éËß}ºøơc›ơ+f´‰ë₫²H+¢XC?7ç7¬́—smÎ:j.¬À±Ä°+T—Q‹ûº 6?öèĐü»ní‹¿)À4÷4ư±÷O~¢—ËáO`w¥-);Ê>ă[ÍJ°̃J€àX-q"³÷O53÷q¼%Eó` v,¶!¥Ä²w~û5¦vE%¯OÆ_³¤$ë:d3.mfrQRJaj₫®%éîhe£¾( IDATæ˜,3't2©-CÆ‚§¶”9dvg&>$:ö’C4¦á =³u×?vâ{ÙëV>[ûÂG/*&xgå[s}üsă9pnîŒÓ^=îñU[uG̃eG1z̃}<ÉÊzÓĂ1óf·ÁY{ç™ °̉£÷è`öë/^?Lđæ¦Ÿ¤́WæeRöKàŸA¢jB‘ÉR@wÁ¥;ïPö#r®¤%ă 1굑IÂQZ×wZR˜ĐƠ¶Q ²®‹§¢È1‹Câ‘⺸ˆ 'up)’¤AÅ®Yă:yG’ulĐ’ËĐƯelk}'µ!,‡Î¬dƠû*ܲ`-›‹>9̉‘7»ßô®O¼îÊï­¡ÑÓÆÉÁˆeŒ¼%«¸“›ØQe(úÁºú é¤UËW­=꥛(V|l&ưF#ª%̓@N,çm[¯=xîYÑKƶØÍ¨‘Ăè½ÆÄ忸¦gƠ¢ÇÊñĂŒ̃ü¾ä›~vA¥ö4)-«¿wÇ̃"×¶dkÑĂ’‚Hi¦tdè­„,̃ĐÇæAv –YÙ[Å ̀V ¯RÂÂLëÙ– ëXDX\yÑ+9í¢ÿ$ *5ŸĐ÷ê@aä¯ÂÍ8-äsYr—1y‡9ăódsÜL†|çxÚÛZélká°™Ư8–ÅJH_±̀³Û+lî-²½äQơlả†H™ÈDJÃuÈç²|́„éáØ¶[âñØ\mr*ŒN^#™•ü»ù̃-Rx×?2ùâÏ}ußoßô0ŲÇç„1´'© &U)dƶd8ư°9L×ɾlD@¦ï_×ÁƠ–pÈXŒï³ ₫½øđ÷įi-°ǾhÊÿiÚs™R¡̉–3"D_ÓW¥ÅµÙØWf\k†iƯ­¼bÿË"ïJ˜§èE,Û^Æ ?d°¿KÀ¹§Cáÿ±÷̃á’]å™ïo­*Ô}útVµÔ­œQa9Ù$ŒpÄ÷2Œ}íÆäûlcûÎđ Øƒ1A–…J(ÇVè¬N'ÇJ;¬µîkíª]Ơ§[BHÂt×zƯƠ§ªÎ®pö÷®/¾ïà0©Ö”V®e¨Z¡X(°iE‰Ó}vÏ+f)ă³ ¨V 71ILÜXbÏL‹= 1SûŸDGM Äܺi ?ưúkøüíO¡”"V$µÊEĆÊnÚ• ¤®SÏ0•üŸ~ÿ/¯úÜg>=󯑤ngÏ »˜3øR= f^Â_̣Ïæ̃ÿ₫¬=û´U#́› VJ(mĐY#ûB]J…Đ÷¨„2,óó6đră¾Ưû[Æf„«øøÿ₫÷„4·û/q́´_+çú›“ízíÀ °:i¼ÎJ•!ô=™à¾¥ơ(!MUÛ'”Aú!åJ…Đ÷-\vÚÓ”B±ÄwvbºÖâé£wctJº4‹NtÔ đD›ÇÎé8Å*ÿfÔ`RJÅ3SüÚ›¯D I”&4åZmu› 8Ï4,/”sÓ£Å;ßù®-Ÿû̀§ï¡{LvÎ ™{ß…£Ï@¡”»¯”~ư·?zë—₫é+oùØÑo›(µ?±1mÚ´ßVHRl>ă×^s>÷Z¤Ênfàv¿¿AHa*¤Y[RŸù‹¿́-ûơNûåË~)'Qé¯/°ưßưô"Wœ9Ø=ăo`´ĐˆRqJ­•غ·Û©„“ÄÔb"ỎZ’̀ÎÍQ­TØux§Ÿ|”¹¥Iw1áD©Îñÿ™ag´WJ;;Œá³ßzˆ—Ÿu7<ô´¥ÅÖ¦ị́ăỚ¸q¢Ä¡É9̃xƯåë¶œ}₫đ¾¦S̀Üè|EÀw`ưĂÜ@±'\¨|ïæ¯₫—¯ơ´×_qÅÅÿøƯˆ; ”û¹¶ƒ/k.Ú¼zWVxtç´Ít²ä§ưŒA\¼qˆÛ;ö6æƯe¿…Ưÿ¤é÷?aÈÚ·×ç¾×èèB[JH§ dÙQJ3Nœ.@L­•°ØŒYj%,¶bnÜ9Áö³Î¦Q¯ÑŒbê͈z³I½Ù¢̃lQk´¨7#­ˆf+¦ÙiE ­(¡%´â„(Nˆ“”8NiDµV̀?̃øM®Ù¾–fbœZ.]îrvd e ±2ÄJ›½Ó5̃₫öw‹Ư½ ÈxójÎ;ÈjêÓÀpÔÅ×O»x{¯;ö»Cï}Ç›>ơÊí«¨ R)¾tÔçu£bàQ*¼é²Ó¹}ïœơ„\bÔd?Y— °%Ù]Ó¬ûë_Î%₫¹Ư?ë÷Ï'eÜ߀xỷ;æ‚ñ„ V?,v•6VµFi;ÓŸ(«s%)Q¢˜œœäÊ3×̉Đ̉É)̉T“¦4U(¥́}m̃tÇ”×HSE+J(¨ß~p7oZ骙ÈHO–8çJ§J¥Z|ë±Cæư¿̣¡ËéPd—ÜÎ]OY“Ṕ<‘æN½Y`̉å;P8BL|àß|́SyăÅ€rèă;RR$ƠbÈèP•Í£Uæi›Ó Oñ-s¬?g­æư¿ü¡ư¸²÷×;í·Ûư$ơ₫úđC^G[q¬íTB+Ñ  íf‘ëL˶™Œ8Ơ†$Ơ4cÅd6®Ă÷$Rf,öäz·¿×x»âcH̉”–‚Oüư¼êüMh¥Ûï){N₫ùY ²÷Åbª¡Ă_û>~9V£âÀ È]SY_½Ê%Ụ́€Đ¤Ă¬»D§ív ˜0ÆưÜư₫ÏÎ}‡÷¾́́M¦R LÑ ¡¤É/½ú"¾»wRÛơn2±32$æ̀U%sû]÷ÔºëÖ%:´̃Í×ÎÊ~-~„i¾úđCÏ´Å%MÖ}&… ц‘²#ÂhÛH>yØióÍ<á¶]œs̃ơeø7?Ÿq̃Fª,aH:sˆ#G200#ú8ö÷HÚ@¢́l₫]{¦xû^}–Ûư‡èË8B/(ds÷Í\Ødí-¯ºæ÷̃~Åébxp@T…À£Ø Å«ÎÙ‚4z¢Üû̀̃s¦‚l+1bĂP‘ååå2ÿùi¿̀ơŸ§ÓؤNvăïÀ ´QƯñüuØçÄ©fËHéYn~–<5¸v pàÈ8×_´)=<éu²ûνF&ß\Lß–"‹S¢ÔđµÛä½WmFk'Nv8ä[~3×?+û59Éúưûđ"¯_₫½?÷%Ó[k ­”êà`;.m[@Ϭ{ dơs‹¬Y³BhÛx½e<€ïËAцD)Zqƒ÷ßG¤Âóñ<éDÄ1aE~,Nm¹đ]‡̀G~ùçÏq@Á%¿ßk+?d”ä@`á½o}ơ§Ï+Ô6¯[mVV‹¬¬xƠù›yb²Nè ḱîRd¸kÖ „\uú(Ǵjüù§>9IgÖ¿ƠăúÏpP|÷à_Ẹ́+•®Ư¯]£7†b`Å2<ÑÍG×yn.ñæÊsax́đ,Î8Û*îx̃s3üÜÜR8Iˆ£ˆ=»wqơ™ël_ưq’ß…TkZIÊ÷öÍpƯë̃üđ]yY.à¹vêü.-¤¬ưê?ø‘_¹î\1Xͪ‘A^wÑ&‹<‰”Æa€y- a´ỵ̈>wÿÓ~üÚ ·ñÆ‹·˜]“uSô£eß\±eT\µuÛ‚…è“ø»ụ̂̃Ÿ|*â÷¿÷=nûç\ˆ4^ôöûçË~É©düĐozAR€°»Uä¤@Œơº̃+BËE':Å÷<%x6á–ư¬å÷·wáSï»–¿ùüÿ&<¼D¢´êĐv÷ä‰,ÄËØcf'²çĐ8+˜[\BJ‰Vº”<& À’h¶RÍ#g̀û^{íö_ëÀÇf̉ŸĂwØÎ d™ú̉u/½â£O:üVäB*ÄÚA©îøÖ·§ÿà~v₫¡ïkƯ¿§éÂܭΧw矦3îÛ;ëʬ¾đ­c,OĂÁZÛN¶v-À¿`‚I˜©Ç ®ƯBàùH!m5!×°³\̣ïx%BhâD¡´á[wƯÏ[.\ghm1Q±|€8U,Ôb’¡áW½ùçạ̈YIĐû€|> ,¨Ú́ô›ßô¦ßúÄß~á›—_rñß­ª₫ÓÛ̃úƇoụ̈§îßÓr¯•…ùrcÖ4‡-3NºÛ™\â嵐ùêÀ¿F4à A-V„Ų3̃g·Ûú»ô$»MrùyÛ |‰ïɽµ9®Û¿œ r3©R4ă”{î¾›RÄx>A€tih;s+mn{üió{ưđ¹0 ‚mí}>ryqù{oưÆ¿ñó?ùÅƯ>°?纷rG¾œ¸ÛíDZ“~Ù1‘ÛưO©Ä_^„ut1rŒ4¦SŸ–­ ÅĐsm­Ç¼Jv‚Ï̃pơ ^.xÜx½‡x¹e½€O¾{Ç\̃FKé#;9åB - ¶%öÏÔÅé]¶Í/VVå€Y€d́<¯̀›wß§ÜmF×µ”Ûågèî0|8;»ß_È…*}è¯çsÇïưÊôîSm.®ưöØx!/Oإʠ‹¬]¬¬°Ơy| ²gÓ`\»p’*q̀o₫o¼pK±n7å»{½ă:Ó$áöǘÿüÉ¿x¶0ó¼ç˜ ́›38€éÏæ ²yƒƒîy³t3ưœ’«/ Ëoz̀[:ư¹‘R`kù"gúÇÙ¥³Ö`e ̉óxêè,goßFxÎH9îï-çÏ ˆ’ZKÜú½9kĂ(¾äĂe ©1´RÍ=ûgć̃ûî˜۟•óaÀT=†­wÖ₫agĐ™±ïwƾÇ»rÆŸ|¥ĂbtÊ•ưúđ"­¥–2AÏ/´Ăªá ̀ä4sˆ±\à<+ê_{đ /¿x°̣×Ï6 8@d^@§´’”¿ưÖƒüÂU›ˆSméÈÛÓuË5uæâ¨i9\ă­¿đëW‚v^@ÙÀs- ö‚@’ó&s;ưÜN¿Û₫r†?E·°gæúŸ²«/à2ëöƠŸhMÚ¢›td¼È ofSƒS\s₫6” <˜gçú÷p?8e^³o) uǸû9«ï/:°¨ÓQôÉ»ü}è›ê :½»§g‹ÔÚP½vRPĐíă 8*›̀І{wOpö™[ <›Ï0øl<£ i¢hF)wß{WTÁXqOyœ^ƒ®ù¥I”1_~à₫ÅŸ½̀₫@.à?×[f´ù|@–ùÏøû—œÁ7—1ú¾á÷àÅYJY =·Ă·C¢ ÛW•œnǰD°X6V· đÀSOó–+ϱLÀ¾!ó³Ç]̃Û tÜŒ¾1¤ÚΤơyîzàa¶¬m Ÿ[´4ƠD©ûÆg¸äÊ—n_æ¹§Ñ=đ|”3Èdµÿ|?@fôªoô}xÑW¹:èo¸¯HF+hÑ•LŒÄ:ƯÀÍr»¬K¸eL?ă‹k6Q*—ñ=¿=X´Ü7tq¢;^'(5|ăÎù¹«¶ ”Æ“VăàømÅ™`h&©90]o}ĂëÏt@Öđ\§Ÿ)1¨zÓ7ø>üPW£¶h:\óæ›)±̉făHÁ‘€d̀½ÂơºZ»è– 7=₫®hï´v:Đ3 3³³Œ¬̃øMrŒ—J[ʰƒ{wqdj혰́7»ê"ÿÔ8MĐH¾~ëƯ¼û­cܼư±ÏÏ¿7û»†ùzS¬,¿ëC½œNg`™n²₫êÀÉ»̃û²ëî.R— ;2ßbËÊC%)•‚O1đ }À³²VBZο¶Jo¶Ûæó®øđ‘E6}1Âh¼Iˆ9G 9mør†œ¤fqó-wpÁi+¨¥*²ă*;“VÆàI¸á‘#æm¯Uäç¼¾Đ€“y9Ïư@+­³=]!Ø?Ûd´0ZöY5X¤àKªÅ€j1 \đ(¡çµÉ?¥́ÛÆhR­QUƒ# |¤çh³c¨ÙÎ-/¿ÜcÂU´6DI Fñÿ₫Ă·¸ö́u¶ñHă§K0JG½å;ơaßM9œ^/ư±Wœ¹nûù{€ç§=¸¿‡åơ¿‚d Àü̉o}äRÈAƒ¯E0ßL(ø’³6¬äœÓVQ(„\HHâ˜rè¼ßRVâË‹ ,0”€HiÎYSaçîưÄIR'æ<èrƒç±Pọ[ïz 7ï<‚çZ™Es/đ$')øV¥Ç—`DÀ¥›W²uEÉlX½JÿÓ—₫a¶§Á)ĸû£°ú„ /àRIrŸ_(lH{.ơf¢¹ù±Ă<5¾Àö±*zư¥l[rç®qîÛ7Íă'*E#,—¿rœ₫ÚÊüH—µ¿u÷ ¿xí¥ˆ/½í5äƠ}ijˆûóˆ•ÿÁhCœ¦,ÍLr÷Î=¬.3·T¤ÇĂç <M —nZÉ•ÛÖ²q¤È¸u÷´ø‰Ÿøñ+̃ûÓâ&0W@¯Únơàä ¥J¡T.ßQôÄ›ç©r jƒçỳÏỊ́ÏƯùJœuÚ—ï8ß~ƯùÅ₫é>å¼’zK[}pA9LÅ¡…˜gn[]]לŸ^¤C– åˆ>ôà¤3~ÀüÖ.ưîoë.{²‰ÀÑJĐî́ËÔy…¢ô“R¹D›$U vn±ÿè ߺÿqJ…á•£üÄ…X3:Âé#!Ö~”ơĂE6 ,%đđDÓuđÁ̀bƒTk@`Z è$FCÚl b«êíKÁ O.ؾ)¿/©–I5̃yƯ|ü«Ñ"j­­ue«Z·ËĐR_£´a¶‘°v¤¼úºk7~ù¾p˜YH†»¿úpR­ö®6U‹‘Ù( °  ´AxÉ;Mÿ l̉Ïf +· çIâDÑjá̀Lz’½ù¥üî'>KT›§¶´ˆR) à 4–¹G\₫„ô:ñ¾=Èå&Üsø4+,®8Ÿ…VÊ;.ÛÄg¾ó¸N• iK¡Ù¿´MAÊ¢(bÿ¤2¿óû¿ÿ̉/ÿĂ¥Ó Ÿ’dœ}8ù=› H¾/„5('́i çă9fßc±# Ü€Pj)Åà)M,±¯ÑÊaH#71IÔ₫m¥ u¥»Î“%I1zÑûæ ÂÀ–ù*üƠ¿ÜÇ;^v…b™F´Øư|̉ˆv¢2_h°uơ°ØvîY«ƒbyẺjLÓ­¹kPơ~oươâ¬~#Đ ^¨“/É̀!0× ü6£Õ ÈníÑn¶;³1Y¿½“W4â”HC3Q4Zơf‹z³E­Ù¢̃¨·Z4£ˆf+¢'4£„VÜ}DIJ3ê<Å Q¢ˆSE’(â$%¤üénäW¯;›85®ô˜ q ƯăÅJ,Ä„äĐLÓüÇÿü_/£##– ˆxưë°'-DI²·è‹,è́ñÂÆÜƯŒ»È4î³ụ̂M<ùÜÎäÄ•&Q$µ‡R¥4ij́g­=”̉ísZê1Kf²ç¨ă‰̉„¹™:4ÁÅg¬Ăw€Rt<›́£kÇc8ÓH*úœk‰×¾ñ-ç9·?ËäeÄú«'ß:¸x¡/MH¡ đDw=^g´×zïbyîPÑ{äæÿ³ævÛ¯5î’)ë*vL8,WØ3Y£•$üÍ—oæuna;3 ñÎP‡)¨Ơ¨±¢P‹gœ¶¦̣ö_üđ%t„tZƒûó}8ù¼€GŸxêk¡ï “›P€ï9Ö]Dû¯íø]¶-ơ)ûØåR,÷¦²‘cwB“AÎ#çϘ ×[1 ósÜpû¼îâ-øí.Ä|ŸñÄJ3¾”z‚ă5̃öúWm§›-èùâ ́¯>ü« ̀7₫Óăñ̃ÎÜưHÑ#đ%B‚0Ù®k–åxù”™iïÀ ]W`¯Ëor\€½S‚ƯÙ3Œ“P ¢8¥+¾úïñ³Öaü"'ÚÔa`d†IªiÄ OJæ©yëë¯?3Ï—‚Pơà_'Üyçf¢A¸\»±]Á‰2H/pÙ}sBC?̃Ο߫E¯–ŸèVöÉOæƯơ=–‰˜j kWÍO’¤6ah̉ˆ?₫́ ¼÷c\.@"rïIC¢ (e‰E³ Å¿ùؾ*çTèóôàd]»¼3MTº s4ÜRXuƯ , …h“z.ë̉w~ ÇûqŒ;1”‹¡3ÀçÁrĂD"76±')VÂC=g6­_Mè |O´µ¡Ưƒ°o¦Æ`ÁĂ€9²ØâåW_±ƠyC9/àùâ ́¯>ü« ¢ªgî–²ăÛ a‚JÅ 3óÿ,O¸̀+ÏÙ`‡‡r`)Æ`z©ÉpÑGYND3ÛHyÛ;̣l·ûçéÂúƠ€>œtKŒÏ×÷}¯Kô3ц¢×å^ÿ/ÑsÛ‰ư—÷"ºËv'BŸŒ¹Xiƒ¢TZÓJRZ±âëß¹‹ëÏÛˆ ¾hkcPÆP«7 }‰Ö¶ùÈBÓ¼ùúWlv»^; _ èÀÉ­Fm—È«… »3®,Èb,áèÀÚNª,UVœ4–ø̉-÷óÚ 6ă d‡´DĂB+±D%î|ÍD‹ /½dĂ .Ư˜€±îHcPJ ÛP%^ŒÄϼóm:ƒÏˆB²Öà~2°'đ+¿ó÷ø‚yÑœ²UƯ9æ—̀3"YËoˆ¢zÏ ˜®½ßơ(ÙÜAwAiC’¤Ô£˜CûâñC3l[·’Đ·ƯCÀÄR„ïµ9…`¢DówüÜù9Èơ½€>œkæ–¿­&Ǻg€j¹hÙ‚s ¼Ỳư¬ŒƠé°Ôˆ IDATL̀pÉΆ̃ăđ»’`çY¨0y(GÖûú©̉DqL3Vü§Ï~…w^± ´ªE.Ä9¼3PđÜh²À“Rḳ‡đï®uq~B°ŸèÀÉăYEàuºí´1–k_Èçÿ·÷bñưGÛĐŸÅ“l‡²ÉÍ"XÊükic[~›qBÔ¨qÿ£OđÚ‹¶â ° âV“À“]= ÓØl;mĂĐÀèÚutëö{úpr­F”NúR¶­N*úmØẽ¿x†Ç:¤¡990¹^A hâ$¥§|₫†ïrΆxís0m²ª`rÔaRQO ¿ö¡_Ù‘€>O@N:À+{úkç*nû.yñÛÜ(ís1âç?èØ}… R*ªF÷«äx ²É?+)–µüϾËO¿ô ¤i¥ÊehO, !Ø?Û0¿đ¾÷]á ¿J§' ¤ßÔ€“dy1₫ÑÀ&ÁLæ6W'²‘³üẸ̀1ÿñæ…°ANV¾Ä©?óTàr„!µDăyaW§̃‰ø´hhÿ܉íM=o†+† â¥6yÚt½<×ÖÚ&[1́cç¾#¼dûF `ïL“PvJ– Eˆf¢9ûœs×̉Q΀₫„`NX»ñ4™jÆ¡‚Mü A”*ªå‚ĐÇ7ôÂ1"_¼~€ƯÓM¾äĐ̃§–\̣¯Úăô»ûđ£̉óÚF;UO«†¤ZsÆh™BàúeØơ¤S²Ög Ï'¸LÂNĐÖúkïèÎÏ»ÿ±e\r¹Ç Ăà ̃Ă0ƠP–î«WpTt̃gçư ×́d)ÉQ Ÿ¿é.®ß1f?£€ ÖUyjºA¤lw¡̉Ă–₫JÎøK¹D`? èÀ6|åon˜ó%mƯîùVÂXµ@)T >ƠBHµàS}¡Oxa§c˜æûlÈâù®R^-x› O=œ35h­ÚzƯn‚vW`æÖK_>¡ï#måƒƯ{ö²wrR 9om•]Ó Z±n·1„Îè‹tzü¾đ­¾4Ø‹µø‹È“ŸÖ`”)œ¾‰ZÊưfŸ!NZiR£QÚ2)'Ø¡r̃Ù±ÈÛÆr|=n½è¡ư6½É†c¶ZCyt=OO-ṿ‹€6qÙç…@:ïÅ÷<œ¼{=/E)‡ç›T!ï¹f;Ê/"“ˆ[vO191Á““uơßCAÚVâµ›ỳ Ñṛyl?LỌP, Ç„Bv¤ËŒv¡‰đÉÄó́o ^ ¡¥¥ê[V p̃yçsƠc Œ¬"jÔ8pø“µ”ézB9đ\Ø`a ¢ [²Ú¿̀ßèÀîzù«^#W½¯Ás¼ÙmêÎDiî||?_¾«EÓHÖ X·zŒ7¼d¯ Êœ5 ÿôØ4{åÑ#‹Èæ"aèa„·-ø ơ˜êÈ* O! \iOw¹¶́Ö›æëơ2Ê/)ïSl?à{ U0´ K´"‘>•¡Q®>cŒ-gÅ5ÛWóôB ÍE¾~ÿ~₫ä̃û™«G …°nå —³¥-c°@¶#ë_ûú±k^ùª‘[¿ơñ¾Á÷à¤X_zpœ¿p ôéÏ­9oĂĐĂ.æaË܈QªIÓ„ĂQ̀ÑÙ%î{|/T*Ná•çnä—^3F’¦ôàGo=td‰ Ö pÿÁ…_:sUåÓơX™jÑ[o7’T%–YǸ¤œuíQºÈẩ;÷Di_(sùé£\{̃^̣Æ‹Ù?ă¡8<²Ø¼‚V’+0ÏÎnLN^D`Đf—DIBèy”BÓׯ䒭«xÍƠ—pÖ†•ܶk’Çvîä_¾79N‘-lŸª4ª-8ª1<߆ 8e¬đÔDx 0GZ¼ëƠ/Û¼á®{êåW]ù_„I¥1& ú«?:ë©Ăṣà|óñ±jxæL=J›¶2°ptm}£Iµ¨É²ơRXW\:@B tƒ;?Ä÷<È_YÁë/ÚLº´ÈưADB*Ơ÷9U˜—ơ†37à‡E|OR<|)™Xḥ·ỵ̈-ŒOR0 Jx6¡4KZ£tâZ‹­²°n‡‚€lPHS è”BÜḉˆ .¶¸è ÎXXúäå—_ùöư;˜ S Ô¼(h}è¯`Ư²gî—nø\¢Œœ©ÅmÎ}í¦ü²+Xi¨‚.=/Üi„@éö́¼­É;0đ=I1đhƠ94×äÈî}ÜöÍYl4Iâó1mMr±œĐ™P¶·Z#ÂJ‘7½ëç˜] >?‡4¥X‘ª¥m¸ µUÊ„E0=ăÂæ„°ă ̉Ú5CIj‘2%_àî¿ÿÂ7îøĂ÷¼áå†m2@J†ôW~èë¦'f¸~ÇJvMƠ¿·yEñ%3ơÄhc„”–ñïXÜe؉8Ùm9a,VÎ[ĐRm+uW”*‰¢Öl±To§i{ȧë<Çi\îqOJ?P´\ˆ̉ˆ"ê­ˆ8QÖø1í©¾®O¦Ew₫å÷í|zß´5ˆ B ©6­”âO¿î­}`ïúW_´ơ·…”¡ÑZä@ ï ôà_Çj$éñÅÖ7‡₫‰¥Ø¹́²Ó[“ Ú°œŒ‡éº§3lÓ-Ơ•—óB RmH•ëP8IƯ‘´çîóe@rçÍ~ïưđ<!%q’Ú¾m»ú”26¾Ï “ö¢›s'ܸïñ́߉¢.oD"í­¥ 0SµˆkÎƯüË==ué9›7¼ÅóUC¥i Hr@úđĂ[YºlËỂƯE_Xi1Z 1 dñỷ¹»¹;óe»Écmrn»ÉOøe3øîÖ`»ốá’oÆcØíă8A¾qHjmǃۯ‘% óICÑåˆöᱯ+³ûƒ¥E/LĐ~ĐÚ4ă”3×­¸dïÄôư/û±ë.ÚưG­†Ơ¿ŸûêgWŸ‡5Rö?Xô¥™©'Ô"ÅR+¥¥̀·RsÇl#aEÅ·ñ2ckC :âí\Ú ¶ºÜHwƠl¹)¿̃Ñàå;Q’°÷î¼ûŸ‰‡cZ†—9ƒèÈ­,2SOˆRmD£M₫©‚fªÅ–ÑêØ·|sç%oxw5,ªô„ûđCOøí{ÛPÑÿ¹F¬DÁBCj@e;³w$Ú§†j(Û;{»*Ó̀{Ô]ä=¹D[B\ÜÜ̉{!VG„$û sŒWq¼dŸXf÷×Î^S¡ÛœB¬uûh¥f¢hÆFzŔŸmÓVV*ÿđ™?}èµ?û¡Mt ơ¯å>¼¸ë±£µ»¯9}øï‹d¾™Á¢ßɸ›n77«ï/F)•‚¼´1”ÏeáM;ÖÙÎrƒ"Ço+îŒê>3æ8¡JÇßÇx̉©çë !¤<Öl”̉¹3®m ä{̀7Sf ÆÁà>ư_îùÓ¿ûê[-ˆll¸ÏĐ€~ƯôÄôY“KÑĶU¥K ‰2aÄL#a¸´)²LozÏí̃‹­„• _öŒ́º„an*//)v̀ €…zƒ±±1'íưâÍÎdI¾̀`³œ€@`„Á8Nƒ60åÜ“±jÀêjH#ÖÏƯ‹mB_P-xYl¡¡k4ˆZ+æoĂ_₫Ë~dÍ‹«~–èSˆơà…X·ï›çÓ·àá#KÿægŒ<\ äªz¤DàI¢Ô^Ä­ÄàK/zóúƯ1v”Ú+ÜÄ8̉Mß̣¶wЬMÖù̃"ç‹‹N 0N‰×̃¾ĐÑ̀Ø Æfÿ*eß6|²&IàyGèÛ ºèKÖ˜¬Eö=羨6È9ÂÑáRÀcău”²Ơ†f¢œRñb3æ—÷á[¾}óiûRze:ă}èÀó³†J>Ϧ# ­ûwŒ•ÿh©¥¼TÛƯÍ÷qjÚFÛñ́…¬³ĂĐNl `®™0V À@)d°0P ©| Äs` W ó@Đ•"ë̀ơ‹çÙØ ÜsW‘yƒ·ï$3øBàQ *År‘¡J‘¡^rÚ sÍÄñ˜cu \—äpÙçĐ|‹8u#ÑZĐ³ưĂR æ)Wlœ[¼ư¿üí—_R*ẈŒÂ}x†Ơ/`}ö£ǜek™X.zÇ…«o“PªE !\K¿±ă}±ÎØúpO¬ _+cKƯ²Ç`0Ú^•RJ"e«†l]¿ߟ¦Xk̉ŒR¢D¥8Ơí`¥s%¹l‹ù¸ü…»ÖÛ±>\Dxd@J|çÍ„¾€bP*„¬®²mÛj±BiÚzˆV(¡“Ô4ز`”j&—âNvÄjqJÁ/ĐL]ÓÔ"%¼ xæ̃ñºgg>ñ¦ưúÏ߃¬”c£§₫êÀ‰×·vÍđÊ3V²{º₫'ë ¿¥Ú¤t´̣²Ä›îé†.Æ«˜¬Å®'^ă AAJ¡Äs`Q±2üÔ›1låè|ƒ{̀2>3Ͼ©E&‰2D‰"V”̉¤.ëîIñç…»yûŸû5oz8F2Ê1O ŒgCOH<_zaàQ¡OàIÊ•*ëW¯äôëxÙYëY¿z%%O0S.ú ©†(Q$Ú L.ûi åĐă‘#5ëEå$SmÚ=¶/´ÿQœ̣»ü¹¯¼ê ïå—_ôI!¤gŒèwöàû]×W/¶n)§/µR|O‚_J_çñĂsÜ»oùÅE´RD­B_â»ÉAéyVgÀSÑéÉă€½ÍGƯeË“–ÉÇ÷$Ân0(Àÿ¾GÁ÷(…!/^Àú ë¹dË;¶mæŒƠCø¾Oœ¦,µÓK‘a‚f À|I¥`‰Mê‘¢‘(ÆvO7­ÛoDOb+Ă%Û4”(c=%[z5ó˜+/½àØ7ñÚ‹¶¬¾Öóƒ’J“|ç`úpâuÏ…wŸ·®ú9§kÉÊJ@+ÑD©¡§¤Ùđ P = ’¥(ذ2ßL­6Ç0ÛHiÄÊMøYb̀,f÷¤ÀsWf3QÔb…Ö†RkÎZÇ«ÏßHª4רy`‚'ÏÄÚØü@9ô‘Úc \"UÀóPJ· =kÛ•IôööY1C)( T+%JO¥2:T!ƠO| ¥k¸ú̀uœ³}+o!1%Å(a¶‘"eêÛ­I`\¯D¤ ­m ƠĐcƯP‘¡’Ïá…SµOvF”2̉ÑĂæ›)ÍDzÏTC²g+M-JÙ¾nå•óKơ'₫ük·ưÔ¼ï'hÔkùÎÁ>,“¤>å×7vM1×]¾iè‹­”Dibegä;̀»Ư_™Ö†Ơµ0hmÛrC_0>=Ç ÷ï¥Xä’-cœ³~˜rè¥Å–éªy^!LH´ÓÜÓÆzC%Ÿ‚ÏĂă öbßä£CUTs‘›oø ‹ơ&­8éê÷]6‘Øă₫đCŸj©Èuox F“ĂÓ ¯XÁƠgobÇæ Œ•³ơ˜ùfJª-Ơ·çY‘íÖFÓÎY(—ÜÓÚ–÷Ê¡O%LƠv8̀»"“&¿ñök¹kß¼¥Lw”A0Œ”69¼ĐjOXʶ°‰}¹@ ª¡$ô= ¾àèb̀ß|₫‹Wü̃‡~n1¦Lú«kÍ5â}åÀÛ<×LPºă//½g¯Ÿ‚/ñ=A-JÑÚÆ©++>Ÿ»s/Oî;ÈR+A»¬ä%›‡Ù¼v§¯b à1߈©Å ćÎêeM=ÙÎg:¹eŒ!*z m%ar±ÎüÂi»wÙ´>icñÙưÙHa]ó•«VCXbĂ`@-R̀4Z©ÂCàû•ü:TZhcHÁ|Aµàă{Isÿ̃qxêï?ỂÂ,MŒ̣û¿ô.îƯ?K5t\ƒ.\8om•ƒóQÛ{ʆ¤ºªî³k£BÍ+â±=oÉCûÆÙµ{§æ‰› b¥iÅ q’b ”‹ÁǿB»yF›FJL×’ññÆßăñl.ˆ{-ræºƠ/¯®Ưº½vtïQ`¨»'¦}è/^¾uØ̀7⿜¬Ecóẹ́Yl”ÆÍé/Eá¢ÏL#EiË…·´´D#NhD ©R€MØ-HIè ÂFÄܘä›÷… }Ö¬YĂËÏZÇe§ ¥©ZL35H´MÈ ƒt­8¥@²²́sx1xÙúåAëû¹ä­#˜m¤l)px!BÊl‡·@©¶·•ĐcƠ@H9ô¸}ßÙƒ{æT÷ú<8™rtfîgJ,Í6Á—.‹_ôXj©®Ư₫¸^@ª)‡ĐH8ºÓHijççSe0F‘¸4àÅ)c× Ø¢àûŒÏƠybÏ~₫RÀ•c¼ö‚ \°q%…À³ ÂHÑJåP2RôÙ7Û"O2z¼+YbK{ß/˦rưIlûVUB,Flb°àS =ö϶xdïa¾ơÈ~́ƯJb‰¢'´â4gđªMm®]SƒM:b¥H’”''j\¹jŒZ+E8sU™Ă ­Îûâ˜9‹6»±±y“¢Ç̃# /´xƠ+́mÀWƯ5Ÿơh):½Z¦§èºp̀çÀlă?Í5SăIk̉ơX1RXj©g%œ)€ÙFÊXµÀ¡…Íz4Un®=·åhV†;U¶*·i|Ï6Ó|¥æa₫ÇÄ8¨ qÅéclZ³’óÖ R-…L5 ÅRùYíä (yPû÷d€’뇋4wî›áĐÓûùΣûi-Α¦)­DÑŒ:;|’:ƒ7Æ Ăr$%µXª ³S¬(ï`¡‘²uE‰éz̉æCÈçcº»;¤£Ơ€#‹Q§ûR`ê‰ ÿÛ_ö]¿ù ?óy—L\ Üÿ9A ÀW¼p°è¯™kXÄ%µ–Z)•Đ£?3— ,xŒU¾¾w̉Îxß©çjĂ1 ºŒKOiC* N-ç~C¦íß=Zk†›—©„û¸ÓFª4¸éË_ ¥$*u:ÇR †#å‘Ñ”À³éưp¾”„AHepˆwứ{ùƒÏü=Q³ÁRÓh¥Ö­OÓ6è¥Ê`°¬À&gđ½ Çmu!ÏH)˜[ ô=ªJA2±!\Ö¿w¬Ø/g̉æMœ\];¶A€80×ä=?ơ“o₫Í÷ưü70iË%#—Tœ¢Ä"} ¾È4-ÛW–@°ØJY3X «g. ›­ª'¬*`̉˜rH#I‘Z±&NÓvKoF¨Ùѫׄ†TDªi” –4ă”f1`“†‰û8đä#ÔMâcÊ~Ưɱöœ€”mAĐ̃æ„öïä¾Jåƒ|đ—>À‘©’TQkFÄIêbùŒ$WÊ\>‘5OY¯Ç6…OÙÍ !Fqáú*‡¢6b¾—à˜̀¿ØĂEœ¬·}üœûb¾?ơÁÿûª¿ûÄÇëÀ’K69…;û\¿cƠCóx¯Dn!Ó»vÙæ(Ơ}Û—~<ƒÉ·ÜVB+Ëởs¶°r È]»Æ™[¤Ö‰bE+µ½₫Ijùó;îq÷Ùéù×hA[˜Ó—ằMefv¥Z(;™ÿ®œ~[ñ7_»í×t„æÛ? \.ÑlÅX̉,¶t’ĐlÅ$JÓvlºX­|™ÈÉ—ù¾$ô­j63P­”Ø06Ê…ḉ`eÙ§™è.€®ư·½ăÓråĐ£•*¢´ ‚Á’'đ÷‰Vó¹À)[́0â©ÉÅÿtæØàŸÏ·R7¢jw©…¦ơÆ£vóI>û¯µ­T‹>¥@0×Hy|ªNœhÎÚ°—n_O=§OñĐi;8E³Ñ UVªhÅDe€`P&ï6›.0°mÆárHc~8Iˆ¢˜(» đ™X€—KböY₫1!©—ZPô4©“,=¦̉àÔ‚3ÍÂÀ³â …̀à0 䜭¸`ûV¶®eóh•™Z‹=3-Ö†l.²ĐL¨Y€¶|yƲ$Üë+`´âs÷Á%«Ÿc:jơm+ËüÎGç!ëÀ¤À00 ,̉é Đ}8ơ–Xù’Í£ƯJ̉?7ÍvíË^db¥ }i‰?r¬1†¡’G)đ˜m$L,¥hÈÀc±¥˜®[wtåĐï¼rñåÛ™^¬ñøá9¾·gœùÙ9Rc\yL§R*h*t„=kZµÅ6(ôRrơwÙĐåDT^=çT©"M’ú<2( ̉)@‹Îs¤cCnË„û>…À§T)ø’°X`ƯêƠ\}₫œ»e=#ƒO2]‹˜i*æ-Pđ%'8´SôV–Ö †̀4R¢TwéfaÔrÀá…‰ÓÈÜ —} ̣?>‰¥°¸ÏPváÀ)É!Đ€Ị̂öM̀ÿíÊ¡Ÿi&ªSj°ØL©}æ›iûâ,zTB™z¸YmOè Æbxv‡2†C ©6ÏKw¬çƠçob)Jxdÿ$ßÚy˜……yë$ÊBbÛ‘­8ˆi'(׆Dµr’:ËzÏçꈋdܤúD±‡/='.Ú£ÀV¤Ô§†I¡TåÜ36ñ̉ vp̃¦U(#˜o%̀Ơjs-Ï&«¡tâ ^ H´a¢3U‡±jÈh¥ÀT-&JtW"Ñ—‚£K6óßsú"Ÿưê7æÜơ^tF_q·y:±´§¨gmû·Ê¨Ÿ=0Ó°=í.Æl)Ă i›oªŸjè1ƯHlSŒ‹1{ÓÓ‘™Q{Ù¸ƠwL6Úf ăKZÎÜ0Ê+ÏÙ@KÁ#&øæăăLOOÓˆ¢T%¶a&3Œ† ˜k*¤°nµÖăÉ\́m¾¯$_'OF×x`·Pˆgv¾‡¯[T‹!^¸̃AxC«&\)ásNçÂÛØ±vˆ…f̀ÑÅˆÇÆÛU ¼Á“M*:’#: I”£‹1‚˜uCFÊ>“µ„8Ơ¬ Ù?Û´ß­c*ÊHJƪ¡(‡>¿ÿá_=àŒÜsŸy9̣~à]ÎiÔÍ »¥â¶Diarœó­”uCE–Z)÷^ÂsT^RfWN§mµ-a\̉ÍĐf¾A€4vú/”ʉæ±ñ©1¬Y1ȇ_»…Xpp|ûÎsàèóKu$’1’j¤IB.è~CpÇèºsR …"•J™œ¾zˆ ßjj CC#l;m-/=w+§mXφ¡ĂóM&k ÷>=OÉưpÉï2ú ; y’³iºƒnƒ›6†ƯÓMŒ1l]Y¢PPÆ0×LɆ3J2eŒÙº²Ä 7»¼ IDAT{qß®'ëÇ₫½»’~ưF SÛøÑBÊà“ùW¿÷‡ư­ÿut±iK1•Đk—_H?®«  ,0e˜0Z hĺưúYX“ẉ»»Èµ+×¹—hCêÆ‡‡K>Ăå$¸gï_Ûµ‡{ß:¡+qB§D©Bkm JñÈ»¸ö¢m$*¢èB)Y?¯ßü…§¼»áŒ;v°„m§Ó ˜ôC€₫.+\»MÜà—/REèÁé{L/5Xj%¤®-e·çIW÷.>ÅÀ6¾T+e¶¯[Á…›FÙºf„@hÎG4EÁ“m·YäƯăü̃):1²̉6éµw¦A¬ æEJ[™Ü¿÷d :¶­,óäTOJÚ]÷₫û¿?´•6$Ú¥J(Ù0\" Ƨg¹uçÓ́ܵƒSs¤­&-eh¶¢4µ’äJµ[©Á~ïCå"£C₫́7~G§c >g­.³ª2¼jÍ ÓY¼¿L}.8 ̀8 8%A ït_ë HÂB±2sàÉOsÉUŸI´ÏÿºưI –́3'~k/F©ÖÄB#§ø › 3 5îß}„JÁcơª1^uÎÎ^3D”¤L×ZéqÀ +…ÙW.ỳ9¢6,ÈMî…L›.8UÅ(e¨è³åHƯ¯]<¯Ñ§ÊĐL««![  >ßÛ¹Ÿÿ₫ưLŒ³P«ÑbqJ+JlC”,RÙœ½ÍI´Û¿tçă\ùỳ7VUB6nÚ.LOd]~MóÀ¶°Agè”ôúĐ½4ÆQk¼¼é¼ß­<Óˆ•˜˜¯ăKAèI’ÀsI&›î³Mª–¿_ …—.LÈtgjÙwèaà³uƯ*.Ø2Æ+ÎeºnsơXµI4ẽ»&—••€Ç'íù€ËÈûÙÿ…û÷đBÄ£%–¨#“%WÆ̉¢%Ê&/G*ĂÅ€@ n}tùØÓ|zZi‘å hÅI÷ø°Î|mO¤ß³}ÁÎ=ùàë.c²&QÚpd!2¿ø₫÷Œüê}wÎ:#¯;£Ÿs!@Í…§4[p] P§¯,µ¦j±đ¤àœM«¹g·¢%N HÛ₫}eräƯ™|FhA"4QªhAYƠœ0̀7"ß„¿»%à‚ÓF8}í*.ÙeÛg‡ö®ë³{̃ẫ~tƒĐ—D«,-ª©*º®â:6©úîƯ¹‘kz7²²¥•lRă¡lG²ëª„Ïâ·₫†ƒ¼ÿTP˜ ¢€w]ë/€óåØđäæÍoMmÙ”ÖÄ+}sœ˜ÊăIAo{–kY0yî`?¦ñ́2–Ëâ"íú4`•‚Uôá®̀35M!­k¤*ÙT’Ö†,Ÿ¸©—¾¾~pʸˬƯ^Í)T=ù<9¡a¶·6S4Ư³É‰qæ †iE¼¼ăS£y₫ ´ô$RÙv”‘q`ÿ~ø3*‹*(H¬d÷́́á̃[®#gI N101‡"àßưÊ6& se< ›:jùä¿ø½Ï>ö#øư₫Sø½ÿáJ¼Ë‰Aă`™ØöÉ·¦>{G“­€6k8l[]Ï™é"EÛåµ¾Yöœ˜&›ÖyߺüÖ7±w(ÇÏ̉7g¤¤-Vđ¡JY©P„/(ªúcº¦¢«*đ(y:›Ö­ä¶ë7³cC'S‡í=Í£¯ï¡d‹zŒ¾̃ h! 2ºÆ†®N̉ºÊà\™„êë0nYQ+n¿₫×NSÙôS#qúÀ9Û-ßơ§†gó§TU]︰¦)MWS†é¢¸ïƠƒ°V[c %˧£®M'¹«wŸzïF̃å©# S“Ô‚ÁĂv½ÅÏ“¾Ú­¢ „_\[íĂF`;ÎbO|¹2 D¾#cUD_U[Ï.¶ă s Ô&U EĂ}V¥`}Ù7ÖJ.ŸĐ4T¤ĐX»aÙ±]·óĂư<ú̉a¯Â¸$‘Xn`½B «ÇÙ¤N]&É›Vpp¬NLʦŒÆŸùÙüäÈ@9Z”b¸ĐÉ̀äŒg×´7®Ÿ+Ùœ5¸wKyÓå̀t‘·F˜-Z˜‡íJl/,úUâå¼ạؾ\)é¬Ïđ‰×ÑÛq-/ŸăÙC£LÎ̀c9>é‡íTøUEAWW4đ̉k§‘TÔw–äđçPư­>̃Eè^jÄ,₫ ¿eĐ[ï‘Ö5,Íïlx~*‹D!B(Ô¤lîíáµ¥…©¹̃o>³Ÿ”®àyÁ˜°'+ƯEÑüöiJ×È$uV´6sMw½+›XƯ˜â¥>ŸIHJĺö,ùÜopö¨TÔøăÀù»[»Û¾”7½ß›¤¢°Pö)©Ú²I>¹­“|Ùå̀t‰SSEF ¼@ËCûĐ3 ÁD̃àñ}#86¶f¹ïæ’ÉG'x³o’ăóׯ ÆiUáÑÖÜÄi?tVU4W"•ÊÀAơÎ₫ù ̣m=çWE(dSOŸ£¶¹ Û Fƒ R¨dëêÙ¼¡›{oXOGG??<È£¯Ÿapâ 4é …Ï`Ú̃âïđ«ÿ¾Á'UA:“fESÛ֮ີíd4Á¼a£« '§ R 3ÏưlO®ïÔ‰"•%¯P$ÔˆóÿÎ{+ÄcS3¯××Ơ^_v¤È•Ú² Æó£ HØ̃UÏÖUµxdïPĂăyJ¾t·ăú€.¾€DU}3NNåBĐÓVËGoØHkm’7‡æyíè ăóyTÏa}KƯΑN&p]S+́2 É%÷û¶k°ôWù‘JBשɤȰaÍ*f™Ê•¨mnăc7ma×Ơ],Xdž§yøù# ͼAJơ|ơcObI_1©ÚèS‚T4¶­mgăêvt7SŸÖéŸ-1•/“PüvagNÿ¬¿•(A¬mÉÈưá¢ûÿ6•MÀè₫¿A ç‹t]@yàO₫ôKß₫êŸ=5:_F௬¦u…”¦Ñ†çË̀¾S¹º=Ë{»˜,ØÏsd¢€i9Ø ~dàB#ĂÉ©<'¦̣ %­u>¾ëjÖµ¤yáä醼Ta¢yî•1fÏÅÉÏFÜùå!Đu=“Àv¡gU ;VßÄmÛ{é›-ó“½'ùO½Œa~ïP¤Ä´}Ñè DR×È­¿u«;ع¡“ô´áx’ɼřYƒÖ‡«̉Œ,”1lκưsetƠ¯ü×¥4^xùƠü±7ß½¿Me¸À̉í¿8ˆs¡ó̃—p3°y:ó7²D¨ ¬¬O1oØœœ6P…Ïy¯ ü8Ó“èª`E]‚–gf Œç˜)R´ÜŨÀ^ÔÆ«lÏ…ĂAÁºÖ,¿±sO›Á“`¹r‘àí₫Ă4UĐQŸâír‡ ü}U4¦T<׿ûy₫P?Ø%@ ö#|à µÂe©”®‘ÔTjR:-Í|pÓJ®_¿‚” # &c9ŸDUU–Ê­mJ“ÖưĂ¾¡ªâÓ€ïên`ău;ôW€MüåŸiüÉ¿3Á ÷â >g7‚¤øó—_ÿÚ­ïÛơŹ¢-!Ä̃Á9Té̉ƯROJSè›1(9.z°ü0²`14g’̉ńnà&ó&¯̀12obZNÀză,ÎÀûO£¦NO˜/{|÷ûOQ̀Í“+–±'̉–‹̣Ù— Bø$›Ểo^²7PABרM'ùĐ®í¨™:ö;p,\Ï]¬èºhô UJ¥Y×̃À=¼§«†”ÊĐ¼Áñ‰<Óơ'ÿ‚öaXdÍê*ƯÍ×el¾L"¡ûÖëÁꆤüñO÷,œ¬́ÿÛ,Ưœ>/Ç@ “„ëÁ̃~̣äÓw~àæ/: i“Ă“¼ufŒ’+ØĐÙÂö«ZÙĐÙĂĐ|Ë“₫¯*p<ÉÈ‚‰'M̉ÂƯ›ÚÀÉéÇÇó Í8AzA¢)p|¢ÀúîÚ=Çô ́ø½p±XØ“—ƉÊèmÔ‹óÖdäçüŸT$Ơ¯ud›;x£oÓñ‡€@ưG!¥i$5H¤¸¶«…kÖvr]W)]a²`Ñ?S¢́¸hª‚‚ ¡)8®$o{4¦UÖµd(Z§G§xè¥_0<>I¶¶/üêí˜GZWYƯ˜Û?ưé₫xG€æ–/~̀c¸P!Đ̀‡ỵ̈Oü̃ï|î…lcó-ª‚<0¼ ¦̣¥²Í̀|}'È&uºWurkï vv51¼`22_FQºâsZäät Ô&U>ÔÛJCZçàX}C Læ ê +rMwo<‚o|^…G0üï"ñÆEÆô¢ºœö—Ë«~^•¾ ZÑñ¸y]#{ö øuTU!©)hzµÍܸ́’÷ohÁñ$ă9“ă“%\)IU45ø³l—Œ®pUsl:Á/đ_|‘Éñ1̣Åëú:‚ƒF_>L®mJñÄSÏ.LTØBê¯9*+Àajđ®Ưÿà̉AÀB©zäÆö[2º"fs9e›œáÏæëªÊ‚f2SèăèéÔT†_{ÛÖ¶S›ô)¼̣e¡€ôµ‹–G̃4é›-Óָĵœ)ñjÿ–í28orצƠÔ¦“  S_ ‰dH”ὃ»ÂË5UE!ÔÉÔ60jêdÓ:Y¡£©* uơܺ¹‹íƯM¤TÁđ|™½C9Ê®$Đ¢iBl¿~ƯdUCöÚ{ñ{^çt_?fÙÀ0mJ¦…m»xHj’ *¼̉7‡¦ ÑƯœá¶ß¹à<̃aï·c¸¸(@J¯üÑÛvíÈ›_Û?Z Vƒ’æo¬9.>¡… EÓ!§)¤J»_<È^9DCc·nZÅöîfkRôÏڰϨ)‚‚é2W*ùÅ´´Îgn\ÍlÑfÿHµM):W®Äu|â ŸtĂ÷ẫâG?j(ÛîÁ̀+Q₫AéW!RÂê¶&u›z»ÙĐÑHïÊF’dtÁäÄDœé´é‚¤æÓ¬;®GMBemsUƠØjˆï¾ÖÏk‡N ËÎ' CJt]ªªaäfäÖukxâÉŸåúư¾?çđ₫óËxÿøÄ]€‹º?*œÔ_zëË×¼çêûöêçù#CØeƒ’åø,µ‡çù– >_]BUH&4̉º†¦iô¬jaûºôvµ“Ơ$}³eÛ „3+9¹ăI2ºJCF£.©"Oœac9̣Ü /¢r GUÄE¯-™”. ¦ ²©®'Ï[L,_4%-s<‰ézÔ'5V5$ñ”Gú†Ùj˜}GN²07‹a9”L Ër°]wQB=”Kè™d‚ú µ5̣[v_Ùơ®Ùºí@ÿáư!ơWŸç/¬ü÷Qá₫+Äù —z|ư¸,Đüù¾̣±OƯóáû̃³©gÓ/NËGßè§0;%l‰,[0Çñ‡»ª’J*¡’Öu2IÖ¶Vî̃²-]Íä ‹á ד$–¨ ù^^WM¶¬~\=Ú(»´G`®d_Ö€¿xÓE‹…²ăÏï] Ï_pÄt|6䮯ª2<›ăǯáÔÉ“äK%Œ²éÓ‚d!®ëùƯà¾éJ*¡“Nê2­«¢¥³›[¯Û oºv“p‹söo~îwŸ{âo§£.á₫ĐÀ0|?‰O —*₫L@Đ ¬^Ư»íÚOưóûn¹ÿ₫ÏíÊ+Gå§D±lS¶mLËÅt=Ç­°Ø*₫ÈkR×|0HhèªÊ®ÍW±sĂJ:듌å,reÿƠTXfSF'¡ NM•@–#ºÜà_¿m+ëRX®Ç|ÙüSú  MĐNĐQ«sl¼À3¯âè‰S” yJ–ƒaZ”mÛv‚ˆ ÜRü¥¡TB#™Đd2¡‹úl¼é†mbGO7›;³̃üï_ø¡¯MÍ ÷Áû₫ Tú₫}Áöư‹¼ËÙb¸ü£Q@Đtë¢)ë·Ưú‘?ø·_¸úÆë¶de2­ÿđ3̣hÿˆ(eÊ–]IÁÀ_‰Mé>$A¦¾Û6­dkW Mµf‹ eOÂæö ç}Å +\ë‹!U¾'.øÉήz̃Êù‘"h¯M’Ij™á•Ç9xz˜ǜeGR2­à^øb§á8sH’ô==t´µ°¥·‡»vôṿßưƯÿùÛƯ?Z8úÚùHí**èb¹₫xàơû—ñ₫q₫ÀeG¾¤t°èÖA LƠ5Ö®_·®öÁo|}ư ;¯¯₫đ¤|åhŸèŸ•ç Ă´9Ư€,Cßë%0H%4ºÊÆZñ´† «Zi¯ÑPU•¹@ü°ÊlÎ’B\̀ƒ#­5:¦#±„ÆñQ̃<5̀̃Ă'X˜ŸĂ²JV%¼w"”f>ÛBR×I'tR ¦©kÖ­’¿~ç bjfÁúÉÿ~|ö»ßúæÔñĂT¶ø¼ˆá‡ >áÔß 0€±Àû‡¹Üú‹àmk¶VĐ ÔiB* í³ÿáÏ×úcw5¾wkoö{//Ă*åEÙö(̣V®çâÅ;%,v©~{-›Ô©I%ø̀Ưïå‘ƯßgvfƯ_¡€À†Q€–t=At/@œçE~~®Q“Ị́ñÛ®çÏ¿ó ErEƒbÙ¦lY¾Ñ;^ ÙÍ"HB×ü¼>¡‘H¥åUkÖˆvç.zºêyø¯¿7µ{÷îù~̣ÄÜ’`céfŸ ûÍ ÷ŸÇ'ú R€‘àë|́ưc¸RQ@¸Đxư %hƒ!¤ HJMGwƯ7üj÷?úđm}9W¼|èŒ<Ô7"J†)MÛeÇÁ´½@k@óú*™¤F:©ó›}_úâ`ÎMQ2üa˜%§º„//í PUUPPüe‡ Å,&,cÿ₫zr&•¢¶¶†ï<ô5>ñ¥o`ÛĂIJ}ÑR(!…·¦‘Jê$u•L:E{G§üä­ÛÅö«åçËưÍ#Í<₫đ×' %â­£ë¼á&_høK[~ÓA 0ÿ<•åŸ8÷_æÄsÂÑà2~«)ÂĂÏùjƒ«&‚tq¼ßúµtú§ÿ²ë₫ÏÜ×ùOáhÿ¸Ø{fLè›cb:eÛ Üï•—-?t™™ÅœŸ£`”pg E¸ u!WwBóØ¿DŸEøº~‘è ‚/•!|ïŸI§ÉeNç¡P¶qÛñÁ)©k$tÀª ‘ɲ©«]̃yó±¢¹Î:~¸øÍ?{`̣¶ÿùÍ™ª(+̃‡̃>$ô,—ơAxŸ îÿl̀ï‰É»œơ7€+ ÁĂePQœ©­lp…`zæ‘oơ?óÈ·W¯¯ÿÇ÷ÜÓ|ÏƯ·7₫ëûïj}åÀ üÁ₫A‘›Ÿ•ºUu¡6®UÆơ\<×[Ê 0çxE€wöHđ…G„Ư@·@,y¢ˆ€¦,ĐŒàˆëz>I‰e3k©¨Z=éƠU…tBCƠuV¯^Ă¯¾ÿZ¹eÓqxß₫â—ø÷?Úưè¿Lx†øVäϦ±ÑÇđ÷.EĐ–I2ËDu ˆÎèU .ăư~'D1¢’[Ëyûb•áç#W˜ó˽¹b=¿₫^G"Ơơ‚ ¥5U p)"Ơi¨ºä€¨×79»__}•ªyQñN·ÊÛÇ>€P` TA"¸R0ÈV]am ÁR™«K‰FÄ%¾îR ôüK鸣— ñ­àª6úXÄ3€đ÷½:2Đ")B¢*E8Wp1ïcơï\9}¼hî²|¿´Lx5zgƒ ?€we ,ÉÈ¥S)^¬WÿùƠŸ_)ï¿\₫oV…÷Î2̃>6øâ³LµÊó_ªv'Ä~ÿeDÛ~K‡sÜØÓÇŸKK”*£¿ÜđưÿU@rv/ÎécˆÏÛ®¿Sï{Ô¸½e¢ƒøÄ'>ñ‰O|âŸøÄ'>ñ‰O|âŸøüÎÿ$le:nIEND®B`‚cutechess-20111114+0.4.2+0.0.1/projects/gui/res/icons/icons.qrc0000664000175000017500000000054311657223322022555 0ustar oliveroliver cutechess_16x16.png cutechess_24x24.png cutechess_32x32.png cutechess_64x64.png cutechess_128x128.png cutechess_256x256.png cutechess_512x512.png cutechess-20111114+0.4.2+0.0.1/projects/gui/res/icons/cutechess_64x64.png0000664000175000017500000001061711657223322024305 0ustar oliveroliver‰PNG  IHDR@@ªiq̃sRGB®ÎébKGDÿÿÿ ½§“ pHYs  œtIMEÛ &ÓñtEXtCommentCreated with GIMPWêIDATxÚí›ytœåuÆï÷}3£™‘F’­Ñ2²Vk±%y‘Á–7lBRئœ””:¤)d! MNJSN{BCÉ mI„6n!BXâ8NJ‚¬c#°°l­¶¼h±ö}43å[̃₫1#!̣G-,§yuFG3ó}ï}æ̃ç̃ûÜwàëÿ÷ïÇMNöpÛD‰/ƯuC ¢w:UÑíqÙOH)Büađd]{í+':·o©XBuq¹‹’1-óW.M|?7Ưưâ•@™ï|ûơ¤”̃ÆÎÁíĂ₫/¼q‡Ÿ?̀ˆ.oȺÆ#̣£ßă}??™¥Í÷ >»)Ÿ¬c¶÷1ăéÛVb •©¨!$đæ¡Ú3ÏưÏ̃́ÆÿàBàg'ûŒS~Ơ4 LƯàæµKq%Ù‰&vU¥ºĐ{42ü1đ$₫ƒà̀Hè't=ÑMÊ3œ<óóZ4›Æ‡¯­ º4éZD4Öí*ơ²,cËûIŒó'{ư÷DtK"ÍåàdÛ)á(jT§t‚Ÿ|ƒ»ïü!Ă&›̃Ø}D± ˆ]ơ$(¥Lí o)̉47Û:Àö5åjhaØä…ŸưœL·€æqYọ́ÑÖêUÀ÷uM“æâơ†&,)QT…p4J0EÁÙ₫Qêê’æ²aZ’NƯ³ëG¯ưÆû¼00¹ÇDJez‚³ư£ë—q¸¡)%NwÑÖx O’é˜.'’ îÿîsû?;ß ̀ß?Ü©­ÊMÍ·©(ơ¦đ‹£'R¢**̉2ˆè:¯ưVC]§IvØ„n̉S¶î›ß|̣©ó¹Ïy»đík|["†dKIư½]ŒĂ!غºŒ×·"e<ÉÙ|$Ú;{ñ)|i.@l¸éÅo<ñmóµ×y ³®ÓTX–™ÂÈdØ5Ở‰&˜›‡¥$-ÅEz›‡¾÷z»è¢s,,}5»^}́ñïl,(*W –%×H)äÛç˜ÆÁ­«Ù¸²”Gă ĐŒƯ3 °eM‡Ñ-‹ï½vkÍz±àoX'»Fp9líèçÆ­ÉÏ\‰ ¤¤0;ƒIÉ`蘠›’ÇŸ~™4BH¡dëmơ;îüøÚm/—=ŨªÊ ?¼93?ÑÑ7Ê‘ö^°º8‹–ºF¦¨^^fE`×TjV-ăµă-qbL”ÀBbZ’·[:øÀÚe„,Mc–È/«Úă¶Bû|ÙÙCÍ-Í ËLÓD,±« ç,/°kºa"¥ ±sœÂR®[QÊ7TsàpC¼ZqĂsA€éhŒÇö>OºÅ’ˆLTỤ̈‰7ggẀˆ* *¦¢fVËFçđTœé…D°d"ç#8Ư;7'̣¼̀9^/ÈwukqB‘ÿñĂ—¨ôÚ¸±l±¨Èñ8₫æï¿ÚtfĐÿ́ĐdhË‚ÀeS„?%;=™­•$Ù4 Óº¨•€Mûâ<₫î“%359Î RbaÍ/æ4¬¹Y‹yîp½|„úÓ½Â)v‡ư©êˆÈ~,ă÷ípç¥4,Ë!„àÄùA4Máö ËèŸ ÏV|3Ëé°cZ&ºææ₫=»yéÀ+?Ư…%%RÈ‹U‚eeéF"én¦gdk+‹ET·äTwk÷×¾̣Åÿ&®¨è&ÙR(REtwRû‹ŸRæ s]I&)Î$ä°Ç‰OLFMṽz3ưĐ&´xœ$l×k–Ó1 ›¦RSYHT—,ö¸Ä—î¾c(ư}m6E "QíÅtCñ³Wjyæ¿÷â8Cun2Yéqs…P £ ¬‚öÜA†Ç=[((JJJ™ Æ+H!øđÚ‚zÜáë~²wpdx¸8L^qLK&Á;Ÿb Ăå°!¥Ä°,;ÉsÏ>KWGÁ@Í̉ñº5™Ÿ‘‚Ưn#æđpÿ¿Ơe(Bpưº•ï™+ƠigÅ̉\B¦Ú¥ơ_úÜà(p0¯8Ä¢9mÓ1»Ă9W)A#aIÿù!TE°uE±¸weêámÛopW]»)½¸jmÚ'?rSjûÙ.å”!§Ï ˆ™₫aÇuåL†Ḿ6Müđ_êºWÿ‚Ä,i:4kË|„u“˜aáĐr±Ùl8’¨B [PQ”K®iÇ´$±XŒJƯÁÚƠ¬uK€LŸ/7kÏ7~´U‚”bIF 9^CJÿ`lï÷¾Ơüè˜Û\^Q$èB»‡ G <î$É´kÀˆ†1¥DZËN4»hLG‚ŸúrnÛ_ßuè’Œ₫₫>ßÄÉWÛ³}ïœ đáuåLE ’]NñÏ÷îp*Àô‚©tSÆLËÂătÖ †'ƒD¡`€ˆn &¦”Ô9FY¦À’’”¥kªL†€V ö‰G¿ú×å%7­̀Ï”i©;ƒ­oN½v°¶'áúT!”¤23%^s¶*Ñ’á°k í#₫jL7¿pn¶tié›àG¾¹HŸQ‹½™₫º½~zÇ*_øØ/~<øïŸ»£ưă;?p8Ô_‚̣órYYä##ÛÇÊÂ,¼‹H¶©¼unˆƯÛVÚ÷ïÛW æ€y›@öŒ‡eçÈ>ơꬠ*‚ÊL'µëH,KÆÿ‡dû†µ,)_Åñî1lª"?}qhëÊâ›#€uƠÍ,Ë:ër¨!m°À´$QĂ$Ó‰Ä tÓÂ0M ÓbJ‡®’v Ó"yQ̣ÎÛn¿p]•“!)­‡Í`=v°©ï}K ¾ƠDy† O¸ù#w̃ä\•)Ϻ́*Êœ¼—ưâ©0ÑØđSÆ%³c äe¤2²fă¶k€2æqŒ?o¨BvØl64M¹·fñ^fDÆù¸½³—9ÍT8J /|ùÁ]BÏU–ỹ© 4U}Ç` †µÄqR4°¬øßuGêÉNsc˜¦Ü¸íƒ×K)óæ‹°çoêª(ÓM!=Ù‘¨₫âÓĐ˜¥üVơ"4?-#“ZÛZÉKM†K*Û|́s̃b++Ơ)F"5Ë )̀ bY&ƯĂ“¨ª]UfG`‰´,¢R%×»˜’Â%hªB0cÚdx½n`±ƯîPc±è }0Ạ̈l7CSÑÏLâÛB Û.ŒÖTE¡ ÓẲ́tV—æÍ ”’˜•…9ŒûƒÔ7"f˜xœ>sÇÍ”.«H>?0úÀ£ỵ̈è¾ÍëV\ؽû®… @cß˳ƯŒ‡bß•p¯©*EÄ?mÓ²8?8‰˜àĐá×ßu LâIÏàTgïÅ5‡ nÇ÷È×îÜ·ÿÀÚ„î·°8 ¦›TçzÅGˆ{-$QĂ"°«ïÄ9€¦i( ewöÁ;ø\û½É6¤Ư’b$¨+»vÜzâèñ–;œø#ú²@DÍ’x£F| ær؈é&÷|°Nt s¢sU±âgƒæL”Êî$kÊ ¹fyk–!-§]#5éb‘Û.++–=sîÂÀ5Kór¾pÅ{_¶ ³ÜëV=.›1­[R€°k‚‘©¼x˜µK}TgSæË˜½“ß »0‘*Yrr²IOOĂ®iH)iïêåxûyê[Îđ±7R’›E²CÁ’à´)´´¶ư†ơ«JÈgW®ê ÿ“*ÄCñ–&~Á³ă|ù©W±,‰P.»u%9¬/Îàl{ó¬Û§»l³¹OJIV₫Röm¦¾å,P8á%đàƯÆMë+1eœ4MË’cÁˆymáâàíKi–.9,=ö–¥ÙqÚ¦·ÇçMăáƯ7p²súÓ½ôøMK7C<ó­GA¼ơH‹[î}€ăgûPŸ7«Ë©^VJui|@"Eúü1Œ©qØĂưW €|oê±` ±’Ça±Ø“ŒnX,ñ¦’›‘ÊÎ  Oiíbà\›¶\Oâ ÀEƒÓ²ØP–ËæuƠ¬*/"/;“¨n WP‡ééi v›Müà‰¯÷̃K-.KyÙĐÚñHÛ́=ØŒ/ƯÍú²\ª 2)̀ô5,D-ALß9LH±C8f̀ÊäIvs}Ăœ8ƠÉ‘“§9Û;È_íº­.ÖWåJè‚/] \–,ëóY]Ó£TẻÔ= oœâÅúÓdx\Ô”ûXQ˜II¦‡X̀˜EÜ| €ítÚ›àí³ÖéDp^ưr$oÊÁíÓ+ÉÙUËí*WÆ–ö̉f Ôâ$])|½ĂdÆû‰Ç¢lî́Qy¸Đ üE ’ë¯@IÑhœràë& 29ÔC<å¾̣ÈáÉ™­OSä”*P*üñơyˆ­D'̉oIEND®B`‚cutechess-20111114+0.4.2+0.0.1/projects/gui/res/icons/cutechess_512x512.png0000664000175000017500000035207011657223322024443 0ustar oliveroliver‰PNG  IHDRôxÔúsRGB®ÎébKGDÿÿÿ ½§“ pHYs  œtIMEÛ  3†”¨tEXtCommentCreated with GIMPW IDATxÚ́wœ$WuïçVu<³7Gm̉å,À’Q@°„1 ˜h̀~ØàÆæx˜œAÈ"["Pλ«ƯƠæ¤ÍqŕTU÷÷ǽU]ƯÓ³I²µ÷˧èÙÙé0½9¿sî9¿X,‹Åb±X,‹Åb±X,‹Åb±X,‹Åb±X,‹Åb±X,‹Åb±X,‹Åb±X,‹Åb±X,‹Åb±X,‹Åb±X,‹Åb±X,‹Åb±X,‹Åb±X,‹Åb±X,‹Åb±X,‹Åb±X,‹Åb±X,‹Åb±X,‹Åb±X,'ÆO×v÷×:n¾a‹åEƒ́[`±¼°|đ×Û§\¿¸ơ}¯œÓTÿÄ03ºÇ<¸‚c…àÑCC¹m·¼zîêc=›H đ}û†Z,+,–S™ßnê¥×.nă±bđ5ï«M:+JøJÁ D@BP¿+¨¿&étüUûGús>Q*ç¿ë)¬y×Å3:vÁ… ûÆ[,+,–›­:ôÉë·₫Ÿơ‡³4T<µ1EgN© ÿĂŸ9f!  „@N9GĐÔºCc`s!÷åOû³̃SyΔ;«=ÿ_½ï#ôă¯í¿„Åb±ÀbùàÎ =xƯ’vH©¾,ưƯÚ̀}£yR̀pg̀Ÿ‰Ëç5•Ưgă‘1ä<…„C¨I8 §‚\Aè¨KÂf”ƒù•0ñ¦#Y(f 惌Rꋯ7é£Ñ7…÷=Dügß ‹Å ‹År²Ü±¾¯_ÚŸ­=̣Á g6₫Ç֯ܲ‹Å"Å`Ö—HfPÛØ‚›ḮÄôæ4À„]ưy çŒz‚!I é„3r\Ah«KÀư ̃1{ đscËẃÚ½ƒAxÛUåĂ×*„ ¥Teà·BÀb±Àb±œs¿-²›̃ñé¤ó¿ÛÔ‡§7ïD¡à¡H(Å èÀî @1ĐÑ5©Dï8¯ ®›@Ê( ‡FÈù yO‚kA@€ YPØ)W€$B]ÊA{]‚ ˆH<{pèízè@Đ”øëWŸƠûÙ¯V°bÀb±Àb±/?ZyđêÅuw-ŸÚ ¾ußz±ăÈ ¾„çKHÅ`0Ap„@Âp H$0]˜ÜÄ«´!•LbR‹îQÅ@a¸`¬(£V×Ñ@¾¥ØO03pAè¨O .é€@`[z²È8ô`.;ú飲ù̃z{À€Æ–V1<Đ+,+,Ëq²Úcœ•$¬ØÓѬÖúÇ7́ÄïW?‡\¾€œ èËè@A‚ăF$]̉w„@2Aç¤F,ëªEgkwêæÁîQ…@!ëI æA߇"‚€®ÄiSh¯O"“œv ä| ätÔĐçV́î]±yÏï>ù†ówÀ¹—₫™³̣ѹJđ·BÀb±Àb±ṬïÜ1é’yí?[ĐQ{ùÛ­û»‘/*ä<ß…°O—ó ®£ƒ¾ë-\×P_߀óf6!S׈®Æ Nï¬ôe}ôe=ä<…œ/uÆOúhH "`b} é¤\B}ÊE&!¸6éP÷¨—øÑ¤ÀÆû·÷m|ưS¿~O-­íb ¯ÇV,+,ËD°̀·xnï¡Ñ€o}d  [ óx± @øf́)×;BW\G ‚¤#"ÊdĐ”I`^gê›ZpÎÔ:´Ơº1V”ØÙŸ¡H¤\-éN0ÀL°j̉ ÁíuI€Ñb0êụ̀ñ-=¹–g¶́zÛß_sö˜2}–spßn¶BÀb±Àb±ÄøÆ½ë̉s¦O9xÉÜæ–Ÿ­Øƒ5Û÷#[đ-úÈû¾T¤̉“æ>‚D¥³|G˜£¡AX p]-@̉u‘N'Ñr0mr'Én\Öf†b`¸àÈHẹ̈¿>ÿ^6H„¤CH:Ä i—Zj( )—¯Ø;’-*ơʹ-ÓĂ»œyÁ%î§S°Ç‹ËŸtæÏŒß>±!Ơ5mFaZs†¿ñĐ6êéîFÖ -ếß t 2Æ?e?|½ ‚Cáñ€itĂ~IW p‘N:¨M¹˜1}:¶×`Ù亨Ê0”0\J?áLđ¤‚b†o&â¡›Í&]BÊÜYŸ¤”«›™‘{l×KP÷¾r^ëkC “L¦Èój}a=,+,–—7·=sđ–¿‰Îú¤ÿ«åƒAÁ—Ø»cë́ó́®­op³£#a¯ÀD‰…‹ËK›O¾ơ|ơÑ=—^1Ö¢¡¾ đ¥„”ºä¯˜c x •"  ´Ä±A₫z#t€˜!C ĐĂOđ¥€¯5˜×ÆÎ₫<s~Ốg#˜’>/BÊÑÇl„D̉¨K9È$\"¸.P“L"çÉè% "‘tKºjÍ·Ơ°ëk¿æÜ÷_}öjóû$*ú¦́Ñ€Åb€Ạ̊ràó?¹n¹ù >ofó#R1ÿfS?< R¡à*Á?N…“›ŒM÷>+]`¡k‚€€ Eôøé„ƒe³;‘-Jtx $¨TyĐ|DÆAºZÏÈIóY Ós‰̃¬æ’áPÂeGêSA¨M8Ô˜q1î¬Ç¤Íï“°IPÄ>F…°Ơ‹Å ‹å¥Ç-7_Á·®8ôñs¦5ÜÑ¡Aø’ )ư‡åÄ¢]µºxYj2! 4›¼:₫˜Â4 677czc¡(\V„¹ïøDD±ŸăÔzÄ܇|9îơæ,j¯å}yÚ»sû{ÔH@/*bsK1 ª}Ëö¿&‹åÅCØ·Àb9qđû³û_z‘A 4¥z“ưëXÎ`¢ Åă†üQªl&tà.ÿbù$\I‡đ†³g`¤`ÿP1ú6<^ ³ă.Å]Œñ—WŒưϼ®ùm5h̀¸ô£Ÿ₫̣濹ê‚ߺ‰D“©¤$p8æ÷Œˆ}»¨¨X,+,–S›}ùV€7.mÏ "<µ~é³_IR—í+»₫Çe₫\₫qåfø=)Ü(Nä à !í]SĐ˜ØÔ…#Jóÿ:½×=̀ 0•TFµ ˆ^s¹@0w%í,¨˜‘N8hL»¼îHŸûà[WQGàûµ2æJ!N`+Ë‹ˆ=°XN€ÿû¡·̣Wüm̉§}åaø¾ßWđ¥‚” f…ø²]¦êI.•Ñ—§Ä•‡ådœ]̉Á?åj?€)Ógâ½OC̃—èóQ›t@áR˜):ÿçcÅZ.=ªFg]I¤Â‚¶4Aôë^ơzí̀(đxæ̣c™`®5₫™-‹Ë)Î_Ÿ;¹vï̃ _1|¥Ư₫”̉®|ñ`+bI6Åo¹ø¹Jƒ™sûxöﺡ€@&©=ˆ«öạ̀;´₫=.È4–ơèÿ…®µ)m@´jÿ(ö́Ù“Đl‚¿gn+?öQƯm%Àb±Àb9å ˜ááu=ß.—ưzc?|I~ ƒ ëîÿxùŸ1¾¼?.ëKÁ?Ê₫E,ûwsfÍÀ».˜‚¬'1’Pfÿ¤Kÿ's¼^Ù©À0f©dÆ´Æ'¢¿}í%·ô÷©….ó̀m̃|/ùíđÁ6Z,VX,§đ ̃÷Ë“®XĐ̉Y›tà{Ẹ¢à¯ ñĂưx÷}5k<ª¸Ê¡G@̀ 0tL¹œD yf`å¾Q¤¢,û§² ĂÉÿ’]0£)ír:•¤û×íÈù­æéÂàŸ7WÂ\¡@• ¯0¾÷Ñb±X`±œœ1­ém‡‹W7Ơ¤øÀ¡CäzÙ ç₫+FÿBP–eSù{µÚx8'̀f¿’ °AŒ MG:™@_ÖGÁ—ZIJ}ö_ê38Q!Bi1í:XÜUGO?»¥ÿÍ×^ơë{@“ ₫•ƯÿŃádÅ ä@¶ `±¼xØ)‹å|î¶»—̀j́›=)ƒû7î£áœ@™±?3éÎQ:¯cÑø ̀ Ób̃ŕ¢XöOfÎ?áè‘¿”ë ][‹fOBoÖÇúĂcHº …đÈ \p<¿*@(`̉ ÿơ«_î́9°Đgÿ F4«@=€Zh_€´I“lTÚ1@‹ÅV,–S—xË5øÊ#»Ï˜>³oÈĂî!H)¡Ôø5¿aø¯VÛ7åMè `Fø\SúO¸©„AÀ«æw`rSgH…„£Ëÿ:_/eÿÏ'èSÉ FB̀m­¡‡}¼ç{ßúÆ€ ö ́ñó~˜̀>@i" in'´X,¶`±œz¼ñ]üí…S3 Ûk¦öd}Îû*²·Ó¥z]¦×k|uÖî8×ö8áå8"̀Ø)¶Ñ@A¥ €® ₫é„‹”+PßĐˆ™“p`¸ˆ1/öXa8¥2!ÁÏ·¨n³!ărà©Í{¼‘₫ni²ûè™ÿøÇázÄ{ªe₫VX,/"} ,–‰Ù¼úiܾjßœ¢ë2ImØGưĂ#ÚơO²n₫ Ơ´ ₫Âf'ÖÄ'ÑŸH„@™DF(¸@̉ÑÁ?tN8xÅü\|Z¶öäóµå¯#ôcųÿ°đ¼Î₫ÍÉ<X>¥Y¹rè¦ë¯Úd‚:Å:b™¿4™˜ừÇÅØçóu•Á‹å{`±K% á " ç ü(»!™p@¦\/Ëœô¥¡€Rs >µ×tˆ¢¦¿tÂA&ᢥ±“;;pp¸ˆá|€„Đ•AƠƒY`?J#`¼ä“›3­uIÆ£Û¨L̃¼z8vy¿̀éƠ -‹˩ço»7ÑVŸùÈ9ÓđôsƯÈçóBÀºÄGûÈØv¾h `,đÇWü}lpÙ@Úu´áOMœ>gM©Å³G'¨¾\¨JH­X8¨ÀQĐ߆‚@1£½.…y­₫æoûè_]·‘ˆR̀.ûqL&_Y ³zû³ ₫‹Ë©ÍÍïư©çdkí…S )IKæMG~tÅ¢‡@)́̀#PŒlQj¿|fxv”~¬tP1׿(øÇv˜)4ư13ÿ™”‹–†Z,lË {ÔĂ‘Q aµỲÆ_7P7~Đ0 ₫d¶ —˜¼‡"`^k†rưÛ-ïÛ Å̀•ˆû°ù/ơ /»•VX,VX,§…@Ø[@0“‚!È€£ü_*ǼÖ4\GĐ_\ăùW ₫2üă» ±CT6û·X^d́®Å2¿Z×½₫†¥íK~¿¹Û»‡!ë­J2$âüå[ôâ‘Í!}¶îˆRÄsM0®M: ÇAM:…º”ƒ„@ÀÀ5 ["s¡‰áKFöâÆDñuĂy_áđˆ׌$æ°$`Å@'ä‚‹;kq(/0§V  ”—đĂl?k®CæŒ}½' <&± €´X¬°XN ®}óßĐïnÿReÈ|÷郔ÍàK†'UdÿËÉ+Ûé[º¡¸E°ÉºĂÊ|äó(øÿpÅ<8|âÖ?"å:@"…ºÖ.$Si03fOªAB®ZØr̀ï). ç—áÙ}J2£ò‡ă¸´qƯ¡ù_ïÚÔwpï è9ä‡MÀß5 ñGl€Åb€ÅrÊqçú½×.n(ÆW̃Å€gÅѨ_Åé£Xđ³s Gä‰Ëmdd\™®–:¼ưÜÉøÔƯÏahßfHEÚtHqIX˜û'™B²® 5µuHgj0f6gpặvDw ÷„ÂøÆwMCT₫¾Ø̉[„dF‘Á̃Gï¿÷ư;6®}̣¿Z×Ô2)‹D:›ÈÔå[éºâê§ËöÜNT;°Ç‹Ë‹ĂOÜ›/< ÷níß~Åü–y·­>Œ#CYxCoÿ3 €˜'´ÚÇR*û•ư}€uđ×@20£µo9k2̣ă#ß₫5¼@"’câú¾ácÓÑ "CO¤̉)4¶v¡¾¾ AèhªÁ KÚáIF&!(F̃—Ú (öúEü{!*Ûï›rÅ„â¶÷åÑ3æ(¥úsc£ï]·qÓ#Ÿÿ̀§¶® boO 8,Ë#¶ Đb‰qó…§á3÷́˜wÅü–ºœ¡,”‚ ú€düUÜá*œpx¼Î¦°Z` ‚ÉG0XX0$|Ÿb^ áăwn€' ~€¢'Hɺù¨TA(íˆÙ ‹’¡Pà:P`¨Ă{‘ïsáĐºd Aøơª=xí™3áùîÚ̉vÅ@]JD̃ ‡P“P¬…ÊüÖLX9 Đ•0úÅâ:ë˜\Ÿ‚&åưºŸOmk̃ùÍÛŸØö¿»éªU}ûvª =£B`±X¬°X^¾zË»pÁ¿ÿ±aiW­H¹#ù")ÅQö?̃Â÷(q‰*â—>Gˆ¹ö3àœ9­[úøÖ}kó ¢ç£èKø²\”‰p/@l±ă©¬¬¸±WŸ³5©$₫ó₫G¡ÖoÙÆúZ\»t2†̣6ÉÂ(ë ˆï/¨öm+ÅÈ{2ê5(*Öû k0çSΓ|É́¦%ó¦vü¨oßÎyµuơé́Øhå˜![`±X`±ụ̈ÎK} >åµáHƒÙ"F”ùËÈ·¿&j«Q³9 x›_1–L®Ç¢Î:|åîµè;´/Qôx2=Úb˜+ŸbF@z=±>P¬3r"Àqđ%Nâ¬ÍøƠ¦! uÔÙ»ăă±Ơ0­1‰WÍmEÖ“ÚtˆÊ÷úTÚ£JƠ#œvˆ.-̉÷Û̃›#đYSêç>¹kàñ g·\ÜỔZ?4ĐWiT)¬°X^`„} ,à¿~;àÆåí-Í5 wGoÓđ§¢®ÿ¥3Ùø8@íÜÓ¯7!̀m«ÇSûsظ¯AP=øKÖ+ˆơQ„&J™Ï›Å2<²PQÀ–Rµ“đ——.ÂôÆ$|̣ Œæ‹úÊp¤»ßùĂÓØ¸¿×,jÅŒæ ’á+FÀẓ!PŒ@–>ö«]̉\áKûœî³½7G«öđÙÓ/úƠ³‡6 ôÖ54%¡W »æ · Æ— UÛ4h±X¬°XNϼïÍøÙÚĂïîÏ̃=P@ïp–$3”Rº®äùcN< 3ơĐ~7́äw„Às'႙ؽó9 ô÷Ă“ ~ ádü•»́J%&R¢‘?“•+:jđ­•=ØÓ=ˆ\ÑC®àa4WD¶àa ¯_₫ăf́,âơKÚP“pàKYÖû PÚx¨Tù%0̀LÏDP!¥ʾr£}‡µă` +aÓ+‚?U Œp—° ‰¡ß¿#"¸ƒLmu Üö̀!¬Ü;)<_¢àÈ}ä‹>²ù€‘ß·ûåj äœ3½ @*R÷çOnû¡ù”6W¥#»`E€Ạ̊üq́[`ùSæ̣ÿ»6=‹‡Ö̃ûçI×ùöá¢Úxx”<©ÏƯ“ƯêØGQ~<Ù\„Ù¿îĐ÷™”‹·7÷líĂ>¾\̀¡àđ¤D`Æ₫TXÖ'q©üÁË* ¸BÀu$\I×›LăU_€7œ̃‚_?´»÷́…dhc£@BJ]ÂH¸ÀH7vf]\µt*2.ö ™Añ”ÁL6„ ÑáÏƠ¹Z^ÀØ3§Eµ˜Ñ’ɤ¦,́{ä̃?ˉ‚{uëE‹Åb€År"́Úô,pö»Åç̃sÍ%Ó2×í,Đî₫¬ÎÀ£à¯ÏÀă¡çÄËÿ¦$z₫“.‘_·l R„OÿâIđh/£Hø~é ̃€¨ó¹À0[₫HÀ‰„@ÂÑ" c̣T¼î́™Øz ?¼ÿY8̉ƒ/¥¾L•¡²ÉÑq] tÂAY‡›Î aÏ@ b¡—¢₫ü’ÍpéÑ{Å¥ HYúN@Q2ºG=^<¥©iùÂ9gêé{bưg†Q~î?¡¾‚°XN {`ù“ç[_üX×â§³Âs½c(RŸy‡Ín›G;Î́¿<ø# ₫Bè '•Bm:‰³§Ơăơ=P#=đ™Æ¿ ÿĐ’/̃ư‡OpGh  mêL,í¬ÁƯkwÁɳx¥­…¥>ö ÏPđä>&lƯ¼÷o<€‹f6ấé P HVÆ2XO1P̀ X×:Ê7#²q@äprA•Ă)‹î1Ú1ÀơµùÄ'?í¤2ÍjP:¨6![ °XNë`ù“çƯ—L)yî´ƒ9̃7˜'Í₫‡gÙà“L4™A‚"}‚.™×fRxË9Sw=¶$ø^ »îcă‡Ñ|üœ?₫ر¬;¬.h@×h›½¼° »ơ᩵›rx~ m…%—U7˜U)l‡Ö¾ĂC¸í₫UµÍ¸â´0Ï…b† vêqFÆ\ª„&3AQtf û L¿w0OíàsgtùèúÿyÑüÉoBÔ(¥*®øÇP¶`±Ø €ÅrB|÷ÏfÙ•ß–r¶ơæH±*uÿ›*@Éçxc~E·?Ê“ö¼'ñ–³'cfsŸ{pà“f̃?PÑ]¥áOU"ÿ“ư ÇÑ"JbÑô.4¤|ö¾H©œÅ }¸$r±¾@*ø2¬ø(xF‡úqûƯáÑ'›„ë IDAT=Y\9¿Ó›Óº1̉y¢̉­Jă+å±›¢¦Fm´„hdpW6åsçv͹cí{•Răº™*•€‰-‹Ë1~‡¥Zr¾ä̃1¬beÿè–ÊûñSZ̉ö°:kÑ\“lX½R‘iÈÓÁ?jÈ‹—₫«dÿáD@t₫Ë₫1ZN; ¾t ²Ù,voX ©̀R!cÎï3³ö;0£{¾1"*x> ÅĂ=đƒ»ŸÄÊYÜtF¦4¦´8O$†b€©Ú;¡e…‚ƒ¢ïS2#zL™±₫đ=³„¯_6¹ưÎg=)ƒÀB¤¡GĂ1AåfAq`…€Åb€ÅrtΘƠ¹l^ ²ơŒäÍ\{I„Ơæ>ûeÆ"$ Ä›–µ£1íâ–ßiȓʀ03?FđJë„£±?Sđ$đư7-‚(¼ư§‘v Ưø¤ç$È1SŸĐiĐ7 Ï÷<ä½£GöàW®Å¡QK'×›^ ̉H 1x|?Àf\0ªxöĐ(­Ú?ë—u5̃¹öÀCæ ¬$Q¬ô°ă‹ËÄüûíŒÈd_!PüĐsƒD±Àhôàø–ËDqdÊv¿+Ř>©|ö¾8°y¶Ë ³ăøưU+ÿÇ2;fĐÙ¿ù'%±øŒs¡ Đ=ZDvûÓPJ›`“ưsÙXCTuĐưº1°èM„yχ'Ûº _¾k5µ×àù“„" |EqẸ́xüQ@©1°P@`6lëÍ!ïK¾vé”ö;Víú‰ÉøăỜ‚`E€Åb€Å2!}óUøÅC—¾bN”ḅBÇ:s•2ÿ₫z=¯¹̀"‚l6¯ ,zvm†°.ưKeóJÿác–eÿ&h§?'Ê₫\ >uÅL$»o}ÉdÂtú+H³=‡n‚F& K?P(ú6 ˜°eĂ³xzÛœ1¹çNo´à’@¬đ¨"À|Uè¶Ù +F¶(ñ«u½äI…?_ÜƠùÏ_ÿñ‘H×£ü( ̉6؋Š‹å踮û~®?‡±|dk0Ÿ¸ñOît9ưWyNFù¢!Q–ư A€+/X†t:ÇöŒAÜ ³jsÄPZnT±Q0Vé½₫Ăă€Àˆ€‚ç#_ôà8¾xçă¸oư>\6¯Îjá„R5 4 &¡s b ª4"˜ó%₫¸}€ÙM6¿ëæ×àæ÷}́,.ˆj0̃-°ÚÎ;`±X`±h₫₫s_°|r]=¼£®eÍ .3·9₫́¿bÛŸ©"´×%qÓ™Ø?`ç̃}đ½bÉî7,ư+ưµe£Ơ²ăX~öïÀ!‚ª„«—LFÊ!üÇkF₫´«¡~½TÖÂèj€}äpÓ 9đ|yˆâ(¾s׸kë.Ư„ f4¢èÇ/àø&ôƒÍ̉%É¥¥B’‡Gôà‰TưÇ>ø̃-¿đ•³Áœ0 •­G€Åb€ÅRâÿưĂûƠ/×uwÖ¤LúÑ]C(úA´JWÅ–₫0á„¶₫Å·ï•uÚR‹Ú¤ƒU›ŸĂÁ̉Ù·¿qv¿Ơ²Qư;B›½ñÜÙXØƠˆ­@qà ü@ơJEçÿñ͆Ơcq\ ôb“yOBFñ‹{Å›‡đ9M¸`f|©~Bóßă ưÂ÷?áJæCĂEzfßOílóƒÛùͮɭ(…MÇ:°X,VX₫ÔQ —1³Ó;æ±²s™ù]₫/›ùæâăÙ/PŸvđ†eØ̉WÀC[»¡^6ä•:ÿËÜm*2₫qÙ̀øG˜¥?‰¦6̀6đôÀóMÙ_– Kf?GÆr[âcD‹ÈHŒ ơàw÷?‚;6 áÊù“pzW-<©}yôÈxP₫\åăq X÷M„}û‡´₫à/6©óǬ½@‚Hdb•€¸°"Àb±Àb)ñú·½à†¥ma_ÿ(dhư«âgá'p|\¶bÙ/af[xø»ŸÅ`Ï!ʘí˜À̀\̃ùÒÇ̀₫C§>×qàÉŒk·ặÓZđ•'»±¿w( ØA¬ÊqđÑ­B€2£ ưz‹±ñÀBÑÇè@|üI¬ï.à¬i hȸfƒb(JÂLUí‚uÅ%_T&È|#”blïÍÑS{†ùÏæ·Ơưasï̀ˆD ÆX£ ‹Å ‹%ä~ïÜĐóP x̃o7÷q|M­lK"าÿض?‡JKÀu€¿X̃̃¾tï}.¶êWA…óøªbÙO\P„3ÿ±M€úÜ¿ä₫Ô6¶`æÜøùú~ÜsÿđóÙXă_<ûçñ¢å8E€4“A QtO@̃Ó#‚GÂ÷ÿ|I¸fa+2®cú b;Âë8<´@™̀øâúĂc4Rđ…­ô‡Í½«˜«z$L€&¸,+́[`ù“â’/%¯?½5‘rÉ7À ›ÿtàñeÿZ p4ú™áB`Ù´I)øÂƒ;‘Ï/uư‡ÙYÙ¿²û?̣úG•́_—₫‰Μтלֈ₫‘”R¥³ÿÈó_™́¿4úw€°ÿ g>® ܱ¾Cù€^³p’úçoÿü¯¡ûRU€Ê€xÀËŸ‰B ¢"GÔgêùù”>OÑvF«(fôg=Z±g˜ëëë:>öŸ₫̉ùW½q!3'Q>Àx£ Ø €Å ‹åè‡ÿí€Ëæ4t6¤Đ;'Ï/9ăEƯÿ8öx\yöÏ1¿œs¾Ä KÛ‘N8x́é•đ³£±e?²Üô'Œ†G³ưÊl]¡gÿG@J‰¯Ưt6Æ<…-GF! £¦L®LJ'xç'̀Q€̉"À“áâ 9_ÂÀO÷G<¸{ o\ÚΆ$<©̀x`(ŒĐâêGe3 2Ç7=c­Ư?§u65}á«ßúñ̀EË»P2 ªæP­1Đb±Àby9ñ¥¿·?sè²íÅïïèËcß` $A4_}­ô­¿5f›Ñ¿0́PƠ™ÿRLQ¦¬3ÿRöVhR„·ß¶rß:H8¥¥?²|Ưo\P¼ÄE€öñgA¸BØV÷ âwƯ‡ Ư¼ú´dN$¸J‰||ˆ‹€° €HÈí*ĐS{‡ù¬éMÉưî¡?$’©zèñÀÊ÷„ÇV,VX,/s^¿¤­fqG-ú²̣¾ŒæÚăAŒùè3ÿ¨ˆ¥,VḈºL7Ơ…I5 ́Ưü,§ÜŒGUdå4₫…»JÙ?̀Ö?íP”À­7¬'‘/2ˆÿJÙIØ<Ÿ̉µ*@Ô€Ø̣ ¥‡¾„çi·À¢ï£x +6nḈ– ®œ? )ăÀaeôÚŒG@èh„@Ü#€C¦h{¢dh³ ö ¨?ëă³›ø̃ÍƯP9"÷¨<°BẠ̀'ƒm´¼́ùùêóó’˜Ú”V[Œ̉Á¡‚)[‡çÈ¥n±£ư—¶đÅL„ÎJ̀jÂy3đơÇ÷cÓ®½đ<O±?mÊZñDË~ªU*¶ư9BÀq\Çë: `á™çăêŸ₫ÛOĂÛù4̉}AXiˆgÿ1/ £‰0Á {0໸zÙTd’ö ̀â ©*ÓôÇTµ1°Úx U¾Ïơç0¥!EKºjÑ<ÿ<ñÇ»îÜÄ̉» Uk „­XlÀby™ÑQ›ÈNªI`÷@^lëÍêr=%ï£ÿ:èG™+͵ ,èl@‘#{¶ĂËẹ̈ uù¿́ÜÿxˆèN N ₫ơ5s°­¯oç (‘D`|¤qËăÿ¦̉U¤w)˜*³V¾Œ­ö|^÷¯̃ÛVẠ̈Éu8wZ=ÂÆ¾²í1pl£ œCGGḿünszÆ<₫»›^ó¶Oûo „p2U€£-²"Àb+ËK™½ínwÁÜ™·,™\ñÚĂ80˜7Kf”Ù?¯̀Œ:•eúfÿ¡ë_hú#tƠx~gΟٌ/?° w€ç{(AùÆ¿x•!@cAŸcă…QöïhÏÿ„ă@>®¼ø\¶h2̃₫‡ GáK=Z¨gÿË=ÿÿ»²ÿ²¬;êe(UĐĂ?’ù W°ưđ üd#®=½Bö ÍÛPv‡HDc€UD€Ö4îơ„‚âĐˆG“j8}̃ŒE§fתÇØå8N‚µ2RTªY,VX,/5̃ÿñO¥ëëëî®M:jå¾̣LŒL€¢ơ¿Ơ@<û¯tûs̀çk’̃|Î4¬ÛÓƒÿzx ¤—GÁ—‘í¯” ɱæ?T)ÿWkaL~‡àGÏ₫ BiÆ?\{Vöñä#¢hlƒ ĐJ‹đuo›¨~â" âqă$Ü €íûQ?©6¯{ èóà 1^„L,D…G‡c…Dđ…1Ÿg´Ô¸_pmÙÿÔƒ÷>'D$G÷°"Àb€Ạ̊RdúÜ…ôíOSͳ—ÿtp(Ñ¢o\́̀¢eâç4^ Ľ₫ÅÀŒ¶zœ>¹?|l;úºÀ—¬á‚ Úg¯̀9ĂD–¿@µ³‚+ô¹ÂqÈoºät\±t₫ơ'÷¢p G Ă`lŒ1¬+‚Ås÷¨Áï$"EFAq¡Sú^ơËpU»÷ ÙÔWÍiF÷˜¬Gˆ˜Q~ea?@5P₫oTzÅL¥ñIO2 d}ßQŸ\´dÙÅ}2½sĂSî!"×Ü)^ 8–iÅb€Ạ̊R`x gàëoZÜUÿ†”+Â.q}V;³®ü­_YBÄJÿ¥™˜2©ï¼`*ô à'<†BÁÊü₫¥Rú±C1qÙXúwíüç ‚ÛĐ7^ºïÍá©UkàyEÆY°´̣·bbá³ÿ•ÆøñODD_mŒ̀₫¢o1z^ûF$n!€º¦̀·?YÛƒ§w€Y[ưJ·ưÅ OÀơ¯²äOU„ɉ€¸[`Ô¡¯eụ̀Eù¢‡»wàă?}SS¸~I+jSnä• {.B`1Åf6¡§b#ÊL„«„—¦#ºG=:4RÄ9Sëđ–w¾çÆæö®fhŸ€4ôT@8UNX!`±Àb9Ơiiët5¤ èÉúØ?TÄŒ¦4Új“H¸e×á™>"@œø8:ÿ±mb¼ó¼É8<êáßµ !¢E?̉X₫FÙÿQ"Ǹówaª‚¢×FppÖŒ\=¿û·o€?̉o2Üxö_:Â>ÖsV ît”×u2‡àUE€Ô=S (=ä=»víÂçØ™Íi¼rv#ˆÄS4q!ô+¡XŸD奛Ă÷@O]Hw d<ºs»̣üök_ù†/₫àgÛ̉9-.R" nd«–—_‚dßËË‘|.‹O₫bEó gϼ%ëKôùcrC 5ÍĐks¥É™’¥ 4 èe|û |©pî¬V,î¬Ă‡~¾ùƒÛQT(ưËRV~Ôma“^́xA§?×q0Íuµ¼îW`O÷¾óÇupƒ<|©ÊÎ₫K~'6ú'& •='Ơ¢R3—?8 X¢»§Gd®[Ú¢R80TÔˆhăb¸r¦*@±­€ăÅ€̃̀ư¥¾1Ÿk\~Å’9‹kçUw÷Ïô°pœdl2àX¦AVXlÀb9•yŲ¹_€¾¬„Cđ%£/ëcFs3Zj‘t‰X¦-ˆ*6Ơiïù̉èŸ `Bോ[±úP¹CÏÁ‡S÷—ª4Zx´ma$);b0åS™Gă::'ặYµxrÓN`´³ñ1ˆY ÇâÓñfÿÇJi«¹́x)ÀT`ö (†”zg@Ñ—(ø>r^??GŸZÛWîĂ¢z̀hN#Pá?GSi3$‡¨â\"¸Dp¢₫ø¿'̀±B̃—x|×0*̣ —Ă?~é;×+)¥ăº¡QPØà ü8€¬°Ø €Ạ̊ào₫₫¿œÑœÆ@6 _é3äb Đ”q1µ)í}yRQÀr÷y₫Çqđê…í8­­ŸùƠSÈçÆtæo²ÿ àRö#%ûg“©Fc&ø'=ûß>}.₫îê³1<2‚ÿû_#I|ă´H V¥eF/Tö4¡p¢•€È(zmUÂñ@‡úÑØ2 —̀mÅP>À`.@"»á¯È”WgDü¡mDirƒŒ“¢#È yÔUŸÄùgŸñ*jŸ7üÄƯw¬qƯDZ)¥0±]°Åb+Ë©N]̉) @±ùůÏîQ›t0·­® $]‚똆;&é ƒiÀ .˜Ơ„Ëæµà×[‡16Đ ßlÀ ³ÿĐđ§̀ïÿx‚+•ÿ\¡E±„ÛØÅíi|ơ‘ƯH‡ô \)¡”‚¿Ÿ}Ÿ@0§ DÀÉVôâ ] ̣̀ °' (Œ àÇ7 1íàÚE­h®I@2O]±IB™à2_ç ‚ëÆÖ' ”z8Œ@( k²#ïÿ«7~ô–¯Üö– đ}á8ñÆÀø áj•‹Å ‹åTaÁ²³œ̃Y ÅŒb b–0 àK… g4¢&†ëº‚à DÓađÇ3馵Ô^µE?Đ~ÿ́~YÅü₫«mû‹eÿ0Ag¯":ÿw…Ö¹ËñïWÏÆÈh«W> á$ôƒ)£GYxÜp‚ÿNxÆÿ$ÿ=â½z\Ï801F-ôt€¯¹ĂøÇŸ=º”ƒ¿X̃–Ú$Ǫ$F ¹f5̣„WE… ÜÚ¯ä}E+÷s:á¸ïºù†ÿư÷ŸÿÖ JJ"¢4Ê+€ °¼ä±G–—}Ư‡øÖ§ö¾fù´Æ› pz³>e¿®³B[]Å@áđP€îüRqǰù„@1ΛшẀ„ÛíÅÚ-;‘/Qđ}ƯHí,Èå–rñ„ÁZWẬ¿ƒ¤«Ëÿ.™öixÓxëíëôî…¯8Öø§Ê6₫EÍvÇ™ưŸLC_üöd¸êçKN‹V@??†Ơ£µxÍÂV̀”ÁÁa®Cȸ̉ iW •èjH¢1ă¢é(WcÆECÚEg} 3[̉èhH¡£!‰º$Úë’hH»äđ¬IqÚâË<·fóêÇ8ˆr{„cÙ[,/9\ûX^̀h«ÿ€äÁ‚î₫º¬/pa´(±¨ˆóg4 {¬ˆ=½cH  œå";0jS ̀j«Ç¶à¯D1ŸƠËw¤É₫9>§S͉Î₫«Íư 'œư Vh˜{~xÓbd >¬ ×…”>fPrœ}ññÿçËó™ GơÛÀ`cñ«GU4&˜÷³Û*|6áâ“—ÏÄÍgvT=̀'üú'ø ’± -ĂüЇ¿66ØÿW?ưÖ—6eœ+F½Ào¯Åb€Ạ̊< ,ˆ ^«å0AĂ„œ)I\qÚ$|¿?‹¤KP,ÀĐ›ĂH`vk˺êđôºg†/Kgÿaw{<§êÑj\é?¹1……]Ø|xI' Pá{ ±&³f´àéƯxh[˜9Ê₫“¹ËD'pă‹ụ̈˜É>÷wÁ ‰ö9ø×ëb{Å« H $”e3ÿ'‘¹Ïïđº2ˆŸp!¶¤(|‹ÂY}íæÇđ°ä¬óñ̃‹¦`å¾a<¶í0>xÙt5¦đĐsƒđ6}TöØ\‚+­ƒĂºKÉjX?·cfơQ@K;2üÿüÙ7´v¼ç;ÿrË#D”©̣~ûĐÿu©·ÙËKÛhyYÑsh?×¼ơ;µÓ›S " P*vάG‡]ư® t"wδ4Ơ¤à:¤ư¯[Ú…ùí5XóÜAx£Ñ™”+Îâé`FÿAg₫nZKÔ5âÂ9-ȸ¿ư1ăFg₫Q€Ír¡“lü{¾ÑéyÿđOh̃ƒ’Ó_XQ¾ºÎYøÀÅSđàÎ!|÷UØ·}3¾÷ØsèlHă²yÍHåN z B…CœºÏ^’ơÈø(†oó¾Âªư#ØÙ—§%₫»¼ÿ›é© §0³CB¤¡ưªY[·@ËKÛhyÙñÛŸ~ÿsÓ3—g´XÚ0ß,₫– |…®†<©pdÔ‹âµbFCM×.nĂ®îa|ç¾µ@à£Hü’ăŸ4ÿh«~ñë~…pMÓ_Âu 7vâ£W-ÅÓ x걇̀VA /Ñ@$6N`æxáZ×+Đ}ăö¾Ûvè:Hº\(xơ“ñáëÎÇ¡1‰oü我#`ÅèîíÇ2¸t^ÚêØ5P€/µ[PXQÑ¿̀Db> ¥KUÜr¬Z £;ë!éZĐ^£®üó?ŸơëÇ×nÊÙ;LBˆØÖ¥Ê¾€ăñW²XlÀbùo€ é:g1#9R”LÑïæxLưươ² ±¢Äh1À¬–´Ô$"w@¥€7Ÿ5’Ÿ¯9*–:₫£NüpÇgúUÓ`ưu"¶ŒÈuôr"ÔµàuçÎĂôÆ$î¼ïø#Ïơ¨RÔa>®(óBî·åçq?ö,߃đ=Gúđê§à=×]‚Kç´à?Y¿ÿr³¤ùt IDATÂh̃C!7†'W<ƒÛWîĂ”Æf4¥0æé&̀À¼WJŲ{„kŸăÙé ÚW4›=tÁWX}`›º³âœEs.½çç·~¢m饳Y)—ˆR•€¸O€­X¬°X^,3nà Lá8_<Q|Éùu}`¸ˆº´ƒY“jáºíM5h«Kàßî߉m[¶€I>³æ7lÂ&.ưWSï¿ăè v—/hÇÛÏŸ†®À¡^È@E}a`S±ç<Ù̀ưùÿç[úPê{0½¡ë¡/%̃qÉܸ¼_züöoß‚b -xÈæ‹Í{Åư<†[WÀ«æ6cQ{ ÆX(6Ẹ́¦#Yœ³hö+~vë÷>6cù…SMđ÷Ts ´"ÀrJc{,/ ù¾ûØ®ót6¼#é–¾¬?NÄ-•ÅSøÑvQá8XĐQ‹Ï̃· ¹n…‚À+3â‰uâ‡Íx±?Çu´ñÏ8ÙE™oÂçÎîÀû._Œ[WwẵU›!‹9x̃øº †{îOvôïùf₫•y|wæHô„ÂG„ÂÇHº.’®@ª± o¿₫Ơ¸j~î¸û́;Ü­Woc̀zǴÙ…ÁT̃¸¬#‰#£qmÔ=̣`½‰Jâ v…¢•ƒƒá¿­TL¹I‡ø¬9]³œq^ûªƠk×÷9Pˆ½E|‚o¡Åb€Ạ̊Ađ¡OüÓ§:êS¯Èû\ ˜ÈØùƃ#^©/ư^ö#á̀i­Á‚öZ|åѽèß³dx¾Œy₫ë…?¨È†£¿°ă°âsÚôG—¾QđsP[Sƒ‹.<K:2xđÉg°uçnHaăŸxđ?ÙT9ó"eÿ_ªî:pLèïßM¦pùgâƯÏÄ̃ƒ‡×ló‘øñÙ,kÿưJHØ»c™6\½¨cŽFô!¶8ú÷ŸÄÄß›’W1JC å.…R1zÇ|Ê$Ÿ{Ú”y³–œÓ¶úÙơëûï/T|ËÇüoÔb9U°G–——¢đDY¼§x̉_₫[84”‰¡ẁG̃—ú±Æú€DJç‰f ƯÇFØbCg™@ŲúÈñωÿ8fAG[ nZ̉‚{6uă® ‡ ˆ ƒ̉„ªÈ₫AÇG^ˆö'Sö/ ₫%½R*ư; ׉Ö07µuẩeóđŸ«à7÷> du¯E àùf×B Q ổ ¼ Wđ‘+xÈ{>xđaÜ·µ×.nżÖȰJbiBï‡HTyoؼXæ̉̉¢°çB*}zVî¡}9¾æÂeW}å›ßùè̀åuHÄị́ ‹Ë‹Á¼ÖÔ$|¥ûiüñ}!P¤₫ä5.Å%KçéF8¬«n8¶æ8±¥Az_™µ·dÖü¢¢ bçßÑ"‡pư+ÏE^ë¶ïF{à+F dt]vö‚ø…r¥9Ù‘?„Ù?(Z̉­Óđë₫ s~ñà*¸¹~¬7†.…½8(Wđt@¾€'׬C÷pW/nÅ”†$üđ}ăr¨£Ta@´<+öĐs}9¾̣Üůùñ~đ‰®å¯˜Î̀"…ê˃*û,+,–‹/¿ 0¹1UpAán:ZŒ{ó@ÿ¢ŸTă¢>íbƠ¾aôŒñÚ3¦ău—,…ªm±B̉̀«']=»‰€˜‘~@.}Ấ£³¡³ßLû \6«{÷ă÷«¶@8é₫×Ç ávÁ“É₫ŸoÄy^#(úÿ́½w˜dWuîưÛûœSƠqzzz¦»''M’Fa”…²ÂL0ÂăûÙæb_csq¸8}F66ׯöÅ\á€H¶I2($F£‰<=s¨ªö¾́}BUwÏLÏŒ‚³ôÔÓÓ¡ª»ªöz×Zïz_’çîZđä:…|øí×óú3ù»‡^b´÷JÈŒÊbd́•U†­)ü@%îSeŸr¥Â}øËÿzŒ¡ño8s!íA¤Á¤jƠÁ™ŸǛ @Wƒ̉NÀ®¾I}å¹ë¯ÿúçïü½öó®[­”’dWsÇoÇ4 ̣øIˆCûöđ­m=·̀o(ü¡#EĂèT˜™¿WŸ¸Ir©L¼'̃̃T ¡àđç̣Â>Æt‘›6.`ñ¢́Ÿ˜ÀA%¤¾ä±“Ê26g™ï]ù3¢?æ£Vù̃×ăIÉ_Ư¿‹₫»ˆ´ ˆBüĐ(ÿ)eX́Éß>G̣ßÉf›*½~æ̃ú'|Œ…¯Iúkfÿ.!,;—?¸y#¿óƯ<₫裈°LÆ{ư†k,ƠÚñéŒæ¯¶jÏcăălíåê³Vpö’fö •™đ#)Ah„N/„h1]"9€NaÆ“¡Bp̃ªöƠ7¼ö•>¿oÇÀ£TÓ&`f’`̣È;yäqBx®³&Tzá¤i5Se7ĂçÙV¯# ̃•<}d‚‘‰•r™GßÅ'¾{úBx÷eÜrƯå8u†¹^p(z®Qñ³U­t̀{,ơkfÿT­¾¹R"…¢iơÙ¬]P$̣K<ưäÙß02†8:ic¿̣Ơÿ©¨ư‘UûCâ£M₫ăâ¡–náÎ÷^h}è>¤?e…xb…tơQegú±YRø¡Â·ă€’âû‡äwÿí!¡yÇ–vÚ\üP™^h3ª!êÙ{ fèÙàˆ­ƯúÅ 6¬^~ơ‡>ôÛo”tœz̀( H*<“PPyä€<̣8à7ç#-l*ܬµS²•˜ùÄ5ưù$¹„Jăº‚æ{Ë́ïdʘ*ôñÜ¡Aêçñ–sÚéƠ-éî±>)#?#:;̀™D(‘vç= ~̣¹÷߈çH~ás/ôï'ŒÀCÓWzĂ ¯ĐêßɈZµ?CzL+Ïuñ\AP߯¿üÊu¬lkäçÿ}å£{fƯ/–-ÿ‹¸­+ĐhB[a.™Wä¹îĨÛÇT¹LÉ)ûVøGCä—ybÿÏ÷”ùÙ³ÛùùKWóâTƒ}=”Iy”­ÜC¤A¦‚Gü¤]›øíÓ@€®jè¤m)‘₫8ơ¸é¬6µ7pp¤ÂDEY± ¬1”ƠĐ™mÚN@đHu´½“RĐ;á‹%Í̃²eËëZ:–́~øÛw¦fât¼.Vyä <æV°rïư÷Ứỹ?]©†K¡ˆÿ¤¨a¥gîÏ•C,o-rhh’G˜(U(Ùî¹o•ø4G đƯ“l\̉ÊÏÛÎá°™¡áa‚(ÂA'°”ÖñÏ2ß=G‚8ÿüó¹åÜe¼÷K{}ñ»„Hü0" C[ư“‘₫å¤Zÿ§’üç’‘ªº"ơ8píªŸkIRÀ’•køóÛ¯£µ̃åÿ|íaFGF "#°”xØÄK-몦;3ƒ€l™]ơ$áp7Oº\½±ƒMíơt 2 @Û6CV,h& fq×!RĐ=î‹-ºà‹nZ´bí₫¾ùƠỬq\­µ>Ñk9¯̃z>{¡,R‚:ÏMnEÏEkÅMœÁùü˳ƒ Úièâ•?•ßæˆWÍ/‰ŸḶ‡ AHKü“Uû₫̉-°î́ xÓågñ•Ƕ±gëÓ¨ 0Œÿ0¶:¶ G¥àLcë!Úị̂©˜¡™5ÂJRñC&Ë>å²Ï̃Ÿă¯ïyÉÏœµ…M J ¢8€D´ c%üØQ1Qöơíoºù#Ÿ₫ꃿ₫d¡XŒ·²‚Y€\' ä‘Ç _À̉4±Ú Î“Fü%>¥Å̀Ù.9¼1­f!`Ùü:ü̉$‘NZ̉‘²ö°ök(»§T&Ø}¨›¿¿o{+|ø¦üƯ»‘¶Î¥x ¾èRWp©s óÚ¸lÓJîÙ=BÏîçÑZ‡Á(2"7‰è>9å½ùñ@€8̀ hØ‹w­GÄJ®ë̉Ú±”¿yç%Œ”Bx~?Rù„J'„ÇḌ8̃÷×:!ưûùªŸ‹7B ̃ÊA@Å™ª”KevoÛÊßÚ’ÛÎ^D[C@Ͳ"hA> Ô àÉCc¢g¼ÂÏƯxå₫ïƯßûˆ_©Ly…Bƒ±l°›ƒ€<~T‘̣xU‡Öÿó7V._₫y ̃•CS!¡̉Ó€j“›Æˆ¹D æ×¹Ôyî́åHßeÛ₫¯$;ù±ưoZV%!(•KüpO]c!Wm\ÂÍç®à‰Ap´Ÿ‚硵æºÍ+¸ơ¢µÜ³kŒÛ_ *øvîÆƠ¿JƠëæÚ₫Ï&¨ơ£=™¹öơh¤©ÄqLvt] C½'ù‡ßÉp)äCŸ{Œ¾»QJ›Ñ;2Œ~´}ïÄÜtÍÏO7Z1>ÔÏsC¯;³“Íü°k¥̀èbXP ™eEPÔªMg¸ v08èÎyEqî+.\{ñµ̃W?÷•SÈPN„ ˜G9È#™âwÿ×_¬lnlø̣ü:‡áR˜´u³ä9éJ™ư·²ÀzϬï=¼«Ññ J!ÿa†•N†”gÚÚ$Â0Ræ‰.Ÿ«Ö/âÖÍí<̉ïàôRßÜÊe[6³{ ÂƯ~hj,qº‹Í́?›|N®œMøH̀’ÈơI&´N4 ë_¦Zƒ+ íœkxó¹|́ëϱïù'QJ§ë*~}URù“4oÄ >×cׂ)4¥¡(đÆÍlỶ̀»Æ‰T́Ơ`@@BỒI' 9͘Ñ3îëÎæ¢Ø¼nƠ%Ë6_4ù­ÿ¸k«={¥˜G/5 ̣x•‡p¤RÔ²ÀEƠJ[|6Ǿ:qû4k6061I?Ja’R”iIW§±œù^̀ ” ÊŒâ£ßÜÉ”ñ‰[7qÇûY6¯YÆë[™(‡ÈÔ€₫xí“Î Y2`­¥ïLåæ\’ü·™}zƒSbÂc̀üw´¢ư¼kùÜ»6Ó54ÎÓϽZ'ÿqë?Ûö³ï?×¾G¼~¨…δä@dAV%)û“倒1°ưûüÚ—_¤è ~ù’%¸ Tf5Ô$|]½ù7Û8@yæx ’ß ‘6ƯI?!Œ”~ëÏÜü‘?ÿÇû̀ 3 ȺỌ̈Q@y \Ó€ÉụÈ@yœh´,Y+îƯïƯØÖ\ÿ̃±Jh̀_É×L=ÿA$íÿ@iZ] Rpß>&ÆÇÍú_¶ưW¦`Øéæ¼ÖÙb^¤ûđăĐPp9:0̀Á’Ç%+æá+ÍK½cŒ¢TDh+ĸj$«üƒ;Ï8  –p²¿ñ®¿̀Îưmë¿àJt±‘Ë®¼–×mXÈmÿ0̣đs„Â1ÄI;̣ˆ×ưbA¦tî~jyn® Àîæ©A‡k7v²qQû†J”QwL“ÿLëÓ^_1Ó«m«(ú&|±¹£^­Û|îÍó–±ïÑoOÓ ÈA@9È#‰?û‡-v,_ơoÍÅ}eơ[ ¨=5Í @QdÖ·Î́hÄ"îy₫ ¾ïS»úYAl5n2@fÍPˆj¹̃ŒăH®ËÂÖù\´¢…OpÖªÅtM(º{û@GÉX!1̀x̃Û¤{:AÀ\3΀!À±Ù¹Ásp¸æÊ+ù³ŸÙÄwLđđ½ßDI7Y§Œ7+R^™–ûéÉoƠ @̀ø\âÂè¼4ạ́ÚÍKX5¿È¡‘ åPYiç ;HÖ må_ÓÁ—R0DôMâ¬z½á̀Í7¶­¿ṕ¡¯}₫I¯P(ª(ÊA@9È#=ëß₫¾µ·ÿăâyE=<ˆx­/̃!Ÿ̃₫·́ #éḥxø¥Av ™Óètw¡W´̣öóă‡p`¸„+2{aCd* Đ¢F€J¤PT"…è÷ơÖ:±ùŒ•—¶®¿pâÁ¯~~«Mü'̉ È#äñÓïÿĐï?µ¬¥¨û'|¡TFHd”Ütz‹4„‘¦µ̃£µÁåÑưĂ 1å§â?aƉ/Û₫Ÿùµ₫u¤´³q‰+ -â¢åóøÊÖn*†€h•‡xfnƯ¼ˆ‹ÎèäáĂeôä BÈ*ƒ6¸?}³ưÙR3ûcˆëPtÓÙÿ¼–̃úÆ›82Ræo¿t?Ñh•ú5¬ÿ0RF3ßJ£Óừ©₫uäÎ\»Y€™R©®êö„”=´nÑÆÛÎïÄ5‡F*‰Ë£™®ˆ}±ô4Âia«€AiÑ;ásF[½^·níƠó–­;ôÈ=_Ư?s)ƯĂĐĐ0“¾ÿñ­<­R$êt¢–ü7z6­q£†gæâ¦M.½"¿uĂ&&J¾üÈ6WªØÆ(›̃úyúh‰×oXÀyÖ€R‡(@8̉₫éIåt® În¤4ƯWÊ„øg*Ghnºågùà‹ù̉³=üă½Ïâù“Ö1±zå/Ö9€¹ ₫ˆÿj¿7—ljçøèéé:1‘²_–dx|‚ ×/ă¼e-Œ–BºÇ}̣ ñj8¡A¦[ §ß5[~¤p¥gw6¨eë7¿a₫uû¹ç«»¬NÀ‰trG̣øÉ̉Ô¤₫ß÷¾¸üⵋ~s̉.…86Y‘á°ÿưHÓRç° ÁăñƯ= ŒŒ›öâG&9+­yºê¬‘̀ÇË₫·íÿÖeÜ´i!́fë^Đ˜Ö¸í4DÖaH ÁđÈ́èeÅÂfn¿r#óZZÙÚWFL&µ₫Ó@€MJ§’ jYÿR +lä¹Fí¯èy¸B¡ç/å̃u1÷îâă_¼ŸÂX¡A”â_ÚU9ÁŸlâÏvN†ù½C\±²™?yÇ•èÎ Ddx®KÁ5Ơ¸#S'¾*nÀỊtṂ—B ,±Ñ‘Qưs¦Ê>yó¥¼aÓ>vÿAF{£VéÏØüƒ£ŸSL₫ÙMä'ŕ}µeđÅV̀‘2k‹~QñJ•€̉ÛƯÍ_åŒñ–s;XÚR´ Î éé€Ù2³Îh@‘LEÖyGß$í«[‹¼ăÆËă/?üû~¥<å 'º"˜ƒ€x/̉ñŒ†BÙu¿́ëyjF?³†Z€p̉ @”ƒ€)ß§âôíæO¿ø]úF'yÛy,n.DYóôœt IR˜ëT¥J¥`ßP™ïíÖËç×ñs×_̣kù…\' äñSm휽¸0ª~qƠ°¤•?˜ƒƯsóë=^́›bp¢D˜55¥4‘®¶¦M«Ö™ñZ‚ ±yŒ€béUH!¹ë™”=ÜÓį4¨Ø™P῭"x~ûN₫üÁCœ½¸‰OưâƠ¬̃p6m7< ®›È »ñ†éξ˜«p²Ú&MÏ&×up…ÆéXÏûoº¢ç°ă±{‰*%ÂØÙª₫E*mûÇÉÿd’₫L¤¿Ú ₫TA0;°Ûe? äûT‚€‘₫₫çg`tª̀;Ïï sñ:€!MÆÊ³[ü¥ À¼H‰PPÜ ĐF0èĐpEÄ à­7\ñ»ók¿¬¢HpâÛyä1kä€<^uQœàóOyûæ%Íoîœr%-p²§5₫Ñ–ưĐ̃́±µ{’—º˜¬øFû?0¶¿ñJVzJ‹i•ÿ±tñxEN@sënظ/?×ËØÈ°Ơ¨vÿÓ™9s\ ÛÆVóưü 'äm[:Y³¬“Ă•:ÆGG AT+€Zđ“Î>E Lî—å3¥?Ïîû{RPX´‚¼ăZ.]Ñ̀¾º‡ư{BKL\₫̉ç'×c%̣ăUöǺ_íÏÔêœh ñ ˜‘(Œdqæ=₫özÜpf,mæàp…ÑJˆéÏØƠü-ÇĐ ˆ5ôL. ö¯Db̉9{q“^¼|ƠƠ-Ë×ú^®G̣ø) đßùưo¯h­kœ £j ôD4ÚÿÆú·½¹ÀÂÆlÛO×Đ8%?¤„v5/n[góÿtPu€'@Ó†÷́~<À›–s̃²îƯÑÇøØ¨iơ«xÔ°¦Ë`É×$‚±‘aî~₫k/äW¯ZCIÙ×; a`‚I2Ó«ÍÛˆµ°-iÅŒ<Ï¡àX£áđöË7ñ¦ ×đ{ßÜĂÖÇî' ƒD́'5úÑÓXÿsM₫ÙÄ|" ¼ö~'Cœm; ÌĽPHFr·Ăµ;¸`YGF|FËQRơ ‘%ö1+1PgÛ3i?Ú/”B*‘çt6ê¥k6̃ØÔ¹bç£÷~ăđLw¬ÿọÈ#y¼êÀû₫LJuùüº#¥0̉U#ƹi±Æö¦û‡*<½¯±É%?¤˜äZó¨nïëPû})Lë=»ÿ —ß¾qu—½ïỉưâ.ƒJUđ©©Y«*Áx]¢(䙃Dn=·_º°e»÷7ÁÚƠÀ„(ªÁ̀L6ùÇ$ÆÄèÇ5~F„È£mùZn»î^8ØÏƯ÷>€_.™äù䨆G1×¹ÿ©$ñ—dÂ>²ă G»y¤.9£ƒ —5Ñ=Va¤UéPTI8ϯ´ œ ˆ´gw6ªåëŒNÀ÷r€:bơ Œ¢¡qùÓ–Í>w•¾Ó¼OqC ¹Ÿ0ïM²½a• +Ù˜¬ø”ÍÈ̃çø“¯₫£·n^ÄÖ¢íđè*0Zf¸¾²€„¸jÁk¤Hx#/tỌ̀‘q¹aaQ¿ûo»ăcw~íƯ*ü|; ¼ÇO|Œ öëÛÿé»í·_¶æư“7T l^S<‘&ÖPASÁ¡½©À®®Av0»ÿA„)ăTW»̣'Ä´ê¿v₫_¥ÿï+‘+¨kjáæ³:ǿS=  Ú„¯y©1ƒĐYÛØÙ2Æ# ØƠ=JIÖñöó± ½“'Œ KĂ8;Í fFx̃?ĂÜ?–ø-¸!J¸ø¢ ù¹‹Wđ»ÿñ<ÏlÛˆŒñRhG'Fëß((Æ¿üdƠ₫NÅđX+ƒ'Û ˆwü³£™,HBRbû`À¦•\¼¬™£cFÊQbt":³w2?afß„”BœÙ̃ —¯\uởó¯u¾óÅ;“̉)ä€"cZ”®~¨y±g‚ce[Sóƒ_üôÇ6\÷æ3µRb¦q€C¾˜G̃ÈăUà·>üÑÛ; k§Be*Ùô|ͶÿM_zñ¼"{†xr×*adÚÿvw=>`³Ơ½æøÀXÿßµ®´.jçúÍËyêđ[÷u™ù(ƯíVZ“ƠÅÓµ%`<­Èjêj°"µbxd˜‡veáÂ…Ürî2*¢À®C=¸Bg Êt3¡89Ê,ë?¶øu\ÊAÈ×ÿç›h©syÛgŸctß DYÅ?eTêôgܧ:¿?Ư àT:Ơ{1 ÄewàđDŸæê \±ª…gº&đ#…2‘ "­₫gv•̀‚€Yv ‡K¡"%6/oë¼îªË×?̣âm½ûvŒÖTưÇêä‘€<̣xơ€÷ÿöïƯ¾°©°¶̉Oæ×é\Ơ©FưÏ$ö åPñåg299AÉö«ï1ƒ¸Ç™ÿ[öläHI}c#×ńà±ư£ííO» ¶ằÉăG3?K!D̉ߨÙlnî_öC;0€(6ñ®KW1̉°”CG€ SÏú̀#¥sÿ̀ cœü]G³®à]/çÖ~†Éí ilŒ•Œ2­ÿ¸½}+/G̣?Ⱦ'ÜåV'@OÓ@€D#=<Ô#¹~S—¯já¹£“·~Dâ 0«F€En¢f#AT눡RH¤´>gÅÂ%]|Éêç_:¼­kï‰9€€¼#€<̣øñúÆ&>ŸºăOo—B¬UJS•­¨âwÛ6%fOĂây¥yjo?ă““”}E% ñĂT¸f¦ê_̀Đ ›@¥¨²À™ËrƠú>8Lwÿ`â&­̣ƒ\̀nê.DjiËØÍ’•: ØÑ=J}C?¿e½n]]]è0¨êXd)̉Züz25úq¤ ó̀Kø×_¼ˆq_óoŸÿ"Z¸‰Éiư«T9ñ4™ü¼|ˆñ4®f³ơ1A€Y|°[r͆.[9í}SÁ*¡$•Ï¢P•©3Ä]”Ö M…Đ[V·/?ë¼ V́:ptÛá—vLfđk­äD-ÈA@̣ÈăÇ·ú_̣#ưƒ÷9R¬l*ºŒẀ,ZỐÂÇæ*R¶z^8<ÄÓ»á‡rPɈÿ(]“ukNÄ™÷ÿE²à9hápëù+9£½™¯>¶±’o€vÿ¿–¨Ç¥f&¦Ï5Mî„>/£¹©‰Ÿß̉Î`¡}]=ˆ „”N¦ú'£óo’¿ëI<…ÖN₫æ]¯¡¢~éÎLjFûŒ$n̉_¤SOƒµ¿¹&ÔÓAúûq ̉€€Çz¯=s ç-ndßP…I_™U,Ơ, fv¬¾2…0¯É@H‰¾`MçÊç¿bÛ¾®»öî¢Ê(ßÈ#y¼úÀ?<¼÷â³–̀û B¥©÷&*Ñ4ñ3ÿ×4zuĂŸíajbœ)?¤íúX q¬«Yư«:„3Ơ?`\̣¬U®ăH<)(6ÎẳËḄ½]LU•:ơ›×)oAçY›ÊßTµ¾‡YÙ_!+¼Đ5v üÂ…èæNºúG¡à¹¶ơ/“ä_ˆ¥~‰r¸₫5pË¹ËøÍÏ=ÎÀ®g¡Ư–ˆ…ŒbÎDl‚3‡¼Q›ˆ_¹‹ç•ɵ"¢±~—Î[³˜•-;ú¦Tl]-¨-đăk¢öº£ˆ¬ˆ”ơoĐ8Bè Öt®Ürá%kÜÓơbÏ̃íCRJg†A‘ƒ€ä‘Ç«Üxûï¸`eë›+‘n+G,hđp¤`̉WÖtFXÆ4T"ÅêuxîßzÉr…²R¥k#]Å«±cé₫&‰:וêê¸|ưb:<Æ®C½ahÚå‘¶d¹Iî4b̃ô›Î|3Ơ ¨åÄ>€”Vxîđ0QàÂó¹ế5Ô{Û Q'UÚúwŒÚŸëJD¡ .¼ˆ¾ñlØƯÍưß{”’ÚÖ”Œ2²#“S!ư½íÿ〓!Ơ `:1¸Ëc+ưÁ>º§à̀U‹i)J”Ñ:™­“ŒPPí`:ºIe›±ÂSXŒŒ;S}̃ªöåW]yņ‡¶̃̃¿÷Å~é8ÎΔf:ä‘€<̣øqï_r₫oÖB´•C¤̀«s( ?4çZd«ÿ:O²²µ¯míeWeË₫¯Xơ:•]Ñ›E'K¼ÿ/R x₫ñEǜ¹Ëxâà({¬3²¹Ç&ỵÓ@€H₫Èl*„ÄÓ{zFØƠ5À–µK¸åüƠ”½v¦¨}\/M₫R6.[Ä¿p Ïv—¹ăË1: +§¼¢÷ăfè¦g¿–>¶f``€>ßáÆ³—Sç  •M7)ká\s«’s–q¥_øƒåu£ç ‘r$¥Ù´dAçM×]µéáíG^́Ùó Âavb`rG?~Éàơ·¿Éù«Ú̃¬-A*æ7xŒ•C4P ç.mF ùÚÛ©„’oÉl‰-oö7ˆcŸzµûÿÉ€Úillâ’³ÖiÁƒÛ3U.Á•Z'»̣:Ă%¨é4먧ưâTö7“x2₫~è³·g”úæy¼í¼ºi¥¿·‡‚ç²nËü₫ kxvûxüi¤À¬üEFđ'²úÙÆ©IöΖ_M  ú.¢ö’©î" èïí¦Ë¯ăM[–áH'%f ›àăê_f®µ$ÁËNlâdÿ-H~~¢é RbĂ’ÖÎ뮺|ư“{º^èÚ½md¦+<9È#kđÆ_xÿóV¶½YÁ‚©@#ÑD€'ơ®¤*J¢±àĐÙ\à[Û9ÔÓOÙW”ƒĐ²ÿ͆@uB3|U«€ñ€´D:'£ …ç®éd¼̣Ă½=øa@éi`£¶ú×sU"1 <ÛÉ YK×ó* ØƠ3ÎÂÖ̃zÎ"¨V&zhí\ÁŸßv[»'ùëïlĂ)(mfÿ¡ƯùOÀ U¿'N¤'›€³Ơ²¨© Û'«@b´”Â4ë»T­U©”s_×aEÍ¼ă‚¥‡†ËU ^Jë0'ồç®Mö®Ư>‰ÿíH#GíeÖR=#S-&ÖZ¯_¼`É%—\²úPÿèvúÁĐ@p 0ƒ-a?iáæ/A¯" 7¬hÿ¥@qF¨Z䱨©À¼:—‘Rˆk‡¡',)P¥ík­‰2•ˆEfÖ*3{ơ­ơ«Ô³»w¼ªÚOú«ÙqĂ)–YU1 JÛ½r-̀¨A΃ÎèÎ !đ'Çø—ïîÄ»f#¼r)ßj¿­#SÿúÓÔB».2TUmèêçoÉoÖđçt%ác%æWœ ÉéXÊYRFé{&ăë§èñ̀Öm½p)—¯n4?8<ăÄƯ%kă—‘kNºiÏ•$x¶KĐXp¨sÍ8ªÁ“† +KZ"TZŸ³vùk>û麻{<à/₫ó —G¥ăL₫ÍüÖ®c:®+£0PTO rÁä‘Ç$â<ê×Ö Zk¦Åp) ¹èPïIÖ´Ơ0ØÛ“°ä³etv3Ú¨îéÔ@ç˜']VTÇ̀e…,]ĐĪùßÖOijÈ´₫Oÿ¹Yc˜¬äeA*>ñÆEÑÔ(ÿ‹üêƠk¹tY+ =úG'q'{‘Å"p]‰Ú-)ͪ¤ˆª Eœ.ŸÚ„ü£'û»«A€Q¡$ DHƃAâŒ̣[Ÿ¹—?}÷k¹|ơ|FÊ!û‡*U›4` èM! ̃•´Ô»H!h,H„´]ê=óơøî‘ơ@ĂD%$T±J$ -E‡Öº:}Îo|àÛû¦@©̉ͯ9ï¶£º¥yÇ‹ÛùÿÿÇ{öf̣Ăl9È@yüHp@mU¤´f¬Ñà9¬ZPçHö•‘2n‚§¬iG”°Ơ¬í $ €t0­²ơ´ÀlÜ9\×¥i~åPstÜÈGJ'-à”i•îÿÿÙØf@Xb@€@ E$Úui¢Â½À/^—4Χ¥©+/»”ÇŸü!…`”:Ï5̉ʼnοU¸S …InëpÇɵÎgJ ÙêûG Né1„@k‘‚Y`ÚôM¥a₫ô‹óÛ·]É6-äÁ=CôMtÎ+Pï:4Më¿©àĐTtPZ³ ÁC ‘$w?!´ÂàT@9P‘±Ÿö#s=GJ³*cåAÇĐ4º¬i­ÓRRÆ5×̃sh¤̀ë.Øđ­7ÜpƯ·ÇÑx˹Ëÿ"~nK—;½]‡k-2r €<̣xEBZ 1 SßĂ¥€E¾³£ß´N1•¬ëHœHâH̉ 0Ơ­ªÿƠ™]kjV©Ö̉?<‡=Śî›B@²2' ö3KÂ×'jA@V`^)CTÂY&?@Áu¹xå<”Ö*ñ̃ËVĐRçpßcO öS_đl×Äv:DH™d‚ÚjÚ'ĂèÓjçû£3ư'HA€ëæ(E„ăHü Ä÷ “#üÓ·àƯ×_Èuë:˜ô“$?V‘Bëj;–é÷™ô#b|Z“©„c?ÓƠA/VÇAÓ3^¡ ¥BĐRï°¸¹  ÎÍ uu7OúåR錇öN}÷©ÿ₫/̃óÚ]›Ï¿ØƯö̀“j†®@rG¯È:ñI4V˜WT4~vó"î*Uè;‚”×x@kiC  K̉ÓI7 [ùg¥w²Rºñîơüz—7½ˆ­GǨ„)i.æØl9çç%NdA@2‡©áŒJ,e³kˆF¢¸àJzi˜¡©€+ÖµsŪ×̣éDzăùg’m‡t-4 €Đ ¥l«;ÛEáôN%Ÿ\IŸ²5qÄ#*e¯§(¶”!Y*ÅäÄ?è*³ni„ë8F (8’ƯSDJ3Q‰(¸"¹îœä:”ökéZfü{EV8È^H©€Æ•’ȶ©&®…ëê=‡¥-E ü̉¥«]®Z{Ơµ¼­4đđ®¾/üÜE+ÿ)~8)©TT{¹æ`àU2 ̣x5…ªaïצ„(³®¶¸¥_½j5¿₫† ©k^ˆ ®cäoIÁµ]dÍJ&Ä«¤r¯r´ºÓRfߺ M ,MâOg₫Î8áÎNjỠ²½ˆU›ÀRP+O›Ê¿h¼¦H!xæÈ8̉<t‚÷ áêøÈ6³ö¼K©/º4Öh¨+P_çQ,xV:X&j‚ɺí>ÄÉOŸbȪÎÄÔ9»µfE§ĤDĐ”¢¬HÔü:Á¯]¹’}ƯC|̣›Oó¯Oá®gû¨ó$gw6rÎâ&6u4Pp̀qZ{é˜h82ÖÈD“ÓØ‹*é XÍáx@&DZS #¥—JâÀp™J¨h(º›6¯yÓ–eï-ï~tßđàÿ÷7_jW*R€Ú¼å"‡éË3ùæ@̃È#Óm(¸‚±’1ùeW¯îüÁÖ,jâê5óù•k×ñÉûBÂá₫D¸'  ¬ëÅ ;ƯÎPi ‘®}I!p]‡e+W3á+Ư;Œ#ŒQ̣·dz3Íÿg”|eöŸá8]€i¯‰¾ºa(çTBeÖͤ`´rÏÎAnÙÔÆÿºy=w.lâûîµ;ç)Pª)Œ3 ØiE"ÑBŸÖª}&’à+²]SíXU‰ü$ï¦ií N…|é¹Ê“e¶ï=ˆ#%Û·Ÿ¥+VrVG—¬˜G[ƒ‡‚Ăe†§üHájsª¬@PöJº‚˜Ê"fĐ.Đ0 1ÂP Êb´Đ๺©è4wÎ+6·7¸ü7̃zđnVaD骵­ ăG[Ø̃é ôơèc4±̣î@̃È#9é'3èçÏ6d/ ñØÖ=|ö©Ö-¬ç¿ă|̃}ăe465™€çRổn€çJ\)“=l)Óê6¹IªÚẩŒWBºFË !1vË;‘€ÚįgªêOàô<Ñ¥4´5Ơ!ôMɺ'“~Ä]Ïö24đ‹óoy‹6]LcÑ¥±®Hc]ú‚G±ààZ#¡¬P”$BEBŸz7@L“Ù}eºY¹â“éjdI’éµ› øHiä£ÛϹ?ºq5]£é:J9TŒ—Ʀ* MVxqçn¾̣èV₫đ¿~È#ûGͲ–"[–6³|~?̉„‘IÚRÖÛ7™N@ 4¥RѨDpÈ^×Yp¯*-¯„âèX…—¦88\ÁUƯe+ç7\¹f~[Éô#û†ơc{?3Đ×£?ú·Ÿi^¶v£Kº2#krM̃!È;yäqº`A\}VÑq«tû®=¼û^®=oo9·J¸‰§sèĐ!J¥ ̉ƒ0ÈH T† ,‘Ng’B̉2µ‡£+ç.n¶¢9Q2kYÿµûÿ'CœÉ™đDø3W¡)9,n›3ÚÜ˵|±;Ÿê¡½Éă­ç´óWõ̀|ºw>kªL)‘¾Dˆ?¶ƒ"0²Çd·b³"Nÿºà+Ñ 85À!’v{"ôăH\iÔ#E±E.S~Äß~÷”ü0¹^¤Ưp¥Àó#¾̣ÈsÜưt3óZZx×´5×3¯ÎeC¡—K(ËPB#´Mê–úÄÊDµà¤úcü7ˆ̀è@kAiü(bwÿÓEZ>¿È«çkཇ†KïíxÇ­o¸ù…ƒưû{ú…îO~đΟB IDATL·ƠÈ „9È#9ç}=óA¶TăÏB«Å¯ùÜû̀TPá²µ ¹iĂ₫ă…öï?À‹½ˆ̣R8H¥ f>+¤i Æîm2£».…À+¹|U3;»́§àº–X“øk¬^O<MWb9V’Ÿ¦ç:­åk’gÍô¡J]„ĐHăPCsÑa¤̣Ÿ/ôó†M øÓ[ÏæË?¨çûÏïähï@•¶zQ¼*˜!Ô% ¯n‚à\«ÿTIŒ ẵ„ëJP!¯¹úµ|øÚ|ÿ£}G©+ˆÂtơR`ºP®c•ÿ\‡B4FPçß8BÇâÅÔ\̃rn;-uu´5x”¬Fɘ¨DD¨Œg€í`Yoáª÷F§×‹®!Ù>©Ảé˜í ́è i(8¢±àĐ̃T`ùü:Íß¼F6®ZöÉO~ßXر¸0ĐÛ­€™Æ9È@y?”a·ÍØ2Oçî&¢H%’¶A¤‰¢)¾úø Üư\ ï¾j—®hæ-g_À]Ïôđ­§vAiÏ‘H!‰”@ˆTÇ?Öï—2–k5Ơ]ËÂN¶vOâ:Nº7_³ÿ?—çL$ÇăɱȦ@<ÎĐhÚ=0áGÓú†Ü¨):’‘RÀníçÊ5óyë%gp陫ù»o>Åá=;́¸ÄnÈ“@¢H#´2Hœ6Í€W œ̣F@æqc f)đÛùđµËÍ'ïßIÑsÍN¿Ơ_ˆ¯ ‰ “ă„xù鮣]‡Oí¦sÑBÖ/¬gMç|ÎZ̉‚#`¤2Q *! ?Rx̉( Æjƒ"Ṣg:Ó$°®‡ñơ¬,±DJĐPïNMiÆË^£R6/n̉À¯ßơØîï¿ọ́ơ_  f¸¤s €<̣˜=–̀+ê¢+.…©çú,*3ơ#eM€4ă Ëă|á±´5xƯùëxçù¬_XÇÓ{{yt×QdP1‡¤ô •J*™®˜ä繦…ûƯ½#8BXñNp₫?ÇîÇ1»Ô€…êäŸñĐpVg#Â’%ÙªO$É@¢ñA%̉|kç «Z'yă™ ùÀÍđ…Gêyú‡OÓ„6ÉÉ—8"Ĉ%p-xëbjçŸjÂM¿ÿå'ú¸iơŸJF i[ÿ©₫ƒÀçW̃x9 øÊ¶‚ñ!¤ăZû/d› G GàH£%Pp$£đ܈CG»éê<₫Rç-oeak óë¹tE3Ír¨è›¯Dø‘ÂQ82ÎW÷₫•MÓJ“yRRpơơp̀}ê]ÇÈ )ÆÊSA„#„èh.°haÛÀçm¾©Müê ¬È@ỳJëiÈ@3{ aØĐF…-ˆŒ Èø¦ONLđäIv÷O!®Ù̀/_¶œwnéàß;¶»ñ8 ‚ÄmME+æ(35:€‡0 €0£₫ÿlJ§#ñOMtJZ)y1¦Îe+LHÛ½ñ́9k} à`ơᩦ‡Î¦o8³ƒ¿xk+₫‰<¸Ç)˜‘€”H?@ˆ „(Đ ­²\ N['àạ̊ˆC¡Nªú£Çl˜8®¤|ô–³™ßPà‘ư½•©D·?v©LÆNÙw9‚HD¦+%B B©‘!†[(<Ç=Gâår™§Ç'i襱àđ̀¢V[æóÚuóÙĐ̃@)" u¤¥ÎĨsGPeƠ5Z!R±rH¨ Fø…í ^?A¤¹då< øđoưæµ÷Üơé}BÈyZ«mâ0͇øß̀r€<̣89° ­úZ¨ŒêZẈBàjiwà%£##üÓ7çóm‹øà ›ø½×­F_¿ßư}‡÷!<‰†Ä®ƠAÓ¹ú ₫kk©Ñ¶¹™•ÎtUO[+D£E’•„­ú~l‚„ÆknĂu]éGNû91 ¼dçÄ®c˜àû‡Ë|uÛ·n^È_¿ưB₫î̃:¶?÷4N]ÁŒG„@ˆ!"Ë Àê,Ô ™_†q@ök§öZŸøü?û²2Ñ®ăX »l«–-áï?ÊÎ;íZ^ôă5 2ÏGZ'Ä>¥Í́]* íc àPp#ü(¢ä:L•}ú†8rÈ¥½³“·méÄ–¶’÷x¸dÆ“~ÄxÙüJ~”fe=ưºN6lön®si.ºúû‡'Ä=w}zhµÉ¿öfWQ&ù«üôÊ@yœz…œXÛÈîçKaöơ#!pMäH”Ö ôvóg÷À½amùÆu|ä›0Ø}m[â4‹®¹ÏKƒ%<)¨(=ƯDƯÎ̃u¢ÖV}`f+ù̀YÈ₫ÍéƒI±ÌlƯm×DldZœ”]@ VÍïd·VwàX?G¼D¹ˆ_oÏ*Nú>xơ*Ö¶ƠQ̣CSíkèùÇÚµWBÖÂ:NÔækQâH)„ʼæ8‘“ ?”BEXPÉzªĐÛÓͽàđæsÚ™ô#¾p G"_MÖ Zi=ư:”1¸ÔFMpẳíH!nØÔ~ °đqśGaA.+œ€<̣¨Çq‰¢0]ÔsăÖ V•²Jh¤( \¥ÑÄqƯ|à3GX¼|5xă₫øæuŒûgđ7÷íd°¿Ïú h¶,kFkŸ4óo©2̉¸vmªªœ‰ÿôj P» }üÄTđ{ZÆ‚EöăüÆ:\G̉?LëèX:Đz Ôî…żÆs$S~Ä'¾wˆ³;›¸~ữ{óå|î;á.C˜ô-đ D*EF¨8Ư<Ư@ öónåÏ8-2&‘HÏ̉¨z\Qí7íûÇè&Ôby„6‚6B°³ ב\³v>ê†+x₫¹gyz?ÎPR:V]1À‘•`¶d·,0²‰ôåÊ~~¼ÇḲשĂṆɌڟë ¤ËÍç,gó¢"w=x˜(4É?T†üé´úŸ©Ê®sªºÉ5®,ÁRœ̀FGà@ $¡RTüsׯĂ¥€á©:Ï!.₫Sëê₫_¢úú‰; h‚3Úêµ'…xÿm×üÙèđ`fơ¯œ¹•l̃‰@vz¥fHü9È@y ?₫µ§×—B½NËhđø©,íiêL¥«h R+”¶ÎmJâ:&¹ÁÁƒ¹ă;!7mîàƯ—¯eO‰]½h ßxq€‚+ µƯ’ȉ]̣¤u€#!ÀÅ@ N ±GÀ‰$ä“J‚bú NZ·â˜bBºP“t®´`Gï$A¤X·°«o½‚oîå ßygđ,˜±€"¥À#³%ÊV¹§sK`.öÂsơ¨’ é¨Ä(₫IcT(°rư™\qÁf₫óÙ#¼Ô7ÆÎómå¯UêC‘ÍrA$1~ÿ2c­Ó̃‡̉à “ñṢWÇÚè÷yúÈ8 (Ñ]m*¤³F†9*¥ưk„ ½ÑÓÂ+ˆÏßÿä‘ÁñR̀ú«₫’½y6ï̀”ü£ Ф´‚ä Ÿö£0¢vÇÇêØu@[5iÛ ĐvåOi3ßW̉”0/<̀§ºû¸ä̀Ơü̉kV²aQ}’ëç348H·Y«D`È]B+”­̉”®®¦t̉@ œ®¨ •l­wq¥`ªJh:3v¦w¤mF+`{ï$;ú¦¸hù<̃°¡…&ï >ư­'º÷ÓXổUA!Dd¹ÊX2c:4Ùß¡Åé#ˆÉÏ\… ŸD&ï™´ ‰F¹Ï̀₫¥ă°vƯz7:|fo*ô-'Å$ÿ(ăX›üODí1YU¿ê½H ¢HqÍ™Ëh(º<¾‡́£ RßK¥ ˜Riu½RPœâÜ d¨PhˆNŒ*4Ƭ¥‰´XHOƒàKàâeíp9a²4̀%v˜ŒH¬&2‚A‡éßáùĂ“Ø=TÁió¸vư È\ ß₫ñ#à£ưz•²Nàäƒ"¡gáBB2©Œ›í‹Ov˜P²Đíoœ'D†>Ë‘wÿ 0 ¦„^|W 0¨NŒăV‰ß“à í‡ZJm¸aă*,lÏă—!¥Ô 9¤Íưm`wÿ±¦$ï0œÙÓBwÜù£CŸúđöh1½k₫dÇï#†¬C#VÍ@²“}|¿¦ t:yíA8C¤”¦ êt;Î è%wyŒ°c¨ág/îÁ}?úœåçặƠsđ á-v:>zçNlß¶M{æ+€)‚b±Ú[ËW¦(V€+mº£ÀŒ@5Œ@8jwh›%‹‘î̉“E#¤gûœ5P̀ô~ûD=À“'A¼₫¬nÔ奸ÁO„r¬îÇ#„Đë‡RJÈHëÜØ@0í{k÷~ÆX̀0—k_<FÇ'°{ß½:*dÄ ¯øÍ¦ûo È́×/L ä&@ÈaȹúóÎ[¦P®Këơ¦X'@Ó÷û£—76 ´¤€y-®ª*Đ#Ûú €\JQW‰Âï`üº£½Ư²sË‚́ü¢œkW¿®.éR?PJ6»LRz—ÖôâiÓá×é9lè Ưë|cÔâ i‚…$ênÙj¾Àèè0o¾_ûÊWpơÇ¿g÷Ă Ÿ¸z¾sËë0ñ2¸\ÛµFóáP fƯ§oÆ™No3T¹v×Sæâ‚…d(Rz×FñÅ;Z)£†¿WöÜ]©Y©Éz₫$QƒÖ^™B¡m“ PO˜ÀS'đ¦usñµ[oÀW\ƒR©¥‚‡–¼‡¢ç!ï:đ¸£çæ!8`&UOX´n¦N°&„eV&₫;&¦AÅÏiøcºî0Hâø̣[ÎBßxyß>äœ)EÔơ[¦?t<^/zR£îßhZ[[qƯù«pFwÇjÆ®7́êm¦ÉN …Jÿ¨ûׯ‹CPkç·̉æ‡ùä­¿±@z̃̃BÀ5æˆG,ëö3 ;Ù™íƠNÚldd²“(₫Ie6G̃&/i‚*]"f¨{‰@è̃: m‰Z«ù$à+ư;đÁ?ú4ZO¿ÊËăë¿~)n»n5ÊÁiøÂ£‡PÂ₫!”«uƯöH@1 ©À”ÎpGF@±È+ü½̉´”Øó£è9‘p[ºËåđlߤƠÙHG=‚ºĐ°¨0ÍpÜ¿sïĂëΘƒmZ€¿fWàéŸƯ`RwÏœÀX ä  …Ⱥ8´)ƒNÖXàØß†±åoø$»¦Ö\r5àï܆©#¡ˆCJwÿ&ơïd°X!!“Îuÿ.ƒç88£·„‹—”đRÿ†Ê8×, )Qh9ư}‚HN„Åy­¸ư‰­¾)̣ö7â‰.ŸR:}•̣¿£Jùû́d ;ÿ£Oºéư´<Ѻ8˜ëÆíÅ4&Rv6œ¨1°FAwláÜ6ôn€z Qó}ø¨û„`®‹©íƒ¸î–°êüWâÕx.̃wé|”¼Exxï}a;;8!ÊS“pÂqBI½- ăÑ€Rº«ÓÙTbEºaL(o¡S#×)ƠL¤Éq½4Ó"‰)́Ju)x ¾Pøñ¶\upëe đÏ̃èÛö4Ù?69uÓŒ,ÚBRÆ âªÑ8ˆ^Ææ1iùkwÿœ… ¡îµá¯®_…û§À‚1)S\ÿâîÿ¸Â¢Tăë:U:Œàqs´s8{ƠÀà”)'4ï9:»ÖI€ås 8½»¨nûêÆ₫üwc+¹J…†ØÑú^ÚªŸH|\ÿkϳ“€́üO­ÿ”hVSlBˆcƠ]ENK0×8 ëTd0K¸5+€ĐUtQp&ë¢iÁ9.*z î4ơª`Ñe¨÷îT̃óåxíé]ø̉ŸÄ¶;# 6̉+• B³¡° _[zØ€d÷ohnlë¾÷_s.J…¾óàPµ2„1ư±ÿ¾¿N¤ºY-:ca Ǹ9æ̀ëÅ̉vî Y€ø¨ÚĂ( fÏ.Çü6Oí­‚~đơ< =çOZùÚ?vÁWÿB€z‚ P‰âŸmd ;ÙiŒºÍ%̉)„ƪÔôS#Hèê€R@±‹¶tØ„"JÚ#pF˜Ô41'pé€3À›À{iv¾»d%>đÖkñG¯[ƒr]¢\[?¼cúöïFÑs@ÄÀ̀z^Ô²c‚F@¤gÿúFa 4 §̣P̣J̉È–đ̀a@-øñ¶a,lÏáU]øÄ[7áïœ=O?b ›¦µ«,"V¤¤öm 4®±` ÿÈ |̉s®7:HB̀[óV.Äן<‚Je ú±†%ă„Êpíïx»ÿÜ1²Ôÿ\wÿgX°h ~{Ó2T}‰]Ă]…?EÆH)ÿ$©†PP«Hà¼-p9£×mØđ‚éüUâX7Û ¨‚8 –`́1@Öưg ;Ùi‡Ó7bƠgᓯ[xË:ô­Æm?Ù‹ <‘Á¸œéQ€ S uñ é=nΙ^%4n‡µ¡-Ç1Y çTµYö÷TaÖH ô+JaÏpßy¦ן5Ÿ|ưø_Äqੵ‹îuóúÆnYFûlêŒb@AˆdVñ×Ô?u-­7]UƯ-ø‡»̉”¿Ùó·<’ÇͶX¢<½ KÎ5Ư¿Ëàz.Z<»·Áă,êâă‡Y¤A éđKKGWÑQ[Æ@»¶m©Z_mÓ÷a÷o§ÿUR>Ú iœ€ d';)ư,¯˜É¦™.xiMYˆYÄînF £ºD`L‚Ëp¿_¯¾F'à0@pÔưÏ=ˆv\…BÎÅ¿¼g>ăi "ܽmÿ₫Đ󺻔uĐÅ`¡ºÜ<ÈëÂI†&¶Asÿüx^·dRaTœI''¸˜¨ üç ƒ¸am7>sƯj¨kWă]ÿpøà!8† `Lo0Ÿ" Tv² EÖ¶'º% ,ê'rüc3Üx₫;ùœ‹9E_Û|‡'ªÑÆH¸=ºLF®Çhú=wª1áP=cùË4Ë´`ñRܺi1êÄá‰:Z\®GBG¾4₫h›ßpVô8Î_TRªœ^µnù³ƠJYXÅ?Ø´¿Ÿes«&¿uÿ/ăÉŒ€²óÿ6h £¥¹Y¦6ÖµqV!,)?#ºz™N\Jơ®”ÔÅÚèêB ¨×Të>ªµ:*ơ:*Ơ:*5uIüùƯ8ôè¸è×ÿ₫·Ç16YƆ|ñ×/Ăk/:K—¯€ă¸đ\Œ`̀…4ưëqCøÑqôl˜16ư±§ØĐª+¯ư<‡›‹Z×­Ç _à Ä][†P ₫ᷮƢ37 ŸÏ¡˜sÑÏ¡àyÈyñÛ×ú n²hîê>ă ưø,O…Đ̣×øư;Œ£¥³ï½á \°¨»÷́E½^’₫Dƒ̣ÿøßÑŸ%@dÆôÇaz ‘s9ˆq¼÷â "ü×öaä]n •âñËŒÅ_c2kï_S^ Û<Ơ–whđÈ ¤ø}”ưÙ3ÿ°đ'oi€fë€ÙÉ€́ü>Ê"#ï_Ï⛫ºƠø**ïă¯ Ç!µÚ°îw›î/Ñ'AŒÀ¤Ô¥`˜Đl@è ‡à°:¾ưßpÍÀé^†÷nZ‰kVàVăë?o‡¶ï̃‹G¦ ‚ºị̂­îße.#x…"r…"v UP2²WꢈYk/ư¸Ÿ÷Y€€vÆ€eǶ·í8óÏÀ­×œ•+NÇâ¹]øƠ đ½§â‰}84î£<1—)¸Ügbió.‡Ç|©,—D³Bhx_²@ %ûIÓ<[ „¼Ă0R đưçqá̉6|à5gbûº…ø»»ŸÆ¡=;ÁĂ‘@ÀHÀ'azHm¤Rîá8€ˆPbí4 üa,t´pƠ¦¨ `û¾ĂđëóR«püƯ?lÍÅc—33ûgp̣E\sf7&ḱƒç0 Á?cv¦?ÈXPwƠê}ùï>w¨oÏ2´̣_6é₫íÙµI÷Ÿ¤ÿ“BÂSIDe'ÙùEóÛ<´xĂ• Üz?æ‹øŒØ&¬À4BAy B*¼aí\|JhQ_˜#l­(!FG! !3›•ÀH‹Ú10!p ÎX´kÎá¸hp'>óƠí(-\…¥ zđªK7bẳN¼vƯB¼Đ7…êä₫ơé~Œ èzpPđä\‰j S)ôĂ7úS)"q`d¿‹éÿ$…Æ-é•Ë;^Äê9E¼æô.|è†Kñ—·°wË3hÍkå{…ùÚÚÖ|AÚÂÙ²»\:& R ̀LJĂî_{;˜×Ăqеä4\´ Ïü×v<¿,Œû´ '§ûoT₫‡Ùz̀£ ¤—œÖ‹-xlï¦ê®ñ †ÿv÷¯T¼1̃—ăgÎ/Ñ#?9yû?@¬ü—‰âo«₫“s$‹¿Èºÿ d';3®¢—3™¨'‘h^ĐOó³ëB£]Mk©Tá{d2.đ›¢'ŒhM’I!ăàD†àp¦?r†jßNl?²»vïÆ%«×¬Ă-oÚ„®E-8cIúGñ•'ú ‚* ´?gú"¯Tœ¨Hƒ€°4ª&‰‹'P ಷ´.@H…CT_ÄÖÎŇ¯_±Ë–âÿơ!´Œg9pF¨Rđ‚ ­¹Ökx,öcá̃?³,9̣\áé"÷ñâ¡Qˆ ! ” Êÿ“ÑưÛ‰‹,ïèP©œĂPhiÁY‹æ¢o¼†I<ܰºÿ™4ŸQ÷o™₫@gÁQ.î}âÙÊÁ[&MƯs9lúßO3uÿ~Öưg ;Ù™ƯÅP¼ó¸~¶j|³}¬*,ôVñÿLVëúùëÙ5@$M Q¸A@z<À8†v¡à Æ₫Q†CưƒØúôcXpî&¸ù">săÙøäüNl˜Ä½;FPtÊu©Œ˜BưØZ6Ùª&lF^¦„” sôă ˆFº q#b뛨ăËơá́ù-¸pi₫ú]Wă¾û Ø̃gÁXṆÔù¨a‰GaIU黜Ó›‰6W)0đ‡spV_„yE†ư`+jcC )’zỖ$8‰ƯHÿ׿–b¯>oÖ-(á₫]£(×\>›lVƯ£Ç†–Ov·zXÓÛJ_₫á“rËoîE£é˜eñO*ÿ³Ơ¿ d';¿`$QÈgûơ*­pÎÀ¹2ë­ÓM" ”àŒ Lk¸ö¡wT‡Ô0øÀ]È{.̃¶ùœưÊ×á#¯=ë”Àˆpp¬†V‡&êPRÙƒ‹p,añvÜ–H₫*¶$œö\Ø­g3Ö%Í=¤´ºß”¥@*<¾‡Æë¸a]7₫ü¦óñ±ÿø¾ÀYŒ3#ù`$˜‘€HŒ0CmüẮ}{ËóJ᛿ºC¼¸m' .7k:ô'rưSñk~\•Íră •ÿÜ₫ä\9‡Ău9Ú öV18YÖ=ĂǮԱtÿ¡—ĐYp•çMVjJ¾ÆÙèø—\ù³éÿ$`«₫%2ú?ÙÉÎ/"®ÑÏüuÓƯÖ’¶AY3xvƯ[ ̀pVJ‚`º0rÁ"­€è¥»P(‰'̣}ܼ¹o¼öjÜpî\°¸ *̉ܵEw®Ăµ@E‘ Óè~kwl†ÀL0â-J}b!¦Q)*”ÅE]3 óñ¾ÿü ̃¸v.>ưæ đÏuaë‹/€ÀaÚœ§æ ̉XeRĂ2O0Ù –6 ́ü ‹íÎà2­¶Ÿ¿₫U€Røè;Pp)NŒ±!“jtŸ:f‹^³óo×<¦B1Mg¯Â%KKx|ß8jDÎaæơ¥È&(ÿă´?ûkzK9¬[ /ßơxù–_¾ê9è¸_Ù„H›ư§uÿ¶ú?ÛûÏ@v²s”‹ 1¨F%Ơÿc0^ P̣ˆ;€'đûÑô"™Ø̃1#  ˜`Lèù´à BÈ(î—ŒhÍÆO>…ơË»10VÆÓ‡&ĐÓêaÓ¼bE .ĂPÙÇÖ½ápp¼¥¦êºdÊ”î>ÊZ°râçlZwéU²"¥|ß´èÇXœ¦µƪø̉c‡°~a yíxđŒÅøÆÄXÿ!3'÷ÁˆP#_«á…¦è¥Œ‡Ø,Ü@£QNÈ:D³+đGu.ÆW̃zUÑ¿o7r9GïưGÆ?2JŒ<̃¸_{$Y₫ZÊÏƠ{ÿóÛ ¸æôŃ©bïh®ẰJj£;b³Î_5Dư±‹"lXTR£SUơ®k.|ˆ<“ögïưÛ†?Íèÿäοm÷›´ưÍN²“d§"À­ ̀)/÷åbzF0\Nøæ“ưøK"×µµ#{Oб„igˆR*2j‰rˆ â0qĐ³k—ë=đµ=-XÚîẫçq`p‡€Ç·B®ØÖœƒ]y¬_Ô•ṣ`Œá¼…m(z ›÷ƪF+¦ê:’·‚™Ï«Ø^–ânIئŒ%pCÆBnº mNDÑØÂă 5!ñĐQŒ×._ÙuÍ+pû}bÿ¡ĂàåI0ÆŒo@€ºè‘I"Œ¶æµNº₫9Œàr½FéKØpΙ€₫ç‹È{ĐÛú×öÏ]'–ö—Z€¨•ÿYí¼`ÍJÀà”z wÉ2Θ9íˆç₫añ—X>'ô÷ÿö£1N¢ø‡]¿@ºéOÓwÿkhL₫Ë<ÿ3́̀êÈO|ë̃…>6ù²Ù$/Æi'ç° œDebR/@‰M‚đïe˜e H ‰t<0@€1B1Ô}D„j`Rôà *“(Oưƒ nQèhmër̀)z8wa+ …̣aMO ̣.Ă¾á*¤)8¾Ø9T#꣔‚Ëbơ¹í%F)3ó»Äƒ_ăŒ­ß{&Êœ"=‚‚ÇRx± R)¬_Øy×^†vÀ÷Ư>xœ1TrÍđÍs!¤˜ª!Í#b8á ¦ĂÀ! »Wá®Z…'Najđˆ1fAȦ@î˜CÚ¢P$—³Èơ¯½½›–—đ\ß$v Uà9ÔƯÅ$̀ĐưÛî‰ Đ­™WTă ô±_¿ñE"r-ó[›E÷´ÿ́d ;ÙI?AH|jÖ”7­¦/ß&¦ÀOH+₫Í6&4­‰@JøB€!ta „DÍ—‘ĐË̃X Ʀ¦@ Û ÁÍåQôæµzXÚ‘C[k \‡£§”Ă²ÎVΩĐ¾á ZÈ\f1(V"Øâ¸Ø0}:@–Á¢½8¨Uú±]~± »‡«8oA+̃´q%æ̀™‹/₫èQĐÀnp̣L8’H:ÁQJ@Z8íOSÿ®£ƯE©7­_Œ¢Ëđ÷<î0åù/ăDF[Ëq<ïÛ«³̉₫tàgÀM­‚ »†*!ø2¯fü<¥wÿϳî₫=ÎpZw£[~ÿ£ûSº{öowÿi{ÿáưiÿ̉úßXfW¸ d';³êÄi–TU·é{ØJƯ₫X÷ÙĂÎö,ù0Í@™½~m3¬La“R@HƯ¥0  ŒÎÑËNd¯›1dµ¿ŒM–±ư°BÁóÀ9G‹ÇÑÛ–Ckk my•s ¸tyÊuº¨úzưîɃ&«©çØ8SÎÉã¾hDj*ơƯ "pÀŒ`¯H<ºoåºÄå+ÛÑyă%øÆ}mØ»{'xẻ 1ÔX€z IÀ R"{çߨ₫…xó…§á=—-Ç·Œ¢<>¦é~¥¬8fƠÈÜg÷‹ùᜠAQ÷ïq cnÎè.à±½ă¨ ‡Qb£f¶Ê {Í16_rƠ! úúÿùt¿ÍÂ¥tÿ3íü—­â_O)₫̣([v2́ ¡´†ëU³¾ *•R4â£\!£ú]ˆ1;€ă' ûÂuĐ,z,Ăà9·Ô…÷]¾ °åHWÿ.ÔÀDͼ÷OÑÈCûxĂ™=-jœn¾₫úmæ »uѤøW1Ưñ/ö“@6È@v²3›ºçû5¯̀®½Ö4/‹>?ªz*4¹x+ƠXt N$ÖåÄÀ€²öÚ£xßP‘ „×súäÛá¶V …Ç 82êy ¤QÅë™4gZ覤€ 5ßÇXÀ!đü@Î_̉₫ä»?rÛ‚·ưæz{‹À9¬˜S€̉¼2RáÁ]c€Ñº×̉0­à+³· (¹m _EN Œô|¿¢IcƠV\·¶5u)n¿çA8ăĂ àVc`A€€4S¢̀Jœöúçp9ƒTÀg÷âµg̀Å7ŸÄáÑ „Rr**±8 VåG"Dö“s8rœ¡»½„΂ƒŸîkâ"¥RÂч₫\¦G?æ…m9̀oËÑ[ßú¶íÜưñD‘n¦üOÿ́µ¿Z“î?+úÈNvfI¼ø¼uçú`7 ©”TØ ºØJJ\ǻ̃‰fpNaDØ̉_1BqájŒ îY®ë6 Ió8)OÊ,‰p|K¹ƯØ>\DZºHă6hJ¤˜#0ÄÊøx5Né}tÎ"‹]θù&B)Ôj5ñù?ư½ŸÿÓßÛo’ÿé¯~ï̀µ.në,0µaQ ¯\^"î8DLúØ=\PP‡Çk$•B`^œÈR—±¨ Eë‘öú!Êä*Hằ÷ÔÁ xœđ¦usÑƯújÜùØ 8¸gœJÆàÔê,€/E$œăÆf×ụís±đô³q÷¶QÜơØó굨ó—Öü_%œŒYùo³:°â~¹ûu8¡{₫B¼ỵ̈eàL›:åfÆ6³-ËxhBơŸw涸Ø7¡°»D&₫wPV€*̉•ÿö́ßOtÿ™ê?ÙÉÎqµEúªq́n*³¹đ¢1 0¼ŸY₫ë ^ơ …^E´+Qă•·Ùj߉‚4Pç&Oÿùh·Ùw©$ØZ„" ÷ÛÍl€™•=n y¤ŸG2B¡5Çá0Bÿx=µđ>̣«7lELÓµ7ÿNïÛßư₫ó kº jí¼œ—Ë1Ç<ÎÍ&¡”Tc•€Ê¾D]H@¾QƯk³{+̉áø@“ÛŒéùư£{DZưH›Vv`Ó[.Âß<¼Ï<úøä$¸Ă5đ„T (0cµË8Ç+çá k:đí§Æđ'Y¦Åưªc\ưS pJÆëŸ;±å/1wnèE«Çñă­Cđ8³ÀlsgĂ˜‹f…®¢«zJ}đ–[÷~øâ®\Ơ‰^:_r_‰g6?†#ƒƒÈ9,Z m‡ÎPl)âüች£øî#/ü²aNTÄØƯÿɈûed ÿ˜̃ùçDX³lÚK-¨øĂågÚ1Bu4í =Ȳư₫ hq–thû`ó–Ư~‚³•ÿIÏÿJ Í̉₫²âŸ€́dçØ.”-G‹/Q® ̀hn~ øj‚l5°˜&„y *øx÷ĂgĂ7̀±£x‘,v Å,‡5ˆªM;G.?Ó¬₫UÊ熼 çKŸ₫Øn›˜9çWu]ơ†›º:<¥¶ºôµo˜Û3¯Û]6¯ˆ<€¾_W庤á²Ñj©€)óáF̀¨ #tëRá]£¨%¼kc/ï¹?ó6ï<ŒÜÔ(|#è#ó.ÅƠ+[đ÷?ƯY›c ‘~B%“¢¡ûoVü™ñ,p97Ư?‡—ËcÓª¹ppßÎQ³ơ€׿™~ªƯưÛlÀÜOÍ-:ôơ¯ưpø‘»ÿóˆ© i+añOvưáÜ?ÛûÏ@v²sJ?7yť!˜ ü I© VªÑ½Í…`t µ;ĐP“u‹o›óDá/ÆŸA!Yÿ™Uôí®1Æö´N†r·̣ä0=èÏî*§ Eü3₫xđ™|F®~ÙƠw-Xº<_p™Z̉Y ó_yƠœ›.+-p€Ñ‚5Q È [Ê€)_@‘6p ̀H`¼`QGï»₫|ơg{ñđæ§P¨MBH@ ‰âüø×½ƒ¸÷Ńp?¦ëu êMªÉ*̉áóë0Ç!ä̀́íâ.œ¹° [&1V ̀ÚŸåïÑ̉₫Z=Gơ¶èÁ÷ù_üâ­ôü·E¡ú?©ü¯¦ÿ,í/ÙÉΉƠ³}ï\»xÎu!/¨ ]EDÀDM̀é®fl„§ề¢ö7*åơ¿ʸêÑÑM€̉œưN„PMzü¨ê†a6¹rí]ª£H0su;ÈØk?êѨ $̉ñBkZs Wë¥>vA‘)…A¥áªÄM`Ươ½#Ö¯Ëz¾öÍáƠkỌ̈\Á ỆÖÛ₫vå²ÓÖäÛZ],ó€%s‹đẹ̈¥¢¾ñ:Ơ %Đ?Udz‡&±g¸‹–¶ăæ‹—bn)‡û~ösÔËR"?gÖÍËă/~r¨Ađ iï₫ăø=ÿ)Q¥µ!³Â~8<‡¡ÏcƠÂnLỚ­%V₫ÎđDc³È%P/6,.Q}b¸₫K×\¹u`ß²ơ<Û–¿I¿ÿÙPÿ6È ~²“ăûûú'Î:(%.œª£#ï`NÑ5¡<"µÈ++<†¬i6…A:3xï­ê# —ÁˆaÅÂ^<ó¼gíD3wæ)€à¸»Æ„@xÓ+{̀”9ànơ@›ó0B”ú0[h{j ºëiƯơ›Â­¢)W—³©ÿ¤‘LZlÏ0«ø³ÄŸĂûTÿ¾]Sưûv…Å ›Ÿ»êùbkÉáƠ÷Ø›̃ưÁ7¼ă׺ç€3{\œÑÓ)¤̣¥¢z đĐQl(CH…×Ơ‹W­z5¾đđ~ •}ü̃k–`¼\Ă³Û÷ÂsT|Í₫-Ÿ©ăüí₫ÉUZø—s<ÏĂ™ËáU§ÍÅS'0Rñ‘sX²/Ñư‹DQñ@@%j¢]ôĂÏ9b!¥:̉w bßÿ­ïÙù©¿T)O‰ú̃OÏ:sưEmy†³æåpí¹0v·Dó9Ürå*üÛ3(å8>sÏ>´¸„—Û0ê×6¥:®Ê¦â¤Dữ gÿzï?ï:(ºz;[1\ö±{¸ ‡±xáT!ÊP˜‘₫'{T¥ $pá’6Ôk5yíúO%éƯư—1ƯóßVưYñÏ@v²s̉’¤R „çĐTŒ<̀1 `¬4Snŧrc¨ÂTè2GfçÚ²œM¹>Å=6[ ù"«U5VÆ(Æ%7;̣Gíi濘iµ«(QhĂ##îh?{"ă›¯÷ºg \NÿÍm°₫™³0‰ȵ¶£§=•s hơ8.]ÖÙ+‡Y8ÿä'—üû₫â ¦¯’ÙE%H ûØÅ[ °–€ øƯÿ^ơœ 2̃~Ë-zÇ{nYÔ[„8«·ÄFÄèÍç̀ƒ ö„çpÔ©53¼^Ǻ÷ÏÏyè÷ï:zïßsœwÖ*\·¦ / Laª.Pt™aÿLÛôQÔ±ImĐÓêÂå ßúPÈÊ0 ¬ÙL½ú—¶÷ßLø—du²âŸ€́dç8Ùî[uahªÀCWÁ…”ÀPÙGñ±*̀qçẾöơvh9 Ût¾É0Ú¶Æ%[L¥étvÜŒiĐAdvÁcmÀ±̣†€¨qG¼IƠ ăa^¼ Ïsà9.<׉Ôđ®Ă@J¡$kt¯#ÆA ĐVđĐ̉Ö%9´å\¸´ yGÛí†B̀í“x`÷§ê¨ù ¿yÉB:kN`AÉâ_Ăt§8?XâæX@Àfi@~ósŸØóÍÏ}b·¹O|è³_\³|톶w^qv¾è2Ỡ=F› !ð@F 0dfIÆGï±PŒi»₫Å€Ás9Ú9¼åœn Mùx¡o 9ÎlztPi«₫ÍÏuĂúE%¥ºáüO€È1s0»ø'W₫ʘÙôÇưÛŒOVø3́œĐQœq‚UO;ĂS>”æ´¸ Yœ́́táhƒAL½Êµdd¸¹¦¢Î:!xôx‚q.ÉtƯ Jr3ÅA5éfÔ>¦…PSÑîñw*dœ3xƒœăÀsu7ÉÍî¾Ă J±VàÜ…Ă-G)ÇÑÙV‚"s–à0º̃"¦ê_bª.px´Œ‡w¢<Ó7 ¦Tm yÏÃap9đÓíE¼m}/~ûÿbÉßü–m˜n$c;É…÷…@‰"n'å#k‚fÀDäüåï¿{+qđ¿söÇ~ă—º6­êV·ŒTỗ=“é‘V¨!ˆfQüâ~ ˜ˆâ~¹N¼xƯjzäU $”Íèë`§ưÙï(̉ă¬̃’«|bô…ï₫tÇô¨ßÀz­’Q¿3™₫سÿ̀ơ/ÙÉÎÉa{ü±‰ßyĂ+ö»L_(…aCEưpÙg@oÉÓ®én|‡A*n‚b´Jûä‡ó\X€ a&nF! Đ1XÀQÏu¡ơRi/Y&äôÀJ÷&ô†m»ÛàÉßạ̀^đ%¬BíÊÇ™®Œ¤À đ|.§™rĐÓሰrN^¾—aa{K»̣¨ åºÀ̃‘*êÄ=/Ƴ}S˜¨èŸđ!ë0Óä9ŒA‘AB*Ô…~MvĂÑơûø­_ǿÇwS£e‹R ʦ¯…Eˆ…Ư.øÉÏ“  $AA`J)ó”ûÔoƯồ%œÿ®k..ơO,ŃÏî„ËÚ̃?Pº‘b IDATEƠºûçDXØî© Ï~́–}˜>÷·AJ÷ŸœưW‘¾ö—¥ưe ;Ù99Gˆ ¼đf|"Pºh-jÏÁå ׯí†RƯ¨ÔB¢R­Á儇wa°́cÿH5®ùBb¬\‡¨NBÔÊP =o%ĂCŸ3€CUÀúEm`ÜÑ÷I ¥$„"ˆ ˆ ¼’D̀˜·_EărspÛz L²^¾{1ˆ»`DX¾¨7ù­o>g–våơ*#­¥Ö(₫×ÉÀ=P ¥Ö–¨û+º@È{¨K…—Ê82écrb }ăuÔ‰±j)()¡`Å Ŧ7ˆ#o•%$£ƒPÆAÇÁ#ĂæÓÍoxM×ß̃¶¢uüĐ®!4êB‚€UH`>p›ÜŸ<…Mh&.ŒØ‚]Ï?éßzËï¿đOŸû́YWÍS?§œ¬"BJˆPT*©Áă! $]ÿŒK¡©:&|Èc@[W7Î[Ø'L Èè=Ø0ïAóâ¾&Ê<…ƯO)Gø‰Óïï¬ÿ•’¢??QüËH_ûK£₫ÓÖ93€́dçÏ ¨ÎuYgFªØ=ZÇÜkuVÏï„P@-Q»/îh‹W—₫ơé©°s¨‡10TjuøBBL=óï„Đ|¾ ¼%áûB¢´`¤”h-°¤w®a€Pøă×,ƒËuáœ!ï¹Q¨ ÷rQ”q.ç4\äó¬ñ÷₫́ƒ‡‘w´æàđàFÆ'ápZÿ.xœÁu¼|+^½q-®<½m=„­‡'H? ¤Ô»û¡Ÿ¿µâ¦ÿÙ^`±ú¹—L?vb̉̀³}Ü₫â®>c®÷ÑO₫åiùƠîO¡—m P± jÂđDawàÀ!hÆđCĐÀ|ó+_ÚwÉ+¯œsó W÷ŒŒâ—Àu8|!áHR­£ÍZé,+^<÷×c%ÏѦ?¼¥ï̃´ áÅ₫)¸‹À¬ö₫ ц ™/u9¡»ÅU=øÈϦ‚zM ÑôÇÿ×Ñhû›6û¯§€4ƠVü3́œÄB4Æ@êkçp;÷́ÇS5•_HÔư¼ÔpóÚ‹Ñw+z óK9\¸¤ +æï½l©)t9t§oîë™ÓïÿƠè‹: }çÍE±† ₫´nĐœ½£u|(¸ Œ1lß{5?”ÂÔ- ̉Ê|b ơ‘Ăơ¡œ%j"̣UÆ.W8G>ç!ï:¨–§°²÷j§ˆj0˜Û@(øRÛÛ "‹[óKË„6B%ŸËƯ=ÓöaÛ‘ºîL¢Ë×,pĐ(óѨif[  0] ́âƯØcẻÀ›­|ëÿ~cûë_uï⽪´”09…I¥ %AR˜¯HÍs*,ß " ü8#x\›₫ä8ĂœR+æµzxh÷hd¶d»₫)5}ïß^ûS–å/cúçơ–rXÜ™§üăû¸ë£Vgnû0ø¨4¹ÙkuLßù— ̉#;ÈNv^>pPơớ½·äa‹Đénµ@ Zt÷>8¥FúM€pÇĂá¥K"×5Œ1̀ko‰¾f~ÉCkăú³æ¢5Ç!¤2i´„'Ü₫â ̃3n(à¹{#‘_09‚Úđa0Îb΅mÈß%iuJØËÎ’ÂE cp#̣V{vïľ½{qغÿ0¦ª¤T¨K‰@(¡ ”ÔÛ‘Ơ­u%…’¦tXµ_ïÏA+ăPÁÆÇ†è±ưèîYP\uÁ+{v °oHßÇ¡Ï8ë=ü”₫̣ËÏ_‡kO+áƯơ¯đ‡AH¿î£êđ}™ñ@¨ú¶ø{óy¨âWV/#Ê]5½¤Úë‹ñCœo@Df+AWkª a`h›Î^‰{æ̀Åø¾¨ëׂ6©Cp¤ñ·· í"£?“ ÄaĐ&@‚„8¡.~¾oT½ë’E­¿ó¾¬¸ơæûw'ºĂäêY8HÓ$K¡î d ’#„™˜€;qäĐÄ7ÿă‡[/¸ø²¥,í¢ûúTøHm}2 *4B¬̃Y¡̣?4¨â,Jü#Îñú³º1¿äá]#±¡”y©}$̉̉₫Vw©»ƠĂû?ö‰ƒßưçÏ2¿W³ŒÍfíO6)üø8<{ ²ó Âø«7₫ú.. ¯Ơ``z‚K ̀mñPößÓJ=@Ũü@ƒ@è ·ºó /äQË4H?$ǹv+o8w1jö́؇/4è¤̉ŸKư} øR"oB ¾ùZƒB‹̀„Đ…Tó¹¾Å–F !¤@ Í¿1ß_dT!FØSÍcăXÚUÀ»ú#ÊßN·Ó«‘Zẽ0Ô…¥1%‹"đ©ÔZ™ ;ƯGÛ:xxÏö!L•±“ælKÙäny€F¥zRÀê‰b–üùŸ;<9Ô_µëäÚŸß„úŸmÚ_VôË‚́üâp4ë« ³Lr¤Y±—º·:çPùº÷…Đă¡‹¸oyÍ×:‚Zø¹¯ï¯ ·¿8ˆB©]‹VÀ÷ëQGï‹đßúæû¨û¾¾¯æë[=àG7?ô÷‚˜DÄØ÷Å,„R”R`!„??€_Á·úsŒ•kX¹`.¤”Ư{J™ Ç G;ÊhBF!0C!F'ÊäX±dq N®€t×¾¤)Mr<`GÓ&)ë´}u»“ »Ùqs3·Qóq$q¶>†Ÿbjøà'nûÔ÷jƠÊÔ ëæ‘Û̉†×»û.·2',Ǥđ/ôüw¹¶eö%s[qÑê^́©`hÊoH±l¶óGÛïßNûkq´åđÜù£ùâ!ñÈJ£ÿ«³,₫IåÖưg ;Ù9•G5T‡fóNÀđ”öpíQ­…yFån(₫ú·éÿF¶@ÁTü@D,‚Ö́.ĂËåáK€RdCăGô¾Œéûđ£”6½/£". P‘á|Ùº)©2éSoRY @F B(``× `¢›7ô@z%«ÈÛ)†³)&k@!^Œ™…¾‰:>0…˯¹₫¬ .»|.göÉÙ}r}^¦Œ’€ Ií׬âe´4z; B`0~󑈦îúÖ—îÿÉöàoó°fI/†Hħ]"ơ&GäÚoe:ÄÅ_₫ä\\ÎĂ’=p™Âö#eí"IvnD3æ%ÜơGjÚßúE%HáËw¾ùÛ ‹‘æ÷oÓÿUë9K₫Ù®¶€0+₫ÈNvN5Àf¼Àu­¬™Î–¹¹¨›Àƒk©„|:t·³oaAỂDsw]\'ûĐÓÂqƯ¹Kx-QH|$è“RB]̣Ö¤ˆ«D{ƠpSªá†Ä}2úHávEJmy‚«è«³Ïư|<Á®$éÿÙÿ̉,3ú?ÙÉÎË0;{Ơ0²V¿ÁUCŒ¯]́CëÖ£Ư „´À€én…R™¬áÑSèjÉie?!Rû+KF/¥ÔẀ&Å[F½Ù=¦ä}%Ë‘v`€‹v® °{Ë PRâæ ½¨Róï̀PÔÑs­ºûYÂÿ”öJA’”{†Ë´¨Œ·₫ÊÍë—¯\Ưn~ûfÏæ)…’ ,d¯ 5 &‚öÈ YôÊ(˜jÂLÚsđo¿đ¥ÿ[Ê9ôÛ¯\§µ9Îà¹:É/hP­ư…Ô?×iycÑâ%¨úÏÖ¦? v₫ĂѨÛï_¿V¥œg₫Ù₫)ºxiÛfó|*L·üơSÀQƯïL~ÿY÷Ÿ€́dçÔŸ¡)_ÂăÔđÆƠÀX$ÅQ Đœ’6ơáá>µEw‡E«Y…± s(¾‹üß-:~¢æăÑG°tù ,\ºP*ºà'| ”ŵ+ *ütŒ]wÚl^ÙÂF‹–—2GH†öâïܼ˰la¯É/°Ín5>–ø1a!©ă øµ*Ûu‹ÛÜô®÷¯w\/ ¼y @`‹ùR#ï…¨™ŸưlFuL¾±-p§R˜‚Ê7₫́w¿÷ïO÷Ë΢‡ KºTØƠ»‡kD~áª_CÔ/×Ô¿ÇV¯\…wnèÁP9ÀhÅ‡Ă¬§^¥₫Æ·l”-¨©¥°¶·U¹œ¡Z­*%ẻ—ßVÿ‡ÏẠw>Z÷/2ê?ÙÉÎËzl5¼JLû{³(UÏÇOa³]q́Ñ€&†°ºÓÁ+WuBBo hÀ£‚?~ƉW ˜[tÑ^té¿?¼ê´¹O¤¦$ª5aAÂß9­øg²“—±ö'¯́i‰}ˆUÖ5ă°°Ă3á4mĐ1₫ĐÆ¨[Osÿ̃Ñ*?PFçü¥(–:À¢Î/öp?5Å¿A„g ”ô‰íjM€M¸90̉‡?»ăy¼é́^´´uhÀpÜR…,ÇÊ5¯Ñ’ gṇ̃v«èÏl`feǛ€@¦€€4æÀ¶ÄµA£ P©)æ¸₫·¾ñƠ/µå®?w‘*¶¶OÇÑƯ¿öú×7k¿FÀÅëVă’eí蟨c².à0‘ %Yô#Æ D*Z$cC¼¼« n¾ê‚ç1}îŸT₫§mO4³û‰₫ÏN²“SŒÔôÂ߬1 ¯|¾P†§†‹è1!†Ÿ§ï”„B¿ÉÀáñ æ-Z–R;±È;À.¨Ç@¤̃()ÓŸŒÖ%»|^súøpby£(‹ZïcdB0„Tđ¥‚ô«¸Ç„>ø‰¿¾̉tøys €ÛÏS7[† ù1h̉-7t̀2đ'ïüׯ<úđ¶Ă#§Ïk¡3vÁơ\äœxÇßqXdúă9Úó?_,áÆuƯØ3\ÅcûÆQp¹5"SÜEŸTX~óµ Àœ ÚsôÍÛ:nF`IË_‘`<íüÛæL3íü«SôvÎN²“Ä›•1ǮϪI¥&̉j{¥´PÜEQ´)@³¸nQ*ˆSñ$â·_¯bj| °¨·Œ;ÀÂyƒ²{º€ïd€€ä-.ƈW ĂơÄ@ :>‚'û}\¼¬s;Z…háø)€F E¼=!phxÏœPo¿ö¥ËιhQ‚˜ 8,5@Ü“H§Í«*;_|~àö;îø÷©8oyj+äµÀÏƠL@Îh<³öG̃xÁJÀÖ#S¨Êû%€Tø«èGWMçÏ@XP̣|ño>Û76t¤XI R$«‘dlm„tåơ›€́dçå9yŒ“Üæ2"jRÂê ̀åiiW>å5Ó¶5ă3í«Üô1€½nØÚ7 Æ€y%0ÎM!e F‘²; ‡9ÉÅÿ῭€Ảøø€/%j~€oÿ×#˜×êâËÚà ©Ÿ'kNt ̀F@`| êøéaêÊÿûo₫éZsJB4 :ÙOV H æ’ÊùÆîY‰ÉÏßö±{¾ÿ“‡ï_6·•Ö,_  9y×AÁăÈy y×ÃusJs°~Q?<‰©„çÀEÚÏ‘ÀHE,E¬à©h¼´¤3RK₫ôo¿|ä‰G™²~äÚd̉3a¶iiÿYñÏ@v²ọ́¼W÷dÀ`Ó‚iƯÍèŸđ¡à¶u6tPG«”h¦µ¡³`$Î̉Eü¥₫ <»ËÖœ\¡FF̃dk¶{'TƯ,Ú^k$¤P±I‘ïc׋Ïâ₫}Uôt–7§Ûm-ew  ¬±„Pˆ2¤" @)¥̃¸ñôNSÜshä,¥ÜNÉS†é7‘̉A‡…´ :9Ô?ôùÏ₫ö#‡ûöÿÊÆE4¿w 9×Ơ·GÑsÀˆđËç/BKÎÁ–2„Rà,¦̣ă÷DLñ7’40Đ̀ àr†¥yƠƯC1lƯºµZ÷Ă—cTÍÿ¬đg ;Ùyy[•™¯A1  ¿†s̃x¡vPÊçH:̃Ù¦;j“ĂÍçÏGO)§á(̃ˆ:jĐ1íן\@%c@HŒâÑÇẶîw#“pƒáø~XH`G΋B3JJܳc„ .§ó¯}ë٦ȧ̉X€—å©JÉNÚÖÔ7ßùí§¿û³—¶Ö$.\9W=ÅGk̃A1ç"ïr̀ë‡ù]%S†êWpM~À’Î<®9c^½ºkz[hóK;j^|ù–oưưg#öû·ç₫"å1Ûsÿđcåo¶÷Ÿ€́dç$ekk.Qœ%ºÙq”¸åd·ß¬ƯŒc{5Đ p8á'Û†0ám V€9\Æ@Œ™uÀ—ûù „C`́ ¥ Öjïß"ĂyË{dz(çFà˜Å€fDm(í¢¨ đ³ƯcàÜáÿÄm¯²X€4_€Đh¶›§¤Ñ麓&R}땟:°ç©MËÛéôU+Pđtñoñtvvঠ—£·äáĐxŒÂ÷f¸2&\ê‚Ï´Í0cènñÔóZpѲv¼ú´NœÙW"¨ÉG¶®xăÛw₫é‡wϳ̃?–+2¥ûO₫T…&»ß¬èg ;Ùùÿiá‡î8ƯEMƠˆ-…(–—À$%¯Å> °Ô&WE{‰¤€ƒă5ŒNƠ°vă¥pŒ_x›}°ÀÇËO¤ŒY!?4†mÆ…KÚÑÓê"R["Æ0é¸7¤b˜ Ô&Gp×Öa\yFOîƠïøíơHß°WÓ‚ƒèÔ?cÓôé @© ơ_½ơ[ư#ăïÜĐƒ¶–Z<-y‹:‹èiơđLß|¡tx^˼săØâ:è*¸ế…mxÍi]8Iơ¶pY¨=¾u_ư—̃}ë¾|¾°ù²Ól~à?ÿeè‰{4†Æ¤¿fªÿ´âŸÿùÖ¿KÛûÏ€@²“—÷pÎhæ÷l#¹Z ֨ŧ̃æ«3T«³ E‡ă“¨û>–·»p̣-àD qÆ)øe-₫¶0ô.RA:E0cƒxö™g°°ÍEO{Q?—¶è Ç ZŒÛ¡­Ù+Â3ûGUàr·¾ï½ç(bvc€Ư8€Dwf"T%"÷C?Ø|×Ó»vJ½æ¼Uđr.æ¶·bÓ™‹Đç "Ă%@o´ç\̀oËayW^­ß†ËWu`ẳ6ëÛ[ùé}Œ}ñ{?ÿ½O₫Ÿ̃Å+^¸đŒ¥?ÿϯ~¾ßüî<å±¥m/ØÂÅä́?™ö—,üYÑÿô8ÙS_”&ÿg?qäƒ×_tÄăº“V3øêFÑ>¯äâ¥Ä>~ª#ßQ*€-„#¢X2ô6µ)¼th׳_蜇̣Ø8×–°DLwÑ$₫û.§J«($C‚\öÿ±÷̃ñ–\g•èÚ{WsnÎ};u«ZÁJ–­`+ÚƒƘ4Œ=¿7d›™áÁo€ß ăaH̀đ̀€ Æ9'9I¶‚¥Vhu«Ơ9̃N¬ª½¿÷Ç̃Uµ«N›$wß6{Aù̃¾÷„:ç\ƠZ_Z_€¯=q÷ßz=6 ă™Ó3RĂ™¸T²¶ÓÖ 0,Y¬*…V}‘=rb¯¼jçĐ½ó×oøÇ?ûư¯Z bª( ̀G¢páÆÑ:ơ±8!"@ß{ßó ¸óË_₫óë7÷̉“§GÙ¦.†í%<~jµ@ÁăưeÑŸzÊÛ:¨›/C€=wèHóÁO|kñÈT>đ'Ü|́‘oן|èÁEó\<å牸hB~Ío«€øWÚù¯ñ;ààpQ4›1y‰¥B;ÔÄÏpăÖ>|ó)è™|V ^ ù3ùÇÓ çÏŸGxï›^{đăI@0ˆs0ƯŸ[ ³2?€ë@‰‚R̀4 „RÂ|íÀ)üÈ]7âe;Çđà₫Óă|*7¸Ú {,0ÎDH…óÓsl²>m7 ø6„óg ù¹Ƅ۩eăB ‚|/€Đ$"Ÿ1æÿÉ{ßơÑk¯½öêŸ{ĂwÄJ×nêÁ¬¾%ûïÿï‡Nùc?y~®Î÷?ñx«Y¯"lÖ%Ú‹ ‹"ÿ|V¢hË_¼ÜÈÖưºèß ‡ơf¬ÏØ2„­—áékÖp·¸?À6¶akä¢èW {Û9|Dø§'Ïăg^¹¥¡Í Ù³ºÙ+ÙH¨ëTN`¬†ÜcPJ­^ $½̣̀é7ûÇâÄ4j‹xËơđµư‡u~=ïkăà*̃+ß§¸A)HÉ0_oâ[ÇçpÇ7ïúÑŸü×—ÿơû½Ẹ́íe€ åJ—üŒ½0¤Û0¥ÿw̃óö¿,ñÿ{îzơÏ:4ư•/ù…o~ñÓ³gN£“'óÚÂCvbô;-=Zʵ0_ó¯å˜ü—›ù_¯rW'.VƠ›gÿÙ•ÿ¥&+Èuµ/›ÎFçq@Ù<Æđøé*~7¿ú5øÆ‡ÿ̉8Æ}*9O2C÷̀r\IZ}5çmßÖ₫”‚âJJD#RøÂ9üùƒ‡ñ?:†[7á…“g1 8ÀlƠ²k?@$BÁ†Ÿ™¢·²ïà₫=ûûÿ}h₫܉̉>€|À.\È€¼æûø\bàrơO98ư o~ư_tww¤Ùlô·Z­>…½zt™×' Ç=Ô!ÛЉø‹¶Ú.Uë°…@¾öŸÿs‘ÿ÷8Ü€Ă÷f¦ÀüqŸ[À…@©oÆ+`3̃K÷hËÛxàǘ¢î đ=0.’I€øk©¯t´Î₫~5†By¡́P„("„R‚Ç₫GÆÜbWḿM^wÆ ÙF·Jg@²ö(c i6NƠŹàÙyºç¾»/¿ë̃û6#­ÿç­ó z"€¢-{IĂ]³Q«ÍLOÎƠkƠ…6ñÚ[£"·7ÚƯüùç°SüU‹Ö¹ûJø IDAT±`ư,E©ÿ¢M®ûß ‡ơƒ@R!y'îu†F0áÚ][+ƒ_¤ÀÈ»¯Ä8‚¹ó˜«‡øí.·èN.!LK¢~fEưk©í¯µ ±é…̃¨”„Œ¤"°… ü‡?7\5‚ÁQì,Ư§đ"¸6ΘH#"©)BØ °X­²a¸fÏ®A0GÇñ×ü~n鼋)b̉\j́.Ÿz·›ḯÙû|$n“}Û&B¤ơüZôcâyóuÑÊäŸ;_ûwÑ¿ë‡&k¨¾`¹h8wÅ2^öR騿äñ¬½í2Y€N9eêpfq ^\ö₫ô'!¡w` ‰₫Ó%;®•Ä­eBkµ&û(DJo$.pèѯƒ”Ä÷"„°¢ÿ́^ƒUg`yL@AphªSó-ú±÷¼ï₫+®¿i,ưÇ»|t6ºX—EÆ;EËvê(®ĂÛµøü×¢ñ½˜Ä«9²Ÿ7Ç,€9s̀[`iê?~ÎÈ"ÿ|©Á­úuÀÁᢡí$¸!êt‡́u«*pÆĐS)éÈŸ§[;-Z®Á°„œƯ®µêÈ!đ–×̃‰ Á¹™à\{¿³µ…Xùz₫îk·R*Y×I‰H*ÈÅ)<|²WïĆ‘aY ‚́{­cˆˆ ”bw@`r¡‰ƒç«l¼عçQ0GÿùAy{`† ë˜ÿ“ÈOtÁëÔŒWäÊ—đm²_4¤>g₫ŒơuÎ|?kƯfÁù•¿nîß ‡ơơgÀ–¹*e]ë"¥·­ T¼äwK-b«Èd˱ÓÙÖ\À§«xưUĂ r/̣Ù/£§âcßæH¥¬@ºĂ~-PV¹Dô‚ I áàù:’đ̃ßưưײï”è´à¥̉w«ÍRmà³ ỵ"À®ÛçI>₫Ù̀ÇtñÇ‘ÿJÉßdpäĂ:&ơ2NL₫A¤Pö8^¹£`E¯/ EØă{ñ4€J2@}̣4º<†w̃µª{ˆ½₫5-À"óµN¬6 {Äå íΧ×GQ) ó'ƒđư×n„ô{²#Œ¥b` •Ư  B“ 8¿ Iº÷Ê%KÄ"ÀöD¿€6 Ø! ï̃¯å¢ư¹%¢ü¥È¶ ê_( ₫¢‰ƒ('Xñ;àà°¾1] D„²`K ÚAέe@ €/¦“¾-  tTKǼæĂOO£¯́Áóú\DJñY®uÑÎZ£²ÊÉפP7Ö[!₫ô¡³Ø5̉…k6ö&SqC ZsöÂÎH³&8h,à §¼éï½e ĐiMđÅ D`ÖsѾ‘¯(º/Jówệ/÷·#ÿ(G₫̉:ï‹e«́à€ƒĂ ®´Lwدæ*5U á•Jđ{ú2%€L ¾CÁ₫~)W”d öT*…‡?‡-›ÆqÍu×A*i2¦¯y °P´¬¶‰0ÎÈ4ä…R"Œ$‚ Àß|Ư>Ç+v "ËØ̣Sˆ³«LqădüÜJ£ß9µ€jK̉o₫ƯƯm¿= `g<´7^ls ¢†@[T-0»‚¨6G₫E5~»Ñ¯‰¥gưe.̣wäĂúå₫|¬E¹ï-.Ë́ûáæ̉¦CD–6²ÎO´RÖÈ®5ZgR„ǽ$ú|àû÷A1Á9¼X$ @O¬6º_…đr÷OÖ“5Iœ>q ÿë¡èEw·n‰€™¨X¥/@æ3¤¬+`( ªYÅÇŸb7mí¥Ÿư÷ïµ¹VơØÍ€EtÁÿF—v,*Ø=³(®çÏ#;h“}­ Úoåˆ?ßñG₫N8\Z*€rÄ˵“c0£€%_Op°ä?/VJ₫´Ä *J#[˜oI|ôÙY lØŒÁñ­º›ˆ#iÛp¥„'ÿ5ơ˜›ÉxM°”h6x̣±o£«\¾ÍPЦJ‚ÆåÆxÁv}0½[b©´:xvăï|Û\cî̃ S3àÅèÈ/ï‰I·“;`¾píiư˜ômâ·Iß&üøˆrÄŸ_̣CI$98àà°Æ?XÎÊË]´l3 B+RđCÙ÷4±Æś…÷]̃½“HˆGÛâZº¨@*œ™¯£op=Cf+ ‡–«̃jtȬ% Ü?i¤Œ'@I¨(ÄáSçđôé9ܲk ]eßO&{±ËùçO˜2éĐ²ƠÀñÙ&ön,ÿà»̃{' dËyÀ ²³)°hYO,̣SùñÀjÙçóÄo§ù—#~çóïà€Ă¥…3“3Ÿđ…µô¯ˆÆí=€¡$”=¡WèÏ(tº:²åÂ&‹̀ô$€î¬—Q„ếöú¸yÏ0¯¢GÍ4ă†¯¬i€µàEgbS "(©{àPJÔ«ÙMœÁ­Ûz±c|Œ‹ö%A Ähiµ‹â ñzâP)H"|öà,ơtw•îyàơW#[°í;-ºXGB È%°“¯Å{:¾̃/rơsÄïà€Ă¥SÓ§Cu%ÜÓ‹$íX̣xB<ܶó%Ậódvá´­ q×3k‚IáÔt'$ƺÀ…€g,·Ư ‘Y´¦hz•÷Íœ;K3±ˆ"‰(Rơ|íÉçqbAbûp<–)¸]²XăyÇ_“^©3禦ÙÉ&^}寮ÑƯ×î@{  Èh½́(ê Èoö³—üØ®Mëçy H¿h–Ÿ:œƒƒ—à,_Å?–ÄÇ—>.gI-#*('Ú®úñ4€åpv¾‰GNa×Wc`d`H2É~‚”•×LǘE.ÈZ¬I½&Xáđ ‡qäØ1́íÖ˘@™‰ ]¼Z7Ă$s’4*„‘BFxèèöî̃5úî_ùơÍÇY±Ù‘@n]×ø >̉ • È—¢1`}˜‹đíĂ~œ|¤¯ñ;8àđ½Ü6Z»¿øZ׌ú+×oî…R”ˆ€Xd Ë_1m6Qù,@B₫Ù÷(hb~fwïêĂ¾M}`̀Z d&(±^ùơÚ&[¥Tr¬&`?F2Â2k‚ơ) ªÎà¯<€]Celܰ!0Éñ"™’¤iŒabz‡§ZxƯí7nƯqƯ­;ơXnKàzÈØûD@ØáÈ7̣ÉÄo›ù=¯ƒƒ—>ù×ê¢ ½% ™?dbq+‰DÔù̃´$Ơ˜eëæŒ(í X¡)º̉&–ÀÆH0àñÓ‹8>apóeđËeM‚åvÄ3ùjU5|{ràÅd¬`&´@)(Æq́¹§051û¯"±4Ï=߇°’óN6)‚é̃ ‹üĂH¢Jœ˜©̉5×\9₫#?üĂ» Ùç›KÀzɨ‚L€MæªàçEé}Z‚äá;8àđ½‰̃₫ÿwü̃'»}v*R„Ñ^C]¸é¾gÄ:\} =q!D† ‹Rø« Y¶ `̉˜©‡˜\lಫ¯CWW7„àLh?äv° ÏWv@ —8Oׇ‹³xáüQ ±ĐŒ0Üíc¸Û‡/L&€rƯđ†L¼r^©’#ªö’»-Vs¥ÍºÏèsÑdêơ:®ïBïÀ N¡s–±)¾Xä߉•2Í€¦!Đó8₫×ƒÏ¢Ú đĂ×A*•® ÎeVëHhs̉‘@=pf1ÀÓMÜôªûö]uÓmăÈ6æí,€ưѬ7!°ĂÁÁ ‡Óó-("LVL×Ct—8ÆûJè7c~HÚ)!VΙY¹»/û%"úåØÂ¾:³N¿'@‘̉¨…§OÎàaƒƒĂđ¸ĐY®G_’ÔưK˜Đ™ =;*b˜~á)|âéó¸rC·^̀²»ø]ălMºO!-T>9M{÷́èÿ¾7¼q7~7€®ˆ€|€¹ÿ‚œp¸DÁÀ0ÚăŒa®b²B*`¤ÇGE˜K|JËD@+T¨ø*¾ÆÍ^{ÀZh³T4_œ]Yâ&@%k‚=Áđơ£³85`Û̃}0}Ü¥[?ïsRΈ7LZøĐç¾)®Ư6)•Ơo‘,­y”ÑlS´›•’8t~‘M̀µđ–Ÿú™Û·lß1`?(Z̀Q¼*ØÁÁÁ ‡K ºĐˆÊ €Çơf VD˜®‡h„ ĂƯ>ú*"ÙWCLt÷¿'8„½‹Çï¸5 ß’ÇrDŸùß¡M¤óíĂẦ jµ̃÷º«P BÆ’Á°üÖC) ™Í'2}$8f>Á ?uóFD¥~ÓmÇ âÑKmh°¦5Á¯ ¶¥jơk5ºyLj÷¯̣̃3û¸đ́½E‘ûˆœpppÀáR$₫Ox₫?qĐ 6₫GRaº¢)Œv—ĐWfNß») T< vyàœĂă ‚[#lÜj d œóÔ™Ï XỊ.xqU[Z»J‚đÏOMºÇw@0˜@®{ÿ"’¾&kÄ0îà*Âï~á8†º}¼b× "Ef³aº&˜¯y.P¿ï±›¢2"PضʡÂưëwƯƠƠƯÓ́‚ |C  è”àqppÀÁá‹"Ù *^ºq‡1DRáÜB Pb¬·„ËǺQöô 2œêqO0]7søÂ–à,!c[Ä„˜!ÿÄ:—–ˆ³[öđüTµ@âæWƯgJÂ4̣¤?ÁÀóÇJ¢ö{¿|/€RdJ¡Œ@`xø+_¼ùº $%eÎ́²È̉¦@Ë_lD¤§èOÖ0Y °u°¾ïÛÄoǵi€ø#ë´.ØÁÁ ‡K]Ư½å_ùÁ;>çq6Ï2QjLœgLTD°k¸‚₫_0T|_øB[—<ßăđEĐ€¥3î–°³D¦L>[ïĐ 9=_…” CÜ/éç²J©‡+<–ô’ÜĐN…)Ûk‚"EhMÀo}̣ ºÊ>zú5ËZÍ€ú5P&«'~¾N˜RËÂ&<<…+†=üÜ{ÿà6¤}ö`»øœp¸ѨW‹­ˆÅ]ÿdoÿ3‘|58·ØB ¶”ĐUâị̂°s¸!JÈ~rpøB÷ xœÏ₫Ôé.Ò±ùM±‹©ÓD±Ǽ¦:ƒcSUüü+6Ẫ Á {8Œq˰¨ư±WRW_«)P›`°ú!Y‘„Ă³spïåÉ%ơ?²N‹yÛbûH3yZ–Ñ₫iG‡'O×qj®Iïú¹Ÿ¾±wxC¾Đ.Ø}n"ÀÁÁ ‡K Tôï£3MƯYÏÚ·ù4áÜB€@Fºơ [Q*C‚/tV ́{¨øe_ ́ ”„€/tfÀña2"Ö&<+S“h6º×́ê¯e_௾}`hĂæ$ĂÀ3Y‡8în̉—#đN)ơ¥„CÑưâç²ËR©d$0’ơ™óø«‡Oâ¾+ÇĐ×Û %ă•<äYQ¤ é pa,ÉÆ$½<àđT ›cÛ{₫ƯûË×’ÏÚ"À̃àHßÁÁ ‡KT 4#ƠE&Z´‘ ïC¨Î.´°ĐŒ×nÁ›^¾?~Ç•Cÿđ")!CÉl ,ùe_è¯0¥ưƠ7‚Àf†ßƯÅ̀8cÆÈ:}"€3#§Î‚đî7̃0¬½q¢P™ƠŒ÷bư°5,²Ơ™:¼RÙ,@(&NÁp—‡;÷ŒB2_:Ïn ä,íæ}â F\él‹Î¾°Dœ%¥Ó̀Fó0HEôßß^}cetvä'₫ÅĂsoĂ¥ˆ£§'ÿü–íÿ®Ë^ ĂÂëyü“@¦j!º|F(qͶx رqA¤pfz >ñ́4NÍ51?;ŸŒBèå4`ɾzRdºúÓYu€™¶q®H¹è‚ƒ5ñ©Óø¾+†À{†Áó‰!g Œ©e#öạ̊́%€•”ˆH/'̉wĐ/Ƭ ¦x>?qŒpîÈA<~₫\1̃‡¯TJˆZD€ L¿?d}(º10-§¤ÂI‹£øßÜ¿R„cÀ={±}¸½e‚36̉%äöë_¹ûÄ“=â2€t±Gû̉'.!ˆ‰é™ç(¾Û>m¬›ÈǸÖñ±o‚ôºĐƯÛ‹]Ă]¸{÷\·}¡$€$₫̣á382ÛÄ™GuÊ^̣c<ñÈ×óñH¾W*ư^‹f%đÓTẁ:àøÚ sxàÊ\÷Ê»±ÿ‹ÿÔÖhóS¾Ù1™_:ºïT X É”C§Œy")!¥Ä̀ô¾̣đ£xÛknÅ`E`ªEŒ¸ỶDÖĂYå”ô­LI~"Iđû†pßåC¸{ÏưD ‚tÀ­’Û¦¦L ,Ó;Á9O\ ¬̉‹›w ăG_¶%Sb™oFø?ß9ó‹DPƒÇ$¶mÜ€·ö±û®Û5xă}oÜ÷ø>²Ú¸a €iC DûV='Ö9ù3đ<¿ü®ï»éÿ¼”ÿs¸Ëógêá’䟉¢Y:ÎFÍ0BĐlaö™ư {\btËÀïÂï½î2ø‚ă¿üÀ0Æplv/>̣ÔNÎÖQ:ƒ Œ´M­1Êñ́Àœ ˆ#®ûÇä7ú ÎÎcÀû^{9̃üĐfxóç <!<¥ i 0®VOS ™7ƒ­²ä]$â¾`ºW!uK$̀MOâđsÏâΛ¯ÇwœÇ̀b œóD$Ø ½`æ½đƒđKØ:>‚7_7†Íư%H#z>ôÄy|ëø<<€æb̉—QñÎ.´L61¿T.ç¢ÿ%|#â^å²N8\‚B B€u\3̃ Ϫ‡w"~¥gpÆ !” A$Ñ$ÂH7·éê<Çäéăcø‰?>€ÊĐFlÀ+wôăµWâg_± %ÁQ{ñ‡Î"”„s³ó¨ÍL`®)!#' íP”‚ëFBà~ë ~èêAtuWÔJ ¥‰A²´·`u­û³‚ß³åÔ³´D,#¬‘=!„¹¢&f¦°cÀẴ­đøáS)“!± ‘LßqÅă…'î̃3„6÷¢êÏä3ÏNà³§ÑŒT›` ‘M)Cú@I¿¯Ô?Đ_ùßüơ[ßø©=g"~»p¹5Áüœpp¸ÔÀË ÊuN("a°â¡$´k`é£E2uà̀D§œ#?Óóçđw‡ ~¨}Ă#ẹ́đûFđ†}#à ØÔ·ƠđJüÓ₫)4gqäÜ4¦kaÙjÂ÷¸!Ô¬ă àÀ₫cxû­›qïí¯Àg>zå’¥ôr R)©Â=KEëqÔÏâi{LÑ4åµụ̈é€8…/âñH3½P̣<|ûø,n;½€»ö âØ™ó¨6CH#$đ°u´=]]¸rC7nßÙj 1±ØÂC/LâÓÏÍàÄÄ,<@$ÓZ°¸"H¥.8CÀ<ܲwûàë~üû>ơ7xYkà83ĐB¶  rù'œppXQOµ"UfŒçŒE:ßĐº̀+ Ù0)…Pê @¤ôÊ^̉Æ4®ÂfŒ#j,bî̀"æĂï<„‘ñÍđÇ[nÜQéÁ+vôáÑ1LÖ%œ«aªÚÀấ <2 Ñh@ ÔCfôM4ç1ƯøkÆđùÏôÀW¡nºç!8g¦Ä “:@ñÿ[oMơë×Ë’­‡Üü»½°d¯€±àƠ“©µ/™q>΀æÔi<ùÜ øÉ{o@wWuɱ¹¿Î9.BEà¶ưhI³çkøÚ¡søæ±y:_…jÖ´;#cPŒ#T”ôSÄÙΔٜ Vmçĺ+ÑøØp×üÀëv~êo>đtöđNÄæ@äÈßÁ ‡KKđ3Óó{Ă–¾·V?£óÑ øÜÁi¼jǶí¾SÇ$‹t<ÁÍy‰̀@r°´¼`ÿ>ö͉1ER7ß™`×&ưf$;¾Í~ÿ˜ypSÇg J)”‡7Âó}ƒ{xÙ‡ïs<5áôB€×́Û„H›J¨x}eGNUñ±'ÏàØä"MƠѨUµ‰˜ôU2^IĐÍ–±(Æi0b‘ùưsuĺ+1`ËØ`7Ê=ChƠ"d·ú¹,·Èßơ88ààp ‘?S3[ßÊ:ÚRaÏHƒ]'L}^YB@RÚ®ÅB:¯ºôi§:Æ•‰€9Âúf„¯OÜ;‡J¹„¾‡ËFº±qûNlë/áU—oÀËwa¶¡^¯ăógpj¾…¹zˆR¹Œ̃₫Àtç<#Ô£‘$()u¾ ¯oÜ/'‘y<1H¤à÷Bt÷›qAưj|ÏĂÎÍ µ¥ư=Áđ‹wlE+R…ov_o_{™…¥î>0Îs]ư@É÷1ÜåaK OŸ«á́BˆgÎÎca~ÇçZ˜¯5¡d¤û18C¤ÈŒV*ó5&}-8”%̃´!"¥…œ"x&Krf!À¾ñơă?û½ó§8‡Ô  ¤Í€q ?èàà€ƒĂ:&ÿ„»~÷×̃ó?ưÈ—₫d âa¾¥¶–”½¬Çü̉eÙă y¬œ—Ư$Ëc!»ú©ôûtn]§À9c`Æ´†1D2@«Î0=;̉É”=Ï ơcptçáƯwlÁÛÇĐ´ÙOwIàMw^ÏŒƒˆ°Øđ˯̃njáÙ%:åR BđÊ"pÏ"—ù`(•¼ÂÚPZ"ṃG‡`<óÎđÂéSˆ¤Ô]ü‚¡,8ºJ¢ê~âö½Øµq§<ñüIÔC…V" Œ$ÂÈx $ N÷?K¸%¦AJOX$¶ÄD8·Ø˜oFtÍÆ¾oÛ†.+âïTÈgœpp¸DDàÈ£_^t=“"Oöÿ¦·Î{¿êyúEöú̃ܶB²ê–1@^vÆơ\<ç LÆÂ@C̀ºËf-ÆPk´àMLĂï9x=#±it×oîĂƯ»qçå£xƠå£mJ'ÿóÄ$M5`úäL€öà?3=éùZ¶®ÏƠª¡5qŒkqüÉZ¸ ˆ̉¬!5³ Ü4v•Kèî*h̃´ đÚ½Cxa²êù m1™–0"„J%Ó2®÷ƒ²½ÖGJ&Ë ³6* gæ[ñ¾V€½×Ư¸uxă¶‘™s'KÄ_›H'¢\À•œppXç°/̉tp²ËGºàñÜ( k¿yÆSŸÇư©AM›ˆ TO»èÅ´O?•ÛpÆÀ’ƸÄ̉–sp®àI)¤R'Π:u§WĐ]¾¶đ'Ÿx²6‡@ÎÓ[÷”JÇèÈlÚ³h9µ¦”0Éîm3vÀ¦VÂÀrêbùUÁơeÎ¥ Á:÷%DđWnÁ¯ÿĂ¹$£eJ.ÊyŒV%÷t0ÎÇPư IDATF‰#±RÚuQf¬˜F pn®A÷¿æ¾Ëî¹ÿ5Ï₫ă_p Ùiß:¸^'.Ư RÆ̉%£ `¥đÁ¦¿ÖZ €Rï8Ÿ´–öÀ*´ë ƲDH¹̀@P´§€yQmÍóÇ Z54ƒ(iˆÓKxâ=:E?&[óöÖ¨ ­Ïâîÿø9Èú˜Iÿ„B7,F ø‹‡Nâ·oÇ«®Ù‰Ï}çˆå `"y…äg©aË́O"BÆB9~uºT´ª³¶ƒ1 HÖ'€üÑ·^ó¥Ï~êø̀ÄÙÚ'̣%ç àà€ƒĂ%@ü,÷oo†à¬›JgÍHån”^Óc¿fºÉ8cæêŸ̀QcvÀËÚ¢âxa‹Í~̀}C"8Ó®$7÷µÔJ+R¨…JÂG2”¢ùª¤J÷ X„n ø1ăߢÂ~9UÅ–øåÄc Rñ¤¡Ï!ÊƯ(W*øđÓSxîÙgp|ß8î¿b_=<ÅÙé,³#ûOb¬íÈzÿu¥ĂZJdÄC+"́.ă;§«XlFtÿkï̃¹yóæ¾™‰³sÈÖÿ}tv„Ë8üKƒ[́p©ÀZAđæ‰Îl,÷Çûè3èñx¶"«Ǜ^²e™ơ¸‰0c‹;Ơ#ă<J½F7v! ¤DIÔ[gæ]}P~‚0DJ4ƒA¡„h!ZA„Ṿ5J₫!‚02÷Ó¿"s„‘~®e0Ô·múç!Â0Dh7Œô:àȼ&)D‘DF "ÁUgñ_>₫(ÎV%î¾|MV/EΜˆ™ÅË|êiô¯EN$<[…Ï"½ơ‘•°cÏĂ`̀ï°íl€ƒƒ—Êßïääô‡“€’ ÂV‹ô¥é:杖ôŒ?O©Ÿ}'̣·ÿ’™~”xS_*L—»J»̃ă#ñ PºM‘̃O H“­!Ư0CèíGEÆÔÈs¤EÚè(ZÉ¡”ñC(₫}²₫×iºđ•”‰©R|Ûx;b¤ÍsGđ±Çàû®̃€[/C$•^ùËÓm€ŒaåAw\æ ]B ¨¶â÷8½ĐBÀÿư›¿}gWWw7§l`ǜư'åà€ƒĂú₫ ;ơüÓŸ€nŸ#1̀µëÖ°̣̉¦‰¬́{œ§V¹íçIê?Kôí?Ï߯ÎdÅ@<¦#×dôÍX<§ÉUAJs˜(7´¢V ̉³}(¥LBA*•ÔáödOH(s₫Öܾ¢tŒ/’*Ù–Dú|_8ôL…¸u÷(ürœA7E&&K©`„LC#2 ˆ”|đ i¶¥HÎP̣Ih†ƯsöD.vôÏppÀÁá|æNĐS a°Â+¸=ÏógâÖ™ü3³„h¿­yÅlRQÚÔfno”I)!&răTh–£a1q¯üÈ,íéx¤Ï‡̀Ï•₫·"³I¿¶0’C‰Ù¹y|åɃ¸aën»j;$÷t“$GⲘ~bfĂ`Û‚§´ï!~¯cñ1]QözJB/gZ¼ámïØ‹´îoq?@œ àđœpp¸Äˆ.vl¶©ươY6‰̀–¸ªs° ‘Û5h;ƠÏ–¡…4…S'´´rÉÜO–9NBÔñH ¥ÆEjrÇ È?¹ c™#>I²<ù‹NXŸ›„7¸ ¢Ü FZQ„ ƠÄ“ă±³ ܲ}£=%0ÄY;c’¦k2çÏXÎê8=¤)¥0°D€¯%á·ÿăïßk¢ü•ñe₫lœppXÑ¿₫¾’*æ–F‰¹ĐŸ1m;D„ÍưeøÆ ù¬éœz–üéBô’·)™öƒu8Únƒ́\\₫₫Ek—3Ó Îđôéy³jY÷œ;s?ú(öwc÷¶M`ÂK7#Æe˜†L"«¯ÂHJ;É(!ƠY0l(A)B3Ô —ûÆ{đ¶÷¼ïFKØÆ@E€…~QN88¬#âÿ]m41["Áó[²Œ1–Iós›­p¿ST¿R^ª$°ß̀Ơ₫¾=ëA‰àQƯ„I¡øø₫³øä3¸c× ºK¦ À“KÙÉ*ÜR¨”>1eL…⾉̀E3›m½ưÿí«̀u®Œt7€_`(îp"ÀÁ ‡ơˆg÷?Ñ›™₫ƒÇWv­VfÙOÎ /µÛd₫’ u2aΖIS0l™7 -J·̃c=̣¨ÇC)¡æÎàC_z{=¼₫æËơb%Ë:Ù*Aǵ“Jz)HÛ×…§Ï×Qñ¸ÙàL×4BÉ6÷ QDçưËeœ€ƒë0€¥Jw7„ưœ¾½€î kÆ›ûÊ( nRÛV¨g}ÿbE@üxmÍ́´:ZÉg#:66.÷FeÆ'́çG3‡©¿S‡SǸ‰XîqM”d" †ó§OàÁ§qïîlÛ0.Ä·ú1{æ6‘AVßA¤’i 81×Âî±₫ÿüño7׺¼đĐ̃ ÀµŒpppÀÁa½‘?:sü¨”µ¹o@Éă–U-µ¥" T z<”}̣ K­}‘”è%X‚H—{±™#r¬¤Ó?GäGÖVs_áựÏ—ˆ…ö“LjøH}û¥R‰# 4đ÷_ ÂÏÜy9d©WwßY[“LåËñ”1­„[á́B Ư%²'’Ï­H€q₫–7Ü¿Ë<€½¨SÀM88ààp)`afRxáĐ©z¨—ä°xĐ®½ ¨Ă‹1Ö± đ¥­ß³Ku––ñMÈ„ƠmD,K₫ökϺíÛµ5v¸̃W£”T̉¹Ï¤HIcR¤ Á°pæü̃çcÛ@ ×nƒRñÅt,ñZ*£‘nl†Jo´AÖ…éz„á¿́êm&Ú·Éßî°³ñµ‘œppÀÁag"^â@a%-)ƯÛ…ùïơ{Q¤¼T& ̃ÀÀ ›àĐ;vù/›¡Xùm;Ư?=s…M#ưèíéBṣ„ñ.P‰±Q́d¨”Ä7¾̣%Àϼ|¢Ê 8ô–C]ĂkùZе‹€t)’2~–d’ÅED85×DÿÀ`Ïïü§÷¿Â¼å¶)íP”päïà€ƒĂ:#}û+<ÏS¹2q{LÏốÿ\3”úFÀu¡{±—ûN볲Ü:›és²'Ö#XÛ4E¼P€3’ả­{öK©»bŸüØư8†»}¼b×°¶æúµ ––Ṿ>K!¨- âs uùÉ`¨…’<Îp×W]ợWï2‘₫R#N88ààp©‚Ùz€ùFOd'”a¨Äï[â 6̀>€µ^ñm²·NưvnYJ…©¹EŒ öb¤¿(M«çw=€Øg¡h¥R¦7vÆ‘̉¥I˜?sïÿêI¼ư¶­Ø´iD€ \0SH³‰ µ?6ˆ0Ykáø\ =%½gÀÚ„̀ÎWCø‚óR©~ÅqÀn\j$ĐÁÁ ‡ơ” øüg?s®U_ü±±LBP „Ó+:ËE¯|É4ør€öØ_G¢Är÷§dáb“?­¢ëq©M±e/g)IÂ#>’àø…;wUúÀˆt)ÀôđdÉRöCϘ)ƯpÈ́́€uÛs -Ú²mKÿ»é—®Av-°È‹7àà€ƒĂz&´¸0/ÔÂ]WnDww7(C₫ñW"{7A: HD¨&ªúʱ#$!¾K3ˆhïέư÷¿úöq,Ưàå¢'œppX§Y€óuåW©G "ùd² ©'€¶¢e`¦`=\æu¯‚Ơ“`u(̣räŸùûŒưå$° 2–/Ep˶>x‚ÅăÛ‹Ü&A•6F¢HḅÜüá?¾ïám#ˆ˜ÈdXÎ!ĐÎÎÄÙ…P‘‚'ôùgÖÂD&«!€í[·ô3¿̉‡v?€¸ _\/€ƒëø3XhƠ­QÀ¢1;fH*R„ñ̃8ă†Ø(;x±@üU @Î 03Ë¿¢ŒkËƯw éHßÛ _¥ŒM°̉6Áaˆ£/ÄSGÎà¯Ú‰ËF{ Đ!Đ~Ơ ±ă`ˆ°ƠÀ@ÅCʼnÉQŒZ 1Q q÷÷½á»_óÀ&dËùfÀ¢ưüœppX‚`!P¼Jøœ/µ3,óBÅç`Ö<¶âz»ĂÚ„c Eº •Bê^€ ^Ă?ˆsU…=[7ÂóD²-Đv d,k«H¦ç@)H©/jÜj4íR— hçH¯Ø<Ôg›•Pl Ä 2N88¬³LÿÊW¿₫” ŸñgÜjk¯]·÷,‘X¸€ÿ¥Ë1+MĽJio€0’•6’Râùc'pàØ)¼íæMØ´q8×vÍ©)ñH@v°2ŸóÑ™&¦ëº=Ënèû̀7%#·̃óÀ₫Á̃\ ? àÁ•œppX÷"€Â0T¢%÷¸YË~ô. «¶̀€uÓ°ºÀz](€åΕŒ‹K3ÊôHÓIU›Ă‡zgCܽw‚s3¨ÍC¡k¡îĐë•™RÈè₫‡ZKb¦̉½íÇ®̃{åUƒh·¶³K9:àà€ƒĂ:ÉP½^¨ÙÑ\ªIxùÖ>x¹l@>'¢ øBG/­TÓ¶‡j‰×jˆZ%½¡TPŒăà“âÙNàƯÛ˜L$Y ߌGơ$0Û1׈Đíód„Q¿‰ú¾’P²aøéóË7ù¥rưWP<˜/8âwpÀÁa=‰.ûÛÿü›§úxđM_0”K 5»J‘RÉïX²Ø|%X?¿ø×zv Ñ ÁëîCoÿ₫₫™9̀Ô‚ÂLLjákú‡@‰0”¨ø~ÿ“ûñÄé¼ñÚQ¿ ÎRçFnMHħLC`½¥Đ¥6ƒwÄŸ¶™ú˜¬…"E?ôĂoºÂóD§^€¼!àJN88¬?() ›©+/”[î97Àü&¼Ø€ˆ]ĐZA”©e∼âupÙ èR@¼# đÉĂø£O?WlïÇoÙƒ–!uƯ ˆt[ ơ+³`¨x©3™º™̣O-˜mD¬›—_{Ó̉À¢ €p'Ö ßäiå\5¤Z sat₫Ÿ ‹ÎOûƯ½É’ Æ.LÄ”2«é’̀°e„KFÀP{K™U¾*³'@Bq³‡ŸÅçÍâuW`ÛÆRà¦'€%ú ô b†( AQˆÑ?Y L¹ÏNÍ·0à¿ư‡r7RS ¥mS ư;8àà°̃A-T~ 3TÈ&•ܵđJ]0“€Ià»uiu¶--!g.n€^ä[AyÁc‡ë#Ë ]Fa¤@Aÿ߼핻Ṇ̃z Œq“^”_ó@€pxr½Z˜ ? )„RÑëo¿ǹ\ËXÚ¸H8!àà€ƒĂ:ɈGŸ|ö+$Ăư%³ü¯›Êr„a/6Éăˆ!T´î̃اÈ̃ÚGÆ X“3ec̀–¿t"@êR@$)`æØüûÏÇ̃ Ư¸zó¤R©7O€íù³Ø”hE eẁ<("œ]˜à®xËÈZçứR€#}'Ö#G-Tk jjëÛ,KQ;Gg›Ùö~ù€k’e„ú́ö•ñªËJ…‹éI€eBÜX,u3Ñî₫´YÆ!P±À(̉B "øÆçàs†7^¿²Ô›5BZ&QÉ`zâÊêë X ¾ßÙÅD„?xÿƯkÎ8Ÿ(£}ÀM88àà°î₫9ÿùßüđƯ\=ÑíóÔ0f B́M×[}ßí+{¼¶6C’æ+_Ç´²ôX$ÁïEep Ï. Ê4úïPO ¤$@ÉT@¤L Ô™€j£_üàqÙX/®ƯÔE:½/8ƒ<}XĂư“µơ@¡·$̀‚˜ –n-l† ’€· yoø©w]o®…ù½ù øœppXoܤ”ÎÊæ*Œ>[Æ26) $k/đ¥Ôí_T[avøOq}?ׂGv.²?6c̉ˆï 0OŸ8O=;‰·¾rF‡A°­Ó́ ˜oH4#…./!Ê)A‚6‚:6Ó„øùwỵ̈íV ‚l€m  WppÀÁáb₫‡¦ê¤wtNëÛ$¯¾sÿÙ₫¸b±̣Ư¢˜—Bsd̃3VĐå¿FC₫ék̀÷ÑQ̣~(EÆ0µz=ù4¶ö—pÿµÛàù%pFVöƼƒ¤Ë) ©`­….ÎÂLÖRaS¯Gú5v*8àà€ƒĂzç`0Mb¹ksñKÓh×_ñ̉Ô?.œ0~ßù‰¿§´́&ÀƠˆÆÀ(]©lW5’²Ë¿Yg â‰i•dâÙC‡ññÇáƠ»‡°e´Äx̉ ­ơăE­ " uyÚ ·nC”pz>À¾íº̃ó;ï¿Å|^ØÛppÀÁa½€Z J¡"Î’0oø)M4#Ư~Âú*ÀÖÙÆ^ª×´„µâ[YL&„̉©€(½ê‹ ǿ·ŸA#nºlç¦ `5hŒÎ ÓMôWJ^j@‹¨•Ë%{̉‘À²{̣½Üºv’ûOÏÁ ‡‹qàèÉOCÉs~<n§¦Ýü—$³#€Éy‡̣ê D)/æƠf&u= Eà\´/́Yöù˜å`&’^€àù#Çñ§ŸùnÚÚ›7hOÆô4‡•‘8· ”ÏœÓRù–z ÙbKal°·<°qÇFCöywt¶ÀN88¬£`–°sÓçPkO/°–,W9›ÜØ8aêœÆXÁÏÖ â&<a¤¿#½hNŸ†ÂŸ;Ë• T²'€eAA¤ ÂzâÔkUüÚkö$Ûc!ÀLß¿0#‚ –¤¬$sî’€SóMlÛ±kôß₫æo]g₫42v€› ppÀÁa‰ï·̣KœNöW¼L”o#’ $¼fïđ²øä¼ÅŒ` BpÁA2\’úÍÆ̃œè̉¾q¾>Ó I}( œŸÀ¿~‘$lß¶ Êd#c˜¬µ*…_ho€\"Öƒ±0¨’º|{oùÖíW^¿í¦@¶'€M₫îúéà€ƒĂE&₫̀÷´LàI|¶Ô`Ư×Nê%ë1Äd¹é – ‡‹ÏXaé÷Đi&@!R ŒF”"<¶ÿ)œŸ«â×ïÙ` ̀ZêÄ0]‹JÂP·—Œ¶9-SÚ»JÅæ ¾àÂ÷½8̣¯ ]́¡³'€+88àà°àésu %Áç ùqt¶t0[@HÅë*ƒäḰẈZ‹Ê&vMuâ(é² i#EƠI¼ă¯¿ ©\9‚Üø9˜÷̀²'Át Óú–D˜Xl̉ ×ï{ëOüän¤)ÿ¢ ÀRûœppÀÁáḄO^("Ï„xzúÜ $!©I‚{¥¤1°Ó>€•’¹-h™¥> ‡.¥ª2c™ˆ_Kßåz(–²Tfc„̉dbo€€8‚£aÿ™Eü««GÑ;8R̉Öó·•2 ZxßúÛq`²‰¼n ä•“~Á9Î.I m°‚2!Ú¿€¡*LVºíú+G^vÍƠƒ¹ @§ ®àà€ƒĂ:đ:đügaa ":ØÂ2 fÏ<·̉ÈIm{ €́ÅA¶X̣?ÄxyJ;ÈêX·kÙ™Ă<-q("!ib,Yœ“¿¹³‚çZêm— ¸b¬ }hUç ”LHb`Ê€ø}¶Ÿ¿}ßéEAñ®€Ø!Phâ0₫âKOă¶]C¸ÿºhÁÓŸ-g8:ƯÁç|)傸ÿ"E¨‡Ev^yí¿\éÉẹ#v# #}'.2ù*—K%XIplê/'ÎöÅ?I^Sª X² ˜̀×’ H#ƯÔ¬¦èv眩*}`~9ûª,ÖLˆ<'–:̣oqÛ·)¼î~‰¡ö†Tv¤ưĂIrÔn¼”!q v¤x"@"©FR1œ8ô4¾q²Ûw aĂ`¤R`Œa¡¥½ÊO3 ñç ư<ŒHÿ€*6÷—àØ´uÇP¥«§‚â2€½"8¿À '.ªà"á›.Ÿ£¿́Áv¤åŒ¡éu°¿'ùY>îÑ¿=ÑôHaº@ø%0Η ¹ó9gư<¬đh |ó‘¾¹]'á`?µÛö}W?Hûôu‚”‘”ÂThÔªøôCû1Üíá¶Ưcˆx Àd5´%°ư^Y©ÿ¸‡¡$8öwĂÜ\%W¤¼ñÇÑ ]‹₫|œpp¸`Yƈ1`±¥ĂFz|”=–n…³.ÏÛÉ.€œ)Íqœ¯½$v ¾'#›ï.:5è-%VưÅ¡ÿ‹₫Xă^€(2£aˆ0Œpà¹øà#çqͦ~Œ÷W’̣ }’sJ<ơg̀đÛ:XF+"j˜QEb9Â/Z”wt¤ïà€ƒĂE"~‹¨ỵï³ -xœa¬§Ï[÷àà‰›\Ñö=ÆI¼ă‰Pû±ûO|«PHqÚŸséH‚ẽW‚$…(TÚĐ)’hƠđ¯}ÇæÜtÙ8Hø¦‰0mi´¯i©Å;†Êëñqr¾…F(ơ³)%@ä¡Ư0? `OØß»,€ƒŒ‹ä *ÂL=‚ÇzÊ" Ơ‘f˜Ă•äZ^½Ù²dV˜̉·ǘ#/¾ÅcL—.–}iw¿~ÿXÇ E{ÿ…Î"H¥-‚Ă(B)̀ÎÍaÿÁpç®\1̃‹°>F(±{¸’˜₫pkë#ă zËï+ăØLÓµ×"¡Ù¨K)¥°ˆ¾Ó^€¼1ƒƒ+ú’>¹$Ûß%©0Üå£â‰\ŸÀ™N'?gȤÂÛÆăXq§Ñïó$–]‚˾7ļTA©Pd!íÇ[;½7E" VÔdˆ ‰ £4 µøæ3Gñ̀¹*®̃¾ƯƯ]xüÔ"@ÅçéÖGgï-a×p Ísœ1ô”´p|ø‹ŸlÖâú~ĐîpÑ¿ƒS 0Ö₫g] Æût?@|…– :ưÏÍR0#ḷ±GƠ¨Ä–s d+ªg+|‘KuôMÅă|+ Q¿ Ÿ_=ÑÀ‰¹f›•B,¬:eIÊ&^½"“ …Pj)ẤÔ¾sø4®ë–Ñ!x¦©@&D'pΰ±¯„C,¶"j$û"â§ơ|ßđ;ù9̣wpÀÁá¢ưQ[=1I˜iDđ8Ç@Å3¤C¸fcÁ™öàœk xÜ`7DZQ̉#Ú•‚»B–Q,]c9¶é4g¾_Áư2G2Ak´¼}Á’Æ»µ¼îv1¿×ùơ–P ‘$@xđѧpzz¯ºl0Yä ®Ecï+aû`óÍÇg@ÛÎh€ˆ¸Eđ¾%́)€¥,á2N88\ØèŸ:EÛ *̀7# T¤«>盀8‚]₫V(†˜é̀Ô–4ï ‰Ÿ¥ öûŸÉb(( 3ø»GO¢·́áÚM½€₫²NíÛär®©í ‹?,f‘»½(Äá2N88\<$^!„ßé—ơPBaÛ`EïŒWÏăđGÉă( ’'à{%Áá ‘ƒ8;Àµ8ˆÅ@^tJÁÇBdÅræ%}w¾»]ˆÚHGÓj³:&*fƸ¬GâÚü'}/¹%¼„`&C£æä IDATÁyê³ƯÀ„‡£ŸÁG÷ŸA_Y˜Ge¬xØ1d‘¤t;"µ¿ƯVÀË üß.₫sË£œpp¸Hđ̃ưÀË>éq6ßg"¿¸¾Ë˜&‰™z”¤ÀÁÊ‚Ă÷Ê@Ù÷Pñ*¾‡²/Pö8Jæw¾§E‚ï¥nẹ¢ /²éøK3PŒ&uúRă#Ó´×aëA*lÂGæ}Œ…–Çơçă ßÓM‹4}x‚C0”%¸°ÿÀaư¸|¬ û6öb±áø¬E₫ñ+¡B1ɬLÀr‘‘-°Ë8¬{xî-pø^Ù«±ó憻=0ưyÛvœ>q¡ïAÆ#c\BpE J™µ´ÆC_)J"NÄËjâÑ6îÆÖ÷É\»ùßÂmƒ«ä¶̀ël Ä2Ïß¡f–í'DWºF·âèä"æêaGúÓ=ܪơ§ƒ—‰€^Êù‹W₫²$ ĂM©ÆZ$nŒCU§ñѧ'ñ¦ëÆÁT[/L7)Ư ¸SÇØç‘#₫|ăŸË88àà°ăVØ€œ1̀6" ty xû+·¡qËV|̣À4¦ê“gOáüôj¡„T A+€ÇÍ~zÓ”¦1 x*ˆ¤˜%X"l—8µÍrQµƠó—³&f¦[½¨Á– ÛY1«'a©”Jú0l™Œ6BƯ‘ƒ́,ˆ½‚™éÙ|nôÄ`ñ{•¼0¿ăf{“W*Á¯ta¨·„ÇÑÓÛk¯Øƒn3ÖJ…ăsM4"Ÿ³l9‚u;,G̣¼Ăa×ư9å₫{spÀÁa]I€l”,0ߌ0Xñđ‰§'păæ.ܶ£O`øÖql¢̃jàØpä̀$ür<Îđ•₫ÆFG°ahĂ[oÜ ¸ụ̀-Ú‘.há¾sÇçZ˜[¨!ŸÔV´€ñä™ăô¸'„Î…£D(u÷¢T®@y"³ư„RI)¡Ès^Ä«a©%ü¨@Xp¦Ç"…€'„'L€À…îÖg0ÙSbÊĂ™¦\Î)8Tß8ú{{°mûܾ£·́«ôb¸·£] >°€æB _x̣Û fGÎÍàÜB€°QEÔªkÆày‘'2‚H!Œ¤¤äudöLEÆE†×ßsÇàgŸ¹åíÿ×o<ûơÏ|äyÆ£ØÀEưN88¬ô cav†¾ôÙOÉGÏüêe£½ÿ¡,¸×’pi§~ŒHẠ̊ÚW>ˆdRÏ "lÖ!p´QĂñ©EMr Øÿ\]#1ÔÓ…[¶ơᶃøƠ× „j3D†øÏazr¬µß&Iñ'ÆC (yÊ÷t¤úÿ³÷æñ–]U¹è7æ\ÍnNªNơmRé;H "m"6øơúĐO½>ơêE½úóqåª?}ïyïŸ Ü zQ/W!iA( H€¤¨J¥ú:ưÙÍjæœăư1ç\kí}ö9U•T5ømꜪ³÷Ù{¯9¾ño|€d'Ø€Íi‡+ÉE¦¥ ½øƯƒzÂÿ ¹½ C;’75ÖÂÙIœ>ủdaA$ȶFŒFª‚É­€ qëM7" ¼å¥!…@£#Àßéàñ)₫ù_>ƒ4W8ý( 3úI £5`́®ăÆ 3eŇÚ%ù@(ä¡B®4\₫‡Ă0|íÖ‡ x㨓j>tèĐÄ=üßn₫Èưzư7¼»º©pḌ¯@5¨£¯uỤ̈¼âŸÿáüóÿëó“ozѳ~{Ïtó»«+Ù²³hüs%YúăÜ ´aähSÖÚ…Ư÷®M¥¤/æ Å¯@ Âư_"¼Œm;wÂ&̃ö ÄxÇk¯qÊsƧ­âÇqzq ù̉i[I! „›}'DGAÙ.Jkhlđyg,fÈ‚•0ˆÂQ D„`ƒHÀ²¸.­í‡°eÇ^¼ùö¸mï$43iUúƯœñK} GŸAÿÄCH»k0DPδÉ]ÑUđ:‘¥iR[¦% ¤ÛhÖ­æê‡Ă%̣Z—ÆSe(U†g''£ï¸ăºèO?ùÅ7¼ö×½£Ư₫†¿®Á@5¨£§2>udw˜ÂϽăOå–¶¼fËxó₫=ÓMdÊđj¢iªP .́,6nͬ÷”׆¡´v-àb\­*Ró`$ ̉ØÑ4"àècÇ øÿrD„Ưû/Ăå³ üàswâ9{&pÛ¾IG…߀?ưÂ9Yèb­›@#”„f#̉€ )UáC@O¶|ö́„Œ ÀT̃é]ĂÀ²Q`M{$ajÛN°1¸îÚëH¾}§»?C Æ»?{-gøô?}Úh$gAJἬ\Đhcư₫+ _?‚é§*J Á.À’ÖÚh;*8Är t„œ` ‹ä†z9fÇó¯ưĐ?~áûî~îơ¿]™q¼i€:ê¨@u\Êxèl‡æÚøèáÅ}SÍà‡·…oÙ3Ơ0½L‹ƠT“B¯JáhƒB—JÜ&åzîEÊ ·JÖ1€ÀÊơƯ­°­_Äxü+‡q́+À‡îû Àj73ăÁăóøÍ¿;ÇNEÿÄaƠwï•´¯‹Z™Ñ’)C9^Yúưsa´Tö=¼¢?жïïß·W_=‹n¦‘(FŒ~•ƠeFU)ƒsŒ¶´#¾ë¶ëö9qú'î?ưÚ¿ï]ïø‡,é{ ‚-†ê¨£uÔqqñá‡pו³84ׯư'×®#à ×íƒ2̀‹½\¤ÚZ¼ "':³ Ú[ÎỠ¨Ơ»T©z‡ÿ—rKŸ·ơåÊ’×"0<0êfÇǻ¿E¡Dge½ƠE, |îĂØ¹{/"I¸q÷î¾f;zI†²‹[L9>8Dc?5±ùƒ“ ^s ¢tïc{94–––đç_8OưËèg ư…“…7a`fdJW¨|¿â—Ë–Cơߘa\ÿ¦ ó+0´₫>Ă×w#¨ă¯eµœ'43N¯e4Ѽç¶­¿ư[¿ñ£/xÑKw₫Đk_ù{t¬®öJ Sƒ€:jPGO2î;ºŒÛ÷Oáª_ÿÇÆç~́Ù/[NôŸmĐË4Ö\Ơï“È#’ÖđG¨Å@®-h„+©‹q±*›@Ev¶BÅ6¼Rá^µ¸D ]‚ƒê΀Àơú—ΜD [ZÂ–É ̀/̀ăƯöWHבf i® ”²ŒÄEl×»x€7d˜"MÎl@N¸è=ùă0Àøô¼é;^†…åU¼û‚̉UÛ²È5¢ D® Œ±´¼)ªùQs|q ¾ü>_ơcàÿÊä̓Kˆ˜/,íˆ ~@ÊqJÆZªI`ªđë¾ơ¯i₫åßáû_uç¯`"`c¼U°FiÄ5PG ê¨ă‰Vư-à®C³¸}ÿ₫ü‹gn¼zÛØÛ¢@Ü=×A'Ó¼–(̣U? [ÚóŸµD„\Ûj½GU߯I² \ê©Ẹ̀›“÷«m«€@€2Ö$G ‚‘6©…̉n¬‹a™)(íƯ% Ï,ç dŒ5Ú́µ1x‹`Ă6€Ë^]Fºx¼ØĐ§…¢†QĂ„!L²† ™RÅd…̉ÆèBËP­̣WÜË郪hoPÅWîV@±té ¹$Ÿ{mÀ\”í%+d×)'Ê`±—ÓL+äW¿ä¯9üÈ#ñOüÊ;̃}ï;óf+Nú=í€qOÑ‚ÔQ€:ê¸Ø¸ëЬ?på\ë­»&ăƯ¹f¬¥•a*¼è ¡èÚèØ§[qéªcr£ÚđÿÂ(‘€].$@Đ‚ ™`* Y@h ĂvÁ"&™B–Û›Özt’s/™æË÷äªàM’瀀ÂöÀ Í’! ›̉ư0S*WÈr,WH•å™ÊvD́JµŸÏ<'öêÇJwưRlT¬ngDP†,‹+ˆ Fªç:Ç’¯¸ụ̈W½óío½öcoüÁzưó¯₫₫f«=ƠïuuåÓ#@j PG ê¨ă<áÅ~ÿøØÊ¹[÷ŒÇ¹æñ~¦¹—k̀RxÄ{³.–æ\lÑKDž€Q,BƠV×û¬K¼>;”´±e¡pb>ö₫óv¤B7«nh–gÈóifGµSܘª_Rh“-ƠŸ3 . µú \ÛCØïs¥‹¹2ȵF®”«₫=``†ú÷åx̃P…O@1̣ÀÜmÔFP5†®3U4#̃KBÆr¢©©™ç¦Ç÷¿üæË÷ÿɧT¯»ăªÿ=ăYT̉T₫¬[uÔ :6 Oûkă¡³]uåÖ–T†±’jVÚøœ_$mrJ̣"áñæỠºm²î¾2>6˜\‡×î®7!0ŒỤ (íuV¹nŒí‡+­mUy[C›b*Ï›ü7JhÎw?"ûƯH)“° ĂÖTÉhûç@̣7\ˆ3×Sú<¨£ç¡ Ÿ7¾ˆë†̣.¢̣}¹m~¦*óÀƠ÷Ķ ú¹!fÅÓÍ^zăå¯ÿăO|©óú^ûqåÁôĐ36} ë¨ăk¢~ êøzˆ¿zp¡øú®C³øÈC ¯{đL‡¯ÜÚJ̀w2hm¨±ƒ±«Ơ]ÿÿb…_4âïù<÷ơ3 À d¸̣f?ÚÆ¥°°Ø ȶÿ=@‡SPæ̃Ÿ@k­5”qÓßr¥FßG¹Ûè¾#~̃>ăØˆ̣ùÙ䮋âÛ¸™ưj¯ßT¾·\/²×Ó¸Û°kU.€ÙàBñEÿç1ôe0„û¹1CŸeh9Q˜iü[ưàÇxüưoü©_¸Ü€@è -‰Ñ̃µ@5PÇ3;^yƠ,~ù£É;öOƱÄ}7î¿!VE½Ü8§¶—¯[ SŒqodộbÔØcc/Q¤̉pƠ\uƠ#ßăö+…©x|ox6CsđåXàÅ0¨¾Gq¹Dɉ A F`¦¢æÛÜ<8ºWööík/u#»âç_`x^FàÂ@ùh¤ƒ½>ÓCSî/ú™F’jüMWï~á̃ŸưŸ¼ñæçü›ÿó»¿å¯A$Pî ”zư$Ÿ}uÔ @OÿøÔ‘eÀk®Ûr㮉è+7í¿!¯¥ ¹fD’Đ@Ä@3ö碌ƒ· uÄÈ2¬°]{áʵ*CÀ›́<œŒ‡¾C¬æ¿/oTaFƯđî3ê÷ËtÊ­:E…_Ơ K#×i2xè Ă&ÿ*x!<áNzqÙ'vûx́„¡‘´[ĂÊÊf)€Àoz_ᄃ̃i¥¯¨›iœ‰Í7ßư²ÿ₫_₫ä¯^ fÂ0bªæAùê먣fêø;Lá_:·-ô¶=SñöP @ăq0ØM­Äùfâư?µ#‰ƠD—f@O2˜«ăáïGå¤K¥ø*đtq¯ăb~Ô}F*ă‡@ËEơ_xăJ̃”Ø ¢‹^™À€@(lBŸh» >wÅFÆơKvÂPmXœùU/ñïD÷|búM¯~á;Íf3é÷=öP₫áPjê):jPÇ33¶G7çÚ¼÷2M¹æ ÇôpăZ›%$`<–hE©2è+¾ \q^[£ÀÀ¨SœFƯá"SƠ7DVN₫ä' $ø5ÄU3&¢'ưëQLرF0˜ˆt3ëU F¬TfX 0̣9x6Üî)í›ù•w̃ö+ïüЧ§̃x÷mok¶Ú“ư^7­<]u⯣u<³âÓ­à¶}“¸uïÄB¦ B)ˆˆ±æë«Nº¸„½œ0¶¶#´c‰D™ ‰óçđụ̀̀¨z!Q¨uÚ eÀ°0%°.vÉñÉ&µ•üGP®·ú}²›×­íshn¼`÷d ÍŒµÔ²EbĂ)ˆÍ?   L4 ]^qû ?ưÎ|6~ăËŸó q£1™&‰cPèÙ€ ¨ăkµ µøÈĂ‹¸mß$₫èŸOM=x¦ûñ@ÖR A@#Ö×ß9öứóô®«7mT!’“Í PÚ¯鹃½bă{>. ́‡o£jNr|>0C—¤âưç÷us₫-“ÿpµ¿‘NaÓä?4 ¸ÑÛU‘TÀ,Æx`ÿL`-Ѷt'¶ÂĂÿ+Uo¦ü4C¥^s xûxŒW>÷úÿ½{ÿá̉$é œđºơ‹…ꨣu|cÆ}G—ṇ̃+gđÁ̃ôÜ}“KWmk73ż–XáßT3@(…U1¿ªï|½uĐÍ ReĐ­@ŒüyA3J0@•äUMđ¥ïÿúÖÀf,Eµ»<Ü:OÓ‹ËS̉ ‡…‰Ă€ÀZ‹ơÉäb']­;÷@ª…˶4K}…L›À{Ll2+\ HA˜lØÏíbOa%Q@InxÛx„ïxѳễz䯻ư%Û08&¢Ä먣u<ưăĂ—³₫·ïŸÂ}G—ƠƯ‡f₫¿ƒ³Íªÿº©]Óä@ơHt‘ÂqwÊ÷2»¾ÉÑsWD¨¥ÓIœQ­\1Hˆ!6£’̃f́¨ßóơ•ç/Đq‘/₫q}Â÷7ª¶>›̀znü±₫úÁ̀XêÙä?è‰Í&•׿]ĂM¦œZÍĐÉ4e…2Ló c‘äW̃rù7ÿÏüå?ÿÄ|ûM4*L@°¨£Ôñô®øïºrÿîGäçN¬}öØểóöMJcư\·÷èd¹f4Bp¨ê»X-?3#+Z„8(/×DÀ®‰†]»aNa˜uà öfÉgƒRôÂ1¤´ ÄûáoÀ¨&{_YW₫àÛDƒ.N•¶Íù‚;ÂT3Ķñk©FZ$ÿrđ|Ô’÷=đÉ?„f(0ßÍq¶“̃Ú0¡€f`¥ŸS?׸rKƒßôĂ?rÏ¿ûÅ߸Á%ư˜ˆ"Œ¬@5¨ăéíâöưSxßÎ̀~ï-Û~tªœ¾y÷Ø”2̀LCi{ˆj7b%°ÔÏ¡ c,–å,ûF tƒ[ÍơrkX3Ñ r%X‹Á"Í %t*F¼0\äœi•n[çæĐl·E0œ ƯđOËØLă0PíÛ7̉`₫±©ø;;Ă?Ó q`¦éçB :b¹ ÊäÁÏ–É „ ¥ÀZjW7332mp®›»-–YèdI®éĐ–¿ù‡~ä·ÿî»ï¼öwÏ13Â(ªú ƒÔ@ Ôñ´‹Csmü9=~ơ\û½gÿ÷™f;É wRE¡´[Øe \¦ °’(ÄÀX$×%ÿ 5Œóßft3PÚ±Y‚Æw}bĐ@2a§̣£!1á08¯ĐP\<"c8-†gÊÉ?ü&Ơ¿LlòÎ Úo[$·ÑÏ·c©¦öMÇP±ÜW₫›&ÿJåÕÙĐá“ÉF€H¯$Xî«oAḿJ:Á@'3èfµ%æïưîïzÏ»~ïw̃úËïúóWæY–Dq#Æúv@mTÇSơ`OYÜwt·ïŸÂGYü¦çïŸüyÍü’8¼–(*Vù¹ƠÙ¤hËTdÚ  t3²´je>ûBÛ~C`’3:B¡JtƒDéâànϽÂÂÁ`c³óPµ:d°IÁxÁ§uQzđQ ±åđë¯̀wï‘·fº@äVYÆăÿ™KDD•kGΑOI¢pè«>p, ÛÆ"h–åZ@„¼O›SJä/½û"Ọ̈l'ĂÙµ̀iÊÏC'Ơ "(Í4ÓTC`îÊ}ß61=ûRóïĂÏÿÀw~ Œ¢8ϲ*æ3CÖ먀:¾>ăĂY±ßíû§đ‰¯.}üùû'ÿ{ˆ—¯%”µ̣‡o$mÔj¦¨ø7f`5UDe9G‹×øc¾›Ù3tëXˆ@¢z kÿ*…@(Y~/…()ù #P/₫¶_KCÏ¥ªú/₫nÔc£\ëût,ûˆh={A›ÜªU¾+µ‰©¨öIP±‚Xøë#¤ RÚëH„DPÑHlŸˆĐŒ$Vú6ù[@1Dưo’ü™«L#ÓÍÊ0/§v±“»ƒk©™¡¤ «cm„•6XM4’\óscc¯ư–»ßñóÿù=ßœg™BlÆÔ @5PÇ×_|êÈ2Ưq`ßơé“Ï}ö̃ñ?¸|Këê(褕Jö'Ze¦^ˆÁú>SÀZªĐ$")jó¤ÊÍ–úiØ>ÙVg‘”ˆCƒF®¡,̀`„ßxGns†½ù±¡m­× \X‰<GüÆưû ȯæ×A„*CPú28$ª£|̃§ß¶( û[ ́‰ ®É{¦®̣®û]ơRơOD˜n‚đ•…¾¥ú©̣"ܸ£6Àr_a<–~£`A%x6À̉LWlm·ßü=ßùtmáÛư?üøÇ´†à‘ÆzĂ ¨£uüëÇCg»84׿¿9¼đ₫çí›|U32Ó̀+}E –₫uËü0Â@Â0c5Q.g”_r•V/74BLs± çÂ*ÿÁÊ[(Ơ„0Ñ0 ’Đ%43”fgùJÈ”†̉ÖPH»-}́VøÚ}••·C„u¡Îùæpb}ú–xe cóà¢Î·;<”đ«lˆ«œ‹å;₫kWñK‰8 Đj„h7"4£[wâ€pƠ\ ©2褺|¢>Oo–ü+æN\aZ¡(’ÿr//À–ÀnÛ#YĐ9đUœç¿“iÊ4óö‰X₫ÚÏ₫Øû^÷½oŒî¼z÷Á^gM0s†̉9PUâ)ꨣu|íÂ÷ùæ¯Å¡¹6¾tºóûû§ßÚ$w3Ḷ¦6äDß»å-,oR"j¬% íX"”™vt{e~Ă»sÙGöiE@/טhHslÇ!@–a•‚*…<—È´Ư{¯´±@ÀXç7Å .àª+p™–ê\8ly$₫ LÅJà € Q$}áPPÑßw ¯Ó̉Rụ̈‰8 Đ#Œ5cŒµh7£xeÚ`±ŸĂ÷˜U;åÁ-Ó#_›ßÎb)0Kœ^˰ÔË+×¼D>̀€°ØÍ1Û JB¦ÛD,aBª e1ÙÑ-»Çùă_>₫Ơ;¯Ú}y¯³êŸFîî¦P¶okûà:jPÇ×>>üĐnß?¼ü=øæC³w¼áÔگïhG’WEÚpÙ7wGÔ°è$păQ¹]†ùJº›DÀX,±’°«À±̃ˆ‡*L_eºç¸C¿Ê¢?}ÇÁDQ„Ë –––0¿²†n¦ÑORäÚ@)eJäÆ@k¶ Àµ4Ú;÷Íĺk 0bLíé40@Y½…½N¡¡(Y’2á[„ྠ‚”¬IA®Ï_Ñh¸Úê? 4b›øç&˜Ùº W]¹-v IDAT~ĐfHK³»­T\0Ÿ ̉ÿU$mߟoơk?ḿƯ Ѻ]CL•Ưø5Ô«‰ÆDốƯăüɇN<ú3o~ĂM}ï=§µ@î—é¡êŸk PG êøÚ$ÿ‡pו³xÏgOm¿a÷Ø·LẠ̈w÷M7‘)Ă+}E ¹Ñ§b9ÎĐ,?!”„T°±#xëÊ÷Ê8U?טj†ˆ¥@ÏÍZc„2ßíysc}v—{$¬Z;pc~¹¶Á¾u{ë1ˆ½ă¶â‹§{8ƯÉqî̀œX飓hdy^’À¥¹Ú0rm€2†EÁçC¶L+–Û Ø%?:ùóÈïø¢™„Kâ{P­p¥ h!–ûø±Gø‰‹ª¿¨̣íÍVúVàça ÄM„A€m3“Ø»uñضÎNăe×́@ä@’HL6$¦IîÀœa :{3˜˜i°¹Î%¤lEÀ‘ù>2e\K¨Ô´T?’₫₫™¶?VĂâÈc!hEØi—µDc,Ư¼k ¿÷î?₫Ç¿xï;¿í§̃ö‡Ó3G–¥”‘ÖÚ·ªº áÔQ€:.mÜwt™nß?Åÿï'íyÑÓ¿ôÊ-íÈô2-2mü¢Ơ"!SQqUè]QPôllëÊ… Q™2‹í_ŃAäN$A:…¸̉¹bdÊ‚ fË<øÊĐ;^±¥C[›/ŸÄ£ z yáñ3 xl)ÁJ/G¿ÛĂ w BicÙcÙ­­nÀëđgƒ °v¢Â{Àyz_—{ P‘¬ÿkÔøëm‰iˆƠ€Ḱ,l¯Mæ~̃*~ú2Ø(á°à ˆbQ[g§Đˆ"Ütù.Da€+÷ïÆåÓö(S†‘d ©‘—‘´f=cq) a`_ª öó Ù:Cj°áJŸ¾M@#´n-%XI”cw0üG…6Œ…^©fˆ@hcÅAU₫¤hÁ‚€•Da,xÏt#~Ó›ÿ{®y₫Ưï}Ï₫Ñï¾ëíÿ×—Iˆˆ©êPƒ€:jPÇSWơ?´€»ÍâöưSüá‡çöæ]ăwmiGw*Ă¼̉WÂ8©´›œ/*Ü@8ú]”‰­:öÖ½lx“”¨ÿ;¥Lcº ¬9AW3ˆQ8®…̉Uá̀èåÚ¸ĂƯW{N¨Å`E¿—¬¥ªHXc‘Ä\;À®‰Íp êÀ -%XMLÚÇG/ Q óó Pº¶;†À2₫ïŒz­ ̉Í« oEŒÂ‡ä½đ Döơ±đ#fƒ[ 6#h¨¢-zÚ›Ü‰Ö Ås¹ÇQñ~$ÏßPêAB‚¥îÑD1«OE²—R:!ŸMø¡°ă~Q ÁŸƯ=;¶a÷LÏÚ1…é‰ „aˆÓv¦µŸằZ†¾s{,'² P¹6M̃W–t@("i]'vZ s`®ï€¦½Ÿ ›ø§[!e°V$KưW+ÿ{Ÿ•È4#vœUQøR¥†„ª­×wXKơsâ‰F̃~íeß7₫#?rÛéÇ̃đÁ÷₫ÁăC¿FUÔm€:jPÇ%‹OYƦđ“ïdæu7ϽmÿLㇶ´#êçSÅd˜Ư¡n@(PTú¾ïj˜‘kF_ûªÙZưÆMà©2‰óƠÙÖ́¤íH¢KDÎ×ßÏX§Ê Ÿ,' nüz(!x@¸ä&$ aư €µL£“i'B³bÁéF€ƒ3 cصu Æ0Wwྣ«8µ`eeÈ“B0è©f­­fÀOpÁXX¶‚¥,– I! |Ÿ[Ih)´&GW¯?×7ÜDx²àâîç’=•IÛñ$¤­ÆÈÂ׿Jư[ÀSöñCiỏUéD„ 5‰+¯¸ qâ•WmAØha¼ƯÂx,KÂB7‡fÆăË r÷K÷¤É@ª£c "µa(Øù|!́‡¤“Úk„V(ĐƒâÚדŸiHs#‹‰e¬ ¦ưKV¤àÁ0K̀EȵA¢ Æ" "Hº„{^©²:åÚGD€°'´(L6¾aï̀•¿ø+¿₫çûñÕ•:|Î1bª-¨£u<ñxđLWmkẵ/Ÿûök·½sçDBIhH‰©–ÄwܸƯ²̀PúYøưÏœD¦8wæ4T,‹áç¿–ú–hÄqlY‡»\©b́pt¯ +¢§l²À²û¶Goˆ8 ш"Û~ Ú”£‘¾-H@ZV 5=‡±ípƯÎ ¼₫¦9(SûtS…•D!U¹ö׋‹VF h`ÁOym©"‘pÉ̃‰æÙÍøùäï¯OÀˆ¤]ç;Û vÉ3Xynm©•aHá ;¯ i}ơ?Ù´ǴÙNnY"(c½R÷;©Ư9=Ơ´‹…&Añßf ¨{™&)·"9ûSßu÷ÛŸsëü[_tÅ–½A)•ûQAß   POÔQ€:.öÀ'¬%ùucqđI{|7‡×^¿³­̣èɵÁB/G’¤®HaGG+  H¶°æ?~cBI”˜2éŸô-˜ô¬Ơ¶ñă hÏøàƒçđđ™̀êỲM¶ñ=w^[L~ $.Âûq$§Z!.›m"Óư\# LjĂè»ÿ~úy†Ơ¶́Èêxd—b¹ÿüƯÂ;/›™₫èĂçyÉ•[o¹·.zøQ‰¿uÔ ă¾£Ëˆ„ˆ,&_¸nǘɴË}eÅm\I ›$ø ÍÀjR±ûƠ @éºçO¯n£›äH2ùåGđƠĂñ™&§§±w¦…»¯œAŘjhGvr`%QH”=ÈCD({ƾ_́X‡R/À…0‹ÜAÏN¹ ¶÷g&„ (—Ô¿²ĐGèªâ±Hbn,Äw^¿Ơ½¢½ø«‡‘)ƒ…³§‘ẲÀ&ÇÚÀÔ$’\¡•eÈ”¶­€~`3 àﵺ¤Ÿ áüø¥Ăa"’ă톢ˆC̀NMb2d4¦¶‚„À-×\çín•×Û0Îuí✕¾‚rú«)M€ªí$ª2₫½÷×È¿z?ia\eÏUfăJñÈkÀ@’¥ø̣É>öÈ"æçÏáô±#I#ËÆèIÀ\;Ä|'‡0lu-Lm$ª¶¸l¶ ¥ç:ùÀD*œüfÿíô°îæ ]v¬a²!ÉBPË»§ÛÛÿîÁS¼óª/!¢V…iS•_§‡Úu[ Ô±qܾ ÿptùî[vLBJ÷=vrj zÂ'‰7úéå@ U±û-S[ɲ=Ú¿ûê Vû9:ư Ư4G®hHWĐï¬à́ Âg¾@˜Û¹S ‰o½f X¢{¦bäÚ¶+G3g~>p+e ƒ‚¨´^S€¢Ñ́¦°TµU€œëj,ôÈÑüVy₫+g\Ù‚L3»z¸ùÚCHz»‹ÑB­M!₫Û¨øßèưÏ–Ïà’Z y/Ttl@srÓ1¡±e/~₫­xñÁÉâ.J[àåœ!ÑWÆù X–&(1°ưä[4¨̣‹:ŸK‡>KéÛ[q} B3”­f$ƠÀ©Å5€5₫â₫Hr‡ù ŒÊ »Ë0p‚J£Ưj"5å ¶Ü‰R[Ƭ áéN¥ưLøD?´Ơr³ÿ6¼ă%È]{́LGĂ  ́ŒéY[›Ø̃4­;¾íûnúÔûß}ëW,ùÉ€j; uÔ[¥êظú¿}ÿ¾2ßăƒ³M³ÔÏÅT#D?×XI´eĂdç văƒ­Pb<–X́[±1+.¦ˆ€3 ü¯/-à _~«½Ư4GkhĂnÔ Å‚ ÀØØíqܶgûvlWÏÙÊ´›i(ĂXKµ5öqÉDReå¬ORC̀À€UUyC Ễù]q`ßT+@+´óîxÚîưC%á3e?'₫½ơ¶ÍB`` ´Z5ûJº„4Uw½¡*¿èßƽÑ~\¯ D‚ĐŒHYH±ÔéĂô–ñĐÉ|ö‘ăèözĐƯ%乆a ׺˜Ü 0¤ˆĂcÍ3ÓÓøÖW¼ Wm ñÏÇ× «evÚÑ6…ˆ!ܧaûx„½Ó $¹Á©µ²ºÍqhÖ¨«½.3{Í\˜i&›&{9·ăî»ÿá¼ø–C?¢̀)€Äµ”»2 ª@ÍÔQÇúêÿ¯/üÚÁÙ&–û¹è¦Úö§c‰nf«æK%6ó,@ª Ú‘e¬»^yL1ÛÑ(阇N?E’iô3…~ªä Êpá€p4¯wS++ÖÖpïÂøäDAˆÛöN BL̀̀bßTŒƯ“±s´‚¯¥ƠT%Ê [U §.·6î4 ô=aT:UËvX!å¸a'Ơh‡²0ŒI\¥Wl~‚g4h‡̣©­ *@¡$L4¬e Ë}U¸,†®& /:¢¡„_Vú₫3!(ƒ¡]ß+ûÛ‘‘îIa–c+9–ScÇ¡»¼€9¾…Ơ.ú+‹ÈÓ>˜Ù™6Y#'­µsu,[O¡”P±„¸ßǹùyܼs¢@@)«(6aĐùpK;D?7XèæV¿à÷ UÿA=ơ&€ÛÓvhE‚g×2<¾Đơ;B́iN†³»ä ÇPºno¥®²µ0°uÔ1Ÿ;“ÑÍÛ"¾y×øOà~nH9+̃vdg¦sM…ÂûR…6ÖŒg,–H$!a ¸­L9Ó–ƠÅydJ!Si®‘(­K•¼p›+æB²ùEÀ½óóv‹\û4¦›wmGĐháƠWÏØê¼€Ư¤Âj¢v·öy€Ü¾Hr¥:4ô=C–Ø̉ Àwsô23Ä<9Ûß•€'}Ū~₫•ª=¶=3Ư ­ßCn0¸o§ –ÊZ—2̣#—\¹î¦º}ŒV(!…ÀdC¢áXÅÀ§ë`mu§ÏÍăÄ™sXëö±°¼‚´×…Ö¹Ḳ¹2Pîk¥]̣w;ª~a ­Q”ˆ“ ‹Ë+b_É@ j9m_ ;'b´"‰S«)´1NđW™(ñ@è<À†«Ø 2&Ü„Àă+)4gÖRLoƯ₫‚Ÿû…·¾è­?öƒ÷đÈOl@2µW@ ê· á¸y[Äsxá#ÓÍ€æ»eÚöüSÅH£R˜Kxdx ¯ Z‘ÀL+ÄÉƠl D1̀…©Ê3(ekÜh(ÅPZ»‘.́„ôNuD$ ç½ ° –H•B/Ͱ,N,¬! C‰4Wè%)T#W ¹̉å2'­*Ißv¼^_a¸Ü0)ÈÎăRX€™¦HWÑÀt3À©Ờ²’­íë˜nØ6¡›jË¡ÊÑ:Ç  ¢ÿª»z®¢_IÆùnÎÏ“/¼í–;¶8tÿé#ª₫1"ÙsÍÔ :Xfƾé²éưDD~ï= {|w3™V€00ÈÔ¥ÿưÆØÍm“ «ïfºH‚Q đ¥Ó=¬&ªb·[¹y…–ß3̀ mRIB9v@80@Êj9ƒ…@¦XíÚï_ü"B)đ/‡Ç1¹u^|p‡æZØåü Ú>gdÆî~å¬(™Â„Đí5DẹïæèçÆV‡NøVZ ‡ ¥₫«`Ø¢öRê ¨b[ ²c‹ư[Û!¶¶#œZM¡ÜVHSè"h ékc “'Ÿß'[ÛQ¹½ÀcK)>đÀ9œ;sS¡Ÿ¤èg9”RÈ”r€PU¾Vv{£)Ö9Û¯½-3»äɦl³XŸ†0dÛnụ̈è|œK1̃pz-+̃ArîÖæ7@/ÓX́çÅ¢ªj̣®₫7¢ÿ‡7V«ÿĐy_Ipf-/tI¦i¥›âºë¯ñ·½æ5Ÿü·ÿRƒBÀÿ̀ªÄjA` ꨦˆđñG?–isESHî冤đIÈ.äQÑmut)ÛH”ÁK̀´Bt3]¤,)€X_I‘äºX¶cç·]%güjỌ̈µB-‚©Œ– a t¹k̃®›ƠE»  ø–ÁZ?Å™sKøêö̉ß¾{?Â0Äß± 3­ĐVÿDXIz™A7×€-Ưm@ÎṭÂ1q`Æ¥ áªúip›m\x^ut²Ÿœíä˜ ±}<©Ờ­{æB÷྅aF$-K3Ûq àç»>}iăK_¸éÚ"”fäJ#SÊQûyn Œư^)S.c2–²æQ̃|É̃ŒñâL®2íÅR&,ÈtL‚6vĂß¿$Kư϶CkSl¸øJ₫ ¿ Á—¬ÖL+@ K=UTÿ ‚ăt'õ;c¼üîW¾äÏ̃û‡GÏx́J-@ue°úº ¨@uÿùCŸ‹¡ %N¯¥$ª¢-"°³%mEQnæ—ö¼ Gs®¥ ÓÍc‘,7¯¹_å}ÚưÂ8Å~y0›CÚ‹ Ë™m13‚BëB3 „oÎŒF«h­3_ÿ«"?ơƠG±m÷>́›ñª«fhÇ;&"t2…^j™\ÙçJmă'W3ô2½îØ}2ïè0 ¯e‹€JÉc'µS;Æ#´c…®¨j#IÎj×.ÈYKØ(Ü÷èÏ÷qøÑGÑí§È—N[(m^I₫ZÛd_Tøl¤oÿ4¥ëŸO¤\NTßm½ă¤} Vz)N.vpó̃)2©Ü‡Ñ%¶Gè¤ÚNË>ùŸï}ç¡êß×–+´í®„H¯¤Ọ̈Ú1]₫ôrÅNÆ/|ÁíÏÎónÿؽï{,©Tü1ô35¨@Ï´8ËŒ9":°÷¿^¹µuG ‰SÅ…é˜¯đˆ€•D!væ6™âK.$IÎP1cº¢—dZ#l^]YÊƠÀA½>q̉º*uø 7ÎíÏTÔè^/@d U)"Âkܘ_h#%}å0N¿ÿ053ƒ¸5W_=‹©±&â(Ät3D;˜ïä‹íÖ»$×d)æz*¢´Ũ$_?EaÛ/Ö%r²°«y[¡ÄX,±’,ö2¨´Ăk]¼ÿó'p̣äI褃<é _i¶U¾̣Â=],V2nÛ¢ïçûÄÏ•d_VøƠÊ+Ÿ‹ÊL•¢D¼æC¥}de4ÂY;Öç+”¢Xô³ĐËúơTI₫›Uÿ#³®áßÖvˆ@Vm)ŒẦ dO¬¤tÓîÿæ‡~üÛ?ô₫ÿy\+UMøºr´ÙÓ©£u|Ç>øå³ÏÚ1_ÓÎv²!y—3$q́\3¡@[kziYfÆj¢0Ó 1ÙĐIµ5 2ÀÚÚ* ëu¦8e¯ÛÚûVxªÚƒ``0ÚÑ5Ki+·ºØ›y …mXí€]„$Ư’›…ùy„r¿âc“˜hcßt×îœÄÙI4B£+ «‰ƯS`œÚ/Ù™ë)lÆ-;_7Ÿ¯ÉF€Dœ^F²¶ŒOYÂ#g×ĐY<ƒ̃Ê".Œ”6PªTîk=ØĂWÆ{’~Å(iT•ôËÄ?øi§ÊÏĂ0Z:ĂD,J ·{z°oºÙvˆ¥¾¥ä%U¼16q₫[Å*Ù·:÷‚5ư $áèR‚^¦ ¥É¼'ˆ€n®qf-ă»ï¼ơÚ[¿é®Ëÿáoî}Ø%|…A?]ùZ ö¨@ḮB¼jº>O8ÓÎä̃÷E¹Ü÷î“s#Œ0K;îuÉÙdB’Û½́­P Ù̃đƒg{X́+kI ›œ¥«Ú½…,¬>ø=[Qö¯y`áüXăTüBÚXf Đ øơµR”€Àµ ¢@¬.#ï­bñœÀưG¸ûÙWậí“x÷û?ŒsgNÛ₫²20¦œ^x2#UsÍÀ NA’(fơhȸÄ̀ @BØ•ÁB@™í»qÇm·àŸư*>÷ÀĂXYZ@–¦Ẹ̀©¶î€yî¾đ¯Ö·4¼v=|¯ûÛ?₫Z‹G%|ÿo+| ¦K”ºªwQ8vv}L4̀wÀl;´Û =h÷[¡ÿÅ&ÉT骠›|™nèfÚù+”- ¾₫`_IéÙă~î—̃₫Ư¯ú›{ÿ@m€}̣χÀ€Á  fjPÇ31¦AK}EÆđÀˆ×đé•iƒ~¦Ñ…]z‰Û¶g,ö¶G˜i… ²Êl†]0#-íY¥ự—Ê:ßÑÔ¯g Ö34‚5º\PD h*EcRÛÑ1FBi×åFq !L,Wxh>Ăá/~ư“ Ës乂RÚ‚~²E˜3ÜqÊü?ú,U¼>—´uă§+„@‰ ±gï>¼ôö[©.NŸ< Ér$i$ˠϸUÉ¥ˆÏ€Á.ñF)àÛđz®¿¾'ư²µU&zß̣Rº×!ÜĈÄr¢­¹s¼̉¹H.ơ•£ØØî—6åkªO±2÷ï₫-¬)ơ™µÜ]ùäÏäö"”N«8±’̣K}h×Ư¯ă³?ôÇïü¬KüƠÛ(wÀ¨@ÏÔˆ[ÉĐÆ=3c%ƠhFÍĐÍø’±₫đ³«S-Ûà{åäÆơ¢@ ¥Û` W”$(-lñ~älX_!2Uêxx÷;É•-3S$éø™̉² ´¡R¥A`µ— »ÚAçÈ3;³n´.΅'“€«É¾XÖ$6$¼t€Ê*%‚ @EĂkK‹€ñX`¥gui6ù+d¹BæÅ|…!)>ªt₫0•?Ú{¼€¤ï@“pÂO›ø%Q€8 ÑÄ¡D_¬%9¦›!̀41KœëdV#| î~ëEª₫«Ô¡#pĂ­íƯLc¡—UÀ)¡˜ṕœÄŒ³ŒvMÆ›˜Đr‰>º[æÎ‰² P»Ö gjœí¤bËX„éfÀ}eˆ —á¡´A7Ơ$*‡1—†¨Và̀ŒNf0áÚÙÉê2„ÎĐŒƯúVÀÑïÊU’¶ÿ­ô"¼ªw¶²ÆĐàîø¡$RỤ́̉@b)×Û¯K2‚íï–‚um}ê™m·56sÇẬÙ“H»]¤i†4Ë©ÚTn†7$Œúó©v&̃± R" ÄQŒ0 1=5À.³éö3Y ÍỶVm_©ô˜)Ö.—ưú“~é¡àÉ`Â÷ U ¢„ó‚đZ(ˆă­8B³£Çª,éb÷6»ÑñL'C7Óv̀´04üÙ,ù¯sá©ÿ¬o‚Ư+kƒcK ˆ Æ­¨ff°›f©̃´f\¹µüæŸø™oyßï₫Æg4+É߀ü<,@Ư¨@Ï€ üù¯ù‹wN¼¦Ê R¬Á´¾.dÖ2v,Ñ„']V@Å’U¸½—i´"‰É©)́;ĐÀé“CPR »B8—È}?YkhÍÎƈ  ªÉeP?P–³â¥O¿ƠÆØm€¥ơ¹6ÿV IDAT­&@k‚‚FæÖ+­‘ôôû}$i†4M‘ç Ú¹nt̃VÁù̃ßÉóưü…\«ÁwÚô÷ !aB)XEè'¶ê×lä9¤¶ç¯4²\´¿¿Ơ´1(óׇ‡®M‘‰7¨ôKßÿ鵃a …‘ă­Æ[MŒ7ˆd‰ˆ»©.VH¼]C†?›)ÿ F[ơf´#{<+ĂXI•Ơ¸Ïj55@Àmêœj†¤}#^vƠÖß0å~Ú/D¨@u`Çưôï_qí‘Yüûf$_ "¥©˜›ö½̣aá”vêíH QÆ%±'÷}ÜBB;”hFvQNª ®káí-Đu³ø§·iå>jsµ ¯¼%D£³́¡ h% µ.÷cókø•¿ŸÇíÓS@<Ơ_u×¶oÊäï«ư+ûÁ—Dë@N±¦ÚÓú ´ oø$„ơrB lŸH‰(E!&Ú-l›lbvÇ><ë²ư80aÿTT€Ü‰F€$7Đ¼̃}XÿwĂ„7ÛöÇæÆB¤ÊàÑù~™üQ‘_‹́3pp¦H ºç³ö´]Roºäßp·*àơ¢ê¨@Ï”8ơøQÀ¿{ϧ̃ñ«?đ²WL4‚›ReĂ®ü‡+ÅÂl;D3pÖ½ÉTœµûuk]C eTc¡—c%QÅïƯ9ăúí-Ü´£ yăº9ẵÎ!í,ăØü V…n§Í̉Zö s—xJvÀĂ妹Bhæç¬/ ø¶@±ÈÆ}á…$ ¨¬ç¥Ê]ih­ ׺ —Œ¾ß`£ăù´£…€̀5X̣‚@¥d—66ÉUÛ2¨¬ü­,Ḳïăp¿ÊØÏL©{đÓ 4PåÛRZQ_àXÀMkR@È“k5±gÇ6Œ·¸üàÜy`¼¨Â3ep|9EĂM¥li‡¬0É­ÿѾØ$­cF₫J÷À‰Øîxd¾‡^^~ ‡g_ưerÚ»'€Đ·̃zÅ_ºdŸU¿¿ơ+,@îrÆzË‚¨@ßàô?`jfKđ?ö-ÇàƠ‹½[öL¢ îeÚ³‹À€̃¸L™¶@¡Z@_ À•í}q@h„v€rn€«‰uWÓ̀%ÿ_]́#–aç„ơŒísæđÈB‚³]…•ù3øÇ£+È”ÂÚÊ28‚[ư »@Hs!̉3Æ1† ¯x¸±³êv:ë)ûÁu·åAß$æ&x`á4̣^Ç%@§pw`Ę g.Øàq X[%m™gÜcŒ“,́Ӧ·£*}Pe£`áÍ`Çö<(<Üøa ÈN#H*ªüHJé&5ăˆ¢ûwmĂ5;'1=·Ó““¸~{ÀR?Ç™µ §×¬n¡Ÿi;! €f 07¹í‡¸`©gw:èêÇ!Eÿºÿđ†D „™f€5g+M`v¢?·K‚Øn²{%D æÆ#D ÿú̃{ΆQÔʳ̀T*~ŸüăÊ-q-1t«'jPÇ3)–ç_:|äWoƯ{ă›n3ưÜøRUÙ9ÖR‰F€HúHh…²đ€_I:©.À„ơ[wcOẨºRØ]3ăèb"àôZ†V(0Ḱk¢½÷2ØƯ‡1'Ï.àó§:8·ÚGwu “;G9r`À›ĐpÝđbB2œYW” _™ú‰ÀU|åûÀjö §ûŸ̀ÄÀ“}œ§$YZè:€£²ưÓG\³2nƒÓÎà{T¥Ë‰èTúéT¡÷¥ëåS%éKGíRÚJßM‹R ’¶¢–6ö́Ư‹f£]³Pbï9loKt2ƒ~®đØb+‰F7ƠÎ B $¤°ßk§V3ÄîóÖ́îL,÷r(]n¦ûQYT]öCD‹$ˆG–’B'PÅR±-’‹‘C!ÛÚ¡ üÊ[₫íĂy– Wᇮڇna…đ `”wQ jPÇ3€ ±‰Éæ›îºå/^6ßMö϶IB¦L¥ 0HrƒvĈÄÙ¢—«;×!¡I„¶„Ăr_¡“)dÎ7~Ó\!r²Ơ# çå/́©ÅÂöÛe¬*»§ É5N5"À5Û÷â¦ËrëƠ®3¼ÿ‹g°œhœ=q -’È|›@»Å2ʽß_µ‡ơ+dÍÀHZ):«*ÁwNĸi.Äß®œƒÉú]]?• À¥U`PX̣j…lù D|%dÔ€rb_ÉØÆ<Ø–¨è‘óYđ”¾Ơ÷É¿¤ôC×ˤ! %‰­kăÎë/Ç »&ĐG %¶¶̀÷:)æ× z¹)œ.¥kEIØÏY9*8è© ´ÁbÏ`-Ơh†¶-°µB»â™È”.WC—¢…b'· 6̀˜Œ%&›滹µÙöƠ?R&ĹF₫ÊüÜ%¤ ^Ó ÆøT <̃wg|à}Dp Q7Ú XG êøFÎê ˆ₫î₫G₫Ÿư/¾₫—ă@V P©Î*忟È £ŸDµÏƠ¼^èÄ.=6B»&pNzË}…µT!ó=Ôr˜῭9L„ëWƠÏ̀ K»^~?Óè+c€³ÍHbn,ÂXÔÀ> Ú0zÉ^üÁgN!O,œ9 @B›¹ó ¯ÚÓÚöCåO†«t×WÄv§@Đ ­z\e)X닪®Ï—è/p)~'Wly«đ’dv Q±X6d)uS™PE­oÍ•Jž~!S`w1„¶â|̣w*ưxr+®¿îZ4B‰×Ư²a¢£›i¬¥g×R<¶Ø·ÀÎi4„cÂĐNŸª +ï Éú¨l%u3f(±s"Âö±sûnäʬÎ~o³­Pb¾›ăøJZŒú÷° ₫Ø»ª{n<Äö±óè'øß>úƠ‡H+‰=¬ü9|ó?3Ü0uơ_€:Y,€74‹¿ÿ%7₫ÎsÏv~éY[Z¼ê¢î¯83ú¹F3 ÂVSƠƒ IoÈb”j%QXî+(34ÍTaK©0;ñ‚'ßw@ƒƠKW5 7/-L3̉Âb7‡„f(1Íjá§_r‚€# đ·_YÁcÇG¯×1° iĐîOëK/¬E­)ĐøêƠ÷‹«•ŸW§´@:ơ]H‚*˜€'ª(MˆÊ¯9ÏĐ}üá˜~)vLµprQ@ FH÷Ù ¬®e%áû½ °=~N?5¯ âF ñÄ,v́Øï½ă ́˜ˆ [_fà‘ù>:·j+jŸåˆ *µÍT¬(ؽk$¹¿/Ä{î_Éy>F7Óxd¾v$±k2Ɖ©28×µm'Oøäï?ù­H¢ œédȵ±́’7²ªø₫V?ïL AÀ¸dC “'çl¥>™Ë 0|“•Ơ @ ꨢ{₫ú?ùï¿û¿5K¬&ªX8 r$¬‰¶}îf(ĐÏ­p`W˜Ç® ^sª₫|Ư¶ºơ› RÖ|TTEöN\™Î́ÇÏM—ỐxơXKrœXI0̃Đ %niáà–pÛÀ»>{§æ—Ñ[:ƒ¾²¾ưi±Ö~Ÿđ­¯°ØÅØÁí)€[64”$…®bŒŸÊ6Àæ¿#s„¨ˆđöµ ! ă$?wï }ǜ»¿̃I_®Ñ C‰(GQ€ñm{pĂ5WcÇx€˜,ÇÑ¥†§W3(ĂÜ'I„Đ%|~ŸD™ÄưGˆ*́Mù2€‘ÊÄ=è ágñá>ç U˜lØ1c÷¤e {¹,Ơ¥RZ¡À|7ÇB7/>³2üaâî<aÛX„-íĐoüüOưć>°X©âÅCI_b°ï_'ÿÔñL!eø–7¼̣O~üơæ·&¯¥*%HqRreå©q[[Q)èkÇ­PBiÛ']èfè;*Ôç̣I£gÏG9¥PuGÍặ^«à–íA¸3+¤² @ Y0÷ÜB)°g2F;–øß³Àväæ₫ÇçÏ"ï­áä©3XË ̉4uëj+́`w¨ áê2Äø̀î;à̃ĐˆôS $´`–f¢ÎÏ“ˆ¿&æ‘đH h„´Ơº·–N„HÛ—×̉ 0Âïœ*ÀAøä¸̃¾D³ÙD³azfccmÑĐKáA0Px̀y1!¬ad¤(Іqx¾A„0¸lÆzïM[!h.́ÆCó VÎÂă‹],÷3ô’ *MaØ‹ưÀ¤kaD €(hÆ!’0„f*V iwlTp?1# ¯];`Đ6ùËQ""D¡i…é&07̃ÀJA…÷?*‚>P„&Â0Ä–™IØ2†éí{°kÇ\·­é†@ª –ú9¯dèeºHú‘ñ“¾Ê/¬1¸­C¦V₫Hå°+ÆGU- PAé±~®‘+€–œX±#…ÛÇ#´#‰=S1º9rĂ,üÿ́½y”eÙŨù;çÜ{ßó”sVeÖ\¥’Ta ̀È6B`·Í`»Æm»í¶[nƒ'Œî66°đ„1F¦ ,É`@ 4R*©¤2«²rÎŒ̀˜_Ä‹7Ư{Ï9ưÇ9wx/"R%„†¢̃^ë­ˆŒ!ßtắ½¿ưíïë&¬wÿ;»Z–µ₫m1óNṾGơw½cå¿úö›¾«?èoü ÛgÁ8ÆÀ8^8E@ù¦~ơï|Û½ÿ×ß₫å©j`wZHß툌‰L!Øb­K¢BÀf'a¶’jË@»±ÀîÀ‰¥àYßJ0|8— ƠÂƯ¬\d#ˆáb@”:3[: i_ÿÿˆ©PRüŒ/¤ïè¥̣¹₫™•›Ï†fE±Đ9<Ѥq÷=\Üp£³Ữec«ÅS«=½iÜ÷̉¹¸!Íz;Ø%² µZ ¤ñ °@ö¾)£¦¯_®‹Ăœr\ăÎH§R­†!¶³Él/;>ŵ+”¹è’ô<D̀/,R¯Ơxñ©#4ª!§Nç₫…/Å8M9»°ÑIIŒ!̣ɾªá.¿\d–»ö!sKQJîÅu]~.%PÉ=ÿLx14—/_{¶$nd)T ³M•gÖº̀ÔCLV˜óbB‰6ltúÚˆ²åÈŸr(G\ ®ÜXĨỡßjûäŸ=ª̣aÙö׌üû B`ă`/Ä/F*‹ög₫ÉßyôÍo~Óg_}×ÑGD›B@ä°§cRkïHÁ™ơ\_cbb¥‰;æë®SÓ†ë;1©6tÏf¥ô˜d®ßî’»,md̉»åb`tdP Ø!øÖÿNYÓ@”fº¥NùLIK¨”{nƲÑIØê%`S5ÅL=dºVcæäÚæ̀j›ôøØ³ë¬wSv¶ÖÜĐ5˜™h`{[Ôˆ““ôă„J'–ÏÉ;î˹́ d0yæ…Ăˆz£áœ `ªQsŸ±˜Ú$Qpÿ©ă¼äø4S3sT«UNÍDôRËúW»lR¯Úèû¡T‚ ("K~YŒÍ‡"‘ñL3riq娑kª”o‡¤w­r,(‰E «‹ Y*d©1Uup¿”óqqkÀ¡fÀV/uº’©u_p3µp÷\-{(âSOïøï^Å1ûơHâÏn™ñOZº™}‚q10.ÆñG4Öê$Ơú̃÷îŸ₫ê¿ûƒooFVÏxÉ[‘÷<ÆŒ©¶L×”ÜXƯàêZ ¡6©’¥é:µÉi^v¤ÉưK ´gKßl;·3Đ~…P8æ|ŸÛµĂ3Ǿ1q{G %ÿQ¤ ÀDIê×ú1Gz5RxøƠEÛ¯UÜúÙbC±ØœåäüƯÄĐïåă—¶¹ÙNP¤G*•P‡4Mœ6Ï“ä_ Øư†ÎeOJ¢J•0tºújÅ8RRŸ˜âÔ©ÓHđ-/:Œ’’¥™Ij,ï è%)ÕLè&8u÷HI¨Di…Đb˜K2Z–¡}Jïu–ÙE ̃·¥N?—ØA> AáÄo(’~jȬu+z‡'"j‘[}}vsÀ³­„+×nvZX̣—_û sơ€ó‰®Îô/DN¸ÇSó „€ØX_ÿ÷xË%ï×ñ&ựMS¸–o<ăx&S&¹rơêÚZ×0]‘¶K‘S$]j?˪KÉR”º>ëP‹ýÜùºƠ\ß0QU§¦8<3A¢ƯªV-˜äMé¯đ©Ë[kH¼uqa„ó|ºṔ8’@ •¤wơ)·¾§$³§đM¯z€×¿ü^*• BjäjkÀ™›m·ZYJâJB%H ŸÜ¸‡`ïRBin^J£Ñ₫I_Œ¨3hR¦Yîđ¥~ d®"¥à¶™ o>ÔIá_fu}ƒ­M’Ø‘Ha™œà̀z̀L¤ĐRc@ ”•>ùP†Nađ®C5‡ñ[xt¹#–/œmûó|4ñkœÖÿ­n£EÀØøc–ç8̣óÔ­eªaµ{úªCÿ₫çß₫^÷̉»ÿ́F'agæÊh™:^¢a²ª8¾ăUwñ±‹[ôµ%R‚@¤ùu¡µPrßRƒHIâÁÀTªƠGJ%Xơ'8ưÿ° ́-`Ëß6ư¿·6Đ¡pLFÆă`ŒŒăĐư‹@ú̀§?¾ññ~ä½÷ƯuúÏV•(xùZ;¨›•€ó}®luéÄ)~’Ö-À{½vÇôn’ÖÙg”ä±su¦–xư퓼èH“Ûf«øÔJ‡AjˆµñI†0ØRg(F — dyd! Ëạ́.ơ(tœBµc|ơËÿ¿Öb}ÊNó`¾̉K4gV»Ä:S,œđ°úNXka¢¢rù\,4CNVXïÄ́ôµw~”¾›Ï>ºP– €ÊùG ̣Kµ@ô—‹¼\»ÿ̃ånE‘’Ơ+qÏÀûäÉ?̣Çgjœ˜®xù`øÄ¥O¯÷9sî›7.£Ó”DâT“¦Æ+I‡p’jĐІ§Î_áE§sr¶Ê™Ơ®»¿2Æ?j ¹k¡‹iưî™›Ù́^2<ó/Ă₫ñÈm°O²å0Œ €q¼°’ÿè ë&̀₫…_x̣^ÿg̃ÿĐ}w¾±íÙüY‡”ù¡VÚ¶:1ư8¥g6©nƯ á\…q‹3l • '́́´ùÿ.@ؘdjj’·¼̣apûlZ謆WvƯ˜ —X¤È …|·(-²ơ Đ[¨đe˜¯Åî5oƯ³.ÙçdBa‡¾(D¶3^2øñ›ÆÂ\3äĐDÄf×i»ç‚@¾ă-“Í—Y₫˜R7Öù`£3µ€ÅFD¢^iØå¯$¿³?±S]»Ă?W†ô‹È (iLؽ+zœnqPÙu9[J!•`¦)ÉÑ© ưÔĐíÇ\ZƯ柼Êåk×ѽ6q§ọ̈ØqbHtJê\N:C¹‚@’FÂÂÚNk­_}Û‘ê‘Ä^¨6Tù«a-ˆ7¾ô¶O"DP"eŒ¢å¤ß/Ư²¯=—1À8ÆÀ8^ …́!¦çưØ̣îÖÚcRÜùÆZ(m¢(Ö›,E%T\¹±Ên§ăfù©›ç§Ú }{å:x×ÉJ ¤ßđ¨@H´Å`w›₫ëW©OÍrb¶ÉŸ{`«B&«§fk¬uRmØî§tbƒ–$ơîr˜/u‘Cë…y1ÀP1°g½a%Bö¨ Ú\ȦØ6(6 MD́ôS–wbªôæ.ĂÛ Ï#îß,o꽪^yD£¥Ư×,MDl4Ư¸đD•5# |Åë.†~₫VkzCÂR9P .k¿ŒÈh¯á K¶Í¢)LU©‚®¦Óëq₫ú6ï?³ÎO_ »µ–?¿$ơ’Ñ₫cª5‰ïüoD6ÊDZ‚qüÙ̃amåɉ)ç‘`M.Œ÷ ¨†’ÛfªÔB ~₫=¿ïÖ₫\̣íüu©ûŒƒ‘äŸî“üÇƯÿ¸Ç ¸eËO>s}å¾{ù‰j£=Hó.  œ]íqfµGª ±?ø2ÙǛ0§€î!Ñ) J‰œôdºïJ*‰ÙÚàéíMÎ^^fbr’ùf…78zñ¾Æzs''"(Ád% HfÍHrn½ÏcW¸²¹ËÓË-VÖ7Ø\»‰Ơ)Æ:“ŸXë¼ËORMê7;LÉ@ÊX“s¤”ă`ü PT=>yö /»ëG§*œ_ï#"¯°8Qq ›~Z!~àMo8s‹¿Ù,¹—“ÿ`ø¿îèR‡ă`/œ1ÀAûĂáỤ̂̃=¿ÿú¯yæăó“'¿^ áDʬ!‚©ZÀƠ6Ưn—8µy×£E[›;ô¹îÇÁ¸̉xˆX3dơ*¥t¨€t„Aç₫¦Ñë´[’Kד̀7+ܳØdf~ùzȽK º±¦—6º®èÄĐ›̣ë…Ùµ^/,¯R±*Íû(̣k©‡éZètßuZ!ü ÖĐÓçØ[öâ×BbmÙ¤,4"&*í~z€´‘Ø[cŒÀû“ÿ`/—Âú¬oFº}m Ö~¬ JºuºùFH#’TBgO}¾•đ¡'¯°ÛÚäѫ۬nl’&̉¾sL%N2O÷QÖ6ïöË™VF†^Hÿ·hă₫ŸÔ°±±Îö毾ï6.oơưcw(K-’œ˜©*ÉÆñăỵ̈_ßP*Z§­ü%ût₫})°\¤@ÿăÄ?.ÆñGl©;Đ·̃÷{yÿGjVÂÙ^cTÉö@󱋛ă¾ƒüué4©ª|&cëûä ÈG‰ôG‚L&6p£‚x«Åö¶ạ̈Í uŇg©4'yưé)îj„hcÙ¤¬´=ă<Ö„m(¯•‰̣z¡-ºMa32™ÍçÓ99Pˆuû•¹ÂÛJ;‚°ËJZvpÄ3ŒáÎ]ø÷³›2[ YlF́ÆÚ¯ư+R[Èóf₫Èv~ñÛæ·†ÜN×xâ^ê±~mƯºêƯSơÜ/6đ‰«Ö7¶X]¾ÂƠ]V6·éu;­I3x?Ơ¹MtvÓ~ÄeL±Ö‰±ùưÛ?…\ES´Ä©&]a²¢Ǿ¥ụ̂1óß+Áûå¤_¶›Î JkJ»ùù4"Ét#d¦0[ó “÷Ùâ©sçé÷¬¯­ĐSº½IêVP“DÁûÚXRíă½ ´ÍˆƒÅ¨«Œ‰Œz)XÜJ«1î÷Ră^ ) ““ %Y •d§Ÿú¤PlWZûÂ=]˨³X.mơ¹m¦ÊTƠ9áI[ŸåmÉs åÉ„xÖÜ'ó·̀ÖCåBU›˜ßxb­Ö6Ï>s–´¿Kª-qªư~¾ƒơ“Ôø´)Aû¹¯M±˜r­€ùzίw댰„ç¼ JưÏœ»x™₫+Npr¦Êå­ẁỢä¿̃I˜¨(û#ÿä‡₫ÜO₫ør¯Û-ö[ưë1LܯûíøÇ…À¸ǸÈÏV ¤RX¸„/¤€cÓ®ouio®(E ’DJ:ñ¨9¨Ô Èî́€/’û¤Y§•‘ïÔ3YT%‰Ö¹¾€’‚@JÇPÚë ºñÑÖ?sñ<Ơ‰f§|ÿ«`¥âÔ\J Ù́¦l÷:±f–µ²¢Ài dă‚\pËD¤¨‡ëÛÚ«–˜iö|¦f”¶,ÚÍJ;aq"¤ƠK `Áb†Xû¶Ô!统 ¤¤)f!E#Ŕtcv;]₫Ûcë<úÔÓ$IJ¼½ê¤—­uâTÖÏ6Ủ¼Ă×CÉ̃X}á$·Hú£\1$],|̣/Y+I •G üH ç“qÛlƒ. ăV/åüFÓs5±ĐLMOËRPî₫o•üËÀ£f@cè\Œc{În#¤4Ö˜ôäl]×#ÅÍv̀‘Ém,Ÿ½Ù¡Ùl`:‚8¥(—´…@y•ë¦FZ?ŸuRgf¤E†¡Ô’B_f",Ú÷¤đ;ƠR¢¤ÉÙlÖ¯üja¨$ÉÖƯ-₫ñ•«4¦g¹ûĐ$o8=P!SƠˆÛgkÜhÇXkiơRz‰)´’¥ÈE‡²ƠÂJ ™¨¬uœ§{ö8Ç'*{ʲ>ĂF7a¾0]XmÇCEŸó˜ ‡Û³¤_ơc–ùf…ùzÀz×A÷«->{}‡=q‰×Æ­éÅ#;ùÅGCZf́{GFSBªÊƯ₫A*#°₫¤ïWO¤È̀®œWB a ‰Â€(T„r_Û|à©5₫ׯªs÷B=G©A Øè$̀7B¾á;¾{î—₫Í¿¼RêäËÀèÚß~³}@÷?q0q”̀ÏŒÑ07yr®1JÇPî&†F¤øÖ{xtªÎ ßçÑK«\n H6·!ÄÂZAªªöli+K³TăȃeÖtaÿ;|ø Ï)(NÏ¢£K£×YI•!YQP̉ØXçS[ë|êŒ`bb‚C3¼ôh“…¹ifë!÷-9­mÖ@¬ IbsăP OV¨(Á•®û₫HóÏŸ"̉ÿ…{Ÿ 5†›»1ǦªtcÍf×SO@5T(é8'JÀ\=`¥£¹xc3‰æCg®Óë¸rơ*zĐÅBñ'©v~jIMÖéŒvˆ”6¾Ă÷sü©aïï—?åÏóñ‘KúBfZ̉­¹*ưn·?”LÎ.0?ƯäälƯS Üỡ‹5×¶ûnưĐ__¯zơWO₫̉¿É;÷Q +Êâ?åÙÿØpă3i· ™5½€₫Å?xü/~ĂKïøÍ(˜\ï&Ü>[ẳVŸ$5¬`,ïÄ´w¶ùơÇVè%͵U)\—~WÚÀ–ÍáV[ e¯²çúh¶ru—u¡Xt^Râ;0é»xA¨¤×Ns@º-LMO³ØŒ¸{i‚ÉéNNW84̉MœƯF'ej*¡âî…:Ï®÷¸¾32üÉ6¾˜¡„xưe»ù µ@̣¢ĂM:±ǽjk¡YQ,4Bꑤ¹¸Oœ[e{}•§–·¹tc•A’¢»ÎI0µÅª^÷µœÀWˆ̣8x߯ –®5FÖơ>W̉—B”d§‹åÄ/e–ô…G¦²ñ”C4’éÅĂÜq̣(w.ṆºNR«U9:QôfÚX®n÷s„ÄZÁCÇÖ()ªBü®Oæ} ÓŸm ĂŸMÿù¿u(ˆ€e$`\Œ€qŒcs-̀ ”´Öq¹ScéÆZ ùØ…Í¡©BJ^{z‰K³$Úp}ư(ïø̀Iw—îN‹ X!ÑFæh€. §”W«ŒÈ\÷ÄP1PÎpåb`HưÍQó1~_ä:îßJ bYLs%Â0$›lmI.ÜØ ÑXe®rêÈÍX¸Úê;óœçYi_8₫ 6»)K!÷/5PRШ(đñ«úqʹóçÙÜÜâÊz›v»N‡¤)qjöÙÍ/fù‘/#º{;¢k\¬kë B́Ÿ́Ë ?ÿèWW¥?)!Àº ó¼ø₫{ù¾W¥Ñl239A{ Ù́%\¸¶Áơz•—Ÿ˜ô²À–›;q® i¬ee7Ǧ*¼̣ ß:ÿđ?°̀­Íö'₫¥ÇÀ8Æñœ ^v|2j„¬´ca¬›·ou–&+,M„\\đÔÍâÔđøµ-Í59>UåU§¹ïØ Ëû\åÓËÖo\#0øå¡à pÂ*v¨ 0¶T äfn‰po×VJĂYaÂk·¯fœ•ùx‚0Đ ’”Ư¶b¥Ơ¡…<{!àÈÑ£œœ®đ̣ă“LT¿<N£´Ï瘪<¹ÚçcÕúu÷pz¡A£^£¢ï}j“ôæ:g/ß@é>“³ |ÇC3~…Ôra£Ÿ¯P"Üsˆ½Đä́¼bÄ·ƒa1 ¤ôµ[%ÿq¼c<Ççl `¾°úCwùéT[Ú̃ÈÅZËb3¢k₫Ç™5úqB?5 RCª] ¤äÔâ$/;6Áé¹³N•đă¿w‰81\¿|)…# –n©Ö9usAËdz‰¬U&fỮA¬́¢-ế9Đé0Ÿ×TC''oă/¿xñD|ă´Å Åh3d)ûÅü®̀&Ÿ9 }G|E8ÙëíPE $µ‰ ¾ơ«_J¤ï₫à±¾¾Nœ¤ô1½A I‰Ḿ÷óµ)3÷ÍpÂ/]Y§ḯ«‹ ?ÚíçfQ#¾üIöR _ù9$,åË`îµJÄw¾îåü//™÷^‚÷ŸÙ䟹XôÎ:ƠJH= hT³‹‡ùWd¢â|~>zi›PÉ\SÂøUÂWŸà>µ’~ó‡ß‡›ñ·Ăđÿ¦ÿÚnDñÊđÿ¸û#ăÇ-Q BkiV%ƯÄ%g+Ûư”ÙzàLLÖR—H½–®Ñ–¾Ö<~u“Ï\̃`ºYå¶¹:ßt÷ÿà ·!„ =¸Ÿùèu’N›µµU´Áuw~D)¯i³*ïƒüe=r§·ß¸ ;ä(¸L!I¤‚XIÂÔ††Ô(m Uê^kYÛé0Øl‘ˆÓÔ¡Úx9Ø/̣ÙººvÄ₫•Wd—’©$‘R¡B†U.äÔwÑÚí±½Ûe§ôâ„Aœ0(í́§¥™~v-[û$₫üư÷z‚û¬É~/s_”ÙûYÂW²€÷³R Ôg—aÄË_̣ ÷µÇókïñå]~î#XƯîBgƒ‹R‚Jä:±7̃7ÏDEđØÍƒ₫KS/‹¥!øÉư¿Ỵ̈ß)wöe4 üơr¢'üqŒ €q<ç@üÂû>ỗú½ß̣¦Ùzưë”H­Æ ¬eºCơ®¥&W[}c¼J^‘x…÷Sow<Öéóđ…uÏOpr¦Ê×Ư1Ë¿₫8B>yí$\ï°yăË­q¢IS—ÈÓ_ ớmm‡‘kÅđ bè1°<¬ñ?¢5`@ *Ù}Å©ä̃…:q<`ợ³Đë§©7wI1Ú !_–„ûWX„”̃Z†!•@!#C)É IèôôSMo3ˆÓœÑŸ!+eQ;"¿;ôó"¯Tà•;}ÊIQơŒ&ưœ<êÆDB ‚0¢Q«R©VyàXZZâ;˜cª"ØîÅ\ÛÜåç>vO=sÙß! •GZ „×Åp«††Å…CÔjN¹0цínJˆR+0îY¬Yâ₫Ú/.—F9¹gŸ$ó;.Æ1.Æñ\@[hLLÉŸûÁï¼̣]ß°üµèuQ TbDî¸Öê¥̀ƠCOU9¿–øĂ´|ÔØ¼BP‹k­.+[>~~ƒM󵧦96̣cKÀïyj“›[mv[œ[ëÇLú$‰) X̣BÀ[Æ¢;! –µ>W1`¥§É5lr…[Í×ß5ĂÚÆ­•ë„QH'i®(g¬¹e°ß˜âOüÍû »œr_‡@… ƒ0Dvû́l®r÷lÀáé:—®jqB§ ’”$ñ¿5ÅØÇ4Ó/'ưám‘l]/û·<âÏ])¥[áóßÇZD1=3Ă½K &đÀ=w1[S¼øPÍNŸ•-̃~f¹N¿µN%”T¥À†*—*vK"Eñwa„â5§gYđœÇnt²HÑWÜ.NDDJŸ{Ïl“ î}»÷ûÚ8ác\ŒăóN{ ø₫ù‰Ÿâÿï·UjÁË{IœËâ÷RĂŒœ«³Üê‘ê$‡O3Ø̉0¬…›uX…'¯·x́Ú6ơjÈ«NL°0QăE‡j|Û}³ÀI>pv“A·ĂÓË›œ_ï2èîRS™Â ^ĐÅ¡ÆÚœ ¦¥Ù#8T ä¯‹§dœs¤1h ¢Rà“×Ún×¼oébIâ jcnɰ·²Đư.¾'¾-qFz.ä*têæ÷JJ.nöHjS$†aV¾%r0¼?œôK̀} È?cîC‘́…—®–¢ÔáËbÖoA#iÎ,̣S œXăöS§xƯ©I®µ5q’đè¥5~ưgYÛé±²ºJˆ!P‚Z8oXeH §[=„€ÛÍrd~€~J'NQY ² ME6ñ7̃ôúG)8:›oœ́Ç1.Æñ…G¥ZSÏ₫úOƯ\Ưư±₫Ñ™:Q l/¶Bà´Ù»±æô\³7BzqJ ÆúY»ñJ~™!® đ‰OIA¤I‡Ù@*E=R¼ôh“j¥Â‹58>=ËÖ½G8»º‹tùơÇWÙjwÑ»ÛÔCå‘W hå‘©:ˆƠzÁ! pÀ6µÖ™ù³·è<Ưnö́ÜÆX~á£çÖƯ - c÷mĂ÷ăx—û¯ÈÙư-ÿÎAÏ#ă¸¹·EHAXº¹ËÓ)d$Ểúcó{¥>_½•ïvỎëzJÊœŒ˜-Óè·†8ƠÓ‹¼äîÛù¦{癜]àU·Ï±Ú³|äéụ̈Ă-~æZ[®­·t‹p…©•$₫ư*VH+ ¤CJI¥Rå̃ă ,ÔỨÿÜzÏ=v2I'y}d"¢â‡ÿÅO_WA t¦V Âräs9̣3c̣÷8ÆÀ8>¿ô{â£g®¾û/¼ú®—TÙ́ÅÆwSN¿|¶°8Yc­ơщ0Æ5ä|›%`QôÀ ưØđ‘ó›âÓ—G¦k4ªß|÷,•`ÓGæiu´Ú]₫Ë#7ˆ;;¨A—PÅ:a Kêƒnt )fù~ ÑŒ ±?JP˜ÔY Àbéơ9ê‘ÿR­‹-óÜ“&ØçUp+‚ă­ ÷k) Jk”€v§G·ÓEM.€ €AÑí—näDÎáûMúe¨,Ṇ̃ä…ÎàIGMtPáS·ó7¾æS]œ¡À;>uƒ?<÷ Ëk\[oa´=ÀZXd±‚h‹k©™̃ $Q ‰E5RT«Täfÿk»1½Dûç7<¾©*ÛñŸÿw+:MÙ'ùï÷ùA‰\Œ €qŒăóÚ_~ͽÿñ¥+»ÿùzs§ï´kK»¯yơmS\ku|‡çæœR»®9Í×ù(ÔØüɧ`QÀáJ9v»gØî¥H)8w£E³^c¾̣.Âb“ûÍqve—ßyf“KW¯¡}¬TX+HLyĐ8TÀĂùZzbŸ´%’UYpÈuÙ±i-œœ®`­¥·zÙÏv ÷¸ª̃gđ¹0Ykíóæd¶·~"~ˉ<•÷ơ¡³¹ÊÎÆ w]äĂ¡"é—Éz̃*¸”ùG¥w³Y¾ƠƯ—…¯*IAKáP!˜æs³Ó¼åë^̀ËMP­V¨’_{|ÿđáOÑß̃ ƠKˆSƒµº Î+æ$d²Ô«ºä¯¨†Z%¤†œ«ñµ·M°̉yv½‡± D±̉ª¤àèT…ÉZ(₫Ö₫._‰·ñ₫§6xty—+Ï ­ºñ€RLKpFfªƒĂ²µªÔMÆZó7¿ú(Z:Ëç‘BbL‚±ø—uÚ‚ƪÔ(*„øÊ.FV,÷{rŸçç¨oÎÄɽVc5ÖJŒÖXcÜëœ%ưü5ÇmxReQ‹ øDï—öô…_Û˺~ጣ‚™£|Ơ+bªªø›_s cÜ<₫C¶y×ĂO³½zƯq;r£ 2ÿ€=¶ÄqJú₫₫3WÊ(PTü­V ¨×j>rp<‹Ùʬ¬¨ÂnhÄ“ç.&{È*û#rÜưc\ŒăOüøï}c,ÓµÀnơR!¥;đ»‰æJ«Ï uîYjÀ]³üϧ·ˆÓ”åVש¶—§F’zÈTö8ív ƇBí R˹åO/[>yq“‰F…7̃3Ç·̃ënBÜÆ;]áÜÍk7—I ¢/L‰R£ t±I ­ÅÊa8YN,B p"Aqbö™!ËXu)ỹ æÿ|“¿ư D „—°•RîAFQ§̉'ĐíÖ&o~ÙƯüf#bw·è─ÁZUd<)rRá(Ä?Úñ+åLw¢æ¾ä!ê?ô£H¯Ópi³Ç¿ÿĂKœ»x™ôRë¤{t&2̃ˆÙ.È÷˜2‘£@ù•G¥̣Î? Ss Ô¢€¯¾óm²Ö‰9¿̃ó×[1û—Bpdªbç‘xÛÛ̃véë½[Ï!—‹F€q̣ǸÇó¢ £Ê|÷7ưÚ7¿fëÿyèÄô‘P¹î>Ó×OR×Q+ßơăƯÙ¼¶›pfµĂV§ÏúnLl ƒØ ­ùIK e‡’Lÿ×BĐ%Ë­Â3º»ƒ„N?áßh‡Ă³ ¤üƠ—æÛ_´@ơ¥KltOóÛÏ´¸|ơ:ëÛ»tÍ`0 ´%@VXăø >SÉ<Á¸û®Ï/(Éßù3TCÉ@b49uKàø9„>_À— ¿BỤ̈~óB¦,¸³ßs,Ị́;^aRA>+×Fb¹~ö³ĂÚûYw/sÓ'DL4j,LÔ˜=~ïzíƒ<°’‹Öû¡‹ÄÚđ‘'/c;„J¡„@#°¹’cq ” ))‘ Qt¦Ra óÄ_­D4¢€ÆÄ/:u„f5ä5''‡^¯Aj‡Ñÿ))¨R\oớ“WÖơs­ Kưc\ŒăO0,`Ó$6ÀÄÛåWè¿÷¿6] Øè$ùáHØî§N"8ÑluSB%™o¼æö)¤˜æ̀j—^¢Ỹêrcg@?q†.ÆBX‚äµ—ư5¢”7‡f­~_ߓʄ€j$ÙØqÔÿö9Í4X¨‡|ĂƯs|ăS̀¿d§V{œ]íríêU^ë’¦)ƒ~”“[MKJse@)°–¹©&BVW׉̀mK„0n¾Œ̀÷ĐŸk₫ÿăÅ_qđ ‹â–Ïç€ÂÀ'ị́ÖC%üÆ“|ưk-ơ¹Ăk›¾ûV~.‹÷‹ e¾!¬ ™h6¸{©Éäü!^ñâûùÆÓMÖ:)­N_~ø×;Ụ̂øÅeƯĐí´ têÇÅi)=ÜL nÂĐÏ–-R¹Y¯µ²°P´vo·ní¸<Ó₫cŸÎûü¿_ỂĐ>ç¯|•.‘bR¬N ëM¢ đ¿$Ơ¦sx¾‰Å¢„DWT£ˆ—ÜswåÈ̉ßxÏ7;†s˼÷³;¼ÿ3—¹¾Ù&ĐHcw_H¬$₫ÿ.C₫£N€9ª%})̣Dï$Ư¿ƒ0bqvz¤¸÷ø"w!’‚cS8ewr};Éï§*&*«­>ÆZB%rLÇZwưÎÔCqíÆj̣®÷₫V»”üË ?“ÿ-Ë—¿fÆEÀ8ÆÀ8¾àî?»i º±²öá»æíDE±ÙM W °ĐŒhD^ḅnq»¯Ù8ˆuªđÀ¡†‡@›\Û¦Çńr½ƠÉ…‚²`¸pZCÅ«…¥Œ£` Ư~̀‡]çÓ×vBđĐÑ ÏÔ™«×xƯ]rfµË Ûá=Ư¤=Đl­¯RỦíoKå`h£Yl„îiv7 €ÀB¨FYÛÂg~Õ[đ'±úgí—ưa„&ö+Zâ5ơĂ@Q¨h¯¯ĐƯmsúÄq®}̀KkRí̃e£SÇ©LrçéS„J̣¦—ßN­ṇ̃;—H4|đ̀ ¿ø¡'ù̀µm.¬nƒ±HƯ£"¤KôB VçYNØ¡ é*s‰,uøÊ¥bvv–#3 ǸMpß±YB%™­´)gW;¤Æº"R„„J 84‘jĂơí‘̣̀?¿úg\`§køàGŸíøï^‘¿œôGƯơÈm\Œc\Œă .²®Bü‡ŸùWÿ́¾ŸúÉß™¤ă=$/ ´¥—¦«q;)S¬'ÑA3TÔCGêZï8UÁÛg«H!84U¥3˜æñ»¬´c6Ú=DPZ3llEn÷Zh ä=·ñĐj¨$ư$àĂç7¨Uv¨(Á]‹MêƠˆ×ß±ÀíK3ÄÚ°Ñ:ÎÛ¹‰Đ1ƯÖ&•@ÑO%o~Ñéê*• :Ûf”–h£÷3èÛSˆ³äóø ªlö‰ï₫¥$̣É?„±:a¡R¤@W苈“w̃Csb‚ï~åqN.ÍQ ¦+‚_|Ÿ|ßgYßjqe³G¿ßEâVé2Ô(u’¾Û}Đ%UÀ²¤9ƒ?T’H¹îßƠ‰^|r¯==ƒ #&ª!SƠ —Á¤†V/¡Ÿ¸-˜HºÄ/qâX•@R—¶úyá‘I₫Z,ÍHqb¦"6Ö×ă·₫·\*%ÿ́VîôËÖ¿£÷+zׯ1.Æ1ö{‘ówửơ¿ú–ÿí7¿ù•÷¾©Hbm\Ró¸—jfªƠPщ5R@-TLV¡go?»̃¥—¸D¾̉N¨…’ÓsU¦ª ͈D[VÚ1Ÿ¼¶C»Ó$E!¾cđÛe‡@¿V虃vôœ…,í I$‚O_m!…àÑËœZœ@Éw>¸À.M#¬å“WZüáÅVõ`¾údJA¤Đº@h[À¦ÿØ̣·¶ÿ™^©0Đ#ÅÀ8ÆÀ8Æq`÷_ù¯¶ƒ«Û1G'Bv•&ÖÙ®4$Ʋk‘bÁ'₫›í˜•Ư879Ï„vDh}Ǥ–Ṿékm*`¡±ØŒxơÉ)ÿPæùí§7IµáÚÖ.©v́ư¼ mñ².h+¶0(Ê¿̀Ø}nưÍ ₫œ¹¾É™ë[üV=âö¹_{jÅfÄ÷¿êæ•G?•ÜólÚđ׿ê(±6ü§]á‘ó7±I¸³í®Ÿđµu&;fd–_6}ÊWE¥ZçT~]/’0p‰? $•PQ‹µÉy^}×̃pÇt₫˜Œup₫ơ>Ë-—¸ă“¾Z½„V/¡—NÎT99Sc§Ÿ̉¤̀Ö]÷¿Ù‰ư†Cöç`I5ܳX'‚÷Ÿ¹™ư­É‘¿»´ô1#·¸ô±ŒŒ&ưq̣wwăÇsF¤/ Ôœ¾wö?ưâ¯üĐ·~ÍK¿o³›ØÎfc-•Prx"B视­^ÂNOÓOM~Pg«\²tù*6wư«(wxŸ®R DÎîÄ\ܦƯ‹ÙîÆôRCRûÉøÚw‰?ÎÄ]°yaPÜ?¥]sr;ØÅÿùº“L×B̃ú®ÇH´¡»ç3H­_!óôæY, ˆ£Óçàøe₫Ó¢PWt» $©±|Ï+sr®Î¾óºƒ”´½æÆ<ÚzÄ'+F™ûÙơ4jT Ăûů¨TBfêæ§âÏƯ?Ÿ¿B‰/ ;±æ̣VŸ8u÷«dá0˜¿Î#+ª×ñ+!¸}¦ÊâD”¿O¬tèôÓ¢¾öâISƠ€»ækV))¤GˆÀĂIåîPê₫wümkä¶í»ÿ] öé₫Íøx#ăÇsAöE–ÏŸÙ₫ƒßÿàï@Ê^M€ra?.ÆÀ8ÆñyC]É`óÆÆFkçzl HÛOR‘íXÏTCV¶;lï´1ì?Û¨ˆ¨Ráǧ˜œ[d©rÏ¢cLï4W·û`ƯX™Oûp1 ¤›*@Øé;¡•PI‘¢Jî_jÀRƒµƯ˜ö åÜj‡ƠNÂæn+ƯX!̀PC̃]j¿:†-¨öqík- ó´.é¼ HµS4tÉj/ÁÄ#)÷Kq a›" ïó|AÛvXŒéÀ‚ijî#}W KÔAÈf/CR2¤¦€ûsE>đBB̃÷Ư~è…y"%2£”LÏ̀đЉYǸ7™n6¹Ó˜öÀĐOµG¤¬çäPAdíp̉Oµ%1–H M„L×B&k!µ@đäÚ€Ç>{~œ̣Ø…kô{=ªh.¼‹{LS $»}PîÍ‘æ!’âüøOƯP*Z§ûíüÔư—“ÿsAÆÉ\ŒcÏ9é4Hè·>̣È>pÿµ©fă¸îI ·Óüĺ½‰6 Ö1¶½ËÿXß Ñ\c²"¹óè<•æ4_Ç4/92A¢]1pa³º‰¡¢dÁ ÷rm΄¤‡`cmt¶…`g  ¤`ºpªYçèT•ƯX“¦†_l§†›Û]ÂÀ C BpÈủ®Ưè$h åe‡xÛÇ2A稽ᑑ.'‘/G”çƠ·èÿ¿À‹ÄP ó+2n8¸^I‹Ä0SQTÉÎînîΘÿHçí}'†UøBßñ+ ª>I‚¬N2?;Í'¯wÜ('(ăĐ̀Ú^æ"=îc(*SóL7"¾åEG¹iÿ=ưƯ!8Ùµ!¹¾Mú₫ưNµA[h„’{ë,4 ÿ»_ç‘Ç`Çl¯\§Ÿh’$%NRb­Ñ©vă ,RT#wܦë+rÏb“sk]´‚f%àÈTÅ®¥ˆ'Ï]ŒKMyv«î¿Ùÿ­ÖÿÆ1q0Ï;ñ律Bˆ_₫‰₫ĂŸúû?pmv²ýzËÚF¤Dª5›Ûm7O5±ÖÄ©v̉¬>q¸™«Î÷H)ÂĐ ²l=̣>ùx•Æ̀"ßöàa^|¤Éms5îX¨s¥5`w°Ư7(á`YW ØÂÁMd³lĂvc—Ü?}­ÍdƠy´›ªpÿ¡nđÁs[¬́Ǽöú¤̃&8KènBjQkơgœ%‚‰éÂPñÊ;ó†Ó{÷ô—·û,ïÄ tF((âCäÅ\¡©KÉßà¶WnŸ­qb¦êD¨„å—wxïǧỠ¥¿~A¢‰SWĐÆ‰&NR7̣×wf**Gæ”"R‚w|z…¿ơÚ•P–™Z`ñ?ü¶Ë₫íÿ¾U*¬á¹Í₫Ëÿ̃¯ûß½ǸÇ8₫XEÀ(  ±6̀Ă—Z;ß0=C=’b®r}«CÚÙvÉ× ŒŸµk]̀È¥Hílt•’ô¥&LÜŒ7R0Öôº—ø…ë—˜]:BT­̣–Wa¦Va¡HÁå­±¶tă]û”È,ƒR̀{)Ưc‘Àî@³Ó×ltB%8»ƒ TFdỏ÷Ÿ¯ ¯IÁÜDÄ©¹ưỔí÷¹´̃æ—>zKW¯ »;ĽIªIRă6̉Ô%|íL‹´ÑCÜ)]Ñ¡µ̣Eåâj c-“Ơ€TǸTŕͮ}ụ̈.ư=×Ùÿsé₫GÙÿăǸÇT”·²Cª̣₫é₫ôË~ùg_zÛl}AËŸƯ¢H’Ô ¥[ïË\Ö¬±hkĐÆ ·‹†Äï‰TĂ½¡RÄË׈Å]¾À̉Ñ“LWo~ñ!&kU­^Êî@ÓSÜ"sè#ß»–y)’y2ˆSËùơƠPR‹$‹ơ(|óƯs RĂ…>k»}–·ûôbÇÓ |úÑƠ4¡*âD“híH€#ZÙ[ŸísÄÀ8₫)C² ”{_É]KÜ6WằƠ*QÈL½‰”‚‡9¹8Éá‰Å†SФ†AêÆ-Ë;Z} %r_y{kN‰È—̣T%ÍHq|¦ B°¼ÑæâJ‹÷|ö:Oœ}†8NHÛë$âT»n?Ơ¥¤ïˆŸn­4+ú²kNb… L…BµLVÍ(²€øÍwưÊêo½ë¿ÜÄ™₫è̉ßVúvÿcèă`_4 ïT¤RöÓïû¥G>»ü¯ô×MÔ°ÀNß1ñ³Ă>Ơ¦èüµ!Í:³Œy¯Ư =Ơ ¥A¦.¤ºPq 4¡R\¿r‘U%ù‰«ËZ˜çCu/Ị̂⣓@…ơNL76N°ëôÚ°¤-àæ|­P Ǵi¶º)ÍH²ĐŒ„à̃Å÷.Ơ¹ÚĐK 똅zÀí§îÀ º$ºP 4₫IíÀÈŒ¿(„€í^Bœ·+oíóđ­ö-¶Ø~ÛïØ+„Ü{t–©H0UQ|Ơ='8µ4M¨'§Ư~/Ñ´z)«í˜ÔÚ§ ¨¤ Rï£üBḱ81–j(YhDÔ#gÙÛˆ.lÅœ[Ùåág®̣ɧ.ĐîvIv6ă?II´%ñP‘ô­#ñ•Öó§—ñ2²b åH‹ÿ{_$IuŸù½÷2³®êûœƒ™azN  Ù²±BÖ¢Óeëpl¬Ö–¬ơ.ËÚ»+±ëCÈÖîêK!…6Ë:ÂÂH€BH˲ ƒÀÀĂ sÏtOwÏ ÓguuUåùö—™ơêufu=Mô¾ˆª©>ªº&3¿ïw}?Æ@<ŒôäM -̣̀k£îư?~¤„úÂuƠïRÑ Ë«ưk! ¡€ÆøBø¾À<|bôñ[wôßáùœsBI¦ĐÊÔ²çFØø%"eæóúÅ4̣Dç"M+‹×bKWĂ­w›ŒÀtŒÔNăôA®PÄáƯhoïDwG̃±NÔôgª.¦<”GL·84¤‰£ÆDʶÇ1:cƒQ Í¢hϘ(d(Ö‡Äp÷ï!T̀ª£¾́f¹—Ûú́¼đ3pư ù/ă%›^u>€ÁÎ<àº-kĐ—¦²íc¶êbªâ¢l‹ñJ×çá4`(Û cW>ˆZ¾çs¸\̀é,tæ ´YÂïàù&§:~ûOÁüBS¯Ÿ…çºq¤ïF)~‰ôƒ .đê«§yăfÁÈåĐ 0 YËD.c!k™°LÔ.aïÈ®ßØÅ}€<»ÿhíéŸ>đzư Ñ¿·Dô/oL[ÿ«É_c‘V×Đx+Ç £±!0 »fëßøÎ÷₫äöwï₫èëe‡{~@öŸÆă‡Ï£Z†k×àq7z>S©^Q…ÍXÆi]Bê®oñ7&ú 1N A&›E1ŸÅöÁvtô aG_Ă=Yœ£â86Y!eۇŢ‹vƯC$8¿a†+] £@o›ƠđáL-¸8[¶ăKîR$úÛ€s kP±Nx¯×”.++qqàMÏ[ CEkÑ×áü7SñP²EIÜñ‚º TäfgFM“ơô¾ˆøAÂưd ŒA1ṾprÖÁ©‘Qü₫Û¶₫₫]ơƯk‡²ÑÅ?sb¼8>Ó'ƒ°y  @Ü‚ú"¹®*GÊ‘µ- Å@T`as™i† „C6“AÁbX»ff¾w\Ơƒ Â(Û>OUpa"dÆ%‚ºàcÂí…@Ö$È]ym â–¿g…KHƒ?¿à—/0Qr@Wñjp`CW6^ í¦+ª®¹ª/–5%}|áºæ¨‰/êâ÷ư°®¼ F€­}yŒ"đđk³˜+ÍáàÁƒ(Ï—Q®TQ³kblÏóêØ¿áù‚ØÍ‘K»-“>%B€̉°̀e†©~Ë0„ ¥V.5›¶bíĐ nỮƒKz F ©û ÄÙÈ_@îđÛÜ:³&ÖvXq¦@#Ađ„Dz¦$F̃'+nد̉°±1à$&ư@2kj³:szÛD|uU×ÇK/¿‚̣äYØ®ă9ưhtÏóày¡}s„ˆÉ÷7’>‘× S°p¹aˆhßn¦ƒ6`÷W`]‡‰Ûvöqäđ”î¹û?ưà;ÿưœï¹<Ơî×E=Ơ/oükưGߟdÿ«¡¡€ÆÉD½tQ  €¶Pt†·ù{¾ÿØg6nÛü‘+zy>—5`¢äà>7Æ+3çÉÂB9¼@‹L€­ö•2çuă–ÈO ¡D¥ô׿a‰À2 Ñ;`0X¦…w\± ¸¬Ïa0³óæª.fª~l‰– Äẩ.÷K{r(dOU1Sq›¦Á›=¹Z%Ä‘øj]v,F°½?só&J­_¢È¾ñ’ƒpj´ÁP»FÖu Ós§fđÚù9Ù‰S°QÏw¤yư¨‘Ϧ8¦x܃"‘¾Ồ'“>c,\'̀`˜&3`2&CGï ¬l–_¹ëṛÉ=C8?7Wå/Ÿ­’'ÿßÿ™₫oúÙQ»<ë¢ÑShœ¦qP¯óGÑÿ\Bô?~=j”§tô¯¡€Æªd"•²ºtB»9Ú´(|뱿»¾Ăà7ïX—)¶‰Î¯Ÿ˜çÿ|à9;»× Pµkở€Àơy­ÉuÙ@mÈRÄ€Gl¤̃/`³!JfåQ́êÁG®ÂÆ̃‚b†áèdœs5/ ôĂqº0ˆ4@̃bXß™I ^~öË%üƧøªêr  ùÊ„ˆåMW®) cP8·Poz ›?yØÿ!»̣¢ño hÁ¤Ưy¦æđĐ+¯cfv£ÇĂ­•Ă I_¤ø=_́€#{ûxJ¿8vÂÂLŒ+ŒÑza™l]Å6tuùúáäăï¼m ˜ơfçæ¼‡1âßưo>sjêäÁyI0«G€¯Dÿkÿ%)ê_ní?Ê(hhh qÁ³,! PÉ>Ưá}gø¼  økwüÑÖ́Ckß³{G¾³¯?ÓaEƠó16r ǧkpµZ><ÏË\êBÂ¥ă=´̃¡ÍÂñfX.0 ‹‰~ÏàX¦‰;v"›oC›I‘·(ÎÍ;¨¸Â8ˆ„Q©î$àœ`cwÅ Ă±É*æj^¼Røb˜ç'̉’øu²2¯₫¬A±k¨€óe£³¶°ä•Ö3û°Âå=ư íY„+„+• Ú7ăáĐá#đËÓp€Ü/ÀIY, *v̀›Ùz;‹Ø̉›Ă`?ñ,Ë¶éª “Rtå :¿€yÛkØ­zªÿ„nØlíQP¯äÍ2 ¯ÿºú> gP\¿¡çËNÏÚèi3Ñ_0‘1·a{8…—OAy¡‚éÉób„4$ưȆ7™ô×ơ£7­DJCj#Ÿp% |ü¬>́̃¶{6ṭ®₫5ä²<*üÑ#³ûŸ}¢ôêøLđÓ̃7Ă«své'Eû@c‡¾ư«ÿe)ÚŸQÈ¿ Q"°Ă›ưC“¿†«q©½fB ]ÊD÷Åđëùđ{­đgº  æM·₫Vçí₫hßÍ·ÿîà5ƯÀl-@Íơùô\‰ÜûâY¸v³“ç@̓¾7ôđ®îè^é¦=â4`Jó “MF%A@ÑV(`[ùn¬ïkÇ;/)ÂñX-găO†·đÙ¦¼7ß—*„\€KOÖ¤ñÅÓ%ă%#§Çpàè Tmç§fàÖÂ9ưp:Ä‹›D}Ñ*Gú\!TÆö@À úĸi°°1T¬÷5-tcçöÈY>vỮ×ƠN²ø‡ÇŸ_8t`åŸüYéÙŸ?QŸœ°›|4‹WđÊÑy’×Dæ áMưîKù§EÿZhh ±êYÈ…Q~$:2y) `…?oFÙ4Wè°z‡Öf¼ùéà›?wM¡§ß¸ecó¶ÇyÀɾ±9<¸÷(œ…9pÎ…ÑPX¢ )¬ HÈb€¢%TŒ2R7wɘ ™0Z̀f,ä²\»ơ¼o× >^øëIDATp ÏèT|± ²n½ÿ9g8̣}k‘ëè”Ri`¥.$ÚÖˆp0 &Ávváµ±)|ÿ÷¡²PFi¡‚jµ†íÀö<±_!ôưx"$3=¢Y0ÆHÛcBĐ”±0Ú½" FA39lÚzºº:ñ±«‡ĐÛÑÆ-“’צ9ÎŒŸö¾ôïyñ©ÇæÇ œÊ¼Ÿ ñ̉HŸ'¿¼æ7"oÆ?rư¿¤Y"GGÿZh´Â±D‘Ü —D@Q"UdĂŸ1¥L€zi€ V6gBi¡Đfüèå‰ënbÑ5?}b–jWÜ›ÖOd ™Oñ«ĂŸưø{oÚÔÁo¼´‹›×ăëOq×uÉÄÈ Ô<̃Đî° 'ŒÊ~Đ˜aA± È£¦”Ađ|&l_l§›.•173×ăp®çÆ5éỚ{#ÜLê>ö4˜ „‚¨fFáTEbZ É7RFYHÄ,ËDîøA´À —±ïÅ @€ªí f»á"Q̉ Â%Rq#'  ´̃ÇÑP׌ $²7 –ÉĐ1°–ẹëv_E~çÊ^à¾çđ£“5zÏ×¾uî{_ºkŒû^L¦¾ç©Ç·ú8îÓH_¾É₫\‰ükhÿ‹¢ư…ô“̀~¸& -4̃.âW7RÔ;›£T~ÅËQ’\ÿ̀I@ÎX’Å`ØåÙê7ïüī߼ó̃gïùή—ïéü—wó?¼é’0coÄÿ~~ŒOO¾NææË¨Öld|?. ¸—ö¹× ^¾²\˜Å€“Æ1}ÆÑV,b₫ơqœ; §\íz°ëÁó½z]:±R¬TÙ—ü´î¤(¢g ƒ$¢'oRÅ"2 ụ·`&:ÚÛëa¡fƒ‚ăÆ&>¾ÀçÁ÷/‹JhT¢ zꤙ?™Èä²è)äĐÑÙÉ/Ưv9ùÔơë€LOO»GNŒ÷?µ¿öÿî_Ô&Ç+h̃½ŸñË„Ï_ïW—û¨[₫ª̉­,e¢zZÔ¯ë₫Zh´TÀ—£u†‹#%•ü£(j”3–$¢S3„öÿđ/_@₫-@₫˽́^Ûnâ–=—ç?÷®ơÖtm^8]âg&ÆÈÁ‰lÏÇÂü<2œĂơ)¼€×çÆC³˜xôǯz×ÄJcŸ# €íz¨Ơj¨9ȸ.\ß‚FÛàno4¡Iư¦Äûæs ÑjJăz€´p‡¤ÿ yc¯• &Ê&×CÆ21W®¢ÄBœ€ƒ“¿ơ‹¹}Aöơ¥;dé›á¬>!™|}==ØÜׯ»‡6[¯Ư‚¡,ÈØ¹óî {÷VŸ-áË₫…ññưÏÍJY)–Büi }Ñ1î+Ä‘³«d¸\%ê—ÿjh´ÿ­H‘$ l% çư5´ĐhÉ,€êméë²pÂÈ?€¢>YXÊ-* 4ˆιœ`_ü½ßx€qơ­́ÿíÛ̃ÛùÛïưµ®+7nνwKö.£æùÇ̃‘ª đ]Ü`"íÔ†¢°ÑŸH%s¡ºM- =x®+͸.¼X$dIÏ×…Ạ̀®ëo5A ư‘´,D¡Ëëxâóê ˆ ‚°­ ˆ=₫Ï̀UđƯ½Ó¸¶XŒ‚Z)ü$ ¡3_LüQ÷~´|'́Ơ°²èÄ Ưèêîå;¶o%;º™˜«ñçûÉ̀‘Ó¯û÷=ôđÜ??úÀ´t¼K>¢•Ç÷äăXMï{RÔ/¾Lü$T gj)ä/gtô¯¡€Fˈ€ %DU…At̀†ºˆđ³Ê}’P³IMƒü¥G8ñ̉£?œø₫wơ_ùâ¥m~đ‡_ø›-½í̃½©;6Ís·V%¿8=ƒ}ÇÆay6|Ÿ+wdë‹Ụ̀h´ŒQƒˆÍƒư î́YøƠyˆ%A@Àƒ°3ÇÎsÍ¢ÿtr_™ïY K Ù]1‚ºX‘Ê"I™ ÿp ß ÅQÖ¤à<xB(8ăq¹AlÜ‹́xĂz>k“MËD®{7l¿—¯íDgO?¿l¨@f8ÈC÷ÿhúñÍđÀC³O>üÀ|;̣à'H×Okäă ¤ë7!ư¤h?é–&ÔÇ×₫}èÔ¿†-* ‰OúZ€ÅP¶B₫̣}̉s–" LEIbàĐ O?ôÂSSÈÓ¿8T+d-́ز)w÷×¾: í}¸|Çtänß½uˆ àX äÜûÀ̀ƒïä‹{Ÿ©pßj¥éˆøỉO‹öƠѽ¤F>¯ á» ‰Ûđmöuùæ!ƯêW“¿†-•€’ ˆê¢‰¸k‘g”ÇÍÄƠ$3 6Rlß“¼€₫üÿö“Ÿüd棟₫׃ïûäç׿sMŸûơ"\/àó• äoŸ‡g×0snÔ²âtQ£·Á»7¶áÇGJ`^4“ç`Œ‰ZvU¨¼TïÀâûU₫Ï^âưG‚ ©d Œ0(ƒÁ ÀÁüèk0®Ư…l.Ô¬pø½Â¡1$ư\ù¡Kqé`/>uĂzt¶åAL‚c³ ÿôÔ+µ¯|ñ®Ñ±SÇíÙ©I¯Rñd –Kútܪ‘¾Lú^¡'»* äÇi7™øå,„&} -4Z: —’¨˜t!:"mḰ­„¨?I¤•¬„¬€)ħc'y_ư⿯₫í_ưçÑZeÁÿ̃?¸®Ø7”ùàe]¸û7¶pJ@öoÂưÏ‚»P INpJ[FœFŒä²™xTÎ`\Ïf@ÿ>È¥bÁyks —0¦Œe!cYÈf,0€Q g 9 ơ@2Ù®ôôôà›/Ăåƒmœ„*ăç'çđgü™Ïưô¾fXık’W)&́5›Ơ÷R¢ư¤¿Ñ;)¤ocq «d¼Â÷”,DÚ(¢††-+äH‹*"À—D€£ÜhLñË™l(PŸ32Ñx¢€ù¾çù Ÿ|ÏeÏ÷MŒŸ¾ñ77‚«×é5̃ƒ_L”±o|Ÿ9}’¸^€¶Œ0MímpÀ0Lä2Nh`ă§ö¼™[ú¹ÔcNÉ·¬é¨ï‡¾û¦–i ˜9°¡§ˆò0` ß·7^{%̃·­œsÎ}—ï?[¡wÿù_=ø­/•ÉÏ÷kÉuü¤¨_m “ ?Hˆô½âH]vñKêÏF¿ÏGc]_áû „¯É_C ‹B@̀䬕.¸Lºg’`XÜơ J é/§_ÀP~¯ÚˆdƠk0 Ă´øÖ-Ăä†µÙøûN°Ïœ>e?ub*ø̣₫t|úä$ÓæR¤ŸæÊç"9ůÖê“Fø’÷Ơñeà …ôUgAMüZhüJyµ0I2Q˽\ûÏ¢±d$L,=EĐ`4Äë~đä¿üí{Öw§c]Û¥]¨0¥'|Ñe¯ø9'~£•ÉÑá+wå}ï":¤AB€ù™ùàĐ—rÙ,yåÈ)çÛß₫öù×}lơry¤Ÿ6«¯FùªAå/·“ßY‚ôUâWùü&o"x44´Đ¸è¿4AE{T")=³,ä›Ú3°Ü±Â¥¦ä÷líđÎbÍqÎ HèW_OS×Û̉V́œ‹²¹|½æ]·´»ËÁyËÿ—×gûĂÿdJ17=é½¼÷©r&›£çO®¡^BJôÛ¬{_&₫åÖô”hßNrăŸü;’^ĂOx/jBøzÄOC _©c0I På±, 4nŒú7ÿ5› È,!,,]"Pß›:w~!Ï7¾Œs›\¤×£¤Æ·´†>™l=$/̃ñ°¸{?mT/©‰/©™O}­ !û Äo Ê×@C _i!,îËTÉ $5Ê„¾\£!uẢ†B‹—ÉïXœÆ&úœ_¶˜ifÇ(Q¶§ÿR®|i„o'|³q=/á½øÊûUÿMúZhh,ƒü“²ª(`Hn ”ÉÚRÁ1’H_WL•÷B•÷NVéü#oàsm5̣OJơ/ƠÅï-AüIdŸôœí«¤¯Fúj3ßrù’ˆ^“¾†)Ǫ́'°Ü)Y ¨µ|3!º_ªLä-  ¦ˆHœ`YÆ×Zù¼o6Ê—ÖÅ/ÏÓ«kv—ă¿ŸÔà.Aúj”¯®å•³ÀbO MöZhh¬PT»T¿€,d’VưÔú¿j4””Pû $—Á¸GaµûHÊçs1@Mùé>üBü;ô5sç“}öƠ4̉¬¾JúêŒ~³Í|ô5´ĐиÇ/IÉ Äú ‚ I È‚@\ÎÚg f.t Ùç‹H¤Eưrs_IÏR‹v̉Æö’ù̉º÷›5̣é™} -44Z(+@R²i₫I®ƒi®‚ѺbƠ¢X- D¯u¡³¤Ég ÅÆ:o7é«€¤₫$̣·›€¤¿¤f¾$̉÷¢|tËañkh ¡Ñ"Çs̉eˆµW@Íê!À” Ä…l$)Ñ¿Lô´…ÿUrU#ÿ¤”¿“ mÙK›ƠOôùѾ&} -44ZøØ~3ÄiFCÍ,ˆ­&ÀH zÎC’"2’²­Düê iY¤măKj̃K"~¹Y0‰ô}$×ô—3«¯I_C ‹à_H3Ji›UŸµ°̉€f©ÿ´r@«ÿñ„çˆ&¥ÿŒơç©¡¡€††Æ/ùy®É^CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCăWÿ¯´G9éˆIEND®B`‚cutechess-20111114+0.4.2+0.0.1/projects/gui/res/res.pri0000664000175000017500000000010711657223322021121 0ustar oliveroliverRESOURCES += $$PWD/chessboard/chessboard.qrc \ res/icons/icons.qrc cutechess-20111114+0.4.2+0.0.1/projects/gui/gui.pro0000664000175000017500000000125211657223322020333 0ustar oliveroliverTEMPLATE = app TARGET = cutechess DESTDIR = $$PWD include(../lib/lib.pri) CUTECHESS_VERSION = unknown INCLUDEPATH += $$PWD DEPENDPATH += $$PWD macx-xcode { DEFINES += CUTECHESS_VERSION=\"$$CUTECHESS_VERSION\" }else { OBJECTS_DIR = .obj/ MOC_DIR = .moc/ RCC_DIR = .rcc/ DEFINES += CUTECHESS_VERSION=\\\"$$CUTECHESS_VERSION\\\" } QT += svg win32 { debug { CONFIG += console } RC_FILE = res/icons/cutechess_win.rc } macx { ICON = res/icons/cutechess_mac.icns } # Components include(components/hintlineedit/src/hintlineedit.pri) # GUI include(src/src.pri) # Forms include(ui/ui.pri) UI_HEADERS_DIR = src # Resources include(res/res.pri) cutechess-20111114+0.4.2+0.0.1/projects/gui/ui/0000775000175000017500000000000011657223322017442 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/projects/gui/ui/timecontroldlg.ui0000664000175000017500000001741611657223322023040 0ustar oliveroliver TimeControlDialog 0 0 317 367 Time Controls QLayout::SetFixedSize false Mode false false Tournament time control Tournament true Fixed time limit for each move Time per move Infinite thinking time Infinite QFormLayout::AllNonFixedFieldsGrow Moves: m_movesSpin The number of moves in a time control Whole game 9999 0 Time: m_timeSpin Time limit for the chosen time control 2 0.010000000000000 10000.000000000000000 0.010000000000000 Time unit for the time limit 0 Seconds Minutes Hours Increment (sec): m_incrementSpin Time increment per move in milliseconds Maximum search depth in plies (engines only) 999 Plies: m_pliesSpin Maximum number of nodes to search (engines only) 99999999 Nodes: m_nodesSpin The time limit can be exceeded by this many milliseconds 9999 Margin (msec): m_marginSpin Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() TimeControlDialog accept() 248 254 157 274 buttonBox rejected() TimeControlDialog reject() 316 260 286 274 cutechess-20111114+0.4.2+0.0.1/projects/gui/ui/gamepropertiesdlg.ui0000664000175000017500000000737011657223322023525 0ustar oliveroliver GamePropertiesDialog 0 0 274 212 Game Properties QFormLayout::AllNonFixedFieldsGrow &Event: m_eventEdit &Site: m_siteEdit &Round: m_roundSpin 9999 &Black: m_blackEdit &White: m_whiteEdit Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok m_whiteEdit m_blackEdit m_eventEdit m_siteEdit m_roundSpin buttonBox accepted() GamePropertiesDialog accept() 248 254 157 274 buttonBox rejected() GamePropertiesDialog reject() 316 260 286 274 cutechess-20111114+0.4.2+0.0.1/projects/gui/ui/enginemanagementdlg.ui0000664000175000017500000001167711657223322024006 0ustar oliveroliver EngineManagementDialog 0 0 399 375 Manage Chess Engines &Search: m_searchEngineEdit false &Clear Qt::Vertical QSizePolicy::Fixed 1 5 Configured chess &engines: m_enginesList &Add... false Confi&gure... Qt::Vertical QSizePolicy::Fixed 0 20 false &Remove Qt::Vertical 20 40 QDialogButtonBox::Cancel|QDialogButtonBox::Ok m_enginesList m_addBtn m_configureBtn m_removeBtn buttonBox accepted() EngineManagementDialog accept() 383 305 490 225 buttonBox rejected() EngineManagementDialog reject() 460 305 490 272 m_clearBtn clicked() m_searchEngineEdit clear() 424 27 361 26 cutechess-20111114+0.4.2+0.0.1/projects/gui/ui/newgamedlg.ui0000664000175000017500000002353711657223322022125 0ustar oliveroliver NewGameDialog 0 0 510 242 New Game QLayout::SetFixedSize White Human true false CPU Qt::Horizontal QSizePolicy::Fixed 20 0 false 0 0 false 0 0 Configure... Black Human true false CPU Qt::Horizontal QSizePolicy::Fixed 20 0 false 0 0 false 0 0 Configure... QLayout::SetDefaultConstraint QFormLayout::ExpandingFieldsGrow 0 0 Qt::LeftToRight false Variant: false Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 0 0 Qt::LeftToRight Time Control: 0 0 QDialogButtonBox::Cancel|QDialogButtonBox::Ok m_blackPlayerCpuRadio toggled(bool) m_configureBlackEngineButton setEnabled(bool) 403 82 420 113 m_buttonBox rejected() NewGameDialog reject() 457 232 479 137 m_blackPlayerCpuRadio toggled(bool) m_blackEngineComboBox setEnabled(bool) 287 84 388 118 m_buttonBox accepted() NewGameDialog accept() 269 232 260 111 m_whitePlayerCpuRadio toggled(bool) m_whiteEngineComboBox setEnabled(bool) 42 84 79 118 m_whitePlayerCpuRadio toggled(bool) m_configureWhiteEngineButton setEnabled(bool) 127 83 181 118 cutechess-20111114+0.4.2+0.0.1/projects/gui/ui/gamedatabasesearchdlg.ui0000664000175000017500000003104311657223322024255 0ustar oliveroliver GameDatabaseSearchDialog 0 0 394 296 Advanced Search QFormLayout::AllNonFixedFieldsGrow Event: m_eventEdit The name of the tournament or match event Site: m_siteEdit The location of the event Date: m_minDateCheck 0 0 Enable minimum date false Minimum starting date of the games 1900 1 1 M/d/yyyy true - Qt::AlignCenter 0 0 Enable maximum date false Maximum starting date of the games M/d/yyyy true Round: m_minRoundSpin The minimum round ordinal of the games within the event null 100000 - Qt::AlignCenter The maximum round ordinal of the games within the event null 100000 Player: m_playerSideCombo The side the player plays on Any side White Black The first player's name, in "lastname, firstname" format Opponent: m_opponentEdit The second player's name, in "lastname, firstname" format Result: m_resultCombo false 0 0 Search for the inverse of the chosen result Not The result of the games Any result Any player wins White wins Black wins First player wins First player loses Draw Unfinished Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox m_eventEdit m_siteEdit m_minDateCheck m_minDateEdit m_maxDateCheck m_maxDateEdit m_minRoundSpin m_maxRoundSpin m_playerSideCombo m_playerEdit m_opponentEdit m_invertResultCheck m_resultCombo buttonBox accepted() GameDatabaseSearchDialog accept() 258 290 157 274 buttonBox rejected() GameDatabaseSearchDialog reject() 326 290 286 274 m_minDateCheck toggled(bool) m_minDateEdit setEnabled(bool) 99 91 177 91 m_maxDateCheck toggled(bool) m_maxDateEdit setEnabled(bool) 255 91 333 91 cutechess-20111114+0.4.2+0.0.1/projects/gui/ui/ui.pri0000664000175000017500000000041311657223322020571 0ustar oliveroliverDEPENDPATH += $$PWD FORMS += engineconfigdlg.ui \ enginemanagementdlg.ui \ newgamedlg.ui \ gamepropertiesdlg.ui \ gamedatabasedlg.ui \ importprogressdlg.ui \ gamedatabasesearchdlg.ui \ timecontroldlg.ui cutechess-20111114+0.4.2+0.0.1/projects/gui/ui/engineconfigdlg.ui0000664000175000017500000001521411657223322023126 0ustar oliveroliver EngineConfigurationDialog 0 0 480 400 0 Basic &Name: m_nameEdit Co&mmand: m_commandEdit Browse... Working &Directory: m_workingDirEdit Browse working directory. Browse... &Protocol: m_protocolCombo &Init Strings: m_initStringEdit QPlainTextEdit::NoWrap Scores from &white's perspective Advanced true false Qt::Horizontal 40 20 false Restore the default value for each option Restore defaults Detect the engine's options and supported features Detect true 1 0 false Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok m_buttonBox rejected() EngineConfigurationDialog reject() 336 222 286 196 cutechess-20111114+0.4.2+0.0.1/projects/gui/ui/importprogressdlg.ui0000664000175000017500000000660411657223322023575 0ustar oliveroliver ImportProgressDialog 0 0 330 130 330 130 Importing QLayout::SetFixedSize 75 true File name: Qt::Horizontal QSizePolicy::Fixed 10 0 75 true Status: 75 true Total: Qt::Horizontal QDialogButtonBox::Cancel m_buttonBox accepted() ImportProgressDialog accept() 248 254 157 274 m_buttonBox rejected() ImportProgressDialog reject() 316 260 286 274 cutechess-20111114+0.4.2+0.0.1/projects/gui/ui/gamedatabasedlg.ui0000664000175000017500000002703311657223322023073 0ustar oliveroliver GameDatabaseDialog 0 0 616 423 Game Database &Search: m_searchEdit false &Clear false Advanced... 0 0 Qt::Horizontal 100 0 false 100 0 false 200 0 true 0 0 198 335 Qt::Horizontal 40 20 false false false false Qt::Horizontal 40 20 QFormLayout::AllNonFixedFieldsGrow 75 true White: true PointingHandCursor 75 true Black: true PointingHandCursor 75 true Site: true PointingHandCursor 75 true Event: true PointingHandCursor 75 true Result: true PointingHandCursor QDialogButtonBox::Close buttonBox accepted() GameDatabaseDialog accept() 507 402 556 359 buttonBox rejected() GameDatabaseDialog reject() 410 395 550 417 m_clearBtn clicked() m_searchEdit clear() 481 27 434 24 cutechess-20111114+0.4.2+0.0.1/projects/cli/0000775000175000017500000000000011657223322017010 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/projects/cli/src/0000775000175000017500000000000011657223322017577 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/projects/cli/src/src.pri0000664000175000017500000000026511657223322021105 0ustar oliveroliverDEPENDPATH += $$PWD HEADERS += enginematch.h \ cutechesscoreapp.h \ matchparser.h SOURCES += main.cpp \ cutechesscoreapp.cpp \ enginematch.cpp \ matchparser.cpp cutechess-20111114+0.4.2+0.0.1/projects/cli/src/enginematch.h0000664000175000017500000000613411657223322022236 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef ENGINEMATCH_H #define ENGINEMATCH_H #include #include #include #include #include #include #include #include #include #include #include #include class ChessGame; class OpeningBook; class EngineBuilder; class EngineMatch : public QObject { Q_OBJECT public: EngineMatch(QObject* parent = 0); virtual ~EngineMatch(); void addEngine(const EngineConfiguration& config, const TimeControl& timeControl, const QString& book, int bookDepth); bool setConcurrency(int concurrency); void setDebugMode(bool debug); void setDrawThreshold(int moveNumber, int score); void setEvent(const QString& event); bool setGameCount(int gameCount); bool setPgnDepth(int depth); bool setPgnInput(const QString& filename); void setPgnOutput(const QString& filename, PgnGame::PgnMode mode); void setRecoveryMode(bool recover); void setRepeatOpening(bool repeatOpening); void setResignThreshold(int moveCount, int score); void setSite(const QString& site); bool setVariant(const QString& variant); bool setWait(int msecs); bool initialize(); public slots: void start(); void stop(); signals: void finished(); void stopGame(); private slots: void onGameEnded(); void onManagerReady(); void print(const QString& msg); private: bool loadOpeningBook(const QString& filename, OpeningBook** book); struct EngineData { EngineConfiguration config; TimeControl tc; OpeningBook* book; QString bookFile; int bookDepth; int wins; EngineBuilder* builder; }; int m_gameCount; int m_drawCount; int m_currentGame; int m_finishedGames; int m_pgnDepth; int m_pgnGamesRead; int m_drawMoveNum; int m_drawScore; int m_resignMoveCount; int m_resignScore; int m_wait; bool m_debug; bool m_recover; bool m_finishing; PgnGame::PgnMode m_pgnMode; bool m_repeatOpening; QString m_variant; QVector m_engines; EngineData* m_fcp; EngineData* m_scp; QVector m_openingMoves; QList m_books; QList m_builders; QString m_fen; QString m_event; QString m_site; QFile m_pgnInputFile; PgnStream m_pgnInputStream; QString m_pgnOutput; QTime m_startTime; GameManager m_manager; QMap m_games; }; #endif // ENGINEMATCH_H cutechess-20111114+0.4.2+0.0.1/projects/cli/src/cutechesscoreapp.h0000664000175000017500000000234611657223322023315 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef CUTE_CHESS_CORE_APPLICATION_H #define CUTE_CHESS_CORE_APPLICATION_H #include class EngineManager; class CuteChessCoreApplication : public QCoreApplication { Q_OBJECT public: CuteChessCoreApplication(int& argc, char* argv[]); virtual ~CuteChessCoreApplication(); QString configPath(); EngineManager* engineManager(); static CuteChessCoreApplication* instance(); static void messageHandler(QtMsgType type, const char* message); private: EngineManager* m_engineManager; }; #endif // CUTE_CHESS_CORE_APPLICATION_H cutechess-20111114+0.4.2+0.0.1/projects/cli/src/cutechesscoreapp.cpp0000664000175000017500000000515211657223322023646 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "cutechesscoreapp.h" #include #include #include #include #include #include #include CuteChessCoreApplication::CuteChessCoreApplication(int& argc, char* argv[]) : QCoreApplication(argc, argv), m_engineManager(0) { qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); QCoreApplication::setOrganizationName(QLatin1String("cutechess")); QCoreApplication::setOrganizationDomain(QLatin1String("cutechess.org")); QCoreApplication::setApplicationName(QLatin1String("cutechess")); // Use Ini format on all platforms QSettings::setDefaultFormat(QSettings::IniFormat); qInstallMsgHandler(CuteChessCoreApplication::messageHandler); // Load the engines QString configFile("engines.json"); if (!QFile::exists(configFile)) configFile = configPath() + "/" + configFile; engineManager()->loadEngines(configFile); } CuteChessCoreApplication::~CuteChessCoreApplication() { } void CuteChessCoreApplication::messageHandler(QtMsgType type, const char* message) { switch (type) { case QtDebugMsg: fprintf(stdout, "%s\n", message); break; case QtWarningMsg: fprintf(stderr, "Warning: %s\n", message); break; case QtCriticalMsg: fprintf(stderr, "Critical: %s\n", message); break; case QtFatalMsg: fprintf(stderr, "Fatal: %s\n", message); abort(); } } QString CuteChessCoreApplication::configPath() { // QDesktopServices requires QtGui QSettings settings; QFileInfo fi(settings.fileName()); QDir dir(fi.absolutePath()); if (!dir.exists()) dir.mkpath(fi.absolutePath()); return fi.absolutePath(); } EngineManager* CuteChessCoreApplication::engineManager() { if (m_engineManager == 0) m_engineManager = new EngineManager(this); return m_engineManager; } CuteChessCoreApplication* CuteChessCoreApplication::instance() { return static_cast(QCoreApplication::instance()); } cutechess-20111114+0.4.2+0.0.1/projects/cli/src/main.cpp0000664000175000017500000003604311657223322021235 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include "cutechesscoreapp.h" #include "matchparser.h" #include "enginematch.h" static EngineMatch* match = 0; void sigintHandler(int param) { Q_UNUSED(param); if (match != 0) match->stop(); else abort(); } struct EngineData { EngineConfiguration config; TimeControl tc; QString book; int bookDepth; }; static bool readEngineConfig(const QString& name, EngineConfiguration& config) { const QList engines = CuteChessCoreApplication::instance()->engineManager()->engines(); foreach (const EngineConfiguration& engine, engines) { if (engine.name() == name) { config = engine; return true; } } return false; } static bool parseEngine(const QStringList& args, EngineData& data) { foreach (const QString& arg, args) { QString name = arg.section('=', 0, 0); QString val = arg.section('=', 1); if (name.isEmpty()) continue; if (name == "conf") { if (!readEngineConfig(val, data.config)) { qWarning() << "Unknown engine configuration:" << val; return false; } } else if (name == "name") data.config.setName(val); else if (name == "cmd") data.config.setCommand(val); else if (name == "dir") data.config.setWorkingDirectory(val); else if (name == "arg") data.config.addArgument(val); else if (name == "proto") { if (EngineFactory::protocols().contains(val)) data.config.setProtocol(val); else { qWarning()<< "Usupported chess protocol:" << val; return false; } } // Line that are sent to the engine at startup, ie. before // starting the chess protocol. else if (name == "initstr") data.config.addInitString(val.replace("\\n", "\n")); // Should the engine be restarted after each game? else if (name == "restart") { EngineConfiguration::RestartMode mode; if (val == "auto") mode = EngineConfiguration::RestartAuto; else if (val == "on") mode = EngineConfiguration::RestartOn; else if (val == "off") mode = EngineConfiguration::RestartOff; else { qWarning() << "Invalid restart mode:" << val; return false; } data.config.setRestartMode(mode); } // Time control (moves/time+increment) else if (name == "tc") { TimeControl tc(val); if (!tc.isValid()) { qWarning() << "Invalid time control:" << val; return false; } data.tc.setInfinity(tc.isInfinite()); data.tc.setTimePerTc(tc.timePerTc()); data.tc.setMovesPerTc(tc.movesPerTc()); data.tc.setTimeIncrement(tc.timeIncrement()); } // Search time per move else if (name == "st") { bool ok = false; int moveTime = val.toDouble(&ok) * 1000.0; if (!ok || moveTime <= 0) { qWarning() << "Invalid search time:" << val; return false; } data.tc.setTimePerMove(moveTime); } // Time expiry margin else if (name == "timemargin") { bool ok = false; int margin = val.toInt(&ok); if (!ok || margin < 0) { qWarning() << "Invalid time margin:" << val; return false; } data.tc.setExpiryMargin(margin); } else if (name == "book") data.book = val; else if (name == "bookdepth") { if (val.toInt() <= 0) { qWarning() << "Invalid book depth limit:" << val; return false; } data.bookDepth = val.toInt(); } else if (name == "whitepov") { data.config.setWhiteEvalPov(true); } else if (name == "depth") { if (val.toInt() <= 0) { qWarning() << "Invalid depth limit:" << val; return false; } data.tc.setPlyLimit(val.toInt()); } else if (name == "nodes") { if (val.toInt() <= 0) { qWarning() << "Invalid node limit:" << val; return false; } data.tc.setNodeLimit(val.toInt()); } // Custom engine option else if (name.startsWith("option.")) data.config.addOption(new EngineTextOption(name.section('.', 1), val, val)); else { qWarning() << "Invalid engine option:" << name; return false; } } return true; } static EngineMatch* parseMatch(const QStringList& args, QObject* parent) { MatchParser parser(args); parser.addOption("-fcp", QVariant::StringList, 1); parser.addOption("-scp", QVariant::StringList, 1); parser.addOption("-both", QVariant::StringList, 1); parser.addOption("-variant", QVariant::String, 1, 1); parser.addOption("-book", QVariant::String, 1, 1); parser.addOption("-bookdepth", QVariant::Int, 1, 1); parser.addOption("-concurrency", QVariant::Int, 1, 1); parser.addOption("-draw", QVariant::StringList, 2, 2); parser.addOption("-resign", QVariant::StringList, 2, 2); parser.addOption("-event", QVariant::String, 1, 1); parser.addOption("-games", QVariant::Int, 1, 1); parser.addOption("-debug", QVariant::Bool, 0, 0); parser.addOption("-pgnin", QVariant::String, 1, 1); parser.addOption("-pgndepth", QVariant::Int, 1, 1); parser.addOption("-pgnout", QVariant::StringList, 1, 2); parser.addOption("-repeat", QVariant::Bool, 0, 0); parser.addOption("-recover", QVariant::Bool, 0, 0); parser.addOption("-site", QVariant::String, 1, 1); parser.addOption("-srand", QVariant::UInt, 1, 1); parser.addOption("-wait", QVariant::Int, 1, 1); if (!parser.parse()) return 0; EngineMatch* match = new EngineMatch(parent); EngineData fcp; EngineData scp; fcp.bookDepth = 1000; scp.bookDepth = 1000; QMap options(parser.options()); QMap::const_iterator it; for (it = options.constBegin(); it != options.constEnd(); ++it) { bool ok = true; QString name = it.key(); QVariant value = it.value(); Q_ASSERT(!value.isNull()); // First chess program if (name == "-fcp") ok = parseEngine(value.toStringList(), fcp); // Second chess program else if (name == "-scp") ok = parseEngine(value.toStringList(), scp); // The engine options apply to both engines else if (name == "-both") { ok = (parseEngine(value.toStringList(), fcp) && parseEngine(value.toStringList(), scp)); } // Chess variant (default: standard chess) else if (name == "-variant") ok = match->setVariant(value.toString()); else if (name == "-concurrency") ok = match->setConcurrency(value.toInt()); // Threshold for draw adjudication else if (name == "-draw") { QStringList list = value.toStringList(); bool numOk = false; bool scoreOk = false; int moveNumber = list.at(0).toInt(&numOk); int score = list.at(1).toInt(&scoreOk); ok = (numOk && scoreOk); if (ok) match->setDrawThreshold(moveNumber, score); } // Threshold for resign adjudication else if (name == "-resign") { QStringList list = value.toStringList(); bool countOk = false; bool scoreOk = false; int moveCount = list.at(0).toInt(&countOk); int score = list.at(1).toInt(&scoreOk); ok = (countOk && scoreOk); if (ok) match->setResignThreshold(moveCount, -score); } // Event name else if (name == "-event") match->setEvent(value.toString()); // Number of games to play else if (name == "-games") ok = match->setGameCount(value.toInt()); // Debugging mode. Prints all engine input and output. else if (name == "-debug") match->setDebugMode(true); // PGN input depth in plies else if (name == "-pgndepth") ok = match->setPgnDepth(value.toInt()); // Use a PGN file as the opening book else if (name == "-pgnin") ok = match->setPgnInput(value.toString()); // PGN file where the games should be saved else if (name == "-pgnout") { PgnGame::PgnMode mode = PgnGame::Verbose; QStringList list = value.toStringList(); if (list.size() == 2) { if (list.at(1) == "min") mode = PgnGame::Minimal; else ok = false; } if (ok) match->setPgnOutput(list.at(0), mode); } // Play every opening twice, just switch the players' sides else if (name == "-repeat") match->setRepeatOpening(true); // Recover crashed/stalled engines else if (name == "-recover") match->setRecoveryMode(true); // Site/location name else if (name == "-site") match->setSite(value.toString()); // Set the random seed manually else if (name == "-srand") qsrand(value.toUInt()); // Delay between games else if (name == "-wait") ok = match->setWait(value.toInt()); else qFatal("Unknown argument: \"%s\"", qPrintable(name)); if (!ok) { QString val; if (value.type() == QVariant::StringList) val = value.toStringList().join(" "); else val = value.toString(); qWarning("Invalid value for option \"%s\": \"%s\"", qPrintable(name), qPrintable(val)); delete match; return 0; } } match->addEngine(fcp.config, fcp.tc, fcp.book, fcp.bookDepth); match->addEngine(scp.config, scp.tc, scp.book, scp.bookDepth); return match; } int main(int argc, char* argv[]) { signal(SIGINT, sigintHandler); CuteChessCoreApplication app(argc, argv); QStringList arguments = CuteChessCoreApplication::arguments(); arguments.takeFirst(); // application name // Use trivial command-line parsing for now QTextStream out(stdout); foreach (const QString& arg, arguments) { if (arg == "-v" || arg == "--version") { out << "cutechess-cli " << CUTECHESS_CLI_VERSION << endl; out << "Using Qt version " << qVersion() << endl << endl; out << "Copyright (C) 2008-2011 Ilari Pihlajisto and Arto Jonsson" << endl; out << "This is free software; see the source for copying "; out << "conditions. There is NO" << endl << "warranty; not even for "; out << "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."; out << endl << endl; return 0; } else if (arg == "--engines") { const QList engines = CuteChessCoreApplication::instance()->engineManager()->engines(); foreach (const EngineConfiguration& engine, engines) out << engine.name() << endl; return 0; } else if (arg == "--protocols") { foreach (const QString& protocol, EngineFactory::protocols()) out << protocol << endl; return 0; } else if (arg == "--variants") { foreach (const QString& variant, Chess::BoardFactory::variants()) out << variant << endl; return 0; } else if (arg == "--help") { out << "Usage: cutechess-cli -fcp [eng_options] -scp [eng_options] [options]\n" "Options:\n" " --help Display this information\n" " --version Display the version number\n" " --engines Display a list of configured engines and exit\n" " --protocols Display a list of supported chess protocols and exit\n" " --variants Display a list of supported chess variants and exit\n\n" " -fcp Apply to the first engine\n" " -scp Apply to the second engine\n" " -both Apply to both engines\n" " -variant Set the chess variant to \n" " -concurrency Set the maximum number of concurrent games to \n" " -draw Adjudicate the game as a draw if the score of both\n" " engines is within centipawns from zero after\n" " full moves have been played\n" " -resign Adjudicate the game as a loss if an engine's score is\n" " at least centipawns below zero for at least\n" " consecutive moves\n" " -event Set the event name to \n" " -games Play games\n" " -debug Display all engine input and output\n" " -pgnin Use as the opening book in PGN format\n" " -pgndepth Set the maximum depth for PGN input to plies\n" " -pgnout [min] Save the games to in PGN format. Use the 'min'\n" " argument to save in a minimal PGN format.\n" " -recover Restart crashed engines instead of stopping the match\n" " -repeat Play each opening twice so that both players get\n" " to play it on both sides\n" " -site Set the site/location to \n" " -srand Set the random seed for the book move selector to \n" " -wait Wait milliseconds between games. The default is 0.\n\n" "Engine options:\n" " conf= Use an engine with the name from Cute Chess'\n" " configuration file.\n" " name= Set the name to \n" " cmd= Set the command to \n" " dir= Set the working directory to \n" " arg= Pass to the engine as a command line argument\n" " initstr= Send to the engine's standard input at startup\n" " restart= Set the restart mode to which can be:\n" " 'auto': the engine decides whether to restart (default)\n" " 'on': the engine is always restarted between games\n" " 'off': the engine is never restarted between games\n" " proto= Set the chess protocol to \n" " tc= Set the time control to . The format is\n" " moves/time+increment, where 'moves' is the number of\n" " moves per tc, 'time' is time per tc (either seconds or\n" " minutes:seconds), and 'increment' is time increment\n" " per move in seconds.\n" " Infinite time control can be set with 'tc=inf'.\n" " st= Set the time limit for each move to seconds.\n" " This option can't be used in combination with \"tc\".\n" " timemargin= Let engines go milliseconds over the time limit.\n" " book= Use (Polyglot book file) as the opening book\n" " bookdepth= Set the maximum book depth (in fullmoves) to \n" " whitepov Invert the engine's scores when it plays black. This\n" " option should be used with engines that always report\n" " scores from white's perspective.\n" " depth= Set the search depth limit to plies\n" " nodes= Set the node count limit to nodes\n" " option.= Set custom option to value \n"; return 0; } } match = parseMatch(arguments, &app); if (match == 0) return 1; QObject::connect(match, SIGNAL(finished()), &app, SLOT(quit())); if (!match->initialize()) return 1; match->start(); int ret = app.exec(); qDebug() << "Finished match"; return ret; } cutechess-20111114+0.4.2+0.0.1/projects/cli/src/matchparser.cpp0000664000175000017500000000514411657223322022620 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "matchparser.h" MatchParser::MatchParser(const QStringList& args) : m_args(args) { } void MatchParser::addOption(const QString& name, QVariant::Type type, int minArgs, int maxArgs) { PrivateOption option = { type, minArgs, maxArgs }; m_validOptions[name] = option; } QMap MatchParser::options() const { return m_options; } bool MatchParser::parse() { QStringList::const_iterator it; for (it = m_args.constBegin(); it != m_args.constEnd(); ++it) { if (!m_validOptions.contains(*it)) { qWarning("Unknown option: \"%s\"", qPrintable(*it)); return false; } QString name = *it; PrivateOption& option = m_validOptions[name]; QStringList list; while (++it != m_args.constEnd()) { if (it->size() > 1 && it->startsWith('-')) { bool ok = false; it->toDouble(&ok); if (!ok) break; } list << *it; } --it; if (m_options.contains(name)) { qWarning("Multiple instances of option \"%s\"", qPrintable(name)); return false; } if (list.size() < option.minArgs) { if (option.maxArgs == option.minArgs) qWarning("Option \"%s\" needs %d argument(s)", qPrintable(name), option.minArgs); else qWarning("Option \"%s\" needs at least %d argument(s)", qPrintable(name), option.minArgs); return false; } if (option.maxArgs != -1 && list.size() > option.maxArgs) { qWarning("Too many arguments for option \"%s\"", qPrintable(name)); return false; } // Boolean option if (list.isEmpty()) { m_options[name] = QVariant(true); continue; } QVariant value; if (option.type == QVariant::StringList) value.setValue(list); else value.setValue(list.join(" ")); if (!value.convert(option.type)) { qWarning("Invalid value for option \"%s\": \"%s\"", qPrintable(name), qPrintable(list.join(" "))); return false; } m_options[name] = value; } return true; } cutechess-20111114+0.4.2+0.0.1/projects/cli/src/enginematch.cpp0000664000175000017500000002252711657223322022575 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "enginematch.h" #include #include #include #include #include #include #include #include EngineMatch::EngineMatch(QObject* parent) : QObject(parent), m_gameCount(1), m_drawCount(0), m_currentGame(0), m_finishedGames(0), m_pgnDepth(1000), m_pgnGamesRead(0), m_drawMoveNum(0), m_drawScore(0), m_resignMoveCount(0), m_resignScore(0), m_wait(0), m_debug(false), m_recover(false), m_finishing(false), m_pgnMode(PgnGame::Verbose), m_repeatOpening(false), m_variant("standard"), m_fcp(0), m_scp(0) { m_startTime.start(); } EngineMatch::~EngineMatch() { qDeleteAll(m_books); qDeleteAll(m_builders); } void EngineMatch::stop() { if (m_finishing) return; m_finishing = true; disconnect(&m_manager, SIGNAL(ready()), this, SLOT(onManagerReady())); m_manager.finish(); emit stopGame(); } void EngineMatch::addEngine(const EngineConfiguration& engineConfig, const TimeControl& timeControl, const QString& book, int bookDepth) { // We don't allow more than 2 engines at this point if (m_engines.size() >= 2) { qWarning() << "Only two engines can be added"; return; } if (engineConfig.command().isEmpty()) return; EngineData data = { engineConfig, timeControl, 0, book, bookDepth, 0, 0 }; m_engines.append(data); } bool EngineMatch::setConcurrency(int concurrency) { if (concurrency <= 0) { qWarning() << "Concurrency must be bigger than zero"; return false; } m_manager.setConcurrency(concurrency); return true; } void EngineMatch::setDebugMode(bool debug) { m_debug = debug; } void EngineMatch::setDrawThreshold(int moveNumber, int score) { m_drawMoveNum = moveNumber; m_drawScore = score; } void EngineMatch::setEvent(const QString& event) { m_event = event; } bool EngineMatch::setGameCount(int gameCount) { if (gameCount <= 0) return false; m_gameCount = gameCount; return true; } bool EngineMatch::setPgnDepth(int depth) { if (depth <= 0) return false; m_pgnDepth = depth; return true; } bool EngineMatch::setPgnInput(const QString& filename) { m_pgnInputFile.setFileName(filename); if (!m_pgnInputFile.open(QIODevice::ReadOnly)) { qWarning() << "Can't open PGN file:" << filename; return false; } m_pgnInputStream.setDevice(&m_pgnInputFile); return true; } void EngineMatch::setPgnOutput(const QString& filename, PgnGame::PgnMode mode) { m_pgnOutput = filename; m_pgnMode = mode; } void EngineMatch::setRecoveryMode(bool recover) { m_recover = recover; } void EngineMatch::setRepeatOpening(bool repeatOpening) { m_repeatOpening = repeatOpening; } void EngineMatch::setResignThreshold(int moveCount, int score) { m_resignMoveCount = moveCount; m_resignScore = score; } void EngineMatch::setSite(const QString& site) { m_site = site; } bool EngineMatch::setVariant(const QString& variant) { if (!Chess::BoardFactory::variants().contains(variant)) return false; m_variant = variant; return true; } bool EngineMatch::setWait(int msecs) { if (msecs < 0) return false; m_wait = msecs; return true; } bool EngineMatch::loadOpeningBook(const QString& filename, OpeningBook** book) { *book = new PolyglotBook; if (!(*book)->read(filename)) { delete *book; *book = 0; qWarning() << "Can't open book file" << filename; return false; } m_books << *book; return true; } bool EngineMatch::initialize() { if (m_engines.size() < 2) { qWarning() << "Two engines are needed"; return false; } m_fcp = &m_engines[0]; m_scp = &m_engines[1]; m_finishing = false; m_currentGame = 0; m_finishedGames = 0; m_drawCount = 0; m_games.clear(); QVector::iterator it; if (m_fcp->bookFile == m_scp->bookFile && !m_fcp->bookFile.isEmpty()) { if (!loadOpeningBook(m_fcp->bookFile, &m_fcp->book)) return false; m_scp->book = m_fcp->book; } else { for (it = m_engines.begin(); it != m_engines.end(); ++it) { if (it->bookFile.isEmpty()) continue; if (!loadOpeningBook(it->bookFile, &it->book)) return false; } } for (it = m_engines.begin(); it != m_engines.end(); ++it) { if (!it->tc.isValid()) { qWarning() << "Invalid or missing time control"; return false; } if (it->config.protocol().isEmpty()) { qWarning() << "Missing chess protocol"; return false; } it->wins = 0; it->builder = new EngineBuilder(it->config); m_builders << it->builder; } connect(&m_manager, SIGNAL(ready()), this, SLOT(onManagerReady())); connect(&m_manager, SIGNAL(finished()), this, SIGNAL(finished()), Qt::QueuedConnection); if (m_debug) connect(&m_manager, SIGNAL(debugMessage(QString)), this, SLOT(print(QString))); return true; } void EngineMatch::onGameEnded() { ChessGame* game = qobject_cast(QObject::sender()); Q_ASSERT(game != 0); PgnGame* pgn(game->pgn()); Chess::Result result(game->result()); bool playerMissing(game->player(Chess::Side::White) == 0 || game->player(Chess::Side::Black) == 0); game->deleteLater(); game = 0; if (playerMissing || result.type() == Chess::Result::ResultError) { delete pgn; m_finishedGames++; stop(); return; } int gameId = pgn->round(); int wIndex = !(gameId % 2); qDebug("Game %d ended: %s", gameId, qPrintable(result.toVerboseString())); if (result.isDraw()) m_drawCount++; else if (!result.isNone()) { qDebug("%s wins the game as %s", qPrintable(pgn->playerName(result.winner())), qPrintable(result.winner().toString())); m_engines[wIndex ^ result.winner()].wins++; } int totalResults = m_fcp->wins + m_scp->wins + m_drawCount; qDebug("Score of %s vs %s: %d - %d - %d [%.2f] %d", qPrintable(pgn->playerName(Chess::Side::Type(wIndex))), qPrintable(pgn->playerName(Chess::Side::Type(!wIndex))), m_fcp->wins, m_scp->wins, m_drawCount, double(m_fcp->wins * 2 + m_drawCount) / (totalResults * 2), totalResults); m_games[gameId] = pgn; while (m_games.contains(m_finishedGames + 1)) { m_finishedGames++; pgn = m_games.take(m_finishedGames); if (!m_pgnOutput.isEmpty()) pgn->write(m_pgnOutput, m_pgnMode); delete pgn; } if (m_finishedGames >= m_gameCount || result.type() == Chess::Result::NoResult || (!m_recover && (result.type() == Chess::Result::Disconnection || result.type() == Chess::Result::StalledConnection))) { int score = m_fcp->wins * 2 + m_drawCount; int total = (m_fcp->wins + m_scp->wins + m_drawCount) * 2; if (total > 0) { double ratio = double(score) / double(total); double eloDiff = -400.0 * std::log(1.0 / ratio - 1.0) / std::log(10.0); qDebug("ELO difference: %.0f", eloDiff); } stop(); } } void EngineMatch::onManagerReady() { if (!m_finishing && m_currentGame < m_gameCount) start(); } void EngineMatch::start() { m_currentGame++; qDebug() << "Started game" << m_currentGame << "of" << m_gameCount; Chess::Board* board = Chess::BoardFactory::create(m_variant); Q_ASSERT(board != 0); ChessGame* game = new ChessGame(board, new PgnGame); connect(this, SIGNAL(stopGame()), game, SLOT(kill()), Qt::QueuedConnection); game->setStartDelay(m_wait); EngineData* white = m_fcp; EngineData* black = m_scp; if ((m_currentGame % 2) == 0) qSwap(white, black); game->setTimeControl(white->tc, Chess::Side::White); game->setTimeControl(black->tc, Chess::Side::Black); game->setOpeningBook(white->book, Chess::Side::White, white->bookDepth); game->setOpeningBook(black->book, Chess::Side::Black, black->bookDepth); if (!m_fen.isEmpty() || !m_openingMoves.isEmpty()) { game->setStartingFen(m_fen); m_fen.clear(); game->setMoves(m_openingMoves); m_openingMoves.clear(); } else if (m_pgnInputStream.isOpen()) { PgnGame pgn; if (pgn.read(m_pgnInputStream, m_pgnDepth)) m_pgnGamesRead++; // Rewind the PGN input file else if (m_pgnGamesRead > 0) { m_pgnInputStream.rewind(); bool ok = pgn.read(m_pgnInputStream, m_pgnDepth); Q_ASSERT(ok); Q_UNUSED(ok); m_pgnGamesRead++; } game->setMoves(pgn); } game->generateOpening(); if (m_repeatOpening && (m_currentGame % 2) != 0) { m_fen = game->startingFen(); m_openingMoves = game->moves(); } game->pgn()->setRound(m_currentGame); game->pgn()->setEvent(m_event); game->pgn()->setSite(m_site); game->setDrawThreshold(m_drawMoveNum, m_drawScore); game->setResignThreshold(m_resignMoveCount, m_resignScore); connect(game, SIGNAL(finished()), this, SLOT(onGameEnded())); if (!m_manager.newGame(game, white->builder, black->builder, GameManager::Enqueue, GameManager::ReusePlayers)) stop(); } void EngineMatch::print(const QString& msg) { qDebug("%d %s", m_startTime.elapsed(), qPrintable(msg)); } cutechess-20111114+0.4.2+0.0.1/projects/cli/src/matchparser.h0000664000175000017500000000370611657223322022267 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef MATCHPARSER_H #define MATCHPARSER_H #include #include #include /*! * \brief A command line parser for EngineMatch options * * \sa EngineMatch */ class MatchParser { public: /*! Constructs a new parser for parsing \a args. */ MatchParser(const QStringList& args); /*! * Adds a new command line option. * * \param name The name of the option. * \param type The storage type of the option's value. * For options with multiple arguments this * should be set to QVariant::QStringList. * \param minArgs The minimum number of arguments. * \param maxArgs The maximum number of arguments. A value * of -1 represents infinity. */ void addOption(const QString& name, QVariant::Type type, int minArgs = 0, int maxArgs = -1); /*! Returns the options parsed by \a parse(). */ QMap options() const; /*! * Parses the command line arguments. * Returns true if successfull. */ bool parse(); private: struct PrivateOption { QVariant::Type type; int minArgs; int maxArgs; }; QStringList m_args; QMap m_options; QMap m_validOptions; }; #endif // MATCHPARSER_H cutechess-20111114+0.4.2+0.0.1/projects/cli/cli.pro0000664000175000017500000000074211657223322020304 0ustar oliveroliverTEMPLATE = app TARGET = cutechess-cli DESTDIR = $$PWD include(../lib/lib.pri) CUTECHESS_CLI_VERSION = 0.4.2 INCLUDEPATH += $$PWD DEPENDPATH += $$PWD macx-xcode { DEFINES += CUTECHESS_CLI_VERSION=\"$$CUTECHESS_CLI_VERSION\" } else { OBJECTS_DIR = .obj/ MOC_DIR = .moc/ RCC_DIR = .rcc/ DEFINES += CUTECHESS_CLI_VERSION=\\\"$$CUTECHESS_CLI_VERSION\\\" } win32 { CONFIG += console } mac { CONFIG -= app_bundle } QT -= gui # Code include(src/src.pri) cutechess-20111114+0.4.2+0.0.1/projects/lib/0000775000175000017500000000000011657223322017007 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/projects/lib/components/0000775000175000017500000000000011657223322021174 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/projects/lib/components/json/0000775000175000017500000000000011657223322022145 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/projects/lib/components/json/src/0000775000175000017500000000000011657223322022734 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/projects/lib/components/json/src/jsonserializer.cpp0000664000175000017500000000720311657223322026505 0ustar oliveroliver/* Copyright (c) 2010 Ilari Pihlajisto Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "jsonserializer.h" #include static QString jsonString(const QString& source) { QString str; foreach (const QChar& c, source) { switch (c.toAscii()) { case '\"': str += "\\\""; break; case '\\': str += "\\\\"; break; case '\b': str += "\\b"; break; case '\f': str += "\\f"; break; case '\n': str += "\\n"; break; case '\r': str += "\\r"; break; case '\t': str += "\\t"; break; default: if (c.unicode() >= 128) { QString u(QString::number(c.unicode(), 16)); str += "\\u" + u.rightJustified(4, '0'); } else str += c; break; } } return str; } JsonSerializer::JsonSerializer(const QVariant& data) : m_error(false), m_data(data) { } bool JsonSerializer::hasError() const { return m_error; } QString JsonSerializer::errorString() const { return m_errorString; } void JsonSerializer::setError(const QString &message) { if (m_error) return; m_error = true; m_errorString = message; } bool JsonSerializer::serializeNode(QTextStream& stream, const QVariant& node, int indentLevel) { const QString indent(indentLevel, '\t'); switch (node.type()) { case QVariant::Invalid: stream << "null"; break; case QVariant::Map: { stream << "{\n"; const QVariantMap map(node.toMap()); QVariantMap::const_iterator it; for (it = map.constBegin(); it != map.constEnd(); ++it) { stream << indent << "\t\"" << jsonString(it.key()) << "\" : "; if (!serializeNode(stream, it.value(), indentLevel + 1)) return false; if (it != map.constEnd() - 1) stream << ','; stream << '\n'; } stream << indent << '}'; } break; case QVariant::List: case QVariant::StringList: { stream << "[\n"; const QVariantList list(node.toList()); for (int i = 0; i < list.size(); i++) { stream << indent << '\t'; if (!serializeNode(stream, list.at(i), indentLevel + 1)) return false; if (i != list.size() - 1) stream << ','; stream << '\n'; } stream << indent << ']'; } break; case QVariant::String: case QVariant::ByteArray: stream << '\"' << jsonString(node.toString()) << '\"'; break; default: if (node.canConvert(QVariant::String)) stream << node.toString(); else { setError(QObject::tr("Invalid variant type: %1") .arg(node.typeName())); return false; } break; } return true; } bool JsonSerializer::serialize(QTextStream& stream) { bool ok = serializeNode(stream, m_data, 0); if (ok) stream << '\n'; return ok; } cutechess-20111114+0.4.2+0.0.1/projects/lib/components/json/src/jsonparser.cpp0000664000175000017500000001735211657223322025636 0ustar oliveroliver/* Copyright (c) 2010 Ilari Pihlajisto Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "jsonparser.h" #include QString JsonParser::tokenString(JsonParser::Token type, const QString& str) { if (!str.isEmpty()) return str; switch (type) { case JsonComma: return ","; case JsonColon: return ":"; case JsonBeginObject: return "{"; case JsonEndObject: return "}"; case JsonBeginArray: return "["; case JsonEndArray: return "]"; case JsonTrue: return "true"; case JsonFalse: return "false"; case JsonNull: return "null"; case JsonString: return QObject::tr("(empty string)"); default: return QString(); } } JsonParser::JsonParser(QTextStream& stream) : m_error(false), m_currentLine(1), m_errorLine(0), m_stream(stream) { } bool JsonParser::hasError() const { return m_error; } QString JsonParser::errorString() const { return m_errorString; } qint64 JsonParser::errorLineNumber() const { return m_errorLine; } void JsonParser::setError(const QString& message) { if (m_error) return; m_error = true; m_errorString = message; m_errorLine = m_currentLine; } void JsonParser::clearError() { if (!m_error) return; m_error = false; m_errorString.clear(); m_errorLine = 0; } QVariant JsonParser::parse() { return parseValue(); } JsonParser::Token JsonParser::parseToken() { static const QString termination(",]}"); QChar c; bool escapeChar = false; bool inUnicode = false; QString unicode; Token type = JsonNone; m_lastToken.clear(); while ((!m_stream.atEnd() || !m_buffer.isNull()) && !m_error) { if (m_buffer.isNull()) { m_stream >> c; if (c == '\n') m_currentLine++; } else { c = m_buffer; m_buffer = QChar(); } if (type == JsonNone && c.isSpace()) continue; switch (type) { case JsonNone: switch (c.toAscii()) { case ',': return JsonComma; case ':': return JsonColon; case '{': return JsonBeginObject; case '}': return JsonEndObject; case '[': return JsonBeginArray; case ']': return JsonEndArray; case '\"': type = JsonString; break; default: type = JsonGeneric; m_lastToken += c; break; } break; case JsonString: if (escapeChar) { escapeChar = false; switch (c.toAscii()) { case '\"': case '\\': case '/': m_lastToken += c; break; case 'b': m_lastToken += '\b'; break; case 'f': m_lastToken += '\f'; break; case 'n': m_lastToken += '\n'; break; case 'r': m_lastToken += '\r'; break; case 't': m_lastToken += '\t'; break; case 'u': inUnicode = true; unicode.clear(); break; default: setError(QObject::tr("Unknown escape sequence: \\%1").arg(c)); return JsonError; } break; } if (inUnicode) { if (!c.isLetterOrNumber()) { setError(QObject::tr("Invalid unicode digit: %1").arg(c)); return JsonError; } unicode += c; if (unicode.size() == 4) { bool ok = false; int code = unicode.toInt(&ok, 16); if (!ok) { setError(QObject::tr("Invalid unicode value: \\u%1") .arg(unicode)); return JsonError; } m_lastToken += QChar(code); unicode.clear(); inUnicode = false; } break; } switch (c.toAscii()) { case '\\': escapeChar = true; break; case '\"': return type; default: m_lastToken += c; break; } break; case JsonGeneric: if (!c.isSpace() && !termination.contains(c)) { m_lastToken += c; if (m_stream.atEnd()) c = '\n'; else break; } if (m_lastToken == "true") type = JsonTrue; else if (m_lastToken == "false") type = JsonFalse; else if (m_lastToken == "null") type = JsonNull; else if (m_lastToken.at(0).isDigit() || m_lastToken.at(0) == '-') type = JsonNumber; else { setError(QObject::tr("Unknown token: %1") .arg(m_lastToken)); return JsonError; } m_buffer = c; return type; default: qFatal("UNREACHABLE"); } } setError(QObject::tr("Reached EOF unexpectedly")); return JsonError; } QVariant JsonParser::parseValue(Token* tokenType) { Token type = parseToken(); if (tokenType != 0) *tokenType = type; if (type == JsonError || type == JsonNone || type == JsonGeneric) return QVariant(); switch (type) { case JsonBeginObject: return parseObject(); case JsonBeginArray: return parseArray(); case JsonTrue: return QVariant(true); case JsonFalse: return QVariant(false); case JsonNull: return QVariant(); case JsonNumber: { bool ok = false; if (m_lastToken.contains('.')) { double val = m_lastToken.toDouble(&ok); if (!ok) { setError(QObject::tr("Invalid fraction: %1") .arg(m_lastToken)); return QVariant(); } return val; } else { int val = m_lastToken.toInt(&ok); if (ok) return val; qlonglong longval = m_lastToken.toLongLong(&ok); if (ok) return longval; setError(QObject::tr("Invalid integer: %1") .arg(m_lastToken)); return QVariant(); } } case JsonString: return QVariant(m_lastToken); default: setError(QObject::tr("Invalid value: %1") .arg(tokenString(type, m_lastToken))); return QVariant(); } } QVariant JsonParser::parseObject() { Token t = JsonNone; QString name; QVariant value; QVariantMap map; forever { t = parseToken(); if (t == JsonEndObject) { if (!map.isEmpty()) { setError(QObject::tr("Expected more key/value pairs")); break; } return map; } if (t != JsonString) { setError(QObject::tr("Invalid key: %1") .arg(tokenString(t, m_lastToken))); break; } name = m_lastToken; t = parseToken(); if (t != JsonColon) { setError(QObject::tr("Expected colon instead of: %1") .arg(tokenString(t, m_lastToken))); break; } value = parseValue(); if (m_error) break; map[name] = value; t = parseToken(); if (t == JsonEndObject) return map; if (t != JsonComma) { setError(QObject::tr("Expected comma or closing bracket instead of: %1") .arg(tokenString(t, m_lastToken))); break; } } return QVariant(); } QVariant JsonParser::parseArray() { Token t = JsonNone; QVariant value; QVariantList list; forever { value = parseValue(&t); if (t == JsonError) break; if (t == JsonEndArray) { clearError(); if (!list.isEmpty()) { setError(QObject::tr("Expected more array items")); break; } return list; } list << value; t = parseToken(); if (t == JsonEndArray) return list; if (t != JsonComma) { setError(QObject::tr("Expected comma or closing bracket instead of: %1") .arg(tokenString(t, m_lastToken))); break; } } return QVariant(); } cutechess-20111114+0.4.2+0.0.1/projects/lib/components/json/src/jsonparser.h0000664000175000017500000000525511657223322025302 0ustar oliveroliver/* Copyright (c) 2010 Ilari Pihlajisto Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef JSONPARSER_H #define JSONPARSER_H #include class QTextStream; /*! * \brief A JSON (JavaScript Object Notation) parser. * * JsonParser parses JSON data from a text stream and * converts it into a QVariant. * * JSON specification: http://json.org/ * \sa JsonSerializer */ class LIB_EXPORT JsonParser { public: /*! Creates a new parser that reads data from \a stream. */ JsonParser(QTextStream& stream); /*! * Parses JSON data from the stream. * * Returns a null QVariant object if a parsing error occurs. * Use hasError() to check for errors. */ QVariant parse(); /*! Returns true if a parsing error occured. */ bool hasError() const; /*! Returns a detailed description of the error. */ QString errorString() const; /*! Returns the line number on which the error occured. */ qint64 errorLineNumber() const; private: enum Token { JsonError, JsonGeneric, JsonNone, JsonComma, JsonColon, JsonBeginObject, JsonEndObject, JsonBeginArray, JsonEndArray, JsonTrue, JsonFalse, JsonNull, JsonNumber, JsonString }; static QString tokenString(Token type, const QString& str = QString()); Token parseToken(); QVariant parseValue(Token* tokenType = 0); QVariant parseObject(); QVariant parseArray(); QString parseString(); void setError(const QString& message); void clearError(); bool m_error; qint64 m_currentLine; qint64 m_errorLine; QString m_errorString; QString m_lastToken; QChar m_buffer; QTextStream& m_stream; }; #endif // JSONPARSER_H cutechess-20111114+0.4.2+0.0.1/projects/lib/components/json/src/jsonserializer.h0000664000175000017500000000506411657223322026155 0ustar oliveroliver/* Copyright (c) 2010 Ilari Pihlajisto Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef JSONSERIALIZER_H #define JSONSERIALIZER_H #include #include class QTextStream; /*! * \brief A JSON (JavaScript Object Notation) serializer. * * JsonSerializer converts QVariants into JSON data and writes it * to a text stream. The following QVariant types are supported: * - QVariant::Invalid (JSON null) * - QVariant::Bool (JSON boolean) * - QVariant::ByteArray (JSON string) * - QVariant::List (JSON array) * - QVariant::Map (JSON object) * - QVariant::String (JSON string) * - QVariant::StringList (JSON array) * - any other type that can be converted into a string by QVariant * * JSON specification: http://json.org/ * \sa JsonParser */ class LIB_EXPORT JsonSerializer { public: /*! Creates a new serializer that operates on \a data. */ JsonSerializer(const QVariant& data); /*! * Converts the data into JSON format and writes it to * \a stream. * * Returns false if an invalid or unsupported variant type * is encountered. Otherwise returns true. */ bool serialize(QTextStream& stream); /*! Returns true if an error occured. */ bool hasError() const; /*! Returns a detailed description of the error. */ QString errorString() const; private: bool serializeNode(QTextStream& stream, const QVariant& node, int indentLevel); void setError(const QString& message); bool m_error; const QVariant m_data; QString m_errorString; }; #endif // JSONSERIALIZER_H cutechess-20111114+0.4.2+0.0.1/projects/lib/components/json/src/json.pri0000664000175000017500000000021711657223322024421 0ustar oliveroliverINCLUDEPATH += $$PWD HEADERS += $$PWD/jsonparser.h \ $$PWD/jsonserializer.h SOURCES += $$PWD/jsonparser.cpp \ $$PWD/jsonserializer.cpp cutechess-20111114+0.4.2+0.0.1/projects/lib/components/json/tests/0000775000175000017500000000000011657223322023307 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/projects/lib/components/json/tests/parser/0000775000175000017500000000000011657223322024603 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/projects/lib/components/json/tests/parser/parser.pro0000664000175000017500000000011511657223322026616 0ustar oliveroliverTARGET = tst_jsonparser include(../tests.pri) SOURCES += tst_jsonparser.cpp cutechess-20111114+0.4.2+0.0.1/projects/lib/components/json/tests/parser/sample1.json0000664000175000017500000000110711657223322027037 0ustar oliveroliver{ "glossary": { "title": "example glossary", "GlossDiv": { "title": "S", "GlossList": { "GlossEntry": { "ID": "SGML", "SortAs": "SGML", "GlossTerm": "Standard Generalized Markup Language", "Acronym": "SGML", "Abbrev": "ISO 8879:1986", "GlossDef": { "para": "A meta-markup language, used to create markup languages such as DocBook.", "GlossSeeAlso": ["GML", "XML"] }, "GlossSee": "markup" } } } } } cutechess-20111114+0.4.2+0.0.1/projects/lib/components/json/tests/parser/tst_jsonparser.cpp0000664000175000017500000002134211657223322030371 0ustar oliveroliver/* Copyright (c) 2010 Ilari Pihlajisto Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include class tst_JsonParser: public QObject { Q_OBJECT private slots: void basics_data() const; void basics() const; void invalid_data() const; void invalid() const; void complex_data() const; void complex() const; private: QVariant sample1() const; QVariant sample2() const; }; Q_DECLARE_METATYPE(QVariant) Q_DECLARE_METATYPE(QVariant::Type) void tst_JsonParser::basics_data() const { QTest::addColumn("input"); QTest::addColumn("type"); QTest::addColumn("expected"); QTest::newRow("null") << "null" << QVariant::Invalid << QVariant(); QTest::newRow("true") << "true" << QVariant::Bool << QVariant(true); QTest::newRow("false") << "false" << QVariant::Bool << QVariant(false); QTest::newRow("int") << "1234567890" << QVariant::Int << QVariant(1234567890); QTest::newRow("negative int") << "-1234567890" << QVariant::Int << QVariant(-1234567890); QTest::newRow("64-bit int") << "3567830610840546163" << QVariant::LongLong << QVariant(Q_INT64_C(3567830610840546163)); QTest::newRow("negative 64-bit int") << "-3567830610840546163" << QVariant::LongLong << QVariant(Q_INT64_C(-3567830610840546163)); QTest::newRow("double") << "0.012" << QVariant::Double << QVariant(0.012); QTest::newRow("negative double") << "-0.012" << QVariant::Double << QVariant(-0.012); QTest::newRow("exponent double #1") << "1.234567891234E8" << QVariant::Double << QVariant(123456789.1234); QTest::newRow("exponent double #2") << "1.234567891234e8" << QVariant::Double << QVariant(123456789.1234); QTest::newRow("exponent double #3") << "1.234567891234E+8" << QVariant::Double << QVariant(123456789.1234); QTest::newRow("exponent double #4") << "3.71E-05" << QVariant::Double << QVariant(0.0000371); QTest::newRow("string #1") << "\"\"" << QVariant::String << QVariant(QString()); QTest::newRow("string #2") << "\"JSON string\"" << QVariant::String << QVariant("JSON string"); QTest::newRow("string #3") << "\"line 1\\nline 2\\nline 3\\n\"" << QVariant::String << QVariant("line 1\nline 2\nline 3\n"); QTest::newRow("string #4") << "\"Path = \\\"C:\\\\Program files\\\\foo\\\"\"" << QVariant::String << QVariant("Path = \"C:\\Program files\\foo\""); QTest::newRow("string #5") << "\"\\/\\b\\f\\n\\r\\t\"" << QVariant::String << QVariant("/\b\f\n\r\t"); QTest::newRow("string #6") << "\"\\u2654\\u2659\\u265A\\u265f\"" << QVariant::String << QVariant(QString("%1%2%3%4") .arg(QChar(0x2654)) .arg(QChar(0x2659)) .arg(QChar(0x265A)) .arg(QChar(0x265F))); QVariantMap obj; QTest::newRow("object #1") << "{}" << QVariant::Map << QVariant(obj); obj["foo"] = "bar"; obj["number"] = -25; obj["state"] = QVariant(); QTest::newRow("object #2") << "{\"foo\" : \"bar\", \"number\" : -25, \"state\" : null}" << QVariant::Map << QVariant(obj); obj.clear(); obj["empty array"] = QVariantList(); QTest::newRow("object #3") << "{\"empty array\" : []}" << QVariant::Map << QVariant(obj); QVariantList list; QTest::newRow("array #1") << "[]" << QVariant::List << QVariant(list); list << QVariant(); QTest::newRow("array #2") << "[null]" << QVariant::List << QVariant(list); list.clear(); list << QVariant() << QVariantMap() << "string data" << 1234567890; QTest::newRow("array #3") << "[null, {}, \"string data\", 1234567890]" << QVariant::List << QVariant(list); } void tst_JsonParser::basics() const { QFETCH(QString, input); QFETCH(QVariant::Type, type); QFETCH(QVariant, expected); QTextStream stream(&input, QIODevice::ReadOnly); JsonParser parser(stream); QVariant data(parser.parse()); QCOMPARE(data.type(), type); QCOMPARE(data, expected); } void tst_JsonParser::invalid_data() const { QTest::addColumn("input"); QTest::newRow("invalid #1") << "random text"; QTest::newRow("invalid #2") << "\"endquote missing"; QTest::newRow("invalid #3") << "+256"; QTest::newRow("invalid #4") << "256x"; QTest::newRow("invalid #5") << "100.3.4"; QTest::newRow("invalid #6") << "\"\\u005 \""; QTest::newRow("invalid #7") << "\"\\uffgg\""; QTest::newRow("invalid #8") << "{"; QTest::newRow("invalid #9") << "["; QTest::newRow("invalid #10") << "}"; QTest::newRow("invalid #11") << "]"; QTest::newRow("invalid #12") << "{ ]"; QTest::newRow("invalid #13") << "[ }"; QTest::newRow("invalid #14") << "{ null }"; QTest::newRow("invalid #15") << "{ null, null }"; QTest::newRow("invalid #16") << "{ \"id\" : 1, }"; QTest::newRow("invalid #17") << "{ \"id\" : ,0 }"; QTest::newRow("invalid #18") << "{ , }"; QTest::newRow("invalid #19") << "[ , ]"; QTest::newRow("invalid #20") << "[ \"id\" : 1 ]"; QTest::newRow("invalid #21") << "[ null, ]"; } void tst_JsonParser::invalid() const { QFETCH(QString, input); QTextStream stream(&input, QIODevice::ReadOnly); JsonParser parser(stream); QVariant data(parser.parse()); QVERIFY(data.isNull()); QVERIFY(parser.hasError()); } QVariant tst_JsonParser::sample1() const { QVariantList list; list << "GML" << "XML"; QVariantMap glossDef; glossDef["para"] = "A meta-markup language, used to create markup " "languages such as DocBook."; glossDef["GlossSeeAlso"] = list; QVariantMap glossEntry; glossEntry["ID"] = "SGML"; glossEntry["SortAs"] = "SGML"; glossEntry["GlossTerm"] = "Standard Generalized Markup Language"; glossEntry["Acronym"] = "SGML"; glossEntry["Abbrev"] = "ISO 8879:1986"; glossEntry["GlossDef"] = glossDef; glossEntry["GlossSee"] = "markup"; QVariantMap glossList; glossList["GlossEntry"] = glossEntry; QVariantMap glossDiv; glossDiv["title"] = "S"; glossDiv["GlossList"] = glossList; QVariantMap glossary; glossary["title"] = "example glossary"; glossary["GlossDiv"] = glossDiv; QVariantMap map; map["glossary"] = glossary; return QVariant(map); } QVariant tst_JsonParser::sample2() const { QVariantList list; QVariantMap map; QVariantMap tmp; tmp["id"] = "1001"; tmp["type"] = "Regular"; list << tmp; tmp["id"] = "1002"; tmp["type"] = "Chocolate"; list << tmp; tmp["id"] = "1003"; tmp["type"] = "Blueberry"; list << tmp; tmp["id"] = "1004"; tmp["type"] = "Devil's Food"; list << tmp; QVariantMap batter; batter["batter"] = list; map["id"] = "0001"; map["type"] = "donut"; map["name"] = "Cake"; map["ppu"] = 0.55; map["batters"] = batter; list.clear(); tmp["id"] = "5001"; tmp["type"] = "None"; list << tmp; tmp["id"] = "5002"; tmp["type"] = "Glazed"; list << tmp; tmp["id"] = "5005"; tmp["type"] = "Sugar"; list << tmp; tmp["id"] = "5007"; tmp["type"] = "Powdered Sugar"; list << tmp; tmp["id"] = "5006"; tmp["type"] = "Chocolate with Sprinkles"; list << tmp; tmp["id"] = "5003"; tmp["type"] = "Chocolate"; list << tmp; tmp["id"] = "5004"; tmp["type"] = "Maple"; list << tmp; map["topping"] = list; list.clear(); list << map; return QVariant(list); } void tst_JsonParser::complex_data() const { QTest::addColumn("filename"); QTest::addColumn("type"); QTest::addColumn("expected"); QTest::newRow("complex #1") << "sample1.json" << QVariant::Map << sample1(); QTest::newRow("complex #2") << "sample2.json" << QVariant::List << sample2(); } void tst_JsonParser::complex() const { QFETCH(QString, filename); QFETCH(QVariant::Type, type); QFETCH(QVariant, expected); QFile file(filename); QVERIFY(file.open(QIODevice::Text | QIODevice::ReadOnly)); QTextStream stream(&file); JsonParser parser(stream); QVariant data(parser.parse()); QCOMPARE(data.type(), type); QCOMPARE(data, expected); } QTEST_MAIN(tst_JsonParser) #include "tst_jsonparser.moc" cutechess-20111114+0.4.2+0.0.1/projects/lib/components/json/tests/parser/sample2.json0000664000175000017500000000117511657223322027045 0ustar oliveroliver[ { "id": "0001", "type": "donut", "name": "Cake", "ppu": 0.55, "batters": { "batter": [ { "id": "1001", "type": "Regular" }, { "id": "1002", "type": "Chocolate" }, { "id": "1003", "type": "Blueberry" }, { "id": "1004", "type": "Devil's Food" } ] }, "topping": [ { "id": "5001", "type": "None" }, { "id": "5002", "type": "Glazed" }, { "id": "5005", "type": "Sugar" }, { "id": "5007", "type": "Powdered Sugar" }, { "id": "5006", "type": "Chocolate with Sprinkles" }, { "id": "5003", "type": "Chocolate" }, { "id": "5004", "type": "Maple" } ] } ] cutechess-20111114+0.4.2+0.0.1/projects/lib/components/json/tests/tests.pri0000664000175000017500000000022111657223322025160 0ustar oliveroliverTEMPLATE = app win32:config += CONSOLE CONFIG += qtestlib DEFINES += LIB_EXPORT="" include(../src/json.pri) OBJECTS_DIR = .obj MOC_DIR = .moc cutechess-20111114+0.4.2+0.0.1/projects/lib/components/json/tests/serializer/0000775000175000017500000000000011657223322025460 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/projects/lib/components/json/tests/serializer/tst_jsonserializer.cpp0000664000175000017500000001352411657223322032126 0ustar oliveroliver/* Copyright (c) 2010 Ilari Pihlajisto Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include class tst_JsonSerializer: public QObject { Q_OBJECT private slots: void test_data() const; void test() const; private: QVariant sample1() const; QVariant sample2() const; }; Q_DECLARE_METATYPE(QVariant) QVariant tst_JsonSerializer::sample1() const { QVariantList list; list << "GML" << "XML"; QVariantMap glossDef; glossDef["para"] = "A meta-markup language, used to create markup " "languages such as DocBook."; glossDef["GlossSeeAlso"] = list; QVariantMap glossEntry; glossEntry["ID"] = "SGML"; glossEntry["SortAs"] = "SGML"; glossEntry["GlossTerm"] = "Standard Generalized Markup Language"; glossEntry["Acronym"] = "SGML"; glossEntry["Abbrev"] = "ISO 8879:1986"; glossEntry["GlossDef"] = glossDef; glossEntry["GlossSee"] = "markup"; QVariantMap glossList; glossList["GlossEntry"] = glossEntry; QVariantMap glossDiv; glossDiv["title"] = "S"; glossDiv["GlossList"] = glossList; QVariantMap glossary; glossary["title"] = "example glossary"; glossary["GlossDiv"] = glossDiv; QVariantMap map; map["glossary"] = glossary; return QVariant(map); } QVariant tst_JsonSerializer::sample2() const { QVariantList list; QVariantMap map; QVariantMap tmp; tmp["id"] = "1001"; tmp["type"] = "Regular"; list << tmp; tmp["id"] = "1002"; tmp["type"] = "Chocolate"; list << tmp; tmp["id"] = "1003"; tmp["type"] = "Blueberry"; list << tmp; tmp["id"] = "1004"; tmp["type"] = "Devil's Food"; list << tmp; QVariantMap batter; batter["batter"] = list; map["id"] = "0001"; map["type"] = "donut"; map["name"] = "Cake"; map["ppu"] = 0.55; map["batters"] = batter; list.clear(); tmp["id"] = "5001"; tmp["type"] = "None"; list << tmp; tmp["id"] = "5002"; tmp["type"] = "Glazed"; list << tmp; tmp["id"] = "5005"; tmp["type"] = "Sugar"; list << tmp; tmp["id"] = "5007"; tmp["type"] = "Powdered Sugar"; list << tmp; tmp["id"] = "5006"; tmp["type"] = "Chocolate with Sprinkles"; list << tmp; tmp["id"] = "5003"; tmp["type"] = "Chocolate"; list << tmp; tmp["id"] = "5004"; tmp["type"] = "Maple"; list << tmp; map["topping"] = list; list.clear(); list << map; return QVariant(list); } void tst_JsonSerializer::test_data() const { QTest::addColumn("input"); QTest::newRow("null") << QVariant(); QTest::newRow("true") << QVariant(true); QTest::newRow("false") << QVariant(false); QTest::newRow("int") << QVariant(1234567890); QTest::newRow("negative int") << QVariant(-1234567890); QTest::newRow("64-bit int") << QVariant(Q_INT64_C(3567830610840546163)); QTest::newRow("negative 64-bit int") << QVariant(Q_INT64_C(-3567830610840546163)); QTest::newRow("double") << QVariant(0.012); QTest::newRow("negative double") << QVariant(-0.012); QTest::newRow("exponent double #1") << QVariant(123456789.1234); QTest::newRow("exponent double #2") << QVariant(123456789.1234); QTest::newRow("exponent double #3") << QVariant(123456789.1234); QTest::newRow("exponent double #4") << QVariant(0.0000371); QTest::newRow("string #1") << QVariant(QString()); QTest::newRow("string #2") << QVariant("JSON string"); QTest::newRow("string #3") << QVariant("line 1\nline 2\nline 3\n"); QTest::newRow("string #4") << QVariant("Path = \"C:\\Program files\\foo\""); QTest::newRow("string #5") << QVariant("/\b\f\n\r\t"); QTest::newRow("string #6") << QVariant(QString("%1%2%3%4") .arg(QChar(0x2654)) .arg(QChar(0x2659)) .arg(QChar(0x265A)) .arg(QChar(0x265F))); QVariantMap obj; QTest::newRow("object #1") << QVariant(obj); obj["foo"] = "bar"; obj["number"] = -25; obj["state"] = QVariant(); QTest::newRow("object #2") << QVariant(obj); obj.clear(); obj["empty array"] = QVariantList(); QTest::newRow("object #3") << QVariant(obj); QStringList stringList; stringList << "aA" << "bB" << "cC" << "dD"; obj.clear(); obj["alphabet"] = stringList; QTest::newRow("stringlist") << QVariant(obj); QVariantList list; QTest::newRow("array #1") << QVariant(list); list << QVariant(); QTest::newRow("array #2") << QVariant(list); list.clear(); list << QVariant() << QVariantMap() << "string data" << 1234567890; QTest::newRow("array #3") << QVariant(list); QTest::newRow("complex #1") << sample1(); QTest::newRow("complex #2") << sample2(); } void tst_JsonSerializer::test() const { QFETCH(QVariant, input); JsonSerializer serializer(input); QString str; QTextStream stream(&str, QIODevice::Text | QIODevice::WriteOnly); serializer.serialize(stream); QVERIFY(!serializer.hasError()); stream.setString(&str, QIODevice::ReadOnly); JsonParser parser(stream); QVariant result(parser.parse()); QVERIFY(!parser.hasError()); QCOMPARE(result, input); } QTEST_MAIN(tst_JsonSerializer) #include "tst_jsonserializer.moc" cutechess-20111114+0.4.2+0.0.1/projects/lib/components/json/tests/serializer/serializer.pro0000664000175000017500000000012511657223322030351 0ustar oliveroliverTARGET = tst_jsonserializer include(../tests.pri) SOURCES += tst_jsonserializer.cpp cutechess-20111114+0.4.2+0.0.1/projects/lib/components/json/tests/tests.pro0000664000175000017500000000005711657223322025175 0ustar oliveroliverTEMPLATE = subdirs SUBDIRS = parser serializer cutechess-20111114+0.4.2+0.0.1/projects/lib/src/0000775000175000017500000000000011657223322017576 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/projects/lib/src/gamemanager.h0000664000175000017500000001344411657223322022221 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef GAMEMANAGER_H #define GAMEMANAGER_H #include #include #include class ChessGame; class ChessPlayer; class PlayerBuilder; class GameThread; /*! * \brief A class for managing chess games and players * * GameManager can start games in a new thread, run * multiple games concurrently, and queue games to be * run when a game slot/thread is free. * * \sa ChessGame, PlayerBuilder */ class LIB_EXPORT GameManager : public QObject { Q_OBJECT public: /*! The mode for starting games. */ enum StartMode { /*! The game is started immediately. */ StartImmediately, /*! * The game is added to a queue, and is started when * a game slot becomes free. This could be immediately. */ Enqueue }; /*! The mode for cleaning up after deleted games. */ enum CleanupMode { /*! * The players and their builder objects are deleted * when the game object is deleted. */ DeletePlayers, /*! * The players are left alive after the game is deleted. * If a new game with the same builder objects is started, * the players are reused for that game. */ ReusePlayers }; /*! Creates a new game manager. */ GameManager(QObject* parent = 0); /*! * Returns the list of active games. * * Any game that was started (ie. isn't waiting in the queue) * is considered active even if the game has ended. This is * because the game could still be used for analysis, etc. * The game loses its active status only when it's deleted. */ QList activeGames() const; /*! * Returns the maximum allowed number of concurrent games. * * The concurrency limit only affects games that are started * in Enqueue mode. * * \sa setConcurrency() */ int concurrency() const; /*! * Sets the concurrency limit to \a concurrency. * * \sa concurrency() */ void setConcurrency(int concurrency); /*! * Removes all future games from the queue, waits for * ongoing games to end, and deletes all idle players. * Emits the finished() signal when done. */ void finish(); /*! * Adds a new game to the game manager. * * This function gives control of \a game to the game manager, * which moves the game to its own thread and starts it. Because * the game is played in a separate thread, it must not have a * parent object. When it's not needed anymore, it must be * destroyed with the \a deleteLater() method. Only then will the * game manager free the game slot used by the game. * * Construction of the players is delayed to the moment when the * game starts. If the same builder objects (\a white and \a black) * were used in a previous game, the players are reused instead of * constructing new players. * * If \a mode is StartImmediately, the game starts immediately * even if the number of active games is over the \a concurrency * limit. In \a Enqueue mode the game is started as soon as * a free game slot is available. * * \a cleanupMode determines whether the players and their builder * objects are destroyed or reused after the game. * * Returns true if successfull (ie. the game was added to the queue * or it was started successfully); otherwise returns false. * * \note If there are still free game slots after starting this * game, the ready() signal is emitted immediately. */ bool newGame(ChessGame* game, const PlayerBuilder* white, const PlayerBuilder* black, StartMode startMode = StartImmediately, CleanupMode cleanupMode = DeletePlayers); signals: /*! This signal is emitted when a new game starts. */ void gameStarted(ChessGame* game); /*! * This signal is emitted when a game is destroyed. * * Dereferencing the \a game pointer results in undefined * behavior, so this signal should only be used for cleanup. */ void gameDestroyed(ChessGame* game); /*! * This signal is emitted after a game has started * or after a game has ended, if there are free * game slots. * * \note The signal is NOT emitted if a newly freed * game slot can be used by a game that was waiting in * the queue. */ void ready(); /*! * This signal is emitted when all games have ended and all * idle players have been deleted. Then the manager can be * safely deleted. */ void finished(); /*! This signal redirects the ChessPlayer::debugMessage() signal. */ void debugMessage(const QString& data); private slots: void onGameStarted(); void onThreadReady(); void onThreadQuit(); private: struct GameEntry { ChessGame* game; const PlayerBuilder* white; const PlayerBuilder* black; StartMode startMode; CleanupMode cleanupMode; }; GameThread* getThread(const PlayerBuilder* white, const PlayerBuilder* black); bool startGame(const GameEntry& entry); bool startQueuedGame(); void cleanup(); bool m_finishing; int m_concurrency; int m_activeQueuedGameCount; QList< QPointer > m_threads; QList m_activeThreads; QList m_gameEntries; QList m_activeGames; }; #endif // GAMEMANAGER_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/humanbuilder.h0000664000175000017500000000244011657223322022426 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef HUMANBUILDER_H #define HUMANBUILDER_H #include "playerbuilder.h" #include /*! \brief A class for constructing human players. */ class LIB_EXPORT HumanBuilder : public PlayerBuilder { public: /*! * Creates a new HumanBuilder. * * Any created players will have the name \a playerName, * unless it's an empty string. */ HumanBuilder(const QString& playerName = QString()); // Inherited from PlayerBuilder virtual ChessPlayer* create(QObject* receiver, const char* method, QObject* parent) const; private: QString m_playerName; }; #endif // HUMANBUILDER_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/enginetextoption.cpp0000664000175000017500000000137111657223322023707 0ustar oliveroliver#include "enginetextoption.h" EngineTextOption::EngineTextOption(const QString& name, const QVariant& value, const QVariant& defaultValue, const QString& alias) : EngineOption(name, value, defaultValue, alias) { } EngineOption* EngineTextOption::copy() const { return new EngineTextOption(*this); } bool EngineTextOption::isValid(const QVariant& value) const { return value.canConvert(QVariant::String); } QVariant EngineTextOption::toVariant() const { QVariantMap map; map.insert("type", "text"); map.insert("name", name()); map.insert("value", value()); map.insert("default", defaultValue()); map.insert("alias", alias()); return map; } cutechess-20111114+0.4.2+0.0.1/projects/lib/src/src.pri0000664000175000017500000000272711657223322021111 0ustar oliveroliverinclude(board/board.pri) INCLUDEPATH += $$PWD DEPENDPATH += $$PWD HEADERS += chessengine.h \ chessgame.h \ chessplayer.h \ engineconfiguration.h \ openingbook.h \ pgnstream.h \ pgngame.h \ polyglotbook.h \ timecontrol.h \ uciengine.h \ xboardengine.h \ moveevaluation.h \ enginemanager.h \ humanplayer.h \ engineoption.h \ enginespinoption.h \ enginecombooption.h \ enginecheckoption.h \ enginetextoption.h \ enginebuttonoption.h \ pgngameentry.h \ gamemanager.h \ playerbuilder.h \ enginebuilder.h \ classregistry.h \ enginefactory.h \ humanbuilder.h \ engineoptionfactory.h \ pgngamefilter.h SOURCES += chessengine.cpp \ chessgame.cpp \ chessplayer.cpp \ engineconfiguration.cpp \ openingbook.cpp \ pgnstream.cpp \ pgngame.cpp \ polyglotbook.cpp \ timecontrol.cpp \ uciengine.cpp \ xboardengine.cpp \ moveevaluation.cpp \ enginemanager.cpp \ humanplayer.cpp \ engineoption.cpp \ enginespinoption.cpp \ enginecombooption.cpp \ enginecheckoption.cpp \ enginetextoption.cpp \ enginebuttonoption.cpp \ pgngameentry.cpp \ gamemanager.cpp \ enginebuilder.cpp \ enginefactory.cpp \ humanbuilder.cpp \ engineoptionfactory.cpp \ pgngamefilter.cpp win32 { HEADERS += engineprocess_win.h \ pipereader_win.h SOURCES += engineprocess_win.cpp \ pipereader_win.cpp } cutechess-20111114+0.4.2+0.0.1/projects/lib/src/enginemanager.cpp0000664000175000017500000000537211657223322023111 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "enginemanager.h" #include #include #include #include #include #include EngineManager::EngineManager(QObject* parent) : QObject(parent) { } EngineManager::~EngineManager() { } int EngineManager::engineCount() const { return m_engines.count(); } EngineConfiguration EngineManager::engineAt(int index) const { return m_engines.at(index); } void EngineManager::addEngine(const EngineConfiguration& engine) { m_engines << engine; emit engineAdded(m_engines.size() - 1); } void EngineManager::updateEngineAt(int index, const EngineConfiguration& engine) { m_engines[index] = engine; emit engineUpdated(index); } void EngineManager::removeEngineAt(int index) { emit engineAboutToBeRemoved(index); m_engines.removeAt(index); } QList EngineManager::engines() const { return m_engines; } void EngineManager::setEngines(const QList& engines) { m_engines = engines; emit enginesReset(); } void EngineManager::loadEngines(const QString& fileName) { if (!QFile::exists(fileName)) return; QFile input(fileName); if (!input.open(QIODevice::ReadOnly | QIODevice::Text)) { qWarning() << "cannot open engine configuration file:" << fileName; return; } QTextStream stream(&input); JsonParser parser(stream); const QVariantList engines(parser.parse().toList()); if (parser.hasError()) { qWarning() << "bad engine configuration file line" << parser.errorLineNumber() << "in" << fileName << ":" << parser.errorString(); return; } foreach(const QVariant& engine, engines) addEngine(EngineConfiguration(engine)); } void EngineManager::saveEngines(const QString& fileName) { QVariantList engines; foreach (const EngineConfiguration& config, m_engines) engines << config.toVariant(); QFile output(fileName); if (!output.open(QIODevice::WriteOnly | QIODevice::Text)) { qWarning() << "cannot open engine configuration file:" << fileName; return; } QTextStream out(&output); JsonSerializer serializer(engines); serializer.serialize(out); } cutechess-20111114+0.4.2+0.0.1/projects/lib/src/pipereader_win.cpp0000664000175000017500000000544711657223322023311 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "pipereader_win.h" #include PipeReader::PipeReader(HANDLE pipe, QObject* parent) : QThread(parent), m_pipe(pipe), m_bufEnd(m_buf + BufSize), m_start(m_buf), m_end(m_buf), m_freeBytes(BufSize), m_usedBytes(0), m_lastNewLine(1) { Q_ASSERT(m_pipe != INVALID_HANDLE_VALUE); } qint64 PipeReader::bytesAvailable() const { return qint64(m_usedBytes.available()); } bool PipeReader::canReadLine() const { QMutexLocker locker(&m_mutex); return m_lastNewLine <= m_usedBytes.available(); } qint64 PipeReader::readData(char* data, qint64 maxSize) { int n = qMin(int(maxSize), m_usedBytes.available()); if (n <= 0) return -1; m_usedBytes.acquire(n); // Copy the first (possibly the only) block of data int size1 = qMin(m_bufEnd - m_start, n); memcpy(data, m_start, size_t(size1)); m_start += size1; Q_ASSERT(m_start <= m_bufEnd); if (m_start == m_bufEnd) m_start = m_buf; // Copy the second block of data from the beginning int size2 = n - size1; if (size2 > 0) { memcpy(data + size1, m_start, size_t(size2)); m_start += size2; Q_ASSERT(m_start <= m_bufEnd); if (m_start == m_bufEnd) m_start = m_buf; } Q_ASSERT(n == size1 + size2); m_freeBytes.release(n); return n; } void PipeReader::run() { DWORD dwRead = 0; forever { int maxSize = qMin(BufSize / 10, m_bufEnd - m_end); m_freeBytes.acquire(maxSize); BOOL ok = ReadFile(m_pipe, m_end, maxSize, &dwRead, 0); if (!ok || dwRead == 0) { DWORD err = GetLastError(); if (err != ERROR_INVALID_HANDLE && err != ERROR_BROKEN_PIPE) qWarning("ReadFile failed with 0x%x", int(err)); return; } m_end += dwRead; Q_ASSERT(m_end <= m_bufEnd); QMutexLocker locker(&m_mutex); m_lastNewLine += dwRead; for (int i = 1; i <= int(dwRead); i++) { if (*(m_end - i) == '\n') { m_lastNewLine = i; break; } } if (m_end == m_bufEnd) m_end = m_buf; m_freeBytes.release(maxSize - dwRead); m_usedBytes.release(dwRead); // To avoid signal spam, send the 'readyRead' signal only // if we have a whole line of new data if (m_lastNewLine <= int(dwRead)) emit readyRead(); } } cutechess-20111114+0.4.2+0.0.1/projects/lib/src/classregistry.h0000664000175000017500000000561611657223322022655 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef CLASSREGISTRY_H #define CLASSREGISTRY_H #include #include /*! * Registers a new class. * * \param BASE The base class. * \param TYPE The subclass to register. * \param KEY The key associated with class \a TYPE. * \param REGISTRY A pointer to a ClassRegistry object. * * \note The call to this macro should be in class \a TYPE's * implementation file (.cpp). */ #define REGISTER_CLASS(BASE, TYPE, KEY, REGISTRY) \ static ClassRegistration _class_registration_ ## TYPE(REGISTRY, &ClassRegistry::factory, KEY); /*! * \brief A class for creating objects based on the class' * runtime name or key (a string). * * The created objects of a registry must have the same base class. */ template class ClassRegistry { public: /*! Typedef to the factory function. */ typedef T* (*Factory)(void); /*! * Factory function for creating an object of type \a Subclass, * which must be a subclass of \a T. */ template static T* factory() { return new Subclass; } /*! Returns a list of factory functions. */ const QMap& items() const { return m_items; } /*! Adds a new factory associated with \a key. */ void add(Factory factory, const QString& key) { m_items[key] = factory; } /*! * Creates and returns an object whose type is associated with \a key. * * Returns 0 if there is no type that matches \a key. */ T* create(const QString& key) { if (!m_items.contains(key)) return 0; return m_items[key](); } private: QMap m_items; }; /*! \brief A class for registering a new subclass of the templated class. */ template class ClassRegistration { public: /*! * Creates a new registration object and adds (registers) * a new class to a class registry. * * \param registry A registry where the class is added. * \param factory A factory function for creating instances * of the class. * \param key A key (class name) associated with the class. */ ClassRegistration(ClassRegistry* registry, typename ClassRegistry::Factory factory, const QString& key) { registry->add(factory, key); } }; #endif // CLASSREGISTRY_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/enginespinoption.cpp0000664000175000017500000000243111657223322023672 0ustar oliveroliver#include "enginespinoption.h" EngineSpinOption::EngineSpinOption(const QString& name, const QVariant& value, const QVariant& defaultValue, int min, int max, const QString& alias) : EngineOption(name, value, defaultValue, alias), m_min(min), m_max(max) { } EngineOption* EngineSpinOption::copy() const { return new EngineSpinOption(*this); } bool EngineSpinOption::isValid(const QVariant& value) const { if (m_min > m_max) return false; bool ok = false; int tmp = value.toInt(&ok); if (!ok || ((m_min != 0 || m_max != 0) && (tmp < m_min || tmp > m_max))) return false; return true; } int EngineSpinOption::min() const { return m_min; } int EngineSpinOption::max() const { return m_max; } void EngineSpinOption::setMin(int min) { m_min = min; } void EngineSpinOption::setMax(int max) { m_max = max; } QVariant EngineSpinOption::toVariant() const { QVariantMap map; map.insert("type", "spin"); map.insert("name", name()); map.insert("value", value()); map.insert("default", defaultValue()); map.insert("alias", alias()); map.insert("min", min()); map.insert("max", max()); return map; } cutechess-20111114+0.4.2+0.0.1/projects/lib/src/enginebuttonoption.cpp0000664000175000017500000000067611657223322024245 0ustar oliveroliver#include "enginebuttonoption.h" EngineButtonOption::EngineButtonOption(const QString& name) : EngineOption(name) { } EngineOption* EngineButtonOption::copy() const { return new EngineButtonOption(*this); } bool EngineButtonOption::isValid(const QVariant& value) const { return value.isNull(); } QVariant EngineButtonOption::toVariant() const { QVariantMap map; map.insert("type", "button"); map.insert("name", name()); return map; } cutechess-20111114+0.4.2+0.0.1/projects/lib/src/chessplayer.h0000664000175000017500000001510311657223322022271 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef CHESSPLAYER_H #define CHESSPLAYER_H #include #include #include #include "board/result.h" #include "board/move.h" #include "timecontrol.h" #include "moveevaluation.h" class QTimer; namespace Chess { class Board; } /*! * \brief A chess player, human or AI. * * \sa ChessEngine */ class LIB_EXPORT ChessPlayer : public QObject { Q_OBJECT public: /*! The different states of ChessPlayer. */ enum State { NotStarted, //!< Not started or uninitialized Starting, //!< Starting or initializing Idle, //!< Idle and ready to start a game Observing, //!< Observing a game, or waiting for turn Thinking, //!< Thinking of the next move FinishingGame, //!< Finishing or cleaning up after a game Disconnected //!< Disconnected or terminated }; /*! Creates and initializes a new ChessPlayer object. */ ChessPlayer(QObject* parent = 0); virtual ~ChessPlayer(); /*! * Returns true if the player is ready for input. * * \note When the player's state is \a Disconnected, this * function still returns true if all the cleanup following * the disconnection is done. */ virtual bool isReady() const; /*! Returns the player's state. */ State state() const; /*! * Prepares the player for a new chess game, and then calls * startGame() to start the game. * * \param side The side (color) the player should play as. It * can be NoSide if the player is in force/observer mode. * \param opponent The opposing player. * \param board The chessboard on which the game is played. * * \sa startGame() */ void newGame(Chess::Side side, ChessPlayer* opponent, Chess::Board* board); /*! * Tells the player that the game ended by \a result. * * \note Subclasses that reimplement this function must call * the base implementation. */ virtual void endGame(const Chess::Result& result); /*! Returns the player's evaluation of the current position. */ const MoveEvaluation& evaluation() const; /*! Returns the player's time control. */ const TimeControl* timeControl() const; /*! Sets the time control for the player. */ void setTimeControl(const TimeControl& timeControl); /*! Returns the side of the player. */ Chess::Side side() const; /*! * Sends the next move of an ongoing game to the player. * If the player is in force/observer mode, the move wasn't * necessarily made by the opponent. */ virtual void makeMove(const Chess::Move& move) = 0; /*! Forces the player to play \a move as its next move. */ void makeBookMove(const Chess::Move& move); /*! Returns the player's name. */ QString name() const; /*! Sets the player's name. */ void setName(const QString& name); /*! Returns true if the player can play \a variant. */ virtual bool supportsVariant(const QString& variant) const = 0; /*! Returns true if the player is human. */ virtual bool isHuman() const = 0; public slots: /*! * Waits (without blocking) until the player is ready, * starts the chess clock, and tells the player to start thinking * of the next move. * * \note Subclasses that reimplement this function must call * the base implementation. */ virtual void go(); /*! Terminates the player non-violently. */ virtual void quit(); /*! * Kills the player process or connection, causing it to * exit immediately. * * The player's state is set to \a Disconnected. * * \note Subclasses that reimplement this function must call * the base implementation. */ virtual void kill(); signals: /*! This signal is emitted when the player disconnects. */ void disconnected(); /*! Signals that the player is ready for input. */ void ready() const; /*! * Signals the time left in the player's clock when they * start thinking of their next move. * \param timeLeft Time left in milliseconds. */ void startedThinking(int timeLeft) const; /*! * This signal is emitted when the player stops thinking of * a move. Note that it doesn't necessarily mean that the * player has made a move - they could've lost the game on * time, disconnected, etc. */ void stoppedThinking() const; /*! Signals the player's move. */ void moveMade(const Chess::Move& move) const; /*! Signals that the player forfeits the game. */ void forfeit(const Chess::Result& result) const; /*! Signals a debugging message from the player. */ void debugMessage(const QString& data) const; /*! Emitted when player's name is changed. */ void nameChanged(const QString& name); protected slots: /*! * Called when the player's process or connection * crashes unexpectedly. * * Forfeits the game. */ virtual void onCrashed(); /*! * Called when the player's flag falls. * Forfeits the game. */ virtual void onTimeout(); protected: /*! Returns the chessboard on which the player is playing. */ Chess::Board* board(); /*! Starts the chess game set up by newGame(). */ virtual void startGame() = 0; /*! * Tells the player to start thinking of the next move. * * The player is guaranteed to be ready to move when this * function is called by go(). */ virtual void startThinking() = 0; /*! Emits the forfeit() signal. */ void emitForfeit(Chess::Result::Type type, const QString& description = QString()); /*! * Emits the player's move, and a timeout signal if the * move came too late. */ void emitMove(const Chess::Move& move); /*! Returns the opposing player. */ const ChessPlayer* opponent() const; /*! Sets the player's state to \a state. */ void setState(State state); /*! The current evaluation. */ MoveEvaluation m_eval; private: void startClock(); QString m_name; State m_state; TimeControl m_timeControl; QTimer* m_timer; bool m_forfeited; Chess::Side m_side; Chess::Board* m_board; ChessPlayer* m_opponent; }; #endif // CHESSPLAYER_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/humanplayer.h0000664000175000017500000000446711657223322022307 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef HUMANPLAYER_H #define HUMANPLAYER_H #include "chessplayer.h" #include "board/genericmove.h" /*! * \brief A chess player controlled by a human user. * * A HumanPlayer object works between a graphical chessboard * and a ChessGame object by forwarding the user's moves to the * game. * * Typically human players are created by using a HumanBuilder * object. */ class LIB_EXPORT HumanPlayer : public ChessPlayer { Q_OBJECT public: /*! Creates a new human player. */ HumanPlayer(QObject* parent = 0); // Inherted from ChessPlayer virtual void endGame(const Chess::Result& result); virtual void makeMove(const Chess::Move& move); virtual bool supportsVariant(const QString& variant) const; virtual bool isHuman() const; public slots: /*! * Plays \a move as the human player's next move if * \a side is the player's side and the move is legal; * otherwise does nothing. * * If the player is in \a Thinking state, it plays * the move immediately. If its in \a Observing state, * it saves the move for later, emits the wokeUp() signal, * and plays the move when it gets its turn. */ void onHumanMove(const Chess::GenericMove& move, const Chess::Side& side); signals: /*! * This signal is emitted when the player receives a * user-made move in \a Observing state. * * Normally this signal is connected to ChessGame::resume() * to resume a paused game when the user makes a move. */ void wokeUp(); protected: // Inherited from ChessPlayer virtual void startGame(); virtual void startThinking(); private: Chess::GenericMove m_bufferMove; }; #endif // HUMANPLAYER_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/engineoptionfactory.cpp0000664000175000017500000000452011657223322024371 0ustar oliveroliver#include "engineoptionfactory.h" #include #include "engineoption.h" #include "enginetextoption.h" #include "enginebuttonoption.h" #include "enginecheckoption.h" #include "enginecombooption.h" #include "enginespinoption.h" EngineOption* EngineOptionFactory::create(const QVariantMap& map) { // TODO: use isValid() for each option const QString name = map["name"].toString(); const QString type = map["type"].toString(); const QVariant value = map["value"]; QVariant defaultValue = map["default"]; const QString alias = map["alias"].toString(); if (name.isEmpty()) { qWarning() << "Empty option name"; return 0; } // Special case for the button option type: its value is the name if (type == "button") return new EngineButtonOption(name); if (value.type() != QVariant::Bool && value.type() != QVariant::String && value.type() != QVariant::Int) { qWarning() << "Invalid value type for option:" << name; return 0; } if (defaultValue.isNull()) defaultValue = value; else if (defaultValue.type() != QVariant::Bool && defaultValue.type() != QVariant::String && defaultValue.type() != QVariant::Int) { qWarning() << "Invalid default value type for option:" << name; return 0; } // If the option type has not been defined, use text option as // a default option type if (type.isEmpty()) { return new EngineTextOption(name, value.toString(), defaultValue.toString(), alias); } else if (type == "text") { return new EngineTextOption(name, value.toString(), defaultValue.toString(), alias); } else if (type == "check") { return new EngineCheckOption(name, value.toBool(), defaultValue.toBool(), alias); } else if (type == "combo") { const QVariant choices = map["choices"]; if (choices.type() != QVariant::StringList) return 0; return new EngineComboOption(name, value.toString(), defaultValue.toString(), choices.toStringList(), alias); } else if (type == "spin") { int intValue, defaultIntValue, minValue, maxValue; bool ok; intValue = value.toInt(&ok); if (!ok) return 0; defaultIntValue = defaultValue.toInt(&ok); if (!ok) return 0; minValue = map["min"].toInt(&ok); if (!ok) return 0; maxValue = map["max"].toInt(&ok); if (!ok) return 0; return new EngineSpinOption(name, intValue, defaultIntValue, minValue, maxValue, alias); } return 0; } cutechess-20111114+0.4.2+0.0.1/projects/lib/src/uciengine.cpp0000664000175000017500000002513211657223322022253 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "uciengine.h" #include #include #include #include "board/board.h" #include "board/boardfactory.h" #include "timecontrol.h" #include "enginebuttonoption.h" #include "enginecheckoption.h" #include "enginecombooption.h" #include "enginespinoption.h" #include "enginetextoption.h" UciEngine::UciEngine(QObject* parent) : ChessEngine(parent), m_sendOpponentsName(false) { addVariant("standard"); setName("UciEngine"); } void UciEngine::startProtocol() { // Tell the engine to turn on UCI mode write("uci"); } void UciEngine::sendPosition() { QString str("position"); if (board()->isRandomVariant() || m_startFen != board()->defaultFenString()) str += QString(" fen ") + m_startFen; else str += " startpos"; if (!m_moveStrings.isEmpty()) str += QString(" moves") + m_moveStrings; write(str); } static QString variantFromUci(const QString& str) { if (str.size() < 5 || !str.startsWith("UCI_")) return QString(); QString variant; if (str == "UCI_Chess960") variant = "fischerandom"; else variant = str.mid(4).toLower(); if (!Chess::BoardFactory::variants().contains(variant)) return QString(); return variant; } static QString variantToUci(const QString& str) { if (str.isEmpty() || str == "standard") return QString(); if (str == "fischerandom") return "UCI_Chess960"; if (str == "caparandom") return "UCI_CapaRandom"; QString tmp = QString("UCI_%1").arg(str); tmp[4] = tmp.at(4).toUpper(); return tmp; } void UciEngine::startGame() { Q_ASSERT(supportsVariant(board()->variant())); m_moveStrings.clear(); if (board()->isRandomVariant()) m_startFen = board()->fenString(Chess::Board::ShredderFen); else m_startFen = board()->fenString(Chess::Board::XFen); QString uciVariant(variantToUci(board()->variant())); if (uciVariant != m_variantOption) { if (!m_variantOption.isEmpty()) sendOption(m_variantOption, "false"); m_variantOption = uciVariant; } if (!m_variantOption.isEmpty()) sendOption(m_variantOption, "true"); write("ucinewgame"); if (m_sendOpponentsName) { QString opType = opponent()->isHuman() ? "human" : "computer"; QString value = QString("none none %1 %2") .arg(opType) .arg(opponent()->name()); sendOption("UCI_Opponent", value); } sendPosition(); } void UciEngine::endGame(const Chess::Result& result) { stopThinking(); ChessEngine::endGame(result); } void UciEngine::makeMove(const Chess::Move& move) { m_moveStrings += " " + board()->moveString(move, Chess::Board::LongAlgebraic); sendPosition(); } void UciEngine::startThinking() { const TimeControl* whiteTc = 0; const TimeControl* blackTc = 0; const TimeControl* myTc = timeControl(); if (side() == Chess::Side::White) { whiteTc = myTc; blackTc = opponent()->timeControl(); } else if (side() == Chess::Side::Black) { whiteTc = opponent()->timeControl(); blackTc = myTc; } else qFatal("Player %s doesn't have a side", qPrintable(name())); QString command = "go"; if (myTc->isInfinite()) command += " infinite"; else if (myTc->timePerMove() > 0) command += QString(" movetime %1").arg(myTc->timeLeft()); else { command += QString(" wtime %1").arg(whiteTc->timeLeft()); command += QString(" btime %1").arg(blackTc->timeLeft()); if (whiteTc->timeIncrement() > 0) command += QString(" winc %1").arg(whiteTc->timeIncrement()); if (blackTc->timeIncrement() > 0) command += QString(" binc %1").arg(blackTc->timeIncrement()); if (myTc->movesLeft() > 0) command += QString(" movestogo %1").arg(myTc->movesLeft()); } if (myTc->plyLimit() > 0) command += QString(" depth %1").arg(myTc->plyLimit()); if (myTc->nodeLimit() > 0) command += QString(" nodes %1").arg(myTc->nodeLimit()); write(command); } void UciEngine::sendStop() { write("stop"); } QString UciEngine::protocol() const { return "uci"; } bool UciEngine::sendPing() { write("isready"); return true; } void UciEngine::sendQuit() { write("quit"); } QStringRef UciEngine::parseUciTokens(const QStringRef& first, const QString* types, int typeCount, QVarLengthArray& tokens, int& type) { QStringRef token(first); type = -1; tokens.clear(); do { bool newType = false; for (int i = 0; i < typeCount; i++) { if (token == types[i]) { if (type != -1) return token; type = i; newType = true; break; } } if (!newType && type != -1) tokens.append(token); } while (!(token = nextToken(token)).isNull()); return token; } static QStringRef joinTokens(const QVarLengthArray& tokens) { Q_ASSERT(!tokens.isEmpty()); const QStringRef& last = tokens[tokens.size() - 1]; int start = tokens[0].position(); int end = last.position() + last.size(); return QStringRef(last.string(), start, end - start); } void UciEngine::parseInfo(const QVarLengthArray& tokens, int type) { enum Keyword { InfoDepth, InfoSelDepth, InfoTime, InfoNodes, InfoPv, InfoMultiPv, InfoScore, InfoCurrMove, InfoCurrMoveNumber, InfoHashFull, InfoNps, InfoTbHits, InfoCpuLoad, InfoString, InfoRefutation, InfoCurrLine }; if (tokens.isEmpty()) return; switch (type) { case InfoDepth: m_eval.setDepth(tokens[0].toString().toInt()); break; case InfoTime: m_eval.setTime(tokens[0].toString().toInt()); break; case InfoNodes: m_eval.setNodeCount(tokens[0].toString().toInt()); break; case InfoPv: m_eval.setPv(joinTokens(tokens).toString()); break; case InfoScore: { int score = 0; for (int i = 1; i < tokens.size(); i++) { if (tokens[i - 1] == "cp") { score = tokens[i].toString().toInt(); if (whiteEvalPov() && side() == Chess::Side::Black) score = -score; } else if (tokens[i - 1] == "mate") { score = tokens[i].toString().toInt(); if (score > 0) score = 30001 - score * 2; else if (score < 0) score = -30000 - score * 2; } else if (tokens[i - 1] == "lowerbound" || tokens[i - 1] == "upperbound") return; i++; } m_eval.setScore(score); } break; default: break; } } void UciEngine::parseInfo(const QStringRef& line) { static const QString types[] = { "depth", "seldepth", "time", "nodes", "pv", "multipv", "score", "currmove", "currmovenumber", "hashfull", "nps", "tbhits", "cpuload", "string", "refutation", "currline" }; int type = -1; QStringRef token(nextToken(line)); QVarLengthArray tokens; while (!token.isNull()) { token = parseUciTokens(token, types, 16, tokens, type); parseInfo(tokens, type); } } EngineOption* UciEngine::parseOption(const QStringRef& line) { enum Keyword { OptionName, OptionType, OptionDefault, OptionMin, OptionMax, OptionVar }; static const QString types[] = { "name", "type", "default", "min", "max", "var" }; QString name; QString type; QString value; QStringList choices; int min = 0; int max = 0; int keyword = -1; QStringRef token(nextToken(line)); QVarLengthArray tokens; while (!token.isNull()) { token = parseUciTokens(token, types, 6, tokens, keyword); if (tokens.isEmpty() || keyword == -1) continue; QString str(joinTokens(tokens).toString()); switch (keyword) { case OptionName: name = str; break; case OptionType: type = str; break; case OptionDefault: value = str; break; case OptionMin: min = str.toInt(); break; case OptionMax: max = str.toInt(); break; case OptionVar: choices << str; break; } } if (name.isEmpty()) return 0; if (type == "button") return new EngineButtonOption(name); else if (type == "check") { if (value == "true") return new EngineCheckOption(name, true, true); else return new EngineCheckOption(name, false, false); } else if (type == "combo") return new EngineComboOption(name, value, value, choices); else if (type == "spin") return new EngineSpinOption(name, value.toInt(), value.toInt(), min, max); else if (type == "string") return new EngineTextOption(name, value, value); return 0; } void UciEngine::parseLine(const QString& line) { const QStringRef command(firstToken(line)); if (command == "info") { parseInfo(command); } else if (command == "bestmove") { if (state() != Thinking) { if (state() == FinishingGame) pong(); else qDebug() << "Unexpected move from" << name(); return; } QString moveString(nextToken(command).toString()); m_moveStrings += " " + moveString; Chess::Move move = board()->moveFromString(moveString); if (!move.isNull()) emitMove(move); else emitForfeit(Chess::Result::IllegalMove, moveString); } else if (command == "readyok") { pong(); } else if (command == "uciok") { if (state() == Starting) { onProtocolStart(); ping(); } } else if (command == "id") { QStringRef tag(nextToken(command)); if (tag == "name" && name() == "UciEngine") setName(nextToken(tag, true).toString()); } else if (command == "registration") { if (nextToken(command) == "error") { qDebug() << "Failed to register UCI engine" << name(); write("register later"); } } else if (command == "option") { EngineOption* option = parseOption(command); QString variant; if (option == 0 || !option->isValid()) qDebug() << "Invalid UCI option from" << name() << ":" << line; else if (!(variant = variantFromUci(option->name())).isEmpty()) addVariant(variant); else if (option->name() == "UCI_Opponent") m_sendOpponentsName = true; else if (option->name() == "Ponder" || (option->name().startsWith("UCI_") && option->name() != "UCI_LimitStrength" && option->name() != "UCI_Elo")) { // TODO: Deal with UCI features } else { addOption(option); return; } delete option; } } void UciEngine::sendOption(const QString& name, const QString& value) { if (!value.isEmpty()) write(QString("setoption name %1 value %2").arg(name).arg(value)); else write(QString("setoption name %1").arg(name)); } cutechess-20111114+0.4.2+0.0.1/projects/lib/src/pipereader_win.h0000664000175000017500000000426411657223322022752 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef PIPEREADER_WIN_H #define PIPEREADER_WIN_H #include #include #include #include /*! * \brief A thread class for reading input from a child process * * PipeReader is intended for reading input from chess engines in Windows. * It uses blocking read calls to read from a WinAPI pipe, and * sends the readyRead() signal when a new line of text data is available. * * No event loops are used. The child process has to terminate or be * terminated before the pipe reader can exit cleanly. * * \note This class is for Windows only * \sa EngineProcess */ class LIB_EXPORT PipeReader : public QThread { Q_OBJECT public: /*! Creates a new PipeReader and starts the read loop. */ PipeReader(HANDLE pipe, QObject* parent = 0); /*! * Read up to \a maxSize bytes into \a data. * \return number of bytes read or -1 if an error occurred. */ qint64 readData(char* data, qint64 maxSize); /*! Returns the number of bytes available for reading. */ qint64 bytesAvailable() const; /*! Returns true if a complete line of data can be read. */ bool canReadLine() const; signals: /*! There's a new line of data available. */ void readyRead(); protected: virtual void run(); private: static const int BufSize = 0x8000; HANDLE m_pipe; char m_buf[BufSize]; const char* const m_bufEnd; char* m_start; char* m_end; mutable QMutex m_mutex; QSemaphore m_freeBytes; QSemaphore m_usedBytes; int m_lastNewLine; }; #endif // PIPEREADER_WIN_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/uciengine.h0000664000175000017500000000405511657223322021721 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef UCIENGINE_H #define UCIENGINE_H #include "chessengine.h" #include /*! * \brief A chess engine which uses the UCI chess interface. * * UCI's specifications: http://wbec-ridderkerk.nl/html/UCIProtocol.html */ class LIB_EXPORT UciEngine : public ChessEngine { Q_OBJECT public: /*! Creates a new UciEngine. */ UciEngine(QObject* parent = 0); // Inherited from ChessEngine virtual void endGame(const Chess::Result& result); virtual void makeMove(const Chess::Move& move); virtual QString protocol() const; protected: // Inherited from ChessEngine virtual bool sendPing(); virtual void sendStop(); virtual void sendQuit(); virtual void startProtocol(); virtual void startGame(); virtual void startThinking(); virtual void parseLine(const QString& line); virtual void sendOption(const QString& name, const QString& value); private: static QStringRef parseUciTokens(const QStringRef& first, const QString* types, int typeCount, QVarLengthArray& tokens, int& type); void parseInfo(const QVarLengthArray& tokens, int type); void parseInfo(const QStringRef& line); EngineOption* parseOption(const QStringRef& line); void sendPosition(); QString m_variantOption; QString m_startFen; QString m_moveStrings; bool m_sendOpponentsName; }; #endif // UCIENGINE_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/polyglotbook.h0000664000175000017500000000116411657223322022475 0ustar oliveroliver#ifndef POLYGLOT_BOOK_H #define POLYGLOT_BOOK_H #include "openingbook.h" /*! * \brief Opening book which uses the Polyglot book format. * * The Polyglot opening book format is used by chess engines like * Fruit, Toga, and Glaurung, and of course the UCI to Xboard adapter * Polyglot. * * Specs: http://alpha.uhasselt.be/Research/Algebra/Toga/book_format.html */ class LIB_EXPORT PolyglotBook: public OpeningBook { protected: // Inherited from OpeningBook virtual void readEntry(QDataStream& in); virtual void writeEntry(const Map::const_iterator& it, QDataStream& out) const; }; #endif // POLYGLOT_BOOK_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/engineoption.h0000664000175000017500000000176011657223322022451 0ustar oliveroliver#ifndef ENGINEOPTION_H #define ENGINEOPTION_H #include #include class LIB_EXPORT EngineOption { public: explicit EngineOption(const QString& name, const QVariant& value = QVariant(), const QVariant& defaultValue = QVariant(), const QString& alias = QString()); virtual ~EngineOption(); /*! Creates and returns a deep copy of this option. */ virtual EngineOption* copy() const = 0; bool isValid() const; virtual bool isValid(const QVariant& value) const = 0; QString name() const; QVariant value() const; QVariant defaultValue() const; QString alias() const; void setName(const QString& name); void setValue(const QVariant& value); void setDefaultValue(const QVariant& value); void setAlias(const QString& alias); virtual QVariant toVariant() const = 0; private: QString m_name; QVariant m_value; QVariant m_defaultValue; QString m_alias; }; #endif // ENGINEOPTION_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/enginebuilder.cpp0000664000175000017500000000421511657223322023120 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "enginebuilder.h" #include #include #include "engineprocess.h" #include "enginefactory.h" EngineBuilder::EngineBuilder(const EngineConfiguration& config) : m_config(config) { } ChessPlayer* EngineBuilder::create(QObject* receiver, const char* method, QObject* parent) const { QString path(QDir::currentPath()); EngineProcess* process = new EngineProcess(); QString workDir = m_config.workingDirectory(); if (workDir.isEmpty()) process->setWorkingDirectory(QDir::tempPath()); else { // Make sure the path to the executable is resolved // in the engine's working directory if (!QDir::setCurrent(workDir)) { qWarning() << "Invalid working directory:" << workDir; delete process; return 0; } process->setWorkingDirectory(QDir::currentPath()); } if (!m_config.arguments().isEmpty()) process->start(m_config.command(), m_config.arguments()); else process->start(m_config.command()); bool ok = process->waitForStarted(); if (!workDir.isEmpty()) QDir::setCurrent(path); if (!ok) { qWarning() << "Cannot start engine" << m_config.command(); delete process; return 0; } ChessEngine* engine = EngineFactory::create(m_config.protocol()); Q_ASSERT(engine != 0); engine->setParent(parent); if (receiver != 0 && method != 0) QObject::connect(engine, SIGNAL(debugMessage(QString)), receiver, method); engine->setDevice(process); engine->applyConfiguration(m_config); engine->start(); return engine; } cutechess-20111114+0.4.2+0.0.1/projects/lib/src/humanbuilder.cpp0000664000175000017500000000224411657223322022763 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "humanbuilder.h" #include "humanplayer.h" HumanBuilder::HumanBuilder(const QString& playerName) : m_playerName(playerName) { } ChessPlayer* HumanBuilder::create(QObject *receiver, const char *method, QObject *parent) const { ChessPlayer* player = new HumanPlayer(parent); if (!m_playerName.isEmpty()) player->setName(m_playerName); if (receiver != 0 && method != 0) QObject::connect(player, SIGNAL(debugMessage(QString)), receiver, method); return player; } cutechess-20111114+0.4.2+0.0.1/projects/lib/src/engineprocess_win.h0000664000175000017500000001043011657223322023466 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef ENGINEPROCESS_WIN_H #define ENGINEPROCESS_WIN_H #include #include #include class PipeReader; /*! * \brief A replacement for QProcess on Windows * * Due to polling, QProcess' response times on Windows are too slow for * chess engines. EngineProcess is a different implementation which reads * new data immediately (no polling) when it's available. The interface is * the same as QProcess' with some unneeded features left out. * * On non-Windows platforms EngineProcess is just a typedef to QProcess. * * \sa QProcess * \sa PipeReader */ class LIB_EXPORT EngineProcess : public QIODevice { Q_OBJECT public: /*! The process' exit status. */ enum ExitStatus { NormalExit, //!< The process exited normally CrashExit //!< The process crashed }; /*! Creates a new EngineProcess. */ explicit EngineProcess(QObject* parent = 0); /*! * Destructs the EngineProcess and frees all resources. * If the process is still running, it is killed. */ virtual ~EngineProcess(); // Inherited from QIODevice virtual qint64 bytesAvailable() const; virtual bool canReadLine() const; virtual void close(); virtual bool isSequential() const; /*! Returns the exit code of the last process that finished. */ int exitCode() const; /*! Returns the exit status of the last process that finished. */ ExitStatus exitStatus() const; /*! * Returns the process' working directory. * Returns an empty string if the working directory wasn't * set with setWorkingDirectory(). */ QString workingDirectory() const; /*! * Sets the working directory to dir. * EngineProcess will start the process in this directory. */ void setWorkingDirectory(const QString& dir); /*! * Starts the program \a program in a new process, passing the * command line arguments in \a arguments. The OpenMode is set * to \a mode. * * \note Unlike the same function in QProcess, this one will * block until the process has started. * * \note To check if the process started successfully, call * the waitForStarted() method. */ void start(const QString& program, const QStringList& arguments, OpenMode mode = ReadWrite); /*! Starts the program \a program with OpenMode \a mode. */ void start(const QString& program, OpenMode mode = ReadWrite); /*! * Blocks until the process has finished and the finished() * signal has been emitted. * * Times out after \a msecs milliseconds. If \a msecs is -1 * the function will not time out. * * \return true if the process finished. */ bool waitForFinished(int msecs = 30000); /*! * Returns true if the process started successfully. * Doesn't really wait for anything since the start() method * already did the waiting. */ bool waitForStarted(int msecs = 30000); public slots: /*! Kills the process, causing it to exit immediately. */ void kill(); signals: /*! * Emitted when the process finishes. * \param exitCode exit code of the process * \param exitStatus exit status of the process */ void finished(int exitCode, ExitStatus exitStatus); protected: // Inherited from QIODevice virtual qint64 readData(char* data, qint64 maxSize); virtual qint64 writeData(const char* data, qint64 maxSize); private slots: void onFinished(); private: void cleanup(); void killHandle(HANDLE* handle); bool m_started; bool m_finished; DWORD m_exitCode; ExitStatus m_exitStatus; QString m_workDir; PROCESS_INFORMATION m_processInfo; HANDLE m_inWrite; HANDLE m_outRead; PipeReader* m_reader; }; #endif // ENGINEPROCESS_WIN_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/enginecombooption.h0000664000175000017500000000137611657223322023474 0ustar oliveroliver#ifndef ENGINECOMBOOPTION_H #define ENGINECOMBOOPTION_H #include "engineoption.h" #include class LIB_EXPORT EngineComboOption : public EngineOption { public: EngineComboOption(const QString& name, const QVariant& value = QVariant(), const QVariant& defaultValue = QVariant(), const QStringList& choices = QStringList(), const QString& alias = QString()); // Inherited from EngineOption virtual EngineOption* copy() const; virtual bool isValid(const QVariant& value) const; virtual QVariant toVariant() const; QStringList choices() const; void setChoices(const QStringList& choices); private: QStringList m_choices; }; #endif // ENGINECOMBOOPTION_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/engineoption.cpp0000664000175000017500000000203611657223322023001 0ustar oliveroliver#include "engineoption.h" EngineOption::EngineOption(const QString& name, const QVariant& value, const QVariant& defaultValue, const QString& alias) : m_name(name), m_value(value), m_defaultValue(defaultValue), m_alias(alias) { } EngineOption::~EngineOption() { } bool EngineOption::isValid() const { if (m_name.isEmpty()) return false; if (!isValid(m_value)) return false; if (!m_defaultValue.isNull() && !isValid(m_defaultValue)) return false; return true; } QString EngineOption::name() const { return m_name; } QVariant EngineOption::value() const { return m_value; } QVariant EngineOption::defaultValue() const { return m_defaultValue; } QString EngineOption::alias() const { return m_alias; } void EngineOption::setName(const QString& name) { m_name = name; } void EngineOption::setValue(const QVariant& value) { m_value = value; } void EngineOption::setDefaultValue(const QVariant& value) { m_defaultValue = value; } void EngineOption::setAlias(const QString& alias) { m_alias = alias; } cutechess-20111114+0.4.2+0.0.1/projects/lib/src/enginebuttonoption.h0000664000175000017500000000061411657223322023702 0ustar oliveroliver#ifndef ENGINEBUTTONOPTION_H #define ENGINEBUTTONOPTION_H #include "engineoption.h" class LIB_EXPORT EngineButtonOption : public EngineOption { public: EngineButtonOption(const QString& name); // Inherited from EngineOption virtual EngineOption* copy() const; virtual bool isValid(const QVariant& value) const; virtual QVariant toVariant() const; }; #endif // ENGINEBUTTONOPTION_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/enginefactory.h0000664000175000017500000000171211657223322022605 0ustar oliveroliver#ifndef ENGINEFACTORY_H #define ENGINEFACTORY_H #include #include "classregistry.h" #include "chessengine.h" /*! \brief A factory for creating ChessEngine objects. */ class LIB_EXPORT EngineFactory { public: /*! Returns the class registry for concrete ChessEngine subclasses. */ static ClassRegistry* registry(); /*! * Creates and returns a new engine that uses protocol \a protocol. * Returns 0 if no engine class is associated with \a protocol. */ static ChessEngine* create(const QString& protocol); /*! Returns a list of supported chess protocols. */ static QStringList protocols(); private: EngineFactory(); }; /*! * Registers engine class \a TYPE with protocol name \a PROTOCOL. * * This macro must be called once for every concrete ChessEngine class. */ #define REGISTER_ENGINE_CLASS(TYPE, PROTOCOL) \ REGISTER_CLASS(ChessEngine, TYPE, PROTOCOL, EngineFactory::registry()); #endif // ENGINEFACTORY_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/enginefactory.cpp0000664000175000017500000000076711657223322023151 0ustar oliveroliver#include "enginefactory.h" #include "xboardengine.h" #include "uciengine.h" REGISTER_ENGINE_CLASS(XboardEngine, "xboard") REGISTER_ENGINE_CLASS(UciEngine, "uci") ClassRegistry* EngineFactory::registry() { static ClassRegistry* registry = new ClassRegistry; return registry; } ChessEngine* EngineFactory::create(const QString& protocol) { return registry()->create(protocol); } QStringList EngineFactory::protocols() { return registry()->items().keys(); } cutechess-20111114+0.4.2+0.0.1/projects/lib/src/pgngame.h0000664000175000017500000001337611657223322021377 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef PGNGAME_H #define PGNGAME_H #include #include #include #include #include "board/genericmove.h" #include "board/result.h" class QTextStream; class PgnStream; namespace Chess { class Board; } /*! * \brief A game of chess in PGN format. * * PGN (Portable game notation) is a text format for chess games. * Specification: http://www.very-best.de/pgn-spec.htm * * PgnGame is a middle format between text-based PGN games and games * played by Cute Chess. PgnGame objects are used for converting played * games to PGN format, importing PGN data to opening books, analyzing * previous games on a graphical board, etc. * * \sa PgnStream * \sa ChessGame */ class LIB_EXPORT PgnGame { public: /*! The mode for writing PGN games. */ enum PgnMode { //! Only use data which is required by the PGN standard Minimal, //! Use additional data like extra tags and comments Verbose }; /*! \brief A struct for storing the game's move history. */ struct MoveData { /*! The zobrist position key before the move. */ quint64 key; /*! The move in the "generic" format. */ Chess::GenericMove move; /*! The move in Standard Algebraic Notation. */ QString moveString; /*! A comment/annotation describing the move. */ QString comment; }; /*! Creates a new PgnGame object. */ PgnGame(); /*! Returns true if the game doesn't contain any tags or moves. */ bool isNull() const; /*! Deletes all tags and moves. */ void clear(); /*! Returns the moves that were played in the game. */ const QVector& moves() const; /*! Adds a new move to the game. */ void addMove(const MoveData& data); /*! * Creates a board object for viewing or analyzing the game. * * The board is set to the game's starting position. * Returns 0 on error. */ Chess::Board* createBoard() const; /*! * Reads a game from a PGN text stream. * * \param in The PGN stream to read from. * \param maxMoves The maximum number of halfmoves to read. * * \note Even if the stream contains multiple games, * only one will be read. * * Returns true if any tags and/or moves were read. */ bool read(PgnStream& in, int maxMoves = 1000); /*! Writes the game to a text stream. */ void write(QTextStream& out, PgnMode mode = Verbose) const; /*! * Writes the game to a file. * If the file already exists, the game will be appended * to the end of the file. * * Returns true if successfull. */ bool write(const QString& filename, PgnMode mode = Verbose) const; /*! * Returns the value of tag \a tag. * If \a tag doesn't exist, an empty string is returned. */ QString tagValue(const QString& tag) const; /*! Returns the name of the tournament or match event. */ QString event() const; /*! Returns the location of the event. */ QString site() const; /*! Returns the starting date of the game. */ QDate date() const; /*! Returns the the playing round ordinal of the game. */ int round() const; /*! Returns the player's name who plays \a side. */ QString playerName(Chess::Side side) const; /*! Returns the result of the game. */ Chess::Result result() const; /*! Returns the chess variant of the game. */ QString variant() const; /*! Returns the side that starts the game. */ Chess::Side startingSide() const; /*! Returns the starting position's FEN string. */ QString startingFenString() const; /*! * Sets \a tag's value to \a value. * If \a tag doesn't exist, a new tag is created. */ void setTag(const QString& tag, const QString& value); /*! Sets the name of the tournament or match event. */ void setEvent(const QString& event); /*! Sets the location of the event. */ void setSite(const QString& site); /*! Sets the starting date of the game. */ void setDate(const QDate& date); /*! Sets the playing round ordinal of the game. */ void setRound(int round); /*! Sets the player's name who plays \a side. */ void setPlayerName(Chess::Side side, const QString& name); /*! Sets the result of the game. */ void setResult(const Chess::Result& result); /*! Sets the chess variant of the game. */ void setVariant(const QString& variant); /*! Sets the side that starts the game. */ void setStartingSide(Chess::Side side); /*! Sets the starting position's FEN string. */ void setStartingFenString(Chess::Side side, const QString& fen); /*! * Sets a description for the result. * * The description is appended to the last move's comment/annotation. * \note This is not the same as the "Termination" tag which can * only hold one of the standardized values. */ void setResultDescription(const QString& description); private: bool parseMove(PgnStream& in); Chess::Side m_startingSide; QMap m_tags; QVector m_moves; }; /*! Reads a PGN game from a PGN stream. */ extern LIB_EXPORT PgnStream& operator>>(PgnStream& in, PgnGame& game); /*! Writes a PGN game in verbose mode to a text stream. */ extern LIB_EXPORT QTextStream& operator<<(QTextStream& out, const PgnGame& game); #endif // PGNGAME_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/chessgame.cpp0000664000175000017500000003343611657223322022252 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "chessgame.h" #include #include #include #include "board/board.h" #include "chessplayer.h" #include "openingbook.h" ChessGame::ChessGame(Chess::Board* board, PgnGame* pgn, QObject* parent) : QObject(parent), m_board(board), m_startDelay(0), m_finished(false), m_gameInProgress(false), m_paused(false), m_drawMoveNum(0), m_drawScore(0), m_drawScoreCount(0), m_resignMoveCount(0), m_resignScore(0), m_pgn(pgn) { Q_ASSERT(pgn != 0); for (int i = 0; i < 2; i++) { m_resignScoreCount[i] = 0; m_player[i] = 0; m_book[i] = 0; m_bookDepth[i] = 0; } emit humanEnabled(false); } ChessGame::~ChessGame() { delete m_board; } ChessPlayer* ChessGame::player(Chess::Side side) const { Q_ASSERT(!side.isNull()); return m_player[side]; } bool ChessGame::isFinished() const { return m_finished; } PgnGame* ChessGame::pgn() const { return m_pgn; } Chess::Board* ChessGame::board() const { return m_board; } QString ChessGame::startingFen() const { return m_startingFen; } const QVector& ChessGame::moves() const { return m_moves; } Chess::Result ChessGame::result() const { return m_result; } ChessPlayer* ChessGame::playerToMove() { if (m_board->sideToMove().isNull()) return 0; return m_player[m_board->sideToMove()]; } ChessPlayer* ChessGame::playerToWait() { if (m_board->sideToMove().isNull()) return 0; return m_player[m_board->sideToMove().opposite()]; } void ChessGame::stop() { if (m_finished) return; m_finished = true; emit humanEnabled(false); if (!m_gameInProgress) { m_result = Chess::Result(); finish(); return; } m_gameInProgress = false; m_pgn->setTag("PlyCount", QString::number(m_pgn->moves().size())); m_pgn->setResult(m_result); m_pgn->setResultDescription(m_result.description()); m_player[Chess::Side::White]->endGame(m_result); m_player[Chess::Side::Black]->endGame(m_result); connect(this, SIGNAL(playersReady()), this, SLOT(finish()), Qt::QueuedConnection); syncPlayers(); } void ChessGame::finish() { disconnect(this, SIGNAL(playersReady()), this, SLOT(finish())); for (int i = 0; i < 2; i++) { if (m_player[i] != 0) m_player[i]->disconnect(this); } emit finished(); } void ChessGame::kill() { for (int i = 0; i < 2; i++) { if (m_player[i] != 0) m_player[i]->kill(); } stop(); } void ChessGame::adjudication(const MoveEvaluation& eval) { Chess::Side side(m_board->sideToMove().opposite()); if (eval.depth() <= 0) { m_drawScoreCount = 0; m_resignScoreCount[side] = 0; return; } // Draw adjudication if (m_drawMoveNum > 0) { if (qAbs(eval.score()) <= m_drawScore) m_drawScoreCount++; else m_drawScoreCount = 0; if (m_moves.size() / 2 >= m_drawMoveNum && m_drawScoreCount >= 2) { m_result = Chess::Result(Chess::Result::Adjudication, Chess::Side::NoSide); return; } } // Resign adjudication if (m_resignMoveCount > 0) { int& count = m_resignScoreCount[side]; if (eval.score() <= m_resignScore) count++; else count = 0; if (count >= m_resignMoveCount) m_result = Chess::Result(Chess::Result::Adjudication, side.opposite()); } } static QString evalString(const MoveEvaluation& eval) { if (eval.isBookEval()) return "book"; if (eval.isEmpty()) return QString(); QString str; if (eval.depth() > 0) { int score = eval.score(); int absScore = qAbs(score); if (score > 0) str += "+"; // Detect mate-in-n scores if (absScore > 9900 && (absScore = 1000 - (absScore % 1000)) < 100) { if (score < 0) str += "-"; str += "M" + QString::number(absScore); } else str += QString::number(double(score) / 100.0, 'f', 2); str += "/" + QString::number(eval.depth()) + " "; } int t = eval.time(); if (t == 0) return str + "0s"; int precision = 0; if (t < 100) precision = 3; else if (t < 1000) precision = 2; else if (t < 10000) precision = 1; str += QString::number(double(t / 1000.0), 'f', precision) + 's'; return str; } void ChessGame::addPgnMove(const Chess::Move& move, const QString& comment) { PgnGame::MoveData md; md.key = m_board->key(); md.move = m_board->genericMove(move); md.moveString = m_board->moveString(move, Chess::Board::StandardAlgebraic); md.comment = comment; m_pgn->addMove(md); } void ChessGame::emitLastMove() { PgnGame::MoveData md(m_pgn->moves().last()); emit moveMade(md.move, md.moveString, md.comment); } void ChessGame::onMoveMade(const Chess::Move& move) { ChessPlayer* sender = qobject_cast(QObject::sender()); Q_ASSERT(sender != 0); Q_ASSERT(m_gameInProgress); Q_ASSERT(m_board->isLegalMove(move)); if (sender != playerToMove()) { qDebug() << sender->name() << "tried to make a move on the opponent's turn"; return; } m_moves.append(move); addPgnMove(move, evalString(sender->evaluation())); // Get the result before sending the move to the opponent m_board->makeMove(move); m_result = m_board->result(); if (m_result.isNone()) adjudication(sender->evaluation()); m_board->undoMove(); ChessPlayer* player = playerToWait(); player->makeMove(move); m_board->makeMove(move); if (m_result.isNone()) startTurn(); else stop(); emitLastMove(); } void ChessGame::startTurn() { if (m_paused) return; Chess::Side side(m_board->sideToMove()); Q_ASSERT(!side.isNull()); Chess::Move move(bookMove(side)); if (move.isNull()) m_player[side]->go(); else m_player[side]->makeBookMove(move); emit humanEnabled(m_player[side]->isHuman()); } void ChessGame::onForfeit(const Chess::Result& result) { if (m_finished) return; if (!m_gameInProgress && result.winner().isNull()) { ChessPlayer* sender = qobject_cast(QObject::sender()); Q_ASSERT(sender != 0); qWarning("%s: %s", qPrintable(sender->name()), qPrintable(result.description())); } m_result = result; stop(); } Chess::Move ChessGame::bookMove(Chess::Side side) { Q_ASSERT(!side.isNull()); if (m_book[side] == 0 || m_moves.size() >= m_bookDepth[side] * 2) return Chess::Move(); Chess::GenericMove bookMove = m_book[side]->move(m_board->key()); Chess::Move move = m_board->moveFromGenericMove(bookMove); if (move.isNull()) return Chess::Move(); if (!m_board->isLegalMove(move)) { qWarning("Illegal opening book move for %s: %s", qPrintable(side.toString()), qPrintable(m_board->moveString(move, Chess::Board::LongAlgebraic))); return Chess::Move(); } if (m_board->isRepetition(move)) return Chess::Move(); return move; } void ChessGame::setPlayer(Chess::Side side, ChessPlayer* player) { Q_ASSERT(!side.isNull()); Q_ASSERT(player != 0); m_player[side] = player; } void ChessGame::setStartingFen(const QString& fen) { Q_ASSERT(!m_gameInProgress); m_startingFen = fen; } void ChessGame::setTimeControl(const TimeControl& timeControl, Chess::Side side) { if (side != Chess::Side::White) m_timeControl[Chess::Side::Black] = timeControl; if (side != Chess::Side::Black) m_timeControl[Chess::Side::White] = timeControl; } void ChessGame::setMoves(const QVector& moves) { Q_ASSERT(!m_gameInProgress); m_moves = moves; } void ChessGame::setMoves(const PgnGame& pgn) { Q_ASSERT(pgn.variant() == m_board->variant()); setStartingFen(pgn.startingFenString()); resetBoard(); m_moves.clear(); foreach (const PgnGame::MoveData& md, pgn.moves()) { Chess::Move move(m_board->moveFromGenericMove(md.move)); Q_ASSERT(m_board->isLegalMove(move)); m_board->makeMove(move); if (!m_board->result().isNone()) return; m_moves.append(move); } } void ChessGame::setOpeningBook(const OpeningBook* book, Chess::Side side, int depth) { Q_ASSERT(!m_gameInProgress); if (side.isNull()) { setOpeningBook(book, Chess::Side::White, depth); setOpeningBook(book, Chess::Side::Black, depth); } else { m_book[side] = book; m_bookDepth[side] = depth; } } void ChessGame::generateOpening() { if (m_book[Chess::Side::White] == 0 || m_book[Chess::Side::Black] == 0) return; resetBoard(); // First play moves that are already in the opening foreach (const Chess::Move& move, m_moves) { Q_ASSERT(m_board->isLegalMove(move)); m_board->makeMove(move); if (!m_board->result().isNone()) return; } // Then play the opening book moves forever { Chess::Move move = bookMove(m_board->sideToMove()); if (move.isNull()) break; m_board->makeMove(move); if (!m_board->result().isNone()) break; m_moves.append(move); } } void ChessGame::setStartDelay(int time) { Q_ASSERT(time >= 0); m_startDelay = time; } void ChessGame::pauseThread() { m_pauseSem.release(); m_resumeSem.acquire(); } void ChessGame::lockThread() { if (QThread::currentThread() == thread()) return; QMetaObject::invokeMethod(this, "pauseThread", Qt::QueuedConnection); m_pauseSem.acquire(); } void ChessGame::unlockThread() { if (QThread::currentThread() == thread()) return; m_resumeSem.release(); } void ChessGame::setDrawThreshold(int moveNumber, int score) { m_drawMoveNum = moveNumber; m_drawScore = score; } void ChessGame::setResignThreshold(int moveCount, int score) { m_resignMoveCount = moveCount; m_resignScore = score; } void ChessGame::resetBoard() { QString fen(m_startingFen); if (fen.isEmpty()) { fen = m_board->defaultFenString(); if (m_board->isRandomVariant()) m_startingFen = fen; } if (!m_board->setFenString(fen)) qFatal("Invalid FEN string: %s", qPrintable(fen)); } void ChessGame::onPlayerReady() { ChessPlayer* sender = qobject_cast(QObject::sender()); Q_ASSERT(sender != 0); disconnect(sender, SIGNAL(ready()), this, SLOT(onPlayerReady())); disconnect(sender, SIGNAL(disconnected()), this, SLOT(onPlayerReady())); for (int i = 0; i < 2; i++) { if (!m_player[i]->isReady() && m_player[i]->state() != ChessPlayer::Disconnected) return; } emit playersReady(); } void ChessGame::syncPlayers() { bool ready = true; for (int i = 0; i < 2; i++) { ChessPlayer* player = m_player[i]; Q_ASSERT(player != 0); if (!player->isReady() && player->state() != ChessPlayer::Disconnected) { ready = false; connect(player, SIGNAL(ready()), this, SLOT(onPlayerReady())); connect(player, SIGNAL(disconnected()), this, SLOT(onPlayerReady())); } } if (ready) emit playersReady(); } void ChessGame::start() { if (m_startDelay > 0) { QTimer::singleShot(m_startDelay, this, SLOT(start())); m_startDelay = 0; return; } for (int i = 0; i < 2; i++) { connect(m_player[i], SIGNAL(forfeit(Chess::Result)), this, SLOT(onForfeit(Chess::Result))); } // Start the game in the correct thread connect(this, SIGNAL(playersReady()), this, SLOT(startGame())); QMetaObject::invokeMethod(this, "syncPlayers", Qt::QueuedConnection); } void ChessGame::pause() { m_paused = true; } void ChessGame::resume() { if (!m_paused) return; m_paused = false; QMetaObject::invokeMethod(this, "startTurn", Qt::QueuedConnection); } void ChessGame::initializePgn() { m_pgn->setVariant(m_board->variant()); m_pgn->setStartingFenString(m_board->startingSide(), m_startingFen); m_pgn->setDate(QDate::currentDate()); m_pgn->setPlayerName(Chess::Side::White, m_player[Chess::Side::White]->name()); m_pgn->setPlayerName(Chess::Side::Black, m_player[Chess::Side::Black]->name()); m_pgn->setResult(m_result); if (m_timeControl[Chess::Side::White] == m_timeControl[Chess::Side::Black]) m_pgn->setTag("TimeControl", m_timeControl[0].toString()); else { m_pgn->setTag("WhiteTimeControl", m_timeControl[Chess::Side::White].toString()); m_pgn->setTag("BlackTimeControl", m_timeControl[Chess::Side::Black].toString()); } } void ChessGame::startGame() { m_result = Chess::Result(); emit humanEnabled(false); disconnect(this, SIGNAL(playersReady()), this, SLOT(startGame())); if (m_finished) return; m_gameInProgress = true; for (int i = 0; i < 2; i++) { ChessPlayer* player = m_player[i]; Q_ASSERT(player != 0); Q_ASSERT(player->isReady()); if (player->state() == ChessPlayer::Disconnected) return; if (!player->supportsVariant(m_board->variant())) { qDebug() << player->name() << "doesn't support variant" << m_board->variant(); m_result = Chess::Result(Chess::Result::ResultError); stop(); return; } } resetBoard(); initializePgn(); emit started(); emit fenChanged(m_board->startingFenString()); for (int i = 0; i < 2; i++) { Chess::Side side = Chess::Side::Type(i); Q_ASSERT(m_timeControl[side].isValid()); m_player[side]->setTimeControl(m_timeControl[side]); m_player[side]->newGame(side, m_player[side.opposite()], m_board); } // Play the forced opening moves first for (int i = 0; i < m_moves.size(); i++) { Chess::Move move(m_moves.at(i)); Q_ASSERT(m_board->isLegalMove(move)); addPgnMove(move, "book"); playerToMove()->makeBookMove(move); playerToWait()->makeMove(move); m_board->makeMove(move); emitLastMove(); if (!m_board->result().isNone()) { qDebug() << "Every move was played from the book"; m_result = m_board->result(); stop(); return; } } for (int i = 0; i < 2; i++) { connect(m_player[i], SIGNAL(moveMade(Chess::Move)), this, SLOT(onMoveMade(Chess::Move))); if (m_player[i]->isHuman()) connect(m_player[i], SIGNAL(wokeUp()), this, SLOT(resume())); } startTurn(); } cutechess-20111114+0.4.2+0.0.1/projects/lib/src/chessplayer.cpp0000664000175000017500000001063211657223322022626 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "chessplayer.h" #include #include "board/board.h" ChessPlayer::ChessPlayer(QObject* parent) : QObject(parent), m_state(NotStarted), m_timer(new QTimer(this)), m_forfeited(false), m_board(0), m_opponent(0) { m_timer->setSingleShot(true); connect(m_timer, SIGNAL(timeout()), this, SLOT(onTimeout())); } ChessPlayer::~ChessPlayer() { } bool ChessPlayer::isReady() const { switch (m_state) { case Idle: case Observing: case Thinking: case Disconnected: return true; default: return false; } } void ChessPlayer::newGame(Chess::Side side, ChessPlayer* opponent, Chess::Board* board) { Q_ASSERT(opponent != 0); Q_ASSERT(board != 0); Q_ASSERT(isReady()); Q_ASSERT(m_state != Disconnected); m_forfeited = false; m_eval.clear(); m_opponent = opponent; m_board = board; m_side = side; m_timeControl.initialize(); setState(Observing); startGame(); } void ChessPlayer::endGame(const Chess::Result& result) { Q_UNUSED(result); if (m_state != Observing && m_state != Thinking) return; Q_ASSERT(m_state != Disconnected); setState(FinishingGame); m_board = 0; m_timer->stop(); disconnect(this, SIGNAL(ready()), this, SLOT(go())); } void ChessPlayer::go() { if (m_state == Disconnected) return; setState(Thinking); disconnect(this, SIGNAL(ready()), this, SLOT(go())); if (!isReady()) { connect(this, SIGNAL(ready()), this, SLOT(go())); return; } Q_ASSERT(m_board != 0); m_side = m_board->sideToMove(); startClock(); startThinking(); } void ChessPlayer::quit() { setState(Disconnected); emit disconnected(); } const MoveEvaluation& ChessPlayer::evaluation() const { return m_eval; } void ChessPlayer::startClock() { if (m_state != Thinking) return; m_eval.clear(); if (m_timeControl.isValid()) emit startedThinking(m_timeControl.timeLeft()); m_timeControl.startTimer(); if (!m_timeControl.isInfinite()) { int t = m_timeControl.timeLeft() + m_timeControl.expiryMargin(); m_timer->start(qMax(t, 0) + 200); } } void ChessPlayer::makeBookMove(const Chess::Move& move) { m_timeControl.startTimer(); makeMove(move); m_timeControl.update(); m_eval.setBookEval(true); emit moveMade(move); } const TimeControl* ChessPlayer::timeControl() const { return &m_timeControl; } void ChessPlayer::setTimeControl(const TimeControl& timeControl) { m_timeControl = timeControl; } Chess::Side ChessPlayer::side() const { return m_side; } Chess::Board* ChessPlayer::board() { return m_board; } const ChessPlayer* ChessPlayer::opponent() const { return m_opponent; } ChessPlayer::State ChessPlayer::state() const { return m_state; } void ChessPlayer::setState(State state) { if (state == m_state) return; if (m_state == Thinking) emit stoppedThinking(); m_state = state; } QString ChessPlayer::name() const { return m_name; } void ChessPlayer::setName(const QString& name) { m_name = name; emit nameChanged(m_name); } void ChessPlayer::emitForfeit(Chess::Result::Type type, const QString& description) { if (m_forfeited) return; m_timer->stop(); if (m_state == Thinking) setState(Observing); m_forfeited = true; Chess::Side winner; if (!m_side.isNull()) winner = m_side.opposite(); emit forfeit(Chess::Result(type, winner, description)); } void ChessPlayer::emitMove(const Chess::Move& move) { if (m_state == Thinking) setState(Observing); m_timeControl.update(); m_eval.setTime(m_timeControl.lastMoveTime()); m_timer->stop(); if (m_timeControl.expired()) { emitForfeit(Chess::Result::Timeout); return; } emit moveMade(move); } void ChessPlayer::kill() { setState(Disconnected); emit disconnected(); } void ChessPlayer::onCrashed() { kill(); emitForfeit(Chess::Result::Disconnection); } void ChessPlayer::onTimeout() { emitForfeit(Chess::Result::Timeout); } cutechess-20111114+0.4.2+0.0.1/projects/lib/src/engineoptionfactory.h0000664000175000017500000000043411657223322024036 0ustar oliveroliver#ifndef ENGINE_OPTION_FACTORY_H #define ENGINE_OPTION_FACTORY_H #include class EngineOption; class LIB_EXPORT EngineOptionFactory { public: static EngineOption* create(const QVariantMap& map); private: EngineOptionFactory(); }; #endif // ENGINE_OPTION_FACTORY_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/pgngameentry.h0000664000175000017500000000604711657223322022456 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef PGNGAMEENTRY_H #define PGNGAMEENTRY_H #include #include "board/result.h" class PgnStream; class PgnGameFilter; class QDataStream; /*! * \brief An entry in a PGN collection. * * A PgnGameEntry object contains the tags of a PGN game, and * the position and line number in a PGN stream. * This class was designed for high-performance and low memory * consumption, which is useful for quickly loading large game * collections. * * \sa PgnGame, PgnStream */ class LIB_EXPORT PgnGameEntry { public: /*! A PGN tag's type. */ enum TagType { EventTag, //!< The name of the tournament or match event SiteTag, //!< The location of the event DateTag, //!< The starting date of the game RoundTag, //!< The playing round ordinal of the game WhiteTag, //!< The player of the white pieces BlackTag, //!< The player of the black pieces ResultTag, //!< The result of the game VariantTag //!< The chess variant of the game }; /*! Creates a new empty PgnGameEntry object. */ PgnGameEntry(); /*! Resets the entry to an empty default. */ void clear(); /*! * Reads an entry from a PGN stream. * Returns true if successfull. */ bool read(PgnStream& in); /*! * Reads an entry from data stream. * Returns true if successfull. */ bool read(QDataStream& in); /*! * Writes an entry to data stream. */ void write(QDataStream& out) const; /*! * Returns true if the PGN tags match \a filter. * The matching is case insensitive. */ bool match(const PgnGameFilter& filter) const; /*! Returns the stream position where the game begins. */ qint64 pos() const; /*! Returns the line number where the game begins. */ qint64 lineNumber() const; /*! Returns the tag value corresponding to \a type. */ QString tagValue(TagType type) const; private: void addTag(const QByteArray& tagValue); QByteArray m_data; qint64 m_pos; qint64 m_lineNumber; }; /*! Reads a PGN game entry from a PGN stream. */ extern LIB_EXPORT PgnStream& operator>>(PgnStream& in, PgnGameEntry& entry); /*! Reads a PGN game entry from a data stream. */ extern LIB_EXPORT QDataStream& operator>>(QDataStream& in, PgnGameEntry& entry); /*! Writes a PGN game entry to a data stream. */ extern LIB_EXPORT QDataStream& operator<<(QDataStream& out, const PgnGameEntry& entry); #endif // PGNGAMEENTRY_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/enginecheckoption.cpp0000664000175000017500000000154411657223322024002 0ustar oliveroliver#include "enginecheckoption.h" EngineCheckOption::EngineCheckOption(const QString& name, const QVariant& value, const QVariant& defaultValue, const QString& alias) : EngineOption(name, value, defaultValue, alias) { } EngineOption* EngineCheckOption::copy() const { return new EngineCheckOption(*this); } bool EngineCheckOption::isValid(const QVariant& value) const { if (value.canConvert(QVariant::Bool)) { QString str(value.toString()); return (str == "true" || str == "false"); } return false; } QVariant EngineCheckOption::toVariant() const { QVariantMap map; map.insert("type", "check"); map.insert("name", name()); map.insert("value", value()); map.insert("default", defaultValue()); map.insert("alias", alias()); return map; } cutechess-20111114+0.4.2+0.0.1/projects/lib/src/engineconfiguration.cpp0000664000175000017500000001454711657223322024352 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "engineconfiguration.h" #include "engineoption.h" #include "engineoptionfactory.h" EngineConfiguration::EngineConfiguration() : m_variants(QStringList() << "standard"), m_whiteEvalPov(false), m_restartMode(RestartAuto) { } EngineConfiguration::EngineConfiguration(const QString& name, const QString& command, const QString& protocol) : m_name(name), m_command(command), m_protocol(protocol), m_variants(QStringList() << "standard"), m_whiteEvalPov(false), m_restartMode(RestartAuto) { } EngineConfiguration::EngineConfiguration(const QVariant& variant) : m_variants(QStringList() << "standard"), m_whiteEvalPov(false), m_restartMode(RestartAuto) { const QVariantMap map = variant.toMap(); setName(map["name"].toString()); setCommand(map["command"].toString()); setWorkingDirectory(map["workingDirectory"].toString()); setProtocol(map["protocol"].toString()); if (map.contains("initStrings")) setInitStrings(map["initStrings"].toStringList()); if (map.contains("whitepov")) setWhiteEvalPov(map["whitepov"].toBool()); if (map.contains("restart")) { const QString val(map["restart"].toString()); if (val == "auto") setRestartMode(RestartAuto); else if (val == "on") setRestartMode(RestartOn); else if (val == "off") setRestartMode(RestartOff); } if (map.contains("variants")) setSupportedVariants(map["variants"].toStringList()); if (map.contains("options")) { const QVariantList optionsList = map["options"].toList(); EngineOption* option = 0; foreach (const QVariant& optionVariant, optionsList) { if ((option = EngineOptionFactory::create(optionVariant.toMap())) != 0) addOption(option); } } } EngineConfiguration::EngineConfiguration(const EngineConfiguration& other) : m_name(other.m_name), m_command(other.m_command), m_workingDirectory(other.m_workingDirectory), m_protocol(other.m_protocol), m_arguments(other.m_arguments), m_initStrings(other.m_initStrings), m_variants(other.m_variants), m_whiteEvalPov(other.m_whiteEvalPov), m_restartMode(other.m_restartMode) { foreach (const EngineOption* option, other.options()) addOption(option->copy()); } EngineConfiguration::~EngineConfiguration() { qDeleteAll(m_options); } QVariant EngineConfiguration::toVariant() const { QVariantMap map; map.insert("name", m_name); map.insert("command", m_command); map.insert("workingDirectory", m_workingDirectory); map.insert("protocol", m_protocol); if (!m_initStrings.isEmpty()) map.insert("initStrings", m_initStrings); if (m_whiteEvalPov) map.insert("whitepov", true); if (m_restartMode == RestartOn) map.insert("restart", "on"); else if (m_restartMode == RestartOff) map.insert("restart", "off"); if (m_variants.count("standard") != m_variants.count()) map.insert("variants", m_variants); if (!m_options.isEmpty()) { QVariantList optionsList; foreach (const EngineOption* option, m_options) optionsList.append(option->toVariant()); map.insert("options", optionsList); } return map; } void EngineConfiguration::setName(const QString& name) { m_name = name; } void EngineConfiguration::setCommand(const QString& command) { m_command = command; } void EngineConfiguration::setProtocol(const QString& protocol) { m_protocol = protocol; } void EngineConfiguration::setWorkingDirectory(const QString& workingDir) { m_workingDirectory = workingDir; } QString EngineConfiguration::name() const { return m_name; } QString EngineConfiguration::command() const { return m_command; } QString EngineConfiguration::workingDirectory() const { return m_workingDirectory; } QString EngineConfiguration::protocol() const { return m_protocol; } QStringList EngineConfiguration::arguments() const { return m_arguments; } void EngineConfiguration::setArguments(const QStringList& arguments) { m_arguments = arguments; } void EngineConfiguration::addArgument(const QString& argument) { m_arguments << argument; } QStringList EngineConfiguration::initStrings() const { return m_initStrings; } void EngineConfiguration::setInitStrings(const QStringList& initStrings) { m_initStrings = initStrings; } void EngineConfiguration::addInitString(const QString& initString) { m_initStrings << initString.split('\n'); } QStringList EngineConfiguration::supportedVariants() const { return m_variants; } void EngineConfiguration::setSupportedVariants(const QStringList& variants) { m_variants = variants; } QList EngineConfiguration::options() const { return m_options; } void EngineConfiguration::setOptions(const QList& options) { qDeleteAll(m_options); m_options = options; } void EngineConfiguration::addOption(EngineOption* option) { Q_ASSERT(option != 0); m_options << option; } bool EngineConfiguration::whiteEvalPov() const { return m_whiteEvalPov; } void EngineConfiguration::setWhiteEvalPov(bool whiteEvalPov) { m_whiteEvalPov = whiteEvalPov; } EngineConfiguration::RestartMode EngineConfiguration::restartMode() const { return m_restartMode; } void EngineConfiguration::setRestartMode(RestartMode mode) { m_restartMode = mode; } EngineConfiguration& EngineConfiguration::operator=(const EngineConfiguration& other) { if (this != &other) { setName(other.name()); setCommand(other.command()); setProtocol(other.protocol()); setWorkingDirectory(other.workingDirectory()); setArguments(other.arguments()); setInitStrings(other.initStrings()); setSupportedVariants(other.supportedVariants()); setWhiteEvalPov(other.whiteEvalPov()); setRestartMode(other.restartMode()); qDeleteAll(m_options); m_options.clear(); foreach (const EngineOption* option, other.options()) addOption(option->copy()); } return *this; } cutechess-20111114+0.4.2+0.0.1/projects/lib/src/enginespinoption.h0000664000175000017500000000135111657223322023337 0ustar oliveroliver#ifndef ENGINESPINOPTION_H #define ENGINESPINOPTION_H #include "engineoption.h" class LIB_EXPORT EngineSpinOption : public EngineOption { public: EngineSpinOption(const QString& name, const QVariant& value = QVariant(), const QVariant& defaultValue = QVariant(), int min = 0, int max = 0, const QString& alias = QString()); // Inherited from EngineOption virtual EngineOption* copy() const; virtual bool isValid(const QVariant& value) const; virtual QVariant toVariant() const; int min() const; int max() const; void setMin(int min); void setMax(int max); private: int m_min; int m_max; }; #endif // ENGINESPINOPTION_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/enginetextoption.h0000664000175000017500000000105411657223322023352 0ustar oliveroliver#ifndef ENGINETEXTOPTION_H #define ENGINETEXTOPTION_H #include "engineoption.h" class LIB_EXPORT EngineTextOption : public EngineOption { public: EngineTextOption(const QString& name, const QVariant& value = QVariant(), const QVariant& defaultValue = QVariant(), const QString& alias = QString()); // Inherited from EngineOption virtual EngineOption* copy() const; virtual bool isValid(const QVariant& value) const; virtual QVariant toVariant() const; }; #endif // ENGINETEXTOPTION_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/chessengine.h0000664000175000017500000001607611657223322022254 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef CHESSENGINE_H #define CHESSENGINE_H #include "chessplayer.h" #include #include #include "engineconfiguration.h" class QIODevice; class EngineOption; /*! * \brief An artificial intelligence chess player. * * ChessEngine is a separate process (run locally or over a network) using * either the Xboard or Uci chess protocol. Communication between the GUI * and the chess engines happens via a QIODevice. * * \sa XboardEngine * \sa UciEngine */ class LIB_EXPORT ChessEngine : public ChessPlayer { Q_OBJECT public: /*! * The write mode used by \a write() when the engine is * being pinged. This doesn't affect the IO device's * buffering. */ enum WriteMode { Buffered, //!< Use the write buffer Unbuffered //!< Bypass the write buffer }; /*! Creates and initializes a new ChessEngine. */ ChessEngine(QObject* parent = 0); virtual ~ChessEngine(); /*! Returns the current device associated with the engine. */ QIODevice* device() const; /*! Sets the current device to \a device. */ void setDevice(QIODevice* device); // Inherited from ChessPlayer virtual void endGame(const Chess::Result& result); virtual bool isHuman() const; virtual bool isReady() const; virtual bool supportsVariant(const QString& variant) const; /*! * Starts communicating with the engine. * \note The engine device must already be started. */ void start(); /*! Applies \a configuration to the engine. */ void applyConfiguration(const EngineConfiguration& configuration); /*! * Sends a ping message (an echo request) to the engine to * check if it's still responding to input, and to synchronize * it with the game operator. If the engine doesn't respond in * reasonable time, it will be terminated. * * \note All input to the engine will be delayed until we * get a response to the ping. */ void ping(); /*! Returns the engine's chess protocol. */ virtual QString protocol() const = 0; /*! * Writes text data to the chess engine. * * If \a mode is \a Unbuffered, the data will be written to * the device immediately even if the engine is being pinged. */ void write(const QString& data, WriteMode mode = Buffered); /*! * Sets an option with the name \a name to \a value. * * \note If the engine doesn't have an option called \a name, * nothing happens. */ void setOption(const QString& name, const QVariant& value); /*! Returns a list of supported options and their values. */ QList options() const; /*! Returns a list of supported chess variants. */ QStringList variants() const; public slots: // Inherited from ChessPlayer virtual void go(); virtual void quit(); virtual void kill(); protected: /*! * Reads the first whitespace-delimited token from a string * and returns a QStringRef reference to the token. * * If \a readToEnd is true, the whole string is read, except * for leading and trailing whitespace. Otherwise only one * word is read. * * If \a str doesn't contain any words, a null QStringRef * object is returned. */ static QStringRef firstToken(const QString& str, bool readToEnd = false); /*! * Reads the first whitespace-delimited token after the * token referenced by \a previous. * * If \a readToEnd is true, everything from the first word * after \a previous to the end of the string is read, * except for leading and trailing whitespace. Otherwise * only one word is read. * * If \a previous is null or it's not followed by any words, * a null QStringRef object is returned. */ static QStringRef nextToken(const QStringRef& previous, bool readToEnd = false); // Inherited from ChessPlayer virtual void startGame() = 0; /*! * Puts the engine in the correct mode to start communicating * with it, using the chosen chess protocol. */ virtual void startProtocol() = 0; /*! Parses a line of input from the engine. */ virtual void parseLine(const QString& line) = 0; /*! * Sends a ping command to the engine. * \return True if successfull */ virtual bool sendPing() = 0; /*! Sends the stop command to the engine. */ virtual void sendStop() = 0; /*! Sends the quit command to the engine. */ virtual void sendQuit() = 0; /*! Tells the engine to stop thinking and move now. */ void stopThinking(); /*! Adds \a option to the engine options list. */ void addOption(EngineOption* option); /*! * Returns the option that matches \a name. * Returns 0 if an option with that name doesn't exist. */ EngineOption* getOption(const QString& name) const; /*! Tells the engine to set option \a name's value to \a value. */ virtual void sendOption(const QString& name, const QString& value) = 0; /*! Adds \a variant to the list of supported variants. */ void addVariant(const QString& variant); /*! Clears the list of supported variants. */ void clearVariants(); /*! * Returns the restart mode. * The default value is \a EngineConfiguration::RestartAuto. */ EngineConfiguration::RestartMode restartMode() const; /*! * Returns true if the engine restarts between games; otherwise * returns false. */ virtual bool restartsBetweenGames() const; /*! Are evaluation scores from white's point of view? */ bool whiteEvalPov() const; protected slots: // Inherited from ChessPlayer virtual void onTimeout(); /*! Reads input from the engine. */ void onReadyRead(); /*! Called when the engine doesn't respond to ping. */ void onPingTimeout(); /*! Called when the engine idles for too long. */ void onIdleTimeout(); /*! Called when the engine responds to ping. */ void pong(); /*! * Called when the engine has started the chess protocol and * is ready to start a game. */ void onProtocolStart(); /*! * Flushes the write buffer. * If there are any commands in the buffer, they will be sent * to the engine. */ void flushWriteBuffer(); private slots: void onQuitTimeout(); private: static int s_count; int m_id; State m_pingState; bool m_pinging; bool m_whiteEvalPov; QTimer* m_pingTimer; QTimer* m_quitTimer; QTimer* m_idleTimer; QIODevice *m_ioDevice; QStringList m_writeBuffer; QStringList m_variants; QList m_options; QMap m_optionBuffer; EngineConfiguration::RestartMode m_restartMode; }; #endif // CHESSENGINE_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/pgngamefilter.cpp0000664000175000017500000000247111657223322023132 0ustar oliveroliver#include "pgngamefilter.h" #include PgnGameFilter::PgnGameFilter() : m_type(Advanced), m_minRound(0), m_maxRound(0), m_result(AnyResult), m_resultInverted(false) { } PgnGameFilter::PgnGameFilter(const QString& pattern) : m_type(FixedString), m_pattern(pattern.toLatin1()), m_minRound(0), m_maxRound(0), m_result(AnyResult), m_resultInverted(false) { } void PgnGameFilter::setPattern(const QString& pattern) { m_type = FixedString; m_pattern = pattern.toLatin1(); } void PgnGameFilter::setEvent(const QString& event) { m_event = event.toLatin1(); } void PgnGameFilter::setSite(const QString& site) { m_site = site.toLatin1(); } void PgnGameFilter::setPlayer(const QString& name, Chess::Side side) { m_player = name.toLatin1(); m_playerSide = side; } void PgnGameFilter::setOpponent(const QString& name) { m_opponent = name.toLatin1(); } void PgnGameFilter::setMinDate(const QDate& date) { m_minDate = date; } void PgnGameFilter::setMaxDate(const QDate& date) { m_maxDate = date; } void PgnGameFilter::setMinRound(int round) { m_minRound = round; } void PgnGameFilter::setMaxRound(int round) { m_maxRound = round; } void PgnGameFilter::setResult(Result result) { m_result = result; } void PgnGameFilter::setResultInverted(bool invert) { m_resultInverted = invert; } cutechess-20111114+0.4.2+0.0.1/projects/lib/src/enginecombooption.cpp0000664000175000017500000000204611657223322024022 0ustar oliveroliver#include "enginecombooption.h" EngineComboOption::EngineComboOption(const QString& name, const QVariant& value, const QVariant& defaultValue, const QStringList& choices, const QString& alias) : EngineOption(name, value, defaultValue, alias), m_choices(choices) { } EngineOption* EngineComboOption::copy() const { return new EngineComboOption(*this); } bool EngineComboOption::isValid(const QVariant& value) const { return m_choices.contains(value.toString()); } QStringList EngineComboOption::choices() const { return m_choices; } void EngineComboOption::setChoices(const QStringList& choices) { m_choices = choices; } QVariant EngineComboOption::toVariant() const { QVariantMap map; map.insert("type", "combo"); map.insert("name", name()); map.insert("value", value()); map.insert("default", defaultValue()); map.insert("alias", alias()); map.insert("choices", choices()); return map; } cutechess-20111114+0.4.2+0.0.1/projects/lib/src/xboardengine.h0000664000175000017500000000456211657223322022423 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef XBOARDENGINE_H #define XBOARDENGINE_H #include "chessengine.h" #include "board/board.h" /*! * \brief A chess engine which uses the Xboard chess engine communication protocol. * * Xboard's specifications: http://www.open-aurec.com/wbforum/WinBoard/engine-intf.html */ class LIB_EXPORT XboardEngine : public ChessEngine { Q_OBJECT public: /*! Creates a new XboardEngine. */ XboardEngine(QObject* parent = 0); // Inherited from ChessEngine virtual void endGame(const Chess::Result& result); virtual void makeMove(const Chess::Move& move); virtual QString protocol() const; protected: // Inherited from ChessEngine virtual bool sendPing(); virtual void sendStop(); virtual void sendQuit(); virtual void startProtocol(); virtual void startGame(); virtual void startThinking(); virtual void parseLine(const QString& line); virtual void sendOption(const QString& name, const QString& value); virtual bool restartsBetweenGames() const; protected slots: // Inherited from ChessEngine virtual void onTimeout(); private slots: /*! Initializes the engine, and emits the 'ready' signal. */ void initialize(); private: void setFeature(const QString& name, const QString& val); void setForceMode(bool enable); void sendTimeLeft(); void finishGame(); QString moveString(const Chess::Move& move); bool m_forceMode; bool m_drawOnNextMove; // Engine features bool m_ftName; bool m_ftPing; bool m_ftSetboard; bool m_ftTime; bool m_ftUsermove; bool m_ftReuse; bool m_gotResult; int m_lastPing; Chess::Move m_nextMove; QString m_nextMoveString; Chess::Board::MoveNotation m_notation; QTimer* m_initTimer; }; #endif // XBOARDENGINE_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/enginebuilder.h0000664000175000017500000000232411657223322022564 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef ENGINEBUILDER_H #define ENGINEBUILDER_H #include "playerbuilder.h" #include "engineconfiguration.h" /*! \brief A class for constructing local chess engines. */ class LIB_EXPORT EngineBuilder : public PlayerBuilder { public: /*! Creates a new EngineBuilder. */ EngineBuilder(const EngineConfiguration& config); // Inherited from PlayerBuilder virtual ChessPlayer* create(QObject* receiver, const char* method, QObject* parent) const; private: EngineConfiguration m_config; }; #endif // ENGINEBUILDER_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/gamemanager.cpp0000664000175000017500000002121411657223322022546 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "gamemanager.h" #include #include #include "playerbuilder.h" #include "chessgame.h" #include "chessplayer.h" class GameThread : public QThread { Q_OBJECT public: GameThread(const PlayerBuilder* whiteBuilder, const PlayerBuilder* blackBuilder, QObject* parent); virtual ~GameThread(); bool isReady() const; bool newGame(ChessGame* game); void swapSides(); void quitPlayers(); ChessGame* game() const; const PlayerBuilder* whiteBuilder() const; const PlayerBuilder* blackBuilder() const; GameManager::StartMode startMode() const; GameManager::CleanupMode cleanupMode() const; void setStartMode(GameManager::StartMode mode); void setCleanupMode(GameManager::CleanupMode mode); signals: void ready(); private slots: void onGameDestroyed(); void onPlayerQuit(); private: bool m_ready; bool m_quitting; GameManager::StartMode m_startMode; GameManager::CleanupMode m_cleanupMode; int m_playerCount; ChessGame* m_game; ChessPlayer* m_player[2]; const PlayerBuilder* m_builder[2]; }; GameThread::GameThread(const PlayerBuilder* whiteBuilder, const PlayerBuilder* blackBuilder, QObject* parent) : QThread(parent), m_ready(true), m_quitting(false), m_startMode(GameManager::StartImmediately), m_cleanupMode(GameManager::DeletePlayers), m_playerCount(0), m_game(0) { Q_ASSERT(parent != 0); Q_ASSERT(whiteBuilder != 0); Q_ASSERT(blackBuilder != 0); m_player[Chess::Side::White] = 0; m_player[Chess::Side::Black] = 0; m_builder[Chess::Side::White] = whiteBuilder; m_builder[Chess::Side::Black] = blackBuilder; } GameThread::~GameThread() { for (int i = 0; i < 2; i++) { if (m_player[i] == 0) continue; m_player[i]->disconnect(); m_player[i]->kill(); delete m_player[i]; } } bool GameThread::isReady() const { return m_ready; } bool GameThread::newGame(ChessGame* game) { m_ready = false; m_game = game; m_game->moveToThread(this); connect(game, SIGNAL(destroyed()), this, SLOT(onGameDestroyed())); for (int i = 0; i < 2; i++) { // Delete a disconnected player (crashed engine) so that // it will be restarted. if (m_player[i] != 0 && m_player[i]->state() == ChessPlayer::Disconnected) { m_player[i]->deleteLater(); m_player[i] = 0; } if (m_player[i] == 0) { m_player[i] = m_builder[i]->create(parent(), SIGNAL(debugMessage(QString))); if (m_player[i] == 0) { m_ready = true; m_playerCount = 0; int j = !i; if (m_player[j] != 0) { m_player[j]->kill(); delete m_player[j]; m_player[j] = 0; } return false; } m_player[i]->moveToThread(this); } m_game->setPlayer(Chess::Side::Type(i), m_player[i]); } m_playerCount = 2; return true; } void GameThread::swapSides() { qSwap(m_player[0], m_player[1]); qSwap(m_builder[0], m_builder[1]); } void GameThread::quitPlayers() { if (m_quitting) return; m_quitting = true; if (m_playerCount <= 0) { quit(); return; } for (int i = 0; i < 2; i++) { if (m_player[i] == 0) continue; connect(m_player[i], SIGNAL(disconnected()), this, SLOT(onPlayerQuit()), Qt::QueuedConnection); QMetaObject::invokeMethod(m_player[i], "quit", Qt::QueuedConnection); } } ChessGame* GameThread::game() const { return m_game; } const PlayerBuilder* GameThread::whiteBuilder() const { return m_builder[Chess::Side::White]; } const PlayerBuilder* GameThread::blackBuilder() const { return m_builder[Chess::Side::Black]; } GameManager::StartMode GameThread::startMode() const { return m_startMode; } GameManager::CleanupMode GameThread::cleanupMode() const { return m_cleanupMode; } void GameThread::setStartMode(GameManager::StartMode mode) { m_startMode = mode; } void GameThread::setCleanupMode(GameManager::CleanupMode mode) { m_cleanupMode = mode; } void GameThread::onGameDestroyed() { m_ready = true; emit ready(); } void GameThread::onPlayerQuit() { if (--m_playerCount <= 0) quit(); } GameManager::GameManager(QObject* parent) : QObject(parent), m_finishing(false), m_concurrency(1), m_activeQueuedGameCount(0) { } QList GameManager::activeGames() const { return m_activeGames; } int GameManager::concurrency() const { return m_concurrency; } void GameManager::setConcurrency(int concurrency) { m_concurrency = concurrency; } void GameManager::cleanup() { m_finishing = false; // Remove idle threads from the list QList< QPointer >::iterator it = m_threads.begin(); while (it != m_threads.end()) { if (*it == 0 || !(*it)->isRunning()) it = m_threads.erase(it); else ++it; } if (m_threads.isEmpty()) { emit finished(); return; } // Terminate running threads foreach (GameThread* thread, m_threads) { connect(thread, SIGNAL(finished()), this, SLOT(onThreadQuit()), Qt::QueuedConnection); thread->quitPlayers(); } } void GameManager::finish() { m_gameEntries.clear(); if (m_activeGames.isEmpty()) cleanup(); else m_finishing = true; } bool GameManager::newGame(ChessGame* game, const PlayerBuilder* white, const PlayerBuilder* black, StartMode startMode, CleanupMode cleanupMode) { Q_ASSERT(game != 0); Q_ASSERT(white != 0); Q_ASSERT(black != 0); Q_ASSERT(game->parent() == 0); GameEntry entry = { game, white, black, startMode, cleanupMode }; if (startMode == StartImmediately) return startGame(entry); m_gameEntries << entry; return startQueuedGame(); } void GameManager::onThreadQuit() { GameThread* thread = qobject_cast(QObject::sender()); Q_ASSERT(thread != 0); m_threads.removeOne(thread); thread->deleteLater(); if (m_threads.isEmpty()) { m_finishing = false; emit finished(); } } void GameManager::onThreadReady() { GameThread* thread = qobject_cast(QObject::sender()); Q_ASSERT(thread != 0); ChessGame* game = thread->game(); m_activeGames.removeOne(game); m_threads.removeAll(0); if (thread->cleanupMode() == DeletePlayers) { m_activeThreads.removeOne(thread); delete thread->whiteBuilder(); delete thread->blackBuilder(); connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); thread->quitPlayers(); } if (thread->startMode() == Enqueue) { m_activeQueuedGameCount--; startQueuedGame(); } emit gameDestroyed(game); if (m_finishing && m_activeGames.isEmpty()) cleanup(); } GameThread* GameManager::getThread(const PlayerBuilder* white, const PlayerBuilder* black) { Q_ASSERT(white != 0); Q_ASSERT(black != 0); foreach (GameThread* thread, m_activeThreads) { if (!thread->isReady()) continue; if (thread->whiteBuilder() == black && thread->blackBuilder() == white) thread->swapSides(); if (thread->whiteBuilder() == white && thread->blackBuilder() == black) return thread; } GameThread* gameThread = new GameThread(white, black, this); m_threads << gameThread; m_activeThreads << gameThread; connect(gameThread, SIGNAL(ready()), this, SLOT(onThreadReady())); return gameThread; } void GameManager::onGameStarted() { ChessGame* game = qobject_cast(QObject::sender()); Q_ASSERT(game != 0); emit gameStarted(game); } bool GameManager::startGame(const GameEntry& entry) { GameThread* gameThread = getThread(entry.white, entry.black); Q_ASSERT(gameThread != 0); gameThread->setStartMode(entry.startMode); gameThread->setCleanupMode(entry.cleanupMode); if (!gameThread->newGame(entry.game)) { m_threads.removeOne(gameThread); m_activeThreads.removeOne(gameThread); gameThread->deleteLater(); return false; } m_activeGames << entry.game; if (entry.startMode == Enqueue) m_activeQueuedGameCount++; connect(entry.game, SIGNAL(started()), this, SLOT(onGameStarted()), Qt::QueuedConnection); gameThread->start(); entry.game->start(); return true; } bool GameManager::startQueuedGame() { if (m_activeQueuedGameCount >= m_concurrency) return true; if (m_gameEntries.isEmpty()) { emit ready(); return true; } if (!startGame(m_gameEntries.takeFirst())) return false; return startQueuedGame(); } #include "gamemanager.moc" cutechess-20111114+0.4.2+0.0.1/projects/lib/src/enginemanager.h0000664000175000017500000000462511657223322022556 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef ENGINE_MANAGER_H #define ENGINE_MANAGER_H #include "engineconfiguration.h" /*! * \brief Manages chess engines and their configurations. * * \sa EngineConfiguration */ class LIB_EXPORT EngineManager : public QObject { Q_OBJECT public: /*! Creates a new EngineManager. */ EngineManager(QObject* parent = 0); virtual ~EngineManager(); /*! Returns the number of available engines. */ int engineCount() const; /*! Returns the engine at \a index. */ EngineConfiguration engineAt(int index) const; /*! Adds \a engine to the list of available engines. */ void addEngine(const EngineConfiguration& engine); /*! Updates the engine at \a index with \a engine. */ void updateEngineAt(int index, const EngineConfiguration& engine); /*! Removes the engine at \a index. */ void removeEngineAt(int index); /*! Returns the available engines. */ QList engines() const; /*! Sets the available engines to \a engines. */ void setEngines(const QList& engines); void loadEngines(const QString& fileName); void saveEngines(const QString& fileName); signals: /*! * Emitted when all previously queried engine information is now * invalid and has to be queried again. */ void enginesReset(); /*! Emitted when an engine is added to \a index. */ void engineAdded(int index); /*! * Emitted when an engine at \a index is about to be removed. * \note This signal is emitted before the engine is removed so * the index position is still valid. */ void engineAboutToBeRemoved(int index); /*! Emitted when an engine is updated at \a index. */ void engineUpdated(int index); private: QList m_engines; }; #endif // ENGINE_MANAGER_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/timecontrol.cpp0000664000175000017500000001554411657223322022652 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "timecontrol.h" #include #include TimeControl::TimeControl() : m_movesPerTc(0), m_timePerTc(0), m_timePerMove(0), m_increment(0), m_timeLeft(0), m_movesLeft(0), m_plyLimit(0), m_nodeLimit(0), m_lastMoveTime(0), m_expiryMargin(0), m_expired(false), m_infinite(false) { } TimeControl::TimeControl(const QString& str) : m_movesPerTc(0), m_timePerTc(0), m_timePerMove(0), m_increment(0), m_timeLeft(0), m_movesLeft(0), m_plyLimit(0), m_nodeLimit(0), m_lastMoveTime(0), m_expiryMargin(0), m_expired(false), m_infinite(false) { if (str == "inf") { setInfinity(true); return; } QStringList list = str.split('+'); // increment if (list.size() == 2) { int inc = (int)(list.at(1).toDouble() * 1000); if (inc >= 0) setTimeIncrement(inc); } list = list.at(0).split('/'); QString strTime; // moves per tc if (list.size() == 2) { int nmoves = list.at(0).toInt(); if (nmoves >= 0) setMovesPerTc(nmoves); strTime = list.at(1); } else strTime = list.at(0); // time per tc int ms = 0; list = strTime.split(':'); if (list.size() == 2) ms = (int)(list.at(0).toDouble() * 60000 + list.at(1).toDouble() * 1000); else ms = (int)(list.at(0).toDouble() * 1000); if (ms > 0) setTimePerTc(ms); } bool TimeControl::operator==(const TimeControl& other) const { if (m_movesPerTc == other.m_movesPerTc && m_timePerTc == other.m_timePerTc && m_timePerMove == other.m_timePerMove && m_increment == other.m_increment && m_plyLimit == other.m_plyLimit && m_nodeLimit == other.m_nodeLimit && m_infinite == other.m_infinite) return true; return false; } bool TimeControl::isValid() const { if (m_movesPerTc < 0 || m_timePerTc < 0 || m_timePerMove < 0 || m_increment < 0 || m_plyLimit < 0 || m_nodeLimit < 0 || m_expiryMargin < 0 || (m_timePerTc == m_timePerMove && !m_infinite)) return false; return true; } QString TimeControl::toString() const { if (!isValid()) return QString(); if (m_infinite) return QString("inf"); if (m_timePerMove != 0) return QString("%1/move").arg((double)m_timePerMove / 1000); QString str; if (m_movesPerTc > 0) str += QString::number(m_movesPerTc) + "/"; str += QString::number((double)m_timePerTc / 1000); if (m_increment > 0) str += QString("+") + QString::number((double)m_increment / 1000); return str; } static QString s_timeString(int ms) { if (ms == 0 || ms % 60000 != 0) return QObject::tr("%1 sec").arg(double(ms) / 1000.0); if (ms % 3600000 != 0) return QObject::tr("%1 min").arg(ms / 60000); return QObject::tr("%1 h").arg(ms / 3600000); } static QString s_nodeString(int nodes) { if (nodes == 0 || nodes % 1000 != 0) return QString::number(nodes); else if (nodes % 1000000 != 0) return QObject::tr("%1 k").arg(nodes / 1000); return QObject::tr("%1 M").arg(nodes / 1000000); } QString TimeControl::toVerboseString() const { if (!isValid()) return QString(); QString str; if (m_infinite) str = QObject::tr("infinite time"); else if (m_timePerMove != 0) str = QObject::tr("%1 per move") .arg(s_timeString(m_timePerMove)); else if (m_movesPerTc != 0) str = QObject::tr("%1 moves in %2") .arg(m_movesPerTc) .arg(s_timeString(m_timePerTc)); else str = s_timeString(m_timePerTc); if (m_timePerTc != 0 && m_increment != 0) str += QObject::tr(", %1 increment") .arg(s_timeString(m_increment)); if (m_nodeLimit != 0) str += QObject::tr(", %1 nodes") .arg(s_nodeString(m_nodeLimit)); if (m_plyLimit != 0) str += QObject::tr(", %1 plies").arg(m_plyLimit); if (m_expiryMargin != 0) str += QObject::tr(", %1 msec margin").arg(m_expiryMargin); return str; } void TimeControl::initialize() { m_expired = false; m_lastMoveTime = 0; if (m_timePerTc != 0) { m_timeLeft = m_timePerTc; m_movesLeft = m_movesPerTc; } else if (m_timePerMove != 0) m_timeLeft = m_timePerMove; } bool TimeControl::isInfinite() const { return m_infinite; } int TimeControl::timePerTc() const { return m_timePerTc; } int TimeControl::movesPerTc() const { return m_movesPerTc; } int TimeControl::timeIncrement() const { return m_increment; } int TimeControl::timePerMove() const { return m_timePerMove; } int TimeControl::timeLeft() const { return m_timeLeft; } int TimeControl::movesLeft() const { return m_movesLeft; } int TimeControl::plyLimit() const { return m_plyLimit; } int TimeControl::nodeLimit() const { return m_nodeLimit; } int TimeControl::expiryMargin() const { return m_expiryMargin; } void TimeControl::setInfinity(bool enabled) { m_infinite = enabled; } void TimeControl::setTimePerTc(int timePerTc) { Q_ASSERT(timePerTc >= 0); m_timePerTc = timePerTc; } void TimeControl::setMovesPerTc(int movesPerTc) { Q_ASSERT(movesPerTc >= 0); m_movesPerTc = movesPerTc; } void TimeControl::setTimeIncrement(int increment) { Q_ASSERT(increment >= 0); m_increment = increment; } void TimeControl::setTimePerMove(int timePerMove) { Q_ASSERT(timePerMove >= 0); m_timePerMove = timePerMove; } void TimeControl::setTimeLeft(int timeLeft) { m_timeLeft = timeLeft; } void TimeControl::setMovesLeft(int movesLeft) { Q_ASSERT(movesLeft >= 0); m_movesLeft = movesLeft; } void TimeControl::setPlyLimit(int plies) { Q_ASSERT(plies >= 0); m_plyLimit = plies; } void TimeControl::setNodeLimit(int nodes) { Q_ASSERT(nodes >= 0); m_nodeLimit = nodes; } void TimeControl::setExpiryMargin(int expiryMargin) { Q_ASSERT(expiryMargin >= 0); m_expiryMargin = expiryMargin; } void TimeControl::startTimer() { m_time.start(); } void TimeControl::update() { m_lastMoveTime = m_time.elapsed(); if (!m_infinite && m_lastMoveTime > m_timeLeft + m_expiryMargin) m_expired = true; if (m_timePerMove != 0) setTimeLeft(m_timePerMove); else { setTimeLeft(m_timeLeft + m_increment - m_lastMoveTime); if (m_movesPerTc > 0) { setMovesLeft(m_movesLeft - 1); // Restart the time control if (m_movesLeft == 0) { setMovesLeft(m_movesPerTc); setTimeLeft(m_timePerTc + m_timeLeft); } } } } int TimeControl::lastMoveTime() const { return m_lastMoveTime; } bool TimeControl::expired() const { return m_expired; } int TimeControl::activeTimeLeft() const { return m_timeLeft - m_time.elapsed(); } cutechess-20111114+0.4.2+0.0.1/projects/lib/src/polyglotbook.cpp0000664000175000017500000000424711657223322023035 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "polyglotbook.h" #include static Chess::GenericMove moveFromBits(quint16 pgMove) { using Chess::Square; Square target((quint16)(pgMove << 13) >> 13, (quint16)(pgMove << 10) >> 13); Square source((quint16)(pgMove << 7) >> 13, (quint16)(pgMove << 4) >> 13); int promotion = (quint16)(pgMove << 1) >> 13; if (promotion > 0) promotion++; return Chess::GenericMove(source, target, promotion); } static quint16 moveToBits(const Chess::GenericMove& move) { using Chess::Square; const Square& src = move.sourceSquare(); const Square& trg = move.targetSquare(); quint16 target = trg.file() | (trg.rank() << 3); quint16 source = (src.file() << 6) | (src.rank() << 9); quint16 promotion = 0; if (move.promotion() > 0) promotion = (move.promotion() - 1) << 12; return target | source | promotion; } void PolyglotBook::readEntry(QDataStream& in) { quint64 key; quint16 pgMove; quint16 weight; quint32 learn; // Read the data. No need to worry about endianess, // because QDataStream uses big-endian by default. in >> key >> pgMove >> weight >> learn; Entry entry = { moveFromBits(pgMove), weight }; addEntry(entry, key); } void PolyglotBook::writeEntry(const Map::const_iterator& it, QDataStream& out) const { quint32 learn = 0; quint64 key = it.key(); quint16 pgMove = moveToBits(it.value().move); quint16 weight = it.value().weight; // Store the data. Again, big-endian is used by default. out << key << pgMove << weight << learn; } cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/0000775000175000017500000000000011657223322020665 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/westernboard.cpp0000664000175000017500000006677611657223322024116 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "westernboard.h" #include #include "westernzobrist.h" #include "boardtransition.h" namespace Chess { WesternBoard::WesternBoard(WesternZobrist* zobrist) : Board(zobrist), m_arwidth(0), m_sign(1), m_enpassantSquare(0), m_reversibleMoveCount(0), m_kingCanCapture(true), m_zobrist(zobrist) { setPieceType(Pawn, QObject::tr("pawn"), "P"); setPieceType(Knight, QObject::tr("knight"), "N", KnightMovement); setPieceType(Bishop, QObject::tr("bishop"), "B", BishopMovement); setPieceType(Rook, QObject::tr("rook"), "R", RookMovement); setPieceType(Queen, QObject::tr("queen"), "Q", BishopMovement | RookMovement); setPieceType(King, QObject::tr("king"), "K"); } int WesternBoard::width() const { return 8; } int WesternBoard::height() const { return 8; } bool WesternBoard::kingCanCapture() const { return true; } void WesternBoard::vInitialize() { m_kingCanCapture = kingCanCapture(); m_arwidth = width() + 2; m_castlingRights.rookSquare[Side::White][QueenSide] = 0; m_castlingRights.rookSquare[Side::White][KingSide] = 0; m_castlingRights.rookSquare[Side::Black][QueenSide] = 0; m_castlingRights.rookSquare[Side::Black][KingSide] = 0; m_kingSquare[Side::White] = 0; m_kingSquare[Side::Black] = 0; m_castleTarget[Side::White][QueenSide] = (height() + 1) * m_arwidth + 3; m_castleTarget[Side::White][KingSide] = (height() + 1) * m_arwidth + width() - 1; m_castleTarget[Side::Black][QueenSide] = 2 * m_arwidth + 3; m_castleTarget[Side::Black][KingSide] = 2 * m_arwidth + width() - 1; m_knightOffsets.resize(8); m_knightOffsets[0] = -2 * m_arwidth - 1; m_knightOffsets[1] = -2 * m_arwidth + 1; m_knightOffsets[2] = -m_arwidth - 2; m_knightOffsets[3] = -m_arwidth + 2; m_knightOffsets[4] = m_arwidth - 2; m_knightOffsets[5] = m_arwidth + 2; m_knightOffsets[6] = 2 * m_arwidth - 1; m_knightOffsets[7] = 2 * m_arwidth + 1; m_bishopOffsets.resize(4); m_bishopOffsets[0] = -m_arwidth - 1; m_bishopOffsets[1] = -m_arwidth + 1; m_bishopOffsets[2] = m_arwidth - 1; m_bishopOffsets[3] = m_arwidth + 1; m_rookOffsets.resize(4); m_rookOffsets[0] = -m_arwidth; m_rookOffsets[1] = -1; m_rookOffsets[2] = 1; m_rookOffsets[3] = m_arwidth; } int WesternBoard::captureType(const Move& move) const { if (pieceAt(move.sourceSquare()).type() == Pawn && move.targetSquare() == m_enpassantSquare) return Pawn; return Board::captureType(move); } WesternBoard::CastlingSide WesternBoard::castlingSide(const Move& move) const { int target = move.targetSquare(); const int* rookSq = m_castlingRights.rookSquare[sideToMove()]; if (target == rookSq[QueenSide]) return QueenSide; if (target == rookSq[KingSide]) return KingSide; return NoCastlingSide; } QString WesternBoard::lanMoveString(const Move& move) { CastlingSide cside = castlingSide(move); if (cside != NoCastlingSide && !isRandomVariant()) { Move tmp(move.sourceSquare(), m_castleTarget[sideToMove()][cside]); return Board::lanMoveString(tmp); } return Board::lanMoveString(move); } QString WesternBoard::sanMoveString(const Move& move) { QString str; int source = move.sourceSquare(); int target = move.targetSquare(); Piece piece = pieceAt(source); Piece capture = pieceAt(target); Square square = chessSquare(source); char checkOrMate = 0; makeMove(move); if (inCheck(sideToMove())) { if (canMove()) checkOrMate = '+'; else checkOrMate = '#'; } undoMove(); // drop move if (source == 0 && move.promotion() != Piece::NoPiece) { str = lanMoveString(move); if (checkOrMate != 0) str += checkOrMate; return str; } bool needRank = false; bool needFile = false; Side side = sideToMove(); if (piece.type() == Pawn) { if (target == m_enpassantSquare) capture = Piece(side.opposite(), Pawn); if (capture.isValid()) needFile = true; } else if (piece.type() == King) { CastlingSide cside = castlingSide(move); if (cside != NoCastlingSide) { if (cside == QueenSide) str = "O-O-O"; else str = "O-O"; if (checkOrMate != 0) str += checkOrMate; return str; } else str += pieceSymbol(piece).toUpper(); } else // not king or pawn { str += pieceSymbol(piece).toUpper(); QVarLengthArray moves; generateMoves(moves, piece.type()); for (int i = 0; i < moves.size(); i++) { const Move& move2 = moves.at(i); if (move2.sourceSquare() == 0 || move2.sourceSquare() == source || move2.targetSquare() != target) continue; if (!vIsLegalMove(move2)) continue; Square square2(chessSquare(move2.sourceSquare())); if (square2.file() != square.file()) needFile = true; else if (square2.rank() != square.rank()) needRank = true; } } if (needFile) str += 'a' + square.file(); if (needRank) str += '1' + square.rank(); if (capture.isValid()) str += 'x'; str += squareString(target); if (move.promotion() != Piece::NoPiece) str += "=" + pieceSymbol(move.promotion()).toUpper(); if (checkOrMate != 0) str += checkOrMate; return str; } Move WesternBoard::moveFromLanString(const QString& str) { Move move(Board::moveFromLanString(str)); Side side = sideToMove(); int source = move.sourceSquare(); int target = move.targetSquare(); if (source == m_kingSquare[side] && qAbs(source - target) != 1) { const int* rookSq = m_castlingRights.rookSquare[side]; if (target == m_castleTarget[side][QueenSide]) target = rookSq[QueenSide]; else if (target == m_castleTarget[side][KingSide]) target = rookSq[KingSide]; if (target != 0) return Move(source, target); } return move; } Move WesternBoard::moveFromSanString(const QString& str) { if (str.length() < 2) return Move(); QString mstr = str; Side side = sideToMove(); // Ignore check/mate/strong move/blunder notation while (mstr.endsWith('+') || mstr.endsWith('#') || mstr.endsWith('!') || mstr.endsWith('?')) { mstr.chop(1); } if (mstr.length() < 2) return Move(); // Castling if (mstr.startsWith("O-O")) { CastlingSide cside; if (mstr == "O-O") cside = KingSide; else if (mstr == "O-O-O") cside = QueenSide; else return Move(); int source = m_kingSquare[side]; int target = m_castlingRights.rookSquare[side][cside]; Move move(source, target); if (isLegalMove(move)) return move; else return Move(); } Square sourceSq; Square targetSq; QString::const_iterator it = mstr.begin(); // A SAN move can't start with the capture mark, and // a pawn move must not specify the piece type if (*it == 'x' || pieceFromSymbol(*it) == Pawn) return Move(); // Piece type Piece piece = pieceFromSymbol(*it); if (piece.side() != Side::White) piece = Piece::NoPiece; else piece.setSide(side); if (piece.isEmpty()) { piece = Piece(side, Pawn); targetSq = chessSquare(mstr.mid(0, 2)); if (isValidSquare(targetSq)) it += 2; } else { ++it; // Drop moves if (*it == '@') { targetSq = chessSquare(mstr.right(2)); if (!isValidSquare(targetSq)) return Move(); Move move(0, squareIndex(targetSq), piece.type()); if (isLegalMove(move)) return move; return Move(); } } bool stringIsCapture = false; if (!isValidSquare(targetSq)) { // Source square's file sourceSq.setFile(it->toAscii() - 'a'); if (sourceSq.file() < 0 || sourceSq.file() >= width()) sourceSq.setFile(-1); else if (++it == mstr.end()) return Move(); // Source square's rank if (it->isDigit()) { sourceSq.setRank(it->toAscii() - '1'); if (sourceSq.rank() < 0 || sourceSq.rank() >= height()) return Move(); ++it; } if (it == mstr.end()) { // What we thought was the source square, was // actually the target square. if (isValidSquare(sourceSq)) { targetSq = sourceSq; sourceSq.setRank(-1); sourceSq.setFile(-1); } else return Move(); } // Capture else if (*it == 'x') { if(++it == mstr.end()) return Move(); stringIsCapture = true; } // Target square if (!isValidSquare(targetSq)) { if (it + 1 == mstr.end()) return Move(); targetSq = chessSquare(mstr.mid(it - mstr.begin(), 2)); it += 2; } } if (!isValidSquare(targetSq)) return Move(); int target = squareIndex(targetSq); // Make sure that the move string is right about whether // or not the move is a capture. bool isCapture = false; if (pieceAt(target).side() == side.opposite() || (target == m_enpassantSquare && piece.type() == Pawn)) isCapture = true; if (isCapture != stringIsCapture) return Move(); // Promotion int promotion = Piece::NoPiece; if (it != mstr.end()) { if ((*it == '=' || *it == '(') && ++it == mstr.end()) return Move(); promotion = pieceFromSymbol(*it).type(); if (promotion == Piece::NoPiece) return Move(); } QVarLengthArray moves; generateMoves(moves, piece.type()); const Move* match = 0; // Loop through all legal moves to find a move that matches // the data we got from the move string. for (int i = 0; i < moves.size(); i++) { const Move& move = moves.at(i); if (move.sourceSquare() == 0 || move.targetSquare() != target) continue; Square sourceSq2 = chessSquare(move.sourceSquare()); if (sourceSq.rank() != -1 && sourceSq2.rank() != sourceSq.rank()) continue; if (sourceSq.file() != -1 && sourceSq2.file() != sourceSq.file()) continue; // Castling moves were handled earlier if (pieceAt(target) == Piece(side, Rook)) continue; if (move.promotion() != promotion) continue; if (!vIsLegalMove(move)) continue; // Return an empty move if there are multiple moves that // match the move string. if (match != 0) return Move(); match = &move; } if (match != 0) return *match; return Move(); } QString WesternBoard::castlingRightsString(FenNotation notation) const { QString str; for (int side = Side::White; side <= Side::Black; side++) { for (int cside = KingSide; cside >= QueenSide; cside--) { int rs = m_castlingRights.rookSquare[side][cside]; if (rs == 0) continue; int offset = (cside == QueenSide) ? -1: 1; Piece piece; int i = rs + offset; bool ambiguous = false; // If the castling rook is not the outernmost rook, // the castling square is ambiguous while (!(piece = pieceAt(i)).isWall()) { if (piece == Piece(Side::Type(side), Rook)) { ambiguous = true; break; } i += offset; } QChar c; // If the castling square is ambiguous, then we can't // use 'K' or 'Q'. Instead we'll use the square's file. if (ambiguous || notation == ShredderFen) c = QChar('a' + chessSquare(rs).file()); else { if (cside == 0) c = 'q'; else c = 'k'; } if (side == upperCaseSide()) c = c.toUpper(); str += c; } } if (str.length() == 0) str = "-"; return str; } QString WesternBoard::vFenString(FenNotation notation) const { // Castling rights QString fen = castlingRightsString(notation) + ' '; // En-passant square if (m_enpassantSquare != 0) fen += squareString(m_enpassantSquare); else fen += '-'; // Reversible halfmove count fen += ' '; fen += QString::number(m_reversibleMoveCount); // Full move number fen += ' '; fen += QString::number(m_history.size() / 2 + 1); return fen; } bool WesternBoard::parseCastlingRights(QChar c) { int offset = 0; CastlingSide cside = NoCastlingSide; Side side = (c.isUpper()) ? upperCaseSide() : upperCaseSide().opposite(); c = c.toLower(); if (c == 'q') { cside = QueenSide; offset = -1; } else if (c == 'k') { cside = KingSide; offset = 1; } int kingSq = m_kingSquare[side]; if (offset != 0) { Piece piece; int i = kingSq + offset; int rookSq = 0; // Locate the outernmost rook on the castling side while (!(piece = pieceAt(i)).isWall()) { if (piece == Piece(side, Rook)) rookSq = i; i += offset; } if (rookSq != 0) { setCastlingSquare(side, cside, rookSq); return true; } } else // Shredder FEN or X-FEN { int file = c.toAscii() - 'a'; if (file < 0 || file >= width()) return false; // Get the rook's source square int rookSq; if (side == Side::White) rookSq = (height() + 1) * m_arwidth + 1 + file; else rookSq = 2 * m_arwidth + 1 + file; // Make sure the king and the rook are on the same rank if (abs(kingSq - rookSq) >= width()) return false; // Update castling rights in the FenData object if (pieceAt(rookSq) == Piece(side, Rook)) { if (rookSq > kingSq) cside = KingSide; else cside = QueenSide; setCastlingSquare(side, cside, rookSq); return true; } } return false; } bool WesternBoard::vSetFenString(const QStringList& fen) { if (fen.size() < 2) return false; QStringList::const_iterator token = fen.begin(); // Find the king squares int kingCount[2] = {0, 0}; for (int sq = 0; sq < arraySize(); sq++) { Piece tmp = pieceAt(sq); if (tmp.type() == King) { m_kingSquare[tmp.side()] = sq; kingCount[tmp.side()]++; } } if (kingCount[Side::White] != 1 || kingCount[Side::Black] != 1) return false; // Castling rights m_castlingRights.rookSquare[Side::White][QueenSide] = 0; m_castlingRights.rookSquare[Side::White][KingSide] = 0; m_castlingRights.rookSquare[Side::Black][QueenSide] = 0; m_castlingRights.rookSquare[Side::Black][KingSide] = 0; if (*token != "-") { QString::const_iterator c; for (c = token->begin(); c != token->end(); ++c) { if (!parseCastlingRights(*c)) return false; } } // En-passant square ++token; m_enpassantSquare = 0; Side side(sideToMove()); m_sign = (side == Side::White) ? 1 : -1; if (*token != "-") { setEnpassantSquare(squareIndex(*token)); if (m_enpassantSquare == 0) return false; // Ignore the en-passant square if an en-passant // capture isn't possible. int pawnSq = m_enpassantSquare + m_arwidth * m_sign; Piece ownPawn(side, Pawn); if (pieceAt(pawnSq - 1) != ownPawn && pieceAt(pawnSq + 1) != ownPawn) setEnpassantSquare(0); } // Reversible halfmove count ++token; if (token != fen.end()) { bool ok; int tmp = token->toInt(&ok); if (!ok || tmp < 0) return false; m_reversibleMoveCount = tmp; } else m_reversibleMoveCount = 0; // The full move number is ignored. It's rarely useful m_history.clear(); return true; } void WesternBoard::setEnpassantSquare(int square) { if (square == m_enpassantSquare) return; if (m_enpassantSquare != 0) xorKey(m_zobrist->enpassant(m_enpassantSquare)); if (square != 0) xorKey(m_zobrist->enpassant(square)); m_enpassantSquare = square; } void WesternBoard::setCastlingSquare(Side side, CastlingSide cside, int square) { int& rs = m_castlingRights.rookSquare[side][cside]; if (rs == square) return; if (rs != 0) xorKey(m_zobrist->castling(side, rs)); if (square != 0) xorKey(m_zobrist->castling(side, square)); rs = square; } void WesternBoard::removeCastlingRights(int square) { Piece piece = pieceAt(square); if (piece.type() != Rook) return; Side side(piece.side()); const int* cr = m_castlingRights.rookSquare[side]; if (square == cr[QueenSide]) setCastlingSquare(side, QueenSide, 0); else if (square == cr[KingSide]) setCastlingSquare(side, KingSide, 0); } void WesternBoard::vMakeMove(const Move& move, BoardTransition* transition) { Side side = sideToMove(); int source = move.sourceSquare(); int target = move.targetSquare(); Piece capture = pieceAt(target); int promotionType = move.promotion(); int pieceType = pieceAt(source).type(); int epSq = m_enpassantSquare; int* rookSq = m_castlingRights.rookSquare[side]; bool clearSource = true; bool isReversible = true; Q_ASSERT(target != 0); MoveData md = { capture, epSq, m_castlingRights, NoCastlingSide, m_reversibleMoveCount }; if (source == 0) { Q_ASSERT(promotionType != Piece::NoPiece); pieceType = promotionType; promotionType = Piece::NoPiece; clearSource = false; isReversible = false; epSq = 0; } setEnpassantSquare(0); if (pieceType == King) { // In case of a castling move, make the rook's move CastlingSide cside = castlingSide(move); if (cside != NoCastlingSide) { md.castlingSide = cside; int rookSource = target; target = m_castleTarget[side][cside]; int rookTarget = (cside == QueenSide) ? target + 1 : target -1; if (rookTarget == source || target == source) clearSource = false; Piece rook = Piece(side, Rook); setSquare(rookSource, Piece::NoPiece); setSquare(rookTarget, rook); isReversible = false; if (transition != 0) transition->addMove(chessSquare(rookSource), chessSquare(rookTarget)); } m_kingSquare[side] = target; // Any king move removes all castling rights setCastlingSquare(side, QueenSide, 0); setCastlingSquare(side, KingSide, 0); } else if (pieceType == Pawn) { isReversible = false; // Make an en-passant capture if (target == epSq) { int epTarget = target + m_arwidth * m_sign; setSquare(epTarget, Piece::NoPiece); if (transition != 0) transition->addSquare(chessSquare(epTarget)); } // Push a pawn two squares ahead, creating an en-passant // opportunity for the opponent. else if ((source - target) * m_sign == m_arwidth * 2) { Piece opPawn(side.opposite(), Pawn); if (pieceAt(target - 1) == opPawn || pieceAt(target + 1) == opPawn) setEnpassantSquare(source - m_arwidth * m_sign); } else if (promotionType != Piece::NoPiece) pieceType = promotionType; } else if (pieceType == Rook) { // Remove castling rights from the rook's square for (int i = QueenSide; i <= KingSide; i++) { if (source == rookSq[i]) { setCastlingSquare(side, CastlingSide(i), 0); isReversible = false; break; } } } if (captureType(move) != Piece::NoPiece) { removeCastlingRights(target); isReversible = false; } if (transition != 0) { if (source != 0) transition->addMove(chessSquare(source), chessSquare(target)); else transition->addDrop(Piece(side, pieceType), chessSquare(target)); } setSquare(target, Piece(side, pieceType)); if (clearSource) setSquare(source, Piece::NoPiece); if (isReversible) m_reversibleMoveCount++; else m_reversibleMoveCount = 0; m_history.append(md); m_sign *= -1; } void WesternBoard::vUndoMove(const Move& move) { const MoveData& md = m_history.last(); int source = move.sourceSquare(); int target = move.targetSquare(); m_sign *= -1; Side side = sideToMove(); setEnpassantSquare(md.enpassantSquare); m_reversibleMoveCount = md.reversibleMoveCount; m_castlingRights = md.castlingRights; CastlingSide cside = md.castlingSide; if (cside != NoCastlingSide) { m_kingSquare[side] = source; // Move the rook back after castling int tmp = m_castleTarget[side][cside]; setSquare(tmp, Piece::NoPiece); tmp = (cside == QueenSide) ? tmp + 1 : tmp - 1; setSquare(tmp, Piece::NoPiece); setSquare(target, Piece(side, Rook)); setSquare(source, Piece(side, King)); m_history.pop_back(); return; } else if (target == m_kingSquare[side]) { m_kingSquare[side] = source; } else if (target == m_enpassantSquare) { // Restore the pawn captured by the en-passant move int epTarget = target + m_arwidth * m_sign; setSquare(epTarget, Piece(side.opposite(), Pawn)); } if (move.promotion() != Piece::NoPiece) { if (source != 0) setSquare(source, Piece(side, Pawn)); } else setSquare(source, pieceAt(target)); setSquare(target, md.capture); m_history.pop_back(); } void WesternBoard::generateMovesForPiece(QVarLengthArray& moves, int pieceType, int square) const { if (pieceType == Pawn) return generatePawnMoves(square, moves); if (pieceType == King) { generateHoppingMoves(square, m_bishopOffsets, moves); generateHoppingMoves(square, m_rookOffsets, moves); generateCastlingMoves(moves); return; } if (pieceHasMovement(pieceType, KnightMovement)) generateHoppingMoves(square, m_knightOffsets, moves); if (pieceHasMovement(pieceType, BishopMovement)) generateSlidingMoves(square, m_bishopOffsets, moves); if (pieceHasMovement(pieceType, RookMovement)) generateSlidingMoves(square, m_rookOffsets, moves); } bool WesternBoard::inCheck(Side side, int square) const { Side opSide = side.opposite(); if (square == 0) square = m_kingSquare[side]; // Pawn attacks int step = (side == Side::White) ? -m_arwidth : m_arwidth; // Left side if (pieceAt(square + step - 1) == Piece(opSide, Pawn)) return true; // Right side if (pieceAt(square + step + 1) == Piece(opSide, Pawn)) return true; Piece piece; // Knight, archbishop, chancellor attacks for (int i = 0; i < m_knightOffsets.size(); i++) { piece = pieceAt(square + m_knightOffsets.at(i)); if (piece.side() == opSide && pieceHasMovement(piece.type(), KnightMovement)) return true; } // Bishop, queen, archbishop, king attacks for (int i = 0; i < m_bishopOffsets.size(); i++) { int offset = m_bishopOffsets.at(i); int targetSquare = square + offset; if (m_kingCanCapture && targetSquare == m_kingSquare[opSide]) return true; while ((piece = pieceAt(targetSquare)).isEmpty() || piece.side() == opSide) { if (!piece.isEmpty()) { if (pieceHasMovement(piece.type(), BishopMovement)) return true; break; } targetSquare += offset; } } // Rook, queen, chancellor, king attacks for (int i = 0; i < m_rookOffsets.size(); i++) { int offset = m_rookOffsets[i]; int targetSquare = square + offset; if (m_kingCanCapture && targetSquare == m_kingSquare[opSide]) return true; while ((piece = pieceAt(targetSquare)).isEmpty() || piece.side() == opSide) { if (!piece.isEmpty()) { if (pieceHasMovement(piece.type(), RookMovement)) return true; break; } targetSquare += offset; } } return false; } bool WesternBoard::isLegalPosition() { Side side = sideToMove().opposite(); if (inCheck(side)) return false; if (m_history.isEmpty()) return true; const Move& move = lastMove(); // Make sure that no square between the king's initial and final // squares (including the initial and final squares) are under // attack (in check) by the opponent. CastlingSide cside = m_history.last().castlingSide; if (cside != NoCastlingSide) { int source = move.sourceSquare(); int target = m_castleTarget[side][cside]; int offset = (source <= target) ? 1 : -1; if (source == target) { offset = (cside == KingSide) ? 1 : -1; int i = target - offset; forever { i -= offset; Piece piece(pieceAt(i)); if (piece.isWall()) return true; if (piece.side() == sideToMove() && pieceHasMovement(piece.type(), RookMovement)) return false; } } for (int i = source; i != target; i += offset) { if (inCheck(side, i)) return false; } } return true; } bool WesternBoard::vIsLegalMove(const Move& move) { Q_ASSERT(!move.isNull()); if (!m_kingCanCapture && move.sourceSquare() == m_kingSquare[sideToMove()] && captureType(move) != Piece::NoPiece) return false; return Board::vIsLegalMove(move); } void WesternBoard::addPromotions(int sourceSquare, int targetSquare, QVarLengthArray& moves) const { moves.append(Move(sourceSquare, targetSquare, Knight)); moves.append(Move(sourceSquare, targetSquare, Bishop)); moves.append(Move(sourceSquare, targetSquare, Rook)); moves.append(Move(sourceSquare, targetSquare, Queen)); } void WesternBoard::generatePawnMoves(int sourceSquare, QVarLengthArray& moves) const { int targetSquare; Piece capture; int step = m_sign * m_arwidth; bool isPromotion = pieceAt(sourceSquare - step * 2).isWall(); // One square ahead targetSquare = sourceSquare - step; capture = pieceAt(targetSquare); if (capture.isEmpty()) { if (isPromotion) addPromotions(sourceSquare, targetSquare, moves); else { moves.append(Move(sourceSquare, targetSquare)); // Two squares ahead if (pieceAt(sourceSquare + step * 2).isWall()) { targetSquare -= step; capture = pieceAt(targetSquare); if (capture.isEmpty()) moves.append(Move(sourceSquare, targetSquare)); } } } // Captures, including en-passant moves Side opSide(sideToMove().opposite()); for (int i = -1; i <= 1; i += 2) { targetSquare = sourceSquare - step + i; capture = pieceAt(targetSquare); if (capture.side() == opSide || targetSquare == m_enpassantSquare) { if (isPromotion) addPromotions(sourceSquare, targetSquare, moves); else moves.append(Move(sourceSquare, targetSquare)); } } } bool WesternBoard::canCastle(CastlingSide castlingSide) const { Side side = sideToMove(); int rookSq = m_castlingRights.rookSquare[side][castlingSide]; if (rookSq == 0) return false; int kingSq = m_kingSquare[side]; int target = m_castleTarget[side][castlingSide]; int left; int right; int rtarget; // Find all the squares involved in the castling if (castlingSide == QueenSide) { rtarget = target + 1; if (target < rookSq) left = target; else left = rookSq; if (rtarget > kingSq) right = rtarget; else right = kingSq; } else // Kingside { rtarget = target - 1; if (rtarget < kingSq) left = rtarget; else left = kingSq; if (target > rookSq) right = target; else right = rookSq; } // Make sure that the smallest back rank interval containing the king, // the castling rook, and their destination squares contains no pieces // other than the king and the castling rook. for (int i = left; i <= right; i++) { if (i != kingSq && i != rookSq && !pieceAt(i).isEmpty()) return false; } return true; } void WesternBoard::generateCastlingMoves(QVarLengthArray& moves) const { Side side = sideToMove(); int source = m_kingSquare[side]; for (int i = QueenSide; i <= KingSide; i++) { if (canCastle(CastlingSide(i))) { int target = m_castlingRights.rookSquare[side][i]; moves.append(Move(source, target)); } } } int WesternBoard::kingSquare(Side side) const { Q_ASSERT(!side.isNull()); return m_kingSquare[side]; } int WesternBoard::reversibleMoveCount() const { return m_reversibleMoveCount; } Result WesternBoard::result() { QString str; // Checkmate/Stalemate if (!canMove()) { if (inCheck(sideToMove())) { Side winner = sideToMove().opposite(); str = QObject::tr("%1 mates").arg(winner.toString()); return Result(Result::Win, winner, str); } else { str = QObject::tr("Draw by stalemate"); return Result(Result::Draw, Side::NoSide, str); } } // Insufficient mating material int material[2] = { 0, 0 }; for (int i = 0; i < arraySize(); i++) { const Piece& piece = pieceAt(i); if (!piece.isValid()) continue; if (piece.type() == Knight || piece.type() == Bishop) material[piece.side()] += 1; else material[piece.side()] += 2; } if (material[Side::White] <= 3 && material[Side::Black] <= 3) { str = QObject::tr("Draw by insufficient mating material"); return Result(Result::Draw, Side::NoSide, str); } // 50 move rule if (m_reversibleMoveCount >= 100) { str = QObject::tr("Draw by fifty moves rule"); return Result(Result::Draw, Side::NoSide, str); } // 3-fold repetition if (repeatCount() >= 2) { str = QObject::tr("Draw by 3-fold repetition"); return Result(Result::Draw, Side::NoSide, str); } return Result(); } } // namespace Chess cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/capablancaboard.cpp0000664000175000017500000000323311657223322024447 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "capablancaboard.h" #include "westernzobrist.h" namespace Chess { CapablancaBoard::CapablancaBoard() : WesternBoard(new WesternZobrist()) { setPieceType(Archbishop, QObject::tr("archbishop"), "A", KnightMovement | BishopMovement); setPieceType(Chancellor, QObject::tr("chancellor"), "C", KnightMovement | RookMovement); } Board* CapablancaBoard::copy() const { return new CapablancaBoard(*this); } QString CapablancaBoard::variant() const { return "capablanca"; } int CapablancaBoard::width() const { return 10; } QString CapablancaBoard::defaultFenString() const { return "rnabqkbcnr/pppppppppp/10/10/10/10/PPPPPPPPPP/RNABQKBCNR w KQkq - 0 1"; } void CapablancaBoard::addPromotions(int sourceSquare, int targetSquare, QVarLengthArray& moves) const { WesternBoard::addPromotions(sourceSquare, targetSquare, moves); moves.append(Move(sourceSquare, targetSquare, Archbishop)); moves.append(Move(sourceSquare, targetSquare, Chancellor)); } } // namespace Chess cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/square.h0000664000175000017500000000352311657223322022341 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef SQUARE_H #define SQUARE_H #include namespace Chess { /*! * \brief A generic chess square type consisting of a file and a rank. * * Square is mainly used as a middle-layer between the Board * class (which uses integers for squares) and more generic, high-level * classes like GenericMove. */ class LIB_EXPORT Square { public: /*! Creates a new square with invalid defaults. */ Square(); /*! Creates a new square from \a file and \a rank. */ Square(int file, int rank); /*! Returns true if \a other is the same as this square. */ bool operator==(const Square& other) const; /*! Returns true if \a other is different from this square. */ bool operator!=(const Square& other) const; /*! Returns true if both file and rank have non-negative values. */ bool isValid() const; /*! Zero-based file of the square. 0 is the 'a' file. */ int file() const; /*! Zero-based rank of the square. 0 is white's first rank. */ int rank() const; /*! Sets the file to \a file. */ void setFile(int file); /*! Sets the rank to \a rank. */ void setRank(int rank); private: int m_file; int m_rank; }; } // namespace Chess #endif // SQUARE_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/board.h0000664000175000017500000004154611657223322022137 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef BOARD_H #define BOARD_H #include #include #include #include #include #include "square.h" #include "piece.h" #include "move.h" #include "genericmove.h" #include "zobrist.h" #include "result.h" class QStringList; namespace Chess { class BoardTransition; /*! * \brief An internal chessboard class. * * This is the base class for all chess variants. Board's main purposes are: * - keeping track of the game, and not just piece positions, but also castling * rights, en passant square, played moves, repetitions, etc. * - verifying the legality of moves played * - parsing and generating strings for moves and positions in notations * such as FEN, SAN, and Coordinate notation * - providing information about a game to a graphical board widget * * \internal * The board representation is (width + 2) x (height + 4), so a * traditional 8x8 board would be 10x12, and stored in a one-dimensional * vector with 10 * 12 = 120 elements. */ class LIB_EXPORT Board { public: /*! Coordinate system for the notation of the squares. */ enum CoordinateSystem { /*! * Normal/traditional coordinates used by most chess * variants. * * The file is denoted by a letter, starting with file * 'A' on the left. * The rank is denoted by a number, starting with rank * '1' at the bottom. */ NormalCoordinates, /*! * Inverted coordinates used by some eastern variants like * Shogi. * * The file is denoted by a number, starting with file * '1' on the right. * The rank is denoted by a letter, starting with rank * 'A' at the top. */ InvertedCoordinates }; /*! Notation for move strings. */ enum MoveNotation { StandardAlgebraic, //!< Standard Algebraic notation (SAN). LongAlgebraic //!< Long Algebraic/Coordinate notation. }; /*! Notation for FEN strings. */ enum FenNotation { /*! * X-FEN notation. * \note Specs: http://en.wikipedia.org/wiki/X-FEN */ XFen, /*! Shredder FEN notation. */ ShredderFen }; /*! * Creates a new Board object. * * \param zobrist Zobrist keys for quickly identifying * and comparing positions. The Board class takes ownership of * the zobrist object and takes care of deleting it. */ Board(Zobrist* zobrist); /*! Destructs the Board object. */ virtual ~Board(); /*! Creates and returns a deep copy of this board. */ virtual Board* copy() const = 0; /*! Returns the name of the chess variant. */ virtual QString variant() const = 0; /*! * Returns true if the variant uses randomized starting positions. * The default value is false. */ virtual bool isRandomVariant() const; /*! * Returns true if the variant allows piece drops. * The default value is false. * * \sa CrazyhouseBoard */ virtual bool variantHasDrops() const; /*! * Returns a list of piece types that can be in the reserve, * ie. captured pieces that can be dropped on the board. * * The default implementation returns an empty list. */ virtual QList reservePieceTypes() const; /*! Returns the coordinate system used in the variant. */ virtual CoordinateSystem coordinateSystem() const; /*! Returns the width of the board in squares. */ virtual int width() const = 0; /*! Returns the height of the board in squares. */ virtual int height() const = 0; /*! Returns the variant's default starting FEN string. */ virtual QString defaultFenString() const = 0; /*! Returns the zobrist key for the current position. */ quint64 key() const; /*! * Initializes the board. * This function must be called before a game can be started * on the board. */ void initialize(); /*! Returns true if \a square is on the board. */ bool isValidSquare(const Square& square) const; /*! * Returns the FEN string of the current board position in * X-Fen or Shredder FEN notation */ QString fenString(FenNotation notation = XFen) const; /*! * Returns the FEN string of the starting position. * \note This is not always the same as \a defaultFenString(). */ QString startingFenString() const; /*! * Sets the board position according to a FEN string. * * The \a fen string can be in standard FEN, X-FEN or * Shredder FEN notation. * * Returns true if successfull. */ bool setFenString(const QString& fen); /*! * Sets the board position to the default starting position * of the chess variant. */ void reset(); /*! * Returns the side whose pieces are denoted by uppercase letters. * The default value is White. */ virtual Side upperCaseSide() const; /*! Returns the side to move. */ Side sideToMove() const; /*! Returns the side that made/makes the first move. */ Side startingSide() const; /*! Returns the piece at \a square. */ Piece pieceAt(const Square& square) const; /*! * Returns the number of reserve pieces of type \a piece. * * On variants that don't have piece drops this function * always returns 0. */ int reserveCount(Piece piece) const; /*! Converts \a piece into a piece symbol. */ QString pieceSymbol(Piece piece) const; /*! Converts \a pieceSymbol into a Piece object. */ Piece pieceFromSymbol(const QString& pieceSymbol) const; /*! Returns the internationalized name of \a pieceType. */ QString pieceString(int pieceType) const; /*! * Makes a chess move on the board. * * All details about piece movement, promotions, captures, * drops, etc. are stored in \a transition. These details are * useful mainly for updating a graphical representation of * the board. */ void makeMove(const Move& move, BoardTransition* transition = 0); /*! Reverses the last move. */ void undoMove(); /*! * Converts a Move into a string. * * \note The board must be in a position where \a move can be made. * \sa moveFromString() */ QString moveString(const Move& move, MoveNotation notation); /*! * Converts a move string into a Move. * * \note Returns a null move if \a move is illegal. * \note Notation is automatically detected, and can be anything * that's specified in MoveNotation. * \sa moveString() */ Move moveFromString(const QString& str); /*! * Converts a GenericMove into a Move. * * \note The board must be in a position where \a move can be made. * \sa genericMove() */ Move moveFromGenericMove(const GenericMove& move) const; /*! * Converts a Move into a GenericMove. * * \note The board must be in a position where \a move can be made. * \sa moveFromGenericMove() */ GenericMove genericMove(const Move& move) const; /*! Returns true if \a move is legal in the current position. */ bool isLegalMove(const Move& move); /*! * Returns true if \a move repeats a position that was * reached earlier in the game. */ bool isRepetition(const Move& move); /*! Returns a vector of legal moves in the current position. */ QVector legalMoves(); /*! * Returns the result of the game, or Result::NoResult if * the game is in progress. */ virtual Result result() = 0; protected: /*! * Initializes the variant. * * This function is called by initialize(). Subclasses shouldn't * generally call it by themselves. */ virtual void vInitialize() = 0; /*! * Defines a piece type used in the variant. * If the piece isn't already defined, it's gets added here. * Unlike other initialization which happens in vInitialize(), * all piece types should be defined in the constructor. * * \param type Type of the piece in integer format * \param name The piece's name (internationalized string) * \param symbol Short piece name or piece symbol * \param movement A bit mask for the kinds of moves the * piece can make. */ void setPieceType(int type, const QString& name, const QString& symbol, unsigned movement = 0); /*! Returns true if \pieceType can move like \a movement. */ bool pieceHasMovement(int pieceType, unsigned movement) const; /*! * Makes \a move on the board. * * This function is called by makeMove(), and should take care * of everything except changing the side to move and updating * the move history. * * Details about piece movement, promotions, captures, drops, * etc. should be stored in \a transition. If \a transition is * 0 then it should be ignored. */ virtual void vMakeMove(const Move& move, BoardTransition* transition) = 0; /*! * Reverses \a move on the board. * * This function is called by undoMove() after changing the * side to move to the side that made it. * * \note Unlike vMakeMove(), this function doesn't require * subclasses to update the zobrist position key. */ virtual void vUndoMove(const Move& move) = 0; /*! Converts a square index into a Square object. */ Square chessSquare(int index) const; /*! Converts a string into a Square object. */ Square chessSquare(const QString& str) const; /*! Converts a Square object into a square index. */ int squareIndex(const Square& square) const; /*! Converts a string into a square index. */ int squareIndex(const QString& str) const; /*! Converts a square index into a string. */ QString squareString(int index) const; /*! Converts a Square object into a string. */ QString squareString(const Square& square) const; /*! * Converts a Move object into a string in Long * Algebraic Notation (LAN) */ virtual QString lanMoveString(const Move& move); /*! * Converts a Move object into a string in Standard * Algebraic Notation (SAN). * * \note Specs: http://en.wikipedia.org/wiki/Algebraic_chess_notation */ virtual QString sanMoveString(const Move& move) = 0; /*! Converts a string in LAN format into a Move object. */ virtual Move moveFromLanString(const QString& str); /*! Converts a string in SAN format into a Move object. */ virtual Move moveFromSanString(const QString& str) = 0; /*! * Returns the latter part of the current position's FEN string. * * This function is called by fenString(). The board state, side to * move and hand pieces are handled by the base class. This function * returns the rest of it, if any. */ virtual QString vFenString(FenNotation notation) const = 0; /*! * Sets the board according to a FEN string. * * This function is called by setFenString(). The board state, side * to move and hand pieces are handled by the base class. This * function reads the rest of the string, if any. */ virtual bool vSetFenString(const QStringList& fen) = 0; /*! * Generates pseudo-legal moves for pieces of type \a pieceType. * * \note If \a pieceType is Piece::NoPiece (default), moves are generated * for every piece type. * \sa legalMoves() */ void generateMoves(QVarLengthArray& moves, int pieceType = Piece::NoPiece) const; /*! * Generates piece drops for pieces of type \a pieceType. * * \note If \a pieceType is Piece::NoPiece, moves are generated * for every piece type. * \sa generateMoves() */ void generateDropMoves(QVarLengthArray& moves, int pieceType) const; /*! * Generates pseudo-legal moves for a piece of \a pieceType * at square \a square. * * \note It doesn't matter if \a square doesn't contain a piece of * \a pieceType, the move generator ignores it. */ virtual void generateMovesForPiece(QVarLengthArray& moves, int pieceType, int square) const = 0; /*! * Generates hopping moves for a piece. * * \param sourceSquare The source square of the hopping piece * \param offsets An array of offsets for the target square * \note The generated moves include captures */ void generateHoppingMoves(int sourceSquare, const QVarLengthArray& offsets, QVarLengthArray& moves) const; /*! * Generates sliding moves for a piece. * * \param sourceSquare The source square of the sliding piece * \param offsets An array of offsets for the target square * \note The generated moves include captures */ void generateSlidingMoves(int sourceSquare, const QVarLengthArray& offsets, QVarLengthArray& moves) const; /*! * Returns true if the current position is a legal position. * If the position isn't legal it usually means that the last * move was illegal. */ virtual bool isLegalPosition() = 0; /*! * Returns true if \a move is a legal move. * * This function is called by isLegalMove() after making sure * that there is a pseudo-legal move same as \a move. This * function shouldn't check for the existence of \a move by * generating moves. * * The default implementation only checks if the position * after \a move is legal. */ virtual bool vIsLegalMove(const Move& move); /*! * Returns the type of piece captured by \a move. * Returns Piece::NoPiece if \a move is not a capture. */ virtual int captureType(const Move& move) const; /*! Updates the zobrist position key with \a key. */ void xorKey(quint64 key); /*! * Returns true if a pseudo-legal move \a move exists. * \sa isLegalMove() */ bool moveExists(const Move& move) const; /*! Returns true if the side to move has any legal moves. */ bool canMove(); /*! * Returns the size of the board array, including the padding * (the inaccessible wall squares). */ int arraySize() const; /*! Returns the piece at \a square. */ Piece pieceAt(int square) const; /*! * Sets \a square to contain \a piece. * * This function also updates the zobrist position key, so * subclasses shouldn't mess with it directly. */ void setSquare(int square, Piece piece); /*! Returns the number of halfmoves (plies) played. */ int plyCount() const; /*! * Returns the number of times the current position was * reached previously in the game. */ int repeatCount() const; /*! Returns the last move made in the game. */ const Move& lastMove() const; /*! * Returns the reserve piece type corresponding to \a pieceType. * * The returned value is the type of piece a player receives * (in variants that have piece drops) when he captures a piece of * type \a pieceType. * * The default value is \a pieceType. */ virtual int reserveType(int pieceType) const; /*! Adds \a count pieces of type \a piece to the reserve. */ void addToReserve(const Piece& piece, int count = 1); /*! Removes a piece of type \a piece from the reserve. */ void removeFromReserve(const Piece& piece); private: struct PieceData { QString name; QString symbol; unsigned movement; }; struct MoveData { Move move; quint64 key; }; friend LIB_EXPORT QDebug operator<<(QDebug dbg, const Board* board); bool m_initialized; int m_width; int m_height; Side m_side; Side m_startingSide; QString m_startingFen; quint64 m_key; Zobrist* m_zobrist; QSharedPointer m_sharedZobrist; QVarLengthArray m_pieceData; QVarLengthArray m_squares; QVector m_moveHistory; QVector m_reserve[2]; }; extern LIB_EXPORT QDebug operator<<(QDebug dbg, const Board* board); inline int Board::arraySize() const { return m_squares.size(); } inline Side Board::sideToMove() const { return m_side; } inline Side Board::startingSide() const { return m_startingSide; } inline QString Board::startingFenString() const { return m_startingFen; } inline quint64 Board::key() const { return m_key; } inline void Board::xorKey(quint64 key) { m_key ^= key; } inline Piece Board::pieceAt(int square) const { return m_squares[square]; } inline void Board::setSquare(int square, Piece piece) { Piece& old = m_squares[square]; if (old.isValid()) xorKey(m_zobrist->piece(old, square)); if (piece.isValid()) xorKey(m_zobrist->piece(piece, square)); old = piece; } inline int Board::plyCount() const { return m_moveHistory.size(); } inline const Move& Board::lastMove() const { return m_moveHistory.last().move; } inline bool Board::pieceHasMovement(int pieceType, unsigned movement) const { Q_ASSERT(pieceType != Piece::NoPiece); Q_ASSERT(pieceType < m_pieceData.size()); return (m_pieceData[pieceType].movement & movement); } } // namespace Chess #endif // BOARD_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/crazyhouseboard.h0000664000175000017500000000471511657223322024251 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef CRAZYHOUSEBOARD_H #define CRAZYHOUSEBOARD_H #include "westernboard.h" namespace Chess { /*! * \brief A board for Crazyhouse chess * * Crazyhouse is a variant of standard chess where captured * pieces can be brought back ("dropped") into the game, * similar to Shogi. * * \note Rules: http://en.wikipedia.org/wiki/Crazyhouse */ class LIB_EXPORT CrazyhouseBoard : public WesternBoard { public: /*! Creates a new CrazyhouseBoard object. */ CrazyhouseBoard(); // Inherited from WesternBoard virtual Board* copy() const; virtual QList reservePieceTypes() const; virtual QString variant() const; virtual bool variantHasDrops() const; virtual QString defaultFenString() const; protected: /*! * Promoted piece types for Crazyhouse. * * All of these pieces where promoted from pawns, and * when they're captured they get demoted back to pawns. */ enum CrazyhousePieceType { PromotedKnight = 7, //!< Promoted Knight PromotedBishop, //!< Promoted Bishop PromotedRook, //!< Promoted Rook PromotedQueen, //!< Promoted Queen }; // Inherited from WesternBoard virtual int reserveType(int pieceType) const; virtual QString sanMoveString(const Move& move); virtual Move moveFromSanString(const QString& str); virtual void vMakeMove(const Move& move, BoardTransition* transition); virtual void vUndoMove(const Move& move); virtual void generateMovesForPiece(QVarLengthArray& moves, int pieceType, int square) const; private: static int normalPieceType(int type); static int promotedPieceType(int type); void normalizePieces(Piece piece, QVarLengthArray& squares); void restorePieces(Piece piece, const QVarLengthArray& squares); }; } // namespace Chess #endif // CRAZYHOUSEBOARD_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/genericmove.h0000664000175000017500000000427111657223322023345 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef GENERICMOVE_H #define GENERICMOVE_H #include #include "square.h" namespace Chess { /*! * \brief A chess move independent of chess variant or opening book format * * When a move is made by a human or retrieved from an opening book of any * kind, it will be in this format. Later it can be converted to Chess::Move * by a Chess::Board object. */ class LIB_EXPORT GenericMove { public: /*! Constructs a new null (empty) move. */ GenericMove(); /*! Constructs and initializes a new move. */ GenericMove(const Square& sourceSquare, const Square& targetSquare, int promotion); /*! Returns true if \a other is the same as this move. */ bool operator==(const GenericMove& other) const; /*! Returns true if \a other is different from this move. */ bool operator!=(const GenericMove& other) const; /*! Returns true if this is a null move. */ bool isNull() const; /*! The source square. */ Square sourceSquare() const; /*! The target square. */ Square targetSquare() const; /*! Type of the promotion piece. */ int promotion() const; /*! Sets the source square to \a square. */ void setSourceSquare(const Square& square); /*! Sets the target square to \a square. */ void setTargetSquare(const Square& square); /*! Sets the promotion type to \a pieceType. */ void setPromotion(int pieceType); private: Square m_sourceSquare; Square m_targetSquare; int m_promotion; }; } // namespace Chess Q_DECLARE_METATYPE(Chess::GenericMove) #endif // GENERICMOVE_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/piece.h0000664000175000017500000000724711657223322022135 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef PIECE_H #define PIECE_H #include #include "side.h" namespace Chess { /*! * \brief A chess piece * * The Piece class represents the contents of a square on the chessboard. * It can be an empty piece (NoPiece) or a wall piece (WallPiece) belonging * to neither player (NoSide), or it can be any chess piece belonging * to either White or Black. * * For performance reasons the class is just a wrapper for integer, and it * has a constructor for implicitly converting integers to Piece objects. * * \note A Board object is needed to convert between a Piece and a string. */ class Piece { public: /*! No piece. Used for empty squares. */ static const int NoPiece = 0; /*! A wall square outside of board. */ static const int WallPiece = 100; /*! Creates a new piece of type \a type for \a NoSide. */ Piece(int type = NoPiece); /*! Creates a new piece of type \a type for \a side. */ Piece(Side side, int type); /*! Returns true if \a other is the same as this piece. */ bool operator==(const Piece& other) const; /*! Returns true if \a other is different from this piece. */ bool operator!=(const Piece& other) const; /*! Returns true if this piece is less than \a other. */ bool operator<(const Piece& other) const; /*! Returns true if this piece is more than \a other. */ bool operator>(const Piece& other) const; /*! Returns true if the piece is empty (type is NoPiece). */ bool isEmpty() const; /*! Returns true if this is a valid chess piece. */ bool isValid() const; /*! Returns true if this is a wall piece (inaccessible square). */ bool isWall() const; /*! Returns the side the piece belongs to. */ Side side() const; /*! Returns the type of the piece. */ int type() const; /*! Sets the side to \a side. */ void setSide(Side side); /*! Sets the type to \a type. */ void setType(int type); private: quint16 m_data; }; inline Piece::Piece(int type) : m_data(type | (Side::NoSide << 10)) { } inline Piece::Piece(Side side, int type) : m_data(type | (side << 10)) { Q_ASSERT(!side.isNull()); Q_ASSERT(type != WallPiece); Q_ASSERT(type != NoPiece); } inline bool Piece::operator==(const Piece& other) const { return m_data == other.m_data; } inline bool Piece::operator!=(const Piece& other) const { return m_data != other.m_data; } inline bool Piece::operator<(const Piece& other) const { return m_data < other.m_data; } inline bool Piece::operator>(const Piece& other) const { return m_data > other.m_data; } inline bool Piece::isEmpty() const { return type() == NoPiece; } inline bool Piece::isValid() const { return !side().isNull(); } inline bool Piece::isWall() const { return type() == WallPiece; } inline Side Piece::side() const { return Side(Side::Type(m_data >> 10)); } inline int Piece::type() const { return m_data & 0x3FF; } inline void Piece::setSide(Side side) { m_data = type() | (side << 10); } inline void Piece::setType(int type) { m_data = type | (m_data & 0xC00); } } // namespace Chess #endif // PIECE_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/genericmove.cpp0000664000175000017500000000373111657223322023700 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "genericmove.h" namespace Chess { GenericMove::GenericMove() : m_promotion(0) { } GenericMove::GenericMove(const Square& sourceSquare, const Square& targetSquare, int promotion) : m_sourceSquare(sourceSquare), m_targetSquare(targetSquare), m_promotion(promotion) { } bool GenericMove::operator==(const GenericMove& other) const { if (m_sourceSquare == other.m_sourceSquare && m_targetSquare == other.m_targetSquare && m_promotion == other.m_promotion) return true; return false; } bool GenericMove::operator!=(const GenericMove& other) const { if (m_sourceSquare != other.m_sourceSquare || m_targetSquare != other.m_targetSquare || m_promotion != other.m_promotion) return true; return false; } bool GenericMove::isNull() const { return !(m_sourceSquare.isValid() && m_targetSquare.isValid()); } Square GenericMove::sourceSquare() const { return m_sourceSquare; } Square GenericMove::targetSquare() const { return m_targetSquare; } int GenericMove::promotion() const { return m_promotion; } void GenericMove::setSourceSquare(const Square& square) { m_sourceSquare = square; } void GenericMove::setTargetSquare(const Square& square) { m_targetSquare = square; } void GenericMove::setPromotion(int pieceType) { m_promotion = pieceType; } } // namespace Chess cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/square.cpp0000664000175000017500000000254711657223322022701 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "square.h" namespace Chess { Square::Square() : m_file(-1), m_rank(-1) { } Square::Square(int file, int rank) : m_file(file), m_rank(rank) { } bool Square::operator==(const Square& other) const { return (m_file == other.m_file) && (m_rank == other.m_rank); } bool Square::operator!=(const Square& other) const { return (m_file != other.m_file) || (m_rank != other.m_rank); } bool Square::isValid() const { return (m_file >= 0) && (m_rank >= 0); } int Square::file() const { return m_file; } int Square::rank() const { return m_rank; } void Square::setFile(int file) { m_file = file; } void Square::setRank(int rank) { m_rank = rank; } } // namespace Chess cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/losersboard.cpp0000664000175000017500000000526111657223322023714 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "losersboard.h" #include "westernzobrist.h" namespace Chess { LosersBoard::LosersBoard() : WesternBoard(new WesternZobrist()), m_canCapture(false), m_captureKey(0) { } Board* LosersBoard::copy() const { return new LosersBoard(*this); } QString LosersBoard::variant() const { return "losers"; } QString LosersBoard::defaultFenString() const { return "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"; } bool LosersBoard::vSetFenString(const QStringList& fen) { m_canCapture = false; m_captureKey = 0; return WesternBoard::vSetFenString(fen); } bool LosersBoard::vIsLegalMove(const Move& move) { bool isCapture = (captureType(move) != Piece::NoPiece); if (m_captureKey != key() && !isCapture) { m_captureKey = key(); m_canCapture = false; QVarLengthArray moves; generateMoves(moves); for (int i = 0; i < moves.size(); i++) { if (captureType(moves.at(i)) != Piece::NoPiece && WesternBoard::vIsLegalMove(moves.at(i))) { m_canCapture = true; break; } } } if (!isCapture && m_canCapture) return false; return WesternBoard::vIsLegalMove(move); } Result LosersBoard::result() { Side winner; QString str; // Checkmate/Stalemate if (!canMove()) { winner = sideToMove(); str = QObject::tr("%1 gets mated").arg(winner.toString()); return Result(Result::Win, winner, str); } // Lost all pieces int pieceCount = 0; for (int i = 0; i < arraySize(); i++) { if (pieceAt(i).side() == sideToMove() && ++pieceCount > 1) break; } if (pieceCount <= 1) { winner = sideToMove(); str = QObject::tr("%1 lost all pieces").arg(winner.toString()); return Result(Result::Win, winner, str); } // 50 move rule if (reversibleMoveCount() >= 100) { str = QObject::tr("Draw by fifty moves rule"); return Result(Result::Draw, Side::NoSide, str); } // 3-fold repetition if (repeatCount() >= 2) { str = QObject::tr("Draw by 3-fold repetition"); return Result(Result::Draw, Side::NoSide, str); } return Result(); } } // namespace Chess cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/caparandomboard.h0000664000175000017500000000325511657223322024160 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef CAPARANDOMBOARD_H #define CAPARANDOMBOARD_H #include "capablancaboard.h" namespace Chess { /*! * \brief A board for Capablanca Random chess * * Capablanca Random is like Capablanca chess, but it uses randomized * starting positions similarly to Fischer Random chess. * * \note Rules: http://en.wikipedia.org/wiki/Capablanca_random_chess * \sa CapablancaBoard * \sa FrcBoard */ class LIB_EXPORT CaparandomBoard : public CapablancaBoard { public: /*! Creates a new CaparandomBoard object. */ CaparandomBoard(); // Inherited from CapablancaBoard virtual Board* copy() const; virtual QString variant() const; virtual bool isRandomVariant() const; /*! * Returns a randomized starting FEN string. * * \note qrand() is used for the randomization, so qsrand() * should be called before calling this function. */ virtual QString defaultFenString() const; private: bool pawnsAreSafe(const QVector& pieces) const; }; } // namespace Chess #endif // CAPARANDOMBOARD_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/crazyhouseboard.cpp0000664000175000017500000001267611657223322024611 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "crazyhouseboard.h" #include "westernzobrist.h" #include "boardtransition.h" namespace Chess { CrazyhouseBoard::CrazyhouseBoard() : WesternBoard(new WesternZobrist()) { setPieceType(PromotedKnight, QObject::tr("promoted knight"), "N~", KnightMovement); setPieceType(PromotedBishop, QObject::tr("promoted bishop"), "B~", BishopMovement); setPieceType(PromotedRook, QObject::tr("promoted rook"), "R~", RookMovement); setPieceType(PromotedQueen, QObject::tr("promoted queen"), "Q~", BishopMovement | RookMovement); } Board* CrazyhouseBoard::copy() const { return new CrazyhouseBoard(*this); } QList CrazyhouseBoard::reservePieceTypes() const { QList list; for (int i = 0; i < 2; i++) { for (int type = Pawn; type <= Queen; type++) list << Piece(Side::Type(i), type); } return list; } QString CrazyhouseBoard::variant() const { return "crazyhouse"; } bool CrazyhouseBoard::variantHasDrops() const { return true; } QString CrazyhouseBoard::defaultFenString() const { return "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w - KQkq - 0 1"; } int CrazyhouseBoard::reserveType(int pieceType) const { if (pieceType >= PromotedKnight && pieceType <= PromotedQueen) return Pawn; return pieceType; } int CrazyhouseBoard::normalPieceType(int type) { switch (type) { case PromotedKnight: return Knight; case PromotedBishop: return Bishop; case PromotedRook: return Rook; case PromotedQueen: return Queen; default: return type; } } int CrazyhouseBoard::promotedPieceType(int type) { switch (type) { case Knight: return PromotedKnight; case Bishop: return PromotedBishop; case Rook: return PromotedRook; case Queen: return PromotedQueen; default: return type; } } void CrazyhouseBoard::normalizePieces(Piece piece, QVarLengthArray& squares) { if (!piece.isValid()) return; Piece prom(piece.side(), promotedPieceType(piece.type())); Piece base(piece.side(), normalPieceType(piece.type())); if (base == prom) return; const int size = arraySize(); for (int i = 0; i < size; i++) { if (pieceAt(i) == prom) { squares.append(i); setSquare(i, base); } } } void CrazyhouseBoard::restorePieces(Piece piece, const QVarLengthArray& squares) { if (!piece.isValid() || squares.isEmpty()) return; Piece prom(piece.side(), promotedPieceType(piece.type())); for (int i = 0; i < squares.size(); i++) setSquare(squares.at(i), prom); } QString CrazyhouseBoard::sanMoveString(const Move& move) { Piece piece(pieceAt(move.sourceSquare())); QVarLengthArray squares; normalizePieces(piece, squares); QString str(WesternBoard::sanMoveString(move)); restorePieces(piece, squares); return str; } Move CrazyhouseBoard::moveFromSanString(const QString& str) { if (str.isEmpty()) return Move(); Piece piece(pieceFromSymbol(str.at(0))); if (piece.isValid()) { piece.setSide(sideToMove()); QVarLengthArray squares; normalizePieces(piece, squares); Move move(WesternBoard::moveFromSanString(str)); restorePieces(piece, squares); return move; } return WesternBoard::moveFromSanString(str); } void CrazyhouseBoard::vMakeMove(const Move& move, BoardTransition* transition) { int source = move.sourceSquare(); int target = move.targetSquare(); int prom = move.promotion(); Move tmp(move); if (source != 0 && prom != Piece::NoPiece) tmp = Move(source, target, promotedPieceType(prom)); int ctype = captureType(move); if (ctype != Piece::NoPiece) { Piece reservePiece(sideToMove(), reserveType(ctype)); addToReserve(reservePiece); if (transition != 0) transition->addReservePiece(reservePiece); } else if (source == 0) removeFromReserve(Piece(sideToMove(), prom)); return WesternBoard::vMakeMove(tmp, transition); } void CrazyhouseBoard::vUndoMove(const Move& move) { int source = move.sourceSquare(); int target = move.targetSquare(); int prom = move.promotion(); Move tmp(move); if (source != 0 && prom != Piece::NoPiece) tmp = Move(source, target, promotedPieceType(prom)); WesternBoard::vUndoMove(tmp); int ctype = captureType(move); if (ctype != Piece::NoPiece) removeFromReserve(Piece(sideToMove(), reserveType(ctype))); else if (source == 0) addToReserve(Piece(sideToMove(), prom)); } void CrazyhouseBoard::generateMovesForPiece(QVarLengthArray& moves, int pieceType, int square) const { // Generate drops if (square == 0) { const int size = arraySize(); const int maxRank = height() - 2; for (int i = 0; i < size; i++) { Piece tmp = pieceAt(i); if (!tmp.isEmpty()) continue; if (pieceType == Pawn) { Square sq(chessSquare(i)); if (sq.rank() < 1 || sq.rank() > maxRank) continue; } moves.append(Move(0, i, pieceType)); } } else WesternBoard::generateMovesForPiece(moves, pieceType, square); } } // namespace Chess cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/board.cpp0000664000175000017500000004027611657223322022471 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "board.h" #include #include "zobrist.h" namespace Chess { QDebug operator<<(QDebug dbg, const Board* board) { QString str = "FEN: " + board->fenString() + '\n'; str += QObject::tr("Zobrist key") + ": 0x" + QString::number(board->m_key, 16).toUpper() + '\n'; int i = (board->m_width + 2) * 2; for (int y = 0; y < board->m_height; y++) { i++; for (int x = 0; x < board->m_width; x++) { Piece pc = board->m_squares.at(i); if (pc.isValid()) str += board->pieceSymbol(pc); else str += "."; str += ' '; i++; } i++; str += '\n'; } dbg.nospace() << str; return dbg.space(); } Board::Board(Zobrist* zobrist) : m_initialized(false), m_width(0), m_height(0), m_side(Side::White), m_startingSide(Side::White), m_key(0), m_zobrist(zobrist), m_sharedZobrist(zobrist) { Q_ASSERT(zobrist != 0); setPieceType(Piece::NoPiece, QString(), QString()); } Board::~Board() { } bool Board::isRandomVariant() const { return false; } bool Board::variantHasDrops() const { return false; } QList Board::reservePieceTypes() const { return QList(); } Board::CoordinateSystem Board::coordinateSystem() const { return NormalCoordinates; } Side Board::upperCaseSide() const { return Side::White; } Piece Board::pieceAt(const Square& square) const { if (!isValidSquare(square)) return Piece::WallPiece; return pieceAt(squareIndex(square)); } void Board::initialize() { if (m_initialized) return; m_initialized = true; m_width = width(); m_height = height(); for (int i = 0; i < (m_width + 2) * (m_height + 4); i++) m_squares.append(Piece::WallPiece); vInitialize(); m_zobrist->initialize((m_width + 2) * (m_height + 4), m_pieceData.size()); } void Board::setPieceType(int type, const QString& name, const QString& symbol, unsigned movement) { if (type >= m_pieceData.size()) m_pieceData.resize(type + 1); PieceData data = { name, symbol.toUpper(), movement }; m_pieceData[type] = data; } QString Board::pieceSymbol(Piece piece) const { int type = piece.type(); if (type <= 0 || type >= m_pieceData.size()) return QString(); if (piece.side() == upperCaseSide()) return m_pieceData.at(type).symbol; return m_pieceData.at(type).symbol.toLower(); } Piece Board::pieceFromSymbol(const QString& pieceSymbol) const { if (pieceSymbol.isEmpty()) return Piece::NoPiece; int code = Piece::NoPiece; QString symbol = pieceSymbol.toUpper(); for (int i = 1; i < m_pieceData.size(); i++) { if (symbol == m_pieceData.at(i).symbol) { code = i; break; } } if (code == Piece::NoPiece) return code; Side side(upperCaseSide()); if (pieceSymbol == symbol) return Piece(side, code); return Piece(side.opposite(), code); } QString Board::pieceString(int pieceType) const { if (pieceType <= 0 || pieceType >= m_pieceData.size()) return QString(); return m_pieceData.at(pieceType).name; } int Board::reserveType(int pieceType) const { return pieceType; } int Board::reserveCount(Piece piece) const { if (!piece.isValid() || piece.type() >= m_reserve[piece.side()].size()) return 0; return m_reserve[piece.side()].at(piece.type()); } void Board::addToReserve(const Piece& piece, int count) { Q_ASSERT(piece.isValid()); Q_ASSERT(count > 0); Side side(piece.side()); int type(piece.type()); if (type >= m_reserve[side].size()) m_reserve[side].resize(type + 1); int& oldCount = m_reserve[side][type]; for (int i = 1; i <= count; i++) xorKey(m_zobrist->reservePiece(piece, oldCount++)); } void Board::removeFromReserve(const Piece& piece) { Q_ASSERT(piece.isValid()); Q_ASSERT(piece.type() < m_reserve[piece.side()].size()); int& count = m_reserve[piece.side()][piece.type()]; xorKey(m_zobrist->reservePiece(piece, --count)); } Square Board::chessSquare(int index) const { int arwidth = m_width + 2; int file = (index % arwidth) - 1; int rank = (m_height - 1) - ((index / arwidth) - 2); return Square(file, rank); } int Board::squareIndex(const Square& square) const { if (!isValidSquare(square)) return 0; int rank = (m_height - 1) - square.rank(); return (rank + 2) * (m_width + 2) + 1 + square.file(); } bool Board::isValidSquare(const Chess::Square& square) const { if (!square.isValid() || square.file() >= m_width || square.rank() >= m_height) return false; return true; } QString Board::squareString(int index) const { return squareString(chessSquare(index)); } QString Board::squareString(const Square& square) const { if (!square.isValid()) return QString(); QString str; if (coordinateSystem() == NormalCoordinates) { str += QChar('a' + square.file()); str += QString::number(square.rank() + 1); } else { str += QString::number(m_width - square.file()); str += QChar('a' + (m_height - square.rank()) - 1); } return str; } Square Board::chessSquare(const QString& str) const { if (str.length() < 2) return Square(); bool ok = false; int file = 0; int rank = 0; if (coordinateSystem() == NormalCoordinates) { file = str.at(0).toAscii() - 'a'; rank = str.mid(1).toInt(&ok) - 1; } else { int tmp = str.length() - 1; file = m_width - str.left(tmp).toInt(&ok); rank = m_height - (str.at(tmp).toAscii() - 'a') - 1; } if (!ok) return Square(); return Square(file, rank); } int Board::squareIndex(const QString& str) const { return squareIndex(chessSquare(str)); } QString Board::lanMoveString(const Move& move) { QString str; // Piece drop if (move.sourceSquare() == 0) { Q_ASSERT(move.promotion() != Piece::NoPiece); str += pieceSymbol(move.promotion()).toUpper() + '@'; str += squareString(move.targetSquare()); return str; } str += squareString(move.sourceSquare()); str += squareString(move.targetSquare()); if (move.promotion() != Piece::NoPiece) str += pieceSymbol(move.promotion()).toLower(); return str; } QString Board::moveString(const Move& move, MoveNotation notation) { if (notation == StandardAlgebraic) return sanMoveString(move); return lanMoveString(move); } Move Board::moveFromLanString(const QString& str) { int len = str.length(); if (len < 4) return Move(); Piece promotion; int drop = str.indexOf('@'); if (drop > 0) { promotion = pieceFromSymbol(str.left(drop)); if (!promotion.isValid()) return Move(); Square trg(chessSquare(str.mid(drop + 1))); if (!isValidSquare(trg)) return Move(); return Move(0, squareIndex(trg), promotion.type()); } Square sourceSq(chessSquare(str.mid(0, 2))); Square targetSq(chessSquare(str.mid(2, 2))); if (!isValidSquare(sourceSq) || !isValidSquare(targetSq)) return Move(); if (len > 4) { promotion = pieceFromSymbol(str.mid(len-1)); if (!promotion.isValid()) return Move(); } int source = squareIndex(sourceSq); int target = squareIndex(targetSq); return Move(source, target, promotion.type()); } Move Board::moveFromString(const QString& str) { Move move = moveFromSanString(str); if (move.isNull()) { move = moveFromLanString(str); if (!isLegalMove(move)) return Move(); } return move; } Move Board::moveFromGenericMove(const GenericMove& move) const { int source = squareIndex(move.sourceSquare()); int target = squareIndex(move.targetSquare()); return Move(source, target, move.promotion()); } GenericMove Board::genericMove(const Move& move) const { int source = move.sourceSquare(); int target = move.targetSquare(); return GenericMove(chessSquare(source), chessSquare(target), move.promotion()); } QString Board::fenString(FenNotation notation) const { QString fen; // Squares int i = (m_width + 2) * 2; for (int y = 0; y < m_height; y++) { int nempty = 0; i++; if (y > 0) fen += '/'; for (int x = 0; x < m_width; x++) { Piece pc = m_squares.at(i); if (pc.isEmpty()) nempty++; // Add the number of empty successive squares // to the FEN string. if (nempty > 0 && (!pc.isEmpty() || x == m_width - 1)) { fen += QString::number(nempty); nempty = 0; } if (pc.isValid()) fen += pieceSymbol(pc); i++; } i++; } // Side to move fen += QString(" %1 ").arg(m_side.symbol()); // Hand pieces if (variantHasDrops()) { QString str; for (int i = Side::White; i <= Side::Black; i++) { Side side = Side::Type(i); for (int j = m_reserve[i].size() - 1; j >= 1; j--) { int count = m_reserve[i].at(j); if (count <= 0) continue; if (count > 1) str += QString::number(count); str += pieceSymbol(Piece(side, j)); } } if (str.isEmpty()) str = "-"; fen += str + " "; } return fen + vFenString(notation); } bool Board::setFenString(const QString& fen) { QStringList strList = fen.split(' '); if (strList.isEmpty()) return false; QStringList::iterator token = strList.begin(); if (token->length() < m_height * 2) return false; initialize(); int square = 0; int rankEndSquare = 0; // last square of the previous rank int boardSize = m_width * m_height; int k = (m_width + 2) * 2 + 1; for (int i = 0; i < m_squares.size(); i++) m_squares[i] = Piece::WallPiece; m_key = 0; // Get the board contents (squares) QString pieceStr; for (int i = 0; i < token->length(); i++) { QChar c = token->at(i); // Move to the next rank if (c == '/') { if (!pieceStr.isEmpty()) return false; // Reject the FEN string if the rank didn't // have exactly 'm_width' squares. if (square - rankEndSquare != m_width) return false; rankEndSquare = square; k += 2; continue; } // Add empty squares if (c.isDigit()) { if (!pieceStr.isEmpty()) return false; int j; int nempty; if (i < (token->length() - 1) && token->at(i + 1).isDigit()) { nempty = token->mid(i, 2).toInt(); i++; } else nempty = c.digitValue(); if (nempty > m_width || square + nempty > boardSize) return false; for (j = 0; j < nempty; j++) { square++; setSquare(k++, Piece::NoPiece); } continue; } if (square >= boardSize) return false; pieceStr.append(c); Piece piece = pieceFromSymbol(pieceStr); if (!piece.isValid()) continue; pieceStr.clear(); square++; setSquare(k++, piece); } // The board must have exactly 'boardSize' squares and each rank // must have exactly 'm_width' squares. if (square != boardSize || square - rankEndSquare != m_width) return false; // Side to move if (++token == strList.end()) return false; m_side = Side(*token); m_startingSide = m_side; if (m_side.isNull()) return false; // Hand pieces m_reserve[Side::White].clear(); m_reserve[Side::Black].clear(); if (variantHasDrops() && ++token != strList.end() && *token != "-") { QString::const_iterator it; for (it = token->constBegin(); it != token->constEnd(); ++it) { int count = 1; if (it->isDigit()) { count = it->digitValue(); if (count <= 0) return false; ++it; if (it == token->constEnd()) return false; } Piece tmp = pieceFromSymbol(*it); if (!tmp.isValid()) return false; addToReserve(tmp, count); } } m_moveHistory.clear(); m_startingFen = fen; // Let subclasses handle the rest of the FEN string if (token != strList.end()) ++token; strList.erase(strList.begin(), token); if (!vSetFenString(strList)) return false; if (m_side == Side::White) xorKey(m_zobrist->side()); if (!isLegalPosition()) return false; return true; } void Board::reset() { setFenString(defaultFenString()); } void Board::makeMove(const Move& move, BoardTransition* transition) { Q_ASSERT(!m_side.isNull()); Q_ASSERT(!move.isNull()); MoveData md = { move, m_key }; vMakeMove(move, transition); xorKey(m_zobrist->side()); m_side = m_side.opposite(); m_moveHistory << md; } void Board::undoMove() { Q_ASSERT(!m_moveHistory.isEmpty()); Q_ASSERT(!m_side.isNull()); m_side = m_side.opposite(); vUndoMove(m_moveHistory.last().move); m_key = m_moveHistory.last().key; m_moveHistory.pop_back(); } void Board::generateMoves(QVarLengthArray& moves, int pieceType) const { Q_ASSERT(!m_side.isNull()); // Cut the wall squares (the ones with a value of WallPiece) off // from the squares to iterate over. It bumps the speed up a bit. unsigned begin = (m_width + 2) * 2; unsigned end = m_squares.size() - begin; moves.clear(); for (unsigned sq = begin; sq < end; sq++) { Piece tmp = m_squares.at(sq); if (tmp.side() == m_side && (pieceType == Piece::NoPiece || tmp.type() == pieceType)) generateMovesForPiece(moves, tmp.type(), sq); } generateDropMoves(moves, pieceType); } void Board::generateDropMoves(QVarLengthArray& moves, int pieceType) const { const QVector& pieces(m_reserve[m_side]); if (pieces.isEmpty()) return; if (pieceType == Piece::NoPiece) { for (int i = 1; i < pieces.size(); i++) { Q_ASSERT(pieces.at(i) >= 0); if (pieces.at(i) > 0) generateMovesForPiece(moves, i, 0); } } else if (pieceType < pieces.size() && pieces.at(pieceType) > 0) generateMovesForPiece(moves, pieceType, 0); } void Board::generateHoppingMoves(int sourceSquare, const QVarLengthArray& offsets, QVarLengthArray& moves) const { Side opSide = sideToMove().opposite(); for (int i = 0; i < offsets.size(); i++) { int targetSquare = sourceSquare + offsets.at(i); Piece capture = pieceAt(targetSquare); if (capture.isEmpty() || capture.side() == opSide) moves.append(Move(sourceSquare, targetSquare)); } } void Board::generateSlidingMoves(int sourceSquare, const QVarLengthArray& offsets, QVarLengthArray& moves) const { Side side = sideToMove(); for (int i = 0; i < offsets.size(); i++) { int offset = offsets.at(i); int targetSquare = sourceSquare + offset; Piece capture; while (!(capture = pieceAt(targetSquare)).isWall() && capture.side() != side) { moves.append(Move(sourceSquare, targetSquare)); if (!capture.isEmpty()) break; targetSquare += offset; } } } bool Board::moveExists(const Move& move) const { Q_ASSERT(!move.isNull()); int source = move.sourceSquare(); QVarLengthArray moves; if (source == 0) generateDropMoves(moves, move.promotion()); else { Piece piece = m_squares.at(source); if (piece.side() != m_side) return false; generateMovesForPiece(moves, piece.type(), source); } for (int i = 0; i < moves.size(); i++) { if (moves[i] == move) return true; } return false; } int Board::captureType(const Move& move) const { Q_ASSERT(!move.isNull()); Piece piece(m_squares.at(move.targetSquare())); if (piece.side() == m_side.opposite()) return piece.type(); return Piece::NoPiece; } bool Board::vIsLegalMove(const Move& move) { Q_ASSERT(!move.isNull()); makeMove(move); bool isLegal = isLegalPosition(); undoMove(); return isLegal; } bool Board::isLegalMove(const Move& move) { return !move.isNull() && moveExists(move) && vIsLegalMove(move); } int Board::repeatCount() const { if (plyCount() < 4) return 0; int repeatCount = 0; for (int i = plyCount() - 1; i >= 0; i--) { if (m_moveHistory.at(i).key == m_key) repeatCount++; } return repeatCount; } bool Board::isRepetition(const Chess::Move& move) { Q_ASSERT(!move.isNull()); makeMove(move); bool isRepeat = (repeatCount() > 0); undoMove(); return isRepeat; } bool Board::canMove() { QVarLengthArray moves; generateMoves(moves); for (int i = 0; i < moves.size(); i++) { if (vIsLegalMove(moves.at(i))) return true; } return false; } QVector Board::legalMoves() { QVarLengthArray moves; QVector legalMoves; generateMoves(moves); legalMoves.reserve(moves.size()); for (int i = moves.size() - 1; i >= 0; i--) { if (vIsLegalMove(moves.at(i))) legalMoves << moves.at(i); } return legalMoves; } } // namespace Chess cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/standardboard.cpp0000664000175000017500000020363411657223322024211 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "standardboard.h" #include "westernzobrist.h" // Zobrist keys for Polyglot opening book compatibility // Specs: http://alpha.uhasselt.be/Research/Algebra/Toga/book_format.html static const quint64 s_keys[] = { Q_UINT64_C(0xF8D626AAAF278509), Q_UINT64_C(0x2218DBC13AB50C2A), Q_UINT64_C(0xEB7284FF06058ED8), Q_UINT64_C(0x588B4C4C77A4044D), Q_UINT64_C(0xC2366DF16A5D128C), Q_UINT64_C(0x6AF41C8BC3CD3747), Q_UINT64_C(0xC44724AA3113C398), Q_UINT64_C(0x65B1CB16D7E82B11), Q_UINT64_C(0xE1B9337AEC4F3258), Q_UINT64_C(0xDA9FBBC453B39DD6), Q_UINT64_C(0x30C7DA4974856499), Q_UINT64_C(0x6F1BF73106135133), Q_UINT64_C(0xF0690786D0FA4CF3), Q_UINT64_C(0xFCF7C2FAEC36AE5), Q_UINT64_C(0x7036FB645C8022D1), Q_UINT64_C(0xE86CB406094DC561), Q_UINT64_C(0x5BEE2A1AA2E82902), Q_UINT64_C(0xF37B2423D265081), Q_UINT64_C(0xAA80DD12DFC6514), Q_UINT64_C(0xFA30772D72E666B4), Q_UINT64_C(0x604A1A6573CBAC2A), Q_UINT64_C(0x7F2524F4A8D61248), Q_UINT64_C(0x5CE9158221105F1), Q_UINT64_C(0x600B95C509709C15), Q_UINT64_C(0x7A7BFC26A3776A9B), Q_UINT64_C(0x3C3903FBBB72F5F6), Q_UINT64_C(0xF14B0802E1794CA1), Q_UINT64_C(0x4103F9F6900BF8FE), Q_UINT64_C(0x684A7079EF22B8D5), Q_UINT64_C(0xBFF71E2DDCDA4CE4), Q_UINT64_C(0x539AC6E19DD9546C), Q_UINT64_C(0xA5D4CE1041B2F3E2), Q_UINT64_C(0xB5DB4F70B4BF100C), Q_UINT64_C(0x62633036B52BA698), Q_UINT64_C(0x4B69B89A24C35FFF), Q_UINT64_C(0x735A9D8CC92BFC1E), Q_UINT64_C(0x5FE719284468DA36), Q_UINT64_C(0xE37E4D40DFC80DB7), Q_UINT64_C(0xB5E3FA1D4FFB0FC3), Q_UINT64_C(0x2DBDCEE01B3B710F), Q_UINT64_C(0x9192DA2A8BA59244), Q_UINT64_C(0x1B85755B5078FC8), Q_UINT64_C(0x70CC73D90BC26E24), Q_UINT64_C(0xE21A6B35DF0C3AD7), Q_UINT64_C(0x3A93D8B2806962), Q_UINT64_C(0x1C99DED33CB890A1), Q_UINT64_C(0xCF3145DE0ADD4289), Q_UINT64_C(0xD0E4427A5514FB72), Q_UINT64_C(0x77C621CC9FB3A483), Q_UINT64_C(0x67A34DAC4356550B), Q_UINT64_C(0xFD8295313B655A34), Q_UINT64_C(0xD46E962F1991A4D7), Q_UINT64_C(0x69AE242C10381AA1), Q_UINT64_C(0x8FDCA3ADE6CB188E), Q_UINT64_C(0x8D020DB131D50BF5), Q_UINT64_C(0x1B4BBBCE736A0986), Q_UINT64_C(0x9A42919B79473F2E), Q_UINT64_C(0x85E62C39F15CED02), Q_UINT64_C(0x9761B6F309189C64), Q_UINT64_C(0xF21F2E77914B4387), Q_UINT64_C(0x1CF27C68ACBD3509), Q_UINT64_C(0x69B491A7F7411B53), Q_UINT64_C(0xFA2BC6B2D6FCE1F8), Q_UINT64_C(0x1E2929786E30A7B4), Q_UINT64_C(0x7452ED65CCD9B3B7), Q_UINT64_C(0xFCE3344D3B2AD7EE), Q_UINT64_C(0x34C7D78C383BF9D7), Q_UINT64_C(0x3F2D645159E1E84F), Q_UINT64_C(0xD284281BECF6678C), Q_UINT64_C(0x469EA956C1D8FEC1), Q_UINT64_C(0x7819A719C9D1D9D1), Q_UINT64_C(0xF7A2045F5D685F3A), Q_UINT64_C(0x70CC73D90BC26E24), Q_UINT64_C(0xE21A6B35DF0C3AD7), Q_UINT64_C(0x3A93D8B2806962), Q_UINT64_C(0x1C99DED33CB890A1), Q_UINT64_C(0xCF3145DE0ADD4289), Q_UINT64_C(0xD0E4427A5514FB72), Q_UINT64_C(0x77C621CC9FB3A483), Q_UINT64_C(0x67A34DAC4356550B), Q_UINT64_C(0xDC2476AFF0D52080), Q_UINT64_C(0x975EBFE9E7404DF2), Q_UINT64_C(0x49D4A7E27FE30DF4), Q_UINT64_C(0x8009BFCA4EE4919B), Q_UINT64_C(0xEE8CA80EE2FD32E8), Q_UINT64_C(0xEBADFC49B577F881), Q_UINT64_C(0xF587E73F1A460573), Q_UINT64_C(0x60D166CEA131A27), Q_UINT64_C(0xA84AE7ABE1CAE939), Q_UINT64_C(0x453019A09B558064), Q_UINT64_C(0x3CA4940AF9E05E35), Q_UINT64_C(0x6C4C7F1E2275A0F0), Q_UINT64_C(0xB22AD8F4637056D8), Q_UINT64_C(0xC69F68C241DAF1E), Q_UINT64_C(0x3EED55D6988DAEFA), Q_UINT64_C(0x48BBAD7E68ECC8DD), Q_UINT64_C(0x4B520209CCEDE632), Q_UINT64_C(0xFF3A5C1C94308909), Q_UINT64_C(0x46813A0F9DE6940F), Q_UINT64_C(0x2C8B6238D13E6BCA), Q_UINT64_C(0xB0302CFC591E7C05), Q_UINT64_C(0x39CB94C51143B2E), Q_UINT64_C(0x1466DB569D0E96CA), Q_UINT64_C(0x70CDF56D8F082C6A), Q_UINT64_C(0xA5A19C4046E69125), Q_UINT64_C(0xC927A74ED9FB8E9A), Q_UINT64_C(0xF70DF0133E1F22A6), Q_UINT64_C(0xEF4BB86EC7466519), Q_UINT64_C(0x61D3BC1D115290E8), Q_UINT64_C(0x2128480FCB477CC5), Q_UINT64_C(0x57B1C98CA121C26D), Q_UINT64_C(0x1E75156F3932E738), Q_UINT64_C(0xC50243B023BFDFE6), Q_UINT64_C(0xAAFE82F42080867B), Q_UINT64_C(0xEEA184F941C8AAC3), Q_UINT64_C(0x9D7C10B078EDA916), Q_UINT64_C(0x5D77C0E4A928E18B), Q_UINT64_C(0x19B7A15CD4A74C02), Q_UINT64_C(0x49A00DB17E45B832), Q_UINT64_C(0xE2AB6120AC0236B9), Q_UINT64_C(0x40F4F33B6A247E73), Q_UINT64_C(0xE2F3E6EDD24D21D3), Q_UINT64_C(0xFE15E66AA22062A3), Q_UINT64_C(0xEC6AE23CEC076287), Q_UINT64_C(0x8169D1C0E896C6C4), Q_UINT64_C(0xAD4D06AF5A7D5603), Q_UINT64_C(0x701C04A64A8CC670), Q_UINT64_C(0x11E38538D90C03B3), Q_UINT64_C(0x45B23F95E930EE), Q_UINT64_C(0xA6FEB860A3AB76B), Q_UINT64_C(0xEFC9975564391505), Q_UINT64_C(0xA56D274B00CFCDF4), Q_UINT64_C(0x22D144A3888E887C), Q_UINT64_C(0x98B072469BA02ECE), Q_UINT64_C(0xAD657F11D45BDC09), Q_UINT64_C(0xB4383B8BA3E081E7), Q_UINT64_C(0x93D9CED1D7D22DA8), Q_UINT64_C(0xA15768E68D493ABB), Q_UINT64_C(0x8389B00D9C3F6932), Q_UINT64_C(0x2E52251C1483DB15), Q_UINT64_C(0x1E94588F067A2554), Q_UINT64_C(0x1C934904428EFB93), Q_UINT64_C(0x355B0C4FA499C296), Q_UINT64_C(0x6B9832D7C9F49057), Q_UINT64_C(0xBF291744075B5985), Q_UINT64_C(0x76CBDC2080364F6A), Q_UINT64_C(0x1F567418B0539258), Q_UINT64_C(0x6B7A2DC25E963317), Q_UINT64_C(0x7D72727048E2348), Q_UINT64_C(0xD67C019C98196BDB), Q_UINT64_C(0x880F48854DC6366A), Q_UINT64_C(0x56D7DBDCFA1D9B11), Q_UINT64_C(0xD093B0437CB44CF0), Q_UINT64_C(0x7408FA85B650A350), Q_UINT64_C(0xF0ADF4281F4E99EE), Q_UINT64_C(0xD0DF2775B9D642D7), Q_UINT64_C(0x4D6978048EEBCCCE), Q_UINT64_C(0x80639ABA4603457D), Q_UINT64_C(0x5BA462A34CB7CE4B), Q_UINT64_C(0xD805147E57FD32AD), Q_UINT64_C(0x7E4B4DDF0FD35977), Q_UINT64_C(0x5FA1B4368A490281), Q_UINT64_C(0x10028B42778E4F7E), Q_UINT64_C(0x1FFF44A562725454), Q_UINT64_C(0x2BA069825600EED8), Q_UINT64_C(0xCEC1B09404A7B1B3), Q_UINT64_C(0xE9C48EBAC803580A), Q_UINT64_C(0xCE63248DAF8C3088), Q_UINT64_C(0x4A9E8E87D395E250), Q_UINT64_C(0x30C82C81472F0B5), Q_UINT64_C(0xFCBEFD9E8FFE31E6), Q_UINT64_C(0xFA7F62A7CF7E6C66), Q_UINT64_C(0xEE332516CBF94DDA), Q_UINT64_C(0xDC43B56586DF7533), Q_UINT64_C(0x842ECC0E62CF10E2), Q_UINT64_C(0x5DEF79767D143DB3), Q_UINT64_C(0xEF91CCEAB9143AD9), Q_UINT64_C(0x17D75D2615EFC214), Q_UINT64_C(0x9051392BFB803EE9), Q_UINT64_C(0x61AF84E88FDA46D0), Q_UINT64_C(0xC6BB593042443AE5), Q_UINT64_C(0xDB210584AF2D0B51), Q_UINT64_C(0x64E9E54C5B557E40), Q_UINT64_C(0x758AD1A3E10E3280), Q_UINT64_C(0x3BDAFF9731CCB9BC), Q_UINT64_C(0x22873E9DAE58C19A), Q_UINT64_C(0x8F636073B36AA638), Q_UINT64_C(0x1E3B7919B5F64A0A), Q_UINT64_C(0x8DD9454B0D6FA0FE), Q_UINT64_C(0x6ACDF3DFC3831FC9), Q_UINT64_C(0x6D8A459B1F3335DA), Q_UINT64_C(0x452F31C631004B86), Q_UINT64_C(0x32E70EA39DCE95D2), Q_UINT64_C(0x110818A60069CCFA), Q_UINT64_C(0xBF4EFC5B66CA977), Q_UINT64_C(0x32EF4C91912831D1), Q_UINT64_C(0x66C8B9AA15E86A28), Q_UINT64_C(0x92B7CBB2AC7A9B63), Q_UINT64_C(0xB565CD2069B502CF), Q_UINT64_C(0xF355599EAA2AE71B), Q_UINT64_C(0x42A6A1E985CDB97F), Q_UINT64_C(0x3F3682CE22F2FBB), Q_UINT64_C(0x4E1CED2EF6EE615B), Q_UINT64_C(0x6CC7BCB70B641C91), Q_UINT64_C(0x90C0FAB0BF5010D8), Q_UINT64_C(0x8CD75C27306E4DB1), Q_UINT64_C(0x1E0C436937D20067), Q_UINT64_C(0x1C7300ABFD162539), Q_UINT64_C(0xC2065EB6430AF3CF), Q_UINT64_C(0xF4AA3F25CBB92983), Q_UINT64_C(0x62567AAA1DB4BC28), Q_UINT64_C(0xFF30541B33A88B88), Q_UINT64_C(0xF165B587DF898190), Q_UINT64_C(0x7FD8A7C292FE74F8), Q_UINT64_C(0xFBA47DA7BBE9DF63), Q_UINT64_C(0xE2A880EF685F3FBA), Q_UINT64_C(0xFC7EFAFF94613194), Q_UINT64_C(0xC2A0F80F93E49A1D), Q_UINT64_C(0x462DAEDE8E151DDC), Q_UINT64_C(0x31D71DCE64B2C310), Q_UINT64_C(0x2B2B69C8422A0B77), Q_UINT64_C(0x41758C3B596725ED), Q_UINT64_C(0x5622C33655E30889), Q_UINT64_C(0xBAF396C59202CD19), Q_UINT64_C(0x2581485AB0A79857), Q_UINT64_C(0x6C3B6A75035F1950), Q_UINT64_C(0xC4F2E1B25B5A5E4F), Q_UINT64_C(0x3B802B14F676E241), Q_UINT64_C(0x75334C46C0C39CBA), Q_UINT64_C(0xAE535625CD027654), Q_UINT64_C(0x4A54B219BED31776), Q_UINT64_C(0xD17CF23AC984A340), Q_UINT64_C(0xEAB0EF82596A5A98), Q_UINT64_C(0x27165370463CFD96), Q_UINT64_C(0xE494CF37BF604462), Q_UINT64_C(0x89AD899BB87CF392), Q_UINT64_C(0xC206A930DD9D545B), Q_UINT64_C(0xD485674342D2F9C0), Q_UINT64_C(0xC6DC0BAD1F60D2EE), Q_UINT64_C(0xE6380242C6A258BD), Q_UINT64_C(0x3168F1BFF7B6523F), Q_UINT64_C(0xE99BB165BE4B9168), Q_UINT64_C(0x1F288ADD342A325F), Q_UINT64_C(0x62304F84DAF00713), Q_UINT64_C(0x91ED3830CD824660), Q_UINT64_C(0x7C0C5A9C43E71513), Q_UINT64_C(0xE63D0CF134ED60FB), Q_UINT64_C(0xEB9D8CE975CAD458), Q_UINT64_C(0xEBCBD55438244E6), Q_UINT64_C(0x50174CCA7323820A), Q_UINT64_C(0xFBE65FDB809DCC41), Q_UINT64_C(0x91D9F734EDEC0AB8), Q_UINT64_C(0x47DE68A2C0DF79E9), Q_UINT64_C(0x1BEF78D259EA950A), Q_UINT64_C(0xC66432B7E212040E), Q_UINT64_C(0x930319772C1B1519), Q_UINT64_C(0x552B25132B54484B), Q_UINT64_C(0x1F0EED2E495E0ECD), Q_UINT64_C(0xFE5BB7280EA71A6B), Q_UINT64_C(0x1783659B3EF4A334), Q_UINT64_C(0xA368E3314C31840), Q_UINT64_C(0x5DF55FAB131AAB66), Q_UINT64_C(0x1EF6E6DBB1961EC9), Q_UINT64_C(0x53BBA33AD35D9F15), Q_UINT64_C(0x397335EB683ECC89), Q_UINT64_C(0x714870EEF35B1C15), Q_UINT64_C(0xC20284FC4945C6E5), Q_UINT64_C(0xB724CFA9C2D7EDFD), Q_UINT64_C(0xA58F2584EF4B94EC), Q_UINT64_C(0xA57E6339DD2CF3A0), Q_UINT64_C(0xE51C77A135C3CEB9), Q_UINT64_C(0x95A32E0270BD8867), Q_UINT64_C(0x2E02C6B75F1EC0D3), Q_UINT64_C(0xAD7280420953C5E4), Q_UINT64_C(0x85C027362E00250C), Q_UINT64_C(0xC62BE2AAB5599548), Q_UINT64_C(0x7408F599C803A81C), Q_UINT64_C(0xE8A73464627A644A), Q_UINT64_C(0x5F225601F06FD5E8), Q_UINT64_C(0x587CD6E8B05169CF), Q_UINT64_C(0x4EAA5CF8F952977), Q_UINT64_C(0xAD59815BBD235544), Q_UINT64_C(0x7E74D4C8320B31AA), Q_UINT64_C(0xBA27FC7D573185EE), Q_UINT64_C(0x72D573066DFAB1BC), Q_UINT64_C(0x1FE9902A0968CE97), Q_UINT64_C(0x9FFA62BDB9B1AD7C), Q_UINT64_C(0x533531D7F7676A27), Q_UINT64_C(0x523FF0A8E1515C4), Q_UINT64_C(0x8F421D96343F28A0), Q_UINT64_C(0x8CAD5777EAAF46F1), Q_UINT64_C(0x95B420D699209A26), Q_UINT64_C(0x657BB149385AB45D), Q_UINT64_C(0xD877E14D2F2143E2), Q_UINT64_C(0x4985BBADB6F8F6AF), Q_UINT64_C(0x6CAD1EE1FF694986), Q_UINT64_C(0xF47322256CB5264F), Q_UINT64_C(0x809D6A67AFE7677B), Q_UINT64_C(0xA9602D6BD1CCA665), Q_UINT64_C(0x5826BB90E646C574), Q_UINT64_C(0x9565482631DB26B6), Q_UINT64_C(0xD2A85A04128BFFF3), Q_UINT64_C(0x942406C9ED5BD624), Q_UINT64_C(0xC05B8E994D168218), Q_UINT64_C(0xE10EDA0530E3E631), Q_UINT64_C(0x529FBDA0A1CF2006), Q_UINT64_C(0xA89D9ACC0FEC08E2), Q_UINT64_C(0xD81DC3313AA13F30), Q_UINT64_C(0xAA9F4E0BE0BFE0C8), Q_UINT64_C(0xE3E6059865BEA717), Q_UINT64_C(0x1484E560353113C8), Q_UINT64_C(0xB5E40C1D5C0D475C), Q_UINT64_C(0xD7E51E7A3B8559CB), Q_UINT64_C(0xCCF4EE1B8973ED72), Q_UINT64_C(0x9B0B198FEA6F6038), Q_UINT64_C(0xB98B632A5827298), Q_UINT64_C(0xE5B90B71F790EBF0), Q_UINT64_C(0x282E5F49BB45820B), Q_UINT64_C(0x433B1753B3F0CE45), Q_UINT64_C(0x2FE4541E4C47579B), Q_UINT64_C(0xC6B16DA110C55D18), Q_UINT64_C(0x6533C6666AAC1FFA), Q_UINT64_C(0xC135EB857DB33D07), Q_UINT64_C(0x7DEF2D1998EB3CB4), Q_UINT64_C(0xAE111E05A3AF9412), Q_UINT64_C(0x756B95DBEB257F85), Q_UINT64_C(0x29275967DD7F53AD), Q_UINT64_C(0xEA81639DC476D2B2), Q_UINT64_C(0x9C4FCB9A6F418D3C), Q_UINT64_C(0x7CE9868DA369D7BE), Q_UINT64_C(0xB5872CFB353FBB01), Q_UINT64_C(0xE1ACF60A2A9D651F), Q_UINT64_C(0xFB8351C2E8B7BDB0), Q_UINT64_C(0x7C405F4C9F221C8E), Q_UINT64_C(0xFCE6AB71021DE98), Q_UINT64_C(0xA6DE79D191C5BFF), Q_UINT64_C(0x27E335014D1B9C9A), Q_UINT64_C(0xD90F3E4CD5F89197), Q_UINT64_C(0xC7661934556BA7A8), Q_UINT64_C(0xA83D7DF0D6894E69), Q_UINT64_C(0x8210B39249842AF9), Q_UINT64_C(0x17BBCC1A6D735787), Q_UINT64_C(0xC3D661A849C875C8), Q_UINT64_C(0xDC53F25423C66F19), Q_UINT64_C(0xF96C75380BC02186), Q_UINT64_C(0x21CBAFD4C0D6848), Q_UINT64_C(0x247010A03E5CF51C), Q_UINT64_C(0x6C11ED84379DC9AE), Q_UINT64_C(0xD16FB42BBDA90271), Q_UINT64_C(0xFD023F3F1F453A83), Q_UINT64_C(0x3D882B6F10446821), Q_UINT64_C(0x4072D1701BD415D6), Q_UINT64_C(0xFD7189C606734992), Q_UINT64_C(0xC8C62376C9652D78), Q_UINT64_C(0x201E5F2B698D5E95), Q_UINT64_C(0xE1B16D9EC0A5C5E3), Q_UINT64_C(0xEACF54BBF3975A22), Q_UINT64_C(0x990E3AB6B17FA0E6), Q_UINT64_C(0x7E682E91F1AAAF2), Q_UINT64_C(0x4CE0BBEA52F42178), Q_UINT64_C(0x86C188FA02E320DF), Q_UINT64_C(0xB1E5EC76AE342E4D), Q_UINT64_C(0xA52E99E5554B6AFD), Q_UINT64_C(0x12B19D5E941DA1B4), Q_UINT64_C(0xAAF76C4E9CA21862), Q_UINT64_C(0xA5144587F1792BC4), Q_UINT64_C(0x6CC6E30EB7F77E6F), Q_UINT64_C(0x36572065655FAE54), Q_UINT64_C(0xCAE0A3DAA1E06FA3), Q_UINT64_C(0x3FEB48F4895E1584), Q_UINT64_C(0xA88CCAB0FA4EE30), Q_UINT64_C(0x8DAB1841E2F84C40), Q_UINT64_C(0xFB7A00C8043BE013), Q_UINT64_C(0x5ED9E2DC2215AF7B), Q_UINT64_C(0x8DB0CBCCA0F68FE7), Q_UINT64_C(0x4D51E47230B867C1), Q_UINT64_C(0x6775C508E1CCD5D8), Q_UINT64_C(0xFA1A2DA3AD9C5B65), Q_UINT64_C(0xB2A20BB50E9B0C4B), Q_UINT64_C(0x6FDEB94102560E30), Q_UINT64_C(0x29E5701B728E2B83), Q_UINT64_C(0xDC35D9130F2E8A1), Q_UINT64_C(0x7A8501FB0246C854), Q_UINT64_C(0x2EB80C6E325C99B8), Q_UINT64_C(0x84B84C9705BA4A7), Q_UINT64_C(0x572E25237895BBCB), Q_UINT64_C(0x2499DDCB8A52E8D4), Q_UINT64_C(0x9F9227406C0ECACC), Q_UINT64_C(0x5BDD304652451E16), Q_UINT64_C(0xD204D3662CB12D20), Q_UINT64_C(0xEFA7333DD025C3A0), Q_UINT64_C(0x502008F4E361A790), Q_UINT64_C(0x5422878B6D63A28D), Q_UINT64_C(0x57EA1309901E3799), Q_UINT64_C(0x810E4472184B75B), Q_UINT64_C(0x848A726F601132A8), Q_UINT64_C(0x4F04EDFBFB4B90B6), Q_UINT64_C(0x45347400D78B8B56), Q_UINT64_C(0xC7B0F97213872C20), Q_UINT64_C(0xC2E9CE1F78DB4DD7), Q_UINT64_C(0x90915126A34565D), Q_UINT64_C(0xD98CBB3F1D1E57D9), Q_UINT64_C(0x4370428AD3DDCD87), Q_UINT64_C(0xDA78167267F99DF0), Q_UINT64_C(0xBE5DAAE58DD48A2C), Q_UINT64_C(0x35664CD7D5E5EF77), Q_UINT64_C(0x65BDC6AB5BC4A633), Q_UINT64_C(0x4019C83C9D2750F3), Q_UINT64_C(0x3BB65C74B4733445), Q_UINT64_C(0x98189972C1BA5539), Q_UINT64_C(0x270186D9E59D9A63), Q_UINT64_C(0xA9D90E5BCFDF6640), Q_UINT64_C(0x41A9FD29A12AD630), Q_UINT64_C(0x291BDB539A97875C), Q_UINT64_C(0x87B9659D303F5B0D), Q_UINT64_C(0x657DBFC811A0AA0A), Q_UINT64_C(0x38BE0CC6BDE6A582), Q_UINT64_C(0xC673A82DAE6972AB), Q_UINT64_C(0x3A6EA0C46BBBC661), Q_UINT64_C(0xF40CC7C8FC32C0F2), Q_UINT64_C(0x5CB7D55A6B7E6E1E), Q_UINT64_C(0xB43566E858D291EE), Q_UINT64_C(0x59B312AF98C8FD2F), Q_UINT64_C(0x18386F803BCD7F8C), Q_UINT64_C(0x798D98841D271DE3), Q_UINT64_C(0xDD57C06F11890520), Q_UINT64_C(0x1A319D7F23B6C58B), Q_UINT64_C(0xD373A11484002A84), Q_UINT64_C(0x919772C4E816976A), Q_UINT64_C(0x323EA2EB344DDF45), Q_UINT64_C(0xA88210C9C9DD12E7), Q_UINT64_C(0xE82DCA0C000905CC), Q_UINT64_C(0x5F80536DBC65CB37), Q_UINT64_C(0xB6E83C64A8C63920), Q_UINT64_C(0xD8C32EA7B317196D), Q_UINT64_C(0x9D3D8176072F6C7B), Q_UINT64_C(0xFD901B89A5707920), Q_UINT64_C(0x2F76A55E7FE24053), Q_UINT64_C(0x8CBC6C6D65F67CC2), Q_UINT64_C(0x501BBC4CC57B461A), Q_UINT64_C(0xE0E16D79C9AE0CAF), Q_UINT64_C(0x7F562EC9CDD3982F), Q_UINT64_C(0xC96310A34702F396), Q_UINT64_C(0xCFC362F4430B5EF3), Q_UINT64_C(0x2B6FF9ABAACC7BFC), Q_UINT64_C(0x7814AC5F6C1D2FBD), Q_UINT64_C(0xAF9EEB17929C7ABC), Q_UINT64_C(0x657116BFB38E6A42), Q_UINT64_C(0x6753FDA13F3F34DE), Q_UINT64_C(0x506896E24E95219A), Q_UINT64_C(0x95FBBA6BCF739011), Q_UINT64_C(0x2716168415F038F8), Q_UINT64_C(0x6EBE6D2348C29003), Q_UINT64_C(0xD814EBE4AECD6AF8), Q_UINT64_C(0x1AC33A0A4AA38554), Q_UINT64_C(0xEBD9BD4229A232C6), Q_UINT64_C(0x2209FF676F997607), Q_UINT64_C(0x1E6C0A1E87B5FC8F), Q_UINT64_C(0xA32B40FCFEFFB73A), Q_UINT64_C(0x9E66241A90494EAD), Q_UINT64_C(0xFAC0229EB8F94673), Q_UINT64_C(0xBFD1BE58EDE3B1A3), Q_UINT64_C(0xB62A31D30FE88C52), Q_UINT64_C(0xEA005EB1550946B3), Q_UINT64_C(0xA32BC4D3A932CD9), Q_UINT64_C(0xBE4508CD24443F17), Q_UINT64_C(0x40653286D15285B), Q_UINT64_C(0xDDDDE1C07985BEF4), Q_UINT64_C(0x5B92A09DBAE97D5C), Q_UINT64_C(0x18A000D5196CBA60), Q_UINT64_C(0x6B0E272EE83882EF), Q_UINT64_C(0x94185A2DD7788052), Q_UINT64_C(0x3AF09C275811C225), Q_UINT64_C(0x4B4899C3007D1F4A), Q_UINT64_C(0x2AC4FEA59959C8BD), Q_UINT64_C(0x54B2AAAB423CDB5B), Q_UINT64_C(0x5FE4256A910C51B), Q_UINT64_C(0xC97524AE38F9B925), Q_UINT64_C(0x78786D407892D92F), Q_UINT64_C(0xCAE6F59E1A19D47F), Q_UINT64_C(0x6FB3810952C4733), Q_UINT64_C(0xFDAF8AA047D33586), Q_UINT64_C(0x81EC2DDD030DDFAF), Q_UINT64_C(0xFA7240FCF173F90F), Q_UINT64_C(0x9F2BCB0B9616F985), Q_UINT64_C(0xE550E9BC77E2CB8D), Q_UINT64_C(0xF036ABBB3C626752), Q_UINT64_C(0x60D465941613203A), Q_UINT64_C(0xFDE3F2A16A014E7C), Q_UINT64_C(0xDD179BEA2693EEFD), Q_UINT64_C(0x1005D553EBF8DF4A), Q_UINT64_C(0x1B11CBC06B7694CE), Q_UINT64_C(0xE1AEE68F33F3AEDF), Q_UINT64_C(0x19D605AC0BB75EBA), Q_UINT64_C(0x53B3F5ECA1E49AB1), Q_UINT64_C(0xA7B919CEE0D922A7), Q_UINT64_C(0xC9DEF1ACA9E566C4), Q_UINT64_C(0xA21FA08BBA43F7C3), Q_UINT64_C(0xDA2DFFF4767F9DF7), Q_UINT64_C(0xA429F6E915699B51), Q_UINT64_C(0x5559358491F4020C), Q_UINT64_C(0xA6C6DD2AD5A90CE), Q_UINT64_C(0x799E81F05BC93F31), Q_UINT64_C(0x86536B8CF3428A8C), Q_UINT64_C(0x97D7374C60087B73), Q_UINT64_C(0xA246637CFF328532), Q_UINT64_C(0x43FCAE60CC0EBA0), Q_UINT64_C(0x920E449535DD359E), Q_UINT64_C(0x70EB093B15B290CC), Q_UINT64_C(0x73A1921916591CBD), Q_UINT64_C(0xCE1AE056E48417C9), Q_UINT64_C(0x5C002D0C209583CE), Q_UINT64_C(0xB9FD7620E7316243), Q_UINT64_C(0x5A7E8A57DB91B77), Q_UINT64_C(0xB5889C6E15630A75), Q_UINT64_C(0x4A750A09CE9573F7), Q_UINT64_C(0xCF464CEC899A2F8A), Q_UINT64_C(0xF538639CE705B824), Q_UINT64_C(0x3C79A0FF5580EF7F), Q_UINT64_C(0xEDE6C87F8477609D), Q_UINT64_C(0xFB951877C06E057C), Q_UINT64_C(0xA843D943A544EE86), Q_UINT64_C(0x2171E64683023A08), Q_UINT64_C(0x5B9B63EB9CEFF80C), Q_UINT64_C(0x506AACF489889342), Q_UINT64_C(0x1881AFC9A3A701D6), Q_UINT64_C(0x6503080440750644), Q_UINT64_C(0xDFD395339CDBF4A7), Q_UINT64_C(0xEF927DBCF00C20F2), Q_UINT64_C(0x7B32F7D1E03680EC), Q_UINT64_C(0x9FFC4884A28CA647), Q_UINT64_C(0xFC751A94DFCCB6A1), Q_UINT64_C(0x9C1633264DB49C89), Q_UINT64_C(0xB3F22C3D0B0B38ED), Q_UINT64_C(0x390E5FB44D01144B), Q_UINT64_C(0x5BFEA5B4712768E9), Q_UINT64_C(0x1E1032911FA78984), Q_UINT64_C(0x9A74ACB964E78CB3), Q_UINT64_C(0x4F80F7A035DAFB04), Q_UINT64_C(0x6304D09A0B3738C4), Q_UINT64_C(0xA2ACCA35B04BDFEA), Q_UINT64_C(0x72C532DDDF863AFB), Q_UINT64_C(0x87B3E2B2B5C907B1), Q_UINT64_C(0xA366E5B8C54F48B8), Q_UINT64_C(0xAE4A9346CC3F7CF2), Q_UINT64_C(0x1920C04D47267BBD), Q_UINT64_C(0x87BF02C6B49E2AE9), Q_UINT64_C(0x92237AC237F3859), Q_UINT64_C(0xFF07F64EF8ED14D0), Q_UINT64_C(0x8DE8DCA9F03CC54E), Q_UINT64_C(0x44ACA94945C31026), Q_UINT64_C(0x1ECFBF01B1129F68), Q_UINT64_C(0x27E6AD7891165C3F), Q_UINT64_C(0x8535F040B9744FF1), Q_UINT64_C(0x54B3F4FA5F40D873), Q_UINT64_C(0x72B12C32127FED2B), Q_UINT64_C(0xEE954D3C7B411F47), Q_UINT64_C(0x9A85AC909A24EAA1), Q_UINT64_C(0x70AC4CD9F04F21F5), Q_UINT64_C(0xF9B89D3E99A075C2), Q_UINT64_C(0xDF917C6D8CA75A72), Q_UINT64_C(0x5C0CF4C49BADEED1), Q_UINT64_C(0x14ACBAF4777D5776), Q_UINT64_C(0xF145B6BECCDEA195), Q_UINT64_C(0xDABF2AC8201752FC), Q_UINT64_C(0x24C3C94DF9C8D3F6), Q_UINT64_C(0xBB6E2924F03912EA), Q_UINT64_C(0xCE26C0B95C980D9), Q_UINT64_C(0xA49CD132BFBF7CC4), Q_UINT64_C(0xE99D662AF4243939), Q_UINT64_C(0xD00C37F7FB6ACA8E), Q_UINT64_C(0x6E026BE8C6604B9F), Q_UINT64_C(0x5355F900C2A82DC7), Q_UINT64_C(0x7FB9F855A997142), Q_UINT64_C(0x5093417AA8A7ED5E), Q_UINT64_C(0x7BCBC38DA25A7F3C), Q_UINT64_C(0x19FC8A768CF4B6D4), Q_UINT64_C(0x637A7780DECFC0D9), Q_UINT64_C(0x8249A47AEE0E41F7), Q_UINT64_C(0x79AD695501E7D1E8), Q_UINT64_C(0x7F08F6327D2E9850), Q_UINT64_C(0x616174F6AA9B6FB5), Q_UINT64_C(0x2BA04114676403F7), Q_UINT64_C(0x4CD364C99A21AFF4), Q_UINT64_C(0x4CA343F0A3F0D93E), Q_UINT64_C(0xF282424CEF98035B), Q_UINT64_C(0xFCF4501947B20AE), Q_UINT64_C(0xD91323B4C22F57B1), Q_UINT64_C(0xA63060012A95BBDD), Q_UINT64_C(0xBD142194FE4D22CE), Q_UINT64_C(0xEBEE7B52E375FF8E), Q_UINT64_C(0xF12D5DB3D062400B), Q_UINT64_C(0x9AE21EB2CAE9B65F), Q_UINT64_C(0xAC359DE9BD27329A), Q_UINT64_C(0xD2DDE3B7C684831C), Q_UINT64_C(0xB9834E0ABCB685BE), Q_UINT64_C(0xDDB2B6D22145094C), Q_UINT64_C(0x5E0B6BBD43B7605), Q_UINT64_C(0xAABA573156EADD82), Q_UINT64_C(0xBED8E6095383FA7B), Q_UINT64_C(0x4054E51F6431C996), Q_UINT64_C(0x3B5030F00793C5D2), Q_UINT64_C(0x903BFCE2E4037ADF), Q_UINT64_C(0x12EF53585E7C1B36), Q_UINT64_C(0x3B136FD4F47A0234), Q_UINT64_C(0x70276A9020157374), Q_UINT64_C(0xDE54BD5D3BEAEDE9), Q_UINT64_C(0xF97513F6C0D163B9), Q_UINT64_C(0x7E474BE4FAB6E17F), Q_UINT64_C(0x90D331A41308B8F3), Q_UINT64_C(0xF151CDE862BEE4DD), Q_UINT64_C(0x1ACB89A43A2C593E), Q_UINT64_C(0x6F7CF66CD2D40A72), Q_UINT64_C(0x31EF2592A2D55578), Q_UINT64_C(0xB269CAB20F5C0EDC), Q_UINT64_C(0xDB32183B09E37DFC), Q_UINT64_C(0x7C77C6875117E9B1), Q_UINT64_C(0xB31B9639F9154FFF), Q_UINT64_C(0xB5097FDD1F96DF21), Q_UINT64_C(0x8604196E9D42CAAD), Q_UINT64_C(0xBD1901B905911DA8), Q_UINT64_C(0x60C42F5DEF3BD6A2), Q_UINT64_C(0xF678647E3519AC6E), Q_UINT64_C(0x1B85D488D0F20CC5), Q_UINT64_C(0xDAB9FE6525D89021), Q_UINT64_C(0xD151D86ADB73615), Q_UINT64_C(0xA865A54EDCC0F019), Q_UINT64_C(0x93C42566AEF98FFB), Q_UINT64_C(0x99E7AFEABE000731), Q_UINT64_C(0x48CBFF086DDF285A), Q_UINT64_C(0x8854D4B8D00F1EB7), Q_UINT64_C(0x15035A7756C335E2), Q_UINT64_C(0x4FEABFBBDB619CB), Q_UINT64_C(0x742E1E651C60BA83), Q_UINT64_C(0x9A9632E65904AD3C), Q_UINT64_C(0x881B82A13B51B9E2), Q_UINT64_C(0x506E6744CD974924), Q_UINT64_C(0xB0183DB56FFC6A79), Q_UINT64_C(0xED9B915C66ED37E), Q_UINT64_C(0x5E11E86D5873D484), Q_UINT64_C(0xB57E7CEB56A30E41), Q_UINT64_C(0x688E67F6CFB85DE6), Q_UINT64_C(0x722FF175F572C348), Q_UINT64_C(0x1D1260A51107FE97), Q_UINT64_C(0x7A249A57EC0C9BA2), Q_UINT64_C(0x4208FE9E8F7F2D6), Q_UINT64_C(0x5A110C6058B920A0), Q_UINT64_C(0xCD9A497658A5698), Q_UINT64_C(0x56FD23C8F9715A4C), Q_UINT64_C(0x284C847B9D887AAE), Q_UINT64_C(0x51D3FBA464B2FF8E), Q_UINT64_C(0xF9770FE3DA06C6ED), Q_UINT64_C(0xA90B24499FCFAFB1), Q_UINT64_C(0x77A225A07CC2C6BD), Q_UINT64_C(0x513E5E634C70E331), Q_UINT64_C(0x4361C0CA3F692F12), Q_UINT64_C(0xD941ACA44B20A45B), Q_UINT64_C(0x528F7C8602C5807B), Q_UINT64_C(0x52AB92BEB9613989), Q_UINT64_C(0x9D1DFA2EFC557F73), Q_UINT64_C(0x899FAE4CD6BB109B), Q_UINT64_C(0x16B36DC740EF867), Q_UINT64_C(0x40E087931A00930D), Q_UINT64_C(0x8CFFA9412EB642C1), Q_UINT64_C(0x68CA39053261169F), Q_UINT64_C(0x7A1EE967D27579E2), Q_UINT64_C(0x9D1D60E5076F5B6F), Q_UINT64_C(0x3810E399B6F65BA2), Q_UINT64_C(0x32095B6D4AB5F9B1), Q_UINT64_C(0x35CAB62109DD038A), Q_UINT64_C(0x89E2311CAC5D17C8), Q_UINT64_C(0xEC921AB8C861035E), Q_UINT64_C(0x87D380BDA5BF7859), Q_UINT64_C(0x16B9F7E06C453A21), Q_UINT64_C(0x7BA2484C8A0FD54E), Q_UINT64_C(0xF3A678CAD9A2E38C), Q_UINT64_C(0x39B0BF7DDE437BA2), Q_UINT64_C(0xFCAF55C1BF8A4424), Q_UINT64_C(0x18FCF680573FA594), Q_UINT64_C(0x4C0563B89F495AC3), Q_UINT64_C(0xC21BF7D74B3CCB11), Q_UINT64_C(0xA08289F5E0F81C39), Q_UINT64_C(0xD2B7ADEEDED1F73F), Q_UINT64_C(0xF7A255D83BC373F8), Q_UINT64_C(0xD7F4F2448C0CEB81), Q_UINT64_C(0xD95BE88CD210FFA7), Q_UINT64_C(0x336F52F8FF4728E7), Q_UINT64_C(0xA74049DAC312AC71), Q_UINT64_C(0xA2F61BB6E437FDB5), Q_UINT64_C(0x4F2A5CB07F6A35B3), Q_UINT64_C(0xD77D40BEC1B47726), Q_UINT64_C(0x1A9904D40FD6294F), Q_UINT64_C(0xC547F57E42A7444E), Q_UINT64_C(0x78E37644E7CAD29E), Q_UINT64_C(0xFE9A44E9362F05FA), Q_UINT64_C(0x8BD35CC38336615), Q_UINT64_C(0x9315E5EB3A129ACE), Q_UINT64_C(0x94061B871E04DF75), Q_UINT64_C(0xDF1D9F9D784BA010), Q_UINT64_C(0x3BBA57B68871B59D), Q_UINT64_C(0x4EFA096C3993EA30), Q_UINT64_C(0x77CB914FC38B518D), Q_UINT64_C(0x2B2CD3C13AB74613), Q_UINT64_C(0x96DBBDCE4C61DFF9), Q_UINT64_C(0xC351E7003628291F), Q_UINT64_C(0xBB22FFD391C084AB), Q_UINT64_C(0x816C900BE8FA35A9), Q_UINT64_C(0x6F19CAEA234653FB), Q_UINT64_C(0xB20F27046A1E30ED), Q_UINT64_C(0xA6BDF4EA6610A00D), Q_UINT64_C(0xA81DE1EEC60A54A7), Q_UINT64_C(0x64EE3B82A7EF3666), Q_UINT64_C(0x741D4AB853685B2F), Q_UINT64_C(0xABF0B642DE57D30E), Q_UINT64_C(0x143C428B608A8E1E), Q_UINT64_C(0xA47107358D53127A), Q_UINT64_C(0x276E9E8F9B1C0E08), Q_UINT64_C(0xC5ACDDF5F0693605), Q_UINT64_C(0x33716260CBFD5CF8), Q_UINT64_C(0xF30F952752ED7ECA), Q_UINT64_C(0x65E197277D8F4FD8), Q_UINT64_C(0xB747E119AA67766C), Q_UINT64_C(0xCA2AACDB3C82638B), Q_UINT64_C(0x828B42055B7D639B), Q_UINT64_C(0xCBE56A48E523E5E7), Q_UINT64_C(0xEBB06F391E722323), Q_UINT64_C(0x160A97FA53619750), Q_UINT64_C(0x1745DCEA893DA6B), Q_UINT64_C(0x6A611EBA1D3A26B1), Q_UINT64_C(0x43F3AACA76E645A8), Q_UINT64_C(0xA9ADE905A4ED3D6D), Q_UINT64_C(0xAF66F55917303882), Q_UINT64_C(0x418E01A9C44AAED4), Q_UINT64_C(0xFBD4870C3DEAA3D1), Q_UINT64_C(0x38ABC9194B251C18), Q_UINT64_C(0x406B6B24EF4499F1), Q_UINT64_C(0x8E73027027EE8713), Q_UINT64_C(0xCE1B4EB4E8B2755A), Q_UINT64_C(0x8BB7361F189005D3), Q_UINT64_C(0xDFACEC9FF262F74C), Q_UINT64_C(0x568362AB91CD0CDA), Q_UINT64_C(0x545359E58BBB19F), Q_UINT64_C(0x3D5774A11D31AB39), Q_UINT64_C(0x8A1B083821F40CB4), Q_UINT64_C(0x7B4A38E32537DF62), Q_UINT64_C(0x950113646D1D6E03), Q_UINT64_C(0x4DA8979A0041E8A9), Q_UINT64_C(0x3BC36E078F7515D7), Q_UINT64_C(0x5D0A12F27AD310D1), Q_UINT64_C(0x7F9D1A2E1EBE1327), Q_UINT64_C(0xA1041B7E3778684F), Q_UINT64_C(0xBEF86AE14588663F), Q_UINT64_C(0xE479EE5B9930578C), Q_UINT64_C(0xE7F28ECD2D49EECD), Q_UINT64_C(0x56C074A581EA17FE), Q_UINT64_C(0x5544F7D774B14AEF), Q_UINT64_C(0x7B3F0195FC6F290F), Q_UINT64_C(0x12153635B2C0CF57), Q_UINT64_C(0x7F5126DBBA5E0CA7), Q_UINT64_C(0x7A76956C3EAFB413), Q_UINT64_C(0xEF9F9039B5687E59), Q_UINT64_C(0xE03E65585470E7B7), Q_UINT64_C(0x829626E3892D95D7), Q_UINT64_C(0x92FAE24291F2B3F1), Q_UINT64_C(0x63E22C147B9C3403), Q_UINT64_C(0xC678B6D860284A1C), Q_UINT64_C(0x5873888850659AE7), Q_UINT64_C(0x981DCD296A8736D), Q_UINT64_C(0x9F65789A6509A440), Q_UINT64_C(0x9FF38FED72E9052F), Q_UINT64_C(0xB2D4D11F648B0F8B), Q_UINT64_C(0x5677A505B0A72311), Q_UINT64_C(0xD2733C4335C6A72F), Q_UINT64_C(0x7E75D99D94A70F4D), Q_UINT64_C(0x6CED1983376FA72B), Q_UINT64_C(0x97FCAACBF030BC24), Q_UINT64_C(0x7B77497B32503B12), Q_UINT64_C(0x8547EDDFB81CCB94), Q_UINT64_C(0x79999CDFF70902CB), Q_UINT64_C(0xCFFE1939438E9B24), Q_UINT64_C(0xE9F631D64A15A88B), Q_UINT64_C(0x3ADAE26BACF0CF3D), Q_UINT64_C(0xB7A0B174CFF6F36E), Q_UINT64_C(0xD4DBA84729AF48AD), Q_UINT64_C(0x2E18BC1AD9704A68), Q_UINT64_C(0x2DE0966DAF2F8B1C), Q_UINT64_C(0xB9C11D5B1E43A07E), Q_UINT64_C(0x64972D68DEE33360), Q_UINT64_C(0x94628D38D0C20584), Q_UINT64_C(0xDBC0D2B6AB90A559), Q_UINT64_C(0x4637EE463E27655D), Q_UINT64_C(0xF23CE066ABF1241C), Q_UINT64_C(0x1DD01AAFCD53486A), Q_UINT64_C(0x1FCA8A92FD719F85), Q_UINT64_C(0xFC7C95D827357AFA), Q_UINT64_C(0x18A6A990C8B35EBD), Q_UINT64_C(0xCCCB7005C6B9C28D), Q_UINT64_C(0x3BDBB92C43B17F26), Q_UINT64_C(0xAA70B5B4F89695A2), Q_UINT64_C(0xE94C39A54A98307F), Q_UINT64_C(0x784B11D6292BA5D), Q_UINT64_C(0x47E2EC47068CF37E), Q_UINT64_C(0x11317BA87905E790), Q_UINT64_C(0x7FBF21EC8A1F45EC), Q_UINT64_C(0x1725CABFCB045B00), Q_UINT64_C(0x964E915CD5E2B207), Q_UINT64_C(0x3E2B8BCBF016D66D), Q_UINT64_C(0xBE7444E39328A0AC), Q_UINT64_C(0xF85B2B4FBCDE44B7), Q_UINT64_C(0x49353FEA39BA63B1), Q_UINT64_C(0x54534340E2C7C25), Q_UINT64_C(0xCBE3A7499046CB36), Q_UINT64_C(0x23B70EDB1955C4BF), Q_UINT64_C(0xC330DE426430F69D), Q_UINT64_C(0x4715ED43E8A45C0A), Q_UINT64_C(0xA8D7E4DAB780A08D), Q_UINT64_C(0x572B974F03CE0BB), Q_UINT64_C(0xB57D2E985E1419C7), Q_UINT64_C(0xE8D9ECBE2CF3D73F), Q_UINT64_C(0x2FE4B17170E59750), Q_UINT64_C(0xD49A5DFDAE0A5872), Q_UINT64_C(0x3DC7D4E4167963EE), Q_UINT64_C(0xFF172C0EDC26E796), Q_UINT64_C(0x6A477FA8D26E7FE6), Q_UINT64_C(0x71C636E3094C1B2E), Q_UINT64_C(0xDFC6202EB8AE5DBD), Q_UINT64_C(0x55D035B7BFB78D57), Q_UINT64_C(0x683CC7F6AEE35B37), Q_UINT64_C(0x717BF12777C01265), Q_UINT64_C(0x605A94F1EEDA57B8), Q_UINT64_C(0x29EF5F9C324ECE9D), Q_UINT64_C(0x18588FCCCFDCEAA5), Q_UINT64_C(0xB14425AFF8350B88), Q_UINT64_C(0x71C429FC21C26D18), Q_UINT64_C(0x243B6FC154C4DCB8), Q_UINT64_C(0x83CEF85126C0016E), Q_UINT64_C(0x6E0E99F13CA0BA26), Q_UINT64_C(0xE7E273CFE048DD7B), Q_UINT64_C(0xAC3B275CCE403191), Q_UINT64_C(0x7121D93AFF7EDE87), Q_UINT64_C(0x195D44062E46EE1), Q_UINT64_C(0xFD8E8FC93BB16403), Q_UINT64_C(0xDA52E2993CF7DC6), Q_UINT64_C(0xA601FA61EAE4B090), Q_UINT64_C(0x34514495CA2F51C9), Q_UINT64_C(0x715E1AFFBBCC508C), Q_UINT64_C(0x14DA7808379161F0), Q_UINT64_C(0x534EE54EF4960AC7), Q_UINT64_C(0x49A57E644EC5AAB7), Q_UINT64_C(0x7EF949307896F221), Q_UINT64_C(0xDF609E04F356AA37), Q_UINT64_C(0xFFFDF4D4A34ABDF0), Q_UINT64_C(0x4305193E0332F368), Q_UINT64_C(0x89E235DAF37D00DF), Q_UINT64_C(0x5397CB5C78380A59), Q_UINT64_C(0xC5DF26FB2EEA1BAA), Q_UINT64_C(0xEA3578F6B90091E7), Q_UINT64_C(0x7CB3531DCAB61A06), Q_UINT64_C(0x57CD5EB0C095DFD7), Q_UINT64_C(0x1ADB8862C4ED469D), Q_UINT64_C(0xC66D79EA66E23459), Q_UINT64_C(0x6BD6E3FBCA467509), Q_UINT64_C(0xEBE9EA2ADF4321C7), Q_UINT64_C(0x3219A39EE587A30), Q_UINT64_C(0x49787FEF17AF9924), Q_UINT64_C(0xA1E9300CD8520548), Q_UINT64_C(0x5B45E522E4B1B4EF), Q_UINT64_C(0xB49C3B3995091A36), Q_UINT64_C(0xD4490AD526F14431), Q_UINT64_C(0x12A8F216AF9418C2), Q_UINT64_C(0xDEC4A244062E1D5B), Q_UINT64_C(0x478EDC03D9887A6D), Q_UINT64_C(0xABEEDDB2DDE06FF1), Q_UINT64_C(0x58EFC10B06A2068D), Q_UINT64_C(0xC6E57A78FBD986E0), Q_UINT64_C(0x2EAB8CA63CE802D7), Q_UINT64_C(0x14A195640116F336), Q_UINT64_C(0x7C0828DD624EC390), Q_UINT64_C(0xD74BBE77E6116AC7), Q_UINT64_C(0x804456AF10F5FB53), Q_UINT64_C(0x5B7729619ED8F9A7), Q_UINT64_C(0xD142DE229B57D1A9), Q_UINT64_C(0x2472F6207C2D0484), Q_UINT64_C(0xC2A1E7B5B459AEB5), Q_UINT64_C(0xAB4F6451CC1D45EC), Q_UINT64_C(0x63767572AE3D6174), Q_UINT64_C(0xA59E0BD101731A28), Q_UINT64_C(0x116D0016CB948F09), Q_UINT64_C(0x2CF9C8CA052F6E9F), Q_UINT64_C(0xB090A7560A968E3), Q_UINT64_C(0x56851C604AEB8775), Q_UINT64_C(0xDF89B35FADE795AC), Q_UINT64_C(0xEB3593803173E0CE), Q_UINT64_C(0x9C4CD6257C5A3603), Q_UINT64_C(0xAF0C317D32ADAA8A), Q_UINT64_C(0x258E5A80C7204C4B), Q_UINT64_C(0x8B889D624D44885D), Q_UINT64_C(0xF4D14597E660F855), Q_UINT64_C(0xD4347F66EC8941C3), Q_UINT64_C(0xE699ED85B0DFB40D), Q_UINT64_C(0xF7D517A5F7CBF696), Q_UINT64_C(0xE102AD12F54FAD76), Q_UINT64_C(0x1FE2CCA76517DB90), Q_UINT64_C(0xD7504DFA8816EDBB), Q_UINT64_C(0xB9571FA04DC089C8), Q_UINT64_C(0x1DDC0325259B27DE), Q_UINT64_C(0xCF3F4688801EB9AA), Q_UINT64_C(0xF4F5D05C10CAB243), Q_UINT64_C(0x38B6525C21A42B0E), Q_UINT64_C(0x36F60E2BA4FA6800), Q_UINT64_C(0xE31A5399C74DD277), Q_UINT64_C(0x5EBC9CDB03510A45), Q_UINT64_C(0x66C1A2A1A60CD889), Q_UINT64_C(0x9E17E49642A3E4C1), Q_UINT64_C(0xEDB454E7BADC0805), Q_UINT64_C(0x50B704CAB602C329), Q_UINT64_C(0x4CC317FB9CDDD023), Q_UINT64_C(0x66B4835D9EAFEA22), Q_UINT64_C(0x219B97E26FFC81BD), Q_UINT64_C(0x261E4E4C0A333A9D), Q_UINT64_C(0x43A8D61177324CD), Q_UINT64_C(0x6027FEADFD96EFA7), Q_UINT64_C(0x4ED0FE7E9DC91335), Q_UINT64_C(0xE4DBF0634473F5D2), Q_UINT64_C(0x1761F93A44D5AEFE), Q_UINT64_C(0x53898E4C3910DA55), Q_UINT64_C(0x734DE8181F6EC39A), Q_UINT64_C(0x2680B122BAA28D97), Q_UINT64_C(0x298AF231C85BAFAB), Q_UINT64_C(0x7983EED3740847D5), Q_UINT64_C(0x4B056DF8B0E913AD), Q_UINT64_C(0x927490C42469E7AD), Q_UINT64_C(0xA09E8C8C35AB96DE), Q_UINT64_C(0xFA7E393983325753), Q_UINT64_C(0xD6B6D0ECC617C699), Q_UINT64_C(0xDFEA21EA9E7557E3), Q_UINT64_C(0xB67C1FA481680AF8), Q_UINT64_C(0xCA1E3785A9E724E5), Q_UINT64_C(0x1CFC8BED0D681639), Q_UINT64_C(0xD18D8549D140CAEA), Q_UINT64_C(0x8831C46CD07C4C07), Q_UINT64_C(0x81E8FB81F242DD58), Q_UINT64_C(0xC27C2D12D7A2DB7E), Q_UINT64_C(0xF3A4D55F9DCE9B9A), Q_UINT64_C(0x445F4361A64917E0), Q_UINT64_C(0x7405D8483E0D7EFB), Q_UINT64_C(0x90BBDD9BF117116), Q_UINT64_C(0x1BD258C174253890), Q_UINT64_C(0xCFEB9676BC40468A), Q_UINT64_C(0x5287319C1C0D2D23), Q_UINT64_C(0xCE71D8BF1AB5E93D), Q_UINT64_C(0x57942ABB8BB173C8), Q_UINT64_C(0x3727A8A8700362DB), Q_UINT64_C(0x5FB3BA14587A35E1), Q_UINT64_C(0xFC9E7446427C7655), Q_UINT64_C(0xA4476AF0A4012A86), Q_UINT64_C(0xF9B85B290E8D9DC4), Q_UINT64_C(0xC070E9A44E258395), Q_UINT64_C(0x81418D459CC3EB26), Q_UINT64_C(0x691CE947F1F61284), Q_UINT64_C(0xF76AF56B007E777A), Q_UINT64_C(0xCFEAA9840C0ECD7F), Q_UINT64_C(0x61313703B982EC38), Q_UINT64_C(0x304306693E2C9379), Q_UINT64_C(0x4AA580CF2157F3DC), Q_UINT64_C(0x74D9AB10C6DB5526), Q_UINT64_C(0x2C2BADD9C0D4E255), Q_UINT64_C(0x1AF23D95844A7B4), Q_UINT64_C(0xDAEFF47F173D3EB5), Q_UINT64_C(0x48CF32761DFE0B66), Q_UINT64_C(0x868B17FE1893C3B7), Q_UINT64_C(0x2B89B3FEB722F15A), Q_UINT64_C(0x287BD163A7C660B7), Q_UINT64_C(0x9E5ACC12E101CAFC), Q_UINT64_C(0x643C9189D256EB68), Q_UINT64_C(0x5DCBAC3BB766C32B), Q_UINT64_C(0x1E68FB08CED5E58E), Q_UINT64_C(0xC9B45FA29D9E89CC), Q_UINT64_C(0xFEA4F373B72D45ED), Q_UINT64_C(0xF44A11EA3677A393), Q_UINT64_C(0xCC9AFD4BC48D4EE2), Q_UINT64_C(0x3C0E4393E4220F54), Q_UINT64_C(0xCD04F3FF001A4778), Q_UINT64_C(0xE3273522064480CA), Q_UINT64_C(0x9F91508BFFCFC14A), Q_UINT64_C(0x49A7F41061A9E60), Q_UINT64_C(0xFCB6BE43A9F2FE9B), Q_UINT64_C(0x8DE8A1C7797DA9B), Q_UINT64_C(0x8F9887E6078735A1), Q_UINT64_C(0xB5B4071DBFC73A66), Q_UINT64_C(0xA68AF6A1F4CF2B16), Q_UINT64_C(0x44119897998B4BE3), Q_UINT64_C(0x1F2B1D1F15F6DC9C), Q_UINT64_C(0xB69E38A8965C6B65), Q_UINT64_C(0xAA9119FF184CCCF4), Q_UINT64_C(0xF43C732873F24C13), Q_UINT64_C(0xFB4A3D794A9A80D2), Q_UINT64_C(0x3550C2321FD6109C), Q_UINT64_C(0x371F77E76BB8417E), Q_UINT64_C(0x6BFA9AAE5EC05779), Q_UINT64_C(0x80B46921877E7D9D), Q_UINT64_C(0xC70A712087829541), Q_UINT64_C(0x9C1169FA2777B874), Q_UINT64_C(0x78EDEFD694AF1EED), Q_UINT64_C(0x6DC93D9526A50E68), Q_UINT64_C(0xEE97F453F06791ED), Q_UINT64_C(0x32AB0EDB696703D3), Q_UINT64_C(0x3A6853C7E70757A7), Q_UINT64_C(0x31865CED6120F37D), Q_UINT64_C(0x67FEF95D92607890), Q_UINT64_C(0x6886EBFE977FF290), Q_UINT64_C(0x279E159591F0AA4), Q_UINT64_C(0x5092EF950A16DA0B), Q_UINT64_C(0x9338E69C052B8E7B), Q_UINT64_C(0x455A4B4CFE30E3F5), Q_UINT64_C(0x6B02E63195AD0CF8), Q_UINT64_C(0x6B17B224BAD6BF27), Q_UINT64_C(0xD1E0CCD25BB9C169), Q_UINT64_C(0xDE0C89A556B9AE70), Q_UINT64_C(0x50065E535A213CF6), Q_UINT64_C(0x303654A628BC4558), Q_UINT64_C(0x60536FAB6DD8FC7), Q_UINT64_C(0x22AF003AB672E811), Q_UINT64_C(0x52E762596BF68235), Q_UINT64_C(0x9AEBA33AC6ECC6B0), Q_UINT64_C(0x944F6DE09134DFB6), Q_UINT64_C(0x6C47BEC883A7DE39), Q_UINT64_C(0x6AD047C430A12104), Q_UINT64_C(0xA5B1CFDBA0AB4067), Q_UINT64_C(0x7C45D833AFF07862), Q_UINT64_C(0x77B47209CA3D1200), Q_UINT64_C(0xF374D0C88BF49710), Q_UINT64_C(0xC0C0F5A60EF4CDCF), Q_UINT64_C(0xCAF21ECD4377B28C), Q_UINT64_C(0x57277707199B8175), Q_UINT64_C(0x506C11B9D90E8B1D), Q_UINT64_C(0xD83CC2687A19255F), Q_UINT64_C(0x4A29C6465A314CD1), Q_UINT64_C(0xED2DF21216235097), Q_UINT64_C(0xB5635C95FF7296E2), Q_UINT64_C(0x6B8E3C0EAFC3AB32), Q_UINT64_C(0x3B31538038B70006), Q_UINT64_C(0xB0774D261CC609DB), Q_UINT64_C(0x443F64EC5A371195), Q_UINT64_C(0x4112CF68649A260E), Q_UINT64_C(0xD813F2FAB7F5C5CA), Q_UINT64_C(0x660D3257380841EE), Q_UINT64_C(0x59AC2C7873F910A3), Q_UINT64_C(0xE846963877671A17), Q_UINT64_C(0x93B633ABFA3469F8), Q_UINT64_C(0xDFA2F970B7554580), Q_UINT64_C(0x2810272A0A494442), Q_UINT64_C(0x6FFE73E81B637FB3), Q_UINT64_C(0xDDF957BC36D8B9CA), Q_UINT64_C(0x64D0E29EEA8838B3), Q_UINT64_C(0x8DD9BDFD96B9F63), Q_UINT64_C(0x87E79E5A57D1D13), Q_UINT64_C(0xE328E230E3E2B3FB), Q_UINT64_C(0x1C2559E30F0946BE), Q_UINT64_C(0x720BF5F26F4D2EAA), Q_UINT64_C(0x977DBD4995C0F49D), Q_UINT64_C(0xD60D58C26193C3C8), Q_UINT64_C(0xEC4A3BDFBB7E2C64), Q_UINT64_C(0x6962A54B9C36D0C9), Q_UINT64_C(0xF3EAB5E373BE9F6F), Q_UINT64_C(0x80A839811F81C77F), Q_UINT64_C(0xD0F186DF3AA2FA5D), Q_UINT64_C(0x398F9C5E392614CB), Q_UINT64_C(0x3A7B0200AF8B9549), Q_UINT64_C(0x4228B4C2D0BA809B), Q_UINT64_C(0x969F078D084BDF7F), Q_UINT64_C(0x5CC2DE17EC8795F3), Q_UINT64_C(0xF6EDF7ED3A63CBD8), Q_UINT64_C(0x7636B03C6F138C80), Q_UINT64_C(0xD69E826E8D6625D2), Q_UINT64_C(0xEA13A4A7503CFD81), Q_UINT64_C(0x1072E1F3D1DD7006), Q_UINT64_C(0x82AF6553BE1D8A3D), Q_UINT64_C(0x9F78E4296075737F), Q_UINT64_C(0x77DBC735A5D3BB73), Q_UINT64_C(0x24974B668E353CDC), Q_UINT64_C(0x1CD34226DC04B76D), Q_UINT64_C(0xAED23F34EFAF4BF7), Q_UINT64_C(0xB49738B8349614C8), Q_UINT64_C(0xA18F95B9EBE202B2), Q_UINT64_C(0x9C44E522CB2631B6), Q_UINT64_C(0x115F24C4DEA8E6A4), Q_UINT64_C(0x6BF1F99FDEE4334C), Q_UINT64_C(0xF60CCCB5B4EDDC4A), Q_UINT64_C(0xF8F920AB0E85CB7C), Q_UINT64_C(0xD2692E8FB4BDFB9E), Q_UINT64_C(0xECEEAFCC1FE49C7B), Q_UINT64_C(0x13791B1B5F18188), Q_UINT64_C(0x94CBADD1BDB8B58D), Q_UINT64_C(0xD9E8323A41FABA1B), Q_UINT64_C(0xF29ADDC93DB99E06), Q_UINT64_C(0x334CF776D70C454), Q_UINT64_C(0xA3A5054D333C7975), Q_UINT64_C(0xDB6B244EE93770EA), Q_UINT64_C(0xB30BB7F9B6A27E62), Q_UINT64_C(0x1E771E283DFD3DF3), Q_UINT64_C(0xD87DF748D4A935), Q_UINT64_C(0xF1BCC3D275AFE51A), Q_UINT64_C(0xE728E8C83C334074), Q_UINT64_C(0x96FBF83A12884624), Q_UINT64_C(0x81A1549FD6573DA5), Q_UINT64_C(0x5FA7867CAF35E149), Q_UINT64_C(0x56986E2EF3ED091B), Q_UINT64_C(0x917F1DD5F8886C61), Q_UINT64_C(0xD20D8C88C8FFE65F), Q_UINT64_C(0xBE1D061C9DA215A1), Q_UINT64_C(0xE403BA1D71679770), Q_UINT64_C(0x150F361DAB9DEC26), Q_UINT64_C(0x9F6A419D382595F4), Q_UINT64_C(0x64A53DC924FE7AC9), Q_UINT64_C(0x142DE49FFF7A7C3D), Q_UINT64_C(0xC335248857FA9E7), Q_UINT64_C(0xA9C32D5EAE45305), Q_UINT64_C(0xE6C42178C4BBB92E), Q_UINT64_C(0x71F1CE2490D20B07), Q_UINT64_C(0x28F84B43FD399EEB), Q_UINT64_C(0x493EA8F9753981DE), Q_UINT64_C(0x65FA4F227A2B6D79), Q_UINT64_C(0xD5F9E858292504D5), Q_UINT64_C(0xC2B5A03F71471A6F), Q_UINT64_C(0x59300222B4561E00), Q_UINT64_C(0xCE2F8642CA0712DC), Q_UINT64_C(0x7CA9723FBB2E8988), Q_UINT64_C(0x2785338347F2BA08), Q_UINT64_C(0xC61BB3A141E50E8C), Q_UINT64_C(0x2BCCBF617E17F7FA), Q_UINT64_C(0x92CEA15FEA1570), Q_UINT64_C(0x5E5637885F29BC2B), Q_UINT64_C(0x7EBA726D8C94094B), Q_UINT64_C(0xA56A5F0BFE39272), Q_UINT64_C(0xD79476A84EE20D06), Q_UINT64_C(0x9E4C1269BAA4BF37), Q_UINT64_C(0x17EFEE45B0DEE640), Q_UINT64_C(0x1D95B0A5FCF90BC6), Q_UINT64_C(0x93CBE0B699C2585D), Q_UINT64_C(0x246DFE9363A682E6), Q_UINT64_C(0x7EE353FCF5CD5DC2), Q_UINT64_C(0x7DC7785B8EFDFC80), Q_UINT64_C(0x8AF38731C02BA980), Q_UINT64_C(0x1FAB64EA29A2DDF7), Q_UINT64_C(0xE4D9429322CD065A), Q_UINT64_C(0x9DA058C67844F20C), Q_UINT64_C(0x24C0E332B70019B0), Q_UINT64_C(0x233003B5A6CFE6AD), Q_UINT64_C(0xD586BD01C5C217F6), Q_UINT64_C(0x16ED69B640345D52), Q_UINT64_C(0xD4B1D8F1C1379A10), Q_UINT64_C(0xF05D129681949A4C), Q_UINT64_C(0x964781CE734B3C84), Q_UINT64_C(0x9C2ED44081CE5FBD), Q_UINT64_C(0x522E23F3925E319E), Q_UINT64_C(0x177E00F9FC32F791), Q_UINT64_C(0x2BC60A63A6F3B3F2), Q_UINT64_C(0x222BBFAE61725606), Q_UINT64_C(0x486289DDCC3D6780), Q_UINT64_C(0xD8E615B98B2EDD71), Q_UINT64_C(0xDC0BD71B2BBBD2F8), Q_UINT64_C(0xF8549E1A3AA5E00D), Q_UINT64_C(0x7A69AFDCC42261A), Q_UINT64_C(0xC4C118BFE78FEAAE), Q_UINT64_C(0xF9F4892ED96BD438), Q_UINT64_C(0x1AF3DBE25D8F45DA), Q_UINT64_C(0xF5B4B0B0D2DEEEB4), Q_UINT64_C(0x962ACEEFA82E1C84), Q_UINT64_C(0x46E3ECAAF453CE9), Q_UINT64_C(0xE3B2CE59F1ADC513), Q_UINT64_C(0xD228E078F32F44DB), Q_UINT64_C(0x55B6344CF97AAFAE), Q_UINT64_C(0xB862225B055B6960), Q_UINT64_C(0xCAC09AFBDDD2CDB4), Q_UINT64_C(0xDAF8E9829FE96B5F), Q_UINT64_C(0xB5FDFC5D3132C498), Q_UINT64_C(0x310CB380DB6F7503), Q_UINT64_C(0xE87FBB46217A360E), Q_UINT64_C(0x2102AE466EBB1148), Q_UINT64_C(0xDC18936DE692EDA9), Q_UINT64_C(0x5C63C9773B896313), Q_UINT64_C(0xD5764DF8E597383A), Q_UINT64_C(0x2A86143DF52ED2B7), Q_UINT64_C(0x9588E6D639FD657), Q_UINT64_C(0x22BCCA7179F6F98C), Q_UINT64_C(0x7B11F66F913FD6A1), Q_UINT64_C(0x8A238ACA5D70BC01), Q_UINT64_C(0x376F91D2FE31AB34), Q_UINT64_C(0x8AE8C32B18A764E7), Q_UINT64_C(0x4E698D55B171A819), Q_UINT64_C(0x57097D875837A86), Q_UINT64_C(0x51FA164BA15A2024), Q_UINT64_C(0x11857C8AE5ECE282), Q_UINT64_C(0xE12614F85ED4463), Q_UINT64_C(0xB16C60A6F750F06D), Q_UINT64_C(0xE22B7F4F1D37F38E), Q_UINT64_C(0xABB2A5C6CCA6BF7B), Q_UINT64_C(0x63BA1402BCD700C7), Q_UINT64_C(0xE6F4F767E2FEEACF), Q_UINT64_C(0xE44B611E749E5BB4), Q_UINT64_C(0x3104180C25A2C83D), Q_UINT64_C(0x223DDA40658FCF6F), Q_UINT64_C(0x72B0869B6B5C016A), Q_UINT64_C(0xD12C5F2B65D57A6D), Q_UINT64_C(0xD3447B7471133EEF), Q_UINT64_C(0xE67997D839E29E00), Q_UINT64_C(0x77913DC5F0FCF4A8), Q_UINT64_C(0xD1C9396DF4441C1F), Q_UINT64_C(0x70DE309862A395BF), Q_UINT64_C(0x569214F17B577E49), Q_UINT64_C(0xF13A9F525964B43D), Q_UINT64_C(0x268CC049EA9C9193), Q_UINT64_C(0x202BC1CE11299299), Q_UINT64_C(0xDDEAAF93312DE40), Q_UINT64_C(0x3F18205EFEA8D4E1), Q_UINT64_C(0x746D101338AEFECC), Q_UINT64_C(0x7C716AE1EE2FA0C0), Q_UINT64_C(0x54D16714A2E21833), Q_UINT64_C(0x4624932E00B967BB), Q_UINT64_C(0x269E8F6F613A95B), Q_UINT64_C(0x6E547C58D5B8E0B6), Q_UINT64_C(0x3F6E35A083906CE2), Q_UINT64_C(0x461C787DA6D39287), Q_UINT64_C(0x456B13B48BA14D3E), Q_UINT64_C(0x13208F2F3BBBCBCD), Q_UINT64_C(0x9FD9D09B0BCB0CC6), Q_UINT64_C(0x2EA80842562611A3), Q_UINT64_C(0x7C6A516016BBA328), Q_UINT64_C(0x7E11E8FD8971863C), Q_UINT64_C(0xF1D5D10C4371CA97), Q_UINT64_C(0xFBEE22F1C4794DB3), Q_UINT64_C(0x440FA4EE9B95CE5), Q_UINT64_C(0x249540E9C01F5590), Q_UINT64_C(0x5CAFD766426FCA9F), Q_UINT64_C(0x455D292596C1C249), Q_UINT64_C(0x61792414CC27B556), Q_UINT64_C(0xD7DFBED555838D82), Q_UINT64_C(0xAD2CEFCC8821AAE2), Q_UINT64_C(0xF986B171F10C9CD8), Q_UINT64_C(0x95FEBC8B40E5C16B), Q_UINT64_C(0x4396D320F53B48E0), Q_UINT64_C(0xFFA4915F24EBF599), Q_UINT64_C(0xBF2ACDC7614AEE18), Q_UINT64_C(0x3685E0834D27C16C), Q_UINT64_C(0xB12AF8749B280CA4), Q_UINT64_C(0xBCC928EC0B31E86D), Q_UINT64_C(0xDCA4586B13D7BF2F), Q_UINT64_C(0x1CD832A71FEBEB79), Q_UINT64_C(0xA077AD985CCDA491), Q_UINT64_C(0x1E449EFC1EA851A9), Q_UINT64_C(0xBFFEF9D3EA83FF8A), Q_UINT64_C(0xA5876E9AB5B62C2F), Q_UINT64_C(0x6AE97C384B49BBF5), Q_UINT64_C(0xABD49C6450CF44BA), Q_UINT64_C(0x6CE61B36DFE3A2A9), Q_UINT64_C(0x6F383137A881C02F), Q_UINT64_C(0x6A0D690F234FEC2E), Q_UINT64_C(0x4173887850FEB813), Q_UINT64_C(0x69800934BE5F0FB4), Q_UINT64_C(0xD79A277FA5EE0B7D), Q_UINT64_C(0x722F20F6C983AF1F), Q_UINT64_C(0x1A396AD150FD8628), Q_UINT64_C(0xDDA7A8C620D3F45A), Q_UINT64_C(0xC4756429C0FAAAE9), Q_UINT64_C(0xD3D6BA273CF7A9CF), Q_UINT64_C(0xD6F48274C510403B), Q_UINT64_C(0x7F88AD29B44A60AE), Q_UINT64_C(0x77DED73FCFE5ACF3), Q_UINT64_C(0xED1EEC4D07F6C5F3), Q_UINT64_C(0x731CF9A2B3E69101), Q_UINT64_C(0x95115C6B16CBFC53), Q_UINT64_C(0xC6377B48F0FF5A04), Q_UINT64_C(0xA1623EA2072BA691), Q_UINT64_C(0x2D6385D5DEFBA3EC), Q_UINT64_C(0xB53229ED8AE98A05), Q_UINT64_C(0x3CA991513A832A60), Q_UINT64_C(0x81BD2FEB07DC1B2), Q_UINT64_C(0xDB66D8B4739EAE6D), Q_UINT64_C(0x5127152585FB0236), Q_UINT64_C(0x871A8BAF905FFE5F), Q_UINT64_C(0x4B2CEC12E28EF0A8), Q_UINT64_C(0xA15BC40D676B8059), Q_UINT64_C(0x4D019C4D521F9F0D), Q_UINT64_C(0x40185CAC031D6A), Q_UINT64_C(0xA102BAA74E6EA4CC), Q_UINT64_C(0x770AD606DB9A489E), Q_UINT64_C(0xC83865D9BCBADEAB), Q_UINT64_C(0xC0ED0F7C0221EF20), Q_UINT64_C(0x61B08FE50CE9B4DD), Q_UINT64_C(0x457F98F52B5B9A8B), Q_UINT64_C(0x9F37DA3E069B4F3F), Q_UINT64_C(0x16E2563EBDEB76CD), Q_UINT64_C(0x1FC53027ABBDE320), Q_UINT64_C(0x3EBE566AA57C3504), Q_UINT64_C(0x36F117F03C169259), Q_UINT64_C(0x94863345C47C009D), Q_UINT64_C(0x1664C1F26180474E), Q_UINT64_C(0x62A0B1E25812F7A8), Q_UINT64_C(0x1472D67CB21D6933), Q_UINT64_C(0xFE66E31B6EF68DA), Q_UINT64_C(0x2DC2CD84C8BABBE4), Q_UINT64_C(0xA8807FC12376DE5E), Q_UINT64_C(0xFC5374D1BD27B04A), Q_UINT64_C(0x74926FFA7431AC44), Q_UINT64_C(0x66CC273FDA40B2C3), Q_UINT64_C(0x89213887A68993BD), Q_UINT64_C(0xEE67914331AB2BE), Q_UINT64_C(0x53444E636E28864A), Q_UINT64_C(0x30E4D661ACB60423), Q_UINT64_C(0xE6A7849FE7DEB15F), Q_UINT64_C(0x8C54305DE4553F33), Q_UINT64_C(0xF003268AEBFDBEFE), Q_UINT64_C(0x31D97BA51F94D328), Q_UINT64_C(0x490A4FD8CC7ACCB1), Q_UINT64_C(0xE1FB595A41EF4665), Q_UINT64_C(0xE71A7B8A8B239989), Q_UINT64_C(0xCE013FB905AEE038), Q_UINT64_C(0x6DB3584E1C34FF53), Q_UINT64_C(0x3EA458773E1D6AB5), Q_UINT64_C(0x912516C640F34164), Q_UINT64_C(0x883BC1186DB1424B), Q_UINT64_C(0x2EC36EB66A4AEED8), Q_UINT64_C(0x797ACDDCFEB64EE4), Q_UINT64_C(0x7F76BB7EAA449E30), Q_UINT64_C(0xF8FF8A4CA2B27482), Q_UINT64_C(0x394892E1F2B1BB90), Q_UINT64_C(0x4BAF246B8D469EB8), Q_UINT64_C(0xF59AB89D33102DE6), Q_UINT64_C(0x24EBEF21DD8CD878), Q_UINT64_C(0x6D80A3EA724BFDC3), Q_UINT64_C(0x4ED3EFA64DAB1F9A), Q_UINT64_C(0x5187E679610F0CC6), Q_UINT64_C(0x98C9BD638D376C00), Q_UINT64_C(0x931BC3482E871415), Q_UINT64_C(0xC0A525FD102934D0), Q_UINT64_C(0x9DAF8EE2F4F9CA8), Q_UINT64_C(0xF37148CF3794439B), Q_UINT64_C(0xAC9938057E5661D), Q_UINT64_C(0x8C9EB0E2433437D4), Q_UINT64_C(0xCC72E82728195BFB), Q_UINT64_C(0x5EAA084386052B27), Q_UINT64_C(0x42E240CB63689F2F), Q_UINT64_C(0x6D2BDCDAE2919661), Q_UINT64_C(0x42880B0236E4D951), Q_UINT64_C(0x5F0F4A5898171BB6), Q_UINT64_C(0x39F890F579F92F88), Q_UINT64_C(0x93C5B5F47356388B), Q_UINT64_C(0x63DC359D8D231B78), Q_UINT64_C(0xEC16CA8AEA98AD76), Q_UINT64_C(0x47EE51E01786C0D), Q_UINT64_C(0x5D57FDC24613C035), Q_UINT64_C(0x3253A729B9BA3DDE), Q_UINT64_C(0x8C74C368081B3075), Q_UINT64_C(0xB9BC6C87167C33E7), Q_UINT64_C(0x7EF48F2B83024E20), Q_UINT64_C(0x11D505D4C351BD7F), Q_UINT64_C(0x6568FCA92C76A243), Q_UINT64_C(0x4DE0B0F40F32A7B8), Q_UINT64_C(0x96D693460CC37E5D), Q_UINT64_C(0xF9A2A8FC7456DEEB), Q_UINT64_C(0xDC1B40BB4D4DF1B0), Q_UINT64_C(0x18727070F1BD400B), Q_UINT64_C(0x1FCBACD259BF02E7), Q_UINT64_C(0xD310A7C2CE9B6555), Q_UINT64_C(0xBF983FE0FE5D8244), Q_UINT64_C(0x9F74D14F7454A824), Q_UINT64_C(0x51EBDC4AB9BA3035), Q_UINT64_C(0x5C82C505DB9AB0FA), Q_UINT64_C(0xFCF7FE8A3430B241), Q_UINT64_C(0x167EFF15A9E9AF74), Q_UINT64_C(0x5E66B27B148F119D), Q_UINT64_C(0x4C9F34427501B447), Q_UINT64_C(0x14A68FD73C910841), Q_UINT64_C(0xA71B9B83461CBD93), Q_UINT64_C(0x3488B95B0F1850F), Q_UINT64_C(0x637B2B34FF93C040), Q_UINT64_C(0x9D1BC9A3DD90A94), Q_UINT64_C(0x3575668334A1DD3B), Q_UINT64_C(0x735E2B97A4C45A23), Q_UINT64_C(0x194F508B7E617E1C), Q_UINT64_C(0x44D577CE26E12E5D), Q_UINT64_C(0xAA649C6EBCFD50FC), Q_UINT64_C(0x8DBD98A352AFD40B), Q_UINT64_C(0x87D2074B81D79217), Q_UINT64_C(0x19F3C751D3E92AE1), Q_UINT64_C(0xB4AB30F062B19ABF), Q_UINT64_C(0x7B0500AC42047AC4), Q_UINT64_C(0xC9452CA81A09D85D), Q_UINT64_C(0x24AA6C514DA27500), Q_UINT64_C(0xA28FAED3689F95BB), Q_UINT64_C(0xC83350115F9A613F), Q_UINT64_C(0x5D1A1AE85B49AA1), Q_UINT64_C(0x679F848F6E8FC971), Q_UINT64_C(0x7449BBFF801FED0B), Q_UINT64_C(0x7D11CDB1C3B7ADF0), Q_UINT64_C(0x82C7709E781EB7CC), Q_UINT64_C(0xF3218F1C9510786C), Q_UINT64_C(0x331478F3AF51BBE6), Q_UINT64_C(0x4BB38DE5E7219443), Q_UINT64_C(0xE1A1184053CD2CF3), Q_UINT64_C(0xED01A22A64258031), Q_UINT64_C(0xD7E765D58755C10), Q_UINT64_C(0x1A083822CEAFE02D), Q_UINT64_C(0x9605D5F0E25EC3B0), Q_UINT64_C(0xD021FF5CD13A2ED5), Q_UINT64_C(0x40BDF15D4A672E32), Q_UINT64_C(0x11355146FD56395), Q_UINT64_C(0x5DB4832046F3D9E5), Q_UINT64_C(0x239F8B2D7FF719CC), Q_UINT64_C(0xBEDB87820B300578), Q_UINT64_C(0xD48E0D91309D5495), Q_UINT64_C(0x9D39247E33776D41), Q_UINT64_C(0x2AF7398005AAA5C7), Q_UINT64_C(0x44DB015024623547), Q_UINT64_C(0x9C15F73E62A76AE2), Q_UINT64_C(0x75834465489C0C89), Q_UINT64_C(0x3290AC3A203001BF), Q_UINT64_C(0xFBBAD1F61042279), Q_UINT64_C(0xE83A908FF2FB60CA), Q_UINT64_C(0xD9AEA92E9B82F7D7), Q_UINT64_C(0x125DFFB1B0033D85), Q_UINT64_C(0xDF3C5A6BDE6ED558), Q_UINT64_C(0xD15B7567CC8C9994), Q_UINT64_C(0x33820EFB5D00EA05), Q_UINT64_C(0x7A7CB7F62DADEA6), Q_UINT64_C(0xD786A7818C7A441B), Q_UINT64_C(0x49083EAF1220799E), Q_UINT64_C(0xE806DB566CE19D0C), Q_UINT64_C(0xB1E64841769BA28B), Q_UINT64_C(0xF0EA3BE7461E1868), Q_UINT64_C(0xEDE2D8ABCF3BC02C), Q_UINT64_C(0xE4215E28EA15F7D8), Q_UINT64_C(0xE5CC6571AAB4EAA4), Q_UINT64_C(0xCF1C488E9C820D52), Q_UINT64_C(0xE901A40CE658D4ED), Q_UINT64_C(0x3088075A531C35CC), Q_UINT64_C(0x2E405CD11AAF14D5), Q_UINT64_C(0x8F44BD3F98D45E85), Q_UINT64_C(0x44590BA83F5B62C7), Q_UINT64_C(0x1BB0C75386F4E2FA), Q_UINT64_C(0x2061E167F40C03A6), Q_UINT64_C(0x7FDDFB73A3FC2855), Q_UINT64_C(0x47EE611ABBCB0D66), Q_UINT64_C(0x823DC7CF1D36FA8E), Q_UINT64_C(0x5F47FFACA586F256), Q_UINT64_C(0xEFC20227120A4242), Q_UINT64_C(0x62DD10895A0616AA), Q_UINT64_C(0xE0C5E3A99DEF2D5F), Q_UINT64_C(0xA3A1CE99B7C09FED), Q_UINT64_C(0xC59E3E840A464485), Q_UINT64_C(0x49BE6C9ACE6FE276), Q_UINT64_C(0xCD3029D2069CB5C0), Q_UINT64_C(0xB901970A56321509), Q_UINT64_C(0x870CBE02E1262067), Q_UINT64_C(0x1293EA5D0A1FAB4F), Q_UINT64_C(0xD75CBD2A79109164), Q_UINT64_C(0x6761A49C0AB093FB), Q_UINT64_C(0xC5A31678A39AD9A2), Q_UINT64_C(0x5EBCE9C5A6308D03), Q_UINT64_C(0x7E9B255587E5C249), Q_UINT64_C(0xFE04C9D3D87162BD), Q_UINT64_C(0xA4FC4BD4FC5558CA), Q_UINT64_C(0xE755178D58FC4E76), Q_UINT64_C(0x69B97DB1A4C03DFE), Q_UINT64_C(0xF9B5B7C4ACC67C96), Q_UINT64_C(0xFC6A82D64B8655FB), Q_UINT64_C(0x9C684CB6C4D24417), Q_UINT64_C(0x8EC97D2917456ED0), Q_UINT64_C(0x6703DF9D2924E97E), Q_UINT64_C(0x1A98A523CB8B869), Q_UINT64_C(0xB384E1E1F56B8966), Q_UINT64_C(0xD7288E012AEB8D31), Q_UINT64_C(0xDE336A2A4BC1C44B), Q_UINT64_C(0xBF692B38D079F23), Q_UINT64_C(0x2C604A7A177326B3), Q_UINT64_C(0x4850E73E03EB6064), Q_UINT64_C(0xCFC447F1E53C8E1B), Q_UINT64_C(0xB05CA3F564268D99), Q_UINT64_C(0x9AE182C8BC9474E8), Q_UINT64_C(0x62174C4EC793FAA), Q_UINT64_C(0x19E964407E09C6AD), Q_UINT64_C(0x51039AB7712457C3), Q_UINT64_C(0xC07A3F80C31FB4B4), Q_UINT64_C(0xB46EE9C5E64A6E7C), Q_UINT64_C(0xB3819A42ABE61C87), Q_UINT64_C(0x21A007933A522A20), Q_UINT64_C(0x2DF16F761598AA4F), Q_UINT64_C(0x763C4A1371B368FD), Q_UINT64_C(0xF793C46702E086A0), Q_UINT64_C(0x97B330C4F8EB88DC), Q_UINT64_C(0xDA084354F03CFD28), Q_UINT64_C(0x19AFE59AE451497F), Q_UINT64_C(0x52593803DFF1E840), Q_UINT64_C(0xF4F076E65F2CE6F0), Q_UINT64_C(0x11379625747D5AF3), Q_UINT64_C(0xBCE5D2248682C115), Q_UINT64_C(0x9DA4243DE836994F), Q_UINT64_C(0x66F70B33FE09017), Q_UINT64_C(0x4DC4DE189B671A1C), Q_UINT64_C(0xFF4D19A4372964D2), Q_UINT64_C(0x79A594F48D9FC14B), Q_UINT64_C(0xC5CC1D89724FA456), Q_UINT64_C(0x5648F680F11A2741), Q_UINT64_C(0x2D255069F0B7DAB3), Q_UINT64_C(0x9BC5A38EF729ABD4), Q_UINT64_C(0xEF2F054308F6A2BC), Q_UINT64_C(0xAF2042F5CC5C2858), Q_UINT64_C(0x480412BAB7F5BE2A), Q_UINT64_C(0xAEF3AF4A563DFE43), Q_UINT64_C(0xEF38249EAB24559B), Q_UINT64_C(0xC02CE5D9EDB6DCCB), Q_UINT64_C(0xA87832D392EFEE56), Q_UINT64_C(0x65942C7B3C7E11AE), Q_UINT64_C(0xDED2D633CAD004F6), Q_UINT64_C(0x21F08570F420E565), Q_UINT64_C(0xB415938D7DA94E3C), Q_UINT64_C(0x91B859E59ECB6350), Q_UINT64_C(0x10CFF333E0ED804A), Q_UINT64_C(0x28AED140BE0BB7DD), Q_UINT64_C(0x6B7A4C702BFE9530), Q_UINT64_C(0x4AF027D39D96C6F6), Q_UINT64_C(0x7EED120D54CF2DD9), Q_UINT64_C(0x22FE545401165F1C), Q_UINT64_C(0xC91800E98FB99929), Q_UINT64_C(0x808BD68E6AC10365), Q_UINT64_C(0xDEC468145B7605F6), Q_UINT64_C(0x1BEDE3A3AEF53302), Q_UINT64_C(0x43539603D6C55602), Q_UINT64_C(0xAA969B5C691CCB7A), Q_UINT64_C(0x53B53CFF084DBBE4), Q_UINT64_C(0x82C93DA09A63AB88), Q_UINT64_C(0x56436C9FE1A1AA8D), Q_UINT64_C(0xEFAC4B70633B8F81), Q_UINT64_C(0xBB215798D45DF7AF), Q_UINT64_C(0x45F20042F24F1768), Q_UINT64_C(0x930F80F4E8EB7462), Q_UINT64_C(0xFF6712FFCFD75EA1), Q_UINT64_C(0xAE623FD67468AA70), Q_UINT64_C(0xDD2C5BC84BC8D8FC), Q_UINT64_C(0x646EBA6B1B2D82AA), Q_UINT64_C(0x45203C04D96D1BDD), Q_UINT64_C(0x5BBCEDD5AAC241FB), Q_UINT64_C(0x5B850BEAADBA9EB7), Q_UINT64_C(0xC1356E175D3212B7), Q_UINT64_C(0xFF9C94156B411A98), Q_UINT64_C(0x4A4B589F7BC066B3), Q_UINT64_C(0xDAD93ADD928E32F1), Q_UINT64_C(0xEE4FAABB1D0F60D9), Q_UINT64_C(0x56E890FF282F1FCE), Q_UINT64_C(0xC426885553EF5F1B), Q_UINT64_C(0x2886FED586BAC9), Q_UINT64_C(0x8D198B212B022695), Q_UINT64_C(0x229E0F877BC12463), Q_UINT64_C(0x9E1315CDAB71CC75), Q_UINT64_C(0x4D738571F14B9BE1), Q_UINT64_C(0x2E0D09DF94495B8), Q_UINT64_C(0xAF7DE544C1E3FD12), Q_UINT64_C(0xCF9B6F23E1F126FD), Q_UINT64_C(0xF79887BE147870BB), Q_UINT64_C(0x4E52E5020AF9E6E5), Q_UINT64_C(0x9562304EAAF4C163), Q_UINT64_C(0xA0F58406D9A0A5E3), Q_UINT64_C(0x4E5E360C619F3A8A), Q_UINT64_C(0xA79B26CD1DB6D85B), Q_UINT64_C(0x8B0DD22C68DB4EF0), Q_UINT64_C(0x2DBAF19CF7BA1BC7), Q_UINT64_C(0x273947E45D23A245), Q_UINT64_C(0xBD7A5F0B09EE48E9), Q_UINT64_C(0x93E6F3940A085045), Q_UINT64_C(0xF841AE335FE2081F), Q_UINT64_C(0x21ADE9C05AA9D300), Q_UINT64_C(0x972AE72F0D39527A), Q_UINT64_C(0xEACBF6D9F834D914), Q_UINT64_C(0xF68F42E66EC592A4), Q_UINT64_C(0x3C05F9A14AEE9F0C), Q_UINT64_C(0x243A624AC1535ECC), Q_UINT64_C(0xBE28A542D88CAF6D), Q_UINT64_C(0x80FDF15D1EF183AD), Q_UINT64_C(0xDFA6F540973D637A), Q_UINT64_C(0x9A535D0DDFA4AE2B), Q_UINT64_C(0xBBB9BEF7209E47AC), Q_UINT64_C(0xDC842B7E2819E230), Q_UINT64_C(0xBA89142E007503B8), Q_UINT64_C(0xA3BC941D0A5061CB), Q_UINT64_C(0xE9F6760E32CD8021), Q_UINT64_C(0x9C7E552BC76492F), Q_UINT64_C(0x852F54934DA55CC9), Q_UINT64_C(0x8107FCCF064FCF56), Q_UINT64_C(0x98954D51FFF6580), Q_UINT64_C(0xA66E66E972A18FA1), Q_UINT64_C(0xE52BA6C9A2794F9), Q_UINT64_C(0xE9F6082B05542E4E), Q_UINT64_C(0xEBFAFA33D7254B59), Q_UINT64_C(0x9255ABB50D532280), Q_UINT64_C(0xB9AB4CE57F2D34F3), Q_UINT64_C(0x693501D628297551), Q_UINT64_C(0xC62C58F97DD949BF), Q_UINT64_C(0xCD454F8F19C5126A), Q_UINT64_C(0xBBE83F4ECC2BDECB), Q_UINT64_C(0xCCD44DAD39A17F3D), Q_UINT64_C(0x3482B6C0DB88A8D9), Q_UINT64_C(0x947AE053EE56E63C), Q_UINT64_C(0xC8C93882F9475F5F), Q_UINT64_C(0x3A9BF55BA91F81CA), Q_UINT64_C(0xD9A11FBB3D9808E4), Q_UINT64_C(0xFD22063EDC29FCA), Q_UINT64_C(0xB3F256D8ACA0B0B9), Q_UINT64_C(0xB03031A8B4516E84), Q_UINT64_C(0x35DD37D5871448AF), Q_UINT64_C(0xFD3024EEE99BE715), Q_UINT64_C(0x3B58F552A438759E), Q_UINT64_C(0x6F423357E7C6A9F9), Q_UINT64_C(0x325928EE6E6F8794), Q_UINT64_C(0xD0E4366228B03343), Q_UINT64_C(0x565C31F7DE89EA27), Q_UINT64_C(0x30F5611484119414), Q_UINT64_C(0xD873DB391292ED4F), Q_UINT64_C(0x7BD94E1D8E17DEBC), Q_UINT64_C(0xC7D9F16864A76E94), Q_UINT64_C(0x3B3ED3FB66C884A9), Q_UINT64_C(0x83DF7693DB92E039), Q_UINT64_C(0x65D34954DAF3CEBD), Q_UINT64_C(0xB4B81B3FA97511E2), Q_UINT64_C(0xB422061193D6F6A7), Q_UINT64_C(0x71582401C38434D), Q_UINT64_C(0x7A13F18BBEDC4FF5), Q_UINT64_C(0xBC4097B116C524D2), Q_UINT64_C(0x59B97885E2F2EA28), Q_UINT64_C(0x99170A5DC3115544), Q_UINT64_C(0x8F83912E50A95CBB), Q_UINT64_C(0xDFABE7ED507D031E), Q_UINT64_C(0xD60F6DCEDC314222), Q_UINT64_C(0x56963B0DCA418FC0), Q_UINT64_C(0x16F50EDF91E513AF), Q_UINT64_C(0xEF1955914B609F93), Q_UINT64_C(0x565601C0364E3228), Q_UINT64_C(0xECB53939887E8175), Q_UINT64_C(0xBAC7A9A18531294B), Q_UINT64_C(0xB344C470397BBA52), Q_UINT64_C(0xC80301965A4F5B96), Q_UINT64_C(0xB7E4E0745B44863F), Q_UINT64_C(0x37624AE5A48FA6E9), Q_UINT64_C(0x957BAF61700CFF4E), Q_UINT64_C(0x3A6C27934E31188A), Q_UINT64_C(0xD49503536ABCA345), Q_UINT64_C(0x88E049589C432E0), Q_UINT64_C(0xF943AEE7FEBF21B8), Q_UINT64_C(0x6C3B8E3E336139D3), Q_UINT64_C(0x364F6FFA464EE52E), Q_UINT64_C(0xEC2C2E8AB929929C), Q_UINT64_C(0x371A871F5B734AD1), Q_UINT64_C(0x7F9B6AF1EBF78BAF), Q_UINT64_C(0x58627E1A149BBA21), Q_UINT64_C(0x2CD16E2ABD791E33), Q_UINT64_C(0xD363EFF5F0977996), Q_UINT64_C(0xCE2A38C344A6EED), Q_UINT64_C(0x1A804AADB9CFA741), Q_UINT64_C(0x907F30421D78C5DE), Q_UINT64_C(0x501F65EDB3034D07), Q_UINT64_C(0x3B19671C68219AB0), Q_UINT64_C(0xB7B12313AE8FFDD), Q_UINT64_C(0x953F1EA2EEE7A6E5), Q_UINT64_C(0x514D79A727FE363D), Q_UINT64_C(0x5BDC41EDF6C001D5), Q_UINT64_C(0xDFD3204932FA11CB), Q_UINT64_C(0x9FE26CE9B88F2CC7), Q_UINT64_C(0x6B1D4662F0703356), Q_UINT64_C(0x18182A5BF908CAA5), Q_UINT64_C(0x528E946A1801E7DC), Q_UINT64_C(0xAC5E9610F1CD3A85), Q_UINT64_C(0x5265AE65582FB7), Q_UINT64_C(0x11C95AFD3033F6D7), Q_UINT64_C(0x151BA697FE01D4C2), Q_UINT64_C(0x6E9D87664063E0CA), Q_UINT64_C(0xC7A3572D50BE9190), Q_UINT64_C(0xEEF7985DC648EDB9), Q_UINT64_C(0xC89290F017E45B49), Q_UINT64_C(0x1FA85542E122FA15), Q_UINT64_C(0xE96E20BA4514B68A), Q_UINT64_C(0x609AC19AEA0C1CC7), Q_UINT64_C(0xB56447289FC5ACA), Q_UINT64_C(0xF8876B0931DA4597), Q_UINT64_C(0x74D974D8ED62AE91), Q_UINT64_C(0x587EF6A023D5EA2), Q_UINT64_C(0xAE090C3989194D0F), Q_UINT64_C(0x9C55702F2D16DF7), Q_UINT64_C(0x48E7F5B49BBAFF50), Q_UINT64_C(0x4076CBF03C303517), Q_UINT64_C(0x3EA1E1DBA973FA83), Q_UINT64_C(0xCE33B6796296D4B7), Q_UINT64_C(0x23A922886214DB6E), Q_UINT64_C(0x27BBAB250CDA4B15), Q_UINT64_C(0xDA89B2AF2534EA8F), Q_UINT64_C(0xF1EC650DFFC8FB07), Q_UINT64_C(0x57A6299ECC94971A), Q_UINT64_C(0xB1FBD4103CECE237), Q_UINT64_C(0x8E261A24D022CB39), Q_UINT64_C(0x42A51020B054A5B1), Q_UINT64_C(0x5DFB99344D1F3596), Q_UINT64_C(0xD007862D1FF5471A), Q_UINT64_C(0x3ACE9D2D8E6A8E31), Q_UINT64_C(0x26E6DB8FFDF5ADFE), Q_UINT64_C(0x469356C504EC9F9D), Q_UINT64_C(0xC8763C5B08D1908C), Q_UINT64_C(0x3F6C6AF859D80055), Q_UINT64_C(0x7F7CC39420A3A545), Q_UINT64_C(0x9BFB227EBDF4C5CE), Q_UINT64_C(0x89039D79D6FC5C5C), Q_UINT64_C(0x8FE88B57305E2AB6), Q_UINT64_C(0x1F7B9E79C0388645), Q_UINT64_C(0x2EE75B18F5F9B8B9), Q_UINT64_C(0x604D51B25FBF70E2), Q_UINT64_C(0x73AA8A564FB7AC9E), Q_UINT64_C(0x1A8C1E992B941148), Q_UINT64_C(0xAAC40A2703D9BEA0), Q_UINT64_C(0x764DBEAE7FA4F3A6), Q_UINT64_C(0x1E99B96E70A9BE8B), Q_UINT64_C(0x2C5E9DEB57EF4743), Q_UINT64_C(0x3A938FEE32D29981), Q_UINT64_C(0x5B452D1049ABEDD1), Q_UINT64_C(0x62F4F6158E96ABD0), Q_UINT64_C(0x9FC10D0F989993E0), Q_UINT64_C(0xDE68A2355B93CAE6), Q_UINT64_C(0xA44CFE79AE538BBE), Q_UINT64_C(0x9D1D84FCCE371425), Q_UINT64_C(0x51D2B1AB2DDFB636), Q_UINT64_C(0x2FD7E4B9E72CD38C), Q_UINT64_C(0x65CA5B96B7552210), Q_UINT64_C(0xDD69A0D8AB3B546D), Q_UINT64_C(0x1AA62DFD2DF51558), Q_UINT64_C(0x11C0D78503B7FA0E), Q_UINT64_C(0x13328503DF48229F), Q_UINT64_C(0xD6BF7BAEE43CAC40), Q_UINT64_C(0x4838D65F6EF6748F), Q_UINT64_C(0x1E152328F3318DEA), Q_UINT64_C(0x8F8419A348F296BF), Q_UINT64_C(0x72C8834A5957B511), Q_UINT64_C(0xD7A023A73260B45C), Q_UINT64_C(0x94EBC8ABCFB56DAE), Q_UINT64_C(0xEA2F10DB4A041E40), Q_UINT64_C(0xADA54288597DF0C6), Q_UINT64_C(0xA319CE15B0B4DB31), Q_UINT64_C(0x73973751F12DD5E), Q_UINT64_C(0x8A8E849EB32781A5), Q_UINT64_C(0xE1925C71285279F5), Q_UINT64_C(0x74C04BF1790C0EFE), Q_UINT64_C(0x4DDA48153C94938A), Q_UINT64_C(0x9D266D6A1CC0542C), Q_UINT64_C(0x7440FB816508C4FE), Q_UINT64_C(0x2973F90EB09051C3), Q_UINT64_C(0x2753D1DDD85B3F86), Q_UINT64_C(0x1B0CAB936E65C744), Q_UINT64_C(0xB559EB1D04E5E932), Q_UINT64_C(0xC37B45B3F8D6F2BA), Q_UINT64_C(0xC3A9DC228CAAC9E9), Q_UINT64_C(0xF3B8B6675A6507FF), Q_UINT64_C(0x9FC477DE4ED681DA), Q_UINT64_C(0x67378D8ECCEF96CB), Q_UINT64_C(0x6DD856D94D259236), Q_UINT64_C(0x745AB7E19564403D), Q_UINT64_C(0xBE330A7458E85219), Q_UINT64_C(0xDBC27AB5447822BF), Q_UINT64_C(0x9B3CDB65F82CA382), Q_UINT64_C(0xB67B7896167B4C84), Q_UINT64_C(0xBFCED1B0048EAC50), Q_UINT64_C(0xA9119B60369FFEBD), Q_UINT64_C(0x1FFF7AC80904BF45), Q_UINT64_C(0xAC12FB171817EEE7), Q_UINT64_C(0xAF08DA9177DDA93D), Q_UINT64_C(0x44962ED382E30FF4), Q_UINT64_C(0x576B834EEACAE651), Q_UINT64_C(0xDA3A361B1C5157B1), Q_UINT64_C(0xDCDD7D20903D0C25), Q_UINT64_C(0x36833336D068F707), Q_UINT64_C(0xCE68341F79893389), Q_UINT64_C(0xAB9090168DD05F34), Q_UINT64_C(0x43954B3252DC25E5), Q_UINT64_C(0xB438C2B67F98E5E9), Q_UINT64_C(0x10DCD78E3851A492), Q_UINT64_C(0x642A50BE22044CE6), Q_UINT64_C(0x2943BAF20B6DC0B8), Q_UINT64_C(0x3E3011E5B9AEB2DA), Q_UINT64_C(0x8CD127A98AABDE96), Q_UINT64_C(0xD7CA42C26A86AC37), Q_UINT64_C(0x99F4C3CF53ABCC2C), Q_UINT64_C(0x209EE04F0C7A8B08), Q_UINT64_C(0x76802E63D56F0A1A), Q_UINT64_C(0xF42103FD3F0CE7BC), Q_UINT64_C(0x7FE8EE0B74AAE5C0), Q_UINT64_C(0x6688932D4BA155F0), Q_UINT64_C(0x1EEFB6D229349FAE), Q_UINT64_C(0xF853D9DCD68DB21), Q_UINT64_C(0x94A7C02B5030A3C3), Q_UINT64_C(0xC5A73C4C943E60F1), Q_UINT64_C(0x363A8CCC4D94ED82), Q_UINT64_C(0x9D082375155DB103), Q_UINT64_C(0xE24B6D9BC8A2FD1A), Q_UINT64_C(0x43A6AB2AF8AE7BF9), Q_UINT64_C(0xA16B629D61616B78), Q_UINT64_C(0xF1C391B29C25861A), Q_UINT64_C(0x50DE046243C2AC45), Q_UINT64_C(0xA5F0468CF4489F83), Q_UINT64_C(0xD32C58C25B3D8E88), Q_UINT64_C(0xCD645A4EDB1A4965), Q_UINT64_C(0xEF945D47EA18443), Q_UINT64_C(0xA21311AD6759F9E8), Q_UINT64_C(0xE746A2D821C7F4A), Q_UINT64_C(0xB97720282F2C04C9), Q_UINT64_C(0xE798EFEFFEDACE99), Q_UINT64_C(0x3F8521779810EC4), Q_UINT64_C(0x8615F9721E3C59CE), Q_UINT64_C(0x150405A36992E15), Q_UINT64_C(0xC997170FAD126717), Q_UINT64_C(0xF7E48A65055C50FD), Q_UINT64_C(0xA623C7A0DA92906B), Q_UINT64_C(0x1F011D6D603132DC), Q_UINT64_C(0x880F80ED3BD2DADD), Q_UINT64_C(0xCF45B6A3E1F6FDB8), Q_UINT64_C(0x73385DDCA56282AB), Q_UINT64_C(0xF92AFC0E84C82E46), Q_UINT64_C(0x60592BFCE46D40B1), Q_UINT64_C(0xA4EC0132764CA04B), Q_UINT64_C(0x733EA705FAE4FA77), Q_UINT64_C(0xB4D8F77BC3E56167), Q_UINT64_C(0x9E21F4F903B33FD9), Q_UINT64_C(0x9D765E419FB69F6D), Q_UINT64_C(0xD30C088BA61EA5EF), Q_UINT64_C(0x5D94337FBFAF7F5B), Q_UINT64_C(0x1A4E4822EB4D7A59), Q_UINT64_C(0xEA37B2C3F3B49439), Q_UINT64_C(0xEEF8BC6E13D467E7), Q_UINT64_C(0x959F587D507A8359), Q_UINT64_C(0xB063E962E045F54D), Q_UINT64_C(0x60E8ED72C0DFF5D1), Q_UINT64_C(0x7B64978555326F9F), Q_UINT64_C(0xFD080D236DA814BA), Q_UINT64_C(0x8C90FD9B083F4558), Q_UINT64_C(0x106F72FE81E2C590), Q_UINT64_C(0x7976033A39F7D952), Q_UINT64_C(0x77E20A7B35B8AE6F), Q_UINT64_C(0x5CC3EC118AF097F), Q_UINT64_C(0xEF02CDD06FFDB432), Q_UINT64_C(0xA1082C0466DF6C0A), Q_UINT64_C(0x8215E577001332C8), Q_UINT64_C(0xD39BB9C3A48DB6CF), Q_UINT64_C(0x2738259634305C14), Q_UINT64_C(0x61CF4F94C97DF93D), Q_UINT64_C(0x1B6BACA2AE4E125B), Q_UINT64_C(0x758F450C88572E0B), Q_UINT64_C(0xAE0AFB44CAF2183F), Q_UINT64_C(0xD8E2D1645D2AFEE9), Q_UINT64_C(0xBF84470805E69B5F), Q_UINT64_C(0x94C3251F06F90CF3), Q_UINT64_C(0x3E003E616A6591E9), Q_UINT64_C(0xB925A6CD0421AFF3), Q_UINT64_C(0x61BDD1307C66E300), Q_UINT64_C(0xBF8D5108E27E0D48), Q_UINT64_C(0x240AB57A8B888B20), Q_UINT64_C(0xFC87614BAF287E07), Q_UINT64_C(0xE28ECD0A504A68AA), Q_UINT64_C(0xA91136155B95F567), Q_UINT64_C(0xA2EBEE47E2FBFCE1), Q_UINT64_C(0xD9F1F30CCD97FB09), Q_UINT64_C(0xEFED53D75FD64E6B), Q_UINT64_C(0x2E6D02C36017F67F), Q_UINT64_C(0xA9AA4D20DB084E9B), Q_UINT64_C(0xB64BE8D8B25396C1), Q_UINT64_C(0x70CB6AF7C2D5BCF0), Q_UINT64_C(0x98F076A4F7A2322E), Q_UINT64_C(0x9F62086FA605AD89), Q_UINT64_C(0xA72F1F601511F6BE), Q_UINT64_C(0x106C09B972D2E822), Q_UINT64_C(0x7FBA195410E5CA30), Q_UINT64_C(0x7884D9BC6CB569D8), Q_UINT64_C(0x647DFEDCD894A29), Q_UINT64_C(0x63573FF03E224774), Q_UINT64_C(0x4FC8E9560F91B123), Q_UINT64_C(0x1DB956E450275779), Q_UINT64_C(0xB8D91274B9E9D4FB), Q_UINT64_C(0xE7FBFFF6E7FDED91), Q_UINT64_C(0xFC017631C316778D), Q_UINT64_C(0x21E0BD5026C619BF), Q_UINT64_C(0x3B097ADAF088F94E), Q_UINT64_C(0x8D14DEDB30BE846E), Q_UINT64_C(0xF95CFFA23AF5F6F4), Q_UINT64_C(0x3871700761B3F743), Q_UINT64_C(0xCA672B91E9E4FA16), Q_UINT64_C(0x64C8E531BFF53B55), Q_UINT64_C(0x241260ED4AD1E87D), Q_UINT64_C(0x6B478F44714E779D), Q_UINT64_C(0xE39E6D7FAB950FB), Q_UINT64_C(0x1F837CC7350524), Q_UINT64_C(0x1877B51E57A764D5), Q_UINT64_C(0xA2853B80F17F58EE), Q_UINT64_C(0x993E1DE72D36D310), Q_UINT64_C(0xB3598080CE64A656), Q_UINT64_C(0x252F59CF0D9F04BB), Q_UINT64_C(0xD23C8E176D113600), Q_UINT64_C(0x1BDA0492E7E4586E), Q_UINT64_C(0x72A80E8D2B39E2A), Q_UINT64_C(0x7D4124345708ACB3), Q_UINT64_C(0xBFFF6114701B0D2F), Q_UINT64_C(0xEA5A184B9517E8CA), Q_UINT64_C(0x3CAA2A37AA023E7C), Q_UINT64_C(0xEC1E3FE968443DE8), Q_UINT64_C(0xA979B742CB112673), Q_UINT64_C(0xBF2D52D67C4C7034), Q_UINT64_C(0xA7C9A5A34B45BD5D), Q_UINT64_C(0x1ACC3F6A9FB35135), Q_UINT64_C(0x4B1E73095E666C01), Q_UINT64_C(0x85EF5974316D7FC2), Q_UINT64_C(0x8E64CAA0B0AEB08F), Q_UINT64_C(0x3F2F578E1DB59D20), Q_UINT64_C(0xE434CC0A9CD687BD), Q_UINT64_C(0x90B5104E92F152AA), Q_UINT64_C(0x352CD63217EF76B2), Q_UINT64_C(0xB8D716F0590F2695), Q_UINT64_C(0x23E92E8E391F929), Q_UINT64_C(0x67A463C0C1AF1BC7), Q_UINT64_C(0xE9ED918B80FAD591), Q_UINT64_C(0x2290F0ACE780FC05), Q_UINT64_C(0x43FDB69FBB713F6E), Q_UINT64_C(0x77CB7A49BE28E7FE), Q_UINT64_C(0x66573645F2152EB8), Q_UINT64_C(0x110AA013AB13D159), Q_UINT64_C(0x605FB6CA7B9FEDF4), Q_UINT64_C(0xC2CDE6E0B545FBE2), Q_UINT64_C(0xB4417D9E245D497A), Q_UINT64_C(0x7F57BD56E22165FF), Q_UINT64_C(0x9D47CF4DF245A5E9), Q_UINT64_C(0xE7AD2A60786964D2), Q_UINT64_C(0x62DC3A4E8E2D62E8), Q_UINT64_C(0xBC4EDC33C17B18DE), Q_UINT64_C(0x812D70FDEE39853E), Q_UINT64_C(0x1D895E2E66E2E891), Q_UINT64_C(0x7DEB25E797FD60AE), Q_UINT64_C(0x11106176813E50A6), Q_UINT64_C(0xE0F88101D39C69F7), Q_UINT64_C(0xA4E8CD515861060), Q_UINT64_C(0x174130651687D064), Q_UINT64_C(0xC8B248361A505A7), Q_UINT64_C(0xCF05DAF5AC8D77B0), Q_UINT64_C(0x49CAD48CEBF4A71E), Q_UINT64_C(0x7A4C10EC2158C4A6), Q_UINT64_C(0xD9E92AA246BF719E), Q_UINT64_C(0x13AE978D09FE5557), Q_UINT64_C(0x730499AF921549FF), Q_UINT64_C(0x4E4B705B92903BA4), Q_UINT64_C(0xFF577222C14F0A3A), Q_UINT64_C(0xD68495B907505CFE), Q_UINT64_C(0xA33DF61270B23FD1), Q_UINT64_C(0x963EF2C96B33BE31), Q_UINT64_C(0x74F85198B05A2E7D), Q_UINT64_C(0x5A0F544DD2B1FB18), Q_UINT64_C(0x3727073C2E134B1), Q_UINT64_C(0xC7F6AA2DE59AEA61), Q_UINT64_C(0x352787BAA0D7C22F), Q_UINT64_C(0x9853EAB63B5E0B35), Q_UINT64_C(0xABBDCDD7ED5C0860), Q_UINT64_C(0x58FC9FAA0DDB331F), Q_UINT64_C(0x5ED0E1C3BAC871B7), Q_UINT64_C(0xF6F7FD1431714200), Q_UINT64_C(0x30C05B1BA332F41C), Q_UINT64_C(0x8D2636B81555A786), Q_UINT64_C(0x46C9FEB55D120902), Q_UINT64_C(0xCCEC0A73B49C9921), Q_UINT64_C(0x4E9D2827355FC492), Q_UINT64_C(0x19EBB029435DCB0F), Q_UINT64_C(0x4659D2B743848A2C), Q_UINT64_C(0x87D8E041774FAC30), Q_UINT64_C(0x91E6ADF31AB02ADA), Q_UINT64_C(0x4AE7D6A36EB5DBCB), Q_UINT64_C(0x2D8D5432157064C8), Q_UINT64_C(0xD1E649DE1E7F268B), Q_UINT64_C(0x8A328A1CEDFE552C), Q_UINT64_C(0x7A3AEC79624C7DA), Q_UINT64_C(0x84547DDC3E203C94), Q_UINT64_C(0x990A98FD5071D263), Q_UINT64_C(0x1A4FF12616EEFC89), Q_UINT64_C(0xC7B699A5477014EA), Q_UINT64_C(0xF3CA1D92C54F84BF), Q_UINT64_C(0xFB152FE3FF26DA89), Q_UINT64_C(0x3E666E6F69AE2C15), Q_UINT64_C(0x3B544EBE544C19F9), Q_UINT64_C(0xE805A1E290CF2456), Q_UINT64_C(0x24B33C9D7ED25117), Q_UINT64_C(0xE74733427B72F0C1), Q_UINT64_C(0xA804D18B7097475), Q_UINT64_C(0x57E3306D881EDB4F), Q_UINT64_C(0x1060F6B4EC7B82B3), Q_UINT64_C(0x1F5A1EC6D06F5AD4), Q_UINT64_C(0x81536D601170FC20), Q_UINT64_C(0x91B534F885818A06), Q_UINT64_C(0xEC8177F83F900978), Q_UINT64_C(0x190E714FADA5156E), Q_UINT64_C(0xB592BF39B0364963), Q_UINT64_C(0x89C350C893AE7DC1), Q_UINT64_C(0xAC042E70F8B383F2), Q_UINT64_C(0xB49B52E587A1EE60), Q_UINT64_C(0xFD4F8282C3D9791F), Q_UINT64_C(0xDB26AF80925F6A9), Q_UINT64_C(0x5E90277E7CB39E2D), Q_UINT64_C(0x2C046F22062DC67D), Q_UINT64_C(0xB10BB459132D0A26), Q_UINT64_C(0x3FA9DDFB67E2F199), Q_UINT64_C(0xE09B88E1914F7AF), Q_UINT64_C(0x10E8B35AF3EEAB37), Q_UINT64_C(0x9EEDECA8E272B933), Q_UINT64_C(0xD4C718BC4AE8AE5F), Q_UINT64_C(0x1B94254B080DA283), Q_UINT64_C(0xC715AF96CE798D4B), Q_UINT64_C(0x230E343DFBA08D33), Q_UINT64_C(0x43ED7F5A0FAE657D), Q_UINT64_C(0x3A88A0FBBCB05C63), Q_UINT64_C(0x21874B8B4D2DBC4F), Q_UINT64_C(0x1BDEA12E35F6A8C9), Q_UINT64_C(0x53C065C6C8E63528), Q_UINT64_C(0xE34A1D250E7A8D6B), Q_UINT64_C(0xD6B04D3B7651DD7E), Q_UINT64_C(0x7A82860807EF61E9), Q_UINT64_C(0x469ED6ECF34076E4), Q_UINT64_C(0xAD1B35B1D597B23B), Q_UINT64_C(0x581B678AC22F5025), Q_UINT64_C(0x5F0477CA4069407D), Q_UINT64_C(0xC41B1E57FA9203C7), Q_UINT64_C(0xB7063D3DB02D4CCA), Q_UINT64_C(0x15F95E490ECAEAA4), Q_UINT64_C(0x828386C926107F14), Q_UINT64_C(0x7BA18CE74D6C263F), Q_UINT64_C(0x5CCB5EFA7BE7F541), Q_UINT64_C(0x6AB52C9EF7D54FC), Q_UINT64_C(0xC5ED1ED6CAB85516), Q_UINT64_C(0xD68719F67A9A5FE6), Q_UINT64_C(0x3DD5F0914F578827), Q_UINT64_C(0x2E5A86B440811D75), Q_UINT64_C(0xCAEF87A00C9CF9F8), Q_UINT64_C(0x2FCCCD9062D25827), Q_UINT64_C(0x74C5309606137D59), Q_UINT64_C(0x5AE494C4BDF36285), Q_UINT64_C(0x7C7FA74105624E40) }; namespace Chess { StandardBoard::StandardBoard() : WesternBoard(new WesternZobrist(s_keys)) { } Board* StandardBoard::copy() const { return new StandardBoard(*this); } QString StandardBoard::variant() const { return "standard"; } QString StandardBoard::defaultFenString() const { return "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"; } } // namespace Chess cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/standardboard.h0000664000175000017500000000270111657223322023646 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef STANDARDBOARD_H #define STANDARDBOARD_H #include "westernboard.h" namespace Chess { /*! * \brief A board for standard chess * * This is the most common chess variant, and one that is * supported by almost all chess engines. * * StandardBoard uses Polyglot-compatible zobrist position keys, * so Polyglot opening books can be used easily. * * \note Rules: http://www.fide.com/component/handbook/?id=124&view=article * \sa PolyglotBook */ class LIB_EXPORT StandardBoard : public WesternBoard { public: /*! Creates a new StandardBoard object. */ StandardBoard(); // Inherited from WesternBoard virtual Board* copy() const; virtual QString variant() const; virtual QString defaultFenString() const; }; } // namespace Chess #endif // STANDARDBOARD_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/capablancaboard.h0000664000175000017500000000330311657223322024112 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef CAPABLANCABOARD_H #define CAPABLANCABOARD_H #include "westernboard.h" namespace Chess { /*! * \brief A board for Capablanca chess * * Capablanca chess is a variant of standard chess which adds two * piece types and is played on a 10x8 board. * * \note Rules: http://en.wikipedia.org/wiki/Capablanca_chess */ class LIB_EXPORT CapablancaBoard : public WesternBoard { public: /*! Creates a new CapablancaBoard object. */ CapablancaBoard(); // Inherited from WesternBoard virtual Board* copy() const; virtual QString variant() const; virtual int width() const; virtual QString defaultFenString() const; protected: /*! Special piece types for Capablanca variants. */ enum CapablancaPieceType { Archbishop = 7, //!< Archbishop (knight + bishop) Chancellor //!< Chancellor (knight + rook) }; // Inherited from WesternBoard virtual void addPromotions(int sourceSquare, int targetSquare, QVarLengthArray& moves) const; }; } // namespace Chess #endif // CAPABLANCABOARD_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/westernzobrist.h0000664000175000017500000000334611657223322024150 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef WESTERNZOBRIST_H #define WESTERNZOBRIST_H #include "zobrist.h" #include namespace Chess { /*! \brief Zobrist keys for Western chess variants */ class LIB_EXPORT WesternZobrist : public Zobrist { public: /*! * Creates a new uninitialized WesternZobrist object. * * \param keys An array of zobrist keys that can be used * instead of the random numbers generated by the Zobrist * class. */ WesternZobrist(const quint64* keys = 0); // Inherited from Zobrist virtual void initialize(int squareCount, int pieceTypeCount); virtual quint64 side() const; virtual quint64 piece(const Piece& piece, int square) const; /*! * Returns the zobrist value for an en-passant target * at \a square. */ virtual quint64 enpassant(int square) const; /*! * Returns the zobrist value for player \a side's * castling rook at \a square. */ virtual quint64 castling(int side, int square) const; private: int m_castlingIndex; int m_pieceIndex; QMutex m_mutex; }; } //namespace Chess #endif // WESTERNZOBRIST_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/atomicboard.h0000664000175000017500000000354111657223322023325 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef ATOMICBOARD_H #define ATOMICBOARD_H #include "westernboard.h" namespace Chess { /*! * \brief A board for Atomic chess * * Atomic chess is a variant of standard chess where captures result * in an explosion on the target square. * * \note Rules: http://en.wikipedia.org/wiki/Atomic_chess */ class LIB_EXPORT AtomicBoard : public WesternBoard { public: /*! Creates a new AtomicBoard object. */ AtomicBoard(); // Inherited from WesternBoard virtual Board* copy() const; virtual QString variant() const; virtual QString defaultFenString() const; virtual Result result(); protected: // Inherited from WesternBoard virtual void vInitialize(); virtual bool inCheck(Side side, int square = 0) const; virtual bool kingCanCapture() const; virtual bool vSetFenString(const QStringList& fen); virtual bool vIsLegalMove(const Move& move); virtual void vMakeMove(const Move& move, BoardTransition* transition); virtual void vUndoMove(const Move& move); private: struct MoveData { bool isCapture; Piece piece; Piece captures[8]; }; QVector m_history; int m_offsets[8]; }; } // namespace Chess #endif // ATOMICBOARD_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/gothicboard.cpp0000664000175000017500000000206011657223322023654 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "gothicboard.h" namespace Chess { GothicBoard::GothicBoard() : CapablancaBoard() { } Board* GothicBoard::copy() const { return new GothicBoard(*this); } QString GothicBoard::variant() const { return "gothic"; } QString GothicBoard::defaultFenString() const { return "rnbqckabnr/pppppppppp/10/10/10/10/PPPPPPPPPP/RNBQCKABNR w KQkq - 0 1"; } } // namespace Chess cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/boardfactory.cpp0000664000175000017500000000163411657223322024054 0ustar oliveroliver#include "boardfactory.h" #include "atomicboard.h" #include "capablancaboard.h" #include "caparandomboard.h" #include "crazyhouseboard.h" #include "frcboard.h" #include "gothicboard.h" #include "losersboard.h" #include "standardboard.h" namespace Chess { REGISTER_BOARD(AtomicBoard, "atomic") REGISTER_BOARD(CapablancaBoard, "capablanca") REGISTER_BOARD(CaparandomBoard, "caparandom") REGISTER_BOARD(CrazyhouseBoard, "crazyhouse") REGISTER_BOARD(FrcBoard, "fischerandom") REGISTER_BOARD(GothicBoard, "gothic") REGISTER_BOARD(LosersBoard, "losers") REGISTER_BOARD(StandardBoard, "standard") ClassRegistry* BoardFactory::registry() { static ClassRegistry* registry = new ClassRegistry; return registry; } Board* BoardFactory::create(const QString& variant) { return registry()->create(variant); } QStringList BoardFactory::variants() { return registry()->items().keys(); } } // namespace Chess cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/frcboard.h0000664000175000017500000000327311657223322022625 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef FRCBOARD_H #define FRCBOARD_H #include "standardboard.h" namespace Chess { /*! * \brief A board for Fischer Random chess (or Chess 960) * * Fischer Random is like standard chess, but it uses randomized * starting positions, one of which is the starting position of * standard chess. FrcBoard uses the same zobrist position keys * as StandardBoard, so Polyglot opening books can be used. * * \note Rules: http://en.wikipedia.org/wiki/Chess960 * \sa StandardBoard * \sa CaparandomBoard */ class LIB_EXPORT FrcBoard : public StandardBoard { public: /*! Creates a new FrcBoard object. */ FrcBoard(); // Inherited from StandardBoard virtual Board* copy() const; virtual QString variant() const; virtual bool isRandomVariant() const; /*! * Returns a randomized starting FEN string. * * \note qrand() is used for the randomization, so qsrand() * should be called before calling this function. */ virtual QString defaultFenString() const; }; } // namespace Chess #endif // FRCBOARD_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/frcboard.cpp0000664000175000017500000000453311657223322023160 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "frcboard.h" #include "piece.h" static void addPiece(QVector& pieces, int piece, int pos, int start = 0, int step = 1) { int i = 0; for (int j = start; j < pieces.size(); j += step) { if (pieces.at(j) != Chess::Piece::NoPiece) continue; if (i == pos) { pieces[j] = piece; break; } i++; } } namespace Chess { FrcBoard::FrcBoard() : StandardBoard() { } Board* FrcBoard::copy() const { return new FrcBoard(*this); } QString FrcBoard::variant() const { return "fischerandom"; } bool FrcBoard::isRandomVariant() const { return true; } QString FrcBoard::defaultFenString() const { const int empty = Piece::NoPiece; QVector pieces(8, empty); addPiece(pieces, Bishop, qrand() % 4, 0, 2); addPiece(pieces, Bishop, qrand() % 4, 1, 2); addPiece(pieces, Queen, qrand() % 6); addPiece(pieces, Knight, qrand() % 5); addPiece(pieces, Knight, qrand() % 4); addPiece(pieces, Rook, 0); addPiece(pieces, King, 0); addPiece(pieces, Rook, 0); QString fen; // Black pieces foreach (int pieceType, pieces) fen += pieceSymbol(Piece(Side::Black, pieceType)); fen += '/'; // Black pawns for (int i = 0; i < width(); i++) fen += pieceSymbol(Piece(Side::Black, Pawn)); fen += '/'; // Empty squares for (int i = 0; i < height() - 4; i++) fen += QString::number(pieces.size()) + '/'; // White pawns for (int i = 0; i < width(); i++) fen += pieceSymbol(Piece(Side::White, Pawn)); fen += '/'; // White pieces foreach (int pieceType, pieces) fen += pieceSymbol(Piece(Side::White, pieceType)); // Side to move, castling rights, enpassant square, etc. fen += " w KQkq - 0 1"; return fen; } } // namespace Chess cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/side.cpp0000664000175000017500000000227411657223322022322 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "side.h" #include namespace Chess { Side::Side(const QString& symbol) { if (symbol == "w") m_type = White; else if (symbol == "b") m_type = Black; else m_type = NoSide; } QString Side::symbol() const { if (m_type == White) return "w"; else if (m_type == Black) return "b"; return QString(); } QString Side::toString() const { if (m_type == White) return QObject::tr("white"); else if (m_type == Black) return QObject::tr("black"); return QString(); } } // namespace Chess cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/atomicboard.cpp0000664000175000017500000000762411657223322023666 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "atomicboard.h" #include "westernzobrist.h" #include "boardtransition.h" namespace Chess { AtomicBoard::AtomicBoard() : WesternBoard(new WesternZobrist()) { for (int i = 0; i < 8; i++) m_offsets[i] = 0; } Board* AtomicBoard::copy() const { return new AtomicBoard(*this); } QString AtomicBoard::variant() const { return "atomic"; } QString AtomicBoard::defaultFenString() const { return "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"; } bool AtomicBoard::kingCanCapture() const { return false; } void AtomicBoard::vInitialize() { int arwidth = width() + 2; m_offsets[0] = -arwidth - 1; m_offsets[1] = -arwidth; m_offsets[2] = -arwidth + 1; m_offsets[3] = -1; m_offsets[4] = 1; m_offsets[5] = arwidth - 1; m_offsets[6] = arwidth; m_offsets[7] = arwidth + 1; WesternBoard::vInitialize(); } bool AtomicBoard::vSetFenString(const QStringList& fen) { m_history.clear(); return WesternBoard::vSetFenString(fen); } bool AtomicBoard::inCheck(Side side, int square) const { if (square == 0) { int kingSq = kingSquare(side); // If the kings touch, there's no check for (int i = 0; i < 8; i++) { Piece pc = pieceAt(kingSq + m_offsets[i]); if (pc.type() == King) return false; } } return WesternBoard::inCheck(side, square); } bool AtomicBoard::vIsLegalMove(const Move& move) { Q_ASSERT(!move.isNull()); if (captureType(move) != Piece::NoPiece) { bool explodeOppKing = false; int target = move.targetSquare(); for (int i = 0; i < 8; i++) { Piece pc = pieceAt(target + m_offsets[i]); if (pc.type() == King) { // Can't explode your own king if (pc.side() == sideToMove()) return false; explodeOppKing = true; } } // The move is always legal if the enemy king // is in the blast zone and own king is safe if (explodeOppKing) return true; } return WesternBoard::vIsLegalMove(move); } void AtomicBoard::vMakeMove(const Move& move, BoardTransition* transition) { MoveData md; md.isCapture = (captureType(move) != Piece::NoPiece); md.piece = pieceAt(move.sourceSquare()); WesternBoard::vMakeMove(move, transition); if (md.isCapture) { int target = move.targetSquare(); setSquare(target, Piece::NoPiece); for (int i = 0; i < 8; i++) { int sq = target + m_offsets[i]; Piece& pc = md.captures[i]; pc = pieceAt(sq); if (pc.isWall() || pc.type() == Pawn) continue; removeCastlingRights(sq); setSquare(sq, Piece::NoPiece); if (transition != 0) transition->addSquare(chessSquare(sq)); } } m_history << md; } void AtomicBoard::vUndoMove(const Move& move) { int source = move.sourceSquare(); int target = move.targetSquare(); WesternBoard::vUndoMove(move); const MoveData& md = m_history.last(); if (md.isCapture) { setSquare(source, md.piece); for (int i = 0; i < 8; i++) { int sq = target + m_offsets[i]; if (md.captures[i].isValid()) setSquare(sq, md.captures[i]); } } m_history.pop_back(); } Result AtomicBoard::result() { Side side(sideToMove()); if (pieceAt(kingSquare(side)).isEmpty()) { Side winner = side.opposite(); QString str = QObject::tr("%1's king exploded").arg(side.toString()); return Result(Result::Win, winner, str); } return WesternBoard::result(); } } // namespace Chess cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/zobrist.cpp0000664000175000017500000000547211657223322023075 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "zobrist.h" #include #include #include #include "piece.h" static QVarLengthArray s_keys; static QMutex s_mutex; namespace Chess { int Zobrist::s_randomSeed = 1; /*! * The "minimal standard" random number generator * by Park and Miller. * Returns a pseudo-random integer between 1 and 2147483646. */ int Zobrist::random32() { const int a = 16807; const int m = 2147483647; const int q = (m / a); const int r = (m % a); int hi = s_randomSeed / q; int lo = s_randomSeed % q; int test = a * lo - r * hi; if (test > 0) s_randomSeed = test; else s_randomSeed = test + m; return s_randomSeed; } Zobrist::Zobrist(const quint64* keys) : m_initialized(false), m_squareCount(0), m_pieceTypeCount(0), m_keys(keys) { } bool Zobrist::isInitialized() const { return m_initialized; } void Zobrist::initialize(int squareCount, int pieceTypeCount) { Q_ASSERT(squareCount > 0); Q_ASSERT(pieceTypeCount > 1); QMutexLocker locker(&s_mutex); if (m_initialized) return; m_squareCount = squareCount; m_pieceTypeCount = pieceTypeCount; if (m_keys == 0) { // Initialize the global zobrist array if (s_keys.isEmpty()) { for (int i = 0; i < s_keys.capacity(); i++) s_keys.append(random64()); } m_keys = s_keys.constData(); } m_initialized = true; } quint64 Zobrist::side() const { return m_keys[0]; } quint64 Zobrist::piece(const Piece& piece, int square) const { Q_ASSERT(piece.isValid()); Q_ASSERT(piece.type() >= 0 && piece.type() < m_pieceTypeCount); Q_ASSERT(square >= 0 && square < m_squareCount); int i = 1 + m_squareCount * m_pieceTypeCount * piece.side() + piece.type() * m_squareCount + square; return m_keys[i]; } quint64 Zobrist::reservePiece(const Piece& piece, int slot) const { Q_ASSERT(slot >= 0); // HACK: Use the "wall" squares (0...n) as slots // for hand pieces. return this->piece(piece, slot); } quint64 Zobrist::random64() { quint64 random1 = (quint64)random32(); quint64 random2 = (quint64)random32(); quint64 random3 = (quint64)random32(); return random1 ^ (random2 << 31) ^ (random3 << 62); } } // namespace Chess cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/zobrist.h0000664000175000017500000000641611657223322022541 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef ZOBRIST_H #define ZOBRIST_H #include namespace Chess { class Piece; /*! * \brief Unsigned 64-bit values for generating zobrist position keys. * * Chess::Board uses zobrist keys to quickly and easily compare two * positions for equality. Primary uses for zobrist keys are: * - Detecting repetitions, ie. a draw by three-fold repetition * - Opening books * - In hash table entries */ class LIB_EXPORT Zobrist { public: /*! * Creates a new uninitialized Zobrist object. * * \param keys An array of zobrist keys that can be used * instead of the random numbers generated by the Zobrist * class. */ Zobrist(const quint64* keys = 0); /*! Destroys the Zobrist object. */ virtual ~Zobrist() {} /*! Returns true if the keys are initialized. */ bool isInitialized() const; /*! * Initializes the zobrist numbers. * * \param squareCount The number of squares the board has, * including the invisible "Wall" squares. * \param pieceTypeCount The number of piece types the variant * has, including the empty "NoPiece" type (type 0). * * \note Subclasses that reimplement this function must call * the base implementation. */ virtual void initialize(int squareCount, int pieceTypeCount); /*! * Returns the zobrist value for side to move. * This value must be in the key on black's turn. */ virtual quint64 side() const; /*! Returns the zobrist value for \a piece at \a square. */ virtual quint64 piece(const Piece& piece, int square) const; /*! * Returns the zobrist value for reserve piece \a piece at \a slot. * * \note \a slot is zero-based, so the first piece of type * \a piece is at slot 0. */ virtual quint64 reservePiece(const Piece& piece, int slot) const; protected: /*! * Returns the number of squares the board has, including the * invisible "Wall" squares. */ int squareCount() const; /*! * Returns the number of piece types the variant has, including * the empty "NoPiece" type (type 0). */ int pieceTypeCount() const; /*! Returns the array of zobrist keys. */ const quint64* keys() const; /*! Returns an unsigned 64-bit pseudo-random number. */ static quint64 random64(); private: static int random32(); static int s_randomSeed; bool m_initialized; int m_squareCount; int m_pieceTypeCount; const quint64* m_keys; }; inline int Zobrist::squareCount() const { return m_squareCount; } inline int Zobrist::pieceTypeCount() const { return m_pieceTypeCount; } inline const quint64* Zobrist::keys() const { return m_keys; } } //namespace Chess #endif // ZOBRIST cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/caparandomboard.cpp0000664000175000017500000000670211657223322024513 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "caparandomboard.h" static void addPiece(QVector& pieces, int piece, int pos, int start = 0, int step = 1) { int i = 0; for (int j = start; j < pieces.size(); j += step) { if (pieces.at(j) != Chess::Piece::NoPiece) continue; if (i == pos) { pieces[j] = piece; break; } i++; } } namespace Chess { CaparandomBoard::CaparandomBoard() : CapablancaBoard() { } Board* CaparandomBoard::copy() const { return new CaparandomBoard(*this); } QString CaparandomBoard::variant() const { return "caparandom"; } bool CaparandomBoard::isRandomVariant() const { return true; } bool CaparandomBoard::pawnsAreSafe(const QVector& pieces) const { int size = pieces.size(); for (int i = 0; i < size; i++) { bool safe = false; for (int j = i - 2; j <= i + 2; j += 4) { if (j < 0 || j >= size) continue; if (pieceHasMovement(pieces.at(j), KnightMovement)) safe = true; } for (int j = i - 1; j <= i + 1; j += 2) { if (j < 0 || j >= size) continue; if (pieceHasMovement(pieces.at(j), BishopMovement) || pieces.at(j) == King) safe = true; } if (pieceHasMovement(pieces.at(i), RookMovement) || pieces.at(i) == King) safe = true; if (!safe) return false; } return true; } QString CaparandomBoard::defaultFenString() const { const int empty = Piece::NoPiece; QVector pieces(10); // Generate positions until we get one where all the pawns are // protected. This usually takes a handful of tries. do { pieces.fill(empty); if ((qrand() % 2) == 0) { addPiece(pieces, Queen, qrand() % 5, 0, 2); addPiece(pieces, Archbishop, qrand() % 5, 1, 2); } else { addPiece(pieces, Archbishop, qrand() % 5, 0, 2); addPiece(pieces, Queen, qrand() % 5, 1, 2); } addPiece(pieces, Bishop, qrand() % 4, 0, 2); addPiece(pieces, Bishop, qrand() % 4, 1, 2); addPiece(pieces, Chancellor, qrand() % 6); addPiece(pieces, Knight, qrand() % 5); addPiece(pieces, Knight, qrand() % 4); addPiece(pieces, Rook, 0); addPiece(pieces, King, 0); addPiece(pieces, Rook, 0); } while (!pawnsAreSafe(pieces)); QString fen; // Black pieces foreach (int pieceType, pieces) fen += pieceSymbol(Piece(Side::Black, pieceType)); fen += '/'; // Black pawns for (int i = 0; i < width(); i++) fen += pieceSymbol(Piece(Side::Black, Pawn)); fen += '/'; // Empty squares for (int i = 0; i < height() - 4; i++) fen += QString::number(pieces.size()) + '/'; // White pawns for (int i = 0; i < width(); i++) fen += pieceSymbol(Piece(Side::White, Pawn)); fen += '/'; // White pieces foreach (int pieceType, pieces) fen += pieceSymbol(Piece(Side::White, pieceType)); // Side to move, castling rights, enpassant square, etc. fen += " w KQkq - 0 1"; return fen; } } // namespace Chess cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/move.h0000664000175000017500000000616711657223322022016 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef MOVE_H #define MOVE_H #include #include namespace Chess { /*! * \brief A small and efficient chessmove class. * * This class is designed to be used internally by Board objects, * and to store minimal information about the move. A Board object * is needed to verify the move's legality or to convert it to a string. * * The source and target squares have an integer format specific to a * certain type of chess variant. The Board class has methods for * converting between these integers and the generic Square type. * * \sa Piece * \sa Board * \sa GenericMove */ class Move { public: /*! Creates an empty Move (null move). */ Move(); /*! * Creates a new Move object with at least a source * square and a target square. */ Move(int sourceSquare, int targetSquare, int promotion = 0); /*! * The source square. * * A value of 0 means that this move is a piece drop, * a special move allowed by some variants. */ int sourceSquare() const; /*! The target square. */ int targetSquare() const; /*! * Type of the promotion piece. * * A value of 0 means no promotion. * If this move is a piece drop, the promotion type * denotes the type of the dropped piece. */ int promotion() const; /*! Returns true if this is a null move. */ bool isNull() const; /*! Returns true if \a other is equal to this move. */ bool operator==(const Move& other) const; /*! Returns true if \a other is different from this move. */ bool operator!=(const Move& other) const; private: quint32 m_data; }; inline Move::Move() : m_data(0) { } inline Move::Move(int sourceSquare, int targetSquare, int promotion) : m_data(sourceSquare | (targetSquare << 10) | (promotion << 20)) { Q_ASSERT(sourceSquare >= 0 && sourceSquare <= 0x3FF); Q_ASSERT(targetSquare >= 0 && targetSquare <= 0x3FF); Q_ASSERT(promotion >= 0 && promotion <= 0x3FF); } inline bool Move::isNull() const { return (m_data == 0); } inline bool Move::operator==(const Move& other) const { return (m_data == other.m_data); } inline bool Move::operator!=(const Move& other) const { return (m_data != other.m_data); } inline int Move::sourceSquare() const { return m_data & 0x3FF; } inline int Move::targetSquare() const { return (m_data >> 10) & 0x3FF; } inline int Move::promotion() const { return (m_data >> 20) & 0x3FF; } } // namespace Chess Q_DECLARE_METATYPE(Chess::Move) #endif // MOVE_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/losersboard.h0000664000175000017500000000314211657223322023355 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef LOSERSBOARD_H #define LOSERSBOARD_H #include "westernboard.h" namespace Chess { /*! * \brief A board for Losers chess (or Wild 17) * * Losers is a variant of Standard chess where the players * try to lose all of their pieces, except for the king. If a * player can capture an opponent's piece, they must do so. * * \note Rules: http://wiki.wildchess.org/wiki/index.php/Losers */ class LIB_EXPORT LosersBoard : public WesternBoard { public: /*! Creates a new LosersBoard object. */ LosersBoard(); // Inherited from WesternBoard virtual Board* copy() const; virtual QString variant() const; virtual QString defaultFenString() const; virtual Result result(); protected: // Inherited from WesternBoard virtual bool vSetFenString(const QStringList& fen); virtual bool vIsLegalMove(const Move& move); private: bool m_canCapture; quint64 m_captureKey; }; } // namespace Chess #endif // LOSERSBOARD_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/westernboard.h0000664000175000017500000001227611657223322023545 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef WESTERNBOARD_H #define WESTERNBOARD_H #include "board.h" namespace Chess { class WesternZobrist; /*! * \brief A board for western chess variants * * WesternBoard serves as the overclass for all western variants. * In addition to possibly unique pieces, a western variant has * the same pieces as standard chess, the same rules for castling, * en-passant capture, promotion, etc. * * WesternBoard implements the rules of standard chess, including * check, checkmate, stalemate, promotion, 3-fold repetition, * 50 move rule and draws by insufficient material. */ class LIB_EXPORT WesternBoard : public Board { public: /*! Creates a new WesternBoard object. */ WesternBoard(WesternZobrist* zobrist); // Inherited from Board virtual int width() const; virtual int height() const; virtual Result result(); protected: /*! Basic piece types for western variants. */ enum WesternPieceType { Pawn = 1, //!< Pawn Knight, //!< Knight Bishop, //!< Bishop Rook, //!< Rook Queen, //!< Queen King //!< King }; /*! Movement mask for Knight moves. */ static const unsigned KnightMovement = 2; /*! Movement mask for Bishop moves. */ static const unsigned BishopMovement = 4; /*! Movement mask for Rook moves. */ static const unsigned RookMovement = 8; /*! * Returns true if the king can capture opposing pieces. * The default value is true. * \sa AtomicBoard */ virtual bool kingCanCapture() const; /*! * Adds pawn promotions to a move list. * * This function is called when a pawn can promote by * moving from \a sourceSquare to \a targetSquare. * This function generates all the possible promotions * and adds them to \a moves. */ virtual void addPromotions(int sourceSquare, int targetSquare, QVarLengthArray& moves) const; /*! Returns the king square of \a side. */ int kingSquare(Side side) const; /*! Returns the number of consecutive reversible moves made. */ int reversibleMoveCount() const; /*! * Removes castling rights at \a square. * * If one of the players has a rook at \a square, the rook can't * be used for castling. This function should be called when a * capture happens at \a square. */ void removeCastlingRights(int square); /*! * Returns true if \a side is under attack at \a square. * If \a square is 0, then the king square is used. */ virtual bool inCheck(Side side, int square = 0) const; // Inherited from Board virtual void vInitialize(); virtual QString vFenString(FenNotation notation) const; virtual bool vSetFenString(const QStringList& fen); virtual QString lanMoveString(const Move& move); virtual QString sanMoveString(const Move& move); virtual Move moveFromLanString(const QString& str); virtual Move moveFromSanString(const QString& str); virtual void vMakeMove(const Move& move, BoardTransition* transition); virtual void vUndoMove(const Move& move); virtual void generateMovesForPiece(QVarLengthArray& moves, int pieceType, int square) const; virtual bool vIsLegalMove(const Move& move); virtual bool isLegalPosition(); virtual int captureType(const Move& move) const; private: enum CastlingSide { QueenSide, KingSide, NoCastlingSide }; struct CastlingRights { // Usage: 'rookSquare[Side][CastlingSide]' // A value of zero (square 0) means no castling rights int rookSquare[2][2]; }; // Data for reversing/unmaking a move struct MoveData { Piece capture; int enpassantSquare; CastlingRights castlingRights; CastlingSide castlingSide; int reversibleMoveCount; }; void generateCastlingMoves(QVarLengthArray& moves) const; void generatePawnMoves(int sourceSquare, QVarLengthArray& moves) const; bool canCastle(CastlingSide castlingSide) const; QString castlingRightsString(FenNotation notation) const; bool parseCastlingRights(QChar c); CastlingSide castlingSide(const Move& move) const; void setEnpassantSquare(int square); void setCastlingSquare(Side side, CastlingSide cside, int square); int m_arwidth; int m_sign; int m_kingSquare[2]; int m_enpassantSquare; int m_reversibleMoveCount; bool m_kingCanCapture; QVector m_history; CastlingRights m_castlingRights; int m_castleTarget[2][2]; const WesternZobrist* m_zobrist; QVarLengthArray m_knightOffsets; QVarLengthArray m_bishopOffsets; QVarLengthArray m_rookOffsets; }; } // namespace Chess #endif // WESTERNBOARD_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/side.h0000664000175000017500000000450311657223322021764 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef SIDE_H #define SIDE_H #include #include namespace Chess { /*! * \brief The side or color of a chess player. * * This class is a simple wrapper for the enumerated type Side::Type. * Side objects can be used just like one would use an enum type * (eg. as an array index). */ class LIB_EXPORT Side { public: /*! The enumerated type for the side. */ enum Type { White, //!< The side with the white pieces. Black, //!< The side with the black pieces. NoSide //!< No side }; /*! Constructs a new, null Side object. */ Side(); /*! Constructs a new Side object of type \a type. */ Side(Type type); /*! * Constructs a new Side object from a symbol. * * The symbol can be "w" for \a White, "b" for \a Black, * or anything else for \a NoSide. */ explicit Side(const QString& symbol); /*! Returns true if the side is \a NoSide. */ bool isNull() const; /*! Operator for the \a Type value of the side. */ operator Type() const; /*! * Returns the opposite side. * \note The side must not be null. */ Side opposite() const; /*! Returns the text symbol for the side. */ QString symbol() const; /*! Returns a localized name of the side. */ QString toString() const; private: Type m_type; }; inline Side::Side() : m_type(NoSide) { } inline Side::Side(Type type) : m_type(type) { } inline bool Side::isNull() const { return (m_type == NoSide); } inline Side::operator Type() const { return m_type; } inline Side Side::opposite() const { Q_ASSERT(!isNull()); return Side(Type(int(m_type) ^ 1)); } } // namespace Chess Q_DECLARE_METATYPE(Chess::Side) #endif // SIDE_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/boardtransition.cpp0000664000175000017500000000236511657223322024601 0ustar oliveroliver#include "boardtransition.h" namespace Chess { BoardTransition::BoardTransition() { } bool BoardTransition::isEmpty() const { return (m_moves.isEmpty() && m_drops.isEmpty() && m_squares.isEmpty() && m_reserve.isEmpty()); } void BoardTransition::clear() { m_moves.clear(); m_drops.clear(); m_squares.clear(); m_reserve.clear(); } QList BoardTransition::moves() const { return m_moves; } QList BoardTransition::drops() const { return m_drops; } QList BoardTransition::squares() const { return m_squares; } QList BoardTransition::reserve() const { return m_reserve; } void BoardTransition::addMove(const Square& source, const Square& target) { Move move = { source, target }; m_moves.append(move); addSquare(source); addSquare(target); } void BoardTransition::addDrop(const Piece& piece, const Square& target) { Drop drop = { piece, target }; m_drops.append(drop); addSquare(target); addReservePiece(piece); } void BoardTransition::addSquare(const Square& square) { if (!m_squares.contains(square)) m_squares.append(square); } void BoardTransition::addReservePiece(const Piece& piece) { if (!m_reserve.contains(piece)) m_reserve.append(piece); } } // namespace Chess cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/result.h0000664000175000017500000000625511657223322022364 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef RESULT_H #define RESULT_H #include "side.h" namespace Chess { /*! * \brief The result of a chess game * * The Result class is used to store the result of a chess game, * and to compare it to other results. */ class LIB_EXPORT Result { public: /*! Result type. */ enum Type { //! Win by any means. Win, //! Draw by any means. Draw, //! Loser resigns. Resignation, //! A player's time flag falls. Timeout, //! Adjudication by the GUI. Adjudication, //! Loser tries to make an illegal move. IllegalMove, //! Loser disconnects, or terminates (if it's an engine). Disconnection, //! Loser's connection stalls (doesn't respond to ping). StalledConnection, //! Both players agree to a result. Agreement, //! No result. The game may continue. NoResult, //! Result error, caused by an invalid result string. ResultError }; /*! * Creates a new result. * * \param type The type of the result * \param winner The winning side (or NoSide in case of a draw) * \param description A description of the result. If the Result * class has a preset description for \a type, this * additional description is appended to it. */ explicit Result(Type type = NoResult, Side winner = Side(), const QString& description = QString()); /*! Creates a new result from a string. */ explicit Result(const QString& str); /*! Returns true if \a other is the same as this result. */ bool operator==(const Result& other) const; /*! Returns true if \a other different from this result. */ bool operator!=(const Result& other) const; /*! Returns true if the result is NoResult. */ bool isNone() const; /*! Returns true if the result is Draw. */ bool isDraw() const; /*! Returns the winning side, or NoSide if there's no winner. */ Side winner() const; /*! Returns the losing side, or NoSide if there's no loser. */ Side loser() const; /*! Returns the type of the result. */ Type type() const; /*! Returns the result description. */ QString description() const; /*! * Returns the short string representation of the result. * Can be "1-0", "0-1", "1/2-1/2", or "*". */ QString toShortString() const; /*! * Returns the verbose string representation of the result. * * Uses the format "result {description}". * Eg. "1-0 {White mates}". */ QString toVerboseString() const; private: Type m_type; Side m_winner; QString m_description; }; } // namespace Chess #endif // RESULT_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/boardfactory.h0000664000175000017500000000162711657223322023523 0ustar oliveroliver#ifndef BOARDFACTORY_H #define BOARDFACTORY_H #include #include #include "board.h" namespace Chess { /*! \brief A factory for creating Board objects. */ class LIB_EXPORT BoardFactory { public: /*! Returns the class registry for concrete Board subclasses. */ static ClassRegistry* registry(); /*! * Creates and returns a new Board of variant \a variant. * Returns 0 if \a variant is not supported. */ static Board* create(const QString& variant); /*! Returns a list of supported chess variants. */ static QStringList variants(); private: BoardFactory(); }; /*! * Registers board class \a TYPE with variant name \a VARIANT. * * This macro must be called once for every concrete Board class. */ #define REGISTER_BOARD(TYPE, VARIANT) \ REGISTER_CLASS(Board, TYPE, VARIANT, BoardFactory::registry()); } // namespace Chess #endif // BOARDFACTORY_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/boardtransition.h0000664000175000017500000000607411657223322024247 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef BOARDTRANSITION_H #define BOARDTRANSITION_H #include #include "square.h" #include "piece.h" namespace Chess { /*! * \brief Details of a board transition caused by a move. * * This class stores information about the movement of pieces * and changed squares on a chessboard. Two types of information * are stored: movement, and changed squares and reserve pieces. * The latter type of information is sufficient for updating the * state of a graphical board, and the former can be used to * display or animate the actual chessmove. * * \sa Board::makeMove() */ class LIB_EXPORT BoardTransition { public: /*! \brief Movement on the board. */ struct Move { Square source; //!< Source square Square target; //!< Target square }; /*! * \brief A piece drop. * * In some chess variants it's possible to bring * captured pieces back to the game from a piece reserve. */ struct Drop { Piece piece; //!< Type of the dropped piece Square target; //!< Target square of the drop }; /*! Creates a new empty BoardTransition object. */ BoardTransition(); /*! Returns true if there are no transitions. */ bool isEmpty() const; /*! Clears all data, ie. empties the transition. */ void clear(); /*! * Returns a list of "moves". * * One chessmove can involve several moving pieces, and * the actual chessmove may not be on the returned list. */ QList moves() const; /*! Returns a list of piece drops. */ QList drops() const; /*! Returns a list of changed squares. */ QList squares() const; /*! Returns a list of changed piece reserves. */ QList reserve() const; /*! Adds a new "move" from \a source to \a target. */ void addMove(const Square& source, const Square& target); /*! Adds a new piece drop of \a piece to \a target. */ void addDrop(const Piece& piece, const Square& target); /*! * Adds a new changed square. * * If \a square already exists in the transition, this * function does nothing. */ void addSquare(const Square& square); /*! * Adds a new changed reserve piece. * * If \a piece already exists in the transition, this * function does nothing. */ void addReservePiece(const Piece& piece); private: QList m_moves; QList m_drops; QList m_squares; QList m_reserve; }; } // namespace Chess #endif // BOARDTRANSITION_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/westernzobrist.cpp0000664000175000017500000000365711657223322024510 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "westernzobrist.h" #include #include "piece.h" namespace Chess { WesternZobrist::WesternZobrist(const quint64* keys) : Zobrist(keys), m_castlingIndex(0), m_pieceIndex(0) { } void WesternZobrist::initialize(int squareCount, int pieceTypeCount) { QMutexLocker locker(&m_mutex); if (isInitialized()) return; Zobrist::initialize(squareCount, pieceTypeCount); m_castlingIndex = 1 + squareCount; m_pieceIndex = m_castlingIndex + squareCount * 2; } quint64 WesternZobrist::side() const { return keys()[0]; } quint64 WesternZobrist::piece(const Piece& piece, int square) const { Q_ASSERT(piece.isValid()); Q_ASSERT(piece.type() >= 0 && piece.type() < pieceTypeCount()); Q_ASSERT(square >= 0 && square < squareCount()); int i = m_pieceIndex + squareCount() * pieceTypeCount() * piece.side() + piece.type() * squareCount() + square; return keys()[i]; } quint64 WesternZobrist::enpassant(int square) const { Q_ASSERT(square >= 0 && square < squareCount()); return keys()[1 + square]; } quint64 WesternZobrist::castling(int side, int square) const { Q_ASSERT(side != Side::NoSide); Q_ASSERT(square >= 0 && square < squareCount()); return keys()[m_castlingIndex + squareCount() * side + square]; } } // namespace Chess cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/gothicboard.h0000664000175000017500000000245511657223322023331 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef GOTHICBOARD_H #define GOTHICBOARD_H #include "capablancaboard.h" namespace Chess { /*! * \brief A board for Gothic chess * * Gothic chess is a variant of Capablanca chess that uses a * different starting position. * * \note Rules: http://www.gothicchess.com/rules.html * \sa CapablancaBoard */ class LIB_EXPORT GothicBoard : public CapablancaBoard { public: /*! Creates a new GothicBoard object. */ GothicBoard(); // Inherited from CapablancaBoard virtual Board* copy() const; virtual QString variant() const; virtual QString defaultFenString() const; }; } // namespace Chess #endif // GOTHICBOARD_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/result.cpp0000664000175000017500000000760111657223322022713 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "result.h" #include namespace Chess { Result::Result(Type type, Side winner, const QString& description) : m_type(type), m_winner(winner), m_description(description) { } Result::Result(const QString& str) : m_type(ResultError) { if (str.startsWith("1-0")) { m_type = Win; m_winner = Side::White; } else if (str.startsWith("0-1")) { m_type = Win; m_winner = Side::Black; } else if (str.startsWith("1/2-1/2")) m_type = Draw; else if (str.startsWith("*")) m_type = NoResult; int start = str.indexOf('{'); int end = str.lastIndexOf('}'); if (start != -1 && end != -1) m_description = str.mid(start + 1, end - start - 1); } bool Result::operator==(const Result& other) const { return (m_type == other.m_type && m_winner == other.m_winner && m_description == other.m_description); } bool Result::operator!=(const Result& other) const { return (m_type != other.m_type || m_winner != other.m_winner || m_description != other.m_description); } bool Result::isNone() const { return m_type == NoResult; } bool Result::isDraw() const { return (m_winner.isNull() && m_type != NoResult && m_type != ResultError); } Side Result::winner() const { return m_winner; } Side Result::loser() const { if (m_winner.isNull()) return Side::NoSide; return m_winner.opposite(); } Result::Type Result::type() const { return m_type; } QString Result::description() const { QString w(winner().toString()); QString l(loser().toString()); QString str; if (m_type == Resignation) str = QObject::tr("%1 resigns").arg(l); else if (m_type == Timeout) { if (l.isEmpty()) str = QObject::tr("Draw by timeout"); else str = QObject::tr("%1 loses on time").arg(l); } else if (m_type == Adjudication) { if (w.isEmpty()) str = QObject::tr("Draw by adjudication"); else str = QObject::tr("%1 wins by adjudication").arg(w); } else if (m_type == IllegalMove) str = QObject::tr("%1 makes an illegal move").arg(l); else if (m_type == Disconnection) { if (l.isEmpty()) str = QObject::tr("Draw by disconnection"); else str = QObject::tr("%1 disconnects").arg(l); } else if (m_type == StalledConnection) { if (l.isEmpty()) str = QObject::tr("Draw by stalled connection"); else str = QObject::tr("%1's connection stalls").arg(l); } else if (m_type == Agreement) { if (w.isEmpty()) str = QObject::tr("Draw by agreement"); else str = QObject::tr("%1 wins by agreement").arg(w); } else if (m_type == NoResult) str = QObject::tr("No result"); else if (m_type == ResultError) str = QObject::tr("Result error"); if (m_description.isEmpty()) { if (m_type == Win) str = QObject::tr("%1 wins").arg(w); else if (m_type == Draw) str = QObject::tr("Drawn game"); } else { if (!str.isEmpty()) str += ": "; str += m_description; } Q_ASSERT(!str.isEmpty()); str[0] = str.at(0).toUpper(); return str; } QString Result::toShortString() const { if (m_type == NoResult || m_type == ResultError) return "*"; if (m_winner == Side::White) return "1-0"; if (m_winner == Side::Black) return "0-1"; return "1/2-1/2"; } QString Result::toVerboseString() const { return toShortString() + QString(" {") + description() + "}"; } } // namespace Chess cutechess-20111114+0.4.2+0.0.1/projects/lib/src/board/board.pri0000664000175000017500000000143711657223322022475 0ustar oliveroliverDEPENDPATH += $$PWD SOURCES += board.cpp \ westernboard.cpp \ square.cpp \ standardboard.cpp \ capablancaboard.cpp \ zobrist.cpp \ westernzobrist.cpp \ frcboard.cpp \ caparandomboard.cpp \ result.cpp \ side.cpp \ genericmove.cpp \ atomicboard.cpp \ losersboard.cpp \ gothicboard.cpp \ crazyhouseboard.cpp \ boardfactory.cpp \ boardtransition.cpp HEADERS += board.h \ move.h \ piece.h \ westernboard.h \ square.h \ standardboard.h \ capablancaboard.h \ zobrist.h \ westernzobrist.h \ frcboard.h \ caparandomboard.h \ result.h \ side.h \ genericmove.h \ atomicboard.h \ losersboard.h \ gothicboard.h \ crazyhouseboard.h \ boardfactory.h \ boardtransition.h cutechess-20111114+0.4.2+0.0.1/projects/lib/src/enginecheckoption.h0000664000175000017500000000106411657223322023444 0ustar oliveroliver#ifndef ENGINECHECKOPTION_H #define ENGINECHECKOPTION_H #include "engineoption.h" class LIB_EXPORT EngineCheckOption : public EngineOption { public: EngineCheckOption(const QString& name, const QVariant& value = QVariant(), const QVariant& defaultValue = QVariant(), const QString& alias = QString()); // Inherited from EngineOption virtual EngineOption* copy() const; virtual bool isValid(const QVariant& value) const; virtual QVariant toVariant() const; }; #endif // ENGINECHECKOPTION_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/chessgame.h0000664000175000017500000000660511657223322021715 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef CHESSGAME_H #define CHESSGAME_H #include #include #include #include #include "pgngame.h" #include "board/result.h" #include "board/move.h" #include "timecontrol.h" namespace Chess { class Board; } class ChessPlayer; class OpeningBook; class MoveEvaluation; class LIB_EXPORT ChessGame : public QObject { Q_OBJECT public: ChessGame(Chess::Board* board, PgnGame* pgn, QObject* parent = 0); virtual ~ChessGame(); ChessPlayer* player(Chess::Side side) const; bool isFinished() const; PgnGame* pgn() const; Chess::Board* board() const; QString startingFen() const; const QVector& moves() const; Chess::Result result() const; void setPlayer(Chess::Side side, ChessPlayer* player); void setStartingFen(const QString& fen); void setTimeControl(const TimeControl& timeControl, Chess::Side side = Chess::Side()); void setMoves(const QVector& moves); void setMoves(const PgnGame& pgn); void setOpeningBook(const OpeningBook* book, Chess::Side side = Chess::Side(), int depth = 1000); void setDrawThreshold(int moveNumber, int score); void setResignThreshold(int moveCount, int score); void setStartDelay(int time); void generateOpening(); void lockThread(); void unlockThread(); public slots: void start(); void pause(); void resume(); void stop(); void kill(); void onMoveMade(const Chess::Move& move); signals: void humanEnabled(bool); void fenChanged(const QString& fenString); void moveMade(const Chess::GenericMove& move, const QString& sanString, const QString& comment); void started(); void finished(); void playersReady(); private slots: void startGame(); void startTurn(); void finish(); void onForfeit(const Chess::Result& result); void onPlayerReady(); void syncPlayers(); void pauseThread(); private: void adjudication(const MoveEvaluation& eval); Chess::Move bookMove(Chess::Side side); ChessPlayer* playerToMove(); ChessPlayer* playerToWait(); void resetBoard(); void initializePgn(); void addPgnMove(const Chess::Move& move, const QString& comment); void emitLastMove(); Chess::Board* m_board; ChessPlayer* m_player[2]; TimeControl m_timeControl[2]; const OpeningBook* m_book[2]; int m_bookDepth[2]; int m_startDelay; bool m_finished; bool m_gameInProgress; bool m_paused; int m_drawMoveNum; int m_drawScore; int m_drawScoreCount; int m_resignMoveCount; int m_resignScore; int m_resignScoreCount[2]; QString m_startingFen; Chess::Result m_result; QVector m_moves; PgnGame* m_pgn; QSemaphore m_pauseSem; QSemaphore m_resumeSem; }; #endif // CHESSGAME_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/pgngameentry.cpp0000664000175000017500000001711511657223322023007 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "pgngameentry.h" #include #include #include #include "pgnstream.h" #include "pgngamefilter.h" PgnStream& operator>>(PgnStream& in, PgnGameEntry& entry) { entry.read(in); return in; } QDataStream& operator>>(QDataStream& in, PgnGameEntry& entry) { entry.read(in); return in; } QDataStream& operator<<(QDataStream& out, const PgnGameEntry& entry) { entry.write(out); return out; } PgnGameEntry::PgnGameEntry() : m_pos(0), m_lineNumber(1) { } static int s_stringContains(const char* s1, const char* s2, int size) { Q_ASSERT(s1 != 0); Q_ASSERT(s2 != 0); Q_ASSERT(size >= 0); if (!*s2) return 0; if (size == 0) return -1; const char* s1_begin = s1; while (s1 - s1_begin < size) { if (toupper(*s1) == toupper(*s2)) { const char* a = s1; const char* b = s2; while (*b && a - s1_begin < size - 1) { if (toupper(*a) != toupper(*b)) break; a++; b++; } if (!*b) return b - s2; } s1++; } return -1; } static int s_stringToInt(const char *s, int size) { int num = 0; for (int i = 0; i < size; i++) { if (!isdigit(s[i])) return 0; num = num * 10 + (s[i] - '0'); } return num; } bool PgnGameEntry::match(const PgnGameFilter& filter) const { const char* data = m_data.constData(); if (filter.type() == PgnGameFilter::FixedString) return s_stringContains(data, filter.pattern(), m_data.size()) != -1; int whitePlayer = 0; int i = 0; for (int type = 0; type < 8; type++) { int size = data[i++]; const char* str = data + i; switch (type) { case EventTag: if (s_stringContains(str, filter.event(), size) == -1) return false; break; case SiteTag: if (s_stringContains(str, filter.site(), size) == -1) return false; break; case DateTag: if (!filter.minDate().isNull() || !filter.maxDate().isNull()) { if (size < 10) return false; int year = s_stringToInt(str, 4); if (year == 0) return false; int month = s_stringToInt(str + 5, 2); if (month == 0) month = 1; int day = s_stringToInt(str + 8, 2); if (day == 0) day = 1; QDate date(year, month, day); if ((!filter.minDate().isNull() && date < filter.minDate()) || (!filter.maxDate().isNull() && date > filter.maxDate())) return false; } break; case RoundTag: if (filter.minRound() != 0 || filter.maxRound() != 0) { int round = s_stringToInt(str, size); if (round == 0 || (filter.minRound() != 0 && round < filter.minRound()) || (filter.maxRound() != 0 && round > filter.maxRound())) return false; } break; case WhiteTag: { int len1 = -1; int len2 = -1; if (filter.playerSide() != Chess::Side::Black) len1 = s_stringContains(str, filter.player(), size); if (filter.playerSide() != Chess::Side::White) len2 = s_stringContains(str, filter.opponent(), size); if (len1 == -1 && len2 == -1) return false; whitePlayer = (len1 >= len2) ? 1 : 2; } break; case BlackTag: { int len1 = -1; int len2 = -1; if (filter.playerSide() != Chess::Side::White && whitePlayer != 1) len1 = s_stringContains(str, filter.player(), size); if (filter.playerSide() != Chess::Side::Black && whitePlayer != 2) len2 = s_stringContains(str, filter.opponent(), size); if (len1 == -1 && len2 == -1) return false; } break; case ResultTag: { if (filter.result() == PgnGameFilter::AnyResult) break; Chess::Result result(QString::fromLatin1(str, size)); int winner = 0; if (!result.winner().isNull()) { if (whitePlayer == 1) winner = result.winner() + 1; else { if (result.winner() == Chess::Side::White) winner = 2; else winner = 1; } } bool ok; switch (filter.result()) { case PgnGameFilter::EitherPlayerWins: ok = !result.winner().isNull(); break; case PgnGameFilter::WhiteWins: ok = result.winner() == Chess::Side::White; break; case PgnGameFilter::BlackWins: ok = result.winner() == Chess::Side::Black; break; case PgnGameFilter::FirstPlayerWins: ok = winner == 1; break; case PgnGameFilter::FirstPlayerLoses: ok = winner == 2; break; case PgnGameFilter::Draw: ok = result.isDraw(); break; case PgnGameFilter::Unfinished: ok = result.isNone(); break; default: ok = true; break; } if (ok == filter.isResultInverted()) return false; } break; default: break; } i += size; } return true; } void PgnGameEntry::addTag(const QByteArray& tagValue) { int size = qMin(127, tagValue.size()); m_data.append(char(size)); m_data.append(tagValue.constData(), size); } void PgnGameEntry::clear() { m_pos = 0; m_lineNumber = 1; m_data.clear(); } static void skipSection(PgnStream& in, char type) { char end; switch (type) { case '(': end = ')'; break; case '{': end = '}'; break; default: return; } int level = 1; char c; while ((c = in.readChar()) != 0) { if (c == end && --level == 0) break; if (c == type) level++; } } bool PgnGameEntry::read(PgnStream& in) { char c; QByteArray tagName; QByteArray tagValue; QMap tags; bool haveTagName = false; bool foundTag = false; bool inTag = false; bool inQuotes = false; clear(); while ((c = in.readChar()) != 0) { if (!inTag) { if (c == '[') { inTag = true; if (!foundTag) { foundTag = true; m_pos = in.pos() - 1; m_lineNumber = in.lineNumber(); } } else if (foundTag && !isspace(c)) break; else skipSection(in, c); continue; } if ((c == ']' && !inQuotes) || c == '\n' || c == '\r') { tags[tagName] = tagValue; tagName.clear(); tagValue.clear(); inTag = false; inQuotes = false; haveTagName = false; continue; } if (!haveTagName) { if (c == ' ') haveTagName = true; else tagName += c; } else if (c == '\"') inQuotes = !inQuotes; else if (inQuotes) tagValue += c; } addTag(tags["Event"]); addTag(tags["Site"]); addTag(tags["Date"]); addTag(tags["Round"]); addTag(tags["White"]); addTag(tags["Black"]); addTag(tags["Result"]); addTag(tags["Variant"]); return foundTag; } bool PgnGameEntry::read(QDataStream& in) { // modifying this function can cause backward compatibility issues // in other programs. in >> m_pos; in >> m_lineNumber; in >> m_data; return in.status() == QDataStream::Ok; } void PgnGameEntry::write(QDataStream& out) const { // modifying this function can cause backward compatibility issues // in other programs. out << m_pos; out << m_lineNumber; out << m_data; } qint64 PgnGameEntry::pos() const { return m_pos; } qint64 PgnGameEntry::lineNumber() const { return m_lineNumber; } QString PgnGameEntry::tagValue(TagType type) const { int i = 0; for (int j = 0; j < type; j++) i += m_data[i] + 1; int size = m_data[i]; if (size == 0) return QString(); return m_data.mid(i + 1, size); } cutechess-20111114+0.4.2+0.0.1/projects/lib/src/timecontrol.h0000664000175000017500000001264111657223322022312 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef TIMECONTROL_H #define TIMECONTROL_H #include #include /*! * \brief Time controls of a chess game. * * TimeControl is used for telling the chess players how much time * they can spend thinking of their moves. * * \note All time handling is done in milliseconds. */ class LIB_EXPORT TimeControl { public: /*! Creates a new time control with invalid default settings. */ TimeControl(); /*! * Creates a new time control from a string. * * \a str must either be "inf" for infinite time, or it can use * the format: movesPerTc/timePerTc+timeIncrement * - timePerTc is time in seconds if it's a single value. * It can also use the form minutes:seconds. * - if movesPerTc is 0, it should be left out, and the slash * character isn't needed. * - timeIncrement is the time increment per move in seconds. * If it's 0, it should be left out along with the plus sign. * * Example 1 (40 moves in 120 seconds): * TimeControl("40/120"); * * Example 2 (same as example 1, 40 moves in 2 minutes): * TimeControl("40/2:0"); * * Example 3 (whole game in 2.5 minutes plus 5 sec increment): * TimeControl("2:30+5"); * * Example 4 (infinite thinking time): * TimeControl("inf"); */ TimeControl(const QString& str); /*! * Returns true if \a other is the same as this time control. * * The state of a game (eg. time left, used time, the expiry flag) * and the expiry margin are ignored. */ bool operator==(const TimeControl& other) const; /*! Returns true if the time control is valid. */ bool isValid() const; /*! Returns the time control string in PGN format. */ QString toString() const; /*! Returns a verbose description of the time control. */ QString toVerboseString() const; /*! Initializes the time control ready for a new game. */ void initialize(); /*! Returns true if the time control is infinite. */ bool isInfinite() const; /*! * Returns the time per time control, * or 0 if there's no specified total time. */ int timePerTc() const; /*! * Returns the number of moves per time control, * or 0 if the whole game is played in timePerTc() time. */ int movesPerTc() const; /*! Returns the time increment per move. */ int timeIncrement() const; /*! * Returns the time per move. * * The player will think of each move this long at most. * Returns 0 if there's no specified total time. */ int timePerMove() const; /*! Returns the time left in the time control. */ int timeLeft() const; /*! * Returns the number of full moves left in the time control, * or 0 if the number of moves is not specified. */ int movesLeft() const; /*! Returns the maximum search depth in plies. */ int plyLimit() const; /*! Returns the node limit for each move. */ int nodeLimit() const; /*! * Returns the expiry margin. * * Expiry margin is the amount of time a player can go over * the time limit without losing on time. * The default value is 0. */ int expiryMargin() const; /*! * If \a enabled is true, infinite time control is enabled; * otherwise it is disabled. */ void setInfinity(bool enabled = true); /*! Sets the time per time control. */ void setTimePerTc(int timePerTc); /*! Sets the number of moves per time control. */ void setMovesPerTc(int movesPerTc); /*! Sets the time increment per move. */ void setTimeIncrement(int increment); /*! Sets the time per move. */ void setTimePerMove(int timePerMove); /*! Sets the time left in the time control. */ void setTimeLeft(int timeLeft); /*! Sets the number of full moves left in the time control. */ void setMovesLeft(int movesLeft); /*! Sets the maximum search depth in plies. */ void setPlyLimit(int plies); /*! Sets the node limit. */ void setNodeLimit(int nodes); /*! Sets the expiry margin. */ void setExpiryMargin(int expiryMargin); /*! Start the timer. */ void startTimer(); /*! Update the time control with the elapsed time. */ void update(); /*! Returns the last elapsed move time. */ int lastMoveTime() const; /*! Returns true if the allotted time has expired. */ bool expired() const; /*! * Returns the time left in an active clock. * * The TimeControl object doesn't know whether the clock is * active or not. It's recommended to check the player's * state first to verify that it's in the thinking state. */ int activeTimeLeft() const; private: int m_movesPerTc; int m_timePerTc; int m_timePerMove; int m_increment; int m_timeLeft; int m_movesLeft; int m_plyLimit; int m_nodeLimit; int m_lastMoveTime; int m_expiryMargin; bool m_expired; bool m_infinite; QTime m_time; }; #endif // TIMECONTROL_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/pgngamefilter.h0000664000175000017500000001351011657223322022573 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef PGNGAMEFILTER_H #define PGNGAMEFILTER_H #include #include #include class QString; class PgnGameEntry; /*! * \brief A filter for chess games in a PGN database. * * A PgnGameFilter object can be used to filter games in a PGN * database by matching the filtering terms to the games' PGN * tags. * * \sa PgnGameEntry */ class LIB_EXPORT PgnGameFilter { public: /*! The type of the filter. */ enum Type { /*! Filter all tags with a single fixed string. */ FixedString, /*! Use invididual filtering terms for each tag. */ Advanced }; /*! The result of the game. */ enum Result { AnyResult, //!< Any result (no filtering) EitherPlayerWins, //!< Either player wins WhiteWins, //!< The white player wins BlackWins, //!< The black player wins FirstPlayerWins, //!< The first player wins FirstPlayerLoses, //!< The first player loses Draw, //!< The game is a draw Unfinished //!< The game wasn't completed }; /*! * Creates a new empty filter. * * An empty filter will not filter out any games. * The filter's type is \a Advanced. */ PgnGameFilter(); /*! * Creates a new filter based on a fixed string. * * Games that have tags matching \a pattern will be filtered in. * The filter's type is \a FixedString. */ PgnGameFilter(const QString& pattern); /*! Returns the type of the filter. */ Type type() const; /*! Returns the pattern for \a FixedString mode. */ const char* pattern() const; /*! Returns the filter for the \a Event tag. */ const char* event() const; /*! Returns the filter for the \a Site tag. */ const char* site() const; /*! * Returns the filter for the first player. * * The first player's side/color is determined by the * playerSide() member function. */ const char* player() const; /*! Returns the filter for the opponent of the first player. */ const char* opponent() const; /*! Returns the filter for the side/color of the first player. */ Chess::Side playerSide() const; /*! * Returns the filter for the game's minimum starting date. * * \note A null QDate won't filter out any games. */ const QDate& minDate() const; /*! * Returns the filter for the game's maximum starting date. * * \note A null QDate won't filter out any games. */ const QDate& maxDate() const; /*! Returns the filter for the minimum round ordinal. */ int minRound() const; /*! Returns the filter for the maximum round ordinal. */ int maxRound() const; /*! Returns the filter for the \a Result tag. */ Result result() const; /*! * Returns true if the filter is looking for the inverse * of \a result(); otherwise returns false. */ bool isResultInverted() const; /*! * Sets the \a FixedString pattern to \a pattern. * * This function will change the filter type to \a FixedString. */ void setPattern(const QString& pattern); /*! Sets the \a Event tag filter to \a event. */ void setEvent(const QString& event); /*! Sets the \a Site tag filter to \a site. */ void setSite(const QString& site); /*! Sets the minimum starting date filter to \a date. */ void setMinDate(const QDate& date); /*! Sets the maximum starting date filter to \a date. */ void setMaxDate(const QDate& date); /*! Sets the minimum round ordinal filter to \a round. */ void setMinRound(int round); /*! Sets the maximum round ordinal filter to \a round. */ void setMaxRound(int round); /*! Sets the \a side player's filter to \a name. */ void setPlayer(const QString& name, Chess::Side side); /*! Sets the first player's opponent filter to \a name. */ void setOpponent(const QString& name); /*! Sets the \a Result tag filter to \a result. */ void setResult(Result result); /*! Sets the \a resultInverted value to \a invert. */ void setResultInverted(bool invert); private: Type m_type; QByteArray m_pattern; QByteArray m_event; QByteArray m_site; QByteArray m_player; QByteArray m_opponent; Chess::Side m_playerSide; QDate m_minDate; QDate m_maxDate; int m_minRound; int m_maxRound; Result m_result; bool m_resultInverted; }; inline PgnGameFilter::Type PgnGameFilter::type() const { return m_type; } inline const char* PgnGameFilter::pattern() const { return m_pattern.constData(); } inline const char* PgnGameFilter::event() const { return m_event.constData(); } inline const char* PgnGameFilter::site() const { return m_site.constData(); } inline const QDate& PgnGameFilter::minDate() const { return m_minDate; } inline const QDate& PgnGameFilter::maxDate() const { return m_maxDate; } inline int PgnGameFilter::minRound() const { return m_minRound; } inline int PgnGameFilter::maxRound() const { return m_maxRound; } inline PgnGameFilter::Result PgnGameFilter::result() const { return m_result; } inline bool PgnGameFilter::isResultInverted() const { return m_resultInverted; } inline const char* PgnGameFilter::player() const { return m_player.constData(); } inline const char* PgnGameFilter::opponent() const { return m_opponent.constData(); } inline Chess::Side PgnGameFilter::playerSide() const { return m_playerSide; } #endif // PGNGAMEFILTER_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/engineprocess.h0000664000175000017500000000165111657223322022616 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef ENGINEPROCESS_H #define ENGINEPROCESS_H #include #ifdef Q_WS_WIN #include "engineprocess_win.h" #else // not Q_WS_WIN #include #define EngineProcess QProcess #endif // not Q_WS_WIN #endif // ENGINEPROCESS_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/openingbook.cpp0000664000175000017500000000740711657223322022624 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "openingbook.h" #include #include #include #include "pgngame.h" #include "pgnstream.h" QDataStream& operator>>(QDataStream& in, OpeningBook* book) { while (!in.status() != QDataStream::Ok) book->readEntry(in); return in; } QDataStream& operator<<(QDataStream& out, const OpeningBook* book) { OpeningBook::Map::const_iterator it; for (it = book->m_map.constBegin(); it != book->m_map.constEnd(); ++it) book->writeEntry(it, out); return out; } bool OpeningBook::read(const QString& filename) { QFile file(filename); if (!file.open(QIODevice::ReadOnly)) return false; m_map.clear(); QDataStream in(&file); in >> this; return !m_map.isEmpty(); } bool OpeningBook::write(const QString& filename) const { QFile file(filename); if (!file.open(QIODevice::WriteOnly)) return false; QDataStream out(&file); out << this; return true; } void OpeningBook::addEntry(const Entry& entry, quint64 key) { Map::iterator it = m_map.find(key); while (it != m_map.end() && it.key() == key) { Entry& tmp = it.value(); if (tmp.move == entry.move) { tmp.weight += entry.weight; return; } ++it; } m_map.insert(key, entry); } int OpeningBook::import(const PgnGame& pgn, int maxMoves) { Q_ASSERT(maxMoves > 0); Chess::Side winner(pgn.result().winner()); int loserMod = -1; int weight = 1; maxMoves = qMin(maxMoves, pgn.moves().size()); int ret = maxMoves; if (!winner.isNull()) { loserMod = int(pgn.startingSide() == winner); weight = 2; ret = (ret - loserMod) / 2 + loserMod; } const QVector& moves = pgn.moves(); for (int i = 0; i < maxMoves; i++) { // Skip the loser's moves if ((i % 2) != loserMod) { Entry entry = { moves.at(i).move, weight }; addEntry(entry, moves.at(i).key); } } return ret; } int OpeningBook::import(PgnStream& in, int maxMoves) { Q_ASSERT(maxMoves > 0); if (!in.isOpen()) return 0; int moveCount = 0; while (in.status() == PgnStream::Ok) { PgnGame game; game.read(in, maxMoves); if (game.moves().isEmpty()) break; moveCount += import(game, maxMoves); } return moveCount; } static quint32 s_rand32() { const quint32 random1 = quint32(qrand()); const quint32 random2 = quint32(qrand()); const quint32 random3 = quint32(qrand()); return random1 ^ (random2 << 15) ^ (random3 << 30); } Chess::GenericMove OpeningBook::move(quint64 key) const { Chess::GenericMove move; // There can be multiple entries/moves with the same key. // We need to find them all to choose the best one QList entries = m_map.values(key); if (entries.size() == 0) return move; // Calculate the total weight of all available moves int totalWeight = 0; foreach (const Entry& entry, entries) totalWeight += entry.weight; if (totalWeight <= 0) return move; // Pick a move randomly, with the highest-weighted move having // the highest probability of getting picked. int pick = s_rand32() % totalWeight; int currentWeight = 0; foreach (const Entry& entry, entries) { currentWeight += entry.weight; if (currentWeight > pick) return entry.move; } return move; } cutechess-20111114+0.4.2+0.0.1/projects/lib/src/playerbuilder.h0000664000175000017500000000321711657223322022615 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef PLAYERBUILDER_H #define PLAYERBUILDER_H class QObject; class ChessPlayer; /*! * \brief A class for constructing new chess players. * * PlayerBuilder's subclasses can create all types of chess players. * This class enables a GameManager object to take control of * constructing, reusing and deleting players, and running multiple * games concurrently, which requires multiple instances of the * same players. * * \sa GameManager */ class LIB_EXPORT PlayerBuilder { public: virtual ~PlayerBuilder() {} /*! * Creates a new player and sets its parent to \a parent. * * \param receiver The receiver of the player's debugging messages. * \param method The receiver's method the \a debugMessage(QString) * signal will connect to. * \param parent The player's parent object. */ virtual ChessPlayer* create(QObject* receiver = 0, const char* method = 0, QObject* parent = 0) const = 0; }; #endif // PLAYERBUILDER_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/pgnstream.h0000664000175000017500000001350611657223322021754 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef PGNSTREAM_H #define PGNSTREAM_H #include #include class QIODevice; namespace Chess { class Board; } /*! * \brief A class for reading games in PGN format from a text stream. * * PgnStream is used for reading PGN games from a QIODevice or a string. * It has its own input methods, and keeps track of the current line * number which can be used to report errors in the games. PgnStream * also has its own Chess::Board object, so that the same board can be * easily used with all the games in the stream. The chess variant can * be changed at any time, so it's possible to read PGN streams that * contain games of multiple variants. * * \sa PgnGame * \sa OpeningBook */ class LIB_EXPORT PgnStream { public: /*! The current status of the PGN stream. */ enum Status { Ok, //!< The stream is operating normally. ReadPastEnd //!< The stream has read past the end of the data. }; /*! The type of a PGN token. */ enum TokenType { /*! Empty token (ie. nothing was read). */ NoToken, /*! Move string in Standard Algebraic Notation. */ PgnMove, /*! Move number before a full move. */ PgnMoveNumber, /*! * PGN tag. * \note The token string does NOT contain the opening * and closing square brackets. */ PgnTag, /*! * PGN comment. * \note The token string does NOT contain the opening * and closing brackets. */ PgnComment, /*! One-line PGN comment. */ PgnLineComment, /*! NAG code (Numeric Annotation Glyph). */ PgnNag, /*! Game result. */ PgnResult, /*! Unknown token. */ Unknown }; /*! * Creates a new PgnStream. * * A device or a string must be set before the stream * can be used. */ explicit PgnStream(const QString& variant = "standard"); /*! Creates a PgnStream that operates on \a device. */ explicit PgnStream(QIODevice* device, const QString& variant = "standard"); /*! Creates a PgnStream that operates on \a string. */ explicit PgnStream(const QByteArray* string, const QString& variant = "standard"); /*! Destructs the PgnStream object. */ ~PgnStream(); /*! * Returns the Board object which is used to verify the moves * and FEN strings in the stream. */ Chess::Board* board(); /*! Returns the assigned device, or 0 if no device is in use. */ QIODevice* device() const; /*! Sets the current device to \a device. */ void setDevice(QIODevice* device); /*! Returns the assigned string, or 0 if no string is in use. */ const QByteArray* string() const; /*! Sets the current string to \a string. */ void setString(const QByteArray* string); /*! Returns the chess variant. */ QString variant() const; /*! * Sets the chess variant to \a variant. * Returns true if successfull. */ bool setVariant(const QString& variant); /*! Returns true if the stream is open. */ bool isOpen() const; /*! Returns the current position in the stream. */ qint64 pos() const; /*! Returns the current line number. */ qint64 lineNumber() const; /*! Resets the stream to its default state. */ void reset(); /*! Reads one character and returns it. */ char readChar(); /*! * Rewinds the stream position by one character, which means that * the next time readChar() is called, nothing is read and the * buffer character is returned. * * \note Only one character is kept in the buffer, so calling * this method multiple times in a row has the same effect as * calling it just once. */ void rewindChar(); /*! * Rewinds back to the start of input. * This is equivalent to calling \a seek(0). */ void rewind(); /*! * Seeks to position \a pos in the device, and sets the current * line number to \a lineNumber. * Returns true if successfull. */ bool seek(qint64 pos, qint64 lineNumber = 1); /*! Returns the status of the stream. */ Status status() const; /*! * Seeks to the next game in the stream. Returns true if a game * is available; otherwise returns false. * * This function must be called once for each new game, or * nothing can be parsed. * * \sa readNext() */ bool nextGame(); /*! * Reads the next token and returns its type. * * Returns PgnStream::NoToken if a token is not available. * \sa nextGame(), tokenType(), tokenString() */ TokenType readNext(); /*! * Returns the current token as string. * \sa tokenType() */ QByteArray tokenString() const; /*! * Returns the type of the current token. * \sa tokenString() */ TokenType tokenType() const; /*! Returns the name of the current PGN tag. */ QByteArray tagName() const; /*! Returns the value of the current PGN tag. */ QByteArray tagValue() const; private: enum Phase { OutOfGame, InTags, InGame }; void parseUntil(const char* chars); void parseTag(); void parseComment(char opBracket); Chess::Board* m_board; qint64 m_pos; qint64 m_lineNumber; char m_lastChar; QByteArray m_tokenString; QByteArray m_tagName; QByteArray m_tagValue; TokenType m_tokenType; QIODevice* m_device; const QByteArray* m_string; Status m_status; Phase m_phase; }; #endif // PGNSTREAM_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/moveevaluation.cpp0000664000175000017500000000225511657223322023344 0ustar oliveroliver#include "moveevaluation.h" MoveEvaluation::MoveEvaluation() : m_isBookEval(false), m_depth(0), m_score(0), m_time(0), m_nodeCount(0) { } bool MoveEvaluation::isEmpty() const { if (m_depth == 0 && m_score == 0 && m_time < 500 && m_nodeCount == 0) return true; return false; } bool MoveEvaluation::isBookEval() const { return m_isBookEval; } int MoveEvaluation::depth() const { return m_depth; } int MoveEvaluation::score() const { return m_score; } int MoveEvaluation::time() const { return m_time; } int MoveEvaluation::nodeCount() const { return m_nodeCount; } QString MoveEvaluation::pv() const { return m_pv; } void MoveEvaluation::clear() { m_isBookEval = false; m_depth = 0; m_score = 0; m_time = 0; m_nodeCount = 0; m_pv.clear(); } void MoveEvaluation::setBookEval(bool isBookEval) { m_isBookEval = isBookEval; } void MoveEvaluation::setDepth(int depth) { m_depth = depth; } void MoveEvaluation::setScore(int score) { m_score = score; } void MoveEvaluation::setTime(int time) { m_time = time; } void MoveEvaluation::setNodeCount(int nodeCount) { m_nodeCount = nodeCount; } void MoveEvaluation::setPv(const QString& pv) { m_pv = pv; } cutechess-20111114+0.4.2+0.0.1/projects/lib/src/moveevaluation.h0000664000175000017500000000372111657223322023010 0ustar oliveroliver#ifndef MOVEEVALUATION_H #define MOVEEVALUATION_H #include /*! * \brief Evaluation data for a chess move. * * Before chess engines send their move they usually print information * about the moves they're thinking of, how many nodes they've searched, * the search depth, etc. This class stores that information so that it * could be saved in a PGN file or displayed on the screen. * * From human players we can only get the move time. */ class LIB_EXPORT MoveEvaluation { public: /*! Constructs an empty MoveEvaluation object. */ MoveEvaluation(); /*! Returns true if the evaluation is empty. */ bool isEmpty() const; /*! Returns true if the evaluation points to a book move. */ bool isBookEval() const; /*! * How many plies were searched? * \note For human players this is always 0. */ int depth() const; /*! * Score in centipawns from the player's point of view. * \note For human player this always 0. */ int score() const; /*! Move time in milliseconds. */ int time() const; /*! * How many nodes were searched? * \note For human players this is always 0. */ int nodeCount() const; /*! * The principal variation. * This is a sequence of moves that an engine * expects to be played next. * \note For human players this is always empty. */ QString pv() const; /*! Resets everything to zero. */ void clear(); /*! Sets book evaluation. */ void setBookEval(bool isBookEval); /*! Sets the search depth to \a depth. */ void setDepth(int depth); /*! Sets the score to \a score. */ void setScore(int score); /*! Sets the move time to \a time. */ void setTime(int time); /*! Sets the node count to \a nodeCount. */ void setNodeCount(int nodeCount); /*! Sets the principal variation to \a pv. */ void setPv(const QString& pv); private: bool m_isBookEval; int m_depth; int m_score; int m_time; int m_nodeCount; QString m_pv; }; #endif // MOVEEVALUATION_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/xboardengine.cpp0000664000175000017500000003025211657223322022751 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "xboardengine.h" #include #include #include #include #include #include #include "timecontrol.h" #include "enginespinoption.h" #include "enginetextoption.h" static QString msToXboardTime(int ms) { int sec = ms / 1000; QString number = QString::number(sec / 60); if (sec % 60 != 0) number += QString(":%1").arg(sec % 60, 2, 10, QChar('0')); return number; } static const int s_infiniteSec = 86400; XboardEngine::XboardEngine(QObject* parent) : ChessEngine(parent), m_forceMode(false), m_drawOnNextMove(false), m_ftName(false), m_ftPing(false), m_ftSetboard(false), m_ftTime(true), m_ftUsermove(false), m_ftReuse(true), m_gotResult(false), m_lastPing(0), m_notation(Chess::Board::LongAlgebraic), m_initTimer(new QTimer(this)) { m_initTimer->setSingleShot(true); m_initTimer->setInterval(2000); connect(m_initTimer, SIGNAL(timeout()), this, SLOT(initialize())); addVariant("standard"); setName("XboardEngine"); } void XboardEngine::startProtocol() { // Tell the engine to turn on xboard mode write("xboard"); // Tell the engine that we're using Xboard protocol 2 write("protover 2"); // Give the engine 2 seconds to reply to the protover command. // This is how Xboard deals with protocol 1 engines. m_initTimer->start(); } void XboardEngine::initialize() { if (state() == Starting) { onProtocolStart(); emit ready(); } } static QString variantFromXboard(const QString& str) { if (str == "normal") return "standard"; return str; } static QString variantToXboard(const QString& str) { if (str == "standard") return "normal"; return str; } void XboardEngine::startGame() { m_drawOnNextMove = false; m_gotResult = false; m_forceMode = false; m_nextMove = Chess::Move(); write("new"); if (board()->variant() != "standard") write("variant " + variantToXboard(board()->variant())); if (board()->isRandomVariant() || board()->fenString() != board()->defaultFenString()) { if (m_ftSetboard) write("setboard " + board()->fenString()); else qDebug() << name() << "doesn't support the setboard command."; } // Send the time controls const TimeControl* myTc = timeControl(); if (myTc->isInfinite()) write(QString("st %1").arg(s_infiniteSec)); else if (myTc->timePerMove() > 0) write(QString("st %1").arg(myTc->timePerMove() / 1000)); else write(QString("level %1 %2 %3") .arg(myTc->movesPerTc()) .arg(msToXboardTime(myTc->timePerTc())) .arg(myTc->timeIncrement() / 1000)); if (myTc->plyLimit() > 0) write(QString("sd %1").arg(myTc->plyLimit())); // Show thinking write("post"); // Disable pondering write("easy"); setForceMode(true); // Tell the opponent's type and name to the engine if (m_ftName) { if (!opponent()->isHuman()) write("computer"); write("name " + opponent()->name()); } } bool XboardEngine::restartsBetweenGames() const { if (restartMode() == EngineConfiguration::RestartAuto) return !m_ftReuse; return ChessEngine::restartsBetweenGames(); } void XboardEngine::endGame(const Chess::Result& result) { State s = state(); if (s != Thinking && s != Observing) return; if (s != Thinking) m_gotResult = true; stopThinking(); setForceMode(true); write("result " + result.toVerboseString()); ChessEngine::endGame(result); // If the engine can't be pinged, we may have to wait for // for a move or a result, or an error, or whatever. We // would like to extend our middle fingers to every engine // developer who fails to support the ping command. if (!m_ftPing && m_gotResult) finishGame(); } void XboardEngine::finishGame() { if (!m_ftPing && state() == FinishingGame) { // Give the engine enough time to send all pending // output relating to the current game m_gotResult = true; QTimer::singleShot(200, this, SLOT(pong())); } } void XboardEngine::sendTimeLeft() { if (!m_ftTime) return; if (timeControl()->isInfinite()) { write(QString("time %1").arg(s_infiniteSec)); return; } int csLeft = timeControl()->timeLeft() / 10; int ocsLeft = opponent()->timeControl()->timeLeft() / 10; if (csLeft < 0) csLeft = 0; if (ocsLeft < 0) ocsLeft = 0; write(QString("time %1\notim %2").arg(csLeft).arg(ocsLeft)); } void XboardEngine::setForceMode(bool enable) { if (enable && !m_forceMode) { m_forceMode = true; write("force"); // If there's a move pending, and we didn't get the // 'go' command, we'll send the move in force mode. if (!m_nextMove.isNull()) makeMove(m_nextMove); } m_forceMode = enable; } QString XboardEngine::moveString(const Chess::Move& move) { Q_ASSERT(!move.isNull()); // Xboard always uses SAN for castling moves in random variants if (m_notation == Chess::Board::LongAlgebraic && board()->isRandomVariant()) { QString str(board()->moveString(move, Chess::Board::StandardAlgebraic)); if (str.startsWith("O-O")) return str; } return board()->moveString(move, m_notation); } void XboardEngine::makeMove(const Chess::Move& move) { Q_ASSERT(!move.isNull()); QString moveString; if (move == m_nextMove) moveString = m_nextMoveString; else moveString = this->moveString(move); // If we're not in force mode, we'll have to wait for the // 'go' command until the move can be sent to the engine. if (!m_forceMode) { if (m_nextMove.isNull()) { m_nextMove = move; m_nextMoveString = moveString; return; } else if (move != m_nextMove) setForceMode(true); } if (m_ftUsermove) write("usermove " + moveString); else write(moveString); m_nextMove = Chess::Move(); } void XboardEngine::startThinking() { setForceMode(false); sendTimeLeft(); if (m_nextMove.isNull()) write("go"); else makeMove(m_nextMove); } void XboardEngine::onTimeout() { if (m_drawOnNextMove) { Q_ASSERT(state() == Thinking); m_drawOnNextMove = false; qDebug("%s forfeits by invalid draw claim", qPrintable(name())); emitForfeit(Chess::Result::Adjudication); } else ChessEngine::onTimeout(); } void XboardEngine::sendStop() { write("?"); } QString XboardEngine::protocol() const { return "xboard"; } bool XboardEngine::sendPing() { if (!m_ftPing) { if (state() == FinishingGame) return true; return false; } // Ping the engine with a random number. The engine should // later send the number back at us. m_lastPing = (qrand() % 32) + 1; write(QString("ping %1").arg(m_lastPing)); return true; } void XboardEngine::sendQuit() { write("quit"); } void XboardEngine::setFeature(const QString& name, const QString& val) { if (name == "ping") m_ftPing = (val == "1"); else if (name == "setboard") m_ftSetboard = (val == "1"); else if (name == "san") { if (val == "1") m_notation = Chess::Board::StandardAlgebraic; else m_notation = Chess::Board::LongAlgebraic; } else if (name == "usermove") m_ftUsermove = (val == "1"); else if (name == "time") m_ftTime = (val == "1"); else if (name == "reuse") m_ftReuse = (val == "1"); else if (name == "myname") { if (this->name() == "XboardEngine") setName(val); } else if (name == "variants") { clearVariants(); QStringList variants = val.split(','); foreach (const QString& str, variants) { QString variant = variantFromXboard(str.trimmed()); if (!variant.isEmpty()) addVariant(variant); } } else if (name == "name") m_ftName = (val == "1"); else if (name == "memory") { if (val == "1") addOption(new EngineSpinOption("memory", 32, 32, 0, INT_MAX - 1)); } else if (name == "smp") { if (val == "1") addOption(new EngineSpinOption("cores", 1, 1, 0, INT_MAX - 1)); } else if (name == "egt") { QStringList list = val.split(','); foreach (const QString& str, list) { QString egtType = QString("egtpath %1").arg(str.trimmed()); addOption(new EngineTextOption(egtType, QString(), QString())); } } else if (name == "done") { write("accepted done", Unbuffered); m_initTimer->stop(); if (val == "1") initialize(); return; } else { write("rejected " + name, Unbuffered); return; } write("accepted " + name, Unbuffered); } void XboardEngine::parseLine(const QString& line) { const QStringRef command(firstToken(line)); if (command.isEmpty()) return; if (command == "1-0" || command == "0-1" || command == "1/2-1/2" || command == "resign") { if ((state() != Thinking && state() != Observing) || !board()->result().isNone()) { finishGame(); return; } if (command == "1/2-1/2") { if (state() == Thinking) // The engine claims that its next move will draw the game m_drawOnNextMove = true; else { qDebug("%s forfeits by invalid draw claim", qPrintable(name())); emitForfeit(Chess::Result::Adjudication); } return; } if ((command == "1-0" && side() == Chess::Side::White) || (command == "0-1" && side() == Chess::Side::Black)) { qDebug("%s forfeits by invalid victory claim", qPrintable(name())); emitForfeit(Chess::Result::Adjudication); } else emitForfeit(Chess::Result::Resignation); } else if (command.at(0).isDigit()) // principal variation { bool ok = false; int val = 0; QStringRef ref(command); // Search depth QString depth(ref.toString()); if (!(depth.end() - 1)->isDigit()) depth.chop(1); m_eval.setDepth(depth.toInt()); // Evaluation if ((ref = nextToken(ref)).isNull()) return; val = ref.toString().toInt(&ok); if (ok) { if (whiteEvalPov() && side() == Chess::Side::Black) val = -val; m_eval.setScore(val); } // Search time if ((ref = nextToken(ref)).isNull()) return; val = ref.toString().toInt(&ok); if (ok) m_eval.setTime(val * 10); // Node count if ((ref = nextToken(ref)).isNull()) return; val = ref.toString().toInt(&ok); if (ok) m_eval.setNodeCount(val); // Principal variation if ((ref = nextToken(ref, true)).isNull()) return; m_eval.setPv(ref.toString()); return; } const QString args(nextToken(command, true).toString()); if (command == "move") { if (state() != Thinking) { if (state() == FinishingGame) finishGame(); else qDebug() << "Unexpected move from" << name(); return; } Chess::Move move = board()->moveFromString(args); if (move.isNull()) { emitForfeit(Chess::Result::IllegalMove, args); return; } if (m_drawOnNextMove) { m_drawOnNextMove = false; Chess::Result boardResult; board()->makeMove(move); boardResult = board()->result(); board()->undoMove(); // If the engine claimed a draw before this move, the // game must have ended in a draw by now if (!boardResult.isDraw()) { qDebug("%s forfeits by invalid draw claim", qPrintable(name())); emitForfeit(Chess::Result::Adjudication); return; } } emitMove(move); } else if (command == "pong") { if (args.toInt() == m_lastPing) pong(); } else if (command == "feature") { QRegExp rx("\\w+\\s*=\\s*(\"[^\"]*\"|\\d+)"); int pos = 0; QString feature; QStringList list; while ((pos = rx.indexIn(args, pos)) != -1) { list = rx.cap().split('='); if (list.count() != 2) continue; feature = list.at(0).trimmed(); QString val = list.at(1).trimmed(); val.remove('\"'); setFeature(feature, val); pos += rx.matchedLength(); } } else if (command == "Error") { // If the engine complains about an unknown result command, // we can assume that it's safe to finish the game. QString str = args.section(':', 1).trimmed(); if (str.startsWith("result")) finishGame(); } } void XboardEngine::sendOption(const QString& name, const QString& value) { write(name + " " + value); } cutechess-20111114+0.4.2+0.0.1/projects/lib/src/humanplayer.cpp0000664000175000017500000000363611657223322022637 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "humanplayer.h" #include "board/board.h" HumanPlayer::HumanPlayer(QObject* parent) : ChessPlayer(parent) { setState(Idle); setName("Human"); } void HumanPlayer::startGame() { Q_ASSERT(m_bufferMove.isNull()); } void HumanPlayer::startThinking() { if (m_bufferMove.isNull()) return; Chess::Move move(board()->moveFromGenericMove(m_bufferMove)); m_bufferMove = Chess::GenericMove(); if (board()->isLegalMove(move)) emitMove(move); } void HumanPlayer::endGame(const Chess::Result& result) { Q_ASSERT(m_bufferMove.isNull()); ChessPlayer::endGame(result); setState(Idle); } void HumanPlayer::makeMove(const Chess::Move& move) { Q_UNUSED(move); Q_ASSERT(m_bufferMove.isNull()); } bool HumanPlayer::supportsVariant(const QString& variant) const { Q_UNUSED(variant); return true; } bool HumanPlayer::isHuman() const { return true; } void HumanPlayer::onHumanMove(const Chess::GenericMove& move, const Chess::Side& side) { if (side != this->side()) return; Q_ASSERT(m_bufferMove.isNull()); if (state() != Thinking) { if (state() == Observing) m_bufferMove = move; emit wokeUp(); return; } Chess::Move tmp(board()->moveFromGenericMove(move)); Q_ASSERT(board()->isLegalMove(tmp)); emitMove(tmp); } cutechess-20111114+0.4.2+0.0.1/projects/lib/src/pgnstream.cpp0000664000175000017500000001562711657223322022315 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "pgnstream.h" #include #include #include #include PgnStream::PgnStream(const QString& variant) : m_board(0), m_pos(0), m_lineNumber(1), m_tokenType(NoToken), m_device(0), m_string(0), m_status(Ok), m_phase(OutOfGame) { setVariant(variant); } PgnStream::PgnStream(QIODevice* device, const QString& variant) : m_board(0) { setVariant(variant); setDevice(device); } PgnStream::PgnStream(const QByteArray* string, const QString& variant) : m_board(0) { setVariant(variant); setString(string); } PgnStream::~PgnStream() { delete m_board; } void PgnStream::reset() { m_pos = 0; m_lineNumber = 1; m_tokenString.clear(); m_tagName.clear(); m_tagValue.clear(); m_tokenType = NoToken; m_device = 0; m_string = 0; m_status = Ok; m_phase = OutOfGame; } Chess::Board* PgnStream::board() { return m_board; } QIODevice* PgnStream::device() const { return m_device; } void PgnStream::setDevice(QIODevice* device) { Q_ASSERT(device != 0); reset(); m_device = device; } const QByteArray* PgnStream::string() const { return m_string; } void PgnStream::setString(const QByteArray* string) { Q_ASSERT(string != 0); reset(); m_string = string; } QString PgnStream::variant() const { Q_ASSERT(m_board != 0); return m_board->variant(); } bool PgnStream::setVariant(const QString& variant) { if (m_board != 0 && m_board->variant() == variant) return true; if (!Chess::BoardFactory::variants().contains(variant)) return false; delete m_board; m_board = Chess::BoardFactory::create(variant); Q_ASSERT(m_board != 0); return true; } bool PgnStream::isOpen() const { return (m_device && m_device->isOpen()) || m_string; } qint64 PgnStream::pos() const { if (m_device) return m_device->pos(); return m_pos; } qint64 PgnStream::lineNumber() const { return m_lineNumber; } char PgnStream::readChar() { char c; if (m_device) { if (!m_device->getChar(&m_lastChar)) { m_status = ReadPastEnd; return 0; } c = m_lastChar; } else if (m_string && m_pos < m_string->size()) { c = m_string->at(m_pos++); } else { m_status = ReadPastEnd; return 0; } if (c == '\n') m_lineNumber++; return c; } void PgnStream::rewind() { seek(0); } void PgnStream::rewindChar() { Q_ASSERT(pos() > 0); char c; if (m_device) { c = m_lastChar; m_device->ungetChar(m_lastChar); m_lastChar = 0; } else if (m_string) c = m_string->at(m_pos--); else return; if (c == '\n') m_lineNumber--; } bool PgnStream::seek(qint64 pos, qint64 lineNumber) { if (pos < 0) return false; bool ok = false; if (m_device) { ok = m_device->seek(pos); m_pos = 0; } else if (m_string) { ok = pos < m_string->size(); m_pos = pos; } if (!ok) return false; m_status = Ok; m_lineNumber = lineNumber; m_lastChar = 0; m_phase = OutOfGame; return true; } PgnStream::Status PgnStream::status() const { return m_status; } void PgnStream::parseUntil(const char* chars) { Q_ASSERT(chars != 0); char c; while ((c = readChar()) != 0) { if (strchr(chars, c)) break; m_tokenString.append(c); } } void PgnStream::parseTag() { bool inQuotes = false; int phase = 0; char c; m_tagName.clear(); m_tagValue.clear(); while ((c = readChar()) != 0) { if (!inQuotes && c == ']') break; if (c == '\n' || c == '\r') break; m_tokenString.append(c); switch (phase) { case 0: if (!isspace(c)) { phase++; m_tagName.append(c); } break; case 1: if (!isspace(c)) m_tagName.append(c); else phase++; break; case 2: if (!isspace(c)) { phase++; if (c == '\"') inQuotes = true; else m_tagValue.append(c); } break; case 3: if (inQuotes) { if (c == '\"') { inQuotes = false; phase++; } else m_tagValue.append(c); } else if (!isspace(c)) m_tagValue.append(c); break; default: break; } } } void PgnStream::parseComment(char opBracket) { int level = 1; char clBracket = (opBracket == '(') ? ')' : '}'; char c; while ((c = readChar()) != 0) { if (c == opBracket) level++; else if (c == clBracket && --level <= 0) break; m_tokenString.append(c); } } bool PgnStream::nextGame() { char c; while ((c = readChar()) != 0) { if (c == '[') { rewindChar(); m_phase = InTags; return true; } } return false; } PgnStream::TokenType PgnStream::readNext() { if (m_phase == OutOfGame) return NoToken; m_tokenType = NoToken; m_tokenString.clear(); char c; while ((c = readChar()) != 0) { switch (c) { case ' ': case '\t': case '\n': case '\r': case '.': break; case '%': // Escape mechanism (skip this line) parseUntil("\n\r"); m_tokenString.clear(); break; case '[': if (m_phase != InTags) { rewindChar(); m_phase = OutOfGame; return NoToken; } m_tokenType = PgnTag; parseTag(); return m_tokenType; case '(': case '{': m_tokenType = PgnComment; parseComment(c); return m_tokenType; case ';': m_tokenType = PgnLineComment; parseUntil("\n\r"); return m_tokenType; case '$': // NAG (Numeric Annotation Glyph) m_tokenType = PgnNag; parseUntil(" \t\n\r"); return m_tokenType; case '*': // Unfinished game m_tokenType = PgnResult; m_tokenString = "*"; m_phase = OutOfGame; return m_tokenType; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '0': // Move number or result m_tokenString.append(c); parseUntil(". \t\n\r"); if (m_tokenString == "1-0" || m_tokenString == "0-1" || m_tokenString == "1/2-1/2") { m_tokenType = PgnResult; m_phase = OutOfGame; } else { if (m_tokenString.endsWith('.')) m_tokenString.chop(1); m_tokenType = PgnMoveNumber; m_phase = InGame; } return m_tokenType; default: m_tokenType = PgnMove; m_tokenString.append(c); parseUntil(" \t\n\r"); m_phase = InGame; return m_tokenType; } } return NoToken; } QByteArray PgnStream::tokenString() const { return m_tokenString; } PgnStream::TokenType PgnStream::tokenType() const { return m_tokenType; } QByteArray PgnStream::tagName() const { return m_tagName; } QByteArray PgnStream::tagValue() const { return m_tagValue; } cutechess-20111114+0.4.2+0.0.1/projects/lib/src/pgngame.cpp0000664000175000017500000002113011657223322021715 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "pgngame.h" #include #include #include #include "board/boardfactory.h" #include "pgnstream.h" PgnStream& operator>>(PgnStream& in, PgnGame& game) { game.read(in); return in; } QTextStream& operator<<(QTextStream& out, const PgnGame& game) { game.write(out); return out; } PgnGame::PgnGame() : m_startingSide(Chess::Side::White) { } bool PgnGame::isNull() const { return (m_tags.isEmpty() && m_moves.isEmpty()); } void PgnGame::clear() { m_startingSide = Chess::Side(); m_tags.clear(); m_moves.clear(); } const QVector& PgnGame::moves() const { return m_moves; } void PgnGame::addMove(const MoveData& data) { m_moves.append(data); } Chess::Board* PgnGame::createBoard() const { Chess::Board* board = Chess::BoardFactory::create(variant()); if (board == 0) return 0; bool ok = true; QString fen(startingFenString()); if (!fen.isEmpty()) ok = board->setFenString(fen); else { board->reset(); ok = !board->isRandomVariant(); } if (!ok) { delete board; return 0; } return board; } bool PgnGame::parseMove(PgnStream& in) { if (m_tags.isEmpty()) { qDebug() << "No tags found"; return false; } Chess::Board* board(in.board()); // If the FEN string wasn't already set by the FEN tag, // set the board when we get the first move if (m_moves.isEmpty()) { QString tmp(m_tags.value("Variant")); if (!tmp.isEmpty() && !in.setVariant(tmp)) { qDebug() << "Unknown variant:" << tmp; return false; } board = in.board(); if (tmp.isEmpty() && board->variant() != "standard") m_tags["Variant"] = board->variant(); tmp = m_tags.value("FEN"); if (tmp.isEmpty()) { if (board->isRandomVariant()) { qDebug() << "Missing FEN tag"; return false; } tmp = board->defaultFenString(); } if (!board->setFenString(tmp)) { qDebug() << "Invalid FEN string:" << tmp; return false; } m_startingSide = board->startingSide(); } const QString str(in.tokenString()); Chess::Move move(board->moveFromString(str)); if (move.isNull()) { qDebug() << "Illegal move:" << str; return false; } MoveData md = { board->key(), board->genericMove(move), str, QString() }; addMove(md); board->makeMove(move); return true; } bool PgnGame::read(PgnStream& in, int maxMoves) { clear(); if (!in.nextGame()) return false; while (in.status() == PgnStream::Ok) { bool stop = false; switch (in.readNext()) { case PgnStream::PgnTag: m_tags[in.tagName()] = in.tagValue(); break; case PgnStream::PgnMove: stop = !parseMove(in) || m_moves.size() >= maxMoves; break; case PgnStream::PgnResult: { const QString str(in.tokenString()); QString& tag = m_tags["Result"]; if (!tag.isEmpty() && str != tag) qDebug() << "Line" << in.lineNumber() << ": The termination " "marker is different from the result tag"; tag = str; } stop = true; break; case PgnStream::PgnNag: { bool ok; int nag = in.tokenString().toInt(&ok); if (!ok || nag < 0 || nag > 255) qDebug() << "Invalid NAG:" << in.tokenString(); } break; case PgnStream::NoToken: stop = true; break; default: break; } if (stop) break; } if (m_tags.isEmpty()) return false; m_tags["PlyCount"] = QString::number(m_moves.size()); return true; } static void writeTag(QTextStream& out, const QString& tag, const QString& value) { if (!value.isEmpty()) out << "[" << tag << " \"" << value << "\"]\n"; else out << "[" << tag << " \"?\"]\n"; } void PgnGame::write(QTextStream& out, PgnMode mode) const { if (m_tags.isEmpty()) return; // The seven tag roster QStringList roster; roster << "Event" << "Site" << "Date" << "Round" << "White" << "Black" << "Result"; foreach (const QString& tag, roster) writeTag(out, tag, m_tags.value(tag)); // Other supported tags if (mode == Verbose) { QMap::const_iterator it; for (it = m_tags.constBegin(); it != m_tags.constEnd(); ++it) { if (!roster.contains(it.key()) && !it.value().isEmpty()) writeTag(out, it.key(), it.value()); } } else if (mode == Minimal && m_tags.contains("FEN")) { writeTag(out, "FEN", m_tags["FEN"]); writeTag(out, "SetUp", m_tags["SetUp"]); } QString str; int lineLength = 0; int movenum = 0; int side = m_startingSide; for (int i = 0; i < m_moves.size(); i++) { const MoveData& data = m_moves.at(i); str.clear(); if (side == Chess::Side::White || i == 0) str = QString::number(++movenum) + ". "; str += data.moveString; if (mode == Verbose && !data.comment.isEmpty()) str += QString(" {%1}").arg(data.comment); // Limit the lines to 80 characters if (lineLength == 0 || lineLength + str.size() >= 80) { out << "\n" << str; lineLength = str.size(); } else { out << " " << str; lineLength += str.size() + 1; } side = !side; } str = m_tags.value("Result"); if (lineLength + str.size() >= 80) out << "\n" << str << "\n\n"; else out << " " << str << "\n\n"; } bool PgnGame::write(const QString& filename, PgnMode mode) const { if (m_tags.isEmpty()) return false; QFile file(filename); if (!file.open(QIODevice::Append)) return false; QTextStream out(&file); write(out, mode); return true; } QString PgnGame::tagValue(const QString& tag) const { return m_tags.value(tag); } QString PgnGame::event() const { return m_tags.value("Event"); } QString PgnGame::site() const { return m_tags.value("Site"); } QDate PgnGame::date() const { return QDate::fromString(m_tags.value("Date"), "yyyy.MM.dd"); } int PgnGame::round() const { return m_tags.value("Round").toInt(); } QString PgnGame::playerName(Chess::Side side) const { if (side == Chess::Side::White) return m_tags.value("White"); else if (side == Chess::Side::Black) return m_tags.value("Black"); return QString(); } Chess::Result PgnGame::result() const { return Chess::Result(m_tags.value("Result")); } QString PgnGame::variant() const { if (m_tags.contains("Variant")) return m_tags.value("Variant"); return "standard"; } Chess::Side PgnGame::startingSide() const { return m_startingSide; } QString PgnGame::startingFenString() const { return m_tags.value("FEN"); } void PgnGame::setTag(const QString& tag, const QString& value) { m_tags[tag] = value; } void PgnGame::setEvent(const QString& event) { m_tags["Event"] = event; } void PgnGame::setSite(const QString& site) { m_tags["Site"] = site; } void PgnGame::setDate(const QDate& date) { m_tags["Date"] = date.toString("yyyy.MM.dd"); } void PgnGame::setRound(int round) { m_tags["Round"] = QString::number(round); } void PgnGame::setPlayerName(Chess::Side side, const QString& name) { if (side == Chess::Side::White) m_tags["White"] = name; else if (side == Chess::Side::Black) m_tags["Black"] = name; } void PgnGame::setResult(const Chess::Result& result) { m_tags["Result"] = result.toShortString(); switch (result.type()) { case Chess::Result::Adjudication: m_tags["Termination"] = "adjudication"; break; case Chess::Result::Timeout: m_tags["Termination"] = "time forfeit"; break; case Chess::Result::Disconnection: m_tags["Termination"] = "abandoned"; break; case Chess::Result::NoResult: m_tags["Termination"] = "unterminated"; break; default: m_tags.remove("Termination"); break; } } void PgnGame::setVariant(const QString& variant) { if (variant == "standard") m_tags.remove("Variant"); else m_tags["Variant"] = variant; } void PgnGame::setStartingSide(Chess::Side side) { m_startingSide = side; } void PgnGame::setStartingFenString(Chess::Side side, const QString& fen) { m_startingSide = side; if (fen.isEmpty()) { m_tags.remove("FEN"); m_tags.remove("SetUp"); } else { m_tags["FEN"] = fen; m_tags["SetUp"] = "1"; } } void PgnGame::setResultDescription(const QString& description) { if (description.isEmpty() || m_moves.isEmpty()) return; QString& comment = m_moves.last().comment; if (!comment.isEmpty()) comment += ", "; comment += description; } cutechess-20111114+0.4.2+0.0.1/projects/lib/src/openingbook.h0000664000175000017500000000707111657223322022266 0ustar oliveroliver#ifndef OPENING_BOOK_H #define OPENING_BOOK_H #include #include #include "board/genericmove.h" class QString; class QDataStream; class PgnGame; class PgnStream; /*! * \brief A collection of opening moves for chess. * * OpeningBook is a container (binary tree) class for opening moves that * can be played by the GUI. When the game goes "out of book", control * of the game is transferred to the players. * * The opening book can be stored externally in a binary file. When it's needed, * it is loaded in memory, and positions can be found quickly by searching * the book for Zobrist keys that match the current board position. */ class LIB_EXPORT OpeningBook { public: /*! Destroys the opening book. */ virtual ~OpeningBook() {} /*! * Imports a PGN game. * * \param pgn The game to import. * \param maxMoves The maximum number of halfmoves that * can be imported. * * Returns the number of moves imported. */ int import(const PgnGame& pgn, int maxMoves); /*! * Imports PGN games from a stream. * * \param in The PGN stream that contains the games. * \param maxMoves The maximum number of halfmoves per game * that can be imported. * * Returns the number of moves imported. */ int import(PgnStream& in, int maxMoves); /*! * Returns a move that can be played in a position where the * Zobrist key is \a key. * * If no matching moves are found, an empty (illegal) move is * returned. * * If there are multiple matches, a random, weighted move is * returned. Popular moves have a higher probablity of being * selected than unpopular ones. */ Chess::GenericMove move(quint64 key) const; /*! * Reads a book from \a filename. * Returns true if successfull. */ bool read(const QString& filename); /*! * Writes the book to \a filename. * Returns true if successfull. */ bool write(const QString& filename) const; protected: friend LIB_EXPORT QDataStream& operator>>(QDataStream& in, OpeningBook* book); friend LIB_EXPORT QDataStream& operator<<(QDataStream& out, const OpeningBook* book); /*! * \brief An entry in the opening book. * * \note Each entry is paired with a Zobrist key. * \note The book file may not use the same structure * for the entries. */ struct Entry { /*! A book move. */ Chess::GenericMove move; /*! * A weight or score, usually based on popularity * of the move. The higher the weight, the more * likely the move will be played. */ quint16 weight; }; /*! The type of binary tree. */ typedef QMultiMap Map; /*! Adds a new entry to the book. */ void addEntry(const Entry& entry, quint64 key); /*! * Reads a new book entry from \a in. * * The implementation must call addEntry() to add the * entry to the book. */ virtual void readEntry(QDataStream& in) = 0; /*! Writes the key and entry pointed to by \a it, to \a out. */ virtual void writeEntry(const Map::const_iterator& it, QDataStream& out) const = 0; private: Map m_map; }; /*! * Reads a book from a data stream. * * \note Multiple book files can be appended to the same * OpeningBook object. */ extern LIB_EXPORT QDataStream& operator>>(QDataStream& in, OpeningBook* book); /*! * Writes a book to a data stream. * * \warning Do not write multiple OpeningBook objects to the same * data stream, because the books are likely to have duplicate * entries. */ extern LIB_EXPORT QDataStream& operator<<(QDataStream& out, const OpeningBook* book); #endif // OPENING_BOOK_H cutechess-20111114+0.4.2+0.0.1/projects/lib/src/chessengine.cpp0000664000175000017500000002072611657223322022604 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "chessengine.h" #include #include #include #include #include #include "engineoption.h" int ChessEngine::s_count = 0; QStringRef ChessEngine::nextToken(const QStringRef& previous, bool untilEnd) { const QString* str = previous.string(); if (str == 0) return QStringRef(); int i; int start = -1; int firstPos = previous.position() + previous.size(); for (i = firstPos; i < str->size(); i++) { if (str->at(i).isSpace()) { if (start == -1) continue; break; } else if (start == -1) { start = i; if (untilEnd) { int end = str->size(); while (str->at(--end).isSpace()) ; i = end + 1; break; } } } if (start == -1) return QStringRef(); return QStringRef(str, start, i - start); } QStringRef ChessEngine::firstToken(const QString& str, bool untilEnd) { return nextToken(QStringRef(&str, 0, 0), untilEnd); } ChessEngine::ChessEngine(QObject* parent) : ChessPlayer(parent), m_id(s_count++), m_pingState(NotStarted), m_pinging(false), m_whiteEvalPov(false), m_pingTimer(new QTimer(this)), m_quitTimer(new QTimer(this)), m_idleTimer(new QTimer(this)), m_ioDevice(0), m_restartMode(EngineConfiguration::RestartAuto) { m_pingTimer->setSingleShot(true); m_pingTimer->setInterval(10000); connect(m_pingTimer, SIGNAL(timeout()), this, SLOT(onPingTimeout())); m_quitTimer->setSingleShot(true); m_quitTimer->setInterval(2000); connect(m_quitTimer, SIGNAL(timeout()), this, SLOT(onQuitTimeout())); m_idleTimer->setSingleShot(true); m_idleTimer->setInterval(10000); connect(m_idleTimer, SIGNAL(timeout()), this, SLOT(onIdleTimeout())); } ChessEngine::~ChessEngine() { qDeleteAll(m_options); } QIODevice* ChessEngine::device() const { return m_ioDevice; } void ChessEngine::setDevice(QIODevice* device) { Q_ASSERT(device != 0); m_ioDevice = device; m_ioDevice->setParent(this); connect(m_ioDevice, SIGNAL(readyRead()), this, SLOT(onReadyRead())); connect(m_ioDevice, SIGNAL(readChannelFinished()), this, SLOT(onCrashed())); } void ChessEngine::applyConfiguration(const EngineConfiguration& configuration) { if (!configuration.name().isEmpty()) setName(configuration.name()); foreach (const QString& str, configuration.initStrings()) write(str); foreach (EngineOption* option, configuration.options()) setOption(option->name(), option->value()); m_whiteEvalPov = configuration.whiteEvalPov(); m_restartMode = configuration.restartMode(); } void ChessEngine::addOption(EngineOption* option) { Q_ASSERT(option != 0); m_options.append(option); } EngineOption* ChessEngine::getOption(const QString& name) const { foreach (EngineOption* option, m_options) { if (option->alias() == name || option->name() == name) return option; } return 0; } void ChessEngine::setOption(const QString& name, const QVariant& value) { if (state() == Starting || state() == NotStarted) { m_optionBuffer[name] = value; return; } EngineOption* option = getOption(name); if (option == 0) { qDebug() << this->name() << "doesn't have option" << name; return; } if (!option->isValid(value)) { qDebug() << "Invalid value for option" << name << ":" << value.toString(); return; } option->setValue(value); sendOption(option->name(), value.toString()); } QList ChessEngine::options() const { return m_options; } QStringList ChessEngine::variants() const { return m_variants; } void ChessEngine::addVariant(const QString& variant) { if (!m_variants.contains(variant)) m_variants << variant; } void ChessEngine::clearVariants() { m_variants.clear(); } void ChessEngine::start() { if (state() != NotStarted) return; m_pinging = false; setState(Starting); flushWriteBuffer(); startProtocol(); m_pinging = true; } void ChessEngine::onProtocolStart() { m_pinging = false; setState(Idle); Q_ASSERT(isReady()); flushWriteBuffer(); QMap::const_iterator i = m_optionBuffer.constBegin(); while (i != m_optionBuffer.constEnd()) { setOption(i.key(), i.value()); ++i; } m_optionBuffer.clear(); } void ChessEngine::go() { if (state() == Observing) ping(); ChessPlayer::go(); } EngineConfiguration::RestartMode ChessEngine::restartMode() const { return m_restartMode; } bool ChessEngine::restartsBetweenGames() const { return m_restartMode == EngineConfiguration::RestartOn; } bool ChessEngine::whiteEvalPov() const { return m_whiteEvalPov; } void ChessEngine::endGame(const Chess::Result& result) { ChessPlayer::endGame(result); if (restartsBetweenGames()) quit(); else ping(); } bool ChessEngine::isHuman() const { return false; } bool ChessEngine::isReady() const { if (m_pinging) return false; return ChessPlayer::isReady(); } bool ChessEngine::supportsVariant(const QString& variant) const { return m_variants.contains(variant); } void ChessEngine::stopThinking() { if (state() == Thinking && !m_pinging) { m_idleTimer->start(); sendStop(); } } void ChessEngine::onIdleTimeout() { m_idleTimer->stop(); if (state() != Thinking || m_pinging) return; m_writeBuffer.clear(); kill(); emitForfeit(Chess::Result::StalledConnection); } void ChessEngine::kill() { if (state() == Disconnected) return; m_pinging = false; m_pingTimer->stop(); m_writeBuffer.clear(); disconnect(m_ioDevice, SIGNAL(readChannelFinished()), this, SLOT(onCrashed())); m_ioDevice->close(); ChessPlayer::kill(); } void ChessEngine::onTimeout() { stopThinking(); } void ChessEngine::ping() { if (m_pinging || state() == NotStarted || state() == Disconnected || !sendPing()) return; m_pinging = true; m_pingState = state(); m_pingTimer->start(); } void ChessEngine::pong() { if (!m_pinging) return; m_pingTimer->stop(); m_pinging = false; flushWriteBuffer(); if (state() == FinishingGame) { if (m_pingState == FinishingGame) { setState(Idle); m_pingState = Idle; } // If the status changed while waiting for a ping response, then // ping again to make sure that we can move on to the next game. else { ping(); return; } } emit ready(); } void ChessEngine::onPingTimeout() { qDebug() << "Engine" << name() << "failed to respond to ping"; m_pinging = false; m_writeBuffer.clear(); kill(); emitForfeit(Chess::Result::StalledConnection); } void ChessEngine::write(const QString& data, WriteMode mode) { if (state() == Disconnected) return; if (state() == NotStarted || (m_pinging && mode == Buffered)) { m_writeBuffer.append(data); return; } Q_ASSERT(m_ioDevice->isWritable()); emit debugMessage(QString(">%1(%2): %3") .arg(name()) .arg(m_id) .arg(data)); m_ioDevice->write(data.toAscii() + "\n"); } void ChessEngine::onReadyRead() { while (m_ioDevice->isReadable() && m_ioDevice->canReadLine()) { m_idleTimer->stop(); QString line = QString(m_ioDevice->readLine()); if (line.endsWith('\n')) line.chop(1); if (line.endsWith('\r')) line.chop(1); if (line.isEmpty()) continue; emit debugMessage(QString("<%1(%2): %3") .arg(name()) .arg(m_id) .arg(line)); parseLine(line); } } void ChessEngine::flushWriteBuffer() { if (m_pinging || state() == NotStarted) return; foreach (const QString& line, m_writeBuffer) write(line); m_writeBuffer.clear(); } void ChessEngine::onQuitTimeout() { Q_ASSERT(state() != Disconnected); disconnect(m_ioDevice, SIGNAL(readChannelFinished()), this, SLOT(onQuitTimeout())); if (!m_quitTimer->isActive()) kill(); else m_quitTimer->stop(); ChessPlayer::quit(); } void ChessEngine::quit() { if (!m_ioDevice || !m_ioDevice->isOpen() || state() == Disconnected) return ChessPlayer::quit(); disconnect(m_ioDevice, SIGNAL(readChannelFinished()), this, SLOT(onCrashed())); connect(m_ioDevice, SIGNAL(readChannelFinished()), this, SLOT(onQuitTimeout())); sendQuit(); m_quitTimer->start(); } cutechess-20111114+0.4.2+0.0.1/projects/lib/src/engineprocess_win.cpp0000664000175000017500000001744711657223322024040 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #include "engineprocess_win.h" #include #include #include #include "pipereader_win.h" EngineProcess::EngineProcess(QObject* parent) : QIODevice(parent), m_started(false), m_finished(false), m_exitCode(0), m_exitStatus(EngineProcess::NormalExit), m_inWrite(INVALID_HANDLE_VALUE), m_outRead(INVALID_HANDLE_VALUE), m_reader(0) { } EngineProcess::~EngineProcess() { if (m_started) { qWarning("EngineProcess: Destroyed while process is still running."); kill(); waitForFinished(); } cleanup(); } int EngineProcess::exitCode() const { return (int)m_exitCode; } EngineProcess::ExitStatus EngineProcess::exitStatus() const { return m_exitStatus; } qint64 EngineProcess::bytesAvailable() const { qint64 n = QIODevice::bytesAvailable(); if (!m_started) return n; return m_reader->bytesAvailable() + n; } bool EngineProcess::canReadLine() const { if (!m_started) return QIODevice::canReadLine(); return m_reader->canReadLine() || QIODevice::canReadLine(); } void EngineProcess::killHandle(HANDLE* handle) { if (*handle == INVALID_HANDLE_VALUE) return; CloseHandle(*handle); *handle = INVALID_HANDLE_VALUE; } void EngineProcess::cleanup() { if (m_reader != 0) { if (m_reader->isRunning()) { qWarning("EngineProcess: pipe reader was terminated"); m_reader->terminate(); } delete m_reader; m_reader = 0; } killHandle(&m_inWrite); killHandle(&m_outRead); killHandle(&m_processInfo.hProcess); killHandle(&m_processInfo.hThread); m_started = false; } void EngineProcess::close() { if (!m_started) return; emit aboutToClose(); kill(); waitForFinished(-1); cleanup(); QIODevice::close(); } bool EngineProcess::isSequential() const { return true; } void EngineProcess::setWorkingDirectory(const QString& dir) { m_workDir = dir; } static QString quoteString(QString str) { if (!str.contains(' ')) return str; if (!str.startsWith('\"')) str.prepend('\"'); if (!str.endsWith('\"')) str.append('\"'); return str; } static QString commandLine(const QString& prog, const QStringList& args) { QString cmd = QDir::toNativeSeparators(quoteString(prog)); foreach (const QString& arg, args) cmd += ' ' + quoteString(arg); return cmd; } void EngineProcess::start(const QString& program, const QStringList& arguments, OpenMode mode) { if (m_started) close(); m_started = false; m_finished = false; m_exitCode = 0; m_exitStatus = NormalExit; // Temporary handles for the child process' end of the pipes HANDLE outWrite; HANDLE inRead; // Security attributes. Use the same one for both pipes. SECURITY_ATTRIBUTES saAttr; saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; CreatePipe(&m_outRead, &outWrite, &saAttr, 0); CreatePipe(&inRead, &m_inWrite, &saAttr, 0); STARTUPINFO startupInfo; ZeroMemory(&startupInfo, sizeof(startupInfo)); startupInfo.cb = sizeof(startupInfo); startupInfo.hStdError = outWrite; startupInfo.hStdOutput = outWrite; startupInfo.hStdInput = inRead; startupInfo.dwFlags |= STARTF_USESTDHANDLES; // Call DuplicateHandle with a NULL target to get non-inheritable // handles for the parent process' ends of the pipes DuplicateHandle(GetCurrentProcess(), m_outRead, // child's stdout read end GetCurrentProcess(), NULL, // no target 0, // flags FALSE, // not inheritable DUPLICATE_SAME_ACCESS); // same handle access DuplicateHandle(GetCurrentProcess(), m_inWrite, // child's stdin write end GetCurrentProcess(), NULL, // no target 0, // flags FALSE, // not inheritable DUPLICATE_SAME_ACCESS); // same handle access BOOL ok = FALSE; QString cmd = commandLine(program, arguments); QString wdir = QDir::toNativeSeparators(m_workDir); ZeroMemory(&m_processInfo, sizeof(m_processInfo)); #ifdef UNICODE ok = CreateProcessW(NULL, (WCHAR*)cmd.utf16(), NULL, // process attributes NULL, // thread attributes TRUE, // inherit handles CREATE_NEW_PROCESS_GROUP, // creation flags NULL, // environment wdir.isEmpty() ? NULL : (WCHAR*)wdir.utf16(), &startupInfo, &m_processInfo); #else // not UNICODE ok = CreateProcessA(NULL, cmd.toLocal8Bit().data(), NULL, // process attributes NULL, // thread attributes TRUE, // inherit handles CREATE_NEW_PROCESS_GROUP, // creation flags NULL, // environment wdir.isEmpty() ? NULL : wdir.toLocal8Bit().data(), &startupInfo, &m_processInfo); #endif // not UNICODE m_started = (bool)ok; if (ok) { // Close the child process' ends of the pipes to make sure // that ReadFile and WriteFile will return when the child // terminates and closes its pipes killHandle(&outWrite); killHandle(&inRead); // Start reading input from the child m_reader = new PipeReader(m_outRead, this); connect(m_reader, SIGNAL(finished()), this, SLOT(onFinished())); connect(m_reader, SIGNAL(finished()), this, SIGNAL(readChannelFinished())); connect(m_reader, SIGNAL(readyRead()), this, SIGNAL(readyRead())); m_reader->start(); // Make QIODevice aware that the device is now open QIODevice::open(mode); } else cleanup(); } void EngineProcess::start(const QString& program, OpenMode mode) { QStringList args; QRegExp rx("((?:[^\\s\"]+)|(?:\"(?:\\\\\"|[^\"])*\"))"); int pos = 0; while ((pos = rx.indexIn(program, pos)) != -1) { args << rx.cap(); pos += rx.matchedLength(); } if (args.isEmpty()) return; QString prog = args.first(); args.removeFirst(); start(prog, args, mode); } void EngineProcess::kill() { if (m_started) TerminateProcess(m_processInfo.hProcess, 0xf291); } void EngineProcess::onFinished() { if (!m_started || m_finished) return; if (GetExitCodeProcess(m_processInfo.hProcess, &m_exitCode) && m_exitCode != STILL_ACTIVE) { m_finished = true; m_exitStatus = NormalExit; if (m_exitCode != 0) m_exitStatus = CrashExit; Q_ASSERT(m_reader == 0 || m_reader->isFinished()); cleanup(); emit finished((int)m_exitCode, m_exitStatus); } } bool EngineProcess::waitForFinished(int msecs) { if (!m_started) return true; DWORD dwWait; if (msecs == -1) dwWait = INFINITE; else dwWait = msecs; DWORD ret = WaitForSingleObject(m_processInfo.hProcess, dwWait); if (ret == WAIT_OBJECT_0) { // The blocking ReadFile call in the pipe reader should // return now that the pipes are closed. But if it doesn't // happen, the pipe reader will be terminated violently // after the timeout. m_reader->wait(10000); onFinished(); return true; } return false; } bool EngineProcess::waitForStarted(int msecs) { // Don't wait here because CreateProcess already did the waiting Q_UNUSED(msecs); return m_started; } QString EngineProcess::workingDirectory() const { return m_workDir; } qint64 EngineProcess::readData(char* data, qint64 maxSize) { if (!m_started) return -1; return m_reader->readData(data, maxSize); } qint64 EngineProcess::writeData(const char* data, qint64 maxSize) { if (!m_started) return -1; DWORD dwWritten = 0; if (!WriteFile(m_inWrite, data, (DWORD)maxSize, &dwWritten, 0)) return -1; return (qint64)dwWritten; } cutechess-20111114+0.4.2+0.0.1/projects/lib/src/engineconfiguration.h0000664000175000017500000001201011657223322023776 0ustar oliveroliver/* This file is part of Cute Chess. Cute Chess is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Cute Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cute Chess. If not, see . */ #ifndef ENGINE_CONFIGURATION_H #define ENGINE_CONFIGURATION_H #include #include class EngineOption; /*! * \brief The EngineConfiguration class defines a chess engine configuration. * * \sa EngineConfigurationModel */ class LIB_EXPORT EngineConfiguration { public: /*! * The modes that determine whether the engine * will be restarted between games. */ enum RestartMode { RestartAuto, //!< The engine decides whether to restart RestartOn, //!< The engine is always restarted between games RestartOff //!< The engine is never restarted between games }; /*! Creates an empty chess engine configuration. */ EngineConfiguration(); /*! * Creates a new chess engine configuration with specified name, * command and protocol settings. */ EngineConfiguration(const QString& name, const QString& command, const QString& protocol); /*! Creates a new chess engine configuration from a QVariant. */ EngineConfiguration(const QVariant& variant); /*! Creates a new chess engine configuration from \a other. */ EngineConfiguration(const EngineConfiguration& other); /*! Destroys the engine configuration. */ ~EngineConfiguration(); /*! * Converts the object into a QVariant. * * This makes it easy to serialize EngineConfiguration * objects with QJson. */ QVariant toVariant() const; /*! * Sets the engine's name. * * \sa name() */ void setName(const QString& name); /*! * Sets the command which is used to launch the engine. * * \sa command() */ void setCommand(const QString& command); /*! * Sets the working directory the engine uses. * * \sa workingDirectory() */ void setWorkingDirectory(const QString& workingDir); /*! * Sets the communication protocol the engine uses. * * \sa protocol() */ void setProtocol(const QString& protocol); /*! * Returns the engine's name. * * \sa setName() */ QString name() const; /*! * Returns the command which is used to launch the engine. * * \sa setCommand() */ QString command() const; /*! * Returns the working directory the engine uses. * * \sa setWorkingDirectory() */ QString workingDirectory() const; /*! * Returns the communication protocol the engine uses. * * \sa setProtocol() */ QString protocol() const; /*! Returns the command line arguments sent to the engine. */ QStringList arguments() const; /*! Sets the command line arguments sent to the engine. */ void setArguments(const QStringList& arguments); /*! Adds new command line argument. */ void addArgument(const QString& argument); /*! Returns the initialization strings sent to the engine. */ QStringList initStrings() const; /*! Sets the initialization strings sent to the engine. */ void setInitStrings(const QStringList& initStrings); /*! Adds new initialization string. */ void addInitString(const QString& initString); /*! * Returns a list of the chess variants the engine can play. * * Returns a list containing variant \a "standard" by default. */ QStringList supportedVariants() const; /*! Sets the list of supported variants to \a variants. */ void setSupportedVariants(const QStringList& variants); /*! Returns the options sent to the engine. */ QList options() const; /*! Sets the options sent to the engine. */ void setOptions(const QList& options); /*! Adds new option. */ void addOption(EngineOption* option); /*! Returns true if evaluation is from white's point of view. */ bool whiteEvalPov() const; /*! Sets white evaluation point of view. */ void setWhiteEvalPov(bool whiteEvalPov); /*! * Returns the restart mode. * The default value is \a RestartAuto. */ RestartMode restartMode() const; /*! Sets the restart mode to \a mode. */ void setRestartMode(RestartMode mode); /*! * Assigns \a other to this engine configuration and returns * a reference to this object. */ EngineConfiguration& operator=(const EngineConfiguration& other); private: QString m_name; QString m_command; QString m_workingDirectory; QString m_protocol; QStringList m_arguments; QStringList m_initStrings; QStringList m_variants; QList m_options; bool m_whiteEvalPov; RestartMode m_restartMode; }; #endif // ENGINE_CONFIGURATION_H cutechess-20111114+0.4.2+0.0.1/projects/lib/lib.pri0000664000175000017500000000024011657223322020265 0ustar oliveroliverINCLUDEPATH += $$PWD/src LIBS += -lcutechess -L$$PWD win32:!static { DEFINES += LIB_EXPORT="__declspec(dllimport)" } else { DEFINES += LIB_EXPORT="" } cutechess-20111114+0.4.2+0.0.1/projects/lib/3rdparty/0000775000175000017500000000000011657223322020557 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/projects/lib/3rdparty/README0000664000175000017500000000010011657223322021426 0ustar oliveroliverThird-party libraries used by Cute Chess should be placed here. cutechess-20111114+0.4.2+0.0.1/projects/lib/tests/0000775000175000017500000000000011657223322020151 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/projects/lib/tests/tests.pri0000664000175000017500000000016311657223322022027 0ustar oliveroliverTEMPLATE = app win32:config += CONSOLE CONFIG += qtestlib include(../lib.pri) OBJECTS_DIR = .obj MOC_DIR = .moc cutechess-20111114+0.4.2+0.0.1/projects/lib/tests/tests.pro0000664000175000017500000000005011657223322022030 0ustar oliveroliverTEMPLATE = subdirs SUBDIRS = chessboard cutechess-20111114+0.4.2+0.0.1/projects/lib/tests/chessboard/0000775000175000017500000000000011657223322022266 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/projects/lib/tests/chessboard/chessboard.pro0000664000175000017500000000010311657223322025117 0ustar oliveroliverinclude(../tests.pri) TARGET = tst_board SOURCES += tst_board.cpp cutechess-20111114+0.4.2+0.0.1/projects/lib/tests/chessboard/tst_board.cpp0000664000175000017500000001552411657223322024762 0ustar oliveroliver#include #include #include class tst_Board: public QObject { Q_OBJECT public: tst_Board(); private slots: void zobristKeys_data() const; void zobristKeys(); void moveStrings_data() const; void moveStrings(); void perft_data() const; void perft(); void cleanupTestCase(); private: void setVariant(const QString& variant); Chess::Board* m_board; }; tst_Board::tst_Board() : m_board(0) { } void tst_Board::cleanupTestCase() { delete m_board; } void tst_Board::setVariant(const QString& variant) { if (m_board == 0 || m_board->variant() != variant) { delete m_board; m_board = Chess::BoardFactory::create(variant); } QVERIFY(m_board != 0); } static quint64 perftVal(Chess::Board* board, int depth) { quint64 nodeCount = 0; QVector moves(board->legalMoves()); if (depth == 1 || moves.size() == 0) return moves.size(); QVector::const_iterator it; for (it = moves.begin(); it != moves.end(); ++it) { board->makeMove(*it); nodeCount += perftVal(board, depth - 1); board->undoMove(); } return nodeCount; } static quint64 perftRoot(const Chess::Board* board, const Chess::Move& move, int depth) { Chess::Board* tmp = board->copy(); Q_ASSERT(tmp != 0); tmp->makeMove(move); quint64 val = perftVal(tmp, depth - 1); delete tmp; return val; } static quint64 smpPerft(Chess::Board* board, int depth) { QVector moves(board->legalMoves()); if (depth <= 1) return moves.size(); QVector< QFuture > futures; foreach (const Chess::Move& move, moves) futures << QtConcurrent::run(perftRoot, board, move, depth); quint64 nodeCount = 0; foreach (const QFuture& future, futures) nodeCount += future.result(); return nodeCount; } void tst_Board::zobristKeys_data() const { QTest::addColumn("variant"); QTest::addColumn("fen"); QTest::addColumn("key"); QString variant = "standard"; QTest::newRow("startpos") << variant << "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1" << Q_UINT64_C(0x463b96181691fc9c); QTest::newRow("e2e4") << variant << "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3" << Q_UINT64_C(0x823c9b50fd114196); QTest::newRow("e2e4 d7d5") << variant << "rnbqkbnr/ppp1pppp/8/3p4/4P3/8/PPPP1PPP/RNBQKBNR w KQkq d6" << Q_UINT64_C(0x0756b94461c50fb0); QTest::newRow("e2e4 d7d5 e4e5") << variant << "rnbqkbnr/ppp1pppp/8/3pP3/8/8/PPPP1PPP/RNBQKBNR b KQkq -" << Q_UINT64_C(0x662fafb965db29d4); QTest::newRow("e2e4 d7d5 e4e5 f7f5") << variant << "rnbqkbnr/ppp1p1pp/8/3pPp2/8/8/PPPP1PPP/RNBQKBNR w KQkq f6" << Q_UINT64_C(0x22a48b5a8e47ff78); QTest::newRow("e2e4 d7d5 e4e5 f7f5 e1e2") << variant << "rnbqkbnr/ppp1p1pp/8/3pPp2/8/8/PPPPKPPP/RNBQ1BNR b kq -" << Q_UINT64_C(0x652a607ca3f242c1); QTest::newRow("e2e4 d7d5 e4e5 f7f5 e1e2 e8f7") << variant << "rnbq1bnr/ppp1pkpp/8/3pPp2/8/8/PPPPKPPP/RNBQ1BNR w - -" << Q_UINT64_C(0x00fdd303c946bdd9); QTest::newRow("a2a4 b7b5 h2h4 b5b4 c2c4") << variant << "rnbqkbnr/p1pppppp/8/8/PpP4P/8/1P1PPPP1/RNBQKBNR b KQkq c3" << Q_UINT64_C(0x3c8123ea7b067637); QTest::newRow("a2a4 b7b5 h2h4 b5b4 c2c4 b4c3 a1a3") << variant << "rnbqkbnr/p1pppppp/8/8/P6P/R1p5/1P1PPPP1/1NBQKBNR b Kkq -" << Q_UINT64_C(0x5c3f9b829b279560); } void tst_Board::zobristKeys() { QFETCH(QString, variant); QFETCH(QString, fen); QFETCH(quint64, key); setVariant(variant); QVERIFY(m_board->setFenString(fen)); QCOMPARE(m_board->key(), key); } void tst_Board::moveStrings_data() const { QTest::addColumn("variant"); QTest::addColumn("moves"); QTest::addColumn("startfen"); QTest::addColumn("endfen"); QTest::newRow("san") << "standard" << "e4 Nc6 e5 d5 exd6 Be6 Nf3 Qd7 Bb5 O-O-O dxc7 a6 O-O Qxd2 " "cxd8=N Qxc1 Bxc6 Qxd1 Nxb7 Qxf1+ Kxf1 Bxa2 Rxa2 Kc7" << "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1" << "5bnr/1Nk1pppp/p1B5/8/8/5N2/RPP2PPP/1N3K2 w - - 1 13"; QTest::newRow("coord") << "standard" << "e2e4 b8c6 e4e5 d7d5 e5d6 c8e6 g1f3 d8d7 f1b5 e8c8 d6c7 " "a7a6 e1g1 d7d2 c7d8n d2c1 b5c6 c1d1 d8b7 d1f1 g1f1 e6a2 " "a1a2 c8c7" << "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1" << "5bnr/1Nk1pppp/p1B5/8/8/5N2/RPP2PPP/1N3K2 w - - 1 13"; } void tst_Board::moveStrings() { QFETCH(QString, variant); QFETCH(QString, moves); QFETCH(QString, startfen); QFETCH(QString, endfen); setVariant(variant); QVERIFY(m_board->setFenString(startfen)); QStringList moveList = moves.split(' '); foreach (const QString& moveStr, moveList) { Chess::Move move = m_board->moveFromString(moveStr); QVERIFY(m_board->isLegalMove(move)); m_board->makeMove(move); } QCOMPARE(m_board->fenString(), endfen); for (int i = 0; i < moveList.size(); i++) m_board->undoMove(); QCOMPARE(m_board->fenString(), startfen); } void tst_Board::perft_data() const { QTest::addColumn("variant"); QTest::addColumn("fen"); QTest::addColumn("depth"); QTest::addColumn("nodecount"); QString variant = "standard"; QTest::newRow("startpos") << variant << "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1" << 5 << Q_UINT64_C(4865609); QTest::newRow("pos2") << variant << "r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq -" << 4 << Q_UINT64_C(4085603); QTest::newRow("pos3") << variant << "8/3K4/2p5/p2b2r1/5k2/8/8/1q6 b - -" << 2 << Q_UINT64_C(279); QTest::newRow("pos4") << variant << "8/2p5/3p4/KP5r/1R3p1k/8/4P1P1/8 w - -" << 6 << Q_UINT64_C(11030083); variant = "capablanca"; QTest::newRow("gothic startpos") << variant << "rnbqckabnr/pppppppppp/10/10/10/10/PPPPPPPPPP/RNBQCKABNR w KQkq - 0 1" << 4 << Q_UINT64_C(808984); QTest::newRow("goth2") << variant << "r1b1c2rk1/p4a1ppp/1ppq2pn2/3p1p4/3A1Pn3/1PN3PN2/P1PQP1BPPP/3RC2RK1 w - -" << 4 << Q_UINT64_C(7917813); QTest::newRow("goth3") << variant << "r1b2k2nr/p1ppq1ppbp/n1Pcpa2p1/5p4/5P4/1p1PBCPN2/PP1QP1BPPP/RN3KA2R w KQkq -" << 4 << Q_UINT64_C(4869569); variant = "fischerandom"; QTest::newRow("frc1") << variant << "1rk3r1/8/8/8/8/8/8/1RK1R3 w EBgb -" << 2 << Q_UINT64_C(464); QTest::newRow("frc2") << variant << "bnrbnkrq/pppppppp/8/8/8/8/PPPPPPPP/BNRBNKRQ w KQkq - 0 1" << 4 << Q_UINT64_C(233585); QTest::newRow("frc3") << variant << "2rkr3/5PP1/8/5Q2/5q2/8/5pp1/2RKR3 w KQkq - 0 1" << 3 << Q_UINT64_C(71005); variant = "crazyhouse"; QTest::newRow("crazyhouse startpos") << variant << "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w - KQkq - 0 1" << 5 << Q_UINT64_C(4888832); } void tst_Board::perft() { QFETCH(QString, variant); QFETCH(QString, fen); QFETCH(int, depth); QFETCH(quint64, nodecount); setVariant(variant); QVERIFY(m_board->setFenString(fen)); QCOMPARE(smpPerft(m_board, depth), nodecount); } QTEST_MAIN(tst_Board) #include "tst_board.moc" cutechess-20111114+0.4.2+0.0.1/projects/lib/benchmarks/0000775000175000017500000000000011657223322021124 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/projects/lib/benchmarks/pgngame/0000775000175000017500000000000011657223322022542 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/projects/lib/benchmarks/pgngame/tst_pgngame.cpp0000664000175000017500000001142311657223322025557 0ustar oliveroliver#include #include #include class tst_PgnGame: public QObject { Q_OBJECT private slots: void parser_data() const; void parser(); }; void tst_PgnGame::parser_data() const { QTest::addColumn("pgn"); QByteArray pgn; pgn = "[Event \"?\"]\n" "[Site \"Linares\"]\n" "[Date \"1993.??.??\"]\n" "[Round \"0.12\"]\n" "[White \"Karpov,An\"]\n" "[Black \"Kramnik,V\"]\n" "[Result \"1/2-1/2\"]\n" "[ECO \"B13\"]\n\n" "1. c4 c6 2. e4 d5 3. exd5 cxd5 4. d4 Nf6 5. Nc3 Nc6 6. Nf3 Bg4 7. cxd5\n" "Nxd5 8. Qb3 Bxf3 9. gxf3 e6 10. Qxb7 Nxd4 11. Bb5+ Nxb5 12. Qc6+ Ke7\n" "13. Qxb5 Qd7 14. Nxd5+ Qxd5 15. Bg5+ f6 16. Qxd5 exd5 17. Be3 Ke6\n" "18. O-O-O Bb4 19. Rd3 Rhd8 20. a3 Rac8+ 21. Kb1 Bc5 22. Re1 Kd6 23. Rg1\n" "g6 24. Rgd1 Ke6 25. Re1 Bxe3 26. Rdxe3+ Kf5 27. Re7 Kf4 28. R1e3 a5\n" "29. h3 h5 30. R7e6 Kg5 31. Ra6 d4 32. f4+ Kf5 33. Rxa5+ Kxf4 34. Rd3 Ke4\n" "35. Rd2 g5 36. Ra6 f5 37. Re6+ Kf3 38. Re5 Kf4 39. Re6 h4 40. Rd3 g4\n" "41. Rh6 Kg5 42. Rh7 Rc6 43. a4 Rd5 44. a5 Rcd6 45. Ra7 gxh3 46. Rg7+ Kf4\n" "47. Rh7 Ke4 48. Rxh3 Rxa5 49. Kc2 Rb5 50. Re7+ Kf4 51. Rxh4+ Kf3\n" "52. Rh3+ Kxf2 53. Rd3 Rc6+ 54. Kb1 Rb4 55. b3 f4 56. Re4 Rf6 57. Kb2 f3\n" "58. Ka3 Rbb6 59. Rdxd4 Rg6 60. Rd2+ Kg3 61. Re3 Rbe6 62. Rc3 Ra6+\n" "63. Kb2 Rg4 64. Rd8 Rf6 65. Rd2 Rgf4 66. Ka3 Kg4 67. Rf2 Ra6+ 68. Kb2\n" "Rh6 69. Ka3 Rh1 70. Rd3 Kg3 71. Rc2 Rhh4 72. Re3 Rh2 73. Rc8 Kg2\n" "74. Rg8+ Kf1 75. b4 f2 76. Rb3 Rhh4 77. Rgg3 Rd4 78. Ka4 Rhe4 79. Ka5\n" "Rd2 80. Rh3 Ke2 81. Rh2 Ra2+ 82. Kb6 Re6+ 83. Kc5 Rc2+ 84. Kb5 Rh6\n" "85. Rg2 Rf6 86. Rh2 Rh6 87. Rg2 Kf1 88. Rg5 Rf6 89. Rc5 Rd2 90. Rc6 Rf4\n" "91. Rc1+ Kg2 92. Rbb1 Rf8 93. Ka5 Ra2+ 94. Kb6 Rf6+ 95. Kc5 Rf5+ 96. Kb6\n" "Re2 97. b5 Re6+ 98. Ka5 Rfe5 99. Ka4 Re4+ 1/2-1/2\n"; QTest::newRow("game1") << pgn; pgn = "[Event \"CCRL 40/40\"]\n" "[Site \"CCRL\"]\n" "[Date \"2009.03.01\"]\n" "[Round \"164.1.156\"]\n" "[White \"Cheese 1.3\"]\n" "[Black \"Chezzz 1.0.3\"]\n" "[Result \"0-1\"]\n" "[ECO \"C15\"]\n" "[Opening \"French\"]\n" "[Variation \"Winawer (Nimzovich) variation\"]\n" "[PlyCount \"102\"]\n" "[WhiteElo \"2408\"]\n" "1. e4 e6 2. d4 d5 3. Nc3 Bb4 4. Qd3 Ne7 5. Ne2 c5 6. Bg5 f6 7. Bd2 Nbc6 8.\n" "O-O-O {-0.23/13 33s} O-O {+0.03/12 45s} 9. a3 {-0.13/13 28s} c4 {+0.11/13 45s}\n" "10. Qg3 {+0.04/13 46s} Ba5 {+0.20/12 45s} 11. f3 {+0.04/13 45s} a6 {+0.05/12\n" "45s} 12. h4 {+0.17/13 37s} b5 {+0.14/13 45s} 13. h5 {+0.26/13 46s} Bxc3\n" "{+0.31/13 45s} 14. Bxc3 {+0.13/14 44s} a5 {+0.33/13 45s} 15. h6 {+0.24/13 46s}\n" "g6 {+0.42/13 45s} 16. Bd2 {+0.12/14 33s} b4 {+0.50/13 45s} 17. a4 {+0.12/12\n" "29s} b3 {+0.82/13 45s} 18. c3 {-0.36/14 47s} Qd7 {+1.02/15 113s} 19. Bf4\n" "{-0.40/14 48s} Na7 {+1.01/14 42s} 20. Bd6 {-0.70/15 48s} Rf7 {+1.15/14 42s} 21.\n" "Kd2 {-1.08/14 26s} Bb7 {+1.50/14 84s} 22. Bxe7 {-0.50/14 49s} Rxe7 {+1.50/12\n" "20s} 23. Nf4 {-0.73/14 49s} Kh8 {+1.53/13 41s} 24. exd5 {-0.98/13 49s} exd5\n" "{+1.57/13 20s} 25. Nxg6+ {-0.95/14 49s} hxg6 {+2.31/14 21s} 26. Qxg6 {-1.15/15\n" "31s} Qd6 {+2.44/14 43s} 27. Kc1 {-1.92/15 50s} Rg8 {+2.97/14 43s} 28. Qh5\n" "{-2.36/15 50s} Qf4+ {+3.89/15 43s} 29. Kb1 {-3.69/17 36s} Rg5 {+4.02/15 263s}\n" "30. Qh3 {-3.85/16 51s} Qd2 {+3.60/15 26s} 31. Bd3 {-4.28/16 30s} Qxg2 {+3.71/14\n" "23s} 32. Qxg2 {-3.02/16 54s} Rxg2 {+3.81/15 11s} 33. Bf1 {-3.05/16 54s} Rc2\n" "{+3.77/15 25s} 34. Ka1 {-3.49/16 54s} Bc6 {+3.62/14 25s} 35. Bh3 {-3.74/16 30s}\n" "Bxa4 {+3.84/14 25s} 36. Rb1 {-3.80/15 58s} Nb5 {+3.87/14 25s} 37. Bf5 {-4.29/15\n" "38s} Nxc3 {+3.93/15 25s} 38. Bxc2 {-5.02/17 65s} bxc2 {+4.19/14 12s} 39. bxc3\n" "{-5.24/17 65s} cxb1=R+ {+4.76/14 42s} 40. Kxb1 {-5.35/17 32s} Bb3 {+4.76/13\n" "19s} 41. Rh2 {-5.42/18 38s} Re3 {+5.16/14 37s} 42. Kb2 {-6.35/17 21s} Rxf3\n" "{+5.37/14 37s} 43. Rg2 {-6.96/17 38s} Kh7 {+5.51/14 37s} 44. Rh2 {-7.15/20 38s}\n" "f5 {+6.09/14 46s} 45. Re2 {-7.95/16 38s} Kxh6 {+5.96/13 37s} 46. Re6+ {-8.34/16\n" "38s} Kg5 {+6.32/14 37s} 47. Re2 {-8.66/16 38s} Kf4 {+6.66/13 37s} 48. Rg2\n" "{-10.04/17 38s} Ke3 {+8.12/13 37s} 49. Ka3 {-11.44/18 38s} f4 {+9.40/14 37s}\n" "50. Rg5 {-12.37/18 38s} Rf1 {+9.91/13 37s} 51. Re5+ {-16.96/17 38s} Kd3\n" "{+12.91/14 37s 0-1 Adjudication} 0-1\n"; QTest::newRow("game2") << pgn; } void tst_PgnGame::parser() { QFETCH(QByteArray, pgn); PgnStream stream(&pgn); PgnGame game; QBENCHMARK { QVERIFY(game.read(stream)); stream.rewind(); } } QTEST_MAIN(tst_PgnGame) #include "tst_pgngame.moc" cutechess-20111114+0.4.2+0.0.1/projects/lib/benchmarks/pgngame/pgngame.pro0000664000175000017500000000011411657223322024676 0ustar oliveroliverinclude(../benchmarks.pri) TARGET = tst_pgngame SOURCES += tst_pgngame.cpp cutechess-20111114+0.4.2+0.0.1/projects/lib/benchmarks/benchmarks.pro0000664000175000017500000000004511657223322023762 0ustar oliveroliverTEMPLATE = subdirs SUBDIRS = pgngame cutechess-20111114+0.4.2+0.0.1/projects/lib/benchmarks/benchmarks.pri0000664000175000017500000000016311657223322023755 0ustar oliveroliverTEMPLATE = app win32:config += CONSOLE CONFIG += qtestlib include(../lib.pri) OBJECTS_DIR = .obj MOC_DIR = .moc cutechess-20111114+0.4.2+0.0.1/projects/lib/lib.pro0000664000175000017500000000040611657223322020277 0ustar oliveroliverTEMPLATE = lib TARGET = cutechess QT = core DESTDIR = $$PWD win32:!static { DEFINES += LIB_EXPORT="__declspec(dllexport)" } else { DEFINES += LIB_EXPORT="" } include(src/src.pri) include(components/json/src/json.pri) OBJECTS_DIR = .obj MOC_DIR = .moc cutechess-20111114+0.4.2+0.0.1/COPYING0000664000175000017500000007733111657223322015456 0ustar oliveroliver GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS cutechess-20111114+0.4.2+0.0.1/README0000664000175000017500000000036611657223322015275 0ustar oliveroliver Cute Chess - A graphical user interface for chess engines Cute Chess is a graphical user interface built with Qt for chess engines supporting either the Xboard or UCI protocols. Please read the INSTALL file for installation instructions. cutechess-20111114+0.4.2+0.0.1/INSTALL0000664000175000017500000000253411657223322015445 0ustar oliveroliver Installation Cute Chess requires Qt (at least version 4.6) and qmake (the Qt Makefile generator). The current qmake project file doesn't have support for installations. However the main executable has the necessary resources built-in by default so it's the only thing you need to deploy. If you're using Qt Creator to build the sources you can skip the rest of this document. First you need to build Cute Chess' Makefile in either release or debug mode. Release mode is for general program usage and offers the best performance. Debug mode is for debugging Cute Chess. To build the Makefile in release mode: $ qmake -config release or in debug mode: $ qmake -config debug And to build the source: $ make or $ nmake (Visual C++) To build on a Macintosh, add "-spec macx-g++" to the qmake command. Documentation is available as Unix manual pages and in HTML format. Building the documentation in either format requires asciidoc (http://www.methods.co.nz/asciidoc/). $ make doc-man (documentation as Unix manual pages) $ make doc-html (documentation in HTML format) The documentation is built to the "docs" directory. If you want to have an overview of Cute Chess' source you can build the API documentation: $ make doc-api You need doxygen (http://www.doxygen.org/) in order to build the API documentation. cutechess-20111114+0.4.2+0.0.1/TODO0000664000175000017500000000346411657223322015107 0ustar oliveroliver- Add more stuff to the Chess namespace (Game, Player, etc.) chess.h should probably be in lib/src, not lib/src/chessboard - Complete Xboard and UCI support (including the analysis feature) - More unit tests for the Chess library - Better error handling in OpeningBook - Better error handling in PgnGame - FICS support - Tournaments - Add a bunch of bugs to Sloppy, and test it with the gui - Create an engine-testing tool for the gui, which finds out and summarizes the engine's features, and runs tests: - illegal moves - invalid FEN strings - very long strings - invalid time controls (eg. negative time left) - negative minimum search depth - test the ping time - Use ECO codes to determine the opening name for PGN games - EPD tests for engines - Design a file format for tournaments - Provide code examples in documentation - Verify Qt version requirement before release - Use PgnStream for HTTP downloading - Apply for the Qt Ambassador program (application showcase) after first public release: http://qt.nokia.com/qtambassador - Use model testing tools to check validity of all model classes during runtime (http://developer.qt.nokia.com/wiki/Model_Test) User Interface -------------- - (Mac) dropping FEN on Cute Chess' icon in Dock - (Mac) provide Dock menu - (Mac) provide global menubar - Per window dialogs should use QDialog::open() instead of exec() - Moving a piece by selecting (clicking with a mouse) a source and a destination squares - Highlight attacked pieces - Application icon that looks good on Win, Mac, GTK. Examples: Firefox, Arora. Should have (at least) sizes of 512x512, 128x128, 32x32, 16x16 - Analyzing feature. Probably should be placed in its own dock window with a selectable list of engines. - All game information should be editable in Game|Properties. cutechess-20111114+0.4.2+0.0.1/cutechess.pro0000664000175000017500000000124311657223322017120 0ustar oliveroliver# Check Qt version contains(QT_VERSION, ^4\\.[0-5]\\..*) { message("Cannot build Cute Chess with Qt version $${QT_VERSION}.") error("Qt version 4.6 or later is required.") } TEMPLATE = subdirs SUBDIRS = projects # API documentation (Doxygen) doc-api.commands = doxygen docs/api/api.doxygen QMAKE_EXTRA_TARGETS += doc-api # Unix manual pages doc-man.commands += a2x -f manpage docs/cutechess.txt; doc-man.commands += a2x -f manpage docs/cutechess-cli.txt QMAKE_EXTRA_TARGETS += doc-man # html documentation doc-html.commands += asciidoc -b xhtml11 docs/cutechess.txt; doc-html.commands += asciidoc -b xhtml11 docs/cutechess-cli.txt QMAKE_EXTRA_TARGETS += doc-html cutechess-20111114+0.4.2+0.0.1/docs/0000775000175000017500000000000011657223322015340 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/docs/cutechess.txt0000664000175000017500000000146211657223322020072 0ustar oliveroliverCUTECHESS(6) ============ NAME ---- cutechess - A graphical user interface for chess engines SYNOPSIS -------- *cutechess* ['OPTIONS'] DESCRIPTION ----------- Description of Cute Chess. OPTIONS ------- -v:: \--version:: Display the version information. FILES ----- ~/.config/cutechess/cutechess.ini:: User configuration file. /etc/xdg/cutechess/cutechess.ini:: System-wide configuration file. AUTHOR ------ Written by Ilari Pihlajisto and Arto Jonsson . RESOURCES --------- * Source code: * Mailing list: COPYING ------- Copyright \(C) 2008-2011 Ilari Pihlajisto and Arto Jonsson. Free use of this software is granted under the terms of GNU General Public License (GPL). cutechess-20111114+0.4.2+0.0.1/docs/cutechess-cli.txt0000664000175000017500000001116611657223322020641 0ustar oliveroliverCUTECHESS-CLI(6) ================ NAME ---- cutechess-cli - A command-line tool for chess engines matches SYNOPSIS -------- *cutechess-cli* -fcp ['ENGINE OPTIONS'] -scp ['ENGINE OPTIONS'] ['OPTIONS'] *cutechess-cli* -both ['ENGINE OPTIONS'] ['OPTIONS'] DESCRIPTION ----------- Runs chess matches from the command line. OPTIONS ------- \--version:: Display the version information. \--help:: Display help information. \--engines:: Display a list of configured engines and exit. \--protocols:: Display a list of supported chess protocols and exit. \--variants:: Display a list of supported chess variants and exit. -fcp :: Apply to the first engine. -scp :: Apply to the second engine. -both :: Apply to both engines. -variant :: Set chess variant to . -concurrency :: Set the maximum number of concurrent games to . -draw :: Adjudicate the game as a draw if the score of both engines is within centipawns from zero after full moves have been played. -resign :: Adjudicate the game as a loss if an engine's score is at least centipawns below zero for at least consecutive moves. -event :: Set the event name to . -games :: Play games. -debug:: Display all engine input and output. -pgnin :: Use as the opening book in PGN format. -pgndepth :: Set the maximum depth for PGN input to plies. -pgnout [min]:: Save the games to in PGN format. Use the 'min' argument to save in a minimal PGN format. -recover:: Restart crashed engines instead of stopping the match. -repeat:: Play each opening twice so that both players get to play it on both sides. -site :: Set the site / location to . -srand :: Set the random seed for the book move selector to . -wait :: Wait milliseconds between games. The default is 0. ENGINE OPTIONS -------------- conf=:: Use an engine with the name from Cute Chess\' configuration file. name=:: Set the name to . cmd=:: Set the command to . dir=:: Set the working directory to . arg=:: Pass to the engine as a command line argument. initstr=:: Send to the engine's standard input at startup. restart=:: Set the restart mode to which can be: 'auto': the engine decides whether to restart (default) 'on': the engine is always restarted between games 'off': the engine is never restarted between games proto=:: Set the chess protocol to . tc=:: Set the time control to . The format is moves/time+increment, where 'moves' is the number of moves per tc, 'time' is time per tc (either seconds or minutes:seconds), and 'increment' is time increment per move in seconds. Infinite time control can be set with 'tc=inf'. st=:: Set the time limit for each move to seconds. This option can't be used in combination with "tc". timemargin=:: Let engines go milliseconds over the time limit. book=:: Use (Polyglot book file) as the opening book. bookdepth=:: Set the maximum book depth (in fullmoves) to . whitepov:: Invert the engine's scores when it plays black. This option should be used with engines that always report scores from white's perspective. depth=:: Set the search depth limit to plies. nodes=:: Set the node count limit to nodes. option.=:: Set custom engine option to value . EXAMPLES -------- * Play ten games between two Sloppy engines with a time control of 40 moves in 60 seconds. ----------- $ cutechess-cli -both cmd=sloppy proto=xboard tc=40/60 -games 10 ----------- * Use the 'name=Atak' parameter because it's a Xboard protocol 1 engine and doesn't tell its name. * Use the 'dir=C:\atak' parameter to point the location of the executable. * Glaurung can tell its name and is in the PATH variable so only the command is needed. * Set Glaurung to use 1 thread. * Set the time control to 40 moves in one minute and 30 seconds with a one second increment. ----------- $ cutechess-cli -fcp name=Atak cmd=Atak32.exe dir=C:\atak proto=xboard -scp cmd=glaurung proto=uci option.Threads=1 -both tc=40/1:30+1 ----------- AUTHOR ------ Written by Ilari Pihlajisto and Arto Jonsson . RESOURCES --------- * Source code: * Mailing list: COPYING ------- Copyright \(C) 2008-2011 Ilari Pihlajisto and Arto Jonsson. Free use of this software is granted under the terms of GNU General Public License (GPL). cutechess-20111114+0.4.2+0.0.1/docs/api/0000775000175000017500000000000011657223322016111 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/docs/api/README0000664000175000017500000000027611657223322016776 0ustar oliveroliverCute Chess' API documentation will be placed here. You can build it with the "doc-api" target: $ make doc-api Doxygen (http://www.doxygen.org/) is required to build the documentation. cutechess-20111114+0.4.2+0.0.1/docs/api/api.doxygen0000664000175000017500000017441711657223322020277 0ustar oliveroliver# Doxyfile 1.5.8 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = "Cute Chess" # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = "0.1" # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = ./docs/api/ # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, # Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, # Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, Slovene, # Spanish, Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it parses. # With this tag you can assign which parser to use for a given extension. # Doxygen has a built-in mapping, but you can override or extend it using this tag. # The format is ext=language, where ext is a file extension, and language is one of # the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, # Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat # .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), # use: inc=Fortran f=C EXTENSION_MAPPING = # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) # will make doxygen to replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penality. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will rougly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols SYMBOL_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = NO # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespace are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = YES # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = YES # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = YES # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = NO # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = NO # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = NO # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = NO # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. # This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by # doxygen. The layout file controls the global structure of the generated output files # in an output format independent way. The create the layout file that represents # doxygen's defaults, run doxygen with the -l option. You can optionally specify a # file name after the option, if omitted DoxygenLayout.xml will be used as the name # of the layout file. LAYOUT_FILE = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be abled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = ./projects/ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 FILE_PATTERNS = # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = */.obj/* \ */.moc/* \ */.rcc/* \ */tests/* \ */ui_* \ */*_p.* \ */*_win.* \ */*_unix.* # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. # If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. # Doxygen will compare the file name with each pattern and apply the # filter if there is a match. # The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. # Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = NO # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER # are set, an additional index file will be generated that can be used as input for # Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated # HTML documentation. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. # For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's # filter section matches. # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to FRAME, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. Other possible values # for this tag are: HIERARCHIES, which will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list; # ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which # disables this behavior completely. For backwards compatibility with previous # releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE # respectively. GENERATE_TREEVIEW = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. # This is useful # if you want to understand what is going on. # On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse # the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = "./docs/api/qt.tag = http://doc.trolltech.com/latest" # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option is superseded by the HAVE_DOT option below. This is only a # fallback. It is recommended to install and use dot, since it yields more # powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # By default doxygen will write a font called FreeSans.ttf to the output # directory and reference it in all dot files that doxygen generates. This # font does not include all possible unicode characters however, so when you need # these (or just want a differently looking font) you can specify the font name # using DOT_FONTNAME. You need need to make sure dot is able to find the font, # which can be done by putting it in a standard location or by setting the # DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory # containing the font. DOT_FONTNAME = FreeSans # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the output directory to look for the # FreeSans.ttf font (which doxygen will put there itself). If you specify a # different font using DOT_FONTNAME you can set the path where dot # can find it using this tag. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = YES # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Options related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO cutechess-20111114+0.4.2+0.0.1/docs/api/qt.tag0000664000175000017500000051616211657223322017245 0ustar oliveroliver Q3Accel q3accel.html Q3Action q3action.html Q3ActionGroup q3actiongroup.html Q3AsciiBucket q3asciibucket.html Q3AsciiCacheIterator q3asciicacheiterator.html Q3AsciiDictIterator q3asciidictiterator.html Q3BaseBucket q3basebucket.html Q3ButtonGroup q3buttongroup.html Q3CacheIterator q3cacheiterator.html Q3Canvas q3canvas.html Q3CanvasEllipse q3canvasellipse.html Q3CanvasItem q3canvasitem.html RttiValues q3canvasitem.html 8ba52c6d519bd51dc0ec7176da0bb03f Q3CanvasItemList q3canvasitemlist.html Q3CanvasLine q3canvasline.html Q3CanvasPixmap q3canvaspixmap.html Q3CanvasPixmapArray q3canvaspixmaparray.html Q3CanvasPolygon q3canvaspolygon.html Q3CanvasPolygonalItem q3canvaspolygonalitem.html Q3CanvasRectangle q3canvasrectangle.html Q3CanvasSpline q3canvasspline.html Q3CanvasSprite q3canvassprite.html FrameAnimationType q3canvassprite.html 9fda5c9f89122745bab10c22dea7bcef Q3CanvasText q3canvastext.html Q3CanvasView q3canvasview.html Q3CheckListItem q3checklistitem.html Type q3checklistitem.html 2f2e28b09ebf7202a08ea104e6fb6acd ToggleState q3checklistitem.html 40db69158507e74d3e6aa0773f215e03 Q3CheckTableItem q3checktableitem.html Q3ColorDrag q3colordrag.html Q3ComboBox q3combobox.html Q3ComboTableItem q3combotableitem.html Q3CString q3cstring.html Q3DataBrowser q3databrowser.html Boundary q3databrowser.html 3b92a88a3ca611b3acda828e09d8f6cb Q3DataTable q3datatable.html Refresh q3datatable.html dc7106db68554f1873bbb870e61465ec Q3DataView q3dataview.html Q3DateEdit q3dateedit.html Q3DateTimeEdit q3datetimeedit.html Q3DictIterator q3dictiterator.html Q3Dns q3dns.html RecordType q3dns.html 84d0d36d4c45737a8506795772da59bc Q3Dns::MailServer q3dns_1_1mailserver.html Q3Dns::Server q3dns_1_1server.html Q3DnsSocket q3dnssocket.html Q3DockArea q3dockarea.html HandlePosition q3dockarea.html e7a326d366e51de9c93b6465578c419e Q3DockAreaLayout q3dockarealayout.html Q3DockWindow q3dockwindow.html Place q3dockwindow.html 4787895b944f7a42f51b500d5eadd2ef CloseMode q3dockwindow.html 3a4784ae3221a8c836368a4e0a1899f7 Q3DragObject q3dragobject.html Q3DropSite q3dropsite.html Q3FileDialog q3filedialog.html Q3FileIconProvider q3fileiconprovider.html Q3FilePreview q3filepreview.html Q3Ftp q3ftp.html State q3ftp.html c2a028420be4ef0ec960adee51bb4ff8 Error q3ftp.html 6dea201e445788076a30f734ea8efe8e Command q3ftp.html 62abda519fcbdc529cecbebccf08c5cf Q3GCache q3gcache.html KeyType q3gcache.html 9e228513e08dcbaa996d71eb8be70141 Q3GCacheIterator q3gcacheiterator.html Q3GDict q3gdict.html KeyType q3gdict.html e11ee6c3bc204cf10389b6da85f9da3d Q3GDictIterator q3gdictiterator.html Q3GList q3glist.html Q3GListIterator q3glistiterator.html Q3GListStdIterator q3gliststditerator.html Q3Grid q3grid.html Q3GridView q3gridview.html Q3GroupBox q3groupbox.html Q3HBox q3hbox.html Q3HBoxLayout q3hboxlayout.html Q3HButtonGroup q3hbuttongroup.html Q3Header q3header.html Q3Http q3http.html State q3http.html 52c21d29a6247bfe77ab48d42c1b0e5e Error q3http.html 79d68e2ba455b41f3834d008d10a503a Q3HttpHeader q3httpheader.html Q3HttpRequestHeader q3httprequestheader.html Q3HttpResponseHeader q3httpresponseheader.html Q3IconDrag q3icondrag.html Q3IconDragItem q3icondragitem.html Q3IconView q3iconview.html StringComparisonMode q3iconview.html 2e7373b0440a14c37bc73556b2624fc6 Q3IconViewItem q3iconviewitem.html Q3ImageDrag q3imagedrag.html Q3IntBucket q3intbucket.html Q3IntCacheIterator q3intcacheiterator.html Q3IntDictIterator q3intdictiterator.html Q3ListBox q3listbox.html Q3ListBoxItem q3listboxitem.html Q3ListBoxPixmap q3listboxpixmap.html Q3ListBoxText q3listboxtext.html Q3ListView q3listview.html Q3ListViewItem q3listviewitem.html Q3ListViewItemIterator q3listviewitemiterator.html IteratorFlag q3listviewitemiterator.html a5e97030fdbc247a5a317c3647fcbe7e Q3MainWindow q3mainwindow.html Q3MimeSourceFactory q3mimesourcefactory.html Q3MultiLineEdit q3multilineedit.html Q3NetworkOperation q3networkoperation.html Q3NetworkProtocol q3networkprotocol.html State q3networkprotocol.html 01392cbcc1da8f43f69c03f6a79f5d21 Operation q3networkprotocol.html 41bfa2db52e5ba977b95e169a4db1181 ConnectionState q3networkprotocol.html 708ba95cf7d0d622f2d4c478e7f7b548 Error q3networkprotocol.html e45b28299f4ad369551da8ba45230a45 Q3NetworkProtocolFactory q3networkprotocolfactory.html Q3NetworkProtocolFactoryBase q3networkprotocolfactorybase.html Q3PolygonScanner q3polygonscanner.html Edge q3polygonscanner.html a15ba82f02592f09b93619798d4924eb Q3Process q3process.html Communication q3process.html e86e1f10e97e342c337d6b713dd18aff Q3ProgressBar q3progressbar.html Q3ProgressDialog q3progressdialog.html Q3PtrBucket q3ptrbucket.html Q3PtrCollection q3ptrcollection.html Q3PtrDictIterator q3ptrdictiterator.html Q3PtrListIterator q3ptrlistiterator.html Q3RangeControl q3rangecontrol.html Q3ScrollView q3scrollview.html Q3Semaphore q3semaphore.html Q3ServerSocket q3serversocket.html Q3SimpleRichText q3simplerichtext.html Q3SingleCleanupHandler q3singlecleanuphandler.html Q3Socket q3socket.html Error q3socket.html 16472fb77efdedf403045ba0ff0c9939 State q3socket.html dc4ffd0b6efb181b37452c82be6f580f Q3SocketDevice q3socketdevice.html Type q3socketdevice.html 43522765aaf777c455d744ed905f7f9a Protocol q3socketdevice.html 1a431071b2a1e0f4508083b271470981 Error q3socketdevice.html d9dfd48903685dbbd1b33cd63cd5acfd Q3SpinWidget q3spinwidget.html ButtonSymbols q3spinwidget.html 31b36c5d284b658ec37063ad265affb0 Q3SqlCursor q3sqlcursor.html Mode q3sqlcursor.html 85bcfc61beda65dcef5d3f1721eeebe7 Q3SqlEditorFactory q3sqleditorfactory.html Q3SqlForm q3sqlform.html Q3SqlPropertyMap q3sqlpropertymap.html Q3SqlRecordInfo q3sqlrecordinfo.html Q3SqlSelectCursor q3sqlselectcursor.html Q3StoredDrag q3storeddrag.html Q3StrIList q3strilist.html Q3StringBucket q3stringbucket.html Q3StrIVec q3strivec.html Q3StrList q3strlist.html Q3StyleSheet q3stylesheet.html Q3StyleSheetItem q3stylesheetitem.html AdditionalStyleValues q3stylesheetitem.html 0032855d2001bdea6bcdc51eb4af43c9 DisplayMode q3stylesheetitem.html 26c2967d8e0ffd57d697dd80aa011284 VerticalAlignment q3stylesheetitem.html 99869cfc3cdd1ee39f674f1c6d27de7b WhiteSpaceMode q3stylesheetitem.html 78c310b1cd3edb55168a9468c0749992 Margin q3stylesheetitem.html 4525f7a26e2a79da43d382fc2c66bd89 ListStyle q3stylesheetitem.html 8b42726d20167e73ccda16aef11f86f2 Q3SyntaxHighlighter q3syntaxhighlighter.html Q3TabDialog q3tabdialog.html Q3Table q3table.html SelectionMode q3table.html 17a8a64cddc6e0324fcb23dbe86f579c FocusStyle q3table.html ac42c94c76d0708954b67ed2bf8e7d71 EditMode q3table.html 8a3d066192aa309dac178ce073cfa0d1 Q3TableItem q3tableitem.html EditType q3tableitem.html 24a3fab0f2922ca67e0607ef37240bd4 Q3TableSelection q3tableselection.html Q3TextBrowser q3textbrowser.html Q3TextDrag q3textdrag.html Q3TextEdit q3textedit.html Q3TextEditOptimPrivate q3texteditoptimprivate.html TagType q3texteditoptimprivate.html 38cc6e3b81506edbf7e0a4b55e51fcdf Q3TextStream q3textstream.html Encoding q3textstream.html c481ebdd088e6d990340758f008c59fe Q3TimeEdit q3timeedit.html Q3ToolBar q3toolbar.html Q3TSManip q3tsmanip.html Q3UriDrag q3uridrag.html Q3Url q3url.html Q3UrlOperator q3urloperator.html Q3ValueList q3valuelist.html Q3ValueListConstIterator q3valuelistconstiterator.html Q3VBoxLayout q3vboxlayout.html Q3VButtonGroup q3vbuttongroup.html Q3WhatsThis q3whatsthis.html Q3WidgetStack q3widgetstack.html Q3Wizard q3wizard.html QAbstractButton qabstractbutton.html QAbstractEventDispatcher qabstracteventdispatcher.html QAbstractExtensionFactory qabstractextensionfactory.html QAbstractFileEngine qabstractfileengine.html FileFlag qabstractfileengine.html 4387318a25b5d71145c481dc1d7577b4 FileOwner qabstractfileengine.html 14bc410e3e934b65aef3150150afb85f FileTime qabstractfileengine.html 8a33e04cd595d559ad0799ab98fdcd79 Extension qabstractfileengine.html df30cdba816afadbcaef253af7aa3308 QAbstractFileEngine::ExtensionOption qabstractfileengine_1_1extensionoption.html QAbstractFileEngine::ExtensionReturn qabstractfileengine_1_1extensionreturn.html QAbstractFileEngine::MapExtensionOption qabstractfileengine_1_1mapextensionoption.html QAbstractFileEngine::MapExtensionReturn qabstractfileengine_1_1mapextensionreturn.html QAbstractFileEngine::UnMapExtensionOption qabstractfileengine_1_1unmapextensionoption.html QAbstractFileEngineIterator qabstractfileengineiterator.html EntryInfoType qabstractfileengineiterator.html 28358f0fa38c87e4b405c4538def1f7c QAbstractGraphicsShapeItem qabstractgraphicsshapeitem.html QAbstractItemDelegate qabstractitemdelegate.html EndEditHint qabstractitemdelegate.html d6b0cf3991959379d7021bac482d209f QAbstractItemModel qabstractitemmodel.html QAbstractItemView qabstractitemview.html CursorAction qabstractitemview.html 9e17d46c835f633fb60f100adf7d5ce3 State qabstractitemview.html 6ddb0821fb7f882ce34106a923bb3eb9 DropIndicatorPosition qabstractitemview.html 7e069c16c9c35b353211f316212275a6 QAbstractListModel qabstractlistmodel.html QAbstractMessageHandler qabstractmessagehandler.html QAbstractPageSetupDialog qabstractpagesetupdialog.html QAbstractPrintDialog qabstractprintdialog.html QAbstractProxyModel qabstractproxymodel.html QAbstractScrollArea qabstractscrollarea.html QAbstractSlider qabstractslider.html SliderAction qabstractslider.html 53436565cecc4e85998e704a8f5ae41d SliderChange qabstractslider.html e8f323c760a523c96a7213fbf6f72fe3 QAbstractSocket qabstractsocket.html SocketType qabstractsocket.html d5ac7b88a4fc10c5519e3dde68da1bd6 NetworkLayerProtocol qabstractsocket.html 455874240fe227db36eb6118b4af6a20 SocketError qabstractsocket.html cecc50185857fb890476d5b86484feb7 SocketState qabstractsocket.html 0e0649c2321bf5789b2539a02c0a3c7e QAbstractSpinBox qabstractspinbox.html QAbstractTableModel qabstracttablemodel.html QAbstractTextDocumentLayout qabstracttextdocumentlayout.html QAbstractUndoItem qabstractundoitem.html QAbstractUriResolver qabstracturiresolver.html QAbstractXmlNodeModel qabstractxmlnodemodel.html SimpleAxis qabstractxmlnodemodel.html b3c2d946f71537b6a604a2c2ae8bad43 NodeCopySetting qabstractxmlnodemodel.html b354f348f83ad23727204bb687ae5d4a QAbstractXmlReceiver qabstractxmlreceiver.html QAccessible qaccessible.html Event qaccessible.html cc40bfdfc2d4a5dc8108fb6467635a06 StateFlag qaccessible.html 03af0ce96e46716960c5b842bab85346 Text qaccessible.html 4a1fb9b9e005ec967dac33df760ea390 RelationFlag qaccessible.html 386099a04c6f088fb8970cd0df4e8570 Method qaccessible.html 430a40fc04b1c358bd790349f1d5247a QAccessible2Interface qaccessible2interface.html QAccessibleApplication qaccessibleapplication.html QAccessibleBridge qaccessiblebridge.html QAccessibleEditableTextInterface qaccessibleeditabletextinterface.html QAccessibleEvent qaccessibleevent.html QAccessibleInterface qaccessibleinterface.html QAccessibleInterfaceEx qaccessibleinterfaceex.html QAccessibleObject qaccessibleobject.html QAccessibleObjectEx qaccessibleobjectex.html QAccessiblePlugin qaccessibleplugin.html QAccessibleSimpleEditableTextInterface qaccessiblesimpleeditabletextinterface.html QAccessibleTableInterface qaccessibletableinterface.html QAccessibleTextInterface qaccessibletextinterface.html QAccessibleValueInterface qaccessiblevalueinterface.html QAccessibleWidget qaccessiblewidget.html QAccessibleWidgetEx qaccessiblewidgetex.html QAction qaction.html QActionEvent qactionevent.html QActionGroup qactiongroup.html QApplication qapplication.html Type qapplication.html 8f86c58d22c7f245554ee187be7e0a8f ColorSpec qapplication.html 573a3353e4c7eabab4be03133771b7d7 QArgument qargument.html QAssistantClient qassistantclient.html QAtomicPointer qatomicpointer.html QAuthenticator qauthenticator.html QBasicAtomicPointer qbasicatomicpointer.html QBasicTimer qbasictimer.html QBitArray qbitarray.html QBitmap qbitmap.html QBitRef qbitref.html QBool qbool.html QBoxLayout qboxlayout.html QBrush qbrush.html QBuffer qbuffer.html QButtonGroup qbuttongroup.html QByteArray qbytearray.html QByteArrayMatcher qbytearraymatcher.html QByteRef qbyteref.html QCache qcache.html QCalendarWidget qcalendarwidget.html QChar qchar.html SpecialCharacter qchar.html 0ae10b5b6cf1609bee2b8ecb0523bfa5 Category qchar.html 62908095db0c54f35ff2ae928c621a97 Direction qchar.html 54978126be7630b3e85394325a822302 Decomposition qchar.html 13be45046e82a6d2991cef0b7c18d522 Joining qchar.html 086edd55a90ad2cf910ca3ab5fbe7bde CombiningClass qchar.html 4afa2062d86c443e1f2dc9151925c8cb UnicodeVersion qchar.html 5c86755e75fe6775c1003269694e9060 QCharRef qcharref.html QCheckBox qcheckbox.html ToggleState qcheckbox.html 8d5f14f7f1914890bc6d4063dc0b59e2 QChildEvent qchildevent.html QCleanlooksStyle qcleanlooksstyle.html QClipboard qclipboard.html Mode qclipboard.html bbeea2d17ea5254a9f79e77db35fa533 QClipboardEvent qclipboardevent.html QCloseEvent qcloseevent.html QColor qcolor.html Spec qcolor.html 1cc79a12c227638358dc456e8a8e5bb4 QColorDialog qcolordialog.html QColorGroup qcolorgroup.html QColormap qcolormap.html Mode qcolormap.html 484a77968b06a81481590f3ecaa4a2cc QColumnView qcolumnview.html QComboBox qcombobox.html QCommandLinkButton qcommandlinkbutton.html QCommonStyle qcommonstyle.html QCompleter qcompleter.html CompletionMode qcompleter.html 31716b6544428b5e8dc65bb7e8932bcd ModelSorting qcompleter.html 5a608740691124a975ac12eec62889b6 QConicalGradient qconicalgradient.html QConstString qconststring.html QContextMenuEvent qcontextmenuevent.html Reason qcontextmenuevent.html ab2030d4a241180b5d2ff260f16d7dc0 QCoreApplication qcoreapplication.html Encoding qcoreapplication.html b99720198a54d269001a6e990feab856 QCryptographicHash qcryptographichash.html Algorithm qcryptographichash.html 0c5ff8351479093c89d615652444c25e QCursor qcursor.html QCustomEvent qcustomevent.html QDataStream qdatastream.html Version qdatastream.html 18dbd8448c0dfe28a7fa1f746122a542 ByteOrder qdatastream.html 0cc872752a2cc23a0cf2bcb359cdf135 Status qdatastream.html 3fb47dd8c59d1c4399ccd80bd0ad839a QDataWidgetMapper qdatawidgetmapper.html QDateEdit qdateedit.html QDateTime qdatetime.html QDateTimeEdit qdatetimeedit.html QDBusAbstractAdaptor qdbusabstractadaptor.html QDBusAbstractInterface qdbusabstractinterface.html QDBusArgument qdbusargument.html QDBusConnection qdbusconnection.html QDBusConnectionInterface qdbusconnectioninterface.html ServiceQueueOptions qdbusconnectioninterface.html 843286a2e7a1acc7114ca2071bfb688c ServiceReplacementOptions qdbusconnectioninterface.html 8982cd6133fee3da93dfc6b4db96658e RegisterServiceReply qdbusconnectioninterface.html e6d988d335fa2d0cca96ef5c5707d979 QDBusContext qdbuscontext.html QDBusError qdbuserror.html ErrorType qdbuserror.html 627211fc4aa4d26d6131af9f7f8d8fa3 QDBusInterface qdbusinterface.html QDBusMessage qdbusmessage.html MessageType qdbusmessage.html 99ffac3ccf917a669ad01a63336d717b QDBusReply qdbusreply.html QDBusReply< void > qdbusreply_3_01void_01_4.html QDBusServer qdbusserver.html QDBusSignature qdbussignature.html QDBusVariant qdbusvariant.html QDesignerActionEditorInterface qdesigneractioneditorinterface.html QDesignerBrushManagerInterface qdesignerbrushmanagerinterface.html QDesignerComponents qdesignercomponents.html QDesignerContainerExtension qdesignercontainerextension.html QDesignerCustomWidgetInterface qdesignercustomwidgetinterface.html QDesignerDnDItemInterface qdesignerdnditeminterface.html DropType qdesignerdnditeminterface.html 463a00a39bded4843d9b7f5a619dddfd QDesignerDynamicPropertySheetExtension qdesignerdynamicpropertysheetextension.html QDesignerExtraInfoExtension qdesignerextrainfoextension.html QDesignerFormEditorInterface qdesignerformeditorinterface.html QDesignerFormEditorPluginInterface qdesignerformeditorplugininterface.html QDesignerFormWindowCursorInterface qdesignerformwindowcursorinterface.html MoveOperation qdesignerformwindowcursorinterface.html 80dfb1199ca5a074ce55d1df0b4e0b8e MoveMode qdesignerformwindowcursorinterface.html 67daab1bddf76afdef35e16809ac621c QDesignerFormWindowInterface qdesignerformwindowinterface.html FeatureFlag qdesignerformwindowinterface.html 21d8f3250a7a91f74e31a65b07ad098c QDesignerFormWindowManagerInterface qdesignerformwindowmanagerinterface.html QDesignerFormWindowToolInterface qdesignerformwindowtoolinterface.html QDesignerIconCacheInterface qdesignericoncacheinterface.html QDesignerIntegrationInterface qdesignerintegrationinterface.html QDesignerLanguageExtension qdesignerlanguageextension.html QDesignerLayoutDecorationExtension qdesignerlayoutdecorationextension.html InsertMode qdesignerlayoutdecorationextension.html 98202a74234d60a59e817a292264958a QDesignerMemberSheetExtension qdesignermembersheetextension.html QDesignerMetaDataBaseInterface qdesignermetadatabaseinterface.html QDesignerMetaDataBaseItemInterface qdesignermetadatabaseiteminterface.html QDesignerObjectInspectorInterface qdesignerobjectinspectorinterface.html QDesignerPromotionInterface qdesignerpromotioninterface.html QDesignerPropertyEditorInterface qdesignerpropertyeditorinterface.html QDesignerPropertySheetExtension qdesignerpropertysheetextension.html QDesignerResourceBrowserInterface qdesignerresourcebrowserinterface.html QDesignerTaskMenuExtension qdesignertaskmenuextension.html QDesignerWidgetBoxInterface qdesignerwidgetboxinterface.html QDesignerWidgetBoxInterface::Category qdesignerwidgetboxinterface_1_1category.html Type qdesignerwidgetboxinterface_1_1category.html ee2656b109a5d393956e8ac8c8c7c232 QDesignerWidgetBoxInterface::Widget qdesignerwidgetboxinterface_1_1widget.html Type qdesignerwidgetboxinterface_1_1widget.html f956b7197f2d46b99fad09abbde0c55e QDesignerWidgetDataBaseInterface qdesignerwidgetdatabaseinterface.html QDesignerWidgetDataBaseItemInterface qdesignerwidgetdatabaseiteminterface.html QDesignerWidgetFactoryInterface qdesignerwidgetfactoryinterface.html QDesktopServices qdesktopservices.html StandardLocation qdesktopservices.html bf3083c538687b735a2dfd25241966b6 QDesktopWidget qdesktopwidget.html QDial qdial.html QDialog qdialog.html DialogCode qdialog.html ac172ad5a693ffa0e2eb5f3acf42dd41 QDialogButtonBox qdialogbuttonbox.html QDir qdir.html QDirIterator qdiriterator.html IteratorFlag qdiriterator.html 1fcac202675f7ce7bba067bc83ab71b0 QDirModel qdirmodel.html Roles qdirmodel.html 7c5cfbe04f1527b4ed76574670d8a275 qdoc qdoc.html QDockWidget qdockwidget.html QDomAttr qdomattr.html QDomCDATASection qdomcdatasection.html QDomCharacterData qdomcharacterdata.html QDomComment qdomcomment.html QDomDocument qdomdocument.html QDomDocumentFragment qdomdocumentfragment.html QDomDocumentType qdomdocumenttype.html QDomElement qdomelement.html QDomEntity qdomentity.html QDomEntityReference qdomentityreference.html QDomImplementation qdomimplementation.html InvalidDataPolicy qdomimplementation.html 78f0e3d9d6bc72ae5dbb44c9e37301b8 QDomNamedNodeMap qdomnamednodemap.html QDomNode qdomnode.html NodeType qdomnode.html d538c8d6d0bb0415b24e63c70df51e23 EncodingPolicy qdomnode.html 04668bbdc98a1f753c27a8b697f814d9 QDomNodeList qdomnodelist.html QDomNotation qdomnotation.html QDomProcessingInstruction qdomprocessinginstruction.html QDomText qdomtext.html QDoubleSpinBox qdoublespinbox.html QDoubleValidator qdoublevalidator.html Notation qdoublevalidator.html e01895204e1ff2ffe53434a933b89507 QDrag qdrag.html QDragEnterEvent qdragenterevent.html QDragLeaveEvent qdragleaveevent.html QDragMoveEvent qdragmoveevent.html QDragResponseEvent qdragresponseevent.html QDropEvent qdropevent.html Action qdropevent.html 55b456d37dd07a7f511ca9e3c5e7a54e QDynamicPropertyChangeEvent qdynamicpropertychangeevent.html QErrorMessage qerrormessage.html QEvent qevent.html QEventLoop qeventloop.html QEventSizeOfChecker< sizeof(QEvent)> qeventsizeofchecker_3_01sizeof_07qevent_08_4.html QExplicitlySharedDataPointer qexplicitlyshareddatapointer.html QExtensionFactory qextensionfactory.html QExtensionManager qextensionmanager.html QFile qfile.html QFileDialog qfiledialog.html FileMode qfiledialog.html 15798c396f023f117038e02a95b5cc72 AcceptMode qfiledialog.html bc14c6ce2947b973f657421e40ccf667 DialogLabel qfiledialog.html a63be2402ae2f0fa1e7587df140976fc Option qfiledialog.html 85c34b7f6a002e41d24a923484fcacde QFileIconProvider qfileiconprovider.html IconType qfileiconprovider.html 9c0e535f5f3af991357a628a5ce4c87e QFileInfo qfileinfo.html Permission qfileinfo.html 0a405d0218c890bda924688602c90878 QFileOpenEvent qfileopenevent.html QFileSystemModel qfilesystemmodel.html Roles qfilesystemmodel.html 851f56b737ee24c3a83101a61f8ace44 QFileSystemWatcher qfilesystemwatcher.html QFlag qflag.html QFlags qflags.html QFocusEvent qfocusevent.html Reason qfocusevent.html d026b76d53464a35607da42054355eb0 QFocusFrame qfocusframe.html QFont qfont.html QFontComboBox qfontcombobox.html QFontDatabase qfontdatabase.html QFontDialog qfontdialog.html QFontMetrics qfontmetrics.html QFontMetricsF qfontmetricsf.html QForeachContainer qforeachcontainer.html QFormLayout qformlayout.html QFrame qframe.html QFSFileEngine qfsfileengine.html QFtp qftp.html State qftp.html 38883d0a35eb15701fb76f819b144535 Error qftp.html 1b67cf59ac62586c7e16140cb8c47ce6 Command qftp.html 5e69ac550eeddf6bbb7e2b7cb68b440b TransferMode qftp.html 626c30e1717f5df8d1554c016f67b7de TransferType qftp.html 0624b991cc0cf6da224e0f24a9227535 QFuture qfuture.html QFuture::const_iterator qfuture_1_1const__iterator.html QFutureInterface qfutureinterface.html QFutureInterface< void > qfutureinterface_3_01void_01_4.html QFutureInterfaceBase qfutureinterfacebase.html State qfutureinterfacebase.html 596344316ec963f1bf868aad81f2a86b QFutureWatcher qfuturewatcher.html QFutureWatcher< void > qfuturewatcher_3_01void_01_4.html QFutureWatcherBase qfuturewatcherbase.html QGenericArgument qgenericargument.html QGenericReturnArgument qgenericreturnargument.html QGLContext qglcontext.html QGLFormat qglformat.html OpenGLVersionFlag qglformat.html bc05c53155a31a844e0e333fff07c944 QGLFramebufferObject qglframebufferobject.html QGlobalStatic qglobalstatic.html QGlobalStaticDeleter qglobalstaticdeleter.html QGLPixelBuffer qglpixelbuffer.html QGLWidget qglwidget.html QGradient qgradient.html QGraphicsEllipseItem qgraphicsellipseitem.html QGraphicsGridLayout qgraphicsgridlayout.html QGraphicsItem qgraphicsitem.html GraphicsItemFlag qgraphicsitem.html 5b6cd805e9b41b4fc40a31f9d4aa9cc6 CacheMode qgraphicsitem.html 8401c7317653336246896a7443e88b13 Extension qgraphicsitem.html f13cb167724aa6e595147ce4c4f9a158 QGraphicsItemAnimation qgraphicsitemanimation.html QGraphicsItemGroup qgraphicsitemgroup.html QGraphicsLayout qgraphicslayout.html QGraphicsLayoutItem qgraphicslayoutitem.html QGraphicsLinearLayout qgraphicslinearlayout.html QGraphicsLineItem qgraphicslineitem.html QGraphicsPathItem qgraphicspathitem.html QGraphicsPixmapItem qgraphicspixmapitem.html ShapeMode qgraphicspixmapitem.html 26d52ba01c9b48b50ee2a2ae541d649b QGraphicsPolygonItem qgraphicspolygonitem.html QGraphicsProxyWidget qgraphicsproxywidget.html QGraphicsRectItem qgraphicsrectitem.html QGraphicsScene qgraphicsscene.html ItemIndexMethod qgraphicsscene.html adb8e9e72587606e0c878abd0f998e50 SceneLayer qgraphicsscene.html 7d612d5d7cdab11a90c07a8586a587ad QGraphicsSceneContextMenuEvent qgraphicsscenecontextmenuevent.html Reason qgraphicsscenecontextmenuevent.html a4fed077a3a6fa305074026f29f16c33 QGraphicsSceneDragDropEvent qgraphicsscenedragdropevent.html QGraphicsSceneEvent qgraphicssceneevent.html QGraphicsSceneHelpEvent qgraphicsscenehelpevent.html QGraphicsSceneHoverEvent qgraphicsscenehoverevent.html QGraphicsSceneMouseEvent qgraphicsscenemouseevent.html QGraphicsSceneMoveEvent qgraphicsscenemoveevent.html QGraphicsSceneResizeEvent qgraphicssceneresizeevent.html QGraphicsSceneWheelEvent qgraphicsscenewheelevent.html QGraphicsSimpleTextItem qgraphicssimpletextitem.html QGraphicsSvgItem qgraphicssvgitem.html QGraphicsTextItem qgraphicstextitem.html QGraphicsView qgraphicsview.html QGraphicsWidget qgraphicswidget.html qGreater qgreater.html QGridLayout qgridlayout.html QGroupBox qgroupbox.html QHash qhash.html QHash::const_iterator qhash_1_1const__iterator.html QHash::iterator qhash_1_1iterator.html QHBoxLayout qhboxlayout.html QHeaderView qheaderview.html QHelpContentItem qhelpcontentitem.html QHelpContentModel qhelpcontentmodel.html QHelpContentWidget qhelpcontentwidget.html QHelpEngine qhelpengine.html QHelpEngineCore qhelpenginecore.html QHelpEvent qhelpevent.html QHelpIndexModel qhelpindexmodel.html QHelpIndexWidget qhelpindexwidget.html QHelpSearchEngine qhelpsearchengine.html QHelpSearchQuery qhelpsearchquery.html FieldName qhelpsearchquery.html 429c301bccdfb06a28076303e5652b15 QHelpSearchQueryWidget qhelpsearchquerywidget.html QHelpSearchResultWidget qhelpsearchresultwidget.html QHideEvent qhideevent.html QHostAddress qhostaddress.html SpecialAddress qhostaddress.html 19aaf15ec8753e65e4009179253144cc QHostInfo qhostinfo.html HostInfoError qhostinfo.html 73098ab1250de10817242d3dfdbb21d2 QHoverEvent qhoverevent.html QHttp qhttp.html ConnectionMode qhttp.html baf5a9d25b8472eadb4480beacf410d8 State qhttp.html 422e980bf154098de36830b37be1aaf4 Error qhttp.html 2c6cbc067b7d3b90aa028a1f94352ae5 QHttpHeader qhttpheader.html QHttpRequestHeader qhttprequestheader.html QHttpResponseHeader qhttpresponseheader.html QIBaseDriver qibasedriver.html QIBaseResult qibaseresult.html QIcon qicon.html Mode qicon.html 3f3ff41c1f42cc780429a1f09be3a099 State qicon.html 7420b51208274ae0d5df011c71f388fb Size qicon.html 960be594f91a5eac0525cdb30d09497d QIconDragEvent qicondragevent.html QIconEngineV2 qiconenginev2.html QImage qimage.html InvertMode qimage.html d9b80c88c10642b966b73f9e9b4b6d20 Format qimage.html 810aa2990f23c8aa8dc82c59ba11bd8d Endian qimage.html f50c4ef1ebd046b866473029a1d593c4 QImageIOHandler qimageiohandler.html QImageReader qimagereader.html ImageReaderError qimagereader.html 48e6e4652fad7b41f03bfec5c68c68c7 QImageTextKeyLang qimagetextkeylang.html QImageWriter qimagewriter.html ImageWriterError qimagewriter.html 75a14885f19c2378f532af267d1fe437 QInputContext qinputcontext.html QInputContextFactory qinputcontextfactory.html QInputDialog qinputdialog.html QInputEvent qinputevent.html QInputMethodEvent qinputmethodevent.html AttributeType qinputmethodevent.html b47086f75f988816e3c677202492b655 QInputMethodEvent::Attribute qinputmethodevent_1_1attribute.html QInternal qinternal.html PaintDeviceFlags qinternal.html 14a4c68c9d5acd100b6ab7fc3ecfefd8 RelayoutType qinternal.html 753454eeb29c7a1cab637c46c3d71fcf Callback qinternal.html f9ccb74b85a2ed416c158f5d90eaa911 InternalFunction qinternal.html 6483a9a8bea41f45849964799386d78b DockPosition qinternal.html beb34a925c2d73b90e5ef0411680c49b QIntForSize qintforsize.html QIntForSize< 4 > qintforsize_3_014_01_4.html QIntForSize< 8 > qintforsize_3_018_01_4.html QIntForType qintfortype.html QIntValidator qintvalidator.html QIODevice qiodevice.html QIPv6Address qipv6address.html QItemDelegate qitemdelegate.html QItemEditorCreator qitemeditorcreator.html QItemEditorCreatorBase qitemeditorcreatorbase.html QItemEditorFactory qitemeditorfactory.html QItemSelection qitemselection.html QItemSelectionModel qitemselectionmodel.html QKeyEvent qkeyevent.html QKeySequence qkeysequence.html StandardKey qkeysequence.html 15521fc8b42acb57dea8577bbdef3eb5 SequenceMatch qkeysequence.html 56ed3f5dd35f19aeb86d68b9d64c6227 SequenceFormat qkeysequence.html b0e5f353b230fa1c3312fc047d213d12 QLabel qlabel.html QLatin1String qlatin1string.html QLayout qlayout.html QLayoutItem qlayoutitem.html QLayoutIterator qlayoutiterator.html QLCDNumber qlcdnumber.html qLess qless.html QLibrary qlibrary.html QLinearGradient qlineargradient.html QLineEdit qlineedit.html DummyFrame qlineedit.html dc14953da4e15f4832fe6077ed637657 QLineF qlinef.html IntersectType qlinef.html 229dbbfaa621d7515424f7f14d3d5b81 QLinkedList qlinkedlist.html QLinkedList::const_iterator qlinkedlist_1_1const__iterator.html QLinkedList::iterator qlinkedlist_1_1iterator.html QList qlist.html QList::const_iterator qlist_1_1const__iterator.html QList::iterator qlist_1_1iterator.html QListView qlistview.html QListWidget qlistwidget.html QListWidgetItem qlistwidgetitem.html ItemType qlistwidgetitem.html 624145014101a562c0f27e189975292e QLocale qlocale.html Language qlocale.html 76c1777c0d96afce7c47f62ca479d19d Country qlocale.html af06683f6137aef58004e03fd3d43af4 MeasurementSystem qlocale.html 5de94f4c14d159c67f389dae97228481 FormatType qlocale.html 610ad393cd833df62e1db2858bec0cee NumberOption qlocale.html e0507558fdbfe0768bc819989c5ee021 QLocalServer qlocalserver.html QLocalSocket qlocalsocket.html QMacMime qmacmime.html QMacMimeType qmacmime.html cc7794067ebc7ff120a9f7d61eb798b7 QMacPasteboardMime qmacpasteboardmime.html QMacPasteboardMimeType qmacpasteboardmime.html 7e8453ba16915b5edd8e6a8961b95f34 QMainWindow qmainwindow.html QMap qmap.html QMap::const_iterator qmap_1_1const__iterator.html QMap::iterator qmap_1_1iterator.html QMatrix qmatrix.html QMdiArea qmdiarea.html QMdiSubWindow qmdisubwindow.html SubWindowOption qmdisubwindow.html 7d09c25d4744edcdddd67cff4fe60d9e QMenu qmenu.html QMenuBar qmenubar.html DummyFrame qmenubar.html f085eea1a7fb31fe4eee328668886440 Separator qmenubar.html 4cd85a1b25d948d93007946d61d35c71 QMenubarUpdatedEvent qmenubarupdatedevent.html QMessageBox qmessagebox.html QMetaClassInfo qmetaclassinfo.html QMetaEnum qmetaenum.html QMetaMethod qmetamethod.html Access qmetamethod.html 36d5eb5734fead63bb1da34767fb71f0 MethodType qmetamethod.html 7c12a58fa6c8d00cc5f3221dc88ab7e1 Attributes qmetamethod.html a28d465f516f411ed87a2b049a11adef QMetaProperty qmetaproperty.html QMimeData qmimedata.html QModelIndex qmodelindex.html QMotifStyle qmotifstyle.html QMouseEvent qmouseevent.html QMoveEvent qmoveevent.html QMovie qmovie.html QMultiHash qmultihash.html QMultiMap qmultimap.html QMutex qmutex.html RecursionMode qmutex.html 0c63147a8929fd30b4c8e19a84d1f347 QMutexLocker qmutexlocker.html QMYSQLDriver qmysqldriver.html QMYSQLResult qmysqlresult.html QNetworkAccessManager qnetworkaccessmanager.html Operation qnetworkaccessmanager.html ad2428436fcb5aadb95006b53a2f055f QNetworkAddressEntry qnetworkaddressentry.html QNetworkCookie qnetworkcookie.html RawForm qnetworkcookie.html ce047d3461130dd3012f068fe00bf7c2 QNetworkCookieJar qnetworkcookiejar.html QNetworkInterface qnetworkinterface.html InterfaceFlag qnetworkinterface.html 7a703efcbccbc62086594ed91fef103f QNetworkProxy qnetworkproxy.html QNetworkReply qnetworkreply.html QNetworkRequest qnetworkrequest.html KnownHeaders qnetworkrequest.html 03c8cdc6a338025b5eb6b23a36e16cba Attribute qnetworkrequest.html 2553891d72f893e8e7e5e1b338c158c1 CacheLoadControl qnetworkrequest.html ed83bdcb45c3be284c59797b4125d304 QNoDebug qnodebug.html QObject qobject.html QObjectData qobjectdata.html QObjectUserData qobjectuserdata.html QODBCDriver qodbcdriver.html QODBCResult qodbcresult.html QPageSetupDialog qpagesetupdialog.html QPaintDevice qpaintdevice.html PaintDeviceMetric qpaintdevice.html 5a1a008bc2430e392c3bd0b4f8a92002 QPaintEngine qpaintengine.html QPaintEngineState qpaintenginestate.html QPainter qpainter.html QPainterPath qpainterpath.html ElementType qpainterpath.html d5d0eca6eeeb61e79fbe8f7315ba072e QPainterPath::Element qpainterpath_1_1element.html QPainterPathPrivate qpainterpathprivate.html QPainterPathStroker qpainterpathstroker.html QPaintEvent qpaintevent.html QPair qpair.html QPalette qpalette.html QPen qpen.html QPersistentModelIndex qpersistentmodelindex.html QPicture qpicture.html QPictureIO qpictureio.html QPixmap qpixmap.html HBitmapFormat qpixmap.html 38fb1e13d63b9a97c4e3cc1d4f554cd6 ColorMode qpixmap.html 5af00b2cb173d55620235fd2ec1b637b QPlainTextDocumentLayout qplaintextdocumentlayout.html QPlainTextEdit qplaintextedit.html QPlastiqueStyle qplastiquestyle.html QPluginLoader qpluginloader.html QPointF qpointf.html QPolygon qpolygon.html QPolygonF qpolygonf.html QPrintDialog qprintdialog.html QPrinter qprinter.html QPrinterInfo qprinterinfo.html QPrintPreviewDialog qprintpreviewdialog.html QPrintPreviewWidget qprintpreviewwidget.html QProcess qprocess.html ProcessError qprocess.html b29a7a53337c0176974dc6d72c41a6d2 ProcessState qprocess.html 4dddabebd7916b743d6dfc05f23576c9 ProcessChannel qprocess.html 432490c869bb28e2dcbb06d5061b43fc ProcessChannelMode qprocess.html 632383b0b3c2025b2f5c7c0d765481e6 ExitStatus qprocess.html b9e431e6ca1c2e4326c17122c57c73ee QProgressBar qprogressbar.html QProgressDialog qprogressdialog.html QProxyModel qproxymodel.html QPSQLDriver qpsqldriver.html Protocol qpsqldriver.html e67a2903284cedcac40610587f77c735 QPSQLResult qpsqlresult.html QPushButton qpushbutton.html QRadialGradient qradialgradient.html QRadioButton qradiobutton.html QReadLocker qreadlocker.html QReadWriteLock qreadwritelock.html RecursionMode qreadwritelock.html 9e241c5403936b8bd14633ee60430c85 QRectF qrectf.html QRegExp qregexp.html PatternSyntax qregexp.html e22d1bc206dc820fbe6e19bd885c616a CaretMode qregexp.html 60b49033013a4b1d9c9d83f3b887ec05 QRegExpValidator qregexpvalidator.html QRegion qregion.html RegionType qregion.html ab3bf6ea3bf2046f4e6d6352029d5b4e QResizeEvent qresizeevent.html QResource qresource.html QReturnArgument qreturnargument.html QRubberBand qrubberband.html Shape qrubberband.html 0a9d1cf61b82315e6a045c1149c4b552 QScriptable qscriptable.html QScriptClass qscriptclass.html QueryFlag qscriptclass.html 9d88686c80385797280205be4c9f21e1 QScriptClassPropertyIterator qscriptclasspropertyiterator.html QScriptContext qscriptcontext.html ExecutionState qscriptcontext.html 045fa4738e8052eb25dfaf8ec0765075 Error qscriptcontext.html 8803efd71490edfaf64ecb675a8f8a8c QScriptContextInfo qscriptcontextinfo.html FunctionType qscriptcontextinfo.html 7ae804f3237e2d077e03c4f80e4d4270 QScriptEngineAgent qscriptengineagent.html Extension qscriptengineagent.html df41c5f8f2316874462eb60dde8a8bf8 QScriptExtensionPlugin qscriptextensionplugin.html QScriptString qscriptstring.html QScriptValue qscriptvalue.html ResolveFlag qscriptvalue.html 6779374a7f80389382a802bbc7f5137e QScriptValueIterator qscriptvalueiterator.html QScrollArea qscrollarea.html QScrollBar qscrollbar.html QSemaphore qsemaphore.html QSessionManager qsessionmanager.html RestartHint qsessionmanager.html 9d70e4d4985c740ede79d09ff1f26756 QSettings qsettings.html QSharedData qshareddata.html QSharedDataPointer qshareddatapointer.html QSharedMemory qsharedmemory.html QShortcut qshortcut.html QShortcutEvent qshortcutevent.html QShowEvent qshowevent.html QSignalMapper qsignalmapper.html QSignalSpy qsignalspy.html QSimpleXmlNodeModel qsimplexmlnodemodel.html QSizeF qsizef.html QSizeGrip qsizegrip.html QSizePolicy qsizepolicy.html PolicyFlag qsizepolicy.html 615d47c1fc9b40da3cefc64e887f08d4 Policy qsizepolicy.html eabfd4d8a8c2081bf215795f9707bc03 ControlType qsizepolicy.html 79bb83ae584a57901e2352c0f1515699 ExpandData qsizepolicy.html 13ae2c9e64b0d4c37029c5eb79678c69 QSlider qslider.html QSortFilterProxyModel qsortfilterproxymodel.html QSound qsound.html QSourceLocation qsourcelocation.html QSpacerItem qspaceritem.html QSpinBox qspinbox.html QSplashScreen qsplashscreen.html QSplitter qsplitter.html ResizeMode qsplitter.html 5ab05cb061d06b1fa46e8f2326806a06 QSplitterHandle qsplitterhandle.html QSpontaneKeyEvent qspontanekeyevent.html QSqlDatabase qsqldatabase.html QSqlDriver qsqldriver.html QSqlDriverCreator qsqldrivercreator.html QSqlDriverCreatorBase qsqldrivercreatorbase.html QSqlField qsqlfield.html RequiredStatus qsqlfield.html 1e49c91b081e5f30e2aa496dc0a96c76 QSQLite2Driver qsqlite2driver.html QSQLite2Result qsqlite2result.html QSQLiteDriver qsqlitedriver.html QSQLiteResult qsqliteresult.html QSqlQuery qsqlquery.html BatchExecutionMode qsqlquery.html 84e67822888422b657dd9fd0e1337e42 QSqlQueryModel qsqlquerymodel.html QSqlRecord qsqlrecord.html QSqlRelationalTableModel qsqlrelationaltablemodel.html QSqlResult qsqlresult.html BindingSyntax qsqlresult.html 406d244b9abf9ae7983408df9b624f78 VirtualHookOperation qsqlresult.html 5ccb16add1c651aba3aae8de5c387cd5 QSqlTableModel qsqltablemodel.html QSslCertificate qsslcertificate.html SubjectInfo qsslcertificate.html 958e6fe4b1b7e6909f2aab39641f3f1b QSslCipher qsslcipher.html QSslConfiguration qsslconfiguration.html QSslError qsslerror.html SslError qsslerror.html 7a98b251806bf965d364bff0461d5ca7 QSslKey qsslkey.html QSslSocket qsslsocket.html SslMode qsslsocket.html 7aef782fb2d69e2baef162134c6fd4d0 PeerVerifyMode qsslsocket.html 45ec942c7266f20a461bec6a83a25e4a QStackedLayout qstackedlayout.html QStackedWidget qstackedwidget.html QStandardItem qstandarditem.html ItemType qstandarditem.html 2ea443b261782bd1fb15d5972d8ffa8b QStandardItemEditorCreator qstandarditemeditorcreator.html QStandardItemModel qstandarditemmodel.html QStatusBar qstatusbar.html QStatusTipEvent qstatustipevent.html QString qstring.html SectionFlag qstring.html 8011ed67b62c31897ec24a04348f28c9 SplitBehavior qstring.html 7219a82554025f226a2c36104c45b323 NormalizationForm qstring.html ec58d6548770d862c0d679de1befdd54 QStringList qstringlist.html QStringMatcher qstringmatcher.html QStringRef qstringref.html QStyle qstyle.html StateFlag qstyle.html 088a1cd1741289f73db04a8966ab4f24 PrimitiveElement qstyle.html a523079ca612e9a869f15ef39aeb6d79 ControlElement qstyle.html 69ef1dc6ae45f293c0614a5bbc734ebf SubElement qstyle.html e0e0a0337a7fe6ded6b3575e01b2e668 ComplexControl qstyle.html a37f8e3261ba71c3593eec0f70ab674c SubControl qstyle.html f95b36fbbded39edbf665da2fe6aebd3 PixelMetric qstyle.html 90fb8e303d9024e203d03d15a86662fe ContentsType qstyle.html 08ce0bc12ccf2c58b80de242149eacd8 StyleHint qstyle.html 3c1acbe2063c2662a2fb28c65fab721c StandardPixmap qstyle.html 68b63036421523c45f4fab19c644fd84 QStyledItemDelegate qstyleditemdelegate.html QStyleFactory qstylefactory.html QStyleHintReturn qstylehintreturn.html HintReturnType qstylehintreturn.html b57046d6c23e6cc5abbd2b7660d2e997 StyleOptionType qstylehintreturn.html 06b069ce91d95186571f4170a74be275 StyleOptionVersion qstylehintreturn.html 0655f1dd6b4c2849c427bd6f4435f473 QStyleHintReturnMask qstylehintreturnmask.html StyleOptionType qstylehintreturnmask.html e7145c7a33c5635dc623b9314a890c47 StyleOptionVersion qstylehintreturnmask.html 51f6d7f7762faa8429d2de3eaac17978 QStyleHintReturnVariant qstylehintreturnvariant.html StyleOptionType qstylehintreturnvariant.html dcec1e03a241a63dc924703d97c490dc StyleOptionVersion qstylehintreturnvariant.html 7369940fe28da7ddfa266e41b307f762 QStyleOption qstyleoption.html OptionType qstyleoption.html 1d57eaae2323031b4d8ede74d2219995 StyleOptionType qstyleoption.html 1d90df07b54c9ecfee23751eddb5eea7 StyleOptionVersion qstyleoption.html e2f1ff9800ece1aff009aeaf8a4ec372 QStyleOptionButton qstyleoptionbutton.html StyleOptionType qstyleoptionbutton.html 177d990f195630bbc27bb69de7144190 StyleOptionVersion qstyleoptionbutton.html 28ec5dca06615049c07ef156634f367d ButtonFeature qstyleoptionbutton.html 3505675bf5bc27f5d38eeda60c2efa6e QStyleOptionComplex qstyleoptioncomplex.html StyleOptionType qstyleoptioncomplex.html 27c1ef703ffc4f54c66fbfde6bb1bda2 StyleOptionVersion qstyleoptioncomplex.html e1d69f5060a9220c0987677fc8234f32 QStyleOptionDockWidget qstyleoptiondockwidget.html StyleOptionType qstyleoptiondockwidget.html f34118f1880c7756238828b140c2b684 StyleOptionVersion qstyleoptiondockwidget.html 320347aef593905ce6d7cd37fb4599a4 QStyleOptionDockWidgetV2 qstyleoptiondockwidgetv2.html StyleOptionVersion qstyleoptiondockwidgetv2.html e79e2550e2561d15c56c6acad152f74e QStyleOptionFocusRect qstyleoptionfocusrect.html StyleOptionType qstyleoptionfocusrect.html 9652bff13205e046ce47fc982fd41b37 StyleOptionVersion qstyleoptionfocusrect.html 4ff8c92ef96c8a7f4c556658da12b0b1 QStyleOptionFrame qstyleoptionframe.html StyleOptionType qstyleoptionframe.html 48b984e9d394b48d6a574a02802a327f StyleOptionVersion qstyleoptionframe.html 30e2b48e359273e859d3410ad27c3914 QStyleOptionFrameV2 qstyleoptionframev2.html StyleOptionVersion qstyleoptionframev2.html 628f59c42d0b91ad60c735da7c64239d FrameFeature qstyleoptionframev2.html 3804418509ce4030e25c8ff2ca105753 QStyleOptionGraphicsItem qstyleoptiongraphicsitem.html StyleOptionType qstyleoptiongraphicsitem.html 588aabf2ac41b1774b32bd905a3ad8f1 StyleOptionVersion qstyleoptiongraphicsitem.html e16d0fa9b88111d7290dd7d97d4cab45 QStyleOptionGroupBox qstyleoptiongroupbox.html StyleOptionType qstyleoptiongroupbox.html 8b30b5099de3a355fdb2df95282bf961 StyleOptionVersion qstyleoptiongroupbox.html d61b3bd646120c781c857a0ebedde6c7 QStyleOptionHeader qstyleoptionheader.html StyleOptionType qstyleoptionheader.html a28ed04fcb63b390f7895c40dfac0a3f StyleOptionVersion qstyleoptionheader.html 7fa31d6e405cc14aa99e21798ac8ccaa SectionPosition qstyleoptionheader.html 267461de36af34dcecee9d6827837429 SelectedPosition qstyleoptionheader.html 77ceef6095518503b8650a254a3043a2 SortIndicator qstyleoptionheader.html 0f34e1cf3a147687b8c2cf39042f5314 QStyleOptionMenuItem qstyleoptionmenuitem.html StyleOptionType qstyleoptionmenuitem.html 6fac8e42660462c9941b5d80ef77c67f StyleOptionVersion qstyleoptionmenuitem.html e9f58cd974889292545115d3e0cd6a30 MenuItemType qstyleoptionmenuitem.html 3281996c7506799274f27eef662a70dd CheckType qstyleoptionmenuitem.html 2b7c82431ba4899e1c13dcdb691f4c27 QStyleOptionProgressBarV2 qstyleoptionprogressbarv2.html StyleOptionType qstyleoptionprogressbarv2.html 6a11f3992b8a47bf3488c8768d7c71fd StyleOptionVersion qstyleoptionprogressbarv2.html 526e69c548ea00b8163bba44007e34dc QStyleOptionQ3ListView qstyleoptionq3listview.html StyleOptionType qstyleoptionq3listview.html 194659cf9f927bac3701152e9bf2254c StyleOptionVersion qstyleoptionq3listview.html 759c1334b272aed6e798de347d195711 QStyleOptionQ3ListViewItem qstyleoptionq3listviewitem.html StyleOptionType qstyleoptionq3listviewitem.html 4fd7edb15cb12c4b12575e307f1f8eed StyleOptionVersion qstyleoptionq3listviewitem.html 05d2a3fd5b127115061b416c70a17f37 Q3ListViewItemFeature qstyleoptionq3listviewitem.html a0bbb56a88a62ceee5d87d1339564ac8 QStyleOptionRubberBand qstyleoptionrubberband.html StyleOptionType qstyleoptionrubberband.html 74c59cd4f1510fba13d3dbb6291113f5 StyleOptionVersion qstyleoptionrubberband.html d1a6aedfb25d191496cde8f930e1c09a QStyleOptionSizeGrip qstyleoptionsizegrip.html StyleOptionType qstyleoptionsizegrip.html e6e74145081494136e956bd7a014decd StyleOptionVersion qstyleoptionsizegrip.html c11d3902a0c8cdb8773aba1ebb7f23ce QStyleOptionSlider qstyleoptionslider.html StyleOptionType qstyleoptionslider.html fe664c2c67feafd3295a979fda0aa807 StyleOptionVersion qstyleoptionslider.html 3368d12d8b70ddc8762f84bbd9d6e2a9 QStyleOptionSpinBox qstyleoptionspinbox.html StyleOptionType qstyleoptionspinbox.html e3dcbb6e3e514f8b933cd82a566ba30d StyleOptionVersion qstyleoptionspinbox.html badc594276364e40cfdd868765ead14d QStyleOptionTabBarBase qstyleoptiontabbarbase.html StyleOptionType qstyleoptiontabbarbase.html fca4623ae67c7030c7520452bc8ee14f StyleOptionVersion qstyleoptiontabbarbase.html 90f87e0bac21193153816ba801dea117 QStyleOptionTitleBar qstyleoptiontitlebar.html StyleOptionType qstyleoptiontitlebar.html 2540ca9db978212c26d14ce25af1c889 StyleOptionVersion qstyleoptiontitlebar.html 3f96fcbc3eb84737a3808d87b11c8c2a QStyleOptionToolBar qstyleoptiontoolbar.html StyleOptionType qstyleoptiontoolbar.html 34cf705e4692dc3ec61002b278eb151e StyleOptionVersion qstyleoptiontoolbar.html 77e8099cb430602af179ac4383d7b33e ToolBarPosition qstyleoptiontoolbar.html 9e7e2ccc8077454d82ebeec5f2db4407 ToolBarFeature qstyleoptiontoolbar.html c877ebd8a5ae51af3d6d0cdb689f3de6 QStyleOptionToolBox qstyleoptiontoolbox.html StyleOptionType qstyleoptiontoolbox.html c4dec26188676b2fb38892bc59d26ae0 StyleOptionVersion qstyleoptiontoolbox.html 8d1475409578df7c286f17e1404d3b96 QStyleOptionToolBoxV2 qstyleoptiontoolboxv2.html StyleOptionVersion qstyleoptiontoolboxv2.html d68191388839799e2bf6f38169a45924 TabPosition qstyleoptiontoolboxv2.html a2ebf2c18732200caa8789340e1ea715 SelectedPosition qstyleoptiontoolboxv2.html f65e9fc64611434d7ef4f3c09fdc4386 QStyleOptionToolButton qstyleoptiontoolbutton.html StyleOptionType qstyleoptiontoolbutton.html 0c2c3996b3b3aec7a7393ed083f41aee StyleOptionVersion qstyleoptiontoolbutton.html 0b61837ba6df60e9cb4389ab5b97ae50 ToolButtonFeature qstyleoptiontoolbutton.html 2b4f85d9fb97be432950bbc59ddbb09b QStyleOptionViewItem qstyleoptionviewitem.html StyleOptionType qstyleoptionviewitem.html 160783902a17516de98c16ffd48cc140 StyleOptionVersion qstyleoptionviewitem.html 1ff2702362e6b339f44b06ee99d8dc8e Position qstyleoptionviewitem.html 7c0e31262ce9c5693337127b8677cdba QStyleOptionViewItemV2 qstyleoptionviewitemv2.html StyleOptionVersion qstyleoptionviewitemv2.html 86170a4700db845e48cc066f005ca46d ViewItemFeature qstyleoptionviewitemv2.html 1ee39cc272a94f052b577b0a98fb3d51 QStyleOptionViewItemV4 qstyleoptionviewitemv4.html StyleOptionVersion qstyleoptionviewitemv4.html 32dbd1d2930ffe8aabfbc37704ae9337 ViewItemPosition qstyleoptionviewitemv4.html 7bd6a31fe36bc49a2538d055fe442f3d QSvgGenerator qsvggenerator.html QSvgRenderer qsvgrenderer.html QSvgWidget qsvgwidget.html QSyntaxHighlighter qsyntaxhighlighter.html QSysInfo qsysinfo.html Sizes qsysinfo.html d128a3df9d8fc2a413e20c2b8bf358a8 Endian qsysinfo.html 650bfed7d0f4920b2753cec329e2f1e6 WinVersion qsysinfo.html 9af00ec041c15e67313ccfa797ea4387 MacVersion qsysinfo.html 9b7e6dee4aa421583310b493a77e51b6 QSystemLocale qsystemlocale.html QueryType qsystemlocale.html 2e224a1c6e16e2fdeea92a5a6bb05108 QSystemSemaphore qsystemsemaphore.html AccessMode qsystemsemaphore.html 70c2d0e4ee4f45ba40a81f66fd1edb15 SystemSemaphoreError qsystemsemaphore.html ec41364b52ca15e302b3f425078c773b QSystemTrayIcon qsystemtrayicon.html ActivationReason qsystemtrayicon.html 436af1d5974ef5a40af3c7f0712c2679 MessageIcon qsystemtrayicon.html 7d79bd78e7d26b1c0babc84c6a198162 QT_NO_QOBJECT qt__no__qobject.html OpenModeFlag qt__no__qobject.html 21b2ad2c5375d3ad81b64ce00c02741a ValueOwnership qt__no__qobject.html e1da56f10f27b08dd91dd7b2704b830d QObjectWrapOption qt__no__qobject.html bd4b72d6d80fad6b5c8116bf9be9070e QTabBar qtabbar.html QTabletEvent qtabletevent.html TabletDevice qtabletevent.html 38c508f311a0775614e46ff3071c5dce PointerType qtabletevent.html 71145a52a82c973dd4250c5894918c61 QTableView qtableview.html QTableWidget qtablewidget.html QTableWidgetItem qtablewidgetitem.html ItemType qtablewidgetitem.html 33c145cb9d45d2b9947cb799742d1eca QTabWidget qtabwidget.html QTcpServer qtcpserver.html QTcpSocket qtcpsocket.html QTemporaryFile qtemporaryfile.html QTestAccessibility qtestaccessibility.html QTestData qtestdata.html QTestDelayEvent qtestdelayevent.html QTestEventList qtesteventlist.html QTestKeyClicksEvent qtestkeyclicksevent.html QTestKeyEvent qtestkeyevent.html QTestMouseEvent qtestmouseevent.html QTextBlock qtextblock.html QTextBlock::iterator qtextblock_1_1iterator.html QTextBlockFormat qtextblockformat.html QTextBlockGroup qtextblockgroup.html QTextBlockUserData qtextblockuserdata.html QTextBoundaryFinder qtextboundaryfinder.html BoundaryType qtextboundaryfinder.html fd4fc6c9c14e939289510e5ded23b8f7 BoundaryReason qtextboundaryfinder.html cfbe3a6eaf4e37093e8365a0314715d3 QTextBrowser qtextbrowser.html QTextCodec qtextcodec.html QTextCursor qtextcursor.html MoveMode qtextcursor.html 4c943c201465a5202a32eea499c963db MoveOperation qtextcursor.html b8b9550ee992f725e9d1204a84c20b3a SelectionType qtextcursor.html 444695e37aba900951508cda520017cd QTextDecoder qtextdecoder.html QTextDocument qtextdocument.html MetaInformation qtextdocument.html 1d9b5cab0689bddfd89d3de98321c6d8 FindFlag qtextdocument.html 1b7ec6d35c5d1a8c5125dd3145580263 ResourceType qtextdocument.html 056519b7e251698b54431c71d86b4624 QTextDocumentFragment qtextdocumentfragment.html QTextEdit qtextedit.html KeyboardAction qtextedit.html 116279630b609f0a99c5bd7cfffdb15e QTextEncoder qtextencoder.html QTextFormat qtextformat.html QTextFragment qtextfragment.html QTextFrame qtextframe.html QTextFrame::iterator qtextframe_1_1iterator.html QTextFrameFormat qtextframeformat.html Position qtextframeformat.html c40dbf1c0a81e50f961f15ee7977b5ad BorderStyle qtextframeformat.html 6d351675c89536890b4efd0bdf5534e1 QTextFrameLayoutData qtextframelayoutdata.html QTextImageFormat qtextimageformat.html QTextInlineObject qtextinlineobject.html QTextIStream qtextistream.html QTextItem qtextitem.html RenderFlag qtextitem.html eebe9d888b128d52703c659b6febe727 QTextLayout qtextlayout.html CursorMode qtextlayout.html e860be0507fa5cecb9d2e44669d815e9 QTextLength qtextlength.html Type qtextlength.html dc954b9b53c6f980da9bccef4f316a3e QTextLine qtextline.html Edge qtextline.html b72d6cd6ebc9a2fbbb0660678cb4b579 CursorPosition qtextline.html bbc36047bae69233fcaeae6aa5eeeb84 QTextList qtextlist.html QTextListFormat qtextlistformat.html Style qtextlistformat.html 4e3749cb45536beb88661d7f22513251 QTextObject qtextobject.html QTextObjectInterface qtextobjectinterface.html QTextOption qtextoption.html TabType qtextoption.html 90bff559256e1fa1d94a1788bc7069a1 WrapMode qtextoption.html d844cd82ea153e36d307426780f4a117 Flag qtextoption.html d506d639c8ed18d114a2d502b0409b48 QTextOStream qtextostream.html QTextStream qtextstream.html Status qtextstream.html Status-enum QTextStreamManipulator qtextstreammanipulator.html QTextTable qtexttable.html QTextTableCell qtexttablecell.html QTextTableCellFormat qtexttablecellformat.html QTextTableFormat qtexttableformat.html QThread qthread.html Priority qthread.html 7abf5caadc33903ab308916dceee5c54 QThreadPool qthreadpool.html QThreadStorage qthreadstorage.html QTime qtime.html QTimeEdit qtimeedit.html QTimeLine qtimeline.html State qtimeline.html c29cbeaeb676a0a7f1c8af5b57bdae82 Direction qtimeline.html e712bf6b1755d7d788c0ff1afbae9c1d CurveShape qtimeline.html f24ff407fb64a3882cf740923d4dd768 QTimerEvent qtimerevent.html QToolBar qtoolbar.html QToolBarChangeEvent qtoolbarchangeevent.html QToolBox qtoolbox.html QToolButton qtoolbutton.html QTransform qtransform.html QTranslator qtranslator.html QTreeView qtreeview.html QTreeWidget qtreewidget.html QTreeWidgetItem qtreewidgetitem.html ItemType qtreewidgetitem.html 6b33c839ed2de1f9e5b32f4d8ba4719d ChildIndicatorPolicy qtreewidgetitem.html b4c3aa05c07f34c89d841a675c690856 QTreeWidgetItemIterator qtreewidgetitemiterator.html IteratorFlag qtreewidgetitemiterator.html 1d405d2f3e0ef1f15699ce594d28eae1 QTypeInfo qtypeinfo.html QTypeInfo< T * > qtypeinfo_3_01t_01_5_01_4.html QUdpSocket qudpsocket.html BindFlag qudpsocket.html 3751515130ee01bccf8c4b600bd83864 QUiLoader quiloader.html QUintForSize quintforsize.html QUintForSize< 4 > quintforsize_3_014_01_4.html QUintForSize< 8 > quintforsize_3_018_01_4.html QUintForType quintfortype.html QUndoCommand qundocommand.html QUndoStack qundostack.html QUnixPrintWidget qunixprintwidget.html QUpdateLaterEvent qupdatelaterevent.html QUrl qurl.html ParsingMode qurl.html 8ac511aa3cef7474b4111f90549ad52d FormattingOption qurl.html b93c34c3e0af1f1311861871fa014524 QUrlInfo qurlinfo.html PermissionSpec qurlinfo.html 16519be21c4bfa1801f96fa99c2c22cd QValidator qvalidator.html State qvalidator.html 615cda51100b08f4f8e004ddfe3a2202 QVariant qvariant.html Type qvariant.html 8e1414f284ce72d9e6a85f2dcf80c754 QVariantComparisonHelper qvariantcomparisonhelper.html QVarLengthArray qvarlengtharray.html QVBoxLayout qvboxlayout.html QVector qvector.html QVector::const_iterator qvector_1_1const__iterator.html QVector::iterator qvector_1_1iterator.html QWaitCondition qwaitcondition.html QWebFrame qwebframe.html QWebHistory qwebhistory.html QWebHistoryInterface qwebhistoryinterface.html QWebHistoryItem qwebhistoryitem.html QWebHitTestResult qwebhittestresult.html QWebPage qwebpage.html WebAction qwebpage.html 0175ae5524b2b2a0a3582753ee3b9dd1 FindFlag qwebpage.html 3f19743a9d70c74f6440ae0b625d2b69 WebWindowType qwebpage.html 066e9949f06582ffb303688bfbabca2f Extension qwebpage.html 69b9368571a901ac5c2c44c07fc6f196 QWebPage::ExtensionOption qwebpage_1_1extensionoption.html QWebPage::ExtensionReturn qwebpage_1_1extensionreturn.html QWebPluginFactory qwebpluginfactory.html Extension qwebpluginfactory.html 092068f66c2651f953416d1b7c21b823 QWebPluginFactory::ExtensionOption qwebpluginfactory_1_1extensionoption.html QWebPluginFactory::ExtensionReturn qwebpluginfactory_1_1extensionreturn.html QWebSettings qwebsettings.html FontFamily qwebsettings.html de158ede90a3fedd258272525a4f906e WebAttribute qwebsettings.html 464eea6a97932ec95b23df9449dd29b3 WebGraphic qwebsettings.html b2197cbe473eb64293e1671e39e72055 FontSize qwebsettings.html a062fe6e7e753a6092b4a69cd94cb8df QWebView qwebview.html QWhatsThis qwhatsthis.html QWhatsThisClickedEvent qwhatsthisclickedevent.html QWheelEvent qwheelevent.html QWidget qwidget.html BackgroundOrigin qwidget.html 4660ffd918849117c906d43af7236b16 QWidgetAction qwidgetaction.html QWidgetData qwidgetdata.html QWidgetItem qwidgetitem.html QWidgetItemV2 qwidgetitemv2.html QWindowsMime qwindowsmime.html QWindowsMobileStyle qwindowsmobilestyle.html QWindowsStyle qwindowsstyle.html QWindowStateChangeEvent qwindowstatechangeevent.html QWindowsVistaStyle qwindowsvistastyle.html QWindowsXPStyle qwindowsxpstyle.html QWizard qwizard.html QWizardPage qwizardpage.html QWorkspace qworkspace.html WindowOrder qworkspace.html 87917446dd11f4b927b53345674e2a9e QWriteLocker qwritelocker.html QX11EmbedContainer qx11embedcontainer.html Error qx11embedcontainer.html b294c386ff72b70092fe2736268101b5 QX11EmbedWidget qx11embedwidget.html Error qx11embedwidget.html 21edb75905b1eea840abd0304534afb0 QX11Info qx11info.html QXmlAttributes qxmlattributes.html QXmlContentHandler qxmlcontenthandler.html QXmlDeclHandler qxmldeclhandler.html QXmlDefaultHandler qxmldefaulthandler.html QXmlDTDHandler qxmldtdhandler.html QXmlEntityResolver qxmlentityresolver.html QXmlErrorHandler qxmlerrorhandler.html QXmlFormatter qxmlformatter.html QXmlInputSource qxmlinputsource.html QXmlItem qxmlitem.html QXmlLexicalHandler qxmllexicalhandler.html QXmlLocator qxmllocator.html QXmlName qxmlname.html QXmlNamePool qxmlnamepool.html QXmlNamespaceSupport qxmlnamespacesupport.html QXmlNodeModelIndex qxmlnodemodelindex.html NodeKind qxmlnodemodelindex.html c746712c7077a2cf2c0d34e61ea12493 DocumentOrder qxmlnodemodelindex.html 1bfecac46a0dfab6ba941dbcdfd255d6 Axis qxmlnodemodelindex.html fbac59d439d338baa7563a361d3bd530 QXmlParseException qxmlparseexception.html QXmlQuery qxmlquery.html QXmlReader qxmlreader.html QXmlResultItems qxmlresultitems.html QXmlSerializer qxmlserializer.html QXmlSimpleReader qxmlsimplereader.html QXmlStreamAttribute qxmlstreamattribute.html QXmlStreamAttributes qxmlstreamattributes.html QXmlStreamEntityDeclaration qxmlstreamentitydeclaration.html QXmlStreamEntityResolver qxmlstreamentityresolver.html QXmlStreamNamespaceDeclaration qxmlstreamnamespacedeclaration.html QXmlStreamNotationDeclaration qxmlstreamnotationdeclaration.html QXmlStreamReader qxmlstreamreader.html QXmlStreamWriter qxmlstreamwriter.html QAlgorithmsPrivate qalgorithmsprivate.html QFormInternal qforminternal.html QFormInternal::QAbstractFormBuilder qforminternal_1_1qabstractformbuilder.html QFormInternal::QFormBuilder qforminternal_1_1qformbuilder.html QGL qgl.html FormatOption qgl.html 8f66296dd735106fc3a676d46f42adb9 QMdi qmdi.html QPatternist qpatternist.html QPatternist::NodeIndexStorage qpatternist_1_1nodeindexstorage.html QPatternistSDK qpatternistsdk.html Qt qt.html HitTestAccuracy qt.html 7ae2072ce48064c4f1d8df37eb16e91a WhiteSpaceMode qt.html 91cab8ff21e40462b97dc635e3027a10 QT_NAMESPACE qt__namespace.html QtConcurrent qtconcurrent.html QTest qtest.html QtPrivate qtprivate.html std std.html WebCore webcore.html cutechess-20111114+0.4.2+0.0.1/AUTHORS0000664000175000017500000000015111657223322015455 0ustar oliveroliverThe PRIMARY AUTHORS are: Ilari Pihlajisto Arto Jonsson cutechess-20111114+0.4.2+0.0.1/tools/0000775000175000017500000000000011657223322015550 5ustar oliverolivercutechess-20111114+0.4.2+0.0.1/tools/tagtrimmer.cpp0000664000175000017500000000740311657223322020433 0ustar oliveroliver/* A command-line tool for removing unneeded data from a Doxygen tagfile. The tool's main purpose is to trim the Qt library's tagfile to a manageable size, but it may work with other tagfiles as well. */ #include #include #include /*! * Remove the Doxygen-generated "class", "namespace", or whatever prefix * from a file name, and make it lowercase. */ static void fixFilename(QDomElement& node, const QString& compoundKind) { QDomNode child = node.firstChild(); QString text = child.nodeValue(); if (text.startsWith(compoundKind)) { int len = compoundKind.length(); text = text.mid(len).toLower(); child.setNodeValue(text); } } /*! Remove duplicate members from the compound. */ static void trimMembers(QDomElement& compound) { QDomElement elem; for (elem = compound.firstChildElement("member"); !elem.isNull(); elem = elem.nextSiblingElement("member")) { QDomElement nameElem1 = elem.firstChildElement("name"); QDomElement elem2 = elem.nextSiblingElement("member"); while (!elem2.isNull()) { // If two members have a "name" tag with the same // value, the second one of them gets removed. QDomElement nameElem2 = elem2.firstChildElement("name"); if (nameElem2.text() == nameElem1.text()) { QDomElement old = elem2; elem2 = elem2.nextSiblingElement("member"); compound.removeChild(old); continue; } elem2 = elem2.nextSiblingElement("member"); } } } /*! Remove unneeded nodes from a compound. */ static void trimCompound(QDomElement& compound) { QDomElement elem = compound.firstChildElement(); while (!elem.isNull()) { QString name = elem.tagName(); if (name == "filename") fixFilename(elem, compound.attribute("kind")); else if (name == "member" && elem.attribute("kind") == "enumeration") { QDomElement tmp(elem.firstChildElement("anchorfile")); if (!tmp.isNull()) fixFilename(tmp, compound.attribute("kind")); // The "arglist" tag is never used in class or // namespace compounds. tmp = elem.firstChildElement("arglist"); if (!tmp.isNull()) elem.removeChild(tmp); } else if (name != "name") { QDomElement old = elem; elem = elem.nextSiblingElement(); compound.removeChild(old); continue; } elem = elem.nextSiblingElement(); } trimMembers(compound); } /*! Trim out useless weight from the tagfile. */ static bool trimDoc(QDomDocument& doc) { QDomElement root = doc.documentElement(); if (root.tagName() != "tagfile") return false; QDomElement compound = root.firstChildElement(); while (!compound.isNull()) { QString compoundKind = compound.attribute("kind"); if (compound.tagName() != "compound" || (compoundKind != "class" && compoundKind != "namespace")) { QDomElement old = compound; compound = compound.nextSiblingElement(); root.removeChild(old); continue; } trimCompound(compound); compound = compound.nextSiblingElement(); } return true; } int main(int argc, char* argv[]) { QCoreApplication app(argc, argv); QStringList args = app.arguments(); if (args.size() <= 2) { qDebug() << "Usage: tagtrimmer SOURCE_FILE DEST_FILE"; return 1; } QFile file(args[1]); if (!file.open(QIODevice::ReadOnly)) { qWarning() << "Can't open file" << args[1]; return 1; } QDomDocument doc; QString errorMsg; int line, col; if (!doc.setContent(&file, &errorMsg, &line, &col)) { qWarning() << "Error in line" << line << "column" << col; qWarning() << errorMsg; return 1; } file.close(); if (!trimDoc(doc)) { qWarning() << "Couldn't trim the Doxytag file" << args[1]; return 1; } QFile file2(args[2]); if (!file2.open(QIODevice::WriteOnly)) { qWarning() << "Can't open file" << args[2]; return 1; } QTextStream out(&file2); doc.save(out, 2); return 0; } cutechess-20111114+0.4.2+0.0.1/tools/tagtrimmer.pro0000664000175000017500000000015111657223322020442 0ustar oliveroliverTEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . QT += xml # Input SOURCES += tagtrimmer.cpp cutechess-20111114+0.4.2+0.0.1/tools/src-entries.sh0000775000175000017500000000530011657223322020343 0ustar oliveroliver#!/bin/sh # Print TODO, FIXME, HACK and NOTE entries from source code files. # Default settings print_todos="yes" print_fixmes="yes" print_hacks="yes" print_notes="yes" print_line_numbers="yes" print_file_name="yes" print_entries() { for file in `find . \( ! -regex '.*/\..*' -a -name "*.cpp" -o -name "*.h" \) -type f` do grep -n -E '^\W*// (TODO|FIXME|HACK|NOTE):' $file | while read entry do local line_num=`echo "$entry" | cut -f 1 -d :` local entry_type=`echo "$entry" | cut -f 2 -d : | sed -e 's/^\W*//g'` local entry_text="`echo $entry | cut -f 3 -d : | sed -e 's/^\W*//g'`" # Should we print this type of entry? local print_this_type="yes" case $entry_type in TODO ) if [ $print_todos = "no" ]; then print_this_type="no" fi ;; FIXME ) if [ $print_fixmes = "no" ]; then print_this_type="no" fi ;; HACK ) if [ $print_hacks = "no" ]; then print_this_type="no" fi ;; NOTE ) if [ $print_notes = "no" ]; then print_this_type="no" fi ;; esac if [ $print_this_type = "yes" ] then if [ $print_file_name = "no" ] then echo "$entry_type: $entry_text" else if [ $print_line_numbers = "no" ] then echo "$file: $entry_type: $entry_text" else echo "$file:$line_num: $entry_type: $entry_text" fi fi fi done done } print_usage() { echo "Usage: src-entries.sh [options]" echo "" echo "Print TODO, FIXME, HACK and NOTE entries from source code files. All" echo "entries are printed by default with the file name and line number." echo "" echo "The entries must be in format:" echo "" echo " // [TODO|FIXME|HACK|NOTE]: " echo "" echo "Only one entry per line (text included) is currently supported." echo "" echo "Options:" echo "" echo " --no-file-name don't print the file name where the entry came from" echo " --no-line-number don't print the line number where the entry came from" echo " --no-todos don't print TODO entries" echo " --no-fixmes don't print FIXME entries" echo " --no-hacks don't print HACK entries" echo " --no-notes don't print NOTE entries" echo "" exit 0 } while [ $# -ge 1 ] do case $1 in --no-file-name ) print_file_name="no" # Disable printing line number too as it's pretty much useless # without the file name print_line_numbers="no" ;; --no-line-number ) print_line_numbers="no" ;; --no-todos ) print_todos="no" ;; --no-fixmes ) print_fixmes="no" ;; --no-hacks ) print_hacks="no" ;; --no-notes ) print_notes="no" ;; * ) print_usage ;; esac shift done print_entries exit 0 cutechess-20111114+0.4.2+0.0.1/tools/clop-cutechess-cli.py0000775000175000017500000001012111657223322021606 0ustar oliveroliver#!/usr/bin/python # -*- coding: utf-8 -*- """ Usage: clop-cutechess-cli.py CPU_ID SEED [PARAM_NAME PARAM_VALUE]... Run cutechess-cli with CLOP_PARAM(s). CPU_ID Symbolic name of the CPU or machine that should run the game SEED Running number for the game to be played PARAM_NAME Name of a parameter that's being optimized PARAM_VALUE Integer value for parameter PARAM_NAME CLOP is a black-box parameter tuning tool designed and written by Rémi Coulom. More information about CLOP can be found at the CLOP website: http://remi.coulom.free.fr/CLOP/ This script works between CLOP and cutechess-cli. The path to this script, without any parameters, should be on the "Script" line of the .clop file. 'Replications' in the .clop file should be set to 2 so that this script can alternate the engine's playing side correctly. In this script the variables 'cutechess_cli_path', 'engine', 'engine_param_cmd', 'opponents' and 'options' must be modified to fit the test environment and conditions. The default values are just examples. When the game is completed the script writes the game outcome to its standard output: W = win L = loss D = draw """ from subprocess import Popen, PIPE import sys import exceptions # Path to the cutechess-cli executable. # On Windows this should point to cutechess-cli.exe cutechess_cli_path = 'path_to_cutechess-cli/cutechess-cli.sh' # The engine whose parameters will be optimized engine = 'conf=MyEngine' # Format for the commands that are sent to the engine to # set the parameter values. When the command is sent, # {name} will be replaced with the parameter name and {value} # with the parameter value. engine_param_cmd = 'setvalue {name} {value}' # A pool of opponents for the engine. The opponent will be # chosen based on the seed sent by CLOP. opponents = [ 'conf=OpponentEngine1', 'conf=OpponentEngine2', 'conf=OpponentEngine3' ] # Additional cutechess-cli options, eg. time control and opening book options = '-both tc=40/1+0.05 -draw 80 1 -resign 5 500' def main(argv = None): if argv is None: argv = sys.argv[1:] if len(argv) == 0 or argv[0] == '--help': print __doc__ return 0 argv = argv[1:] if len(argv) < 3 or len(argv) % 2 == 0: print 'Too few arguments' return 2 clop_seed = 0 try: clop_seed = int(argv[0]) except exceptions.ValueError: print 'Invalid seed value: %s' % argv[0] return 2 fcp = engine scp = opponents[(clop_seed >> 1) % len(opponents)] # Parse the parameters that should be optimized for i in range(1, len(argv), 2): # Make sure the parameter value is numeric try: float(argv[i + 1]) except exceptions.ValueError: print 'Invalid value for parameter %s: %s' % (argv[i], argv[i + 1]) return 2 # Pass CLOP's parameters to the engine by using # cutechess-cli's initialization string feature initstr = engine_param_cmd.format(name = argv[i], value = argv[i + 1]) fcp += ' initstr="%s"' % initstr # Choose the engine's playing side (color) based on CLOP's seed if clop_seed % 2 != 0: fcp, scp = scp, fcp cutechess_args = '-fcp %s -scp %s %s' % (fcp, scp, options) command = '%s %s' % (cutechess_cli_path, cutechess_args) # Run cutechess-cli and wait for it to finish process = Popen(command, shell = True, stdout = PIPE) output = process.communicate()[0] if process.returncode != 0: print 'Could not execute command: %s' % command return 2 # Convert Cutechess-cli's result into W/L/D # Note that only one game should be played result = -1 for line in output.splitlines(): if line.startswith('Game 1 ended:'): if line.find("1-0") != -1: result = clop_seed % 2 elif line.find("0-1") != -1: result = (clop_seed % 2) ^ 1 break if result == -1: print 'D' elif result == 0: print 'W' elif result == 1: print 'L' if __name__ == "__main__": sys.exit(main())