diff --git a/src/blackcore/airspacemonitor.cpp b/src/blackcore/airspacemonitor.cpp index 9d3026a8f..2abbbe10a 100644 --- a/src/blackcore/airspacemonitor.cpp +++ b/src/blackcore/airspacemonitor.cpp @@ -32,7 +32,6 @@ using namespace BlackMisc::Weather; namespace BlackCore { - CAirspaceMonitor::CAirspaceMonitor(BlackMisc::Simulation::IOwnAircraftProvider *ownAircraftProvider, INetwork *network, CWebDataServices *webDataReader, QObject *parent) : QObject(parent), COwnAircraftAware(ownAircraftProvider), @@ -855,7 +854,7 @@ namespace BlackCore if (!model.hasValidDbKey() && !model.getLivery().hasValidDbKey()) { // create a pseudo livery, try to find airline first - CAirlineIcaoCode airlineIcao(this->getAirlineIcaoCodeForDesignator(airlineIcaoDesignator)); + CAirlineIcaoCode airlineIcao(this->smartAirlineIcaoSelector(CAirlineIcaoCode(airlineIcaoDesignator))); if (!airlineIcao.hasValidDbKey()) { // no DB data, we update as much as possible diff --git a/src/blackcore/icaodatareader.cpp b/src/blackcore/icaodatareader.cpp index b712ee278..eecef5739 100644 --- a/src/blackcore/icaodatareader.cpp +++ b/src/blackcore/icaodatareader.cpp @@ -90,7 +90,7 @@ namespace BlackCore return m_countries.findBestMatchByCountryName(name); } - CAirlineIcaoCode CIcaoDataReader::getAirlineIcaoCodeForDesignator(const QString &designator) const + CAirlineIcaoCodeList CIcaoDataReader::getAirlineIcaoCodesForDesignator(const QString &designator) const { return getAirlineIcaoCodes().findByVDesignator(designator); } diff --git a/src/blackcore/icaodatareader.h b/src/blackcore/icaodatareader.h index e172a7f4d..82551a023 100644 --- a/src/blackcore/icaodatareader.h +++ b/src/blackcore/icaodatareader.h @@ -74,7 +74,7 @@ namespace BlackCore //! Get airline ICAO information for designator //! \threadsafe - BlackMisc::Aviation::CAirlineIcaoCode getAirlineIcaoCodeForDesignator(const QString &designator) const; + BlackMisc::Aviation::CAirlineIcaoCodeList getAirlineIcaoCodesForDesignator(const QString &designator) const; //! Get airline ICAO information for key //! \threadsafe diff --git a/src/blackcore/webdataservices.cpp b/src/blackcore/webdataservices.cpp index 6d37efdd9..525491904 100644 --- a/src/blackcore/webdataservices.cpp +++ b/src/blackcore/webdataservices.cpp @@ -362,6 +362,12 @@ namespace BlackCore return 0; } + CAirlineIcaoCode CWebDataServices::smartAirlineIcaoSelector(const CAirlineIcaoCode &icaoPattern) const + { + if (m_icaoDataReader) { return m_icaoDataReader->smartAirlineIcaoSelector(icaoPattern); } + return CAirlineIcaoCode(); + } + CAirlineIcaoCode CWebDataServices::getAirlineIcaoCodeForDbKey(int key) const { if (m_icaoDataReader) { return m_icaoDataReader->getAirlineIcaoCodeForDbKey(key); } @@ -410,10 +416,10 @@ namespace BlackCore return 0; } - CAirlineIcaoCode CWebDataServices::getAirlineIcaoCodeForDesignator(const QString &designator) const + CAirlineIcaoCodeList CWebDataServices::getAirlineIcaoCodeForDesignator(const QString &designator) const { - if (m_icaoDataReader) { return m_icaoDataReader->getAirlineIcaoCodeForDesignator(designator); } - return CAirlineIcaoCode(); + if (m_icaoDataReader) { return m_icaoDataReader->getAirlineIcaoCodesForDesignator(designator); } + return CAirlineIcaoCodeList(); } void CWebDataServices::gracefulShutdown() diff --git a/src/blackcore/webdataservices.h b/src/blackcore/webdataservices.h index 8345271ce..ed92b85d0 100644 --- a/src/blackcore/webdataservices.h +++ b/src/blackcore/webdataservices.h @@ -77,185 +77,60 @@ namespace BlackCore // ------------------------ provider functionality start ------------------------------ - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::connectDataReadSignal - //! \ingroup webdatareaderprovider + //! \name Provider interface functions + //! @{ virtual QList connectDataReadSignal( QObject *receiver, std::function dataRead) override; - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::connectDataPublishSignal - //! \ingroup webdatareaderprovider virtual QList connectDataPublishSignal( QObject *receiver, std::function dataPublished) override; - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::triggerRead - //! \ingroup webdatareaderprovider virtual BlackMisc::Network::CEntityFlags::Entity triggerRead(BlackMisc::Network::CEntityFlags::Entity whatToRead, const QDateTime &newerThan = QDateTime()) override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getVatsimFsdServers - //! \ingroup webdatareaderprovider virtual BlackMisc::Network::CServerList getVatsimFsdServers() const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getVatsimVoiceServers - //! \ingroup webdatareaderprovider virtual BlackMisc::Network::CServerList getVatsimVoiceServers() const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getDistributors - //! \ingroup webdatareaderprovider virtual BlackMisc::Simulation::CDistributorList getDistributors() const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getDistributorsCount - //! \ingroup webdatareaderprovider virtual int getDistributorsCount() const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::smartDistributorSelector - //! \ingroup webdatareaderprovider virtual BlackMisc::Simulation::CDistributor smartDistributorSelector(const BlackMisc::Simulation::CDistributor &distributor) const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getLiveries - //! \ingroup webdatareaderprovider virtual BlackMisc::Aviation::CLiveryList getLiveries() const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getLiveriesCount - //! \ingroup webdatareaderprovider virtual int getLiveriesCount() const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getLiveryForCombinedCode - //! \ingroup webdatareaderprovider virtual BlackMisc::Aviation::CLivery getLiveryForCombinedCode(const QString &combinedCode) const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getStdLiveryForAirlineCode - //! \ingroup webdatareaderprovider virtual BlackMisc::Aviation::CLivery getStdLiveryForAirlineCode(const BlackMisc::Aviation::CAirlineIcaoCode &icao) const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getLiveryForDbKey - //! \ingroup webdatareaderprovider virtual BlackMisc::Aviation::CLivery getLiveryForDbKey(int id) const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::smartLiverySelector - //! \ingroup webdatareaderprovider virtual BlackMisc::Aviation::CLivery smartLiverySelector(const BlackMisc::Aviation::CLivery &livery) const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getModels - //! \ingroup webdatareaderprovider virtual BlackMisc::Simulation::CAircraftModelList getModels() const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getModelsCount - //! \ingroup webdatareaderprovider virtual int getModelsCount() const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getModelDbKeys - //! \ingroup webdatareaderprovider virtual QList getModelDbKeys() const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getModelStrings - //! \ingroup webdatareaderprovider virtual QStringList getModelStrings() const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getModelsForAircraftDesignatorAndLiveryCombinedCode - //! \ingroup webdatareaderprovider virtual BlackMisc::Simulation::CAircraftModelList getModelsForAircraftDesignatorAndLiveryCombinedCode(const QString &aircraftDesignator, const QString &combinedCode) const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getModelForModelString - //! \ingroup webdatareaderprovider virtual BlackMisc::Simulation::CAircraftModel getModelForModelString(const QString &modelString) const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getAircraftIcaoCodes - //! \ingroup webdatareaderprovider virtual BlackMisc::Aviation::CAircraftIcaoCodeList getAircraftIcaoCodes() const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getAircraftIcaoCodesCount - //! \ingroup webdatareaderprovider virtual int getAircraftIcaoCodesCount() const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getAircraftIcaoCodeForDesignator - //! \ingroup webdatareaderprovider virtual BlackMisc::Aviation::CAircraftIcaoCode getAircraftIcaoCodeForDesignator(const QString &designator) const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getAircraftIcaoCodeForDbKey - //! \ingroup webdatareaderprovider virtual BlackMisc::Aviation::CAircraftIcaoCode getAircraftIcaoCodeForDbKey(int key) const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getAircraftIcaoCodeForDbKey - //! \ingroup webdatareaderprovider virtual BlackMisc::Aviation::CAircraftIcaoCode smartAircraftIcaoSelector(const BlackMisc::Aviation::CAircraftIcaoCode &icao) const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getAirlineIcaoCodes - //! \ingroup webdatareaderprovider virtual BlackMisc::Aviation::CAirlineIcaoCodeList getAirlineIcaoCodes() const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getAirlineIcaoCodesCount - //! \ingroup webdatareaderprovider virtual int getAirlineIcaoCodesCount() const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getAirlineIcaoCodeForDbKey - //! \ingroup webdatareaderprovider + virtual BlackMisc::Aviation::CAirlineIcaoCode smartAirlineIcaoSelector(const BlackMisc::Aviation::CAirlineIcaoCode &icaoPattern) const override; virtual BlackMisc::Aviation::CAirlineIcaoCode getAirlineIcaoCodeForDbKey(int key) const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getAirlineIcaoCodeForDesignator - //! \ingroup webdatareaderprovider - virtual BlackMisc::Aviation::CAirlineIcaoCode getAirlineIcaoCodeForDesignator(const QString &designator) const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getCountries - //! \ingroup webdatareaderprovider + virtual BlackMisc::Aviation::CAirlineIcaoCodeList getAirlineIcaoCodeForDesignator(const QString &designator) const override; virtual BlackMisc::CCountryList getCountries() const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getCountries - //! \ingroup webdatareaderprovider virtual int getCountriesCount() const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getCountryForName - //! \ingroup webdatareaderprovider virtual BlackMisc::CCountry getCountryForName(const QString &name) const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getCountryForIsoCode - //! \ingroup webdatareaderprovider virtual BlackMisc::CCountry getCountryForIsoCode(const QString &iso) const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getMetars - //! \ingroup webdatareaderprovider virtual BlackMisc::Weather::CMetarSet getMetars() const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getMetarForAirport - //! \ingroup webdatareaderprovider virtual BlackMisc::Weather::CMetar getMetarForAirport(const BlackMisc::Aviation::CAirportIcaoCode &icao) const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getMetarForAirport - //! \ingroup webdatareaderprovider virtual int getMetarsCount() const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getUsersForCallsign - //! \ingroup webdatareaderprovider virtual BlackMisc::Network::CUserList getUsersForCallsign(const BlackMisc::Aviation::CCallsign &callsign) const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getAtcStationsForCallsign - //! \ingroup webdatareaderprovider virtual BlackMisc::Aviation::CAtcStationList getAtcStationsForCallsign(const BlackMisc::Aviation::CCallsign &callsign) const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::getVoiceCapabilityForCallsign - //! \ingroup webdatareaderprovider virtual BlackMisc::Network::CVoiceCapabilities getVoiceCapabilityForCallsign(const BlackMisc::Aviation::CCallsign &callsign) const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::updateWithWebData - //! \ingroup webdatareaderprovider virtual void updateWithVatsimDataFileData(BlackMisc::Simulation::CSimulatedAircraft &aircraftToBeUdpated) const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::asyncPublishModels - //! \ingroup webdatareaderprovider virtual BlackMisc::CStatusMessageList asyncPublishModels(const BlackMisc::Simulation::CAircraftModelList &models) const override; - - //! \copydoc BlackMisc::Network::IWebDataServicesProvider::canConnectSwiftDb - //! \ingroup webdatareaderprovider virtual bool canConnectSwiftDb() const override; - - //! Save all DB data to a JSON files - //! \ingroup webdatareaderprovider virtual bool writeDbDataToDisk(const QString &dir) const override; - - //! Load DB data from JSON files - //! \ingroup webdatareaderprovider virtual bool readDbDataFromDisk(const QString &dir, bool inBackground) override; + //! }@ // ------------------------ provider functionality end ---------------------------- diff --git a/src/blackmisc/aviation/aircrafticaocode.cpp b/src/blackmisc/aviation/aircrafticaocode.cpp index 07efad279..d28563119 100644 --- a/src/blackmisc/aviation/aircrafticaocode.cpp +++ b/src/blackmisc/aviation/aircrafticaocode.cpp @@ -25,7 +25,7 @@ namespace BlackMisc namespace Aviation { CAircraftIcaoCode::CAircraftIcaoCode(const QString &designator, const QString &combinedType) : - m_designator(designator), m_combinedType(combinedType) + m_designator(designator.trimmed().toUpper()), m_combinedType(combinedType.trimmed().toUpper()) {} CAircraftIcaoCode::CAircraftIcaoCode(const QString &icao, const QString &combinedType, const QString &manufacturer, const QString &model, const QString &wtc, bool realworld, bool legacy, bool military, int rank) @@ -58,13 +58,14 @@ namespace BlackMisc void CAircraftIcaoCode::updateMissingParts(const CAircraftIcaoCode &otherIcaoCode) { - if (!this->hasDesignator()) { this->setDesignator(otherIcaoCode.getDesignator()); } - if (!this->hasValidWtc()) { this->setWtc(otherIcaoCode.getDesignator()); } - if (!this->hasValidCombinedType()) { this->setCombinedType(otherIcaoCode.getCombinedType()); } + if (!this->hasValidDesignator() && otherIcaoCode.hasValidDesignator()) { this->setDesignator(otherIcaoCode.getDesignator()); } + if (!this->hasValidWtc() && otherIcaoCode.hasValidWtc()) { this->setWtc(otherIcaoCode.getDesignator()); } + if (!this->hasValidCombinedType() && otherIcaoCode.hasValidCombinedType()) { this->setCombinedType(otherIcaoCode.getCombinedType()); } if (this->m_manufacturer.isEmpty()) { this->setManufacturer(otherIcaoCode.getManufacturer());} if (this->m_modelDescription.isEmpty()) { this->setModelDescription(otherIcaoCode.getModelDescription()); } if (!this->hasValidDbKey()) { + // need to observe if it makes sense to copy the key but not copying the whole object this->setDbKey(otherIcaoCode.getDbKey()); this->setUtcTimestamp(otherIcaoCode.getUtcTimestamp()); } @@ -87,9 +88,14 @@ namespace BlackMisc return !this->m_designator.isEmpty(); } + bool CAircraftIcaoCode::hasValidDesignator() const + { + return isValidDesignator(this->m_designator); + } + bool CAircraftIcaoCode::hasKnownDesignator() const { - return (this->hasDesignator() && this->getDesignator() != "ZZZZ"); + return (this->hasValidDesignator() && this->getDesignator() != getUnassignedDesignator()); } bool CAircraftIcaoCode::isIataSameAsDesignator() const @@ -431,6 +437,29 @@ namespace BlackMisc return false; } + const QString &CAircraftIcaoCode::getUnassignedDesignator() + { + static const QString i("ZZZZ"); + return i; + } + + const QStringList &CAircraftIcaoCode::getSpecialDesignators() + { + static const QStringList s({ "ZZZZ", "SHIP", "BALL", "GLID", "ULAC", "GYRO", "UHEL", "GLID", "ULAC", "GYRO", "UHEL"}); + return s; + } + + const QString CAircraftIcaoCode::normalizeDesignator(const QString candidate) + { + QString n(candidate.trimmed().toUpper()); + if (n.isEmpty()) { return n; } + + static QThreadStorage tsRegex; + if (! tsRegex.hasLocalData()) { tsRegex.setLocalData(QRegularExpression("[^a-zA-Z\\d\\s]")); } + const QRegularExpression ®exp = tsRegex.localData(); + return n.remove(regexp); + } + CAircraftIcaoCode CAircraftIcaoCode::fromDatabaseJson(const QJsonObject &json, const QString &prefix) { if (!existsKey(json, prefix)) diff --git a/src/blackmisc/aviation/aircrafticaocode.h b/src/blackmisc/aviation/aircrafticaocode.h index 0962a24ff..3626397f8 100644 --- a/src/blackmisc/aviation/aircrafticaocode.h +++ b/src/blackmisc/aviation/aircrafticaocode.h @@ -72,6 +72,9 @@ namespace BlackMisc //! Aircraft designator? bool hasDesignator() const; + //! Valid aircraft designator? + bool hasValidDesignator() const; + //! Has designator and designator is not "ZZZZ" bool hasKnownDesignator() const; @@ -237,6 +240,15 @@ namespace BlackMisc //! Valid WTC code? static bool isValidWtc(const QString &candidate); + //! The unassigned designator ("ZZZZ") + static const QString &getUnassignedDesignator(); + + //! List of the special designators ("ZZZZ", "UHEL", ...) + static const QStringList &getSpecialDesignators(); + + //! Normalize designator, remove illegal characters + static const QString normalizeDesignator(const QString candidate); + //! From our database JSON format static CAircraftIcaoCode fromDatabaseJson(const QJsonObject &json, const QString &prefix = QString()); diff --git a/src/blackmisc/aviation/aircrafticaocodelist.cpp b/src/blackmisc/aviation/aircrafticaocodelist.cpp index 32ad87bba..48ecf7664 100644 --- a/src/blackmisc/aviation/aircrafticaocodelist.cpp +++ b/src/blackmisc/aviation/aircrafticaocodelist.cpp @@ -135,6 +135,7 @@ namespace BlackMisc if (c.hasCompleteData()) { return c; } } + // get an initial set of data we can choose from CAircraftIcaoCodeList codes; if (icaoPattern.hasKnownDesignator()) { @@ -172,7 +173,7 @@ namespace BlackMisc } // further reduce by manufacturer - if (icaoPattern.hasManufacturer()) + if (icaoPattern.hasManufacturer() && codes.contains(&CAircraftIcaoCode::getManufacturer, icaoPattern.getManufacturer())) { const QString m(icaoPattern.getManufacturer()); codes = codes.findByManufacturer(m); @@ -181,17 +182,25 @@ namespace BlackMisc // intentionally continue here } + // further reduce by IATA + if (icaoPattern.hasIataCode() && codes.contains(&CAircraftIcaoCode::getIataCode, icaoPattern.getIataCode())) + { + const QString i(icaoPattern.getIataCode()); + codes = codes.findByIataCode(i); + if (codes.size() == 1) { return codes.front(); } + + // intentionally continue here + } + // lucky punch on description? - if (icaoPattern.hasModelDescription()) + if (icaoPattern.hasModelDescription() && codes.contains(&CAircraftIcaoCode::getModelDescription, icaoPattern.getModelDescription())) { // do not affect codes here, it might return no results const QString d(icaoPattern.getModelDescription()); CAircraftIcaoCodeList cm(codes.findByDescription(d)); if (cm.size() == 1) { return cm.front(); } - if (cm.size() > 1 && cm.size() < codes.size()) { return codes.front(); } } return codes.frontOrDefault(); // sorted by rank } - } // namespace } // namespace diff --git a/src/blackmisc/aviation/airlineicaocode.cpp b/src/blackmisc/aviation/airlineicaocode.cpp index f37cc5ace..d55e4fea6 100644 --- a/src/blackmisc/aviation/airlineicaocode.cpp +++ b/src/blackmisc/aviation/airlineicaocode.cpp @@ -38,6 +38,17 @@ namespace BlackMisc return QString("V").append(this->m_designator); } + void CAirlineIcaoCode::setDesignator(const QString &icaoDesignator) + { + this->m_designator = icaoDesignator.trimmed().toUpper(); + if (this->m_designator.length() == 4 && this->m_designator.startsWith("V")) + { + // a virtual designator was provided + this->setVirtualAirline(true); + this->m_designator = this->m_designator.right(3); + } + } + QString CAirlineIcaoCode::getDesignatorNameCountry() const { QString s(this->getDesignator()); @@ -56,6 +67,11 @@ namespace BlackMisc return isValidAirlineDesignator(m_designator); } + bool CAirlineIcaoCode::hasIataCode() const + { + return !this->m_iataCode.isEmpty(); + } + bool CAirlineIcaoCode::matchesDesignator(const QString &designator) const { if (designator.isEmpty()) { return false; } @@ -68,6 +84,24 @@ namespace BlackMisc return designator.trimmed().toUpper() == this->getVDesignator(); } + bool CAirlineIcaoCode::matchesIataCode(const QString &iata) const + { + if (iata.isEmpty()) { return false; } + return iata.trimmed().toUpper() == this->m_iataCode; + } + + bool CAirlineIcaoCode::matchesDesignatorOrIataCode(const QString &candidate) const + { + if (candidate.isEmpty()) { return false; } + return this->matchesDesignator(candidate) || this->matchesIataCode(candidate); + } + + bool CAirlineIcaoCode::matchesVDesignatorOrIataCode(const QString &candidate) const + { + if (candidate.isEmpty()) { return false; } + return this->matchesVDesignator(candidate) || this->matchesIataCode(candidate); + } + bool CAirlineIcaoCode::hasCompleteData() const { return this->hasValidDesignator() && this->hasValidCountry() && this->hasName(); @@ -105,6 +139,8 @@ namespace BlackMisc { case IndexAirlineDesignator: return CVariant::fromValue(this->m_designator); + case IndexIataCode: + return CVariant::fromValue(this->m_iataCode); case IndexAirlineCountryIso: return CVariant::fromValue(this->getCountryIso()); case IndexAirlineCountry: @@ -134,6 +170,9 @@ namespace BlackMisc case IndexAirlineDesignator: this->setDesignator(variant.value()); break; + case IndexIataCode: + this->setIataCode(variant.value()); + break; case IndexAirlineCountry: this->setCountry(variant.value()); break; @@ -164,6 +203,8 @@ namespace BlackMisc { case IndexAirlineDesignator: return this->m_designator.compare(compareValue.getDesignator()); + case IndexIataCode: + return this->m_iataCode.compare(compareValue.getIataCode()); case IndexAirlineCountry: return this->m_country.comparePropertyByIndex(compareValue.getCountry(), index.copyFrontRemoved()); case IndexDesignatorNameCountry: @@ -198,7 +239,7 @@ namespace BlackMisc if (airline.length() < 2 || airline.length() > 5) return false; static QThreadStorage tsRegex; - if (! tsRegex.hasLocalData()) { tsRegex.setLocalData(QRegularExpression("^[A-Z]+[A-Z0-9]*$")); } + if (! tsRegex.hasLocalData()) { tsRegex.setLocalData(QRegularExpression("^[A-Z0-9]+$")); } const QRegularExpression ®exp = tsRegex.localData(); return (regexp.match(airline).hasMatch()); } @@ -255,6 +296,7 @@ namespace BlackMisc } QString designator(json.value(prefix + "designator").toString()); + QString iata(json.value(prefix + "iata").toString()); QString telephony(json.value(prefix + "callsign").toString()); QString name(json.value(prefix + "name").toString()); QString countryIso(json.value(prefix + "country").toString()); @@ -266,6 +308,7 @@ namespace BlackMisc CCountry(countryIso, countryName), telephony, va, operating ); + code.setIataCode(iata); code.setKeyAndTimestampFromDatabaseJson(json, prefix); return code; } diff --git a/src/blackmisc/aviation/airlineicaocode.h b/src/blackmisc/aviation/airlineicaocode.h index 4bbf41df4..d8dd935f6 100644 --- a/src/blackmisc/aviation/airlineicaocode.h +++ b/src/blackmisc/aviation/airlineicaocode.h @@ -34,6 +34,7 @@ namespace BlackMisc enum ColumnIndex { IndexAirlineDesignator = BlackMisc::CPropertyIndex::GlobalIndexCAirlineIcaoCode, + IndexIataCode, IndexAirlineName, IndexAirlineCountryIso, IndexAirlineCountry, @@ -59,7 +60,13 @@ namespace BlackMisc const QString getVDesignator() const; //! Set airline, e.g. "DLH" - void setDesignator(const QString &icaoDesignator) { this->m_designator = icaoDesignator.trimmed().toUpper(); } + void setDesignator(const QString &icaoDesignator); + + //! IATA code + const QString &getIataCode() const { return m_iataCode; } + + //! Set IATA code + void setIataCode(const QString &iataCode) { this->m_iataCode = iataCode.trimmed().toUpper(); } //! Get country, e.g. "FR" const QString &getCountryIso() const { return this->m_country.getIsoCode(); } @@ -106,12 +113,24 @@ namespace BlackMisc //! Airline designator available? bool hasValidDesignator() const; + //! IATA code? + bool hasIataCode() const; + //! Matches designator string? bool matchesDesignator(const QString &designator) const; //! Matches v-designator string? bool matchesVDesignator(const QString &designator) const; + //! Matches IATA code? + bool matchesIataCode(const QString &iata) const; + + //! Matches IATA code or designator? + bool matchesDesignatorOrIataCode(const QString &candidate) const; + + //! Matches IATA code or v-designator? + bool matchesVDesignatorOrIataCode(const QString &candidate) const; + //! Telephony designator? bool hasTelephonyDesignator() const { return !this->m_telephonyDesignator.isEmpty(); } @@ -154,6 +173,7 @@ namespace BlackMisc private: BLACK_ENABLE_TUPLE_CONVERSION(CAirlineIcaoCode) QString m_designator; //!< "DLH" + QString m_iataCode; //!< "LH" QString m_name; //!< "Lufthansa" BlackMisc::CCountry m_country; //!< Country QString m_telephonyDesignator; //!< "Speedbird" diff --git a/src/blackmisc/aviation/airlineicaocodelist.cpp b/src/blackmisc/aviation/airlineicaocodelist.cpp index 989e357ce..9272146f3 100644 --- a/src/blackmisc/aviation/airlineicaocodelist.cpp +++ b/src/blackmisc/aviation/airlineicaocodelist.cpp @@ -17,7 +17,7 @@ namespace BlackMisc CSequence(other) { } - CAirlineIcaoCodeList CAirlineIcaoCodeList::findByDesignator(const QString &designator) + CAirlineIcaoCodeList CAirlineIcaoCodeList::findByDesignator(const QString &designator) const { if (CAirlineIcaoCode::isValidAirlineDesignator(designator)) { return CAirlineIcaoCodeList(); } return this->findBy([&](const CAirlineIcaoCode & code) @@ -26,6 +26,52 @@ namespace BlackMisc }); } + CAirlineIcaoCodeList CAirlineIcaoCodeList::findByIataCode(const QString &iata) const + { + if (iata.isEmpty()) { return CAirlineIcaoCodeList(); } + return this->findBy([&](const CAirlineIcaoCode & code) + { + return code.matchesIataCode(iata); + }); + } + + CAirlineIcaoCodeList CAirlineIcaoCodeList::findByDesignatorOrIataCode(const QString &designatorOrIata) const + { + if (designatorOrIata.isEmpty()) { return CAirlineIcaoCodeList(); } + return this->findBy([&](const CAirlineIcaoCode & code) + { + return code.matchesDesignatorOrIataCode(designatorOrIata); + }); + } + + CAirlineIcaoCodeList CAirlineIcaoCodeList::findByVDesignator(const QString &designator) const + { + if (!CAirlineIcaoCode::isValidAirlineDesignator(designator)) { return CAirlineIcaoCodeList(); } + return this->findBy([&](const CAirlineIcaoCode & code) + { + return code.matchesVDesignator(designator); + }); + } + + CAirlineIcaoCodeList CAirlineIcaoCodeList::findByVDesignatorOrIataCode(const QString &designatorOrIata) const + { + if (designatorOrIata.isEmpty()) { return CAirlineIcaoCodeList(); } + return this->findBy([&](const CAirlineIcaoCode & code) + { + return code.matchesVDesignatorOrIataCode(designatorOrIata); + }); + } + + CAirlineIcaoCodeList CAirlineIcaoCodeList::findByCountryIsoCode(const QString &isoCode) const + { + if (isoCode.length() != 2) { return CAirlineIcaoCodeList(); } + const QString iso(isoCode.toUpper()); + return this->findBy([&](const CAirlineIcaoCode & code) + { + return code.getCountry().getIsoCode() == iso; + }); + } + CAirlineIcaoCode CAirlineIcaoCodeList::smartAirlineIcaoSelector(const CAirlineIcaoCode &icaoPattern) const { if (icaoPattern.hasValidDbKey()) @@ -33,19 +79,28 @@ namespace BlackMisc return this->findByKey(icaoPattern.getDbKey(), icaoPattern); } - if (!icaoPattern.hasValidDesignator()) { return CAirlineIcaoCode(); } - - //! \todo smart airline selector, further criteria - return icaoPattern; - } - - CAirlineIcaoCode CAirlineIcaoCodeList::findByVDesignator(const QString &designator) - { - if (!CAirlineIcaoCode::isValidAirlineDesignator(designator)) { return CAirlineIcaoCode(); } - return this->findFirstByOrDefault([&](const CAirlineIcaoCode & code) + // search by parts + CAirlineIcaoCodeList codes; + if (icaoPattern.hasValidDesignator()) { - return code.matchesVDesignator(designator); - }); + codes = this->findByVDesignator(icaoPattern.getVDesignator()); + } + else + { + codes == this->findByIataCode(icaoPattern.getIataCode()); + } + + if (codes.size() == 1) { return codes.front(); } + + // further reduce + if (icaoPattern.hasValidCountry()) + { + CAirlineIcaoCodeList countryCodes = codes.findByCountryIsoCode(icaoPattern.getCountry().getIsoCode()); + if (!countryCodes.isEmpty()) { return countryCodes.front(); } + } + + if (!codes.isEmpty()) { return codes.front(); } + return icaoPattern; } CAirlineIcaoCodeList CAirlineIcaoCodeList::fromDatabaseJson(const QJsonArray &array, bool ignoreIncomplete) diff --git a/src/blackmisc/aviation/airlineicaocodelist.h b/src/blackmisc/aviation/airlineicaocodelist.h index 6ced35e8d..f5e0fd7df 100644 --- a/src/blackmisc/aviation/airlineicaocodelist.h +++ b/src/blackmisc/aviation/airlineicaocodelist.h @@ -41,14 +41,27 @@ namespace BlackMisc //! Find by designator //! Not unique because of virtual airlines - CAirlineIcaoCodeList findByDesignator(const QString &designator); + CAirlineIcaoCodeList findByDesignator(const QString &designator) const; + + //! Find by v-designator, this should be unique + CAirlineIcaoCodeList findByVDesignator(const QString &designator) const; + + //! Find by IATA code + //! Not unique because of virtual airlines + CAirlineIcaoCodeList findByIataCode(const QString &iata) const; + + //! Find by designator or IATA code + CAirlineIcaoCodeList findByDesignatorOrIataCode(const QString &designatorOrIata) const; + + //! Find by v-designator or IATA code + CAirlineIcaoCodeList findByVDesignatorOrIataCode(const QString &designatorOrIata) const; + + //! Find by country code + CAirlineIcaoCodeList findByCountryIsoCode(const QString &isoCode) const; //! Best selection by given pattern CAirlineIcaoCode smartAirlineIcaoSelector(const CAirlineIcaoCode &icaoPattern) const; - //! Find by v-designator, this should be unique - CAirlineIcaoCode findByVDesignator(const QString &designator); - //! String list for completion by ICAO designator QStringList toIcaoDesignatorCompleterStrings() const; diff --git a/src/blackmisc/network/webdataservicesprovider.cpp b/src/blackmisc/network/webdataservicesprovider.cpp index 1b73ae68f..562890b47 100644 --- a/src/blackmisc/network/webdataservicesprovider.cpp +++ b/src/blackmisc/network/webdataservicesprovider.cpp @@ -205,11 +205,18 @@ namespace BlackMisc return this->m_webDataReaderProvider->getAirlineIcaoCodesCount(); } - CAirlineIcaoCode CWebDataServicesAware::getAirlineIcaoCodeForDesignator(const QString &designator) const + CAirlineIcaoCodeList CWebDataServicesAware::getAirlineIcaoCodesForDesignator(const QString &designator) const + { + Q_ASSERT_X(this->m_webDataReaderProvider, Q_FUNC_INFO, "Missing provider"); + if (!hasProvider()) { return CAirlineIcaoCodeList(); } + return this->m_webDataReaderProvider->getAirlineIcaoCodeForDesignator(designator); + } + + CAirlineIcaoCode CWebDataServicesAware::smartAirlineIcaoSelector(const CAirlineIcaoCode &code) const { Q_ASSERT_X(this->m_webDataReaderProvider, Q_FUNC_INFO, "Missing provider"); if (!hasProvider()) { return CAirlineIcaoCode(); } - return this->m_webDataReaderProvider->getAirlineIcaoCodeForDesignator(designator); + return this->m_webDataReaderProvider->smartAirlineIcaoSelector(code); } CAirlineIcaoCode CWebDataServicesAware::getAirlineIcaoCodeForDbKey(int id) const diff --git a/src/blackmisc/network/webdataservicesprovider.h b/src/blackmisc/network/webdataservicesprovider.h index 50bb1f457..511467d49 100644 --- a/src/blackmisc/network/webdataservicesprovider.h +++ b/src/blackmisc/network/webdataservicesprovider.h @@ -158,12 +158,16 @@ namespace BlackMisc //! ICAO code for designator //! \threadsafe - virtual BlackMisc::Aviation::CAirlineIcaoCode getAirlineIcaoCodeForDesignator(const QString &designator) const = 0; + virtual BlackMisc::Aviation::CAirlineIcaoCodeList getAirlineIcaoCodeForDesignator(const QString &designator) const = 0; //! ICAO code for id //! \threadsafe virtual BlackMisc::Aviation::CAirlineIcaoCode getAirlineIcaoCodeForDbKey(int id) const = 0; + //! Smart airline selector + //! \threadsafe + virtual Aviation::CAirlineIcaoCode smartAirlineIcaoSelector(const BlackMisc::Aviation::CAirlineIcaoCode &code) const = 0; + //! Countries //! \threadsafe virtual BlackMisc::CCountryList getCountries() const = 0; @@ -315,7 +319,10 @@ namespace BlackMisc int getAirlineIcaoCodesCount() const; //! \copydoc IWebDataServicesProvider::getAirlineIcaoCodeForDesignator - BlackMisc::Aviation::CAirlineIcaoCode getAirlineIcaoCodeForDesignator(const QString &designator) const; + Aviation::CAirlineIcaoCodeList getAirlineIcaoCodesForDesignator(const QString &designator) const; + + //! \copydoc IWebDataServicesProvider::smartAirlineIcaoSelector + Aviation::CAirlineIcaoCode smartAirlineIcaoSelector(const BlackMisc::Aviation::CAirlineIcaoCode &code) const; //! \copydoc IWebDataServicesProvider::getAirlineIcaoCodeForDbKey BlackMisc::Aviation::CAirlineIcaoCode getAirlineIcaoCodeForDbKey(int id) const; diff --git a/src/blackmisc/simulation/aircraftmodellist.cpp b/src/blackmisc/simulation/aircraftmodellist.cpp index 1c92f8c8b..78667ab9c 100644 --- a/src/blackmisc/simulation/aircraftmodellist.cpp +++ b/src/blackmisc/simulation/aircraftmodellist.cpp @@ -90,6 +90,14 @@ namespace BlackMisc }); } + CAircraftModelList CAircraftModelList::findWithFileName() const + { + return this->findBy([ = ](const CAircraftModel & model) + { + return model.hasFileName(); + }); + } + void CAircraftModelList::setSimulatorInfo(const CSimulatorInfo &info) { for (CAircraftModel &model : (*this)) diff --git a/src/blackmisc/simulation/aircraftmodellist.h b/src/blackmisc/simulation/aircraftmodellist.h index 40108cc72..4b8525f9c 100644 --- a/src/blackmisc/simulation/aircraftmodellist.h +++ b/src/blackmisc/simulation/aircraftmodellist.h @@ -64,6 +64,9 @@ namespace BlackMisc //! Find by model string CAircraftModelList findByAircraftDesignatorAndLiveryCombinedCode(const QString &aircraftDesignator, const QString &combinedCode) const; + //! With file name + CAircraftModelList findWithFileName() const; + //! Set simulator for all elements void setSimulatorInfo(const BlackMisc::Simulation::CSimulatorInfo &info);