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.
*/
#include "blackmisc/simulation/matchingutils.h"
#include "blackmisc/aviation/aircrafticaocode.h"
#include "blackmisc/comparefunctions.h"
#include "blackmisc/db/datastoreutility.h"
#include "blackmisc/logcategory.h"
#include "blackmisc/comparefunctions.h"
#include "blackmisc/logcategorylist.h"
#include "blackmisc/propertyindex.h"
#include "blackmisc/statusmessage.h"
@@ -28,6 +28,7 @@
using namespace BlackMisc;
using namespace BlackMisc::Db;
using namespace BlackMisc::Simulation;
namespace BlackMisc
{
@@ -130,35 +131,48 @@ namespace BlackMisc
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;
if (this->hasValidDesignator() && this->getDesignator() == otherCode.getDesignator())
{
// 0..65
score += 50; // same designator
CMatchingUtils::addLogDetailsToList(log, *this, QString("Same designator: %1").arg(score));
int scoreOld = score;
if (this->getRank() == 0) { score += 15; }
else if (this->getRank() == 1) { score += 12; }
else if (this->getRank() < 10) { score += (10 - this->getRank()); }
if (score > scoreOld)
{
CMatchingUtils::addLogDetailsToList(log, *this, QString("Added rank: %1").arg(score));
}
}
else
{
if (this->hasFamily() && this->getFamily() == otherCode.getFamily())
{
score += 30;
CMatchingUtils::addLogDetailsToList(log, *this, QString("Added family: %1").arg(score));
}
else if (this->hasValidCombinedType() && otherCode.getCombinedType() == this->getCombinedType())
{
score += 20;
CMatchingUtils::addLogDetailsToList(log, *this, QString("Added combined code: %1").arg(score));
}
else if (this->hasValidCombinedType())
{
if (this->getEngineCount() == otherCode.getEngineCount()) { score += 2; }
if (this->getEngineType() == otherCode.getEngineType()) { 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()))
{
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))
{
CMatchingUtils::addLogDetailsToList(log, *this, QString("Contains manufacturer '%1': %2").arg(this->getManufacturer()).arg(score));
score += 5;
}
}
// 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
return score;
}

View File

@@ -289,7 +289,7 @@ namespace BlackMisc
//! Considers rank, manufacturer and family 0..100
//! \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?
static bool isValidDesignator(const QString &designator);

View File

@@ -9,6 +9,7 @@
#include "airlineicaocode.h"
#include "callsign.h"
#include "blackmisc/simulation/matchingutils.h"
#include "blackmisc/db/datastoreutility.h"
#include "blackmisc/comparefunctions.h"
#include "blackmisc/icons.h"
@@ -32,6 +33,7 @@
using namespace BlackMisc;
using namespace BlackMisc::Db;
using namespace BlackMisc::Simulation;
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)
{
if (m_designator.length() == 4)
@@ -57,7 +59,7 @@ namespace BlackMisc
const QString CAirlineIcaoCode::getVDesignator() const
{
if (!isVirtualAirline()) { return m_designator; }
if (!this->isVirtualAirline()) { return m_designator; }
return QLatin1Char('V') % m_designator;
}
@@ -89,7 +91,7 @@ namespace BlackMisc
QString CAirlineIcaoCode::getSimplifiedName() const
{
return BlackMisc::simplifyNameForSearch(this->getName());
return simplifyNameForSearch(this->getName());
}
bool CAirlineIcaoCode::hasValidCountry() const
@@ -183,7 +185,7 @@ namespace BlackMisc
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 (IDatastoreObjectWithIntegerKey::canHandleIndex(index)) { return IDatastoreObjectWithIntegerKey::propertyByIndex(index); }
@@ -297,7 +299,7 @@ namespace BlackMisc
QString s(getVDesignator());
if (s.isEmpty()) s = "????";
if (hasName()) { s = s.append(" ").append(getName()); }
return s.append(getDbKeyAsStringInParentheses(" "));
return s.append(this->getDbKeyAsStringInParentheses(" "));
}
CAirlineIcaoCode CAirlineIcaoCode::thisOrCallsignCode(const CCallsign &callsign) const
@@ -360,34 +362,43 @@ namespace BlackMisc
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();
int score = 0;
if (otherCode.hasValidDesignator() && this->getDesignator() == otherCode.getDesignator())
{
score += 60;
CMatchingUtils::addLogDetailsToList(log, *this, QString("Same designator: %1").arg(score));
}
// only for DB values we check VA
if (bothFromDb && this->isVirtualAirline() == otherCode.isVirtualAirline())
{
score += 20;
CMatchingUtils::addLogDetailsToList(log, *this, QString("VA equality: %1").arg(score));
}
// consider the various names
if (this->hasName() && this->getName() == otherCode.getName())
{
score += 20;
CMatchingUtils::addLogDetailsToList(log, *this, QString("Same name '%1': %2").arg(this->getName()).arg(score));
}
else if (this->hasTelephonyDesignator() && this->getTelephonyDesignator() == otherCode.getTelephonyDesignator())
{
score += 15;
CMatchingUtils::addLogDetailsToList(log, *this, QString("Same telephony '%1': %2").arg(this->getTelephonyDesignator()).arg(score));
}
else if (this->hasSimplifiedName() && this->getSimplifiedName() == otherCode.getSimplifiedName())
{
score += 10;
CMatchingUtils::addLogDetailsToList(log, *this, QString("Same simplified name '%1': %2").arg(this->getSimplifiedName()).arg(score));
}
return score;
}

