Ref T182, aircraft ICAO, airline ICAO and livery also contribute to scoring log messages

This commit is contained in:
Klaus Basan
2017-11-08 02:49:23 +01:00
parent f288d3d0f2
commit 9048ff0977
8 changed files with 80 additions and 29 deletions

View File

@@ -7,10 +7,10 @@
* contained in the LICENSE file. * contained in the LICENSE file.
*/ */
#include "blackmisc/simulation/matchingutils.h"
#include "blackmisc/aviation/aircrafticaocode.h" #include "blackmisc/aviation/aircrafticaocode.h"
#include "blackmisc/comparefunctions.h"
#include "blackmisc/db/datastoreutility.h" #include "blackmisc/db/datastoreutility.h"
#include "blackmisc/logcategory.h" #include "blackmisc/comparefunctions.h"
#include "blackmisc/logcategorylist.h" #include "blackmisc/logcategorylist.h"
#include "blackmisc/propertyindex.h" #include "blackmisc/propertyindex.h"
#include "blackmisc/statusmessage.h" #include "blackmisc/statusmessage.h"
@@ -28,6 +28,7 @@
using namespace BlackMisc; using namespace BlackMisc;
using namespace BlackMisc::Db; using namespace BlackMisc::Db;
using namespace BlackMisc::Simulation;
namespace BlackMisc namespace BlackMisc
{ {
@@ -130,35 +131,48 @@ namespace BlackMisc
return this->getCombinedIcaoStringWithKey(); return this->getCombinedIcaoStringWithKey();
} }
int CAircraftIcaoCode::calculateScore(const CAircraftIcaoCode &otherCode) const int CAircraftIcaoCode::calculateScore(const CAircraftIcaoCode &otherCode, CStatusMessageList *log) const
{ {
if (this->isDbEqual(otherCode)) { return 100; } if (this->isDbEqual(otherCode))
{
CMatchingUtils::addLogDetailsToList(log, *this, QString("Equal DB code: 100"));
return 100;
}
int score = 0; int score = 0;
if (this->hasValidDesignator() && this->getDesignator() == otherCode.getDesignator()) if (this->hasValidDesignator() && this->getDesignator() == otherCode.getDesignator())
{ {
// 0..65 // 0..65
score += 50; // same designator score += 50; // same designator
CMatchingUtils::addLogDetailsToList(log, *this, QString("Same designator: %1").arg(score));
int scoreOld = score;
if (this->getRank() == 0) { score += 15; } if (this->getRank() == 0) { score += 15; }
else if (this->getRank() == 1) { score += 12; } else if (this->getRank() == 1) { score += 12; }
else if (this->getRank() < 10) { score += (10 - this->getRank()); } else if (this->getRank() < 10) { score += (10 - this->getRank()); }
if (score > scoreOld)
{
CMatchingUtils::addLogDetailsToList(log, *this, QString("Added rank: %1").arg(score));
}
} }
else else
{ {
if (this->hasFamily() && this->getFamily() == otherCode.getFamily()) if (this->hasFamily() && this->getFamily() == otherCode.getFamily())
{ {
score += 30; score += 30;
CMatchingUtils::addLogDetailsToList(log, *this, QString("Added family: %1").arg(score));
} }
else if (this->hasValidCombinedType() && otherCode.getCombinedType() == this->getCombinedType()) else if (this->hasValidCombinedType() && otherCode.getCombinedType() == this->getCombinedType())
{ {
score += 20; score += 20;
CMatchingUtils::addLogDetailsToList(log, *this, QString("Added combined code: %1").arg(score));
} }
else if (this->hasValidCombinedType()) else if (this->hasValidCombinedType())
{ {
if (this->getEngineCount() == otherCode.getEngineCount()) { score += 2; } if (this->getEngineCount() == otherCode.getEngineCount()) { score += 2; }
if (this->getEngineType() == otherCode.getEngineType()) { score += 2; } if (this->getEngineType() == otherCode.getEngineType()) { score += 2; }
if (this->getAircraftType() == otherCode.getAircraftType()) { score += 2; } if (this->getAircraftType() == otherCode.getAircraftType()) { score += 2; }
CMatchingUtils::addLogDetailsToList(log, *this, QString("Added combined code parts: %1").arg(score));
} }
} }
@@ -168,16 +182,21 @@ namespace BlackMisc
if (this->matchesManufacturer(otherCode.getManufacturer())) if (this->matchesManufacturer(otherCode.getManufacturer()))
{ {
score += 10; score += 10;
CMatchingUtils::addLogDetailsToList(log, *this, QString("Matches manufacturer '%1': %2").arg(this->getManufacturer()).arg(score));
} }
else if (this->getManufacturer().contains(otherCode.getManufacturer(), Qt::CaseInsensitive)) else if (this->getManufacturer().contains(otherCode.getManufacturer(), Qt::CaseInsensitive))
{ {
CMatchingUtils::addLogDetailsToList(log, *this, QString("Contains manufacturer '%1': %2").arg(this->getManufacturer()).arg(score));
score += 5; score += 5;
} }
} }
// 0..75 so far // 0..75 so far
if (this->isMilitary() == otherCode.isMilitary()) { score += 10; } if (this->isMilitary() == otherCode.isMilitary())
{
score += 10;
CMatchingUtils::addLogDetailsToList(log, *this, QString("Matches military flag '%1': %2").arg(boolToYesNo(this->isMilitary())).arg(score));
}
// 0..85 // 0..85
return score; return score;
} }

