mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-03-30 11:55:35 +08:00
refs #444 Move CAircraftMatcher into Simulation namespace
It used to be before in FsCommon namespace, however it does not have any MSFS specific implementation any more and is used by xplane driver as well.
This commit is contained in:
committed by
Mathew Sutcliffe
parent
b0530aa567
commit
b28634e586
256
src/blackmisc/simulation/aircraftmatcher.cpp
Normal file
256
src/blackmisc/simulation/aircraftmatcher.cpp
Normal file
@@ -0,0 +1,256 @@
|
||||
/* Copyright (C) 2013
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "aircraftmatcher.h"
|
||||
#include "blackmisc/logmessage.h"
|
||||
#include "blackmisc/worker.h"
|
||||
#include <utility>
|
||||
#include <atomic>
|
||||
|
||||
using namespace BlackMisc;
|
||||
using namespace BlackMisc::Simulation;
|
||||
using namespace BlackMisc::Network;
|
||||
using namespace BlackMisc::Aviation;
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
namespace Simulation
|
||||
{
|
||||
|
||||
CAircraftMatcher::CAircraftMatcher(MatchingMode matchingMode, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_matchingMode(matchingMode)
|
||||
{ }
|
||||
|
||||
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]()
|
||||
{
|
||||
initImpl();
|
||||
});
|
||||
}
|
||||
|
||||
bool CAircraftMatcher::isInitialized() const
|
||||
{
|
||||
return m_initState == InitFinished;
|
||||
}
|
||||
|
||||
void CAircraftMatcher::setModelMappingProvider(std::unique_ptr<IModelMappingsProvider> mappings)
|
||||
{
|
||||
m_mappingsProvider = std::move(mappings);
|
||||
if (m_matchingMode.testFlag(ModelMapping)) { initMappings(); }
|
||||
}
|
||||
|
||||
void CAircraftMatcher::setMatchingModes(MatchingMode matchingModes)
|
||||
{
|
||||
m_matchingMode = matchingModes;
|
||||
if (m_matchingMode.testFlag(ModelMapping) && m_modelMappings.isEmpty()) initMappings();
|
||||
}
|
||||
|
||||
CAircraftModel CAircraftMatcher::getClosestMatch(const CSimulatedAircraft &remoteAircraft)
|
||||
{
|
||||
CAircraftModel aircraftModel(remoteAircraft); // set defaults
|
||||
|
||||
// Manually set string?
|
||||
if (remoteAircraft.getModel().hasManuallySetString())
|
||||
{
|
||||
// manual set model, maybe update missing parts
|
||||
aircraftModel.updateMissingParts(remoteAircraft.getModel());
|
||||
aircraftModel.setCallsign(remoteAircraft.getCallsign());
|
||||
reverseLookupIcaoData(aircraftModel);
|
||||
return aircraftModel;
|
||||
}
|
||||
|
||||
// mapper ready?
|
||||
if (!isInitialized())
|
||||
{
|
||||
// will be removed later, just for experimental version
|
||||
aircraftModel = getDefaultModel();
|
||||
aircraftModel.setCallsign(remoteAircraft.getCallsign());
|
||||
CLogMessage(static_cast<CAircraftMatcher *>(nullptr)).warning("Matcher not initialized, set to default model");
|
||||
return aircraftModel;
|
||||
}
|
||||
|
||||
aircraftModel = matchByExactModelName(remoteAircraft);
|
||||
|
||||
if (!aircraftModel.hasModelString())
|
||||
{
|
||||
aircraftModel = matchByMapping(remoteAircraft);
|
||||
}
|
||||
|
||||
if (!aircraftModel.hasModelString())
|
||||
{
|
||||
aircraftModel = matchByAlgorithm(remoteAircraft);
|
||||
}
|
||||
|
||||
if (!aircraftModel.hasModelString())
|
||||
{
|
||||
aircraftModel = getDefaultModel();
|
||||
}
|
||||
aircraftModel.setCallsign(remoteAircraft.getCallsign());
|
||||
|
||||
Q_ASSERT(!aircraftModel.getCallsign().isEmpty());
|
||||
Q_ASSERT(aircraftModel.hasModelString());
|
||||
Q_ASSERT(aircraftModel.getModelType() != CAircraftModel::TypeUnknown);
|
||||
|
||||
return aircraftModel;
|
||||
}
|
||||
|
||||
CAircraftIcaoData CAircraftMatcher::getIcaoForModelString(const QString &modelString) const
|
||||
{
|
||||
if (modelString.isEmpty() || !isInitialized()) { return CAircraftIcaoData(); }
|
||||
CAircraftMappingList mappings = m_mappingsProvider->getMappingList().findByModelString(modelString);
|
||||
if (mappings.isEmpty()) { return CAircraftIcaoData(); }
|
||||
return mappings.front().getIcao();
|
||||
}
|
||||
|
||||
int CAircraftMatcher::synchronize()
|
||||
{
|
||||
return synchronizeWithExistingModels(m_installedModels.getSortedModelStrings());
|
||||
}
|
||||
|
||||
void CAircraftMatcher::cancelInit()
|
||||
{
|
||||
// when running, force re-init
|
||||
this->m_initState = NotInitialized;
|
||||
}
|
||||
|
||||
const CAircraftModel &CAircraftMatcher::getDefaultModel()
|
||||
{
|
||||
return m_defaultModel;
|
||||
}
|
||||
|
||||
void CAircraftMatcher::setDefaultModel(const BlackMisc::Simulation::CAircraftModel &defaultModel)
|
||||
{
|
||||
m_defaultModel = defaultModel;
|
||||
}
|
||||
|
||||
void CAircraftMatcher::ps_setModelMappingRules(const CAircraftMappingList &mappings)
|
||||
{
|
||||
m_modelMappings = mappings;
|
||||
}
|
||||
|
||||
void CAircraftMatcher::initImpl()
|
||||
{
|
||||
InitState e = NotInitialized;
|
||||
InitState d = InitInProgress;
|
||||
if (!m_initState.compare_exchange_strong(e, d)) { return; }
|
||||
|
||||
// sync
|
||||
this->synchronize();
|
||||
CLogMessage(this).debug() << "Mapping definitions after sync" << m_modelMappings.size();
|
||||
|
||||
// finish
|
||||
CLogMessage(this).info("Mapping system: %1 definitions for %2 installed models") << m_modelMappings.size()
|
||||
<< m_installedModels.size();
|
||||
m_initState = InitFinished;
|
||||
emit initializationFinished();
|
||||
}
|
||||
|
||||
void CAircraftMatcher::initMappings()
|
||||
{
|
||||
Q_ASSERT(m_mappingsProvider);
|
||||
int mappingsSize = m_mappingsProvider->getMappingList().size();
|
||||
if (mappingsSize < 1)
|
||||
{
|
||||
m_mappingsProvider->read();
|
||||
m_modelMappings = m_mappingsProvider->getMappingList();
|
||||
mappingsSize = m_modelMappings.size();
|
||||
if (mappingsSize < 1)
|
||||
{
|
||||
CLogMessage(this).error("Reading mapping rules failed or empty!");
|
||||
// Turn off the model mapping mode
|
||||
m_matchingMode &= ~ModelMapping;
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_modelMappings = m_mappingsProvider->getMappingList();
|
||||
CLogMessage(this).debug() << "Mapping definitions" << mappingsSize;
|
||||
}
|
||||
|
||||
CAircraftModel CAircraftMatcher::matchByExactModelName(const CSimulatedAircraft &remoteAircraft)
|
||||
{
|
||||
CAircraftModel aircraftModel(remoteAircraft);
|
||||
// Model by queried string
|
||||
const CClient remoteClient = remoteAircraft.getClient();
|
||||
if (remoteClient.getAircraftModel().hasQueriedModelString())
|
||||
{
|
||||
QString directModelString = remoteClient.getAircraftModel().getModelString();
|
||||
if (!directModelString.isEmpty() && m_installedModels.containsModelString(directModelString))
|
||||
{
|
||||
aircraftModel = m_installedModels.findFirstByModelString(directModelString);
|
||||
aircraftModel.setModelType(CAircraftModel::TypeQueriedFromNetwork);
|
||||
}
|
||||
}
|
||||
|
||||
return aircraftModel;
|
||||
}
|
||||
|
||||
CAircraftModel CAircraftMatcher::matchByMapping(const CSimulatedAircraft &remoteAircraft)
|
||||
{
|
||||
CAircraftModel aircraftModel;
|
||||
CAircraftIcaoData icao = remoteAircraft.getIcaoInfo();
|
||||
BlackMisc::Network::CAircraftMappingList mappingList = m_modelMappings.findByIcaoAircraftAndAirlineDesignator(icao, true);
|
||||
if (!mappingList.isEmpty())
|
||||
{
|
||||
CAircraftModel modelFromMappings = mappingList.front().getModel();
|
||||
// now turn the model from the mapping rules into a model from the simulator which has more metadata
|
||||
aircraftModel = m_installedModels.findFirstByModelString(modelFromMappings.getModelString());
|
||||
Q_ASSERT(aircraftModel.getModelString() == modelFromMappings.getModelString());
|
||||
aircraftModel.updateMissingParts(modelFromMappings); // update ICAO
|
||||
aircraftModel.setModelType(CAircraftModel::TypeModelMatching);
|
||||
}
|
||||
|
||||
return aircraftModel;
|
||||
}
|
||||
|
||||
CAircraftModel CAircraftMatcher::matchByAlgorithm(const CSimulatedAircraft & /** remoteAircraft **/)
|
||||
{
|
||||
// Use an algorithm to find the best match
|
||||
return CAircraftModel();
|
||||
}
|
||||
|
||||
int CAircraftMatcher::synchronizeWithExistingModels(const QStringList &modelNames, Qt::CaseSensitivity cs)
|
||||
{
|
||||
if (modelNames.isEmpty() || m_modelMappings.isEmpty()) { return 0; }
|
||||
CAircraftMappingList newList;
|
||||
for (const CAircraftMapping &mapping : m_modelMappings)
|
||||
{
|
||||
if (this->m_initState != InitInProgress) { return 0; } // canceled
|
||||
QString modelString = mapping.getModel().getModelString();
|
||||
if (modelString.isEmpty()) { continue; }
|
||||
if (modelNames.contains(modelString, cs))
|
||||
{
|
||||
newList.push_back(mapping);
|
||||
}
|
||||
}
|
||||
this->m_modelMappings = newList;
|
||||
return this->m_modelMappings.size();
|
||||
}
|
||||
|
||||
void CAircraftMatcher::reverseLookupIcaoData(CAircraftModel &model)
|
||||
{
|
||||
if (isInitialized())
|
||||
{
|
||||
// reverse lookup of ICAO
|
||||
CAircraftIcaoData icao = getIcaoForModelString(model.getModelString());
|
||||
icao.updateMissingParts(icao);
|
||||
model.setIcao(icao);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace
|
||||
148
src/blackmisc/simulation/aircraftmatcher.h
Normal file
148
src/blackmisc/simulation/aircraftmatcher.h
Normal file
@@ -0,0 +1,148 @@
|
||||
/* Copyright (C) 2015
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef BLACKMISC_SIMULATION_AIRCRAFTMATCHER_H
|
||||
#define BLACKMISC_SIMULATION_AIRCRAFTMATCHER_H
|
||||
|
||||
#include "blackmisc/blackmiscexport.h"
|
||||
#include "blackmisc/simulation/modelmappingsprovider.h"
|
||||
#include "blackmisc/simulation/simulatedaircraft.h"
|
||||
#include "blackmisc/simulation/aircraftmodellist.h"
|
||||
#include "blackmisc/worker.h"
|
||||
#include <QObject>
|
||||
#include <QScopedPointer>
|
||||
#include <memory>
|
||||
#include <atomic>
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
namespace Simulation
|
||||
{
|
||||
|
||||
/*! Matcher for all models
|
||||
* \details Reads all the mapping rules and all the available flight simulator models.
|
||||
* Then all rules for models not existing are eliminated ( \sa synchronize ).
|
||||
* Thereafter all existing models and mappings can be obtained from here.
|
||||
*/
|
||||
class BLACKMISC_EXPORT CAircraftMatcher : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
signals:
|
||||
//! Full init completed
|
||||
void initializationFinished();
|
||||
|
||||
public:
|
||||
//! Enabled matching mode flags
|
||||
enum MatchingModeFlag
|
||||
{
|
||||
ExactMatch = 1 << 0,
|
||||
ModelMapping = 1 << 1,
|
||||
ModelMatching = 1 << 2,
|
||||
AllModes = ExactMatch | ModelMapping | ModelMatching
|
||||
};
|
||||
Q_DECLARE_FLAGS(MatchingMode, MatchingModeFlag)
|
||||
|
||||
//! 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<IModelMappingsProvider> mappings);
|
||||
|
||||
//! Set the enabled matching modes
|
||||
void setMatchingModes(MatchingMode matchingModes);
|
||||
|
||||
//! Get the closest matching aircraft model.
|
||||
//! Result depends on enabled modes.
|
||||
//! \sa MatchingModeFlag
|
||||
CAircraftModel getClosestMatch(const CSimulatedAircraft &remoteAircraft);
|
||||
|
||||
//! Get all mappings
|
||||
const BlackMisc::Network::CAircraftMappingList &getAircraftMappingList() const { return m_mappingsProvider->getMappingList(); }
|
||||
|
||||
//! Inverse lookup
|
||||
BlackMisc::Aviation::CAircraftIcaoData getIcaoForModelString(const QString &modelString) const;
|
||||
|
||||
//! Number of mapping definitions
|
||||
int countMappingRules() const { return m_modelMappings.size(); }
|
||||
|
||||
//! Synchronize models and mappings
|
||||
//! \remarks after this step, we only have mappings for which we have models
|
||||
int synchronize();
|
||||
|
||||
//! Shutdown
|
||||
void cancelInit();
|
||||
|
||||
//! default model
|
||||
const BlackMisc::Simulation::CAircraftModel &getDefaultModel();
|
||||
|
||||
//! Set default model
|
||||
void setDefaultModel(const BlackMisc::Simulation::CAircraftModel &defaultModel);
|
||||
|
||||
private slots:
|
||||
//! Set the mapping rules
|
||||
void ps_setModelMappingRules(const BlackMisc::Network::CAircraftMappingList &mappings);
|
||||
|
||||
private:
|
||||
//! Init state
|
||||
enum InitState
|
||||
{
|
||||
NotInitialized,
|
||||
InitInProgress,
|
||||
InitFinished
|
||||
};
|
||||
|
||||
void initImpl();
|
||||
void initMappings();
|
||||
|
||||
CAircraftModel matchByExactModelName(const CSimulatedAircraft &remoteAircraft);
|
||||
CAircraftModel matchByMapping(const CSimulatedAircraft &remoteAircraft);
|
||||
CAircraftModel matchByAlgorithm(const CSimulatedAircraft &remoteAircraft);
|
||||
|
||||
//! Synchronize with existing model names, remove unneeded models
|
||||
int synchronizeWithExistingModels(const QStringList &modelNames, Qt::CaseSensitivity cs = Qt::CaseInsensitive);
|
||||
|
||||
//! Reverse lookup
|
||||
void reverseLookupIcaoData(BlackMisc::Simulation::CAircraftModel &model);
|
||||
|
||||
std::unique_ptr<BlackMisc::Simulation::IModelMappingsProvider> m_mappingsProvider; //!< Provides all mapping definitions
|
||||
std::atomic<InitState> m_initState { NotInitialized };
|
||||
QPointer<BlackMisc::CWorker> m_initWorker;
|
||||
MatchingMode m_matchingMode = ModelMatching;
|
||||
CAircraftModelList m_installedModels;
|
||||
BlackMisc::Network::CAircraftMappingList m_modelMappings;
|
||||
BlackMisc::Simulation::CAircraftModel m_defaultModel;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(BlackMisc::Simulation::CAircraftMatcher::MatchingMode)
|
||||
|
||||
#endif // guard
|
||||
@@ -1,259 +0,0 @@
|
||||
/* Copyright (C) 2013
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "aircraftmatcher.h"
|
||||
#include "blackmisc/logmessage.h"
|
||||
#include "blackmisc/worker.h"
|
||||
#include <utility>
|
||||
#include <atomic>
|
||||
|
||||
using namespace BlackMisc;
|
||||
using namespace BlackMisc::Simulation;
|
||||
using namespace BlackMisc::Network;
|
||||
using namespace BlackMisc::Aviation;
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
namespace Simulation
|
||||
{
|
||||
namespace FsCommon
|
||||
{
|
||||
|
||||
CAircraftMatcher::CAircraftMatcher(MatchingMode matchingMode, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_matchingMode(matchingMode)
|
||||
{ }
|
||||
|
||||
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]()
|
||||
{
|
||||
initImpl();
|
||||
});
|
||||
}
|
||||
|
||||
bool CAircraftMatcher::isInitialized() const
|
||||
{
|
||||
return m_initState == InitFinished;
|
||||
}
|
||||
|
||||
void CAircraftMatcher::setModelMappingProvider(std::unique_ptr<IModelMappingsProvider> mappings)
|
||||
{
|
||||
m_mappingsProvider = std::move(mappings);
|
||||
if (m_matchingMode.testFlag(ModelMapping)) { initMappings(); }
|
||||
}
|
||||
|
||||
void CAircraftMatcher::setMatchingModes(MatchingMode matchingModes)
|
||||
{
|
||||
m_matchingMode = matchingModes;
|
||||
if (m_matchingMode.testFlag(ModelMapping) && m_modelMappings.isEmpty()) initMappings();
|
||||
}
|
||||
|
||||
CAircraftModel CAircraftMatcher::getClosestMatch(const CSimulatedAircraft &remoteAircraft)
|
||||
{
|
||||
CAircraftModel aircraftModel(remoteAircraft); // set defaults
|
||||
|
||||
// Manually set string?
|
||||
if (remoteAircraft.getModel().hasManuallySetString())
|
||||
{
|
||||
// manual set model, maybe update missing parts
|
||||
aircraftModel.updateMissingParts(remoteAircraft.getModel());
|
||||
aircraftModel.setCallsign(remoteAircraft.getCallsign());
|
||||
reverseLookupIcaoData(aircraftModel);
|
||||
return aircraftModel;
|
||||
}
|
||||
|
||||
// mapper ready?
|
||||
if (!isInitialized())
|
||||
{
|
||||
// will be removed later, just for experimental version
|
||||
aircraftModel = getDefaultModel();
|
||||
aircraftModel.setCallsign(remoteAircraft.getCallsign());
|
||||
CLogMessage(static_cast<CAircraftMatcher *>(nullptr)).warning("Matcher not initialized, set to default model");
|
||||
return aircraftModel;
|
||||
}
|
||||
|
||||
aircraftModel = matchByExactModelName(remoteAircraft);
|
||||
|
||||
if (!aircraftModel.hasModelString())
|
||||
{
|
||||
aircraftModel = matchByMapping(remoteAircraft);
|
||||
}
|
||||
|
||||
if (!aircraftModel.hasModelString())
|
||||
{
|
||||
aircraftModel = matchByAlgorithm(remoteAircraft);
|
||||
}
|
||||
|
||||
if (!aircraftModel.hasModelString())
|
||||
{
|
||||
aircraftModel = getDefaultModel();
|
||||
}
|
||||
aircraftModel.setCallsign(remoteAircraft.getCallsign());
|
||||
|
||||
Q_ASSERT(!aircraftModel.getCallsign().isEmpty());
|
||||
Q_ASSERT(aircraftModel.hasModelString());
|
||||
Q_ASSERT(aircraftModel.getModelType() != CAircraftModel::TypeUnknown);
|
||||
|
||||
return aircraftModel;
|
||||
}
|
||||
|
||||
CAircraftIcaoData CAircraftMatcher::getIcaoForModelString(const QString &modelString) const
|
||||
{
|
||||
if (modelString.isEmpty() || !isInitialized()) { return CAircraftIcaoData(); }
|
||||
CAircraftMappingList mappings = m_mappingsProvider->getMappingList().findByModelString(modelString);
|
||||
if (mappings.isEmpty()) { return CAircraftIcaoData(); }
|
||||
return mappings.front().getIcao();
|
||||
}
|
||||
|
||||
int CAircraftMatcher::synchronize()
|
||||
{
|
||||
return synchronizeWithExistingModels(m_installedModels.getSortedModelStrings());
|
||||
}
|
||||
|
||||
void CAircraftMatcher::cancelInit()
|
||||
{
|
||||
// when running, force re-init
|
||||
this->m_initState = NotInitialized;
|
||||
}
|
||||
|
||||
const CAircraftModel &CAircraftMatcher::getDefaultModel()
|
||||
{
|
||||
return m_defaultModel;
|
||||
}
|
||||
|
||||
void CAircraftMatcher::setDefaultModel(const BlackMisc::Simulation::CAircraftModel &defaultModel)
|
||||
{
|
||||
m_defaultModel = defaultModel;
|
||||
}
|
||||
|
||||
void CAircraftMatcher::ps_setModelMappingRules(const CAircraftMappingList &mappings)
|
||||
{
|
||||
m_modelMappings = mappings;
|
||||
}
|
||||
|
||||
void CAircraftMatcher::initImpl()
|
||||
{
|
||||
InitState e = NotInitialized;
|
||||
InitState d = InitInProgress;
|
||||
if (!m_initState.compare_exchange_strong(e, d)) { return; }
|
||||
|
||||
// sync
|
||||
this->synchronize();
|
||||
CLogMessage(this).debug() << "Mapping definitions after sync" << m_modelMappings.size();
|
||||
|
||||
// finish
|
||||
CLogMessage(this).info("Mapping system: %1 definitions for %2 installed models") << m_modelMappings.size()
|
||||
<< m_installedModels.size();
|
||||
m_initState = InitFinished;
|
||||
emit initializationFinished();
|
||||
}
|
||||
|
||||
void CAircraftMatcher::initMappings()
|
||||
{
|
||||
Q_ASSERT(m_mappingsProvider);
|
||||
int mappingsSize = m_mappingsProvider->getMappingList().size();
|
||||
if (mappingsSize < 1)
|
||||
{
|
||||
m_mappingsProvider->read();
|
||||
m_modelMappings = m_mappingsProvider->getMappingList();
|
||||
mappingsSize = m_modelMappings.size();
|
||||
if (mappingsSize < 1)
|
||||
{
|
||||
CLogMessage(this).error("Reading mapping rules failed or empty!");
|
||||
// Turn off the model mapping mode
|
||||
m_matchingMode &= ~ModelMapping;
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_modelMappings = m_mappingsProvider->getMappingList();
|
||||
CLogMessage(this).debug() << "Mapping definitions" << mappingsSize;
|
||||
}
|
||||
|
||||
CAircraftModel CAircraftMatcher::matchByExactModelName(const CSimulatedAircraft &remoteAircraft)
|
||||
{
|
||||
CAircraftModel aircraftModel(remoteAircraft);
|
||||
// Model by queried string
|
||||
const CClient remoteClient = remoteAircraft.getClient();
|
||||
if (remoteClient.getAircraftModel().hasQueriedModelString())
|
||||
{
|
||||
QString directModelString = remoteClient.getAircraftModel().getModelString();
|
||||
if (!directModelString.isEmpty() && m_installedModels.containsModelString(directModelString))
|
||||
{
|
||||
aircraftModel = m_installedModels.findFirstByModelString(directModelString);
|
||||
aircraftModel.setModelType(CAircraftModel::TypeQueriedFromNetwork);
|
||||
}
|
||||
}
|
||||
|
||||
return aircraftModel;
|
||||
}
|
||||
|
||||
CAircraftModel CAircraftMatcher::matchByMapping(const CSimulatedAircraft &remoteAircraft)
|
||||
{
|
||||
CAircraftModel aircraftModel;
|
||||
CAircraftIcaoData icao = remoteAircraft.getIcaoInfo();
|
||||
BlackMisc::Network::CAircraftMappingList mappingList = m_modelMappings.findByIcaoAircraftAndAirlineDesignator(icao, true);
|
||||
if (!mappingList.isEmpty())
|
||||
{
|
||||
CAircraftModel modelFromMappings = mappingList.front().getModel();
|
||||
// now turn the model from the mapping rules into a model from the simulator which has more metadata
|
||||
aircraftModel = m_installedModels.findFirstByModelString(modelFromMappings.getModelString());
|
||||
Q_ASSERT(aircraftModel.getModelString() == modelFromMappings.getModelString());
|
||||
aircraftModel.updateMissingParts(modelFromMappings); // update ICAO
|
||||
aircraftModel.setModelType(CAircraftModel::TypeModelMatching);
|
||||
}
|
||||
|
||||
return aircraftModel;
|
||||
}
|
||||
|
||||
CAircraftModel CAircraftMatcher::matchByAlgorithm(const CSimulatedAircraft & /** remoteAircraft **/)
|
||||
{
|
||||
// Use an algorithm to find the best match
|
||||
return CAircraftModel();
|
||||
}
|
||||
|
||||
int CAircraftMatcher::synchronizeWithExistingModels(const QStringList &modelNames, Qt::CaseSensitivity cs)
|
||||
{
|
||||
if (modelNames.isEmpty() || m_modelMappings.isEmpty()) { return 0; }
|
||||
CAircraftMappingList newList;
|
||||
for (const CAircraftMapping &mapping : m_modelMappings)
|
||||
{
|
||||
if (this->m_initState != InitInProgress) { return 0; } // canceled
|
||||
QString modelString = mapping.getModel().getModelString();
|
||||
if (modelString.isEmpty()) { continue; }
|
||||
if (modelNames.contains(modelString, cs))
|
||||
{
|
||||
newList.push_back(mapping);
|
||||
}
|
||||
}
|
||||
this->m_modelMappings = newList;
|
||||
return this->m_modelMappings.size();
|
||||
}
|
||||
|
||||
void CAircraftMatcher::reverseLookupIcaoData(CAircraftModel &model)
|
||||
{
|
||||
if (isInitialized())
|
||||
{
|
||||
// reverse lookup of ICAO
|
||||
CAircraftIcaoData icao = getIcaoForModelString(model.getModelString());
|
||||
icao.updateMissingParts(icao);
|
||||
model.setIcao(icao);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
@@ -1,153 +0,0 @@
|
||||
/* Copyright (C) 2015
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef BLACKMISC_SIMULATION_FSCOMMON_AIRCRAFTMATCHER_H
|
||||
#define BLACKMISC_SIMULATION_FSCOMMON_AIRCRAFTMATCHER_H
|
||||
|
||||
#include "aircraftcfgentrieslist.h"
|
||||
#include "blackmisc/blackmiscexport.h"
|
||||
#include "blackmisc/simulation/modelmappingsprovider.h"
|
||||
#include "blackmisc/simulation/simulatedaircraft.h"
|
||||
#include "blackmisc/worker.h"
|
||||
#include <QObject>
|
||||
#include <QScopedPointer>
|
||||
#include <QFuture>
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
#include <QReadWriteLock>
|
||||
#include <memory>
|
||||
#include <atomic>
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
namespace Simulation
|
||||
{
|
||||
namespace FsCommon
|
||||
{
|
||||
//! Mapper for all models (works for FS9/FSX).
|
||||
//! \details Reads all the mapping rules and all the available flight simulator models.
|
||||
//! Then all rules for models not existing are eliminated ( \sa synchronize ).
|
||||
//! Thereafter all existing models and mappings can be obtained from here.
|
||||
//! \sa CAircraftCfgEntries
|
||||
//! \sa CAircraftCfgEntriesList
|
||||
class BLACKMISC_EXPORT CAircraftMatcher : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
signals:
|
||||
//! Full init completed
|
||||
void initializationFinished();
|
||||
|
||||
public:
|
||||
//! Enabled matching mode flags
|
||||
enum MatchingModeFlag
|
||||
{
|
||||
ExactMatch = 1 << 0,
|
||||
ModelMapping = 1 << 1,
|
||||
ModelMatching = 1 << 2,
|
||||
AllModes = ExactMatch | ModelMapping | ModelMatching
|
||||
};
|
||||
Q_DECLARE_FLAGS(MatchingMode, MatchingModeFlag)
|
||||
|
||||
//! 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<IModelMappingsProvider> mappings);
|
||||
|
||||
//! Set the enabled matching modes
|
||||
void setMatchingModes(MatchingMode matchingModes);
|
||||
|
||||
//! Get the closest matching aircraft model.
|
||||
//! Result depends on enabled modes.
|
||||
//! \sa MatchingModeFlag
|
||||
CAircraftModel getClosestMatch(const CSimulatedAircraft &remoteAircraft);
|
||||
|
||||
//! Get all mappings
|
||||
const BlackMisc::Network::CAircraftMappingList &getAircraftMappingList() const { return m_mappingsProvider->getMappingList(); }
|
||||
|
||||
//! Inverse lookup
|
||||
BlackMisc::Aviation::CAircraftIcaoData getIcaoForModelString(const QString &modelString) const;
|
||||
|
||||
//! Number of mapping definitions
|
||||
int countMappingRules() const { return m_modelMappings.size(); }
|
||||
|
||||
//! Synchronize models and mappings
|
||||
//! \remarks after this step, we only have mappings for which we have models
|
||||
int synchronize();
|
||||
|
||||
//! Shutdown
|
||||
void cancelInit();
|
||||
|
||||
//! default model
|
||||
const BlackMisc::Simulation::CAircraftModel &getDefaultModel();
|
||||
|
||||
//! Set default model
|
||||
void setDefaultModel(const BlackMisc::Simulation::CAircraftModel &defaultModel);
|
||||
|
||||
private slots:
|
||||
//! Set the mapping rules
|
||||
void ps_setModelMappingRules(const BlackMisc::Network::CAircraftMappingList &mappings);
|
||||
|
||||
private:
|
||||
//! Init state
|
||||
enum InitState
|
||||
{
|
||||
NotInitialized,
|
||||
InitInProgress,
|
||||
InitFinished
|
||||
};
|
||||
|
||||
void initImpl();
|
||||
void initMappings();
|
||||
|
||||
CAircraftModel matchByExactModelName(const CSimulatedAircraft &remoteAircraft);
|
||||
CAircraftModel matchByMapping(const CSimulatedAircraft &remoteAircraft);
|
||||
CAircraftModel matchByAlgorithm(const CSimulatedAircraft &remoteAircraft);
|
||||
|
||||
//! Synchronize with existing model names, remove unneeded models
|
||||
int synchronizeWithExistingModels(const QStringList &modelNames, Qt::CaseSensitivity cs = Qt::CaseInsensitive);
|
||||
|
||||
//! Reverse lookup
|
||||
void reverseLookupIcaoData(BlackMisc::Simulation::CAircraftModel &model);
|
||||
|
||||
std::unique_ptr<BlackMisc::Simulation::IModelMappingsProvider> m_mappingsProvider; //!< Provides all mapping definitions
|
||||
std::atomic<InitState> m_initState { NotInitialized };
|
||||
QPointer<BlackMisc::CWorker> m_initWorker;
|
||||
MatchingMode m_matchingMode = ModelMatching;
|
||||
CAircraftModelList m_installedModels;
|
||||
BlackMisc::Network::CAircraftMappingList m_modelMappings;
|
||||
BlackMisc::Simulation::CAircraftModel m_defaultModel;
|
||||
};
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(BlackMisc::Simulation::FsCommon::CAircraftMatcher::MatchingMode)
|
||||
|
||||
#endif // guard
|
||||
Reference in New Issue
Block a user