File indexing completed on 2024-12-08 09:32:23
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"