View File

@@ -289,7 +289,7 @@ namespace BlackMisc
//! Considers rank, manufacturer and family 0..100 //! Considers rank, manufacturer and family 0..100
//! \remark normally used with a selected set of ICAO codes or combined types //! \remark normally used with a selected set of ICAO codes or combined types
int calculateScore(const CAircraftIcaoCode &otherCode) const; int calculateScore(const CAircraftIcaoCode &otherCode, CStatusMessageList *log = nullptr) const;
//! Valid designator? //! Valid designator?
static bool isValidDesignator(const QString &designator); static bool isValidDesignator(const QString &designator);

View File

@@ -9,6 +9,7 @@
#include "airlineicaocode.h" #include "airlineicaocode.h"
#include "callsign.h" #include "callsign.h"
#include "blackmisc/simulation/matchingutils.h"
#include "blackmisc/db/datastoreutility.h" #include "blackmisc/db/datastoreutility.h"
#include "blackmisc/comparefunctions.h" #include "blackmisc/comparefunctions.h"
#include "blackmisc/icons.h" #include "blackmisc/icons.h"
@@ -32,6 +33,7 @@
using namespace BlackMisc; using namespace BlackMisc;
using namespace BlackMisc::Db; using namespace BlackMisc::Db;
using namespace BlackMisc::Simulation;
namespace BlackMisc namespace BlackMisc
{ {
@@ -46,7 +48,7 @@ namespace BlackMisc
} }
} }
CAirlineIcaoCode::CAirlineIcaoCode(const QString &airlineDesignator, const QString &airlineName, const BlackMisc::CCountry &country, const QString &telephony, bool virtualAirline, bool operating) CAirlineIcaoCode::CAirlineIcaoCode(const QString &airlineDesignator, const QString &airlineName, const CCountry &country, const QString &telephony, bool virtualAirline, bool operating)
: m_designator(airlineDesignator.trimmed().toUpper()), m_name(airlineName), m_telephonyDesignator(telephony), m_country(country), m_isVa(virtualAirline), m_isOperating(operating) : m_designator(airlineDesignator.trimmed().toUpper()), m_name(airlineName), m_telephonyDesignator(telephony), m_country(country), m_isVa(virtualAirline), m_isOperating(operating)
{ {
if (m_designator.length() == 4) if (m_designator.length() == 4)
@@ -57,7 +59,7 @@ namespace BlackMisc
const QString CAirlineIcaoCode::getVDesignator() const const QString CAirlineIcaoCode::getVDesignator() const
{ {
if (!isVirtualAirline()) { return m_designator; } if (!this->isVirtualAirline()) { return m_designator; }
return QLatin1Char('V') % m_designator; return QLatin1Char('V') % m_designator;
} }
@@ -89,7 +91,7 @@ namespace BlackMisc
QString CAirlineIcaoCode::getSimplifiedName() const QString CAirlineIcaoCode::getSimplifiedName() const
{ {
return BlackMisc::simplifyNameForSearch(this->getName()); return simplifyNameForSearch(this->getName());
} }
bool CAirlineIcaoCode::hasValidCountry() const bool CAirlineIcaoCode::hasValidCountry() const
@@ -183,7 +185,7 @@ namespace BlackMisc
QLatin1String(" Mil: ") % boolToYesNo(this->isMilitary()); QLatin1String(" Mil: ") % boolToYesNo(this->isMilitary());
} }
CVariant CAirlineIcaoCode::propertyByIndex(const BlackMisc::CPropertyIndex &index) const CVariant CAirlineIcaoCode::propertyByIndex(const CPropertyIndex &index) const
{ {
if (index.isMyself()) { return CVariant::from(*this); } if (index.isMyself()) { return CVariant::from(*this); }
if (IDatastoreObjectWithIntegerKey::canHandleIndex(index)) { return IDatastoreObjectWithIntegerKey::propertyByIndex(index); } if (IDatastoreObjectWithIntegerKey::canHandleIndex(index)) { return IDatastoreObjectWithIntegerKey::propertyByIndex(index); }
@@ -297,7 +299,7 @@ namespace BlackMisc
QString s(getVDesignator()); QString s(getVDesignator());
if (s.isEmpty()) s = "????"; if (s.isEmpty()) s = "????";
if (hasName()) { s = s.append(" ").append(getName()); } if (hasName()) { s = s.append(" ").append(getName()); }
return s.append(getDbKeyAsStringInParentheses(" ")); return s.append(this->getDbKeyAsStringInParentheses(" "));
} }
CAirlineIcaoCode CAirlineIcaoCode::thisOrCallsignCode(const CCallsign &callsign) const CAirlineIcaoCode CAirlineIcaoCode::thisOrCallsignCode(const CCallsign &callsign) const
@@ -360,34 +362,43 @@ namespace BlackMisc
return this->getCombinedStringWithKey(); return this->getCombinedStringWithKey();
} }
int CAirlineIcaoCode::calculateScore(const CAirlineIcaoCode &otherCode) const int CAirlineIcaoCode::calculateScore(const CAirlineIcaoCode &otherCode, CStatusMessageList *log) const
{ {
if (this->isDbEqual(otherCode)) { return 100; } if (this->isDbEqual(otherCode))
{
CMatchingUtils::addLogDetailsToList(log, *this, QStringLiteral("DB equal score: 100"));
return 100;
}
const bool bothFromDb = this->isLoadedFromDb() && otherCode.isLoadedFromDb(); const bool bothFromDb = this->isLoadedFromDb() && otherCode.isLoadedFromDb();
int score = 0; int score = 0;
if (otherCode.hasValidDesignator() && this->getDesignator() == otherCode.getDesignator()) if (otherCode.hasValidDesignator() && this->getDesignator() == otherCode.getDesignator())
{ {
score += 60; score += 60;
CMatchingUtils::addLogDetailsToList(log, *this, QString("Same designator: %1").arg(score));
} }
// only for DB values we check VA // only for DB values we check VA
if (bothFromDb && this->isVirtualAirline() == otherCode.isVirtualAirline()) if (bothFromDb && this->isVirtualAirline() == otherCode.isVirtualAirline())
{ {
score += 20; score += 20;
CMatchingUtils::addLogDetailsToList(log, *this, QString("VA equality: %1").arg(score));
} }
// consider the various names // consider the various names
if (this->hasName() && this->getName() == otherCode.getName()) if (this->hasName() && this->getName() == otherCode.getName())
{ {
score += 20; score += 20;
CMatchingUtils::addLogDetailsToList(log, *this, QString("Same name '%1': %2").arg(this->getName()).arg(score));
} }
else if (this->hasTelephonyDesignator() && this->getTelephonyDesignator() == otherCode.getTelephonyDesignator()) else if (this->hasTelephonyDesignator() && this->getTelephonyDesignator() == otherCode.getTelephonyDesignator())
{ {
score += 15; score += 15;
CMatchingUtils::addLogDetailsToList(log, *this, QString("Same telephony '%1': %2").arg(this->getTelephonyDesignator()).arg(score));
} }
else if (this->hasSimplifiedName() && this->getSimplifiedName() == otherCode.getSimplifiedName()) else if (this->hasSimplifiedName() && this->getSimplifiedName() == otherCode.getSimplifiedName())
{ {
score += 10; score += 10;
CMatchingUtils::addLogDetailsToList(log, *this, QString("Same simplified name '%1': %2").arg(this->getSimplifiedName()).arg(score));
} }
return score; return score;
} }

