diff --git a/src/blackcore/aircraftmatcher.cpp b/src/blackcore/aircraftmatcher.cpp index bff19852d..389b3a822 100644 --- a/src/blackcore/aircraftmatcher.cpp +++ b/src/blackcore/aircraftmatcher.cpp @@ -872,6 +872,8 @@ namespace BlackCore if (setup.getMatchingMode().testFlag(CAircraftMatcherSetup::ByIcaoData)) { + // by airline/aircraft or by aircraft/airline depending on setup + // family is also considered matchedModels = ifPossibleReduceByIcaoData(remoteAircraft, matchedModels, setup, reduced, log); } else if (log) @@ -891,6 +893,16 @@ namespace BlackCore } } + if (setup.useCategoryMatching()) + { + matchedModels = categoryMatcher.reduceByCategories(modelSet, setup, remoteAircraft, reduced, shortLog, log); + // ?? break here ?? + } + else if (log) + { + CMatchingUtils::addLogDetailsToList(log, remoteAircraft, QStringLiteral("category matchig disabled"), getLogCategories()); + } + // if not yet reduced, reduce to VTOL if (!reduced && remoteAircraft.isVtol() && matchedModels.containsVtol() && mode.testFlag(CAircraftMatcherSetup::ByVtol)) { diff --git a/src/blackmisc/simulation/categorymatcher.cpp b/src/blackmisc/simulation/categorymatcher.cpp index 7b3036dab..52a0f146d 100644 --- a/src/blackmisc/simulation/categorymatcher.cpp +++ b/src/blackmisc/simulation/categorymatcher.cpp @@ -7,6 +7,11 @@ */ #include "categorymatcher.h" +#include "simulatedaircraft.h" +#include "aircraftmatchersetup.h" +#include "matchingutils.h" +#include "blackmisc/statusmessagelist.h" + #include using namespace BlackMisc::Aviation; @@ -15,6 +20,12 @@ namespace BlackMisc { namespace Simulation { + const CLogCategoryList &CCategoryMatcher::getLogCategories() + { + static const CLogCategoryList cats { CLogCategory::matching() }; + return cats; + } + void CCategoryMatcher::setCategories(const CAircraftCategoryList &categories) { m_all = categories; @@ -46,5 +57,95 @@ namespace BlackMisc m_militaryRotorAircraft = militaryRotor; } } + + CAircraftModelList CCategoryMatcher::reduceByCategories(const CAircraftModelList &modelSet, const CAircraftMatcherSetup &setup, const CSimulatedAircraft &remoteAircraft, bool &reduced, bool shortLog, CStatusMessageList *log) const + { + Q_UNUSED(shortLog); + + reduced = false; + if (!setup.useCategoryMatching()) + { + if (log) { CMatchingUtils::addLogDetailsToList(log, remoteAircraft, QStringLiteral("Disabled category matching"), getLogCategories()); } + return modelSet; + } + if (m_all.isEmpty()) + { + CMatchingUtils::addLogDetailsToList(log, remoteAircraft, QStringLiteral("Disabled category matching"), getLogCategories()); + return modelSet; + } + + if (!m_gliders.isEmpty() && setup.getMatchingMode().testFlag(CAircraftMatcherSetup::ByCategoryGlider) && this->isGlider(remoteAircraft.getAircraftIcaoCode())) + { + // we have a glider + const int firstLevel = this->gliderFirstLevel(); + const CAircraftModelList gliders = modelSet.findByCategoryFirstLevel(firstLevel); + if (!gliders.isEmpty()) + { + const CAircraftCategory category = remoteAircraft.getAircraftIcaoCode().getCategory(); + reduced = true; // in any case reduced + + const CAircraftModelList sameGliders = modelSet.findByCategory(category); + if (!sameGliders.isEmpty()) + { + if (log) { CMatchingUtils::addLogDetailsToList(log, remoteAircraft, QStringLiteral("Reduced to %1 models by category : '%2'").arg(sameGliders.size()).arg(category.toQString(true)), getLogCategories()); } + return sameGliders; + } + + const CAircraftCategoryList siblings = m_gliders.findSiblings(category); + const CAircraftModelList siblingGliders = modelSet.findByCategories(siblings); + if (!siblings.isEmpty() && !siblingGliders.isEmpty()) + { + if (log) { CMatchingUtils::addLogDetailsToList(log, remoteAircraft, QStringLiteral("Reduced to %1 sibling models by categories : '%2'").arg(siblingGliders.size()).arg(siblings.getLevelsString()), getLogCategories()); } + return sameGliders; + } + + CMatchingUtils::addLogDetailsToList(log, remoteAircraft, QStringLiteral("Reduced to %1 models by 'GLIDER' category").arg(sameGliders.size()), getLogCategories()); + return gliders; + } + else + { + if (log) { CMatchingUtils::addLogDetailsToList(log, remoteAircraft, QStringLiteral("No glider categories of level %1 in set").arg(firstLevel), getLogCategories()); } + static const QStringList substituteIcaos({ "UHEL", "GLID", "ULAC" }); // maybe also GYRO + static const QString substituteIcaosStr = substituteIcaos.join(", "); + + CAircraftModelList substitutes = modelSet.findByDesignatorsOrFamilyWithColorLivery(substituteIcaos); + if (substitutes.isEmpty()) + { + substitutes = modelSet.findByCombinedType(QStringLiteral("L1P")); + if (!substitutes.isEmpty()) + { + reduced = true; + if (log) { CMatchingUtils::addLogDetailsToList(log, remoteAircraft, QStringLiteral("No gliders, reduced to 'L1P' models: %1' (avoid absurd matchings)").arg(substitutes.size()), getLogCategories()); } + return substitutes; + } + } + else + { + reduced = true; + if (log) { CMatchingUtils::addLogDetailsToList(log, remoteAircraft, QStringLiteral("Reduced to %1 models by '%2'").arg(substitutes.size()).arg(substituteIcaosStr), getLogCategories()); } + return substitutes; + } + } + } + + return modelSet; + } + + bool CCategoryMatcher::isGlider(const CAircraftIcaoCode &icao) const + { + if (icao.getDesignator() == CAircraftIcaoCode::getGliderDesignator()) { return true; } + const int glider1st = this->gliderFirstLevel(); + if (glider1st >= 0 && icao.hasCategory()) + { + return icao.getCategory().getFirstLevel() == glider1st; + } + return false; + } + + int CCategoryMatcher::gliderFirstLevel() const + { + if (m_gliders.isEmpty()) { return -1; } + return m_gliders.front().getFirstLevel(); + } } // namespace } // namespace diff --git a/src/blackmisc/simulation/categorymatcher.h b/src/blackmisc/simulation/categorymatcher.h index a53dcb4a0..ba3ba2b25 100644 --- a/src/blackmisc/simulation/categorymatcher.h +++ b/src/blackmisc/simulation/categorymatcher.h @@ -11,17 +11,26 @@ #ifndef BLACKMISC_SIMULATION_CATEGORYMATCHER_H #define BLACKMISC_SIMULATION_CATEGORYMATCHER_H +#include "aircraftmodellist.h" #include "blackmisc/aviation/aircraftcategorylist.h" #include "blackmisc/blackmiscexport.h" namespace BlackMisc { + class CStatusMessageList; + namespace Simulation { + class CSimulatedAircraft; + class CAircraftMatcherSetup; + //! Category matcher, uses the DB categories class BLACKMISC_EXPORT CCategoryMatcher { public: + //! Log categories + static const BlackMisc::CLogCategoryList &getLogCategories(); + //! Constructor CCategoryMatcher() {} @@ -34,7 +43,16 @@ namespace BlackMisc const Aviation::CAircraftCategoryList &militaryRotorCategories() const { return m_militaryRotorAircraft; } //! @} + //! Reduce by categories + CAircraftModelList reduceByCategories(const CAircraftModelList &modelSet, const CAircraftMatcherSetup &setup, const CSimulatedAircraft &remoteAircraft, bool &reduced, bool shortLog, CStatusMessageList *log = nullptr) const; + private: + //! Glider? + bool isGlider(const Aviation::CAircraftIcaoCode &icao) const; + + //! Get the glider top level + int gliderFirstLevel() const; + Aviation::CAircraftCategoryList m_all; Aviation::CAircraftCategoryList m_gliders; Aviation::CAircraftCategoryList m_militaryWingAircraft;