mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-05-04 17:30:12 +08:00
refs #638, reverse lookup in model matcher
This commit is contained in:
@@ -10,6 +10,7 @@
|
|||||||
#include "aircraftmatcher.h"
|
#include "aircraftmatcher.h"
|
||||||
#include "blackmisc/logmessage.h"
|
#include "blackmisc/logmessage.h"
|
||||||
#include "blackmisc/worker.h"
|
#include "blackmisc/worker.h"
|
||||||
|
#include "blackcore/application.h"
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
||||||
@@ -17,6 +18,7 @@ using namespace BlackMisc;
|
|||||||
using namespace BlackMisc::Simulation;
|
using namespace BlackMisc::Simulation;
|
||||||
using namespace BlackMisc::Network;
|
using namespace BlackMisc::Network;
|
||||||
using namespace BlackMisc::Aviation;
|
using namespace BlackMisc::Aviation;
|
||||||
|
using namespace BlackCore;
|
||||||
|
|
||||||
namespace BlackCore
|
namespace BlackCore
|
||||||
{
|
{
|
||||||
@@ -51,30 +53,58 @@ namespace BlackCore
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
// try to find in installed models by model string
|
// try to find in installed models by model string
|
||||||
aircraftModel = matchByExactModelString(remoteAircraft, matchModels, log);
|
if (mode.testFlag(ByModelString))
|
||||||
if (aircraftModel.hasModelString()) { break; }
|
{
|
||||||
|
aircraftModel = matchByExactModelString(remoteAircraft, matchModels, log);
|
||||||
|
if (aircraftModel.hasModelString()) { break; }
|
||||||
|
}
|
||||||
|
else if (log)
|
||||||
|
{
|
||||||
|
logDetails(log, remoteAircraft, "Skipping model string match");
|
||||||
|
}
|
||||||
|
|
||||||
// by livery, then by ICAO
|
// by livery, then by ICAO
|
||||||
aircraftModel = matchByLiveryAndIcaoCode(remoteAircraft, matchModels, log);
|
if (mode.testFlag(ByLivery))
|
||||||
if (aircraftModel.hasModelString()) { break; }
|
{
|
||||||
|
aircraftModel = matchByLiveryAndIcaoCode(remoteAircraft, matchModels, log);
|
||||||
|
if (aircraftModel.hasModelString()) { break; }
|
||||||
|
}
|
||||||
|
else if (log)
|
||||||
|
{
|
||||||
|
logDetails(log, remoteAircraft, "Skipping livery match");
|
||||||
|
}
|
||||||
|
|
||||||
// by ICAO data from set
|
// by ICAO data from set
|
||||||
aircraftModel = matchModelsByIcaoData(remoteAircraft, matchModels, false, log);
|
aircraftModel = matchModelsByIcaoData(remoteAircraft, matchModels, false, log);
|
||||||
if (aircraftModel.hasModelString()) { break; }
|
if (aircraftModel.hasModelString()) { break; }
|
||||||
|
|
||||||
// family
|
// family
|
||||||
QString family = remoteAircraft.getAircraftIcaoCode().getFamily();
|
if (mode.testFlag(ByFamily))
|
||||||
aircraftModel = matchByFamily(remoteAircraft, family, matchModels, "real family", log);
|
{
|
||||||
if (aircraftModel.hasModelString()) { break; }
|
QString family = remoteAircraft.getAircraftIcaoCode().getFamily();
|
||||||
|
aircraftModel = matchByFamily(remoteAircraft, family, matchModels, "real family", log);
|
||||||
|
if (aircraftModel.hasModelString()) { break; }
|
||||||
|
|
||||||
// scenario: the ICAO actually is the family
|
// scenario: the ICAO actually is the family
|
||||||
family = remoteAircraft.getAircraftIcaoCodeDesignator();
|
family = remoteAircraft.getAircraftIcaoCodeDesignator();
|
||||||
aircraftModel = matchByFamily(remoteAircraft, family, matchModels, "ICAO treated as family", log);
|
aircraftModel = matchByFamily(remoteAircraft, family, matchModels, "ICAO treated as family", log);
|
||||||
if (aircraftModel.hasModelString()) { break; }
|
if (aircraftModel.hasModelString()) { break; }
|
||||||
|
}
|
||||||
|
else if (log)
|
||||||
|
{
|
||||||
|
logDetails(log, remoteAircraft, "Skipping family match");
|
||||||
|
}
|
||||||
|
|
||||||
// combined code
|
// combined code
|
||||||
aircraftModel = matchByCombinedCode(remoteAircraft, matchModels, true, log);
|
if (mode.testFlag(ByCombinedCode))
|
||||||
if (aircraftModel.hasModelString()) { break; }
|
{
|
||||||
|
aircraftModel = matchByCombinedCode(remoteAircraft, matchModels, true, log);
|
||||||
|
if (aircraftModel.hasModelString()) { break; }
|
||||||
|
}
|
||||||
|
else if (log)
|
||||||
|
{
|
||||||
|
logDetails(log, remoteAircraft, "Skipping combined code match");
|
||||||
|
}
|
||||||
|
|
||||||
aircraftModel = getDefaultModel();
|
aircraftModel = getDefaultModel();
|
||||||
logDetails(log, remoteAircraft, "Using default model " + aircraftModel.getModelString());
|
logDetails(log, remoteAircraft, "Using default model " + aircraftModel.getModelString());
|
||||||
@@ -91,6 +121,80 @@ namespace BlackCore
|
|||||||
return aircraftModel;
|
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)
|
int CAircraftMatcher::setModelSet(const CAircraftModelList &models)
|
||||||
{
|
{
|
||||||
CAircraftModelList modelsCleaned(models);
|
CAircraftModelList modelsCleaned(models);
|
||||||
@@ -356,10 +460,15 @@ namespace BlackCore
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CAircraftMatcher::logDetails(CStatusMessageList *log, const CSimulatedAircraft &remoteAircraft, const QString &message, CStatusMessage::StatusSeverity s)
|
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 (!log) { return; }
|
||||||
if (message.isEmpty()) { 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);
|
log->push_back(m);
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
@@ -40,7 +40,9 @@ namespace BlackCore
|
|||||||
ByModelString = 1 << 0,
|
ByModelString = 1 << 0,
|
||||||
ByIcaoData = 1 << 1,
|
ByIcaoData = 1 << 1,
|
||||||
ByFamily = 1 << 2,
|
ByFamily = 1 << 2,
|
||||||
All = ByModelString | ByIcaoData | ByFamily
|
ByLivery = 1 << 3,
|
||||||
|
ByCombinedCode = 1 << 4,
|
||||||
|
All = ByModelString | ByIcaoData | ByFamily | ByLivery | ByCombinedCode
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(MatchingMode, MatchingModeFlag)
|
Q_DECLARE_FLAGS(MatchingMode, MatchingModeFlag)
|
||||||
|
|
||||||
@@ -59,8 +61,13 @@ namespace BlackCore
|
|||||||
//! Get the closest matching aircraft model.
|
//! Get the closest matching aircraft model.
|
||||||
//! Result depends on enabled modes.
|
//! Result depends on enabled modes.
|
||||||
//! \sa MatchingModeFlag
|
//! \sa MatchingModeFlag
|
||||||
|
//! \threadsafe
|
||||||
BlackMisc::Simulation::CAircraftModel getClosestMatch(const BlackMisc::Simulation::CSimulatedAircraft &remoteAircraft, BlackMisc::CStatusMessageList *log = nullptr) const;
|
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
|
//! Get the models
|
||||||
BlackMisc::Simulation::CAircraftModelList getModelSet() const { return m_modelSet; }
|
BlackMisc::Simulation::CAircraftModelList getModelSet() const { return m_modelSet; }
|
||||||
|
|
||||||
@@ -113,6 +120,13 @@ namespace BlackCore
|
|||||||
const QString &message,
|
const QString &message,
|
||||||
BlackMisc::CStatusMessage::StatusSeverity s = BlackMisc::CStatusMessage::SeverityInfo);
|
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;
|
MatchingMode m_matchingMode = All;
|
||||||
BlackMisc::Simulation::CAircraftModel m_defaultModel; //!< model to be used as default model
|
BlackMisc::Simulation::CAircraftModel m_defaultModel; //!< model to be used as default model
|
||||||
BlackMisc::Simulation::CAircraftModelList m_modelSet; //!< models used for model matching
|
BlackMisc::Simulation::CAircraftModelList m_modelSet; //!< models used for model matching
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "airspacemonitor.h"
|
#include "airspacemonitor.h"
|
||||||
#include "blackcore/application.h"
|
#include "blackcore/application.h"
|
||||||
|
#include "blackcore/aircraftmatcher.h"
|
||||||
#include "blackcore/registermetadata.h"
|
#include "blackcore/registermetadata.h"
|
||||||
#include "blackcore/webdataservices.h"
|
#include "blackcore/webdataservices.h"
|
||||||
#include "blackcore/vatsimbookingreader.h"
|
#include "blackcore/vatsimbookingreader.h"
|
||||||
@@ -793,6 +794,7 @@ namespace BlackCore
|
|||||||
bool existingAircraft = !remoteAircraft.getCallsign().isEmpty();
|
bool existingAircraft = !remoteAircraft.getCallsign().isEmpty();
|
||||||
|
|
||||||
CAircraftModel model; // generate a model for that aircraft
|
CAircraftModel model; // generate a model for that aircraft
|
||||||
|
model.setCallsign(callsign);
|
||||||
if (existingAircraft)
|
if (existingAircraft)
|
||||||
{
|
{
|
||||||
model = remoteAircraft.getModel();
|
model = remoteAircraft.getModel();
|
||||||
@@ -814,70 +816,10 @@ namespace BlackCore
|
|||||||
|
|
||||||
// we have no DB model yet, but do we have model string?
|
// we have no DB model yet, but do we have model string?
|
||||||
if (!model.hasModelString() && !modelString.isEmpty()) { model.setModelString(modelString); }
|
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);
|
QWriteLocker l(&m_lockAircraft);
|
||||||
if (this->m_aircraftInRange.containsCallsign(callsign))
|
if (this->m_aircraftInRange.containsCallsign(callsign))
|
||||||
|
|||||||
Reference in New Issue
Block a user