View File

@@ -223,7 +223,7 @@ namespace BlackMisc
QString asHtmlSummary() const; QString asHtmlSummary() const;
//! Score against other code 0..100 //! Score against other code 0..100
int calculateScore(const CAirlineIcaoCode &otherCode) const; int calculateScore(const CAirlineIcaoCode &otherCode, CStatusMessageList *log = nullptr) const;
//! Valid designator? //! Valid designator?
static bool isValidAirlineDesignator(const QString &airline); static bool isValidAirlineDesignator(const QString &airline);

View File

@@ -7,10 +7,11 @@
* contained in the LICENSE file. * contained in the LICENSE file.
*/ */
#include "blackmisc/simulation/matchingutils.h"
#include "blackmisc/db/datastoreutility.h"
#include "blackmisc/aviation/livery.h" #include "blackmisc/aviation/livery.h"
#include "blackmisc/compare.h" #include "blackmisc/compare.h"
#include "blackmisc/comparefunctions.h" #include "blackmisc/comparefunctions.h"
#include "blackmisc/db/datastoreutility.h"
#include "blackmisc/logcategory.h" #include "blackmisc/logcategory.h"
#include "blackmisc/logcategorylist.h" #include "blackmisc/logcategorylist.h"
#include "blackmisc/propertyindex.h" #include "blackmisc/propertyindex.h"
@@ -29,6 +30,7 @@
using namespace BlackMisc; using namespace BlackMisc;
using namespace BlackMisc::Db; using namespace BlackMisc::Db;
using namespace BlackMisc::PhysicalQuantities; using namespace BlackMisc::PhysicalQuantities;
using namespace BlackMisc::Simulation;
namespace BlackMisc namespace BlackMisc
{ {
@@ -113,7 +115,7 @@ namespace BlackMisc
bool CLivery::matchesCombinedCode(const QString &candidate) const bool CLivery::matchesCombinedCode(const QString &candidate) const
{ {
if (candidate.isEmpty() || !this->hasCombinedCode()) { return false; } if (candidate.isEmpty() || !this->hasCombinedCode()) { return false; }
QString c(candidate.trimmed().toUpper()); const QString c(candidate.trimmed().toUpper());
return c == m_combinedCode; return c == m_combinedCode;
} }
@@ -372,9 +374,13 @@ namespace BlackMisc
).replace(" ", "&nbsp;"); ).replace(" ", "&nbsp;");
} }
int CLivery::calculateScore(const CLivery &otherLivery, bool preferColorLiveries) const int CLivery::calculateScore(const CLivery &otherLivery, bool preferColorLiveries, CStatusMessageList *log) const
{ {
if (this->isDbEqual(otherLivery)) { return 100; } if (this->isDbEqual(otherLivery))
{
CMatchingUtils::addLogDetailsToList(log, *this, QStringLiteral("Equal DB code: 100"));
return 100;
}
// get a level // get a level
static const int sameAirlineIcaoLevel = CAirlineIcaoCode("DLH").calculateScore(CAirlineIcaoCode("DLH")); static const int sameAirlineIcaoLevel = CAirlineIcaoCode("DLH").calculateScore(CAirlineIcaoCode("DLH"));
@@ -382,11 +388,13 @@ namespace BlackMisc
int score = 0; int score = 0;
const double colorMultiplier = 1.0 - this->getColorDistance(otherLivery); const double colorMultiplier = 1.0 - this->getColorDistance(otherLivery);
if (this->isColorLivery() && otherLivery.isColorLivery()) if (this->isColorLivery() && otherLivery.isColorLivery())
{ {
// 2 color liveries 25..85 // 2 color liveries 25..85
score = 25; score = 25;
score += 60 * colorMultiplier; score += 60 * colorMultiplier;
CMatchingUtils::addLogDetailsToList(log, *this, QString("2 color liveries, color multiplier %1: %2").arg(colorMultiplier).arg(score));
} }
else if (this->isAirlineLivery() && otherLivery.isAirlineLivery()) else if (this->isAirlineLivery() && otherLivery.isAirlineLivery())
{ {
@@ -395,9 +403,14 @@ namespace BlackMisc
// 0..25 based on color distance // 0..25 based on color distance
// 0..10 based on mil.flag // 0..10 based on mil.flag
// same ICAO at least means 30, max 50 // same ICAO at least means 30, max 50
score = 0.5 * this->getAirlineIcaoCode().calculateScore(otherLivery.getAirlineIcaoCode()); score = 0.5 * this->getAirlineIcaoCode().calculateScore(otherLivery.getAirlineIcaoCode(), log);
score += 25 * colorMultiplier; score += 25 * colorMultiplier;
if (this->isMilitary() == otherLivery.isMilitary()) { score += 10; } CMatchingUtils::addLogDetailsToList(log, *this, QString("2 airline liveries, color multiplier %1: %2").arg(colorMultiplier).arg(score));
if (this->isMilitary() == otherLivery.isMilitary())
{
CMatchingUtils::addLogDetailsToList(log, *this, QString("Mil.flag '%1' matches: %2").arg(boolToYesNo(this->isMilitary())).arg(score));
score += 10;
}
} }
else if ((this->isColorLivery() && otherLivery.isAirlineLivery()) || (otherLivery.isColorLivery() && this->isAirlineLivery())) else if ((this->isColorLivery() && otherLivery.isAirlineLivery()) || (otherLivery.isColorLivery() && this->isAirlineLivery()))
{ {
@@ -406,6 +419,7 @@ namespace BlackMisc
// 25 is weaker as same ICAO code / 2 from above // 25 is weaker as same ICAO code / 2 from above
score = preferColorLiveries ? 25 : 0; score = preferColorLiveries ? 25 : 0;
score += 25 * colorMultiplier; // needs to be the same as in 2 airlines score += 25 * colorMultiplier; // needs to be the same as in 2 airlines
CMatchingUtils::addLogDetailsToList(log, *this, QString("Color/airline mixed, color multiplier %1: %2").arg(colorMultiplier).arg(score));
} }
return score; return score;
} }

