Ref T70, utility functions

* remove duplicates
* 3 model descriptions
This commit is contained in:
Klaus Basan
2017-06-15 00:33:38 +02:00
parent 96c27c1c5b
commit 63598a6a4e
4 changed files with 169 additions and 66 deletions

View File

@@ -55,6 +55,19 @@ namespace BlackMisc
if (m_rank < 0 || m_rank >= 10) { m_rank = 10; }
}
CAircraftIcaoCode::CAircraftIcaoCode(const QString &icao, const QString &iata, const QString &family, const QString &combinedType, const QString &manufacturer,
const QString &model, const QString &modelIata, const QString &modelSwift, const QString &wtc, bool realworld, bool legacy, bool military, int rank)
: m_designator(icao.trimmed().toUpper()),
m_iataCode(iata.trimmed().toUpper()),
m_family(family.trimmed().toUpper()),
m_combinedType(combinedType.trimmed().toUpper()),
m_manufacturer(manufacturer.trimmed()),
m_modelDescription(model.trimmed()), m_modelIataDescription(modelIata.trimmed()), m_modelSwiftDescription(modelSwift.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; }
}
QString CAircraftIcaoCode::getDesignatorDbKey() const
{
if (this->isLoadedFromDb())
@@ -83,6 +96,9 @@ namespace BlackMisc
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->m_modelIataDescription.isEmpty()) { this->setModelIataDescription(otherIcaoCode.getModelIataDescription()); }
if (this->m_modelSwiftDescription.isEmpty()) { this->setModelSwiftDescription(otherIcaoCode.getModelSwiftDescription()); }
if (this->m_family.isEmpty()) { this->setFamily(otherIcaoCode.getFamily()); }
if (!this->hasValidDbKey())
{
// need to observe if it makes sense to copy the key but not copying the whole object
@@ -224,6 +240,18 @@ namespace BlackMisc
return c;
}
QString CAircraftIcaoCode::getCombinedModelDescription() const
{
// Shortcut for most cases
if (!this->hasModelIataDescription() && !this->hasModelSwiftDescription()) { return this->getModelDescription(); }
QStringList combined({ this->getModelDescription() });
if (this->hasModelIataDescription()) { combined.append(this->getModelIataDescription()); }
if (this->hasModelSwiftDescription()) { combined.append(this->getModelSwiftDescription()); }
combined.removeDuplicates();
return combined.join(", ");
}
bool CAircraftIcaoCode::matchesCombinedType(const QString &combinedType) const
{
const QString cc(combinedType.toUpper().trimmed().replace(' ', '*').replace('-', '*'));
@@ -291,6 +319,12 @@ namespace BlackMisc
return false;
}
bool CAircraftIcaoCode::isDbDuplicate() const
{
return m_modelIataDescription.startsWith("duplicate", Qt::CaseInsensitive) ||
m_modelSwiftDescription.startsWith("duplicate", Qt::CaseInsensitive);
}
void CAircraftIcaoCode::setCodeFlags(bool military, bool legacy, bool realWorld)
{
m_military = military;
@@ -402,7 +436,7 @@ namespace BlackMisc
{
if (index.isMyself()) { return CVariant::from(*this); }
if (IDatastoreObjectWithIntegerKey::canHandleIndex(index)) { return IDatastoreObjectWithIntegerKey::propertyByIndex(index); }
ColumnIndex i = index.frontCasted<ColumnIndex>();
const ColumnIndex i = index.frontCasted<ColumnIndex>();
switch (i)
{
case IndexAircraftDesignator:
@@ -415,6 +449,12 @@ namespace BlackMisc
return CVariant::fromValue(this->m_combinedType);
case IndexModelDescription:
return CVariant::fromValue(this->m_modelDescription);
case IndexModelIataDescription:
return CVariant::fromValue(this->m_modelIataDescription);
case IndexModelSwiftDescription:
return CVariant::fromValue(this->m_modelSwiftDescription);
case IndexCombinedDescription:
return CVariant::fromValue(this->getCombinedModelDescription());
case IndexManufacturer:
return CVariant::fromValue(this->m_manufacturer);
case IndexWtc:
@@ -440,7 +480,7 @@ namespace BlackMisc
{
if (index.isMyself()) { (*this) = variant.to<CAircraftIcaoCode>(); return; }
if (IDatastoreObjectWithIntegerKey::canHandleIndex(index)) { IDatastoreObjectWithIntegerKey::setPropertyByIndex(index, variant); return; }
ColumnIndex i = index.frontCasted<ColumnIndex>();
const ColumnIndex i = index.frontCasted<ColumnIndex>();
switch (i)
{
case IndexAircraftDesignator:
@@ -458,6 +498,12 @@ namespace BlackMisc
case IndexModelDescription:
this->setModelDescription(variant.value<QString>());
break;
case IndexModelIataDescription:
this->setModelIataDescription(variant.value<QString>());
break;
case IndexModelSwiftDescription:
this->setModelSwiftDescription(variant.value<QString>());
break;
case IndexManufacturer:
this->setManufacturer(variant.value<QString>());
break;
@@ -496,6 +542,24 @@ namespace BlackMisc
return m_combinedType.compare(compareValue.getCombinedType(), Qt::CaseInsensitive);
case IndexModelDescription:
return m_modelDescription.compare(compareValue.getModelDescription(), Qt::CaseInsensitive);
case IndexModelIataDescription:
return m_modelIataDescription.compare(compareValue.getModelIataDescription(), Qt::CaseInsensitive);
case IndexModelSwiftDescription:
return m_modelSwiftDescription.compare(compareValue.getModelSwiftDescription(), Qt::CaseInsensitive);
case IndexCombinedDescription:
{
// compare without generating new strings
int c = m_modelDescription.compare(compareValue.getModelDescription(), Qt::CaseInsensitive);
if (c == 0)
{
c = m_modelIataDescription.compare(compareValue.getModelIataDescription(), Qt::CaseInsensitive);
if (c == 0)
{
c = m_modelSwiftDescription.compare(compareValue.getModelSwiftDescription(), Qt::CaseInsensitive);
}
}
return c;
}
case IndexManufacturer:
return m_manufacturer.compare(compareValue.getManufacturer(), Qt::CaseInsensitive);
case IndexWtc:
@@ -615,15 +679,17 @@ namespace BlackMisc
return CAircraftIcaoCode();
}
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());
QString engine(json.value(prefix + "engine").toString());
int engineCount(json.value(prefix + "enginecount").toInt(-1));
QString combined(createdCombinedString(type, engineCount, engine));
const QString designator(json.value(prefix + "designator").toString());
const QString iata(json.value(prefix + "iata").toString());
const QString family(json.value(prefix + "family").toString());
const QString manufacturer(json.value(prefix + "manufacturer").toString());
const QString model(json.value(prefix + "model").toString());
const QString modelIata(json.value(prefix + "modeliata").toString());
const QString modelSwift(json.value(prefix + "modelswift").toString());
const QString type(json.value(prefix + "type").toString());
const QString engine(json.value(prefix + "engine").toString());
const int engineCount(json.value(prefix + "enginecount").toInt(-1));
const QString combined(createdCombinedString(type, engineCount, engine));
QString wtc(json.value(prefix + "wtc").toString());
if (wtc.length() > 1 && wtc.contains("/"))
{
@@ -632,17 +698,16 @@ namespace BlackMisc
}
Q_ASSERT_X(wtc.length() < 2, Q_FUNC_INFO, "WTC too long");
bool real = CDatastoreUtility::dbBoolStringToBool(json.value(prefix + "realworld").toString());
bool legacy = CDatastoreUtility::dbBoolStringToBool(json.value(prefix + "legacy").toString());
bool military = CDatastoreUtility::dbBoolStringToBool(json.value(prefix + "military").toString());
int rank(json.value(prefix + "rank").toInt(10));
const bool real = CDatastoreUtility::dbBoolStringToBool(json.value(prefix + "realworld").toString());
const bool legacy = CDatastoreUtility::dbBoolStringToBool(json.value(prefix + "legacy").toString());
const bool military = CDatastoreUtility::dbBoolStringToBool(json.value(prefix + "military").toString());
const int rank(json.value(prefix + "rank").toInt(10));
CAircraftIcaoCode code(
designator, iata, combined,
manufacturer, model, wtc,
designator, iata, family, combined, manufacturer,
model, modelIata, modelSwift, wtc,
real, legacy, military, rank
);
code.setFamily(family);
code.setKeyAndTimestampFromDatabaseJson(json, prefix);
return code;
}
@@ -650,39 +715,17 @@ namespace BlackMisc
QString CAircraftIcaoCode::createdCombinedString(const QString &type, const QString &engineCount, const QString &engine)
{
Q_ASSERT_X(engineCount.length() < 2, Q_FUNC_INFO, "Wrong engine count");
QString c(type.trimmed().toUpper().left(1));
if (c.isEmpty()) { c.append("-"); }
if (engineCount.isEmpty())
{
c.append("-");
}
else
{
c.append(engineCount);
}
if (engine.isEmpty())
{
c.append("-");
}
else
{
c.append(engine.at(0));
}
QString c(type.isEmpty() ? "-" : type.trimmed().left(1).toUpper());
c += engineCount.isEmpty() ? "-" : engineCount.trimmed();
c += engine.isEmpty() ? "-" : engine.trimmed().left(1).toUpper();
Q_ASSERT_X(c.length() == 3, Q_FUNC_INFO, "Wrong combined length");
return c;
}
QString CAircraftIcaoCode::createdCombinedString(const QString &type, int engineCount, const QString &engine)
{
if (engineCount >= 0 && engineCount < 10)
{
return createdCombinedString(type, QString::number(engineCount), engine);
}
else
{
return createdCombinedString(type, "", engine);
}
const bool valid = engineCount >= 0 && engineCount < 10;
return createdCombinedString(type, valid ? QString::number(engineCount) : "", engine);
}
} // namespace
} // namespace

