From 3f5a12de8b9cd2cffc2bc4f84b7fdf84873552f8 Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Wed, 15 Aug 2018 01:12:55 +0200 Subject: [PATCH] Ref T298, matcher improvements * better messages * clear messages when restarted * better usage of setup flags --- src/blackcore/aircraftmatcher.cpp | 136 +++++++++++------- src/blackcore/aircraftmatcher.h | 16 ++- .../simulation/aircraftmodellist.cpp | 22 +-- 3 files changed, 108 insertions(+), 66 deletions(-) diff --git a/src/blackcore/aircraftmatcher.cpp b/src/blackcore/aircraftmatcher.cpp index 4913842c4..6a6ad7324 100644 --- a/src/blackcore/aircraftmatcher.cpp +++ b/src/blackcore/aircraftmatcher.cpp @@ -107,8 +107,14 @@ namespace BlackCore static const QString m2("Input model: '%1' '%2'"); static const QString m3("Matching uses model set of %1 models\n%2"); static const QString m4("Setup %1"); + static const QString summary = QStringLiteral("\n-----------------------------------------\n") % + QStringLiteral("- Combined: %1 -> %2\n") % + QStringLiteral("- Aircraft: %3 -> %4\n") % + QStringLiteral("- Airline: %5 -> %6\n") % + QStringLiteral("-----------------------------------------\n"); const QDateTime startTime = QDateTime::currentDateTimeUtc(); + if (log) { log->clear(); } CMatchingUtils::addLogDetailsToList(log, remoteAircraft, m1.arg(startTime.toString(format))); CMatchingUtils::addLogDetailsToList(log, remoteAircraft, m2.arg(remoteAircraft.getCallsignAsString(), remoteAircraft.getModel().toQString())); CMatchingUtils::addLogDetailsToList(log, remoteAircraft, m3.arg(modelSet.size()).arg(modelSet.extCoverageSummary(remoteAircraft.getModel()))); @@ -168,6 +174,9 @@ namespace BlackCore candidates = CAircraftMatcher::getClosestMatchStepwiseReduceImplementation(modelSet, setup, remoteAircraft, log); break; case CAircraftMatcherSetup::MatchingScoreBased: + candidates = CAircraftMatcher::getClosestMatchScoreImplementation(modelSet, setup, remoteAircraft, maxScore, log); + break; + case CAircraftMatcherSetup::MatchingStepwiseReducePlusScoreBased: default: candidates = CAircraftMatcher::getClosestMatchStepwiseReduceImplementation(modelSet, setup, remoteAircraft, log); candidates = CAircraftMatcher::getClosestMatchScoreImplementation(candidates, setup, remoteAircraft, maxScore, log); @@ -201,6 +210,12 @@ namespace BlackCore break; } CMatchingUtils::addLogDetailsToList(log, remoteAircraft, ps.arg(candidates.size()).arg(CAircraftMatcherSetup::strategyToString(usedStrategy))); + CMatchingUtils::addLogDetailsToList(log, remoteAircraft, + summary.arg( + remoteAircraft.getAircraftIcaoCode().getCombinedType(), matchedModel.getAircraftIcaoCode().getCombinedType(), + remoteAircraft.getAircraftIcaoCode().getDesignatorDbKey(), matchedModel.getAircraftIcaoCode().getDesignatorDbKey(), + remoteAircraft.getAirlineIcaoCode().getVDesignatorDbKey(), matchedModel.getAirlineIcaoCode().getVDesignatorDbKey() + )); } } @@ -635,7 +650,7 @@ namespace BlackCore if (mode.testFlag(CAircraftMatcherSetup::ByLivery)) { matchedModels = ifPossibleReduceByLiveryAndAircraftIcaoCode(remoteAircraft, matchedModels, reduced, log); - if (reduced) { break; } // almost perfect, we stop here + if (reduced) { break; } // almost perfect, we stop here (we have ICAO + livery match) } else if (log) { @@ -649,36 +664,36 @@ namespace BlackCore else if (log) { CMatchingUtils::addLogDetailsToList(log, remoteAircraft, QStringLiteral("Skipping ICAO reduction"), getLogCategories()); + + // family only because aircraft ICAO is not used + if (mode.testFlag(CAircraftMatcherSetup::ByFamily)) + { + matchedModels = ifPossibleReduceByFamily(remoteAircraft, matchedModels, reduced, log); + if (reduced) { break; } + } + else if (log) + { + CMatchingUtils::addLogDetailsToList(log, remoteAircraft, "Skipping family match", getLogCategories()); + } } // if not yet reduced, reduce to VTOL - if (!reduced && remoteAircraft.isVtol() && matchedModels.containsVtol()) + if (!reduced && remoteAircraft.isVtol() && matchedModels.containsVtol() && mode.testFlag(CAircraftMatcherSetup::ByVtol)) { matchedModels = matchedModels.findByVtolFlag(true); CMatchingUtils::addLogDetailsToList(log, remoteAircraft, "Aircraft is VTOL, reduced to VTOL", getLogCategories()); } - // family - if (mode.testFlag(CAircraftMatcherSetup::ByFamily)) + // military / civilian + if (mode.testFlag(CAircraftMatcherSetup::ByMilitary)) { - QString family = remoteAircraft.getAircraftIcaoCode().getFamily(); - matchedModels = ifPossibleReduceByFamily(remoteAircraft, family, matchedModels, "real family", reduced, log); - if (reduced) { break; } - - // scenario: the ICAO actually is the family - family = remoteAircraft.getAircraftIcaoCodeDesignator(); - matchedModels = ifPossibleReduceByFamily(remoteAircraft, family, matchedModels, "ICAO treated as family", reduced, log); - if (reduced) { break; } - } - else if (log) - { - CMatchingUtils::addLogDetailsToList(log, remoteAircraft, "Skipping family match", getLogCategories()); + matchedModels = ifPossibleReduceByMilitaryFlag(remoteAircraft, matchedModels, reduced, log); } // combined code if (mode.testFlag(CAircraftMatcherSetup::ByCombinedType)) { - matchedModels = ifPossibleReduceByCombinedCode(remoteAircraft, matchedModels, reduced, log); + matchedModels = ifPossibleReduceByCombinedType(remoteAircraft, matchedModels, reduced, log); if (reduced) { break; } } else if (log) @@ -689,10 +704,9 @@ namespace BlackCore while (false); // here we have a list of possible models, we reduce/refine further - if (matchedModels.size() > 1) + if (matchedModels.size() > 1 && mode.testFlag(CAircraftMatcherSetup::ByManufacturer)) { - matchedModels = ifPossibleReduceByManufacturer(remoteAircraft, matchedModels, "2nd pass", reduced, log); - matchedModels = ifPossibleReduceByMilitaryFlag(remoteAircraft, matchedModels, reduced, log); + matchedModels = ifPossibleReduceByManufacturer(remoteAircraft, matchedModels, "2nd trial to reduce by manufacturer. ", reduced, log); } return matchedModels; @@ -748,14 +762,6 @@ namespace BlackCore } } - // here we have a list of possible models, we reduce/refine further - if (matchedModels.size() > 1) - { - bool reduced = false; - matchedModels = ifPossibleReduceByManufacturer(remoteAircraft, matchedModels, "combined code reduction", reduced, log); - matchedModels = ifPossibleReduceByMilitaryFlag(remoteAircraft, matchedModels, reduced, log); - } - // return if (matchedModels.isEmpty()) { return defaultModel; } return matchedModels.front(); @@ -812,6 +818,7 @@ namespace BlackCore CAircraftModelList CAircraftMatcher::ifPossibleReduceByIcaoData(const CSimulatedAircraft &remoteAircraft, const CAircraftModelList &inList, const CAircraftMatcherSetup &setup, bool &reduced, CStatusMessageList *log) { + const CAircraftMatcherSetup::MatchingMode mode = setup.getMatchingMode(); if (inList.isEmpty()) { if (log) { CMatchingUtils::addLogDetailsToList(log, remoteAircraft, "Empty list, skipping step", getLogCategories()); } @@ -819,18 +826,18 @@ namespace BlackCore } reduced = false; - if (setup.getMatchingMode().testFlag(CAircraftMatcherSetup::ByIcaoOrderAirlineFirst)) + if (mode.testFlag(CAircraftMatcherSetup::ByIcaoOrderAirlineFirst)) { bool r; CAircraftModelList models = ifPossibleReduceByAirline(remoteAircraft, inList, "Reduce by airline first.", r, log); - models = ifPossibleReduceByAircraft(remoteAircraft, models, "Reduce by aircraft ICAO second.", r, log); + models = ifPossibleReduceByAircraftOrFamily(remoteAircraft, models, setup, "Reduce by aircraft ICAO second.", r, log); reduced = r; if (reduced) { return models; } } - else if (setup.getMatchingMode().testFlag(CAircraftMatcherSetup::ByIcaoData)) + else if (mode.testFlag(CAircraftMatcherSetup::ByIcaoData)) { bool r; - CAircraftModelList models = ifPossibleReduceByAircraft(remoteAircraft, inList, "Reduce by aircraft ICAO first.", r, log); + CAircraftModelList models = ifPossibleReduceByAircraftOrFamily(remoteAircraft, inList, setup, "Reduce by aircraft ICAO first.", r, log); models = ifPossibleReduceByAirline(remoteAircraft, models, "Reduce by airline second.", r, log); reduced = r; if (reduced) { return models; } @@ -843,10 +850,22 @@ namespace BlackCore return inList; } + CAircraftModelList CAircraftMatcher::ifPossibleReduceByFamily(const CSimulatedAircraft &remoteAircraft, const CAircraftModelList &inList, bool &reduced, CStatusMessageList *log) + { + reduced = false; + QString family = remoteAircraft.getAircraftIcaoCode().getFamily(); + CAircraftModelList matchedModels = ifPossibleReduceByFamily(remoteAircraft, family, inList, "real family", reduced, log); + if (reduced) { return matchedModels; } + + // scenario: the ICAO actually is the family + family = remoteAircraft.getAircraftIcaoCodeDesignator(); + return ifPossibleReduceByFamily(remoteAircraft, family, inList, "ICAO treated as family", reduced, log); + } + CAircraftModelList CAircraftMatcher::ifPossibleReduceByFamily(const CSimulatedAircraft &remoteAircraft, const QString &family, const CAircraftModelList &inList, const QString &hint, bool &reduced, CStatusMessageList *log) { // Use an algorithm to find the best match - reduced = true; + reduced = false; if (family.isEmpty()) { if (log) { CMatchingUtils::addLogDetailsToList(log, remoteAircraft, "No family, skipping step (" % hint % ")", getLogCategories()); } @@ -861,12 +880,12 @@ namespace BlackCore CAircraftModelList found(inList.findByFamily(family)); if (found.isEmpty()) { - if (log) { CMatchingUtils::addLogDetailsToList(log, remoteAircraft, "Not found by family " % family % " (" % hint % ")"); } + if (log) { CMatchingUtils::addLogDetailsToList(log, remoteAircraft, "Not found by family '" % family % "' (" % hint % ")"); } return inList; } reduced = true; - CMatchingUtils::addLogDetailsToList(log, remoteAircraft, "Found by family " % family % " (" % hint % ") size " % QString::number(found.size()), getLogCategories()); + CMatchingUtils::addLogDetailsToList(log, remoteAircraft, "Found by family '" % family % "' (" % hint % ") size " % QString::number(found.size()), getLogCategories()); return found; } @@ -889,11 +908,11 @@ namespace BlackCore const CAircraftModelList outList(inList.findByManufacturer(m)); if (outList.isEmpty()) { - if (log) { CMatchingUtils::addLogDetailsToList(log, remoteAircraft, info % " Not found " % m % ", cannot reduce", getLogCategories()); } + if (log) { CMatchingUtils::addLogDetailsToList(log, remoteAircraft, info % " Not found '" % m % "', cannot reduce", getLogCategories()); } return inList; } - if (log) { CMatchingUtils::addLogDetailsToList(log, remoteAircraft, info % " Reduced by " % m % " results: " % QString::number(outList.size()), getLogCategories()); } + if (log) { CMatchingUtils::addLogDetailsToList(log, remoteAircraft, info % " Reduced by '" % m % "' results: " % QString::number(outList.size()), getLogCategories()); } reduced = true; return outList; } @@ -948,11 +967,19 @@ namespace BlackCore return inList; } - if (log) { CMatchingUtils::addLogDetailsToList(log, remoteAircraft, info % " Reduced reduce by '" % remoteAircraft.getAircraftIcaoCodeDesignator() % "' to " % QString::number(outList.size()), getLogCategories()); } + if (log) { CMatchingUtils::addLogDetailsToList(log, remoteAircraft, info % " Reduced by '" % remoteAircraft.getAircraftIcaoCodeDesignator() % "' to " % QString::number(outList.size()), getLogCategories()); } reduced = true; return outList; } + CAircraftModelList CAircraftMatcher::ifPossibleReduceByAircraftOrFamily(const CSimulatedAircraft &remoteAircraft, const CAircraftModelList &inList, const CAircraftMatcherSetup &setup, const QString &info, bool &reduced, CStatusMessageList *log) + { + reduced = false; + const CAircraftModelList outList = ifPossibleReduceByAircraft(remoteAircraft, inList, info, reduced, log); + if (reduced || !setup.getMatchingMode().testFlag(CAircraftMatcherSetup::ByFamily)) { return outList; } + return ifPossibleReduceByFamily(remoteAircraft, inList, reduced, log); + } + CAircraftModelList CAircraftMatcher::ifPossibleReduceByAirline(const CSimulatedAircraft &remoteAircraft, const CAircraftModelList &inList, const QString &info, bool &reduced, CStatusMessageList *log) { reduced = false; @@ -975,12 +1002,12 @@ namespace BlackCore return inList; } - if (log) { CMatchingUtils::addLogDetailsToList(log, remoteAircraft, info % " Reduced reduce by '" % remoteAircraft.getAirlineIcaoCodeDesignator() % "' to " % QString::number(outList.size()), getLogCategories()); } + if (log) { CMatchingUtils::addLogDetailsToList(log, remoteAircraft, info % " Reduced by '" % remoteAircraft.getAirlineIcaoCodeDesignator() % "' to " % QString::number(outList.size()), getLogCategories()); } reduced = true; return outList; } - CAircraftModelList CAircraftMatcher::ifPossibleReduceByCombinedCode(const CSimulatedAircraft &remoteAircraft, const CAircraftModelList &inList, bool &reduced, CStatusMessageList *log) + CAircraftModelList CAircraftMatcher::ifPossibleReduceByCombinedType(const CSimulatedAircraft &remoteAircraft, const CAircraftModelList &inList, bool &reduced, CStatusMessageList *log) { reduced = false; if (!remoteAircraft.getAircraftIcaoCode().hasValidCombinedType()) @@ -1000,8 +1027,8 @@ namespace BlackCore if (log) { CMatchingUtils::addLogDetailsToList(log, remoteAircraft, "Found by combined code " % cc % ", possible " % QString::number(byCombinedCode.size()), getLogCategories()); } if (byCombinedCode.size() > 1) { - byCombinedCode = ifPossibleReduceByAirline(remoteAircraft, byCombinedCode, "Combined code", reduced, log); - byCombinedCode = ifPossibleReduceByManufacturer(remoteAircraft, byCombinedCode, "Combined code", reduced, log); + byCombinedCode = ifPossibleReduceByAirline(remoteAircraft, byCombinedCode, "Combined code airline reduction. ", reduced, log); + byCombinedCode = ifPossibleReduceByManufacturer(remoteAircraft, byCombinedCode, "Combined code manufacturer reduction. ", reduced, log); reduced = true; } return byCombinedCode; @@ -1019,20 +1046,23 @@ namespace BlackCore return inList; } - if (log) - { - if (inList.size() > byMilitaryFlag.size()) - { - CMatchingUtils::addLogDetailsToList(log, remoteAircraft, "Models reduced to " % mil % " aircraft, size " % QString::number(byMilitaryFlag.size()), getLogCategories()); - } - else - { - CMatchingUtils::addLogDetailsToList(log, remoteAircraft, "Models not reduced by " % mil % ", size " % QString::number(byMilitaryFlag.size()), getLogCategories()); - } - } + if (log) { CMatchingUtils::addLogDetailsToList(log, remoteAircraft, "Models reduced to " % mil % " aircraft, size " % QString::number(byMilitaryFlag.size()), getLogCategories()); } return byMilitaryFlag; } + CAircraftModelList CAircraftMatcher::ifPossibleReduceByVTOLFlag(const CSimulatedAircraft &remoteAircraft, const CAircraftModelList &inList, bool &reduced, CStatusMessageList *log) + { + reduced = false; + if (!inList.containsVtol()) + { + CMatchingUtils::addLogDetailsToList(log, remoteAircraft, "Cannot reduce to VTOL aircraft", getLogCategories()); + return inList; + } + CAircraftModelList vtolModels = inList.findByVtolFlag(true); + if (log) { CMatchingUtils::addLogDetailsToList(log, remoteAircraft, "Models reduced to " % QString::number(vtolModels.size()) % " VTOL aircraft", getLogCategories()); } + return vtolModels; + } + QString CAircraftMatcher::scoresToString(const ScoredModels &scores, int lastElements) { if (scores.isEmpty()) { return ""; } diff --git a/src/blackcore/aircraftmatcher.h b/src/blackcore/aircraftmatcher.h index dc30bcdce..ca6f18ae8 100644 --- a/src/blackcore/aircraftmatcher.h +++ b/src/blackcore/aircraftmatcher.h @@ -201,7 +201,11 @@ namespace BlackCore //! Find model by aircraft family //! \threadsafe - static BlackMisc::Simulation::CAircraftModelList ifPossibleReduceByFamily(const BlackMisc::Simulation::CSimulatedAircraft &remoteAircraft, const QString &family, const BlackMisc::Simulation::CAircraftModelList &inList, const QString &modelSource, bool &reduced, BlackMisc::CStatusMessageList *log); + static BlackMisc::Simulation::CAircraftModelList ifPossibleReduceByFamily(const BlackMisc::Simulation::CSimulatedAircraft &remoteAircraft, const BlackMisc::Simulation::CAircraftModelList &inList, bool &reduced, BlackMisc::CStatusMessageList *log); + + //! Find model by aircraft family + //! \threadsafe + static BlackMisc::Simulation::CAircraftModelList ifPossibleReduceByFamily(const BlackMisc::Simulation::CSimulatedAircraft &remoteAircraft, const QString &family, const BlackMisc::Simulation::CAircraftModelList &inList, const QString &hint, bool &reduced, BlackMisc::CStatusMessageList *log); //! Search for exact livery and aircraft ICAO code //! \threadsafe @@ -219,18 +223,26 @@ namespace BlackCore //! \threadsafe static BlackMisc::Simulation::CAircraftModelList ifPossibleReduceByAircraft(const BlackMisc::Simulation::CSimulatedAircraft &remoteAircraft, const BlackMisc::Simulation::CAircraftModelList &inList, const QString &info, bool &reduced, BlackMisc::CStatusMessageList *log); + //! Reduce by aircraft ICAO or family + //! \threadsafe + static BlackMisc::Simulation::CAircraftModelList ifPossibleReduceByAircraftOrFamily(const BlackMisc::Simulation::CSimulatedAircraft &remoteAircraft, const BlackMisc::Simulation::CAircraftModelList &inList, const BlackMisc::Simulation::CAircraftMatcherSetup &setup, const QString &info, bool &reduced, BlackMisc::CStatusMessageList *log); + //! Reduce by airline ICAO //! \threadsafe static BlackMisc::Simulation::CAircraftModelList ifPossibleReduceByAirline(const BlackMisc::Simulation::CSimulatedAircraft &remoteAircraft, const BlackMisc::Simulation::CAircraftModelList &inList, const QString &info, bool &reduced, BlackMisc::CStatusMessageList *log); //! Installed models by combined code (ie L2J, L1P, ...) //! \threadsafe - static BlackMisc::Simulation::CAircraftModelList ifPossibleReduceByCombinedCode(const BlackMisc::Simulation::CSimulatedAircraft &remoteAircraft, const BlackMisc::Simulation::CAircraftModelList &inList, bool &reduced, BlackMisc::CStatusMessageList *log); + static BlackMisc::Simulation::CAircraftModelList ifPossibleReduceByCombinedType(const BlackMisc::Simulation::CSimulatedAircraft &remoteAircraft, const BlackMisc::Simulation::CAircraftModelList &inList, bool &reduced, BlackMisc::CStatusMessageList *log); //! By military flag //! \threadsafe static BlackMisc::Simulation::CAircraftModelList ifPossibleReduceByMilitaryFlag(const BlackMisc::Simulation::CSimulatedAircraft &remoteAircraft, const BlackMisc::Simulation::CAircraftModelList &inList, bool &reduced, BlackMisc::CStatusMessageList *log); + //! By VTOL flag + //! \threadsafe + static BlackMisc::Simulation::CAircraftModelList ifPossibleReduceByVTOLFlag(const BlackMisc::Simulation::CSimulatedAircraft &remoteAircraft, const BlackMisc::Simulation::CAircraftModelList &inList, bool &reduced, BlackMisc::CStatusMessageList *log); + //! Scores to string for debugging //! \threadsafe static QString scoresToString(const BlackMisc::Simulation::ScoredModels &scores, int lastElements = 5); diff --git a/src/blackmisc/simulation/aircraftmodellist.cpp b/src/blackmisc/simulation/aircraftmodellist.cpp index a29244942..8068c5c77 100644 --- a/src/blackmisc/simulation/aircraftmodellist.cpp +++ b/src/blackmisc/simulation/aircraftmodellist.cpp @@ -1070,26 +1070,26 @@ namespace BlackMisc { return QStringLiteral("Entries: ") % QString::number(this->size()) % - QStringLiteral(" valid DB keys: ") % QString::number(this->countWithValidDbKey()) % separator % + QStringLiteral(" | valid DB keys: ") % QString::number(this->countWithValidDbKey()) % separator % QStringLiteral("color liveries: ") % QString::number(this->countModelsWithColorLivery()) % - QStringLiteral(" airline liveries: ") % QString::number(this->countModelsWithAirlineLivery()) % separator % - QStringLiteral("VTOL: ") % QString::number(this->countVtolAircraft()) % separator % - QStringLiteral("Simulators: ") % this->countPerSimulator().toQString() % separator % - QStringLiteral("Military: ") % QString::number(this->countMilitaryAircraft()) % - QStringLiteral(" civilian: ") % QString::number(this->countCivilianAircraft()) % separator % + QStringLiteral(" | airline liveries: ") % QString::number(this->countModelsWithAirlineLivery()) % separator % + QStringLiteral("VTOL: ") % QString::number(this->countVtolAircraft()) % + QStringLiteral(" | military: ") % QString::number(this->countMilitaryAircraft()) % + QStringLiteral(" | civilian: ") % QString::number(this->countCivilianAircraft()) % separator % QStringLiteral("Different airlines: ") % QString::number(this->countDifferentAirlines()) % separator % - QStringLiteral("Combined types: ") % this->getCombinedTypesAsString(); + QStringLiteral("Combined types: '") % this->getCombinedTypesAsString() % QStringLiteral("'") % separator % + QStringLiteral("Simulators: ") % this->countPerSimulator().toQString(); } QString CAircraftModelList::extCoverageSummary(const CAircraftModel &checkModel, const QString &separator) const { - const bool combined = this->containsCombinedType(checkModel.getAircraftIcaoCode().getCombinedType()); - const bool airline = checkModel.hasAirlineDesignator() && this->containsAirlineLivery(checkModel.getAirlineIcaoCode()); + const bool combinedCodeForModel = this->containsCombinedType(checkModel.getAircraftIcaoCode().getCombinedType()); + const bool airlineForModel = checkModel.hasAirlineDesignator() && this->containsAirlineLivery(checkModel.getAirlineIcaoCode()); return coverageSummary(separator) % separator % - QStringLiteral("Has combined: ") % boolToYesNo(combined) % + QStringLiteral("Data for input model, has combined: ") % boolToYesNo(combinedCodeForModel) % ( checkModel.hasAirlineDesignator() ? - QStringLiteral(" airline '") % checkModel.getAirlineIcaoCodeDesignator() % QStringLiteral("': ") % boolToYesNo(airline) : + QStringLiteral(" airline '") % checkModel.getAirlineIcaoCodeDesignator() % QStringLiteral("': ") % boolToYesNo(airlineForModel) : QStringLiteral("") ); }