View File

@@ -178,7 +178,7 @@ namespace BlackMisc
//! Score by comparison to another livery 0..100 //! Score by comparison to another livery 0..100
//! \remark normally used with liveries preselect by airline ICAO code //! \remark normally used with liveries preselect by airline ICAO code
int calculateScore(const CLivery &otherLivery, bool preferColorLiveries = false) const; int calculateScore(const CLivery &otherLivery, bool preferColorLiveries = false, CStatusMessageList *log = nullptr) const;
//! Object from JSON //! Object from JSON
static CLivery fromDatabaseJson(const QJsonObject &json, const QString &prefix = QString("liv_")); static CLivery fromDatabaseJson(const QJsonObject &json, const QString &prefix = QString("liv_"));

View File

@@ -578,10 +578,9 @@ namespace BlackMisc
int CAircraftModel::calculateScore(const CAircraftModel &compareModel, bool preferColorLiveries, CStatusMessageList *log) const int CAircraftModel::calculateScore(const CAircraftModel &compareModel, bool preferColorLiveries, CStatusMessageList *log) const
{ {
const int icaoScore = this->getAircraftIcaoCode().calculateScore(compareModel.getAircraftIcaoCode()); const int icaoScore = this->getAircraftIcaoCode().calculateScore(compareModel.getAircraftIcaoCode(), log);
CMatchingUtils::addLogDetailsToList(log, this->getCallsign(), QString("ICAO score: ").arg(icaoScore)); const int liveryScore = this->getLivery().calculateScore(compareModel.getLivery(), preferColorLiveries, log);
const int liveryScore = this->getLivery().calculateScore(compareModel.getLivery(), preferColorLiveries); CMatchingUtils::addLogDetailsToList(log, this->getCallsign(), QString("ICAO score: %1 | livery score: %2").arg(icaoScore).arg(liveryScore));
CMatchingUtils::addLogDetailsToList(log, this->getCallsign(), QString("Livery score: ").arg(liveryScore));
return 0.5 * (icaoScore + liveryScore); return 0.5 * (icaoScore + liveryScore);
} }