View File

@@ -44,13 +44,16 @@ namespace BlackMisc
IndexCombinedAircraftType,
IndexManufacturer,
IndexModelDescription,
IndexModelIataDescription,
IndexModelSwiftDescription,
IndexCombinedDescription,
IndexWtc,
IndexIsRealworld,
IndexIsMilitary,
IndexIsLegacy,
IndexIsVtol,
IndexRank,
IndexDesignatorManufacturer //!< designator and manufacturer
IndexDesignatorManufacturer //!< designator and manufacturer
};
//! Default constructor.
@@ -67,6 +70,10 @@ namespace BlackMisc
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);
//! Constructor
CAircraftIcaoCode(const QString &icao, const QString &iata, const QString &family, const QString &combinedType, const QString &manufacturer,
const QString &model, const QString &modelIata, const QString &modelSwift, const QString &wtc, bool realworld, bool legacy, bool military, int rank);
//! Get ICAO designator, e.g. "B737"
const QString &getDesignator() const { return m_designator; }
@@ -133,9 +140,18 @@ namespace BlackMisc
//! Set type
void setCombinedType(const QString &type) { this->m_combinedType = type.trimmed().toUpper(); }
//! Get model description, e.g. "A-330-200"
//! Get IACO model description, e.g. "A-330-200"
const QString &getModelDescription() const { return m_modelDescription; }
//! Get IATA model description
const QString &getModelIataDescription() const { return m_modelIataDescription; }
//! Get swift model description
const QString &getModelSwiftDescription() const { return m_modelSwiftDescription; }
//! Combined description
QString getCombinedModelDescription() const;
//! Matches given combined code
//! \remark * can be used as wildcard, e.g. L*J, L**
bool matchesCombinedType(const QString &combinedType) const;
@@ -143,12 +159,24 @@ namespace BlackMisc
//! Designator + Manufacturer
QString getDesignatorManufacturer() const;
//! Set the model description
//! Set the model description (ICAO description)
void setModelDescription(const QString &modelDescription) { m_modelDescription = modelDescription.trimmed(); }
//! Has model description
//! Set the alternative IATA model description
void setModelIataDescription(const QString &modelDescription) { m_modelIataDescription = modelDescription.trimmed(); }
//! Set the alternative swift model description
void setModelSwiftDescription(const QString &modelDescription) { m_modelSwiftDescription = modelDescription.trimmed(); }
//! Has model description?
bool hasModelDescription() const { return !this->m_modelDescription.isEmpty(); }
//! Has IATA model description?
bool hasModelIataDescription() const { return !this->m_modelIataDescription.isEmpty(); }
//! Has swift model description?
bool hasModelSwiftDescription() const { return !this->m_modelSwiftDescription.isEmpty(); }
//! Get manufacturer, e.g. "Airbus"
const QString &getManufacturer() const { return m_manufacturer; }
@@ -182,6 +210,10 @@ namespace BlackMisc
//! Legacy aircraft (no current ICAO code)
bool isLegacyAircraft() const { return m_legacy; }
//! Is DB duplicate, means redundant ICAO DB entry.
//! \see https://aviation.stackexchange.com/q/37848/4024
bool isDbDuplicate() const;
//! Flags
void setCodeFlags(bool military, bool legacy, bool realWorld);
@@ -280,17 +312,19 @@ namespace BlackMisc
static CAircraftIcaoCode fromDatabaseJson(const QJsonObject &json, const QString &prefix = QString());
private:
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"
QString m_wtc; //!< wake turbulence "M","H" "L/M", "L", we only use the one letter versions
bool m_realWorld = true; //!< real world aircraft
bool m_legacy = false; //!< legacy code
bool m_military = false; //!< military aircraft?
int m_rank = 10; //!< rank among same codes
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", the ICAO description
QString m_modelIataDescription; //!< alternative IATA description
QString m_modelSwiftDescription; //!< alternative swift description
QString m_wtc; //!< wake turbulence "M","H" "L/M", "L", we only use the one letter versions
bool m_realWorld = true; //!< real world aircraft
bool m_legacy = false; //!< legacy code
bool m_military = false; //!< military aircraft?
int m_rank = 10; //!< rank among same codes
//! Create a combined string like L2J
static QString createdCombinedString(const QString &type, const QString &engineCount, const QString &engine);
@@ -308,6 +342,8 @@ namespace BlackMisc
BLACK_METAMEMBER(combinedType),
BLACK_METAMEMBER(manufacturer),
BLACK_METAMEMBER(modelDescription),
BLACK_METAMEMBER(modelIataDescription),
BLACK_METAMEMBER(modelSwiftDescription),
BLACK_METAMEMBER(wtc),
BLACK_METAMEMBER(military),
BLACK_METAMEMBER(realWorld),

