diff --git a/src/blackcore/aircraftmatcher.cpp b/src/blackcore/aircraftmatcher.cpp index c5b3ce27e..92bd94260 100644 --- a/src/blackcore/aircraftmatcher.cpp +++ b/src/blackcore/aircraftmatcher.cpp @@ -10,6 +10,7 @@ #include "aircraftmatcher.h" #include "blackmisc/logmessage.h" #include "blackmisc/worker.h" +#include "blackcore/application.h" #include #include @@ -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 diff --git a/src/blackcore/aircraftmatcher.h b/src/blackcore/aircraftmatcher.h index d5e2b7e63..b682124de 100644 --- a/src/blackcore/aircraftmatcher.h +++ b/src/blackcore/aircraftmatcher.h @@ -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 diff --git a/src/blackcore/airspacemonitor.cpp b/src/blackcore/airspacemonitor.cpp index e71617ca5..5116c4b76 100644 --- a/src/blackcore/airspacemonitor.cpp +++ b/src/blackcore/airspacemonitor.cpp @@ -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))