File indexing completed on 2024-12-01 06:39:00

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2014 Abhinav Gangwar <abhgang@gmail.com>
0004 //
0005 
0006 // Self
0007 #include "CountryByFlag.h"
0008 
0009 // Qt
0010 #include <QTime>
0011 #include <QImage>
0012 #include <QString>
0013 #include <QVector>
0014 #include <QVariant>
0015 #include <QVariantList>
0016 
0017 // Marble
0018 #include <marble/MarbleWidget.h>
0019 #include <marble/MarbleModel.h>
0020 #include <marble/GeoDataTreeModel.h>
0021 #include <marble/MarbleDirs.h>
0022 #include <marble/MarbleDebug.h>
0023 #include <marble/MarblePlacemarkModel.h>
0024 
0025 #include <marble/GeoDataDocument.h>
0026 #include <marble/GeoDataPlacemark.h>
0027 
0028 namespace Marble
0029 {
0030 class CountryByFlagPrivate
0031 {
0032 public:
0033     CountryByFlagPrivate( MarbleWidget *marbleWidget )
0034     : m_marbleWidget( marbleWidget ),
0035       m_parent( nullptr ),
0036       m_countryNames( nullptr )
0037     {
0038         m_continentsAndOceans
0039             << QStringLiteral("Asia") << QStringLiteral("Africa")
0040             << QStringLiteral("North America") << QStringLiteral("South America")
0041             << QStringLiteral("Antarctica") << QStringLiteral("Europe")
0042             << QStringLiteral("Australia")
0043             << QStringLiteral("Arctic Ocean") << QStringLiteral("Indian Ocean")
0044             << QStringLiteral("North Atlantic Ocean") << QStringLiteral("North Pacific Ocean")
0045             << QStringLiteral("South Pacific Ocean") << QStringLiteral("South Atlantic Ocean")
0046             << QStringLiteral("Southern Ocean");
0047     }
0048 
0049     MarbleWidget *m_marbleWidget;
0050     CountryByFlag *m_parent;
0051 
0052     /**
0053      * Document to store point placemarks which
0054      * have country names ( from file "boundaryplacemarks.cache" )
0055      */
0056     GeoDataDocument *m_countryNames;
0057 
0058     /*
0059      * When I select a random placemark form boundaryplacemarks.cache
0060      * it may represent a continent. Since there is no flag
0061      * for a continent, we will not use this placemark to post question.
0062      * This list will help checking whether the placemark chosen to
0063      * post question is a continent/ocean .
0064      */
0065     QStringList m_continentsAndOceans;
0066 };
0067 
0068 CountryByFlag::CountryByFlag( MarbleWidget *marbleWidget )
0069     : QObject(),
0070       d ( new CountryByFlagPrivate(marbleWidget) )
0071 {
0072     d->m_parent = this;
0073 }
0074 
0075 CountryByFlag::~CountryByFlag()
0076 {
0077     delete d->m_countryNames;
0078     delete d;
0079 }
0080 
0081 void CountryByFlag::initiateGame()
0082 {
0083     /**
0084      * First remove the GeoDataDocument, which displays
0085      * country names, from map.
0086      */
0087 
0088     if ( !d->m_countryNames ) {
0089         const GeoDataTreeModel *const treeModel = d->m_marbleWidget->model()->treeModel();
0090         for ( int i = 0; i < treeModel->rowCount(); ++i ) {
0091             QVariant const data = treeModel->data ( treeModel->index ( i, 0 ), MarblePlacemarkModel::ObjectPointerRole );
0092             GeoDataObject *object = qvariant_cast<GeoDataObject*>( data );
0093             Q_ASSERT_X( object, "CountryByFlag::initiateGame",
0094                         "failed to get valid data from treeModel for GeoDataObject" );
0095             if (auto doc = geodata_cast<GeoDataDocument>(object)) {
0096                 QFileInfo fileInfo( doc->fileName() );
0097                 if (fileInfo.fileName() == QLatin1String("boundaryplacemarks.cache")) {
0098                     d->m_countryNames = doc;
0099                     break;
0100                 }
0101             }
0102         }
0103     }
0104 
0105     if ( d->m_countryNames ) {
0106         d->m_countryNames->setVisible( false );
0107         d->m_marbleWidget->model()->treeModel()->updateFeature( d->m_countryNames );
0108         d->m_marbleWidget->centerOn( 23.0, 42.0 );
0109         d->m_marbleWidget->setDistance( 7500 );
0110         d->m_marbleWidget->setHighlightEnabled( false );
0111         emit gameInitialized();
0112     }
0113 }
0114 
0115 void CountryByFlag::postQuestion( QObject *gameObject )
0116 {
0117     /**
0118      * Find a random placemark
0119      */
0120     Q_ASSERT_X( d->m_countryNames, "CountryByFlag::postQuestion",
0121                 "CountryByFlagPrivate::m_countryNames is NULL" );
0122     QVector<GeoDataPlacemark*> countryPlacemarks = d->m_countryNames->placemarkList();
0123 
0124     uint randomSeed = uint(QTime::currentTime().msec());
0125     qsrand( randomSeed );
0126 
0127     bool found = false;
0128     GeoDataPlacemark *placemark = nullptr;
0129     QVariantList answerOptions;
0130     QString flagPath;
0131 
0132     while ( !found ) {
0133         int randomIndex = qrand()%countryPlacemarks.size();
0134         placemark = countryPlacemarks[randomIndex];
0135 
0136         if ( !d->m_continentsAndOceans.contains(placemark->name(), Qt::CaseSensitive) ) {
0137             const QString countryCode = placemark->countryCode().toLower();
0138             flagPath = MarbleDirs::path(QLatin1String("flags/flag_") + countryCode + QLatin1String(".svg"));
0139             QImage flag = QFile::exists( flagPath ) ? QImage( flagPath ) : QImage();
0140             if ( !flag.isNull() ) {
0141                 flagPath = QLatin1String("../../../data/flags/flag_") + countryCode + QLatin1String(".svg");
0142                 found = true;
0143             }
0144         }
0145     }
0146 
0147     answerOptions << placemark->name()
0148     << countryPlacemarks[qrand()%countryPlacemarks.size()]->name()
0149     << countryPlacemarks[qrand()%countryPlacemarks.size()]->name()
0150     << countryPlacemarks[qrand()%countryPlacemarks.size()]->name();
0151 
0152     // Randomize the options in the list answerOptions
0153     for ( int i = 0; i < answerOptions.size(); ++i ) {
0154         QVariant option = answerOptions.takeAt( qrand()%answerOptions.size() );
0155         answerOptions.append( option );
0156     }
0157     if ( gameObject ) {
0158         QMetaObject::invokeMethod( gameObject, "countryByFlagQuestion",
0159                                    Q_ARG(QVariant, QVariant(answerOptions)),
0160                                    Q_ARG(QVariant, QVariant(flagPath)),
0161                                    Q_ARG(QVariant, QVariant(placemark->name())) );
0162     }
0163 }
0164 
0165 }   // namespace Marble
0166 
0167 #include "moc_CountryByFlag.cpp"