View File

@@ -718,15 +718,23 @@ namespace BlackMisc
ScoredModels scoreMap; ScoredModels scoreMap;
// normally prefer colors if there is no airline // normally prefer colors if there is no airline
CMatchingUtils::addLogDetailsToList(log, remoteModel.getCallsign(), QString("Prefer color liveries: %1, airline: '%2', ignore zero scores: %3").arg(boolToYesNo(preferColorLiveries), remoteModel.getAirlineIcaoCodeDesignator(), boolToYesNo(ignoreZeroScores))); CMatchingUtils::addLogDetailsToList(log, remoteModel.getCallsign(), QString("Prefer color liveries: '%1', airline: '%2', ignore zero scores: '%3'").arg(boolToYesNo(preferColorLiveries), remoteModel.getAirlineIcaoCodeDesignator(), boolToYesNo(ignoreZeroScores)));
CMatchingUtils::addLogDetailsToList(log, remoteModel.getCallsign(), QString("Scoring in list with %1 models, airline liveries: %2, color liveries: %3").arg(this->size()).arg(this->countModelsWithAirlineLivery()).arg(this->countModelsWithColorLivery())); CMatchingUtils::addLogDetailsToList(log, remoteModel.getCallsign(), QString("--- Start scoring in list with %1 models, airline liveries: %2, color liveries: %3").arg(this->size()).arg(this->countModelsWithAirlineLivery()).arg(this->countModelsWithColorLivery()));
int c = 1;
for (const CAircraftModel &model : *this) for (const CAircraftModel &model : *this)
{ {
const int score = model.calculateScore(remoteModel, preferColorLiveries, log); CStatusMessageList subMsgs;
const int score = model.calculateScore(remoteModel, preferColorLiveries, log ? &subMsgs : nullptr);
if (ignoreZeroScores && score < 1) { continue; } if (ignoreZeroScores && score < 1) { continue; }
CMatchingUtils::addLogDetailsToList(log, remoteModel.getCallsign(), QString("--- Calculating #%1 '%2'---").arg(c++).arg(model.getModelStringAndDbKey()));
if (log) { log->push_back(subMsgs); }
CMatchingUtils::addLogDetailsToList(log, remoteModel.getCallsign(), QString("--- End calculating #%1 ---").arg(c));
scoreMap.insertMulti(score, model); scoreMap.insertMulti(score, model);
} }
CMatchingUtils::addLogDetailsToList(log, remoteModel.getCallsign(), QStringLiteral("--- End scoring ---"));
return scoreMap; return scoreMap;
} }