View File

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

View File

@@ -7,10 +7,11 @@
* contained in the LICENSE file.
*/
#include "blackmisc/simulation/matchingutils.h"
#include "blackmisc/db/datastoreutility.h"
#include "blackmisc/aviation/livery.h"
#include "blackmisc/compare.h"
#include "blackmisc/comparefunctions.h"
#include "blackmisc/db/datastoreutility.h"
#include "blackmisc/logcategory.h"
#include "blackmisc/logcategorylist.h"
#include "blackmisc/propertyindex.h"
@@ -29,6 +30,7 @@
using namespace BlackMisc;
using namespace BlackMisc::Db;
using namespace BlackMisc::PhysicalQuantities;
using namespace BlackMisc::Simulation;
namespace BlackMisc
{
@@ -113,7 +115,7 @@ namespace BlackMisc
bool CLivery::matchesCombinedCode(const QString &candidate) const
{
if (candidate.isEmpty() || !this->hasCombinedCode()) { return false; }
QString c(candidate.trimmed().toUpper());
const QString c(candidate.trimmed().toUpper());
return c == m_combinedCode;
}
@@ -372,9 +374,13 @@ namespace BlackMisc
).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
static const int sameAirlineIcaoLevel = CAirlineIcaoCode("DLH").calculateScore(CAirlineIcaoCode("DLH"));
@@ -382,11 +388,13 @@ namespace BlackMisc
int score = 0;
const double colorMultiplier = 1.0 - this->getColorDistance(otherLivery);
if (this->isColorLivery() && otherLivery.isColorLivery())
{
// 2 color liveries 25..85
score = 25;
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())
{
@@ -395,9 +403,14 @@ namespace BlackMisc
// 0..25 based on color distance
// 0..10 based on mil.flag
// 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;
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()))
{
@@ -406,6 +419,7 @@ namespace BlackMisc
// 25 is weaker as same ICAO code / 2 from above
score = preferColorLiveries ? 25 : 0;
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;
}

View File

@@ -178,7 +178,7 @@ namespace BlackMisc
//! Score by comparison to another livery 0..100
//! \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
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
{
const int icaoScore = this->getAircraftIcaoCode().calculateScore(compareModel.getAircraftIcaoCode());
CMatchingUtils::addLogDetailsToList(log, this->getCallsign(), QString("ICAO score: ").arg(icaoScore));
const int liveryScore = this->getLivery().calculateScore(compareModel.getLivery(), preferColorLiveries);
CMatchingUtils::addLogDetailsToList(log, this->getCallsign(), QString("Livery score: ").arg(liveryScore));
const int icaoScore = this->getAircraftIcaoCode().calculateScore(compareModel.getAircraftIcaoCode(), log);
const int liveryScore = this->getLivery().calculateScore(compareModel.getLivery(), preferColorLiveries, log);
CMatchingUtils::addLogDetailsToList(log, this->getCallsign(), QString("ICAO score: %1 | livery score: %2").arg(icaoScore).arg(liveryScore));
return 0.5 * (icaoScore + liveryScore);
}

View File

@@ -718,15 +718,23 @@ namespace BlackMisc
ScoredModels scoreMap;
// 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("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("Prefer color liveries: '%1', airline: '%2', ignore zero scores: '%3'").arg(boolToYesNo(preferColorLiveries), remoteModel.getAirlineIcaoCodeDesignator(), boolToYesNo(ignoreZeroScores)));
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)
{
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; }
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);
}
CMatchingUtils::addLogDetailsToList(log, remoteModel.getCallsign(), QStringLiteral("--- End scoring ---"));
return scoreMap;
}