refs #638, reverse lookup in model matcher

This commit is contained in:
Klaus Basan
2016-04-09 14:07:41 +02:00
parent 1953665c40
commit fdd7fa62d5
3 changed files with 143 additions and 78 deletions

View File

@@ -10,6 +10,7 @@
#include "aircraftmatcher.h"
#include "blackmisc/logmessage.h"
#include "blackmisc/worker.h"
#include "blackcore/application.h"
#include <utility>
#include <atomic>
@@ -17,6 +18,7 @@ using namespace BlackMisc;
using namespace BlackMisc::Simulation;
using namespace BlackMisc::Network;
using namespace BlackMisc::Aviation;
using namespace BlackCore;
namespace BlackCore
{
@@ -51,30 +53,58 @@ namespace BlackCore
do
{
// try to find in installed models by model string
aircraftModel = matchByExactModelString(remoteAircraft, matchModels, log);
if (aircraftModel.hasModelString()) { break; }
if (mode.testFlag(ByModelString))
{
aircraftModel = matchByExactModelString(remoteAircraft, matchModels, log);
if (aircraftModel.hasModelString()) { break; }
}
else if (log)
{
logDetails(log, remoteAircraft, "Skipping model string match");
}
// by livery, then by ICAO
aircraftModel = matchByLiveryAndIcaoCode(remoteAircraft, matchModels, log);
if (aircraftModel.hasModelString()) { break; }
if (mode.testFlag(ByLivery))
{
aircraftModel = matchByLiveryAndIcaoCode(remoteAircraft, matchModels, log);
if (aircraftModel.hasModelString()) { break; }
}
else if (log)
{
logDetails(log, remoteAircraft, "Skipping livery match");
}
// by ICAO data from set
aircraftModel = matchModelsByIcaoData(remoteAircraft, matchModels, false, log);
if (aircraftModel.hasModelString()) { break; }
// family
QString family = remoteAircraft.getAircraftIcaoCode().getFamily();
aircraftModel = matchByFamily(remoteAircraft, family, matchModels, "real family", log);
if (aircraftModel.hasModelString()) { break; }
if (mode.testFlag(ByFamily))
{
QString family = remoteAircraft.getAircraftIcaoCode().getFamily();
aircraftModel = matchByFamily(remoteAircraft, family, matchModels, "real family", log);
if (aircraftModel.hasModelString()) { break; }
// scenario: the ICAO actually is the family
family = remoteAircraft.getAircraftIcaoCodeDesignator();
aircraftModel = matchByFamily(remoteAircraft, family, matchModels, "ICAO treated as family", log);
if (aircraftModel.hasModelString()) { break; }
// scenario: the ICAO actually is the family
family = remoteAircraft.getAircraftIcaoCodeDesignator();
aircraftModel = matchByFamily(remoteAircraft, family, matchModels, "ICAO treated as family", log);
if (aircraftModel.hasModelString()) { break; }
}
else if (log)
{
logDetails(log, remoteAircraft, "Skipping family match");
}
// combined code
aircraftModel = matchByCombinedCode(remoteAircraft, matchModels, true, log);
if (aircraftModel.hasModelString()) { break; }
if (mode.testFlag(ByCombinedCode))
{
aircraftModel = matchByCombinedCode(remoteAircraft, matchModels, true, log);
if (aircraftModel.hasModelString()) { break; }
}
else if (log)
{
logDetails(log, remoteAircraft, "Skipping combined code match");
}
aircraftModel = getDefaultModel();
logDetails(log, remoteAircraft, "Using default model " + aircraftModel.getModelString());
@@ -91,6 +121,80 @@ namespace BlackCore
return aircraftModel;
}
CAircraftModel CAircraftMatcher::reverseLookup(const CAircraftModel &modelToLookup, const QString &liveryInfo, CStatusMessageList *log)
{
CAircraftModel model(modelToLookup);
const CCallsign callsign(model.getCallsign());
if (model.hasModelString())
{
// if we find the model here we have a fully defined DB model
const CAircraftModel modelFromDb(sApp->getWebDataServices()->getModelForModelString(model.getModelString()));
if (modelFromDb.hasValidDbKey())
{
model = modelFromDb;
if (log) { logDetails(log, callsign, QString("Reverse looked up DB model `%1` for %2").arg(modelFromDb.getDbKey()).arg(callsign.toQString())); }
}
}
// only if not yet matched with DB
const QString aircraftIcaoDesignator(model.getAircraftIcaoCodeDesignator());
const QString airlineIcaoDesignator(model.getAircraftIcaoCodeDesignator());
if (!model.hasValidDbKey())
{
// try to match by livery
const QString livery(liveryInfo);
if (CLivery::isValidCombinedCode(livery))
{
// search DB model by livery
const CAircraftModelList models(sApp->getWebDataServices()->getModelsForAircraftDesignatorAndLiveryCombinedCode(aircraftIcaoDesignator, livery));
if (models.isEmpty())
{
// no models for that livery, search for livery only
const CLivery databaseLivery(sApp->getWebDataServices()->getLiveryForCombinedCode(livery));
if (databaseLivery.hasValidDbKey())
{
// we have found a livery in the DB
model.setLivery(databaseLivery);
}
}
else
{
// model by livery data found
model = models.front();
}
}
// if no DB livery, create own dummy livery
if (!model.hasValidDbKey() && !model.getLivery().hasValidDbKey())
{
// create a pseudo livery, try to find airline first
CAirlineIcaoCode airlineIcao(sApp->getWebDataServices()->smartAirlineIcaoSelector(CAirlineIcaoCode(airlineIcaoDesignator)));
if (!airlineIcao.hasValidDbKey())
{
// no DB data, we update as much as possible
airlineIcao = model.getAirlineIcaoCode();
airlineIcao.updateMissingParts(CAirlineIcaoCode(airlineIcaoDesignator));
}
const CLivery liveryDummy(livery, airlineIcao, "Generated");
model.setLivery(liveryDummy);
}
if (!model.getAircraftIcaoCode().hasValidDbKey())
{
CAircraftIcaoCode aircraftIcao(sApp->getWebDataServices()->getAircraftIcaoCodeForDesignator(aircraftIcaoDesignator));
if (!aircraftIcao.hasValidDbKey())
{
// no DB data, we update as much as possible
aircraftIcao = model.getAircraftIcaoCode();
aircraftIcao.updateMissingParts(CAircraftIcaoCode(aircraftIcaoDesignator));
}
model.setAircraftIcaoCode(aircraftIcao);
}
} // model from DB
return model;
}
int CAircraftMatcher::setModelSet(const CAircraftModelList &models)
{
CAircraftModelList modelsCleaned(models);
@@ -356,10 +460,15 @@ namespace BlackCore
}
void CAircraftMatcher::logDetails(CStatusMessageList *log, const CSimulatedAircraft &remoteAircraft, const QString &message, CStatusMessage::StatusSeverity s)
{
logDetails(log, remoteAircraft.getCallsign(), message, s);
}
void CAircraftMatcher::logDetails(CStatusMessageList *log, const CCallsign &callsign, const QString &message, CStatusMessage::StatusSeverity s)
{
if (!log) { return; }
if (message.isEmpty()) { return; }
const CStatusMessage m(getLogCategories(), s, remoteAircraft.hasCallsign() ? remoteAircraft.getCallsign().toQString() + ": " + message.trimmed() : message.trimmed());
const CStatusMessage m(getLogCategories(), s, callsign.isEmpty() ? callsign.toQString() + ": " + message.trimmed() : message.trimmed());
log->push_back(m);
}
} // namespace

