From 940c0ce0c4711a5d0a58be6fdbb2a7a29c8cc26a Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Thu, 28 Jan 2016 04:06:05 +0100 Subject: [PATCH] refs #580, refs #586, add IATA code/family to aircraft ICAO object (alias) and list * fixed const * finders * completer strings --- src/blackmisc/aviation/aircrafticaocode.cpp | 93 ++++++++++++++++++- src/blackmisc/aviation/aircrafticaocode.h | 58 +++++++++++- .../aviation/aircrafticaocodelist.cpp | 71 ++++++++++++-- src/blackmisc/aviation/aircrafticaocodelist.h | 22 ++++- 4 files changed, 225 insertions(+), 19 deletions(-) diff --git a/src/blackmisc/aviation/aircrafticaocode.cpp b/src/blackmisc/aviation/aircrafticaocode.cpp index 00938767c..07efad279 100644 --- a/src/blackmisc/aviation/aircrafticaocode.cpp +++ b/src/blackmisc/aviation/aircrafticaocode.cpp @@ -29,7 +29,19 @@ namespace BlackMisc {} 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) - : m_designator(icao.trimmed().toUpper()), m_combinedType(combinedType.trimmed().toUpper()), m_manufacturer(manufacturer.trimmed()), + : m_designator(icao.trimmed().toUpper()), + m_combinedType(combinedType.trimmed().toUpper()), + m_manufacturer(manufacturer.trimmed()), + m_modelDescription(model.trimmed()), m_wtc(wtc.trimmed().toUpper()), m_realWorld(realworld), m_legacy(legacy), m_military(military), m_rank(rank) + { + if (m_rank < 0 || m_rank >= 10) { m_rank = 10; } + } + + CAircraftIcaoCode::CAircraftIcaoCode(const QString &icao, const QString &iata, const QString &combinedType, const QString &manufacturer, const QString &model, const QString &wtc, bool realworld, bool legacy, bool military, int rank) + : m_designator(icao.trimmed().toUpper()), + m_iataCode(iata.trimmed().toUpper()), + m_combinedType(combinedType.trimmed().toUpper()), + m_manufacturer(manufacturer.trimmed()), m_modelDescription(model.trimmed()), m_wtc(wtc.trimmed().toUpper()), m_realWorld(realworld), m_legacy(legacy), m_military(military), m_rank(rank) { if (m_rank < 0 || m_rank >= 10) { m_rank = 10; } @@ -60,7 +72,7 @@ namespace BlackMisc CStatusMessageList CAircraftIcaoCode::validate() const { - static const CLogCategoryList cats( { CLogCategory("swift.blackmisc.aircrafticao"), CLogCategory::validation()}); + static const CLogCategoryList cats({ CLogCategory("swift.blackmisc.aircrafticao"), CLogCategory::validation()}); CStatusMessageList msg; if (!hasKnownDesignator()) { msg.push_back(CStatusMessage(cats, CStatusMessage::SeverityError, "Aircraft ICAO: unknown designator")); } if (!hasValidCombinedType()) { msg.push_back(CStatusMessage(cats, CStatusMessage::SeverityError, "Aircraft ICAO: invalid combined type")); } @@ -80,6 +92,16 @@ namespace BlackMisc return (this->hasDesignator() && this->getDesignator() != "ZZZZ"); } + bool CAircraftIcaoCode::isIataSameAsDesignator() const + { + return hasDesignator() && hasIataCode() && m_iataCode == m_designator; + } + + bool CAircraftIcaoCode::isFamilySameAsDesignator() const + { + return hasFamily() && hasDesignator() && m_designator == m_family; + } + bool CAircraftIcaoCode::hasValidCombinedType() const { return isValidCombinedType(getCombinedType()); @@ -191,7 +213,7 @@ namespace BlackMisc } } - QString CAircraftIcaoCode::getCombinedStringWithKey() const + QString CAircraftIcaoCode::getCombinedIcaoStringWithKey() const { QString s(getDesignator()); if (hasManufacturer()) { s = s.append(" ").append(getManufacturer()); } @@ -199,6 +221,26 @@ namespace BlackMisc return s.append(" ").append(getDbKeyAsStringInParentheses()); } + QString CAircraftIcaoCode::getCombinedIataStringWithKey() const + { + if (!this->hasIataCode()) { return ""; } + QString s(getIataCode()); + s = s.append(" [IATA]"); + if (hasManufacturer()) { s = s.append(" ").append(getManufacturer()); } + if (hasModelDescription()) { s = s.append(" ").append(getModelDescription()); } + return s.append(" ").append(getDbKeyAsStringInParentheses()); + } + + QString CAircraftIcaoCode::getCombinedFamilyStringWithKey() const + { + if (!this->hasFamily()) { return ""; } + QString s(getFamily()); + s = s.append(" [family]"); + if (hasManufacturer()) { s = s.append(" ").append(getManufacturer()); } + if (hasModelDescription()) { s = s.append(" ").append(getModelDescription()); } + return s.append(" ").append(getDbKeyAsStringInParentheses()); + } + bool CAircraftIcaoCode::hasCompleteData() const { return hasValidCombinedType() && hasDesignator() && hasValidWtc() && hasManufacturer(); @@ -210,6 +252,32 @@ namespace BlackMisc return designator.trimmed().toUpper() == this->m_designator; } + bool CAircraftIcaoCode::matchesIataCode(const QString &iata) const + { + if (iata.isEmpty()) { return false; } + return iata.trimmed().toUpper() == this->m_iataCode; + } + + bool CAircraftIcaoCode::matchesFamily(const QString &family) const + { + if (family.isEmpty()) { return false; } + return family.trimmed().toUpper() == this->m_family; + } + + bool CAircraftIcaoCode::matchesDesignatorOrIata(const QString &icaoOrIata) const + { + if (icaoOrIata.isEmpty()) { return false; } + return matchesDesignator(icaoOrIata) || matchesIataCode(icaoOrIata); + } + + bool CAircraftIcaoCode::matchesDesignatorIataOrFamily(const QString &icaoIataOrFamily) const + { + if (icaoIataOrFamily.isEmpty()) { return false; } + return matchesDesignator(icaoIataOrFamily) || + matchesIataCode(icaoIataOrFamily) || + matchesFamily(icaoIataOrFamily); + } + CVariant CAircraftIcaoCode::propertyByIndex(const BlackMisc::CPropertyIndex &index) const { if (index.isMyself()) { return CVariant::from(*this); } @@ -219,6 +287,10 @@ namespace BlackMisc { case IndexAircraftDesignator: return CVariant::fromValue(this->m_designator); + case IndexIataCode: + return CVariant::fromValue(this->m_iataCode); + case IndexFamily: + return CVariant::fromValue(this->m_family); case IndexCombinedAircraftType: return CVariant::fromValue(this->m_combinedType); case IndexModelDescription: @@ -254,6 +326,12 @@ namespace BlackMisc case IndexAircraftDesignator: this->setDesignator(variant.value()); break; + case IndexIataCode: + this->setIataCode(variant.value()); + break; + case IndexFamily: + this->setFamily(variant.value()); + break; case IndexCombinedAircraftType: this->setCombinedType(variant.value()); break; @@ -290,6 +368,10 @@ namespace BlackMisc { case IndexAircraftDesignator: return m_designator.compare(compareValue.getDesignator(), Qt::CaseInsensitive); + case IndexIataCode: + return m_iataCode.compare(compareValue.getIataCode(), Qt::CaseInsensitive); + case IndexFamily: + return m_family.compare(compareValue.getFamily(), Qt::CaseInsensitive); case IndexCombinedAircraftType: return m_combinedType.compare(compareValue.getCombinedType(), Qt::CaseInsensitive); case IndexModelDescription: @@ -358,6 +440,8 @@ namespace BlackMisc } QString designator(json.value(prefix + "designator").toString()); + QString iata(json.value(prefix + "iata").toString()); + QString family(json.value(prefix + "family").toString()); QString manufacturer(json.value(prefix + "manufacturer").toString()); QString model(json.value(prefix + "model").toString()); QString type(json.value(prefix + "type").toString()); @@ -378,10 +462,11 @@ namespace BlackMisc Q_ASSERT_X(wtc.length() < 2, Q_FUNC_INFO, "WTC too long"); CAircraftIcaoCode code( - designator, combined, + designator, iata, combined, manufacturer, model, wtc, real, legacy, military, rank ); + code.setFamily(family); code.setKeyAndTimestampFromDatabaseJson(json, prefix); return code; } diff --git a/src/blackmisc/aviation/aircrafticaocode.h b/src/blackmisc/aviation/aircrafticaocode.h index 832e10e9c..0962a24ff 100644 --- a/src/blackmisc/aviation/aircrafticaocode.h +++ b/src/blackmisc/aviation/aircrafticaocode.h @@ -35,6 +35,8 @@ namespace BlackMisc enum ColumnIndex { IndexAircraftDesignator = BlackMisc::CPropertyIndex::GlobalIndexCAircraftIcaoCode, + IndexIataCode, + IndexFamily, IndexCombinedAircraftType, IndexManufacturer, IndexModelDescription, @@ -57,6 +59,10 @@ namespace BlackMisc CAircraftIcaoCode(const QString &icao, const QString &combinedType, const QString &manufacturer, const QString &model, const QString &wtc, bool realworld, bool legacy, bool military, int rank); + //! Constructor + CAircraftIcaoCode(const QString &icao, const QString &iata, const QString &combinedType, const QString &manufacturer, + const QString &model, const QString &wtc, bool realworld, bool legacy, bool military, int rank); + //! Get ICAO designator, e.g. "B737" const QString &getDesignator() const { return m_designator; } @@ -69,6 +75,30 @@ namespace BlackMisc //! Has designator and designator is not "ZZZZ" bool hasKnownDesignator() const; + //! IATA code + const QString &getIataCode() const { return m_iataCode; } + + //! Set IATA code + void setIataCode(const QString &iata) { this->m_iataCode = iata.toUpper().trimmed(); } + + //! Has IATA code? + bool hasIataCode() const { return !this->m_iataCode.isEmpty(); } + + //! IATA code same as designator? + bool isIataSameAsDesignator() const; + + //! Family (e.g. A350) + const QString &getFamily() const { return m_family; } + + //! Set family + void setFamily(const QString &family) { this->m_family = family.toUpper().trimmed(); } + + //! Has family? + bool hasFamily() const { return !this->m_family.isEmpty(); } + + //! Family same as designator? + bool isFamilySameAsDesignator() const; + //! Get type, e.g. "L2J" const QString &getCombinedType() const { return this->m_combinedType; } @@ -129,7 +159,7 @@ namespace BlackMisc //! Real world aircraft? bool isRealWorld() const { return m_realWorld; } - //! Legacy aircraft + //! Legacy aircraft (no current ICAO code) bool isLegacyAircraft() const { return m_legacy; } //! Flags @@ -153,8 +183,14 @@ namespace BlackMisc //! Ranking void setRank(int rank); - //! Comined descriptive string with key - QString getCombinedStringWithKey() const; + //! Combined ICAO descriptive string with key + QString getCombinedIcaoStringWithKey() const; + + //! Combined IATA descriptive string with key + QString getCombinedIataStringWithKey() const; + + //! Combined family descriptive string with key + QString getCombinedFamilyStringWithKey() const; //! All data set? bool hasCompleteData() const; @@ -162,6 +198,18 @@ namespace BlackMisc //! Matches designator string? bool matchesDesignator(const QString &designator) const; + //! Matches IATA string? + bool matchesIataCode(const QString &iata) const; + + //! Matches family? + bool matchesFamily(const QString &family) const; + + //! Matches ICAO or IATA code + bool matchesDesignatorOrIata(const QString &icaoOrIata) const; + + //! Matches ICAO, IATA, family? + bool matchesDesignatorIataOrFamily(const QString &icaoIataOrFamily) const; + //! \copydoc CValueObject::propertyByIndex CVariant propertyByIndex(const BlackMisc::CPropertyIndex &index) const; @@ -195,6 +243,8 @@ namespace BlackMisc private: BLACK_ENABLE_TUPLE_CONVERSION(CAircraftIcaoCode) QString m_designator; //!< "B737" + QString m_iataCode; //!< "320" + QString m_family; //!< "A350" (not a real ICAO code, but a family) QString m_combinedType; //!< "L2J" QString m_manufacturer; //!< "Airbus" QString m_modelDescription; //!< "A-330-200" @@ -218,6 +268,8 @@ BLACK_DECLARE_TUPLE_CONVERSION(BlackMisc::Aviation::CAircraftIcaoCode, ( o.m_dbKey, o.m_timestampMSecsSinceEpoch, o.m_designator, + o.m_iataCode, + o.m_family, o.m_combinedType, o.m_manufacturer, o.m_modelDescription, diff --git a/src/blackmisc/aviation/aircrafticaocodelist.cpp b/src/blackmisc/aviation/aircrafticaocodelist.cpp index 884c33189..e32ecab68 100644 --- a/src/blackmisc/aviation/aircrafticaocodelist.cpp +++ b/src/blackmisc/aviation/aircrafticaocodelist.cpp @@ -18,7 +18,7 @@ namespace BlackMisc CSequence(other) { } - CAircraftIcaoCodeList CAircraftIcaoCodeList::findByDesignator(const QString &designator) + CAircraftIcaoCodeList CAircraftIcaoCodeList::findByDesignator(const QString &designator) const { if (!CAircraftIcaoCode::isValidDesignator(designator)) { return CAircraftIcaoCodeList(); } return this->findBy([&](const CAircraftIcaoCode & code) @@ -27,7 +27,43 @@ namespace BlackMisc }); } - CAircraftIcaoCodeList CAircraftIcaoCodeList::findByManufacturer(const QString &manufacturer) + CAircraftIcaoCodeList CAircraftIcaoCodeList::findByDesignatorOrIataCode(const QString &icaoOrIata) const + { + if (icaoOrIata.isEmpty()) { return CAircraftIcaoCodeList(); } + return this->findBy([&](const CAircraftIcaoCode & code) + { + return code.matchesDesignatorOrIata(icaoOrIata); + }); + } + + CAircraftIcaoCodeList CAircraftIcaoCodeList::findByDesignatorIataOrFamily(const QString &icaoIataOrFamily) const + { + if (icaoIataOrFamily.isEmpty()) { return CAircraftIcaoCodeList(); } + return this->findBy([&](const CAircraftIcaoCode & code) + { + return code.matchesDesignatorIataOrFamily(icaoIataOrFamily); + }); + } + + CAircraftIcaoCodeList CAircraftIcaoCodeList::findByIataCode(const QString &iata) const + { + if (iata.isEmpty()) { return CAircraftIcaoCodeList(); } + return this->findBy([&](const CAircraftIcaoCode & code) + { + return code.matchesIataCode(iata); + }); + } + + CAircraftIcaoCodeList CAircraftIcaoCodeList::findByFamily(const QString &family) const + { + if (family.isEmpty()) { return CAircraftIcaoCodeList(); } + return this->findBy([&](const CAircraftIcaoCode & code) + { + return code.matchesFamily(family); + }); + } + + CAircraftIcaoCodeList CAircraftIcaoCodeList::findByManufacturer(const QString &manufacturer) const { if (manufacturer.isEmpty()) { return CAircraftIcaoCodeList(); } return this->findBy([&](const CAircraftIcaoCode & code) @@ -36,7 +72,7 @@ namespace BlackMisc }); } - CAircraftIcaoCodeList CAircraftIcaoCodeList::findByDescription(const QString &description) + CAircraftIcaoCodeList CAircraftIcaoCodeList::findByDescription(const QString &description) const { if (description.isEmpty()) { return CAircraftIcaoCodeList(); } return this->findBy([&](const CAircraftIcaoCode & code) @@ -45,7 +81,7 @@ namespace BlackMisc }); } - CAircraftIcaoCode CAircraftIcaoCodeList::findFirstByDesignatorAndRank(const QString &designator) + CAircraftIcaoCode CAircraftIcaoCodeList::findFirstByDesignatorAndRank(const QString &designator) const { if (!CAircraftIcaoCode::isValidDesignator(designator)) { return CAircraftIcaoCode(); } CAircraftIcaoCodeList codes(findByDesignator(designator)); @@ -60,12 +96,20 @@ namespace BlackMisc this->sortBy(&CAircraftIcaoCode::getRank); } - QStringList CAircraftIcaoCodeList::toCompleterStrings() const + QStringList CAircraftIcaoCodeList::toCompleterStrings(bool withIataCodes, bool withFamily) const { QStringList c; for (const CAircraftIcaoCode &icao : *this) { - c.append(icao.getCombinedStringWithKey()); + c.append(icao.getCombinedIcaoStringWithKey()); + if (withIataCodes && icao.hasIataCode() && !icao.isIataSameAsDesignator()) + { + c.append(icao.getCombinedIataStringWithKey()); + } + if (withFamily && icao.hasFamily() && !icao.isFamilySameAsDesignator()) + { + c.append(icao.getCombinedFamilyStringWithKey()); + } } return c; } @@ -96,8 +140,21 @@ namespace BlackMisc { const QString d(icaoPattern.getDesignator()); codes = codes.findByDesignator(d); + + // we have an exact match if (codes.size() == 1) { return codes.front(); } - if (codes.isEmpty()) { return icaoPattern; } + + if (codes.isEmpty()) + { + // now we search if the ICAO designator is + // actually an IATA code + codes = codes.findByIataCode(d); + if (codes.isEmpty()) + { + // still empty, bye + return icaoPattern; + } + } codes.sortByRank(); // intentionally continue here diff --git a/src/blackmisc/aviation/aircrafticaocodelist.h b/src/blackmisc/aviation/aircrafticaocodelist.h index a18b096e3..b3cd7be80 100644 --- a/src/blackmisc/aviation/aircrafticaocodelist.h +++ b/src/blackmisc/aviation/aircrafticaocodelist.h @@ -39,16 +39,28 @@ namespace BlackMisc CAircraftIcaoCodeList(const CSequence &other); //! Find by designator - CAircraftIcaoCodeList findByDesignator(const QString &designator); + CAircraftIcaoCodeList findByDesignator(const QString &designator) const; + + //! Find by IATA code + CAircraftIcaoCodeList findByIataCode(const QString &iata) const; + + //! Find by family + CAircraftIcaoCodeList findByFamily(const QString &family) const; + + //! Find by ICAO/IATA code + CAircraftIcaoCodeList findByDesignatorOrIataCode(const QString &icaoOrIata) const; + + //! Find by ICAO/IATA code or family + CAircraftIcaoCodeList findByDesignatorIataOrFamily(const QString &icaoIataOrFamily) const; //! Find by manufacturer - CAircraftIcaoCodeList findByManufacturer(const QString &manufacturer); + CAircraftIcaoCodeList findByManufacturer(const QString &manufacturer) const; //! Find by model description - CAircraftIcaoCodeList findByDescription(const QString &description); + CAircraftIcaoCodeList findByDescription(const QString &description) const; //! Find by designator, then best match by rank - CAircraftIcaoCode findFirstByDesignatorAndRank(const QString &designator); + CAircraftIcaoCode findFirstByDesignatorAndRank(const QString &designator) const; //! Best selection by given pattern CAircraftIcaoCode smartAircraftIcaoSelector(const CAircraftIcaoCode &icaoPattern) const; @@ -57,7 +69,7 @@ namespace BlackMisc void sortByRank(); //! For selection completion - QStringList toCompleterStrings() const; + QStringList toCompleterStrings(bool withIataCodes = false, bool withFamily = false) const; //! From our database JSON format static CAircraftIcaoCodeList fromDatabaseJson(const QJsonArray &array, bool ignoreIncomplete = true);