diff --git a/src/blackmisc/simulation/aircraftmatcher.cpp b/src/blackmisc/simulation/aircraftmatcher.cpp index 5106eedbf..e8e7a0ef2 100644 --- a/src/blackmisc/simulation/aircraftmatcher.cpp +++ b/src/blackmisc/simulation/aircraftmatcher.cpp @@ -22,6 +22,11 @@ namespace BlackMisc { namespace Simulation { + const CLogCategoryList &CAircraftMatcher::getLogCategories() + { + static const BlackMisc::CLogCategoryList cats { BlackMisc::CLogCategory::matching() }; + return cats; + } CAircraftMatcher::CAircraftMatcher(MatchingMode matchingMode, QObject *parent) : QObject(parent), @@ -29,100 +34,74 @@ namespace BlackMisc { } CAircraftMatcher::~CAircraftMatcher() - { - cancelInit(); - if (this->m_initWorker) { this->m_initWorker->waitForFinished(); } - } - - void CAircraftMatcher::init() - { - if (m_initState != NotInitialized) { return; } - m_initWorker = BlackMisc::CWorker::fromTask(this, "CAircraftMatcher::initImpl", [this]() - { - this->initImpl(); - }); - } - - bool CAircraftMatcher::isInitialized() const - { - return m_initState == InitFinished; - } + { } void CAircraftMatcher::setModelMappingProvider(std::unique_ptr mappings) { - m_mappingsProvider = std::move(mappings); - if (m_matchingMode.testFlag(ModelMapping)) { initMappings(); } + this->m_mappingsProvider = std::move(mappings); + CAircraftModelList models = this->m_mappingsProvider->getMatchingModels(); + int d = models.removeIfExcluded(); + this->m_models.uniqueWrite() = models; // local copy + CLogMessage(this).info("Added %1 models for model matching, %2 removed") << models.size() << d; } - void CAircraftMatcher::setMatchingModes(MatchingMode matchingModes) + void CAircraftMatcher::setLogDetails(bool log) { - m_matchingMode = matchingModes; - if (m_matchingMode.testFlag(ModelMapping) && m_modelsFromDatastoreInstalled.isEmpty()) - { - initMappings(); - } + this->m_logDetails = log; } - CAircraftModel CAircraftMatcher::getClosestMatch(const CSimulatedAircraft &remoteAircraft) + void CAircraftMatcher::reload() + { + + } + + CAircraftModel CAircraftMatcher::getClosestMatch(const CSimulatedAircraft &remoteAircraft) const { CAircraftModel aircraftModel(remoteAircraft.getModel()); // set defaults // Manually set string? if (remoteAircraft.getModel().hasManuallySetString()) { - // manual set model, maybe update missing parts - aircraftModel.updateMissingParts(remoteAircraft.getModel()); - aircraftModel.setCallsign(remoteAircraft.getCallsign()); - return aircraftModel; - } - - // mapper ready? - if (!isInitialized()) - { - // will be removed later, just for experimental version - aircraftModel = getDefaultModel(); - aircraftModel.setCallsign(remoteAircraft.getCallsign()); - CLogMessage(static_cast(nullptr)).warning("Matcher not initialized, set to default model"); - return aircraftModel; + // the user did a manual mapping "by hand", so he really should know what he is doing + // no matching + this->logDetails(remoteAircraft, "Manually set model " + remoteAircraft.getModelString()); + return remoteAircraft.getModel(); } + QString log; do { - //! \todo this code here is partially nuts and needs to be adjusted - //! as soon as we have real DB data - //! things to change: - //! 1) instead of keeping two lists (DB data + own models) just - //! update / enhance the list of installed models with the DB metadata - //! then there is only one search required - //! 2) Keep a cache of installed models enriched by the DB metadata (that will eliminate all - //! sync processes and can be done offline - //! 3) drivers which can assign reliable ICAO codes should do this as much as possible - //! the sync process with DB will improve those information (by livery details, but in case - //! of now metadata from DB we have the best matching data we can get - //! Also such data can be used in the mapping tool as default values (Less values to type in) - // try to find in installed models by model string - aircraftModel = matchByExactModelName(remoteAircraft); - if (aircraftModel.hasModelString()) { break; } + aircraftModel = matchByExactModelString(remoteAircraft); + if (aircraftModel.hasModelString()) + { + if (this->m_logDetails) { log = "Matched by exact model string " + aircraftModel.getModelString(); } + break; + } // ------------ start parts depending on swift DB data ------------------- // by DB ICAO data - aircraftModel = matchInstalledModelsByIcaoData(remoteAircraft); - if (aircraftModel.hasModelString()) { break; } + aircraftModel = matchModelsByIcaoData(remoteAircraft, log); + if (aircraftModel.hasModelString()) + { + break; + } // ------------ end parts depending on swift DB data ------------------- - aircraftModel = matchByAlgorithm(remoteAircraft); + aircraftModel = matchByFamily(remoteAircraft, log); if (aircraftModel.hasModelString()) { break; } aircraftModel = getDefaultModel(); } while (false); - // copy over callsign + // copy over callsign and other data aircraftModel.setCallsign(remoteAircraft.getCallsign()); + this->logDetails(aircraftModel, log); + Q_ASSERT_X(!aircraftModel.getCallsign().isEmpty(), Q_FUNC_INFO, "Missing callsign"); Q_ASSERT_X(aircraftModel.hasModelString(), Q_FUNC_INFO, "Missing model string"); Q_ASSERT_X(aircraftModel.getModelType() != CAircraftModel::TypeUnknown, Q_FUNC_INFO, "Missing model type"); @@ -130,18 +109,7 @@ namespace BlackMisc return aircraftModel; } - int CAircraftMatcher::synchronize() - { - return synchronizeWithExistingModels(m_installedModels.getModelStrings()); - } - - void CAircraftMatcher::cancelInit() - { - // when running, force re-init - this->m_initState = NotInitialized; - } - - const CAircraftModel &CAircraftMatcher::getDefaultModel() + const CAircraftModel &CAircraftMatcher::getDefaultModel() const { return m_defaultModel; } diff --git a/src/blackmisc/simulation/aircraftmatcher.h b/src/blackmisc/simulation/aircraftmatcher.h index 9c40fad80..d8fe4bb35 100644 --- a/src/blackmisc/simulation/aircraftmatcher.h +++ b/src/blackmisc/simulation/aircraftmatcher.h @@ -16,7 +16,6 @@ #include "blackmisc/simulation/modelmappingsprovider.h" #include "blackmisc/simulation/simulatedaircraft.h" #include "blackmisc/simulation/aircraftmodellist.h" -#include "blackmisc/worker.h" #include #include #include @@ -48,29 +47,14 @@ namespace BlackMisc }; Q_DECLARE_FLAGS(MatchingMode, MatchingModeFlag) + //! Log categories + static const BlackMisc::CLogCategoryList &getLogCategories(); + //! Constructor CAircraftMatcher(MatchingMode matchingMode = ModelMatching, QObject *parent = nullptr); //! Destructor - ~CAircraftMatcher(); - - //! Initialize - void init(); - - //! Init completed? - bool isInitialized() const; - - //! Get all models - const CAircraftModelList &getInstalledModelsList() const { return m_installedModels; } - - //! Set the list of installed models - void setInstalledModels(const CAircraftModelList &models) { m_installedModels = models; } - - //! Number of models - int countInstalledModels() const { return m_installedModels.size(); } - - //! Set the model mapping provider. The CAircraftMatcher will move the object and take over ownership - void setModelMappingProvider(std::unique_ptr mappings); + virtual ~CAircraftMatcher(); //! Set the enabled matching modes void setMatchingModes(MatchingMode matchingModes); @@ -78,35 +62,27 @@ namespace BlackMisc //! Get the closest matching aircraft model. //! Result depends on enabled modes. //! \sa MatchingModeFlag - CAircraftModel getClosestMatch(const CSimulatedAircraft &remoteAircraft); + //! \threadsafe + CAircraftModel getClosestMatch(const CSimulatedAircraft &remoteAircraft) const; //! Get all mappings - BlackMisc::Simulation::CAircraftModelList getMappingModels() const { return m_mappingsProvider->getMappingModels(); } + BlackMisc::Simulation::CAircraftModelList getMatchingModels() const { return m_mappingsProvider->getMatchingModels(); } - //! Number of mapping definitions - int countMappingRules() const { return m_modelsFromDatastoreInstalled.size(); } + //! Set the model mapping provider. The CAircraftMatcher will move the object and take over ownership + void setModelMappingProvider(std::unique_ptr mappings); - //! Synchronize models and mappings - //! \remarks after this step, we only have mappings for which we have models - int synchronize(); + //! Log.details? + void setLogDetails(bool log); - //! Shutdown - void cancelInit(); + //! Reload + void reload(); - //! default model - const BlackMisc::Simulation::CAircraftModel &getDefaultModel(); + //! Default model + const BlackMisc::Simulation::CAircraftModel &getDefaultModel() const; //! Set default model void setDefaultModel(const BlackMisc::Simulation::CAircraftModel &defaultModel); - signals: - //! Full init completed - void initializationFinished(); - - private slots: - //! Set the datatstore models - void ps_setDatastoreModels(const CAircraftModelList &mappings); - private: //! Init state enum InitState @@ -116,27 +92,26 @@ namespace BlackMisc InitFinished }; - void initImpl(); - void initMappings(); + //! Search in models by key (aka model string) + //! \threadsafe + CAircraftModel matchByExactModelString(const CSimulatedAircraft &remoteAircraft) const; - //! Search in installed models by key (aka model string) - CAircraftModel matchByExactModelName(const CSimulatedAircraft &remoteAircraft); + //! Installed models by ICAO data + //! \threadsafe + CAircraftModel matchModelsByIcaoData(const CSimulatedAircraft &remoteAircraft, QString &log) const; - //! Installed models by database ICAO data (requires DB entries) - CAircraftModel matchInstalledModelsByIcaoData(const CSimulatedAircraft &remoteAircraft); + //! Find model by aircraft family + CAircraftModel matchByFamily(const CSimulatedAircraft &remoteAircraft, QString &log) const; - CAircraftModel matchByAlgorithm(const CSimulatedAircraft &remoteAircraft); - - //! Synchronize with existing model names, remove unneeded models - int synchronizeWithExistingModels(const QStringList &modelNames, Qt::CaseSensitivity cs = Qt::CaseInsensitive); + //! Log. details about mapping of particular aircraft + //! threadsafe + void logDetails(const BlackMisc::Simulation::CSimulatedAircraft &remoteAircraft, const QString &message) const; + MatchingMode m_matchingMode = ModelMatching; + BlackMisc::Simulation::CAircraftModel m_defaultModel; //!< model to be used as default model + BlackMisc::LockFree m_models; //!< models used for model matching std::unique_ptr m_mappingsProvider; //!< Provides all mapping definitions - std::atomic m_initState { NotInitialized }; - QPointer m_initWorker; - MatchingMode m_matchingMode = ModelMatching; - CAircraftModelList m_installedModels; //!< my simulator`s installed models - CAircraftModelList m_modelsFromDatastoreInstalled; //!< models from datastore I do actually have installed - BlackMisc::Simulation::CAircraftModel m_defaultModel; //!< model to be used as default model + std::atomic m_logDetails { false }; //!< log details }; } } // namespace diff --git a/src/blackmisc/simulation/aircraftmodel.cpp b/src/blackmisc/simulation/aircraftmodel.cpp index 6afad9b2b..97db1fa8e 100644 --- a/src/blackmisc/simulation/aircraftmodel.cpp +++ b/src/blackmisc/simulation/aircraftmodel.cpp @@ -44,7 +44,7 @@ namespace BlackMisc QString CAircraftModel::convertToQString(bool i18n) const { QString s = this->m_modelString; - if (!s.isEmpty()) { s += ' '; } + if (!s.isEmpty()) { s += " tpye: "; } s += this->getModelTypeAsString(); s += ' '; s += this->m_aircraftIcao.toQString(i18n); @@ -339,6 +339,7 @@ namespace BlackMisc return; } + if (this->m_callsign.isEmpty()) { this->setCallsign(otherModel.getCallsign()); } if (this->m_modelString.isEmpty()) { this->setModelString(otherModel.getModelString()); } if (this->m_description.isEmpty()) { this->setDescription(otherModel.getDescription()); } if (this->m_fileName.isEmpty()) { this->setFileName(otherModel.getFileName()); } diff --git a/src/blackmisc/simulation/aircraftmodellist.cpp b/src/blackmisc/simulation/aircraftmodellist.cpp index 1f77ab848..f236da087 100644 --- a/src/blackmisc/simulation/aircraftmodellist.cpp +++ b/src/blackmisc/simulation/aircraftmodellist.cpp @@ -215,6 +215,44 @@ namespace BlackMisc return c; } + int CAircraftModelList::removeAllWithoutModelString() + { + if (this->isEmpty()) { return 0; } + int c = 0; + for (auto it = this->begin(); it != this->end();) + { + if (it->hasModelString()) + { + ++it; + } + else + { + c++; + it = this->erase(it); + } + } + return c; + } + + int CAircraftModelList::removeIfExcluded() + { + if (this->isEmpty()) { return 0; } + int c = 0; + for (auto it = this->begin(); it != this->end();) + { + if (it->getModelMode() != CAircraftModel::Exclude) + { + ++it; + } + else + { + c++; + it = this->erase(it); + } + } + return c; + } + int CAircraftModelList::replaceOrAddModelsWithString(const CAircraftModelList &addOrReplaceList, Qt::CaseSensitivity sensitivity) { if (addOrReplaceList.isEmpty()) { return 0; } diff --git a/src/blackmisc/simulation/aircraftmodellist.h b/src/blackmisc/simulation/aircraftmodellist.h index 60ee1b61d..0105f2744 100644 --- a/src/blackmisc/simulation/aircraftmodellist.h +++ b/src/blackmisc/simulation/aircraftmodellist.h @@ -102,8 +102,17 @@ namespace BlackMisc int removeModelsWithString(const QStringList &modelStrings, Qt::CaseSensitivity sensitivity); //! Remove if not matching simulator + //! \return number of elements removed int removeIfNotMatchingSimulator(const CSimulatorInfo &needToMatch); + //! Remove if having no model string + //! \return number of elements removed + int removeAllWithoutModelString(); + + //! Remove if excluded CAircraftModel::Exclude + //! \return number of elements removed + int removeIfExcluded(); + //! Replace or add based on model string //! \return number of elements removed int replaceOrAddModelsWithString(const CAircraftModelList &addOrReplaceList, Qt::CaseSensitivity sensitivity); diff --git a/src/plugins/simulator/fscommon/simulatorfscommon.cpp b/src/plugins/simulator/fscommon/simulatorfscommon.cpp index f470c0050..a8d4420f0 100644 --- a/src/plugins/simulator/fscommon/simulatorfscommon.cpp +++ b/src/plugins/simulator/fscommon/simulatorfscommon.cpp @@ -9,7 +9,7 @@ #include "simulatorfscommon.h" #include "blackmisc/logmessage.h" -#include "blackmisc/simulation/fscommon/modelmappingsprovidervpilot.h" +#include "blackmisc/simulation/modelmappingsprovider.h" using namespace BlackMisc::PhysicalQuantities; using namespace BlackMisc::Simulation; @@ -33,41 +33,17 @@ namespace BlackSimPlugin QObject *parent) : CSimulatorCommon(info, ownAircraftProvider, renderedAircraftProvider, pluginStorageProvider, weatherGridProvider, parent), m_fsuipc(new CFsuipc()), - m_aircraftCfgParser(CAircraftCfgParser::createModelLoader(CSimulatorInfo(info.getIdentifier()))), m_modelMatcher(CAircraftMatcher::AllModes, this) { - // hack to init mapper - connect(&m_modelMatcher, &CAircraftMatcher::initializationFinished, this, &CSimulatorFsCommon::ps_mapperInitialized); - auto modelMappingsProvider = std::unique_ptr { std::make_unique(true) }; - m_modelMatcher.setModelMappingProvider(std::move(modelMappingsProvider)); - - bool c = connect(m_aircraftCfgParser.get(), &CAircraftCfgParser::loadingFinished, this, &CSimulatorFsCommon::ps_aircraftCfgParsingFinished); - Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect signal"); - Q_UNUSED(c); - - //! \todo remove from plugin if data there are cached as well - /** - CVariant aircraftCfg = getPluginData(this, "aircraft_cfg"); - if (aircraftCfg.isValid()) - { - // will behave like parsing was finished - m_aircraftCfgParser->updateCfgEntriesList(aircraftCfg.value()); - } - else - { - m_aircraftCfgParser->startLoading(CAircraftCfgParser::LoadInBackground); - } - **/ - m_aircraftCfgParser->startLoading(CAircraftCfgParser::InBackgroundWithCache); + // init mapper + CSimulatorInfo sim(info.getIdentifier()); + this->m_modelMatcher.setModelMappingProvider( + std::make_unique(sim, this) + ); } CSimulatorFsCommon::~CSimulatorFsCommon() { } - void CSimulatorFsCommon::ps_mapperInitialized() - { - emit this->installedAircraftModelsChanged(); - } - bool CSimulatorFsCommon::disconnectFrom() { if (this->m_fsuipc) { this->m_fsuipc->disconnect(); } @@ -125,18 +101,19 @@ namespace BlackSimPlugin CAircraftModelList CSimulatorFsCommon::getInstalledModels() const { - return m_modelMatcher.getInstalledModelsList(); + return m_modelMatcher.getMatchingModels(); } void CSimulatorFsCommon::reloadInstalledModels() { - m_aircraftCfgParser->startLoading(); + this->m_modelMatcher.reload(); } CPixmap CSimulatorFsCommon::iconForModel(const QString &modelString) const { CStatusMessage msg; - CPixmap pm(m_aircraftCfgParser->iconForModel(modelString, msg)); + // CPixmap pm(m_aircraftCfgParser->iconForModel(modelString, msg)); + CPixmap pm; if (!msg.isEmpty()) { CLogMessage::preformatted(msg);} return pm; } @@ -172,23 +149,5 @@ namespace BlackSimPlugin } CSimulatorCommon::enableDebugMessages(driver, interpolator); } - - void CSimulatorFsCommon::unload() - { - this->m_aircraftCfgParser->cancelLoading(); - this->m_modelMatcher.cancelInit(); - CSimulatorCommon::unload(); - } - - void CSimulatorFsCommon::ps_aircraftCfgParsingFinished(bool success) - { - if (!success) { return; } - setPluginData(this, "aircraft_cfg", CVariant::from(m_aircraftCfgParser->getAircraftCfgEntriesList())); - m_modelMatcher.setInstalledModels(m_aircraftCfgParser->getAircraftCfgEntriesList().toAircraftModelList()); - - // Now the matcher has all required information to be initialized - m_modelMatcher.init(); - } - } // namespace } // namespace diff --git a/src/plugins/simulator/fscommon/simulatorfscommon.h b/src/plugins/simulator/fscommon/simulatorfscommon.h index aedfce1f7..2909cebf4 100644 --- a/src/plugins/simulator/fscommon/simulatorfscommon.h +++ b/src/plugins/simulator/fscommon/simulatorfscommon.h @@ -73,9 +73,6 @@ namespace BlackSimPlugin //! \copydoc BlackCore::ISimulator::enableDebugMessages virtual void enableDebugMessages(bool driver, bool interpolator) override; - //! \copydoc BlackCore::ISimulator::unload - virtual void unload() override; - protected: //! Constructor CSimulatorFsCommon(const BlackMisc::Simulation::CSimulatorPluginInfo &info, @@ -91,15 +88,14 @@ namespace BlackSimPlugin bool m_simPaused = false; //!< Simulator paused? bool m_simTimeSynced = false; //!< Time synchronized? BlackMisc::PhysicalQuantities::CTime m_syncTimeOffset; //!< time offset - BlackMisc::Aviation::CAirportList m_airportsInRange; //!< aiports in range of own aircraft + BlackMisc::Aviation::CAirportList m_airportsInRange; //!< airports in range of own aircraft // cockpit as set in SIM - BlackMisc::Aviation::CComSystem m_simCom1; //!< cockpit COM1 state in simulator - BlackMisc::Aviation::CComSystem m_simCom2; //!< cockpit COM2 state in simulator + BlackMisc::Aviation::CComSystem m_simCom1; //!< cockpit COM1 state in simulator + BlackMisc::Aviation::CComSystem m_simCom2; //!< cockpit COM2 state in simulator BlackMisc::Aviation::CTransponder m_simTransponder; //!< cockpit xpdr state in simulator // parser / matcher - std::unique_ptr m_aircraftCfgParser; //!< aircraft.cfg parser BlackMisc::Simulation::CAircraftMatcher m_modelMatcher; //!< Model matcher //! Set own model @@ -107,13 +103,6 @@ namespace BlackSimPlugin //! Set own model void setOwnAircraftModel(const QString &modelName); - - protected slots: - //! Mapper has been initialized - void ps_mapperInitialized(); - - //! aircraft.cfg files parsing is finished - void ps_aircraftCfgParsingFinished(bool success); }; } // namespace diff --git a/src/plugins/simulator/xplane/simulatorxplane.cpp b/src/plugins/simulator/xplane/simulatorxplane.cpp index 93556471e..9ef431263 100644 --- a/src/plugins/simulator/xplane/simulatorxplane.cpp +++ b/src/plugins/simulator/xplane/simulatorxplane.cpp @@ -191,9 +191,6 @@ namespace BlackSimPlugin CAircraftModel aircraftModel(*modelStringsIt, CAircraftModel::TypeDatabaseEntry, QString(), aircraftIcao, livery); m_installedModels.push_back(aircraftModel); } - - m_modelMatcher.setInstalledModels(m_installedModels); - m_modelMatcher.init(); } bool CSimulatorXPlane::isConnected() const