View File

@@ -172,6 +172,11 @@ namespace BlackMisc
this->removeIf([](const CAircraftIcaoCode & icao) { return !icao.hasValidCombinedType(); });
}
void CAircraftIcaoCodeList::removeDuplicates()
{
this->removeIf(&CAircraftIcaoCode::isDbDuplicate, true);
}
QStringList CAircraftIcaoCodeList::toCompleterStrings(bool withIataCodes, bool withFamily, bool sort) const
{
QStringList c;
@@ -218,6 +223,18 @@ namespace BlackMisc
return c;
}
QSet<QString> CAircraftIcaoCodeList::allFamilies() const
{
QSet<QString> c;
for (const CAircraftIcaoCode &icao : *this)
{
if (!icao.hasFamily()) { continue; }
const QString d(icao.getFamily());
c.insert(d);
}
return c;
}
QSet<QString> CAircraftIcaoCodeList::allManufacturers(bool onlyKnownDesignators) const
{
QSet<QString> c;
@@ -231,15 +248,16 @@ namespace BlackMisc
return c;
}
CAircraftIcaoCodeList CAircraftIcaoCodeList::fromDatabaseJson(const QJsonArray &array, bool ignoreIncomplete)
CAircraftIcaoCodeList CAircraftIcaoCodeList::fromDatabaseJson(const QJsonArray &array, bool ignoreIncompleteAndDuplicates)
{
CAircraftIcaoCodeList codes;
for (const QJsonValue &value : array)
{
CAircraftIcaoCode icao(CAircraftIcaoCode::fromDatabaseJson(value.toObject()));
if (ignoreIncomplete && !icao.hasSpecialDesignator() && !icao.hasCompleteData())
const CAircraftIcaoCode icao(CAircraftIcaoCode::fromDatabaseJson(value.toObject()));
if (ignoreIncompleteAndDuplicates)
{
continue;
if (!icao.hasSpecialDesignator() && !icao.hasCompleteData()) { continue; }
if (icao.isDbDuplicate()) { continue; }
}
codes.push_back(icao);
}
@@ -250,7 +268,7 @@ namespace BlackMisc
{
if (icaoPattern.hasValidDbKey())
{
int k = icaoPattern.getDbKey();
const int k = icaoPattern.getDbKey();
CAircraftIcaoCode c(this->findByKey(k));
if (c.hasCompleteData()) { return c; }
}

View File

@@ -103,17 +103,23 @@ namespace BlackMisc
//! Remove invalid combined codes
void removeInvalidCombinedCodes();
//! Remove duplicates as marked by CAircraftIcaoCode::isDbDuplicate
void removeDuplicates();
//! For selection completion
QStringList toCompleterStrings(bool withIataCodes = false, bool withFamily = false, bool sort = true) const;
//! All ICAO codes, no duplicates
QSet<QString> allIcaoCodes(bool noUnspecified = true) const;
//! All families, no duplicates
QSet<QString> allFamilies() const;
//! All manufacturers
QSet<QString> allManufacturers(bool onlyKnownDesignators = true) const;
//! From our database JSON format
static CAircraftIcaoCodeList fromDatabaseJson(const QJsonArray &array, bool ignoreIncomplete = true);
static CAircraftIcaoCodeList fromDatabaseJson(const QJsonArray &array, bool ignoreIncompleteAndDuplicates = true);
};
} //namespace
} // namespace