View File

@@ -40,7 +40,9 @@ namespace BlackCore
ByModelString = 1 << 0,
ByIcaoData = 1 << 1,
ByFamily = 1 << 2,
All = ByModelString | ByIcaoData | ByFamily
ByLivery = 1 << 3,
ByCombinedCode = 1 << 4,
All = ByModelString | ByIcaoData | ByFamily | ByLivery | ByCombinedCode
};
Q_DECLARE_FLAGS(MatchingMode, MatchingModeFlag)
@@ -59,8 +61,13 @@ namespace BlackCore
//! Get the closest matching aircraft model.
//! Result depends on enabled modes.
//! \sa MatchingModeFlag
//! \threadsafe
BlackMisc::Simulation::CAircraftModel getClosestMatch(const BlackMisc::Simulation::CSimulatedAircraft &remoteAircraft, BlackMisc::CStatusMessageList *log = nullptr) const;
//! Try to find the corresponding data in DB and get best information for following matching
//! \threadsafe
static BlackMisc::Simulation::CAircraftModel reverseLookup(const BlackMisc::Simulation::CAircraftModel &modelToLookup, const QString &liveryInfo, BlackMisc::CStatusMessageList *log = nullptr);
//! Get the models
BlackMisc::Simulation::CAircraftModelList getModelSet() const { return m_modelSet; }
@@ -113,6 +120,13 @@ namespace BlackCore
const QString &message,
BlackMisc::CStatusMessage::StatusSeverity s = BlackMisc::CStatusMessage::SeverityInfo);
//! Add to log. if applicable
//! \treadsafe
static void logDetails(BlackMisc::CStatusMessageList *log,
const BlackMisc::Aviation::CCallsign &callsign,
const QString &message,
BlackMisc::CStatusMessage::StatusSeverity s = BlackMisc::CStatusMessage::SeverityInfo);
MatchingMode m_matchingMode = All;
BlackMisc::Simulation::CAircraftModel m_defaultModel; //!< model to be used as default model
BlackMisc::Simulation::CAircraftModelList m_modelSet; //!< models used for model matching

View File

@@ -9,6 +9,7 @@
#include "airspacemonitor.h"
#include "blackcore/application.h"
#include "blackcore/aircraftmatcher.h"
#include "blackcore/registermetadata.h"
#include "blackcore/webdataservices.h"
#include "blackcore/vatsimbookingreader.h"
@@ -793,6 +794,7 @@ namespace BlackCore
bool existingAircraft = !remoteAircraft.getCallsign().isEmpty();
CAircraftModel model; // generate a model for that aircraft
model.setCallsign(callsign);
if (existingAircraft)
{
model = remoteAircraft.getModel();
@@ -814,70 +816,10 @@ namespace BlackCore
// we have no DB model yet, but do we have model string?
if (!model.hasModelString() && !modelString.isEmpty()) { model.setModelString(modelString); }
if (model.hasModelString())
{
// if we find the model here we have a fully defined DB model
const CAircraftModel modelFromDb(sApp->getWebDataServices()->getModelForModelString(model.getModelString()));
if (modelFromDb.hasValidDbKey())
{
model = modelFromDb;
this->logMatching(QString("Reverse looked up DB model `%1` for %2").arg(modelFromDb.getDbKey()).arg(callsign.toQString()));
}
}
// only if not yet matched with DB
if (!model.hasValidDbKey())
{
// try to match by livery
if (CLivery::isValidCombinedCode(livery))
{
// search DB model by livery
const CAircraftModelList models(sApp->getWebDataServices()->getModelsForAircraftDesignatorAndLiveryCombinedCode(aircraftIcaoDesignator, livery));
if (models.isEmpty())
{
// no models for that livery, search for livery only
const CLivery databaseLivery(sApp->getWebDataServices()->getLiveryForCombinedCode(livery));
if (databaseLivery.hasValidDbKey())
{
// we have found a livery in the DB
model.setLivery(databaseLivery);
}
}
else
{
// model by livery data found
model = models.front();
}
}
// if no DB livery, create own dummy livery
if (!model.hasValidDbKey() && !model.getLivery().hasValidDbKey())
{
// create a pseudo livery, try to find airline first
CAirlineIcaoCode airlineIcao(sApp->getWebDataServices()->smartAirlineIcaoSelector(CAirlineIcaoCode(airlineIcaoDesignator)));
if (!airlineIcao.hasValidDbKey())
{
// no DB data, we update as much as possible
airlineIcao = model.getAirlineIcaoCode();
airlineIcao.updateMissingParts(CAirlineIcaoCode(airlineIcaoDesignator));
}
CLivery liveryDummy(livery, airlineIcao, "Generated");
model.setLivery(liveryDummy);
}
if (!model.getAircraftIcaoCode().hasValidDbKey())
{
CAircraftIcaoCode aircraftIcao(sApp->getWebDataServices()->getAircraftIcaoCodeForDesignator(aircraftIcaoDesignator));
if (!aircraftIcao.hasValidDbKey())
{
// no DB data, we update as much as possible
aircraftIcao = model.getAircraftIcaoCode();
aircraftIcao.updateMissingParts(CAircraftIcaoCode(aircraftIcaoDesignator));
}
model.setAircraftIcaoCode(aircraftIcao);
}
} // model from DB
CStatusMessageList reverseLookup;
model = CAircraftMatcher::reverseLookup(model, livery, &reverseLookup);
if (this->m_logMatchingProcess && !reverseLookup.isEmpty()) { CLogMessage::preformatted(reverseLookup); }
{
QWriteLocker l(&m_lockAircraft);
if (this->m_aircraftInRange.containsCallsign(callsign))